summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/accel/habanalabs/common/command_buffer.c6
-rw-r--r--drivers/accel/habanalabs/common/command_submission.c61
-rw-r--r--drivers/accel/habanalabs/common/debugfs.c60
-rw-r--r--drivers/accel/habanalabs/common/device.c112
-rw-r--r--drivers/accel/habanalabs/common/firmware_if.c212
-rw-r--r--drivers/accel/habanalabs/common/habanalabs.h77
-rw-r--r--drivers/accel/habanalabs/common/habanalabs_drv.c9
-rw-r--r--drivers/accel/habanalabs/common/habanalabs_ioctl.c35
-rw-r--r--drivers/accel/habanalabs/common/irq.c2
-rw-r--r--drivers/accel/habanalabs/common/memory.c104
-rw-r--r--drivers/accel/habanalabs/common/mmu/mmu.c56
-rw-r--r--drivers/accel/habanalabs/common/security.c57
-rw-r--r--drivers/accel/habanalabs/gaudi/gaudi.c13
-rw-r--r--drivers/accel/habanalabs/gaudi2/gaudi2.c334
-rw-r--r--drivers/accel/habanalabs/gaudi2/gaudi2P.h2
-rw-r--r--drivers/accel/habanalabs/gaudi2/gaudi2_security.c15
-rw-r--r--drivers/accel/habanalabs/goya/goya.c3
-rw-r--r--drivers/accel/habanalabs/goya/goya_coresight.c9
-rw-r--r--drivers/accel/habanalabs/include/common/cpucp_if.h22
-rw-r--r--drivers/accel/habanalabs/include/common/hl_boot_if.h41
-rw-r--r--drivers/accel/habanalabs/include/gaudi2/asic_reg/gaudi2_regs.h11
-rw-r--r--drivers/accel/habanalabs/include/gaudi2/gaudi2_fw_if.h2
-rw-r--r--drivers/accessibility/speakup/Kconfig1
-rw-r--r--drivers/accessibility/speakup/main.c2
-rw-r--r--drivers/acpi/Kconfig2
-rw-r--r--drivers/acpi/Makefile2
-rw-r--r--drivers/acpi/ec.c18
-rw-r--r--drivers/acpi/osl.c2
-rw-r--r--drivers/acpi/processor_core.c29
-rw-r--r--drivers/acpi/riscv/Makefile2
-rw-r--r--drivers/acpi/riscv/rhct.c83
-rw-r--r--drivers/acpi/tables.c10
-rw-r--r--drivers/android/binder.c15
-rw-r--r--drivers/android/binder_internal.h3
-rw-r--r--drivers/ata/ahci_brcm.c6
-rw-r--r--drivers/ata/ahci_ceva.c2
-rw-r--r--drivers/ata/ahci_da850.c2
-rw-r--r--drivers/ata/ahci_dm816.c2
-rw-r--r--drivers/ata/ahci_dwc.c2
-rw-r--r--drivers/ata/ahci_imx.c2
-rw-r--r--drivers/ata/ahci_mtk.c2
-rw-r--r--drivers/ata/ahci_mvebu.c2
-rw-r--r--drivers/ata/ahci_octeon.c1
-rw-r--r--drivers/ata/ahci_platform.c10
-rw-r--r--drivers/ata/ahci_qoriq.c2
-rw-r--r--drivers/ata/ahci_seattle.c2
-rw-r--r--drivers/ata/ahci_st.c2
-rw-r--r--drivers/ata/ahci_sunxi.c2
-rw-r--r--drivers/ata/ahci_tegra.c2
-rw-r--r--drivers/ata/ahci_xgene.c2
-rw-r--r--drivers/ata/libahci.c61
-rw-r--r--drivers/ata/libata-core.c214
-rw-r--r--drivers/ata/libata-eh.c151
-rw-r--r--drivers/ata/libata-sata.c153
-rw-r--r--drivers/ata/libata-scsi.c387
-rw-r--r--drivers/ata/libata.h2
-rw-r--r--drivers/ata/pata_ixp4xx_cf.c2
-rw-r--r--drivers/ata/pata_octeon_cf.c27
-rw-r--r--drivers/ata/pata_of_platform.c2
-rw-r--r--drivers/ata/pata_parport/aten.c103
-rw-r--r--drivers/ata/pata_parport/bpck.c466
-rw-r--r--drivers/ata/pata_parport/bpck6.c67
-rw-r--r--drivers/ata/pata_parport/comm.c238
-rw-r--r--drivers/ata/pata_parport/dstr.c285
-rw-r--r--drivers/ata/pata_parport/epat.c320
-rw-r--r--drivers/ata/pata_parport/epia.c442
-rw-r--r--drivers/ata/pata_parport/fit2.c131
-rw-r--r--drivers/ata/pata_parport/fit3.c206
-rw-r--r--drivers/ata/pata_parport/friq.c292
-rw-r--r--drivers/ata/pata_parport/frpw.c322
-rw-r--r--drivers/ata/pata_parport/kbic.c314
-rw-r--r--drivers/ata/pata_parport/ktti.c85
-rw-r--r--drivers/ata/pata_parport/on20.c149
-rw-r--r--drivers/ata/pata_parport/on26.c414
-rw-r--r--drivers/ata/pata_platform.c2
-rw-r--r--drivers/ata/sata_highbank.c2
-rw-r--r--drivers/ata/sata_svw.c8
-rw-r--r--drivers/auxdisplay/cfag12864bfb.c2
-rw-r--r--drivers/auxdisplay/ht16k33.c2
-rw-r--r--drivers/base/isa.c7
-rw-r--r--drivers/base/node.c8
-rw-r--r--drivers/base/property.c12
-rw-r--r--drivers/bluetooth/virtio_bt.c1
-rw-r--r--drivers/bus/fsl-mc/dprc-driver.c18
-rw-r--r--drivers/bus/fsl-mc/fsl-mc-allocator.c35
-rw-r--r--drivers/bus/fsl-mc/fsl-mc-bus.c7
-rw-r--r--drivers/bus/ti-sysc.c4
-rw-r--r--drivers/cdrom/gdrom.c4
-rw-r--r--drivers/cdx/cdx.c18
-rw-r--r--drivers/cdx/controller/Kconfig10
-rw-r--r--drivers/cdx/controller/mcdi.c86
-rw-r--r--drivers/cdx/controller/mcdi.h6
-rw-r--r--drivers/char/Kconfig3
-rw-r--r--drivers/char/bsr.c21
-rw-r--r--drivers/char/dsp56k.c18
-rw-r--r--drivers/char/hw_random/Kconfig27
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/cn10k-rng.c63
-rw-r--r--drivers/char/hw_random/histb-rng.c (renamed from drivers/crypto/hisilicon/trng/trng-stb.c)83
-rw-r--r--drivers/char/hw_random/imx-rngc.c53
-rw-r--r--drivers/char/hw_random/st-rng.c21
-rw-r--r--drivers/char/hw_random/virtio-rng.c10
-rw-r--r--drivers/char/lp.c18
-rw-r--r--drivers/char/mem.c22
-rw-r--r--drivers/char/misc.c39
-rw-r--r--drivers/char/ppdev.c19
-rw-r--r--drivers/char/virtio_console.c25
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c52
-rw-r--r--drivers/char/xillybus/xillybus_class.c21
-rw-r--r--drivers/clk/Kconfig1
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/actions/owl-composite.c35
-rw-r--r--drivers/clk/at91/at91rm9200.c14
-rw-r--r--drivers/clk/at91/at91sam9260.c14
-rw-r--r--drivers/clk/at91/at91sam9g45.c16
-rw-r--r--drivers/clk/at91/at91sam9n12.c14
-rw-r--r--drivers/clk/at91/at91sam9rl.c14
-rw-r--r--drivers/clk/at91/at91sam9x5.c20
-rw-r--r--drivers/clk/at91/clk-generated.c11
-rw-r--r--drivers/clk/at91/clk-main.c33
-rw-r--r--drivers/clk/at91/clk-master.c28
-rw-r--r--drivers/clk/at91/clk-peripheral.c22
-rw-r--r--drivers/clk/at91/clk-programmable.c11
-rw-r--r--drivers/clk/at91/clk-sam9x60-pll.c17
-rw-r--r--drivers/clk/at91/clk-smd.c29
-rw-r--r--drivers/clk/at91/clk-system.c12
-rw-r--r--drivers/clk/at91/clk-utmi.c24
-rw-r--r--drivers/clk/at91/dt-compat.c23
-rw-r--r--drivers/clk/at91/pmc.h36
-rw-r--r--drivers/clk/at91/sam9x60.c20
-rw-r--r--drivers/clk/at91/sama5d2.c20
-rw-r--r--drivers/clk/at91/sama5d3.c16
-rw-r--r--drivers/clk/at91/sama5d4.c18
-rw-r--r--drivers/clk/at91/sama7g5.c796
-rw-r--r--drivers/clk/at91/sckc.c76
-rw-r--r--drivers/clk/bcm/clk-raspberrypi.c4
-rw-r--r--drivers/clk/berlin/berlin2-div.c1
-rw-r--r--drivers/clk/clk-axi-clkgen.c14
-rw-r--r--drivers/clk/clk-cdce706.c32
-rw-r--r--drivers/clk/clk-cdce925.c14
-rw-r--r--drivers/clk/clk-cs2000-cp.c2
-rw-r--r--drivers/clk/clk-k210.c3
-rw-r--r--drivers/clk/clk-lan966x.c17
-rw-r--r--drivers/clk/clk-lmk04832.c1
-rw-r--r--drivers/clk/clk-lochnagar.c1
-rw-r--r--drivers/clk/clk-max9485.c2
-rw-r--r--drivers/clk/clk-qoriq.c1
-rw-r--r--drivers/clk/clk-renesas-pcie.c6
-rw-r--r--drivers/clk/clk-si514.c2
-rw-r--r--drivers/clk/clk-si521xx.c2
-rw-r--r--drivers/clk/clk-si5341.c59
-rw-r--r--drivers/clk/clk-si5351.c69
-rw-r--r--drivers/clk/clk-si544.c2
-rw-r--r--drivers/clk/clk-si570.c2
-rw-r--r--drivers/clk/clk-stm32f4.c1
-rw-r--r--drivers/clk/clk-versaclock5.c52
-rw-r--r--drivers/clk/clk-versaclock7.c7
-rw-r--r--drivers/clk/clk-wm831x.c1
-rw-r--r--drivers/clk/clk.c111
-rw-r--r--drivers/clk/clk_test.c180
-rw-r--r--drivers/clk/davinci/da8xx-cfgchip.c12
-rw-r--r--drivers/clk/imx/clk-busy.c1
-rw-r--r--drivers/clk/imx/clk-composite-8m.c31
-rw-r--r--drivers/clk/imx/clk-fixup-mux.c1
-rw-r--r--drivers/clk/imx/clk-imx6sx.c8
-rw-r--r--drivers/clk/imx/clk-imx6ul.c2
-rw-r--r--drivers/clk/imx/clk-imx8mn.c8
-rw-r--r--drivers/clk/imx/clk-imx8mp.c24
-rw-r--r--drivers/clk/imx/clk-imx93.c15
-rw-r--r--drivers/clk/imx/clk-imxrt1050.c22
-rw-r--r--drivers/clk/imx/clk-scu.c24
-rw-r--r--drivers/clk/imx/clk.c8
-rw-r--r--drivers/clk/imx/clk.h1
-rw-r--r--drivers/clk/ingenic/cgu.c15
-rw-r--r--drivers/clk/ingenic/tcu.c19
-rw-r--r--drivers/clk/keystone/sci-clk.c2
-rw-r--r--drivers/clk/keystone/syscon-clk.c49
-rw-r--r--drivers/clk/mediatek/Kconfig12
-rw-r--r--drivers/clk/mediatek/clk-cpumux.c1
-rw-r--r--drivers/clk/mediatek/clk-mt2701-aud.c6
-rw-r--r--drivers/clk/mediatek/clk-mt2701-bdp.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2701-eth.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2701-g3d.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2701-hif.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2701-img.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2701-mm.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2701-vdec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2712-apmixedsys.c6
-rw-r--r--drivers/clk/mediatek/clk-mt2712-bdp.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2712-img.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2712-jpgdec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2712-mfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2712-mm.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2712-vdec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2712-venc.c2
-rw-r--r--drivers/clk/mediatek/clk-mt2712.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6765-audio.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6765-cam.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6765-img.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6765-mipi0a.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6765-mm.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6765-vcodec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6765.c20
-rw-r--r--drivers/clk/mediatek/clk-mt6779-aud.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6779-cam.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6779-img.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6779-ipe.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6779-mfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6779-mm.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6779-vdec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6779-venc.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6779.c26
-rw-r--r--drivers/clk/mediatek/clk-mt6795-apmixedsys.c6
-rw-r--r--drivers/clk/mediatek/clk-mt6795-infracfg.c6
-rw-r--r--drivers/clk/mediatek/clk-mt6795-mfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6795-mm.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6795-pericfg.c6
-rw-r--r--drivers/clk/mediatek/clk-mt6795-topckgen.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6795-vdecsys.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6795-vencsys.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6797-img.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6797-mm.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6797-vdec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt6797-venc.c2
-rw-r--r--drivers/clk/mediatek/clk-mt7622-apmixedsys.c6
-rw-r--r--drivers/clk/mediatek/clk-mt7622-aud.c6
-rw-r--r--drivers/clk/mediatek/clk-mt7622-eth.c2
-rw-r--r--drivers/clk/mediatek/clk-mt7622-hif.c2
-rw-r--r--drivers/clk/mediatek/clk-mt7622-infracfg.c6
-rw-r--r--drivers/clk/mediatek/clk-mt7622.c2
-rw-r--r--drivers/clk/mediatek/clk-mt7629-hif.c2
-rw-r--r--drivers/clk/mediatek/clk-mt7981-eth.c2
-rw-r--r--drivers/clk/mediatek/clk-mt7981-infracfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt7981-topckgen.c14
-rw-r--r--drivers/clk/mediatek/clk-mt7986-eth.c2
-rw-r--r--drivers/clk/mediatek/clk-mt7986-infracfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt7986-topckgen.c14
-rw-r--r--drivers/clk/mediatek/clk-mt8135-apmixedsys.c6
-rw-r--r--drivers/clk/mediatek/clk-mt8135.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8167-aud.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8167-img.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8167-mfgcfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8167-mm.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8167-vdec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8167.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8173-apmixedsys.c13
-rw-r--r--drivers/clk/mediatek/clk-mt8173-img.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8173-infracfg.c6
-rw-r--r--drivers/clk/mediatek/clk-mt8173-mm.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8173-pericfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8173-topckgen.c26
-rw-r--r--drivers/clk/mediatek/clk-mt8173-vdecsys.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8173-vencsys.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8183-audio.c6
-rw-r--r--drivers/clk/mediatek/clk-mt8183-cam.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8183-img.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8183-ipu0.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8183-ipu1.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8183-ipu_adl.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8183-ipu_conn.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8183-mfgcfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8183-mm.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8183-vdec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8183-venc.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8183.c24
-rw-r--r--drivers/clk/mediatek/clk-mt8186-apmixedsys.c6
-rw-r--r--drivers/clk/mediatek/clk-mt8186-cam.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8186-img.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8186-infra_ao.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8186-ipe.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8186-mcu.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8186-mdp.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8186-mfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8186-mm.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8186-topckgen.c26
-rw-r--r--drivers/clk/mediatek/clk-mt8186-vdec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8186-venc.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8186-wpe.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-adsp_audio26m.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-apmixedsys.c6
-rw-r--r--drivers/clk/mediatek/clk-mt8188-cam.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-ccu.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-img.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-imp_iic_wrap.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-infra_ao.c26
-rw-r--r--drivers/clk/mediatek/clk-mt8188-ipe.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-mfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-peri_ao.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-topckgen.c46
-rw-r--r--drivers/clk/mediatek/clk-mt8188-vdec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-vdo0.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-vdo1.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-venc.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-vpp0.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-vpp1.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8188-wpe.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192-apmixedsys.c6
-rw-r--r--drivers/clk/mediatek/clk-mt8192-aud.c6
-rw-r--r--drivers/clk/mediatek/clk-mt8192-cam.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192-img.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192-ipe.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192-mdp.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192-mfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192-mm.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192-msdc.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192-scp_adsp.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192-vdec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192-venc.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8192.c25
-rw-r--r--drivers/clk/mediatek/clk-mt8195-apmixedsys.c6
-rw-r--r--drivers/clk/mediatek/clk-mt8195-apusys_pll.c6
-rw-r--r--drivers/clk/mediatek/clk-mt8195-cam.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-ccu.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-img.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-infra_ao.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-ipe.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-mfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-peri_ao.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-scp_adsp.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-topckgen.c52
-rw-r--r--drivers/clk/mediatek/clk-mt8195-vdec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-vdo0.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-vdo1.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-venc.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-vpp0.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-vpp1.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8195-wpe.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8365-apu.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8365-cam.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8365-mfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8365-mm.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8365-vdec.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8365-venc.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8365.c40
-rw-r--r--drivers/clk/mediatek/clk-mt8516-aud.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8516.c2
-rw-r--r--drivers/clk/mediatek/clk-mtk.c25
-rw-r--r--drivers/clk/mediatek/clk-mtk.h4
-rw-r--r--drivers/clk/mediatek/clk-mux.c2
-rw-r--r--drivers/clk/meson/Kconfig20
-rw-r--r--drivers/clk/meson/Makefile2
-rw-r--r--drivers/clk/meson/a1-peripherals.c2243
-rw-r--r--drivers/clk/meson/a1-peripherals.h113
-rw-r--r--drivers/clk/meson/a1-pll.c356
-rw-r--r--drivers/clk/meson/a1-pll.h47
-rw-r--r--drivers/clk/meson/clk-pll.c47
-rw-r--r--drivers/clk/meson/clk-pll.h2
-rw-r--r--drivers/clk/microchip/Kconfig4
-rw-r--r--drivers/clk/microchip/clk-pic32mzda.c2
-rw-r--r--drivers/clk/mvebu/ap-cpu-clk.c16
-rw-r--r--drivers/clk/mvebu/armada_ap_cp_helper.c8
-rw-r--r--drivers/clk/mvebu/clk-cpu.c14
-rw-r--r--drivers/clk/nuvoton/Kconfig19
-rw-r--r--drivers/clk/nuvoton/Makefile4
-rw-r--r--drivers/clk/nuvoton/clk-ma35d1-divider.c132
-rw-r--r--drivers/clk/nuvoton/clk-ma35d1-pll.c360
-rw-r--r--drivers/clk/nuvoton/clk-ma35d1.c1059
-rw-r--r--drivers/clk/nuvoton/clk-ma35d1.h18
-rw-r--r--drivers/clk/pxa/clk-pxa.c1
-rw-r--r--drivers/clk/pxa/clk-pxa25x.c2
-rw-r--r--drivers/clk/pxa/clk-pxa27x.c3
-rw-r--r--drivers/clk/qcom/Kconfig133
-rw-r--r--drivers/clk/qcom/Makefile7
-rw-r--r--drivers/clk/qcom/apss-ipq-pll.c19
-rw-r--r--drivers/clk/qcom/camcc-sc7180.c19
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.c21
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.h3
-rw-r--r--drivers/clk/qcom/clk-branch.c6
-rw-r--r--drivers/clk/qcom/clk-cbf-8996.c60
-rw-r--r--drivers/clk/qcom/clk-rcg.h2
-rw-r--r--drivers/clk/qcom/clk-rcg2.c2
-rw-r--r--drivers/clk/qcom/clk-rpmh.c19
-rw-r--r--drivers/clk/qcom/clk-smd-rpm.c58
-rw-r--r--drivers/clk/qcom/dispcc-qcm2290.c12
-rw-r--r--drivers/clk/qcom/gcc-ipq5332.c6
-rw-r--r--drivers/clk/qcom/gcc-ipq6018.c45
-rw-r--r--drivers/clk/qcom/gcc-ipq9574.c506
-rw-r--r--drivers/clk/qcom/gcc-qcm2290.c62
-rw-r--r--drivers/clk/qcom/gcc-sc8280xp.c18
-rw-r--r--drivers/clk/qcom/gcc-sdm660.c2
-rw-r--r--drivers/clk/qcom/gcc-sdx75.c2970
-rw-r--r--drivers/clk/qcom/gcc-sm6115.c8
-rw-r--r--drivers/clk/qcom/gcc-sm8450.c39
-rw-r--r--drivers/clk/qcom/gpucc-sc8280xp.c19
-rw-r--r--drivers/clk/qcom/gpucc-sm6375.c19
-rw-r--r--drivers/clk/qcom/gpucc-sm8450.c766
-rw-r--r--drivers/clk/qcom/gpucc-sm8550.c611
-rw-r--r--drivers/clk/qcom/lpasscc-sc8280xp.c87
-rw-r--r--drivers/clk/qcom/mmcc-msm8974.c23
-rw-r--r--drivers/clk/qcom/videocc-sm8350.c552
-rw-r--r--drivers/clk/qcom/videocc-sm8450.c463
-rw-r--r--drivers/clk/qcom/videocc-sm8550.c470
-rw-r--r--drivers/clk/ralink/Kconfig7
-rw-r--r--drivers/clk/ralink/Makefile1
-rw-r--r--drivers/clk/ralink/clk-mtmips.c1117
-rw-r--r--drivers/clk/renesas/clk-mstp.c18
-rw-r--r--drivers/clk/renesas/r8a779a0-cpg-mssr.c1
-rw-r--r--drivers/clk/renesas/r9a06g032-clocks.c1
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.c31
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.c22
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.h3
-rw-r--r--drivers/clk/samsung/Kconfig1
-rw-r--r--drivers/clk/samsung/clk-exynos-clkout.c3
-rw-r--r--drivers/clk/samsung/clk-exynos4.c44
-rw-r--r--drivers/clk/sifive/sifive-prci.c4
-rw-r--r--drivers/clk/socfpga/clk-gate.c1
-rw-r--r--drivers/clk/sprd/composite.c9
-rw-r--r--drivers/clk/sprd/div.c14
-rw-r--r--drivers/clk/sprd/div.h5
-rw-r--r--drivers/clk/st/clk-flexgen.c15
-rw-r--r--drivers/clk/stm32/clk-stm32-core.c33
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-a64.c14
-rw-r--r--drivers/clk/tegra/clk-bpmp.c1
-rw-r--r--drivers/clk/tegra/clk-periph.c17
-rw-r--r--drivers/clk/tegra/clk-super.c16
-rw-r--r--drivers/clk/tegra/clk-tegra-super-cclk.c15
-rw-r--r--drivers/clk/tegra/clk-tegra124-emc.c2
-rw-r--r--drivers/clk/ti/clkctrl.c7
-rw-r--r--drivers/clk/ux500/clk-prcmu.c1
-rw-r--r--drivers/clk/ux500/clk-sysctrl.c1
-rw-r--r--drivers/clk/versatile/clk-sp810.c1
-rw-r--r--drivers/clk/xilinx/clk-xlnx-clock-wizard.c7
-rw-r--r--drivers/clocksource/timer-riscv.c92
-rw-r--r--drivers/comedi/Kconfig103
-rw-r--r--drivers/comedi/comedi_fops.c47
-rw-r--r--drivers/comedi/drivers/comedi_test.c23
-rw-r--r--drivers/counter/104-quad-8.c802
-rw-r--r--drivers/counter/Kconfig23
-rw-r--r--drivers/counter/Makefile1
-rw-r--r--drivers/counter/counter-sysfs.c8
-rw-r--r--drivers/counter/i8254.c447
-rw-r--r--drivers/counter/stm32-timer-cnt.c3
-rw-r--r--drivers/cpufreq/Kconfig3
-rw-r--r--drivers/cpufreq/armada-8k-cpufreq.c16
-rw-r--r--drivers/cpufreq/cpufreq-dt-platdev.c5
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c30
-rw-r--r--drivers/cpufreq/intel_pstate.c58
-rw-r--r--drivers/cpufreq/mediatek-cpufreq.c13
-rw-r--r--drivers/cpufreq/qcom-cpufreq-hw.c2
-rw-r--r--drivers/cpufreq/qcom-cpufreq-nvmem.c63
-rw-r--r--drivers/cpufreq/sparc-us2e-cpufreq.c58
-rw-r--r--drivers/cpufreq/sparc-us3-cpufreq.c58
-rw-r--r--drivers/cpufreq/tegra194-cpufreq.c6
-rw-r--r--drivers/cpufreq/ti-cpufreq.c1
-rw-r--r--drivers/crypto/Kconfig1
-rw-r--r--drivers/crypto/Makefile1
-rw-r--r--drivers/crypto/atmel-ecc.c2
-rw-r--r--drivers/crypto/atmel-sha204a.c2
-rw-r--r--drivers/crypto/caam/Kconfig9
-rw-r--r--drivers/crypto/caam/caamalg_qi2.c4
-rw-r--r--drivers/crypto/caam/caamrng.c48
-rw-r--r--drivers/crypto/caam/ctrl.c274
-rw-r--r--drivers/crypto/caam/intern.h1
-rw-r--r--drivers/crypto/caam/regs.h14
-rw-r--r--drivers/crypto/ccp/platform-access.c5
-rw-r--r--drivers/crypto/ccp/sp-pci.c43
-rw-r--r--drivers/crypto/hisilicon/Kconfig7
-rw-r--r--drivers/crypto/hisilicon/Makefile2
-rw-r--r--drivers/crypto/hisilicon/qm.c5
-rw-r--r--drivers/crypto/hisilicon/trng/Makefile3
-rw-r--r--drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c2
-rw-r--r--drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c229
-rw-r--r--drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h2
-rw-r--r--drivers/crypto/intel/qat/qat_4xxx/adf_drv.c45
-rw-r--r--drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c12
-rw-r--r--drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c12
-rw-r--r--drivers/crypto/intel/qat/qat_c62x/adf_drv.c12
-rw-r--r--drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c12
-rw-r--r--drivers/crypto/intel/qat/qat_common/Makefile4
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_accel_devices.h2
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_accel_engine.c2
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_admin.c1
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_cfg.c24
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_cfg.h2
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h8
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_common_drv.h2
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_dbgfs.c69
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_dbgfs.h29
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c12
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h1
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_init.c6
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_sysfs.c60
-rw-r--r--drivers/crypto/intel/qat/qat_common/icp_qat_hw.h3
-rw-r--r--drivers/crypto/intel/qat/qat_common/qat_algs.c1
-rw-r--r--drivers/crypto/intel/qat/qat_common/qat_asym_algs.c14
-rw-r--r--drivers/crypto/intel/qat/qat_common/qat_uclo.c8
-rw-r--r--drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c12
-rw-r--r--drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c12
-rw-r--r--drivers/crypto/marvell/cesa/cipher.c2
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cpt_common.h15
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c3
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptlf.c34
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptlf.h33
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptpf.h7
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c41
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c247
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c10
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptvf.h1
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c8
-rw-r--r--drivers/crypto/n2_core.c9
-rw-r--r--drivers/crypto/nx/Makefile2
-rw-r--r--drivers/crypto/nx/nx.h4
-rw-r--r--drivers/crypto/sa2ul.h2
-rw-r--r--drivers/crypto/starfive/Kconfig20
-rw-r--r--drivers/crypto/starfive/Makefile4
-rw-r--r--drivers/crypto/starfive/jh7110-cryp.c258
-rw-r--r--drivers/crypto/starfive/jh7110-cryp.h172
-rw-r--r--drivers/crypto/starfive/jh7110-hash.c899
-rw-r--r--drivers/crypto/starfive/jh7110-rsa.c617
-rw-r--r--drivers/crypto/virtio/virtio_crypto_core.c1
-rw-r--r--drivers/cxl/Kconfig14
-rw-r--r--drivers/cxl/acpi.c208
-rw-r--r--drivers/cxl/core/Makefile1
-rw-r--r--drivers/cxl/core/core.h11
-rw-r--r--drivers/cxl/core/hdm.c48
-rw-r--r--drivers/cxl/core/mbox.c339
-rw-r--r--drivers/cxl/core/memdev.c503
-rw-r--r--drivers/cxl/core/pci.c31
-rw-r--r--drivers/cxl/core/pmem.c2
-rw-r--r--drivers/cxl/core/pmu.c68
-rw-r--r--drivers/cxl/core/port.c163
-rw-r--r--drivers/cxl/core/region.c168
-rw-r--r--drivers/cxl/core/regs.c182
-rw-r--r--drivers/cxl/cxl.h104
-rw-r--r--drivers/cxl/cxlmem.h229
-rw-r--r--drivers/cxl/cxlpci.h1
-rw-r--r--drivers/cxl/mem.c26
-rw-r--r--drivers/cxl/pci.c486
-rw-r--r--drivers/cxl/pmem.c35
-rw-r--r--drivers/cxl/pmu.h28
-rw-r--r--drivers/cxl/port.c21
-rw-r--r--drivers/cxl/security.c27
-rw-r--r--drivers/dax/bus.c64
-rw-r--r--drivers/dax/bus.h8
-rw-r--r--drivers/dax/cxl.c8
-rw-r--r--drivers/dax/dax-private.h11
-rw-r--r--drivers/dax/device.c3
-rw-r--r--drivers/dax/hmem/hmem.c8
-rw-r--r--drivers/dax/kmem.c2
-rw-r--r--drivers/dax/pmem.c7
-rw-r--r--drivers/dax/super.c5
-rw-r--r--drivers/dma-buf/dma-resv.c2
-rw-r--r--drivers/dma-buf/sw_sync.c2
-rw-r--r--drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c4
-rw-r--r--drivers/dma/ioat/dma.c12
-rw-r--r--drivers/extcon/Kconfig1
-rw-r--r--drivers/extcon/extcon-axp288.c2
-rw-r--r--drivers/extcon/extcon-fsa9480.c2
-rw-r--r--drivers/extcon/extcon-palmas.c1
-rw-r--r--drivers/extcon/extcon-ptn5150.c2
-rw-r--r--drivers/extcon/extcon-qcom-spmi-misc.c4
-rw-r--r--drivers/extcon/extcon-rt8973a.c2
-rw-r--r--drivers/extcon/extcon-sm5502.c2
-rw-r--r--drivers/extcon/extcon-usbc-tusb320.c155
-rw-r--r--drivers/extcon/extcon.c368
-rw-r--r--drivers/extcon/extcon.h8
-rw-r--r--drivers/firewire/.kunitconfig4
-rw-r--r--drivers/firewire/Kconfig16
-rw-r--r--drivers/firewire/Makefile3
-rw-r--r--drivers/firewire/core-cdev.c252
-rw-r--r--drivers/firewire/core-device.c2
-rw-r--r--drivers/firewire/core-topology.c2
-rw-r--r--drivers/firewire/core-transaction.c93
-rw-r--r--drivers/firewire/core.h7
-rw-r--r--drivers/firewire/net.c6
-rw-r--r--drivers/firewire/ohci.c191
-rw-r--r--drivers/firewire/uapi-test.c89
-rw-r--r--drivers/firmware/arm_scmi/driver.c1
-rw-r--r--drivers/firmware/arm_scmi/powercap.c173
-rw-r--r--drivers/firmware/arm_scmi/smc.c30
-rw-r--r--drivers/firmware/cirrus/cs_dsp.c8
-rw-r--r--drivers/firmware/dmi-sysfs.c4
-rw-r--r--drivers/firmware/efi/efi.c1
-rw-r--r--drivers/firmware/efi/esrt.c6
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c6
-rw-r--r--drivers/firmware/efi/vars.c12
-rw-r--r--drivers/firmware/stratix10-svc.c2
-rw-r--r--drivers/firmware/sysfb.c2
-rw-r--r--drivers/firmware/tegra/bpmp-tegra186.c204
-rw-r--r--drivers/firmware/tegra/bpmp.c4
-rw-r--r--drivers/firmware/xilinx/zynqmp-debug.c2
-rw-r--r--drivers/firmware/xilinx/zynqmp-debug.h2
-rw-r--r--drivers/firmware/xilinx/zynqmp.c14
-rw-r--r--drivers/fpga/dfl-fme-main.c4
-rw-r--r--drivers/fpga/intel-m10-bmc-sec-update.c47
-rw-r--r--drivers/fpga/zynq-fpga.c8
-rw-r--r--drivers/gpio/Kconfig55
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/gpio-adnp.c2
-rw-r--r--drivers/gpio/gpio-aggregator.c110
-rw-r--r--drivers/gpio/gpio-brcmstb.c3
-rw-r--r--drivers/gpio/gpio-davinci.c4
-rw-r--r--drivers/gpio/gpio-fxl6408.c2
-rw-r--r--drivers/gpio/gpio-gw-pld.c2
-rw-r--r--drivers/gpio/gpio-ixp4xx.c4
-rw-r--r--drivers/gpio/gpio-lpc18xx.c1
-rw-r--r--drivers/gpio/gpio-max7300.c2
-rw-r--r--drivers/gpio/gpio-max732x.c2
-rw-r--r--drivers/gpio/gpio-mlxbf3.c248
-rw-r--r--drivers/gpio/gpio-mpc8xxx.c7
-rw-r--r--drivers/gpio/gpio-pca953x.c2
-rw-r--r--drivers/gpio/gpio-pca9570.c2
-rw-r--r--drivers/gpio/gpio-pcf857x.c2
-rw-r--r--drivers/gpio/gpio-sa1100.c1
-rw-r--r--drivers/gpio/gpio-sch311x.c26
-rw-r--r--drivers/gpio/gpio-tangier.c4
-rw-r--r--drivers/gpio/gpio-tegra186.c92
-rw-r--r--drivers/gpio/gpio-tpic2810.c27
-rw-r--r--drivers/gpio/gpio-tps65086.c27
-rw-r--r--drivers/gpio/gpio-tps65219.c185
-rw-r--r--drivers/gpio/gpio-ts4900.c2
-rw-r--r--drivers/gpio/gpio-twl4030.c64
-rw-r--r--drivers/gpio/gpio-xra1403.c1
-rw-r--r--drivers/gpio/gpio-zynq.c46
-rw-r--r--drivers/gpio/gpiolib-legacy.c12
-rw-r--r--drivers/gpio/gpiolib.c44
-rw-r--r--drivers/gpu/drm/Kconfig14
-rw-r--r--drivers/gpu/drm/Makefile4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Kconfig10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Makefile30
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h79
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c407
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c82
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h60
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c154
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c123
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c384
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c325
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.h55
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c182
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c210
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c470
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h68
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c171
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c49
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c38
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_csa.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c41
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c243
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c305
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c350
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell.h44
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c83
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c32
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c52
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c141
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c372
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h142
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c63
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h50
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c33
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c46
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.h8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c28
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c47
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c46
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h24
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c50
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.h9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c187
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c246
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h72
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c261
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c116
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h43
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c330
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c34
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umr.h36
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c83
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c59
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h35
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c237
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c33
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c67
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c399
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h182
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c51
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/aqua_vanjaram_reg_init.c658
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik_sdma.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c278
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c312
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c33
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c51
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c114
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c194
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c24
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c34
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c4165
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c850
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c57
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c46
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c616
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c1074
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h51
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v10_1.c36
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v11_0.c59
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c915
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmsch_v3_0.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmsch_v4_0.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c118
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nv.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nvd.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v13_0.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v13_0.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c32
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c491
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_dma.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.c103
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.h30
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15.c87
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15_common.h69
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc21.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ta_ras_if.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v8_10.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v8_10.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v4_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c1541
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h29
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vega20_ih.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.c10
-rw-r--r--drivers/gpu/drm/amd/amdkfd/Makefile4
-rw-r--r--drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c8
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_chardev.c460
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.c83
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.h8
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_debug.c1118
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_debug.h123
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device.c481
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c1031
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h35
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c10
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c14
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_events.c93
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_events.h1
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c12
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c405
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c29
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c108
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c64
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_iommu.c31
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c18
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_migrate.c85
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_migrate.h9
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c40
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h17
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c14
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c32
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c83
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c423
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c19
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c34
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c86
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c4
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_ai.h73
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_priv.h320
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c283
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c98
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c54
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h22
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_svm.c303
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_svm.h29
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.c213
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.h14
-rw-r--r--drivers/gpu/drm/amd/amdxcp/Makefile25
-rw-r--r--drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c110
-rw-r--r--drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.h29
-rw-r--r--drivers/gpu/drm/amd/display/Kconfig19
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c231
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h4
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c31
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c196
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c36
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c5
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/command_table2.c25
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c20
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c58
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c73
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c36
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c50
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c42
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c58
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c42
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c53
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c71
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c436
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c375
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c35
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c38
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h40
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c310
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dp_types.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dsc.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_helper.c90
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_stream.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c38
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c258
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c252
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.h46
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c30
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c157
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c20
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c80
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c29
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h28
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c96
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c34
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c39
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c83
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c68
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c34
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/Makefile38
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c70
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c34
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c34
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c31
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c30
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c121
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c45
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c42
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c63
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c165
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c45
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c88
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c20
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c51
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h22
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c221
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c55
-rw-r--r--drivers/gpu/drm/amd/display/dc/dm_services.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dm_services_types.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/Makefile5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c66
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c70
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c244
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c45
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c65
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c34
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c555
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c20
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c504
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_types.h14
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/abm.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h167
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c83
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_detection.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dpms.c225
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_factory.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c36
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c29
-rw-r--r--drivers/gpu/drm/amd/display/dmub/dmub_srv.h18
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h40
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c5
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h2
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c6
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h4
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c5
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h2
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c62
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h33
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c16
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h3
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c47
-rw-r--r--drivers/gpu/drm/amd/display/include/fixed31_32.h2
-rw-r--r--drivers/gpu/drm/amd/display/include/signal_types.h28
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c15
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.c43
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.h3
-rw-r--r--drivers/gpu/drm/amd/include/amd_shared.h1
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_offset.h14
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_sh_mask.h69
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h10
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h4
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_0_0_sh_mask.h4
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_offset.h192
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_sh_mask.h1112
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_1_8_0_offset.h56
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_1_8_0_sh_mask.h325
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_9_0_offset.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/sdma/sdma_4_4_2_offset.h4
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/sdma/sdma_4_4_2_sh_mask.h24
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_13_0_3_offset.h177
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_13_0_3_sh_mask.h428
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_4_0_3_offset.h2332
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_4_0_3_sh_mask.h10919
-rw-r--r--drivers/gpu/drm/amd/include/atomfirmware.h1
-rw-r--r--drivers/gpu/drm/amd/include/discovery.h32
-rw-r--r--drivers/gpu/drm/amd/include/kgd_kfd_interface.h59
-rw-r--r--drivers/gpu/drm/amd/include/mes_v11_api_def.h22
-rw-r--r--drivers/gpu/drm/amd/include/v9_structs.h30
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_pm.c68
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_v13_0_0_pptable.h16
-rw-r--r--drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c6
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c12
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.c36
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c10
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_aldebaran.h2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h51
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_5.h2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_6.h15
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h31
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_yellow_carp.h2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h17
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_ppsmc.h3
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h14
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h16
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c18
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c1
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c52
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c492
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c95
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c81
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.h2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c396
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c488
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c142
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.h1
-rw-r--r--drivers/gpu/drm/arm/hdlcd_drv.c2
-rw-r--r--drivers/gpu/drm/armada/Kconfig1
-rw-r--r--drivers/gpu/drm/armada/Makefile3
-rw-r--r--drivers/gpu/drm/armada/armada_drm.h10
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c14
-rw-r--r--drivers/gpu/drm/armada/armada_fb.c1
-rw-r--r--drivers/gpu/drm/armada/armada_fbdev.c126
-rw-r--r--drivers/gpu/drm/bridge/Kconfig1
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c2
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix-anx6345.c2
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c2
-rw-r--r--drivers/gpu/drm/bridge/analogix/anx7625.c131
-rw-r--r--drivers/gpu/drm/bridge/chipone-icn6211.c2
-rw-r--r--drivers/gpu/drm/bridge/chrontel-ch7033.c2
-rw-r--r--drivers/gpu/drm/bridge/cros-ec-anx7688.c2
-rw-r--r--drivers/gpu/drm/bridge/display-connector.c61
-rw-r--r--drivers/gpu/drm/bridge/fsl-ldb.c14
-rw-r--r--drivers/gpu/drm/bridge/imx/Kconfig5
-rw-r--r--drivers/gpu/drm/bridge/imx/Makefile5
-rw-r--r--drivers/gpu/drm/bridge/imx/imx-ldb-helper.c17
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qm-ldb.c (renamed from drivers/gpu/drm/bridge/imx/imx8qm-ldb-drv.c)0
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c (renamed from drivers/gpu/drm/bridge/imx/imx8qxp-ldb-drv.c)0
-rw-r--r--drivers/gpu/drm/bridge/ite-it6505.c5
-rw-r--r--drivers/gpu/drm/bridge/ite-it66121.c2
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt8912b.c2
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9211.c6
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9611.c6
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9611uxc.c2
-rw-r--r--drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c4
-rw-r--r--drivers/gpu/drm/bridge/nxp-ptn3460.c2
-rw-r--r--drivers/gpu/drm/bridge/parade-ps8622.c2
-rw-r--r--drivers/gpu/drm/bridge/parade-ps8640.c2
-rw-r--r--drivers/gpu/drm/bridge/samsung-dsim.c194
-rw-r--r--drivers/gpu/drm/bridge/sii902x.c2
-rw-r--r--drivers/gpu/drm/bridge/sii9234.c2
-rw-r--r--drivers/gpu/drm/bridge/sil-sii8620.c2
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi.c2
-rw-r--r--drivers/gpu/drm/bridge/tc358762.c15
-rw-r--r--drivers/gpu/drm/bridge/tc358767.c201
-rw-r--r--drivers/gpu/drm/bridge/tc358768.c99
-rw-r--r--drivers/gpu/drm/bridge/tc358775.c2
-rw-r--r--drivers/gpu/drm/bridge/ti-dlpc3433.c2
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi83.c22
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi86.c21
-rw-r--r--drivers/gpu/drm/bridge/ti-tfp410.c2
-rw-r--r--drivers/gpu/drm/display/drm_dp_mst_topology.c109
-rw-r--r--drivers/gpu/drm/display/drm_dsc_helper.c1065
-rw-r--r--drivers/gpu/drm/drm_aperture.c11
-rw-r--r--drivers/gpu/drm/drm_atomic.c1
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c13
-rw-r--r--drivers/gpu/drm/drm_connector.c189
-rw-r--r--drivers/gpu/drm/drm_drv.c4
-rw-r--r--drivers/gpu/drm/drm_edid.c38
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c402
-rw-r--r--drivers/gpu/drm/drm_fbdev_dma.c11
-rw-r--r--drivers/gpu/drm/drm_fbdev_generic.c11
-rw-r--r--drivers/gpu/drm/drm_file.c132
-rw-r--r--drivers/gpu/drm/drm_gem_framebuffer_helper.c9
-rw-r--r--drivers/gpu/drm/drm_gem_vram_helper.c6
-rw-r--r--drivers/gpu/drm/drm_sysfs.c51
-rw-r--r--drivers/gpu/drm/exynos/Kconfig1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c9
-rw-r--r--drivers/gpu/drm/gma500/Kconfig1
-rw-r--r--drivers/gpu/drm/gma500/fbdev.c10
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.c43
-rw-r--r--drivers/gpu/drm/hyperv/hyperv_drm_drv.c1
-rw-r--r--drivers/gpu/drm/i2c/tda9950.c2
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c2
-rw-r--r--drivers/gpu/drm/i915/Kconfig1
-rw-r--r--drivers/gpu/drm/i915/Kconfig.debug1
-rw-r--r--drivers/gpu/drm/i915/Makefile21
-rw-r--r--drivers/gpu/drm/i915/display/g4x_dp.c4
-rw-r--r--drivers/gpu/drm/i915/display/g4x_hdmi.c113
-rw-r--r--drivers/gpu/drm/i915/display/g4x_hdmi.h4
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_plane.c5
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_wm.c4
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_wm.h1
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic.c259
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic_plane.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_audio.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_bios.c251
-rw-r--r--drivers/gpu/drm/i915/display/intel_bios.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_bw.c348
-rw-r--r--drivers/gpu/drm/i915/display/intel_bw.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c181
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.c725
-rw-r--r--drivers/gpu/drm/i915/display/intel_connector.c22
-rw-r--r--drivers/gpu/drm/i915/display/intel_connector.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_crt.c55
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.c20
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.h10
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc_state_dump.c54
-rw-r--r--drivers/gpu/drm/i915/display/intel_cursor.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.c3046
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.h50
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h274
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c502
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c80
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c1182
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.h69
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_core.h19
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_debugfs.c27
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.c917
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.h129
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_driver.c590
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_driver.h36
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_irq.c1687
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_irq.h81
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.c66
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_map.c92
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_well.c5
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_well.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_reg_defs.h14
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_reset.c135
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_reset.h14
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_trace.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h73
-rw-r--r--drivers/gpu/drm/i915/display/intel_dkl_phy.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_dkl_phy.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c370
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux.c45
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux_regs.h62
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_link_training.c436
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c17
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll.c41
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.c92
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpt.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_drrs.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dvo.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb.c54
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb_pin.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc.c15
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbdev.c60
-rw-r--r--drivers/gpu/drm/i915/display/intel_fdi.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_fifo_underrun.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_global_state.c12
-rw-r--r--drivers/gpu/drm/i915/display/intel_global_state.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_gmbus.c5
-rw-r--r--drivers/gpu/drm/i915/display/intel_gmbus.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp.c815
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp.h12
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp_gsc.c18
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.c127
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.h9
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug.c19
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug_irq.c1442
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug_irq.h35
-rw-r--r--drivers/gpu/drm/i915/display/intel_hti.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_load_detect.c225
-rw-r--r--drivers/gpu/drm/i915/display/intel_load_detect.h20
-rw-r--r--drivers/gpu/drm/i915/display/intel_lvds.c16
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_lock.c50
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_lock.h33
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_setup.c356
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_verify.c36
-rw-r--r--drivers/gpu/drm/i915/display/intel_opregion.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_overlay.c16
-rw-r--r--drivers/gpu/drm/i915/display/intel_panel.c113
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch_display.c20
-rw-r--r--drivers/gpu/drm/i915/display/intel_pipe_crc.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_plane_initial.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_pmdemand.c620
-rw-r--r--drivers/gpu/drm/i915/display/intel_pmdemand.h67
-rw-r--r--drivers/gpu/drm/i915/display/intel_pps.c20
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c269
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr_regs.h207
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo.c108
-rw-r--r--drivers/gpu/drm/i915/display/intel_snps_phy.c7
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.h10
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite_uapi.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.c414
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.h5
-rw-r--r--drivers/gpu/drm/i915/display/intel_tv.c20
-rw-r--r--drivers/gpu/drm/i915/display/intel_vblank.c15
-rw-r--r--drivers/gpu/drm/i915/display/intel_vblank.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc.c443
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr.c64
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr.h10
-rw-r--r--drivers/gpu/drm/i915/display/skl_scaler.c314
-rw-r--r--drivers/gpu/drm/i915/display/skl_scaler.h12
-rw-r--r--drivers/gpu/drm/i915/display/skl_universal_plane.c27
-rw-r--r--drivers/gpu/drm/i915/display/skl_watermark.c10
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi.c7
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi_pll.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_context.c6
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_create.c40
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_domain.c61
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c18
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_mman.c148
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_mman.h2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object.c66
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object.h10
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object_types.h68
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_pages.c5
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_region.h4
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_shmem.c11
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_shrinker.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_stolen.c12
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm.h3
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c13
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/huge_pages.c108
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c18
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c2
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c2
-rw-r--r--drivers/gpu/drm/i915/gt/gen6_ppgtt.c10
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_engine_cs.c38
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_ppgtt.c84
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_ppgtt.h3
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context.c5
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context.h8
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context_types.h2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_cs.c2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_pm.c4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_types.h1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_user.c2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_execlists_submission.c5
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ggtt.c111
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c8
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c10
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_irq.c28
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_pm.c6
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c5
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_regs.h19
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_requests.c10
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c35
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gtt.c47
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gtt.h36
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc.c4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_migrate.c51
-rw-r--r--drivers/gpu/drm/i915/gt/intel_migrate.h13
-rw-r--r--drivers/gpu/drm/i915/gt/intel_mocs.c70
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ppgtt.c4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rc6.c167
-rw-r--r--drivers/gpu/drm/i915/gt/intel_reset.c9
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rps.c22
-rw-r--r--drivers/gpu/drm/i915/gt/intel_workarounds.c56
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_engine_cs.c2
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_engine_pm.c3
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_migrate.c47
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_mocs.c3
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_reset.c8
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_rps.c1
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_slpc.c42
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_timeline.c2
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_tlb.c15
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h21
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h1
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h30
-rw-r--r--drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h20
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_binary_headers.h74
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c37
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h1
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c424
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.h18
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c102
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h17
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.c104
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.h27
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc.c10
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc.h1
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c36
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c268
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h3
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c140
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h17
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c12
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h44
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c40
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h1
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h1
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c75
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_huc.c225
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_huc.h26
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c235
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_huc_fw.h6
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_huc_print.h21
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc.c26
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc.h3
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c367
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h26
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h6
-rw-r--r--drivers/gpu/drm/i915/gvt/aperture_gm.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/cmd_parser.c6
-rw-r--r--drivers/gpu/drm/i915/gvt/edid.c10
-rw-r--r--drivers/gpu/drm/i915/gvt/handlers.c2
-rw-r--r--drivers/gpu/drm/i915/i915_active.h14
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c52
-rw-r--r--drivers/gpu/drm/i915/i915_driver.c115
-rw-r--r--drivers/gpu/drm/i915/i915_drm_client.c71
-rw-r--r--drivers/gpu/drm/i915/i915_drm_client.h24
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h477
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c33
-rw-r--r--drivers/gpu/drm/i915/i915_getparam.c13
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c153
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.h10
-rw-r--r--drivers/gpu/drm/i915/i915_hwmon.c91
-rw-r--r--drivers/gpu/drm/i915/i915_hwmon.h7
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c2675
-rw-r--r--drivers/gpu/drm/i915/i915_irq.h48
-rw-r--r--drivers/gpu/drm/i915/i915_pci.c455
-rw-r--r--drivers/gpu/drm/i915/i915_perf.c93
-rw-r--r--drivers/gpu/drm/i915/i915_perf_oa_regs.h4
-rw-r--r--drivers/gpu/drm/i915/i915_perf_types.h12
-rw-r--r--drivers/gpu/drm/i915/i915_pmu.c294
-rw-r--r--drivers/gpu/drm/i915/i915_pmu.h28
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h539
-rw-r--r--drivers/gpu/drm/i915/i915_reg_defs.h105
-rw-r--r--drivers/gpu/drm/i915/i915_request.c2
-rw-r--r--drivers/gpu/drm/i915/i915_request.h52
-rw-r--r--drivers/gpu/drm/i915/i915_scatterlist.h9
-rw-r--r--drivers/gpu/drm/i915/i915_utils.h2
-rw-r--r--drivers/gpu/drm/i915/i915_vma.c18
-rw-r--r--drivers/gpu/drm/i915/i915_vma.h4
-rw-r--r--drivers/gpu/drm/i915/i915_vma_resource.h46
-rw-r--r--drivers/gpu/drm/i915/i915_vma_types.h2
-rw-r--r--drivers/gpu/drm/i915/intel_clock_gating.c5
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.c209
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.h74
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.c2
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.h6
-rw-r--r--drivers/gpu/drm/i915/intel_step.c8
-rw-r--r--drivers/gpu/drm/i915/intel_wakeref.c22
-rw-r--r--drivers/gpu/drm/i915/intel_wakeref.h12
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp.c102
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp.h2
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h41
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c6
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.c444
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.h43
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_huc.c2
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_pm.c3
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_regs.h27
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_session.c25
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_tee.c2
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_types.h24
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_gem.c5
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_gem_evict.c8
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_gem_gtt.c17
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_perf.c2
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_sw_fence.c16
-rw-r--r--drivers/gpu/drm/i915/selftests/igt_live_test.c47
-rw-r--r--drivers/gpu/drm/i915/selftests/intel_memory_region.c4
-rw-r--r--drivers/gpu/drm/i915/selftests/mock_gem_device.c16
-rw-r--r--drivers/gpu/drm/i915/selftests/mock_gtt.c8
-rw-r--r--drivers/gpu/drm/imx/lcdc/imx-lcdc.c4
-rw-r--r--drivers/gpu/drm/meson/Kconfig7
-rw-r--r--drivers/gpu/drm/meson/Makefile3
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c64
-rw-r--r--drivers/gpu/drm/meson/meson_drv.h1
-rw-r--r--drivers/gpu/drm/meson/meson_dw_mipi_dsi.c352
-rw-r--r--drivers/gpu/drm/meson/meson_dw_mipi_dsi.h160
-rw-r--r--drivers/gpu/drm/meson/meson_encoder_dsi.c174
-rw-r--r--drivers/gpu/drm/meson/meson_encoder_dsi.h13
-rw-r--r--drivers/gpu/drm/meson/meson_registers.h25
-rw-r--r--drivers/gpu/drm/meson/meson_venc.c244
-rw-r--r--drivers/gpu/drm/meson/meson_venc.h6
-rw-r--r--drivers/gpu/drm/meson/meson_vpp.h2
-rw-r--r--drivers/gpu/drm/msm/Kconfig1
-rw-r--r--drivers/gpu/drm/msm/Makefile2
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_debugfs.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c3
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c128
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.h6
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c622
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.h4
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c14
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_hfi.c33
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c31
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c8
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h154
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h46
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h51
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h42
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h78
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h42
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h24
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h13
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h173
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h13
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h138
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h44
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h47
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h63
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h52
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h37
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c287
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h18
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h28
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c259
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c20
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c58
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c141
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h98
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c76
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h25
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c55
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h24
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c387
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c38
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h12
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c184
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c335
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h42
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c43
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h51
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c33
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h14
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c125
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h78
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c362
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h66
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c50
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c52
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h32
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c33
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h11
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c86
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h45
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c139
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c167
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c68
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h14
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c82
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_ctrl.h1
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.c6
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.h5
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c50
-rw-r--r--drivers/gpu/drm/msm/dp/dp_hpd.c67
-rw-r--r--drivers/gpu/drm/msm/dp/dp_hpd.h78
-rw-r--r--drivers/gpu/drm/msm/dp/dp_panel.h1
-rw-r--r--drivers/gpu/drm/msm/dp/dp_power.c78
-rw-r--r--drivers/gpu/drm/msm/dp/dp_power.h3
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.h1
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c177
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c68
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.h3
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c3
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c97
-rw-r--r--drivers/gpu/drm/msm/msm_debugfs.c6
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c15
-rw-r--r--drivers/gpu/drm/msm/msm_dsc_helper.h38
-rw-r--r--drivers/gpu/drm/msm/msm_fbdev.c43
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c15
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c7
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c6
-rw-r--r--drivers/gpu/drm/msm/msm_mdss.c10
-rw-r--r--drivers/gpu/drm/msm/msm_rd.c24
-rw-r--r--drivers/gpu/drm/mxsfb/lcdif_drv.c73
-rw-r--r--drivers/gpu/drm/mxsfb/lcdif_drv.h3
-rw-r--r--drivers/gpu/drm/mxsfb/lcdif_kms.c201
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c13
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_debugfs.c19
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_hwmon.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ttm.c10
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/power_budget.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/pcie.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c2
-rw-r--r--drivers/gpu/drm/omapdrm/Kconfig1
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fbdev.c11
-rw-r--r--drivers/gpu/drm/panel/Kconfig7
-rw-r--r--drivers/gpu/drm/panel/Makefile1
-rw-r--r--drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c876
-rw-r--r--drivers/gpu/drm/panel/panel-edp.c10
-rw-r--r--drivers/gpu/drm/panel/panel-khadas-ts050.c16
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt36523.c569
-rw-r--r--drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c2
-rw-r--r--drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c2
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c585
-rw-r--r--drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c43
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c135
-rw-r--r--drivers/gpu/drm/panel/panel-sitronix-st7703.c102
-rw-r--r--drivers/gpu/drm/radeon/Kconfig1
-rw-r--r--drivers/gpu/drm/radeon/ci_dpm.c28
-rw-r--r--drivers/gpu/drm/radeon/cypress_dpm.c8
-rw-r--r--drivers/gpu/drm/radeon/ni_dpm.c8
-rw-r--r--drivers/gpu/drm/radeon/r100.c8
-rw-r--r--drivers/gpu/drm/radeon/r300.c2
-rw-r--r--drivers/gpu/drm/radeon/r420.c2
-rw-r--r--drivers/gpu/drm/radeon/r600.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_acpi.h9
-rw-r--r--drivers/gpu/drm/radeon/radeon_atpx_handler.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_fbdev.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_ib.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c3
-rw-r--r--drivers/gpu/drm/radeon/rs400.c2
-rw-r--r--drivers/gpu/drm/radeon/rv515.c4
-rw-r--r--drivers/gpu/drm/radeon/rv740_dpm.c8
-rw-r--r--drivers/gpu/drm/renesas/Kconfig4
-rw-r--r--drivers/gpu/drm/renesas/Makefile4
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/Kconfig (renamed from drivers/gpu/drm/rcar-du/Kconfig)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/Makefile (renamed from drivers/gpu/drm/rcar-du/Makefile)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c (renamed from drivers/gpu/drm/rcar-du/rcar_cmm.c)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_cmm.h (renamed from drivers/gpu/drm/rcar-du/rcar_cmm.h)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c (renamed from drivers/gpu/drm/rcar-du/rcar_du_crtc.c)37
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h (renamed from drivers/gpu/drm/rcar-du/rcar_du_crtc.h)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c (renamed from drivers/gpu/drm/rcar-du/rcar_du_drv.c)48
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.h (renamed from drivers/gpu/drm/rcar-du/rcar_du_drv.h)2
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_encoder.c (renamed from drivers/gpu/drm/rcar-du/rcar_du_encoder.c)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_encoder.h (renamed from drivers/gpu/drm/rcar-du/rcar_du_encoder.h)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_group.c (renamed from drivers/gpu/drm/rcar-du/rcar_du_group.c)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_group.h (renamed from drivers/gpu/drm/rcar-du/rcar_du_group.h)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c (renamed from drivers/gpu/drm/rcar-du/rcar_du_kms.c)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.h (renamed from drivers/gpu/drm/rcar-du/rcar_du_kms.h)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.c (renamed from drivers/gpu/drm/rcar-du/rcar_du_plane.c)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.h (renamed from drivers/gpu/drm/rcar-du/rcar_du_plane.h)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_regs.h (renamed from drivers/gpu/drm/rcar-du/rcar_du_regs.h)3
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.c (renamed from drivers/gpu/drm/rcar-du/rcar_du_vsp.c)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.h (renamed from drivers/gpu/drm/rcar-du/rcar_du_vsp.h)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c (renamed from drivers/gpu/drm/rcar-du/rcar_du_writeback.c)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.h (renamed from drivers/gpu/drm/rcar-du/rcar_du_writeback.h)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c (renamed from drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c (renamed from drivers/gpu/drm/rcar-du/rcar_lvds.c)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_lvds.h (renamed from drivers/gpu/drm/rcar-du/rcar_lvds.h)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_lvds_regs.h (renamed from drivers/gpu/drm/rcar-du/rcar_lvds_regs.h)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c (renamed from drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.h (renamed from drivers/gpu/drm/rcar-du/rcar_mipi_dsi.h)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi_regs.h (renamed from drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi.c (renamed from drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c)0
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi_regs.h (renamed from drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h)0
-rw-r--r--drivers/gpu/drm/renesas/shmobile/Kconfig (renamed from drivers/gpu/drm/shmobile/Kconfig)4
-rw-r--r--drivers/gpu/drm/renesas/shmobile/Makefile (renamed from drivers/gpu/drm/shmobile/Makefile)0
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_backlight.c (renamed from drivers/gpu/drm/shmobile/shmob_drm_backlight.c)0
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_backlight.h (renamed from drivers/gpu/drm/shmobile/shmob_drm_backlight.h)0
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c (renamed from drivers/gpu/drm/shmobile/shmob_drm_crtc.c)35
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.h (renamed from drivers/gpu/drm/shmobile/shmob_drm_crtc.h)0
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c (renamed from drivers/gpu/drm/shmobile/shmob_drm_drv.c)3
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.h (renamed from drivers/gpu/drm/shmobile/shmob_drm_drv.h)0
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.c (renamed from drivers/gpu/drm/shmobile/shmob_drm_kms.c)9
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.h (renamed from drivers/gpu/drm/shmobile/shmob_drm_kms.h)0
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.c (renamed from drivers/gpu/drm/shmobile/shmob_drm_plane.c)5
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.h (renamed from drivers/gpu/drm/shmobile/shmob_drm_plane.h)0
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_regs.h (renamed from drivers/gpu/drm/shmobile/shmob_drm_regs.h)0
-rw-r--r--drivers/gpu/drm/rockchip/cdn-dp-core.c5
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c8
-rw-r--r--drivers/gpu/drm/scheduler/sched_entity.c55
-rw-r--r--drivers/gpu/drm/scheduler/sched_fence.c4
-rw-r--r--drivers/gpu/drm/scheduler/sched_main.c37
-rw-r--r--drivers/gpu/drm/solomon/ssd130x-i2c.c2
-rw-r--r--drivers/gpu/drm/solomon/ssd130x.h6
-rw-r--r--drivers/gpu/drm/sti/sti_dvo.c2
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.c11
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.h2
-rw-r--r--drivers/gpu/drm/stm/drv.c2
-rw-r--r--drivers/gpu/drm/stm/dw_mipi_dsi-stm.c4
-rw-r--r--drivers/gpu/drm/stm/ltdc.c4
-rw-r--r--drivers/gpu/drm/sun4i/Makefile2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c65
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon_dclk.c (renamed from drivers/gpu/drm/sun4i/sun4i_dotclock.c)2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon_dclk.h (renamed from drivers/gpu/drm/sun4i/sun4i_dotclock.h)0
-rw-r--r--drivers/gpu/drm/tegra/Kconfig1
-rw-r--r--drivers/gpu/drm/tegra/drm.c2
-rw-r--r--drivers/gpu/drm/tegra/fbdev.c8
-rw-r--r--drivers/gpu/drm/tegra/sor.c1
-rw-r--r--drivers/gpu/drm/tests/drm_rect_test.c315
-rw-r--r--drivers/gpu/drm/ttm/ttm_device.c4
-rw-r--r--drivers/gpu/drm/ttm/ttm_pool.c14
-rw-r--r--drivers/gpu/drm/ttm/ttm_tt.c7
-rw-r--r--drivers/gpu/drm/tve200/tve200_drv.c4
-rw-r--r--drivers/gpu/drm/udl/udl_main.c2
-rw-r--r--drivers/gpu/drm/vc4/tests/vc4_mock.h3
-rw-r--r--drivers/gpu/drm/vc4/tests/vc4_mock_output.c4
-rw-r--r--drivers/gpu/drm/vc4/vc4_dpi.c7
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h65
-rw-r--r--drivers/gpu/drm/vc4/vc4_dsi.c17
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c338
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.h25
-rw-r--r--drivers/gpu/drm/vc4/vc4_kms.c16
-rw-r--r--drivers/gpu/drm/vc4/vc4_plane.c3
-rw-r--r--drivers/gpu/drm/vc4/vc4_txp.c12
-rw-r--r--drivers/gpu/drm/vc4/vc4_vec.c14
-rw-r--r--drivers/gpu/drm/virtio/Makefile2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h4
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_ioctl.c182
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_submit.c311
-rw-r--r--drivers/gpu/drm/vkms/vkms_composer.c38
-rw-r--r--drivers/gpu/drm/vkms/vkms_crtc.c5
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.c6
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.h6
-rw-r--r--drivers/gpu/drm/vkms/vkms_formats.c145
-rw-r--r--drivers/gpu/drm/vkms/vkms_formats.h2
-rw-r--r--drivers/gpu/drm/vkms/vkms_plane.c50
-rw-r--r--drivers/gpu/ipu-v3/ipu-prv.h1
-rw-r--r--drivers/hid/Kconfig20
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/amd-sfh-hid/amd_sfh_client.c47
-rw-r--r--drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c24
-rw-r--r--drivers/hid/hid-apple.c13
-rw-r--r--drivers/hid/hid-asus.c42
-rw-r--r--drivers/hid/hid-core.c118
-rw-r--r--drivers/hid/hid-ids.h15
-rw-r--r--drivers/hid/hid-logitech-hidpp.c6
-rw-r--r--drivers/hid/hid-microsoft.c11
-rw-r--r--drivers/hid/hid-nvidia-shield.c738
-rw-r--r--drivers/hid/hid-picolcd_fb.c4
-rw-r--r--drivers/hid/hid-quirks.c1
-rw-r--r--drivers/hid/hidraw.c9
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-acpi.c2
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-of-elan.c2
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-of-goodix.c18
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-of.c2
-rw-r--r--drivers/hid/intel-ish-hid/ipc/hw-ish.h1
-rw-r--r--drivers/hid/intel-ish-hid/ipc/pci-ish.c1
-rw-r--r--drivers/hid/wacom_wac.c6
-rw-r--r--drivers/hid/wacom_wac.h2
-rw-r--r--drivers/hsi/clients/ssi_protocol.c2
-rw-r--r--drivers/hsi/controllers/omap_ssi_core.c1
-rw-r--r--drivers/hsi/controllers/omap_ssi_port.c14
-rw-r--r--drivers/hwmon/Kconfig28
-rw-r--r--drivers/hwmon/Makefile3
-rw-r--r--drivers/hwmon/ad7414.c2
-rw-r--r--drivers/hwmon/ad7418.c2
-rw-r--r--drivers/hwmon/adc128d818.c2
-rw-r--r--drivers/hwmon/adm1021.c2
-rw-r--r--drivers/hwmon/adm1025.c2
-rw-r--r--drivers/hwmon/adm1026.c2
-rw-r--r--drivers/hwmon/adm1029.c2
-rw-r--r--drivers/hwmon/adm1031.c2
-rw-r--r--drivers/hwmon/adm1177.c2
-rw-r--r--drivers/hwmon/adm9240.c2
-rw-r--r--drivers/hwmon/ads7828.c2
-rw-r--r--drivers/hwmon/adt7410.c2
-rw-r--r--drivers/hwmon/adt7411.c2
-rw-r--r--drivers/hwmon/adt7462.c2
-rw-r--r--drivers/hwmon/adt7470.c2
-rw-r--r--drivers/hwmon/adt7475.c10
-rw-r--r--drivers/hwmon/aht10.c154
-rw-r--r--drivers/hwmon/amc6821.c2
-rw-r--r--drivers/hwmon/aquacomputer_d5next.c117
-rw-r--r--drivers/hwmon/asb100.c2
-rw-r--r--drivers/hwmon/asc7621.c2
-rw-r--r--drivers/hwmon/asus-ec-sensors.c30
-rw-r--r--drivers/hwmon/atxp1.c2
-rw-r--r--drivers/hwmon/corsair-psu.c90
-rw-r--r--drivers/hwmon/dme1737.c2
-rw-r--r--drivers/hwmon/ds1621.c2
-rw-r--r--drivers/hwmon/ds620.c2
-rw-r--r--drivers/hwmon/emc1403.c2
-rw-r--r--drivers/hwmon/emc2103.c2
-rw-r--r--drivers/hwmon/emc2305.c2
-rw-r--r--drivers/hwmon/emc6w201.c2
-rw-r--r--drivers/hwmon/f71882fg.c7
-rw-r--r--drivers/hwmon/f75375s.c2
-rw-r--r--drivers/hwmon/fschmd.c2
-rw-r--r--drivers/hwmon/ftsteutates.c2
-rw-r--r--drivers/hwmon/g760a.c2
-rw-r--r--drivers/hwmon/g762.c2
-rw-r--r--drivers/hwmon/gl518sm.c2
-rw-r--r--drivers/hwmon/gl520sm.c2
-rw-r--r--drivers/hwmon/gsc-hwmon.c6
-rw-r--r--drivers/hwmon/hih6130.c2
-rw-r--r--drivers/hwmon/hp-wmi-sensors.c2004
-rw-r--r--drivers/hwmon/hwmon.c11
-rw-r--r--drivers/hwmon/ina209.c2
-rw-r--r--drivers/hwmon/ina238.c2
-rw-r--r--drivers/hwmon/ina2xx.c2
-rw-r--r--drivers/hwmon/ina3221.c2
-rw-r--r--drivers/hwmon/intel-m10-bmc-hwmon.c1
-rw-r--r--drivers/hwmon/it87.c136
-rw-r--r--drivers/hwmon/jc42.c2
-rw-r--r--drivers/hwmon/lineage-pem.c2
-rw-r--r--drivers/hwmon/lm63.c2
-rw-r--r--drivers/hwmon/lm73.c2
-rw-r--r--drivers/hwmon/lm75.c4
-rw-r--r--drivers/hwmon/lm77.c2
-rw-r--r--drivers/hwmon/lm78.c2
-rw-r--r--drivers/hwmon/lm80.c2
-rw-r--r--drivers/hwmon/lm83.c2
-rw-r--r--drivers/hwmon/lm85.c2
-rw-r--r--drivers/hwmon/lm87.c2
-rw-r--r--drivers/hwmon/lm90.c2
-rw-r--r--drivers/hwmon/lm92.c2
-rw-r--r--drivers/hwmon/lm93.c2
-rw-r--r--drivers/hwmon/lm95234.c2
-rw-r--r--drivers/hwmon/lm95241.c2
-rw-r--r--drivers/hwmon/lm95245.c4
-rw-r--r--drivers/hwmon/ltc2945.c2
-rw-r--r--drivers/hwmon/ltc2947-i2c.c2
-rw-r--r--drivers/hwmon/ltc2990.c2
-rw-r--r--drivers/hwmon/ltc2992.c2
-rw-r--r--drivers/hwmon/ltc4151.c2
-rw-r--r--drivers/hwmon/ltc4215.c2
-rw-r--r--drivers/hwmon/ltc4222.c2
-rw-r--r--drivers/hwmon/ltc4245.c2
-rw-r--r--drivers/hwmon/ltc4260.c2
-rw-r--r--drivers/hwmon/ltc4261.c2
-rw-r--r--drivers/hwmon/max1111.c1
-rw-r--r--drivers/hwmon/max127.c2
-rw-r--r--drivers/hwmon/max16065.c2
-rw-r--r--drivers/hwmon/max1619.c2
-rw-r--r--drivers/hwmon/max1668.c2
-rw-r--r--drivers/hwmon/max31730.c2
-rw-r--r--drivers/hwmon/max31760.c2
-rw-r--r--drivers/hwmon/max31790.c2
-rw-r--r--drivers/hwmon/max31827.c466
-rw-r--r--drivers/hwmon/max6620.c2
-rw-r--r--drivers/hwmon/max6621.c2
-rw-r--r--drivers/hwmon/max6639.c2
-rw-r--r--drivers/hwmon/max6642.c2
-rw-r--r--drivers/hwmon/max6650.c2
-rw-r--r--drivers/hwmon/max6697.c2
-rw-r--r--drivers/hwmon/mc34vr500.c2
-rw-r--r--drivers/hwmon/mcp3021.c2
-rw-r--r--drivers/hwmon/nct6683.c3
-rw-r--r--drivers/hwmon/nct6775-core.c55
-rw-r--r--drivers/hwmon/nct6775-i2c.c4
-rw-r--r--drivers/hwmon/nct6775-platform.c41
-rw-r--r--drivers/hwmon/nct6775.h2
-rw-r--r--drivers/hwmon/nct7802.c2
-rw-r--r--drivers/hwmon/nct7904.c2
-rw-r--r--drivers/hwmon/occ/p8_i2c.c2
-rw-r--r--drivers/hwmon/oxp-sensors.c194
-rw-r--r--drivers/hwmon/pcf8591.c2
-rw-r--r--drivers/hwmon/pmbus/acbel-fsg032.c2
-rw-r--r--drivers/hwmon/pmbus/adm1266.c4
-rw-r--r--drivers/hwmon/pmbus/adm1275.c118
-rw-r--r--drivers/hwmon/pmbus/bel-pfe.c2
-rw-r--r--drivers/hwmon/pmbus/bpa-rs600.c2
-rw-r--r--drivers/hwmon/pmbus/delta-ahe50dc-fan.c2
-rw-r--r--drivers/hwmon/pmbus/dps920ab.c2
-rw-r--r--drivers/hwmon/pmbus/fsp-3y.c2
-rw-r--r--drivers/hwmon/pmbus/ibm-cffps.c2
-rw-r--r--drivers/hwmon/pmbus/inspur-ipsps.c2
-rw-r--r--drivers/hwmon/pmbus/ir35221.c2
-rw-r--r--drivers/hwmon/pmbus/ir36021.c2
-rw-r--r--drivers/hwmon/pmbus/ir38064.c2
-rw-r--r--drivers/hwmon/pmbus/irps5401.c2
-rw-r--r--drivers/hwmon/pmbus/isl68137.c2
-rw-r--r--drivers/hwmon/pmbus/lm25066.c2
-rw-r--r--drivers/hwmon/pmbus/lt7182s.c2
-rw-r--r--drivers/hwmon/pmbus/ltc2978.c2
-rw-r--r--drivers/hwmon/pmbus/ltc3815.c2
-rw-r--r--drivers/hwmon/pmbus/max15301.c2
-rw-r--r--drivers/hwmon/pmbus/max16064.c2
-rw-r--r--drivers/hwmon/pmbus/max16601.c8
-rw-r--r--drivers/hwmon/pmbus/max20730.c2
-rw-r--r--drivers/hwmon/pmbus/max20751.c2
-rw-r--r--drivers/hwmon/pmbus/max31785.c2
-rw-r--r--drivers/hwmon/pmbus/max34440.c2
-rw-r--r--drivers/hwmon/pmbus/max8688.c2
-rw-r--r--drivers/hwmon/pmbus/mp2888.c2
-rw-r--r--drivers/hwmon/pmbus/mp2975.c2
-rw-r--r--drivers/hwmon/pmbus/mp5023.c2
-rw-r--r--drivers/hwmon/pmbus/mpq7932.c2
-rw-r--r--drivers/hwmon/pmbus/pim4328.c2
-rw-r--r--drivers/hwmon/pmbus/pli1209bc.c2
-rw-r--r--drivers/hwmon/pmbus/pm6764tr.c2
-rw-r--r--drivers/hwmon/pmbus/pmbus.c2
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c6
-rw-r--r--drivers/hwmon/pmbus/pxe1610.c2
-rw-r--r--drivers/hwmon/pmbus/q54sj108a2.c2
-rw-r--r--drivers/hwmon/pmbus/stpddc60.c2
-rw-r--r--drivers/hwmon/pmbus/tda38640.c2
-rw-r--r--drivers/hwmon/pmbus/tps40422.c2
-rw-r--r--drivers/hwmon/pmbus/tps53679.c2
-rw-r--r--drivers/hwmon/pmbus/tps546d24.c2
-rw-r--r--drivers/hwmon/pmbus/ucd9000.c4
-rw-r--r--drivers/hwmon/pmbus/ucd9200.c2
-rw-r--r--drivers/hwmon/pmbus/xdpe12284.c2
-rw-r--r--drivers/hwmon/pmbus/xdpe152c4.c2
-rw-r--r--drivers/hwmon/pmbus/zl6100.c2
-rw-r--r--drivers/hwmon/powr1220.c2
-rw-r--r--drivers/hwmon/sbrmi.c2
-rw-r--r--drivers/hwmon/sbtsi_temp.c2
-rw-r--r--drivers/hwmon/sht21.c2
-rw-r--r--drivers/hwmon/sht3x.c125
-rw-r--r--drivers/hwmon/sht4x.c2
-rw-r--r--drivers/hwmon/shtc1.c2
-rw-r--r--drivers/hwmon/smm665.c2
-rw-r--r--drivers/hwmon/smsc47m192.c2
-rw-r--r--drivers/hwmon/stts751.c2
-rw-r--r--drivers/hwmon/tc654.c2
-rw-r--r--drivers/hwmon/tc74.c2
-rw-r--r--drivers/hwmon/thmc50.c2
-rw-r--r--drivers/hwmon/tmp102.c4
-rw-r--r--drivers/hwmon/tmp103.c2
-rw-r--r--drivers/hwmon/tmp108.c4
-rw-r--r--drivers/hwmon/tmp401.c2
-rw-r--r--drivers/hwmon/tmp421.c2
-rw-r--r--drivers/hwmon/tmp464.c4
-rw-r--r--drivers/hwmon/tmp513.c2
-rw-r--r--drivers/hwmon/tps23861.c2
-rw-r--r--drivers/hwmon/w83773g.c2
-rw-r--r--drivers/hwmon/w83781d.c2
-rw-r--r--drivers/hwmon/w83791d.c2
-rw-r--r--drivers/hwmon/w83792d.c2
-rw-r--r--drivers/hwmon/w83793.c2
-rw-r--r--drivers/hwmon/w83795.c2
-rw-r--r--drivers/hwmon/w83l785ts.c2
-rw-r--r--drivers/hwmon/w83l786ng.c2
-rw-r--r--drivers/hwspinlock/omap_hwspinlock.c2
-rw-r--r--drivers/hwtracing/coresight/Kconfig11
-rw-r--r--drivers/hwtracing/coresight/Makefile1
-rw-r--r--drivers/hwtracing/coresight/coresight-catu.c21
-rw-r--r--drivers/hwtracing/coresight/coresight-core.c605
-rw-r--r--drivers/hwtracing/coresight/coresight-cti-core.c52
-rw-r--r--drivers/hwtracing/coresight/coresight-cti-sysfs.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-cti.h4
-rw-r--r--drivers/hwtracing/coresight/coresight-dummy.c163
-rw-r--r--drivers/hwtracing/coresight/coresight-etb10.c13
-rw-r--r--drivers/hwtracing/coresight/coresight-etm-perf.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-etm3x-core.c6
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x-core.c20
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x-sysfs.c27
-rw-r--r--drivers/hwtracing/coresight/coresight-funnel.c26
-rw-r--r--drivers/hwtracing/coresight/coresight-platform.c269
-rw-r--r--drivers/hwtracing/coresight/coresight-priv.h36
-rw-r--r--drivers/hwtracing/coresight/coresight-replicator.c23
-rw-r--r--drivers/hwtracing/coresight/coresight-stm.c6
-rw-r--r--drivers/hwtracing/coresight/coresight-sysfs.c17
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-etf.c26
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-etr.c110
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc.h2
-rw-r--r--drivers/hwtracing/coresight/coresight-tpda.c23
-rw-r--r--drivers/hwtracing/coresight/coresight-tpdm.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-tpiu.c7
-rw-r--r--drivers/hwtracing/coresight/coresight-trbe.c3
-rw-r--r--drivers/hwtracing/coresight/ultrasoc-smb.c11
-rw-r--r--drivers/hwtracing/coresight/ultrasoc-smb.h2
-rw-r--r--drivers/hwtracing/ptt/hisi_ptt.c444
-rw-r--r--drivers/hwtracing/ptt/hisi_ptt.h56
-rw-r--r--drivers/i2c/busses/Kconfig4
-rw-r--r--drivers/i2c/busses/i2c-altera.c6
-rw-r--r--drivers/i2c/busses/i2c-amd-mp2-plat.c5
-rw-r--r--drivers/i2c/busses/i2c-aspeed.c6
-rw-r--r--drivers/i2c/busses/i2c-at91-core.c6
-rw-r--r--drivers/i2c/busses/i2c-au1550.c5
-rw-r--r--drivers/i2c/busses/i2c-axxia.c6
-rw-r--r--drivers/i2c/busses/i2c-bcm-iproc.c6
-rw-r--r--drivers/i2c/busses/i2c-bcm-kona.c6
-rw-r--r--drivers/i2c/busses/i2c-bcm2835.c6
-rw-r--r--drivers/i2c/busses/i2c-brcmstb.c5
-rw-r--r--drivers/i2c/busses/i2c-cadence.c6
-rw-r--r--drivers/i2c/busses/i2c-cbus-gpio.c6
-rw-r--r--drivers/i2c/busses/i2c-cht-wc.c6
-rw-r--r--drivers/i2c/busses/i2c-cpm.c6
-rw-r--r--drivers/i2c/busses/i2c-cros-ec-tunnel.c6
-rw-r--r--drivers/i2c/busses/i2c-davinci.c29
-rw-r--r--drivers/i2c/busses/i2c-designware-common.c8
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h4
-rw-r--r--drivers/i2c/busses/i2c-designware-master.c89
-rw-r--r--drivers/i2c/busses/i2c-designware-pcidrv.c13
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c21
-rw-r--r--drivers/i2c/busses/i2c-digicolor.c6
-rw-r--r--drivers/i2c/busses/i2c-dln2.c6
-rw-r--r--drivers/i2c/busses/i2c-emev2.c6
-rw-r--r--drivers/i2c/busses/i2c-exynos5.c6
-rw-r--r--drivers/i2c/busses/i2c-gpio.c6
-rw-r--r--drivers/i2c/busses/i2c-gxp.c6
-rw-r--r--drivers/i2c/busses/i2c-highlander.c6
-rw-r--r--drivers/i2c/busses/i2c-hix5hd2.c23
-rw-r--r--drivers/i2c/busses/i2c-i801.c128
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c10
-rw-r--r--drivers/i2c/busses/i2c-img-scb.c8
-rw-r--r--drivers/i2c/busses/i2c-imx-lpi2c.c8
-rw-r--r--drivers/i2c/busses/i2c-imx.c6
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c6
-rw-r--r--drivers/i2c/busses/i2c-isch.c6
-rw-r--r--drivers/i2c/busses/i2c-jz4780.c5
-rw-r--r--drivers/i2c/busses/i2c-kempld.c6
-rw-r--r--drivers/i2c/busses/i2c-lpc2k.c28
-rw-r--r--drivers/i2c/busses/i2c-meson.c6
-rw-r--r--drivers/i2c/busses/i2c-microchip-corei2c.c6
-rw-r--r--drivers/i2c/busses/i2c-mlxbf.c6
-rw-r--r--drivers/i2c/busses/i2c-mlxcpld.c6
-rw-r--r--drivers/i2c/busses/i2c-mpc.c11
-rw-r--r--drivers/i2c/busses/i2c-mt65xx.c6
-rw-r--r--drivers/i2c/busses/i2c-mt7621.c26
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c6
-rw-r--r--drivers/i2c/busses/i2c-mxs.c6
-rw-r--r--drivers/i2c/busses/i2c-nomadik.c48
-rw-r--r--drivers/i2c/busses/i2c-npcm7xx.c5
-rw-r--r--drivers/i2c/busses/i2c-nvidia-gpu.c3
-rw-r--r--drivers/i2c/busses/i2c-ocores.c70
-rw-r--r--drivers/i2c/busses/i2c-octeon-platdrv.c5
-rw-r--r--drivers/i2c/busses/i2c-omap.c6
-rw-r--r--drivers/i2c/busses/i2c-opal.c6
-rw-r--r--drivers/i2c/busses/i2c-owl.c18
-rw-r--r--drivers/i2c/busses/i2c-pasemi-platform.c25
-rw-r--r--drivers/i2c/busses/i2c-pca-platform.c6
-rw-r--r--drivers/i2c/busses/i2c-pnx.c6
-rw-r--r--drivers/i2c/busses/i2c-powermac.c6
-rw-r--r--drivers/i2c/busses/i2c-pxa.c6
-rw-r--r--drivers/i2c/busses/i2c-qcom-cci.c9
-rw-r--r--drivers/i2c/busses/i2c-qcom-geni.c5
-rw-r--r--drivers/i2c/busses/i2c-qup.c5
-rw-r--r--drivers/i2c/busses/i2c-rcar.c6
-rw-r--r--drivers/i2c/busses/i2c-riic.c6
-rw-r--r--drivers/i2c/busses/i2c-rk3x.c6
-rw-r--r--drivers/i2c/busses/i2c-rzv2m.c49
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c6
-rw-r--r--drivers/i2c/busses/i2c-scmi.c6
-rw-r--r--drivers/i2c/busses/i2c-sh7760.c9
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c5
-rw-r--r--drivers/i2c/busses/i2c-simtec.c6
-rw-r--r--drivers/i2c/busses/i2c-st.c6
-rw-r--r--drivers/i2c/busses/i2c-stm32f4.c6
-rw-r--r--drivers/i2c/busses/i2c-stm32f7.c6
-rw-r--r--drivers/i2c/busses/i2c-sun6i-p2wi.c23
-rw-r--r--drivers/i2c/busses/i2c-synquacer.c6
-rw-r--r--drivers/i2c/busses/i2c-tegra-bpmp.c6
-rw-r--r--drivers/i2c/busses/i2c-tegra.c114
-rw-r--r--drivers/i2c/busses/i2c-tiny-usb.c4
-rw-r--r--drivers/i2c/busses/i2c-uniphier-f.c27
-rw-r--r--drivers/i2c/busses/i2c-uniphier.c27
-rw-r--r--drivers/i2c/busses/i2c-versatile.c9
-rw-r--r--drivers/i2c/busses/i2c-viperboard.c6
-rw-r--r--drivers/i2c/busses/i2c-wmt.c10
-rw-r--r--drivers/i2c/busses/i2c-xgene-slimpro.c6
-rw-r--r--drivers/i2c/busses/i2c-xiic.c26
-rw-r--r--drivers/i2c/busses/i2c-xlp9xx.c6
-rw-r--r--drivers/i2c/busses/scx200_acb.c6
-rw-r--r--drivers/i2c/i2c-core-base.c19
-rw-r--r--drivers/i2c/muxes/i2c-arb-gpio-challenge.c5
-rw-r--r--drivers/i2c/muxes/i2c-demux-pinctrl.c6
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpio.c6
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpmux.c6
-rw-r--r--drivers/i2c/muxes/i2c-mux-mlxcpld.c5
-rw-r--r--drivers/i2c/muxes/i2c-mux-pinctrl.c6
-rw-r--r--drivers/i2c/muxes/i2c-mux-reg.c6
-rw-r--r--drivers/i3c/master/svc-i3c-master.c51
-rw-r--r--drivers/idle/intel_idle.c2
-rw-r--r--drivers/iio/accel/adxl313_i2c.c2
-rw-r--r--drivers/iio/accel/adxl345_i2c.c2
-rw-r--r--drivers/iio/accel/adxl355_i2c.c2
-rw-r--r--drivers/iio/accel/adxl367_i2c.c2
-rw-r--r--drivers/iio/accel/adxl372_i2c.c2
-rw-r--r--drivers/iio/accel/bma180.c2
-rw-r--r--drivers/iio/accel/bma400_core.c3
-rw-r--r--drivers/iio/accel/bma400_i2c.c2
-rw-r--r--drivers/iio/accel/bmc150-accel-i2c.c2
-rw-r--r--drivers/iio/accel/da280.c2
-rw-r--r--drivers/iio/accel/da311.c2
-rw-r--r--drivers/iio/accel/dmard06.c2
-rw-r--r--drivers/iio/accel/dmard09.c2
-rw-r--r--drivers/iio/accel/dmard10.c2
-rw-r--r--drivers/iio/accel/fxls8962af-core.c8
-rw-r--r--drivers/iio/accel/fxls8962af-i2c.c2
-rw-r--r--drivers/iio/accel/kionix-kx022a-i2c.c3
-rw-r--r--drivers/iio/accel/kionix-kx022a-spi.c1
-rw-r--r--drivers/iio/accel/kionix-kx022a.c13
-rw-r--r--drivers/iio/accel/kxcjk-1013.c2
-rw-r--r--drivers/iio/accel/kxsd9-i2c.c2
-rw-r--r--drivers/iio/accel/mc3230.c2
-rw-r--r--drivers/iio/accel/mma7455_i2c.c2
-rw-r--r--drivers/iio/accel/mma7660.c2
-rw-r--r--drivers/iio/accel/mma8452.c2
-rw-r--r--drivers/iio/accel/mma9551.c2
-rw-r--r--drivers/iio/accel/mma9553.c2
-rw-r--r--drivers/iio/accel/msa311.c2
-rw-r--r--drivers/iio/accel/mxc4005.c2
-rw-r--r--drivers/iio/accel/mxc6255.c2
-rw-r--r--drivers/iio/accel/st_accel_core.c1
-rw-r--r--drivers/iio/accel/st_accel_i2c.c2
-rw-r--r--drivers/iio/accel/stk8312.c2
-rw-r--r--drivers/iio/accel/stk8ba50.c2
-rw-r--r--drivers/iio/adc/Kconfig13
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/ad7091r5.c2
-rw-r--r--drivers/iio/adc/ad7192.c8
-rw-r--r--drivers/iio/adc/ad7291.c2
-rw-r--r--drivers/iio/adc/ad799x.c2
-rw-r--r--drivers/iio/adc/ina2xx-adc.c2
-rw-r--r--drivers/iio/adc/ltc2471.c2
-rw-r--r--drivers/iio/adc/ltc2485.c2
-rw-r--r--drivers/iio/adc/ltc2497.c2
-rw-r--r--drivers/iio/adc/max1363.c2
-rw-r--r--drivers/iio/adc/max77541-adc.c194
-rw-r--r--drivers/iio/adc/max9611.c2
-rw-r--r--drivers/iio/adc/mcp3422.c2
-rw-r--r--drivers/iio/adc/meson_saradc.c2
-rw-r--r--drivers/iio/adc/nau7802.c2
-rw-r--r--drivers/iio/adc/palmas_gpadc.c1
-rw-r--r--drivers/iio/adc/qcom-spmi-adc5.c15
-rw-r--r--drivers/iio/adc/qcom-spmi-vadc.c19
-rw-r--r--drivers/iio/adc/rockchip_saradc.c246
-rw-r--r--drivers/iio/adc/rtq6056.c2
-rw-r--r--drivers/iio/adc/stm32-adc.c2
-rw-r--r--drivers/iio/adc/ti-adc081c.c2
-rw-r--r--drivers/iio/adc/ti-ads1015.c2
-rw-r--r--drivers/iio/adc/ti-ads1100.c2
-rw-r--r--drivers/iio/adc/ti-ads7924.c2
-rw-r--r--drivers/iio/adc/xilinx-ams.c9
-rw-r--r--drivers/iio/adc/xilinx-xadc-core.c17
-rw-r--r--drivers/iio/addac/ad74413r.c11
-rw-r--r--drivers/iio/amplifiers/ad8366.c2
-rw-r--r--drivers/iio/cdc/ad7150.c2
-rw-r--r--drivers/iio/cdc/ad7746.c2
-rw-r--r--drivers/iio/chemical/ams-iaq-core.c2
-rw-r--r--drivers/iio/chemical/atlas-ezo-sensor.c2
-rw-r--r--drivers/iio/chemical/atlas-sensor.c2
-rw-r--r--drivers/iio/chemical/bme680_i2c.c2
-rw-r--r--drivers/iio/chemical/ccs811.c2
-rw-r--r--drivers/iio/chemical/scd30_i2c.c2
-rw-r--r--drivers/iio/chemical/scd4x.c2
-rw-r--r--drivers/iio/chemical/sgp30.c2
-rw-r--r--drivers/iio/chemical/sgp40.c2
-rw-r--r--drivers/iio/chemical/sps30_i2c.c2
-rw-r--r--drivers/iio/chemical/sunrise_co2.c2
-rw-r--r--drivers/iio/chemical/vz89x.c2
-rw-r--r--drivers/iio/dac/ad5064.c2
-rw-r--r--drivers/iio/dac/ad5380.c2
-rw-r--r--drivers/iio/dac/ad5446.c2
-rw-r--r--drivers/iio/dac/ad5593r.c2
-rw-r--r--drivers/iio/dac/ad5696-i2c.c2
-rw-r--r--drivers/iio/dac/ds4424.c2
-rw-r--r--drivers/iio/dac/m62332.c2
-rw-r--r--drivers/iio/dac/max517.c2
-rw-r--r--drivers/iio/dac/max5821.c2
-rw-r--r--drivers/iio/dac/mcp4725.c2
-rw-r--r--drivers/iio/dac/ti-dac5571.c2
-rw-r--r--drivers/iio/gyro/bmg160_i2c.c2
-rw-r--r--drivers/iio/gyro/fxas21002c_i2c.c2
-rw-r--r--drivers/iio/gyro/itg3200_core.c2
-rw-r--r--drivers/iio/gyro/mpu3050-i2c.c2
-rw-r--r--drivers/iio/gyro/st_gyro_i2c.c2
-rw-r--r--drivers/iio/health/afe4404.c2
-rw-r--r--drivers/iio/health/max30100.c2
-rw-r--r--drivers/iio/health/max30102.c2
-rw-r--r--drivers/iio/humidity/am2315.c2
-rw-r--r--drivers/iio/humidity/hdc100x.c2
-rw-r--r--drivers/iio/humidity/hdc2010.c2
-rw-r--r--drivers/iio/humidity/hts221_i2c.c2
-rw-r--r--drivers/iio/humidity/htu21.c2
-rw-r--r--drivers/iio/humidity/si7005.c2
-rw-r--r--drivers/iio/humidity/si7020.c2
-rw-r--r--drivers/iio/imu/bmi160/bmi160_i2c.c2
-rw-r--r--drivers/iio/imu/bno055/bno055_i2c.c2
-rw-r--r--drivers/iio/imu/fxos8700_i2c.c2
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c2
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c49
-rw-r--r--drivers/iio/imu/inv_mpu6050/Kconfig4
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c10
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c8
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h2
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c5
-rw-r--r--drivers/iio/imu/kmx61.c2
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c2
-rw-r--r--drivers/iio/imu/st_lsm9ds0/Kconfig3
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c14
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c5
-rw-r--r--drivers/iio/industrialio-buffer.c98
-rw-r--r--drivers/iio/industrialio-trigger.c22
-rw-r--r--drivers/iio/light/Kconfig25
-rw-r--r--drivers/iio/light/Makefile2
-rw-r--r--drivers/iio/light/adjd_s311.c2
-rw-r--r--drivers/iio/light/adux1020.c2
-rw-r--r--drivers/iio/light/al3010.c2
-rw-r--r--drivers/iio/light/al3320a.c10
-rw-r--r--drivers/iio/light/apds9300.c2
-rw-r--r--drivers/iio/light/apds9960.c2
-rw-r--r--drivers/iio/light/as73211.c2
-rw-r--r--drivers/iio/light/bh1750.c2
-rw-r--r--drivers/iio/light/bh1780.c2
-rw-r--r--drivers/iio/light/cm32181.c2
-rw-r--r--drivers/iio/light/cm3232.c2
-rw-r--r--drivers/iio/light/cm3323.c2
-rw-r--r--drivers/iio/light/cm36651.c2
-rw-r--r--drivers/iio/light/gp2ap002.c2
-rw-r--r--drivers/iio/light/gp2ap020a00f.c2
-rw-r--r--drivers/iio/light/isl29018.c2
-rw-r--r--drivers/iio/light/isl29028.c2
-rw-r--r--drivers/iio/light/isl29125.c2
-rw-r--r--drivers/iio/light/jsa1212.c2
-rw-r--r--drivers/iio/light/ltr501.c2
-rw-r--r--drivers/iio/light/ltrf216a.c2
-rw-r--r--drivers/iio/light/lv0104cs.c2
-rw-r--r--drivers/iio/light/max44000.c2
-rw-r--r--drivers/iio/light/max44009.c2
-rw-r--r--drivers/iio/light/noa1305.c2
-rw-r--r--drivers/iio/light/opt3001.c2
-rw-r--r--drivers/iio/light/opt4001.c467
-rw-r--r--drivers/iio/light/pa12203001.c2
-rw-r--r--drivers/iio/light/rohm-bu27008.c1026
-rw-r--r--drivers/iio/light/rohm-bu27034.c3
-rw-r--r--drivers/iio/light/rpr0521.c2
-rw-r--r--drivers/iio/light/si1133.c2
-rw-r--r--drivers/iio/light/si1145.c2
-rw-r--r--drivers/iio/light/st_uvis25_i2c.c2
-rw-r--r--drivers/iio/light/stk3310.c2
-rw-r--r--drivers/iio/light/tcs3414.c2
-rw-r--r--drivers/iio/light/tcs3472.c2
-rw-r--r--drivers/iio/light/tsl2563.c2
-rw-r--r--drivers/iio/light/tsl2583.c2
-rw-r--r--drivers/iio/light/tsl2591.c2
-rw-r--r--drivers/iio/light/tsl2772.c2
-rw-r--r--drivers/iio/light/tsl4531.c2
-rw-r--r--drivers/iio/light/us5182d.c2
-rw-r--r--drivers/iio/light/vcnl4000.c2
-rw-r--r--drivers/iio/light/vcnl4035.c2
-rw-r--r--drivers/iio/light/veml6030.c2
-rw-r--r--drivers/iio/light/veml6070.c2
-rw-r--r--drivers/iio/light/vl6180.c2
-rw-r--r--drivers/iio/light/zopt2201.c2
-rw-r--r--drivers/iio/magnetometer/ak8974.c2
-rw-r--r--drivers/iio/magnetometer/ak8975.c2
-rw-r--r--drivers/iio/magnetometer/bmc150_magn_i2c.c2
-rw-r--r--drivers/iio/magnetometer/hmc5843_i2c.c2
-rw-r--r--drivers/iio/magnetometer/mag3110.c2
-rw-r--r--drivers/iio/magnetometer/mmc35240.c2
-rw-r--r--drivers/iio/magnetometer/rm3100-i2c.c2
-rw-r--r--drivers/iio/magnetometer/st_magn_core.c1
-rw-r--r--drivers/iio/magnetometer/st_magn_i2c.c2
-rw-r--r--drivers/iio/magnetometer/tmag5273.c2
-rw-r--r--drivers/iio/magnetometer/yamaha-yas530.c2
-rw-r--r--drivers/iio/potentiometer/Kconfig10
-rw-r--r--drivers/iio/potentiometer/Makefile1
-rw-r--r--drivers/iio/potentiometer/ad5110.c2
-rw-r--r--drivers/iio/potentiometer/ad5272.c2
-rw-r--r--drivers/iio/potentiometer/ds1803.c2
-rw-r--r--drivers/iio/potentiometer/max5432.c2
-rw-r--r--drivers/iio/potentiometer/mcp4018.c2
-rw-r--r--drivers/iio/potentiometer/mcp4531.c2
-rw-r--r--drivers/iio/potentiometer/tpl0102.c2
-rw-r--r--drivers/iio/potentiometer/x9250.c220
-rw-r--r--drivers/iio/potentiostat/lmp91000.c2
-rw-r--r--drivers/iio/pressure/Kconfig13
-rw-r--r--drivers/iio/pressure/Makefile1
-rw-r--r--drivers/iio/pressure/abp060mg.c2
-rw-r--r--drivers/iio/pressure/bmp280-i2c.c2
-rw-r--r--drivers/iio/pressure/dlhl60d.c2
-rw-r--r--drivers/iio/pressure/dps310.c2
-rw-r--r--drivers/iio/pressure/hp03.c2
-rw-r--r--drivers/iio/pressure/hp206c.c2
-rw-r--r--drivers/iio/pressure/icp10100.c2
-rw-r--r--drivers/iio/pressure/mpl115_i2c.c2
-rw-r--r--drivers/iio/pressure/mpl3115.c2
-rw-r--r--drivers/iio/pressure/mprls0025pa.c450
-rw-r--r--drivers/iio/pressure/ms5611_i2c.c2
-rw-r--r--drivers/iio/pressure/ms5637.c2
-rw-r--r--drivers/iio/pressure/st_pressure_i2c.c2
-rw-r--r--drivers/iio/pressure/t5403.c2
-rw-r--r--drivers/iio/pressure/zpa2326_i2c.c2
-rw-r--r--drivers/iio/proximity/isl29501.c2
-rw-r--r--drivers/iio/proximity/mb1232.c2
-rw-r--r--drivers/iio/proximity/pulsedlight-lidar-lite-v2.c2
-rw-r--r--drivers/iio/proximity/rfd77402.c2
-rw-r--r--drivers/iio/proximity/srf08.c2
-rw-r--r--drivers/iio/proximity/sx9310.c2
-rw-r--r--drivers/iio/proximity/sx9324.c2
-rw-r--r--drivers/iio/proximity/sx9360.c2
-rw-r--r--drivers/iio/proximity/sx9500.c2
-rw-r--r--drivers/iio/proximity/vcnl3020.c2
-rw-r--r--drivers/iio/proximity/vl53l0x-i2c.c2
-rw-r--r--drivers/iio/temperature/max30208.c2
-rw-r--r--drivers/iio/temperature/mlx90614.c239
-rw-r--r--drivers/iio/temperature/mlx90632.c2
-rw-r--r--drivers/iio/temperature/tmp006.c10
-rw-r--r--drivers/iio/temperature/tmp007.c2
-rw-r--r--drivers/iio/temperature/tmp117.c2
-rw-r--r--drivers/iio/temperature/tsys01.c2
-rw-r--r--drivers/iio/temperature/tsys02d.c2
-rw-r--r--drivers/infiniband/core/cma.c3
-rw-r--r--drivers/infiniband/hw/bnxt_re/bnxt_re.h5
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.c292
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.h19
-rw-r--r--drivers/infiniband/hw/bnxt_re/main.c192
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_fp.c104
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_fp.h2
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.c664
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.h52
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.c177
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.h34
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_sp.c19
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_sp.h5
-rw-r--r--drivers/infiniband/hw/erdma/erdma.h16
-rw-r--r--drivers/infiniband/hw/erdma/erdma_hw.h64
-rw-r--r--drivers/infiniband/hw/erdma/erdma_main.c53
-rw-r--r--drivers/infiniband/hw/erdma/erdma_verbs.c178
-rw-r--r--drivers/infiniband/hw/erdma/erdma_verbs.h13
-rw-r--r--drivers/infiniband/hw/hfi1/ipoib_tx.c4
-rw-r--r--drivers/infiniband/hw/hfi1/mmu_rb.c108
-rw-r--r--drivers/infiniband/hw/hfi1/mmu_rb.h10
-rw-r--r--drivers/infiniband/hw/hfi1/sdma.c23
-rw-r--r--drivers/infiniband/hw/hfi1/sdma.h47
-rw-r--r--drivers/infiniband/hw/hfi1/sdma_txreq.h2
-rw-r--r--drivers/infiniband/hw/hfi1/trace_mmu.h48
-rw-r--r--drivers/infiniband/hw/hfi1/user_sdma.c137
-rw-r--r--drivers/infiniband/hw/hfi1/user_sdma.h1
-rw-r--r--drivers/infiniband/hw/hfi1/vnic_sdma.c4
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hem.c51
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v2.c24
-rw-r--r--drivers/infiniband/hw/irdma/uk.c10
-rw-r--r--drivers/infiniband/hw/irdma/verbs.c41
-rw-r--r--drivers/infiniband/hw/mana/qp.c5
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h1
-rw-r--r--drivers/infiniband/hw/mlx5/qp.h12
-rw-r--r--drivers/infiniband/hw/mlx5/qpc.c93
-rw-r--r--drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c8
-rw-r--r--drivers/infiniband/sw/rxe/rxe.c9
-rw-r--r--drivers/infiniband/sw/rxe/rxe_comp.c2
-rw-r--r--drivers/infiniband/sw/rxe/rxe_cq.c5
-rw-r--r--drivers/infiniband/sw/rxe/rxe_loc.h2
-rw-r--r--drivers/infiniband/sw/rxe/rxe_mr.c21
-rw-r--r--drivers/infiniband/sw/rxe/rxe_mw.c22
-rw-r--r--drivers/infiniband/sw/rxe/rxe_opcode.h3
-rw-r--r--drivers/infiniband/sw/rxe/rxe_param.h2
-rw-r--r--drivers/infiniband/sw/rxe/rxe_qp.c7
-rw-r--r--drivers/infiniband/sw/rxe/rxe_req.c2
-rw-r--r--drivers/infiniband/sw/rxe/rxe_resp.c25
-rw-r--r--drivers/infiniband/sw/rxe/rxe_task.c110
-rw-r--r--drivers/infiniband/sw/rxe/rxe_task.h6
-rw-r--r--drivers/infiniband/sw/rxe/rxe_verbs.c45
-rw-r--r--drivers/infiniband/sw/rxe/rxe_verbs.h21
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt.c1
-rw-r--r--drivers/input/Kconfig2
-rw-r--r--drivers/input/gameport/gameport.c18
-rw-r--r--drivers/input/input.c6
-rw-r--r--drivers/input/joystick/Kconfig14
-rw-r--r--drivers/input/joystick/as5011.c2
-rw-r--r--drivers/input/joystick/qwiic-joystick.c2
-rw-r--r--drivers/input/joystick/xpad.c64
-rw-r--r--drivers/input/keyboard/adp5588-keys.c2
-rw-r--r--drivers/input/keyboard/adp5589-keys.c2
-rw-r--r--drivers/input/keyboard/atkbd.c102
-rw-r--r--drivers/input/keyboard/cap11xx.c2
-rw-r--r--drivers/input/keyboard/cypress-sf.c2
-rw-r--r--drivers/input/keyboard/dlink-dir685-touchkeys.c2
-rw-r--r--drivers/input/keyboard/gpio_keys.c6
-rw-r--r--drivers/input/keyboard/lm8323.c2
-rw-r--r--drivers/input/keyboard/lm8333.c2
-rw-r--r--drivers/input/keyboard/max7359_keypad.c2
-rw-r--r--drivers/input/keyboard/mcs_touchkey.c2
-rw-r--r--drivers/input/keyboard/mpr121_touchkey.c2
-rw-r--r--drivers/input/keyboard/pinephone-keyboard.c2
-rw-r--r--drivers/input/keyboard/qt1050.c2
-rw-r--r--drivers/input/keyboard/qt1070.c2
-rw-r--r--drivers/input/keyboard/qt2160.c2
-rw-r--r--drivers/input/keyboard/tca6416-keypad.c2
-rw-r--r--drivers/input/keyboard/tca8418_keypad.c2
-rw-r--r--drivers/input/keyboard/tm2-touchkey.c2
-rw-r--r--drivers/input/misc/ad714x-i2c.c2
-rw-r--r--drivers/input/misc/adxl34x-i2c.c2
-rw-r--r--drivers/input/misc/adxl34x.c3
-rw-r--r--drivers/input/misc/apanel.c2
-rw-r--r--drivers/input/misc/atmel_captouch.c2
-rw-r--r--drivers/input/misc/bma150.c2
-rw-r--r--drivers/input/misc/cma3000_d0x_i2c.c2
-rw-r--r--drivers/input/misc/da7280.c2
-rw-r--r--drivers/input/misc/drv260x.c58
-rw-r--r--drivers/input/misc/drv2665.c2
-rw-r--r--drivers/input/misc/drv2667.c2
-rw-r--r--drivers/input/misc/ibm-panel.c2
-rw-r--r--drivers/input/misc/iqs269a.c2
-rw-r--r--drivers/input/misc/iqs626a.c2
-rw-r--r--drivers/input/misc/iqs7222.c2
-rw-r--r--drivers/input/misc/kxtj9.c2
-rw-r--r--drivers/input/misc/mma8450.c2
-rw-r--r--drivers/input/misc/pcf8574_keypad.c2
-rw-r--r--drivers/input/misc/pm8941-pwrkey.c19
-rw-r--r--drivers/input/misc/pwm-vibra.c36
-rw-r--r--drivers/input/misc/tps65219-pwrbutton.c12
-rw-r--r--drivers/input/misc/uinput.c34
-rw-r--r--drivers/input/mouse/cyapa.c2
-rw-r--r--drivers/input/mouse/elan_i2c_core.c2
-rw-r--r--drivers/input/mouse/psmouse-base.c86
-rw-r--r--drivers/input/mouse/psmouse.h2
-rw-r--r--drivers/input/mouse/synaptics.c10
-rw-r--r--drivers/input/mouse/synaptics_i2c.c2
-rw-r--r--drivers/input/mouse/trackpoint.c2
-rw-r--r--drivers/input/rmi4/rmi_i2c.c2
-rw-r--r--drivers/input/rmi4/rmi_smbus.c2
-rw-r--r--drivers/input/serio/Kconfig1
-rw-r--r--drivers/input/serio/libps2.c293
-rw-r--r--drivers/input/tests/input_test.c38
-rw-r--r--drivers/input/touchscreen/Kconfig1
-rw-r--r--drivers/input/touchscreen/ad7879-i2c.c2
-rw-r--r--drivers/input/touchscreen/ads7846.c114
-rw-r--r--drivers/input/touchscreen/ar1021_i2c.c2
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c87
-rw-r--r--drivers/input/touchscreen/auo-pixcir-ts.c2
-rw-r--r--drivers/input/touchscreen/bu21013_ts.c2
-rw-r--r--drivers/input/touchscreen/bu21029_ts.c2
-rw-r--r--drivers/input/touchscreen/chipone_icn8318.c2
-rw-r--r--drivers/input/touchscreen/chipone_icn8505.c2
-rw-r--r--drivers/input/touchscreen/cy8ctma140.c2
-rw-r--r--drivers/input/touchscreen/cy8ctmg110_ts.c2
-rw-r--r--drivers/input/touchscreen/cyttsp4_core.c3
-rw-r--r--drivers/input/touchscreen/cyttsp4_i2c.c2
-rw-r--r--drivers/input/touchscreen/cyttsp5.c84
-rw-r--r--drivers/input/touchscreen/cyttsp_i2c.c2
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c3
-rw-r--r--drivers/input/touchscreen/eeti_ts.c2
-rw-r--r--drivers/input/touchscreen/egalax_ts.c2
-rw-r--r--drivers/input/touchscreen/ektf2127.c2
-rw-r--r--drivers/input/touchscreen/elants_i2c.c2
-rw-r--r--drivers/input/touchscreen/exc3000.c2
-rw-r--r--drivers/input/touchscreen/goodix.c2
-rw-r--r--drivers/input/touchscreen/hideep.c2
-rw-r--r--drivers/input/touchscreen/himax_hx83112b.c2
-rw-r--r--drivers/input/touchscreen/hycon-hy46xx.c2
-rw-r--r--drivers/input/touchscreen/hynitron_cstxxx.c2
-rw-r--r--drivers/input/touchscreen/ili210x.c38
-rw-r--r--drivers/input/touchscreen/ilitek_ts_i2c.c2
-rw-r--r--drivers/input/touchscreen/imagis.c2
-rw-r--r--drivers/input/touchscreen/iqs5xx.c2
-rw-r--r--drivers/input/touchscreen/max11801_ts.c2
-rw-r--r--drivers/input/touchscreen/mcs5000_ts.c2
-rw-r--r--drivers/input/touchscreen/melfas_mip4.c2
-rw-r--r--drivers/input/touchscreen/migor_ts.c2
-rw-r--r--drivers/input/touchscreen/mms114.c2
-rw-r--r--drivers/input/touchscreen/msg2638.c2
-rw-r--r--drivers/input/touchscreen/novatek-nvt-ts.c2
-rw-r--r--drivers/input/touchscreen/pixcir_i2c_ts.c2
-rw-r--r--drivers/input/touchscreen/raydium_i2c_ts.c2
-rw-r--r--drivers/input/touchscreen/rohm_bu21023.c2
-rw-r--r--drivers/input/touchscreen/s6sy761.c2
-rw-r--r--drivers/input/touchscreen/silead.c2
-rw-r--r--drivers/input/touchscreen/sis_i2c.c2
-rw-r--r--drivers/input/touchscreen/st1232.c2
-rw-r--r--drivers/input/touchscreen/stmfts.c2
-rw-r--r--drivers/input/touchscreen/sx8654.c2
-rw-r--r--drivers/input/touchscreen/tsc2004.c2
-rw-r--r--drivers/input/touchscreen/tsc2007_core.c2
-rw-r--r--drivers/input/touchscreen/wacom_i2c.c2
-rw-r--r--drivers/input/touchscreen/wdt87xx_i2c.c2
-rw-r--r--drivers/input/touchscreen/zet6223.c2
-rw-r--r--drivers/input/touchscreen/zforce_ts.c2
-rw-r--r--drivers/input/touchscreen/zinitix.c2
-rw-r--r--drivers/interconnect/Kconfig6
-rw-r--r--drivers/interconnect/Makefile2
-rw-r--r--drivers/interconnect/core.c52
-rw-r--r--drivers/interconnect/icc-clk.c174
-rw-r--r--drivers/interconnect/qcom/icc-rpm.c112
-rw-r--r--drivers/interconnect/qcom/icc-rpm.h22
-rw-r--r--drivers/interconnect/qcom/msm8996.c35
-rw-r--r--drivers/interconnect/qcom/sdm660.c17
-rw-r--r--drivers/iommu/amd/amd_iommu.h91
-rw-r--r--drivers/iommu/amd/amd_iommu_types.h87
-rw-r--r--drivers/iommu/amd/init.c38
-rw-r--r--drivers/iommu/amd/io_pgtable.c4
-rw-r--r--drivers/iommu/amd/io_pgtable_v2.c2
-rw-r--r--drivers/iommu/amd/iommu.c99
-rw-r--r--drivers/iommu/amd/iommu_v2.c4
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c61
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h8
-rw-r--r--drivers/iommu/arm/arm-smmu/arm-smmu.c4
-rw-r--r--drivers/iommu/dma-iommu.c3
-rw-r--r--drivers/iommu/fsl_pamu_domain.c113
-rw-r--r--drivers/iommu/intel/iommu.c29
-rw-r--r--drivers/iommu/iommu-sva.c2
-rw-r--r--drivers/iommu/iommu.c694
-rw-r--r--drivers/iommu/iommufd/device.c2
-rw-r--r--drivers/iommu/iommufd/io_pagetable.c14
-rw-r--r--drivers/iommu/iova.c8
-rw-r--r--drivers/iommu/virtio-iommu.c57
-rw-r--r--drivers/irqchip/irq-riscv-intc.c70
-rw-r--r--drivers/isdn/Kconfig1
-rw-r--r--drivers/isdn/hardware/mISDN/Kconfig12
-rw-r--r--drivers/leds/Kconfig37
-rw-r--r--drivers/leds/Makefile2
-rw-r--r--drivers/leds/flash/leds-aat1290.c2
-rw-r--r--drivers/leds/flash/leds-as3645a.c6
-rw-r--r--drivers/leds/flash/leds-lm3601x.c2
-rw-r--r--drivers/leds/flash/leds-qcom-flash.c17
-rw-r--r--drivers/leds/flash/leds-rt4505.c2
-rw-r--r--drivers/leds/flash/leds-sgm3140.c1
-rw-r--r--drivers/leds/led-class.c2
-rw-r--r--drivers/leds/led-core.c81
-rw-r--r--drivers/leds/led-triggers.c17
-rw-r--r--drivers/leds/leds-an30259a.c2
-rw-r--r--drivers/leds/leds-aw200xx.c594
-rw-r--r--drivers/leds/leds-aw2013.c2
-rw-r--r--drivers/leds/leds-bd2606mvv.c2
-rw-r--r--drivers/leds/leds-bd2802.c2
-rw-r--r--drivers/leds/leds-blinkm.c4
-rw-r--r--drivers/leds/leds-cht-wcove.c476
-rw-r--r--drivers/leds/leds-gpio.c18
-rw-r--r--drivers/leds/leds-is31fl319x.c2
-rw-r--r--drivers/leds/leds-is31fl32xx.c2
-rw-r--r--drivers/leds/leds-lm3530.c2
-rw-r--r--drivers/leds/leds-lm3532.c2
-rw-r--r--drivers/leds/leds-lm355x.c2
-rw-r--r--drivers/leds/leds-lm3642.c2
-rw-r--r--drivers/leds/leds-lm3692x.c2
-rw-r--r--drivers/leds/leds-lm3697.c2
-rw-r--r--drivers/leds/leds-lp3944.c2
-rw-r--r--drivers/leds/leds-lp3952.c2
-rw-r--r--drivers/leds/leds-lp50xx.c2
-rw-r--r--drivers/leds/leds-lp5521.c13
-rw-r--r--drivers/leds/leds-lp5523.c16
-rw-r--r--drivers/leds/leds-lp5562.c2
-rw-r--r--drivers/leds/leds-lp55xx-common.c9
-rw-r--r--drivers/leds/leds-lp8501.c10
-rw-r--r--drivers/leds/leds-lp8860.c2
-rw-r--r--drivers/leds/leds-mt6323.c446
-rw-r--r--drivers/leds/leds-pca9532.c2
-rw-r--r--drivers/leds/leds-pca955x.c2
-rw-r--r--drivers/leds/leds-pca963x.c2
-rw-r--r--drivers/leds/leds-spi-byte.c2
-rw-r--r--drivers/leds/leds-tca6507.c2
-rw-r--r--drivers/leds/leds-tlc591xx.c2
-rw-r--r--drivers/leds/leds-turris-omnia.c2
-rw-r--r--drivers/leds/rgb/leds-qcom-lpg.c23
-rw-r--r--drivers/leds/simple/Kconfig31
-rw-r--r--drivers/leds/simple/Makefile5
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c66
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio-core.c104
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c66
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio.c139
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio.h22
-rw-r--r--drivers/leds/simple/simatic-ipc-leds.c1
-rw-r--r--drivers/leds/trigger/ledtrig-disk.c9
-rw-r--r--drivers/leds/trigger/ledtrig-mtd.c8
-rw-r--r--drivers/leds/trigger/ledtrig-netdev.c6
-rw-r--r--drivers/macintosh/ams/ams-i2c.c2
-rw-r--r--drivers/macintosh/smu.c15
-rw-r--r--drivers/macintosh/therm_adt746x.c2
-rw-r--r--drivers/macintosh/therm_windtunnel.c2
-rw-r--r--drivers/macintosh/via-cuda.c16
-rw-r--r--drivers/macintosh/via-pmu.c23
-rw-r--r--drivers/macintosh/windfarm_ad7417_sensor.c2
-rw-r--r--drivers/macintosh/windfarm_fcu_controls.c2
-rw-r--r--drivers/macintosh/windfarm_lm75_sensor.c2
-rw-r--r--drivers/macintosh/windfarm_lm87_sensor.c2
-rw-r--r--drivers/macintosh/windfarm_max6690_sensor.c2
-rw-r--r--drivers/macintosh/windfarm_smu_sat.c2
-rw-r--r--drivers/mailbox/tegra-hsp.c16
-rw-r--r--drivers/mailbox/ti-msgmgr.c12
-rw-r--r--drivers/md/bcache/super.c123
-rw-r--r--drivers/md/dm-bufio.c24
-rw-r--r--drivers/md/dm-core.h3
-rw-r--r--drivers/md/dm-crypt.c66
-rw-r--r--drivers/md/dm-flakey.c210
-rw-r--r--drivers/md/dm-integrity.c85
-rw-r--r--drivers/md/dm-ioctl.c98
-rw-r--r--drivers/md/dm-thin-metadata.c58
-rw-r--r--drivers/md/dm-thin.c41
-rw-r--r--drivers/md/dm-zone.c15
-rw-r--r--drivers/md/dm.c127
-rw-r--r--drivers/md/dm.h3
-rw-r--r--drivers/md/md.c32
-rw-r--r--drivers/md/md.h4
-rw-r--r--drivers/md/persistent-data/dm-block-manager.c6
-rw-r--r--drivers/md/persistent-data/dm-block-manager.h1
-rw-r--r--drivers/md/persistent-data/dm-space-map.h3
-rw-r--r--drivers/md/persistent-data/dm-transaction-manager.c3
-rw-r--r--drivers/md/raid0.c62
-rw-r--r--drivers/md/raid0.h1
-rw-r--r--drivers/md/raid1-10.c2
-rw-r--r--drivers/md/raid10.c6
-rw-r--r--drivers/media/cec/i2c/Kconfig1
-rw-r--r--drivers/media/cec/i2c/ch7322.c2
-rw-r--r--drivers/media/common/saa7146/saa7146_core.c6
-rw-r--r--drivers/media/dvb-core/dvbdev.c161
-rw-r--r--drivers/media/dvb-frontends/a8293.c2
-rw-r--r--drivers/media/dvb-frontends/af9013.c2
-rw-r--r--drivers/media/dvb-frontends/af9033.c2
-rw-r--r--drivers/media/dvb-frontends/au8522_decoder.c2
-rw-r--r--drivers/media/dvb-frontends/cxd2099.c2
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_core.c2
-rw-r--r--drivers/media/dvb-frontends/dvb-pll.c2
-rw-r--r--drivers/media/dvb-frontends/helene.c2
-rw-r--r--drivers/media/dvb-frontends/lgdt3306a.c2
-rw-r--r--drivers/media/dvb-frontends/lgdt330x.c2
-rw-r--r--drivers/media/dvb-frontends/m88ds3103.c2
-rw-r--r--drivers/media/dvb-frontends/mb86a20s.c5
-rw-r--r--drivers/media/dvb-frontends/mn88443x.c2
-rw-r--r--drivers/media/dvb-frontends/mn88472.c2
-rw-r--r--drivers/media/dvb-frontends/mn88473.c2
-rw-r--r--drivers/media/dvb-frontends/mxl692.c2
-rw-r--r--drivers/media/dvb-frontends/rtl2830.c2
-rw-r--r--drivers/media/dvb-frontends/rtl2832.c2
-rw-r--r--drivers/media/dvb-frontends/si2165.c2
-rw-r--r--drivers/media/dvb-frontends/si2168.c2
-rw-r--r--drivers/media/dvb-frontends/sp2.c2
-rw-r--r--drivers/media/dvb-frontends/stv090x.c2
-rw-r--r--drivers/media/dvb-frontends/stv6110x.c2
-rw-r--r--drivers/media/dvb-frontends/tc90522.c2
-rw-r--r--drivers/media/dvb-frontends/tda10071.c2
-rw-r--r--drivers/media/dvb-frontends/ts2020.c2
-rw-r--r--drivers/media/i2c/Kconfig14
-rw-r--r--drivers/media/i2c/Makefile1
-rw-r--r--drivers/media/i2c/ad5820.c2
-rw-r--r--drivers/media/i2c/adp1653.c2
-rw-r--r--drivers/media/i2c/adv7170.c2
-rw-r--r--drivers/media/i2c/adv7175.c2
-rw-r--r--drivers/media/i2c/adv7180.c2
-rw-r--r--drivers/media/i2c/adv7183.c2
-rw-r--r--drivers/media/i2c/adv7343.c2
-rw-r--r--drivers/media/i2c/adv7393.c2
-rw-r--r--drivers/media/i2c/adv748x/adv748x-core.c2
-rw-r--r--drivers/media/i2c/adv7511-v4l2.c2
-rw-r--r--drivers/media/i2c/adv7604.c2
-rw-r--r--drivers/media/i2c/adv7842.c2
-rw-r--r--drivers/media/i2c/ak7375.c2
-rw-r--r--drivers/media/i2c/ak881x.c2
-rw-r--r--drivers/media/i2c/ar0521.c2
-rw-r--r--drivers/media/i2c/bt819.c2
-rw-r--r--drivers/media/i2c/bt856.c2
-rw-r--r--drivers/media/i2c/bt866.c2
-rw-r--r--drivers/media/i2c/ccs/ccs-core.c2
-rw-r--r--drivers/media/i2c/cs3308.c2
-rw-r--r--drivers/media/i2c/cs5345.c2
-rw-r--r--drivers/media/i2c/cs53l32a.c2
-rw-r--r--drivers/media/i2c/cx25840/cx25840-core.c2
-rw-r--r--drivers/media/i2c/dw9714.c2
-rw-r--r--drivers/media/i2c/dw9768.c2
-rw-r--r--drivers/media/i2c/dw9807-vcm.c2
-rw-r--r--drivers/media/i2c/et8ek8/et8ek8_driver.c2
-rw-r--r--drivers/media/i2c/hi556.c2
-rw-r--r--drivers/media/i2c/hi846.c5
-rw-r--r--drivers/media/i2c/hi847.c2
-rw-r--r--drivers/media/i2c/imx208.c2
-rw-r--r--drivers/media/i2c/imx214.c2
-rw-r--r--drivers/media/i2c/imx219.c2
-rw-r--r--drivers/media/i2c/imx258.c2
-rw-r--r--drivers/media/i2c/imx274.c2
-rw-r--r--drivers/media/i2c/imx290.c4
-rw-r--r--drivers/media/i2c/imx296.c6
-rw-r--r--drivers/media/i2c/imx319.c2
-rw-r--r--drivers/media/i2c/imx334.c64
-rw-r--r--drivers/media/i2c/imx335.c2
-rw-r--r--drivers/media/i2c/imx355.c2
-rw-r--r--drivers/media/i2c/imx412.c2
-rw-r--r--drivers/media/i2c/imx415.c2
-rw-r--r--drivers/media/i2c/ir-kbd-i2c.c2
-rw-r--r--drivers/media/i2c/isl7998x.c2
-rw-r--r--drivers/media/i2c/ks0127.c2
-rw-r--r--drivers/media/i2c/lm3560.c2
-rw-r--r--drivers/media/i2c/lm3646.c2
-rw-r--r--drivers/media/i2c/m52790.c2
-rw-r--r--drivers/media/i2c/max2175.c2
-rw-r--r--drivers/media/i2c/max9286.c2
-rw-r--r--drivers/media/i2c/ml86v7667.c2
-rw-r--r--drivers/media/i2c/msp3400-driver.c2
-rw-r--r--drivers/media/i2c/mt9m001.c2
-rw-r--r--drivers/media/i2c/mt9m111.c2
-rw-r--r--drivers/media/i2c/mt9p031.c2
-rw-r--r--drivers/media/i2c/mt9t112.c2
-rw-r--r--drivers/media/i2c/mt9v011.c2
-rw-r--r--drivers/media/i2c/mt9v032.c2
-rw-r--r--drivers/media/i2c/mt9v111.c2
-rw-r--r--drivers/media/i2c/og01a1b.c2
-rw-r--r--drivers/media/i2c/ov01a10.c1004
-rw-r--r--drivers/media/i2c/ov02a10.c4
-rw-r--r--drivers/media/i2c/ov08d10.c2
-rw-r--r--drivers/media/i2c/ov08x40.c2
-rw-r--r--drivers/media/i2c/ov13858.c2
-rw-r--r--drivers/media/i2c/ov13b10.c2
-rw-r--r--drivers/media/i2c/ov2640.c2
-rw-r--r--drivers/media/i2c/ov2659.c2
-rw-r--r--drivers/media/i2c/ov2680.c2
-rw-r--r--drivers/media/i2c/ov2685.c4
-rw-r--r--drivers/media/i2c/ov2740.c2
-rw-r--r--drivers/media/i2c/ov4689.c2
-rw-r--r--drivers/media/i2c/ov5640.c21
-rw-r--r--drivers/media/i2c/ov5645.c2
-rw-r--r--drivers/media/i2c/ov5647.c2
-rw-r--r--drivers/media/i2c/ov5648.c4
-rw-r--r--drivers/media/i2c/ov5670.c2
-rw-r--r--drivers/media/i2c/ov5675.c2
-rw-r--r--drivers/media/i2c/ov5693.c6
-rw-r--r--drivers/media/i2c/ov5695.c4
-rw-r--r--drivers/media/i2c/ov6650.c2
-rw-r--r--drivers/media/i2c/ov7251.c2
-rw-r--r--drivers/media/i2c/ov7640.c2
-rw-r--r--drivers/media/i2c/ov7670.c2
-rw-r--r--drivers/media/i2c/ov772x.c2
-rw-r--r--drivers/media/i2c/ov7740.c2
-rw-r--r--drivers/media/i2c/ov8856.c2
-rw-r--r--drivers/media/i2c/ov8858.c4
-rw-r--r--drivers/media/i2c/ov8865.c4
-rw-r--r--drivers/media/i2c/ov9282.c2
-rw-r--r--drivers/media/i2c/ov9640.c2
-rw-r--r--drivers/media/i2c/ov9650.c2
-rw-r--r--drivers/media/i2c/ov9734.c2
-rw-r--r--drivers/media/i2c/rdacm20.c2
-rw-r--r--drivers/media/i2c/rdacm21.c2
-rw-r--r--drivers/media/i2c/rj54n1cb0c.c2
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-core.c2
-rw-r--r--drivers/media/i2c/s5k5baf.c2
-rw-r--r--drivers/media/i2c/s5k6a3.c2
-rw-r--r--drivers/media/i2c/saa6588.c2
-rw-r--r--drivers/media/i2c/saa6752hs.c2
-rw-r--r--drivers/media/i2c/saa7110.c2
-rw-r--r--drivers/media/i2c/saa7115.c2
-rw-r--r--drivers/media/i2c/saa7127.c2
-rw-r--r--drivers/media/i2c/saa717x.c2
-rw-r--r--drivers/media/i2c/saa7185.c2
-rw-r--r--drivers/media/i2c/sony-btf-mpx.c2
-rw-r--r--drivers/media/i2c/st-mipid02.c17
-rw-r--r--drivers/media/i2c/st-vgxy61.c2
-rw-r--r--drivers/media/i2c/tc358743.c2
-rw-r--r--drivers/media/i2c/tc358746.c2
-rw-r--r--drivers/media/i2c/tda1997x.c2
-rw-r--r--drivers/media/i2c/tda7432.c2
-rw-r--r--drivers/media/i2c/tda9840.c2
-rw-r--r--drivers/media/i2c/tea6415c.c2
-rw-r--r--drivers/media/i2c/tea6420.c2
-rw-r--r--drivers/media/i2c/ths7303.c2
-rw-r--r--drivers/media/i2c/ths8200.c2
-rw-r--r--drivers/media/i2c/tlv320aic23b.c2
-rw-r--r--drivers/media/i2c/tvaudio.c2
-rw-r--r--drivers/media/i2c/tvp514x.c2
-rw-r--r--drivers/media/i2c/tvp5150.c2
-rw-r--r--drivers/media/i2c/tvp7002.c2
-rw-r--r--drivers/media/i2c/tw2804.c2
-rw-r--r--drivers/media/i2c/tw9903.c2
-rw-r--r--drivers/media/i2c/tw9906.c2
-rw-r--r--drivers/media/i2c/tw9910.c2
-rw-r--r--drivers/media/i2c/uda1342.c2
-rw-r--r--drivers/media/i2c/upd64031a.c2
-rw-r--r--drivers/media/i2c/upd64083.c2
-rw-r--r--drivers/media/i2c/video-i2c.c4
-rw-r--r--drivers/media/i2c/vp27smpx.c2
-rw-r--r--drivers/media/i2c/vpx3220.c2
-rw-r--r--drivers/media/i2c/wm8739.c2
-rw-r--r--drivers/media/i2c/wm8775.c2
-rw-r--r--drivers/media/mc/mc-entity.c18
-rw-r--r--drivers/media/pci/bt8xx/dst_ca.c2
-rw-r--r--drivers/media/pci/cx18/cx18-av-vbi.c2
-rw-r--r--drivers/media/pci/cx18/cx18-dvb.c4
-rw-r--r--drivers/media/pci/dm1105/Kconfig2
-rw-r--r--drivers/media/pci/intel/ipu3/ipu3-cio2-main.c31
-rw-r--r--drivers/media/pci/ivtv/ivtvfb.c4
-rw-r--r--drivers/media/pci/saa7164/saa7164-dvb.c4
-rw-r--r--drivers/media/pci/ttpci/budget-core.c4
-rw-r--r--drivers/media/pci/tw686x/tw686x-audio.c2
-rw-r--r--drivers/media/platform/amphion/vdec.c7
-rw-r--r--drivers/media/platform/amphion/venc.c4
-rw-r--r--drivers/media/platform/amphion/vpu_malone.c12
-rw-r--r--drivers/media/platform/amphion/vpu_v4l2.c5
-rw-r--r--drivers/media/platform/amphion/vpu_v4l2.h2
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c828
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c17
-rw-r--r--drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c15
-rw-r--r--drivers/media/platform/mediatek/vcodec/Makefile8
-rw-r--r--drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c215
-rw-r--r--drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h74
-rw-r--r--drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c5
-rw-r--r--drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c26
-rw-r--r--drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c106
-rw-r--r--drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h8
-rw-r--r--drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c8
-rw-r--r--drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c2
-rw-r--r--drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c8
-rw-r--r--drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h26
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c2207
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c6
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c1097
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c4
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec_drv_if.c8
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec_drv_if.h2
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c132
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h32
-rw-r--r--drivers/media/platform/mediatek/vpu/mtk_vpu.c7
-rw-r--r--drivers/media/platform/nxp/imx7-media-csi.c94
-rw-r--r--drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c2
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe.c6
-rw-r--r--drivers/media/platform/qcom/venus/core.h39
-rw-r--r--drivers/media/platform/qcom/venus/helpers.c33
-rw-r--r--drivers/media/platform/qcom/venus/hfi_cmds.c19
-rw-r--r--drivers/media/platform/qcom/venus/hfi_cmds.h4
-rw-r--r--drivers/media/platform/qcom/venus/hfi_helper.h2
-rw-r--r--drivers/media/platform/qcom/venus/hfi_msgs.c34
-rw-r--r--drivers/media/platform/qcom/venus/hfi_msgs.h14
-rw-r--r--drivers/media/platform/qcom/venus/hfi_plat_bufs.h3
-rw-r--r--drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c11
-rw-r--r--drivers/media/platform/qcom/venus/hfi_venus.c28
-rw-r--r--drivers/media/platform/qcom/venus/vdec.c94
-rw-r--r--drivers/media/platform/qcom/venus/venc.c35
-rw-r--r--drivers/media/platform/renesas/rcar-isp.c1
-rw-r--r--drivers/media/platform/renesas/rcar-vin/rcar-core.c13
-rw-r--r--drivers/media/platform/renesas/rcar-vin/rcar-csi2.c100
-rw-r--r--drivers/media/platform/renesas/rcar_fdp1.c5
-rw-r--r--drivers/media/platform/renesas/rcar_jpu.c55
-rw-r--r--drivers/media/platform/renesas/renesas-ceu.c9
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c8
-rw-r--r--drivers/media/platform/rockchip/rga/rga.c9
-rw-r--r--drivers/media/platform/samsung/exynos4-is/Kconfig2
-rw-r--r--drivers/media/platform/samsung/exynos4-is/fimc-core.c2
-rw-r--r--drivers/media/platform/samsung/exynos4-is/fimc-lite.c2
-rw-r--r--drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h12
-rw-r--r--drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c37
-rw-r--r--drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h4
-rw-r--r--drivers/media/platform/st/sti/hva/hva-h264.c8
-rw-r--r--drivers/media/platform/verisilicon/Makefile3
-rw-r--r--drivers/media/platform/verisilicon/hantro.h8
-rw-r--r--drivers/media/platform/verisilicon/hantro_drv.c68
-rw-r--r--drivers/media/platform/verisilicon/hantro_hevc.c23
-rw-r--r--drivers/media/platform/verisilicon/hantro_hw.h102
-rw-r--r--drivers/media/platform/verisilicon/hantro_postproc.c9
-rw-r--r--drivers/media/platform/verisilicon/hantro_v4l2.c67
-rw-r--r--drivers/media/platform/verisilicon/hantro_v4l2.h8
-rw-r--r--drivers/media/platform/verisilicon/rockchip_av1_entropymode.c4424
-rw-r--r--drivers/media/platform/verisilicon/rockchip_av1_entropymode.h272
-rw-r--r--drivers/media/platform/verisilicon/rockchip_av1_filmgrain.c401
-rw-r--r--drivers/media/platform/verisilicon/rockchip_av1_filmgrain.h36
-rw-r--r--drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c2232
-rw-r--r--drivers/media/platform/verisilicon/rockchip_vpu981_regs.h477
-rw-r--r--drivers/media/platform/verisilicon/rockchip_vpu_hw.c134
-rw-r--r--drivers/media/platform/via/via-camera.c51
-rw-r--r--drivers/media/platform/video-mux.c102
-rw-r--r--drivers/media/radio/Kconfig14
-rw-r--r--drivers/media/radio/radio-tea5764.c2
-rw-r--r--drivers/media/radio/saa7706h.c2
-rw-r--r--drivers/media/radio/si470x/radio-si470x-i2c.c2
-rw-r--r--drivers/media/radio/si4713/si4713.c2
-rw-r--r--drivers/media/radio/tef6862.c2
-rw-r--r--drivers/media/radio/wl128x/fmdrv_common.c6
-rw-r--r--drivers/media/rc/Kconfig6
-rw-r--r--drivers/media/test-drivers/vidtv/vidtv_demod.c2
-rw-r--r--drivers/media/test-drivers/vidtv/vidtv_tuner.c2
-rw-r--r--drivers/media/test-drivers/vivid/vivid-vid-cap.c49
-rw-r--r--drivers/media/tuners/e4000.c2
-rw-r--r--drivers/media/tuners/fc2580.c2
-rw-r--r--drivers/media/tuners/m88rs6000t.c2
-rw-r--r--drivers/media/tuners/mt2060.c2
-rw-r--r--drivers/media/tuners/mxl301rf.c2
-rw-r--r--drivers/media/tuners/qm1d1b0004.c2
-rw-r--r--drivers/media/tuners/qm1d1c0042.c2
-rw-r--r--drivers/media/tuners/si2157.c2
-rw-r--r--drivers/media/tuners/tda18212.c2
-rw-r--r--drivers/media/tuners/tda18250.c2
-rw-r--r--drivers/media/tuners/tua9001.c2
-rw-r--r--drivers/media/usb/as102/as102_usb_drv.c6
-rw-r--r--drivers/media/usb/au0828/au0828-core.c2
-rw-r--r--drivers/media/usb/dvb-usb-v2/az6007.c19
-rw-r--r--drivers/media/usb/dvb-usb/af9005-fe.c3
-rw-r--r--drivers/media/usb/dvb-usb/az6027.c34
-rw-r--r--drivers/media/usb/dvb-usb/dtt200u-fe.c2
-rw-r--r--drivers/media/usb/dvb-usb/dw2102.c26
-rw-r--r--drivers/media/usb/dvb-usb/opera1.c3
-rw-r--r--drivers/media/usb/dvb-usb/pctv452e.c20
-rw-r--r--drivers/media/usb/go7007/s2250-board.c2
-rw-r--r--drivers/media/usb/siano/smsusb.c3
-rw-r--r--drivers/media/usb/stk1160/Kconfig12
-rw-r--r--drivers/media/usb/ttusb-dec/ttusb_dec.c2
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c137
-rw-r--r--drivers/media/usb/uvc/uvc_v4l2.c79
-rw-r--r--drivers/media/usb/uvc/uvc_video.c20
-rw-r--r--drivers/media/usb/uvc/uvcvideo.h12
-rw-r--r--drivers/media/v4l2-core/tuner-core.c2
-rw-r--r--drivers/media/v4l2-core/v4l2-common.c162
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls-core.c263
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls-defs.c61
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c2
-rw-r--r--drivers/media/v4l2-core/v4l2-mc.c38
-rw-r--r--drivers/memory/Kconfig11
-rw-r--r--drivers/memory/Makefile1
-rw-r--r--drivers/memory/atmel-sdramc.c74
-rw-r--r--drivers/memory/brcmstb_dpfe.c4
-rw-r--r--drivers/memory/renesas-rpc-if.c53
-rw-r--r--drivers/memory/tegra/mc.c24
-rw-r--r--drivers/memory/tegra/mc.h1
-rw-r--r--drivers/memory/tegra/tegra186-emc.c133
-rw-r--r--drivers/memory/tegra/tegra234.c595
-rw-r--r--drivers/message/fusion/Kconfig2
-rw-r--r--drivers/message/fusion/mptbase.c4
-rw-r--r--drivers/message/fusion/mptctl.c2
-rw-r--r--drivers/mfd/88pm800.c2
-rw-r--r--drivers/mfd/88pm805.c2
-rw-r--r--drivers/mfd/88pm80x.c1
-rw-r--r--drivers/mfd/88pm860x-core.c3
-rw-r--r--drivers/mfd/Kconfig17
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/aat2870-core.c4
-rw-r--r--drivers/mfd/acer-ec-a500.c2
-rw-r--r--drivers/mfd/act8945a.c2
-rw-r--r--drivers/mfd/adp5520.c2
-rw-r--r--drivers/mfd/arizona-i2c.c2
-rw-r--r--drivers/mfd/as3711.c2
-rw-r--r--drivers/mfd/as3722.c2
-rw-r--r--drivers/mfd/atc260x-i2c.c2
-rw-r--r--drivers/mfd/axp20x-i2c.c4
-rw-r--r--drivers/mfd/axp20x.c141
-rw-r--r--drivers/mfd/bcm590xx.c2
-rw-r--r--drivers/mfd/bd9571mwv.c2
-rw-r--r--drivers/mfd/da903x.c2
-rw-r--r--drivers/mfd/da9052-i2c.c2
-rw-r--r--drivers/mfd/da9055-i2c.c2
-rw-r--r--drivers/mfd/da9062-core.c2
-rw-r--r--drivers/mfd/da9063-i2c.c2
-rw-r--r--drivers/mfd/da9150-core.c2
-rw-r--r--drivers/mfd/dln2.c1
-rw-r--r--drivers/mfd/ene-kb3930.c2
-rw-r--r--drivers/mfd/gateworks-gsc.c2
-rw-r--r--drivers/mfd/intel-lpss-acpi.c3
-rw-r--r--drivers/mfd/intel-lpss.c2
-rw-r--r--drivers/mfd/intel-m10-bmc-core.c90
-rw-r--r--drivers/mfd/intel-m10-bmc-pmci.c1
-rw-r--r--drivers/mfd/intel-m10-bmc-spi.c15
-rw-r--r--drivers/mfd/intel_soc_pmic_chtdc_ti.c2
-rw-r--r--drivers/mfd/intel_soc_pmic_chtwc.c2
-rw-r--r--drivers/mfd/intel_soc_pmic_crc.c2
-rw-r--r--drivers/mfd/iqs62x.c2
-rw-r--r--drivers/mfd/khadas-mcu.c2
-rw-r--r--drivers/mfd/lm3533-core.c4
-rw-r--r--drivers/mfd/lochnagar-i2c.c2
-rw-r--r--drivers/mfd/lp3943.c2
-rw-r--r--drivers/mfd/lp873x.c2
-rw-r--r--drivers/mfd/lp87565.c2
-rw-r--r--drivers/mfd/lp8788.c2
-rw-r--r--drivers/mfd/madera-i2c.c2
-rw-r--r--drivers/mfd/max14577.c2
-rw-r--r--drivers/mfd/max77541.c224
-rw-r--r--drivers/mfd/max77620.c2
-rw-r--r--drivers/mfd/max77650.c2
-rw-r--r--drivers/mfd/max77686.c2
-rw-r--r--drivers/mfd/max77693.c2
-rw-r--r--drivers/mfd/max77714.c2
-rw-r--r--drivers/mfd/max77843.c2
-rw-r--r--drivers/mfd/max8907.c4
-rw-r--r--drivers/mfd/max8925-i2c.c3
-rw-r--r--drivers/mfd/max8997.c2
-rw-r--r--drivers/mfd/max8998.c2
-rw-r--r--drivers/mfd/mc13xxx-i2c.c2
-rw-r--r--drivers/mfd/menelaus.c2
-rw-r--r--drivers/mfd/menf21bmc.c2
-rw-r--r--drivers/mfd/mfd-core.c6
-rw-r--r--drivers/mfd/mp2629.c2
-rw-r--r--drivers/mfd/mt6360-core.c2
-rw-r--r--drivers/mfd/mt6370.c2
-rw-r--r--drivers/mfd/ntxec.c2
-rw-r--r--drivers/mfd/palmas.c2
-rw-r--r--drivers/mfd/pcf50633-core.c2
-rw-r--r--drivers/mfd/qcom-pm8008.c4
-rw-r--r--drivers/mfd/rc5t583-irq.c2
-rw-r--r--drivers/mfd/rc5t583.c2
-rw-r--r--drivers/mfd/retu-mfd.c2
-rw-r--r--drivers/mfd/rk8xx-i2c.c2
-rw-r--r--drivers/mfd/rn5t618.c2
-rw-r--r--drivers/mfd/rohm-bd71828.c2
-rw-r--r--drivers/mfd/rohm-bd718x7.c2
-rw-r--r--drivers/mfd/rohm-bd9576.c2
-rw-r--r--drivers/mfd/rsmu_i2c.c2
-rw-r--r--drivers/mfd/rt4831.c2
-rw-r--r--drivers/mfd/rt5033.c10
-rw-r--r--drivers/mfd/rt5120.c2
-rw-r--r--drivers/mfd/sec-core.c2
-rw-r--r--drivers/mfd/si476x-i2c.c2
-rw-r--r--drivers/mfd/simple-mfd-i2c.c20
-rw-r--r--drivers/mfd/sky81452.c2
-rw-r--r--drivers/mfd/smpro-core.c2
-rw-r--r--drivers/mfd/stmfx.c9
-rw-r--r--drivers/mfd/stmpe-i2c.c2
-rw-r--r--drivers/mfd/stmpe.c4
-rw-r--r--drivers/mfd/stpmic1.c27
-rw-r--r--drivers/mfd/stw481x.c2
-rw-r--r--drivers/mfd/tc3589x.c2
-rw-r--r--drivers/mfd/ti-lmu.c2
-rw-r--r--drivers/mfd/tps6105x.c2
-rw-r--r--drivers/mfd/tps65010.c16
-rw-r--r--drivers/mfd/tps6507x.c2
-rw-r--r--drivers/mfd/tps65086.c2
-rw-r--r--drivers/mfd/tps65090.c2
-rw-r--r--drivers/mfd/tps65217.c2
-rw-r--r--drivers/mfd/tps65218.c2
-rw-r--r--drivers/mfd/tps65219.c42
-rw-r--r--drivers/mfd/tps6586x.c2
-rw-r--r--drivers/mfd/tps65910.c2
-rw-r--r--drivers/mfd/tps65912-i2c.c2
-rw-r--r--drivers/mfd/tps6594-i2c.c4
-rw-r--r--drivers/mfd/tps6594-spi.c2
-rw-r--r--drivers/mfd/twl-core.c2
-rw-r--r--drivers/mfd/twl6040.c4
-rw-r--r--drivers/mfd/wcd934x.c28
-rw-r--r--drivers/mfd/wl1273-core.c2
-rw-r--r--drivers/mfd/wm831x-core.c2
-rw-r--r--drivers/mfd/wm831x-i2c.c2
-rw-r--r--drivers/mfd/wm8350-i2c.c2
-rw-r--r--drivers/mfd/wm8400-core.c4
-rw-r--r--drivers/mfd/wm8994-core.c4
-rw-r--r--drivers/misc/Kconfig23
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/ad525x_dpot-i2c.c2
-rw-r--r--drivers/misc/altera-stapl/Makefile3
-rw-r--r--drivers/misc/altera-stapl/altera.c6
-rw-r--r--drivers/misc/apds9802als.c2
-rw-r--r--drivers/misc/apds990x.c4
-rw-r--r--drivers/misc/bh1770glc.c4
-rw-r--r--drivers/misc/ds1682.c2
-rw-r--r--drivers/misc/eeprom/at24.c5
-rw-r--r--drivers/misc/eeprom/ee1004.c2
-rw-r--r--drivers/misc/eeprom/eeprom.c2
-rw-r--r--drivers/misc/eeprom/idt_89hpesx.c2
-rw-r--r--drivers/misc/eeprom/max6875.c2
-rw-r--r--drivers/misc/fastrpc.c5
-rw-r--r--drivers/misc/hmc6352.c2
-rw-r--r--drivers/misc/ics932s401.c2
-rw-r--r--drivers/misc/isl29003.c2
-rw-r--r--drivers/misc/isl29020.c2
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d_i2c.c2
-rw-r--r--drivers/misc/lkdtm/core.c2
-rw-r--r--drivers/misc/mei/Kconfig2
-rw-r--r--drivers/misc/mei/Makefile1
-rw-r--r--drivers/misc/mei/bus-fixup.c4
-rw-r--r--drivers/misc/mei/bus.c9
-rw-r--r--drivers/misc/mei/gsc_proxy/Kconfig14
-rw-r--r--drivers/misc/mei/gsc_proxy/Makefile7
-rw-r--r--drivers/misc/mei/gsc_proxy/mei_gsc_proxy.c208
-rw-r--r--drivers/misc/mei/hdcp/mei_hdcp.c26
-rw-r--r--drivers/misc/pci_endpoint_test.c25
-rw-r--r--drivers/misc/smpro-errmon.c1
-rw-r--r--drivers/misc/sram.c9
-rw-r--r--drivers/misc/tps6594-esm.c132
-rw-r--r--drivers/misc/tps6594-pfsm.c306
-rw-r--r--drivers/misc/tsl2550.c2
-rw-r--r--drivers/misc/uacce/uacce.c25
-rw-r--r--drivers/misc/xilinx_sdfec.c12
-rw-r--r--drivers/mmc/host/omap.c46
-rw-r--r--drivers/mux/Kconfig2
-rw-r--r--drivers/mux/adg792a.c2
-rw-r--r--drivers/mux/mmio.c2
-rw-r--r--drivers/net/arcnet/arcnet.c8
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c4
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c4
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/debugfs.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c8
-rw-r--r--drivers/net/ethernet/microsoft/mana/mana_en.c5
-rw-r--r--drivers/nvdimm/bus.c2
-rw-r--r--drivers/nvdimm/dimm_devs.c4
-rw-r--r--drivers/nvdimm/pmem.c2
-rw-r--r--drivers/nvme/host/Makefile2
-rw-r--r--drivers/nvme/host/constants.c2
-rw-r--r--drivers/nvme/host/core.c155
-rw-r--r--drivers/nvme/host/ioctl.c70
-rw-r--r--drivers/nvme/host/multipath.c10
-rw-r--r--drivers/nvme/host/nvme.h5
-rw-r--r--drivers/nvme/host/pci.c5
-rw-r--r--drivers/nvme/host/pr.c315
-rw-r--r--drivers/nvme/target/nvmet.h2
-rw-r--r--drivers/nvmem/Kconfig10
-rw-r--r--drivers/nvmem/Makefile2
-rw-r--r--drivers/nvmem/brcm_nvram.c28
-rw-r--r--drivers/nvmem/core.c32
-rw-r--r--drivers/nvmem/imx-ocotp-ele.c175
-rw-r--r--drivers/nvmem/imx-ocotp.c10
-rw-r--r--drivers/nvmem/rmem.c1
-rw-r--r--drivers/nvmem/rockchip-otp.c191
-rw-r--r--drivers/nvmem/sunplus-ocotp.c9
-rw-r--r--drivers/nvmem/zynqmp_nvmem.c2
-rw-r--r--drivers/of/of_reserved_mem.c60
-rw-r--r--drivers/of/platform.c7
-rw-r--r--drivers/of/unittest.c32
-rw-r--r--drivers/opp/core.c44
-rw-r--r--drivers/opp/debugfs.c1
-rw-r--r--drivers/opp/of.c40
-rw-r--r--drivers/opp/opp.h6
-rw-r--r--drivers/parisc/ccio-dma.c18
-rw-r--r--drivers/parisc/dino.c5
-rw-r--r--drivers/parisc/eisa.c2
-rw-r--r--drivers/parisc/lba_pci.c8
-rw-r--r--drivers/parisc/pdc_stable.c36
-rw-r--r--drivers/parisc/sba_iommu.c32
-rw-r--r--drivers/parport/Kconfig3
-rw-r--r--drivers/pci/controller/cadence/pci-j721e.c6
-rw-r--r--drivers/pci/controller/cadence/pcie-cadence-host.c27
-rw-r--r--drivers/pci/controller/dwc/pci-imx6.c23
-rw-r--r--drivers/pci/controller/dwc/pci-layerscape-ep.c100
-rw-r--r--drivers/pci/controller/dwc/pcie-bt1.c6
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-host.c13
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.c20
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.h1
-rw-r--r--drivers/pci/controller/dwc/pcie-histb.c6
-rw-r--r--drivers/pci/controller/dwc/pcie-intel-gw.c6
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom-ep.c10
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom.c73
-rw-r--r--drivers/pci/controller/dwc/pcie-tegra194.c52
-rw-r--r--drivers/pci/controller/pci-aardvark.c6
-rw-r--r--drivers/pci/controller/pci-ftpci100.c14
-rw-r--r--drivers/pci/controller/pci-mvebu.c6
-rw-r--r--drivers/pci/controller/pci-tegra.c6
-rw-r--r--drivers/pci/controller/pci-xgene-msi.c6
-rw-r--r--drivers/pci/controller/pcie-altera-msi.c5
-rw-r--r--drivers/pci/controller/pcie-altera.c6
-rw-r--r--drivers/pci/controller/pcie-brcmstb.c6
-rw-r--r--drivers/pci/controller/pcie-hisi-error.c6
-rw-r--r--drivers/pci/controller/pcie-iproc-platform.c6
-rw-r--r--drivers/pci/controller/pcie-iproc.c4
-rw-r--r--drivers/pci/controller/pcie-iproc.h2
-rw-r--r--drivers/pci/controller/pcie-mediatek-gen3.c6
-rw-r--r--drivers/pci/controller/pcie-mediatek.c6
-rw-r--r--drivers/pci/controller/pcie-mt7621.c6
-rw-r--r--drivers/pci/controller/pcie-rcar-host.c25
-rw-r--r--drivers/pci/controller/pcie-rockchip-ep.c221
-rw-r--r--drivers/pci/controller/pcie-rockchip-host.c6
-rw-r--r--drivers/pci/controller/pcie-rockchip.c17
-rw-r--r--drivers/pci/controller/pcie-rockchip.h49
-rw-r--r--drivers/pci/controller/vmd.c11
-rw-r--r--drivers/pci/endpoint/functions/Kconfig12
-rw-r--r--drivers/pci/endpoint/functions/Makefile1
-rw-r--r--drivers/pci/endpoint/functions/pci-epf-mhi.c458
-rw-r--r--drivers/pci/endpoint/functions/pci-epf-ntb.c4
-rw-r--r--drivers/pci/endpoint/functions/pci-epf-test.c271
-rw-r--r--drivers/pci/endpoint/functions/pci-epf-vntb.c14
-rw-r--r--drivers/pci/endpoint/pci-ep-cfs.c73
-rw-r--r--drivers/pci/endpoint/pci-epc-core.c56
-rw-r--r--drivers/pci/endpoint/pci-epf-core.c42
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c5
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c21
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c12
-rw-r--r--drivers/pci/of.c14
-rw-r--r--drivers/pci/pci-acpi.c53
-rw-r--r--drivers/pci/pci.c192
-rw-r--r--drivers/pci/pci.h19
-rw-r--r--drivers/pci/pcie/aspm.c101
-rw-r--r--drivers/pci/probe.c12
-rw-r--r--drivers/pci/quirks.c111
-rw-r--r--drivers/pcmcia/Kconfig5
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c2
-rw-r--r--drivers/perf/Kconfig13
-rw-r--r--drivers/perf/Makefile1
-rw-r--r--drivers/perf/cxl_pmu.c990
-rw-r--r--drivers/perf/riscv_pmu_sbi.c23
-rw-r--r--drivers/phy/Kconfig1
-rw-r--r--drivers/phy/cadence/phy-cadence-sierra.c1
-rw-r--r--drivers/phy/cadence/phy-cadence-torrent.c1
-rw-r--r--drivers/phy/ti/phy-am654-serdes.c1
-rw-r--r--drivers/phy/ti/phy-j721e-wiz.c1
-rw-r--r--drivers/pinctrl/Kconfig1
-rw-r--r--drivers/pinctrl/Makefile2
-rw-r--r--drivers/pinctrl/bcm/pinctrl-bcm2835.c6
-rw-r--r--drivers/pinctrl/freescale/pinctrl-scu.c3
-rw-r--r--drivers/pinctrl/intel/pinctrl-baytrail.c104
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c26
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c54
-rw-r--r--drivers/pinctrl/intel/pinctrl-merrifield.c16
-rw-r--r--drivers/pinctrl/intel/pinctrl-meteorlake.c212
-rw-r--r--drivers/pinctrl/intel/pinctrl-moorefield.c16
-rw-r--r--drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c2
-rw-r--r--drivers/pinctrl/nxp/pinctrl-s32.h14
-rw-r--r--drivers/pinctrl/nxp/pinctrl-s32cc.c42
-rw-r--r--drivers/pinctrl/nxp/pinctrl-s32g2.c14
-rw-r--r--drivers/pinctrl/pinctrl-amd.c50
-rw-r--r--drivers/pinctrl/pinctrl-amd.h1
-rw-r--r--drivers/pinctrl/pinctrl-at91-pio4.c17
-rw-r--r--drivers/pinctrl/pinctrl-at91.c8
-rw-r--r--drivers/pinctrl/pinctrl-axp209.c42
-rw-r--r--drivers/pinctrl/pinctrl-cy8c95x0.c2
-rw-r--r--drivers/pinctrl/pinctrl-falcon.c1
-rw-r--r--drivers/pinctrl/pinctrl-mcp23s08_i2c.c2
-rw-r--r--drivers/pinctrl/pinctrl-microchip-sgpio.c5
-rw-r--r--drivers/pinctrl/pinctrl-sx150x.c2
-rw-r--r--drivers/pinctrl/pinctrl-xway.c2
-rw-r--r--drivers/pinctrl/pinmux.c15
-rw-r--r--drivers/pinctrl/qcom/Kconfig463
-rw-r--r--drivers/pinctrl/qcom/Kconfig.msm369
-rw-r--r--drivers/pinctrl/qcom/Makefile4
-rw-r--r--drivers/pinctrl/qcom/pinctrl-apq8064.c104
-rw-r--r--drivers/pinctrl/qcom/pinctrl-apq8084.c264
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq4019.c104
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq5018.c783
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq5332.c206
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq6018.c260
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq8064.c114
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq8074.c240
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq9574.c176
-rw-r--r--drivers/pinctrl/qcom/pinctrl-mdm9607.c276
-rw-r--r--drivers/pinctrl/qcom/pinctrl-mdm9615.c90
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.c13
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.h42
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8226.c156
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8660.c252
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8909.c268
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8916.c556
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8953.c424
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8960.c464
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8976.c212
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8994.c564
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8996.c508
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8998.c380
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8x74.c474
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qcm2290.c230
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qcs404.c388
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qdf2xxx.c8
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qdu1000.c249
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sa8775p.c327
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc7180.c254
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc7280.c322
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc8180x.c292
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc8280xp.c358
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm660.c387
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm670.c284
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm845.c286
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdx55.c190
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdx65.c194
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdx75.c1144
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6115.c162
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6125.c282
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6350.c296
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6375.c358
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm7150.c247
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8150.c286
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8250.c258
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8350.c298
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8450.c300
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8550.c320
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-gpio.c2
-rw-r--r--drivers/pinctrl/renesas/pfc-r8a77970.c2
-rw-r--r--drivers/pinctrl/renesas/pfc-r8a77980.c6
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear.c1
-rw-r--r--drivers/pinctrl/stm32/Kconfig6
-rw-r--r--drivers/pinctrl/stm32/Makefile1
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32.h3
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32mp257.c2581
-rw-r--r--drivers/pinctrl/sunplus/sppctl.c23
-rw-r--r--drivers/pinctrl/tegra/Kconfig4
-rw-r--r--drivers/pinctrl/tegra/Makefile1
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra.c28
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra.h3
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra114.c7
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra124.c7
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra194.c7
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra20.c7
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra210.c7
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra234.c1960
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra30.c7
-rw-r--r--drivers/platform/chrome/cros_ec_typec.c2
-rw-r--r--drivers/platform/mellanox/mlxbf-bootctl.c144
-rw-r--r--drivers/platform/surface/aggregator/Kconfig2
-rw-r--r--drivers/platform/surface/surface3_power.c2
-rw-r--r--drivers/platform/x86/Kconfig11
-rw-r--r--drivers/platform/x86/Makefile2
-rw-r--r--drivers/platform/x86/amd/pmc.c123
-rw-r--r--drivers/platform/x86/amd/pmf/Kconfig11
-rw-r--r--drivers/platform/x86/amd/pmf/auto-mode.c143
-rw-r--r--drivers/platform/x86/amd/pmf/cnqf.c75
-rw-r--r--drivers/platform/x86/amd/pmf/sps.c55
-rw-r--r--drivers/platform/x86/apple-gmux.c4
-rw-r--r--drivers/platform/x86/asus-tf103c-dock.c2
-rw-r--r--drivers/platform/x86/dell/dell-rbtn.c13
-rw-r--r--drivers/platform/x86/dell/dell-wmi-sysman/sysman.c13
-rw-r--r--drivers/platform/x86/gigabyte-wmi.c46
-rw-r--r--drivers/platform/x86/hp/hp-wmi.c156
-rw-r--r--drivers/platform/x86/intel/int3472/clk_and_regulator.c168
-rw-r--r--drivers/platform/x86/intel/int3472/common.h28
-rw-r--r--drivers/platform/x86/intel/int3472/discrete.c102
-rw-r--r--drivers/platform/x86/intel/int3472/tps68470.c2
-rw-r--r--drivers/platform/x86/intel/pmc/Makefile4
-rw-r--r--drivers/platform/x86/intel/pmc/adl.c16
-rw-r--r--drivers/platform/x86/intel/pmc/cnp.c18
-rw-r--r--drivers/platform/x86/intel/pmc/core.c485
-rw-r--r--drivers/platform/x86/intel/pmc/core.h128
-rw-r--r--drivers/platform/x86/intel/pmc/core_ssram.c133
-rw-r--r--drivers/platform/x86/intel/pmc/icl.c7
-rw-r--r--drivers/platform/x86/intel/pmc/mtl.c977
-rw-r--r--drivers/platform/x86/intel/pmc/spt.c7
-rw-r--r--drivers/platform/x86/intel/pmc/tgl.c21
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_common.c1
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c2
-rw-r--r--drivers/platform/x86/intel/tpmi.c8
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/Kconfig4
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/Makefile2
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c51
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h16
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c413
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c1
-rw-r--r--drivers/platform/x86/lenovo-yogabook-wmi.c408
-rw-r--r--drivers/platform/x86/lenovo-yogabook.c573
-rw-r--r--drivers/platform/x86/simatic-ipc.c7
-rw-r--r--drivers/platform/x86/system76_acpi.c2
-rw-r--r--drivers/platform/x86/think-lmi.c65
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c6
-rw-r--r--drivers/platform/x86/toshiba_acpi.c2
-rw-r--r--drivers/platform/x86/wmi.c104
-rw-r--r--drivers/platform/x86/x86-android-tablets/asus.c6
-rw-r--r--drivers/platform/x86/x86-android-tablets/core.c32
-rw-r--r--drivers/platform/x86/x86-android-tablets/dmi.c22
-rw-r--r--drivers/platform/x86/x86-android-tablets/lenovo.c41
-rw-r--r--drivers/platform/x86/x86-android-tablets/other.c112
-rw-r--r--drivers/platform/x86/x86-android-tablets/x86-android-tablets.h5
-rw-r--r--drivers/power/reset/Kconfig1
-rw-r--r--drivers/power/reset/at91-reset.c9
-rw-r--r--drivers/power/reset/gpio-restart.c7
-rw-r--r--drivers/power/reset/qcom-pon.c22
-rw-r--r--drivers/power/supply/Kconfig17
-rw-r--r--drivers/power/supply/Makefile2
-rw-r--r--drivers/power/supply/adp5061.c2
-rw-r--r--drivers/power/supply/axp20x_usb_power.c307
-rw-r--r--drivers/power/supply/bd99954-charger.c2
-rw-r--r--drivers/power/supply/bq2415x_charger.c2
-rw-r--r--drivers/power/supply/bq24190_charger.c2
-rw-r--r--drivers/power/supply/bq24257_charger.c2
-rw-r--r--drivers/power/supply/bq24735-charger.c2
-rw-r--r--drivers/power/supply/bq2515x_charger.c2
-rw-r--r--drivers/power/supply/bq256xx_charger.c30
-rw-r--r--drivers/power/supply/bq25890_charger.c2
-rw-r--r--drivers/power/supply/bq25980_charger.c2
-rw-r--r--drivers/power/supply/bq27xxx_battery_i2c.c2
-rw-r--r--drivers/power/supply/cros_peripheral_charger.c25
-rw-r--r--drivers/power/supply/cw2015_battery.c2
-rw-r--r--drivers/power/supply/ds2782_battery.c2
-rw-r--r--drivers/power/supply/ip5xxx_power.c2
-rw-r--r--drivers/power/supply/lp8727_charger.c2
-rw-r--r--drivers/power/supply/ltc2941-battery-gauge.c2
-rw-r--r--drivers/power/supply/ltc4162-l-charger.c2
-rw-r--r--drivers/power/supply/max14656_charger_detector.c2
-rw-r--r--drivers/power/supply/max17040_battery.c2
-rw-r--r--drivers/power/supply/max17042_battery.c9
-rw-r--r--drivers/power/supply/max77976_charger.c2
-rw-r--r--drivers/power/supply/power_supply_hwmon.c2
-rw-r--r--drivers/power/supply/power_supply_leds.c5
-rw-r--r--drivers/power/supply/qcom_pmi8998_charger.c1059
-rw-r--r--drivers/power/supply/rk817_charger.c2
-rw-r--r--drivers/power/supply/rt5033_battery.c40
-rw-r--r--drivers/power/supply/rt5033_charger.c472
-rw-r--r--drivers/power/supply/rt9455_charger.c2
-rw-r--r--drivers/power/supply/rt9467-charger.c4
-rw-r--r--drivers/power/supply/rt9471.c2
-rw-r--r--drivers/power/supply/sbs-battery.c2
-rw-r--r--drivers/power/supply/sbs-charger.c2
-rw-r--r--drivers/power/supply/sbs-manager.c2
-rw-r--r--drivers/power/supply/smb347-charger.c2
-rw-r--r--drivers/power/supply/twl4030_madc_battery.c8
-rw-r--r--drivers/power/supply/ucs1002_power.c2
-rw-r--r--drivers/power/supply/ug3105_battery.c2
-rw-r--r--drivers/powercap/arm_scmi_powercap.c16
-rw-r--r--drivers/pwm/Kconfig21
-rw-r--r--drivers/pwm/Makefile2
-rw-r--r--drivers/pwm/pwm-ab8500.c2
-rw-r--r--drivers/pwm/pwm-clk.c12
-rw-r--r--drivers/pwm/pwm-imx-tpm.c7
-rw-r--r--drivers/pwm/pwm-mediatek.c39
-rw-r--r--drivers/pwm/pwm-meson.c212
-rw-r--r--drivers/pwm/pwm-microchip-core.c507
-rw-r--r--drivers/pwm/pwm-mtk-disp.c13
-rw-r--r--drivers/pwm/pwm-pca9685.c2
-rw-r--r--drivers/pwm/pwm-rz-mtu3.c551
-rw-r--r--drivers/pwm/pwm-sifive.c7
-rw-r--r--drivers/pwm/sysfs.c17
-rw-r--r--drivers/regulator/Kconfig11
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/max77541-regulator.c153
-rw-r--r--drivers/remoteproc/Kconfig2
-rw-r--r--drivers/remoteproc/da8xx_remoteproc.c6
-rw-r--r--drivers/remoteproc/imx_dsp_rproc.c17
-rw-r--r--drivers/remoteproc/imx_rproc.c6
-rw-r--r--drivers/remoteproc/keystone_remoteproc.c6
-rw-r--r--drivers/remoteproc/meson_mx_ao_arc.c6
-rw-r--r--drivers/remoteproc/mtk_scp.c6
-rw-r--r--drivers/remoteproc/omap_remoteproc.c6
-rw-r--r--drivers/remoteproc/pru_rproc.c21
-rw-r--r--drivers/remoteproc/qcom_q6v5_adsp.c6
-rw-r--r--drivers/remoteproc/qcom_q6v5_mss.c6
-rw-r--r--drivers/remoteproc/qcom_q6v5_pas.c8
-rw-r--r--drivers/remoteproc/qcom_q6v5_wcss.c6
-rw-r--r--drivers/remoteproc/qcom_wcnss.c6
-rw-r--r--drivers/remoteproc/rcar_rproc.c6
-rw-r--r--drivers/remoteproc/remoteproc_virtio.c6
-rw-r--r--drivers/remoteproc/st_remoteproc.c6
-rw-r--r--drivers/remoteproc/stm32_rproc.c88
-rw-r--r--drivers/remoteproc/wkup_m3_rproc.c6
-rw-r--r--drivers/reset/Kconfig11
-rw-r--r--drivers/reset/Makefile2
-rw-r--r--drivers/reset/reset-ath79.c4
-rw-r--r--drivers/reset/reset-axs10x.c4
-rw-r--r--drivers/reset/reset-brcmstb-rescal.c4
-rw-r--r--drivers/reset/reset-hsdk.c7
-rw-r--r--drivers/reset/reset-lpc18xx.c4
-rw-r--r--drivers/reset/reset-ma35d1.c235
-rw-r--r--drivers/reset/reset-meson-audio-arb.c7
-rw-r--r--drivers/reset/reset-meson.c4
-rw-r--r--drivers/reset/reset-oxnas.c114
-rw-r--r--drivers/reset/starfive/Kconfig3
-rw-r--r--drivers/reset/sti/Kconfig4
-rw-r--r--drivers/reset/sti/Makefile4
-rw-r--r--drivers/reset/sti/reset-syscfg.c18
-rw-r--r--drivers/rtc/Kconfig27
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/rtc-ab-b5ze-s3.c2
-rw-r--r--drivers/rtc/rtc-ab-eoz9.c4
-rw-r--r--drivers/rtc/rtc-abx80x.c2
-rw-r--r--drivers/rtc/rtc-bq32k.c2
-rw-r--r--drivers/rtc/rtc-ds1307.c2
-rw-r--r--drivers/rtc/rtc-ds1374.c2
-rw-r--r--drivers/rtc/rtc-ds1672.c2
-rw-r--r--drivers/rtc/rtc-ds3232.c4
-rw-r--r--drivers/rtc/rtc-em3027.c2
-rw-r--r--drivers/rtc/rtc-fm3130.c2
-rw-r--r--drivers/rtc/rtc-hym8563.c2
-rw-r--r--drivers/rtc/rtc-isl12022.c4
-rw-r--r--drivers/rtc/rtc-isl12026.c2
-rw-r--r--drivers/rtc/rtc-isl1208.c132
-rw-r--r--drivers/rtc/rtc-loongson.c397
-rw-r--r--drivers/rtc/rtc-ls1x.c192
-rw-r--r--drivers/rtc/rtc-m41t80.c2
-rw-r--r--drivers/rtc/rtc-max6900.c2
-rw-r--r--drivers/rtc/rtc-nct3018y.c2
-rw-r--r--drivers/rtc/rtc-pcf2127.c2
-rw-r--r--drivers/rtc/rtc-pcf85063.c2
-rw-r--r--drivers/rtc/rtc-pcf8523.c2
-rw-r--r--drivers/rtc/rtc-pcf85363.c2
-rw-r--r--drivers/rtc/rtc-pcf8563.c2
-rw-r--r--drivers/rtc/rtc-pcf8583.c2
-rw-r--r--drivers/rtc/rtc-rs5c372.c2
-rw-r--r--drivers/rtc/rtc-rv3028.c9
-rw-r--r--drivers/rtc/rtc-rv3029c2.c2
-rw-r--r--drivers/rtc/rtc-rv3032.c4
-rw-r--r--drivers/rtc/rtc-rv8803.c2
-rw-r--r--drivers/rtc/rtc-rx6110.c2
-rw-r--r--drivers/rtc/rtc-rx8010.c2
-rw-r--r--drivers/rtc/rtc-rx8025.c2
-rw-r--r--drivers/rtc/rtc-rx8581.c2
-rw-r--r--drivers/rtc/rtc-s35390a.c2
-rw-r--r--drivers/rtc/rtc-sd3078.c2
-rw-r--r--drivers/rtc/rtc-st-lpc.c16
-rw-r--r--drivers/rtc/rtc-stm32.c28
-rw-r--r--drivers/rtc/rtc-sun6i.c1
-rw-r--r--drivers/rtc/rtc-x1205.c2
-rw-r--r--drivers/s390/block/dasd.c7
-rw-r--r--drivers/s390/block/dcssblk.c3
-rw-r--r--drivers/s390/char/Kconfig2
-rw-r--r--drivers/s390/char/uvdevice.c231
-rw-r--r--drivers/sbus/char/oradax.c21
-rw-r--r--drivers/scsi/3w-xxxx.c4
-rw-r--r--drivers/scsi/Kconfig25
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic79xx2
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic7xxx2
-rw-r--r--drivers/scsi/aic94xx/Kconfig2
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.c4
-rw-r--r--drivers/scsi/bfa/bfa_fcs.c4
-rw-r--r--drivers/scsi/bfa/bfa_fcs_lport.c20
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c2
-rw-r--r--drivers/scsi/bfa/bfa_svc.c2
-rw-r--r--drivers/scsi/bfa/bfad.c10
-rw-r--r--drivers/scsi/bfa/bfad_attr.c2
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c4
-rw-r--r--drivers/scsi/bfa/bfad_im.c2
-rw-r--r--drivers/scsi/fcoe/fcoe_transport.c2
-rw-r--r--drivers/scsi/fnic/fnic_debugfs.c8
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas.h2
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c3
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v1_hw.c7
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v2_hw.c7
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v3_hw.c28
-rw-r--r--drivers/scsi/hosts.c1
-rw-r--r--drivers/scsi/libsas/sas_expander.c124
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c3
-rw-r--r--drivers/scsi/lpfc/lpfc.h65
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c92
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c44
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c59
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h20
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h14
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c276
-rw-r--r--drivers/scsi/lpfc/lpfc_logmsg.h6
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.c61
-rw-r--r--drivers/scsi/lpfc/lpfc_nvmet.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c68
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c446
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/megaraid/Kconfig.megaraid6
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h8
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr.h8
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_fw.c7
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_transport.c2
-rw-r--r--drivers/scsi/mvsas/Kconfig2
-rw-r--r--drivers/scsi/pcmcia/Kconfig6
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c32
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c22
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h1
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.c126
-rw-r--r--drivers/scsi/qedf/qedf_main.c3
-rw-r--r--drivers/scsi/qla2xxx/Kconfig2
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c13
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h26
-rw-r--r--drivers/scsi/qla2xxx/qla_edif.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c267
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c36
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c64
-rw-r--r--drivers/scsi/qla2xxx/qla_mr.c20
-rw-r--r--drivers/scsi/qla2xxx/qla_nvme.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c133
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h4
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c8
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c14
-rw-r--r--drivers/scsi/scsi.c171
-rw-r--r--drivers/scsi/scsi_common.c46
-rw-r--r--drivers/scsi/scsi_error.c48
-rw-r--r--drivers/scsi/scsi_lib.c137
-rw-r--r--drivers/scsi/scsi_priv.h6
-rw-r--r--drivers/scsi/scsi_scan.c3
-rw-r--r--drivers/scsi/scsi_sysfs.c30
-rw-r--r--drivers/scsi/scsi_transport_fc.c2
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c3
-rw-r--r--drivers/scsi/scsi_transport_sas.c2
-rw-r--r--drivers/scsi/scsi_transport_srp.c6
-rw-r--r--drivers/scsi/sd.c189
-rw-r--r--drivers/scsi/sd_zbc.c2
-rw-r--r--drivers/scsi/sg.c2
-rw-r--r--drivers/scsi/smartpqi/Kconfig2
-rw-r--r--drivers/scsi/smartpqi/smartpqi.h6
-rw-r--r--drivers/scsi/smartpqi/smartpqi_init.c286
-rw-r--r--drivers/scsi/smartpqi/smartpqi_sas_transport.c34
-rw-r--r--drivers/scsi/smartpqi/smartpqi_sis.c2
-rw-r--r--drivers/scsi/smartpqi/smartpqi_sis.h2
-rw-r--r--drivers/scsi/snic/snic_disc.c2
-rw-r--r--drivers/scsi/sr.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c2
-rw-r--r--drivers/scsi/virtio_scsi.c4
-rw-r--r--drivers/soc/amlogic/meson-secure-pwrc.c2
-rw-r--r--drivers/soc/fsl/dpio/dpio-driver.c8
-rw-r--r--drivers/soc/fsl/qe/Kconfig1
-rw-r--r--drivers/soc/mediatek/mtk-mutex.c1
-rw-r--r--drivers/soc/mediatek/mtk-pmic-wrap.c292
-rw-r--r--drivers/soc/mediatek/mtk-svs.c4
-rw-r--r--drivers/soc/qcom/Kconfig11
-rw-r--r--drivers/soc/qcom/Makefile1
-rw-r--r--drivers/soc/qcom/icc-bwmon.c2
-rw-r--r--drivers/soc/qcom/mdt_loader.c49
-rw-r--r--drivers/soc/qcom/ocmem.c10
-rw-r--r--drivers/soc/qcom/pmic_glink.c8
-rw-r--r--drivers/soc/qcom/pmic_glink_altmode.c5
-rw-r--r--drivers/soc/qcom/qcom-geni-se.c28
-rw-r--r--drivers/soc/qcom/qmi_interface.c2
-rw-r--r--drivers/soc/qcom/ramp_controller.c11
-rw-r--r--drivers/soc/qcom/rpm_master_stats.c163
-rw-r--r--drivers/soc/qcom/rpmpd.c4
-rw-r--r--drivers/soc/qcom/smem.c31
-rw-r--r--drivers/soc/qcom/socinfo.c111
-rw-r--r--drivers/soc/renesas/rcar-rst.c15
-rw-r--r--drivers/soc/renesas/rmobile-sysc.c29
-rw-r--r--drivers/soc/rockchip/dtpm.c54
-rw-r--r--drivers/soc/rockchip/pm_domains.c160
-rw-r--r--drivers/soc/samsung/exynos-pmu.c9
-rw-r--r--drivers/soc/samsung/exynos-pmu.h2
-rw-r--r--drivers/soc/samsung/exynos4-pmu.c13
-rw-r--r--drivers/soc/tegra/Kconfig1
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra30.c2
-rw-r--r--drivers/soc/tegra/fuse/tegra-apbmisc.c3
-rw-r--r--drivers/soc/tegra/pmc.c31
-rw-r--r--drivers/soc/ti/Kconfig2
-rw-r--r--drivers/soc/ti/pruss.c263
-rw-r--r--drivers/soc/ti/pruss.h88
-rw-r--r--drivers/soc/ti/smartreflex.c4
-rw-r--r--drivers/soc/ti/wkup_m3_ipc.c2
-rw-r--r--drivers/soc/xilinx/xlnx_event_manager.c6
-rw-r--r--drivers/soc/xilinx/zynqmp_power.c4
-rw-r--r--drivers/soundwire/Kconfig1
-rw-r--r--drivers/soundwire/Makefile3
-rw-r--r--drivers/soundwire/amd_manager.c9
-rw-r--r--drivers/soundwire/bus.c30
-rw-r--r--drivers/soundwire/cadence_master.c50
-rw-r--r--drivers/soundwire/cadence_master.h5
-rw-r--r--drivers/soundwire/debugfs.c12
-rw-r--r--drivers/soundwire/generic_bandwidth_allocation.c10
-rw-r--r--drivers/soundwire/intel.c57
-rw-r--r--drivers/soundwire/intel.h16
-rw-r--r--drivers/soundwire/intel_ace2x.c393
-rw-r--r--drivers/soundwire/intel_ace2x_debugfs.c147
-rw-r--r--drivers/soundwire/intel_auxdevice.c17
-rw-r--r--drivers/soundwire/intel_bus_common.c92
-rw-r--r--drivers/soundwire/intel_init.c21
-rw-r--r--drivers/soundwire/qcom.c496
-rw-r--r--drivers/soundwire/stream.c161
-rw-r--r--drivers/staging/axis-fifo/axis-fifo.c3
-rw-r--r--drivers/staging/iio/addac/adt7316-i2c.c2
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c2
-rw-r--r--drivers/staging/media/atomisp/Makefile1
-rw-r--r--drivers/staging/media/atomisp/TODO238
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-gc0310.c313
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-gc2235.c2
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-lm3554.c2
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c2
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-ov2680.c252
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-ov2722.c2
-rw-r--r--drivers/staging/media/atomisp/i2c/gc0310.h309
-rw-r--r--drivers/staging/media/atomisp/i2c/ov2680.h141
-rw-r--r--drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c42
-rw-r--r--drivers/staging/media/atomisp/include/linux/atomisp.h127
-rw-r--r--drivers/staging/media/atomisp/include/linux/atomisp_platform.h1
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp-regs.h1
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_cmd.c1034
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_cmd.h28
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_common.h4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat.h41
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat_css20.c283
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h55
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_csi2.c10
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_csi2.h94
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c874
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_drvfs.c2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_fops.c183
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_fops.h3
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c248
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_internal.h29
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_ioctl.c398
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_ioctl.h5
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_subdev.c262
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_subdev.h36
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_v4l2.c425
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_v4l2.h4
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h2
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c62
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css.c524
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_firmware.c33
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_mipi.c56
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_sp.c10
-rw-r--r--drivers/staging/media/av7110/av7110_av.c4
-rw-r--r--drivers/staging/media/imx/imx-media-utils.c2
-rw-r--r--drivers/staging/media/imx/imx6-mipi-csi2.c45
-rw-r--r--drivers/staging/media/max96712/max96712.c40
-rw-r--r--drivers/staging/media/tegra-video/Kconfig1
-rw-r--r--drivers/staging/media/tegra-video/Makefile2
-rw-r--r--drivers/staging/media/tegra-video/csi.c48
-rw-r--r--drivers/staging/media/tegra-video/csi.h4
-rw-r--r--drivers/staging/media/tegra-video/tegra20.c661
-rw-r--r--drivers/staging/media/tegra-video/tegra210.c90
-rw-r--r--drivers/staging/media/tegra-video/vi.c222
-rw-r--r--drivers/staging/media/tegra-video/vi.h71
-rw-r--r--drivers/staging/media/tegra-video/video.c5
-rw-r--r--drivers/staging/media/tegra-video/video.h2
-rw-r--r--drivers/staging/media/tegra-video/vip.c287
-rw-r--r--drivers/staging/media/tegra-video/vip.h68
-rw-r--r--drivers/staging/most/i2c/i2c.c2
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.c2
-rw-r--r--drivers/staging/pi433/pi433_if.c1
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/Kconfig1
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_def.h8
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c6
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c97
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h1
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c62
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h6
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_cam.c2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c82
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.h3
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.c168
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c4
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pm.c2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_ps.c20
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_wx.c73
-rw-r--r--drivers/staging/rtl8192e/rtl819x_HT.h67
-rw-r--r--drivers/staging/rtl8192e/rtl819x_HTProc.c12
-rw-r--r--drivers/staging/rtl8192e/rtl819x_Qos.h1
-rw-r--r--drivers/staging/rtl8192e/rtl819x_TS.h2
-rw-r--r--drivers/staging/rtl8192e/rtllib.h87
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c63
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac.c333
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac_wx.c85
-rw-r--r--drivers/staging/rtl8192e/rtllib_tx.c16
-rw-r--r--drivers/staging/rtl8192e/rtllib_wx.c31
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c5
-rw-r--r--drivers/staging/rtl8723bs/include/sta_info.h26
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c62
-rw-r--r--drivers/staging/rts5208/rtsx.c20
-rw-r--r--drivers/staging/sm750fb/Kconfig2
-rw-r--r--drivers/staging/sm750fb/sm750.c2
-rw-r--r--drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h2
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c4
-rw-r--r--drivers/staging/vt6655/Kconfig2
-rw-r--r--drivers/staging/wlan-ng/hfa384x.h21
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c21
-rw-r--r--drivers/staging/wlan-ng/p80211conv.c21
-rw-r--r--drivers/staging/wlan-ng/p80211conv.h21
-rw-r--r--drivers/staging/wlan-ng/p80211hdr.h21
-rw-r--r--drivers/staging/wlan-ng/p80211ioctl.h21
-rw-r--r--drivers/staging/wlan-ng/p80211metadef.h21
-rw-r--r--drivers/staging/wlan-ng/p80211metastruct.h39
-rw-r--r--drivers/staging/wlan-ng/p80211mgmt.h21
-rw-r--r--drivers/staging/wlan-ng/p80211msg.h21
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.c21
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.h21
-rw-r--r--drivers/staging/wlan-ng/p80211req.c21
-rw-r--r--drivers/staging/wlan-ng/p80211req.h21
-rw-r--r--drivers/staging/wlan-ng/p80211types.h21
-rw-r--r--drivers/staging/wlan-ng/p80211wep.c21
-rw-r--r--drivers/staging/wlan-ng/prism2fw.c21
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.c73
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.h21
-rw-r--r--drivers/staging/wlan-ng/prism2mib.c21
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c21
-rw-r--r--drivers/target/iscsi/iscsi_target_parameters.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c4
-rw-r--r--drivers/target/target_core_configfs.c10
-rw-r--r--drivers/target/target_core_device.c6
-rw-r--r--drivers/target/target_core_file.c4
-rw-r--r--drivers/target/target_core_iblock.c275
-rw-r--r--drivers/target/target_core_pr.c79
-rw-r--r--drivers/target/target_core_rd.c4
-rw-r--r--drivers/target/target_core_sbc.c13
-rw-r--r--drivers/target/target_core_spc.c113
-rw-r--r--drivers/tee/optee/smc_abi.c3
-rw-r--r--drivers/thunderbolt/Makefile2
-rw-r--r--drivers/thunderbolt/acpi.c5
-rw-r--r--drivers/thunderbolt/clx.c423
-rw-r--r--drivers/thunderbolt/ctl.c28
-rw-r--r--drivers/thunderbolt/debugfs.c64
-rw-r--r--drivers/thunderbolt/dma_test.c12
-rw-r--r--drivers/thunderbolt/eeprom.c3
-rw-r--r--drivers/thunderbolt/icm.c30
-rw-r--r--drivers/thunderbolt/nhi.c42
-rw-r--r--drivers/thunderbolt/nhi.h4
-rw-r--r--drivers/thunderbolt/nhi_regs.h19
-rw-r--r--drivers/thunderbolt/nvm.c4
-rw-r--r--drivers/thunderbolt/quirks.c10
-rw-r--r--drivers/thunderbolt/retimer.c64
-rw-r--r--drivers/thunderbolt/switch.c594
-rw-r--r--drivers/thunderbolt/tb.c329
-rw-r--r--drivers/thunderbolt/tb.h243
-rw-r--r--drivers/thunderbolt/tb_msgs.h7
-rw-r--r--drivers/thunderbolt/tb_regs.h25
-rw-r--r--drivers/thunderbolt/test.c83
-rw-r--r--drivers/thunderbolt/tmu.c713
-rw-r--r--drivers/thunderbolt/tunnel.c239
-rw-r--r--drivers/thunderbolt/usb4.c114
-rw-r--r--drivers/thunderbolt/xdomain.c98
-rw-r--r--drivers/tty/n_tty.c25
-rw-r--r--drivers/tty/serial/8250/8250.h11
-rw-r--r--drivers/tty/serial/8250/8250_aspeed_vuart.c3
-rw-r--r--drivers/tty/serial/8250/8250_bcm7271.c4
-rw-r--r--drivers/tty/serial/8250/8250_core.c91
-rw-r--r--drivers/tty/serial/8250/8250_early.c21
-rw-r--r--drivers/tty/serial/8250/8250_em.c4
-rw-r--r--drivers/tty/serial/8250/8250_exar.c4
-rw-r--r--drivers/tty/serial/8250/8250_fsl.c17
-rw-r--r--drivers/tty/serial/8250/8250_mtk.c59
-rw-r--r--drivers/tty/serial/8250/8250_of.c6
-rw-r--r--drivers/tty/serial/8250/8250_omap.c215
-rw-r--r--drivers/tty/serial/8250/8250_pci.c19
-rw-r--r--drivers/tty/serial/8250/8250_port.c167
-rw-r--r--drivers/tty/serial/8250/8250_pxa.c2
-rw-r--r--drivers/tty/serial/8250/8250_rt288x.c136
-rw-r--r--drivers/tty/serial/8250/8250_uniphier.c4
-rw-r--r--drivers/tty/serial/8250/Kconfig16
-rw-r--r--drivers/tty/serial/8250/Makefile1
-rw-r--r--drivers/tty/serial/Kconfig23
-rw-r--r--drivers/tty/serial/Makefile6
-rw-r--r--drivers/tty/serial/amba-pl011.c7
-rw-r--r--drivers/tty/serial/atmel_serial.c9
-rw-r--r--drivers/tty/serial/clps711x.c4
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_core.c5
-rw-r--r--drivers/tty/serial/fsl_lpuart.c57
-rw-r--r--drivers/tty/serial/imx.c22
-rw-r--r--drivers/tty/serial/lantiq.c4
-rw-r--r--drivers/tty/serial/ma35d1_serial.c821
-rw-r--r--drivers/tty/serial/max310x.c2
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c5
-rw-r--r--drivers/tty/serial/samsung_tty.c19
-rw-r--r--drivers/tty/serial/sc16is7xx.c2
-rw-r--r--drivers/tty/serial/serial_base.h46
-rw-r--r--drivers/tty/serial/serial_base_bus.c205
-rw-r--r--drivers/tty/serial/serial_core.c210
-rw-r--r--drivers/tty/serial/serial_ctrl.c68
-rw-r--r--drivers/tty/serial/serial_port.c105
-rw-r--r--drivers/tty/serial/st-asc.c6
-rw-r--r--drivers/tty/serial/stm32-usart.c5
-rw-r--r--drivers/tty/serial/uartlite.c12
-rw-r--r--drivers/tty/serial/xilinx_uartps.c5
-rw-r--r--drivers/tty/tty.h11
-rw-r--r--drivers/tty/tty_audit.c43
-rw-r--r--drivers/tty/tty_io.c31
-rw-r--r--drivers/ufs/core/ufs-fault-injection.c2
-rw-r--r--drivers/ufs/core/ufs-hwmon.c2
-rw-r--r--drivers/ufs/core/ufs-mcq.c296
-rw-r--r--drivers/ufs/core/ufs-sysfs.c35
-rw-r--r--drivers/ufs/core/ufshcd-crypto.c2
-rw-r--r--drivers/ufs/core/ufshcd-priv.h27
-rw-r--r--drivers/ufs/core/ufshcd.c471
-rw-r--r--drivers/ufs/core/ufshpb.c6
-rw-r--r--drivers/ufs/core/ufshpb.h2
-rw-r--r--drivers/ufs/host/Kconfig2
-rw-r--r--drivers/ufs/host/Makefile4
-rw-r--r--drivers/ufs/host/cdns-pltfrm.c1
-rw-r--r--drivers/ufs/host/tc-dwc-g210-pci.c10
-rw-r--r--drivers/ufs/host/tc-dwc-g210-pltfrm.c1
-rw-r--r--drivers/ufs/host/ufs-exynos.c3
-rw-r--r--drivers/ufs/host/ufs-hisi.c25
-rw-r--r--drivers/ufs/host/ufs-mediatek.c6
-rw-r--r--drivers/ufs/host/ufs-qcom-ice.c244
-rw-r--r--drivers/ufs/host/ufs-qcom.c102
-rw-r--r--drivers/ufs/host/ufs-qcom.h32
-rw-r--r--drivers/ufs/host/ufs-sprd.c1
-rw-r--r--drivers/ufs/host/ufshcd-pci.c11
-rw-r--r--drivers/ufs/host/ufshcd-pltfrm.c6
-rw-r--r--drivers/ufs/host/ufshcd-pltfrm.h1
-rw-r--r--drivers/uio/uio_dfl.c2
-rw-r--r--drivers/usb/c67x00/c67x00-drv.c6
-rw-r--r--drivers/usb/cdns3/Kconfig11
-rw-r--r--drivers/usb/cdns3/Makefile1
-rw-r--r--drivers/usb/cdns3/cdns3-gadget.c15
-rw-r--r--drivers/usb/cdns3/cdns3-imx.c30
-rw-r--r--drivers/usb/cdns3/cdns3-plat.c5
-rw-r--r--drivers/usb/cdns3/cdns3-starfive.c246
-rw-r--r--drivers/usb/cdns3/cdns3-ti.c6
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c11
-rw-r--r--drivers/usb/chipidea/ci_hdrc_msm.c6
-rw-r--r--drivers/usb/chipidea/ci_hdrc_tegra.c6
-rw-r--r--drivers/usb/chipidea/ci_hdrc_usb2.c6
-rw-r--r--drivers/usb/chipidea/core.c6
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c38
-rw-r--r--drivers/usb/common/led.c4
-rw-r--r--drivers/usb/common/usb-conn-gpio.c6
-rw-r--r--drivers/usb/core/devio.c18
-rw-r--r--drivers/usb/core/hcd-pci.c24
-rw-r--r--drivers/usb/core/hub.c15
-rw-r--r--drivers/usb/core/hub.h4
-rw-r--r--drivers/usb/core/port.c32
-rw-r--r--drivers/usb/dwc2/params.c21
-rw-r--r--drivers/usb/dwc2/platform.c22
-rw-r--r--drivers/usb/dwc3/core.c17
-rw-r--r--drivers/usb/dwc3/core.h2
-rw-r--r--drivers/usb/dwc3/dwc3-am62.c5
-rw-r--r--drivers/usb/dwc3/dwc3-exynos.c6
-rw-r--r--drivers/usb/dwc3/dwc3-imx8mp.c6
-rw-r--r--drivers/usb/dwc3/dwc3-keystone.c6
-rw-r--r--drivers/usb/dwc3/dwc3-meson-g12a.c27
-rw-r--r--drivers/usb/dwc3/dwc3-of-simple.c6
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c6
-rw-r--r--drivers/usb/dwc3/dwc3-qcom.c43
-rw-r--r--drivers/usb/dwc3/dwc3-st.c6
-rw-r--r--drivers/usb/dwc3/dwc3-xilinx.c6
-rw-r--r--drivers/usb/dwc3/ep0.c3
-rw-r--r--drivers/usb/dwc3/gadget.c13
-rw-r--r--drivers/usb/fotg210/fotg210-core.c6
-rw-r--r--drivers/usb/gadget/function/f_hid.c21
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c8
-rw-r--r--drivers/usb/gadget/function/f_printer.c29
-rw-r--r--drivers/usb/gadget/function/u_serial.c22
-rw-r--r--drivers/usb/gadget/function/uvc_video.c50
-rw-r--r--drivers/usb/gadget/legacy/g_ffs.c4
-rw-r--r--drivers/usb/gadget/legacy/hid.c6
-rw-r--r--drivers/usb/gadget/udc/Kconfig2
-rw-r--r--drivers/usb/gadget/udc/Makefile1
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/core.c8
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.c6
-rw-r--r--drivers/usb/gadget/udc/bcm63xx_udc.c6
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_core.c5
-rw-r--r--drivers/usb/gadget/udc/cdns2/Kconfig11
-rw-r--r--drivers/usb/gadget/udc/cdns2/Makefile7
-rw-r--r--drivers/usb/gadget/udc/cdns2/cdns2-debug.h203
-rw-r--r--drivers/usb/gadget/udc/cdns2/cdns2-ep0.c659
-rw-r--r--drivers/usb/gadget/udc/cdns2/cdns2-gadget.c2474
-rw-r--r--drivers/usb/gadget/udc/cdns2/cdns2-gadget.h707
-rw-r--r--drivers/usb/gadget/udc/cdns2/cdns2-pci.c138
-rw-r--r--drivers/usb/gadget/udc/cdns2/cdns2-trace.c11
-rw-r--r--drivers/usb/gadget/udc/cdns2/cdns2-trace.h605
-rw-r--r--drivers/usb/gadget/udc/core.c24
-rw-r--r--drivers/usb/gadget/udc/dummy_hcd.c11
-rw-r--r--drivers/usb/gadget/udc/fsl_qe_udc.c6
-rw-r--r--drivers/usb/gadget/udc/fusb300_udc.c6
-rw-r--r--drivers/usb/gadget/udc/m66592-udc.c5
-rw-r--r--drivers/usb/gadget/udc/mv_u3d_core.c6
-rw-r--r--drivers/usb/gadget/udc/mv_udc_core.c6
-rw-r--r--drivers/usb/gadget/udc/net2272.c6
-rw-r--r--drivers/usb/gadget/udc/omap_udc.c6
-rw-r--r--drivers/usb/gadget/udc/pxa27x_udc.c12
-rw-r--r--drivers/usb/gadget/udc/r8a66597-udc.c6
-rw-r--r--drivers/usb/gadget/udc/renesas_usb3.c6
-rw-r--r--drivers/usb/gadget/udc/renesas_usbf.c6
-rw-r--r--drivers/usb/gadget/udc/rzv2m_usb3drd.c6
-rw-r--r--drivers/usb/gadget/udc/snps_udc_plat.c8
-rw-r--r--drivers/usb/gadget/udc/tegra-xudc.c6
-rw-r--r--drivers/usb/gadget/udc/udc-xilinx.c8
-rw-r--r--drivers/usb/host/Kconfig4
-rw-r--r--drivers/usb/host/ehci-atmel.c6
-rw-r--r--drivers/usb/host/ehci-brcm.c5
-rw-r--r--drivers/usb/host/ehci-exynos.c6
-rw-r--r--drivers/usb/host/ehci-fsl.c6
-rw-r--r--drivers/usb/host/ehci-grlib.c6
-rw-r--r--drivers/usb/host/ehci-mv.c6
-rw-r--r--drivers/usb/host/ehci-npcm7xx.c6
-rw-r--r--drivers/usb/host/ehci-omap.c6
-rw-r--r--drivers/usb/host/ehci-orion.c6
-rw-r--r--drivers/usb/host/ehci-pci.c3
-rw-r--r--drivers/usb/host/ehci-platform.c6
-rw-r--r--drivers/usb/host/ehci-ppc-of.c6
-rw-r--r--drivers/usb/host/ehci-sh.c6
-rw-r--r--drivers/usb/host/ehci-spear.c6
-rw-r--r--drivers/usb/host/ehci-st.c6
-rw-r--r--drivers/usb/host/ehci-xilinx-of.c6
-rw-r--r--drivers/usb/host/fhci-hcd.c9
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c5
-rw-r--r--drivers/usb/host/isp116x-hcd.c7
-rw-r--r--drivers/usb/host/isp1362-hcd.c6
-rw-r--r--drivers/usb/host/octeon-hcd.c6
-rw-r--r--drivers/usb/host/ohci-at91.c5
-rw-r--r--drivers/usb/host/ohci-da8xx.c6
-rw-r--r--drivers/usb/host/ohci-exynos.c6
-rw-r--r--drivers/usb/host/ohci-nxp.c6
-rw-r--r--drivers/usb/host/ohci-omap.c5
-rw-r--r--drivers/usb/host/ohci-pci.c8
-rw-r--r--drivers/usb/host/ohci-platform.c8
-rw-r--r--drivers/usb/host/ohci-ppc-of.c6
-rw-r--r--drivers/usb/host/ohci-pxa27x.c12
-rw-r--r--drivers/usb/host/ohci-s3c2410.c5
-rw-r--r--drivers/usb/host/ohci-sm501.c6
-rw-r--r--drivers/usb/host/ohci-spear.c5
-rw-r--r--drivers/usb/host/ohci-st.c6
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c6
-rw-r--r--drivers/usb/host/r8a66597-hcd.c5
-rw-r--r--drivers/usb/host/sl811-hcd.c5
-rw-r--r--drivers/usb/host/uhci-grlib.c6
-rw-r--r--drivers/usb/host/uhci-hcd.c2
-rw-r--r--drivers/usb/host/uhci-hcd.h24
-rw-r--r--drivers/usb/host/uhci-pci.c7
-rw-r--r--drivers/usb/host/uhci-platform.c6
-rw-r--r--drivers/usb/host/xhci-histb.c20
-rw-r--r--drivers/usb/host/xhci-mem.c132
-rw-r--r--drivers/usb/host/xhci-mtk.c12
-rw-r--r--drivers/usb/host/xhci-pci.c24
-rw-r--r--drivers/usb/host/xhci-plat.c23
-rw-r--r--drivers/usb/host/xhci-plat.h2
-rw-r--r--drivers/usb/host/xhci-rcar.c6
-rw-r--r--drivers/usb/host/xhci-ring.c137
-rw-r--r--drivers/usb/host/xhci-tegra.c12
-rw-r--r--drivers/usb/host/xhci-trace.h9
-rw-r--r--drivers/usb/host/xhci.c56
-rw-r--r--drivers/usb/host/xhci.h9
-rw-r--r--drivers/usb/isp1760/isp1760-if.c6
-rw-r--r--drivers/usb/misc/onboard_usb_hub.c6
-rw-r--r--drivers/usb/misc/qcom_eud.c10
-rw-r--r--drivers/usb/misc/usb251xb.c11
-rw-r--r--drivers/usb/misc/usb3503.c8
-rw-r--r--drivers/usb/misc/usb4604.c2
-rw-r--r--drivers/usb/mon/mon_bin.c19
-rw-r--r--drivers/usb/musb/musb_core.c1
-rw-r--r--drivers/usb/musb/musb_core.h2
-rw-r--r--drivers/usb/musb/tusb6010.c53
-rw-r--r--drivers/usb/phy/phy-isp1301.c2
-rw-r--r--drivers/usb/phy/phy-tahvo.c2
-rw-r--r--drivers/usb/renesas_usbhs/common.c6
-rw-r--r--drivers/usb/roles/class.c17
-rw-r--r--drivers/usb/roles/intel-xhci-usb-role-switch.c6
-rw-r--r--drivers/usb/serial/ark3116.c7
-rw-r--r--drivers/usb/serial/belkin_sa.c12
-rw-r--r--drivers/usb/serial/ch341.c37
-rw-r--r--drivers/usb/serial/cp210x.c14
-rw-r--r--drivers/usb/serial/digi_acceleport.c7
-rw-r--r--drivers/usb/serial/f81232.c4
-rw-r--r--drivers/usb/serial/f81534.c4
-rw-r--r--drivers/usb/serial/ftdi_sio.c10
-rw-r--r--drivers/usb/serial/io_edgeport.c6
-rw-r--r--drivers/usb/serial/io_ti.c9
-rw-r--r--drivers/usb/serial/keyspan.c5
-rw-r--r--drivers/usb/serial/keyspan_pda.c8
-rw-r--r--drivers/usb/serial/mct_u232.c6
-rw-r--r--drivers/usb/serial/mos7720.c9
-rw-r--r--drivers/usb/serial/mos7840.c7
-rw-r--r--drivers/usb/serial/mxuport.c6
-rw-r--r--drivers/usb/serial/option.c4
-rw-r--r--drivers/usb/serial/pl2303.c14
-rw-r--r--drivers/usb/serial/quatech2.c8
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c10
-rw-r--r--drivers/usb/serial/upd78f0730.c7
-rw-r--r--drivers/usb/serial/usb-serial.c4
-rw-r--r--drivers/usb/serial/usb_debug.c13
-rw-r--r--drivers/usb/serial/whiteheat.c7
-rw-r--r--drivers/usb/serial/xr_serial.c4
-rw-r--r--drivers/usb/typec/Kconfig13
-rw-r--r--drivers/usb/typec/Makefile1
-rw-r--r--drivers/usb/typec/anx7411.c2
-rw-r--r--drivers/usb/typec/class.c4
-rw-r--r--drivers/usb/typec/hd3ss3220.c4
-rw-r--r--drivers/usb/typec/mux.c61
-rw-r--r--drivers/usb/typec/mux/Kconfig10
-rw-r--r--drivers/usb/typec/mux/Makefile1
-rw-r--r--drivers/usb/typec/mux/fsa4480.c128
-rw-r--r--drivers/usb/typec/mux/gpio-sbu-mux.c11
-rw-r--r--drivers/usb/typec/mux/intel_pmc_mux.c56
-rw-r--r--drivers/usb/typec/mux/nb7vpq904m.c529
-rw-r--r--drivers/usb/typec/mux/pi3usb30532.c2
-rw-r--r--drivers/usb/typec/qcom-pmic-typec.c261
-rw-r--r--drivers/usb/typec/rt1719.c2
-rw-r--r--drivers/usb/typec/stusb160x.c2
-rw-r--r--drivers/usb/typec/tcpm/Kconfig11
-rw-r--r--drivers/usb/typec/tcpm/Makefile1
-rw-r--r--drivers/usb/typec/tcpm/fusb302.c2
-rw-r--r--drivers/usb/typec/tcpm/qcom/Makefile6
-rw-r--r--drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c344
-rw-r--r--drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c528
-rw-r--r--drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h119
-rw-r--r--drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c556
-rw-r--r--drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h195
-rw-r--r--drivers/usb/typec/tcpm/tcpci.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpci_maxim_core.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpci_mt6360.c5
-rw-r--r--drivers/usb/typec/tcpm/tcpci_mt6370.c6
-rw-r--r--drivers/usb/typec/tcpm/tcpci_rt1711h.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpm.c27
-rw-r--r--drivers/usb/typec/tcpm/wcove.c6
-rw-r--r--drivers/usb/typec/tipd/core.c2
-rw-r--r--drivers/usb/typec/ucsi/psy.c14
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c17
-rw-r--r--drivers/usb/typec/ucsi/ucsi_acpi.c6
-rw-r--r--drivers/usb/typec/ucsi/ucsi_ccg.c2
-rw-r--r--drivers/usb/typec/ucsi/ucsi_glink.c2
-rw-r--r--drivers/usb/typec/ucsi/ucsi_stm32g0.c2
-rw-r--r--drivers/usb/typec/wusb3801.c2
-rw-r--r--drivers/usb/usbip/stub_main.c4
-rw-r--r--drivers/usb/usbip/vhci_hcd.c6
-rw-r--r--drivers/vdpa/Kconfig10
-rw-r--r--drivers/vdpa/Makefile1
-rw-r--r--drivers/vdpa/ifcvf/ifcvf_base.c201
-rw-r--r--drivers/vdpa/ifcvf/ifcvf_base.h48
-rw-r--r--drivers/vdpa/ifcvf/ifcvf_main.c108
-rw-r--r--drivers/vdpa/mlx5/net/mlx5_vnet.c165
-rw-r--r--drivers/vdpa/mlx5/net/mlx5_vnet.h15
-rw-r--r--drivers/vdpa/pds/Makefile10
-rw-r--r--drivers/vdpa/pds/aux_drv.c140
-rw-r--r--drivers/vdpa/pds/aux_drv.h26
-rw-r--r--drivers/vdpa/pds/cmds.c185
-rw-r--r--drivers/vdpa/pds/cmds.h18
-rw-r--r--drivers/vdpa/pds/debugfs.c289
-rw-r--r--drivers/vdpa/pds/debugfs.h17
-rw-r--r--drivers/vdpa/pds/vdpa_dev.c769
-rw-r--r--drivers/vdpa/pds/vdpa_dev.h49
-rw-r--r--drivers/vdpa/solidrun/snet_ctrl.c6
-rw-r--r--drivers/vdpa/solidrun/snet_hwmon.c2
-rw-r--r--drivers/vdpa/solidrun/snet_main.c15
-rw-r--r--drivers/vdpa/solidrun/snet_vdpa.h1
-rw-r--r--drivers/vdpa/vdpa_user/vduse_dev.c6
-rw-r--r--drivers/vfio/Kconfig1
-rw-r--r--drivers/vfio/Makefile5
-rw-r--r--drivers/vfio/cdx/Kconfig17
-rw-r--r--drivers/vfio/cdx/Makefile8
-rw-r--r--drivers/vfio/cdx/main.c234
-rw-r--r--drivers/vfio/cdx/private.h28
-rw-r--r--drivers/vfio/fsl-mc/Kconfig6
-rw-r--r--drivers/vfio/fsl-mc/vfio_fsl_mc.c3
-rw-r--r--drivers/vfio/mdev/mdev_core.c23
-rw-r--r--drivers/vfio/pci/Kconfig8
-rw-r--r--drivers/vfio/pci/hisilicon/Kconfig4
-rw-r--r--drivers/vfio/pci/mlx5/Kconfig2
-rw-r--r--drivers/vfio/pci/vfio_pci_config.c8
-rw-r--r--drivers/vfio/pci/vfio_pci_core.c46
-rw-r--r--drivers/vfio/pci/vfio_pci_intrs.c305
-rw-r--r--drivers/vfio/platform/Kconfig18
-rw-r--r--drivers/vfio/platform/Makefile9
-rw-r--r--drivers/vfio/platform/reset/Kconfig2
-rw-r--r--drivers/vhost/net.c8
-rw-r--r--drivers/vhost/scsi.c103
-rw-r--r--drivers/vhost/vhost.c419
-rw-r--r--drivers/vhost/vhost.h24
-rw-r--r--drivers/vhost/vsock.c4
-rw-r--r--drivers/video/Kconfig7
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/aperture.c70
-rw-r--r--drivers/video/backlight/adp8860_bl.c4
-rw-r--r--drivers/video/backlight/adp8870_bl.c4
-rw-r--r--drivers/video/backlight/arcxcnn_bl.c2
-rw-r--r--drivers/video/backlight/bd6107.c2
-rw-r--r--drivers/video/backlight/ktz8866.c2
-rw-r--r--drivers/video/backlight/led_bl.c5
-rw-r--r--drivers/video/backlight/lm3630a_bl.c10
-rw-r--r--drivers/video/backlight/lm3639_bl.c2
-rw-r--r--drivers/video/backlight/lp855x_bl.c50
-rw-r--r--drivers/video/backlight/lv5207lp.c2
-rw-r--r--drivers/video/backlight/pwm_bl.c9
-rw-r--r--drivers/video/console/Kconfig1
-rw-r--r--drivers/video/console/Makefile4
-rw-r--r--drivers/video/console/sticon.c6
-rw-r--r--drivers/video/fbdev/Kconfig24
-rw-r--r--drivers/video/fbdev/arcfb.c12
-rw-r--r--drivers/video/fbdev/aty/atyfb.h2
-rw-r--r--drivers/video/fbdev/aty/mach64_cursor.c2
-rw-r--r--drivers/video/fbdev/au1200fb.c2
-rw-r--r--drivers/video/fbdev/broadsheetfb.c18
-rw-r--r--drivers/video/fbdev/chipsfb.c2
-rw-r--r--drivers/video/fbdev/cobalt_lcdfb.c6
-rw-r--r--drivers/video/fbdev/core/Makefile2
-rw-r--r--drivers/video/fbdev/core/fb_io_fops.c133
-rw-r--r--drivers/video/fbdev/core/fb_sys_fops.c36
-rw-r--r--drivers/video/fbdev/core/fbcon.c1
-rw-r--r--drivers/video/fbdev/core/fbmem.c113
-rw-r--r--drivers/video/fbdev/core/sysimgblt.c2
-rw-r--r--drivers/video/fbdev/hecubafb.c12
-rw-r--r--drivers/video/fbdev/hitfb.c130
-rw-r--r--drivers/video/fbdev/hyperv_fb.c2
-rw-r--r--drivers/video/fbdev/kyro/fbdev.c2
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_accel.c6
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_base.h4
-rw-r--r--drivers/video/fbdev/metronomefb.c18
-rw-r--r--drivers/video/fbdev/omap/lcd_mipid.c16
-rw-r--r--drivers/video/fbdev/ps3fb.c4
-rw-r--r--drivers/video/fbdev/pvr2fb.c5
-rw-r--r--drivers/video/fbdev/sh7760fb.c2
-rw-r--r--drivers/video/fbdev/sh_mobile_lcdcfb.c2
-rw-r--r--drivers/video/fbdev/sm712fb.c10
-rw-r--r--drivers/video/fbdev/smscufx.c14
-rw-r--r--drivers/video/fbdev/ssd1307fb.c3
-rw-r--r--drivers/video/fbdev/sstfb.c2
-rw-r--r--drivers/video/fbdev/sticore.h404
-rw-r--r--drivers/video/fbdev/stifb.c10
-rw-r--r--drivers/video/fbdev/tdfxfb.c2
-rw-r--r--drivers/video/fbdev/udlfb.c12
-rw-r--r--drivers/video/fbdev/vfb.c2
-rw-r--r--drivers/video/fbdev/via/via-core.c2
-rw-r--r--drivers/video/fbdev/via/via-gpio.c28
-rw-r--r--drivers/video/fbdev/via/via-gpio.h13
-rw-r--r--drivers/video/fbdev/wmt_ge_rops.c2
-rw-r--r--drivers/video/fbdev/xen-fbfront.c2
-rw-r--r--drivers/video/sticore.c (renamed from drivers/video/console/sticore.c)284
-rw-r--r--drivers/virtio/virtio_pci_common.h7
-rw-r--r--drivers/virtio/virtio_pci_modern_dev.c33
-rw-r--r--drivers/virtio/virtio_vdpa.c4
-rw-r--r--drivers/w1/masters/sgi_w1.c2
-rw-r--r--drivers/w1/slaves/Kconfig4
-rw-r--r--drivers/w1/slaves/w1_ds2438.c2
-rw-r--r--drivers/w1/slaves/w1_therm.c37
-rw-r--r--drivers/w1/w1.c55
4115 files changed, 188059 insertions, 57658 deletions
diff --git a/drivers/accel/habanalabs/common/command_buffer.c b/drivers/accel/habanalabs/common/command_buffer.c
index 6e09f48750a0..08f7aee42624 100644
--- a/drivers/accel/habanalabs/common/command_buffer.c
+++ b/drivers/accel/habanalabs/common/command_buffer.c
@@ -27,12 +27,6 @@ static int cb_map_mem(struct hl_ctx *ctx, struct hl_cb *cb)
return -EINVAL;
}
- if (!hdev->mmu_enable) {
- dev_err_ratelimited(hdev->dev,
- "Cannot map CB because MMU is disabled\n");
- return -EINVAL;
- }
-
if (cb->is_mmu_mapped)
return 0;
diff --git a/drivers/accel/habanalabs/common/command_submission.c b/drivers/accel/habanalabs/common/command_submission.c
index af9d2e22c6e7..c23829dab97a 100644
--- a/drivers/accel/habanalabs/common/command_submission.c
+++ b/drivers/accel/habanalabs/common/command_submission.c
@@ -280,14 +280,8 @@ bool cs_needs_timeout(struct hl_cs *cs)
static bool is_cb_patched(struct hl_device *hdev, struct hl_cs_job *job)
{
- /*
- * Patched CB is created for external queues jobs, and for H/W queues
- * jobs if the user CB was allocated by driver and MMU is disabled.
- */
- return (job->queue_type == QUEUE_TYPE_EXT ||
- (job->queue_type == QUEUE_TYPE_HW &&
- job->is_kernel_allocated_cb &&
- !hdev->mmu_enable));
+ /* Patched CB is created for external queues jobs */
+ return (job->queue_type == QUEUE_TYPE_EXT);
}
/*
@@ -363,14 +357,13 @@ static void hl_complete_job(struct hl_device *hdev, struct hl_cs_job *job)
}
}
- /* For H/W queue jobs, if a user CB was allocated by driver and MMU is
- * enabled, the user CB isn't released in cs_parser() and thus should be
+ /* For H/W queue jobs, if a user CB was allocated by driver,
+ * the user CB isn't released in cs_parser() and thus should be
* released here. This is also true for INT queues jobs which were
* allocated by driver.
*/
- if ((job->is_kernel_allocated_cb &&
- ((job->queue_type == QUEUE_TYPE_HW && hdev->mmu_enable) ||
- job->queue_type == QUEUE_TYPE_INT))) {
+ if (job->is_kernel_allocated_cb &&
+ (job->queue_type == QUEUE_TYPE_HW || job->queue_type == QUEUE_TYPE_INT)) {
atomic_dec(&job->user_cb->cs_cnt);
hl_cb_put(job->user_cb);
}
@@ -804,12 +797,14 @@ out:
static void cs_timedout(struct work_struct *work)
{
+ struct hl_cs *cs = container_of(work, struct hl_cs, work_tdr.work);
+ bool skip_reset_on_timeout, device_reset = false;
struct hl_device *hdev;
u64 event_mask = 0x0;
+ uint timeout_sec;
int rc;
- struct hl_cs *cs = container_of(work, struct hl_cs,
- work_tdr.work);
- bool skip_reset_on_timeout = cs->skip_reset_on_timeout, device_reset = false;
+
+ skip_reset_on_timeout = cs->skip_reset_on_timeout;
rc = cs_get_unless_zero(cs);
if (!rc)
@@ -840,29 +835,31 @@ static void cs_timedout(struct work_struct *work)
event_mask |= HL_NOTIFIER_EVENT_CS_TIMEOUT;
}
+ timeout_sec = jiffies_to_msecs(hdev->timeout_jiffies) / 1000;
+
switch (cs->type) {
case CS_TYPE_SIGNAL:
dev_err(hdev->dev,
- "Signal command submission %llu has not finished in time!\n",
- cs->sequence);
+ "Signal command submission %llu has not finished in %u seconds!\n",
+ cs->sequence, timeout_sec);
break;
case CS_TYPE_WAIT:
dev_err(hdev->dev,
- "Wait command submission %llu has not finished in time!\n",
- cs->sequence);
+ "Wait command submission %llu has not finished in %u seconds!\n",
+ cs->sequence, timeout_sec);
break;
case CS_TYPE_COLLECTIVE_WAIT:
dev_err(hdev->dev,
- "Collective Wait command submission %llu has not finished in time!\n",
- cs->sequence);
+ "Collective Wait command submission %llu has not finished in %u seconds!\n",
+ cs->sequence, timeout_sec);
break;
default:
dev_err(hdev->dev,
- "Command submission %llu has not finished in time!\n",
- cs->sequence);
+ "Command submission %llu has not finished in %u seconds!\n",
+ cs->sequence, timeout_sec);
break;
}
@@ -1139,11 +1136,10 @@ static void force_complete_cs(struct hl_device *hdev)
spin_unlock(&hdev->cs_mirror_lock);
}
-void hl_abort_waitings_for_completion(struct hl_device *hdev)
+void hl_abort_waiting_for_cs_completions(struct hl_device *hdev)
{
force_complete_cs(hdev);
force_complete_multi_cs(hdev);
- hl_release_pending_user_interrupts(hdev);
}
static void job_wq_completion(struct work_struct *work)
@@ -1948,8 +1944,7 @@ static int cs_ioctl_signal_wait_create_jobs(struct hl_device *hdev,
else
cb_size = hdev->asic_funcs->get_signal_cb_size(hdev);
- cb = hl_cb_kernel_create(hdev, cb_size,
- q_type == QUEUE_TYPE_HW && hdev->mmu_enable);
+ cb = hl_cb_kernel_create(hdev, cb_size, q_type == QUEUE_TYPE_HW);
if (!cb) {
atomic64_inc(&ctx->cs_counters.out_of_mem_drop_cnt);
atomic64_inc(&cntr->out_of_mem_drop_cnt);
@@ -2152,7 +2147,7 @@ static int cs_ioctl_unreserve_signals(struct hl_fpriv *hpriv, u32 handle_id)
hdev->asic_funcs->hw_queues_unlock(hdev);
rc = -EINVAL;
- goto out;
+ goto out_unlock;
}
/*
@@ -2167,15 +2162,21 @@ static int cs_ioctl_unreserve_signals(struct hl_fpriv *hpriv, u32 handle_id)
/* Release the id and free allocated memory of the handle */
idr_remove(&mgr->handles, handle_id);
+
+ /* unlock before calling ctx_put, where we might sleep */
+ spin_unlock(&mgr->lock);
hl_ctx_put(encaps_sig_hdl->ctx);
kfree(encaps_sig_hdl);
+ goto out;
} else {
rc = -EINVAL;
dev_err(hdev->dev, "failed to unreserve signals, cannot find handler\n");
}
-out:
+
+out_unlock:
spin_unlock(&mgr->lock);
+out:
return rc;
}
diff --git a/drivers/accel/habanalabs/common/debugfs.c b/drivers/accel/habanalabs/common/debugfs.c
index 22dd17c077c0..9e84a47a21dc 100644
--- a/drivers/accel/habanalabs/common/debugfs.c
+++ b/drivers/accel/habanalabs/common/debugfs.c
@@ -255,9 +255,6 @@ static int vm_show(struct seq_file *s, void *data)
u64 j;
int i;
- if (!dev_entry->hdev->mmu_enable)
- return 0;
-
mutex_lock(&dev_entry->ctx_mem_hash_mutex);
list_for_each_entry(ctx, &dev_entry->ctx_mem_hash_list, debugfs_list) {
@@ -436,9 +433,6 @@ static int mmu_show(struct seq_file *s, void *data)
u64 virt_addr = dev_entry->mmu_addr, phys_addr;
int i;
- if (!hdev->mmu_enable)
- return 0;
-
if (dev_entry->mmu_asid == HL_KERNEL_ASID_ID)
ctx = hdev->kernel_ctx;
else
@@ -496,9 +490,6 @@ static ssize_t mmu_asid_va_write(struct file *file, const char __user *buf,
char *c;
ssize_t rc;
- if (!hdev->mmu_enable)
- return count;
-
if (count > sizeof(kbuf) - 1)
goto err;
if (copy_from_user(kbuf, buf, count))
@@ -535,9 +526,6 @@ static int mmu_ack_error(struct seq_file *s, void *data)
struct hl_device *hdev = dev_entry->hdev;
int rc;
- if (!hdev->mmu_enable)
- return 0;
-
if (!dev_entry->mmu_cap_mask) {
dev_err(hdev->dev, "mmu_cap_mask is not set\n");
goto err;
@@ -563,9 +551,6 @@ static ssize_t mmu_ack_error_value_write(struct file *file,
char kbuf[MMU_KBUF_SIZE];
ssize_t rc;
- if (!hdev->mmu_enable)
- return count;
-
if (count > sizeof(kbuf) - 1)
goto err;
@@ -661,9 +646,6 @@ static bool hl_is_device_va(struct hl_device *hdev, u64 addr)
{
struct asic_fixed_properties *prop = &hdev->asic_prop;
- if (!hdev->mmu_enable)
- goto out;
-
if (prop->dram_supports_virtual_memory &&
(addr >= prop->dmmu.start_addr && addr < prop->dmmu.end_addr))
return true;
@@ -675,7 +657,7 @@ static bool hl_is_device_va(struct hl_device *hdev, u64 addr)
if (addr >= prop->pmmu_huge.start_addr &&
addr < prop->pmmu_huge.end_addr)
return true;
-out:
+
return false;
}
@@ -685,9 +667,6 @@ static bool hl_is_device_internal_memory_va(struct hl_device *hdev, u64 addr,
struct asic_fixed_properties *prop = &hdev->asic_prop;
u64 dram_start_addr, dram_end_addr;
- if (!hdev->mmu_enable)
- return false;
-
if (prop->dram_supports_virtual_memory) {
dram_start_addr = prop->dmmu.start_addr;
dram_end_addr = prop->dmmu.end_addr;
@@ -1756,17 +1735,15 @@ static void add_files_to_device(struct hl_device *hdev, struct hl_dbg_device_ent
}
}
-void hl_debugfs_add_device(struct hl_device *hdev)
+int hl_debugfs_device_init(struct hl_device *hdev)
{
struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
int count = ARRAY_SIZE(hl_debugfs_list);
dev_entry->hdev = hdev;
- dev_entry->entry_arr = kmalloc_array(count,
- sizeof(struct hl_debugfs_entry),
- GFP_KERNEL);
+ dev_entry->entry_arr = kmalloc_array(count, sizeof(struct hl_debugfs_entry), GFP_KERNEL);
if (!dev_entry->entry_arr)
- return;
+ return -ENOMEM;
dev_entry->data_dma_blob_desc.size = 0;
dev_entry->data_dma_blob_desc.data = NULL;
@@ -1787,21 +1764,14 @@ void hl_debugfs_add_device(struct hl_device *hdev)
spin_lock_init(&dev_entry->userptr_spinlock);
mutex_init(&dev_entry->ctx_mem_hash_mutex);
- dev_entry->root = debugfs_create_dir(dev_name(hdev->dev),
- hl_debug_root);
-
- add_files_to_device(hdev, dev_entry, dev_entry->root);
- if (!hdev->asic_prop.fw_security_enabled)
- add_secured_nodes(dev_entry, dev_entry->root);
+ return 0;
}
-void hl_debugfs_remove_device(struct hl_device *hdev)
+void hl_debugfs_device_fini(struct hl_device *hdev)
{
struct hl_dbg_device_entry *entry = &hdev->hl_debugfs;
int i;
- debugfs_remove_recursive(entry->root);
-
mutex_destroy(&entry->ctx_mem_hash_mutex);
mutex_destroy(&entry->file_mutex);
@@ -1814,6 +1784,24 @@ void hl_debugfs_remove_device(struct hl_device *hdev)
kfree(entry->entry_arr);
}
+void hl_debugfs_add_device(struct hl_device *hdev)
+{
+ struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
+
+ dev_entry->root = debugfs_create_dir(dev_name(hdev->dev), hl_debug_root);
+
+ add_files_to_device(hdev, dev_entry, dev_entry->root);
+ if (!hdev->asic_prop.fw_security_enabled)
+ add_secured_nodes(dev_entry, dev_entry->root);
+}
+
+void hl_debugfs_remove_device(struct hl_device *hdev)
+{
+ struct hl_dbg_device_entry *entry = &hdev->hl_debugfs;
+
+ debugfs_remove_recursive(entry->root);
+}
+
void hl_debugfs_add_file(struct hl_fpriv *hpriv)
{
struct hl_dbg_device_entry *dev_entry = &hpriv->hdev->hl_debugfs;
diff --git a/drivers/accel/habanalabs/common/device.c b/drivers/accel/habanalabs/common/device.c
index fabfc501ef54..b97339d1f7c6 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -674,7 +674,7 @@ static int device_init_cdev(struct hl_device *hdev, struct class *class,
return 0;
}
-static int device_cdev_sysfs_add(struct hl_device *hdev)
+static int cdev_sysfs_debugfs_add(struct hl_device *hdev)
{
int rc;
@@ -699,7 +699,9 @@ static int device_cdev_sysfs_add(struct hl_device *hdev)
goto delete_ctrl_cdev_device;
}
- hdev->cdev_sysfs_created = true;
+ hl_debugfs_add_device(hdev);
+
+ hdev->cdev_sysfs_debugfs_created = true;
return 0;
@@ -710,11 +712,12 @@ delete_cdev_device:
return rc;
}
-static void device_cdev_sysfs_del(struct hl_device *hdev)
+static void cdev_sysfs_debugfs_remove(struct hl_device *hdev)
{
- if (!hdev->cdev_sysfs_created)
+ if (!hdev->cdev_sysfs_debugfs_created)
goto put_devices;
+ hl_debugfs_remove_device(hdev);
hl_sysfs_fini(hdev);
cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl);
cdev_device_del(&hdev->cdev, hdev->dev);
@@ -981,6 +984,18 @@ static void device_early_fini(struct hl_device *hdev)
hdev->asic_funcs->early_fini(hdev);
}
+static bool is_pci_link_healthy(struct hl_device *hdev)
+{
+ u16 vendor_id;
+
+ if (!hdev->pdev)
+ return false;
+
+ pci_read_config_word(hdev->pdev, PCI_VENDOR_ID, &vendor_id);
+
+ return (vendor_id == PCI_VENDOR_ID_HABANALABS);
+}
+
static void hl_device_heartbeat(struct work_struct *work)
{
struct hl_device *hdev = container_of(work, struct hl_device,
@@ -995,7 +1010,8 @@ static void hl_device_heartbeat(struct work_struct *work)
goto reschedule;
if (hl_device_operational(hdev, NULL))
- dev_err(hdev->dev, "Device heartbeat failed!\n");
+ dev_err(hdev->dev, "Device heartbeat failed! PCI link is %s\n",
+ is_pci_link_healthy(hdev) ? "healthy" : "broken");
info.err_type = HL_INFO_FW_HEARTBEAT_ERR;
info.event_mask = &event_mask;
@@ -1157,6 +1173,16 @@ static void take_release_locks(struct hl_device *hdev)
mutex_unlock(&hdev->fpriv_ctrl_list_lock);
}
+static void hl_abort_waiting_for_completions(struct hl_device *hdev)
+{
+ hl_abort_waiting_for_cs_completions(hdev);
+
+ /* Release all pending user interrupts, each pending user interrupt
+ * holds a reference to a user context.
+ */
+ hl_release_pending_user_interrupts(hdev);
+}
+
static void cleanup_resources(struct hl_device *hdev, bool hard_reset, bool fw_reset,
bool skip_wq_flush)
{
@@ -1176,10 +1202,7 @@ static void cleanup_resources(struct hl_device *hdev, bool hard_reset, bool fw_r
/* flush the MMU prefetch workqueue */
flush_workqueue(hdev->prefetch_wq);
- /* Release all pending user interrupts, each pending user interrupt
- * holds a reference to user context
- */
- hl_release_pending_user_interrupts(hdev);
+ hl_abort_waiting_for_completions(hdev);
}
/*
@@ -1921,7 +1944,7 @@ out:
hl_ctx_put(ctx);
- hl_abort_waitings_for_completion(hdev);
+ hl_abort_waiting_for_completions(hdev);
return 0;
@@ -2034,7 +2057,7 @@ out_err:
int hl_device_init(struct hl_device *hdev)
{
int i, rc, cq_cnt, user_interrupt_cnt, cq_ready_cnt;
- bool add_cdev_sysfs_on_err = false;
+ bool expose_interfaces_on_err = false;
rc = create_cdev(hdev);
if (rc)
@@ -2150,16 +2173,22 @@ int hl_device_init(struct hl_device *hdev)
hdev->device_release_watchdog_timeout_sec = HL_DEVICE_RELEASE_WATCHDOG_TIMEOUT_SEC;
hdev->memory_scrub_val = MEM_SCRUB_DEFAULT_VAL;
- hl_debugfs_add_device(hdev);
- /* debugfs nodes are created in hl_ctx_init so it must be called after
- * hl_debugfs_add_device.
+ rc = hl_debugfs_device_init(hdev);
+ if (rc) {
+ dev_err(hdev->dev, "failed to initialize debugfs entry structure\n");
+ kfree(hdev->kernel_ctx);
+ goto mmu_fini;
+ }
+
+ /* The debugfs entry structure is accessed in hl_ctx_init(), so it must be called after
+ * hl_debugfs_device_init().
*/
rc = hl_ctx_init(hdev, hdev->kernel_ctx, true);
if (rc) {
dev_err(hdev->dev, "failed to initialize kernel context\n");
kfree(hdev->kernel_ctx);
- goto remove_device_from_debugfs;
+ goto debugfs_device_fini;
}
rc = hl_cb_pool_init(hdev);
@@ -2175,11 +2204,10 @@ int hl_device_init(struct hl_device *hdev)
}
/*
- * From this point, override rc (=0) in case of an error to allow
- * debugging (by adding char devices and create sysfs nodes as part of
- * the error flow).
+ * From this point, override rc (=0) in case of an error to allow debugging
+ * (by adding char devices and creating sysfs/debugfs files as part of the error flow).
*/
- add_cdev_sysfs_on_err = true;
+ expose_interfaces_on_err = true;
/* Device is now enabled as part of the initialization requires
* communication with the device firmware to get information that
@@ -2221,15 +2249,13 @@ int hl_device_init(struct hl_device *hdev)
}
/*
- * Expose devices and sysfs nodes to user.
- * From here there is no need to add char devices and create sysfs nodes
- * in case of an error.
+ * Expose devices and sysfs/debugfs files to user.
+ * From here there is no need to expose them in case of an error.
*/
- add_cdev_sysfs_on_err = false;
- rc = device_cdev_sysfs_add(hdev);
+ expose_interfaces_on_err = false;
+ rc = cdev_sysfs_debugfs_add(hdev);
if (rc) {
- dev_err(hdev->dev,
- "Failed to add char devices and sysfs nodes\n");
+ dev_err(hdev->dev, "Failed to add char devices and sysfs/debugfs files\n");
rc = 0;
goto out_disabled;
}
@@ -2275,8 +2301,8 @@ release_ctx:
if (hl_ctx_put(hdev->kernel_ctx) != 1)
dev_err(hdev->dev,
"kernel ctx is still alive on initialization failure\n");
-remove_device_from_debugfs:
- hl_debugfs_remove_device(hdev);
+debugfs_device_fini:
+ hl_debugfs_device_fini(hdev);
mmu_fini:
hl_mmu_fini(hdev);
eq_fini:
@@ -2300,15 +2326,11 @@ free_dev:
put_device(hdev->dev);
out_disabled:
hdev->disabled = true;
- if (add_cdev_sysfs_on_err)
- device_cdev_sysfs_add(hdev);
- if (hdev->pdev)
- dev_err(&hdev->pdev->dev,
- "Failed to initialize hl%d. Device %s is NOT usable !\n",
- hdev->cdev_idx, dev_name(&(hdev)->pdev->dev));
- else
- pr_err("Failed to initialize hl%d. Device %s is NOT usable !\n",
- hdev->cdev_idx, dev_name(&(hdev)->pdev->dev));
+ if (expose_interfaces_on_err)
+ cdev_sysfs_debugfs_add(hdev);
+ dev_err(&hdev->pdev->dev,
+ "Failed to initialize hl%d. Device %s is NOT usable !\n",
+ hdev->cdev_idx, dev_name(&hdev->pdev->dev));
return rc;
}
@@ -2427,8 +2449,6 @@ void hl_device_fini(struct hl_device *hdev)
if ((hdev->kernel_ctx) && (hl_ctx_put(hdev->kernel_ctx) != 1))
dev_err(hdev->dev, "kernel ctx is still alive\n");
- hl_debugfs_remove_device(hdev);
-
hl_dec_fini(hdev);
hl_vm_fini(hdev);
@@ -2453,8 +2473,10 @@ void hl_device_fini(struct hl_device *hdev)
device_early_fini(hdev);
- /* Hide devices and sysfs nodes from user */
- device_cdev_sysfs_del(hdev);
+ /* Hide devices and sysfs/debugfs files from user */
+ cdev_sysfs_debugfs_remove(hdev);
+
+ hl_debugfs_device_fini(hdev);
pr_info("removed device successfully\n");
}
@@ -2667,3 +2689,11 @@ void hl_handle_fw_err(struct hl_device *hdev, struct hl_info_fw_err_info *info)
if (info->event_mask)
*info->event_mask |= HL_NOTIFIER_EVENT_CRITICL_FW_ERR;
}
+
+void hl_enable_err_info_capture(struct hl_error_info *captured_err_info)
+{
+ vfree(captured_err_info->page_fault_info.user_mappings);
+ memset(captured_err_info, 0, sizeof(struct hl_error_info));
+ atomic_set(&captured_err_info->cs_timeout.write_enable, 1);
+ captured_err_info->undef_opcode.write_enable = true;
+}
diff --git a/drivers/accel/habanalabs/common/firmware_if.c b/drivers/accel/habanalabs/common/firmware_if.c
index 59f61ec66445..acbc1a6b5cb1 100644
--- a/drivers/accel/habanalabs/common/firmware_if.c
+++ b/drivers/accel/habanalabs/common/firmware_if.c
@@ -71,38 +71,124 @@ free_fw_ver:
return NULL;
}
-static int hl_get_preboot_major_minor(struct hl_device *hdev, char *preboot_ver)
+/**
+ * extract_u32_until_given_char() - given a string of the format "<u32><char>*", extract the u32.
+ * @str: the given string
+ * @ver_num: the pointer to the extracted u32 to be returned to the caller.
+ * @given_char: the given char at the end of the u32 in the string
+ *
+ * Return: Upon success, return a pointer to the given_char in the string. Upon failure, return NULL
+ */
+static char *extract_u32_until_given_char(char *str, u32 *ver_num, char given_char)
{
- char major[8], minor[8], *first_dot, *second_dot;
- int rc;
+ char num_str[8] = {}, *ch;
- first_dot = strnstr(preboot_ver, ".", 10);
- if (first_dot) {
- strscpy(major, preboot_ver, first_dot - preboot_ver + 1);
- rc = kstrtou32(major, 10, &hdev->fw_major_version);
- } else {
- rc = -EINVAL;
+ ch = strchrnul(str, given_char);
+ if (*ch == '\0' || ch == str || ch - str >= sizeof(num_str))
+ return NULL;
+
+ memcpy(num_str, str, ch - str);
+ if (kstrtou32(num_str, 10, ver_num))
+ return NULL;
+ return ch;
+}
+
+/**
+ * hl_get_sw_major_minor_subminor() - extract the FW's SW version major, minor, sub-minor
+ * from the version string
+ * @hdev: pointer to the hl_device
+ * @fw_str: the FW's version string
+ *
+ * The extracted version is set in the hdev fields: fw_sw_{major/minor/sub_minor}_ver.
+ *
+ * fw_str is expected to have one of two possible formats, examples:
+ * 1) 'Preboot version hl-gaudi2-1.9.0-fw-42.0.1-sec-3'
+ * 2) 'Preboot version hl-gaudi2-1.9.0-rc-fw-42.0.1-sec-3'
+ * In those examples, the SW major,minor,subminor are correspondingly: 1,9,0.
+ *
+ * Return: 0 for success or a negative error code for failure.
+ */
+static int hl_get_sw_major_minor_subminor(struct hl_device *hdev, const char *fw_str)
+{
+ char *end, *start;
+
+ end = strnstr(fw_str, "-rc-", VERSION_MAX_LEN);
+ if (end == fw_str)
+ return -EINVAL;
+
+ if (!end)
+ end = strnstr(fw_str, "-fw-", VERSION_MAX_LEN);
+
+ if (end == fw_str)
+ return -EINVAL;
+
+ if (!end)
+ return -EINVAL;
+
+ for (start = end - 1; start != fw_str; start--) {
+ if (*start == '-')
+ break;
}
- if (rc) {
- dev_err(hdev->dev, "Error %d parsing preboot major version\n", rc);
- return rc;
+ if (start == fw_str)
+ return -EINVAL;
+
+ /* start/end point each to the starting and ending hyphen of the sw version e.g. -1.9.0- */
+ start++;
+ start = extract_u32_until_given_char(start, &hdev->fw_sw_major_ver, '.');
+ if (!start)
+ goto err_zero_ver;
+
+ start++;
+ start = extract_u32_until_given_char(start, &hdev->fw_sw_minor_ver, '.');
+ if (!start)
+ goto err_zero_ver;
+
+ start++;
+ start = extract_u32_until_given_char(start, &hdev->fw_sw_sub_minor_ver, '-');
+ if (!start)
+ goto err_zero_ver;
+
+ return 0;
+
+err_zero_ver:
+ hdev->fw_sw_major_ver = 0;
+ hdev->fw_sw_minor_ver = 0;
+ hdev->fw_sw_sub_minor_ver = 0;
+ return -EINVAL;
+}
+
+/**
+ * hl_get_preboot_major_minor() - extract the FW's version major, minor from the version string.
+ * @hdev: pointer to the hl_device
+ * @preboot_ver: the FW's version string
+ *
+ * preboot_ver is expected to be the format of <major>.<minor>.<sub minor>*, e.g: 42.0.1-sec-3
+ * The extracted version is set in the hdev fields: fw_inner_{major/minor}_ver.
+ *
+ * Return: 0 on success, negative error code for failure.
+ */
+static int hl_get_preboot_major_minor(struct hl_device *hdev, char *preboot_ver)
+{
+ preboot_ver = extract_u32_until_given_char(preboot_ver, &hdev->fw_inner_major_ver, '.');
+ if (!preboot_ver) {
+ dev_err(hdev->dev, "Error parsing preboot major version\n");
+ goto err_zero_ver;
}
- /* skip the first dot */
- first_dot++;
+ preboot_ver++;
- second_dot = strnstr(first_dot, ".", 10);
- if (second_dot) {
- strscpy(minor, first_dot, second_dot - first_dot + 1);
- rc = kstrtou32(minor, 10, &hdev->fw_minor_version);
- } else {
- rc = -EINVAL;
+ preboot_ver = extract_u32_until_given_char(preboot_ver, &hdev->fw_inner_minor_ver, '.');
+ if (!preboot_ver) {
+ dev_err(hdev->dev, "Error parsing preboot minor version\n");
+ goto err_zero_ver;
}
+ return 0;
- if (rc)
- dev_err(hdev->dev, "Error %d parsing preboot minor version\n", rc);
- return rc;
+err_zero_ver:
+ hdev->fw_inner_major_ver = 0;
+ hdev->fw_inner_minor_ver = 0;
+ return -EINVAL;
}
static int hl_request_fw(struct hl_device *hdev,
@@ -505,6 +591,20 @@ void hl_fw_cpu_accessible_dma_pool_free(struct hl_device *hdev, size_t size,
size);
}
+int hl_fw_send_soft_reset(struct hl_device *hdev)
+{
+ struct cpucp_packet pkt;
+ int rc;
+
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.ctl = cpu_to_le32(CPUCP_PACKET_SOFT_RESET << CPUCP_PKT_CTL_OPCODE_SHIFT);
+ rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 0, NULL);
+ if (rc)
+ dev_err(hdev->dev, "failed to send soft-reset msg (err = %d)\n", rc);
+
+ return rc;
+}
+
int hl_fw_send_device_activity(struct hl_device *hdev, bool open)
{
struct cpucp_packet pkt;
@@ -1268,8 +1368,10 @@ void hl_fw_ask_hard_reset_without_linux(struct hl_device *hdev)
void hl_fw_ask_halt_machine_without_linux(struct hl_device *hdev)
{
- struct static_fw_load_mgr *static_loader =
- &hdev->fw_loader.static_loader;
+ struct fw_load_mgr *fw_loader = &hdev->fw_loader;
+ u32 status, cpu_boot_status_reg, cpu_timeout;
+ struct static_fw_load_mgr *static_loader;
+ struct pre_fw_load_props *pre_fw_load;
int rc;
if (hdev->device_cpu_is_halted)
@@ -1277,12 +1379,28 @@ void hl_fw_ask_halt_machine_without_linux(struct hl_device *hdev)
/* Stop device CPU to make sure nothing bad happens */
if (hdev->asic_prop.dynamic_fw_load) {
+ pre_fw_load = &fw_loader->pre_fw_load;
+ cpu_timeout = fw_loader->cpu_timeout;
+ cpu_boot_status_reg = pre_fw_load->cpu_boot_status_reg;
+
rc = hl_fw_dynamic_send_protocol_cmd(hdev, &hdev->fw_loader,
- COMMS_GOTO_WFE, 0, false,
- hdev->fw_loader.cpu_timeout);
- if (rc)
+ COMMS_GOTO_WFE, 0, false, cpu_timeout);
+ if (rc) {
dev_err(hdev->dev, "Failed sending COMMS_GOTO_WFE\n");
+ } else {
+ rc = hl_poll_timeout(
+ hdev,
+ cpu_boot_status_reg,
+ status,
+ status == CPU_BOOT_STATUS_IN_WFE,
+ hdev->fw_poll_interval_usec,
+ cpu_timeout);
+ if (rc)
+ dev_err(hdev->dev, "Current status=%u. Timed-out updating to WFE\n",
+ status);
+ }
} else {
+ static_loader = &hdev->fw_loader.static_loader;
WREG32(static_loader->kmd_msg_to_cpu_reg, KMD_MSG_GOTO_WFE);
msleep(static_loader->cpu_reset_wait_msec);
@@ -2151,6 +2269,7 @@ static int hl_fw_dynamic_read_device_fw_version(struct hl_device *hdev,
struct asic_fixed_properties *prop = &hdev->asic_prop;
char *preboot_ver, *boot_ver;
char btl_ver[32];
+ int rc;
switch (fwc) {
case FW_COMP_BOOT_FIT:
@@ -2164,20 +2283,20 @@ static int hl_fw_dynamic_read_device_fw_version(struct hl_device *hdev,
break;
case FW_COMP_PREBOOT:
strscpy(prop->preboot_ver, fw_version, VERSION_MAX_LEN);
- preboot_ver = strnstr(prop->preboot_ver, "Preboot",
- VERSION_MAX_LEN);
+ preboot_ver = strnstr(prop->preboot_ver, "Preboot", VERSION_MAX_LEN);
+ dev_info(hdev->dev, "preboot full version: '%s'\n", preboot_ver);
+
if (preboot_ver && preboot_ver != prop->preboot_ver) {
strscpy(btl_ver, prop->preboot_ver,
min((int) (preboot_ver - prop->preboot_ver), 31));
dev_info(hdev->dev, "%s\n", btl_ver);
}
+ rc = hl_get_sw_major_minor_subminor(hdev, preboot_ver);
+ if (rc)
+ return rc;
preboot_ver = extract_fw_ver_from_str(prop->preboot_ver);
if (preboot_ver) {
- int rc;
-
- dev_info(hdev->dev, "preboot version %s\n", preboot_ver);
-
rc = hl_get_preboot_major_minor(hdev, preboot_ver);
kfree(preboot_ver);
if (rc)
@@ -2367,16 +2486,6 @@ static int hl_fw_dynamic_load_image(struct hl_device *hdev,
if (rc)
goto release_fw;
- /* update state according to boot stage */
- if (cur_fwc == FW_COMP_BOOT_FIT) {
- struct cpu_dyn_regs *dyn_regs;
-
- dyn_regs = &fw_loader->dynamic_loader.comm_desc.cpu_dyn_regs;
- hl_fw_boot_fit_update_state(hdev,
- le32_to_cpu(dyn_regs->cpu_boot_dev_sts0),
- le32_to_cpu(dyn_regs->cpu_boot_dev_sts1));
- }
-
/* copy boot fit to space allocated by FW */
rc = hl_fw_dynamic_copy_image(hdev, fw, fw_loader);
if (rc)
@@ -2679,6 +2788,14 @@ static int hl_fw_dynamic_init_cpu(struct hl_device *hdev,
goto protocol_err;
}
+ rc = hl_fw_dynamic_wait_for_boot_fit_active(hdev, fw_loader);
+ if (rc)
+ goto protocol_err;
+
+ hl_fw_boot_fit_update_state(hdev,
+ le32_to_cpu(dyn_regs->cpu_boot_dev_sts0),
+ le32_to_cpu(dyn_regs->cpu_boot_dev_sts1));
+
/*
* when testing FW load (without Linux) on PLDM we don't want to
* wait until boot fit is active as it may take several hours.
@@ -2688,10 +2805,6 @@ static int hl_fw_dynamic_init_cpu(struct hl_device *hdev,
if (hdev->pldm && !(hdev->fw_components & FW_TYPE_LINUX))
return 0;
- rc = hl_fw_dynamic_wait_for_boot_fit_active(hdev, fw_loader);
- if (rc)
- goto protocol_err;
-
/* Enable DRAM scrambling before Linux boot and after successful
* UBoot
*/
@@ -2725,7 +2838,8 @@ static int hl_fw_dynamic_init_cpu(struct hl_device *hdev,
if (rc)
goto protocol_err;
- hl_fw_linux_update_state(hdev, le32_to_cpu(dyn_regs->cpu_boot_dev_sts0),
+ hl_fw_linux_update_state(hdev,
+ le32_to_cpu(dyn_regs->cpu_boot_dev_sts0),
le32_to_cpu(dyn_regs->cpu_boot_dev_sts1));
hl_fw_dynamic_update_linux_interrupt_if(hdev);
diff --git a/drivers/accel/habanalabs/common/habanalabs.h b/drivers/accel/habanalabs/common/habanalabs.h
index eaae69a9f817..d92ba2e30e31 100644
--- a/drivers/accel/habanalabs/common/habanalabs.h
+++ b/drivers/accel/habanalabs/common/habanalabs.h
@@ -36,6 +36,8 @@
struct hl_device;
struct hl_fpriv;
+#define PCI_VENDOR_ID_HABANALABS 0x1da3
+
/* Use upper bits of mmap offset to store habana driver specific information.
* bits[63:59] - Encode mmap type
* bits[45:0] - mmap offset value
@@ -113,18 +115,6 @@ enum hl_mmu_page_table_location {
MMU_NUM_PGT_LOCATIONS /* num of PGT locations */
};
-/**
- * enum hl_mmu_enablement - what mmu modules to enable
- * @MMU_EN_NONE: mmu disabled.
- * @MMU_EN_ALL: enable all.
- * @MMU_EN_PMMU_ONLY: Enable only the PMMU leaving the DMMU disabled.
- */
-enum hl_mmu_enablement {
- MMU_EN_NONE = 0,
- MMU_EN_ALL = 1,
- MMU_EN_PMMU_ONLY = 3, /* N/A for Goya/Gaudi */
-};
-
/*
* HL_RSVD_SOBS 'sync stream' reserved sync objects per QMAN stream
* HL_RSVD_MONS 'sync stream' reserved monitors per QMAN stream
@@ -2568,12 +2558,7 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
ktime_t __timeout; \
u32 __elbi_read; \
int __rc = 0; \
- if (hdev->pdev) \
- __timeout = ktime_add_us(ktime_get(), timeout_us); \
- else \
- __timeout = ktime_add_us(ktime_get(),\
- min((u64)(timeout_us * 10), \
- (u64) HL_SIM_MAX_TIMEOUT_US)); \
+ __timeout = ktime_add_us(ktime_get(), timeout_us); \
might_sleep_if(sleep_us); \
for (;;) { \
if (elbi) { \
@@ -2625,13 +2610,7 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
u8 __arr_idx; \
int __rc = 0; \
\
- if (hdev->pdev) \
- __timeout = ktime_add_us(ktime_get(), timeout_us); \
- else \
- __timeout = ktime_add_us(ktime_get(),\
- min(((u64)timeout_us * 10), \
- (u64) HL_SIM_MAX_TIMEOUT_US)); \
- \
+ __timeout = ktime_add_us(ktime_get(), timeout_us); \
might_sleep_if(sleep_us); \
if (arr_size >= 64) \
__rc = -EINVAL; \
@@ -2689,12 +2668,8 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
mem_written_by_device) \
({ \
ktime_t __timeout; \
- if (hdev->pdev) \
- __timeout = ktime_add_us(ktime_get(), timeout_us); \
- else \
- __timeout = ktime_add_us(ktime_get(),\
- min((u64)(timeout_us * 100), \
- (u64) HL_SIM_MAX_TIMEOUT_US)); \
+ \
+ __timeout = ktime_add_us(ktime_get(), timeout_us); \
might_sleep_if(sleep_us); \
for (;;) { \
/* Verify we read updates done by other cores or by device */ \
@@ -3225,8 +3200,11 @@ struct hl_reset_info {
* @captured_err_info: holds information about errors.
* @reset_info: holds current device reset information.
* @stream_master_qid_arr: pointer to array with QIDs of master streams.
- * @fw_major_version: major version of current loaded preboot.
- * @fw_minor_version: minor version of current loaded preboot.
+ * @fw_inner_major_ver: the major of current loaded preboot inner version.
+ * @fw_inner_minor_ver: the minor of current loaded preboot inner version.
+ * @fw_sw_major_ver: the major of current loaded preboot SW version.
+ * @fw_sw_minor_ver: the minor of current loaded preboot SW version.
+ * @fw_sw_sub_minor_ver: the sub-minor of current loaded preboot SW version.
* @dram_used_mem: current DRAM memory consumption.
* @memory_scrub_val: the value to which the dram will be scrubbed to using cb scrub_device_dram
* @timeout_jiffies: device CS timeout value.
@@ -3287,7 +3265,7 @@ struct hl_reset_info {
* @in_debug: whether the device is in a state where the profiling/tracing infrastructure
* can be used. This indication is needed because in some ASICs we need to do
* specific operations to enable that infrastructure.
- * @cdev_sysfs_created: were char devices and sysfs nodes created.
+ * @cdev_sysfs_debugfs_created: were char devices and sysfs/debugfs files created.
* @stop_on_err: true if engines should stop on error.
* @supports_sync_stream: is sync stream supported.
* @sync_stream_queue_idx: helper index for sync stream queues initialization.
@@ -3314,7 +3292,7 @@ struct hl_reset_info {
* @nic_ports_mask: Controls which NIC ports are enabled. Used only for testing.
* @fw_components: Controls which f/w components to load to the device. There are multiple f/w
* stages and sometimes we want to stop at a certain stage. Used only for testing.
- * @mmu_enable: Whether to enable or disable the device MMU(s). Used only for testing.
+ * @mmu_disable: Disable the device MMU(s). Used only for testing.
* @cpu_queues_enable: Whether to enable queues communication vs. the f/w. Used only for testing.
* @pldm: Whether we are running in Palladium environment. Used only for testing.
* @hard_reset_on_fw_events: Whether to do device hard-reset when a fatal event is received from
@@ -3412,8 +3390,11 @@ struct hl_device {
struct hl_reset_info reset_info;
u32 *stream_master_qid_arr;
- u32 fw_major_version;
- u32 fw_minor_version;
+ u32 fw_inner_major_ver;
+ u32 fw_inner_minor_ver;
+ u32 fw_sw_major_ver;
+ u32 fw_sw_minor_ver;
+ u32 fw_sw_sub_minor_ver;
atomic64_t dram_used_mem;
u64 memory_scrub_val;
u64 timeout_jiffies;
@@ -3451,7 +3432,7 @@ struct hl_device {
u8 init_done;
u8 device_cpu_disabled;
u8 in_debug;
- u8 cdev_sysfs_created;
+ u8 cdev_sysfs_debugfs_created;
u8 stop_on_err;
u8 supports_sync_stream;
u8 sync_stream_queue_idx;
@@ -3474,7 +3455,7 @@ struct hl_device {
/* Parameters for bring-up to be upstreamed */
u64 nic_ports_mask;
u64 fw_components;
- u8 mmu_enable;
+ u8 mmu_disable;
u8 cpu_queues_enable;
u8 pldm;
u8 hard_reset_on_fw_events;
@@ -3547,9 +3528,15 @@ struct hl_ioctl_desc {
hl_ioctl_t *func;
};
-static inline bool hl_is_fw_ver_below_1_9(struct hl_device *hdev)
+static inline bool hl_is_fw_sw_ver_below(struct hl_device *hdev, u32 fw_sw_major, u32 fw_sw_minor)
{
- return (hdev->fw_major_version < 42);
+ if (hdev->fw_sw_major_ver < fw_sw_major)
+ return true;
+ if (hdev->fw_sw_major_ver > fw_sw_major)
+ return false;
+ if (hdev->fw_sw_minor_ver < fw_sw_minor)
+ return true;
+ return false;
}
/*
@@ -3813,8 +3800,6 @@ struct pgt_info *hl_mmu_hr_get_alloc_next_hop(struct hl_ctx *ctx,
u64 curr_pte, bool *is_new_hop);
int hl_mmu_hr_get_tlb_info(struct hl_ctx *ctx, u64 virt_addr, struct hl_mmu_hop_info *hops,
struct hl_hr_mmu_funcs *hr_func);
-void hl_mmu_swap_out(struct hl_ctx *ctx);
-void hl_mmu_swap_in(struct hl_ctx *ctx);
int hl_mmu_if_set_funcs(struct hl_device *hdev);
void hl_mmu_v1_set_funcs(struct hl_device *hdev, struct hl_mmu_funcs *mmu);
void hl_mmu_v2_hr_set_funcs(struct hl_device *hdev, struct hl_mmu_funcs *mmu);
@@ -3872,6 +3857,7 @@ int hl_fw_dram_replaced_row_get(struct hl_device *hdev,
int hl_fw_dram_pending_row_get(struct hl_device *hdev, u32 *pend_rows_num);
int hl_fw_cpucp_engine_core_asid_set(struct hl_device *hdev, u32 asid);
int hl_fw_send_device_activity(struct hl_device *hdev, bool open);
+int hl_fw_send_soft_reset(struct hl_device *hdev);
int hl_pci_bars_map(struct hl_device *hdev, const char * const name[3],
bool is_wc[3]);
int hl_pci_elbi_read(struct hl_device *hdev, u64 addr, u32 *data);
@@ -3921,7 +3907,7 @@ void hl_dec_fini(struct hl_device *hdev);
void hl_dec_ctx_fini(struct hl_ctx *ctx);
void hl_release_pending_user_interrupts(struct hl_device *hdev);
-void hl_abort_waitings_for_completion(struct hl_device *hdev);
+void hl_abort_waiting_for_cs_completions(struct hl_device *hdev);
int hl_cs_signal_sob_wraparound_handler(struct hl_device *hdev, u32 q_idx,
struct hl_hw_sob **hw_sob, u32 count, bool encaps_sig);
@@ -3958,11 +3944,14 @@ void hl_handle_page_fault(struct hl_device *hdev, u64 addr, u16 eng_id, bool is_
u64 *event_mask);
void hl_handle_critical_hw_err(struct hl_device *hdev, u16 event_id, u64 *event_mask);
void hl_handle_fw_err(struct hl_device *hdev, struct hl_info_fw_err_info *info);
+void hl_enable_err_info_capture(struct hl_error_info *captured_err_info);
#ifdef CONFIG_DEBUG_FS
void hl_debugfs_init(void);
void hl_debugfs_fini(void);
+int hl_debugfs_device_init(struct hl_device *hdev);
+void hl_debugfs_device_fini(struct hl_device *hdev);
void hl_debugfs_add_device(struct hl_device *hdev);
void hl_debugfs_remove_device(struct hl_device *hdev);
void hl_debugfs_add_file(struct hl_fpriv *hpriv);
diff --git a/drivers/accel/habanalabs/common/habanalabs_drv.c b/drivers/accel/habanalabs/common/habanalabs_drv.c
index d9df64e75f33..7263e84c1a4d 100644
--- a/drivers/accel/habanalabs/common/habanalabs_drv.c
+++ b/drivers/accel/habanalabs/common/habanalabs_drv.c
@@ -13,6 +13,7 @@
#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/vmalloc.h>
#define CREATE_TRACE_POINTS
#include <trace/events/habanalabs.h>
@@ -54,8 +55,6 @@ module_param(boot_error_status_mask, ulong, 0444);
MODULE_PARM_DESC(boot_error_status_mask,
"Mask of the error status during device CPU boot (If bitX is cleared then error X is masked. Default all 1's)");
-#define PCI_VENDOR_ID_HABANALABS 0x1da3
-
#define PCI_IDS_GOYA 0x0001
#define PCI_IDS_GAUDI 0x1000
#define PCI_IDS_GAUDI_SEC 0x1010
@@ -220,9 +219,7 @@ int hl_device_open(struct inode *inode, struct file *filp)
hl_debugfs_add_file(hpriv);
- memset(&hdev->captured_err_info, 0, sizeof(hdev->captured_err_info));
- atomic_set(&hdev->captured_err_info.cs_timeout.write_enable, 1);
- hdev->captured_err_info.undef_opcode.write_enable = true;
+ hl_enable_err_info_capture(&hdev->captured_err_info);
hdev->open_counter++;
hdev->last_successful_open_jif = jiffies;
@@ -307,7 +304,6 @@ static void set_driver_behavior_per_device(struct hl_device *hdev)
{
hdev->nic_ports_mask = 0;
hdev->fw_components = FW_TYPE_ALL_TYPES;
- hdev->mmu_enable = MMU_EN_ALL;
hdev->cpu_queues_enable = 1;
hdev->pldm = 0;
hdev->hard_reset_on_fw_events = 1;
@@ -382,7 +378,6 @@ static int fixup_device_params(struct hl_device *hdev)
/* If CPU queues not enabled, no way to do heartbeat */
if (!hdev->cpu_queues_enable)
hdev->heartbeat = 0;
-
fixup_device_params_per_asic(hdev, tmp_timeout);
return 0;
diff --git a/drivers/accel/habanalabs/common/habanalabs_ioctl.c b/drivers/accel/habanalabs/common/habanalabs_ioctl.c
index 203ee857810c..6a45a92344e9 100644
--- a/drivers/accel/habanalabs/common/habanalabs_ioctl.c
+++ b/drivers/accel/habanalabs/common/habanalabs_ioctl.c
@@ -62,7 +62,7 @@ static int hw_ip_info(struct hl_device *hdev, struct hl_info_args *args)
hw_ip.device_id = hdev->asic_funcs->get_pci_id(hdev);
hw_ip.sram_base_address = prop->sram_user_base_address;
hw_ip.dram_base_address =
- hdev->mmu_enable && prop->dram_supports_virtual_memory ?
+ prop->dram_supports_virtual_memory ?
prop->dmmu.start_addr : prop->dram_user_base_address;
hw_ip.tpc_enabled_mask = prop->tpc_enabled_mask & 0xFF;
hw_ip.tpc_enabled_mask_ext = prop->tpc_enabled_mask;
@@ -71,11 +71,8 @@ static int hw_ip_info(struct hl_device *hdev, struct hl_info_args *args)
dram_available_size = prop->dram_size - dram_kmd_size;
- if (hdev->mmu_enable == MMU_EN_ALL)
- hw_ip.dram_size = DIV_ROUND_DOWN_ULL(dram_available_size,
- prop->dram_page_size) * prop->dram_page_size;
- else
- hw_ip.dram_size = dram_available_size;
+ hw_ip.dram_size = DIV_ROUND_DOWN_ULL(dram_available_size, prop->dram_page_size) *
+ prop->dram_page_size;
if (hw_ip.dram_size > PAGE_SIZE)
hw_ip.dram_enabled = 1;
@@ -842,15 +839,15 @@ static int hw_err_info(struct hl_fpriv *hpriv, struct hl_info_args *args)
struct hw_err_info *info;
int rc;
- if ((!user_buf_size) || (!user_buf))
+ if (!user_buf)
return -EINVAL;
- if (user_buf_size < sizeof(struct hl_info_hw_err_event))
- return -ENOMEM;
-
info = &hdev->captured_err_info.hw_err;
if (!info->event_info_available)
- return -ENOENT;
+ return 0;
+
+ if (user_buf_size < sizeof(struct hl_info_hw_err_event))
+ return -ENOMEM;
rc = copy_to_user(user_buf, &info->event, sizeof(struct hl_info_hw_err_event));
return rc ? -EFAULT : 0;
@@ -864,15 +861,15 @@ static int fw_err_info(struct hl_fpriv *hpriv, struct hl_info_args *args)
struct fw_err_info *info;
int rc;
- if ((!user_buf_size) || (!user_buf))
+ if (!user_buf)
return -EINVAL;
- if (user_buf_size < sizeof(struct hl_info_fw_err_event))
- return -ENOMEM;
-
info = &hdev->captured_err_info.fw_err;
if (!info->event_info_available)
- return -ENOENT;
+ return 0;
+
+ if (user_buf_size < sizeof(struct hl_info_fw_err_event))
+ return -ENOMEM;
rc = copy_to_user(user_buf, &info->event, sizeof(struct hl_info_fw_err_event));
return rc ? -EFAULT : 0;
@@ -1198,7 +1195,7 @@ static long _hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg,
out_err:
if (retcode)
- dev_dbg(dev, "error in ioctl: pid=%d, cmd=0x%02x, nr=0x%02x\n",
+ dev_dbg_ratelimited(dev, "error in ioctl: pid=%d, cmd=0x%02x, nr=0x%02x\n",
task_pid_nr(current), cmd, nr);
if (kdata != stack_kdata)
@@ -1222,7 +1219,7 @@ long hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
if ((nr >= HL_COMMAND_START) && (nr < HL_COMMAND_END)) {
ioctl = &hl_ioctls[nr];
} else {
- dev_err(hdev->dev, "invalid ioctl: pid=%d, nr=0x%02x\n",
+ dev_dbg_ratelimited(hdev->dev, "invalid ioctl: pid=%d, nr=0x%02x\n",
task_pid_nr(current), nr);
return -ENOTTY;
}
@@ -1245,7 +1242,7 @@ long hl_ioctl_control(struct file *filep, unsigned int cmd, unsigned long arg)
if (nr == _IOC_NR(HL_IOCTL_INFO)) {
ioctl = &hl_ioctls_control[nr];
} else {
- dev_err(hdev->dev_ctrl, "invalid ioctl: pid=%d, nr=0x%02x\n",
+ dev_dbg_ratelimited(hdev->dev_ctrl, "invalid ioctl: pid=%d, nr=0x%02x\n",
task_pid_nr(current), nr);
return -ENOTTY;
}
diff --git a/drivers/accel/habanalabs/common/irq.c b/drivers/accel/habanalabs/common/irq.c
index c67895b1cdeb..b1010d206c2e 100644
--- a/drivers/accel/habanalabs/common/irq.c
+++ b/drivers/accel/habanalabs/common/irq.c
@@ -430,7 +430,7 @@ irqreturn_t hl_irq_handler_eq(int irq, void *arg)
cur_eqe_index = FIELD_GET(EQ_CTL_INDEX_MASK, cur_eqe);
if ((hdev->event_queue.check_eqe_index) &&
(((eq->prev_eqe_index + 1) & EQ_CTL_INDEX_MASK) != cur_eqe_index)) {
- dev_dbg(hdev->dev,
+ dev_err(hdev->dev,
"EQE %#x in queue is ready but index does not match %d!=%d",
cur_eqe,
((eq->prev_eqe_index + 1) & EQ_CTL_INDEX_MASK),
diff --git a/drivers/accel/habanalabs/common/memory.c b/drivers/accel/habanalabs/common/memory.c
index a7b6a273ce21..4fc72a07d2f5 100644
--- a/drivers/accel/habanalabs/common/memory.c
+++ b/drivers/accel/habanalabs/common/memory.c
@@ -1034,30 +1034,6 @@ static void unmap_phys_pg_pack(struct hl_ctx *ctx, u64 vaddr,
}
}
-static int get_paddr_from_handle(struct hl_ctx *ctx, struct hl_mem_in *args,
- u64 *paddr)
-{
- struct hl_device *hdev = ctx->hdev;
- struct hl_vm *vm = &hdev->vm;
- struct hl_vm_phys_pg_pack *phys_pg_pack;
- u32 handle;
-
- handle = lower_32_bits(args->map_device.handle);
- spin_lock(&vm->idr_lock);
- phys_pg_pack = idr_find(&vm->phys_pg_pack_handles, handle);
- if (!phys_pg_pack) {
- spin_unlock(&vm->idr_lock);
- dev_err(hdev->dev, "no match for handle %u\n", handle);
- return -EINVAL;
- }
-
- *paddr = phys_pg_pack->pages[0];
-
- spin_unlock(&vm->idr_lock);
-
- return 0;
-}
-
/**
* map_device_va() - map the given memory.
* @ctx: pointer to the context structure.
@@ -2094,76 +2070,6 @@ err_free_dmabuf_wrapper:
return rc;
}
-static int mem_ioctl_no_mmu(struct hl_fpriv *hpriv, union hl_mem_args *args)
-{
- struct hl_device *hdev = hpriv->hdev;
- u64 block_handle, device_addr = 0;
- struct hl_ctx *ctx = hpriv->ctx;
- u32 handle = 0, block_size;
- int rc;
-
- switch (args->in.op) {
- case HL_MEM_OP_ALLOC:
- if (args->in.alloc.mem_size == 0) {
- dev_err(hdev->dev, "alloc size must be larger than 0\n");
- rc = -EINVAL;
- goto out;
- }
-
- /* Force contiguous as there are no real MMU
- * translations to overcome physical memory gaps
- */
- args->in.flags |= HL_MEM_CONTIGUOUS;
- rc = alloc_device_memory(ctx, &args->in, &handle);
-
- memset(args, 0, sizeof(*args));
- args->out.handle = (__u64) handle;
- break;
-
- case HL_MEM_OP_FREE:
- rc = free_device_memory(ctx, &args->in);
- break;
-
- case HL_MEM_OP_MAP:
- if (args->in.flags & HL_MEM_USERPTR) {
- dev_err(hdev->dev, "Failed to map host memory when MMU is disabled\n");
- rc = -EPERM;
- } else {
- rc = get_paddr_from_handle(ctx, &args->in, &device_addr);
- memset(args, 0, sizeof(*args));
- args->out.device_virt_addr = device_addr;
- }
-
- break;
-
- case HL_MEM_OP_UNMAP:
- rc = 0;
- break;
-
- case HL_MEM_OP_MAP_BLOCK:
- rc = map_block(hdev, args->in.map_block.block_addr, &block_handle, &block_size);
- args->out.block_handle = block_handle;
- args->out.block_size = block_size;
- break;
-
- case HL_MEM_OP_EXPORT_DMABUF_FD:
- dev_err(hdev->dev, "Failed to export dma-buf object when MMU is disabled\n");
- rc = -EPERM;
- break;
-
- case HL_MEM_OP_TS_ALLOC:
- rc = allocate_timestamps_buffers(hpriv, &args->in, &args->out.handle);
- break;
- default:
- dev_err(hdev->dev, "Unknown opcode for memory IOCTL\n");
- rc = -EINVAL;
- break;
- }
-
-out:
- return rc;
-}
-
static void ts_buff_release(struct hl_mmap_mem_buf *buf)
{
struct hl_ts_buff *ts_buff = buf->private;
@@ -2282,9 +2188,6 @@ int hl_mem_ioctl(struct hl_fpriv *hpriv, void *data)
return -EBUSY;
}
- if (!hdev->mmu_enable)
- return mem_ioctl_no_mmu(hpriv, args);
-
switch (args->in.op) {
case HL_MEM_OP_ALLOC:
if (args->in.alloc.mem_size == 0) {
@@ -2779,13 +2682,10 @@ int hl_vm_ctx_init(struct hl_ctx *ctx)
atomic64_set(&ctx->dram_phys_mem, 0);
/*
- * - If MMU is enabled, init the ranges as usual.
- * - If MMU is disabled, in case of host mapping, the returned address
- * is the given one.
* In case of DRAM mapping, the returned address is the physical
* address of the memory related to the given handle.
*/
- if (!ctx->hdev->mmu_enable)
+ if (ctx->hdev->mmu_disable)
return 0;
dram_range_start = prop->dmmu.start_addr;
@@ -2835,7 +2735,7 @@ void hl_vm_ctx_fini(struct hl_ctx *ctx)
struct hl_mem_in args;
int i;
- if (!hdev->mmu_enable)
+ if (hdev->mmu_disable)
return;
hl_debugfs_remove_ctx_mem_hash(hdev, ctx);
diff --git a/drivers/accel/habanalabs/common/mmu/mmu.c b/drivers/accel/habanalabs/common/mmu/mmu.c
index f379e5b461a6..b2145716c605 100644
--- a/drivers/accel/habanalabs/common/mmu/mmu.c
+++ b/drivers/accel/habanalabs/common/mmu/mmu.c
@@ -44,7 +44,7 @@ int hl_mmu_init(struct hl_device *hdev)
{
int rc = -EOPNOTSUPP;
- if (!hdev->mmu_enable)
+ if (hdev->mmu_disable)
return 0;
mutex_init(&hdev->mmu_lock);
@@ -82,7 +82,7 @@ fini_dr_mmu:
*/
void hl_mmu_fini(struct hl_device *hdev)
{
- if (!hdev->mmu_enable)
+ if (hdev->mmu_disable)
return;
if (hdev->mmu_func[MMU_DR_PGT].fini != NULL)
@@ -107,7 +107,7 @@ int hl_mmu_ctx_init(struct hl_ctx *ctx)
struct hl_device *hdev = ctx->hdev;
int rc = -EOPNOTSUPP;
- if (!hdev->mmu_enable)
+ if (hdev->mmu_disable)
return 0;
if (hdev->mmu_func[MMU_DR_PGT].ctx_init != NULL) {
@@ -145,7 +145,7 @@ void hl_mmu_ctx_fini(struct hl_ctx *ctx)
{
struct hl_device *hdev = ctx->hdev;
- if (!hdev->mmu_enable)
+ if (hdev->mmu_disable)
return;
if (hdev->mmu_func[MMU_DR_PGT].ctx_fini != NULL)
@@ -233,7 +233,7 @@ int hl_mmu_unmap_page(struct hl_ctx *ctx, u64 virt_addr, u32 page_size, bool flu
u64 real_virt_addr;
bool is_dram_addr;
- if (!hdev->mmu_enable)
+ if (hdev->mmu_disable)
return 0;
is_dram_addr = hl_is_dram_va(hdev, virt_addr);
@@ -301,7 +301,7 @@ int hl_mmu_map_page(struct hl_ctx *ctx, u64 virt_addr, u64 phys_addr, u32 page_s
bool is_dram_addr;
- if (!hdev->mmu_enable)
+ if (hdev->mmu_disable)
return 0;
is_dram_addr = hl_is_dram_va(hdev, virt_addr);
@@ -472,46 +472,6 @@ int hl_mmu_unmap_contiguous(struct hl_ctx *ctx, u64 virt_addr, u32 size)
return rc;
}
-/*
- * hl_mmu_swap_out - marks all mapping of the given ctx as swapped out
- *
- * @ctx: pointer to the context structure
- *
- */
-void hl_mmu_swap_out(struct hl_ctx *ctx)
-{
- struct hl_device *hdev = ctx->hdev;
-
- if (!hdev->mmu_enable)
- return;
-
- if (hdev->mmu_func[MMU_DR_PGT].swap_out != NULL)
- hdev->mmu_func[MMU_DR_PGT].swap_out(ctx);
-
- if (hdev->mmu_func[MMU_HR_PGT].swap_out != NULL)
- hdev->mmu_func[MMU_HR_PGT].swap_out(ctx);
-}
-
-/*
- * hl_mmu_swap_in - marks all mapping of the given ctx as swapped in
- *
- * @ctx: pointer to the context structure
- *
- */
-void hl_mmu_swap_in(struct hl_ctx *ctx)
-{
- struct hl_device *hdev = ctx->hdev;
-
- if (!hdev->mmu_enable)
- return;
-
- if (hdev->mmu_func[MMU_DR_PGT].swap_in != NULL)
- hdev->mmu_func[MMU_DR_PGT].swap_in(ctx);
-
- if (hdev->mmu_func[MMU_HR_PGT].swap_in != NULL)
- hdev->mmu_func[MMU_HR_PGT].swap_in(ctx);
-}
-
static void hl_mmu_pa_page_with_offset(struct hl_ctx *ctx, u64 virt_addr,
struct hl_mmu_hop_info *hops,
u64 *phys_addr)
@@ -594,7 +554,7 @@ int hl_mmu_get_tlb_info(struct hl_ctx *ctx, u64 virt_addr,
int pgt_residency, rc;
bool is_dram_addr;
- if (!hdev->mmu_enable)
+ if (hdev->mmu_disable)
return -EOPNOTSUPP;
prop = &hdev->asic_prop;
@@ -625,7 +585,7 @@ int hl_mmu_get_tlb_info(struct hl_ctx *ctx, u64 virt_addr,
int hl_mmu_if_set_funcs(struct hl_device *hdev)
{
- if (!hdev->mmu_enable)
+ if (hdev->mmu_disable)
return 0;
switch (hdev->asic_type) {
diff --git a/drivers/accel/habanalabs/common/security.c b/drivers/accel/habanalabs/common/security.c
index 297e6e44fd0c..fe913965dbad 100644
--- a/drivers/accel/habanalabs/common/security.c
+++ b/drivers/accel/habanalabs/common/security.c
@@ -284,14 +284,14 @@ void hl_secure_block(struct hl_device *hdev,
* @instance_offset: offset between instances
* @pb_blocks: blocks array
* @blocks_array_size: blocks array size
- * @regs_array: register array
- * @regs_array_size: register array size
+ * @user_regs_array: unsecured register array
+ * @user_regs_array_size: unsecured register array size
* @mask: enabled instances mask: 1- enabled, 0- disabled
*/
int hl_init_pb_with_mask(struct hl_device *hdev, u32 num_dcores,
u32 dcore_offset, u32 num_instances, u32 instance_offset,
const u32 pb_blocks[], u32 blocks_array_size,
- const u32 *regs_array, u32 regs_array_size, u64 mask)
+ const u32 *user_regs_array, u32 user_regs_array_size, u64 mask)
{
int i, j;
struct hl_block_glbl_sec *glbl_sec;
@@ -303,8 +303,8 @@ int hl_init_pb_with_mask(struct hl_device *hdev, u32 num_dcores,
return -ENOMEM;
hl_secure_block(hdev, glbl_sec, blocks_array_size);
- hl_unsecure_registers(hdev, regs_array, regs_array_size, 0, pb_blocks,
- glbl_sec, blocks_array_size);
+ hl_unsecure_registers(hdev, user_regs_array, user_regs_array_size, 0,
+ pb_blocks, glbl_sec, blocks_array_size);
/* Fill all blocks with the same configuration */
for (i = 0 ; i < num_dcores ; i++) {
@@ -336,19 +336,19 @@ int hl_init_pb_with_mask(struct hl_device *hdev, u32 num_dcores,
* @instance_offset: offset between instances
* @pb_blocks: blocks array
* @blocks_array_size: blocks array size
- * @regs_array: register array
- * @regs_array_size: register array size
+ * @user_regs_array: unsecured register array
+ * @user_regs_array_size: unsecured register array size
*
*/
int hl_init_pb(struct hl_device *hdev, u32 num_dcores, u32 dcore_offset,
u32 num_instances, u32 instance_offset,
const u32 pb_blocks[], u32 blocks_array_size,
- const u32 *regs_array, u32 regs_array_size)
+ const u32 *user_regs_array, u32 user_regs_array_size)
{
return hl_init_pb_with_mask(hdev, num_dcores, dcore_offset,
num_instances, instance_offset, pb_blocks,
- blocks_array_size, regs_array, regs_array_size,
- ULLONG_MAX);
+ blocks_array_size, user_regs_array,
+ user_regs_array_size, ULLONG_MAX);
}
/**
@@ -364,15 +364,15 @@ int hl_init_pb(struct hl_device *hdev, u32 num_dcores, u32 dcore_offset,
* @instance_offset: offset between instances
* @pb_blocks: blocks array
* @blocks_array_size: blocks array size
- * @regs_range_array: register range array
- * @regs_range_array_size: register range array size
+ * @user_regs_range_array: unsecured register range array
+ * @user_regs_range_array_size: unsecured register range array size
* @mask: enabled instances mask: 1- enabled, 0- disabled
*/
int hl_init_pb_ranges_with_mask(struct hl_device *hdev, u32 num_dcores,
u32 dcore_offset, u32 num_instances, u32 instance_offset,
const u32 pb_blocks[], u32 blocks_array_size,
- const struct range *regs_range_array, u32 regs_range_array_size,
- u64 mask)
+ const struct range *user_regs_range_array,
+ u32 user_regs_range_array_size, u64 mask)
{
int i, j, rc = 0;
struct hl_block_glbl_sec *glbl_sec;
@@ -384,8 +384,8 @@ int hl_init_pb_ranges_with_mask(struct hl_device *hdev, u32 num_dcores,
return -ENOMEM;
hl_secure_block(hdev, glbl_sec, blocks_array_size);
- rc = hl_unsecure_registers_range(hdev, regs_range_array,
- regs_range_array_size, 0, pb_blocks, glbl_sec,
+ rc = hl_unsecure_registers_range(hdev, user_regs_range_array,
+ user_regs_range_array_size, 0, pb_blocks, glbl_sec,
blocks_array_size);
if (rc)
goto free_glbl_sec;
@@ -422,19 +422,20 @@ free_glbl_sec:
* @instance_offset: offset between instances
* @pb_blocks: blocks array
* @blocks_array_size: blocks array size
- * @regs_range_array: register range array
- * @regs_range_array_size: register range array size
+ * @user_regs_range_array: unsecured register range array
+ * @user_regs_range_array_size: unsecured register range array size
*
*/
int hl_init_pb_ranges(struct hl_device *hdev, u32 num_dcores,
u32 dcore_offset, u32 num_instances, u32 instance_offset,
const u32 pb_blocks[], u32 blocks_array_size,
- const struct range *regs_range_array, u32 regs_range_array_size)
+ const struct range *user_regs_range_array,
+ u32 user_regs_range_array_size)
{
return hl_init_pb_ranges_with_mask(hdev, num_dcores, dcore_offset,
num_instances, instance_offset, pb_blocks,
- blocks_array_size, regs_range_array,
- regs_range_array_size, ULLONG_MAX);
+ blocks_array_size, user_regs_range_array,
+ user_regs_range_array_size, ULLONG_MAX);
}
/**
@@ -447,14 +448,14 @@ int hl_init_pb_ranges(struct hl_device *hdev, u32 num_dcores,
* @instance_offset: offset between instances
* @pb_blocks: blocks array
* @blocks_array_size: blocks array size
- * @regs_array: register array
- * @regs_array_size: register array size
+ * @user_regs_array: unsecured register array
+ * @user_regs_array_size: unsecured register array size
*
*/
int hl_init_pb_single_dcore(struct hl_device *hdev, u32 dcore_offset,
u32 num_instances, u32 instance_offset,
const u32 pb_blocks[], u32 blocks_array_size,
- const u32 *regs_array, u32 regs_array_size)
+ const u32 *user_regs_array, u32 user_regs_array_size)
{
int i, rc = 0;
struct hl_block_glbl_sec *glbl_sec;
@@ -466,8 +467,8 @@ int hl_init_pb_single_dcore(struct hl_device *hdev, u32 dcore_offset,
return -ENOMEM;
hl_secure_block(hdev, glbl_sec, blocks_array_size);
- rc = hl_unsecure_registers(hdev, regs_array, regs_array_size, 0,
- pb_blocks, glbl_sec, blocks_array_size);
+ rc = hl_unsecure_registers(hdev, user_regs_array, user_regs_array_size,
+ 0, pb_blocks, glbl_sec, blocks_array_size);
if (rc)
goto free_glbl_sec;
@@ -495,8 +496,8 @@ free_glbl_sec:
* @instance_offset: offset between instances
* @pb_blocks: blocks array
* @blocks_array_size: blocks array size
- * @regs_range_array: register range array
- * @regs_range_array_size: register range array size
+ * @user_regs_range_array: unsecured register range array
+ * @user_regs_range_array_size: unsecured register range array size
*
*/
int hl_init_pb_ranges_single_dcore(struct hl_device *hdev, u32 dcore_offset,
diff --git a/drivers/accel/habanalabs/gaudi/gaudi.c b/drivers/accel/habanalabs/gaudi/gaudi.c
index a29aa8f7b6f3..056e2ef44afb 100644
--- a/drivers/accel/habanalabs/gaudi/gaudi.c
+++ b/drivers/accel/habanalabs/gaudi/gaudi.c
@@ -114,13 +114,6 @@ static u32 gaudi_stream_master[GAUDI_STREAM_MASTER_ARR_SIZE] = {
GAUDI_QUEUE_ID_DMA_1_3
};
-static const char gaudi_irq_name[GAUDI_MSI_ENTRIES][GAUDI_MAX_STRING_LEN] = {
- "gaudi cq 0_0", "gaudi cq 0_1", "gaudi cq 0_2", "gaudi cq 0_3",
- "gaudi cq 1_0", "gaudi cq 1_1", "gaudi cq 1_2", "gaudi cq 1_3",
- "gaudi cq 5_0", "gaudi cq 5_1", "gaudi cq 5_2", "gaudi cq 5_3",
- "gaudi cpu eq"
-};
-
static const u8 gaudi_dma_assignment[GAUDI_DMA_MAX] = {
[GAUDI_PCI_DMA_1] = GAUDI_ENGINE_ID_DMA_0,
[GAUDI_PCI_DMA_2] = GAUDI_ENGINE_ID_DMA_1,
@@ -1476,8 +1469,7 @@ static int gaudi_collective_wait_create_job(struct hl_device *hdev,
}
/* Allocate internal mapped CB for non patched CBs */
- cb = hl_cb_kernel_create(hdev, cb_size,
- hdev->mmu_enable && !patched_cb);
+ cb = hl_cb_kernel_create(hdev, cb_size, !patched_cb);
if (!cb) {
atomic64_inc(&ctx->cs_counters.out_of_mem_drop_cnt);
atomic64_inc(&cntr->out_of_mem_drop_cnt);
@@ -3651,9 +3643,6 @@ static int gaudi_mmu_init(struct hl_device *hdev)
u64 hop0_addr;
int rc, i;
- if (!hdev->mmu_enable)
- return 0;
-
if (gaudi->hw_cap_initialized & HW_CAP_MMU)
return 0;
diff --git a/drivers/accel/habanalabs/gaudi2/gaudi2.c b/drivers/accel/habanalabs/gaudi2/gaudi2.c
index b778cf764a68..20c4583f12b0 100644
--- a/drivers/accel/habanalabs/gaudi2/gaudi2.c
+++ b/drivers/accel/habanalabs/gaudi2/gaudi2.c
@@ -57,13 +57,13 @@
#define GAUDI2_NA_EVENT_CAUSE 0xFF
#define GAUDI2_NUM_OF_QM_ERR_CAUSE 18
-#define GAUDI2_NUM_OF_QM_LCP_ERR_CAUSE 25
+#define GAUDI2_NUM_OF_LOWER_QM_ERR_CAUSE 25
#define GAUDI2_NUM_OF_QM_ARB_ERR_CAUSE 3
#define GAUDI2_NUM_OF_ARC_SEI_ERR_CAUSE 14
#define GAUDI2_NUM_OF_CPU_SEI_ERR_CAUSE 3
#define GAUDI2_NUM_OF_QM_SEI_ERR_CAUSE 2
#define GAUDI2_NUM_OF_ROT_ERR_CAUSE 22
-#define GAUDI2_NUM_OF_TPC_INTR_CAUSE 30
+#define GAUDI2_NUM_OF_TPC_INTR_CAUSE 31
#define GAUDI2_NUM_OF_DEC_ERR_CAUSE 25
#define GAUDI2_NUM_OF_MME_ERR_CAUSE 16
#define GAUDI2_NUM_OF_MME_SBTE_ERR_CAUSE 5
@@ -162,6 +162,9 @@
#define PSOC_RAZWI_ENG_STR_SIZE 128
#define PSOC_RAZWI_MAX_ENG_PER_RTR 5
+/* HW scrambles only bits 0-25 */
+#define HW_UNSCRAMBLED_BITS_MASK GENMASK_ULL(63, 26)
+
struct gaudi2_razwi_info {
u32 axuser_xy;
u32 rtr_ctrl;
@@ -801,7 +804,7 @@ static const char * const gaudi2_qman_error_cause[GAUDI2_NUM_OF_QM_ERR_CAUSE] =
"PQC L2H error"
};
-static const char * const gaudi2_qman_lower_cp_error_cause[GAUDI2_NUM_OF_QM_LCP_ERR_CAUSE] = {
+static const char * const gaudi2_lower_qman_error_cause[GAUDI2_NUM_OF_LOWER_QM_ERR_CAUSE] = {
"RSVD0",
"CQ AXI HBW error",
"CP AXI HBW error",
@@ -891,6 +894,7 @@ static const char * const gaudi2_tpc_interrupts_cause[GAUDI2_NUM_OF_TPC_INTR_CAU
"invalid_lock_access",
"LD_L protection violation",
"ST_L protection violation",
+ "D$ L0CS mismatch",
};
static const char * const guadi2_mme_error_cause[GAUDI2_NUM_OF_MME_ERR_CAUSE] = {
@@ -3615,6 +3619,12 @@ static int gaudi2_sw_init(struct hl_device *hdev)
prop->supports_compute_reset = true;
+ /* Event queue sanity check added in FW version 1.11 */
+ if (hl_is_fw_sw_ver_below(hdev, 1, 11))
+ hdev->event_queue.check_eqe_index = false;
+ else
+ hdev->event_queue.check_eqe_index = true;
+
hdev->asic_funcs->set_pci_memory_regions(hdev);
rc = gaudi2_special_blocks_iterator_config(hdev);
@@ -3630,8 +3640,8 @@ static int gaudi2_sw_init(struct hl_device *hdev)
special_blocks_free:
gaudi2_special_blocks_iterator_free(hdev);
free_scratchpad_mem:
- hl_asic_dma_pool_free(hdev, gaudi2->scratchpad_kernel_address,
- gaudi2->scratchpad_bus_address);
+ hl_asic_dma_free_coherent(hdev, PAGE_SIZE, gaudi2->scratchpad_kernel_address,
+ gaudi2->scratchpad_bus_address);
free_virt_msix_db_mem:
hl_cpu_accessible_dma_pool_free(hdev, prop->pmmu.page_size, gaudi2->virt_msix_db_cpu_addr);
free_cpu_accessible_dma_pool:
@@ -4526,7 +4536,7 @@ static int gaudi2_set_tpc_engine_mode(struct hl_device *hdev, u32 engine_id, u32
reg_base = gaudi2_tpc_cfg_blocks_bases[tpc_id];
reg_addr = reg_base + TPC_CFG_STALL_OFFSET;
reg_val = FIELD_PREP(DCORE0_TPC0_CFG_TPC_STALL_V_MASK,
- !!(engine_command == HL_ENGINE_STALL));
+ (engine_command == HL_ENGINE_STALL) ? 1 : 0);
WREG32(reg_addr, reg_val);
if (engine_command == HL_ENGINE_RESUME) {
@@ -4550,7 +4560,7 @@ static int gaudi2_set_mme_engine_mode(struct hl_device *hdev, u32 engine_id, u32
reg_base = gaudi2_mme_ctrl_lo_blocks_bases[mme_id];
reg_addr = reg_base + MME_CTRL_LO_QM_STALL_OFFSET;
reg_val = FIELD_PREP(DCORE0_MME_CTRL_LO_QM_STALL_V_MASK,
- !!(engine_command == HL_ENGINE_STALL));
+ (engine_command == HL_ENGINE_STALL) ? 1 : 0);
WREG32(reg_addr, reg_val);
return 0;
@@ -4571,7 +4581,7 @@ static int gaudi2_set_edma_engine_mode(struct hl_device *hdev, u32 engine_id, u3
reg_base = gaudi2_dma_core_blocks_bases[edma_id];
reg_addr = reg_base + EDMA_CORE_CFG_STALL_OFFSET;
reg_val = FIELD_PREP(DCORE0_EDMA0_CORE_CFG_1_HALT_MASK,
- !!(engine_command == HL_ENGINE_STALL));
+ (engine_command == HL_ENGINE_STALL) ? 1 : 0);
WREG32(reg_addr, reg_val);
if (engine_command == HL_ENGINE_STALL) {
@@ -6148,18 +6158,24 @@ static int gaudi2_execute_soft_reset(struct hl_device *hdev, bool driver_perform
u32 poll_timeout_us)
{
struct cpu_dyn_regs *dyn_regs = &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs;
+ int rc = 0;
if (!driver_performs_reset) {
- /* set SP to indicate reset request sent to FW */
- if (dyn_regs->cpu_rst_status)
- WREG32(le32_to_cpu(dyn_regs->cpu_rst_status), CPU_RST_STATUS_NA);
- else
- WREG32(mmCPU_RST_STATUS_TO_HOST, CPU_RST_STATUS_NA);
-
- WREG32(le32_to_cpu(dyn_regs->gic_host_soft_rst_irq),
- gaudi2_irq_map_table[GAUDI2_EVENT_CPU_SOFT_RESET].cpu_id);
-
- return gaudi2_get_soft_rst_done_indication(hdev, poll_timeout_us);
+ if (hl_is_fw_sw_ver_below(hdev, 1, 10)) {
+ /* set SP to indicate reset request sent to FW */
+ if (dyn_regs->cpu_rst_status)
+ WREG32(le32_to_cpu(dyn_regs->cpu_rst_status), CPU_RST_STATUS_NA);
+ else
+ WREG32(mmCPU_RST_STATUS_TO_HOST, CPU_RST_STATUS_NA);
+ WREG32(le32_to_cpu(dyn_regs->gic_host_soft_rst_irq),
+ gaudi2_irq_map_table[GAUDI2_EVENT_CPU_SOFT_RESET].cpu_id);
+
+ /* wait for f/w response */
+ rc = gaudi2_get_soft_rst_done_indication(hdev, poll_timeout_us);
+ } else {
+ rc = hl_fw_send_soft_reset(hdev);
+ }
+ return rc;
}
/* Block access to engines, QMANs and SM during reset, these
@@ -7231,7 +7247,7 @@ static bool gaudi2_get_tpc_idle_status(struct hl_device *hdev, u64 *mask_arr, u8
gaudi2_iterate_tpcs(hdev, &tpc_iter);
- return tpc_idle_data.is_idle;
+ return *tpc_idle_data.is_idle;
}
static bool gaudi2_get_decoder_idle_status(struct hl_device *hdev, u64 *mask_arr, u8 mask_len,
@@ -7737,137 +7753,28 @@ static bool gaudi2_handle_ecc_event(struct hl_device *hdev, u16 event_type,
return !!ecc_data->is_critical;
}
-/*
- * gaudi2_queue_idx_dec - decrement queue index (pi/ci) and handle wrap
- *
- * @idx: the current pi/ci value
- * @q_len: the queue length (power of 2)
- *
- * @return the cyclically decremented index
- */
-static inline u32 gaudi2_queue_idx_dec(u32 idx, u32 q_len)
-{
- u32 mask = q_len - 1;
-
- /*
- * modular decrement is equivalent to adding (queue_size -1)
- * later we take LSBs to make sure the value is in the
- * range [0, queue_len - 1]
- */
- return (idx + q_len - 1) & mask;
-}
-
-/**
- * gaudi2_print_sw_config_stream_data - print SW config stream data
- *
- * @hdev: pointer to the habanalabs device structure
- * @stream: the QMAN's stream
- * @qman_base: base address of QMAN registers block
- */
-static void gaudi2_print_sw_config_stream_data(struct hl_device *hdev,
- u32 stream, u64 qman_base)
-{
- u64 cq_ptr_lo, cq_ptr_hi, cq_tsize, cq_ptr;
- u32 cq_ptr_lo_off, size;
-
- cq_ptr_lo_off = mmDCORE0_TPC0_QM_CQ_PTR_LO_1 - mmDCORE0_TPC0_QM_CQ_PTR_LO_0;
-
- cq_ptr_lo = qman_base + (mmDCORE0_TPC0_QM_CQ_PTR_LO_0 - mmDCORE0_TPC0_QM_BASE) +
- stream * cq_ptr_lo_off;
-
- cq_ptr_hi = cq_ptr_lo + (mmDCORE0_TPC0_QM_CQ_PTR_HI_0 - mmDCORE0_TPC0_QM_CQ_PTR_LO_0);
-
- cq_tsize = cq_ptr_lo + (mmDCORE0_TPC0_QM_CQ_TSIZE_0 - mmDCORE0_TPC0_QM_CQ_PTR_LO_0);
-
- cq_ptr = (((u64) RREG32(cq_ptr_hi)) << 32) | RREG32(cq_ptr_lo);
- size = RREG32(cq_tsize);
- dev_info(hdev->dev, "stop on err: stream: %u, addr: %#llx, size: %x\n",
- stream, cq_ptr, size);
-}
-
-/**
- * gaudi2_print_last_pqes_on_err - print last PQEs on error
- *
- * @hdev: pointer to the habanalabs device structure
- * @qid_base: first QID of the QMAN (out of 4 streams)
- * @stream: the QMAN's stream
- * @qman_base: base address of QMAN registers block
- * @pr_sw_conf: if true print the SW config stream data (CQ PTR and SIZE)
- */
-static void gaudi2_print_last_pqes_on_err(struct hl_device *hdev, u32 qid_base, u32 stream,
- u64 qman_base, bool pr_sw_conf)
+static void print_lower_qman_data_on_err(struct hl_device *hdev, u64 qman_base)
{
- u32 ci, qm_ci_stream_off;
- struct hl_hw_queue *q;
- u64 pq_ci;
- int i;
-
- q = &hdev->kernel_queues[qid_base + stream];
-
- qm_ci_stream_off = mmDCORE0_TPC0_QM_PQ_CI_1 - mmDCORE0_TPC0_QM_PQ_CI_0;
- pq_ci = qman_base + (mmDCORE0_TPC0_QM_PQ_CI_0 - mmDCORE0_TPC0_QM_BASE) +
- stream * qm_ci_stream_off;
-
- hdev->asic_funcs->hw_queues_lock(hdev);
-
- if (pr_sw_conf)
- gaudi2_print_sw_config_stream_data(hdev, stream, qman_base);
-
- ci = RREG32(pq_ci);
-
- /* we should start printing form ci -1 */
- ci = gaudi2_queue_idx_dec(ci, HL_QUEUE_LENGTH);
-
- for (i = 0; i < PQ_FETCHER_CACHE_SIZE; i++) {
- struct hl_bd *bd;
- u64 addr;
- u32 len;
-
- bd = q->kernel_address;
- bd += ci;
-
- len = le32_to_cpu(bd->len);
- /* len 0 means uninitialized entry- break */
- if (!len)
- break;
-
- addr = le64_to_cpu(bd->ptr);
-
- dev_info(hdev->dev, "stop on err PQE(stream %u): ci: %u, addr: %#llx, size: %x\n",
- stream, ci, addr, len);
-
- /* get previous ci, wrap if needed */
- ci = gaudi2_queue_idx_dec(ci, HL_QUEUE_LENGTH);
- }
-
- hdev->asic_funcs->hw_queues_unlock(hdev);
-}
+ u32 lo, hi, cq_ptr_size, arc_cq_ptr_size;
+ u64 cq_ptr, arc_cq_ptr, cp_current_inst;
-/**
- * print_qman_data_on_err - extract QMAN data on error
- *
- * @hdev: pointer to the habanalabs device structure
- * @qid_base: first QID of the QMAN (out of 4 streams)
- * @stream: the QMAN's stream
- * @qman_base: base address of QMAN registers block
- *
- * This function attempt to extract as much data as possible on QMAN error.
- * On upper CP print the SW config stream data and last 8 PQEs.
- * On lower CP print SW config data and last PQEs of ALL 4 upper CPs
- */
-static void print_qman_data_on_err(struct hl_device *hdev, u32 qid_base, u32 stream, u64 qman_base)
-{
- u32 i;
+ lo = RREG32(qman_base + QM_CQ_PTR_LO_4_OFFSET);
+ hi = RREG32(qman_base + QM_CQ_PTR_HI_4_OFFSET);
+ cq_ptr = ((u64) hi) << 32 | lo;
+ cq_ptr_size = RREG32(qman_base + QM_CQ_TSIZE_4_OFFSET);
- if (stream != QMAN_STREAMS) {
- gaudi2_print_last_pqes_on_err(hdev, qid_base, stream, qman_base, true);
- return;
- }
+ lo = RREG32(qman_base + QM_ARC_CQ_PTR_LO_OFFSET);
+ hi = RREG32(qman_base + QM_ARC_CQ_PTR_HI_OFFSET);
+ arc_cq_ptr = ((u64) hi) << 32 | lo;
+ arc_cq_ptr_size = RREG32(qman_base + QM_ARC_CQ_TSIZE_OFFSET);
- gaudi2_print_sw_config_stream_data(hdev, stream, qman_base);
+ lo = RREG32(qman_base + QM_CP_CURRENT_INST_LO_4_OFFSET);
+ hi = RREG32(qman_base + QM_CP_CURRENT_INST_HI_4_OFFSET);
+ cp_current_inst = ((u64) hi) << 32 | lo;
- for (i = 0 ; i < QMAN_STREAMS ; i++)
- gaudi2_print_last_pqes_on_err(hdev, qid_base, i, qman_base, false);
+ dev_info(hdev->dev,
+ "LowerQM. CQ: {ptr %#llx, size %u}, ARC_CQ: {ptr %#llx, size %u}, CP: {instruction %#llx}\n",
+ cq_ptr, cq_ptr_size, arc_cq_ptr, arc_cq_ptr_size, cp_current_inst);
}
static int gaudi2_handle_qman_err_generic(struct hl_device *hdev, u16 event_type,
@@ -7888,8 +7795,8 @@ static int gaudi2_handle_qman_err_generic(struct hl_device *hdev, u16 event_type
continue;
if (i == QMAN_STREAMS) {
- snprintf(reg_desc, ARRAY_SIZE(reg_desc), "LowerCP");
- num_error_causes = GAUDI2_NUM_OF_QM_LCP_ERR_CAUSE;
+ snprintf(reg_desc, ARRAY_SIZE(reg_desc), "LowerQM");
+ num_error_causes = GAUDI2_NUM_OF_LOWER_QM_ERR_CAUSE;
} else {
snprintf(reg_desc, ARRAY_SIZE(reg_desc), "stream%u", i);
num_error_causes = GAUDI2_NUM_OF_QM_ERR_CAUSE;
@@ -7900,12 +7807,13 @@ static int gaudi2_handle_qman_err_generic(struct hl_device *hdev, u16 event_type
gaudi2_print_event(hdev, event_type, true,
"%s. err cause: %s", reg_desc,
i == QMAN_STREAMS ?
- gaudi2_qman_lower_cp_error_cause[j] :
+ gaudi2_lower_qman_error_cause[j] :
gaudi2_qman_error_cause[j]);
error_count++;
}
- print_qman_data_on_err(hdev, qid_base, i, qman_base);
+ if (i == QMAN_STREAMS)
+ print_lower_qman_data_on_err(hdev, qman_base);
}
arb_err_val = RREG32(arb_err_addr);
@@ -8033,7 +7941,7 @@ static void gaudi2_ack_module_razwi_event_handler(struct hl_device *hdev,
u8 module_sub_idx, u64 *event_mask)
{
bool via_sft = false;
- u32 hbw_rtr_id, lbw_rtr_id, dcore_id, dcore_rtr_id, eng_id;
+ u32 hbw_rtr_id, lbw_rtr_id, dcore_id, dcore_rtr_id, eng_id, binned_idx;
u64 hbw_rtr_mstr_if_base_addr, lbw_rtr_mstr_if_base_addr;
u32 hbw_shrd_aw = 0, hbw_shrd_ar = 0;
u32 lbw_shrd_aw = 0, lbw_shrd_ar = 0;
@@ -8041,15 +7949,21 @@ static void gaudi2_ack_module_razwi_event_handler(struct hl_device *hdev,
switch (module) {
case RAZWI_TPC:
+ sprintf(initiator_name, "TPC_%u", module_idx);
+ if (hdev->tpc_binning) {
+ binned_idx = __ffs(hdev->tpc_binning);
+ if (binned_idx == module_idx)
+ module_idx = TPC_ID_DCORE0_TPC6;
+ }
+
hbw_rtr_id = gaudi2_tpc_initiator_hbw_rtr_id[module_idx];
- if (hl_is_fw_ver_below_1_9(hdev) &&
+ if (hl_is_fw_sw_ver_below(hdev, 1, 9) &&
!hdev->asic_prop.fw_security_enabled &&
((module_idx == 0) || (module_idx == 1)))
lbw_rtr_id = DCORE0_RTR0;
else
lbw_rtr_id = gaudi2_tpc_initiator_lbw_rtr_id[module_idx];
- sprintf(initiator_name, "TPC_%u", module_idx);
break;
case RAZWI_MME:
sprintf(initiator_name, "MME_%u", module_idx);
@@ -8108,9 +8022,14 @@ static void gaudi2_ack_module_razwi_event_handler(struct hl_device *hdev,
sprintf(initiator_name, "NIC_%u", module_idx);
break;
case RAZWI_DEC:
+ sprintf(initiator_name, "DEC_%u", module_idx);
+ if (hdev->decoder_binning) {
+ binned_idx = __ffs(hdev->decoder_binning);
+ if (binned_idx == module_idx)
+ module_idx = DEC_ID_PCIE_VDEC1;
+ }
hbw_rtr_id = gaudi2_dec_initiator_hbw_rtr_id[module_idx];
lbw_rtr_id = gaudi2_dec_initiator_lbw_rtr_id[module_idx];
- sprintf(initiator_name, "DEC_%u", module_idx);
break;
case RAZWI_ROT:
hbw_rtr_id = gaudi2_rot_initiator_hbw_rtr_id[module_idx];
@@ -8251,6 +8170,7 @@ static bool gaudi2_handle_psoc_razwi_happened(struct hl_device *hdev, u32 razwi_
u16 num_of_eng, eng_id[PSOC_RAZWI_MAX_ENG_PER_RTR];
char eng_name_str[PSOC_RAZWI_ENG_STR_SIZE];
bool razwi_happened = false;
+ u64 addr;
int i;
num_of_eng = gaudi2_psoc_razwi_get_engines(common_razwi_info, ARRAY_SIZE(common_razwi_info),
@@ -8269,43 +8189,53 @@ static bool gaudi2_handle_psoc_razwi_happened(struct hl_device *hdev, u32 razwi_
if (RREG32(base[i] + DEC_RAZWI_HBW_AW_SET)) {
addr_hi = RREG32(base[i] + DEC_RAZWI_HBW_AW_ADDR_HI);
addr_lo = RREG32(base[i] + DEC_RAZWI_HBW_AW_ADDR_LO);
- dev_err(hdev->dev,
+ addr = ((u64)addr_hi << 32) + addr_lo;
+ if (addr) {
+ dev_err(hdev->dev,
"PSOC HBW AW RAZWI: %s, address (aligned to 128 byte): 0x%llX\n",
- eng_name_str, ((u64)addr_hi << 32) + addr_lo);
- hl_handle_razwi(hdev, ((u64)addr_hi << 32) + addr_lo, &eng_id[0],
+ eng_name_str, addr);
+ hl_handle_razwi(hdev, addr, &eng_id[0],
num_of_eng, HL_RAZWI_HBW | HL_RAZWI_WRITE, event_mask);
- razwi_happened = true;
+ razwi_happened = true;
+ }
}
if (RREG32(base[i] + DEC_RAZWI_HBW_AR_SET)) {
addr_hi = RREG32(base[i] + DEC_RAZWI_HBW_AR_ADDR_HI);
addr_lo = RREG32(base[i] + DEC_RAZWI_HBW_AR_ADDR_LO);
- dev_err(hdev->dev,
+ addr = ((u64)addr_hi << 32) + addr_lo;
+ if (addr) {
+ dev_err(hdev->dev,
"PSOC HBW AR RAZWI: %s, address (aligned to 128 byte): 0x%llX\n",
- eng_name_str, ((u64)addr_hi << 32) + addr_lo);
- hl_handle_razwi(hdev, ((u64)addr_hi << 32) + addr_lo, &eng_id[0],
+ eng_name_str, addr);
+ hl_handle_razwi(hdev, addr, &eng_id[0],
num_of_eng, HL_RAZWI_HBW | HL_RAZWI_READ, event_mask);
- razwi_happened = true;
+ razwi_happened = true;
+ }
}
if (RREG32(base[i] + DEC_RAZWI_LBW_AW_SET)) {
addr_lo = RREG32(base[i] + DEC_RAZWI_LBW_AW_ADDR);
- dev_err(hdev->dev,
+ if (addr_lo) {
+ dev_err(hdev->dev,
"PSOC LBW AW RAZWI: %s, address (aligned to 128 byte): 0x%X\n",
eng_name_str, addr_lo);
- hl_handle_razwi(hdev, addr_lo, &eng_id[0],
+ hl_handle_razwi(hdev, addr_lo, &eng_id[0],
num_of_eng, HL_RAZWI_LBW | HL_RAZWI_WRITE, event_mask);
- razwi_happened = true;
+ razwi_happened = true;
+ }
}
if (RREG32(base[i] + DEC_RAZWI_LBW_AR_SET)) {
addr_lo = RREG32(base[i] + DEC_RAZWI_LBW_AR_ADDR);
- dev_err(hdev->dev,
- "PSOC LBW AR RAZWI: %s, address (aligned to 128 byte): 0x%X\n",
- eng_name_str, addr_lo);
- hl_handle_razwi(hdev, addr_lo, &eng_id[0],
+ if (addr_lo) {
+ dev_err(hdev->dev,
+ "PSOC LBW AR RAZWI: %s, address (aligned to 128 byte): 0x%X\n",
+ eng_name_str, addr_lo);
+ hl_handle_razwi(hdev, addr_lo, &eng_id[0],
num_of_eng, HL_RAZWI_LBW | HL_RAZWI_READ, event_mask);
- razwi_happened = true;
+ razwi_happened = true;
+ }
}
/* In common case the loop will break, when there is only one engine id, or
* several engines with the same router. The exceptional case is with psoc razwi
@@ -8789,13 +8719,13 @@ static int gaudi2_handle_kdma_core_event(struct hl_device *hdev, u16 event_type,
return error_count;
}
-static int gaudi2_handle_dma_core_event(struct hl_device *hdev, u16 event_type, int sts_addr)
+static int gaudi2_handle_dma_core_event(struct hl_device *hdev, u16 event_type, u64 intr_cause)
{
- u32 error_count = 0, sts_val = RREG32(sts_addr);
+ u32 error_count = 0;
int i;
for (i = 0 ; i < GAUDI2_NUM_OF_DMA_CORE_INTR_CAUSE ; i++)
- if (sts_val & BIT(i)) {
+ if (intr_cause & BIT(i)) {
gaudi2_print_event(hdev, event_type, true,
"err cause: %s", gaudi2_dma_core_interrupts_cause[i]);
error_count++;
@@ -8806,27 +8736,6 @@ static int gaudi2_handle_dma_core_event(struct hl_device *hdev, u16 event_type,
return error_count;
}
-static int gaudi2_handle_pdma_core_event(struct hl_device *hdev, u16 event_type, int pdma_idx)
-{
- u32 sts_addr;
-
- sts_addr = mmPDMA0_CORE_ERR_CAUSE + pdma_idx * PDMA_OFFSET;
- return gaudi2_handle_dma_core_event(hdev, event_type, sts_addr);
-}
-
-static int gaudi2_handle_edma_core_event(struct hl_device *hdev, u16 event_type, int edma_idx)
-{
- static const int edma_event_index_map[] = {2, 3, 0, 1, 6, 7, 4, 5};
- u32 sts_addr, index;
-
- index = edma_event_index_map[edma_idx];
-
- sts_addr = mmDCORE0_EDMA0_CORE_ERR_CAUSE +
- DCORE_OFFSET * (index / NUM_OF_EDMA_PER_DCORE) +
- DCORE_EDMA_OFFSET * (index % NUM_OF_EDMA_PER_DCORE);
- return gaudi2_handle_dma_core_event(hdev, event_type, sts_addr);
-}
-
static void gaudi2_print_pcie_mstr_rr_mstr_if_razwi_info(struct hl_device *hdev, u64 *event_mask)
{
u32 mstr_if_base_addr = mmPCIE_MSTR_RR_MSTR_IF_RR_SHRD_HBW_BASE, razwi_happened_addr;
@@ -8866,6 +8775,9 @@ static int gaudi2_print_pcie_addr_dec_info(struct hl_device *hdev, u16 event_typ
u32 error_count = 0;
int i;
+ gaudi2_print_event(hdev, event_type, true,
+ "intr_cause_data: %#llx", intr_cause_data);
+
for (i = 0 ; i < GAUDI2_NUM_OF_PCIE_ADDR_DEC_ERR_CAUSE ; i++) {
if (!(intr_cause_data & BIT_ULL(i)))
continue;
@@ -8874,16 +8786,15 @@ static int gaudi2_print_pcie_addr_dec_info(struct hl_device *hdev, u16 event_typ
"err cause: %s", gaudi2_pcie_addr_dec_error_cause[i]);
error_count++;
- switch (intr_cause_data & BIT_ULL(i)) {
- case PCIE_WRAP_PCIE_IC_SEI_INTR_IND_AXI_LBW_ERR_INTR_MASK:
- hl_check_for_glbl_errors(hdev);
- break;
- case PCIE_WRAP_PCIE_IC_SEI_INTR_IND_BAD_ACCESS_INTR_MASK:
- gaudi2_print_pcie_mstr_rr_mstr_if_razwi_info(hdev, event_mask);
- break;
- }
+ /*
+ * Always check for LBW and HBW additional info as the indication itself is
+ * sometimes missing
+ */
}
+ hl_check_for_glbl_errors(hdev);
+ gaudi2_print_pcie_mstr_rr_mstr_if_razwi_info(hdev, event_mask);
+
return error_count;
}
@@ -8937,11 +8848,16 @@ static void gaudi2_handle_page_error(struct hl_device *hdev, u64 mmu_base, bool
addr <<= 32;
addr |= RREG32(mmu_base + MMU_OFFSET(mmDCORE0_HMMU0_MMU_PAGE_ERROR_CAPTURE_VA));
- if (!is_pmmu)
+ if (is_pmmu) {
+ dev_err_ratelimited(hdev->dev, "PMMU page fault on va 0x%llx\n", addr);
+ } else {
+
addr = gaudi2_mmu_descramble_addr(hdev, addr);
+ addr &= HW_UNSCRAMBLED_BITS_MASK;
+ dev_err_ratelimited(hdev->dev, "HMMU page fault on va range 0x%llx - 0x%llx\n",
+ addr, addr + ~HW_UNSCRAMBLED_BITS_MASK);
+ }
- dev_err_ratelimited(hdev->dev, "%s page fault on va 0x%llx\n",
- is_pmmu ? "PMMU" : "HMMU", addr);
hl_handle_page_fault(hdev, addr, 0, is_pmmu, event_mask);
WREG32(mmu_base + MMU_OFFSET(mmDCORE0_HMMU0_MMU_ACCESS_PAGE_ERROR_VALID), 0);
@@ -9709,19 +9625,19 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent
case GAUDI2_EVENT_KDMA_CH0_AXI_ERR_RSP:
case GAUDI2_EVENT_KDMA0_CORE:
error_count = gaudi2_handle_kdma_core_event(hdev, event_type,
- le64_to_cpu(eq_entry->intr_cause.intr_cause_data));
+ le64_to_cpu(eq_entry->intr_cause.intr_cause_data));
event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR;
break;
case GAUDI2_EVENT_HDMA2_CORE ... GAUDI2_EVENT_HDMA5_CORE:
- index = event_type - GAUDI2_EVENT_HDMA2_CORE;
- error_count = gaudi2_handle_edma_core_event(hdev, event_type, index);
+ error_count = gaudi2_handle_dma_core_event(hdev, event_type,
+ le64_to_cpu(eq_entry->intr_cause.intr_cause_data));
event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR;
break;
case GAUDI2_EVENT_PDMA0_CORE ... GAUDI2_EVENT_PDMA1_CORE:
- index = event_type - GAUDI2_EVENT_PDMA0_CORE;
- error_count = gaudi2_handle_pdma_core_event(hdev, event_type, index);
+ error_count = gaudi2_handle_dma_core_event(hdev, event_type,
+ le64_to_cpu(eq_entry->intr_cause.intr_cause_data));
event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR;
break;
diff --git a/drivers/accel/habanalabs/gaudi2/gaudi2P.h b/drivers/accel/habanalabs/gaudi2/gaudi2P.h
index 1cebe707772e..5f3ce086928e 100644
--- a/drivers/accel/habanalabs/gaudi2/gaudi2P.h
+++ b/drivers/accel/habanalabs/gaudi2/gaudi2P.h
@@ -98,7 +98,7 @@
#define GAUDI2_DEFAULT_CARD_NAME "HL225"
#define QMAN_STREAMS 4
-#define PQ_FETCHER_CACHE_SIZE 8
+
#define NUM_OF_MME_SBTE_PORTS 5
#define NUM_OF_MME_WB_PORTS 2
diff --git a/drivers/accel/habanalabs/gaudi2/gaudi2_security.c b/drivers/accel/habanalabs/gaudi2/gaudi2_security.c
index 694735f9e6e6..2742b1f801eb 100644
--- a/drivers/accel/habanalabs/gaudi2/gaudi2_security.c
+++ b/drivers/accel/habanalabs/gaudi2/gaudi2_security.c
@@ -479,6 +479,7 @@ static const u32 gaudi2_pb_dcr0_edma0_unsecured_regs[] = {
mmDCORE0_EDMA0_CORE_CTX_TE_NUMROWS,
mmDCORE0_EDMA0_CORE_CTX_IDX,
mmDCORE0_EDMA0_CORE_CTX_IDX_INC,
+ mmDCORE0_EDMA0_CORE_RD_LBW_RATE_LIM_CFG,
mmDCORE0_EDMA0_QM_CQ_CFG0_0,
mmDCORE0_EDMA0_QM_CQ_CFG0_1,
mmDCORE0_EDMA0_QM_CQ_CFG0_2,
@@ -1533,6 +1534,10 @@ static const u32 gaudi2_pb_dcr0_tpc0_unsecured_regs[] = {
mmDCORE0_TPC0_CFG_QM_KERNEL_CONFIG,
mmDCORE0_TPC0_CFG_QM_KERNEL_ID,
mmDCORE0_TPC0_CFG_QM_POWER_LOOP,
+ mmDCORE0_TPC0_CFG_TSB_CFG_MTRR_2_0,
+ mmDCORE0_TPC0_CFG_TSB_CFG_MTRR_2_1,
+ mmDCORE0_TPC0_CFG_TSB_CFG_MTRR_2_2,
+ mmDCORE0_TPC0_CFG_TSB_CFG_MTRR_2_3,
mmDCORE0_TPC0_CFG_LUT_FUNC32_BASE2_ADDR_LO,
mmDCORE0_TPC0_CFG_LUT_FUNC32_BASE2_ADDR_HI,
mmDCORE0_TPC0_CFG_LUT_FUNC64_BASE2_ADDR_LO,
@@ -1541,6 +1546,7 @@ static const u32 gaudi2_pb_dcr0_tpc0_unsecured_regs[] = {
mmDCORE0_TPC0_CFG_LUT_FUNC128_BASE2_ADDR_HI,
mmDCORE0_TPC0_CFG_LUT_FUNC256_BASE2_ADDR_LO,
mmDCORE0_TPC0_CFG_LUT_FUNC256_BASE2_ADDR_HI,
+ mmDCORE0_TPC0_CFG_FP8_143_BIAS,
mmDCORE0_TPC0_CFG_ROUND_CSR,
mmDCORE0_TPC0_CFG_CONV_ROUND_CSR,
mmDCORE0_TPC0_CFG_SEMAPHORE,
@@ -3442,15 +3448,6 @@ static int gaudi2_init_protection_bits(struct hl_device *hdev)
ARRAY_SIZE(gaudi2_pb_thermal_sensor0), NULL, HL_PB_NA);
}
- /* HBM */
- /* Temporarily skip until SW-63348 is solved
- * instance_offset = mmHBM1_MC0_BASE - mmHBM0_MC0_BASE;
- * rc |= hl_init_pb_with_mask(hdev, HL_PB_SHARED, HL_PB_NA, GAUDI2_HBM_NUM,
- * instance_offset, gaudi2_pb_hbm,
- * ARRAY_SIZE(gaudi2_pb_hbm), NULL, HL_PB_NA,
- * prop->dram_enabled_mask);
- */
-
/* Scheduler ARCs */
instance_offset = mmARC_FARM_ARC1_AUX_BASE - mmARC_FARM_ARC0_AUX_BASE;
rc |= hl_init_pb_ranges(hdev, HL_PB_SHARED, HL_PB_NA,
diff --git a/drivers/accel/habanalabs/goya/goya.c b/drivers/accel/habanalabs/goya/goya.c
index fb0ac9df841a..7c685e6075f6 100644
--- a/drivers/accel/habanalabs/goya/goya.c
+++ b/drivers/accel/habanalabs/goya/goya.c
@@ -2671,9 +2671,6 @@ int goya_mmu_init(struct hl_device *hdev)
u64 hop0_addr;
int rc, i;
- if (!hdev->mmu_enable)
- return 0;
-
if (goya->hw_cap_initialized & HW_CAP_MMU)
return 0;
diff --git a/drivers/accel/habanalabs/goya/goya_coresight.c b/drivers/accel/habanalabs/goya/goya_coresight.c
index e7ac3046cfaa..a6d6cc38bcd8 100644
--- a/drivers/accel/habanalabs/goya/goya_coresight.c
+++ b/drivers/accel/habanalabs/goya/goya_coresight.c
@@ -371,13 +371,8 @@ static int goya_etr_validate_address(struct hl_device *hdev, u64 addr,
return false;
}
- if (hdev->mmu_enable) {
- range_start = prop->dmmu.start_addr;
- range_end = prop->dmmu.end_addr;
- } else {
- range_start = prop->dram_user_base_address;
- range_end = prop->dram_end_address;
- }
+ range_start = prop->dmmu.start_addr;
+ range_end = prop->dmmu.end_addr;
return hl_mem_area_inside_range(addr, size, range_start, range_end);
}
diff --git a/drivers/accel/habanalabs/include/common/cpucp_if.h b/drivers/accel/habanalabs/include/common/cpucp_if.h
index 8bbe685458c4..33807b839c37 100644
--- a/drivers/accel/habanalabs/include/common/cpucp_if.h
+++ b/drivers/accel/habanalabs/include/common/cpucp_if.h
@@ -359,7 +359,7 @@ struct hl_eq_entry {
union {
__le64 data_placeholder;
struct hl_eq_ecc_data ecc_data;
- struct hl_eq_hbm_ecc_data hbm_ecc_data; /* Gaudi1 HBM */
+ struct hl_eq_hbm_ecc_data hbm_ecc_data; /* Obsolete */
struct hl_eq_sm_sei_data sm_sei_data;
struct cpucp_pkt_sync_err pkt_sync_err;
struct hl_eq_fw_alive fw_alive;
@@ -653,7 +653,7 @@ enum pq_init_status {
* which address is passed via the CpuCp packet. In addition, the host's driver
* passes the max size it allows the CpuCP to write to the structure, to prevent
* data corruption in case of mismatched driver/FW versions.
- * Relevant only to Gaudi.
+ * Obsolete.
*
* CPUCP_PACKET_GENERIC_PASSTHROUGH -
* Generic opcode for all firmware info that is only passed to host
@@ -665,6 +665,9 @@ enum pq_init_status {
*
* CPUCP_PACKET_REGISTER_INTERRUPTS -
* Packet to register interrupts indicating LKD is ready to receive events from FW.
+ *
+ * CPUCP_PACKET_SOFT_RESET -
+ * Packet to perform soft-reset.
*/
enum cpucp_packet_id {
@@ -731,6 +734,7 @@ enum cpucp_packet_id {
CPUCP_PACKET_RESERVED11, /* not used */
CPUCP_PACKET_RESERVED12, /* internal */
CPUCP_PACKET_REGISTER_INTERRUPTS, /* internal */
+ CPUCP_PACKET_SOFT_RESET, /* internal */
CPUCP_PACKET_ID_MAX /* must be last */
};
@@ -864,19 +868,19 @@ struct cpucp_array_data_packet {
enum cpucp_led_index {
CPUCP_LED0_INDEX = 0,
CPUCP_LED1_INDEX,
- CPUCP_LED2_INDEX
+ CPUCP_LED2_INDEX,
+ CPUCP_LED_MAX_INDEX = CPUCP_LED2_INDEX
};
/*
* enum cpucp_packet_rc - Error return code
* @cpucp_packet_success -> in case of success.
- * @cpucp_packet_invalid -> this is to support Goya and Gaudi platform.
+ * @cpucp_packet_invalid -> this is to support first generation platforms.
* @cpucp_packet_fault -> in case of processing error like failing to
* get device binding or semaphore etc.
- * @cpucp_packet_invalid_pkt -> when cpucp packet is un-supported. This is
- * supported Greco onwards.
+ * @cpucp_packet_invalid_pkt -> when cpucp packet is un-supported.
* @cpucp_packet_invalid_params -> when checking parameter like length of buffer
- * or attribute value etc. Supported Greco onwards.
+ * or attribute value etc.
* @cpucp_packet_rc_max -> It indicates size of enum so should be at last.
*/
enum cpucp_packet_rc {
@@ -1361,7 +1365,7 @@ struct cpucp_dev_info_signed {
#define DCORE_MON_REGS_SZ 512
/*
* struct dcore_monitor_regs_data - DCORE monitor regs data.
- * the structure follows sync manager block layout. relevant only to Gaudi.
+ * the structure follows sync manager block layout. Obsolete.
* @mon_pay_addrl: array of payload address low bits.
* @mon_pay_addrh: array of payload address high bits.
* @mon_pay_data: array of payload data.
@@ -1376,7 +1380,7 @@ struct dcore_monitor_regs_data {
__le32 mon_status[DCORE_MON_REGS_SZ];
};
-/* contains SM data for each SYNC_MNGR (relevant only to Gaudi) */
+/* contains SM data for each SYNC_MNGR (Obsolete) */
struct cpucp_monitor_dump {
struct dcore_monitor_regs_data sync_mngr_w_s;
struct dcore_monitor_regs_data sync_mngr_e_s;
diff --git a/drivers/accel/habanalabs/include/common/hl_boot_if.h b/drivers/accel/habanalabs/include/common/hl_boot_if.h
index c58d76a2705c..cff79f7f9f75 100644
--- a/drivers/accel/habanalabs/include/common/hl_boot_if.h
+++ b/drivers/accel/habanalabs/include/common/hl_boot_if.h
@@ -35,6 +35,7 @@ enum cpu_boot_err {
CPU_BOOT_ERR_TPM_FAIL = 20,
CPU_BOOT_ERR_TMP_THRESH_INIT_FAIL = 21,
CPU_BOOT_ERR_EEPROM_FAIL = 22,
+ CPU_BOOT_ERR_ENG_ARC_MEM_SCRUB_FAIL = 23,
CPU_BOOT_ERR_ENABLED = 31,
CPU_BOOT_ERR_SCND_EN = 63,
CPU_BOOT_ERR_LAST = 64 /* we have 2 registers of 32 bits */
@@ -51,6 +52,7 @@ enum cpu_boot_err {
(1 << CPU_BOOT_ERR_DEVICE_UNUSABLE_FAIL) | \
(1 << CPU_BOOT_ERR_BINNING_FAIL) | \
(1 << CPU_BOOT_ERR_DRAM_SKIPPED) | \
+ (1 << CPU_BOOT_ERR_ENG_ARC_MEM_SCRUB_FAIL) | \
(1 << CPU_BOOT_ERR_EEPROM_FAIL))
/*
@@ -132,6 +134,9 @@ enum cpu_boot_err {
* CPU_BOOT_ERR_EEPROM_FAIL Failed reading EEPROM data. Defaults
* are used.
*
+ * CPU_BOOT_ERR_ENG_ARC_MEM_SCRUB_FAIL Failed scrubbing the Engines/ARCFarm
+ * memories. Boot disabled until reset.
+ *
* CPU_BOOT_ERR0_ENABLED Error registers enabled.
* This is a main indication that the
* running FW populates the error
@@ -157,6 +162,7 @@ enum cpu_boot_err {
#define CPU_BOOT_ERR0_TPM_FAIL (1 << CPU_BOOT_ERR_TPM_FAIL)
#define CPU_BOOT_ERR0_TMP_THRESH_INIT_FAIL (1 << CPU_BOOT_ERR_TMP_THRESH_INIT_FAIL)
#define CPU_BOOT_ERR0_EEPROM_FAIL (1 << CPU_BOOT_ERR_EEPROM_FAIL)
+#define CPU_BOOT_ERR0_ENG_ARC_MEM_SCRUB_FAIL (1 << CPU_BOOT_ERR_ENG_ARC_MEM_SCRUB_FAIL)
#define CPU_BOOT_ERR0_ENABLED (1 << CPU_BOOT_ERR_ENABLED)
#define CPU_BOOT_ERR1_ENABLED (1 << CPU_BOOT_ERR_ENABLED)
@@ -744,36 +750,6 @@ struct comms_status {
};
};
-/**
- * HL_MODULES_MAX_NUM is determined by the size of modules_mask in struct
- * hl_component_versions
- */
-enum hl_modules {
- HL_MODULES_BOOT_INFO = 0,
- HL_MODULES_EEPROM,
- HL_MODULES_FDT,
- HL_MODULES_I2C,
- HL_MODULES_LZ4,
- HL_MODULES_MBEDTLS,
- HL_MODULES_MAX_NUM = 16
-};
-
-/**
- * HL_COMPONENTS_MAX_NUM is determined by the size of components_mask in
- * struct cpucp_versions
- */
-enum hl_components {
- HL_COMPONENTS_PID = 0,
- HL_COMPONENTS_MGMT,
- HL_COMPONENTS_PREBOOT,
- HL_COMPONENTS_PPBOOT,
- HL_COMPONENTS_ARMCP,
- HL_COMPONENTS_CPLD,
- HL_COMPONENTS_UBOOT,
- HL_COMPONENTS_FUSE,
- HL_COMPONENTS_MAX_NUM = 16
-};
-
#define NAME_MAX_LEN 32 /* bytes */
struct hl_module_data {
__u8 name[NAME_MAX_LEN];
@@ -787,8 +763,6 @@ struct hl_module_data {
* @component: version of the component itself.
* @fw_os: Firmware OS Version.
* @comp_name: Name of the component.
- * @modules_mask: i'th bit (from LSB) is a flag - on if module i in enum
- * hl_modules is used.
* @modules_counter: number of set bits in modules_mask.
* @reserved: reserved for future use.
* @modules: versions of the component's modules. Elborated explanation in
@@ -800,9 +774,8 @@ struct hl_component_versions {
__u8 component[VERSION_MAX_LEN];
__u8 fw_os[VERSION_MAX_LEN];
__u8 comp_name[NAME_MAX_LEN];
- __le16 modules_mask;
__u8 modules_counter;
- __u8 reserved[1];
+ __u8 reserved[3];
struct hl_module_data modules[];
};
diff --git a/drivers/accel/habanalabs/include/gaudi2/asic_reg/gaudi2_regs.h b/drivers/accel/habanalabs/include/gaudi2/asic_reg/gaudi2_regs.h
index 6c58af614236..a08378d0802b 100644
--- a/drivers/accel/habanalabs/include/gaudi2/asic_reg/gaudi2_regs.h
+++ b/drivers/accel/habanalabs/include/gaudi2/asic_reg/gaudi2_regs.h
@@ -242,6 +242,17 @@
#define QM_FENCE2_OFFSET (mmPDMA0_QM_CP_FENCE2_RDATA_0 - mmPDMA0_QM_BASE)
#define QM_SEI_STATUS_OFFSET (mmPDMA0_QM_SEI_STATUS - mmPDMA0_QM_BASE)
+#define QM_CQ_PTR_LO_4_OFFSET (mmPDMA0_QM_CQ_PTR_LO_4 - mmPDMA0_QM_BASE)
+#define QM_CQ_PTR_HI_4_OFFSET (mmPDMA0_QM_CQ_PTR_HI_4 - mmPDMA0_QM_BASE)
+#define QM_CQ_TSIZE_4_OFFSET (mmPDMA0_QM_CQ_TSIZE_4 - mmPDMA0_QM_BASE)
+
+#define QM_ARC_CQ_PTR_LO_OFFSET (mmPDMA0_QM_ARC_CQ_PTR_LO - mmPDMA0_QM_BASE)
+#define QM_ARC_CQ_PTR_HI_OFFSET (mmPDMA0_QM_ARC_CQ_PTR_HI - mmPDMA0_QM_BASE)
+#define QM_ARC_CQ_TSIZE_OFFSET (mmPDMA0_QM_ARC_CQ_TSIZE - mmPDMA0_QM_BASE)
+
+#define QM_CP_CURRENT_INST_LO_4_OFFSET (mmPDMA0_QM_CP_CURRENT_INST_LO_4 - mmPDMA0_QM_BASE)
+#define QM_CP_CURRENT_INST_HI_4_OFFSET (mmPDMA0_QM_CP_CURRENT_INST_HI_4 - mmPDMA0_QM_BASE)
+
#define SFT_OFFSET (mmSFT1_HBW_RTR_IF0_RTR_H3_BASE - mmSFT0_HBW_RTR_IF0_RTR_H3_BASE)
#define SFT_IF_RTR_OFFSET (mmSFT0_HBW_RTR_IF1_RTR_H3_BASE - mmSFT0_HBW_RTR_IF0_RTR_H3_BASE)
diff --git a/drivers/accel/habanalabs/include/gaudi2/gaudi2_fw_if.h b/drivers/accel/habanalabs/include/gaudi2/gaudi2_fw_if.h
index 8522f24deac0..18ca147b1c86 100644
--- a/drivers/accel/habanalabs/include/gaudi2/gaudi2_fw_if.h
+++ b/drivers/accel/habanalabs/include/gaudi2/gaudi2_fw_if.h
@@ -62,7 +62,7 @@ struct gaudi2_cold_rst_data {
u32 fake_security_enable : 1;
u32 fake_sig_validation_en : 1;
u32 bist_skip_enable : 1;
- u32 bist_need_iatu_config : 1;
+ u32 reserved1 : 1;
u32 fake_bis_compliant : 1;
u32 wd_rst_cause_arm : 1;
u32 wd_rst_cause_arcpid : 1;
diff --git a/drivers/accessibility/speakup/Kconfig b/drivers/accessibility/speakup/Kconfig
index 07ecbbde0384..e84fb617acc4 100644
--- a/drivers/accessibility/speakup/Kconfig
+++ b/drivers/accessibility/speakup/Kconfig
@@ -46,6 +46,7 @@ if SPEAKUP
config SPEAKUP_SERIALIO
def_bool y
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
config SPEAKUP_SYNTH_ACNTSA
tristate "Accent SA synthesizer support"
diff --git a/drivers/accessibility/speakup/main.c b/drivers/accessibility/speakup/main.c
index 56c073103cbb..1fbc9b921c4f 100644
--- a/drivers/accessibility/speakup/main.c
+++ b/drivers/accessibility/speakup/main.c
@@ -1287,7 +1287,7 @@ static struct var_t spk_vars[NB_ID] = {
[PUNC_LEVEL_ID] = { PUNC_LEVEL, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
[READING_PUNC_ID] = { READING_PUNC, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
[CURSOR_TIME_ID] = { CURSOR_TIME, .u.n = {NULL, 120, 50, 600, 0, 0, NULL} },
- [SAY_CONTROL_ID] { SAY_CONTROL, TOGGLE_0},
+ [SAY_CONTROL_ID] = { SAY_CONTROL, TOGGLE_0},
[SAY_WORD_CTL_ID] = {SAY_WORD_CTL, TOGGLE_0},
[NO_INTERRUPT_ID] = { NO_INTERRUPT, TOGGLE_0},
[KEY_ECHO_ID] = { KEY_ECHO, .u.n = {NULL, 1, 0, 2, 0, 0, NULL} },
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ccbeab9500ec..00dd309b6682 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -542,10 +542,10 @@ config ACPI_PFRUT
if ARM64
source "drivers/acpi/arm64/Kconfig"
+endif
config ACPI_PPTT
bool
-endif
config ACPI_PCC
bool "ACPI PCC Address Space"
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index feb36c0b9446..3fc5a0d54f6e 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -131,3 +131,5 @@ obj-y += dptf/
obj-$(CONFIG_ARM64) += arm64/
obj-$(CONFIG_ACPI_VIOT) += viot.o
+
+obj-$(CONFIG_RISCV) += riscv/
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 8569f55e55b6..660834a49c1f 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -1267,12 +1267,8 @@ static void acpi_ec_event_handler(struct work_struct *work)
spin_unlock_irq(&ec->lock);
}
-static void acpi_ec_handle_interrupt(struct acpi_ec *ec)
+static void clear_gpe_and_advance_transaction(struct acpi_ec *ec, bool interrupt)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ec->lock, flags);
-
/*
* Clear GPE_STS upfront to allow subsequent hardware GPE_STS 0->1
* changes to always trigger a GPE interrupt.
@@ -1289,6 +1285,16 @@ static void acpi_ec_handle_interrupt(struct acpi_ec *ec)
acpi_clear_gpe(NULL, ec->gpe);
advance_transaction(ec, true);
+}
+
+static void acpi_ec_handle_interrupt(struct acpi_ec *ec)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ec->lock, flags);
+
+ clear_gpe_and_advance_transaction(ec, true);
+
spin_unlock_irqrestore(&ec->lock, flags);
}
@@ -2083,7 +2089,7 @@ bool acpi_ec_dispatch_gpe(void)
if (acpi_ec_gpe_status_set(first_ec)) {
pm_pr_dbg("ACPI EC GPE status set\n");
- advance_transaction(first_ec, false);
+ clear_gpe_and_advance_transaction(first_ec, false);
work_in_progress = acpi_ec_work_in_progress(first_ec);
}
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 3269a888fb7a..f725813d0cce 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -276,7 +276,7 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
return NULL;
}
-#if defined(CONFIG_IA64) || defined(CONFIG_ARM64)
+#if defined(CONFIG_IA64) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
/* ioremap will take care of cache attributes */
#define should_use_kmap(pfn) 0
#else
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 2ac48cda5b20..d6606a9f2da6 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -106,6 +106,32 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry,
return -EINVAL;
}
+/*
+ * Retrieve the RISC-V hartid for the processor
+ */
+static int map_rintc_hartid(struct acpi_subtable_header *entry,
+ int device_declaration, u32 acpi_id,
+ phys_cpuid_t *hartid)
+{
+ struct acpi_madt_rintc *rintc =
+ container_of(entry, struct acpi_madt_rintc, header);
+
+ if (!(rintc->flags & ACPI_MADT_ENABLED))
+ return -ENODEV;
+
+ /* device_declaration means Device object in DSDT, in the
+ * RISC-V, logical processors are required to
+ * have a Processor Device object in the DSDT, so we should
+ * check device_declaration here
+ */
+ if (device_declaration && rintc->uid == acpi_id) {
+ *hartid = rintc->hart_id;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
int type, u32 acpi_id)
{
@@ -136,6 +162,9 @@ static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
} else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
if (!map_gicc_mpidr(header, type, acpi_id, &phys_id))
break;
+ } else if (header->type == ACPI_MADT_TYPE_RINTC) {
+ if (!map_rintc_hartid(header, type, acpi_id, &phys_id))
+ break;
}
entry += header->length;
}
diff --git a/drivers/acpi/riscv/Makefile b/drivers/acpi/riscv/Makefile
new file mode 100644
index 000000000000..8b3b126e0b94
--- /dev/null
+++ b/drivers/acpi/riscv/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += rhct.o
diff --git a/drivers/acpi/riscv/rhct.c b/drivers/acpi/riscv/rhct.c
new file mode 100644
index 000000000000..b280b3e9c7d9
--- /dev/null
+++ b/drivers/acpi/riscv/rhct.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2022-2023, Ventana Micro Systems Inc
+ * Author: Sunil V L <sunilvl@ventanamicro.com>
+ *
+ */
+
+#define pr_fmt(fmt) "ACPI: RHCT: " fmt
+
+#include <linux/acpi.h>
+
+static struct acpi_table_header *acpi_get_rhct(void)
+{
+ static struct acpi_table_header *rhct;
+ acpi_status status;
+
+ /*
+ * RHCT will be used at runtime on every CPU, so we
+ * don't need to call acpi_put_table() to release the table mapping.
+ */
+ if (!rhct) {
+ status = acpi_get_table(ACPI_SIG_RHCT, 0, &rhct);
+ if (ACPI_FAILURE(status)) {
+ pr_warn_once("No RHCT table found\n");
+ return NULL;
+ }
+ }
+
+ return rhct;
+}
+
+/*
+ * During early boot, the caller should call acpi_get_table() and pass its pointer to
+ * these functions(and free up later). At run time, since this table can be used
+ * multiple times, NULL may be passed in order to use the cached table.
+ */
+int acpi_get_riscv_isa(struct acpi_table_header *table, unsigned int cpu, const char **isa)
+{
+ struct acpi_rhct_node_header *node, *ref_node, *end;
+ u32 size_hdr = sizeof(struct acpi_rhct_node_header);
+ u32 size_hartinfo = sizeof(struct acpi_rhct_hart_info);
+ struct acpi_rhct_hart_info *hart_info;
+ struct acpi_rhct_isa_string *isa_node;
+ struct acpi_table_rhct *rhct;
+ u32 *hart_info_node_offset;
+ u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+
+ BUG_ON(acpi_disabled);
+
+ if (!table) {
+ rhct = (struct acpi_table_rhct *)acpi_get_rhct();
+ if (!rhct)
+ return -ENOENT;
+ } else {
+ rhct = (struct acpi_table_rhct *)table;
+ }
+
+ end = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->header.length);
+
+ for (node = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->node_offset);
+ node < end;
+ node = ACPI_ADD_PTR(struct acpi_rhct_node_header, node, node->length)) {
+ if (node->type == ACPI_RHCT_NODE_TYPE_HART_INFO) {
+ hart_info = ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, size_hdr);
+ hart_info_node_offset = ACPI_ADD_PTR(u32, hart_info, size_hartinfo);
+ if (acpi_cpu_id != hart_info->uid)
+ continue;
+
+ for (int i = 0; i < hart_info->num_offsets; i++) {
+ ref_node = ACPI_ADD_PTR(struct acpi_rhct_node_header,
+ rhct, hart_info_node_offset[i]);
+ if (ref_node->type == ACPI_RHCT_NODE_TYPE_ISA_STRING) {
+ isa_node = ACPI_ADD_PTR(struct acpi_rhct_isa_string,
+ ref_node, size_hdr);
+ *isa = isa_node->isa;
+ return 0;
+ }
+ }
+ }
+ }
+
+ return -1;
+}
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 7b4680da57d7..8ab0a82b4da4 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -220,6 +220,16 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
}
break;
+ case ACPI_MADT_TYPE_RINTC:
+ {
+ struct acpi_madt_rintc *p = (struct acpi_madt_rintc *)header;
+
+ pr_debug("RISC-V INTC (acpi_uid[0x%04x] hart_id[0x%llx] %s)\n",
+ p->uid, p->hart_id,
+ (p->flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
+ }
+ break;
+
default:
pr_warn("Found unsupported MADT entry (type = 0x%x)\n",
header->type);
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 8fb7672021ee..486c8271cab7 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -66,6 +66,7 @@
#include <linux/syscalls.h>
#include <linux/task_work.h>
#include <linux/sizes.h>
+#include <linux/ktime.h>
#include <uapi/linux/android/binder.h>
@@ -2918,6 +2919,7 @@ static void binder_transaction(struct binder_proc *proc,
binder_size_t last_fixup_min_off = 0;
struct binder_context *context = proc->context;
int t_debug_id = atomic_inc_return(&binder_last_id);
+ ktime_t t_start_time = ktime_get();
char *secctx = NULL;
u32 secctx_sz = 0;
struct list_head sgc_head;
@@ -3159,6 +3161,7 @@ static void binder_transaction(struct binder_proc *proc,
binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
t->debug_id = t_debug_id;
+ t->start_time = t_start_time;
if (reply)
binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -3183,6 +3186,8 @@ static void binder_transaction(struct binder_proc *proc,
t->from = thread;
else
t->from = NULL;
+ t->from_pid = proc->pid;
+ t->from_tid = thread->pid;
t->sender_euid = task_euid(proc->tsk);
t->to_proc = target_proc;
t->to_thread = target_thread;
@@ -5944,17 +5949,19 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
{
struct binder_proc *to_proc;
struct binder_buffer *buffer = t->buffer;
+ ktime_t current_time = ktime_get();
spin_lock(&t->lock);
to_proc = t->to_proc;
seq_printf(m,
- "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d",
+ "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d elapsed %lldms",
prefix, t->debug_id, t,
- t->from ? t->from->proc->pid : 0,
- t->from ? t->from->pid : 0,
+ t->from_pid,
+ t->from_tid,
to_proc ? to_proc->pid : 0,
t->to_thread ? t->to_thread->pid : 0,
- t->code, t->flags, t->priority, t->need_reply);
+ t->code, t->flags, t->priority, t->need_reply,
+ ktime_ms_delta(current_time, t->start_time));
spin_unlock(&t->lock);
if (proc != to_proc) {
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index 28ef5b3704b1..7270d4d22207 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -515,6 +515,8 @@ struct binder_transaction {
int debug_id;
struct binder_work work;
struct binder_thread *from;
+ pid_t from_pid;
+ pid_t from_tid;
struct binder_transaction *from_parent;
struct binder_proc *to_proc;
struct binder_thread *to_thread;
@@ -528,6 +530,7 @@ struct binder_transaction {
long priority;
long saved_priority;
kuid_t sender_euid;
+ ktime_t start_time;
struct list_head fd_fixups;
binder_uintptr_t security_ctx;
/**
diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c
index 4e3dc2b6d67f..70c3a33eee6f 100644
--- a/drivers/ata/ahci_brcm.c
+++ b/drivers/ata/ahci_brcm.c
@@ -544,7 +544,7 @@ out_reset:
return ret;
}
-static int brcm_ahci_remove(struct platform_device *pdev)
+static void brcm_ahci_remove(struct platform_device *pdev)
{
struct ata_host *host = dev_get_drvdata(&pdev->dev);
struct ahci_host_priv *hpriv = host->private_data;
@@ -552,7 +552,7 @@ static int brcm_ahci_remove(struct platform_device *pdev)
brcm_sata_phys_disable(priv);
- return ata_platform_remove_one(pdev);
+ ata_platform_remove_one(pdev);
}
static void brcm_ahci_shutdown(struct platform_device *pdev)
@@ -573,7 +573,7 @@ static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume);
static struct platform_driver brcm_ahci_driver = {
.probe = brcm_ahci_probe,
- .remove = brcm_ahci_remove,
+ .remove_new = brcm_ahci_remove,
.shutdown = brcm_ahci_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c
index bc027468decb..c2b6be083af4 100644
--- a/drivers/ata/ahci_ceva.c
+++ b/drivers/ata/ahci_ceva.c
@@ -369,7 +369,7 @@ MODULE_DEVICE_TABLE(of, ceva_ahci_of_match);
static struct platform_driver ceva_ahci_driver = {
.probe = ceva_ahci_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = ceva_ahci_of_match,
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c
index ca0924dc5bd2..55a6627d5450 100644
--- a/drivers/ata/ahci_da850.c
+++ b/drivers/ata/ahci_da850.c
@@ -238,7 +238,7 @@ MODULE_DEVICE_TABLE(of, ahci_da850_of_match);
static struct platform_driver ahci_da850_driver = {
.probe = ahci_da850_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = ahci_da850_of_match,
diff --git a/drivers/ata/ahci_dm816.c b/drivers/ata/ahci_dm816.c
index b08547b877a1..4cb70064fb99 100644
--- a/drivers/ata/ahci_dm816.c
+++ b/drivers/ata/ahci_dm816.c
@@ -182,7 +182,7 @@ MODULE_DEVICE_TABLE(of, ahci_dm816_of_match);
static struct platform_driver ahci_dm816_driver = {
.probe = ahci_dm816_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.driver = {
.name = AHCI_DM816_DRV_NAME,
.of_match_table = ahci_dm816_of_match,
diff --git a/drivers/ata/ahci_dwc.c b/drivers/ata/ahci_dwc.c
index 4bfbb09cdc02..9604a2f6ed48 100644
--- a/drivers/ata/ahci_dwc.c
+++ b/drivers/ata/ahci_dwc.c
@@ -478,7 +478,7 @@ MODULE_DEVICE_TABLE(of, ahci_dwc_of_match);
static struct platform_driver ahci_dwc_driver = {
.probe = ahci_dwc_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.shutdown = ahci_platform_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 3a8c248e7c0e..9fa005965f3b 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -1223,7 +1223,7 @@ static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume);
static struct platform_driver imx_ahci_driver = {
.probe = imx_ahci_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = imx_ahci_of_match,
diff --git a/drivers/ata/ahci_mtk.c b/drivers/ata/ahci_mtk.c
index 0bf83a297091..5083fb6c4927 100644
--- a/drivers/ata/ahci_mtk.c
+++ b/drivers/ata/ahci_mtk.c
@@ -173,7 +173,7 @@ MODULE_DEVICE_TABLE(of, ahci_of_match);
static struct platform_driver mtk_ahci_driver = {
.probe = mtk_ahci_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = ahci_of_match,
diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c
index 596cf017f427..764501518582 100644
--- a/drivers/ata/ahci_mvebu.c
+++ b/drivers/ata/ahci_mvebu.c
@@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, ahci_mvebu_of_match);
static struct platform_driver ahci_mvebu_driver = {
.probe = ahci_mvebu_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.suspend = ahci_mvebu_suspend,
.resume = ahci_mvebu_resume,
.driver = {
diff --git a/drivers/ata/ahci_octeon.c b/drivers/ata/ahci_octeon.c
index 5021ab3ede49..e89807fa928e 100644
--- a/drivers/ata/ahci_octeon.c
+++ b/drivers/ata/ahci_octeon.c
@@ -16,7 +16,6 @@
#include <linux/of_platform.h>
#include <asm/octeon/octeon.h>
-#include <asm/bitfield.h>
#define CVMX_SATA_UCTL_SHIM_CFG 0xE8
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 299ee686ac49..81fc63f6b008 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -9,14 +9,14 @@
*/
#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/device.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/libata.h>
#include <linux/ahci_platform.h>
-#include <linux/acpi.h>
#include <linux/pci_ids.h>
#include "ahci.h"
@@ -56,10 +56,10 @@ static int ahci_probe(struct platform_device *pdev)
if (rc)
return rc;
- if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci"))
+ if (device_is_compatible(dev, "hisilicon,hisi-ahci"))
hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ;
- port = acpi_device_get_match_data(dev);
+ port = device_get_match_data(dev);
if (!port)
port = &ahci_port_info;
@@ -96,7 +96,7 @@ MODULE_DEVICE_TABLE(acpi, ahci_acpi_match);
static struct platform_driver ahci_driver = {
.probe = ahci_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.shutdown = ahci_platform_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
index 0ba764d283c8..3d01b118c9a1 100644
--- a/drivers/ata/ahci_qoriq.c
+++ b/drivers/ata/ahci_qoriq.c
@@ -359,7 +359,7 @@ static SIMPLE_DEV_PM_OPS(ahci_qoriq_pm_ops, ahci_platform_suspend,
static struct platform_driver ahci_qoriq_driver = {
.probe = ahci_qoriq_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = ahci_qoriq_of_match,
diff --git a/drivers/ata/ahci_seattle.c b/drivers/ata/ahci_seattle.c
index 9eda7bbd2151..2c32d58c6ae7 100644
--- a/drivers/ata/ahci_seattle.c
+++ b/drivers/ata/ahci_seattle.c
@@ -187,7 +187,7 @@ MODULE_DEVICE_TABLE(acpi, ahci_acpi_match);
static struct platform_driver ahci_seattle_driver = {
.probe = ahci_seattle_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.acpi_match_table = ahci_acpi_match,
diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c
index f2c1edb36986..d4a626f87963 100644
--- a/drivers/ata/ahci_st.c
+++ b/drivers/ata/ahci_st.c
@@ -239,7 +239,7 @@ static struct platform_driver st_ahci_driver = {
.of_match_table = st_ahci_match,
},
.probe = st_ahci_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
};
module_platform_driver(st_ahci_driver);
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
index 076c12b4ba08..04531fa95e40 100644
--- a/drivers/ata/ahci_sunxi.c
+++ b/drivers/ata/ahci_sunxi.c
@@ -292,7 +292,7 @@ MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match);
static struct platform_driver ahci_sunxi_driver = {
.probe = ahci_sunxi_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = ahci_sunxi_of_match,
diff --git a/drivers/ata/ahci_tegra.c b/drivers/ata/ahci_tegra.c
index 8e5e2b359f2d..21c20793e517 100644
--- a/drivers/ata/ahci_tegra.c
+++ b/drivers/ata/ahci_tegra.c
@@ -609,7 +609,7 @@ deinit_controller:
static struct platform_driver tegra_ahci_driver = {
.probe = tegra_ahci_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = tegra_ahci_of_match,
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index 83f5ff54ef5b..eb773f2e28fc 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -868,7 +868,7 @@ disable_resources:
static struct platform_driver xgene_ahci_driver = {
.probe = xgene_ahci_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = xgene_ahci_of_match,
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 9c2cb6cbea76..06aec35f88f2 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -975,44 +975,43 @@ int ahci_reset_controller(struct ata_host *host)
void __iomem *mmio = hpriv->mmio;
u32 tmp;
- /* we must be in AHCI mode, before using anything
- * AHCI-specific, such as HOST_RESET.
+ /*
+ * We must be in AHCI mode, before using anything AHCI-specific, such
+ * as HOST_RESET.
*/
ahci_enable_ahci(mmio);
- /* global controller reset */
- if (!ahci_skip_host_reset) {
- tmp = readl(mmio + HOST_CTL);
- if ((tmp & HOST_RESET) == 0) {
- writel(tmp | HOST_RESET, mmio + HOST_CTL);
- readl(mmio + HOST_CTL); /* flush */
- }
+ /* Global controller reset */
+ if (ahci_skip_host_reset) {
+ dev_info(host->dev, "Skipping global host reset\n");
+ return 0;
+ }
- /*
- * to perform host reset, OS should set HOST_RESET
- * and poll until this bit is read to be "0".
- * reset must complete within 1 second, or
- * the hardware should be considered fried.
- */
- tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET,
- HOST_RESET, 10, 1000);
+ tmp = readl(mmio + HOST_CTL);
+ if (!(tmp & HOST_RESET)) {
+ writel(tmp | HOST_RESET, mmio + HOST_CTL);
+ readl(mmio + HOST_CTL); /* flush */
+ }
- if (tmp & HOST_RESET) {
- dev_err(host->dev, "controller reset failed (0x%x)\n",
- tmp);
- return -EIO;
- }
+ /*
+ * To perform host reset, OS should set HOST_RESET and poll until this
+ * bit is read to be "0". Reset must complete within 1 second, or the
+ * hardware should be considered fried.
+ */
+ tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET,
+ HOST_RESET, 10, 1000);
+ if (tmp & HOST_RESET) {
+ dev_err(host->dev, "Controller reset failed (0x%x)\n",
+ tmp);
+ return -EIO;
+ }
- /* turn on AHCI mode */
- ahci_enable_ahci(mmio);
+ /* Turn on AHCI mode */
+ ahci_enable_ahci(mmio);
- /* Some registers might be cleared on reset. Restore
- * initial values.
- */
- if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO))
- ahci_restore_initial_config(host);
- } else
- dev_info(host->dev, "skipping global host reset\n");
+ /* Some registers might be cleared on reset. Restore initial values. */
+ if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO))
+ ahci_restore_initial_config(host);
return 0;
}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b4f246f0cac7..d37ab6087f2f 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -665,12 +665,33 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev)
return block;
}
+/*
+ * Set a taskfile command duration limit index.
+ */
+static inline void ata_set_tf_cdl(struct ata_queued_cmd *qc, int cdl)
+{
+ struct ata_taskfile *tf = &qc->tf;
+
+ if (tf->protocol == ATA_PROT_NCQ)
+ tf->auxiliary |= cdl;
+ else
+ tf->feature |= cdl;
+
+ /*
+ * Mark this command as having a CDL and request the result
+ * task file so that we can inspect the sense data available
+ * bit on completion.
+ */
+ qc->flags |= ATA_QCFLAG_HAS_CDL | ATA_QCFLAG_RESULT_TF;
+}
+
/**
* ata_build_rw_tf - Build ATA taskfile for given read/write request
* @qc: Metadata associated with the taskfile to build
* @block: Block address
* @n_block: Number of blocks
* @tf_flags: RW/FUA etc...
+ * @cdl: Command duration limit index
* @class: IO priority class
*
* LOCKING:
@@ -685,7 +706,7 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev)
* -EINVAL if the request is invalid.
*/
int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block,
- unsigned int tf_flags, int class)
+ unsigned int tf_flags, int cdl, int class)
{
struct ata_taskfile *tf = &qc->tf;
struct ata_device *dev = qc->dev;
@@ -724,11 +745,20 @@ int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block,
if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED &&
class == IOPRIO_CLASS_RT)
tf->hob_nsect |= ATA_PRIO_HIGH << ATA_SHIFT_PRIO;
+
+ if ((dev->flags & ATA_DFLAG_CDL_ENABLED) && cdl)
+ ata_set_tf_cdl(qc, cdl);
+
} else if (dev->flags & ATA_DFLAG_LBA) {
tf->flags |= ATA_TFLAG_LBA;
- /* We need LBA48 for FUA writes */
- if (!(tf->flags & ATA_TFLAG_FUA) && lba_28_ok(block, n_block)) {
+ if ((dev->flags & ATA_DFLAG_CDL_ENABLED) && cdl)
+ ata_set_tf_cdl(qc, cdl);
+
+ /* Both FUA writes and a CDL index require 48-bit commands */
+ if (!(tf->flags & ATA_TFLAG_FUA) &&
+ !(qc->flags & ATA_QCFLAG_HAS_CDL) &&
+ lba_28_ok(block, n_block)) {
/* use LBA28 */
tf->device |= (block >> 24) & 0xf;
} else if (lba_48_ok(block, n_block)) {
@@ -2367,6 +2397,139 @@ static void ata_dev_config_trusted(struct ata_device *dev)
dev->flags |= ATA_DFLAG_TRUSTED;
}
+static void ata_dev_config_cdl(struct ata_device *dev)
+{
+ struct ata_port *ap = dev->link->ap;
+ unsigned int err_mask;
+ bool cdl_enabled;
+ u64 val;
+
+ if (ata_id_major_version(dev->id) < 12)
+ goto not_supported;
+
+ if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE) ||
+ !ata_identify_page_supported(dev, ATA_LOG_SUPPORTED_CAPABILITIES) ||
+ !ata_identify_page_supported(dev, ATA_LOG_CURRENT_SETTINGS))
+ goto not_supported;
+
+ err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE,
+ ATA_LOG_SUPPORTED_CAPABILITIES,
+ ap->sector_buf, 1);
+ if (err_mask)
+ goto not_supported;
+
+ /* Check Command Duration Limit Supported bits */
+ val = get_unaligned_le64(&ap->sector_buf[168]);
+ if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(0)))
+ goto not_supported;
+
+ /* Warn the user if command duration guideline is not supported */
+ if (!(val & BIT_ULL(1)))
+ ata_dev_warn(dev,
+ "Command duration guideline is not supported\n");
+
+ /*
+ * We must have support for the sense data for successful NCQ commands
+ * log indicated by the successful NCQ command sense data supported bit.
+ */
+ val = get_unaligned_le64(&ap->sector_buf[8]);
+ if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(47))) {
+ ata_dev_warn(dev,
+ "CDL supported but Successful NCQ Command Sense Data is not supported\n");
+ goto not_supported;
+ }
+
+ /* Without NCQ autosense, the successful NCQ commands log is useless. */
+ if (!ata_id_has_ncq_autosense(dev->id)) {
+ ata_dev_warn(dev,
+ "CDL supported but NCQ autosense is not supported\n");
+ goto not_supported;
+ }
+
+ /*
+ * If CDL is marked as enabled, make sure the feature is enabled too.
+ * Conversely, if CDL is disabled, make sure the feature is turned off.
+ */
+ err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE,
+ ATA_LOG_CURRENT_SETTINGS,
+ ap->sector_buf, 1);
+ if (err_mask)
+ goto not_supported;
+
+ val = get_unaligned_le64(&ap->sector_buf[8]);
+ cdl_enabled = val & BIT_ULL(63) && val & BIT_ULL(21);
+ if (dev->flags & ATA_DFLAG_CDL_ENABLED) {
+ if (!cdl_enabled) {
+ /* Enable CDL on the device */
+ err_mask = ata_dev_set_feature(dev, SETFEATURES_CDL, 1);
+ if (err_mask) {
+ ata_dev_err(dev,
+ "Enable CDL feature failed\n");
+ goto not_supported;
+ }
+ }
+ } else {
+ if (cdl_enabled) {
+ /* Disable CDL on the device */
+ err_mask = ata_dev_set_feature(dev, SETFEATURES_CDL, 0);
+ if (err_mask) {
+ ata_dev_err(dev,
+ "Disable CDL feature failed\n");
+ goto not_supported;
+ }
+ }
+ }
+
+ /*
+ * While CDL itself has to be enabled using sysfs, CDL requires that
+ * sense data for successful NCQ commands is enabled to work properly.
+ * Just like ata_dev_config_sense_reporting(), enable it unconditionally
+ * if supported.
+ */
+ if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(18))) {
+ err_mask = ata_dev_set_feature(dev,
+ SETFEATURE_SENSE_DATA_SUCC_NCQ, 0x1);
+ if (err_mask) {
+ ata_dev_warn(dev,
+ "failed to enable Sense Data for successful NCQ commands, Emask 0x%x\n",
+ err_mask);
+ goto not_supported;
+ }
+ }
+
+ /*
+ * Allocate a buffer to handle reading the sense data for successful
+ * NCQ Commands log page for commands using a CDL with one of the limit
+ * policy set to 0xD (successful completion with sense data available
+ * bit set).
+ */
+ if (!ap->ncq_sense_buf) {
+ ap->ncq_sense_buf = kmalloc(ATA_LOG_SENSE_NCQ_SIZE, GFP_KERNEL);
+ if (!ap->ncq_sense_buf)
+ goto not_supported;
+ }
+
+ /*
+ * Command duration limits is supported: cache the CDL log page 18h
+ * (command duration descriptors).
+ */
+ err_mask = ata_read_log_page(dev, ATA_LOG_CDL, 0, ap->sector_buf, 1);
+ if (err_mask) {
+ ata_dev_warn(dev, "Read Command Duration Limits log failed\n");
+ goto not_supported;
+ }
+
+ memcpy(dev->cdl, ap->sector_buf, ATA_LOG_CDL_SIZE);
+ dev->flags |= ATA_DFLAG_CDL;
+
+ return;
+
+not_supported:
+ dev->flags &= ~(ATA_DFLAG_CDL | ATA_DFLAG_CDL_ENABLED);
+ kfree(ap->ncq_sense_buf);
+ ap->ncq_sense_buf = NULL;
+}
+
static int ata_dev_config_lba(struct ata_device *dev)
{
const u16 *id = dev->id;
@@ -2534,13 +2697,14 @@ static void ata_dev_print_features(struct ata_device *dev)
return;
ata_dev_info(dev,
- "Features:%s%s%s%s%s%s%s\n",
+ "Features:%s%s%s%s%s%s%s%s\n",
dev->flags & ATA_DFLAG_FUA ? " FUA" : "",
dev->flags & ATA_DFLAG_TRUSTED ? " Trust" : "",
dev->flags & ATA_DFLAG_DA ? " Dev-Attention" : "",
dev->flags & ATA_DFLAG_DEVSLP ? " Dev-Sleep" : "",
dev->flags & ATA_DFLAG_NCQ_SEND_RECV ? " NCQ-sndrcv" : "",
dev->flags & ATA_DFLAG_NCQ_PRIO ? " NCQ-prio" : "",
+ dev->flags & ATA_DFLAG_CDL ? " CDL" : "",
dev->cpr_log ? " CPR" : "");
}
@@ -2702,6 +2866,7 @@ int ata_dev_configure(struct ata_device *dev)
ata_dev_config_zac(dev);
ata_dev_config_trusted(dev);
ata_dev_config_cpr(dev);
+ ata_dev_config_cdl(dev);
dev->cdb_len = 32;
if (print_info)
@@ -3802,11 +3967,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
return -ENODEV;
/* fail early if !ATA && !ATAPI to avoid issuing [P]IDENTIFY to PMP */
- if (ata_class_enabled(new_class) &&
- new_class != ATA_DEV_ATA &&
- new_class != ATA_DEV_ATAPI &&
- new_class != ATA_DEV_ZAC &&
- new_class != ATA_DEV_SEMB) {
+ if (ata_class_enabled(new_class) && new_class == ATA_DEV_PMP) {
ata_dev_info(dev, "class mismatch %u != %u\n",
dev->class, new_class);
rc = -ENODEV;
@@ -4766,6 +4927,36 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
fill_result_tf(qc);
trace_ata_qc_complete_done(qc);
+
+ /*
+ * For CDL commands that completed without an error, check if
+ * we have sense data (ATA_SENSE is set). If we do, then the
+ * command may have 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))))) {
+ /*
+ * Tell SCSI EH to not overwrite scmd->result even if
+ * this command is finished with result SAM_STAT_GOOD.
+ */
+ qc->scsicmd->flags |= SCMD_FORCE_EH_SUCCESS;
+ qc->flags |= ATA_QCFLAG_EH_SUCCESS_CMD;
+ ehi->dev_action[dev->devno] |= ATA_EH_GET_SUCCESS_SENSE;
+
+ /*
+ * set pending so that ata_qc_schedule_eh() does not
+ * trigger fast drain, and freeze the port.
+ */
+ ap->pflags |= ATA_PFLAG_EH_PENDING;
+ ata_qc_schedule_eh(qc);
+ return;
+ }
+
/* Some commands need post-processing after successful
* completion.
*/
@@ -5398,6 +5589,7 @@ static void ata_host_release(struct kref *kref)
kfree(ap->pmp_link);
kfree(ap->slave_link);
+ kfree(ap->ncq_sense_buf);
kfree(ap);
host->ports[i] = NULL;
}
@@ -6142,13 +6334,11 @@ EXPORT_SYMBOL_GPL(ata_pci_device_resume);
* LOCKING:
* Inherited from platform layer (may sleep).
*/
-int ata_platform_remove_one(struct platform_device *pdev)
+void ata_platform_remove_one(struct platform_device *pdev)
{
struct ata_host *host = platform_get_drvdata(pdev);
ata_host_detach(host);
-
- return 0;
}
EXPORT_SYMBOL_GPL(ata_platform_remove_one);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 6f8d14191593..35e03679b0bf 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1401,8 +1401,11 @@ unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key)
*
* LOCKING:
* Kernel thread context (may sleep).
+ *
+ * RETURNS:
+ * true if sense data could be fetched, false otherwise.
*/
-static void ata_eh_request_sense(struct ata_queued_cmd *qc)
+static bool ata_eh_request_sense(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *cmd = qc->scsicmd;
struct ata_device *dev = qc->dev;
@@ -1411,15 +1414,12 @@ static void ata_eh_request_sense(struct ata_queued_cmd *qc)
if (ata_port_is_frozen(qc->ap)) {
ata_dev_warn(dev, "sense data available but port frozen\n");
- return;
+ return false;
}
- if (!cmd || qc->flags & ATA_QCFLAG_SENSE_VALID)
- return;
-
if (!ata_id_sense_reporting_enabled(dev->id)) {
ata_dev_warn(qc->dev, "sense data reporting disabled\n");
- return;
+ return false;
}
ata_tf_init(dev, &tf);
@@ -1432,13 +1432,19 @@ static void ata_eh_request_sense(struct ata_queued_cmd *qc)
/* Ignore err_mask; ATA_ERR might be set */
if (tf.status & ATA_SENSE) {
if (ata_scsi_sense_is_valid(tf.lbah, tf.lbam, tf.lbal)) {
- ata_scsi_set_sense(dev, cmd, tf.lbah, tf.lbam, tf.lbal);
+ /* Set sense without also setting scsicmd->result */
+ scsi_build_sense_buffer(dev->flags & ATA_DFLAG_D_SENSE,
+ cmd->sense_buffer, tf.lbah,
+ tf.lbam, tf.lbal);
qc->flags |= ATA_QCFLAG_SENSE_VALID;
+ return true;
}
} else {
ata_dev_warn(dev, "request sense failed stat %02x emask %x\n",
tf.status, err_mask);
}
+
+ return false;
}
/**
@@ -1588,8 +1594,9 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc)
* was not included in the NCQ command error log
* (i.e. NCQ autosense is not supported by the device).
*/
- if (!(qc->flags & ATA_QCFLAG_SENSE_VALID) && (stat & ATA_SENSE))
- ata_eh_request_sense(qc);
+ if (!(qc->flags & ATA_QCFLAG_SENSE_VALID) &&
+ (stat & ATA_SENSE) && ata_eh_request_sense(qc))
+ set_status_byte(qc->scsicmd, SAM_STAT_CHECK_CONDITION);
if (err & ATA_ICRC)
qc->err_mask |= AC_ERR_ATA_BUS;
if (err & (ATA_UNC | ATA_AMNF))
@@ -1817,9 +1824,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
verdict = ata_eh_speed_down_verdict(dev);
/* turn off NCQ? */
- if ((verdict & ATA_EH_SPDN_NCQ_OFF) &&
- (dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ |
- ATA_DFLAG_NCQ_OFF)) == ATA_DFLAG_NCQ) {
+ if ((verdict & ATA_EH_SPDN_NCQ_OFF) && ata_ncq_enabled(dev)) {
dev->flags |= ATA_DFLAG_NCQ_OFF;
ata_dev_warn(dev, "NCQ disabled due to excessive errors\n");
goto done;
@@ -1910,6 +1915,99 @@ static inline bool ata_eh_quiet(struct ata_queued_cmd *qc)
return qc->flags & ATA_QCFLAG_QUIET;
}
+static int ata_eh_read_sense_success_non_ncq(struct ata_link *link)
+{
+ struct ata_port *ap = link->ap;
+ struct ata_queued_cmd *qc;
+
+ qc = __ata_qc_from_tag(ap, link->active_tag);
+ if (!qc)
+ return -EIO;
+
+ if (!(qc->flags & ATA_QCFLAG_EH) ||
+ !(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) ||
+ qc->err_mask)
+ return -EIO;
+
+ if (!ata_eh_request_sense(qc))
+ return -EIO;
+
+ /*
+ * If we have sense data, call scsi_check_sense() in order to set the
+ * correct SCSI ML byte (if any). No point in checking the return value,
+ * since the command has already completed successfully.
+ */
+ scsi_check_sense(qc->scsicmd);
+
+ return 0;
+}
+
+static void ata_eh_get_success_sense(struct ata_link *link)
+{
+ struct ata_eh_context *ehc = &link->eh_context;
+ struct ata_device *dev = link->device;
+ struct ata_port *ap = link->ap;
+ struct ata_queued_cmd *qc;
+ int tag, ret = 0;
+
+ if (!(ehc->i.dev_action[dev->devno] & ATA_EH_GET_SUCCESS_SENSE))
+ return;
+
+ /* if frozen, we can't do much */
+ if (ata_port_is_frozen(ap)) {
+ ata_dev_warn(dev,
+ "successful sense data available but port frozen\n");
+ goto out;
+ }
+
+ /*
+ * If the link has sactive set, then we have outstanding NCQ commands
+ * and have to read the Successful NCQ Commands log to get the sense
+ * data. Otherwise, we are dealing with a non-NCQ command and use
+ * request sense ext command to retrieve the sense data.
+ */
+ if (link->sactive)
+ ret = ata_eh_read_sense_success_ncq_log(link);
+ else
+ ret = ata_eh_read_sense_success_non_ncq(link);
+ if (ret)
+ goto out;
+
+ ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE);
+ return;
+
+out:
+ /*
+ * If we failed to get sense data for a successful command that ought to
+ * have sense data, we cannot simply return BLK_STS_OK to user space.
+ * This is because we can't know if the sense data that we couldn't get
+ * was actually "DATA CURRENTLY UNAVAILABLE". Reporting such a command
+ * as success to user space would result in a silent data corruption.
+ * Thus, add a bogus ABORTED_COMMAND sense data to such commands, such
+ * that SCSI will report these commands as BLK_STS_IOERR to user space.
+ */
+ ata_qc_for_each_raw(ap, qc, tag) {
+ if (!(qc->flags & ATA_QCFLAG_EH) ||
+ !(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) ||
+ qc->err_mask ||
+ ata_dev_phys_link(qc->dev) != link)
+ continue;
+
+ /* We managed to get sense for this success command, skip. */
+ if (qc->flags & ATA_QCFLAG_SENSE_VALID)
+ continue;
+
+ /* This success command did not have any sense data, skip. */
+ if (!(qc->result_tf.status & ATA_SENSE))
+ continue;
+
+ /* This success command had sense data, but we failed to get. */
+ ata_scsi_set_sense(dev, qc->scsicmd, ABORTED_COMMAND, 0, 0);
+ qc->flags |= ATA_QCFLAG_SENSE_VALID;
+ }
+ ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE);
+}
+
/**
* ata_eh_link_autopsy - analyze error and determine recovery action
* @link: host link to perform autopsy on
@@ -1950,6 +2048,14 @@ static void ata_eh_link_autopsy(struct ata_link *link)
/* analyze NCQ failure */
ata_eh_analyze_ncq_error(link);
+ /*
+ * Check if this was a successful command that simply needs sense data.
+ * Since the sense data is not part of the completion, we need to fetch
+ * it using an additional command. Since this can't be done from irq
+ * context, the sense data for successful commands are fetched by EH.
+ */
+ ata_eh_get_success_sense(link);
+
/* any real error trumps AC_ERR_OTHER */
if (ehc->i.err_mask & ~AC_ERR_OTHER)
ehc->i.err_mask &= ~AC_ERR_OTHER;
@@ -1959,6 +2065,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
ata_qc_for_each_raw(ap, qc, tag) {
if (!(qc->flags & ATA_QCFLAG_EH) ||
qc->flags & ATA_QCFLAG_RETRY ||
+ qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD ||
ata_dev_phys_link(qc->dev) != link)
continue;
@@ -3813,16 +3920,30 @@ void ata_eh_finish(struct ata_port *ap)
* generate sense data in this function,
* considering both err_mask and tf.
*/
- if (qc->flags & ATA_QCFLAG_RETRY)
+ if (qc->flags & ATA_QCFLAG_RETRY) {
+ /*
+ * Since qc->err_mask is set, ata_eh_qc_retry()
+ * will not increment scmd->allowed, so upper
+ * layer will only retry the command if it has
+ * not already been retried too many times.
+ */
ata_eh_qc_retry(qc);
- else
+ } else {
ata_eh_qc_complete(qc);
+ }
} else {
- if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+ if (qc->flags & ATA_QCFLAG_SENSE_VALID ||
+ qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) {
ata_eh_qc_complete(qc);
} else {
/* feed zero TF to sense generation */
memset(&qc->result_tf, 0, sizeof(qc->result_tf));
+ /*
+ * Since qc->err_mask is not set,
+ * ata_eh_qc_retry() will increment
+ * scmd->allowed, so upper layer is guaranteed
+ * to retry the command.
+ */
ata_eh_qc_retry(qc);
}
}
diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c
index f3e7396e3191..85e279a12f62 100644
--- a/drivers/ata/libata-sata.c
+++ b/drivers/ata/libata-sata.c
@@ -11,7 +11,9 @@
#include <linux/module.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
#include <linux/libata.h>
+#include <asm/unaligned.h>
#include "libata.h"
#include "libata-transport.h"
@@ -907,10 +909,17 @@ static ssize_t ata_ncq_prio_enable_store(struct device *device,
goto unlock;
}
- if (input)
+ if (input) {
+ if (dev->flags & ATA_DFLAG_CDL_ENABLED) {
+ ata_dev_err(dev,
+ "CDL must be disabled to enable NCQ priority\n");
+ rc = -EINVAL;
+ goto unlock;
+ }
dev->flags |= ATA_DFLAG_NCQ_PRIO_ENABLED;
- else
+ } else {
dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLED;
+ }
unlock:
spin_unlock_irq(ap->lock);
@@ -1023,7 +1032,6 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
/**
* ata_change_queue_depth - Set a device maximum queue depth
* @ap: ATA port of the target device
- * @dev: target ATA device
* @sdev: SCSI device to configure queue depth for
* @queue_depth: new queue depth
*
@@ -1031,33 +1039,47 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
* and libata.
*
*/
-int ata_change_queue_depth(struct ata_port *ap, struct ata_device *dev,
- struct scsi_device *sdev, int queue_depth)
+int ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
+ int queue_depth)
{
+ struct ata_device *dev;
unsigned long flags;
+ int max_queue_depth;
- if (!dev || !ata_dev_enabled(dev))
- return sdev->queue_depth;
+ spin_lock_irqsave(ap->lock, flags);
- if (queue_depth < 1 || queue_depth == sdev->queue_depth)
+ dev = ata_scsi_find_dev(ap, sdev);
+ if (!dev || queue_depth < 1 || queue_depth == sdev->queue_depth) {
+ spin_unlock_irqrestore(ap->lock, flags);
return sdev->queue_depth;
+ }
- /* NCQ enabled? */
- spin_lock_irqsave(ap->lock, flags);
- dev->flags &= ~ATA_DFLAG_NCQ_OFF;
- if (queue_depth == 1 || !ata_ncq_enabled(dev)) {
+ /*
+ * Make sure that the queue depth requested does not exceed the device
+ * capabilities.
+ */
+ max_queue_depth = min(ATA_MAX_QUEUE, sdev->host->can_queue);
+ max_queue_depth = min(max_queue_depth, ata_id_queue_depth(dev->id));
+ if (queue_depth > max_queue_depth) {
+ spin_unlock_irqrestore(ap->lock, flags);
+ return -EINVAL;
+ }
+
+ /*
+ * If NCQ is not supported by the device or if the target queue depth
+ * is 1 (to disable drive side command queueing), turn off NCQ.
+ */
+ if (queue_depth == 1 || !ata_ncq_supported(dev)) {
dev->flags |= ATA_DFLAG_NCQ_OFF;
queue_depth = 1;
+ } else {
+ dev->flags &= ~ATA_DFLAG_NCQ_OFF;
}
- spin_unlock_irqrestore(ap->lock, flags);
- /* limit and apply queue depth */
- queue_depth = min(queue_depth, sdev->host->can_queue);
- queue_depth = min(queue_depth, ata_id_queue_depth(dev->id));
- queue_depth = min(queue_depth, ATA_MAX_QUEUE);
+ spin_unlock_irqrestore(ap->lock, flags);
- if (sdev->queue_depth == queue_depth)
- return -EINVAL;
+ if (queue_depth == sdev->queue_depth)
+ return sdev->queue_depth;
return scsi_change_queue_depth(sdev, queue_depth);
}
@@ -1082,8 +1104,7 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
{
struct ata_port *ap = ata_shost_to_port(sdev->host);
- return ata_change_queue_depth(ap, ata_scsi_find_dev(ap, sdev),
- sdev, queue_depth);
+ return ata_change_queue_depth(ap, sdev, queue_depth);
}
EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
@@ -1402,6 +1423,95 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
}
/**
+ * ata_eh_read_sense_success_ncq_log - Read the sense data for successful
+ * NCQ commands log
+ * @link: ATA link to get sense data for
+ *
+ * Read the sense data for successful NCQ commands log page to obtain
+ * sense data for all NCQ commands that completed successfully with
+ * the sense data available bit set.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+int ata_eh_read_sense_success_ncq_log(struct ata_link *link)
+{
+ struct ata_device *dev = link->device;
+ struct ata_port *ap = dev->link->ap;
+ u8 *buf = ap->ncq_sense_buf;
+ struct ata_queued_cmd *qc;
+ unsigned int err_mask, tag;
+ u8 *sense, sk = 0, asc = 0, ascq = 0;
+ u64 sense_valid, val;
+ int ret = 0;
+
+ err_mask = ata_read_log_page(dev, ATA_LOG_SENSE_NCQ, 0, buf, 2);
+ if (err_mask) {
+ ata_dev_err(dev,
+ "Failed to read Sense Data for Successful NCQ Commands log\n");
+ return -EIO;
+ }
+
+ /* Check the log header */
+ val = get_unaligned_le64(&buf[0]);
+ if ((val & 0xffff) != 1 || ((val >> 16) & 0xff) != 0x0f) {
+ ata_dev_err(dev,
+ "Invalid Sense Data for Successful NCQ Commands log\n");
+ return -EIO;
+ }
+
+ sense_valid = (u64)buf[8] | ((u64)buf[9] << 8) |
+ ((u64)buf[10] << 16) | ((u64)buf[11] << 24);
+
+ ata_qc_for_each_raw(ap, qc, tag) {
+ if (!(qc->flags & ATA_QCFLAG_EH) ||
+ !(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) ||
+ qc->err_mask ||
+ ata_dev_phys_link(qc->dev) != link)
+ continue;
+
+ /*
+ * If the command does not have any sense data, clear ATA_SENSE.
+ * Keep ATA_QCFLAG_EH_SUCCESS_CMD so that command is finished.
+ */
+ if (!(sense_valid & (1ULL << tag))) {
+ qc->result_tf.status &= ~ATA_SENSE;
+ continue;
+ }
+
+ sense = &buf[32 + 24 * tag];
+ sk = sense[0];
+ asc = sense[1];
+ ascq = sense[2];
+
+ if (!ata_scsi_sense_is_valid(sk, asc, ascq)) {
+ ret = -EIO;
+ continue;
+ }
+
+ /* Set sense without also setting scsicmd->result */
+ scsi_build_sense_buffer(dev->flags & ATA_DFLAG_D_SENSE,
+ qc->scsicmd->sense_buffer, sk,
+ asc, ascq);
+ qc->flags |= ATA_QCFLAG_SENSE_VALID;
+
+ /*
+ * If we have sense data, call scsi_check_sense() in order to
+ * set the correct SCSI ML byte (if any). No point in checking
+ * the return value, since the command has already completed
+ * successfully.
+ */
+ scsi_check_sense(qc->scsicmd);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ata_eh_read_sense_success_ncq_log);
+
+/**
* ata_eh_analyze_ncq_error - analyze NCQ error
* @link: ATA link to analyze NCQ error for
*
@@ -1481,6 +1591,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link)
ata_qc_for_each_raw(ap, qc, tag) {
if (!(qc->flags & ATA_QCFLAG_EH) ||
+ qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD ||
ata_dev_phys_link(qc->dev) != link)
continue;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 551077cea4e4..370d18aca71e 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -37,7 +37,7 @@
#include "libata.h"
#include "libata-transport.h"
-#define ATA_SCSI_RBUF_SIZE 576
+#define ATA_SCSI_RBUF_SIZE 2048
static DEFINE_SPINLOCK(ata_scsi_rbuf_lock);
static u8 ata_scsi_rbuf[ATA_SCSI_RBUF_SIZE];
@@ -47,15 +47,19 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);
static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev);
-#define RW_RECOVERY_MPAGE 0x1
-#define RW_RECOVERY_MPAGE_LEN 12
-#define CACHE_MPAGE 0x8
-#define CACHE_MPAGE_LEN 20
-#define CONTROL_MPAGE 0xa
-#define CONTROL_MPAGE_LEN 12
-#define ALL_MPAGES 0x3f
-#define ALL_SUB_MPAGES 0xff
-
+#define RW_RECOVERY_MPAGE 0x1
+#define RW_RECOVERY_MPAGE_LEN 12
+#define CACHE_MPAGE 0x8
+#define CACHE_MPAGE_LEN 20
+#define CONTROL_MPAGE 0xa
+#define CONTROL_MPAGE_LEN 12
+#define ALL_MPAGES 0x3f
+#define ALL_SUB_MPAGES 0xff
+#define CDL_T2A_SUB_MPAGE 0x07
+#define CDL_T2B_SUB_MPAGE 0x08
+#define CDL_T2_SUB_MPAGE_LEN 232
+#define ATA_FEATURE_SUB_MPAGE 0xf2
+#define ATA_FEATURE_SUB_MPAGE_LEN 16
static const u8 def_rw_recovery_mpage[RW_RECOVERY_MPAGE_LEN] = {
RW_RECOVERY_MPAGE,
@@ -209,9 +213,6 @@ void ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd,
{
bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE);
- if (!cmd)
- return;
-
scsi_build_sense(cmd, d_sense, sk, asc, ascq);
}
@@ -221,9 +222,6 @@ void ata_scsi_set_sense_information(struct ata_device *dev,
{
u64 information;
- if (!cmd)
- return;
-
information = ata_tf_read_block(tf, dev);
if (information == U64_MAX)
return;
@@ -1122,7 +1120,7 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev)
if (dev->flags & ATA_DFLAG_AN)
set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events);
- if (dev->flags & ATA_DFLAG_NCQ)
+ if (ata_ncq_supported(dev))
depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
depth = min(ATA_MAX_QUEUE, depth);
scsi_change_queue_depth(sdev, depth);
@@ -1383,6 +1381,18 @@ static inline void scsi_16_lba_len(const u8 *cdb, u64 *plba, u32 *plen)
}
/**
+ * scsi_dld - Get duration limit descriptor index
+ * @cdb: SCSI command to translate
+ *
+ * Returns the dld bits indicating the index of a command duration limit
+ * descriptor.
+ */
+static inline int scsi_dld(const u8 *cdb)
+{
+ return ((cdb[1] & 0x01) << 2) | ((cdb[14] >> 6) & 0x03);
+}
+
+/**
* ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
* @qc: Storage for translated ATA taskfile
*
@@ -1550,6 +1560,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
struct request *rq = scsi_cmd_to_rq(scmd);
int class = IOPRIO_PRIO_CLASS(req_get_ioprio(rq));
unsigned int tf_flags = 0;
+ int dld = 0;
u64 block;
u32 n_block;
int rc;
@@ -1600,6 +1611,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
goto invalid_fld;
}
scsi_16_lba_len(cdb, &block, &n_block);
+ dld = scsi_dld(cdb);
if (cdb[1] & (1 << 3))
tf_flags |= ATA_TFLAG_FUA;
if (!ata_check_nblocks(scmd, n_block))
@@ -1624,7 +1636,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
qc->flags |= ATA_QCFLAG_IO;
qc->nbytes = n_block * scmd->device->sector_size;
- rc = ata_build_rw_tf(qc, block, n_block, tf_flags, class);
+ rc = ata_build_rw_tf(qc, block, n_block, tf_flags, dld, class);
if (likely(rc == 0))
return 0;
@@ -2203,10 +2215,123 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable)
return sizeof(def_cache_mpage);
}
+/*
+ * Simulate MODE SENSE control mode page, sub-page 0.
+ */
+static unsigned int ata_msense_control_spg0(struct ata_device *dev, u8 *buf,
+ bool changeable)
+{
+ modecpy(buf, def_control_mpage,
+ sizeof(def_control_mpage), changeable);
+ if (changeable) {
+ /* ata_mselect_control() */
+ buf[2] |= (1 << 2);
+ } else {
+ bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE);
+
+ /* descriptor format sense data */
+ buf[2] |= (d_sense << 2);
+ }
+
+ return sizeof(def_control_mpage);
+}
+
+/*
+ * Translate an ATA duration limit in microseconds to a SCSI duration limit
+ * using the t2cdlunits 0xa (10ms). Since the SCSI duration limits are 2-bytes
+ * only, take care of overflows.
+ */
+static inline u16 ata_xlat_cdl_limit(u8 *buf)
+{
+ u32 limit = get_unaligned_le32(buf);
+
+ return min_t(u32, limit / 10000, 65535);
+}
+
+/*
+ * Simulate MODE SENSE control mode page, sub-pages 07h and 08h
+ * (command duration limits T2A and T2B mode pages).
+ */
+static unsigned int ata_msense_control_spgt2(struct ata_device *dev, u8 *buf,
+ u8 spg)
+{
+ u8 *b, *cdl = dev->cdl, *desc;
+ u32 policy;
+ int i;
+
+ /*
+ * Fill the subpage. The first four bytes of the T2A/T2B mode pages
+ * are a header. The PAGE LENGTH field is the size of the page
+ * excluding the header.
+ */
+ buf[0] = CONTROL_MPAGE;
+ buf[1] = spg;
+ put_unaligned_be16(CDL_T2_SUB_MPAGE_LEN - 4, &buf[2]);
+ if (spg == CDL_T2A_SUB_MPAGE) {
+ /*
+ * Read descriptors map to the T2A page:
+ * set perf_vs_duration_guidleine.
+ */
+ buf[7] = (cdl[0] & 0x03) << 4;
+ desc = cdl + 64;
+ } else {
+ /* Write descriptors map to the T2B page */
+ desc = cdl + 288;
+ }
+
+ /* Fill the T2 page descriptors */
+ b = &buf[8];
+ policy = get_unaligned_le32(&cdl[0]);
+ for (i = 0; i < 7; i++, b += 32, desc += 32) {
+ /* t2cdlunits: fixed to 10ms */
+ b[0] = 0x0a;
+
+ /* Max inactive time and its policy */
+ put_unaligned_be16(ata_xlat_cdl_limit(&desc[8]), &b[2]);
+ b[6] = ((policy >> 8) & 0x0f) << 4;
+
+ /* Max active time and its policy */
+ put_unaligned_be16(ata_xlat_cdl_limit(&desc[4]), &b[4]);
+ b[6] |= (policy >> 4) & 0x0f;
+
+ /* Command duration guideline and its policy */
+ put_unaligned_be16(ata_xlat_cdl_limit(&desc[16]), &b[10]);
+ b[14] = policy & 0x0f;
+ }
+
+ return CDL_T2_SUB_MPAGE_LEN;
+}
+
+/*
+ * Simulate MODE SENSE control mode page, sub-page f2h
+ * (ATA feature control mode page).
+ */
+static unsigned int ata_msense_control_ata_feature(struct ata_device *dev,
+ u8 *buf)
+{
+ /* PS=0, SPF=1 */
+ buf[0] = CONTROL_MPAGE | (1 << 6);
+ buf[1] = ATA_FEATURE_SUB_MPAGE;
+
+ /*
+ * The first four bytes of ATA Feature Control mode page are a header.
+ * The PAGE LENGTH field is the size of the page excluding the header.
+ */
+ put_unaligned_be16(ATA_FEATURE_SUB_MPAGE_LEN - 4, &buf[2]);
+
+ if (dev->flags & ATA_DFLAG_CDL)
+ buf[4] = 0x02; /* Support T2A and T2B pages */
+ else
+ buf[4] = 0;
+
+ return ATA_FEATURE_SUB_MPAGE_LEN;
+}
+
/**
* ata_msense_control - Simulate MODE SENSE control mode page
* @dev: ATA device of interest
* @buf: output buffer
+ * @spg: sub-page code
* @changeable: whether changeable parameters are requested
*
* Generate a generic MODE SENSE control mode page.
@@ -2215,17 +2340,27 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable)
* None.
*/
static unsigned int ata_msense_control(struct ata_device *dev, u8 *buf,
- bool changeable)
+ u8 spg, bool changeable)
{
- modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable);
- if (changeable) {
- buf[2] |= (1 << 2); /* ata_mselect_control() */
- } else {
- bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE);
-
- buf[2] |= (d_sense << 2); /* descriptor format sense data */
+ unsigned int n;
+
+ switch (spg) {
+ case 0:
+ return ata_msense_control_spg0(dev, buf, changeable);
+ case CDL_T2A_SUB_MPAGE:
+ case CDL_T2B_SUB_MPAGE:
+ return ata_msense_control_spgt2(dev, buf, spg);
+ case ATA_FEATURE_SUB_MPAGE:
+ return ata_msense_control_ata_feature(dev, buf);
+ case ALL_SUB_MPAGES:
+ n = ata_msense_control_spg0(dev, buf, changeable);
+ n += ata_msense_control_spgt2(dev, buf + n, CDL_T2A_SUB_MPAGE);
+ n += ata_msense_control_spgt2(dev, buf + n, CDL_T2A_SUB_MPAGE);
+ n += ata_msense_control_ata_feature(dev, buf + n);
+ return n;
+ default:
+ return 0;
}
- return sizeof(def_control_mpage);
}
/**
@@ -2298,13 +2433,25 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
pg = scsicmd[2] & 0x3f;
spg = scsicmd[3];
+
/*
- * No mode subpages supported (yet) but asking for _all_
- * subpages may be valid
+ * Supported subpages: all subpages and sub-pages 07h, 08h and f2h of
+ * the control page.
*/
- if (spg && (spg != ALL_SUB_MPAGES)) {
- fp = 3;
- goto invalid_fld;
+ if (spg) {
+ switch (spg) {
+ case ALL_SUB_MPAGES:
+ break;
+ case CDL_T2A_SUB_MPAGE:
+ case CDL_T2B_SUB_MPAGE:
+ case ATA_FEATURE_SUB_MPAGE:
+ if (dev->flags & ATA_DFLAG_CDL && pg == CONTROL_MPAGE)
+ break;
+ fallthrough;
+ default:
+ fp = 3;
+ goto invalid_fld;
+ }
}
switch(pg) {
@@ -2317,13 +2464,13 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
break;
case CONTROL_MPAGE:
- p += ata_msense_control(args->dev, p, page_control == 1);
+ p += ata_msense_control(args->dev, p, spg, page_control == 1);
break;
case ALL_MPAGES:
p += ata_msense_rw_recovery(p, page_control == 1);
p += ata_msense_caching(args->id, p, page_control == 1);
- p += ata_msense_control(args->dev, p, page_control == 1);
+ p += ata_msense_control(args->dev, p, spg, page_control == 1);
break;
default: /* invalid page code */
@@ -2342,10 +2489,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc));
}
} else {
- unsigned int output_len = p - rbuf - 2;
-
- rbuf[0] = output_len >> 8;
- rbuf[1] = output_len;
+ put_unaligned_be16(p - rbuf - 2, &rbuf[0]);
rbuf[3] |= dpofua;
if (ebd) {
rbuf[7] = sizeof(sat_blk_desc);
@@ -3260,7 +3404,7 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf)
{
struct ata_device *dev = args->dev;
u8 *cdb = args->cmd->cmnd;
- u8 supported = 0;
+ u8 supported = 0, cdlp = 0, rwcdlp = 0;
unsigned int err = 0;
if (cdb[2] != 1 && cdb[2] != 3) {
@@ -3287,10 +3431,8 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf)
case MAINTENANCE_IN:
case READ_6:
case READ_10:
- case READ_16:
case WRITE_6:
case WRITE_10:
- case WRITE_16:
case ATA_12:
case ATA_16:
case VERIFY:
@@ -3300,6 +3442,28 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf)
case START_STOP:
supported = 3;
break;
+ case READ_16:
+ supported = 3;
+ if (dev->flags & ATA_DFLAG_CDL) {
+ /*
+ * CDL read descriptors map to the T2A page, that is,
+ * rwcdlp = 0x01 and cdlp = 0x01
+ */
+ rwcdlp = 0x01;
+ cdlp = 0x01 << 3;
+ }
+ break;
+ case WRITE_16:
+ supported = 3;
+ if (dev->flags & ATA_DFLAG_CDL) {
+ /*
+ * CDL write descriptors map to the T2B page, that is,
+ * rwcdlp = 0x01 and cdlp = 0x02
+ */
+ rwcdlp = 0x01;
+ cdlp = 0x02 << 3;
+ }
+ break;
case ZBC_IN:
case ZBC_OUT:
if (ata_id_zoned_cap(dev->id) ||
@@ -3315,7 +3479,9 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf)
break;
}
out:
- rbuf[1] = supported; /* supported */
+ /* One command format */
+ rbuf[0] = rwcdlp;
+ rbuf[1] = cdlp | supported;
return err;
}
@@ -3605,20 +3771,11 @@ static int ata_mselect_caching(struct ata_queued_cmd *qc,
return 0;
}
-/**
- * ata_mselect_control - Simulate MODE SELECT for control page
- * @qc: Storage for translated ATA taskfile
- * @buf: input buffer
- * @len: number of valid bytes in the input buffer
- * @fp: out parameter for the failed field on error
- *
- * Prepare a taskfile to modify caching information for the device.
- *
- * LOCKING:
- * None.
+/*
+ * Simulate MODE SELECT control mode page, sub-page 0.
*/
-static int ata_mselect_control(struct ata_queued_cmd *qc,
- const u8 *buf, int len, u16 *fp)
+static int ata_mselect_control_spg0(struct ata_queued_cmd *qc,
+ const u8 *buf, int len, u16 *fp)
{
struct ata_device *dev = qc->dev;
u8 mpage[CONTROL_MPAGE_LEN];
@@ -3640,7 +3797,7 @@ static int ata_mselect_control(struct ata_queued_cmd *qc,
/*
* Check that read-only bits are not modified.
*/
- ata_msense_control(dev, mpage, false);
+ ata_msense_control_spg0(dev, mpage, false);
for (i = 0; i < CONTROL_MPAGE_LEN - 2; i++) {
if (i == 0)
continue;
@@ -3656,6 +3813,84 @@ static int ata_mselect_control(struct ata_queued_cmd *qc,
return 0;
}
+/*
+ * Translate MODE SELECT control mode page, sub-pages f2h (ATA feature mode
+ * page) into a SET FEATURES command.
+ */
+static unsigned int ata_mselect_control_ata_feature(struct ata_queued_cmd *qc,
+ const u8 *buf, int len,
+ u16 *fp)
+{
+ struct ata_device *dev = qc->dev;
+ struct ata_taskfile *tf = &qc->tf;
+ u8 cdl_action;
+
+ /*
+ * The first four bytes of ATA Feature Control mode page are a header,
+ * so offsets in mpage are off by 4 compared to buf. Same for len.
+ */
+ if (len != ATA_FEATURE_SUB_MPAGE_LEN - 4) {
+ *fp = min(len, ATA_FEATURE_SUB_MPAGE_LEN - 4);
+ return -EINVAL;
+ }
+
+ /* Check cdl_ctrl */
+ switch (buf[0] & 0x03) {
+ case 0:
+ /* Disable CDL */
+ cdl_action = 0;
+ dev->flags &= ~ATA_DFLAG_CDL_ENABLED;
+ break;
+ case 0x02:
+ /* Enable CDL T2A/T2B: NCQ priority must be disabled */
+ if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED) {
+ ata_dev_err(dev,
+ "NCQ priority must be disabled to enable CDL\n");
+ return -EINVAL;
+ }
+ cdl_action = 1;
+ dev->flags |= ATA_DFLAG_CDL_ENABLED;
+ break;
+ default:
+ *fp = 0;
+ return -EINVAL;
+ }
+
+ tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
+ tf->protocol = ATA_PROT_NODATA;
+ tf->command = ATA_CMD_SET_FEATURES;
+ tf->feature = SETFEATURES_CDL;
+ tf->nsect = cdl_action;
+
+ return 1;
+}
+
+/**
+ * ata_mselect_control - Simulate MODE SELECT for control page
+ * @qc: Storage for translated ATA taskfile
+ * @spg: target sub-page of the control page
+ * @buf: input buffer
+ * @len: number of valid bytes in the input buffer
+ * @fp: out parameter for the failed field on error
+ *
+ * Prepare a taskfile to modify caching information for the device.
+ *
+ * LOCKING:
+ * None.
+ */
+static int ata_mselect_control(struct ata_queued_cmd *qc, u8 spg,
+ const u8 *buf, int len, u16 *fp)
+{
+ switch (spg) {
+ case 0:
+ return ata_mselect_control_spg0(qc, buf, len, fp);
+ case ATA_FEATURE_SUB_MPAGE:
+ return ata_mselect_control_ata_feature(qc, buf, len, fp);
+ default:
+ return -EINVAL;
+ }
+}
+
/**
* ata_scsi_mode_select_xlat - Simulate MODE SELECT 6, 10 commands
* @qc: Storage for translated ATA taskfile
@@ -3673,7 +3908,7 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc)
const u8 *cdb = scmd->cmnd;
u8 pg, spg;
unsigned six_byte, pg_len, hdr_len, bd_len;
- int len;
+ int len, ret;
u16 fp = (u16)-1;
u8 bp = 0xff;
u8 buffer[64];
@@ -3758,13 +3993,29 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc)
}
/*
- * No mode subpages supported (yet) but asking for _all_
- * subpages may be valid
+ * Supported subpages: all subpages and ATA feature sub-page f2h of
+ * the control page.
*/
- if (spg && (spg != ALL_SUB_MPAGES)) {
- fp = (p[0] & 0x40) ? 1 : 0;
- fp += hdr_len + bd_len;
- goto invalid_param;
+ if (spg) {
+ switch (spg) {
+ case ALL_SUB_MPAGES:
+ /* All subpages is not supported for the control page */
+ if (pg == CONTROL_MPAGE) {
+ fp = (p[0] & 0x40) ? 1 : 0;
+ fp += hdr_len + bd_len;
+ goto invalid_param;
+ }
+ break;
+ case ATA_FEATURE_SUB_MPAGE:
+ if (qc->dev->flags & ATA_DFLAG_CDL &&
+ pg == CONTROL_MPAGE)
+ break;
+ fallthrough;
+ default:
+ fp = (p[0] & 0x40) ? 1 : 0;
+ fp += hdr_len + bd_len;
+ goto invalid_param;
+ }
}
if (pg_len > len)
goto invalid_param_len;
@@ -3777,14 +4028,16 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc)
}
break;
case CONTROL_MPAGE:
- if (ata_mselect_control(qc, p, pg_len, &fp) < 0) {
+ ret = ata_mselect_control(qc, spg, p, pg_len, &fp);
+ if (ret < 0) {
fp += hdr_len + bd_len;
goto invalid_param;
- } else {
- goto skip; /* No ATA command to send */
}
+ if (!ret)
+ goto skip; /* No ATA command to send */
break;
- default: /* invalid page code */
+ default:
+ /* Invalid page code */
fp = bd_len + hdr_len;
goto invalid_param;
}
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 926d0d33cd29..cf993885d2b2 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -45,7 +45,7 @@ static inline void ata_force_cbl(struct ata_port *ap) { }
extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);
extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf);
extern int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block,
- unsigned int tf_flags, int class);
+ unsigned int tf_flags, int dld, int class);
extern u64 ata_tf_read_block(const struct ata_taskfile *tf,
struct ata_device *dev);
extern unsigned ata_exec_internal(struct ata_device *dev,
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index 99a2ce723495..b1daa4d3fcd9 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -303,7 +303,7 @@ static struct platform_driver ixp4xx_pata_platform_driver = {
.of_match_table = ixp4xx_pata_of_match,
},
.probe = ixp4xx_pata_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
};
module_platform_driver(ixp4xx_pata_platform_driver);
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
index b1ce9f1761af..ff538b858928 100644
--- a/drivers/ata/pata_octeon_cf.c
+++ b/drivers/ata/pata_octeon_cf.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <scsi/scsi_host.h>
@@ -804,9 +805,7 @@ static int octeon_cf_probe(struct platform_device *pdev)
struct resource *res_cs0, *res_cs1;
bool is_16bit;
- const __be32 *cs_num;
- struct property *reg_prop;
- int n_addr, n_size, reg_len;
+ u64 reg;
struct device_node *node;
void __iomem *cs0;
void __iomem *cs1 = NULL;
@@ -834,15 +833,10 @@ static int octeon_cf_probe(struct platform_device *pdev)
else
is_16bit = false;
- n_addr = of_n_addr_cells(node);
- n_size = of_n_size_cells(node);
-
- reg_prop = of_find_property(node, "reg", &reg_len);
- if (!reg_prop || reg_len < sizeof(__be32))
- return -EINVAL;
-
- cs_num = reg_prop->value;
- cf_port->cs0 = be32_to_cpup(cs_num);
+ rv = of_property_read_reg(node, 0, &reg, NULL);
+ if (rv < 0)
+ return rv;
+ cf_port->cs0 = upper_32_bits(reg);
if (cf_port->is_true_ide) {
struct device_node *dma_node;
@@ -884,13 +878,12 @@ static int octeon_cf_probe(struct platform_device *pdev)
cs1 = devm_ioremap(&pdev->dev, res_cs1->start,
resource_size(res_cs1));
if (!cs1)
- return rv;
-
- if (reg_len < (n_addr + n_size + 1) * sizeof(__be32))
return -EINVAL;
- cs_num += n_addr + n_size;
- cf_port->cs1 = be32_to_cpup(cs_num);
+ rv = of_property_read_reg(node, 1, &reg, NULL);
+ if (rv < 0)
+ return rv;
+ cf_port->cs1 = upper_32_bits(reg);
}
res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
index 178b28eff170..4956f0f5b93f 100644
--- a/drivers/ata/pata_of_platform.c
+++ b/drivers/ata/pata_of_platform.c
@@ -89,7 +89,7 @@ static struct platform_driver pata_of_platform_driver = {
.of_match_table = pata_of_platform_match,
},
.probe = pata_of_platform_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
};
module_platform_driver(pata_of_platform_driver);
diff --git a/drivers/ata/pata_parport/aten.c b/drivers/ata/pata_parport/aten.c
index 1bd248c42f8b..8328a49a95ef 100644
--- a/drivers/ata/pata_parport/aten.c
+++ b/drivers/ata/pata_parport/aten.c
@@ -1,13 +1,12 @@
-/*
- aten.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- aten.c is a low-level protocol driver for the ATEN EH-100
- parallel port adapter. The EH-100 supports 4-bit and 8-bit
- modes only. There is also an EH-132 which supports EPP mode
- transfers. The EH-132 is not yet supported.
-
-*/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ *
+ * aten.c is a low-level protocol driver for the ATEN EH-100
+ * parallel port adapter. The EH-100 supports 4-bit and 8-bit
+ * modes only. There is also an EH-132 which supports EPP mode
+ * transfers. The EH-132 is not yet supported.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -20,36 +19,36 @@
#define j44(a,b) ((((a>>4)&0x0f)|(b&0xf0))^0x88)
-/* cont = 0 - access the IDE register file
- cont = 1 - access the IDE command set
-*/
-
+/*
+ * cont = 0 - access the IDE register file
+ * cont = 1 - access the IDE command set
+ */
static int cont_map[2] = { 0x08, 0x20 };
static void aten_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
-
-{ int r;
-
- r = regr + cont_map[cont] + 0x80;
+{
+ int r = regr + cont_map[cont] + 0x80;
w0(r); w2(0xe); w2(6); w0(val); w2(7); w2(6); w2(0xc);
}
static int aten_read_regr(struct pi_adapter *pi, int cont, int regr)
+{
+ int a, b, r;
-{ int a, b, r;
-
- r = regr + cont_map[cont] + 0x40;
+ r = regr + cont_map[cont] + 0x40;
switch (pi->mode) {
- case 0: w0(r); w2(0xe); w2(6);
+ case 0:
+ w0(r); w2(0xe); w2(6);
w2(7); w2(6); w2(0);
a = r1(); w0(0x10); b = r1(); w2(0xc);
return j44(a,b);
- case 1: r |= 0x10;
- w0(r); w2(0xe); w2(6); w0(0xff);
+ case 1:
+ r |= 0x10;
+ w0(r); w2(0xe); w2(6); w0(0xff);
w2(0x27); w2(0x26); w2(0x20);
a = r0();
w2(0x26); w2(0xc);
@@ -59,27 +58,30 @@ static int aten_read_regr(struct pi_adapter *pi, int cont, int regr)
}
static void aten_read_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int k, a, b, c, d;
+{
+ int k, a, b, c, d;
switch (pi->mode) {
- case 0: w0(0x48); w2(0xe); w2(6);
- for (k=0;k<count/2;k++) {
+ case 0:
+ w0(0x48); w2(0xe); w2(6);
+ for (k = 0; k < count / 2; k++) {
w2(7); w2(6); w2(2);
a = r1(); w0(0x58); b = r1();
w2(0); d = r1(); w0(0x48); c = r1();
- buf[2*k] = j44(c,d);
- buf[2*k+1] = j44(a,b);
+ buf[2 * k] = j44(c, d);
+ buf[2 * k + 1] = j44(a, b);
}
w2(0xc);
break;
- case 1: w0(0x58); w2(0xe); w2(6);
- for (k=0;k<count/2;k++) {
+ case 1:
+ w0(0x58); w2(0xe); w2(6);
+ for (k = 0; k < count / 2; k++) {
w2(0x27); w2(0x26); w2(0x22);
a = r0(); w2(0x20); b = r0();
- buf[2*k] = b; buf[2*k+1] = a;
+ buf[2 * k] = b;
+ buf[2 * k + 1] = a;
}
w2(0x26); w2(0xc);
break;
@@ -87,36 +89,37 @@ static void aten_read_block(struct pi_adapter *pi, char *buf, int count)
}
static void aten_write_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int k;
+{
+ int k;
w0(0x88); w2(0xe); w2(6);
- for (k=0;k<count/2;k++) {
- w0(buf[2*k+1]); w2(0xe); w2(6);
- w0(buf[2*k]); w2(7); w2(6);
+ for (k = 0; k < count / 2; k++) {
+ w0(buf[2 * k + 1]); w2(0xe); w2(6);
+ w0(buf[2 * k]); w2(7); w2(6);
}
w2(0xc);
}
static void aten_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
- w2(0xc);
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+ w2(0xc);
}
static void aten_disconnect(struct pi_adapter *pi)
-
-{ w0(pi->saved_r0);
- w2(pi->saved_r2);
-}
+{
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
+}
static void aten_log_adapter(struct pi_adapter *pi)
+{
+ char *mode_string[2] = { "4-bit", "8-bit" };
-{ char *mode_string[2] = {"4-bit","8-bit"};
-
- dev_info(&pi->dev, "ATEN EH-100 at 0x%x, mode %d (%s), delay %d\n",
- pi->port, pi->mode, mode_string[pi->mode], pi->delay);
+ dev_info(&pi->dev,
+ "ATEN EH-100 at 0x%x, mode %d (%s), delay %d\n",
+ pi->port, pi->mode, mode_string[pi->mode], pi->delay);
}
static struct pi_protocol aten = {
diff --git a/drivers/ata/pata_parport/bpck.c b/drivers/ata/pata_parport/bpck.c
index 1c5035a09554..9f4309f9b57f 100644
--- a/drivers/ata/pata_parport/bpck.c
+++ b/drivers/ata/pata_parport/bpck.c
@@ -1,11 +1,10 @@
-/*
- bpck.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- bpck.c is a low-level protocol driver for the MicroSolutions
- "backpack" parallel port IDE adapter.
-
-*/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1996-1998 Grant R. Guenther <grant@torque.net>
+ *
+ * bpck.c is a low-level protocol driver for the MicroSolutions
+ * "backpack" parallel port IDE adapter.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -29,59 +28,57 @@
#define j44(l,h) (((l>>3)&0x7)|((l>>4)&0x8)|((h<<1)&0x70)|(h&0x80))
-/* cont = 0 - access the IDE register file
- cont = 1 - access the IDE command set
- cont = 2 - use internal bpck register addressing
-*/
-
+/*
+ * cont = 0 - access the IDE register file
+ * cont = 1 - access the IDE command set
+ * cont = 2 - use internal bpck register addressing
+ */
static int cont_map[3] = { 0x40, 0x48, 0 };
static int bpck_read_regr(struct pi_adapter *pi, int cont, int regr)
-
-{ int r, l, h;
+{
+ int r, l, h;
r = regr + cont_map[cont];
switch (pi->mode) {
-
- case 0: w0(r & 0xf); w0(r); t2(2); t2(4);
+ case 0:
+ w0(r & 0xf); w0(r); t2(2); t2(4);
l = r1();
- t2(4);
- h = r1();
- return j44(l,h);
-
- case 1: w0(r & 0xf); w0(r); t2(2);
- e2(); t2(0x20);
+ t2(4);
+ h = r1();
+ return j44(l, h);
+ case 1:
+ w0(r & 0xf); w0(r); t2(2);
+ e2(); t2(0x20);
t2(4); h = r0();
- t2(1); t2(0x20);
- return h;
-
+ t2(1); t2(0x20);
+ return h;
case 2:
case 3:
- case 4: w0(r); w2(9); w2(0); w2(0x20);
+ case 4:
+ w0(r); w2(9); w2(0); w2(0x20);
h = r4();
w2(0);
return h;
}
return -1;
-}
+}
static void bpck_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
-
-{ int r;
+{
+ int r;
r = regr + cont_map[cont];
switch (pi->mode) {
-
case 0:
case 1: w0(r);
t2(2);
w0(val);
o2(); t2(4); t2(1);
break;
-
case 2:
case 3:
case 4: w0(r); w2(9); w2(0);
@@ -97,210 +94,249 @@ static void bpck_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
#define RR(r) (bpck_read_regr(pi,2,r))
static void bpck_write_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int i;
+{
+ int i;
switch (pi->mode) {
- case 0: WR(4,0x40);
+ case 0:
+ WR(4, 0x40);
+ w0(0x40); t2(2); t2(1);
+ for (i = 0; i < count; i++) {
+ w0(buf[i]);
+ t2(4);
+ }
+ WR(4, 0);
+ break;
+
+ case 1:
+ WR(4, 0x50);
w0(0x40); t2(2); t2(1);
- for (i=0;i<count;i++) { w0(buf[i]); t2(4); }
- WR(4,0);
+ for (i = 0; i < count; i++) {
+ w0(buf[i]);
+ t2(4);
+ }
+ WR(4, 0x10);
break;
- case 1: WR(4,0x50);
- w0(0x40); t2(2); t2(1);
- for (i=0;i<count;i++) { w0(buf[i]); t2(4); }
- WR(4,0x10);
+ case 2:
+ WR(4, 0x48);
+ w0(0x40); w2(9); w2(0); w2(1);
+ for (i = 0; i < count; i++)
+ w4(buf[i]);
+ w2(0);
+ WR(4, 8);
break;
- case 2: WR(4,0x48);
+ case 3:
+ WR(4, 0x48);
w0(0x40); w2(9); w2(0); w2(1);
- for (i=0;i<count;i++) w4(buf[i]);
+ for (i = 0; i < count / 2; i++)
+ w4w(((u16 *)buf)[i]);
w2(0);
- WR(4,8);
+ WR(4, 8);
break;
- case 3: WR(4,0x48);
- w0(0x40); w2(9); w2(0); w2(1);
- for (i=0;i<count/2;i++) w4w(((u16 *)buf)[i]);
- w2(0);
- WR(4,8);
- break;
-
- case 4: WR(4,0x48);
- w0(0x40); w2(9); w2(0); w2(1);
- for (i=0;i<count/4;i++) w4l(((u32 *)buf)[i]);
- w2(0);
- WR(4,8);
- break;
+ case 4:
+ WR(4, 0x48);
+ w0(0x40); w2(9); w2(0); w2(1);
+ for (i = 0; i < count / 4; i++)
+ w4l(((u32 *)buf)[i]);
+ w2(0);
+ WR(4, 8);
+ break;
}
}
static void bpck_read_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int i, l, h;
+{
+ int i, l, h;
switch (pi->mode) {
- case 0: WR(4,0x40);
+ case 0:
+ WR(4, 0x40);
w0(0x40); t2(2);
- for (i=0;i<count;i++) {
- t2(4); l = r1();
- t2(4); h = r1();
- buf[i] = j44(l,h);
+ for (i = 0; i < count; i++) {
+ t2(4); l = r1();
+ t2(4); h = r1();
+ buf[i] = j44(l, h);
}
- WR(4,0);
+ WR(4, 0);
break;
- case 1: WR(4,0x50);
+ case 1:
+ WR(4, 0x50);
w0(0x40); t2(2); t2(0x20);
- for(i=0;i<count;i++) { t2(4); buf[i] = r0(); }
- t2(1); t2(0x20);
- WR(4,0x10);
+ for (i = 0; i < count; i++) {
+ t2(4);
+ buf[i] = r0();
+ }
+ t2(1); t2(0x20);
+ WR(4, 0x10);
break;
- case 2: WR(4,0x48);
+ case 2:
+ WR(4, 0x48);
w0(0x40); w2(9); w2(0); w2(0x20);
- for (i=0;i<count;i++) buf[i] = r4();
+ for (i = 0; i < count; i++)
+ buf[i] = r4();
w2(0);
- WR(4,8);
+ WR(4, 8);
break;
- case 3: WR(4,0x48);
- w0(0x40); w2(9); w2(0); w2(0x20);
- for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w();
- w2(0);
- WR(4,8);
- break;
+ case 3:
+ WR(4, 0x48);
+ w0(0x40); w2(9); w2(0); w2(0x20);
+ for (i = 0; i < count / 2; i++)
+ ((u16 *)buf)[i] = r4w();
+ w2(0);
+ WR(4, 8);
+ break;
- case 4: WR(4,0x48);
- w0(0x40); w2(9); w2(0); w2(0x20);
- for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l();
- w2(0);
- WR(4,8);
- break;
+ case 4:
+ WR(4, 0x48);
+ w0(0x40); w2(9); w2(0); w2(0x20);
+ for (i = 0; i < count / 4; i++)
+ ((u32 *)buf)[i] = r4l();
+ w2(0);
+ WR(4, 8);
+ break;
}
}
static int bpck_probe_unit(struct pi_adapter *pi)
-
-{ int o1, o0, f7, id;
+{
+ int o1, o0, f7, id;
int t, s;
id = pi->unit;
s = 0;
- w2(4); w2(0xe); r2(); t2(2);
+ w2(4); w2(0xe); r2(); t2(2);
o1 = r1()&0xf8;
o0 = r0();
w0(255-id); w2(4); w0(id);
t2(8); t2(8); t2(8);
t2(2); t = r1()&0xf8;
f7 = ((id % 8) == 7);
- if ((f7) || (t != o1)) { t2(2); s = r1()&0xf8; }
+ if ((f7) || (t != o1)) {
+ t2(2);
+ s = r1() & 0xf8;
+ }
if ((t == o1) && ((!f7) || (s == o1))) {
w2(0x4c); w0(o0);
- return 0;
+ return 0;
}
t2(8); w0(0); t2(2); w2(0x4c); w0(o0);
return 1;
}
-
-static void bpck_connect(struct pi_adapter *pi)
-{ pi->saved_r0 = r0();
+static void bpck_connect(struct pi_adapter *pi)
+{
+ pi->saved_r0 = r0();
w0(0xff-pi->unit); w2(4); w0(pi->unit);
- t2(8); t2(8); t2(8);
+ t2(8); t2(8); t2(8);
t2(2); t2(2);
-
- switch (pi->mode) {
- case 0: t2(8); WR(4,0);
+ switch (pi->mode) {
+ case 0:
+ t2(8); WR(4, 0);
break;
-
- case 1: t2(8); WR(4,0x10);
+ case 1:
+ t2(8); WR(4, 0x10);
break;
-
case 2:
- case 3:
- case 4: w2(0); WR(4,8);
+ case 3:
+ case 4:
+ w2(0); WR(4, 8);
break;
-
}
WR(5,8);
-/* if (pi->devtype == PI_PCD) { possibly wrong, purpose unknown */
- WR(0x46,0x10); /* fiddle with ESS logic ??? */
- WR(0x4c,0x38);
- WR(0x4d,0x88);
- WR(0x46,0xa0);
- WR(0x41,0);
- WR(0x4e,8);
-/* }*/
+ /*
+ * Possibly wrong, purpose unknown (fiddle with ESS logic ???)
+ * if (pi->devtype == PI_PCD) {
+ */
+ WR(0x46, 0x10);
+ WR(0x4c, 0x38);
+ WR(0x4d, 0x88);
+ WR(0x46, 0xa0);
+ WR(0x41, 0);
+ WR(0x4e, 8);
+ /* } */
}
static void bpck_disconnect(struct pi_adapter *pi)
-
-{ w0(0);
- if (pi->mode >= 2) { w2(9); w2(0); } else t2(2);
+{
+ w0(0);
+ if (pi->mode >= 2) {
+ w2(9); w2(0);
+ } else {
+ t2(2);
+ }
w2(0x4c); w0(pi->saved_r0);
-}
+}
static void bpck_force_spp(struct pi_adapter *pi)
+{
+ /* This fakes the EPP protocol to turn off EPP ... */
+ pi->saved_r0 = r0();
+ w0(0xff-pi->unit); w2(4); w0(pi->unit);
+ t2(8); t2(8); t2(8);
+ t2(2); t2(2);
-/* This fakes the EPP protocol to turn off EPP ... */
-
-{ pi->saved_r0 = r0();
- w0(0xff-pi->unit); w2(4); w0(pi->unit);
- t2(8); t2(8); t2(8);
- t2(2); t2(2);
-
- w2(0);
- w0(4); w2(9); w2(0);
- w0(0); w2(1); w2(3); w2(0);
- w0(0); w2(9); w2(0);
- w2(0x4c); w0(pi->saved_r0);
+ w2(0);
+ w0(4); w2(9); w2(0);
+ w0(0); w2(1); w2(3); w2(0);
+ w0(0); w2(9); w2(0);
+ w2(0x4c); w0(pi->saved_r0);
}
#define TEST_LEN 16
static int bpck_test_proto(struct pi_adapter *pi)
-
-{ int i, e, l, h, om;
+{
+ int i, e, l, h, om;
char buf[TEST_LEN];
bpck_force_spp(pi);
switch (pi->mode) {
- case 0: bpck_connect(pi);
- WR(0x13,0x7f);
+ case 0:
+ bpck_connect(pi);
+ WR(0x13, 0x7f);
w0(0x13); t2(2);
- for(i=0;i<TEST_LEN;i++) {
- t2(4); l = r1();
- t2(4); h = r1();
- buf[i] = j44(l,h);
+ for (i = 0; i < TEST_LEN; i++) {
+ t2(4); l = r1();
+ t2(4); h = r1();
+ buf[i] = j44(l, h);
}
bpck_disconnect(pi);
break;
- case 1: bpck_connect(pi);
- WR(0x13,0x7f);
- w0(0x13); t2(2); t2(0x20);
- for(i=0;i<TEST_LEN;i++) { t2(4); buf[i] = r0(); }
- t2(1); t2(0x20);
+ case 1:
+ bpck_connect(pi);
+ WR(0x13, 0x7f);
+ w0(0x13); t2(2); t2(0x20);
+ for (i = 0; i < TEST_LEN; i++) {
+ t2(4);
+ buf[i] = r0();
+ }
+ t2(1); t2(0x20);
bpck_disconnect(pi);
break;
case 2:
case 3:
- case 4: om = pi->mode;
+ case 4:
+ om = pi->mode;
pi->mode = 0;
bpck_connect(pi);
- WR(7,3);
- WR(4,8);
+ WR(7, 3);
+ WR(4, 8);
bpck_disconnect(pi);
pi->mode = om;
@@ -308,34 +344,44 @@ static int bpck_test_proto(struct pi_adapter *pi)
w0(0x13); w2(9); w2(1); w0(0); w2(3); w2(0); w2(0xe0);
switch (pi->mode) {
- case 2: for (i=0;i<TEST_LEN;i++) buf[i] = r4();
- break;
- case 3: for (i=0;i<TEST_LEN/2;i++) ((u16 *)buf)[i] = r4w();
- break;
- case 4: for (i=0;i<TEST_LEN/4;i++) ((u32 *)buf)[i] = r4l();
- break;
+ case 2:
+ for (i = 0; i < TEST_LEN; i++)
+ buf[i] = r4();
+ break;
+ case 3:
+ for (i = 0; i < TEST_LEN / 2; i++)
+ ((u16 *)buf)[i] = r4w();
+ break;
+ case 4:
+ for (i = 0; i < TEST_LEN / 4; i++)
+ ((u32 *)buf)[i] = r4l();
+ break;
}
w2(0);
- WR(7,0);
+ WR(7, 0);
bpck_disconnect(pi);
-
break;
}
dev_dbg(&pi->dev, "bpck: 0x%x unit %d mode %d: ",
pi->port, pi->unit, pi->mode);
- print_hex_dump_debug("bpck: ", DUMP_PREFIX_NONE, TEST_LEN, 1, buf, TEST_LEN, false);
+ print_hex_dump_debug("bpck: ", DUMP_PREFIX_NONE, TEST_LEN, 1, buf,
+ TEST_LEN, false);
e = 0;
- for (i=0;i<TEST_LEN;i++) if (buf[i] != (i+1)) e++;
+ for (i = 0; i < TEST_LEN; i++) {
+ if (buf[i] != i + 1)
+ e++;
+ }
+
return e;
}
static void bpck_read_eeprom(struct pi_adapter *pi, char *buf)
-
-{ int i, j, k, p, v, f, om, od;
+{
+ int i, j, k, p, v, f, om, od;
bpck_force_spp(pi);
@@ -343,77 +389,97 @@ static void bpck_read_eeprom(struct pi_adapter *pi, char *buf)
pi->mode = 0; pi->delay = 6;
bpck_connect(pi);
-
- WR(4,0);
- for (i=0;i<64;i++) {
- WR(6,8);
- WR(6,0xc);
- p = 0x100;
- for (k=0;k<9;k++) {
- f = (((i + 0x180) & p) != 0) * 2;
- WR(6,f+0xc);
- WR(6,f+0xd);
- WR(6,f+0xc);
- p = (p >> 1);
- }
- for (j=0;j<2;j++) {
- v = 0;
- for (k=0;k<8;k++) {
- WR(6,0xc);
- WR(6,0xd);
- WR(6,0xc);
- f = RR(0);
- v = 2*v + (f == 0x84);
+
+ WR(4, 0);
+ for (i = 0; i < 64; i++) {
+ WR(6, 8);
+ WR(6, 0xc);
+ p = 0x100;
+ for (k = 0; k < 9; k++) {
+ f = (((i + 0x180) & p) != 0) * 2;
+ WR(6, f + 0xc);
+ WR(6, f + 0xd);
+ WR(6, f + 0xc);
+ p = (p >> 1);
+ }
+ for (j = 0; j < 2; j++) {
+ v = 0;
+ for (k = 0; k < 8; k++) {
+ WR(6, 0xc);
+ WR(6, 0xd);
+ WR(6, 0xc);
+ f = RR(0);
+ v = 2 * v + (f == 0x84);
+ }
+ buf[2 * i + 1 - j] = v;
}
- buf[2*i+1-j] = v;
- }
}
- WR(6,8);
- WR(6,0);
- WR(5,8);
+ WR(6, 8);
+ WR(6, 0);
+ WR(5, 8);
bpck_disconnect(pi);
if (om >= 2) {
- bpck_connect(pi);
- WR(7,3);
- WR(4,8);
- bpck_disconnect(pi);
+ bpck_connect(pi);
+ WR(7, 3);
+ WR(4, 8);
+ bpck_disconnect(pi);
}
pi->mode = om; pi->delay = od;
}
-static int bpck_test_port(struct pi_adapter *pi) /* check for 8-bit port */
-
-{ int i, r, m;
+static int bpck_test_port(struct pi_adapter *pi)
+{
+ int i, r, m;
+ /* Check for 8-bit port */
w2(0x2c); i = r0(); w0(255-i); r = r0(); w0(i);
m = -1;
- if (r == i) m = 2;
- if (r == (255-i)) m = 0;
+ if (r == i)
+ m = 2;
+ if (r == (255-i))
+ m = 0;
+
+ w2(0xc);
+ i = r0();
+ w0(255-i);
+ r = r0();
+ w0(i);
+ if (r != (255-i))
+ m = -1;
+
+ if (m == 0) {
+ w2(6);
+ w2(0xc);
+ r = r0();
+ w0(0xaa);
+ w0(r);
+ w0(0xaa);
+ }
+ if (m == 2) {
+ w2(0x26);
+ w2(0xc);
+ }
- w2(0xc); i = r0(); w0(255-i); r = r0(); w0(i);
- if (r != (255-i)) m = -1;
-
- if (m == 0) { w2(6); w2(0xc); r = r0(); w0(0xaa); w0(r); w0(0xaa); }
- if (m == 2) { w2(0x26); w2(0xc); }
+ if (m == -1)
+ return 0;
- if (m == -1) return 0;
return 5;
}
static void bpck_log_adapter(struct pi_adapter *pi)
-
-{ char *mode_string[5] = { "4-bit","8-bit","EPP-8",
- "EPP-16","EPP-32" };
+{
+ char *mode_str[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
char scratch[128];
bpck_read_eeprom(pi,scratch);
print_hex_dump_bytes("bpck EEPROM: ", DUMP_PREFIX_NONE, scratch, 128);
- dev_info(&pi->dev, "backpack %8.8s unit %d at 0x%x, mode %d (%s), delay %d\n",
+ dev_info(&pi->dev,
+ "backpack %8.8s unit %d at 0x%x, mode %d (%s), delay %d\n",
&scratch[110], pi->unit, pi->port, pi->mode,
- mode_string[pi->mode], pi->delay);
+ mode_str[pi->mode], pi->delay);
}
static struct pi_protocol bpck = {
diff --git a/drivers/ata/pata_parport/bpck6.c b/drivers/ata/pata_parport/bpck6.c
index 76febd07a9bb..c6dbd14120d1 100644
--- a/drivers/ata/pata_parport/bpck6.c
+++ b/drivers/ata/pata_parport/bpck6.c
@@ -1,15 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- backpack.c (c) 2001 Micro Solutions Inc.
- Released under the terms of the GNU General Public license
-
- backpack.c is a low-level protocol driver for the Micro Solutions
- "BACKPACK" parallel port IDE adapter
- (Works on Series 6 drives)
-
- Written by: Ken Hahn (linux-dev@micro-solutions.com)
- Clive Turvey (linux-dev@micro-solutions.com)
-
-*/
+ * (c) 2001 Micro Solutions Inc.
+ *
+ * backpack.c is a low-level protocol driver for the Micro Solutions
+ * "BACKPACK" parallel port IDE adapter (works on Series 6 drives).
+ *
+ * Written by: Ken Hahn (linux-dev@micro-solutions.com)
+ * Clive Turvey (linux-dev@micro-solutions.com)
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -326,11 +324,14 @@ static int bpck6_open(struct pi_adapter *pi)
if (j != k)
goto fail;
- if (i & 4) // EPP
+ if (i & 4) {
+ /* EPP */
parport_frob_control(pi->pardev->port,
PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, 0);
- else // PPC/ECP
+ } else {
+ /* PPC/ECP */
parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, 0);
+ }
pi->private = 0;
@@ -347,17 +348,20 @@ fail:
parport_write_control(pi->pardev->port, pi->saved_r2);
parport_write_data(pi->pardev->port, pi->saved_r0);
- return 0; // FAIL
+ return 0;
}
static void bpck6_deselect(struct pi_adapter *pi)
{
- if (mode_map[pi->mode] & 4) // EPP
+ if (mode_map[pi->mode] & 4) {
+ /* EPP */
parport_frob_control(pi->pardev->port, PARPORT_CONTROL_INIT,
- PARPORT_CONTROL_INIT);
- else // PPC/ECP
+ PARPORT_CONTROL_INIT);
+ } else {
+ /* PPC/ECP */
parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT,
- PARPORT_CONTROL_SELECT);
+ PARPORT_CONTROL_SELECT);
+ }
parport_write_data(pi->pardev->port, pi->saved_r0);
parport_write_control(pi->pardev->port,
@@ -386,7 +390,8 @@ static void bpck6_disconnect(struct pi_adapter *pi)
bpck6_deselect(pi);
}
-static int bpck6_test_port(struct pi_adapter *pi) /* check for 8-bit port */
+/* check for 8-bit port */
+static int bpck6_test_port(struct pi_adapter *pi)
{
dev_dbg(&pi->dev, "PARPORT indicates modes=%x for lp=0x%lx\n",
pi->pardev->port->modes, pi->pardev->port->base);
@@ -413,28 +418,26 @@ static int bpck6_probe_unit(struct pi_adapter *pi)
dev_dbg(&pi->dev, "ppc_open returned %2x\n", out);
- if(out)
- {
+ if (out) {
bpck6_deselect(pi);
dev_dbg(&pi->dev, "leaving probe\n");
pi->mode = saved_mode;
- return(1);
+ return 1;
}
- else
- {
- dev_dbg(&pi->dev, "Failed open\n");
- pi->mode = saved_mode;
- return(0);
- }
+
+ dev_dbg(&pi->dev, "Failed open\n");
+ pi->mode = saved_mode;
+
+ return 0;
}
static void bpck6_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, "Micro Solutions BACKPACK Drive unit %d at 0x%x, mode:%d (%s), delay %d\n",
- pi->unit, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
+ dev_info(&pi->dev,
+ "Micro Solutions BACKPACK Drive unit %d at 0x%x, mode:%d (%s), delay %d\n",
+ pi->unit, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
}
static struct pi_protocol bpck6 = {
diff --git a/drivers/ata/pata_parport/comm.c b/drivers/ata/pata_parport/comm.c
index 4c2f9ad60ad8..cc5485bd0a5b 100644
--- a/drivers/ata/pata_parport/comm.c
+++ b/drivers/ata/pata_parport/comm.c
@@ -1,12 +1,11 @@
-/*
- comm.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- comm.c is a low-level protocol driver for some older models
- of the DataStor "Commuter" parallel to IDE adapter. Some of
- the parallel port devices marketed by Arista currently
- use this adapter.
-*/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1997-1998 Grant R. Guenther <grant@torque.net>
+ *
+ * comm.c is a low-level protocol driver for some older models of the DataStor
+ * "Commuter" parallel to IDE adapter. Some of the parallel port devices
+ * marketed by Arista currently use this adapter.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -17,165 +16,172 @@
#include <asm/io.h>
#include "pata_parport.h"
-/* mode codes: 0 nybble reads, 8-bit writes
- 1 8-bit reads and writes
- 2 8-bit EPP mode
-*/
+/*
+ * mode codes: 0 nybble reads, 8-bit writes
+ * 1 8-bit reads and writes
+ * 2 8-bit EPP mode
+ */
-#define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0))
+#define j44(a, b) (((a >> 3) & 0x0f) | ((b << 1) & 0xf0))
#define P1 w2(5);w2(0xd);w2(0xd);w2(5);w2(4);
#define P2 w2(5);w2(7);w2(7);w2(5);w2(4);
-/* cont = 0 - access the IDE register file
- cont = 1 - access the IDE command set
-*/
-
+/*
+ * cont = 0 - access the IDE register file
+ * cont = 1 - access the IDE command set
+ */
static int cont_map[2] = { 0x08, 0x10 };
static int comm_read_regr(struct pi_adapter *pi, int cont, int regr)
-
-{ int l, h, r;
+{
+ int l, h, r;
r = regr + cont_map[cont];
- switch (pi->mode) {
+ switch (pi->mode) {
+ case 0:
+ w0(r); P1; w0(0);
+ w2(6); l = r1(); w0(0x80); h = r1(); w2(4);
+ return j44(l, h);
- case 0: w0(r); P1; w0(0);
- w2(6); l = r1(); w0(0x80); h = r1(); w2(4);
- return j44(l,h);
-
- case 1: w0(r+0x20); P1;
- w0(0); w2(0x26); h = r0(); w2(4);
- return h;
+ case 1:
+ w0(r+0x20); P1;
+ w0(0); w2(0x26); h = r0(); w2(4);
+ return h;
case 2:
case 3:
- case 4: w3(r+0x20); (void)r1();
- w2(0x24); h = r4(); w2(4);
- return h;
+ case 4:
+ w3(r+0x20); (void)r1();
+ w2(0x24); h = r4(); w2(4);
+ return h;
+ }
- }
- return -1;
-}
+ return -1;
+}
static void comm_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
+{
+ int r = regr + cont_map[cont];
-{ int r;
-
- r = regr + cont_map[cont];
-
- switch (pi->mode) {
-
- case 0:
- case 1: w0(r); P1; w0(val); P2;
+ switch (pi->mode) {
+ case 0:
+ case 1:
+ w0(r); P1; w0(val); P2;
break;
-
case 2:
case 3:
- case 4: w3(r); (void)r1(); w4(val);
- break;
- }
+ case 4:
+ w3(r); (void)r1(); w4(val);
+ break;
+ }
}
static void comm_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
- w2(4); w0(0xff); w2(6);
- w2(4); w0(0xaa); w2(6);
- w2(4); w0(0x00); w2(6);
- w2(4); w0(0x87); w2(6);
- w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4);
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+ w2(4); w0(0xff); w2(6);
+ w2(4); w0(0xaa); w2(6);
+ w2(4); w0(0x00); w2(6);
+ w2(4); w0(0x87); w2(6);
+ w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4);
}
static void comm_disconnect(struct pi_adapter *pi)
-{ w2(0); w2(0); w2(0); w2(4);
+{
+ w2(0); w2(0); w2(0); w2(4);
w0(pi->saved_r0);
- w2(pi->saved_r2);
-}
+ w2(pi->saved_r2);
+}
static void comm_read_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int i, l, h;
-
- switch (pi->mode) {
-
- case 0: w0(0x48); P1;
- for(i=0;i<count;i++) {
- w0(0); w2(6); l = r1();
- w0(0x80); h = r1(); w2(4);
- buf[i] = j44(l,h);
- }
- break;
-
- case 1: w0(0x68); P1; w0(0);
- for(i=0;i<count;i++) {
- w2(0x26); buf[i] = r0(); w2(0x24);
- }
+{
+ int i, l, h;
+
+ switch (pi->mode) {
+ case 0:
+ w0(0x48); P1;
+ for (i = 0; i < count; i++) {
+ w0(0); w2(6); l = r1();
+ w0(0x80); h = r1(); w2(4);
+ buf[i] = j44(l, h);
+ }
+ break;
+ case 1:
+ w0(0x68); P1; w0(0);
+ for (i = 0; i < count; i++) {
+ w2(0x26);
+ buf[i] = r0();
+ w2(0x24);
+ }
w2(4);
break;
-
- case 2: w3(0x68); (void)r1(); w2(0x24);
- for (i=0;i<count;i++) buf[i] = r4();
+ case 2:
+ w3(0x68); (void)r1(); w2(0x24);
+ for (i = 0; i < count; i++)
+ buf[i] = r4();
+ w2(4);
+ break;
+ case 3:
+ w3(0x68); (void)r1(); w2(0x24);
+ for (i = 0; i < count / 2; i++)
+ ((u16 *)buf)[i] = r4w();
+ w2(4);
+ break;
+ case 4:
+ w3(0x68); (void)r1(); w2(0x24);
+ for (i = 0; i < count / 4; i++)
+ ((u32 *)buf)[i] = r4l();
w2(4);
break;
-
- case 3: w3(0x68); (void)r1(); w2(0x24);
- for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w();
- w2(4);
- break;
-
- case 4: w3(0x68); (void)r1(); w2(0x24);
- for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l();
- w2(4);
- break;
-
}
}
/* NB: Watch out for the byte swapped writes ! */
-
static void comm_write_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int k;
-
- switch (pi->mode) {
-
- case 0:
- case 1: w0(0x68); P1;
- for (k=0;k<count;k++) {
- w2(5); w0(buf[k^1]); w2(7);
- }
- w2(5); w2(4);
- break;
-
- case 2: w3(0x48); (void)r1();
- for (k=0;k<count;k++) w4(buf[k^1]);
- break;
-
- case 3: w3(0x48); (void)r1();
+{
+ int k;
+
+ switch (pi->mode) {
+ case 0:
+ case 1:
+ w0(0x68); P1;
+ for (k = 0; k < count; k++) {
+ w2(5);
+ w0(buf[k ^ 1]);
+ w2(7);
+ }
+ w2(5); w2(4);
+ break;
+ case 2:
+ w3(0x48); (void)r1();
+ for (k = 0; k < count; k++)
+ w4(buf[k ^ 1]);
+ break;
+ case 3:
+ w3(0x48); (void)r1();
for (k = 0; k < count / 2; k++)
w4w(swab16(((u16 *)buf)[k]));
- break;
-
- case 4: w3(0x48); (void)r1();
+ break;
+ case 4:
+ w3(0x48); (void)r1();
for (k = 0; k < count / 4; k++)
w4l(swab16(((u16 *)buf)[2 * k]) |
swab16(((u16 *)buf)[2 * k + 1]) << 16);
- break;
-
-
+ 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",
- pi->port, pi->mode, mode_string[pi->mode], pi->delay);
+ dev_info(&pi->dev,
+ "DataStor Commuter at 0x%x, mode %d (%s), delay %d\n",
+ pi->port, pi->mode, mode_string[pi->mode], pi->delay);
}
static struct pi_protocol comm = {
diff --git a/drivers/ata/pata_parport/dstr.c b/drivers/ata/pata_parport/dstr.c
index 2524684be206..368d7c7962a9 100644
--- a/drivers/ata/pata_parport/dstr.c
+++ b/drivers/ata/pata_parport/dstr.c
@@ -1,11 +1,10 @@
-/*
- dstr.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- dstr.c is a low-level protocol driver for the
- DataStor EP2000 parallel to IDE adapter chip.
-
-*/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1997-1998 Grant R. Guenther <grant@torque.net>
+ *
+ * dstr.c is a low-level protocol driver for the DataStor EP2000 parallel
+ * to IDE adapter chip.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -16,178 +15,202 @@
#include <asm/io.h>
#include "pata_parport.h"
-/* mode codes: 0 nybble reads, 8-bit writes
- 1 8-bit reads and writes
- 2 8-bit EPP mode
- 3 EPP-16
- 4 EPP-32
-*/
+/*
+ * mode codes: 0 nybble reads, 8-bit writes
+ * 1 8-bit reads and writes
+ * 2 8-bit EPP mode
+ * 3 EPP-16
+ * 4 EPP-32
+ */
-#define j44(a,b) (((a>>3)&0x07)|((~a>>4)&0x08)|((b<<1)&0x70)|((~b)&0x80))
+#define j44(a, b) (((a >> 3) & 0x07) | ((~a >> 4) & 0x08) | \
+ ((b << 1) & 0x70) | ((~b) & 0x80))
#define P1 w2(5);w2(0xd);w2(5);w2(4);
#define P2 w2(5);w2(7);w2(5);w2(4);
#define P3 w2(6);w2(4);w2(6);w2(4);
-/* cont = 0 - access the IDE register file
- cont = 1 - access the IDE command set
-*/
-
+/*
+ * cont = 0 - access the IDE register file
+ * cont = 1 - access the IDE command set
+ */
static int cont_map[2] = { 0x20, 0x40 };
static int dstr_read_regr(struct pi_adapter *pi, int cont, int regr)
+{
+ int a, b, r;
-{ int a, b, r;
-
- r = regr + cont_map[cont];
+ r = regr + cont_map[cont];
w0(0x81); P1;
- if (pi->mode) { w0(0x11); } else { w0(1); }
+ if (pi->mode)
+ w0(0x11);
+ else
+ w0(1);
P2; w0(r); P1;
- switch (pi->mode) {
-
- case 0: w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4);
- return j44(a,b);
-
- case 1: w0(0); w2(0x26); a = r0(); w2(4);
- return a;
-
+ switch (pi->mode) {
+ case 0:
+ w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4);
+ return j44(a, b);
+ case 1:
+ w0(0); w2(0x26); a = r0(); w2(4);
+ return a;
case 2:
case 3:
- case 4: w2(0x24); a = r4(); w2(4);
- return a;
+ case 4:
+ w2(0x24); a = r4(); w2(4);
+ return a;
+ }
- }
- return -1;
-}
+ return -1;
+}
static void dstr_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
+{
+ int r = regr + cont_map[cont];
-{ int r;
-
- r = regr + cont_map[cont];
-
- w0(0x81); P1;
- if (pi->mode >= 2) { w0(0x11); } else { w0(1); }
+ w0(0x81); P1;
+ if (pi->mode >= 2)
+ w0(0x11);
+ else
+ w0(1);
P2; w0(r); P1;
-
- switch (pi->mode) {
- case 0:
- case 1: w0(val); w2(5); w2(7); w2(5); w2(4);
+ switch (pi->mode) {
+ case 0:
+ case 1:
+ w0(val); w2(5); w2(7); w2(5); w2(4);
break;
-
case 2:
case 3:
- case 4: w4(val);
- break;
- }
+ case 4:
+ w4(val);
+ break;
+ }
}
-#define CCP(x) w0(0xff);w2(0xc);w2(4);\
- w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);w0(0x78);\
- w0(x);w2(5);w2(4);
+#define CCP(x) \
+ do { \
+ w0(0xff); w2(0xc); w2(4); \
+ w0(0xaa); w0(0x55); w0(0); w0(0xff); \
+ w0(0x87); w0(0x78); \
+ w0(x); w2(5); w2(4); \
+ } while (0)
static void dstr_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
- w2(4); CCP(0xe0); w0(0xff);
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+ w2(4); CCP(0xe0); w0(0xff);
}
static void dstr_disconnect(struct pi_adapter *pi)
-
-{ CCP(0x30);
- w0(pi->saved_r0);
- w2(pi->saved_r2);
-}
+{
+ CCP(0x30);
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
+}
static void dstr_read_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int k, a, b;
+{
+ int k, a, b;
w0(0x81); P1;
- if (pi->mode) { w0(0x19); } else { w0(9); }
+ if (pi->mode)
+ w0(0x19);
+ else
+ w0(9);
P2; w0(0x82); P1; P3; w0(0x20); P1;
- switch (pi->mode) {
-
- case 0: for (k=0;k<count;k++) {
- w2(6); a = r1(); w2(4);
- w2(6); b = r1(); w2(4);
- buf[k] = j44(a,b);
- }
- break;
-
- case 1: w0(0);
- for (k=0;k<count;k++) {
- w2(0x26); buf[k] = r0(); w2(0x24);
- }
- w2(4);
- break;
-
- case 2: w2(0x24);
- for (k=0;k<count;k++) buf[k] = r4();
- w2(4);
- break;
-
- case 3: w2(0x24);
- for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
- w2(4);
- break;
-
- case 4: w2(0x24);
- for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
- w2(4);
- break;
-
- }
+ switch (pi->mode) {
+ case 0:
+ for (k = 0; k < count; k++) {
+ w2(6); a = r1(); w2(4);
+ w2(6); b = r1(); w2(4);
+ buf[k] = j44(a, b);
+ }
+ break;
+ case 1:
+ w0(0);
+ for (k = 0; k < count; k++) {
+ w2(0x26);
+ buf[k] = r0();
+ w2(0x24);
+ }
+ w2(4);
+ break;
+ case 2:
+ w2(0x24);
+ for (k = 0; k < count; k++)
+ buf[k] = r4();
+ w2(4);
+ break;
+ case 3:
+ w2(0x24);
+ for (k = 0; k < count / 2; k++)
+ ((u16 *)buf)[k] = r4w();
+ w2(4);
+ break;
+ case 4:
+ w2(0x24);
+ for (k = 0; k < count / 4; k++)
+ ((u32 *)buf)[k] = r4l();
+ w2(4);
+ break;
+ }
}
static void dstr_write_block(struct pi_adapter *pi, char *buf, int count)
+{
+ int k;
-{ int k;
-
- w0(0x81); P1;
- if (pi->mode) { w0(0x19); } else { w0(9); }
- P2; w0(0x82); P1; P3; w0(0x20); P1;
-
- switch (pi->mode) {
-
- case 0:
- case 1: for (k=0;k<count;k++) {
- w2(5); w0(buf[k]); w2(7);
- }
- w2(5); w2(4);
- break;
+ w0(0x81); P1;
+ if (pi->mode)
+ w0(0x19);
+ else
+ w0(9);
+ P2; w0(0x82); P1; P3; w0(0x20); P1;
- case 2: w2(0xc5);
- for (k=0;k<count;k++) w4(buf[k]);
+ switch (pi->mode) {
+ case 0:
+ case 1:
+ for (k = 0; k < count; k++) {
+ w2(5);
+ w0(buf[k]);
+ w2(7);
+ }
+ w2(5); w2(4);
+ break;
+ case 2:
+ w2(0xc5);
+ for (k = 0; k < count; k++)
+ w4(buf[k]);
w2(0xc4);
- break;
-
- case 3: w2(0xc5);
- for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
- w2(0xc4);
- break;
-
- case 4: w2(0xc5);
- for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
- w2(0xc4);
- break;
-
- }
+ break;
+ case 3:
+ w2(0xc5);
+ for (k = 0; k < count / 2; k++)
+ w4w(((u16 *)buf)[k]);
+ w2(0xc4);
+ break;
+ case 4:
+ w2(0xc5);
+ for (k = 0; k < count / 4; k++)
+ w4l(((u32 *)buf)[k]);
+ w2(0xc4);
+ break;
+ }
}
-
static void dstr_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 EP2000 at 0x%x, mode %d (%s), delay %d\n",
- pi->port, pi->mode, mode_string[pi->mode], pi->delay);
+ dev_info(&pi->dev,
+ "DataStor EP2000 at 0x%x, mode %d (%s), delay %d\n",
+ pi->port, pi->mode, mode_string[pi->mode], pi->delay);
}
static struct pi_protocol dstr = {
diff --git a/drivers/ata/pata_parport/epat.c b/drivers/ata/pata_parport/epat.c
index b146999368ae..016bd96bce89 100644
--- a/drivers/ata/pata_parport/epat.c
+++ b/drivers/ata/pata_parport/epat.c
@@ -1,13 +1,12 @@
-/*
- epat.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- This is the low level protocol driver for the EPAT parallel
- to IDE adapter from Shuttle Technologies. This adapter is
- used in many popular parallel port disk products such as the
- SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk.
-
-*/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1997-1998 Grant R. Guenther <grant@torque.net>
+ *
+ * This is the low level protocol driver for the EPAT parallel
+ * to IDE adapter from Shuttle Technologies. This adapter is
+ * used in many popular parallel port disk products such as the
+ * SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -18,276 +17,313 @@
#include <asm/io.h>
#include "pata_parport.h"
-#define j44(a,b) (((a>>4)&0x0f)+(b&0xf0))
-#define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0))
+#define j44(a, b) (((a >> 4) & 0x0f) + (b & 0xf0))
+#define j53(a, b) (((a >> 3) & 0x1f) + ((b << 4) & 0xe0))
static int epatc8;
module_param(epatc8, int, 0);
-MODULE_PARM_DESC(epatc8, "support for the Shuttle EP1284 chip, "
- "used in any recent Imation SuperDisk (LS-120) drive.");
-
-/* cont = 0 IDE register file
- cont = 1 IDE control registers
- cont = 2 internal EPAT registers
-*/
-
+MODULE_PARM_DESC(epatc8,
+ "support for the Shuttle EP1284 chip, "
+ "used in any recent Imation SuperDisk (LS-120) drive.");
+
+/*
+ * cont = 0 IDE register file
+ * cont = 1 IDE control registers
+ * cont = 2 internal EPAT registers
+ */
static int cont_map[3] = { 0x18, 0x10, 0 };
static void epat_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
-
-{ int r;
-
- r = regr + cont_map[cont];
+{
+ int r = regr + cont_map[cont];
switch (pi->mode) {
-
case 0:
case 1:
- case 2: w0(0x60+r); w2(1); w0(val); w2(4);
+ case 2:
+ w0(0x60+r); w2(1); w0(val); w2(4);
break;
-
case 3:
case 4:
- case 5: w3(0x40+r); w4(val);
+ case 5:
+ w3(0x40+r); w4(val);
break;
-
}
}
static int epat_read_regr(struct pi_adapter *pi, int cont, int regr)
-
-{ int a, b, r;
+{
+ int a, b, r;
r = regr + cont_map[cont];
switch (pi->mode) {
- case 0: w0(r); w2(1); w2(3);
+ case 0:
+ w0(r); w2(1); w2(3);
a = r1(); w2(4); b = r1();
- return j44(a,b);
-
- case 1: w0(0x40+r); w2(1); w2(4);
+ return j44(a, b);
+ case 1:
+ w0(0x40+r); w2(1); w2(4);
a = r1(); b = r2(); w0(0xff);
- return j53(a,b);
-
- case 2: w0(0x20+r); w2(1); w2(0x25);
+ return j53(a, b);
+ case 2:
+ w0(0x20+r); w2(1); w2(0x25);
a = r0(); w2(4);
return a;
-
case 3:
case 4:
- case 5: w3(r); w2(0x24); a = r4(); w2(4);
+ case 5:
+ w3(r); w2(0x24); a = r4(); w2(4);
return a;
-
}
+
return -1; /* never gets here */
}
static void epat_read_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int k, ph, a, b;
+{
+ int k, ph, a, b;
switch (pi->mode) {
- case 0: w0(7); w2(1); w2(3); w0(0xff);
+ case 0:
+ w0(7); w2(1); w2(3); w0(0xff);
ph = 0;
- for(k=0;k<count;k++) {
- if (k == count-1) w0(0xfd);
- w2(6+ph); a = r1();
- if (a & 8) b = a;
- else { w2(4+ph); b = r1(); }
- buf[k] = j44(a,b);
+ for (k = 0; k < count; k++) {
+ if (k == count-1)
+ w0(0xfd);
+ w2(6 + ph); a = r1();
+ if (a & 8) {
+ b = a;
+ } else {
+ w2(4+ph); b = r1();
+ }
+ buf[k] = j44(a, b);
ph = 1 - ph;
}
w0(0); w2(4);
break;
- case 1: w0(0x47); w2(1); w2(5); w0(0xff);
+ case 1:
+ w0(0x47); w2(1); w2(5); w0(0xff);
ph = 0;
- for(k=0;k<count;k++) {
- if (k == count-1) w0(0xfd);
- w2(4+ph);
+ for (k = 0; k < count; k++) {
+ if (k == count - 1)
+ w0(0xfd);
+ w2(4 + ph);
a = r1(); b = r2();
- buf[k] = j53(a,b);
+ buf[k] = j53(a, b);
ph = 1 - ph;
}
w0(0); w2(4);
break;
- case 2: w0(0x27); w2(1); w2(0x25); w0(0);
+ case 2:
+ w0(0x27); w2(1); w2(0x25); w0(0);
ph = 0;
- for(k=0;k<count-1;k++) {
- w2(0x24+ph);
+ for (k = 0; k < count - 1; k++) {
+ w2(0x24 + ph);
buf[k] = r0();
ph = 1 - ph;
}
- w2(0x26); w2(0x27); buf[count-1] = r0();
+ w2(0x26); w2(0x27);
+ buf[count - 1] = r0();
w2(0x25); w2(4);
break;
- case 3: w3(0x80); w2(0x24);
- for(k=0;k<count-1;k++) buf[k] = r4();
- w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
+ case 3:
+ w3(0x80); w2(0x24);
+ for (k = 0; k < count - 1; k++)
+ buf[k] = r4();
+ w2(4); w3(0xa0); w2(0x24);
+ buf[count - 1] = r4();
w2(4);
break;
- case 4: w3(0x80); w2(0x24);
- for(k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
- buf[count-2] = r4();
- w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
+ case 4:
+ w3(0x80); w2(0x24);
+ for (k = 0; k < count / 2 - 1; k++)
+ ((u16 *)buf)[k] = r4w();
+ buf[count - 2] = r4();
+ w2(4); w3(0xa0); w2(0x24);
+ buf[count - 1] = r4();
w2(4);
break;
- case 5: w3(0x80); w2(0x24);
- for(k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
- for(k=count-4;k<count-1;k++) buf[k] = r4();
- w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
+ case 5:
+ w3(0x80); w2(0x24);
+ for (k = 0; k < count / 4 - 1; k++)
+ ((u32 *)buf)[k] = r4l();
+ for (k = count - 4; k < count - 1; k++)
+ buf[k] = r4();
+ w2(4); w3(0xa0); w2(0x24);
+ buf[count - 1] = r4();
w2(4);
break;
-
}
}
static void epat_write_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int ph, k;
+{
+ int ph, k;
switch (pi->mode) {
-
case 0:
case 1:
- case 2: w0(0x67); w2(1); w2(5);
+ case 2:
+ w0(0x67); w2(1); w2(5);
ph = 0;
- for(k=0;k<count;k++) {
+ for (k = 0; k < count; k++) {
w0(buf[k]);
- w2(4+ph);
+ w2(4 + ph);
ph = 1 - ph;
}
w2(7); w2(4);
break;
-
- case 3: w3(0xc0);
- for(k=0;k<count;k++) w4(buf[k]);
+ case 3:
+ w3(0xc0);
+ for (k = 0; k < count; k++)
+ w4(buf[k]);
w2(4);
break;
-
- case 4: w3(0xc0);
- for(k=0;k<(count/2);k++) w4w(((u16 *)buf)[k]);
+ case 4:
+ w3(0xc0);
+ for (k = 0; k < count / 2; k++)
+ w4w(((u16 *)buf)[k]);
w2(4);
break;
-
- case 5: w3(0xc0);
- for(k=0;k<(count/4);k++) w4l(((u32 *)buf)[k]);
+ case 5:
+ w3(0xc0);
+ for (k = 0; k < count / 4; k++)
+ w4l(((u32 *)buf)[k]);
w2(4);
break;
-
}
}
/* these macros access the EPAT registers in native addressing */
-#define WR(r,v) epat_write_regr(pi,2,r,v)
-#define RR(r) (epat_read_regr(pi,2,r))
+#define WR(r, v) epat_write_regr(pi, 2, r, v)
+#define RR(r) epat_read_regr(pi, 2, r)
/* and these access the IDE task file */
-#define WRi(r,v) epat_write_regr(pi,0,r,v)
-#define RRi(r) (epat_read_regr(pi,0,r))
+#define WRi(r, v) epat_write_regr(pi, 0, r, v)
+#define RRi(r) epat_read_regr(pi, 0, r)
/* FIXME: the CPP stuff should be fixed to handle multiple EPATs on a chain */
-#define CPP(x) w2(4);w0(0x22);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
- w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
+#define CPP(x) \
+ do { \
+ w2(4); w0(0x22); w0(0xaa); \
+ w0(0x55); w0(0); w0(0xff); \
+ w0(0x87); w0(0x78); w0(x); \
+ w2(4); w2(5); w2(4); w0(0xff); \
+ } while (0)
static void epat_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
/* Initialize the chip */
CPP(0);
if (epatc8) {
- CPP(0x40);CPP(0xe0);
- w0(0);w2(1);w2(4);
- WR(0x8,0x12);WR(0xc,0x14);WR(0x12,0x10);
- WR(0xe,0xf);WR(0xf,4);
+ CPP(0x40); CPP(0xe0);
+ w0(0); w2(1); w2(4);
+ WR(0x8, 0x12);
+ WR(0xc, 0x14);
+ WR(0x12, 0x10);
+ WR(0xe, 0xf);
+ WR(0xf, 4);
/* WR(0xe,0xa);WR(0xf,4); */
- WR(0xe,0xd);WR(0xf,0);
+ WR(0xe, 0xd);
+ WR(0xf, 0);
/* CPP(0x30); */
}
/* Connect to the chip */
CPP(0xe0);
- w0(0);w2(1);w2(4); /* Idle into SPP */
+ w0(0); w2(1); w2(4); /* Idle into SPP */
if (pi->mode >= 3) {
- w0(0);w2(1);w2(4);w2(0xc);
- /* Request EPP */
- w0(0x40);w2(6);w2(7);w2(4);w2(0xc);w2(4);
+ w0(0); w2(1); w2(4); w2(0xc);
+ /* Request EPP */
+ w0(0x40); w2(6); w2(7); w2(4); w2(0xc); w2(4);
}
if (!epatc8) {
- WR(8,0x10); WR(0xc,0x14); WR(0xa,0x38); WR(0x12,0x10);
+ WR(8, 0x10);
+ WR(0xc, 0x14);
+ WR(0xa, 0x38);
+ WR(0x12, 0x10);
}
}
static void epat_disconnect(struct pi_adapter *pi)
-{ CPP(0x30);
+{
+ CPP(0x30);
w0(pi->saved_r0);
w2(pi->saved_r2);
}
static int epat_test_proto(struct pi_adapter *pi)
-
-{ int k, j, f, cc;
- int e[2] = {0,0};
+{
+ int k, j, f, cc;
+ int e[2] = { 0, 0 };
char scratch[512];
- epat_connect(pi);
+ epat_connect(pi);
cc = RR(0xd);
epat_disconnect(pi);
epat_connect(pi);
for (j=0;j<2;j++) {
- WRi(6,0xa0+j*0x10);
- for (k=0;k<256;k++) {
- WRi(2,k^0xaa);
- WRi(3,k^0x55);
- if (RRi(2) != (k^0xaa)) e[j]++;
- }
- }
- epat_disconnect(pi);
-
- f = 0;
- epat_connect(pi);
- WR(0x13,1); WR(0x13,0); WR(0xa,0x11);
- epat_read_block(pi,scratch,512);
-
- for (k=0;k<256;k++) {
- if ((scratch[2*k] & 0xff) != k) f++;
- if ((scratch[2*k+1] & 0xff) != (0xff-k)) f++;
- }
- epat_disconnect(pi);
+ WRi(6, 0xa0 + j * 0x10);
+ for (k = 0; k < 256; k++) {
+ WRi(2, k ^ 0xaa);
+ WRi(3, k ^ 0x55);
+ if (RRi(2) != (k ^ 0xaa))
+ e[j]++;
+ }
+ }
+ epat_disconnect(pi);
- dev_dbg(&pi->dev, "epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)\n",
- pi->port, pi->mode, cc, e[0], e[1], f);
-
- return (e[0] && e[1]) || f;
+ f = 0;
+ epat_connect(pi);
+ WR(0x13, 1); WR(0x13, 0); WR(0xa, 0x11);
+ epat_read_block(pi, scratch, 512);
+
+ for (k = 0; k < 256; k++) {
+ if ((scratch[2 * k] & 0xff) != k)
+ f++;
+ if ((scratch[2 * k + 1] & 0xff) != 0xff - k)
+ f++;
+ }
+ epat_disconnect(pi);
+
+ dev_dbg(&pi->dev,
+ "epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)\n",
+ pi->port, pi->mode, cc, e[0], e[1], f);
+
+ return (e[0] && e[1]) || f;
}
static void epat_log_adapter(struct pi_adapter *pi)
-
-{ int ver;
- char *mode_string[6] =
- {"4-bit","5/3","8-bit","EPP-8","EPP-16","EPP-32"};
+{
+ int ver;
+ char *mode_string[6] =
+ { "4-bit", "5/3", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
epat_connect(pi);
- WR(0xa,0x38); /* read the version code */
- ver = RR(0xb);
- epat_disconnect(pi);
+ WR(0xa, 0x38); /* read the version code */
+ ver = RR(0xb);
+ epat_disconnect(pi);
- dev_info(&pi->dev, "Shuttle EPAT chip %x at 0x%x, mode %d (%s), delay %d\n",
+ dev_info(&pi->dev,
+ "Shuttle EPAT chip %x at 0x%x, mode %d (%s), delay %d\n",
ver, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
}
diff --git a/drivers/ata/pata_parport/epia.c b/drivers/ata/pata_parport/epia.c
index f6db2f79fe99..920e9f40d401 100644
--- a/drivers/ata/pata_parport/epia.c
+++ b/drivers/ata/pata_parport/epia.c
@@ -1,14 +1,13 @@
-/*
- epia.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- epia.c is a low-level protocol driver for Shuttle Technologies
- EPIA parallel to IDE adapter chip. This device is now obsolete
- and has been replaced with the EPAT chip, which is supported
- by epat.c, however, some devices based on EPIA are still
- available.
-
-*/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1997-1998 Grant R. Guenther <grant@torque.net>
+ *
+ * epia.c is a low-level protocol driver for Shuttle Technologies
+ * EPIA parallel to IDE adapter chip. This device is now obsolete
+ * and has been replaced with the EPAT chip, which is supported
+ * by epat.c, however, some devices based on EPIA are still
+ * available.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -19,255 +18,274 @@
#include <asm/io.h>
#include "pata_parport.h"
-/* mode codes: 0 nybble reads on port 1, 8-bit writes
- 1 5/3 reads on ports 1 & 2, 8-bit writes
- 2 8-bit reads and writes
- 3 8-bit EPP mode
- 4 16-bit EPP
- 5 32-bit EPP
-*/
-
-#define j44(a,b) (((a>>4)&0x0f)+(b&0xf0))
-#define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0))
-
-/* cont = 0 IDE register file
- cont = 1 IDE control registers
-*/
-
+/*
+ * mode codes: 0 nybble reads on port 1, 8-bit writes
+ * 1 5/3 reads on ports 1 & 2, 8-bit writes
+ * 2 8-bit reads and writes
+ * 3 8-bit EPP mode
+ * 4 16-bit EPP
+ * 5 32-bit EPP
+ */
+
+#define j44(a, b) (((a >> 4) & 0x0f) + (b & 0xf0))
+#define j53(a, b) (((a >> 3) & 0x1f) + ((b << 4) & 0xe0))
+
+/*
+ * cont = 0 IDE register file
+ * cont = 1 IDE control registers
+ */
static int cont_map[2] = { 0, 0x80 };
static int epia_read_regr(struct pi_adapter *pi, int cont, int regr)
-
-{ int a, b, r;
+{
+ int a, b, r;
regr += cont_map[cont];
- switch (pi->mode) {
-
- case 0: r = regr^0x39;
- w0(r); w2(1); w2(3); w0(r);
- a = r1(); w2(1); b = r1(); w2(4);
- return j44(a,b);
-
- case 1: r = regr^0x31;
- w0(r); w2(1); w0(r&0x37);
- w2(3); w2(5); w0(r|0xf0);
- a = r1(); b = r2(); w2(4);
- return j53(a,b);
-
- case 2: r = regr^0x29;
- w0(r); w2(1); w2(0X21); w2(0x23);
- a = r0(); w2(4);
- return a;
-
+ switch (pi->mode) {
+ case 0:
+ r = regr ^ 0x39;
+ w0(r); w2(1); w2(3); w0(r);
+ a = r1(); w2(1); b = r1(); w2(4);
+ return j44(a, b);
+ case 1:
+ r = regr ^ 0x31;
+ w0(r); w2(1); w0(r & 0x37);
+ w2(3); w2(5); w0(r | 0xf0);
+ a = r1(); b = r2(); w2(4);
+ return j53(a, b);
+ case 2:
+ r = regr^0x29;
+ w0(r); w2(1); w2(0X21); w2(0x23);
+ a = r0(); w2(4);
+ return a;
case 3:
case 4:
- case 5: w3(regr); w2(0x24); a = r4(); w2(4);
- return a;
+ case 5:
+ w3(regr); w2(0x24); a = r4(); w2(4);
+ return a;
+ }
- }
- return -1;
-}
+ return -1;
+}
static void epia_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
-
-{ int r;
+{
+ int r;
regr += cont_map[cont];
- switch (pi->mode) {
-
- case 0:
- case 1:
- case 2: r = regr^0x19;
- w0(r); w2(1); w0(val); w2(3); w2(4);
- break;
-
+ switch (pi->mode) {
+ case 0:
+ case 1:
+ case 2:
+ r = regr ^ 0x19;
+ w0(r); w2(1); w0(val); w2(3); w2(4);
+ break;
case 3:
case 4:
- case 5: r = regr^0x40;
- w3(r); w4(val); w2(4);
- break;
- }
+ case 5:
+ r = regr ^ 0x40;
+ w3(r); w4(val); w2(4);
+ break;
+ }
}
-#define WR(r,v) epia_write_regr(pi,0,r,v)
-#define RR(r) (epia_read_regr(pi,0,r))
-
-/* The use of register 0x84 is entirely unclear - it seems to control
- some EPP counters ... currently we know about 3 different block
- sizes: the standard 512 byte reads and writes, 12 byte writes and
- 2048 byte reads (the last two being used in the CDrom drivers.
-*/
+#define WR(r, v) epia_write_regr(pi, 0, r, v)
+#define RR(r) epia_read_regr(pi, 0, r)
+/*
+ * The use of register 0x84 is entirely unclear - it seems to control
+ * some EPP counters ... currently we know about 3 different block
+ * sizes: the standard 512 byte reads and writes, 12 byte writes and
+ * 2048 byte reads (the last two being used in the CDrom drivers.
+ */
static void epia_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
-
- w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0);
- w2(1); w2(4);
- if (pi->mode >= 3) {
- w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4);
- w2(0x24); w2(0x26); w2(4);
- }
- WR(0x86,8);
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+
+ w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0);
+ w2(1); w2(4);
+ if (pi->mode >= 3) {
+ w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4);
+ w2(0x24); w2(0x26); w2(4);
+ }
+ WR(0x86, 8);
}
static void epia_disconnect(struct pi_adapter *pi)
-
-{ /* WR(0x84,0x10); */
- w0(pi->saved_r0);
- w2(1); w2(4);
- w0(pi->saved_r0);
- w2(pi->saved_r2);
-}
+{
+ /* WR(0x84,0x10); */
+ w0(pi->saved_r0);
+ w2(1); w2(4);
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
+}
static void epia_read_block(struct pi_adapter *pi, char *buf, int count)
-{ int k, ph, a, b;
-
- switch (pi->mode) {
-
- case 0: w0(0x81); w2(1); w2(3); w0(0xc1);
- ph = 1;
- for (k=0;k<count;k++) {
- w2(2+ph); a = r1();
- w2(4+ph); b = r1();
- buf[k] = j44(a,b);
- ph = 1 - ph;
- }
- w0(0); w2(4);
- break;
-
- case 1: w0(0x91); w2(1); w0(0x10); w2(3);
- w0(0x51); w2(5); w0(0xd1);
- ph = 1;
- for (k=0;k<count;k++) {
- w2(4+ph);
- a = r1(); b = r2();
- buf[k] = j53(a,b);
- ph = 1 - ph;
- }
- w0(0); w2(4);
- break;
-
- case 2: w0(0x89); w2(1); w2(0x23); w2(0x21);
- ph = 1;
- for (k=0;k<count;k++) {
- w2(0x24+ph);
- buf[k] = r0();
- ph = 1 - ph;
- }
- w2(6); w2(4);
- break;
-
- case 3: if (count > 512) WR(0x84,3);
+{
+ int k, ph, a, b;
+
+ switch (pi->mode) {
+ case 0:
+ w0(0x81); w2(1); w2(3); w0(0xc1);
+ ph = 1;
+ for (k = 0; k < count; k++) {
+ w2(2+ph); a = r1();
+ w2(4+ph); b = r1();
+ buf[k] = j44(a, b);
+ ph = 1 - ph;
+ }
+ w0(0); w2(4);
+ break;
+ case 1:
+ w0(0x91); w2(1); w0(0x10); w2(3);
+ w0(0x51); w2(5); w0(0xd1);
+ ph = 1;
+ for (k = 0; k < count; k++) {
+ w2(4 + ph);
+ a = r1(); b = r2();
+ buf[k] = j53(a, b);
+ ph = 1 - ph;
+ }
+ w0(0); w2(4);
+ break;
+ case 2:
+ w0(0x89); w2(1); w2(0x23); w2(0x21);
+ ph = 1;
+ for (k = 0; k < count; k++) {
+ w2(0x24 + ph);
+ buf[k] = r0();
+ ph = 1 - ph;
+ }
+ w2(6); w2(4);
+ break;
+ case 3:
+ if (count > 512)
+ WR(0x84, 3);
w3(0); w2(0x24);
- for (k=0;k<count;k++) buf[k] = r4();
- w2(4); WR(0x84,0);
- break;
-
- case 4: if (count > 512) WR(0x84,3);
+ for (k = 0; k < count; k++)
+ buf[k] = r4();
+ w2(4); WR(0x84, 0);
+ break;
+ case 4:
+ if (count > 512)
+ WR(0x84, 3);
w3(0); w2(0x24);
- for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
- w2(4); WR(0x84,0);
- break;
-
- case 5: if (count > 512) WR(0x84,3);
+ for (k = 0; k < count / 2; k++)
+ ((u16 *)buf)[k] = r4w();
+ w2(4); WR(0x84, 0);
+ break;
+ case 5:
+ if (count > 512)
+ WR(0x84, 3);
w3(0); w2(0x24);
- for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
- w2(4); WR(0x84,0);
- break;
-
- }
+ for (k = 0; k < count / 4; k++)
+ ((u32 *)buf)[k] = r4l();
+ w2(4); WR(0x84, 0);
+ break;
+ }
}
static void epia_write_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int ph, k, last, d;
-
- switch (pi->mode) {
-
- case 0:
- case 1:
- case 2: w0(0xa1); w2(1); w2(3); w2(1); w2(5);
- ph = 0; last = 0x8000;
- for (k=0;k<count;k++) {
- d = buf[k];
- if (d != last) { last = d; w0(d); }
- w2(4+ph);
- ph = 1 - ph;
- }
- w2(7); w2(4);
- break;
-
- case 3: if (count < 512) WR(0x84,1);
+{
+ int ph, k, last, d;
+
+ switch (pi->mode) {
+ case 0:
+ case 1:
+ case 2:
+ w0(0xa1); w2(1); w2(3); w2(1); w2(5);
+ ph = 0; last = 0x8000;
+ for (k = 0; k < count; k++) {
+ d = buf[k];
+ if (d != last) {
+ last = d;
+ w0(d);
+ }
+ w2(4 + ph);
+ ph = 1 - ph;
+ }
+ w2(7); w2(4);
+ break;
+ case 3:
+ if (count < 512)
+ WR(0x84, 1);
w3(0x40);
- for (k=0;k<count;k++) w4(buf[k]);
- if (count < 512) WR(0x84,0);
- break;
-
- case 4: if (count < 512) WR(0x84,1);
+ for (k = 0; k < count; k++)
+ w4(buf[k]);
+ if (count < 512)
+ WR(0x84, 0);
+ break;
+ case 4:
+ if (count < 512)
+ WR(0x84, 1);
w3(0x40);
- for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
- if (count < 512) WR(0x84,0);
- break;
-
- case 5: if (count < 512) WR(0x84,1);
+ for (k = 0; k < count / 2; k++)
+ w4w(((u16 *)buf)[k]);
+ if (count < 512)
+ WR(0x84, 0);
+ break;
+ case 5:
+ if (count < 512)
+ WR(0x84, 1);
w3(0x40);
- for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
- if (count < 512) WR(0x84,0);
- break;
-
- }
-
+ for (k = 0; k < count / 4; k++)
+ w4l(((u32 *)buf)[k]);
+ if (count < 512)
+ WR(0x84, 0);
+ break;
+ }
}
static int epia_test_proto(struct pi_adapter *pi)
-
-{ int j, k, f;
- int e[2] = {0,0};
+{
+ int j, k, f;
+ int e[2] = { 0, 0 };
char scratch[512];
- epia_connect(pi);
- for (j=0;j<2;j++) {
- WR(6,0xa0+j*0x10);
- for (k=0;k<256;k++) {
- WR(2,k^0xaa);
- WR(3,k^0x55);
- if (RR(2) != (k^0xaa)) e[j]++;
- }
- WR(2,1); WR(3,1);
- }
- epia_disconnect(pi);
-
- f = 0;
- epia_connect(pi);
- WR(0x84,8);
- epia_read_block(pi,scratch,512);
- for (k=0;k<256;k++) {
- if ((scratch[2*k] & 0xff) != ((k+1) & 0xff)) f++;
- if ((scratch[2*k+1] & 0xff) != ((-2-k) & 0xff)) f++;
- }
- WR(0x84,0);
- epia_disconnect(pi);
+ epia_connect(pi);
+ for (j = 0; j < 2; j++) {
+ WR(6, 0xa0 + j * 0x10);
+ for (k = 0; k < 256; k++) {
+ WR(2, k ^ 0xaa);
+ WR(3, k ^ 0x55);
+ if (RR(2) != (k ^ 0xaa))
+ e[j]++;
+ }
+ WR(2, 1); WR(3, 1);
+ }
+ epia_disconnect(pi);
+
+ f = 0;
+ epia_connect(pi);
+ WR(0x84, 8);
+ epia_read_block(pi, scratch, 512);
+ for (k = 0; k < 256; k++) {
+ if ((scratch[2 * k] & 0xff) != ((k + 1) & 0xff))
+ f++;
+ if ((scratch[2 * k + 1] & 0xff) != ((-2 - k) & 0xff))
+ f++;
+ }
+ WR(0x84, 0);
+ epia_disconnect(pi);
dev_dbg(&pi->dev, "epia: port 0x%x, mode %d, test=(%d,%d,%d)\n",
- pi->port, pi->mode, e[0], e[1], f);
-
- return (e[0] && e[1]) || f;
+ pi->port, pi->mode, e[0], e[1], f);
+ return (e[0] && e[1]) || f;
}
static void epia_log_adapter(struct pi_adapter *pi)
+{
+ char *mode[6] = { "4-bit", "5/3", "8-bit", "EPP-8", "EPP-16", "EPP-32"};
-{ char *mode_string[6] = {"4-bit","5/3","8-bit",
- "EPP-8","EPP-16","EPP-32"};
-
- dev_info(&pi->dev, "Shuttle EPIA at 0x%x, mode %d (%s), delay %d\n",
- pi->port, pi->mode, mode_string[pi->mode], pi->delay);
+ dev_info(&pi->dev,
+ "Shuttle EPIA at 0x%x, mode %d (%s), delay %d\n",
+ pi->port, pi->mode, mode[pi->mode], pi->delay);
}
static struct pi_protocol epia = {
diff --git a/drivers/ata/pata_parport/fit2.c b/drivers/ata/pata_parport/fit2.c
index fd3b2ce426a5..6524f3033b1e 100644
--- a/drivers/ata/pata_parport/fit2.c
+++ b/drivers/ata/pata_parport/fit2.c
@@ -1,17 +1,16 @@
-/*
- fit2.c (c) 1998 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- fit2.c is a low-level protocol driver for the older version
- of the Fidelity International Technology parallel port adapter.
- This adapter is used in their TransDisk 2000 and older TransDisk
- 3000 portable hard-drives. As far as I can tell, this device
- supports 4-bit mode _only_.
-
- Newer models of the FIT products use an enhanced protocol.
- The "fit3" protocol module should support current drives.
-
-*/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1998 Grant R. Guenther <grant@torque.net>
+ *
+ * fit2.c is a low-level protocol driver for the older version
+ * of the Fidelity International Technology parallel port adapter.
+ * This adapter is used in their TransDisk 2000 and older TransDisk
+ * 3000 portable hard-drives. As far as I can tell, this device
+ * supports 4-bit mode _only_.
+ *
+ * Newer models of the FIT products use an enhanced protocol.
+ * The "fit3" protocol module should support current drives.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -22,99 +21,97 @@
#include <asm/io.h>
#include "pata_parport.h"
-#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0))
-
-/* cont = 0 - access the IDE register file
- cont = 1 - access the IDE command set
+#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0))
-NB: The FIT adapter does not appear to use the control registers.
-So, we map ALT_STATUS to STATUS and NO-OP writes to the device
-control register - this means that IDE reset will not work on these
-devices.
-
-*/
+/*
+ * cont = 0 - access the IDE register file
+ * cont = 1 - access the IDE command set
+ *
+ * NB: The FIT adapter does not appear to use the control registers.
+ * So, we map ALT_STATUS to STATUS and NO-OP writes to the device
+ * control register - this means that IDE reset will not work on these
+ * devices.
+ */
static void fit2_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
-
-{ if (cont == 1) return;
+{
+ if (cont == 1)
+ return;
w2(0xc); w0(regr); w2(4); w0(val); w2(5); w0(0); w2(4);
}
static int fit2_read_regr(struct pi_adapter *pi, int cont, int regr)
-
-{ int a, b, r;
+{
+ int a, b, r;
if (cont) {
- if (regr != 6) return 0xff;
- r = 7;
- } else r = regr + 0x10;
+ if (regr != 6)
+ return 0xff;
+ r = 7;
+ } else {
+ r = regr + 0x10;
+ }
- w2(0xc); w0(r); w2(4); w2(5);
- w0(0); a = r1();
- w0(1); b = r1();
+ w2(0xc); w0(r); w2(4); w2(5);
+ w0(0); a = r1();
+ w0(1); b = r1();
w2(4);
- return j44(a,b);
-
+ return j44(a, b);
}
static void fit2_read_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int k, a, b, c, d;
+{
+ int k, a, b, c, d;
w2(0xc); w0(0x10);
- for (k=0;k<count/4;k++) {
-
+ for (k = 0; k < count / 4; k++) {
w2(4); w2(5);
w0(0); a = r1(); w0(1); b = r1();
- w0(3); c = r1(); w0(2); d = r1();
- buf[4*k+0] = j44(a,b);
- buf[4*k+1] = j44(d,c);
-
- w2(4); w2(5);
- a = r1(); w0(3); b = r1();
- w0(1); c = r1(); w0(0); d = r1();
- buf[4*k+2] = j44(d,c);
- buf[4*k+3] = j44(a,b);
+ w0(3); c = r1(); w0(2); d = r1();
+ buf[4 * k + 0] = j44(a, b);
+ buf[4 * k + 1] = j44(d, c);
+ w2(4); w2(5);
+ a = r1(); w0(3); b = r1();
+ w0(1); c = r1(); w0(0); d = r1();
+ buf[4 * k + 2] = j44(d, c);
+ buf[4 * k + 3] = j44(a, b);
}
w2(4);
-
}
static void fit2_write_block(struct pi_adapter *pi, char *buf, int count)
+{
+ int k;
-{ int k;
-
-
- w2(0xc); w0(0);
- for (k=0;k<count/2;k++) {
- w2(4); w0(buf[2*k]);
- w2(5); w0(buf[2*k+1]);
+ w2(0xc); w0(0);
+ for (k = 0; k < count / 2; k++) {
+ w2(4); w0(buf[2 * k]);
+ w2(5); w0(buf[2 * k + 1]);
}
w2(4);
}
static void fit2_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
- w2(0xcc);
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+ w2(0xcc);
}
static void fit2_disconnect(struct pi_adapter *pi)
-
-{ w0(pi->saved_r0);
- w2(pi->saved_r2);
-}
+{
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
+}
static void fit2_log_adapter(struct pi_adapter *pi)
-
{
dev_info(&pi->dev, "FIT 2000 adapter at 0x%x, delay %d\n",
- pi->port, pi->delay);
+ pi->port, pi->delay);
}
diff --git a/drivers/ata/pata_parport/fit3.c b/drivers/ata/pata_parport/fit3.c
index 75df656ac472..c172a38ae67d 100644
--- a/drivers/ata/pata_parport/fit3.c
+++ b/drivers/ata/pata_parport/fit3.c
@@ -1,21 +1,20 @@
-/*
- fit3.c (c) 1998 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- fit3.c is a low-level protocol driver for newer models
- of the Fidelity International Technology parallel port adapter.
- This adapter is used in their TransDisk 3000 portable
- hard-drives, as well as CD-ROM, PD-CD and other devices.
-
- The TD-2000 and certain older devices use a different protocol.
- Try the fit2 protocol module with them.
-
- NB: The FIT adapters do not appear to support the control
- registers. So, we map ALT_STATUS to STATUS and NO-OP writes
- to the device control register - this means that IDE reset
- will not work on these devices.
-
-*/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1998 Grant R. Guenther <grant@torque.net>
+ *
+ * fit3.c is a low-level protocol driver for newer models
+ * of the Fidelity International Technology parallel port adapter.
+ * This adapter is used in their TransDisk 3000 portable
+ * hard-drives, as well as CD-ROM, PD-CD and other devices.
+ *
+ * The TD-2000 and certain older devices use a different protocol.
+ * Try the fit2 protocol module with them.
+ *
+ * NB: The FIT adapters do not appear to support the control
+ * registers. So, we map ALT_STATUS to STATUS and NO-OP writes
+ * to the device control register - this means that IDE reset
+ * will not work on these devices.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -26,152 +25,155 @@
#include <asm/io.h>
#include "pata_parport.h"
-#define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0))
-
-#define w7(byte) {out_p(7,byte);}
-#define r7() (in_p(7) & 0xff)
+#define j44(a, b) (((a >> 3) & 0x0f) | ((b << 1) & 0xf0))
-/* cont = 0 - access the IDE register file
- cont = 1 - access the IDE command set
+#define w7(byte) out_p(7, byte)
+#define r7() (in_p(7) & 0xff)
-*/
+/*
+ * cont = 0 - access the IDE register file
+ * cont = 1 - access the IDE command set
+ */
static void fit3_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
-
-{ if (cont == 1) return;
+{
+ if (cont == 1)
+ return;
switch (pi->mode) {
-
case 0:
- case 1: w2(0xc); w0(regr); w2(0x8); w2(0xc);
- w0(val); w2(0xd);
+ case 1:
+ w2(0xc); w0(regr); w2(0x8); w2(0xc);
+ w0(val); w2(0xd);
w0(0); w2(0xc);
break;
-
- case 2: w2(0xc); w0(regr); w2(0x8); w2(0xc);
+ case 2:
+ w2(0xc); w0(regr); w2(0x8); w2(0xc);
w4(val); w4(0);
w2(0xc);
break;
-
}
}
static int fit3_read_regr(struct pi_adapter *pi, int cont, int regr)
-
-{ int a, b;
+{
+ int a, b;
if (cont) {
- if (regr != 6) return 0xff;
- regr = 7;
- }
+ if (regr != 6)
+ return 0xff;
+ regr = 7;
+ }
switch (pi->mode) {
-
- case 0: w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc);
+ case 0:
+ w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc);
w2(0xd); a = r1();
- w2(0xf); b = r1();
+ w2(0xf); b = r1();
w2(0xc);
- return j44(a,b);
-
- case 1: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
- w2(0xec); w2(0xee); w2(0xef); a = r0();
+ return j44(a, b);
+ case 1:
+ w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
+ w2(0xec); w2(0xee); w2(0xef); a = r0();
w2(0xc);
return a;
-
- case 2: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
- w2(0xec);
- a = r4(); b = r4();
+ case 2:
+ w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
+ w2(0xec);
+ a = r4(); b = r4();
w2(0xc);
return a;
-
}
- return -1;
+ return -1;
}
static void fit3_read_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int k, a, b, c, d;
+{
+ int k, a, b, c, d;
switch (pi->mode) {
-
- case 0: w2(0xc); w0(0x10); w2(0x8); w2(0xc);
- for (k=0;k<count/2;k++) {
- w2(0xd); a = r1();
- w2(0xf); b = r1();
- w2(0xc); c = r1();
- w2(0xe); d = r1();
- buf[2*k ] = j44(a,b);
- buf[2*k+1] = j44(c,d);
+ case 0:
+ w2(0xc); w0(0x10); w2(0x8); w2(0xc);
+ for (k = 0; k < count / 2; k++) {
+ w2(0xd); a = r1();
+ w2(0xf); b = r1();
+ w2(0xc); c = r1();
+ w2(0xe); d = r1();
+ buf[2 * k] = j44(a, b);
+ buf[2 * k + 1] = j44(c, d);
}
w2(0xc);
break;
-
- case 1: w2(0xc); w0(0x90); w2(0x8); w2(0xc);
+ case 1:
+ w2(0xc); w0(0x90); w2(0x8); w2(0xc);
w2(0xec); w2(0xee);
- for (k=0;k<count/2;k++) {
- w2(0xef); a = r0();
- w2(0xee); b = r0();
- buf[2*k ] = a;
- buf[2*k+1] = b;
+ for (k = 0; k < count / 2; k++) {
+ w2(0xef); a = r0();
+ w2(0xee); b = r0();
+ buf[2 * k] = a;
+ buf[2 * k + 1] = b;
}
- w2(0xec);
+ w2(0xec);
w2(0xc);
break;
-
- case 2: w2(0xc); w0(0x90); w2(0x8); w2(0xc);
- w2(0xec);
- for (k=0;k<count;k++) buf[k] = r4();
- w2(0xc);
+ case 2:
+ w2(0xc); w0(0x90); w2(0x8); w2(0xc);
+ w2(0xec);
+ for (k = 0; k < count; k++)
+ buf[k] = r4();
+ w2(0xc);
break;
-
}
}
static void fit3_write_block(struct pi_adapter *pi, char *buf, int count)
+{
+ int k;
-{ int k;
-
- switch (pi->mode) {
-
+ switch (pi->mode) {
case 0:
- case 1: w2(0xc); w0(0); w2(0x8); w2(0xc);
- for (k=0;k<count/2;k++) {
- w0(buf[2*k ]); w2(0xd);
- w0(buf[2*k+1]); w2(0xc);
+ case 1:
+ w2(0xc); w0(0); w2(0x8); w2(0xc);
+ for (k = 0; k < count / 2; k++) {
+ w0(buf[2 * k]); w2(0xd);
+ w0(buf[2 * k + 1]); w2(0xc);
}
break;
-
- case 2: w2(0xc); w0(0); w2(0x8); w2(0xc);
- for (k=0;k<count;k++) w4(buf[k]);
- w2(0xc);
+ case 2:
+ w2(0xc); w0(0); w2(0x8); w2(0xc);
+ for (k = 0; k < count; k++)
+ w4(buf[k]);
+ w2(0xc);
break;
}
}
static void fit3_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
w2(0xc); w0(0); w2(0xa);
- if (pi->mode == 2) {
- w2(0xc); w0(0x9); w2(0x8); w2(0xc);
- }
+ if (pi->mode == 2) {
+ w2(0xc); w0(0x9);
+ w2(0x8); w2(0xc);
+ }
}
static void fit3_disconnect(struct pi_adapter *pi)
-
-{ w2(0xc); w0(0xa); w2(0x8); w2(0xc);
+{
+ w2(0xc); w0(0xa); w2(0x8); w2(0xc);
w0(pi->saved_r0);
- w2(pi->saved_r2);
-}
+ w2(pi->saved_r2);
+}
static void fit3_log_adapter(struct pi_adapter *pi)
+{
+ char *mode_string[3] = { "4-bit", "8-bit", "EPP"};
-{ char *mode_string[3] = {"4-bit","8-bit","EPP"};
-
- dev_info(&pi->dev, "FIT 3000 adapter at 0x%x, mode %d (%s), delay %d\n",
- pi->port, pi->mode, mode_string[pi->mode], pi->delay);
+ dev_info(&pi->dev,
+ "FIT 3000 adapter at 0x%x, mode %d (%s), delay %d\n",
+ pi->port, pi->mode, mode_string[pi->mode], pi->delay);
}
static struct pi_protocol fit3 = {
diff --git a/drivers/ata/pata_parport/friq.c b/drivers/ata/pata_parport/friq.c
index 1647264cd9a8..dc428f54fe0c 100644
--- a/drivers/ata/pata_parport/friq.c
+++ b/drivers/ata/pata_parport/friq.c
@@ -1,24 +1,23 @@
-/*
- friq.c (c) 1998 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License
-
- friq.c is a low-level protocol driver for the Freecom "IQ"
- parallel port IDE adapter. Early versions of this adapter
- use the 'frpw' protocol.
-
- Freecom uses this adapter in a battery powered external
- CD-ROM drive. It is also used in LS-120 drives by
- Maxell and Panasonic, and other devices.
-
- The battery powered drive requires software support to
- control the power to the drive. This module enables the
- drive power when the high level driver (pcd) is loaded
- and disables it when the module is unloaded. Note, if
- the friq module is built in to the kernel, the power
- will never be switched off, so other means should be
- used to conserve battery power.
-
-*/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1998 Grant R. Guenther <grant@torque.net>
+ *
+ * friq.c is a low-level protocol driver for the Freecom "IQ"
+ * parallel port IDE adapter. Early versions of this adapter
+ * use the 'frpw' protocol.
+ *
+ * Freecom uses this adapter in a battery powered external
+ * CD-ROM drive. It is also used in LS-120 drives by
+ * Maxell and Panasonic, and other devices.
+ *
+ * The battery powered drive requires software support to
+ * control the power to the drive. This module enables the
+ * drive power when the high level driver (pcd) is loaded
+ * and disables it when the module is unloaded. Note, if
+ * the friq module is built in to the kernel, the power
+ * will never be switched off, so other means should be
+ * used to conserve battery power.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -29,197 +28,206 @@
#include <asm/io.h>
#include "pata_parport.h"
-#define CMD(x) w2(4);w0(0xff);w0(0xff);w0(0x73);w0(0x73);\
- w0(0xc9);w0(0xc9);w0(0x26);w0(0x26);w0(x);w0(x);
+#define CMD(x) \
+ do { \
+ w2(4); w0(0xff); w0(0xff); w0(0x73); w0(0x73); \
+ w0(0xc9); w0(0xc9); w0(0x26); \
+ w0(0x26); w0(x); w0(x); \
+ } while (0)
-#define j44(l,h) (((l>>4)&0x0f)|(h&0xf0))
+#define j44(l, h) (((l >> 4) & 0x0f) | (h & 0xf0))
-/* cont = 0 - access the IDE register file
- cont = 1 - access the IDE command set
-*/
-
-static int cont_map[2] = { 0x08, 0x10 };
+/*
+ * cont = 0 - access the IDE register file
+ * cont = 1 - access the IDE command set
+ */
+static int cont_map[2] = { 0x08, 0x10 };
static int friq_read_regr(struct pi_adapter *pi, int cont, int regr)
-
-{ int h,l,r;
+{
+ int h, l, r;
r = regr + cont_map[cont];
CMD(r);
w2(6); l = r1();
w2(4); h = r1();
- w2(4);
-
- return j44(l,h);
+ w2(4);
+ return j44(l, h);
}
static void friq_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
-
-{ int r;
-
- r = regr + cont_map[cont];
+{
+ int r = regr + cont_map[cont];
CMD(r);
w0(val);
- w2(5);w2(7);w2(5);w2(4);
+ w2(5); w2(7); w2(5); w2(4);
}
static void friq_read_block_int(struct pi_adapter *pi, char *buf, int count, int regr)
+{
+ int h, l, k, ph;
-{ int h, l, k, ph;
-
- switch(pi->mode) {
-
- case 0: CMD(regr);
- for (k=0;k<count;k++) {
- w2(6); l = r1();
- w2(4); h = r1();
- buf[k] = j44(l,h);
- }
- w2(4);
- break;
-
- case 1: ph = 2;
- CMD(regr+0xc0);
- w0(0xff);
- for (k=0;k<count;k++) {
- w2(0xa4 + ph);
- buf[k] = r0();
- ph = 2 - ph;
- }
- w2(0xac); w2(0xa4); w2(4);
- break;
-
- case 2: CMD(regr+0x80);
- for (k=0;k<count-2;k++) buf[k] = r4();
+ switch (pi->mode) {
+ case 0:
+ CMD(regr);
+ for (k = 0; k < count; k++) {
+ w2(6); l = r1();
+ w2(4); h = r1();
+ buf[k] = j44(l, h);
+ }
+ w2(4);
+ break;
+ case 1:
+ ph = 2;
+ CMD(regr + 0xc0);
+ w0(0xff);
+ for (k = 0; k < count; k++) {
+ w2(0xa4 + ph);
+ buf[k] = r0();
+ ph = 2 - ph;
+ }
+ w2(0xac); w2(0xa4); w2(4);
+ break;
+ case 2:
+ CMD(regr + 0x80);
+ for (k = 0; k < count - 2; k++)
+ buf[k] = r4();
w2(0xac); w2(0xa4);
- buf[count-2] = r4();
- buf[count-1] = r4();
+ buf[count - 2] = r4();
+ buf[count - 1] = r4();
w2(4);
break;
-
- case 3: CMD(regr+0x80);
- for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
- w2(0xac); w2(0xa4);
- buf[count-2] = r4();
- buf[count-1] = r4();
- w2(4);
- break;
-
- case 4: CMD(regr+0x80);
- for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
- buf[count-4] = r4();
- buf[count-3] = r4();
- w2(0xac); w2(0xa4);
- buf[count-2] = r4();
- buf[count-1] = r4();
- w2(4);
- break;
-
- }
+ case 3:
+ CMD(regr + 0x80);
+ for (k = 0; k < count / 2 - 1; k++)
+ ((u16 *)buf)[k] = r4w();
+ w2(0xac); w2(0xa4);
+ buf[count - 2] = r4();
+ buf[count - 1] = r4();
+ w2(4);
+ break;
+ case 4:
+ CMD(regr + 0x80);
+ for (k = 0; k < count / 4 - 1; k++)
+ ((u32 *)buf)[k] = r4l();
+ buf[count - 4] = r4();
+ buf[count - 3] = r4();
+ w2(0xac); w2(0xa4);
+ buf[count - 2] = r4();
+ buf[count - 1] = r4();
+ w2(4);
+ break;
+ }
}
static void friq_read_block(struct pi_adapter *pi, char *buf, int count)
-
-{ friq_read_block_int(pi,buf,count,0x08);
+{
+ friq_read_block_int(pi, buf, count, 0x08);
}
static void friq_write_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int k;
-
- switch(pi->mode) {
+{
+ int k;
+ switch (pi->mode) {
case 0:
- case 1: CMD(8); w2(5);
- for (k=0;k<count;k++) {
+ case 1:
+ CMD(8); w2(5);
+ for (k = 0; k < count; k++) {
w0(buf[k]);
- w2(7);w2(5);
+ w2(7); w2(5);
}
w2(4);
break;
-
- case 2: CMD(0xc8); w2(5);
- for (k=0;k<count;k++) w4(buf[k]);
+ case 2:
+ CMD(0xc8); w2(5);
+ for (k = 0; k < count; k++)
+ w4(buf[k]);
+ w2(4);
+ break;
+ case 3:
+ CMD(0xc8); w2(5);
+ for (k = 0; k < count / 2; k++)
+ w4w(((u16 *)buf)[k]);
+ w2(4);
+ break;
+ case 4:
+ CMD(0xc8); w2(5);
+ for (k = 0; k < count / 4; k++)
+ w4l(((u32 *)buf)[k]);
w2(4);
break;
-
- case 3: CMD(0xc8); w2(5);
- for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
- w2(4);
- break;
-
- case 4: CMD(0xc8); w2(5);
- for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
- w2(4);
- break;
- }
+}
}
static void friq_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
w2(4);
}
static void friq_disconnect(struct pi_adapter *pi)
-
-{ CMD(0x20);
+{
+ CMD(0x20);
w0(pi->saved_r0);
- w2(pi->saved_r2);
-}
+ w2(pi->saved_r2);
+}
static int friq_test_proto(struct pi_adapter *pi)
-
-{ int j, k, r;
- int e[2] = {0,0};
+{
+ int j, k, r;
+ int e[2] = { 0, 0 };
char scratch[512];
- pi->saved_r0 = r0();
+ pi->saved_r0 = r0();
w0(0xff); udelay(20); CMD(0x3d); /* turn the power on */
udelay(500);
w0(pi->saved_r0);
friq_connect(pi);
- for (j=0;j<2;j++) {
- friq_write_regr(pi,0,6,0xa0+j*0x10);
- for (k=0;k<256;k++) {
- friq_write_regr(pi,0,2,k^0xaa);
- friq_write_regr(pi,0,3,k^0x55);
- if (friq_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
- }
- }
+ for (j = 0; j < 2; j++) {
+ friq_write_regr(pi, 0, 6, 0xa0 + j * 0x10);
+ for (k = 0; k < 256; k++) {
+ friq_write_regr(pi, 0, 2, k ^ 0xaa);
+ friq_write_regr(pi, 0, 3, k ^ 0x55);
+ if (friq_read_regr(pi, 0, 2) != (k ^ 0xaa))
+ e[j]++;
+ }
+ }
friq_disconnect(pi);
friq_connect(pi);
- friq_read_block_int(pi,scratch,512,0x10);
- r = 0;
- for (k=0;k<128;k++) if (scratch[k] != k) r++;
+ friq_read_block_int(pi, scratch, 512, 0x10);
+ r = 0;
+ for (k = 0; k < 128; k++) {
+ if (scratch[k] != k)
+ r++;
+ }
friq_disconnect(pi);
- dev_dbg(&pi->dev, "friq: port 0x%x, mode %d, test=(%d,%d,%d)\n",
- pi->port, pi->mode, e[0], e[1], r);
+ dev_dbg(&pi->dev,
+ "friq: port 0x%x, mode %d, test=(%d,%d,%d)\n",
+ pi->port, pi->mode, e[0], e[1], r);
- return (r || (e[0] && e[1]));
+ return r || (e[0] && e[1]);
}
-
static void friq_log_adapter(struct pi_adapter *pi)
+{
+ char *mode_string[6] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32"};
-{ char *mode_string[6] = {"4-bit","8-bit",
- "EPP-8","EPP-16","EPP-32"};
-
- dev_info(&pi->dev, "Freecom IQ ASIC-2 adapter at 0x%x, mode %d (%s), delay %d\n",
- pi->port, pi->mode, mode_string[pi->mode], pi->delay);
+ dev_info(&pi->dev,
+ "Freecom IQ ASIC-2 adapter at 0x%x, mode %d (%s), delay %d\n",
+ pi->port, pi->mode, mode_string[pi->mode], pi->delay);
pi->private = 1;
friq_connect(pi);
CMD(0x9e); /* disable sleep timer */
friq_disconnect(pi);
-
}
static void friq_release_proto(struct pi_adapter *pi)
diff --git a/drivers/ata/pata_parport/frpw.c b/drivers/ata/pata_parport/frpw.c
index 3ec0abf16fa6..28d9bb2c6baf 100644
--- a/drivers/ata/pata_parport/frpw.c
+++ b/drivers/ata/pata_parport/frpw.c
@@ -1,17 +1,15 @@
-/*
- frpw.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License
-
- frpw.c is a low-level protocol driver for the Freecom "Power"
- parallel port IDE adapter.
-
- Some applications of this adapter may require a "printer" reset
- prior to loading the driver. This can be done by loading and
- unloading the "lp" driver, or it can be done by this driver
- if you define FRPW_HARD_RESET. The latter is not recommended
- as it may upset devices on other ports.
-
-*/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1996-1998 Grant R. Guenther <grant@torque.net>
+ *
+ * frpw.c is a low-level protocol driver for the Freecom "Power" parallel port
+ * IDE adapter.
+ *
+ * Some applications of this adapter may require a "printer" reset prior to
+ * loading the driver. This can be done by loading and unloading the "lp"
+ * driver, or it can be done by this driver if you define FRPW_HARD_RESET.
+ * The latter is not recommended as it may upset devices on other ports.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -25,15 +23,15 @@
#define cec4 w2(0xc);w2(0xe);w2(0xe);w2(0xc);w2(4);w2(4);w2(4);
#define j44(l,h) (((l>>4)&0x0f)|(h&0xf0))
-/* cont = 0 - access the IDE register file
- cont = 1 - access the IDE command set
-*/
-
+/*
+ * cont = 0 - access the IDE register file
+ * cont = 1 - access the IDE command set
+ */
static int cont_map[2] = { 0x08, 0x10 };
static int frpw_read_regr(struct pi_adapter *pi, int cont, int regr)
-
-{ int h,l,r;
+{
+ int h, l, r;
r = regr + cont_map[cont];
@@ -41,145 +39,156 @@ static int frpw_read_regr(struct pi_adapter *pi, int cont, int regr)
w0(r); cec4;
w2(6); l = r1();
w2(4); h = r1();
- w2(4);
-
- return j44(l,h);
+ w2(4);
+ return j44(l, h);
}
static void frpw_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
+{
+ int r = regr + cont_map[cont];
-{ int r;
-
- r = regr + cont_map[cont];
-
- w2(4); w0(r); cec4;
+ w2(4); w0(r); cec4;
w0(val);
- w2(5);w2(7);w2(5);w2(4);
+ w2(5); w2(7); w2(5); w2(4);
}
-static void frpw_read_block_int(struct pi_adapter *pi, char *buf, int count, int regr)
-
-{ int h, l, k, ph;
-
- switch(pi->mode) {
-
- case 0: w2(4); w0(regr); cec4;
- for (k=0;k<count;k++) {
- w2(6); l = r1();
- w2(4); h = r1();
- buf[k] = j44(l,h);
- }
- w2(4);
- break;
-
- case 1: ph = 2;
- w2(4); w0(regr + 0xc0); cec4;
- w0(0xff);
- for (k=0;k<count;k++) {
- w2(0xa4 + ph);
- buf[k] = r0();
- ph = 2 - ph;
- }
- w2(0xac); w2(0xa4); w2(4);
- break;
-
- case 2: w2(4); w0(regr + 0x80); cec4;
- for (k=0;k<count;k++) buf[k] = r4();
- w2(0xac); w2(0xa4);
- w2(4);
- break;
-
- case 3: w2(4); w0(regr + 0x80); cec4;
- for (k=0;k<count-2;k++) buf[k] = r4();
+static void frpw_read_block_int(struct pi_adapter *pi, char *buf, int count,
+ int regr)
+{
+ int h, l, k, ph;
+
+ switch (pi->mode) {
+ case 0:
+ w2(4); w0(regr); cec4;
+ for (k = 0; k < count; k++) {
+ w2(6); l = r1();
+ w2(4); h = r1();
+ buf[k] = j44(l, h);
+ }
+ w2(4);
+ break;
+
+ case 1:
+ ph = 2;
+ w2(4); w0(regr + 0xc0); cec4;
+ w0(0xff);
+ for (k = 0; k < count; k++) {
+ w2(0xa4 + ph);
+ buf[k] = r0();
+ ph = 2 - ph;
+ }
+ w2(0xac); w2(0xa4); w2(4);
+ break;
+
+ case 2:
+ w2(4); w0(regr + 0x80); cec4;
+ for (k = 0; k < count; k++)
+ buf[k] = r4();
w2(0xac); w2(0xa4);
- buf[count-2] = r4();
- buf[count-1] = r4();
w2(4);
break;
- case 4: w2(4); w0(regr + 0x80); cec4;
- for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
- w2(0xac); w2(0xa4);
- buf[count-2] = r4();
- buf[count-1] = r4();
- w2(4);
- break;
-
- case 5: w2(4); w0(regr + 0x80); cec4;
- for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
- buf[count-4] = r4();
- buf[count-3] = r4();
- w2(0xac); w2(0xa4);
- buf[count-2] = r4();
- buf[count-1] = r4();
- w2(4);
- break;
+ case 3:
+ w2(4); w0(regr + 0x80); cec4;
+ for (k = 0; k < count - 2; k++)
+ buf[k] = r4();
+ w2(0xac); w2(0xa4);
+ buf[count - 2] = r4();
+ buf[count - 1] = r4();
+ w2(4);
+ break;
+
+ case 4:
+ w2(4); w0(regr + 0x80); cec4;
+ for (k = 0; k < count / 2 - 1; k++)
+ ((u16 *)buf)[k] = r4w();
+ w2(0xac); w2(0xa4);
+ buf[count - 2] = r4();
+ buf[count - 1] = r4();
+ w2(4);
+ break;
+ case 5:
+ w2(4); w0(regr + 0x80); cec4;
+ for (k = 0; k < count / 4 - 1; k++)
+ ((u32 *)buf)[k] = r4l();
+ buf[count - 4] = r4();
+ buf[count - 3] = r4();
+ w2(0xac); w2(0xa4);
+ buf[count - 2] = r4();
+ buf[count - 1] = r4();
+ w2(4);
+ break;
}
}
static void frpw_read_block(struct pi_adapter *pi, char *buf, int count)
-
-{ frpw_read_block_int(pi,buf,count,0x08);
+{
+ frpw_read_block_int(pi, buf, count, 0x08);
}
static void frpw_write_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int k;
-
- switch(pi->mode) {
+{
+ int k;
+ switch (pi->mode) {
case 0:
case 1:
- case 2: w2(4); w0(8); cec4; w2(5);
- for (k=0;k<count;k++) {
+ case 2:
+ w2(4); w0(8); cec4; w2(5);
+ for (k = 0; k < count; k++) {
w0(buf[k]);
- w2(7);w2(5);
+ w2(7); w2(5);
}
w2(4);
break;
- case 3: w2(4); w0(0xc8); cec4; w2(5);
- for (k=0;k<count;k++) w4(buf[k]);
+ case 3:
+ w2(4); w0(0xc8); cec4; w2(5);
+ for (k = 0; k < count; k++)
+ w4(buf[k]);
w2(4);
break;
- case 4: w2(4); w0(0xc8); cec4; w2(5);
- for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
- w2(4);
- break;
+ case 4:
+ w2(4); w0(0xc8); cec4; w2(5);
+ for (k = 0; k < count / 2; k++)
+ w4w(((u16 *)buf)[k]);
+ w2(4);
+ break;
- case 5: w2(4); w0(0xc8); cec4; w2(5);
- for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
- w2(4);
- break;
+ case 5:
+ w2(4); w0(0xc8); cec4; w2(5);
+ for (k = 0; k < count / 4; k++)
+ w4l(((u32 *)buf)[k]);
+ w2(4);
+ break;
}
}
static void frpw_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
w2(4);
}
static void frpw_disconnect(struct pi_adapter *pi)
-
-{ w2(4); w0(0x20); cec4;
+{
+ w2(4); w0(0x20); cec4;
w0(pi->saved_r0);
- w2(pi->saved_r2);
-}
-
-/* Stub logic to see if PNP string is available - used to distinguish
- between the Xilinx and ASIC implementations of the Freecom adapter.
-*/
+ w2(pi->saved_r2);
+}
+/*
+ * Stub logic to see if PNP string is available - used to distinguish
+ * between the Xilinx and ASIC implementations of the Freecom adapter.
+ * returns chip_type: 0 = Xilinx, 1 = ASIC
+ */
static int frpw_test_pnp(struct pi_adapter *pi)
-
-/* returns chip_type: 0 = Xilinx, 1 = ASIC */
-
-{ int olddelay, a, b;
+{
+ int olddelay, a, b;
#ifdef FRPW_HARD_RESET
w0(0); w2(8); udelay(50); w2(0xc); /* parallel bus reset */
@@ -191,7 +200,7 @@ static int frpw_test_pnp(struct pi_adapter *pi)
pi->saved_r0 = r0();
pi->saved_r2 = r2();
-
+
w2(4); w0(4); w2(6); w2(7);
a = r1() & 0xff; w2(4); b = r1() & 0xff;
w2(0xc); w2(0xe); w2(4);
@@ -200,65 +209,70 @@ static int frpw_test_pnp(struct pi_adapter *pi)
w0(pi->saved_r0);
w2(pi->saved_r2);
- return ((~a&0x40) && (b&0x40));
-}
-
-/* We use the pi->private to remember the result of the PNP test.
- To make this work, private = port*2 + chip. Yes, I know it's
- a hack :-(
-*/
+ return ((~a & 0x40) && (b & 0x40));
+}
+/*
+ * We use the pi->private to remember the result of the PNP test.
+ * To make this work, private = port*2 + chip. Yes, I know it's a hack :-(
+ */
static int frpw_test_proto(struct pi_adapter *pi)
-
-{ int j, k, r;
- int e[2] = {0,0};
+{
+ int j, k, r;
+ int e[2] = { 0, 0 };
char scratch[512];
- if ((pi->private>>1) != pi->port)
- pi->private = frpw_test_pnp(pi) + 2*pi->port;
+ if ((pi->private >> 1) != pi->port)
+ pi->private = frpw_test_pnp(pi) + 2*pi->port;
- if (((pi->private%2) == 0) && (pi->mode > 2)) {
- dev_dbg(&pi->dev, "frpw: Xilinx does not support mode %d\n", pi->mode);
- return 1;
+ if (((pi->private & 0x1) == 0) && (pi->mode > 2)) {
+ dev_dbg(&pi->dev,
+ "frpw: Xilinx does not support mode %d\n", pi->mode);
+ return 1;
}
- if (((pi->private%2) == 1) && (pi->mode == 2)) {
+ if (((pi->private & 0x1) == 1) && (pi->mode == 2)) {
dev_dbg(&pi->dev, "frpw: ASIC does not support mode 2\n");
- return 1;
+ return 1;
}
frpw_connect(pi);
- for (j=0;j<2;j++) {
- frpw_write_regr(pi,0,6,0xa0+j*0x10);
- for (k=0;k<256;k++) {
- frpw_write_regr(pi,0,2,k^0xaa);
- frpw_write_regr(pi,0,3,k^0x55);
- if (frpw_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
- }
- }
+ for (j = 0; j < 2; j++) {
+ frpw_write_regr(pi, 0, 6, 0xa0 + j * 0x10);
+ for (k = 0; k < 256; k++) {
+ frpw_write_regr(pi, 0, 2, k ^ 0xaa);
+ frpw_write_regr(pi, 0, 3, k ^ 0x55);
+ if (frpw_read_regr(pi, 0, 2) != (k ^ 0xaa))
+ e[j]++;
+ }
+ }
frpw_disconnect(pi);
frpw_connect(pi);
- frpw_read_block_int(pi,scratch,512,0x10);
- r = 0;
- for (k=0;k<128;k++) if (scratch[k] != k) r++;
+ frpw_read_block_int(pi, scratch, 512, 0x10);
+ r = 0;
+ for (k = 0; k < 128; k++) {
+ if (scratch[k] != k)
+ r++;
+ }
frpw_disconnect(pi);
- dev_dbg(&pi->dev, "frpw: port 0x%x, chip %ld, mode %d, test=(%d,%d,%d)\n",
- pi->port, (pi->private%2), pi->mode, e[0], e[1], r);
+ dev_dbg(&pi->dev,
+ "frpw: port 0x%x, chip %ld, mode %d, test=(%d,%d,%d)\n",
+ pi->port, (pi->private%2), pi->mode, e[0], e[1], r);
- return (r || (e[0] && e[1]));
+ return r || (e[0] && e[1]);
}
-
static void frpw_log_adapter(struct pi_adapter *pi)
-{ char *mode_string[6] = {"4-bit","8-bit","EPP",
- "EPP-8","EPP-16","EPP-32"};
+{
+ char *mode[6] = { "4-bit", "8-bit", "EPP", "EPP-8", "EPP-16", "EPP-32"};
- dev_info(&pi->dev, "Freecom (%s) adapter at 0x%x, mode %d (%s), delay %d\n",
- ((pi->private % 2) == 0) ? "Xilinx" : "ASIC",
- pi->port, pi->mode, mode_string[pi->mode], pi->delay);
+ dev_info(&pi->dev,
+ "Freecom (%s) adapter at 0x%x, mode %d (%s), delay %d\n",
+ ((pi->private & 0x1) == 0) ? "Xilinx" : "ASIC",
+ pi->port, pi->mode, mode[pi->mode], pi->delay);
}
static struct pi_protocol frpw = {
diff --git a/drivers/ata/pata_parport/kbic.c b/drivers/ata/pata_parport/kbic.c
index 8213e62f8f00..6023e071516d 100644
--- a/drivers/ata/pata_parport/kbic.c
+++ b/drivers/ata/pata_parport/kbic.c
@@ -1,16 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- kbic.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- This is a low-level driver for the KBIC-951A and KBIC-971A
- parallel to IDE adapter chips from KingByte Information Systems.
-
- The chips are almost identical, however, the wakeup code
- required for the 971A interferes with the correct operation of
- the 951A, so this driver registers itself twice, once for
- each chip.
-
-*/
+ * (c) 1997-1998 Grant R. Guenther <grant@torque.net>
+ *
+ * This is a low-level driver for the KBIC-951A and KBIC-971A
+ * parallel to IDE adapter chips from KingByte Information Systems.
+ *
+ * The chips are almost identical, however, the wakeup code
+ * required for the 971A interferes with the correct operation of
+ * the 951A, so this driver registers itself twice, once for
+ * each chip.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -21,212 +20,223 @@
#include <asm/io.h>
#include "pata_parport.h"
-#define r12w() (delay_p,inw(pi->port+1)&0xffff)
+#define r12w() (delay_p, inw(pi->port + 1) & 0xffff)
-#define j44(a,b) ((((a>>4)&0x0f)|(b&0xf0))^0x88)
-#define j53(w) (((w>>3)&0x1f)|((w>>4)&0xe0))
+#define j44(a, b) ((((a >> 4) & 0x0f) | (b & 0xf0)) ^ 0x88)
+#define j53(w) (((w >> 3) & 0x1f) | ((w >> 4) & 0xe0))
-/* cont = 0 - access the IDE register file
- cont = 1 - access the IDE command set
-*/
-
-static int cont_map[2] = { 0x80, 0x40 };
+/*
+ * cont = 0 - access the IDE register file
+ * cont = 1 - access the IDE command set
+ */
+static int cont_map[2] = { 0x80, 0x40 };
static int kbic_read_regr(struct pi_adapter *pi, int cont, int regr)
+{
+ int a, b, s;
-{ int a, b, s;
-
- s = cont_map[cont];
+ s = cont_map[cont];
switch (pi->mode) {
-
- case 0: w0(regr|0x18|s); w2(4); w2(6); w2(4); w2(1); w0(8);
- a = r1(); w0(0x28); b = r1(); w2(4);
- return j44(a,b);
-
- case 1: w0(regr|0x38|s); w2(4); w2(6); w2(4); w2(5); w0(8);
+ case 0:
+ w0(regr | 0x18 | s); w2(4); w2(6); w2(4); w2(1); w0(8);
+ a = r1(); w0(0x28); b = r1(); w2(4);
+ return j44(a, b);
+ case 1:
+ w0(regr|0x38 | s); w2(4); w2(6); w2(4); w2(5); w0(8);
a = r12w(); w2(4);
return j53(a);
-
- case 2: w0(regr|0x08|s); w2(4); w2(6); w2(4); w2(0xa5); w2(0xa1);
+ case 2:
+ w0(regr | 0x08 | s); w2(4); w2(6); w2(4); w2(0xa5); w2(0xa1);
a = r0(); w2(4);
- return a;
-
+ return a;
case 3:
case 4:
- case 5: w0(0x20|s); w2(4); w2(6); w2(4); w3(regr);
+ case 5:
+ w0(0x20 | s); w2(4); w2(6); w2(4); w3(regr);
a = r4(); b = r4(); w2(4); w2(0); w2(4);
return a;
-
}
+
return -1;
-}
+}
static void kbic_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
+{
+ int s = cont_map[cont];
-{ int s;
-
- s = cont_map[cont];
-
- switch (pi->mode) {
-
- case 0:
- case 1:
- case 2: w0(regr|0x10|s); w2(4); w2(6); w2(4);
+ switch (pi->mode) {
+ case 0:
+ case 1:
+ case 2:
+ w0(regr | 0x10 | s); w2(4); w2(6); w2(4);
w0(val); w2(5); w2(4);
break;
-
case 3:
case 4:
- case 5: w0(0x20|s); w2(4); w2(6); w2(4); w3(regr);
+ case 5:
+ w0(0x20 | s); w2(4); w2(6); w2(4); w3(regr);
w4(val); w4(val);
w2(4); w2(0); w2(4);
- break;
-
+ break;
}
}
static void k951_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
- w2(4);
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+ w2(4);
}
static void k951_disconnect(struct pi_adapter *pi)
-
-{ w0(pi->saved_r0);
- w2(pi->saved_r2);
+{
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
}
-#define CCP(x) w2(0xc4);w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);\
- w0(0x78);w0(x);w2(0xc5);w2(0xc4);w0(0xff);
+#define CCP(x) \
+ do { \
+ w2(0xc4); w0(0xaa); w0(0x55); \
+ w0(0); w0(0xff); w0(0x87); \
+ w0(0x78); w0(x); w2(0xc5); \
+ w2(0xc4); w0(0xff); \
+ } while (0)
static void k971_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
CCP(0x20);
- w2(4);
+ w2(4);
}
static void k971_disconnect(struct pi_adapter *pi)
-
-{ CCP(0x30);
+{
+ CCP(0x30);
w0(pi->saved_r0);
- w2(pi->saved_r2);
+ w2(pi->saved_r2);
}
-/* counts must be congruent to 0 MOD 4, but all known applications
- have this property.
-*/
-
+/*
+ * count must be congruent to 0 MOD 4, but all known applications
+ *have this property.
+ */
static void kbic_read_block(struct pi_adapter *pi, char *buf, int count)
+{
+ int k, a, b;
-{ int k, a, b;
-
- switch (pi->mode) {
-
- case 0: w0(0x98); w2(4); w2(6); w2(4);
- for (k=0;k<count/2;k++) {
- w2(1); w0(8); a = r1();
- w0(0x28); b = r1();
- buf[2*k] = j44(a,b);
- w2(5); b = r1();
- w0(8); a = r1();
- buf[2*k+1] = j44(a,b);
+ switch (pi->mode) {
+ case 0:
+ w0(0x98); w2(4); w2(6); w2(4);
+ for (k = 0; k < count / 2; k++) {
+ w2(1); w0(8);
+ a = r1();
+ w0(0x28);
+ b = r1();
+ buf[2 * k] = j44(a, b);
+ w2(5);
+ b = r1();
+ w0(8);
+ a = r1();
+ buf[2 * k + 1] = j44(a, b);
w2(4);
- }
- break;
-
- case 1: w0(0xb8); w2(4); w2(6); w2(4);
- for (k=0;k<count/4;k++) {
- w0(0xb8);
- w2(4); w2(5);
- w0(8); buf[4*k] = j53(r12w());
- w0(0xb8); buf[4*k+1] = j53(r12w());
+ }
+ break;
+ case 1:
+ w0(0xb8); w2(4); w2(6); w2(4);
+ for (k = 0; k < count / 4; k++) {
+ w0(0xb8);
w2(4); w2(5);
- buf[4*k+3] = j53(r12w());
- w0(8); buf[4*k+2] = j53(r12w());
- }
- w2(4);
- break;
-
- case 2: w0(0x88); w2(4); w2(6); w2(4);
- for (k=0;k<count/2;k++) {
- w2(0xa0); w2(0xa1); buf[2*k] = r0();
- w2(0xa5); buf[2*k+1] = r0();
- }
- w2(4);
- break;
-
- case 3: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
- for (k=0;k<count;k++) buf[k] = r4();
- w2(4); w2(0); w2(4);
- break;
-
- case 4: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
- for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
- w2(4); w2(0); w2(4);
- break;
-
- case 5: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
- for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
- w2(4); w2(0); w2(4);
- break;
-
-
- }
+ w0(8);
+ buf[4 * k] = j53(r12w());
+ w0(0xb8);
+ buf[4 * k + 1] = j53(r12w());
+ w2(4); w2(5);
+ buf[4 * k + 3] = j53(r12w());
+ w0(8);
+ buf[4 * k + 2] = j53(r12w());
+ }
+ w2(4);
+ break;
+ case 2:
+ w0(0x88); w2(4); w2(6); w2(4);
+ for (k = 0; k < count / 2; k++) {
+ w2(0xa0); w2(0xa1);
+ buf[2 * k] = r0();
+ w2(0xa5);
+ buf[2 * k + 1] = r0();
+ }
+ w2(4);
+ break;
+ case 3:
+ w0(0xa0); w2(4); w2(6); w2(4); w3(0);
+ for (k = 0; k < count; k++)
+ buf[k] = r4();
+ w2(4); w2(0); w2(4);
+ break;
+ case 4:
+ w0(0xa0); w2(4); w2(6); w2(4); w3(0);
+ for (k = 0; k < count / 2; k++)
+ ((u16 *)buf)[k] = r4w();
+ w2(4); w2(0); w2(4);
+ break;
+ case 5:
+ w0(0xa0); w2(4); w2(6); w2(4); w3(0);
+ for (k = 0; k < count / 4; k++)
+ ((u32 *)buf)[k] = r4l();
+ w2(4); w2(0); w2(4);
+ break;
+ }
}
static void kbic_write_block(struct pi_adapter *pi, char *buf, int count)
+{
+ int k;
-{ int k;
-
- switch (pi->mode) {
-
- case 0:
- case 1:
- case 2: w0(0x90); w2(4); w2(6); w2(4);
- for(k=0;k<count/2;k++) {
- w0(buf[2*k+1]); w2(0); w2(4);
- w0(buf[2*k]); w2(5); w2(4);
+ switch (pi->mode) {
+ case 0:
+ case 1:
+ case 2:
+ w0(0x90); w2(4); w2(6); w2(4);
+ for (k = 0; k < count / 2; k++) {
+ w0(buf[2 * k + 1]);
+ w2(0); w2(4);
+ w0(buf[2 * k]);
+ w2(5); w2(4);
}
break;
-
- case 3: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
- for(k=0;k<count/2;k++) {
- w4(buf[2*k+1]);
- w4(buf[2*k]);
- }
+ case 3:
+ w0(0xa0); w2(4); w2(6); w2(4); w3(0);
+ for (k = 0; k < count / 2; k++) {
+ w4(buf[2 * k + 1]);
+ w4(buf[2 * k]);
+ }
w2(4); w2(0); w2(4);
break;
-
- case 4: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
+ case 4:
+ w0(0xa0); w2(4); w2(6); w2(4); w3(0);
for (k = 0; k < count / 2; k++)
w4w(swab16(((u16 *)buf)[k]));
- w2(4); w2(0); w2(4);
- break;
-
- case 5: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
+ w2(4); w2(0); w2(4);
+ break;
+ case 5:
+ w0(0xa0); w2(4); w2(6); w2(4); w3(0);
for (k = 0; k < count / 4; k++)
w4l(swab16(((u16 *)buf)[2 * k]) |
swab16(((u16 *)buf)[2 * k + 1]) << 16);
- w2(4); w2(0); w2(4);
- break;
-
- }
-
+ w2(4); w2(0); w2(4);
+ break;
+ }
}
static void kbic_log_adapter(struct pi_adapter *pi, char *chip)
-
-{ char *mode_string[6] = {"4-bit","5/3","8-bit",
- "EPP-8","EPP_16","EPP-32"};
+{
+ char *mode[6] = { "4-bit", "5/3", "8-bit", "EPP-8", "EPP_16", "EPP-32"};
dev_info(&pi->dev, "KingByte %s at 0x%x, mode %d (%s), delay %d\n",
- chip, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
+ chip, pi->port, pi->mode, mode[pi->mode], pi->delay);
}
static void k951_log_adapter(struct pi_adapter *pi)
diff --git a/drivers/ata/pata_parport/ktti.c b/drivers/ata/pata_parport/ktti.c
index 4890b1f12348..bca6c20ef617 100644
--- a/drivers/ata/pata_parport/ktti.c
+++ b/drivers/ata/pata_parport/ktti.c
@@ -1,12 +1,11 @@
-/*
- ktti.c (c) 1998 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- ktti.c is a low-level protocol driver for the KT Technology
- parallel port adapter. This adapter is used in the "PHd"
- portable hard-drives. As far as I can tell, this device
- supports 4-bit mode _only_.
-
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1998 Grant R. Guenther <grant@torque.net>
+ *
+ * ktti.c is a low-level protocol driver for the KT Technology
+ * parallel port adapter. This adapter is used in the "PHd"
+ * portable hard-drives. As far as I can tell, this device
+ * supports 4-bit mode _only_.
*/
#include <linux/module.h>
@@ -18,80 +17,76 @@
#include <asm/io.h>
#include "pata_parport.h"
-#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0))
+#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0))
-/* cont = 0 - access the IDE register file
- cont = 1 - access the IDE command set
-*/
-
-static int cont_map[2] = { 0x10, 0x08 };
+/*
+ * cont = 0 - access the IDE register file
+ * cont = 1 - access the IDE command set
+ */
+static int cont_map[2] = { 0x10, 0x08 };
static void ktti_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
+{
+ int r = regr + cont_map[cont];
-{ int r;
-
- r = regr + cont_map[cont];
-
- w0(r); w2(0xb); w2(0xa); w2(3); w2(6);
+ w0(r); w2(0xb); w2(0xa); w2(3); w2(6);
w0(val); w2(3); w0(0); w2(6); w2(0xb);
}
static int ktti_read_regr(struct pi_adapter *pi, int cont, int regr)
-
-{ int a, b, r;
+{
+ int a, b, r;
r = regr + cont_map[cont];
- w0(r); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9);
+ w0(r); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9);
a = r1(); w2(0xc); b = r1(); w2(9); w2(0xc); w2(9);
- return j44(a,b);
-
+ return j44(a, b);
}
static void ktti_read_block(struct pi_adapter *pi, char *buf, int count)
+{
+ int k, a, b;
-{ int k, a, b;
-
- for (k=0;k<count/2;k++) {
+ for (k = 0; k < count / 2; k++) {
w0(0x10); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9);
a = r1(); w2(0xc); b = r1(); w2(9);
- buf[2*k] = j44(a,b);
+ buf[2*k] = j44(a, b);
a = r1(); w2(0xc); b = r1(); w2(9);
- buf[2*k+1] = j44(a,b);
+ buf[2*k+1] = j44(a, b);
}
}
static void ktti_write_block(struct pi_adapter *pi, char *buf, int count)
+{
+ int k;
-{ int k;
-
- for (k=0;k<count/2;k++) {
+ for (k = 0; k < count / 2; k++) {
w0(0x10); w2(0xb); w2(0xa); w2(3); w2(6);
- w0(buf[2*k]); w2(3);
- w0(buf[2*k+1]); w2(6);
+ w0(buf[2 * k]); w2(3);
+ w0(buf[2 * k + 1]); w2(6);
w2(0xb);
}
}
static void ktti_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
- w2(0xb); w2(0xa); w0(0); w2(3); w2(6);
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+ w2(0xb); w2(0xa); w0(0); w2(3); w2(6);
}
static void ktti_disconnect(struct pi_adapter *pi)
-
-{ w2(0xb); w2(0xa); w0(0xa0); w2(3); w2(4);
+{
+ w2(0xb); w2(0xa); w0(0xa0); w2(3); w2(4);
w0(pi->saved_r0);
- w2(pi->saved_r2);
-}
+ w2(pi->saved_r2);
+}
static void ktti_log_adapter(struct pi_adapter *pi)
-
{
dev_info(&pi->dev, "KT adapter at 0x%x, delay %d\n",
- pi->port, pi->delay);
+ pi->port, pi->delay);
}
static struct pi_protocol ktti = {
diff --git a/drivers/ata/pata_parport/on20.c b/drivers/ata/pata_parport/on20.c
index 276ace12d490..34e69da2bec8 100644
--- a/drivers/ata/pata_parport/on20.c
+++ b/drivers/ata/pata_parport/on20.c
@@ -1,10 +1,10 @@
-/*
- on20.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- on20.c is a low-level protocol driver for the
- Onspec 90c20 parallel to IDE adapter.
-*/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1996-1998 Grant R. Guenther <grant@torque.net>
+ *
+ * on20.c is a low-level protocol driver for the
+ * Onspec 90c20 parallel to IDE adapter.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -15,99 +15,114 @@
#include <asm/io.h>
#include "pata_parport.h"
-#define op(f) w2(4);w0(f);w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4);
-#define vl(v) w2(4);w0(v);w2(5);w2(7);w2(5);w2(4);
-
-#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0))
-
-/* cont = 0 - access the IDE register file
- cont = 1 - access the IDE command set
-*/
-
-static int on20_read_regr(struct pi_adapter *pi, int cont, int regr)
-
-{ int h,l, r ;
+#define op(f) \
+ do { \
+ w2(4); w0(f); w2(5); w2(0xd); \
+ w2(5); w2(0xd); w2(5); w2(4); \
+ } while (0)
- r = (regr<<2) + 1 + cont;
+#define vl(v) \
+ do { \
+ w2(4); w0(v); w2(5); \
+ w2(7); w2(5); w2(4); \
+ } while (0)
- op(1); vl(r); op(0);
+#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0))
- switch (pi->mode) {
-
- case 0: w2(4); w2(6); l = r1();
- w2(4); w2(6); h = r1();
- w2(4); w2(6); w2(4); w2(6); w2(4);
- return j44(l,h);
-
- case 1: w2(4); w2(0x26); r = r0();
- w2(4); w2(0x26); w2(4);
- return r;
+/*
+ * cont = 0 - access the IDE register file
+ * cont = 1 - access the IDE command set
+ */
+static int on20_read_regr(struct pi_adapter *pi, int cont, int regr)
+{
+ int h, l, r;
+
+ r = (regr << 2) + 1 + cont;
+
+ op(1); vl(r); op(0);
+
+ switch (pi->mode) {
+ case 0:
+ w2(4); w2(6); l = r1();
+ w2(4); w2(6); h = r1();
+ w2(4); w2(6); w2(4); w2(6); w2(4);
+ return j44(l, h);
+ case 1:
+ w2(4); w2(0x26); r = r0();
+ w2(4); w2(0x26); w2(4);
+ return r;
}
+
return -1;
-}
+}
static void on20_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
+{
+ int r = (regr << 2) + 1 + cont;
-{ int r;
-
- r = (regr<<2) + 1 + cont;
-
- op(1); vl(r);
- op(0); vl(val);
+ op(1); vl(r);
+ op(0); vl(val);
op(0); vl(val);
}
static void on20_connect(struct pi_adapter *pi)
-
-{ pi->saved_r0 = r0();
- pi->saved_r2 = r2();
-
- w2(4);w0(0);w2(0xc);w2(4);w2(6);w2(4);w2(6);w2(4);
- if (pi->mode) { op(2); vl(8); op(2); vl(9); }
- else { op(2); vl(0); op(2); vl(8); }
+{
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+
+ w2(4); w0(0); w2(0xc); w2(4); w2(6); w2(4); w2(6); w2(4);
+ if (pi->mode) {
+ op(2); vl(8); op(2); vl(9);
+ } else {
+ op(2); vl(0); op(2); vl(8);
+ }
}
static void on20_disconnect(struct pi_adapter *pi)
-
-{ w2(4);w0(7);w2(4);w2(0xc);w2(4);
- w0(pi->saved_r0);
- w2(pi->saved_r2);
-}
+{
+ w2(4); w0(7); w2(4); w2(0xc); w2(4);
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
+}
static void on20_read_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int k, l, h;
+{
+ int k, l, h;
op(1); vl(1); op(0);
- for (k=0;k<count;k++)
- if (pi->mode) {
- w2(4); w2(0x26); buf[k] = r0();
- } else {
- w2(6); l = r1(); w2(4);
- w2(6); h = r1(); w2(4);
- buf[k] = j44(l,h);
- }
+ for (k = 0; k < count; k++) {
+ if (pi->mode) {
+ w2(4); w2(0x26); buf[k] = r0();
+ } else {
+ w2(6); l = r1(); w2(4);
+ w2(6); h = r1(); w2(4);
+ buf[k] = j44(l, h);
+ }
+ }
w2(4);
}
static void on20_write_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int k;
+{
+ int k;
op(1); vl(1); op(0);
- for (k=0;k<count;k++) { w2(5); w0(buf[k]); w2(7); }
+ for (k = 0; k < count; k++) {
+ w2(5); w0(buf[k]); w2(7);
+ }
w2(4);
}
static void on20_log_adapter(struct pi_adapter *pi)
+{
+ char *mode_string[2] = { "4-bit", "8-bit" };
-{ char *mode_string[2] = {"4-bit","8-bit"};
-
- dev_info(&pi->dev, "OnSpec 90c20 at 0x%x, mode %d (%s), delay %d\n",
- pi->port, pi->mode, mode_string[pi->mode], pi->delay);
+ dev_info(&pi->dev,
+ "OnSpec 90c20 at 0x%x, mode %d (%s), delay %d\n",
+ pi->port, pi->mode, mode_string[pi->mode], pi->delay);
}
static struct pi_protocol on20 = {
diff --git a/drivers/ata/pata_parport/on26.c b/drivers/ata/pata_parport/on26.c
index dc47a54b121f..5da317b394c1 100644
--- a/drivers/ata/pata_parport/on26.c
+++ b/drivers/ata/pata_parport/on26.c
@@ -1,11 +1,10 @@
-/*
- on26.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- on26.c is a low-level protocol driver for the
- OnSpec 90c26 parallel to IDE adapter chip.
-
-*/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (c) 1997-1998 Grant R. Guenther <grant@torque.net>
+ *
+ * on26.c is a low-level protocol driver for the
+ * OnSpec 90c26 parallel to IDE adapter chip.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -16,260 +15,281 @@
#include <asm/io.h>
#include "pata_parport.h"
-/* mode codes: 0 nybble reads, 8-bit writes
- 1 8-bit reads and writes
- 2 8-bit EPP mode
- 3 EPP-16
- 4 EPP-32
-*/
+/*
+ * mode codes: 0 nybble reads, 8-bit writes
+ * 1 8-bit reads and writes
+ * 2 8-bit EPP mode
+ * 3 EPP-16
+ * 4 EPP-32
+ */
-#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0))
+#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0))
-#define P1 w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4);
-#define P2 w2(5);w2(7);w2(5);w2(4);
+#define P1 \
+ do { \
+ w2(5); w2(0xd); w2(5); w2(0xd); w2(5); w2(4); \
+ } while (0)
-/* cont = 0 - access the IDE register file
- cont = 1 - access the IDE command set
-*/
-
-static int on26_read_regr(struct pi_adapter *pi, int cont, int regr)
+#define P2 \
+ do { \
+ w2(5); w2(7); w2(5); w2(4); \
+ } while (0)
-{ int a, b, r;
+/*
+ * cont = 0 - access the IDE register file
+ * cont = 1 - access the IDE command set
+ */
- r = (regr<<2) + 1 + cont;
+static int on26_read_regr(struct pi_adapter *pi, int cont, int regr)
+{
+ int a, b, r;
- switch (pi->mode) {
+ r = (regr << 2) + 1 + cont;
- case 0: w0(1); P1; w0(r); P2; w0(0); P1;
+ switch (pi->mode) {
+ case 0:
+ w0(1); P1; w0(r); P2; w0(0); P1;
w2(6); a = r1(); w2(4);
w2(6); b = r1(); w2(4);
w2(6); w2(4); w2(6); w2(4);
- return j44(a,b);
-
- case 1: w0(1); P1; w0(r); P2; w0(0); P1;
+ return j44(a, b);
+ case 1:
+ w0(1); P1; w0(r); P2; w0(0); P1;
w2(0x26); a = r0(); w2(4); w2(0x26); w2(4);
- return a;
-
+ return a;
case 2:
case 3:
- case 4: w3(1); w3(1); w2(5); w4(r); w2(4);
+ case 4:
+ w3(1); w3(1); w2(5); w4(r); w2(4);
w3(0); w3(0); w2(0x24); a = r4(); w2(4);
w2(0x24); (void)r4(); w2(4);
- return a;
+ return a;
+ }
- }
- return -1;
-}
+ return -1;
+}
static void on26_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
+{
+ int r = (regr << 2) + 1 + cont;
-{ int r;
-
- r = (regr<<2) + 1 + cont;
-
- switch (pi->mode) {
-
- case 0:
- case 1: w0(1); P1; w0(r); P2; w0(0); P1;
+ switch (pi->mode) {
+ case 0:
+ case 1:
+ w0(1); P1; w0(r); P2; w0(0); P1;
w0(val); P2; w0(val); P2;
break;
-
case 2:
case 3:
- case 4: w3(1); w3(1); w2(5); w4(r); w2(4);
- w3(0); w3(0);
+ case 4:
+ w3(1); w3(1); w2(5); w4(r); w2(4);
+ w3(0); w3(0);
w2(5); w4(val); w2(4);
w2(5); w4(val); w2(4);
- break;
- }
+ break;
+ }
}
-#define CCP(x) w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
- w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
+#define CCP(x) \
+ do { \
+ w0(0xfe); w0(0xaa); w0(0x55); w0(0); \
+ w0(0xff); w0(0x87); w0(0x78); w0(x); \
+ w2(4); w2(5); w2(4); w0(0xff); \
+ } while (0)
static void on26_connect(struct pi_adapter *pi)
-
-{ int x;
+{
+ int x;
pi->saved_r0 = r0();
- pi->saved_r2 = r2();
+ pi->saved_r2 = r2();
- CCP(0x20);
- x = 8; if (pi->mode) x = 9;
+ CCP(0x20);
+ if (pi->mode)
+ x = 9;
+ else
+ x = 8;
w0(2); P1; w0(8); P2;
w0(2); P1; w0(x); P2;
}
static void on26_disconnect(struct pi_adapter *pi)
-
-{ if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); }
- else { w0(4); P1; w0(4); P1; }
+{
+ if (pi->mode >= 2) {
+ w3(4); w3(4); w3(4); w3(4);
+ } else {
+ w0(4); P1; w0(4); P1;
+ }
CCP(0x30);
- w0(pi->saved_r0);
- w2(pi->saved_r2);
-}
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
+}
#define RESET_WAIT 200
-static int on26_test_port(struct pi_adapter *pi) /* hard reset */
+/* hard reset */
+static int on26_test_port(struct pi_adapter *pi)
+{
+ int i, m, d, x = 0, y = 0;
-{ int i, m, d, x=0, y=0;
-
- pi->saved_r0 = r0();
- pi->saved_r2 = r2();
-
- d = pi->delay;
- m = pi->mode;
- pi->delay = 5;
- pi->mode = 0;
-
- w2(0xc);
-
- CCP(0x30); CCP(0);
-
- w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);
- i = ((r1() & 0xf0) << 4); w0(0x87);
- i |= (r1() & 0xf0); w0(0x78);
- w0(0x20);w2(4);w2(5);
- i |= ((r1() & 0xf0) >> 4);
- w2(4);w0(0xff);
-
- if (i == 0xb5f) {
-
- w0(2); P1; w0(0); P2;
- w0(3); P1; w0(0); P2;
- w0(2); P1; w0(8); P2; udelay(100);
- w0(2); P1; w0(0xa); P2; udelay(100);
- w0(2); P1; w0(8); P2; udelay(1000);
-
- on26_write_regr(pi,0,6,0xa0);
-
- for (i=0;i<RESET_WAIT;i++) {
- on26_write_regr(pi,0,6,0xa0);
- x = on26_read_regr(pi,0,7);
- on26_write_regr(pi,0,6,0xb0);
- y = on26_read_regr(pi,0,7);
- if (!((x&0x80)||(y&0x80))) break;
- mdelay(100);
- }
-
- if (i == RESET_WAIT)
- dev_err(&pi->dev, "on26: Device reset failed (%x,%x)\n", x, y);
-
- w0(4); P1; w0(4); P1;
- }
+ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+
+ d = pi->delay;
+ m = pi->mode;
+ pi->delay = 5;
+ pi->mode = 0;
+
+ w2(0xc);
+
+ CCP(0x30); CCP(0);
+
+ w0(0xfe); w0(0xaa); w0(0x55); w0(0); w0(0xff);
+ i = ((r1() & 0xf0) << 4); w0(0x87);
+ i |= (r1() & 0xf0); w0(0x78);
+ w0(0x20); w2(4); w2(5);
+ i |= ((r1() & 0xf0) >> 4);
+ w2(4); w0(0xff);
+
+ if (i == 0xb5f) {
+ w0(2); P1; w0(0); P2;
+ w0(3); P1; w0(0); P2;
+ w0(2); P1; w0(8); P2; udelay(100);
+ w0(2); P1; w0(0xa); P2; udelay(100);
+ w0(2); P1; w0(8); P2; udelay(1000);
+
+ on26_write_regr(pi, 0, 6, 0xa0);
+
+ for (i = 0; i < RESET_WAIT; i++) {
+ on26_write_regr(pi, 0, 6, 0xa0);
+ x = on26_read_regr(pi, 0, 7);
+ on26_write_regr(pi, 0, 6, 0xb0);
+ y = on26_read_regr(pi, 0, 7);
+ if (!((x & 0x80) || (y & 0x80)))
+ break;
+ mdelay(100);
+ }
+
+ if (i == RESET_WAIT)
+ dev_err(&pi->dev,
+ "on26: Device reset failed (%x,%x)\n", x, y);
+
+ w0(4); P1; w0(4); P1;
+ }
- CCP(0x30);
+ CCP(0x30);
- pi->delay = d;
- pi->mode = m;
- w0(pi->saved_r0);
- w2(pi->saved_r2);
+ pi->delay = d;
+ pi->mode = m;
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
- return 5;
+ return 5;
}
-
static void on26_read_block(struct pi_adapter *pi, char *buf, int count)
+{
+ int k, a, b;
-{ int k, a, b;
-
- switch (pi->mode) {
-
- case 0: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1;
+ switch (pi->mode) {
+ case 0:
+ w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1;
udelay(10);
- for (k=0;k<count;k++) {
- w2(6); a = r1();
- w2(4); b = r1();
- buf[k] = j44(a,b);
- }
- w0(2); P1; w0(8); P2;
- break;
-
- case 1: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
+ for (k = 0; k < count; k++) {
+ w2(6); a = r1();
+ w2(4); b = r1();
+ buf[k] = j44(a, b);
+ }
+ w0(2); P1; w0(8); P2;
+ break;
+ case 1:
+ w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
+ udelay(10);
+ for (k = 0; k < count / 2; k++) {
+ w2(0x26); buf[2 * k] = r0();
+ w2(0x24); buf[2 * k + 1] = r0();
+ }
+ w0(2); P1; w0(9); P2;
+ break;
+ case 2:
+ w3(1); w3(1); w2(5); w4(1); w2(4);
+ w3(0); w3(0); w2(0x24);
+ udelay(10);
+ for (k = 0; k < count; k++)
+ buf[k] = r4();
+ w2(4);
+ break;
+ case 3:
+ w3(1); w3(1); w2(5); w4(1); w2(4);
+ w3(0); w3(0); w2(0x24);
udelay(10);
- for (k=0;k<count/2;k++) {
- w2(0x26); buf[2*k] = r0();
- w2(0x24); buf[2*k+1] = r0();
- }
- w0(2); P1; w0(9); P2;
- break;
-
- case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
+ for (k = 0; k < count / 2; k++)
+ ((u16 *)buf)[k] = r4w();
+ w2(4);
+ break;
+ case 4:
+ w3(1); w3(1); w2(5); w4(1); w2(4);
w3(0); w3(0); w2(0x24);
udelay(10);
- for (k=0;k<count;k++) buf[k] = r4();
- w2(4);
- break;
-
- case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
- w3(0); w3(0); w2(0x24);
- udelay(10);
- for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
- w2(4);
- break;
-
- case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
- w3(0); w3(0); w2(0x24);
- udelay(10);
- for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
- w2(4);
- break;
-
- }
+ for (k = 0; k < count / 4; k++)
+ ((u32 *)buf)[k] = r4l();
+ w2(4);
+ break;
+ }
}
static void on26_write_block(struct pi_adapter *pi, char *buf, int count)
-
-{ int k;
-
- switch (pi->mode) {
-
- case 0:
- case 1: w0(1); P1; w0(1); P2;
- w0(2); P1; w0(0x18+pi->mode); P2; w0(0); P1;
+{
+ int k;
+
+ switch (pi->mode) {
+ case 0:
+ case 1:
+ w0(1); P1; w0(1); P2;
+ w0(2); P1; w0(0x18 + pi->mode); P2; w0(0); P1;
udelay(10);
- for (k=0;k<count/2;k++) {
- w2(5); w0(buf[2*k]);
- w2(7); w0(buf[2*k+1]);
- }
- w2(5); w2(4);
- w0(2); P1; w0(8+pi->mode); P2;
- break;
-
- case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
+ for (k = 0; k < count / 2; k++) {
+ w2(5); w0(buf[2 * k]);
+ w2(7); w0(buf[2 * k + 1]);
+ }
+ w2(5); w2(4);
+ w0(2); P1; w0(8 + pi->mode); P2;
+ break;
+ case 2:
+ w3(1); w3(1); w2(5); w4(1); w2(4);
w3(0); w3(0); w2(0xc5);
udelay(10);
- for (k=0;k<count;k++) w4(buf[k]);
+ for (k = 0; k < count; k++)
+ w4(buf[k]);
w2(0xc4);
- break;
-
- case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
- w3(0); w3(0); w2(0xc5);
- udelay(10);
- for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
- w2(0xc4);
- break;
-
- case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
- w3(0); w3(0); w2(0xc5);
- udelay(10);
- for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
- w2(0xc4);
- break;
-
- }
-
+ break;
+ case 3:
+ w3(1); w3(1); w2(5); w4(1); w2(4);
+ w3(0); w3(0); w2(0xc5);
+ udelay(10);
+ for (k = 0; k < count / 2; k++)
+ w4w(((u16 *)buf)[k]);
+ w2(0xc4);
+ break;
+ case 4:
+ w3(1); w3(1); w2(5); w4(1); w2(4);
+ w3(0); w3(0); w2(0xc5);
+ udelay(10);
+ for (k = 0; k < count / 4; k++)
+ w4l(((u32 *)buf)[k]);
+ w2(0xc4);
+ break;
+ }
}
static void on26_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, "OnSpec 90c26 at 0x%x, mode %d (%s), delay %d\n",
- pi->port, pi->mode, mode_string[pi->mode], pi->delay);
+ dev_info(&pi->dev,
+ "OnSpec 90c26 at 0x%x, mode %d (%s), delay %d\n",
+ pi->port, pi->mode, mode_string[pi->mode], pi->delay);
}
static struct pi_protocol on26 = {
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 87479bc893b2..232c3dad7ee8 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -223,7 +223,7 @@ static int pata_platform_probe(struct platform_device *pdev)
static struct platform_driver pata_platform_driver = {
.probe = pata_platform_probe,
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
},
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 8237ece4a46f..d6b324d03e59 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -614,7 +614,7 @@ static SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops,
ahci_highbank_suspend, ahci_highbank_resume);
static struct platform_driver ahci_highbank_driver = {
- .remove = ata_platform_remove_one,
+ .remove_new = ata_platform_remove_one,
.driver = {
.name = "highbank-ahci",
.of_match_table = ahci_of_match,
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index c47c3fb434d5..598a872f6a08 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -32,6 +32,7 @@
#include <scsi/scsi.h>
#include <linux/libata.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#define DRV_NAME "sata_svw"
#define DRV_VERSION "2.3"
@@ -319,10 +320,11 @@ static int k2_sata_show_info(struct seq_file *m, struct Scsi_Host *shost)
/* Match it to a port node */
index = (ap == ap->host->ports[0]) ? 0 : 1;
for (np = np->child; np != NULL; np = np->sibling) {
- const u32 *reg = of_get_property(np, "reg", NULL);
- if (!reg)
+ u64 reg;
+
+ if (of_property_read_reg(np, 0, &reg, NULL))
continue;
- if (index == *reg) {
+ if (index == reg) {
seq_printf(m, "devspec: %pOF\n", np);
break;
}
diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c
index 0df474506fb9..c2cab7e2b126 100644
--- a/drivers/auxdisplay/cfag12864bfb.c
+++ b/drivers/auxdisplay/cfag12864bfb.c
@@ -72,7 +72,7 @@ static int cfag12864bfb_probe(struct platform_device *device)
if (!info)
goto none;
- info->screen_base = (char __iomem *) cfag12864b_buffer;
+ info->screen_buffer = cfag12864b_buffer;
info->screen_size = CFAG12864B_SIZE;
info->fbops = &cfag12864bfb_ops;
info->fix = cfag12864bfb_fix;
diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c
index d44814b9562a..0c5cd5193fbf 100644
--- a/drivers/auxdisplay/ht16k33.c
+++ b/drivers/auxdisplay/ht16k33.c
@@ -640,7 +640,7 @@ static int ht16k33_fbdev_probe(struct device *dev, struct ht16k33_priv *priv,
INIT_DELAYED_WORK(&priv->work, ht16k33_fb_update);
fbdev->info->fbops = &ht16k33_fb_ops;
- fbdev->info->screen_base = (char __iomem *) fbdev->buffer;
+ fbdev->info->screen_buffer = fbdev->buffer;
fbdev->info->screen_size = HT16K33_FB_SIZE;
fbdev->info->fix = ht16k33_fb_fix;
fbdev->info->var = ht16k33_fb_var;
diff --git a/drivers/base/isa.c b/drivers/base/isa.c
index 55e3ee2da98f..675ad3139224 100644
--- a/drivers/base/isa.c
+++ b/drivers/base/isa.c
@@ -149,11 +149,8 @@ int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev)
break;
}
- if (isa_dev->dev.platform_data) {
- isa_dev->next = isa_driver->devices;
- isa_driver->devices = &isa_dev->dev;
- } else
- device_unregister(&isa_dev->dev);
+ isa_dev->next = isa_driver->devices;
+ isa_driver->devices = &isa_dev->dev;
}
if (!error && !isa_driver->devices)
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 655975946ef6..9de524e56307 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -162,15 +162,15 @@ free:
}
#ifdef CONFIG_HMEM_REPORTING
-#define ACCESS_ATTR(name) \
-static ssize_t name##_show(struct device *dev, \
+#define ACCESS_ATTR(property) \
+static ssize_t property##_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
return sysfs_emit(buf, "%u\n", \
- to_access_nodes(dev)->hmem_attrs.name); \
+ to_access_nodes(dev)->hmem_attrs.property); \
} \
-static DEVICE_ATTR_RO(name)
+static DEVICE_ATTR_RO(property)
ACCESS_ATTR(read_bandwidth);
ACCESS_ATTR(read_latency);
diff --git a/drivers/base/property.c b/drivers/base/property.c
index f6117ec9805c..8c40abed7852 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -987,12 +987,18 @@ EXPORT_SYMBOL(fwnode_iomap);
* @fwnode: Pointer to the firmware node
* @index: Zero-based index of the IRQ
*
- * Return: Linux IRQ number on success. Other values are determined
- * according to acpi_irq_get() or of_irq_get() operation.
+ * Return: Linux IRQ number on success. Negative errno on failure.
*/
int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index)
{
- return fwnode_call_int_op(fwnode, irq_get, index);
+ int ret;
+
+ ret = fwnode_call_int_op(fwnode, irq_get, index);
+ /* We treat mapping errors as invalid case */
+ if (ret == 0)
+ return -EINVAL;
+
+ return ret;
}
EXPORT_SYMBOL(fwnode_irq_get);
diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c
index c570c45d1480..2ac70b560c46 100644
--- a/drivers/bluetooth/virtio_bt.c
+++ b/drivers/bluetooth/virtio_bt.c
@@ -79,6 +79,7 @@ static int virtbt_close_vdev(struct virtio_bluetooth *vbt)
while ((skb = virtqueue_detach_unused_buf(vq)))
kfree_skb(skb);
+ cond_resched();
}
return 0;
diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
index 4c84be378bf2..4b68c84ef485 100644
--- a/drivers/bus/fsl-mc/dprc-driver.c
+++ b/drivers/bus/fsl-mc/dprc-driver.c
@@ -45,6 +45,9 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
struct fsl_mc_child_objs *objs;
struct fsl_mc_device *mc_dev;
+ if (!dev_is_fsl_mc(dev))
+ return 0;
+
mc_dev = to_fsl_mc_device(dev);
objs = data;
@@ -64,6 +67,9 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
static int __fsl_mc_device_remove(struct device *dev, void *data)
{
+ if (!dev_is_fsl_mc(dev))
+ return 0;
+
fsl_mc_device_remove(to_fsl_mc_device(dev));
return 0;
}
@@ -835,15 +841,14 @@ EXPORT_SYMBOL_GPL(dprc_cleanup);
* It tears down the interrupts that were configured for the DPRC device.
* It destroys the interrupt pool associated with this MC bus.
*/
-static int dprc_remove(struct fsl_mc_device *mc_dev)
+static void dprc_remove(struct fsl_mc_device *mc_dev)
{
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
- if (!is_fsl_mc_bus_dprc(mc_dev))
- return -EINVAL;
-
- if (!mc_bus->irq_resources)
- return -EINVAL;
+ if (!mc_bus->irq_resources) {
+ dev_err(&mc_dev->dev, "No irq resources, so unbinding the device failed\n");
+ return;
+ }
if (dev_get_msi_domain(&mc_dev->dev))
dprc_teardown_irq(mc_dev);
@@ -853,7 +858,6 @@ static int dprc_remove(struct fsl_mc_device *mc_dev)
dprc_cleanup(mc_dev);
dev_info(&mc_dev->dev, "DPRC device unbound from driver");
- return 0;
}
static const struct fsl_mc_device_id match_id_table[] = {
diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c
index dced427ca8ba..b5e8c021fa1f 100644
--- a/drivers/bus/fsl-mc/fsl-mc-allocator.c
+++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
@@ -103,26 +103,32 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
struct fsl_mc_resource *resource;
int error = -EINVAL;
- if (!fsl_mc_is_allocatable(mc_dev))
- goto out;
+ mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
+ mc_bus = to_fsl_mc_bus(mc_bus_dev);
resource = mc_dev->resource;
- if (!resource || resource->data != mc_dev)
+ if (!resource || resource->data != mc_dev) {
+ dev_err(&mc_bus_dev->dev, "resource mismatch\n");
goto out;
+ }
- mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
- mc_bus = to_fsl_mc_bus(mc_bus_dev);
res_pool = resource->parent_pool;
- if (res_pool != &mc_bus->resource_pools[resource->type])
+ if (res_pool != &mc_bus->resource_pools[resource->type]) {
+ dev_err(&mc_bus_dev->dev, "pool mismatch\n");
goto out;
+ }
mutex_lock(&res_pool->mutex);
- if (res_pool->max_count <= 0)
+ if (res_pool->max_count <= 0) {
+ dev_err(&mc_bus_dev->dev, "max_count underflow\n");
goto out_unlock;
+ }
if (res_pool->free_count <= 0 ||
- res_pool->free_count > res_pool->max_count)
+ res_pool->free_count > res_pool->max_count) {
+ dev_err(&mc_bus_dev->dev, "free_count mismatch\n");
goto out_unlock;
+ }
/*
* If the device is currently allocated, its resource is not
@@ -557,12 +563,9 @@ static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
struct fsl_mc_resource_pool *res_pool =
&mc_bus->resource_pools[pool_type];
- int free_count = 0;
- list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
- free_count++;
+ list_for_each_entry_safe(resource, next, &res_pool->free_list, node)
devm_kfree(&mc_bus_dev->dev, resource);
- }
}
void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
@@ -609,22 +612,18 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
* fsl_mc_allocator_remove - callback invoked when an allocatable device is
* being removed from the system
*/
-static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
+static void fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
{
int error;
- if (!fsl_mc_is_allocatable(mc_dev))
- return -EINVAL;
-
if (mc_dev->resource) {
error = fsl_mc_resource_pool_remove_device(mc_dev);
if (error < 0)
- return error;
+ return;
}
dev_dbg(&mc_dev->dev,
"Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
- return 0;
}
static const struct fsl_mc_device_id match_id_table[] = {
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 653e2d4c116f..4352745a923c 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -454,13 +454,8 @@ static int fsl_mc_driver_remove(struct device *dev)
{
struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
- int error;
- error = mc_drv->remove(mc_dev);
- if (error < 0) {
- dev_err(dev, "%s failed: %d\n", __func__, error);
- return error;
- }
+ mc_drv->remove(mc_dev);
return 0;
}
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index 6c49de37d5e9..21fe9854703f 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -1791,7 +1791,7 @@ static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset,
if (!ddata->module_va)
return -EIO;
- /* DISP_CONTROL */
+ /* DISP_CONTROL, shut down lcd and digit on disable if enabled */
val = sysc_read(ddata, dispc_offset + 0x40);
lcd_en = val & lcd_en_mask;
digit_en = val & digit_en_mask;
@@ -1803,7 +1803,7 @@ static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset,
else
irq_mask |= BIT(2) | BIT(3); /* EVSYNC bits */
}
- if (disable & (lcd_en | digit_en))
+ if (disable && (lcd_en || digit_en))
sysc_write(ddata, dispc_offset + 0x40,
val & ~(lcd_en_mask | digit_en_mask));
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index 3a46e27479ff..d668b174ace9 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -481,7 +481,7 @@ static int gdrom_bdops_open(struct gendisk *disk, blk_mode_t mode)
disk_check_media_change(disk);
mutex_lock(&gdrom_mutex);
- ret = cdrom_open(gd.cd_info);
+ ret = cdrom_open(gd.cd_info, mode);
mutex_unlock(&gdrom_mutex);
return ret;
}
@@ -489,7 +489,7 @@ static int gdrom_bdops_open(struct gendisk *disk, blk_mode_t mode)
static void gdrom_bdops_release(struct gendisk *disk)
{
mutex_lock(&gdrom_mutex);
- cdrom_release(gd.cd_info, mode);
+ cdrom_release(gd.cd_info);
mutex_unlock(&gdrom_mutex);
}
diff --git a/drivers/cdx/cdx.c b/drivers/cdx/cdx.c
index 38511fd36325..d2cad4c670a0 100644
--- a/drivers/cdx/cdx.c
+++ b/drivers/cdx/cdx.c
@@ -62,6 +62,8 @@
#include <linux/mm.h>
#include <linux/xarray.h>
#include <linux/cdx/cdx_bus.h>
+#include <linux/iommu.h>
+#include <linux/dma-map-ops.h>
#include "cdx.h"
/* Default DMA mask for devices on a CDX bus */
@@ -257,6 +259,7 @@ static void cdx_shutdown(struct device *dev)
static int cdx_dma_configure(struct device *dev)
{
+ struct cdx_driver *cdx_drv = to_cdx_driver(dev->driver);
struct cdx_device *cdx_dev = to_cdx_device(dev);
u32 input_id = cdx_dev->req_id;
int ret;
@@ -267,9 +270,23 @@ static int cdx_dma_configure(struct device *dev)
return ret;
}
+ if (!ret && !cdx_drv->driver_managed_dma) {
+ ret = iommu_device_use_default_domain(dev);
+ if (ret)
+ arch_teardown_dma_ops(dev);
+ }
+
return 0;
}
+static void cdx_dma_cleanup(struct device *dev)
+{
+ struct cdx_driver *cdx_drv = to_cdx_driver(dev->driver);
+
+ if (!cdx_drv->driver_managed_dma)
+ iommu_device_unuse_default_domain(dev);
+}
+
/* show configuration fields */
#define cdx_config_attr(field, format_string) \
static ssize_t \
@@ -405,6 +422,7 @@ struct bus_type cdx_bus_type = {
.remove = cdx_remove,
.shutdown = cdx_shutdown,
.dma_configure = cdx_dma_configure,
+ .dma_cleanup = cdx_dma_cleanup,
.bus_groups = cdx_bus_groups,
.dev_groups = cdx_dev_groups,
};
diff --git a/drivers/cdx/controller/Kconfig b/drivers/cdx/controller/Kconfig
index c3e3b9ff8dfe..61bf17fbe433 100644
--- a/drivers/cdx/controller/Kconfig
+++ b/drivers/cdx/controller/Kconfig
@@ -18,14 +18,4 @@ config CDX_CONTROLLER
If unsure, say N.
-config MCDI_LOGGING
- bool "MCDI Logging for the CDX controller"
- depends on CDX_CONTROLLER
- help
- Enable MCDI Logging for
- the CDX Controller for debug
- purpose.
-
- If unsure, say N.
-
endif
diff --git a/drivers/cdx/controller/mcdi.c b/drivers/cdx/controller/mcdi.c
index a211a2ca762e..1eedc5eeb315 100644
--- a/drivers/cdx/controller/mcdi.c
+++ b/drivers/cdx/controller/mcdi.c
@@ -31,10 +31,6 @@ struct cdx_mcdi_copy_buffer {
struct cdx_dword buffer[DIV_ROUND_UP(MCDI_CTL_SDU_LEN_MAX, 4)];
};
-#ifdef CONFIG_MCDI_LOGGING
-#define LOG_LINE_MAX (1024 - 32)
-#endif
-
static void cdx_mcdi_cancel_cmd(struct cdx_mcdi *cdx, struct cdx_mcdi_cmd *cmd);
static void cdx_mcdi_wait_for_cleanup(struct cdx_mcdi *cdx);
static int cdx_mcdi_rpc_async_internal(struct cdx_mcdi *cdx,
@@ -119,14 +115,9 @@ int cdx_mcdi_init(struct cdx_mcdi *cdx)
mcdi = cdx_mcdi_if(cdx);
mcdi->cdx = cdx;
-#ifdef CONFIG_MCDI_LOGGING
- mcdi->logging_buffer = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
- if (!mcdi->logging_buffer)
- goto fail2;
-#endif
mcdi->workqueue = alloc_ordered_workqueue("mcdi_wq", 0);
if (!mcdi->workqueue)
- goto fail3;
+ goto fail2;
mutex_init(&mcdi->iface_lock);
mcdi->mode = MCDI_MODE_EVENTS;
INIT_LIST_HEAD(&mcdi->cmd_list);
@@ -135,11 +126,7 @@ int cdx_mcdi_init(struct cdx_mcdi *cdx)
mcdi->new_epoch = true;
return 0;
-fail3:
-#ifdef CONFIG_MCDI_LOGGING
- kfree(mcdi->logging_buffer);
fail2:
-#endif
kfree(cdx->mcdi);
cdx->mcdi = NULL;
fail:
@@ -156,10 +143,6 @@ void cdx_mcdi_finish(struct cdx_mcdi *cdx)
cdx_mcdi_wait_for_cleanup(cdx);
-#ifdef CONFIG_MCDI_LOGGING
- kfree(mcdi->logging_buffer);
-#endif
-
destroy_workqueue(mcdi->workqueue);
kfree(cdx->mcdi);
cdx->mcdi = NULL;
@@ -246,15 +229,9 @@ static void cdx_mcdi_send_request(struct cdx_mcdi *cdx,
size_t hdr_len;
bool not_epoch;
u32 xflags;
-#ifdef CONFIG_MCDI_LOGGING
- char *buf;
-#endif
if (!mcdi)
return;
-#ifdef CONFIG_MCDI_LOGGING
- buf = mcdi->logging_buffer; /* page-sized */
-#endif
mcdi->prev_seq = cmd->seq;
mcdi->seq_held_by[cmd->seq] = cmd;
@@ -281,39 +258,12 @@ static void cdx_mcdi_send_request(struct cdx_mcdi *cdx,
MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_PLATFORM);
hdr_len = 8;
-#ifdef CONFIG_MCDI_LOGGING
- if (!WARN_ON_ONCE(!buf)) {
- const struct cdx_dword *frags[] = { hdr, inbuf };
- const size_t frag_len[] = { hdr_len, round_up(inlen, 4) };
- int bytes = 0;
- int i, j;
-
- for (j = 0; j < ARRAY_SIZE(frags); j++) {
- const struct cdx_dword *frag;
-
- frag = frags[j];
- for (i = 0;
- i < frag_len[j] / 4;
- i++) {
- /*
- * Do not exceed the internal printk limit.
- * The string before that is just over 70 bytes.
- */
- if ((bytes + 75) > LOG_LINE_MAX) {
- pr_info("MCDI RPC REQ:%s \\\n", buf);
- bytes = 0;
- }
- bytes += snprintf(buf + bytes,
- LOG_LINE_MAX - bytes, " %08x",
- le32_to_cpu(frag[i].cdx_u32));
- }
- }
-
- pr_info("MCDI RPC REQ:%s\n", buf);
- }
-#endif
hdr[0].cdx_u32 |= (__force __le32)(cdx_mcdi_payload_csum(hdr, hdr_len, inbuf, inlen) <<
MCDI_HEADER_XFLAGS_LBN);
+
+ print_hex_dump_debug("MCDI REQ HEADER: ", DUMP_PREFIX_NONE, 32, 4, hdr, hdr_len, false);
+ print_hex_dump_debug("MCDI REQ PAYLOAD: ", DUMP_PREFIX_NONE, 32, 4, inbuf, inlen, false);
+
cdx->mcdi_ops->mcdi_request(cdx, hdr, hdr_len, inbuf, inlen);
mcdi->new_epoch = false;
@@ -700,28 +650,10 @@ static bool cdx_mcdi_complete_cmd(struct cdx_mcdi_iface *mcdi,
resp_data_len = 0;
}
-#ifdef CONFIG_MCDI_LOGGING
- if (!WARN_ON_ONCE(!mcdi->logging_buffer)) {
- char *log = mcdi->logging_buffer;
- int i, bytes = 0;
- size_t rlen;
-
- WARN_ON_ONCE(resp_hdr_len % 4);
-
- rlen = resp_hdr_len / 4 + DIV_ROUND_UP(resp_data_len, 4);
-
- for (i = 0; i < rlen; i++) {
- if ((bytes + 75) > LOG_LINE_MAX) {
- pr_info("MCDI RPC RESP:%s \\\n", log);
- bytes = 0;
- }
- bytes += snprintf(log + bytes, LOG_LINE_MAX - bytes,
- " %08x", le32_to_cpu(outbuf[i].cdx_u32));
- }
-
- pr_info("MCDI RPC RESP:%s\n", log);
- }
-#endif
+ print_hex_dump_debug("MCDI RESP HEADER: ", DUMP_PREFIX_NONE, 32, 4,
+ outbuf, resp_hdr_len, false);
+ print_hex_dump_debug("MCDI RESP PAYLOAD: ", DUMP_PREFIX_NONE, 32, 4,
+ outbuf + (resp_hdr_len / 4), resp_data_len, false);
if (error && resp_data_len == 0) {
/* MC rebooted during command */
diff --git a/drivers/cdx/controller/mcdi.h b/drivers/cdx/controller/mcdi.h
index 0bfbeab04e43..54a65e9760ae 100644
--- a/drivers/cdx/controller/mcdi.h
+++ b/drivers/cdx/controller/mcdi.h
@@ -153,8 +153,6 @@ struct cdx_mcdi_cmd {
* @mode: Poll for mcdi completion, or wait for an mcdi_event
* @prev_seq: The last used sequence number
* @new_epoch: Indicates start of day or start of MC reboot recovery
- * @logging_buffer: Buffer that may be used to build MCDI tracing messages
- * @logging_enabled: Whether to trace MCDI
*/
struct cdx_mcdi_iface {
struct cdx_mcdi *cdx;
@@ -170,10 +168,6 @@ struct cdx_mcdi_iface {
enum cdx_mcdi_mode mode;
u8 prev_seq;
bool new_epoch;
-#ifdef CONFIG_MCDI_LOGGING
- bool logging_enabled;
- char *logging_buffer;
-#endif
};
/**
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 801d6c83f896..625af75833fc 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -34,6 +34,7 @@ config TTY_PRINTK_LEVEL
config PRINTER
tristate "Parallel printer support"
depends on PARPORT
+ depends on HAS_IOPORT || PARPORT_NOT_PC
help
If you intend to attach a printer to the parallel port of your Linux
box (as opposed to using a serial printer; if the connector at the
@@ -340,7 +341,7 @@ config NVRAM
config DEVPORT
bool "/dev/port character device"
- depends on ISA || PCI
+ depends on HAS_IOPORT
default y
help
Say Y here if you want to support the /dev/port device. The /dev/port
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index ff429ba02fa4..12143854aeac 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -61,7 +61,6 @@ struct bsr_dev {
static unsigned total_bsr_devs;
static LIST_HEAD(bsr_devs);
-static struct class *bsr_class;
static int bsr_major;
enum {
@@ -108,6 +107,11 @@ static struct attribute *bsr_dev_attrs[] = {
};
ATTRIBUTE_GROUPS(bsr_dev);
+static const struct class bsr_class = {
+ .name = "bsr",
+ .dev_groups = bsr_dev_groups,
+};
+
static int bsr_mmap(struct file *filp, struct vm_area_struct *vma)
{
unsigned long size = vma->vm_end - vma->vm_start;
@@ -244,7 +248,7 @@ static int bsr_add_node(struct device_node *bn)
goto out_err;
}
- cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev,
+ cur->bsr_device = device_create(&bsr_class, NULL, cur->bsr_dev,
cur, "%s", cur->bsr_name);
if (IS_ERR(cur->bsr_device)) {
printk(KERN_ERR "device_create failed for %s\n",
@@ -293,13 +297,9 @@ static int __init bsr_init(void)
if (!np)
goto out_err;
- bsr_class = class_create("bsr");
- if (IS_ERR(bsr_class)) {
- printk(KERN_ERR "class_create() failed for bsr_class\n");
- ret = PTR_ERR(bsr_class);
+ ret = class_register(&bsr_class);
+ if (ret)
goto out_err_1;
- }
- bsr_class->dev_groups = bsr_dev_groups;
ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
bsr_major = MAJOR(bsr_dev);
@@ -320,7 +320,7 @@ static int __init bsr_init(void)
unregister_chrdev_region(bsr_dev, BSR_MAX_DEVS);
out_err_2:
- class_destroy(bsr_class);
+ class_unregister(&bsr_class);
out_err_1:
of_node_put(np);
@@ -335,8 +335,7 @@ static void __exit bsr_exit(void)
bsr_cleanup_devs();
- if (bsr_class)
- class_destroy(bsr_class);
+ class_unregister(&bsr_class);
if (bsr_major)
unregister_chrdev_region(MKDEV(bsr_major, 0), BSR_MAX_DEVS);
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index b3eaf3e5ef2e..bda27e595da1 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -101,7 +101,9 @@ static struct dsp56k_device {
int tx_wsize, rx_wsize;
} dsp56k;
-static struct class *dsp56k_class;
+static const struct class dsp56k_class = {
+ .name = "dsp56k",
+};
static int dsp56k_reset(void)
{
@@ -493,7 +495,7 @@ static const char banner[] __initconst = KERN_INFO "DSP56k driver installed\n";
static int __init dsp56k_init_driver(void)
{
- int err = 0;
+ int err;
if(!MACH_IS_ATARI || !ATARIHW_PRESENT(DSP56K)) {
printk("DSP56k driver: Hardware not present\n");
@@ -504,12 +506,10 @@ static int __init dsp56k_init_driver(void)
printk("DSP56k driver: Unable to register driver\n");
return -ENODEV;
}
- dsp56k_class = class_create("dsp56k");
- if (IS_ERR(dsp56k_class)) {
- err = PTR_ERR(dsp56k_class);
+ err = class_register(&dsp56k_class);
+ if (err)
goto out_chrdev;
- }
- device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL,
+ device_create(&dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL,
"dsp56k");
printk(banner);
@@ -524,8 +524,8 @@ module_init(dsp56k_init_driver);
static void __exit dsp56k_cleanup_driver(void)
{
- device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
- class_destroy(dsp56k_class);
+ device_destroy(&dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
+ class_unregister(&dsp56k_class);
unregister_chrdev(DSP56K_MAJOR, "dsp56k");
}
module_exit(dsp56k_cleanup_driver);
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 4fdf07ae3c54..e0b3786ca51b 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -335,9 +335,20 @@ config HW_RANDOM_HISI
If unsure, say Y.
+config HW_RANDOM_HISTB
+ tristate "Hisilicon STB Random Number Generator support"
+ depends on ARCH_HISI || COMPILE_TEST
+ default ARCH_HISI
+ help
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on Hisilicon Hi37xx SoC.
+
+ To compile this driver as a module, choose M here: the
+ module will be called histb-rng.
+
config HW_RANDOM_ST
tristate "ST Microelectronics HW Random Number Generator support"
- depends on HW_RANDOM && ARCH_STI
+ depends on HW_RANDOM && (ARCH_STI || COMPILE_TEST)
help
This driver provides kernel-side support for the Random Number
Generator hardware found on STi series of SoCs.
@@ -400,9 +411,9 @@ config HW_RANDOM_POLARFIRE_SOC
config HW_RANDOM_MESON
tristate "Amlogic Meson Random Number Generator support"
- depends on HW_RANDOM
depends on ARCH_MESON || COMPILE_TEST
- default y
+ depends on HAS_IOMEM && OF
+ default HW_RANDOM if ARCH_MESON
help
This driver provides kernel-side support for the Random Number
Generator hardware found on Amlogic Meson SoCs.
@@ -427,9 +438,9 @@ config HW_RANDOM_CAVIUM
config HW_RANDOM_MTK
tristate "Mediatek Random Number Generator support"
- depends on HW_RANDOM
depends on ARCH_MEDIATEK || COMPILE_TEST
- default y
+ depends on HAS_IOMEM && OF
+ default HW_RANDOM if ARCH_MEDIATEK
help
This driver provides kernel-side support for the Random Number
Generator hardware found on Mediatek SoCs.
@@ -456,7 +467,8 @@ config HW_RANDOM_S390
config HW_RANDOM_EXYNOS
tristate "Samsung Exynos True Random Number Generator support"
depends on ARCH_EXYNOS || COMPILE_TEST
- default HW_RANDOM
+ depends on HAS_IOMEM
+ default HW_RANDOM if ARCH_EXYNOS
help
This driver provides support for the True Random Number
Generator available in Exynos SoCs.
@@ -483,7 +495,8 @@ config HW_RANDOM_OPTEE
config HW_RANDOM_NPCM
tristate "NPCM Random Number Generator support"
depends on ARCH_NPCM || COMPILE_TEST
- default HW_RANDOM
+ depends on HAS_IOMEM
+ default HW_RANDOM if ARCH_NPCM
help
This driver provides support for the Random Number
Generator hardware available in Nuvoton NPCM SoCs.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 09bde4a0f971..32549a1186dc 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o
+obj-$(CONFIG_HW_RANDOM_HISTB) += histb-rng.o
obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o
diff --git a/drivers/char/hw_random/cn10k-rng.c b/drivers/char/hw_random/cn10k-rng.c
index c1193f85982c..0cd7e1a8e499 100644
--- a/drivers/char/hw_random/cn10k-rng.c
+++ b/drivers/char/hw_random/cn10k-rng.c
@@ -23,14 +23,49 @@
#define RNM_PF_RANDOM 0x400
#define RNM_TRNG_RESULT 0x408
+/* Extended TRNG Read and Status Registers */
+#define RNM_PF_TRNG_DAT 0x1000
+#define RNM_PF_TRNG_RES 0x1008
+
struct cn10k_rng {
void __iomem *reg_base;
struct hwrng ops;
struct pci_dev *pdev;
+ /* Octeon CN10K-A A0/A1, CNF10K-A A0/A1 and CNF10K-B A0/B0
+ * does not support extended TRNG registers
+ */
+ bool extended_trng_regs;
};
#define PLAT_OCTEONTX_RESET_RNG_EBG_HEALTH_STATE 0xc2000b0f
+#define PCI_SUBSYS_DEVID_CN10K_A_RNG 0xB900
+#define PCI_SUBSYS_DEVID_CNF10K_A_RNG 0xBA00
+#define PCI_SUBSYS_DEVID_CNF10K_B_RNG 0xBC00
+
+static bool cn10k_is_extended_trng_regs_supported(struct pci_dev *pdev)
+{
+ /* CN10K-A A0/A1 */
+ if ((pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_RNG) &&
+ (!pdev->revision || (pdev->revision & 0xff) == 0x50 ||
+ (pdev->revision & 0xff) == 0x51))
+ return false;
+
+ /* CNF10K-A A0 */
+ if ((pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_RNG) &&
+ (!pdev->revision || (pdev->revision & 0xff) == 0x60 ||
+ (pdev->revision & 0xff) == 0x61))
+ return false;
+
+ /* CNF10K-B A0/B0 */
+ if ((pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_B_RNG) &&
+ (!pdev->revision || (pdev->revision & 0xff) == 0x70 ||
+ (pdev->revision & 0xff) == 0x74))
+ return false;
+
+ return true;
+}
+
static unsigned long reset_rng_health_state(struct cn10k_rng *rng)
{
struct arm_smccc_res res;
@@ -63,9 +98,23 @@ static int check_rng_health(struct cn10k_rng *rng)
return 0;
}
-static void cn10k_read_trng(struct cn10k_rng *rng, u64 *value)
+/* Returns true when valid data available otherwise return false */
+static bool cn10k_read_trng(struct cn10k_rng *rng, u64 *value)
{
+ u16 retry_count = 0;
u64 upper, lower;
+ u64 status;
+
+ if (rng->extended_trng_regs) {
+ do {
+ *value = readq(rng->reg_base + RNM_PF_TRNG_DAT);
+ if (*value)
+ return true;
+ status = readq(rng->reg_base + RNM_PF_TRNG_RES);
+ if (!status && (retry_count++ > 0x1000))
+ return false;
+ } while (!status);
+ }
*value = readq(rng->reg_base + RNM_PF_RANDOM);
@@ -82,6 +131,7 @@ static void cn10k_read_trng(struct cn10k_rng *rng, u64 *value)
*value = (upper & 0xFFFFFFFF00000000) | (lower & 0xFFFFFFFF);
}
+ return true;
}
static int cn10k_rng_read(struct hwrng *hwrng, void *data,
@@ -100,7 +150,8 @@ static int cn10k_rng_read(struct hwrng *hwrng, void *data,
size = max;
while (size >= 8) {
- cn10k_read_trng(rng, &value);
+ if (!cn10k_read_trng(rng, &value))
+ goto out;
*((u64 *)pos) = value;
size -= 8;
@@ -108,7 +159,8 @@ static int cn10k_rng_read(struct hwrng *hwrng, void *data,
}
if (size > 0) {
- cn10k_read_trng(rng, &value);
+ if (!cn10k_read_trng(rng, &value))
+ goto out;
while (size > 0) {
*pos = (u8)value;
@@ -118,6 +170,7 @@ static int cn10k_rng_read(struct hwrng *hwrng, void *data,
}
}
+out:
return max - size;
}
@@ -144,9 +197,11 @@ static int cn10k_rng_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!rng->ops.name)
return -ENOMEM;
- rng->ops.read = cn10k_rng_read;
+ rng->ops.read = cn10k_rng_read;
rng->ops.priv = (unsigned long)rng;
+ rng->extended_trng_regs = cn10k_is_extended_trng_regs_supported(pdev);
+
reset_rng_health_state(rng);
err = devm_hwrng_register(&pdev->dev, &rng->ops);
diff --git a/drivers/crypto/hisilicon/trng/trng-stb.c b/drivers/char/hw_random/histb-rng.c
index 29200a7d3d81..f652e1135e4b 100644
--- a/drivers/crypto/hisilicon/trng/trng-stb.c
+++ b/drivers/char/hw_random/histb-rng.c
@@ -1,31 +1,27 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
- * Device driver for True RNG in HiSTB SoCs
- *
* Copyright (c) 2023 David Yang
*/
-#include <crypto/internal/rng.h>
-#include <linux/device.h>
#include <linux/err.h>
#include <linux/hw_random.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/platform_device.h>
-#define HISTB_TRNG_CTRL 0x0
+#define RNG_CTRL 0x0
#define RNG_SOURCE GENMASK(1, 0)
#define DROP_ENABLE BIT(5)
#define POST_PROCESS_ENABLE BIT(7)
#define POST_PROCESS_DEPTH GENMASK(15, 8)
-#define HISTB_TRNG_NUMBER 0x4
-#define HISTB_TRNG_STAT 0x8
+#define RNG_NUMBER 0x4
+#define RNG_STAT 0x8
#define DATA_COUNT GENMASK(2, 0) /* max 4 */
-struct histb_trng_priv {
+struct histb_rng_priv {
struct hwrng rng;
void __iomem *base;
};
@@ -35,19 +31,19 @@ struct histb_trng_priv {
* depth = 1 -> ~1ms
* depth = 255 -> ~16ms
*/
-static int histb_trng_wait(void __iomem *base)
+static int histb_rng_wait(void __iomem *base)
{
u32 val;
- return readl_relaxed_poll_timeout(base + HISTB_TRNG_STAT, val,
+ return readl_relaxed_poll_timeout(base + RNG_STAT, val,
val & DATA_COUNT, 1000, 30 * 1000);
}
-static void histb_trng_init(void __iomem *base, unsigned int depth)
+static void histb_rng_init(void __iomem *base, unsigned int depth)
{
u32 val;
- val = readl_relaxed(base + HISTB_TRNG_CTRL);
+ val = readl_relaxed(base + RNG_CTRL);
val &= ~RNG_SOURCE;
val |= 2;
@@ -58,72 +54,72 @@ static void histb_trng_init(void __iomem *base, unsigned int depth)
val |= POST_PROCESS_ENABLE;
val |= DROP_ENABLE;
- writel_relaxed(val, base + HISTB_TRNG_CTRL);
+ writel_relaxed(val, base + RNG_CTRL);
}
-static int histb_trng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+static int histb_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
- struct histb_trng_priv *priv = container_of(rng, typeof(*priv), rng);
+ struct histb_rng_priv *priv = container_of(rng, typeof(*priv), rng);
void __iomem *base = priv->base;
for (int i = 0; i < max; i += sizeof(u32)) {
- if (!(readl_relaxed(base + HISTB_TRNG_STAT) & DATA_COUNT)) {
+ if (!(readl_relaxed(base + RNG_STAT) & DATA_COUNT)) {
if (!wait)
return i;
- if (histb_trng_wait(base)) {
+ if (histb_rng_wait(base)) {
pr_err("failed to generate random number, generated %d\n",
i);
return i ? i : -ETIMEDOUT;
}
}
- *(u32 *) (data + i) = readl_relaxed(base + HISTB_TRNG_NUMBER);
+ *(u32 *) (data + i) = readl_relaxed(base + RNG_NUMBER);
}
return max;
}
-static unsigned int histb_trng_get_depth(void __iomem *base)
+static unsigned int histb_rng_get_depth(void __iomem *base)
{
- return (readl_relaxed(base + HISTB_TRNG_CTRL) & POST_PROCESS_DEPTH) >> 8;
+ return (readl_relaxed(base + RNG_CTRL) & POST_PROCESS_DEPTH) >> 8;
}
static ssize_t
depth_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct histb_trng_priv *priv = dev_get_drvdata(dev);
+ struct histb_rng_priv *priv = dev_get_drvdata(dev);
void __iomem *base = priv->base;
- return sprintf(buf, "%d\n", histb_trng_get_depth(base));
+ return sprintf(buf, "%d\n", histb_rng_get_depth(base));
}
static ssize_t
depth_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct histb_trng_priv *priv = dev_get_drvdata(dev);
+ struct histb_rng_priv *priv = dev_get_drvdata(dev);
void __iomem *base = priv->base;
unsigned int depth;
if (kstrtouint(buf, 0, &depth))
return -ERANGE;
- histb_trng_init(base, depth);
+ histb_rng_init(base, depth);
return count;
}
static DEVICE_ATTR_RW(depth);
-static struct attribute *histb_trng_attrs[] = {
+static struct attribute *histb_rng_attrs[] = {
&dev_attr_depth.attr,
NULL,
};
-ATTRIBUTE_GROUPS(histb_trng);
+ATTRIBUTE_GROUPS(histb_rng);
-static int histb_trng_probe(struct platform_device *pdev)
+static int histb_rng_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct histb_trng_priv *priv;
+ struct histb_rng_priv *priv;
void __iomem *base;
int ret;
@@ -133,17 +129,17 @@ static int histb_trng_probe(struct platform_device *pdev)
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
- return -ENOMEM;
+ return PTR_ERR(base);
- histb_trng_init(base, 144);
- if (histb_trng_wait(base)) {
+ histb_rng_init(base, 144);
+ if (histb_rng_wait(base)) {
dev_err(dev, "cannot bring up device\n");
return -ENODEV;
}
priv->base = base;
priv->rng.name = pdev->name;
- priv->rng.read = histb_trng_read;
+ priv->rng.read = histb_rng_read;
ret = devm_hwrng_register(dev, &priv->rng);
if (ret) {
dev_err(dev, "failed to register hwrng: %d\n", ret);
@@ -155,22 +151,23 @@ static int histb_trng_probe(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id histb_trng_of_match[] = {
- { .compatible = "hisilicon,histb-trng", },
+static const struct of_device_id histb_rng_of_match[] = {
+ { .compatible = "hisilicon,histb-rng", },
{ }
};
+MODULE_DEVICE_TABLE(of, histb_rng_of_match);
-static struct platform_driver histb_trng_driver = {
- .probe = histb_trng_probe,
+static struct platform_driver histb_rng_driver = {
+ .probe = histb_rng_probe,
.driver = {
- .name = "histb-trng",
- .of_match_table = histb_trng_of_match,
- .dev_groups = histb_trng_groups,
+ .name = "histb-rng",
+ .of_match_table = histb_rng_of_match,
+ .dev_groups = histb_rng_groups,
},
};
-module_platform_driver(histb_trng_driver);
+module_platform_driver(histb_rng_driver);
-MODULE_DESCRIPTION("HiSTB True RNG");
+MODULE_DESCRIPTION("Hisilicon STB random number generator driver");
MODULE_LICENSE("Dual MIT/GPL");
MODULE_AUTHOR("David Yang <mmyangfl@gmail.com>");
diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c
index a1c24148ed31..bf07f17f78c8 100644
--- a/drivers/char/hw_random/imx-rngc.c
+++ b/drivers/char/hw_random/imx-rngc.c
@@ -17,6 +17,7 @@
#include <linux/hw_random.h>
#include <linux/completion.h>
#include <linux/io.h>
+#include <linux/bitfield.h>
#define RNGC_VER_ID 0x0000
#define RNGC_COMMAND 0x0004
@@ -26,7 +27,7 @@
#define RNGC_FIFO 0x0014
/* the fields in the ver id register */
-#define RNGC_TYPE_SHIFT 28
+#define RNG_TYPE GENMASK(31, 28)
#define RNGC_VER_MAJ_SHIFT 8
/* the rng_type field */
@@ -34,20 +35,19 @@
#define RNGC_TYPE_RNGC 0x2
-#define RNGC_CMD_CLR_ERR 0x00000020
-#define RNGC_CMD_CLR_INT 0x00000010
-#define RNGC_CMD_SEED 0x00000002
-#define RNGC_CMD_SELF_TEST 0x00000001
+#define RNGC_CMD_CLR_ERR BIT(5)
+#define RNGC_CMD_CLR_INT BIT(4)
+#define RNGC_CMD_SEED BIT(1)
+#define RNGC_CMD_SELF_TEST BIT(0)
-#define RNGC_CTRL_MASK_ERROR 0x00000040
-#define RNGC_CTRL_MASK_DONE 0x00000020
-#define RNGC_CTRL_AUTO_SEED 0x00000010
+#define RNGC_CTRL_MASK_ERROR BIT(6)
+#define RNGC_CTRL_MASK_DONE BIT(5)
+#define RNGC_CTRL_AUTO_SEED BIT(4)
-#define RNGC_STATUS_ERROR 0x00010000
-#define RNGC_STATUS_FIFO_LEVEL_MASK 0x00000f00
-#define RNGC_STATUS_FIFO_LEVEL_SHIFT 8
-#define RNGC_STATUS_SEED_DONE 0x00000020
-#define RNGC_STATUS_ST_DONE 0x00000010
+#define RNGC_STATUS_ERROR BIT(16)
+#define RNGC_STATUS_FIFO_LEVEL_MASK GENMASK(11, 8)
+#define RNGC_STATUS_SEED_DONE BIT(5)
+#define RNGC_STATUS_ST_DONE BIT(4)
#define RNGC_ERROR_STATUS_STAT_ERR 0x00000008
@@ -110,7 +110,7 @@ static int imx_rngc_self_test(struct imx_rngc *rngc)
cmd = readl(rngc->base + RNGC_COMMAND);
writel(cmd | RNGC_CMD_SELF_TEST, rngc->base + RNGC_COMMAND);
- ret = wait_for_completion_timeout(&rngc->rng_op_done, RNGC_TIMEOUT);
+ ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT));
imx_rngc_irq_mask_clear(rngc);
if (!ret)
return -ETIMEDOUT;
@@ -122,7 +122,6 @@ static int imx_rngc_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng);
unsigned int status;
- unsigned int level;
int retval = 0;
while (max >= sizeof(u32)) {
@@ -132,11 +131,7 @@ static int imx_rngc_read(struct hwrng *rng, void *data, size_t max, bool wait)
if (status & RNGC_STATUS_ERROR)
break;
- /* how many random numbers are in FIFO? [0-16] */
- level = (status & RNGC_STATUS_FIFO_LEVEL_MASK) >>
- RNGC_STATUS_FIFO_LEVEL_SHIFT;
-
- if (level) {
+ if (status & RNGC_STATUS_FIFO_LEVEL_MASK) {
/* retrieve a random number from FIFO */
*(u32 *)data = readl(rngc->base + RNGC_FIFO);
@@ -187,9 +182,7 @@ static int imx_rngc_init(struct hwrng *rng)
cmd = readl(rngc->base + RNGC_COMMAND);
writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND);
- ret = wait_for_completion_timeout(&rngc->rng_op_done,
- RNGC_TIMEOUT);
-
+ ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT));
if (!ret) {
ret = -ETIMEDOUT;
goto err;
@@ -229,7 +222,7 @@ static void imx_rngc_cleanup(struct hwrng *rng)
imx_rngc_irq_mask_clear(rngc);
}
-static int imx_rngc_probe(struct platform_device *pdev)
+static int __init imx_rngc_probe(struct platform_device *pdev)
{
struct imx_rngc *rngc;
int ret;
@@ -256,7 +249,7 @@ static int imx_rngc_probe(struct platform_device *pdev)
return irq;
ver_id = readl(rngc->base + RNGC_VER_ID);
- rng_type = ver_id >> RNGC_TYPE_SHIFT;
+ rng_type = FIELD_GET(RNG_TYPE, ver_id);
/*
* This driver supports only RNGC and RNGB. (There's a different
* driver for RNGA.)
@@ -305,7 +298,7 @@ static int imx_rngc_probe(struct platform_device *pdev)
return 0;
}
-static int __maybe_unused imx_rngc_suspend(struct device *dev)
+static int imx_rngc_suspend(struct device *dev)
{
struct imx_rngc *rngc = dev_get_drvdata(dev);
@@ -314,7 +307,7 @@ static int __maybe_unused imx_rngc_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused imx_rngc_resume(struct device *dev)
+static int imx_rngc_resume(struct device *dev)
{
struct imx_rngc *rngc = dev_get_drvdata(dev);
@@ -323,10 +316,10 @@ static int __maybe_unused imx_rngc_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(imx_rngc_pm_ops, imx_rngc_suspend, imx_rngc_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(imx_rngc_pm_ops, imx_rngc_suspend, imx_rngc_resume);
static const struct of_device_id imx_rngc_dt_ids[] = {
- { .compatible = "fsl,imx25-rngb", .data = NULL, },
+ { .compatible = "fsl,imx25-rngb" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_rngc_dt_ids);
@@ -334,7 +327,7 @@ MODULE_DEVICE_TABLE(of, imx_rngc_dt_ids);
static struct platform_driver imx_rngc_driver = {
.driver = {
.name = KBUILD_MODNAME,
- .pm = &imx_rngc_pm_ops,
+ .pm = pm_sleep_ptr(&imx_rngc_pm_ops),
.of_match_table = imx_rngc_dt_ids,
},
};
diff --git a/drivers/char/hw_random/st-rng.c b/drivers/char/hw_random/st-rng.c
index 15ba1e6fae4d..6e9dfac9fc9f 100644
--- a/drivers/char/hw_random/st-rng.c
+++ b/drivers/char/hw_random/st-rng.c
@@ -42,7 +42,6 @@
struct st_rng_data {
void __iomem *base;
- struct clk *clk;
struct hwrng ops;
};
@@ -85,26 +84,18 @@ static int st_rng_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
- clk = devm_clk_get(&pdev->dev, NULL);
+ clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(clk))
return PTR_ERR(clk);
- ret = clk_prepare_enable(clk);
- if (ret)
- return ret;
-
ddata->ops.priv = (unsigned long)ddata;
ddata->ops.read = st_rng_read;
ddata->ops.name = pdev->name;
ddata->base = base;
- ddata->clk = clk;
-
- dev_set_drvdata(&pdev->dev, ddata);
ret = devm_hwrng_register(&pdev->dev, &ddata->ops);
if (ret) {
dev_err(&pdev->dev, "Failed to register HW RNG\n");
- clk_disable_unprepare(clk);
return ret;
}
@@ -113,15 +104,6 @@ static int st_rng_probe(struct platform_device *pdev)
return 0;
}
-static int st_rng_remove(struct platform_device *pdev)
-{
- struct st_rng_data *ddata = dev_get_drvdata(&pdev->dev);
-
- clk_disable_unprepare(ddata->clk);
-
- return 0;
-}
-
static const struct of_device_id st_rng_match[] __maybe_unused = {
{ .compatible = "st,rng" },
{},
@@ -134,7 +116,6 @@ static struct platform_driver st_rng_driver = {
.of_match_table = of_match_ptr(st_rng_match),
},
.probe = st_rng_probe,
- .remove = st_rng_remove
};
module_platform_driver(st_rng_driver);
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index f7690e0f92ed..e41a84e6b4b5 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -4,6 +4,7 @@
* Copyright (C) 2007, 2008 Rusty Russell IBM Corporation
*/
+#include <asm/barrier.h>
#include <linux/err.h>
#include <linux/hw_random.h>
#include <linux/scatterlist.h>
@@ -37,13 +38,13 @@ struct virtrng_info {
static void random_recv_done(struct virtqueue *vq)
{
struct virtrng_info *vi = vq->vdev->priv;
+ unsigned int len;
/* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
- if (!virtqueue_get_buf(vi->vq, &vi->data_avail))
+ if (!virtqueue_get_buf(vi->vq, &len))
return;
- vi->data_idx = 0;
-
+ smp_store_release(&vi->data_avail, len);
complete(&vi->have_data);
}
@@ -52,7 +53,6 @@ static void request_entropy(struct virtrng_info *vi)
struct scatterlist sg;
reinit_completion(&vi->have_data);
- vi->data_avail = 0;
vi->data_idx = 0;
sg_init_one(&sg, vi->data, sizeof(vi->data));
@@ -88,7 +88,7 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
read = 0;
/* copy available data */
- if (vi->data_avail) {
+ if (smp_load_acquire(&vi->data_avail)) {
chunk = copy_data(vi, buf, size);
size -= chunk;
read += chunk;
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 70cfc5140c2c..2f171d14b9b5 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -145,7 +145,9 @@ static struct lp_struct lp_table[LP_NO];
static int port_num[LP_NO];
static unsigned int lp_count = 0;
-static struct class *lp_class;
+static const struct class lp_class = {
+ .name = "printer",
+};
#ifdef CONFIG_LP_CONSOLE
static struct parport *console_registered;
@@ -932,7 +934,7 @@ static int lp_register(int nr, struct parport *port)
if (reset)
lp_reset(nr);
- device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
+ device_create(&lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
"lp%d", nr);
printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name,
@@ -1004,7 +1006,7 @@ static void lp_detach(struct parport *port)
if (port_num[n] == port->number) {
port_num[n] = -1;
lp_count--;
- device_destroy(lp_class, MKDEV(LP_MAJOR, n));
+ device_destroy(&lp_class, MKDEV(LP_MAJOR, n));
parport_unregister_device(lp_table[n].dev);
}
}
@@ -1049,11 +1051,9 @@ static int __init lp_init(void)
return -EIO;
}
- lp_class = class_create("printer");
- if (IS_ERR(lp_class)) {
- err = PTR_ERR(lp_class);
+ err = class_register(&lp_class);
+ if (err)
goto out_reg;
- }
if (parport_register_driver(&lp_driver)) {
printk(KERN_ERR "lp: unable to register with parport\n");
@@ -1072,7 +1072,7 @@ static int __init lp_init(void)
return 0;
out_class:
- class_destroy(lp_class);
+ class_unregister(&lp_class);
out_reg:
unregister_chrdev(LP_MAJOR, "lp");
return err;
@@ -1115,7 +1115,7 @@ static void lp_cleanup_module(void)
#endif
unregister_chrdev(LP_MAJOR, "lp");
- class_destroy(lp_class);
+ class_unregister(&lp_class);
}
__setup("lp=", lp_setup);
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index f494d31f2b98..0fcc8615fb4f 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -90,13 +90,6 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
}
#endif
-#ifndef unxlate_dev_mem_ptr
-#define unxlate_dev_mem_ptr unxlate_dev_mem_ptr
-void __weak unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
-{
-}
-#endif
-
static inline bool should_stop_iteration(void)
{
if (need_resched())
@@ -753,20 +746,23 @@ static char *mem_devnode(const struct device *dev, umode_t *mode)
return NULL;
}
-static struct class *mem_class;
+static const struct class mem_class = {
+ .name = "mem",
+ .devnode = mem_devnode,
+};
static int __init chr_dev_init(void)
{
+ int retval;
int minor;
if (register_chrdev(MEM_MAJOR, "mem", &memory_fops))
printk("unable to get major %d for memory devs\n", MEM_MAJOR);
- mem_class = class_create("mem");
- if (IS_ERR(mem_class))
- return PTR_ERR(mem_class);
+ retval = class_register(&mem_class);
+ if (retval)
+ return retval;
- mem_class->devnode = mem_devnode;
for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) {
if (!devlist[minor].name)
continue;
@@ -777,7 +773,7 @@ static int __init chr_dev_init(void)
if ((minor == DEVPORT_MINOR) && !arch_has_dev_port())
continue;
- device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor),
+ device_create(&mem_class, NULL, MKDEV(MEM_MAJOR, minor),
NULL, devlist[minor].name);
}
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 1c44c29a666e..541edc26ec89 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -168,7 +168,21 @@ fail:
return err;
}
-static struct class *misc_class;
+static char *misc_devnode(const struct device *dev, umode_t *mode)
+{
+ const struct miscdevice *c = dev_get_drvdata(dev);
+
+ if (mode && c->mode)
+ *mode = c->mode;
+ if (c->nodename)
+ return kstrdup(c->nodename, GFP_KERNEL);
+ return NULL;
+}
+
+static const struct class misc_class = {
+ .name = "misc",
+ .devnode = misc_devnode,
+};
static const struct file_operations misc_fops = {
.owner = THIS_MODULE,
@@ -226,7 +240,7 @@ int misc_register(struct miscdevice *misc)
dev = MKDEV(MISC_MAJOR, misc->minor);
misc->this_device =
- device_create_with_groups(misc_class, misc->parent, dev,
+ device_create_with_groups(&misc_class, misc->parent, dev,
misc, misc->groups, "%s", misc->name);
if (IS_ERR(misc->this_device)) {
if (is_dynamic) {
@@ -263,43 +277,30 @@ void misc_deregister(struct miscdevice *misc)
mutex_lock(&misc_mtx);
list_del(&misc->list);
- device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
+ device_destroy(&misc_class, MKDEV(MISC_MAJOR, misc->minor));
misc_minor_free(misc->minor);
mutex_unlock(&misc_mtx);
}
EXPORT_SYMBOL(misc_deregister);
-static char *misc_devnode(const struct device *dev, umode_t *mode)
-{
- const struct miscdevice *c = dev_get_drvdata(dev);
-
- if (mode && c->mode)
- *mode = c->mode;
- if (c->nodename)
- return kstrdup(c->nodename, GFP_KERNEL);
- return NULL;
-}
-
static int __init misc_init(void)
{
int err;
struct proc_dir_entry *ret;
ret = proc_create_seq("misc", 0, NULL, &misc_seq_ops);
- misc_class = class_create("misc");
- err = PTR_ERR(misc_class);
- if (IS_ERR(misc_class))
+ err = class_register(&misc_class);
+ if (err)
goto fail_remove;
err = -EIO;
if (register_chrdev(MISC_MAJOR, "misc", &misc_fops))
goto fail_printk;
- misc_class->devnode = misc_devnode;
return 0;
fail_printk:
pr_err("unable to get major %d for misc devices\n", MISC_MAJOR);
- class_destroy(misc_class);
+ class_unregister(&misc_class);
fail_remove:
if (ret)
remove_proc_entry("misc", NULL);
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 81ed58157b15..4c188e9e477c 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -773,7 +773,9 @@ static __poll_t pp_poll(struct file *file, poll_table *wait)
return mask;
}
-static struct class *ppdev_class;
+static const struct class ppdev_class = {
+ .name = CHRDEV,
+};
static const struct file_operations pp_fops = {
.owner = THIS_MODULE,
@@ -794,7 +796,7 @@ static void pp_attach(struct parport *port)
if (devices[port->number])
return;
- ret = device_create(ppdev_class, port->dev,
+ ret = device_create(&ppdev_class, port->dev,
MKDEV(PP_MAJOR, port->number), NULL,
"parport%d", port->number);
if (IS_ERR(ret)) {
@@ -810,7 +812,7 @@ static void pp_detach(struct parport *port)
if (!devices[port->number])
return;
- device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
+ device_destroy(&ppdev_class, MKDEV(PP_MAJOR, port->number));
devices[port->number] = NULL;
}
@@ -841,11 +843,10 @@ static int __init ppdev_init(void)
pr_warn(CHRDEV ": unable to get major %d\n", PP_MAJOR);
return -EIO;
}
- ppdev_class = class_create(CHRDEV);
- if (IS_ERR(ppdev_class)) {
- err = PTR_ERR(ppdev_class);
+ err = class_register(&ppdev_class);
+ if (err)
goto out_chrdev;
- }
+
err = parport_register_driver(&pp_driver);
if (err < 0) {
pr_warn(CHRDEV ": unable to register with parport\n");
@@ -856,7 +857,7 @@ static int __init ppdev_init(void)
goto out;
out_class:
- class_destroy(ppdev_class);
+ class_unregister(&ppdev_class);
out_chrdev:
unregister_chrdev(PP_MAJOR, CHRDEV);
out:
@@ -867,7 +868,7 @@ static void __exit ppdev_cleanup(void)
{
/* Clean up all parport stuff */
parport_unregister_driver(&pp_driver);
- class_destroy(ppdev_class);
+ class_unregister(&ppdev_class);
unregister_chrdev(PP_MAJOR, CHRDEV);
}
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index b65c809a4e97..680d1ef2a217 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -40,9 +40,6 @@
* across multiple devices and multiple ports per device.
*/
struct ports_driver_data {
- /* Used for registering chardevs */
- struct class *class;
-
/* Used for exporting per-port information to debugfs */
struct dentry *debugfs_dir;
@@ -55,6 +52,10 @@ struct ports_driver_data {
static struct ports_driver_data pdrvdata;
+static const struct class port_class = {
+ .name = "virtio-ports",
+};
+
static DEFINE_SPINLOCK(pdrvdata_lock);
static DECLARE_COMPLETION(early_console_added);
@@ -1399,7 +1400,7 @@ static int add_port(struct ports_device *portdev, u32 id)
"Error %d adding cdev for port %u\n", err, id);
goto free_cdev;
}
- port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev,
+ port->dev = device_create(&port_class, &port->portdev->vdev->dev,
devt, port, "vport%up%u",
port->portdev->vdev->index, id);
if (IS_ERR(port->dev)) {
@@ -1465,7 +1466,7 @@ static int add_port(struct ports_device *portdev, u32 id)
free_inbufs:
free_device:
- device_destroy(pdrvdata.class, port->dev->devt);
+ device_destroy(&port_class, port->dev->devt);
free_cdev:
cdev_del(port->cdev);
free_port:
@@ -1540,7 +1541,7 @@ static void unplug_port(struct port *port)
port->portdev = NULL;
sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
- device_destroy(pdrvdata.class, port->dev->devt);
+ device_destroy(&port_class, port->dev->devt);
cdev_del(port->cdev);
debugfs_remove(port->debugfs_file);
@@ -1935,6 +1936,7 @@ static void remove_vqs(struct ports_device *portdev)
flush_bufs(vq, true);
while ((buf = virtqueue_detach_unused_buf(vq)))
free_buf(buf, true);
+ cond_resched();
}
portdev->vdev->config->del_vqs(portdev->vdev);
kfree(portdev->in_vqs);
@@ -2244,12 +2246,9 @@ static int __init virtio_console_init(void)
{
int err;
- pdrvdata.class = class_create("virtio-ports");
- if (IS_ERR(pdrvdata.class)) {
- err = PTR_ERR(pdrvdata.class);
- pr_err("Error %d creating virtio-ports class\n", err);
+ err = class_register(&port_class);
+ if (err)
return err;
- }
pdrvdata.debugfs_dir = debugfs_create_dir("virtio-ports", NULL);
INIT_LIST_HEAD(&pdrvdata.consoles);
@@ -2271,7 +2270,7 @@ unregister:
unregister_virtio_driver(&virtio_console);
free:
debugfs_remove_recursive(pdrvdata.debugfs_dir);
- class_destroy(pdrvdata.class);
+ class_unregister(&port_class);
return err;
}
@@ -2282,7 +2281,7 @@ static void __exit virtio_console_fini(void)
unregister_virtio_driver(&virtio_console);
unregister_virtio_driver(&virtio_rproc_serial);
- class_destroy(pdrvdata.class);
+ class_unregister(&port_class);
debugfs_remove_recursive(pdrvdata.debugfs_dir);
}
module_init(virtio_console_init);
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index a46f637da959..f60bb6151402 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -113,7 +113,9 @@ static DEFINE_MUTEX(hwicap_mutex);
static bool probed_devices[HWICAP_DEVICES];
static struct mutex icap_sem;
-static struct class *icap_class;
+static const struct class icap_class = {
+ .name = "xilinx_config",
+};
#define UNIMPLEMENTED 0xFFFF
@@ -687,7 +689,7 @@ static int hwicap_setup(struct device *dev, int id,
goto failed3;
}
- device_create(icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id);
+ device_create(&icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id);
return 0; /* success */
failed3:
@@ -721,27 +723,6 @@ static struct hwicap_driver_config fifo_icap_config = {
.reset = fifo_icap_reset,
};
-static int hwicap_remove(struct device *dev)
-{
- struct hwicap_drvdata *drvdata;
-
- drvdata = dev_get_drvdata(dev);
-
- if (!drvdata)
- return 0;
-
- device_destroy(icap_class, drvdata->devt);
- cdev_del(&drvdata->cdev);
- iounmap(drvdata->base_address);
- release_mem_region(drvdata->mem_start, drvdata->mem_size);
- kfree(drvdata);
-
- mutex_lock(&icap_sem);
- probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
- mutex_unlock(&icap_sem);
- return 0; /* success */
-}
-
#ifdef CONFIG_OF
static int hwicap_of_probe(struct platform_device *op,
const struct hwicap_driver_config *config)
@@ -825,9 +806,22 @@ static int hwicap_drv_probe(struct platform_device *pdev)
&buffer_icap_config, regs);
}
-static int hwicap_drv_remove(struct platform_device *pdev)
+static void hwicap_drv_remove(struct platform_device *pdev)
{
- return hwicap_remove(&pdev->dev);
+ struct device *dev = &pdev->dev;
+ struct hwicap_drvdata *drvdata;
+
+ drvdata = dev_get_drvdata(dev);
+
+ device_destroy(&icap_class, drvdata->devt);
+ cdev_del(&drvdata->cdev);
+ iounmap(drvdata->base_address);
+ release_mem_region(drvdata->mem_start, drvdata->mem_size);
+ kfree(drvdata);
+
+ mutex_lock(&icap_sem);
+ probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
+ mutex_unlock(&icap_sem);
}
#ifdef CONFIG_OF
@@ -844,7 +838,7 @@ MODULE_DEVICE_TABLE(of, hwicap_of_match);
static struct platform_driver hwicap_platform_driver = {
.probe = hwicap_drv_probe,
- .remove = hwicap_drv_remove,
+ .remove_new = hwicap_drv_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = hwicap_of_match,
@@ -856,7 +850,9 @@ static int __init hwicap_module_init(void)
dev_t devt;
int retval;
- icap_class = class_create("xilinx_config");
+ retval = class_register(&icap_class);
+ if (retval)
+ return retval;
mutex_init(&icap_sem);
devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
@@ -882,7 +878,7 @@ static void __exit hwicap_module_cleanup(void)
{
dev_t devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
- class_destroy(icap_class);
+ class_unregister(&icap_class);
platform_driver_unregister(&hwicap_platform_driver);
diff --git a/drivers/char/xillybus/xillybus_class.c b/drivers/char/xillybus/xillybus_class.c
index 89926fe9d813..c92a628e389e 100644
--- a/drivers/char/xillybus/xillybus_class.c
+++ b/drivers/char/xillybus/xillybus_class.c
@@ -23,7 +23,9 @@ MODULE_LICENSE("GPL v2");
static DEFINE_MUTEX(unit_mutex);
static LIST_HEAD(unit_list);
-static struct class *xillybus_class;
+static const struct class xillybus_class = {
+ .name = "xillybus",
+};
#define UNITNAMELEN 16
@@ -121,7 +123,7 @@ int xillybus_init_chrdev(struct device *dev,
len -= namelen + 1;
idt += namelen + 1;
- device = device_create(xillybus_class,
+ device = device_create(&xillybus_class,
NULL,
MKDEV(unit->major,
i + unit->lowest_minor),
@@ -152,7 +154,7 @@ int xillybus_init_chrdev(struct device *dev,
unroll_device_create:
for (i--; i >= 0; i--)
- device_destroy(xillybus_class, MKDEV(unit->major,
+ device_destroy(&xillybus_class, MKDEV(unit->major,
i + unit->lowest_minor));
cdev_del(unit->cdev);
@@ -193,7 +195,7 @@ void xillybus_cleanup_chrdev(void *private_data,
for (minor = unit->lowest_minor;
minor < (unit->lowest_minor + unit->num_nodes);
minor++)
- device_destroy(xillybus_class, MKDEV(unit->major, minor));
+ device_destroy(&xillybus_class, MKDEV(unit->major, minor));
cdev_del(unit->cdev);
@@ -242,19 +244,12 @@ EXPORT_SYMBOL(xillybus_find_inode);
static int __init xillybus_class_init(void)
{
- xillybus_class = class_create("xillybus");
-
- if (IS_ERR(xillybus_class)) {
- pr_warn("Failed to register xillybus class\n");
-
- return PTR_ERR(xillybus_class);
- }
- return 0;
+ return class_register(&xillybus_class);
}
static void __exit xillybus_class_exit(void)
{
- class_destroy(xillybus_class);
+ class_unregister(&xillybus_class);
}
module_init(xillybus_class_init);
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c0c8e526a1e9..93f38a8178ba 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -478,6 +478,7 @@ source "drivers/clk/meson/Kconfig"
source "drivers/clk/mstar/Kconfig"
source "drivers/clk/microchip/Kconfig"
source "drivers/clk/mvebu/Kconfig"
+source "drivers/clk/nuvoton/Kconfig"
source "drivers/clk/pistachio/Kconfig"
source "drivers/clk/qcom/Kconfig"
source "drivers/clk/ralink/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 0aebef17edc6..7cb000549b61 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -106,6 +106,7 @@ endif
obj-y += mstar/
obj-y += mvebu/
obj-$(CONFIG_ARCH_MXS) += mxs/
+obj-$(CONFIG_ARCH_MA35) += nuvoton/
obj-$(CONFIG_COMMON_CLK_NXP) += nxp/
obj-$(CONFIG_COMMON_CLK_PISTACHIO) += pistachio/
obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
diff --git a/drivers/clk/actions/owl-composite.c b/drivers/clk/actions/owl-composite.c
index 101706e0c66f..48f177f6ce9c 100644
--- a/drivers/clk/actions/owl-composite.c
+++ b/drivers/clk/actions/owl-composite.c
@@ -53,13 +53,19 @@ static int owl_comp_is_enabled(struct clk_hw *hw)
return owl_gate_clk_is_enabled(common, &comp->gate_hw);
}
-static long owl_comp_div_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int owl_comp_div_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
+ long rate;
- return owl_divider_helper_round_rate(&comp->common, &comp->rate.div_hw,
- rate, parent_rate);
+ rate = owl_divider_helper_round_rate(&comp->common, &comp->rate.div_hw,
+ req->rate, &req->best_parent_rate);
+ if (rate < 0)
+ return rate;
+
+ req->rate = rate;
+ return 0;
}
static unsigned long owl_comp_div_recalc_rate(struct clk_hw *hw,
@@ -80,14 +86,20 @@ static int owl_comp_div_set_rate(struct clk_hw *hw, unsigned long rate,
rate, parent_rate);
}
-static long owl_comp_fact_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int owl_comp_fact_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
+ long rate;
- return owl_factor_helper_round_rate(&comp->common,
- &comp->rate.factor_hw,
- rate, parent_rate);
+ rate = owl_factor_helper_round_rate(&comp->common,
+ &comp->rate.factor_hw,
+ req->rate, &req->best_parent_rate);
+ if (rate < 0)
+ return rate;
+
+ req->rate = rate;
+ return 0;
}
static unsigned long owl_comp_fact_recalc_rate(struct clk_hw *hw,
@@ -152,7 +164,7 @@ const struct clk_ops owl_comp_div_ops = {
.is_enabled = owl_comp_is_enabled,
/* div_ops */
- .round_rate = owl_comp_div_round_rate,
+ .determine_rate = owl_comp_div_determine_rate,
.recalc_rate = owl_comp_div_recalc_rate,
.set_rate = owl_comp_div_set_rate,
};
@@ -169,7 +181,7 @@ const struct clk_ops owl_comp_fact_ops = {
.is_enabled = owl_comp_is_enabled,
/* fact_ops */
- .round_rate = owl_comp_fact_round_rate,
+ .determine_rate = owl_comp_fact_determine_rate,
.recalc_rate = owl_comp_fact_recalc_rate,
.set_rate = owl_comp_fact_set_rate,
};
@@ -189,6 +201,7 @@ const struct clk_ops owl_comp_fix_fact_ops = {
const struct clk_ops owl_comp_pass_ops = {
/* mux_ops */
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = owl_comp_get_parent,
.set_parent = owl_comp_set_parent,
diff --git a/drivers/clk/at91/at91rm9200.c b/drivers/clk/at91/at91rm9200.c
index 0b860126d589..3f19e737ae4d 100644
--- a/drivers/clk/at91/at91rm9200.c
+++ b/drivers/clk/at91/at91rm9200.c
@@ -108,12 +108,12 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
bypass = of_property_read_bool(np, "atmel,osc-bypass");
- hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL,
bypass);
if (IS_ERR(hw))
goto err_free;
- hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc");
+ hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc", NULL);
if (IS_ERR(hw))
goto err_free;
@@ -140,7 +140,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
parent_names[2] = "pllack";
parent_names[3] = "pllbck";
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
- parent_names,
+ parent_names, NULL,
&at91rm9200_master_layout,
&rm9200_mck_characteristics,
&rm9200_mck_lock);
@@ -148,7 +148,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
- "masterck_pres",
+ "masterck_pres", NULL,
&at91rm9200_master_layout,
&rm9200_mck_characteristics,
&rm9200_mck_lock, CLK_SET_RATE_GATE, 0);
@@ -171,7 +171,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
- parent_names, 4, i,
+ parent_names, NULL, 4, i,
&at91rm9200_programmable_layout,
NULL);
if (IS_ERR(hw))
@@ -182,7 +182,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(at91rm9200_systemck); i++) {
hw = at91_clk_register_system(regmap, at91rm9200_systemck[i].n,
- at91rm9200_systemck[i].p,
+ at91rm9200_systemck[i].p, NULL,
at91rm9200_systemck[i].id, 0);
if (IS_ERR(hw))
goto err_free;
@@ -193,7 +193,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(at91rm9200_periphck); i++) {
hw = at91_clk_register_peripheral(regmap,
at91rm9200_periphck[i].n,
- "masterck_div",
+ "masterck_div", NULL,
at91rm9200_periphck[i].id);
if (IS_ERR(hw))
goto err_free;
diff --git a/drivers/clk/at91/at91sam9260.c b/drivers/clk/at91/at91sam9260.c
index b521f470428f..0799a13060ea 100644
--- a/drivers/clk/at91/at91sam9260.c
+++ b/drivers/clk/at91/at91sam9260.c
@@ -363,12 +363,12 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
bypass = of_property_read_bool(np, "atmel,osc-bypass");
- hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL,
bypass);
if (IS_ERR(hw))
goto err_free;
- hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc");
+ hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc", NULL);
if (IS_ERR(hw))
goto err_free;
@@ -416,7 +416,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
parent_names[2] = "pllack";
parent_names[3] = "pllbck";
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
- parent_names,
+ parent_names, NULL,
&at91rm9200_master_layout,
data->mck_characteristics,
&at91sam9260_mck_lock);
@@ -424,7 +424,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
- "masterck_pres",
+ "masterck_pres", NULL,
&at91rm9200_master_layout,
data->mck_characteristics,
&at91sam9260_mck_lock,
@@ -448,7 +448,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
- parent_names, 4, i,
+ parent_names, NULL, 4, i,
&at91rm9200_programmable_layout,
NULL);
if (IS_ERR(hw))
@@ -459,7 +459,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
for (i = 0; i < data->num_sck; i++) {
hw = at91_clk_register_system(regmap, data->sck[i].n,
- data->sck[i].p,
+ data->sck[i].p, NULL,
data->sck[i].id, 0);
if (IS_ERR(hw))
goto err_free;
@@ -470,7 +470,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
for (i = 0; i < data->num_pck; i++) {
hw = at91_clk_register_peripheral(regmap,
data->pck[i].n,
- "masterck_div",
+ "masterck_div", NULL,
data->pck[i].id);
if (IS_ERR(hw))
goto err_free;
diff --git a/drivers/clk/at91/at91sam9g45.c b/drivers/clk/at91/at91sam9g45.c
index 5099669ddcbd..f45a7b80f7d8 100644
--- a/drivers/clk/at91/at91sam9g45.c
+++ b/drivers/clk/at91/at91sam9g45.c
@@ -123,12 +123,12 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
bypass = of_property_read_bool(np, "atmel,osc-bypass");
- hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL,
bypass);
if (IS_ERR(hw))
goto err_free;
- hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc");
+ hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc", NULL);
if (IS_ERR(hw))
goto err_free;
@@ -145,7 +145,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
at91sam9g45_pmc->chws[PMC_PLLACK] = hw;
- hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
+ hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck", NULL);
if (IS_ERR(hw))
goto err_free;
@@ -156,7 +156,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
- parent_names,
+ parent_names, NULL,
&at91rm9200_master_layout,
&mck_characteristics,
&at91sam9g45_mck_lock);
@@ -164,7 +164,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
- "masterck_pres",
+ "masterck_pres", NULL,
&at91rm9200_master_layout,
&mck_characteristics,
&at91sam9g45_mck_lock,
@@ -191,7 +191,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
- parent_names, 5, i,
+ parent_names, NULL, 5, i,
&at91sam9g45_programmable_layout,
NULL);
if (IS_ERR(hw))
@@ -202,7 +202,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(at91sam9g45_systemck); i++) {
hw = at91_clk_register_system(regmap, at91sam9g45_systemck[i].n,
- at91sam9g45_systemck[i].p,
+ at91sam9g45_systemck[i].p, NULL,
at91sam9g45_systemck[i].id,
at91sam9g45_systemck[i].flags);
if (IS_ERR(hw))
@@ -214,7 +214,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(at91sam9g45_periphck); i++) {
hw = at91_clk_register_peripheral(regmap,
at91sam9g45_periphck[i].n,
- "masterck_div",
+ "masterck_div", NULL,
at91sam9g45_periphck[i].id);
if (IS_ERR(hw))
goto err_free;
diff --git a/drivers/clk/at91/at91sam9n12.c b/drivers/clk/at91/at91sam9n12.c
index 08a10e12d08d..751786184ae2 100644
--- a/drivers/clk/at91/at91sam9n12.c
+++ b/drivers/clk/at91/at91sam9n12.c
@@ -147,14 +147,14 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
bypass = of_property_read_bool(np, "atmel,osc-bypass");
- hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL,
bypass);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = "main_rc_osc";
parent_names[1] = "main_osc";
- hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+ hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2);
if (IS_ERR(hw))
goto err_free;
@@ -183,7 +183,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
parent_names[2] = "plladivck";
parent_names[3] = "pllbck";
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
- parent_names,
+ parent_names, NULL,
&at91sam9x5_master_layout,
&mck_characteristics,
&at91sam9n12_mck_lock);
@@ -191,7 +191,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
- "masterck_pres",
+ "masterck_pres", NULL,
&at91sam9x5_master_layout,
&mck_characteristics,
&at91sam9n12_mck_lock,
@@ -216,7 +216,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
- parent_names, 5, i,
+ parent_names, NULL, 5, i,
&at91sam9x5_programmable_layout,
NULL);
if (IS_ERR(hw))
@@ -227,7 +227,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(at91sam9n12_systemck); i++) {
hw = at91_clk_register_system(regmap, at91sam9n12_systemck[i].n,
- at91sam9n12_systemck[i].p,
+ at91sam9n12_systemck[i].p, NULL,
at91sam9n12_systemck[i].id,
at91sam9n12_systemck[i].flags);
if (IS_ERR(hw))
@@ -240,7 +240,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&at91sam9n12_pcr_layout,
at91sam9n12_periphck[i].n,
- "masterck_div",
+ "masterck_div", NULL,
at91sam9n12_periphck[i].id,
&range, INT_MIN, 0);
if (IS_ERR(hw))
diff --git a/drivers/clk/at91/at91sam9rl.c b/drivers/clk/at91/at91sam9rl.c
index 1a1b6b2bb0e3..969f809e7d65 100644
--- a/drivers/clk/at91/at91sam9rl.c
+++ b/drivers/clk/at91/at91sam9rl.c
@@ -95,7 +95,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
if (!at91sam9rl_pmc)
return;
- hw = at91_clk_register_rm9200_main(regmap, "mainck", mainxtal_name);
+ hw = at91_clk_register_rm9200_main(regmap, "mainck", mainxtal_name, NULL);
if (IS_ERR(hw))
goto err_free;
@@ -109,7 +109,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
at91sam9rl_pmc->chws[PMC_PLLACK] = hw;
- hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
+ hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck", NULL);
if (IS_ERR(hw))
goto err_free;
@@ -120,7 +120,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
parent_names[2] = "pllack";
parent_names[3] = "utmick";
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
- parent_names,
+ parent_names, NULL,
&at91rm9200_master_layout,
&sam9rl_mck_characteristics,
&sam9rl_mck_lock);
@@ -128,7 +128,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
- "masterck_pres",
+ "masterck_pres", NULL,
&at91rm9200_master_layout,
&sam9rl_mck_characteristics,
&sam9rl_mck_lock, CLK_SET_RATE_GATE, 0);
@@ -148,7 +148,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
- parent_names, 5, i,
+ parent_names, NULL, 5, i,
&at91rm9200_programmable_layout,
NULL);
if (IS_ERR(hw))
@@ -159,7 +159,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(at91sam9rl_systemck); i++) {
hw = at91_clk_register_system(regmap, at91sam9rl_systemck[i].n,
- at91sam9rl_systemck[i].p,
+ at91sam9rl_systemck[i].p, NULL,
at91sam9rl_systemck[i].id, 0);
if (IS_ERR(hw))
goto err_free;
@@ -170,7 +170,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(at91sam9rl_periphck); i++) {
hw = at91_clk_register_peripheral(regmap,
at91sam9rl_periphck[i].n,
- "masterck_div",
+ "masterck_div", NULL,
at91sam9rl_periphck[i].id);
if (IS_ERR(hw))
goto err_free;
diff --git a/drivers/clk/at91/at91sam9x5.c b/drivers/clk/at91/at91sam9x5.c
index 13e589c95907..3b801d12fac0 100644
--- a/drivers/clk/at91/at91sam9x5.c
+++ b/drivers/clk/at91/at91sam9x5.c
@@ -169,14 +169,14 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
bypass = of_property_read_bool(np, "atmel,osc-bypass");
- hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL,
bypass);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = "main_rc_osc";
parent_names[1] = "main_osc";
- hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+ hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2);
if (IS_ERR(hw))
goto err_free;
@@ -193,7 +193,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
at91sam9x5_pmc->chws[PMC_PLLACK] = hw;
- hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
+ hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck", NULL);
if (IS_ERR(hw))
goto err_free;
@@ -204,14 +204,14 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
- parent_names,
+ parent_names, NULL,
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
- "masterck_pres",
+ "masterck_pres", NULL,
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE, 0);
@@ -241,7 +241,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
- parent_names, 5, i,
+ parent_names, NULL, 5, i,
&at91sam9x5_programmable_layout,
NULL);
if (IS_ERR(hw))
@@ -252,7 +252,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
for (i = 0; i < ARRAY_SIZE(at91sam9x5_systemck); i++) {
hw = at91_clk_register_system(regmap, at91sam9x5_systemck[i].n,
- at91sam9x5_systemck[i].p,
+ at91sam9x5_systemck[i].p, NULL,
at91sam9x5_systemck[i].id,
at91sam9x5_systemck[i].flags);
if (IS_ERR(hw))
@@ -263,7 +263,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
if (has_lcdck) {
hw = at91_clk_register_system(regmap, "lcdck", "masterck_div",
- 3, 0);
+ NULL, 3, 0);
if (IS_ERR(hw))
goto err_free;
@@ -274,7 +274,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&at91sam9x5_pcr_layout,
at91sam9x5_periphck[i].n,
- "masterck_div",
+ "masterck_div", NULL,
at91sam9x5_periphck[i].id,
&range, INT_MIN, 0);
if (IS_ERR(hw))
@@ -287,7 +287,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&at91sam9x5_pcr_layout,
extra_pcks[i].n,
- "masterck_div",
+ "masterck_div", NULL,
extra_pcks[i].id,
&range, INT_MIN, 0);
if (IS_ERR(hw))
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
index 943ea67bf135..4b4edeecc889 100644
--- a/drivers/clk/at91/clk-generated.c
+++ b/drivers/clk/at91/clk-generated.c
@@ -319,22 +319,29 @@ struct clk_hw * __init
at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
const struct clk_pcr_layout *layout,
const char *name, const char **parent_names,
+ struct clk_hw **parent_hws,
u32 *mux_table, u8 num_parents, u8 id,
const struct clk_range *range,
int chg_pid)
{
struct clk_generated *gck;
- struct clk_init_data init;
+ struct clk_init_data init = {};
struct clk_hw *hw;
int ret;
+ if (!(parent_names || parent_hws))
+ return ERR_PTR(-ENOMEM);
+
gck = kzalloc(sizeof(*gck), GFP_KERNEL);
if (!gck)
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &generated_ops;
- init.parent_names = parent_names;
+ if (parent_hws)
+ init.parent_hws = (const struct clk_hw **)parent_hws;
+ else
+ init.parent_names = parent_names;
init.num_parents = num_parents;
init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
if (chg_pid >= 0)
diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
index 8601b27c1ae0..9b462becc693 100644
--- a/drivers/clk/at91/clk-main.c
+++ b/drivers/clk/at91/clk-main.c
@@ -152,14 +152,15 @@ struct clk_hw * __init
at91_clk_register_main_osc(struct regmap *regmap,
const char *name,
const char *parent_name,
+ struct clk_parent_data *parent_data,
bool bypass)
{
struct clk_main_osc *osc;
- struct clk_init_data init;
+ struct clk_init_data init = {};
struct clk_hw *hw;
int ret;
- if (!name || !parent_name)
+ if (!name || !(parent_name || parent_data))
return ERR_PTR(-EINVAL);
osc = kzalloc(sizeof(*osc), GFP_KERNEL);
@@ -168,7 +169,10 @@ at91_clk_register_main_osc(struct regmap *regmap,
init.name = name;
init.ops = &main_osc_ops;
- init.parent_names = &parent_name;
+ if (parent_data)
+ init.parent_data = (const struct clk_parent_data *)parent_data;
+ else
+ init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = CLK_IGNORE_UNUSED;
@@ -397,17 +401,18 @@ static const struct clk_ops rm9200_main_ops = {
struct clk_hw * __init
at91_clk_register_rm9200_main(struct regmap *regmap,
const char *name,
- const char *parent_name)
+ const char *parent_name,
+ struct clk_hw *parent_hw)
{
struct clk_rm9200_main *clkmain;
- struct clk_init_data init;
+ struct clk_init_data init = {};
struct clk_hw *hw;
int ret;
if (!name)
return ERR_PTR(-EINVAL);
- if (!parent_name)
+ if (!(parent_name || parent_hw))
return ERR_PTR(-EINVAL);
clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
@@ -416,7 +421,10 @@ at91_clk_register_rm9200_main(struct regmap *regmap,
init.name = name;
init.ops = &rm9200_main_ops;
- init.parent_names = &parent_name;
+ if (parent_hw)
+ init.parent_hws = (const struct clk_hw **)&parent_hw;
+ else
+ init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = 0;
@@ -533,6 +541,7 @@ static const struct clk_ops sam9x5_main_ops = {
.prepare = clk_sam9x5_main_prepare,
.is_prepared = clk_sam9x5_main_is_prepared,
.recalc_rate = clk_sam9x5_main_recalc_rate,
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = clk_sam9x5_main_set_parent,
.get_parent = clk_sam9x5_main_get_parent,
.save_context = clk_sam9x5_main_save_context,
@@ -543,10 +552,11 @@ struct clk_hw * __init
at91_clk_register_sam9x5_main(struct regmap *regmap,
const char *name,
const char **parent_names,
+ struct clk_hw **parent_hws,
int num_parents)
{
struct clk_sam9x5_main *clkmain;
- struct clk_init_data init;
+ struct clk_init_data init = {};
unsigned int status;
struct clk_hw *hw;
int ret;
@@ -554,7 +564,7 @@ at91_clk_register_sam9x5_main(struct regmap *regmap,
if (!name)
return ERR_PTR(-EINVAL);
- if (!parent_names || !num_parents)
+ if (!(parent_hws || parent_names) || !num_parents)
return ERR_PTR(-EINVAL);
clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
@@ -563,7 +573,10 @@ at91_clk_register_sam9x5_main(struct regmap *regmap,
init.name = name;
init.ops = &sam9x5_main_ops;
- init.parent_names = parent_names;
+ if (parent_hws)
+ init.parent_hws = (const struct clk_hw **)parent_hws;
+ else
+ init.parent_names = parent_names;
init.num_parents = num_parents;
init.flags = CLK_SET_PARENT_GATE;
diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
index b7cd1924de52..15c46489ba85 100644
--- a/drivers/clk/at91/clk-master.c
+++ b/drivers/clk/at91/clk-master.c
@@ -473,18 +473,19 @@ static struct clk_hw * __init
at91_clk_register_master_internal(struct regmap *regmap,
const char *name, int num_parents,
const char **parent_names,
+ struct clk_hw **parent_hws,
const struct clk_master_layout *layout,
const struct clk_master_characteristics *characteristics,
const struct clk_ops *ops, spinlock_t *lock, u32 flags)
{
struct clk_master *master;
- struct clk_init_data init;
+ struct clk_init_data init = {};
struct clk_hw *hw;
unsigned int mckr;
unsigned long irqflags;
int ret;
- if (!name || !num_parents || !parent_names || !lock)
+ if (!name || !num_parents || !(parent_names || parent_hws) || !lock)
return ERR_PTR(-EINVAL);
master = kzalloc(sizeof(*master), GFP_KERNEL);
@@ -493,7 +494,10 @@ at91_clk_register_master_internal(struct regmap *regmap,
init.name = name;
init.ops = ops;
- init.parent_names = parent_names;
+ if (parent_hws)
+ init.parent_hws = (const struct clk_hw **)parent_hws;
+ else
+ init.parent_names = parent_names;
init.num_parents = num_parents;
init.flags = flags;
@@ -527,12 +531,13 @@ struct clk_hw * __init
at91_clk_register_master_pres(struct regmap *regmap,
const char *name, int num_parents,
const char **parent_names,
+ struct clk_hw **parent_hws,
const struct clk_master_layout *layout,
const struct clk_master_characteristics *characteristics,
spinlock_t *lock)
{
return at91_clk_register_master_internal(regmap, name, num_parents,
- parent_names, layout,
+ parent_names, parent_hws, layout,
characteristics,
&master_pres_ops,
lock, CLK_SET_RATE_GATE);
@@ -541,7 +546,7 @@ at91_clk_register_master_pres(struct regmap *regmap,
struct clk_hw * __init
at91_clk_register_master_div(struct regmap *regmap,
const char *name, const char *parent_name,
- const struct clk_master_layout *layout,
+ struct clk_hw *parent_hw, const struct clk_master_layout *layout,
const struct clk_master_characteristics *characteristics,
spinlock_t *lock, u32 flags, u32 safe_div)
{
@@ -554,7 +559,8 @@ at91_clk_register_master_div(struct regmap *regmap,
ops = &master_div_ops_chg;
hw = at91_clk_register_master_internal(regmap, name, 1,
- &parent_name, layout,
+ parent_name ? &parent_name : NULL,
+ parent_hw ? &parent_hw : NULL, layout,
characteristics, ops,
lock, flags);
@@ -806,18 +812,19 @@ struct clk_hw * __init
at91_clk_sama7g5_register_master(struct regmap *regmap,
const char *name, int num_parents,
const char **parent_names,
+ struct clk_hw **parent_hws,
u32 *mux_table,
spinlock_t *lock, u8 id,
bool critical, int chg_pid)
{
struct clk_master *master;
struct clk_hw *hw;
- struct clk_init_data init;
+ struct clk_init_data init = {};
unsigned long flags;
unsigned int val;
int ret;
- if (!name || !num_parents || !parent_names || !mux_table ||
+ if (!name || !num_parents || !(parent_names || parent_hws) || !mux_table ||
!lock || id > MASTER_MAX_ID)
return ERR_PTR(-EINVAL);
@@ -827,7 +834,10 @@ at91_clk_sama7g5_register_master(struct regmap *regmap,
init.name = name;
init.ops = &sama7g5_master_ops;
- init.parent_names = parent_names;
+ if (parent_hws)
+ init.parent_hws = (const struct clk_hw **)parent_hws;
+ else
+ init.parent_names = parent_names;
init.num_parents = num_parents;
init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
if (chg_pid >= 0)
diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c
index 93ea685e27f6..c173a44c800a 100644
--- a/drivers/clk/at91/clk-peripheral.c
+++ b/drivers/clk/at91/clk-peripheral.c
@@ -97,14 +97,15 @@ static const struct clk_ops peripheral_ops = {
struct clk_hw * __init
at91_clk_register_peripheral(struct regmap *regmap, const char *name,
- const char *parent_name, u32 id)
+ const char *parent_name, struct clk_hw *parent_hw,
+ u32 id)
{
struct clk_peripheral *periph;
- struct clk_init_data init;
+ struct clk_init_data init = {};
struct clk_hw *hw;
int ret;
- if (!name || !parent_name || id > PERIPHERAL_ID_MAX)
+ if (!name || !(parent_name || parent_hw) || id > PERIPHERAL_ID_MAX)
return ERR_PTR(-EINVAL);
periph = kzalloc(sizeof(*periph), GFP_KERNEL);
@@ -113,7 +114,10 @@ at91_clk_register_peripheral(struct regmap *regmap, const char *name,
init.name = name;
init.ops = &peripheral_ops;
- init.parent_names = &parent_name;
+ if (parent_hw)
+ init.parent_hws = (const struct clk_hw **)&parent_hw;
+ else
+ init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = 0;
@@ -444,15 +448,16 @@ struct clk_hw * __init
at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
const struct clk_pcr_layout *layout,
const char *name, const char *parent_name,
+ struct clk_hw *parent_hw,
u32 id, const struct clk_range *range,
int chg_pid, unsigned long flags)
{
struct clk_sam9x5_peripheral *periph;
- struct clk_init_data init;
+ struct clk_init_data init = {};
struct clk_hw *hw;
int ret;
- if (!name || !parent_name)
+ if (!name || !(parent_name || parent_hw))
return ERR_PTR(-EINVAL);
periph = kzalloc(sizeof(*periph), GFP_KERNEL);
@@ -460,7 +465,10 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
return ERR_PTR(-ENOMEM);
init.name = name;
- init.parent_names = &parent_name;
+ if (parent_hw)
+ init.parent_hws = (const struct clk_hw **)&parent_hw;
+ else
+ init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = flags;
if (chg_pid < 0) {
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index 6c4b259d31d3..1195fb405503 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -215,16 +215,16 @@ static const struct clk_ops programmable_ops = {
struct clk_hw * __init
at91_clk_register_programmable(struct regmap *regmap,
const char *name, const char **parent_names,
- u8 num_parents, u8 id,
+ struct clk_hw **parent_hws, u8 num_parents, u8 id,
const struct clk_programmable_layout *layout,
u32 *mux_table)
{
struct clk_programmable *prog;
struct clk_hw *hw;
- struct clk_init_data init;
+ struct clk_init_data init = {};
int ret;
- if (id > PROG_ID_MAX)
+ if (id > PROG_ID_MAX || !(parent_names || parent_hws))
return ERR_PTR(-EINVAL);
prog = kzalloc(sizeof(*prog), GFP_KERNEL);
@@ -233,7 +233,10 @@ at91_clk_register_programmable(struct regmap *regmap,
init.name = name;
init.ops = &programmable_ops;
- init.parent_names = parent_names;
+ if (parent_hws)
+ init.parent_hws = (const struct clk_hw **)parent_hws;
+ else
+ init.parent_names = parent_names;
init.num_parents = num_parents;
init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c
index 0882ed01d5c2..ff65f7b916f0 100644
--- a/drivers/clk/at91/clk-sam9x60-pll.c
+++ b/drivers/clk/at91/clk-sam9x60-pll.c
@@ -616,7 +616,7 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
{
struct sam9x60_frac *frac;
struct clk_hw *hw;
- struct clk_init_data init;
+ struct clk_init_data init = {};
unsigned long parent_rate, irqflags;
unsigned int val;
int ret;
@@ -629,7 +629,10 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
return ERR_PTR(-ENOMEM);
init.name = name;
- init.parent_names = &parent_name;
+ if (parent_name)
+ init.parent_names = &parent_name;
+ else
+ init.parent_hws = (const struct clk_hw **)&parent_hw;
init.num_parents = 1;
if (flags & CLK_SET_RATE_GATE)
init.ops = &sam9x60_frac_pll_ops;
@@ -692,14 +695,15 @@ free:
struct clk_hw * __init
sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
- const char *name, const char *parent_name, u8 id,
+ const char *name, const char *parent_name,
+ struct clk_hw *parent_hw, u8 id,
const struct clk_pll_characteristics *characteristics,
const struct clk_pll_layout *layout, u32 flags,
u32 safe_div)
{
struct sam9x60_div *div;
struct clk_hw *hw;
- struct clk_init_data init;
+ struct clk_init_data init = {};
unsigned long irqflags;
unsigned int val;
int ret;
@@ -716,7 +720,10 @@ sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
return ERR_PTR(-ENOMEM);
init.name = name;
- init.parent_names = &parent_name;
+ if (parent_hw)
+ init.parent_hws = (const struct clk_hw **)&parent_hw;
+ else
+ init.parent_names = &parent_name;
init.num_parents = 1;
if (flags & CLK_SET_RATE_GATE)
init.ops = &sam9x60_div_pll_ops;
diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c
index 160378438f1b..09c649c8598e 100644
--- a/drivers/clk/at91/clk-smd.c
+++ b/drivers/clk/at91/clk-smd.c
@@ -36,26 +36,31 @@ static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw,
return parent_rate / (smddiv + 1);
}
-static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int at91sam9x5_clk_smd_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
unsigned long div;
unsigned long bestrate;
unsigned long tmp;
- if (rate >= *parent_rate)
- return *parent_rate;
+ if (req->rate >= req->best_parent_rate) {
+ req->rate = req->best_parent_rate;
+ return 0;
+ }
- div = *parent_rate / rate;
- if (div > SMD_MAX_DIV)
- return *parent_rate / (SMD_MAX_DIV + 1);
+ div = req->best_parent_rate / req->rate;
+ if (div > SMD_MAX_DIV) {
+ req->rate = req->best_parent_rate / (SMD_MAX_DIV + 1);
+ return 0;
+ }
- bestrate = *parent_rate / div;
- tmp = *parent_rate / (div + 1);
- if (bestrate - rate > rate - tmp)
+ bestrate = req->best_parent_rate / div;
+ tmp = req->best_parent_rate / (div + 1);
+ if (bestrate - req->rate > req->rate - tmp)
bestrate = tmp;
- return bestrate;
+ req->rate = bestrate;
+ return 0;
}
static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index)
@@ -98,7 +103,7 @@ static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops at91sam9x5_smd_ops = {
.recalc_rate = at91sam9x5_clk_smd_recalc_rate,
- .round_rate = at91sam9x5_clk_smd_round_rate,
+ .determine_rate = at91sam9x5_clk_smd_determine_rate,
.get_parent = at91sam9x5_clk_smd_get_parent,
.set_parent = at91sam9x5_clk_smd_set_parent,
.set_rate = at91sam9x5_clk_smd_set_rate,
diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c
index 10193650429e..90eed39d0785 100644
--- a/drivers/clk/at91/clk-system.c
+++ b/drivers/clk/at91/clk-system.c
@@ -105,14 +105,15 @@ static const struct clk_ops system_ops = {
struct clk_hw * __init
at91_clk_register_system(struct regmap *regmap, const char *name,
- const char *parent_name, u8 id, unsigned long flags)
+ const char *parent_name, struct clk_hw *parent_hw, u8 id,
+ unsigned long flags)
{
struct clk_system *sys;
struct clk_hw *hw;
- struct clk_init_data init;
+ struct clk_init_data init = {};
int ret;
- if (!parent_name || id > SYSTEM_MAX_ID)
+ if (!(parent_name || parent_hw) || id > SYSTEM_MAX_ID)
return ERR_PTR(-EINVAL);
sys = kzalloc(sizeof(*sys), GFP_KERNEL);
@@ -121,7 +122,10 @@ at91_clk_register_system(struct regmap *regmap, const char *name,
init.name = name;
init.ops = &system_ops;
- init.parent_names = &parent_name;
+ if (parent_hw)
+ init.parent_hws = (const struct clk_hw **)&parent_hw;
+ else
+ init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = CLK_SET_RATE_PARENT | flags;
diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c
index a22c10d9a1b9..40c84f5af5e8 100644
--- a/drivers/clk/at91/clk-utmi.c
+++ b/drivers/clk/at91/clk-utmi.c
@@ -144,21 +144,30 @@ static struct clk_hw * __init
at91_clk_register_utmi_internal(struct regmap *regmap_pmc,
struct regmap *regmap_sfr,
const char *name, const char *parent_name,
+ struct clk_hw *parent_hw,
const struct clk_ops *ops, unsigned long flags)
{
struct clk_utmi *utmi;
struct clk_hw *hw;
- struct clk_init_data init;
+ struct clk_init_data init = {};
int ret;
+ if (!(parent_name || parent_hw))
+ return ERR_PTR(-EINVAL);
+
utmi = kzalloc(sizeof(*utmi), GFP_KERNEL);
if (!utmi)
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = ops;
- init.parent_names = parent_name ? &parent_name : NULL;
- init.num_parents = parent_name ? 1 : 0;
+ if (parent_hw) {
+ init.parent_hws = parent_hw ? (const struct clk_hw **)&parent_hw : NULL;
+ init.num_parents = parent_hw ? 1 : 0;
+ } else {
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+ }
init.flags = flags;
utmi->hw.init = &init;
@@ -177,10 +186,11 @@ at91_clk_register_utmi_internal(struct regmap *regmap_pmc,
struct clk_hw * __init
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
- const char *name, const char *parent_name)
+ const char *name, const char *parent_name,
+ struct clk_hw *parent_hw)
{
return at91_clk_register_utmi_internal(regmap_pmc, regmap_sfr, name,
- parent_name, &utmi_ops, CLK_SET_RATE_GATE);
+ parent_name, parent_hw, &utmi_ops, CLK_SET_RATE_GATE);
}
static int clk_utmi_sama7g5_prepare(struct clk_hw *hw)
@@ -279,8 +289,8 @@ static const struct clk_ops sama7g5_utmi_ops = {
struct clk_hw * __init
at91_clk_sama7g5_register_utmi(struct regmap *regmap_pmc, const char *name,
- const char *parent_name)
+ const char *parent_name, struct clk_hw *parent_hw)
{
return at91_clk_register_utmi_internal(regmap_pmc, NULL, name,
- parent_name, &sama7g5_utmi_ops, 0);
+ parent_name, parent_hw, &sama7g5_utmi_ops, 0);
}
diff --git a/drivers/clk/at91/dt-compat.c b/drivers/clk/at91/dt-compat.c
index 97f67e23ef80..a32dc2111b90 100644
--- a/drivers/clk/at91/dt-compat.c
+++ b/drivers/clk/at91/dt-compat.c
@@ -171,7 +171,7 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
&dt_pcr_layout, name,
- parent_names, NULL,
+ parent_names, NULL, NULL,
num_parents, id, &range,
chg_pid);
if (IS_ERR(hw))
@@ -269,7 +269,7 @@ static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
if (IS_ERR(regmap))
return;
- hw = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
+ hw = at91_clk_register_main_osc(regmap, name, parent_name, NULL, bypass);
if (IS_ERR(hw))
return;
@@ -323,7 +323,7 @@ static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
if (IS_ERR(regmap))
return;
- hw = at91_clk_register_rm9200_main(regmap, name, parent_name);
+ hw = at91_clk_register_rm9200_main(regmap, name, parent_name, NULL);
if (IS_ERR(hw))
return;
@@ -354,7 +354,7 @@ static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
of_property_read_string(np, "clock-output-names", &name);
- hw = at91_clk_register_sam9x5_main(regmap, name, parent_names,
+ hw = at91_clk_register_sam9x5_main(regmap, name, parent_names, NULL,
num_parents);
if (IS_ERR(hw))
return;
@@ -420,12 +420,12 @@ of_at91_clk_master_setup(struct device_node *np,
return;
hw = at91_clk_register_master_pres(regmap, "masterck_pres", num_parents,
- parent_names, layout,
+ parent_names, NULL, layout,
characteristics, &mck_lock);
if (IS_ERR(hw))
goto out_free_characteristics;
- hw = at91_clk_register_master_div(regmap, name, "masterck_pres",
+ hw = at91_clk_register_master_div(regmap, name, "masterck_pres", NULL,
layout, characteristics,
&mck_lock, CLK_SET_RATE_GATE, 0);
if (IS_ERR(hw))
@@ -490,7 +490,7 @@ of_at91_clk_periph_setup(struct device_node *np, u8 type)
if (type == PERIPHERAL_AT91RM9200) {
hw = at91_clk_register_peripheral(regmap, name,
- parent_name, id);
+ parent_name, NULL, id);
} else {
struct clk_range range = CLK_RANGE(0, 0);
unsigned long flags = 0;
@@ -512,6 +512,7 @@ of_at91_clk_periph_setup(struct device_node *np, u8 type)
&dt_pcr_layout,
name,
parent_name,
+ NULL,
id, &range,
INT_MIN,
flags);
@@ -769,7 +770,7 @@ of_at91_clk_prog_setup(struct device_node *np,
name = progclknp->name;
hw = at91_clk_register_programmable(regmap, name,
- parent_names, num_parents,
+ parent_names, NULL, num_parents,
id, layout, mux_table);
if (IS_ERR(hw))
continue;
@@ -907,8 +908,8 @@ static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)
if (!strcmp(sysclknp->name, "ddrck"))
flags = CLK_IS_CRITICAL;
- hw = at91_clk_register_system(regmap, name, parent_name, id,
- flags);
+ hw = at91_clk_register_system(regmap, name, parent_name, NULL,
+ id, flags);
if (IS_ERR(hw))
continue;
@@ -1054,7 +1055,7 @@ static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
regmap_sfr = NULL;
}
- hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name);
+ hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name, NULL);
if (IS_ERR(hw))
return;
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index 1b3ca7dd9b57..0f52e80bcd49 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -144,7 +144,8 @@ struct clk_hw * __init
at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
const struct clk_pcr_layout *layout,
const char *name, const char **parent_names,
- u32 *mux_table, u8 num_parents, u8 id,
+ struct clk_hw **parent_hws, u32 *mux_table,
+ u8 num_parents, u8 id,
const struct clk_range *range, int chg_pid);
struct clk_hw * __init
@@ -161,25 +162,29 @@ at91_clk_register_main_rc_osc(struct regmap *regmap, const char *name,
u32 frequency, u32 accuracy);
struct clk_hw * __init
at91_clk_register_main_osc(struct regmap *regmap, const char *name,
- const char *parent_name, bool bypass);
+ const char *parent_name,
+ struct clk_parent_data *parent_data, bool bypass);
struct clk_hw * __init
at91_clk_register_rm9200_main(struct regmap *regmap,
const char *name,
- const char *parent_name);
+ const char *parent_name,
+ struct clk_hw *parent_hw);
struct clk_hw * __init
at91_clk_register_sam9x5_main(struct regmap *regmap, const char *name,
- const char **parent_names, int num_parents);
+ const char **parent_names,
+ struct clk_hw **parent_hws, int num_parents);
struct clk_hw * __init
at91_clk_register_master_pres(struct regmap *regmap, const char *name,
int num_parents, const char **parent_names,
+ struct clk_hw **parent_hws,
const struct clk_master_layout *layout,
const struct clk_master_characteristics *characteristics,
spinlock_t *lock);
struct clk_hw * __init
at91_clk_register_master_div(struct regmap *regmap, const char *name,
- const char *parent_names,
+ const char *parent_names, struct clk_hw *parent_hw,
const struct clk_master_layout *layout,
const struct clk_master_characteristics *characteristics,
spinlock_t *lock, u32 flags, u32 safe_div);
@@ -187,17 +192,20 @@ at91_clk_register_master_div(struct regmap *regmap, const char *name,
struct clk_hw * __init
at91_clk_sama7g5_register_master(struct regmap *regmap,
const char *name, int num_parents,
- const char **parent_names, u32 *mux_table,
+ const char **parent_names,
+ struct clk_hw **parent_hws, u32 *mux_table,
spinlock_t *lock, u8 id, bool critical,
int chg_pid);
struct clk_hw * __init
at91_clk_register_peripheral(struct regmap *regmap, const char *name,
- const char *parent_name, u32 id);
+ const char *parent_name, struct clk_hw *parent_hw,
+ u32 id);
struct clk_hw * __init
at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
const struct clk_pcr_layout *layout,
const char *name, const char *parent_name,
+ struct clk_hw *parent_hw,
u32 id, const struct clk_range *range,
int chg_pid, unsigned long flags);
@@ -212,7 +220,8 @@ at91_clk_register_plldiv(struct regmap *regmap, const char *name,
struct clk_hw * __init
sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
- const char *name, const char *parent_name, u8 id,
+ const char *name, const char *parent_name,
+ struct clk_hw *parent_hw, u8 id,
const struct clk_pll_characteristics *characteristics,
const struct clk_pll_layout *layout, u32 flags,
u32 safe_div);
@@ -226,7 +235,8 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
struct clk_hw * __init
at91_clk_register_programmable(struct regmap *regmap, const char *name,
- const char **parent_names, u8 num_parents, u8 id,
+ const char **parent_names, struct clk_hw **parent_hws,
+ u8 num_parents, u8 id,
const struct clk_programmable_layout *layout,
u32 *mux_table);
@@ -242,7 +252,8 @@ at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
struct clk_hw * __init
at91_clk_register_system(struct regmap *regmap, const char *name,
- const char *parent_name, u8 id, unsigned long flags);
+ const char *parent_name, struct clk_hw *parent_hw,
+ u8 id, unsigned long flags);
struct clk_hw * __init
at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
@@ -259,10 +270,11 @@ at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
struct clk_hw * __init
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
- const char *name, const char *parent_name);
+ const char *name, const char *parent_name,
+ struct clk_hw *parent_hw);
struct clk_hw * __init
at91_clk_sama7g5_register_utmi(struct regmap *regmap, const char *name,
- const char *parent_name);
+ const char *parent_name, struct clk_hw *parent_hw);
#endif /* __PMC_H_ */
diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c
index ac070db58195..e309cbf3cb9a 100644
--- a/drivers/clk/at91/sam9x60.c
+++ b/drivers/clk/at91/sam9x60.c
@@ -219,14 +219,14 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
if (IS_ERR(hw))
goto err_free;
- hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, 0);
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL, 0);
if (IS_ERR(hw))
goto err_free;
main_osc_hw = hw;
parent_names[0] = "main_rc_osc";
parent_names[1] = "main_osc";
- hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+ hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2);
if (IS_ERR(hw))
goto err_free;
@@ -246,7 +246,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
goto err_free;
hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "pllack_divck",
- "pllack_fracck", 0, &plla_characteristics,
+ "pllack_fracck", NULL, 0, &plla_characteristics,
&pll_div_layout,
/*
* This feeds CPU. It should not
@@ -266,7 +266,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
goto err_free;
hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "upllck_divck",
- "upllck_fracck", 1, &upll_characteristics,
+ "upllck_fracck", NULL, 1, &upll_characteristics,
&pll_div_layout,
CLK_SET_RATE_GATE |
CLK_SET_PARENT_GATE |
@@ -280,13 +280,13 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "pllack_divck";
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 3,
- parent_names, &sam9x60_master_layout,
+ parent_names, NULL, &sam9x60_master_layout,
&mck_characteristics, &mck_lock);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
- "masterck_pres", &sam9x60_master_layout,
+ "masterck_pres", NULL, &sam9x60_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE, 0);
if (IS_ERR(hw))
@@ -313,7 +313,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
- parent_names, 6, i,
+ parent_names, NULL, 6, i,
&sam9x60_programmable_layout,
NULL);
if (IS_ERR(hw))
@@ -324,7 +324,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(sam9x60_systemck); i++) {
hw = at91_clk_register_system(regmap, sam9x60_systemck[i].n,
- sam9x60_systemck[i].p,
+ sam9x60_systemck[i].p, NULL,
sam9x60_systemck[i].id,
sam9x60_systemck[i].flags);
if (IS_ERR(hw))
@@ -337,7 +337,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sam9x60_pcr_layout,
sam9x60_periphck[i].n,
- "masterck_div",
+ "masterck_div", NULL,
sam9x60_periphck[i].id,
&range, INT_MIN,
sam9x60_periphck[i].flags);
@@ -351,7 +351,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
&sam9x60_pcr_layout,
sam9x60_gck[i].n,
- parent_names, NULL, 6,
+ parent_names, NULL, NULL, 6,
sam9x60_gck[i].id,
&sam9x60_gck[i].r, INT_MIN);
if (IS_ERR(hw))
diff --git a/drivers/clk/at91/sama5d2.c b/drivers/clk/at91/sama5d2.c
index c0e3e1a4bbf3..c16594fce90c 100644
--- a/drivers/clk/at91/sama5d2.c
+++ b/drivers/clk/at91/sama5d2.c
@@ -202,14 +202,14 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
bypass = of_property_read_bool(np, "atmel,osc-bypass");
- hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL,
bypass);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = "main_rc_osc";
parent_names[1] = "main_osc";
- hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+ hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2);
if (IS_ERR(hw))
goto err_free;
@@ -249,7 +249,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
if (IS_ERR(regmap_sfr))
regmap_sfr = NULL;
- hw = at91_clk_register_utmi(regmap, regmap_sfr, "utmick", "mainck");
+ hw = at91_clk_register_utmi(regmap, regmap_sfr, "utmick", "mainck", NULL);
if (IS_ERR(hw))
goto err_free;
@@ -260,14 +260,14 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
- parent_names,
+ parent_names, NULL,
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
- "masterck_pres",
+ "masterck_pres", NULL,
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE, 0);
@@ -300,7 +300,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
- parent_names, 6, i,
+ parent_names, NULL, 6, i,
&sama5d2_programmable_layout,
NULL);
if (IS_ERR(hw))
@@ -311,7 +311,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(sama5d2_systemck); i++) {
hw = at91_clk_register_system(regmap, sama5d2_systemck[i].n,
- sama5d2_systemck[i].p,
+ sama5d2_systemck[i].p, NULL,
sama5d2_systemck[i].id,
sama5d2_systemck[i].flags);
if (IS_ERR(hw))
@@ -324,7 +324,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama5d2_pcr_layout,
sama5d2_periphck[i].n,
- "masterck_div",
+ "masterck_div", NULL,
sama5d2_periphck[i].id,
&range, INT_MIN,
sama5d2_periphck[i].flags);
@@ -338,7 +338,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama5d2_pcr_layout,
sama5d2_periph32ck[i].n,
- "h32mxck",
+ "h32mxck", NULL,
sama5d2_periph32ck[i].id,
&sama5d2_periph32ck[i].r,
INT_MIN, 0);
@@ -358,7 +358,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
&sama5d2_pcr_layout,
sama5d2_gck[i].n,
- parent_names, NULL, 6,
+ parent_names, NULL, NULL, 6,
sama5d2_gck[i].id,
&sama5d2_gck[i].r,
sama5d2_gck[i].chg_pid);
diff --git a/drivers/clk/at91/sama5d3.c b/drivers/clk/at91/sama5d3.c
index ad6068b884de..522ce6031446 100644
--- a/drivers/clk/at91/sama5d3.c
+++ b/drivers/clk/at91/sama5d3.c
@@ -150,14 +150,14 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
bypass = of_property_read_bool(np, "atmel,osc-bypass");
- hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL,
bypass);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = "main_rc_osc";
parent_names[1] = "main_osc";
- hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+ hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2);
if (IS_ERR(hw))
goto err_free;
@@ -172,7 +172,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
sama5d3_pmc->chws[PMC_PLLACK] = hw;
- hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
+ hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck", NULL);
if (IS_ERR(hw))
goto err_free;
@@ -183,14 +183,14 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
- parent_names,
+ parent_names, NULL,
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
- "masterck_pres",
+ "masterck_pres", NULL,
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE, 0);
@@ -220,7 +220,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
- parent_names, 5, i,
+ parent_names, NULL, 5, i,
&at91sam9x5_programmable_layout,
NULL);
if (IS_ERR(hw))
@@ -231,7 +231,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(sama5d3_systemck); i++) {
hw = at91_clk_register_system(regmap, sama5d3_systemck[i].n,
- sama5d3_systemck[i].p,
+ sama5d3_systemck[i].p, NULL,
sama5d3_systemck[i].id,
sama5d3_systemck[i].flags);
if (IS_ERR(hw))
@@ -244,7 +244,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama5d3_pcr_layout,
sama5d3_periphck[i].n,
- "masterck_div",
+ "masterck_div", NULL,
sama5d3_periphck[i].id,
&sama5d3_periphck[i].r,
INT_MIN,
diff --git a/drivers/clk/at91/sama5d4.c b/drivers/clk/at91/sama5d4.c
index e876ec971a39..160c0bddb6a3 100644
--- a/drivers/clk/at91/sama5d4.c
+++ b/drivers/clk/at91/sama5d4.c
@@ -165,14 +165,14 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
bypass = of_property_read_bool(np, "atmel,osc-bypass");
- hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL,
bypass);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = "main_rc_osc";
parent_names[1] = "main_osc";
- hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+ hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2);
if (IS_ERR(hw))
goto err_free;
@@ -187,7 +187,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
sama5d4_pmc->chws[PMC_PLLACK] = hw;
- hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
+ hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck", NULL);
if (IS_ERR(hw))
goto err_free;
@@ -198,14 +198,14 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
- parent_names,
+ parent_names, NULL,
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
- "masterck_pres",
+ "masterck_pres", NULL,
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE, 0);
@@ -243,7 +243,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
- parent_names, 5, i,
+ parent_names, NULL, 5, i,
&at91sam9x5_programmable_layout,
NULL);
if (IS_ERR(hw))
@@ -254,7 +254,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(sama5d4_systemck); i++) {
hw = at91_clk_register_system(regmap, sama5d4_systemck[i].n,
- sama5d4_systemck[i].p,
+ sama5d4_systemck[i].p, NULL,
sama5d4_systemck[i].id,
sama5d4_systemck[i].flags);
if (IS_ERR(hw))
@@ -267,7 +267,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama5d4_pcr_layout,
sama5d4_periphck[i].n,
- "masterck_div",
+ "masterck_div", NULL,
sama5d4_periphck[i].id,
&range, INT_MIN,
sama5d4_periphck[i].flags);
@@ -281,7 +281,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama5d4_pcr_layout,
sama5d4_periph32ck[i].n,
- "h32mxck",
+ "h32mxck", NULL,
sama5d4_periph32ck[i].id,
&range, INT_MIN, 0);
if (IS_ERR(hw))
diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c
index f135b662f1ff..91b5c6f14819 100644
--- a/drivers/clk/at91/sama7g5.c
+++ b/drivers/clk/at91/sama7g5.c
@@ -57,6 +57,18 @@ enum pll_ids {
};
/*
+ * PLL component identifier
+ * @PLL_COMPID_FRAC: Fractional PLL component identifier
+ * @PLL_COMPID_DIV0: 1st PLL divider component identifier
+ * @PLL_COMPID_DIV1: 2nd PLL divider component identifier
+ */
+enum pll_component_id {
+ PLL_COMPID_FRAC,
+ PLL_COMPID_DIV0,
+ PLL_COMPID_DIV1,
+};
+
+/*
* PLL type identifiers
* @PLL_TYPE_FRAC: fractional PLL identifier
* @PLL_TYPE_DIV: divider PLL identifier
@@ -119,185 +131,233 @@ static const struct clk_pll_characteristics pll_characteristics = {
};
/*
+ * SAMA7G5 PLL possible parents
+ * @SAMA7G5_PLL_PARENT_MAINCK: MAINCK is PLL a parent
+ * @SAMA7G5_PLL_PARENT_MAIN_XTAL: MAIN XTAL is a PLL parent
+ * @SAMA7G5_PLL_PARENT_FRACCK: Frac PLL is a PLL parent (for PLL dividers)
+ */
+enum sama7g5_pll_parent {
+ SAMA7G5_PLL_PARENT_MAINCK,
+ SAMA7G5_PLL_PARENT_MAIN_XTAL,
+ SAMA7G5_PLL_PARENT_FRACCK,
+};
+
+/*
* PLL clocks description
* @n: clock name
- * @p: clock parent
* @l: clock layout
* @c: clock characteristics
+ * @hw: pointer to clk_hw
* @t: clock type
* @f: clock flags
+ * @p: clock parent
* @eid: export index in sama7g5->chws[] array
* @safe_div: intermediate divider need to be set on PRE_RATE_CHANGE
* notification
*/
-static const struct {
+static struct sama7g5_pll {
const char *n;
- const char *p;
const struct clk_pll_layout *l;
const struct clk_pll_characteristics *c;
+ struct clk_hw *hw;
unsigned long f;
+ enum sama7g5_pll_parent p;
u8 t;
u8 eid;
u8 safe_div;
} sama7g5_plls[][PLL_ID_MAX] = {
[PLL_ID_CPU] = {
- { .n = "cpupll_fracck",
- .p = "mainck",
- .l = &pll_layout_frac,
- .c = &cpu_pll_characteristics,
- .t = PLL_TYPE_FRAC,
- /*
- * This feeds cpupll_divpmcck which feeds CPU. It should
- * not be disabled.
- */
- .f = CLK_IS_CRITICAL, },
-
- { .n = "cpupll_divpmcck",
- .p = "cpupll_fracck",
- .l = &pll_layout_divpmc,
- .c = &cpu_pll_characteristics,
- .t = PLL_TYPE_DIV,
- /* This feeds CPU. It should not be disabled. */
- .f = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT,
- .eid = PMC_CPUPLL,
- /*
- * Safe div=15 should be safe even for switching b/w 1GHz and
- * 90MHz (frac pll might go up to 1.2GHz).
- */
- .safe_div = 15, },
+ [PLL_COMPID_FRAC] = {
+ .n = "cpupll_fracck",
+ .p = SAMA7G5_PLL_PARENT_MAINCK,
+ .l = &pll_layout_frac,
+ .c = &cpu_pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ /*
+ * This feeds cpupll_divpmcck which feeds CPU. It should
+ * not be disabled.
+ */
+ .f = CLK_IS_CRITICAL,
+ },
+
+ [PLL_COMPID_DIV0] = {
+ .n = "cpupll_divpmcck",
+ .p = SAMA7G5_PLL_PARENT_FRACCK,
+ .l = &pll_layout_divpmc,
+ .c = &cpu_pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ /* This feeds CPU. It should not be disabled. */
+ .f = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT,
+ .eid = PMC_CPUPLL,
+ /*
+ * Safe div=15 should be safe even for switching b/w 1GHz and
+ * 90MHz (frac pll might go up to 1.2GHz).
+ */
+ .safe_div = 15,
+ },
},
[PLL_ID_SYS] = {
- { .n = "syspll_fracck",
- .p = "mainck",
- .l = &pll_layout_frac,
- .c = &pll_characteristics,
- .t = PLL_TYPE_FRAC,
- /*
- * This feeds syspll_divpmcck which may feed critical parts
- * of the systems like timers. Therefore it should not be
- * disabled.
- */
- .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
-
- { .n = "syspll_divpmcck",
- .p = "syspll_fracck",
- .l = &pll_layout_divpmc,
- .c = &pll_characteristics,
- .t = PLL_TYPE_DIV,
- /*
- * This may feed critical parts of the systems like timers.
- * Therefore it should not be disabled.
- */
- .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
- .eid = PMC_SYSPLL, },
+ [PLL_COMPID_FRAC] = {
+ .n = "syspll_fracck",
+ .p = SAMA7G5_PLL_PARENT_MAINCK,
+ .l = &pll_layout_frac,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ /*
+ * This feeds syspll_divpmcck which may feed critical parts
+ * of the systems like timers. Therefore it should not be
+ * disabled.
+ */
+ .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
+ },
+
+ [PLL_COMPID_DIV0] = {
+ .n = "syspll_divpmcck",
+ .p = SAMA7G5_PLL_PARENT_FRACCK,
+ .l = &pll_layout_divpmc,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ /*
+ * This may feed critical parts of the systems like timers.
+ * Therefore it should not be disabled.
+ */
+ .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
+ .eid = PMC_SYSPLL,
+ },
},
[PLL_ID_DDR] = {
- { .n = "ddrpll_fracck",
- .p = "mainck",
- .l = &pll_layout_frac,
- .c = &pll_characteristics,
- .t = PLL_TYPE_FRAC,
- /*
- * This feeds ddrpll_divpmcck which feeds DDR. It should not
- * be disabled.
- */
- .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
-
- { .n = "ddrpll_divpmcck",
- .p = "ddrpll_fracck",
- .l = &pll_layout_divpmc,
- .c = &pll_characteristics,
- .t = PLL_TYPE_DIV,
- /* This feeds DDR. It should not be disabled. */
- .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
+ [PLL_COMPID_FRAC] = {
+ .n = "ddrpll_fracck",
+ .p = SAMA7G5_PLL_PARENT_MAINCK,
+ .l = &pll_layout_frac,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ /*
+ * This feeds ddrpll_divpmcck which feeds DDR. It should not
+ * be disabled.
+ */
+ .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
+ },
+
+ [PLL_COMPID_DIV0] = {
+ .n = "ddrpll_divpmcck",
+ .p = SAMA7G5_PLL_PARENT_FRACCK,
+ .l = &pll_layout_divpmc,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ /* This feeds DDR. It should not be disabled. */
+ .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
+ },
},
[PLL_ID_IMG] = {
- { .n = "imgpll_fracck",
- .p = "mainck",
- .l = &pll_layout_frac,
- .c = &pll_characteristics,
- .t = PLL_TYPE_FRAC,
- .f = CLK_SET_RATE_GATE, },
-
- { .n = "imgpll_divpmcck",
- .p = "imgpll_fracck",
- .l = &pll_layout_divpmc,
- .c = &pll_characteristics,
- .t = PLL_TYPE_DIV,
- .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
- CLK_SET_RATE_PARENT, },
+ [PLL_COMPID_FRAC] = {
+ .n = "imgpll_fracck",
+ .p = SAMA7G5_PLL_PARENT_MAINCK,
+ .l = &pll_layout_frac,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ .f = CLK_SET_RATE_GATE,
+ },
+
+ [PLL_COMPID_DIV0] = {
+ .n = "imgpll_divpmcck",
+ .p = SAMA7G5_PLL_PARENT_FRACCK,
+ .l = &pll_layout_divpmc,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT,
+ },
},
[PLL_ID_BAUD] = {
- { .n = "baudpll_fracck",
- .p = "mainck",
- .l = &pll_layout_frac,
- .c = &pll_characteristics,
- .t = PLL_TYPE_FRAC,
- .f = CLK_SET_RATE_GATE, },
-
- { .n = "baudpll_divpmcck",
- .p = "baudpll_fracck",
- .l = &pll_layout_divpmc,
- .c = &pll_characteristics,
- .t = PLL_TYPE_DIV,
- .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
- CLK_SET_RATE_PARENT, },
+ [PLL_COMPID_FRAC] = {
+ .n = "baudpll_fracck",
+ .p = SAMA7G5_PLL_PARENT_MAINCK,
+ .l = &pll_layout_frac,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ .f = CLK_SET_RATE_GATE, },
+
+ [PLL_COMPID_DIV0] = {
+ .n = "baudpll_divpmcck",
+ .p = SAMA7G5_PLL_PARENT_FRACCK,
+ .l = &pll_layout_divpmc,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT,
+ },
},
[PLL_ID_AUDIO] = {
- { .n = "audiopll_fracck",
- .p = "main_xtal",
- .l = &pll_layout_frac,
- .c = &pll_characteristics,
- .t = PLL_TYPE_FRAC,
- .f = CLK_SET_RATE_GATE, },
-
- { .n = "audiopll_divpmcck",
- .p = "audiopll_fracck",
- .l = &pll_layout_divpmc,
- .c = &pll_characteristics,
- .t = PLL_TYPE_DIV,
- .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
- CLK_SET_RATE_PARENT,
- .eid = PMC_AUDIOPMCPLL, },
-
- { .n = "audiopll_diviock",
- .p = "audiopll_fracck",
- .l = &pll_layout_divio,
- .c = &pll_characteristics,
- .t = PLL_TYPE_DIV,
- .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
- CLK_SET_RATE_PARENT,
- .eid = PMC_AUDIOIOPLL, },
+ [PLL_COMPID_FRAC] = {
+ .n = "audiopll_fracck",
+ .p = SAMA7G5_PLL_PARENT_MAIN_XTAL,
+ .l = &pll_layout_frac,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ .f = CLK_SET_RATE_GATE,
+ },
+
+ [PLL_COMPID_DIV0] = {
+ .n = "audiopll_divpmcck",
+ .p = SAMA7G5_PLL_PARENT_FRACCK,
+ .l = &pll_layout_divpmc,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT,
+ .eid = PMC_AUDIOPMCPLL,
+ },
+
+ [PLL_COMPID_DIV1] = {
+ .n = "audiopll_diviock",
+ .p = SAMA7G5_PLL_PARENT_FRACCK,
+ .l = &pll_layout_divio,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT,
+ .eid = PMC_AUDIOIOPLL,
+ },
},
[PLL_ID_ETH] = {
- { .n = "ethpll_fracck",
- .p = "main_xtal",
- .l = &pll_layout_frac,
- .c = &pll_characteristics,
- .t = PLL_TYPE_FRAC,
- .f = CLK_SET_RATE_GATE, },
-
- { .n = "ethpll_divpmcck",
- .p = "ethpll_fracck",
- .l = &pll_layout_divpmc,
- .c = &pll_characteristics,
- .t = PLL_TYPE_DIV,
- .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
- CLK_SET_RATE_PARENT, },
+ [PLL_COMPID_FRAC] = {
+ .n = "ethpll_fracck",
+ .p = SAMA7G5_PLL_PARENT_MAIN_XTAL,
+ .l = &pll_layout_frac,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ .f = CLK_SET_RATE_GATE,
+ },
+
+ [PLL_COMPID_DIV0] = {
+ .n = "ethpll_divpmcck",
+ .p = SAMA7G5_PLL_PARENT_FRACCK,
+ .l = &pll_layout_divpmc,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT,
+ },
},
};
+/* Used to create an array entry identifying a PLL by its components. */
+#define PLL_IDS_TO_ARR_ENTRY(_id, _comp) { PLL_ID_##_id, PLL_COMPID_##_comp}
+
/*
* Master clock (MCK[1..4]) description
* @n: clock name
- * @ep: extra parents names array
- * @ep_chg_chg_id: index in parents array that specifies the changeable
+ * @ep: extra parents names array (entry formed by PLL components
+ * identifiers (see enum pll_component_id))
+ * @hw: pointer to clk_hw
+ * @ep_chg_id: index in parents array that specifies the changeable
* parent
* @ep_count: extra parents count
* @ep_mux_table: mux table for extra parents
@@ -305,9 +365,13 @@ static const struct {
* @eid: export index in sama7g5->chws[] array
* @c: true if clock is critical and cannot be disabled
*/
-static const struct {
+static struct {
const char *n;
- const char *ep[4];
+ struct {
+ int pll_id;
+ int pll_compid;
+ } ep[4];
+ struct clk_hw *hw;
int ep_chg_id;
u8 ep_count;
u8 ep_mux_table[4];
@@ -315,9 +379,10 @@ static const struct {
u8 eid;
u8 c;
} sama7g5_mckx[] = {
+ { .n = "mck0", }, /* Dummy entry for MCK0 to store hw in probe. */
{ .n = "mck1",
.id = 1,
- .ep = { "syspll_divpmcck", },
+ .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), },
.ep_mux_table = { 5, },
.ep_count = 1,
.ep_chg_id = INT_MIN,
@@ -326,7 +391,7 @@ static const struct {
{ .n = "mck2",
.id = 2,
- .ep = { "ddrpll_divpmcck", },
+ .ep = { PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), },
.ep_mux_table = { 6, },
.ep_count = 1,
.ep_chg_id = INT_MIN,
@@ -334,14 +399,15 @@ static const struct {
{ .n = "mck3",
.id = 3,
- .ep = { "syspll_divpmcck", "ddrpll_divpmcck", "imgpll_divpmcck", },
+ .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(DDR, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), },
.ep_mux_table = { 5, 6, 7, },
.ep_count = 3,
.ep_chg_id = 5, },
{ .n = "mck4",
.id = 4,
- .ep = { "syspll_divpmcck", },
+ .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), },
.ep_mux_table = { 5, },
.ep_count = 1,
.ep_chg_id = INT_MIN,
@@ -351,120 +417,137 @@ static const struct {
/*
* System clock description
* @n: clock name
- * @p: clock parent name
* @id: clock id
*/
static const struct {
const char *n;
- const char *p;
u8 id;
} sama7g5_systemck[] = {
- { .n = "pck0", .p = "prog0", .id = 8, },
- { .n = "pck1", .p = "prog1", .id = 9, },
- { .n = "pck2", .p = "prog2", .id = 10, },
- { .n = "pck3", .p = "prog3", .id = 11, },
- { .n = "pck4", .p = "prog4", .id = 12, },
- { .n = "pck5", .p = "prog5", .id = 13, },
- { .n = "pck6", .p = "prog6", .id = 14, },
- { .n = "pck7", .p = "prog7", .id = 15, },
+ { .n = "pck0", .id = 8, },
+ { .n = "pck1", .id = 9, },
+ { .n = "pck2", .id = 10, },
+ { .n = "pck3", .id = 11, },
+ { .n = "pck4", .id = 12, },
+ { .n = "pck5", .id = 13, },
+ { .n = "pck6", .id = 14, },
+ { .n = "pck7", .id = 15, },
};
/* Mux table for programmable clocks. */
static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 5, 6, 7, 8, 9, 10, };
/*
+ * Peripheral clock parent hw identifier (used to index in sama7g5_mckx[])
+ * @PCK_PARENT_HW_MCK0: pck parent hw identifier is MCK0
+ * @PCK_PARENT_HW_MCK1: pck parent hw identifier is MCK1
+ * @PCK_PARENT_HW_MCK2: pck parent hw identifier is MCK2
+ * @PCK_PARENT_HW_MCK3: pck parent hw identifier is MCK3
+ * @PCK_PARENT_HW_MCK4: pck parent hw identifier is MCK4
+ * @PCK_PARENT_HW_MAX: max identifier
+ */
+enum sama7g5_pck_parent_hw_id {
+ PCK_PARENT_HW_MCK0,
+ PCK_PARENT_HW_MCK1,
+ PCK_PARENT_HW_MCK2,
+ PCK_PARENT_HW_MCK3,
+ PCK_PARENT_HW_MCK4,
+ PCK_PARENT_HW_MAX,
+};
+
+/*
* Peripheral clock description
* @n: clock name
- * @p: clock parent name
+ * @p: clock parent hw id
* @r: clock range values
* @id: clock id
* @chgp: index in parent array of the changeable parent
*/
-static const struct {
+static struct {
const char *n;
- const char *p;
+ enum sama7g5_pck_parent_hw_id p;
struct clk_range r;
u8 chgp;
u8 id;
} sama7g5_periphck[] = {
- { .n = "pioA_clk", .p = "mck0", .id = 11, },
- { .n = "securam_clk", .p = "mck0", .id = 18, },
- { .n = "sfr_clk", .p = "mck1", .id = 19, },
- { .n = "hsmc_clk", .p = "mck1", .id = 21, },
- { .n = "xdmac0_clk", .p = "mck1", .id = 22, },
- { .n = "xdmac1_clk", .p = "mck1", .id = 23, },
- { .n = "xdmac2_clk", .p = "mck1", .id = 24, },
- { .n = "acc_clk", .p = "mck1", .id = 25, },
- { .n = "aes_clk", .p = "mck1", .id = 27, },
- { .n = "tzaesbasc_clk", .p = "mck1", .id = 28, },
- { .n = "asrc_clk", .p = "mck1", .id = 30, .r = { .max = 200000000, }, },
- { .n = "cpkcc_clk", .p = "mck0", .id = 32, },
- { .n = "csi_clk", .p = "mck3", .id = 33, .r = { .max = 266000000, }, .chgp = 1, },
- { .n = "csi2dc_clk", .p = "mck3", .id = 34, .r = { .max = 266000000, }, .chgp = 1, },
- { .n = "eic_clk", .p = "mck1", .id = 37, },
- { .n = "flex0_clk", .p = "mck1", .id = 38, },
- { .n = "flex1_clk", .p = "mck1", .id = 39, },
- { .n = "flex2_clk", .p = "mck1", .id = 40, },
- { .n = "flex3_clk", .p = "mck1", .id = 41, },
- { .n = "flex4_clk", .p = "mck1", .id = 42, },
- { .n = "flex5_clk", .p = "mck1", .id = 43, },
- { .n = "flex6_clk", .p = "mck1", .id = 44, },
- { .n = "flex7_clk", .p = "mck1", .id = 45, },
- { .n = "flex8_clk", .p = "mck1", .id = 46, },
- { .n = "flex9_clk", .p = "mck1", .id = 47, },
- { .n = "flex10_clk", .p = "mck1", .id = 48, },
- { .n = "flex11_clk", .p = "mck1", .id = 49, },
- { .n = "gmac0_clk", .p = "mck1", .id = 51, },
- { .n = "gmac1_clk", .p = "mck1", .id = 52, },
- { .n = "icm_clk", .p = "mck1", .id = 55, },
- { .n = "isc_clk", .p = "mck3", .id = 56, .r = { .max = 266000000, }, .chgp = 1, },
- { .n = "i2smcc0_clk", .p = "mck1", .id = 57, .r = { .max = 200000000, }, },
- { .n = "i2smcc1_clk", .p = "mck1", .id = 58, .r = { .max = 200000000, }, },
- { .n = "matrix_clk", .p = "mck1", .id = 60, },
- { .n = "mcan0_clk", .p = "mck1", .id = 61, .r = { .max = 200000000, }, },
- { .n = "mcan1_clk", .p = "mck1", .id = 62, .r = { .max = 200000000, }, },
- { .n = "mcan2_clk", .p = "mck1", .id = 63, .r = { .max = 200000000, }, },
- { .n = "mcan3_clk", .p = "mck1", .id = 64, .r = { .max = 200000000, }, },
- { .n = "mcan4_clk", .p = "mck1", .id = 65, .r = { .max = 200000000, }, },
- { .n = "mcan5_clk", .p = "mck1", .id = 66, .r = { .max = 200000000, }, },
- { .n = "pdmc0_clk", .p = "mck1", .id = 68, .r = { .max = 200000000, }, },
- { .n = "pdmc1_clk", .p = "mck1", .id = 69, .r = { .max = 200000000, }, },
- { .n = "pit64b0_clk", .p = "mck1", .id = 70, },
- { .n = "pit64b1_clk", .p = "mck1", .id = 71, },
- { .n = "pit64b2_clk", .p = "mck1", .id = 72, },
- { .n = "pit64b3_clk", .p = "mck1", .id = 73, },
- { .n = "pit64b4_clk", .p = "mck1", .id = 74, },
- { .n = "pit64b5_clk", .p = "mck1", .id = 75, },
- { .n = "pwm_clk", .p = "mck1", .id = 77, },
- { .n = "qspi0_clk", .p = "mck1", .id = 78, },
- { .n = "qspi1_clk", .p = "mck1", .id = 79, },
- { .n = "sdmmc0_clk", .p = "mck1", .id = 80, },
- { .n = "sdmmc1_clk", .p = "mck1", .id = 81, },
- { .n = "sdmmc2_clk", .p = "mck1", .id = 82, },
- { .n = "sha_clk", .p = "mck1", .id = 83, },
- { .n = "spdifrx_clk", .p = "mck1", .id = 84, .r = { .max = 200000000, }, },
- { .n = "spdiftx_clk", .p = "mck1", .id = 85, .r = { .max = 200000000, }, },
- { .n = "ssc0_clk", .p = "mck1", .id = 86, .r = { .max = 200000000, }, },
- { .n = "ssc1_clk", .p = "mck1", .id = 87, .r = { .max = 200000000, }, },
- { .n = "tcb0_ch0_clk", .p = "mck1", .id = 88, .r = { .max = 200000000, }, },
- { .n = "tcb0_ch1_clk", .p = "mck1", .id = 89, .r = { .max = 200000000, }, },
- { .n = "tcb0_ch2_clk", .p = "mck1", .id = 90, .r = { .max = 200000000, }, },
- { .n = "tcb1_ch0_clk", .p = "mck1", .id = 91, .r = { .max = 200000000, }, },
- { .n = "tcb1_ch1_clk", .p = "mck1", .id = 92, .r = { .max = 200000000, }, },
- { .n = "tcb1_ch2_clk", .p = "mck1", .id = 93, .r = { .max = 200000000, }, },
- { .n = "tcpca_clk", .p = "mck1", .id = 94, },
- { .n = "tcpcb_clk", .p = "mck1", .id = 95, },
- { .n = "tdes_clk", .p = "mck1", .id = 96, },
- { .n = "trng_clk", .p = "mck1", .id = 97, },
- { .n = "udphsa_clk", .p = "mck1", .id = 104, },
- { .n = "udphsb_clk", .p = "mck1", .id = 105, },
- { .n = "uhphs_clk", .p = "mck1", .id = 106, },
+ { .n = "pioA_clk", .p = PCK_PARENT_HW_MCK0, .id = 11, },
+ { .n = "securam_clk", .p = PCK_PARENT_HW_MCK0, .id = 18, },
+ { .n = "sfr_clk", .p = PCK_PARENT_HW_MCK1, .id = 19, },
+ { .n = "hsmc_clk", .p = PCK_PARENT_HW_MCK1, .id = 21, },
+ { .n = "xdmac0_clk", .p = PCK_PARENT_HW_MCK1, .id = 22, },
+ { .n = "xdmac1_clk", .p = PCK_PARENT_HW_MCK1, .id = 23, },
+ { .n = "xdmac2_clk", .p = PCK_PARENT_HW_MCK1, .id = 24, },
+ { .n = "acc_clk", .p = PCK_PARENT_HW_MCK1, .id = 25, },
+ { .n = "aes_clk", .p = PCK_PARENT_HW_MCK1, .id = 27, },
+ { .n = "tzaesbasc_clk", .p = PCK_PARENT_HW_MCK1, .id = 28, },
+ { .n = "asrc_clk", .p = PCK_PARENT_HW_MCK1, .id = 30, .r = { .max = 200000000, }, },
+ { .n = "cpkcc_clk", .p = PCK_PARENT_HW_MCK0, .id = 32, },
+ { .n = "csi_clk", .p = PCK_PARENT_HW_MCK3, .id = 33, .r = { .max = 266000000, }, .chgp = 1, },
+ { .n = "csi2dc_clk", .p = PCK_PARENT_HW_MCK3, .id = 34, .r = { .max = 266000000, }, .chgp = 1, },
+ { .n = "eic_clk", .p = PCK_PARENT_HW_MCK1, .id = 37, },
+ { .n = "flex0_clk", .p = PCK_PARENT_HW_MCK1, .id = 38, },
+ { .n = "flex1_clk", .p = PCK_PARENT_HW_MCK1, .id = 39, },
+ { .n = "flex2_clk", .p = PCK_PARENT_HW_MCK1, .id = 40, },
+ { .n = "flex3_clk", .p = PCK_PARENT_HW_MCK1, .id = 41, },
+ { .n = "flex4_clk", .p = PCK_PARENT_HW_MCK1, .id = 42, },
+ { .n = "flex5_clk", .p = PCK_PARENT_HW_MCK1, .id = 43, },
+ { .n = "flex6_clk", .p = PCK_PARENT_HW_MCK1, .id = 44, },
+ { .n = "flex7_clk", .p = PCK_PARENT_HW_MCK1, .id = 45, },
+ { .n = "flex8_clk", .p = PCK_PARENT_HW_MCK1, .id = 46, },
+ { .n = "flex9_clk", .p = PCK_PARENT_HW_MCK1, .id = 47, },
+ { .n = "flex10_clk", .p = PCK_PARENT_HW_MCK1, .id = 48, },
+ { .n = "flex11_clk", .p = PCK_PARENT_HW_MCK1, .id = 49, },
+ { .n = "gmac0_clk", .p = PCK_PARENT_HW_MCK1, .id = 51, },
+ { .n = "gmac1_clk", .p = PCK_PARENT_HW_MCK1, .id = 52, },
+ { .n = "icm_clk", .p = PCK_PARENT_HW_MCK1, .id = 55, },
+ { .n = "isc_clk", .p = PCK_PARENT_HW_MCK3, .id = 56, .r = { .max = 266000000, }, .chgp = 1, },
+ { .n = "i2smcc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 57, .r = { .max = 200000000, }, },
+ { .n = "i2smcc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 58, .r = { .max = 200000000, }, },
+ { .n = "matrix_clk", .p = PCK_PARENT_HW_MCK1, .id = 60, },
+ { .n = "mcan0_clk", .p = PCK_PARENT_HW_MCK1, .id = 61, .r = { .max = 200000000, }, },
+ { .n = "mcan1_clk", .p = PCK_PARENT_HW_MCK1, .id = 62, .r = { .max = 200000000, }, },
+ { .n = "mcan2_clk", .p = PCK_PARENT_HW_MCK1, .id = 63, .r = { .max = 200000000, }, },
+ { .n = "mcan3_clk", .p = PCK_PARENT_HW_MCK1, .id = 64, .r = { .max = 200000000, }, },
+ { .n = "mcan4_clk", .p = PCK_PARENT_HW_MCK1, .id = 65, .r = { .max = 200000000, }, },
+ { .n = "mcan5_clk", .p = PCK_PARENT_HW_MCK1, .id = 66, .r = { .max = 200000000, }, },
+ { .n = "pdmc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 68, .r = { .max = 200000000, }, },
+ { .n = "pdmc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 69, .r = { .max = 200000000, }, },
+ { .n = "pit64b0_clk", .p = PCK_PARENT_HW_MCK1, .id = 70, },
+ { .n = "pit64b1_clk", .p = PCK_PARENT_HW_MCK1, .id = 71, },
+ { .n = "pit64b2_clk", .p = PCK_PARENT_HW_MCK1, .id = 72, },
+ { .n = "pit64b3_clk", .p = PCK_PARENT_HW_MCK1, .id = 73, },
+ { .n = "pit64b4_clk", .p = PCK_PARENT_HW_MCK1, .id = 74, },
+ { .n = "pit64b5_clk", .p = PCK_PARENT_HW_MCK1, .id = 75, },
+ { .n = "pwm_clk", .p = PCK_PARENT_HW_MCK1, .id = 77, },
+ { .n = "qspi0_clk", .p = PCK_PARENT_HW_MCK1, .id = 78, },
+ { .n = "qspi1_clk", .p = PCK_PARENT_HW_MCK1, .id = 79, },
+ { .n = "sdmmc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 80, },
+ { .n = "sdmmc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 81, },
+ { .n = "sdmmc2_clk", .p = PCK_PARENT_HW_MCK1, .id = 82, },
+ { .n = "sha_clk", .p = PCK_PARENT_HW_MCK1, .id = 83, },
+ { .n = "spdifrx_clk", .p = PCK_PARENT_HW_MCK1, .id = 84, .r = { .max = 200000000, }, },
+ { .n = "spdiftx_clk", .p = PCK_PARENT_HW_MCK1, .id = 85, .r = { .max = 200000000, }, },
+ { .n = "ssc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 86, .r = { .max = 200000000, }, },
+ { .n = "ssc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 87, .r = { .max = 200000000, }, },
+ { .n = "tcb0_ch0_clk", .p = PCK_PARENT_HW_MCK1, .id = 88, .r = { .max = 200000000, }, },
+ { .n = "tcb0_ch1_clk", .p = PCK_PARENT_HW_MCK1, .id = 89, .r = { .max = 200000000, }, },
+ { .n = "tcb0_ch2_clk", .p = PCK_PARENT_HW_MCK1, .id = 90, .r = { .max = 200000000, }, },
+ { .n = "tcb1_ch0_clk", .p = PCK_PARENT_HW_MCK1, .id = 91, .r = { .max = 200000000, }, },
+ { .n = "tcb1_ch1_clk", .p = PCK_PARENT_HW_MCK1, .id = 92, .r = { .max = 200000000, }, },
+ { .n = "tcb1_ch2_clk", .p = PCK_PARENT_HW_MCK1, .id = 93, .r = { .max = 200000000, }, },
+ { .n = "tcpca_clk", .p = PCK_PARENT_HW_MCK1, .id = 94, },
+ { .n = "tcpcb_clk", .p = PCK_PARENT_HW_MCK1, .id = 95, },
+ { .n = "tdes_clk", .p = PCK_PARENT_HW_MCK1, .id = 96, },
+ { .n = "trng_clk", .p = PCK_PARENT_HW_MCK1, .id = 97, },
+ { .n = "udphsa_clk", .p = PCK_PARENT_HW_MCK1, .id = 104, },
+ { .n = "udphsb_clk", .p = PCK_PARENT_HW_MCK1, .id = 105, },
+ { .n = "uhphs_clk", .p = PCK_PARENT_HW_MCK1, .id = 106, },
};
/*
* Generic clock description
* @n: clock name
- * @pp: PLL parents
+ * @pp: PLL parents (entry formed by PLL components identifiers
+ * (see enum pll_component_id))
* @pp_mux_table: PLL parents mux table
* @r: clock output range
* @pp_chg_id: id in parent array of changeable PLL parent
@@ -473,7 +556,10 @@ static const struct {
*/
static const struct {
const char *n;
- const char *pp[8];
+ struct {
+ int pll_id;
+ int pll_compid;
+ } pp[8];
const char pp_mux_table[8];
struct clk_range r;
int pp_chg_id;
@@ -483,7 +569,8 @@ static const struct {
{ .n = "adc_gclk",
.id = 26,
.r = { .max = 100000000, },
- .pp = { "syspll_divpmcck", "imgpll_divpmcck", "audiopll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
.pp_mux_table = { 5, 7, 9, },
.pp_count = 3,
.pp_chg_id = INT_MIN, },
@@ -491,7 +578,7 @@ static const struct {
{ .n = "asrc_gclk",
.id = 30,
.r = { .max = 200000000 },
- .pp = { "audiopll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
.pp_mux_table = { 9, },
.pp_count = 1,
.pp_chg_id = 3, },
@@ -499,7 +586,7 @@ static const struct {
{ .n = "csi_gclk",
.id = 33,
.r = { .max = 27000000 },
- .pp = { "ddrpll_divpmcck", "imgpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), },
.pp_mux_table = { 6, 7, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -507,7 +594,7 @@ static const struct {
{ .n = "flex0_gclk",
.id = 38,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -515,7 +602,7 @@ static const struct {
{ .n = "flex1_gclk",
.id = 39,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -523,7 +610,7 @@ static const struct {
{ .n = "flex2_gclk",
.id = 40,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -531,7 +618,7 @@ static const struct {
{ .n = "flex3_gclk",
.id = 41,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -539,7 +626,7 @@ static const struct {
{ .n = "flex4_gclk",
.id = 42,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -547,7 +634,7 @@ static const struct {
{ .n = "flex5_gclk",
.id = 43,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -555,7 +642,7 @@ static const struct {
{ .n = "flex6_gclk",
.id = 44,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -563,7 +650,7 @@ static const struct {
{ .n = "flex7_gclk",
.id = 45,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -571,7 +658,7 @@ static const struct {
{ .n = "flex8_gclk",
.id = 46,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -579,7 +666,7 @@ static const struct {
{ .n = "flex9_gclk",
.id = 47,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -587,7 +674,7 @@ static const struct {
{ .n = "flex10_gclk",
.id = 48,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -595,7 +682,7 @@ static const struct {
{ .n = "flex11_gclk",
.id = 49,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -603,7 +690,7 @@ static const struct {
{ .n = "gmac0_gclk",
.id = 51,
.r = { .max = 125000000 },
- .pp = { "ethpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
.pp_mux_table = { 10, },
.pp_count = 1,
.pp_chg_id = 3, },
@@ -611,7 +698,7 @@ static const struct {
{ .n = "gmac1_gclk",
.id = 52,
.r = { .max = 50000000 },
- .pp = { "ethpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
.pp_mux_table = { 10, },
.pp_count = 1,
.pp_chg_id = INT_MIN, },
@@ -619,7 +706,7 @@ static const struct {
{ .n = "gmac0_tsu_gclk",
.id = 53,
.r = { .max = 300000000 },
- .pp = { "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
.pp_mux_table = { 9, 10, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -627,7 +714,7 @@ static const struct {
{ .n = "gmac1_tsu_gclk",
.id = 54,
.r = { .max = 300000000 },
- .pp = { "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
.pp_mux_table = { 9, 10, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -635,7 +722,7 @@ static const struct {
{ .n = "i2smcc0_gclk",
.id = 57,
.r = { .max = 100000000 },
- .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
.pp_mux_table = { 5, 9, },
.pp_count = 2,
.pp_chg_id = 4, },
@@ -643,7 +730,7 @@ static const struct {
{ .n = "i2smcc1_gclk",
.id = 58,
.r = { .max = 100000000 },
- .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
.pp_mux_table = { 5, 9, },
.pp_count = 2,
.pp_chg_id = 4, },
@@ -651,7 +738,7 @@ static const struct {
{ .n = "mcan0_gclk",
.id = 61,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -659,7 +746,7 @@ static const struct {
{ .n = "mcan1_gclk",
.id = 62,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -667,7 +754,7 @@ static const struct {
{ .n = "mcan2_gclk",
.id = 63,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -675,7 +762,7 @@ static const struct {
{ .n = "mcan3_gclk",
.id = 64,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -683,7 +770,7 @@ static const struct {
{ .n = "mcan4_gclk",
.id = 65,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -691,7 +778,7 @@ static const struct {
{ .n = "mcan5_gclk",
.id = 66,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -699,7 +786,7 @@ static const struct {
{ .n = "pdmc0_gclk",
.id = 68,
.r = { .max = 50000000 },
- .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
.pp_mux_table = { 5, 9, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -707,7 +794,7 @@ static const struct {
{ .n = "pdmc1_gclk",
.id = 69,
.r = { .max = 50000000, },
- .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
.pp_mux_table = { 5, 9, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -715,8 +802,9 @@ static const struct {
{ .n = "pit64b0_gclk",
.id = 70,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
- "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
.pp_mux_table = { 5, 7, 8, 9, 10, },
.pp_count = 5,
.pp_chg_id = INT_MIN, },
@@ -724,8 +812,9 @@ static const struct {
{ .n = "pit64b1_gclk",
.id = 71,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
- "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
.pp_mux_table = { 5, 7, 8, 9, 10, },
.pp_count = 5,
.pp_chg_id = INT_MIN, },
@@ -733,8 +822,9 @@ static const struct {
{ .n = "pit64b2_gclk",
.id = 72,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
- "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
.pp_mux_table = { 5, 7, 8, 9, 10, },
.pp_count = 5,
.pp_chg_id = INT_MIN, },
@@ -742,8 +832,9 @@ static const struct {
{ .n = "pit64b3_gclk",
.id = 73,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
- "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
.pp_mux_table = { 5, 7, 8, 9, 10, },
.pp_count = 5,
.pp_chg_id = INT_MIN, },
@@ -751,8 +842,9 @@ static const struct {
{ .n = "pit64b4_gclk",
.id = 74,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
- "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
.pp_mux_table = { 5, 7, 8, 9, 10, },
.pp_count = 5,
.pp_chg_id = INT_MIN, },
@@ -760,8 +852,9 @@ static const struct {
{ .n = "pit64b5_gclk",
.id = 75,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
- "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
.pp_mux_table = { 5, 7, 8, 9, 10, },
.pp_count = 5,
.pp_chg_id = INT_MIN, },
@@ -769,7 +862,7 @@ static const struct {
{ .n = "qspi0_gclk",
.id = 78,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -777,7 +870,7 @@ static const struct {
{ .n = "qspi1_gclk",
.id = 79,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = INT_MIN, },
@@ -785,7 +878,7 @@ static const struct {
{ .n = "sdmmc0_gclk",
.id = 80,
.r = { .max = 208000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = 4, },
@@ -793,7 +886,7 @@ static const struct {
{ .n = "sdmmc1_gclk",
.id = 81,
.r = { .max = 208000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = 4, },
@@ -801,7 +894,7 @@ static const struct {
{ .n = "sdmmc2_gclk",
.id = 82,
.r = { .max = 208000000 },
- .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },
.pp_mux_table = { 5, 8, },
.pp_count = 2,
.pp_chg_id = 4, },
@@ -809,7 +902,7 @@ static const struct {
{ .n = "spdifrx_gclk",
.id = 84,
.r = { .max = 150000000 },
- .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
.pp_mux_table = { 5, 9, },
.pp_count = 2,
.pp_chg_id = 4, },
@@ -817,7 +910,7 @@ static const struct {
{ .n = "spdiftx_gclk",
.id = 85,
.r = { .max = 25000000 },
- .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },
.pp_mux_table = { 5, 9, },
.pp_count = 2,
.pp_chg_id = 4, },
@@ -825,8 +918,9 @@ static const struct {
{ .n = "tcb0_ch0_gclk",
.id = 88,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
- "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
.pp_mux_table = { 5, 7, 8, 9, 10, },
.pp_count = 5,
.pp_chg_id = INT_MIN, },
@@ -834,8 +928,9 @@ static const struct {
{ .n = "tcb1_ch0_gclk",
.id = 91,
.r = { .max = 200000000 },
- .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
- "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),
+ PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },
.pp_mux_table = { 5, 7, 8, 9, 10, },
.pp_count = 5,
.pp_chg_id = INT_MIN, },
@@ -884,34 +979,25 @@ static const struct clk_pcr_layout sama7g5_pcr_layout = {
static void __init sama7g5_pmc_setup(struct device_node *np)
{
- const char *td_slck_name, *md_slck_name, *mainxtal_name;
+ const char *main_xtal_name = "main_xtal";
struct pmc_data *sama7g5_pmc;
- const char *parent_names[10];
void **alloc_mem = NULL;
int alloc_mem_size = 0;
struct regmap *regmap;
- struct clk_hw *hw;
+ struct clk_hw *hw, *main_rc_hw, *main_osc_hw, *main_xtal_hw;
+ struct clk_hw *td_slck_hw, *md_slck_hw;
+ static struct clk_parent_data parent_data;
+ struct clk_hw *parent_hws[10];
bool bypass;
int i, j;
- i = of_property_match_string(np, "clock-names", "td_slck");
- if (i < 0)
- return;
-
- td_slck_name = of_clk_get_parent_name(np, i);
-
- i = of_property_match_string(np, "clock-names", "md_slck");
- if (i < 0)
- return;
-
- md_slck_name = of_clk_get_parent_name(np, i);
+ td_slck_hw = __clk_get_hw(of_clk_get_by_name(np, "td_slck"));
+ md_slck_hw = __clk_get_hw(of_clk_get_by_name(np, "md_slck"));
+ main_xtal_hw = __clk_get_hw(of_clk_get_by_name(np, main_xtal_name));
- i = of_property_match_string(np, "clock-names", "main_xtal");
- if (i < 0)
+ if (!td_slck_hw || !md_slck_hw || !main_xtal_hw)
return;
- mainxtal_name = of_clk_get_parent_name(np, i);
-
regmap = device_node_to_regmap(np);
if (IS_ERR(regmap))
return;
@@ -929,21 +1015,23 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
if (!alloc_mem)
goto err_free;
- hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
- 50000000);
- if (IS_ERR(hw))
+ main_rc_hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
+ 50000000);
+ if (IS_ERR(main_rc_hw))
goto err_free;
bypass = of_property_read_bool(np, "atmel,osc-bypass");
- hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
- bypass);
- if (IS_ERR(hw))
+ parent_data.name = main_xtal_name;
+ parent_data.fw_name = main_xtal_name;
+ main_osc_hw = at91_clk_register_main_osc(regmap, "main_osc", NULL,
+ &parent_data, bypass);
+ if (IS_ERR(main_osc_hw))
goto err_free;
- parent_names[0] = "main_rc_osc";
- parent_names[1] = "main_osc";
- hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+ parent_hws[0] = main_rc_hw;
+ parent_hws[1] = main_osc_hw;
+ hw = at91_clk_register_sam9x5_main(regmap, "mainck", NULL, parent_hws, 2);
if (IS_ERR(hw))
goto err_free;
@@ -958,15 +1046,22 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
switch (sama7g5_plls[i][j].t) {
case PLL_TYPE_FRAC:
- if (!strcmp(sama7g5_plls[i][j].p, "mainck"))
+ switch (sama7g5_plls[i][j].p) {
+ case SAMA7G5_PLL_PARENT_MAINCK:
parent_hw = sama7g5_pmc->chws[PMC_MAIN];
- else
- parent_hw = __clk_get_hw(of_clk_get_by_name(np,
- sama7g5_plls[i][j].p));
+ break;
+ case SAMA7G5_PLL_PARENT_MAIN_XTAL:
+ parent_hw = main_xtal_hw;
+ break;
+ default:
+ /* Should not happen. */
+ parent_hw = NULL;
+ break;
+ }
hw = sam9x60_clk_register_frac_pll(regmap,
&pmc_pll_lock, sama7g5_plls[i][j].n,
- sama7g5_plls[i][j].p, parent_hw, i,
+ NULL, parent_hw, i,
sama7g5_plls[i][j].c,
sama7g5_plls[i][j].l,
sama7g5_plls[i][j].f);
@@ -975,7 +1070,7 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
case PLL_TYPE_DIV:
hw = sam9x60_clk_register_div_pll(regmap,
&pmc_pll_lock, sama7g5_plls[i][j].n,
- sama7g5_plls[i][j].p, i,
+ NULL, sama7g5_plls[i][0].hw, i,
sama7g5_plls[i][j].c,
sama7g5_plls[i][j].l,
sama7g5_plls[i][j].f,
@@ -989,25 +1084,27 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
if (IS_ERR(hw))
goto err_free;
+ sama7g5_plls[i][j].hw = hw;
if (sama7g5_plls[i][j].eid)
sama7g5_pmc->chws[sama7g5_plls[i][j].eid] = hw;
}
}
- parent_names[0] = "cpupll_divpmcck";
- hw = at91_clk_register_master_div(regmap, "mck0", "cpupll_divpmcck",
+ hw = at91_clk_register_master_div(regmap, "mck0", NULL,
+ sama7g5_plls[PLL_ID_CPU][1].hw,
&mck0_layout, &mck0_characteristics,
&pmc_mck0_lock, CLK_GET_RATE_NOCACHE, 5);
if (IS_ERR(hw))
goto err_free;
- sama7g5_pmc->chws[PMC_MCK] = hw;
+ sama7g5_mckx[PCK_PARENT_HW_MCK0].hw = sama7g5_pmc->chws[PMC_MCK] = hw;
- parent_names[0] = md_slck_name;
- parent_names[1] = td_slck_name;
- parent_names[2] = "mainck";
- for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) {
+ parent_hws[0] = md_slck_hw;
+ parent_hws[1] = td_slck_hw;
+ parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN];
+ for (i = PCK_PARENT_HW_MCK1; i < ARRAY_SIZE(sama7g5_mckx); i++) {
u8 num_parents = 3 + sama7g5_mckx[i].ep_count;
+ struct clk_hw *tmp_parent_hws[8];
u32 *mux_table;
mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
@@ -1018,11 +1115,17 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
SAMA7G5_INIT_TABLE(mux_table, 3);
SAMA7G5_FILL_TABLE(&mux_table[3], sama7g5_mckx[i].ep_mux_table,
sama7g5_mckx[i].ep_count);
- SAMA7G5_FILL_TABLE(&parent_names[3], sama7g5_mckx[i].ep,
+ for (j = 0; j < sama7g5_mckx[i].ep_count; j++) {
+ u8 pll_id = sama7g5_mckx[i].ep[j].pll_id;
+ u8 pll_compid = sama7g5_mckx[i].ep[j].pll_compid;
+
+ tmp_parent_hws[j] = sama7g5_plls[pll_id][pll_compid].hw;
+ }
+ SAMA7G5_FILL_TABLE(&parent_hws[3], tmp_parent_hws,
sama7g5_mckx[i].ep_count);
hw = at91_clk_sama7g5_register_master(regmap, sama7g5_mckx[i].n,
- num_parents, parent_names, mux_table,
+ num_parents, NULL, parent_hws, mux_table,
&pmc_mckX_lock, sama7g5_mckx[i].id,
sama7g5_mckx[i].c,
sama7g5_mckx[i].ep_chg_id);
@@ -1031,31 +1134,32 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
alloc_mem[alloc_mem_size++] = mux_table;
+ sama7g5_mckx[i].hw = hw;
if (sama7g5_mckx[i].eid)
sama7g5_pmc->chws[sama7g5_mckx[i].eid] = hw;
}
- hw = at91_clk_sama7g5_register_utmi(regmap, "utmick", "main_xtal");
+ hw = at91_clk_sama7g5_register_utmi(regmap, "utmick", NULL, main_xtal_hw);
if (IS_ERR(hw))
goto err_free;
sama7g5_pmc->chws[PMC_UTMI] = hw;
- parent_names[0] = md_slck_name;
- parent_names[1] = td_slck_name;
- parent_names[2] = "mainck";
- parent_names[3] = "syspll_divpmcck";
- parent_names[4] = "ddrpll_divpmcck";
- parent_names[5] = "imgpll_divpmcck";
- parent_names[6] = "baudpll_divpmcck";
- parent_names[7] = "audiopll_divpmcck";
- parent_names[8] = "ethpll_divpmcck";
+ parent_hws[0] = md_slck_hw;
+ parent_hws[1] = td_slck_hw;
+ parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN];
+ parent_hws[3] = sama7g5_plls[PLL_ID_SYS][PLL_COMPID_DIV0].hw;
+ parent_hws[4] = sama7g5_plls[PLL_ID_DDR][PLL_COMPID_DIV0].hw;
+ parent_hws[5] = sama7g5_plls[PLL_ID_IMG][PLL_COMPID_DIV0].hw;
+ parent_hws[6] = sama7g5_plls[PLL_ID_BAUD][PLL_COMPID_DIV0].hw;
+ parent_hws[7] = sama7g5_plls[PLL_ID_AUDIO][PLL_COMPID_DIV0].hw;
+ parent_hws[8] = sama7g5_plls[PLL_ID_ETH][PLL_COMPID_DIV0].hw;
for (i = 0; i < 8; i++) {
char name[6];
snprintf(name, sizeof(name), "prog%d", i);
- hw = at91_clk_register_programmable(regmap, name, parent_names,
+ hw = at91_clk_register_programmable(regmap, name, NULL, parent_hws,
9, i,
&programmable_layout,
sama7g5_prog_mux_table);
@@ -1067,7 +1171,7 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) {
hw = at91_clk_register_system(regmap, sama7g5_systemck[i].n,
- sama7g5_systemck[i].p,
+ NULL, sama7g5_pmc->pchws[i],
sama7g5_systemck[i].id, 0);
if (IS_ERR(hw))
goto err_free;
@@ -1079,7 +1183,8 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama7g5_pcr_layout,
sama7g5_periphck[i].n,
- sama7g5_periphck[i].p,
+ NULL,
+ sama7g5_mckx[sama7g5_periphck[i].p].hw,
sama7g5_periphck[i].id,
&sama7g5_periphck[i].r,
sama7g5_periphck[i].chgp ? 0 :
@@ -1090,11 +1195,12 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
sama7g5_pmc->phws[sama7g5_periphck[i].id] = hw;
}
- parent_names[0] = md_slck_name;
- parent_names[1] = td_slck_name;
- parent_names[2] = "mainck";
+ parent_hws[0] = md_slck_hw;
+ parent_hws[1] = td_slck_hw;
+ parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN];
for (i = 0; i < ARRAY_SIZE(sama7g5_gck); i++) {
u8 num_parents = 3 + sama7g5_gck[i].pp_count;
+ struct clk_hw *tmp_parent_hws[8];
u32 *mux_table;
mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
@@ -1105,13 +1211,19 @@ static void __init sama7g5_pmc_setup(struct device_node *np)
SAMA7G5_INIT_TABLE(mux_table, 3);
SAMA7G5_FILL_TABLE(&mux_table[3], sama7g5_gck[i].pp_mux_table,
sama7g5_gck[i].pp_count);
- SAMA7G5_FILL_TABLE(&parent_names[3], sama7g5_gck[i].pp,
+ for (j = 0; j < sama7g5_gck[i].pp_count; j++) {
+ u8 pll_id = sama7g5_gck[i].pp[j].pll_id;
+ u8 pll_compid = sama7g5_gck[i].pp[j].pll_compid;
+
+ tmp_parent_hws[j] = sama7g5_plls[pll_id][pll_compid].hw;
+ }
+ SAMA7G5_FILL_TABLE(&parent_hws[3], tmp_parent_hws,
sama7g5_gck[i].pp_count);
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
&sama7g5_pcr_layout,
- sama7g5_gck[i].n,
- parent_names, mux_table,
+ sama7g5_gck[i].n, NULL,
+ parent_hws, mux_table,
num_parents,
sama7g5_gck[i].id,
&sama7g5_gck[i].r,
diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c
index fdc9b669f8a7..7741d8f3dbee 100644
--- a/drivers/clk/at91/sckc.c
+++ b/drivers/clk/at91/sckc.c
@@ -117,17 +117,17 @@ static const struct clk_ops slow_osc_ops = {
static struct clk_hw * __init
at91_clk_register_slow_osc(void __iomem *sckcr,
const char *name,
- const char *parent_name,
+ const struct clk_parent_data *parent_data,
unsigned long startup,
bool bypass,
const struct clk_slow_bits *bits)
{
struct clk_slow_osc *osc;
struct clk_hw *hw;
- struct clk_init_data init;
+ struct clk_init_data init = {};
int ret;
- if (!sckcr || !name || !parent_name)
+ if (!sckcr || !name || !parent_data)
return ERR_PTR(-EINVAL);
osc = kzalloc(sizeof(*osc), GFP_KERNEL);
@@ -136,7 +136,7 @@ at91_clk_register_slow_osc(void __iomem *sckcr,
init.name = name;
init.ops = &slow_osc_ops;
- init.parent_names = &parent_name;
+ init.parent_data = parent_data;
init.num_parents = 1;
init.flags = CLK_IGNORE_UNUSED;
@@ -310,6 +310,7 @@ static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw)
}
static const struct clk_ops sam9x5_slow_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = clk_sam9x5_slow_set_parent,
.get_parent = clk_sam9x5_slow_get_parent,
};
@@ -317,16 +318,16 @@ static const struct clk_ops sam9x5_slow_ops = {
static struct clk_hw * __init
at91_clk_register_sam9x5_slow(void __iomem *sckcr,
const char *name,
- const char **parent_names,
+ const struct clk_hw **parent_hws,
int num_parents,
const struct clk_slow_bits *bits)
{
struct clk_sam9x5_slow *slowck;
struct clk_hw *hw;
- struct clk_init_data init;
+ struct clk_init_data init = {};
int ret;
- if (!sckcr || !name || !parent_names || !num_parents)
+ if (!sckcr || !name || !parent_hws || !num_parents)
return ERR_PTR(-EINVAL);
slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
@@ -335,7 +336,7 @@ at91_clk_register_sam9x5_slow(void __iomem *sckcr,
init.name = name;
init.ops = &sam9x5_slow_ops;
- init.parent_names = parent_names;
+ init.parent_hws = parent_hws;
init.num_parents = num_parents;
init.flags = 0;
@@ -366,18 +367,21 @@ static void __init at91sam9x5_sckc_register(struct device_node *np,
unsigned int rc_osc_startup_us,
const struct clk_slow_bits *bits)
{
- const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
void __iomem *regbase = of_iomap(np, 0);
struct device_node *child = NULL;
const char *xtal_name;
struct clk_hw *slow_rc, *slow_osc, *slowck;
+ static struct clk_parent_data parent_data = {
+ .name = "slow_xtal",
+ };
+ const struct clk_hw *parent_hws[2];
bool bypass;
int ret;
if (!regbase)
return;
- slow_rc = at91_clk_register_slow_rc_osc(regbase, parent_names[0],
+ slow_rc = at91_clk_register_slow_rc_osc(regbase, "slow_rc_osc",
32768, 50000000,
rc_osc_startup_us, bits);
if (IS_ERR(slow_rc))
@@ -401,12 +405,16 @@ static void __init at91sam9x5_sckc_register(struct device_node *np,
if (!xtal_name)
goto unregister_slow_rc;
- slow_osc = at91_clk_register_slow_osc(regbase, parent_names[1],
- xtal_name, 1200000, bypass, bits);
+ parent_data.fw_name = xtal_name;
+
+ slow_osc = at91_clk_register_slow_osc(regbase, "slow_osc",
+ &parent_data, 1200000, bypass, bits);
if (IS_ERR(slow_osc))
goto unregister_slow_rc;
- slowck = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names,
+ parent_hws[0] = slow_rc;
+ parent_hws[1] = slow_osc;
+ slowck = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_hws,
2, bits);
if (IS_ERR(slowck))
goto unregister_slow_osc;
@@ -464,14 +472,17 @@ static void __init of_sam9x60_sckc_setup(struct device_node *np)
struct clk_hw_onecell_data *clk_data;
struct clk_hw *slow_rc, *slow_osc;
const char *xtal_name;
- const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
+ const struct clk_hw *parent_hws[2];
+ static struct clk_parent_data parent_data = {
+ .name = "slow_xtal",
+ };
bool bypass;
int ret;
if (!regbase)
return;
- slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL, parent_names[0],
+ slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL, "slow_rc_osc",
NULL, 0, 32768,
93750000);
if (IS_ERR(slow_rc))
@@ -481,9 +492,10 @@ static void __init of_sam9x60_sckc_setup(struct device_node *np)
if (!xtal_name)
goto unregister_slow_rc;
+ parent_data.fw_name = xtal_name;
bypass = of_property_read_bool(np, "atmel,osc-bypass");
- slow_osc = at91_clk_register_slow_osc(regbase, parent_names[1],
- xtal_name, 5000000, bypass,
+ slow_osc = at91_clk_register_slow_osc(regbase, "slow_osc",
+ &parent_data, 5000000, bypass,
&at91sam9x60_bits);
if (IS_ERR(slow_osc))
goto unregister_slow_rc;
@@ -494,14 +506,16 @@ static void __init of_sam9x60_sckc_setup(struct device_node *np)
/* MD_SLCK and TD_SLCK. */
clk_data->num = 2;
- clk_data->hws[0] = clk_hw_register_fixed_rate(NULL, "md_slck",
- parent_names[0],
- 0, 32768);
+ clk_data->hws[0] = clk_hw_register_fixed_rate_parent_hw(NULL, "md_slck",
+ slow_rc,
+ 0, 32768);
if (IS_ERR(clk_data->hws[0]))
goto clk_data_free;
+ parent_hws[0] = slow_rc;
+ parent_hws[1] = slow_osc;
clk_data->hws[1] = at91_clk_register_sam9x5_slow(regbase, "td_slck",
- parent_names, 2,
+ parent_hws, 2,
&at91sam9x60_bits);
if (IS_ERR(clk_data->hws[1]))
goto unregister_md_slck;
@@ -572,30 +586,36 @@ static void __init of_sama5d4_sckc_setup(struct device_node *np)
void __iomem *regbase = of_iomap(np, 0);
struct clk_hw *slow_rc, *slowck;
struct clk_sama5d4_slow_osc *osc;
- struct clk_init_data init;
+ struct clk_init_data init = {};
const char *xtal_name;
- const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
+ const struct clk_hw *parent_hws[2];
+ static struct clk_parent_data parent_data = {
+ .name = "slow_xtal",
+ };
int ret;
if (!regbase)
return;
slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL,
- parent_names[0],
+ "slow_rc_osc",
NULL, 0, 32768,
250000000);
if (IS_ERR(slow_rc))
return;
xtal_name = of_clk_get_parent_name(np, 0);
+ if (!xtal_name)
+ goto unregister_slow_rc;
+ parent_data.fw_name = xtal_name;
osc = kzalloc(sizeof(*osc), GFP_KERNEL);
if (!osc)
goto unregister_slow_rc;
- init.name = parent_names[1];
+ init.name = "slow_osc";
init.ops = &sama5d4_slow_osc_ops;
- init.parent_names = &xtal_name;
+ init.parent_data = &parent_data;
init.num_parents = 1;
init.flags = CLK_IGNORE_UNUSED;
@@ -608,8 +628,10 @@ static void __init of_sama5d4_sckc_setup(struct device_node *np)
if (ret)
goto free_slow_osc_data;
+ parent_hws[0] = slow_rc;
+ parent_hws[1] = &osc->hw;
slowck = at91_clk_register_sam9x5_slow(regbase, "slowck",
- parent_names, 2,
+ parent_hws, 2,
&at91sama5d4_bits);
if (IS_ERR(slowck))
goto unregister_slow_osc;
diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c
index eb399a4d141b..829406dc44a2 100644
--- a/drivers/clk/bcm/clk-raspberrypi.c
+++ b/drivers/clk/bcm/clk-raspberrypi.c
@@ -356,9 +356,9 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi,
while (clks->id) {
struct raspberrypi_clk_variant *variant;
- if (clks->id > RPI_FIRMWARE_NUM_CLK_ID) {
+ if (clks->id >= RPI_FIRMWARE_NUM_CLK_ID) {
dev_err(rpi->dev, "Unknown clock id: %u (max: %u)\n",
- clks->id, RPI_FIRMWARE_NUM_CLK_ID);
+ clks->id, RPI_FIRMWARE_NUM_CLK_ID - 1);
return -EINVAL;
}
diff --git a/drivers/clk/berlin/berlin2-div.c b/drivers/clk/berlin/berlin2-div.c
index eb14a5bc0507..0a248bfe2193 100644
--- a/drivers/clk/berlin/berlin2-div.c
+++ b/drivers/clk/berlin/berlin2-div.c
@@ -210,6 +210,7 @@ static unsigned long berlin2_div_recalc_rate(struct clk_hw *hw,
}
static const struct clk_ops berlin2_div_rate_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.recalc_rate = berlin2_div_recalc_rate,
};
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index a04a3d38c76e..bf4d8ddc93ae 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -384,23 +384,25 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
return 0;
}
-static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int axi_clkgen_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(hw);
const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
unsigned int d, m, dout;
unsigned long long tmp;
- axi_clkgen_calc_params(limits, *parent_rate, rate, &d, &m, &dout);
+ axi_clkgen_calc_params(limits, req->best_parent_rate, req->rate,
+ &d, &m, &dout);
if (d == 0 || dout == 0 || m == 0)
return -EINVAL;
- tmp = (unsigned long long)*parent_rate * m;
+ tmp = (unsigned long long)req->best_parent_rate * m;
tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d);
- return min_t(unsigned long long, tmp, LONG_MAX);
+ req->rate = min_t(unsigned long long, tmp, LONG_MAX);
+ return 0;
}
static unsigned int axi_clkgen_get_div(struct axi_clkgen *axi_clkgen,
@@ -495,7 +497,7 @@ static u8 axi_clkgen_get_parent(struct clk_hw *clk_hw)
static const struct clk_ops axi_clkgen_ops = {
.recalc_rate = axi_clkgen_recalc_rate,
- .round_rate = axi_clkgen_round_rate,
+ .determine_rate = axi_clkgen_determine_rate,
.set_rate = axi_clkgen_set_rate,
.enable = axi_clkgen_enable,
.disable = axi_clkgen_disable,
diff --git a/drivers/clk/clk-cdce706.c b/drivers/clk/clk-cdce706.c
index d8bee8180a6b..dd3d42d9ad86 100644
--- a/drivers/clk/clk-cdce706.c
+++ b/drivers/clk/clk-cdce706.c
@@ -155,6 +155,7 @@ static u8 cdce706_clkin_get_parent(struct clk_hw *hw)
}
static const struct clk_ops cdce706_clkin_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = cdce706_clkin_set_parent,
.get_parent = cdce706_clkin_get_parent,
};
@@ -287,18 +288,19 @@ static unsigned long cdce706_divider_recalc_rate(struct clk_hw *hw,
return 0;
}
-static long cdce706_divider_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int cdce706_divider_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct cdce706_hw_data *hwd = to_hw_data(hw);
struct cdce706_dev_data *cdce = hwd->dev_data;
+ unsigned long rate = req->rate;
unsigned long mul, div;
dev_dbg(&hwd->dev_data->client->dev,
"%s, rate: %lu, parent_rate: %lu\n",
- __func__, rate, *parent_rate);
+ __func__, rate, req->best_parent_rate);
- rational_best_approximation(rate, *parent_rate,
+ rational_best_approximation(rate, req->best_parent_rate,
1, CDCE706_DIVIDER_DIVIDER_MAX,
&mul, &div);
if (!mul)
@@ -343,8 +345,8 @@ static long cdce706_divider_round_rate(struct clk_hw *hw, unsigned long rate,
dev_dbg(&hwd->dev_data->client->dev,
"%s, altering parent rate: %lu -> %lu\n",
- __func__, *parent_rate, rate * div);
- *parent_rate = rate * div;
+ __func__, req->best_parent_rate, rate * div);
+ req->best_parent_rate = rate * div;
}
hwd->div = div;
@@ -352,7 +354,8 @@ static long cdce706_divider_round_rate(struct clk_hw *hw, unsigned long rate,
"%s, divider: %d, div: %lu\n",
__func__, hwd->idx, div);
- return *parent_rate / div;
+ req->rate = req->best_parent_rate / div;
+ return 0;
}
static int cdce706_divider_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -374,7 +377,7 @@ static const struct clk_ops cdce706_divider_ops = {
.set_parent = cdce706_divider_set_parent,
.get_parent = cdce706_divider_get_parent,
.recalc_rate = cdce706_divider_recalc_rate,
- .round_rate = cdce706_divider_round_rate,
+ .determine_rate = cdce706_divider_determine_rate,
.set_rate = cdce706_divider_set_rate,
};
@@ -420,11 +423,12 @@ static unsigned long cdce706_clkout_recalc_rate(struct clk_hw *hw,
return parent_rate;
}
-static long cdce706_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int cdce706_clkout_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- *parent_rate = rate;
- return rate;
+ req->best_parent_rate = req->rate;
+
+ return 0;
}
static int cdce706_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -439,7 +443,7 @@ static const struct clk_ops cdce706_clkout_ops = {
.set_parent = cdce706_clkout_set_parent,
.get_parent = cdce706_clkout_get_parent,
.recalc_rate = cdce706_clkout_recalc_rate,
- .round_rate = cdce706_clkout_round_rate,
+ .determine_rate = cdce706_clkout_determine_rate,
.set_rate = cdce706_clkout_set_rate,
};
@@ -684,7 +688,7 @@ static struct i2c_driver cdce706_i2c_driver = {
.name = "cdce706",
.of_match_table = of_match_ptr(cdce706_dt_match),
},
- .probe_new = cdce706_probe,
+ .probe = cdce706_probe,
.id_table = cdce706_id,
};
module_i2c_driver(cdce706_i2c_driver);
diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c
index 6350682f7e6d..96ac90364847 100644
--- a/drivers/clk/clk-cdce925.c
+++ b/drivers/clk/clk-cdce925.c
@@ -701,6 +701,10 @@ static int cdce925_probe(struct i2c_client *client)
for (i = 0; i < data->chip_info->num_plls; ++i) {
pll_clk_name[i] = kasprintf(GFP_KERNEL, "%pOFn.pll%d",
client->dev.of_node, i);
+ if (!pll_clk_name[i]) {
+ err = -ENOMEM;
+ goto error;
+ }
init.name = pll_clk_name[i];
data->pll[i].chip = data;
data->pll[i].hw.init = &init;
@@ -742,6 +746,10 @@ static int cdce925_probe(struct i2c_client *client)
init.num_parents = 1;
init.parent_names = &parent_name; /* Mux Y1 to input */
init.name = kasprintf(GFP_KERNEL, "%pOFn.Y1", client->dev.of_node);
+ if (!init.name) {
+ err = -ENOMEM;
+ goto error;
+ }
data->clk[0].chip = data;
data->clk[0].hw.init = &init;
data->clk[0].index = 0;
@@ -760,6 +768,10 @@ static int cdce925_probe(struct i2c_client *client)
for (i = 1; i < data->chip_info->num_outputs; ++i) {
init.name = kasprintf(GFP_KERNEL, "%pOFn.Y%d",
client->dev.of_node, i+1);
+ if (!init.name) {
+ err = -ENOMEM;
+ goto error;
+ }
data->clk[i].chip = data;
data->clk[i].hw.init = &init;
data->clk[i].index = i;
@@ -824,7 +836,7 @@ static struct i2c_driver cdce925_driver = {
.name = "cdce925",
.of_match_table = of_match_ptr(clk_cdce925_of_match),
},
- .probe_new = cdce925_probe,
+ .probe = cdce925_probe,
.id_table = cdce925_id,
};
module_i2c_driver(cdce925_driver);
diff --git a/drivers/clk/clk-cs2000-cp.c b/drivers/clk/clk-cs2000-cp.c
index 320d39922206..b82fee6a3d6f 100644
--- a/drivers/clk/clk-cs2000-cp.c
+++ b/drivers/clk/clk-cs2000-cp.c
@@ -622,7 +622,7 @@ static struct i2c_driver cs2000_driver = {
.pm = &cs2000_pm_ops,
.of_match_table = cs2000_of_match,
},
- .probe_new = cs2000_probe,
+ .probe = cs2000_probe,
.remove = cs2000_remove,
.id_table = cs2000_id,
};
diff --git a/drivers/clk/clk-k210.c b/drivers/clk/clk-k210.c
index 4eed667eddaf..870adac5cdee 100644
--- a/drivers/clk/clk-k210.c
+++ b/drivers/clk/clk-k210.c
@@ -537,6 +537,7 @@ static const struct clk_ops k210_pll2_ops = {
.disable = k210_pll_disable,
.is_enabled = k210_pll_is_enabled,
.recalc_rate = k210_pll_get_rate,
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = k210_pll2_set_parent,
.get_parent = k210_pll2_get_parent,
};
@@ -635,6 +636,7 @@ static unsigned long k210_aclk_get_rate(struct clk_hw *hw,
}
static const struct clk_ops k210_aclk_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = k210_aclk_set_parent,
.get_parent = k210_aclk_get_parent,
.recalc_rate = k210_aclk_get_rate,
@@ -774,6 +776,7 @@ static unsigned long k210_clk_get_rate(struct clk_hw *hw,
static const struct clk_ops k210_clk_mux_ops = {
.enable = k210_clk_enable,
.disable = k210_clk_disable,
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = k210_clk_set_parent,
.get_parent = k210_clk_get_parent,
.recalc_rate = k210_clk_get_rate,
diff --git a/drivers/clk/clk-lan966x.c b/drivers/clk/clk-lan966x.c
index 460e7216bfa1..870fd7df50c1 100644
--- a/drivers/clk/clk-lan966x.c
+++ b/drivers/clk/clk-lan966x.c
@@ -103,22 +103,6 @@ static int lan966x_gck_set_rate(struct clk_hw *hw,
return 0;
}
-static long lan966x_gck_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
-{
- unsigned int div;
-
- if (rate == 0 || *parent_rate == 0)
- return -EINVAL;
-
- if (rate >= *parent_rate)
- return *parent_rate;
-
- div = DIV_ROUND_CLOSEST(*parent_rate, rate);
-
- return *parent_rate / div;
-}
-
static unsigned long lan966x_gck_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
@@ -177,7 +161,6 @@ static const struct clk_ops lan966x_gck_ops = {
.enable = lan966x_gck_enable,
.disable = lan966x_gck_disable,
.set_rate = lan966x_gck_set_rate,
- .round_rate = lan966x_gck_round_rate,
.recalc_rate = lan966x_gck_recalc_rate,
.determine_rate = lan966x_gck_determine_rate,
.set_parent = lan966x_gck_set_parent,
diff --git a/drivers/clk/clk-lmk04832.c b/drivers/clk/clk-lmk04832.c
index afdfee3b365f..e22ac93e0c2f 100644
--- a/drivers/clk/clk-lmk04832.c
+++ b/drivers/clk/clk-lmk04832.c
@@ -1279,6 +1279,7 @@ static const struct clk_ops lmk04832_clkout_ops = {
.is_enabled = lmk04832_clkout_is_enabled,
.prepare = lmk04832_clkout_prepare,
.unprepare = lmk04832_clkout_unprepare,
+ .determine_rate = __clk_mux_determine_rate,
.set_parent = lmk04832_clkout_set_parent,
.get_parent = lmk04832_clkout_get_parent,
};
diff --git a/drivers/clk/clk-lochnagar.c b/drivers/clk/clk-lochnagar.c
index 80944bf482e9..db468a62c8d7 100644
--- a/drivers/clk/clk-lochnagar.c
+++ b/drivers/clk/clk-lochnagar.c
@@ -209,6 +209,7 @@ static u8 lochnagar_clk_get_parent(struct clk_hw *hw)
static const struct clk_ops lochnagar_clk_ops = {
.prepare = lochnagar_clk_prepare,
.unprepare = lochnagar_clk_unprepare,
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = lochnagar_clk_set_parent,
.get_parent = lochnagar_clk_get_parent,
};
diff --git a/drivers/clk/clk-max9485.c b/drivers/clk/clk-max9485.c
index 5f85b0a32872..be9020b6c789 100644
--- a/drivers/clk/clk-max9485.c
+++ b/drivers/clk/clk-max9485.c
@@ -376,7 +376,7 @@ static struct i2c_driver max9485_driver = {
.pm = &max9485_pm_ops,
.of_match_table = max9485_dt_ids,
},
- .probe_new = max9485_i2c_probe,
+ .probe = max9485_i2c_probe,
.id_table = max9485_i2c_ids,
};
module_i2c_driver(max9485_driver);
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 5eddb9f0d6bd..e3386fd98c5e 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -878,6 +878,7 @@ static u8 mux_get_parent(struct clk_hw *hw)
}
static const struct clk_ops cmux_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = mux_get_parent,
.set_parent = mux_set_parent,
};
diff --git a/drivers/clk/clk-renesas-pcie.c b/drivers/clk/clk-renesas-pcie.c
index 10d31c222a1c..7d7b2cb75318 100644
--- a/drivers/clk/clk-renesas-pcie.c
+++ b/drivers/clk/clk-renesas-pcie.c
@@ -392,8 +392,8 @@ static const struct rs9_chip_info renesas_9fgv0441_info = {
};
static const struct i2c_device_id rs9_id[] = {
- { "9fgv0241", .driver_data = RENESAS_9FGV0241 },
- { "9fgv0441", .driver_data = RENESAS_9FGV0441 },
+ { "9fgv0241", .driver_data = (kernel_ulong_t)&renesas_9fgv0241_info },
+ { "9fgv0441", .driver_data = (kernel_ulong_t)&renesas_9fgv0441_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, rs9_id);
@@ -413,7 +413,7 @@ static struct i2c_driver rs9_driver = {
.pm = &rs9_pm_ops,
.of_match_table = clk_rs9_of_match,
},
- .probe_new = rs9_probe,
+ .probe = rs9_probe,
.id_table = rs9_id,
};
module_i2c_driver(rs9_driver);
diff --git a/drivers/clk/clk-si514.c b/drivers/clk/clk-si514.c
index cabdd8e8f4db..e8c18afac184 100644
--- a/drivers/clk/clk-si514.c
+++ b/drivers/clk/clk-si514.c
@@ -387,7 +387,7 @@ static struct i2c_driver si514_driver = {
.name = "si514",
.of_match_table = clk_si514_of_match,
},
- .probe_new = si514_probe,
+ .probe = si514_probe,
.id_table = si514_id,
};
module_i2c_driver(si514_driver);
diff --git a/drivers/clk/clk-si521xx.c b/drivers/clk/clk-si521xx.c
index ac8d4c59cd3d..4eaf1b53f06b 100644
--- a/drivers/clk/clk-si521xx.c
+++ b/drivers/clk/clk-si521xx.c
@@ -385,7 +385,7 @@ static struct i2c_driver si521xx_driver = {
.pm = &si521xx_pm_ops,
.of_match_table = clk_si521xx_of_match,
},
- .probe_new = si521xx_probe,
+ .probe = si521xx_probe,
.id_table = si521xx_id,
};
module_i2c_driver(si521xx_driver);
diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c
index 0e528d7ba656..9599857842c7 100644
--- a/drivers/clk/clk-si5341.c
+++ b/drivers/clk/clk-si5341.c
@@ -551,6 +551,7 @@ static int si5341_clk_set_parent(struct clk_hw *hw, u8 index)
}
static const struct clk_ops si5341_clk_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = si5341_clk_set_parent,
.get_parent = si5341_clk_get_parent,
.recalc_rate = si5341_clk_recalc_rate,
@@ -827,19 +828,20 @@ static unsigned long si5341_output_clk_recalc_rate(struct clk_hw *hw,
return parent_rate / r_divider;
}
-static long si5341_output_clk_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int si5341_output_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
+ unsigned long rate = req->rate;
unsigned long r;
if (!rate)
return 0;
- r = *parent_rate >> 1;
+ r = req->best_parent_rate >> 1;
/* If rate is an even divisor, no changes to parent required */
if (r && !(r % rate))
- return (long)rate;
+ return 0;
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
if (rate > 200000000) {
@@ -849,14 +851,15 @@ static long si5341_output_clk_round_rate(struct clk_hw *hw, unsigned long rate,
/* Take a parent frequency near 400 MHz */
r = (400000000u / rate) & ~1;
}
- *parent_rate = r * rate;
+ req->best_parent_rate = r * rate;
} else {
/* We cannot change our parent's rate, report what we can do */
r /= rate;
- rate = *parent_rate / (r << 1);
+ rate = req->best_parent_rate / (r << 1);
}
- return rate;
+ req->rate = rate;
+ return 0;
}
static int si5341_output_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -929,7 +932,7 @@ static const struct clk_ops si5341_output_clk_ops = {
.prepare = si5341_output_clk_prepare,
.unprepare = si5341_output_clk_unprepare,
.recalc_rate = si5341_output_clk_recalc_rate,
- .round_rate = si5341_output_clk_round_rate,
+ .determine_rate = si5341_output_clk_determine_rate,
.set_rate = si5341_output_clk_set_rate,
.set_parent = si5341_output_set_parent,
.get_parent = si5341_output_get_parent,
@@ -1553,7 +1556,7 @@ static int si5341_probe(struct i2c_client *client)
struct clk_init_data init;
struct clk *input;
const char *root_clock_name;
- const char *synth_clock_names[SI5341_NUM_SYNTH];
+ const char *synth_clock_names[SI5341_NUM_SYNTH] = { NULL };
int err;
unsigned int i;
struct clk_si5341_output_config config[SI5341_MAX_NUM_OUTPUTS];
@@ -1697,6 +1700,10 @@ static int si5341_probe(struct i2c_client *client)
for (i = 0; i < data->num_synth; ++i) {
synth_clock_names[i] = devm_kasprintf(&client->dev, GFP_KERNEL,
"%s.N%u", client->dev.of_node->name, i);
+ if (!synth_clock_names[i]) {
+ err = -ENOMEM;
+ goto free_clk_names;
+ }
init.name = synth_clock_names[i];
data->synth[i].index = i;
data->synth[i].data = data;
@@ -1705,6 +1712,7 @@ static int si5341_probe(struct i2c_client *client)
if (err) {
dev_err(&client->dev,
"synth N%u registration failed\n", i);
+ goto free_clk_names;
}
}
@@ -1714,6 +1722,10 @@ static int si5341_probe(struct i2c_client *client)
for (i = 0; i < data->num_outputs; ++i) {
init.name = kasprintf(GFP_KERNEL, "%s.%d",
client->dev.of_node->name, i);
+ if (!init.name) {
+ err = -ENOMEM;
+ goto free_clk_names;
+ }
init.flags = config[i].synth_master ? CLK_SET_RATE_PARENT : 0;
data->clk[i].index = i;
data->clk[i].data = data;
@@ -1735,7 +1747,7 @@ static int si5341_probe(struct i2c_client *client)
if (err) {
dev_err(&client->dev,
"output %u registration failed\n", i);
- goto cleanup;
+ goto free_clk_names;
}
if (config[i].always_on)
clk_prepare(data->clk[i].hw.clk);
@@ -1745,7 +1757,7 @@ static int si5341_probe(struct i2c_client *client)
data);
if (err) {
dev_err(&client->dev, "unable to add clk provider\n");
- goto cleanup;
+ goto free_clk_names;
}
if (initialization_required) {
@@ -1753,11 +1765,11 @@ static int si5341_probe(struct i2c_client *client)
regcache_cache_only(data->regmap, false);
err = regcache_sync(data->regmap);
if (err < 0)
- goto cleanup;
+ goto free_clk_names;
err = si5341_finalize_defaults(data);
if (err < 0)
- goto cleanup;
+ goto free_clk_names;
}
/* wait for device to report input clock present and PLL lock */
@@ -1766,32 +1778,31 @@ static int si5341_probe(struct i2c_client *client)
10000, 250000);
if (err) {
dev_err(&client->dev, "Error waiting for input clock or PLL lock\n");
- goto cleanup;
+ goto free_clk_names;
}
/* clear sticky alarm bits from initialization */
err = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0);
if (err) {
dev_err(&client->dev, "unable to clear sticky status\n");
- goto cleanup;
+ goto free_clk_names;
}
err = sysfs_create_files(&client->dev.kobj, si5341_attributes);
- if (err) {
+ if (err)
dev_err(&client->dev, "unable to create sysfs files\n");
- goto cleanup;
- }
+free_clk_names:
/* Free the names, clk framework makes copies */
for (i = 0; i < data->num_synth; ++i)
devm_kfree(&client->dev, (void *)synth_clock_names[i]);
- return 0;
-
cleanup:
- for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) {
- if (data->clk[i].vddo_reg)
- regulator_disable(data->clk[i].vddo_reg);
+ if (err) {
+ for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) {
+ if (data->clk[i].vddo_reg)
+ regulator_disable(data->clk[i].vddo_reg);
+ }
}
return err;
}
@@ -1834,7 +1845,7 @@ static struct i2c_driver si5341_driver = {
.name = "si5341",
.of_match_table = clk_si5341_of_match,
},
- .probe_new = si5341_probe,
+ .probe = si5341_probe,
.remove = si5341_remove,
.id_table = si5341_id,
};
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c
index 4fcf7056717e..31c3c8a71f12 100644
--- a/drivers/clk/clk-si5351.c
+++ b/drivers/clk/clk-si5351.c
@@ -442,11 +442,12 @@ static unsigned long si5351_pll_recalc_rate(struct clk_hw *hw,
return (unsigned long)rate;
}
-static long si5351_pll_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int si5351_pll_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct si5351_hw_data *hwdata =
container_of(hw, struct si5351_hw_data, hw);
+ unsigned long rate = req->rate;
unsigned long rfrac, denom, a, b, c;
unsigned long long lltmp;
@@ -456,18 +457,18 @@ static long si5351_pll_round_rate(struct clk_hw *hw, unsigned long rate,
rate = SI5351_PLL_VCO_MAX;
/* determine integer part of feedback equation */
- a = rate / *parent_rate;
+ a = rate / req->best_parent_rate;
if (a < SI5351_PLL_A_MIN)
- rate = *parent_rate * SI5351_PLL_A_MIN;
+ rate = req->best_parent_rate * SI5351_PLL_A_MIN;
if (a > SI5351_PLL_A_MAX)
- rate = *parent_rate * SI5351_PLL_A_MAX;
+ rate = req->best_parent_rate * SI5351_PLL_A_MAX;
/* find best approximation for b/c = fVCO mod fIN */
denom = 1000 * 1000;
- lltmp = rate % (*parent_rate);
+ lltmp = rate % (req->best_parent_rate);
lltmp *= denom;
- do_div(lltmp, *parent_rate);
+ do_div(lltmp, req->best_parent_rate);
rfrac = (unsigned long)lltmp;
b = 0;
@@ -484,19 +485,20 @@ static long si5351_pll_round_rate(struct clk_hw *hw, unsigned long rate,
hwdata->params.p1 -= 512;
/* recalculate rate by fIN * (a + b/c) */
- lltmp = *parent_rate;
+ lltmp = req->best_parent_rate;
lltmp *= b;
do_div(lltmp, c);
rate = (unsigned long)lltmp;
- rate += *parent_rate * a;
+ rate += req->best_parent_rate * a;
dev_dbg(&hwdata->drvdata->client->dev,
"%s - %s: a = %lu, b = %lu, c = %lu, parent_rate = %lu, rate = %lu\n",
__func__, clk_hw_get_name(hw), a, b, c,
- *parent_rate, rate);
+ req->best_parent_rate, rate);
- return rate;
+ req->rate = rate;
+ return 0;
}
static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -533,7 +535,7 @@ static const struct clk_ops si5351_pll_ops = {
.set_parent = si5351_pll_set_parent,
.get_parent = si5351_pll_get_parent,
.recalc_rate = si5351_pll_recalc_rate,
- .round_rate = si5351_pll_round_rate,
+ .determine_rate = si5351_pll_determine_rate,
.set_rate = si5351_pll_set_rate,
};
@@ -640,11 +642,12 @@ static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw,
return (unsigned long)rate;
}
-static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int si5351_msynth_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct si5351_hw_data *hwdata =
container_of(hw, struct si5351_hw_data, hw);
+ unsigned long rate = req->rate;
unsigned long long lltmp;
unsigned long a, b, c;
int divby4;
@@ -679,10 +682,10 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
b = 0;
c = 1;
- *parent_rate = a * rate;
+ req->best_parent_rate = a * rate;
} else if (hwdata->num >= 6) {
/* determine the closest integer divider */
- a = DIV_ROUND_CLOSEST(*parent_rate, rate);
+ a = DIV_ROUND_CLOSEST(req->best_parent_rate, rate);
if (a < SI5351_MULTISYNTH_A_MIN)
a = SI5351_MULTISYNTH_A_MIN;
if (a > SI5351_MULTISYNTH67_A_MAX)
@@ -700,7 +703,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
}
/* determine integer part of divider equation */
- a = *parent_rate / rate;
+ a = req->best_parent_rate / rate;
if (a < SI5351_MULTISYNTH_A_MIN)
a = SI5351_MULTISYNTH_A_MIN;
if (a > SI5351_MULTISYNTH_A_MAX)
@@ -708,7 +711,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
/* find best approximation for b/c = fVCO mod fOUT */
denom = 1000 * 1000;
- lltmp = (*parent_rate) % rate;
+ lltmp = req->best_parent_rate % rate;
lltmp *= denom;
do_div(lltmp, rate);
rfrac = (unsigned long)lltmp;
@@ -722,7 +725,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
}
/* recalculate rate by fOUT = fIN / (a + b/c) */
- lltmp = *parent_rate;
+ lltmp = req->best_parent_rate;
lltmp *= c;
do_div(lltmp, a * c + b);
rate = (unsigned long)lltmp;
@@ -747,9 +750,11 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
dev_dbg(&hwdata->drvdata->client->dev,
"%s - %s: a = %lu, b = %lu, c = %lu, divby4 = %d, parent_rate = %lu, rate = %lu\n",
__func__, clk_hw_get_name(hw), a, b, c, divby4,
- *parent_rate, rate);
+ req->best_parent_rate, rate);
- return rate;
+ req->rate = rate;
+
+ return 0;
}
static int si5351_msynth_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -789,7 +794,7 @@ static const struct clk_ops si5351_msynth_ops = {
.set_parent = si5351_msynth_set_parent,
.get_parent = si5351_msynth_get_parent,
.recalc_rate = si5351_msynth_recalc_rate,
- .round_rate = si5351_msynth_round_rate,
+ .determine_rate = si5351_msynth_determine_rate,
.set_rate = si5351_msynth_set_rate,
};
@@ -1032,11 +1037,12 @@ static unsigned long si5351_clkout_recalc_rate(struct clk_hw *hw,
return parent_rate >> rdiv;
}
-static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int si5351_clkout_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct si5351_hw_data *hwdata =
container_of(hw, struct si5351_hw_data, hw);
+ unsigned long rate = req->rate;
unsigned char rdiv;
/* clkout6/7 can only handle output freqencies < 150MHz */
@@ -1058,13 +1064,13 @@ static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
rdiv += 1;
rate *= 2;
}
- *parent_rate = rate;
+ req->best_parent_rate = rate;
} else {
unsigned long new_rate, new_err, err;
/* round to closed rdiv */
rdiv = SI5351_OUTPUT_CLK_DIV_1;
- new_rate = *parent_rate;
+ new_rate = req->best_parent_rate;
err = abs(new_rate - rate);
do {
new_rate >>= 1;
@@ -1075,14 +1081,15 @@ static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
err = new_err;
} while (1);
}
- rate = *parent_rate >> rdiv;
+ rate = req->best_parent_rate >> rdiv;
dev_dbg(&hwdata->drvdata->client->dev,
"%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n",
__func__, clk_hw_get_name(hw), (1 << rdiv),
- *parent_rate, rate);
+ req->best_parent_rate, rate);
- return rate;
+ req->rate = rate;
+ return 0;
}
static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -1142,7 +1149,7 @@ static const struct clk_ops si5351_clkout_ops = {
.set_parent = si5351_clkout_set_parent,
.get_parent = si5351_clkout_get_parent,
.recalc_rate = si5351_clkout_recalc_rate,
- .round_rate = si5351_clkout_round_rate,
+ .determine_rate = si5351_clkout_determine_rate,
.set_rate = si5351_clkout_set_rate,
};
@@ -1656,7 +1663,7 @@ static struct i2c_driver si5351_driver = {
.name = "si5351",
.of_match_table = of_match_ptr(si5351_dt_ids),
},
- .probe_new = si5351_i2c_probe,
+ .probe = si5351_i2c_probe,
.id_table = si5351_i2c_ids,
};
module_i2c_driver(si5351_driver);
diff --git a/drivers/clk/clk-si544.c b/drivers/clk/clk-si544.c
index 089786907641..22925968aa35 100644
--- a/drivers/clk/clk-si544.c
+++ b/drivers/clk/clk-si544.c
@@ -520,7 +520,7 @@ static struct i2c_driver si544_driver = {
.name = "si544",
.of_match_table = clk_si544_of_match,
},
- .probe_new = si544_probe,
+ .probe = si544_probe,
.id_table = si544_id,
};
module_i2c_driver(si544_driver);
diff --git a/drivers/clk/clk-si570.c b/drivers/clk/clk-si570.c
index 0b834e9efb4b..de0212fb5f87 100644
--- a/drivers/clk/clk-si570.c
+++ b/drivers/clk/clk-si570.c
@@ -510,7 +510,7 @@ static struct i2c_driver si570_driver = {
.name = "si570",
.of_match_table = clk_si570_of_match,
},
- .probe_new = si570_probe,
+ .probe = si570_probe,
.id_table = si570_id,
};
module_i2c_driver(si570_driver);
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 473dfe632cc5..07c13ebe327d 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -1045,6 +1045,7 @@ static int cclk_mux_set_parent(struct clk_hw *hw, u8 index)
}
static const struct clk_ops cclk_mux_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = cclk_mux_get_parent,
.set_parent = cclk_mux_set_parent,
};
diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c
index fa71a57875ce..8bc54176f325 100644
--- a/drivers/clk/clk-versaclock5.c
+++ b/drivers/clk/clk-versaclock5.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@@ -281,6 +282,7 @@ static int vc5_mux_set_parent(struct clk_hw *hw, u8 index)
}
static const struct clk_ops vc5_mux_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = vc5_mux_set_parent,
.get_parent = vc5_mux_get_parent,
};
@@ -725,6 +727,7 @@ static int vc5_clk_out_set_parent(struct clk_hw *hw, u8 index)
static const struct clk_ops vc5_clk_out_ops = {
.prepare = vc5_clk_out_prepare,
.unprepare = vc5_clk_out_unprepare,
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = vc5_clk_out_set_parent,
.get_parent = vc5_clk_out_get_parent,
};
@@ -953,7 +956,7 @@ static int vc5_probe(struct i2c_client *client)
i2c_set_clientdata(client, vc5);
vc5->client = client;
- vc5->chip_info = of_device_get_match_data(&client->dev);
+ vc5->chip_info = device_get_match_data(&client->dev);
vc5->pin_xin = devm_clk_get(&client->dev, "xin");
if (PTR_ERR(vc5->pin_xin) == -EPROBE_DEFER)
@@ -1028,6 +1031,11 @@ static int vc5_probe(struct i2c_client *client)
}
init.name = kasprintf(GFP_KERNEL, "%pOFn.mux", client->dev.of_node);
+ if (!init.name) {
+ ret = -ENOMEM;
+ goto err_clk;
+ }
+
init.ops = &vc5_mux_ops;
init.flags = 0;
init.parent_names = parent_names;
@@ -1042,6 +1050,10 @@ static int vc5_probe(struct i2c_client *client)
memset(&init, 0, sizeof(init));
init.name = kasprintf(GFP_KERNEL, "%pOFn.dbl",
client->dev.of_node);
+ if (!init.name) {
+ ret = -ENOMEM;
+ goto err_clk;
+ }
init.ops = &vc5_dbl_ops;
init.flags = CLK_SET_RATE_PARENT;
init.parent_names = parent_names;
@@ -1057,6 +1069,10 @@ static int vc5_probe(struct i2c_client *client)
/* Register PFD */
memset(&init, 0, sizeof(init));
init.name = kasprintf(GFP_KERNEL, "%pOFn.pfd", client->dev.of_node);
+ if (!init.name) {
+ ret = -ENOMEM;
+ goto err_clk;
+ }
init.ops = &vc5_pfd_ops;
init.flags = CLK_SET_RATE_PARENT;
init.parent_names = parent_names;
@@ -1074,6 +1090,10 @@ static int vc5_probe(struct i2c_client *client)
/* Register PLL */
memset(&init, 0, sizeof(init));
init.name = kasprintf(GFP_KERNEL, "%pOFn.pll", client->dev.of_node);
+ if (!init.name) {
+ ret = -ENOMEM;
+ goto err_clk;
+ }
init.ops = &vc5_pll_ops;
init.flags = CLK_SET_RATE_PARENT;
init.parent_names = parent_names;
@@ -1093,6 +1113,10 @@ static int vc5_probe(struct i2c_client *client)
memset(&init, 0, sizeof(init));
init.name = kasprintf(GFP_KERNEL, "%pOFn.fod%d",
client->dev.of_node, idx);
+ if (!init.name) {
+ ret = -ENOMEM;
+ goto err_clk;
+ }
init.ops = &vc5_fod_ops;
init.flags = CLK_SET_RATE_PARENT;
init.parent_names = parent_names;
@@ -1111,6 +1135,10 @@ static int vc5_probe(struct i2c_client *client)
memset(&init, 0, sizeof(init));
init.name = kasprintf(GFP_KERNEL, "%pOFn.out0_sel_i2cb",
client->dev.of_node);
+ if (!init.name) {
+ ret = -ENOMEM;
+ goto err_clk;
+ }
init.ops = &vc5_clk_out_ops;
init.flags = CLK_SET_RATE_PARENT;
init.parent_names = parent_names;
@@ -1137,6 +1165,10 @@ static int vc5_probe(struct i2c_client *client)
memset(&init, 0, sizeof(init));
init.name = kasprintf(GFP_KERNEL, "%pOFn.out%d",
client->dev.of_node, idx + 1);
+ if (!init.name) {
+ ret = -ENOMEM;
+ goto err_clk;
+ }
init.ops = &vc5_clk_out_ops;
init.flags = CLK_SET_RATE_PARENT;
init.parent_names = parent_names;
@@ -1271,14 +1303,14 @@ static const struct vc5_chip_info idt_5p49v6975_info = {
};
static const struct i2c_device_id vc5_id[] = {
- { "5p49v5923", .driver_data = IDT_VC5_5P49V5923 },
- { "5p49v5925", .driver_data = IDT_VC5_5P49V5925 },
- { "5p49v5933", .driver_data = IDT_VC5_5P49V5933 },
- { "5p49v5935", .driver_data = IDT_VC5_5P49V5935 },
- { "5p49v60", .driver_data = IDT_VC6_5P49V60 },
- { "5p49v6901", .driver_data = IDT_VC6_5P49V6901 },
- { "5p49v6965", .driver_data = IDT_VC6_5P49V6965 },
- { "5p49v6975", .driver_data = IDT_VC6_5P49V6975 },
+ { "5p49v5923", .driver_data = (kernel_ulong_t)&idt_5p49v5923_info },
+ { "5p49v5925", .driver_data = (kernel_ulong_t)&idt_5p49v5925_info },
+ { "5p49v5933", .driver_data = (kernel_ulong_t)&idt_5p49v5933_info },
+ { "5p49v5935", .driver_data = (kernel_ulong_t)&idt_5p49v5935_info },
+ { "5p49v60", .driver_data = (kernel_ulong_t)&idt_5p49v60_info },
+ { "5p49v6901", .driver_data = (kernel_ulong_t)&idt_5p49v6901_info },
+ { "5p49v6965", .driver_data = (kernel_ulong_t)&idt_5p49v6965_info },
+ { "5p49v6975", .driver_data = (kernel_ulong_t)&idt_5p49v6975_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, vc5_id);
@@ -1304,7 +1336,7 @@ static struct i2c_driver vc5_driver = {
.pm = &vc5_pm_ops,
.of_match_table = clk_vc5_of_match,
},
- .probe_new = vc5_probe,
+ .probe = vc5_probe,
.remove = vc5_remove,
.id_table = vc5_id,
};
diff --git a/drivers/clk/clk-versaclock7.c b/drivers/clk/clk-versaclock7.c
index 8e4f86e852aa..9babb7913c1c 100644
--- a/drivers/clk/clk-versaclock7.c
+++ b/drivers/clk/clk-versaclock7.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/swab.h>
@@ -1108,7 +1109,7 @@ static int vc7_probe(struct i2c_client *client)
i2c_set_clientdata(client, vc7);
vc7->client = client;
- vc7->chip_info = of_device_get_match_data(&client->dev);
+ vc7->chip_info = device_get_match_data(&client->dev);
vc7->pin_xin = devm_clk_get(&client->dev, "xin");
if (PTR_ERR(vc7->pin_xin) == -EPROBE_DEFER) {
@@ -1282,7 +1283,7 @@ static const struct regmap_config vc7_regmap_config = {
};
static const struct i2c_device_id vc7_i2c_id[] = {
- { "rc21008a", VC7_RC21008A },
+ { "rc21008a", .driver_data = (kernel_ulong_t)&vc7_rc21008a_info },
{}
};
MODULE_DEVICE_TABLE(i2c, vc7_i2c_id);
@@ -1298,7 +1299,7 @@ static struct i2c_driver vc7_i2c_driver = {
.name = "vc7",
.of_match_table = vc7_of_match,
},
- .probe_new = vc7_probe,
+ .probe = vc7_probe,
.remove = vc7_remove,
.id_table = vc7_i2c_id,
};
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
index ae6dd38ec053..34e9d4d541e2 100644
--- a/drivers/clk/clk-wm831x.c
+++ b/drivers/clk/clk-wm831x.c
@@ -329,6 +329,7 @@ static const struct clk_ops wm831x_clkout_ops = {
.is_prepared = wm831x_clkout_is_prepared,
.prepare = wm831x_clkout_prepare,
.unprepare = wm831x_clkout_unprepare,
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = wm831x_clkout_get_parent,
.set_parent = wm831x_clkout_set_parent,
};
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 27c30a533759..c249f9791ae8 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -594,45 +594,59 @@ clk_core_forward_rate_req(struct clk_core *core,
req->max_rate = old_req->max_rate;
}
-int clk_mux_determine_rate_flags(struct clk_hw *hw,
- struct clk_rate_request *req,
- unsigned long flags)
+static int
+clk_core_determine_rate_no_reparent(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- struct clk_core *core = hw->core, *parent, *best_parent = NULL;
- int i, num_parents, ret;
- unsigned long best = 0;
-
- /* if NO_REPARENT flag set, pass through to current parent */
- if (core->flags & CLK_SET_RATE_NO_REPARENT) {
- parent = core->parent;
- if (core->flags & CLK_SET_RATE_PARENT) {
- struct clk_rate_request parent_req;
+ struct clk_core *core = hw->core;
+ struct clk_core *parent = core->parent;
+ unsigned long best;
+ int ret;
- if (!parent) {
- req->rate = 0;
- return 0;
- }
+ if (core->flags & CLK_SET_RATE_PARENT) {
+ struct clk_rate_request parent_req;
- clk_core_forward_rate_req(core, req, parent, &parent_req, req->rate);
+ if (!parent) {
+ req->rate = 0;
+ return 0;
+ }
- trace_clk_rate_request_start(&parent_req);
+ clk_core_forward_rate_req(core, req, parent, &parent_req,
+ req->rate);
- ret = clk_core_round_rate_nolock(parent, &parent_req);
- if (ret)
- return ret;
+ trace_clk_rate_request_start(&parent_req);
- trace_clk_rate_request_done(&parent_req);
+ ret = clk_core_round_rate_nolock(parent, &parent_req);
+ if (ret)
+ return ret;
- best = parent_req.rate;
- } else if (parent) {
- best = clk_core_get_rate_nolock(parent);
- } else {
- best = clk_core_get_rate_nolock(core);
- }
+ trace_clk_rate_request_done(&parent_req);
- goto out;
+ best = parent_req.rate;
+ } else if (parent) {
+ best = clk_core_get_rate_nolock(parent);
+ } else {
+ best = clk_core_get_rate_nolock(core);
}
+ req->best_parent_rate = best;
+ req->rate = best;
+
+ return 0;
+}
+
+int clk_mux_determine_rate_flags(struct clk_hw *hw,
+ struct clk_rate_request *req,
+ unsigned long flags)
+{
+ struct clk_core *core = hw->core, *parent, *best_parent = NULL;
+ int i, num_parents, ret;
+ unsigned long best = 0;
+
+ /* if NO_REPARENT flag set, pass through to current parent */
+ if (core->flags & CLK_SET_RATE_NO_REPARENT)
+ return clk_core_determine_rate_no_reparent(hw, req);
+
/* find the parent that can provide the fastest rate <= rate */
num_parents = core->num_parents;
for (i = 0; i < num_parents; i++) {
@@ -670,9 +684,7 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw,
if (!best_parent)
return -EINVAL;
-out:
- if (best_parent)
- req->best_parent_hw = best_parent->hw;
+ req->best_parent_hw = best_parent->hw;
req->best_parent_rate = best;
req->rate = best;
@@ -772,6 +784,25 @@ int __clk_mux_determine_rate_closest(struct clk_hw *hw,
}
EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
+/*
+ * clk_hw_determine_rate_no_reparent - clk_ops::determine_rate implementation for a clk that doesn't reparent
+ * @hw: mux type clk to determine rate on
+ * @req: rate request, also used to return preferred frequency
+ *
+ * Helper for finding best parent rate to provide a given frequency.
+ * This can be used directly as a determine_rate callback (e.g. for a
+ * mux), or from a more complex clock that may combine a mux with other
+ * operations.
+ *
+ * Returns: 0 on success, -EERROR value on error
+ */
+int clk_hw_determine_rate_no_reparent(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return clk_core_determine_rate_no_reparent(hw, req);
+}
+EXPORT_SYMBOL_GPL(clk_hw_determine_rate_no_reparent);
+
/*** clk api ***/
static void clk_core_rate_unprotect(struct clk_core *core)
@@ -1549,6 +1580,7 @@ void clk_hw_forward_rate_request(const struct clk_hw *hw,
parent->core, req,
parent_rate);
}
+EXPORT_SYMBOL_GPL(clk_hw_forward_rate_request);
static bool clk_core_can_round(struct clk_core * const core)
{
@@ -3745,6 +3777,13 @@ static int __clk_core_init(struct clk_core *core)
goto out;
}
+ if (core->ops->set_parent && !core->ops->determine_rate) {
+ pr_err("%s: %s must implement .set_parent & .determine_rate\n",
+ __func__, core->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
if (core->num_parents > 1 && !core->ops->get_parent) {
pr_err("%s: %s must implement .get_parent as it has multi parents\n",
__func__, core->name);
@@ -4301,11 +4340,18 @@ static int clk_nodrv_set_parent(struct clk_hw *hw, u8 index)
return -ENXIO;
}
+static int clk_nodrv_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return -ENXIO;
+}
+
static const struct clk_ops clk_nodrv_ops = {
.enable = clk_nodrv_prepare_enable,
.disable = clk_nodrv_disable_unprepare,
.prepare = clk_nodrv_prepare_enable,
.unprepare = clk_nodrv_disable_unprepare,
+ .determine_rate = clk_nodrv_determine_rate,
.set_rate = clk_nodrv_set_rate,
.set_parent = clk_nodrv_set_parent,
};
@@ -4695,6 +4741,7 @@ int devm_clk_notifier_register(struct device *dev, struct clk *clk,
if (!ret) {
devres->clk = clk;
devres->nb = nb;
+ devres_add(dev, devres);
} else {
devres_free(devres);
}
diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c
index f9a5c2964c65..a154ec9d0111 100644
--- a/drivers/clk/clk_test.c
+++ b/drivers/clk/clk_test.c
@@ -104,6 +104,23 @@ static const struct clk_ops clk_dummy_minimize_rate_ops = {
};
static const struct clk_ops clk_dummy_single_parent_ops = {
+ /*
+ * FIXME: Even though we should probably be able to use
+ * __clk_mux_determine_rate() here, if we use it and call
+ * clk_round_rate() or clk_set_rate() with a rate lower than
+ * what all the parents can provide, it will return -EINVAL.
+ *
+ * This is due to the fact that it has the undocumented
+ * behaviour to always pick up the closest rate higher than the
+ * requested rate. If we get something lower, it thus considers
+ * that it's not acceptable and will return an error.
+ *
+ * It's somewhat inconsistent and creates a weird threshold
+ * between rates above the parent rate which would be rounded to
+ * what the parent can provide, but rates below will simply
+ * return an error.
+ */
+ .determine_rate = __clk_mux_determine_rate_closest,
.set_parent = clk_dummy_single_set_parent,
.get_parent = clk_dummy_single_get_parent,
};
@@ -141,6 +158,12 @@ static const struct clk_ops clk_multiple_parents_mux_ops = {
.determine_rate = __clk_mux_determine_rate_closest,
};
+static const struct clk_ops clk_multiple_parents_no_reparent_mux_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
+ .get_parent = clk_multiple_parents_mux_get_parent,
+ .set_parent = clk_multiple_parents_mux_set_parent,
+};
+
static int clk_test_init_with_ops(struct kunit *test, const struct clk_ops *ops)
{
struct clk_dummy_context *ctx;
@@ -266,7 +289,8 @@ static void clk_test_round_set_get_rate(struct kunit *test)
struct clk_dummy_context *ctx = test->priv;
struct clk_hw *hw = &ctx->hw;
struct clk *clk = clk_hw_get_clk(hw, NULL);
- unsigned long rounded_rate, set_rate;
+ unsigned long set_rate;
+ long rounded_rate;
rounded_rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_1);
KUNIT_ASSERT_GT(test, rounded_rate, 0);
@@ -851,7 +875,7 @@ clk_test_orphan_transparent_multiple_parent_mux_set_range_round_rate(struct kuni
struct clk_multiple_parent_ctx *ctx = test->priv;
struct clk_hw *hw = &ctx->hw;
struct clk *clk = clk_hw_get_clk(hw, NULL);
- unsigned long rate;
+ long rate;
int ret;
ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2);
@@ -1090,7 +1114,7 @@ clk_test_single_parent_mux_set_range_round_rate_parent_only(struct kunit *test)
struct clk_hw *hw = &ctx->hw;
struct clk *clk = clk_hw_get_clk(hw, NULL);
struct clk *parent;
- unsigned long rate;
+ long rate;
int ret;
parent = clk_get_parent(clk);
@@ -1120,7 +1144,7 @@ clk_test_single_parent_mux_set_range_round_rate_child_smaller(struct kunit *test
struct clk_hw *hw = &ctx->hw;
struct clk *clk = clk_hw_get_clk(hw, NULL);
struct clk *parent;
- unsigned long rate;
+ long rate;
int ret;
parent = clk_get_parent(clk);
@@ -1158,7 +1182,7 @@ clk_test_single_parent_mux_set_range_round_rate_parent_smaller(struct kunit *tes
struct clk_hw *hw = &ctx->hw;
struct clk *clk = clk_hw_get_clk(hw, NULL);
struct clk *parent;
- unsigned long rate;
+ long rate;
int ret;
parent = clk_get_parent(clk);
@@ -2394,10 +2418,156 @@ static struct kunit_suite clk_mux_notifier_test_suite = {
.test_cases = clk_mux_notifier_test_cases,
};
+static int
+clk_mux_no_reparent_test_init(struct kunit *test)
+{
+ struct clk_multiple_parent_ctx *ctx;
+ const char *parents[2] = { "parent-0", "parent-1"};
+ int ret;
+
+ ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ test->priv = ctx;
+
+ ctx->parents_ctx[0].hw.init = CLK_HW_INIT_NO_PARENT("parent-0",
+ &clk_dummy_rate_ops,
+ 0);
+ ctx->parents_ctx[0].rate = DUMMY_CLOCK_RATE_1;
+ ret = clk_hw_register(NULL, &ctx->parents_ctx[0].hw);
+ if (ret)
+ return ret;
+
+ ctx->parents_ctx[1].hw.init = CLK_HW_INIT_NO_PARENT("parent-1",
+ &clk_dummy_rate_ops,
+ 0);
+ ctx->parents_ctx[1].rate = DUMMY_CLOCK_RATE_2;
+ ret = clk_hw_register(NULL, &ctx->parents_ctx[1].hw);
+ if (ret)
+ return ret;
+
+ ctx->current_parent = 0;
+ ctx->hw.init = CLK_HW_INIT_PARENTS("test-mux", parents,
+ &clk_multiple_parents_no_reparent_mux_ops,
+ 0);
+ ret = clk_hw_register(NULL, &ctx->hw);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void
+clk_mux_no_reparent_test_exit(struct kunit *test)
+{
+ struct clk_multiple_parent_ctx *ctx = test->priv;
+
+ clk_hw_unregister(&ctx->hw);
+ clk_hw_unregister(&ctx->parents_ctx[0].hw);
+ clk_hw_unregister(&ctx->parents_ctx[1].hw);
+}
+
+/*
+ * Test that if the we have a mux that cannot change parent and we call
+ * clk_round_rate() on it with a rate that should cause it to change
+ * parent, it won't.
+ */
+static void clk_mux_no_reparent_round_rate(struct kunit *test)
+{
+ struct clk_multiple_parent_ctx *ctx = test->priv;
+ struct clk_hw *hw = &ctx->hw;
+ struct clk *clk = clk_hw_get_clk(hw, NULL);
+ struct clk *other_parent, *parent;
+ unsigned long other_parent_rate;
+ unsigned long parent_rate;
+ long rounded_rate;
+
+ parent = clk_get_parent(clk);
+ KUNIT_ASSERT_PTR_NE(test, parent, NULL);
+
+ parent_rate = clk_get_rate(parent);
+ KUNIT_ASSERT_GT(test, parent_rate, 0);
+
+ other_parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, other_parent);
+ KUNIT_ASSERT_FALSE(test, clk_is_match(parent, other_parent));
+
+ other_parent_rate = clk_get_rate(other_parent);
+ KUNIT_ASSERT_GT(test, other_parent_rate, 0);
+ clk_put(other_parent);
+
+ rounded_rate = clk_round_rate(clk, other_parent_rate);
+ KUNIT_ASSERT_GT(test, rounded_rate, 0);
+ KUNIT_EXPECT_EQ(test, rounded_rate, parent_rate);
+
+ clk_put(clk);
+}
+
+/*
+ * Test that if the we have a mux that cannot change parent and we call
+ * clk_set_rate() on it with a rate that should cause it to change
+ * parent, it won't.
+ */
+static void clk_mux_no_reparent_set_rate(struct kunit *test)
+{
+ struct clk_multiple_parent_ctx *ctx = test->priv;
+ struct clk_hw *hw = &ctx->hw;
+ struct clk *clk = clk_hw_get_clk(hw, NULL);
+ struct clk *other_parent, *parent;
+ unsigned long other_parent_rate;
+ unsigned long parent_rate;
+ unsigned long rate;
+ int ret;
+
+ parent = clk_get_parent(clk);
+ KUNIT_ASSERT_PTR_NE(test, parent, NULL);
+
+ parent_rate = clk_get_rate(parent);
+ KUNIT_ASSERT_GT(test, parent_rate, 0);
+
+ other_parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, other_parent);
+ KUNIT_ASSERT_FALSE(test, clk_is_match(parent, other_parent));
+
+ other_parent_rate = clk_get_rate(other_parent);
+ KUNIT_ASSERT_GT(test, other_parent_rate, 0);
+ clk_put(other_parent);
+
+ ret = clk_set_rate(clk, other_parent_rate);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ rate = clk_get_rate(clk);
+ KUNIT_ASSERT_GT(test, rate, 0);
+ KUNIT_EXPECT_EQ(test, rate, parent_rate);
+
+ clk_put(clk);
+}
+
+static struct kunit_case clk_mux_no_reparent_test_cases[] = {
+ KUNIT_CASE(clk_mux_no_reparent_round_rate),
+ KUNIT_CASE(clk_mux_no_reparent_set_rate),
+ {}
+};
+
+/*
+ * Test suite for a clock mux that isn't allowed to change parent, using
+ * the clk_hw_determine_rate_no_reparent() helper.
+ *
+ * These tests exercise that helper, and the proper selection of
+ * rates and parents.
+ */
+static struct kunit_suite clk_mux_no_reparent_test_suite = {
+ .name = "clk-mux-no-reparent",
+ .init = clk_mux_no_reparent_test_init,
+ .exit = clk_mux_no_reparent_test_exit,
+ .test_cases = clk_mux_no_reparent_test_cases,
+};
+
kunit_test_suites(
&clk_leaf_mux_set_rate_parent_test_suite,
&clk_test_suite,
&clk_multiple_parents_mux_test_suite,
+ &clk_mux_no_reparent_test_suite,
&clk_mux_notifier_test_suite,
&clk_orphan_transparent_multiple_parent_mux_test_suite,
&clk_orphan_transparent_single_parent_test_suite,
diff --git a/drivers/clk/davinci/da8xx-cfgchip.c b/drivers/clk/davinci/da8xx-cfgchip.c
index 4103d605e804..e5b2cdfe88ce 100644
--- a/drivers/clk/davinci/da8xx-cfgchip.c
+++ b/drivers/clk/davinci/da8xx-cfgchip.c
@@ -229,6 +229,7 @@ static u8 da8xx_cfgchip_mux_clk_get_parent(struct clk_hw *hw)
}
static const struct clk_ops da8xx_cfgchip_mux_clk_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = da8xx_cfgchip_mux_clk_set_parent,
.get_parent = da8xx_cfgchip_mux_clk_get_parent,
};
@@ -461,10 +462,12 @@ static unsigned long da8xx_usb0_clk48_recalc_rate(struct clk_hw *hw,
return 48000000;
}
-static long da8xx_usb0_clk48_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int da8xx_usb0_clk48_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- return 48000000;
+ req->rate = 48000000;
+
+ return 0;
}
static int da8xx_usb0_clk48_set_parent(struct clk_hw *hw, u8 index)
@@ -493,7 +496,7 @@ static const struct clk_ops da8xx_usb0_clk48_ops = {
.disable = da8xx_usb0_clk48_disable,
.is_enabled = da8xx_usb0_clk48_is_enabled,
.recalc_rate = da8xx_usb0_clk48_recalc_rate,
- .round_rate = da8xx_usb0_clk48_round_rate,
+ .determine_rate = da8xx_usb0_clk48_determine_rate,
.set_parent = da8xx_usb0_clk48_set_parent,
.get_parent = da8xx_usb0_clk48_get_parent,
};
@@ -564,6 +567,7 @@ static u8 da8xx_usb1_clk48_get_parent(struct clk_hw *hw)
}
static const struct clk_ops da8xx_usb1_clk48_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = da8xx_usb1_clk48_set_parent,
.get_parent = da8xx_usb1_clk48_get_parent,
};
diff --git a/drivers/clk/imx/clk-busy.c b/drivers/clk/imx/clk-busy.c
index 6f17311647f3..f163df952ccc 100644
--- a/drivers/clk/imx/clk-busy.c
+++ b/drivers/clk/imx/clk-busy.c
@@ -148,6 +148,7 @@ static int clk_busy_mux_set_parent(struct clk_hw *hw, u8 index)
}
static const struct clk_ops clk_busy_mux_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = clk_busy_mux_get_parent,
.set_parent = clk_busy_mux_set_parent,
};
diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c
index cbf0d7955a00..7a6e3ce97133 100644
--- a/drivers/clk/imx/clk-composite-8m.c
+++ b/drivers/clk/imx/clk-composite-8m.c
@@ -119,10 +119,41 @@ static int imx8m_clk_composite_divider_set_rate(struct clk_hw *hw,
return ret;
}
+static int imx8m_divider_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_divider *divider = to_clk_divider(hw);
+ int prediv_value;
+ int div_value;
+
+ /* if read only, just return current value */
+ if (divider->flags & CLK_DIVIDER_READ_ONLY) {
+ u32 val;
+
+ val = readl(divider->reg);
+ prediv_value = val >> divider->shift;
+ prediv_value &= clk_div_mask(divider->width);
+ prediv_value++;
+
+ div_value = val >> PCG_DIV_SHIFT;
+ div_value &= clk_div_mask(PCG_DIV_WIDTH);
+ div_value++;
+
+ return divider_ro_determine_rate(hw, req, divider->table,
+ PCG_PREDIV_WIDTH + PCG_DIV_WIDTH,
+ divider->flags, prediv_value * div_value);
+ }
+
+ return divider_determine_rate(hw, req, divider->table,
+ PCG_PREDIV_WIDTH + PCG_DIV_WIDTH,
+ divider->flags);
+}
+
static const struct clk_ops imx8m_clk_composite_divider_ops = {
.recalc_rate = imx8m_clk_composite_divider_recalc_rate,
.round_rate = imx8m_clk_composite_divider_round_rate,
.set_rate = imx8m_clk_composite_divider_set_rate,
+ .determine_rate = imx8m_divider_determine_rate,
};
static u8 imx8m_clk_composite_mux_get_parent(struct clk_hw *hw)
diff --git a/drivers/clk/imx/clk-fixup-mux.c b/drivers/clk/imx/clk-fixup-mux.c
index c82401570c84..b48701864ef0 100644
--- a/drivers/clk/imx/clk-fixup-mux.c
+++ b/drivers/clk/imx/clk-fixup-mux.c
@@ -60,6 +60,7 @@ static int clk_fixup_mux_set_parent(struct clk_hw *hw, u8 index)
}
static const struct clk_ops clk_fixup_mux_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = clk_fixup_mux_get_parent,
.set_parent = clk_fixup_mux_set_parent,
};
diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c
index 7cf86707bc39..3f1502933e59 100644
--- a/drivers/clk/imx/clk-imx6sx.c
+++ b/drivers/clk/imx/clk-imx6sx.c
@@ -302,10 +302,10 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
hws[IMX6SX_CLK_CKO2_SEL] = imx_clk_hw_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels));
hws[IMX6SX_CLK_CKO] = imx_clk_hw_mux("cko", base + 0x60, 8, 1, cko_sels, ARRAY_SIZE(cko_sels));
- hws[IMX6SX_CLK_LDB_DI1_DIV_SEL] = imx_clk_hw_mux_flags("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels), CLK_SET_RATE_PARENT);
- hws[IMX6SX_CLK_LDB_DI0_DIV_SEL] = imx_clk_hw_mux_flags("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels), CLK_SET_RATE_PARENT);
- hws[IMX6SX_CLK_LDB_DI1_SEL] = imx_clk_hw_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels), CLK_SET_RATE_PARENT);
- hws[IMX6SX_CLK_LDB_DI0_SEL] = imx_clk_hw_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels), CLK_SET_RATE_PARENT);
+ hws[IMX6SX_CLK_LDB_DI1_DIV_SEL] = imx_clk_hw_mux("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
+ hws[IMX6SX_CLK_LDB_DI0_DIV_SEL] = imx_clk_hw_mux("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
+ hws[IMX6SX_CLK_LDB_DI1_SEL] = imx_clk_hw_mux("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels));
+ hws[IMX6SX_CLK_LDB_DI0_SEL] = imx_clk_hw_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
hws[IMX6SX_CLK_LCDIF1_PRE_SEL] = imx_clk_hw_mux_flags("lcdif1_pre_sel", base + 0x38, 15, 3, lcdif1_pre_sels, ARRAY_SIZE(lcdif1_pre_sels), CLK_SET_RATE_PARENT);
hws[IMX6SX_CLK_LCDIF1_SEL] = imx_clk_hw_mux_flags("lcdif1_sel", base + 0x38, 9, 3, lcdif1_sels, ARRAY_SIZE(lcdif1_sels), CLK_SET_RATE_PARENT);
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c
index e3696a88b5a3..f9394e94f69d 100644
--- a/drivers/clk/imx/clk-imx6ul.c
+++ b/drivers/clk/imx/clk-imx6ul.c
@@ -544,6 +544,8 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clk_set_parent(hws[IMX6UL_CLK_ENET1_REF_SEL]->clk, hws[IMX6UL_CLK_ENET_REF]->clk);
clk_set_parent(hws[IMX6UL_CLK_ENET2_REF_SEL]->clk, hws[IMX6UL_CLK_ENET2_REF]->clk);
+
+ imx_register_uart_clocks();
}
CLK_OF_DECLARE(imx6ul, "fsl,imx6ul-ccm", imx6ul_clocks_init);
diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
index 4b23a4648600..4bd1ed11353b 100644
--- a/drivers/clk/imx/clk-imx8mn.c
+++ b/drivers/clk/imx/clk-imx8mn.c
@@ -323,7 +323,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
void __iomem *base;
int ret;
- clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
+ clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
IMX8MN_CLK_END), GFP_KERNEL);
if (WARN_ON(!clk_hw_data))
return -ENOMEM;
@@ -340,10 +340,10 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
hws[IMX8MN_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mn-anatop");
- base = of_iomap(np, 0);
+ base = devm_of_iomap(dev, np, 0, NULL);
of_node_put(np);
- if (WARN_ON(!base)) {
- ret = -ENOMEM;
+ if (WARN_ON(IS_ERR(base))) {
+ ret = PTR_ERR(base);
goto unregister_hws;
}
diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index f26ae8de4cc6..1469249386dd 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -414,25 +414,22 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np;
void __iomem *anatop_base, *ccm_base;
+ int err;
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop");
- anatop_base = of_iomap(np, 0);
+ anatop_base = devm_of_iomap(dev, np, 0, NULL);
of_node_put(np);
- if (WARN_ON(!anatop_base))
- return -ENOMEM;
+ if (WARN_ON(IS_ERR(anatop_base)))
+ return PTR_ERR(anatop_base);
np = dev->of_node;
ccm_base = devm_platform_ioremap_resource(pdev, 0);
- if (WARN_ON(IS_ERR(ccm_base))) {
- iounmap(anatop_base);
+ if (WARN_ON(IS_ERR(ccm_base)))
return PTR_ERR(ccm_base);
- }
- clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, IMX8MP_CLK_END), GFP_KERNEL);
- if (WARN_ON(!clk_hw_data)) {
- iounmap(anatop_base);
+ clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX8MP_CLK_END), GFP_KERNEL);
+ if (WARN_ON(!clk_hw_data))
return -ENOMEM;
- }
clk_hw_data->num = IMX8MP_CLK_END;
hws = clk_hw_data->hws;
@@ -722,7 +719,12 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
imx_check_clk_hws(hws, IMX8MP_CLK_END);
- of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
+ err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
+ if (err < 0) {
+ dev_err(dev, "failed to register hws for i.MX8MP\n");
+ imx_unregister_hw_clocks(hws, IMX8MP_CLK_END);
+ return err;
+ }
imx_register_uart_clocks();
diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
index 07b4a043e449..b6c7c2725906 100644
--- a/drivers/clk/imx/clk-imx93.c
+++ b/drivers/clk/imx/clk-imx93.c
@@ -264,7 +264,7 @@ static int imx93_clocks_probe(struct platform_device *pdev)
void __iomem *base, *anatop_base;
int i, ret;
- clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
+ clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
IMX93_CLK_END), GFP_KERNEL);
if (!clk_hw_data)
return -ENOMEM;
@@ -288,10 +288,12 @@ static int imx93_clocks_probe(struct platform_device *pdev)
"sys_pll_pfd2", 1, 2);
np = of_find_compatible_node(NULL, NULL, "fsl,imx93-anatop");
- anatop_base = of_iomap(np, 0);
+ anatop_base = devm_of_iomap(dev, np, 0, NULL);
of_node_put(np);
- if (WARN_ON(!anatop_base))
- return -ENOMEM;
+ if (WARN_ON(IS_ERR(anatop_base))) {
+ ret = PTR_ERR(base);
+ goto unregister_hws;
+ }
clks[IMX93_CLK_ARM_PLL] = imx_clk_fracn_gppll_integer("arm_pll", "osc_24m",
anatop_base + 0x1000,
@@ -304,8 +306,8 @@ static int imx93_clocks_probe(struct platform_device *pdev)
np = dev->of_node;
base = devm_platform_ioremap_resource(pdev, 0);
if (WARN_ON(IS_ERR(base))) {
- iounmap(anatop_base);
- return PTR_ERR(base);
+ ret = PTR_ERR(base);
+ goto unregister_hws;
}
for (i = 0; i < ARRAY_SIZE(root_array); i++) {
@@ -345,7 +347,6 @@ static int imx93_clocks_probe(struct platform_device *pdev)
unregister_hws:
imx_unregister_hw_clocks(clks, IMX93_CLK_END);
- iounmap(anatop_base);
return ret;
}
diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c
index fd5c51fc92c0..08d155feb035 100644
--- a/drivers/clk/imx/clk-imxrt1050.c
+++ b/drivers/clk/imx/clk-imxrt1050.c
@@ -42,7 +42,7 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
struct device_node *anp;
int ret;
- clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
+ clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
IMXRT1050_CLK_END), GFP_KERNEL);
if (WARN_ON(!clk_hw_data))
return -ENOMEM;
@@ -53,10 +53,12 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
hws[IMXRT1050_CLK_OSC] = imx_get_clk_hw_by_name(np, "osc");
anp = of_find_compatible_node(NULL, NULL, "fsl,imxrt-anatop");
- pll_base = of_iomap(anp, 0);
+ pll_base = devm_of_iomap(dev, anp, 0, NULL);
of_node_put(anp);
- if (WARN_ON(!pll_base))
- return -ENOMEM;
+ if (WARN_ON(IS_ERR(pll_base))) {
+ ret = PTR_ERR(pll_base);
+ goto unregister_hws;
+ }
/* Anatop clocks */
hws[IMXRT1050_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0UL);
@@ -104,8 +106,10 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
/* CCM clocks */
ccm_base = devm_platform_ioremap_resource(pdev, 0);
- if (WARN_ON(IS_ERR(ccm_base)))
- return PTR_ERR(ccm_base);
+ if (WARN_ON(IS_ERR(ccm_base))) {
+ ret = PTR_ERR(ccm_base);
+ goto unregister_hws;
+ }
hws[IMXRT1050_CLK_ARM_PODF] = imx_clk_hw_divider("arm_podf", "pll1_arm", ccm_base + 0x10, 0, 3);
hws[IMXRT1050_CLK_PRE_PERIPH_SEL] = imx_clk_hw_mux("pre_periph_sel", ccm_base + 0x18, 18, 2,
@@ -149,8 +153,12 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
if (ret < 0) {
dev_err(dev, "Failed to register clks for i.MXRT1050.\n");
- imx_unregister_hw_clocks(hws, IMXRT1050_CLK_END);
+ goto unregister_hws;
}
+ return 0;
+
+unregister_hws:
+ imx_unregister_hw_clocks(hws, IMXRT1050_CLK_END);
return ret;
}
static const struct of_device_id imxrt1050_clk_of_match[] = {
diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
index 1e6870f3671f..85041e339515 100644
--- a/drivers/clk/imx/clk-scu.c
+++ b/drivers/clk/imx/clk-scu.c
@@ -251,6 +251,23 @@ static unsigned long clk_scu_recalc_rate(struct clk_hw *hw,
}
/*
+ * clk_scu_determine_rate - Returns the closest rate for a SCU clock
+ * @hw: clock to round rate for
+ * @req: clock rate request
+ *
+ * Returns 0 on success, a negative error on failure
+ */
+static int clk_scu_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ /*
+ * Assume we support all the requested rate and let the SCU firmware
+ * to handle the left work
+ */
+ return 0;
+}
+
+/*
* clk_scu_round_rate - Round clock rate for a SCU clock
* @hw: clock to round rate for
* @rate: rate to round
@@ -425,7 +442,7 @@ static void clk_scu_unprepare(struct clk_hw *hw)
static const struct clk_ops clk_scu_ops = {
.recalc_rate = clk_scu_recalc_rate,
- .round_rate = clk_scu_round_rate,
+ .determine_rate = clk_scu_determine_rate,
.set_rate = clk_scu_set_rate,
.get_parent = clk_scu_get_parent,
.set_parent = clk_scu_set_parent,
@@ -707,11 +724,11 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
void imx_clk_scu_unregister(void)
{
- struct imx_scu_clk_node *clk;
+ struct imx_scu_clk_node *clk, *n;
int i;
for (i = 0; i < IMX_SC_R_LAST; i++) {
- list_for_each_entry(clk, &imx_scu_clks[i], node) {
+ list_for_each_entry_safe(clk, n, &imx_scu_clks[i], node) {
clk_hw_unregister(clk->hw);
kfree(clk);
}
@@ -785,6 +802,7 @@ static int clk_gpr_mux_scu_set_parent(struct clk_hw *hw, u8 index)
}
static const struct clk_ops clk_gpr_mux_scu_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = clk_gpr_mux_scu_get_parent,
.set_parent = clk_gpr_mux_scu_set_parent,
};
diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c
index 19cde59a20cb..e35496af5ceb 100644
--- a/drivers/clk/imx/clk.c
+++ b/drivers/clk/imx/clk.c
@@ -20,14 +20,6 @@ EXPORT_SYMBOL_GPL(imx_ccm_lock);
bool mcore_booted;
EXPORT_SYMBOL_GPL(mcore_booted);
-void imx_unregister_clocks(struct clk *clks[], unsigned int count)
-{
- unsigned int i;
-
- for (i = 0; i < count; i++)
- clk_unregister(clks[i]);
-}
-
void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count)
{
unsigned int i;
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 1031468701d7..af19d9f6aed0 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -19,7 +19,6 @@ static inline void imx_register_uart_clocks(void)
}
#endif
void imx_mmdc_mask_handshake(void __iomem *ccm_base, unsigned int chn);
-void imx_unregister_clocks(struct clk *clks[], unsigned int count);
void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count);
extern void imx_cscmr1_fixup(u32 *val);
diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index 1f7ba30f5a1b..0c9c8344ad11 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -491,22 +491,23 @@ ingenic_clk_calc_div(struct clk_hw *hw,
return div;
}
-static long
-ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate,
- unsigned long *parent_rate)
+static int ingenic_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
unsigned int div = 1;
if (clk_info->type & CGU_CLK_DIV)
- div = ingenic_clk_calc_div(hw, clk_info, *parent_rate, req_rate);
+ div = ingenic_clk_calc_div(hw, clk_info, req->best_parent_rate,
+ req->rate);
else if (clk_info->type & CGU_CLK_FIXDIV)
div = clk_info->fixdiv.div;
else if (clk_hw_can_set_rate_parent(hw))
- *parent_rate = req_rate;
+ req->best_parent_rate = req->rate;
- return DIV_ROUND_UP(*parent_rate, div);
+ req->rate = DIV_ROUND_UP(req->best_parent_rate, div);
+ return 0;
}
static inline int ingenic_clk_check_stable(struct ingenic_cgu *cgu,
@@ -626,7 +627,7 @@ static const struct clk_ops ingenic_clk_ops = {
.set_parent = ingenic_clk_set_parent,
.recalc_rate = ingenic_clk_recalc_rate,
- .round_rate = ingenic_clk_round_rate,
+ .determine_rate = ingenic_clk_determine_rate,
.set_rate = ingenic_clk_set_rate,
.enable = ingenic_clk_enable,
diff --git a/drivers/clk/ingenic/tcu.c b/drivers/clk/ingenic/tcu.c
index d5544cbc5c48..7d04ef40b7cf 100644
--- a/drivers/clk/ingenic/tcu.c
+++ b/drivers/clk/ingenic/tcu.c
@@ -178,18 +178,21 @@ static u8 ingenic_tcu_get_prescale(unsigned long rate, unsigned long req_rate)
return 5; /* /1024 divider */
}
-static long ingenic_tcu_round_rate(struct clk_hw *hw, unsigned long req_rate,
- unsigned long *parent_rate)
+static int ingenic_tcu_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- unsigned long rate = *parent_rate;
+ unsigned long rate = req->best_parent_rate;
u8 prescale;
- if (req_rate > rate)
- return rate;
+ if (req->rate > rate) {
+ req->rate = rate;
+ return 0;
+ }
- prescale = ingenic_tcu_get_prescale(rate, req_rate);
+ prescale = ingenic_tcu_get_prescale(rate, req->rate);
- return rate >> (prescale * 2);
+ req->rate = rate >> (prescale * 2);
+ return 0;
}
static int ingenic_tcu_set_rate(struct clk_hw *hw, unsigned long req_rate,
@@ -219,7 +222,7 @@ static const struct clk_ops ingenic_tcu_clk_ops = {
.set_parent = ingenic_tcu_set_parent,
.recalc_rate = ingenic_tcu_recalc_rate,
- .round_rate = ingenic_tcu_round_rate,
+ .determine_rate = ingenic_tcu_determine_rate,
.set_rate = ingenic_tcu_set_rate,
.enable = ingenic_tcu_enable,
diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c
index 910ecd58c4ca..6c1df4f11536 100644
--- a/drivers/clk/keystone/sci-clk.c
+++ b/drivers/clk/keystone/sci-clk.c
@@ -294,6 +294,8 @@ static int _sci_clk_build(struct sci_clk_provider *provider,
name = kasprintf(GFP_KERNEL, "clk:%d:%d", sci_clk->dev_id,
sci_clk->clk_id);
+ if (!name)
+ return -ENOMEM;
init.name = name;
diff --git a/drivers/clk/keystone/syscon-clk.c b/drivers/clk/keystone/syscon-clk.c
index 5d7cc83682da..d33f74119488 100644
--- a/drivers/clk/keystone/syscon-clk.c
+++ b/drivers/clk/keystone/syscon-clk.c
@@ -4,10 +4,12 @@
*/
#include <linux/clk-provider.h>
+#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/slab.h>
struct ti_syscon_gate_clk_priv {
struct clk_hw hw;
@@ -61,21 +63,31 @@ static const struct clk_ops ti_syscon_gate_clk_ops = {
static struct clk_hw
*ti_syscon_gate_clk_register(struct device *dev, struct regmap *regmap,
+ const char *parent_name,
const struct ti_syscon_gate_clk_data *data)
{
struct ti_syscon_gate_clk_priv *priv;
struct clk_init_data init;
+ char *name = NULL;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return ERR_PTR(-ENOMEM);
- init.name = data->name;
init.ops = &ti_syscon_gate_clk_ops;
- init.parent_names = NULL;
- init.num_parents = 0;
- init.flags = 0;
+ if (parent_name) {
+ name = kasprintf(GFP_KERNEL, "%s:%s", data->name, parent_name);
+ init.name = name;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = CLK_SET_RATE_PARENT;
+ } else {
+ init.name = data->name;
+ init.parent_names = NULL;
+ init.num_parents = 0;
+ init.flags = 0;
+ }
priv->regmap = regmap;
priv->reg = data->offset;
@@ -83,6 +95,10 @@ static struct clk_hw
priv->hw.init = &init;
ret = devm_clk_hw_register(dev, &priv->hw);
+
+ if (name)
+ kfree(init.name);
+
if (ret)
return ERR_PTR(ret);
@@ -94,22 +110,30 @@ static int ti_syscon_gate_clk_probe(struct platform_device *pdev)
const struct ti_syscon_gate_clk_data *data, *p;
struct clk_hw_onecell_data *hw_data;
struct device *dev = &pdev->dev;
+ int num_clks, num_parents, i;
+ const char *parent_name;
struct regmap *regmap;
- int num_clks, i;
data = device_get_match_data(dev);
if (!data)
return -EINVAL;
- regmap = syscon_node_to_regmap(dev->of_node);
+ regmap = device_node_to_regmap(dev->of_node);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap),
- "failed to find parent regmap\n");
+ "failed to get regmap\n");
num_clks = 0;
for (p = data; p->name; p++)
num_clks++;
+ num_parents = of_clk_get_parent_count(dev->of_node);
+ if (of_device_is_compatible(dev->of_node, "ti,am62-audio-refclk") &&
+ num_parents == 0) {
+ return dev_err_probe(dev, -EINVAL,
+ "must specify a parent clock\n");
+ }
+
hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, num_clks),
GFP_KERNEL);
if (!hw_data)
@@ -117,8 +141,10 @@ static int ti_syscon_gate_clk_probe(struct platform_device *pdev)
hw_data->num = num_clks;
+ parent_name = of_clk_get_parent_name(dev->of_node, 0);
for (i = 0; i < num_clks; i++) {
hw_data->hws[i] = ti_syscon_gate_clk_register(dev, regmap,
+ parent_name,
&data[i]);
if (IS_ERR(hw_data->hws[i]))
dev_warn(dev, "failed to register %s\n",
@@ -166,6 +192,11 @@ static const struct ti_syscon_gate_clk_data am62_clk_data[] = {
{ /* Sentinel */ },
};
+static const struct ti_syscon_gate_clk_data am62_audio_clk_data[] = {
+ TI_SYSCON_CLK_GATE("audio_refclk", 0x0, 15),
+ { /* Sentinel */ },
+};
+
static const struct of_device_id ti_syscon_gate_clk_ids[] = {
{
.compatible = "ti,am654-ehrpwm-tbclk",
@@ -179,6 +210,10 @@ static const struct of_device_id ti_syscon_gate_clk_ids[] = {
.compatible = "ti,am62-epwm-tbclk",
.data = &am62_clk_data,
},
+ {
+ .compatible = "ti,am62-audio-refclk",
+ .data = &am62_audio_clk_data,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, ti_syscon_gate_clk_ids);
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 99e67c07e638..48b42d11111c 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -781,72 +781,84 @@ config COMMON_CLK_MT8192
config COMMON_CLK_MT8192_AUDSYS
tristate "Clock driver for MediaTek MT8192 audsys"
depends on COMMON_CLK_MT8192
+ default COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 audsys clocks.
config COMMON_CLK_MT8192_CAMSYS
tristate "Clock driver for MediaTek MT8192 camsys"
depends on COMMON_CLK_MT8192
+ default COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 camsys and camsys_raw clocks.
config COMMON_CLK_MT8192_IMGSYS
tristate "Clock driver for MediaTek MT8192 imgsys"
depends on COMMON_CLK_MT8192
+ default COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 imgsys and imgsys2 clocks.
config COMMON_CLK_MT8192_IMP_IIC_WRAP
tristate "Clock driver for MediaTek MT8192 imp_iic_wrap"
depends on COMMON_CLK_MT8192
+ default COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 imp_iic_wrap clocks.
config COMMON_CLK_MT8192_IPESYS
tristate "Clock driver for MediaTek MT8192 ipesys"
depends on COMMON_CLK_MT8192
+ default COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 ipesys clocks.
config COMMON_CLK_MT8192_MDPSYS
tristate "Clock driver for MediaTek MT8192 mdpsys"
depends on COMMON_CLK_MT8192
+ default COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 mdpsys clocks.
config COMMON_CLK_MT8192_MFGCFG
tristate "Clock driver for MediaTek MT8192 mfgcfg"
depends on COMMON_CLK_MT8192
+ default COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 mfgcfg clocks.
config COMMON_CLK_MT8192_MMSYS
tristate "Clock driver for MediaTek MT8192 mmsys"
depends on COMMON_CLK_MT8192
+ default COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 mmsys clocks.
config COMMON_CLK_MT8192_MSDC
tristate "Clock driver for MediaTek MT8192 msdc"
depends on COMMON_CLK_MT8192
+ default COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 msdc and msdc_top clocks.
config COMMON_CLK_MT8192_SCP_ADSP
tristate "Clock driver for MediaTek MT8192 scp_adsp"
depends on COMMON_CLK_MT8192
+ default COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 scp_adsp clocks.
config COMMON_CLK_MT8192_VDECSYS
tristate "Clock driver for MediaTek MT8192 vdecsys"
depends on COMMON_CLK_MT8192
+ default COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 vdecsys and vdecsys_soc clocks.
config COMMON_CLK_MT8192_VENCSYS
tristate "Clock driver for MediaTek MT8192 vencsys"
depends on COMMON_CLK_MT8192
+ default COMMON_CLK_MT8192
help
This driver supports MediaTek MT8192 vencsys clocks.
diff --git a/drivers/clk/mediatek/clk-cpumux.c b/drivers/clk/mediatek/clk-cpumux.c
index da05f06192c0..a03826db4dcb 100644
--- a/drivers/clk/mediatek/clk-cpumux.c
+++ b/drivers/clk/mediatek/clk-cpumux.c
@@ -53,6 +53,7 @@ static int clk_cpumux_set_parent(struct clk_hw *hw, u8 index)
}
static const struct clk_ops clk_cpumux_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = clk_cpumux_get_parent,
.set_parent = clk_cpumux_set_parent,
};
diff --git a/drivers/clk/mediatek/clk-mt2701-aud.c b/drivers/clk/mediatek/clk-mt2701-aud.c
index 5cd343b98685..3ce7e71196fd 100644
--- a/drivers/clk/mediatek/clk-mt2701-aud.c
+++ b/drivers/clk/mediatek/clk-mt2701-aud.c
@@ -150,15 +150,15 @@ err_plat_populate:
return r;
}
-static int clk_mt2701_aud_remove(struct platform_device *pdev)
+static void clk_mt2701_aud_remove(struct platform_device *pdev)
{
of_platform_depopulate(&pdev->dev);
- return mtk_clk_simple_remove(pdev);
+ mtk_clk_simple_remove(pdev);
}
static struct platform_driver clk_mt2701_aud_drv = {
.probe = clk_mt2701_aud_probe,
- .remove = clk_mt2701_aud_remove,
+ .remove_new = clk_mt2701_aud_remove,
.driver = {
.name = "clk-mt2701-aud",
.of_match_table = of_match_clk_mt2701_aud,
diff --git a/drivers/clk/mediatek/clk-mt2701-bdp.c b/drivers/clk/mediatek/clk-mt2701-bdp.c
index 4c5b70d48df9..b25703ec8dc0 100644
--- a/drivers/clk/mediatek/clk-mt2701-bdp.c
+++ b/drivers/clk/mediatek/clk-mt2701-bdp.c
@@ -99,7 +99,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_bdp);
static struct platform_driver clk_mt2701_bdp_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2701-bdp",
.of_match_table = of_match_clk_mt2701_bdp,
diff --git a/drivers/clk/mediatek/clk-mt2701-eth.c b/drivers/clk/mediatek/clk-mt2701-eth.c
index 9a1fb0c93964..056d1e8459da 100644
--- a/drivers/clk/mediatek/clk-mt2701-eth.c
+++ b/drivers/clk/mediatek/clk-mt2701-eth.c
@@ -53,7 +53,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_eth);
static struct platform_driver clk_mt2701_eth_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2701-eth",
.of_match_table = of_match_clk_mt2701_eth,
diff --git a/drivers/clk/mediatek/clk-mt2701-g3d.c b/drivers/clk/mediatek/clk-mt2701-g3d.c
index c0006861a317..e03ac76279ba 100644
--- a/drivers/clk/mediatek/clk-mt2701-g3d.c
+++ b/drivers/clk/mediatek/clk-mt2701-g3d.c
@@ -52,7 +52,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_g3d);
static struct platform_driver clk_mt2701_g3d_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2701-g3d",
.of_match_table = of_match_clk_mt2701_g3d,
diff --git a/drivers/clk/mediatek/clk-mt2701-hif.c b/drivers/clk/mediatek/clk-mt2701-hif.c
index ff7c0b3228e4..cbd5ece3e9e9 100644
--- a/drivers/clk/mediatek/clk-mt2701-hif.c
+++ b/drivers/clk/mediatek/clk-mt2701-hif.c
@@ -50,7 +50,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_hif);
static struct platform_driver clk_mt2701_hif_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2701-hif",
.of_match_table = of_match_clk_mt2701_hif,
diff --git a/drivers/clk/mediatek/clk-mt2701-img.c b/drivers/clk/mediatek/clk-mt2701-img.c
index baa1194eb01e..2768360b213e 100644
--- a/drivers/clk/mediatek/clk-mt2701-img.c
+++ b/drivers/clk/mediatek/clk-mt2701-img.c
@@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_img);
static struct platform_driver clk_mt2701_img_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2701-img",
.of_match_table = of_match_clk_mt2701_img,
diff --git a/drivers/clk/mediatek/clk-mt2701-mm.c b/drivers/clk/mediatek/clk-mt2701-mm.c
index c62c56fd2b7e..2b990b5a0422 100644
--- a/drivers/clk/mediatek/clk-mt2701-mm.c
+++ b/drivers/clk/mediatek/clk-mt2701-mm.c
@@ -80,7 +80,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt2701_mm_id_table);
static struct platform_driver clk_mt2701_mm_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt2701-mm",
},
diff --git a/drivers/clk/mediatek/clk-mt2701-vdec.c b/drivers/clk/mediatek/clk-mt2701-vdec.c
index b7f97bc51c16..57711b953b7f 100644
--- a/drivers/clk/mediatek/clk-mt2701-vdec.c
+++ b/drivers/clk/mediatek/clk-mt2701-vdec.c
@@ -52,7 +52,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_vdec);
static struct platform_driver clk_mt2701_vdec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2701-vdec",
.of_match_table = of_match_clk_mt2701_vdec,
diff --git a/drivers/clk/mediatek/clk-mt2712-apmixedsys.c b/drivers/clk/mediatek/clk-mt2712-apmixedsys.c
index 9d2fcda285fb..43272dc744c7 100644
--- a/drivers/clk/mediatek/clk-mt2712-apmixedsys.c
+++ b/drivers/clk/mediatek/clk-mt2712-apmixedsys.c
@@ -138,7 +138,7 @@ free_clk_data:
return r;
}
-static int clk_mt2712_apmixed_remove(struct platform_device *pdev)
+static void clk_mt2712_apmixed_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -146,8 +146,6 @@ static int clk_mt2712_apmixed_remove(struct platform_device *pdev)
of_clk_del_provider(node);
mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static const struct of_device_id of_match_clk_mt2712_apmixed[] = {
@@ -158,7 +156,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_apmixed);
static struct platform_driver clk_mt2712_apmixed_drv = {
.probe = clk_mt2712_apmixed_probe,
- .remove = clk_mt2712_apmixed_remove,
+ .remove_new = clk_mt2712_apmixed_remove,
.driver = {
.name = "clk-mt2712-apmixed",
.of_match_table = of_match_clk_mt2712_apmixed,
diff --git a/drivers/clk/mediatek/clk-mt2712-bdp.c b/drivers/clk/mediatek/clk-mt2712-bdp.c
index f78e01819316..1b54b1f3808d 100644
--- a/drivers/clk/mediatek/clk-mt2712-bdp.c
+++ b/drivers/clk/mediatek/clk-mt2712-bdp.c
@@ -69,7 +69,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_bdp);
static struct platform_driver clk_mt2712_bdp_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2712-bdp",
.of_match_table = of_match_clk_mt2712_bdp,
diff --git a/drivers/clk/mediatek/clk-mt2712-img.c b/drivers/clk/mediatek/clk-mt2712-img.c
index fbe7084886a0..1fecc0f68f0e 100644
--- a/drivers/clk/mediatek/clk-mt2712-img.c
+++ b/drivers/clk/mediatek/clk-mt2712-img.c
@@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_img);
static struct platform_driver clk_mt2712_img_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2712-img",
.of_match_table = of_match_clk_mt2712_img,
diff --git a/drivers/clk/mediatek/clk-mt2712-jpgdec.c b/drivers/clk/mediatek/clk-mt2712-jpgdec.c
index 7e8c2ebcdee0..019080d6d0f0 100644
--- a/drivers/clk/mediatek/clk-mt2712-jpgdec.c
+++ b/drivers/clk/mediatek/clk-mt2712-jpgdec.c
@@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_jpgdec);
static struct platform_driver clk_mt2712_jpgdec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2712-jpgdec",
.of_match_table = of_match_clk_mt2712_jpgdec,
diff --git a/drivers/clk/mediatek/clk-mt2712-mfg.c b/drivers/clk/mediatek/clk-mt2712-mfg.c
index 932ea449d299..39161516cf21 100644
--- a/drivers/clk/mediatek/clk-mt2712-mfg.c
+++ b/drivers/clk/mediatek/clk-mt2712-mfg.c
@@ -42,7 +42,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_mfg);
static struct platform_driver clk_mt2712_mfg_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2712-mfg",
.of_match_table = of_match_clk_mt2712_mfg,
diff --git a/drivers/clk/mediatek/clk-mt2712-mm.c b/drivers/clk/mediatek/clk-mt2712-mm.c
index 204a3eae08dc..15cb61fe2d2f 100644
--- a/drivers/clk/mediatek/clk-mt2712-mm.c
+++ b/drivers/clk/mediatek/clk-mt2712-mm.c
@@ -121,7 +121,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt2712_mm_id_table);
static struct platform_driver clk_mt2712_mm_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt2712-mm",
},
diff --git a/drivers/clk/mediatek/clk-mt2712-vdec.c b/drivers/clk/mediatek/clk-mt2712-vdec.c
index 2fc1f82ebf5d..e1dd38fc2b3c 100644
--- a/drivers/clk/mediatek/clk-mt2712-vdec.c
+++ b/drivers/clk/mediatek/clk-mt2712-vdec.c
@@ -55,7 +55,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_vdec);
static struct platform_driver clk_mt2712_vdec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2712-vdec",
.of_match_table = of_match_clk_mt2712_vdec,
diff --git a/drivers/clk/mediatek/clk-mt2712-venc.c b/drivers/clk/mediatek/clk-mt2712-venc.c
index 6d053a00cf95..ef6608a5db38 100644
--- a/drivers/clk/mediatek/clk-mt2712-venc.c
+++ b/drivers/clk/mediatek/clk-mt2712-venc.c
@@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_venc);
static struct platform_driver clk_mt2712_venc_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2712-venc",
.of_match_table = of_match_clk_mt2712_venc,
diff --git a/drivers/clk/mediatek/clk-mt2712.c b/drivers/clk/mediatek/clk-mt2712.c
index 74c529f6163d..c4cc68c47af9 100644
--- a/drivers/clk/mediatek/clk-mt2712.c
+++ b/drivers/clk/mediatek/clk-mt2712.c
@@ -995,7 +995,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712);
static struct platform_driver clk_mt2712_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt2712",
.of_match_table = of_match_clk_mt2712,
diff --git a/drivers/clk/mediatek/clk-mt6765-audio.c b/drivers/clk/mediatek/clk-mt6765-audio.c
index 9e98d6997329..901bf793c272 100644
--- a/drivers/clk/mediatek/clk-mt6765-audio.c
+++ b/drivers/clk/mediatek/clk-mt6765-audio.c
@@ -69,7 +69,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6765_audio);
static struct platform_driver clk_mt6765_audio_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6765-audio",
.of_match_table = of_match_clk_mt6765_audio,
diff --git a/drivers/clk/mediatek/clk-mt6765-cam.c b/drivers/clk/mediatek/clk-mt6765-cam.c
index 6f6b29d8b29a..19cedfa832bc 100644
--- a/drivers/clk/mediatek/clk-mt6765-cam.c
+++ b/drivers/clk/mediatek/clk-mt6765-cam.c
@@ -50,7 +50,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6765_cam);
static struct platform_driver clk_mt6765_cam_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6765-cam",
.of_match_table = of_match_clk_mt6765_cam,
diff --git a/drivers/clk/mediatek/clk-mt6765-img.c b/drivers/clk/mediatek/clk-mt6765-img.c
index 984201077a20..16e20c61932e 100644
--- a/drivers/clk/mediatek/clk-mt6765-img.c
+++ b/drivers/clk/mediatek/clk-mt6765-img.c
@@ -46,7 +46,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6765_img);
static struct platform_driver clk_mt6765_img_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6765-img",
.of_match_table = of_match_clk_mt6765_img,
diff --git a/drivers/clk/mediatek/clk-mt6765-mipi0a.c b/drivers/clk/mediatek/clk-mt6765-mipi0a.c
index a47937f4efe5..cc5bb0c95f08 100644
--- a/drivers/clk/mediatek/clk-mt6765-mipi0a.c
+++ b/drivers/clk/mediatek/clk-mt6765-mipi0a.c
@@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6765_mipi0a);
static struct platform_driver clk_mt6765_mipi0a_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6765-mipi0a",
.of_match_table = of_match_clk_mt6765_mipi0a,
diff --git a/drivers/clk/mediatek/clk-mt6765-mm.c b/drivers/clk/mediatek/clk-mt6765-mm.c
index 2b8fc052558e..fc5842e13b78 100644
--- a/drivers/clk/mediatek/clk-mt6765-mm.c
+++ b/drivers/clk/mediatek/clk-mt6765-mm.c
@@ -72,7 +72,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6765_mm);
static struct platform_driver clk_mt6765_mm_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6765-mm",
.of_match_table = of_match_clk_mt6765_mm,
diff --git a/drivers/clk/mediatek/clk-mt6765-vcodec.c b/drivers/clk/mediatek/clk-mt6765-vcodec.c
index 36df9615b1be..d6e036795b0a 100644
--- a/drivers/clk/mediatek/clk-mt6765-vcodec.c
+++ b/drivers/clk/mediatek/clk-mt6765-vcodec.c
@@ -45,7 +45,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6765_vcodec);
static struct platform_driver clk_mt6765_vcodec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6765-vcodec",
.of_match_table = of_match_clk_mt6765_vcodec,
diff --git a/drivers/clk/mediatek/clk-mt6765.c b/drivers/clk/mediatek/clk-mt6765.c
index fa7948ef1e68..0377e6dd3206 100644
--- a/drivers/clk/mediatek/clk-mt6765.c
+++ b/drivers/clk/mediatek/clk-mt6765.c
@@ -367,10 +367,12 @@ static const struct mtk_mux top_muxes[] = {
/* CLK_CFG_0 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR,
- 0, 2, 7, CLK_CFG_UPDATE, 0, CLK_IS_CRITICAL),
+ 0, 2, 7, CLK_CFG_UPDATE, 0,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents,
CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR,
- 8, 2, 15, CLK_CFG_UPDATE, 1, CLK_IS_CRITICAL),
+ 8, 2, 15, CLK_CFG_UPDATE, 1,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MM_SEL, "mm_sel", mm_parents, CLK_CFG_0,
CLK_CFG_0_SET, CLK_CFG_0_CLR, 16, 3, 23,
CLK_CFG_UPDATE, 2),
@@ -404,15 +406,15 @@ static const struct mtk_mux top_muxes[] = {
CLK_CFG_2_SET, CLK_CFG_2_CLR, 24, 2, 31,
CLK_CFG_UPDATE, 11),
/* CLK_CFG_3 */
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc5hclk",
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc5hclk",
msdc5hclk_parents, CLK_CFG_3, CLK_CFG_3_SET,
- CLK_CFG_3_CLR, 0, 2, 7, CLK_CFG_UPDATE, 12),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel",
+ CLK_CFG_3_CLR, 0, 2, 7, CLK_CFG_UPDATE, 12, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel",
msdc50_0_parents, CLK_CFG_3, CLK_CFG_3_SET,
- CLK_CFG_3_CLR, 8, 3, 15, CLK_CFG_UPDATE, 13),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel",
+ CLK_CFG_3_CLR, 8, 3, 15, CLK_CFG_UPDATE, 13, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel",
msdc30_1_parents, CLK_CFG_3, CLK_CFG_3_SET,
- CLK_CFG_3_CLR, 16, 3, 23, CLK_CFG_UPDATE, 14),
+ CLK_CFG_3_CLR, 16, 3, 23, CLK_CFG_UPDATE, 14, 0),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents,
CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR,
24, 2, 31, CLK_CFG_UPDATE, 15),
@@ -459,7 +461,7 @@ static const struct mtk_mux top_muxes[] = {
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_PWRAP_ULPOSC_SEL, "ulposc_sel",
ulposc_parents, CLK_CFG_7, CLK_CFG_7_SET,
CLK_CFG_7_CLR, 0, 3, 7, CLK_CFG_UPDATE, 28,
- CLK_IS_CRITICAL),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM_SEL, "camtm_sel", camtm_parents,
CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, 8, 2, 15,
CLK_CFG_UPDATE, 29),
diff --git a/drivers/clk/mediatek/clk-mt6779-aud.c b/drivers/clk/mediatek/clk-mt6779-aud.c
index 6e3280d3a2e6..a97e1117d30b 100644
--- a/drivers/clk/mediatek/clk-mt6779-aud.c
+++ b/drivers/clk/mediatek/clk-mt6779-aud.c
@@ -106,7 +106,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_aud);
static struct platform_driver clk_mt6779_aud_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6779-aud",
.of_match_table = of_match_clk_mt6779_aud,
diff --git a/drivers/clk/mediatek/clk-mt6779-cam.c b/drivers/clk/mediatek/clk-mt6779-cam.c
index b4c4c7248672..7b1a40d891ad 100644
--- a/drivers/clk/mediatek/clk-mt6779-cam.c
+++ b/drivers/clk/mediatek/clk-mt6779-cam.c
@@ -55,7 +55,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_cam);
static struct platform_driver clk_mt6779_cam_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6779-cam",
.of_match_table = of_match_clk_mt6779_cam,
diff --git a/drivers/clk/mediatek/clk-mt6779-img.c b/drivers/clk/mediatek/clk-mt6779-img.c
index b760a8af3462..1c53209f60a9 100644
--- a/drivers/clk/mediatek/clk-mt6779-img.c
+++ b/drivers/clk/mediatek/clk-mt6779-img.c
@@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_img);
static struct platform_driver clk_mt6779_img_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6779-img",
.of_match_table = of_match_clk_mt6779_img,
diff --git a/drivers/clk/mediatek/clk-mt6779-ipe.c b/drivers/clk/mediatek/clk-mt6779-ipe.c
index 9285a792c59b..784bc08ace5e 100644
--- a/drivers/clk/mediatek/clk-mt6779-ipe.c
+++ b/drivers/clk/mediatek/clk-mt6779-ipe.c
@@ -49,7 +49,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_ipe);
static struct platform_driver clk_mt6779_ipe_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6779-ipe",
.of_match_table = of_match_clk_mt6779_ipe,
diff --git a/drivers/clk/mediatek/clk-mt6779-mfg.c b/drivers/clk/mediatek/clk-mt6779-mfg.c
index d20f32d4f827..040e4c45fa5f 100644
--- a/drivers/clk/mediatek/clk-mt6779-mfg.c
+++ b/drivers/clk/mediatek/clk-mt6779-mfg.c
@@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_mfg);
static struct platform_driver clk_mt6779_mfg_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6779-mfg",
.of_match_table = of_match_clk_mt6779_mfg,
diff --git a/drivers/clk/mediatek/clk-mt6779-mm.c b/drivers/clk/mediatek/clk-mt6779-mm.c
index c2f700ae6c2c..5e17e441f679 100644
--- a/drivers/clk/mediatek/clk-mt6779-mm.c
+++ b/drivers/clk/mediatek/clk-mt6779-mm.c
@@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt6779_mm_id_table);
static struct platform_driver clk_mt6779_mm_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt6779-mm",
},
diff --git a/drivers/clk/mediatek/clk-mt6779-vdec.c b/drivers/clk/mediatek/clk-mt6779-vdec.c
index e062ed5aa45f..a411c23512b7 100644
--- a/drivers/clk/mediatek/clk-mt6779-vdec.c
+++ b/drivers/clk/mediatek/clk-mt6779-vdec.c
@@ -56,7 +56,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_vdec);
static struct platform_driver clk_mt6779_vdec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6779-vdec",
.of_match_table = of_match_clk_mt6779_vdec,
diff --git a/drivers/clk/mediatek/clk-mt6779-venc.c b/drivers/clk/mediatek/clk-mt6779-venc.c
index 0ae8ac28f838..f14512d284d6 100644
--- a/drivers/clk/mediatek/clk-mt6779-venc.c
+++ b/drivers/clk/mediatek/clk-mt6779-venc.c
@@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_venc);
static struct platform_driver clk_mt6779_venc_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6779-venc",
.of_match_table = of_match_clk_mt6779_venc,
diff --git a/drivers/clk/mediatek/clk-mt6779.c b/drivers/clk/mediatek/clk-mt6779.c
index 1f5ea1508f61..f33fbaee1404 100644
--- a/drivers/clk/mediatek/clk-mt6779.c
+++ b/drivers/clk/mediatek/clk-mt6779.c
@@ -640,7 +640,7 @@ static const struct mtk_mux top_muxes[] = {
/* CLK_CFG_0 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI, "axi_sel", axi_parents,
0x20, 0x24, 0x28, 0, 2, 7,
- 0x004, 0, CLK_IS_CRITICAL),
+ 0x004, 0, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MM, "mm_sel", mm_parents,
0x20, 0x24, 0x28, 8, 3, 15, 0x004, 1),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SCP, "scp_sel", scp_parents,
@@ -687,16 +687,16 @@ static const struct mtk_mux top_muxes[] = {
0x70, 0x74, 0x78, 0, 1, 7, 0x004, 20),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI, "spi_sel", spi_parents,
0x70, 0x74, 0x78, 8, 2, 15, 0x004, 21),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK, "msdc50_hclk_sel",
- msdc50_hclk_parents, 0x70, 0x74, 0x78,
- 16, 2, 23, 0x004, 22),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0, "msdc50_0_sel",
- msdc50_0_parents, 0x70, 0x74, 0x78,
- 24, 3, 31, 0x004, 23),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_HCLK, "msdc50_hclk_sel",
+ msdc50_hclk_parents, 0x70, 0x74, 0x78,
+ 16, 2, 23, 0x004, 22, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0, "msdc50_0_sel",
+ msdc50_0_parents, 0x70, 0x74, 0x78,
+ 24, 3, 31, 0x004, 23, 0),
/* CLK_CFG_6 */
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1, "msdc30_1_sel",
- msdc30_1_parents, 0x80, 0x84, 0x88,
- 0, 3, 7, 0x004, 24),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1, "msdc30_1_sel",
+ msdc30_1_parents, 0x80, 0x84, 0x88,
+ 0, 3, 7, 0x004, 24, 0),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD, "audio_sel", audio_parents,
0x80, 0x84, 0x88, 8, 2, 15, 0x004, 25),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS, "aud_intbus_sel",
@@ -710,7 +710,7 @@ static const struct mtk_mux top_muxes[] = {
0x90, 0x94, 0x98, 0, 2, 7, 0x004, 28),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SSPM, "sspm_sel", sspm_parents,
0x90, 0x94, 0x98, 8, 3, 15,
- 0x004, 29, CLK_IS_CRITICAL),
+ 0x004, 29, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI0, "dpi0_sel", dpi0_parents,
0x90, 0x94, 0x98, 16, 3, 23, 0x004, 30),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SCAM, "scam_sel", scam_parents,
@@ -727,7 +727,7 @@ static const struct mtk_mux top_muxes[] = {
16, 2, 23, 0x008, 3),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM, "spm_sel", spm_parents,
0xa0, 0xa4, 0xa8, 24, 2, 31,
- 0x008, 4, CLK_IS_CRITICAL),
+ 0x008, 4, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
/* CLK_CFG_9 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C, "i2c_sel", i2c_parents,
0xb0, 0xb4, 0xb8, 0, 2, 7, 0x008, 5),
@@ -1303,7 +1303,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779);
static struct platform_driver clk_mt6779_infra_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6779-infra",
.of_match_table = of_match_clk_mt6779_infra,
diff --git a/drivers/clk/mediatek/clk-mt6795-apmixedsys.c b/drivers/clk/mediatek/clk-mt6795-apmixedsys.c
index 8b30109f253c..8c65974ed9b8 100644
--- a/drivers/clk/mediatek/clk-mt6795-apmixedsys.c
+++ b/drivers/clk/mediatek/clk-mt6795-apmixedsys.c
@@ -187,7 +187,7 @@ free_clk_data:
return ret;
}
-static int clk_mt6795_apmixed_remove(struct platform_device *pdev)
+static void clk_mt6795_apmixed_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -197,13 +197,11 @@ static int clk_mt6795_apmixed_remove(struct platform_device *pdev)
mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs,
ARRAY_SIZE(pllfhs), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static struct platform_driver clk_mt6795_apmixed_drv = {
.probe = clk_mt6795_apmixed_probe,
- .remove = clk_mt6795_apmixed_remove,
+ .remove_new = clk_mt6795_apmixed_remove,
.driver = {
.name = "clk-mt6795-apmixed",
.of_match_table = of_match_clk_mt6795_apmixed,
diff --git a/drivers/clk/mediatek/clk-mt6795-infracfg.c b/drivers/clk/mediatek/clk-mt6795-infracfg.c
index 086ea1438564..06d7fdf3098b 100644
--- a/drivers/clk/mediatek/clk-mt6795-infracfg.c
+++ b/drivers/clk/mediatek/clk-mt6795-infracfg.c
@@ -127,7 +127,7 @@ free_clk_data:
return ret;
}
-static int clk_mt6795_infracfg_remove(struct platform_device *pdev)
+static void clk_mt6795_infracfg_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -136,8 +136,6 @@ static int clk_mt6795_infracfg_remove(struct platform_device *pdev)
mtk_clk_unregister_cpumuxes(cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data);
mtk_clk_unregister_gates(infra_gates, ARRAY_SIZE(infra_gates), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static struct platform_driver clk_mt6795_infracfg_drv = {
@@ -146,7 +144,7 @@ static struct platform_driver clk_mt6795_infracfg_drv = {
.of_match_table = of_match_clk_mt6795_infracfg,
},
.probe = clk_mt6795_infracfg_probe,
- .remove = clk_mt6795_infracfg_remove,
+ .remove_new = clk_mt6795_infracfg_remove,
};
module_platform_driver(clk_mt6795_infracfg_drv);
diff --git a/drivers/clk/mediatek/clk-mt6795-mfg.c b/drivers/clk/mediatek/clk-mt6795-mfg.c
index 1d658bb19e82..dff6a6ded837 100644
--- a/drivers/clk/mediatek/clk-mt6795-mfg.c
+++ b/drivers/clk/mediatek/clk-mt6795-mfg.c
@@ -43,7 +43,7 @@ static struct platform_driver clk_mt6795_mfg_drv = {
.of_match_table = of_match_clk_mt6795_mfg,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt6795_mfg_drv);
diff --git a/drivers/clk/mediatek/clk-mt6795-mm.c b/drivers/clk/mediatek/clk-mt6795-mm.c
index 8acc9cad2875..ced6e310d694 100644
--- a/drivers/clk/mediatek/clk-mt6795-mm.c
+++ b/drivers/clk/mediatek/clk-mt6795-mm.c
@@ -93,7 +93,7 @@ static struct platform_driver clk_mt6795_mm_drv = {
},
.id_table = clk_mt6795_mm_id_table,
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
};
module_platform_driver(clk_mt6795_mm_drv);
diff --git a/drivers/clk/mediatek/clk-mt6795-pericfg.c b/drivers/clk/mediatek/clk-mt6795-pericfg.c
index 62cc19eee2c7..3f6bea418a5a 100644
--- a/drivers/clk/mediatek/clk-mt6795-pericfg.c
+++ b/drivers/clk/mediatek/clk-mt6795-pericfg.c
@@ -136,7 +136,7 @@ free_clk_data:
return ret;
}
-static int clk_mt6795_pericfg_remove(struct platform_device *pdev)
+static void clk_mt6795_pericfg_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -145,8 +145,6 @@ static int clk_mt6795_pericfg_remove(struct platform_device *pdev)
mtk_clk_unregister_composites(peri_clks, ARRAY_SIZE(peri_clks), clk_data);
mtk_clk_unregister_gates(peri_gates, ARRAY_SIZE(peri_gates), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static struct platform_driver clk_mt6795_pericfg_drv = {
@@ -155,7 +153,7 @@ static struct platform_driver clk_mt6795_pericfg_drv = {
.of_match_table = of_match_clk_mt6795_pericfg,
},
.probe = clk_mt6795_pericfg_probe,
- .remove = clk_mt6795_pericfg_remove,
+ .remove_new = clk_mt6795_pericfg_remove,
};
module_platform_driver(clk_mt6795_pericfg_drv);
diff --git a/drivers/clk/mediatek/clk-mt6795-topckgen.c b/drivers/clk/mediatek/clk-mt6795-topckgen.c
index 9c6d63a80b19..be595853a925 100644
--- a/drivers/clk/mediatek/clk-mt6795-topckgen.c
+++ b/drivers/clk/mediatek/clk-mt6795-topckgen.c
@@ -547,7 +547,7 @@ static struct platform_driver clk_mt6795_topckgen_drv = {
.of_match_table = of_match_clk_mt6795_topckgen,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt6795_topckgen_drv);
diff --git a/drivers/clk/mediatek/clk-mt6795-vdecsys.c b/drivers/clk/mediatek/clk-mt6795-vdecsys.c
index f2968f859dca..9e91d6f7f5bf 100644
--- a/drivers/clk/mediatek/clk-mt6795-vdecsys.c
+++ b/drivers/clk/mediatek/clk-mt6795-vdecsys.c
@@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6795_vdecsys);
static struct platform_driver clk_mt6795_vdecsys_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6795-vdecsys",
.of_match_table = of_match_clk_mt6795_vdecsys,
diff --git a/drivers/clk/mediatek/clk-mt6795-vencsys.c b/drivers/clk/mediatek/clk-mt6795-vencsys.c
index 2f8d48da1a85..bd81e80b744f 100644
--- a/drivers/clk/mediatek/clk-mt6795-vencsys.c
+++ b/drivers/clk/mediatek/clk-mt6795-vencsys.c
@@ -43,7 +43,7 @@ static struct platform_driver clk_mt6795_vencsys_drv = {
.of_match_table = of_match_clk_mt6795_vencsys,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt6795_vencsys_drv);
diff --git a/drivers/clk/mediatek/clk-mt6797-img.c b/drivers/clk/mediatek/clk-mt6797-img.c
index 00fc0a03e646..e1c1ee692a1d 100644
--- a/drivers/clk/mediatek/clk-mt6797-img.c
+++ b/drivers/clk/mediatek/clk-mt6797-img.c
@@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6797_img);
static struct platform_driver clk_mt6797_img_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6797-img",
.of_match_table = of_match_clk_mt6797_img,
diff --git a/drivers/clk/mediatek/clk-mt6797-mm.c b/drivers/clk/mediatek/clk-mt6797-mm.c
index caacfa40a5bc..5b0a77530b62 100644
--- a/drivers/clk/mediatek/clk-mt6797-mm.c
+++ b/drivers/clk/mediatek/clk-mt6797-mm.c
@@ -93,7 +93,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt6797_mm_id_table);
static struct platform_driver clk_mt6797_mm_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt6797-mm",
},
diff --git a/drivers/clk/mediatek/clk-mt6797-vdec.c b/drivers/clk/mediatek/clk-mt6797-vdec.c
index 447fe6fa8e15..0ed6710ab88e 100644
--- a/drivers/clk/mediatek/clk-mt6797-vdec.c
+++ b/drivers/clk/mediatek/clk-mt6797-vdec.c
@@ -54,7 +54,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6797_vdec);
static struct platform_driver clk_mt6797_vdec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6797-vdec",
.of_match_table = of_match_clk_mt6797_vdec,
diff --git a/drivers/clk/mediatek/clk-mt6797-venc.c b/drivers/clk/mediatek/clk-mt6797-venc.c
index 95b89ff8fd19..93d1da7423fe 100644
--- a/drivers/clk/mediatek/clk-mt6797-venc.c
+++ b/drivers/clk/mediatek/clk-mt6797-venc.c
@@ -45,7 +45,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6797_venc);
static struct platform_driver clk_mt6797_venc_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt6797-venc",
.of_match_table = of_match_clk_mt6797_venc,
diff --git a/drivers/clk/mediatek/clk-mt7622-apmixedsys.c b/drivers/clk/mediatek/clk-mt7622-apmixedsys.c
index a36808d074d6..9cffd278e9a4 100644
--- a/drivers/clk/mediatek/clk-mt7622-apmixedsys.c
+++ b/drivers/clk/mediatek/clk-mt7622-apmixedsys.c
@@ -119,7 +119,7 @@ unregister_plls:
return ret;
}
-static int clk_mt7622_apmixed_remove(struct platform_device *pdev)
+static void clk_mt7622_apmixed_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -128,8 +128,6 @@ static int clk_mt7622_apmixed_remove(struct platform_device *pdev)
mtk_clk_unregister_gates(apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data);
mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static const struct of_device_id of_match_clk_mt7622_apmixed[] = {
@@ -140,7 +138,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7622_apmixed);
static struct platform_driver clk_mt7622_apmixed_drv = {
.probe = clk_mt7622_apmixed_probe,
- .remove = clk_mt7622_apmixed_remove,
+ .remove_new = clk_mt7622_apmixed_remove,
.driver = {
.name = "clk-mt7622-apmixed",
.of_match_table = of_match_clk_mt7622_apmixed,
diff --git a/drivers/clk/mediatek/clk-mt7622-aud.c b/drivers/clk/mediatek/clk-mt7622-aud.c
index dd1799dd8435..c3ce65ced902 100644
--- a/drivers/clk/mediatek/clk-mt7622-aud.c
+++ b/drivers/clk/mediatek/clk-mt7622-aud.c
@@ -135,10 +135,10 @@ err_plat_populate:
return r;
}
-static int clk_mt7622_aud_remove(struct platform_device *pdev)
+static void clk_mt7622_aud_remove(struct platform_device *pdev)
{
of_platform_depopulate(&pdev->dev);
- return mtk_clk_simple_remove(pdev);
+ mtk_clk_simple_remove(pdev);
}
static const struct of_device_id of_match_clk_mt7622_aud[] = {
@@ -149,7 +149,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7622_aud);
static struct platform_driver clk_mt7622_aud_drv = {
.probe = clk_mt7622_aud_probe,
- .remove = clk_mt7622_aud_remove,
+ .remove_new = clk_mt7622_aud_remove,
.driver = {
.name = "clk-mt7622-aud",
.of_match_table = of_match_clk_mt7622_aud,
diff --git a/drivers/clk/mediatek/clk-mt7622-eth.c b/drivers/clk/mediatek/clk-mt7622-eth.c
index f96b36737029..df81e445026a 100644
--- a/drivers/clk/mediatek/clk-mt7622-eth.c
+++ b/drivers/clk/mediatek/clk-mt7622-eth.c
@@ -81,7 +81,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7622_eth);
static struct platform_driver clk_mt7622_eth_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt7622-eth",
.of_match_table = of_match_clk_mt7622_eth,
diff --git a/drivers/clk/mediatek/clk-mt7622-hif.c b/drivers/clk/mediatek/clk-mt7622-hif.c
index f440943f0d46..9c738d730a7b 100644
--- a/drivers/clk/mediatek/clk-mt7622-hif.c
+++ b/drivers/clk/mediatek/clk-mt7622-hif.c
@@ -93,7 +93,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7622_hif);
static struct platform_driver clk_mt7622_hif_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt7622-hif",
.of_match_table = of_match_clk_mt7622_hif,
diff --git a/drivers/clk/mediatek/clk-mt7622-infracfg.c b/drivers/clk/mediatek/clk-mt7622-infracfg.c
index 9dc05526f287..6bc911cb29a6 100644
--- a/drivers/clk/mediatek/clk-mt7622-infracfg.c
+++ b/drivers/clk/mediatek/clk-mt7622-infracfg.c
@@ -101,7 +101,7 @@ free_clk_data:
return ret;
}
-static int clk_mt7622_infracfg_remove(struct platform_device *pdev)
+static void clk_mt7622_infracfg_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -110,8 +110,6 @@ static int clk_mt7622_infracfg_remove(struct platform_device *pdev)
mtk_clk_unregister_cpumuxes(cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data);
mtk_clk_unregister_gates(infra_clks, ARRAY_SIZE(infra_clks), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static struct platform_driver clk_mt7622_infracfg_drv = {
@@ -120,7 +118,7 @@ static struct platform_driver clk_mt7622_infracfg_drv = {
.of_match_table = of_match_clk_mt7622_infracfg,
},
.probe = clk_mt7622_infracfg_probe,
- .remove = clk_mt7622_infracfg_remove,
+ .remove_new = clk_mt7622_infracfg_remove,
};
module_platform_driver(clk_mt7622_infracfg_drv);
diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c
index 274895264427..fa5fb5891a09 100644
--- a/drivers/clk/mediatek/clk-mt7622.c
+++ b/drivers/clk/mediatek/clk-mt7622.c
@@ -526,7 +526,7 @@ static struct platform_driver clk_mt7622_drv = {
.of_match_table = of_match_clk_mt7622,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt7622_drv)
diff --git a/drivers/clk/mediatek/clk-mt7629-hif.c b/drivers/clk/mediatek/clk-mt7629-hif.c
index c89036bee9a7..ec3a71ebb766 100644
--- a/drivers/clk/mediatek/clk-mt7629-hif.c
+++ b/drivers/clk/mediatek/clk-mt7629-hif.c
@@ -88,7 +88,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7629_hif);
static struct platform_driver clk_mt7629_hif_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt7629-hif",
.of_match_table = of_match_clk_mt7629_hif,
diff --git a/drivers/clk/mediatek/clk-mt7981-eth.c b/drivers/clk/mediatek/clk-mt7981-eth.c
index b1f256b5ed4e..6bc509a54e14 100644
--- a/drivers/clk/mediatek/clk-mt7981-eth.c
+++ b/drivers/clk/mediatek/clk-mt7981-eth.c
@@ -109,7 +109,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7981_eth);
static struct platform_driver clk_mt7981_eth_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt7981-eth",
.of_match_table = of_match_clk_mt7981_eth,
diff --git a/drivers/clk/mediatek/clk-mt7981-infracfg.c b/drivers/clk/mediatek/clk-mt7981-infracfg.c
index 293261ef71e6..7e9d3d309151 100644
--- a/drivers/clk/mediatek/clk-mt7981-infracfg.c
+++ b/drivers/clk/mediatek/clk-mt7981-infracfg.c
@@ -199,7 +199,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7981_infracfg);
static struct platform_driver clk_mt7981_infracfg_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt7981-infracfg",
.of_match_table = of_match_clk_mt7981_infracfg,
diff --git a/drivers/clk/mediatek/clk-mt7981-topckgen.c b/drivers/clk/mediatek/clk-mt7981-topckgen.c
index 3aba1a9b9a36..4740776e7aab 100644
--- a/drivers/clk/mediatek/clk-mt7981-topckgen.c
+++ b/drivers/clk/mediatek/clk-mt7981-topckgen.c
@@ -310,12 +310,12 @@ static const struct mtk_mux top_muxes[] = {
pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2, 31,
0x1C0, 7),
/* CLK_CFG_2 */
- MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_208M_SEL, "emmc_208m_sel",
- emmc_208m_parents, 0x020, 0x024, 0x028, 0, 3, 7,
- 0x1C0, 8),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel",
- emmc_400m_parents, 0x020, 0x024, 0x028, 8, 2, 15,
- 0x1C0, 9),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_EMMC_208M_SEL, "emmc_208m_sel",
+ emmc_208m_parents, 0x020, 0x024, 0x028, 0, 3, 7,
+ 0x1C0, 8, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel",
+ emmc_400m_parents, 0x020, 0x024, 0x028, 8, 2, 15,
+ 0x1C0, 9, 0),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_F26M_SEL, "csw_f26m_sel",
csw_f26m_parents, 0x020, 0x024, 0x028, 16, 1, 23,
0x1C0, 10,
@@ -414,7 +414,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7981_topckgen);
static struct platform_driver clk_mt7981_topckgen_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt7981-topckgen",
.of_match_table = of_match_clk_mt7981_topckgen,
diff --git a/drivers/clk/mediatek/clk-mt7986-eth.c b/drivers/clk/mediatek/clk-mt7986-eth.c
index 0681988960cc..854e2c565041 100644
--- a/drivers/clk/mediatek/clk-mt7986-eth.c
+++ b/drivers/clk/mediatek/clk-mt7986-eth.c
@@ -94,7 +94,7 @@ static struct platform_driver clk_mt7986_eth_drv = {
.of_match_table = of_match_clk_mt7986_eth,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt7986_eth_drv);
diff --git a/drivers/clk/mediatek/clk-mt7986-infracfg.c b/drivers/clk/mediatek/clk-mt7986-infracfg.c
index b7efa70c2d6c..c576e9fb986c 100644
--- a/drivers/clk/mediatek/clk-mt7986-infracfg.c
+++ b/drivers/clk/mediatek/clk-mt7986-infracfg.c
@@ -179,7 +179,7 @@ static struct platform_driver clk_mt7986_infracfg_drv = {
.of_match_table = of_match_clk_mt7986_infracfg,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt7986_infracfg_drv);
diff --git a/drivers/clk/mediatek/clk-mt7986-topckgen.c b/drivers/clk/mediatek/clk-mt7986-topckgen.c
index fbca3feded8f..af151b016872 100644
--- a/drivers/clk/mediatek/clk-mt7986-topckgen.c
+++ b/drivers/clk/mediatek/clk-mt7986-topckgen.c
@@ -193,12 +193,12 @@ static const struct mtk_mux top_muxes[] = {
pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2,
31, 0x1C0, 7),
/* CLK_CFG_2 */
- MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel",
- emmc_250m_parents, 0x020, 0x024, 0x028, 0, 1, 7,
- 0x1C0, 8),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_416M_SEL, "emmc_416m_sel",
- emmc_416m_parents, 0x020, 0x024, 0x028, 8, 1, 15,
- 0x1C0, 9),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel",
+ emmc_250m_parents, 0x020, 0x024, 0x028, 0, 1, 7,
+ 0x1C0, 8, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_EMMC_416M_SEL, "emmc_416m_sel",
+ emmc_416m_parents, 0x020, 0x024, 0x028, 8, 1, 15,
+ 0x1C0, 9, 0),
MUX_GATE_CLR_SET_UPD(CLK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel",
f_26m_adc_parents, 0x020, 0x024, 0x028, 16, 1, 23,
0x1C0, 10),
@@ -308,7 +308,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7986_topckgen);
static struct platform_driver clk_mt7986_topckgen_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt7986-topckgen",
.of_match_table = of_match_clk_mt7986_topckgen,
diff --git a/drivers/clk/mediatek/clk-mt8135-apmixedsys.c b/drivers/clk/mediatek/clk-mt8135-apmixedsys.c
index 744aae092281..d1239b4b3db7 100644
--- a/drivers/clk/mediatek/clk-mt8135-apmixedsys.c
+++ b/drivers/clk/mediatek/clk-mt8135-apmixedsys.c
@@ -73,7 +73,7 @@ unregister_plls:
return ret;
}
-static int clk_mt8135_apmixed_remove(struct platform_device *pdev)
+static void clk_mt8135_apmixed_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -81,8 +81,6 @@ static int clk_mt8135_apmixed_remove(struct platform_device *pdev)
of_clk_del_provider(node);
mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static const struct of_device_id of_match_clk_mt8135_apmixed[] = {
@@ -93,7 +91,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8135_apmixed);
static struct platform_driver clk_mt8135_apmixed_drv = {
.probe = clk_mt8135_apmixed_probe,
- .remove = clk_mt8135_apmixed_remove,
+ .remove_new = clk_mt8135_apmixed_remove,
.driver = {
.name = "clk-mt8135-apmixed",
.of_match_table = of_match_clk_mt8135_apmixed,
diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c
index 084e48a554c2..019af88d7f9c 100644
--- a/drivers/clk/mediatek/clk-mt8135.c
+++ b/drivers/clk/mediatek/clk-mt8135.c
@@ -558,7 +558,7 @@ static struct platform_driver clk_mt8135_drv = {
.of_match_table = of_match_clk_mt8135,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt8135_drv);
diff --git a/drivers/clk/mediatek/clk-mt8167-aud.c b/drivers/clk/mediatek/clk-mt8167-aud.c
index 86125635c8a6..b73058edf3d6 100644
--- a/drivers/clk/mediatek/clk-mt8167-aud.c
+++ b/drivers/clk/mediatek/clk-mt8167-aud.c
@@ -56,7 +56,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8167_audsys);
static struct platform_driver clk_mt8167_audsys_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8167-audsys",
.of_match_table = of_match_clk_mt8167_audsys,
diff --git a/drivers/clk/mediatek/clk-mt8167-img.c b/drivers/clk/mediatek/clk-mt8167-img.c
index 315b7f64bad6..ba07d20f14b3 100644
--- a/drivers/clk/mediatek/clk-mt8167-img.c
+++ b/drivers/clk/mediatek/clk-mt8167-img.c
@@ -48,7 +48,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8167_imgsys);
static struct platform_driver clk_mt8167_imgsys_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8167-imgsys",
.of_match_table = of_match_clk_mt8167_imgsys,
diff --git a/drivers/clk/mediatek/clk-mt8167-mfgcfg.c b/drivers/clk/mediatek/clk-mt8167-mfgcfg.c
index 4851f5bf3a90..5f7dbaf97e96 100644
--- a/drivers/clk/mediatek/clk-mt8167-mfgcfg.c
+++ b/drivers/clk/mediatek/clk-mt8167-mfgcfg.c
@@ -46,7 +46,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8167_mfgcfg);
static struct platform_driver clk_mt8167_mfgcfg_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8167-mfgcfg",
.of_match_table = of_match_clk_mt8167_mfgcfg,
diff --git a/drivers/clk/mediatek/clk-mt8167-mm.c b/drivers/clk/mediatek/clk-mt8167-mm.c
index 4e053c61315d..6472e76567a5 100644
--- a/drivers/clk/mediatek/clk-mt8167-mm.c
+++ b/drivers/clk/mediatek/clk-mt8167-mm.c
@@ -87,7 +87,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8167_mm_id_table);
static struct platform_driver clk_mt8167_mm_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8167-mm",
},
diff --git a/drivers/clk/mediatek/clk-mt8167-vdec.c b/drivers/clk/mediatek/clk-mt8167-vdec.c
index 76900f393d31..2f662b3f16a9 100644
--- a/drivers/clk/mediatek/clk-mt8167-vdec.c
+++ b/drivers/clk/mediatek/clk-mt8167-vdec.c
@@ -55,7 +55,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8167_vdec);
static struct platform_driver clk_mt8167_vdec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8167-vdecsys",
.of_match_table = of_match_clk_mt8167_vdec,
diff --git a/drivers/clk/mediatek/clk-mt8167.c b/drivers/clk/mediatek/clk-mt8167.c
index b9041f79cbbd..270221c6e6e8 100644
--- a/drivers/clk/mediatek/clk-mt8167.c
+++ b/drivers/clk/mediatek/clk-mt8167.c
@@ -887,7 +887,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8167);
static struct platform_driver clk_mt8167_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8167",
.of_match_table = of_match_clk_mt8167,
diff --git a/drivers/clk/mediatek/clk-mt8173-apmixedsys.c b/drivers/clk/mediatek/clk-mt8173-apmixedsys.c
index 8c2aa8b0f39e..1bbb21ab1786 100644
--- a/drivers/clk/mediatek/clk-mt8173-apmixedsys.c
+++ b/drivers/clk/mediatek/clk-mt8173-apmixedsys.c
@@ -148,11 +148,13 @@ static int clk_mt8173_apmixed_probe(struct platform_device *pdev)
base = of_iomap(node, 0);
if (!base)
- return PTR_ERR(base);
+ return -ENOMEM;
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
- if (IS_ERR_OR_NULL(clk_data))
+ if (IS_ERR_OR_NULL(clk_data)) {
+ iounmap(base);
return -ENOMEM;
+ }
fhctl_parse_dt(fhctl_node, pllfhs, ARRAY_SIZE(pllfhs));
r = mtk_clk_register_pllfhs(node, plls, ARRAY_SIZE(plls),
@@ -186,10 +188,11 @@ unregister_plls:
ARRAY_SIZE(pllfhs), clk_data);
free_clk_data:
mtk_free_clk_data(clk_data);
+ iounmap(base);
return r;
}
-static int clk_mt8173_apmixed_remove(struct platform_device *pdev)
+static void clk_mt8173_apmixed_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -199,13 +202,11 @@ static int clk_mt8173_apmixed_remove(struct platform_device *pdev)
mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs,
ARRAY_SIZE(pllfhs), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static struct platform_driver clk_mt8173_apmixed_drv = {
.probe = clk_mt8173_apmixed_probe,
- .remove = clk_mt8173_apmixed_remove,
+ .remove_new = clk_mt8173_apmixed_remove,
.driver = {
.name = "clk-mt8173-apmixed",
.of_match_table = of_match_clk_mt8173_apmixed,
diff --git a/drivers/clk/mediatek/clk-mt8173-img.c b/drivers/clk/mediatek/clk-mt8173-img.c
index 6db2b9ab2bc9..1011b9ab3dad 100644
--- a/drivers/clk/mediatek/clk-mt8173-img.c
+++ b/drivers/clk/mediatek/clk-mt8173-img.c
@@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8173_imgsys);
static struct platform_driver clk_mt8173_vdecsys_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8173-imgsys",
.of_match_table = of_match_clk_mt8173_imgsys,
diff --git a/drivers/clk/mediatek/clk-mt8173-infracfg.c b/drivers/clk/mediatek/clk-mt8173-infracfg.c
index 4ed5043076ec..2f2f074e231a 100644
--- a/drivers/clk/mediatek/clk-mt8173-infracfg.c
+++ b/drivers/clk/mediatek/clk-mt8173-infracfg.c
@@ -129,7 +129,7 @@ unregister_gates:
return r;
}
-static int clk_mt8173_infracfg_remove(struct platform_device *pdev)
+static void clk_mt8173_infracfg_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -138,8 +138,6 @@ static int clk_mt8173_infracfg_remove(struct platform_device *pdev)
mtk_clk_unregister_cpumuxes(cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data);
mtk_clk_unregister_gates(infra_gates, ARRAY_SIZE(infra_gates), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static struct platform_driver clk_mt8173_infracfg_drv = {
@@ -148,7 +146,7 @@ static struct platform_driver clk_mt8173_infracfg_drv = {
.of_match_table = of_match_clk_mt8173_infracfg,
},
.probe = clk_mt8173_infracfg_probe,
- .remove = clk_mt8173_infracfg_remove,
+ .remove_new = clk_mt8173_infracfg_remove,
};
module_platform_driver(clk_mt8173_infracfg_drv);
diff --git a/drivers/clk/mediatek/clk-mt8173-mm.c b/drivers/clk/mediatek/clk-mt8173-mm.c
index 18e466dbf610..ffed6c5bfde2 100644
--- a/drivers/clk/mediatek/clk-mt8173-mm.c
+++ b/drivers/clk/mediatek/clk-mt8173-mm.c
@@ -106,7 +106,7 @@ static struct platform_driver clk_mt8173_mm_drv = {
},
.id_table = clk_mt8173_mm_id_table,
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
};
module_platform_driver(clk_mt8173_mm_drv);
diff --git a/drivers/clk/mediatek/clk-mt8173-pericfg.c b/drivers/clk/mediatek/clk-mt8173-pericfg.c
index bebda74d0f43..783efed3f254 100644
--- a/drivers/clk/mediatek/clk-mt8173-pericfg.c
+++ b/drivers/clk/mediatek/clk-mt8173-pericfg.c
@@ -115,7 +115,7 @@ static struct platform_driver clk_mt8173_pericfg_drv = {
.of_match_table = of_match_clk_mt8173_pericfg,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt8173_pericfg_drv);
diff --git a/drivers/clk/mediatek/clk-mt8173-topckgen.c b/drivers/clk/mediatek/clk-mt8173-topckgen.c
index baa8fd6cb312..6bb7ffd74487 100644
--- a/drivers/clk/mediatek/clk-mt8173-topckgen.c
+++ b/drivers/clk/mediatek/clk-mt8173-topckgen.c
@@ -547,17 +547,17 @@ static const struct mtk_composite top_muxes[] = {
MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31),
/* CLK_CFG_3 */
MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7),
- MUX_GATE(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents,
- 0x0070, 8, 3, 15),
- MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents,
- 0x0070, 16, 4, 23),
- MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents,
- 0x0070, 24, 3, 31),
+ MUX_GATE_FLAGS(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents,
+ 0x0070, 8, 3, 15, 0),
+ MUX_GATE_FLAGS(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents,
+ 0x0070, 16, 4, 23, 0),
+ MUX_GATE_FLAGS(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents,
+ 0x0070, 24, 3, 31, 0),
/* CLK_CFG_4 */
- MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents,
- 0x0080, 0, 3, 7),
- MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents,
- 0x0080, 8, 4, 15),
+ MUX_GATE_FLAGS(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents,
+ 0x0080, 0, 3, 7, 0),
+ MUX_GATE_FLAGS(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents,
+ 0x0080, 8, 4, 15, 0),
MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents,
0x0080, 16, 2, 23),
MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
@@ -595,8 +595,8 @@ static const struct mtk_composite top_muxes[] = {
MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents,
0x00c0, 24, 3, 31),
/* CLK_CFG_13 */
- MUX_GATE(CLK_TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents,
- 0x00d0, 0, 3, 7),
+ MUX_GATE_FLAGS(CLK_TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents,
+ 0x00d0, 0, 3, 7, 0),
MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15),
MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents,
0x00d0, 16, 2, 23),
@@ -646,7 +646,7 @@ static struct platform_driver clk_mt8173_topckgen_drv = {
.of_match_table = of_match_clk_mt8173_topckgen,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt8173_topckgen_drv);
diff --git a/drivers/clk/mediatek/clk-mt8173-vdecsys.c b/drivers/clk/mediatek/clk-mt8173-vdecsys.c
index 625ca0b09cc2..011e3812156f 100644
--- a/drivers/clk/mediatek/clk-mt8173-vdecsys.c
+++ b/drivers/clk/mediatek/clk-mt8173-vdecsys.c
@@ -46,7 +46,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8173_vdecsys);
static struct platform_driver clk_mt8173_vdecsys_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8173-vdecsys",
.of_match_table = of_match_clk_mt8173_vdecsys,
diff --git a/drivers/clk/mediatek/clk-mt8173-vencsys.c b/drivers/clk/mediatek/clk-mt8173-vencsys.c
index 87755dd1a337..1bf84ae6a0bc 100644
--- a/drivers/clk/mediatek/clk-mt8173-vencsys.c
+++ b/drivers/clk/mediatek/clk-mt8173-vencsys.c
@@ -57,7 +57,7 @@ static struct platform_driver clk_mt8173_vencsys_drv = {
.of_match_table = of_match_clk_mt8173_vencsys,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt8173_vencsys_drv);
diff --git a/drivers/clk/mediatek/clk-mt8183-audio.c b/drivers/clk/mediatek/clk-mt8183-audio.c
index 9938c6466e76..716b26825ef0 100644
--- a/drivers/clk/mediatek/clk-mt8183-audio.c
+++ b/drivers/clk/mediatek/clk-mt8183-audio.c
@@ -87,10 +87,10 @@ static int clk_mt8183_audio_probe(struct platform_device *pdev)
return r;
}
-static int clk_mt8183_audio_remove(struct platform_device *pdev)
+static void clk_mt8183_audio_remove(struct platform_device *pdev)
{
of_platform_depopulate(&pdev->dev);
- return mtk_clk_simple_remove(pdev);
+ mtk_clk_simple_remove(pdev);
}
static const struct of_device_id of_match_clk_mt8183_audio[] = {
@@ -101,7 +101,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_audio);
static struct platform_driver clk_mt8183_audio_drv = {
.probe = clk_mt8183_audio_probe,
- .remove = clk_mt8183_audio_remove,
+ .remove_new = clk_mt8183_audio_remove,
.driver = {
.name = "clk-mt8183-audio",
.of_match_table = of_match_clk_mt8183_audio,
diff --git a/drivers/clk/mediatek/clk-mt8183-cam.c b/drivers/clk/mediatek/clk-mt8183-cam.c
index c0719624004f..b0f8e4242a63 100644
--- a/drivers/clk/mediatek/clk-mt8183-cam.c
+++ b/drivers/clk/mediatek/clk-mt8183-cam.c
@@ -51,7 +51,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_cam);
static struct platform_driver clk_mt8183_cam_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8183-cam",
.of_match_table = of_match_clk_mt8183_cam,
diff --git a/drivers/clk/mediatek/clk-mt8183-img.c b/drivers/clk/mediatek/clk-mt8183-img.c
index 55fc80615724..6e177d2e8872 100644
--- a/drivers/clk/mediatek/clk-mt8183-img.c
+++ b/drivers/clk/mediatek/clk-mt8183-img.c
@@ -51,7 +51,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_img);
static struct platform_driver clk_mt8183_img_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8183-img",
.of_match_table = of_match_clk_mt8183_img,
diff --git a/drivers/clk/mediatek/clk-mt8183-ipu0.c b/drivers/clk/mediatek/clk-mt8183-ipu0.c
index 59255eab6fe2..0b61c7af8aea 100644
--- a/drivers/clk/mediatek/clk-mt8183-ipu0.c
+++ b/drivers/clk/mediatek/clk-mt8183-ipu0.c
@@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_ipu_core0);
static struct platform_driver clk_mt8183_ipu_core0_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8183-ipu_core0",
.of_match_table = of_match_clk_mt8183_ipu_core0,
diff --git a/drivers/clk/mediatek/clk-mt8183-ipu1.c b/drivers/clk/mediatek/clk-mt8183-ipu1.c
index c4baa052c809..544b1ca0e1c5 100644
--- a/drivers/clk/mediatek/clk-mt8183-ipu1.c
+++ b/drivers/clk/mediatek/clk-mt8183-ipu1.c
@@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_ipu_core1);
static struct platform_driver clk_mt8183_ipu_core1_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8183-ipu_core1",
.of_match_table = of_match_clk_mt8183_ipu_core1,
diff --git a/drivers/clk/mediatek/clk-mt8183-ipu_adl.c b/drivers/clk/mediatek/clk-mt8183-ipu_adl.c
index 74866e9c50d7..7f53674f393c 100644
--- a/drivers/clk/mediatek/clk-mt8183-ipu_adl.c
+++ b/drivers/clk/mediatek/clk-mt8183-ipu_adl.c
@@ -42,7 +42,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_ipu_adl);
static struct platform_driver clk_mt8183_ipu_adl_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8183-ipu_adl",
.of_match_table = of_match_clk_mt8183_ipu_adl,
diff --git a/drivers/clk/mediatek/clk-mt8183-ipu_conn.c b/drivers/clk/mediatek/clk-mt8183-ipu_conn.c
index bd7303105357..fb03ad2d8f6a 100644
--- a/drivers/clk/mediatek/clk-mt8183-ipu_conn.c
+++ b/drivers/clk/mediatek/clk-mt8183-ipu_conn.c
@@ -111,7 +111,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_ipu_conn);
static struct platform_driver clk_mt8183_ipu_conn_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8183-ipu_conn",
.of_match_table = of_match_clk_mt8183_ipu_conn,
diff --git a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c
index 816ecf1191ee..ba504e19d420 100644
--- a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c
+++ b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c
@@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_mfg);
static struct platform_driver clk_mt8183_mfg_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8183-mfg",
.of_match_table = of_match_clk_mt8183_mfg,
diff --git a/drivers/clk/mediatek/clk-mt8183-mm.c b/drivers/clk/mediatek/clk-mt8183-mm.c
index 2f99828bff1b..8aaddcfee568 100644
--- a/drivers/clk/mediatek/clk-mt8183-mm.c
+++ b/drivers/clk/mediatek/clk-mt8183-mm.c
@@ -95,7 +95,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8183_mm_id_table);
static struct platform_driver clk_mt8183_mm_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8183-mm",
},
diff --git a/drivers/clk/mediatek/clk-mt8183-vdec.c b/drivers/clk/mediatek/clk-mt8183-vdec.c
index 513b7956cbea..8c99ae89834f 100644
--- a/drivers/clk/mediatek/clk-mt8183-vdec.c
+++ b/drivers/clk/mediatek/clk-mt8183-vdec.c
@@ -55,7 +55,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_vdec);
static struct platform_driver clk_mt8183_vdec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8183-vdec",
.of_match_table = of_match_clk_mt8183_vdec,
diff --git a/drivers/clk/mediatek/clk-mt8183-venc.c b/drivers/clk/mediatek/clk-mt8183-venc.c
index 532f6e12a561..a8e0220902ae 100644
--- a/drivers/clk/mediatek/clk-mt8183-venc.c
+++ b/drivers/clk/mediatek/clk-mt8183-venc.c
@@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_venc);
static struct platform_driver clk_mt8183_venc_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8183-venc",
.of_match_table = of_match_clk_mt8183_venc,
diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c
index 2336a1b69c09..1ba421b38ec5 100644
--- a/drivers/clk/mediatek/clk-mt8183.c
+++ b/drivers/clk/mediatek/clk-mt8183.c
@@ -451,7 +451,8 @@ static const char * const aud_2_parents[] = {
static const struct mtk_mux top_muxes[] = {
/* CLK_CFG_0 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_AXI, "axi_sel",
- axi_parents, 0x40, 0x44, 0x48, 0, 2, 7, 0x004, 0, CLK_IS_CRITICAL),
+ axi_parents, 0x40, 0x44, 0x48, 0, 2, 7, 0x004, 0,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MM, "mm_sel",
mm_parents, 0x40, 0x44, 0x48, 8, 3, 15, 0x004, 1),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_IMG, "img_sel",
@@ -486,14 +487,14 @@ static const struct mtk_mux top_muxes[] = {
MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SPI, "spi_sel",
spi_parents, 0x70, 0x74, 0x78, 24, 2, 31, 0x004, 15),
/* CLK_CFG_4 */
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC50_0_HCLK, "msdc50_hclk_sel",
- msdc50_hclk_parents, 0x80, 0x84, 0x88, 0, 2, 7, 0x004, 16),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC50_0, "msdc50_0_sel",
- msdc50_0_parents, 0x80, 0x84, 0x88, 8, 3, 15, 0x004, 17),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC30_1, "msdc30_1_sel",
- msdc30_1_parents, 0x80, 0x84, 0x88, 16, 3, 23, 0x004, 18),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC30_2, "msdc30_2_sel",
- msdc30_2_parents, 0x80, 0x84, 0x88, 24, 3, 31, 0x004, 19),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_MSDC50_0_HCLK, "msdc50_hclk_sel",
+ msdc50_hclk_parents, 0x80, 0x84, 0x88, 0, 2, 7, 0x004, 16, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_MSDC50_0, "msdc50_0_sel",
+ msdc50_0_parents, 0x80, 0x84, 0x88, 8, 3, 15, 0x004, 17, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_MSDC30_1, "msdc30_1_sel",
+ msdc30_1_parents, 0x80, 0x84, 0x88, 16, 3, 23, 0x004, 18, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_MSDC30_2, "msdc30_2_sel",
+ msdc30_2_parents, 0x80, 0x84, 0x88, 24, 3, 31, 0x004, 19, 0),
/* CLK_CFG_5 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUDIO, "audio_sel",
audio_parents, 0x90, 0x94, 0x98, 0, 2, 7, 0x004, 20),
@@ -518,7 +519,8 @@ static const struct mtk_mux top_muxes[] = {
MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SSUSB_TOP_XHCI, "ssusb_top_xhci_sel",
ssusb_top_xhci_parents, 0xb0, 0xb4, 0xb8, 16, 2, 23, 0x004, 30),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_SPM, "spm_sel",
- spm_parents, 0xb0, 0xb4, 0xb8, 24, 1, 31, 0x008, 0, CLK_IS_CRITICAL),
+ spm_parents, 0xb0, 0xb4, 0xb8, 24, 1, 31, 0x008, 0,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
/* CLK_CFG_8 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_I2C, "i2c_sel",
i2c_parents, 0xc0, 0xc4, 0xc8, 0, 2, 7, 0x008, 1),
@@ -872,7 +874,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183);
static struct platform_driver clk_mt8183_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8183",
.of_match_table = of_match_clk_mt8183,
diff --git a/drivers/clk/mediatek/clk-mt8186-apmixedsys.c b/drivers/clk/mediatek/clk-mt8186-apmixedsys.c
index da7950d51c64..fff64a8fd557 100644
--- a/drivers/clk/mediatek/clk-mt8186-apmixedsys.c
+++ b/drivers/clk/mediatek/clk-mt8186-apmixedsys.c
@@ -172,7 +172,7 @@ free_apmixed_data:
return r;
}
-static int clk_mt8186_apmixed_remove(struct platform_device *pdev)
+static void clk_mt8186_apmixed_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -181,13 +181,11 @@ static int clk_mt8186_apmixed_remove(struct platform_device *pdev)
mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs,
ARRAY_SIZE(pllfhs), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static struct platform_driver clk_mt8186_apmixed_drv = {
.probe = clk_mt8186_apmixed_probe,
- .remove = clk_mt8186_apmixed_remove,
+ .remove_new = clk_mt8186_apmixed_remove,
.driver = {
.name = "clk-mt8186-apmixed",
.of_match_table = of_match_clk_mt8186_apmixed,
diff --git a/drivers/clk/mediatek/clk-mt8186-cam.c b/drivers/clk/mediatek/clk-mt8186-cam.c
index 656d9e6f3ee2..effd2900d2e8 100644
--- a/drivers/clk/mediatek/clk-mt8186-cam.c
+++ b/drivers/clk/mediatek/clk-mt8186-cam.c
@@ -82,7 +82,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_cam);
static struct platform_driver clk_mt8186_cam_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8186-cam",
.of_match_table = of_match_clk_mt8186_cam,
diff --git a/drivers/clk/mediatek/clk-mt8186-img.c b/drivers/clk/mediatek/clk-mt8186-img.c
index 754b27f03817..71b0571e6351 100644
--- a/drivers/clk/mediatek/clk-mt8186-img.c
+++ b/drivers/clk/mediatek/clk-mt8186-img.c
@@ -60,7 +60,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_img);
static struct platform_driver clk_mt8186_img_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8186-img",
.of_match_table = of_match_clk_mt8186_img,
diff --git a/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c
index 7619c357b150..640ccb553274 100644
--- a/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c
+++ b/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c
@@ -59,7 +59,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_imp_iic_wrap);
static struct platform_driver clk_mt8186_imp_iic_wrap_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8186-imp_iic_wrap",
.of_match_table = of_match_clk_mt8186_imp_iic_wrap,
diff --git a/drivers/clk/mediatek/clk-mt8186-infra_ao.c b/drivers/clk/mediatek/clk-mt8186-infra_ao.c
index a907a5def5b8..837304cd0ed7 100644
--- a/drivers/clk/mediatek/clk-mt8186-infra_ao.c
+++ b/drivers/clk/mediatek/clk-mt8186-infra_ao.c
@@ -231,7 +231,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_infra_ao);
static struct platform_driver clk_mt8186_infra_ao_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8186-infra-ao",
.of_match_table = of_match_clk_mt8186_infra_ao,
diff --git a/drivers/clk/mediatek/clk-mt8186-ipe.c b/drivers/clk/mediatek/clk-mt8186-ipe.c
index 50e340035aa7..60739e225cb6 100644
--- a/drivers/clk/mediatek/clk-mt8186-ipe.c
+++ b/drivers/clk/mediatek/clk-mt8186-ipe.c
@@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_ipe);
static struct platform_driver clk_mt8186_ipe_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8186-ipe",
.of_match_table = of_match_clk_mt8186_ipe,
diff --git a/drivers/clk/mediatek/clk-mt8186-mcu.c b/drivers/clk/mediatek/clk-mt8186-mcu.c
index d1640e4dc2ad..eb54ccb77b74 100644
--- a/drivers/clk/mediatek/clk-mt8186-mcu.c
+++ b/drivers/clk/mediatek/clk-mt8186-mcu.c
@@ -60,7 +60,7 @@ static struct platform_driver clk_mt8186_mcu_drv = {
.of_match_table = of_match_clk_mt8186_mcu,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt8186_mcu_drv);
diff --git a/drivers/clk/mediatek/clk-mt8186-mdp.c b/drivers/clk/mediatek/clk-mt8186-mdp.c
index e1d19007e375..9a335f2285ce 100644
--- a/drivers/clk/mediatek/clk-mt8186-mdp.c
+++ b/drivers/clk/mediatek/clk-mt8186-mdp.c
@@ -72,7 +72,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_mdp);
static struct platform_driver clk_mt8186_mdp_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8186-mdp",
.of_match_table = of_match_clk_mt8186_mdp,
diff --git a/drivers/clk/mediatek/clk-mt8186-mfg.c b/drivers/clk/mediatek/clk-mt8186-mfg.c
index aeb098b54585..7618dad9e0e0 100644
--- a/drivers/clk/mediatek/clk-mt8186-mfg.c
+++ b/drivers/clk/mediatek/clk-mt8186-mfg.c
@@ -41,7 +41,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_mfg);
static struct platform_driver clk_mt8186_mfg_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8186-mfg",
.of_match_table = of_match_clk_mt8186_mfg,
diff --git a/drivers/clk/mediatek/clk-mt8186-mm.c b/drivers/clk/mediatek/clk-mt8186-mm.c
index fc3bb6d1f714..44ed504a8069 100644
--- a/drivers/clk/mediatek/clk-mt8186-mm.c
+++ b/drivers/clk/mediatek/clk-mt8186-mm.c
@@ -71,7 +71,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8186_mm_id_table);
static struct platform_driver clk_mt8186_mm_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8186-mm",
},
diff --git a/drivers/clk/mediatek/clk-mt8186-topckgen.c b/drivers/clk/mediatek/clk-mt8186-topckgen.c
index 1a0340a20beb..8e385d6bfef2 100644
--- a/drivers/clk/mediatek/clk-mt8186-topckgen.c
+++ b/drivers/clk/mediatek/clk-mt8186-topckgen.c
@@ -504,10 +504,10 @@ static const struct mtk_mux top_mtk_muxes[] = {
*/
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI, "top_axi", axi_parents,
0x0040, 0x0044, 0x0048, 0, 2, 7, 0x0004, 0,
- CLK_IS_CRITICAL),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SCP, "top_scp", scp_parents,
0x0040, 0x0044, 0x0048, 8, 3, 15, 0x0004, 1,
- CLK_IS_CRITICAL),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG, "top_mfg",
mfg_parents, 0x0040, 0x0044, 0x0048, 16, 2, 23, 0x0004, 2),
MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG, "top_camtg",
@@ -531,12 +531,12 @@ static const struct mtk_mux top_mtk_muxes[] = {
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI, "top_spi",
spi_parents, 0x0060, 0x0064, 0x0068, 24, 3, 31, 0x0004, 11),
/* CLK_CFG_3 */
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK, "top_msdc5hclk",
- msdc5hclk_parents, 0x0070, 0x0074, 0x0078, 0, 2, 7, 0x0004, 12),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0, "top_msdc50_0",
- msdc50_0_parents, 0x0070, 0x0074, 0x0078, 8, 3, 15, 0x0004, 13),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1, "top_msdc30_1",
- msdc30_1_parents, 0x0070, 0x0074, 0x0078, 16, 3, 23, 0x0004, 14),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_HCLK, "top_msdc5hclk",
+ msdc5hclk_parents, 0x0070, 0x0074, 0x0078, 0, 2, 7, 0x0004, 12, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0, "top_msdc50_0",
+ msdc50_0_parents, 0x0070, 0x0074, 0x0078, 8, 3, 15, 0x0004, 13, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1, "top_msdc30_1",
+ msdc30_1_parents, 0x0070, 0x0074, 0x0078, 16, 3, 23, 0x0004, 14, 0),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO, "top_audio",
audio_parents, 0x0070, 0x0074, 0x0078, 24, 2, 31, 0x0004, 15),
/* CLK_CFG_4 */
@@ -559,7 +559,7 @@ static const struct mtk_mux top_mtk_muxes[] = {
disp_pwm_parents, 0x0090, 0x0094, 0x0098, 8, 3, 15, 0x0004, 21),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SSPM, "top_sspm", sspm_parents,
0x0090, 0x0094, 0x0098, 16, 3, 23, 0x0004, 22,
- CLK_IS_CRITICAL),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_DXCC, "top_dxcc",
dxcc_parents, 0x0090, 0x0094, 0x0098, 24, 2, 31, 0x0004, 23),
/*
@@ -570,10 +570,10 @@ static const struct mtk_mux top_mtk_muxes[] = {
usb_parents, 0x00a0, 0x00a4, 0x00a8, 0, 2, 7, 0x0004, 24),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SRCK, "top_srck", srck_parents,
0x00a0, 0x00a4, 0x00a8, 8, 2, 15, 0x0004, 25,
- CLK_IS_CRITICAL),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM, "top_spm", spm_parents,
0x00a0, 0x00a4, 0x00a8, 16, 2, 23, 0x0004, 26,
- CLK_IS_CRITICAL),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C, "top_i2c",
i2c_parents, 0x00a0, 0x00a4, 0x00a8, 24, 2, 31, 0x0004, 27),
/* CLK_CFG_7 */
@@ -627,7 +627,7 @@ static const struct mtk_mux top_mtk_muxes[] = {
*/
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DVFSRC, "top_dvfsrc", dvfsrc_parents,
0x0100, 0x0104, 0x0108, 0, 1, 7, 0x0008, 17,
- CLK_IS_CRITICAL),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_DSI_OCC, "top_dsi_occ",
dsi_occ_parents, 0x0100, 0x0104, 0x0108, 8, 2, 15, 0x0008, 18),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_MST, "top_spmi_mst",
@@ -725,7 +725,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_topck);
static struct platform_driver clk_mt8186_topck_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8186-topck",
.of_match_table = of_match_clk_mt8186_topck,
diff --git a/drivers/clk/mediatek/clk-mt8186-vdec.c b/drivers/clk/mediatek/clk-mt8186-vdec.c
index 9bf3b8632870..0b814e8e107f 100644
--- a/drivers/clk/mediatek/clk-mt8186-vdec.c
+++ b/drivers/clk/mediatek/clk-mt8186-vdec.c
@@ -80,7 +80,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_vdec);
static struct platform_driver clk_mt8186_vdec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8186-vdec",
.of_match_table = of_match_clk_mt8186_vdec,
diff --git a/drivers/clk/mediatek/clk-mt8186-venc.c b/drivers/clk/mediatek/clk-mt8186-venc.c
index 0c1bc94e84cf..9493e51af3e2 100644
--- a/drivers/clk/mediatek/clk-mt8186-venc.c
+++ b/drivers/clk/mediatek/clk-mt8186-venc.c
@@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_venc);
static struct platform_driver clk_mt8186_venc_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8186-venc",
.of_match_table = of_match_clk_mt8186_venc,
diff --git a/drivers/clk/mediatek/clk-mt8186-wpe.c b/drivers/clk/mediatek/clk-mt8186-wpe.c
index c4727b1cb64d..a0174eabef4a 100644
--- a/drivers/clk/mediatek/clk-mt8186-wpe.c
+++ b/drivers/clk/mediatek/clk-mt8186-wpe.c
@@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_wpe);
static struct platform_driver clk_mt8186_wpe_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8186-wpe",
.of_match_table = of_match_clk_mt8186_wpe,
diff --git a/drivers/clk/mediatek/clk-mt8188-adsp_audio26m.c b/drivers/clk/mediatek/clk-mt8188-adsp_audio26m.c
index 808f2ad3b7ee..1dc3d2bad42d 100644
--- a/drivers/clk/mediatek/clk-mt8188-adsp_audio26m.c
+++ b/drivers/clk/mediatek/clk-mt8188-adsp_audio26m.c
@@ -40,7 +40,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_adsp_audio26m);
static struct platform_driver clk_mt8188_adsp_audio26m_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8188-adsp_audio26m",
.of_match_table = of_match_clk_mt8188_adsp_audio26m,
diff --git a/drivers/clk/mediatek/clk-mt8188-apmixedsys.c b/drivers/clk/mediatek/clk-mt8188-apmixedsys.c
index 9d21da2d9aa7..3c1ace87796b 100644
--- a/drivers/clk/mediatek/clk-mt8188-apmixedsys.c
+++ b/drivers/clk/mediatek/clk-mt8188-apmixedsys.c
@@ -132,7 +132,7 @@ free_apmixed_data:
return r;
}
-static int clk_mt8188_apmixed_remove(struct platform_device *pdev)
+static void clk_mt8188_apmixed_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -141,13 +141,11 @@ static int clk_mt8188_apmixed_remove(struct platform_device *pdev)
mtk_clk_unregister_gates(apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data);
mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static struct platform_driver clk_mt8188_apmixed_drv = {
.probe = clk_mt8188_apmixed_probe,
- .remove = clk_mt8188_apmixed_remove,
+ .remove_new = clk_mt8188_apmixed_remove,
.driver = {
.name = "clk-mt8188-apmixed",
.of_match_table = of_match_clk_mt8188_apmixed,
diff --git a/drivers/clk/mediatek/clk-mt8188-cam.c b/drivers/clk/mediatek/clk-mt8188-cam.c
index c5a3856bd223..f78f564aa27e 100644
--- a/drivers/clk/mediatek/clk-mt8188-cam.c
+++ b/drivers/clk/mediatek/clk-mt8188-cam.c
@@ -109,7 +109,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_cam);
static struct platform_driver clk_mt8188_cam_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8188-cam",
.of_match_table = of_match_clk_mt8188_cam,
diff --git a/drivers/clk/mediatek/clk-mt8188-ccu.c b/drivers/clk/mediatek/clk-mt8188-ccu.c
index ebc0d3aeee11..428dcc4818c2 100644
--- a/drivers/clk/mediatek/clk-mt8188-ccu.c
+++ b/drivers/clk/mediatek/clk-mt8188-ccu.c
@@ -39,7 +39,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_ccu);
static struct platform_driver clk_mt8188_ccu_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8188-ccu",
.of_match_table = of_match_clk_mt8188_ccu,
diff --git a/drivers/clk/mediatek/clk-mt8188-img.c b/drivers/clk/mediatek/clk-mt8188-img.c
index b4622875e14c..76c64a8992a4 100644
--- a/drivers/clk/mediatek/clk-mt8188-img.c
+++ b/drivers/clk/mediatek/clk-mt8188-img.c
@@ -101,7 +101,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_imgsys_main);
static struct platform_driver clk_mt8188_imgsys_main_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8188-imgsys_main",
.of_match_table = of_match_clk_mt8188_imgsys_main,
diff --git a/drivers/clk/mediatek/clk-mt8188-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8188-imp_iic_wrap.c
index da41a3c59919..66946784cdba 100644
--- a/drivers/clk/mediatek/clk-mt8188-imp_iic_wrap.c
+++ b/drivers/clk/mediatek/clk-mt8188-imp_iic_wrap.c
@@ -71,7 +71,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_imp_iic_wrap);
static struct platform_driver clk_mt8188_imp_iic_wrap_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8188-imp_iic_wrap",
.of_match_table = of_match_clk_mt8188_imp_iic_wrap,
diff --git a/drivers/clk/mediatek/clk-mt8188-infra_ao.c b/drivers/clk/mediatek/clk-mt8188-infra_ao.c
index 91c35db40b4e..f590178737cb 100644
--- a/drivers/clk/mediatek/clk-mt8188-infra_ao.c
+++ b/drivers/clk/mediatek/clk-mt8188-infra_ao.c
@@ -5,6 +5,7 @@
*/
#include <dt-bindings/clock/mediatek,mt8188-clk.h>
+#include <dt-bindings/reset/mt8188-resets.h>
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
@@ -176,9 +177,32 @@ static const struct mtk_gate infra_ao_clks[] = {
"infra_ao_aes_msdcfde_0p", "top_aes_msdcfde", 18),
};
+static u16 infra_ao_rst_ofs[] = {
+ INFRA_RST0_SET_OFFSET,
+ INFRA_RST1_SET_OFFSET,
+ INFRA_RST2_SET_OFFSET,
+ INFRA_RST3_SET_OFFSET,
+ INFRA_RST4_SET_OFFSET,
+};
+
+static u16 infra_ao_idx_map[] = {
+ [MT8188_INFRA_RST1_THERMAL_MCU_RST] = 1 * RST_NR_PER_BANK + 2,
+ [MT8188_INFRA_RST1_THERMAL_CTRL_RST] = 1 * RST_NR_PER_BANK + 4,
+ [MT8188_INFRA_RST3_PTP_CTRL_RST] = 3 * RST_NR_PER_BANK + 5,
+};
+
+static const struct mtk_clk_rst_desc infra_ao_rst_desc = {
+ .version = MTK_RST_SET_CLR,
+ .rst_bank_ofs = infra_ao_rst_ofs,
+ .rst_bank_nr = ARRAY_SIZE(infra_ao_rst_ofs),
+ .rst_idx_map = infra_ao_idx_map,
+ .rst_idx_map_nr = ARRAY_SIZE(infra_ao_idx_map),
+};
+
static const struct mtk_clk_desc infra_ao_desc = {
.clks = infra_ao_clks,
.num_clks = ARRAY_SIZE(infra_ao_clks),
+ .rst_desc = &infra_ao_rst_desc,
};
static const struct of_device_id of_match_clk_mt8188_infra_ao[] = {
@@ -189,7 +213,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_infra_ao);
static struct platform_driver clk_mt8188_infra_ao_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8188-infra_ao",
.of_match_table = of_match_clk_mt8188_infra_ao,
diff --git a/drivers/clk/mediatek/clk-mt8188-ipe.c b/drivers/clk/mediatek/clk-mt8188-ipe.c
index c07afbd1429e..54fe6b689b47 100644
--- a/drivers/clk/mediatek/clk-mt8188-ipe.c
+++ b/drivers/clk/mediatek/clk-mt8188-ipe.c
@@ -41,7 +41,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_ipe);
static struct platform_driver clk_mt8188_ipe_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8188-ipe",
.of_match_table = of_match_clk_mt8188_ipe,
diff --git a/drivers/clk/mediatek/clk-mt8188-mfg.c b/drivers/clk/mediatek/clk-mt8188-mfg.c
index e5a6eaf84672..1c8ef4c6820f 100644
--- a/drivers/clk/mediatek/clk-mt8188-mfg.c
+++ b/drivers/clk/mediatek/clk-mt8188-mfg.c
@@ -38,7 +38,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_mfgcfg);
static struct platform_driver clk_mt8188_mfgcfg_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8188-mfgcfg",
.of_match_table = of_match_clk_mt8188_mfgcfg,
diff --git a/drivers/clk/mediatek/clk-mt8188-peri_ao.c b/drivers/clk/mediatek/clk-mt8188-peri_ao.c
index b00e1ae8bd26..a8214e42b8e5 100644
--- a/drivers/clk/mediatek/clk-mt8188-peri_ao.c
+++ b/drivers/clk/mediatek/clk-mt8188-peri_ao.c
@@ -49,7 +49,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_peri_ao);
static struct platform_driver clk_mt8188_peri_ao_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8188-peri_ao",
.of_match_table = of_match_clk_mt8188_peri_ao,
diff --git a/drivers/clk/mediatek/clk-mt8188-topckgen.c b/drivers/clk/mediatek/clk-mt8188-topckgen.c
index c56ec42cb15f..d2eba2d6af8d 100644
--- a/drivers/clk/mediatek/clk-mt8188-topckgen.c
+++ b/drivers/clk/mediatek/clk-mt8188-topckgen.c
@@ -954,13 +954,17 @@ static const struct mtk_mux top_mtk_muxes[] = {
* spm_sel and scp_sel are main clocks in always-on co-processor.
*/
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI, "top_axi", axi_parents,
- 0x020, 0x024, 0x028, 0, 4, 7, 0x04, 0, CLK_IS_CRITICAL),
+ 0x020, 0x024, 0x028, 0, 4, 7, 0x04, 0,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM, "top_spm", spm_parents,
- 0x020, 0x024, 0x028, 8, 4, 15, 0x04, 1, CLK_IS_CRITICAL),
+ 0x020, 0x024, 0x028, 8, 4, 15, 0x04, 1,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SCP, "top_scp", scp_parents,
- 0x020, 0x024, 0x028, 16, 4, 23, 0x04, 2, CLK_IS_CRITICAL),
+ 0x020, 0x024, 0x028, 16, 4, 23, 0x04, 2,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_BUS_AXIMEM, "top_bus_aximem", bus_aximem_parents,
- 0x020, 0x024, 0x028, 24, 4, 31, 0x04, 3, CLK_IS_CRITICAL),
+ 0x020, 0x024, 0x028, 24, 4, 31, 0x04, 3,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
/* CLK_CFG_1 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_VPP, "top_vpp",
vpp_parents, 0x02C, 0x030, 0x034, 0, 4, 7, 0x04, 4),
@@ -1011,15 +1015,15 @@ static const struct mtk_mux top_mtk_muxes[] = {
uart_parents, 0x068, 0x06C, 0x070, 0, 4, 7, 0x04, 24),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI, "top_spi",
spi_parents, 0x068, 0x06C, 0x070, 8, 4, 15, 0x04, 25),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK, "top_msdc5hclk",
- msdc5hclk_parents, 0x068, 0x06C, 0x070, 16, 4, 23, 0x04, 26),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0, "top_msdc50_0",
- msdc50_0_parents, 0x068, 0x06C, 0x070, 24, 4, 31, 0x04, 27),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_HCLK, "top_msdc5hclk",
+ msdc5hclk_parents, 0x068, 0x06C, 0x070, 16, 4, 23, 0x04, 26, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0, "top_msdc50_0",
+ msdc50_0_parents, 0x068, 0x06C, 0x070, 24, 4, 31, 0x04, 27, 0),
/* CLK_CFG_7 */
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1, "top_msdc30_1",
- msdc30_1_parents, 0x074, 0x078, 0x07C, 0, 4, 7, 0x04, 28),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2, "top_msdc30_2",
- msdc30_2_parents, 0x074, 0x078, 0x07C, 8, 4, 15, 0x04, 29),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1, "top_msdc30_1",
+ msdc30_1_parents, 0x074, 0x078, 0x07C, 0, 4, 7, 0x04, 28, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_2, "top_msdc30_2",
+ msdc30_2_parents, 0x074, 0x078, 0x07C, 8, 4, 15, 0x04, 29, 0),
MUX_GATE_CLR_SET_UPD(CLK_TOP_INTDIR, "top_intdir",
intdir_parents, 0x074, 0x078, 0x07C, 16, 4, 23, 0x04, 30),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS, "top_aud_intbus",
@@ -1078,7 +1082,8 @@ static const struct mtk_mux top_mtk_muxes[] = {
MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM, "top_pwm",
pwm_parents, 0x0BC, 0x0C0, 0x0C4, 8, 4, 15, 0x08, 21),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MCUPM, "top_mcupm", mcupm_parents,
- 0x0BC, 0x0C0, 0x0C4, 16, 4, 23, 0x08, 22, CLK_IS_CRITICAL),
+ 0x0BC, 0x0C0, 0x0C4, 16, 4, 23, 0x08, 22,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_P_MST, "top_spmi_p_mst",
spmi_p_mst_parents, 0x0BC, 0x0C0, 0x0C4, 24, 4, 31, 0x08, 23),
/*
@@ -1088,7 +1093,8 @@ static const struct mtk_mux top_mtk_muxes[] = {
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_M_MST, "top_spmi_m_mst",
spmi_m_mst_parents, 0x0C8, 0x0CC, 0x0D0, 0, 4, 7, 0x08, 24),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DVFSRC, "top_dvfsrc", dvfsrc_parents,
- 0x0C8, 0x0CC, 0x0D0, 8, 4, 15, 0x08, 25, CLK_IS_CRITICAL),
+ 0x0C8, 0x0CC, 0x0D0, 8, 4, 15, 0x08, 25,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_TL, "top_tl",
tl_parents, 0x0C8, 0x0CC, 0x0D0, 16, 4, 23, 0x08, 26),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_MSDCFDE, "top_aes_msdcfde",
@@ -1164,9 +1170,11 @@ static const struct mtk_mux top_mtk_muxes[] = {
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINOR, "top_spinor",
spinor_parents, 0x0128, 0x012C, 0x0130, 0, 4, 7, 0x0C, 24),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_ULPOSC, "top_ulposc", ulposc_parents,
- 0x0128, 0x012C, 0x0130, 8, 4, 15, 0x0C, 25, CLK_IS_CRITICAL),
+ 0x0128, 0x012C, 0x0130, 8, 4, 15, 0x0C, 25,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SRCK, "top_srck", srck_parents,
- 0x0128, 0x012C, 0x0130, 16, 4, 23, 0x0C, 26, CLK_IS_CRITICAL),
+ 0x0128, 0x012C, 0x0130, 16, 4, 23, 0x0C, 26,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
};
static const struct mtk_composite top_adj_divs[] = {
@@ -1322,7 +1330,7 @@ free_top_data:
return r;
}
-static int clk_mt8188_topck_remove(struct platform_device *pdev)
+static void clk_mt8188_topck_remove(struct platform_device *pdev)
{
struct clk_hw_onecell_data *top_clk_data = platform_get_drvdata(pdev);
struct device_node *node = pdev->dev.of_node;
@@ -1334,13 +1342,11 @@ static int clk_mt8188_topck_remove(struct platform_device *pdev)
mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data);
mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), top_clk_data);
mtk_free_clk_data(top_clk_data);
-
- return 0;
}
static struct platform_driver clk_mt8188_topck_drv = {
.probe = clk_mt8188_topck_probe,
- .remove = clk_mt8188_topck_remove,
+ .remove_new = clk_mt8188_topck_remove,
.driver = {
.name = "clk-mt8188-topck",
.of_match_table = of_match_clk_mt8188_topck,
diff --git a/drivers/clk/mediatek/clk-mt8188-vdec.c b/drivers/clk/mediatek/clk-mt8188-vdec.c
index 8c3d76531753..db5855d133ac 100644
--- a/drivers/clk/mediatek/clk-mt8188-vdec.c
+++ b/drivers/clk/mediatek/clk-mt8188-vdec.c
@@ -81,7 +81,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_vdec);
static struct platform_driver clk_mt8188_vdec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8188-vdec",
.of_match_table = of_match_clk_mt8188_vdec,
diff --git a/drivers/clk/mediatek/clk-mt8188-vdo0.c b/drivers/clk/mediatek/clk-mt8188-vdo0.c
index d2be44c2f3f5..d252e198678c 100644
--- a/drivers/clk/mediatek/clk-mt8188-vdo0.c
+++ b/drivers/clk/mediatek/clk-mt8188-vdo0.c
@@ -97,7 +97,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8188_vdo0_id_table);
static struct platform_driver clk_mt8188_vdo0_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8188-vdo0",
},
diff --git a/drivers/clk/mediatek/clk-mt8188-vdo1.c b/drivers/clk/mediatek/clk-mt8188-vdo1.c
index 2ef8cae2e16e..7b72d54086db 100644
--- a/drivers/clk/mediatek/clk-mt8188-vdo1.c
+++ b/drivers/clk/mediatek/clk-mt8188-vdo1.c
@@ -144,7 +144,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8188_vdo1_id_table);
static struct platform_driver clk_mt8188_vdo1_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8188-vdo1",
},
diff --git a/drivers/clk/mediatek/clk-mt8188-venc.c b/drivers/clk/mediatek/clk-mt8188-venc.c
index 245367f33fa5..5b1713908ed2 100644
--- a/drivers/clk/mediatek/clk-mt8188-venc.c
+++ b/drivers/clk/mediatek/clk-mt8188-venc.c
@@ -45,7 +45,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_venc1);
static struct platform_driver clk_mt8188_venc1_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8188-venc1",
.of_match_table = of_match_clk_mt8188_venc1,
diff --git a/drivers/clk/mediatek/clk-mt8188-vpp0.c b/drivers/clk/mediatek/clk-mt8188-vpp0.c
index 07bdedf6a21a..e7b02b26fefb 100644
--- a/drivers/clk/mediatek/clk-mt8188-vpp0.c
+++ b/drivers/clk/mediatek/clk-mt8188-vpp0.c
@@ -104,7 +104,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8188_vpp0_id_table);
static struct platform_driver clk_mt8188_vpp0_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8188-vpp0",
},
diff --git a/drivers/clk/mediatek/clk-mt8188-vpp1.c b/drivers/clk/mediatek/clk-mt8188-vpp1.c
index d4e66b240573..e8f0f7eca097 100644
--- a/drivers/clk/mediatek/clk-mt8188-vpp1.c
+++ b/drivers/clk/mediatek/clk-mt8188-vpp1.c
@@ -99,7 +99,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8188_vpp1_id_table);
static struct platform_driver clk_mt8188_vpp1_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8188-vpp1",
},
diff --git a/drivers/clk/mediatek/clk-mt8188-wpe.c b/drivers/clk/mediatek/clk-mt8188-wpe.c
index 393ac38a2172..f394ec049872 100644
--- a/drivers/clk/mediatek/clk-mt8188-wpe.c
+++ b/drivers/clk/mediatek/clk-mt8188-wpe.c
@@ -94,7 +94,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_wpe);
static struct platform_driver clk_mt8188_wpe_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8188-wpe",
.of_match_table = of_match_clk_mt8188_wpe,
diff --git a/drivers/clk/mediatek/clk-mt8192-apmixedsys.c b/drivers/clk/mediatek/clk-mt8192-apmixedsys.c
index eafd34297b9a..3590932acc63 100644
--- a/drivers/clk/mediatek/clk-mt8192-apmixedsys.c
+++ b/drivers/clk/mediatek/clk-mt8192-apmixedsys.c
@@ -188,7 +188,7 @@ free_clk_data:
return r;
}
-static int clk_mt8192_apmixed_remove(struct platform_device *pdev)
+static void clk_mt8192_apmixed_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -198,8 +198,6 @@ static int clk_mt8192_apmixed_remove(struct platform_device *pdev)
mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs,
ARRAY_SIZE(pllfhs), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static struct platform_driver clk_mt8192_apmixed_drv = {
@@ -208,7 +206,7 @@ static struct platform_driver clk_mt8192_apmixed_drv = {
.of_match_table = of_match_clk_mt8192_apmixed,
},
.probe = clk_mt8192_apmixed_probe,
- .remove = clk_mt8192_apmixed_remove,
+ .remove_new = clk_mt8192_apmixed_remove,
};
module_platform_driver(clk_mt8192_apmixed_drv);
MODULE_DESCRIPTION("MediaTek MT8192 apmixed clocks driver");
diff --git a/drivers/clk/mediatek/clk-mt8192-aud.c b/drivers/clk/mediatek/clk-mt8192-aud.c
index ee251492d4f1..5bce67bf701d 100644
--- a/drivers/clk/mediatek/clk-mt8192-aud.c
+++ b/drivers/clk/mediatek/clk-mt8192-aud.c
@@ -97,10 +97,10 @@ static int clk_mt8192_aud_probe(struct platform_device *pdev)
return r;
}
-static int clk_mt8192_aud_remove(struct platform_device *pdev)
+static void clk_mt8192_aud_remove(struct platform_device *pdev)
{
of_platform_depopulate(&pdev->dev);
- return mtk_clk_simple_remove(pdev);
+ mtk_clk_simple_remove(pdev);
}
static const struct of_device_id of_match_clk_mt8192_aud[] = {
@@ -111,7 +111,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_aud);
static struct platform_driver clk_mt8192_aud_drv = {
.probe = clk_mt8192_aud_probe,
- .remove = clk_mt8192_aud_remove,
+ .remove_new = clk_mt8192_aud_remove,
.driver = {
.name = "clk-mt8192-aud",
.of_match_table = of_match_clk_mt8192_aud,
diff --git a/drivers/clk/mediatek/clk-mt8192-cam.c b/drivers/clk/mediatek/clk-mt8192-cam.c
index 7befd6ee8c79..7b9327eba924 100644
--- a/drivers/clk/mediatek/clk-mt8192-cam.c
+++ b/drivers/clk/mediatek/clk-mt8192-cam.c
@@ -99,7 +99,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_cam);
static struct platform_driver clk_mt8192_cam_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8192-cam",
.of_match_table = of_match_clk_mt8192_cam,
diff --git a/drivers/clk/mediatek/clk-mt8192-img.c b/drivers/clk/mediatek/clk-mt8192-img.c
index a7505150a9d0..0208030c31a0 100644
--- a/drivers/clk/mediatek/clk-mt8192-img.c
+++ b/drivers/clk/mediatek/clk-mt8192-img.c
@@ -62,7 +62,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_img);
static struct platform_driver clk_mt8192_img_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8192-img",
.of_match_table = of_match_clk_mt8192_img,
diff --git a/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c
index cd5d00a7c54b..275581f8c710 100644
--- a/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c
+++ b/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c
@@ -111,7 +111,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_imp_iic_wrap);
static struct platform_driver clk_mt8192_imp_iic_wrap_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8192-imp_iic_wrap",
.of_match_table = of_match_clk_mt8192_imp_iic_wrap,
diff --git a/drivers/clk/mediatek/clk-mt8192-ipe.c b/drivers/clk/mediatek/clk-mt8192-ipe.c
index dee671ae38e6..f3656c3b9573 100644
--- a/drivers/clk/mediatek/clk-mt8192-ipe.c
+++ b/drivers/clk/mediatek/clk-mt8192-ipe.c
@@ -49,7 +49,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_ipe);
static struct platform_driver clk_mt8192_ipe_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8192-ipe",
.of_match_table = of_match_clk_mt8192_ipe,
diff --git a/drivers/clk/mediatek/clk-mt8192-mdp.c b/drivers/clk/mediatek/clk-mt8192-mdp.c
index f7b27264e378..5385ac95533a 100644
--- a/drivers/clk/mediatek/clk-mt8192-mdp.c
+++ b/drivers/clk/mediatek/clk-mt8192-mdp.c
@@ -74,7 +74,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_mdp);
static struct platform_driver clk_mt8192_mdp_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8192-mdp",
.of_match_table = of_match_clk_mt8192_mdp,
diff --git a/drivers/clk/mediatek/clk-mt8192-mfg.c b/drivers/clk/mediatek/clk-mt8192-mfg.c
index 85f76a2bbac4..0ac7045cf5d1 100644
--- a/drivers/clk/mediatek/clk-mt8192-mfg.c
+++ b/drivers/clk/mediatek/clk-mt8192-mfg.c
@@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_mfg);
static struct platform_driver clk_mt8192_mfg_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8192-mfg",
.of_match_table = of_match_clk_mt8192_mfg,
diff --git a/drivers/clk/mediatek/clk-mt8192-mm.c b/drivers/clk/mediatek/clk-mt8192-mm.c
index 47335d517714..b294184c5183 100644
--- a/drivers/clk/mediatek/clk-mt8192-mm.c
+++ b/drivers/clk/mediatek/clk-mt8192-mm.c
@@ -93,7 +93,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8192_mm_id_table);
static struct platform_driver clk_mt8192_mm_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8192-mm",
},
diff --git a/drivers/clk/mediatek/clk-mt8192-msdc.c b/drivers/clk/mediatek/clk-mt8192-msdc.c
index 60d65f96d39a..9da647c5b8b3 100644
--- a/drivers/clk/mediatek/clk-mt8192-msdc.c
+++ b/drivers/clk/mediatek/clk-mt8192-msdc.c
@@ -56,7 +56,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_msdc);
static struct platform_driver clk_mt8192_msdc_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8192-msdc",
.of_match_table = of_match_clk_mt8192_msdc,
diff --git a/drivers/clk/mediatek/clk-mt8192-scp_adsp.c b/drivers/clk/mediatek/clk-mt8192-scp_adsp.c
index 6aad57797c39..44091147c813 100644
--- a/drivers/clk/mediatek/clk-mt8192-scp_adsp.c
+++ b/drivers/clk/mediatek/clk-mt8192-scp_adsp.c
@@ -42,7 +42,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_scp_adsp);
static struct platform_driver clk_mt8192_scp_adsp_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8192-scp_adsp",
.of_match_table = of_match_clk_mt8192_scp_adsp,
diff --git a/drivers/clk/mediatek/clk-mt8192-vdec.c b/drivers/clk/mediatek/clk-mt8192-vdec.c
index 473afd58495c..d82dee8317b2 100644
--- a/drivers/clk/mediatek/clk-mt8192-vdec.c
+++ b/drivers/clk/mediatek/clk-mt8192-vdec.c
@@ -86,7 +86,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_vdec);
static struct platform_driver clk_mt8192_vdec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8192-vdec",
.of_match_table = of_match_clk_mt8192_vdec,
diff --git a/drivers/clk/mediatek/clk-mt8192-venc.c b/drivers/clk/mediatek/clk-mt8192-venc.c
index 57b1b16e2310..b0ef242991e5 100644
--- a/drivers/clk/mediatek/clk-mt8192-venc.c
+++ b/drivers/clk/mediatek/clk-mt8192-venc.c
@@ -45,7 +45,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_venc);
static struct platform_driver clk_mt8192_venc_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8192-venc",
.of_match_table = of_match_clk_mt8192_venc,
diff --git a/drivers/clk/mediatek/clk-mt8192.c b/drivers/clk/mediatek/clk-mt8192.c
index aa11291463f7..462ec4465b50 100644
--- a/drivers/clk/mediatek/clk-mt8192.c
+++ b/drivers/clk/mediatek/clk-mt8192.c
@@ -549,15 +549,15 @@ static const struct mtk_mux top_mtk_muxes[] = {
/* CLK_CFG_0 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_SEL, "axi_sel",
axi_parents, 0x010, 0x014, 0x018, 0, 3, 7, 0x004, 0,
- CLK_IS_CRITICAL),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM_SEL, "spm_sel",
spm_parents, 0x010, 0x014, 0x018, 8, 2, 15, 0x004, 1,
- CLK_IS_CRITICAL),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SCP_SEL, "scp_sel",
scp_parents, 0x010, 0x014, 0x018, 16, 3, 23, 0x004, 2),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_BUS_AXIMEM_SEL, "bus_aximem_sel",
bus_aximem_parents, 0x010, 0x014, 0x018, 24, 3, 31, 0x004, 3,
- CLK_IS_CRITICAL),
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
/* CLK_CFG_1 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_SEL, "disp_sel",
disp_parents, 0x020, 0x024, 0x028, 0, 4, 7, 0x004, 4),
@@ -601,15 +601,16 @@ static const struct mtk_mux top_mtk_muxes[] = {
uart_parents, 0x070, 0x074, 0x078, 8, 1, 15, 0x004, 25),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel",
spi_parents, 0x070, 0x074, 0x078, 16, 2, 23, 0x004, 26),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel",
- msdc50_0_h_parents, 0x070, 0x074, 0x078, 24, 2, 31, 0x004, 27),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel",
+ msdc50_0_h_parents, 0x070, 0x074, 0x078, 24, 2,
+ 31, 0x004, 27, 0),
/* CLK_CFG_7 */
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel",
- msdc50_0_parents, 0x080, 0x084, 0x088, 0, 3, 7, 0x004, 28),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel",
- msdc30_parents, 0x080, 0x084, 0x088, 8, 3, 15, 0x004, 29),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel",
- msdc30_parents, 0x080, 0x084, 0x088, 16, 3, 23, 0x004, 30),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel",
+ msdc50_0_parents, 0x080, 0x084, 0x088, 0, 3, 7, 0x004, 28, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel",
+ msdc30_parents, 0x080, 0x084, 0x088, 8, 3, 15, 0x004, 29, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel",
+ msdc30_parents, 0x080, 0x084, 0x088, 16, 3, 23, 0x004, 30, 0),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel",
audio_parents, 0x080, 0x084, 0x088, 24, 2, 31, 0x008, 0),
/* CLK_CFG_8 */
@@ -1027,7 +1028,7 @@ static struct platform_driver clk_mt8192_drv = {
.of_match_table = of_match_clk_mt8192,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt8192_drv);
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mediatek/clk-mt8195-apmixedsys.c b/drivers/clk/mediatek/clk-mt8195-apmixedsys.c
index 8b9b5d820286..502a9dc1fdb8 100644
--- a/drivers/clk/mediatek/clk-mt8195-apmixedsys.c
+++ b/drivers/clk/mediatek/clk-mt8195-apmixedsys.c
@@ -209,7 +209,7 @@ free_apmixed_data:
return r;
}
-static int clk_mt8195_apmixed_remove(struct platform_device *pdev)
+static void clk_mt8195_apmixed_remove(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -219,13 +219,11 @@ static int clk_mt8195_apmixed_remove(struct platform_device *pdev)
mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs,
ARRAY_SIZE(pllfhs), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static struct platform_driver clk_mt8195_apmixed_drv = {
.probe = clk_mt8195_apmixed_probe,
- .remove = clk_mt8195_apmixed_remove,
+ .remove_new = clk_mt8195_apmixed_remove,
.driver = {
.name = "clk-mt8195-apmixed",
.of_match_table = of_match_clk_mt8195_apmixed,
diff --git a/drivers/clk/mediatek/clk-mt8195-apusys_pll.c b/drivers/clk/mediatek/clk-mt8195-apusys_pll.c
index de04c087c8c3..79762bc85cd7 100644
--- a/drivers/clk/mediatek/clk-mt8195-apusys_pll.c
+++ b/drivers/clk/mediatek/clk-mt8195-apusys_pll.c
@@ -85,7 +85,7 @@ free_apusys_pll_data:
return r;
}
-static int clk_mt8195_apusys_pll_remove(struct platform_device *pdev)
+static void clk_mt8195_apusys_pll_remove(struct platform_device *pdev)
{
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
struct device_node *node = pdev->dev.of_node;
@@ -93,8 +93,6 @@ static int clk_mt8195_apusys_pll_remove(struct platform_device *pdev)
of_clk_del_provider(node);
mtk_clk_unregister_plls(apusys_plls, ARRAY_SIZE(apusys_plls), clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
static const struct of_device_id of_match_clk_mt8195_apusys_pll[] = {
@@ -105,7 +103,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_apusys_pll);
static struct platform_driver clk_mt8195_apusys_pll_drv = {
.probe = clk_mt8195_apusys_pll_probe,
- .remove = clk_mt8195_apusys_pll_remove,
+ .remove_new = clk_mt8195_apusys_pll_remove,
.driver = {
.name = "clk-mt8195-apusys_pll",
.of_match_table = of_match_clk_mt8195_apusys_pll,
diff --git a/drivers/clk/mediatek/clk-mt8195-cam.c b/drivers/clk/mediatek/clk-mt8195-cam.c
index 77e608be579a..24cd6a2092b6 100644
--- a/drivers/clk/mediatek/clk-mt8195-cam.c
+++ b/drivers/clk/mediatek/clk-mt8195-cam.c
@@ -135,7 +135,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_cam);
static struct platform_driver clk_mt8195_cam_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8195-cam",
.of_match_table = of_match_clk_mt8195_cam,
diff --git a/drivers/clk/mediatek/clk-mt8195-ccu.c b/drivers/clk/mediatek/clk-mt8195-ccu.c
index bdc2e6f3e9ce..24dab128507a 100644
--- a/drivers/clk/mediatek/clk-mt8195-ccu.c
+++ b/drivers/clk/mediatek/clk-mt8195-ccu.c
@@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_ccu);
static struct platform_driver clk_mt8195_ccu_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8195-ccu",
.of_match_table = of_match_clk_mt8195_ccu,
diff --git a/drivers/clk/mediatek/clk-mt8195-img.c b/drivers/clk/mediatek/clk-mt8195-img.c
index d853e0e63d87..c7dc3e9d133d 100644
--- a/drivers/clk/mediatek/clk-mt8195-img.c
+++ b/drivers/clk/mediatek/clk-mt8195-img.c
@@ -89,7 +89,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_img);
static struct platform_driver clk_mt8195_img_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8195-img",
.of_match_table = of_match_clk_mt8195_img,
diff --git a/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c
index 1d808876f5c5..94912d45509e 100644
--- a/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c
+++ b/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c
@@ -59,7 +59,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_imp_iic_wrap);
static struct platform_driver clk_mt8195_imp_iic_wrap_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8195-imp_iic_wrap",
.of_match_table = of_match_clk_mt8195_imp_iic_wrap,
diff --git a/drivers/clk/mediatek/clk-mt8195-infra_ao.c b/drivers/clk/mediatek/clk-mt8195-infra_ao.c
index f3ee4390707d..dfba6eb61ccf 100644
--- a/drivers/clk/mediatek/clk-mt8195-infra_ao.c
+++ b/drivers/clk/mediatek/clk-mt8195-infra_ao.c
@@ -233,7 +233,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_infra_ao);
static struct platform_driver clk_mt8195_infra_ao_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8195-infra_ao",
.of_match_table = of_match_clk_mt8195_infra_ao,
diff --git a/drivers/clk/mediatek/clk-mt8195-ipe.c b/drivers/clk/mediatek/clk-mt8195-ipe.c
index 4c47f6521275..21e76e5ad376 100644
--- a/drivers/clk/mediatek/clk-mt8195-ipe.c
+++ b/drivers/clk/mediatek/clk-mt8195-ipe.c
@@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_ipe);
static struct platform_driver clk_mt8195_ipe_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8195-ipe",
.of_match_table = of_match_clk_mt8195_ipe,
diff --git a/drivers/clk/mediatek/clk-mt8195-mfg.c b/drivers/clk/mediatek/clk-mt8195-mfg.c
index 038acf0b1167..4951574abf2a 100644
--- a/drivers/clk/mediatek/clk-mt8195-mfg.c
+++ b/drivers/clk/mediatek/clk-mt8195-mfg.c
@@ -42,7 +42,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_mfg);
static struct platform_driver clk_mt8195_mfg_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8195-mfg",
.of_match_table = of_match_clk_mt8195_mfg,
diff --git a/drivers/clk/mediatek/clk-mt8195-peri_ao.c b/drivers/clk/mediatek/clk-mt8195-peri_ao.c
index 0de162593c01..39069aaf6bcd 100644
--- a/drivers/clk/mediatek/clk-mt8195-peri_ao.c
+++ b/drivers/clk/mediatek/clk-mt8195-peri_ao.c
@@ -55,7 +55,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_peri_ao);
static struct platform_driver clk_mt8195_peri_ao_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8195-peri_ao",
.of_match_table = of_match_clk_mt8195_peri_ao,
diff --git a/drivers/clk/mediatek/clk-mt8195-scp_adsp.c b/drivers/clk/mediatek/clk-mt8195-scp_adsp.c
index d0d3e3b09780..2b94d75be295 100644
--- a/drivers/clk/mediatek/clk-mt8195-scp_adsp.c
+++ b/drivers/clk/mediatek/clk-mt8195-scp_adsp.c
@@ -40,7 +40,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_scp_adsp);
static struct platform_driver clk_mt8195_scp_adsp_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8195-scp_adsp",
.of_match_table = of_match_clk_mt8195_scp_adsp,
diff --git a/drivers/clk/mediatek/clk-mt8195-topckgen.c b/drivers/clk/mediatek/clk-mt8195-topckgen.c
index 3c2174c3e742..81daa24cadde 100644
--- a/drivers/clk/mediatek/clk-mt8195-topckgen.c
+++ b/drivers/clk/mediatek/clk-mt8195-topckgen.c
@@ -862,13 +862,17 @@ static const struct mtk_mux top_mtk_muxes[] = {
* top_spm and top_scp are main clocks in always-on co-processor.
*/
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI, "top_axi",
- axi_parents, 0x020, 0x024, 0x028, 0, 3, 7, 0x04, 0, CLK_IS_CRITICAL),
+ axi_parents, 0x020, 0x024, 0x028, 0, 3, 7, 0x04, 0,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM, "top_spm",
- spm_parents, 0x020, 0x024, 0x028, 8, 2, 15, 0x04, 1, CLK_IS_CRITICAL),
+ spm_parents, 0x020, 0x024, 0x028, 8, 2, 15, 0x04, 1,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SCP, "top_scp",
- scp_parents, 0x020, 0x024, 0x028, 16, 3, 23, 0x04, 2, CLK_IS_CRITICAL),
+ scp_parents, 0x020, 0x024, 0x028, 16, 3, 23, 0x04, 2,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_BUS_AXIMEM, "top_bus_aximem",
- bus_aximem_parents, 0x020, 0x024, 0x028, 24, 3, 31, 0x04, 3, CLK_IS_CRITICAL),
+ bus_aximem_parents, 0x020, 0x024, 0x028, 24, 3, 31, 0x04, 3,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
/* CLK_CFG_1 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_VPP, "top_vpp",
vpp_parents, 0x02C, 0x030, 0x034, 0, 4, 7, 0x04, 4),
@@ -926,15 +930,15 @@ static const struct mtk_mux top_mtk_muxes[] = {
/* CLK_CFG_7 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIS, "top_spis",
spis_parents, 0x074, 0x078, 0x07C, 0, 3, 7, 0x04, 28),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK, "top_msdc50_0_hclk",
- msdc50_0_h_parents, 0x074, 0x078, 0x07C, 8, 2, 15, 0x04, 29),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0, "top_msdc50_0",
- msdc50_0_parents, 0x074, 0x078, 0x07C, 16, 3, 23, 0x04, 30),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1, "top_msdc30_1",
- msdc30_parents, 0x074, 0x078, 0x07C, 24, 3, 31, 0x04, 31),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_HCLK, "top_msdc50_0_hclk",
+ msdc50_0_h_parents, 0x074, 0x078, 0x07C, 8, 2, 15, 0x04, 29, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0, "top_msdc50_0",
+ msdc50_0_parents, 0x074, 0x078, 0x07C, 16, 3, 23, 0x04, 30, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1, "top_msdc30_1",
+ msdc30_parents, 0x074, 0x078, 0x07C, 24, 3, 31, 0x04, 31, 0),
/* CLK_CFG_8 */
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2, "top_msdc30_2",
- msdc30_parents, 0x080, 0x084, 0x088, 0, 3, 7, 0x08, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_2, "top_msdc30_2",
+ msdc30_parents, 0x080, 0x084, 0x088, 0, 3, 7, 0x08, 0, 0),
MUX_GATE_CLR_SET_UPD(CLK_TOP_INTDIR, "top_intdir",
intdir_parents, 0x080, 0x084, 0x088, 8, 2, 15, 0x08, 1),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS, "top_aud_intbus",
@@ -951,7 +955,8 @@ static const struct mtk_mux top_mtk_muxes[] = {
MUX_GATE_CLR_SET_UPD(CLK_TOP_ATB, "top_atb",
atb_parents, 0x08C, 0x090, 0x094, 8, 2, 15, 0x08, 5),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_PWRMCU, "top_pwrmcu",
- pwrmcu_parents, 0x08C, 0x090, 0x094, 16, 3, 23, 0x08, 6, CLK_IS_CRITICAL),
+ pwrmcu_parents, 0x08C, 0x090, 0x094, 16, 3, 23, 0x08, 6,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_DP, "top_dp",
dp_parents, 0x08C, 0x090, 0x094, 24, 4, 31, 0x08, 7),
/* CLK_CFG_10 */
@@ -1020,7 +1025,8 @@ static const struct mtk_mux top_mtk_muxes[] = {
MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM, "top_pwm",
pwm_parents, 0x0E0, 0x0E4, 0x0E8, 16, 1, 23, 0x0C, 2),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MCUPM, "top_mcupm",
- mcupm_parents, 0x0E0, 0x0E4, 0x0E8, 24, 2, 31, 0x0C, 3, CLK_IS_CRITICAL),
+ mcupm_parents, 0x0E0, 0x0E4, 0x0E8, 24, 2, 31, 0x0C, 3,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
/*
* CLK_CFG_17
* top_dvfsrc is for internal DVFS usage, should not be handled by Linux.
@@ -1030,7 +1036,8 @@ static const struct mtk_mux top_mtk_muxes[] = {
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_M_MST, "top_spmi_m_mst",
spmi_parents, 0x0EC, 0x0F0, 0x0F4, 8, 4, 15, 0x0C, 5),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DVFSRC, "top_dvfsrc",
- dvfsrc_parents, 0x0EC, 0x0F0, 0x0F4, 16, 2, 23, 0x0C, 6, CLK_IS_CRITICAL),
+ dvfsrc_parents, 0x0EC, 0x0F0, 0x0F4, 16, 2, 23, 0x0C, 6,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_TL, "top_tl",
tl_parents, 0x0EC, 0x0F0, 0x0F4, 24, 2, 31, 0x0C, 7),
/* CLK_CFG_18 */
@@ -1141,11 +1148,14 @@ static const struct mtk_mux top_mtk_muxes[] = {
MUX_GATE_CLR_SET_UPD(CLK_TOP_DVIO_DGI_REF, "top_dvio_dgi_ref",
dvio_dgi_ref_parents, 0x017C, 0x0180, 0x0184, 0, 3, 7, 0x010, 20),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_ULPOSC, "top_ulposc",
- ulposc_parents, 0x017C, 0x0180, 0x0184, 8, 2, 15, 0x010, 21, CLK_IS_CRITICAL),
+ ulposc_parents, 0x017C, 0x0180, 0x0184, 8, 2, 15, 0x010, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_ULPOSC_CORE, "top_ulposc_core",
- ulposc_core_parents, 0x017C, 0x0180, 0x0184, 16, 2, 23, 0x010, 22, CLK_IS_CRITICAL),
+ ulposc_core_parents, 0x017C, 0x0180, 0x0184, 16, 2, 23, 0x010, 22,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SRCK, "top_srck",
- srck_parents, 0x017C, 0x0180, 0x0184, 24, 1, 31, 0x010, 23, CLK_IS_CRITICAL),
+ srck_parents, 0x017C, 0x0180, 0x0184, 24, 1, 31, 0x010, 23,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
/*
* the clocks in CLK_CFG_30 ~ 37 are backup clock source, no need to handled
* by Linux.
@@ -1317,7 +1327,7 @@ free_top_data:
return r;
}
-static int clk_mt8195_topck_remove(struct platform_device *pdev)
+static void clk_mt8195_topck_remove(struct platform_device *pdev)
{
struct clk_hw_onecell_data *top_clk_data = platform_get_drvdata(pdev);
struct device_node *node = pdev->dev.of_node;
@@ -1329,13 +1339,11 @@ static int clk_mt8195_topck_remove(struct platform_device *pdev)
mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data);
mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), top_clk_data);
mtk_free_clk_data(top_clk_data);
-
- return 0;
}
static struct platform_driver clk_mt8195_topck_drv = {
.probe = clk_mt8195_topck_probe,
- .remove = clk_mt8195_topck_remove,
+ .remove_new = clk_mt8195_topck_remove,
.driver = {
.name = "clk-mt8195-topck",
.of_match_table = of_match_clk_mt8195_topck,
diff --git a/drivers/clk/mediatek/clk-mt8195-vdec.c b/drivers/clk/mediatek/clk-mt8195-vdec.c
index 2bcbceb10326..d266a6d3b603 100644
--- a/drivers/clk/mediatek/clk-mt8195-vdec.c
+++ b/drivers/clk/mediatek/clk-mt8195-vdec.c
@@ -97,7 +97,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_vdec);
static struct platform_driver clk_mt8195_vdec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8195-vdec",
.of_match_table = of_match_clk_mt8195_vdec,
diff --git a/drivers/clk/mediatek/clk-mt8195-vdo0.c b/drivers/clk/mediatek/clk-mt8195-vdo0.c
index 509780750e43..34fc318c146c 100644
--- a/drivers/clk/mediatek/clk-mt8195-vdo0.c
+++ b/drivers/clk/mediatek/clk-mt8195-vdo0.c
@@ -106,7 +106,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8195_vdo0_id_table);
static struct platform_driver clk_mt8195_vdo0_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8195-vdo0",
},
diff --git a/drivers/clk/mediatek/clk-mt8195-vdo1.c b/drivers/clk/mediatek/clk-mt8195-vdo1.c
index 0a5214a1ed25..e400631e1dbe 100644
--- a/drivers/clk/mediatek/clk-mt8195-vdo1.c
+++ b/drivers/clk/mediatek/clk-mt8195-vdo1.c
@@ -133,7 +133,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8195_vdo1_id_table);
static struct platform_driver clk_mt8195_vdo1_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8195-vdo1",
},
diff --git a/drivers/clk/mediatek/clk-mt8195-venc.c b/drivers/clk/mediatek/clk-mt8195-venc.c
index 0991a6968765..93093fadfd0d 100644
--- a/drivers/clk/mediatek/clk-mt8195-venc.c
+++ b/drivers/clk/mediatek/clk-mt8195-venc.c
@@ -62,7 +62,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_venc);
static struct platform_driver clk_mt8195_venc_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8195-venc",
.of_match_table = of_match_clk_mt8195_venc,
diff --git a/drivers/clk/mediatek/clk-mt8195-vpp0.c b/drivers/clk/mediatek/clk-mt8195-vpp0.c
index 1a98fb9a25e8..81725fcb3a72 100644
--- a/drivers/clk/mediatek/clk-mt8195-vpp0.c
+++ b/drivers/clk/mediatek/clk-mt8195-vpp0.c
@@ -99,7 +99,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8195_vpp0_id_table);
static struct platform_driver clk_mt8195_vpp0_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8195-vpp0",
},
diff --git a/drivers/clk/mediatek/clk-mt8195-vpp1.c b/drivers/clk/mediatek/clk-mt8195-vpp1.c
index c2d5b582f53a..867fde4e575b 100644
--- a/drivers/clk/mediatek/clk-mt8195-vpp1.c
+++ b/drivers/clk/mediatek/clk-mt8195-vpp1.c
@@ -97,7 +97,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8195_vpp1_id_table);
static struct platform_driver clk_mt8195_vpp1_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8195-vpp1",
},
diff --git a/drivers/clk/mediatek/clk-mt8195-wpe.c b/drivers/clk/mediatek/clk-mt8195-wpe.c
index 289896cb2f6c..7324738179a4 100644
--- a/drivers/clk/mediatek/clk-mt8195-wpe.c
+++ b/drivers/clk/mediatek/clk-mt8195-wpe.c
@@ -136,7 +136,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_wpe);
static struct platform_driver clk_mt8195_wpe_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8195-wpe",
.of_match_table = of_match_clk_mt8195_wpe,
diff --git a/drivers/clk/mediatek/clk-mt8365-apu.c b/drivers/clk/mediatek/clk-mt8365-apu.c
index 74f7fb22c87f..4f10ce1531d2 100644
--- a/drivers/clk/mediatek/clk-mt8365-apu.c
+++ b/drivers/clk/mediatek/clk-mt8365-apu.c
@@ -46,7 +46,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8365_apu);
static struct platform_driver clk_mt8365_apu_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8365-apu",
.of_match_table = of_match_clk_mt8365_apu,
diff --git a/drivers/clk/mediatek/clk-mt8365-cam.c b/drivers/clk/mediatek/clk-mt8365-cam.c
index 61516e19acd1..fe428a4f1d37 100644
--- a/drivers/clk/mediatek/clk-mt8365-cam.c
+++ b/drivers/clk/mediatek/clk-mt8365-cam.c
@@ -48,7 +48,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8365_cam);
static struct platform_driver clk_mt8365_cam_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8365-cam",
.of_match_table = of_match_clk_mt8365_cam,
diff --git a/drivers/clk/mediatek/clk-mt8365-mfg.c b/drivers/clk/mediatek/clk-mt8365-mfg.c
index 4c836c69db4f..4a590284f7e2 100644
--- a/drivers/clk/mediatek/clk-mt8365-mfg.c
+++ b/drivers/clk/mediatek/clk-mt8365-mfg.c
@@ -54,7 +54,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8365_mfg);
static struct platform_driver clk_mt8365_mfg_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8365-mfg",
.of_match_table = of_match_clk_mt8365_mfg,
diff --git a/drivers/clk/mediatek/clk-mt8365-mm.c b/drivers/clk/mediatek/clk-mt8365-mm.c
index 44427120846f..01a2ef8f594e 100644
--- a/drivers/clk/mediatek/clk-mt8365-mm.c
+++ b/drivers/clk/mediatek/clk-mt8365-mm.c
@@ -85,7 +85,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8365_mm_id_table);
static struct platform_driver clk_mt8365_mm_drv = {
.probe = mtk_clk_pdev_probe,
- .remove = mtk_clk_pdev_remove,
+ .remove_new = mtk_clk_pdev_remove,
.driver = {
.name = "clk-mt8365-mm",
},
diff --git a/drivers/clk/mediatek/clk-mt8365-vdec.c b/drivers/clk/mediatek/clk-mt8365-vdec.c
index b51571e9da00..233924837c3b 100644
--- a/drivers/clk/mediatek/clk-mt8365-vdec.c
+++ b/drivers/clk/mediatek/clk-mt8365-vdec.c
@@ -54,7 +54,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8365_vdec);
static struct platform_driver clk_mt8365_vdec_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8365-vdec",
.of_match_table = of_match_clk_mt8365_vdec,
diff --git a/drivers/clk/mediatek/clk-mt8365-venc.c b/drivers/clk/mediatek/clk-mt8365-venc.c
index 572344645c86..cc063f18e56b 100644
--- a/drivers/clk/mediatek/clk-mt8365-venc.c
+++ b/drivers/clk/mediatek/clk-mt8365-venc.c
@@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8365_venc);
static struct platform_driver clk_mt8365_venc_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8365-venc",
.of_match_table = of_match_clk_mt8365_venc,
diff --git a/drivers/clk/mediatek/clk-mt8365.c b/drivers/clk/mediatek/clk-mt8365.c
index c87a6c4a7967..1dca18f99134 100644
--- a/drivers/clk/mediatek/clk-mt8365.c
+++ b/drivers/clk/mediatek/clk-mt8365.c
@@ -411,7 +411,7 @@ static const struct mtk_mux top_muxes[] = {
/* CLK_CFG_0 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
0x040, 0x044, 0x048, 0, 2, 7, CLK_CFG_UPDATE,
- 0, CLK_IS_CRITICAL),
+ 0, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x040,
0x044, 0x048, 8, 2, 15, CLK_CFG_UPDATE, 1),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x040, 0x044,
@@ -432,22 +432,22 @@ static const struct mtk_mux top_muxes[] = {
0x064, 0x068, 0, 1, 7, CLK_CFG_UPDATE, 8),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x060,
0x064, 0x068, 8, 2, 15, CLK_CFG_UPDATE, 9),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HC_SEL, "msdc50_0_hc_sel",
- msdc50_0_hc_parents, 0x060, 0x064, 0x068, 16, 2,
- 23, CLK_CFG_UPDATE, 10),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC2_2_HC_SEL, "msdc2_2_hc_sel",
- msdc50_0_hc_parents, 0x060, 0x064, 0x068, 24, 2,
- 31, CLK_CFG_UPDATE, 11),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_HC_SEL, "msdc50_0_hc_sel",
+ msdc50_0_hc_parents, 0x060, 0x064, 0x068, 16, 2,
+ 23, CLK_CFG_UPDATE, 10, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC2_2_HC_SEL, "msdc2_2_hc_sel",
+ msdc50_0_hc_parents, 0x060, 0x064, 0x068, 24, 2,
+ 31, CLK_CFG_UPDATE, 11, 0),
/* CLK_CFG_3 */
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel",
- msdc50_0_parents, 0x070, 0x074, 0x078, 0, 3, 7,
- CLK_CFG_UPDATE, 12),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_2_SEL, "msdc50_2_sel",
- msdc50_2_parents, 0x070, 0x074, 0x078, 8, 3, 15,
- CLK_CFG_UPDATE, 13),
- MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel",
- msdc30_1_parents, 0x070, 0x074, 0x078, 16, 3, 23,
- CLK_CFG_UPDATE, 14),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel",
+ msdc50_0_parents, 0x070, 0x074, 0x078, 0, 3, 7,
+ CLK_CFG_UPDATE, 12, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_2_SEL, "msdc50_2_sel",
+ msdc50_2_parents, 0x070, 0x074, 0x078, 8, 3, 15,
+ CLK_CFG_UPDATE, 13, 0),
+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel",
+ msdc30_1_parents, 0x070, 0x074, 0x078, 16, 3, 23,
+ CLK_CFG_UPDATE, 14, 0),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents,
0x070, 0x074, 0x078, 24, 2, 31, CLK_CFG_UPDATE,
15),
@@ -476,7 +476,7 @@ static const struct mtk_mux top_muxes[] = {
/* CLK_CFG_6 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DXCC_SEL, "dxcc_sel", dxcc_parents,
0x0a0, 0x0a4, 0x0a8, 0, 2, 7, CLK_CFG_UPDATE,
- 24, CLK_IS_CRITICAL),
+ 24, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_SYS_SEL, "ssusb_sys_sel",
ssusb_sys_parents, 0x0a0, 0x0a4, 0x0a8, 8, 2, 15,
CLK_CFG_UPDATE, 25),
@@ -484,8 +484,8 @@ static const struct mtk_mux top_muxes[] = {
ssusb_sys_parents, 0x0a0, 0x0a4, 0x0a8, 16, 2, 23,
CLK_CFG_UPDATE, 26),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM_SEL, "spm_sel", spm_parents,
- 0x0a0, 0x0a4, 0x0a8, 24, 1, 31,
- CLK_CFG_UPDATE, 27, CLK_IS_CRITICAL),
+ 0x0a0, 0x0a4, 0x0a8, 24, 1, 31, CLK_CFG_UPDATE,
+ 27, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
/* CLK_CFG_7 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x0b0,
0x0b4, 0x0b8, 0, 3, 7, CLK_CFG_UPDATE, 28),
@@ -811,7 +811,7 @@ static struct platform_driver clk_mt8365_drv = {
.of_match_table = of_match_clk_mt8365,
},
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
};
module_platform_driver(clk_mt8365_drv);
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mediatek/clk-mt8516-aud.c b/drivers/clk/mediatek/clk-mt8516-aud.c
index 48340fc7430d..d1e848e78fd5 100644
--- a/drivers/clk/mediatek/clk-mt8516-aud.c
+++ b/drivers/clk/mediatek/clk-mt8516-aud.c
@@ -55,7 +55,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8516_aud);
static struct platform_driver clk_mt8516_aud_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8516-aud",
.of_match_table = of_match_clk_mt8516_aud,
diff --git a/drivers/clk/mediatek/clk-mt8516.c b/drivers/clk/mediatek/clk-mt8516.c
index 21eb052b0a53..b8ae837c59dc 100644
--- a/drivers/clk/mediatek/clk-mt8516.c
+++ b/drivers/clk/mediatek/clk-mt8516.c
@@ -669,7 +669,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8516);
static struct platform_driver clk_mt8516_drv = {
.probe = mtk_clk_simple_probe,
- .remove = mtk_clk_simple_remove,
+ .remove_new = mtk_clk_simple_remove,
.driver = {
.name = "clk-mt8516",
.of_match_table = of_match_clk_mt8516,
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index fd2214c3242f..2e55368dc4d8 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -469,7 +469,7 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
const struct platform_device_id *id;
const struct mtk_clk_desc *mcd;
struct clk_hw_onecell_data *clk_data;
- void __iomem *base;
+ void __iomem *base = NULL;
int num_clks, r;
mcd = device_get_match_data(&pdev->dev);
@@ -483,8 +483,8 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
return -EINVAL;
}
- /* Composite clocks needs us to pass iomem pointer */
- if (mcd->composite_clks) {
+ /* Composite and divider clocks needs us to pass iomem pointer */
+ if (mcd->composite_clks || mcd->divider_clks) {
if (!mcd->shared_io)
base = devm_platform_ioremap_resource(pdev, 0);
else
@@ -500,8 +500,10 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
num_clks += mcd->num_mux_clks + mcd->num_divider_clks;
clk_data = mtk_alloc_clk_data(num_clks);
- if (!clk_data)
- return -ENOMEM;
+ if (!clk_data) {
+ r = -ENOMEM;
+ goto free_base;
+ }
if (mcd->fixed_clks) {
r = mtk_clk_register_fixed_clks(mcd->fixed_clks,
@@ -599,12 +601,13 @@ unregister_fixed_clks:
mcd->num_fixed_clks, clk_data);
free_data:
mtk_free_clk_data(clk_data);
+free_base:
if (mcd->shared_io && base)
iounmap(base);
return r;
}
-static int __mtk_clk_simple_remove(struct platform_device *pdev,
+static void __mtk_clk_simple_remove(struct platform_device *pdev,
struct device_node *node)
{
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
@@ -629,8 +632,6 @@ static int __mtk_clk_simple_remove(struct platform_device *pdev,
mtk_clk_unregister_fixed_clks(mcd->fixed_clks,
mcd->num_fixed_clks, clk_data);
mtk_free_clk_data(clk_data);
-
- return 0;
}
int mtk_clk_pdev_probe(struct platform_device *pdev)
@@ -650,18 +651,18 @@ int mtk_clk_simple_probe(struct platform_device *pdev)
}
EXPORT_SYMBOL_GPL(mtk_clk_simple_probe);
-int mtk_clk_pdev_remove(struct platform_device *pdev)
+void mtk_clk_pdev_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->parent->of_node;
- return __mtk_clk_simple_remove(pdev, node);
+ __mtk_clk_simple_remove(pdev, node);
}
EXPORT_SYMBOL_GPL(mtk_clk_pdev_remove);
-int mtk_clk_simple_remove(struct platform_device *pdev)
+void mtk_clk_simple_remove(struct platform_device *pdev)
{
- return __mtk_clk_simple_remove(pdev, pdev->dev.of_node);
+ __mtk_clk_simple_remove(pdev, pdev->dev.of_node);
}
EXPORT_SYMBOL_GPL(mtk_clk_simple_remove);
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index b7a751861fce..22096501a60a 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -240,8 +240,8 @@ struct mtk_clk_desc {
};
int mtk_clk_pdev_probe(struct platform_device *pdev);
-int mtk_clk_pdev_remove(struct platform_device *pdev);
+void mtk_clk_pdev_remove(struct platform_device *pdev);
int mtk_clk_simple_probe(struct platform_device *pdev);
-int mtk_clk_simple_remove(struct platform_device *pdev);
+void mtk_clk_simple_remove(struct platform_device *pdev);
#endif /* __DRV_CLK_MTK_H */
diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c
index c8593554239d..c93bc7f926e5 100644
--- a/drivers/clk/mediatek/clk-mux.c
+++ b/drivers/clk/mediatek/clk-mux.c
@@ -168,7 +168,7 @@ static struct clk_hw *mtk_clk_register_mux(struct device *dev,
return ERR_PTR(-ENOMEM);
init.name = mux->name;
- init.flags = mux->flags | CLK_SET_RATE_PARENT;
+ init.flags = mux->flags;
init.parent_names = mux->parent_names;
init.num_parents = mux->num_parents;
init.ops = mux->ops;
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index fc002c155bc3..8ce846fdbe43 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -99,6 +99,26 @@ config COMMON_CLK_AXG_AUDIO
Support for the audio clock controller on AmLogic A113D devices,
aka axg, Say Y if you want audio subsystem to work.
+config COMMON_CLK_A1_PLL
+ tristate "Amlogic A1 SoC PLL controller support"
+ depends on ARM64
+ select COMMON_CLK_MESON_REGMAP
+ select COMMON_CLK_MESON_PLL
+ help
+ Support for the PLL clock controller on Amlogic A113L based
+ device, A1 SoC Family. Say Y if you want A1 PLL clock controller
+ to work.
+
+config COMMON_CLK_A1_PERIPHERALS
+ tristate "Amlogic A1 SoC Peripherals clock controller support"
+ depends on ARM64
+ select COMMON_CLK_MESON_DUALDIV
+ select COMMON_CLK_MESON_REGMAP
+ help
+ Support for the Peripherals clock controller on Amlogic A113L based
+ device, A1 SoC Family. Say Y if you want A1 Peripherals clock
+ controller to work.
+
config COMMON_CLK_G12A
tristate "G12 and SM1 SoC clock controllers support"
depends on ARM64
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 6eca2a406ee3..d5288662881d 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -16,6 +16,8 @@ obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o
obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
+obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
+obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
diff --git a/drivers/clk/meson/a1-peripherals.c b/drivers/clk/meson/a1-peripherals.c
new file mode 100644
index 000000000000..75dfae210fe5
--- /dev/null
+++ b/drivers/clk/meson/a1-peripherals.c
@@ -0,0 +1,2243 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Jian Hu <jian.hu@amlogic.com>
+ *
+ * Copyright (c) 2023, SberDevices. All Rights Reserved.
+ * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "a1-peripherals.h"
+#include "clk-dualdiv.h"
+#include "clk-regmap.h"
+
+static struct clk_regmap xtal_in = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SYS_OSCIN_CTRL,
+ .bit_idx = 0,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "xtal_in",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fixpll_in = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SYS_OSCIN_CTRL,
+ .bit_idx = 1,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fixpll_in",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap usb_phy_in = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SYS_OSCIN_CTRL,
+ .bit_idx = 2,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "usb_phy_in",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap usb_ctrl_in = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SYS_OSCIN_CTRL,
+ .bit_idx = 3,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "usb_ctrl_in",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap hifipll_in = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SYS_OSCIN_CTRL,
+ .bit_idx = 4,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hifipll_in",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap syspll_in = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SYS_OSCIN_CTRL,
+ .bit_idx = 5,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "syspll_in",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap dds_in = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SYS_OSCIN_CTRL,
+ .bit_idx = 6,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dds_in",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap rtc_32k_in = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = RTC_BY_OSCIN_CTRL0,
+ .bit_idx = 31,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "rtc_32k_in",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static const struct meson_clk_dualdiv_param clk_32k_div_table[] = {
+ {
+ .dual = 1,
+ .n1 = 733,
+ .m1 = 8,
+ .n2 = 732,
+ .m2 = 11,
+ },
+ {}
+};
+
+static struct clk_regmap rtc_32k_div = {
+ .data = &(struct meson_clk_dualdiv_data){
+ .n1 = {
+ .reg_off = RTC_BY_OSCIN_CTRL0,
+ .shift = 0,
+ .width = 12,
+ },
+ .n2 = {
+ .reg_off = RTC_BY_OSCIN_CTRL0,
+ .shift = 12,
+ .width = 12,
+ },
+ .m1 = {
+ .reg_off = RTC_BY_OSCIN_CTRL1,
+ .shift = 0,
+ .width = 12,
+ },
+ .m2 = {
+ .reg_off = RTC_BY_OSCIN_CTRL1,
+ .shift = 12,
+ .width = 12,
+ },
+ .dual = {
+ .reg_off = RTC_BY_OSCIN_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .table = clk_32k_div_table,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "rtc_32k_div",
+ .ops = &meson_clk_dualdiv_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &rtc_32k_in.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap rtc_32k_xtal = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = RTC_BY_OSCIN_CTRL1,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "rtc_32k_xtal",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &rtc_32k_in.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap rtc_32k_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = RTC_CTRL,
+ .mask = 0x3,
+ .shift = 0,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "rtc_32k_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &rtc_32k_xtal.hw,
+ &rtc_32k_div.hw,
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap rtc = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = RTC_BY_OSCIN_CTRL0,
+ .bit_idx = 30,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "rtc",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &rtc_32k_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static u32 mux_table_sys[] = { 0, 1, 2, 3, 7 };
+static const struct clk_parent_data sys_parents[] = {
+ { .fw_name = "xtal" },
+ { .fw_name = "fclk_div2" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div5" },
+ { .hw = &rtc.hw },
+};
+
+static struct clk_regmap sys_b_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = SYS_CLK_CTRL0,
+ .mask = 0x7,
+ .shift = 26,
+ .table = mux_table_sys,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sys_b_sel",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_data = sys_parents,
+ .num_parents = ARRAY_SIZE(sys_parents),
+ },
+};
+
+static struct clk_regmap sys_b_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = SYS_CLK_CTRL0,
+ .shift = 16,
+ .width = 10,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sys_b_div",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sys_b_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap sys_b = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SYS_CLK_CTRL0,
+ .bit_idx = 29,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sys_b",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sys_b_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap sys_a_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = SYS_CLK_CTRL0,
+ .mask = 0x7,
+ .shift = 10,
+ .table = mux_table_sys,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sys_a_sel",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_data = sys_parents,
+ .num_parents = ARRAY_SIZE(sys_parents),
+ },
+};
+
+static struct clk_regmap sys_a_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = SYS_CLK_CTRL0,
+ .shift = 0,
+ .width = 10,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sys_a_div",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sys_a_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap sys_a = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SYS_CLK_CTRL0,
+ .bit_idx = 13,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sys_a",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sys_a_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap sys = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = SYS_CLK_CTRL0,
+ .mask = 0x1,
+ .shift = 31,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sys",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sys_a.hw,
+ &sys_b.hw,
+ },
+ .num_parents = 2,
+ /*
+ * This clock is used by APB bus which is set in boot ROM code
+ * and is required by the platform to operate correctly.
+ * Until the following condition are met, we need this clock to
+ * be marked as critical:
+ * a) Mark the clock used by a firmware resource, if possible
+ * b) CCF has a clock hand-off mechanism to make the sure the
+ * clock stays on until the proper driver comes along
+ */
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ },
+};
+
+static u32 mux_table_dsp_ab[] = { 0, 1, 2, 3, 4, 7 };
+static const struct clk_parent_data dsp_ab_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .fw_name = "fclk_div2", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "hifi_pll", },
+ { .hw = &rtc.hw },
+};
+
+static struct clk_regmap dspa_a_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = DSPA_CLK_CTRL0,
+ .mask = 0x7,
+ .shift = 10,
+ .table = mux_table_dsp_ab,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dspa_a_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = dsp_ab_parent_data,
+ .num_parents = ARRAY_SIZE(dsp_ab_parent_data),
+ },
+};
+
+static struct clk_regmap dspa_a_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = DSPA_CLK_CTRL0,
+ .shift = 0,
+ .width = 10,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dspa_a_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspa_a_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspa_a = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = DSPA_CLK_CTRL0,
+ .bit_idx = 13,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dspa_a",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspa_a_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspa_b_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = DSPA_CLK_CTRL0,
+ .mask = 0x7,
+ .shift = 26,
+ .table = mux_table_dsp_ab,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dspa_b_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = dsp_ab_parent_data,
+ .num_parents = ARRAY_SIZE(dsp_ab_parent_data),
+ },
+};
+
+static struct clk_regmap dspa_b_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = DSPA_CLK_CTRL0,
+ .shift = 16,
+ .width = 10,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dspa_b_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspa_b_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspa_b = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = DSPA_CLK_CTRL0,
+ .bit_idx = 29,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dspa_b",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspa_b_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspa_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = DSPA_CLK_CTRL0,
+ .mask = 0x1,
+ .shift = 15,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dspa_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspa_a.hw,
+ &dspa_b.hw,
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspa_en = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = DSPA_CLK_EN,
+ .bit_idx = 1,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dspa_en",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspa_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspa_en_nic = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = DSPA_CLK_EN,
+ .bit_idx = 0,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dspa_en_nic",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspa_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspb_a_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = DSPB_CLK_CTRL0,
+ .mask = 0x7,
+ .shift = 10,
+ .table = mux_table_dsp_ab,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dspb_a_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = dsp_ab_parent_data,
+ .num_parents = ARRAY_SIZE(dsp_ab_parent_data),
+ },
+};
+
+static struct clk_regmap dspb_a_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = DSPB_CLK_CTRL0,
+ .shift = 0,
+ .width = 10,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dspb_a_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspb_a_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspb_a = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = DSPB_CLK_CTRL0,
+ .bit_idx = 13,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dspb_a",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspb_a_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspb_b_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = DSPB_CLK_CTRL0,
+ .mask = 0x7,
+ .shift = 26,
+ .table = mux_table_dsp_ab,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dspb_b_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = dsp_ab_parent_data,
+ .num_parents = ARRAY_SIZE(dsp_ab_parent_data),
+ },
+};
+
+static struct clk_regmap dspb_b_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = DSPB_CLK_CTRL0,
+ .shift = 16,
+ .width = 10,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dspb_b_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspb_b_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspb_b = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = DSPB_CLK_CTRL0,
+ .bit_idx = 29,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dspb_b",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspb_b_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspb_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = DSPB_CLK_CTRL0,
+ .mask = 0x1,
+ .shift = 15,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dspb_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspb_a.hw,
+ &dspb_b.hw,
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspb_en = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = DSPB_CLK_EN,
+ .bit_idx = 1,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dspb_en",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspb_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dspb_en_nic = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = DSPB_CLK_EN,
+ .bit_idx = 0,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dspb_en_nic",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dspb_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap clk_24m = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLK12_24_CTRL,
+ .bit_idx = 11,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "24m",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor clk_24m_div2 = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "24m_div2",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &clk_24m.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap clk_12m = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLK12_24_CTRL,
+ .bit_idx = 10,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "12m",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &clk_24m_div2.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_div2_divn_pre = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = CLK12_24_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2_divn_pre",
+ .ops = &clk_regmap_divider_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "fclk_div2",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_div2_divn = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CLK12_24_CTRL,
+ .bit_idx = 12,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2_divn",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_div2_divn_pre.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/*
+ * the index 2 is sys_pll_div16, it will be implemented in the CPU clock driver,
+ * the index 4 is the clock measurement source, it's not supported yet
+ */
+static u32 gen_table[] = { 0, 1, 3, 5, 6, 7, 8 };
+static const struct clk_parent_data gen_parent_data[] = {
+ { .fw_name = "xtal", },
+ { .hw = &rtc.hw },
+ { .fw_name = "hifi_pll", },
+ { .fw_name = "fclk_div2", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "fclk_div7", },
+};
+
+static struct clk_regmap gen_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = GEN_CLK_CTRL,
+ .mask = 0xf,
+ .shift = 12,
+ .table = gen_table,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "gen_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = gen_parent_data,
+ .num_parents = ARRAY_SIZE(gen_parent_data),
+ /*
+ * The GEN clock can be connected to an external pad, so it
+ * may be set up directly from the device tree. Additionally,
+ * the GEN clock can be inherited from a more accurate RTC
+ * clock, so in certain situations, it may be necessary
+ * to freeze its parent.
+ */
+ .flags = CLK_SET_RATE_NO_REPARENT,
+ },
+};
+
+static struct clk_regmap gen_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = GEN_CLK_CTRL,
+ .shift = 0,
+ .width = 11,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "gen_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &gen_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap gen = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = GEN_CLK_CTRL,
+ .bit_idx = 11,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "gen",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &gen_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap saradc_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = SAR_ADC_CLK_CTRL,
+ .mask = 0x1,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "saradc_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .fw_name = "xtal", },
+ { .hw = &sys.hw, },
+ },
+ .num_parents = 2,
+ },
+};
+
+static struct clk_regmap saradc_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = SAR_ADC_CLK_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "saradc_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &saradc_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap saradc = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SAR_ADC_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "saradc",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &saradc_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data pwm_abcd_parents[] = {
+ { .fw_name = "xtal", },
+ { .hw = &sys.hw },
+ { .hw = &rtc.hw },
+};
+
+static struct clk_regmap pwm_a_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = PWM_CLK_AB_CTRL,
+ .mask = 0x1,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_a_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = pwm_abcd_parents,
+ .num_parents = ARRAY_SIZE(pwm_abcd_parents),
+ },
+};
+
+static struct clk_regmap pwm_a_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = PWM_CLK_AB_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_a_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &pwm_a_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap pwm_a = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = PWM_CLK_AB_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "pwm_a",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &pwm_a_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap pwm_b_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = PWM_CLK_AB_CTRL,
+ .mask = 0x1,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_b_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = pwm_abcd_parents,
+ .num_parents = ARRAY_SIZE(pwm_abcd_parents),
+ },
+};
+
+static struct clk_regmap pwm_b_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = PWM_CLK_AB_CTRL,
+ .shift = 16,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_b_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &pwm_b_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap pwm_b = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = PWM_CLK_AB_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "pwm_b",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &pwm_b_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap pwm_c_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = PWM_CLK_CD_CTRL,
+ .mask = 0x1,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_c_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = pwm_abcd_parents,
+ .num_parents = ARRAY_SIZE(pwm_abcd_parents),
+ },
+};
+
+static struct clk_regmap pwm_c_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = PWM_CLK_CD_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_c_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &pwm_c_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap pwm_c = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = PWM_CLK_CD_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "pwm_c",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &pwm_c_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap pwm_d_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = PWM_CLK_CD_CTRL,
+ .mask = 0x1,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_d_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = pwm_abcd_parents,
+ .num_parents = ARRAY_SIZE(pwm_abcd_parents),
+ },
+};
+
+static struct clk_regmap pwm_d_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = PWM_CLK_CD_CTRL,
+ .shift = 16,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_d_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &pwm_d_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap pwm_d = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = PWM_CLK_CD_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "pwm_d",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &pwm_d_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data pwm_ef_parents[] = {
+ { .fw_name = "xtal", },
+ { .hw = &sys.hw },
+ { .fw_name = "fclk_div5", },
+ { .hw = &rtc.hw },
+};
+
+static struct clk_regmap pwm_e_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = PWM_CLK_EF_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_e_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = pwm_ef_parents,
+ .num_parents = ARRAY_SIZE(pwm_ef_parents),
+ },
+};
+
+static struct clk_regmap pwm_e_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = PWM_CLK_EF_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_e_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &pwm_e_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap pwm_e = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = PWM_CLK_EF_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "pwm_e",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &pwm_e_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap pwm_f_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = PWM_CLK_EF_CTRL,
+ .mask = 0x3,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_f_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = pwm_ef_parents,
+ .num_parents = ARRAY_SIZE(pwm_ef_parents),
+ },
+};
+
+static struct clk_regmap pwm_f_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = PWM_CLK_EF_CTRL,
+ .shift = 16,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "pwm_f_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &pwm_f_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap pwm_f = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = PWM_CLK_EF_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "pwm_f",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &pwm_f_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/*
+ * spicc clk
+ * fdiv2 |\ |\ _____
+ * ---------| |---DIV--| | | | spicc out
+ * ---------| | | |-----|GATE |---------
+ * ..... |/ | / |_____|
+ * --------------------|/
+ * 24M
+ */
+static const struct clk_parent_data spicc_spifc_parents[] = {
+ { .fw_name = "fclk_div2"},
+ { .fw_name = "fclk_div3"},
+ { .fw_name = "fclk_div5"},
+ { .fw_name = "hifi_pll" },
+};
+
+static struct clk_regmap spicc_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = SPICC_CLK_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "spicc_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = spicc_spifc_parents,
+ .num_parents = ARRAY_SIZE(spicc_spifc_parents),
+ },
+};
+
+static struct clk_regmap spicc_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = SPICC_CLK_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "spicc_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &spicc_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap spicc_sel2 = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = SPICC_CLK_CTRL,
+ .mask = 0x1,
+ .shift = 15,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "spicc_sel2",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .hw = &spicc_div.hw },
+ { .fw_name = "xtal", },
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap spicc = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SPICC_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spicc",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &spicc_sel2.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap ts_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = TS_CLK_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ts_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap ts = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = TS_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "ts",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &ts_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap spifc_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = SPIFC_CLK_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "spifc_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = spicc_spifc_parents,
+ .num_parents = ARRAY_SIZE(spicc_spifc_parents),
+ },
+};
+
+static struct clk_regmap spifc_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = SPIFC_CLK_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "spifc_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &spifc_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap spifc_sel2 = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = SPIFC_CLK_CTRL,
+ .mask = 0x1,
+ .shift = 15,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "spifc_sel2",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .hw = &spifc_div.hw },
+ { .fw_name = "xtal", },
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap spifc = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SPIFC_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spifc",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &spifc_sel2.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data usb_bus_parents[] = {
+ { .fw_name = "xtal", },
+ { .hw = &sys.hw },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div5", },
+};
+
+static struct clk_regmap usb_bus_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = USB_BUSCLK_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_bus_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = usb_bus_parents,
+ .num_parents = ARRAY_SIZE(usb_bus_parents),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap usb_bus_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = USB_BUSCLK_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_bus_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &usb_bus_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap usb_bus = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = USB_BUSCLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "usb_bus",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &usb_bus_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data sd_emmc_psram_dmc_parents[] = {
+ { .fw_name = "fclk_div2", },
+ { .fw_name = "fclk_div3", },
+ { .fw_name = "fclk_div5", },
+ { .fw_name = "hifi_pll", },
+};
+
+static struct clk_regmap sd_emmc_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = SD_EMMC_CLK_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sd_emmc_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = sd_emmc_psram_dmc_parents,
+ .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents),
+ },
+};
+
+static struct clk_regmap sd_emmc_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = SD_EMMC_CLK_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sd_emmc_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sd_emmc_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap sd_emmc_sel2 = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = SD_EMMC_CLK_CTRL,
+ .mask = 0x1,
+ .shift = 15,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "sd_emmc_sel2",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .hw = &sd_emmc_div.hw },
+ { .fw_name = "xtal", },
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap sd_emmc = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = SD_EMMC_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sd_emmc_sel2.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap psram_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = PSRAM_CLK_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "psram_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = sd_emmc_psram_dmc_parents,
+ .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents),
+ },
+};
+
+static struct clk_regmap psram_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = PSRAM_CLK_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "psram_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &psram_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap psram_sel2 = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = PSRAM_CLK_CTRL,
+ .mask = 0x1,
+ .shift = 15,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "psram_sel2",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .hw = &psram_div.hw },
+ { .fw_name = "xtal", },
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap psram = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = PSRAM_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "psram",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &psram_sel2.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dmc_sel = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = DMC_CLK_CTRL,
+ .mask = 0x3,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dmc_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = sd_emmc_psram_dmc_parents,
+ .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents),
+ },
+};
+
+static struct clk_regmap dmc_div = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = DMC_CLK_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dmc_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dmc_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dmc_sel2 = {
+ .data = &(struct clk_regmap_mux_data){
+ .offset = DMC_CLK_CTRL,
+ .mask = 0x1,
+ .shift = 15,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "dmc_sel2",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = (const struct clk_parent_data []) {
+ { .hw = &dmc_div.hw },
+ { .fw_name = "xtal", },
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dmc = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = DMC_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dmc",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dmc_sel2.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap ceca_32k_in = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CECA_CLK_CTRL0,
+ .bit_idx = 31,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "ceca_32k_in",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap ceca_32k_div = {
+ .data = &(struct meson_clk_dualdiv_data){
+ .n1 = {
+ .reg_off = CECA_CLK_CTRL0,
+ .shift = 0,
+ .width = 12,
+ },
+ .n2 = {
+ .reg_off = CECA_CLK_CTRL0,
+ .shift = 12,
+ .width = 12,
+ },
+ .m1 = {
+ .reg_off = CECA_CLK_CTRL1,
+ .shift = 0,
+ .width = 12,
+ },
+ .m2 = {
+ .reg_off = CECA_CLK_CTRL1,
+ .shift = 12,
+ .width = 12,
+ },
+ .dual = {
+ .reg_off = CECA_CLK_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .table = clk_32k_div_table,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ceca_32k_div",
+ .ops = &meson_clk_dualdiv_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &ceca_32k_in.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap ceca_32k_sel_pre = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CECA_CLK_CTRL1,
+ .mask = 0x1,
+ .shift = 24,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ceca_32k_sel_pre",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &ceca_32k_div.hw,
+ &ceca_32k_in.hw,
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap ceca_32k_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CECA_CLK_CTRL1,
+ .mask = 0x1,
+ .shift = 31,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ceca_32k_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &ceca_32k_sel_pre.hw,
+ &rtc.hw,
+ },
+ .num_parents = 2,
+ },
+};
+
+static struct clk_regmap ceca_32k_out = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CECA_CLK_CTRL0,
+ .bit_idx = 30,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ceca_32k_out",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &ceca_32k_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap cecb_32k_in = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CECB_CLK_CTRL0,
+ .bit_idx = 31,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "cecb_32k_in",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap cecb_32k_div = {
+ .data = &(struct meson_clk_dualdiv_data){
+ .n1 = {
+ .reg_off = CECB_CLK_CTRL0,
+ .shift = 0,
+ .width = 12,
+ },
+ .n2 = {
+ .reg_off = CECB_CLK_CTRL0,
+ .shift = 12,
+ .width = 12,
+ },
+ .m1 = {
+ .reg_off = CECB_CLK_CTRL1,
+ .shift = 0,
+ .width = 12,
+ },
+ .m2 = {
+ .reg_off = CECB_CLK_CTRL1,
+ .shift = 12,
+ .width = 12,
+ },
+ .dual = {
+ .reg_off = CECB_CLK_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .table = clk_32k_div_table,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cecb_32k_div",
+ .ops = &meson_clk_dualdiv_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &cecb_32k_in.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap cecb_32k_sel_pre = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CECB_CLK_CTRL1,
+ .mask = 0x1,
+ .shift = 24,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cecb_32k_sel_pre",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &cecb_32k_div.hw,
+ &cecb_32k_in.hw,
+ },
+ .num_parents = 2,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap cecb_32k_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = CECB_CLK_CTRL1,
+ .mask = 0x1,
+ .shift = 31,
+ .flags = CLK_MUX_ROUND_CLOSEST,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cecb_32k_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &cecb_32k_sel_pre.hw,
+ &rtc.hw,
+ },
+ .num_parents = 2,
+ },
+};
+
+static struct clk_regmap cecb_32k_out = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = CECB_CLK_CTRL0,
+ .bit_idx = 30,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "cecb_32k_out",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &cecb_32k_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+#define MESON_GATE(_name, _reg, _bit) \
+ MESON_PCLK(_name, _reg, _bit, &sys.hw)
+
+static MESON_GATE(clktree, SYS_CLK_EN0, 0);
+static MESON_GATE(reset_ctrl, SYS_CLK_EN0, 1);
+static MESON_GATE(analog_ctrl, SYS_CLK_EN0, 2);
+static MESON_GATE(pwr_ctrl, SYS_CLK_EN0, 3);
+static MESON_GATE(pad_ctrl, SYS_CLK_EN0, 4);
+static MESON_GATE(sys_ctrl, SYS_CLK_EN0, 5);
+static MESON_GATE(temp_sensor, SYS_CLK_EN0, 6);
+static MESON_GATE(am2axi_dev, SYS_CLK_EN0, 7);
+static MESON_GATE(spicc_b, SYS_CLK_EN0, 8);
+static MESON_GATE(spicc_a, SYS_CLK_EN0, 9);
+static MESON_GATE(msr, SYS_CLK_EN0, 10);
+static MESON_GATE(audio, SYS_CLK_EN0, 11);
+static MESON_GATE(jtag_ctrl, SYS_CLK_EN0, 12);
+static MESON_GATE(saradc_en, SYS_CLK_EN0, 13);
+static MESON_GATE(pwm_ef, SYS_CLK_EN0, 14);
+static MESON_GATE(pwm_cd, SYS_CLK_EN0, 15);
+static MESON_GATE(pwm_ab, SYS_CLK_EN0, 16);
+static MESON_GATE(cec, SYS_CLK_EN0, 17);
+static MESON_GATE(i2c_s, SYS_CLK_EN0, 18);
+static MESON_GATE(ir_ctrl, SYS_CLK_EN0, 19);
+static MESON_GATE(i2c_m_d, SYS_CLK_EN0, 20);
+static MESON_GATE(i2c_m_c, SYS_CLK_EN0, 21);
+static MESON_GATE(i2c_m_b, SYS_CLK_EN0, 22);
+static MESON_GATE(i2c_m_a, SYS_CLK_EN0, 23);
+static MESON_GATE(acodec, SYS_CLK_EN0, 24);
+static MESON_GATE(otp, SYS_CLK_EN0, 25);
+static MESON_GATE(sd_emmc_a, SYS_CLK_EN0, 26);
+static MESON_GATE(usb_phy, SYS_CLK_EN0, 27);
+static MESON_GATE(usb_ctrl, SYS_CLK_EN0, 28);
+static MESON_GATE(sys_dspb, SYS_CLK_EN0, 29);
+static MESON_GATE(sys_dspa, SYS_CLK_EN0, 30);
+static MESON_GATE(dma, SYS_CLK_EN0, 31);
+static MESON_GATE(irq_ctrl, SYS_CLK_EN1, 0);
+static MESON_GATE(nic, SYS_CLK_EN1, 1);
+static MESON_GATE(gic, SYS_CLK_EN1, 2);
+static MESON_GATE(uart_c, SYS_CLK_EN1, 3);
+static MESON_GATE(uart_b, SYS_CLK_EN1, 4);
+static MESON_GATE(uart_a, SYS_CLK_EN1, 5);
+static MESON_GATE(sys_psram, SYS_CLK_EN1, 6);
+static MESON_GATE(rsa, SYS_CLK_EN1, 8);
+static MESON_GATE(coresight, SYS_CLK_EN1, 9);
+static MESON_GATE(am2axi_vad, AXI_CLK_EN, 0);
+static MESON_GATE(audio_vad, AXI_CLK_EN, 1);
+static MESON_GATE(axi_dmc, AXI_CLK_EN, 3);
+static MESON_GATE(axi_psram, AXI_CLK_EN, 4);
+static MESON_GATE(ramb, AXI_CLK_EN, 5);
+static MESON_GATE(rama, AXI_CLK_EN, 6);
+static MESON_GATE(axi_spifc, AXI_CLK_EN, 7);
+static MESON_GATE(axi_nic, AXI_CLK_EN, 8);
+static MESON_GATE(axi_dma, AXI_CLK_EN, 9);
+static MESON_GATE(cpu_ctrl, AXI_CLK_EN, 10);
+static MESON_GATE(rom, AXI_CLK_EN, 11);
+static MESON_GATE(prod_i2c, AXI_CLK_EN, 12);
+
+/* Array of all clocks registered by this provider */
+static struct clk_hw_onecell_data a1_periphs_clks = {
+ .hws = {
+ [CLKID_XTAL_IN] = &xtal_in.hw,
+ [CLKID_FIXPLL_IN] = &fixpll_in.hw,
+ [CLKID_USB_PHY_IN] = &usb_phy_in.hw,
+ [CLKID_USB_CTRL_IN] = &usb_ctrl_in.hw,
+ [CLKID_HIFIPLL_IN] = &hifipll_in.hw,
+ [CLKID_SYSPLL_IN] = &syspll_in.hw,
+ [CLKID_DDS_IN] = &dds_in.hw,
+ [CLKID_SYS] = &sys.hw,
+ [CLKID_CLKTREE] = &clktree.hw,
+ [CLKID_RESET_CTRL] = &reset_ctrl.hw,
+ [CLKID_ANALOG_CTRL] = &analog_ctrl.hw,
+ [CLKID_PWR_CTRL] = &pwr_ctrl.hw,
+ [CLKID_PAD_CTRL] = &pad_ctrl.hw,
+ [CLKID_SYS_CTRL] = &sys_ctrl.hw,
+ [CLKID_TEMP_SENSOR] = &temp_sensor.hw,
+ [CLKID_AM2AXI_DIV] = &am2axi_dev.hw,
+ [CLKID_SPICC_B] = &spicc_b.hw,
+ [CLKID_SPICC_A] = &spicc_a.hw,
+ [CLKID_MSR] = &msr.hw,
+ [CLKID_AUDIO] = &audio.hw,
+ [CLKID_JTAG_CTRL] = &jtag_ctrl.hw,
+ [CLKID_SARADC_EN] = &saradc_en.hw,
+ [CLKID_PWM_EF] = &pwm_ef.hw,
+ [CLKID_PWM_CD] = &pwm_cd.hw,
+ [CLKID_PWM_AB] = &pwm_ab.hw,
+ [CLKID_CEC] = &cec.hw,
+ [CLKID_I2C_S] = &i2c_s.hw,
+ [CLKID_IR_CTRL] = &ir_ctrl.hw,
+ [CLKID_I2C_M_D] = &i2c_m_d.hw,
+ [CLKID_I2C_M_C] = &i2c_m_c.hw,
+ [CLKID_I2C_M_B] = &i2c_m_b.hw,
+ [CLKID_I2C_M_A] = &i2c_m_a.hw,
+ [CLKID_ACODEC] = &acodec.hw,
+ [CLKID_OTP] = &otp.hw,
+ [CLKID_SD_EMMC_A] = &sd_emmc_a.hw,
+ [CLKID_USB_PHY] = &usb_phy.hw,
+ [CLKID_USB_CTRL] = &usb_ctrl.hw,
+ [CLKID_SYS_DSPB] = &sys_dspb.hw,
+ [CLKID_SYS_DSPA] = &sys_dspa.hw,
+ [CLKID_DMA] = &dma.hw,
+ [CLKID_IRQ_CTRL] = &irq_ctrl.hw,
+ [CLKID_NIC] = &nic.hw,
+ [CLKID_GIC] = &gic.hw,
+ [CLKID_UART_C] = &uart_c.hw,
+ [CLKID_UART_B] = &uart_b.hw,
+ [CLKID_UART_A] = &uart_a.hw,
+ [CLKID_SYS_PSRAM] = &sys_psram.hw,
+ [CLKID_RSA] = &rsa.hw,
+ [CLKID_CORESIGHT] = &coresight.hw,
+ [CLKID_AM2AXI_VAD] = &am2axi_vad.hw,
+ [CLKID_AUDIO_VAD] = &audio_vad.hw,
+ [CLKID_AXI_DMC] = &axi_dmc.hw,
+ [CLKID_AXI_PSRAM] = &axi_psram.hw,
+ [CLKID_RAMB] = &ramb.hw,
+ [CLKID_RAMA] = &rama.hw,
+ [CLKID_AXI_SPIFC] = &axi_spifc.hw,
+ [CLKID_AXI_NIC] = &axi_nic.hw,
+ [CLKID_AXI_DMA] = &axi_dma.hw,
+ [CLKID_CPU_CTRL] = &cpu_ctrl.hw,
+ [CLKID_ROM] = &rom.hw,
+ [CLKID_PROC_I2C] = &prod_i2c.hw,
+ [CLKID_DSPA_SEL] = &dspa_sel.hw,
+ [CLKID_DSPB_SEL] = &dspb_sel.hw,
+ [CLKID_DSPA_EN] = &dspa_en.hw,
+ [CLKID_DSPA_EN_NIC] = &dspa_en_nic.hw,
+ [CLKID_DSPB_EN] = &dspb_en.hw,
+ [CLKID_DSPB_EN_NIC] = &dspb_en_nic.hw,
+ [CLKID_RTC] = &rtc.hw,
+ [CLKID_CECA_32K] = &ceca_32k_out.hw,
+ [CLKID_CECB_32K] = &cecb_32k_out.hw,
+ [CLKID_24M] = &clk_24m.hw,
+ [CLKID_12M] = &clk_12m.hw,
+ [CLKID_FCLK_DIV2_DIVN] = &fclk_div2_divn.hw,
+ [CLKID_GEN] = &gen.hw,
+ [CLKID_SARADC_SEL] = &saradc_sel.hw,
+ [CLKID_SARADC] = &saradc.hw,
+ [CLKID_PWM_A] = &pwm_a.hw,
+ [CLKID_PWM_B] = &pwm_b.hw,
+ [CLKID_PWM_C] = &pwm_c.hw,
+ [CLKID_PWM_D] = &pwm_d.hw,
+ [CLKID_PWM_E] = &pwm_e.hw,
+ [CLKID_PWM_F] = &pwm_f.hw,
+ [CLKID_SPICC] = &spicc.hw,
+ [CLKID_TS] = &ts.hw,
+ [CLKID_SPIFC] = &spifc.hw,
+ [CLKID_USB_BUS] = &usb_bus.hw,
+ [CLKID_SD_EMMC] = &sd_emmc.hw,
+ [CLKID_PSRAM] = &psram.hw,
+ [CLKID_DMC] = &dmc.hw,
+ [CLKID_SYS_A_SEL] = &sys_a_sel.hw,
+ [CLKID_SYS_A_DIV] = &sys_a_div.hw,
+ [CLKID_SYS_A] = &sys_a.hw,
+ [CLKID_SYS_B_SEL] = &sys_b_sel.hw,
+ [CLKID_SYS_B_DIV] = &sys_b_div.hw,
+ [CLKID_SYS_B] = &sys_b.hw,
+ [CLKID_DSPA_A_SEL] = &dspa_a_sel.hw,
+ [CLKID_DSPA_A_DIV] = &dspa_a_div.hw,
+ [CLKID_DSPA_A] = &dspa_a.hw,
+ [CLKID_DSPA_B_SEL] = &dspa_b_sel.hw,
+ [CLKID_DSPA_B_DIV] = &dspa_b_div.hw,
+ [CLKID_DSPA_B] = &dspa_b.hw,
+ [CLKID_DSPB_A_SEL] = &dspb_a_sel.hw,
+ [CLKID_DSPB_A_DIV] = &dspb_a_div.hw,
+ [CLKID_DSPB_A] = &dspb_a.hw,
+ [CLKID_DSPB_B_SEL] = &dspb_b_sel.hw,
+ [CLKID_DSPB_B_DIV] = &dspb_b_div.hw,
+ [CLKID_DSPB_B] = &dspb_b.hw,
+ [CLKID_RTC_32K_IN] = &rtc_32k_in.hw,
+ [CLKID_RTC_32K_DIV] = &rtc_32k_div.hw,
+ [CLKID_RTC_32K_XTAL] = &rtc_32k_xtal.hw,
+ [CLKID_RTC_32K_SEL] = &rtc_32k_sel.hw,
+ [CLKID_CECB_32K_IN] = &cecb_32k_in.hw,
+ [CLKID_CECB_32K_DIV] = &cecb_32k_div.hw,
+ [CLKID_CECB_32K_SEL_PRE] = &cecb_32k_sel_pre.hw,
+ [CLKID_CECB_32K_SEL] = &cecb_32k_sel.hw,
+ [CLKID_CECA_32K_IN] = &ceca_32k_in.hw,
+ [CLKID_CECA_32K_DIV] = &ceca_32k_div.hw,
+ [CLKID_CECA_32K_SEL_PRE] = &ceca_32k_sel_pre.hw,
+ [CLKID_CECA_32K_SEL] = &ceca_32k_sel.hw,
+ [CLKID_DIV2_PRE] = &fclk_div2_divn_pre.hw,
+ [CLKID_24M_DIV2] = &clk_24m_div2.hw,
+ [CLKID_GEN_SEL] = &gen_sel.hw,
+ [CLKID_GEN_DIV] = &gen_div.hw,
+ [CLKID_SARADC_DIV] = &saradc_div.hw,
+ [CLKID_PWM_A_SEL] = &pwm_a_sel.hw,
+ [CLKID_PWM_A_DIV] = &pwm_a_div.hw,
+ [CLKID_PWM_B_SEL] = &pwm_b_sel.hw,
+ [CLKID_PWM_B_DIV] = &pwm_b_div.hw,
+ [CLKID_PWM_C_SEL] = &pwm_c_sel.hw,
+ [CLKID_PWM_C_DIV] = &pwm_c_div.hw,
+ [CLKID_PWM_D_SEL] = &pwm_d_sel.hw,
+ [CLKID_PWM_D_DIV] = &pwm_d_div.hw,
+ [CLKID_PWM_E_SEL] = &pwm_e_sel.hw,
+ [CLKID_PWM_E_DIV] = &pwm_e_div.hw,
+ [CLKID_PWM_F_SEL] = &pwm_f_sel.hw,
+ [CLKID_PWM_F_DIV] = &pwm_f_div.hw,
+ [CLKID_SPICC_SEL] = &spicc_sel.hw,
+ [CLKID_SPICC_DIV] = &spicc_div.hw,
+ [CLKID_SPICC_SEL2] = &spicc_sel2.hw,
+ [CLKID_TS_DIV] = &ts_div.hw,
+ [CLKID_SPIFC_SEL] = &spifc_sel.hw,
+ [CLKID_SPIFC_DIV] = &spifc_div.hw,
+ [CLKID_SPIFC_SEL2] = &spifc_sel2.hw,
+ [CLKID_USB_BUS_SEL] = &usb_bus_sel.hw,
+ [CLKID_USB_BUS_DIV] = &usb_bus_div.hw,
+ [CLKID_SD_EMMC_SEL] = &sd_emmc_sel.hw,
+ [CLKID_SD_EMMC_DIV] = &sd_emmc_div.hw,
+ [CLKID_SD_EMMC_SEL2] = &sd_emmc_sel2.hw,
+ [CLKID_PSRAM_SEL] = &psram_sel.hw,
+ [CLKID_PSRAM_DIV] = &psram_div.hw,
+ [CLKID_PSRAM_SEL2] = &psram_sel2.hw,
+ [CLKID_DMC_SEL] = &dmc_sel.hw,
+ [CLKID_DMC_DIV] = &dmc_div.hw,
+ [CLKID_DMC_SEL2] = &dmc_sel2.hw,
+ [NR_CLKS] = NULL,
+ },
+ .num = NR_CLKS,
+};
+
+/* Convenience table to populate regmap in .probe */
+static struct clk_regmap *const a1_periphs_regmaps[] = {
+ &xtal_in,
+ &fixpll_in,
+ &usb_phy_in,
+ &usb_ctrl_in,
+ &hifipll_in,
+ &syspll_in,
+ &dds_in,
+ &sys,
+ &clktree,
+ &reset_ctrl,
+ &analog_ctrl,
+ &pwr_ctrl,
+ &pad_ctrl,
+ &sys_ctrl,
+ &temp_sensor,
+ &am2axi_dev,
+ &spicc_b,
+ &spicc_a,
+ &msr,
+ &audio,
+ &jtag_ctrl,
+ &saradc_en,
+ &pwm_ef,
+ &pwm_cd,
+ &pwm_ab,
+ &cec,
+ &i2c_s,
+ &ir_ctrl,
+ &i2c_m_d,
+ &i2c_m_c,
+ &i2c_m_b,
+ &i2c_m_a,
+ &acodec,
+ &otp,
+ &sd_emmc_a,
+ &usb_phy,
+ &usb_ctrl,
+ &sys_dspb,
+ &sys_dspa,
+ &dma,
+ &irq_ctrl,
+ &nic,
+ &gic,
+ &uart_c,
+ &uart_b,
+ &uart_a,
+ &sys_psram,
+ &rsa,
+ &coresight,
+ &am2axi_vad,
+ &audio_vad,
+ &axi_dmc,
+ &axi_psram,
+ &ramb,
+ &rama,
+ &axi_spifc,
+ &axi_nic,
+ &axi_dma,
+ &cpu_ctrl,
+ &rom,
+ &prod_i2c,
+ &dspa_sel,
+ &dspb_sel,
+ &dspa_en,
+ &dspa_en_nic,
+ &dspb_en,
+ &dspb_en_nic,
+ &rtc,
+ &ceca_32k_out,
+ &cecb_32k_out,
+ &clk_24m,
+ &clk_12m,
+ &fclk_div2_divn,
+ &gen,
+ &saradc_sel,
+ &saradc,
+ &pwm_a,
+ &pwm_b,
+ &pwm_c,
+ &pwm_d,
+ &pwm_e,
+ &pwm_f,
+ &spicc,
+ &ts,
+ &spifc,
+ &usb_bus,
+ &sd_emmc,
+ &psram,
+ &dmc,
+ &sys_a_sel,
+ &sys_a_div,
+ &sys_a,
+ &sys_b_sel,
+ &sys_b_div,
+ &sys_b,
+ &dspa_a_sel,
+ &dspa_a_div,
+ &dspa_a,
+ &dspa_b_sel,
+ &dspa_b_div,
+ &dspa_b,
+ &dspb_a_sel,
+ &dspb_a_div,
+ &dspb_a,
+ &dspb_b_sel,
+ &dspb_b_div,
+ &dspb_b,
+ &rtc_32k_in,
+ &rtc_32k_div,
+ &rtc_32k_xtal,
+ &rtc_32k_sel,
+ &cecb_32k_in,
+ &cecb_32k_div,
+ &cecb_32k_sel_pre,
+ &cecb_32k_sel,
+ &ceca_32k_in,
+ &ceca_32k_div,
+ &ceca_32k_sel_pre,
+ &ceca_32k_sel,
+ &fclk_div2_divn_pre,
+ &gen_sel,
+ &gen_div,
+ &saradc_div,
+ &pwm_a_sel,
+ &pwm_a_div,
+ &pwm_b_sel,
+ &pwm_b_div,
+ &pwm_c_sel,
+ &pwm_c_div,
+ &pwm_d_sel,
+ &pwm_d_div,
+ &pwm_e_sel,
+ &pwm_e_div,
+ &pwm_f_sel,
+ &pwm_f_div,
+ &spicc_sel,
+ &spicc_div,
+ &spicc_sel2,
+ &ts_div,
+ &spifc_sel,
+ &spifc_div,
+ &spifc_sel2,
+ &usb_bus_sel,
+ &usb_bus_div,
+ &sd_emmc_sel,
+ &sd_emmc_div,
+ &sd_emmc_sel2,
+ &psram_sel,
+ &psram_div,
+ &psram_sel2,
+ &dmc_sel,
+ &dmc_div,
+ &dmc_sel2,
+};
+
+static struct regmap_config a1_periphs_regmap_cfg = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static int meson_a1_periphs_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ void __iomem *base;
+ struct regmap *map;
+ int clkid, i, err;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return dev_err_probe(dev, PTR_ERR(base),
+ "can't ioremap resource\n");
+
+ map = devm_regmap_init_mmio(dev, base, &a1_periphs_regmap_cfg);
+ if (IS_ERR(map))
+ return dev_err_probe(dev, PTR_ERR(map),
+ "can't init regmap mmio region\n");
+
+ /* Populate regmap for the regmap backed clocks */
+ for (i = 0; i < ARRAY_SIZE(a1_periphs_regmaps); i++)
+ a1_periphs_regmaps[i]->map = map;
+
+ for (clkid = 0; clkid < a1_periphs_clks.num; clkid++) {
+ err = devm_clk_hw_register(dev, a1_periphs_clks.hws[clkid]);
+ if (err)
+ return dev_err_probe(dev, err,
+ "clock[%d] registration failed\n",
+ clkid);
+ }
+
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+ &a1_periphs_clks);
+}
+
+static const struct of_device_id a1_periphs_clkc_match_table[] = {
+ { .compatible = "amlogic,a1-peripherals-clkc", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, a1_periphs_clkc_match_table);
+
+static struct platform_driver a1_periphs_clkc_driver = {
+ .probe = meson_a1_periphs_probe,
+ .driver = {
+ .name = "a1-peripherals-clkc",
+ .of_match_table = a1_periphs_clkc_match_table,
+ },
+};
+
+module_platform_driver(a1_periphs_clkc_driver);
+MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
+MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/meson/a1-peripherals.h b/drivers/clk/meson/a1-peripherals.h
new file mode 100644
index 000000000000..526fc9ba5c9f
--- /dev/null
+++ b/drivers/clk/meson/a1-peripherals.h
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Amlogic A1 Peripherals Clock Controller internals
+ *
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Jian Hu <jian.hu@amlogic.com>
+ *
+ * Copyright (c) 2023, SberDevices. All Rights Reserved.
+ * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
+ */
+
+#ifndef __A1_PERIPHERALS_H
+#define __A1_PERIPHERALS_H
+
+/* peripherals clock controller register offset */
+#define SYS_OSCIN_CTRL 0x0
+#define RTC_BY_OSCIN_CTRL0 0x4
+#define RTC_BY_OSCIN_CTRL1 0x8
+#define RTC_CTRL 0xc
+#define SYS_CLK_CTRL0 0x10
+#define SYS_CLK_EN0 0x1c
+#define SYS_CLK_EN1 0x20
+#define AXI_CLK_EN 0x24
+#define DSPA_CLK_EN 0x28
+#define DSPB_CLK_EN 0x2c
+#define DSPA_CLK_CTRL0 0x30
+#define DSPB_CLK_CTRL0 0x34
+#define CLK12_24_CTRL 0x38
+#define GEN_CLK_CTRL 0x3c
+#define SAR_ADC_CLK_CTRL 0xc0
+#define PWM_CLK_AB_CTRL 0xc4
+#define PWM_CLK_CD_CTRL 0xc8
+#define PWM_CLK_EF_CTRL 0xcc
+#define SPICC_CLK_CTRL 0xd0
+#define TS_CLK_CTRL 0xd4
+#define SPIFC_CLK_CTRL 0xd8
+#define USB_BUSCLK_CTRL 0xdc
+#define SD_EMMC_CLK_CTRL 0xe0
+#define CECA_CLK_CTRL0 0xe4
+#define CECA_CLK_CTRL1 0xe8
+#define CECB_CLK_CTRL0 0xec
+#define CECB_CLK_CTRL1 0xf0
+#define PSRAM_CLK_CTRL 0xf4
+#define DMC_CLK_CTRL 0xf8
+
+/* include the CLKIDs that have been made part of the DT binding */
+#include <dt-bindings/clock/amlogic,a1-peripherals-clkc.h>
+
+/*
+ * CLKID index values for internal clocks
+ *
+ * These indices are entirely contrived and do not map onto the hardware.
+ * It has now been decided to expose everything by default in the DT header:
+ * include/dt-bindings/clock/a1-peripherals-clkc.h.
+ * Only the clocks ids we don't want to expose, such as the internal muxes and
+ * dividers of composite clocks, will remain defined here.
+ */
+#define CLKID_XTAL_IN 0
+#define CLKID_DSPA_SEL 61
+#define CLKID_DSPB_SEL 62
+#define CLKID_SARADC_SEL 74
+#define CLKID_SYS_A_SEL 89
+#define CLKID_SYS_A_DIV 90
+#define CLKID_SYS_A 91
+#define CLKID_SYS_B_SEL 92
+#define CLKID_SYS_B_DIV 93
+#define CLKID_SYS_B 94
+#define CLKID_DSPA_A_DIV 96
+#define CLKID_DSPA_A 97
+#define CLKID_DSPA_B_DIV 99
+#define CLKID_DSPA_B 100
+#define CLKID_DSPB_A_DIV 102
+#define CLKID_DSPB_A 103
+#define CLKID_DSPB_B_DIV 105
+#define CLKID_DSPB_B 106
+#define CLKID_RTC_32K_IN 107
+#define CLKID_RTC_32K_DIV 108
+#define CLKID_RTC_32K_XTAL 109
+#define CLKID_RTC_32K_SEL 110
+#define CLKID_CECB_32K_IN 111
+#define CLKID_CECB_32K_DIV 112
+#define CLKID_CECA_32K_IN 115
+#define CLKID_CECA_32K_DIV 116
+#define CLKID_DIV2_PRE 119
+#define CLKID_24M_DIV2 120
+#define CLKID_GEN_DIV 122
+#define CLKID_SARADC_DIV 123
+#define CLKID_PWM_A_DIV 125
+#define CLKID_PWM_B_DIV 127
+#define CLKID_PWM_C_DIV 129
+#define CLKID_PWM_D_DIV 131
+#define CLKID_PWM_E_DIV 133
+#define CLKID_PWM_F_DIV 135
+#define CLKID_SPICC_SEL 136
+#define CLKID_SPICC_DIV 137
+#define CLKID_SPICC_SEL2 138
+#define CLKID_TS_DIV 139
+#define CLKID_SPIFC_SEL 140
+#define CLKID_SPIFC_DIV 141
+#define CLKID_SPIFC_SEL2 142
+#define CLKID_USB_BUS_SEL 143
+#define CLKID_USB_BUS_DIV 144
+#define CLKID_SD_EMMC_SEL 145
+#define CLKID_SD_EMMC_DIV 146
+#define CLKID_PSRAM_SEL 148
+#define CLKID_PSRAM_DIV 149
+#define CLKID_PSRAM_SEL2 150
+#define CLKID_DMC_SEL 151
+#define CLKID_DMC_DIV 152
+#define CLKID_DMC_SEL2 153
+#define NR_CLKS 154
+
+#endif /* __A1_PERIPHERALS_H */
diff --git a/drivers/clk/meson/a1-pll.c b/drivers/clk/meson/a1-pll.c
new file mode 100644
index 000000000000..bd2f1d1ec6e4
--- /dev/null
+++ b/drivers/clk/meson/a1-pll.c
@@ -0,0 +1,356 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Jian Hu <jian.hu@amlogic.com>
+ *
+ * Copyright (c) 2023, SberDevices. All Rights Reserved.
+ * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "a1-pll.h"
+#include "clk-regmap.h"
+
+static struct clk_regmap fixed_pll_dco = {
+ .data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 0,
+ .width = 8,
+ },
+ .n = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 10,
+ .width = 5,
+ },
+ .frac = {
+ .reg_off = ANACTRL_FIXPLL_CTRL1,
+ .shift = 0,
+ .width = 19,
+ },
+ .l = {
+ .reg_off = ANACTRL_FIXPLL_STS,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 29,
+ .width = 1,
+ },
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fixed_pll_dco",
+ .ops = &meson_clk_pll_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "fixpll_in",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fixed_pll = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_FIXPLL_CTRL0,
+ .bit_idx = 20,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fixed_pll",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll_dco.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static const struct pll_mult_range hifi_pll_mult_range = {
+ .min = 32,
+ .max = 64,
+};
+
+static const struct reg_sequence hifi_init_regs[] = {
+ { .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x01800000 },
+ { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00001100 },
+ { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x100a1100 },
+ { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x00302000 },
+ { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x01f18000 },
+};
+
+static struct clk_regmap hifi_pll = {
+ .data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 0,
+ .width = 8,
+ },
+ .n = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 10,
+ .width = 5,
+ },
+ .frac = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL1,
+ .shift = 0,
+ .width = 19,
+ },
+ .l = {
+ .reg_off = ANACTRL_HIFIPLL_STS,
+ .shift = 31,
+ .width = 1,
+ },
+ .current_en = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 26,
+ .width = 1,
+ },
+ .l_detect = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL2,
+ .shift = 6,
+ .width = 1,
+ },
+ .range = &hifi_pll_mult_range,
+ .init_regs = hifi_init_regs,
+ .init_count = ARRAY_SIZE(hifi_init_regs),
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "hifi_pll",
+ .ops = &meson_clk_pll_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "hifipll_in",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor fclk_div2_div = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_div2 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_FIXPLL_CTRL0,
+ .bit_idx = 21,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_div2_div.hw
+ },
+ .num_parents = 1,
+ /*
+ * This clock is used by DDR clock in BL2 firmware
+ * and is required by the platform to operate correctly.
+ * Until the following condition are met, we need this clock to
+ * be marked as critical:
+ * a) Mark the clock used by a firmware resource, if possible
+ * b) CCF has a clock hand-off mechanism to make the sure the
+ * clock stays on until the proper driver comes along
+ */
+ .flags = CLK_IS_CRITICAL,
+ },
+};
+
+static struct clk_fixed_factor fclk_div3_div = {
+ .mult = 1,
+ .div = 3,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div3_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_div3 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_FIXPLL_CTRL0,
+ .bit_idx = 22,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div3",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_div3_div.hw
+ },
+ .num_parents = 1,
+ /*
+ * This clock is used by APB bus which is set in boot ROM code
+ * and is required by the platform to operate correctly.
+ */
+ .flags = CLK_IS_CRITICAL,
+ },
+};
+
+static struct clk_fixed_factor fclk_div5_div = {
+ .mult = 1,
+ .div = 5,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div5_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_div5 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_FIXPLL_CTRL0,
+ .bit_idx = 23,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div5",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_div5_div.hw
+ },
+ .num_parents = 1,
+ /*
+ * This clock is used by AXI bus which setted in Romcode
+ * and is required by the platform to operate correctly.
+ */
+ .flags = CLK_IS_CRITICAL,
+ },
+};
+
+static struct clk_fixed_factor fclk_div7_div = {
+ .mult = 1,
+ .div = 7,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div7_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_div7 = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = ANACTRL_FIXPLL_CTRL0,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div7",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_div7_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+/* Array of all clocks registered by this provider */
+static struct clk_hw_onecell_data a1_pll_clks = {
+ .hws = {
+ [CLKID_FIXED_PLL_DCO] = &fixed_pll_dco.hw,
+ [CLKID_FIXED_PLL] = &fixed_pll.hw,
+ [CLKID_FCLK_DIV2_DIV] = &fclk_div2_div.hw,
+ [CLKID_FCLK_DIV3_DIV] = &fclk_div3_div.hw,
+ [CLKID_FCLK_DIV5_DIV] = &fclk_div5_div.hw,
+ [CLKID_FCLK_DIV7_DIV] = &fclk_div7_div.hw,
+ [CLKID_FCLK_DIV2] = &fclk_div2.hw,
+ [CLKID_FCLK_DIV3] = &fclk_div3.hw,
+ [CLKID_FCLK_DIV5] = &fclk_div5.hw,
+ [CLKID_FCLK_DIV7] = &fclk_div7.hw,
+ [CLKID_HIFI_PLL] = &hifi_pll.hw,
+ [NR_PLL_CLKS] = NULL,
+ },
+ .num = NR_PLL_CLKS,
+};
+
+static struct clk_regmap *const a1_pll_regmaps[] = {
+ &fixed_pll_dco,
+ &fixed_pll,
+ &fclk_div2,
+ &fclk_div3,
+ &fclk_div5,
+ &fclk_div7,
+ &hifi_pll,
+};
+
+static struct regmap_config a1_pll_regmap_cfg = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static int meson_a1_pll_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ void __iomem *base;
+ struct regmap *map;
+ int clkid, i, err;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return dev_err_probe(dev, PTR_ERR(base),
+ "can't ioremap resource\n");
+
+ map = devm_regmap_init_mmio(dev, base, &a1_pll_regmap_cfg);
+ if (IS_ERR(map))
+ return dev_err_probe(dev, PTR_ERR(map),
+ "can't init regmap mmio region\n");
+
+ /* Populate regmap for the regmap backed clocks */
+ for (i = 0; i < ARRAY_SIZE(a1_pll_regmaps); i++)
+ a1_pll_regmaps[i]->map = map;
+
+ /* Register clocks */
+ for (clkid = 0; clkid < a1_pll_clks.num; clkid++) {
+ err = devm_clk_hw_register(dev, a1_pll_clks.hws[clkid]);
+ if (err)
+ return dev_err_probe(dev, err,
+ "clock[%d] registration failed\n",
+ clkid);
+ }
+
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+ &a1_pll_clks);
+}
+
+static const struct of_device_id a1_pll_clkc_match_table[] = {
+ { .compatible = "amlogic,a1-pll-clkc", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, a1_pll_clkc_match_table);
+
+static struct platform_driver a1_pll_clkc_driver = {
+ .probe = meson_a1_pll_probe,
+ .driver = {
+ .name = "a1-pll-clkc",
+ .of_match_table = a1_pll_clkc_match_table,
+ },
+};
+
+module_platform_driver(a1_pll_clkc_driver);
+MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
+MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/meson/a1-pll.h b/drivers/clk/meson/a1-pll.h
new file mode 100644
index 000000000000..29726651b056
--- /dev/null
+++ b/drivers/clk/meson/a1-pll.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Amlogic A1 PLL Clock Controller internals
+ *
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Jian Hu <jian.hu@amlogic.com>
+ *
+ * Copyright (c) 2023, SberDevices. All Rights Reserved.
+ * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
+ */
+
+#ifndef __A1_PLL_H
+#define __A1_PLL_H
+
+#include "clk-pll.h"
+
+/* PLL register offset */
+#define ANACTRL_FIXPLL_CTRL0 0x0
+#define ANACTRL_FIXPLL_CTRL1 0x4
+#define ANACTRL_FIXPLL_STS 0x14
+#define ANACTRL_HIFIPLL_CTRL0 0xc0
+#define ANACTRL_HIFIPLL_CTRL1 0xc4
+#define ANACTRL_HIFIPLL_CTRL2 0xc8
+#define ANACTRL_HIFIPLL_CTRL3 0xcc
+#define ANACTRL_HIFIPLL_CTRL4 0xd0
+#define ANACTRL_HIFIPLL_STS 0xd4
+
+/* include the CLKIDs that have been made part of the DT binding */
+#include <dt-bindings/clock/amlogic,a1-pll-clkc.h>
+
+/*
+ * CLKID index values for internal clocks
+ *
+ * These indices are entirely contrived and do not map onto the hardware.
+ * It has now been decided to expose everything by default in the DT header:
+ * include/dt-bindings/clock/a1-pll-clkc.h. Only the clocks ids we don't want
+ * to expose, such as the internal muxes and dividers of composite clocks,
+ * will remain defined here.
+ */
+#define CLKID_FIXED_PLL_DCO 0
+#define CLKID_FCLK_DIV2_DIV 2
+#define CLKID_FCLK_DIV3_DIV 3
+#define CLKID_FCLK_DIV5_DIV 4
+#define CLKID_FCLK_DIV7_DIV 5
+#define NR_PLL_CLKS 11
+
+#endif /* __A1_PLL_H */
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index afefeba6e458..8fef90bf962f 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -295,10 +295,14 @@ static int meson_clk_pll_init(struct clk_hw *hw)
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
if (pll->init_count) {
- meson_parm_write(clk->map, &pll->rst, 1);
+ if (MESON_PARM_APPLICABLE(&pll->rst))
+ meson_parm_write(clk->map, &pll->rst, 1);
+
regmap_multi_reg_write(clk->map, pll->init_regs,
pll->init_count);
- meson_parm_write(clk->map, &pll->rst, 0);
+
+ if (MESON_PARM_APPLICABLE(&pll->rst))
+ meson_parm_write(clk->map, &pll->rst, 0);
}
return 0;
@@ -309,8 +313,11 @@ static int meson_clk_pll_is_enabled(struct clk_hw *hw)
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
- if (meson_parm_read(clk->map, &pll->rst) ||
- !meson_parm_read(clk->map, &pll->en) ||
+ if (MESON_PARM_APPLICABLE(&pll->rst) &&
+ meson_parm_read(clk->map, &pll->rst))
+ return 0;
+
+ if (!meson_parm_read(clk->map, &pll->en) ||
!meson_parm_read(clk->map, &pll->l))
return 0;
@@ -341,13 +348,34 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
return 0;
/* Make sure the pll is in reset */
- meson_parm_write(clk->map, &pll->rst, 1);
+ if (MESON_PARM_APPLICABLE(&pll->rst))
+ meson_parm_write(clk->map, &pll->rst, 1);
/* Enable the pll */
meson_parm_write(clk->map, &pll->en, 1);
/* Take the pll out reset */
- meson_parm_write(clk->map, &pll->rst, 0);
+ if (MESON_PARM_APPLICABLE(&pll->rst))
+ meson_parm_write(clk->map, &pll->rst, 0);
+
+ /*
+ * Compared with the previous SoCs, self-adaption current module
+ * is newly added for A1, keep the new power-on sequence to enable the
+ * PLL. The sequence is:
+ * 1. enable the pll, delay for 10us
+ * 2. enable the pll self-adaption current module, delay for 40us
+ * 3. enable the lock detect module
+ */
+ if (MESON_PARM_APPLICABLE(&pll->current_en)) {
+ usleep_range(10, 20);
+ meson_parm_write(clk->map, &pll->current_en, 1);
+ usleep_range(40, 50);
+ }
+
+ if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
+ meson_parm_write(clk->map, &pll->l_detect, 1);
+ meson_parm_write(clk->map, &pll->l_detect, 0);
+ }
if (meson_clk_pll_wait_lock(hw))
return -EIO;
@@ -361,10 +389,15 @@ static void meson_clk_pll_disable(struct clk_hw *hw)
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
/* Put the pll is in reset */
- meson_parm_write(clk->map, &pll->rst, 1);
+ if (MESON_PARM_APPLICABLE(&pll->rst))
+ meson_parm_write(clk->map, &pll->rst, 1);
/* Disable the pll */
meson_parm_write(clk->map, &pll->en, 0);
+
+ /* Disable PLL internal self-adaption current module */
+ if (MESON_PARM_APPLICABLE(&pll->current_en))
+ meson_parm_write(clk->map, &pll->current_en, 0);
}
static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h
index 367efd0f6410..a2228c0fdce5 100644
--- a/drivers/clk/meson/clk-pll.h
+++ b/drivers/clk/meson/clk-pll.h
@@ -36,6 +36,8 @@ struct meson_clk_pll_data {
struct parm frac;
struct parm l;
struct parm rst;
+ struct parm current_en;
+ struct parm l_detect;
const struct reg_sequence *init_regs;
unsigned int init_count;
const struct pll_params_table *table;
diff --git a/drivers/clk/microchip/Kconfig b/drivers/clk/microchip/Kconfig
index e33e51978938..0724ce65898f 100644
--- a/drivers/clk/microchip/Kconfig
+++ b/drivers/clk/microchip/Kconfig
@@ -5,8 +5,8 @@ config COMMON_CLK_PIC32
config MCHP_CLK_MPFS
bool "Clk driver for PolarFire SoC"
- depends on SOC_MICROCHIP_POLARFIRE || COMPILE_TEST
- default SOC_MICROCHIP_POLARFIRE
+ depends on ARCH_MICROCHIP_POLARFIRE || COMPILE_TEST
+ default ARCH_MICROCHIP_POLARFIRE
select AUXILIARY_BUS
help
Supports Clock Configuration for PolarFire SoC
diff --git a/drivers/clk/microchip/clk-pic32mzda.c b/drivers/clk/microchip/clk-pic32mzda.c
index b72c76f9ecd1..eabfc4931fe9 100644
--- a/drivers/clk/microchip/clk-pic32mzda.c
+++ b/drivers/clk/microchip/clk-pic32mzda.c
@@ -184,7 +184,7 @@ static int pic32mzda_clk_probe(struct platform_device *pdev)
clks[UPLLCLK] = clk_register_fixed_rate(&pdev->dev, "usbphy_clk", NULL,
0, 24000000);
/* fixed rate (optional) clock */
- if (of_find_property(np, "microchip,pic32mzda-sosc", NULL)) {
+ if (of_property_read_bool(np, "microchip,pic32mzda-sosc")) {
pr_info("pic32-clk: dt requests SOSC.\n");
clks[SOSCCLK] = pic32_sosc_clk_register(&sosc_clk, core);
}
diff --git a/drivers/clk/mvebu/ap-cpu-clk.c b/drivers/clk/mvebu/ap-cpu-clk.c
index 71bdd7c3ff03..d8a7a4c90d54 100644
--- a/drivers/clk/mvebu/ap-cpu-clk.c
+++ b/drivers/clk/mvebu/ap-cpu-clk.c
@@ -253,12 +253,12 @@ static int ap_cpu_clock_probe(struct platform_device *pdev)
*/
nclusters = 1;
for_each_of_cpu_node(dn) {
- int cpu, err;
+ u64 cpu;
- err = of_property_read_u32(dn, "reg", &cpu);
- if (WARN_ON(err)) {
+ cpu = of_get_cpu_hwid(dn, 0);
+ if (WARN_ON(cpu == OF_BAD_ADDR)) {
of_node_put(dn);
- return err;
+ return -EINVAL;
}
/* If cpu2 or cpu3 is enabled */
@@ -288,12 +288,12 @@ static int ap_cpu_clock_probe(struct platform_device *pdev)
struct clk_init_data init;
const char *parent_name;
struct clk *parent;
- int cpu, err;
+ u64 cpu;
- err = of_property_read_u32(dn, "reg", &cpu);
- if (WARN_ON(err)) {
+ cpu = of_get_cpu_hwid(dn, 0);
+ if (WARN_ON(cpu == OF_BAD_ADDR)) {
of_node_put(dn);
- return err;
+ return -EINVAL;
}
cluster_index = cpu & APN806_CLUSTER_NUM_MASK;
diff --git a/drivers/clk/mvebu/armada_ap_cp_helper.c b/drivers/clk/mvebu/armada_ap_cp_helper.c
index 6a930f697ee5..e7005de66327 100644
--- a/drivers/clk/mvebu/armada_ap_cp_helper.c
+++ b/drivers/clk/mvebu/armada_ap_cp_helper.c
@@ -16,15 +16,13 @@
char *ap_cp_unique_name(struct device *dev, struct device_node *np,
const char *name)
{
- const __be32 *reg;
- u64 addr;
+ struct resource res;
/* Do not create a name if there is no clock */
if (!name)
return NULL;
- reg = of_get_property(np, "reg", NULL);
- addr = of_translate_address(np, reg);
+ of_address_to_resource(np, 0, &res);
return devm_kasprintf(dev, GFP_KERNEL, "%llx-%s",
- (unsigned long long)addr, name);
+ (unsigned long long)res.start, name);
}
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
index c2af3395cf13..db2b38c21304 100644
--- a/drivers/clk/mvebu/clk-cpu.c
+++ b/drivers/clk/mvebu/clk-cpu.c
@@ -168,8 +168,8 @@ static void __init of_cpu_clk_setup(struct device_node *node)
struct cpu_clk *cpuclk;
void __iomem *clock_complex_base = of_iomap(node, 0);
void __iomem *pmu_dfs_base = of_iomap(node, 1);
- int ncpus = 0;
- struct device_node *dn;
+ int ncpus = num_possible_cpus();
+ int cpu;
if (clock_complex_base == NULL) {
pr_err("%s: clock-complex base register not set\n",
@@ -181,9 +181,6 @@ static void __init of_cpu_clk_setup(struct device_node *node)
pr_warn("%s: pmu-dfs base register not set, dynamic frequency scaling not available\n",
__func__);
- for_each_of_cpu_node(dn)
- ncpus++;
-
cpuclk = kcalloc(ncpus, sizeof(*cpuclk), GFP_KERNEL);
if (WARN_ON(!cpuclk))
goto cpuclk_out;
@@ -192,19 +189,14 @@ static void __init of_cpu_clk_setup(struct device_node *node)
if (WARN_ON(!clks))
goto clks_out;
- for_each_of_cpu_node(dn) {
+ for_each_possible_cpu(cpu) {
struct clk_init_data init;
struct clk *clk;
char *clk_name = kzalloc(5, GFP_KERNEL);
- int cpu, err;
if (WARN_ON(!clk_name))
goto bail_out;
- err = of_property_read_u32(dn, "reg", &cpu);
- if (WARN_ON(err))
- goto bail_out;
-
sprintf(clk_name, "cpu%d", cpu);
cpuclk[cpu].parent_name = of_clk_get_parent_name(node, 0);
diff --git a/drivers/clk/nuvoton/Kconfig b/drivers/clk/nuvoton/Kconfig
new file mode 100644
index 000000000000..fe4b7f62f467
--- /dev/null
+++ b/drivers/clk/nuvoton/Kconfig
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0
+# common clock support for Nuvoton SoC family.
+
+config COMMON_CLK_NUVOTON
+ bool "Nuvoton clock controller common support"
+ depends on ARCH_MA35 || COMPILE_TEST
+ default y
+ help
+ Say y here to enable common clock controller for Nuvoton platforms.
+
+if COMMON_CLK_NUVOTON
+
+config CLK_MA35D1
+ bool "Nuvoton MA35D1 clock controller support"
+ default y
+ help
+ Build the clock controller driver for MA35D1 SoC.
+
+endif
diff --git a/drivers/clk/nuvoton/Makefile b/drivers/clk/nuvoton/Makefile
new file mode 100644
index 000000000000..c3c59dd9f2aa
--- /dev/null
+++ b/drivers/clk/nuvoton/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_CLK_MA35D1) += clk-ma35d1.o
+obj-$(CONFIG_CLK_MA35D1) += clk-ma35d1-divider.o
+obj-$(CONFIG_CLK_MA35D1) += clk-ma35d1-pll.o
diff --git a/drivers/clk/nuvoton/clk-ma35d1-divider.c b/drivers/clk/nuvoton/clk-ma35d1-divider.c
new file mode 100644
index 000000000000..bb8c23d2b895
--- /dev/null
+++ b/drivers/clk/nuvoton/clk-ma35d1-divider.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023 Nuvoton Technology Corp.
+ * Author: Chi-Fang Li <cfli0@nuvoton.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+
+#include "clk-ma35d1.h"
+
+struct ma35d1_adc_clk_div {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u8 shift;
+ u8 width;
+ u32 mask;
+ const struct clk_div_table *table;
+ /* protects concurrent access to clock divider registers */
+ spinlock_t *lock;
+};
+
+static inline struct ma35d1_adc_clk_div *to_ma35d1_adc_clk_div(struct clk_hw *_hw)
+{
+ return container_of(_hw, struct ma35d1_adc_clk_div, hw);
+}
+
+static unsigned long ma35d1_clkdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ unsigned int val;
+ struct ma35d1_adc_clk_div *dclk = to_ma35d1_adc_clk_div(hw);
+
+ val = readl_relaxed(dclk->reg) >> dclk->shift;
+ val &= clk_div_mask(dclk->width);
+ val += 1;
+ return divider_recalc_rate(hw, parent_rate, val, dclk->table,
+ CLK_DIVIDER_ROUND_CLOSEST, dclk->width);
+}
+
+static long ma35d1_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate)
+{
+ struct ma35d1_adc_clk_div *dclk = to_ma35d1_adc_clk_div(hw);
+
+ return divider_round_rate(hw, rate, prate, dclk->table,
+ dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static int ma35d1_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
+{
+ int value;
+ unsigned long flags = 0;
+ u32 data;
+ struct ma35d1_adc_clk_div *dclk = to_ma35d1_adc_clk_div(hw);
+
+ value = divider_get_val(rate, parent_rate, dclk->table,
+ dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
+
+ spin_lock_irqsave(dclk->lock, flags);
+
+ data = readl_relaxed(dclk->reg);
+ data &= ~(clk_div_mask(dclk->width) << dclk->shift);
+ data |= (value - 1) << dclk->shift;
+ data |= dclk->mask;
+ writel_relaxed(data, dclk->reg);
+
+ spin_unlock_irqrestore(dclk->lock, flags);
+ return 0;
+}
+
+static const struct clk_ops ma35d1_adc_clkdiv_ops = {
+ .recalc_rate = ma35d1_clkdiv_recalc_rate,
+ .round_rate = ma35d1_clkdiv_round_rate,
+ .set_rate = ma35d1_clkdiv_set_rate,
+};
+
+struct clk_hw *ma35d1_reg_adc_clkdiv(struct device *dev, const char *name,
+ struct clk_hw *parent_hw, spinlock_t *lock,
+ unsigned long flags, void __iomem *reg,
+ u8 shift, u8 width, u32 mask_bit)
+{
+ struct ma35d1_adc_clk_div *div;
+ struct clk_init_data init;
+ struct clk_div_table *table;
+ struct clk_parent_data pdata = { .index = 0 };
+ u32 max_div, min_div;
+ struct clk_hw *hw;
+ int ret;
+ int i;
+
+ div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ max_div = clk_div_mask(width) + 1;
+ min_div = 1;
+
+ table = devm_kcalloc(dev, max_div + 1, sizeof(*table), GFP_KERNEL);
+ if (!table)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < max_div; i++) {
+ table[i].val = min_div + i;
+ table[i].div = 2 * table[i].val;
+ }
+ table[max_div].val = 0;
+ table[max_div].div = 0;
+
+ memset(&init, 0, sizeof(init));
+ init.name = name;
+ init.ops = &ma35d1_adc_clkdiv_ops;
+ init.flags |= flags;
+ pdata.hw = parent_hw;
+ init.parent_data = &pdata;
+ init.num_parents = 1;
+
+ div->reg = reg;
+ div->shift = shift;
+ div->width = width;
+ div->mask = mask_bit ? BIT(mask_bit) : 0;
+ div->lock = lock;
+ div->hw.init = &init;
+ div->table = table;
+
+ hw = &div->hw;
+ ret = devm_clk_hw_register(dev, hw);
+ if (ret)
+ return ERR_PTR(ret);
+ return hw;
+}
+EXPORT_SYMBOL_GPL(ma35d1_reg_adc_clkdiv);
diff --git a/drivers/clk/nuvoton/clk-ma35d1-pll.c b/drivers/clk/nuvoton/clk-ma35d1-pll.c
new file mode 100644
index 000000000000..ff3fb8b87c24
--- /dev/null
+++ b/drivers/clk/nuvoton/clk-ma35d1-pll.c
@@ -0,0 +1,360 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023 Nuvoton Technology Corp.
+ * Author: Chi-Fang Li <cfli0@nuvoton.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/container_of.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/slab.h>
+#include <linux/units.h>
+#include <dt-bindings/clock/nuvoton,ma35d1-clk.h>
+
+#include "clk-ma35d1.h"
+
+/* PLL frequency limits */
+#define PLL_FREF_MAX_FREQ (200 * HZ_PER_MHZ)
+#define PLL_FREF_MIN_FREQ (1 * HZ_PER_MHZ)
+#define PLL_FREF_M_MAX_FREQ (40 * HZ_PER_MHZ)
+#define PLL_FREF_M_MIN_FREQ (10 * HZ_PER_MHZ)
+#define PLL_FCLK_MAX_FREQ (2400 * HZ_PER_MHZ)
+#define PLL_FCLK_MIN_FREQ (600 * HZ_PER_MHZ)
+#define PLL_FCLKO_MAX_FREQ (2400 * HZ_PER_MHZ)
+#define PLL_FCLKO_MIN_FREQ (85700 * HZ_PER_KHZ)
+#define PLL_SS_RATE 0x77
+#define PLL_SLOPE 0x58CFA
+
+#define REG_PLL_CTL0_OFFSET 0x0
+#define REG_PLL_CTL1_OFFSET 0x4
+#define REG_PLL_CTL2_OFFSET 0x8
+
+/* bit fields for REG_CLK_PLL0CTL0, which is SMIC PLL design */
+#define SPLL0_CTL0_FBDIV GENMASK(7, 0)
+#define SPLL0_CTL0_INDIV GENMASK(11, 8)
+#define SPLL0_CTL0_OUTDIV GENMASK(13, 12)
+#define SPLL0_CTL0_PD BIT(16)
+#define SPLL0_CTL0_BP BIT(17)
+
+/* bit fields for REG_CLK_PLLxCTL0 ~ REG_CLK_PLLxCTL2, where x = 2 ~ 5 */
+#define PLL_CTL0_FBDIV GENMASK(10, 0)
+#define PLL_CTL0_INDIV GENMASK(17, 12)
+#define PLL_CTL0_MODE GENMASK(19, 18)
+#define PLL_CTL0_SSRATE GENMASK(30, 20)
+#define PLL_CTL1_PD BIT(0)
+#define PLL_CTL1_BP BIT(1)
+#define PLL_CTL1_OUTDIV GENMASK(6, 4)
+#define PLL_CTL1_FRAC GENMASK(31, 24)
+#define PLL_CTL2_SLOPE GENMASK(23, 0)
+
+#define INDIV_MIN 1
+#define INDIV_MAX 63
+#define FBDIV_MIN 16
+#define FBDIV_MAX 2047
+#define FBDIV_FRAC_MIN 1600
+#define FBDIV_FRAC_MAX 204700
+#define OUTDIV_MIN 1
+#define OUTDIV_MAX 7
+
+#define PLL_MODE_INT 0
+#define PLL_MODE_FRAC 1
+#define PLL_MODE_SS 2
+
+struct ma35d1_clk_pll {
+ struct clk_hw hw;
+ u32 id;
+ u8 mode;
+ void __iomem *ctl0_base;
+ void __iomem *ctl1_base;
+ void __iomem *ctl2_base;
+};
+
+static inline struct ma35d1_clk_pll *to_ma35d1_clk_pll(struct clk_hw *_hw)
+{
+ return container_of(_hw, struct ma35d1_clk_pll, hw);
+}
+
+static unsigned long ma35d1_calc_smic_pll_freq(u32 pll0_ctl0,
+ unsigned long parent_rate)
+{
+ u32 m, n, p, outdiv;
+ u64 pll_freq;
+
+ if (pll0_ctl0 & SPLL0_CTL0_BP)
+ return parent_rate;
+
+ n = FIELD_GET(SPLL0_CTL0_FBDIV, pll0_ctl0);
+ m = FIELD_GET(SPLL0_CTL0_INDIV, pll0_ctl0);
+ p = FIELD_GET(SPLL0_CTL0_OUTDIV, pll0_ctl0);
+ outdiv = 1 << p;
+ pll_freq = (u64)parent_rate * n;
+ div_u64(pll_freq, m * outdiv);
+ return pll_freq;
+}
+
+static unsigned long ma35d1_calc_pll_freq(u8 mode, u32 *reg_ctl, unsigned long parent_rate)
+{
+ unsigned long pll_freq, x;
+ u32 m, n, p;
+
+ if (reg_ctl[1] & PLL_CTL1_BP)
+ return parent_rate;
+
+ n = FIELD_GET(PLL_CTL0_FBDIV, reg_ctl[0]);
+ m = FIELD_GET(PLL_CTL0_INDIV, reg_ctl[0]);
+ p = FIELD_GET(PLL_CTL1_OUTDIV, reg_ctl[1]);
+
+ if (mode == PLL_MODE_INT) {
+ pll_freq = (u64)parent_rate * n;
+ div_u64(pll_freq, m * p);
+ } else {
+ x = FIELD_GET(PLL_CTL1_FRAC, reg_ctl[1]);
+ /* 2 decimal places floating to integer (ex. 1.23 to 123) */
+ n = n * 100 + ((x * 100) / FIELD_MAX(PLL_CTL1_FRAC));
+ pll_freq = div_u64(parent_rate * n, 100 * m * p);
+ }
+ return pll_freq;
+}
+
+static int ma35d1_pll_find_closest(struct ma35d1_clk_pll *pll, unsigned long rate,
+ unsigned long parent_rate, u32 *reg_ctl,
+ unsigned long *freq)
+{
+ unsigned long min_diff = ULONG_MAX;
+ int fbdiv_min, fbdiv_max;
+ int p, m, n;
+
+ *freq = 0;
+ if (rate < PLL_FCLKO_MIN_FREQ || rate > PLL_FCLKO_MAX_FREQ)
+ return -EINVAL;
+
+ if (pll->mode == PLL_MODE_INT) {
+ fbdiv_min = FBDIV_MIN;
+ fbdiv_max = FBDIV_MAX;
+ } else {
+ fbdiv_min = FBDIV_FRAC_MIN;
+ fbdiv_max = FBDIV_FRAC_MAX;
+ }
+
+ for (m = INDIV_MIN; m <= INDIV_MAX; m++) {
+ for (n = fbdiv_min; n <= fbdiv_max; n++) {
+ for (p = OUTDIV_MIN; p <= OUTDIV_MAX; p++) {
+ unsigned long tmp, fout, fclk, diff;
+
+ tmp = div_u64(parent_rate, m);
+ if (tmp < PLL_FREF_M_MIN_FREQ ||
+ tmp > PLL_FREF_M_MAX_FREQ)
+ continue; /* constrain */
+
+ fclk = div_u64(parent_rate * n, m);
+ /* for 2 decimal places */
+ if (pll->mode != PLL_MODE_INT)
+ fclk = div_u64(fclk, 100);
+
+ if (fclk < PLL_FCLK_MIN_FREQ ||
+ fclk > PLL_FCLK_MAX_FREQ)
+ continue; /* constrain */
+
+ fout = div_u64(fclk, p);
+ if (fout < PLL_FCLKO_MIN_FREQ ||
+ fout > PLL_FCLKO_MAX_FREQ)
+ continue; /* constrain */
+
+ diff = abs(rate - fout);
+ if (diff < min_diff) {
+ reg_ctl[0] = FIELD_PREP(PLL_CTL0_INDIV, m) |
+ FIELD_PREP(PLL_CTL0_FBDIV, n);
+ reg_ctl[1] = FIELD_PREP(PLL_CTL1_OUTDIV, p);
+ *freq = fout;
+ min_diff = diff;
+ if (min_diff == 0)
+ break;
+ }
+ }
+ }
+ }
+ if (*freq == 0)
+ return -EINVAL; /* cannot find even one valid setting */
+ return 0;
+}
+
+static int ma35d1_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw);
+ u32 reg_ctl[3] = { 0 };
+ unsigned long pll_freq;
+ int ret;
+
+ if (parent_rate < PLL_FREF_MIN_FREQ || parent_rate > PLL_FREF_MAX_FREQ)
+ return -EINVAL;
+
+ ret = ma35d1_pll_find_closest(pll, rate, parent_rate, reg_ctl, &pll_freq);
+ if (ret != 0)
+ return ret;
+
+ switch (pll->mode) {
+ case PLL_MODE_INT:
+ reg_ctl[0] |= FIELD_PREP(PLL_CTL0_MODE, PLL_MODE_INT);
+ break;
+ case PLL_MODE_FRAC:
+ reg_ctl[0] |= FIELD_PREP(PLL_CTL0_MODE, PLL_MODE_FRAC);
+ break;
+ case PLL_MODE_SS:
+ reg_ctl[0] |= FIELD_PREP(PLL_CTL0_MODE, PLL_MODE_SS) |
+ FIELD_PREP(PLL_CTL0_SSRATE, PLL_SS_RATE);
+ reg_ctl[2] = FIELD_PREP(PLL_CTL2_SLOPE, PLL_SLOPE);
+ break;
+ }
+ reg_ctl[1] |= PLL_CTL1_PD;
+
+ writel_relaxed(reg_ctl[0], pll->ctl0_base);
+ writel_relaxed(reg_ctl[1], pll->ctl1_base);
+ writel_relaxed(reg_ctl[2], pll->ctl2_base);
+ return 0;
+}
+
+static unsigned long ma35d1_clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw);
+ u32 reg_ctl[3];
+ unsigned long pll_freq;
+
+ if (parent_rate < PLL_FREF_MIN_FREQ || parent_rate > PLL_FREF_MAX_FREQ)
+ return 0;
+
+ switch (pll->id) {
+ case CAPLL:
+ reg_ctl[0] = readl_relaxed(pll->ctl0_base);
+ pll_freq = ma35d1_calc_smic_pll_freq(reg_ctl[0], parent_rate);
+ return pll_freq;
+ case DDRPLL:
+ case APLL:
+ case EPLL:
+ case VPLL:
+ reg_ctl[0] = readl_relaxed(pll->ctl0_base);
+ reg_ctl[1] = readl_relaxed(pll->ctl1_base);
+ pll_freq = ma35d1_calc_pll_freq(pll->mode, reg_ctl, parent_rate);
+ return pll_freq;
+ }
+ return 0;
+}
+
+static long ma35d1_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw);
+ u32 reg_ctl[3] = { 0 };
+ unsigned long pll_freq;
+ long ret;
+
+ if (*parent_rate < PLL_FREF_MIN_FREQ || *parent_rate > PLL_FREF_MAX_FREQ)
+ return -EINVAL;
+
+ ret = ma35d1_pll_find_closest(pll, rate, *parent_rate, reg_ctl, &pll_freq);
+ if (ret < 0)
+ return ret;
+
+ switch (pll->id) {
+ case CAPLL:
+ reg_ctl[0] = readl_relaxed(pll->ctl0_base);
+ pll_freq = ma35d1_calc_smic_pll_freq(reg_ctl[0], *parent_rate);
+ return pll_freq;
+ case DDRPLL:
+ case APLL:
+ case EPLL:
+ case VPLL:
+ reg_ctl[0] = readl_relaxed(pll->ctl0_base);
+ reg_ctl[1] = readl_relaxed(pll->ctl1_base);
+ pll_freq = ma35d1_calc_pll_freq(pll->mode, reg_ctl, *parent_rate);
+ return pll_freq;
+ }
+ return 0;
+}
+
+static int ma35d1_clk_pll_is_prepared(struct clk_hw *hw)
+{
+ struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw);
+ u32 val = readl_relaxed(pll->ctl1_base);
+
+ return !(val & PLL_CTL1_PD);
+}
+
+static int ma35d1_clk_pll_prepare(struct clk_hw *hw)
+{
+ struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw);
+ u32 val;
+
+ val = readl_relaxed(pll->ctl1_base);
+ val &= ~PLL_CTL1_PD;
+ writel_relaxed(val, pll->ctl1_base);
+ return 0;
+}
+
+static void ma35d1_clk_pll_unprepare(struct clk_hw *hw)
+{
+ struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw);
+ u32 val;
+
+ val = readl_relaxed(pll->ctl1_base);
+ val |= PLL_CTL1_PD;
+ writel_relaxed(val, pll->ctl1_base);
+}
+
+static const struct clk_ops ma35d1_clk_pll_ops = {
+ .is_prepared = ma35d1_clk_pll_is_prepared,
+ .prepare = ma35d1_clk_pll_prepare,
+ .unprepare = ma35d1_clk_pll_unprepare,
+ .set_rate = ma35d1_clk_pll_set_rate,
+ .recalc_rate = ma35d1_clk_pll_recalc_rate,
+ .round_rate = ma35d1_clk_pll_round_rate,
+};
+
+static const struct clk_ops ma35d1_clk_fixed_pll_ops = {
+ .recalc_rate = ma35d1_clk_pll_recalc_rate,
+ .round_rate = ma35d1_clk_pll_round_rate,
+};
+
+struct clk_hw *ma35d1_reg_clk_pll(struct device *dev, u32 id, u8 u8mode, const char *name,
+ struct clk_hw *parent_hw, void __iomem *base)
+{
+ struct clk_parent_data pdata = { .index = 0 };
+ struct clk_init_data init = {};
+ struct ma35d1_clk_pll *pll;
+ struct clk_hw *hw;
+ int ret;
+
+ pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ pll->id = id;
+ pll->mode = u8mode;
+ pll->ctl0_base = base + REG_PLL_CTL0_OFFSET;
+ pll->ctl1_base = base + REG_PLL_CTL1_OFFSET;
+ pll->ctl2_base = base + REG_PLL_CTL2_OFFSET;
+
+ init.name = name;
+ init.flags = 0;
+ pdata.hw = parent_hw;
+ init.parent_data = &pdata;
+ init.num_parents = 1;
+
+ if (id == CAPLL || id == DDRPLL)
+ init.ops = &ma35d1_clk_fixed_pll_ops;
+ else
+ init.ops = &ma35d1_clk_pll_ops;
+
+ pll->hw.init = &init;
+ hw = &pll->hw;
+
+ ret = devm_clk_hw_register(dev, hw);
+ if (ret)
+ return ERR_PTR(ret);
+ return hw;
+}
+EXPORT_SYMBOL_GPL(ma35d1_reg_clk_pll);
diff --git a/drivers/clk/nuvoton/clk-ma35d1.c b/drivers/clk/nuvoton/clk-ma35d1.c
new file mode 100644
index 000000000000..f1fe7edd21b5
--- /dev/null
+++ b/drivers/clk/nuvoton/clk-ma35d1.c
@@ -0,0 +1,1059 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023 Nuvoton Technology Corp.
+ * Author: Chi-Fang Li <cfli0@nuvoton.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <dt-bindings/clock/nuvoton,ma35d1-clk.h>
+
+#include "clk-ma35d1.h"
+
+static DEFINE_SPINLOCK(ma35d1_lock);
+
+#define PLL_MAX_NUM 5
+
+/* Clock Control Registers Offset */
+#define REG_CLK_PWRCTL 0x00
+#define REG_CLK_SYSCLK0 0x04
+#define REG_CLK_SYSCLK1 0x08
+#define REG_CLK_APBCLK0 0x0c
+#define REG_CLK_APBCLK1 0x10
+#define REG_CLK_APBCLK2 0x14
+#define REG_CLK_CLKSEL0 0x18
+#define REG_CLK_CLKSEL1 0x1c
+#define REG_CLK_CLKSEL2 0x20
+#define REG_CLK_CLKSEL3 0x24
+#define REG_CLK_CLKSEL4 0x28
+#define REG_CLK_CLKDIV0 0x2c
+#define REG_CLK_CLKDIV1 0x30
+#define REG_CLK_CLKDIV2 0x34
+#define REG_CLK_CLKDIV3 0x38
+#define REG_CLK_CLKDIV4 0x3c
+#define REG_CLK_CLKOCTL 0x40
+#define REG_CLK_STATUS 0x50
+#define REG_CLK_PLL0CTL0 0x60
+#define REG_CLK_PLL2CTL0 0x80
+#define REG_CLK_PLL2CTL1 0x84
+#define REG_CLK_PLL2CTL2 0x88
+#define REG_CLK_PLL3CTL0 0x90
+#define REG_CLK_PLL3CTL1 0x94
+#define REG_CLK_PLL3CTL2 0x98
+#define REG_CLK_PLL4CTL0 0xa0
+#define REG_CLK_PLL4CTL1 0xa4
+#define REG_CLK_PLL4CTL2 0xa8
+#define REG_CLK_PLL5CTL0 0xb0
+#define REG_CLK_PLL5CTL1 0xb4
+#define REG_CLK_PLL5CTL2 0xb8
+#define REG_CLK_CLKDCTL 0xc0
+#define REG_CLK_CLKDSTS 0xc4
+#define REG_CLK_CDUPB 0xc8
+#define REG_CLK_CDLOWB 0xcc
+#define REG_CLK_CKFLTRCTL 0xd0
+#define REG_CLK_TESTCLK 0xf0
+#define REG_CLK_PLLCTL 0x40
+
+#define PLL_MODE_INT 0
+#define PLL_MODE_FRAC 1
+#define PLL_MODE_SS 2
+
+static const struct clk_parent_data ca35clk_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "capll", },
+ { .fw_name = "ddrpll", },
+};
+
+static const struct clk_parent_data sysclk0_sel_clks[] = {
+ { .fw_name = "epll_div2", },
+ { .fw_name = "syspll", },
+};
+
+static const struct clk_parent_data sysclk1_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "syspll", },
+};
+
+static const struct clk_parent_data axiclk_sel_clks[] = {
+ { .fw_name = "capll_div2", },
+ { .fw_name = "capll_div4", },
+};
+
+static const struct clk_parent_data ccap_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "vpll", },
+ { .fw_name = "apll", },
+ { .fw_name = "syspll", },
+};
+
+static const struct clk_parent_data sdh_sel_clks[] = {
+ { .fw_name = "syspll", },
+ { .fw_name = "apll", },
+};
+
+static const struct clk_parent_data dcu_sel_clks[] = {
+ { .fw_name = "epll_div2", },
+ { .fw_name = "syspll", },
+};
+
+static const struct clk_parent_data gfx_sel_clks[] = {
+ { .fw_name = "epll", },
+ { .fw_name = "syspll", },
+};
+
+static const struct clk_parent_data dbg_sel_clks[] = {
+ { .fw_name = "hirc", },
+ { .fw_name = "syspll", },
+};
+
+static const struct clk_parent_data timer0_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk0", },
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "lirc", },
+ { .index = -1, },
+ { .fw_name = "hirc", },
+};
+
+static const struct clk_parent_data timer1_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk0", },
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "lirc", },
+ { .index = -1, },
+ { .fw_name = "hirc", },
+};
+
+static const struct clk_parent_data timer2_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk1", },
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "lirc", },
+ { .index = -1, },
+ { .fw_name = "hirc", },
+};
+
+static const struct clk_parent_data timer3_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk1", },
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "lirc", },
+ { .index = -1, },
+ { .fw_name = "hirc", },
+};
+
+static const struct clk_parent_data timer4_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk2", },
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "lirc", },
+ { .index = -1, },
+ { .fw_name = "hirc", },
+};
+
+static const struct clk_parent_data timer5_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk2", },
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "lirc", },
+ { .index = -1, },
+ { .fw_name = "hirc", },
+};
+
+static const struct clk_parent_data timer6_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk0", },
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "lirc", },
+ { .index = -1, },
+ { .fw_name = "hirc", },
+};
+
+static const struct clk_parent_data timer7_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk0", },
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "lirc", },
+ { .index = -1, },
+ { .fw_name = "hirc", },
+};
+
+static const struct clk_parent_data timer8_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk1", },
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "lirc", },
+ { .index = -1, },
+ { .fw_name = "hirc", },
+};
+
+static const struct clk_parent_data timer9_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk1", },
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "lirc", },
+ { .index = -1, },
+ { .fw_name = "hirc", },
+};
+
+static const struct clk_parent_data timer10_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk2", },
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "lirc", },
+ { .index = -1, },
+ { .fw_name = "hirc", },
+};
+
+static const struct clk_parent_data timer11_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk2", },
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "lirc", },
+ { .index = -1, },
+ { .fw_name = "hirc", },
+};
+
+static const struct clk_parent_data uart_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "sysclk1_div2", },
+};
+
+static const struct clk_parent_data wdt0_sel_clks[] = {
+ { .index = -1, },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk3_div4096", },
+ { .fw_name = "lirc", },
+};
+
+static const struct clk_parent_data wdt1_sel_clks[] = {
+ { .index = -1, },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk3_div4096", },
+ { .fw_name = "lirc", },
+};
+
+static const struct clk_parent_data wdt2_sel_clks[] = {
+ { .index = -1, },
+ { .fw_name = "lxt", },
+ { .fw_name = "pclk4_div4096", },
+ { .fw_name = "lirc", },
+};
+
+static const struct clk_parent_data wwdt0_sel_clks[] = {
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "pclk3_div4096", },
+ { .fw_name = "lirc", },
+};
+
+static const struct clk_parent_data wwdt1_sel_clks[] = {
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "pclk3_div4096", },
+ { .fw_name = "lirc", },
+};
+
+static const struct clk_parent_data wwdt2_sel_clks[] = {
+ { .index = -1, },
+ { .index = -1, },
+ { .fw_name = "pclk4_div4096", },
+ { .fw_name = "lirc", },
+};
+
+static const struct clk_parent_data spi0_sel_clks[] = {
+ { .fw_name = "pclk1", },
+ { .fw_name = "apll", },
+};
+
+static const struct clk_parent_data spi1_sel_clks[] = {
+ { .fw_name = "pclk2", },
+ { .fw_name = "apll", },
+};
+
+static const struct clk_parent_data spi2_sel_clks[] = {
+ { .fw_name = "pclk1", },
+ { .fw_name = "apll", },
+};
+
+static const struct clk_parent_data spi3_sel_clks[] = {
+ { .fw_name = "pclk2", },
+ { .fw_name = "apll", },
+};
+
+static const struct clk_parent_data qspi0_sel_clks[] = {
+ { .fw_name = "pclk0", },
+ { .fw_name = "apll", },
+};
+
+static const struct clk_parent_data qspi1_sel_clks[] = {
+ { .fw_name = "pclk0", },
+ { .fw_name = "apll", },
+};
+
+static const struct clk_parent_data i2s0_sel_clks[] = {
+ { .fw_name = "apll", },
+ { .fw_name = "sysclk1_div2", },
+};
+
+static const struct clk_parent_data i2s1_sel_clks[] = {
+ { .fw_name = "apll", },
+ { .fw_name = "sysclk1_div2", },
+};
+
+static const struct clk_parent_data can_sel_clks[] = {
+ { .fw_name = "apll", },
+ { .fw_name = "vpll", },
+};
+
+static const struct clk_parent_data cko_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+ { .fw_name = "hirc", },
+ { .fw_name = "lirc", },
+ { .fw_name = "capll_div4", },
+ { .fw_name = "syspll", },
+ { .fw_name = "ddrpll", },
+ { .fw_name = "epll_div2", },
+ { .fw_name = "apll", },
+ { .fw_name = "vpll", },
+};
+
+static const struct clk_parent_data smc_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "pclk4", },
+};
+
+static const struct clk_parent_data kpi_sel_clks[] = {
+ { .fw_name = "hxt", },
+ { .fw_name = "lxt", },
+};
+
+static const struct clk_div_table ip_div_table[] = {
+ {0, 2}, {1, 4}, {2, 6}, {3, 8}, {4, 10},
+ {5, 12}, {6, 14}, {7, 16}, {0, 0},
+};
+
+static const struct clk_div_table eadc_div_table[] = {
+ {0, 2}, {1, 4}, {2, 6}, {3, 8}, {4, 10},
+ {5, 12}, {6, 14}, {7, 16}, {8, 18},
+ {9, 20}, {10, 22}, {11, 24}, {12, 26},
+ {13, 28}, {14, 30}, {15, 32}, {0, 0},
+};
+
+static struct clk_hw *ma35d1_clk_fixed(const char *name, int rate)
+{
+ return clk_hw_register_fixed_rate(NULL, name, NULL, 0, rate);
+}
+
+static struct clk_hw *ma35d1_clk_mux_parent(struct device *dev, const char *name,
+ void __iomem *reg, u8 shift, u8 width,
+ const struct clk_parent_data *pdata,
+ int num_pdata)
+{
+ return clk_hw_register_mux_parent_data(dev, name, pdata, num_pdata,
+ CLK_SET_RATE_NO_REPARENT, reg, shift,
+ width, 0, &ma35d1_lock);
+}
+
+static struct clk_hw *ma35d1_clk_mux(struct device *dev, const char *name,
+ void __iomem *reg, u8 shift, u8 width,
+ const struct clk_parent_data *pdata,
+ int num_pdata)
+{
+ return clk_hw_register_mux_parent_data(dev, name, pdata, num_pdata,
+ CLK_SET_RATE_NO_REPARENT, reg, shift,
+ width, 0, &ma35d1_lock);
+}
+
+static struct clk_hw *ma35d1_clk_divider(struct device *dev, const char *name,
+ const char *parent, void __iomem *reg,
+ u8 shift, u8 width)
+{
+ return devm_clk_hw_register_divider(dev, name, parent, CLK_SET_RATE_PARENT,
+ reg, shift, width, 0, &ma35d1_lock);
+}
+
+static struct clk_hw *ma35d1_clk_divider_pow2(struct device *dev, const char *name,
+ const char *parent, void __iomem *reg,
+ u8 shift, u8 width)
+{
+ return devm_clk_hw_register_divider(dev, name, parent,
+ CLK_DIVIDER_POWER_OF_TWO, reg, shift,
+ width, 0, &ma35d1_lock);
+}
+
+static struct clk_hw *ma35d1_clk_divider_table(struct device *dev, const char *name,
+ const char *parent, void __iomem *reg,
+ u8 shift, u8 width,
+ const struct clk_div_table *table)
+{
+ return devm_clk_hw_register_divider_table(dev, name, parent, 0,
+ reg, shift, width, 0,
+ table, &ma35d1_lock);
+}
+
+static struct clk_hw *ma35d1_clk_fixed_factor(struct device *dev, const char *name,
+ const char *parent, unsigned int mult,
+ unsigned int div)
+{
+ return devm_clk_hw_register_fixed_factor(dev, name, parent,
+ CLK_SET_RATE_PARENT, mult, div);
+}
+
+static struct clk_hw *ma35d1_clk_gate(struct device *dev, const char *name, const char *parent,
+ void __iomem *reg, u8 shift)
+{
+ return devm_clk_hw_register_gate(dev, name, parent, CLK_SET_RATE_PARENT,
+ reg, shift, 0, &ma35d1_lock);
+}
+
+static int ma35d1_get_pll_setting(struct device_node *clk_node, u32 *pllmode)
+{
+ const char *of_str;
+ int i;
+
+ for (i = 0; i < PLL_MAX_NUM; i++) {
+ if (of_property_read_string_index(clk_node, "nuvoton,pll-mode", i, &of_str))
+ return -EINVAL;
+ if (!strcmp(of_str, "integer"))
+ pllmode[i] = PLL_MODE_INT;
+ else if (!strcmp(of_str, "fractional"))
+ pllmode[i] = PLL_MODE_FRAC;
+ else if (!strcmp(of_str, "spread-spectrum"))
+ pllmode[i] = PLL_MODE_SS;
+ else
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int ma35d1_clocks_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *clk_node = pdev->dev.of_node;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ void __iomem *clk_base;
+ static struct clk_hw **hws;
+ static struct clk_hw_onecell_data *ma35d1_hw_data;
+ u32 pllmode[PLL_MAX_NUM];
+ int ret;
+
+ ma35d1_hw_data = devm_kzalloc(dev,
+ struct_size(ma35d1_hw_data, hws, CLK_MAX_IDX),
+ GFP_KERNEL);
+ if (!ma35d1_hw_data)
+ return -ENOMEM;
+
+ ma35d1_hw_data->num = CLK_MAX_IDX;
+ hws = ma35d1_hw_data->hws;
+
+ clk_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(clk_base))
+ return PTR_ERR(clk_base);
+
+ ret = ma35d1_get_pll_setting(clk_node, pllmode);
+ if (ret < 0) {
+ dev_err(dev, "Invalid PLL setting!\n");
+ return -EINVAL;
+ }
+
+ hws[HXT] = ma35d1_clk_fixed("hxt", 24000000);
+ hws[HXT_GATE] = ma35d1_clk_gate(dev, "hxt_gate", "hxt",
+ clk_base + REG_CLK_PWRCTL, 0);
+ hws[LXT] = ma35d1_clk_fixed("lxt", 32768);
+ hws[LXT_GATE] = ma35d1_clk_gate(dev, "lxt_gate", "lxt",
+ clk_base + REG_CLK_PWRCTL, 1);
+ hws[HIRC] = ma35d1_clk_fixed("hirc", 12000000);
+ hws[HIRC_GATE] = ma35d1_clk_gate(dev, "hirc_gate", "hirc",
+ clk_base + REG_CLK_PWRCTL, 2);
+ hws[LIRC] = ma35d1_clk_fixed("lirc", 32000);
+ hws[LIRC_GATE] = ma35d1_clk_gate(dev, "lirc_gate", "lirc",
+ clk_base + REG_CLK_PWRCTL, 3);
+
+ hws[CAPLL] = ma35d1_reg_clk_pll(dev, CAPLL, pllmode[0], "capll",
+ hws[HXT], clk_base + REG_CLK_PLL0CTL0);
+ hws[SYSPLL] = ma35d1_clk_fixed("syspll", 180000000);
+ hws[DDRPLL] = ma35d1_reg_clk_pll(dev, DDRPLL, pllmode[1], "ddrpll",
+ hws[HXT], clk_base + REG_CLK_PLL2CTL0);
+ hws[APLL] = ma35d1_reg_clk_pll(dev, APLL, pllmode[2], "apll",
+ hws[HXT], clk_base + REG_CLK_PLL3CTL0);
+ hws[EPLL] = ma35d1_reg_clk_pll(dev, EPLL, pllmode[3], "epll",
+ hws[HXT], clk_base + REG_CLK_PLL4CTL0);
+ hws[VPLL] = ma35d1_reg_clk_pll(dev, VPLL, pllmode[4], "vpll",
+ hws[HXT], clk_base + REG_CLK_PLL5CTL0);
+
+ hws[EPLL_DIV2] = ma35d1_clk_fixed_factor(dev, "epll_div2", "epll", 1, 2);
+ hws[EPLL_DIV4] = ma35d1_clk_fixed_factor(dev, "epll_div4", "epll", 1, 4);
+ hws[EPLL_DIV8] = ma35d1_clk_fixed_factor(dev, "epll_div8", "epll", 1, 8);
+
+ hws[CA35CLK_MUX] = ma35d1_clk_mux_parent(dev, "ca35clk_mux",
+ clk_base + REG_CLK_CLKSEL0, 0, 2,
+ ca35clk_sel_clks,
+ ARRAY_SIZE(ca35clk_sel_clks));
+ hws[AXICLK_DIV2] = ma35d1_clk_fixed_factor(dev, "capll_div2", "ca35clk_mux", 1, 2);
+ hws[AXICLK_DIV4] = ma35d1_clk_fixed_factor(dev, "capll_div4", "ca35clk_mux", 1, 4);
+
+ hws[AXICLK_MUX] = ma35d1_clk_mux(dev, "axiclk_mux", clk_base + REG_CLK_CLKDIV0,
+ 26, 1, axiclk_sel_clks,
+ ARRAY_SIZE(axiclk_sel_clks));
+ hws[SYSCLK0_MUX] = ma35d1_clk_mux(dev, "sysclk0_mux", clk_base + REG_CLK_CLKSEL0,
+ 2, 1, sysclk0_sel_clks,
+ ARRAY_SIZE(sysclk0_sel_clks));
+ hws[SYSCLK1_MUX] = ma35d1_clk_mux(dev, "sysclk1_mux", clk_base + REG_CLK_CLKSEL0,
+ 4, 1, sysclk1_sel_clks,
+ ARRAY_SIZE(sysclk1_sel_clks));
+ hws[SYSCLK1_DIV2] = ma35d1_clk_fixed_factor(dev, "sysclk1_div2", "sysclk1_mux", 1, 2);
+
+ /* HCLK0~3 & PCLK0~4 */
+ hws[HCLK0] = ma35d1_clk_fixed_factor(dev, "hclk0", "sysclk1_mux", 1, 1);
+ hws[HCLK1] = ma35d1_clk_fixed_factor(dev, "hclk1", "sysclk1_mux", 1, 1);
+ hws[HCLK2] = ma35d1_clk_fixed_factor(dev, "hclk2", "sysclk1_mux", 1, 1);
+ hws[PCLK0] = ma35d1_clk_fixed_factor(dev, "pclk0", "sysclk1_mux", 1, 1);
+ hws[PCLK1] = ma35d1_clk_fixed_factor(dev, "pclk1", "sysclk1_mux", 1, 1);
+ hws[PCLK2] = ma35d1_clk_fixed_factor(dev, "pclk2", "sysclk1_mux", 1, 1);
+
+ hws[HCLK3] = ma35d1_clk_fixed_factor(dev, "hclk3", "sysclk1_mux", 1, 2);
+ hws[PCLK3] = ma35d1_clk_fixed_factor(dev, "pclk3", "sysclk1_mux", 1, 2);
+ hws[PCLK4] = ma35d1_clk_fixed_factor(dev, "pclk4", "sysclk1_mux", 1, 2);
+
+ hws[USBPHY0] = ma35d1_clk_fixed("usbphy0", 480000000);
+ hws[USBPHY1] = ma35d1_clk_fixed("usbphy1", 480000000);
+
+ /* DDR */
+ hws[DDR0_GATE] = ma35d1_clk_gate(dev, "ddr0_gate", "ddrpll",
+ clk_base + REG_CLK_SYSCLK0, 4);
+ hws[DDR6_GATE] = ma35d1_clk_gate(dev, "ddr6_gate", "ddrpll",
+ clk_base + REG_CLK_SYSCLK0, 5);
+
+ hws[CAN0_MUX] = ma35d1_clk_mux(dev, "can0_mux", clk_base + REG_CLK_CLKSEL4,
+ 16, 1, can_sel_clks, ARRAY_SIZE(can_sel_clks));
+ hws[CAN0_DIV] = ma35d1_clk_divider_table(dev, "can0_div", "can0_mux",
+ clk_base + REG_CLK_CLKDIV0,
+ 0, 3, ip_div_table);
+ hws[CAN0_GATE] = ma35d1_clk_gate(dev, "can0_gate", "can0_div",
+ clk_base + REG_CLK_SYSCLK0, 8);
+ hws[CAN1_MUX] = ma35d1_clk_mux(dev, "can1_mux", clk_base + REG_CLK_CLKSEL4,
+ 17, 1, can_sel_clks, ARRAY_SIZE(can_sel_clks));
+ hws[CAN1_DIV] = ma35d1_clk_divider_table(dev, "can1_div", "can1_mux",
+ clk_base + REG_CLK_CLKDIV0,
+ 4, 3, ip_div_table);
+ hws[CAN1_GATE] = ma35d1_clk_gate(dev, "can1_gate", "can1_div",
+ clk_base + REG_CLK_SYSCLK0, 9);
+ hws[CAN2_MUX] = ma35d1_clk_mux(dev, "can2_mux", clk_base + REG_CLK_CLKSEL4,
+ 18, 1, can_sel_clks, ARRAY_SIZE(can_sel_clks));
+ hws[CAN2_DIV] = ma35d1_clk_divider_table(dev, "can2_div", "can2_mux",
+ clk_base + REG_CLK_CLKDIV0,
+ 8, 3, ip_div_table);
+ hws[CAN2_GATE] = ma35d1_clk_gate(dev, "can2_gate", "can2_div",
+ clk_base + REG_CLK_SYSCLK0, 10);
+ hws[CAN3_MUX] = ma35d1_clk_mux(dev, "can3_mux", clk_base + REG_CLK_CLKSEL4,
+ 19, 1, can_sel_clks, ARRAY_SIZE(can_sel_clks));
+ hws[CAN3_DIV] = ma35d1_clk_divider_table(dev, "can3_div", "can3_mux",
+ clk_base + REG_CLK_CLKDIV0,
+ 12, 3, ip_div_table);
+ hws[CAN3_GATE] = ma35d1_clk_gate(dev, "can3_gate", "can3_div",
+ clk_base + REG_CLK_SYSCLK0, 11);
+
+ hws[SDH0_MUX] = ma35d1_clk_mux(dev, "sdh0_mux", clk_base + REG_CLK_CLKSEL0,
+ 16, 2, sdh_sel_clks, ARRAY_SIZE(sdh_sel_clks));
+ hws[SDH0_GATE] = ma35d1_clk_gate(dev, "sdh0_gate", "sdh0_mux",
+ clk_base + REG_CLK_SYSCLK0, 16);
+ hws[SDH1_MUX] = ma35d1_clk_mux(dev, "sdh1_mux", clk_base + REG_CLK_CLKSEL0,
+ 18, 2, sdh_sel_clks, ARRAY_SIZE(sdh_sel_clks));
+ hws[SDH1_GATE] = ma35d1_clk_gate(dev, "sdh1_gate", "sdh1_mux",
+ clk_base + REG_CLK_SYSCLK0, 17);
+
+ hws[NAND_GATE] = ma35d1_clk_gate(dev, "nand_gate", "hclk1",
+ clk_base + REG_CLK_SYSCLK0, 18);
+
+ hws[USBD_GATE] = ma35d1_clk_gate(dev, "usbd_gate", "usbphy0",
+ clk_base + REG_CLK_SYSCLK0, 19);
+ hws[USBH_GATE] = ma35d1_clk_gate(dev, "usbh_gate", "usbphy0",
+ clk_base + REG_CLK_SYSCLK0, 20);
+ hws[HUSBH0_GATE] = ma35d1_clk_gate(dev, "husbh0_gate", "usbphy0",
+ clk_base + REG_CLK_SYSCLK0, 21);
+ hws[HUSBH1_GATE] = ma35d1_clk_gate(dev, "husbh1_gate", "usbphy0",
+ clk_base + REG_CLK_SYSCLK0, 22);
+
+ hws[GFX_MUX] = ma35d1_clk_mux(dev, "gfx_mux", clk_base + REG_CLK_CLKSEL0,
+ 26, 1, gfx_sel_clks, ARRAY_SIZE(gfx_sel_clks));
+ hws[GFX_GATE] = ma35d1_clk_gate(dev, "gfx_gate", "gfx_mux",
+ clk_base + REG_CLK_SYSCLK0, 24);
+ hws[VC8K_GATE] = ma35d1_clk_gate(dev, "vc8k_gate", "sysclk0_mux",
+ clk_base + REG_CLK_SYSCLK0, 25);
+ hws[DCU_MUX] = ma35d1_clk_mux(dev, "dcu_mux", clk_base + REG_CLK_CLKSEL0,
+ 24, 1, dcu_sel_clks, ARRAY_SIZE(dcu_sel_clks));
+ hws[DCU_GATE] = ma35d1_clk_gate(dev, "dcu_gate", "dcu_mux",
+ clk_base + REG_CLK_SYSCLK0, 26);
+ hws[DCUP_DIV] = ma35d1_clk_divider_table(dev, "dcup_div", "vpll",
+ clk_base + REG_CLK_CLKDIV0,
+ 16, 3, ip_div_table);
+
+ hws[EMAC0_GATE] = ma35d1_clk_gate(dev, "emac0_gate", "epll_div2",
+ clk_base + REG_CLK_SYSCLK0, 27);
+ hws[EMAC1_GATE] = ma35d1_clk_gate(dev, "emac1_gate", "epll_div2",
+ clk_base + REG_CLK_SYSCLK0, 28);
+
+ hws[CCAP0_MUX] = ma35d1_clk_mux(dev, "ccap0_mux", clk_base + REG_CLK_CLKSEL0,
+ 12, 1, ccap_sel_clks, ARRAY_SIZE(ccap_sel_clks));
+ hws[CCAP0_DIV] = ma35d1_clk_divider(dev, "ccap0_div", "ccap0_mux",
+ clk_base + REG_CLK_CLKDIV1, 8, 4);
+ hws[CCAP0_GATE] = ma35d1_clk_gate(dev, "ccap0_gate", "ccap0_div",
+ clk_base + REG_CLK_SYSCLK0, 29);
+ hws[CCAP1_MUX] = ma35d1_clk_mux(dev, "ccap1_mux", clk_base + REG_CLK_CLKSEL0,
+ 14, 1, ccap_sel_clks, ARRAY_SIZE(ccap_sel_clks));
+ hws[CCAP1_DIV] = ma35d1_clk_divider(dev, "ccap1_div", "ccap1_mux",
+ clk_base + REG_CLK_CLKDIV1,
+ 12, 4);
+ hws[CCAP1_GATE] = ma35d1_clk_gate(dev, "ccap1_gate", "ccap1_div",
+ clk_base + REG_CLK_SYSCLK0, 30);
+
+ hws[PDMA0_GATE] = ma35d1_clk_gate(dev, "pdma0_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 0);
+ hws[PDMA1_GATE] = ma35d1_clk_gate(dev, "pdma1_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 1);
+ hws[PDMA2_GATE] = ma35d1_clk_gate(dev, "pdma2_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 2);
+ hws[PDMA3_GATE] = ma35d1_clk_gate(dev, "pdma3_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 3);
+
+ hws[WH0_GATE] = ma35d1_clk_gate(dev, "wh0_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 4);
+ hws[WH1_GATE] = ma35d1_clk_gate(dev, "wh1_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 5);
+
+ hws[HWS_GATE] = ma35d1_clk_gate(dev, "hws_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 6);
+
+ hws[EBI_GATE] = ma35d1_clk_gate(dev, "ebi_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 7);
+
+ hws[SRAM0_GATE] = ma35d1_clk_gate(dev, "sram0_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 8);
+ hws[SRAM1_GATE] = ma35d1_clk_gate(dev, "sram1_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 9);
+
+ hws[ROM_GATE] = ma35d1_clk_gate(dev, "rom_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 10);
+
+ hws[TRA_GATE] = ma35d1_clk_gate(dev, "tra_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 11);
+
+ hws[DBG_MUX] = ma35d1_clk_mux(dev, "dbg_mux", clk_base + REG_CLK_CLKSEL0,
+ 27, 1, dbg_sel_clks, ARRAY_SIZE(dbg_sel_clks));
+ hws[DBG_GATE] = ma35d1_clk_gate(dev, "dbg_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 12);
+
+ hws[CKO_MUX] = ma35d1_clk_mux(dev, "cko_mux", clk_base + REG_CLK_CLKSEL4,
+ 24, 4, cko_sel_clks, ARRAY_SIZE(cko_sel_clks));
+ hws[CKO_DIV] = ma35d1_clk_divider_pow2(dev, "cko_div", "cko_mux",
+ clk_base + REG_CLK_CLKOCTL, 0, 4);
+ hws[CKO_GATE] = ma35d1_clk_gate(dev, "cko_gate", "cko_div",
+ clk_base + REG_CLK_SYSCLK1, 13);
+
+ hws[GTMR_GATE] = ma35d1_clk_gate(dev, "gtmr_gate", "hirc",
+ clk_base + REG_CLK_SYSCLK1, 14);
+
+ hws[GPA_GATE] = ma35d1_clk_gate(dev, "gpa_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 16);
+ hws[GPB_GATE] = ma35d1_clk_gate(dev, "gpb_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 17);
+ hws[GPC_GATE] = ma35d1_clk_gate(dev, "gpc_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 18);
+ hws[GPD_GATE] = ma35d1_clk_gate(dev, "gpd_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 19);
+ hws[GPE_GATE] = ma35d1_clk_gate(dev, "gpe_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 20);
+ hws[GPF_GATE] = ma35d1_clk_gate(dev, "gpf_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 21);
+ hws[GPG_GATE] = ma35d1_clk_gate(dev, "gpg_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 22);
+ hws[GPH_GATE] = ma35d1_clk_gate(dev, "gph_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 23);
+ hws[GPI_GATE] = ma35d1_clk_gate(dev, "gpi_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 24);
+ hws[GPJ_GATE] = ma35d1_clk_gate(dev, "gpj_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 25);
+ hws[GPK_GATE] = ma35d1_clk_gate(dev, "gpk_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 26);
+ hws[GPL_GATE] = ma35d1_clk_gate(dev, "gpl_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 27);
+ hws[GPM_GATE] = ma35d1_clk_gate(dev, "gpm_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 28);
+ hws[GPN_GATE] = ma35d1_clk_gate(dev, "gpn_gate", "hclk0",
+ clk_base + REG_CLK_SYSCLK1, 29);
+
+ hws[TMR0_MUX] = ma35d1_clk_mux(dev, "tmr0_mux", clk_base + REG_CLK_CLKSEL1,
+ 0, 3, timer0_sel_clks,
+ ARRAY_SIZE(timer0_sel_clks));
+ hws[TMR0_GATE] = ma35d1_clk_gate(dev, "tmr0_gate", "tmr0_mux",
+ clk_base + REG_CLK_APBCLK0, 0);
+ hws[TMR1_MUX] = ma35d1_clk_mux(dev, "tmr1_mux", clk_base + REG_CLK_CLKSEL1,
+ 4, 3, timer1_sel_clks,
+ ARRAY_SIZE(timer1_sel_clks));
+ hws[TMR1_GATE] = ma35d1_clk_gate(dev, "tmr1_gate", "tmr1_mux",
+ clk_base + REG_CLK_APBCLK0, 1);
+ hws[TMR2_MUX] = ma35d1_clk_mux(dev, "tmr2_mux", clk_base + REG_CLK_CLKSEL1,
+ 8, 3, timer2_sel_clks,
+ ARRAY_SIZE(timer2_sel_clks));
+ hws[TMR2_GATE] = ma35d1_clk_gate(dev, "tmr2_gate", "tmr2_mux",
+ clk_base + REG_CLK_APBCLK0, 2);
+ hws[TMR3_MUX] = ma35d1_clk_mux(dev, "tmr3_mux", clk_base + REG_CLK_CLKSEL1,
+ 12, 3, timer3_sel_clks,
+ ARRAY_SIZE(timer3_sel_clks));
+ hws[TMR3_GATE] = ma35d1_clk_gate(dev, "tmr3_gate", "tmr3_mux",
+ clk_base + REG_CLK_APBCLK0, 3);
+ hws[TMR4_MUX] = ma35d1_clk_mux(dev, "tmr4_mux", clk_base + REG_CLK_CLKSEL1,
+ 16, 3, timer4_sel_clks,
+ ARRAY_SIZE(timer4_sel_clks));
+ hws[TMR4_GATE] = ma35d1_clk_gate(dev, "tmr4_gate", "tmr4_mux",
+ clk_base + REG_CLK_APBCLK0, 4);
+ hws[TMR5_MUX] = ma35d1_clk_mux(dev, "tmr5_mux", clk_base + REG_CLK_CLKSEL1,
+ 20, 3, timer5_sel_clks,
+ ARRAY_SIZE(timer5_sel_clks));
+ hws[TMR5_GATE] = ma35d1_clk_gate(dev, "tmr5_gate", "tmr5_mux",
+ clk_base + REG_CLK_APBCLK0, 5);
+ hws[TMR6_MUX] = ma35d1_clk_mux(dev, "tmr6_mux", clk_base + REG_CLK_CLKSEL1,
+ 24, 3, timer6_sel_clks,
+ ARRAY_SIZE(timer6_sel_clks));
+ hws[TMR6_GATE] = ma35d1_clk_gate(dev, "tmr6_gate", "tmr6_mux",
+ clk_base + REG_CLK_APBCLK0, 6);
+ hws[TMR7_MUX] = ma35d1_clk_mux(dev, "tmr7_mux", clk_base + REG_CLK_CLKSEL1,
+ 28, 3, timer7_sel_clks,
+ ARRAY_SIZE(timer7_sel_clks));
+ hws[TMR7_GATE] = ma35d1_clk_gate(dev, "tmr7_gate", "tmr7_mux",
+ clk_base + REG_CLK_APBCLK0, 7);
+ hws[TMR8_MUX] = ma35d1_clk_mux(dev, "tmr8_mux", clk_base + REG_CLK_CLKSEL2,
+ 0, 3, timer8_sel_clks,
+ ARRAY_SIZE(timer8_sel_clks));
+ hws[TMR8_GATE] = ma35d1_clk_gate(dev, "tmr8_gate", "tmr8_mux",
+ clk_base + REG_CLK_APBCLK0, 8);
+ hws[TMR9_MUX] = ma35d1_clk_mux(dev, "tmr9_mux", clk_base + REG_CLK_CLKSEL2,
+ 4, 3, timer9_sel_clks,
+ ARRAY_SIZE(timer9_sel_clks));
+ hws[TMR9_GATE] = ma35d1_clk_gate(dev, "tmr9_gate", "tmr9_mux",
+ clk_base + REG_CLK_APBCLK0, 9);
+ hws[TMR10_MUX] = ma35d1_clk_mux(dev, "tmr10_mux", clk_base + REG_CLK_CLKSEL2,
+ 8, 3, timer10_sel_clks,
+ ARRAY_SIZE(timer10_sel_clks));
+ hws[TMR10_GATE] = ma35d1_clk_gate(dev, "tmr10_gate", "tmr10_mux",
+ clk_base + REG_CLK_APBCLK0, 10);
+ hws[TMR11_MUX] = ma35d1_clk_mux(dev, "tmr11_mux", clk_base + REG_CLK_CLKSEL2,
+ 12, 3, timer11_sel_clks,
+ ARRAY_SIZE(timer11_sel_clks));
+ hws[TMR11_GATE] = ma35d1_clk_gate(dev, "tmr11_gate", "tmr11_mux",
+ clk_base + REG_CLK_APBCLK0, 11);
+
+ hws[UART0_MUX] = ma35d1_clk_mux(dev, "uart0_mux", clk_base + REG_CLK_CLKSEL2,
+ 16, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART0_DIV] = ma35d1_clk_divider(dev, "uart0_div", "uart0_mux",
+ clk_base + REG_CLK_CLKDIV1,
+ 16, 4);
+ hws[UART0_GATE] = ma35d1_clk_gate(dev, "uart0_gate", "uart0_div",
+ clk_base + REG_CLK_APBCLK0, 12);
+ hws[UART1_MUX] = ma35d1_clk_mux(dev, "uart1_mux", clk_base + REG_CLK_CLKSEL2,
+ 18, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART1_DIV] = ma35d1_clk_divider(dev, "uart1_div", "uart1_mux",
+ clk_base + REG_CLK_CLKDIV1,
+ 20, 4);
+ hws[UART1_GATE] = ma35d1_clk_gate(dev, "uart1_gate", "uart1_div",
+ clk_base + REG_CLK_APBCLK0, 13);
+ hws[UART2_MUX] = ma35d1_clk_mux(dev, "uart2_mux", clk_base + REG_CLK_CLKSEL2,
+ 20, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART2_DIV] = ma35d1_clk_divider(dev, "uart2_div", "uart2_mux",
+ clk_base + REG_CLK_CLKDIV1,
+ 24, 4);
+ hws[UART2_GATE] = ma35d1_clk_gate(dev, "uart2_gate", "uart2_div",
+ clk_base + REG_CLK_APBCLK0, 14);
+ hws[UART3_MUX] = ma35d1_clk_mux(dev, "uart3_mux", clk_base + REG_CLK_CLKSEL2,
+ 22, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART3_DIV] = ma35d1_clk_divider(dev, "uart3_div", "uart3_mux",
+ clk_base + REG_CLK_CLKDIV1,
+ 28, 4);
+ hws[UART3_GATE] = ma35d1_clk_gate(dev, "uart3_gate", "uart3_div",
+ clk_base + REG_CLK_APBCLK0, 15);
+ hws[UART4_MUX] = ma35d1_clk_mux(dev, "uart4_mux", clk_base + REG_CLK_CLKSEL2,
+ 24, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART4_DIV] = ma35d1_clk_divider(dev, "uart4_div", "uart4_mux",
+ clk_base + REG_CLK_CLKDIV2,
+ 0, 4);
+ hws[UART4_GATE] = ma35d1_clk_gate(dev, "uart4_gate", "uart4_div",
+ clk_base + REG_CLK_APBCLK0, 16);
+ hws[UART5_MUX] = ma35d1_clk_mux(dev, "uart5_mux", clk_base + REG_CLK_CLKSEL2,
+ 26, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART5_DIV] = ma35d1_clk_divider(dev, "uart5_div", "uart5_mux",
+ clk_base + REG_CLK_CLKDIV2,
+ 4, 4);
+ hws[UART5_GATE] = ma35d1_clk_gate(dev, "uart5_gate", "uart5_div",
+ clk_base + REG_CLK_APBCLK0, 17);
+ hws[UART6_MUX] = ma35d1_clk_mux(dev, "uart6_mux", clk_base + REG_CLK_CLKSEL2,
+ 28, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART6_DIV] = ma35d1_clk_divider(dev, "uart6_div", "uart6_mux",
+ clk_base + REG_CLK_CLKDIV2,
+ 8, 4);
+ hws[UART6_GATE] = ma35d1_clk_gate(dev, "uart6_gate", "uart6_div",
+ clk_base + REG_CLK_APBCLK0, 18);
+ hws[UART7_MUX] = ma35d1_clk_mux(dev, "uart7_mux", clk_base + REG_CLK_CLKSEL2,
+ 30, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART7_DIV] = ma35d1_clk_divider(dev, "uart7_div", "uart7_mux",
+ clk_base + REG_CLK_CLKDIV2,
+ 12, 4);
+ hws[UART7_GATE] = ma35d1_clk_gate(dev, "uart7_gate", "uart7_div",
+ clk_base + REG_CLK_APBCLK0, 19);
+ hws[UART8_MUX] = ma35d1_clk_mux(dev, "uart8_mux", clk_base + REG_CLK_CLKSEL3,
+ 0, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART8_DIV] = ma35d1_clk_divider(dev, "uart8_div", "uart8_mux",
+ clk_base + REG_CLK_CLKDIV2,
+ 16, 4);
+ hws[UART8_GATE] = ma35d1_clk_gate(dev, "uart8_gate", "uart8_div",
+ clk_base + REG_CLK_APBCLK0, 20);
+ hws[UART9_MUX] = ma35d1_clk_mux(dev, "uart9_mux", clk_base + REG_CLK_CLKSEL3,
+ 2, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART9_DIV] = ma35d1_clk_divider(dev, "uart9_div", "uart9_mux",
+ clk_base + REG_CLK_CLKDIV2,
+ 20, 4);
+ hws[UART9_GATE] = ma35d1_clk_gate(dev, "uart9_gate", "uart9_div",
+ clk_base + REG_CLK_APBCLK0, 21);
+ hws[UART10_MUX] = ma35d1_clk_mux(dev, "uart10_mux", clk_base + REG_CLK_CLKSEL3,
+ 4, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART10_DIV] = ma35d1_clk_divider(dev, "uart10_div", "uart10_mux",
+ clk_base + REG_CLK_CLKDIV2,
+ 24, 4);
+ hws[UART10_GATE] = ma35d1_clk_gate(dev, "uart10_gate", "uart10_div",
+ clk_base + REG_CLK_APBCLK0, 22);
+ hws[UART11_MUX] = ma35d1_clk_mux(dev, "uart11_mux", clk_base + REG_CLK_CLKSEL3,
+ 6, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART11_DIV] = ma35d1_clk_divider(dev, "uart11_div", "uart11_mux",
+ clk_base + REG_CLK_CLKDIV2,
+ 28, 4);
+ hws[UART11_GATE] = ma35d1_clk_gate(dev, "uart11_gate", "uart11_div",
+ clk_base + REG_CLK_APBCLK0, 23);
+ hws[UART12_MUX] = ma35d1_clk_mux(dev, "uart12_mux", clk_base + REG_CLK_CLKSEL3,
+ 8, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART12_DIV] = ma35d1_clk_divider(dev, "uart12_div", "uart12_mux",
+ clk_base + REG_CLK_CLKDIV3,
+ 0, 4);
+ hws[UART12_GATE] = ma35d1_clk_gate(dev, "uart12_gate", "uart12_div",
+ clk_base + REG_CLK_APBCLK0, 24);
+ hws[UART13_MUX] = ma35d1_clk_mux(dev, "uart13_mux", clk_base + REG_CLK_CLKSEL3,
+ 10, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART13_DIV] = ma35d1_clk_divider(dev, "uart13_div", "uart13_mux",
+ clk_base + REG_CLK_CLKDIV3,
+ 4, 4);
+ hws[UART13_GATE] = ma35d1_clk_gate(dev, "uart13_gate", "uart13_div",
+ clk_base + REG_CLK_APBCLK0, 25);
+ hws[UART14_MUX] = ma35d1_clk_mux(dev, "uart14_mux", clk_base + REG_CLK_CLKSEL3,
+ 12, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART14_DIV] = ma35d1_clk_divider(dev, "uart14_div", "uart14_mux",
+ clk_base + REG_CLK_CLKDIV3,
+ 8, 4);
+ hws[UART14_GATE] = ma35d1_clk_gate(dev, "uart14_gate", "uart14_div",
+ clk_base + REG_CLK_APBCLK0, 26);
+ hws[UART15_MUX] = ma35d1_clk_mux(dev, "uart15_mux", clk_base + REG_CLK_CLKSEL3,
+ 14, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART15_DIV] = ma35d1_clk_divider(dev, "uart15_div", "uart15_mux",
+ clk_base + REG_CLK_CLKDIV3,
+ 12, 4);
+ hws[UART15_GATE] = ma35d1_clk_gate(dev, "uart15_gate", "uart15_div",
+ clk_base + REG_CLK_APBCLK0, 27);
+ hws[UART16_MUX] = ma35d1_clk_mux(dev, "uart16_mux", clk_base + REG_CLK_CLKSEL3,
+ 16, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks));
+ hws[UART16_DIV] = ma35d1_clk_divider(dev, "uart16_div", "uart16_mux",
+ clk_base + REG_CLK_CLKDIV3,
+ 16, 4);
+ hws[UART16_GATE] = ma35d1_clk_gate(dev, "uart16_gate", "uart16_div",
+ clk_base + REG_CLK_APBCLK0, 28);
+
+ hws[RTC_GATE] = ma35d1_clk_gate(dev, "rtc_gate", "lxt",
+ clk_base + REG_CLK_APBCLK0, 29);
+ hws[DDR_GATE] = ma35d1_clk_gate(dev, "ddr_gate", "ddrpll",
+ clk_base + REG_CLK_APBCLK0, 30);
+
+ hws[KPI_MUX] = ma35d1_clk_mux(dev, "kpi_mux", clk_base + REG_CLK_CLKSEL4,
+ 30, 1, kpi_sel_clks, ARRAY_SIZE(kpi_sel_clks));
+ hws[KPI_DIV] = ma35d1_clk_divider(dev, "kpi_div", "kpi_mux",
+ clk_base + REG_CLK_CLKDIV4,
+ 24, 8);
+ hws[KPI_GATE] = ma35d1_clk_gate(dev, "kpi_gate", "kpi_div",
+ clk_base + REG_CLK_APBCLK0, 31);
+
+ hws[I2C0_GATE] = ma35d1_clk_gate(dev, "i2c0_gate", "pclk0",
+ clk_base + REG_CLK_APBCLK1, 0);
+ hws[I2C1_GATE] = ma35d1_clk_gate(dev, "i2c1_gate", "pclk1",
+ clk_base + REG_CLK_APBCLK1, 1);
+ hws[I2C2_GATE] = ma35d1_clk_gate(dev, "i2c2_gate", "pclk2",
+ clk_base + REG_CLK_APBCLK1, 2);
+ hws[I2C3_GATE] = ma35d1_clk_gate(dev, "i2c3_gate", "pclk0",
+ clk_base + REG_CLK_APBCLK1, 3);
+ hws[I2C4_GATE] = ma35d1_clk_gate(dev, "i2c4_gate", "pclk1",
+ clk_base + REG_CLK_APBCLK1, 4);
+ hws[I2C5_GATE] = ma35d1_clk_gate(dev, "i2c5_gate", "pclk2",
+ clk_base + REG_CLK_APBCLK1, 5);
+
+ hws[QSPI0_MUX] = ma35d1_clk_mux(dev, "qspi0_mux", clk_base + REG_CLK_CLKSEL4,
+ 8, 2, qspi0_sel_clks, ARRAY_SIZE(qspi0_sel_clks));
+ hws[QSPI0_GATE] = ma35d1_clk_gate(dev, "qspi0_gate", "qspi0_mux",
+ clk_base + REG_CLK_APBCLK1, 6);
+ hws[QSPI1_MUX] = ma35d1_clk_mux(dev, "qspi1_mux", clk_base + REG_CLK_CLKSEL4,
+ 10, 2, qspi1_sel_clks, ARRAY_SIZE(qspi1_sel_clks));
+ hws[QSPI1_GATE] = ma35d1_clk_gate(dev, "qspi1_gate", "qspi1_mux",
+ clk_base + REG_CLK_APBCLK1, 7);
+
+ hws[SMC0_MUX] = ma35d1_clk_mux(dev, "smc0_mux", clk_base + REG_CLK_CLKSEL4,
+ 28, 1, smc_sel_clks, ARRAY_SIZE(smc_sel_clks));
+ hws[SMC0_DIV] = ma35d1_clk_divider(dev, "smc0_div", "smc0_mux",
+ clk_base + REG_CLK_CLKDIV1,
+ 0, 4);
+ hws[SMC0_GATE] = ma35d1_clk_gate(dev, "smc0_gate", "smc0_div",
+ clk_base + REG_CLK_APBCLK1, 12);
+ hws[SMC1_MUX] = ma35d1_clk_mux(dev, "smc1_mux", clk_base + REG_CLK_CLKSEL4,
+ 29, 1, smc_sel_clks, ARRAY_SIZE(smc_sel_clks));
+ hws[SMC1_DIV] = ma35d1_clk_divider(dev, "smc1_div", "smc1_mux",
+ clk_base + REG_CLK_CLKDIV1,
+ 4, 4);
+ hws[SMC1_GATE] = ma35d1_clk_gate(dev, "smc1_gate", "smc1_div",
+ clk_base + REG_CLK_APBCLK1, 13);
+
+ hws[WDT0_MUX] = ma35d1_clk_mux(dev, "wdt0_mux", clk_base + REG_CLK_CLKSEL3,
+ 20, 2, wdt0_sel_clks, ARRAY_SIZE(wdt0_sel_clks));
+ hws[WDT0_GATE] = ma35d1_clk_gate(dev, "wdt0_gate", "wdt0_mux",
+ clk_base + REG_CLK_APBCLK1, 16);
+ hws[WDT1_MUX] = ma35d1_clk_mux(dev, "wdt1_mux", clk_base + REG_CLK_CLKSEL3,
+ 24, 2, wdt1_sel_clks, ARRAY_SIZE(wdt1_sel_clks));
+ hws[WDT1_GATE] = ma35d1_clk_gate(dev, "wdt1_gate", "wdt1_mux",
+ clk_base + REG_CLK_APBCLK1, 17);
+ hws[WDT2_MUX] = ma35d1_clk_mux(dev, "wdt2_mux", clk_base + REG_CLK_CLKSEL3,
+ 28, 2, wdt2_sel_clks, ARRAY_SIZE(wdt2_sel_clks));
+ hws[WDT2_GATE] = ma35d1_clk_gate(dev, "wdt2_gate", "wdt2_mux",
+ clk_base + REG_CLK_APBCLK1, 18);
+
+ hws[WWDT0_MUX] = ma35d1_clk_mux(dev, "wwdt0_mux", clk_base + REG_CLK_CLKSEL3,
+ 22, 2, wwdt0_sel_clks, ARRAY_SIZE(wwdt0_sel_clks));
+ hws[WWDT1_MUX] = ma35d1_clk_mux(dev, "wwdt1_mux", clk_base + REG_CLK_CLKSEL3,
+ 26, 2, wwdt1_sel_clks, ARRAY_SIZE(wwdt1_sel_clks));
+ hws[WWDT2_MUX] = ma35d1_clk_mux(dev, "wwdt2_mux", clk_base + REG_CLK_CLKSEL3,
+ 30, 2, wwdt2_sel_clks, ARRAY_SIZE(wwdt2_sel_clks));
+
+ hws[EPWM0_GATE] = ma35d1_clk_gate(dev, "epwm0_gate", "pclk1",
+ clk_base + REG_CLK_APBCLK1, 24);
+ hws[EPWM1_GATE] = ma35d1_clk_gate(dev, "epwm1_gate", "pclk2",
+ clk_base + REG_CLK_APBCLK1, 25);
+ hws[EPWM2_GATE] = ma35d1_clk_gate(dev, "epwm2_gate", "pclk1",
+ clk_base + REG_CLK_APBCLK1, 26);
+
+ hws[I2S0_MUX] = ma35d1_clk_mux(dev, "i2s0_mux", clk_base + REG_CLK_CLKSEL4,
+ 12, 2, i2s0_sel_clks, ARRAY_SIZE(i2s0_sel_clks));
+ hws[I2S0_GATE] = ma35d1_clk_gate(dev, "i2s0_gate", "i2s0_mux",
+ clk_base + REG_CLK_APBCLK2, 0);
+ hws[I2S1_MUX] = ma35d1_clk_mux(dev, "i2s1_mux", clk_base + REG_CLK_CLKSEL4,
+ 14, 2, i2s1_sel_clks, ARRAY_SIZE(i2s1_sel_clks));
+ hws[I2S1_GATE] = ma35d1_clk_gate(dev, "i2s1_gate", "i2s1_mux",
+ clk_base + REG_CLK_APBCLK2, 1);
+
+ hws[SSMCC_GATE] = ma35d1_clk_gate(dev, "ssmcc_gate", "pclk3",
+ clk_base + REG_CLK_APBCLK2, 2);
+ hws[SSPCC_GATE] = ma35d1_clk_gate(dev, "sspcc_gate", "pclk3",
+ clk_base + REG_CLK_APBCLK2, 3);
+
+ hws[SPI0_MUX] = ma35d1_clk_mux(dev, "spi0_mux", clk_base + REG_CLK_CLKSEL4,
+ 0, 2, spi0_sel_clks, ARRAY_SIZE(spi0_sel_clks));
+ hws[SPI0_GATE] = ma35d1_clk_gate(dev, "spi0_gate", "spi0_mux",
+ clk_base + REG_CLK_APBCLK2, 4);
+ hws[SPI1_MUX] = ma35d1_clk_mux(dev, "spi1_mux", clk_base + REG_CLK_CLKSEL4,
+ 2, 2, spi1_sel_clks, ARRAY_SIZE(spi1_sel_clks));
+ hws[SPI1_GATE] = ma35d1_clk_gate(dev, "spi1_gate", "spi1_mux",
+ clk_base + REG_CLK_APBCLK2, 5);
+ hws[SPI2_MUX] = ma35d1_clk_mux(dev, "spi2_mux", clk_base + REG_CLK_CLKSEL4,
+ 4, 2, spi2_sel_clks, ARRAY_SIZE(spi2_sel_clks));
+ hws[SPI2_GATE] = ma35d1_clk_gate(dev, "spi2_gate", "spi2_mux",
+ clk_base + REG_CLK_APBCLK2, 6);
+ hws[SPI3_MUX] = ma35d1_clk_mux(dev, "spi3_mux", clk_base + REG_CLK_CLKSEL4,
+ 6, 2, spi3_sel_clks, ARRAY_SIZE(spi3_sel_clks));
+ hws[SPI3_GATE] = ma35d1_clk_gate(dev, "spi3_gate", "spi3_mux",
+ clk_base + REG_CLK_APBCLK2, 7);
+
+ hws[ECAP0_GATE] = ma35d1_clk_gate(dev, "ecap0_gate", "pclk1",
+ clk_base + REG_CLK_APBCLK2, 8);
+ hws[ECAP1_GATE] = ma35d1_clk_gate(dev, "ecap1_gate", "pclk2",
+ clk_base + REG_CLK_APBCLK2, 9);
+ hws[ECAP2_GATE] = ma35d1_clk_gate(dev, "ecap2_gate", "pclk1",
+ clk_base + REG_CLK_APBCLK2, 10);
+
+ hws[QEI0_GATE] = ma35d1_clk_gate(dev, "qei0_gate", "pclk1",
+ clk_base + REG_CLK_APBCLK2, 12);
+ hws[QEI1_GATE] = ma35d1_clk_gate(dev, "qei1_gate", "pclk2",
+ clk_base + REG_CLK_APBCLK2, 13);
+ hws[QEI2_GATE] = ma35d1_clk_gate(dev, "qei2_gate", "pclk1",
+ clk_base + REG_CLK_APBCLK2, 14);
+
+ hws[ADC_DIV] = ma35d1_reg_adc_clkdiv(dev, "adc_div", hws[PCLK0],
+ &ma35d1_lock, 0,
+ clk_base + REG_CLK_CLKDIV4,
+ 4, 17, 0x1ffff);
+ hws[ADC_GATE] = ma35d1_clk_gate(dev, "adc_gate", "adc_div",
+ clk_base + REG_CLK_APBCLK2, 24);
+
+ hws[EADC_DIV] = ma35d1_clk_divider_table(dev, "eadc_div", "pclk2",
+ clk_base + REG_CLK_CLKDIV4,
+ 0, 4, eadc_div_table);
+ hws[EADC_GATE] = ma35d1_clk_gate(dev, "eadc_gate", "eadc_div",
+ clk_base + REG_CLK_APBCLK2, 25);
+
+ return devm_of_clk_add_hw_provider(dev,
+ of_clk_hw_onecell_get,
+ ma35d1_hw_data);
+}
+
+static const struct of_device_id ma35d1_clk_of_match[] = {
+ { .compatible = "nuvoton,ma35d1-clk" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ma35d1_clk_of_match);
+
+static struct platform_driver ma35d1_clk_driver = {
+ .probe = ma35d1_clocks_probe,
+ .driver = {
+ .name = "ma35d1-clk",
+ .of_match_table = ma35d1_clk_of_match,
+ },
+};
+
+static int __init ma35d1_clocks_init(void)
+{
+ return platform_driver_register(&ma35d1_clk_driver);
+}
+
+postcore_initcall(ma35d1_clocks_init);
+
+MODULE_AUTHOR("Chi-Fang Li <cfli0@nuvoton.com>");
+MODULE_DESCRIPTION("NUVOTON MA35D1 Clock Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/nuvoton/clk-ma35d1.h b/drivers/clk/nuvoton/clk-ma35d1.h
new file mode 100644
index 000000000000..3adee440f60a
--- /dev/null
+++ b/drivers/clk/nuvoton/clk-ma35d1.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 Nuvoton Technology Corp.
+ * Author: Chi-Fang Li <cfli0@nuvoton.com>
+ */
+
+#ifndef __DRV_CLK_NUVOTON_MA35D1_H
+#define __DRV_CLK_NUVOTON_MA35D1_H
+
+struct clk_hw *ma35d1_reg_clk_pll(struct device *dev, u32 id, u8 u8mode, const char *name,
+ struct clk_hw *parent_hw, void __iomem *base);
+
+struct clk_hw *ma35d1_reg_adc_clkdiv(struct device *dev, const char *name,
+ struct clk_hw *parent_hw, spinlock_t *lock,
+ unsigned long flags, void __iomem *reg,
+ u8 shift, u8 width, u32 mask_bit);
+
+#endif /* __DRV_CLK_NUVOTON_MA35D1_H */
diff --git a/drivers/clk/pxa/clk-pxa.c b/drivers/clk/pxa/clk-pxa.c
index 374098ebbf2b..ebee2afd05de 100644
--- a/drivers/clk/pxa/clk-pxa.c
+++ b/drivers/clk/pxa/clk-pxa.c
@@ -82,6 +82,7 @@ static u8 cken_get_parent(struct clk_hw *hw)
}
static const struct clk_ops cken_mux_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = cken_get_parent,
.set_parent = dummy_clk_set_parent,
};
diff --git a/drivers/clk/pxa/clk-pxa25x.c b/drivers/clk/pxa/clk-pxa25x.c
index 93d5907b8530..0a4da519d704 100644
--- a/drivers/clk/pxa/clk-pxa25x.c
+++ b/drivers/clk/pxa/clk-pxa25x.c
@@ -11,10 +11,12 @@
*/
#include <linux/clk-provider.h>
#include <linux/clk.h>
+#include <linux/clk/pxa.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/soc/pxa/smemc.h>
+#include <linux/soc/pxa/cpu.h>
#include <dt-bindings/clock/pxa-clock.h>
#include "clk-pxa.h"
diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c
index 116c6ac666e3..2bea89874ec1 100644
--- a/drivers/clk/pxa/clk-pxa27x.c
+++ b/drivers/clk/pxa/clk-pxa27x.c
@@ -12,6 +12,7 @@
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/soc/pxa/smemc.h>
+#include <linux/clk/pxa.h>
#include <dt-bindings/clock/pxa-clock.h>
#include "clk-pxa.h"
@@ -99,7 +100,7 @@ unsigned int pxa27x_get_clk_frequency_khz(int info)
return (unsigned int)clks[0] / KHz;
}
-bool pxa27x_is_ppll_disabled(void)
+static bool pxa27x_is_ppll_disabled(void)
{
unsigned long ccsr = readl(clk_regs + CCSR);
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 12be3e2371b3..263e55d75e3f 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -48,6 +48,7 @@ config QCOM_CLK_APCS_MSM8916
config QCOM_CLK_APCC_MSM8996
tristate "MSM8996 CPU Clock Controller"
select QCOM_KRYO_L2_ACCESSORS
+ select INTERCONNECT_CLK if INTERCONNECT
depends on ARM64
help
Support for the CPU clock controller on msm8996 devices.
@@ -57,6 +58,7 @@ config QCOM_CLK_APCC_MSM8996
config QCOM_CLK_APCS_SDX55
tristate "SDX55 and SDX65 APCS Clock Controller"
depends on QCOM_APCS_IPC || COMPILE_TEST
+ depends on ARM || COMPILE_TEST
help
Support for the APCS Clock Controller on SDX55, SDX65 platforms. The
APCS is managing the mux and divider which feeds the CPUs.
@@ -100,6 +102,7 @@ config QCOM_CLK_RPMH
config APQ_GCC_8084
tristate "APQ8084 Global Clock Controller"
+ depends on ARM || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on apq8084 devices.
@@ -108,6 +111,7 @@ config APQ_GCC_8084
config APQ_MMCC_8084
tristate "APQ8084 Multimedia Clock Controller"
+ depends on ARM || COMPILE_TEST
select APQ_GCC_8084
select QCOM_GDSC
help
@@ -159,6 +163,7 @@ config IPQ_GCC_6018
config IPQ_GCC_806X
tristate "IPQ806x Global Clock Controller"
+ depends on ARM || COMPILE_TEST
help
Support for the global clock controller on ipq806x devices.
Say Y if you want to use peripheral devices such as UART, SPI,
@@ -166,6 +171,7 @@ config IPQ_GCC_806X
config IPQ_LCC_806X
tristate "IPQ806x LPASS Clock Controller"
+ depends on ARM || COMPILE_TEST
select IPQ_GCC_806X
help
Support for the LPASS clock controller on ipq806x devices.
@@ -191,6 +197,7 @@ config IPQ_GCC_9574
config MSM_GCC_8660
tristate "MSM8660 Global Clock Controller"
+ depends on ARM || COMPILE_TEST
help
Support for the global clock controller on msm8660 devices.
Say Y if you want to use peripheral devices such as UART, SPI,
@@ -198,6 +205,7 @@ config MSM_GCC_8660
config MSM_GCC_8909
tristate "MSM8909 Global Clock Controller"
+ depends on ARM || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on msm8909 devices.
@@ -232,6 +240,7 @@ config MSM_GCC_8939
config MSM_GCC_8960
tristate "APQ8064/MSM8960 Global Clock Controller"
+ depends on ARM || COMPILE_TEST
help
Support for the global clock controller on apq8064/msm8960 devices.
Say Y if you want to use peripheral devices such as UART, SPI,
@@ -239,6 +248,7 @@ config MSM_GCC_8960
config MSM_LCC_8960
tristate "APQ8064/MSM8960 LPASS Clock Controller"
+ depends on ARM || COMPILE_TEST
select MSM_GCC_8960
help
Support for the LPASS clock controller on apq8064/msm8960 devices.
@@ -247,6 +257,7 @@ config MSM_LCC_8960
config MDM_GCC_9607
tristate "MDM9607 Global Clock Controller"
+ depends on ARM || COMPILE_TEST
help
Support for the global clock controller on mdm9607 devices.
Say Y if you want to use peripheral devices such as UART, SPI,
@@ -254,6 +265,7 @@ config MDM_GCC_9607
config MDM_GCC_9615
tristate "MDM9615 Global Clock Controller"
+ depends on ARM || COMPILE_TEST
help
Support for the global clock controller on mdm9615 devices.
Say Y if you want to use peripheral devices such as UART, SPI,
@@ -261,6 +273,7 @@ config MDM_GCC_9615
config MDM_LCC_9615
tristate "MDM9615 LPASS Clock Controller"
+ depends on ARM || COMPILE_TEST
select MDM_GCC_9615
help
Support for the LPASS clock controller on mdm9615 devices.
@@ -269,6 +282,7 @@ config MDM_LCC_9615
config MSM_MMCC_8960
tristate "MSM8960 Multimedia Clock Controller"
+ depends on ARM || COMPILE_TEST
select MSM_GCC_8960
help
Support for the multimedia clock controller on msm8960 devices.
@@ -285,6 +299,7 @@ config MSM_GCC_8953
config MSM_GCC_8974
tristate "MSM8974 Global Clock Controller"
+ depends on ARM || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on msm8974 devices.
@@ -293,6 +308,7 @@ config MSM_GCC_8974
config MSM_MMCC_8974
tristate "MSM8974 Multimedia Clock Controller"
+ depends on ARM || COMPILE_TEST
select MSM_GCC_8974
select QCOM_GDSC
help
@@ -393,6 +409,7 @@ config QCS_GCC_404
config SC_CAMCC_7180
tristate "SC7180 Camera Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_7180
help
Support for the camera clock controller on Qualcomm Technologies, Inc
@@ -402,6 +419,7 @@ config SC_CAMCC_7180
config SC_CAMCC_7280
tristate "SC7280 Camera Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_7280
help
Support for the camera clock controller on Qualcomm Technologies, Inc
@@ -411,6 +429,7 @@ config SC_CAMCC_7280
config SC_DISPCC_7180
tristate "SC7180 Display Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_7180
help
Support for the display clock controller on Qualcomm Technologies, Inc
@@ -420,6 +439,7 @@ config SC_DISPCC_7180
config SC_DISPCC_7280
tristate "SC7280 Display Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_7280
help
Support for the display clock controller on Qualcomm Technologies, Inc.
@@ -429,6 +449,7 @@ config SC_DISPCC_7280
config SC_DISPCC_8280XP
tristate "SC8280XP Display Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_8280XP
help
Support for the two display clock controllers on Qualcomm
@@ -458,6 +479,7 @@ config SC_GCC_7180
tristate "SC7180 Global Clock Controller"
select QCOM_GDSC
depends on COMMON_CLK_QCOM
+ depends on ARM64 || COMPILE_TEST
help
Support for the global clock controller on SC7180 devices.
Say Y if you want to use peripheral devices such as UART, SPI,
@@ -467,6 +489,7 @@ config SC_GCC_7280
tristate "SC7280 Global Clock Controller"
select QCOM_GDSC
depends on COMMON_CLK_QCOM
+ depends on ARM64 || COMPILE_TEST
help
Support for the global clock controller on SC7280 devices.
Say Y if you want to use peripheral devices such as UART, SPI,
@@ -476,6 +499,7 @@ config SC_GCC_8180X
tristate "SC8180X Global Clock Controller"
select QCOM_GDSC
depends on COMMON_CLK_QCOM
+ depends on ARM64 || COMPILE_TEST
help
Support for the global clock controller on SC8180X devices.
Say Y if you want to use peripheral devices such as UART, SPI,
@@ -485,6 +509,7 @@ config SC_GCC_8280XP
tristate "SC8280XP Global Clock Controller"
select QCOM_GDSC
depends on COMMON_CLK_QCOM
+ depends on ARM64 || COMPILE_TEST
help
Support for the global clock controller on SC8280XP devices.
Say Y if you want to use peripheral devices such as UART, SPI,
@@ -492,6 +517,7 @@ config SC_GCC_8280XP
config SC_GPUCC_7180
tristate "SC7180 Graphics Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_7180
help
Support for the graphics clock controller on SC7180 devices.
@@ -500,6 +526,7 @@ config SC_GPUCC_7180
config SC_GPUCC_7280
tristate "SC7280 Graphics Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_7280
help
Support for the graphics clock controller on SC7280 devices.
@@ -508,6 +535,7 @@ config SC_GPUCC_7280
config SC_GPUCC_8280XP
tristate "SC8280XP Graphics Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_8280XP
help
Support for the graphics clock controller on SC8280XP devices.
@@ -516,14 +544,25 @@ config SC_GPUCC_8280XP
config SC_LPASSCC_7280
tristate "SC7280 Low Power Audio Subsystem (LPASS) Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_7280
help
Support for the LPASS clock controller on SC7280 devices.
Say Y if you want to use the LPASS branch clocks of the LPASS clock
controller to reset the LPASS subsystem.
+config SC_LPASSCC_8280XP
+ tristate "SC8280 Low Power Audio Subsystem (LPASS) Clock Controller"
+ depends on ARM64 || COMPILE_TEST
+ select SC_GCC_8280XP
+ help
+ Support for the LPASS clock controller on SC8280XP devices.
+ Say Y if you want to use the LPASS branch clocks of the LPASS clock
+ controller to reset the LPASS subsystem.
+
config SC_LPASS_CORECC_7180
tristate "SC7180 LPASS Core Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_7180
help
Support for the LPASS(Low Power Audio Subsystem) core clock controller
@@ -533,6 +572,7 @@ config SC_LPASS_CORECC_7180
config SC_LPASS_CORECC_7280
tristate "SC7280 LPASS Core & Audio Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_7280
select QCOM_GDSC
help
@@ -543,6 +583,7 @@ config SC_LPASS_CORECC_7280
config SC_MSS_7180
tristate "SC7180 Modem Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_7180
help
Support for the Modem Subsystem clock controller on Qualcomm
@@ -552,6 +593,7 @@ config SC_MSS_7180
config SC_VIDEOCC_7180
tristate "SC7180 Video Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_7180
help
Support for the video clock controller on SC7180 devices.
@@ -560,6 +602,7 @@ config SC_VIDEOCC_7180
config SC_VIDEOCC_7280
tristate "SC7280 Video Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SC_GCC_7280
help
Support for the video clock controller on SC7280 devices.
@@ -568,6 +611,7 @@ config SC_VIDEOCC_7280
config SDM_CAMCC_845
tristate "SDM845 Camera Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SDM_GCC_845
help
Support for the camera clock controller on SDM845 devices.
@@ -575,6 +619,7 @@ config SDM_CAMCC_845
config SDM_GCC_660
tristate "SDM660 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on SDM660 devices.
@@ -583,6 +628,7 @@ config SDM_GCC_660
config SDM_MMCC_660
tristate "SDM660 Multimedia Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SDM_GCC_660
select QCOM_GDSC
help
@@ -592,6 +638,7 @@ config SDM_MMCC_660
config SDM_GPUCC_660
tristate "SDM660 Graphics Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SDM_GCC_660
select QCOM_GDSC
help
@@ -623,6 +670,7 @@ config QDU_GCC_1000
config SDM_GCC_845
tristate "SDM845/SDM670 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on SDM845 and SDM670 devices.
@@ -631,6 +679,7 @@ config SDM_GCC_845
config SDM_GPUCC_845
tristate "SDM845 Graphics Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SDM_GCC_845
help
Support for the graphics clock controller on SDM845 devices.
@@ -639,6 +688,7 @@ config SDM_GPUCC_845
config SDM_VIDEOCC_845
tristate "SDM845 Video Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SDM_GCC_845
select QCOM_GDSC
help
@@ -648,6 +698,7 @@ config SDM_VIDEOCC_845
config SDM_DISPCC_845
tristate "SDM845 Display Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SDM_GCC_845
help
Support for the display clock controller on Qualcomm Technologies, Inc
@@ -657,6 +708,7 @@ config SDM_DISPCC_845
config SDM_LPASSCC_845
tristate "SDM845 Low Power Audio Subsystem (LPAAS) Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SDM_GCC_845
help
Support for the LPASS clock controller on SDM845 devices.
@@ -665,6 +717,7 @@ config SDM_LPASSCC_845
config SDX_GCC_55
tristate "SDX55 Global Clock Controller"
+ depends on ARM || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on SDX55 devices.
@@ -673,14 +726,24 @@ config SDX_GCC_55
config SDX_GCC_65
tristate "SDX65 Global Clock Controller"
+ depends on ARM || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on SDX65 devices.
Say Y if you want to use peripheral devices such as UART,
SPI, I2C, USB, SD/UFS, PCIe etc.
+config SDX_GCC_75
+ tristate "SDX75 Global Clock Controller"
+ select QCOM_GDSC
+ help
+ Support for the global clock controller on SDX75 devices.
+ Say Y if you want to use peripheral devices such as UART,
+ SPI, I2C, USB, SD/eMMC, PCIe etc.
+
config SM_CAMCC_6350
tristate "SM6350 Camera Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SM_GCC_6350
help
Support for the camera clock controller on SM6350 devices.
@@ -688,6 +751,7 @@ config SM_CAMCC_6350
config SM_CAMCC_8250
tristate "SM8250 Camera Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SM_GCC_8250
help
Support for the camera clock controller on SM8250 devices.
@@ -695,6 +759,7 @@ config SM_CAMCC_8250
config SM_CAMCC_8450
tristate "SM8450 Camera Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SM_GCC_8450
help
Support for the camera clock controller on SM8450 devices.
@@ -702,6 +767,7 @@ config SM_CAMCC_8450
config SM_DISPCC_6115
tristate "SM6115 Display Clock Controller"
+ depends on ARM64 || COMPILE_TEST
depends on SM_GCC_6115
help
Support for the display clock controller on Qualcomm Technologies, Inc
@@ -711,6 +777,7 @@ config SM_DISPCC_6115
config SM_DISPCC_6125
tristate "SM6125 Display Clock Controller"
+ depends on ARM64 || COMPILE_TEST
depends on SM_GCC_6125
help
Support for the display clock controller on Qualcomm Technologies, Inc
@@ -720,6 +787,7 @@ config SM_DISPCC_6125
config SM_DISPCC_8250
tristate "SM8150/SM8250/SM8350 Display Clock Controller"
+ depends on ARM64 || COMPILE_TEST
depends on SM_GCC_8150 || SM_GCC_8250 || SM_GCC_8350
help
Support for the display clock controller on Qualcomm Technologies, Inc
@@ -729,6 +797,7 @@ config SM_DISPCC_8250
config SM_DISPCC_6350
tristate "SM6350 Display Clock Controller"
+ depends on ARM64 || COMPILE_TEST
depends on SM_GCC_6350
help
Support for the display clock controller on Qualcomm Technologies, Inc
@@ -738,6 +807,7 @@ config SM_DISPCC_6350
config SM_DISPCC_6375
tristate "SM6375 Display Clock Controller"
+ depends on ARM64 || COMPILE_TEST
depends on SM_GCC_6375
help
Support for the display clock controller on Qualcomm Technologies, Inc
@@ -747,6 +817,7 @@ config SM_DISPCC_6375
config SM_DISPCC_8450
tristate "SM8450 Display Clock Controller"
+ depends on ARM64 || COMPILE_TEST
depends on SM_GCC_8450
help
Support for the display clock controller on Qualcomm Technologies, Inc
@@ -756,6 +827,7 @@ config SM_DISPCC_8450
config SM_DISPCC_8550
tristate "SM8550 Display Clock Controller"
+ depends on ARM64 || COMPILE_TEST
depends on SM_GCC_8550
help
Support for the display clock controller on Qualcomm Technologies, Inc
@@ -765,6 +837,7 @@ config SM_DISPCC_8550
config SM_GCC_6115
tristate "SM6115 and SM4250 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on SM6115 and SM4250 devices.
@@ -773,6 +846,7 @@ config SM_GCC_6115
config SM_GCC_6125
tristate "SM6125 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
help
Support for the global clock controller on SM6125 devices.
Say Y if you want to use peripheral devices such as UART,
@@ -780,6 +854,7 @@ config SM_GCC_6125
config SM_GCC_6350
tristate "SM6350 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on SM6350 devices.
@@ -788,6 +863,7 @@ config SM_GCC_6350
config SM_GCC_6375
tristate "SM6375 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on SM6375 devices.
@@ -804,6 +880,7 @@ config SM_GCC_7150
config SM_GCC_8150
tristate "SM8150 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
help
Support for the global clock controller on SM8150 devices.
Say Y if you want to use peripheral devices such as UART,
@@ -811,6 +888,7 @@ config SM_GCC_8150
config SM_GCC_8250
tristate "SM8250 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on SM8250 devices.
@@ -819,6 +897,7 @@ config SM_GCC_8250
config SM_GCC_8350
tristate "SM8350 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on SM8350 devices.
@@ -827,6 +906,7 @@ config SM_GCC_8350
config SM_GCC_8450
tristate "SM8450 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on SM8450 devices.
@@ -835,6 +915,7 @@ config SM_GCC_8450
config SM_GCC_8550
tristate "SM8550 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select QCOM_GDSC
help
Support for the global clock controller on SM8550 devices.
@@ -870,6 +951,7 @@ config SM_GPUCC_6375
config SM_GPUCC_6350
tristate "SM6350 Graphics Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SM_GCC_6350
help
Support for the graphics clock controller on SM6350 devices.
@@ -878,6 +960,7 @@ config SM_GPUCC_6350
config SM_GPUCC_8150
tristate "SM8150 Graphics Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SM_GCC_8150
help
Support for the graphics clock controller on SM8150 devices.
@@ -886,6 +969,7 @@ config SM_GPUCC_8150
config SM_GPUCC_8250
tristate "SM8250 Graphics Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SM_GCC_8250
help
Support for the graphics clock controller on SM8250 devices.
@@ -894,14 +978,32 @@ config SM_GPUCC_8250
config SM_GPUCC_8350
tristate "SM8350 Graphics Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SM_GCC_8350
help
Support for the graphics clock controller on SM8350 devices.
Say Y if you want to support graphics controller devices and
functionality such as 3D graphics.
+config SM_GPUCC_8450
+ tristate "SM8450 Graphics Clock Controller"
+ select SM_GCC_8450
+ help
+ Support for the graphics clock controller on SM8450 devices.
+ Say Y if you want to support graphics controller devices and
+ functionality such as 3D graphics.
+
+config SM_GPUCC_8550
+ tristate "SM8550 Graphics Clock Controller"
+ select SM_GCC_8550
+ help
+ Support for the graphics clock controller on SM8550 devices.
+ Say Y if you want to support graphics controller devices and
+ functionality such as 3D graphics.
+
config SM_TCSRCC_8550
tristate "SM8550 TCSR Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select QCOM_GDSC
help
Support for the TCSR clock controller on SM8550 devices.
@@ -909,6 +1011,7 @@ config SM_TCSRCC_8550
config SM_VIDEOCC_8150
tristate "SM8150 Video Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SM_GCC_8150
select QCOM_GDSC
help
@@ -918,6 +1021,7 @@ config SM_VIDEOCC_8150
config SM_VIDEOCC_8250
tristate "SM8250 Video Clock Controller"
+ depends on ARM64 || COMPILE_TEST
select SM_GCC_8250
select QCOM_GDSC
help
@@ -925,6 +1029,25 @@ config SM_VIDEOCC_8250
Say Y if you want to support video devices and functionality such as
video encode and decode.
+config SM_VIDEOCC_8350
+ tristate "SM8350 Video Clock Controller"
+ select SM_GCC_8350
+ select QCOM_GDSC
+ help
+ Support for the video clock controller on SM8350 devices.
+ Say Y if you want to support video devices and functionality such as
+ video encode and decode.
+
+config SM_VIDEOCC_8550
+ tristate "SM8550 Video Clock Controller"
+ select SM_GCC_8550
+ select QCOM_GDSC
+ help
+ Support for the video clock controller on Qualcomm Technologies, Inc.
+ SM8550 devices.
+ Say Y if you want to support video devices and functionality such as
+ video encode/decode.
+
config SPMI_PMIC_CLKDIV
tristate "SPMI PMIC clkdiv Support"
depends on SPMI || COMPILE_TEST
@@ -958,8 +1081,18 @@ config KRAITCC
config CLK_GFM_LPASS_SM8250
tristate "SM8250 GFM LPASS Clocks"
+ depends on ARM64 || COMPILE_TEST
help
Support for the Glitch Free Mux (GFM) Low power audio
subsystem (LPASS) clocks found on SM8250 SoCs.
+config SM_VIDEOCC_8450
+ tristate "SM8450 Video Clock Controller"
+ select SM_GCC_8450
+ select QCOM_GDSC
+ help
+ Support for the video clock controller on Qualcomm Technologies, Inc.
+ SM8450 devices.
+ Say Y if you want to support video devices and functionality such as
+ video encode/decode.
endif
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 9ff4c373ad95..e6e294274c35 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_SC_GPUCC_7180) += gpucc-sc7180.o
obj-$(CONFIG_SC_GPUCC_7280) += gpucc-sc7280.o
obj-$(CONFIG_SC_GPUCC_8280XP) += gpucc-sc8280xp.o
obj-$(CONFIG_SC_LPASSCC_7280) += lpasscc-sc7280.o
+obj-$(CONFIG_SC_LPASSCC_8280XP) += lpasscc-sc8280xp.o
obj-$(CONFIG_SC_LPASS_CORECC_7180) += lpasscorecc-sc7180.o
obj-$(CONFIG_SC_LPASS_CORECC_7280) += lpasscorecc-sc7280.o lpassaudiocc-sc7280.o
obj-$(CONFIG_SC_MSS_7180) += mss-sc7180.o
@@ -97,6 +98,7 @@ obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o
obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
obj-$(CONFIG_SDX_GCC_55) += gcc-sdx55.o
obj-$(CONFIG_SDX_GCC_65) += gcc-sdx65.o
+obj-$(CONFIG_SDX_GCC_75) += gcc-sdx75.o
obj-$(CONFIG_SM_CAMCC_6350) += camcc-sm6350.o
obj-$(CONFIG_SM_CAMCC_8250) += camcc-sm8250.o
obj-$(CONFIG_SM_CAMCC_8450) += camcc-sm8450.o
@@ -124,9 +126,14 @@ obj-$(CONFIG_SM_GPUCC_6375) += gpucc-sm6375.o
obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o
obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o
obj-$(CONFIG_SM_GPUCC_8350) += gpucc-sm8350.o
+obj-$(CONFIG_SM_GPUCC_8450) += gpucc-sm8450.o
+obj-$(CONFIG_SM_GPUCC_8550) += gpucc-sm8550.o
obj-$(CONFIG_SM_TCSRCC_8550) += tcsrcc-sm8550.o
obj-$(CONFIG_SM_VIDEOCC_8150) += videocc-sm8150.o
obj-$(CONFIG_SM_VIDEOCC_8250) += videocc-sm8250.o
+obj-$(CONFIG_SM_VIDEOCC_8350) += videocc-sm8350.o
+obj-$(CONFIG_SM_VIDEOCC_8450) += videocc-sm8450.o
+obj-$(CONFIG_SM_VIDEOCC_8550) += videocc-sm8550.o
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c
index cf4f0d340cbf..ce28d882ee78 100644
--- a/drivers/clk/qcom/apss-ipq-pll.c
+++ b/drivers/clk/qcom/apss-ipq-pll.c
@@ -111,6 +111,18 @@ static const struct alpha_pll_config ipq8074_pll_config = {
.test_ctl_hi_val = 0x4000,
};
+static const struct alpha_pll_config ipq9574_pll_config = {
+ .l = 0x3b,
+ .config_ctl_val = 0x200d4828,
+ .config_ctl_hi_val = 0x6,
+ .early_output_mask = BIT(3),
+ .aux2_output_mask = BIT(2),
+ .aux_output_mask = BIT(1),
+ .main_output_mask = BIT(0),
+ .test_ctl_val = 0x0,
+ .test_ctl_hi_val = 0x4000,
+};
+
struct apss_pll_data {
int pll_type;
struct clk_alpha_pll *pll;
@@ -135,6 +147,12 @@ static struct apss_pll_data ipq6018_pll_data = {
.pll_config = &ipq6018_pll_config,
};
+static struct apss_pll_data ipq9574_pll_data = {
+ .pll_type = CLK_ALPHA_PLL_TYPE_HUAYRA,
+ .pll = &ipq_pll_huayra,
+ .pll_config = &ipq9574_pll_config,
+};
+
static const struct regmap_config ipq_pll_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -180,6 +198,7 @@ static const struct of_device_id apss_ipq_pll_match_table[] = {
{ .compatible = "qcom,ipq5332-a53pll", .data = &ipq5332_pll_data },
{ .compatible = "qcom,ipq6018-a53pll", .data = &ipq6018_pll_data },
{ .compatible = "qcom,ipq8074-a53pll", .data = &ipq8074_pll_data },
+ { .compatible = "qcom,ipq9574-a73pll", .data = &ipq9574_pll_data },
{ }
};
MODULE_DEVICE_TABLE(of, apss_ipq_pll_match_table);
diff --git a/drivers/clk/qcom/camcc-sc7180.c b/drivers/clk/qcom/camcc-sc7180.c
index e2b4804695f3..8a4ba7a19ed1 100644
--- a/drivers/clk/qcom/camcc-sc7180.c
+++ b/drivers/clk/qcom/camcc-sc7180.c
@@ -1480,12 +1480,21 @@ static struct clk_branch cam_cc_sys_tmr_clk = {
},
};
+static struct gdsc titan_top_gdsc = {
+ .gdscr = 0xb134,
+ .pd = {
+ .name = "titan_top_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
static struct gdsc bps_gdsc = {
.gdscr = 0x6004,
.pd = {
.name = "bps_gdsc",
},
.pwrsts = PWRSTS_OFF_ON,
+ .parent = &titan_top_gdsc.pd,
.flags = HW_CTRL,
};
@@ -1495,6 +1504,7 @@ static struct gdsc ife_0_gdsc = {
.name = "ife_0_gdsc",
},
.pwrsts = PWRSTS_OFF_ON,
+ .parent = &titan_top_gdsc.pd,
};
static struct gdsc ife_1_gdsc = {
@@ -1503,6 +1513,7 @@ static struct gdsc ife_1_gdsc = {
.name = "ife_1_gdsc",
},
.pwrsts = PWRSTS_OFF_ON,
+ .parent = &titan_top_gdsc.pd,
};
static struct gdsc ipe_0_gdsc = {
@@ -1512,15 +1523,9 @@ static struct gdsc ipe_0_gdsc = {
},
.pwrsts = PWRSTS_OFF_ON,
.flags = HW_CTRL,
+ .parent = &titan_top_gdsc.pd,
};
-static struct gdsc titan_top_gdsc = {
- .gdscr = 0xb134,
- .pd = {
- .name = "titan_top_gdsc",
- },
- .pwrsts = PWRSTS_OFF_ON,
-};
static struct clk_hw *cam_cc_sc7180_hws[] = {
[CAM_CC_PLL2_OUT_EARLY] = &cam_cc_pll2_out_early.hw,
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index b9f6535a7ba7..e4ef645f65d1 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -55,6 +55,7 @@
#define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL])
#define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U])
#define PLL_TEST_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U1])
+#define PLL_TEST_CTL_U2(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U2])
#define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS])
#define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE])
#define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC])
@@ -383,10 +384,21 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val);
- clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),
- config->test_ctl_val);
- clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll),
- config->test_ctl_hi_val);
+ if (config->test_ctl_mask)
+ regmap_update_bits(regmap, PLL_TEST_CTL(pll),
+ config->test_ctl_mask,
+ config->test_ctl_val);
+ else
+ clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),
+ config->test_ctl_val);
+
+ if (config->test_ctl_hi_mask)
+ regmap_update_bits(regmap, PLL_TEST_CTL_U(pll),
+ config->test_ctl_hi_mask,
+ config->test_ctl_hi_val);
+ else
+ clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll),
+ config->test_ctl_hi_val);
if (pll->flags & SUPPORTS_FSM_MODE)
qcom_pll_set_fsm_mode(regmap, PLL_MODE(pll), 6, 0);
@@ -2096,6 +2108,7 @@ void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regma
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val);
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val);
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val);
+ clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U2(pll), config->test_ctl_hi2_val);
/* Disable PLL output */
regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index d07b17186b90..e4bd863027ab 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -123,8 +123,11 @@ struct alpha_pll_config {
u32 user_ctl_hi_val;
u32 user_ctl_hi1_val;
u32 test_ctl_val;
+ u32 test_ctl_mask;
u32 test_ctl_hi_val;
+ u32 test_ctl_hi_mask;
u32 test_ctl_hi1_val;
+ u32 test_ctl_hi2_val;
u32 main_output_mask;
u32 aux_output_mask;
u32 aux2_output_mask;
diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c
index ca896ebf7e1b..fc4735f74f0f 100644
--- a/drivers/clk/qcom/clk-branch.c
+++ b/drivers/clk/qcom/clk-branch.c
@@ -43,6 +43,7 @@ static bool clk_branch2_check_halt(const struct clk_branch *br, bool enabling)
{
u32 val;
u32 mask;
+ bool invert = (br->halt_check == BRANCH_HALT_ENABLE);
mask = CBCR_NOC_FSM_STATUS;
mask |= CBCR_CLK_OFF;
@@ -51,11 +52,10 @@ static bool clk_branch2_check_halt(const struct clk_branch *br, bool enabling)
if (enabling) {
val &= mask;
- return (val & CBCR_CLK_OFF) == 0 ||
+ return (val & CBCR_CLK_OFF) == (invert ? CBCR_CLK_OFF : 0) ||
FIELD_GET(CBCR_NOC_FSM_STATUS, val) == FSM_STATUS_ON;
- } else {
- return val & CBCR_CLK_OFF;
}
+ return (val & CBCR_CLK_OFF) == (invert ? 0 : CBCR_CLK_OFF);
}
static int clk_branch_wait(const struct clk_branch *br, bool enabling,
diff --git a/drivers/clk/qcom/clk-cbf-8996.c b/drivers/clk/qcom/clk-cbf-8996.c
index cfd567636f4e..1e23b734abb3 100644
--- a/drivers/clk/qcom/clk-cbf-8996.c
+++ b/drivers/clk/qcom/clk-cbf-8996.c
@@ -5,11 +5,15 @@
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/interconnect-clk.h>
+#include <linux/interconnect-provider.h>
#include <linux/of.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <dt-bindings/interconnect/qcom,msm8996-cbf.h>
+
#include "clk-alpha-pll.h"
#include "clk-regmap.h"
@@ -223,6 +227,49 @@ static const struct regmap_config cbf_msm8996_regmap_config = {
.val_format_endian = REGMAP_ENDIAN_LITTLE,
};
+#ifdef CONFIG_INTERCONNECT
+
+/* Random ID that doesn't clash with main qnoc and OSM */
+#define CBF_MASTER_NODE 2000
+
+static int qcom_msm8996_cbf_icc_register(struct platform_device *pdev, struct clk_hw *cbf_hw)
+{
+ struct device *dev = &pdev->dev;
+ struct clk *clk = devm_clk_hw_get_clk(dev, cbf_hw, "cbf");
+ const struct icc_clk_data data[] = {
+ { .clk = clk, .name = "cbf", },
+ };
+ struct icc_provider *provider;
+
+ provider = icc_clk_register(dev, CBF_MASTER_NODE, ARRAY_SIZE(data), data);
+ if (IS_ERR(provider))
+ return PTR_ERR(provider);
+
+ platform_set_drvdata(pdev, provider);
+
+ return 0;
+}
+
+static int qcom_msm8996_cbf_icc_remove(struct platform_device *pdev)
+{
+ struct icc_provider *provider = platform_get_drvdata(pdev);
+
+ icc_clk_unregister(provider);
+
+ return 0;
+}
+#define qcom_msm8996_cbf_icc_sync_state icc_sync_state
+#else
+static int qcom_msm8996_cbf_icc_register(struct platform_device *pdev, struct clk_hw *cbf_hw)
+{
+ dev_warn(&pdev->dev, "CONFIG_INTERCONNECT is disabled, CBF clock is fixed\n");
+
+ return 0;
+}
+#define qcom_msm8996_cbf_icc_remove(pdev) (0)
+#define qcom_msm8996_cbf_icc_sync_state NULL
+#endif
+
static int qcom_msm8996_cbf_probe(struct platform_device *pdev)
{
void __iomem *base;
@@ -281,7 +328,16 @@ static int qcom_msm8996_cbf_probe(struct platform_device *pdev)
if (ret)
return ret;
- return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &cbf_mux.clkr.hw);
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &cbf_mux.clkr.hw);
+ if (ret)
+ return ret;
+
+ return qcom_msm8996_cbf_icc_register(pdev, &cbf_mux.clkr.hw);
+}
+
+static int qcom_msm8996_cbf_remove(struct platform_device *pdev)
+{
+ return qcom_msm8996_cbf_icc_remove(pdev);
}
static const struct of_device_id qcom_msm8996_cbf_match_table[] = {
@@ -292,9 +348,11 @@ MODULE_DEVICE_TABLE(of, qcom_msm8996_cbf_match_table);
static struct platform_driver qcom_msm8996_cbf_driver = {
.probe = qcom_msm8996_cbf_probe,
+ .remove = qcom_msm8996_cbf_remove,
.driver = {
.name = "qcom-msm8996-cbf",
.of_match_table = qcom_msm8996_cbf_match_table,
+ .sync_state = qcom_msm8996_cbf_icc_sync_state,
},
};
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index 01581f4d2c39..e6d84c8c7989 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -141,6 +141,7 @@ extern const struct clk_ops clk_dyn_rcg_ops;
* @clkr: regmap clock handle
* @cfg_off: defines the cfg register offset from the CMD_RCGR + CFG_REG
* @parked_cfg: cached value of the CFG register for parked RCGs
+ * @hw_clk_ctrl: whether to enable hardware clock control
*/
struct clk_rcg2 {
u32 cmd_rcgr;
@@ -152,6 +153,7 @@ struct clk_rcg2 {
struct clk_regmap clkr;
u8 cfg_off;
u32 parked_cfg;
+ bool hw_clk_ctrl;
};
#define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 76551534f10d..e22baf3a7112 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -325,6 +325,8 @@ static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f,
cfg |= rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
if (rcg->mnd_width && f->n && (f->m != f->n))
cfg |= CFG_MODE_DUAL_EDGE;
+ if (rcg->hw_clk_ctrl)
+ cfg |= CFG_HW_CLK_CTRL_MASK;
*_cfg &= ~mask;
*_cfg |= cfg;
diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c
index 45ee370f3307..86572570bc54 100644
--- a/drivers/clk/qcom/clk-rpmh.c
+++ b/drivers/clk/qcom/clk-rpmh.c
@@ -700,6 +700,24 @@ static const struct clk_rpmh_desc clk_rpmh_qdu1000 = {
.num_clks = ARRAY_SIZE(qdu1000_rpmh_clocks),
};
+static struct clk_hw *sdx75_rpmh_clocks[] = {
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div4.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div4_ao.hw,
+ [RPMH_RF_CLK1] = &clk_rpmh_rf_clk1_a.hw,
+ [RPMH_RF_CLK1_A] = &clk_rpmh_rf_clk1_a_ao.hw,
+ [RPMH_RF_CLK2] = &clk_rpmh_rf_clk2_a.hw,
+ [RPMH_RF_CLK2_A] = &clk_rpmh_rf_clk2_a_ao.hw,
+ [RPMH_RF_CLK3] = &clk_rpmh_rf_clk3_a.hw,
+ [RPMH_RF_CLK3_A] = &clk_rpmh_rf_clk3_a_ao.hw,
+ [RPMH_QPIC_CLK] = &clk_rpmh_qpic_clk.hw,
+ [RPMH_IPA_CLK] = &clk_rpmh_ipa.hw,
+};
+
+static const struct clk_rpmh_desc clk_rpmh_sdx75 = {
+ .clks = sdx75_rpmh_clocks,
+ .num_clks = ARRAY_SIZE(sdx75_rpmh_clocks),
+};
+
static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
void *data)
{
@@ -792,6 +810,7 @@ static const struct of_device_id clk_rpmh_match_table[] = {
{ .compatible = "qcom,sdm670-rpmh-clk", .data = &clk_rpmh_sdm670},
{ .compatible = "qcom,sdx55-rpmh-clk", .data = &clk_rpmh_sdx55},
{ .compatible = "qcom,sdx65-rpmh-clk", .data = &clk_rpmh_sdx65},
+ { .compatible = "qcom,sdx75-rpmh-clk", .data = &clk_rpmh_sdx75},
{ .compatible = "qcom,sm6350-rpmh-clk", .data = &clk_rpmh_sm6350},
{ .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150},
{ .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250},
diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
index 887b945a6fb7..e4de74b68797 100644
--- a/drivers/clk/qcom/clk-smd-rpm.c
+++ b/drivers/clk/qcom/clk-smd-rpm.c
@@ -67,7 +67,7 @@
type, r_id, key)
#define __DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(_prefix, _name, _active,\
- type, r_id, r, key) \
+ type, r_id, r, key, ao_flags) \
static struct clk_smd_rpm clk_smd_rpm_##_prefix##_active; \
static struct clk_smd_rpm clk_smd_rpm_##_prefix##_name = { \
.rpm_res_type = (type), \
@@ -102,12 +102,13 @@
.name = "xo_board", \
}, \
.num_parents = 1, \
+ .flags = (ao_flags), \
}, \
}
#define __DEFINE_CLK_SMD_RPM_BRANCH(_name, _active, type, r_id, r, key) \
__DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(/* empty */, \
- _name, _active, type, r_id, r, key)
+ _name, _active, type, r_id, r, key, 0)
#define DEFINE_CLK_SMD_RPM(_name, type, r_id) \
__DEFINE_CLK_SMD_RPM(_name##_clk, _name##_a_clk, \
@@ -126,12 +127,12 @@
#define DEFINE_CLK_SMD_RPM_BRANCH(_name, type, r_id, r) \
__DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(branch_, \
_name##_clk, _name##_a_clk, \
- type, r_id, r, QCOM_RPM_SMD_KEY_ENABLE)
+ type, r_id, r, QCOM_RPM_SMD_KEY_ENABLE, 0)
-#define DEFINE_CLK_SMD_RPM_BRANCH_A(_name, type, r_id, r) \
+#define DEFINE_CLK_SMD_RPM_BRANCH_A(_name, type, r_id, r, ao_flags) \
__DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(branch_, \
_name, _name##_a, type, \
- r_id, r, QCOM_RPM_SMD_KEY_ENABLE)
+ r_id, r, QCOM_RPM_SMD_KEY_ENABLE, ao_flags)
#define DEFINE_CLK_SMD_RPM_QDSS(_name, type, r_id) \
__DEFINE_CLK_SMD_RPM(_name##_clk, _name##_a_clk, \
@@ -146,7 +147,7 @@
__DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(_prefix, \
_name, _name##_a, \
QCOM_SMD_RPM_CLK_BUF_A, r_id, r, \
- QCOM_RPM_KEY_SOFTWARE_ENABLE)
+ QCOM_RPM_KEY_SOFTWARE_ENABLE, 0)
#define DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(_name, r_id, r) \
DEFINE_CLK_SMD_RPM_XO_BUFFER(_name, r_id, r); \
@@ -156,6 +157,8 @@
#define to_clk_smd_rpm(_hw) container_of(_hw, struct clk_smd_rpm, hw)
+static struct qcom_smd_rpm *rpmcc_smd_rpm;
+
struct clk_smd_rpm {
const int rpm_res_type;
const int rpm_key;
@@ -166,7 +169,6 @@ struct clk_smd_rpm {
struct clk_smd_rpm *peer;
struct clk_hw hw;
unsigned long rate;
- struct qcom_smd_rpm *rpm;
};
struct clk_smd_rpm_req {
@@ -178,6 +180,7 @@ struct clk_smd_rpm_req {
struct rpm_smd_clk_desc {
struct clk_smd_rpm **clks;
size_t num_clks;
+ bool scaling_before_handover;
};
static DEFINE_MUTEX(rpm_smd_clk_lock);
@@ -191,12 +194,12 @@ static int clk_smd_rpm_handoff(struct clk_smd_rpm *r)
.value = cpu_to_le32(r->branch ? 1 : INT_MAX),
};
- ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+ ret = qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE,
r->rpm_res_type, r->rpm_clk_id, &req,
sizeof(req));
if (ret)
return ret;
- ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE,
+ ret = qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_SLEEP_STATE,
r->rpm_res_type, r->rpm_clk_id, &req,
sizeof(req));
if (ret)
@@ -214,7 +217,7 @@ static int clk_smd_rpm_set_rate_active(struct clk_smd_rpm *r,
.value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */
};
- return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+ return qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE,
r->rpm_res_type, r->rpm_clk_id, &req,
sizeof(req));
}
@@ -228,7 +231,7 @@ static int clk_smd_rpm_set_rate_sleep(struct clk_smd_rpm *r,
.value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */
};
- return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE,
+ return qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_SLEEP_STATE,
r->rpm_res_type, r->rpm_clk_id, &req,
sizeof(req));
}
@@ -395,7 +398,7 @@ static unsigned long clk_smd_rpm_recalc_rate(struct clk_hw *hw,
return r->rate;
}
-static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm)
+static int clk_smd_rpm_enable_scaling(void)
{
int ret;
struct clk_smd_rpm_req req = {
@@ -404,7 +407,7 @@ static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm)
.value = cpu_to_le32(1),
};
- ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_SLEEP_STATE,
+ ret = qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_SLEEP_STATE,
QCOM_SMD_RPM_MISC_CLK,
QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req));
if (ret) {
@@ -412,7 +415,7 @@ static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm)
return ret;
}
- ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+ ret = qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE,
QCOM_SMD_RPM_MISC_CLK,
QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req));
if (ret) {
@@ -438,10 +441,11 @@ static const struct clk_ops clk_smd_rpm_branch_ops = {
.recalc_rate = clk_smd_rpm_recalc_rate,
};
-DEFINE_CLK_SMD_RPM_BRANCH_A(bi_tcxo, QCOM_SMD_RPM_MISC_CLK, 0, 19200000);
+/* Disabling BI_TCXO_AO could gate the root clock source of the entire system. */
+DEFINE_CLK_SMD_RPM_BRANCH_A(bi_tcxo, QCOM_SMD_RPM_MISC_CLK, 0, 19200000, CLK_IS_CRITICAL);
DEFINE_CLK_SMD_RPM_BRANCH(qdss, QCOM_SMD_RPM_MISC_CLK, 1, 19200000);
DEFINE_CLK_SMD_RPM_QDSS(qdss, QCOM_SMD_RPM_MISC_CLK, 1);
-DEFINE_CLK_SMD_RPM_BRANCH_A(bimc_freq_log, QCOM_SMD_RPM_MISC_CLK, 4, 1);
+DEFINE_CLK_SMD_RPM_BRANCH_A(bimc_freq_log, QCOM_SMD_RPM_MISC_CLK, 4, 1, 0);
DEFINE_CLK_SMD_RPM_BRANCH(mss_cfg_ahb, QCOM_SMD_RPM_MCFG_CLK, 0, 19200000);
@@ -693,6 +697,7 @@ static struct clk_smd_rpm *msm8974_clks[] = {
static const struct rpm_smd_clk_desc rpm_clk_msm8974 = {
.clks = msm8974_clks,
.num_clks = ARRAY_SIZE(msm8974_clks),
+ .scaling_before_handover = true,
};
static struct clk_smd_rpm *msm8976_clks[] = {
@@ -1301,12 +1306,11 @@ static int rpm_smd_clk_probe(struct platform_device *pdev)
{
int ret;
size_t num_clks, i;
- struct qcom_smd_rpm *rpm;
struct clk_smd_rpm **rpm_smd_clks;
const struct rpm_smd_clk_desc *desc;
- rpm = dev_get_drvdata(pdev->dev.parent);
- if (!rpm) {
+ rpmcc_smd_rpm = dev_get_drvdata(pdev->dev.parent);
+ if (!rpmcc_smd_rpm) {
dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
return -ENODEV;
}
@@ -1318,20 +1322,26 @@ static int rpm_smd_clk_probe(struct platform_device *pdev)
rpm_smd_clks = desc->clks;
num_clks = desc->num_clks;
+ if (desc->scaling_before_handover) {
+ ret = clk_smd_rpm_enable_scaling();
+ if (ret)
+ goto err;
+ }
+
for (i = 0; i < num_clks; i++) {
if (!rpm_smd_clks[i])
continue;
- rpm_smd_clks[i]->rpm = rpm;
-
ret = clk_smd_rpm_handoff(rpm_smd_clks[i]);
if (ret)
goto err;
}
- ret = clk_smd_rpm_enable_scaling(rpm);
- if (ret)
- goto err;
+ if (!desc->scaling_before_handover) {
+ ret = clk_smd_rpm_enable_scaling();
+ if (ret)
+ goto err;
+ }
for (i = 0; i < num_clks; i++) {
if (!rpm_smd_clks[i])
diff --git a/drivers/clk/qcom/dispcc-qcm2290.c b/drivers/clk/qcom/dispcc-qcm2290.c
index e9cfe41c0442..44dd5cfcc150 100644
--- a/drivers/clk/qcom/dispcc-qcm2290.c
+++ b/drivers/clk/qcom/dispcc-qcm2290.c
@@ -24,9 +24,11 @@
enum {
P_BI_TCXO,
+ P_BI_TCXO_AO,
P_DISP_CC_PLL0_OUT_MAIN,
P_DSI0_PHY_PLL_OUT_BYTECLK,
P_DSI0_PHY_PLL_OUT_DSICLK,
+ P_GPLL0_OUT_DIV,
P_GPLL0_OUT_MAIN,
P_SLEEP_CLK,
};
@@ -82,8 +84,8 @@ static const struct clk_parent_data disp_cc_parent_data_1[] = {
};
static const struct parent_map disp_cc_parent_map_2[] = {
- { P_BI_TCXO, 0 },
- { P_GPLL0_OUT_MAIN, 4 },
+ { P_BI_TCXO_AO, 0 },
+ { P_GPLL0_OUT_DIV, 4 },
};
static const struct clk_parent_data disp_cc_parent_data_2[] = {
@@ -151,9 +153,9 @@ static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = {
};
static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = {
- F(19200000, P_BI_TCXO, 1, 0, 0),
- F(37500000, P_GPLL0_OUT_MAIN, 8, 0, 0),
- F(75000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
+ F(19200000, P_BI_TCXO_AO, 1, 0, 0),
+ F(37500000, P_GPLL0_OUT_DIV, 8, 0, 0),
+ F(75000000, P_GPLL0_OUT_DIV, 4, 0, 0),
{ }
};
diff --git a/drivers/clk/qcom/gcc-ipq5332.c b/drivers/clk/qcom/gcc-ipq5332.c
index bdb4a0a11d07..a75ab88ed14c 100644
--- a/drivers/clk/qcom/gcc-ipq5332.c
+++ b/drivers/clk/qcom/gcc-ipq5332.c
@@ -20,8 +20,8 @@
#include "reset.h"
enum {
- DT_SLEEP_CLK,
DT_XO,
+ DT_SLEEP_CLK,
DT_PCIE_2LANE_PHY_PIPE_CLK,
DT_PCIE_2LANE_PHY_PIPE_CLK_X1,
DT_USB_PCIE_WRAPPER_PIPE_CLK,
@@ -366,7 +366,7 @@ static struct clk_rcg2 gcc_adss_pwm_clk_src = {
};
static const struct freq_tbl ftbl_gcc_apss_axi_clk_src[] = {
- F(480000000, P_GPLL4_OUT_MAIN, 2.5, 0, 0),
+ F(480000000, P_GPLL4_OUT_AUX, 2.5, 0, 0),
F(533333333, P_GPLL0_OUT_MAIN, 1.5, 0, 0),
{ }
};
@@ -963,7 +963,7 @@ static struct clk_rcg2 gcc_sdcc1_apps_clk_src = {
.name = "gcc_sdcc1_apps_clk_src",
.parent_data = gcc_parent_data_9,
.num_parents = ARRAY_SIZE(gcc_parent_data_9),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
diff --git a/drivers/clk/qcom/gcc-ipq6018.c b/drivers/clk/qcom/gcc-ipq6018.c
index 3f9c2f61a5d9..86b43175b042 100644
--- a/drivers/clk/qcom/gcc-ipq6018.c
+++ b/drivers/clk/qcom/gcc-ipq6018.c
@@ -26,8 +26,6 @@
#include "clk-regmap-mux.h"
#include "reset.h"
-#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
-
enum {
P_XO,
P_BIAS_PLL,
@@ -1654,7 +1652,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
.name = "sdcc1_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll2_gpll0_out_main_div2,
.num_parents = 4,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -4151,15 +4149,18 @@ static struct clk_branch gcc_dcc_clk = {
static const struct alpha_pll_config ubi32_pll_config = {
.l = 0x3e,
- .alpha = 0x57,
- .config_ctl_val = 0x240d6aa8,
- .config_ctl_hi_val = 0x3c2,
+ .alpha = 0x6667,
+ .config_ctl_val = 0x240d4828,
+ .config_ctl_hi_val = 0x6,
.main_output_mask = BIT(0),
.aux_output_mask = BIT(1),
.pre_div_val = 0x0,
.pre_div_mask = BIT(12),
.post_div_val = 0x0,
.post_div_mask = GENMASK(9, 8),
+ .alpha_en_mask = BIT(24),
+ .test_ctl_val = 0x1C0000C0,
+ .test_ctl_hi_val = 0x4000,
};
static const struct alpha_pll_config nss_crypto_pll_config = {
@@ -4517,24 +4518,24 @@ static const struct qcom_reset_map gcc_ipq6018_resets[] = {
[GCC_PCIE0_AHB_ARES] = { 0x75040, 5 },
[GCC_PCIE0_AXI_MASTER_STICKY_ARES] = { 0x75040, 6 },
[GCC_PCIE0_AXI_SLAVE_STICKY_ARES] = { 0x75040, 7 },
- [GCC_PPE_FULL_RESET] = { 0x68014, 0 },
- [GCC_UNIPHY0_SOFT_RESET] = { 0x56004, 0 },
+ [GCC_PPE_FULL_RESET] = { .reg = 0x68014, .bitmask = 0xf0000 },
+ [GCC_UNIPHY0_SOFT_RESET] = { .reg = 0x56004, .bitmask = 0x3ff2 },
[GCC_UNIPHY0_XPCS_RESET] = { 0x56004, 2 },
- [GCC_UNIPHY1_SOFT_RESET] = { 0x56104, 0 },
+ [GCC_UNIPHY1_SOFT_RESET] = { .reg = 0x56104, .bitmask = 0x32 },
[GCC_UNIPHY1_XPCS_RESET] = { 0x56104, 2 },
- [GCC_EDMA_HW_RESET] = { 0x68014, 0 },
- [GCC_NSSPORT1_RESET] = { 0x68014, 0 },
- [GCC_NSSPORT2_RESET] = { 0x68014, 0 },
- [GCC_NSSPORT3_RESET] = { 0x68014, 0 },
- [GCC_NSSPORT4_RESET] = { 0x68014, 0 },
- [GCC_NSSPORT5_RESET] = { 0x68014, 0 },
- [GCC_UNIPHY0_PORT1_ARES] = { 0x56004, 0 },
- [GCC_UNIPHY0_PORT2_ARES] = { 0x56004, 0 },
- [GCC_UNIPHY0_PORT3_ARES] = { 0x56004, 0 },
- [GCC_UNIPHY0_PORT4_ARES] = { 0x56004, 0 },
- [GCC_UNIPHY0_PORT5_ARES] = { 0x56004, 0 },
- [GCC_UNIPHY0_PORT_4_5_RESET] = { 0x56004, 0 },
- [GCC_UNIPHY0_PORT_4_RESET] = { 0x56004, 0 },
+ [GCC_EDMA_HW_RESET] = { .reg = 0x68014, .bitmask = 0x300000 },
+ [GCC_NSSPORT1_RESET] = { .reg = 0x68014, .bitmask = 0x1000003 },
+ [GCC_NSSPORT2_RESET] = { .reg = 0x68014, .bitmask = 0x200000c },
+ [GCC_NSSPORT3_RESET] = { .reg = 0x68014, .bitmask = 0x4000030 },
+ [GCC_NSSPORT4_RESET] = { .reg = 0x68014, .bitmask = 0x8000300 },
+ [GCC_NSSPORT5_RESET] = { .reg = 0x68014, .bitmask = 0x10000c00 },
+ [GCC_UNIPHY0_PORT1_ARES] = { .reg = 0x56004, .bitmask = 0x30 },
+ [GCC_UNIPHY0_PORT2_ARES] = { .reg = 0x56004, .bitmask = 0xc0 },
+ [GCC_UNIPHY0_PORT3_ARES] = { .reg = 0x56004, .bitmask = 0x300 },
+ [GCC_UNIPHY0_PORT4_ARES] = { .reg = 0x56004, .bitmask = 0xc00 },
+ [GCC_UNIPHY0_PORT5_ARES] = { .reg = 0x56004, .bitmask = 0x3000 },
+ [GCC_UNIPHY0_PORT_4_5_RESET] = { .reg = 0x56004, .bitmask = 0x3c02 },
+ [GCC_UNIPHY0_PORT_4_RESET] = { .reg = 0x56004, .bitmask = 0xc02 },
[GCC_LPASS_BCR] = {0x1F000, 0},
[GCC_UBI32_TBU_BCR] = {0x65000, 0},
[GCC_LPASS_TBU_BCR] = {0x6C000, 0},
diff --git a/drivers/clk/qcom/gcc-ipq9574.c b/drivers/clk/qcom/gcc-ipq9574.c
index b2a2d618a5ec..6914f962c893 100644
--- a/drivers/clk/qcom/gcc-ipq9574.c
+++ b/drivers/clk/qcom/gcc-ipq9574.c
@@ -3,24 +3,24 @@
* Copyright (c) 2023 The Linux Foundation. All rights reserved.
*/
+#include <linux/clk-provider.h>
#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/platform_device.h>
#include <linux/regmap.h>
-#include <linux/reset-controller.h>
#include <dt-bindings/clock/qcom,ipq9574-gcc.h>
#include <dt-bindings/reset/qcom,ipq9574-gcc.h>
-#include "clk-rcg.h"
-#include "clk-branch.h"
#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
#include "clk-regmap-divider.h"
#include "clk-regmap-mux.h"
#include "clk-regmap-phy-mux.h"
+#include "common.h"
#include "reset.h"
/* Need to match the order of clocks in DT binding */
@@ -69,7 +69,7 @@ static struct clk_alpha_pll gpll0_main = {
.clkr = {
.enable_reg = 0x0b000,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gpll0_main",
.parent_data = gcc_xo_data,
.num_parents = ARRAY_SIZE(gcc_xo_data),
@@ -81,7 +81,7 @@ static struct clk_alpha_pll gpll0_main = {
static struct clk_fixed_factor gpll0_out_main_div2 = {
.mult = 1,
.div = 2,
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gpll0_out_main_div2",
.parent_hws = (const struct clk_hw *[]) {
&gpll0_main.clkr.hw
@@ -96,7 +96,7 @@ static struct clk_alpha_pll_postdiv gpll0 = {
.offset = 0x20000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "gpll0",
.parent_hws = (const struct clk_hw *[]) {
&gpll0_main.clkr.hw
@@ -113,7 +113,7 @@ static struct clk_alpha_pll gpll4_main = {
.clkr = {
.enable_reg = 0x0b000,
.enable_mask = BIT(2),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gpll4_main",
.parent_data = gcc_xo_data,
.num_parents = ARRAY_SIZE(gcc_xo_data),
@@ -126,7 +126,7 @@ static struct clk_alpha_pll_postdiv gpll4 = {
.offset = 0x22000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "gpll4",
.parent_hws = (const struct clk_hw *[]) {
&gpll4_main.clkr.hw
@@ -143,7 +143,7 @@ static struct clk_alpha_pll gpll2_main = {
.clkr = {
.enable_reg = 0x0b000,
.enable_mask = BIT(1),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gpll2_main",
.parent_data = gcc_xo_data,
.num_parents = ARRAY_SIZE(gcc_xo_data),
@@ -156,7 +156,7 @@ static struct clk_alpha_pll_postdiv gpll2 = {
.offset = 0x21000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "gpll2",
.parent_hws = (const struct clk_hw *[]) {
&gpll2_main.clkr.hw
@@ -172,7 +172,7 @@ static struct clk_branch gcc_sleep_clk_src = {
.clkr = {
.enable_reg = 0x3400c,
.enable_mask = BIT(1),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_sleep_clk_src",
.parent_data = gcc_sleep_clk_data,
.num_parents = ARRAY_SIZE(gcc_sleep_clk_data),
@@ -420,7 +420,7 @@ static struct clk_rcg2 apss_ahb_clk_src = {
.freq_tbl = ftbl_apss_ahb_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "apss_ahb_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -438,7 +438,7 @@ static struct clk_rcg2 apss_axi_clk_src = {
.freq_tbl = ftbl_apss_axi_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_div2_gpll0_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "apss_axi_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_div2_gpll0,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_div2_gpll0),
@@ -458,7 +458,7 @@ static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_qup1_i2c_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -483,7 +483,7 @@ static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_qup1_spi_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -496,7 +496,7 @@ static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_qup2_i2c_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -510,7 +510,7 @@ static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_qup2_spi_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -523,7 +523,7 @@ static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_qup3_i2c_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -537,7 +537,7 @@ static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_qup3_spi_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -550,7 +550,7 @@ static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_qup4_i2c_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -564,7 +564,7 @@ static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_qup4_spi_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -577,7 +577,7 @@ static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_qup5_i2c_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -591,7 +591,7 @@ static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_qup5_spi_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -604,7 +604,7 @@ static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
.freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_qup6_i2c_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -618,7 +618,7 @@ static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_qup6_spi_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -650,7 +650,7 @@ static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_uart1_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -664,7 +664,7 @@ static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_uart2_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -678,7 +678,7 @@ static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_uart3_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -692,7 +692,7 @@ static struct clk_rcg2 blsp1_uart4_apps_clk_src = {
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_uart4_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -706,7 +706,7 @@ static struct clk_rcg2 blsp1_uart5_apps_clk_src = {
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_uart5_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -720,7 +720,7 @@ static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "blsp1_uart6_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -728,13 +728,48 @@ static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
},
};
+static const struct freq_tbl ftbl_gcc_crypto_clk_src[] = {
+ F(160000000, P_GPLL0, 5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_crypto_clk_src = {
+ .cmd_rcgr = 0x16004,
+ .freq_tbl = ftbl_gcc_crypto_clk_src,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_crypto_clk_src",
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_crypto_clk = {
+ .halt_reg = 0x1600c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x0b004,
+ .enable_mask = BIT(14),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_crypto_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_crypto_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
static struct clk_branch gcc_apss_ahb_clk = {
.halt_reg = 0x24018,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x0b004,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_apss_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&apss_ahb_clk_src.clkr.hw
@@ -752,7 +787,7 @@ static struct clk_branch gcc_apss_axi_clk = {
.clkr = {
.enable_reg = 0x0b004,
.enable_mask = BIT(1),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_apss_axi_clk",
.parent_hws = (const struct clk_hw *[]) {
&apss_axi_clk_src.clkr.hw
@@ -769,7 +804,7 @@ static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
.clkr = {
.enable_reg = 0x2024,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_qup1_i2c_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_qup1_i2c_apps_clk_src.clkr.hw
@@ -786,7 +821,7 @@ static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
.clkr = {
.enable_reg = 0x02020,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_qup1_spi_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_qup1_spi_apps_clk_src.clkr.hw
@@ -803,7 +838,7 @@ static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
.clkr = {
.enable_reg = 0x03024,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_qup2_i2c_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_qup2_i2c_apps_clk_src.clkr.hw
@@ -820,7 +855,7 @@ static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
.clkr = {
.enable_reg = 0x03020,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_qup2_spi_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_qup2_spi_apps_clk_src.clkr.hw
@@ -837,7 +872,7 @@ static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
.clkr = {
.enable_reg = 0x04024,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_qup3_i2c_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_qup3_i2c_apps_clk_src.clkr.hw
@@ -854,7 +889,7 @@ static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
.clkr = {
.enable_reg = 0x04020,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_qup3_spi_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_qup3_spi_apps_clk_src.clkr.hw
@@ -871,7 +906,7 @@ static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
.clkr = {
.enable_reg = 0x05024,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_qup4_i2c_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_qup4_i2c_apps_clk_src.clkr.hw
@@ -888,7 +923,7 @@ static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
.clkr = {
.enable_reg = 0x05020,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_qup4_spi_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_qup4_spi_apps_clk_src.clkr.hw
@@ -905,7 +940,7 @@ static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
.clkr = {
.enable_reg = 0x06024,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_qup5_i2c_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_qup5_i2c_apps_clk_src.clkr.hw
@@ -922,7 +957,7 @@ static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
.clkr = {
.enable_reg = 0x06020,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_qup5_spi_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_qup5_spi_apps_clk_src.clkr.hw
@@ -939,7 +974,7 @@ static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
.clkr = {
.enable_reg = 0x07024,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_qup6_i2c_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_qup6_i2c_apps_clk_src.clkr.hw
@@ -956,7 +991,7 @@ static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
.clkr = {
.enable_reg = 0x07020,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_qup6_spi_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_qup6_spi_apps_clk_src.clkr.hw
@@ -973,7 +1008,7 @@ static struct clk_branch gcc_blsp1_uart1_apps_clk = {
.clkr = {
.enable_reg = 0x02040,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_uart1_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_uart1_apps_clk_src.clkr.hw
@@ -990,7 +1025,7 @@ static struct clk_branch gcc_blsp1_uart2_apps_clk = {
.clkr = {
.enable_reg = 0x03040,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_uart2_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_uart2_apps_clk_src.clkr.hw
@@ -1007,7 +1042,7 @@ static struct clk_branch gcc_blsp1_uart3_apps_clk = {
.clkr = {
.enable_reg = 0x04054,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_uart3_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_uart3_apps_clk_src.clkr.hw
@@ -1024,7 +1059,7 @@ static struct clk_branch gcc_blsp1_uart4_apps_clk = {
.clkr = {
.enable_reg = 0x05040,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_uart4_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_uart4_apps_clk_src.clkr.hw
@@ -1041,7 +1076,7 @@ static struct clk_branch gcc_blsp1_uart5_apps_clk = {
.clkr = {
.enable_reg = 0x06040,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_uart5_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_uart5_apps_clk_src.clkr.hw
@@ -1058,7 +1093,7 @@ static struct clk_branch gcc_blsp1_uart6_apps_clk = {
.clkr = {
.enable_reg = 0x07040,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_uart6_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&blsp1_uart6_apps_clk_src.clkr.hw
@@ -1080,7 +1115,7 @@ static struct clk_rcg2 pcie0_axi_m_clk_src = {
.freq_tbl = ftbl_pcie0_axi_m_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll4_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie0_axi_m_clk_src",
.parent_data = gcc_xo_gpll0_gpll4,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4),
@@ -1093,7 +1128,7 @@ static struct clk_branch gcc_pcie0_axi_m_clk = {
.clkr = {
.enable_reg = 0x28038,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie0_axi_m_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie0_axi_m_clk_src.clkr.hw
@@ -1110,7 +1145,7 @@ static struct clk_branch gcc_anoc_pcie0_1lane_m_clk = {
.clkr = {
.enable_reg = 0x2e07c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_anoc_pcie0_1lane_m_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie0_axi_m_clk_src.clkr.hw
@@ -1127,7 +1162,7 @@ static struct clk_rcg2 pcie1_axi_m_clk_src = {
.freq_tbl = ftbl_pcie0_axi_m_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll4_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie1_axi_m_clk_src",
.parent_data = gcc_xo_gpll0_gpll4,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4),
@@ -1140,7 +1175,7 @@ static struct clk_branch gcc_pcie1_axi_m_clk = {
.clkr = {
.enable_reg = 0x29038,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie1_axi_m_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie1_axi_m_clk_src.clkr.hw
@@ -1157,7 +1192,7 @@ static struct clk_branch gcc_anoc_pcie1_1lane_m_clk = {
.clkr = {
.enable_reg = 0x2e08c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_anoc_pcie1_1lane_m_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie1_axi_m_clk_src.clkr.hw
@@ -1179,7 +1214,7 @@ static struct clk_rcg2 pcie2_axi_m_clk_src = {
.freq_tbl = ftbl_pcie2_axi_m_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie2_axi_m_clk_src",
.parent_data = gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk),
@@ -1192,7 +1227,7 @@ static struct clk_branch gcc_pcie2_axi_m_clk = {
.clkr = {
.enable_reg = 0x2a038,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie2_axi_m_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie2_axi_m_clk_src.clkr.hw
@@ -1209,7 +1244,7 @@ static struct clk_branch gcc_anoc_pcie2_2lane_m_clk = {
.clkr = {
.enable_reg = 0x2e080,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_anoc_pcie2_2lane_m_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie2_axi_m_clk_src.clkr.hw
@@ -1226,7 +1261,7 @@ static struct clk_rcg2 pcie3_axi_m_clk_src = {
.freq_tbl = ftbl_pcie2_axi_m_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie3_axi_m_clk_src",
.parent_data = gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk),
@@ -1239,7 +1274,7 @@ static struct clk_branch gcc_pcie3_axi_m_clk = {
.clkr = {
.enable_reg = 0x2b038,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie3_axi_m_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie3_axi_m_clk_src.clkr.hw
@@ -1256,7 +1291,7 @@ static struct clk_branch gcc_anoc_pcie3_2lane_m_clk = {
.clkr = {
.enable_reg = 0x2e090,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_anoc_pcie3_2lane_m_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie3_axi_m_clk_src.clkr.hw
@@ -1273,7 +1308,7 @@ static struct clk_rcg2 pcie0_axi_s_clk_src = {
.freq_tbl = ftbl_pcie0_axi_m_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll4_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie0_axi_s_clk_src",
.parent_data = gcc_xo_gpll0_gpll4,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4),
@@ -1286,7 +1321,7 @@ static struct clk_branch gcc_pcie0_axi_s_clk = {
.clkr = {
.enable_reg = 0x2803c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie0_axi_s_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie0_axi_s_clk_src.clkr.hw
@@ -1303,7 +1338,7 @@ static struct clk_branch gcc_pcie0_axi_s_bridge_clk = {
.clkr = {
.enable_reg = 0x28040,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie0_axi_s_bridge_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie0_axi_s_clk_src.clkr.hw
@@ -1320,7 +1355,7 @@ static struct clk_branch gcc_snoc_pcie0_1lane_s_clk = {
.clkr = {
.enable_reg = 0x2e048,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_snoc_pcie0_1lane_s_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie0_axi_s_clk_src.clkr.hw
@@ -1337,7 +1372,7 @@ static struct clk_rcg2 pcie1_axi_s_clk_src = {
.freq_tbl = ftbl_pcie0_axi_m_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll4_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie1_axi_s_clk_src",
.parent_data = gcc_xo_gpll0_gpll4,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4),
@@ -1350,7 +1385,7 @@ static struct clk_branch gcc_pcie1_axi_s_clk = {
.clkr = {
.enable_reg = 0x2903c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie1_axi_s_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie1_axi_s_clk_src.clkr.hw
@@ -1367,7 +1402,7 @@ static struct clk_branch gcc_pcie1_axi_s_bridge_clk = {
.clkr = {
.enable_reg = 0x29040,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie1_axi_s_bridge_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie1_axi_s_clk_src.clkr.hw
@@ -1384,7 +1419,7 @@ static struct clk_branch gcc_snoc_pcie1_1lane_s_clk = {
.clkr = {
.enable_reg = 0x2e04c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_snoc_pcie1_1lane_s_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie1_axi_s_clk_src.clkr.hw
@@ -1401,7 +1436,7 @@ static struct clk_rcg2 pcie2_axi_s_clk_src = {
.freq_tbl = ftbl_pcie0_axi_m_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll4_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie2_axi_s_clk_src",
.parent_data = gcc_xo_gpll0_gpll4,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4),
@@ -1414,7 +1449,7 @@ static struct clk_branch gcc_pcie2_axi_s_clk = {
.clkr = {
.enable_reg = 0x2a03c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie2_axi_s_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie2_axi_s_clk_src.clkr.hw
@@ -1431,7 +1466,7 @@ static struct clk_branch gcc_pcie2_axi_s_bridge_clk = {
.clkr = {
.enable_reg = 0x2a040,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie2_axi_s_bridge_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie2_axi_s_clk_src.clkr.hw
@@ -1448,7 +1483,7 @@ static struct clk_branch gcc_snoc_pcie2_2lane_s_clk = {
.clkr = {
.enable_reg = 0x2e050,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_snoc_pcie2_2lane_s_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie2_axi_s_clk_src.clkr.hw
@@ -1465,7 +1500,7 @@ static struct clk_rcg2 pcie3_axi_s_clk_src = {
.freq_tbl = ftbl_pcie0_axi_m_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll4_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie3_axi_s_clk_src",
.parent_data = gcc_xo_gpll0_gpll4,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4),
@@ -1478,7 +1513,7 @@ static struct clk_branch gcc_pcie3_axi_s_clk = {
.clkr = {
.enable_reg = 0x2b03c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie3_axi_s_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie3_axi_s_clk_src.clkr.hw
@@ -1495,7 +1530,7 @@ static struct clk_branch gcc_pcie3_axi_s_bridge_clk = {
.clkr = {
.enable_reg = 0x2b040,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie3_axi_s_bridge_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie3_axi_s_clk_src.clkr.hw
@@ -1512,7 +1547,7 @@ static struct clk_branch gcc_snoc_pcie3_2lane_s_clk = {
.clkr = {
.enable_reg = 0x2e054,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_snoc_pcie3_2lane_s_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie3_axi_s_clk_src.clkr.hw
@@ -1527,7 +1562,7 @@ static struct clk_branch gcc_snoc_pcie3_2lane_s_clk = {
static struct clk_regmap_phy_mux pcie0_pipe_clk_src = {
.reg = 0x28064,
.clkr = {
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "pcie0_pipe_clk_src",
.parent_data = &(const struct clk_parent_data) {
.index = DT_PCIE30_PHY0_PIPE_CLK,
@@ -1541,7 +1576,7 @@ static struct clk_regmap_phy_mux pcie0_pipe_clk_src = {
static struct clk_regmap_phy_mux pcie1_pipe_clk_src = {
.reg = 0x29064,
.clkr = {
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "pcie1_pipe_clk_src",
.parent_data = &(const struct clk_parent_data) {
.index = DT_PCIE30_PHY1_PIPE_CLK,
@@ -1555,7 +1590,7 @@ static struct clk_regmap_phy_mux pcie1_pipe_clk_src = {
static struct clk_regmap_phy_mux pcie2_pipe_clk_src = {
.reg = 0x2a064,
.clkr = {
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "pcie2_pipe_clk_src",
.parent_data = &(const struct clk_parent_data) {
.index = DT_PCIE30_PHY2_PIPE_CLK,
@@ -1569,7 +1604,7 @@ static struct clk_regmap_phy_mux pcie2_pipe_clk_src = {
static struct clk_regmap_phy_mux pcie3_pipe_clk_src = {
.reg = 0x2b064,
.clkr = {
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "pcie3_pipe_clk_src",
.parent_data = &(const struct clk_parent_data) {
.index = DT_PCIE30_PHY3_PIPE_CLK,
@@ -1591,7 +1626,7 @@ static struct clk_rcg2 pcie0_rchng_clk_src = {
.freq_tbl = ftbl_pcie_rchng_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie0_rchng_clk_src",
.parent_data = gcc_xo_gpll0,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0),
@@ -1604,7 +1639,7 @@ static struct clk_branch gcc_pcie0_rchng_clk = {
.clkr = {
.enable_reg = 0x28028,
.enable_mask = BIT(1),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie0_rchng_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie0_rchng_clk_src.clkr.hw
@@ -1622,7 +1657,7 @@ static struct clk_rcg2 pcie1_rchng_clk_src = {
.freq_tbl = ftbl_pcie_rchng_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie1_rchng_clk_src",
.parent_data = gcc_xo_gpll0,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0),
@@ -1635,7 +1670,7 @@ static struct clk_branch gcc_pcie1_rchng_clk = {
.clkr = {
.enable_reg = 0x29028,
.enable_mask = BIT(1),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie1_rchng_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie1_rchng_clk_src.clkr.hw
@@ -1652,7 +1687,7 @@ static struct clk_rcg2 pcie2_rchng_clk_src = {
.freq_tbl = ftbl_pcie_rchng_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie2_rchng_clk_src",
.parent_data = gcc_xo_gpll0,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0),
@@ -1665,7 +1700,7 @@ static struct clk_branch gcc_pcie2_rchng_clk = {
.clkr = {
.enable_reg = 0x2a028,
.enable_mask = BIT(1),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie2_rchng_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie2_rchng_clk_src.clkr.hw
@@ -1682,7 +1717,7 @@ static struct clk_rcg2 pcie3_rchng_clk_src = {
.freq_tbl = ftbl_pcie_rchng_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie3_rchng_clk_src",
.parent_data = gcc_xo_gpll0,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0),
@@ -1695,7 +1730,7 @@ static struct clk_branch gcc_pcie3_rchng_clk = {
.clkr = {
.enable_reg = 0x2b028,
.enable_mask = BIT(1),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie3_rchng_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie3_rchng_clk_src.clkr.hw
@@ -1718,7 +1753,7 @@ static struct clk_rcg2 pcie_aux_clk_src = {
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_aux_core_pi_sleep_clk_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcie_aux_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_aux_core_pi_sleep_clk,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_aux_core_pi_sleep_clk),
@@ -1731,7 +1766,7 @@ static struct clk_branch gcc_pcie0_aux_clk = {
.clkr = {
.enable_reg = 0x28034,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie0_aux_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie_aux_clk_src.clkr.hw
@@ -1748,7 +1783,7 @@ static struct clk_branch gcc_pcie1_aux_clk = {
.clkr = {
.enable_reg = 0x29034,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie1_aux_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie_aux_clk_src.clkr.hw
@@ -1765,7 +1800,7 @@ static struct clk_branch gcc_pcie2_aux_clk = {
.clkr = {
.enable_reg = 0x2a034,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie2_aux_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie_aux_clk_src.clkr.hw
@@ -1782,7 +1817,7 @@ static struct clk_branch gcc_pcie3_aux_clk = {
.clkr = {
.enable_reg = 0x2b034,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie3_aux_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcie_aux_clk_src.clkr.hw
@@ -1805,7 +1840,7 @@ static struct clk_rcg2 usb0_aux_clk_src = {
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_core_pi_sleep_clk_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "usb0_aux_clk_src",
.parent_data = gcc_xo_gpll0_core_pi_sleep_clk,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_core_pi_sleep_clk),
@@ -1818,7 +1853,7 @@ static struct clk_branch gcc_usb0_aux_clk = {
.clkr = {
.enable_reg = 0x2c048,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_usb0_aux_clk",
.parent_hws = (const struct clk_hw *[]) {
&usb0_aux_clk_src.clkr.hw
@@ -1842,7 +1877,7 @@ static struct clk_rcg2 usb0_master_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_out_main_div2_gpll0_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "usb0_master_clk_src",
.parent_data = gcc_xo_gpll0_out_main_div2_gpll0,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_out_main_div2_gpll0),
@@ -1855,7 +1890,7 @@ static struct clk_branch gcc_usb0_master_clk = {
.clkr = {
.enable_reg = 0x2c044,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_usb0_master_clk",
.parent_hws = (const struct clk_hw *[]) {
&usb0_master_clk_src.clkr.hw
@@ -1872,7 +1907,7 @@ static struct clk_branch gcc_snoc_usb_clk = {
.clkr = {
.enable_reg = 0x2e058,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_snoc_usb_clk",
.parent_hws = (const struct clk_hw *[]) {
&usb0_master_clk_src.clkr.hw
@@ -1889,7 +1924,7 @@ static struct clk_branch gcc_anoc_usb_axi_clk = {
.clkr = {
.enable_reg = 0x2e084,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_anoc_usb_axi_clk",
.parent_hws = (const struct clk_hw *[]) {
&usb0_master_clk_src.clkr.hw
@@ -1913,7 +1948,7 @@ static struct clk_rcg2 usb0_mock_utmi_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_gpll4_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "usb0_mock_utmi_clk_src",
.parent_data = gcc_xo_gpll4_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll4_gpll0_gpll0_out_main_div2),
@@ -1925,7 +1960,7 @@ static struct clk_regmap_div usb0_mock_utmi_div_clk_src = {
.reg = 0x2c040,
.shift = 0,
.width = 2,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "usb0_mock_utmi_div_clk_src",
.parent_data = &(const struct clk_parent_data) {
.hw = &usb0_mock_utmi_clk_src.clkr.hw,
@@ -1941,7 +1976,7 @@ static struct clk_branch gcc_usb0_mock_utmi_clk = {
.clkr = {
.enable_reg = 0x2c04c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_usb0_mock_utmi_clk",
.parent_hws = (const struct clk_hw *[]) {
&usb0_mock_utmi_div_clk_src.clkr.hw
@@ -1959,7 +1994,7 @@ static struct clk_regmap_mux usb0_pipe_clk_src = {
.width = 2,
.parent_map = gcc_usb3phy_0_cc_pipe_clk_xo_map,
.clkr = {
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "usb0_pipe_clk_src",
.parent_data = gcc_usb3phy_0_cc_pipe_clk_xo,
.num_parents = ARRAY_SIZE(gcc_usb3phy_0_cc_pipe_clk_xo),
@@ -1988,7 +2023,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll2_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "sdcc1_apps_clk_src",
.parent_data = gcc_xo_gpll0_gpll2_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2_gpll0_out_main_div2),
@@ -2001,7 +2036,7 @@ static struct clk_branch gcc_sdcc1_apps_clk = {
.clkr = {
.enable_reg = 0x3302c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_sdcc1_apps_clk",
.parent_hws = (const struct clk_hw *[]) {
&sdcc1_apps_clk_src.clkr.hw
@@ -2024,7 +2059,7 @@ static struct clk_rcg2 sdcc1_ice_core_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll4_gpll0_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "sdcc1_ice_core_clk_src",
.parent_data = gcc_xo_gpll0_gpll4_gpll0_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_gpll0_div2),
@@ -2037,7 +2072,7 @@ static struct clk_branch gcc_sdcc1_ice_core_clk = {
.clkr = {
.enable_reg = 0x33030,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_sdcc1_ice_core_clk",
.parent_hws = (const struct clk_hw *[]) {
&sdcc1_ice_core_clk_src.clkr.hw
@@ -2062,7 +2097,7 @@ static struct clk_rcg2 pcnoc_bfdcd_clk_src = {
.freq_tbl = ftbl_pcnoc_bfdcd_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "pcnoc_bfdcd_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -2071,12 +2106,44 @@ static struct clk_rcg2 pcnoc_bfdcd_clk_src = {
},
};
+static struct clk_branch gcc_crypto_axi_clk = {
+ .halt_reg = 0x16010,
+ .clkr = {
+ .enable_reg = 0x16010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_crypto_axi_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &pcnoc_bfdcd_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_crypto_ahb_clk = {
+ .halt_reg = 0x16014,
+ .clkr = {
+ .enable_reg = 0x16014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_crypto_ahb_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &pcnoc_bfdcd_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
static struct clk_branch gcc_nsscfg_clk = {
.halt_reg = 0x1702c,
.clkr = {
.enable_reg = 0x1702c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nsscfg_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2093,7 +2160,7 @@ static struct clk_branch gcc_nssnoc_nsscc_clk = {
.clkr = {
.enable_reg = 0x17030,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nssnoc_nsscc_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2110,7 +2177,7 @@ static struct clk_branch gcc_nsscc_clk = {
.clkr = {
.enable_reg = 0x17034,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nsscc_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2127,7 +2194,7 @@ static struct clk_branch gcc_nssnoc_pcnoc_1_clk = {
.clkr = {
.enable_reg = 0x17080,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nssnoc_pcnoc_1_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2144,7 +2211,7 @@ static struct clk_branch gcc_qdss_dap_ahb_clk = {
.clkr = {
.enable_reg = 0x2d064,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_dap_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2161,7 +2228,7 @@ static struct clk_branch gcc_qdss_cfg_ahb_clk = {
.clkr = {
.enable_reg = 0x2d068,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_cfg_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2178,7 +2245,7 @@ static struct clk_branch gcc_qpic_ahb_clk = {
.clkr = {
.enable_reg = 0x32010,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qpic_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2195,7 +2262,7 @@ static struct clk_branch gcc_qpic_clk = {
.clkr = {
.enable_reg = 0x32014,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qpic_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2213,7 +2280,7 @@ static struct clk_branch gcc_blsp1_ahb_clk = {
.clkr = {
.enable_reg = 0x0b004,
.enable_mask = BIT(4),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_blsp1_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2230,7 +2297,7 @@ static struct clk_branch gcc_mdio_ahb_clk = {
.clkr = {
.enable_reg = 0x17040,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_mdio_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2248,7 +2315,7 @@ static struct clk_branch gcc_prng_ahb_clk = {
.clkr = {
.enable_reg = 0x0b004,
.enable_mask = BIT(10),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_prng_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2265,7 +2332,7 @@ static struct clk_branch gcc_uniphy0_ahb_clk = {
.clkr = {
.enable_reg = 0x1704c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_uniphy0_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2282,7 +2349,7 @@ static struct clk_branch gcc_uniphy1_ahb_clk = {
.clkr = {
.enable_reg = 0x1705c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_uniphy1_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2299,7 +2366,7 @@ static struct clk_branch gcc_uniphy2_ahb_clk = {
.clkr = {
.enable_reg = 0x1706c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_uniphy2_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2316,7 +2383,7 @@ static struct clk_branch gcc_cmn_12gpll_ahb_clk = {
.clkr = {
.enable_reg = 0x3a004,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_cmn_12gpll_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2333,7 +2400,7 @@ static struct clk_branch gcc_cmn_12gpll_apu_clk = {
.clkr = {
.enable_reg = 0x3a00c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_cmn_12gpll_apu_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2350,7 +2417,7 @@ static struct clk_branch gcc_pcie0_ahb_clk = {
.clkr = {
.enable_reg = 0x28030,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie0_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2367,7 +2434,7 @@ static struct clk_branch gcc_pcie1_ahb_clk = {
.clkr = {
.enable_reg = 0x29030,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie1_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2384,7 +2451,7 @@ static struct clk_branch gcc_pcie2_ahb_clk = {
.clkr = {
.enable_reg = 0x2a030,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie2_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2401,7 +2468,7 @@ static struct clk_branch gcc_pcie3_ahb_clk = {
.clkr = {
.enable_reg = 0x2b030,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcie3_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2418,7 +2485,7 @@ static struct clk_branch gcc_usb0_phy_cfg_ahb_clk = {
.clkr = {
.enable_reg = 0x2c05c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_usb0_phy_cfg_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2435,7 +2502,7 @@ static struct clk_branch gcc_sdcc1_ahb_clk = {
.clkr = {
.enable_reg = 0x33034,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_sdcc1_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&pcnoc_bfdcd_clk_src.clkr.hw
@@ -2460,7 +2527,7 @@ static struct clk_rcg2 system_noc_bfdcd_clk_src = {
.freq_tbl = ftbl_system_noc_bfdcd_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll4_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "system_noc_bfdcd_clk_src",
.parent_data = gcc_xo_gpll0_gpll4,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4),
@@ -2475,7 +2542,7 @@ static struct clk_branch gcc_q6ss_boot_clk = {
.clkr = {
.enable_reg = 0x25080,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_q6ss_boot_clk",
.parent_hws = (const struct clk_hw *[]) {
&system_noc_bfdcd_clk_src.clkr.hw
@@ -2492,7 +2559,7 @@ static struct clk_branch gcc_nssnoc_snoc_clk = {
.clkr = {
.enable_reg = 0x17028,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nssnoc_snoc_clk",
.parent_hws = (const struct clk_hw *[]) {
&system_noc_bfdcd_clk_src.clkr.hw
@@ -2509,7 +2576,7 @@ static struct clk_branch gcc_nssnoc_snoc_1_clk = {
.clkr = {
.enable_reg = 0x1707c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nssnoc_snoc_1_clk",
.parent_hws = (const struct clk_hw *[]) {
&system_noc_bfdcd_clk_src.clkr.hw
@@ -2526,7 +2593,7 @@ static struct clk_branch gcc_qdss_etr_usb_clk = {
.clkr = {
.enable_reg = 0x2d060,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_etr_usb_clk",
.parent_hws = (const struct clk_hw *[]) {
&system_noc_bfdcd_clk_src.clkr.hw
@@ -2549,7 +2616,7 @@ static struct clk_rcg2 wcss_ahb_clk_src = {
.freq_tbl = ftbl_wcss_ahb_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "wcss_ahb_clk_src",
.parent_data = gcc_xo_gpll0,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0),
@@ -2562,7 +2629,7 @@ static struct clk_branch gcc_q6_ahb_clk = {
.clkr = {
.enable_reg = 0x25014,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_q6_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&wcss_ahb_clk_src.clkr.hw
@@ -2579,7 +2646,7 @@ static struct clk_branch gcc_q6_ahb_s_clk = {
.clkr = {
.enable_reg = 0x25018,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_q6_ahb_s_clk",
.parent_hws = (const struct clk_hw *[]) {
&wcss_ahb_clk_src.clkr.hw
@@ -2596,7 +2663,7 @@ static struct clk_branch gcc_wcss_ecahb_clk = {
.clkr = {
.enable_reg = 0x25058,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_wcss_ecahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&wcss_ahb_clk_src.clkr.hw
@@ -2613,7 +2680,7 @@ static struct clk_branch gcc_wcss_acmt_clk = {
.clkr = {
.enable_reg = 0x2505c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_wcss_acmt_clk",
.parent_hws = (const struct clk_hw *[]) {
&wcss_ahb_clk_src.clkr.hw
@@ -2630,7 +2697,7 @@ static struct clk_branch gcc_sys_noc_wcss_ahb_clk = {
.clkr = {
.enable_reg = 0x2e030,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_sys_noc_wcss_ahb_clk",
.parent_hws = (const struct clk_hw *[]) {
&wcss_ahb_clk_src.clkr.hw
@@ -2654,7 +2721,7 @@ static struct clk_rcg2 wcss_axi_m_clk_src = {
.freq_tbl = ftbl_wcss_axi_m_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "wcss_axi_m_clk_src",
.parent_data = gcc_xo_gpll0,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0),
@@ -2667,7 +2734,7 @@ static struct clk_branch gcc_anoc_wcss_axi_m_clk = {
.clkr = {
.enable_reg = 0x2e0a8,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_anoc_wcss_axi_m_clk",
.parent_hws = (const struct clk_hw *[]) {
&wcss_axi_m_clk_src.clkr.hw
@@ -2689,7 +2756,7 @@ static struct clk_rcg2 qdss_at_clk_src = {
.freq_tbl = ftbl_qdss_at_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll4_gpll0_gpll0_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "qdss_at_clk_src",
.parent_data = gcc_xo_gpll4_gpll0_gpll0_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll4_gpll0_gpll0_div2),
@@ -2702,7 +2769,7 @@ static struct clk_branch gcc_q6ss_atbm_clk = {
.clkr = {
.enable_reg = 0x2501c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_q6ss_atbm_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_at_clk_src.clkr.hw
@@ -2719,7 +2786,7 @@ static struct clk_branch gcc_wcss_dbg_ifc_atb_clk = {
.clkr = {
.enable_reg = 0x2503c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_wcss_dbg_ifc_atb_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_at_clk_src.clkr.hw
@@ -2736,7 +2803,7 @@ static struct clk_branch gcc_nssnoc_atb_clk = {
.clkr = {
.enable_reg = 0x17014,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nssnoc_atb_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_at_clk_src.clkr.hw
@@ -2753,7 +2820,7 @@ static struct clk_branch gcc_qdss_at_clk = {
.clkr = {
.enable_reg = 0x2d038,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_at_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_at_clk_src.clkr.hw
@@ -2770,7 +2837,7 @@ static struct clk_branch gcc_sys_noc_at_clk = {
.clkr = {
.enable_reg = 0x2e038,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_sys_noc_at_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_at_clk_src.clkr.hw
@@ -2787,7 +2854,7 @@ static struct clk_branch gcc_pcnoc_at_clk = {
.clkr = {
.enable_reg = 0x31024,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_pcnoc_at_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_at_clk_src.clkr.hw
@@ -2802,7 +2869,7 @@ static struct clk_branch gcc_pcnoc_at_clk = {
static struct clk_fixed_factor gcc_eud_at_div_clk_src = {
.mult = 1,
.div = 6,
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_eud_at_div_clk_src",
.parent_hws = (const struct clk_hw *[]) {
&qdss_at_clk_src.clkr.hw
@@ -2818,7 +2885,7 @@ static struct clk_branch gcc_usb0_eud_at_clk = {
.clkr = {
.enable_reg = 0x30004,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_usb0_eud_at_clk",
.parent_hws = (const struct clk_hw *[]) {
&gcc_eud_at_div_clk_src.hw
@@ -2835,7 +2902,7 @@ static struct clk_branch gcc_qdss_eud_at_clk = {
.clkr = {
.enable_reg = 0x2d06c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_eud_at_clk",
.parent_hws = (const struct clk_hw *[]) {
&gcc_eud_at_div_clk_src.hw
@@ -2858,7 +2925,7 @@ static struct clk_rcg2 qdss_stm_clk_src = {
.freq_tbl = ftbl_qdss_stm_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "qdss_stm_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
@@ -2871,7 +2938,7 @@ static struct clk_branch gcc_qdss_stm_clk = {
.clkr = {
.enable_reg = 0x2d03c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_stm_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_stm_clk_src.clkr.hw
@@ -2888,7 +2955,7 @@ static struct clk_branch gcc_sys_noc_qdss_stm_axi_clk = {
.clkr = {
.enable_reg = 0x2e034,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_sys_noc_qdss_stm_axi_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_stm_clk_src.clkr.hw
@@ -2910,7 +2977,7 @@ static struct clk_rcg2 qdss_traceclkin_clk_src = {
.freq_tbl = ftbl_qdss_traceclkin_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll4_gpll0_gpll0_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "qdss_traceclkin_clk_src",
.parent_data = gcc_xo_gpll4_gpll0_gpll0_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll4_gpll0_gpll0_div2),
@@ -2923,7 +2990,7 @@ static struct clk_branch gcc_qdss_traceclkin_clk = {
.clkr = {
.enable_reg = 0x2d040,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_traceclkin_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_traceclkin_clk_src.clkr.hw
@@ -2945,7 +3012,7 @@ static struct clk_rcg2 qdss_tsctr_clk_src = {
.freq_tbl = ftbl_qdss_tsctr_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll4_gpll0_gpll0_div2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "qdss_tsctr_clk_src",
.parent_data = gcc_xo_gpll4_gpll0_gpll0_div2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll4_gpll0_gpll0_div2),
@@ -2956,7 +3023,7 @@ static struct clk_rcg2 qdss_tsctr_clk_src = {
static struct clk_fixed_factor qdss_tsctr_div2_clk_src = {
.mult = 1,
.div = 2,
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "qdss_tsctr_div2_clk_src",
.parent_hws = (const struct clk_hw *[]) {
&qdss_tsctr_clk_src.clkr.hw
@@ -2972,7 +3039,7 @@ static struct clk_branch gcc_q6_tsctr_1to2_clk = {
.clkr = {
.enable_reg = 0x25020,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_q6_tsctr_1to2_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_tsctr_div2_clk_src.hw
@@ -2989,7 +3056,7 @@ static struct clk_branch gcc_wcss_dbg_ifc_nts_clk = {
.clkr = {
.enable_reg = 0x25040,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_wcss_dbg_ifc_nts_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_tsctr_div2_clk_src.hw
@@ -3006,7 +3073,7 @@ static struct clk_branch gcc_qdss_tsctr_div2_clk = {
.clkr = {
.enable_reg = 0x2d044,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_tsctr_div2_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_tsctr_div2_clk_src.hw
@@ -3029,7 +3096,7 @@ static struct clk_rcg2 uniphy_sys_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "uniphy_sys_clk_src",
.parent_data = gcc_xo_data,
.num_parents = ARRAY_SIZE(gcc_xo_data),
@@ -3043,7 +3110,7 @@ static struct clk_rcg2 nss_ts_clk_src = {
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_xo_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "nss_ts_clk_src",
.parent_data = gcc_xo_data,
.num_parents = ARRAY_SIZE(gcc_xo_data),
@@ -3056,7 +3123,7 @@ static struct clk_branch gcc_qdss_ts_clk = {
.clkr = {
.enable_reg = 0x2d078,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_ts_clk",
.parent_hws = (const struct clk_hw *[]) {
&nss_ts_clk_src.clkr.hw
@@ -3071,7 +3138,7 @@ static struct clk_branch gcc_qdss_ts_clk = {
static struct clk_fixed_factor qdss_dap_sync_clk_src = {
.mult = 1,
.div = 4,
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "qdss_dap_sync_clk_src",
.parent_hws = (const struct clk_hw *[]) {
&qdss_tsctr_clk_src.clkr.hw
@@ -3086,7 +3153,7 @@ static struct clk_branch gcc_qdss_tsctr_div4_clk = {
.clkr = {
.enable_reg = 0x2d04c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_tsctr_div4_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_dap_sync_clk_src.hw
@@ -3101,7 +3168,7 @@ static struct clk_branch gcc_qdss_tsctr_div4_clk = {
static struct clk_fixed_factor qdss_tsctr_div8_clk_src = {
.mult = 1,
.div = 8,
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "qdss_tsctr_div8_clk_src",
.parent_hws = (const struct clk_hw *[]) {
&qdss_tsctr_clk_src.clkr.hw
@@ -3116,7 +3183,7 @@ static struct clk_branch gcc_nss_ts_clk = {
.clkr = {
.enable_reg = 0x17018,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nss_ts_clk",
.parent_hws = (const struct clk_hw *[]) {
&nss_ts_clk_src.clkr.hw
@@ -3133,7 +3200,7 @@ static struct clk_branch gcc_qdss_tsctr_div8_clk = {
.clkr = {
.enable_reg = 0x2d050,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_tsctr_div8_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_tsctr_div8_clk_src.hw
@@ -3148,7 +3215,7 @@ static struct clk_branch gcc_qdss_tsctr_div8_clk = {
static struct clk_fixed_factor qdss_tsctr_div16_clk_src = {
.mult = 1,
.div = 16,
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "qdss_tsctr_div16_clk_src",
.parent_hws = (const struct clk_hw *[]) {
&qdss_tsctr_clk_src.clkr.hw
@@ -3163,7 +3230,7 @@ static struct clk_branch gcc_qdss_tsctr_div16_clk = {
.clkr = {
.enable_reg = 0x2d054,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_tsctr_div16_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_tsctr_div16_clk_src.hw
@@ -3180,7 +3247,7 @@ static struct clk_branch gcc_q6ss_pclkdbg_clk = {
.clkr = {
.enable_reg = 0x25024,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_q6ss_pclkdbg_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_dap_sync_clk_src.hw
@@ -3197,7 +3264,7 @@ static struct clk_branch gcc_q6ss_trig_clk = {
.clkr = {
.enable_reg = 0x25068,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_q6ss_trig_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_dap_sync_clk_src.hw
@@ -3214,7 +3281,7 @@ static struct clk_branch gcc_wcss_dbg_ifc_apb_clk = {
.clkr = {
.enable_reg = 0x25038,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_wcss_dbg_ifc_apb_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_dap_sync_clk_src.hw
@@ -3231,7 +3298,7 @@ static struct clk_branch gcc_wcss_dbg_ifc_dapbus_clk = {
.clkr = {
.enable_reg = 0x25044,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_wcss_dbg_ifc_dapbus_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_dap_sync_clk_src.hw
@@ -3248,7 +3315,7 @@ static struct clk_branch gcc_qdss_dap_clk = {
.clkr = {
.enable_reg = 0x2d058,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_dap_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_dap_sync_clk_src.hw
@@ -3265,7 +3332,7 @@ static struct clk_branch gcc_qdss_apb2jtag_clk = {
.clkr = {
.enable_reg = 0x2d05c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_apb2jtag_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_dap_sync_clk_src.hw
@@ -3280,7 +3347,7 @@ static struct clk_branch gcc_qdss_apb2jtag_clk = {
static struct clk_fixed_factor qdss_tsctr_div3_clk_src = {
.mult = 1,
.div = 3,
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "qdss_tsctr_div3_clk_src",
.parent_hws = (const struct clk_hw *[]) {
&qdss_tsctr_clk_src.clkr.hw
@@ -3295,7 +3362,7 @@ static struct clk_branch gcc_qdss_tsctr_div3_clk = {
.clkr = {
.enable_reg = 0x2d048,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_qdss_tsctr_div3_clk",
.parent_hws = (const struct clk_hw *[]) {
&qdss_tsctr_div3_clk_src.hw
@@ -3321,7 +3388,7 @@ static struct clk_rcg2 qpic_io_macro_clk_src = {
.freq_tbl = ftbl_qpic_io_macro_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "qpic_io_macro_clk_src",
.parent_data = gcc_xo_gpll0_gpll2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2),
@@ -3334,7 +3401,7 @@ static struct clk_branch gcc_qpic_io_macro_clk = {
.clkr = {
.enable_reg = 0x3200c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data){
+ .hw.init = &(const struct clk_init_data){
.name = "gcc_qpic_io_macro_clk",
.parent_hws = (const struct clk_hw *[]){
&qpic_io_macro_clk_src.clkr.hw
@@ -3356,7 +3423,7 @@ static struct clk_rcg2 q6_axi_clk_src = {
.freq_tbl = ftbl_q6_axi_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll2_gpll4_pi_sleep_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "q6_axi_clk_src",
.parent_data = gcc_xo_gpll0_gpll2_gpll4_pi_sleep,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2_gpll4_pi_sleep),
@@ -3369,7 +3436,7 @@ static struct clk_branch gcc_q6_axim_clk = {
.clkr = {
.enable_reg = 0x2500c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_q6_axim_clk",
.parent_hws = (const struct clk_hw *[]) {
&q6_axi_clk_src.clkr.hw
@@ -3387,7 +3454,7 @@ static struct clk_branch gcc_wcss_q6_tbu_clk = {
.clkr = {
.enable_reg = 0xb00c,
.enable_mask = BIT(6),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_wcss_q6_tbu_clk",
.parent_hws = (const struct clk_hw *[]) {
&q6_axi_clk_src.clkr.hw
@@ -3404,7 +3471,7 @@ static struct clk_branch gcc_mem_noc_q6_axi_clk = {
.clkr = {
.enable_reg = 0x19010,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_mem_noc_q6_axi_clk",
.parent_hws = (const struct clk_hw *[]) {
&q6_axi_clk_src.clkr.hw
@@ -3433,7 +3500,7 @@ static struct clk_rcg2 q6_axim2_clk_src = {
.freq_tbl = ftbl_q6_axim2_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll4_bias_pll_ubinc_clk_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "q6_axim2_clk_src",
.parent_data = gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk),
@@ -3451,7 +3518,7 @@ static struct clk_rcg2 nssnoc_memnoc_bfdcd_clk_src = {
.freq_tbl = ftbl_nssnoc_memnoc_bfdcd_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_aux_gpll2_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "nssnoc_memnoc_bfdcd_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_aux_gpll2,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_aux_gpll2),
@@ -3464,7 +3531,7 @@ static struct clk_branch gcc_nssnoc_memnoc_clk = {
.clkr = {
.enable_reg = 0x17024,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nssnoc_memnoc_clk",
.parent_hws = (const struct clk_hw *[]) {
&nssnoc_memnoc_bfdcd_clk_src.clkr.hw
@@ -3481,7 +3548,7 @@ static struct clk_branch gcc_nssnoc_mem_noc_1_clk = {
.clkr = {
.enable_reg = 0x17084,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nssnoc_mem_noc_1_clk",
.parent_hws = (const struct clk_hw *[]) {
&nssnoc_memnoc_bfdcd_clk_src.clkr.hw
@@ -3498,7 +3565,7 @@ static struct clk_branch gcc_nss_tbu_clk = {
.clkr = {
.enable_reg = 0xb00c,
.enable_mask = BIT(4),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nss_tbu_clk",
.parent_hws = (const struct clk_hw *[]) {
&nssnoc_memnoc_bfdcd_clk_src.clkr.hw
@@ -3515,7 +3582,7 @@ static struct clk_branch gcc_mem_noc_nssnoc_clk = {
.clkr = {
.enable_reg = 0x19014,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_mem_noc_nssnoc_clk",
.parent_hws = (const struct clk_hw *[]) {
&nssnoc_memnoc_bfdcd_clk_src.clkr.hw
@@ -3537,7 +3604,7 @@ static struct clk_rcg2 lpass_axim_clk_src = {
.freq_tbl = ftbl_lpass_axim_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "lpass_axim_clk_src",
.parent_data = gcc_xo_gpll0,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0),
@@ -3550,7 +3617,7 @@ static struct clk_rcg2 lpass_sway_clk_src = {
.freq_tbl = ftbl_lpass_axim_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "lpass_sway_clk_src",
.parent_data = gcc_xo_gpll0,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0),
@@ -3569,7 +3636,7 @@ static struct clk_rcg2 adss_pwm_clk_src = {
.freq_tbl = ftbl_adss_pwm_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "adss_pwm_clk_src",
.parent_data = gcc_xo_gpll0,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0),
@@ -3582,7 +3649,7 @@ static struct clk_branch gcc_adss_pwm_clk = {
.clkr = {
.enable_reg = 0x1c00c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_adss_pwm_clk",
.parent_hws = (const struct clk_hw *[]) {
&adss_pwm_clk_src.clkr.hw
@@ -3605,7 +3672,7 @@ static struct clk_rcg2 gp1_clk_src = {
.freq_tbl = ftbl_gp1_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_sleep_clk_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "gp1_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_sleep_clk,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_sleep_clk),
@@ -3618,7 +3685,7 @@ static struct clk_rcg2 gp2_clk_src = {
.freq_tbl = ftbl_gp1_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_sleep_clk_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "gp2_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_sleep_clk,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_sleep_clk),
@@ -3631,7 +3698,7 @@ static struct clk_rcg2 gp3_clk_src = {
.freq_tbl = ftbl_gp1_clk_src,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_gpll0_sleep_clk_map,
- .clkr.hw.init = &(struct clk_init_data) {
+ .clkr.hw.init = &(const struct clk_init_data) {
.name = "gp3_clk_src",
.parent_data = gcc_xo_gpll0_gpll0_sleep_clk,
.num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_sleep_clk),
@@ -3644,7 +3711,7 @@ static struct clk_branch gcc_xo_clk_src = {
.clkr = {
.enable_reg = 0x34004,
.enable_mask = BIT(1),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_xo_clk_src",
.parent_data = gcc_xo_data,
.num_parents = ARRAY_SIZE(gcc_xo_data),
@@ -3659,7 +3726,7 @@ static struct clk_branch gcc_nssnoc_xo_dcd_clk = {
.clkr = {
.enable_reg = 0x17074,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nssnoc_xo_dcd_clk",
.parent_hws = (const struct clk_hw *[]) {
&gcc_xo_clk_src.clkr.hw
@@ -3676,7 +3743,7 @@ static struct clk_branch gcc_xo_clk = {
.clkr = {
.enable_reg = 0x34018,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_xo_clk",
.parent_hws = (const struct clk_hw *[]) {
&gcc_xo_clk_src.clkr.hw
@@ -3693,7 +3760,7 @@ static struct clk_branch gcc_uniphy0_sys_clk = {
.clkr = {
.enable_reg = 0x17048,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_uniphy0_sys_clk",
.parent_hws = (const struct clk_hw *[]) {
&uniphy_sys_clk_src.clkr.hw
@@ -3710,7 +3777,7 @@ static struct clk_branch gcc_uniphy1_sys_clk = {
.clkr = {
.enable_reg = 0x17058,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_uniphy1_sys_clk",
.parent_hws = (const struct clk_hw *[]) {
&uniphy_sys_clk_src.clkr.hw
@@ -3727,7 +3794,7 @@ static struct clk_branch gcc_uniphy2_sys_clk = {
.clkr = {
.enable_reg = 0x17068,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_uniphy2_sys_clk",
.parent_hws = (const struct clk_hw *[]) {
&uniphy_sys_clk_src.clkr.hw
@@ -3744,7 +3811,7 @@ static struct clk_branch gcc_cmn_12gpll_sys_clk = {
.clkr = {
.enable_reg = 0x3a008,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_cmn_12gpll_sys_clk",
.parent_hws = (const struct clk_hw *[]) {
&uniphy_sys_clk_src.clkr.hw
@@ -3759,7 +3826,7 @@ static struct clk_branch gcc_cmn_12gpll_sys_clk = {
static struct clk_fixed_factor gcc_xo_div4_clk_src = {
.mult = 1,
.div = 4,
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_xo_div4_clk_src",
.parent_hws = (const struct clk_hw *[]) {
&gcc_xo_clk_src.clkr.hw
@@ -3775,7 +3842,7 @@ static struct clk_branch gcc_nssnoc_qosgen_ref_clk = {
.clkr = {
.enable_reg = 0x1701c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nssnoc_qosgen_ref_clk",
.parent_hws = (const struct clk_hw *[]) {
&gcc_xo_div4_clk_src.hw
@@ -3792,7 +3859,7 @@ static struct clk_branch gcc_nssnoc_timeout_ref_clk = {
.clkr = {
.enable_reg = 0x17020,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_nssnoc_timeout_ref_clk",
.parent_hws = (const struct clk_hw *[]) {
&gcc_xo_div4_clk_src.hw
@@ -3809,7 +3876,7 @@ static struct clk_branch gcc_xo_div4_clk = {
.clkr = {
.enable_reg = 0x3401c,
.enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data) {
+ .hw.init = &(const struct clk_init_data) {
.name = "gcc_xo_div4_clk",
.parent_hws = (const struct clk_hw *[]) {
&gcc_xo_div4_clk_src.hw
@@ -3880,6 +3947,10 @@ static struct clk_regmap *gcc_ipq9574_clks[] = {
[GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr,
[GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr,
[GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr,
+ [GCC_CRYPTO_AHB_CLK] = &gcc_crypto_ahb_clk.clkr,
+ [GCC_CRYPTO_AXI_CLK] = &gcc_crypto_axi_clk.clkr,
+ [GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr,
+ [GCC_CRYPTO_CLK_SRC] = &gcc_crypto_clk_src.clkr,
[PCIE0_AXI_M_CLK_SRC] = &pcie0_axi_m_clk_src.clkr,
[GCC_PCIE0_AXI_M_CLK] = &gcc_pcie0_axi_m_clk.clkr,
[PCIE1_AXI_M_CLK_SRC] = &pcie1_axi_m_clk_src.clkr,
@@ -4063,6 +4134,7 @@ static const struct qcom_reset_map gcc_ipq9574_resets[] = {
[GCC_CMN_BLK_AHB_ARES] = { 0x3a010, 0 },
[GCC_CMN_BLK_SYS_ARES] = { 0x3a010, 1 },
[GCC_CMN_BLK_APU_ARES] = { 0x3a010, 2 },
+ [GCC_CRYPTO_BCR] = { 0x16000, 0 },
[GCC_DCC_BCR] = { 0x35000, 0 },
[GCC_DDRSS_BCR] = { 0x11000, 0 },
[GCC_IMEM_BCR] = { 0x0e000, 0 },
diff --git a/drivers/clk/qcom/gcc-qcm2290.c b/drivers/clk/qcom/gcc-qcm2290.c
index 096deff2ba25..48995e50c6bd 100644
--- a/drivers/clk/qcom/gcc-qcm2290.c
+++ b/drivers/clk/qcom/gcc-qcm2290.c
@@ -650,7 +650,7 @@ static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = {
.name = "gcc_usb30_prim_mock_utmi_clk_src",
.parent_data = gcc_parents_0,
.num_parents = ARRAY_SIZE(gcc_parents_0),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -686,7 +686,7 @@ static struct clk_rcg2 gcc_camss_axi_clk_src = {
.name = "gcc_camss_axi_clk_src",
.parent_data = gcc_parents_4,
.num_parents = ARRAY_SIZE(gcc_parents_4),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -706,7 +706,7 @@ static struct clk_rcg2 gcc_camss_cci_clk_src = {
.name = "gcc_camss_cci_clk_src",
.parent_data = gcc_parents_9,
.num_parents = ARRAY_SIZE(gcc_parents_9),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -728,7 +728,7 @@ static struct clk_rcg2 gcc_camss_csi0phytimer_clk_src = {
.name = "gcc_camss_csi0phytimer_clk_src",
.parent_data = gcc_parents_5,
.num_parents = ARRAY_SIZE(gcc_parents_5),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -742,7 +742,7 @@ static struct clk_rcg2 gcc_camss_csi1phytimer_clk_src = {
.name = "gcc_camss_csi1phytimer_clk_src",
.parent_data = gcc_parents_5,
.num_parents = ARRAY_SIZE(gcc_parents_5),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -764,7 +764,7 @@ static struct clk_rcg2 gcc_camss_mclk0_clk_src = {
.parent_data = gcc_parents_3,
.num_parents = ARRAY_SIZE(gcc_parents_3),
.flags = CLK_OPS_PARENT_ENABLE,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -779,7 +779,7 @@ static struct clk_rcg2 gcc_camss_mclk1_clk_src = {
.parent_data = gcc_parents_3,
.num_parents = ARRAY_SIZE(gcc_parents_3),
.flags = CLK_OPS_PARENT_ENABLE,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -794,7 +794,7 @@ static struct clk_rcg2 gcc_camss_mclk2_clk_src = {
.parent_data = gcc_parents_3,
.num_parents = ARRAY_SIZE(gcc_parents_3),
.flags = CLK_OPS_PARENT_ENABLE,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -809,7 +809,7 @@ static struct clk_rcg2 gcc_camss_mclk3_clk_src = {
.parent_data = gcc_parents_3,
.num_parents = ARRAY_SIZE(gcc_parents_3),
.flags = CLK_OPS_PARENT_ENABLE,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -830,7 +830,7 @@ static struct clk_rcg2 gcc_camss_ope_ahb_clk_src = {
.name = "gcc_camss_ope_ahb_clk_src",
.parent_data = gcc_parents_6,
.num_parents = ARRAY_SIZE(gcc_parents_6),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -854,7 +854,7 @@ static struct clk_rcg2 gcc_camss_ope_clk_src = {
.parent_data = gcc_parents_6,
.num_parents = ARRAY_SIZE(gcc_parents_6),
.flags = CLK_SET_RATE_PARENT,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -888,7 +888,7 @@ static struct clk_rcg2 gcc_camss_tfe_0_clk_src = {
.name = "gcc_camss_tfe_0_clk_src",
.parent_data = gcc_parents_7,
.num_parents = ARRAY_SIZE(gcc_parents_7),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -912,7 +912,7 @@ static struct clk_rcg2 gcc_camss_tfe_0_csid_clk_src = {
.name = "gcc_camss_tfe_0_csid_clk_src",
.parent_data = gcc_parents_8,
.num_parents = ARRAY_SIZE(gcc_parents_8),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -926,7 +926,7 @@ static struct clk_rcg2 gcc_camss_tfe_1_clk_src = {
.name = "gcc_camss_tfe_1_clk_src",
.parent_data = gcc_parents_7,
.num_parents = ARRAY_SIZE(gcc_parents_7),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -940,7 +940,7 @@ static struct clk_rcg2 gcc_camss_tfe_1_csid_clk_src = {
.name = "gcc_camss_tfe_1_csid_clk_src",
.parent_data = gcc_parents_8,
.num_parents = ARRAY_SIZE(gcc_parents_8),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -963,7 +963,7 @@ static struct clk_rcg2 gcc_camss_tfe_cphy_rx_clk_src = {
.parent_data = gcc_parents_10,
.num_parents = ARRAY_SIZE(gcc_parents_10),
.flags = CLK_OPS_PARENT_ENABLE,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -984,7 +984,7 @@ static struct clk_rcg2 gcc_camss_top_ahb_clk_src = {
.name = "gcc_camss_top_ahb_clk_src",
.parent_data = gcc_parents_4,
.num_parents = ARRAY_SIZE(gcc_parents_4),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -1006,7 +1006,7 @@ static struct clk_rcg2 gcc_gp1_clk_src = {
.name = "gcc_gp1_clk_src",
.parent_data = gcc_parents_2,
.num_parents = ARRAY_SIZE(gcc_parents_2),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -1020,7 +1020,7 @@ static struct clk_rcg2 gcc_gp2_clk_src = {
.name = "gcc_gp2_clk_src",
.parent_data = gcc_parents_2,
.num_parents = ARRAY_SIZE(gcc_parents_2),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -1034,7 +1034,7 @@ static struct clk_rcg2 gcc_gp3_clk_src = {
.name = "gcc_gp3_clk_src",
.parent_data = gcc_parents_2,
.num_parents = ARRAY_SIZE(gcc_parents_2),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -1054,7 +1054,7 @@ static struct clk_rcg2 gcc_pdm2_clk_src = {
.name = "gcc_pdm2_clk_src",
.parent_data = gcc_parents_0,
.num_parents = ARRAY_SIZE(gcc_parents_0),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -1082,7 +1082,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = {
.name = "gcc_qupv3_wrap0_s0_clk_src",
.parent_data = gcc_parents_1,
.num_parents = ARRAY_SIZE(gcc_parents_1),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
};
static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = {
@@ -1098,7 +1098,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = {
.name = "gcc_qupv3_wrap0_s1_clk_src",
.parent_data = gcc_parents_1,
.num_parents = ARRAY_SIZE(gcc_parents_1),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
};
static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = {
@@ -1114,7 +1114,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = {
.name = "gcc_qupv3_wrap0_s2_clk_src",
.parent_data = gcc_parents_1,
.num_parents = ARRAY_SIZE(gcc_parents_1),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
};
static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = {
@@ -1130,7 +1130,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = {
.name = "gcc_qupv3_wrap0_s3_clk_src",
.parent_data = gcc_parents_1,
.num_parents = ARRAY_SIZE(gcc_parents_1),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
};
static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = {
@@ -1146,7 +1146,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = {
.name = "gcc_qupv3_wrap0_s4_clk_src",
.parent_data = gcc_parents_1,
.num_parents = ARRAY_SIZE(gcc_parents_1),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
};
static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = {
@@ -1162,7 +1162,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = {
.name = "gcc_qupv3_wrap0_s5_clk_src",
.parent_data = gcc_parents_1,
.num_parents = ARRAY_SIZE(gcc_parents_1),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
};
static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = {
@@ -1219,7 +1219,7 @@ static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = {
.name = "gcc_sdcc1_ice_core_clk_src",
.parent_data = gcc_parents_0,
.num_parents = ARRAY_SIZE(gcc_parents_0),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -1266,7 +1266,7 @@ static struct clk_rcg2 gcc_usb30_prim_master_clk_src = {
.name = "gcc_usb30_prim_master_clk_src",
.parent_data = gcc_parents_0,
.num_parents = ARRAY_SIZE(gcc_parents_0),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -1280,7 +1280,7 @@ static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = {
.name = "gcc_usb3_prim_phy_aux_clk_src",
.parent_data = gcc_parents_13,
.num_parents = ARRAY_SIZE(gcc_parents_13),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -1303,7 +1303,7 @@ static struct clk_rcg2 gcc_video_venus_clk_src = {
.parent_data = gcc_parents_14,
.num_parents = ARRAY_SIZE(gcc_parents_14),
.flags = CLK_SET_RATE_PARENT,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
diff --git a/drivers/clk/qcom/gcc-sc8280xp.c b/drivers/clk/qcom/gcc-sc8280xp.c
index 04a99dbaa57e..b90c71637814 100644
--- a/drivers/clk/qcom/gcc-sc8280xp.c
+++ b/drivers/clk/qcom/gcc-sc8280xp.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/regmap.h>
@@ -7421,9 +7422,19 @@ static int gcc_sc8280xp_probe(struct platform_device *pdev)
struct regmap *regmap;
int ret;
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
+
regmap = qcom_cc_map(pdev, &gcc_sc8280xp_desc);
- if (IS_ERR(regmap))
+ if (IS_ERR(regmap)) {
+ pm_runtime_put(&pdev->dev);
return PTR_ERR(regmap);
+ }
/*
* Keep the clocks always-ON
@@ -7445,7 +7456,10 @@ static int gcc_sc8280xp_probe(struct platform_device *pdev)
if (ret)
return ret;
- return qcom_cc_really_probe(pdev, &gcc_sc8280xp_desc, regmap);
+ ret = qcom_cc_really_probe(pdev, &gcc_sc8280xp_desc, regmap);
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
}
static const struct of_device_id gcc_sc8280xp_match_table[] = {
diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c
index db918c92a522..6afce8e42ede 100644
--- a/drivers/clk/qcom/gcc-sdm660.c
+++ b/drivers/clk/qcom/gcc-sdm660.c
@@ -25,8 +25,6 @@
#include "reset.h"
#include "gdsc.h"
-#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
-
enum {
P_XO,
P_SLEEP_CLK,
diff --git a/drivers/clk/qcom/gcc-sdx75.c b/drivers/clk/qcom/gcc-sdx75.c
new file mode 100644
index 000000000000..b6772abdcec5
--- /dev/null
+++ b/drivers/clk/qcom/gcc-sdx75.c
@@ -0,0 +1,2970 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sdx75-gcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "clk-regmap-phy-mux.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_BI_TCXO,
+ DT_SLEEP_CLK,
+ DT_EMAC0_SGMIIPHY_MAC_RCLK,
+ DT_EMAC0_SGMIIPHY_MAC_TCLK,
+ DT_EMAC0_SGMIIPHY_RCLK,
+ DT_EMAC0_SGMIIPHY_TCLK,
+ DT_EMAC1_SGMIIPHY_MAC_RCLK,
+ DT_EMAC1_SGMIIPHY_MAC_TCLK,
+ DT_EMAC1_SGMIIPHY_RCLK,
+ DT_EMAC1_SGMIIPHY_TCLK,
+ DT_PCIE20_PHY_AUX_CLK,
+ DT_PCIE_1_PIPE_CLK,
+ DT_PCIE_2_PIPE_CLK,
+ DT_PCIE_PIPE_CLK,
+ DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK,
+};
+
+enum {
+ P_BI_TCXO,
+ P_EMAC0_SGMIIPHY_MAC_RCLK,
+ P_EMAC0_SGMIIPHY_MAC_TCLK,
+ P_EMAC0_SGMIIPHY_RCLK,
+ P_EMAC0_SGMIIPHY_TCLK,
+ P_EMAC1_SGMIIPHY_MAC_RCLK,
+ P_EMAC1_SGMIIPHY_MAC_TCLK,
+ P_EMAC1_SGMIIPHY_RCLK,
+ P_EMAC1_SGMIIPHY_TCLK,
+ P_GPLL0_OUT_EVEN,
+ P_GPLL0_OUT_MAIN,
+ P_GPLL4_OUT_MAIN,
+ P_GPLL5_OUT_MAIN,
+ P_GPLL6_OUT_MAIN,
+ P_GPLL8_OUT_MAIN,
+ P_PCIE20_PHY_AUX_CLK,
+ P_PCIE_1_PIPE_CLK,
+ P_PCIE_2_PIPE_CLK,
+ P_PCIE_PIPE_CLK,
+ P_SLEEP_CLK,
+ P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK,
+};
+
+static struct clk_alpha_pll gpll0 = {
+ .offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x7d000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_ole_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll0_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll0_out_even = {
+ .offset = 0x0,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_gpll0_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll0_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpll0_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll4 = {
+ .offset = 0x4000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x7d000,
+ .enable_mask = BIT(4),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpll4",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_ole_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll gpll5 = {
+ .offset = 0x5000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x7d000,
+ .enable_mask = BIT(5),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpll5",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_ole_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll gpll6 = {
+ .offset = 0x6000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x7d000,
+ .enable_mask = BIT(6),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpll6",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_ole_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll gpll8 = {
+ .offset = 0x8000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x7d000,
+ .enable_mask = BIT(8),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpll8",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_ole_ops,
+ },
+ },
+};
+
+static const struct parent_map gcc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_GPLL4_OUT_MAIN, 2 },
+ { P_GPLL5_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+ { .hw = &gpll5.clkr.hw },
+ { .hw = &gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_SLEEP_CLK, 5 },
+ { P_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpll0.clkr.hw },
+ { .index = DT_SLEEP_CLK },
+ { .hw = &gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_SLEEP_CLK, 5 },
+};
+
+static const struct clk_parent_data gcc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map gcc_parent_map_4[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_SLEEP_CLK, 5 },
+};
+
+static const struct clk_parent_data gcc_parent_data_4[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpll0.clkr.hw },
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map gcc_parent_map_5[] = {
+ { P_EMAC0_SGMIIPHY_RCLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_5[] = {
+ { .index = DT_EMAC0_SGMIIPHY_RCLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_6[] = {
+ { P_EMAC0_SGMIIPHY_TCLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_6[] = {
+ { .index = DT_EMAC0_SGMIIPHY_TCLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_7[] = {
+ { P_EMAC0_SGMIIPHY_MAC_RCLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_7[] = {
+ { .index = DT_EMAC0_SGMIIPHY_MAC_RCLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_8[] = {
+ { P_EMAC0_SGMIIPHY_MAC_TCLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_8[] = {
+ { .index = DT_EMAC0_SGMIIPHY_MAC_TCLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_9[] = {
+ { P_EMAC1_SGMIIPHY_RCLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_9[] = {
+ { .index = DT_EMAC1_SGMIIPHY_RCLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_10[] = {
+ { P_EMAC1_SGMIIPHY_TCLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_10[] = {
+ { .index = DT_EMAC1_SGMIIPHY_TCLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_11[] = {
+ { P_EMAC1_SGMIIPHY_MAC_RCLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_11[] = {
+ { .index = DT_EMAC1_SGMIIPHY_MAC_RCLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_12[] = {
+ { P_EMAC1_SGMIIPHY_MAC_TCLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_12[] = {
+ { .index = DT_EMAC1_SGMIIPHY_MAC_TCLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_15[] = {
+ { P_PCIE20_PHY_AUX_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_15[] = {
+ { .index = DT_PCIE20_PHY_AUX_CLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_17[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_GPLL6_OUT_MAIN, 2 },
+ { P_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_17[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_18[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_GPLL8_OUT_MAIN, 2 },
+ { P_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_18[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll8.clkr.hw },
+ { .hw = &gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_19[] = {
+ { P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_19[] = {
+ { .index = DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK },
+ { .index = DT_BI_TCXO },
+};
+
+static struct clk_regmap_mux gcc_emac0_cc_sgmiiphy_rx_clk_src = {
+ .reg = 0x71060,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_5,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_cc_sgmiiphy_rx_clk_src",
+ .parent_data = gcc_parent_data_5,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_5),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_emac0_cc_sgmiiphy_tx_clk_src = {
+ .reg = 0x71058,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_6,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_cc_sgmiiphy_tx_clk_src",
+ .parent_data = gcc_parent_data_6,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_6),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_emac0_sgmiiphy_mac_rclk_src = {
+ .reg = 0x71098,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_7,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_sgmiiphy_mac_rclk_src",
+ .parent_data = gcc_parent_data_7,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_7),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_emac0_sgmiiphy_mac_tclk_src = {
+ .reg = 0x71094,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_8,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_sgmiiphy_mac_tclk_src",
+ .parent_data = gcc_parent_data_8,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_8),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_emac1_cc_sgmiiphy_rx_clk_src = {
+ .reg = 0x72060,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_9,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_cc_sgmiiphy_rx_clk_src",
+ .parent_data = gcc_parent_data_9,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_9),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_emac1_cc_sgmiiphy_tx_clk_src = {
+ .reg = 0x72058,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_10,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_cc_sgmiiphy_tx_clk_src",
+ .parent_data = gcc_parent_data_10,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_10),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_emac1_sgmiiphy_mac_rclk_src = {
+ .reg = 0x72098,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_11,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_sgmiiphy_mac_rclk_src",
+ .parent_data = gcc_parent_data_11,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_11),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_emac1_sgmiiphy_mac_tclk_src = {
+ .reg = 0x72094,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_12,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_sgmiiphy_mac_tclk_src",
+ .parent_data = gcc_parent_data_12,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_12),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_phy_mux gcc_pcie_1_pipe_clk_src = {
+ .reg = 0x67084,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_PCIE_1_PIPE_CLK,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_regmap_phy_mux gcc_pcie_2_pipe_clk_src = {
+ .reg = 0x68050,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_PCIE_2_PIPE_CLK,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_pcie_aux_clk_src = {
+ .reg = 0x53074,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_15,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_aux_clk_src",
+ .parent_data = gcc_parent_data_15,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_15),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_phy_mux gcc_pcie_pipe_clk_src = {
+ .reg = 0x53058,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_PCIE_PIPE_CLK,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_usb3_phy_pipe_clk_src = {
+ .reg = 0x27070,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_19,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_phy_pipe_clk_src",
+ .parent_data = gcc_parent_data_19,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_19),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_eee_emac0_clk_src[] = {
+ F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_eee_emac0_clk_src = {
+ .cmd_rcgr = 0x710b0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_eee_emac0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_eee_emac0_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_eee_emac1_clk_src = {
+ .cmd_rcgr = 0x720b0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_eee_emac0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_eee_emac1_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_emac0_phy_aux_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_emac0_phy_aux_clk_src = {
+ .cmd_rcgr = 0x7102c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_phy_aux_clk_src",
+ .parent_data = gcc_parent_data_4,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_4),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_emac0_ptp_clk_src[] = {
+ F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(125000000, P_GPLL4_OUT_MAIN, 4, 0, 0),
+ F(230400000, P_GPLL5_OUT_MAIN, 3.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_emac0_ptp_clk_src = {
+ .cmd_rcgr = 0x7107c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_emac0_ptp_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_ptp_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_emac0_rgmii_clk_src[] = {
+ F(5000000, P_GPLL0_OUT_EVEN, 10, 1, 6),
+ F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(125000000, P_GPLL4_OUT_MAIN, 4, 0, 0),
+ F(250000000, P_GPLL4_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_emac0_rgmii_clk_src = {
+ .cmd_rcgr = 0x71064,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_emac0_rgmii_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_rgmii_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_emac1_phy_aux_clk_src = {
+ .cmd_rcgr = 0x7202c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_phy_aux_clk_src",
+ .parent_data = gcc_parent_data_4,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_4),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_emac1_ptp_clk_src = {
+ .cmd_rcgr = 0x7207c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_emac0_ptp_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_ptp_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_emac1_rgmii_clk_src = {
+ .cmd_rcgr = 0x72064,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_emac0_rgmii_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_rgmii_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
+ F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_gp1_clk_src = {
+ .cmd_rcgr = 0x47004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp1_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp2_clk_src = {
+ .cmd_rcgr = 0x48004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp2_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp3_clk_src = {
+ .cmd_rcgr = 0x49004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp3_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie_1_aux_phy_clk_src = {
+ .cmd_rcgr = 0x67044,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_aux_phy_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_1_phy_rchng_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pcie_1_phy_rchng_clk_src = {
+ .cmd_rcgr = 0x6706c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie_1_phy_rchng_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_phy_rchng_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie_2_aux_phy_clk_src = {
+ .cmd_rcgr = 0x68064,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_aux_phy_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie_2_phy_rchng_clk_src = {
+ .cmd_rcgr = 0x68038,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie_1_phy_rchng_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_phy_rchng_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie_aux_phy_clk_src = {
+ .cmd_rcgr = 0x5305c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_aux_phy_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie_rchng_phy_clk_src = {
+ .cmd_rcgr = 0x53078,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie_1_phy_rchng_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_rchng_phy_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pdm2_clk_src = {
+ .cmd_rcgr = 0x34010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pdm2_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
+ F(7372800, P_GPLL0_OUT_EVEN, 1, 384, 15625),
+ F(14745600, P_GPLL0_OUT_EVEN, 1, 768, 15625),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(29491200, P_GPLL0_OUT_EVEN, 1, 1536, 15625),
+ F(32000000, P_GPLL0_OUT_EVEN, 1, 8, 75),
+ F(48000000, P_GPLL0_OUT_EVEN, 1, 4, 25),
+ F(64000000, P_GPLL0_OUT_EVEN, 1, 16, 75),
+ F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(80000000, P_GPLL0_OUT_EVEN, 1, 4, 15),
+ F(96000000, P_GPLL0_OUT_EVEN, 1, 8, 25),
+ F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
+ { }
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = {
+ .cmd_rcgr = 0x6c010,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = {
+ .cmd_rcgr = 0x6c148,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = {
+ .cmd_rcgr = 0x6c280,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s3_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = {
+ .cmd_rcgr = 0x6c3b8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s4_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = {
+ .cmd_rcgr = 0x6c4f0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s5_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = {
+ .cmd_rcgr = 0x6c628,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s6_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s6_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s6_clk_src = {
+ .cmd_rcgr = 0x6c760,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s6_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s7_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s7_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s7_clk_src = {
+ .cmd_rcgr = 0x6c898,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s7_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s8_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s8_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s8_clk_src = {
+ .cmd_rcgr = 0x6c9d0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s8_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = {
+ F(144000, P_BI_TCXO, 16, 3, 25),
+ F(400000, P_BI_TCXO, 12, 1, 4),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(20000000, P_GPLL0_OUT_EVEN, 5, 1, 3),
+ F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
+ F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0),
+ F(192000000, P_GPLL6_OUT_MAIN, 2, 0, 0),
+ F(384000000, P_GPLL6_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0x6b014,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_17,
+ .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_apps_clk_src",
+ .parent_data = gcc_parent_data_17,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_17),
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
+ F(400000, P_BI_TCXO, 12, 1, 4),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
+ F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0),
+ F(202000000, P_GPLL8_OUT_MAIN, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
+ .cmd_rcgr = 0x6a018,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_18,
+ .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc2_apps_clk_src",
+ .parent_data = gcc_parent_data_18,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_18),
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_master_clk_src[] = {
+ F(200000000, P_GPLL0_OUT_EVEN, 1.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb30_master_clk_src = {
+ .cmd_rcgr = 0x27034,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_usb30_master_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_master_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb30_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x2704c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_mock_utmi_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb3_phy_aux_clk_src[] = {
+ F(1000000, P_BI_TCXO, 1, 5, 96),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb3_phy_aux_clk_src = {
+ .cmd_rcgr = 0x27074,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_usb3_phy_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_phy_aux_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_pcie_1_pipe_div2_clk_src = {
+ .reg = 0x67088,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_pipe_div2_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_1_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_pcie_2_pipe_div2_clk_src = {
+ .reg = 0x68088,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_pipe_div2_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_2_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_usb30_mock_utmi_postdiv_clk_src = {
+ .reg = 0x27064,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_mock_utmi_postdiv_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb30_mock_utmi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .halt_reg = 0x37004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x37004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(26),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_boot_rom_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_eee_emac0_clk = {
+ .halt_reg = 0x710ac,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x710ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_eee_emac0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_eee_emac0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_eee_emac1_clk = {
+ .halt_reg = 0x720ac,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x720ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_eee_emac1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_eee_emac1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_axi_clk = {
+ .halt_reg = 0x71018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x71018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x71018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_cc_sgmiiphy_rx_clk = {
+ .halt_reg = 0x7105c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x7105c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_cc_sgmiiphy_rx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac0_cc_sgmiiphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_cc_sgmiiphy_tx_clk = {
+ .halt_reg = 0x71054,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x71054,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_cc_sgmiiphy_tx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac0_cc_sgmiiphy_tx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_phy_aux_clk = {
+ .halt_reg = 0x71028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x71028,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_phy_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac0_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_ptp_clk = {
+ .halt_reg = 0x71044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x71044,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_ptp_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac0_ptp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_rgmii_clk = {
+ .halt_reg = 0x71050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x71050,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_rgmii_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac0_rgmii_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_rpcs_rx_clk = {
+ .halt_reg = 0x710a0,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x710a0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_rpcs_rx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac0_sgmiiphy_mac_rclk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_rpcs_tx_clk = {
+ .halt_reg = 0x7109c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x7109c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_rpcs_tx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac0_sgmiiphy_mac_tclk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_slv_ahb_clk = {
+ .halt_reg = 0x71024,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x71024,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x71024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_slv_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_xgxs_rx_clk = {
+ .halt_reg = 0x710a8,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x710a8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_xgxs_rx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac0_sgmiiphy_mac_rclk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_xgxs_tx_clk = {
+ .halt_reg = 0x710a4,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x710a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_xgxs_tx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac0_sgmiiphy_mac_tclk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac1_axi_clk = {
+ .halt_reg = 0x72018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x72018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x72018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac1_cc_sgmiiphy_rx_clk = {
+ .halt_reg = 0x7205c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x7205c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_cc_sgmiiphy_rx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac1_cc_sgmiiphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac1_cc_sgmiiphy_tx_clk = {
+ .halt_reg = 0x72054,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x72054,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_cc_sgmiiphy_tx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac1_cc_sgmiiphy_tx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac1_phy_aux_clk = {
+ .halt_reg = 0x72028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x72028,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_phy_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac1_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac1_ptp_clk = {
+ .halt_reg = 0x72044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x72044,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_ptp_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac1_ptp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac1_rgmii_clk = {
+ .halt_reg = 0x72050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x72050,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_rgmii_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac1_rgmii_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac1_rpcs_rx_clk = {
+ .halt_reg = 0x720a0,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x720a0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_rpcs_rx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac1_sgmiiphy_mac_rclk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac1_rpcs_tx_clk = {
+ .halt_reg = 0x7209c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x7209c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_rpcs_tx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac1_sgmiiphy_mac_tclk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac1_slv_ahb_clk = {
+ .halt_reg = 0x72024,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x72024,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x72024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_slv_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac1_xgxs_rx_clk = {
+ .halt_reg = 0x720a8,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x720a8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_xgxs_rx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac1_sgmiiphy_mac_rclk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac1_xgxs_tx_clk = {
+ .halt_reg = 0x720a4,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x720a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac1_xgxs_tx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac1_sgmiiphy_mac_tclk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac_0_clkref_en = {
+ .halt_reg = 0x98108,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x98108,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac_0_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac_1_clkref_en = {
+ .halt_reg = 0x9810c,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x9810c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac_1_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x47000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x47000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+ .halt_reg = 0x48000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x48000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+ .halt_reg = 0x49000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x49000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_clkref_en = {
+ .halt_reg = 0x98004,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x98004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_aux_clk = {
+ .halt_reg = 0x67038,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(22),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_1_aux_phy_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_cfg_ahb_clk = {
+ .halt_reg = 0x67034,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x67034,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(21),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_clkref_en = {
+ .halt_reg = 0x98114,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x98114,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_mstr_axi_clk = {
+ .halt_reg = 0x67028,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(20),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_mstr_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_phy_rchng_clk = {
+ .halt_reg = 0x67068,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(24),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_phy_rchng_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_1_phy_rchng_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_pipe_clk = {
+ .halt_reg = 0x6705c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(23),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_pipe_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_1_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_pipe_div2_clk = {
+ .halt_reg = 0x6708c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x7d020,
+ .enable_mask = BIT(3),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_pipe_div2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_1_pipe_div2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_slv_axi_clk = {
+ .halt_reg = 0x6701c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(19),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_slv_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_slv_q2a_axi_clk = {
+ .halt_reg = 0x67018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(18),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_slv_q2a_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_2_aux_clk = {
+ .halt_reg = 0x68058,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(29),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_2_aux_phy_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_2_cfg_ahb_clk = {
+ .halt_reg = 0x68034,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x68034,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(28),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_2_clkref_en = {
+ .halt_reg = 0x98110,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x98110,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_2_mstr_axi_clk = {
+ .halt_reg = 0x68028,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(8),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_mstr_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_2_phy_rchng_clk = {
+ .halt_reg = 0x68098,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(31),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_phy_rchng_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_2_phy_rchng_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_2_pipe_clk = {
+ .halt_reg = 0x6807c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(30),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_pipe_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_2_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_2_pipe_div2_clk = {
+ .halt_reg = 0x6808c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x7d020,
+ .enable_mask = BIT(4),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_pipe_div2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_2_pipe_div2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_2_slv_axi_clk = {
+ .halt_reg = 0x6801c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(26),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_slv_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_2_slv_q2a_axi_clk = {
+ .halt_reg = 0x68018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(25),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_2_slv_q2a_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_aux_clk = {
+ .halt_reg = 0x5303c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x5303c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(15),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_cfg_ahb_clk = {
+ .halt_reg = 0x53034,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x53034,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(13),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_mstr_axi_clk = {
+ .halt_reg = 0x53028,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x53028,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(12),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_mstr_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_pipe_clk = {
+ .halt_reg = 0x5304c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x5304c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(17),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_pipe_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_rchng_phy_clk = {
+ .halt_reg = 0x53038,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x53038,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(14),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_rchng_phy_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_rchng_phy_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_sleep_clk = {
+ .halt_reg = 0x53048,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x53048,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(16),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_sleep_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_aux_phy_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_slv_axi_clk = {
+ .halt_reg = 0x5301c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(11),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_slv_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_slv_q2a_axi_clk = {
+ .halt_reg = 0x53018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x53018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(10),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_slv_q2a_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+ .halt_reg = 0x3400c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3400c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pdm2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+ .halt_reg = 0x34004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x34004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_xo4_clk = {
+ .halt_reg = 0x34008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x34008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm_xo4_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = {
+ .halt_reg = 0x2d018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(15),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_core_2x_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_core_clk = {
+ .halt_reg = 0x2d008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(14),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s0_clk = {
+ .halt_reg = 0x6c004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(16),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s1_clk = {
+ .halt_reg = 0x6c13c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(17),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s2_clk = {
+ .halt_reg = 0x6c274,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(18),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s3_clk = {
+ .halt_reg = 0x6c3ac,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(19),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s4_clk = {
+ .halt_reg = 0x6c4e4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(20),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s4_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s5_clk = {
+ .halt_reg = 0x6c61c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(21),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s5_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s5_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s6_clk = {
+ .halt_reg = 0x6c754,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(22),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s6_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s6_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s7_clk = {
+ .halt_reg = 0x6c88c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(23),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s7_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s7_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s8_clk = {
+ .halt_reg = 0x6c9c4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7d020,
+ .enable_mask = BIT(7),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s8_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s8_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = {
+ .halt_reg = 0x2d000,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x2d000,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(12),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_0_m_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = {
+ .halt_reg = 0x2d004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x2d004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(13),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_0_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .halt_reg = 0x6b004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x6b004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0x6b008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x6b008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sdcc1_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+ .halt_reg = 0x6a010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x6a010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+ .halt_reg = 0x6a004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x6a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc2_apps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sdcc2_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb2_clkref_en = {
+ .halt_reg = 0x98008,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x98008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb2_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_master_clk = {
+ .halt_reg = 0x27018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x27018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_master_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb30_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_mock_utmi_clk = {
+ .halt_reg = 0x27030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x27030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_mock_utmi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb30_mock_utmi_postdiv_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_mstr_axi_clk = {
+ .halt_reg = 0x27024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x27024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_mstr_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_sleep_clk = {
+ .halt_reg = 0x2702c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2702c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_slv_ahb_clk = {
+ .halt_reg = 0x27028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x27028,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_slv_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_phy_aux_clk = {
+ .halt_reg = 0x27068,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x27068,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_phy_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb3_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_phy_pipe_clk = {
+ .halt_reg = 0x2706c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x2706c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x2706c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_phy_pipe_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb3_phy_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_clkref_en = {
+ .halt_reg = 0x98000,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x98000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = {
+ .halt_reg = 0x29004,
+ .halt_check = BRANCH_HALT,
+ .hwcg_reg = 0x29004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x29004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb_phy_cfg_ahb2phy_clk",
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct gdsc gcc_emac0_gdsc = {
+ .gdscr = 0x71004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_emac0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gcc_emac1_gdsc = {
+ .gdscr = 0x72004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_emac1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gcc_pcie_1_gdsc = {
+ .gdscr = 0x67004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_pcie_1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gcc_pcie_1_phy_gdsc = {
+ .gdscr = 0x56004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x2,
+ .pd = {
+ .name = "gcc_pcie_1_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gcc_pcie_2_gdsc = {
+ .gdscr = 0x68004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_pcie_2_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gcc_pcie_2_phy_gdsc = {
+ .gdscr = 0x6e004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x2,
+ .pd = {
+ .name = "gcc_pcie_2_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gcc_pcie_gdsc = {
+ .gdscr = 0x53004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_pcie_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gcc_pcie_phy_gdsc = {
+ .gdscr = 0x54004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x2,
+ .pd = {
+ .name = "gcc_pcie_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gcc_usb30_gdsc = {
+ .gdscr = 0x27004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_usb30_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gcc_usb3_phy_gdsc = {
+ .gdscr = 0x28008,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x2,
+ .pd = {
+ .name = "gcc_usb3_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct clk_regmap *gcc_sdx75_clocks[] = {
+ [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+ [GCC_EEE_EMAC0_CLK] = &gcc_eee_emac0_clk.clkr,
+ [GCC_EEE_EMAC0_CLK_SRC] = &gcc_eee_emac0_clk_src.clkr,
+ [GCC_EEE_EMAC1_CLK] = &gcc_eee_emac1_clk.clkr,
+ [GCC_EEE_EMAC1_CLK_SRC] = &gcc_eee_emac1_clk_src.clkr,
+ [GCC_EMAC0_AXI_CLK] = &gcc_emac0_axi_clk.clkr,
+ [GCC_EMAC0_CC_SGMIIPHY_RX_CLK] = &gcc_emac0_cc_sgmiiphy_rx_clk.clkr,
+ [GCC_EMAC0_CC_SGMIIPHY_RX_CLK_SRC] = &gcc_emac0_cc_sgmiiphy_rx_clk_src.clkr,
+ [GCC_EMAC0_CC_SGMIIPHY_TX_CLK] = &gcc_emac0_cc_sgmiiphy_tx_clk.clkr,
+ [GCC_EMAC0_CC_SGMIIPHY_TX_CLK_SRC] = &gcc_emac0_cc_sgmiiphy_tx_clk_src.clkr,
+ [GCC_EMAC0_PHY_AUX_CLK] = &gcc_emac0_phy_aux_clk.clkr,
+ [GCC_EMAC0_PHY_AUX_CLK_SRC] = &gcc_emac0_phy_aux_clk_src.clkr,
+ [GCC_EMAC0_PTP_CLK] = &gcc_emac0_ptp_clk.clkr,
+ [GCC_EMAC0_PTP_CLK_SRC] = &gcc_emac0_ptp_clk_src.clkr,
+ [GCC_EMAC0_RGMII_CLK] = &gcc_emac0_rgmii_clk.clkr,
+ [GCC_EMAC0_RGMII_CLK_SRC] = &gcc_emac0_rgmii_clk_src.clkr,
+ [GCC_EMAC0_RPCS_RX_CLK] = &gcc_emac0_rpcs_rx_clk.clkr,
+ [GCC_EMAC0_RPCS_TX_CLK] = &gcc_emac0_rpcs_tx_clk.clkr,
+ [GCC_EMAC0_SGMIIPHY_MAC_RCLK_SRC] = &gcc_emac0_sgmiiphy_mac_rclk_src.clkr,
+ [GCC_EMAC0_SGMIIPHY_MAC_TCLK_SRC] = &gcc_emac0_sgmiiphy_mac_tclk_src.clkr,
+ [GCC_EMAC0_SLV_AHB_CLK] = &gcc_emac0_slv_ahb_clk.clkr,
+ [GCC_EMAC0_XGXS_RX_CLK] = &gcc_emac0_xgxs_rx_clk.clkr,
+ [GCC_EMAC0_XGXS_TX_CLK] = &gcc_emac0_xgxs_tx_clk.clkr,
+ [GCC_EMAC1_AXI_CLK] = &gcc_emac1_axi_clk.clkr,
+ [GCC_EMAC1_CC_SGMIIPHY_RX_CLK] = &gcc_emac1_cc_sgmiiphy_rx_clk.clkr,
+ [GCC_EMAC1_CC_SGMIIPHY_RX_CLK_SRC] = &gcc_emac1_cc_sgmiiphy_rx_clk_src.clkr,
+ [GCC_EMAC1_CC_SGMIIPHY_TX_CLK] = &gcc_emac1_cc_sgmiiphy_tx_clk.clkr,
+ [GCC_EMAC1_CC_SGMIIPHY_TX_CLK_SRC] = &gcc_emac1_cc_sgmiiphy_tx_clk_src.clkr,
+ [GCC_EMAC1_PHY_AUX_CLK] = &gcc_emac1_phy_aux_clk.clkr,
+ [GCC_EMAC1_PHY_AUX_CLK_SRC] = &gcc_emac1_phy_aux_clk_src.clkr,
+ [GCC_EMAC1_PTP_CLK] = &gcc_emac1_ptp_clk.clkr,
+ [GCC_EMAC1_PTP_CLK_SRC] = &gcc_emac1_ptp_clk_src.clkr,
+ [GCC_EMAC1_RGMII_CLK] = &gcc_emac1_rgmii_clk.clkr,
+ [GCC_EMAC1_RGMII_CLK_SRC] = &gcc_emac1_rgmii_clk_src.clkr,
+ [GCC_EMAC1_RPCS_RX_CLK] = &gcc_emac1_rpcs_rx_clk.clkr,
+ [GCC_EMAC1_RPCS_TX_CLK] = &gcc_emac1_rpcs_tx_clk.clkr,
+ [GCC_EMAC1_SGMIIPHY_MAC_RCLK_SRC] = &gcc_emac1_sgmiiphy_mac_rclk_src.clkr,
+ [GCC_EMAC1_SGMIIPHY_MAC_TCLK_SRC] = &gcc_emac1_sgmiiphy_mac_tclk_src.clkr,
+ [GCC_EMAC1_SLV_AHB_CLK] = &gcc_emac1_slv_ahb_clk.clkr,
+ [GCC_EMAC1_XGXS_RX_CLK] = &gcc_emac1_xgxs_rx_clk.clkr,
+ [GCC_EMAC1_XGXS_TX_CLK] = &gcc_emac1_xgxs_tx_clk.clkr,
+ [GCC_EMAC_0_CLKREF_EN] = &gcc_emac_0_clkref_en.clkr,
+ [GCC_EMAC_1_CLKREF_EN] = &gcc_emac_1_clkref_en.clkr,
+ [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+ [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr,
+ [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+ [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr,
+ [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+ [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr,
+ [GCC_PCIE_0_CLKREF_EN] = &gcc_pcie_0_clkref_en.clkr,
+ [GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr,
+ [GCC_PCIE_1_AUX_PHY_CLK_SRC] = &gcc_pcie_1_aux_phy_clk_src.clkr,
+ [GCC_PCIE_1_CFG_AHB_CLK] = &gcc_pcie_1_cfg_ahb_clk.clkr,
+ [GCC_PCIE_1_CLKREF_EN] = &gcc_pcie_1_clkref_en.clkr,
+ [GCC_PCIE_1_MSTR_AXI_CLK] = &gcc_pcie_1_mstr_axi_clk.clkr,
+ [GCC_PCIE_1_PHY_RCHNG_CLK] = &gcc_pcie_1_phy_rchng_clk.clkr,
+ [GCC_PCIE_1_PHY_RCHNG_CLK_SRC] = &gcc_pcie_1_phy_rchng_clk_src.clkr,
+ [GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr,
+ [GCC_PCIE_1_PIPE_CLK_SRC] = &gcc_pcie_1_pipe_clk_src.clkr,
+ [GCC_PCIE_1_PIPE_DIV2_CLK] = &gcc_pcie_1_pipe_div2_clk.clkr,
+ [GCC_PCIE_1_PIPE_DIV2_CLK_SRC] = &gcc_pcie_1_pipe_div2_clk_src.clkr,
+ [GCC_PCIE_1_SLV_AXI_CLK] = &gcc_pcie_1_slv_axi_clk.clkr,
+ [GCC_PCIE_1_SLV_Q2A_AXI_CLK] = &gcc_pcie_1_slv_q2a_axi_clk.clkr,
+ [GCC_PCIE_2_AUX_CLK] = &gcc_pcie_2_aux_clk.clkr,
+ [GCC_PCIE_2_AUX_PHY_CLK_SRC] = &gcc_pcie_2_aux_phy_clk_src.clkr,
+ [GCC_PCIE_2_CFG_AHB_CLK] = &gcc_pcie_2_cfg_ahb_clk.clkr,
+ [GCC_PCIE_2_CLKREF_EN] = &gcc_pcie_2_clkref_en.clkr,
+ [GCC_PCIE_2_MSTR_AXI_CLK] = &gcc_pcie_2_mstr_axi_clk.clkr,
+ [GCC_PCIE_2_PHY_RCHNG_CLK] = &gcc_pcie_2_phy_rchng_clk.clkr,
+ [GCC_PCIE_2_PHY_RCHNG_CLK_SRC] = &gcc_pcie_2_phy_rchng_clk_src.clkr,
+ [GCC_PCIE_2_PIPE_CLK] = &gcc_pcie_2_pipe_clk.clkr,
+ [GCC_PCIE_2_PIPE_CLK_SRC] = &gcc_pcie_2_pipe_clk_src.clkr,
+ [GCC_PCIE_2_PIPE_DIV2_CLK] = &gcc_pcie_2_pipe_div2_clk.clkr,
+ [GCC_PCIE_2_PIPE_DIV2_CLK_SRC] = &gcc_pcie_2_pipe_div2_clk_src.clkr,
+ [GCC_PCIE_2_SLV_AXI_CLK] = &gcc_pcie_2_slv_axi_clk.clkr,
+ [GCC_PCIE_2_SLV_Q2A_AXI_CLK] = &gcc_pcie_2_slv_q2a_axi_clk.clkr,
+ [GCC_PCIE_AUX_CLK] = &gcc_pcie_aux_clk.clkr,
+ [GCC_PCIE_AUX_CLK_SRC] = &gcc_pcie_aux_clk_src.clkr,
+ [GCC_PCIE_AUX_PHY_CLK_SRC] = &gcc_pcie_aux_phy_clk_src.clkr,
+ [GCC_PCIE_CFG_AHB_CLK] = &gcc_pcie_cfg_ahb_clk.clkr,
+ [GCC_PCIE_MSTR_AXI_CLK] = &gcc_pcie_mstr_axi_clk.clkr,
+ [GCC_PCIE_PIPE_CLK] = &gcc_pcie_pipe_clk.clkr,
+ [GCC_PCIE_PIPE_CLK_SRC] = &gcc_pcie_pipe_clk_src.clkr,
+ [GCC_PCIE_RCHNG_PHY_CLK] = &gcc_pcie_rchng_phy_clk.clkr,
+ [GCC_PCIE_RCHNG_PHY_CLK_SRC] = &gcc_pcie_rchng_phy_clk_src.clkr,
+ [GCC_PCIE_SLEEP_CLK] = &gcc_pcie_sleep_clk.clkr,
+ [GCC_PCIE_SLV_AXI_CLK] = &gcc_pcie_slv_axi_clk.clkr,
+ [GCC_PCIE_SLV_Q2A_AXI_CLK] = &gcc_pcie_slv_q2a_axi_clk.clkr,
+ [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+ [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr,
+ [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+ [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr,
+ [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr,
+ [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr,
+ [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr,
+ [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr,
+ [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr,
+ [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr,
+ [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr,
+ [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr,
+ [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S6_CLK] = &gcc_qupv3_wrap0_s6_clk.clkr,
+ [GCC_QUPV3_WRAP0_S6_CLK_SRC] = &gcc_qupv3_wrap0_s6_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S7_CLK] = &gcc_qupv3_wrap0_s7_clk.clkr,
+ [GCC_QUPV3_WRAP0_S7_CLK_SRC] = &gcc_qupv3_wrap0_s7_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S8_CLK] = &gcc_qupv3_wrap0_s8_clk.clkr,
+ [GCC_QUPV3_WRAP0_S8_CLK_SRC] = &gcc_qupv3_wrap0_s8_clk_src.clkr,
+ [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr,
+ [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr,
+ [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
+ [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+ [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr,
+ [GCC_USB2_CLKREF_EN] = &gcc_usb2_clkref_en.clkr,
+ [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
+ [GCC_USB30_MASTER_CLK_SRC] = &gcc_usb30_master_clk_src.clkr,
+ [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
+ [GCC_USB30_MOCK_UTMI_CLK_SRC] = &gcc_usb30_mock_utmi_clk_src.clkr,
+ [GCC_USB30_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb30_mock_utmi_postdiv_clk_src.clkr,
+ [GCC_USB30_MSTR_AXI_CLK] = &gcc_usb30_mstr_axi_clk.clkr,
+ [GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr,
+ [GCC_USB30_SLV_AHB_CLK] = &gcc_usb30_slv_ahb_clk.clkr,
+ [GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr,
+ [GCC_USB3_PHY_AUX_CLK_SRC] = &gcc_usb3_phy_aux_clk_src.clkr,
+ [GCC_USB3_PHY_PIPE_CLK] = &gcc_usb3_phy_pipe_clk.clkr,
+ [GCC_USB3_PHY_PIPE_CLK_SRC] = &gcc_usb3_phy_pipe_clk_src.clkr,
+ [GCC_USB3_PRIM_CLKREF_EN] = &gcc_usb3_prim_clkref_en.clkr,
+ [GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr,
+ [GPLL0] = &gpll0.clkr,
+ [GPLL0_OUT_EVEN] = &gpll0_out_even.clkr,
+ [GPLL4] = &gpll4.clkr,
+ [GPLL5] = &gpll5.clkr,
+ [GPLL6] = &gpll6.clkr,
+ [GPLL8] = &gpll8.clkr,
+};
+
+static struct gdsc *gcc_sdx75_gdscs[] = {
+ [GCC_EMAC0_GDSC] = &gcc_emac0_gdsc,
+ [GCC_EMAC1_GDSC] = &gcc_emac1_gdsc,
+ [GCC_PCIE_1_GDSC] = &gcc_pcie_1_gdsc,
+ [GCC_PCIE_1_PHY_GDSC] = &gcc_pcie_1_phy_gdsc,
+ [GCC_PCIE_2_GDSC] = &gcc_pcie_2_gdsc,
+ [GCC_PCIE_2_PHY_GDSC] = &gcc_pcie_2_phy_gdsc,
+ [GCC_PCIE_GDSC] = &gcc_pcie_gdsc,
+ [GCC_PCIE_PHY_GDSC] = &gcc_pcie_phy_gdsc,
+ [GCC_USB30_GDSC] = &gcc_usb30_gdsc,
+ [GCC_USB3_PHY_GDSC] = &gcc_usb3_phy_gdsc,
+};
+
+static const struct qcom_reset_map gcc_sdx75_resets[] = {
+ [GCC_EMAC0_BCR] = { 0x71000 },
+ [GCC_EMAC0_RGMII_CLK_ARES] = { 0x71050, 2 },
+ [GCC_EMAC1_BCR] = { 0x72000 },
+ [GCC_EMMC_BCR] = { 0x6b000 },
+ [GCC_PCIE_1_BCR] = { 0x67000 },
+ [GCC_PCIE_1_LINK_DOWN_BCR] = { 0x9e700 },
+ [GCC_PCIE_1_NOCSR_COM_PHY_BCR] = { 0x56120 },
+ [GCC_PCIE_1_PHY_BCR] = { 0x56000 },
+ [GCC_PCIE_2_BCR] = { 0x68000 },
+ [GCC_PCIE_2_LINK_DOWN_BCR] = { 0x9f700 },
+ [GCC_PCIE_2_NOCSR_COM_PHY_BCR] = { 0x6e130 },
+ [GCC_PCIE_2_PHY_BCR] = { 0x6e000 },
+ [GCC_PCIE_BCR] = { 0x53000 },
+ [GCC_PCIE_LINK_DOWN_BCR] = { 0x87000 },
+ [GCC_PCIE_NOCSR_COM_PHY_BCR] = { 0x88008 },
+ [GCC_PCIE_PHY_BCR] = { 0x54000 },
+ [GCC_PCIE_PHY_CFG_AHB_BCR] = { 0x88000 },
+ [GCC_PCIE_PHY_COM_BCR] = { 0x88004 },
+ [GCC_PCIE_PHY_NOCSR_COM_PHY_BCR] = { 0x8800c },
+ [GCC_QUSB2PHY_BCR] = { 0x2a000 },
+ [GCC_TCSR_PCIE_BCR] = { 0x84000 },
+ [GCC_USB30_BCR] = { 0x27000 },
+ [GCC_USB3_PHY_BCR] = { 0x28000 },
+ [GCC_USB3PHY_PHY_BCR] = { 0x28004 },
+ [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x29000 },
+};
+
+static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = {
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s6_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s7_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s8_clk_src),
+};
+
+static const struct regmap_config gcc_sdx75_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1f41f0,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_sdx75_desc = {
+ .config = &gcc_sdx75_regmap_config,
+ .clks = gcc_sdx75_clocks,
+ .num_clks = ARRAY_SIZE(gcc_sdx75_clocks),
+ .resets = gcc_sdx75_resets,
+ .num_resets = ARRAY_SIZE(gcc_sdx75_resets),
+ .gdscs = gcc_sdx75_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_sdx75_gdscs),
+};
+
+static const struct of_device_id gcc_sdx75_match_table[] = {
+ { .compatible = "qcom,sdx75-gcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_sdx75_match_table);
+
+static int gcc_sdx75_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ regmap = qcom_cc_map(pdev, &gcc_sdx75_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks,
+ ARRAY_SIZE(gcc_dfs_clocks));
+ if (ret)
+ return ret;
+
+ /*
+ * Keep clocks always enabled:
+ * gcc_ahb_pcie_link_clk
+ * gcc_xo_pcie_link_clk
+ */
+ regmap_update_bits(regmap, 0x3e004, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x3e008, BIT(0), BIT(0));
+
+ return qcom_cc_really_probe(pdev, &gcc_sdx75_desc, regmap);
+}
+
+static struct platform_driver gcc_sdx75_driver = {
+ .probe = gcc_sdx75_probe,
+ .driver = {
+ .name = "gcc-sdx75",
+ .of_match_table = gcc_sdx75_match_table,
+ },
+};
+
+static int __init gcc_sdx75_init(void)
+{
+ return platform_driver_register(&gcc_sdx75_driver);
+}
+subsys_initcall(gcc_sdx75_init);
+
+static void __exit gcc_sdx75_exit(void)
+{
+ platform_driver_unregister(&gcc_sdx75_driver);
+}
+module_exit(gcc_sdx75_exit);
+
+MODULE_DESCRIPTION("QTI GCC SDX75 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/gcc-sm6115.c b/drivers/clk/qcom/gcc-sm6115.c
index 5f09aefa7fb9..033e308ff865 100644
--- a/drivers/clk/qcom/gcc-sm6115.c
+++ b/drivers/clk/qcom/gcc-sm6115.c
@@ -119,6 +119,8 @@ static const struct alpha_pll_config gpll10_config = {
.vco_mask = GENMASK(21, 20),
.main_output_mask = BIT(0),
.config_ctl_val = 0x4001055b,
+ .test_ctl_hi1_val = 0x1,
+ .test_ctl_hi_mask = 0x1,
};
static struct clk_alpha_pll gpll10 = {
@@ -170,6 +172,8 @@ static const struct alpha_pll_config gpll11_config = {
.vco_val = 0x2 << 20,
.vco_mask = GENMASK(21, 20),
.config_ctl_val = 0x4001055b,
+ .test_ctl_hi1_val = 0x1,
+ .test_ctl_hi_mask = 0x1,
};
static struct clk_alpha_pll gpll11 = {
@@ -362,6 +366,8 @@ static const struct alpha_pll_config gpll8_config = {
.post_div_val = 0x1 << 8,
.post_div_mask = GENMASK(11, 8),
.config_ctl_val = 0x4001055b,
+ .test_ctl_hi1_val = 0x1,
+ .test_ctl_hi_mask = 0x1,
};
static struct clk_alpha_pll gpll8 = {
@@ -413,6 +419,8 @@ static const struct alpha_pll_config gpll9_config = {
.post_div_mask = GENMASK(9, 8),
.main_output_mask = BIT(0),
.config_ctl_val = 0x00004289,
+ .test_ctl_mask = GENMASK(31, 0),
+ .test_ctl_val = 0x08000000,
};
static struct clk_alpha_pll gpll9 = {
diff --git a/drivers/clk/qcom/gcc-sm8450.c b/drivers/clk/qcom/gcc-sm8450.c
index 84764cc3db4f..75635d40a12d 100644
--- a/drivers/clk/qcom/gcc-sm8450.c
+++ b/drivers/clk/qcom/gcc-sm8450.c
@@ -334,6 +334,7 @@ static struct clk_rcg2 gcc_gp1_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_gp1_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_gp1_clk_src",
.parent_data = gcc_parent_data_1,
@@ -349,6 +350,7 @@ static struct clk_rcg2 gcc_gp2_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_gp1_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_gp2_clk_src",
.parent_data = gcc_parent_data_1,
@@ -364,6 +366,7 @@ static struct clk_rcg2 gcc_gp3_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_gp1_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_gp3_clk_src",
.parent_data = gcc_parent_data_1,
@@ -384,6 +387,7 @@ static struct clk_rcg2 gcc_pcie_0_aux_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_2,
.freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_0_aux_clk_src",
.parent_data = gcc_parent_data_2,
@@ -405,6 +409,7 @@ static struct clk_rcg2 gcc_pcie_0_phy_rchng_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_0_phy_rchng_clk_src",
.parent_data = gcc_parent_data_0,
@@ -420,6 +425,7 @@ static struct clk_rcg2 gcc_pcie_1_aux_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_2,
.freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_1_aux_clk_src",
.parent_data = gcc_parent_data_2,
@@ -435,6 +441,7 @@ static struct clk_rcg2 gcc_pcie_1_phy_rchng_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_pcie_1_phy_rchng_clk_src",
.parent_data = gcc_parent_data_0,
@@ -455,6 +462,7 @@ static struct clk_rcg2 gcc_pdm2_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_pdm2_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_pdm2_clk_src",
.parent_data = gcc_parent_data_0,
@@ -493,6 +501,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init,
};
@@ -510,6 +519,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init,
};
@@ -527,6 +537,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init,
};
@@ -544,6 +555,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init,
};
@@ -561,6 +573,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init,
};
@@ -590,6 +603,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s5_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init,
};
@@ -607,6 +621,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s6_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap0_s6_clk_src_init,
};
@@ -624,6 +639,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s7_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap0_s7_clk_src_init,
};
@@ -660,6 +676,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap1_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init,
};
@@ -677,6 +694,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap1_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init,
};
@@ -694,6 +712,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init,
};
@@ -711,6 +730,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init,
};
@@ -728,6 +748,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init,
};
@@ -745,6 +766,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init,
};
@@ -762,6 +784,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s6_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap1_s6_clk_src_init,
};
@@ -779,6 +802,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s0_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap1_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap2_s0_clk_src_init,
};
@@ -796,6 +820,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s1_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap1_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap2_s1_clk_src_init,
};
@@ -813,6 +838,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s2_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap2_s2_clk_src_init,
};
@@ -830,6 +856,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s3_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap2_s3_clk_src_init,
};
@@ -847,6 +874,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s4_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap2_s4_clk_src_init,
};
@@ -864,6 +892,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s5_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap2_s5_clk_src_init,
};
@@ -881,6 +910,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s6_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &gcc_qupv3_wrap2_s6_clk_src_init,
};
@@ -899,6 +929,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_7,
.freq_tbl = ftbl_gcc_sdcc2_apps_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc2_apps_clk_src",
.parent_data = gcc_parent_data_7,
@@ -921,6 +952,7 @@ static struct clk_rcg2 gcc_sdcc4_apps_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_sdcc4_apps_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc4_apps_clk_src",
.parent_data = gcc_parent_data_0,
@@ -944,6 +976,7 @@ static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_phy_axi_clk_src",
.parent_data = gcc_parent_data_0,
@@ -966,6 +999,7 @@ static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_phy_ice_core_clk_src",
.parent_data = gcc_parent_data_0,
@@ -987,6 +1021,7 @@ static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_3,
.freq_tbl = ftbl_gcc_ufs_phy_phy_aux_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_phy_phy_aux_clk_src",
.parent_data = gcc_parent_data_3,
@@ -1002,6 +1037,7 @@ static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_phy_unipro_core_clk_src",
.parent_data = gcc_parent_data_0,
@@ -1025,6 +1061,7 @@ static struct clk_rcg2 gcc_usb30_prim_master_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_usb30_prim_master_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_usb30_prim_master_clk_src",
.parent_data = gcc_parent_data_0,
@@ -1040,6 +1077,7 @@ static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_usb30_prim_mock_utmi_clk_src",
.parent_data = gcc_parent_data_0,
@@ -1055,6 +1093,7 @@ static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = {
.hid_width = 5,
.parent_map = gcc_parent_map_2,
.freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .hw_clk_ctrl = true,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_usb3_prim_phy_aux_clk_src",
.parent_data = gcc_parent_data_2,
diff --git a/drivers/clk/qcom/gpucc-sc8280xp.c b/drivers/clk/qcom/gpucc-sc8280xp.c
index ea1e9505c335..8e147ee294ee 100644
--- a/drivers/clk/qcom/gpucc-sc8280xp.c
+++ b/drivers/clk/qcom/gpucc-sc8280xp.c
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,gpucc-sc8280xp.h>
@@ -424,10 +425,21 @@ static struct qcom_cc_desc gpu_cc_sc8280xp_desc = {
static int gpu_cc_sc8280xp_probe(struct platform_device *pdev)
{
struct regmap *regmap;
+ int ret;
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
regmap = qcom_cc_map(pdev, &gpu_cc_sc8280xp_desc);
- if (IS_ERR(regmap))
+ if (IS_ERR(regmap)) {
+ pm_runtime_put(&pdev->dev);
return PTR_ERR(regmap);
+ }
clk_lucid_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
clk_lucid_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
@@ -439,7 +451,10 @@ static int gpu_cc_sc8280xp_probe(struct platform_device *pdev)
regmap_update_bits(regmap, 0x1170, BIT(0), BIT(0));
regmap_update_bits(regmap, 0x109c, BIT(0), BIT(0));
- return qcom_cc_really_probe(pdev, &gpu_cc_sc8280xp_desc, regmap);
+ ret = qcom_cc_really_probe(pdev, &gpu_cc_sc8280xp_desc, regmap);
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
}
static const struct of_device_id gpu_cc_sc8280xp_match_table[] = {
diff --git a/drivers/clk/qcom/gpucc-sm6375.c b/drivers/clk/qcom/gpucc-sm6375.c
index d3620344a009..2d863dc3d83b 100644
--- a/drivers/clk/qcom/gpucc-sm6375.c
+++ b/drivers/clk/qcom/gpucc-sm6375.c
@@ -7,6 +7,7 @@
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,sm6375-gpucc.h>
@@ -434,15 +435,29 @@ MODULE_DEVICE_TABLE(of, gpucc_sm6375_match_table);
static int gpucc_sm6375_probe(struct platform_device *pdev)
{
struct regmap *regmap;
+ int ret;
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
regmap = qcom_cc_map(pdev, &gpucc_sm6375_desc);
- if (IS_ERR(regmap))
+ if (IS_ERR(regmap)) {
+ pm_runtime_put(&pdev->dev);
return PTR_ERR(regmap);
+ }
clk_lucid_pll_configure(&gpucc_pll0, regmap, &gpucc_pll0_config);
clk_lucid_pll_configure(&gpucc_pll1, regmap, &gpucc_pll1_config);
- return qcom_cc_really_probe(pdev, &gpucc_sm6375_desc, regmap);
+ ret = qcom_cc_really_probe(pdev, &gpucc_sm6375_desc, regmap);
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
}
static struct platform_driver gpucc_sm6375_driver = {
diff --git a/drivers/clk/qcom/gpucc-sm8450.c b/drivers/clk/qcom/gpucc-sm8450.c
new file mode 100644
index 000000000000..16c0381b3087
--- /dev/null
+++ b/drivers/clk/qcom/gpucc-sm8450.c
@@ -0,0 +1,766 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sm8450-gpucc.h>
+#include <dt-bindings/reset/qcom,sm8450-gpucc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "clk-regmap-phy-mux.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_BI_TCXO,
+ DT_GPLL0_OUT_MAIN,
+ DT_GPLL0_OUT_MAIN_DIV,
+};
+
+enum {
+ P_BI_TCXO,
+ P_GPLL0_OUT_MAIN,
+ P_GPLL0_OUT_MAIN_DIV,
+ P_GPU_CC_PLL0_OUT_MAIN,
+ P_GPU_CC_PLL1_OUT_MAIN,
+};
+
+static struct pll_vco lucid_evo_vco[] = {
+ { 249600000, 2000000000, 0 },
+};
+
+static struct alpha_pll_config gpu_cc_pll0_config = {
+ .l = 0x1d,
+ .alpha = 0xb000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000805,
+};
+
+static struct clk_alpha_pll gpu_cc_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_pll0",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static struct alpha_pll_config gpu_cc_pll1_config = {
+ .l = 0x34,
+ .alpha = 0x1555,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000805,
+};
+
+static struct clk_alpha_pll gpu_cc_pll1 = {
+ .offset = 0x1000,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_pll1",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct parent_map gpu_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_GPLL0_OUT_MAIN },
+ { .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct parent_map gpu_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPU_CC_PLL0_OUT_MAIN, 1 },
+ { P_GPU_CC_PLL1_OUT_MAIN, 3 },
+ { P_GPLL0_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpu_cc_pll0.clkr.hw },
+ { .hw = &gpu_cc_pll1.clkr.hw },
+ { .index = DT_GPLL0_OUT_MAIN },
+ { .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct parent_map gpu_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPU_CC_PLL1_OUT_MAIN, 3 },
+ { P_GPLL0_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpu_cc_pll1.clkr.hw },
+ { .index = DT_GPLL0_OUT_MAIN },
+ { .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct parent_map gpu_cc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = {
+ F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_ff_clk_src = {
+ .cmd_rcgr = 0x9474,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_0,
+ .freq_tbl = ftbl_gpu_cc_ff_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_ff_clk_src",
+ .parent_data = gpu_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
+ F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_gmu_clk_src = {
+ .cmd_rcgr = 0x9318,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_1,
+ .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_gmu_clk_src",
+ .parent_data = gpu_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = {
+ F(150000000, P_GPLL0_OUT_MAIN_DIV, 2, 0, 0),
+ F(240000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0),
+ F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_hub_clk_src = {
+ .cmd_rcgr = 0x93ec,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_2,
+ .freq_tbl = ftbl_gpu_cc_hub_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_hub_clk_src",
+ .parent_data = gpu_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_xo_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_xo_clk_src = {
+ .cmd_rcgr = 0x9010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_3,
+ .freq_tbl = ftbl_gpu_cc_xo_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_xo_clk_src",
+ .parent_data = gpu_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div gpu_cc_demet_div_clk_src = {
+ .reg = 0x9054,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gpu_cc_demet_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpu_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gpu_cc_hub_ahb_div_clk_src = {
+ .reg = 0x9430,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gpu_cc_hub_ahb_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gpu_cc_hub_cx_int_div_clk_src = {
+ .reg = 0x942c,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gpu_cc_hub_cx_int_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gpu_cc_xo_div_clk_src = {
+ .reg = 0x9050,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gpu_cc_xo_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpu_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch gpu_cc_ahb_clk = {
+ .halt_reg = 0x911c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x911c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_ahb_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_crc_ahb_clk = {
+ .halt_reg = 0x9120,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9120,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_crc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_ahb_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_apb_clk = {
+ .halt_reg = 0x912c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x912c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_cx_apb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_ff_clk = {
+ .halt_reg = 0x914c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x914c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_cx_ff_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_ff_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_gmu_clk = {
+ .halt_reg = 0x913c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x913c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_cx_gmu_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_gmu_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
+ .halt_reg = 0x9130,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9130,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_cx_snoc_dvm_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cxo_aon_clk = {
+ .halt_reg = 0x9004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_cxo_aon_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cxo_clk = {
+ .halt_reg = 0x9144,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9144,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_cxo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_demet_clk = {
+ .halt_reg = 0x900c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x900c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_demet_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_demet_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_freq_measure_clk = {
+ .halt_reg = 0x9008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_freq_measure_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_xo_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_gx_ff_clk = {
+ .halt_reg = 0x90c0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x90c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_gx_ff_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_ff_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_gx_gfx3d_clk = {
+ .halt_reg = 0x90a8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x90a8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_gx_gfx3d_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_gx_gfx3d_rdvm_clk = {
+ .halt_reg = 0x90c8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x90c8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_gx_gfx3d_rdvm_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_gx_gmu_clk = {
+ .halt_reg = 0x90bc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x90bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_gx_gmu_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_gmu_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_gx_vsense_clk = {
+ .halt_reg = 0x90b0,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x90b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_gx_vsense_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
+ .halt_reg = 0x7000,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hub_aon_clk = {
+ .halt_reg = 0x93e8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x93e8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_hub_aon_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hub_cx_int_clk = {
+ .halt_reg = 0x9148,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9148,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_hub_cx_int_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_cx_int_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_memnoc_gfx_clk = {
+ .halt_reg = 0x9150,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9150,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_memnoc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_mnd1x_0_gfx3d_clk = {
+ .halt_reg = 0x9288,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9288,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_mnd1x_0_gfx3d_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_mnd1x_1_gfx3d_clk = {
+ .halt_reg = 0x928c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x928c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_mnd1x_1_gfx3d_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_sleep_clk = {
+ .halt_reg = 0x9134,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9134,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpu_cc_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc gpu_cx_gdsc = {
+ .gdscr = 0x9108,
+ .gds_hw_ctrl = 0x953c,
+ .clk_dis_wait_val = 8,
+ .pd = {
+ .name = "gpu_cx_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gpu_gx_gdsc = {
+ .gdscr = 0x905c,
+ .clamp_io_ctrl = 0x9504,
+ .resets = (unsigned int []){ GPUCC_GPU_CC_GX_BCR,
+ GPUCC_GPU_CC_ACD_BCR,
+ GPUCC_GPU_CC_GX_ACD_IROOT_BCR },
+ .reset_count = 3,
+ .pd = {
+ .name = "gpu_gx_gdsc",
+ .power_on = gdsc_gx_do_nothing_enable,
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = CLAMP_IO | AON_RESET | SW_RESET | POLL_CFG_GDSCR,
+};
+
+static struct clk_regmap *gpu_cc_sm8450_clocks[] = {
+ [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
+ [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
+ [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr,
+ [GPU_CC_CX_FF_CLK] = &gpu_cc_cx_ff_clk.clkr,
+ [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
+ [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
+ [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
+ [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
+ [GPU_CC_DEMET_CLK] = &gpu_cc_demet_clk.clkr,
+ [GPU_CC_DEMET_DIV_CLK_SRC] = &gpu_cc_demet_div_clk_src.clkr,
+ [GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr,
+ [GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr,
+ [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
+ [GPU_CC_GX_FF_CLK] = &gpu_cc_gx_ff_clk.clkr,
+ [GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr,
+ [GPU_CC_GX_GFX3D_RDVM_CLK] = &gpu_cc_gx_gfx3d_rdvm_clk.clkr,
+ [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
+ [GPU_CC_GX_VSENSE_CLK] = &gpu_cc_gx_vsense_clk.clkr,
+ [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
+ [GPU_CC_HUB_AHB_DIV_CLK_SRC] = &gpu_cc_hub_ahb_div_clk_src.clkr,
+ [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr,
+ [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr,
+ [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr,
+ [GPU_CC_HUB_CX_INT_DIV_CLK_SRC] = &gpu_cc_hub_cx_int_div_clk_src.clkr,
+ [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr,
+ [GPU_CC_MND1X_0_GFX3D_CLK] = &gpu_cc_mnd1x_0_gfx3d_clk.clkr,
+ [GPU_CC_MND1X_1_GFX3D_CLK] = &gpu_cc_mnd1x_1_gfx3d_clk.clkr,
+ [GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
+ [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
+ [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr,
+ [GPU_CC_XO_CLK_SRC] = &gpu_cc_xo_clk_src.clkr,
+ [GPU_CC_XO_DIV_CLK_SRC] = &gpu_cc_xo_div_clk_src.clkr,
+};
+
+static const struct qcom_reset_map gpu_cc_sm8450_resets[] = {
+ [GPUCC_GPU_CC_XO_BCR] = { 0x9000 },
+ [GPUCC_GPU_CC_GX_BCR] = { 0x9058 },
+ [GPUCC_GPU_CC_CX_BCR] = { 0x9104 },
+ [GPUCC_GPU_CC_GFX3D_AON_BCR] = { 0x9198 },
+ [GPUCC_GPU_CC_ACD_BCR] = { 0x9358 },
+ [GPUCC_GPU_CC_FAST_HUB_BCR] = { 0x93e4 },
+ [GPUCC_GPU_CC_FF_BCR] = { 0x9470 },
+ [GPUCC_GPU_CC_GMU_BCR] = { 0x9314 },
+ [GPUCC_GPU_CC_GX_ACD_IROOT_BCR] = { 0x958c },
+};
+
+static struct gdsc *gpu_cc_sm8450_gdscs[] = {
+ [GPU_CX_GDSC] = &gpu_cx_gdsc,
+ [GPU_GX_GDSC] = &gpu_gx_gdsc,
+};
+
+static const struct regmap_config gpu_cc_sm8450_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xa000,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gpu_cc_sm8450_desc = {
+ .config = &gpu_cc_sm8450_regmap_config,
+ .clks = gpu_cc_sm8450_clocks,
+ .num_clks = ARRAY_SIZE(gpu_cc_sm8450_clocks),
+ .resets = gpu_cc_sm8450_resets,
+ .num_resets = ARRAY_SIZE(gpu_cc_sm8450_resets),
+ .gdscs = gpu_cc_sm8450_gdscs,
+ .num_gdscs = ARRAY_SIZE(gpu_cc_sm8450_gdscs),
+};
+
+static const struct of_device_id gpu_cc_sm8450_match_table[] = {
+ { .compatible = "qcom,sm8450-gpucc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gpu_cc_sm8450_match_table);
+
+static int gpu_cc_sm8450_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &gpu_cc_sm8450_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ clk_lucid_evo_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
+ clk_lucid_evo_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
+
+ return qcom_cc_really_probe(pdev, &gpu_cc_sm8450_desc, regmap);
+}
+
+static struct platform_driver gpu_cc_sm8450_driver = {
+ .probe = gpu_cc_sm8450_probe,
+ .driver = {
+ .name = "sm8450-gpucc",
+ .of_match_table = gpu_cc_sm8450_match_table,
+ },
+};
+module_platform_driver(gpu_cc_sm8450_driver);
+
+MODULE_DESCRIPTION("QTI GPU_CC SM8450 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/gpucc-sm8550.c b/drivers/clk/qcom/gpucc-sm8550.c
new file mode 100644
index 000000000000..8a2e3522af51
--- /dev/null
+++ b/drivers/clk/qcom/gpucc-sm8550.c
@@ -0,0 +1,611 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sm8550-gpucc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_BI_TCXO,
+ DT_GPLL0_OUT_MAIN,
+ DT_GPLL0_OUT_MAIN_DIV,
+};
+
+enum {
+ P_BI_TCXO,
+ P_GPLL0_OUT_MAIN,
+ P_GPLL0_OUT_MAIN_DIV,
+ P_GPU_CC_PLL0_OUT_MAIN,
+ P_GPU_CC_PLL1_OUT_MAIN,
+};
+
+static const struct pll_vco lucid_ole_vco[] = {
+ { 249600000, 2300000000, 0 },
+};
+
+static const struct alpha_pll_config gpu_cc_pll0_config = {
+ /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */
+ .l = 0x4444000d,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll gpu_cc_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct alpha_pll_config gpu_cc_pll1_config = {
+ /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */
+ .l = 0x44440016,
+ .alpha = 0xeaaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll gpu_cc_pll1 = {
+ .offset = 0x1000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_pll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct parent_map gpu_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_GPLL0_OUT_MAIN },
+ { .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct parent_map gpu_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPU_CC_PLL0_OUT_MAIN, 1 },
+ { P_GPU_CC_PLL1_OUT_MAIN, 3 },
+ { P_GPLL0_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpu_cc_pll0.clkr.hw },
+ { .hw = &gpu_cc_pll1.clkr.hw },
+ { .index = DT_GPLL0_OUT_MAIN },
+ { .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct parent_map gpu_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPU_CC_PLL1_OUT_MAIN, 3 },
+ { P_GPLL0_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpu_cc_pll1.clkr.hw },
+ { .index = DT_GPLL0_OUT_MAIN },
+ { .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct parent_map gpu_cc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = {
+ F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_ff_clk_src = {
+ .cmd_rcgr = 0x9474,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_0,
+ .freq_tbl = ftbl_gpu_cc_ff_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_ff_clk_src",
+ .parent_data = gpu_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(220000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0),
+ F(550000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_gmu_clk_src = {
+ .cmd_rcgr = 0x9318,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_1,
+ .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_gmu_clk_src",
+ .parent_data = gpu_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = {
+ F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
+ F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
+ F(400000000, P_GPLL0_OUT_MAIN, 1.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_hub_clk_src = {
+ .cmd_rcgr = 0x93ec,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_2,
+ .freq_tbl = ftbl_gpu_cc_hub_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_hub_clk_src",
+ .parent_data = gpu_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_xo_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_xo_clk_src = {
+ .cmd_rcgr = 0x9010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_3,
+ .freq_tbl = ftbl_gpu_cc_xo_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_xo_clk_src",
+ .parent_data = gpu_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div gpu_cc_demet_div_clk_src = {
+ .reg = 0x9054,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_demet_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gpu_cc_xo_div_clk_src = {
+ .reg = 0x9050,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_xo_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch gpu_cc_ahb_clk = {
+ .halt_reg = 0x911c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x911c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_crc_ahb_clk = {
+ .halt_reg = 0x9120,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9120,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_crc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_ff_clk = {
+ .halt_reg = 0x914c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x914c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_cx_ff_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_ff_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_gmu_clk = {
+ .halt_reg = 0x913c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x913c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_cx_gmu_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_gmu_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cxo_clk = {
+ .halt_reg = 0x9144,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9144,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_cxo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_freq_measure_clk = {
+ .halt_reg = 0x9008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_freq_measure_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_xo_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
+ .halt_reg = 0x7000,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hub_aon_clk = {
+ .halt_reg = 0x93e8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x93e8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_hub_aon_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hub_cx_int_clk = {
+ .halt_reg = 0x9148,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9148,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_hub_cx_int_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_memnoc_gfx_clk = {
+ .halt_reg = 0x9150,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9150,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_memnoc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_mnd1x_0_gfx3d_clk = {
+ .halt_reg = 0x9288,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9288,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_mnd1x_0_gfx3d_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_mnd1x_1_gfx3d_clk = {
+ .halt_reg = 0x928c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x928c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_mnd1x_1_gfx3d_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_sleep_clk = {
+ .halt_reg = 0x9134,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9134,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc gpu_cc_cx_gdsc = {
+ .gdscr = 0x9108,
+ .gds_hw_ctrl = 0x953c,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gpu_cc_cx_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE | VOTABLE,
+};
+
+static struct gdsc gpu_cc_gx_gdsc = {
+ .gdscr = 0x905c,
+ .clamp_io_ctrl = 0x9504,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gpu_cc_gx_gdsc",
+ .power_on = gdsc_gx_do_nothing_enable,
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = CLAMP_IO | POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct clk_regmap *gpu_cc_sm8550_clocks[] = {
+ [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
+ [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
+ [GPU_CC_CX_FF_CLK] = &gpu_cc_cx_ff_clk.clkr,
+ [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
+ [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
+ [GPU_CC_DEMET_DIV_CLK_SRC] = &gpu_cc_demet_div_clk_src.clkr,
+ [GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr,
+ [GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr,
+ [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
+ [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
+ [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr,
+ [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr,
+ [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr,
+ [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr,
+ [GPU_CC_MND1X_0_GFX3D_CLK] = &gpu_cc_mnd1x_0_gfx3d_clk.clkr,
+ [GPU_CC_MND1X_1_GFX3D_CLK] = &gpu_cc_mnd1x_1_gfx3d_clk.clkr,
+ [GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
+ [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
+ [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr,
+ [GPU_CC_XO_CLK_SRC] = &gpu_cc_xo_clk_src.clkr,
+ [GPU_CC_XO_DIV_CLK_SRC] = &gpu_cc_xo_div_clk_src.clkr,
+};
+
+static struct gdsc *gpu_cc_sm8550_gdscs[] = {
+ [GPU_CC_CX_GDSC] = &gpu_cc_cx_gdsc,
+ [GPU_CC_GX_GDSC] = &gpu_cc_gx_gdsc,
+};
+
+static const struct qcom_reset_map gpu_cc_sm8550_resets[] = {
+ [GPUCC_GPU_CC_ACD_BCR] = { 0x9358 },
+ [GPUCC_GPU_CC_CX_BCR] = { 0x9104 },
+ [GPUCC_GPU_CC_FAST_HUB_BCR] = { 0x93e4 },
+ [GPUCC_GPU_CC_FF_BCR] = { 0x9470 },
+ [GPUCC_GPU_CC_GFX3D_AON_BCR] = { 0x9198 },
+ [GPUCC_GPU_CC_GMU_BCR] = { 0x9314 },
+ [GPUCC_GPU_CC_GX_BCR] = { 0x9058 },
+ [GPUCC_GPU_CC_XO_BCR] = { 0x9000 },
+};
+
+static const struct regmap_config gpu_cc_sm8550_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x9988,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gpu_cc_sm8550_desc = {
+ .config = &gpu_cc_sm8550_regmap_config,
+ .clks = gpu_cc_sm8550_clocks,
+ .num_clks = ARRAY_SIZE(gpu_cc_sm8550_clocks),
+ .resets = gpu_cc_sm8550_resets,
+ .num_resets = ARRAY_SIZE(gpu_cc_sm8550_resets),
+ .gdscs = gpu_cc_sm8550_gdscs,
+ .num_gdscs = ARRAY_SIZE(gpu_cc_sm8550_gdscs),
+};
+
+static const struct of_device_id gpu_cc_sm8550_match_table[] = {
+ { .compatible = "qcom,sm8550-gpucc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gpu_cc_sm8550_match_table);
+
+static int gpu_cc_sm8550_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &gpu_cc_sm8550_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ clk_lucid_evo_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
+ clk_lucid_evo_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
+
+ /*
+ * Keep clocks always enabled:
+ * gpu_cc_cxo_aon_clk
+ * gpu_cc_demet_clk
+ */
+ regmap_update_bits(regmap, 0x9004, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x900c, BIT(0), BIT(0));
+
+ return qcom_cc_really_probe(pdev, &gpu_cc_sm8550_desc, regmap);
+}
+
+static struct platform_driver gpu_cc_sm8550_driver = {
+ .probe = gpu_cc_sm8550_probe,
+ .driver = {
+ .name = "gpu_cc-sm8550",
+ .of_match_table = gpu_cc_sm8550_match_table,
+ },
+};
+
+static int __init gpu_cc_sm8550_init(void)
+{
+ return platform_driver_register(&gpu_cc_sm8550_driver);
+}
+subsys_initcall(gpu_cc_sm8550_init);
+
+static void __exit gpu_cc_sm8550_exit(void)
+{
+ platform_driver_unregister(&gpu_cc_sm8550_driver);
+}
+module_exit(gpu_cc_sm8550_exit);
+
+MODULE_DESCRIPTION("QTI GPUCC SM8550 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/lpasscc-sc8280xp.c b/drivers/clk/qcom/lpasscc-sc8280xp.c
new file mode 100644
index 000000000000..43b37ce397cf
--- /dev/null
+++ b/drivers/clk/qcom/lpasscc-sc8280xp.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sc8280xp-lpasscc.h>
+
+#include "common.h"
+#include "reset.h"
+
+static const struct qcom_reset_map lpass_audiocc_sc8280xp_resets[] = {
+ [LPASS_AUDIO_SWR_RX_CGCR] = { 0xa0, 1 },
+ [LPASS_AUDIO_SWR_WSA_CGCR] = { 0xb0, 1 },
+ [LPASS_AUDIO_SWR_WSA2_CGCR] = { 0xd8, 1 },
+};
+
+static struct regmap_config lpass_audiocc_sc8280xp_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .name = "lpass-audio-csr",
+ .max_register = 0x1000,
+};
+
+static const struct qcom_cc_desc lpass_audiocc_sc8280xp_reset_desc = {
+ .config = &lpass_audiocc_sc8280xp_regmap_config,
+ .resets = lpass_audiocc_sc8280xp_resets,
+ .num_resets = ARRAY_SIZE(lpass_audiocc_sc8280xp_resets),
+};
+
+static const struct qcom_reset_map lpasscc_sc8280xp_resets[] = {
+ [LPASS_AUDIO_SWR_TX_CGCR] = { 0xc010, 1 },
+};
+
+static struct regmap_config lpasscc_sc8280xp_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .name = "lpass-tcsr",
+ .max_register = 0x12000,
+};
+
+static const struct qcom_cc_desc lpasscc_sc8280xp_reset_desc = {
+ .config = &lpasscc_sc8280xp_regmap_config,
+ .resets = lpasscc_sc8280xp_resets,
+ .num_resets = ARRAY_SIZE(lpasscc_sc8280xp_resets),
+};
+
+static const struct of_device_id lpasscc_sc8280xp_match_table[] = {
+ {
+ .compatible = "qcom,sc8280xp-lpassaudiocc",
+ .data = &lpass_audiocc_sc8280xp_reset_desc,
+ }, {
+ .compatible = "qcom,sc8280xp-lpasscc",
+ .data = &lpasscc_sc8280xp_reset_desc,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lpasscc_sc8280xp_match_table);
+
+static int lpasscc_sc8280xp_probe(struct platform_device *pdev)
+{
+ const struct qcom_cc_desc *desc = of_device_get_match_data(&pdev->dev);
+
+ return qcom_cc_probe_by_index(pdev, 0, desc);
+}
+
+static struct platform_driver lpasscc_sc8280xp_driver = {
+ .probe = lpasscc_sc8280xp_probe,
+ .driver = {
+ .name = "lpasscc-sc8280xp",
+ .of_match_table = lpasscc_sc8280xp_match_table,
+ },
+};
+
+module_platform_driver(lpasscc_sc8280xp_driver);
+
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
+MODULE_DESCRIPTION("QTI LPASSCC SC8280XP Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c
index 4273fce9a4a4..82f6bad144a9 100644
--- a/drivers/clk/qcom/mmcc-msm8974.c
+++ b/drivers/clk/qcom/mmcc-msm8974.c
@@ -485,7 +485,7 @@ static struct clk_rcg2 mdp_clk_src = {
.name = "mdp_clk_src",
.parent_data = mmcc_xo_mmpll0_dsi_hdmi_gpll0,
.num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_dsi_hdmi_gpll0),
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_shared_ops,
},
};
@@ -2204,23 +2204,6 @@ static struct clk_branch ocmemcx_ocmemnoc_clk = {
},
};
-static struct clk_branch oxili_ocmemgx_clk = {
- .halt_reg = 0x402c,
- .clkr = {
- .enable_reg = 0x402c,
- .enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data){
- .name = "oxili_ocmemgx_clk",
- .parent_data = (const struct clk_parent_data[]){
- { .fw_name = "gfx3d_clk_src", .name = "gfx3d_clk_src" },
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch ocmemnoc_clk = {
.halt_reg = 0x50b4,
.clkr = {
@@ -2401,7 +2384,7 @@ static struct gdsc mdss_gdsc = {
.pd = {
.name = "mdss",
},
- .pwrsts = PWRSTS_RET_ON,
+ .pwrsts = PWRSTS_OFF_ON,
};
static struct gdsc camss_jpeg_gdsc = {
@@ -2512,7 +2495,6 @@ static struct clk_regmap *mmcc_msm8226_clocks[] = {
[MMSS_MMSSNOC_AXI_CLK] = &mmss_mmssnoc_axi_clk.clkr,
[MMSS_S0_AXI_CLK] = &mmss_s0_axi_clk.clkr,
[OCMEMCX_AHB_CLK] = &ocmemcx_ahb_clk.clkr,
- [OXILI_OCMEMGX_CLK] = &oxili_ocmemgx_clk.clkr,
[OXILI_GFX3D_CLK] = &oxili_gfx3d_clk.clkr,
[OXILICX_AHB_CLK] = &oxilicx_ahb_clk.clkr,
[OXILICX_AXI_CLK] = &oxilicx_axi_clk.clkr,
@@ -2670,7 +2652,6 @@ static struct clk_regmap *mmcc_msm8974_clocks[] = {
[MMSS_S0_AXI_CLK] = &mmss_s0_axi_clk.clkr,
[OCMEMCX_AHB_CLK] = &ocmemcx_ahb_clk.clkr,
[OCMEMCX_OCMEMNOC_CLK] = &ocmemcx_ocmemnoc_clk.clkr,
- [OXILI_OCMEMGX_CLK] = &oxili_ocmemgx_clk.clkr,
[OCMEMNOC_CLK] = &ocmemnoc_clk.clkr,
[OXILI_GFX3D_CLK] = &oxili_gfx3d_clk.clkr,
[OXILICX_AHB_CLK] = &oxilicx_ahb_clk.clkr,
diff --git a/drivers/clk/qcom/videocc-sm8350.c b/drivers/clk/qcom/videocc-sm8350.c
new file mode 100644
index 000000000000..b148877fc73d
--- /dev/null
+++ b/drivers/clk/qcom/videocc-sm8350.c
@@ -0,0 +1,552 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sm8350-videocc.h>
+#include <dt-bindings/reset/qcom,sm8350-videocc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "common.h"
+#include "reset.h"
+#include "gdsc.h"
+
+enum {
+ DT_BI_TCXO,
+ DT_BI_TCXO_AO,
+ DT_SLEEP_CLK,
+};
+
+enum {
+ P_BI_TCXO,
+ P_BI_TCXO_AO,
+ P_SLEEP_CLK,
+ P_VIDEO_PLL0_OUT_MAIN,
+ P_VIDEO_PLL1_OUT_MAIN,
+};
+
+static const struct pll_vco lucid_5lpe_vco[] = {
+ { 249600000, 1750000000, 0 },
+};
+
+static const struct alpha_pll_config video_pll0_config = {
+ .l = 0x25,
+ .alpha = 0x8000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00002261,
+ .config_ctl_hi1_val = 0x2a9a699c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000000,
+ .test_ctl_hi1_val = 0x01800000,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000805,
+ .user_ctl_hi1_val = 0x00000000,
+};
+
+static struct clk_alpha_pll video_pll0 = {
+ .offset = 0x42c,
+ .vco_table = lucid_5lpe_vco,
+ .num_vco = ARRAY_SIZE(lucid_5lpe_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_pll0",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_5lpe_ops,
+ },
+ },
+};
+
+static const struct alpha_pll_config video_pll1_config = {
+ .l = 0x2b,
+ .alpha = 0xc000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00002261,
+ .config_ctl_hi1_val = 0x2a9a699c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000000,
+ .test_ctl_hi1_val = 0x01800000,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000805,
+ .user_ctl_hi1_val = 0x00000000,
+};
+
+static struct clk_alpha_pll video_pll1 = {
+ .offset = 0x7d0,
+ .vco_table = lucid_5lpe_vco,
+ .num_vco = ARRAY_SIZE(lucid_5lpe_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_pll1",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_5lpe_ops,
+ },
+ },
+};
+
+static const struct parent_map video_cc_parent_map_0[] = {
+ { P_BI_TCXO_AO, 0 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO_AO },
+};
+
+static const struct parent_map video_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_VIDEO_PLL0_OUT_MAIN, 1 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &video_pll0.clkr.hw },
+};
+
+static const struct parent_map video_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_VIDEO_PLL1_OUT_MAIN, 1 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &video_pll1.clkr.hw },
+};
+
+static const struct freq_tbl ftbl_video_cc_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_ahb_clk_src = {
+ .cmd_rcgr = 0xbd4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_0,
+ .freq_tbl = ftbl_video_cc_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_ahb_clk_src",
+ .parent_data = video_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = {
+ F(720000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1014000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1098000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1332000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_mvs0_clk_src = {
+ .cmd_rcgr = 0xb94,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_1,
+ .freq_tbl = ftbl_video_cc_mvs0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_clk_src",
+ .parent_data = video_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = {
+ F(840000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1098000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1332000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_mvs1_clk_src = {
+ .cmd_rcgr = 0xbb4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_2,
+ .freq_tbl = ftbl_video_cc_mvs1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_clk_src",
+ .parent_data = video_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_sleep_clk_src = {
+ .cmd_rcgr = 0xef0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .freq_tbl = ftbl_video_cc_sleep_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_sleep_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_SLEEP_CLK,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 video_cc_xo_clk_src = {
+ .cmd_rcgr = 0xecc,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_0,
+ .freq_tbl = ftbl_video_cc_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_xo_clk_src",
+ .parent_data = video_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs0_div_clk_src = {
+ .reg = 0xd54,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_mvs0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = {
+ .reg = 0xc54,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0c_div2_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_mvs0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs1_div_clk_src = {
+ .reg = 0xdd4,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_mvs1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = {
+ .reg = 0xcf4,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1c_div2_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_mvs1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch video_cc_mvs0_clk = {
+ .halt_reg = 0xd34,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0xd34,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0xd34,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_mvs0_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs0c_clk = {
+ .halt_reg = 0xc34,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xc34,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0c_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_mvs0c_div2_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs1_clk = {
+ .halt_reg = 0xdb4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0xdb4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0xdb4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_mvs1_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs1_div2_clk = {
+ .halt_reg = 0xdf4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0xdf4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0xdf4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_div2_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_mvs1c_div2_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs1c_clk = {
+ .halt_reg = 0xcd4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xcd4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1c_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_mvs1c_div2_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_sleep_clk = {
+ .halt_reg = 0xf10,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf10,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_sleep_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &video_cc_sleep_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc mvs0c_gdsc = {
+ .gdscr = 0xbf8,
+ .pd = {
+ .name = "mvs0c_gdsc",
+ },
+ .flags = RETAIN_FF_ENABLE,
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc mvs1c_gdsc = {
+ .gdscr = 0xc98,
+ .pd = {
+ .name = "mvs1c_gdsc",
+ },
+ .flags = RETAIN_FF_ENABLE,
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc mvs0_gdsc = {
+ .gdscr = 0xd18,
+ .pd = {
+ .name = "mvs0_gdsc",
+ },
+ .flags = HW_CTRL | RETAIN_FF_ENABLE,
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc mvs1_gdsc = {
+ .gdscr = 0xd98,
+ .pd = {
+ .name = "mvs1_gdsc",
+ },
+ .flags = HW_CTRL | RETAIN_FF_ENABLE,
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct clk_regmap *video_cc_sm8350_clocks[] = {
+ [VIDEO_CC_AHB_CLK_SRC] = &video_cc_ahb_clk_src.clkr,
+ [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr,
+ [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr,
+ [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr,
+ [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr,
+ [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr,
+ [VIDEO_CC_MVS1_CLK] = &video_cc_mvs1_clk.clkr,
+ [VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr,
+ [VIDEO_CC_MVS1_DIV2_CLK] = &video_cc_mvs1_div2_clk.clkr,
+ [VIDEO_CC_MVS1_DIV_CLK_SRC] = &video_cc_mvs1_div_clk_src.clkr,
+ [VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr,
+ [VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr,
+ [VIDEO_CC_SLEEP_CLK] = &video_cc_sleep_clk.clkr,
+ [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr,
+ [VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr,
+ [VIDEO_PLL0] = &video_pll0.clkr,
+ [VIDEO_PLL1] = &video_pll1.clkr,
+};
+
+static const struct qcom_reset_map video_cc_sm8350_resets[] = {
+ [VIDEO_CC_CVP_INTERFACE_BCR] = { 0xe54 },
+ [VIDEO_CC_CVP_MVS0_BCR] = { 0xd14 },
+ [VIDEO_CC_MVS0C_CLK_ARES] = { 0xc34, 2 },
+ [VIDEO_CC_CVP_MVS0C_BCR] = { 0xbf4 },
+ [VIDEO_CC_CVP_MVS1_BCR] = { 0xd94 },
+ [VIDEO_CC_MVS1C_CLK_ARES] = { 0xcd4, 2 },
+ [VIDEO_CC_CVP_MVS1C_BCR] = { 0xc94 },
+};
+
+static struct gdsc *video_cc_sm8350_gdscs[] = {
+ [MVS0C_GDSC] = &mvs0c_gdsc,
+ [MVS1C_GDSC] = &mvs1c_gdsc,
+ [MVS0_GDSC] = &mvs0_gdsc,
+ [MVS1_GDSC] = &mvs1_gdsc,
+};
+
+static const struct regmap_config video_cc_sm8350_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x10000,
+ .fast_io = true,
+};
+
+static struct qcom_cc_desc video_cc_sm8350_desc = {
+ .config = &video_cc_sm8350_regmap_config,
+ .clks = video_cc_sm8350_clocks,
+ .num_clks = ARRAY_SIZE(video_cc_sm8350_clocks),
+ .resets = video_cc_sm8350_resets,
+ .num_resets = ARRAY_SIZE(video_cc_sm8350_resets),
+ .gdscs = video_cc_sm8350_gdscs,
+ .num_gdscs = ARRAY_SIZE(video_cc_sm8350_gdscs),
+};
+
+static int video_cc_sm8350_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
+
+ regmap = qcom_cc_map(pdev, &video_cc_sm8350_desc);
+ if (IS_ERR(regmap)) {
+ pm_runtime_put(&pdev->dev);
+ return PTR_ERR(regmap);
+ }
+
+ clk_lucid_pll_configure(&video_pll0, regmap, &video_pll0_config);
+ clk_lucid_pll_configure(&video_pll1, regmap, &video_pll1_config);
+
+ /*
+ * Keep clocks always enabled:
+ * video_cc_ahb_clk
+ * video_cc_xo_clk
+ */
+ regmap_update_bits(regmap, 0xe58, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0xeec, BIT(0), BIT(0));
+
+ ret = qcom_cc_really_probe(pdev, &video_cc_sm8350_desc, regmap);
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
+}
+
+static const struct of_device_id video_cc_sm8350_match_table[] = {
+ { .compatible = "qcom,sm8350-videocc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, video_cc_sm8350_match_table);
+
+static struct platform_driver video_cc_sm8350_driver = {
+ .probe = video_cc_sm8350_probe,
+ .driver = {
+ .name = "sm8350-videocc",
+ .of_match_table = video_cc_sm8350_match_table,
+ },
+};
+module_platform_driver(video_cc_sm8350_driver);
+
+MODULE_DESCRIPTION("QTI SM8350 VIDEOCC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/videocc-sm8450.c b/drivers/clk/qcom/videocc-sm8450.c
new file mode 100644
index 000000000000..7d0029b8b799
--- /dev/null
+++ b/drivers/clk/qcom/videocc-sm8450.c
@@ -0,0 +1,463 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sm8450-videocc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_BI_TCXO,
+};
+
+enum {
+ P_BI_TCXO,
+ P_VIDEO_CC_PLL0_OUT_MAIN,
+ P_VIDEO_CC_PLL1_OUT_MAIN,
+};
+
+static const struct pll_vco lucid_evo_vco[] = {
+ { 249600000, 2020000000, 0 },
+};
+
+static const struct alpha_pll_config video_cc_pll0_config = {
+ /* .l includes CAL_L_VAL, L_VAL fields */
+ .l = 0x0044001e,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000805,
+};
+
+static struct clk_alpha_pll video_cc_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct alpha_pll_config video_cc_pll1_config = {
+ /* .l includes CAL_L_VAL, L_VAL fields */
+ .l = 0x0044002b,
+ .alpha = 0xc000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000805,
+};
+
+static struct clk_alpha_pll video_cc_pll1 = {
+ .offset = 0x1000,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_pll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct parent_map video_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_VIDEO_CC_PLL0_OUT_MAIN, 1 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &video_cc_pll0.clkr.hw },
+};
+
+static const struct parent_map video_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_VIDEO_CC_PLL1_OUT_MAIN, 1 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &video_cc_pll1.clkr.hw },
+};
+
+static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = {
+ F(576000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(720000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1014000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1098000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1332000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_mvs0_clk_src = {
+ .cmd_rcgr = 0x8000,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_0,
+ .freq_tbl = ftbl_video_cc_mvs0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_clk_src",
+ .parent_data = video_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = {
+ F(840000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1050000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1350000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1500000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1650000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_mvs1_clk_src = {
+ .cmd_rcgr = 0x8018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_1,
+ .freq_tbl = ftbl_video_cc_mvs1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_clk_src",
+ .parent_data = video_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs0_div_clk_src = {
+ .reg = 0x80b8,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = {
+ .reg = 0x806c,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0c_div2_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs1_div_clk_src = {
+ .reg = 0x80dc,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = {
+ .reg = 0x8094,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1c_div2_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch video_cc_mvs0_clk = {
+ .halt_reg = 0x80b0,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x80b0,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x80b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs0c_clk = {
+ .halt_reg = 0x8064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0c_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0c_div2_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs1_clk = {
+ .halt_reg = 0x80d4,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x80d4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x80d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs1_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs1c_clk = {
+ .halt_reg = 0x808c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x808c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1c_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs1c_div2_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc video_cc_mvs0c_gdsc = {
+ .gdscr = 0x804c,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs0c_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct gdsc video_cc_mvs0_gdsc = {
+ .gdscr = 0x809c,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &video_cc_mvs0c_gdsc.pd,
+ .flags = RETAIN_FF_ENABLE | HW_CTRL,
+};
+
+static struct gdsc video_cc_mvs1c_gdsc = {
+ .gdscr = 0x8074,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs1c_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct gdsc video_cc_mvs1_gdsc = {
+ .gdscr = 0x80c0,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &video_cc_mvs1c_gdsc.pd,
+ .flags = RETAIN_FF_ENABLE | HW_CTRL,
+};
+
+static struct clk_regmap *video_cc_sm8450_clocks[] = {
+ [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr,
+ [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr,
+ [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr,
+ [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr,
+ [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr,
+ [VIDEO_CC_MVS1_CLK] = &video_cc_mvs1_clk.clkr,
+ [VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr,
+ [VIDEO_CC_MVS1_DIV_CLK_SRC] = &video_cc_mvs1_div_clk_src.clkr,
+ [VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr,
+ [VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr,
+ [VIDEO_CC_PLL0] = &video_cc_pll0.clkr,
+ [VIDEO_CC_PLL1] = &video_cc_pll1.clkr,
+};
+
+static struct gdsc *video_cc_sm8450_gdscs[] = {
+ [VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc,
+ [VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc,
+ [VIDEO_CC_MVS1C_GDSC] = &video_cc_mvs1c_gdsc,
+ [VIDEO_CC_MVS1_GDSC] = &video_cc_mvs1_gdsc,
+};
+
+static const struct qcom_reset_map video_cc_sm8450_resets[] = {
+ [CVP_VIDEO_CC_INTERFACE_BCR] = { 0x80e0 },
+ [CVP_VIDEO_CC_MVS0_BCR] = { 0x8098 },
+ [CVP_VIDEO_CC_MVS0C_BCR] = { 0x8048 },
+ [CVP_VIDEO_CC_MVS1_BCR] = { 0x80bc },
+ [CVP_VIDEO_CC_MVS1C_BCR] = { 0x8070 },
+ [VIDEO_CC_MVS0C_CLK_ARES] = { 0x8064, 2 },
+ [VIDEO_CC_MVS1C_CLK_ARES] = { 0x808c, 2 },
+};
+
+static const struct regmap_config video_cc_sm8450_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x9f4c,
+ .fast_io = true,
+};
+
+static struct qcom_cc_desc video_cc_sm8450_desc = {
+ .config = &video_cc_sm8450_regmap_config,
+ .clks = video_cc_sm8450_clocks,
+ .num_clks = ARRAY_SIZE(video_cc_sm8450_clocks),
+ .resets = video_cc_sm8450_resets,
+ .num_resets = ARRAY_SIZE(video_cc_sm8450_resets),
+ .gdscs = video_cc_sm8450_gdscs,
+ .num_gdscs = ARRAY_SIZE(video_cc_sm8450_gdscs),
+};
+
+static const struct of_device_id video_cc_sm8450_match_table[] = {
+ { .compatible = "qcom,sm8450-videocc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, video_cc_sm8450_match_table);
+
+static int video_cc_sm8450_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
+
+ regmap = qcom_cc_map(pdev, &video_cc_sm8450_desc);
+ if (IS_ERR(regmap)) {
+ pm_runtime_put(&pdev->dev);
+ return PTR_ERR(regmap);
+ }
+
+ clk_lucid_evo_pll_configure(&video_cc_pll0, regmap, &video_cc_pll0_config);
+ clk_lucid_evo_pll_configure(&video_cc_pll1, regmap, &video_cc_pll1_config);
+
+ /*
+ * Keep clocks always enabled:
+ * video_cc_ahb_clk
+ * video_cc_sleep_clk
+ * video_cc_xo_clk
+ */
+ regmap_update_bits(regmap, 0x80e4, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x8130, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x8114, BIT(0), BIT(0));
+
+ ret = qcom_cc_really_probe(pdev, &video_cc_sm8450_desc, regmap);
+
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
+}
+
+static struct platform_driver video_cc_sm8450_driver = {
+ .probe = video_cc_sm8450_probe,
+ .driver = {
+ .name = "video_cc-sm8450",
+ .of_match_table = video_cc_sm8450_match_table,
+ },
+};
+
+static int __init video_cc_sm8450_init(void)
+{
+ return platform_driver_register(&video_cc_sm8450_driver);
+}
+subsys_initcall(video_cc_sm8450_init);
+
+static void __exit video_cc_sm8450_exit(void)
+{
+ platform_driver_unregister(&video_cc_sm8450_driver);
+}
+module_exit(video_cc_sm8450_exit);
+
+MODULE_DESCRIPTION("QTI VIDEOCC SM8450 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/videocc-sm8550.c b/drivers/clk/qcom/videocc-sm8550.c
new file mode 100644
index 000000000000..e2400fe23e60
--- /dev/null
+++ b/drivers/clk/qcom/videocc-sm8550.c
@@ -0,0 +1,470 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sm8450-videocc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_BI_TCXO,
+};
+
+enum {
+ P_BI_TCXO,
+ P_VIDEO_CC_PLL0_OUT_MAIN,
+ P_VIDEO_CC_PLL1_OUT_MAIN,
+};
+
+static const struct pll_vco lucid_ole_vco[] = {
+ { 249600000, 2300000000, 0 },
+};
+
+static const struct alpha_pll_config video_cc_pll0_config = {
+ /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */
+ .l = 0x44440025,
+ .alpha = 0x8000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll video_cc_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct alpha_pll_config video_cc_pll1_config = {
+ /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */
+ .l = 0x44440036,
+ .alpha = 0xb000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll video_cc_pll1 = {
+ .offset = 0x1000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_pll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct parent_map video_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_VIDEO_CC_PLL0_OUT_MAIN, 1 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &video_cc_pll0.clkr.hw },
+};
+
+static const struct parent_map video_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_VIDEO_CC_PLL1_OUT_MAIN, 1 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &video_cc_pll1.clkr.hw },
+};
+
+static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = {
+ F(720000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1014000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1098000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1332000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1600000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_mvs0_clk_src = {
+ .cmd_rcgr = 0x8000,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_0,
+ .freq_tbl = ftbl_video_cc_mvs0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_clk_src",
+ .parent_data = video_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = {
+ F(1050000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1350000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1500000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1650000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_mvs1_clk_src = {
+ .cmd_rcgr = 0x8018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_1,
+ .freq_tbl = ftbl_video_cc_mvs1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_clk_src",
+ .parent_data = video_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs0_div_clk_src = {
+ .reg = 0x80c4,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = {
+ .reg = 0x8070,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0c_div2_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs1_div_clk_src = {
+ .reg = 0x80ec,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = {
+ .reg = 0x809c,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1c_div2_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch video_cc_mvs0_clk = {
+ .halt_reg = 0x80b8,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x80b8,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x80b8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs0c_clk = {
+ .halt_reg = 0x8064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0c_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0c_div2_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs1_clk = {
+ .halt_reg = 0x80e0,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x80e0,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x80e0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs1_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs1c_clk = {
+ .halt_reg = 0x8090,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8090,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1c_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs1c_div2_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc video_cc_mvs0c_gdsc = {
+ .gdscr = 0x804c,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs0c_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc video_cc_mvs0_gdsc = {
+ .gdscr = 0x80a4,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &video_cc_mvs0c_gdsc.pd,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL,
+};
+
+static struct gdsc video_cc_mvs1c_gdsc = {
+ .gdscr = 0x8078,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs1c_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc video_cc_mvs1_gdsc = {
+ .gdscr = 0x80cc,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &video_cc_mvs1c_gdsc.pd,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL,
+};
+
+static struct clk_regmap *video_cc_sm8550_clocks[] = {
+ [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr,
+ [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr,
+ [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr,
+ [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr,
+ [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr,
+ [VIDEO_CC_MVS1_CLK] = &video_cc_mvs1_clk.clkr,
+ [VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr,
+ [VIDEO_CC_MVS1_DIV_CLK_SRC] = &video_cc_mvs1_div_clk_src.clkr,
+ [VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr,
+ [VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr,
+ [VIDEO_CC_PLL0] = &video_cc_pll0.clkr,
+ [VIDEO_CC_PLL1] = &video_cc_pll1.clkr,
+};
+
+static struct gdsc *video_cc_sm8550_gdscs[] = {
+ [VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc,
+ [VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc,
+ [VIDEO_CC_MVS1C_GDSC] = &video_cc_mvs1c_gdsc,
+ [VIDEO_CC_MVS1_GDSC] = &video_cc_mvs1_gdsc,
+};
+
+static const struct qcom_reset_map video_cc_sm8550_resets[] = {
+ [CVP_VIDEO_CC_INTERFACE_BCR] = { 0x80f0 },
+ [CVP_VIDEO_CC_MVS0_BCR] = { 0x80a0 },
+ [CVP_VIDEO_CC_MVS0C_BCR] = { 0x8048 },
+ [CVP_VIDEO_CC_MVS1_BCR] = { 0x80c8 },
+ [CVP_VIDEO_CC_MVS1C_BCR] = { 0x8074 },
+ [VIDEO_CC_MVS0C_CLK_ARES] = { 0x8064, 2 },
+ [VIDEO_CC_MVS1C_CLK_ARES] = { 0x8090, 2 },
+};
+
+static const struct regmap_config video_cc_sm8550_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x9f4c,
+ .fast_io = true,
+};
+
+static struct qcom_cc_desc video_cc_sm8550_desc = {
+ .config = &video_cc_sm8550_regmap_config,
+ .clks = video_cc_sm8550_clocks,
+ .num_clks = ARRAY_SIZE(video_cc_sm8550_clocks),
+ .resets = video_cc_sm8550_resets,
+ .num_resets = ARRAY_SIZE(video_cc_sm8550_resets),
+ .gdscs = video_cc_sm8550_gdscs,
+ .num_gdscs = ARRAY_SIZE(video_cc_sm8550_gdscs),
+};
+
+static const struct of_device_id video_cc_sm8550_match_table[] = {
+ { .compatible = "qcom,sm8550-videocc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, video_cc_sm8550_match_table);
+
+static int video_cc_sm8550_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
+
+ regmap = qcom_cc_map(pdev, &video_cc_sm8550_desc);
+ if (IS_ERR(regmap)) {
+ pm_runtime_put(&pdev->dev);
+ return PTR_ERR(regmap);
+ }
+
+ clk_lucid_evo_pll_configure(&video_cc_pll0, regmap, &video_cc_pll0_config);
+ clk_lucid_evo_pll_configure(&video_cc_pll1, regmap, &video_cc_pll1_config);
+
+ /*
+ * Keep clocks always enabled:
+ * video_cc_ahb_clk
+ * video_cc_sleep_clk
+ * video_cc_xo_clk
+ */
+ regmap_update_bits(regmap, 0x80f4, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x8140, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x8124, BIT(0), BIT(0));
+
+ ret = qcom_cc_really_probe(pdev, &video_cc_sm8550_desc, regmap);
+
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
+}
+
+static struct platform_driver video_cc_sm8550_driver = {
+ .probe = video_cc_sm8550_probe,
+ .driver = {
+ .name = "video_cc-sm8550",
+ .of_match_table = video_cc_sm8550_match_table,
+ },
+};
+
+static int __init video_cc_sm8550_init(void)
+{
+ return platform_driver_register(&video_cc_sm8550_driver);
+}
+subsys_initcall(video_cc_sm8550_init);
+
+static void __exit video_cc_sm8550_exit(void)
+{
+ platform_driver_unregister(&video_cc_sm8550_driver);
+}
+module_exit(video_cc_sm8550_exit);
+
+MODULE_DESCRIPTION("QTI VIDEOCC SM8550 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/ralink/Kconfig b/drivers/clk/ralink/Kconfig
index 6580d5edc676..7c4f335864a8 100644
--- a/drivers/clk/ralink/Kconfig
+++ b/drivers/clk/ralink/Kconfig
@@ -9,3 +9,10 @@ config CLK_MT7621
select MFD_SYSCON
help
This driver supports MediaTek MT7621 basic clocks.
+
+config CLK_MTMIPS
+ bool "Clock driver for MTMIPS SoCs"
+ depends on SOC_RT305X || SOC_RT288X || SOC_RT3883 || SOC_MT7620 || COMPILE_TEST
+ select MFD_SYSCON
+ help
+ This driver supports MTMIPS basic clocks.
diff --git a/drivers/clk/ralink/Makefile b/drivers/clk/ralink/Makefile
index cf6f9216379d..398c1bf8cbc1 100644
--- a/drivers/clk/ralink/Makefile
+++ b/drivers/clk/ralink/Makefile
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CLK_MT7621) += clk-mt7621.o
+obj-$(CONFIG_CLK_MTMIPS) += clk-mtmips.o
diff --git a/drivers/clk/ralink/clk-mtmips.c b/drivers/clk/ralink/clk-mtmips.c
new file mode 100644
index 000000000000..1e7991439527
--- /dev/null
+++ b/drivers/clk/ralink/clk-mtmips.c
@@ -0,0 +1,1117 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MTMIPS SoCs Clock Driver
+ * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+/* Configuration registers */
+#define SYSC_REG_SYSTEM_CONFIG 0x10
+#define SYSC_REG_CLKCFG0 0x2c
+#define SYSC_REG_RESET_CTRL 0x34
+#define SYSC_REG_CPU_SYS_CLKCFG 0x3c
+#define SYSC_REG_CPLL_CONFIG0 0x54
+#define SYSC_REG_CPLL_CONFIG1 0x58
+
+/* RT2880 SoC */
+#define RT2880_CONFIG_CPUCLK_SHIFT 20
+#define RT2880_CONFIG_CPUCLK_MASK 0x3
+#define RT2880_CONFIG_CPUCLK_250 0x0
+#define RT2880_CONFIG_CPUCLK_266 0x1
+#define RT2880_CONFIG_CPUCLK_280 0x2
+#define RT2880_CONFIG_CPUCLK_300 0x3
+
+/* RT305X SoC */
+#define RT305X_SYSCFG_CPUCLK_SHIFT 18
+#define RT305X_SYSCFG_CPUCLK_MASK 0x1
+#define RT305X_SYSCFG_CPUCLK_LOW 0x0
+#define RT305X_SYSCFG_CPUCLK_HIGH 0x1
+
+/* RT3352 SoC */
+#define RT3352_SYSCFG0_CPUCLK_SHIFT 8
+#define RT3352_SYSCFG0_CPUCLK_MASK 0x1
+#define RT3352_SYSCFG0_CPUCLK_LOW 0x0
+#define RT3352_SYSCFG0_CPUCLK_HIGH 0x1
+
+/* RT3383 SoC */
+#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17)
+#define RT3883_SYSCFG0_CPUCLK_SHIFT 8
+#define RT3883_SYSCFG0_CPUCLK_MASK 0x3
+#define RT3883_SYSCFG0_CPUCLK_250 0x0
+#define RT3883_SYSCFG0_CPUCLK_384 0x1
+#define RT3883_SYSCFG0_CPUCLK_480 0x2
+#define RT3883_SYSCFG0_CPUCLK_500 0x3
+
+/* RT5350 SoC */
+#define RT5350_CLKCFG0_XTAL_SEL BIT(20)
+#define RT5350_SYSCFG0_CPUCLK_SHIFT 8
+#define RT5350_SYSCFG0_CPUCLK_MASK 0x3
+#define RT5350_SYSCFG0_CPUCLK_360 0x0
+#define RT5350_SYSCFG0_CPUCLK_320 0x2
+#define RT5350_SYSCFG0_CPUCLK_300 0x3
+
+/* MT7620 and MT76x8 SoCs */
+#define MT7620_XTAL_FREQ_SEL BIT(6)
+#define CPLL_CFG0_SW_CFG BIT(31)
+#define CPLL_CFG0_PLL_MULT_RATIO_SHIFT 16
+#define CPLL_CFG0_PLL_MULT_RATIO_MASK 0x7
+#define CPLL_CFG0_LC_CURFCK BIT(15)
+#define CPLL_CFG0_BYPASS_REF_CLK BIT(14)
+#define CPLL_CFG0_PLL_DIV_RATIO_SHIFT 10
+#define CPLL_CFG0_PLL_DIV_RATIO_MASK 0x3
+#define CPLL_CFG1_CPU_AUX1 BIT(25)
+#define CPLL_CFG1_CPU_AUX0 BIT(24)
+#define CLKCFG0_PERI_CLK_SEL BIT(4)
+#define CPU_SYS_CLKCFG_OCP_RATIO_SHIFT 16
+#define CPU_SYS_CLKCFG_OCP_RATIO_MASK 0xf
+#define CPU_SYS_CLKCFG_OCP_RATIO_1 0 /* 1:1 (Reserved) */
+#define CPU_SYS_CLKCFG_OCP_RATIO_1_5 1 /* 1:1.5 (Reserved) */
+#define CPU_SYS_CLKCFG_OCP_RATIO_2 2 /* 1:2 */
+#define CPU_SYS_CLKCFG_OCP_RATIO_2_5 3 /* 1:2.5 (Reserved) */
+#define CPU_SYS_CLKCFG_OCP_RATIO_3 4 /* 1:3 */
+#define CPU_SYS_CLKCFG_OCP_RATIO_3_5 5 /* 1:3.5 (Reserved) */
+#define CPU_SYS_CLKCFG_OCP_RATIO_4 6 /* 1:4 */
+#define CPU_SYS_CLKCFG_OCP_RATIO_5 7 /* 1:5 */
+#define CPU_SYS_CLKCFG_OCP_RATIO_10 8 /* 1:10 */
+#define CPU_SYS_CLKCFG_CPU_FDIV_SHIFT 8
+#define CPU_SYS_CLKCFG_CPU_FDIV_MASK 0x1f
+#define CPU_SYS_CLKCFG_CPU_FFRAC_SHIFT 0
+#define CPU_SYS_CLKCFG_CPU_FFRAC_MASK 0x1f
+
+/* clock scaling */
+#define CLKCFG_FDIV_MASK 0x1f00
+#define CLKCFG_FDIV_USB_VAL 0x0300
+#define CLKCFG_FFRAC_MASK 0x001f
+#define CLKCFG_FFRAC_USB_VAL 0x0003
+
+struct mtmips_clk;
+struct mtmips_clk_fixed;
+struct mtmips_clk_factor;
+
+struct mtmips_clk_data {
+ struct mtmips_clk *clk_base;
+ size_t num_clk_base;
+ struct mtmips_clk_fixed *clk_fixed;
+ size_t num_clk_fixed;
+ struct mtmips_clk_factor *clk_factor;
+ size_t num_clk_factor;
+ struct mtmips_clk *clk_periph;
+ size_t num_clk_periph;
+};
+
+struct mtmips_clk_priv {
+ struct regmap *sysc;
+ const struct mtmips_clk_data *data;
+};
+
+struct mtmips_clk {
+ struct clk_hw hw;
+ struct mtmips_clk_priv *priv;
+};
+
+struct mtmips_clk_fixed {
+ const char *name;
+ const char *parent;
+ unsigned long rate;
+ struct clk_hw *hw;
+};
+
+struct mtmips_clk_factor {
+ const char *name;
+ const char *parent;
+ int mult;
+ int div;
+ unsigned long flags;
+ struct clk_hw *hw;
+};
+
+static unsigned long mtmips_pherip_clk_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return parent_rate;
+}
+
+static const struct clk_ops mtmips_periph_clk_ops = {
+ .recalc_rate = mtmips_pherip_clk_rate,
+};
+
+#define CLK_PERIPH(_name, _parent) { \
+ .init = &(const struct clk_init_data) { \
+ .name = _name, \
+ .ops = &mtmips_periph_clk_ops, \
+ .parent_data = &(const struct clk_parent_data) {\
+ .name = _parent, \
+ .fw_name = _parent \
+ }, \
+ .num_parents = 1, \
+ /* \
+ * There are drivers for these SoCs that are \
+ * older than clock driver and are not prepared \
+ * for the clock. We don't want the kernel to \
+ * disable anything so we add CLK_IS_CRITICAL \
+ * flag here. \
+ */ \
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL \
+ }, \
+}
+
+static struct mtmips_clk rt2880_pherip_clks[] = {
+ { CLK_PERIPH("300100.timer", "bus") },
+ { CLK_PERIPH("300120.watchdog", "bus") },
+ { CLK_PERIPH("300500.uart", "bus") },
+ { CLK_PERIPH("300900.i2c", "bus") },
+ { CLK_PERIPH("300c00.uartlite", "bus") },
+ { CLK_PERIPH("400000.ethernet", "bus") },
+ { CLK_PERIPH("480000.wmac", "xtal") }
+};
+
+static struct mtmips_clk rt305x_pherip_clks[] = {
+ { CLK_PERIPH("10000100.timer", "bus") },
+ { CLK_PERIPH("10000120.watchdog", "bus") },
+ { CLK_PERIPH("10000500.uart", "bus") },
+ { CLK_PERIPH("10000900.i2c", "bus") },
+ { CLK_PERIPH("10000a00.i2s", "bus") },
+ { CLK_PERIPH("10000b00.spi", "bus") },
+ { CLK_PERIPH("10000b40.spi", "bus") },
+ { CLK_PERIPH("10000c00.uartlite", "bus") },
+ { CLK_PERIPH("10100000.ethernet", "bus") },
+ { CLK_PERIPH("10180000.wmac", "xtal") }
+};
+
+static struct mtmips_clk rt5350_pherip_clks[] = {
+ { CLK_PERIPH("10000100.timer", "bus") },
+ { CLK_PERIPH("10000120.watchdog", "bus") },
+ { CLK_PERIPH("10000500.uart", "periph") },
+ { CLK_PERIPH("10000900.i2c", "periph") },
+ { CLK_PERIPH("10000a00.i2s", "periph") },
+ { CLK_PERIPH("10000b00.spi", "bus") },
+ { CLK_PERIPH("10000b40.spi", "bus") },
+ { CLK_PERIPH("10000c00.uartlite", "periph") },
+ { CLK_PERIPH("10100000.ethernet", "bus") },
+ { CLK_PERIPH("10180000.wmac", "xtal") }
+};
+
+static struct mtmips_clk mt7620_pherip_clks[] = {
+ { CLK_PERIPH("10000100.timer", "periph") },
+ { CLK_PERIPH("10000120.watchdog", "periph") },
+ { CLK_PERIPH("10000500.uart", "periph") },
+ { CLK_PERIPH("10000900.i2c", "periph") },
+ { CLK_PERIPH("10000a00.i2s", "periph") },
+ { CLK_PERIPH("10000b00.spi", "bus") },
+ { CLK_PERIPH("10000b40.spi", "bus") },
+ { CLK_PERIPH("10000c00.uartlite", "periph") },
+ { CLK_PERIPH("10180000.wmac", "xtal") }
+};
+
+static struct mtmips_clk mt76x8_pherip_clks[] = {
+ { CLK_PERIPH("10000100.timer", "periph") },
+ { CLK_PERIPH("10000120.watchdog", "periph") },
+ { CLK_PERIPH("10000900.i2c", "periph") },
+ { CLK_PERIPH("10000a00.i2s", "pcmi2s") },
+ { CLK_PERIPH("10000b00.spi", "bus") },
+ { CLK_PERIPH("10000b40.spi", "bus") },
+ { CLK_PERIPH("10000c00.uart0", "periph") },
+ { CLK_PERIPH("10000d00.uart1", "periph") },
+ { CLK_PERIPH("10000e00.uart2", "periph") },
+ { CLK_PERIPH("10300000.wmac", "xtal") }
+};
+
+static int mtmips_register_pherip_clocks(struct device_node *np,
+ struct clk_hw_onecell_data *clk_data,
+ struct mtmips_clk_priv *priv)
+{
+ struct clk_hw **hws = clk_data->hws;
+ struct mtmips_clk *sclk;
+ size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed +
+ priv->data->num_clk_factor;
+ int ret, i;
+
+ for (i = 0; i < priv->data->num_clk_periph; i++) {
+ int idx = idx_start + i;
+
+ sclk = &priv->data->clk_periph[i];
+ ret = of_clk_hw_register(np, &sclk->hw);
+ if (ret) {
+ pr_err("Couldn't register peripheral clock %d\n", idx);
+ goto err_clk_unreg;
+ }
+
+ hws[idx] = &sclk->hw;
+ }
+
+ return 0;
+
+err_clk_unreg:
+ while (--i >= 0) {
+ sclk = &priv->data->clk_periph[i];
+ clk_hw_unregister(&sclk->hw);
+ }
+ return ret;
+}
+
+#define CLK_FIXED(_name, _parent, _rate) \
+ { \
+ .name = _name, \
+ .parent = _parent, \
+ .rate = _rate \
+ }
+
+static struct mtmips_clk_fixed rt305x_fixed_clocks[] = {
+ CLK_FIXED("xtal", NULL, 40000000)
+};
+
+static struct mtmips_clk_fixed rt3352_fixed_clocks[] = {
+ CLK_FIXED("periph", "xtal", 40000000)
+};
+
+static struct mtmips_clk_fixed mt76x8_fixed_clocks[] = {
+ CLK_FIXED("pcmi2s", "xtal", 480000000),
+ CLK_FIXED("periph", "xtal", 40000000)
+};
+
+static int mtmips_register_fixed_clocks(struct clk_hw_onecell_data *clk_data,
+ struct mtmips_clk_priv *priv)
+{
+ struct clk_hw **hws = clk_data->hws;
+ struct mtmips_clk_fixed *sclk;
+ size_t idx_start = priv->data->num_clk_base;
+ int ret, i;
+
+ for (i = 0; i < priv->data->num_clk_fixed; i++) {
+ int idx = idx_start + i;
+
+ sclk = &priv->data->clk_fixed[i];
+ sclk->hw = clk_hw_register_fixed_rate(NULL, sclk->name,
+ sclk->parent, 0,
+ sclk->rate);
+ if (IS_ERR(sclk->hw)) {
+ ret = PTR_ERR(sclk->hw);
+ pr_err("Couldn't register fixed clock %d\n", idx);
+ goto err_clk_unreg;
+ }
+
+ hws[idx] = sclk->hw;
+ }
+
+ return 0;
+
+err_clk_unreg:
+ while (--i >= 0) {
+ sclk = &priv->data->clk_fixed[i];
+ clk_hw_unregister_fixed_rate(sclk->hw);
+ }
+ return ret;
+}
+
+#define CLK_FACTOR(_name, _parent, _mult, _div) \
+ { \
+ .name = _name, \
+ .parent = _parent, \
+ .mult = _mult, \
+ .div = _div, \
+ .flags = CLK_SET_RATE_PARENT \
+ }
+
+static struct mtmips_clk_factor rt2880_factor_clocks[] = {
+ CLK_FACTOR("bus", "cpu", 1, 2)
+};
+
+static struct mtmips_clk_factor rt305x_factor_clocks[] = {
+ CLK_FACTOR("bus", "cpu", 1, 3)
+};
+
+static int mtmips_register_factor_clocks(struct clk_hw_onecell_data *clk_data,
+ struct mtmips_clk_priv *priv)
+{
+ struct clk_hw **hws = clk_data->hws;
+ struct mtmips_clk_factor *sclk;
+ size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed;
+ int ret, i;
+
+ for (i = 0; i < priv->data->num_clk_factor; i++) {
+ int idx = idx_start + i;
+
+ sclk = &priv->data->clk_factor[i];
+ sclk->hw = clk_hw_register_fixed_factor(NULL, sclk->name,
+ sclk->parent, sclk->flags,
+ sclk->mult, sclk->div);
+ if (IS_ERR(sclk->hw)) {
+ ret = PTR_ERR(sclk->hw);
+ pr_err("Couldn't register factor clock %d\n", idx);
+ goto err_clk_unreg;
+ }
+
+ hws[idx] = sclk->hw;
+ }
+
+ return 0;
+
+err_clk_unreg:
+ while (--i >= 0) {
+ sclk = &priv->data->clk_factor[i];
+ clk_hw_unregister_fixed_factor(sclk->hw);
+ }
+ return ret;
+}
+
+static inline struct mtmips_clk *to_mtmips_clk(struct clk_hw *hw)
+{
+ return container_of(hw, struct mtmips_clk, hw);
+}
+
+static unsigned long rt5350_xtal_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 val;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &val);
+ if (!(val & RT5350_CLKCFG0_XTAL_SEL))
+ return 20000000;
+
+ return 40000000;
+}
+
+static unsigned long rt5350_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long xtal_clk)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ t = (t >> RT5350_SYSCFG0_CPUCLK_SHIFT) & RT5350_SYSCFG0_CPUCLK_MASK;
+
+ switch (t) {
+ case RT5350_SYSCFG0_CPUCLK_360:
+ return 360000000;
+ case RT5350_SYSCFG0_CPUCLK_320:
+ return 320000000;
+ case RT5350_SYSCFG0_CPUCLK_300:
+ return 300000000;
+ default:
+ BUG();
+ }
+}
+
+static unsigned long rt5350_bus_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ if (parent_rate == 320000000)
+ return parent_rate / 4;
+
+ return parent_rate / 3;
+}
+
+static unsigned long rt3352_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long xtal_clk)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ t = (t >> RT3352_SYSCFG0_CPUCLK_SHIFT) & RT3352_SYSCFG0_CPUCLK_MASK;
+
+ switch (t) {
+ case RT3352_SYSCFG0_CPUCLK_LOW:
+ return 384000000;
+ case RT3352_SYSCFG0_CPUCLK_HIGH:
+ return 400000000;
+ default:
+ BUG();
+ }
+}
+
+static unsigned long rt305x_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long xtal_clk)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ t = (t >> RT305X_SYSCFG_CPUCLK_SHIFT) & RT305X_SYSCFG_CPUCLK_MASK;
+
+ switch (t) {
+ case RT305X_SYSCFG_CPUCLK_LOW:
+ return 320000000;
+ case RT305X_SYSCFG_CPUCLK_HIGH:
+ return 384000000;
+ default:
+ BUG();
+ }
+}
+
+static unsigned long rt3883_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long xtal_clk)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ t = (t >> RT3883_SYSCFG0_CPUCLK_SHIFT) & RT3883_SYSCFG0_CPUCLK_MASK;
+
+ switch (t) {
+ case RT3883_SYSCFG0_CPUCLK_250:
+ return 250000000;
+ case RT3883_SYSCFG0_CPUCLK_384:
+ return 384000000;
+ case RT3883_SYSCFG0_CPUCLK_480:
+ return 480000000;
+ case RT3883_SYSCFG0_CPUCLK_500:
+ return 500000000;
+ default:
+ BUG();
+ }
+}
+
+static unsigned long rt3883_bus_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 ddr2;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ ddr2 = t & RT3883_SYSCFG0_DRAM_TYPE_DDR2;
+
+ switch (parent_rate) {
+ case 250000000:
+ return (ddr2) ? 125000000 : 83000000;
+ case 384000000:
+ return (ddr2) ? 128000000 : 96000000;
+ case 480000000:
+ return (ddr2) ? 160000000 : 120000000;
+ case 500000000:
+ return (ddr2) ? 166000000 : 125000000;
+ default:
+ WARN_ON_ONCE(parent_rate == 0);
+ return parent_rate / 4;
+ }
+}
+
+static unsigned long rt2880_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long xtal_clk)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ t = (t >> RT2880_CONFIG_CPUCLK_SHIFT) & RT2880_CONFIG_CPUCLK_MASK;
+
+ switch (t) {
+ case RT2880_CONFIG_CPUCLK_250:
+ return 250000000;
+ case RT2880_CONFIG_CPUCLK_266:
+ return 266000000;
+ case RT2880_CONFIG_CPUCLK_280:
+ return 280000000;
+ case RT2880_CONFIG_CPUCLK_300:
+ return 300000000;
+ default:
+ BUG();
+ }
+}
+
+static u32 mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div)
+{
+ u64 t;
+
+ t = ref_rate;
+ t *= mul;
+ t = div_u64(t, div);
+
+ return t;
+}
+
+static unsigned long mt7620_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ static const u32 clk_divider[] = { 2, 3, 4, 8 };
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ unsigned long cpu_pll;
+ u32 t;
+ u32 mul;
+ u32 div;
+
+ regmap_read(sysc, SYSC_REG_CPLL_CONFIG0, &t);
+ if (t & CPLL_CFG0_BYPASS_REF_CLK) {
+ cpu_pll = parent_rate;
+ } else if ((t & CPLL_CFG0_SW_CFG) == 0) {
+ cpu_pll = 600000000;
+ } else {
+ mul = (t >> CPLL_CFG0_PLL_MULT_RATIO_SHIFT) &
+ CPLL_CFG0_PLL_MULT_RATIO_MASK;
+ mul += 24;
+ if (t & CPLL_CFG0_LC_CURFCK)
+ mul *= 2;
+
+ div = (t >> CPLL_CFG0_PLL_DIV_RATIO_SHIFT) &
+ CPLL_CFG0_PLL_DIV_RATIO_MASK;
+
+ WARN_ON_ONCE(div >= ARRAY_SIZE(clk_divider));
+
+ cpu_pll = mt7620_calc_rate(parent_rate, mul, clk_divider[div]);
+ }
+
+ regmap_read(sysc, SYSC_REG_CPLL_CONFIG1, &t);
+ if (t & CPLL_CFG1_CPU_AUX1)
+ return parent_rate;
+
+ if (t & CPLL_CFG1_CPU_AUX0)
+ return 480000000;
+
+ return cpu_pll;
+}
+
+static unsigned long mt7620_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+ u32 mul;
+ u32 div;
+
+ regmap_read(sysc, SYSC_REG_CPU_SYS_CLKCFG, &t);
+ mul = t & CPU_SYS_CLKCFG_CPU_FFRAC_MASK;
+ div = (t >> CPU_SYS_CLKCFG_CPU_FDIV_SHIFT) &
+ CPU_SYS_CLKCFG_CPU_FDIV_MASK;
+
+ return mt7620_calc_rate(parent_rate, mul, div);
+}
+
+static unsigned long mt7620_bus_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ static const u32 ocp_dividers[16] = {
+ [CPU_SYS_CLKCFG_OCP_RATIO_2] = 2,
+ [CPU_SYS_CLKCFG_OCP_RATIO_3] = 3,
+ [CPU_SYS_CLKCFG_OCP_RATIO_4] = 4,
+ [CPU_SYS_CLKCFG_OCP_RATIO_5] = 5,
+ [CPU_SYS_CLKCFG_OCP_RATIO_10] = 10,
+ };
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+ u32 ocp_ratio;
+ u32 div;
+
+ regmap_read(sysc, SYSC_REG_CPU_SYS_CLKCFG, &t);
+ ocp_ratio = (t >> CPU_SYS_CLKCFG_OCP_RATIO_SHIFT) &
+ CPU_SYS_CLKCFG_OCP_RATIO_MASK;
+
+ if (WARN_ON_ONCE(ocp_ratio >= ARRAY_SIZE(ocp_dividers)))
+ return parent_rate;
+
+ div = ocp_dividers[ocp_ratio];
+
+ if (WARN(!div, "invalid divider for OCP ratio %u", ocp_ratio))
+ return parent_rate;
+
+ return parent_rate / div;
+}
+
+static unsigned long mt7620_periph_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_CLKCFG0, &t);
+ if (t & CLKCFG0_PERI_CLK_SEL)
+ return parent_rate;
+
+ return 40000000;
+}
+
+static unsigned long mt76x8_xtal_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ if (t & MT7620_XTAL_FREQ_SEL)
+ return 40000000;
+
+ return 20000000;
+}
+
+static unsigned long mt76x8_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long xtal_clk)
+{
+ if (xtal_clk == 40000000)
+ return 580000000;
+
+ return 575000000;
+}
+
+#define CLK_BASE(_name, _parent, _recalc) { \
+ .init = &(const struct clk_init_data) { \
+ .name = _name, \
+ .ops = &(const struct clk_ops) { \
+ .recalc_rate = _recalc, \
+ }, \
+ .parent_data = &(const struct clk_parent_data) { \
+ .name = _parent, \
+ .fw_name = _parent \
+ }, \
+ .num_parents = _parent ? 1 : 0 \
+ }, \
+}
+
+static struct mtmips_clk rt2880_clks_base[] = {
+ { CLK_BASE("cpu", "xtal", rt2880_cpu_recalc_rate) }
+};
+
+static struct mtmips_clk rt305x_clks_base[] = {
+ { CLK_BASE("cpu", "xtal", rt305x_cpu_recalc_rate) }
+};
+
+static struct mtmips_clk rt3352_clks_base[] = {
+ { CLK_BASE("xtal", NULL, rt5350_xtal_recalc_rate) },
+ { CLK_BASE("cpu", "xtal", rt3352_cpu_recalc_rate) }
+};
+
+static struct mtmips_clk rt3883_clks_base[] = {
+ { CLK_BASE("cpu", "xtal", rt3883_cpu_recalc_rate) },
+ { CLK_BASE("bus", "cpu", rt3883_bus_recalc_rate) }
+};
+
+static struct mtmips_clk rt5350_clks_base[] = {
+ { CLK_BASE("xtal", NULL, rt5350_xtal_recalc_rate) },
+ { CLK_BASE("cpu", "xtal", rt5350_cpu_recalc_rate) },
+ { CLK_BASE("bus", "cpu", rt5350_bus_recalc_rate) }
+};
+
+static struct mtmips_clk mt7620_clks_base[] = {
+ { CLK_BASE("xtal", NULL, mt76x8_xtal_recalc_rate) },
+ { CLK_BASE("pll", "xtal", mt7620_pll_recalc_rate) },
+ { CLK_BASE("cpu", "pll", mt7620_cpu_recalc_rate) },
+ { CLK_BASE("periph", "xtal", mt7620_periph_recalc_rate) },
+ { CLK_BASE("bus", "cpu", mt7620_bus_recalc_rate) }
+};
+
+static struct mtmips_clk mt76x8_clks_base[] = {
+ { CLK_BASE("xtal", NULL, mt76x8_xtal_recalc_rate) },
+ { CLK_BASE("cpu", "xtal", mt76x8_cpu_recalc_rate) }
+};
+
+static int mtmips_register_clocks(struct device_node *np,
+ struct clk_hw_onecell_data *clk_data,
+ struct mtmips_clk_priv *priv)
+{
+ struct clk_hw **hws = clk_data->hws;
+ struct mtmips_clk *sclk;
+ int ret, i;
+
+ for (i = 0; i < priv->data->num_clk_base; i++) {
+ sclk = &priv->data->clk_base[i];
+ sclk->priv = priv;
+ ret = of_clk_hw_register(np, &sclk->hw);
+ if (ret) {
+ pr_err("Couldn't register top clock %i\n", i);
+ goto err_clk_unreg;
+ }
+
+ hws[i] = &sclk->hw;
+ }
+
+ return 0;
+
+err_clk_unreg:
+ while (--i >= 0) {
+ sclk = &priv->data->clk_base[i];
+ clk_hw_unregister(&sclk->hw);
+ }
+ return ret;
+}
+
+static const struct mtmips_clk_data rt2880_clk_data = {
+ .clk_base = rt2880_clks_base,
+ .num_clk_base = ARRAY_SIZE(rt2880_clks_base),
+ .clk_fixed = rt305x_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
+ .clk_factor = rt2880_factor_clocks,
+ .num_clk_factor = ARRAY_SIZE(rt2880_factor_clocks),
+ .clk_periph = rt2880_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(rt2880_pherip_clks),
+};
+
+static const struct mtmips_clk_data rt305x_clk_data = {
+ .clk_base = rt305x_clks_base,
+ .num_clk_base = ARRAY_SIZE(rt305x_clks_base),
+ .clk_fixed = rt305x_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
+ .clk_factor = rt305x_factor_clocks,
+ .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
+ .clk_periph = rt305x_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(rt305x_pherip_clks),
+};
+
+static const struct mtmips_clk_data rt3352_clk_data = {
+ .clk_base = rt3352_clks_base,
+ .num_clk_base = ARRAY_SIZE(rt3352_clks_base),
+ .clk_fixed = rt3352_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks),
+ .clk_factor = rt305x_factor_clocks,
+ .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
+ .clk_periph = rt5350_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks),
+};
+
+static const struct mtmips_clk_data rt3883_clk_data = {
+ .clk_base = rt3883_clks_base,
+ .num_clk_base = ARRAY_SIZE(rt3883_clks_base),
+ .clk_fixed = rt305x_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
+ .clk_factor = NULL,
+ .num_clk_factor = 0,
+ .clk_periph = rt5350_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks),
+};
+
+static const struct mtmips_clk_data rt5350_clk_data = {
+ .clk_base = rt5350_clks_base,
+ .num_clk_base = ARRAY_SIZE(rt5350_clks_base),
+ .clk_fixed = rt3352_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks),
+ .clk_factor = NULL,
+ .num_clk_factor = 0,
+ .clk_periph = rt5350_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks),
+};
+
+static const struct mtmips_clk_data mt7620_clk_data = {
+ .clk_base = mt7620_clks_base,
+ .num_clk_base = ARRAY_SIZE(mt7620_clks_base),
+ .clk_fixed = NULL,
+ .num_clk_fixed = 0,
+ .clk_factor = NULL,
+ .num_clk_factor = 0,
+ .clk_periph = mt7620_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(mt7620_pherip_clks),
+};
+
+static const struct mtmips_clk_data mt76x8_clk_data = {
+ .clk_base = mt76x8_clks_base,
+ .num_clk_base = ARRAY_SIZE(mt76x8_clks_base),
+ .clk_fixed = mt76x8_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(mt76x8_fixed_clocks),
+ .clk_factor = rt305x_factor_clocks,
+ .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
+ .clk_periph = mt76x8_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(mt76x8_pherip_clks),
+};
+
+static const struct of_device_id mtmips_of_match[] = {
+ {
+ .compatible = "ralink,rt2880-sysc",
+ .data = &rt2880_clk_data,
+ },
+ {
+ .compatible = "ralink,rt3050-sysc",
+ .data = &rt305x_clk_data,
+ },
+ {
+ .compatible = "ralink,rt3052-sysc",
+ .data = &rt305x_clk_data,
+ },
+ {
+ .compatible = "ralink,rt3352-sysc",
+ .data = &rt3352_clk_data,
+ },
+ {
+ .compatible = "ralink,rt3883-sysc",
+ .data = &rt3883_clk_data,
+ },
+ {
+ .compatible = "ralink,rt5350-sysc",
+ .data = &rt5350_clk_data,
+ },
+ {
+ .compatible = "ralink,mt7620-sysc",
+ .data = &mt7620_clk_data,
+ },
+ {
+ .compatible = "ralink,mt7628-sysc",
+ .data = &mt76x8_clk_data,
+ },
+ {
+ .compatible = "ralink,mt7688-sysc",
+ .data = &mt76x8_clk_data,
+ },
+ {}
+};
+
+static void __init mtmips_clk_regs_init(struct device_node *node,
+ struct mtmips_clk_priv *priv)
+{
+ u32 t;
+
+ if (!of_device_is_compatible(node, "ralink,mt7620-sysc"))
+ return;
+
+ /*
+ * When the CPU goes into sleep mode, the BUS
+ * clock will be too low for USB to function properly.
+ * Adjust the busses fractional divider to fix this
+ */
+ regmap_read(priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, &t);
+ t &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK);
+ t |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL;
+ regmap_write(priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, t);
+}
+
+static void __init mtmips_clk_init(struct device_node *node)
+{
+ const struct of_device_id *match;
+ const struct mtmips_clk_data *data;
+ struct mtmips_clk_priv *priv;
+ struct clk_hw_onecell_data *clk_data;
+ int ret, i, count;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return;
+
+ priv->sysc = syscon_node_to_regmap(node);
+ if (IS_ERR(priv->sysc)) {
+ pr_err("Could not get sysc syscon regmap\n");
+ goto free_clk_priv;
+ }
+
+ mtmips_clk_regs_init(node, priv);
+
+ match = of_match_node(mtmips_of_match, node);
+ if (WARN_ON(!match))
+ return;
+
+ data = match->data;
+ priv->data = data;
+ count = priv->data->num_clk_base + priv->data->num_clk_fixed +
+ priv->data->num_clk_factor + priv->data->num_clk_periph;
+ clk_data = kzalloc(struct_size(clk_data, hws, count), GFP_KERNEL);
+ if (!clk_data)
+ goto free_clk_priv;
+
+ ret = mtmips_register_clocks(node, clk_data, priv);
+ if (ret) {
+ pr_err("Couldn't register top clocks\n");
+ goto free_clk_data;
+ }
+
+ ret = mtmips_register_fixed_clocks(clk_data, priv);
+ if (ret) {
+ pr_err("Couldn't register fixed clocks\n");
+ goto unreg_clk_top;
+ }
+
+ ret = mtmips_register_factor_clocks(clk_data, priv);
+ if (ret) {
+ pr_err("Couldn't register factor clocks\n");
+ goto unreg_clk_fixed;
+ }
+
+ ret = mtmips_register_pherip_clocks(node, clk_data, priv);
+ if (ret) {
+ pr_err("Couldn't register peripheral clocks\n");
+ goto unreg_clk_factor;
+ }
+
+ clk_data->num = count;
+
+ ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+ if (ret) {
+ pr_err("Couldn't add clk hw provider\n");
+ goto unreg_clk_periph;
+ }
+
+ return;
+
+unreg_clk_periph:
+ for (i = 0; i < priv->data->num_clk_periph; i++) {
+ struct mtmips_clk *sclk = &priv->data->clk_periph[i];
+
+ clk_hw_unregister(&sclk->hw);
+ }
+
+unreg_clk_factor:
+ for (i = 0; i < priv->data->num_clk_factor; i++) {
+ struct mtmips_clk_factor *sclk = &priv->data->clk_factor[i];
+
+ clk_hw_unregister_fixed_factor(sclk->hw);
+ }
+
+unreg_clk_fixed:
+ for (i = 0; i < priv->data->num_clk_fixed; i++) {
+ struct mtmips_clk_fixed *sclk = &priv->data->clk_fixed[i];
+
+ clk_hw_unregister_fixed_rate(sclk->hw);
+ }
+
+unreg_clk_top:
+ for (i = 0; i < priv->data->num_clk_base; i++) {
+ struct mtmips_clk *sclk = &priv->data->clk_base[i];
+
+ clk_hw_unregister(&sclk->hw);
+ }
+
+free_clk_data:
+ kfree(clk_data);
+
+free_clk_priv:
+ kfree(priv);
+}
+CLK_OF_DECLARE_DRIVER(rt2880_clk, "ralink,rt2880-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(rt3050_clk, "ralink,rt3050-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(rt3052_clk, "ralink,rt3052-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(rt3352_clk, "ralink,rt3352-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(rt3883_clk, "ralink,rt3883-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(rt5350_clk, "ralink,rt5350-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(mt7620_clk, "ralink,mt7620-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(mt7628_clk, "ralink,mt7628-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(mt7688_clk, "ralink,mt7688-sysc", mtmips_clk_init);
+
+struct mtmips_rst {
+ struct reset_controller_dev rcdev;
+ struct regmap *sysc;
+};
+
+static struct mtmips_rst *to_mtmips_rst(struct reset_controller_dev *dev)
+{
+ return container_of(dev, struct mtmips_rst, rcdev);
+}
+
+static int mtmips_assert_device(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct mtmips_rst *data = to_mtmips_rst(rcdev);
+ struct regmap *sysc = data->sysc;
+
+ return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), BIT(id));
+}
+
+static int mtmips_deassert_device(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct mtmips_rst *data = to_mtmips_rst(rcdev);
+ struct regmap *sysc = data->sysc;
+
+ return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), 0);
+}
+
+static int mtmips_reset_device(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ int ret;
+
+ ret = mtmips_assert_device(rcdev, id);
+ if (ret < 0)
+ return ret;
+
+ return mtmips_deassert_device(rcdev, id);
+}
+
+static int mtmips_rst_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+ unsigned long id = reset_spec->args[0];
+
+ if (id == 0 || id >= rcdev->nr_resets)
+ return -EINVAL;
+
+ return id;
+}
+
+static const struct reset_control_ops reset_ops = {
+ .reset = mtmips_reset_device,
+ .assert = mtmips_assert_device,
+ .deassert = mtmips_deassert_device
+};
+
+static int mtmips_reset_init(struct device *dev, struct regmap *sysc)
+{
+ struct mtmips_rst *rst_data;
+
+ rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL);
+ if (!rst_data)
+ return -ENOMEM;
+
+ rst_data->sysc = sysc;
+ rst_data->rcdev.ops = &reset_ops;
+ rst_data->rcdev.owner = THIS_MODULE;
+ rst_data->rcdev.nr_resets = 32;
+ rst_data->rcdev.of_reset_n_cells = 1;
+ rst_data->rcdev.of_xlate = mtmips_rst_xlate;
+ rst_data->rcdev.of_node = dev_of_node(dev);
+
+ return devm_reset_controller_register(dev, &rst_data->rcdev);
+}
+
+static int mtmips_clk_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct mtmips_clk_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->sysc = syscon_node_to_regmap(np);
+ if (IS_ERR(priv->sysc))
+ return dev_err_probe(dev, PTR_ERR(priv->sysc),
+ "Could not get sysc syscon regmap\n");
+
+ ret = mtmips_reset_init(dev, priv->sysc);
+ if (ret)
+ return dev_err_probe(dev, ret, "Could not init reset controller\n");
+
+ return 0;
+}
+
+static const struct of_device_id mtmips_clk_of_match[] = {
+ { .compatible = "ralink,rt2880-reset" },
+ { .compatible = "ralink,rt2880-sysc" },
+ { .compatible = "ralink,rt3050-sysc" },
+ { .compatible = "ralink,rt3052-sysc" },
+ { .compatible = "ralink,rt3352-sysc" },
+ { .compatible = "ralink,rt3883-sysc" },
+ { .compatible = "ralink,rt5350-sysc" },
+ { .compatible = "ralink,mt7620-sysc" },
+ { .compatible = "ralink,mt7628-sysc" },
+ { .compatible = "ralink,mt7688-sysc" },
+ {}
+};
+
+static struct platform_driver mtmips_clk_driver = {
+ .probe = mtmips_clk_probe,
+ .driver = {
+ .name = "mtmips-clk",
+ .of_match_table = mtmips_clk_of_match,
+ },
+};
+
+static int __init mtmips_clk_reset_init(void)
+{
+ return platform_driver_register(&mtmips_clk_driver);
+}
+arch_initcall(mtmips_clk_reset_init);
diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c
index 90804ac06fa5..6280f4dfed71 100644
--- a/drivers/clk/renesas/clk-mstp.c
+++ b/drivers/clk/renesas/clk-mstp.c
@@ -14,6 +14,7 @@
#include <linux/clk/renesas.h>
#include <linux/device.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/pm_clock.h>
@@ -78,8 +79,8 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
struct mstp_clock_group *group = clock->group;
u32 bitmask = BIT(clock->bit_index);
unsigned long flags;
- unsigned int i;
u32 value;
+ int ret;
spin_lock_irqsave(&group->lock, flags);
@@ -101,19 +102,14 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
if (!enable || !group->mstpsr)
return 0;
- for (i = 1000; i > 0; --i) {
- if (!(cpg_mstp_read(group, group->mstpsr) & bitmask))
- break;
- cpu_relax();
- }
-
- if (!i) {
+ /* group->width_8bit is always false if group->mstpsr is present */
+ ret = readl_poll_timeout_atomic(group->mstpsr, value,
+ !(value & bitmask), 0, 10);
+ if (ret)
pr_err("%s: failed to enable %p[%d]\n", __func__,
group->smstpcr, clock->bit_index);
- return -ETIMEDOUT;
- }
- return 0;
+ return ret;
}
static int cpg_mstp_clock_enable(struct clk_hw *hw)
diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
index fcc8279647a6..4c2872f45387 100644
--- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
@@ -170,6 +170,7 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
DEF_MOD("msi3", 621, R8A779A0_CLK_MSO),
DEF_MOD("msi4", 622, R8A779A0_CLK_MSO),
DEF_MOD("msi5", 623, R8A779A0_CLK_MSO),
+ DEF_MOD("pwm0", 628, R8A779A0_CLK_S1D8),
DEF_MOD("rpc-if", 629, R8A779A0_CLK_RPCD2),
DEF_MOD("scif0", 702, R8A779A0_CLK_S1D8),
DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8),
diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c
index 40828616f723..55db63c7041a 100644
--- a/drivers/clk/renesas/r9a06g032-clocks.c
+++ b/drivers/clk/renesas/r9a06g032-clocks.c
@@ -1121,6 +1121,7 @@ static int r9a06g032_clk_mux_set_parent(struct clk_hw *hw, u8 index)
}
static const struct clk_ops clk_bitselect_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = r9a06g032_clk_mux_get_parent,
.set_parent = r9a06g032_clk_mux_set_parent,
};
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index e9c0e341380e..2772499d2016 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -17,6 +17,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_address.h>
@@ -196,8 +197,8 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
struct device *dev = priv->dev;
u32 bitmask = BIT(bit);
unsigned long flags;
- unsigned int i;
u32 value;
+ int error;
dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk,
enable ? "ON" : "OFF");
@@ -228,19 +229,13 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
if (!enable || priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
return 0;
- for (i = 1000; i > 0; --i) {
- if (!(readl(priv->base + priv->status_regs[reg]) & bitmask))
- break;
- cpu_relax();
- }
-
- if (!i) {
+ error = readl_poll_timeout_atomic(priv->base + priv->status_regs[reg],
+ value, !(value & bitmask), 0, 10);
+ if (error)
dev_err(dev, "Failed to enable SMSTP %p[%d]\n",
priv->base + priv->control_regs[reg], bit);
- return -ETIMEDOUT;
- }
- return 0;
+ return error;
}
static int cpg_mstp_clock_enable(struct clk_hw *hw)
@@ -896,8 +891,9 @@ static int cpg_mssr_suspend_noirq(struct device *dev)
static int cpg_mssr_resume_noirq(struct device *dev)
{
struct cpg_mssr_priv *priv = dev_get_drvdata(dev);
- unsigned int reg, i;
+ unsigned int reg;
u32 mask, oldval, newval;
+ int error;
/* This is the best we can do to check for the presence of PSCI */
if (!psci_ops.cpu_suspend)
@@ -935,14 +931,9 @@ static int cpg_mssr_resume_noirq(struct device *dev)
if (!mask)
continue;
- for (i = 1000; i > 0; --i) {
- oldval = readl(priv->base + priv->status_regs[reg]);
- if (!(oldval & mask))
- break;
- cpu_relax();
- }
-
- if (!i)
+ error = readl_poll_timeout_atomic(priv->base + priv->status_regs[reg],
+ oldval, !(oldval & mask), 0, 10);
+ if (error)
dev_warn(dev, "Failed to enable SMSTP%u[0x%x]\n", reg,
oldval & mask);
}
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index 93b02cdc98c2..bc623515ad84 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -603,10 +603,8 @@ static int rzg2l_cpg_sipll5_set_rate(struct clk_hw *hw,
}
/* Output clock setting 1 */
- writel(CPG_SIPLL5_CLK1_POSTDIV1_WEN | CPG_SIPLL5_CLK1_POSTDIV2_WEN |
- CPG_SIPLL5_CLK1_REFDIV_WEN | (params.pl5_postdiv1 << 0) |
- (params.pl5_postdiv2 << 4) | (params.pl5_refdiv << 8),
- priv->base + CPG_SIPLL5_CLK1);
+ writel((params.pl5_postdiv1 << 0) | (params.pl5_postdiv2 << 4) |
+ (params.pl5_refdiv << 8), priv->base + CPG_SIPLL5_CLK1);
/* Output clock setting, SSCG modulation value setting 3 */
writel((params.pl5_fracin << 8), priv->base + CPG_SIPLL5_CLK3);
@@ -905,9 +903,9 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable)
unsigned int reg = clock->off;
struct device *dev = priv->dev;
unsigned long flags;
- unsigned int i;
u32 bitmask = BIT(clock->bit);
u32 value;
+ int error;
if (!clock->off) {
dev_dbg(dev, "%pC does not support ON/OFF\n", hw->clk);
@@ -932,19 +930,13 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable)
if (!priv->info->has_clk_mon_regs)
return 0;
- for (i = 1000; i > 0; --i) {
- if (((readl(priv->base + CLK_MON_R(reg))) & bitmask))
- break;
- cpu_relax();
- }
-
- if (!i) {
+ error = readl_poll_timeout_atomic(priv->base + CLK_MON_R(reg), value,
+ value & bitmask, 0, 10);
+ if (error)
dev_err(dev, "Failed to enable CLK_ON %p\n",
priv->base + CLK_ON_R(reg));
- return -ETIMEDOUT;
- }
- return 0;
+ return error;
}
static int rzg2l_mod_clock_enable(struct clk_hw *hw)
diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
index eee780276a9e..6cee9e56acc7 100644
--- a/drivers/clk/renesas/rzg2l-cpg.h
+++ b/drivers/clk/renesas/rzg2l-cpg.h
@@ -32,9 +32,6 @@
#define CPG_SIPLL5_STBY_RESETB_WEN BIT(16)
#define CPG_SIPLL5_STBY_SSCG_EN_WEN BIT(18)
#define CPG_SIPLL5_STBY_DOWNSPREAD_WEN BIT(20)
-#define CPG_SIPLL5_CLK1_POSTDIV1_WEN BIT(16)
-#define CPG_SIPLL5_CLK1_POSTDIV2_WEN BIT(20)
-#define CPG_SIPLL5_CLK1_REFDIV_WEN BIT(24)
#define CPG_SIPLL5_CLK4_RESV_LSB (0xFF)
#define CPG_SIPLL5_MON_PLL5_LOCK BIT(4)
diff --git a/drivers/clk/samsung/Kconfig b/drivers/clk/samsung/Kconfig
index c07bb50513bf..76a494e95027 100644
--- a/drivers/clk/samsung/Kconfig
+++ b/drivers/clk/samsung/Kconfig
@@ -2,6 +2,7 @@
# Recent Exynos platforms should just select COMMON_CLK_SAMSUNG:
config COMMON_CLK_SAMSUNG
bool "Samsung Exynos clock controller support" if COMPILE_TEST
+ depends on OF
select S3C64XX_COMMON_CLK if ARM && ARCH_S3C64XX
select S5PV210_COMMON_CLK if ARM && ARCH_S5PV210
select EXYNOS_3250_COMMON_CLK if ARM && SOC_EXYNOS3250
diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c
index 0cff1c94c35e..72b6cf83aff4 100644
--- a/drivers/clk/samsung/clk-exynos-clkout.c
+++ b/drivers/clk/samsung/clk-exynos-clkout.c
@@ -56,6 +56,9 @@ static const struct of_device_id exynos_clkout_ids[] = {
.compatible = "samsung,exynos4210-pmu",
.data = &exynos_clkout_exynos4,
}, {
+ .compatible = "samsung,exynos4212-pmu",
+ .data = &exynos_clkout_exynos4,
+ }, {
.compatible = "samsung,exynos4412-pmu",
.data = &exynos_clkout_exynos4,
}, {
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index d7dbb3858347..43207257a9cc 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -138,7 +138,8 @@
/* the exynos4 soc type */
enum exynos4_soc {
EXYNOS4210,
- EXYNOS4X12,
+ EXYNOS4212,
+ EXYNOS4412,
};
/* list of PLLs to be registered */
@@ -1205,6 +1206,24 @@ static const struct exynos_cpuclk_cfg_data e4210_armclk_d[] __initconst = {
{ 0 },
};
+static const struct exynos_cpuclk_cfg_data e4212_armclk_d[] __initconst = {
+ { 1500000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4210_CPU_DIV1(2, 6), },
+ { 1400000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4210_CPU_DIV1(2, 6), },
+ { 1300000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4210_CPU_DIV1(2, 5), },
+ { 1200000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4210_CPU_DIV1(2, 5), },
+ { 1100000, E4210_CPU_DIV0(2, 1, 4, 0, 6, 3), E4210_CPU_DIV1(2, 4), },
+ { 1000000, E4210_CPU_DIV0(1, 1, 4, 0, 5, 2), E4210_CPU_DIV1(2, 4), },
+ { 900000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4210_CPU_DIV1(2, 3), },
+ { 800000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4210_CPU_DIV1(2, 3), },
+ { 700000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), },
+ { 600000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), },
+ { 500000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), },
+ { 400000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), },
+ { 300000, E4210_CPU_DIV0(1, 1, 2, 0, 4, 2), E4210_CPU_DIV1(2, 3), },
+ { 200000, E4210_CPU_DIV0(1, 1, 1, 0, 3, 1), E4210_CPU_DIV1(2, 3), },
+ { 0 },
+};
+
#define E4412_CPU_DIV1(cores, hpm, copy) \
(((cores) << 8) | ((hpm) << 4) | ((copy) << 0))
@@ -1233,6 +1252,11 @@ static const struct samsung_cpu_clock exynos4210_cpu_clks[] __initconst = {
CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1, 0x14200, e4210_armclk_d),
};
+static const struct samsung_cpu_clock exynos4212_cpu_clks[] __initconst = {
+ CPU_CLK(CLK_ARM_CLK, "armclk", CLK_MOUT_APLL, CLK_MOUT_MPLL_USER_C,
+ CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1, 0x14200, e4212_armclk_d),
+};
+
static const struct samsung_cpu_clock exynos4412_cpu_clks[] __initconst = {
CPU_CLK(CLK_ARM_CLK, "armclk", CLK_MOUT_APLL, CLK_MOUT_MPLL_USER_C,
CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1, 0x14200, e4412_armclk_d),
@@ -1326,11 +1350,15 @@ static void __init exynos4_clk_init(struct device_node *np,
samsung_clk_register_fixed_factor(ctx,
exynos4x12_fixed_factor_clks,
ARRAY_SIZE(exynos4x12_fixed_factor_clks));
- samsung_clk_register_cpu(ctx, exynos4412_cpu_clks,
- ARRAY_SIZE(exynos4412_cpu_clks));
+ if (soc == EXYNOS4412)
+ samsung_clk_register_cpu(ctx, exynos4412_cpu_clks,
+ ARRAY_SIZE(exynos4412_cpu_clks));
+ else
+ samsung_clk_register_cpu(ctx, exynos4212_cpu_clks,
+ ARRAY_SIZE(exynos4212_cpu_clks));
}
- if (soc == EXYNOS4X12)
+ if (soc == EXYNOS4212 || soc == EXYNOS4412)
exynos4x12_core_down_clock();
samsung_clk_extended_sleep_init(reg_base,
@@ -1363,8 +1391,14 @@ static void __init exynos4210_clk_init(struct device_node *np)
}
CLK_OF_DECLARE(exynos4210_clk, "samsung,exynos4210-clock", exynos4210_clk_init);
+static void __init exynos4212_clk_init(struct device_node *np)
+{
+ exynos4_clk_init(np, EXYNOS4212);
+}
+CLK_OF_DECLARE(exynos4212_clk, "samsung,exynos4212-clock", exynos4212_clk_init);
+
static void __init exynos4412_clk_init(struct device_node *np)
{
- exynos4_clk_init(np, EXYNOS4X12);
+ exynos4_clk_init(np, EXYNOS4412);
}
CLK_OF_DECLARE(exynos4412_clk, "samsung,exynos4412-clock", exynos4412_clk_init);
diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c
index 916d2fc28b9c..e317f3454e93 100644
--- a/drivers/clk/sifive/sifive-prci.c
+++ b/drivers/clk/sifive/sifive-prci.c
@@ -567,7 +567,6 @@ static int __prci_register_clocks(struct device *dev, struct __prci_data *pd,
static int sifive_prci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct resource *res;
struct __prci_data *pd;
const struct prci_clk_desc *desc;
int r;
@@ -578,8 +577,7 @@ static int sifive_prci_probe(struct platform_device *pdev)
if (!pd)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- pd->va = devm_ioremap_resource(dev, res);
+ pd->va = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pd->va))
return PTR_ERR(pd->va);
diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c
index 32ccda960f28..8dd601bd8538 100644
--- a/drivers/clk/socfpga/clk-gate.c
+++ b/drivers/clk/socfpga/clk-gate.c
@@ -110,6 +110,7 @@ static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk,
static struct clk_ops gateclk_ops = {
.recalc_rate = socfpga_clk_recalc_rate,
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = socfpga_clk_get_parent,
.set_parent = socfpga_clk_set_parent,
};
diff --git a/drivers/clk/sprd/composite.c b/drivers/clk/sprd/composite.c
index ebb644820b1e..ad6b6383e21f 100644
--- a/drivers/clk/sprd/composite.c
+++ b/drivers/clk/sprd/composite.c
@@ -9,13 +9,12 @@
#include "composite.h"
-static long sprd_comp_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int sprd_comp_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct sprd_comp *cc = hw_to_sprd_comp(hw);
- return sprd_div_helper_round_rate(&cc->common, &cc->div,
- rate, parent_rate);
+ return divider_determine_rate(hw, req, NULL, cc->div.width, 0);
}
static unsigned long sprd_comp_recalc_rate(struct clk_hw *hw,
@@ -53,7 +52,7 @@ const struct clk_ops sprd_comp_ops = {
.get_parent = sprd_comp_get_parent,
.set_parent = sprd_comp_set_parent,
- .round_rate = sprd_comp_round_rate,
+ .determine_rate = sprd_comp_determine_rate,
.recalc_rate = sprd_comp_recalc_rate,
.set_rate = sprd_comp_set_rate,
};
diff --git a/drivers/clk/sprd/div.c b/drivers/clk/sprd/div.c
index 7621a1d1ab9c..c7261630cab4 100644
--- a/drivers/clk/sprd/div.c
+++ b/drivers/clk/sprd/div.c
@@ -9,23 +9,13 @@
#include "div.h"
-long sprd_div_helper_round_rate(struct sprd_clk_common *common,
- const struct sprd_div_internal *div,
- unsigned long rate,
- unsigned long *parent_rate)
-{
- return divider_round_rate(&common->hw, rate, parent_rate,
- NULL, div->width, 0);
-}
-EXPORT_SYMBOL_GPL(sprd_div_helper_round_rate);
-
static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct sprd_div *cd = hw_to_sprd_div(hw);
- return sprd_div_helper_round_rate(&cd->common, &cd->div,
- rate, parent_rate);
+ return divider_round_rate(&cd->common.hw, rate, parent_rate, NULL,
+ cd->div.width, 0);
}
unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
diff --git a/drivers/clk/sprd/div.h b/drivers/clk/sprd/div.h
index 6acfe6b179fc..f5d614b3dcf1 100644
--- a/drivers/clk/sprd/div.h
+++ b/drivers/clk/sprd/div.h
@@ -64,11 +64,6 @@ static inline struct sprd_div *hw_to_sprd_div(const struct clk_hw *hw)
return container_of(common, struct sprd_div, common);
}
-long sprd_div_helper_round_rate(struct sprd_clk_common *common,
- const struct sprd_div_internal *div,
- unsigned long rate,
- unsigned long *parent_rate);
-
unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
const struct sprd_div_internal *div,
unsigned long parent_rate);
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index 7ae4f656191e..5292208c4dd8 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -119,20 +119,21 @@ clk_best_div(unsigned long parent_rate, unsigned long rate)
return parent_rate / rate + ((rate > (2*(parent_rate % rate))) ? 0 : 1);
}
-static long flexgen_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+static int flexgen_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
unsigned long div;
/* Round div according to exact prate and wished rate */
- div = clk_best_div(*prate, rate);
+ div = clk_best_div(req->best_parent_rate, req->rate);
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
- *prate = rate * div;
- return rate;
+ req->best_parent_rate = req->rate * div;
+ return 0;
}
- return *prate / div;
+ req->rate = req->best_parent_rate / div;
+ return 0;
}
static unsigned long flexgen_recalc_rate(struct clk_hw *hw,
@@ -197,7 +198,7 @@ static const struct clk_ops flexgen_ops = {
.is_enabled = flexgen_is_enabled,
.get_parent = flexgen_get_parent,
.set_parent = flexgen_set_parent,
- .round_rate = flexgen_round_rate,
+ .determine_rate = flexgen_determine_rate,
.recalc_rate = flexgen_recalc_rate,
.set_rate = flexgen_set_rate,
};
diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c
index 45a279e73779..d5aa09e9fce4 100644
--- a/drivers/clk/stm32/clk-stm32-core.c
+++ b/drivers/clk/stm32/clk-stm32-core.c
@@ -275,6 +275,7 @@ static int clk_stm32_mux_set_parent(struct clk_hw *hw, u8 index)
}
const struct clk_ops clk_stm32_mux_ops = {
+ .determine_rate = __clk_mux_determine_rate,
.get_parent = clk_stm32_mux_get_parent,
.set_parent = clk_stm32_mux_set_parent,
};
@@ -425,15 +426,15 @@ static unsigned long clk_stm32_composite_recalc_rate(struct clk_hw *hw,
composite->div_id, parent_rate);
}
-static long clk_stm32_composite_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+static int clk_stm32_composite_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
-
const struct stm32_div_cfg *divider;
+ unsigned long rate;
if (composite->div_id == NO_STM32_DIV)
- return rate;
+ return 0;
divider = &composite->clock_data->dividers[composite->div_id];
@@ -444,14 +445,24 @@ static long clk_stm32_composite_round_rate(struct clk_hw *hw, unsigned long rate
val = readl(composite->base + divider->offset) >> divider->shift;
val &= clk_div_mask(divider->width);
- return divider_ro_round_rate(hw, rate, prate, divider->table,
- divider->width, divider->flags,
- val);
+ rate = divider_ro_round_rate(hw, req->rate, &req->best_parent_rate,
+ divider->table, divider->width, divider->flags,
+ val);
+ if (rate < 0)
+ return rate;
+
+ req->rate = rate;
+ return 0;
}
- return divider_round_rate_parent(hw, clk_hw_get_parent(hw),
- rate, prate, divider->table,
- divider->width, divider->flags);
+ rate = divider_round_rate_parent(hw, clk_hw_get_parent(hw),
+ req->rate, &req->best_parent_rate,
+ divider->table, divider->width, divider->flags);
+ if (rate < 0)
+ return rate;
+
+ req->rate = rate;
+ return 0;
}
static u8 clk_stm32_composite_get_parent(struct clk_hw *hw)
@@ -601,7 +612,7 @@ static void clk_stm32_composite_disable_unused(struct clk_hw *hw)
const struct clk_ops clk_stm32_composite_ops = {
.set_rate = clk_stm32_composite_set_rate,
.recalc_rate = clk_stm32_composite_recalc_rate,
- .round_rate = clk_stm32_composite_round_rate,
+ .determine_rate = clk_stm32_composite_determine_rate,
.get_parent = clk_stm32_composite_get_parent,
.set_parent = clk_stm32_composite_set_parent,
.enable = clk_stm32_composite_gate_enable,
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 41519185600a..eb36f8f77d55 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -528,11 +528,18 @@ static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
0x104, 0, 4, 24, 3, BIT(31),
CLK_SET_RATE_PARENT);
+/*
+ * DSI output seems to work only when PLL_MIPI selected. Set it and prevent
+ * the mux from reparenting.
+ */
+#define SUN50I_A64_TCON0_CLK_REG 0x118
+
static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
static const u8 tcon0_table[] = { 0, 2, };
static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,
tcon0_table, 0x118, 24, 3, BIT(31),
- CLK_SET_RATE_PARENT);
+ CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT);
static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" };
static const u8 tcon1_table[] = { 0, 2, };
@@ -953,6 +960,11 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev)
writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
+ /* Set PLL MIPI as parent for TCON0 */
+ val = readl(reg + SUN50I_A64_TCON0_CLK_REG);
+ val &= ~GENMASK(26, 24);
+ writel(val | (0 << 24), reg + SUN50I_A64_TCON0_CLK_REG);
+
ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a64_ccu_desc);
if (ret)
return ret;
diff --git a/drivers/clk/tegra/clk-bpmp.c b/drivers/clk/tegra/clk-bpmp.c
index 0ecdffaa6b16..a9f3fb448de6 100644
--- a/drivers/clk/tegra/clk-bpmp.c
+++ b/drivers/clk/tegra/clk-bpmp.c
@@ -286,6 +286,7 @@ static const struct clk_ops tegra_bpmp_clk_mux_ops = {
.unprepare = tegra_bpmp_clk_unprepare,
.is_prepared = tegra_bpmp_clk_is_prepared,
.recalc_rate = tegra_bpmp_clk_recalc_rate,
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = tegra_bpmp_clk_set_parent,
.get_parent = tegra_bpmp_clk_get_parent,
};
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index 79ca3aa072b7..0626650a7011 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -45,16 +45,22 @@ static unsigned long clk_periph_recalc_rate(struct clk_hw *hw,
return div_ops->recalc_rate(div_hw, parent_rate);
}
-static long clk_periph_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+static int clk_periph_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct tegra_clk_periph *periph = to_clk_periph(hw);
const struct clk_ops *div_ops = periph->div_ops;
struct clk_hw *div_hw = &periph->divider.hw;
+ unsigned long rate;
__clk_hw_set_clk(div_hw, hw);
- return div_ops->round_rate(div_hw, rate, prate);
+ rate = div_ops->round_rate(div_hw, req->rate, &req->best_parent_rate);
+ if (rate < 0)
+ return rate;
+
+ req->rate = rate;
+ return 0;
}
static int clk_periph_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -130,7 +136,7 @@ const struct clk_ops tegra_clk_periph_ops = {
.get_parent = clk_periph_get_parent,
.set_parent = clk_periph_set_parent,
.recalc_rate = clk_periph_recalc_rate,
- .round_rate = clk_periph_round_rate,
+ .determine_rate = clk_periph_determine_rate,
.set_rate = clk_periph_set_rate,
.is_enabled = clk_periph_is_enabled,
.enable = clk_periph_enable,
@@ -140,6 +146,7 @@ const struct clk_ops tegra_clk_periph_ops = {
};
static const struct clk_ops tegra_clk_periph_nodiv_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = clk_periph_get_parent,
.set_parent = clk_periph_set_parent,
.is_enabled = clk_periph_is_enabled,
@@ -153,7 +160,7 @@ static const struct clk_ops tegra_clk_periph_no_gate_ops = {
.get_parent = clk_periph_get_parent,
.set_parent = clk_periph_set_parent,
.recalc_rate = clk_periph_recalc_rate,
- .round_rate = clk_periph_round_rate,
+ .determine_rate = clk_periph_determine_rate,
.set_rate = clk_periph_set_rate,
.restore_context = clk_periph_restore_context,
};
diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c
index a98a420398fa..7ec47942720c 100644
--- a/drivers/clk/tegra/clk-super.c
+++ b/drivers/clk/tegra/clk-super.c
@@ -136,20 +136,28 @@ static void clk_super_mux_restore_context(struct clk_hw *hw)
}
static const struct clk_ops tegra_clk_super_mux_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = clk_super_get_parent,
.set_parent = clk_super_set_parent,
.restore_context = clk_super_mux_restore_context,
};
-static long clk_super_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int clk_super_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
struct clk_hw *div_hw = &super->frac_div.hw;
+ unsigned long rate;
__clk_hw_set_clk(div_hw, hw);
- return super->div_ops->round_rate(div_hw, rate, parent_rate);
+ rate = super->div_ops->round_rate(div_hw, req->rate,
+ &req->best_parent_rate);
+ if (rate < 0)
+ return rate;
+
+ req->rate = rate;
+ return 0;
}
static unsigned long clk_super_recalc_rate(struct clk_hw *hw,
@@ -192,7 +200,7 @@ const struct clk_ops tegra_clk_super_ops = {
.get_parent = clk_super_get_parent,
.set_parent = clk_super_set_parent,
.set_rate = clk_super_set_rate,
- .round_rate = clk_super_round_rate,
+ .determine_rate = clk_super_determine_rate,
.recalc_rate = clk_super_recalc_rate,
.restore_context = clk_super_restore_context,
};
diff --git a/drivers/clk/tegra/clk-tegra-super-cclk.c b/drivers/clk/tegra/clk-tegra-super-cclk.c
index 68d7bcd5fc8a..3b22a4d0dffc 100644
--- a/drivers/clk/tegra/clk-tegra-super-cclk.c
+++ b/drivers/clk/tegra/clk-tegra-super-cclk.c
@@ -86,9 +86,18 @@ static int cclk_super_determine_rate(struct clk_hw *hw,
if (rate <= pllp_rate) {
if (super->flags & TEGRA20_SUPER_CLK)
rate = pllp_rate;
- else
- rate = tegra_clk_super_ops.round_rate(hw, rate,
- &pllp_rate);
+ else {
+ struct clk_rate_request parent = {
+ .rate = req->rate,
+ .best_parent_rate = pllp_rate,
+ };
+
+ clk_hw_get_rate_range(hw, &parent.min_rate,
+ &parent.max_rate);
+ tegra_clk_super_ops.determine_rate(hw, &parent);
+ pllp_rate = parent.best_parent_rate;
+ rate = parent.rate;
+ }
req->best_parent_rate = pllp_rate;
req->best_parent_hw = pllp_hw;
diff --git a/drivers/clk/tegra/clk-tegra124-emc.c b/drivers/clk/tegra/clk-tegra124-emc.c
index 219c80653dbd..2a6db0434281 100644
--- a/drivers/clk/tegra/clk-tegra124-emc.c
+++ b/drivers/clk/tegra/clk-tegra124-emc.c
@@ -464,6 +464,7 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra,
err = load_one_timing_from_dt(tegra, timing, child);
if (err) {
of_node_put(child);
+ kfree(tegra->timings);
return err;
}
@@ -515,6 +516,7 @@ struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np
err = load_timings_from_dt(tegra, node, node_ram_code);
if (err) {
of_node_put(node);
+ kfree(tegra);
return ERR_PTR(err);
}
}
diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c
index b6fce916967c..8c40f10280b7 100644
--- a/drivers/clk/ti/clkctrl.c
+++ b/drivers/clk/ti/clkctrl.c
@@ -258,6 +258,9 @@ static const char * __init clkctrl_get_clock_name(struct device_node *np,
if (clkctrl_name && !legacy_naming) {
clock_name = kasprintf(GFP_KERNEL, "%s-clkctrl:%04x:%d",
clkctrl_name, offset, index);
+ if (!clock_name)
+ return NULL;
+
strreplace(clock_name, '_', '-');
return clock_name;
@@ -586,6 +589,10 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
if (clkctrl_name) {
provider->clkdm_name = kasprintf(GFP_KERNEL,
"%s_clkdm", clkctrl_name);
+ if (!provider->clkdm_name) {
+ kfree(provider);
+ return;
+ }
goto clkdm_found;
}
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
index 4deb37f19a7c..5cbf24c94606 100644
--- a/drivers/clk/ux500/clk-prcmu.c
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -344,6 +344,7 @@ static const struct clk_ops clk_prcmu_clkout_ops = {
.prepare = clk_prcmu_clkout_prepare,
.unprepare = clk_prcmu_clkout_unprepare,
.recalc_rate = clk_prcmu_clkout_recalc_rate,
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = clk_prcmu_clkout_get_parent,
.set_parent = clk_prcmu_clkout_set_parent,
};
diff --git a/drivers/clk/ux500/clk-sysctrl.c b/drivers/clk/ux500/clk-sysctrl.c
index 702f2f8b43fa..ba3258c88d28 100644
--- a/drivers/clk/ux500/clk-sysctrl.c
+++ b/drivers/clk/ux500/clk-sysctrl.c
@@ -110,6 +110,7 @@ static const struct clk_ops clk_sysctrl_gate_fixed_rate_ops = {
};
static const struct clk_ops clk_sysctrl_set_parent_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = clk_sysctrl_set_parent,
.get_parent = clk_sysctrl_get_parent,
};
diff --git a/drivers/clk/versatile/clk-sp810.c b/drivers/clk/versatile/clk-sp810.c
index caf0cd2fb5b6..45adac1b4630 100644
--- a/drivers/clk/versatile/clk-sp810.c
+++ b/drivers/clk/versatile/clk-sp810.c
@@ -63,6 +63,7 @@ static int clk_sp810_timerclken_set_parent(struct clk_hw *hw, u8 index)
}
static const struct clk_ops clk_sp810_timerclken_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = clk_sp810_timerclken_get_parent,
.set_parent = clk_sp810_timerclken_set_parent,
};
diff --git a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c
index e83f104fad02..d56822ce6126 100644
--- a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c
+++ b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c
@@ -525,7 +525,7 @@ static struct clk *clk_wzrd_register_divider(struct device *dev,
hw = &div->hw;
ret = devm_clk_hw_register(dev, hw);
if (ret)
- hw = ERR_PTR(ret);
+ return ERR_PTR(ret);
return hw->clk;
}
@@ -648,6 +648,11 @@ static int clk_wzrd_probe(struct platform_device *pdev)
}
clkout_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_out0", dev_name(&pdev->dev));
+ if (!clkout_name) {
+ ret = -ENOMEM;
+ goto err_disable_clk;
+ }
+
if (nr_outputs == 1) {
clk_wzrd->clkout[0] = clk_wzrd_register_divider
(&pdev->dev, clkout_name,
diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
index 5f0f10c7e222..da3071b387eb 100644
--- a/drivers/clocksource/timer-riscv.c
+++ b/drivers/clocksource/timer-riscv.c
@@ -10,6 +10,7 @@
#define pr_fmt(fmt) "riscv-timer: " fmt
+#include <linux/acpi.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/cpu.h>
@@ -124,61 +125,28 @@ static irqreturn_t riscv_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __init riscv_timer_init_dt(struct device_node *n)
+static int __init riscv_timer_init_common(void)
{
- int cpuid, error;
- unsigned long hartid;
- struct device_node *child;
+ int error;
struct irq_domain *domain;
+ struct fwnode_handle *intc_fwnode = riscv_get_intc_hwnode();
- error = riscv_of_processor_hartid(n, &hartid);
- if (error < 0) {
- pr_warn("Not valid hartid for node [%pOF] error = [%lu]\n",
- n, hartid);
- return error;
- }
-
- cpuid = riscv_hartid_to_cpuid(hartid);
- if (cpuid < 0) {
- pr_warn("Invalid cpuid for hartid [%lu]\n", hartid);
- return cpuid;
- }
-
- if (cpuid != smp_processor_id())
- return 0;
-
- child = of_find_compatible_node(NULL, NULL, "riscv,timer");
- if (child) {
- riscv_timer_cannot_wake_cpu = of_property_read_bool(child,
- "riscv,timer-cannot-wake-cpu");
- of_node_put(child);
- }
-
- domain = NULL;
- child = of_get_compatible_child(n, "riscv,cpu-intc");
- if (!child) {
- pr_err("Failed to find INTC node [%pOF]\n", n);
- return -ENODEV;
- }
- domain = irq_find_host(child);
- of_node_put(child);
+ domain = irq_find_matching_fwnode(intc_fwnode, DOMAIN_BUS_ANY);
if (!domain) {
- pr_err("Failed to find IRQ domain for node [%pOF]\n", n);
+ pr_err("Failed to find irq_domain for INTC node [%pfwP]\n",
+ intc_fwnode);
return -ENODEV;
}
riscv_clock_event_irq = irq_create_mapping(domain, RV_IRQ_TIMER);
if (!riscv_clock_event_irq) {
- pr_err("Failed to map timer interrupt for node [%pOF]\n", n);
+ pr_err("Failed to map timer interrupt for node [%pfwP]\n", intc_fwnode);
return -ENODEV;
}
- pr_info("%s: Registering clocksource cpuid [%d] hartid [%lu]\n",
- __func__, cpuid, hartid);
error = clocksource_register_hz(&riscv_clocksource, riscv_timebase);
if (error) {
- pr_err("RISCV timer register failed [%d] for cpu = [%d]\n",
- error, cpuid);
+ pr_err("RISCV timer registration failed [%d]\n", error);
return error;
}
@@ -207,4 +175,46 @@ static int __init riscv_timer_init_dt(struct device_node *n)
return error;
}
+static int __init riscv_timer_init_dt(struct device_node *n)
+{
+ int cpuid, error;
+ unsigned long hartid;
+ struct device_node *child;
+
+ error = riscv_of_processor_hartid(n, &hartid);
+ if (error < 0) {
+ pr_warn("Invalid hartid for node [%pOF] error = [%lu]\n",
+ n, hartid);
+ return error;
+ }
+
+ cpuid = riscv_hartid_to_cpuid(hartid);
+ if (cpuid < 0) {
+ pr_warn("Invalid cpuid for hartid [%lu]\n", hartid);
+ return cpuid;
+ }
+
+ if (cpuid != smp_processor_id())
+ return 0;
+
+ child = of_find_compatible_node(NULL, NULL, "riscv,timer");
+ if (child) {
+ riscv_timer_cannot_wake_cpu = of_property_read_bool(child,
+ "riscv,timer-cannot-wake-cpu");
+ of_node_put(child);
+ }
+
+ return riscv_timer_init_common();
+}
+
TIMER_OF_DECLARE(riscv_timer, "riscv", riscv_timer_init_dt);
+
+#ifdef CONFIG_ACPI
+static int __init riscv_timer_acpi_init(struct acpi_table_header *table)
+{
+ return riscv_timer_init_common();
+}
+
+TIMER_ACPI_DECLARE(aclint_mtimer, ACPI_SIG_RHCT, riscv_timer_acpi_init);
+
+#endif
diff --git a/drivers/comedi/Kconfig b/drivers/comedi/Kconfig
index 9af280735cba..7a8d402f05be 100644
--- a/drivers/comedi/Kconfig
+++ b/drivers/comedi/Kconfig
@@ -67,6 +67,7 @@ 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
@@ -79,6 +80,7 @@ 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
@@ -89,6 +91,7 @@ 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
@@ -100,7 +103,8 @@ if COMEDI_ISA_DRIVERS
config COMEDI_PCL711
tristate "Advantech PCL-711/711b and ADlink ACL-8112 ISA card support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
help
Enable support for Advantech PCL-711 and 711b, ADlink ACL-8112
@@ -161,8 +165,9 @@ 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
- select COMEDI_8254
+ depends on 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,
@@ -173,8 +178,9 @@ 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
- select COMEDI_8254
+ depends on COMEDI_8254
help
Enable support for Advantech PCL-814 and PCL-816 ISA cards
@@ -183,8 +189,9 @@ 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
- select COMEDI_8254
+ depends on COMEDI_8254
help
Enable support for Advantech PCL-818 ISA cards
PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818 and PCL-718
@@ -203,7 +210,7 @@ config COMEDI_PCM3724
config COMEDI_AMPLC_DIO200_ISA
tristate "Amplicon PC212E/PC214E/PC215E/PC218E/PC272E"
- select COMEDI_AMPLC_DIO200
+ depends on COMEDI_AMPLC_DIO200
help
Enable support for Amplicon PC212E, PC214E, PC215E, PC218E and
PC272E ISA DIO boards
@@ -255,7 +262,8 @@ config COMEDI_DAC02
config COMEDI_DAS16M1
tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
select COMEDI_8255
help
Enable support for Measurement Computing CIO-DAS16/M1 ISA cards.
@@ -265,7 +273,7 @@ config COMEDI_DAS16M1
config COMEDI_DAS08_ISA
tristate "DAS-08 compatible ISA and PC/104 card support"
- select COMEDI_DAS08
+ depends on COMEDI_DAS08
help
Enable support for Keithley Metrabyte/ComputerBoards DAS08
and compatible ISA and PC/104 cards:
@@ -278,8 +286,9 @@ 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
- select COMEDI_8254
+ depends on COMEDI_8254
select COMEDI_8255
help
Enable support for Keithley Metrabyte/ComputerBoards DAS16
@@ -296,7 +305,8 @@ config COMEDI_DAS16
config COMEDI_DAS800
tristate "DAS800 and compatible ISA card support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
help
Enable support for Keithley Metrabyte DAS800 and compatible ISA cards
Keithley Metrabyte DAS-800, DAS-801, DAS-802
@@ -308,8 +318,9 @@ config COMEDI_DAS800
config COMEDI_DAS1800
tristate "DAS1800 and compatible ISA card support"
+ depends on HAS_IOPORT
select COMEDI_ISADMA if ISA_DMA_API
- select COMEDI_8254
+ depends on COMEDI_8254
help
Enable support for DAS1800 and compatible ISA cards
Keithley Metrabyte DAS-1701ST, DAS-1701ST-DA, DAS-1701/AO,
@@ -323,7 +334,8 @@ config COMEDI_DAS1800
config COMEDI_DAS6402
tristate "DAS6402 and compatible ISA card support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
help
Enable support for DAS6402 and compatible ISA cards
Computerboards, Keithley Metrabyte DAS6402 and compatibles
@@ -402,7 +414,8 @@ config COMEDI_FL512
config COMEDI_AIO_AIO12_8
tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
select COMEDI_8255
help
Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board
@@ -456,8 +469,9 @@ 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
- select COMEDI_8254
+ depends on COMEDI_8254
help
Enable support for National Instruments AT-A2150 cards
@@ -466,7 +480,8 @@ config COMEDI_NI_AT_A2150
config COMEDI_NI_AT_AO
tristate "NI AT-AO-6/10 EISA card support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
help
Enable support for National Instruments AT-AO-6/10 cards
@@ -497,7 +512,7 @@ config COMEDI_NI_ATMIO16D
config COMEDI_NI_LABPC_ISA
tristate "NI Lab-PC and compatibles ISA support"
- select COMEDI_NI_LABPC
+ depends on COMEDI_NI_LABPC
help
Enable support for National Instruments Lab-PC and compatibles
Lab-PC-1200, Lab-PC-1200AI, Lab-PC+.
@@ -561,7 +576,7 @@ endif # COMEDI_ISA_DRIVERS
menuconfig COMEDI_PCI_DRIVERS
tristate "Comedi PCI drivers"
- depends on PCI
+ depends on PCI && HAS_IOPORT
help
Enable support for comedi PCI drivers.
@@ -710,7 +725,8 @@ config COMEDI_ADL_PCI8164
config COMEDI_ADL_PCI9111
tristate "ADLink PCI-9111HR support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
help
Enable support for ADlink PCI9111 cards
@@ -720,7 +736,7 @@ config COMEDI_ADL_PCI9111
config COMEDI_ADL_PCI9118
tristate "ADLink PCI-9118DG, PCI-9118HG, PCI-9118HR support"
depends on HAS_DMA
- select COMEDI_8254
+ depends on COMEDI_8254
help
Enable support for ADlink PCI-9118DG, PCI-9118HG, PCI-9118HR cards
@@ -729,7 +745,8 @@ config COMEDI_ADL_PCI9118
config COMEDI_ADV_PCI1710
tristate "Advantech PCI-171x and PCI-1731 support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
help
Enable support for Advantech PCI-1710, PCI-1710HG, PCI-1711,
PCI-1713 and PCI-1731
@@ -773,7 +790,8 @@ config COMEDI_ADV_PCI1760
config COMEDI_ADV_PCI_DIO
tristate "Advantech PCI DIO card support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
select COMEDI_8255
help
Enable support for Advantech PCI DIO cards
@@ -786,7 +804,7 @@ config COMEDI_ADV_PCI_DIO
config COMEDI_AMPLC_DIO200_PCI
tristate "Amplicon PCI215/PCI272/PCIe215/PCIe236/PCIe296 DIO support"
- select COMEDI_AMPLC_DIO200
+ depends on COMEDI_AMPLC_DIO200
help
Enable support for Amplicon PCI215, PCI272, PCIe215, PCIe236
and PCIe296 DIO boards.
@@ -814,7 +832,8 @@ config COMEDI_AMPLC_PC263_PCI
config COMEDI_AMPLC_PCI224
tristate "Amplicon PCI224 and PCI234 support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
help
Enable support for Amplicon PCI224 and PCI234 AO boards
@@ -823,7 +842,8 @@ config COMEDI_AMPLC_PCI224
config COMEDI_AMPLC_PCI230
tristate "Amplicon PCI230 and PCI260 support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
select COMEDI_8255
help
Enable support for Amplicon PCI230 and PCI260 Multifunction I/O
@@ -842,7 +862,7 @@ config COMEDI_CONTEC_PCI_DIO
config COMEDI_DAS08_PCI
tristate "DAS-08 PCI support"
- select COMEDI_DAS08
+ depends on COMEDI_DAS08
help
Enable support for PCI DAS-08 cards.
@@ -929,7 +949,8 @@ config COMEDI_CB_PCIDAS64
config COMEDI_CB_PCIDAS
tristate "MeasurementComputing PCI-DAS support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
select COMEDI_8255
help
Enable support for ComputerBoards/MeasurementComputing PCI-DAS with
@@ -953,7 +974,8 @@ config COMEDI_CB_PCIDDA
config COMEDI_CB_PCIMDAS
tristate "MeasurementComputing PCIM-DAS1602/16, PCIe-DAS1602/16 support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
select COMEDI_8255
help
Enable support for ComputerBoards/MeasurementComputing PCI Migration
@@ -973,7 +995,8 @@ config COMEDI_CB_PCIMDDA
config COMEDI_ME4000
tristate "Meilhaus ME-4000 support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
help
Enable support for Meilhaus PCI data acquisition cards
ME-4650, ME-4670i, ME-4680, ME-4680i and ME-4680is
@@ -1031,7 +1054,7 @@ config COMEDI_NI_670X
config COMEDI_NI_LABPC_PCI
tristate "NI Lab-PC PCI-1200 support"
- select COMEDI_NI_LABPC
+ depends on COMEDI_NI_LABPC
help
Enable support for National Instruments Lab-PC PCI-1200.
@@ -1053,6 +1076,7 @@ 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
@@ -1074,7 +1098,8 @@ config COMEDI_NI_PCIMIO
config COMEDI_RTD520
tristate "Real Time Devices PCI4520/DM7520 support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
help
Enable support for Real Time Devices PCI4520/DM7520
@@ -1114,7 +1139,8 @@ if COMEDI_PCMCIA_DRIVERS
config COMEDI_CB_DAS16_CS
tristate "CB DAS16 series PCMCIA support"
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
help
Enable support for the ComputerBoards/MeasurementComputing PCMCIA
cards DAS16/16, PCM-DAS16D/12 and PCM-DAS16s/16
@@ -1124,7 +1150,7 @@ config COMEDI_CB_DAS16_CS
config COMEDI_DAS08_CS
tristate "CB DAS08 PCMCIA support"
- select COMEDI_DAS08
+ depends on COMEDI_DAS08
help
Enable support for the ComputerBoards/MeasurementComputing DAS-08
PCMCIA card
@@ -1134,6 +1160,7 @@ 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
@@ -1142,6 +1169,7 @@ 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
@@ -1151,7 +1179,7 @@ config COMEDI_NI_DAQ_DIO24_CS
config COMEDI_NI_LABPC_CS
tristate "NI DAQCard-1200 PCMCIA support"
- select COMEDI_NI_LABPC
+ depends on COMEDI_NI_LABPC
help
Enable support for the National Instruments PCMCIA DAQCard-1200
@@ -1160,6 +1188,7 @@ 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
@@ -1172,6 +1201,7 @@ 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
@@ -1248,12 +1278,14 @@ 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.
@@ -1285,7 +1317,7 @@ config COMEDI_KCOMEDILIB
called kcomedilib.
config COMEDI_AMPLC_DIO200
- select COMEDI_8254
+ depends on COMEDI_8254
tristate
config COMEDI_AMPLC_PC236
@@ -1294,7 +1326,7 @@ config COMEDI_AMPLC_PC236
config COMEDI_DAS08
tristate
- select COMEDI_8254
+ depends on COMEDI_8254
select COMEDI_8255
config COMEDI_ISADMA
@@ -1302,7 +1334,8 @@ config COMEDI_ISADMA
config COMEDI_NI_LABPC
tristate
- select COMEDI_8254
+ depends on HAS_IOPORT
+ depends on COMEDI_8254
select COMEDI_8255
config COMEDI_NI_LABPC_ISADMA
diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
index 8e43918d38c4..1548dea15df1 100644
--- a/drivers/comedi/comedi_fops.c
+++ b/drivers/comedi/comedi_fops.c
@@ -97,7 +97,6 @@ static DEFINE_MUTEX(comedi_subdevice_minor_table_lock);
static struct comedi_subdevice
*comedi_subdevice_minor_table[COMEDI_NUM_SUBDEVICE_MINORS];
-static struct class *comedi_class;
static struct cdev comedi_cdev;
static void comedi_device_init(struct comedi_device *dev)
@@ -187,18 +186,6 @@ static struct comedi_device *comedi_clear_board_minor(unsigned int minor)
return dev;
}
-static void comedi_free_board_dev(struct comedi_device *dev)
-{
- if (dev) {
- comedi_device_cleanup(dev);
- if (dev->class_dev) {
- device_destroy(comedi_class,
- MKDEV(COMEDI_MAJOR, dev->minor));
- }
- comedi_dev_put(dev);
- }
-}
-
static struct comedi_subdevice *
comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned int minor)
{
@@ -611,6 +598,23 @@ static struct attribute *comedi_dev_attrs[] = {
};
ATTRIBUTE_GROUPS(comedi_dev);
+static const struct class comedi_class = {
+ .name = "comedi",
+ .dev_groups = comedi_dev_groups,
+};
+
+static void comedi_free_board_dev(struct comedi_device *dev)
+{
+ if (dev) {
+ comedi_device_cleanup(dev);
+ if (dev->class_dev) {
+ device_destroy(&comedi_class,
+ MKDEV(COMEDI_MAJOR, dev->minor));
+ }
+ comedi_dev_put(dev);
+ }
+}
+
static void __comedi_clear_subdevice_runflags(struct comedi_subdevice *s,
unsigned int bits)
{
@@ -3263,7 +3267,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
return ERR_PTR(-EBUSY);
}
dev->minor = i;
- csdev = device_create(comedi_class, hardware_device,
+ csdev = device_create(&comedi_class, hardware_device,
MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
if (!IS_ERR(csdev))
dev->class_dev = get_device(csdev);
@@ -3312,7 +3316,7 @@ int comedi_alloc_subdevice_minor(struct comedi_subdevice *s)
}
i += COMEDI_NUM_BOARD_MINORS;
s->minor = i;
- csdev = device_create(comedi_class, dev->class_dev,
+ csdev = device_create(&comedi_class, dev->class_dev,
MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i",
dev->minor, s->index);
if (!IS_ERR(csdev))
@@ -3337,7 +3341,7 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s)
comedi_subdevice_minor_table[i] = NULL;
mutex_unlock(&comedi_subdevice_minor_table_lock);
if (s->class_dev) {
- device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
+ device_destroy(&comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
s->class_dev = NULL;
}
}
@@ -3383,15 +3387,12 @@ static int __init comedi_init(void)
if (retval)
goto out_unregister_chrdev_region;
- comedi_class = class_create("comedi");
- if (IS_ERR(comedi_class)) {
- retval = PTR_ERR(comedi_class);
+ retval = class_register(&comedi_class);
+ if (retval) {
pr_err("failed to create class\n");
goto out_cdev_del;
}
- comedi_class->dev_groups = comedi_dev_groups;
-
/* create devices files for legacy/manual use */
for (i = 0; i < comedi_num_legacy_minors; i++) {
struct comedi_device *dev;
@@ -3413,7 +3414,7 @@ static int __init comedi_init(void)
out_cleanup_board_minors:
comedi_cleanup_board_minors();
- class_destroy(comedi_class);
+ class_unregister(&comedi_class);
out_cdev_del:
cdev_del(&comedi_cdev);
out_unregister_chrdev_region:
@@ -3425,7 +3426,7 @@ module_init(comedi_init);
static void __exit comedi_cleanup(void)
{
comedi_cleanup_board_minors();
- class_destroy(comedi_class);
+ class_unregister(&comedi_class);
cdev_del(&comedi_cdev);
unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
diff --git a/drivers/comedi/drivers/comedi_test.c b/drivers/comedi/drivers/comedi_test.c
index c02dc19a679b..30ea8b53ebf8 100644
--- a/drivers/comedi/drivers/comedi_test.c
+++ b/drivers/comedi/drivers/comedi_test.c
@@ -60,7 +60,9 @@
static bool config_mode;
static unsigned int set_amplitude;
static unsigned int set_period;
-static struct class *ctcls;
+static const struct class ctcls = {
+ .name = CLASS_NAME,
+};
static struct device *ctdev;
module_param_named(noauto, config_mode, bool, 0444);
@@ -795,13 +797,13 @@ static int __init comedi_test_init(void)
}
if (!config_mode) {
- ctcls = class_create(CLASS_NAME);
- if (IS_ERR(ctcls)) {
+ ret = class_register(&ctcls);
+ if (ret) {
pr_warn("comedi_test: unable to create class\n");
goto clean3;
}
- ctdev = device_create(ctcls, NULL, MKDEV(0, 0), NULL, DEV_NAME);
+ ctdev = device_create(&ctcls, NULL, MKDEV(0, 0), NULL, DEV_NAME);
if (IS_ERR(ctdev)) {
pr_warn("comedi_test: unable to create device\n");
goto clean2;
@@ -817,13 +819,10 @@ static int __init comedi_test_init(void)
return 0;
clean:
- device_destroy(ctcls, MKDEV(0, 0));
+ device_destroy(&ctcls, MKDEV(0, 0));
clean2:
- class_destroy(ctcls);
- ctdev = NULL;
+ class_unregister(&ctcls);
clean3:
- ctcls = NULL;
-
return 0;
}
module_init(comedi_test_init);
@@ -833,9 +832,9 @@ static void __exit comedi_test_exit(void)
if (ctdev)
comedi_auto_unconfig(ctdev);
- if (ctcls) {
- device_destroy(ctcls, MKDEV(0, 0));
- class_destroy(ctcls);
+ if (class_is_registered(&ctcls)) {
+ device_destroy(&ctcls, MKDEV(0, 0));
+ class_unregister(&ctcls);
}
comedi_driver_unregister(&waveform_driver);
diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c
index d9cb937665cf..ed1f57511955 100644
--- a/drivers/counter/104-quad-8.c
+++ b/drivers/counter/104-quad-8.c
@@ -5,10 +5,11 @@
*
* This driver supports the ACCES 104-QUAD-8 and ACCES 104-QUAD-4.
*/
-#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
#include <linux/counter.h>
#include <linux/device.h>
-#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
@@ -17,8 +18,11 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/types.h>
+#include <linux/regmap.h>
#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/unaligned.h>
#define QUAD8_EXTENT 32
@@ -34,118 +38,196 @@ MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers");
#define QUAD8_NUM_COUNTERS 8
-/**
- * struct channel_reg - channel register structure
- * @data: Count data
- * @control: Channel flags and control
- */
-struct channel_reg {
- u8 data;
- u8 control;
-};
-
-/**
- * struct quad8_reg - device register structure
- * @channel: quadrature counter data and control
- * @interrupt_status: channel interrupt status
- * @channel_oper: enable/reset counters and interrupt functions
- * @index_interrupt: enable channel interrupts
- * @reserved: reserved for Factory Use
- * @index_input_levels: index signal logical input level
- * @cable_status: differential encoder cable status
- */
-struct quad8_reg {
- struct channel_reg channel[QUAD8_NUM_COUNTERS];
- u8 interrupt_status;
- u8 channel_oper;
- u8 index_interrupt;
- u8 reserved[3];
- u8 index_input_levels;
- u8 cable_status;
-};
+#define QUAD8_DATA(_channel) ((_channel) * 2)
+#define QUAD8_CONTROL(_channel) (QUAD8_DATA(_channel) + 1)
+#define QUAD8_INTERRUPT_STATUS 0x10
+#define QUAD8_CHANNEL_OPERATION 0x11
+#define QUAD8_INDEX_INTERRUPT 0x12
+#define QUAD8_INDEX_INPUT_LEVELS 0x16
+#define QUAD8_CABLE_STATUS 0x17
/**
* struct quad8 - device private data structure
* @lock: lock to prevent clobbering device states during R/W ops
- * @counter: instance of the counter_device
+ * @cmr: array of Counter Mode Register states
+ * @ior: array of Input / Output Control Register states
+ * @idr: array of Index Control Register states
* @fck_prescaler: array of filter clock prescaler configurations
* @preset: array of preset values
- * @count_mode: array of count mode configurations
- * @quadrature_mode: array of quadrature mode configurations
- * @quadrature_scale: array of quadrature mode scale configurations
- * @ab_enable: array of A and B inputs enable configurations
- * @preset_enable: array of set_to_preset_on_index attribute configurations
- * @irq_trigger: array of current IRQ trigger function configurations
- * @synchronous_mode: array of index function synchronous mode configurations
- * @index_polarity: array of index function polarity configurations
* @cable_fault_enable: differential encoder cable status enable configurations
- * @reg: I/O address offset for the device registers
+ * @map: regmap for the device
*/
struct quad8 {
spinlock_t lock;
+ u8 cmr[QUAD8_NUM_COUNTERS];
+ u8 ior[QUAD8_NUM_COUNTERS];
+ u8 idr[QUAD8_NUM_COUNTERS];
unsigned int fck_prescaler[QUAD8_NUM_COUNTERS];
unsigned int preset[QUAD8_NUM_COUNTERS];
- unsigned int count_mode[QUAD8_NUM_COUNTERS];
- unsigned int quadrature_mode[QUAD8_NUM_COUNTERS];
- unsigned int quadrature_scale[QUAD8_NUM_COUNTERS];
- unsigned int ab_enable[QUAD8_NUM_COUNTERS];
- unsigned int preset_enable[QUAD8_NUM_COUNTERS];
- unsigned int irq_trigger[QUAD8_NUM_COUNTERS];
- unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
- unsigned int index_polarity[QUAD8_NUM_COUNTERS];
unsigned int cable_fault_enable;
- struct quad8_reg __iomem *reg;
+ struct regmap *map;
+};
+
+static const struct regmap_range quad8_wr_ranges[] = {
+ regmap_reg_range(0x0, 0xF), regmap_reg_range(0x11, 0x12), regmap_reg_range(0x17, 0x17),
+};
+static const struct regmap_range quad8_rd_ranges[] = {
+ regmap_reg_range(0x0, 0x12), regmap_reg_range(0x16, 0x18),
+};
+static const struct regmap_access_table quad8_wr_table = {
+ .yes_ranges = quad8_wr_ranges,
+ .n_yes_ranges = ARRAY_SIZE(quad8_wr_ranges),
+};
+static const struct regmap_access_table quad8_rd_table = {
+ .yes_ranges = quad8_rd_ranges,
+ .n_yes_ranges = ARRAY_SIZE(quad8_rd_ranges),
+};
+static const struct regmap_config quad8_regmap_config = {
+ .reg_bits = 8,
+ .reg_stride = 1,
+ .val_bits = 8,
+ .io_port = true,
+ .wr_table = &quad8_wr_table,
+ .rd_table = &quad8_rd_table,
};
/* Error flag */
-#define QUAD8_FLAG_E BIT(4)
+#define FLAG_E BIT(4)
/* Up/Down flag */
-#define QUAD8_FLAG_UD BIT(5)
+#define FLAG_UD BIT(5)
+/* Counting up */
+#define UP 0x1
+
+#define REGISTER_SELECTION GENMASK(6, 5)
+
/* Reset and Load Signal Decoders */
-#define QUAD8_CTR_RLD 0x00
+#define SELECT_RLD u8_encode_bits(0x0, REGISTER_SELECTION)
/* Counter Mode Register */
-#define QUAD8_CTR_CMR 0x20
+#define SELECT_CMR u8_encode_bits(0x1, REGISTER_SELECTION)
/* Input / Output Control Register */
-#define QUAD8_CTR_IOR 0x40
+#define SELECT_IOR u8_encode_bits(0x2, REGISTER_SELECTION)
/* Index Control Register */
-#define QUAD8_CTR_IDR 0x60
+#define SELECT_IDR u8_encode_bits(0x3, REGISTER_SELECTION)
+
+/*
+ * Reset and Load Signal Decoders
+ */
+#define RESETS GENMASK(2, 1)
+#define LOADS GENMASK(4, 3)
/* Reset Byte Pointer (three byte data pointer) */
-#define QUAD8_RLD_RESET_BP 0x01
-/* Reset Counter */
-#define QUAD8_RLD_RESET_CNTR 0x02
-/* Reset Borrow Toggle, Carry Toggle, Compare Toggle, and Sign flags */
-#define QUAD8_RLD_RESET_FLAGS 0x04
+#define RESET_BP BIT(0)
+/* Reset Borrow Toggle, Carry toggle, Compare toggle, Sign, and Index flags */
+#define RESET_BT_CT_CPT_S_IDX u8_encode_bits(0x2, RESETS)
/* Reset Error flag */
-#define QUAD8_RLD_RESET_E 0x06
+#define RESET_E u8_encode_bits(0x3, RESETS)
/* Preset Register to Counter */
-#define QUAD8_RLD_PRESET_CNTR 0x08
+#define TRANSFER_PR_TO_CNTR u8_encode_bits(0x1, LOADS)
/* Transfer Counter to Output Latch */
-#define QUAD8_RLD_CNTR_OUT 0x10
+#define TRANSFER_CNTR_TO_OL u8_encode_bits(0x2, LOADS)
/* Transfer Preset Register LSB to FCK Prescaler */
-#define QUAD8_RLD_PRESET_PSC 0x18
-#define QUAD8_CHAN_OP_RESET_COUNTERS 0x01
-#define QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC 0x04
-#define QUAD8_CMR_QUADRATURE_X1 0x08
-#define QUAD8_CMR_QUADRATURE_X2 0x10
-#define QUAD8_CMR_QUADRATURE_X4 0x18
+#define TRANSFER_PR0_TO_PSC u8_encode_bits(0x3, LOADS)
+
+/*
+ * Counter Mode Registers
+ */
+#define COUNT_ENCODING BIT(0)
+#define COUNT_MODE GENMASK(2, 1)
+#define QUADRATURE_MODE GENMASK(4, 3)
+/* Binary count */
+#define BINARY u8_encode_bits(0x0, COUNT_ENCODING)
+/* Normal count */
+#define NORMAL_COUNT 0x0
+/* Range Limit */
+#define RANGE_LIMIT 0x1
+/* Non-recycle count */
+#define NON_RECYCLE_COUNT 0x2
+/* Modulo-N */
+#define MODULO_N 0x3
+/* Non-quadrature */
+#define NON_QUADRATURE 0x0
+/* Quadrature X1 */
+#define QUADRATURE_X1 0x1
+/* Quadrature X2 */
+#define QUADRATURE_X2 0x2
+/* Quadrature X4 */
+#define QUADRATURE_X4 0x3
+
+/*
+ * Input/Output Control Register
+ */
+#define AB_GATE BIT(0)
+#define LOAD_PIN BIT(1)
+#define FLG_PINS GENMASK(4, 3)
+/* Disable inputs A and B */
+#define DISABLE_AB u8_encode_bits(0x0, AB_GATE)
+/* Load Counter input */
+#define LOAD_CNTR 0x0
+/* FLG1 = CARRY(active low); FLG2 = BORROW(active low) */
+#define FLG1_CARRY_FLG2_BORROW 0x0
+/* FLG1 = COMPARE(active low); FLG2 = BORROW(active low) */
+#define FLG1_COMPARE_FLG2_BORROW 0x1
+/* FLG1 = Carry(active low)/Borrow(active low); FLG2 = U/D(active low) flag */
+#define FLG1_CARRYBORROW_FLG2_UD 0x2
+/* FLG1 = INDX (low pulse at INDEX pin active level); FLG2 = E flag */
+#define FLG1_INDX_FLG2_E 0x3
+
+/*
+ * INDEX CONTROL REGISTERS
+ */
+#define INDEX_MODE BIT(0)
+#define INDEX_POLARITY BIT(1)
+/* Disable Index mode */
+#define DISABLE_INDEX_MODE 0x0
+/* Enable Index mode */
+#define ENABLE_INDEX_MODE 0x1
+/* Negative Index Polarity */
+#define NEGATIVE_INDEX_POLARITY 0x0
+/* Positive Index Polarity */
+#define POSITIVE_INDEX_POLARITY 0x1
+
+/*
+ * Channel Operation Register
+ */
+#define COUNTERS_OPERATION BIT(0)
+#define INTERRUPT_FUNCTION BIT(2)
+/* Enable all Counters */
+#define ENABLE_COUNTERS u8_encode_bits(0x0, COUNTERS_OPERATION)
+/* Reset all Counters */
+#define RESET_COUNTERS u8_encode_bits(0x1, COUNTERS_OPERATION)
+/* Disable the interrupt function */
+#define DISABLE_INTERRUPT_FUNCTION u8_encode_bits(0x0, INTERRUPT_FUNCTION)
+/* Enable the interrupt function */
+#define ENABLE_INTERRUPT_FUNCTION u8_encode_bits(0x1, INTERRUPT_FUNCTION)
+/* Any write to the Channel Operation register clears any pending interrupts */
+#define CLEAR_PENDING_INTERRUPTS (ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION)
/* Each Counter is 24 bits wide */
#define LS7267_CNTR_MAX GENMASK(23, 0)
+static __always_inline int quad8_control_register_update(struct regmap *const map, u8 *const buf,
+ const size_t channel, const u8 val,
+ const u8 field)
+{
+ u8p_replace_bits(&buf[channel], val, field);
+ return regmap_write(map, QUAD8_CONTROL(channel), buf[channel]);
+}
+
static int quad8_signal_read(struct counter_device *counter,
struct counter_signal *signal,
enum counter_signal_level *level)
{
const struct quad8 *const priv = counter_priv(counter);
- unsigned int state;
+ int ret;
/* Only Index signal levels can be read */
if (signal->id < 16)
return -EINVAL;
- state = ioread8(&priv->reg->index_input_levels) & BIT(signal->id - 16);
+ ret = regmap_test_bits(priv->map, QUAD8_INDEX_INPUT_LEVELS, BIT(signal->id - 16));
+ if (ret < 0)
+ return ret;
- *level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
+ *level = (ret) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
return 0;
}
@@ -154,65 +236,81 @@ static int quad8_count_read(struct counter_device *counter,
struct counter_count *count, u64 *val)
{
struct quad8 *const priv = counter_priv(counter);
- struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
unsigned long irqflags;
- int i;
-
- *val = 0;
+ u8 value[3];
+ int ret;
spin_lock_irqsave(&priv->lock, irqflags);
- /* Reset Byte Pointer; transfer Counter to Output Latch */
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
- &chan->control);
-
- for (i = 0; i < 3; i++)
- *val |= (unsigned long)ioread8(&chan->data) << (8 * i);
+ ret = regmap_write(priv->map, QUAD8_CONTROL(count->id),
+ SELECT_RLD | RESET_BP | TRANSFER_CNTR_TO_OL);
+ if (ret)
+ goto exit_unlock;
+ ret = regmap_noinc_read(priv->map, QUAD8_DATA(count->id), value, sizeof(value));
+exit_unlock:
spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ *val = get_unaligned_le24(value);
+
+ return ret;
+}
+
+static int quad8_preset_register_set(struct quad8 *const priv, const size_t id,
+ const unsigned long preset)
+{
+ u8 value[3];
+ int ret;
+
+ put_unaligned_le24(preset, value);
+
+ ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP);
+ if (ret)
+ return ret;
+ return regmap_noinc_write(priv->map, QUAD8_DATA(id), value, sizeof(value));
+}
+
+static int quad8_flag_register_reset(struct quad8 *const priv, const size_t id)
+{
+ int ret;
+
+ ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BT_CT_CPT_S_IDX);
+ if (ret)
+ return ret;
+ return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_E);
}
static int quad8_count_write(struct counter_device *counter,
struct counter_count *count, u64 val)
{
struct quad8 *const priv = counter_priv(counter);
- struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
unsigned long irqflags;
- int i;
+ int ret;
if (val > LS7267_CNTR_MAX)
return -ERANGE;
spin_lock_irqsave(&priv->lock, irqflags);
- /* Reset Byte Pointer */
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
-
/* Counter can only be set via Preset Register */
- for (i = 0; i < 3; i++)
- iowrite8(val >> (8 * i), &chan->data);
+ ret = quad8_preset_register_set(priv, count->id, val);
+ if (ret)
+ goto exit_unlock;
+ ret = regmap_write(priv->map, QUAD8_CONTROL(count->id), SELECT_RLD | TRANSFER_PR_TO_CNTR);
+ if (ret)
+ goto exit_unlock;
- /* Transfer Preset Register to Counter */
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, &chan->control);
-
- /* Reset Byte Pointer */
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
+ ret = quad8_flag_register_reset(priv, count->id);
+ if (ret)
+ goto exit_unlock;
/* Set Preset Register back to original value */
- val = priv->preset[count->id];
- for (i = 0; i < 3; i++)
- iowrite8(val >> (8 * i), &chan->data);
-
- /* Reset Borrow, Carry, Compare, and Sign flags */
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control);
- /* Reset Error flag */
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control);
+ ret = quad8_preset_register_set(priv, count->id, priv->preset[count->id]);
+exit_unlock:
spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ return ret;
}
static const enum counter_function quad8_count_functions_list[] = {
@@ -225,19 +323,17 @@ static const enum counter_function quad8_count_functions_list[] = {
static int quad8_function_get(const struct quad8 *const priv, const size_t id,
enum counter_function *const function)
{
- if (!priv->quadrature_mode[id]) {
+ switch (u8_get_bits(priv->cmr[id], QUADRATURE_MODE)) {
+ case NON_QUADRATURE:
*function = COUNTER_FUNCTION_PULSE_DIRECTION;
return 0;
- }
-
- switch (priv->quadrature_scale[id]) {
- case 0:
+ case QUADRATURE_X1:
*function = COUNTER_FUNCTION_QUADRATURE_X1_A;
return 0;
- case 1:
+ case QUADRATURE_X2:
*function = COUNTER_FUNCTION_QUADRATURE_X2_A;
return 0;
- case 2:
+ case QUADRATURE_X4:
*function = COUNTER_FUNCTION_QUADRATURE_X4;
return 0;
default:
@@ -269,60 +365,46 @@ static int quad8_function_write(struct counter_device *counter,
{
struct quad8 *const priv = counter_priv(counter);
const int id = count->id;
- unsigned int *const quadrature_mode = priv->quadrature_mode + id;
- unsigned int *const scale = priv->quadrature_scale + id;
- unsigned int *const synchronous_mode = priv->synchronous_mode + id;
- u8 __iomem *const control = &priv->reg->channel[id].control;
unsigned long irqflags;
unsigned int mode_cfg;
- unsigned int idr_cfg;
+ bool synchronous_mode;
+ int ret;
- spin_lock_irqsave(&priv->lock, irqflags);
-
- mode_cfg = priv->count_mode[id] << 1;
- idr_cfg = priv->index_polarity[id] << 1;
-
- if (function == COUNTER_FUNCTION_PULSE_DIRECTION) {
- *quadrature_mode = 0;
-
- /* Quadrature scaling only available in quadrature mode */
- *scale = 0;
+ switch (function) {
+ case COUNTER_FUNCTION_PULSE_DIRECTION:
+ mode_cfg = NON_QUADRATURE;
+ break;
+ case COUNTER_FUNCTION_QUADRATURE_X1_A:
+ mode_cfg = QUADRATURE_X1;
+ break;
+ case COUNTER_FUNCTION_QUADRATURE_X2_A:
+ mode_cfg = QUADRATURE_X2;
+ break;
+ case COUNTER_FUNCTION_QUADRATURE_X4:
+ mode_cfg = QUADRATURE_X4;
+ break;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
+ }
- /* Synchronous function not supported in non-quadrature mode */
- if (*synchronous_mode) {
- *synchronous_mode = 0;
- /* Disable synchronous function mode */
- iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
- }
- } else {
- *quadrature_mode = 1;
+ spin_lock_irqsave(&priv->lock, irqflags);
- switch (function) {
- case COUNTER_FUNCTION_QUADRATURE_X1_A:
- *scale = 0;
- mode_cfg |= QUAD8_CMR_QUADRATURE_X1;
- break;
- case COUNTER_FUNCTION_QUADRATURE_X2_A:
- *scale = 1;
- mode_cfg |= QUAD8_CMR_QUADRATURE_X2;
- break;
- case COUNTER_FUNCTION_QUADRATURE_X4:
- *scale = 2;
- mode_cfg |= QUAD8_CMR_QUADRATURE_X4;
- break;
- default:
- /* should never reach this path */
- spin_unlock_irqrestore(&priv->lock, irqflags);
- return -EINVAL;
- }
+ /* Synchronous function not supported in non-quadrature mode */
+ synchronous_mode = u8_get_bits(priv->idr[id], INDEX_MODE) == ENABLE_INDEX_MODE;
+ if (synchronous_mode && mode_cfg == NON_QUADRATURE) {
+ ret = quad8_control_register_update(priv->map, priv->idr, id, DISABLE_INDEX_MODE,
+ INDEX_MODE);
+ if (ret)
+ goto exit_unlock;
}
- /* Load mode configuration to Counter Mode Register */
- iowrite8(QUAD8_CTR_CMR | mode_cfg, control);
+ ret = quad8_control_register_update(priv->map, priv->cmr, id, mode_cfg, QUADRATURE_MODE);
+exit_unlock:
spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ return ret;
}
static int quad8_direction_read(struct counter_device *counter,
@@ -330,13 +412,13 @@ static int quad8_direction_read(struct counter_device *counter,
enum counter_count_direction *direction)
{
const struct quad8 *const priv = counter_priv(counter);
- unsigned int ud_flag;
- u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control;
-
- /* U/D flag: nonzero = up, zero = down */
- ud_flag = ioread8(flag_addr) & QUAD8_FLAG_UD;
+ unsigned int flag;
+ int ret;
- *direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD :
+ ret = regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag);
+ if (ret)
+ return ret;
+ *direction = (u8_get_bits(flag, FLAG_UD) == UP) ? COUNTER_COUNT_DIRECTION_FORWARD :
COUNTER_COUNT_DIRECTION_BACKWARD;
return 0;
@@ -366,13 +448,13 @@ static int quad8_action_read(struct counter_device *counter,
const size_t signal_a_id = count->synapses[0].signal->id;
enum counter_count_direction direction;
+ /* Default action mode */
+ *action = COUNTER_SYNAPSE_ACTION_NONE;
+
/* Handle Index signals */
if (synapse->signal->id >= 16) {
- if (!priv->preset_enable[count->id])
+ if (u8_get_bits(priv->ior[count->id], LOAD_PIN) == LOAD_CNTR)
*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
- else
- *action = COUNTER_SYNAPSE_ACTION_NONE;
-
return 0;
}
@@ -392,9 +474,6 @@ static int quad8_action_read(struct counter_device *counter,
spin_unlock_irqrestore(&priv->lock, irqflags);
- /* Default action mode */
- *action = COUNTER_SYNAPSE_ACTION_NONE;
-
/* Determine action mode based on current count function mode */
switch (function) {
case COUNTER_FUNCTION_PULSE_DIRECTION:
@@ -422,67 +501,57 @@ static int quad8_action_read(struct counter_device *counter,
}
}
-enum {
- QUAD8_EVENT_CARRY = 0,
- QUAD8_EVENT_COMPARE = 1,
- QUAD8_EVENT_CARRY_BORROW = 2,
- QUAD8_EVENT_INDEX = 3,
-};
-
static int quad8_events_configure(struct counter_device *counter)
{
struct quad8 *const priv = counter_priv(counter);
unsigned long irq_enabled = 0;
unsigned long irqflags;
struct counter_event_node *event_node;
- unsigned int next_irq_trigger;
- unsigned long ior_cfg;
+ u8 flg_pins;
+ int ret;
spin_lock_irqsave(&priv->lock, irqflags);
list_for_each_entry(event_node, &counter->events_list, l) {
switch (event_node->event) {
case COUNTER_EVENT_OVERFLOW:
- next_irq_trigger = QUAD8_EVENT_CARRY;
+ flg_pins = FLG1_CARRY_FLG2_BORROW;
break;
case COUNTER_EVENT_THRESHOLD:
- next_irq_trigger = QUAD8_EVENT_COMPARE;
+ flg_pins = FLG1_COMPARE_FLG2_BORROW;
break;
case COUNTER_EVENT_OVERFLOW_UNDERFLOW:
- next_irq_trigger = QUAD8_EVENT_CARRY_BORROW;
+ flg_pins = FLG1_CARRYBORROW_FLG2_UD;
break;
case COUNTER_EVENT_INDEX:
- next_irq_trigger = QUAD8_EVENT_INDEX;
+ flg_pins = FLG1_INDX_FLG2_E;
break;
default:
/* should never reach this path */
- spin_unlock_irqrestore(&priv->lock, irqflags);
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit_unlock;
}
/* Enable IRQ line */
irq_enabled |= BIT(event_node->channel);
/* Skip configuration if it is the same as previously set */
- if (priv->irq_trigger[event_node->channel] == next_irq_trigger)
+ if (flg_pins == u8_get_bits(priv->ior[event_node->channel], FLG_PINS))
continue;
/* Save new IRQ function configuration */
- priv->irq_trigger[event_node->channel] = next_irq_trigger;
-
- /* Load configuration to I/O Control Register */
- ior_cfg = priv->ab_enable[event_node->channel] |
- priv->preset_enable[event_node->channel] << 1 |
- priv->irq_trigger[event_node->channel] << 3;
- iowrite8(QUAD8_CTR_IOR | ior_cfg,
- &priv->reg->channel[event_node->channel].control);
+ ret = quad8_control_register_update(priv->map, priv->ior, event_node->channel,
+ flg_pins, FLG_PINS);
+ if (ret)
+ goto exit_unlock;
}
- iowrite8(irq_enabled, &priv->reg->index_interrupt);
+ ret = regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, irq_enabled);
+exit_unlock:
spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ return ret;
}
static int quad8_watch_validate(struct counter_device *counter,
@@ -531,7 +600,7 @@ static int quad8_index_polarity_get(struct counter_device *counter,
const struct quad8 *const priv = counter_priv(counter);
const size_t channel_id = signal->id - 16;
- *index_polarity = priv->index_polarity[channel_id];
+ *index_polarity = u8_get_bits(priv->idr[channel_id], INDEX_POLARITY);
return 0;
}
@@ -542,22 +611,17 @@ static int quad8_index_polarity_set(struct counter_device *counter,
{
struct quad8 *const priv = counter_priv(counter);
const size_t channel_id = signal->id - 16;
- u8 __iomem *const control = &priv->reg->channel[channel_id].control;
unsigned long irqflags;
- unsigned int idr_cfg = index_polarity << 1;
+ int ret;
spin_lock_irqsave(&priv->lock, irqflags);
- idr_cfg |= priv->synchronous_mode[channel_id];
-
- priv->index_polarity[channel_id] = index_polarity;
-
- /* Load Index Control configuration to Index Control Register */
- iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
+ ret = quad8_control_register_update(priv->map, priv->idr, channel_id, index_polarity,
+ INDEX_POLARITY);
spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ return ret;
}
static int quad8_polarity_read(struct counter_device *counter,
@@ -571,7 +635,7 @@ static int quad8_polarity_read(struct counter_device *counter,
if (err)
return err;
- *polarity = (index_polarity) ? COUNTER_SIGNAL_POLARITY_POSITIVE :
+ *polarity = (index_polarity == POSITIVE_INDEX_POLARITY) ? COUNTER_SIGNAL_POLARITY_POSITIVE :
COUNTER_SIGNAL_POLARITY_NEGATIVE;
return 0;
@@ -581,7 +645,8 @@ static int quad8_polarity_write(struct counter_device *counter,
struct counter_signal *signal,
enum counter_signal_polarity polarity)
{
- const u32 pol = (polarity == COUNTER_SIGNAL_POLARITY_POSITIVE) ? 1 : 0;
+ const u32 pol = (polarity == COUNTER_SIGNAL_POLARITY_POSITIVE) ? POSITIVE_INDEX_POLARITY :
+ NEGATIVE_INDEX_POLARITY;
return quad8_index_polarity_set(counter, signal, pol);
}
@@ -598,7 +663,7 @@ static int quad8_synchronous_mode_get(struct counter_device *counter,
const struct quad8 *const priv = counter_priv(counter);
const size_t channel_id = signal->id - 16;
- *synchronous_mode = priv->synchronous_mode[channel_id];
+ *synchronous_mode = u8_get_bits(priv->idr[channel_id], INDEX_MODE);
return 0;
}
@@ -609,28 +674,26 @@ static int quad8_synchronous_mode_set(struct counter_device *counter,
{
struct quad8 *const priv = counter_priv(counter);
const size_t channel_id = signal->id - 16;
- u8 __iomem *const control = &priv->reg->channel[channel_id].control;
+ u8 quadrature_mode;
unsigned long irqflags;
- unsigned int idr_cfg = synchronous_mode;
+ int ret;
spin_lock_irqsave(&priv->lock, irqflags);
- idr_cfg |= priv->index_polarity[channel_id] << 1;
-
/* Index function must be non-synchronous in non-quadrature mode */
- if (synchronous_mode && !priv->quadrature_mode[channel_id]) {
- spin_unlock_irqrestore(&priv->lock, irqflags);
- return -EINVAL;
+ quadrature_mode = u8_get_bits(priv->idr[channel_id], QUADRATURE_MODE);
+ if (synchronous_mode && quadrature_mode == NON_QUADRATURE) {
+ ret = -EINVAL;
+ goto exit_unlock;
}
- priv->synchronous_mode[channel_id] = synchronous_mode;
-
- /* Load Index Control configuration to Index Control Register */
- iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
+ ret = quad8_control_register_update(priv->map, priv->idr, channel_id, synchronous_mode,
+ INDEX_MODE);
+exit_unlock:
spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ return ret;
}
static int quad8_count_floor_read(struct counter_device *counter,
@@ -648,18 +711,17 @@ static int quad8_count_mode_read(struct counter_device *counter,
{
const struct quad8 *const priv = counter_priv(counter);
- /* Map 104-QUAD-8 count mode to Generic Counter count mode */
- switch (priv->count_mode[count->id]) {
- case 0:
+ switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) {
+ case NORMAL_COUNT:
*cnt_mode = COUNTER_COUNT_MODE_NORMAL;
break;
- case 1:
+ case RANGE_LIMIT:
*cnt_mode = COUNTER_COUNT_MODE_RANGE_LIMIT;
break;
- case 2:
+ case NON_RECYCLE_COUNT:
*cnt_mode = COUNTER_COUNT_MODE_NON_RECYCLE;
break;
- case 3:
+ case MODULO_N:
*cnt_mode = COUNTER_COUNT_MODE_MODULO_N;
break;
}
@@ -673,23 +735,21 @@ static int quad8_count_mode_write(struct counter_device *counter,
{
struct quad8 *const priv = counter_priv(counter);
unsigned int count_mode;
- unsigned int mode_cfg;
- u8 __iomem *const control = &priv->reg->channel[count->id].control;
unsigned long irqflags;
+ int ret;
- /* Map Generic Counter count mode to 104-QUAD-8 count mode */
switch (cnt_mode) {
case COUNTER_COUNT_MODE_NORMAL:
- count_mode = 0;
+ count_mode = NORMAL_COUNT;
break;
case COUNTER_COUNT_MODE_RANGE_LIMIT:
- count_mode = 1;
+ count_mode = RANGE_LIMIT;
break;
case COUNTER_COUNT_MODE_NON_RECYCLE:
- count_mode = 2;
+ count_mode = NON_RECYCLE_COUNT;
break;
case COUNTER_COUNT_MODE_MODULO_N:
- count_mode = 3;
+ count_mode = MODULO_N;
break;
default:
/* should never reach this path */
@@ -698,21 +758,12 @@ static int quad8_count_mode_write(struct counter_device *counter,
spin_lock_irqsave(&priv->lock, irqflags);
- priv->count_mode[count->id] = count_mode;
-
- /* Set count mode configuration value */
- mode_cfg = count_mode << 1;
-
- /* Add quadrature mode configuration */
- if (priv->quadrature_mode[count->id])
- mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3;
-
- /* Load mode configuration to Counter Mode Register */
- iowrite8(QUAD8_CTR_CMR | mode_cfg, control);
+ ret = quad8_control_register_update(priv->map, priv->cmr, count->id, count_mode,
+ COUNT_MODE);
spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ return ret;
}
static int quad8_count_enable_read(struct counter_device *counter,
@@ -720,7 +771,7 @@ static int quad8_count_enable_read(struct counter_device *counter,
{
const struct quad8 *const priv = counter_priv(counter);
- *enable = priv->ab_enable[count->id];
+ *enable = u8_get_bits(priv->ior[count->id], AB_GATE);
return 0;
}
@@ -729,23 +780,16 @@ static int quad8_count_enable_write(struct counter_device *counter,
struct counter_count *count, u8 enable)
{
struct quad8 *const priv = counter_priv(counter);
- u8 __iomem *const control = &priv->reg->channel[count->id].control;
unsigned long irqflags;
- unsigned int ior_cfg;
+ int ret;
spin_lock_irqsave(&priv->lock, irqflags);
- priv->ab_enable[count->id] = enable;
-
- ior_cfg = enable | priv->preset_enable[count->id] << 1 |
- priv->irq_trigger[count->id] << 3;
-
- /* Load I/O control configuration */
- iowrite8(QUAD8_CTR_IOR | ior_cfg, control);
+ ret = quad8_control_register_update(priv->map, priv->ior, count->id, enable, AB_GATE);
spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ return ret;
}
static const char *const quad8_noise_error_states[] = {
@@ -757,9 +801,13 @@ static int quad8_error_noise_get(struct counter_device *counter,
struct counter_count *count, u32 *noise_error)
{
const struct quad8 *const priv = counter_priv(counter);
- u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control;
+ unsigned int flag;
+ int ret;
- *noise_error = !!(ioread8(flag_addr) & QUAD8_FLAG_E);
+ ret = regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag);
+ if (ret)
+ return ret;
+ *noise_error = u8_get_bits(flag, FLAG_E);
return 0;
}
@@ -774,38 +822,24 @@ static int quad8_count_preset_read(struct counter_device *counter,
return 0;
}
-static void quad8_preset_register_set(struct quad8 *const priv, const int id,
- const unsigned int preset)
-{
- struct channel_reg __iomem *const chan = priv->reg->channel + id;
- int i;
-
- priv->preset[id] = preset;
-
- /* Reset Byte Pointer */
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
-
- /* Set Preset Register */
- for (i = 0; i < 3; i++)
- iowrite8(preset >> (8 * i), &chan->data);
-}
-
static int quad8_count_preset_write(struct counter_device *counter,
struct counter_count *count, u64 preset)
{
struct quad8 *const priv = counter_priv(counter);
unsigned long irqflags;
+ int ret;
if (preset > LS7267_CNTR_MAX)
return -ERANGE;
spin_lock_irqsave(&priv->lock, irqflags);
- quad8_preset_register_set(priv, count->id, preset);
+ priv->preset[count->id] = preset;
+ ret = quad8_preset_register_set(priv, count->id, preset);
spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ return ret;
}
static int quad8_count_ceiling_read(struct counter_device *counter,
@@ -817,9 +851,9 @@ static int quad8_count_ceiling_read(struct counter_device *counter,
spin_lock_irqsave(&priv->lock, irqflags);
/* Range Limit and Modulo-N count modes use preset value as ceiling */
- switch (priv->count_mode[count->id]) {
- case 1:
- case 3:
+ switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) {
+ case RANGE_LIMIT:
+ case MODULO_N:
*ceiling = priv->preset[count->id];
break;
default:
@@ -837,6 +871,7 @@ static int quad8_count_ceiling_write(struct counter_device *counter,
{
struct quad8 *const priv = counter_priv(counter);
unsigned long irqflags;
+ int ret;
if (ceiling > LS7267_CNTR_MAX)
return -ERANGE;
@@ -844,17 +879,20 @@ static int quad8_count_ceiling_write(struct counter_device *counter,
spin_lock_irqsave(&priv->lock, irqflags);
/* Range Limit and Modulo-N count modes use preset value as ceiling */
- switch (priv->count_mode[count->id]) {
- case 1:
- case 3:
- quad8_preset_register_set(priv, count->id, ceiling);
- spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) {
+ case RANGE_LIMIT:
+ case MODULO_N:
+ priv->preset[count->id] = ceiling;
+ ret = quad8_preset_register_set(priv, count->id, ceiling);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
}
spin_unlock_irqrestore(&priv->lock, irqflags);
- return -EINVAL;
+ return ret;
}
static int quad8_count_preset_enable_read(struct counter_device *counter,
@@ -863,7 +901,8 @@ static int quad8_count_preset_enable_read(struct counter_device *counter,
{
const struct quad8 *const priv = counter_priv(counter);
- *preset_enable = !priv->preset_enable[count->id];
+ /* Preset enable is active low in Input/Output Control register */
+ *preset_enable = !u8_get_bits(priv->ior[count->id], LOAD_PIN);
return 0;
}
@@ -873,26 +912,18 @@ static int quad8_count_preset_enable_write(struct counter_device *counter,
u8 preset_enable)
{
struct quad8 *const priv = counter_priv(counter);
- u8 __iomem *const control = &priv->reg->channel[count->id].control;
unsigned long irqflags;
- unsigned int ior_cfg;
-
- /* Preset enable is active low in Input/Output Control register */
- preset_enable = !preset_enable;
+ int ret;
spin_lock_irqsave(&priv->lock, irqflags);
- priv->preset_enable[count->id] = preset_enable;
-
- ior_cfg = priv->ab_enable[count->id] | preset_enable << 1 |
- priv->irq_trigger[count->id] << 3;
-
- /* Load I/O control configuration to Input / Output Control Register */
- iowrite8(QUAD8_CTR_IOR | ior_cfg, control);
+ /* Preset enable is active low in Input/Output Control register */
+ ret = quad8_control_register_update(priv->map, priv->ior, count->id, !preset_enable,
+ LOAD_PIN);
spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ return ret;
}
static int quad8_signal_cable_fault_read(struct counter_device *counter,
@@ -903,7 +934,7 @@ static int quad8_signal_cable_fault_read(struct counter_device *counter,
const size_t channel_id = signal->id / 2;
unsigned long irqflags;
bool disabled;
- unsigned int status;
+ int ret;
spin_lock_irqsave(&priv->lock, irqflags);
@@ -914,13 +945,16 @@ static int quad8_signal_cable_fault_read(struct counter_device *counter,
return -EINVAL;
}
- /* Logic 0 = cable fault */
- status = ioread8(&priv->reg->cable_status);
+ ret = regmap_test_bits(priv->map, QUAD8_CABLE_STATUS, BIT(channel_id));
+ if (ret < 0) {
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+ return ret;
+ }
spin_unlock_irqrestore(&priv->lock, irqflags);
- /* Mask respective channel and invert logic */
- *cable_fault = !(status & BIT(channel_id));
+ /* Logic 0 = cable fault */
+ *cable_fault = !ret;
return 0;
}
@@ -945,6 +979,7 @@ static int quad8_signal_cable_fault_enable_write(struct counter_device *counter,
const size_t channel_id = signal->id / 2;
unsigned long irqflags;
unsigned int cable_fault_enable;
+ int ret;
spin_lock_irqsave(&priv->lock, irqflags);
@@ -956,11 +991,11 @@ static int quad8_signal_cable_fault_enable_write(struct counter_device *counter,
/* Enable is active low in Differential Encoder Cable Status register */
cable_fault_enable = ~priv->cable_fault_enable;
- iowrite8(cable_fault_enable, &priv->reg->cable_status);
+ ret = regmap_write(priv->map, QUAD8_CABLE_STATUS, cable_fault_enable);
spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ return ret;
}
static int quad8_signal_fck_prescaler_read(struct counter_device *counter,
@@ -974,30 +1009,37 @@ static int quad8_signal_fck_prescaler_read(struct counter_device *counter,
return 0;
}
+static int quad8_filter_clock_prescaler_set(struct quad8 *const priv, const size_t id,
+ const u8 prescaler)
+{
+ int ret;
+
+ ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP);
+ if (ret)
+ return ret;
+ ret = regmap_write(priv->map, QUAD8_DATA(id), prescaler);
+ if (ret)
+ return ret;
+ return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | TRANSFER_PR0_TO_PSC);
+}
+
static int quad8_signal_fck_prescaler_write(struct counter_device *counter,
struct counter_signal *signal,
u8 prescaler)
{
struct quad8 *const priv = counter_priv(counter);
const size_t channel_id = signal->id / 2;
- struct channel_reg __iomem *const chan = priv->reg->channel + channel_id;
unsigned long irqflags;
+ int ret;
spin_lock_irqsave(&priv->lock, irqflags);
priv->fck_prescaler[channel_id] = prescaler;
-
- /* Reset Byte Pointer */
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
-
- /* Set filter clock factor */
- iowrite8(prescaler, &chan->data);
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
- &chan->control);
+ ret = quad8_filter_clock_prescaler_set(priv, channel_id, prescaler);
spin_unlock_irqrestore(&priv->lock, irqflags);
- return 0;
+ return ret;
}
static struct counter_comp quad8_signal_ext[] = {
@@ -1150,77 +1192,93 @@ static irqreturn_t quad8_irq_handler(int irq, void *private)
{
struct counter_device *counter = private;
struct quad8 *const priv = counter_priv(counter);
+ unsigned int status;
unsigned long irq_status;
unsigned long channel;
+ unsigned int flg_pins;
u8 event;
+ int ret;
- irq_status = ioread8(&priv->reg->interrupt_status);
- if (!irq_status)
+ ret = regmap_read(priv->map, QUAD8_INTERRUPT_STATUS, &status);
+ if (ret)
+ return ret;
+ if (!status)
return IRQ_NONE;
+ irq_status = status;
for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) {
- switch (priv->irq_trigger[channel]) {
- case QUAD8_EVENT_CARRY:
+ flg_pins = u8_get_bits(priv->ior[channel], FLG_PINS);
+ switch (flg_pins) {
+ case FLG1_CARRY_FLG2_BORROW:
event = COUNTER_EVENT_OVERFLOW;
break;
- case QUAD8_EVENT_COMPARE:
+ case FLG1_COMPARE_FLG2_BORROW:
event = COUNTER_EVENT_THRESHOLD;
break;
- case QUAD8_EVENT_CARRY_BORROW:
+ case FLG1_CARRYBORROW_FLG2_UD:
event = COUNTER_EVENT_OVERFLOW_UNDERFLOW;
break;
- case QUAD8_EVENT_INDEX:
+ case FLG1_INDX_FLG2_E:
event = COUNTER_EVENT_INDEX;
break;
default:
/* should never reach this path */
WARN_ONCE(true, "invalid interrupt trigger function %u configured for channel %lu\n",
- priv->irq_trigger[channel], channel);
+ flg_pins, channel);
continue;
}
counter_push_event(counter, event, channel);
}
- /* Clear pending interrupts on device */
- iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper);
+ ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, CLEAR_PENDING_INTERRUPTS);
+ if (ret)
+ return ret;
return IRQ_HANDLED;
}
-static void quad8_init_counter(struct channel_reg __iomem *const chan)
+static int quad8_init_counter(struct quad8 *const priv, const size_t channel)
{
- unsigned long i;
+ int ret;
+
+ ret = quad8_filter_clock_prescaler_set(priv, channel, 0);
+ if (ret)
+ return ret;
+ ret = quad8_preset_register_set(priv, channel, 0);
+ if (ret)
+ return ret;
+ ret = quad8_flag_register_reset(priv, channel);
+ if (ret)
+ return ret;
- /* Reset Byte Pointer */
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
- /* Reset filter clock factor */
- iowrite8(0, &chan->data);
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
- &chan->control);
- /* Reset Byte Pointer */
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
- /* Reset Preset Register */
- for (i = 0; i < 3; i++)
- iowrite8(0x00, &chan->data);
- /* Reset Borrow, Carry, Compare, and Sign flags */
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control);
- /* Reset Error flag */
- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control);
/* Binary encoding; Normal count; non-quadrature mode */
- iowrite8(QUAD8_CTR_CMR, &chan->control);
+ priv->cmr[channel] = SELECT_CMR | BINARY | u8_encode_bits(NORMAL_COUNT, COUNT_MODE) |
+ u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE);
+ ret = regmap_write(priv->map, QUAD8_CONTROL(channel), priv->cmr[channel]);
+ if (ret)
+ return ret;
+
/* Disable A and B inputs; preset on index; FLG1 as Carry */
- iowrite8(QUAD8_CTR_IOR, &chan->control);
+ priv->ior[channel] = SELECT_IOR | DISABLE_AB | u8_encode_bits(LOAD_CNTR, LOAD_PIN) |
+ u8_encode_bits(FLG1_CARRY_FLG2_BORROW, FLG_PINS);
+ ret = regmap_write(priv->map, QUAD8_CONTROL(channel), priv->ior[channel]);
+ if (ret)
+ return ret;
+
/* Disable index function; negative index polarity */
- iowrite8(QUAD8_CTR_IDR, &chan->control);
+ priv->idr[channel] = SELECT_IDR | u8_encode_bits(DISABLE_INDEX_MODE, INDEX_MODE) |
+ u8_encode_bits(NEGATIVE_INDEX_POLARITY, INDEX_POLARITY);
+ return regmap_write(priv->map, QUAD8_CONTROL(channel), priv->idr[channel]);
}
static int quad8_probe(struct device *dev, unsigned int id)
{
struct counter_device *counter;
struct quad8 *priv;
+ void __iomem *regs;
unsigned long i;
- int err;
+ int ret;
if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) {
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
@@ -1233,10 +1291,15 @@ static int quad8_probe(struct device *dev, unsigned int id)
return -ENOMEM;
priv = counter_priv(counter);
- priv->reg = devm_ioport_map(dev, base[id], QUAD8_EXTENT);
- if (!priv->reg)
+ regs = devm_ioport_map(dev, base[id], QUAD8_EXTENT);
+ if (!regs)
return -ENOMEM;
+ priv->map = devm_regmap_init_mmio(dev, regs, &quad8_regmap_config);
+ if (IS_ERR(priv->map))
+ return dev_err_probe(dev, PTR_ERR(priv->map),
+ "Unable to initialize register map\n");
+
/* Initialize Counter device and driver data */
counter->name = dev_name(dev);
counter->parent = dev;
@@ -1249,25 +1312,38 @@ static int quad8_probe(struct device *dev, unsigned int id)
spin_lock_init(&priv->lock);
/* Reset Index/Interrupt Register */
- iowrite8(0x00, &priv->reg->index_interrupt);
+ ret = regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, 0x00);
+ if (ret)
+ return ret;
/* Reset all counters and disable interrupt function */
- iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, &priv->reg->channel_oper);
+ ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION,
+ RESET_COUNTERS | DISABLE_INTERRUPT_FUNCTION);
+ if (ret)
+ return ret;
/* Set initial configuration for all counters */
- for (i = 0; i < QUAD8_NUM_COUNTERS; i++)
- quad8_init_counter(priv->reg->channel + i);
+ for (i = 0; i < QUAD8_NUM_COUNTERS; i++) {
+ ret = quad8_init_counter(priv, i);
+ if (ret)
+ return ret;
+ }
/* Disable Differential Encoder Cable Status for all channels */
- iowrite8(0xFF, &priv->reg->cable_status);
+ ret = regmap_write(priv->map, QUAD8_CABLE_STATUS, GENMASK(7, 0));
+ if (ret)
+ return ret;
/* Enable all counters and enable interrupt function */
- iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper);
+ ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION,
+ ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION);
+ if (ret)
+ return ret;
- err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler,
+ ret = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler,
IRQF_SHARED, counter->name, counter);
- if (err)
- return err;
+ if (ret)
+ return ret;
- err = devm_counter_add(dev, counter);
- if (err < 0)
- return dev_err_probe(dev, err, "Failed to add counter\n");
+ ret = devm_counter_add(dev, counter);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to add counter\n");
return 0;
}
diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig
index 4228be917038..bca21df51168 100644
--- a/drivers/counter/Kconfig
+++ b/drivers/counter/Kconfig
@@ -10,20 +10,37 @@ menuconfig COUNTER
interface. You only need to enable this, if you also want to enable
one or more of the counter device drivers below.
+config I8254
+ tristate
+ select COUNTER
+ select REGMAP
+ help
+ Enables support for the i8254 interface library functions. The i8254
+ interface library provides functions to facilitate communication with
+ interfaces compatible with the venerable Intel 8254 Programmable
+ Interval Timer (PIT). The Intel 825x family of chips was first
+ released in the early 1980s but compatible interfaces are nowadays
+ typically found embedded in larger VLSI processing chips and FPGA
+ components.
+
+ If built as a module its name will be i8254.
+
if COUNTER
config 104_QUAD_8
tristate "ACCES 104-QUAD-8 driver"
depends on (PC104 && X86) || COMPILE_TEST
+ depends on HAS_IOPORT_MAP
select ISA_BUS_API
+ select REGMAP_MMIO
help
Say yes here to build support for the ACCES 104-QUAD-8 quadrature
encoder counter/interface device family (104-QUAD-8, 104-QUAD-4).
A counter's respective error flag may be cleared by performing a write
- operation on the respective count value attribute. Although the
- 104-QUAD-8 counters have a 25-bit range, only the lower 24 bits may be
- set, either directly or via the counter's preset attribute.
+ operation on the respective count value attribute. The 104-QUAD-8
+ counters may be set either directly or via the counter's preset
+ attribute.
The base port addresses for the devices may be configured via the base
array module parameter. The interrupt line numbers for the devices may
diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile
index 933fdd50b3e4..fa3c1d08f706 100644
--- a/drivers/counter/Makefile
+++ b/drivers/counter/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_COUNTER) += counter.o
counter-y := counter-core.o counter-sysfs.o counter-chrdev.o
+obj-$(CONFIG_I8254) += i8254.o
obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o
obj-$(CONFIG_INTERRUPT_CNT) += interrupt-cnt.o
obj-$(CONFIG_RZ_MTU3_CNT) += rz-mtu3-cnt.o
diff --git a/drivers/counter/counter-sysfs.c b/drivers/counter/counter-sysfs.c
index b9efe66f9f8d..42c523343d32 100644
--- a/drivers/counter/counter-sysfs.c
+++ b/drivers/counter/counter-sysfs.c
@@ -88,7 +88,13 @@ static const char *const counter_count_mode_str[] = {
[COUNTER_COUNT_MODE_NORMAL] = "normal",
[COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit",
[COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle",
- [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n"
+ [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n",
+ [COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT] = "interrupt on terminal count",
+ [COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT] = "hardware retriggerable one-shot",
+ [COUNTER_COUNT_MODE_RATE_GENERATOR] = "rate generator",
+ [COUNTER_COUNT_MODE_SQUARE_WAVE_MODE] = "square wave mode",
+ [COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE] = "software triggered strobe",
+ [COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE] = "hardware triggered strobe",
};
static const char *const counter_signal_polarity_str[] = {
diff --git a/drivers/counter/i8254.c b/drivers/counter/i8254.c
new file mode 100644
index 000000000000..c41e4fdc9601
--- /dev/null
+++ b/drivers/counter/i8254.c
@@ -0,0 +1,447 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel 8254 Programmable Interval Timer
+ * Copyright (C) William Breathitt Gray
+ */
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/counter.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/i8254.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+
+#include <asm/unaligned.h>
+
+#define I8254_COUNTER_REG(_counter) (_counter)
+#define I8254_CONTROL_REG 0x3
+
+#define I8254_SC GENMASK(7, 6)
+#define I8254_RW GENMASK(5, 4)
+#define I8254_M GENMASK(3, 1)
+#define I8254_CONTROL(_sc, _rw, _m) \
+ (u8_encode_bits(_sc, I8254_SC) | u8_encode_bits(_rw, I8254_RW) | \
+ u8_encode_bits(_m, I8254_M))
+
+#define I8254_RW_TWO_BYTE 0x3
+#define I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT 0
+#define I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT 1
+#define I8254_MODE_RATE_GENERATOR 2
+#define I8254_MODE_SQUARE_WAVE_MODE 3
+#define I8254_MODE_SOFTWARE_TRIGGERED_STROBE 4
+#define I8254_MODE_HARDWARE_TRIGGERED_STROBE 5
+
+#define I8254_COUNTER_LATCH(_counter) I8254_CONTROL(_counter, 0x0, 0x0)
+#define I8254_PROGRAM_COUNTER(_counter, _mode) I8254_CONTROL(_counter, I8254_RW_TWO_BYTE, _mode)
+
+#define I8254_NUM_COUNTERS 3
+
+/**
+ * struct i8254 - I8254 device private data structure
+ * @lock: synchronization lock to prevent I/O race conditions
+ * @preset: array of Counter Register states
+ * @out_mode: array of mode configuration states
+ * @map: Regmap for the device
+ */
+struct i8254 {
+ struct mutex lock;
+ u16 preset[I8254_NUM_COUNTERS];
+ u8 out_mode[I8254_NUM_COUNTERS];
+ struct regmap *map;
+};
+
+static int i8254_count_read(struct counter_device *const counter, struct counter_count *const count,
+ u64 *const val)
+{
+ struct i8254 *const priv = counter_priv(counter);
+ int ret;
+ u8 value[2];
+
+ mutex_lock(&priv->lock);
+
+ ret = regmap_write(priv->map, I8254_CONTROL_REG, I8254_COUNTER_LATCH(count->id));
+ if (ret) {
+ mutex_unlock(&priv->lock);
+ return ret;
+ }
+ ret = regmap_noinc_read(priv->map, I8254_COUNTER_REG(count->id), value, sizeof(value));
+ if (ret) {
+ mutex_unlock(&priv->lock);
+ return ret;
+ }
+
+ mutex_unlock(&priv->lock);
+
+ *val = get_unaligned_le16(value);
+
+ return ret;
+}
+
+static int i8254_function_read(struct counter_device *const counter,
+ struct counter_count *const count,
+ enum counter_function *const function)
+{
+ *function = COUNTER_FUNCTION_DECREASE;
+ return 0;
+}
+
+#define I8254_SYNAPSES_PER_COUNT 2
+#define I8254_SIGNAL_ID_CLK 0
+#define I8254_SIGNAL_ID_GATE 1
+
+static int i8254_action_read(struct counter_device *const counter,
+ struct counter_count *const count,
+ struct counter_synapse *const synapse,
+ enum counter_synapse_action *const action)
+{
+ struct i8254 *const priv = counter_priv(counter);
+
+ switch (synapse->signal->id % I8254_SYNAPSES_PER_COUNT) {
+ case I8254_SIGNAL_ID_CLK:
+ *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE;
+ return 0;
+ case I8254_SIGNAL_ID_GATE:
+ switch (priv->out_mode[count->id]) {
+ case I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT:
+ case I8254_MODE_RATE_GENERATOR:
+ case I8254_MODE_SQUARE_WAVE_MODE:
+ case I8254_MODE_HARDWARE_TRIGGERED_STROBE:
+ *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
+ return 0;
+ default:
+ *action = COUNTER_SYNAPSE_ACTION_NONE;
+ return 0;
+ }
+ default:
+ /* should never reach this path */
+ return -EINVAL;
+ }
+}
+
+static int i8254_count_ceiling_read(struct counter_device *const counter,
+ struct counter_count *const count, u64 *const ceiling)
+{
+ struct i8254 *const priv = counter_priv(counter);
+
+ mutex_lock(&priv->lock);
+
+ switch (priv->out_mode[count->id]) {
+ case I8254_MODE_RATE_GENERATOR:
+ /* Rate Generator decrements 0 by one and the counter "wraps around" */
+ *ceiling = (priv->preset[count->id] == 0) ? U16_MAX : priv->preset[count->id];
+ break;
+ case I8254_MODE_SQUARE_WAVE_MODE:
+ if (priv->preset[count->id] % 2)
+ *ceiling = priv->preset[count->id] - 1;
+ else if (priv->preset[count->id] == 0)
+ /* Square Wave Mode decrements 0 by two and the counter "wraps around" */
+ *ceiling = U16_MAX - 1;
+ else
+ *ceiling = priv->preset[count->id];
+ break;
+ default:
+ *ceiling = U16_MAX;
+ break;
+ }
+
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int i8254_count_mode_read(struct counter_device *const counter,
+ struct counter_count *const count,
+ enum counter_count_mode *const count_mode)
+{
+ const struct i8254 *const priv = counter_priv(counter);
+
+ switch (priv->out_mode[count->id]) {
+ case I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT:
+ *count_mode = COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT;
+ return 0;
+ case I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT:
+ *count_mode = COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT;
+ return 0;
+ case I8254_MODE_RATE_GENERATOR:
+ *count_mode = COUNTER_COUNT_MODE_RATE_GENERATOR;
+ return 0;
+ case I8254_MODE_SQUARE_WAVE_MODE:
+ *count_mode = COUNTER_COUNT_MODE_SQUARE_WAVE_MODE;
+ return 0;
+ case I8254_MODE_SOFTWARE_TRIGGERED_STROBE:
+ *count_mode = COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE;
+ return 0;
+ case I8254_MODE_HARDWARE_TRIGGERED_STROBE:
+ *count_mode = COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE;
+ return 0;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
+ }
+}
+
+static int i8254_count_mode_write(struct counter_device *const counter,
+ struct counter_count *const count,
+ const enum counter_count_mode count_mode)
+{
+ struct i8254 *const priv = counter_priv(counter);
+ u8 out_mode;
+ int ret;
+
+ switch (count_mode) {
+ case COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT:
+ out_mode = I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT;
+ break;
+ case COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT:
+ out_mode = I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT;
+ break;
+ case COUNTER_COUNT_MODE_RATE_GENERATOR:
+ out_mode = I8254_MODE_RATE_GENERATOR;
+ break;
+ case COUNTER_COUNT_MODE_SQUARE_WAVE_MODE:
+ out_mode = I8254_MODE_SQUARE_WAVE_MODE;
+ break;
+ case COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE:
+ out_mode = I8254_MODE_SOFTWARE_TRIGGERED_STROBE;
+ break;
+ case COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE:
+ out_mode = I8254_MODE_HARDWARE_TRIGGERED_STROBE;
+ break;
+ default:
+ /* should never reach this path */
+ return -EINVAL;
+ }
+
+ mutex_lock(&priv->lock);
+
+ /* Counter Register is cleared when the counter is programmed */
+ priv->preset[count->id] = 0;
+ priv->out_mode[count->id] = out_mode;
+ ret = regmap_write(priv->map, I8254_CONTROL_REG,
+ I8254_PROGRAM_COUNTER(count->id, out_mode));
+
+ mutex_unlock(&priv->lock);
+
+ return ret;
+}
+
+static int i8254_count_floor_read(struct counter_device *const counter,
+ struct counter_count *const count, u64 *const floor)
+{
+ struct i8254 *const priv = counter_priv(counter);
+
+ mutex_lock(&priv->lock);
+
+ switch (priv->out_mode[count->id]) {
+ case I8254_MODE_RATE_GENERATOR:
+ /* counter is always reloaded after 1, but 0 is a possible reload value */
+ *floor = (priv->preset[count->id] == 0) ? 0 : 1;
+ break;
+ case I8254_MODE_SQUARE_WAVE_MODE:
+ /* counter is always reloaded after 2 for even preset values */
+ *floor = (priv->preset[count->id] % 2 || priv->preset[count->id] == 0) ? 0 : 2;
+ break;
+ default:
+ *floor = 0;
+ break;
+ }
+
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int i8254_count_preset_read(struct counter_device *const counter,
+ struct counter_count *const count, u64 *const preset)
+{
+ const struct i8254 *const priv = counter_priv(counter);
+
+ *preset = priv->preset[count->id];
+
+ return 0;
+}
+
+static int i8254_count_preset_write(struct counter_device *const counter,
+ struct counter_count *const count, const u64 preset)
+{
+ struct i8254 *const priv = counter_priv(counter);
+ int ret;
+ u8 value[2];
+
+ if (preset > U16_MAX)
+ return -ERANGE;
+
+ mutex_lock(&priv->lock);
+
+ if (priv->out_mode[count->id] == I8254_MODE_RATE_GENERATOR ||
+ priv->out_mode[count->id] == I8254_MODE_SQUARE_WAVE_MODE) {
+ if (preset == 1) {
+ mutex_unlock(&priv->lock);
+ return -EINVAL;
+ }
+ }
+
+ priv->preset[count->id] = preset;
+
+ put_unaligned_le16(preset, value);
+ ret = regmap_noinc_write(priv->map, I8254_COUNTER_REG(count->id), value, 2);
+
+ mutex_unlock(&priv->lock);
+
+ return ret;
+}
+
+static int i8254_init_hw(struct regmap *const map)
+{
+ unsigned long i;
+ int ret;
+
+ for (i = 0; i < I8254_NUM_COUNTERS; i++) {
+ /* Initialize each counter to Mode 0 */
+ ret = regmap_write(map, I8254_CONTROL_REG,
+ I8254_PROGRAM_COUNTER(i, I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT));
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct counter_ops i8254_ops = {
+ .count_read = i8254_count_read,
+ .function_read = i8254_function_read,
+ .action_read = i8254_action_read,
+};
+
+#define I8254_SIGNAL(_id, _name) { \
+ .id = (_id), \
+ .name = (_name), \
+}
+
+static struct counter_signal i8254_signals[] = {
+ I8254_SIGNAL(0, "CLK 0"), I8254_SIGNAL(1, "GATE 0"),
+ I8254_SIGNAL(2, "CLK 1"), I8254_SIGNAL(3, "GATE 1"),
+ I8254_SIGNAL(4, "CLK 2"), I8254_SIGNAL(5, "GATE 2"),
+};
+
+static const enum counter_synapse_action i8254_clk_actions[] = {
+ COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
+};
+static const enum counter_synapse_action i8254_gate_actions[] = {
+ COUNTER_SYNAPSE_ACTION_NONE,
+ COUNTER_SYNAPSE_ACTION_RISING_EDGE,
+};
+
+#define I8254_SYNAPSES_BASE(_id) ((_id) * I8254_SYNAPSES_PER_COUNT)
+#define I8254_SYNAPSE_CLK(_id) { \
+ .actions_list = i8254_clk_actions, \
+ .num_actions = ARRAY_SIZE(i8254_clk_actions), \
+ .signal = &i8254_signals[I8254_SYNAPSES_BASE(_id) + 0], \
+}
+#define I8254_SYNAPSE_GATE(_id) { \
+ .actions_list = i8254_gate_actions, \
+ .num_actions = ARRAY_SIZE(i8254_gate_actions), \
+ .signal = &i8254_signals[I8254_SYNAPSES_BASE(_id) + 1], \
+}
+
+static struct counter_synapse i8254_synapses[] = {
+ I8254_SYNAPSE_CLK(0), I8254_SYNAPSE_GATE(0),
+ I8254_SYNAPSE_CLK(1), I8254_SYNAPSE_GATE(1),
+ I8254_SYNAPSE_CLK(2), I8254_SYNAPSE_GATE(2),
+};
+
+static const enum counter_function i8254_functions_list[] = {
+ COUNTER_FUNCTION_DECREASE,
+};
+
+static const enum counter_count_mode i8254_count_modes[] = {
+ COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT,
+ COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT,
+ COUNTER_COUNT_MODE_RATE_GENERATOR,
+ COUNTER_COUNT_MODE_SQUARE_WAVE_MODE,
+ COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE,
+ COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE,
+};
+
+static DEFINE_COUNTER_AVAILABLE(i8254_count_modes_available, i8254_count_modes);
+
+static struct counter_comp i8254_count_ext[] = {
+ COUNTER_COMP_CEILING(i8254_count_ceiling_read, NULL),
+ COUNTER_COMP_COUNT_MODE(i8254_count_mode_read, i8254_count_mode_write,
+ i8254_count_modes_available),
+ COUNTER_COMP_FLOOR(i8254_count_floor_read, NULL),
+ COUNTER_COMP_PRESET(i8254_count_preset_read, i8254_count_preset_write),
+};
+
+#define I8254_COUNT(_id, _name) { \
+ .id = (_id), \
+ .name = (_name), \
+ .functions_list = i8254_functions_list, \
+ .num_functions = ARRAY_SIZE(i8254_functions_list), \
+ .synapses = &i8254_synapses[I8254_SYNAPSES_BASE(_id)], \
+ .num_synapses = I8254_SYNAPSES_PER_COUNT, \
+ .ext = i8254_count_ext, \
+ .num_ext = ARRAY_SIZE(i8254_count_ext) \
+}
+
+static struct counter_count i8254_counts[I8254_NUM_COUNTERS] = {
+ I8254_COUNT(0, "Counter 0"), I8254_COUNT(1, "Counter 1"), I8254_COUNT(2, "Counter 2"),
+};
+
+/**
+ * devm_i8254_regmap_register - Register an i8254 Counter device
+ * @dev: device that is registering this i8254 Counter device
+ * @config: configuration for i8254_regmap_config
+ *
+ * Registers an Intel 8254 Programmable Interval Timer Counter device. Returns 0 on success and
+ * negative error number on failure.
+ */
+int devm_i8254_regmap_register(struct device *const dev,
+ const struct i8254_regmap_config *const config)
+{
+ struct counter_device *counter;
+ struct i8254 *priv;
+ int err;
+
+ if (!config->parent)
+ return -EINVAL;
+
+ if (!config->map)
+ return -EINVAL;
+
+ counter = devm_counter_alloc(dev, sizeof(*priv));
+ if (!counter)
+ return -ENOMEM;
+ priv = counter_priv(counter);
+ priv->map = config->map;
+
+ counter->name = dev_name(config->parent);
+ counter->parent = config->parent;
+ counter->ops = &i8254_ops;
+ counter->counts = i8254_counts;
+ counter->num_counts = ARRAY_SIZE(i8254_counts);
+ counter->signals = i8254_signals;
+ counter->num_signals = ARRAY_SIZE(i8254_signals);
+
+ mutex_init(&priv->lock);
+
+ err = i8254_init_hw(priv->map);
+ if (err)
+ return err;
+
+ err = devm_counter_add(dev, counter);
+ if (err < 0)
+ return dev_err_probe(dev, err, "Failed to add counter\n");
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(devm_i8254_regmap_register, I8254);
+
+MODULE_AUTHOR("William Breathitt Gray");
+MODULE_DESCRIPTION("Intel 8254 Programmable Interval Timer");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(COUNTER);
diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c
index 9bf20a5d6bda..6206d2dc3d47 100644
--- a/drivers/counter/stm32-timer-cnt.c
+++ b/drivers/counter/stm32-timer-cnt.c
@@ -342,6 +342,9 @@ static int stm32_timer_cnt_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
+ /* Reset input selector to its default input */
+ regmap_write(priv->regmap, TIM_TISEL, 0x0);
+
/* Register Counter device */
ret = devm_counter_add(dev, counter);
if (ret < 0)
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index a1c51abddbc5..f429b9b37b76 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -218,7 +218,8 @@ config CPUFREQ_DT
If in doubt, say N.
config CPUFREQ_DT_PLATDEV
- bool
+ tristate "Generic DT based cpufreq platdev driver"
+ depends on OF
help
This adds a generic DT based cpufreq platdev driver for frequency
management. This creates a 'cpufreq-dt' platform device, on the
diff --git a/drivers/cpufreq/armada-8k-cpufreq.c b/drivers/cpufreq/armada-8k-cpufreq.c
index b0fc5e84f857..8afefdea4d80 100644
--- a/drivers/cpufreq/armada-8k-cpufreq.c
+++ b/drivers/cpufreq/armada-8k-cpufreq.c
@@ -21,6 +21,13 @@
#include <linux/pm_opp.h>
#include <linux/slab.h>
+static const struct of_device_id __maybe_unused armada_8k_cpufreq_of_match[] = {
+ { .compatible = "marvell,ap806-cpu-clock" },
+ { .compatible = "marvell,ap807-cpu-clock" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, armada_8k_cpufreq_of_match);
+
/*
* Setup the opps list with the divider for the max frequency, that
* will be filled at runtime.
@@ -127,7 +134,8 @@ static int __init armada_8k_cpufreq_init(void)
struct device_node *node;
struct cpumask cpus;
- node = of_find_compatible_node(NULL, NULL, "marvell,ap806-cpu-clock");
+ node = of_find_matching_node_and_match(NULL, armada_8k_cpufreq_of_match,
+ NULL);
if (!node || !of_device_is_available(node)) {
of_node_put(node);
return -ENODEV;
@@ -204,12 +212,6 @@ static void __exit armada_8k_cpufreq_exit(void)
}
module_exit(armada_8k_cpufreq_exit);
-static const struct of_device_id __maybe_unused armada_8k_cpufreq_of_match[] = {
- { .compatible = "marvell,ap806-cpu-clock" },
- { },
-};
-MODULE_DEVICE_TABLE(of, armada_8k_cpufreq_of_match);
-
MODULE_AUTHOR("Gregory Clement <gregory.clement@bootlin.com>");
MODULE_DESCRIPTION("Armada 8K cpufreq driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 338cf6cc6596..e2b20080de3a 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -5,6 +5,7 @@
*/
#include <linux/err.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -85,6 +86,8 @@ static const struct of_device_id allowlist[] __initconst = {
{ .compatible = "st-ericsson,u9500", },
{ .compatible = "st-ericsson,u9540", },
+ { .compatible = "starfive,jh7110", },
+
{ .compatible = "ti,omap2", },
{ .compatible = "ti,omap4", },
{ .compatible = "ti,omap5", },
@@ -165,6 +168,7 @@ static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "ti,dra7", },
{ .compatible = "ti,omap3", },
{ .compatible = "ti,am625", },
+ { .compatible = "ti,am62a7", },
{ .compatible = "qcom,ipq8064", },
{ .compatible = "qcom,apq8064", },
@@ -214,3 +218,4 @@ create_pdev:
sizeof(struct cpufreq_dt_platform_data)));
}
core_initcall(cpufreq_dt_platdev_init);
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 48e1772e98fd..9fb1501033bb 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -209,6 +209,14 @@ static struct cpufreq_driver imx6q_cpufreq_driver = {
.suspend = cpufreq_generic_suspend,
};
+static void imx6x_disable_freq_in_opp(struct device *dev, unsigned long freq)
+{
+ int ret = dev_pm_opp_disable(dev, freq);
+
+ if (ret < 0 && ret != -ENODEV)
+ dev_warn(dev, "failed to disable %ldMHz OPP\n", freq / 1000000);
+}
+
#define OCOTP_CFG3 0x440
#define OCOTP_CFG3_SPEED_SHIFT 16
#define OCOTP_CFG3_SPEED_1P2GHZ 0x3
@@ -254,17 +262,15 @@ static int imx6q_opp_check_speed_grading(struct device *dev)
val &= 0x3;
if (val < OCOTP_CFG3_SPEED_996MHZ)
- if (dev_pm_opp_disable(dev, 996000000))
- dev_warn(dev, "failed to disable 996MHz OPP\n");
+ imx6x_disable_freq_in_opp(dev, 996000000);
if (of_machine_is_compatible("fsl,imx6q") ||
of_machine_is_compatible("fsl,imx6qp")) {
if (val != OCOTP_CFG3_SPEED_852MHZ)
- if (dev_pm_opp_disable(dev, 852000000))
- dev_warn(dev, "failed to disable 852MHz OPP\n");
+ imx6x_disable_freq_in_opp(dev, 852000000);
+
if (val != OCOTP_CFG3_SPEED_1P2GHZ)
- if (dev_pm_opp_disable(dev, 1200000000))
- dev_warn(dev, "failed to disable 1.2GHz OPP\n");
+ imx6x_disable_freq_in_opp(dev, 1200000000);
}
return 0;
@@ -316,20 +322,16 @@ static int imx6ul_opp_check_speed_grading(struct device *dev)
val >>= OCOTP_CFG3_SPEED_SHIFT;
val &= 0x3;
- if (of_machine_is_compatible("fsl,imx6ul")) {
+ if (of_machine_is_compatible("fsl,imx6ul"))
if (val != OCOTP_CFG3_6UL_SPEED_696MHZ)
- if (dev_pm_opp_disable(dev, 696000000))
- dev_warn(dev, "failed to disable 696MHz OPP\n");
- }
+ imx6x_disable_freq_in_opp(dev, 696000000);
if (of_machine_is_compatible("fsl,imx6ull")) {
if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ)
- if (dev_pm_opp_disable(dev, 792000000))
- dev_warn(dev, "failed to disable 792MHz OPP\n");
+ imx6x_disable_freq_in_opp(dev, 792000000);
if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ)
- if (dev_pm_opp_disable(dev, 900000000))
- dev_warn(dev, "failed to disable 900MHz OPP\n");
+ imx6x_disable_freq_in_opp(dev, 900000000);
}
return ret;
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index f29182512b98..8ca2bce4341a 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -302,6 +302,13 @@ static bool hwp_forced __read_mostly;
static struct cpufreq_driver *intel_pstate_driver __read_mostly;
+#define HYBRID_SCALING_FACTOR 78741
+
+static inline int core_get_scaling(void)
+{
+ return 100000;
+}
+
#ifdef CONFIG_ACPI
static bool acpi_ppc;
#endif
@@ -400,6 +407,26 @@ static int intel_pstate_get_cppc_guaranteed(int cpu)
return cppc_perf.nominal_perf;
}
+
+static int intel_pstate_cppc_get_scaling(int cpu)
+{
+ struct cppc_perf_caps cppc_perf;
+ int ret;
+
+ ret = cppc_get_perf_caps(cpu, &cppc_perf);
+
+ /*
+ * If the nominal frequency and the nominal performance are not
+ * zero and the ratio between them is not 100, return the hybrid
+ * scaling factor.
+ */
+ if (!ret && cppc_perf.nominal_perf && cppc_perf.nominal_freq &&
+ cppc_perf.nominal_perf * 100 != cppc_perf.nominal_freq)
+ return HYBRID_SCALING_FACTOR;
+
+ return core_get_scaling();
+}
+
#else /* CONFIG_ACPI_CPPC_LIB */
static inline void intel_pstate_set_itmt_prio(int cpu)
{
@@ -492,6 +519,11 @@ static inline int intel_pstate_get_cppc_guaranteed(int cpu)
{
return -ENOTSUPP;
}
+
+static int intel_pstate_cppc_get_scaling(int cpu)
+{
+ return core_get_scaling();
+}
#endif /* CONFIG_ACPI_CPPC_LIB */
/**
@@ -1897,11 +1929,6 @@ static int core_get_turbo_pstate(int cpu)
return ret;
}
-static inline int core_get_scaling(void)
-{
- return 100000;
-}
-
static u64 core_get_val(struct cpudata *cpudata, int pstate)
{
u64 val;
@@ -1938,16 +1965,28 @@ static void hybrid_get_type(void *data)
*cpu_type = get_this_hybrid_cpu_type();
}
-static int hybrid_get_cpu_scaling(int cpu)
+static int hwp_get_cpu_scaling(int cpu)
{
u8 cpu_type = 0;
smp_call_function_single(cpu, hybrid_get_type, &cpu_type, 1);
/* P-cores have a smaller perf level-to-freqency scaling factor. */
if (cpu_type == 0x40)
- return 78741;
+ return HYBRID_SCALING_FACTOR;
- return core_get_scaling();
+ /* Use default core scaling for E-cores */
+ if (cpu_type == 0x20)
+ return core_get_scaling();
+
+ /*
+ * If reached here, this system is either non-hybrid (like Tiger
+ * Lake) or hybrid-capable (like Alder Lake or Raptor Lake) with
+ * no E cores (in which case CPUID for hybrid support is 0).
+ *
+ * The CPPC nominal_frequency field is 0 for non-hybrid systems,
+ * so the default core scaling will be used for them.
+ */
+ return intel_pstate_cppc_get_scaling(cpu);
}
static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
@@ -3395,8 +3434,7 @@ static int __init intel_pstate_init(void)
if (!default_driver)
default_driver = &intel_pstate;
- if (boot_cpu_has(X86_FEATURE_HYBRID_CPU))
- pstate_funcs.get_cpu_scaling = hybrid_get_cpu_scaling;
+ pstate_funcs.get_cpu_scaling = hwp_get_cpu_scaling;
goto hwp_cpu_matched;
}
diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
index 9a39a7ccfae9..fef68cb2b38f 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -696,9 +696,16 @@ static const struct mtk_cpufreq_platform_data mt2701_platform_data = {
static const struct mtk_cpufreq_platform_data mt7622_platform_data = {
.min_volt_shift = 100000,
.max_volt_shift = 200000,
- .proc_max_volt = 1360000,
+ .proc_max_volt = 1350000,
.sram_min_volt = 0,
- .sram_max_volt = 1360000,
+ .sram_max_volt = 1350000,
+ .ccifreq_supported = false,
+};
+
+static const struct mtk_cpufreq_platform_data mt7623_platform_data = {
+ .min_volt_shift = 100000,
+ .max_volt_shift = 200000,
+ .proc_max_volt = 1300000,
.ccifreq_supported = false,
};
@@ -734,7 +741,7 @@ static const struct of_device_id mtk_cpufreq_machines[] __initconst = {
{ .compatible = "mediatek,mt2701", .data = &mt2701_platform_data },
{ .compatible = "mediatek,mt2712", .data = &mt2701_platform_data },
{ .compatible = "mediatek,mt7622", .data = &mt7622_platform_data },
- { .compatible = "mediatek,mt7623", .data = &mt7622_platform_data },
+ { .compatible = "mediatek,mt7623", .data = &mt7623_platform_data },
{ .compatible = "mediatek,mt8167", .data = &mt8516_platform_data },
{ .compatible = "mediatek,mt817x", .data = &mt2701_platform_data },
{ .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
index a78d7a27b4b5..f2830371d25f 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
@@ -661,7 +661,7 @@ static int qcom_cpufreq_hw_driver_probe(struct platform_device *pdev)
ret = dev_pm_opp_of_find_icc_paths(cpu_dev, NULL);
if (ret)
- return ret;
+ return dev_err_probe(dev, ret, "Failed to find icc paths\n");
for (num_domains = 0; num_domains < MAX_FREQ_DOMAINS; num_domains++)
if (!platform_get_resource(pdev, IORESOURCE_MEM, num_domains))
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index a577586b23be..a88b6fe5db50 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -29,20 +29,7 @@
#include <linux/slab.h>
#include <linux/soc/qcom/smem.h>
-#define MSM_ID_SMEM 137
-
-enum _msm_id {
- MSM8996V3 = 0xF6ul,
- APQ8096V3 = 0x123ul,
- MSM8996SG = 0x131ul,
- APQ8096SG = 0x138ul,
-};
-
-enum _msm8996_version {
- MSM8996_V3,
- MSM8996_SG,
- NUM_OF_MSM8996_VERSIONS,
-};
+#include <dt-bindings/arm/qcom,ids.h>
struct qcom_cpufreq_drv;
@@ -140,60 +127,32 @@ static void get_krait_bin_format_b(struct device *cpu_dev,
dev_dbg(cpu_dev, "PVS version: %d\n", *pvs_ver);
}
-static enum _msm8996_version qcom_cpufreq_get_msm_id(void)
-{
- size_t len;
- u32 *msm_id;
- enum _msm8996_version version;
-
- msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
- if (IS_ERR(msm_id))
- return NUM_OF_MSM8996_VERSIONS;
-
- /* The first 4 bytes are format, next to them is the actual msm-id */
- msm_id++;
-
- switch ((enum _msm_id)*msm_id) {
- case MSM8996V3:
- case APQ8096V3:
- version = MSM8996_V3;
- break;
- case MSM8996SG:
- case APQ8096SG:
- version = MSM8996_SG;
- break;
- default:
- version = NUM_OF_MSM8996_VERSIONS;
- }
-
- return version;
-}
-
static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
struct nvmem_cell *speedbin_nvmem,
char **pvs_name,
struct qcom_cpufreq_drv *drv)
{
size_t len;
+ u32 msm_id;
u8 *speedbin;
- enum _msm8996_version msm8996_version;
+ int ret;
*pvs_name = NULL;
- msm8996_version = qcom_cpufreq_get_msm_id();
- if (NUM_OF_MSM8996_VERSIONS == msm8996_version) {
- dev_err(cpu_dev, "Not Snapdragon 820/821!");
- return -ENODEV;
- }
+ ret = qcom_smem_get_soc_id(&msm_id);
+ if (ret)
+ return ret;
speedbin = nvmem_cell_read(speedbin_nvmem, &len);
if (IS_ERR(speedbin))
return PTR_ERR(speedbin);
- switch (msm8996_version) {
- case MSM8996_V3:
+ switch (msm_id) {
+ case QCOM_ID_MSM8996:
+ case QCOM_ID_APQ8096:
drv->versions = 1 << (unsigned int)(*speedbin);
break;
- case MSM8996_SG:
+ case QCOM_ID_MSM8996SG:
+ case QCOM_ID_APQ8096SG:
drv->versions = 1 << ((unsigned int)(*speedbin) + 4);
break;
default:
diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c
index 92acbb25abb3..d3510cfdb3eb 100644
--- a/drivers/cpufreq/sparc-us2e-cpufreq.c
+++ b/drivers/cpufreq/sparc-us2e-cpufreq.c
@@ -20,8 +20,6 @@
#include <asm/asi.h>
#include <asm/timer.h>
-static struct cpufreq_driver *cpufreq_us2e_driver;
-
struct us2e_freq_percpu_info {
struct cpufreq_frequency_table table[6];
};
@@ -300,12 +298,19 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
static int us2e_freq_cpu_exit(struct cpufreq_policy *policy)
{
- if (cpufreq_us2e_driver)
- us2e_freq_target(policy, 0);
-
+ us2e_freq_target(policy, 0);
return 0;
}
+static struct cpufreq_driver cpufreq_us2e_driver = {
+ .name = "UltraSPARC-IIe",
+ .init = us2e_freq_cpu_init,
+ .verify = cpufreq_generic_frequency_table_verify,
+ .target_index = us2e_freq_target,
+ .get = us2e_freq_get,
+ .exit = us2e_freq_cpu_exit,
+};
+
static int __init us2e_freq_init(void)
{
unsigned long manuf, impl, ver;
@@ -319,39 +324,15 @@ static int __init us2e_freq_init(void)
impl = ((ver >> 32) & 0xffff);
if (manuf == 0x17 && impl == 0x13) {
- struct cpufreq_driver *driver;
-
- ret = -ENOMEM;
- driver = kzalloc(sizeof(*driver), GFP_KERNEL);
- if (!driver)
- goto err_out;
-
- us2e_freq_table = kzalloc((NR_CPUS * sizeof(*us2e_freq_table)),
- GFP_KERNEL);
+ us2e_freq_table = kzalloc(NR_CPUS * sizeof(*us2e_freq_table),
+ GFP_KERNEL);
if (!us2e_freq_table)
- goto err_out;
-
- driver->init = us2e_freq_cpu_init;
- driver->verify = cpufreq_generic_frequency_table_verify;
- driver->target_index = us2e_freq_target;
- driver->get = us2e_freq_get;
- driver->exit = us2e_freq_cpu_exit;
- strcpy(driver->name, "UltraSPARC-IIe");
+ return -ENOMEM;
- cpufreq_us2e_driver = driver;
- ret = cpufreq_register_driver(driver);
+ ret = cpufreq_register_driver(&cpufreq_us2e_driver);
if (ret)
- goto err_out;
+ kfree(us2e_freq_table);
- return 0;
-
-err_out:
- if (driver) {
- kfree(driver);
- cpufreq_us2e_driver = NULL;
- }
- kfree(us2e_freq_table);
- us2e_freq_table = NULL;
return ret;
}
@@ -360,13 +341,8 @@ err_out:
static void __exit us2e_freq_exit(void)
{
- if (cpufreq_us2e_driver) {
- cpufreq_unregister_driver(cpufreq_us2e_driver);
- kfree(cpufreq_us2e_driver);
- cpufreq_us2e_driver = NULL;
- kfree(us2e_freq_table);
- us2e_freq_table = NULL;
- }
+ cpufreq_unregister_driver(&cpufreq_us2e_driver);
+ kfree(us2e_freq_table);
}
MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c
index e41b35b16afd..91d1ed558136 100644
--- a/drivers/cpufreq/sparc-us3-cpufreq.c
+++ b/drivers/cpufreq/sparc-us3-cpufreq.c
@@ -19,8 +19,6 @@
#include <asm/head.h>
#include <asm/timer.h>
-static struct cpufreq_driver *cpufreq_us3_driver;
-
struct us3_freq_percpu_info {
struct cpufreq_frequency_table table[4];
};
@@ -144,12 +142,19 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
{
- if (cpufreq_us3_driver)
- us3_freq_target(policy, 0);
-
+ us3_freq_target(policy, 0);
return 0;
}
+static struct cpufreq_driver cpufreq_us3_driver = {
+ .name = "UltraSPARC-III",
+ .init = us3_freq_cpu_init,
+ .verify = cpufreq_generic_frequency_table_verify,
+ .target_index = us3_freq_target,
+ .get = us3_freq_get,
+ .exit = us3_freq_cpu_exit,
+};
+
static int __init us3_freq_init(void)
{
unsigned long manuf, impl, ver;
@@ -167,39 +172,15 @@ static int __init us3_freq_init(void)
impl == CHEETAH_PLUS_IMPL ||
impl == JAGUAR_IMPL ||
impl == PANTHER_IMPL)) {
- struct cpufreq_driver *driver;
-
- ret = -ENOMEM;
- driver = kzalloc(sizeof(*driver), GFP_KERNEL);
- if (!driver)
- goto err_out;
-
- us3_freq_table = kzalloc((NR_CPUS * sizeof(*us3_freq_table)),
- GFP_KERNEL);
+ us3_freq_table = kzalloc(NR_CPUS * sizeof(*us3_freq_table),
+ GFP_KERNEL);
if (!us3_freq_table)
- goto err_out;
-
- driver->init = us3_freq_cpu_init;
- driver->verify = cpufreq_generic_frequency_table_verify;
- driver->target_index = us3_freq_target;
- driver->get = us3_freq_get;
- driver->exit = us3_freq_cpu_exit;
- strcpy(driver->name, "UltraSPARC-III");
+ return -ENOMEM;
- cpufreq_us3_driver = driver;
- ret = cpufreq_register_driver(driver);
+ ret = cpufreq_register_driver(&cpufreq_us3_driver);
if (ret)
- goto err_out;
+ kfree(us3_freq_table);
- return 0;
-
-err_out:
- if (driver) {
- kfree(driver);
- cpufreq_us3_driver = NULL;
- }
- kfree(us3_freq_table);
- us3_freq_table = NULL;
return ret;
}
@@ -208,13 +189,8 @@ err_out:
static void __exit us3_freq_exit(void)
{
- if (cpufreq_us3_driver) {
- cpufreq_unregister_driver(cpufreq_us3_driver);
- kfree(cpufreq_us3_driver);
- cpufreq_us3_driver = NULL;
- kfree(us3_freq_table);
- us3_freq_table = NULL;
- }
+ cpufreq_unregister_driver(&cpufreq_us3_driver);
+ kfree(us3_freq_table);
}
MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
diff --git a/drivers/cpufreq/tegra194-cpufreq.c b/drivers/cpufreq/tegra194-cpufreq.c
index c8d03346068a..36dad5ea5947 100644
--- a/drivers/cpufreq/tegra194-cpufreq.c
+++ b/drivers/cpufreq/tegra194-cpufreq.c
@@ -686,8 +686,10 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
/* Check for optional OPPv2 and interconnect paths on CPU0 to enable ICC scaling */
cpu_dev = get_cpu_device(0);
- if (!cpu_dev)
- return -EPROBE_DEFER;
+ if (!cpu_dev) {
+ err = -EPROBE_DEFER;
+ goto err_free_res;
+ }
if (dev_pm_opp_of_get_opp_desc_node(cpu_dev)) {
err = dev_pm_opp_of_find_icc_paths(cpu_dev, NULL);
diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
index be4209d97cb3..d5cd2fd25cad 100644
--- a/drivers/cpufreq/ti-cpufreq.c
+++ b/drivers/cpufreq/ti-cpufreq.c
@@ -337,6 +337,7 @@ static const struct of_device_id ti_cpufreq_of_match[] = {
{ .compatible = "ti,omap34xx", .data = &omap34xx_soc_data, },
{ .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, },
{ .compatible = "ti,am625", .data = &am625_soc_data, },
+ { .compatible = "ti,am62a7", .data = &am625_soc_data, },
/* legacy */
{ .compatible = "ti,omap3430", .data = &omap34xx_soc_data, },
{ .compatible = "ti,omap3630", .data = &omap36xx_soc_data, },
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 9c440cd0fed0..9f5b2d28bff5 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -807,5 +807,6 @@ config CRYPTO_DEV_SA2UL
acceleration for cryptographic algorithms on these devices.
source "drivers/crypto/aspeed/Kconfig"
+source "drivers/crypto/starfive/Kconfig"
endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 51d36701e785..d859d6a5f3a4 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -50,3 +50,4 @@ obj-y += xilinx/
obj-y += hisilicon/
obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/
obj-y += intel/
+obj-y += starfive/
diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index aac64b555204..432beabd79e6 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -389,7 +389,7 @@ static struct i2c_driver atmel_ecc_driver = {
.name = "atmel-ecc",
.of_match_table = of_match_ptr(atmel_ecc_dt_ids),
},
- .probe_new = atmel_ecc_probe,
+ .probe = atmel_ecc_probe,
.remove = atmel_ecc_remove,
.id_table = atmel_ecc_id,
};
diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
index 44a185a84760..c77f482d2a97 100644
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -141,7 +141,7 @@ static const struct i2c_device_id atmel_sha204a_id[] = {
MODULE_DEVICE_TABLE(i2c, atmel_sha204a_id);
static struct i2c_driver atmel_sha204a_driver = {
- .probe_new = atmel_sha204a_probe,
+ .probe = atmel_sha204a_probe,
.remove = atmel_sha204a_remove,
.id_table = atmel_sha204a_id,
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index ec6a9e6ad4d2..c631f99e415f 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -162,6 +162,15 @@ config CRYPTO_DEV_FSL_CAAM_PRNG_API
config CRYPTO_DEV_FSL_CAAM_BLOB_GEN
bool
+config CRYPTO_DEV_FSL_CAAM_RNG_TEST
+ bool "Test caam rng"
+ select CRYPTO_DEV_FSL_CAAM_RNG_API
+ help
+ Selecting this will enable a self-test to run for the
+ caam RNG.
+ This test is several minutes long and executes
+ just before the RNG is registered with the hw_random API.
+
endif # CRYPTO_DEV_FSL_CAAM_JR
endif # CRYPTO_DEV_FSL_CAAM
diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
index 5c8d35edaa1c..9156bbe038b7 100644
--- a/drivers/crypto/caam/caamalg_qi2.c
+++ b/drivers/crypto/caam/caamalg_qi2.c
@@ -5402,7 +5402,7 @@ err_dma_mask:
return err;
}
-static int __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev)
+static void __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev)
{
struct device *dev;
struct dpaa2_caam_priv *priv;
@@ -5443,8 +5443,6 @@ static int __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev)
free_percpu(priv->ppriv);
fsl_mc_portal_free(priv->mc_io);
kmem_cache_destroy(qi_cache);
-
- return 0;
}
int dpaa2_caam_enqueue(struct device *dev, struct caam_request *req)
diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
index 50eb55da45c2..b3d14a7f4dd1 100644
--- a/drivers/crypto/caam/caamrng.c
+++ b/drivers/crypto/caam/caamrng.c
@@ -172,6 +172,50 @@ static void caam_cleanup(struct hwrng *rng)
kfifo_free(&ctx->fifo);
}
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST
+static inline void test_len(struct hwrng *rng, size_t len, bool wait)
+{
+ u8 *buf;
+ int read_len;
+ struct caam_rng_ctx *ctx = to_caam_rng_ctx(rng);
+ struct device *dev = ctx->ctrldev;
+
+ buf = kcalloc(CAAM_RNG_MAX_FIFO_STORE_SIZE, sizeof(u8), GFP_KERNEL);
+
+ while (len > 0) {
+ read_len = rng->read(rng, buf, len, wait);
+
+ if (read_len < 0 || (read_len == 0 && wait)) {
+ dev_err(dev, "RNG Read FAILED received %d bytes\n",
+ read_len);
+ kfree(buf);
+ return;
+ }
+
+ print_hex_dump_debug("random bytes@: ",
+ DUMP_PREFIX_ADDRESS, 16, 4,
+ buf, read_len, 1);
+
+ len = len - read_len;
+ }
+
+ kfree(buf);
+}
+
+static inline void test_mode_once(struct hwrng *rng, bool wait)
+{
+ test_len(rng, 32, wait);
+ test_len(rng, 64, wait);
+ test_len(rng, 128, wait);
+}
+
+static void self_test(struct hwrng *rng)
+{
+ pr_info("Executing RNG SELF-TEST with wait\n");
+ test_mode_once(rng, true);
+}
+#endif
+
static int caam_init(struct hwrng *rng)
{
struct caam_rng_ctx *ctx = to_caam_rng_ctx(rng);
@@ -258,6 +302,10 @@ int caam_rng_init(struct device *ctrldev)
return ret;
}
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST
+ self_test(&ctx->rng);
+#endif
+
devres_close_group(ctrldev, caam_rng_init);
return 0;
}
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index bedcc2ab3a00..ff9ddbbca377 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -79,6 +79,15 @@ static void build_deinstantiation_desc(u32 *desc, int handle)
append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
}
+static const struct of_device_id imx8m_machine_match[] = {
+ { .compatible = "fsl,imx8mm", },
+ { .compatible = "fsl,imx8mn", },
+ { .compatible = "fsl,imx8mp", },
+ { .compatible = "fsl,imx8mq", },
+ { .compatible = "fsl,imx8ulp", },
+ { }
+};
+
/*
* run_descriptor_deco0 - runs a descriptor on DECO0, under direct control of
* the software (no JR/QI used).
@@ -105,10 +114,7 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
* Apparently on i.MX8M{Q,M,N,P} it doesn't matter if virt_en == 1
* and the following steps should be performed regardless
*/
- of_machine_is_compatible("fsl,imx8mq") ||
- of_machine_is_compatible("fsl,imx8mm") ||
- of_machine_is_compatible("fsl,imx8mn") ||
- of_machine_is_compatible("fsl,imx8mp")) {
+ of_match_node(imx8m_machine_match, of_root)) {
clrsetbits_32(&ctrl->deco_rsr, 0, DECORSR_JR0);
while (!(rd_reg32(&ctrl->deco_rsr) & DECORSR_VALID) &&
@@ -344,16 +350,15 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
/*
* kick_trng - sets the various parameters for enabling the initialization
* of the RNG4 block in CAAM
- * @pdev - pointer to the platform device
+ * @dev - pointer to the controller device
* @ent_delay - Defines the length (in system clocks) of each entropy sample.
*/
-static void kick_trng(struct platform_device *pdev, int ent_delay)
+static void kick_trng(struct device *dev, int ent_delay)
{
- struct device *ctrldev = &pdev->dev;
- struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
struct caam_ctrl __iomem *ctrl;
struct rng4tst __iomem *r4tst;
- u32 val;
+ u32 val, rtsdctl;
ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
r4tst = &ctrl->r4tst[0];
@@ -369,26 +374,38 @@ static void kick_trng(struct platform_device *pdev, int ent_delay)
* Performance-wise, it does not make sense to
* set the delay to a value that is lower
* than the last one that worked (i.e. the state handles
- * were instantiated properly. Thus, instead of wasting
- * time trying to set the values controlling the sample
- * frequency, the function simply returns.
+ * were instantiated properly).
+ */
+ rtsdctl = rd_reg32(&r4tst->rtsdctl);
+ val = (rtsdctl & RTSDCTL_ENT_DLY_MASK) >> RTSDCTL_ENT_DLY_SHIFT;
+ if (ent_delay > val) {
+ val = ent_delay;
+ /* min. freq. count, equal to 1/4 of the entropy sample length */
+ wr_reg32(&r4tst->rtfrqmin, val >> 2);
+ /* max. freq. count, equal to 16 times the entropy sample length */
+ wr_reg32(&r4tst->rtfrqmax, val << 4);
+ }
+
+ wr_reg32(&r4tst->rtsdctl, (val << RTSDCTL_ENT_DLY_SHIFT) |
+ RTSDCTL_SAMP_SIZE_VAL);
+
+ /*
+ * To avoid reprogramming the self-test parameters over and over again,
+ * use RTSDCTL[SAMP_SIZE] as an indicator.
*/
- val = (rd_reg32(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK)
- >> RTSDCTL_ENT_DLY_SHIFT;
- if (ent_delay <= val)
- goto start_rng;
-
- val = rd_reg32(&r4tst->rtsdctl);
- val = (val & ~RTSDCTL_ENT_DLY_MASK) |
- (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
- wr_reg32(&r4tst->rtsdctl, val);
- /* min. freq. count, equal to 1/4 of the entropy sample length */
- wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2);
- /* disable maximum frequency count */
- wr_reg32(&r4tst->rtfrqmax, RTFRQMAX_DISABLE);
- /* read the control register */
- val = rd_reg32(&r4tst->rtmctl);
-start_rng:
+ if ((rtsdctl & RTSDCTL_SAMP_SIZE_MASK) != RTSDCTL_SAMP_SIZE_VAL) {
+ wr_reg32(&r4tst->rtscmisc, (2 << 16) | 32);
+ wr_reg32(&r4tst->rtpkrrng, 570);
+ wr_reg32(&r4tst->rtpkrmax, 1600);
+ wr_reg32(&r4tst->rtscml, (122 << 16) | 317);
+ wr_reg32(&r4tst->rtscrl[0], (80 << 16) | 107);
+ wr_reg32(&r4tst->rtscrl[1], (57 << 16) | 62);
+ wr_reg32(&r4tst->rtscrl[2], (39 << 16) | 39);
+ wr_reg32(&r4tst->rtscrl[3], (27 << 16) | 26);
+ wr_reg32(&r4tst->rtscrl[4], (19 << 16) | 18);
+ wr_reg32(&r4tst->rtscrl[5], (18 << 16) | 17);
+ }
+
/*
* select raw sampling in both entropy shifter
* and statistical checker; ; put RNG4 into run mode
@@ -618,10 +635,115 @@ static bool needs_entropy_delay_adjustment(void)
return false;
}
+static int caam_ctrl_rng_init(struct device *dev)
+{
+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
+ struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl;
+ int ret, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
+ u8 rng_vid;
+
+ if (ctrlpriv->era < 10) {
+ struct caam_perfmon __iomem *perfmon;
+
+ perfmon = ctrlpriv->total_jobrs ?
+ (struct caam_perfmon __iomem *)&ctrlpriv->jr[0]->perfmon :
+ (struct caam_perfmon __iomem *)&ctrl->perfmon;
+
+ rng_vid = (rd_reg32(&perfmon->cha_id_ls) &
+ CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
+ } else {
+ struct version_regs __iomem *vreg;
+
+ vreg = ctrlpriv->total_jobrs ?
+ (struct version_regs __iomem *)&ctrlpriv->jr[0]->vreg :
+ (struct version_regs __iomem *)&ctrl->vreg;
+
+ rng_vid = (rd_reg32(&vreg->rng) & CHA_VER_VID_MASK) >>
+ CHA_VER_VID_SHIFT;
+ }
+
+ /*
+ * If SEC has RNG version >= 4 and RNG state handle has not been
+ * already instantiated, do RNG instantiation
+ * In case of SoCs with Management Complex, RNG is managed by MC f/w.
+ */
+ if (!(ctrlpriv->mc_en && ctrlpriv->pr_support) && rng_vid >= 4) {
+ ctrlpriv->rng4_sh_init =
+ rd_reg32(&ctrl->r4tst[0].rdsta);
+ /*
+ * If the secure keys (TDKEK, JDKEK, TDSK), were already
+ * generated, signal this to the function that is instantiating
+ * the state handles. An error would occur if RNG4 attempts
+ * to regenerate these keys before the next POR.
+ */
+ gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1;
+ ctrlpriv->rng4_sh_init &= RDSTA_MASK;
+ do {
+ int inst_handles =
+ rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_MASK;
+ /*
+ * If either SH were instantiated by somebody else
+ * (e.g. u-boot) then it is assumed that the entropy
+ * parameters are properly set and thus the function
+ * setting these (kick_trng(...)) is skipped.
+ * Also, if a handle was instantiated, do not change
+ * the TRNG parameters.
+ */
+ if (needs_entropy_delay_adjustment())
+ ent_delay = 12000;
+ if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
+ dev_info(dev,
+ "Entropy delay = %u\n",
+ ent_delay);
+ kick_trng(dev, ent_delay);
+ ent_delay += 400;
+ }
+ /*
+ * if instantiate_rng(...) fails, the loop will rerun
+ * and the kick_trng(...) function will modify the
+ * upper and lower limits of the entropy sampling
+ * interval, leading to a successful initialization of
+ * the RNG.
+ */
+ ret = instantiate_rng(dev, inst_handles,
+ gen_sk);
+ /*
+ * Entropy delay is determined via TRNG characterization.
+ * TRNG characterization is run across different voltages
+ * and temperatures.
+ * If worst case value for ent_dly is identified,
+ * the loop can be skipped for that platform.
+ */
+ if (needs_entropy_delay_adjustment())
+ break;
+ if (ret == -EAGAIN)
+ /*
+ * if here, the loop will rerun,
+ * so don't hog the CPU
+ */
+ cpu_relax();
+ } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
+ if (ret) {
+ dev_err(dev, "failed to instantiate RNG");
+ return ret;
+ }
+ /*
+ * Set handles initialized by this module as the complement of
+ * the already initialized ones
+ */
+ ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_MASK;
+
+ /* Enable RDB bit so that RNG works faster */
+ clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
+ }
+
+ return 0;
+}
+
/* Probe routine for CAAM top (controller) level */
static int caam_probe(struct platform_device *pdev)
{
- int ret, ring, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
+ int ret, ring;
u64 caam_id;
const struct soc_device_attribute *imx_soc_match;
struct device *dev;
@@ -631,10 +753,8 @@ static int caam_probe(struct platform_device *pdev)
struct caam_perfmon __iomem *perfmon;
struct dentry *dfs_root;
u32 scfgr, comp_params;
- u8 rng_vid;
int pg_size;
int BLOCK_OFFSET = 0;
- bool pr_support = false;
bool reg_access = true;
ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(*ctrlpriv), GFP_KERNEL);
@@ -646,6 +766,9 @@ static int caam_probe(struct platform_device *pdev)
nprop = pdev->dev.of_node;
imx_soc_match = soc_device_match(caam_imx_soc_table);
+ if (!imx_soc_match && of_match_node(imx8m_machine_match, of_root))
+ return -EPROBE_DEFER;
+
caam_imx = (bool)imx_soc_match;
if (imx_soc_match) {
@@ -770,7 +893,8 @@ static int caam_probe(struct platform_device *pdev)
mc_version = fsl_mc_get_version();
if (mc_version)
- pr_support = check_version(mc_version, 10, 20, 0);
+ ctrlpriv->pr_support = check_version(mc_version, 10, 20,
+ 0);
else
return -EPROBE_DEFER;
}
@@ -861,9 +985,6 @@ set_dma_mask:
return -ENOMEM;
}
- if (!reg_access)
- goto report_live;
-
comp_params = rd_reg32(&perfmon->comp_parms_ls);
ctrlpriv->blob_present = !!(comp_params & CTPR_LS_BLOB);
@@ -873,8 +994,6 @@ set_dma_mask:
* check both here.
*/
if (ctrlpriv->era < 10) {
- rng_vid = (rd_reg32(&perfmon->cha_id_ls) &
- CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
ctrlpriv->blob_present = ctrlpriv->blob_present &&
(rd_reg32(&perfmon->cha_num_ls) & CHA_ID_LS_AES_MASK);
} else {
@@ -884,91 +1003,16 @@ set_dma_mask:
(struct version_regs __iomem *)&ctrlpriv->jr[0]->vreg :
(struct version_regs __iomem *)&ctrl->vreg;
- rng_vid = (rd_reg32(&vreg->rng) & CHA_VER_VID_MASK) >>
- CHA_VER_VID_SHIFT;
ctrlpriv->blob_present = ctrlpriv->blob_present &&
(rd_reg32(&vreg->aesa) & CHA_VER_MISC_AES_NUM_MASK);
}
- /*
- * If SEC has RNG version >= 4 and RNG state handle has not been
- * already instantiated, do RNG instantiation
- * In case of SoCs with Management Complex, RNG is managed by MC f/w.
- */
- if (!(ctrlpriv->mc_en && pr_support) && rng_vid >= 4) {
- ctrlpriv->rng4_sh_init =
- rd_reg32(&ctrl->r4tst[0].rdsta);
- /*
- * If the secure keys (TDKEK, JDKEK, TDSK), were already
- * generated, signal this to the function that is instantiating
- * the state handles. An error would occur if RNG4 attempts
- * to regenerate these keys before the next POR.
- */
- gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1;
- ctrlpriv->rng4_sh_init &= RDSTA_MASK;
- do {
- int inst_handles =
- rd_reg32(&ctrl->r4tst[0].rdsta) &
- RDSTA_MASK;
- /*
- * If either SH were instantiated by somebody else
- * (e.g. u-boot) then it is assumed that the entropy
- * parameters are properly set and thus the function
- * setting these (kick_trng(...)) is skipped.
- * Also, if a handle was instantiated, do not change
- * the TRNG parameters.
- */
- if (needs_entropy_delay_adjustment())
- ent_delay = 12000;
- if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
- dev_info(dev,
- "Entropy delay = %u\n",
- ent_delay);
- kick_trng(pdev, ent_delay);
- ent_delay += 400;
- }
- /*
- * if instantiate_rng(...) fails, the loop will rerun
- * and the kick_trng(...) function will modify the
- * upper and lower limits of the entropy sampling
- * interval, leading to a successful initialization of
- * the RNG.
- */
- ret = instantiate_rng(dev, inst_handles,
- gen_sk);
- /*
- * Entropy delay is determined via TRNG characterization.
- * TRNG characterization is run across different voltages
- * and temperatures.
- * If worst case value for ent_dly is identified,
- * the loop can be skipped for that platform.
- */
- if (needs_entropy_delay_adjustment())
- break;
- if (ret == -EAGAIN)
- /*
- * if here, the loop will rerun,
- * so don't hog the CPU
- */
- cpu_relax();
- } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
- if (ret) {
- dev_err(dev, "failed to instantiate RNG");
+ if (reg_access) {
+ ret = caam_ctrl_rng_init(dev);
+ if (ret)
return ret;
- }
- /*
- * Set handles initialized by this module as the complement of
- * the already initialized ones
- */
- ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_MASK;
-
- /* Enable RDB bit so that RNG works faster */
- clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
}
-report_live:
- /* NOTE: RTIC detection ought to go here, around Si time */
-
caam_id = (u64)rd_reg32(&perfmon->caam_id_ms) << 32 |
(u64)rd_reg32(&perfmon->caam_id_ls);
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 86ed1b91c22d..b4f7bf77f487 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -95,6 +95,7 @@ struct caam_drv_private {
u8 blob_present; /* Nonzero if BLOB support present in device */
u8 mc_en; /* Nonzero if MC f/w is active */
u8 optee_en; /* Nonzero if OP-TEE f/w is active */
+ bool pr_support; /* RNG prediction resistance available */
int secvio_irq; /* Security violation interrupt number */
int virt_en; /* Virtualization enabled in CAAM */
int era; /* CAAM Era (internal HW revision) */
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 66928f8a0c4b..189e74c21f0c 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -3,7 +3,7 @@
* CAAM hardware register-level view
*
* Copyright 2008-2011 Freescale Semiconductor, Inc.
- * Copyright 2018 NXP
+ * Copyright 2018, 2023 NXP
*/
#ifndef REGS_H
@@ -523,6 +523,8 @@ struct rng4tst {
#define RTSDCTL_ENT_DLY_MASK (0xffff << RTSDCTL_ENT_DLY_SHIFT)
#define RTSDCTL_ENT_DLY_MIN 3200
#define RTSDCTL_ENT_DLY_MAX 12800
+#define RTSDCTL_SAMP_SIZE_MASK 0xffff
+#define RTSDCTL_SAMP_SIZE_VAL 512
u32 rtsdctl; /* seed control register */
union {
u32 rtsblim; /* PRGM=1: sparse bit limit register */
@@ -534,7 +536,15 @@ struct rng4tst {
u32 rtfrqmax; /* PRGM=1: freq. count max. limit register */
u32 rtfrqcnt; /* PRGM=0: freq. count register */
};
- u32 rsvd1[40];
+ union {
+ u32 rtscmc; /* statistical check run monobit count */
+ u32 rtscml; /* statistical check run monobit limit */
+ };
+ union {
+ u32 rtscrc[6]; /* statistical check run length count */
+ u32 rtscrl[6]; /* statistical check run length limit */
+ };
+ u32 rsvd1[33];
#define RDSTA_SKVT 0x80000000
#define RDSTA_SKVN 0x40000000
#define RDSTA_PR0 BIT(4)
diff --git a/drivers/crypto/ccp/platform-access.c b/drivers/crypto/ccp/platform-access.c
index 939c924fc383..94367bc49e35 100644
--- a/drivers/crypto/ccp/platform-access.c
+++ b/drivers/crypto/ccp/platform-access.c
@@ -67,6 +67,11 @@ int psp_send_platform_access_msg(enum psp_platform_access_msg msg,
return -ENODEV;
pa_dev = psp->platform_access_data;
+
+ if (!pa_dev->vdata->cmdresp_reg || !pa_dev->vdata->cmdbuff_addr_lo_reg ||
+ !pa_dev->vdata->cmdbuff_addr_hi_reg)
+ return -ENODEV;
+
cmd = psp->io_regs + pa_dev->vdata->cmdresp_reg;
lo = psp->io_regs + pa_dev->vdata->cmdbuff_addr_lo_reg;
hi = psp->io_regs + pa_dev->vdata->cmdbuff_addr_hi_reg;
diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
index aa15bc4cac2b..b603ad9b8341 100644
--- a/drivers/crypto/ccp/sp-pci.c
+++ b/drivers/crypto/ccp/sp-pci.c
@@ -361,6 +361,14 @@ static const struct tee_vdata teev1 = {
.ring_rptr_reg = 0x10554, /* C2PMSG_21 */
};
+static const struct tee_vdata teev2 = {
+ .cmdresp_reg = 0x10944, /* C2PMSG_17 */
+ .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */
+ .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */
+ .ring_wptr_reg = 0x10950, /* C2PMSG_20 */
+ .ring_rptr_reg = 0x10954, /* C2PMSG_21 */
+};
+
static const struct platform_access_vdata pa_v1 = {
.cmdresp_reg = 0x10570, /* C2PMSG_28 */
.cmdbuff_addr_lo_reg = 0x10574, /* C2PMSG_29 */
@@ -369,6 +377,11 @@ static const struct platform_access_vdata pa_v1 = {
.doorbell_cmd_reg = 0x10a40, /* C2PMSG_80 */
};
+static const struct platform_access_vdata pa_v2 = {
+ .doorbell_button_reg = 0x10a24, /* C2PMSG_73 */
+ .doorbell_cmd_reg = 0x10a40, /* C2PMSG_80 */
+};
+
static const struct psp_vdata pspv1 = {
.sev = &sevv1,
.feature_reg = 0x105fc, /* C2PMSG_63 */
@@ -399,6 +412,22 @@ static const struct psp_vdata pspv4 = {
.intsts_reg = 0x10694, /* P2CMSG_INTSTS */
};
+static const struct psp_vdata pspv5 = {
+ .tee = &teev2,
+ .platform_access = &pa_v2,
+ .feature_reg = 0x109fc, /* C2PMSG_63 */
+ .inten_reg = 0x10510, /* P2CMSG_INTEN */
+ .intsts_reg = 0x10514, /* P2CMSG_INTSTS */
+};
+
+static const struct psp_vdata pspv6 = {
+ .sev = &sevv2,
+ .tee = &teev2,
+ .feature_reg = 0x109fc, /* C2PMSG_63 */
+ .inten_reg = 0x10510, /* P2CMSG_INTEN */
+ .intsts_reg = 0x10514, /* P2CMSG_INTSTS */
+};
+
#endif
static const struct sp_dev_vdata dev_vdata[] = {
@@ -453,6 +482,18 @@ static const struct sp_dev_vdata dev_vdata[] = {
.psp_vdata = &pspv3,
#endif
},
+ { /* 7 */
+ .bar = 2,
+#ifdef CONFIG_CRYPTO_DEV_SP_PSP
+ .psp_vdata = &pspv5,
+#endif
+ },
+ { /* 8 */
+ .bar = 2,
+#ifdef CONFIG_CRYPTO_DEV_SP_PSP
+ .psp_vdata = &pspv6,
+#endif
+ },
};
static const struct pci_device_id sp_pci_table[] = {
{ PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&dev_vdata[0] },
@@ -463,6 +504,8 @@ static const struct pci_device_id sp_pci_table[] = {
{ PCI_VDEVICE(AMD, 0x14CA), (kernel_ulong_t)&dev_vdata[5] },
{ PCI_VDEVICE(AMD, 0x15C7), (kernel_ulong_t)&dev_vdata[6] },
{ PCI_VDEVICE(AMD, 0x1649), (kernel_ulong_t)&dev_vdata[6] },
+ { PCI_VDEVICE(AMD, 0x17E0), (kernel_ulong_t)&dev_vdata[7] },
+ { PCI_VDEVICE(AMD, 0x156E), (kernel_ulong_t)&dev_vdata[8] },
/* Last entry must be zero */
{ 0, }
};
diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig
index e8690c223584..4137a8bf131f 100644
--- a/drivers/crypto/hisilicon/Kconfig
+++ b/drivers/crypto/hisilicon/Kconfig
@@ -82,10 +82,3 @@ config CRYPTO_DEV_HISI_TRNG
select CRYPTO_RNG
help
Support for HiSilicon TRNG Driver.
-
-config CRYPTO_DEV_HISTB_TRNG
- tristate "Support for HiSTB TRNG Driver"
- depends on ARCH_HISI || COMPILE_TEST
- select HW_RANDOM
- help
- Support for HiSTB TRNG Driver.
diff --git a/drivers/crypto/hisilicon/Makefile b/drivers/crypto/hisilicon/Makefile
index fc51e0edec69..8595a5a5d228 100644
--- a/drivers/crypto/hisilicon/Makefile
+++ b/drivers/crypto/hisilicon/Makefile
@@ -5,4 +5,4 @@ obj-$(CONFIG_CRYPTO_DEV_HISI_SEC2) += sec2/
obj-$(CONFIG_CRYPTO_DEV_HISI_QM) += hisi_qm.o
hisi_qm-objs = qm.o sgl.o debugfs.o
obj-$(CONFIG_CRYPTO_DEV_HISI_ZIP) += zip/
-obj-y += trng/
+obj-$(CONFIG_CRYPTO_DEV_HISI_TRNG) += trng/
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
index ad0c042b5e66..edc6fd44e7ca 100644
--- a/drivers/crypto/hisilicon/qm.c
+++ b/drivers/crypto/hisilicon/qm.c
@@ -610,7 +610,10 @@ EXPORT_SYMBOL_GPL(hisi_qm_wait_mb_ready);
static void qm_mb_write(struct hisi_qm *qm, const void *src)
{
void __iomem *fun_base = qm->io_base + QM_MB_CMD_SEND_BASE;
+
+#if IS_ENABLED(CONFIG_ARM64)
unsigned long tmp0 = 0, tmp1 = 0;
+#endif
if (!IS_ENABLED(CONFIG_ARM64)) {
memcpy_toio(fun_base, src, 16);
@@ -618,6 +621,7 @@ static void qm_mb_write(struct hisi_qm *qm, const void *src)
return;
}
+#if IS_ENABLED(CONFIG_ARM64)
asm volatile("ldp %0, %1, %3\n"
"stp %0, %1, %2\n"
"dmb oshst\n"
@@ -626,6 +630,7 @@ static void qm_mb_write(struct hisi_qm *qm, const void *src)
"+Q" (*((char __iomem *)fun_base))
: "Q" (*((char *)src))
: "memory");
+#endif
}
static int qm_mb_nolock(struct hisi_qm *qm, struct qm_mailbox *mailbox)
diff --git a/drivers/crypto/hisilicon/trng/Makefile b/drivers/crypto/hisilicon/trng/Makefile
index cf20b057c66b..d909079f351c 100644
--- a/drivers/crypto/hisilicon/trng/Makefile
+++ b/drivers/crypto/hisilicon/trng/Makefile
@@ -1,5 +1,2 @@
obj-$(CONFIG_CRYPTO_DEV_HISI_TRNG) += hisi-trng-v2.o
hisi-trng-v2-objs = trng.o
-
-obj-$(CONFIG_CRYPTO_DEV_HISTB_TRNG) += histb-trng.o
-histb-trng-objs += trng-stb.o
diff --git a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
index ed15379a9818..4a18095ae5d8 100644
--- a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
+++ b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
@@ -1175,9 +1175,9 @@ static int aead_perform(struct aead_request *req, int encrypt,
/* The 12 hmac bytes are scattered,
* we need to copy them into a safe buffer */
req_ctx->hmac_virt = dma_pool_alloc(buffer_pool, flags, &dma);
- crypt->icv_rev_aes = dma;
if (unlikely(!req_ctx->hmac_virt))
goto free_buf_dst;
+ crypt->icv_rev_aes = dma;
if (!encrypt) {
scatterwalk_map_and_copy(req_ctx->hmac_virt,
req->src, cryptlen, authsize, 0);
diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
index 7324b86a4f40..e543a9e24a06 100644
--- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
+++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
@@ -11,37 +11,76 @@
#include "adf_4xxx_hw_data.h"
#include "icp_qat_hw.h"
+enum adf_fw_objs {
+ ADF_FW_SYM_OBJ,
+ ADF_FW_ASYM_OBJ,
+ ADF_FW_DC_OBJ,
+ ADF_FW_ADMIN_OBJ,
+};
+
+static const char * const adf_4xxx_fw_objs[] = {
+ [ADF_FW_SYM_OBJ] = ADF_4XXX_SYM_OBJ,
+ [ADF_FW_ASYM_OBJ] = ADF_4XXX_ASYM_OBJ,
+ [ADF_FW_DC_OBJ] = ADF_4XXX_DC_OBJ,
+ [ADF_FW_ADMIN_OBJ] = ADF_4XXX_ADMIN_OBJ,
+};
+
+static const char * const adf_402xx_fw_objs[] = {
+ [ADF_FW_SYM_OBJ] = ADF_402XX_SYM_OBJ,
+ [ADF_FW_ASYM_OBJ] = ADF_402XX_ASYM_OBJ,
+ [ADF_FW_DC_OBJ] = ADF_402XX_DC_OBJ,
+ [ADF_FW_ADMIN_OBJ] = ADF_402XX_ADMIN_OBJ,
+};
+
struct adf_fw_config {
u32 ae_mask;
- char *obj_name;
+ enum adf_fw_objs obj;
};
-static struct adf_fw_config adf_4xxx_fw_cy_config[] = {
- {0xF0, ADF_4XXX_SYM_OBJ},
- {0xF, ADF_4XXX_ASYM_OBJ},
- {0x100, ADF_4XXX_ADMIN_OBJ},
+static const struct adf_fw_config adf_fw_cy_config[] = {
+ {0xF0, ADF_FW_SYM_OBJ},
+ {0xF, ADF_FW_ASYM_OBJ},
+ {0x100, ADF_FW_ADMIN_OBJ},
};
-static struct adf_fw_config adf_4xxx_fw_dc_config[] = {
- {0xF0, ADF_4XXX_DC_OBJ},
- {0xF, ADF_4XXX_DC_OBJ},
- {0x100, ADF_4XXX_ADMIN_OBJ},
+static const struct adf_fw_config adf_fw_dc_config[] = {
+ {0xF0, ADF_FW_DC_OBJ},
+ {0xF, ADF_FW_DC_OBJ},
+ {0x100, ADF_FW_ADMIN_OBJ},
};
-static struct adf_fw_config adf_402xx_fw_cy_config[] = {
- {0xF0, ADF_402XX_SYM_OBJ},
- {0xF, ADF_402XX_ASYM_OBJ},
- {0x100, ADF_402XX_ADMIN_OBJ},
+static const struct adf_fw_config adf_fw_sym_config[] = {
+ {0xF0, ADF_FW_SYM_OBJ},
+ {0xF, ADF_FW_SYM_OBJ},
+ {0x100, ADF_FW_ADMIN_OBJ},
};
-static struct adf_fw_config adf_402xx_fw_dc_config[] = {
- {0xF0, ADF_402XX_DC_OBJ},
- {0xF, ADF_402XX_DC_OBJ},
- {0x100, ADF_402XX_ADMIN_OBJ},
+static const struct adf_fw_config adf_fw_asym_config[] = {
+ {0xF0, ADF_FW_ASYM_OBJ},
+ {0xF, ADF_FW_ASYM_OBJ},
+ {0x100, ADF_FW_ADMIN_OBJ},
};
+static const struct adf_fw_config adf_fw_asym_dc_config[] = {
+ {0xF0, ADF_FW_ASYM_OBJ},
+ {0xF, ADF_FW_DC_OBJ},
+ {0x100, ADF_FW_ADMIN_OBJ},
+};
+
+static const struct adf_fw_config adf_fw_sym_dc_config[] = {
+ {0xF0, ADF_FW_SYM_OBJ},
+ {0xF, ADF_FW_DC_OBJ},
+ {0x100, ADF_FW_ADMIN_OBJ},
+};
+
+static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_dc_config));
+static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_sym_config));
+static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_asym_config));
+static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_asym_dc_config));
+static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_sym_dc_config));
+
/* Worker thread to service arbiter mappings */
-static const u32 thrd_to_arb_map_cy[ADF_4XXX_MAX_ACCELENGINES] = {
+static const u32 default_thrd_to_arb_map[ADF_4XXX_MAX_ACCELENGINES] = {
0x5555555, 0x5555555, 0x5555555, 0x5555555,
0xAAAAAAA, 0xAAAAAAA, 0xAAAAAAA, 0xAAAAAAA,
0x0
@@ -61,12 +100,26 @@ static struct adf_hw_device_class adf_4xxx_class = {
enum dev_services {
SVC_CY = 0,
+ SVC_CY2,
SVC_DC,
+ SVC_SYM,
+ SVC_ASYM,
+ SVC_DC_ASYM,
+ SVC_ASYM_DC,
+ SVC_DC_SYM,
+ SVC_SYM_DC,
};
static const char *const dev_cfg_services[] = {
[SVC_CY] = ADF_CFG_CY,
+ [SVC_CY2] = ADF_CFG_ASYM_SYM,
[SVC_DC] = ADF_CFG_DC,
+ [SVC_SYM] = ADF_CFG_SYM,
+ [SVC_ASYM] = ADF_CFG_ASYM,
+ [SVC_DC_ASYM] = ADF_CFG_DC_ASYM,
+ [SVC_ASYM_DC] = ADF_CFG_ASYM_DC,
+ [SVC_DC_SYM] = ADF_CFG_DC_SYM,
+ [SVC_SYM_DC] = ADF_CFG_SYM_DC,
};
static int get_service_enabled(struct adf_accel_dev *accel_dev)
@@ -156,45 +209,50 @@ static void set_msix_default_rttable(struct adf_accel_dev *accel_dev)
static u32 get_accel_cap(struct adf_accel_dev *accel_dev)
{
struct pci_dev *pdev = accel_dev->accel_pci_dev.pci_dev;
- u32 capabilities_cy, capabilities_dc;
+ u32 capabilities_sym, capabilities_asym, capabilities_dc;
u32 fusectl1;
/* Read accelerator capabilities mask */
pci_read_config_dword(pdev, ADF_4XXX_FUSECTL1_OFFSET, &fusectl1);
- capabilities_cy = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC |
- ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC |
+ capabilities_sym = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC |
ICP_ACCEL_CAPABILITIES_CIPHER |
ICP_ACCEL_CAPABILITIES_AUTHENTICATION |
ICP_ACCEL_CAPABILITIES_SHA3 |
ICP_ACCEL_CAPABILITIES_SHA3_EXT |
ICP_ACCEL_CAPABILITIES_HKDF |
- ICP_ACCEL_CAPABILITIES_ECEDMONT |
ICP_ACCEL_CAPABILITIES_CHACHA_POLY |
ICP_ACCEL_CAPABILITIES_AESGCM_SPC |
ICP_ACCEL_CAPABILITIES_AES_V2;
/* A set bit in fusectl1 means the feature is OFF in this SKU */
if (fusectl1 & ICP_ACCEL_4XXX_MASK_CIPHER_SLICE) {
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC;
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_HKDF;
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CIPHER;
+ capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC;
+ capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_HKDF;
+ capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CIPHER;
}
+
if (fusectl1 & ICP_ACCEL_4XXX_MASK_UCS_SLICE) {
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CHACHA_POLY;
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_AESGCM_SPC;
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_AES_V2;
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CIPHER;
+ capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CHACHA_POLY;
+ capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_AESGCM_SPC;
+ capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_AES_V2;
+ capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CIPHER;
}
+
if (fusectl1 & ICP_ACCEL_4XXX_MASK_AUTH_SLICE) {
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION;
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_SHA3;
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_SHA3_EXT;
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CIPHER;
+ capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION;
+ capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_SHA3;
+ capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_SHA3_EXT;
+ capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CIPHER;
}
+
+ capabilities_asym = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC |
+ ICP_ACCEL_CAPABILITIES_CIPHER |
+ ICP_ACCEL_CAPABILITIES_ECEDMONT;
+
if (fusectl1 & ICP_ACCEL_4XXX_MASK_PKE_SLICE) {
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC;
- capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_ECEDMONT;
+ capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC;
+ capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_ECEDMONT;
}
capabilities_dc = ICP_ACCEL_CAPABILITIES_COMPRESSION |
@@ -211,12 +269,23 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev)
switch (get_service_enabled(accel_dev)) {
case SVC_CY:
- return capabilities_cy;
+ case SVC_CY2:
+ return capabilities_sym | capabilities_asym;
case SVC_DC:
return capabilities_dc;
+ case SVC_SYM:
+ return capabilities_sym;
+ case SVC_ASYM:
+ return capabilities_asym;
+ case SVC_ASYM_DC:
+ case SVC_DC_ASYM:
+ return capabilities_asym | capabilities_dc;
+ case SVC_SYM_DC:
+ case SVC_DC_SYM:
+ return capabilities_sym | capabilities_dc;
+ default:
+ return 0;
}
-
- return 0;
}
static enum dev_sku_info get_sku(struct adf_hw_device_data *self)
@@ -227,13 +296,11 @@ static enum dev_sku_info get_sku(struct adf_hw_device_data *self)
static const u32 *adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev)
{
switch (get_service_enabled(accel_dev)) {
- case SVC_CY:
- return thrd_to_arb_map_cy;
case SVC_DC:
return thrd_to_arb_map_dc;
+ default:
+ return default_thrd_to_arb_map;
}
-
- return NULL;
}
static void get_arb_info(struct arb_info *arb_info)
@@ -304,47 +371,83 @@ static int adf_init_device(struct adf_accel_dev *accel_dev)
static u32 uof_get_num_objs(void)
{
- BUILD_BUG_ON_MSG(ARRAY_SIZE(adf_4xxx_fw_cy_config) !=
- ARRAY_SIZE(adf_4xxx_fw_dc_config),
- "Size mismatch between adf_4xxx_fw_*_config arrays");
-
- return ARRAY_SIZE(adf_4xxx_fw_cy_config);
+ return ARRAY_SIZE(adf_fw_cy_config);
}
-static char *uof_get_name_4xxx(struct adf_accel_dev *accel_dev, u32 obj_num)
+static const char *uof_get_name(struct adf_accel_dev *accel_dev, u32 obj_num,
+ const char * const fw_objs[], int num_objs)
{
+ int id;
+
switch (get_service_enabled(accel_dev)) {
case SVC_CY:
- return adf_4xxx_fw_cy_config[obj_num].obj_name;
+ case SVC_CY2:
+ id = adf_fw_cy_config[obj_num].obj;
+ break;
case SVC_DC:
- return adf_4xxx_fw_dc_config[obj_num].obj_name;
+ id = adf_fw_dc_config[obj_num].obj;
+ break;
+ case SVC_SYM:
+ id = adf_fw_sym_config[obj_num].obj;
+ break;
+ case SVC_ASYM:
+ id = adf_fw_asym_config[obj_num].obj;
+ break;
+ case SVC_ASYM_DC:
+ case SVC_DC_ASYM:
+ id = adf_fw_asym_dc_config[obj_num].obj;
+ break;
+ case SVC_SYM_DC:
+ case SVC_DC_SYM:
+ id = adf_fw_sym_dc_config[obj_num].obj;
+ break;
+ default:
+ id = -EINVAL;
+ break;
}
- return NULL;
+ if (id < 0 || id > num_objs)
+ return NULL;
+
+ return fw_objs[id];
}
-static char *uof_get_name_402xx(struct adf_accel_dev *accel_dev, u32 obj_num)
+static const char *uof_get_name_4xxx(struct adf_accel_dev *accel_dev, u32 obj_num)
{
- switch (get_service_enabled(accel_dev)) {
- case SVC_CY:
- return adf_402xx_fw_cy_config[obj_num].obj_name;
- case SVC_DC:
- return adf_402xx_fw_dc_config[obj_num].obj_name;
- }
+ int num_fw_objs = ARRAY_SIZE(adf_4xxx_fw_objs);
- return NULL;
+ return uof_get_name(accel_dev, obj_num, adf_4xxx_fw_objs, num_fw_objs);
+}
+
+static const char *uof_get_name_402xx(struct adf_accel_dev *accel_dev, u32 obj_num)
+{
+ int num_fw_objs = ARRAY_SIZE(adf_402xx_fw_objs);
+
+ return uof_get_name(accel_dev, obj_num, adf_402xx_fw_objs, num_fw_objs);
}
static u32 uof_get_ae_mask(struct adf_accel_dev *accel_dev, u32 obj_num)
{
switch (get_service_enabled(accel_dev)) {
case SVC_CY:
- return adf_4xxx_fw_cy_config[obj_num].ae_mask;
+ return adf_fw_cy_config[obj_num].ae_mask;
case SVC_DC:
- return adf_4xxx_fw_dc_config[obj_num].ae_mask;
+ return adf_fw_dc_config[obj_num].ae_mask;
+ case SVC_CY2:
+ return adf_fw_cy_config[obj_num].ae_mask;
+ case SVC_SYM:
+ return adf_fw_sym_config[obj_num].ae_mask;
+ case SVC_ASYM:
+ return adf_fw_asym_config[obj_num].ae_mask;
+ case SVC_ASYM_DC:
+ case SVC_DC_ASYM:
+ return adf_fw_asym_dc_config[obj_num].ae_mask;
+ case SVC_SYM_DC:
+ case SVC_DC_SYM:
+ return adf_fw_sym_dc_config[obj_num].ae_mask;
+ default:
+ return 0;
}
-
- return 0;
}
void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id)
diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h
index 085e259c245a..e5b314d2b60e 100644
--- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h
+++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h
@@ -72,7 +72,7 @@ enum icp_qat_4xxx_slice_mask {
ICP_ACCEL_4XXX_MASK_COMPRESS_SLICE = BIT(3),
ICP_ACCEL_4XXX_MASK_UCS_SLICE = BIT(4),
ICP_ACCEL_4XXX_MASK_EIA3_SLICE = BIT(5),
- ICP_ACCEL_4XXX_MASK_SMX_SLICE = BIT(6),
+ ICP_ACCEL_4XXX_MASK_SMX_SLICE = BIT(7),
};
void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id);
diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
index ceb87327a5fe..1a15600361d0 100644
--- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
@@ -7,6 +7,7 @@
#include <adf_accel_devices.h>
#include <adf_cfg.h>
#include <adf_common_drv.h>
+#include <adf_dbgfs.h>
#include "adf_4xxx_hw_data.h"
#include "qat_compression.h"
@@ -24,11 +25,25 @@ MODULE_DEVICE_TABLE(pci, adf_pci_tbl);
enum configs {
DEV_CFG_CY = 0,
DEV_CFG_DC,
+ DEV_CFG_SYM,
+ DEV_CFG_ASYM,
+ DEV_CFG_ASYM_SYM,
+ DEV_CFG_ASYM_DC,
+ DEV_CFG_DC_ASYM,
+ DEV_CFG_SYM_DC,
+ DEV_CFG_DC_SYM,
};
static const char * const services_operations[] = {
ADF_CFG_CY,
ADF_CFG_DC,
+ ADF_CFG_SYM,
+ ADF_CFG_ASYM,
+ ADF_CFG_ASYM_SYM,
+ ADF_CFG_ASYM_DC,
+ ADF_CFG_DC_ASYM,
+ ADF_CFG_SYM_DC,
+ ADF_CFG_DC_SYM,
};
static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
@@ -37,8 +52,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
adf_clean_hw_data_4xxx(accel_dev->hw_device);
accel_dev->hw_device = NULL;
}
+ adf_dbgfs_exit(accel_dev);
adf_cfg_dev_remove(accel_dev);
- debugfs_remove(accel_dev->debugfs_dir);
adf_devmgr_rm_dev(accel_dev, NULL);
}
@@ -241,6 +256,21 @@ err:
return ret;
}
+static int adf_no_dev_config(struct adf_accel_dev *accel_dev)
+{
+ unsigned long val;
+ int ret;
+
+ val = 0;
+ ret = adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_DC,
+ &val, ADF_DEC);
+ if (ret)
+ return ret;
+
+ return adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_CY,
+ &val, ADF_DEC);
+}
+
int adf_gen4_dev_config(struct adf_accel_dev *accel_dev)
{
char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0};
@@ -265,11 +295,15 @@ int adf_gen4_dev_config(struct adf_accel_dev *accel_dev)
switch (ret) {
case DEV_CFG_CY:
+ case DEV_CFG_ASYM_SYM:
ret = adf_crypto_dev_config(accel_dev);
break;
case DEV_CFG_DC:
ret = adf_comp_dev_config(accel_dev);
break;
+ default:
+ ret = adf_no_dev_config(accel_dev);
+ break;
}
if (ret)
@@ -289,7 +323,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct adf_accel_dev *accel_dev;
struct adf_accel_pci *accel_pci_dev;
struct adf_hw_device_data *hw_data;
- char name[ADF_DEVICE_NAME_LENGTH];
unsigned int i, bar_nr;
unsigned long bar_mask;
struct adf_bar *bar;
@@ -348,12 +381,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_err;
}
- /* Create dev top level debugfs entry */
- snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX,
- hw_data->dev_class->name, pci_name(pdev));
-
- accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
-
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
if (ret)
@@ -410,6 +437,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_err;
}
+ adf_dbgfs_init(accel_dev);
+
ret = adf_dev_up(accel_dev, true);
if (ret)
goto out_err_dev_stop;
diff --git a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c
index bb4dca735ab5..468c9102093f 100644
--- a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c
@@ -16,6 +16,7 @@
#include <adf_accel_devices.h>
#include <adf_common_drv.h>
#include <adf_cfg.h>
+#include <adf_dbgfs.h>
#include "adf_c3xxx_hw_data.h"
static const struct pci_device_id adf_pci_tbl[] = {
@@ -65,8 +66,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
kfree(accel_dev->hw_device);
accel_dev->hw_device = NULL;
}
+ adf_dbgfs_exit(accel_dev);
adf_cfg_dev_remove(accel_dev);
- debugfs_remove(accel_dev->debugfs_dir);
adf_devmgr_rm_dev(accel_dev, NULL);
}
@@ -75,7 +76,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct adf_accel_dev *accel_dev;
struct adf_accel_pci *accel_pci_dev;
struct adf_hw_device_data *hw_data;
- char name[ADF_DEVICE_NAME_LENGTH];
unsigned int i, bar_nr;
unsigned long bar_mask;
int ret;
@@ -142,12 +142,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_err;
}
- /* Create dev top level debugfs entry */
- snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX,
- hw_data->dev_class->name, pci_name(pdev));
-
- accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
-
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
if (ret)
@@ -199,6 +193,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_err_free_reg;
}
+ adf_dbgfs_init(accel_dev);
+
ret = adf_dev_up(accel_dev, true);
if (ret)
goto out_err_dev_stop;
diff --git a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c
index e8cc10f64134..d5a0ecca9d0b 100644
--- a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c
@@ -16,6 +16,7 @@
#include <adf_accel_devices.h>
#include <adf_common_drv.h>
#include <adf_cfg.h>
+#include <adf_dbgfs.h>
#include "adf_c3xxxvf_hw_data.h"
static const struct pci_device_id adf_pci_tbl[] = {
@@ -64,8 +65,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
kfree(accel_dev->hw_device);
accel_dev->hw_device = NULL;
}
+ adf_dbgfs_exit(accel_dev);
adf_cfg_dev_remove(accel_dev);
- debugfs_remove(accel_dev->debugfs_dir);
pf = adf_devmgr_pci_to_accel_dev(accel_pci_dev->pci_dev->physfn);
adf_devmgr_rm_dev(accel_dev, pf);
}
@@ -76,7 +77,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct adf_accel_dev *pf;
struct adf_accel_pci *accel_pci_dev;
struct adf_hw_device_data *hw_data;
- char name[ADF_DEVICE_NAME_LENGTH];
unsigned int i, bar_nr;
unsigned long bar_mask;
int ret;
@@ -123,12 +123,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw_data->ae_mask = hw_data->get_ae_mask(hw_data);
accel_pci_dev->sku = hw_data->get_sku(hw_data);
- /* Create dev top level debugfs entry */
- snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX,
- hw_data->dev_class->name, pci_name(pdev));
-
- accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
-
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
if (ret)
@@ -173,6 +167,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Completion for VF2PF request/response message exchange */
init_completion(&accel_dev->vf.msg_received);
+ adf_dbgfs_init(accel_dev);
+
ret = adf_dev_up(accel_dev, false);
if (ret)
goto out_err_dev_stop;
diff --git a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c
index ca18ae14c099..0186921be936 100644
--- a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c
@@ -16,6 +16,7 @@
#include <adf_accel_devices.h>
#include <adf_common_drv.h>
#include <adf_cfg.h>
+#include <adf_dbgfs.h>
#include "adf_c62x_hw_data.h"
static const struct pci_device_id adf_pci_tbl[] = {
@@ -65,8 +66,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
kfree(accel_dev->hw_device);
accel_dev->hw_device = NULL;
}
+ adf_dbgfs_exit(accel_dev);
adf_cfg_dev_remove(accel_dev);
- debugfs_remove(accel_dev->debugfs_dir);
adf_devmgr_rm_dev(accel_dev, NULL);
}
@@ -75,7 +76,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct adf_accel_dev *accel_dev;
struct adf_accel_pci *accel_pci_dev;
struct adf_hw_device_data *hw_data;
- char name[ADF_DEVICE_NAME_LENGTH];
unsigned int i, bar_nr;
unsigned long bar_mask;
int ret;
@@ -142,12 +142,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_err;
}
- /* Create dev top level debugfs entry */
- snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX,
- hw_data->dev_class->name, pci_name(pdev));
-
- accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
-
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
if (ret)
@@ -199,6 +193,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_err_free_reg;
}
+ adf_dbgfs_init(accel_dev);
+
ret = adf_dev_up(accel_dev, true);
if (ret)
goto out_err_dev_stop;
diff --git a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c
index 37566309df94..c9ae6c0d0dca 100644
--- a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c
@@ -16,6 +16,7 @@
#include <adf_accel_devices.h>
#include <adf_common_drv.h>
#include <adf_cfg.h>
+#include <adf_dbgfs.h>
#include "adf_c62xvf_hw_data.h"
static const struct pci_device_id adf_pci_tbl[] = {
@@ -64,8 +65,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
kfree(accel_dev->hw_device);
accel_dev->hw_device = NULL;
}
+ adf_dbgfs_exit(accel_dev);
adf_cfg_dev_remove(accel_dev);
- debugfs_remove(accel_dev->debugfs_dir);
pf = adf_devmgr_pci_to_accel_dev(accel_pci_dev->pci_dev->physfn);
adf_devmgr_rm_dev(accel_dev, pf);
}
@@ -76,7 +77,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct adf_accel_dev *pf;
struct adf_accel_pci *accel_pci_dev;
struct adf_hw_device_data *hw_data;
- char name[ADF_DEVICE_NAME_LENGTH];
unsigned int i, bar_nr;
unsigned long bar_mask;
int ret;
@@ -123,12 +123,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw_data->ae_mask = hw_data->get_ae_mask(hw_data);
accel_pci_dev->sku = hw_data->get_sku(hw_data);
- /* Create dev top level debugfs entry */
- snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX,
- hw_data->dev_class->name, pci_name(pdev));
-
- accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
-
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
if (ret)
@@ -173,6 +167,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Completion for VF2PF request/response message exchange */
init_completion(&accel_dev->vf.msg_received);
+ adf_dbgfs_init(accel_dev);
+
ret = adf_dev_up(accel_dev, false);
if (ret)
goto out_err_dev_stop;
diff --git a/drivers/crypto/intel/qat/qat_common/Makefile b/drivers/crypto/intel/qat/qat_common/Makefile
index 1fb8d50f509f..38de3aba6e8c 100644
--- a/drivers/crypto/intel/qat/qat_common/Makefile
+++ b/drivers/crypto/intel/qat/qat_common/Makefile
@@ -27,7 +27,9 @@ intel_qat-objs := adf_cfg.o \
qat_hal.o \
qat_bl.o
-intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o
+intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o \
+ adf_dbgfs.o
+
intel_qat-$(CONFIG_PCI_IOV) += adf_sriov.o adf_vf_isr.o adf_pfvf_utils.o \
adf_pfvf_pf_msg.o adf_pfvf_pf_proto.o \
adf_pfvf_vf_msg.o adf_pfvf_vf_proto.o \
diff --git a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h
index bd19e6460899..0399417b91fc 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h
@@ -202,7 +202,7 @@ struct adf_hw_device_data {
int (*ring_pair_reset)(struct adf_accel_dev *accel_dev, u32 bank_nr);
void (*reset_device)(struct adf_accel_dev *accel_dev);
void (*set_msix_rttable)(struct adf_accel_dev *accel_dev);
- char *(*uof_get_name)(struct adf_accel_dev *accel_dev, u32 obj_num);
+ const char *(*uof_get_name)(struct adf_accel_dev *accel_dev, u32 obj_num);
u32 (*uof_get_num_objs)(void);
u32 (*uof_get_ae_mask)(struct adf_accel_dev *accel_dev, u32 obj_num);
int (*dev_config)(struct adf_accel_dev *accel_dev);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_accel_engine.c b/drivers/crypto/intel/qat/qat_common/adf_accel_engine.c
index 4ce2b666929e..6be064dc64c8 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_accel_engine.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_accel_engine.c
@@ -13,7 +13,7 @@ static int adf_ae_fw_load_images(struct adf_accel_dev *accel_dev, void *fw_addr,
struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
struct adf_hw_device_data *hw_device = accel_dev->hw_device;
struct icp_qat_fw_loader_handle *loader;
- char *obj_name;
+ const char *obj_name;
u32 num_objs;
u32 ae_mask;
int i;
diff --git a/drivers/crypto/intel/qat/qat_common/adf_admin.c b/drivers/crypto/intel/qat/qat_common/adf_admin.c
index 3b6184c35081..118775ee02f2 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_admin.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_admin.c
@@ -286,7 +286,6 @@ int adf_init_admin_pm(struct adf_accel_dev *accel_dev, u32 idle_delay)
return adf_send_admin(accel_dev, &req, &resp, ae_mask);
}
-EXPORT_SYMBOL_GPL(adf_init_admin_pm);
int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
{
diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.c b/drivers/crypto/intel/qat/qat_common/adf_cfg.c
index 1931e5b37f2b..8836f015c39c 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_cfg.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.c
@@ -74,15 +74,30 @@ int adf_cfg_dev_add(struct adf_accel_dev *accel_dev)
INIT_LIST_HEAD(&dev_cfg_data->sec_list);
init_rwsem(&dev_cfg_data->lock);
accel_dev->cfg = dev_cfg_data;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
- /* accel_dev->debugfs_dir should always be non-NULL here */
- dev_cfg_data->debug = debugfs_create_file("dev_cfg", S_IRUSR,
+void adf_cfg_dev_dbgfs_add(struct adf_accel_dev *accel_dev)
+{
+ struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
+
+ dev_cfg_data->debug = debugfs_create_file("dev_cfg", 0400,
accel_dev->debugfs_dir,
dev_cfg_data,
&qat_dev_cfg_fops);
- return 0;
}
-EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
+
+void adf_cfg_dev_dbgfs_rm(struct adf_accel_dev *accel_dev)
+{
+ struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
+
+ if (!dev_cfg_data)
+ return;
+
+ debugfs_remove(dev_cfg_data->debug);
+ dev_cfg_data->debug = NULL;
+}
static void adf_cfg_section_del_all(struct list_head *head);
@@ -116,7 +131,6 @@ void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
down_write(&dev_cfg_data->lock);
adf_cfg_section_del_all(&dev_cfg_data->sec_list);
up_write(&dev_cfg_data->lock);
- debugfs_remove(dev_cfg_data->debug);
kfree(dev_cfg_data);
accel_dev->cfg = NULL;
}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.h b/drivers/crypto/intel/qat/qat_common/adf_cfg.h
index 376cde61a60e..c0c9052b2213 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_cfg.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.h
@@ -31,6 +31,8 @@ struct adf_cfg_device_data {
int adf_cfg_dev_add(struct adf_accel_dev *accel_dev);
void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev);
+void adf_cfg_dev_dbgfs_add(struct adf_accel_dev *accel_dev);
+void adf_cfg_dev_dbgfs_rm(struct adf_accel_dev *accel_dev);
int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name);
void adf_cfg_del_all(struct adf_accel_dev *accel_dev);
int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h b/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h
index 5d8c3bdb258c..3ae1e5caee0e 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h
@@ -25,7 +25,15 @@
#define ADF_DC "Dc"
#define ADF_CFG_DC "dc"
#define ADF_CFG_CY "sym;asym"
+#define ADF_CFG_SYM "sym"
+#define ADF_CFG_ASYM "asym"
+#define ADF_CFG_ASYM_SYM "asym;sym"
+#define ADF_CFG_ASYM_DC "asym;dc"
+#define ADF_CFG_DC_ASYM "dc;asym"
+#define ADF_CFG_SYM_DC "sym;dc"
+#define ADF_CFG_DC_SYM "dc;sym"
#define ADF_SERVICES_ENABLED "ServicesEnabled"
+#define ADF_PM_IDLE_SUPPORT "PmIdleSupport"
#define ADF_ETRMGR_COALESCING_ENABLED "InterruptCoalescingEnabled"
#define ADF_ETRMGR_COALESCING_ENABLED_FORMAT \
ADF_ETRMGR_BANK "%d" ADF_ETRMGR_COALESCING_ENABLED
diff --git a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h
index db79759bee61..b8132eb9bc2a 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h
@@ -187,7 +187,7 @@ void qat_uclo_del_obj(struct icp_qat_fw_loader_handle *handle);
int qat_uclo_wr_mimage(struct icp_qat_fw_loader_handle *handle, void *addr_ptr,
int mem_size);
int qat_uclo_map_obj(struct icp_qat_fw_loader_handle *handle,
- void *addr_ptr, u32 mem_size, char *obj_name);
+ void *addr_ptr, u32 mem_size, const char *obj_name);
int qat_uclo_set_cfg_ae_mask(struct icp_qat_fw_loader_handle *handle,
unsigned int cfg_ae_mask);
int adf_init_misc_wq(void);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c
new file mode 100644
index 000000000000..d0a2f892e6eb
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Intel Corporation */
+
+#include <linux/debugfs.h>
+#include "adf_accel_devices.h"
+#include "adf_cfg.h"
+#include "adf_common_drv.h"
+#include "adf_dbgfs.h"
+
+/**
+ * adf_dbgfs_init() - add persistent debugfs entries
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * This function creates debugfs entries that are persistent through a device
+ * state change (from up to down or vice versa).
+ */
+void adf_dbgfs_init(struct adf_accel_dev *accel_dev)
+{
+ char name[ADF_DEVICE_NAME_LENGTH];
+ void *ret;
+
+ /* Create dev top level debugfs entry */
+ snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX,
+ accel_dev->hw_device->dev_class->name,
+ pci_name(accel_dev->accel_pci_dev.pci_dev));
+
+ ret = debugfs_create_dir(name, NULL);
+ if (IS_ERR_OR_NULL(ret))
+ return;
+
+ accel_dev->debugfs_dir = ret;
+
+ adf_cfg_dev_dbgfs_add(accel_dev);
+}
+EXPORT_SYMBOL_GPL(adf_dbgfs_init);
+
+/**
+ * adf_dbgfs_exit() - remove persistent debugfs entries
+ * @accel_dev: Pointer to acceleration device.
+ */
+void adf_dbgfs_exit(struct adf_accel_dev *accel_dev)
+{
+ adf_cfg_dev_dbgfs_rm(accel_dev);
+ debugfs_remove(accel_dev->debugfs_dir);
+}
+EXPORT_SYMBOL_GPL(adf_dbgfs_exit);
+
+/**
+ * adf_dbgfs_add() - add non-persistent debugfs entries
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * This function creates debugfs entries that are not persistent through
+ * a device state change (from up to down or vice versa).
+ */
+void adf_dbgfs_add(struct adf_accel_dev *accel_dev)
+{
+ if (!accel_dev->debugfs_dir)
+ return;
+}
+
+/**
+ * adf_dbgfs_rm() - remove non-persistent debugfs entries
+ * @accel_dev: Pointer to acceleration device.
+ */
+void adf_dbgfs_rm(struct adf_accel_dev *accel_dev)
+{
+ if (!accel_dev->debugfs_dir)
+ return;
+}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.h b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.h
new file mode 100644
index 000000000000..e0cb2c2a2ed0
--- /dev/null
+++ b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Intel Corporation */
+
+#ifndef ADF_DBGFS_H
+#define ADF_DBGFS_H
+
+#ifdef CONFIG_DEBUG_FS
+void adf_dbgfs_init(struct adf_accel_dev *accel_dev);
+void adf_dbgfs_add(struct adf_accel_dev *accel_dev);
+void adf_dbgfs_rm(struct adf_accel_dev *accel_dev);
+void adf_dbgfs_exit(struct adf_accel_dev *accel_dev);
+#else
+static inline void adf_dbgfs_init(struct adf_accel_dev *accel_dev)
+{
+}
+
+static inline void adf_dbgfs_add(struct adf_accel_dev *accel_dev)
+{
+}
+
+static inline void adf_dbgfs_rm(struct adf_accel_dev *accel_dev)
+{
+}
+
+static inline void adf_dbgfs_exit(struct adf_accel_dev *accel_dev)
+{
+}
+#endif
+#endif
diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c
index 7037c0892a8a..34c6cd8e27c0 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c
@@ -23,15 +23,25 @@ struct adf_gen4_pm_data {
static int send_host_msg(struct adf_accel_dev *accel_dev)
{
+ char pm_idle_support_cfg[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {};
void __iomem *pmisc = adf_get_pmisc_base(accel_dev);
+ bool pm_idle_support;
u32 msg;
+ int ret;
msg = ADF_CSR_RD(pmisc, ADF_GEN4_PM_HOST_MSG);
if (msg & ADF_GEN4_PM_MSG_PENDING)
return -EBUSY;
+ adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
+ ADF_PM_IDLE_SUPPORT, pm_idle_support_cfg);
+ ret = kstrtobool(pm_idle_support_cfg, &pm_idle_support);
+ if (ret)
+ pm_idle_support = true;
+
/* Send HOST_MSG */
- msg = FIELD_PREP(ADF_GEN4_PM_MSG_PAYLOAD_BIT_MASK, PM_SET_MIN);
+ msg = FIELD_PREP(ADF_GEN4_PM_MSG_PAYLOAD_BIT_MASK,
+ pm_idle_support ? PM_SET_MIN : PM_NO_CHANGE);
msg |= ADF_GEN4_PM_MSG_PENDING;
ADF_CSR_WR(pmisc, ADF_GEN4_PM_HOST_MSG, msg);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h
index f8f8a9ee29e5..dd112923e006 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h
@@ -37,6 +37,7 @@
#define ADF_GEN4_PM_DEFAULT_IDLE_FILTER (0x0)
#define ADF_GEN4_PM_MAX_IDLE_FILTER (0x7)
+#define ADF_GEN4_PM_DEFAULT_IDLE_SUPPORT (0x1)
int adf_gen4_enable_pm(struct adf_accel_dev *accel_dev);
bool adf_gen4_handle_pm_interrupt(struct adf_accel_dev *accel_dev);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_init.c b/drivers/crypto/intel/qat/qat_common/adf_init.c
index 0985f64ab11a..826179c98524 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_init.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_init.c
@@ -7,6 +7,7 @@
#include "adf_accel_devices.h"
#include "adf_cfg.h"
#include "adf_common_drv.h"
+#include "adf_dbgfs.h"
static LIST_HEAD(service_table);
static DEFINE_MUTEX(service_lock);
@@ -216,6 +217,9 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev)
clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
return -EFAULT;
}
+
+ adf_dbgfs_add(accel_dev);
+
return 0;
}
@@ -240,6 +244,8 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev)
!test_bit(ADF_STATUS_STARTING, &accel_dev->status))
return;
+ adf_dbgfs_rm(accel_dev);
+
clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs.c b/drivers/crypto/intel/qat/qat_common/adf_sysfs.c
index 3eb6611ab1b1..a74d2f930367 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_sysfs.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs.c
@@ -78,6 +78,13 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr,
static const char * const services_operations[] = {
ADF_CFG_CY,
ADF_CFG_DC,
+ ADF_CFG_SYM,
+ ADF_CFG_ASYM,
+ ADF_CFG_ASYM_SYM,
+ ADF_CFG_ASYM_DC,
+ ADF_CFG_DC_ASYM,
+ ADF_CFG_SYM_DC,
+ ADF_CFG_DC_SYM,
};
static ssize_t cfg_services_show(struct device *dev, struct device_attribute *attr,
@@ -145,12 +152,65 @@ static ssize_t cfg_services_store(struct device *dev, struct device_attribute *a
return count;
}
+static ssize_t pm_idle_enabled_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ char pm_idle_enabled[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {};
+ struct adf_accel_dev *accel_dev;
+ int ret;
+
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
+ ADF_PM_IDLE_SUPPORT, pm_idle_enabled);
+ if (ret)
+ return sysfs_emit(buf, "1\n");
+
+ return sysfs_emit(buf, "%s\n", pm_idle_enabled);
+}
+
+static ssize_t pm_idle_enabled_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long pm_idle_enabled_cfg_val;
+ struct adf_accel_dev *accel_dev;
+ bool pm_idle_enabled;
+ int ret;
+
+ ret = kstrtobool(buf, &pm_idle_enabled);
+ if (ret)
+ return ret;
+
+ pm_idle_enabled_cfg_val = pm_idle_enabled;
+ accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+ if (!accel_dev)
+ return -EINVAL;
+
+ if (adf_dev_started(accel_dev)) {
+ dev_info(dev, "Device qat_dev%d must be down to set pm_idle_enabled.\n",
+ accel_dev->accel_id);
+ return -EINVAL;
+ }
+
+ ret = adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC,
+ ADF_PM_IDLE_SUPPORT, &pm_idle_enabled_cfg_val,
+ ADF_DEC);
+ if (ret)
+ return ret;
+
+ return count;
+}
+static DEVICE_ATTR_RW(pm_idle_enabled);
+
static DEVICE_ATTR_RW(state);
static DEVICE_ATTR_RW(cfg_services);
static struct attribute *qat_attrs[] = {
&dev_attr_state.attr,
&dev_attr_cfg_services.attr,
+ &dev_attr_pm_idle_enabled.attr,
NULL,
};
diff --git a/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h b/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h
index 4042739bb6fa..a65059e56248 100644
--- a/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h
+++ b/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h
@@ -87,8 +87,7 @@ enum icp_qat_capabilities_mask {
ICP_ACCEL_CAPABILITIES_AUTHENTICATION = BIT(3),
ICP_ACCEL_CAPABILITIES_RESERVED_1 = BIT(4),
ICP_ACCEL_CAPABILITIES_COMPRESSION = BIT(5),
- ICP_ACCEL_CAPABILITIES_LZS_COMPRESSION = BIT(6),
- ICP_ACCEL_CAPABILITIES_RAND = BIT(7),
+ /* Bits 6-7 are currently reserved */
ICP_ACCEL_CAPABILITIES_ZUC = BIT(8),
ICP_ACCEL_CAPABILITIES_SHA3 = BIT(9),
/* Bits 10-11 are currently reserved */
diff --git a/drivers/crypto/intel/qat/qat_common/qat_algs.c b/drivers/crypto/intel/qat/qat_common/qat_algs.c
index 538dcbfbcd26..3c4bba4a8779 100644
--- a/drivers/crypto/intel/qat/qat_common/qat_algs.c
+++ b/drivers/crypto/intel/qat/qat_common/qat_algs.c
@@ -106,7 +106,6 @@ static int qat_get_inter_state_size(enum icp_qat_hw_auth_algo qat_hash_alg)
default:
return -EFAULT;
}
- return -EFAULT;
}
static int qat_alg_do_precomputes(struct icp_qat_hw_auth_algo_blk *hash,
diff --git a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c
index 935a7e012946..4128200a9032 100644
--- a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c
+++ b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c
@@ -170,15 +170,14 @@ static void qat_dh_cb(struct icp_qat_fw_pke_resp *resp)
}
areq->dst_len = req->ctx.dh->p_size;
+ dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size,
+ DMA_FROM_DEVICE);
if (req->dst_align) {
scatterwalk_map_and_copy(req->dst_align, areq->dst, 0,
areq->dst_len, 1);
kfree_sensitive(req->dst_align);
}
- dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size,
- DMA_FROM_DEVICE);
-
dma_unmap_single(dev, req->phy_in, sizeof(struct qat_dh_input_params),
DMA_TO_DEVICE);
dma_unmap_single(dev, req->phy_out,
@@ -521,12 +520,14 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp)
err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL;
- kfree_sensitive(req->src_align);
-
dma_unmap_single(dev, req->in.rsa.enc.m, req->ctx.rsa->key_sz,
DMA_TO_DEVICE);
+ kfree_sensitive(req->src_align);
+
areq->dst_len = req->ctx.rsa->key_sz;
+ dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz,
+ DMA_FROM_DEVICE);
if (req->dst_align) {
scatterwalk_map_and_copy(req->dst_align, areq->dst, 0,
areq->dst_len, 1);
@@ -534,9 +535,6 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp)
kfree_sensitive(req->dst_align);
}
- dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz,
- DMA_FROM_DEVICE);
-
dma_unmap_single(dev, req->phy_in, sizeof(struct qat_rsa_input_params),
DMA_TO_DEVICE);
dma_unmap_single(dev, req->phy_out,
diff --git a/drivers/crypto/intel/qat/qat_common/qat_uclo.c b/drivers/crypto/intel/qat/qat_common/qat_uclo.c
index 3ba8ca20b3d7..ce837bcc1cab 100644
--- a/drivers/crypto/intel/qat/qat_common/qat_uclo.c
+++ b/drivers/crypto/intel/qat/qat_common/qat_uclo.c
@@ -1685,7 +1685,7 @@ static void qat_uclo_del_mof(struct icp_qat_fw_loader_handle *handle)
}
static int qat_uclo_seek_obj_inside_mof(struct icp_qat_mof_handle *mobj_handle,
- char *obj_name, char **obj_ptr,
+ const char *obj_name, char **obj_ptr,
unsigned int *obj_size)
{
struct icp_qat_mof_objhdr *obj_hdr = mobj_handle->obj_table.obj_hdr;
@@ -1837,8 +1837,8 @@ static int qat_uclo_check_mof_format(struct icp_qat_mof_file_hdr *mof_hdr)
static int qat_uclo_map_mof_obj(struct icp_qat_fw_loader_handle *handle,
struct icp_qat_mof_file_hdr *mof_ptr,
- u32 mof_size, char *obj_name, char **obj_ptr,
- unsigned int *obj_size)
+ u32 mof_size, const char *obj_name,
+ char **obj_ptr, unsigned int *obj_size)
{
struct icp_qat_mof_chunkhdr *mof_chunkhdr;
unsigned int file_id = mof_ptr->file_id;
@@ -1888,7 +1888,7 @@ static int qat_uclo_map_mof_obj(struct icp_qat_fw_loader_handle *handle,
}
int qat_uclo_map_obj(struct icp_qat_fw_loader_handle *handle,
- void *addr_ptr, u32 mem_size, char *obj_name)
+ void *addr_ptr, u32 mem_size, const char *obj_name)
{
char *obj_addr;
u32 obj_size;
diff --git a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c
index e18860ab5c8e..1e748e8ce12d 100644
--- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c
@@ -16,6 +16,7 @@
#include <adf_accel_devices.h>
#include <adf_common_drv.h>
#include <adf_cfg.h>
+#include <adf_dbgfs.h>
#include "adf_dh895xcc_hw_data.h"
static const struct pci_device_id adf_pci_tbl[] = {
@@ -65,8 +66,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
kfree(accel_dev->hw_device);
accel_dev->hw_device = NULL;
}
+ adf_dbgfs_exit(accel_dev);
adf_cfg_dev_remove(accel_dev);
- debugfs_remove(accel_dev->debugfs_dir);
adf_devmgr_rm_dev(accel_dev, NULL);
}
@@ -75,7 +76,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct adf_accel_dev *accel_dev;
struct adf_accel_pci *accel_pci_dev;
struct adf_hw_device_data *hw_data;
- char name[ADF_DEVICE_NAME_LENGTH];
unsigned int i, bar_nr;
unsigned long bar_mask;
int ret;
@@ -140,12 +140,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_err;
}
- /* Create dev top level debugfs entry */
- snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX,
- hw_data->dev_class->name, pci_name(pdev));
-
- accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
-
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
if (ret)
@@ -199,6 +193,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_err_free_reg;
}
+ adf_dbgfs_init(accel_dev);
+
ret = adf_dev_up(accel_dev, true);
if (ret)
goto out_err_dev_stop;
diff --git a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c
index 96854a1cd87e..fefb85ceaeb9 100644
--- a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c
@@ -16,6 +16,7 @@
#include <adf_accel_devices.h>
#include <adf_common_drv.h>
#include <adf_cfg.h>
+#include <adf_dbgfs.h>
#include "adf_dh895xccvf_hw_data.h"
static const struct pci_device_id adf_pci_tbl[] = {
@@ -64,8 +65,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
kfree(accel_dev->hw_device);
accel_dev->hw_device = NULL;
}
+ adf_dbgfs_exit(accel_dev);
adf_cfg_dev_remove(accel_dev);
- debugfs_remove(accel_dev->debugfs_dir);
pf = adf_devmgr_pci_to_accel_dev(accel_pci_dev->pci_dev->physfn);
adf_devmgr_rm_dev(accel_dev, pf);
}
@@ -76,7 +77,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct adf_accel_dev *pf;
struct adf_accel_pci *accel_pci_dev;
struct adf_hw_device_data *hw_data;
- char name[ADF_DEVICE_NAME_LENGTH];
unsigned int i, bar_nr;
unsigned long bar_mask;
int ret;
@@ -123,12 +123,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw_data->ae_mask = hw_data->get_ae_mask(hw_data);
accel_pci_dev->sku = hw_data->get_sku(hw_data);
- /* Create dev top level debugfs entry */
- snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX,
- hw_data->dev_class->name, pci_name(pdev));
-
- accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
-
/* Create device configuration table */
ret = adf_cfg_dev_add(accel_dev);
if (ret)
@@ -173,6 +167,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Completion for VF2PF request/response message exchange */
init_completion(&accel_dev->vf.msg_received);
+ adf_dbgfs_init(accel_dev);
+
ret = adf_dev_up(accel_dev, false);
if (ret)
goto out_err_dev_stop;
diff --git a/drivers/crypto/marvell/cesa/cipher.c b/drivers/crypto/marvell/cesa/cipher.c
index c6f2fa753b7c..0f37dfd42d85 100644
--- a/drivers/crypto/marvell/cesa/cipher.c
+++ b/drivers/crypto/marvell/cesa/cipher.c
@@ -297,7 +297,7 @@ static int mv_cesa_des_setkey(struct crypto_skcipher *cipher, const u8 *key,
static int mv_cesa_des3_ede_setkey(struct crypto_skcipher *cipher,
const u8 *key, unsigned int len)
{
- struct mv_cesa_des_ctx *ctx = crypto_skcipher_ctx(cipher);
+ struct mv_cesa_des3_ctx *ctx = crypto_skcipher_ctx(cipher);
int err;
err = verify_skcipher_des3_key(cipher, key);
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h b/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h
index 6019066a6451..46b778bbbee4 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h
+++ b/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h
@@ -40,11 +40,26 @@ enum otx2_cpt_eng_type {
};
/* Take mbox id from end of CPT mbox range in AF (range 0xA00 - 0xBFF) */
+#define MBOX_MSG_RX_INLINE_IPSEC_LF_CFG 0xBFE
#define MBOX_MSG_GET_ENG_GRP_NUM 0xBFF
#define MBOX_MSG_GET_CAPS 0xBFD
#define MBOX_MSG_GET_KVF_LIMITS 0xBFC
/*
+ * Message request to config cpt lf for inline inbound ipsec.
+ * This message is only used between CPT PF <-> CPT VF
+ */
+struct otx2_cpt_rx_inline_lf_cfg {
+ struct mbox_msghdr hdr;
+ u16 sso_pf_func;
+ u16 param1;
+ u16 param2;
+ u16 opcode;
+ u32 credit;
+ u32 reserved;
+};
+
+/*
* Message request and response to get engine group number
* which has attached a given type of engines (SE, AE, IE)
* This messages are only used between CPT PF <=> CPT VF
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c b/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c
index 115997475beb..273ee5352a50 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c
@@ -141,6 +141,8 @@ int otx2_cpt_attach_rscrs_msg(struct otx2_cptlfs_info *lfs)
req->hdr.sig = OTX2_MBOX_REQ_SIG;
req->hdr.pcifunc = 0;
req->cptlfs = lfs->lfs_num;
+ req->cpt_blkaddr = lfs->blkaddr;
+ req->modify = 1;
ret = otx2_cpt_send_mbox_msg(mbox, lfs->pdev);
if (ret)
return ret;
@@ -168,6 +170,7 @@ int otx2_cpt_detach_rsrcs_msg(struct otx2_cptlfs_info *lfs)
req->hdr.id = MBOX_MSG_DETACH_RESOURCES;
req->hdr.sig = OTX2_MBOX_REQ_SIG;
req->hdr.pcifunc = 0;
+ req->cptlfs = 1;
ret = otx2_cpt_send_mbox_msg(mbox, lfs->pdev);
if (ret)
return ret;
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptlf.c b/drivers/crypto/marvell/octeontx2/otx2_cptlf.c
index 71e5f79431af..6edd27ff8c4e 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptlf.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptlf.c
@@ -13,10 +13,10 @@ static void cptlf_do_set_done_time_wait(struct otx2_cptlf_info *lf,
{
union otx2_cptx_lf_done_wait done_wait;
- done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
- OTX2_CPT_LF_DONE_WAIT);
+ done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr,
+ lf->slot, OTX2_CPT_LF_DONE_WAIT);
done_wait.s.time_wait = time_wait;
- otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
OTX2_CPT_LF_DONE_WAIT, done_wait.u);
}
@@ -24,10 +24,10 @@ static void cptlf_do_set_done_num_wait(struct otx2_cptlf_info *lf, int num_wait)
{
union otx2_cptx_lf_done_wait done_wait;
- done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
- OTX2_CPT_LF_DONE_WAIT);
+ done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr,
+ lf->slot, OTX2_CPT_LF_DONE_WAIT);
done_wait.s.num_wait = num_wait;
- otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
OTX2_CPT_LF_DONE_WAIT, done_wait.u);
}
@@ -147,7 +147,7 @@ static void cptlf_set_misc_intrs(struct otx2_cptlfs_info *lfs, u8 enable)
irq_misc.s.nwrp = 0x1;
for (slot = 0; slot < lfs->lfs_num; slot++)
- otx2_cpt_write64(lfs->reg_base, BLKADDR_CPT0, slot, reg,
+ otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot, reg,
irq_misc.u);
}
@@ -157,7 +157,7 @@ static void cptlf_enable_intrs(struct otx2_cptlfs_info *lfs)
/* Enable done interrupts */
for (slot = 0; slot < lfs->lfs_num; slot++)
- otx2_cpt_write64(lfs->reg_base, BLKADDR_CPT0, slot,
+ otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot,
OTX2_CPT_LF_DONE_INT_ENA_W1S, 0x1);
/* Enable Misc interrupts */
cptlf_set_misc_intrs(lfs, true);
@@ -168,7 +168,7 @@ static void cptlf_disable_intrs(struct otx2_cptlfs_info *lfs)
int slot;
for (slot = 0; slot < lfs->lfs_num; slot++)
- otx2_cpt_write64(lfs->reg_base, BLKADDR_CPT0, slot,
+ otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot,
OTX2_CPT_LF_DONE_INT_ENA_W1C, 0x1);
cptlf_set_misc_intrs(lfs, false);
}
@@ -177,7 +177,7 @@ static inline int cptlf_read_done_cnt(struct otx2_cptlf_info *lf)
{
union otx2_cptx_lf_done irq_cnt;
- irq_cnt.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ irq_cnt.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
OTX2_CPT_LF_DONE);
return irq_cnt.s.done;
}
@@ -189,8 +189,8 @@ static irqreturn_t cptlf_misc_intr_handler(int __always_unused irq, void *arg)
struct device *dev;
dev = &lf->lfs->pdev->dev;
- irq_misc.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
- OTX2_CPT_LF_MISC_INT);
+ irq_misc.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr,
+ lf->slot, OTX2_CPT_LF_MISC_INT);
irq_misc_ack.u = 0x0;
if (irq_misc.s.fault) {
@@ -222,7 +222,7 @@ static irqreturn_t cptlf_misc_intr_handler(int __always_unused irq, void *arg)
}
/* Acknowledge interrupts */
- otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
OTX2_CPT_LF_MISC_INT, irq_misc_ack.u);
return IRQ_HANDLED;
@@ -237,13 +237,13 @@ static irqreturn_t cptlf_done_intr_handler(int irq, void *arg)
/* Read the number of completed requests */
irq_cnt = cptlf_read_done_cnt(lf);
if (irq_cnt) {
- done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0,
+ done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr,
lf->slot, OTX2_CPT_LF_DONE_WAIT);
/* Acknowledge the number of completed requests */
- otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
OTX2_CPT_LF_DONE_ACK, irq_cnt);
- otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
OTX2_CPT_LF_DONE_WAIT, done_wait.u);
if (unlikely(!lf->wqe)) {
dev_err(&lf->lfs->pdev->dev, "No work for LF %d\n",
@@ -393,7 +393,7 @@ int otx2_cptlf_init(struct otx2_cptlfs_info *lfs, u8 eng_grp_mask, int pri,
OTX2_CPT_LMT_LF_LMTLINEX(0));
lfs->lf[slot].ioreg = lfs->reg_base +
- OTX2_CPT_RVU_FUNC_ADDR_S(BLKADDR_CPT0, slot,
+ OTX2_CPT_RVU_FUNC_ADDR_S(lfs->blkaddr, slot,
OTX2_CPT_LF_NQX(0));
}
/* Send request to attach LFs */
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptlf.h b/drivers/crypto/marvell/octeontx2/otx2_cptlf.h
index 4fcaf61a70e3..5302fe3d0e6f 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptlf.h
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptlf.h
@@ -180,7 +180,7 @@ static inline void otx2_cptlf_set_iqueues_base_addr(
for (slot = 0; slot < lfs->lfs_num; slot++) {
lf_q_base.u = lfs->lf[slot].iqueue.dma_addr;
- otx2_cpt_write64(lfs->reg_base, BLKADDR_CPT0, slot,
+ otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot,
OTX2_CPT_LF_Q_BASE, lf_q_base.u);
}
}
@@ -191,7 +191,7 @@ static inline void otx2_cptlf_do_set_iqueue_size(struct otx2_cptlf_info *lf)
lf_q_size.s.size_div40 = OTX2_CPT_SIZE_DIV40 +
OTX2_CPT_EXTRA_SIZE_DIV40;
- otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
OTX2_CPT_LF_Q_SIZE, lf_q_size.u);
}
@@ -207,15 +207,16 @@ static inline void otx2_cptlf_do_disable_iqueue(struct otx2_cptlf_info *lf)
{
union otx2_cptx_lf_ctl lf_ctl = { .u = 0x0 };
union otx2_cptx_lf_inprog lf_inprog;
+ u8 blkaddr = lf->lfs->blkaddr;
int timeout = 20;
/* Disable instructions enqueuing */
- otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot,
OTX2_CPT_LF_CTL, lf_ctl.u);
/* Wait for instruction queue to become empty */
do {
- lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0,
+ lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, blkaddr,
lf->slot, OTX2_CPT_LF_INPROG);
if (!lf_inprog.s.inflight)
break;
@@ -234,7 +235,7 @@ static inline void otx2_cptlf_do_disable_iqueue(struct otx2_cptlf_info *lf)
* the queue should be empty at this point
*/
lf_inprog.s.eena = 0x0;
- otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot,
OTX2_CPT_LF_INPROG, lf_inprog.u);
}
@@ -249,14 +250,15 @@ static inline void otx2_cptlf_disable_iqueues(struct otx2_cptlfs_info *lfs)
static inline void otx2_cptlf_set_iqueue_enq(struct otx2_cptlf_info *lf,
bool enable)
{
+ u8 blkaddr = lf->lfs->blkaddr;
union otx2_cptx_lf_ctl lf_ctl;
- lf_ctl.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ lf_ctl.u = otx2_cpt_read64(lf->lfs->reg_base, blkaddr, lf->slot,
OTX2_CPT_LF_CTL);
/* Set iqueue's enqueuing */
lf_ctl.s.ena = enable ? 0x1 : 0x0;
- otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot,
OTX2_CPT_LF_CTL, lf_ctl.u);
}
@@ -269,13 +271,14 @@ static inline void otx2_cptlf_set_iqueue_exec(struct otx2_cptlf_info *lf,
bool enable)
{
union otx2_cptx_lf_inprog lf_inprog;
+ u8 blkaddr = lf->lfs->blkaddr;
- lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, blkaddr, lf->slot,
OTX2_CPT_LF_INPROG);
/* Set iqueue's execution */
lf_inprog.s.eena = enable ? 0x1 : 0x0;
- otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot,
+ otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot,
OTX2_CPT_LF_INPROG, lf_inprog.u);
}
@@ -364,6 +367,18 @@ static inline bool otx2_cptlf_started(struct otx2_cptlfs_info *lfs)
return atomic_read(&lfs->state) == OTX2_CPTLF_STARTED;
}
+static inline void otx2_cptlf_set_dev_info(struct otx2_cptlfs_info *lfs,
+ struct pci_dev *pdev,
+ void __iomem *reg_base,
+ struct otx2_mbox *mbox,
+ int blkaddr)
+{
+ lfs->pdev = pdev;
+ lfs->reg_base = reg_base;
+ lfs->mbox = mbox;
+ lfs->blkaddr = blkaddr;
+}
+
int otx2_cptlf_init(struct otx2_cptlfs_info *lfs, u8 eng_grp_msk, int pri,
int lfs_num);
void otx2_cptlf_shutdown(struct otx2_cptlfs_info *lfs);
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf.h b/drivers/crypto/marvell/octeontx2/otx2_cptpf.h
index 936174b012e8..a209ec5af381 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptpf.h
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf.h
@@ -31,6 +31,7 @@ struct otx2_cptpf_dev {
struct otx2_cptvf_info vf[OTX2_CPT_MAX_VFS_NUM];
struct otx2_cpt_eng_grps eng_grps;/* Engine groups information */
struct otx2_cptlfs_info lfs; /* CPT LFs attached to this PF */
+ struct otx2_cptlfs_info cpt1_lfs; /* CPT1 LFs attached to this PF */
/* HW capabilities for each engine type */
union otx2_cpt_eng_caps eng_caps[OTX2_CPT_MAX_ENG_TYPES];
bool is_eng_caps_discovered;
@@ -40,6 +41,9 @@ struct otx2_cptpf_dev {
struct work_struct afpf_mbox_work;
struct workqueue_struct *afpf_mbox_wq;
+ struct otx2_mbox afpf_mbox_up;
+ struct work_struct afpf_mbox_up_work;
+
/* VF <=> PF mbox */
struct otx2_mbox vfpf_mbox;
struct workqueue_struct *vfpf_mbox_wq;
@@ -52,8 +56,10 @@ struct otx2_cptpf_dev {
u8 pf_id; /* RVU PF number */
u8 max_vfs; /* Maximum number of VFs supported by CPT */
u8 enabled_vfs; /* Number of enabled VFs */
+ u8 sso_pf_func_ovrd; /* SSO PF_FUNC override bit */
u8 kvf_limits; /* Kernel crypto limits */
bool has_cpt1;
+ u8 rsrc_req_blkaddr;
/* Devlink */
struct devlink *dl;
@@ -61,6 +67,7 @@ struct otx2_cptpf_dev {
irqreturn_t otx2_cptpf_afpf_mbox_intr(int irq, void *arg);
void otx2_cptpf_afpf_mbox_handler(struct work_struct *work);
+void otx2_cptpf_afpf_mbox_up_handler(struct work_struct *work);
irqreturn_t otx2_cptpf_vfpf_mbox_intr(int irq, void *arg);
void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work);
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
index 30e6acfc93d9..e34223daa327 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
@@ -13,6 +13,8 @@
#define OTX2_CPT_DRV_NAME "rvu_cptpf"
#define OTX2_CPT_DRV_STRING "Marvell RVU CPT Physical Function Driver"
+#define CPT_UC_RID_CN9K_B0 1
+
static void cptpf_enable_vfpf_mbox_intr(struct otx2_cptpf_dev *cptpf,
int num_vfs)
{
@@ -473,10 +475,19 @@ static int cptpf_afpf_mbox_init(struct otx2_cptpf_dev *cptpf)
if (err)
goto error;
+ err = otx2_mbox_init(&cptpf->afpf_mbox_up, cptpf->afpf_mbox_base,
+ pdev, cptpf->reg_base, MBOX_DIR_PFAF_UP, 1);
+ if (err)
+ goto mbox_cleanup;
+
INIT_WORK(&cptpf->afpf_mbox_work, otx2_cptpf_afpf_mbox_handler);
+ INIT_WORK(&cptpf->afpf_mbox_up_work, otx2_cptpf_afpf_mbox_up_handler);
mutex_init(&cptpf->lock);
+
return 0;
+mbox_cleanup:
+ otx2_mbox_destroy(&cptpf->afpf_mbox);
error:
destroy_workqueue(cptpf->afpf_mbox_wq);
return err;
@@ -486,6 +497,33 @@ static void cptpf_afpf_mbox_destroy(struct otx2_cptpf_dev *cptpf)
{
destroy_workqueue(cptpf->afpf_mbox_wq);
otx2_mbox_destroy(&cptpf->afpf_mbox);
+ otx2_mbox_destroy(&cptpf->afpf_mbox_up);
+}
+
+static ssize_t sso_pf_func_ovrd_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct otx2_cptpf_dev *cptpf = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", cptpf->sso_pf_func_ovrd);
+}
+
+static ssize_t sso_pf_func_ovrd_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct otx2_cptpf_dev *cptpf = dev_get_drvdata(dev);
+ u8 sso_pf_func_ovrd;
+
+ if (!(cptpf->pdev->revision == CPT_UC_RID_CN9K_B0))
+ return count;
+
+ if (kstrtou8(buf, 0, &sso_pf_func_ovrd))
+ return -EINVAL;
+
+ cptpf->sso_pf_func_ovrd = sso_pf_func_ovrd;
+
+ return count;
}
static ssize_t kvf_limits_show(struct device *dev,
@@ -518,8 +556,11 @@ static ssize_t kvf_limits_store(struct device *dev,
}
static DEVICE_ATTR_RW(kvf_limits);
+static DEVICE_ATTR_RW(sso_pf_func_ovrd);
+
static struct attribute *cptpf_attrs[] = {
&dev_attr_kvf_limits.attr,
+ &dev_attr_sso_pf_func_ovrd.attr,
NULL
};
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c
index dee0aa60b698..480b3720f15a 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c
@@ -5,6 +5,20 @@
#include "otx2_cptpf.h"
#include "rvu_reg.h"
+/* Fastpath ipsec opcode with inplace processing */
+#define CPT_INLINE_RX_OPCODE (0x26 | (1 << 6))
+#define CN10K_CPT_INLINE_RX_OPCODE (0x29 | (1 << 6))
+
+#define cpt_inline_rx_opcode(pdev) \
+({ \
+ u8 opcode; \
+ if (is_dev_otx2(pdev)) \
+ opcode = CPT_INLINE_RX_OPCODE; \
+ else \
+ opcode = CN10K_CPT_INLINE_RX_OPCODE; \
+ (opcode); \
+})
+
/*
* CPT PF driver version, It will be incremented by 1 for every feature
* addition in CPT mailbox messages.
@@ -112,6 +126,139 @@ static int handle_msg_kvf_limits(struct otx2_cptpf_dev *cptpf,
return 0;
}
+static int send_inline_ipsec_inbound_msg(struct otx2_cptpf_dev *cptpf,
+ int sso_pf_func, u8 slot)
+{
+ struct cpt_inline_ipsec_cfg_msg *req;
+ struct pci_dev *pdev = cptpf->pdev;
+
+ req = (struct cpt_inline_ipsec_cfg_msg *)
+ otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0,
+ sizeof(*req), sizeof(struct msg_rsp));
+ if (req == NULL) {
+ dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");
+ return -EFAULT;
+ }
+ memset(req, 0, sizeof(*req));
+ req->hdr.id = MBOX_MSG_CPT_INLINE_IPSEC_CFG;
+ req->hdr.sig = OTX2_MBOX_REQ_SIG;
+ req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0);
+ req->dir = CPT_INLINE_INBOUND;
+ req->slot = slot;
+ req->sso_pf_func_ovrd = cptpf->sso_pf_func_ovrd;
+ req->sso_pf_func = sso_pf_func;
+ req->enable = 1;
+
+ return otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev);
+}
+
+static int rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf, u8 egrp,
+ struct otx2_cpt_rx_inline_lf_cfg *req)
+{
+ struct nix_inline_ipsec_cfg *nix_req;
+ struct pci_dev *pdev = cptpf->pdev;
+ int ret;
+
+ nix_req = (struct nix_inline_ipsec_cfg *)
+ otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0,
+ sizeof(*nix_req),
+ sizeof(struct msg_rsp));
+ if (nix_req == NULL) {
+ dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");
+ return -EFAULT;
+ }
+ memset(nix_req, 0, sizeof(*nix_req));
+ nix_req->hdr.id = MBOX_MSG_NIX_INLINE_IPSEC_CFG;
+ nix_req->hdr.sig = OTX2_MBOX_REQ_SIG;
+ nix_req->enable = 1;
+ if (!req->credit || req->credit > OTX2_CPT_INST_QLEN_MSGS)
+ nix_req->cpt_credit = OTX2_CPT_INST_QLEN_MSGS - 1;
+ else
+ nix_req->cpt_credit = req->credit - 1;
+ nix_req->gen_cfg.egrp = egrp;
+ if (req->opcode)
+ nix_req->gen_cfg.opcode = req->opcode;
+ else
+ nix_req->gen_cfg.opcode = cpt_inline_rx_opcode(pdev);
+ nix_req->gen_cfg.param1 = req->param1;
+ nix_req->gen_cfg.param2 = req->param2;
+ nix_req->inst_qsel.cpt_pf_func = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0);
+ nix_req->inst_qsel.cpt_slot = 0;
+ ret = otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev);
+ if (ret)
+ return ret;
+
+ if (cptpf->has_cpt1) {
+ ret = send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 1);
+ if (ret)
+ return ret;
+ }
+
+ return send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 0);
+}
+
+static int handle_msg_rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf,
+ struct mbox_msghdr *req)
+{
+ struct otx2_cpt_rx_inline_lf_cfg *cfg_req;
+ u8 egrp;
+ int ret;
+
+ cfg_req = (struct otx2_cpt_rx_inline_lf_cfg *)req;
+ if (cptpf->lfs.lfs_num) {
+ dev_err(&cptpf->pdev->dev,
+ "LF is already configured for RX inline ipsec.\n");
+ return -EEXIST;
+ }
+ /*
+ * Allow LFs to execute requests destined to only grp IE_TYPES and
+ * set queue priority of each LF to high
+ */
+ egrp = otx2_cpt_get_eng_grp(&cptpf->eng_grps, OTX2_CPT_IE_TYPES);
+ if (egrp == OTX2_CPT_INVALID_CRYPTO_ENG_GRP) {
+ dev_err(&cptpf->pdev->dev,
+ "Engine group for inline ipsec is not available\n");
+ return -ENOENT;
+ }
+
+ otx2_cptlf_set_dev_info(&cptpf->lfs, cptpf->pdev, cptpf->reg_base,
+ &cptpf->afpf_mbox, BLKADDR_CPT0);
+ ret = otx2_cptlf_init(&cptpf->lfs, 1 << egrp, OTX2_CPT_QUEUE_HI_PRIO,
+ 1);
+ if (ret) {
+ dev_err(&cptpf->pdev->dev,
+ "LF configuration failed for RX inline ipsec.\n");
+ return ret;
+ }
+
+ if (cptpf->has_cpt1) {
+ cptpf->rsrc_req_blkaddr = BLKADDR_CPT1;
+ otx2_cptlf_set_dev_info(&cptpf->cpt1_lfs, cptpf->pdev,
+ cptpf->reg_base, &cptpf->afpf_mbox,
+ BLKADDR_CPT1);
+ ret = otx2_cptlf_init(&cptpf->cpt1_lfs, 1 << egrp,
+ OTX2_CPT_QUEUE_HI_PRIO, 1);
+ if (ret) {
+ dev_err(&cptpf->pdev->dev,
+ "LF configuration failed for RX inline ipsec.\n");
+ goto lf_cleanup;
+ }
+ cptpf->rsrc_req_blkaddr = 0;
+ }
+
+ ret = rx_inline_ipsec_lf_cfg(cptpf, egrp, cfg_req);
+ if (ret)
+ goto lf1_cleanup;
+
+ return 0;
+
+lf1_cleanup:
+ otx2_cptlf_shutdown(&cptpf->cpt1_lfs);
+lf_cleanup:
+ otx2_cptlf_shutdown(&cptpf->lfs);
+ return ret;
+}
+
static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf,
struct otx2_cptvf_info *vf,
struct mbox_msghdr *req, int size)
@@ -132,6 +279,10 @@ static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf,
case MBOX_MSG_GET_KVF_LIMITS:
err = handle_msg_kvf_limits(cptpf, vf, req);
break;
+ case MBOX_MSG_RX_INLINE_IPSEC_LF_CFG:
+ err = handle_msg_rx_inline_ipsec_lf_cfg(cptpf, req);
+ break;
+
default:
err = forward_to_af(cptpf, vf, req, size);
break;
@@ -224,14 +375,28 @@ void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work)
irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg)
{
struct otx2_cptpf_dev *cptpf = arg;
+ struct otx2_mbox_dev *mdev;
+ struct otx2_mbox *mbox;
+ struct mbox_hdr *hdr;
u64 intr;
/* Read the interrupt bits */
intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT);
if (intr & 0x1ULL) {
- /* Schedule work queue function to process the MBOX request */
- queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work);
+ mbox = &cptpf->afpf_mbox;
+ mdev = &mbox->dev[0];
+ hdr = mdev->mbase + mbox->rx_start;
+ if (hdr->num_msgs)
+ /* Schedule work queue function to process the MBOX request */
+ queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work);
+
+ mbox = &cptpf->afpf_mbox_up;
+ mdev = &mbox->dev[0];
+ hdr = mdev->mbase + mbox->rx_start;
+ if (hdr->num_msgs)
+ /* Schedule work queue function to process the MBOX request */
+ queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_up_work);
/* Clear and ack the interrupt */
otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT,
0x1ULL);
@@ -242,6 +407,7 @@ irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg)
static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf,
struct mbox_msghdr *msg)
{
+ struct otx2_cptlfs_info *lfs = &cptpf->lfs;
struct device *dev = &cptpf->pdev->dev;
struct cpt_rd_wr_reg_msg *rsp_rd_wr;
@@ -254,6 +420,8 @@ static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf,
msg->sig, msg->id);
return;
}
+ if (cptpf->rsrc_req_blkaddr == BLKADDR_CPT1)
+ lfs = &cptpf->cpt1_lfs;
switch (msg->id) {
case MBOX_MSG_READY:
@@ -273,11 +441,14 @@ static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf,
break;
case MBOX_MSG_ATTACH_RESOURCES:
if (!msg->rc)
- cptpf->lfs.are_lfs_attached = 1;
+ lfs->are_lfs_attached = 1;
break;
case MBOX_MSG_DETACH_RESOURCES:
if (!msg->rc)
- cptpf->lfs.are_lfs_attached = 0;
+ lfs->are_lfs_attached = 0;
+ break;
+ case MBOX_MSG_CPT_INLINE_IPSEC_CFG:
+ case MBOX_MSG_NIX_INLINE_IPSEC_CFG:
break;
default:
@@ -367,3 +538,71 @@ void otx2_cptpf_afpf_mbox_handler(struct work_struct *work)
}
otx2_mbox_reset(afpf_mbox, 0);
}
+
+static void handle_msg_cpt_inst_lmtst(struct otx2_cptpf_dev *cptpf,
+ struct mbox_msghdr *msg)
+{
+ struct cpt_inst_lmtst_req *req = (struct cpt_inst_lmtst_req *)msg;
+ struct otx2_cptlfs_info *lfs = &cptpf->lfs;
+ struct msg_rsp *rsp;
+
+ if (cptpf->lfs.lfs_num)
+ lfs->ops->send_cmd((union otx2_cpt_inst_s *)req->inst, 1,
+ &lfs->lf[0]);
+
+ rsp = (struct msg_rsp *)otx2_mbox_alloc_msg(&cptpf->afpf_mbox_up, 0,
+ sizeof(*rsp));
+ if (!rsp)
+ return;
+
+ rsp->hdr.id = msg->id;
+ rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
+ rsp->hdr.pcifunc = 0;
+ rsp->hdr.rc = 0;
+}
+
+static void process_afpf_mbox_up_msg(struct otx2_cptpf_dev *cptpf,
+ struct mbox_msghdr *msg)
+{
+ if (msg->id >= MBOX_MSG_MAX) {
+ dev_err(&cptpf->pdev->dev,
+ "MBOX msg with unknown ID %d\n", msg->id);
+ return;
+ }
+
+ switch (msg->id) {
+ case MBOX_MSG_CPT_INST_LMTST:
+ handle_msg_cpt_inst_lmtst(cptpf, msg);
+ break;
+ default:
+ otx2_reply_invalid_msg(&cptpf->afpf_mbox_up, 0, 0, msg->id);
+ }
+}
+
+void otx2_cptpf_afpf_mbox_up_handler(struct work_struct *work)
+{
+ struct otx2_cptpf_dev *cptpf;
+ struct otx2_mbox_dev *mdev;
+ struct mbox_hdr *rsp_hdr;
+ struct mbox_msghdr *msg;
+ struct otx2_mbox *mbox;
+ int offset, i;
+
+ cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_up_work);
+ mbox = &cptpf->afpf_mbox_up;
+ mdev = &mbox->dev[0];
+ /* Sync mbox data into memory */
+ smp_wmb();
+
+ rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
+ offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);
+
+ for (i = 0; i < rsp_hdr->num_msgs; i++) {
+ msg = (struct mbox_msghdr *)(mdev->mbase + offset);
+
+ process_afpf_mbox_up_msg(cptpf, msg);
+
+ offset = mbox->rx_start + msg->next_msgoff;
+ }
+ otx2_mbox_msg_send(mbox, 0);
+}
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c
index 1577986677f6..1958b797a421 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c
@@ -1504,11 +1504,9 @@ int otx2_cpt_discover_eng_capabilities(struct otx2_cptpf_dev *cptpf)
if (ret)
goto delete_grps;
- lfs->pdev = pdev;
- lfs->reg_base = cptpf->reg_base;
- lfs->mbox = &cptpf->afpf_mbox;
- lfs->blkaddr = BLKADDR_CPT0;
- ret = otx2_cptlf_init(&cptpf->lfs, OTX2_CPT_ALL_ENG_GRPS_MASK,
+ otx2_cptlf_set_dev_info(lfs, cptpf->pdev, cptpf->reg_base,
+ &cptpf->afpf_mbox, BLKADDR_CPT0);
+ ret = otx2_cptlf_init(lfs, OTX2_CPT_ALL_ENG_GRPS_MASK,
OTX2_CPT_QUEUE_HI_PRIO, 1);
if (ret)
goto delete_grps;
@@ -1562,7 +1560,7 @@ int otx2_cpt_discover_eng_capabilities(struct otx2_cptpf_dev *cptpf)
free_result:
kfree(result);
lf_cleanup:
- otx2_cptlf_shutdown(&cptpf->lfs);
+ otx2_cptlf_shutdown(lfs);
delete_grps:
delete_engine_grps(pdev, &cptpf->eng_grps);
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf.h b/drivers/crypto/marvell/octeontx2/otx2_cptvf.h
index 4207e2236903..994291e90da1 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptvf.h
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf.h
@@ -19,6 +19,7 @@ struct otx2_cptvf_dev {
struct otx2_mbox pfvf_mbox;
struct work_struct pfvf_mbox_work;
struct workqueue_struct *pfvf_mbox_wq;
+ int blkaddr;
void *bbuf_base;
unsigned long cap_flag;
};
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c
index 6023a7adb70c..bac729c885f9 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c
@@ -277,12 +277,11 @@ static int cptvf_lf_init(struct otx2_cptvf_dev *cptvf)
if (ret)
return ret;
- lfs->reg_base = cptvf->reg_base;
- lfs->pdev = cptvf->pdev;
- lfs->mbox = &cptvf->pfvf_mbox;
-
lfs_num = cptvf->lfs.kvf_limits ? cptvf->lfs.kvf_limits :
num_online_cpus();
+
+ otx2_cptlf_set_dev_info(lfs, cptvf->pdev, cptvf->reg_base,
+ &cptvf->pfvf_mbox, cptvf->blkaddr);
ret = otx2_cptlf_init(lfs, eng_grp_msk, OTX2_CPT_QUEUE_HI_PRIO,
lfs_num);
if (ret)
@@ -380,6 +379,7 @@ static int otx2_cptvf_probe(struct pci_dev *pdev,
if (ret)
goto destroy_pfvf_mbox;
+ cptvf->blkaddr = BLKADDR_CPT0;
/* Initialize CPT LFs */
ret = cptvf_lf_init(cptvf);
if (ret)
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index 20d0dcd50344..4f6ca229ee5e 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/cpumask.h>
#include <linux/slab.h>
@@ -1795,11 +1796,9 @@ static int grab_mdesc_irq_props(struct mdesc_handle *mdesc,
struct spu_mdesc_info *ip,
const char *node_name)
{
- const unsigned int *reg;
- u64 node;
+ u64 node, reg;
- reg = of_get_property(dev->dev.of_node, "reg", NULL);
- if (!reg)
+ if (of_property_read_reg(dev->dev.of_node, 0, &reg, NULL) < 0)
return -ENODEV;
mdesc_for_each_node_by_name(mdesc, node, "virtual-device") {
@@ -1810,7 +1809,7 @@ static int grab_mdesc_irq_props(struct mdesc_handle *mdesc,
if (!name || strcmp(name, node_name))
continue;
chdl = mdesc_get_property(mdesc, node, "cfg-handle", NULL);
- if (!chdl || (*chdl != *reg))
+ if (!chdl || (*chdl != reg))
continue;
ip->cfg_handle = *chdl;
return get_irq_props(mdesc, node, ip);
diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile
index d00181a26dd6..483cef62acee 100644
--- a/drivers/crypto/nx/Makefile
+++ b/drivers/crypto/nx/Makefile
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CRYPTO_DEV_NX_ENCRYPT) += nx-crypto.o
nx-crypto-objs := nx.o \
- nx_debugfs.o \
nx-aes-cbc.o \
nx-aes-ecb.o \
nx-aes-gcm.o \
@@ -11,6 +10,7 @@ nx-crypto-objs := nx.o \
nx-sha256.o \
nx-sha512.o
+nx-crypto-$(CONFIG_DEBUG_FS) += nx_debugfs.o
obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES) += nx-compress-pseries.o nx-compress.o
obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV) += nx-compress-powernv.o nx-compress.o
nx-compress-objs := nx-842.o
diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h
index c6233173c612..2697baebb6a3 100644
--- a/drivers/crypto/nx/nx.h
+++ b/drivers/crypto/nx/nx.h
@@ -170,8 +170,8 @@ struct nx_sg *nx_walk_and_build(struct nx_sg *, unsigned int,
void nx_debugfs_init(struct nx_crypto_driver *);
void nx_debugfs_fini(struct nx_crypto_driver *);
#else
-#define NX_DEBUGFS_INIT(drv) (0)
-#define NX_DEBUGFS_FINI(drv) (0)
+#define NX_DEBUGFS_INIT(drv) do {} while (0)
+#define NX_DEBUGFS_FINI(drv) do {} while (0)
#endif
#define NX_PAGE_NUM(x) ((u64)(x) & 0xfffffffffffff000ULL)
diff --git a/drivers/crypto/sa2ul.h b/drivers/crypto/sa2ul.h
index 92bf97232a29..12c17a68d350 100644
--- a/drivers/crypto/sa2ul.h
+++ b/drivers/crypto/sa2ul.h
@@ -170,7 +170,7 @@ struct sa_tfm_ctx;
* the following range, so avoid using it.
*/
#define SA_UNSAFE_DATA_SZ_MIN 240
-#define SA_UNSAFE_DATA_SZ_MAX 256
+#define SA_UNSAFE_DATA_SZ_MAX 255
struct sa_match_data;
diff --git a/drivers/crypto/starfive/Kconfig b/drivers/crypto/starfive/Kconfig
new file mode 100644
index 000000000000..df745fcb09df
--- /dev/null
+++ b/drivers/crypto/starfive/Kconfig
@@ -0,0 +1,20 @@
+#
+# StarFive crypto drivers configuration
+#
+
+config CRYPTO_DEV_JH7110
+ tristate "StarFive JH7110 cryptographic engine driver"
+ depends on SOC_STARFIVE || AMBA_PL08X || COMPILE_TEST
+ depends on HAS_DMA
+ select CRYPTO_ENGINE
+ select CRYPTO_HMAC
+ select CRYPTO_SHA256
+ select CRYPTO_SHA512
+ select CRYPTO_SM3_GENERIC
+ select CRYPTO_RSA
+ help
+ Support for StarFive JH7110 crypto hardware acceleration engine.
+ This module provides acceleration for public key algo,
+ skciphers, AEAD and hash functions.
+
+ If you choose 'M' here, this module will be called jh7110-crypto.
diff --git a/drivers/crypto/starfive/Makefile b/drivers/crypto/starfive/Makefile
new file mode 100644
index 000000000000..98b01d2f1ccf
--- /dev/null
+++ b/drivers/crypto/starfive/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_CRYPTO_DEV_JH7110) += jh7110-crypto.o
+jh7110-crypto-objs := jh7110-cryp.o jh7110-hash.o jh7110-rsa.o
diff --git a/drivers/crypto/starfive/jh7110-cryp.c b/drivers/crypto/starfive/jh7110-cryp.c
new file mode 100644
index 000000000000..cc43556b6c80
--- /dev/null
+++ b/drivers/crypto/starfive/jh7110-cryp.c
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Cryptographic API.
+ *
+ * Support for StarFive hardware cryptographic engine.
+ * Copyright (c) 2022 StarFive Technology
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+#include "jh7110-cryp.h"
+
+#define DRIVER_NAME "jh7110-crypto"
+
+struct starfive_dev_list {
+ struct list_head dev_list;
+ spinlock_t lock; /* protect dev_list */
+};
+
+static struct starfive_dev_list dev_list = {
+ .dev_list = LIST_HEAD_INIT(dev_list.dev_list),
+ .lock = __SPIN_LOCK_UNLOCKED(dev_list.lock),
+};
+
+struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx)
+{
+ struct starfive_cryp_dev *cryp = NULL, *tmp;
+
+ spin_lock_bh(&dev_list.lock);
+ if (!ctx->cryp) {
+ list_for_each_entry(tmp, &dev_list.dev_list, list) {
+ cryp = tmp;
+ break;
+ }
+ ctx->cryp = cryp;
+ } else {
+ cryp = ctx->cryp;
+ }
+
+ spin_unlock_bh(&dev_list.lock);
+
+ return cryp;
+}
+
+static int starfive_dma_init(struct starfive_cryp_dev *cryp)
+{
+ dma_cap_mask_t mask;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ cryp->tx = dma_request_chan(cryp->dev, "tx");
+ if (IS_ERR(cryp->tx))
+ return dev_err_probe(cryp->dev, PTR_ERR(cryp->tx),
+ "Error requesting tx dma channel.\n");
+
+ cryp->rx = dma_request_chan(cryp->dev, "rx");
+ if (IS_ERR(cryp->rx)) {
+ dma_release_channel(cryp->tx);
+ return dev_err_probe(cryp->dev, PTR_ERR(cryp->rx),
+ "Error requesting rx dma channel.\n");
+ }
+
+ return 0;
+}
+
+static void starfive_dma_cleanup(struct starfive_cryp_dev *cryp)
+{
+ dma_release_channel(cryp->tx);
+ dma_release_channel(cryp->rx);
+}
+
+static irqreturn_t starfive_cryp_irq(int irq, void *priv)
+{
+ u32 status;
+ struct starfive_cryp_dev *cryp = (struct starfive_cryp_dev *)priv;
+
+ status = readl(cryp->base + STARFIVE_IE_FLAG_OFFSET);
+ if (status & STARFIVE_IE_FLAG_HASH_DONE) {
+ status = readl(cryp->base + STARFIVE_IE_MASK_OFFSET);
+ status |= STARFIVE_IE_MASK_HASH_DONE;
+ writel(status, cryp->base + STARFIVE_IE_MASK_OFFSET);
+ tasklet_schedule(&cryp->hash_done);
+ }
+
+ if (status & STARFIVE_IE_FLAG_PKA_DONE) {
+ status = readl(cryp->base + STARFIVE_IE_MASK_OFFSET);
+ status |= STARFIVE_IE_MASK_PKA_DONE;
+ writel(status, cryp->base + STARFIVE_IE_MASK_OFFSET);
+ complete(&cryp->pka_done);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int starfive_cryp_probe(struct platform_device *pdev)
+{
+ struct starfive_cryp_dev *cryp;
+ struct resource *res;
+ int irq;
+ int ret;
+
+ cryp = devm_kzalloc(&pdev->dev, sizeof(*cryp), GFP_KERNEL);
+ if (!cryp)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, cryp);
+ cryp->dev = &pdev->dev;
+
+ cryp->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(cryp->base))
+ return dev_err_probe(&pdev->dev, PTR_ERR(cryp->base),
+ "Error remapping memory for platform device\n");
+
+ tasklet_init(&cryp->hash_done, starfive_hash_done_task, (unsigned long)cryp);
+
+ cryp->phys_base = res->start;
+ cryp->dma_maxburst = 32;
+
+ cryp->hclk = devm_clk_get(&pdev->dev, "hclk");
+ if (IS_ERR(cryp->hclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(cryp->hclk),
+ "Error getting hardware reference clock\n");
+
+ cryp->ahb = devm_clk_get(&pdev->dev, "ahb");
+ if (IS_ERR(cryp->ahb))
+ return dev_err_probe(&pdev->dev, PTR_ERR(cryp->ahb),
+ "Error getting ahb reference clock\n");
+
+ cryp->rst = devm_reset_control_get_shared(cryp->dev, NULL);
+ if (IS_ERR(cryp->rst))
+ return dev_err_probe(&pdev->dev, PTR_ERR(cryp->rst),
+ "Error getting hardware reset line\n");
+
+ init_completion(&cryp->pka_done);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_irq(&pdev->dev, irq, starfive_cryp_irq, 0, pdev->name,
+ (void *)cryp);
+ if (ret)
+ return dev_err_probe(&pdev->dev, irq,
+ "Failed to register interrupt handler\n");
+
+ clk_prepare_enable(cryp->hclk);
+ clk_prepare_enable(cryp->ahb);
+ reset_control_deassert(cryp->rst);
+
+ spin_lock(&dev_list.lock);
+ list_add(&cryp->list, &dev_list.dev_list);
+ spin_unlock(&dev_list.lock);
+
+ ret = starfive_dma_init(cryp);
+ if (ret) {
+ if (ret == -EPROBE_DEFER)
+ goto err_probe_defer;
+ else
+ goto err_dma_init;
+ }
+
+ /* Initialize crypto engine */
+ cryp->engine = crypto_engine_alloc_init(&pdev->dev, 1);
+ if (!cryp->engine) {
+ ret = -ENOMEM;
+ goto err_engine;
+ }
+
+ ret = crypto_engine_start(cryp->engine);
+ if (ret)
+ goto err_engine_start;
+
+ ret = starfive_hash_register_algs();
+ if (ret)
+ goto err_algs_hash;
+
+ ret = starfive_rsa_register_algs();
+ if (ret)
+ goto err_algs_rsa;
+
+ return 0;
+
+err_algs_rsa:
+ starfive_hash_unregister_algs();
+err_algs_hash:
+ crypto_engine_stop(cryp->engine);
+err_engine_start:
+ crypto_engine_exit(cryp->engine);
+err_engine:
+ starfive_dma_cleanup(cryp);
+err_dma_init:
+ spin_lock(&dev_list.lock);
+ list_del(&cryp->list);
+ spin_unlock(&dev_list.lock);
+
+ clk_disable_unprepare(cryp->hclk);
+ clk_disable_unprepare(cryp->ahb);
+ reset_control_assert(cryp->rst);
+
+ tasklet_kill(&cryp->hash_done);
+err_probe_defer:
+ return ret;
+}
+
+static int starfive_cryp_remove(struct platform_device *pdev)
+{
+ struct starfive_cryp_dev *cryp = platform_get_drvdata(pdev);
+
+ starfive_hash_unregister_algs();
+ starfive_rsa_unregister_algs();
+
+ tasklet_kill(&cryp->hash_done);
+
+ crypto_engine_stop(cryp->engine);
+ crypto_engine_exit(cryp->engine);
+
+ starfive_dma_cleanup(cryp);
+
+ spin_lock(&dev_list.lock);
+ list_del(&cryp->list);
+ spin_unlock(&dev_list.lock);
+
+ clk_disable_unprepare(cryp->hclk);
+ clk_disable_unprepare(cryp->ahb);
+ reset_control_assert(cryp->rst);
+
+ return 0;
+}
+
+static const struct of_device_id starfive_dt_ids[] __maybe_unused = {
+ { .compatible = "starfive,jh7110-crypto", .data = NULL},
+ {},
+};
+MODULE_DEVICE_TABLE(of, starfive_dt_ids);
+
+static struct platform_driver starfive_cryp_driver = {
+ .probe = starfive_cryp_probe,
+ .remove = starfive_cryp_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = starfive_dt_ids,
+ },
+};
+
+module_platform_driver(starfive_cryp_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("StarFive JH7110 Cryptographic Module");
diff --git a/drivers/crypto/starfive/jh7110-cryp.h b/drivers/crypto/starfive/jh7110-cryp.h
new file mode 100644
index 000000000000..0cdcffc0d7d4
--- /dev/null
+++ b/drivers/crypto/starfive/jh7110-cryp.h
@@ -0,0 +1,172 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __STARFIVE_STR_H__
+#define __STARFIVE_STR_H__
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+
+#include <crypto/engine.h>
+#include <crypto/sha2.h>
+#include <crypto/sm3.h>
+
+#define STARFIVE_ALG_CR_OFFSET 0x0
+#define STARFIVE_ALG_FIFO_OFFSET 0x4
+#define STARFIVE_IE_MASK_OFFSET 0x8
+#define STARFIVE_IE_FLAG_OFFSET 0xc
+#define STARFIVE_DMA_IN_LEN_OFFSET 0x10
+#define STARFIVE_DMA_OUT_LEN_OFFSET 0x14
+
+#define STARFIVE_IE_MASK_HASH_DONE 0x4
+#define STARFIVE_IE_MASK_PKA_DONE 0x8
+#define STARFIVE_IE_FLAG_HASH_DONE 0x4
+#define STARFIVE_IE_FLAG_PKA_DONE 0x8
+
+#define STARFIVE_MSG_BUFFER_SIZE SZ_16K
+#define MAX_KEY_SIZE SHA512_BLOCK_SIZE
+
+union starfive_hash_csr {
+ u32 v;
+ struct {
+ u32 start :1;
+ u32 reset :1;
+ u32 ie :1;
+ u32 firstb :1;
+#define STARFIVE_HASH_SM3 0x0
+#define STARFIVE_HASH_SHA224 0x3
+#define STARFIVE_HASH_SHA256 0x4
+#define STARFIVE_HASH_SHA384 0x5
+#define STARFIVE_HASH_SHA512 0x6
+#define STARFIVE_HASH_MODE_MASK 0x7
+ u32 mode :3;
+ u32 rsvd_1 :1;
+ u32 final :1;
+ u32 rsvd_2 :2;
+#define STARFIVE_HASH_HMAC_FLAGS 0x800
+ u32 hmac :1;
+ u32 rsvd_3 :1;
+#define STARFIVE_HASH_KEY_DONE BIT(13)
+ u32 key_done :1;
+ u32 key_flag :1;
+ u32 hmac_done :1;
+#define STARFIVE_HASH_BUSY BIT(16)
+ u32 busy :1;
+ u32 hashdone :1;
+ u32 rsvd_4 :14;
+ };
+};
+
+union starfive_pka_cacr {
+ u32 v;
+ struct {
+ u32 start :1;
+ u32 reset :1;
+ u32 ie :1;
+ u32 rsvd_0 :1;
+ u32 fifo_mode :1;
+ u32 not_r2 :1;
+ u32 ecc_sub :1;
+ u32 pre_expf :1;
+ u32 cmd :4;
+ u32 rsvd_1 :1;
+ u32 ctrl_dummy :1;
+ u32 ctrl_false :1;
+ u32 cln_done :1;
+ u32 opsize :6;
+ u32 rsvd_2 :2;
+ u32 exposize :6;
+ u32 rsvd_3 :1;
+ u32 bigendian :1;
+ };
+};
+
+struct starfive_rsa_key {
+ u8 *n;
+ u8 *e;
+ u8 *d;
+ int e_bitlen;
+ int d_bitlen;
+ int bitlen;
+ size_t key_sz;
+};
+
+union starfive_alg_cr {
+ u32 v;
+ struct {
+ u32 start :1;
+ u32 aes_dma_en :1;
+ u32 rsvd_0 :1;
+ u32 hash_dma_en :1;
+ u32 alg_done :1;
+ u32 rsvd_1 :3;
+ u32 clear :1;
+ u32 rsvd_2 :23;
+ };
+};
+
+struct starfive_cryp_ctx {
+ struct crypto_engine_ctx enginectx;
+ struct starfive_cryp_dev *cryp;
+ struct starfive_cryp_request_ctx *rctx;
+
+ unsigned int hash_mode;
+ u8 key[MAX_KEY_SIZE];
+ int keylen;
+ bool is_hmac;
+ struct starfive_rsa_key rsa_key;
+ struct crypto_akcipher *akcipher_fbk;
+ struct crypto_ahash *ahash_fbk;
+};
+
+struct starfive_cryp_dev {
+ struct list_head list;
+ struct device *dev;
+ struct clk *hclk;
+ struct clk *ahb;
+ struct reset_control *rst;
+
+ void __iomem *base;
+ phys_addr_t phys_base;
+
+ u32 dma_maxburst;
+ struct dma_chan *tx;
+ struct dma_chan *rx;
+ struct dma_slave_config cfg_in;
+ struct dma_slave_config cfg_out;
+ struct crypto_engine *engine;
+ struct tasklet_struct hash_done;
+ struct completion pka_done;
+ int err;
+ union starfive_alg_cr alg_cr;
+ union {
+ struct ahash_request *hreq;
+ } req;
+};
+
+struct starfive_cryp_request_ctx {
+ union {
+ union starfive_hash_csr hash;
+ union starfive_pka_cacr pka;
+ } csr;
+
+ struct scatterlist *in_sg;
+ struct scatterlist *out_sg;
+ struct ahash_request ahash_fbk_req;
+ size_t total;
+ size_t nents;
+ unsigned int blksize;
+ unsigned int digsize;
+ unsigned long in_sg_len;
+ u8 rsa_data[] __aligned(sizeof(u32));
+};
+
+struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx);
+
+int starfive_hash_register_algs(void);
+void starfive_hash_unregister_algs(void);
+
+int starfive_rsa_register_algs(void);
+void starfive_rsa_unregister_algs(void);
+
+void starfive_hash_done_task(unsigned long param);
+#endif
diff --git a/drivers/crypto/starfive/jh7110-hash.c b/drivers/crypto/starfive/jh7110-hash.c
new file mode 100644
index 000000000000..5064150b8a1c
--- /dev/null
+++ b/drivers/crypto/starfive/jh7110-hash.c
@@ -0,0 +1,899 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Hash function and HMAC support for StarFive driver
+ *
+ * Copyright (c) 2022 StarFive Technology
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/crypto.h>
+#include <linux/dma-direct.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/amba/pl080.h>
+
+#include <crypto/hash.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/internal/hash.h>
+
+#include "jh7110-cryp.h"
+
+#define STARFIVE_HASH_REGS_OFFSET 0x300
+#define STARFIVE_HASH_SHACSR (STARFIVE_HASH_REGS_OFFSET + 0x0)
+#define STARFIVE_HASH_SHAWDR (STARFIVE_HASH_REGS_OFFSET + 0x4)
+#define STARFIVE_HASH_SHARDR (STARFIVE_HASH_REGS_OFFSET + 0x8)
+#define STARFIVE_HASH_SHAWSR (STARFIVE_HASH_REGS_OFFSET + 0xC)
+#define STARFIVE_HASH_SHAWLEN3 (STARFIVE_HASH_REGS_OFFSET + 0x10)
+#define STARFIVE_HASH_SHAWLEN2 (STARFIVE_HASH_REGS_OFFSET + 0x14)
+#define STARFIVE_HASH_SHAWLEN1 (STARFIVE_HASH_REGS_OFFSET + 0x18)
+#define STARFIVE_HASH_SHAWLEN0 (STARFIVE_HASH_REGS_OFFSET + 0x1C)
+#define STARFIVE_HASH_SHAWKR (STARFIVE_HASH_REGS_OFFSET + 0x20)
+#define STARFIVE_HASH_SHAWKLEN (STARFIVE_HASH_REGS_OFFSET + 0x24)
+
+#define STARFIVE_HASH_BUFLEN SHA512_BLOCK_SIZE
+#define STARFIVE_HASH_RESET 0x2
+
+static inline int starfive_hash_wait_busy(struct starfive_cryp_ctx *ctx)
+{
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+ u32 status;
+
+ return readl_relaxed_poll_timeout(cryp->base + STARFIVE_HASH_SHACSR, status,
+ !(status & STARFIVE_HASH_BUSY), 10, 100000);
+}
+
+static inline int starfive_hash_wait_key_done(struct starfive_cryp_ctx *ctx)
+{
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+ u32 status;
+
+ return readl_relaxed_poll_timeout(cryp->base + STARFIVE_HASH_SHACSR, status,
+ (status & STARFIVE_HASH_KEY_DONE), 10, 100000);
+}
+
+static int starfive_hash_hmac_key(struct starfive_cryp_ctx *ctx)
+{
+ struct starfive_cryp_request_ctx *rctx = ctx->rctx;
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+ int klen = ctx->keylen, loop;
+ unsigned int *key = (unsigned int *)ctx->key;
+ unsigned char *cl;
+
+ writel(ctx->keylen, cryp->base + STARFIVE_HASH_SHAWKLEN);
+
+ rctx->csr.hash.hmac = 1;
+ rctx->csr.hash.key_flag = 1;
+
+ writel(rctx->csr.hash.v, cryp->base + STARFIVE_HASH_SHACSR);
+
+ for (loop = 0; loop < klen / sizeof(unsigned int); loop++, key++)
+ writel(*key, cryp->base + STARFIVE_HASH_SHAWKR);
+
+ if (klen & 0x3) {
+ cl = (unsigned char *)key;
+ for (loop = 0; loop < (klen & 0x3); loop++, cl++)
+ writeb(*cl, cryp->base + STARFIVE_HASH_SHAWKR);
+ }
+
+ if (starfive_hash_wait_key_done(ctx))
+ return dev_err_probe(cryp->dev, -ETIMEDOUT, "starfive_hash_wait_key_done error\n");
+
+ return 0;
+}
+
+static void starfive_hash_start(void *param)
+{
+ struct starfive_cryp_ctx *ctx = param;
+ struct starfive_cryp_request_ctx *rctx = ctx->rctx;
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+ union starfive_alg_cr alg_cr;
+ union starfive_hash_csr csr;
+ u32 stat;
+
+ dma_unmap_sg(cryp->dev, rctx->in_sg, rctx->in_sg_len, DMA_TO_DEVICE);
+
+ alg_cr.v = 0;
+ alg_cr.clear = 1;
+
+ writel(alg_cr.v, cryp->base + STARFIVE_ALG_CR_OFFSET);
+
+ csr.v = readl(cryp->base + STARFIVE_HASH_SHACSR);
+ csr.firstb = 0;
+ csr.final = 1;
+
+ stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET);
+ stat &= ~STARFIVE_IE_MASK_HASH_DONE;
+ writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET);
+ writel(csr.v, cryp->base + STARFIVE_HASH_SHACSR);
+}
+
+static int starfive_hash_xmit_dma(struct starfive_cryp_ctx *ctx)
+{
+ struct starfive_cryp_request_ctx *rctx = ctx->rctx;
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+ struct dma_async_tx_descriptor *in_desc;
+ union starfive_alg_cr alg_cr;
+ int total_len;
+ int ret;
+
+ if (!rctx->total) {
+ starfive_hash_start(ctx);
+ return 0;
+ }
+
+ writel(rctx->total, cryp->base + STARFIVE_DMA_IN_LEN_OFFSET);
+
+ total_len = rctx->total;
+ total_len = (total_len & 0x3) ? (((total_len >> 2) + 1) << 2) : total_len;
+ sg_dma_len(rctx->in_sg) = total_len;
+
+ alg_cr.v = 0;
+ alg_cr.start = 1;
+ alg_cr.hash_dma_en = 1;
+
+ writel(alg_cr.v, cryp->base + STARFIVE_ALG_CR_OFFSET);
+
+ ret = dma_map_sg(cryp->dev, rctx->in_sg, rctx->in_sg_len, DMA_TO_DEVICE);
+ if (!ret)
+ return dev_err_probe(cryp->dev, -EINVAL, "dma_map_sg() error\n");
+
+ cryp->cfg_in.direction = DMA_MEM_TO_DEV;
+ cryp->cfg_in.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ cryp->cfg_in.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ cryp->cfg_in.src_maxburst = cryp->dma_maxburst;
+ cryp->cfg_in.dst_maxburst = cryp->dma_maxburst;
+ cryp->cfg_in.dst_addr = cryp->phys_base + STARFIVE_ALG_FIFO_OFFSET;
+
+ dmaengine_slave_config(cryp->tx, &cryp->cfg_in);
+
+ in_desc = dmaengine_prep_slave_sg(cryp->tx, rctx->in_sg,
+ ret, DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ if (!in_desc)
+ return -EINVAL;
+
+ in_desc->callback = starfive_hash_start;
+ in_desc->callback_param = ctx;
+
+ dmaengine_submit(in_desc);
+ dma_async_issue_pending(cryp->tx);
+
+ return 0;
+}
+
+static int starfive_hash_xmit(struct starfive_cryp_ctx *ctx)
+{
+ struct starfive_cryp_request_ctx *rctx = ctx->rctx;
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+ int ret = 0;
+
+ rctx->csr.hash.v = 0;
+ rctx->csr.hash.reset = 1;
+ writel(rctx->csr.hash.v, cryp->base + STARFIVE_HASH_SHACSR);
+
+ if (starfive_hash_wait_busy(ctx))
+ return dev_err_probe(cryp->dev, -ETIMEDOUT, "Error resetting engine.\n");
+
+ rctx->csr.hash.v = 0;
+ rctx->csr.hash.mode = ctx->hash_mode;
+ rctx->csr.hash.ie = 1;
+
+ if (ctx->is_hmac) {
+ ret = starfive_hash_hmac_key(ctx);
+ if (ret)
+ return ret;
+ } else {
+ rctx->csr.hash.start = 1;
+ rctx->csr.hash.firstb = 1;
+ writel(rctx->csr.hash.v, cryp->base + STARFIVE_HASH_SHACSR);
+ }
+
+ return starfive_hash_xmit_dma(ctx);
+}
+
+static int starfive_hash_copy_hash(struct ahash_request *req)
+{
+ struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req);
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
+ int count, *data;
+ int mlen;
+
+ if (!req->result)
+ return 0;
+
+ mlen = rctx->digsize / sizeof(u32);
+ data = (u32 *)req->result;
+
+ for (count = 0; count < mlen; count++)
+ data[count] = readl(ctx->cryp->base + STARFIVE_HASH_SHARDR);
+
+ return 0;
+}
+
+void starfive_hash_done_task(unsigned long param)
+{
+ struct starfive_cryp_dev *cryp = (struct starfive_cryp_dev *)param;
+ int err = cryp->err;
+
+ if (!err)
+ err = starfive_hash_copy_hash(cryp->req.hreq);
+
+ /* Reset to clear hash_done in irq register*/
+ writel(STARFIVE_HASH_RESET, cryp->base + STARFIVE_HASH_SHACSR);
+
+ crypto_finalize_hash_request(cryp->engine, cryp->req.hreq, err);
+}
+
+static int starfive_hash_check_aligned(struct scatterlist *sg, size_t total, size_t align)
+{
+ int len = 0;
+
+ if (!total)
+ return 0;
+
+ if (!IS_ALIGNED(total, align))
+ return -EINVAL;
+
+ while (sg) {
+ if (!IS_ALIGNED(sg->offset, sizeof(u32)))
+ return -EINVAL;
+
+ if (!IS_ALIGNED(sg->length, align))
+ return -EINVAL;
+
+ len += sg->length;
+ sg = sg_next(sg);
+ }
+
+ if (len != total)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int starfive_hash_one_request(struct crypto_engine *engine, void *areq)
+{
+ struct ahash_request *req = container_of(areq, struct ahash_request,
+ base);
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+
+ if (!cryp)
+ return -ENODEV;
+
+ return starfive_hash_xmit(ctx);
+}
+
+static int starfive_hash_init(struct ahash_request *req)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req);
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk);
+ ahash_request_set_callback(&rctx->ahash_fbk_req,
+ req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->base.complete, req->base.data);
+
+ ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src,
+ req->result, req->nbytes);
+
+ return crypto_ahash_init(&rctx->ahash_fbk_req);
+}
+
+static int starfive_hash_update(struct ahash_request *req)
+{
+ struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk);
+ ahash_request_set_callback(&rctx->ahash_fbk_req,
+ req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->base.complete, req->base.data);
+
+ ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src,
+ req->result, req->nbytes);
+
+ return crypto_ahash_update(&rctx->ahash_fbk_req);
+}
+
+static int starfive_hash_final(struct ahash_request *req)
+{
+ struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk);
+ ahash_request_set_callback(&rctx->ahash_fbk_req,
+ req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->base.complete, req->base.data);
+
+ ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src,
+ req->result, req->nbytes);
+
+ return crypto_ahash_final(&rctx->ahash_fbk_req);
+}
+
+static int starfive_hash_finup(struct ahash_request *req)
+{
+ struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk);
+ ahash_request_set_callback(&rctx->ahash_fbk_req,
+ req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->base.complete, req->base.data);
+
+ ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src,
+ req->result, req->nbytes);
+
+ return crypto_ahash_finup(&rctx->ahash_fbk_req);
+}
+
+static int starfive_hash_digest_fb(struct ahash_request *req)
+{
+ struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk);
+ ahash_request_set_callback(&rctx->ahash_fbk_req, req->base.flags,
+ req->base.complete, req->base.data);
+
+ ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src,
+ req->result, req->nbytes);
+
+ return crypto_ahash_digest(&rctx->ahash_fbk_req);
+}
+
+static int starfive_hash_digest(struct ahash_request *req)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req);
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+
+ memset(rctx, 0, sizeof(struct starfive_cryp_request_ctx));
+
+ cryp->req.hreq = req;
+ rctx->total = req->nbytes;
+ rctx->in_sg = req->src;
+ rctx->blksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+ rctx->digsize = crypto_ahash_digestsize(tfm);
+ rctx->in_sg_len = sg_nents_for_len(rctx->in_sg, rctx->total);
+ ctx->rctx = rctx;
+
+ if (starfive_hash_check_aligned(rctx->in_sg, rctx->total, rctx->blksize))
+ return starfive_hash_digest_fb(req);
+
+ return crypto_transfer_hash_request_to_engine(cryp->engine, req);
+}
+
+static int starfive_hash_export(struct ahash_request *req, void *out)
+{
+ struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk);
+ ahash_request_set_callback(&rctx->ahash_fbk_req,
+ req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->base.complete, req->base.data);
+
+ return crypto_ahash_export(&rctx->ahash_fbk_req, out);
+}
+
+static int starfive_hash_import(struct ahash_request *req, const void *in)
+{
+ struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk);
+ ahash_request_set_callback(&rctx->ahash_fbk_req,
+ req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->base.complete, req->base.data);
+
+ return crypto_ahash_import(&rctx->ahash_fbk_req, in);
+}
+
+static int starfive_hash_init_tfm(struct crypto_ahash *hash,
+ const char *alg_name,
+ unsigned int mode)
+{
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash);
+
+ ctx->cryp = starfive_cryp_find_dev(ctx);
+
+ if (!ctx->cryp)
+ return -ENODEV;
+
+ ctx->ahash_fbk = crypto_alloc_ahash(alg_name, 0,
+ CRYPTO_ALG_NEED_FALLBACK);
+
+ if (IS_ERR(ctx->ahash_fbk))
+ return dev_err_probe(ctx->cryp->dev, PTR_ERR(ctx->ahash_fbk),
+ "starfive_hash: Could not load fallback driver.\n");
+
+ crypto_ahash_set_statesize(hash, crypto_ahash_statesize(ctx->ahash_fbk));
+ crypto_ahash_set_reqsize(hash, sizeof(struct starfive_cryp_request_ctx) +
+ crypto_ahash_reqsize(ctx->ahash_fbk));
+
+ ctx->keylen = 0;
+ ctx->hash_mode = mode;
+
+ ctx->enginectx.op.do_one_request = starfive_hash_one_request;
+ ctx->enginectx.op.prepare_request = NULL;
+ ctx->enginectx.op.unprepare_request = NULL;
+
+ return 0;
+}
+
+static void starfive_hash_exit_tfm(struct crypto_ahash *hash)
+{
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash);
+
+ crypto_free_ahash(ctx->ahash_fbk);
+
+ ctx->ahash_fbk = NULL;
+ ctx->enginectx.op.do_one_request = NULL;
+ ctx->enginectx.op.prepare_request = NULL;
+ ctx->enginectx.op.unprepare_request = NULL;
+}
+
+static int starfive_hash_long_setkey(struct starfive_cryp_ctx *ctx,
+ const u8 *key, unsigned int keylen,
+ const char *alg_name)
+{
+ struct crypto_wait wait;
+ struct ahash_request *req;
+ struct scatterlist sg;
+ struct crypto_ahash *ahash_tfm;
+ u8 *buf;
+ int ret;
+
+ ahash_tfm = crypto_alloc_ahash(alg_name, 0, 0);
+ if (IS_ERR(ahash_tfm))
+ return PTR_ERR(ahash_tfm);
+
+ req = ahash_request_alloc(ahash_tfm, GFP_KERNEL);
+ if (!req) {
+ ret = -ENOMEM;
+ goto err_free_ahash;
+ }
+
+ crypto_init_wait(&wait);
+ ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ crypto_req_done, &wait);
+ crypto_ahash_clear_flags(ahash_tfm, ~0);
+
+ buf = kzalloc(keylen + STARFIVE_HASH_BUFLEN, GFP_KERNEL);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto err_free_req;
+ }
+
+ memcpy(buf, key, keylen);
+ sg_init_one(&sg, buf, keylen);
+ ahash_request_set_crypt(req, &sg, ctx->key, keylen);
+
+ ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
+
+ kfree(buf);
+err_free_req:
+ ahash_request_free(req);
+err_free_ahash:
+ crypto_free_ahash(ahash_tfm);
+ return ret;
+}
+
+static int starfive_hash_setkey(struct crypto_ahash *hash,
+ const u8 *key, unsigned int keylen)
+{
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash);
+ unsigned int digestsize = crypto_ahash_digestsize(hash);
+ unsigned int blocksize = crypto_ahash_blocksize(hash);
+ const char *alg_name;
+
+ crypto_ahash_setkey(ctx->ahash_fbk, key, keylen);
+
+ if (keylen <= blocksize) {
+ memcpy(ctx->key, key, keylen);
+ ctx->keylen = keylen;
+ return 0;
+ }
+
+ ctx->keylen = digestsize;
+
+ switch (digestsize) {
+ case SHA224_DIGEST_SIZE:
+ alg_name = "sha224-starfive";
+ break;
+ case SHA256_DIGEST_SIZE:
+ if (ctx->hash_mode == STARFIVE_HASH_SM3)
+ alg_name = "sm3-starfive";
+ else
+ alg_name = "sha256-starfive";
+ break;
+ case SHA384_DIGEST_SIZE:
+ alg_name = "sha384-starfive";
+ break;
+ case SHA512_DIGEST_SIZE:
+ alg_name = "sha512-starfive";
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return starfive_hash_long_setkey(ctx, key, keylen, alg_name);
+}
+
+static int starfive_sha224_init_tfm(struct crypto_ahash *hash)
+{
+ return starfive_hash_init_tfm(hash, "sha224-generic",
+ STARFIVE_HASH_SHA224);
+}
+
+static int starfive_sha256_init_tfm(struct crypto_ahash *hash)
+{
+ return starfive_hash_init_tfm(hash, "sha256-generic",
+ STARFIVE_HASH_SHA256);
+}
+
+static int starfive_sha384_init_tfm(struct crypto_ahash *hash)
+{
+ return starfive_hash_init_tfm(hash, "sha384-generic",
+ STARFIVE_HASH_SHA384);
+}
+
+static int starfive_sha512_init_tfm(struct crypto_ahash *hash)
+{
+ return starfive_hash_init_tfm(hash, "sha512-generic",
+ STARFIVE_HASH_SHA512);
+}
+
+static int starfive_sm3_init_tfm(struct crypto_ahash *hash)
+{
+ return starfive_hash_init_tfm(hash, "sm3-generic",
+ STARFIVE_HASH_SM3);
+}
+
+static int starfive_hmac_sha224_init_tfm(struct crypto_ahash *hash)
+{
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash);
+
+ ctx->is_hmac = true;
+
+ return starfive_hash_init_tfm(hash, "hmac(sha224-generic)",
+ STARFIVE_HASH_SHA224);
+}
+
+static int starfive_hmac_sha256_init_tfm(struct crypto_ahash *hash)
+{
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash);
+
+ ctx->is_hmac = true;
+
+ return starfive_hash_init_tfm(hash, "hmac(sha256-generic)",
+ STARFIVE_HASH_SHA256);
+}
+
+static int starfive_hmac_sha384_init_tfm(struct crypto_ahash *hash)
+{
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash);
+
+ ctx->is_hmac = true;
+
+ return starfive_hash_init_tfm(hash, "hmac(sha384-generic)",
+ STARFIVE_HASH_SHA384);
+}
+
+static int starfive_hmac_sha512_init_tfm(struct crypto_ahash *hash)
+{
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash);
+
+ ctx->is_hmac = true;
+
+ return starfive_hash_init_tfm(hash, "hmac(sha512-generic)",
+ STARFIVE_HASH_SHA512);
+}
+
+static int starfive_hmac_sm3_init_tfm(struct crypto_ahash *hash)
+{
+ struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash);
+
+ ctx->is_hmac = true;
+
+ return starfive_hash_init_tfm(hash, "hmac(sm3-generic)",
+ STARFIVE_HASH_SM3);
+}
+
+static struct ahash_alg algs_sha2_sm3[] = {
+{
+ .init = starfive_hash_init,
+ .update = starfive_hash_update,
+ .final = starfive_hash_final,
+ .finup = starfive_hash_finup,
+ .digest = starfive_hash_digest,
+ .export = starfive_hash_export,
+ .import = starfive_hash_import,
+ .init_tfm = starfive_sha224_init_tfm,
+ .exit_tfm = starfive_hash_exit_tfm,
+ .halg = {
+ .digestsize = SHA224_DIGEST_SIZE,
+ .statesize = sizeof(struct sha256_state),
+ .base = {
+ .cra_name = "sha224",
+ .cra_driver_name = "sha224-starfive",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA224_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ }
+ }
+}, {
+ .init = starfive_hash_init,
+ .update = starfive_hash_update,
+ .final = starfive_hash_final,
+ .finup = starfive_hash_finup,
+ .digest = starfive_hash_digest,
+ .export = starfive_hash_export,
+ .import = starfive_hash_import,
+ .init_tfm = starfive_hmac_sha224_init_tfm,
+ .exit_tfm = starfive_hash_exit_tfm,
+ .setkey = starfive_hash_setkey,
+ .halg = {
+ .digestsize = SHA224_DIGEST_SIZE,
+ .statesize = sizeof(struct sha256_state),
+ .base = {
+ .cra_name = "hmac(sha224)",
+ .cra_driver_name = "sha224-hmac-starfive",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA224_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ }
+ }
+}, {
+ .init = starfive_hash_init,
+ .update = starfive_hash_update,
+ .final = starfive_hash_final,
+ .finup = starfive_hash_finup,
+ .digest = starfive_hash_digest,
+ .export = starfive_hash_export,
+ .import = starfive_hash_import,
+ .init_tfm = starfive_sha256_init_tfm,
+ .exit_tfm = starfive_hash_exit_tfm,
+ .halg = {
+ .digestsize = SHA256_DIGEST_SIZE,
+ .statesize = sizeof(struct sha256_state),
+ .base = {
+ .cra_name = "sha256",
+ .cra_driver_name = "sha256-starfive",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ }
+ }
+}, {
+ .init = starfive_hash_init,
+ .update = starfive_hash_update,
+ .final = starfive_hash_final,
+ .finup = starfive_hash_finup,
+ .digest = starfive_hash_digest,
+ .export = starfive_hash_export,
+ .import = starfive_hash_import,
+ .init_tfm = starfive_hmac_sha256_init_tfm,
+ .exit_tfm = starfive_hash_exit_tfm,
+ .setkey = starfive_hash_setkey,
+ .halg = {
+ .digestsize = SHA256_DIGEST_SIZE,
+ .statesize = sizeof(struct sha256_state),
+ .base = {
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "sha256-hmac-starfive",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ }
+ }
+}, {
+ .init = starfive_hash_init,
+ .update = starfive_hash_update,
+ .final = starfive_hash_final,
+ .finup = starfive_hash_finup,
+ .digest = starfive_hash_digest,
+ .export = starfive_hash_export,
+ .import = starfive_hash_import,
+ .init_tfm = starfive_sha384_init_tfm,
+ .exit_tfm = starfive_hash_exit_tfm,
+ .halg = {
+ .digestsize = SHA384_DIGEST_SIZE,
+ .statesize = sizeof(struct sha512_state),
+ .base = {
+ .cra_name = "sha384",
+ .cra_driver_name = "sha384-starfive",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA384_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ }
+ }
+}, {
+ .init = starfive_hash_init,
+ .update = starfive_hash_update,
+ .final = starfive_hash_final,
+ .finup = starfive_hash_finup,
+ .digest = starfive_hash_digest,
+ .export = starfive_hash_export,
+ .import = starfive_hash_import,
+ .init_tfm = starfive_hmac_sha384_init_tfm,
+ .exit_tfm = starfive_hash_exit_tfm,
+ .setkey = starfive_hash_setkey,
+ .halg = {
+ .digestsize = SHA384_DIGEST_SIZE,
+ .statesize = sizeof(struct sha512_state),
+ .base = {
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "sha384-hmac-starfive",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA384_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ }
+ }
+}, {
+ .init = starfive_hash_init,
+ .update = starfive_hash_update,
+ .final = starfive_hash_final,
+ .finup = starfive_hash_finup,
+ .digest = starfive_hash_digest,
+ .export = starfive_hash_export,
+ .import = starfive_hash_import,
+ .init_tfm = starfive_sha512_init_tfm,
+ .exit_tfm = starfive_hash_exit_tfm,
+ .halg = {
+ .digestsize = SHA512_DIGEST_SIZE,
+ .statesize = sizeof(struct sha512_state),
+ .base = {
+ .cra_name = "sha512",
+ .cra_driver_name = "sha512-starfive",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA512_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ }
+ }
+}, {
+ .init = starfive_hash_init,
+ .update = starfive_hash_update,
+ .final = starfive_hash_final,
+ .finup = starfive_hash_finup,
+ .digest = starfive_hash_digest,
+ .export = starfive_hash_export,
+ .import = starfive_hash_import,
+ .init_tfm = starfive_hmac_sha512_init_tfm,
+ .exit_tfm = starfive_hash_exit_tfm,
+ .setkey = starfive_hash_setkey,
+ .halg = {
+ .digestsize = SHA512_DIGEST_SIZE,
+ .statesize = sizeof(struct sha512_state),
+ .base = {
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "sha512-hmac-starfive",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA512_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ }
+ }
+}, {
+ .init = starfive_hash_init,
+ .update = starfive_hash_update,
+ .final = starfive_hash_final,
+ .finup = starfive_hash_finup,
+ .digest = starfive_hash_digest,
+ .export = starfive_hash_export,
+ .import = starfive_hash_import,
+ .init_tfm = starfive_sm3_init_tfm,
+ .exit_tfm = starfive_hash_exit_tfm,
+ .halg = {
+ .digestsize = SM3_DIGEST_SIZE,
+ .statesize = sizeof(struct sm3_state),
+ .base = {
+ .cra_name = "sm3",
+ .cra_driver_name = "sm3-starfive",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SM3_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ }
+ }
+}, {
+ .init = starfive_hash_init,
+ .update = starfive_hash_update,
+ .final = starfive_hash_final,
+ .finup = starfive_hash_finup,
+ .digest = starfive_hash_digest,
+ .export = starfive_hash_export,
+ .import = starfive_hash_import,
+ .init_tfm = starfive_hmac_sm3_init_tfm,
+ .exit_tfm = starfive_hash_exit_tfm,
+ .setkey = starfive_hash_setkey,
+ .halg = {
+ .digestsize = SM3_DIGEST_SIZE,
+ .statesize = sizeof(struct sm3_state),
+ .base = {
+ .cra_name = "hmac(sm3)",
+ .cra_driver_name = "sm3-hmac-starfive",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SM3_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ }
+ }
+},
+};
+
+int starfive_hash_register_algs(void)
+{
+ return crypto_register_ahashes(algs_sha2_sm3, ARRAY_SIZE(algs_sha2_sm3));
+}
+
+void starfive_hash_unregister_algs(void)
+{
+ crypto_unregister_ahashes(algs_sha2_sm3, ARRAY_SIZE(algs_sha2_sm3));
+}
diff --git a/drivers/crypto/starfive/jh7110-rsa.c b/drivers/crypto/starfive/jh7110-rsa.c
new file mode 100644
index 000000000000..f31bbd825f88
--- /dev/null
+++ b/drivers/crypto/starfive/jh7110-rsa.c
@@ -0,0 +1,617 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * StarFive Public Key Algo acceleration driver
+ *
+ * Copyright (c) 2022 StarFive Technology
+ */
+
+#include <linux/crypto.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-direct.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <crypto/akcipher.h>
+#include <crypto/algapi.h>
+#include <crypto/internal/akcipher.h>
+#include <crypto/internal/rsa.h>
+#include <crypto/scatterwalk.h>
+
+#include "jh7110-cryp.h"
+
+#define STARFIVE_PKA_REGS_OFFSET 0x400
+#define STARFIVE_PKA_CACR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x0)
+#define STARFIVE_PKA_CASR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x4)
+#define STARFIVE_PKA_CAAR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x8)
+#define STARFIVE_PKA_CAER_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x108)
+#define STARFIVE_PKA_CANR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x208)
+
+// R^2 mod N and N0'
+#define CRYPTO_CMD_PRE 0x0
+// A * R mod N ==> A
+#define CRYPTO_CMD_ARN 0x5
+// A * E * R mod N ==> A
+#define CRYPTO_CMD_AERN 0x6
+// A * A * R mod N ==> A
+#define CRYPTO_CMD_AARN 0x7
+
+#define STARFIVE_RSA_MAX_KEYSZ 256
+#define STARFIVE_RSA_RESET 0x2
+
+static inline int starfive_pka_wait_done(struct starfive_cryp_ctx *ctx)
+{
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+
+ return wait_for_completion_timeout(&cryp->pka_done,
+ usecs_to_jiffies(100000));
+}
+
+static inline void starfive_pka_irq_mask_clear(struct starfive_cryp_ctx *ctx)
+{
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+ u32 stat;
+
+ stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET);
+ stat &= ~STARFIVE_IE_MASK_PKA_DONE;
+ writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET);
+
+ reinit_completion(&cryp->pka_done);
+}
+
+static void starfive_rsa_free_key(struct starfive_rsa_key *key)
+{
+ if (key->d)
+ kfree_sensitive(key->d);
+ if (key->e)
+ kfree_sensitive(key->e);
+ if (key->n)
+ kfree_sensitive(key->n);
+ memset(key, 0, sizeof(*key));
+}
+
+static unsigned int starfive_rsa_get_nbit(u8 *pa, u32 snum, int key_sz)
+{
+ u32 i;
+ u8 value;
+
+ i = snum >> 3;
+
+ value = pa[key_sz - i - 1];
+ value >>= snum & 0x7;
+ value &= 0x1;
+
+ return value;
+}
+
+static int starfive_rsa_montgomery_form(struct starfive_cryp_ctx *ctx,
+ u32 *out, u32 *in, u8 mont,
+ u32 *mod, int bit_len)
+{
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+ struct starfive_cryp_request_ctx *rctx = ctx->rctx;
+ int count = rctx->total / sizeof(u32) - 1;
+ int loop;
+ u32 temp;
+ u8 opsize;
+
+ opsize = (bit_len - 1) >> 5;
+ rctx->csr.pka.v = 0;
+
+ writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
+
+ for (loop = 0; loop <= opsize; loop++)
+ writel(mod[opsize - loop], cryp->base + STARFIVE_PKA_CANR_OFFSET + loop * 4);
+
+ if (mont) {
+ rctx->csr.pka.v = 0;
+ rctx->csr.pka.cln_done = 1;
+ rctx->csr.pka.opsize = opsize;
+ rctx->csr.pka.exposize = opsize;
+ rctx->csr.pka.cmd = CRYPTO_CMD_PRE;
+ rctx->csr.pka.start = 1;
+ rctx->csr.pka.not_r2 = 1;
+ rctx->csr.pka.ie = 1;
+
+ starfive_pka_irq_mask_clear(ctx);
+ writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
+
+ if (!starfive_pka_wait_done(ctx))
+ return -ETIMEDOUT;
+
+ for (loop = 0; loop <= opsize; loop++)
+ writel(in[opsize - loop], cryp->base + STARFIVE_PKA_CAAR_OFFSET + loop * 4);
+
+ writel(0x1000000, cryp->base + STARFIVE_PKA_CAER_OFFSET);
+
+ for (loop = 1; loop <= opsize; loop++)
+ writel(0, cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4);
+
+ rctx->csr.pka.v = 0;
+ rctx->csr.pka.cln_done = 1;
+ rctx->csr.pka.opsize = opsize;
+ rctx->csr.pka.exposize = opsize;
+ rctx->csr.pka.cmd = CRYPTO_CMD_AERN;
+ rctx->csr.pka.start = 1;
+ rctx->csr.pka.ie = 1;
+
+ starfive_pka_irq_mask_clear(ctx);
+ writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
+
+ if (!starfive_pka_wait_done(ctx))
+ return -ETIMEDOUT;
+ } else {
+ rctx->csr.pka.v = 0;
+ rctx->csr.pka.cln_done = 1;
+ rctx->csr.pka.opsize = opsize;
+ rctx->csr.pka.exposize = opsize;
+ rctx->csr.pka.cmd = CRYPTO_CMD_PRE;
+ rctx->csr.pka.start = 1;
+ rctx->csr.pka.pre_expf = 1;
+ rctx->csr.pka.ie = 1;
+
+ starfive_pka_irq_mask_clear(ctx);
+ writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
+
+ if (!starfive_pka_wait_done(ctx))
+ return -ETIMEDOUT;
+
+ for (loop = 0; loop <= count; loop++)
+ writel(in[count - loop], cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4);
+
+ /*pad with 0 up to opsize*/
+ for (loop = count + 1; loop <= opsize; loop++)
+ writel(0, cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4);
+
+ rctx->csr.pka.v = 0;
+ rctx->csr.pka.cln_done = 1;
+ rctx->csr.pka.opsize = opsize;
+ rctx->csr.pka.exposize = opsize;
+ rctx->csr.pka.cmd = CRYPTO_CMD_ARN;
+ rctx->csr.pka.start = 1;
+ rctx->csr.pka.ie = 1;
+
+ starfive_pka_irq_mask_clear(ctx);
+ writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
+
+ if (!starfive_pka_wait_done(ctx))
+ return -ETIMEDOUT;
+ }
+
+ for (loop = 0; loop <= opsize; loop++) {
+ temp = readl(cryp->base + STARFIVE_PKA_CAAR_OFFSET + 0x4 * loop);
+ out[opsize - loop] = temp;
+ }
+
+ return 0;
+}
+
+static int starfive_rsa_cpu_start(struct starfive_cryp_ctx *ctx, u32 *result,
+ u8 *de, u32 *n, int key_sz)
+{
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+ struct starfive_cryp_request_ctx *rctx = ctx->rctx;
+ struct starfive_rsa_key *key = &ctx->rsa_key;
+ u32 temp;
+ int ret = 0;
+ int opsize, mlen, loop;
+ unsigned int *mta;
+
+ opsize = (key_sz - 1) >> 2;
+
+ mta = kmalloc(key_sz, GFP_KERNEL);
+ if (!mta)
+ return -ENOMEM;
+
+ ret = starfive_rsa_montgomery_form(ctx, mta, (u32 *)rctx->rsa_data,
+ 0, n, key_sz << 3);
+ if (ret) {
+ dev_err_probe(cryp->dev, ret, "Conversion to Montgomery failed");
+ goto rsa_err;
+ }
+
+ for (loop = 0; loop <= opsize; loop++)
+ writel(mta[opsize - loop],
+ cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4);
+
+ for (loop = key->bitlen - 1; loop > 0; loop--) {
+ mlen = starfive_rsa_get_nbit(de, loop - 1, key_sz);
+
+ rctx->csr.pka.v = 0;
+ rctx->csr.pka.cln_done = 1;
+ rctx->csr.pka.opsize = opsize;
+ rctx->csr.pka.exposize = opsize;
+ rctx->csr.pka.cmd = CRYPTO_CMD_AARN;
+ rctx->csr.pka.start = 1;
+ rctx->csr.pka.ie = 1;
+
+ starfive_pka_irq_mask_clear(ctx);
+ writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
+
+ ret = -ETIMEDOUT;
+ if (!starfive_pka_wait_done(ctx))
+ goto rsa_err;
+
+ if (mlen) {
+ rctx->csr.pka.v = 0;
+ rctx->csr.pka.cln_done = 1;
+ rctx->csr.pka.opsize = opsize;
+ rctx->csr.pka.exposize = opsize;
+ rctx->csr.pka.cmd = CRYPTO_CMD_AERN;
+ rctx->csr.pka.start = 1;
+ rctx->csr.pka.ie = 1;
+
+ starfive_pka_irq_mask_clear(ctx);
+ writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
+
+ if (!starfive_pka_wait_done(ctx))
+ goto rsa_err;
+ }
+ }
+
+ for (loop = 0; loop <= opsize; loop++) {
+ temp = readl(cryp->base + STARFIVE_PKA_CAAR_OFFSET + 0x4 * loop);
+ result[opsize - loop] = temp;
+ }
+
+ ret = starfive_rsa_montgomery_form(ctx, result, result, 1, n, key_sz << 3);
+ if (ret)
+ dev_err_probe(cryp->dev, ret, "Conversion from Montgomery failed");
+rsa_err:
+ kfree(mta);
+ return ret;
+}
+
+static int starfive_rsa_start(struct starfive_cryp_ctx *ctx, u8 *result,
+ u8 *de, u8 *n, int key_sz)
+{
+ return starfive_rsa_cpu_start(ctx, (u32 *)result, de, (u32 *)n, key_sz);
+}
+
+static int starfive_rsa_enc_core(struct starfive_cryp_ctx *ctx, int enc)
+{
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+ struct starfive_cryp_request_ctx *rctx = ctx->rctx;
+ struct starfive_rsa_key *key = &ctx->rsa_key;
+ int ret = 0;
+
+ writel(STARFIVE_RSA_RESET, cryp->base + STARFIVE_PKA_CACR_OFFSET);
+
+ rctx->total = sg_copy_to_buffer(rctx->in_sg, rctx->nents,
+ rctx->rsa_data, rctx->total);
+
+ if (enc) {
+ key->bitlen = key->e_bitlen;
+ ret = starfive_rsa_start(ctx, rctx->rsa_data, key->e,
+ key->n, key->key_sz);
+ } else {
+ key->bitlen = key->d_bitlen;
+ ret = starfive_rsa_start(ctx, rctx->rsa_data, key->d,
+ key->n, key->key_sz);
+ }
+
+ if (ret)
+ goto err_rsa_crypt;
+
+ sg_copy_buffer(rctx->out_sg, sg_nents(rctx->out_sg),
+ rctx->rsa_data, key->key_sz, 0, 0);
+
+err_rsa_crypt:
+ writel(STARFIVE_RSA_RESET, cryp->base + STARFIVE_PKA_CACR_OFFSET);
+ kfree(rctx->rsa_data);
+ return ret;
+}
+
+static int starfive_rsa_enc(struct akcipher_request *req)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+ struct starfive_rsa_key *key = &ctx->rsa_key;
+ struct starfive_cryp_request_ctx *rctx = akcipher_request_ctx(req);
+ int ret;
+
+ if (!key->key_sz) {
+ akcipher_request_set_tfm(req, ctx->akcipher_fbk);
+ ret = crypto_akcipher_encrypt(req);
+ akcipher_request_set_tfm(req, tfm);
+ return ret;
+ }
+
+ if (unlikely(!key->n || !key->e))
+ return -EINVAL;
+
+ if (req->dst_len < key->key_sz)
+ return dev_err_probe(cryp->dev, -EOVERFLOW,
+ "Output buffer length less than parameter n\n");
+
+ rctx->in_sg = req->src;
+ rctx->out_sg = req->dst;
+ rctx->total = req->src_len;
+ rctx->nents = sg_nents(rctx->in_sg);
+ ctx->rctx = rctx;
+
+ return starfive_rsa_enc_core(ctx, 1);
+}
+
+static int starfive_rsa_dec(struct akcipher_request *req)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct starfive_cryp_dev *cryp = ctx->cryp;
+ struct starfive_rsa_key *key = &ctx->rsa_key;
+ struct starfive_cryp_request_ctx *rctx = akcipher_request_ctx(req);
+ int ret;
+
+ if (!key->key_sz) {
+ akcipher_request_set_tfm(req, ctx->akcipher_fbk);
+ ret = crypto_akcipher_decrypt(req);
+ akcipher_request_set_tfm(req, tfm);
+ return ret;
+ }
+
+ if (unlikely(!key->n || !key->d))
+ return -EINVAL;
+
+ if (req->dst_len < key->key_sz)
+ return dev_err_probe(cryp->dev, -EOVERFLOW,
+ "Output buffer length less than parameter n\n");
+
+ rctx->in_sg = req->src;
+ rctx->out_sg = req->dst;
+ ctx->rctx = rctx;
+ rctx->total = req->src_len;
+
+ return starfive_rsa_enc_core(ctx, 0);
+}
+
+static int starfive_rsa_set_n(struct starfive_rsa_key *rsa_key,
+ const char *value, size_t vlen)
+{
+ const char *ptr = value;
+ unsigned int bitslen;
+ int ret;
+
+ while (!*ptr && vlen) {
+ ptr++;
+ vlen--;
+ }
+ rsa_key->key_sz = vlen;
+ bitslen = rsa_key->key_sz << 3;
+
+ /* check valid key size */
+ if (bitslen & 0x1f)
+ return -EINVAL;
+
+ ret = -ENOMEM;
+ rsa_key->n = kmemdup(ptr, rsa_key->key_sz, GFP_KERNEL);
+ if (!rsa_key->n)
+ goto err;
+
+ return 0;
+ err:
+ rsa_key->key_sz = 0;
+ rsa_key->n = NULL;
+ starfive_rsa_free_key(rsa_key);
+ return ret;
+}
+
+static int starfive_rsa_set_e(struct starfive_rsa_key *rsa_key,
+ const char *value, size_t vlen)
+{
+ const char *ptr = value;
+ unsigned char pt;
+ int loop;
+
+ while (!*ptr && vlen) {
+ ptr++;
+ vlen--;
+ }
+ pt = *ptr;
+
+ if (!rsa_key->key_sz || !vlen || vlen > rsa_key->key_sz) {
+ rsa_key->e = NULL;
+ return -EINVAL;
+ }
+
+ rsa_key->e = kzalloc(rsa_key->key_sz, GFP_KERNEL);
+ if (!rsa_key->e)
+ return -ENOMEM;
+
+ for (loop = 8; loop > 0; loop--) {
+ if (pt >> (loop - 1))
+ break;
+ }
+
+ rsa_key->e_bitlen = (vlen - 1) * 8 + loop;
+
+ memcpy(rsa_key->e + (rsa_key->key_sz - vlen), ptr, vlen);
+
+ return 0;
+}
+
+static int starfive_rsa_set_d(struct starfive_rsa_key *rsa_key,
+ const char *value, size_t vlen)
+{
+ const char *ptr = value;
+ unsigned char pt;
+ int loop;
+ int ret;
+
+ while (!*ptr && vlen) {
+ ptr++;
+ vlen--;
+ }
+ pt = *ptr;
+
+ ret = -EINVAL;
+ if (!rsa_key->key_sz || !vlen || vlen > rsa_key->key_sz)
+ goto err;
+
+ ret = -ENOMEM;
+ rsa_key->d = kzalloc(rsa_key->key_sz, GFP_KERNEL);
+ if (!rsa_key->d)
+ goto err;
+
+ for (loop = 8; loop > 0; loop--) {
+ if (pt >> (loop - 1))
+ break;
+ }
+
+ rsa_key->d_bitlen = (vlen - 1) * 8 + loop;
+
+ memcpy(rsa_key->d + (rsa_key->key_sz - vlen), ptr, vlen);
+
+ return 0;
+ err:
+ rsa_key->d = NULL;
+ return ret;
+}
+
+static int starfive_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen, bool private)
+{
+ struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_key raw_key = {NULL};
+ struct starfive_rsa_key *rsa_key = &ctx->rsa_key;
+ int ret;
+
+ if (private)
+ ret = rsa_parse_priv_key(&raw_key, key, keylen);
+ else
+ ret = rsa_parse_pub_key(&raw_key, key, keylen);
+ if (ret < 0)
+ goto err;
+
+ starfive_rsa_free_key(rsa_key);
+
+ /* Use fallback for mod > 256 + 1 byte prefix */
+ if (raw_key.n_sz > STARFIVE_RSA_MAX_KEYSZ + 1)
+ return 0;
+
+ ret = starfive_rsa_set_n(rsa_key, raw_key.n, raw_key.n_sz);
+ if (ret)
+ return ret;
+
+ ret = starfive_rsa_set_e(rsa_key, raw_key.e, raw_key.e_sz);
+ if (ret)
+ goto err;
+
+ if (private) {
+ ret = starfive_rsa_set_d(rsa_key, raw_key.d, raw_key.d_sz);
+ if (ret)
+ goto err;
+ }
+
+ if (!rsa_key->n || !rsa_key->e) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (private && !rsa_key->d) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ return 0;
+ err:
+ starfive_rsa_free_key(rsa_key);
+ return ret;
+}
+
+static int starfive_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
+ int ret;
+
+ ret = crypto_akcipher_set_pub_key(ctx->akcipher_fbk, key, keylen);
+ if (ret)
+ return ret;
+
+ return starfive_rsa_setkey(tfm, key, keylen, false);
+}
+
+static int starfive_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
+ int ret;
+
+ ret = crypto_akcipher_set_priv_key(ctx->akcipher_fbk, key, keylen);
+ if (ret)
+ return ret;
+
+ return starfive_rsa_setkey(tfm, key, keylen, true);
+}
+
+static unsigned int starfive_rsa_max_size(struct crypto_akcipher *tfm)
+{
+ struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+ if (ctx->rsa_key.key_sz)
+ return ctx->rsa_key.key_sz;
+
+ return crypto_akcipher_maxsize(ctx->akcipher_fbk);
+}
+
+static int starfive_rsa_init_tfm(struct crypto_akcipher *tfm)
+{
+ struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+ ctx->akcipher_fbk = crypto_alloc_akcipher("rsa-generic", 0, 0);
+ if (IS_ERR(ctx->akcipher_fbk))
+ return PTR_ERR(ctx->akcipher_fbk);
+
+ ctx->cryp = starfive_cryp_find_dev(ctx);
+ if (!ctx->cryp) {
+ crypto_free_akcipher(ctx->akcipher_fbk);
+ return -ENODEV;
+ }
+
+ akcipher_set_reqsize(tfm, sizeof(struct starfive_cryp_request_ctx) +
+ sizeof(struct crypto_akcipher) + 32);
+
+ return 0;
+}
+
+static void starfive_rsa_exit_tfm(struct crypto_akcipher *tfm)
+{
+ struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct starfive_rsa_key *key = (struct starfive_rsa_key *)&ctx->rsa_key;
+
+ crypto_free_akcipher(ctx->akcipher_fbk);
+ starfive_rsa_free_key(key);
+}
+
+static struct akcipher_alg starfive_rsa = {
+ .encrypt = starfive_rsa_enc,
+ .decrypt = starfive_rsa_dec,
+ .sign = starfive_rsa_dec,
+ .verify = starfive_rsa_enc,
+ .set_pub_key = starfive_rsa_set_pub_key,
+ .set_priv_key = starfive_rsa_set_priv_key,
+ .max_size = starfive_rsa_max_size,
+ .init = starfive_rsa_init_tfm,
+ .exit = starfive_rsa_exit_tfm,
+ .base = {
+ .cra_name = "rsa",
+ .cra_driver_name = "starfive-rsa",
+ .cra_flags = CRYPTO_ALG_TYPE_AKCIPHER |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_priority = 3000,
+ .cra_module = THIS_MODULE,
+ .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
+ },
+};
+
+int starfive_rsa_register_algs(void)
+{
+ return crypto_register_akcipher(&starfive_rsa);
+}
+
+void starfive_rsa_unregister_algs(void)
+{
+ crypto_unregister_akcipher(&starfive_rsa);
+}
diff --git a/drivers/crypto/virtio/virtio_crypto_core.c b/drivers/crypto/virtio/virtio_crypto_core.c
index 1198bd306365..94849fa3bd74 100644
--- a/drivers/crypto/virtio/virtio_crypto_core.c
+++ b/drivers/crypto/virtio/virtio_crypto_core.c
@@ -480,6 +480,7 @@ static void virtcrypto_free_unused_reqs(struct virtio_crypto *vcrypto)
kfree(vc_req->req_data);
kfree(vc_req->sgs);
}
+ cond_resched();
}
}
diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig
index ff4e78117b31..fcbf8295fde3 100644
--- a/drivers/cxl/Kconfig
+++ b/drivers/cxl/Kconfig
@@ -82,6 +82,7 @@ config CXL_PMEM
config CXL_MEM
tristate "CXL: Memory Expansion"
depends on CXL_PCI
+ select FW_UPLOAD
default CXL_BUS
help
The CXL.mem protocol allows a device to act as a provider of "System
@@ -139,4 +140,17 @@ config CXL_REGION_INVALIDATION_TEST
If unsure, or if this kernel is meant for production environments,
say N.
+config CXL_PMU
+ tristate "CXL Performance Monitoring Unit"
+ default CXL_BUS
+ depends on PERF_EVENTS
+ help
+ Support performance monitoring as defined in CXL rev 3.0
+ section 13.2: Performance Monitoring. CXL components may have
+ one or more CXL Performance Monitoring Units (CPMUs).
+
+ Say 'y/m' to enable a driver that will attach to performance
+ monitoring units and provide standard perf based interfaces.
+
+ If unsure say 'm'.
endif
diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
index 7e1765b09e04..658e6b84a769 100644
--- a/drivers/cxl/acpi.c
+++ b/drivers/cxl/acpi.c
@@ -258,7 +258,7 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
cxld = &cxlrd->cxlsd.cxld;
cxld->flags = cfmws_to_decoder_flags(cfmws->restrictions);
- cxld->target_type = CXL_DECODER_EXPANDER;
+ cxld->target_type = CXL_DECODER_HOSTONLYMEM;
cxld->hpa_range = (struct range) {
.start = res->start,
.end = res->end,
@@ -327,66 +327,21 @@ __mock struct acpi_device *to_cxl_host_bridge(struct device *host,
return NULL;
}
-/*
- * A host bridge is a dport to a CFMWS decode and it is a uport to the
- * dport (PCIe Root Ports) in the host bridge.
- */
-static int add_host_bridge_uport(struct device *match, void *arg)
-{
- struct cxl_port *root_port = arg;
- struct device *host = root_port->dev.parent;
- struct acpi_device *hb = to_cxl_host_bridge(host, match);
- struct acpi_pci_root *pci_root;
- struct cxl_dport *dport;
- struct cxl_port *port;
- struct device *bridge;
- int rc;
-
- if (!hb)
- return 0;
-
- pci_root = acpi_pci_find_root(hb->handle);
- bridge = pci_root->bus->bridge;
- dport = cxl_find_dport_by_dev(root_port, bridge);
- if (!dport) {
- dev_dbg(host, "host bridge expected and not found\n");
- return 0;
- }
-
- if (dport->rch) {
- dev_info(bridge, "host supports CXL (restricted)\n");
- return 0;
- }
-
- rc = devm_cxl_register_pci_bus(host, bridge, pci_root->bus);
- if (rc)
- return rc;
-
- port = devm_cxl_add_port(host, bridge, dport->component_reg_phys,
- dport);
- if (IS_ERR(port))
- return PTR_ERR(port);
-
- dev_info(bridge, "host supports CXL\n");
-
- return 0;
-}
-
+/* Note, @dev is used by mock_acpi_table_parse_cedt() */
struct cxl_chbs_context {
struct device *dev;
unsigned long long uid;
- resource_size_t rcrb;
- resource_size_t chbcr;
+ resource_size_t base;
u32 cxl_version;
};
-static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,
- const unsigned long end)
+static int cxl_get_chbs_iter(union acpi_subtable_headers *header, void *arg,
+ const unsigned long end)
{
struct cxl_chbs_context *ctx = arg;
struct acpi_cedt_chbs *chbs;
- if (ctx->chbcr)
+ if (ctx->base != CXL_RESOURCE_NONE)
return 0;
chbs = (struct acpi_cedt_chbs *) header;
@@ -395,23 +350,39 @@ static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,
return 0;
ctx->cxl_version = chbs->cxl_version;
- ctx->rcrb = CXL_RESOURCE_NONE;
- ctx->chbcr = CXL_RESOURCE_NONE;
-
if (!chbs->base)
return 0;
- if (chbs->cxl_version != ACPI_CEDT_CHBS_VERSION_CXL11) {
- ctx->chbcr = chbs->base;
+ if (chbs->cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11 &&
+ chbs->length != CXL_RCRB_SIZE)
return 0;
+
+ ctx->base = chbs->base;
+
+ return 0;
+}
+
+static int cxl_get_chbs(struct device *dev, struct acpi_device *hb,
+ struct cxl_chbs_context *ctx)
+{
+ unsigned long long uid;
+ int rc;
+
+ rc = acpi_evaluate_integer(hb->handle, METHOD_NAME__UID, NULL, &uid);
+ if (rc != AE_OK) {
+ dev_err(dev, "unable to retrieve _UID\n");
+ return -ENOENT;
}
- if (chbs->length != CXL_RCRB_SIZE)
- return 0;
+ dev_dbg(dev, "UID found: %lld\n", uid);
+ *ctx = (struct cxl_chbs_context) {
+ .dev = dev,
+ .uid = uid,
+ .base = CXL_RESOURCE_NONE,
+ .cxl_version = UINT_MAX,
+ };
- ctx->rcrb = chbs->base;
- ctx->chbcr = cxl_rcrb_to_component(ctx->dev, chbs->base,
- CXL_RCRB_DOWNSTREAM);
+ acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbs_iter, ctx);
return 0;
}
@@ -420,7 +391,6 @@ static int add_host_bridge_dport(struct device *match, void *arg)
{
acpi_status rc;
struct device *bridge;
- unsigned long long uid;
struct cxl_dport *dport;
struct cxl_chbs_context ctx;
struct acpi_pci_root *pci_root;
@@ -431,51 +401,107 @@ static int add_host_bridge_dport(struct device *match, void *arg)
if (!hb)
return 0;
- rc = acpi_evaluate_integer(hb->handle, METHOD_NAME__UID, NULL, &uid);
- if (rc != AE_OK) {
- dev_err(match, "unable to retrieve _UID\n");
- return -ENODEV;
- }
-
- dev_dbg(match, "UID found: %lld\n", uid);
-
- ctx = (struct cxl_chbs_context) {
- .dev = match,
- .uid = uid,
- };
- acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbcr, &ctx);
+ rc = cxl_get_chbs(match, hb, &ctx);
+ if (rc)
+ return rc;
- if (!ctx.chbcr) {
+ if (ctx.cxl_version == UINT_MAX) {
dev_warn(match, "No CHBS found for Host Bridge (UID %lld)\n",
- uid);
+ ctx.uid);
return 0;
}
- if (ctx.rcrb != CXL_RESOURCE_NONE)
- dev_dbg(match, "RCRB found for UID %lld: %pa\n", uid, &ctx.rcrb);
-
- if (ctx.chbcr == CXL_RESOURCE_NONE) {
- dev_warn(match, "CHBCR invalid for Host Bridge (UID %lld)\n",
- uid);
+ if (ctx.base == CXL_RESOURCE_NONE) {
+ dev_warn(match, "CHBS invalid for Host Bridge (UID %lld)\n",
+ ctx.uid);
return 0;
}
- dev_dbg(match, "CHBCR found: %pa\n", &ctx.chbcr);
-
pci_root = acpi_pci_find_root(hb->handle);
bridge = pci_root->bus->bridge;
- if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11)
- dport = devm_cxl_add_rch_dport(root_port, bridge, uid,
- ctx.chbcr, ctx.rcrb);
- else
- dport = devm_cxl_add_dport(root_port, bridge, uid,
- ctx.chbcr);
+
+ /*
+ * In RCH mode, bind the component regs base to the dport. In
+ * VH mode it will be bound to the CXL host bridge's port
+ * object later in add_host_bridge_uport().
+ */
+ if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) {
+ dev_dbg(match, "RCRB found for UID %lld: %pa\n", ctx.uid,
+ &ctx.base);
+ dport = devm_cxl_add_rch_dport(root_port, bridge, ctx.uid,
+ ctx.base);
+ } else {
+ dport = devm_cxl_add_dport(root_port, bridge, ctx.uid,
+ CXL_RESOURCE_NONE);
+ }
+
if (IS_ERR(dport))
return PTR_ERR(dport);
return 0;
}
+/*
+ * A host bridge is a dport to a CFMWS decode and it is a uport to the
+ * dport (PCIe Root Ports) in the host bridge.
+ */
+static int add_host_bridge_uport(struct device *match, void *arg)
+{
+ struct cxl_port *root_port = arg;
+ struct device *host = root_port->dev.parent;
+ struct acpi_device *hb = to_cxl_host_bridge(host, match);
+ struct acpi_pci_root *pci_root;
+ struct cxl_dport *dport;
+ struct cxl_port *port;
+ struct device *bridge;
+ struct cxl_chbs_context ctx;
+ resource_size_t component_reg_phys;
+ int rc;
+
+ if (!hb)
+ return 0;
+
+ pci_root = acpi_pci_find_root(hb->handle);
+ bridge = pci_root->bus->bridge;
+ dport = cxl_find_dport_by_dev(root_port, bridge);
+ if (!dport) {
+ dev_dbg(host, "host bridge expected and not found\n");
+ return 0;
+ }
+
+ if (dport->rch) {
+ dev_info(bridge, "host supports CXL (restricted)\n");
+ return 0;
+ }
+
+ rc = cxl_get_chbs(match, hb, &ctx);
+ if (rc)
+ return rc;
+
+ if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) {
+ dev_warn(bridge,
+ "CXL CHBS version mismatch, skip port registration\n");
+ return 0;
+ }
+
+ component_reg_phys = ctx.base;
+ if (component_reg_phys != CXL_RESOURCE_NONE)
+ dev_dbg(match, "CHBCR found for UID %lld: %pa\n",
+ ctx.uid, &component_reg_phys);
+
+ rc = devm_cxl_register_pci_bus(host, bridge, pci_root->bus);
+ if (rc)
+ return rc;
+
+ port = devm_cxl_add_port(host, bridge, component_reg_phys, dport);
+ if (IS_ERR(port))
+ return PTR_ERR(port);
+
+ dev_info(bridge, "host supports CXL\n");
+
+ return 0;
+}
+
static int add_root_nvdimm_bridge(struct device *match, void *data)
{
struct cxl_decoder *cxld;
diff --git a/drivers/cxl/core/Makefile b/drivers/cxl/core/Makefile
index ca4ae31d8f57..1f66b5d4d935 100644
--- a/drivers/cxl/core/Makefile
+++ b/drivers/cxl/core/Makefile
@@ -12,5 +12,6 @@ cxl_core-y += memdev.o
cxl_core-y += mbox.o
cxl_core-y += pci.o
cxl_core-y += hdm.o
+cxl_core-y += pmu.o
cxl_core-$(CONFIG_TRACING) += trace.o
cxl_core-$(CONFIG_CXL_REGION) += region.o
diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index 27f0968449de..45e7e044cf4a 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -6,6 +6,7 @@
extern const struct device_type cxl_nvdimm_bridge_type;
extern const struct device_type cxl_nvdimm_type;
+extern const struct device_type cxl_pmu_type;
extern struct attribute_group cxl_base_attribute_group;
@@ -63,6 +64,16 @@ int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size);
int cxl_dpa_free(struct cxl_endpoint_decoder *cxled);
resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled);
resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled);
+
+enum cxl_rcrb {
+ CXL_RCRB_DOWNSTREAM,
+ CXL_RCRB_UPSTREAM,
+};
+struct cxl_rcrb_info;
+resource_size_t __rcrb_to_component(struct device *dev,
+ struct cxl_rcrb_info *ri,
+ enum cxl_rcrb which);
+
extern struct rw_semaphore cxl_dpa_rwsem;
int cxl_memdev_init(void);
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index 7889ff203a34..4449b34a80cc 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -85,6 +85,7 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
struct cxl_component_regs *regs)
{
struct cxl_register_map map = {
+ .dev = &port->dev,
.resource = port->component_reg_phys,
.base = crb,
.max_size = CXL_COMPONENT_REG_BLOCK_SIZE,
@@ -97,8 +98,7 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
return -ENODEV;
}
- return cxl_map_component_regs(&port->dev, regs, &map,
- BIT(CXL_CM_CAP_CAP_ID_HDM));
+ return cxl_map_component_regs(&map, regs, BIT(CXL_CM_CAP_CAP_ID_HDM));
}
static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
@@ -570,8 +570,9 @@ static void cxld_set_interleave(struct cxl_decoder *cxld, u32 *ctrl)
static void cxld_set_type(struct cxl_decoder *cxld, u32 *ctrl)
{
- u32p_replace_bits(ctrl, !!(cxld->target_type == 3),
- CXL_HDM_DECODER0_CTRL_TYPE);
+ u32p_replace_bits(ctrl,
+ !!(cxld->target_type == CXL_DECODER_HOSTONLYMEM),
+ CXL_HDM_DECODER0_CTRL_HOSTONLY);
}
static int cxlsd_set_targets(struct cxl_switch_decoder *cxlsd, u64 *tgt)
@@ -764,7 +765,7 @@ static int cxl_setup_hdm_decoder_from_dvsec(
if (!len)
return -ENOENT;
- cxld->target_type = CXL_DECODER_EXPANDER;
+ cxld->target_type = CXL_DECODER_HOSTONLYMEM;
cxld->commit = NULL;
cxld->reset = NULL;
cxld->hpa_range = info->dvsec_range[which];
@@ -793,8 +794,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
int *target_map, void __iomem *hdm, int which,
u64 *dpa_base, struct cxl_endpoint_dvsec_info *info)
{
+ struct cxl_endpoint_decoder *cxled = NULL;
u64 size, base, skip, dpa_size, lo, hi;
- struct cxl_endpoint_decoder *cxled;
bool committed;
u32 remainder;
int i, rc;
@@ -827,6 +828,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
return -ENXIO;
}
+ if (info)
+ cxled = to_cxl_endpoint_decoder(&cxld->dev);
cxld->hpa_range = (struct range) {
.start = base,
.end = base + size - 1,
@@ -837,10 +840,10 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
cxld->flags |= CXL_DECODER_F_ENABLE;
if (ctrl & CXL_HDM_DECODER0_CTRL_LOCK)
cxld->flags |= CXL_DECODER_F_LOCK;
- if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl))
- cxld->target_type = CXL_DECODER_EXPANDER;
+ if (FIELD_GET(CXL_HDM_DECODER0_CTRL_HOSTONLY, ctrl))
+ cxld->target_type = CXL_DECODER_HOSTONLYMEM;
else
- cxld->target_type = CXL_DECODER_ACCELERATOR;
+ cxld->target_type = CXL_DECODER_DEVMEM;
if (cxld->id != port->commit_end + 1) {
dev_warn(&port->dev,
"decoder%d.%d: Committed out of order\n",
@@ -856,12 +859,28 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
}
port->commit_end = cxld->id;
} else {
- /* unless / until type-2 drivers arrive, assume type-3 */
- if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl) == 0) {
- ctrl |= CXL_HDM_DECODER0_CTRL_TYPE;
+ if (cxled) {
+ struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
+ struct cxl_dev_state *cxlds = cxlmd->cxlds;
+
+ /*
+ * Default by devtype until a device arrives that needs
+ * more precision.
+ */
+ if (cxlds->type == CXL_DEVTYPE_CLASSMEM)
+ cxld->target_type = CXL_DECODER_HOSTONLYMEM;
+ else
+ cxld->target_type = CXL_DECODER_DEVMEM;
+ } else {
+ /* To be overridden by region type at commit time */
+ cxld->target_type = CXL_DECODER_HOSTONLYMEM;
+ }
+
+ if (!FIELD_GET(CXL_HDM_DECODER0_CTRL_HOSTONLY, ctrl) &&
+ cxld->target_type == CXL_DECODER_HOSTONLYMEM) {
+ ctrl |= CXL_HDM_DECODER0_CTRL_HOSTONLY;
writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which));
}
- cxld->target_type = CXL_DECODER_EXPANDER;
}
rc = eiw_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl),
&cxld->interleave_ways);
@@ -880,7 +899,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
port->id, cxld->id, cxld->hpa_range.start, cxld->hpa_range.end,
cxld->interleave_ways, cxld->interleave_granularity);
- if (!info) {
+ if (!cxled) {
lo = readl(hdm + CXL_HDM_DECODER0_TL_LOW(which));
hi = readl(hdm + CXL_HDM_DECODER0_TL_HIGH(which));
target_list.value = (hi << 32) + lo;
@@ -903,7 +922,6 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
lo = readl(hdm + CXL_HDM_DECODER0_SKIP_LOW(which));
hi = readl(hdm + CXL_HDM_DECODER0_SKIP_HIGH(which));
skip = (hi << 32) + lo;
- cxled = to_cxl_endpoint_decoder(&cxld->dev);
rc = devm_cxl_dpa_reserve(cxled, *dpa_base + skip, dpa_size, skip);
if (rc) {
dev_err(&port->dev,
diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index bea9cf31a12d..d6d067fbee97 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -182,7 +182,7 @@ static const char *cxl_mem_opcode_to_name(u16 opcode)
/**
* cxl_internal_send_cmd() - Kernel internal interface to send a mailbox command
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
* @mbox_cmd: initialized command to execute
*
* Context: Any context.
@@ -198,19 +198,19 @@ static const char *cxl_mem_opcode_to_name(u16 opcode)
* error. While this distinction can be useful for commands from userspace, the
* kernel will only be able to use results when both are successful.
*/
-int cxl_internal_send_cmd(struct cxl_dev_state *cxlds,
+int cxl_internal_send_cmd(struct cxl_memdev_state *mds,
struct cxl_mbox_cmd *mbox_cmd)
{
size_t out_size, min_out;
int rc;
- if (mbox_cmd->size_in > cxlds->payload_size ||
- mbox_cmd->size_out > cxlds->payload_size)
+ if (mbox_cmd->size_in > mds->payload_size ||
+ mbox_cmd->size_out > mds->payload_size)
return -E2BIG;
out_size = mbox_cmd->size_out;
min_out = mbox_cmd->min_out;
- rc = cxlds->mbox_send(cxlds, mbox_cmd);
+ rc = mds->mbox_send(mds, mbox_cmd);
/*
* EIO is reserved for a payload size mismatch and mbox_send()
* may not return this error.
@@ -220,7 +220,8 @@ int cxl_internal_send_cmd(struct cxl_dev_state *cxlds,
if (rc)
return rc;
- if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS)
+ if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS &&
+ mbox_cmd->return_code != CXL_MBOX_CMD_RC_BACKGROUND)
return cxl_mbox_cmd_rc2errno(mbox_cmd);
if (!out_size)
@@ -297,7 +298,7 @@ static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in)
}
static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox,
- struct cxl_dev_state *cxlds, u16 opcode,
+ struct cxl_memdev_state *mds, u16 opcode,
size_t in_size, size_t out_size, u64 in_payload)
{
*mbox = (struct cxl_mbox_cmd) {
@@ -312,7 +313,7 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox,
return PTR_ERR(mbox->payload_in);
if (!cxl_payload_from_user_allowed(opcode, mbox->payload_in)) {
- dev_dbg(cxlds->dev, "%s: input payload not allowed\n",
+ dev_dbg(mds->cxlds.dev, "%s: input payload not allowed\n",
cxl_mem_opcode_to_name(opcode));
kvfree(mbox->payload_in);
return -EBUSY;
@@ -321,7 +322,7 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox,
/* Prepare to handle a full payload for variable sized output */
if (out_size == CXL_VARIABLE_PAYLOAD)
- mbox->size_out = cxlds->payload_size;
+ mbox->size_out = mds->payload_size;
else
mbox->size_out = out_size;
@@ -343,7 +344,7 @@ static void cxl_mbox_cmd_dtor(struct cxl_mbox_cmd *mbox)
static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd,
const struct cxl_send_command *send_cmd,
- struct cxl_dev_state *cxlds)
+ struct cxl_memdev_state *mds)
{
if (send_cmd->raw.rsvd)
return -EINVAL;
@@ -353,13 +354,13 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd,
* gets passed along without further checking, so it must be
* validated here.
*/
- if (send_cmd->out.size > cxlds->payload_size)
+ if (send_cmd->out.size > mds->payload_size)
return -EINVAL;
if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode))
return -EPERM;
- dev_WARN_ONCE(cxlds->dev, true, "raw command path used\n");
+ dev_WARN_ONCE(mds->cxlds.dev, true, "raw command path used\n");
*mem_cmd = (struct cxl_mem_command) {
.info = {
@@ -375,7 +376,7 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd,
static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd,
const struct cxl_send_command *send_cmd,
- struct cxl_dev_state *cxlds)
+ struct cxl_memdev_state *mds)
{
struct cxl_mem_command *c = &cxl_mem_commands[send_cmd->id];
const struct cxl_command_info *info = &c->info;
@@ -390,11 +391,11 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd,
return -EINVAL;
/* Check that the command is enabled for hardware */
- if (!test_bit(info->id, cxlds->enabled_cmds))
+ if (!test_bit(info->id, mds->enabled_cmds))
return -ENOTTY;
/* Check that the command is not claimed for exclusive kernel use */
- if (test_bit(info->id, cxlds->exclusive_cmds))
+ if (test_bit(info->id, mds->exclusive_cmds))
return -EBUSY;
/* Check the input buffer is the expected size */
@@ -423,7 +424,7 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd,
/**
* cxl_validate_cmd_from_user() - Check fields for CXL_MEM_SEND_COMMAND.
* @mbox_cmd: Sanitized and populated &struct cxl_mbox_cmd.
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
* @send_cmd: &struct cxl_send_command copied in from userspace.
*
* Return:
@@ -438,7 +439,7 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd,
* safe to send to the hardware.
*/
static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd,
- struct cxl_dev_state *cxlds,
+ struct cxl_memdev_state *mds,
const struct cxl_send_command *send_cmd)
{
struct cxl_mem_command mem_cmd;
@@ -452,20 +453,20 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd,
* supports, but output can be arbitrarily large (simply write out as
* much data as the hardware provides).
*/
- if (send_cmd->in.size > cxlds->payload_size)
+ if (send_cmd->in.size > mds->payload_size)
return -EINVAL;
/* Sanitize and construct a cxl_mem_command */
if (send_cmd->id == CXL_MEM_COMMAND_ID_RAW)
- rc = cxl_to_mem_cmd_raw(&mem_cmd, send_cmd, cxlds);
+ rc = cxl_to_mem_cmd_raw(&mem_cmd, send_cmd, mds);
else
- rc = cxl_to_mem_cmd(&mem_cmd, send_cmd, cxlds);
+ rc = cxl_to_mem_cmd(&mem_cmd, send_cmd, mds);
if (rc)
return rc;
/* Sanitize and construct a cxl_mbox_cmd */
- return cxl_mbox_cmd_ctor(mbox_cmd, cxlds, mem_cmd.opcode,
+ return cxl_mbox_cmd_ctor(mbox_cmd, mds, mem_cmd.opcode,
mem_cmd.info.size_in, mem_cmd.info.size_out,
send_cmd->in.payload);
}
@@ -473,6 +474,7 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd,
int cxl_query_cmd(struct cxl_memdev *cxlmd,
struct cxl_mem_query_commands __user *q)
{
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
struct device *dev = &cxlmd->dev;
struct cxl_mem_command *cmd;
u32 n_commands;
@@ -494,9 +496,9 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd,
cxl_for_each_cmd(cmd) {
struct cxl_command_info info = cmd->info;
- if (test_bit(info.id, cxlmd->cxlds->enabled_cmds))
+ if (test_bit(info.id, mds->enabled_cmds))
info.flags |= CXL_MEM_COMMAND_FLAG_ENABLED;
- if (test_bit(info.id, cxlmd->cxlds->exclusive_cmds))
+ if (test_bit(info.id, mds->exclusive_cmds))
info.flags |= CXL_MEM_COMMAND_FLAG_EXCLUSIVE;
if (copy_to_user(&q->commands[j++], &info, sizeof(info)))
@@ -511,7 +513,7 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd,
/**
* handle_mailbox_cmd_from_user() - Dispatch a mailbox command for userspace.
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
* @mbox_cmd: The validated mailbox command.
* @out_payload: Pointer to userspace's output payload.
* @size_out: (Input) Max payload size to copy out.
@@ -532,12 +534,12 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd,
*
* See cxl_send_cmd().
*/
-static int handle_mailbox_cmd_from_user(struct cxl_dev_state *cxlds,
+static int handle_mailbox_cmd_from_user(struct cxl_memdev_state *mds,
struct cxl_mbox_cmd *mbox_cmd,
u64 out_payload, s32 *size_out,
u32 *retval)
{
- struct device *dev = cxlds->dev;
+ struct device *dev = mds->cxlds.dev;
int rc;
dev_dbg(dev,
@@ -547,7 +549,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_dev_state *cxlds,
cxl_mem_opcode_to_name(mbox_cmd->opcode),
mbox_cmd->opcode, mbox_cmd->size_in);
- rc = cxlds->mbox_send(cxlds, mbox_cmd);
+ rc = mds->mbox_send(mds, mbox_cmd);
if (rc)
goto out;
@@ -576,7 +578,7 @@ out:
int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s)
{
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
struct device *dev = &cxlmd->dev;
struct cxl_send_command send;
struct cxl_mbox_cmd mbox_cmd;
@@ -587,11 +589,11 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s)
if (copy_from_user(&send, s, sizeof(send)))
return -EFAULT;
- rc = cxl_validate_cmd_from_user(&mbox_cmd, cxlmd->cxlds, &send);
+ rc = cxl_validate_cmd_from_user(&mbox_cmd, mds, &send);
if (rc)
return rc;
- rc = handle_mailbox_cmd_from_user(cxlds, &mbox_cmd, send.out.payload,
+ rc = handle_mailbox_cmd_from_user(mds, &mbox_cmd, send.out.payload,
&send.out.size, &send.retval);
if (rc)
return rc;
@@ -602,13 +604,14 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s)
return 0;
}
-static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 *size, u8 *out)
+static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid,
+ u32 *size, u8 *out)
{
u32 remaining = *size;
u32 offset = 0;
while (remaining) {
- u32 xfer_size = min_t(u32, remaining, cxlds->payload_size);
+ u32 xfer_size = min_t(u32, remaining, mds->payload_size);
struct cxl_mbox_cmd mbox_cmd;
struct cxl_mbox_get_log log;
int rc;
@@ -627,7 +630,7 @@ static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 *size, u8
.payload_out = out,
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
/*
* The output payload length that indicates the number
@@ -654,17 +657,18 @@ static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 *size, u8
/**
* cxl_walk_cel() - Walk through the Command Effects Log.
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
* @size: Length of the Command Effects Log.
* @cel: CEL
*
* Iterate over each entry in the CEL and determine if the driver supports the
* command. If so, the command is enabled for the device and can be used later.
*/
-static void cxl_walk_cel(struct cxl_dev_state *cxlds, size_t size, u8 *cel)
+static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
{
struct cxl_cel_entry *cel_entry;
const int cel_entries = size / sizeof(*cel_entry);
+ struct device *dev = mds->cxlds.dev;
int i;
cel_entry = (struct cxl_cel_entry *) cel;
@@ -674,39 +678,39 @@ static void cxl_walk_cel(struct cxl_dev_state *cxlds, size_t size, u8 *cel)
struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
if (!cmd && !cxl_is_poison_command(opcode)) {
- dev_dbg(cxlds->dev,
+ dev_dbg(dev,
"Opcode 0x%04x unsupported by driver\n", opcode);
continue;
}
if (cmd)
- set_bit(cmd->info.id, cxlds->enabled_cmds);
+ set_bit(cmd->info.id, mds->enabled_cmds);
if (cxl_is_poison_command(opcode))
- cxl_set_poison_cmd_enabled(&cxlds->poison, opcode);
+ cxl_set_poison_cmd_enabled(&mds->poison, opcode);
- dev_dbg(cxlds->dev, "Opcode 0x%04x enabled\n", opcode);
+ dev_dbg(dev, "Opcode 0x%04x enabled\n", opcode);
}
}
-static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_dev_state *cxlds)
+static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_memdev_state *mds)
{
struct cxl_mbox_get_supported_logs *ret;
struct cxl_mbox_cmd mbox_cmd;
int rc;
- ret = kvmalloc(cxlds->payload_size, GFP_KERNEL);
+ ret = kvmalloc(mds->payload_size, GFP_KERNEL);
if (!ret)
return ERR_PTR(-ENOMEM);
mbox_cmd = (struct cxl_mbox_cmd) {
.opcode = CXL_MBOX_OP_GET_SUPPORTED_LOGS,
- .size_out = cxlds->payload_size,
+ .size_out = mds->payload_size,
.payload_out = ret,
/* At least the record number field must be valid */
.min_out = 2,
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc < 0) {
kvfree(ret);
return ERR_PTR(rc);
@@ -729,22 +733,22 @@ static const uuid_t log_uuid[] = {
/**
* cxl_enumerate_cmds() - Enumerate commands for a device.
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
*
* Returns 0 if enumerate completed successfully.
*
* CXL devices have optional support for certain commands. This function will
* determine the set of supported commands for the hardware and update the
- * enabled_cmds bitmap in the @cxlds.
+ * enabled_cmds bitmap in the @mds.
*/
-int cxl_enumerate_cmds(struct cxl_dev_state *cxlds)
+int cxl_enumerate_cmds(struct cxl_memdev_state *mds)
{
struct cxl_mbox_get_supported_logs *gsl;
- struct device *dev = cxlds->dev;
+ struct device *dev = mds->cxlds.dev;
struct cxl_mem_command *cmd;
int i, rc;
- gsl = cxl_get_gsl(cxlds);
+ gsl = cxl_get_gsl(mds);
if (IS_ERR(gsl))
return PTR_ERR(gsl);
@@ -765,19 +769,19 @@ int cxl_enumerate_cmds(struct cxl_dev_state *cxlds)
goto out;
}
- rc = cxl_xfer_log(cxlds, &uuid, &size, log);
+ rc = cxl_xfer_log(mds, &uuid, &size, log);
if (rc) {
kvfree(log);
goto out;
}
- cxl_walk_cel(cxlds, size, log);
+ cxl_walk_cel(mds, size, log);
kvfree(log);
/* In case CEL was bogus, enable some default commands. */
cxl_for_each_cmd(cmd)
if (cmd->flags & CXL_CMD_FLAG_FORCE_ENABLE)
- set_bit(cmd->info.id, cxlds->enabled_cmds);
+ set_bit(cmd->info.id, mds->enabled_cmds);
/* Found the required CEL */
rc = 0;
@@ -838,7 +842,7 @@ static void cxl_event_trace_record(const struct cxl_memdev *cxlmd,
}
}
-static int cxl_clear_event_record(struct cxl_dev_state *cxlds,
+static int cxl_clear_event_record(struct cxl_memdev_state *mds,
enum cxl_event_log_type log,
struct cxl_get_event_payload *get_pl)
{
@@ -852,9 +856,9 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds,
int i;
/* Payload size may limit the max handles */
- if (pl_size > cxlds->payload_size) {
- max_handles = (cxlds->payload_size - sizeof(*payload)) /
- sizeof(__le16);
+ if (pl_size > mds->payload_size) {
+ max_handles = (mds->payload_size - sizeof(*payload)) /
+ sizeof(__le16);
pl_size = struct_size(payload, handles, max_handles);
}
@@ -879,12 +883,12 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds,
i = 0;
for (cnt = 0; cnt < total; cnt++) {
payload->handles[i++] = get_pl->records[cnt].hdr.handle;
- dev_dbg(cxlds->dev, "Event log '%d': Clearing %u\n",
- log, le16_to_cpu(payload->handles[i]));
+ dev_dbg(mds->cxlds.dev, "Event log '%d': Clearing %u\n", log,
+ le16_to_cpu(payload->handles[i]));
if (i == max_handles) {
payload->nr_recs = i;
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc)
goto free_pl;
i = 0;
@@ -895,7 +899,7 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds,
if (i) {
payload->nr_recs = i;
mbox_cmd.size_in = struct_size(payload, handles, i);
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc)
goto free_pl;
}
@@ -905,32 +909,34 @@ free_pl:
return rc;
}
-static void cxl_mem_get_records_log(struct cxl_dev_state *cxlds,
+static void cxl_mem_get_records_log(struct cxl_memdev_state *mds,
enum cxl_event_log_type type)
{
+ struct cxl_memdev *cxlmd = mds->cxlds.cxlmd;
+ struct device *dev = mds->cxlds.dev;
struct cxl_get_event_payload *payload;
struct cxl_mbox_cmd mbox_cmd;
u8 log_type = type;
u16 nr_rec;
- mutex_lock(&cxlds->event.log_lock);
- payload = cxlds->event.buf;
+ mutex_lock(&mds->event.log_lock);
+ payload = mds->event.buf;
mbox_cmd = (struct cxl_mbox_cmd) {
.opcode = CXL_MBOX_OP_GET_EVENT_RECORD,
.payload_in = &log_type,
.size_in = sizeof(log_type),
.payload_out = payload,
- .size_out = cxlds->payload_size,
+ .size_out = mds->payload_size,
.min_out = struct_size(payload, records, 0),
};
do {
int rc, i;
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc) {
- dev_err_ratelimited(cxlds->dev,
+ dev_err_ratelimited(dev,
"Event log '%d': Failed to query event records : %d",
type, rc);
break;
@@ -941,27 +947,27 @@ static void cxl_mem_get_records_log(struct cxl_dev_state *cxlds,
break;
for (i = 0; i < nr_rec; i++)
- cxl_event_trace_record(cxlds->cxlmd, type,
+ cxl_event_trace_record(cxlmd, type,
&payload->records[i]);
if (payload->flags & CXL_GET_EVENT_FLAG_OVERFLOW)
- trace_cxl_overflow(cxlds->cxlmd, type, payload);
+ trace_cxl_overflow(cxlmd, type, payload);
- rc = cxl_clear_event_record(cxlds, type, payload);
+ rc = cxl_clear_event_record(mds, type, payload);
if (rc) {
- dev_err_ratelimited(cxlds->dev,
+ dev_err_ratelimited(dev,
"Event log '%d': Failed to clear events : %d",
type, rc);
break;
}
} while (nr_rec);
- mutex_unlock(&cxlds->event.log_lock);
+ mutex_unlock(&mds->event.log_lock);
}
/**
* cxl_mem_get_event_records - Get Event Records from the device
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
* @status: Event Status register value identifying which events are available.
*
* Retrieve all event records available on the device, report them as trace
@@ -970,24 +976,24 @@ static void cxl_mem_get_records_log(struct cxl_dev_state *cxlds,
* See CXL rev 3.0 @8.2.9.2.2 Get Event Records
* See CXL rev 3.0 @8.2.9.2.3 Clear Event Records
*/
-void cxl_mem_get_event_records(struct cxl_dev_state *cxlds, u32 status)
+void cxl_mem_get_event_records(struct cxl_memdev_state *mds, u32 status)
{
- dev_dbg(cxlds->dev, "Reading event logs: %x\n", status);
+ dev_dbg(mds->cxlds.dev, "Reading event logs: %x\n", status);
if (status & CXLDEV_EVENT_STATUS_FATAL)
- cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_FATAL);
+ cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_FATAL);
if (status & CXLDEV_EVENT_STATUS_FAIL)
- cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_FAIL);
+ cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_FAIL);
if (status & CXLDEV_EVENT_STATUS_WARN)
- cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_WARN);
+ cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_WARN);
if (status & CXLDEV_EVENT_STATUS_INFO)
- cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_INFO);
+ cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_INFO);
}
EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, CXL);
/**
* cxl_mem_get_partition_info - Get partition info
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
*
* Retrieve the current partition info for the device specified. The active
* values are the current capacity in bytes. If not 0, the 'next' values are
@@ -997,7 +1003,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, CXL);
*
* See CXL @8.2.9.5.2.1 Get Partition Info
*/
-static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds)
+static int cxl_mem_get_partition_info(struct cxl_memdev_state *mds)
{
struct cxl_mbox_get_partition_info pi;
struct cxl_mbox_cmd mbox_cmd;
@@ -1008,17 +1014,17 @@ static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds)
.size_out = sizeof(pi),
.payload_out = &pi,
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc)
return rc;
- cxlds->active_volatile_bytes =
+ mds->active_volatile_bytes =
le64_to_cpu(pi.active_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
- cxlds->active_persistent_bytes =
+ mds->active_persistent_bytes =
le64_to_cpu(pi.active_persistent_cap) * CXL_CAPACITY_MULTIPLIER;
- cxlds->next_volatile_bytes =
+ mds->next_volatile_bytes =
le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
- cxlds->next_persistent_bytes =
+ mds->next_persistent_bytes =
le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
return 0;
@@ -1026,14 +1032,14 @@ static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds)
/**
* cxl_dev_state_identify() - Send the IDENTIFY command to the device.
- * @cxlds: The device data for the operation
+ * @mds: The driver data for the operation
*
* Return: 0 if identify was executed successfully or media not ready.
*
* This will dispatch the identify command to the device and on success populate
* structures to be exported to sysfs.
*/
-int cxl_dev_state_identify(struct cxl_dev_state *cxlds)
+int cxl_dev_state_identify(struct cxl_memdev_state *mds)
{
/* See CXL 2.0 Table 175 Identify Memory Device Output Payload */
struct cxl_mbox_identify id;
@@ -1041,7 +1047,7 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds)
u32 val;
int rc;
- if (!cxlds->media_ready)
+ if (!mds->cxlds.media_ready)
return 0;
mbox_cmd = (struct cxl_mbox_cmd) {
@@ -1049,31 +1055,92 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds)
.size_out = sizeof(id),
.payload_out = &id,
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc < 0)
return rc;
- cxlds->total_bytes =
+ mds->total_bytes =
le64_to_cpu(id.total_capacity) * CXL_CAPACITY_MULTIPLIER;
- cxlds->volatile_only_bytes =
+ mds->volatile_only_bytes =
le64_to_cpu(id.volatile_capacity) * CXL_CAPACITY_MULTIPLIER;
- cxlds->persistent_only_bytes =
+ mds->persistent_only_bytes =
le64_to_cpu(id.persistent_capacity) * CXL_CAPACITY_MULTIPLIER;
- cxlds->partition_align_bytes =
+ mds->partition_align_bytes =
le64_to_cpu(id.partition_align) * CXL_CAPACITY_MULTIPLIER;
- cxlds->lsa_size = le32_to_cpu(id.lsa_size);
- memcpy(cxlds->firmware_version, id.fw_revision, sizeof(id.fw_revision));
+ mds->lsa_size = le32_to_cpu(id.lsa_size);
+ memcpy(mds->firmware_version, id.fw_revision,
+ sizeof(id.fw_revision));
- if (test_bit(CXL_POISON_ENABLED_LIST, cxlds->poison.enabled_cmds)) {
+ if (test_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds)) {
val = get_unaligned_le24(id.poison_list_max_mer);
- cxlds->poison.max_errors = min_t(u32, val, CXL_POISON_LIST_MAX);
+ mds->poison.max_errors = min_t(u32, val, CXL_POISON_LIST_MAX);
}
return 0;
}
EXPORT_SYMBOL_NS_GPL(cxl_dev_state_identify, CXL);
+/**
+ * cxl_mem_sanitize() - Send a sanitization command to the device.
+ * @mds: The device data for the operation
+ * @cmd: The specific sanitization command opcode
+ *
+ * Return: 0 if the command was executed successfully, regardless of
+ * whether or not the actual security operation is done in the background,
+ * such as for the Sanitize case.
+ * Error return values can be the result of the mailbox command, -EINVAL
+ * when security requirements are not met or invalid contexts.
+ *
+ * See CXL 3.0 @8.2.9.8.5.1 Sanitize and @8.2.9.8.5.2 Secure Erase.
+ */
+int cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd)
+{
+ int rc;
+ u32 sec_out = 0;
+ struct cxl_get_security_output {
+ __le32 flags;
+ } out;
+ struct cxl_mbox_cmd sec_cmd = {
+ .opcode = CXL_MBOX_OP_GET_SECURITY_STATE,
+ .payload_out = &out,
+ .size_out = sizeof(out),
+ };
+ struct cxl_mbox_cmd mbox_cmd = { .opcode = cmd };
+ struct cxl_dev_state *cxlds = &mds->cxlds;
+
+ if (cmd != CXL_MBOX_OP_SANITIZE && cmd != CXL_MBOX_OP_SECURE_ERASE)
+ return -EINVAL;
+
+ rc = cxl_internal_send_cmd(mds, &sec_cmd);
+ if (rc < 0) {
+ dev_err(cxlds->dev, "Failed to get security state : %d", rc);
+ return rc;
+ }
+
+ /*
+ * Prior to using these commands, any security applied to
+ * the user data areas of the device shall be DISABLED (or
+ * UNLOCKED for secure erase case).
+ */
+ sec_out = le32_to_cpu(out.flags);
+ if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET)
+ return -EINVAL;
+
+ if (cmd == CXL_MBOX_OP_SECURE_ERASE &&
+ sec_out & CXL_PMEM_SEC_STATE_LOCKED)
+ return -EINVAL;
+
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
+ if (rc < 0) {
+ dev_err(cxlds->dev, "Failed to sanitize device : %d", rc);
+ return rc;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_mem_sanitize, CXL);
+
static int add_dpa_res(struct device *dev, struct resource *parent,
struct resource *res, resource_size_t start,
resource_size_t size, const char *type)
@@ -1100,8 +1167,9 @@ static int add_dpa_res(struct device *dev, struct resource *parent,
return 0;
}
-int cxl_mem_create_range_info(struct cxl_dev_state *cxlds)
+int cxl_mem_create_range_info(struct cxl_memdev_state *mds)
{
+ struct cxl_dev_state *cxlds = &mds->cxlds;
struct device *dev = cxlds->dev;
int rc;
@@ -1113,35 +1181,35 @@ int cxl_mem_create_range_info(struct cxl_dev_state *cxlds)
}
cxlds->dpa_res =
- (struct resource)DEFINE_RES_MEM(0, cxlds->total_bytes);
+ (struct resource)DEFINE_RES_MEM(0, mds->total_bytes);
- if (cxlds->partition_align_bytes == 0) {
+ if (mds->partition_align_bytes == 0) {
rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0,
- cxlds->volatile_only_bytes, "ram");
+ mds->volatile_only_bytes, "ram");
if (rc)
return rc;
return add_dpa_res(dev, &cxlds->dpa_res, &cxlds->pmem_res,
- cxlds->volatile_only_bytes,
- cxlds->persistent_only_bytes, "pmem");
+ mds->volatile_only_bytes,
+ mds->persistent_only_bytes, "pmem");
}
- rc = cxl_mem_get_partition_info(cxlds);
+ rc = cxl_mem_get_partition_info(mds);
if (rc) {
dev_err(dev, "Failed to query partition information\n");
return rc;
}
rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0,
- cxlds->active_volatile_bytes, "ram");
+ mds->active_volatile_bytes, "ram");
if (rc)
return rc;
return add_dpa_res(dev, &cxlds->dpa_res, &cxlds->pmem_res,
- cxlds->active_volatile_bytes,
- cxlds->active_persistent_bytes, "pmem");
+ mds->active_volatile_bytes,
+ mds->active_persistent_bytes, "pmem");
}
EXPORT_SYMBOL_NS_GPL(cxl_mem_create_range_info, CXL);
-int cxl_set_timestamp(struct cxl_dev_state *cxlds)
+int cxl_set_timestamp(struct cxl_memdev_state *mds)
{
struct cxl_mbox_cmd mbox_cmd;
struct cxl_mbox_set_timestamp_in pi;
@@ -1154,7 +1222,7 @@ int cxl_set_timestamp(struct cxl_dev_state *cxlds)
.payload_in = &pi,
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
/*
* Command is optional. Devices may have another way of providing
* a timestamp, or may return all 0s in timestamp fields.
@@ -1170,18 +1238,18 @@ EXPORT_SYMBOL_NS_GPL(cxl_set_timestamp, CXL);
int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
struct cxl_region *cxlr)
{
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
struct cxl_mbox_poison_out *po;
struct cxl_mbox_poison_in pi;
struct cxl_mbox_cmd mbox_cmd;
int nr_records = 0;
int rc;
- rc = mutex_lock_interruptible(&cxlds->poison.lock);
+ rc = mutex_lock_interruptible(&mds->poison.lock);
if (rc)
return rc;
- po = cxlds->poison.list_out;
+ po = mds->poison.list_out;
pi.offset = cpu_to_le64(offset);
pi.length = cpu_to_le64(len / CXL_POISON_LEN_MULT);
@@ -1189,13 +1257,13 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
.opcode = CXL_MBOX_OP_GET_POISON,
.size_in = sizeof(pi),
.payload_in = &pi,
- .size_out = cxlds->payload_size,
+ .size_out = mds->payload_size,
.payload_out = po,
.min_out = struct_size(po, record, 0),
};
do {
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc)
break;
@@ -1206,14 +1274,14 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
/* Protect against an uncleared _FLAG_MORE */
nr_records = nr_records + le16_to_cpu(po->count);
- if (nr_records >= cxlds->poison.max_errors) {
+ if (nr_records >= mds->poison.max_errors) {
dev_dbg(&cxlmd->dev, "Max Error Records reached: %d\n",
nr_records);
break;
}
} while (po->flags & CXL_POISON_FLAG_MORE);
- mutex_unlock(&cxlds->poison.lock);
+ mutex_unlock(&mds->poison.lock);
return rc;
}
EXPORT_SYMBOL_NS_GPL(cxl_mem_get_poison, CXL);
@@ -1223,52 +1291,53 @@ static void free_poison_buf(void *buf)
kvfree(buf);
}
-/* Get Poison List output buffer is protected by cxlds->poison.lock */
-static int cxl_poison_alloc_buf(struct cxl_dev_state *cxlds)
+/* Get Poison List output buffer is protected by mds->poison.lock */
+static int cxl_poison_alloc_buf(struct cxl_memdev_state *mds)
{
- cxlds->poison.list_out = kvmalloc(cxlds->payload_size, GFP_KERNEL);
- if (!cxlds->poison.list_out)
+ mds->poison.list_out = kvmalloc(mds->payload_size, GFP_KERNEL);
+ if (!mds->poison.list_out)
return -ENOMEM;
- return devm_add_action_or_reset(cxlds->dev, free_poison_buf,
- cxlds->poison.list_out);
+ return devm_add_action_or_reset(mds->cxlds.dev, free_poison_buf,
+ mds->poison.list_out);
}
-int cxl_poison_state_init(struct cxl_dev_state *cxlds)
+int cxl_poison_state_init(struct cxl_memdev_state *mds)
{
int rc;
- if (!test_bit(CXL_POISON_ENABLED_LIST, cxlds->poison.enabled_cmds))
+ if (!test_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds))
return 0;
- rc = cxl_poison_alloc_buf(cxlds);
+ rc = cxl_poison_alloc_buf(mds);
if (rc) {
- clear_bit(CXL_POISON_ENABLED_LIST, cxlds->poison.enabled_cmds);
+ clear_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds);
return rc;
}
- mutex_init(&cxlds->poison.lock);
+ mutex_init(&mds->poison.lock);
return 0;
}
EXPORT_SYMBOL_NS_GPL(cxl_poison_state_init, CXL);
-struct cxl_dev_state *cxl_dev_state_create(struct device *dev)
+struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
{
- struct cxl_dev_state *cxlds;
+ struct cxl_memdev_state *mds;
- cxlds = devm_kzalloc(dev, sizeof(*cxlds), GFP_KERNEL);
- if (!cxlds) {
+ mds = devm_kzalloc(dev, sizeof(*mds), GFP_KERNEL);
+ if (!mds) {
dev_err(dev, "No memory available\n");
return ERR_PTR(-ENOMEM);
}
- mutex_init(&cxlds->mbox_mutex);
- mutex_init(&cxlds->event.log_lock);
- cxlds->dev = dev;
+ mutex_init(&mds->mbox_mutex);
+ mutex_init(&mds->event.log_lock);
+ mds->cxlds.dev = dev;
+ mds->cxlds.type = CXL_DEVTYPE_CLASSMEM;
- return cxlds;
+ return mds;
}
-EXPORT_SYMBOL_NS_GPL(cxl_dev_state_create, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_memdev_state_create, CXL);
void __init cxl_mbox_init(void)
{
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 057a43267290..f99e7ec3cc40 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2020 Intel Corporation. */
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/firmware.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/idr.h>
@@ -39,8 +41,11 @@ static ssize_t firmware_version_show(struct device *dev,
{
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
- return sysfs_emit(buf, "%.16s\n", cxlds->firmware_version);
+ if (!mds)
+ return sysfs_emit(buf, "\n");
+ return sysfs_emit(buf, "%.16s\n", mds->firmware_version);
}
static DEVICE_ATTR_RO(firmware_version);
@@ -49,8 +54,11 @@ static ssize_t payload_max_show(struct device *dev,
{
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
- return sysfs_emit(buf, "%zu\n", cxlds->payload_size);
+ if (!mds)
+ return sysfs_emit(buf, "\n");
+ return sysfs_emit(buf, "%zu\n", mds->payload_size);
}
static DEVICE_ATTR_RO(payload_max);
@@ -59,8 +67,11 @@ static ssize_t label_storage_size_show(struct device *dev,
{
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
- return sysfs_emit(buf, "%zu\n", cxlds->lsa_size);
+ if (!mds)
+ return sysfs_emit(buf, "\n");
+ return sysfs_emit(buf, "%zu\n", mds->lsa_size);
}
static DEVICE_ATTR_RO(label_storage_size);
@@ -107,6 +118,89 @@ static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(numa_node);
+static ssize_t security_state_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+ struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
+ u64 reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET);
+ u32 pct = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_PCT_MASK, reg);
+ u16 cmd = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK, reg);
+ unsigned long state = mds->security.state;
+
+ if (cmd == CXL_MBOX_OP_SANITIZE && pct != 100)
+ return sysfs_emit(buf, "sanitize\n");
+
+ if (!(state & CXL_PMEM_SEC_STATE_USER_PASS_SET))
+ return sysfs_emit(buf, "disabled\n");
+ if (state & CXL_PMEM_SEC_STATE_FROZEN ||
+ state & CXL_PMEM_SEC_STATE_MASTER_PLIMIT ||
+ state & CXL_PMEM_SEC_STATE_USER_PLIMIT)
+ return sysfs_emit(buf, "frozen\n");
+ if (state & CXL_PMEM_SEC_STATE_LOCKED)
+ return sysfs_emit(buf, "locked\n");
+ else
+ return sysfs_emit(buf, "unlocked\n");
+}
+static struct device_attribute dev_attr_security_state =
+ __ATTR(state, 0444, security_state_show, NULL);
+
+static ssize_t security_sanitize_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
+ struct cxl_port *port = cxlmd->endpoint;
+ bool sanitize;
+ ssize_t rc;
+
+ if (kstrtobool(buf, &sanitize) || !sanitize)
+ return -EINVAL;
+
+ if (!port || !is_cxl_endpoint(port))
+ return -EINVAL;
+
+ /* ensure no regions are mapped to this memdev */
+ if (port->commit_end != -1)
+ return -EBUSY;
+
+ rc = cxl_mem_sanitize(mds, CXL_MBOX_OP_SANITIZE);
+
+ return rc ? rc : len;
+}
+static struct device_attribute dev_attr_security_sanitize =
+ __ATTR(sanitize, 0200, NULL, security_sanitize_store);
+
+static ssize_t security_erase_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
+ struct cxl_port *port = cxlmd->endpoint;
+ ssize_t rc;
+ bool erase;
+
+ if (kstrtobool(buf, &erase) || !erase)
+ return -EINVAL;
+
+ if (!port || !is_cxl_endpoint(port))
+ return -EINVAL;
+
+ /* ensure no regions are mapped to this memdev */
+ if (port->commit_end != -1)
+ return -EBUSY;
+
+ rc = cxl_mem_sanitize(mds, CXL_MBOX_OP_SECURE_ERASE);
+
+ return rc ? rc : len;
+}
+static struct device_attribute dev_attr_security_erase =
+ __ATTR(erase, 0200, NULL, security_erase_store);
+
static int cxl_get_poison_by_memdev(struct cxl_memdev *cxlmd)
{
struct cxl_dev_state *cxlds = cxlmd->cxlds;
@@ -140,7 +234,7 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
struct cxl_port *port;
int rc;
- port = dev_get_drvdata(&cxlmd->dev);
+ port = cxlmd->endpoint;
if (!port || !is_cxl_endpoint(port))
return -EINVAL;
@@ -198,7 +292,7 @@ static struct cxl_region *cxl_dpa_to_region(struct cxl_memdev *cxlmd, u64 dpa)
ctx = (struct cxl_dpa_to_region_context) {
.dpa = dpa,
};
- port = dev_get_drvdata(&cxlmd->dev);
+ port = cxlmd->endpoint;
if (port && is_cxl_endpoint(port) && port->commit_end != -1)
device_for_each_child(&port->dev, &ctx, __cxl_dpa_to_region);
@@ -231,7 +325,7 @@ static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa)
int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
{
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
struct cxl_mbox_inject_poison inject;
struct cxl_poison_record record;
struct cxl_mbox_cmd mbox_cmd;
@@ -255,13 +349,13 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
.size_in = sizeof(inject),
.payload_in = &inject,
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc)
goto out;
cxlr = cxl_dpa_to_region(cxlmd, dpa);
if (cxlr)
- dev_warn_once(cxlds->dev,
+ dev_warn_once(mds->cxlds.dev,
"poison inject dpa:%#llx region: %s\n", dpa,
dev_name(&cxlr->dev));
@@ -279,7 +373,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_inject_poison, CXL);
int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
{
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
struct cxl_mbox_clear_poison clear;
struct cxl_poison_record record;
struct cxl_mbox_cmd mbox_cmd;
@@ -312,14 +406,15 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
.payload_in = &clear,
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc)
goto out;
cxlr = cxl_dpa_to_region(cxlmd, dpa);
if (cxlr)
- dev_warn_once(cxlds->dev, "poison clear dpa:%#llx region: %s\n",
- dpa, dev_name(&cxlr->dev));
+ dev_warn_once(mds->cxlds.dev,
+ "poison clear dpa:%#llx region: %s\n", dpa,
+ dev_name(&cxlr->dev));
record = (struct cxl_poison_record) {
.address = cpu_to_le64(dpa),
@@ -352,6 +447,13 @@ static struct attribute *cxl_memdev_ram_attributes[] = {
NULL,
};
+static struct attribute *cxl_memdev_security_attributes[] = {
+ &dev_attr_security_state.attr,
+ &dev_attr_security_sanitize.attr,
+ &dev_attr_security_erase.attr,
+ NULL,
+};
+
static umode_t cxl_memdev_visible(struct kobject *kobj, struct attribute *a,
int n)
{
@@ -375,10 +477,16 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = {
.attrs = cxl_memdev_pmem_attributes,
};
+static struct attribute_group cxl_memdev_security_attribute_group = {
+ .name = "security",
+ .attrs = cxl_memdev_security_attributes,
+};
+
static const struct attribute_group *cxl_memdev_attribute_groups[] = {
&cxl_memdev_attribute_group,
&cxl_memdev_ram_attribute_group,
&cxl_memdev_pmem_attribute_group,
+ &cxl_memdev_security_attribute_group,
NULL,
};
@@ -397,17 +505,18 @@ EXPORT_SYMBOL_NS_GPL(is_cxl_memdev, CXL);
/**
* set_exclusive_cxl_commands() - atomically disable user cxl commands
- * @cxlds: The device state to operate on
+ * @mds: The device state to operate on
* @cmds: bitmap of commands to mark exclusive
*
* Grab the cxl_memdev_rwsem in write mode to flush in-flight
* invocations of the ioctl path and then disable future execution of
* commands with the command ids set in @cmds.
*/
-void set_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds)
+void set_exclusive_cxl_commands(struct cxl_memdev_state *mds,
+ unsigned long *cmds)
{
down_write(&cxl_memdev_rwsem);
- bitmap_or(cxlds->exclusive_cmds, cxlds->exclusive_cmds, cmds,
+ bitmap_or(mds->exclusive_cmds, mds->exclusive_cmds, cmds,
CXL_MEM_COMMAND_ID_MAX);
up_write(&cxl_memdev_rwsem);
}
@@ -415,23 +524,34 @@ EXPORT_SYMBOL_NS_GPL(set_exclusive_cxl_commands, CXL);
/**
* clear_exclusive_cxl_commands() - atomically enable user cxl commands
- * @cxlds: The device state to modify
+ * @mds: The device state to modify
* @cmds: bitmap of commands to mark available for userspace
*/
-void clear_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds)
+void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds,
+ unsigned long *cmds)
{
down_write(&cxl_memdev_rwsem);
- bitmap_andnot(cxlds->exclusive_cmds, cxlds->exclusive_cmds, cmds,
+ bitmap_andnot(mds->exclusive_cmds, mds->exclusive_cmds, cmds,
CXL_MEM_COMMAND_ID_MAX);
up_write(&cxl_memdev_rwsem);
}
EXPORT_SYMBOL_NS_GPL(clear_exclusive_cxl_commands, CXL);
+static void cxl_memdev_security_shutdown(struct device *dev)
+{
+ struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
+
+ if (mds->security.poll)
+ cancel_delayed_work_sync(&mds->security.poll_dwork);
+}
+
static void cxl_memdev_shutdown(struct device *dev)
{
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
down_write(&cxl_memdev_rwsem);
+ cxl_memdev_security_shutdown(dev);
cxlmd->cxlds = NULL;
up_write(&cxl_memdev_rwsem);
}
@@ -511,10 +631,12 @@ static long cxl_memdev_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct cxl_memdev *cxlmd = file->private_data;
+ struct cxl_dev_state *cxlds;
int rc = -ENXIO;
down_read(&cxl_memdev_rwsem);
- if (cxlmd->cxlds)
+ cxlds = cxlmd->cxlds;
+ if (cxlds && cxlds->type == CXL_DEVTYPE_CLASSMEM)
rc = __cxl_memdev_ioctl(cxlmd, cmd, arg);
up_read(&cxl_memdev_rwsem);
@@ -542,6 +664,316 @@ static int cxl_memdev_release_file(struct inode *inode, struct file *file)
return 0;
}
+/**
+ * cxl_mem_get_fw_info - Get Firmware info
+ * @mds: The device data for the operation
+ *
+ * Retrieve firmware info for the device specified.
+ *
+ * Return: 0 if no error: or the result of the mailbox command.
+ *
+ * See CXL-3.0 8.2.9.3.1 Get FW Info
+ */
+static int cxl_mem_get_fw_info(struct cxl_memdev_state *mds)
+{
+ struct cxl_mbox_get_fw_info info;
+ struct cxl_mbox_cmd mbox_cmd;
+ int rc;
+
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_GET_FW_INFO,
+ .size_out = sizeof(info),
+ .payload_out = &info,
+ };
+
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
+ if (rc < 0)
+ return rc;
+
+ mds->fw.num_slots = info.num_slots;
+ mds->fw.cur_slot = FIELD_GET(CXL_FW_INFO_SLOT_INFO_CUR_MASK,
+ info.slot_info);
+
+ return 0;
+}
+
+/**
+ * cxl_mem_activate_fw - Activate Firmware
+ * @mds: The device data for the operation
+ * @slot: slot number to activate
+ *
+ * Activate firmware in a given slot for the device specified.
+ *
+ * Return: 0 if no error: or the result of the mailbox command.
+ *
+ * See CXL-3.0 8.2.9.3.3 Activate FW
+ */
+static int cxl_mem_activate_fw(struct cxl_memdev_state *mds, int slot)
+{
+ struct cxl_mbox_activate_fw activate;
+ struct cxl_mbox_cmd mbox_cmd;
+
+ if (slot == 0 || slot > mds->fw.num_slots)
+ return -EINVAL;
+
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_ACTIVATE_FW,
+ .size_in = sizeof(activate),
+ .payload_in = &activate,
+ };
+
+ /* Only offline activation supported for now */
+ activate.action = CXL_FW_ACTIVATE_OFFLINE;
+ activate.slot = slot;
+
+ return cxl_internal_send_cmd(mds, &mbox_cmd);
+}
+
+/**
+ * cxl_mem_abort_fw_xfer - Abort an in-progress FW transfer
+ * @mds: The device data for the operation
+ *
+ * Abort an in-progress firmware transfer for the device specified.
+ *
+ * Return: 0 if no error: or the result of the mailbox command.
+ *
+ * See CXL-3.0 8.2.9.3.2 Transfer FW
+ */
+static int cxl_mem_abort_fw_xfer(struct cxl_memdev_state *mds)
+{
+ struct cxl_mbox_transfer_fw *transfer;
+ struct cxl_mbox_cmd mbox_cmd;
+ int rc;
+
+ transfer = kzalloc(struct_size(transfer, data, 0), GFP_KERNEL);
+ if (!transfer)
+ return -ENOMEM;
+
+ /* Set a 1s poll interval and a total wait time of 30s */
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_TRANSFER_FW,
+ .size_in = sizeof(*transfer),
+ .payload_in = transfer,
+ .poll_interval_ms = 1000,
+ .poll_count = 30,
+ };
+
+ transfer->action = CXL_FW_TRANSFER_ACTION_ABORT;
+
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
+ kfree(transfer);
+ return rc;
+}
+
+static void cxl_fw_cleanup(struct fw_upload *fwl)
+{
+ struct cxl_memdev_state *mds = fwl->dd_handle;
+
+ mds->fw.next_slot = 0;
+}
+
+static int cxl_fw_do_cancel(struct fw_upload *fwl)
+{
+ struct cxl_memdev_state *mds = fwl->dd_handle;
+ struct cxl_dev_state *cxlds = &mds->cxlds;
+ struct cxl_memdev *cxlmd = cxlds->cxlmd;
+ int rc;
+
+ rc = cxl_mem_abort_fw_xfer(mds);
+ if (rc < 0)
+ dev_err(&cxlmd->dev, "Error aborting FW transfer: %d\n", rc);
+
+ return FW_UPLOAD_ERR_CANCELED;
+}
+
+static enum fw_upload_err cxl_fw_prepare(struct fw_upload *fwl, const u8 *data,
+ u32 size)
+{
+ struct cxl_memdev_state *mds = fwl->dd_handle;
+ struct cxl_mbox_transfer_fw *transfer;
+
+ if (!size)
+ return FW_UPLOAD_ERR_INVALID_SIZE;
+
+ mds->fw.oneshot = struct_size(transfer, data, size) <
+ mds->payload_size;
+
+ if (cxl_mem_get_fw_info(mds))
+ return FW_UPLOAD_ERR_HW_ERROR;
+
+ /*
+ * So far no state has been changed, hence no other cleanup is
+ * necessary. Simply return the cancelled status.
+ */
+ if (test_and_clear_bit(CXL_FW_CANCEL, mds->fw.state))
+ return FW_UPLOAD_ERR_CANCELED;
+
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static enum fw_upload_err cxl_fw_write(struct fw_upload *fwl, const u8 *data,
+ u32 offset, u32 size, u32 *written)
+{
+ struct cxl_memdev_state *mds = fwl->dd_handle;
+ struct cxl_dev_state *cxlds = &mds->cxlds;
+ struct cxl_memdev *cxlmd = cxlds->cxlmd;
+ struct cxl_mbox_transfer_fw *transfer;
+ struct cxl_mbox_cmd mbox_cmd;
+ u32 cur_size, remaining;
+ size_t size_in;
+ int rc;
+
+ *written = 0;
+
+ /* Offset has to be aligned to 128B (CXL-3.0 8.2.9.3.2 Table 8-57) */
+ if (!IS_ALIGNED(offset, CXL_FW_TRANSFER_ALIGNMENT)) {
+ dev_err(&cxlmd->dev,
+ "misaligned offset for FW transfer slice (%u)\n",
+ offset);
+ return FW_UPLOAD_ERR_RW_ERROR;
+ }
+
+ /*
+ * Pick transfer size based on mds->payload_size @size must bw 128-byte
+ * aligned, ->payload_size is a power of 2 starting at 256 bytes, and
+ * sizeof(*transfer) is 128. These constraints imply that @cur_size
+ * will always be 128b aligned.
+ */
+ cur_size = min_t(size_t, size, mds->payload_size - sizeof(*transfer));
+
+ remaining = size - cur_size;
+ size_in = struct_size(transfer, data, cur_size);
+
+ if (test_and_clear_bit(CXL_FW_CANCEL, mds->fw.state))
+ return cxl_fw_do_cancel(fwl);
+
+ /*
+ * Slot numbers are 1-indexed
+ * cur_slot is the 0-indexed next_slot (i.e. 'cur_slot - 1 + 1')
+ * Check for rollover using modulo, and 1-index it by adding 1
+ */
+ mds->fw.next_slot = (mds->fw.cur_slot % mds->fw.num_slots) + 1;
+
+ /* Do the transfer via mailbox cmd */
+ transfer = kzalloc(size_in, GFP_KERNEL);
+ if (!transfer)
+ return FW_UPLOAD_ERR_RW_ERROR;
+
+ transfer->offset = cpu_to_le32(offset / CXL_FW_TRANSFER_ALIGNMENT);
+ memcpy(transfer->data, data + offset, cur_size);
+ if (mds->fw.oneshot) {
+ transfer->action = CXL_FW_TRANSFER_ACTION_FULL;
+ transfer->slot = mds->fw.next_slot;
+ } else {
+ if (offset == 0) {
+ transfer->action = CXL_FW_TRANSFER_ACTION_INITIATE;
+ } else if (remaining == 0) {
+ transfer->action = CXL_FW_TRANSFER_ACTION_END;
+ transfer->slot = mds->fw.next_slot;
+ } else {
+ transfer->action = CXL_FW_TRANSFER_ACTION_CONTINUE;
+ }
+ }
+
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_TRANSFER_FW,
+ .size_in = size_in,
+ .payload_in = transfer,
+ .poll_interval_ms = 1000,
+ .poll_count = 30,
+ };
+
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
+ if (rc < 0) {
+ rc = FW_UPLOAD_ERR_RW_ERROR;
+ goto out_free;
+ }
+
+ *written = cur_size;
+
+ /* Activate FW if oneshot or if the last slice was written */
+ if (mds->fw.oneshot || remaining == 0) {
+ dev_dbg(&cxlmd->dev, "Activating firmware slot: %d\n",
+ mds->fw.next_slot);
+ rc = cxl_mem_activate_fw(mds, mds->fw.next_slot);
+ if (rc < 0) {
+ dev_err(&cxlmd->dev, "Error activating firmware: %d\n",
+ rc);
+ rc = FW_UPLOAD_ERR_HW_ERROR;
+ goto out_free;
+ }
+ }
+
+ rc = FW_UPLOAD_ERR_NONE;
+
+out_free:
+ kfree(transfer);
+ return rc;
+}
+
+static enum fw_upload_err cxl_fw_poll_complete(struct fw_upload *fwl)
+{
+ struct cxl_memdev_state *mds = fwl->dd_handle;
+
+ /*
+ * cxl_internal_send_cmd() handles background operations synchronously.
+ * No need to wait for completions here - any errors would've been
+ * reported and handled during the ->write() call(s).
+ * Just check if a cancel request was received, and return success.
+ */
+ if (test_and_clear_bit(CXL_FW_CANCEL, mds->fw.state))
+ return cxl_fw_do_cancel(fwl);
+
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static void cxl_fw_cancel(struct fw_upload *fwl)
+{
+ struct cxl_memdev_state *mds = fwl->dd_handle;
+
+ set_bit(CXL_FW_CANCEL, mds->fw.state);
+}
+
+static const struct fw_upload_ops cxl_memdev_fw_ops = {
+ .prepare = cxl_fw_prepare,
+ .write = cxl_fw_write,
+ .poll_complete = cxl_fw_poll_complete,
+ .cancel = cxl_fw_cancel,
+ .cleanup = cxl_fw_cleanup,
+};
+
+static void devm_cxl_remove_fw_upload(void *fwl)
+{
+ firmware_upload_unregister(fwl);
+}
+
+int cxl_memdev_setup_fw_upload(struct cxl_memdev_state *mds)
+{
+ struct cxl_dev_state *cxlds = &mds->cxlds;
+ struct device *dev = &cxlds->cxlmd->dev;
+ struct fw_upload *fwl;
+ int rc;
+
+ if (!test_bit(CXL_MEM_COMMAND_ID_GET_FW_INFO, mds->enabled_cmds))
+ return 0;
+
+ fwl = firmware_upload_register(THIS_MODULE, dev, dev_name(dev),
+ &cxl_memdev_fw_ops, mds);
+ if (IS_ERR(fwl))
+ return dev_err_probe(dev, PTR_ERR(fwl),
+ "Failed to register firmware loader\n");
+
+ rc = devm_add_action_or_reset(cxlds->dev, devm_cxl_remove_fw_upload,
+ fwl);
+ if (rc)
+ dev_err(dev,
+ "Failed to add firmware loader remove action: %d\n",
+ rc);
+
+ return rc;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_memdev_setup_fw_upload, CXL);
+
static const struct file_operations cxl_memdev_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = cxl_memdev_ioctl,
@@ -551,6 +983,35 @@ static const struct file_operations cxl_memdev_fops = {
.llseek = noop_llseek,
};
+static void put_sanitize(void *data)
+{
+ struct cxl_memdev_state *mds = data;
+
+ sysfs_put(mds->security.sanitize_node);
+}
+
+static int cxl_memdev_security_init(struct cxl_memdev *cxlmd)
+{
+ struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
+ struct device *dev = &cxlmd->dev;
+ struct kernfs_node *sec;
+
+ sec = sysfs_get_dirent(dev->kobj.sd, "security");
+ if (!sec) {
+ dev_err(dev, "sysfs_get_dirent 'security' failed\n");
+ return -ENODEV;
+ }
+ mds->security.sanitize_node = sysfs_get_dirent(sec, "state");
+ sysfs_put(sec);
+ if (!mds->security.sanitize_node) {
+ dev_err(dev, "sysfs_get_dirent 'state' failed\n");
+ return -ENODEV;
+ }
+
+ return devm_add_action_or_reset(cxlds->dev, put_sanitize, mds);
+ }
+
struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds)
{
struct cxl_memdev *cxlmd;
@@ -579,6 +1040,10 @@ struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds)
if (rc)
goto err;
+ rc = cxl_memdev_security_init(cxlmd);
+ if (rc)
+ goto err;
+
rc = devm_add_action_or_reset(cxlds->dev, cxl_memdev_unregister, cxlmd);
if (rc)
return ERR_PTR(rc);
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 67f4ab6daa34..c7a7887ebdcf 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -67,7 +67,7 @@ static int match_add_dports(struct pci_dev *pdev, void *data)
/**
* devm_cxl_port_enumerate_dports - enumerate downstream ports of the upstream port
- * @port: cxl_port whose ->uport is the upstream of dports to be enumerated
+ * @port: cxl_port whose ->uport_dev is the upstream of dports to be enumerated
*
* Returns a positive number of dports enumerated or a negative error
* code.
@@ -308,36 +308,17 @@ static void disable_hdm(void *_cxlhdm)
hdm + CXL_HDM_DECODER_CTRL_OFFSET);
}
-int devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm)
+static int devm_cxl_enable_hdm(struct device *host, struct cxl_hdm *cxlhdm)
{
- void __iomem *hdm;
+ void __iomem *hdm = cxlhdm->regs.hdm_decoder;
u32 global_ctrl;
- /*
- * If the hdm capability was not mapped there is nothing to enable and
- * the caller is responsible for what happens next. For example,
- * emulate a passthrough decoder.
- */
- if (IS_ERR(cxlhdm))
- return 0;
-
- hdm = cxlhdm->regs.hdm_decoder;
global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET);
-
- /*
- * If the HDM decoder capability was enabled on entry, skip
- * registering disable_hdm() since this decode capability may be
- * owned by platform firmware.
- */
- if (global_ctrl & CXL_HDM_DECODER_ENABLE)
- return 0;
-
writel(global_ctrl | CXL_HDM_DECODER_ENABLE,
hdm + CXL_HDM_DECODER_CTRL_OFFSET);
- return devm_add_action_or_reset(&port->dev, disable_hdm, cxlhdm);
+ return devm_add_action_or_reset(host, disable_hdm, cxlhdm);
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_enable_hdm, CXL);
int cxl_dvsec_rr_decode(struct device *dev, int d,
struct cxl_endpoint_dvsec_info *info)
@@ -511,7 +492,7 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
if (info->mem_enabled)
return 0;
- rc = devm_cxl_enable_hdm(port, cxlhdm);
+ rc = devm_cxl_enable_hdm(&port->dev, cxlhdm);
if (rc)
return rc;
@@ -622,7 +603,7 @@ static int cxl_cdat_read_table(struct device *dev,
*/
void read_cdat_data(struct cxl_port *port)
{
- struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport);
+ struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
struct device *host = cxlmd->dev.parent;
struct device *dev = &port->dev;
struct pci_doe_mb *cdat_doe;
diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c
index f8c38d997252..fc94f5240327 100644
--- a/drivers/cxl/core/pmem.c
+++ b/drivers/cxl/core/pmem.c
@@ -64,7 +64,7 @@ static int match_nvdimm_bridge(struct device *dev, void *data)
struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_memdev *cxlmd)
{
- struct cxl_port *port = find_cxl_root(dev_get_drvdata(&cxlmd->dev));
+ struct cxl_port *port = find_cxl_root(cxlmd->endpoint);
struct device *dev;
if (!port)
diff --git a/drivers/cxl/core/pmu.c b/drivers/cxl/core/pmu.c
new file mode 100644
index 000000000000..7684c843e5a5
--- /dev/null
+++ b/drivers/cxl/core/pmu.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Huawei. All rights reserved. */
+
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/idr.h>
+#include <cxlmem.h>
+#include <pmu.h>
+#include <cxl.h>
+#include "core.h"
+
+static void cxl_pmu_release(struct device *dev)
+{
+ struct cxl_pmu *pmu = to_cxl_pmu(dev);
+
+ kfree(pmu);
+}
+
+const struct device_type cxl_pmu_type = {
+ .name = "cxl_pmu",
+ .release = cxl_pmu_release,
+};
+
+static void remove_dev(void *dev)
+{
+ device_del(dev);
+}
+
+int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs,
+ int assoc_id, int index, enum cxl_pmu_type type)
+{
+ struct cxl_pmu *pmu;
+ struct device *dev;
+ int rc;
+
+ pmu = kzalloc(sizeof(*pmu), GFP_KERNEL);
+ if (!pmu)
+ return -ENOMEM;
+
+ pmu->assoc_id = assoc_id;
+ pmu->index = index;
+ pmu->type = type;
+ pmu->base = regs->pmu;
+ dev = &pmu->dev;
+ device_initialize(dev);
+ device_set_pm_not_required(dev);
+ dev->parent = parent;
+ dev->bus = &cxl_bus_type;
+ dev->type = &cxl_pmu_type;
+ switch (pmu->type) {
+ case CXL_PMU_MEMDEV:
+ rc = dev_set_name(dev, "pmu_mem%d.%d", assoc_id, index);
+ break;
+ }
+ if (rc)
+ goto err;
+
+ rc = device_add(dev);
+ if (rc)
+ goto err;
+
+ return devm_add_action_or_reset(parent, remove_dev, dev);
+
+err:
+ put_device(&pmu->dev);
+ return rc;
+}
+EXPORT_SYMBOL_NS_GPL(devm_cxl_pmu_add, CXL);
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index e7c284c890bc..724be8448eb4 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -56,6 +56,8 @@ static int cxl_device_id(const struct device *dev)
return CXL_DEVICE_MEMORY_EXPANDER;
if (dev->type == CXL_REGION_TYPE())
return CXL_DEVICE_REGION;
+ if (dev->type == &cxl_pmu_type)
+ return CXL_DEVICE_PMU;
return 0;
}
@@ -117,9 +119,9 @@ static ssize_t target_type_show(struct device *dev,
struct cxl_decoder *cxld = to_cxl_decoder(dev);
switch (cxld->target_type) {
- case CXL_DECODER_ACCELERATOR:
+ case CXL_DECODER_DEVMEM:
return sysfs_emit(buf, "accelerator\n");
- case CXL_DECODER_EXPANDER:
+ case CXL_DECODER_HOSTONLYMEM:
return sysfs_emit(buf, "expander\n");
}
return -ENXIO;
@@ -561,9 +563,9 @@ static void unregister_port(void *_port)
* unregistered while holding their parent port lock.
*/
if (!parent)
- lock_dev = port->uport;
+ lock_dev = port->uport_dev;
else if (is_cxl_root(parent))
- lock_dev = parent->uport;
+ lock_dev = parent->uport_dev;
else
lock_dev = &parent->dev;
@@ -583,7 +585,8 @@ static int devm_cxl_link_uport(struct device *host, struct cxl_port *port)
{
int rc;
- rc = sysfs_create_link(&port->dev.kobj, &port->uport->kobj, "uport");
+ rc = sysfs_create_link(&port->dev.kobj, &port->uport_dev->kobj,
+ "uport");
if (rc)
return rc;
return devm_add_action_or_reset(host, cxl_unlink_uport, port);
@@ -605,7 +608,7 @@ static int devm_cxl_link_parent_dport(struct device *host,
if (!parent_dport)
return 0;
- rc = sysfs_create_link(&port->dev.kobj, &parent_dport->dport->kobj,
+ rc = sysfs_create_link(&port->dev.kobj, &parent_dport->dport_dev->kobj,
"parent_dport");
if (rc)
return rc;
@@ -614,7 +617,7 @@ static int devm_cxl_link_parent_dport(struct device *host,
static struct lock_class_key cxl_port_key;
-static struct cxl_port *cxl_port_alloc(struct device *uport,
+static struct cxl_port *cxl_port_alloc(struct device *uport_dev,
resource_size_t component_reg_phys,
struct cxl_dport *parent_dport)
{
@@ -630,7 +633,7 @@ static struct cxl_port *cxl_port_alloc(struct device *uport,
if (rc < 0)
goto err;
port->id = rc;
- port->uport = uport;
+ port->uport_dev = uport_dev;
/*
* The top-level cxl_port "cxl_root" does not have a cxl_port as
@@ -658,12 +661,13 @@ static struct cxl_port *cxl_port_alloc(struct device *uport,
if (iter->host_bridge)
port->host_bridge = iter->host_bridge;
else if (parent_dport->rch)
- port->host_bridge = parent_dport->dport;
+ port->host_bridge = parent_dport->dport_dev;
else
- port->host_bridge = iter->uport;
- dev_dbg(uport, "host-bridge: %s\n", dev_name(port->host_bridge));
+ port->host_bridge = iter->uport_dev;
+ dev_dbg(uport_dev, "host-bridge: %s\n",
+ dev_name(port->host_bridge));
} else
- dev->parent = uport;
+ dev->parent = uport_dev;
port->component_reg_phys = component_reg_phys;
ida_init(&port->decoder_ida);
@@ -686,8 +690,38 @@ err:
return ERR_PTR(rc);
}
+static int cxl_setup_comp_regs(struct device *dev, struct cxl_register_map *map,
+ resource_size_t component_reg_phys)
+{
+ if (component_reg_phys == CXL_RESOURCE_NONE)
+ return 0;
+
+ *map = (struct cxl_register_map) {
+ .dev = dev,
+ .reg_type = CXL_REGLOC_RBI_COMPONENT,
+ .resource = component_reg_phys,
+ .max_size = CXL_COMPONENT_REG_BLOCK_SIZE,
+ };
+
+ return cxl_setup_regs(map);
+}
+
+static inline int cxl_port_setup_regs(struct cxl_port *port,
+ resource_size_t component_reg_phys)
+{
+ 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)
+{
+ return cxl_setup_comp_regs(dport->dport_dev, &dport->comp_map,
+ component_reg_phys);
+}
+
static struct cxl_port *__devm_cxl_add_port(struct device *host,
- struct device *uport,
+ struct device *uport_dev,
resource_size_t component_reg_phys,
struct cxl_dport *parent_dport)
{
@@ -695,12 +729,12 @@ static struct cxl_port *__devm_cxl_add_port(struct device *host,
struct device *dev;
int rc;
- port = cxl_port_alloc(uport, component_reg_phys, parent_dport);
+ port = cxl_port_alloc(uport_dev, component_reg_phys, parent_dport);
if (IS_ERR(port))
return port;
dev = &port->dev;
- if (is_cxl_memdev(uport))
+ if (is_cxl_memdev(uport_dev))
rc = dev_set_name(dev, "endpoint%d", port->id);
else if (parent_dport)
rc = dev_set_name(dev, "port%d", port->id);
@@ -709,6 +743,10 @@ static struct cxl_port *__devm_cxl_add_port(struct device *host,
if (rc)
goto err;
+ rc = cxl_port_setup_regs(port, component_reg_phys);
+ if (rc)
+ goto err;
+
rc = device_add(dev);
if (rc)
goto err;
@@ -735,28 +773,29 @@ err:
/**
* devm_cxl_add_port - register a cxl_port in CXL memory decode hierarchy
* @host: host device for devm operations
- * @uport: "physical" device implementing this upstream port
+ * @uport_dev: "physical" device implementing this upstream port
* @component_reg_phys: (optional) for configurable cxl_port instances
* @parent_dport: next hop up in the CXL memory decode hierarchy
*/
-struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport,
+struct cxl_port *devm_cxl_add_port(struct device *host,
+ struct device *uport_dev,
resource_size_t component_reg_phys,
struct cxl_dport *parent_dport)
{
struct cxl_port *port, *parent_port;
- port = __devm_cxl_add_port(host, uport, component_reg_phys,
+ port = __devm_cxl_add_port(host, uport_dev, component_reg_phys,
parent_dport);
parent_port = parent_dport ? parent_dport->port : NULL;
if (IS_ERR(port)) {
- dev_dbg(uport, "Failed to add%s%s%s: %ld\n",
+ dev_dbg(uport_dev, "Failed to add%s%s%s: %ld\n",
parent_port ? " port to " : "",
parent_port ? dev_name(&parent_port->dev) : "",
parent_port ? "" : " root port",
PTR_ERR(port));
} else {
- dev_dbg(uport, "%s added%s%s%s\n",
+ dev_dbg(uport_dev, "%s added%s%s%s\n",
dev_name(&port->dev),
parent_port ? " to " : "",
parent_port ? dev_name(&parent_port->dev) : "",
@@ -773,33 +812,34 @@ struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port)
if (is_cxl_root(port))
return NULL;
- if (dev_is_pci(port->uport)) {
- struct pci_dev *pdev = to_pci_dev(port->uport);
+ if (dev_is_pci(port->uport_dev)) {
+ struct pci_dev *pdev = to_pci_dev(port->uport_dev);
return pdev->subordinate;
}
- return xa_load(&cxl_root_buses, (unsigned long)port->uport);
+ return xa_load(&cxl_root_buses, (unsigned long)port->uport_dev);
}
EXPORT_SYMBOL_NS_GPL(cxl_port_to_pci_bus, CXL);
-static void unregister_pci_bus(void *uport)
+static void unregister_pci_bus(void *uport_dev)
{
- xa_erase(&cxl_root_buses, (unsigned long)uport);
+ xa_erase(&cxl_root_buses, (unsigned long)uport_dev);
}
-int devm_cxl_register_pci_bus(struct device *host, struct device *uport,
+int devm_cxl_register_pci_bus(struct device *host, struct device *uport_dev,
struct pci_bus *bus)
{
int rc;
- if (dev_is_pci(uport))
+ if (dev_is_pci(uport_dev))
return -EINVAL;
- rc = xa_insert(&cxl_root_buses, (unsigned long)uport, bus, GFP_KERNEL);
+ rc = xa_insert(&cxl_root_buses, (unsigned long)uport_dev, bus,
+ GFP_KERNEL);
if (rc)
return rc;
- return devm_add_action_or_reset(host, unregister_pci_bus, uport);
+ return devm_add_action_or_reset(host, unregister_pci_bus, uport_dev);
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_register_pci_bus, CXL);
@@ -847,22 +887,22 @@ static struct cxl_dport *find_dport(struct cxl_port *port, int id)
return NULL;
}
-static int add_dport(struct cxl_port *port, struct cxl_dport *new)
+static int add_dport(struct cxl_port *port, struct cxl_dport *dport)
{
struct cxl_dport *dup;
int rc;
device_lock_assert(&port->dev);
- dup = find_dport(port, new->port_id);
+ dup = find_dport(port, dport->port_id);
if (dup) {
dev_err(&port->dev,
"unable to add dport%d-%s non-unique port id (%s)\n",
- new->port_id, dev_name(new->dport),
- dev_name(dup->dport));
+ dport->port_id, dev_name(dport->dport_dev),
+ dev_name(dup->dport_dev));
return -EBUSY;
}
- rc = xa_insert(&port->dports, (unsigned long)new->dport, new,
+ rc = xa_insert(&port->dports, (unsigned long)dport->dport_dev, dport,
GFP_KERNEL);
if (rc)
return rc;
@@ -895,8 +935,8 @@ static void cxl_dport_remove(void *data)
struct cxl_dport *dport = data;
struct cxl_port *port = dport->port;
- xa_erase(&port->dports, (unsigned long) dport->dport);
- put_device(dport->dport);
+ xa_erase(&port->dports, (unsigned long) dport->dport_dev);
+ put_device(dport->dport_dev);
}
static void cxl_dport_unlink(void *data)
@@ -920,7 +960,7 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
int rc;
if (is_cxl_root(port))
- host = port->uport;
+ host = port->uport_dev;
else
host = &port->dev;
@@ -938,13 +978,29 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
if (!dport)
return ERR_PTR(-ENOMEM);
- dport->dport = dport_dev;
+ if (rcrb != CXL_RESOURCE_NONE) {
+ dport->rcrb.base = rcrb;
+ component_reg_phys = __rcrb_to_component(dport_dev, &dport->rcrb,
+ CXL_RCRB_DOWNSTREAM);
+ if (component_reg_phys == CXL_RESOURCE_NONE) {
+ dev_warn(dport_dev, "Invalid Component Registers in RCRB");
+ return ERR_PTR(-ENXIO);
+ }
+
+ dport->rch = true;
+ }
+
+ if (component_reg_phys != CXL_RESOURCE_NONE)
+ dev_dbg(dport_dev, "Component Registers found for dport: %pa\n",
+ &component_reg_phys);
+
+ dport->dport_dev = dport_dev;
dport->port_id = port_id;
- dport->component_reg_phys = component_reg_phys;
dport->port = port;
- if (rcrb != CXL_RESOURCE_NONE)
- dport->rch = true;
- dport->rcrb = rcrb;
+
+ rc = cxl_dport_setup_regs(dport, component_reg_phys);
+ if (rc)
+ return ERR_PTR(rc);
cond_cxl_root_lock(port);
rc = add_dport(port, dport);
@@ -1004,14 +1060,12 @@ EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport, CXL);
* @port: the cxl_port that references this dport
* @dport_dev: firmware or PCI device representing the dport
* @port_id: identifier for this dport in a decoder's target list
- * @component_reg_phys: optional location of CXL component registers
* @rcrb: mandatory location of a Root Complex Register Block
*
* See CXL 3.0 9.11.8 CXL Devices Attached to an RCH
*/
struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
struct device *dport_dev, int port_id,
- resource_size_t component_reg_phys,
resource_size_t rcrb)
{
struct cxl_dport *dport;
@@ -1022,7 +1076,7 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
}
dport = __devm_cxl_add_dport(port, dport_dev, port_id,
- component_reg_phys, rcrb);
+ CXL_RESOURCE_NONE, rcrb);
if (IS_ERR(dport)) {
dev_dbg(dport_dev, "failed to add RCH dport to %s: %ld\n",
dev_name(&port->dev), PTR_ERR(dport));
@@ -1161,7 +1215,7 @@ static struct device *grandparent(struct device *dev)
static void delete_endpoint(void *data)
{
struct cxl_memdev *cxlmd = data;
- struct cxl_port *endpoint = dev_get_drvdata(&cxlmd->dev);
+ struct cxl_port *endpoint = cxlmd->endpoint;
struct cxl_port *parent_port;
struct device *parent;
@@ -1176,6 +1230,7 @@ static void delete_endpoint(void *data)
devm_release_action(parent, cxl_unlink_uport, endpoint);
devm_release_action(parent, unregister_port, endpoint);
}
+ cxlmd->endpoint = NULL;
device_unlock(parent);
put_device(parent);
out:
@@ -1187,7 +1242,7 @@ int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint)
struct device *dev = &cxlmd->dev;
get_device(&endpoint->dev);
- dev_set_drvdata(dev, endpoint);
+ cxlmd->endpoint = endpoint;
cxlmd->depth = endpoint->depth;
return devm_add_action_or_reset(dev, delete_endpoint, cxlmd);
}
@@ -1363,7 +1418,7 @@ out:
rc = PTR_ERR(port);
else {
dev_dbg(&cxlmd->dev, "add to new port %s:%s\n",
- dev_name(&port->dev), dev_name(port->uport));
+ dev_name(&port->dev), dev_name(port->uport_dev));
rc = cxl_add_ep(dport, &cxlmd->dev);
if (rc == -EBUSY) {
/*
@@ -1425,7 +1480,8 @@ retry:
if (port) {
dev_dbg(&cxlmd->dev,
"found already registered port %s:%s\n",
- dev_name(&port->dev), dev_name(port->uport));
+ dev_name(&port->dev),
+ dev_name(port->uport_dev));
rc = cxl_add_ep(dport, &cxlmd->dev);
/*
@@ -1465,6 +1521,13 @@ retry:
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_ports, CXL);
+struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev,
+ struct cxl_dport **dport)
+{
+ return find_cxl_port(pdev->dev.parent, dport);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_pci_find_port, CXL);
+
struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd,
struct cxl_dport **dport)
{
@@ -1550,7 +1613,7 @@ static int cxl_decoder_init(struct cxl_port *port, struct cxl_decoder *cxld)
/* Pre initialize an "empty" decoder */
cxld->interleave_ways = 1;
cxld->interleave_granularity = PAGE_SIZE;
- cxld->target_type = CXL_DECODER_EXPANDER;
+ cxld->target_type = CXL_DECODER_HOSTONLYMEM;
cxld->hpa_range = (struct range) {
.start = 0,
.end = -1,
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index f822de44bee0..e115ba382e04 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -125,10 +125,38 @@ static struct cxl_region_ref *cxl_rr_load(struct cxl_port *port,
return xa_load(&port->regions, (unsigned long)cxlr);
}
+static int cxl_region_invalidate_memregion(struct cxl_region *cxlr)
+{
+ if (!cpu_cache_has_invalidate_memregion()) {
+ if (IS_ENABLED(CONFIG_CXL_REGION_INVALIDATION_TEST)) {
+ dev_warn_once(
+ &cxlr->dev,
+ "Bypassing cpu_cache_invalidate_memregion() for testing!\n");
+ return 0;
+ } else {
+ dev_err(&cxlr->dev,
+ "Failed to synchronize CPU cache state\n");
+ return -ENXIO;
+ }
+ }
+
+ cpu_cache_invalidate_memregion(IORES_DESC_CXL);
+ return 0;
+}
+
static int cxl_region_decode_reset(struct cxl_region *cxlr, int count)
{
struct cxl_region_params *p = &cxlr->params;
- int i;
+ int i, rc = 0;
+
+ /*
+ * Before region teardown attempt to flush, and if the flush
+ * fails cancel the region teardown for data consistency
+ * concerns
+ */
+ rc = cxl_region_invalidate_memregion(cxlr);
+ if (rc)
+ return rc;
for (i = count - 1; i >= 0; i--) {
struct cxl_endpoint_decoder *cxled = p->targets[i];
@@ -136,7 +164,6 @@ static int cxl_region_decode_reset(struct cxl_region *cxlr, int count)
struct cxl_port *iter = cxled_to_port(cxled);
struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct cxl_ep *ep;
- int rc = 0;
if (cxlds->rcd)
goto endpoint_reset;
@@ -155,14 +182,19 @@ static int cxl_region_decode_reset(struct cxl_region *cxlr, int count)
rc = cxld->reset(cxld);
if (rc)
return rc;
+ set_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
}
endpoint_reset:
rc = cxled->cxld.reset(&cxled->cxld);
if (rc)
return rc;
+ set_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
}
+ /* all decoders associated with this region have been torn down */
+ clear_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
+
return 0;
}
@@ -256,9 +288,19 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr,
goto out;
}
- if (commit)
+ /*
+ * Invalidate caches before region setup to drop any speculative
+ * consumption of this address space
+ */
+ rc = cxl_region_invalidate_memregion(cxlr);
+ if (rc)
+ return rc;
+
+ if (commit) {
rc = cxl_region_decode_commit(cxlr);
- else {
+ if (rc == 0)
+ p->state = CXL_CONFIG_COMMIT;
+ } else {
p->state = CXL_CONFIG_RESET_PENDING;
up_write(&cxl_region_rwsem);
device_release_driver(&cxlr->dev);
@@ -268,18 +310,20 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr,
* The lock was dropped, so need to revalidate that the reset is
* still pending.
*/
- if (p->state == CXL_CONFIG_RESET_PENDING)
+ if (p->state == CXL_CONFIG_RESET_PENDING) {
rc = cxl_region_decode_reset(cxlr, p->interleave_ways);
+ /*
+ * Revert to committed since there may still be active
+ * decoders associated with this region, or move forward
+ * to active to mark the reset successful
+ */
+ if (rc)
+ p->state = CXL_CONFIG_COMMIT;
+ else
+ p->state = CXL_CONFIG_ACTIVE;
+ }
}
- if (rc)
- goto out;
-
- if (commit)
- p->state = CXL_CONFIG_COMMIT;
- else if (p->state == CXL_CONFIG_RESET_PENDING)
- p->state = CXL_CONFIG_ACTIVE;
-
out:
up_write(&cxl_region_rwsem);
@@ -809,6 +853,18 @@ static int cxl_rr_alloc_decoder(struct cxl_port *port, struct cxl_region *cxlr,
return -EBUSY;
}
+ /*
+ * Endpoints should already match the region type, but backstop that
+ * assumption with an assertion. Switch-decoders change mapping-type
+ * based on what is mapped when they are assigned to a region.
+ */
+ dev_WARN_ONCE(&cxlr->dev,
+ port == cxled_to_port(cxled) &&
+ cxld->target_type != cxlr->type,
+ "%s:%s mismatch decoder type %d -> %d\n",
+ dev_name(&cxled_to_memdev(cxled)->dev),
+ dev_name(&cxld->dev), cxld->target_type, cxlr->type);
+ cxld->target_type = cxlr->type;
cxl_rr->decoder = cxld;
return 0;
}
@@ -906,10 +962,10 @@ static int cxl_port_attach_region(struct cxl_port *port,
dev_dbg(&cxlr->dev,
"%s:%s %s add: %s:%s @ %d next: %s nr_eps: %d nr_targets: %d\n",
- dev_name(port->uport), dev_name(&port->dev),
+ dev_name(port->uport_dev), dev_name(&port->dev),
dev_name(&cxld->dev), dev_name(&cxlmd->dev),
dev_name(&cxled->cxld.dev), pos,
- ep ? ep->next ? dev_name(ep->next->uport) :
+ ep ? ep->next ? dev_name(ep->next->uport_dev) :
dev_name(&cxlmd->dev) :
"none",
cxl_rr->nr_eps, cxl_rr->nr_targets);
@@ -984,7 +1040,7 @@ static int check_last_peer(struct cxl_endpoint_decoder *cxled,
*/
if (pos < distance) {
dev_dbg(&cxlr->dev, "%s:%s: cannot host %s:%s at %d\n",
- dev_name(port->uport), dev_name(&port->dev),
+ dev_name(port->uport_dev), dev_name(&port->dev),
dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos);
return -ENXIO;
}
@@ -994,7 +1050,7 @@ static int check_last_peer(struct cxl_endpoint_decoder *cxled,
if (ep->dport != ep_peer->dport) {
dev_dbg(&cxlr->dev,
"%s:%s: %s:%s pos %d mismatched peer %s:%s\n",
- dev_name(port->uport), dev_name(&port->dev),
+ dev_name(port->uport_dev), dev_name(&port->dev),
dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos,
dev_name(&cxlmd_peer->dev),
dev_name(&cxled_peer->cxld.dev));
@@ -1026,7 +1082,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
*/
if (!is_power_of_2(cxl_rr->nr_targets)) {
dev_dbg(&cxlr->dev, "%s:%s: invalid target count %d\n",
- dev_name(port->uport), dev_name(&port->dev),
+ dev_name(port->uport_dev), dev_name(&port->dev),
cxl_rr->nr_targets);
return -EINVAL;
}
@@ -1076,7 +1132,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
rc = granularity_to_eig(parent_ig, &peig);
if (rc) {
dev_dbg(&cxlr->dev, "%s:%s: invalid parent granularity: %d\n",
- dev_name(parent_port->uport),
+ dev_name(parent_port->uport_dev),
dev_name(&parent_port->dev), parent_ig);
return rc;
}
@@ -1084,7 +1140,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
rc = ways_to_eiw(parent_iw, &peiw);
if (rc) {
dev_dbg(&cxlr->dev, "%s:%s: invalid parent interleave: %d\n",
- dev_name(parent_port->uport),
+ dev_name(parent_port->uport_dev),
dev_name(&parent_port->dev), parent_iw);
return rc;
}
@@ -1093,7 +1149,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
rc = ways_to_eiw(iw, &eiw);
if (rc) {
dev_dbg(&cxlr->dev, "%s:%s: invalid port interleave: %d\n",
- dev_name(port->uport), dev_name(&port->dev), iw);
+ dev_name(port->uport_dev), dev_name(&port->dev), iw);
return rc;
}
@@ -1113,7 +1169,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
rc = eig_to_granularity(eig, &ig);
if (rc) {
dev_dbg(&cxlr->dev, "%s:%s: invalid interleave: %d\n",
- dev_name(port->uport), dev_name(&port->dev),
+ dev_name(port->uport_dev), dev_name(&port->dev),
256 << eig);
return rc;
}
@@ -1126,11 +1182,11 @@ static int cxl_port_setup_targets(struct cxl_port *port,
((cxld->flags & CXL_DECODER_F_ENABLE) == 0)) {
dev_err(&cxlr->dev,
"%s:%s %s expected iw: %d ig: %d %pr\n",
- dev_name(port->uport), dev_name(&port->dev),
+ dev_name(port->uport_dev), dev_name(&port->dev),
__func__, iw, ig, p->res);
dev_err(&cxlr->dev,
"%s:%s %s got iw: %d ig: %d state: %s %#llx:%#llx\n",
- dev_name(port->uport), dev_name(&port->dev),
+ dev_name(port->uport_dev), dev_name(&port->dev),
__func__, cxld->interleave_ways,
cxld->interleave_granularity,
(cxld->flags & CXL_DECODER_F_ENABLE) ?
@@ -1147,22 +1203,22 @@ static int cxl_port_setup_targets(struct cxl_port *port,
.end = p->res->end,
};
}
- dev_dbg(&cxlr->dev, "%s:%s iw: %d ig: %d\n", dev_name(port->uport),
+ dev_dbg(&cxlr->dev, "%s:%s iw: %d ig: %d\n", dev_name(port->uport_dev),
dev_name(&port->dev), iw, ig);
add_target:
if (cxl_rr->nr_targets_set == cxl_rr->nr_targets) {
dev_dbg(&cxlr->dev,
"%s:%s: targets full trying to add %s:%s at %d\n",
- dev_name(port->uport), dev_name(&port->dev),
+ dev_name(port->uport_dev), dev_name(&port->dev),
dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos);
return -ENXIO;
}
if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) {
if (cxlsd->target[cxl_rr->nr_targets_set] != ep->dport) {
dev_dbg(&cxlr->dev, "%s:%s: %s expected %s at %d\n",
- dev_name(port->uport), dev_name(&port->dev),
+ dev_name(port->uport_dev), dev_name(&port->dev),
dev_name(&cxlsd->cxld.dev),
- dev_name(ep->dport->dport),
+ dev_name(ep->dport->dport_dev),
cxl_rr->nr_targets_set);
return -ENXIO;
}
@@ -1172,8 +1228,8 @@ add_target:
out_target_set:
cxl_rr->nr_targets_set += inc;
dev_dbg(&cxlr->dev, "%s:%s target[%d] = %s for %s:%s @ %d\n",
- dev_name(port->uport), dev_name(&port->dev),
- cxl_rr->nr_targets_set - 1, dev_name(ep->dport->dport),
+ dev_name(port->uport_dev), dev_name(&port->dev),
+ cxl_rr->nr_targets_set - 1, dev_name(ep->dport->dport_dev),
dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos);
return 0;
@@ -1492,7 +1548,7 @@ static int cmp_decode_pos(const void *a, const void *b)
if (!dev) {
struct range *range = &cxled_a->cxld.hpa_range;
- dev_err(port->uport,
+ dev_err(port->uport_dev,
"failed to find decoder that maps %#llx-%#llx\n",
range->start, range->end);
goto err;
@@ -1507,14 +1563,15 @@ static int cmp_decode_pos(const void *a, const void *b)
put_device(dev);
if (a_pos < 0 || b_pos < 0) {
- dev_err(port->uport,
+ dev_err(port->uport_dev,
"failed to find shared decoder for %s and %s\n",
dev_name(cxlmd_a->dev.parent),
dev_name(cxlmd_b->dev.parent));
goto err;
}
- dev_dbg(port->uport, "%s comes %s %s\n", dev_name(cxlmd_a->dev.parent),
+ dev_dbg(port->uport_dev, "%s comes %s %s\n",
+ dev_name(cxlmd_a->dev.parent),
a_pos - b_pos < 0 ? "before" : "after",
dev_name(cxlmd_b->dev.parent));
@@ -1674,7 +1731,6 @@ static int cxl_region_attach(struct cxl_region *cxlr,
if (rc)
goto err_decrement;
p->state = CXL_CONFIG_ACTIVE;
- set_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags);
}
cxled->cxld.interleave_ways = p->interleave_ways;
@@ -2059,11 +2115,11 @@ static struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd,
if (rc)
goto err;
- rc = devm_add_action_or_reset(port->uport, unregister_region, cxlr);
+ rc = devm_add_action_or_reset(port->uport_dev, unregister_region, cxlr);
if (rc)
return ERR_PTR(rc);
- dev_dbg(port->uport, "%s: created %s\n",
+ dev_dbg(port->uport_dev, "%s: created %s\n",
dev_name(&cxlrd->cxlsd.cxld.dev), dev_name(dev));
return cxlr;
@@ -2103,7 +2159,7 @@ static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd,
return ERR_PTR(-EBUSY);
}
- return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_EXPANDER);
+ return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_HOSTONLYMEM);
}
static ssize_t create_pmem_region_store(struct device *dev,
@@ -2191,7 +2247,7 @@ static ssize_t delete_region_store(struct device *dev,
if (IS_ERR(cxlr))
return PTR_ERR(cxlr);
- devm_release_action(port->uport, unregister_region, cxlr);
+ devm_release_action(port->uport_dev, unregister_region, cxlr);
put_device(&cxlr->dev);
return len;
@@ -2356,7 +2412,8 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
rc = device_for_each_child(&port->dev, &ctx, poison_by_decoder);
if (rc == 1)
- rc = cxl_get_poison_unmapped(to_cxl_memdev(port->uport), &ctx);
+ rc = cxl_get_poison_unmapped(to_cxl_memdev(port->uport_dev),
+ &ctx);
up_read(&cxl_region_rwsem);
return rc;
@@ -2732,7 +2789,7 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
err:
up_write(&cxl_region_rwsem);
- devm_release_action(port->uport, unregister_region, cxlr);
+ devm_release_action(port->uport_dev, unregister_region, cxlr);
return ERR_PTR(rc);
}
@@ -2803,30 +2860,6 @@ out:
}
EXPORT_SYMBOL_NS_GPL(cxl_add_to_region, CXL);
-static int cxl_region_invalidate_memregion(struct cxl_region *cxlr)
-{
- if (!test_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags))
- return 0;
-
- if (!cpu_cache_has_invalidate_memregion()) {
- if (IS_ENABLED(CONFIG_CXL_REGION_INVALIDATION_TEST)) {
- dev_warn_once(
- &cxlr->dev,
- "Bypassing cpu_cache_invalidate_memregion() for testing!\n");
- clear_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags);
- return 0;
- } else {
- dev_err(&cxlr->dev,
- "Failed to synchronize CPU cache state\n");
- return -ENXIO;
- }
- }
-
- cpu_cache_invalidate_memregion(IORES_DESC_CXL);
- clear_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags);
- return 0;
-}
-
static int is_system_ram(struct resource *res, void *arg)
{
struct cxl_region *cxlr = arg;
@@ -2854,7 +2887,12 @@ static int cxl_region_probe(struct device *dev)
goto out;
}
- rc = cxl_region_invalidate_memregion(cxlr);
+ if (test_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags)) {
+ dev_err(&cxlr->dev,
+ "failed to activate, re-commit region and retry\n");
+ rc = -ENXIO;
+ goto out;
+ }
/*
* From this point on any path that changes the region's state away from
diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
index 1476a0299c9b..6281127b3e9d 100644
--- a/drivers/cxl/core/regs.c
+++ b/drivers/cxl/core/regs.c
@@ -6,6 +6,7 @@
#include <linux/pci.h>
#include <cxlmem.h>
#include <cxlpci.h>
+#include <pmu.h>
#include "core.h"
@@ -199,11 +200,13 @@ void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr,
return ret_val;
}
-int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs,
- struct cxl_register_map *map, unsigned long map_mask)
+int cxl_map_component_regs(const struct cxl_register_map *map,
+ struct cxl_component_regs *regs,
+ unsigned long map_mask)
{
+ struct device *dev = map->dev;
struct mapinfo {
- struct cxl_reg_map *rmap;
+ const struct cxl_reg_map *rmap;
void __iomem **addr;
} mapinfo[] = {
{ &map->component_map.hdm_decoder, &regs->hdm_decoder },
@@ -231,13 +234,13 @@ int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs,
}
EXPORT_SYMBOL_NS_GPL(cxl_map_component_regs, CXL);
-int cxl_map_device_regs(struct device *dev,
- struct cxl_device_regs *regs,
- struct cxl_register_map *map)
+int cxl_map_device_regs(const struct cxl_register_map *map,
+ struct cxl_device_regs *regs)
{
+ struct device *dev = map->dev;
resource_size_t phys_addr = map->resource;
struct mapinfo {
- struct cxl_reg_map *rmap;
+ const struct cxl_reg_map *rmap;
void __iomem **addr;
} mapinfo[] = {
{ &map->device_map.status, &regs->status, },
@@ -286,23 +289,30 @@ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi,
}
/**
- * cxl_find_regblock() - Locate register blocks by type
+ * cxl_find_regblock_instance() - Locate a register block by type / index
* @pdev: The CXL PCI device to enumerate.
* @type: Register Block Indicator id
* @map: Enumeration output, clobbered on error
+ * @index: Index into which particular instance of a regblock wanted in the
+ * order found in register locator DVSEC.
*
* Return: 0 if register block enumerated, negative error code otherwise
*
* A CXL DVSEC may point to one or more register blocks, search for them
- * by @type.
+ * by @type and @index.
*/
-int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
- struct cxl_register_map *map)
+int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type,
+ struct cxl_register_map *map, int index)
{
u32 regloc_size, regblocks;
+ int instance = 0;
int regloc, i;
- map->resource = CXL_RESOURCE_NONE;
+ *map = (struct cxl_register_map) {
+ .dev = &pdev->dev,
+ .resource = CXL_RESOURCE_NONE,
+ };
+
regloc = pci_find_dvsec_capability(pdev, PCI_DVSEC_VENDOR_ID_CXL,
CXL_DVSEC_REG_LOCATOR);
if (!regloc)
@@ -323,20 +333,148 @@ int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
if (!cxl_decode_regblock(pdev, reg_lo, reg_hi, map))
continue;
- if (map->reg_type == type)
- return 0;
+ if (map->reg_type == type) {
+ if (index == instance)
+ return 0;
+ instance++;
+ }
}
map->resource = CXL_RESOURCE_NONE;
return -ENODEV;
}
+EXPORT_SYMBOL_NS_GPL(cxl_find_regblock_instance, CXL);
+
+/**
+ * cxl_find_regblock() - Locate register blocks by type
+ * @pdev: The CXL PCI device to enumerate.
+ * @type: Register Block Indicator id
+ * @map: Enumeration output, clobbered on error
+ *
+ * Return: 0 if register block enumerated, negative error code otherwise
+ *
+ * A CXL DVSEC may point to one or more register blocks, search for them
+ * by @type.
+ */
+int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
+ struct cxl_register_map *map)
+{
+ return cxl_find_regblock_instance(pdev, type, map, 0);
+}
EXPORT_SYMBOL_NS_GPL(cxl_find_regblock, CXL);
-resource_size_t cxl_rcrb_to_component(struct device *dev,
- resource_size_t rcrb,
- enum cxl_rcrb which)
+/**
+ * cxl_count_regblock() - Count instances of a given regblock type.
+ * @pdev: The CXL PCI device to enumerate.
+ * @type: Register Block Indicator id
+ *
+ * Some regblocks may be repeated. Count how many instances.
+ *
+ * Return: count of matching regblocks.
+ */
+int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type)
+{
+ struct cxl_register_map map;
+ int rc, count = 0;
+
+ while (1) {
+ rc = cxl_find_regblock_instance(pdev, type, &map, count);
+ if (rc)
+ return count;
+ count++;
+ }
+}
+EXPORT_SYMBOL_NS_GPL(cxl_count_regblock, CXL);
+
+int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs,
+ struct cxl_register_map *map)
+{
+ struct device *dev = &pdev->dev;
+ resource_size_t phys_addr;
+
+ phys_addr = map->resource;
+ regs->pmu = devm_cxl_iomap_block(dev, phys_addr, CXL_PMU_REGMAP_SIZE);
+ if (!regs->pmu)
+ return -ENOMEM;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_map_pmu_regs, CXL);
+
+static int cxl_map_regblock(struct cxl_register_map *map)
+{
+ struct device *dev = map->dev;
+
+ map->base = ioremap(map->resource, map->max_size);
+ if (!map->base) {
+ dev_err(dev, "failed to map registers\n");
+ return -ENOMEM;
+ }
+
+ dev_dbg(dev, "Mapped CXL Memory Device resource %pa\n", &map->resource);
+ return 0;
+}
+
+static void cxl_unmap_regblock(struct cxl_register_map *map)
+{
+ iounmap(map->base);
+ map->base = NULL;
+}
+
+static int cxl_probe_regs(struct cxl_register_map *map)
+{
+ struct cxl_component_reg_map *comp_map;
+ struct cxl_device_reg_map *dev_map;
+ struct device *dev = map->dev;
+ void __iomem *base = map->base;
+
+ switch (map->reg_type) {
+ case CXL_REGLOC_RBI_COMPONENT:
+ comp_map = &map->component_map;
+ cxl_probe_component_regs(dev, base, comp_map);
+ dev_dbg(dev, "Set up component registers\n");
+ break;
+ case CXL_REGLOC_RBI_MEMDEV:
+ dev_map = &map->device_map;
+ cxl_probe_device_regs(dev, base, dev_map);
+ if (!dev_map->status.valid || !dev_map->mbox.valid ||
+ !dev_map->memdev.valid) {
+ dev_err(dev, "registers not found: %s%s%s\n",
+ !dev_map->status.valid ? "status " : "",
+ !dev_map->mbox.valid ? "mbox " : "",
+ !dev_map->memdev.valid ? "memdev " : "");
+ return -ENXIO;
+ }
+
+ dev_dbg(dev, "Probing device registers...\n");
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int cxl_setup_regs(struct cxl_register_map *map)
+{
+ int rc;
+
+ rc = cxl_map_regblock(map);
+ if (rc)
+ return rc;
+
+ rc = cxl_probe_regs(map);
+ cxl_unmap_regblock(map);
+
+ return rc;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_setup_regs, CXL);
+
+resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri,
+ enum cxl_rcrb which)
{
resource_size_t component_reg_phys;
+ resource_size_t rcrb = ri->base;
void __iomem *addr;
u32 bar0, bar1;
u16 cmd;
@@ -395,4 +533,12 @@ resource_size_t cxl_rcrb_to_component(struct device *dev,
return component_reg_phys;
}
-EXPORT_SYMBOL_NS_GPL(cxl_rcrb_to_component, CXL);
+
+resource_size_t cxl_rcd_component_reg_phys(struct device *dev,
+ struct cxl_dport *dport)
+{
+ if (!dport->rch)
+ return CXL_RESOURCE_NONE;
+ return __rcrb_to_component(dev, &dport->rcrb, CXL_RCRB_UPSTREAM);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_rcd_component_reg_phys, CXL);
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index f93a28538962..76d92561af29 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -56,7 +56,7 @@
#define CXL_HDM_DECODER0_CTRL_COMMIT BIT(9)
#define CXL_HDM_DECODER0_CTRL_COMMITTED BIT(10)
#define CXL_HDM_DECODER0_CTRL_COMMIT_ERROR BIT(11)
-#define CXL_HDM_DECODER0_CTRL_TYPE BIT(12)
+#define CXL_HDM_DECODER0_CTRL_HOSTONLY BIT(12)
#define CXL_HDM_DECODER0_TL_LOW(i) (0x20 * (i) + 0x24)
#define CXL_HDM_DECODER0_TL_HIGH(i) (0x20 * (i) + 0x28)
#define CXL_HDM_DECODER0_SKIP_LOW(i) CXL_HDM_DECODER0_TL_LOW(i)
@@ -176,14 +176,22 @@ static inline int ways_to_eiw(unsigned int ways, u8 *eiw)
/* CXL 2.0 8.2.8.4 Mailbox Registers */
#define CXLDEV_MBOX_CAPS_OFFSET 0x00
#define CXLDEV_MBOX_CAP_PAYLOAD_SIZE_MASK GENMASK(4, 0)
+#define CXLDEV_MBOX_CAP_BG_CMD_IRQ BIT(6)
+#define CXLDEV_MBOX_CAP_IRQ_MSGNUM_MASK GENMASK(10, 7)
#define CXLDEV_MBOX_CTRL_OFFSET 0x04
#define CXLDEV_MBOX_CTRL_DOORBELL BIT(0)
+#define CXLDEV_MBOX_CTRL_BG_CMD_IRQ BIT(2)
#define CXLDEV_MBOX_CMD_OFFSET 0x08
#define CXLDEV_MBOX_CMD_COMMAND_OPCODE_MASK GENMASK_ULL(15, 0)
#define CXLDEV_MBOX_CMD_PAYLOAD_LENGTH_MASK GENMASK_ULL(36, 16)
#define CXLDEV_MBOX_STATUS_OFFSET 0x10
+#define CXLDEV_MBOX_STATUS_BG_CMD BIT(0)
#define CXLDEV_MBOX_STATUS_RET_CODE_MASK GENMASK_ULL(47, 32)
#define CXLDEV_MBOX_BG_CMD_STATUS_OFFSET 0x18
+#define CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK GENMASK_ULL(15, 0)
+#define CXLDEV_MBOX_BG_CMD_COMMAND_PCT_MASK GENMASK_ULL(22, 16)
+#define CXLDEV_MBOX_BG_CMD_COMMAND_RC_MASK GENMASK_ULL(47, 32)
+#define CXLDEV_MBOX_BG_CMD_COMMAND_VENDOR_MASK GENMASK_ULL(63, 48)
#define CXLDEV_MBOX_PAYLOAD_OFFSET 0x20
/*
@@ -209,6 +217,10 @@ struct cxl_regs {
struct_group_tagged(cxl_device_regs, device_regs,
void __iomem *status, *mbox, *memdev;
);
+
+ struct_group_tagged(cxl_pmu_regs, pmu_regs,
+ void __iomem *pmu;
+ );
};
struct cxl_reg_map {
@@ -229,16 +241,23 @@ struct cxl_device_reg_map {
struct cxl_reg_map memdev;
};
+struct cxl_pmu_reg_map {
+ struct cxl_reg_map pmu;
+};
+
/**
* struct cxl_register_map - DVSEC harvested register block mapping parameters
+ * @dev: device for devm operations and logging
* @base: virtual base of the register-block-BAR + @block_offset
* @resource: physical resource base of the register block
* @max_size: maximum mapping size to perform register search
* @reg_type: see enum cxl_regloc_type
* @component_map: cxl_reg_map for component registers
* @device_map: cxl_reg_maps for device registers
+ * @pmu_map: cxl_reg_maps for CXL Performance Monitoring Units
*/
struct cxl_register_map {
+ struct device *dev;
void __iomem *base;
resource_size_t resource;
resource_size_t max_size;
@@ -246,6 +265,7 @@ struct cxl_register_map {
union {
struct cxl_component_reg_map component_map;
struct cxl_device_reg_map device_map;
+ struct cxl_pmu_reg_map pmu_map;
};
};
@@ -253,23 +273,24 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base,
struct cxl_component_reg_map *map);
void cxl_probe_device_regs(struct device *dev, void __iomem *base,
struct cxl_device_reg_map *map);
-int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs,
- struct cxl_register_map *map,
+int cxl_map_component_regs(const struct cxl_register_map *map,
+ struct cxl_component_regs *regs,
unsigned long map_mask);
-int cxl_map_device_regs(struct device *dev, struct cxl_device_regs *regs,
- struct cxl_register_map *map);
+int cxl_map_device_regs(const struct cxl_register_map *map,
+ struct cxl_device_regs *regs);
+int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs,
+ struct cxl_register_map *map);
enum cxl_regloc_type;
+int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type);
+int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type,
+ struct cxl_register_map *map, int index);
int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
struct cxl_register_map *map);
-
-enum cxl_rcrb {
- CXL_RCRB_DOWNSTREAM,
- CXL_RCRB_UPSTREAM,
-};
-resource_size_t cxl_rcrb_to_component(struct device *dev,
- resource_size_t rcrb,
- enum cxl_rcrb which);
+int cxl_setup_regs(struct cxl_register_map *map);
+struct cxl_dport;
+resource_size_t cxl_rcd_component_reg_phys(struct device *dev,
+ struct cxl_dport *dport);
#define CXL_RESOURCE_NONE ((resource_size_t) -1)
#define CXL_TARGET_STRLEN 20
@@ -290,8 +311,8 @@ resource_size_t cxl_rcrb_to_component(struct device *dev,
#define CXL_DECODER_F_MASK GENMASK(5, 0)
enum cxl_decoder_type {
- CXL_DECODER_ACCELERATOR = 2,
- CXL_DECODER_EXPANDER = 3,
+ CXL_DECODER_DEVMEM = 2,
+ CXL_DECODER_HOSTONLYMEM = 3,
};
/*
@@ -463,17 +484,19 @@ struct cxl_region_params {
};
/*
- * Flag whether this region needs to have its HPA span synchronized with
- * CPU cache state at region activation time.
- */
-#define CXL_REGION_F_INCOHERENT 0
-
-/*
* Indicate whether this region has been assembled by autodetection or
* userspace assembly. Prevent endpoint decoders outside of automatic
* detection from being added to the region.
*/
-#define CXL_REGION_F_AUTO 1
+#define CXL_REGION_F_AUTO 0
+
+/*
+ * Require that a committed region successfully complete a teardown once
+ * any of its associated decoders have been torn down. This maintains
+ * the commit state for the region since there are committed decoders,
+ * but blocks cxl_region_probe().
+ */
+#define CXL_REGION_F_NEEDS_RESET 1
/**
* struct cxl_region - CXL region
@@ -541,7 +564,7 @@ struct cxl_dax_region {
* downstream port devices to construct a CXL memory
* decode hierarchy.
* @dev: this port's device
- * @uport: PCI or platform device implementing the upstream port capability
+ * @uport_dev: PCI or platform device implementing the upstream port capability
* @host_bridge: Shortcut to the platform attach point for this port
* @id: id for port device-name
* @dports: cxl_dport instances referenced by decoders
@@ -549,6 +572,7 @@ struct cxl_dax_region {
* @regions: cxl_region_ref instances, regions mapped by this port
* @parent_dport: dport that points to this port in the parent
* @decoder_ida: allocator for decoder ids
+ * @comp_map: component register capability mappings
* @nr_dports: number of entries in @dports
* @hdm_end: track last allocated HDM decoder instance for allocation ordering
* @commit_end: cursor to track highest committed decoder for commit ordering
@@ -560,7 +584,7 @@ struct cxl_dax_region {
*/
struct cxl_port {
struct device dev;
- struct device *uport;
+ struct device *uport_dev;
struct device *host_bridge;
int id;
struct xarray dports;
@@ -568,6 +592,7 @@ struct cxl_port {
struct xarray regions;
struct cxl_dport *parent_dport;
struct ida decoder_ida;
+ struct cxl_register_map comp_map;
int nr_dports;
int hdm_end;
int commit_end;
@@ -587,20 +612,25 @@ cxl_find_dport_by_dev(struct cxl_port *port, const struct device *dport_dev)
return xa_load(&port->dports, (unsigned long)dport_dev);
}
+struct cxl_rcrb_info {
+ resource_size_t base;
+ u16 aer_cap;
+};
+
/**
* struct cxl_dport - CXL downstream port
- * @dport: PCI bridge or firmware device representing the downstream link
+ * @dport_dev: PCI bridge or firmware device representing the downstream link
+ * @comp_map: component register capability mappings
* @port_id: unique hardware identifier for dport in decoder target list
- * @component_reg_phys: downstream port component registers
- * @rcrb: base address for the Root Complex Register Block
+ * @rcrb: Data about the Root Complex Register Block layout
* @rch: Indicate whether this dport was enumerated in RCH or VH mode
* @port: reference to cxl_port that contains this downstream port
*/
struct cxl_dport {
- struct device *dport;
+ struct device *dport_dev;
+ struct cxl_register_map comp_map;
int port_id;
- resource_size_t component_reg_phys;
- resource_size_t rcrb;
+ struct cxl_rcrb_info rcrb;
bool rch;
struct cxl_port *port;
};
@@ -641,27 +671,30 @@ struct cxl_region_ref {
/*
* The platform firmware device hosting the root is also the top of the
* CXL port topology. All other CXL ports have another CXL port as their
- * parent and their ->uport / host device is out-of-line of the port
+ * parent and their ->uport_dev / host device is out-of-line of the port
* ancestry.
*/
static inline bool is_cxl_root(struct cxl_port *port)
{
- return port->uport == port->dev.parent;
+ return port->uport_dev == port->dev.parent;
}
bool is_cxl_port(const struct device *dev);
struct cxl_port *to_cxl_port(const struct device *dev);
struct pci_bus;
-int devm_cxl_register_pci_bus(struct device *host, struct device *uport,
+int devm_cxl_register_pci_bus(struct device *host, struct device *uport_dev,
struct pci_bus *bus);
struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port);
-struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport,
+struct cxl_port *devm_cxl_add_port(struct device *host,
+ struct device *uport_dev,
resource_size_t component_reg_phys,
struct cxl_dport *parent_dport);
struct cxl_port *find_cxl_root(struct cxl_port *port);
int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd);
void cxl_bus_rescan(void);
void cxl_bus_drain(void);
+struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev,
+ struct cxl_dport **dport);
struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd,
struct cxl_dport **dport);
bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd);
@@ -671,7 +704,6 @@ struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port,
resource_size_t component_reg_phys);
struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
struct device *dport_dev, int port_id,
- resource_size_t component_reg_phys,
resource_size_t rcrb);
struct cxl_decoder *to_cxl_decoder(struct device *dev);
@@ -710,7 +742,6 @@ struct cxl_endpoint_dvsec_info {
struct cxl_hdm;
struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port,
struct cxl_endpoint_dvsec_info *info);
-int devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm);
int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
struct cxl_endpoint_dvsec_info *info);
int devm_cxl_add_passthrough_decoder(struct cxl_port *port);
@@ -750,6 +781,7 @@ void cxl_driver_unregister(struct cxl_driver *cxl_drv);
#define CXL_DEVICE_REGION 6
#define CXL_DEVICE_PMEM_REGION 7
#define CXL_DEVICE_DAX_REGION 8
+#define CXL_DEVICE_PMU 9
#define MODULE_ALIAS_CXL(type) MODULE_ALIAS("cxl:t" __stringify(type) "*")
#define CXL_MODALIAS_FMT "cxl:t%d"
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index a2845a7a69d8..79e99c873ca2 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -5,6 +5,7 @@
#include <uapi/linux/cxl_mem.h>
#include <linux/cdev.h>
#include <linux/uuid.h>
+#include <linux/rcuwait.h>
#include "cxl.h"
/* CXL 2.0 8.2.8.5.1.1 Memory Device Status Register */
@@ -38,6 +39,7 @@
* @detach_work: active memdev lost a port in its ancestry
* @cxl_nvb: coordinate removal of @cxl_nvd if present
* @cxl_nvd: optional bridge to an nvdimm if the device supports pmem
+ * @endpoint: connection to the CXL port topology for this memory device
* @id: id number of this memdev instance.
* @depth: endpoint port depth
*/
@@ -48,6 +50,7 @@ struct cxl_memdev {
struct work_struct detach_work;
struct cxl_nvdimm_bridge *cxl_nvb;
struct cxl_nvdimm *cxl_nvd;
+ struct cxl_port *endpoint;
int id;
int depth;
};
@@ -72,16 +75,18 @@ cxled_to_memdev(struct cxl_endpoint_decoder *cxled)
{
struct cxl_port *port = to_cxl_port(cxled->cxld.dev.parent);
- return to_cxl_memdev(port->uport);
+ return to_cxl_memdev(port->uport_dev);
}
bool is_cxl_memdev(const struct device *dev);
static inline bool is_cxl_endpoint(struct cxl_port *port)
{
- return is_cxl_memdev(port->uport);
+ return is_cxl_memdev(port->uport_dev);
}
struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds);
+struct cxl_memdev_state;
+int cxl_memdev_setup_fw_upload(struct cxl_memdev_state *mds);
int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
resource_size_t base, resource_size_t len,
resource_size_t skipped);
@@ -108,6 +113,9 @@ static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port,
* variable sized output commands, it tells the exact number of bytes
* written.
* @min_out: (input) internal command output payload size validation
+ * @poll_count: (input) Number of timeouts to attempt.
+ * @poll_interval_ms: (input) Time between mailbox background command polling
+ * interval timeouts.
* @return_code: (output) Error code returned from hardware.
*
* This is the primary mechanism used to send commands to the hardware.
@@ -123,6 +131,8 @@ struct cxl_mbox_cmd {
size_t size_in;
size_t size_out;
size_t min_out;
+ int poll_count;
+ int poll_interval_ms;
u16 return_code;
};
@@ -195,7 +205,7 @@ static inline int cxl_mbox_cmd_rc2errno(struct cxl_mbox_cmd *mbox_cmd)
*/
#define CXL_CAPACITY_MULTIPLIER SZ_256M
-/**
+/*
* Event Interrupt Policy
*
* CXL rev 3.0 section 8.2.9.2.4; Table 8-52
@@ -215,8 +225,8 @@ struct cxl_event_interrupt_policy {
/**
* struct cxl_event_state - Event log driver state
*
- * @event_buf: Buffer to receive event data
- * @event_log_lock: Serialize event_buf and log use
+ * @buf: Buffer to receive event data
+ * @log_lock: Serialize event_buf and log use
*/
struct cxl_event_state {
struct cxl_get_event_payload *buf;
@@ -254,6 +264,115 @@ struct cxl_poison_state {
struct mutex lock; /* Protect reads of poison list */
};
+/*
+ * Get FW Info
+ * CXL rev 3.0 section 8.2.9.3.1; Table 8-56
+ */
+struct cxl_mbox_get_fw_info {
+ u8 num_slots;
+ u8 slot_info;
+ u8 activation_cap;
+ u8 reserved[13];
+ char slot_1_revision[16];
+ char slot_2_revision[16];
+ char slot_3_revision[16];
+ char slot_4_revision[16];
+} __packed;
+
+#define CXL_FW_INFO_SLOT_INFO_CUR_MASK GENMASK(2, 0)
+#define CXL_FW_INFO_SLOT_INFO_NEXT_MASK GENMASK(5, 3)
+#define CXL_FW_INFO_SLOT_INFO_NEXT_SHIFT 3
+#define CXL_FW_INFO_ACTIVATION_CAP_HAS_LIVE_ACTIVATE BIT(0)
+
+/*
+ * Transfer FW Input Payload
+ * CXL rev 3.0 section 8.2.9.3.2; Table 8-57
+ */
+struct cxl_mbox_transfer_fw {
+ u8 action;
+ u8 slot;
+ u8 reserved[2];
+ __le32 offset;
+ u8 reserved2[0x78];
+ u8 data[];
+} __packed;
+
+#define CXL_FW_TRANSFER_ACTION_FULL 0x0
+#define CXL_FW_TRANSFER_ACTION_INITIATE 0x1
+#define CXL_FW_TRANSFER_ACTION_CONTINUE 0x2
+#define CXL_FW_TRANSFER_ACTION_END 0x3
+#define CXL_FW_TRANSFER_ACTION_ABORT 0x4
+
+/*
+ * CXL rev 3.0 section 8.2.9.3.2 mandates 128-byte alignment for FW packages
+ * and for each part transferred in a Transfer FW command.
+ */
+#define CXL_FW_TRANSFER_ALIGNMENT 128
+
+/*
+ * Activate FW Input Payload
+ * CXL rev 3.0 section 8.2.9.3.3; Table 8-58
+ */
+struct cxl_mbox_activate_fw {
+ u8 action;
+ u8 slot;
+} __packed;
+
+#define CXL_FW_ACTIVATE_ONLINE 0x0
+#define CXL_FW_ACTIVATE_OFFLINE 0x1
+
+/* FW state bits */
+#define CXL_FW_STATE_BITS 32
+#define CXL_FW_CANCEL BIT(0)
+
+/**
+ * struct cxl_fw_state - Firmware upload / activation state
+ *
+ * @state: fw_uploader state bitmask
+ * @oneshot: whether the fw upload fits in a single transfer
+ * @num_slots: Number of FW slots available
+ * @cur_slot: Slot number currently active
+ * @next_slot: Slot number for the new firmware
+ */
+struct cxl_fw_state {
+ DECLARE_BITMAP(state, CXL_FW_STATE_BITS);
+ bool oneshot;
+ int num_slots;
+ int cur_slot;
+ int next_slot;
+};
+
+/**
+ * struct cxl_security_state - Device security state
+ *
+ * @state: state of last security operation
+ * @poll: polling for sanitization is enabled, device has no mbox irq support
+ * @poll_tmo_secs: polling timeout
+ * @poll_dwork: polling work item
+ * @sanitize_node: sanitation sysfs file to notify
+ */
+struct cxl_security_state {
+ unsigned long state;
+ bool poll;
+ int poll_tmo_secs;
+ struct delayed_work poll_dwork;
+ struct kernfs_node *sanitize_node;
+};
+
+/*
+ * enum cxl_devtype - delineate type-2 from a generic type-3 device
+ * @CXL_DEVTYPE_DEVMEM - Vendor specific CXL Type-2 device implementing HDM-D or
+ * HDM-DB, no requirement that this device implements a
+ * mailbox, or other memory-device-standard manageability
+ * flows.
+ * @CXL_DEVTYPE_CLASSMEM - Common class definition of a CXL Type-3 device with
+ * HDM-H and class-mandatory memory device registers
+ */
+enum cxl_devtype {
+ CXL_DEVTYPE_DEVMEM,
+ CXL_DEVTYPE_CLASSMEM,
+};
+
/**
* struct cxl_dev_state - The driver device state
*
@@ -267,6 +386,36 @@ struct cxl_poison_state {
* @cxl_dvsec: Offset to the PCIe device DVSEC
* @rcd: operating in RCD mode (CXL 3.0 9.11.8 CXL Devices Attached to an RCH)
* @media_ready: Indicate whether the device media is usable
+ * @dpa_res: Overall DPA resource tree for the device
+ * @pmem_res: Active Persistent memory capacity configuration
+ * @ram_res: Active Volatile memory capacity configuration
+ * @component_reg_phys: register base of component registers
+ * @serial: PCIe Device Serial Number
+ * @type: Generic Memory Class device or Vendor Specific Memory device
+ */
+struct cxl_dev_state {
+ struct device *dev;
+ struct cxl_memdev *cxlmd;
+ struct cxl_regs regs;
+ int cxl_dvsec;
+ bool rcd;
+ bool media_ready;
+ struct resource dpa_res;
+ struct resource pmem_res;
+ struct resource ram_res;
+ resource_size_t component_reg_phys;
+ u64 serial;
+ enum cxl_devtype type;
+};
+
+/**
+ * struct cxl_memdev_state - Generic Type-3 Memory Device Class driver data
+ *
+ * CXL 8.1.12.1 PCI Header - Class Code Register Memory Device defines
+ * common memory device functionality like the presence of a mailbox and
+ * the functionality related to that like Identify Memory Device and Get
+ * Partition Info
+ * @cxlds: Core driver state common across Type-2 and Type-3 devices
* @payload_size: Size of space for payload
* (CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register)
* @lsa_size: Size of Label Storage Area
@@ -275,9 +424,6 @@ struct cxl_poison_state {
* @firmware_version: Firmware version for the memory device.
* @enabled_cmds: Hardware commands found enabled in CEL.
* @exclusive_cmds: Commands that are kernel-internal only
- * @dpa_res: Overall DPA resource tree for the device
- * @pmem_res: Active Persistent memory capacity configuration
- * @ram_res: Active Volatile memory capacity configuration
* @total_bytes: sum of all possible capacities
* @volatile_only_bytes: hard volatile capacity
* @persistent_only_bytes: hard persistent capacity
@@ -286,54 +432,48 @@ struct cxl_poison_state {
* @active_persistent_bytes: sum of hard + soft persistent
* @next_volatile_bytes: volatile capacity change pending device reset
* @next_persistent_bytes: persistent capacity change pending device reset
- * @component_reg_phys: register base of component registers
- * @info: Cached DVSEC information about the device.
- * @serial: PCIe Device Serial Number
* @event: event log driver state
* @poison: poison driver state info
+ * @fw: firmware upload / activation state
* @mbox_send: @dev specific transport for transmitting mailbox commands
*
- * See section 8.2.9.5.2 Capacity Configuration and Label Storage for
+ * See CXL 3.0 8.2.9.8.2 Capacity Configuration and Label Storage for
* details on capacity parameters.
*/
-struct cxl_dev_state {
- struct device *dev;
- struct cxl_memdev *cxlmd;
-
- struct cxl_regs regs;
- int cxl_dvsec;
-
- bool rcd;
- bool media_ready;
+struct cxl_memdev_state {
+ struct cxl_dev_state cxlds;
size_t payload_size;
size_t lsa_size;
struct mutex mbox_mutex; /* Protects device mailbox and firmware */
char firmware_version[0x10];
DECLARE_BITMAP(enabled_cmds, CXL_MEM_COMMAND_ID_MAX);
DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX);
-
- struct resource dpa_res;
- struct resource pmem_res;
- struct resource ram_res;
u64 total_bytes;
u64 volatile_only_bytes;
u64 persistent_only_bytes;
u64 partition_align_bytes;
-
u64 active_volatile_bytes;
u64 active_persistent_bytes;
u64 next_volatile_bytes;
u64 next_persistent_bytes;
-
- resource_size_t component_reg_phys;
- u64 serial;
-
struct cxl_event_state event;
struct cxl_poison_state poison;
+ struct cxl_security_state security;
+ struct cxl_fw_state fw;
- int (*mbox_send)(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd);
+ struct rcuwait mbox_wait;
+ int (*mbox_send)(struct cxl_memdev_state *mds,
+ struct cxl_mbox_cmd *cmd);
};
+static inline struct cxl_memdev_state *
+to_cxl_memdev_state(struct cxl_dev_state *cxlds)
+{
+ if (cxlds->type != CXL_DEVTYPE_CLASSMEM)
+ return NULL;
+ return container_of(cxlds, struct cxl_memdev_state, cxlds);
+}
+
enum cxl_opcode {
CXL_MBOX_OP_INVALID = 0x0000,
CXL_MBOX_OP_RAW = CXL_MBOX_OP_INVALID,
@@ -342,6 +482,7 @@ enum cxl_opcode {
CXL_MBOX_OP_GET_EVT_INT_POLICY = 0x0102,
CXL_MBOX_OP_SET_EVT_INT_POLICY = 0x0103,
CXL_MBOX_OP_GET_FW_INFO = 0x0200,
+ CXL_MBOX_OP_TRANSFER_FW = 0x0201,
CXL_MBOX_OP_ACTIVATE_FW = 0x0202,
CXL_MBOX_OP_SET_TIMESTAMP = 0x0301,
CXL_MBOX_OP_GET_SUPPORTED_LOGS = 0x0400,
@@ -362,6 +503,8 @@ enum cxl_opcode {
CXL_MBOX_OP_GET_SCAN_MEDIA_CAPS = 0x4303,
CXL_MBOX_OP_SCAN_MEDIA = 0x4304,
CXL_MBOX_OP_GET_SCAN_MEDIA = 0x4305,
+ CXL_MBOX_OP_SANITIZE = 0x4400,
+ CXL_MBOX_OP_SECURE_ERASE = 0x4401,
CXL_MBOX_OP_GET_SECURITY_STATE = 0x4500,
CXL_MBOX_OP_SET_PASSPHRASE = 0x4501,
CXL_MBOX_OP_DISABLE_PASSPHRASE = 0x4502,
@@ -692,18 +835,20 @@ enum {
CXL_PMEM_SEC_PASS_USER,
};
-int cxl_internal_send_cmd(struct cxl_dev_state *cxlds,
+int cxl_internal_send_cmd(struct cxl_memdev_state *mds,
struct cxl_mbox_cmd *cmd);
-int cxl_dev_state_identify(struct cxl_dev_state *cxlds);
+int cxl_dev_state_identify(struct cxl_memdev_state *mds);
int cxl_await_media_ready(struct cxl_dev_state *cxlds);
-int cxl_enumerate_cmds(struct cxl_dev_state *cxlds);
-int cxl_mem_create_range_info(struct cxl_dev_state *cxlds);
-struct cxl_dev_state *cxl_dev_state_create(struct device *dev);
-void set_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds);
-void clear_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds);
-void cxl_mem_get_event_records(struct cxl_dev_state *cxlds, u32 status);
-int cxl_set_timestamp(struct cxl_dev_state *cxlds);
-int cxl_poison_state_init(struct cxl_dev_state *cxlds);
+int cxl_enumerate_cmds(struct cxl_memdev_state *mds);
+int cxl_mem_create_range_info(struct cxl_memdev_state *mds);
+struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev);
+void set_exclusive_cxl_commands(struct cxl_memdev_state *mds,
+ unsigned long *cmds);
+void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds,
+ unsigned long *cmds);
+void cxl_mem_get_event_records(struct cxl_memdev_state *mds, u32 status);
+int cxl_set_timestamp(struct cxl_memdev_state *mds);
+int cxl_poison_state_init(struct cxl_memdev_state *mds);
int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
struct cxl_region *cxlr);
int cxl_trigger_poison_list(struct cxl_memdev *cxlmd);
@@ -722,6 +867,8 @@ static inline void cxl_mem_active_dec(void)
}
#endif
+int cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd);
+
struct cxl_hdm {
struct cxl_component_regs regs;
unsigned int decoder_count;
diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
index 7c02e55b8042..0fa4799ea316 100644
--- a/drivers/cxl/cxlpci.h
+++ b/drivers/cxl/cxlpci.h
@@ -67,6 +67,7 @@ enum cxl_regloc_type {
CXL_REGLOC_RBI_COMPONENT,
CXL_REGLOC_RBI_VIRT,
CXL_REGLOC_RBI_MEMDEV,
+ CXL_REGLOC_RBI_PMU,
CXL_REGLOC_RBI_TYPES
};
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index 519edd0eb196..317c7548e4e9 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -51,7 +51,6 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
struct cxl_port *parent_port = parent_dport->port;
struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct cxl_port *endpoint, *iter, *down;
- resource_size_t component_reg_phys;
int rc;
/*
@@ -66,17 +65,8 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
ep->next = down;
}
- /*
- * The component registers for an RCD might come from the
- * host-bridge RCRB if they are not already mapped via the
- * typical register locator mechanism.
- */
- if (parent_dport->rch && cxlds->component_reg_phys == CXL_RESOURCE_NONE)
- component_reg_phys = cxl_rcrb_to_component(
- &cxlmd->dev, parent_dport->rcrb, CXL_RCRB_UPSTREAM);
- else
- component_reg_phys = cxlds->component_reg_phys;
- endpoint = devm_cxl_add_port(host, &cxlmd->dev, component_reg_phys,
+ endpoint = devm_cxl_add_port(host, &cxlmd->dev,
+ cxlds->component_reg_phys,
parent_dport);
if (IS_ERR(endpoint))
return PTR_ERR(endpoint);
@@ -117,6 +107,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(cxl_poison_clear_fops, NULL,
static int cxl_mem_probe(struct device *dev)
{
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct device *endpoint_parent;
struct cxl_port *parent_port;
@@ -141,10 +132,10 @@ static int cxl_mem_probe(struct device *dev)
dentry = cxl_debugfs_create_dir(dev_name(dev));
debugfs_create_devm_seqfile(dev, "dpamem", dentry, cxl_mem_dpa_show);
- if (test_bit(CXL_POISON_ENABLED_INJECT, cxlds->poison.enabled_cmds))
+ if (test_bit(CXL_POISON_ENABLED_INJECT, mds->poison.enabled_cmds))
debugfs_create_file("inject_poison", 0200, dentry, cxlmd,
&cxl_poison_inject_fops);
- if (test_bit(CXL_POISON_ENABLED_CLEAR, cxlds->poison.enabled_cmds))
+ if (test_bit(CXL_POISON_ENABLED_CLEAR, mds->poison.enabled_cmds))
debugfs_create_file("clear_poison", 0200, dentry, cxlmd,
&cxl_poison_clear_fops);
@@ -163,7 +154,7 @@ static int cxl_mem_probe(struct device *dev)
}
if (dport->rch)
- endpoint_parent = parent_port->uport;
+ endpoint_parent = parent_port->uport_dev;
else
endpoint_parent = &parent_port->dev;
@@ -227,9 +218,12 @@ static umode_t cxl_mem_visible(struct kobject *kobj, struct attribute *a, int n)
{
if (a == &dev_attr_trigger_poison_list.attr) {
struct device *dev = kobj_to_dev(kobj);
+ struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+ struct cxl_memdev_state *mds =
+ to_cxl_memdev_state(cxlmd->cxlds);
if (!test_bit(CXL_POISON_ENABLED_LIST,
- to_cxl_memdev(dev)->cxlds->poison.enabled_cmds))
+ mds->poison.enabled_cmds))
return 0;
}
return a->mode;
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index 0872f2233ed0..1cb1494c28fe 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -13,6 +13,7 @@
#include "cxlmem.h"
#include "cxlpci.h"
#include "cxl.h"
+#include "pmu.h"
/**
* DOC: cxl pci
@@ -84,9 +85,92 @@ static int cxl_pci_mbox_wait_for_doorbell(struct cxl_dev_state *cxlds)
status & CXLMDEV_DEV_FATAL ? " fatal" : "", \
status & CXLMDEV_FW_HALT ? " firmware-halt" : "")
+struct cxl_dev_id {
+ struct cxl_dev_state *cxlds;
+};
+
+static int cxl_request_irq(struct cxl_dev_state *cxlds, int irq,
+ irq_handler_t handler, irq_handler_t thread_fn)
+{
+ struct device *dev = cxlds->dev;
+ struct cxl_dev_id *dev_id;
+
+ /* dev_id must be globally unique and must contain the cxlds */
+ dev_id = devm_kzalloc(dev, sizeof(*dev_id), GFP_KERNEL);
+ if (!dev_id)
+ return -ENOMEM;
+ dev_id->cxlds = cxlds;
+
+ return devm_request_threaded_irq(dev, irq, handler, thread_fn,
+ IRQF_SHARED | IRQF_ONESHOT,
+ NULL, dev_id);
+}
+
+static bool cxl_mbox_background_complete(struct cxl_dev_state *cxlds)
+{
+ u64 reg;
+
+ reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET);
+ return FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_PCT_MASK, reg) == 100;
+}
+
+static irqreturn_t cxl_pci_mbox_irq(int irq, void *id)
+{
+ u64 reg;
+ u16 opcode;
+ struct cxl_dev_id *dev_id = id;
+ struct cxl_dev_state *cxlds = dev_id->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
+
+ if (!cxl_mbox_background_complete(cxlds))
+ return IRQ_NONE;
+
+ reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET);
+ opcode = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK, reg);
+ if (opcode == CXL_MBOX_OP_SANITIZE) {
+ if (mds->security.sanitize_node)
+ sysfs_notify_dirent(mds->security.sanitize_node);
+
+ dev_dbg(cxlds->dev, "Sanitization operation ended\n");
+ } else {
+ /* short-circuit the wait in __cxl_pci_mbox_send_cmd() */
+ rcuwait_wake_up(&mds->mbox_wait);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Sanitization operation polling mode.
+ */
+static void cxl_mbox_sanitize_work(struct work_struct *work)
+{
+ struct cxl_memdev_state *mds =
+ container_of(work, typeof(*mds), security.poll_dwork.work);
+ struct cxl_dev_state *cxlds = &mds->cxlds;
+
+ mutex_lock(&mds->mbox_mutex);
+ if (cxl_mbox_background_complete(cxlds)) {
+ mds->security.poll_tmo_secs = 0;
+ put_device(cxlds->dev);
+
+ if (mds->security.sanitize_node)
+ sysfs_notify_dirent(mds->security.sanitize_node);
+
+ dev_dbg(cxlds->dev, "Sanitization operation ended\n");
+ } else {
+ int timeout = mds->security.poll_tmo_secs + 10;
+
+ mds->security.poll_tmo_secs = min(15 * 60, timeout);
+ queue_delayed_work(system_wq, &mds->security.poll_dwork,
+ timeout * HZ);
+ }
+ mutex_unlock(&mds->mbox_mutex);
+}
+
/**
* __cxl_pci_mbox_send_cmd() - Execute a mailbox command
- * @cxlds: The device state to communicate with.
+ * @mds: The memory device driver data
* @mbox_cmd: Command to send to the memory device.
*
* Context: Any context. Expects mbox_mutex to be held.
@@ -106,16 +190,17 @@ static int cxl_pci_mbox_wait_for_doorbell(struct cxl_dev_state *cxlds)
* not need to coordinate with each other. The driver only uses the primary
* mailbox.
*/
-static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds,
+static int __cxl_pci_mbox_send_cmd(struct cxl_memdev_state *mds,
struct cxl_mbox_cmd *mbox_cmd)
{
+ struct cxl_dev_state *cxlds = &mds->cxlds;
void __iomem *payload = cxlds->regs.mbox + CXLDEV_MBOX_PAYLOAD_OFFSET;
struct device *dev = cxlds->dev;
u64 cmd_reg, status_reg;
size_t out_len;
int rc;
- lockdep_assert_held(&cxlds->mbox_mutex);
+ lockdep_assert_held(&mds->mbox_mutex);
/*
* Here are the steps from 8.2.8.4 of the CXL 2.0 spec.
@@ -144,6 +229,16 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds,
return -EBUSY;
}
+ /*
+ * With sanitize polling, hardware might be done and the poller still
+ * not be in sync. Ensure no new command comes in until so. Keep the
+ * hardware semantics and only allow device health status.
+ */
+ if (mds->security.poll_tmo_secs > 0) {
+ if (mbox_cmd->opcode != CXL_MBOX_OP_GET_HEALTH_INFO)
+ return -EBUSY;
+ }
+
cmd_reg = FIELD_PREP(CXLDEV_MBOX_CMD_COMMAND_OPCODE_MASK,
mbox_cmd->opcode);
if (mbox_cmd->size_in) {
@@ -177,12 +272,80 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds,
mbox_cmd->return_code =
FIELD_GET(CXLDEV_MBOX_STATUS_RET_CODE_MASK, status_reg);
+ /*
+ * Handle the background command in a synchronous manner.
+ *
+ * All other mailbox commands will serialize/queue on the mbox_mutex,
+ * which we currently hold. Furthermore this also guarantees that
+ * cxl_mbox_background_complete() checks are safe amongst each other,
+ * in that no new bg operation can occur in between.
+ *
+ * Background operations are timesliced in accordance with the nature
+ * of the command. In the event of timeout, the mailbox state is
+ * indeterminate until the next successful command submission and the
+ * driver can get back in sync with the hardware state.
+ */
+ if (mbox_cmd->return_code == CXL_MBOX_CMD_RC_BACKGROUND) {
+ u64 bg_status_reg;
+ int i, timeout;
+
+ /*
+ * Sanitization is a special case which monopolizes the device
+ * and cannot be timesliced. Handle asynchronously instead,
+ * and allow userspace to poll(2) for completion.
+ */
+ if (mbox_cmd->opcode == CXL_MBOX_OP_SANITIZE) {
+ if (mds->security.poll) {
+ /* hold the device throughout */
+ get_device(cxlds->dev);
+
+ /* give first timeout a second */
+ timeout = 1;
+ mds->security.poll_tmo_secs = timeout;
+ queue_delayed_work(system_wq,
+ &mds->security.poll_dwork,
+ timeout * HZ);
+ }
+
+ dev_dbg(dev, "Sanitization operation started\n");
+ goto success;
+ }
+
+ dev_dbg(dev, "Mailbox background operation (0x%04x) started\n",
+ mbox_cmd->opcode);
+
+ timeout = mbox_cmd->poll_interval_ms;
+ for (i = 0; i < mbox_cmd->poll_count; i++) {
+ if (rcuwait_wait_event_timeout(&mds->mbox_wait,
+ cxl_mbox_background_complete(cxlds),
+ TASK_UNINTERRUPTIBLE,
+ msecs_to_jiffies(timeout)) > 0)
+ break;
+ }
+
+ if (!cxl_mbox_background_complete(cxlds)) {
+ dev_err(dev, "timeout waiting for background (%d ms)\n",
+ timeout * mbox_cmd->poll_count);
+ return -ETIMEDOUT;
+ }
+
+ bg_status_reg = readq(cxlds->regs.mbox +
+ CXLDEV_MBOX_BG_CMD_STATUS_OFFSET);
+ mbox_cmd->return_code =
+ FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_RC_MASK,
+ bg_status_reg);
+ dev_dbg(dev,
+ "Mailbox background operation (0x%04x) completed\n",
+ mbox_cmd->opcode);
+ }
+
if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS) {
dev_dbg(dev, "Mailbox operation had an error: %s\n",
cxl_mbox_cmd_rc2str(mbox_cmd));
return 0; /* completed but caller must check return_code */
}
+success:
/* #7 */
cmd_reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_CMD_OFFSET);
out_len = FIELD_GET(CXLDEV_MBOX_CMD_PAYLOAD_LENGTH_MASK, cmd_reg);
@@ -196,8 +359,9 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds,
* have requested less data than the hardware supplied even
* within spec.
*/
- size_t n = min3(mbox_cmd->size_out, cxlds->payload_size, out_len);
+ size_t n;
+ n = min3(mbox_cmd->size_out, mds->payload_size, out_len);
memcpy_fromio(mbox_cmd->payload_out, payload, n);
mbox_cmd->size_out = n;
} else {
@@ -207,20 +371,23 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds,
return 0;
}
-static int cxl_pci_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
+static int cxl_pci_mbox_send(struct cxl_memdev_state *mds,
+ struct cxl_mbox_cmd *cmd)
{
int rc;
- mutex_lock_io(&cxlds->mbox_mutex);
- rc = __cxl_pci_mbox_send_cmd(cxlds, cmd);
- mutex_unlock(&cxlds->mbox_mutex);
+ mutex_lock_io(&mds->mbox_mutex);
+ rc = __cxl_pci_mbox_send_cmd(mds, cmd);
+ mutex_unlock(&mds->mbox_mutex);
return rc;
}
-static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds)
+static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds)
{
+ struct cxl_dev_state *cxlds = &mds->cxlds;
const int cap = readl(cxlds->regs.mbox + CXLDEV_MBOX_CAPS_OFFSET);
+ struct device *dev = cxlds->dev;
unsigned long timeout;
u64 md_status;
@@ -234,8 +401,7 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds)
} while (!time_after(jiffies, timeout));
if (!(md_status & CXLMDEV_MBOX_IF_READY)) {
- cxl_err(cxlds->dev, md_status,
- "timeout awaiting mailbox ready");
+ cxl_err(dev, md_status, "timeout awaiting mailbox ready");
return -ETIMEDOUT;
}
@@ -246,12 +412,12 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds)
* source for future doorbell busy events.
*/
if (cxl_pci_mbox_wait_for_doorbell(cxlds) != 0) {
- cxl_err(cxlds->dev, md_status, "timeout awaiting mailbox idle");
+ cxl_err(dev, md_status, "timeout awaiting mailbox idle");
return -ETIMEDOUT;
}
- cxlds->mbox_send = cxl_pci_mbox_send;
- cxlds->payload_size =
+ mds->mbox_send = cxl_pci_mbox_send;
+ mds->payload_size =
1 << FIELD_GET(CXLDEV_MBOX_CAP_PAYLOAD_SIZE_MASK, cap);
/*
@@ -261,121 +427,104 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds)
* there's no point in going forward. If the size is too large, there's
* no harm is soft limiting it.
*/
- cxlds->payload_size = min_t(size_t, cxlds->payload_size, SZ_1M);
- if (cxlds->payload_size < 256) {
- dev_err(cxlds->dev, "Mailbox is too small (%zub)",
- cxlds->payload_size);
+ mds->payload_size = min_t(size_t, mds->payload_size, SZ_1M);
+ if (mds->payload_size < 256) {
+ dev_err(dev, "Mailbox is too small (%zub)",
+ mds->payload_size);
return -ENXIO;
}
- dev_dbg(cxlds->dev, "Mailbox payload sized %zu",
- cxlds->payload_size);
+ dev_dbg(dev, "Mailbox payload sized %zu", mds->payload_size);
- return 0;
-}
+ rcuwait_init(&mds->mbox_wait);
-static int cxl_map_regblock(struct pci_dev *pdev, struct cxl_register_map *map)
-{
- struct device *dev = &pdev->dev;
+ if (cap & CXLDEV_MBOX_CAP_BG_CMD_IRQ) {
+ u32 ctrl;
+ int irq, msgnum;
+ struct pci_dev *pdev = to_pci_dev(cxlds->dev);
- map->base = ioremap(map->resource, map->max_size);
- if (!map->base) {
- dev_err(dev, "failed to map registers\n");
- return -ENOMEM;
+ msgnum = FIELD_GET(CXLDEV_MBOX_CAP_IRQ_MSGNUM_MASK, cap);
+ irq = pci_irq_vector(pdev, msgnum);
+ if (irq < 0)
+ goto mbox_poll;
+
+ if (cxl_request_irq(cxlds, irq, cxl_pci_mbox_irq, NULL))
+ goto mbox_poll;
+
+ /* enable background command mbox irq support */
+ ctrl = readl(cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET);
+ ctrl |= CXLDEV_MBOX_CTRL_BG_CMD_IRQ;
+ writel(ctrl, cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET);
+
+ return 0;
}
- dev_dbg(dev, "Mapped CXL Memory Device resource %pa\n", &map->resource);
+mbox_poll:
+ mds->security.poll = true;
+ INIT_DELAYED_WORK(&mds->security.poll_dwork, cxl_mbox_sanitize_work);
+
+ dev_dbg(cxlds->dev, "Mailbox interrupts are unsupported");
return 0;
}
-static void cxl_unmap_regblock(struct pci_dev *pdev,
- struct cxl_register_map *map)
+/*
+ * Assume that any RCIEP that emits the CXL memory expander class code
+ * is an RCD
+ */
+static bool is_cxl_restricted(struct pci_dev *pdev)
{
- iounmap(map->base);
- map->base = NULL;
+ return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END;
}
-static int cxl_probe_regs(struct pci_dev *pdev, struct cxl_register_map *map)
+static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
+ struct cxl_register_map *map)
{
- struct cxl_component_reg_map *comp_map;
- struct cxl_device_reg_map *dev_map;
- struct device *dev = &pdev->dev;
- void __iomem *base = map->base;
-
- switch (map->reg_type) {
- case CXL_REGLOC_RBI_COMPONENT:
- comp_map = &map->component_map;
- cxl_probe_component_regs(dev, base, comp_map);
- if (!comp_map->hdm_decoder.valid) {
- dev_err(dev, "HDM decoder registers not found\n");
- return -ENXIO;
- }
+ struct cxl_port *port;
+ struct cxl_dport *dport;
+ resource_size_t component_reg_phys;
- if (!comp_map->ras.valid)
- dev_dbg(dev, "RAS registers not found\n");
-
- dev_dbg(dev, "Set up component registers\n");
- break;
- case CXL_REGLOC_RBI_MEMDEV:
- dev_map = &map->device_map;
- cxl_probe_device_regs(dev, base, dev_map);
- if (!dev_map->status.valid || !dev_map->mbox.valid ||
- !dev_map->memdev.valid) {
- dev_err(dev, "registers not found: %s%s%s\n",
- !dev_map->status.valid ? "status " : "",
- !dev_map->mbox.valid ? "mbox " : "",
- !dev_map->memdev.valid ? "memdev " : "");
- return -ENXIO;
- }
+ *map = (struct cxl_register_map) {
+ .dev = &pdev->dev,
+ .resource = CXL_RESOURCE_NONE,
+ };
- dev_dbg(dev, "Probing device registers...\n");
- break;
- default:
- break;
- }
+ port = cxl_pci_find_port(pdev, &dport);
+ if (!port)
+ return -EPROBE_DEFER;
+
+ component_reg_phys = cxl_rcd_component_reg_phys(&pdev->dev, dport);
+
+ put_device(&port->dev);
+
+ if (component_reg_phys == CXL_RESOURCE_NONE)
+ return -ENXIO;
+
+ map->resource = component_reg_phys;
+ map->reg_type = CXL_REGLOC_RBI_COMPONENT;
+ map->max_size = CXL_COMPONENT_REG_BLOCK_SIZE;
return 0;
}
-static int cxl_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
- struct cxl_register_map *map)
+static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
+ struct cxl_register_map *map)
{
int rc;
rc = cxl_find_regblock(pdev, type, map);
- if (rc)
- return rc;
- rc = cxl_map_regblock(pdev, map);
+ /*
+ * If the Register Locator DVSEC does not exist, check if it
+ * is an RCH and try to extract the Component Registers from
+ * an RCRB.
+ */
+ if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev))
+ rc = cxl_rcrb_get_comp_regs(pdev, map);
+
if (rc)
return rc;
- rc = cxl_probe_regs(pdev, map);
- cxl_unmap_regblock(pdev, map);
-
- return rc;
-}
-
-/*
- * Assume that any RCIEP that emits the CXL memory expander class code
- * is an RCD
- */
-static bool is_cxl_restricted(struct pci_dev *pdev)
-{
- return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END;
-}
-
-/*
- * CXL v3.0 6.2.3 Table 6-4
- * The table indicates that if PCIe Flit Mode is set, then CXL is in 256B flits
- * mode, otherwise it's 68B flits mode.
- */
-static bool cxl_pci_flit_256(struct pci_dev *pdev)
-{
- u16 lnksta2;
-
- pcie_capability_read_word(pdev, PCI_EXP_LNKSTA2, &lnksta2);
- return lnksta2 & PCI_EXP_LNKSTA2_FLIT;
+ return cxl_setup_regs(map);
}
static int cxl_pci_ras_unmask(struct pci_dev *pdev)
@@ -404,9 +553,8 @@ static int cxl_pci_ras_unmask(struct pci_dev *pdev)
addr = cxlds->regs.ras + CXL_RAS_UNCORRECTABLE_MASK_OFFSET;
orig_val = readl(addr);
- mask = CXL_RAS_UNCORRECTABLE_MASK_MASK;
- if (!cxl_pci_flit_256(pdev))
- mask &= ~CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK;
+ mask = CXL_RAS_UNCORRECTABLE_MASK_MASK |
+ CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK;
val = orig_val & ~mask;
writel(val, addr);
dev_dbg(&pdev->dev,
@@ -433,18 +581,18 @@ static void free_event_buf(void *buf)
/*
* There is a single buffer for reading event logs from the mailbox. All logs
- * share this buffer protected by the cxlds->event_log_lock.
+ * share this buffer protected by the mds->event_log_lock.
*/
-static int cxl_mem_alloc_event_buf(struct cxl_dev_state *cxlds)
+static int cxl_mem_alloc_event_buf(struct cxl_memdev_state *mds)
{
struct cxl_get_event_payload *buf;
- buf = kvmalloc(cxlds->payload_size, GFP_KERNEL);
+ buf = kvmalloc(mds->payload_size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- cxlds->event.buf = buf;
+ mds->event.buf = buf;
- return devm_add_action_or_reset(cxlds->dev, free_event_buf, buf);
+ return devm_add_action_or_reset(mds->cxlds.dev, free_event_buf, buf);
}
static int cxl_alloc_irq_vectors(struct pci_dev *pdev)
@@ -469,14 +617,11 @@ static int cxl_alloc_irq_vectors(struct pci_dev *pdev)
return 0;
}
-struct cxl_dev_id {
- struct cxl_dev_state *cxlds;
-};
-
static irqreturn_t cxl_event_thread(int irq, void *id)
{
struct cxl_dev_id *dev_id = id;
struct cxl_dev_state *cxlds = dev_id->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
u32 status;
do {
@@ -489,7 +634,7 @@ static irqreturn_t cxl_event_thread(int irq, void *id)
status &= CXLDEV_EVENT_STATUS_ALL;
if (!status)
break;
- cxl_mem_get_event_records(cxlds, status);
+ cxl_mem_get_event_records(mds, status);
cond_resched();
} while (status);
@@ -498,31 +643,21 @@ static irqreturn_t cxl_event_thread(int irq, void *id)
static int cxl_event_req_irq(struct cxl_dev_state *cxlds, u8 setting)
{
- struct device *dev = cxlds->dev;
- struct pci_dev *pdev = to_pci_dev(dev);
- struct cxl_dev_id *dev_id;
+ struct pci_dev *pdev = to_pci_dev(cxlds->dev);
int irq;
if (FIELD_GET(CXLDEV_EVENT_INT_MODE_MASK, setting) != CXL_INT_MSI_MSIX)
return -ENXIO;
- /* dev_id must be globally unique and must contain the cxlds */
- dev_id = devm_kzalloc(dev, sizeof(*dev_id), GFP_KERNEL);
- if (!dev_id)
- return -ENOMEM;
- dev_id->cxlds = cxlds;
-
irq = pci_irq_vector(pdev,
FIELD_GET(CXLDEV_EVENT_INT_MSGNUM_MASK, setting));
if (irq < 0)
return irq;
- return devm_request_threaded_irq(dev, irq, NULL, cxl_event_thread,
- IRQF_SHARED | IRQF_ONESHOT, NULL,
- dev_id);
+ return cxl_request_irq(cxlds, irq, NULL, cxl_event_thread);
}
-static int cxl_event_get_int_policy(struct cxl_dev_state *cxlds,
+static int cxl_event_get_int_policy(struct cxl_memdev_state *mds,
struct cxl_event_interrupt_policy *policy)
{
struct cxl_mbox_cmd mbox_cmd = {
@@ -532,15 +667,15 @@ static int cxl_event_get_int_policy(struct cxl_dev_state *cxlds,
};
int rc;
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc < 0)
- dev_err(cxlds->dev, "Failed to get event interrupt policy : %d",
- rc);
+ dev_err(mds->cxlds.dev,
+ "Failed to get event interrupt policy : %d", rc);
return rc;
}
-static int cxl_event_config_msgnums(struct cxl_dev_state *cxlds,
+static int cxl_event_config_msgnums(struct cxl_memdev_state *mds,
struct cxl_event_interrupt_policy *policy)
{
struct cxl_mbox_cmd mbox_cmd;
@@ -559,23 +694,24 @@ static int cxl_event_config_msgnums(struct cxl_dev_state *cxlds,
.size_in = sizeof(*policy),
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc < 0) {
- dev_err(cxlds->dev, "Failed to set event interrupt policy : %d",
+ dev_err(mds->cxlds.dev, "Failed to set event interrupt policy : %d",
rc);
return rc;
}
/* Retrieve final interrupt settings */
- return cxl_event_get_int_policy(cxlds, policy);
+ return cxl_event_get_int_policy(mds, policy);
}
-static int cxl_event_irqsetup(struct cxl_dev_state *cxlds)
+static int cxl_event_irqsetup(struct cxl_memdev_state *mds)
{
+ struct cxl_dev_state *cxlds = &mds->cxlds;
struct cxl_event_interrupt_policy policy;
int rc;
- rc = cxl_event_config_msgnums(cxlds, &policy);
+ rc = cxl_event_config_msgnums(mds, &policy);
if (rc)
return rc;
@@ -614,7 +750,7 @@ static bool cxl_event_int_is_fw(u8 setting)
}
static int cxl_event_config(struct pci_host_bridge *host_bridge,
- struct cxl_dev_state *cxlds)
+ struct cxl_memdev_state *mds)
{
struct cxl_event_interrupt_policy policy;
int rc;
@@ -626,11 +762,11 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge,
if (!host_bridge->native_cxl_error)
return 0;
- rc = cxl_mem_alloc_event_buf(cxlds);
+ rc = cxl_mem_alloc_event_buf(mds);
if (rc)
return rc;
- rc = cxl_event_get_int_policy(cxlds, &policy);
+ rc = cxl_event_get_int_policy(mds, &policy);
if (rc)
return rc;
@@ -638,15 +774,16 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge,
cxl_event_int_is_fw(policy.warn_settings) ||
cxl_event_int_is_fw(policy.failure_settings) ||
cxl_event_int_is_fw(policy.fatal_settings)) {
- dev_err(cxlds->dev, "FW still in control of Event Logs despite _OSC settings\n");
+ dev_err(mds->cxlds.dev,
+ "FW still in control of Event Logs despite _OSC settings\n");
return -EBUSY;
}
- rc = cxl_event_irqsetup(cxlds);
+ rc = cxl_event_irqsetup(mds);
if (rc)
return rc;
- cxl_mem_get_event_records(cxlds, CXLDEV_EVENT_STATUS_ALL);
+ cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL);
return 0;
}
@@ -654,10 +791,11 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge,
static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct pci_host_bridge *host_bridge = pci_find_host_bridge(pdev->bus);
+ struct cxl_memdev_state *mds;
+ struct cxl_dev_state *cxlds;
struct cxl_register_map map;
struct cxl_memdev *cxlmd;
- struct cxl_dev_state *cxlds;
- int rc;
+ int i, rc, pmu_count;
/*
* Double check the anonymous union trickery in struct cxl_regs
@@ -671,9 +809,10 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return rc;
pci_set_master(pdev);
- cxlds = cxl_dev_state_create(&pdev->dev);
- if (IS_ERR(cxlds))
- return PTR_ERR(cxlds);
+ mds = cxl_memdev_state_create(&pdev->dev);
+ if (IS_ERR(mds))
+ return PTR_ERR(mds);
+ cxlds = &mds->cxlds;
pci_set_drvdata(pdev, cxlds);
cxlds->rcd = is_cxl_restricted(pdev);
@@ -684,11 +823,11 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev_warn(&pdev->dev,
"Device DVSEC not present, skip CXL.mem init\n");
- rc = cxl_setup_regs(pdev, CXL_REGLOC_RBI_MEMDEV, &map);
+ rc = cxl_pci_setup_regs(pdev, CXL_REGLOC_RBI_MEMDEV, &map);
if (rc)
return rc;
- rc = cxl_map_device_regs(&pdev->dev, &cxlds->regs.device_regs, &map);
+ rc = cxl_map_device_regs(&map, &cxlds->regs.device_regs);
if (rc)
return rc;
@@ -697,14 +836,16 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* still be useful for management functions so don't return an error.
*/
cxlds->component_reg_phys = CXL_RESOURCE_NONE;
- rc = cxl_setup_regs(pdev, CXL_REGLOC_RBI_COMPONENT, &map);
+ rc = cxl_pci_setup_regs(pdev, CXL_REGLOC_RBI_COMPONENT, &map);
if (rc)
dev_warn(&pdev->dev, "No component registers (%d)\n", rc);
+ else if (!map.component_map.ras.valid)
+ dev_dbg(&pdev->dev, "RAS registers not found\n");
cxlds->component_reg_phys = map.resource;
- rc = cxl_map_component_regs(&pdev->dev, &cxlds->regs.component,
- &map, BIT(CXL_CM_CAP_CAP_ID_RAS));
+ rc = cxl_map_component_regs(&map, &cxlds->regs.component,
+ BIT(CXL_CM_CAP_CAP_ID_RAS));
if (rc)
dev_dbg(&pdev->dev, "Failed to map RAS capability.\n");
@@ -714,31 +855,31 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
else
dev_warn(&pdev->dev, "Media not active (%d)\n", rc);
- rc = cxl_pci_setup_mailbox(cxlds);
+ rc = cxl_alloc_irq_vectors(pdev);
if (rc)
return rc;
- rc = cxl_enumerate_cmds(cxlds);
+ rc = cxl_pci_setup_mailbox(mds);
if (rc)
return rc;
- rc = cxl_set_timestamp(cxlds);
+ rc = cxl_enumerate_cmds(mds);
if (rc)
return rc;
- rc = cxl_poison_state_init(cxlds);
+ rc = cxl_set_timestamp(mds);
if (rc)
return rc;
- rc = cxl_dev_state_identify(cxlds);
+ rc = cxl_poison_state_init(mds);
if (rc)
return rc;
- rc = cxl_mem_create_range_info(cxlds);
+ rc = cxl_dev_state_identify(mds);
if (rc)
return rc;
- rc = cxl_alloc_irq_vectors(pdev);
+ rc = cxl_mem_create_range_info(mds);
if (rc)
return rc;
@@ -746,7 +887,34 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (IS_ERR(cxlmd))
return PTR_ERR(cxlmd);
- rc = cxl_event_config(host_bridge, cxlds);
+ rc = cxl_memdev_setup_fw_upload(mds);
+ if (rc)
+ return rc;
+
+ pmu_count = cxl_count_regblock(pdev, CXL_REGLOC_RBI_PMU);
+ for (i = 0; i < pmu_count; i++) {
+ struct cxl_pmu_regs pmu_regs;
+
+ rc = cxl_find_regblock_instance(pdev, CXL_REGLOC_RBI_PMU, &map, i);
+ if (rc) {
+ dev_dbg(&pdev->dev, "Could not find PMU regblock\n");
+ break;
+ }
+
+ rc = cxl_map_pmu_regs(pdev, &pmu_regs, &map);
+ if (rc) {
+ dev_dbg(&pdev->dev, "Could not map PMU regs\n");
+ break;
+ }
+
+ rc = devm_cxl_pmu_add(cxlds->dev, &pmu_regs, cxlmd->id, i, CXL_PMU_MEMDEV);
+ if (rc) {
+ dev_dbg(&pdev->dev, "Could not add PMU instance\n");
+ break;
+ }
+ }
+
+ rc = cxl_event_config(host_bridge, mds);
if (rc)
return rc;
diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c
index 71cfa1fdf902..7cb8994f8809 100644
--- a/drivers/cxl/pmem.c
+++ b/drivers/cxl/pmem.c
@@ -15,9 +15,9 @@ extern const struct nvdimm_security_ops *cxl_security_ops;
static __read_mostly DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX);
-static void clear_exclusive(void *cxlds)
+static void clear_exclusive(void *mds)
{
- clear_exclusive_cxl_commands(cxlds, exclusive_cmds);
+ clear_exclusive_cxl_commands(mds, exclusive_cmds);
}
static void unregister_nvdimm(void *nvdimm)
@@ -65,13 +65,13 @@ static int cxl_nvdimm_probe(struct device *dev)
struct cxl_nvdimm *cxl_nvd = to_cxl_nvdimm(dev);
struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
unsigned long flags = 0, cmd_mask = 0;
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct nvdimm *nvdimm;
int rc;
- set_exclusive_cxl_commands(cxlds, exclusive_cmds);
- rc = devm_add_action_or_reset(dev, clear_exclusive, cxlds);
+ set_exclusive_cxl_commands(mds, exclusive_cmds);
+ rc = devm_add_action_or_reset(dev, clear_exclusive, mds);
if (rc)
return rc;
@@ -100,22 +100,23 @@ static struct cxl_driver cxl_nvdimm_driver = {
},
};
-static int cxl_pmem_get_config_size(struct cxl_dev_state *cxlds,
+static int cxl_pmem_get_config_size(struct cxl_memdev_state *mds,
struct nd_cmd_get_config_size *cmd,
unsigned int buf_len)
{
if (sizeof(*cmd) > buf_len)
return -EINVAL;
- *cmd = (struct nd_cmd_get_config_size) {
- .config_size = cxlds->lsa_size,
- .max_xfer = cxlds->payload_size - sizeof(struct cxl_mbox_set_lsa),
+ *cmd = (struct nd_cmd_get_config_size){
+ .config_size = mds->lsa_size,
+ .max_xfer =
+ mds->payload_size - sizeof(struct cxl_mbox_set_lsa),
};
return 0;
}
-static int cxl_pmem_get_config_data(struct cxl_dev_state *cxlds,
+static int cxl_pmem_get_config_data(struct cxl_memdev_state *mds,
struct nd_cmd_get_config_data_hdr *cmd,
unsigned int buf_len)
{
@@ -140,13 +141,13 @@ static int cxl_pmem_get_config_data(struct cxl_dev_state *cxlds,
.payload_out = cmd->out_buf,
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
cmd->status = 0;
return rc;
}
-static int cxl_pmem_set_config_data(struct cxl_dev_state *cxlds,
+static int cxl_pmem_set_config_data(struct cxl_memdev_state *mds,
struct nd_cmd_set_config_hdr *cmd,
unsigned int buf_len)
{
@@ -176,7 +177,7 @@ static int cxl_pmem_set_config_data(struct cxl_dev_state *cxlds,
.size_in = struct_size(set_lsa, data, cmd->in_length),
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
/*
* Set "firmware" status (4-packed bytes at the end of the input
@@ -194,18 +195,18 @@ static int cxl_pmem_nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd,
struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
unsigned long cmd_mask = nvdimm_cmd_mask(nvdimm);
struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
if (!test_bit(cmd, &cmd_mask))
return -ENOTTY;
switch (cmd) {
case ND_CMD_GET_CONFIG_SIZE:
- return cxl_pmem_get_config_size(cxlds, buf, buf_len);
+ return cxl_pmem_get_config_size(mds, buf, buf_len);
case ND_CMD_GET_CONFIG_DATA:
- return cxl_pmem_get_config_data(cxlds, buf, buf_len);
+ return cxl_pmem_get_config_data(mds, buf, buf_len);
case ND_CMD_SET_CONFIG_DATA:
- return cxl_pmem_set_config_data(cxlds, buf, buf_len);
+ return cxl_pmem_set_config_data(mds, buf, buf_len);
default:
return -ENOTTY;
}
diff --git a/drivers/cxl/pmu.h b/drivers/cxl/pmu.h
new file mode 100644
index 000000000000..b1e9bcd9f28c
--- /dev/null
+++ b/drivers/cxl/pmu.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright(c) 2023 Huawei
+ * CXL Specification rev 3.0 Setion 8.2.7 (CPMU Register Interface)
+ */
+#ifndef CXL_PMU_H
+#define CXL_PMU_H
+#include <linux/device.h>
+
+enum cxl_pmu_type {
+ CXL_PMU_MEMDEV,
+};
+
+#define CXL_PMU_REGMAP_SIZE 0xe00 /* Table 8-32 CXL 3.0 specification */
+struct cxl_pmu {
+ struct device dev;
+ void __iomem *base;
+ int assoc_id;
+ int index;
+ enum cxl_pmu_type type;
+};
+
+#define to_cxl_pmu(dev) container_of(dev, struct cxl_pmu, dev)
+struct cxl_pmu_regs;
+int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs,
+ int assoc_id, int idx, enum cxl_pmu_type type);
+
+#endif
diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c
index c23b6164e1c0..6240e05b9542 100644
--- a/drivers/cxl/port.c
+++ b/drivers/cxl/port.c
@@ -60,17 +60,13 @@ static int discover_region(struct device *dev, void *root)
static int cxl_switch_port_probe(struct cxl_port *port)
{
struct cxl_hdm *cxlhdm;
- int rc, nr_dports;
-
- nr_dports = devm_cxl_port_enumerate_dports(port);
- if (nr_dports < 0)
- return nr_dports;
+ int rc;
- cxlhdm = devm_cxl_setup_hdm(port, NULL);
- rc = devm_cxl_enable_hdm(port, cxlhdm);
- if (rc)
+ rc = devm_cxl_port_enumerate_dports(port);
+ if (rc < 0)
return rc;
+ cxlhdm = devm_cxl_setup_hdm(port, NULL);
if (!IS_ERR(cxlhdm))
return devm_cxl_enumerate_decoders(cxlhdm, NULL);
@@ -79,7 +75,7 @@ static int cxl_switch_port_probe(struct cxl_port *port)
return PTR_ERR(cxlhdm);
}
- if (nr_dports == 1) {
+ if (rc == 1) {
dev_dbg(&port->dev, "Fallback to passthrough decoder\n");
return devm_cxl_add_passthrough_decoder(port);
}
@@ -91,7 +87,7 @@ static int cxl_switch_port_probe(struct cxl_port *port)
static int cxl_endpoint_port_probe(struct cxl_port *port)
{
struct cxl_endpoint_dvsec_info info = { .port = port };
- struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport);
+ struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct cxl_hdm *cxlhdm;
struct cxl_port *root;
@@ -102,8 +98,11 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
return rc;
cxlhdm = devm_cxl_setup_hdm(port, &info);
- if (IS_ERR(cxlhdm))
+ if (IS_ERR(cxlhdm)) {
+ if (PTR_ERR(cxlhdm) == -ENODEV)
+ dev_err(&port->dev, "HDM decoder registers not found\n");
return PTR_ERR(cxlhdm);
+ }
/* Cache the data early to ensure is_visible() works */
read_cdat_data(port);
diff --git a/drivers/cxl/security.c b/drivers/cxl/security.c
index 4ad4bda2d18e..21856a3f408e 100644
--- a/drivers/cxl/security.c
+++ b/drivers/cxl/security.c
@@ -14,7 +14,7 @@ static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm,
{
struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
unsigned long security_flags = 0;
struct cxl_get_security_output {
__le32 flags;
@@ -29,11 +29,14 @@ static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm,
.payload_out = &out,
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc < 0)
return 0;
sec_out = le32_to_cpu(out.flags);
+ /* cache security state */
+ mds->security.state = sec_out;
+
if (ptype == NVDIMM_MASTER) {
if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PASS_SET)
set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
@@ -67,7 +70,7 @@ static int cxl_pmem_security_change_key(struct nvdimm *nvdimm,
{
struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
struct cxl_mbox_cmd mbox_cmd;
struct cxl_set_pass set_pass;
@@ -84,7 +87,7 @@ static int cxl_pmem_security_change_key(struct nvdimm *nvdimm,
.payload_in = &set_pass,
};
- return cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ return cxl_internal_send_cmd(mds, &mbox_cmd);
}
static int __cxl_pmem_security_disable(struct nvdimm *nvdimm,
@@ -93,7 +96,7 @@ static int __cxl_pmem_security_disable(struct nvdimm *nvdimm,
{
struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
struct cxl_disable_pass dis_pass;
struct cxl_mbox_cmd mbox_cmd;
@@ -109,7 +112,7 @@ static int __cxl_pmem_security_disable(struct nvdimm *nvdimm,
.payload_in = &dis_pass,
};
- return cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ return cxl_internal_send_cmd(mds, &mbox_cmd);
}
static int cxl_pmem_security_disable(struct nvdimm *nvdimm,
@@ -128,12 +131,12 @@ static int cxl_pmem_security_freeze(struct nvdimm *nvdimm)
{
struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
struct cxl_mbox_cmd mbox_cmd = {
.opcode = CXL_MBOX_OP_FREEZE_SECURITY,
};
- return cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ return cxl_internal_send_cmd(mds, &mbox_cmd);
}
static int cxl_pmem_security_unlock(struct nvdimm *nvdimm,
@@ -141,7 +144,7 @@ static int cxl_pmem_security_unlock(struct nvdimm *nvdimm,
{
struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
u8 pass[NVDIMM_PASSPHRASE_LEN];
struct cxl_mbox_cmd mbox_cmd;
int rc;
@@ -153,7 +156,7 @@ static int cxl_pmem_security_unlock(struct nvdimm *nvdimm,
.payload_in = pass,
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc < 0)
return rc;
@@ -166,7 +169,7 @@ static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm,
{
struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
struct cxl_mbox_cmd mbox_cmd;
struct cxl_pass_erase erase;
int rc;
@@ -182,7 +185,7 @@ static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm,
.payload_in = &erase,
};
- rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
if (rc < 0)
return rc;
diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index 227800053309..0ee96e6fc426 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -446,18 +446,33 @@ static void unregister_dev_dax(void *dev)
put_device(dev);
}
+static void dax_region_free(struct kref *kref)
+{
+ struct dax_region *dax_region;
+
+ dax_region = container_of(kref, struct dax_region, kref);
+ kfree(dax_region);
+}
+
+static void dax_region_put(struct dax_region *dax_region)
+{
+ kref_put(&dax_region->kref, dax_region_free);
+}
+
/* a return value >= 0 indicates this invocation invalidated the id */
static int __free_dev_dax_id(struct dev_dax *dev_dax)
{
- struct dax_region *dax_region = dev_dax->region;
struct device *dev = &dev_dax->dev;
+ struct dax_region *dax_region;
int rc = dev_dax->id;
device_lock_assert(dev);
- if (is_static(dax_region) || dev_dax->id < 0)
+ if (!dev_dax->dyn_id || dev_dax->id < 0)
return -1;
+ dax_region = dev_dax->region;
ida_free(&dax_region->ida, dev_dax->id);
+ dax_region_put(dax_region);
dev_dax->id = -1;
return rc;
}
@@ -473,6 +488,20 @@ static int free_dev_dax_id(struct dev_dax *dev_dax)
return rc;
}
+static int alloc_dev_dax_id(struct dev_dax *dev_dax)
+{
+ struct dax_region *dax_region = dev_dax->region;
+ int id;
+
+ id = ida_alloc(&dax_region->ida, GFP_KERNEL);
+ if (id < 0)
+ return id;
+ kref_get(&dax_region->kref);
+ dev_dax->dyn_id = true;
+ dev_dax->id = id;
+ return id;
+}
+
static ssize_t delete_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len)
{
@@ -560,20 +589,6 @@ static const struct attribute_group *dax_region_attribute_groups[] = {
NULL,
};
-static void dax_region_free(struct kref *kref)
-{
- struct dax_region *dax_region;
-
- dax_region = container_of(kref, struct dax_region, kref);
- kfree(dax_region);
-}
-
-void dax_region_put(struct dax_region *dax_region)
-{
- kref_put(&dax_region->kref, dax_region_free);
-}
-EXPORT_SYMBOL_GPL(dax_region_put);
-
static void dax_region_unregister(void *region)
{
struct dax_region *dax_region = region;
@@ -625,7 +640,6 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
return NULL;
}
- kref_get(&dax_region->kref);
if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region))
return NULL;
return dax_region;
@@ -635,10 +649,12 @@ EXPORT_SYMBOL_GPL(alloc_dax_region);
static void dax_mapping_release(struct device *dev)
{
struct dax_mapping *mapping = to_dax_mapping(dev);
- struct dev_dax *dev_dax = to_dev_dax(dev->parent);
+ struct device *parent = dev->parent;
+ struct dev_dax *dev_dax = to_dev_dax(parent);
ida_free(&dev_dax->ida, mapping->id);
kfree(mapping);
+ put_device(parent);
}
static void unregister_dax_mapping(void *data)
@@ -655,8 +671,7 @@ static void unregister_dax_mapping(void *data)
dev_dax->ranges[mapping->range_id].mapping = NULL;
mapping->range_id = -1;
- device_del(dev);
- put_device(dev);
+ device_unregister(dev);
}
static struct dev_dax_range *get_dax_range(struct device *dev)
@@ -778,6 +793,7 @@ static int devm_register_dax_mapping(struct dev_dax *dev_dax, int range_id)
dev = &mapping->dev;
device_initialize(dev);
dev->parent = &dev_dax->dev;
+ get_device(dev->parent);
dev->type = &dax_mapping_type;
dev_set_name(dev, "mapping%d", mapping->id);
rc = device_add(dev);
@@ -1295,12 +1311,10 @@ static const struct attribute_group *dax_attribute_groups[] = {
static void dev_dax_release(struct device *dev)
{
struct dev_dax *dev_dax = to_dev_dax(dev);
- struct dax_region *dax_region = dev_dax->region;
struct dax_device *dax_dev = dev_dax->dax_dev;
put_dax(dax_dev);
free_dev_dax_id(dev_dax);
- dax_region_put(dax_region);
kfree(dev_dax->pgmap);
kfree(dev_dax);
}
@@ -1324,6 +1338,7 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data)
if (!dev_dax)
return ERR_PTR(-ENOMEM);
+ dev_dax->region = dax_region;
if (is_static(dax_region)) {
if (dev_WARN_ONCE(parent, data->id < 0,
"dynamic id specified to static region\n")) {
@@ -1339,13 +1354,11 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data)
goto err_id;
}
- rc = ida_alloc(&dax_region->ida, GFP_KERNEL);
+ rc = alloc_dev_dax_id(dev_dax);
if (rc < 0)
goto err_id;
- dev_dax->id = rc;
}
- dev_dax->region = dax_region;
dev = &dev_dax->dev;
device_initialize(dev);
dev_set_name(dev, "dax%d.%d", dax_region->id, dev_dax->id);
@@ -1386,7 +1399,6 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data)
dev_dax->target_node = dax_region->target_node;
dev_dax->align = dax_region->align;
ida_init(&dev_dax->ida);
- kref_get(&dax_region->kref);
inode = dax_inode(dax_dev);
dev->devt = inode->i_rdev;
diff --git a/drivers/dax/bus.h b/drivers/dax/bus.h
index 8cd79ab34292..1ccd23360124 100644
--- a/drivers/dax/bus.h
+++ b/drivers/dax/bus.h
@@ -9,7 +9,6 @@ struct dev_dax;
struct resource;
struct dax_device;
struct dax_region;
-void dax_region_put(struct dax_region *dax_region);
/* dax bus specific ioresource flags */
#define IORESOURCE_DAX_STATIC BIT(0)
@@ -49,13 +48,6 @@ void dax_driver_unregister(struct dax_device_driver *dax_drv);
void kill_dev_dax(struct dev_dax *dev_dax);
bool static_dev_dax(struct dev_dax *dev_dax);
-/*
- * While run_dax() is potentially a generic operation that could be
- * defined in include/linux/dax.h we don't want to grow any users
- * outside of drivers/dax/
- */
-void run_dax(struct dax_device *dax_dev);
-
#define MODULE_ALIAS_DAX_DEVICE(type) \
MODULE_ALIAS("dax:t" __stringify(type) "*")
#define DAX_DEVICE_MODALIAS_FMT "dax:t%d"
diff --git a/drivers/dax/cxl.c b/drivers/dax/cxl.c
index ccdf8de85bd5..8bc9d04034d6 100644
--- a/drivers/dax/cxl.c
+++ b/drivers/dax/cxl.c
@@ -13,7 +13,6 @@ static int cxl_dax_region_probe(struct device *dev)
struct cxl_region *cxlr = cxlr_dax->cxlr;
struct dax_region *dax_region;
struct dev_dax_data data;
- struct dev_dax *dev_dax;
if (nid == NUMA_NO_NODE)
nid = memory_add_physaddr_to_nid(cxlr_dax->hpa_range.start);
@@ -28,13 +27,8 @@ static int cxl_dax_region_probe(struct device *dev)
.id = -1,
.size = range_len(&cxlr_dax->hpa_range),
};
- dev_dax = devm_create_dev_dax(&data);
- if (IS_ERR(dev_dax))
- return PTR_ERR(dev_dax);
- /* child dev_dax instances now own the lifetime of the dax_region */
- dax_region_put(dax_region);
- return 0;
+ return PTR_ERR_OR_ZERO(devm_create_dev_dax(&data));
}
static struct cxl_driver cxl_dax_region_driver = {
diff --git a/drivers/dax/dax-private.h b/drivers/dax/dax-private.h
index 1c974b7caae6..27cf2daaaa79 100644
--- a/drivers/dax/dax-private.h
+++ b/drivers/dax/dax-private.h
@@ -52,7 +52,8 @@ struct dax_mapping {
* @region - parent region
* @dax_dev - core dax functionality
* @target_node: effective numa node if dev_dax memory range is onlined
- * @id: ida allocated id
+ * @dyn_id: is this a dynamic or statically created instance
+ * @id: ida allocated id when the dax_region is not static
* @ida: mapping id allocator
* @dev - device core
* @pgmap - pgmap for memmap setup / lifetime (driver owned)
@@ -64,6 +65,7 @@ struct dev_dax {
struct dax_device *dax_dev;
unsigned int align;
int target_node;
+ bool dyn_id;
int id;
struct ida ida;
struct device dev;
@@ -76,6 +78,13 @@ struct dev_dax {
} *ranges;
};
+/*
+ * While run_dax() is potentially a generic operation that could be
+ * defined in include/linux/dax.h we don't want to grow any users
+ * outside of drivers/dax/
+ */
+void run_dax(struct dax_device *dax_dev);
+
static inline struct dev_dax *to_dev_dax(struct device *dev)
{
return container_of(dev, struct dev_dax, dev);
diff --git a/drivers/dax/device.c b/drivers/dax/device.c
index af9930c03c9c..30665a3ff6ea 100644
--- a/drivers/dax/device.c
+++ b/drivers/dax/device.c
@@ -396,7 +396,7 @@ static void dev_dax_kill(void *dev_dax)
kill_dev_dax(dev_dax);
}
-int dev_dax_probe(struct dev_dax *dev_dax)
+static int dev_dax_probe(struct dev_dax *dev_dax)
{
struct dax_device *dax_dev = dev_dax->dax_dev;
struct device *dev = &dev_dax->dev;
@@ -471,7 +471,6 @@ int dev_dax_probe(struct dev_dax *dev_dax)
run_dax(dax_dev);
return devm_add_action_or_reset(dev, dev_dax_kill, dev_dax);
}
-EXPORT_SYMBOL_GPL(dev_dax_probe);
static struct dax_device_driver device_dax_driver = {
.probe = dev_dax_probe,
diff --git a/drivers/dax/hmem/hmem.c b/drivers/dax/hmem/hmem.c
index e5fe8b39fb94..5d2ddef0f8f5 100644
--- a/drivers/dax/hmem/hmem.c
+++ b/drivers/dax/hmem/hmem.c
@@ -16,7 +16,6 @@ static int dax_hmem_probe(struct platform_device *pdev)
struct dax_region *dax_region;
struct memregion_info *mri;
struct dev_dax_data data;
- struct dev_dax *dev_dax;
/*
* @region_idle == true indicates that an administrative agent
@@ -38,13 +37,8 @@ static int dax_hmem_probe(struct platform_device *pdev)
.id = -1,
.size = region_idle ? 0 : range_len(&mri->range),
};
- dev_dax = devm_create_dev_dax(&data);
- if (IS_ERR(dev_dax))
- return PTR_ERR(dev_dax);
- /* child dev_dax instances now own the lifetime of the dax_region */
- dax_region_put(dax_region);
- return 0;
+ return PTR_ERR_OR_ZERO(devm_create_dev_dax(&data));
}
static struct platform_driver dax_hmem_driver = {
diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c
index 7b36db6f1cbd..898ca9505754 100644
--- a/drivers/dax/kmem.c
+++ b/drivers/dax/kmem.c
@@ -99,7 +99,7 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
if (!data->res_name)
goto err_res_name;
- rc = memory_group_register_static(numa_node, total_len);
+ rc = memory_group_register_static(numa_node, PFN_UP(total_len));
if (rc < 0)
goto err_reg_mgid;
data->mgid = rc;
diff --git a/drivers/dax/pmem.c b/drivers/dax/pmem.c
index f050ea78bb83..ae0cb113a5d3 100644
--- a/drivers/dax/pmem.c
+++ b/drivers/dax/pmem.c
@@ -13,7 +13,6 @@ static struct dev_dax *__dax_pmem_probe(struct device *dev)
int rc, id, region_id;
resource_size_t offset;
struct nd_pfn_sb *pfn_sb;
- struct dev_dax *dev_dax;
struct dev_dax_data data;
struct nd_namespace_io *nsio;
struct dax_region *dax_region;
@@ -65,12 +64,8 @@ static struct dev_dax *__dax_pmem_probe(struct device *dev)
.pgmap = &pgmap,
.size = range_len(&range),
};
- dev_dax = devm_create_dev_dax(&data);
- /* child dev_dax instances now own the lifetime of the dax_region */
- dax_region_put(dax_region);
-
- return dev_dax;
+ return devm_create_dev_dax(&data);
}
static int dax_pmem_probe(struct device *dev)
diff --git a/drivers/dax/super.c b/drivers/dax/super.c
index c4c4728a36e4..0da9232ea175 100644
--- a/drivers/dax/super.c
+++ b/drivers/dax/super.c
@@ -203,6 +203,8 @@ size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
size_t nr_pages)
{
+ int ret;
+
if (!dax_alive(dax_dev))
return -ENXIO;
/*
@@ -213,7 +215,8 @@ int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
if (nr_pages != 1)
return -EIO;
- return dax_dev->ops->zero_page_range(dax_dev, pgoff, nr_pages);
+ ret = dax_dev->ops->zero_page_range(dax_dev, pgoff, nr_pages);
+ return dax_mem2blk_err(ret);
}
EXPORT_SYMBOL_GPL(dax_zero_page_range);
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index 2a594b754af1..b6f71eb00866 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -660,7 +660,7 @@ EXPORT_SYMBOL_GPL(dma_resv_get_singleton);
* dma_resv_lock() already
* RETURNS
* Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or
- * greater than zer on success.
+ * greater than zero on success.
*/
long dma_resv_wait_timeout(struct dma_resv *obj, enum dma_resv_usage usage,
bool intr, unsigned long timeout)
diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 348b3a9170fa..63f0aeb66db6 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -85,7 +85,7 @@ static struct sync_timeline *sync_timeline_create(const char *name)
kref_init(&obj->kref);
obj->context = dma_fence_context_alloc(1);
- strlcpy(obj->name, name, sizeof(obj->name));
+ strscpy(obj->name, name, sizeof(obj->name));
obj->pt_tree = RB_ROOT;
INIT_LIST_HEAD(&obj->pt_list);
diff --git a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c
index 8dd40d00a672..a42a37634881 100644
--- a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c
+++ b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c
@@ -765,7 +765,7 @@ err_mcportal:
return err;
}
-static int dpaa2_qdma_remove(struct fsl_mc_device *ls_dev)
+static void dpaa2_qdma_remove(struct fsl_mc_device *ls_dev)
{
struct dpaa2_qdma_engine *dpaa2_qdma;
struct dpaa2_qdma_priv *priv;
@@ -787,8 +787,6 @@ static int dpaa2_qdma_remove(struct fsl_mc_device *ls_dev)
dma_async_device_unregister(&dpaa2_qdma->dma_dev);
kfree(priv);
kfree(dpaa2_qdma);
-
- return 0;
}
static void dpaa2_qdma_shutdown(struct fsl_mc_device *ls_dev)
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index 79d244011093..79d8957f9e60 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -584,11 +584,11 @@ desc_get_errstat(struct ioatdma_chan *ioat_chan, struct ioat_ring_ent *desc)
}
/**
- * __cleanup - reclaim used descriptors
+ * __ioat_cleanup - reclaim used descriptors
* @ioat_chan: channel (ring) to clean
* @phys_complete: zeroed (or not) completion address (from status)
*/
-static void __cleanup(struct ioatdma_chan *ioat_chan, dma_addr_t phys_complete)
+static void __ioat_cleanup(struct ioatdma_chan *ioat_chan, dma_addr_t phys_complete)
{
struct ioatdma_device *ioat_dma = ioat_chan->ioat_dma;
struct ioat_ring_ent *desc;
@@ -675,7 +675,7 @@ static void ioat_cleanup(struct ioatdma_chan *ioat_chan)
spin_lock_bh(&ioat_chan->cleanup_lock);
if (ioat_cleanup_preamble(ioat_chan, &phys_complete))
- __cleanup(ioat_chan, phys_complete);
+ __ioat_cleanup(ioat_chan, phys_complete);
if (is_ioat_halted(*ioat_chan->completion)) {
u32 chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
@@ -712,7 +712,7 @@ static void ioat_restart_channel(struct ioatdma_chan *ioat_chan)
ioat_quiesce(ioat_chan, 0);
if (ioat_cleanup_preamble(ioat_chan, &phys_complete))
- __cleanup(ioat_chan, phys_complete);
+ __ioat_cleanup(ioat_chan, phys_complete);
__ioat_restart_chan(ioat_chan);
}
@@ -786,7 +786,7 @@ static void ioat_eh(struct ioatdma_chan *ioat_chan)
/* cleanup so tail points to descriptor that caused the error */
if (ioat_cleanup_preamble(ioat_chan, &phys_complete))
- __cleanup(ioat_chan, phys_complete);
+ __ioat_cleanup(ioat_chan, phys_complete);
chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
pci_read_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, &chanerr_int);
@@ -943,7 +943,7 @@ void ioat_timer_event(struct timer_list *t)
/* timer restarted in ioat_cleanup_preamble
* and IOAT_COMPLETION_ACK cleared
*/
- __cleanup(ioat_chan, phys_complete);
+ __ioat_cleanup(ioat_chan, phys_complete);
goto unlock_out;
}
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index 290186e44e6b..0ef1971d22bb 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -185,6 +185,7 @@ config EXTCON_USBC_TUSB320
tristate "TI TUSB320 USB-C extcon support"
depends on I2C && TYPEC
select REGMAP_I2C
+ depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
help
Say Y here to enable support for USB Type C cable detection extcon
support using a TUSB320.
diff --git a/drivers/extcon/extcon-axp288.c b/drivers/extcon/extcon-axp288.c
index 180be768c215..a703a8315634 100644
--- a/drivers/extcon/extcon-axp288.c
+++ b/drivers/extcon/extcon-axp288.c
@@ -393,7 +393,7 @@ static int axp288_extcon_probe(struct platform_device *pdev)
adev = acpi_dev_get_first_match_dev("INT3496", NULL, -1);
if (adev) {
info->id_extcon = extcon_get_extcon_dev(acpi_dev_name(adev));
- put_device(&adev->dev);
+ acpi_dev_put(adev);
if (IS_ERR(info->id_extcon))
return PTR_ERR(info->id_extcon);
diff --git a/drivers/extcon/extcon-fsa9480.c b/drivers/extcon/extcon-fsa9480.c
index e8b2671eb29b..e458ce0c45ab 100644
--- a/drivers/extcon/extcon-fsa9480.c
+++ b/drivers/extcon/extcon-fsa9480.c
@@ -369,7 +369,7 @@ static struct i2c_driver fsa9480_i2c_driver = {
.pm = &fsa9480_pm_ops,
.of_match_table = fsa9480_of_match,
},
- .probe_new = fsa9480_probe,
+ .probe = fsa9480_probe,
.id_table = fsa9480_id,
};
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index 32f8b541770b..d339b8680445 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -18,7 +18,6 @@
#include <linux/mfd/palmas.h>
#include <linux/of.h>
#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/workqueue.h>
diff --git a/drivers/extcon/extcon-ptn5150.c b/drivers/extcon/extcon-ptn5150.c
index 017a07197f38..4616da7e5430 100644
--- a/drivers/extcon/extcon-ptn5150.c
+++ b/drivers/extcon/extcon-ptn5150.c
@@ -348,7 +348,7 @@ static struct i2c_driver ptn5150_i2c_driver = {
.name = "ptn5150",
.of_match_table = ptn5150_dt_match,
},
- .probe_new = ptn5150_i2c_probe,
+ .probe = ptn5150_i2c_probe,
.id_table = ptn5150_i2c_id,
};
module_i2c_driver(ptn5150_i2c_driver);
diff --git a/drivers/extcon/extcon-qcom-spmi-misc.c b/drivers/extcon/extcon-qcom-spmi-misc.c
index eb02cb962b5e..f72e90ceca53 100644
--- a/drivers/extcon/extcon-qcom-spmi-misc.c
+++ b/drivers/extcon/extcon-qcom-spmi-misc.c
@@ -123,7 +123,7 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev)
if (ret)
return ret;
- info->id_irq = platform_get_irq_byname(pdev, "usb_id");
+ info->id_irq = platform_get_irq_byname_optional(pdev, "usb_id");
if (info->id_irq > 0) {
ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
qcom_usb_irq_handler,
@@ -136,7 +136,7 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev)
}
}
- info->vbus_irq = platform_get_irq_byname(pdev, "usb_vbus");
+ info->vbus_irq = platform_get_irq_byname_optional(pdev, "usb_vbus");
if (info->vbus_irq > 0) {
ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
qcom_usb_irq_handler,
diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c
index afc9b405d103..19bb49f13fb0 100644
--- a/drivers/extcon/extcon-rt8973a.c
+++ b/drivers/extcon/extcon-rt8973a.c
@@ -695,7 +695,7 @@ static struct i2c_driver rt8973a_muic_i2c_driver = {
.pm = &rt8973a_muic_pm_ops,
.of_match_table = rt8973a_dt_match,
},
- .probe_new = rt8973a_muic_i2c_probe,
+ .probe = rt8973a_muic_i2c_probe,
.remove = rt8973a_muic_i2c_remove,
.id_table = rt8973a_i2c_id,
};
diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c
index 8401e8b27788..c8c4b9ef72aa 100644
--- a/drivers/extcon/extcon-sm5502.c
+++ b/drivers/extcon/extcon-sm5502.c
@@ -840,7 +840,7 @@ static struct i2c_driver sm5502_muic_i2c_driver = {
.pm = &sm5502_muic_pm_ops,
.of_match_table = sm5502_dt_match,
},
- .probe_new = sm5022_muic_i2c_probe,
+ .probe = sm5022_muic_i2c_probe,
.id_table = sm5502_i2c_id,
};
diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c
index b408ce989c22..4d08c2123e59 100644
--- a/drivers/extcon/extcon-usbc-tusb320.c
+++ b/drivers/extcon/extcon-usbc-tusb320.c
@@ -15,6 +15,8 @@
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/usb/typec.h>
+#include <linux/usb/typec_altmode.h>
+#include <linux/usb/role.h>
#define TUSB320_REG8 0x8
#define TUSB320_REG8_CURRENT_MODE_ADVERTISE GENMASK(7, 6)
@@ -26,16 +28,16 @@
#define TUSB320_REG8_CURRENT_MODE_DETECT_MED 0x1
#define TUSB320_REG8_CURRENT_MODE_DETECT_ACC 0x2
#define TUSB320_REG8_CURRENT_MODE_DETECT_HI 0x3
-#define TUSB320_REG8_ACCESSORY_CONNECTED GENMASK(3, 2)
+#define TUSB320_REG8_ACCESSORY_CONNECTED GENMASK(3, 1)
#define TUSB320_REG8_ACCESSORY_CONNECTED_NONE 0x0
#define TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO 0x4
-#define TUSB320_REG8_ACCESSORY_CONNECTED_ACC 0x5
-#define TUSB320_REG8_ACCESSORY_CONNECTED_DEBUG 0x6
+#define TUSB320_REG8_ACCESSORY_CONNECTED_ACHRG 0x5
+#define TUSB320_REG8_ACCESSORY_CONNECTED_DBGDFP 0x6
+#define TUSB320_REG8_ACCESSORY_CONNECTED_DBGUFP 0x7
#define TUSB320_REG8_ACTIVE_CABLE_DETECTION BIT(0)
#define TUSB320_REG9 0x9
-#define TUSB320_REG9_ATTACHED_STATE_SHIFT 6
-#define TUSB320_REG9_ATTACHED_STATE_MASK 0x3
+#define TUSB320_REG9_ATTACHED_STATE GENMASK(7, 6)
#define TUSB320_REG9_CABLE_DIRECTION BIT(5)
#define TUSB320_REG9_INTERRUPT_STATUS BIT(4)
@@ -78,6 +80,8 @@ struct tusb320_priv {
struct typec_capability cap;
enum typec_port_type port_type;
enum typec_pwr_opmode pwr_opmode;
+ struct fwnode_handle *connector_fwnode;
+ struct usb_role_switch *role_sw;
};
static const char * const tusb_attached_states[] = {
@@ -249,8 +253,7 @@ static void tusb320_extcon_irq_handler(struct tusb320_priv *priv, u8 reg)
{
int state, polarity;
- state = (reg >> TUSB320_REG9_ATTACHED_STATE_SHIFT) &
- TUSB320_REG9_ATTACHED_STATE_MASK;
+ state = FIELD_GET(TUSB320_REG9_ATTACHED_STATE, reg);
polarity = !!(reg & TUSB320_REG9_CABLE_DIRECTION);
dev_dbg(priv->dev, "attached state: %s, polarity: %d\n",
@@ -276,32 +279,86 @@ static void tusb320_typec_irq_handler(struct tusb320_priv *priv, u8 reg9)
{
struct typec_port *port = priv->port;
struct device *dev = priv->dev;
- u8 mode, role, state;
+ int typec_mode;
+ enum usb_role usb_role;
+ enum typec_role pwr_role;
+ enum typec_data_role data_role;
+ u8 state, mode, accessory;
int ret, reg8;
bool ori;
+ ret = regmap_read(priv->regmap, TUSB320_REG8, &reg8);
+ if (ret) {
+ dev_err(dev, "error during reg8 i2c read, ret=%d!\n", ret);
+ return;
+ }
+
ori = reg9 & TUSB320_REG9_CABLE_DIRECTION;
typec_set_orientation(port, ori ? TYPEC_ORIENTATION_REVERSE :
TYPEC_ORIENTATION_NORMAL);
- state = (reg9 >> TUSB320_REG9_ATTACHED_STATE_SHIFT) &
- TUSB320_REG9_ATTACHED_STATE_MASK;
- if (state == TUSB320_ATTACHED_STATE_DFP)
- role = TYPEC_SOURCE;
- else
- role = TYPEC_SINK;
+ state = FIELD_GET(TUSB320_REG9_ATTACHED_STATE, reg9);
+ accessory = FIELD_GET(TUSB320_REG8_ACCESSORY_CONNECTED, reg8);
+
+ switch (state) {
+ case TUSB320_ATTACHED_STATE_DFP:
+ typec_mode = TYPEC_MODE_USB2;
+ usb_role = USB_ROLE_HOST;
+ pwr_role = TYPEC_SOURCE;
+ data_role = TYPEC_HOST;
+ break;
+ case TUSB320_ATTACHED_STATE_UFP:
+ typec_mode = TYPEC_MODE_USB2;
+ usb_role = USB_ROLE_DEVICE;
+ pwr_role = TYPEC_SINK;
+ data_role = TYPEC_DEVICE;
+ break;
+ case TUSB320_ATTACHED_STATE_ACC:
+ /*
+ * Accessory detected. For debug accessories, just make some
+ * qualified guesses as to the role for lack of a better option.
+ */
+ if (accessory == TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO ||
+ accessory == TUSB320_REG8_ACCESSORY_CONNECTED_ACHRG) {
+ typec_mode = TYPEC_MODE_AUDIO;
+ usb_role = USB_ROLE_NONE;
+ pwr_role = TYPEC_SINK;
+ data_role = TYPEC_DEVICE;
+ break;
+ } else if (accessory ==
+ TUSB320_REG8_ACCESSORY_CONNECTED_DBGDFP) {
+ typec_mode = TYPEC_MODE_DEBUG;
+ pwr_role = TYPEC_SOURCE;
+ usb_role = USB_ROLE_HOST;
+ data_role = TYPEC_HOST;
+ break;
+ } else if (accessory ==
+ TUSB320_REG8_ACCESSORY_CONNECTED_DBGUFP) {
+ typec_mode = TYPEC_MODE_DEBUG;
+ pwr_role = TYPEC_SINK;
+ usb_role = USB_ROLE_DEVICE;
+ data_role = TYPEC_DEVICE;
+ break;
+ }
- typec_set_vconn_role(port, role);
- typec_set_pwr_role(port, role);
- typec_set_data_role(port, role == TYPEC_SOURCE ?
- TYPEC_HOST : TYPEC_DEVICE);
+ dev_warn(priv->dev, "unexpected ACCESSORY_CONNECTED state %d\n",
+ accessory);
- ret = regmap_read(priv->regmap, TUSB320_REG8, &reg8);
- if (ret) {
- dev_err(dev, "error during reg8 i2c read, ret=%d!\n", ret);
- return;
+ fallthrough;
+ default:
+ typec_mode = TYPEC_MODE_USB2;
+ usb_role = USB_ROLE_NONE;
+ pwr_role = TYPEC_SINK;
+ data_role = TYPEC_DEVICE;
+ break;
}
+ typec_set_vconn_role(port, pwr_role);
+ typec_set_pwr_role(port, pwr_role);
+ typec_set_data_role(port, data_role);
+ typec_set_mode(port, typec_mode);
+ usb_role_switch_set_role(priv->role_sw, usb_role);
+
mode = FIELD_GET(TUSB320_REG8_CURRENT_MODE_DETECT, reg8);
if (mode == TUSB320_REG8_CURRENT_MODE_DETECT_DEF)
typec_set_pwr_opmode(port, TYPEC_PWR_MODE_USB);
@@ -391,27 +448,25 @@ static int tusb320_typec_probe(struct i2c_client *client,
/* Type-C connector found. */
ret = typec_get_fw_cap(&priv->cap, connector);
if (ret)
- return ret;
+ goto err_put;
priv->port_type = priv->cap.type;
/* This goes into register 0x8 field CURRENT_MODE_ADVERTISE */
ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str);
if (ret)
- return ret;
+ goto err_put;
ret = typec_find_pwr_opmode(cap_str);
if (ret < 0)
- return ret;
- if (ret == TYPEC_PWR_MODE_PD)
- return -EINVAL;
+ goto err_put;
priv->pwr_opmode = ret;
/* Initialize the hardware with the devicetree settings. */
ret = tusb320_set_adv_pwr_mode(priv);
if (ret)
- return ret;
+ goto err_put;
priv->cap.revision = USB_TYPEC_REV_1_1;
priv->cap.accessory[0] = TYPEC_ACCESSORY_AUDIO;
@@ -422,10 +477,36 @@ static int tusb320_typec_probe(struct i2c_client *client,
priv->cap.fwnode = connector;
priv->port = typec_register_port(&client->dev, &priv->cap);
- if (IS_ERR(priv->port))
- return PTR_ERR(priv->port);
+ if (IS_ERR(priv->port)) {
+ ret = PTR_ERR(priv->port);
+ goto err_put;
+ }
+
+ /* Find any optional USB role switch that needs reporting to */
+ priv->role_sw = fwnode_usb_role_switch_get(connector);
+ if (IS_ERR(priv->role_sw)) {
+ ret = PTR_ERR(priv->role_sw);
+ goto err_unreg;
+ }
+
+ priv->connector_fwnode = connector;
return 0;
+
+err_unreg:
+ typec_unregister_port(priv->port);
+
+err_put:
+ fwnode_handle_put(connector);
+
+ return ret;
+}
+
+static void tusb320_typec_remove(struct tusb320_priv *priv)
+{
+ usb_role_switch_put(priv->role_sw);
+ typec_unregister_port(priv->port);
+ fwnode_handle_put(priv->connector_fwnode);
}
static int tusb320_probe(struct i2c_client *client)
@@ -438,7 +519,9 @@ static int tusb320_probe(struct i2c_client *client)
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+
priv->dev = &client->dev;
+ i2c_set_clientdata(client, priv);
priv->regmap = devm_regmap_init_i2c(client, &tusb320_regmap_config);
if (IS_ERR(priv->regmap))
@@ -489,10 +572,19 @@ static int tusb320_probe(struct i2c_client *client)
tusb320_irq_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
client->name, priv);
+ if (ret)
+ tusb320_typec_remove(priv);
return ret;
}
+static void tusb320_remove(struct i2c_client *client)
+{
+ struct tusb320_priv *priv = i2c_get_clientdata(client);
+
+ tusb320_typec_remove(priv);
+}
+
static const struct of_device_id tusb320_extcon_dt_match[] = {
{ .compatible = "ti,tusb320", .data = &tusb320_ops, },
{ .compatible = "ti,tusb320l", .data = &tusb320l_ops, },
@@ -501,7 +593,8 @@ static const struct of_device_id tusb320_extcon_dt_match[] = {
MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match);
static struct i2c_driver tusb320_extcon_driver = {
- .probe_new = tusb320_probe,
+ .probe = tusb320_probe,
+ .remove = tusb320_remove,
.driver = {
.name = "extcon-tusb320",
.of_match_table = tusb320_extcon_dt_match,
diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
index d43ba8e7260d..6f7a60d2ed91 100644
--- a/drivers/extcon/extcon.c
+++ b/drivers/extcon/extcon.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/idr.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/fs.h>
@@ -206,6 +207,14 @@ static const struct __extcon_info {
* @attr_name: "name" sysfs entry
* @attr_state: "state" sysfs entry
* @attrs: the array pointing to attr_name and attr_state for attr_g
+ * @usb_propval: the array of USB connector properties
+ * @chg_propval: the array of charger connector properties
+ * @jack_propval: the array of jack connector properties
+ * @disp_propval: the array of display connector properties
+ * @usb_bits: the bit array of the USB connector property capabilities
+ * @chg_bits: the bit array of the charger connector property capabilities
+ * @jack_bits: the bit array of the jack connector property capabilities
+ * @disp_bits: the bit array of the display connector property capabilities
*/
struct extcon_cable {
struct extcon_dev *edev;
@@ -222,20 +231,21 @@ struct extcon_cable {
union extcon_property_value jack_propval[EXTCON_PROP_JACK_CNT];
union extcon_property_value disp_propval[EXTCON_PROP_DISP_CNT];
- unsigned long usb_bits[BITS_TO_LONGS(EXTCON_PROP_USB_CNT)];
- unsigned long chg_bits[BITS_TO_LONGS(EXTCON_PROP_CHG_CNT)];
- unsigned long jack_bits[BITS_TO_LONGS(EXTCON_PROP_JACK_CNT)];
- unsigned long disp_bits[BITS_TO_LONGS(EXTCON_PROP_DISP_CNT)];
+ DECLARE_BITMAP(usb_bits, EXTCON_PROP_USB_CNT);
+ DECLARE_BITMAP(chg_bits, EXTCON_PROP_CHG_CNT);
+ DECLARE_BITMAP(jack_bits, EXTCON_PROP_JACK_CNT);
+ DECLARE_BITMAP(disp_bits, EXTCON_PROP_DISP_CNT);
};
static struct class *extcon_class;
+static DEFINE_IDA(extcon_dev_ids);
static LIST_HEAD(extcon_dev_list);
static DEFINE_MUTEX(extcon_dev_list_lock);
static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
{
- int i = 0;
+ int i;
if (!edev->mutually_exclusive)
return 0;
@@ -362,12 +372,12 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
struct extcon_dev *edev = dev_get_drvdata(dev);
if (edev->max_supported == 0)
- return sprintf(buf, "%u\n", edev->state);
+ return sysfs_emit(buf, "%u\n", edev->state);
for (i = 0; i < edev->max_supported; i++) {
- count += sprintf(buf + count, "%s=%d\n",
- extcon_info[edev->supported_cable[i]].name,
- !!(edev->state & BIT(i)));
+ count += sysfs_emit_at(buf, count, "%s=%d\n",
+ extcon_info[edev->supported_cable[i]].name,
+ !!(edev->state & BIT(i)));
}
return count;
@@ -379,7 +389,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
{
struct extcon_dev *edev = dev_get_drvdata(dev);
- return sprintf(buf, "%s\n", edev->name);
+ return sysfs_emit(buf, "%s\n", edev->name);
}
static DEVICE_ATTR_RO(name);
@@ -390,8 +400,8 @@ static ssize_t cable_name_show(struct device *dev,
attr_name);
int i = cable->cable_index;
- return sprintf(buf, "%s\n",
- extcon_info[cable->edev->supported_cable[i]].name);
+ return sysfs_emit(buf, "%s\n",
+ extcon_info[cable->edev->supported_cable[i]].name);
}
static ssize_t cable_state_show(struct device *dev,
@@ -402,8 +412,8 @@ static ssize_t cable_state_show(struct device *dev,
int i = cable->cable_index;
- return sprintf(buf, "%d\n",
- extcon_get_state(cable->edev, cable->edev->supported_cable[i]));
+ return sysfs_emit(buf, "%d\n",
+ extcon_get_state(cable->edev, cable->edev->supported_cable[i]));
}
/**
@@ -1012,12 +1022,13 @@ ATTRIBUTE_GROUPS(extcon);
static int create_extcon_class(void)
{
- if (!extcon_class) {
- extcon_class = class_create("extcon");
- if (IS_ERR(extcon_class))
- return PTR_ERR(extcon_class);
- extcon_class->dev_groups = extcon_groups;
- }
+ if (extcon_class)
+ return 0;
+
+ extcon_class = class_create("extcon");
+ if (IS_ERR(extcon_class))
+ return PTR_ERR(extcon_class);
+ extcon_class->dev_groups = extcon_groups;
return 0;
}
@@ -1070,6 +1081,156 @@ void extcon_dev_free(struct extcon_dev *edev)
EXPORT_SYMBOL_GPL(extcon_dev_free);
/**
+ * extcon_alloc_cables() - alloc the cables for extcon device
+ * @edev: extcon device which has cables
+ *
+ * Returns 0 if success or error number if fail.
+ */
+static int extcon_alloc_cables(struct extcon_dev *edev)
+{
+ int index;
+ char *str;
+ struct extcon_cable *cable;
+
+ if (!edev)
+ return -EINVAL;
+
+ if (!edev->max_supported)
+ return 0;
+
+ edev->cables = kcalloc(edev->max_supported, sizeof(*edev->cables),
+ GFP_KERNEL);
+ if (!edev->cables)
+ return -ENOMEM;
+
+ for (index = 0; index < edev->max_supported; index++) {
+ cable = &edev->cables[index];
+
+ str = kasprintf(GFP_KERNEL, "cable.%d", index);
+ if (!str) {
+ for (index--; index >= 0; index--) {
+ cable = &edev->cables[index];
+ kfree(cable->attr_g.name);
+ }
+
+ kfree(edev->cables);
+ return -ENOMEM;
+ }
+
+ cable->edev = edev;
+ cable->cable_index = index;
+ cable->attrs[0] = &cable->attr_name.attr;
+ cable->attrs[1] = &cable->attr_state.attr;
+ cable->attrs[2] = NULL;
+ cable->attr_g.name = str;
+ cable->attr_g.attrs = cable->attrs;
+
+ sysfs_attr_init(&cable->attr_name.attr);
+ cable->attr_name.attr.name = "name";
+ cable->attr_name.attr.mode = 0444;
+ cable->attr_name.show = cable_name_show;
+
+ sysfs_attr_init(&cable->attr_state.attr);
+ cable->attr_state.attr.name = "state";
+ cable->attr_state.attr.mode = 0444;
+ cable->attr_state.show = cable_state_show;
+ }
+
+ return 0;
+}
+
+/**
+ * extcon_alloc_muex() - alloc the mutual exclusive for extcon device
+ * @edev: extcon device
+ *
+ * Returns 0 if success or error number if fail.
+ */
+static int extcon_alloc_muex(struct extcon_dev *edev)
+{
+ char *name;
+ int index;
+
+ if (!edev)
+ return -EINVAL;
+
+ if (!(edev->max_supported && edev->mutually_exclusive))
+ return 0;
+
+ /* Count the size of mutually_exclusive array */
+ for (index = 0; edev->mutually_exclusive[index]; index++)
+ ;
+
+ edev->attrs_muex = kcalloc(index + 1, sizeof(*edev->attrs_muex),
+ GFP_KERNEL);
+ if (!edev->attrs_muex)
+ return -ENOMEM;
+
+ edev->d_attrs_muex = kcalloc(index, sizeof(*edev->d_attrs_muex),
+ GFP_KERNEL);
+ if (!edev->d_attrs_muex) {
+ kfree(edev->attrs_muex);
+ return -ENOMEM;
+ }
+
+ for (index = 0; edev->mutually_exclusive[index]; index++) {
+ name = kasprintf(GFP_KERNEL, "0x%x",
+ edev->mutually_exclusive[index]);
+ if (!name) {
+ for (index--; index >= 0; index--)
+ kfree(edev->d_attrs_muex[index].attr.name);
+
+ kfree(edev->d_attrs_muex);
+ kfree(edev->attrs_muex);
+ return -ENOMEM;
+ }
+ sysfs_attr_init(&edev->d_attrs_muex[index].attr);
+ edev->d_attrs_muex[index].attr.name = name;
+ edev->d_attrs_muex[index].attr.mode = 0000;
+ edev->attrs_muex[index] = &edev->d_attrs_muex[index].attr;
+ }
+ edev->attr_g_muex.name = muex_name;
+ edev->attr_g_muex.attrs = edev->attrs_muex;
+
+ return 0;
+}
+
+/**
+ * extcon_alloc_groups() - alloc the groups for extcon device
+ * @edev: extcon device
+ *
+ * Returns 0 if success or error number if fail.
+ */
+static int extcon_alloc_groups(struct extcon_dev *edev)
+{
+ int index;
+
+ if (!edev)
+ return -EINVAL;
+
+ if (!edev->max_supported)
+ return 0;
+
+ edev->extcon_dev_type.groups = kcalloc(edev->max_supported + 2,
+ sizeof(*edev->extcon_dev_type.groups),
+ GFP_KERNEL);
+ if (!edev->extcon_dev_type.groups)
+ return -ENOMEM;
+
+ edev->extcon_dev_type.name = dev_name(&edev->dev);
+ edev->extcon_dev_type.release = dummy_sysfs_dev_release;
+
+ for (index = 0; index < edev->max_supported; index++)
+ edev->extcon_dev_type.groups[index] = &edev->cables[index].attr_g;
+
+ if (edev->mutually_exclusive)
+ edev->extcon_dev_type.groups[index] = &edev->attr_g_muex;
+
+ edev->dev.type = &edev->extcon_dev_type;
+
+ return 0;
+}
+
+/**
* extcon_dev_register() - Register an new extcon device
* @edev: the extcon device to be registered
*
@@ -1085,19 +1246,16 @@ EXPORT_SYMBOL_GPL(extcon_dev_free);
*/
int extcon_dev_register(struct extcon_dev *edev)
{
- int ret, index = 0;
- static atomic_t edev_no = ATOMIC_INIT(-1);
+ int ret, index;
- if (!extcon_class) {
- ret = create_extcon_class();
- if (ret < 0)
- return ret;
- }
+ ret = create_extcon_class();
+ if (ret < 0)
+ return ret;
if (!edev || !edev->supported_cable)
return -EINVAL;
- for (; edev->supported_cable[index] != EXTCON_NONE; index++);
+ for (index = 0; edev->supported_cable[index] != EXTCON_NONE; index++);
edev->max_supported = index;
if (index > SUPPORTED_CABLE_MAX) {
@@ -1115,124 +1273,26 @@ int extcon_dev_register(struct extcon_dev *edev)
"extcon device name is null\n");
return -EINVAL;
}
- dev_set_name(&edev->dev, "extcon%lu",
- (unsigned long)atomic_inc_return(&edev_no));
-
- if (edev->max_supported) {
- char *str;
- struct extcon_cable *cable;
-
- edev->cables = kcalloc(edev->max_supported,
- sizeof(struct extcon_cable),
- GFP_KERNEL);
- if (!edev->cables) {
- ret = -ENOMEM;
- goto err_sysfs_alloc;
- }
- for (index = 0; index < edev->max_supported; index++) {
- cable = &edev->cables[index];
-
- str = kasprintf(GFP_KERNEL, "cable.%d", index);
- if (!str) {
- for (index--; index >= 0; index--) {
- cable = &edev->cables[index];
- kfree(cable->attr_g.name);
- }
- ret = -ENOMEM;
-
- goto err_alloc_cables;
- }
-
- cable->edev = edev;
- cable->cable_index = index;
- cable->attrs[0] = &cable->attr_name.attr;
- cable->attrs[1] = &cable->attr_state.attr;
- cable->attrs[2] = NULL;
- cable->attr_g.name = str;
- cable->attr_g.attrs = cable->attrs;
-
- sysfs_attr_init(&cable->attr_name.attr);
- cable->attr_name.attr.name = "name";
- cable->attr_name.attr.mode = 0444;
- cable->attr_name.show = cable_name_show;
-
- sysfs_attr_init(&cable->attr_state.attr);
- cable->attr_state.attr.name = "state";
- cable->attr_state.attr.mode = 0444;
- cable->attr_state.show = cable_state_show;
- }
- }
- if (edev->max_supported && edev->mutually_exclusive) {
- char *name;
-
- /* Count the size of mutually_exclusive array */
- for (index = 0; edev->mutually_exclusive[index]; index++)
- ;
-
- edev->attrs_muex = kcalloc(index + 1,
- sizeof(struct attribute *),
- GFP_KERNEL);
- if (!edev->attrs_muex) {
- ret = -ENOMEM;
- goto err_muex;
- }
-
- edev->d_attrs_muex = kcalloc(index,
- sizeof(struct device_attribute),
- GFP_KERNEL);
- if (!edev->d_attrs_muex) {
- ret = -ENOMEM;
- kfree(edev->attrs_muex);
- goto err_muex;
- }
-
- for (index = 0; edev->mutually_exclusive[index]; index++) {
- name = kasprintf(GFP_KERNEL, "0x%x",
- edev->mutually_exclusive[index]);
- if (!name) {
- for (index--; index >= 0; index--) {
- kfree(edev->d_attrs_muex[index].attr.
- name);
- }
- kfree(edev->d_attrs_muex);
- kfree(edev->attrs_muex);
- ret = -ENOMEM;
- goto err_muex;
- }
- sysfs_attr_init(&edev->d_attrs_muex[index].attr);
- edev->d_attrs_muex[index].attr.name = name;
- edev->d_attrs_muex[index].attr.mode = 0000;
- edev->attrs_muex[index] = &edev->d_attrs_muex[index]
- .attr;
- }
- edev->attr_g_muex.name = muex_name;
- edev->attr_g_muex.attrs = edev->attrs_muex;
+ ret = ida_alloc(&extcon_dev_ids, GFP_KERNEL);
+ if (ret < 0)
+ return ret;
- }
+ edev->id = ret;
- if (edev->max_supported) {
- edev->extcon_dev_type.groups =
- kcalloc(edev->max_supported + 2,
- sizeof(struct attribute_group *),
- GFP_KERNEL);
- if (!edev->extcon_dev_type.groups) {
- ret = -ENOMEM;
- goto err_alloc_groups;
- }
+ dev_set_name(&edev->dev, "extcon%d", edev->id);
- edev->extcon_dev_type.name = dev_name(&edev->dev);
- edev->extcon_dev_type.release = dummy_sysfs_dev_release;
+ ret = extcon_alloc_cables(edev);
+ if (ret < 0)
+ goto err_alloc_cables;
- for (index = 0; index < edev->max_supported; index++)
- edev->extcon_dev_type.groups[index] =
- &edev->cables[index].attr_g;
- if (edev->mutually_exclusive)
- edev->extcon_dev_type.groups[index] =
- &edev->attr_g_muex;
+ ret = extcon_alloc_muex(edev);
+ if (ret < 0)
+ goto err_alloc_muex;
- edev->dev.type = &edev->extcon_dev_type;
- }
+ ret = extcon_alloc_groups(edev);
+ if (ret < 0)
+ goto err_alloc_groups;
spin_lock_init(&edev->lock);
if (edev->max_supported) {
@@ -1277,13 +1337,14 @@ err_alloc_groups:
kfree(edev->d_attrs_muex);
kfree(edev->attrs_muex);
}
-err_muex:
+err_alloc_muex:
for (index = 0; index < edev->max_supported; index++)
kfree(edev->cables[index].attr_g.name);
-err_alloc_cables:
if (edev->max_supported)
kfree(edev->cables);
-err_sysfs_alloc:
+err_alloc_cables:
+ ida_free(&extcon_dev_ids, edev->id);
+
return ret;
}
EXPORT_SYMBOL_GPL(extcon_dev_register);
@@ -1306,12 +1367,13 @@ void extcon_dev_unregister(struct extcon_dev *edev)
list_del(&edev->entry);
mutex_unlock(&extcon_dev_list_lock);
- if (IS_ERR_OR_NULL(get_device(&edev->dev))) {
- dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n",
- dev_name(&edev->dev));
+ if (!get_device(&edev->dev)) {
+ dev_err(&edev->dev, "Failed to unregister extcon_dev\n");
return;
}
+ ida_free(&extcon_dev_ids, edev->id);
+
device_unregister(&edev->dev);
if (edev->mutually_exclusive && edev->max_supported) {
@@ -1349,7 +1411,7 @@ struct extcon_dev *extcon_find_edev_by_node(struct device_node *node)
mutex_lock(&extcon_dev_list_lock);
list_for_each_entry(edev, &extcon_dev_list, entry)
- if (edev->dev.parent && edev->dev.parent->of_node == node)
+ if (edev->dev.parent && device_match_of_node(edev->dev.parent, node))
goto out;
edev = ERR_PTR(-EPROBE_DEFER);
out:
@@ -1367,21 +1429,17 @@ out:
*/
struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
{
- struct device_node *node;
+ struct device_node *node, *np = dev_of_node(dev);
struct extcon_dev *edev;
- if (!dev)
- return ERR_PTR(-EINVAL);
-
- if (!dev->of_node) {
+ if (!np) {
dev_dbg(dev, "device does not have a device node entry\n");
return ERR_PTR(-EINVAL);
}
- node = of_parse_phandle(dev->of_node, "extcon", index);
+ node = of_parse_phandle(np, "extcon", index);
if (!node) {
- dev_dbg(dev, "failed to get phandle in %pOF node\n",
- dev->of_node);
+ dev_dbg(dev, "failed to get phandle in %pOF node\n", np);
return ERR_PTR(-ENODEV);
}
diff --git a/drivers/extcon/extcon.h b/drivers/extcon/extcon.h
index 93b5e0306966..946182687786 100644
--- a/drivers/extcon/extcon.h
+++ b/drivers/extcon/extcon.h
@@ -13,13 +13,14 @@
* are disabled.
* @mutually_exclusive: Array of mutually exclusive set of cables that cannot
* be attached simultaneously. The array should be
- * ending with NULL or be NULL (no mutually exclusive
- * cables). For example, if it is { 0x7, 0x30, 0}, then,
+ * ending with 0 or be NULL (no mutually exclusive cables).
+ * For example, if it is {0x7, 0x30, 0}, then,
* {0, 1}, {0, 1, 2}, {0, 2}, {1, 2}, or {4, 5} cannot
* be attached simulataneously. {0x7, 0} is equivalent to
* {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
* can be no simultaneous connections.
* @dev: Device of this extcon.
+ * @id: Unique device ID of this extcon.
* @state: Attach/detach state of this extcon. Do not provide at
* register-time.
* @nh_all: Notifier for the state change events for all supported
@@ -27,7 +28,7 @@
* @nh: Notifier for the state change events from this extcon
* @entry: To support list of extcon devices so that users can
* search for extcon devices based on the extcon name.
- * @lock:
+ * @lock: Protects device state and serialises device registration
* @max_supported: Internal value to store the number of cables.
* @extcon_dev_type: Device_type struct to provide attribute_groups
* customized for each extcon device.
@@ -46,6 +47,7 @@ struct extcon_dev {
/* Internal data. Please do not set. */
struct device dev;
+ unsigned int id;
struct raw_notifier_head nh_all;
struct raw_notifier_head *nh;
struct list_head entry;
diff --git a/drivers/firewire/.kunitconfig b/drivers/firewire/.kunitconfig
new file mode 100644
index 000000000000..1599e069395f
--- /dev/null
+++ b/drivers/firewire/.kunitconfig
@@ -0,0 +1,4 @@
+CONFIG_KUNIT=y
+CONFIG_PCI=y
+CONFIG_FIREWIRE=y
+CONFIG_FIREWIRE_KUNIT_UAPI_TEST=y
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
index ec00a6f70da8..0a6596b027db 100644
--- a/drivers/firewire/Kconfig
+++ b/drivers/firewire/Kconfig
@@ -18,6 +18,22 @@ config FIREWIRE
To compile this driver as a module, say M here: the module will be
called firewire-core.
+config FIREWIRE_KUNIT_UAPI_TEST
+ tristate "KUnit tests for layout of structure in UAPI" if !KUNIT_ALL_TESTS
+ depends on FIREWIRE && KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ This builds the KUnit tests whether structures exposed to user
+ space have expected layout.
+
+ KUnit tests run during boot and output the results to the debug
+ log in TAP format (https://testanything.org/). Only useful for
+ kernel devs running KUnit test harness and are not for inclusion
+ into a production build.
+
+ For more information on KUnit and unit tests in general, refer
+ to the KUnit documentation in Documentation/dev-tools/kunit/.
+
config FIREWIRE_OHCI
tristate "OHCI-1394 controllers"
depends on PCI && FIREWIRE && MMU
diff --git a/drivers/firewire/Makefile b/drivers/firewire/Makefile
index e58c8c794778..b24b2879ac34 100644
--- a/drivers/firewire/Makefile
+++ b/drivers/firewire/Makefile
@@ -15,3 +15,6 @@ obj-$(CONFIG_FIREWIRE_SBP2) += firewire-sbp2.o
obj-$(CONFIG_FIREWIRE_NET) += firewire-net.o
obj-$(CONFIG_FIREWIRE_NOSY) += nosy.o
obj-$(CONFIG_PROVIDE_OHCI1394_DMA_INIT) += init_ohci1394_dma.o
+
+firewire-uapi-test-objs += uapi-test.o
+obj-$(CONFIG_FIREWIRE_KUNIT_UAPI_TEST) += firewire-uapi-test.o
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 2c16ee8fd842..6274b86eb943 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -43,6 +43,7 @@
#define FW_CDEV_VERSION_EVENT_REQUEST2 4
#define FW_CDEV_VERSION_ALLOCATE_REGION_END 4
#define FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW 5
+#define FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP 6
struct client {
u32 version;
@@ -169,7 +170,10 @@ struct outbound_transaction_event {
struct event event;
struct client *client;
struct outbound_transaction_resource r;
- struct fw_cdev_event_response response;
+ union {
+ struct fw_cdev_event_response without_tstamp;
+ struct fw_cdev_event_response2 with_tstamp;
+ } rsp;
};
struct inbound_transaction_event {
@@ -177,6 +181,7 @@ struct inbound_transaction_event {
union {
struct fw_cdev_event_request request;
struct fw_cdev_event_request2 request2;
+ struct fw_cdev_event_request3 with_tstamp;
} req;
};
@@ -199,12 +204,18 @@ struct outbound_phy_packet_event {
struct event event;
struct client *client;
struct fw_packet p;
- struct fw_cdev_event_phy_packet phy_packet;
+ union {
+ struct fw_cdev_event_phy_packet without_tstamp;
+ struct fw_cdev_event_phy_packet2 with_tstamp;
+ } phy_packet;
};
struct inbound_phy_packet_event {
struct event event;
- struct fw_cdev_event_phy_packet phy_packet;
+ union {
+ struct fw_cdev_event_phy_packet without_tstamp;
+ struct fw_cdev_event_phy_packet2 with_tstamp;
+ } phy_packet;
};
#ifdef CONFIG_COMPAT
@@ -534,41 +545,64 @@ static void release_transaction(struct client *client,
{
}
-static void complete_transaction(struct fw_card *card, int rcode,
- void *payload, size_t length, void *data)
+static void complete_transaction(struct fw_card *card, int rcode, u32 request_tstamp,
+ u32 response_tstamp, void *payload, size_t length, void *data)
{
struct outbound_transaction_event *e = data;
- struct fw_cdev_event_response *rsp = &e->response;
struct client *client = e->client;
unsigned long flags;
- if (length < rsp->length)
- rsp->length = length;
- if (rcode == RCODE_COMPLETE)
- memcpy(rsp->data, payload, rsp->length);
-
spin_lock_irqsave(&client->lock, flags);
idr_remove(&client->resource_idr, e->r.resource.handle);
if (client->in_shutdown)
wake_up(&client->tx_flush_wait);
spin_unlock_irqrestore(&client->lock, flags);
- rsp->type = FW_CDEV_EVENT_RESPONSE;
- rsp->rcode = rcode;
+ switch (e->rsp.without_tstamp.type) {
+ case FW_CDEV_EVENT_RESPONSE:
+ {
+ struct fw_cdev_event_response *rsp = &e->rsp.without_tstamp;
+
+ if (length < rsp->length)
+ rsp->length = length;
+ if (rcode == RCODE_COMPLETE)
+ memcpy(rsp->data, payload, rsp->length);
+
+ rsp->rcode = rcode;
+
+ // In the case that sizeof(*rsp) doesn't align with the position of the
+ // data, and the read is short, preserve an extra copy of the data
+ // to stay compatible with a pre-2.6.27 bug. Since the bug is harmless
+ // for short reads and some apps depended on it, this is both safe
+ // and prudent for compatibility.
+ if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data))
+ queue_event(client, &e->event, rsp, sizeof(*rsp), rsp->data, rsp->length);
+ else
+ queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length, NULL, 0);
- /*
- * In the case that sizeof(*rsp) doesn't align with the position of the
- * data, and the read is short, preserve an extra copy of the data
- * to stay compatible with a pre-2.6.27 bug. Since the bug is harmless
- * for short reads and some apps depended on it, this is both safe
- * and prudent for compatibility.
- */
- if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data))
- queue_event(client, &e->event, rsp, sizeof(*rsp),
- rsp->data, rsp->length);
- else
- queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length,
- NULL, 0);
+ break;
+ }
+ case FW_CDEV_EVENT_RESPONSE2:
+ {
+ struct fw_cdev_event_response2 *rsp = &e->rsp.with_tstamp;
+
+ if (length < rsp->length)
+ rsp->length = length;
+ if (rcode == RCODE_COMPLETE)
+ memcpy(rsp->data, payload, rsp->length);
+
+ rsp->rcode = rcode;
+ rsp->request_tstamp = request_tstamp;
+ rsp->response_tstamp = response_tstamp;
+
+ queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length, NULL, 0);
+
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+ }
/* Drop the idr's reference */
client_put(client);
@@ -579,6 +613,7 @@ static int init_request(struct client *client,
int destination_id, int speed)
{
struct outbound_transaction_event *e;
+ void *payload;
int ret;
if (request->tcode != TCODE_STREAM_DATA &&
@@ -592,14 +627,25 @@ static int init_request(struct client *client,
e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL);
if (e == NULL)
return -ENOMEM;
-
e->client = client;
- e->response.length = request->length;
- e->response.closure = request->closure;
- if (request->data &&
- copy_from_user(e->response.data,
- u64_to_uptr(request->data), request->length)) {
+ if (client->version < FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP) {
+ struct fw_cdev_event_response *rsp = &e->rsp.without_tstamp;
+
+ rsp->type = FW_CDEV_EVENT_RESPONSE;
+ rsp->length = request->length;
+ rsp->closure = request->closure;
+ payload = rsp->data;
+ } else {
+ struct fw_cdev_event_response2 *rsp = &e->rsp.with_tstamp;
+
+ rsp->type = FW_CDEV_EVENT_RESPONSE2;
+ rsp->length = request->length;
+ rsp->closure = request->closure;
+ payload = rsp->data;
+ }
+
+ if (request->data && copy_from_user(payload, u64_to_uptr(request->data), request->length)) {
ret = -EFAULT;
goto failed;
}
@@ -609,10 +655,9 @@ static int init_request(struct client *client,
if (ret < 0)
goto failed;
- fw_send_request(client->device->card, &e->r.transaction,
- request->tcode, destination_id, request->generation,
- speed, request->offset, e->response.data,
- request->length, complete_transaction, e);
+ fw_send_request_with_tstamp(client->device->card, &e->r.transaction, request->tcode,
+ destination_id, request->generation, speed, request->offset,
+ payload, request->length, complete_transaction, e);
return 0;
failed:
@@ -708,7 +753,7 @@ static void handle_request(struct fw_card *card, struct fw_request *request,
req->handle = r->resource.handle;
req->closure = handler->closure;
event_size0 = sizeof(*req);
- } else {
+ } else if (handler->client->version < FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP) {
struct fw_cdev_event_request2 *req = &e->req.request2;
req->type = FW_CDEV_EVENT_REQUEST2;
@@ -722,6 +767,21 @@ static void handle_request(struct fw_card *card, struct fw_request *request,
req->handle = r->resource.handle;
req->closure = handler->closure;
event_size0 = sizeof(*req);
+ } else {
+ struct fw_cdev_event_request3 *req = &e->req.with_tstamp;
+
+ req->type = FW_CDEV_EVENT_REQUEST3;
+ req->tcode = tcode;
+ req->offset = offset;
+ req->source_node_id = source;
+ req->destination_node_id = destination;
+ req->card = card->index;
+ req->generation = generation;
+ req->length = length;
+ req->handle = r->resource.handle;
+ req->closure = handler->closure;
+ req->tstamp = fw_request_get_timestamp(request);
+ event_size0 = sizeof(*req);
}
queue_event(handler->client, &e->event,
@@ -1495,26 +1555,61 @@ static void outbound_phy_packet_callback(struct fw_packet *packet,
{
struct outbound_phy_packet_event *e =
container_of(packet, struct outbound_phy_packet_event, p);
- struct client *e_client;
+ struct client *e_client = e->client;
+ u32 rcode;
switch (status) {
- /* expected: */
- case ACK_COMPLETE: e->phy_packet.rcode = RCODE_COMPLETE; break;
- /* should never happen with PHY packets: */
- case ACK_PENDING: e->phy_packet.rcode = RCODE_COMPLETE; break;
+ // expected:
+ case ACK_COMPLETE:
+ rcode = RCODE_COMPLETE;
+ break;
+ // should never happen with PHY packets:
+ case ACK_PENDING:
+ rcode = RCODE_COMPLETE;
+ break;
case ACK_BUSY_X:
case ACK_BUSY_A:
- case ACK_BUSY_B: e->phy_packet.rcode = RCODE_BUSY; break;
- case ACK_DATA_ERROR: e->phy_packet.rcode = RCODE_DATA_ERROR; break;
- case ACK_TYPE_ERROR: e->phy_packet.rcode = RCODE_TYPE_ERROR; break;
- /* stale generation; cancelled; on certain controllers: no ack */
- default: e->phy_packet.rcode = status; break;
+ case ACK_BUSY_B:
+ rcode = RCODE_BUSY;
+ break;
+ case ACK_DATA_ERROR:
+ rcode = RCODE_DATA_ERROR;
+ break;
+ case ACK_TYPE_ERROR:
+ rcode = RCODE_TYPE_ERROR;
+ break;
+ // stale generation; cancelled; on certain controllers: no ack
+ default:
+ rcode = status;
+ break;
+ }
+
+ switch (e->phy_packet.without_tstamp.type) {
+ case FW_CDEV_EVENT_PHY_PACKET_SENT:
+ {
+ struct fw_cdev_event_phy_packet *pp = &e->phy_packet.without_tstamp;
+
+ pp->rcode = rcode;
+ pp->data[0] = packet->timestamp;
+ queue_event(e->client, &e->event, &e->phy_packet, sizeof(*pp) + pp->length,
+ NULL, 0);
+ break;
+ }
+ case FW_CDEV_EVENT_PHY_PACKET_SENT2:
+ {
+ struct fw_cdev_event_phy_packet2 *pp = &e->phy_packet.with_tstamp;
+
+ pp->rcode = rcode;
+ pp->tstamp = packet->timestamp;
+ queue_event(e->client, &e->event, &e->phy_packet, sizeof(*pp) + pp->length,
+ NULL, 0);
+ break;
+ }
+ default:
+ WARN_ON(1);
+ break;
}
- e->phy_packet.data[0] = packet->timestamp;
- e_client = e->client;
- queue_event(e->client, &e->event, &e->phy_packet,
- sizeof(e->phy_packet) + e->phy_packet.length, NULL, 0);
client_put(e_client);
}
@@ -1528,7 +1623,7 @@ static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)
if (!client->device->is_local)
return -ENOSYS;
- e = kzalloc(sizeof(*e) + 4, GFP_KERNEL);
+ e = kzalloc(sizeof(*e) + sizeof(a->data), GFP_KERNEL);
if (e == NULL)
return -ENOMEM;
@@ -1541,10 +1636,24 @@ static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)
e->p.header[2] = a->data[1];
e->p.header_length = 12;
e->p.callback = outbound_phy_packet_callback;
- e->phy_packet.closure = a->closure;
- e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_SENT;
- if (is_ping_packet(a->data))
- e->phy_packet.length = 4;
+
+ if (client->version < FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP) {
+ struct fw_cdev_event_phy_packet *pp = &e->phy_packet.without_tstamp;
+
+ pp->closure = a->closure;
+ pp->type = FW_CDEV_EVENT_PHY_PACKET_SENT;
+ if (is_ping_packet(a->data))
+ pp->length = 4;
+ } else {
+ struct fw_cdev_event_phy_packet2 *pp = &e->phy_packet.with_tstamp;
+
+ pp->closure = a->closure;
+ pp->type = FW_CDEV_EVENT_PHY_PACKET_SENT2;
+ // Keep the data field so that application can match the response event to the
+ // request.
+ pp->length = sizeof(a->data);
+ memcpy(pp->data, a->data, sizeof(a->data));
+ }
card->driver->send_request(card, &e->p);
@@ -1583,14 +1692,29 @@ void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p)
if (e == NULL)
break;
- e->phy_packet.closure = client->phy_receiver_closure;
- e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_RECEIVED;
- e->phy_packet.rcode = RCODE_COMPLETE;
- e->phy_packet.length = 8;
- e->phy_packet.data[0] = p->header[1];
- e->phy_packet.data[1] = p->header[2];
- queue_event(client, &e->event,
- &e->phy_packet, sizeof(e->phy_packet) + 8, NULL, 0);
+ if (client->version < FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP) {
+ struct fw_cdev_event_phy_packet *pp = &e->phy_packet.without_tstamp;
+
+ pp->closure = client->phy_receiver_closure;
+ pp->type = FW_CDEV_EVENT_PHY_PACKET_RECEIVED;
+ pp->rcode = RCODE_COMPLETE;
+ pp->length = 8;
+ pp->data[0] = p->header[1];
+ pp->data[1] = p->header[2];
+ queue_event(client, &e->event, &e->phy_packet, sizeof(*pp) + 8, NULL, 0);
+ } else {
+ struct fw_cdev_event_phy_packet2 *pp = &e->phy_packet.with_tstamp;
+
+ pp = &e->phy_packet.with_tstamp;
+ pp->closure = client->phy_receiver_closure;
+ pp->type = FW_CDEV_EVENT_PHY_PACKET_RECEIVED2;
+ pp->rcode = RCODE_COMPLETE;
+ pp->length = 8;
+ pp->tstamp = p->timestamp;
+ pp->data[0] = p->header[1];
+ pp->data[1] = p->header[2];
+ queue_event(client, &e->event, &e->phy_packet, sizeof(*pp) + 8, NULL, 0);
+ }
}
spin_unlock_irqrestore(&card->lock, flags);
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index aa597cda0d88..a3104e35412c 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -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_ATOMIC);
+ device = kzalloc(sizeof(*device), GFP_KERNEL);
if (device == NULL)
break;
diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c
index f40c81534381..88466b663482 100644
--- a/drivers/firewire/core-topology.c
+++ b/drivers/firewire/core-topology.c
@@ -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_ATOMIC);
+ node = kzalloc(struct_size(node, ports, port_count), GFP_KERNEL);
if (node == NULL)
return NULL;
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index a9f70c96323e..130b95aca629 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -70,8 +70,8 @@ static int try_cancel_split_timeout(struct fw_transaction *t)
return 1;
}
-static int close_transaction(struct fw_transaction *transaction,
- struct fw_card *card, int rcode)
+static int close_transaction(struct fw_transaction *transaction, struct fw_card *card, int rcode,
+ u32 response_tstamp)
{
struct fw_transaction *t = NULL, *iter;
unsigned long flags;
@@ -92,7 +92,12 @@ static int close_transaction(struct fw_transaction *transaction,
spin_unlock_irqrestore(&card->lock, flags);
if (t) {
- t->callback(card, rcode, NULL, 0, t->callback_data);
+ if (!t->with_tstamp) {
+ t->callback.without_tstamp(card, rcode, NULL, 0, t->callback_data);
+ } else {
+ t->callback.with_tstamp(card, rcode, t->packet.timestamp, response_tstamp,
+ NULL, 0, t->callback_data);
+ }
return 0;
}
@@ -107,6 +112,8 @@ static int close_transaction(struct fw_transaction *transaction,
int fw_cancel_transaction(struct fw_card *card,
struct fw_transaction *transaction)
{
+ u32 tstamp;
+
/*
* Cancel the packet transmission if it's still queued. That
* will call the packet transmission callback which cancels
@@ -121,7 +128,17 @@ int fw_cancel_transaction(struct fw_card *card,
* if the transaction is still pending and remove it in that case.
*/
- return close_transaction(transaction, card, RCODE_CANCELLED);
+ if (transaction->packet.ack == 0) {
+ // The timestamp is reused since it was just read now.
+ tstamp = transaction->packet.timestamp;
+ } else {
+ u32 curr_cycle_time = 0;
+
+ (void)fw_card_read_cycle_time(card, &curr_cycle_time);
+ tstamp = cycle_time_to_ohci_tstamp(curr_cycle_time);
+ }
+
+ return close_transaction(transaction, card, RCODE_CANCELLED, tstamp);
}
EXPORT_SYMBOL(fw_cancel_transaction);
@@ -140,7 +157,12 @@ static void split_transaction_timeout_callback(struct timer_list *timer)
card->tlabel_mask &= ~(1ULL << t->tlabel);
spin_unlock_irqrestore(&card->lock, flags);
- t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
+ if (!t->with_tstamp) {
+ t->callback.without_tstamp(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
+ } else {
+ t->callback.with_tstamp(card, RCODE_CANCELLED, t->packet.timestamp,
+ t->split_timeout_cycle, NULL, 0, t->callback_data);
+ }
}
static void start_split_transaction_timeout(struct fw_transaction *t,
@@ -162,6 +184,8 @@ static void start_split_transaction_timeout(struct fw_transaction *t,
spin_unlock_irqrestore(&card->lock, flags);
}
+static u32 compute_split_timeout_timestamp(struct fw_card *card, u32 request_timestamp);
+
static void transmit_complete_callback(struct fw_packet *packet,
struct fw_card *card, int status)
{
@@ -170,28 +194,32 @@ static void transmit_complete_callback(struct fw_packet *packet,
switch (status) {
case ACK_COMPLETE:
- close_transaction(t, card, RCODE_COMPLETE);
+ close_transaction(t, card, RCODE_COMPLETE, packet->timestamp);
break;
case ACK_PENDING:
+ {
+ t->split_timeout_cycle =
+ compute_split_timeout_timestamp(card, packet->timestamp) & 0xffff;
start_split_transaction_timeout(t, card);
break;
+ }
case ACK_BUSY_X:
case ACK_BUSY_A:
case ACK_BUSY_B:
- close_transaction(t, card, RCODE_BUSY);
+ close_transaction(t, card, RCODE_BUSY, packet->timestamp);
break;
case ACK_DATA_ERROR:
- close_transaction(t, card, RCODE_DATA_ERROR);
+ close_transaction(t, card, RCODE_DATA_ERROR, packet->timestamp);
break;
case ACK_TYPE_ERROR:
- close_transaction(t, card, RCODE_TYPE_ERROR);
+ close_transaction(t, card, RCODE_TYPE_ERROR, packet->timestamp);
break;
default:
/*
* In this case the ack is really a juju specific
* rcode, so just forward that to the callback.
*/
- close_transaction(t, card, status);
+ close_transaction(t, card, status, packet->timestamp);
break;
}
}
@@ -288,7 +316,8 @@ static int allocate_tlabel(struct fw_card *card)
}
/**
- * fw_send_request() - submit a request packet for transmission
+ * __fw_send_request() - submit a request packet for transmission to generate callback for response
+ * subaction with or without time stamp.
* @card: interface to send the request at
* @t: transaction instance to which the request belongs
* @tcode: transaction code
@@ -298,7 +327,9 @@ static int allocate_tlabel(struct fw_card *card)
* @offset: 48bit wide offset into destination's address space
* @payload: data payload for the request subaction
* @length: length of the payload, in bytes
- * @callback: function to be called when the transaction is completed
+ * @callback: union of two functions whether to receive time stamp or not for response
+ * subaction.
+ * @with_tstamp: Whether to receive time stamp or not for response subaction.
* @callback_data: data to be passed to the transaction completion callback
*
* Submit a request packet into the asynchronous request transmission queue.
@@ -335,10 +366,10 @@ static int allocate_tlabel(struct fw_card *card)
* transaction completion and hence execution of @callback may happen even
* before fw_send_request() returns.
*/
-void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
- int destination_id, int generation, int speed,
- unsigned long long offset, void *payload, size_t length,
- fw_transaction_callback_t callback, void *callback_data)
+void __fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
+ int destination_id, int generation, int speed, unsigned long long offset,
+ void *payload, size_t length, union fw_transaction_callback callback,
+ bool with_tstamp, void *callback_data)
{
unsigned long flags;
int tlabel;
@@ -353,7 +384,19 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
tlabel = allocate_tlabel(card);
if (tlabel < 0) {
spin_unlock_irqrestore(&card->lock, flags);
- callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data);
+ if (!with_tstamp) {
+ callback.without_tstamp(card, RCODE_SEND_ERROR, NULL, 0, callback_data);
+ } else {
+ // Timestamping on behalf of hardware.
+ u32 curr_cycle_time = 0;
+ u32 tstamp;
+
+ (void)fw_card_read_cycle_time(card, &curr_cycle_time);
+ tstamp = cycle_time_to_ohci_tstamp(curr_cycle_time);
+
+ callback.with_tstamp(card, RCODE_SEND_ERROR, tstamp, tstamp, NULL, 0,
+ callback_data);
+ }
return;
}
@@ -361,13 +404,12 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
t->tlabel = tlabel;
t->card = card;
t->is_split_transaction = false;
- timer_setup(&t->split_timeout_timer,
- split_transaction_timeout_callback, 0);
+ timer_setup(&t->split_timeout_timer, split_transaction_timeout_callback, 0);
t->callback = callback;
+ t->with_tstamp = with_tstamp;
t->callback_data = callback_data;
- fw_fill_request(&t->packet, tcode, t->tlabel,
- destination_id, card->node_id, generation,
+ fw_fill_request(&t->packet, tcode, t->tlabel, destination_id, card->node_id, generation,
speed, offset, payload, length);
t->packet.callback = transmit_complete_callback;
@@ -377,7 +419,7 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
card->driver->send_request(card, &t->packet);
}
-EXPORT_SYMBOL(fw_send_request);
+EXPORT_SYMBOL_GPL(__fw_send_request);
struct transaction_callback_data {
struct completion done;
@@ -1047,7 +1089,12 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
*/
card->driver->cancel_packet(card, &t->packet);
- t->callback(card, rcode, data, data_length, t->callback_data);
+ if (!t->with_tstamp) {
+ t->callback.without_tstamp(card, rcode, data, data_length, t->callback_data);
+ } else {
+ t->callback.with_tstamp(card, rcode, t->packet.timestamp, p->timestamp, data,
+ data_length, t->callback_data);
+ }
}
EXPORT_SYMBOL(fw_core_handle_response);
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index eafa4eaae737..2a05f411328f 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -247,6 +247,13 @@ void fw_fill_response(struct fw_packet *response, u32 *request_header,
void fw_request_get(struct fw_request *request);
void fw_request_put(struct fw_request *request);
+// Convert the value of IEEE 1394 CYCLE_TIME register to the format of timeStamp field in
+// descriptors of 1394 OHCI.
+static inline u32 cycle_time_to_ohci_tstamp(u32 tstamp)
+{
+ return (tstamp & 0x0ffff000) >> 12;
+}
+
#define FW_PHY_CONFIG_NO_NODE_ID -1
#define FW_PHY_CONFIG_CURRENT_GAP_COUNT -1
void fw_send_phy_config(struct fw_card *card,
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 538bd677c254..7a4d1a478e33 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -479,7 +479,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
struct sk_buff *skb, u16 source_node_id,
bool is_broadcast, u16 ether_type)
{
- int status;
+ int status, len;
switch (ether_type) {
case ETH_P_ARP:
@@ -533,13 +533,15 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
}
skb->protocol = protocol;
}
+
+ len = skb->len;
status = netif_rx(skb);
if (status == NET_RX_DROP) {
net->stats.rx_errors++;
net->stats.rx_dropped++;
} else {
net->stats.rx_packets++;
- net->stats.rx_bytes += skb->len;
+ net->stats.rx_bytes += len;
}
return 0;
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 17c9d825188b..7e88fd489741 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -677,6 +677,9 @@ static void ar_context_release(struct ar_context *ctx)
struct device *dev = ctx->ohci->card.device;
unsigned int i;
+ if (!ctx->buffer)
+ return;
+
vunmap(ctx->buffer);
for (i = 0; i < AR_BUFFERS; i++) {
@@ -1105,8 +1108,7 @@ static int context_add_buffer(struct context *ctx)
if (ctx->total_allocation >= 16*1024*1024)
return -ENOMEM;
- desc = dma_alloc_coherent(ctx->ohci->card.device, PAGE_SIZE,
- &bus_addr, GFP_ATOMIC);
+ desc = dmam_alloc_coherent(ctx->ohci->card.device, PAGE_SIZE, &bus_addr, GFP_ATOMIC);
if (!desc)
return -ENOMEM;
@@ -1165,10 +1167,10 @@ static void context_release(struct context *ctx)
struct fw_card *card = &ctx->ohci->card;
struct descriptor_buffer *desc, *tmp;
- list_for_each_entry_safe(desc, tmp, &ctx->buffer_list, list)
- dma_free_coherent(card->device, PAGE_SIZE, desc,
- desc->buffer_bus -
- ((void *)&desc->buffer - (void *)desc));
+ list_for_each_entry_safe(desc, tmp, &ctx->buffer_list, list) {
+ dmam_free_coherent(card->device, PAGE_SIZE, desc,
+ desc->buffer_bus - ((void *)&desc->buffer - (void *)desc));
+ }
}
/* Must be called with ohci->lock held */
@@ -1623,6 +1625,8 @@ static void handle_local_request(struct context *ctx, struct fw_packet *packet)
}
}
+static u32 get_cycle_time(struct fw_ohci *ohci);
+
static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
{
unsigned long flags;
@@ -1633,6 +1637,10 @@ static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
if (HEADER_GET_DESTINATION(packet->header[0]) == ctx->ohci->node_id &&
ctx->ohci->generation == packet->generation) {
spin_unlock_irqrestore(&ctx->ohci->lock, flags);
+
+ // Timestamping on behalf of the hardware.
+ packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ctx->ohci));
+
handle_local_request(ctx, packet);
return;
}
@@ -1640,9 +1648,12 @@ static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
ret = at_context_queue_packet(ctx, packet);
spin_unlock_irqrestore(&ctx->ohci->lock, flags);
- if (ret < 0)
- packet->callback(packet, &ctx->ohci->card, packet->ack);
+ if (ret < 0) {
+ // Timestamping on behalf of the hardware.
+ packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ctx->ohci));
+ packet->callback(packet, &ctx->ohci->card, packet->ack);
+ }
}
static void detect_dead_context(struct fw_ohci *ohci,
@@ -2044,8 +2055,7 @@ static void bus_reset_work(struct work_struct *work)
spin_unlock_irq(&ohci->lock);
if (free_rom)
- dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
- free_rom, free_rom_bus);
+ dmam_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, free_rom, free_rom_bus);
log_selfids(ohci, generation, self_id_count);
@@ -2377,10 +2387,8 @@ static int ohci_enable(struct fw_card *card,
*/
if (config_rom) {
- ohci->next_config_rom =
- dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE,
- &ohci->next_config_rom_bus,
- GFP_KERNEL);
+ ohci->next_config_rom = dmam_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+ &ohci->next_config_rom_bus, GFP_KERNEL);
if (ohci->next_config_rom == NULL)
return -ENOMEM;
@@ -2472,9 +2480,8 @@ static int ohci_set_config_rom(struct fw_card *card,
* ohci->next_config_rom to NULL (see bus_reset_work).
*/
- next_config_rom =
- dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE,
- &next_config_rom_bus, GFP_KERNEL);
+ next_config_rom = dmam_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+ &next_config_rom_bus, GFP_KERNEL);
if (next_config_rom == NULL)
return -ENOMEM;
@@ -2507,9 +2514,10 @@ static int ohci_set_config_rom(struct fw_card *card,
spin_unlock_irq(&ohci->lock);
/* If we didn't use the DMA allocation, delete it. */
- if (next_config_rom != NULL)
- dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
- next_config_rom, next_config_rom_bus);
+ if (next_config_rom != NULL) {
+ dmam_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, next_config_rom,
+ next_config_rom_bus);
+ }
/*
* Now initiate a bus reset to have the changes take
@@ -2557,6 +2565,10 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
log_ar_at_event(ohci, 'T', packet->speed, packet->header, 0x20);
driver_data->packet = NULL;
packet->ack = RCODE_CANCELLED;
+
+ // Timestamping on behalf of the hardware.
+ packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci));
+
packet->callback(packet, &ohci->card, packet->ack);
ret = 0;
out:
@@ -3544,6 +3556,19 @@ static inline void pmac_ohci_on(struct pci_dev *dev) {}
static inline void pmac_ohci_off(struct pci_dev *dev) {}
#endif /* CONFIG_PPC_PMAC */
+static void release_ohci(struct device *dev, void *data)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct fw_ohci *ohci = pci_get_drvdata(pdev);
+
+ pmac_ohci_off(pdev);
+
+ ar_context_release(&ohci->ar_response_ctx);
+ ar_context_release(&ohci->ar_request_ctx);
+
+ dev_notice(dev, "removed fw-ohci device\n");
+}
+
static int pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
@@ -3558,25 +3583,22 @@ static int pci_probe(struct pci_dev *dev,
return -ENOSYS;
}
- ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
- if (ohci == NULL) {
- err = -ENOMEM;
- goto fail;
- }
-
+ ohci = devres_alloc(release_ohci, sizeof(*ohci), GFP_KERNEL);
+ if (ohci == NULL)
+ return -ENOMEM;
fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev);
-
+ pci_set_drvdata(dev, ohci);
pmac_ohci_on(dev);
+ devres_add(&dev->dev, ohci);
- err = pci_enable_device(dev);
+ err = pcim_enable_device(dev);
if (err) {
dev_err(&dev->dev, "failed to enable OHCI hardware\n");
- goto fail_free;
+ return err;
}
pci_set_master(dev);
pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0);
- pci_set_drvdata(dev, ohci);
spin_lock_init(&ohci->lock);
mutex_init(&ohci->phy_reg_mutex);
@@ -3586,22 +3608,15 @@ static int pci_probe(struct pci_dev *dev,
if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM) ||
pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE) {
ohci_err(ohci, "invalid MMIO resource\n");
- err = -ENXIO;
- goto fail_disable;
+ return -ENXIO;
}
- err = pci_request_region(dev, 0, ohci_driver_name);
+ err = pcim_iomap_regions(dev, 1 << 0, ohci_driver_name);
if (err) {
- ohci_err(ohci, "MMIO resource unavailable\n");
- goto fail_disable;
- }
-
- ohci->registers = pci_iomap(dev, 0, OHCI1394_REGISTER_SIZE);
- if (ohci->registers == NULL) {
- ohci_err(ohci, "failed to remap registers\n");
- err = -ENXIO;
- goto fail_iomem;
+ ohci_err(ohci, "request and map MMIO resource unavailable\n");
+ return -ENXIO;
}
+ ohci->registers = pcim_iomap_table(dev)[0];
for (i = 0; i < ARRAY_SIZE(ohci_quirks); i++)
if ((ohci_quirks[i].vendor == dev->vendor) &&
@@ -3622,34 +3637,30 @@ static int pci_probe(struct pci_dev *dev,
*/
BUILD_BUG_ON(AR_BUFFERS * sizeof(struct descriptor) > PAGE_SIZE/4);
BUILD_BUG_ON(SELF_ID_BUF_SIZE > PAGE_SIZE/2);
- ohci->misc_buffer = dma_alloc_coherent(ohci->card.device,
- PAGE_SIZE,
- &ohci->misc_buffer_bus,
- GFP_KERNEL);
- if (!ohci->misc_buffer) {
- err = -ENOMEM;
- goto fail_iounmap;
- }
+ ohci->misc_buffer = dmam_alloc_coherent(&dev->dev, PAGE_SIZE, &ohci->misc_buffer_bus,
+ GFP_KERNEL);
+ if (!ohci->misc_buffer)
+ return -ENOMEM;
err = ar_context_init(&ohci->ar_request_ctx, ohci, 0,
OHCI1394_AsReqRcvContextControlSet);
if (err < 0)
- goto fail_misc_buf;
+ return err;
err = ar_context_init(&ohci->ar_response_ctx, ohci, PAGE_SIZE/4,
OHCI1394_AsRspRcvContextControlSet);
if (err < 0)
- goto fail_arreq_ctx;
+ return err;
err = context_init(&ohci->at_request_ctx, ohci,
OHCI1394_AsReqTrContextControlSet, handle_at_packet);
if (err < 0)
- goto fail_arrsp_ctx;
+ return err;
err = context_init(&ohci->at_response_ctx, ohci,
OHCI1394_AsRspTrContextControlSet, handle_at_packet);
if (err < 0)
- goto fail_atreq_ctx;
+ return err;
reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
ohci->ir_context_channels = ~0ULL;
@@ -3658,7 +3669,9 @@ static int pci_probe(struct pci_dev *dev,
ohci->ir_context_mask = ohci->ir_context_support;
ohci->n_ir = hweight32(ohci->ir_context_mask);
size = sizeof(struct iso_context) * ohci->n_ir;
- ohci->ir_context_list = kzalloc(size, GFP_KERNEL);
+ ohci->ir_context_list = devm_kzalloc(&dev->dev, size, GFP_KERNEL);
+ if (!ohci->ir_context_list)
+ return -ENOMEM;
reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
@@ -3671,12 +3684,9 @@ static int pci_probe(struct pci_dev *dev,
ohci->it_context_mask = ohci->it_context_support;
ohci->n_it = hweight32(ohci->it_context_mask);
size = sizeof(struct iso_context) * ohci->n_it;
- ohci->it_context_list = kzalloc(size, GFP_KERNEL);
-
- if (ohci->it_context_list == NULL || ohci->ir_context_list == NULL) {
- err = -ENOMEM;
- goto fail_contexts;
- }
+ ohci->it_context_list = devm_kzalloc(&dev->dev, size, GFP_KERNEL);
+ if (!ohci->it_context_list)
+ return -ENOMEM;
ohci->self_id = ohci->misc_buffer + PAGE_SIZE/2;
ohci->self_id_bus = ohci->misc_buffer_bus + PAGE_SIZE/2;
@@ -3689,17 +3699,16 @@ static int pci_probe(struct pci_dev *dev,
if (!(ohci->quirks & QUIRK_NO_MSI))
pci_enable_msi(dev);
- if (request_irq(dev->irq, irq_handler,
- pci_dev_msi_enabled(dev) ? 0 : IRQF_SHARED,
- ohci_driver_name, ohci)) {
+ err = devm_request_irq(&dev->dev, dev->irq, irq_handler,
+ pci_dev_msi_enabled(dev) ? 0 : IRQF_SHARED, ohci_driver_name, ohci);
+ if (err < 0) {
ohci_err(ohci, "failed to allocate interrupt %d\n", dev->irq);
- err = -EIO;
goto fail_msi;
}
err = fw_card_add(&ohci->card, max_receive, link_speed, guid);
if (err)
- goto fail_irq;
+ goto fail_msi;
version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
ohci_notice(ohci,
@@ -3712,33 +3721,9 @@ static int pci_probe(struct pci_dev *dev,
return 0;
- fail_irq:
- free_irq(dev->irq, ohci);
fail_msi:
pci_disable_msi(dev);
- fail_contexts:
- kfree(ohci->ir_context_list);
- kfree(ohci->it_context_list);
- context_release(&ohci->at_response_ctx);
- fail_atreq_ctx:
- context_release(&ohci->at_request_ctx);
- fail_arrsp_ctx:
- ar_context_release(&ohci->ar_response_ctx);
- fail_arreq_ctx:
- ar_context_release(&ohci->ar_request_ctx);
- fail_misc_buf:
- dma_free_coherent(ohci->card.device, PAGE_SIZE,
- ohci->misc_buffer, ohci->misc_buffer_bus);
- fail_iounmap:
- pci_iounmap(dev, ohci->registers);
- fail_iomem:
- pci_release_region(dev, 0);
- fail_disable:
- pci_disable_device(dev);
- fail_free:
- kfree(ohci);
- pmac_ohci_off(dev);
- fail:
+
return err;
}
@@ -3763,30 +3748,10 @@ static void pci_remove(struct pci_dev *dev)
*/
software_reset(ohci);
- free_irq(dev->irq, ohci);
-
- if (ohci->next_config_rom && ohci->next_config_rom != ohci->config_rom)
- dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
- ohci->next_config_rom, ohci->next_config_rom_bus);
- if (ohci->config_rom)
- dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
- ohci->config_rom, ohci->config_rom_bus);
- ar_context_release(&ohci->ar_request_ctx);
- ar_context_release(&ohci->ar_response_ctx);
- dma_free_coherent(ohci->card.device, PAGE_SIZE,
- ohci->misc_buffer, ohci->misc_buffer_bus);
- context_release(&ohci->at_request_ctx);
- context_release(&ohci->at_response_ctx);
- kfree(ohci->it_context_list);
- kfree(ohci->ir_context_list);
+
pci_disable_msi(dev);
- pci_iounmap(dev, ohci->registers);
- pci_release_region(dev, 0);
- pci_disable_device(dev);
- kfree(ohci);
- pmac_ohci_off(dev);
- dev_notice(&dev->dev, "removed fw-ohci device\n");
+ dev_notice(&dev->dev, "removing fw-ohci device\n");
}
#ifdef CONFIG_PM
diff --git a/drivers/firewire/uapi-test.c b/drivers/firewire/uapi-test.c
new file mode 100644
index 000000000000..2fcbede4fab1
--- /dev/null
+++ b/drivers/firewire/uapi-test.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// uapi_test.c - An application of Kunit to check layout of structures exposed to user space for
+// FireWire subsystem.
+//
+// Copyright (c) 2023 Takashi Sakamoto
+
+#include <kunit/test.h>
+#include <linux/firewire-cdev.h>
+
+// Known issue added at v2.6.27 kernel.
+static void structure_layout_event_response(struct kunit *test)
+{
+#if defined(CONFIG_X86_32)
+ // 4 bytes alignment for aggregate type including 8 bytes storage types.
+ KUNIT_EXPECT_EQ(test, 20, sizeof(struct fw_cdev_event_response));
+#else
+ // 8 bytes alignment for aggregate type including 8 bytes storage types.
+ KUNIT_EXPECT_EQ(test, 24, sizeof(struct fw_cdev_event_response));
+#endif
+
+ KUNIT_EXPECT_EQ(test, 0, offsetof(struct fw_cdev_event_response, closure));
+ KUNIT_EXPECT_EQ(test, 8, offsetof(struct fw_cdev_event_response, type));
+ KUNIT_EXPECT_EQ(test, 12, offsetof(struct fw_cdev_event_response, rcode));
+ KUNIT_EXPECT_EQ(test, 16, offsetof(struct fw_cdev_event_response, length));
+ KUNIT_EXPECT_EQ(test, 20, offsetof(struct fw_cdev_event_response, data));
+}
+
+// Added at v6.5.
+static void structure_layout_event_request3(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, 56, sizeof(struct fw_cdev_event_request3));
+
+ KUNIT_EXPECT_EQ(test, 0, offsetof(struct fw_cdev_event_request3, closure));
+ KUNIT_EXPECT_EQ(test, 8, offsetof(struct fw_cdev_event_request3, type));
+ KUNIT_EXPECT_EQ(test, 12, offsetof(struct fw_cdev_event_request3, tcode));
+ KUNIT_EXPECT_EQ(test, 16, offsetof(struct fw_cdev_event_request3, offset));
+ KUNIT_EXPECT_EQ(test, 24, offsetof(struct fw_cdev_event_request3, source_node_id));
+ KUNIT_EXPECT_EQ(test, 28, offsetof(struct fw_cdev_event_request3, destination_node_id));
+ KUNIT_EXPECT_EQ(test, 32, offsetof(struct fw_cdev_event_request3, card));
+ KUNIT_EXPECT_EQ(test, 36, offsetof(struct fw_cdev_event_request3, generation));
+ KUNIT_EXPECT_EQ(test, 40, offsetof(struct fw_cdev_event_request3, handle));
+ KUNIT_EXPECT_EQ(test, 44, offsetof(struct fw_cdev_event_request3, length));
+ KUNIT_EXPECT_EQ(test, 48, offsetof(struct fw_cdev_event_request3, tstamp));
+ KUNIT_EXPECT_EQ(test, 56, offsetof(struct fw_cdev_event_request3, data));
+}
+
+// Added at v6.5.
+static void structure_layout_event_response2(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, 32, sizeof(struct fw_cdev_event_response2));
+
+ KUNIT_EXPECT_EQ(test, 0, offsetof(struct fw_cdev_event_response2, closure));
+ KUNIT_EXPECT_EQ(test, 8, offsetof(struct fw_cdev_event_response2, type));
+ KUNIT_EXPECT_EQ(test, 12, offsetof(struct fw_cdev_event_response2, rcode));
+ KUNIT_EXPECT_EQ(test, 16, offsetof(struct fw_cdev_event_response2, length));
+ KUNIT_EXPECT_EQ(test, 20, offsetof(struct fw_cdev_event_response2, request_tstamp));
+ KUNIT_EXPECT_EQ(test, 24, offsetof(struct fw_cdev_event_response2, response_tstamp));
+ KUNIT_EXPECT_EQ(test, 32, offsetof(struct fw_cdev_event_response2, data));
+}
+
+// Added at v6.5.
+static void structure_layout_event_phy_packet2(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, 24, sizeof(struct fw_cdev_event_phy_packet2));
+
+ KUNIT_EXPECT_EQ(test, 0, offsetof(struct fw_cdev_event_phy_packet2, closure));
+ KUNIT_EXPECT_EQ(test, 8, offsetof(struct fw_cdev_event_phy_packet2, type));
+ KUNIT_EXPECT_EQ(test, 12, offsetof(struct fw_cdev_event_phy_packet2, rcode));
+ KUNIT_EXPECT_EQ(test, 16, offsetof(struct fw_cdev_event_phy_packet2, length));
+ KUNIT_EXPECT_EQ(test, 20, offsetof(struct fw_cdev_event_phy_packet2, tstamp));
+ KUNIT_EXPECT_EQ(test, 24, offsetof(struct fw_cdev_event_phy_packet2, data));
+}
+
+static struct kunit_case structure_layout_test_cases[] = {
+ KUNIT_CASE(structure_layout_event_response),
+ KUNIT_CASE(structure_layout_event_request3),
+ KUNIT_CASE(structure_layout_event_response2),
+ KUNIT_CASE(structure_layout_event_phy_packet2),
+ {}
+};
+
+static struct kunit_suite structure_layout_test_suite = {
+ .name = "firewire-uapi-structure-layout",
+ .test_cases = structure_layout_test_cases,
+};
+kunit_test_suite(structure_layout_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index e7d97b59963b..b5957cc12fee 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -2914,6 +2914,7 @@ static const struct of_device_id scmi_of_match[] = {
#endif
#ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC
{ .compatible = "arm,scmi-smc", .data = &scmi_smc_desc},
+ { .compatible = "arm,scmi-smc-param", .data = &scmi_smc_desc},
#endif
#ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO
{ .compatible = "arm,scmi-virtio", .data = &scmi_virtio_desc},
diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c
index 83b90bde755c..244929cb4f3e 100644
--- a/drivers/firmware/arm_scmi/powercap.c
+++ b/drivers/firmware/arm_scmi/powercap.c
@@ -108,6 +108,8 @@ struct scmi_powercap_meas_changed_notify_payld {
};
struct scmi_powercap_state {
+ bool enabled;
+ u32 last_pcap;
bool meas_notif_enabled;
u64 thresholds;
#define THRESH_LOW(p, id) \
@@ -313,24 +315,33 @@ static int scmi_powercap_xfer_cap_get(const struct scmi_protocol_handle *ph,
return ret;
}
-static int scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 *power_cap)
+static int __scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
+ const struct scmi_powercap_info *dom,
+ u32 *power_cap)
{
- struct scmi_powercap_info *dom;
- struct powercap_info *pi = ph->get_priv(ph);
-
- if (!power_cap || domain_id >= pi->num_domains)
- return -EINVAL;
-
- dom = pi->powercaps + domain_id;
if (dom->fc_info && dom->fc_info[POWERCAP_FC_CAP].get_addr) {
*power_cap = ioread32(dom->fc_info[POWERCAP_FC_CAP].get_addr);
trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_GET,
- domain_id, *power_cap, 0);
+ dom->id, *power_cap, 0);
return 0;
}
- return scmi_powercap_xfer_cap_get(ph, domain_id, power_cap);
+ return scmi_powercap_xfer_cap_get(ph, dom->id, power_cap);
+}
+
+static int scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 *power_cap)
+{
+ const struct scmi_powercap_info *dom;
+
+ if (!power_cap)
+ return -EINVAL;
+
+ dom = scmi_powercap_dom_info_get(ph, domain_id);
+ if (!dom)
+ return -EINVAL;
+
+ return __scmi_powercap_cap_get(ph, dom, power_cap);
}
static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph,
@@ -375,17 +386,20 @@ static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph,
return ret;
}
-static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 power_cap,
- bool ignore_dresp)
+static int __scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
+ struct powercap_info *pi, u32 domain_id,
+ u32 power_cap, bool ignore_dresp)
{
+ int ret = -EINVAL;
const struct scmi_powercap_info *pc;
pc = scmi_powercap_dom_info_get(ph, domain_id);
- if (!pc || !pc->powercap_cap_config || !power_cap ||
- power_cap < pc->min_power_cap ||
- power_cap > pc->max_power_cap)
- return -EINVAL;
+ if (!pc || !pc->powercap_cap_config)
+ return ret;
+
+ if (power_cap &&
+ (power_cap < pc->min_power_cap || power_cap > pc->max_power_cap))
+ return ret;
if (pc->fc_info && pc->fc_info[POWERCAP_FC_CAP].set_addr) {
struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_CAP];
@@ -394,10 +408,41 @@ static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
ph->hops->fastchannel_db_ring(fci->set_db);
trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_SET,
domain_id, power_cap, 0);
+ ret = 0;
+ } else {
+ ret = scmi_powercap_xfer_cap_set(ph, pc, power_cap,
+ ignore_dresp);
+ }
+
+ /* Save the last explicitly set non-zero powercap value */
+ if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && !ret && power_cap)
+ pi->states[domain_id].last_pcap = power_cap;
+
+ return ret;
+}
+
+static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 power_cap,
+ bool ignore_dresp)
+{
+ struct powercap_info *pi = ph->get_priv(ph);
+
+ /*
+ * Disallow zero as a possible explicitly requested powercap:
+ * there are enable/disable operations for this.
+ */
+ if (!power_cap)
+ return -EINVAL;
+
+ /* Just log the last set request if acting on a disabled domain */
+ if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 &&
+ !pi->states[domain_id].enabled) {
+ pi->states[domain_id].last_pcap = power_cap;
return 0;
}
- return scmi_powercap_xfer_cap_set(ph, pc, power_cap, ignore_dresp);
+ return __scmi_powercap_cap_set(ph, pi, domain_id,
+ power_cap, ignore_dresp);
}
static int scmi_powercap_xfer_pai_get(const struct scmi_protocol_handle *ph,
@@ -564,11 +609,78 @@ scmi_powercap_measurements_threshold_set(const struct scmi_protocol_handle *ph,
return ret;
}
+static int scmi_powercap_cap_enable_set(const struct scmi_protocol_handle *ph,
+ u32 domain_id, bool enable)
+{
+ int ret;
+ u32 power_cap;
+ struct powercap_info *pi = ph->get_priv(ph);
+
+ if (PROTOCOL_REV_MAJOR(pi->version) < 0x2)
+ return -EINVAL;
+
+ if (enable == pi->states[domain_id].enabled)
+ return 0;
+
+ if (enable) {
+ /* Cannot enable with a zero powercap. */
+ if (!pi->states[domain_id].last_pcap)
+ return -EINVAL;
+
+ ret = __scmi_powercap_cap_set(ph, pi, domain_id,
+ pi->states[domain_id].last_pcap,
+ true);
+ } else {
+ ret = __scmi_powercap_cap_set(ph, pi, domain_id, 0, true);
+ }
+
+ if (ret)
+ return ret;
+
+ /*
+ * Update our internal state to reflect final platform state: the SCMI
+ * server could have ignored a disable request and kept enforcing some
+ * powercap limit requested by other agents.
+ */
+ ret = scmi_powercap_cap_get(ph, domain_id, &power_cap);
+ if (!ret)
+ pi->states[domain_id].enabled = !!power_cap;
+
+ return ret;
+}
+
+static int scmi_powercap_cap_enable_get(const struct scmi_protocol_handle *ph,
+ u32 domain_id, bool *enable)
+{
+ int ret;
+ u32 power_cap;
+ struct powercap_info *pi = ph->get_priv(ph);
+
+ *enable = true;
+ if (PROTOCOL_REV_MAJOR(pi->version) < 0x2)
+ return 0;
+
+ /*
+ * Report always real platform state; platform could have ignored
+ * a previous disable request. Default true on any error.
+ */
+ ret = scmi_powercap_cap_get(ph, domain_id, &power_cap);
+ if (!ret)
+ *enable = !!power_cap;
+
+ /* Update internal state with current real platform state */
+ pi->states[domain_id].enabled = *enable;
+
+ return 0;
+}
+
static const struct scmi_powercap_proto_ops powercap_proto_ops = {
.num_domains_get = scmi_powercap_num_domains_get,
.info_get = scmi_powercap_dom_info_get,
.cap_get = scmi_powercap_cap_get,
.cap_set = scmi_powercap_cap_set,
+ .cap_enable_set = scmi_powercap_cap_enable_set,
+ .cap_enable_get = scmi_powercap_cap_enable_get,
.pai_get = scmi_powercap_pai_get,
.pai_set = scmi_powercap_pai_set,
.measurements_get = scmi_powercap_measurements_get,
@@ -829,6 +941,11 @@ scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph)
if (!pinfo->powercaps)
return -ENOMEM;
+ pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains,
+ sizeof(*pinfo->states), GFP_KERNEL);
+ if (!pinfo->states)
+ return -ENOMEM;
+
/*
* Note that any failure in retrieving any domain attribute leads to
* the whole Powercap protocol initialization failure: this way the
@@ -843,15 +960,21 @@ scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph)
if (pinfo->powercaps[domain].fastchannels)
scmi_powercap_domain_init_fc(ph, domain,
&pinfo->powercaps[domain].fc_info);
- }
- pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains,
- sizeof(*pinfo->states), GFP_KERNEL);
- if (!pinfo->states)
- return -ENOMEM;
+ /* Grab initial state when disable is supported. */
+ if (PROTOCOL_REV_MAJOR(version) >= 0x2) {
+ ret = __scmi_powercap_cap_get(ph,
+ &pinfo->powercaps[domain],
+ &pinfo->states[domain].last_pcap);
+ if (ret)
+ return ret;
- pinfo->version = version;
+ pinfo->states[domain].enabled =
+ !!pinfo->states[domain].last_pcap;
+ }
+ }
+ pinfo->version = version;
return ph->set_priv(ph, pinfo);
}
diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c
index 93272e4bbd12..621c37efe3ec 100644
--- a/drivers/firmware/arm_scmi/smc.c
+++ b/drivers/firmware/arm_scmi/smc.c
@@ -20,6 +20,23 @@
#include "common.h"
+/*
+ * The shmem address is split into 4K page and offset.
+ * This is to make sure the parameters fit in 32bit arguments of the
+ * smc/hvc call to keep it uniform across smc32/smc64 conventions.
+ * This however limits the shmem address to 44 bit.
+ *
+ * These optional parameters can be used to distinguish among multiple
+ * scmi instances that are using the same smc-id.
+ * The page parameter is passed in r1/x1/w1 register and the offset parameter
+ * is passed in r2/x2/w2 register.
+ */
+
+#define SHMEM_SIZE (SZ_4K)
+#define SHMEM_SHIFT 12
+#define SHMEM_PAGE(x) (_UL((x) >> SHMEM_SHIFT))
+#define SHMEM_OFFSET(x) ((x) & (SHMEM_SIZE - 1))
+
/**
* struct scmi_smc - Structure representing a SCMI smc transport
*
@@ -30,6 +47,8 @@
* @inflight: Atomic flag to protect access to Tx/Rx shared memory area.
* Used when operating in atomic mode.
* @func_id: smc/hvc call function id
+ * @param_page: 4K page number of the shmem channel
+ * @param_offset: Offset within the 4K page of the shmem channel
*/
struct scmi_smc {
@@ -40,6 +59,8 @@ struct scmi_smc {
#define INFLIGHT_NONE MSG_TOKEN_MAX
atomic_t inflight;
u32 func_id;
+ u32 param_page;
+ u32 param_offset;
};
static irqreturn_t smc_msg_done_isr(int irq, void *data)
@@ -137,6 +158,10 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
if (ret < 0)
return ret;
+ if (of_device_is_compatible(dev->of_node, "arm,scmi-smc-param")) {
+ scmi_info->param_page = SHMEM_PAGE(res.start);
+ scmi_info->param_offset = SHMEM_OFFSET(res.start);
+ }
/*
* If there is an interrupt named "a2p", then the service and
* completion of a message is signaled by an interrupt rather than by
@@ -179,6 +204,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
{
struct scmi_smc *scmi_info = cinfo->transport_info;
struct arm_smccc_res res;
+ unsigned long page = scmi_info->param_page;
+ unsigned long offset = scmi_info->param_offset;
/*
* Channel will be released only once response has been
@@ -188,7 +215,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
shmem_tx_prepare(scmi_info->shmem, xfer, cinfo);
- arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res);
+ arm_smccc_1_1_invoke(scmi_info->func_id, page, offset, 0, 0, 0, 0, 0,
+ &res);
/* Only SMCCC_RET_NOT_SUPPORTED is valid error code */
if (res.a0) {
diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c
index ec056f6f40ce..6a9aa97373d3 100644
--- a/drivers/firmware/cirrus/cs_dsp.c
+++ b/drivers/firmware/cirrus/cs_dsp.c
@@ -2059,10 +2059,10 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
goto out_fw;
}
- cs_dsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
- (le32_to_cpu(hdr->ver) >> 16) & 0xff,
- (le32_to_cpu(hdr->ver) >> 8) & 0xff,
- le32_to_cpu(hdr->ver) & 0xff);
+ cs_dsp_info(dsp, "%s: v%d.%d.%d\n", file,
+ (le32_to_cpu(hdr->ver) >> 16) & 0xff,
+ (le32_to_cpu(hdr->ver) >> 8) & 0xff,
+ le32_to_cpu(hdr->ver) & 0xff);
pos = le32_to_cpu(hdr->len);
diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c
index 03708ab64e56..8d91997036e4 100644
--- a/drivers/firmware/dmi-sysfs.c
+++ b/drivers/firmware/dmi-sysfs.c
@@ -310,6 +310,7 @@ static const struct kobj_type dmi_system_event_log_ktype = {
.default_groups = dmi_sysfs_sel_groups,
};
+#ifdef CONFIG_HAS_IOPORT
typedef u8 (*sel_io_reader)(const struct dmi_system_event_log *sel,
loff_t offset);
@@ -374,6 +375,7 @@ static ssize_t dmi_sel_raw_read_io(struct dmi_sysfs_entry *entry,
return wrote;
}
+#endif
static ssize_t dmi_sel_raw_read_phys32(struct dmi_sysfs_entry *entry,
const struct dmi_system_event_log *sel,
@@ -409,11 +411,13 @@ static ssize_t dmi_sel_raw_read_helper(struct dmi_sysfs_entry *entry,
memcpy(&sel, dh, sizeof(sel));
switch (sel.access_method) {
+#ifdef CONFIG_HAS_IOPORT
case DMI_SEL_ACCESS_METHOD_IO8:
case DMI_SEL_ACCESS_METHOD_IO2x8:
case DMI_SEL_ACCESS_METHOD_IO16:
return dmi_sel_raw_read_io(entry, &sel, state->buf,
state->pos, state->count);
+#endif
case DMI_SEL_ACCESS_METHOD_PHYS32:
return dmi_sel_raw_read_phys32(entry, &sel, state->buf,
state->pos, state->count);
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 3a6ee7bb06f1..1599f1176842 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -214,6 +214,7 @@ static int generic_ops_register(void)
generic_ops.get_variable = efi.get_variable;
generic_ops.get_next_variable = efi.get_next_variable;
generic_ops.query_variable_store = efi_query_variable_store;
+ generic_ops.query_variable_info = efi.query_variable_info;
if (efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE)) {
generic_ops.set_variable = efi.set_variable;
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index 87729c365be1..7a81c0ce4780 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -95,10 +95,6 @@ static ssize_t esre_attr_show(struct kobject *kobj,
struct esre_entry *entry = to_entry(kobj);
struct esre_attribute *attr = to_attr(_attr);
- /* Don't tell normal users what firmware versions we've got... */
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-
return attr->show(entry, buf);
}
@@ -156,7 +152,7 @@ static void esre_release(struct kobject *kobj)
kfree(entry);
}
-static struct kobj_type esre1_ktype = {
+static const struct kobj_type esre1_ktype = {
.release = esre_release,
.sysfs_ops = &esre_attr_ops,
.default_groups = esre1_groups,
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 1e0203d74691..732984295295 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -378,6 +378,9 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv,
struct efi_boot_memmap *map;
efi_status_t status;
+ if (efi_disable_pci_dma)
+ efi_pci_disable_bridge_busmaster();
+
status = efi_get_memory_map(&map, true);
if (status != EFI_SUCCESS)
return status;
@@ -388,9 +391,6 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv,
return status;
}
- if (efi_disable_pci_dma)
- efi_pci_disable_bridge_busmaster();
-
status = efi_bs_call(exit_boot_services, handle, map->map_key);
if (status == EFI_INVALID_PARAMETER) {
diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c
index bfc5fa6aa47b..e9dc7116daf1 100644
--- a/drivers/firmware/efi/vars.c
+++ b/drivers/firmware/efi/vars.c
@@ -245,3 +245,15 @@ efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor,
return status;
}
EXPORT_SYMBOL_NS_GPL(efivar_set_variable, EFIVAR);
+
+efi_status_t efivar_query_variable_info(u32 attr,
+ u64 *storage_space,
+ u64 *remaining_space,
+ u64 *max_variable_size)
+{
+ if (!__efivars->ops->query_variable_info)
+ return EFI_UNSUPPORTED;
+ return __efivars->ops->query_variable_info(attr, storage_space,
+ remaining_space, max_variable_size);
+}
+EXPORT_SYMBOL_NS_GPL(efivar_query_variable_info, EFIVAR);
diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c
index 80f4e2d14e04..2d674126160f 100644
--- a/drivers/firmware/stratix10-svc.c
+++ b/drivers/firmware/stratix10-svc.c
@@ -755,7 +755,7 @@ svc_create_memory_pool(struct platform_device *pdev,
end = rounddown(sh_memory->addr + sh_memory->size, PAGE_SIZE);
paddr = begin;
size = end - begin;
- va = memremap(paddr, size, MEMREMAP_WC);
+ va = devm_memremap(dev, paddr, size, MEMREMAP_WC);
if (!va) {
dev_err(dev, "fail to remap shared memory\n");
return ERR_PTR(-EINVAL);
diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
index 3c197db42c9d..82fcfd29bc4d 100644
--- a/drivers/firmware/sysfb.c
+++ b/drivers/firmware/sysfb.c
@@ -128,4 +128,4 @@ unlock_mutex:
}
/* must execute after PCI subsystem for EFI quirks */
-device_initcall(sysfb_init);
+subsys_initcall_sync(sysfb_init);
diff --git a/drivers/firmware/tegra/bpmp-tegra186.c b/drivers/firmware/tegra/bpmp-tegra186.c
index 2e26199041cd..6f0d0511b486 100644
--- a/drivers/firmware/tegra/bpmp-tegra186.c
+++ b/drivers/firmware/tegra/bpmp-tegra186.c
@@ -4,7 +4,9 @@
*/
#include <linux/genalloc.h>
+#include <linux/io.h>
#include <linux/mailbox_client.h>
+#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <soc/tegra/bpmp.h>
@@ -18,7 +20,10 @@ struct tegra186_bpmp {
struct {
struct gen_pool *pool;
- void __iomem *virt;
+ union {
+ void __iomem *sram;
+ void *dram;
+ };
dma_addr_t phys;
} tx, rx;
@@ -118,8 +123,13 @@ static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
queue_size = tegra_ivc_total_queue_size(message_size);
offset = queue_size * index;
- iosys_map_set_vaddr_iomem(&rx, priv->rx.virt + offset);
- iosys_map_set_vaddr_iomem(&tx, priv->tx.virt + offset);
+ if (priv->rx.pool) {
+ iosys_map_set_vaddr_iomem(&rx, priv->rx.sram + offset);
+ iosys_map_set_vaddr_iomem(&tx, priv->tx.sram + offset);
+ } else {
+ iosys_map_set_vaddr(&rx, priv->rx.dram + offset);
+ iosys_map_set_vaddr(&tx, priv->tx.dram + offset);
+ }
err = tegra_ivc_init(channel->ivc, NULL, &rx, priv->rx.phys + offset, &tx,
priv->tx.phys + offset, 1, message_size, tegra186_bpmp_ivc_notify,
@@ -158,18 +168,72 @@ static void mbox_handle_rx(struct mbox_client *client, void *data)
tegra_bpmp_handle_rx(bpmp);
}
-static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
+static void tegra186_bpmp_teardown_channels(struct tegra_bpmp *bpmp)
{
- struct tegra186_bpmp *priv;
+ struct tegra186_bpmp *priv = bpmp->priv;
unsigned int i;
+
+ for (i = 0; i < bpmp->threaded.count; i++) {
+ if (!bpmp->threaded_channels[i].bpmp)
+ continue;
+
+ tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
+ }
+
+ tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
+ tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
+
+ if (priv->tx.pool) {
+ gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.sram, 4096);
+ gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.sram, 4096);
+ }
+}
+
+static int tegra186_bpmp_dram_init(struct tegra_bpmp *bpmp)
+{
+ struct tegra186_bpmp *priv = bpmp->priv;
+ struct device_node *np;
+ struct resource res;
+ size_t size;
int err;
- priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ np = of_parse_phandle(bpmp->dev->of_node, "memory-region", 0);
+ if (!np)
+ return -ENODEV;
- bpmp->priv = priv;
- priv->parent = bpmp;
+ err = of_address_to_resource(np, 0, &res);
+ if (err < 0) {
+ dev_warn(bpmp->dev, "failed to parse memory region: %d\n", err);
+ return err;
+ }
+
+ size = resource_size(&res);
+
+ if (size < SZ_8K) {
+ dev_warn(bpmp->dev, "DRAM region must be larger than 8 KiB\n");
+ return -EINVAL;
+ }
+
+ priv->tx.phys = res.start;
+ priv->rx.phys = res.start + SZ_4K;
+
+ priv->tx.dram = devm_memremap(bpmp->dev, priv->tx.phys, size,
+ MEMREMAP_WC);
+ if (IS_ERR(priv->tx.dram)) {
+ err = PTR_ERR(priv->tx.dram);
+ dev_warn(bpmp->dev, "failed to map DRAM region: %d\n", err);
+ return err;
+ }
+
+ priv->rx.dram = priv->tx.dram + SZ_4K;
+
+ return 0;
+}
+
+static int tegra186_bpmp_sram_init(struct tegra_bpmp *bpmp)
+{
+ struct tegra186_bpmp *priv = bpmp->priv;
+ int err;
priv->tx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 0);
if (!priv->tx.pool) {
@@ -177,8 +241,9 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
return -EPROBE_DEFER;
}
- priv->tx.virt = (void __iomem *)gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
- if (!priv->tx.virt) {
+ priv->tx.sram = (void __iomem *)gen_pool_dma_alloc(priv->tx.pool, 4096,
+ &priv->tx.phys);
+ if (!priv->tx.sram) {
dev_err(bpmp->dev, "failed to allocate from TX pool\n");
return -ENOMEM;
}
@@ -190,22 +255,45 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
goto free_tx;
}
- priv->rx.virt = (void __iomem *)gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
- if (!priv->rx.virt) {
+ priv->rx.sram = (void __iomem *)gen_pool_dma_alloc(priv->rx.pool, 4096,
+ &priv->rx.phys);
+ if (!priv->rx.sram) {
dev_err(bpmp->dev, "failed to allocate from RX pool\n");
err = -ENOMEM;
goto free_tx;
}
+ return 0;
+
+free_tx:
+ gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.sram, 4096);
+
+ return err;
+}
+
+static int tegra186_bpmp_setup_channels(struct tegra_bpmp *bpmp)
+{
+ unsigned int i;
+ int err;
+
+ err = tegra186_bpmp_dram_init(bpmp);
+ if (err == -ENODEV) {
+ err = tegra186_bpmp_sram_init(bpmp);
+ if (err < 0)
+ return err;
+ }
+
err = tegra186_bpmp_channel_init(bpmp->tx_channel, bpmp,
bpmp->soc->channels.cpu_tx.offset);
if (err < 0)
- goto free_rx;
+ return err;
err = tegra186_bpmp_channel_init(bpmp->rx_channel, bpmp,
bpmp->soc->channels.cpu_rx.offset);
- if (err < 0)
- goto cleanup_tx_channel;
+ if (err < 0) {
+ tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
+ return err;
+ }
for (i = 0; i < bpmp->threaded.count; i++) {
unsigned int index = bpmp->soc->channels.thread.offset + i;
@@ -213,9 +301,43 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
err = tegra186_bpmp_channel_init(&bpmp->threaded_channels[i],
bpmp, index);
if (err < 0)
- goto cleanup_channels;
+ break;
}
+ if (err < 0)
+ tegra186_bpmp_teardown_channels(bpmp);
+
+ return err;
+}
+
+static void tegra186_bpmp_reset_channels(struct tegra_bpmp *bpmp)
+{
+ unsigned int i;
+
+ /* reset message channels */
+ tegra186_bpmp_channel_reset(bpmp->tx_channel);
+ tegra186_bpmp_channel_reset(bpmp->rx_channel);
+
+ for (i = 0; i < bpmp->threaded.count; i++)
+ tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
+}
+
+static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
+{
+ struct tegra186_bpmp *priv;
+ int err;
+
+ priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->parent = bpmp;
+ bpmp->priv = priv;
+
+ err = tegra186_bpmp_setup_channels(bpmp);
+ if (err < 0)
+ return err;
+
/* mbox registration */
priv->mbox.client.dev = bpmp->dev;
priv->mbox.client.rx_callback = mbox_handle_rx;
@@ -226,63 +348,27 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
if (IS_ERR(priv->mbox.channel)) {
err = PTR_ERR(priv->mbox.channel);
dev_err(bpmp->dev, "failed to get HSP mailbox: %d\n", err);
- goto cleanup_channels;
+ tegra186_bpmp_teardown_channels(bpmp);
+ return err;
}
- tegra186_bpmp_channel_reset(bpmp->tx_channel);
- tegra186_bpmp_channel_reset(bpmp->rx_channel);
-
- for (i = 0; i < bpmp->threaded.count; i++)
- tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
+ tegra186_bpmp_reset_channels(bpmp);
return 0;
-
-cleanup_channels:
- for (i = 0; i < bpmp->threaded.count; i++) {
- if (!bpmp->threaded_channels[i].bpmp)
- continue;
-
- tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
- }
-
- tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
-cleanup_tx_channel:
- tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
-free_rx:
- gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
-free_tx:
- gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
-
- return err;
}
static void tegra186_bpmp_deinit(struct tegra_bpmp *bpmp)
{
struct tegra186_bpmp *priv = bpmp->priv;
- unsigned int i;
mbox_free_channel(priv->mbox.channel);
- for (i = 0; i < bpmp->threaded.count; i++)
- tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
-
- tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
- tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
-
- gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
- gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
+ tegra186_bpmp_teardown_channels(bpmp);
}
static int tegra186_bpmp_resume(struct tegra_bpmp *bpmp)
{
- unsigned int i;
-
- /* reset message channels */
- tegra186_bpmp_channel_reset(bpmp->tx_channel);
- tegra186_bpmp_channel_reset(bpmp->rx_channel);
-
- for (i = 0; i < bpmp->threaded.count; i++)
- tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
+ tegra186_bpmp_reset_channels(bpmp);
return 0;
}
diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index 8b5e5daa9fae..17bd3590aaa2 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -735,6 +735,8 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
if (!bpmp->threaded_channels)
return -ENOMEM;
+ platform_set_drvdata(pdev, bpmp);
+
err = bpmp->soc->ops->init(bpmp);
if (err < 0)
return err;
@@ -758,8 +760,6 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "firmware: %.*s\n", (int)sizeof(tag), tag);
- platform_set_drvdata(pdev, bpmp);
-
err = of_platform_default_populate(pdev->dev.of_node, NULL, &pdev->dev);
if (err < 0)
goto free_mrq;
diff --git a/drivers/firmware/xilinx/zynqmp-debug.c b/drivers/firmware/xilinx/zynqmp-debug.c
index 99606b34975e..8528850af889 100644
--- a/drivers/firmware/xilinx/zynqmp-debug.c
+++ b/drivers/firmware/xilinx/zynqmp-debug.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2014-2018 Xilinx, Inc.
*
- * Michal Simek <michal.simek@xilinx.com>
+ * Michal Simek <michal.simek@amd.com>
* Davorin Mista <davorin.mista@aggios.com>
* Jolly Shah <jollys@xilinx.com>
* Rajan Vaja <rajanv@xilinx.com>
diff --git a/drivers/firmware/xilinx/zynqmp-debug.h b/drivers/firmware/xilinx/zynqmp-debug.h
index 9929f8b433f5..e1515a93e9e9 100644
--- a/drivers/firmware/xilinx/zynqmp-debug.h
+++ b/drivers/firmware/xilinx/zynqmp-debug.h
@@ -4,7 +4,7 @@
*
* Copyright (C) 2014-2018 Xilinx
*
- * Michal Simek <michal.simek@xilinx.com>
+ * Michal Simek <michal.simek@amd.com>
* Davorin Mista <davorin.mista@aggios.com>
* Jolly Shah <jollys@xilinx.com>
* Rajan Vaja <rajanv@xilinx.com>
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index a736db4a5825..f8c4eb2b43f8 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2014-2022 Xilinx, Inc.
*
- * Michal Simek <michal.simek@xilinx.com>
+ * Michal Simek <michal.simek@amd.com>
* Davorin Mista <davorin.mista@aggios.com>
* Jolly Shah <jollys@xilinx.com>
* Rajan Vaja <rajanv@xilinx.com>
@@ -942,8 +942,16 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
*/
int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
{
- return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
- upper_32_bits(address), size, flags, NULL);
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+ int ret;
+
+ ret = zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
+ upper_32_bits(address), size, flags,
+ ret_payload);
+ if (ret_payload[0])
+ return -ret_payload[0];
+
+ return ret;
}
EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
index 77ea04d4edbe..bcb5d34b3b82 100644
--- a/drivers/fpga/dfl-fme-main.c
+++ b/drivers/fpga/dfl-fme-main.c
@@ -265,7 +265,7 @@ static const struct hwmon_ops thermal_hwmon_ops = {
.read = thermal_hwmon_read,
};
-static const struct hwmon_channel_info *thermal_hwmon_info[] = {
+static const struct hwmon_channel_info * const thermal_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_EMERGENCY |
HWMON_T_MAX | HWMON_T_MAX_ALARM |
HWMON_T_CRIT | HWMON_T_CRIT_ALARM),
@@ -465,7 +465,7 @@ static const struct hwmon_ops power_hwmon_ops = {
.write = power_hwmon_write,
};
-static const struct hwmon_channel_info *power_hwmon_info[] = {
+static const struct hwmon_channel_info * const power_hwmon_info[] = {
HWMON_CHANNEL_INFO(power, HWMON_P_INPUT |
HWMON_P_MAX | HWMON_P_MAX_ALARM |
HWMON_P_CRIT | HWMON_P_CRIT_ALARM),
diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c
index d7e2f9f461bc..31af2e08c825 100644
--- a/drivers/fpga/intel-m10-bmc-sec-update.c
+++ b/drivers/fpga/intel-m10-bmc-sec-update.c
@@ -376,12 +376,11 @@ static enum fw_upload_err rsu_update_init(struct m10bmc_sec *sec)
u32 doorbell_reg, progress, status;
int ret, err;
- ret = regmap_update_bits(sec->m10bmc->regmap,
- csr_map->base + csr_map->doorbell,
- DRBL_RSU_REQUEST | DRBL_HOST_STATUS,
- DRBL_RSU_REQUEST |
- FIELD_PREP(DRBL_HOST_STATUS,
- HOST_STATUS_IDLE));
+ ret = m10bmc_sys_update_bits(sec->m10bmc, csr_map->doorbell,
+ DRBL_RSU_REQUEST | DRBL_HOST_STATUS,
+ DRBL_RSU_REQUEST |
+ FIELD_PREP(DRBL_HOST_STATUS,
+ HOST_STATUS_IDLE));
if (ret)
return FW_UPLOAD_ERR_RW_ERROR;
@@ -450,11 +449,10 @@ static enum fw_upload_err rsu_send_data(struct m10bmc_sec *sec)
u32 doorbell_reg, status;
int ret;
- ret = regmap_update_bits(sec->m10bmc->regmap,
- csr_map->base + csr_map->doorbell,
- DRBL_HOST_STATUS,
- FIELD_PREP(DRBL_HOST_STATUS,
- HOST_STATUS_WRITE_DONE));
+ ret = m10bmc_sys_update_bits(sec->m10bmc, csr_map->doorbell,
+ DRBL_HOST_STATUS,
+ FIELD_PREP(DRBL_HOST_STATUS,
+ HOST_STATUS_WRITE_DONE));
if (ret)
return FW_UPLOAD_ERR_RW_ERROR;
@@ -517,11 +515,10 @@ static enum fw_upload_err rsu_cancel(struct m10bmc_sec *sec)
if (rsu_prog(doorbell) != RSU_PROG_READY)
return FW_UPLOAD_ERR_BUSY;
- ret = regmap_update_bits(sec->m10bmc->regmap,
- csr_map->base + csr_map->doorbell,
- DRBL_HOST_STATUS,
- FIELD_PREP(DRBL_HOST_STATUS,
- HOST_STATUS_ABORT_RSU));
+ ret = m10bmc_sys_update_bits(sec->m10bmc, csr_map->doorbell,
+ DRBL_HOST_STATUS,
+ FIELD_PREP(DRBL_HOST_STATUS,
+ HOST_STATUS_ABORT_RSU));
if (ret)
return FW_UPLOAD_ERR_RW_ERROR;
@@ -547,21 +544,28 @@ static enum fw_upload_err m10bmc_sec_prepare(struct fw_upload *fwl,
if (ret != FW_UPLOAD_ERR_NONE)
goto unlock_flash;
+ m10bmc_fw_state_set(sec->m10bmc, M10BMC_FW_STATE_SEC_UPDATE_PREPARE);
+
ret = rsu_update_init(sec);
if (ret != FW_UPLOAD_ERR_NONE)
- goto unlock_flash;
+ goto fw_state_exit;
ret = rsu_prog_ready(sec);
if (ret != FW_UPLOAD_ERR_NONE)
- goto unlock_flash;
+ goto fw_state_exit;
if (sec->cancel_request) {
ret = rsu_cancel(sec);
- goto unlock_flash;
+ goto fw_state_exit;
}
+ m10bmc_fw_state_set(sec->m10bmc, M10BMC_FW_STATE_SEC_UPDATE_WRITE);
+
return FW_UPLOAD_ERR_NONE;
+fw_state_exit:
+ m10bmc_fw_state_set(sec->m10bmc, M10BMC_FW_STATE_NORMAL);
+
unlock_flash:
if (sec->m10bmc->flash_bulk_ops)
sec->m10bmc->flash_bulk_ops->unlock_write(sec->m10bmc);
@@ -610,6 +614,8 @@ static enum fw_upload_err m10bmc_sec_poll_complete(struct fw_upload *fwl)
if (sec->cancel_request)
return rsu_cancel(sec);
+ m10bmc_fw_state_set(sec->m10bmc, M10BMC_FW_STATE_SEC_UPDATE_PROGRAM);
+
result = rsu_send_data(sec);
if (result != FW_UPLOAD_ERR_NONE)
return result;
@@ -653,6 +659,8 @@ static void m10bmc_sec_cleanup(struct fw_upload *fwl)
(void)rsu_cancel(sec);
+ m10bmc_fw_state_set(sec->m10bmc, M10BMC_FW_STATE_NORMAL);
+
if (sec->m10bmc->flash_bulk_ops)
sec->m10bmc->flash_bulk_ops->unlock_write(sec->m10bmc);
}
@@ -764,3 +772,4 @@ module_platform_driver(intel_m10bmc_sec_driver);
MODULE_AUTHOR("Intel Corporation");
MODULE_DESCRIPTION("Intel MAX10 BMC Secure Update");
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(INTEL_M10_BMC_CORE);
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index ae0da361e6c6..f8214cae9b6e 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -493,15 +493,15 @@ static int zynq_fpga_ops_write_complete(struct fpga_manager *mgr,
if (err)
return err;
- /* Release 'PR' control back to the ICAP */
- zynq_fpga_write(priv, CTRL_OFFSET,
- zynq_fpga_read(priv, CTRL_OFFSET) & ~CTRL_PCAP_PR_MASK);
-
err = zynq_fpga_poll_timeout(priv, INT_STS_OFFSET, intr_status,
intr_status & IXR_PCFG_DONE_MASK,
INIT_POLL_DELAY,
INIT_POLL_TIMEOUT);
+ /* Release 'PR' control back to the ICAP */
+ zynq_fpga_write(priv, CTRL_OFFSET,
+ zynq_fpga_read(priv, CTRL_OFFSET) & ~CTRL_PCAP_PR_MASK);
+
clk_disable(priv->clk);
if (err)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index f45c6a36551c..e382dfebad7c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -704,18 +704,6 @@ config GPIO_VISCONTI
help
Say yes here to support GPIO on Tohisba Visconti.
-config GPIO_VX855
- tristate "VIA VX855/VX875 GPIO"
- depends on (X86 || COMPILE_TEST) && PCI
- select MFD_CORE
- select MFD_VX855
- help
- Support access to the VX855/VX875 GPIO lines through the GPIO library.
-
- This driver provides common support for accessing the device.
- Additional drivers must be enabled in order to use the
- functionality of the device.
-
config GPIO_WCD934X
tristate "Qualcomm Technologies Inc WCD9340/WCD9341 GPIO controller driver"
depends on MFD_WCD934X && OF_GPIO
@@ -835,7 +823,19 @@ config GPIO_IDT3243X
endmenu
menu "Port-mapped I/O GPIO drivers"
- depends on X86 # Unconditional I/O space access
+ depends on X86 && HAS_IOPORT # I/O space access
+
+config GPIO_VX855
+ tristate "VIA VX855/VX875 GPIO"
+ depends on PCI
+ select MFD_CORE
+ select MFD_VX855
+ help
+ Support access to the VX855/VX875 GPIO lines through the GPIO library.
+
+ This driver provides common support for accessing the device.
+ Additional drivers must be enabled in order to use the
+ functionality of the device.
config GPIO_I8255
tristate
@@ -1440,6 +1440,22 @@ config GPIO_TPS65218
Select this option to enable GPIO driver for the TPS65218
chip family.
+config GPIO_TPS65219
+ tristate "TPS65219 GPIO"
+ depends on MFD_TPS65219
+ default MFD_TPS65219
+ help
+ Select this option to enable GPIO driver for the TPS65219 chip
+ family.
+ GPIO0 is statically configured as either input or output prior to
+ Linux boot. It is used for MULTI_DEVICE_ENABLE function. This setting
+ is statically configured by NVM. GPIO0 can't be used as a generic
+ GPIO. It's either a GPO when MULTI_DEVICE_EN=0 or a GPI when
+ MULTI_DEVICE_EN=1.
+
+ This driver can also be built as a module. If so, the module will be
+ called gpio_tps65219.
+
config GPIO_TPS6586X
bool "TPS6586X GPIO"
depends on MFD_TPS6586X
@@ -1583,6 +1599,19 @@ config GPIO_MLXBF2
help
Say Y here if you want GPIO support on Mellanox BlueField 2 SoC.
+config GPIO_MLXBF3
+ tristate "Mellanox BlueField 3 SoC GPIO"
+ depends on (MELLANOX_PLATFORM && ARM64) || COMPILE_TEST
+ select GPIO_GENERIC
+ select GPIOLIB_IRQCHIP
+ help
+ Say Y if you want GPIO support on Mellanox BlueField 3 SoC.
+ This GPIO controller supports interrupt handling and enables the
+ manipulation of certain GPIO pins.
+ This controller should be used in parallel with pinctrl-mlxbf3 to
+ control the desired GPIOs.
+ This driver can also be built as a module called mlxbf3-gpio.
+
config GPIO_ML_IOH
tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
depends on X86 || COMPILE_TEST
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 20036af3acb1..c3ac51d47aa9 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -104,6 +104,7 @@ obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o
obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
obj-$(CONFIG_GPIO_MLXBF) += gpio-mlxbf.o
obj-$(CONFIG_GPIO_MLXBF2) += gpio-mlxbf2.o
+obj-$(CONFIG_GPIO_MLXBF3) += gpio-mlxbf3.o
obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o
obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o
obj-$(CONFIG_GPIO_MOXTET) += gpio-moxtet.o
@@ -160,6 +161,7 @@ obj-$(CONFIG_GPIO_TN48M_CPLD) += gpio-tn48m.o
obj-$(CONFIG_GPIO_TPIC2810) += gpio-tpic2810.o
obj-$(CONFIG_GPIO_TPS65086) += gpio-tps65086.o
obj-$(CONFIG_GPIO_TPS65218) += gpio-tps65218.o
+obj-$(CONFIG_GPIO_TPS65219) += gpio-tps65219.o
obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index 9b01c391efce..6dafab0cf964 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -535,7 +535,7 @@ static struct i2c_driver adnp_i2c_driver = {
.name = "gpio-adnp",
.of_match_table = adnp_of_match,
},
- .probe_new = adnp_i2c_probe,
+ .probe = adnp_i2c_probe,
.id_table = adnp_i2c_id,
};
module_i2c_driver(adnp_i2c_driver);
diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c
index 20a686f12df7..38e0fff9afe7 100644
--- a/drivers/gpio/gpio-aggregator.c
+++ b/drivers/gpio/gpio-aggregator.c
@@ -10,12 +10,15 @@
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/ctype.h>
+#include <linux/delay.h>
#include <linux/idr.h>
#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/overflow.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
@@ -239,6 +242,11 @@ static void __exit gpio_aggregator_remove_all(void)
* GPIO Forwarder
*/
+struct gpiochip_fwd_timing {
+ u32 ramp_up_us;
+ u32 ramp_down_us;
+};
+
struct gpiochip_fwd {
struct gpio_chip chip;
struct gpio_desc **descs;
@@ -246,6 +254,7 @@ struct gpiochip_fwd {
struct mutex mlock; /* protects tmp[] if can_sleep */
spinlock_t slock; /* protects tmp[] if !can_sleep */
};
+ struct gpiochip_fwd_timing *delay_timings;
unsigned long tmp[]; /* values and descs for multiple ops */
};
@@ -330,6 +339,27 @@ static int gpio_fwd_get_multiple_locked(struct gpio_chip *chip,
return error;
}
+static void gpio_fwd_delay(struct gpio_chip *chip, unsigned int offset, int value)
+{
+ struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
+ const struct gpiochip_fwd_timing *delay_timings;
+ bool is_active_low = gpiod_is_active_low(fwd->descs[offset]);
+ u32 delay_us;
+
+ delay_timings = &fwd->delay_timings[offset];
+ if ((!is_active_low && value) || (is_active_low && !value))
+ delay_us = delay_timings->ramp_up_us;
+ else
+ delay_us = delay_timings->ramp_down_us;
+ if (!delay_us)
+ return;
+
+ if (chip->can_sleep)
+ fsleep(delay_us);
+ else
+ udelay(delay_us);
+}
+
static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value)
{
struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
@@ -338,6 +368,9 @@ static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value)
gpiod_set_value_cansleep(fwd->descs[offset], value);
else
gpiod_set_value(fwd->descs[offset], value);
+
+ if (fwd->delay_timings)
+ gpio_fwd_delay(chip, offset, value);
}
static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask,
@@ -390,6 +423,59 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset)
return gpiod_to_irq(fwd->descs[offset]);
}
+/*
+ * The GPIO delay provides a way to configure platform specific delays
+ * for the GPIO ramp-up or ramp-down delays. This can serve the following
+ * purposes:
+ * - Open-drain output using an RC filter
+ */
+#define FWD_FEATURE_DELAY BIT(0)
+
+#ifdef CONFIG_OF_GPIO
+static int gpiochip_fwd_delay_of_xlate(struct gpio_chip *chip,
+ const struct of_phandle_args *gpiospec,
+ u32 *flags)
+{
+ struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
+ struct gpiochip_fwd_timing *timings;
+ u32 line;
+
+ if (gpiospec->args_count != chip->of_gpio_n_cells)
+ return -EINVAL;
+
+ line = gpiospec->args[0];
+ if (line >= chip->ngpio)
+ return -EINVAL;
+
+ timings = &fwd->delay_timings[line];
+ timings->ramp_up_us = gpiospec->args[1];
+ timings->ramp_down_us = gpiospec->args[2];
+
+ return line;
+}
+
+static int gpiochip_fwd_setup_delay_line(struct device *dev, struct gpio_chip *chip,
+ struct gpiochip_fwd *fwd)
+{
+ fwd->delay_timings = devm_kcalloc(dev, chip->ngpio,
+ sizeof(*fwd->delay_timings),
+ GFP_KERNEL);
+ if (!fwd->delay_timings)
+ return -ENOMEM;
+
+ chip->of_xlate = gpiochip_fwd_delay_of_xlate;
+ chip->of_gpio_n_cells = 3;
+
+ return 0;
+}
+#else
+static int gpiochip_fwd_setup_delay_line(struct device *dev, struct gpio_chip *chip,
+ struct gpiochip_fwd *fwd)
+{
+ return 0;
+}
+#endif /* !CONFIG_OF_GPIO */
+
/**
* gpiochip_fwd_create() - Create a new GPIO forwarder
* @dev: Parent device pointer
@@ -397,6 +483,7 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset)
* @descs: Array containing the GPIO descriptors to forward to.
* This array must contain @ngpios entries, and must not be deallocated
* before the forwarder has been destroyed again.
+ * @features: Bitwise ORed features as defined with FWD_FEATURE_*.
*
* This function creates a new gpiochip, which forwards all GPIO operations to
* the passed GPIO descriptors.
@@ -406,7 +493,8 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset)
*/
static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev,
unsigned int ngpios,
- struct gpio_desc *descs[])
+ struct gpio_desc *descs[],
+ unsigned long features)
{
const char *label = dev_name(dev);
struct gpiochip_fwd *fwd;
@@ -459,6 +547,12 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev,
else
spin_lock_init(&fwd->slock);
+ if (features & FWD_FEATURE_DELAY) {
+ error = gpiochip_fwd_setup_delay_line(dev, chip, fwd);
+ if (error)
+ return ERR_PTR(error);
+ }
+
error = devm_gpiochip_add_data(dev, chip, fwd);
if (error)
return ERR_PTR(error);
@@ -476,6 +570,7 @@ static int gpio_aggregator_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct gpio_desc **descs;
struct gpiochip_fwd *fwd;
+ unsigned long features;
int i, n;
n = gpiod_count(dev, NULL);
@@ -492,7 +587,8 @@ static int gpio_aggregator_probe(struct platform_device *pdev)
return PTR_ERR(descs[i]);
}
- fwd = gpiochip_fwd_create(dev, n, descs);
+ features = (uintptr_t)device_get_match_data(dev);
+ fwd = gpiochip_fwd_create(dev, n, descs, features);
if (IS_ERR(fwd))
return PTR_ERR(fwd);
@@ -500,23 +596,25 @@ static int gpio_aggregator_probe(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_OF
static const struct of_device_id gpio_aggregator_dt_ids[] = {
+ {
+ .compatible = "gpio-delay",
+ .data = (void *)FWD_FEATURE_DELAY,
+ },
/*
* Add GPIO-operated devices controlled from userspace below,
- * or use "driver_override" in sysfs
+ * or use "driver_override" in sysfs.
*/
{}
};
MODULE_DEVICE_TABLE(of, gpio_aggregator_dt_ids);
-#endif
static struct platform_driver gpio_aggregator_driver = {
.probe = gpio_aggregator_probe,
.driver = {
.name = DRV_NAME,
.groups = gpio_aggregator_groups,
- .of_match_table = of_match_ptr(gpio_aggregator_dt_ids),
+ .of_match_table = gpio_aggregator_dt_ids,
},
};
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c
index c55b35da61a0..6566517fe0d8 100644
--- a/drivers/gpio/gpio-brcmstb.c
+++ b/drivers/gpio/gpio-brcmstb.c
@@ -609,8 +609,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
INIT_LIST_HEAD(&priv->bank_list);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- reg_base = devm_ioremap_resource(dev, res);
+ reg_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(reg_base))
return PTR_ERR(reg_base);
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index aaaf61dc2632..fff510d86e31 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -692,7 +692,7 @@ static int davinci_gpio_resume(struct device *dev)
return 0;
}
-DEFINE_SIMPLE_DEV_PM_OPS(davinci_gpio_dev_pm_ops, davinci_gpio_suspend,
+static DEFINE_SIMPLE_DEV_PM_OPS(davinci_gpio_dev_pm_ops, davinci_gpio_suspend,
davinci_gpio_resume);
static const struct of_device_id davinci_gpio_ids[] = {
@@ -712,7 +712,7 @@ static struct platform_driver davinci_gpio_driver = {
},
};
-/**
+/*
* GPIO driver registration needs to be done before machine_init functions
* access GPIO. Hence davinci_gpio_drv_reg() is a postcore_initcall.
*/
diff --git a/drivers/gpio/gpio-fxl6408.c b/drivers/gpio/gpio-fxl6408.c
index 208fa851e82a..c14b5cc5e519 100644
--- a/drivers/gpio/gpio-fxl6408.c
+++ b/drivers/gpio/gpio-fxl6408.c
@@ -148,7 +148,7 @@ static struct i2c_driver fxl6408_driver = {
.name = "fxl6408",
.of_match_table = fxl6408_dt_ids,
},
- .probe_new = fxl6408_probe,
+ .probe = fxl6408_probe,
.id_table = fxl6408_id,
};
module_i2c_driver(fxl6408_driver);
diff --git a/drivers/gpio/gpio-gw-pld.c b/drivers/gpio/gpio-gw-pld.c
index 5057fa9ad610..899335da93c7 100644
--- a/drivers/gpio/gpio-gw-pld.c
+++ b/drivers/gpio/gpio-gw-pld.c
@@ -125,7 +125,7 @@ static struct i2c_driver gw_pld_driver = {
.name = "gw_pld",
.of_match_table = gw_pld_dt_ids,
},
- .probe_new = gw_pld_probe,
+ .probe = gw_pld_probe,
.id_table = gw_pld_id,
};
module_i2c_driver(gw_pld_driver);
diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c
index 56656fb519f8..1e29de1671d4 100644
--- a/drivers/gpio/gpio-ixp4xx.c
+++ b/drivers/gpio/gpio-ixp4xx.c
@@ -199,7 +199,6 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct irq_domain *parent;
- struct resource *res;
struct ixp4xx_gpio *g;
struct gpio_irq_chip *girq;
struct device_node *irq_parent;
@@ -210,8 +209,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
return -ENOMEM;
g->dev = dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- g->base = devm_ioremap_resource(dev, res);
+ g->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(g->base))
return PTR_ERR(g->base);
diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c
index d711ae06747e..ed3f653a1dfc 100644
--- a/drivers/gpio/gpio-lpc18xx.c
+++ b/drivers/gpio/gpio-lpc18xx.c
@@ -14,7 +14,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
-#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c
index cf482f4f0098..31c2b95321cc 100644
--- a/drivers/gpio/gpio-max7300.c
+++ b/drivers/gpio/gpio-max7300.c
@@ -62,7 +62,7 @@ static struct i2c_driver max7300_driver = {
.driver = {
.name = "max7300",
},
- .probe_new = max7300_probe,
+ .probe = max7300_probe,
.remove = max7300_remove,
.id_table = max7300_id,
};
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
index 7f2fde191755..fca9ca68e387 100644
--- a/drivers/gpio/gpio-max732x.c
+++ b/drivers/gpio/gpio-max732x.c
@@ -711,7 +711,7 @@ static struct i2c_driver max732x_driver = {
.name = "max732x",
.of_match_table = of_match_ptr(max732x_of_table),
},
- .probe_new = max732x_probe,
+ .probe = max732x_probe,
.id_table = max732x_id,
};
diff --git a/drivers/gpio/gpio-mlxbf3.c b/drivers/gpio/gpio-mlxbf3.c
new file mode 100644
index 000000000000..e30cee108986
--- /dev/null
+++ b/drivers/gpio/gpio-mlxbf3.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause
+/* Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+/*
+ * There are 2 YU GPIO blocks:
+ * gpio[0]: HOST_GPIO0->HOST_GPIO31
+ * gpio[1]: HOST_GPIO32->HOST_GPIO55
+ */
+#define MLXBF3_GPIO_MAX_PINS_PER_BLOCK 32
+
+/*
+ * fw_gpio[x] block registers and their offset
+ */
+#define MLXBF_GPIO_FW_OUTPUT_ENABLE_SET 0x00
+#define MLXBF_GPIO_FW_DATA_OUT_SET 0x04
+
+#define MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR 0x00
+#define MLXBF_GPIO_FW_DATA_OUT_CLEAR 0x04
+
+#define MLXBF_GPIO_CAUSE_RISE_EN 0x00
+#define MLXBF_GPIO_CAUSE_FALL_EN 0x04
+#define MLXBF_GPIO_READ_DATA_IN 0x08
+
+#define MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x00
+#define MLXBF_GPIO_CAUSE_OR_EVTEN0 0x14
+#define MLXBF_GPIO_CAUSE_OR_CLRCAUSE 0x18
+
+struct mlxbf3_gpio_context {
+ struct gpio_chip gc;
+
+ /* YU GPIO block address */
+ void __iomem *gpio_set_io;
+ void __iomem *gpio_clr_io;
+ void __iomem *gpio_io;
+
+ /* YU GPIO cause block address */
+ void __iomem *gpio_cause_io;
+};
+
+static void mlxbf3_gpio_irq_enable(struct irq_data *irqd)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+ struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc);
+ irq_hw_number_t offset = irqd_to_hwirq(irqd);
+ unsigned long flags;
+ u32 val;
+
+ gpiochip_enable_irq(gc, offset);
+
+ raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags);
+ writel(BIT(offset), gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE);
+
+ val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0);
+ val |= BIT(offset);
+ writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0);
+ raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);
+}
+
+static void mlxbf3_gpio_irq_disable(struct irq_data *irqd)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+ struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc);
+ irq_hw_number_t offset = irqd_to_hwirq(irqd);
+ unsigned long flags;
+ u32 val;
+
+ raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags);
+ val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0);
+ val &= ~BIT(offset);
+ writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0);
+ raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);
+
+ gpiochip_disable_irq(gc, offset);
+}
+
+static irqreturn_t mlxbf3_gpio_irq_handler(int irq, void *ptr)
+{
+ struct mlxbf3_gpio_context *gs = ptr;
+ struct gpio_chip *gc = &gs->gc;
+ unsigned long pending;
+ u32 level;
+
+ pending = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0);
+ writel(pending, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE);
+
+ for_each_set_bit(level, &pending, gc->ngpio)
+ generic_handle_domain_irq(gc->irq.domain, level);
+
+ return IRQ_RETVAL(pending);
+}
+
+static int
+mlxbf3_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+ struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc);
+ irq_hw_number_t offset = irqd_to_hwirq(irqd);
+ unsigned long flags;
+ u32 val;
+
+ raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags);
+
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_BOTH:
+ val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN);
+ val |= BIT(offset);
+ writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN);
+ val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN);
+ val |= BIT(offset);
+ writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN);
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN);
+ val |= BIT(offset);
+ writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN);
+ val |= BIT(offset);
+ writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN);
+ break;
+ default:
+ raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);
+ return -EINVAL;
+ }
+
+ raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);
+
+ irq_set_handler_locked(irqd, handle_edge_irq);
+
+ return 0;
+}
+
+/* This function needs to be defined for handle_edge_irq() */
+static void mlxbf3_gpio_irq_ack(struct irq_data *data)
+{
+}
+
+static const struct irq_chip gpio_mlxbf3_irqchip = {
+ .name = "MLNXBF33",
+ .irq_ack = mlxbf3_gpio_irq_ack,
+ .irq_set_type = mlxbf3_gpio_irq_set_type,
+ .irq_enable = mlxbf3_gpio_irq_enable,
+ .irq_disable = mlxbf3_gpio_irq_disable,
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static int mlxbf3_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mlxbf3_gpio_context *gs;
+ struct gpio_irq_chip *girq;
+ struct gpio_chip *gc;
+ int ret, irq;
+
+ gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL);
+ if (!gs)
+ return -ENOMEM;
+
+ gs->gpio_io = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(gs->gpio_io))
+ return PTR_ERR(gs->gpio_io);
+
+ gs->gpio_cause_io = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(gs->gpio_cause_io))
+ return PTR_ERR(gs->gpio_cause_io);
+
+ gs->gpio_set_io = devm_platform_ioremap_resource(pdev, 2);
+ if (IS_ERR(gs->gpio_set_io))
+ return PTR_ERR(gs->gpio_set_io);
+
+ gs->gpio_clr_io = devm_platform_ioremap_resource(pdev, 3);
+ if (IS_ERR(gs->gpio_clr_io))
+ return PTR_ERR(gs->gpio_clr_io);
+ gc = &gs->gc;
+
+ ret = bgpio_init(gc, dev, 4,
+ gs->gpio_io + MLXBF_GPIO_READ_DATA_IN,
+ gs->gpio_set_io + MLXBF_GPIO_FW_DATA_OUT_SET,
+ gs->gpio_clr_io + MLXBF_GPIO_FW_DATA_OUT_CLEAR,
+ gs->gpio_set_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_SET,
+ gs->gpio_clr_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR, 0);
+
+ gc->request = gpiochip_generic_request;
+ gc->free = gpiochip_generic_free;
+ gc->owner = THIS_MODULE;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq >= 0) {
+ girq = &gs->gc.irq;
+ gpio_irq_chip_set_chip(girq, &gpio_mlxbf3_irqchip);
+ girq->default_type = IRQ_TYPE_NONE;
+ /* This will let us handle the parent IRQ in the driver */
+ girq->num_parents = 0;
+ girq->parents = NULL;
+ girq->parent_handler = NULL;
+ girq->handler = handle_bad_irq;
+
+ /*
+ * Directly request the irq here instead of passing
+ * a flow-handler because the irq is shared.
+ */
+ ret = devm_request_irq(dev, irq, mlxbf3_gpio_irq_handler,
+ IRQF_SHARED, dev_name(dev), gs);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to request IRQ");
+ }
+
+ platform_set_drvdata(pdev, gs);
+
+ ret = devm_gpiochip_add_data(dev, &gs->gc, gs);
+ if (ret)
+ dev_err_probe(dev, ret, "Failed adding memory mapped gpiochip\n");
+
+ return 0;
+}
+
+static const struct acpi_device_id mlxbf3_gpio_acpi_match[] = {
+ { "MLNXBF33", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, mlxbf3_gpio_acpi_match);
+
+static struct platform_driver mlxbf3_gpio_driver = {
+ .driver = {
+ .name = "mlxbf3_gpio",
+ .acpi_match_table = mlxbf3_gpio_acpi_match,
+ },
+ .probe = mlxbf3_gpio_probe,
+};
+module_platform_driver(mlxbf3_gpio_driver);
+
+MODULE_DESCRIPTION("NVIDIA BlueField-3 GPIO Driver");
+MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c
index 3eb08cd1fdc0..5979a36bf754 100644
--- a/drivers/gpio/gpio-mpc8xxx.c
+++ b/drivers/gpio/gpio-mpc8xxx.c
@@ -12,7 +12,6 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
@@ -375,8 +374,12 @@ static int mpc8xxx_probe(struct platform_device *pdev)
if (of_device_is_compatible(np, "fsl,qoriq-gpio") ||
of_device_is_compatible(np, "fsl,ls1028a-gpio") ||
of_device_is_compatible(np, "fsl,ls1088a-gpio") ||
- is_acpi_node(fwnode))
+ is_acpi_node(fwnode)) {
gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
+ /* Also, latch state of GPIOs configured as output by bootloader. */
+ gc->bgpio_data = gc->read_reg(mpc8xxx_gc->regs + GPIO_DAT) &
+ gc->read_reg(mpc8xxx_gc->regs + GPIO_DIR);
+ }
ret = devm_gpiochip_add_data(&pdev->dev, gc, mpc8xxx_gc);
if (ret) {
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 1286b22ef23a..a806a3c1b801 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -1375,7 +1375,7 @@ static struct i2c_driver pca953x_driver = {
.of_match_table = pca953x_dt_ids,
.acpi_match_table = pca953x_acpi_ids,
},
- .probe_new = pca953x_probe,
+ .probe = pca953x_probe,
.remove = pca953x_remove,
.id_table = pca953x_id,
};
diff --git a/drivers/gpio/gpio-pca9570.c b/drivers/gpio/gpio-pca9570.c
index 6a5a8e593ed5..d8db80ef1293 100644
--- a/drivers/gpio/gpio-pca9570.c
+++ b/drivers/gpio/gpio-pca9570.c
@@ -175,7 +175,7 @@ static struct i2c_driver pca9570_driver = {
.name = "pca9570",
.of_match_table = pca9570_of_match_table,
},
- .probe_new = pca9570_probe,
+ .probe = pca9570_probe,
.id_table = pca9570_id_table,
};
module_i2c_driver(pca9570_driver);
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index 3de1d3ad7472..c4c785548408 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -419,7 +419,7 @@ static struct i2c_driver pcf857x_driver = {
.name = "pcf857x",
.of_match_table = pcf857x_of_table,
},
- .probe_new = pcf857x_probe,
+ .probe = pcf857x_probe,
.shutdown = pcf857x_shutdown,
.id_table = pcf857x_id,
};
diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c
index edff5e81489f..242dad763ac4 100644
--- a/drivers/gpio/gpio-sa1100.c
+++ b/drivers/gpio/gpio-sa1100.c
@@ -12,6 +12,7 @@
#include <soc/sa1100/pwer.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
+#include <mach/generic.h>
struct sa1100_gpio_chip {
struct gpio_chip chip;
diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c
index da01e1cad7cb..ba4fccf3cc94 100644
--- a/drivers/gpio/gpio-sch311x.c
+++ b/drivers/gpio/gpio-sch311x.c
@@ -281,8 +281,6 @@ static int sch311x_gpio_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- platform_set_drvdata(pdev, priv);
-
for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) {
block = &priv->blocks[i];
@@ -305,42 +303,22 @@ static int sch311x_gpio_probe(struct platform_device *pdev)
block->data_reg = sch311x_gpio_blocks[i].data_reg;
block->runtime_reg = pdata->runtime_reg;
- err = gpiochip_add_data(&block->chip, block);
+ err = devm_gpiochip_add_data(&pdev->dev, &block->chip, block);
if (err < 0) {
dev_err(&pdev->dev,
"Could not register gpiochip, %d\n", err);
- goto exit_err;
+ return err;
}
dev_info(&pdev->dev,
"SMSC SCH311x GPIO block %d registered.\n", i);
}
return 0;
-
-exit_err:
- /* release already registered chips */
- for (--i; i >= 0; i--)
- gpiochip_remove(&priv->blocks[i].chip);
- return err;
-}
-
-static int sch311x_gpio_remove(struct platform_device *pdev)
-{
- struct sch311x_gpio_priv *priv = platform_get_drvdata(pdev);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) {
- gpiochip_remove(&priv->blocks[i].chip);
- dev_info(&pdev->dev,
- "SMSC SCH311x GPIO block %d unregistered.\n", i);
- }
- return 0;
}
static struct platform_driver sch311x_gpio_driver = {
.driver.name = DRV_NAME,
.probe = sch311x_gpio_probe,
- .remove = sch311x_gpio_remove,
};
diff --git a/drivers/gpio/gpio-tangier.c b/drivers/gpio/gpio-tangier.c
index e990781935ba..7ce3eddaed25 100644
--- a/drivers/gpio/gpio-tangier.c
+++ b/drivers/gpio/gpio-tangier.c
@@ -16,6 +16,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/math.h>
#include <linux/module.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/spinlock.h>
@@ -428,10 +429,11 @@ static int tng_gpio_add_pin_ranges(struct gpio_chip *chip)
int devm_tng_gpio_probe(struct device *dev, struct tng_gpio *gpio)
{
const struct tng_gpio_info *info = &gpio->info;
+ size_t nctx = DIV_ROUND_UP(info->ngpio, 32);
struct gpio_irq_chip *girq;
int ret;
- gpio->ctx = devm_kcalloc(dev, DIV_ROUND_UP(info->ngpio, 32), sizeof(*gpio->ctx), GFP_KERNEL);
+ gpio->ctx = devm_kcalloc(dev, nctx, sizeof(*gpio->ctx), GFP_KERNEL);
if (!gpio->ctx)
return -ENOMEM;
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
index b904de0b1784..80d08ddde40e 100644
--- a/drivers/gpio/gpio-tegra186.c
+++ b/drivers/gpio/gpio-tegra186.c
@@ -27,6 +27,22 @@
#define TEGRA186_GPIO_INT_ROUTE_MAPPING(p, x) (0x14 + (p) * 0x20 + (x) * 4)
+#define TEGRA186_GPIO_VM 0x00
+#define TEGRA186_GPIO_VM_RW_MASK 0x03
+#define TEGRA186_GPIO_SCR 0x04
+#define TEGRA186_GPIO_SCR_PIN_SIZE 0x08
+#define TEGRA186_GPIO_SCR_PORT_SIZE 0x40
+#define TEGRA186_GPIO_SCR_SEC_WEN BIT(28)
+#define TEGRA186_GPIO_SCR_SEC_REN BIT(27)
+#define TEGRA186_GPIO_SCR_SEC_G1W BIT(9)
+#define TEGRA186_GPIO_SCR_SEC_G1R BIT(1)
+#define TEGRA186_GPIO_FULL_ACCESS (TEGRA186_GPIO_SCR_SEC_WEN | \
+ TEGRA186_GPIO_SCR_SEC_REN | \
+ TEGRA186_GPIO_SCR_SEC_G1R | \
+ TEGRA186_GPIO_SCR_SEC_G1W)
+#define TEGRA186_GPIO_SCR_SEC_ENABLE (TEGRA186_GPIO_SCR_SEC_WEN | \
+ TEGRA186_GPIO_SCR_SEC_REN)
+
/* control registers */
#define TEGRA186_GPIO_ENABLE_CONFIG 0x00
#define TEGRA186_GPIO_ENABLE_CONFIG_ENABLE BIT(0)
@@ -81,6 +97,7 @@ struct tegra_gpio_soc {
unsigned int num_pin_ranges;
const char *pinmux;
bool has_gte;
+ bool has_vm_support;
};
struct tegra_gpio {
@@ -130,6 +147,58 @@ static void __iomem *tegra186_gpio_get_base(struct tegra_gpio *gpio,
return gpio->base + offset + pin * 0x20;
}
+static void __iomem *tegra186_gpio_get_secure_base(struct tegra_gpio *gpio,
+ unsigned int pin)
+{
+ const struct tegra_gpio_port *port;
+ unsigned int offset;
+
+ port = tegra186_gpio_get_port(gpio, &pin);
+ if (!port)
+ return NULL;
+
+ offset = port->bank * 0x1000 + port->port * TEGRA186_GPIO_SCR_PORT_SIZE;
+
+ return gpio->secure + offset + pin * TEGRA186_GPIO_SCR_PIN_SIZE;
+}
+
+static inline bool tegra186_gpio_is_accessible(struct tegra_gpio *gpio, unsigned int pin)
+{
+ void __iomem *secure;
+ u32 value;
+
+ secure = tegra186_gpio_get_secure_base(gpio, pin);
+
+ if (gpio->soc->has_vm_support) {
+ value = readl(secure + TEGRA186_GPIO_VM);
+ if ((value & TEGRA186_GPIO_VM_RW_MASK) != TEGRA186_GPIO_VM_RW_MASK)
+ return false;
+ }
+
+ value = __raw_readl(secure + TEGRA186_GPIO_SCR);
+
+ if ((value & TEGRA186_GPIO_SCR_SEC_ENABLE) == 0)
+ return true;
+
+ if ((value & TEGRA186_GPIO_FULL_ACCESS) == TEGRA186_GPIO_FULL_ACCESS)
+ return true;
+
+ return false;
+}
+
+static int tegra186_init_valid_mask(struct gpio_chip *chip,
+ unsigned long *valid_mask, unsigned int ngpios)
+{
+ struct tegra_gpio *gpio = gpiochip_get_data(chip);
+ unsigned int j;
+
+ for (j = 0; j < ngpios; j++) {
+ if (!tegra186_gpio_is_accessible(gpio, j))
+ clear_bit(j, valid_mask);
+ }
+ return 0;
+}
+
static int tegra186_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
@@ -816,6 +885,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
gpio->gpio.set = tegra186_gpio_set;
gpio->gpio.set_config = tegra186_gpio_set_config;
gpio->gpio.add_pin_ranges = tegra186_gpio_add_pin_ranges;
+ gpio->gpio.init_valid_mask = tegra186_init_valid_mask;
if (gpio->soc->has_gte) {
gpio->gpio.en_hw_timestamp = tegra186_gpio_en_hw_ts;
gpio->gpio.dis_hw_timestamp = tegra186_gpio_dis_hw_ts;
@@ -894,11 +964,15 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
np = of_find_matching_node(NULL, tegra186_pmc_of_match);
if (np) {
- irq->parent_domain = irq_find_host(np);
- of_node_put(np);
-
- if (!irq->parent_domain)
- return -EPROBE_DEFER;
+ if (of_device_is_available(np)) {
+ irq->parent_domain = irq_find_host(np);
+ of_node_put(np);
+
+ if (!irq->parent_domain)
+ return -EPROBE_DEFER;
+ } else {
+ of_node_put(np);
+ }
}
irq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio,
@@ -958,6 +1032,7 @@ static const struct tegra_gpio_soc tegra186_main_soc = {
.name = "tegra186-gpio",
.instance = 0,
.num_irqs_per_bank = 1,
+ .has_vm_support = false,
};
#define TEGRA186_AON_GPIO_PORT(_name, _bank, _port, _pins) \
@@ -985,6 +1060,7 @@ static const struct tegra_gpio_soc tegra186_aon_soc = {
.name = "tegra186-gpio-aon",
.instance = 1,
.num_irqs_per_bank = 1,
+ .has_vm_support = false,
};
#define TEGRA194_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \
@@ -1040,6 +1116,7 @@ static const struct tegra_gpio_soc tegra194_main_soc = {
.num_pin_ranges = ARRAY_SIZE(tegra194_main_pin_ranges),
.pin_ranges = tegra194_main_pin_ranges,
.pinmux = "nvidia,tegra194-pinmux",
+ .has_vm_support = true,
};
#define TEGRA194_AON_GPIO_PORT(_name, _bank, _port, _pins) \
@@ -1065,6 +1142,7 @@ static const struct tegra_gpio_soc tegra194_aon_soc = {
.instance = 1,
.num_irqs_per_bank = 8,
.has_gte = true,
+ .has_vm_support = false,
};
#define TEGRA234_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \
@@ -1109,6 +1187,7 @@ static const struct tegra_gpio_soc tegra234_main_soc = {
.name = "tegra234-gpio",
.instance = 0,
.num_irqs_per_bank = 8,
+ .has_vm_support = true,
};
#define TEGRA234_AON_GPIO_PORT(_name, _bank, _port, _pins) \
@@ -1135,6 +1214,7 @@ static const struct tegra_gpio_soc tegra234_aon_soc = {
.instance = 1,
.num_irqs_per_bank = 8,
.has_gte = true,
+ .has_vm_support = false,
};
#define TEGRA241_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \
@@ -1165,6 +1245,7 @@ static const struct tegra_gpio_soc tegra241_main_soc = {
.name = "tegra241-gpio",
.instance = 0,
.num_irqs_per_bank = 8,
+ .has_vm_support = false,
};
#define TEGRA241_AON_GPIO_PORT(_name, _bank, _port, _pins) \
@@ -1186,6 +1267,7 @@ static const struct tegra_gpio_soc tegra241_aon_soc = {
.name = "tegra241-gpio-aon",
.instance = 1,
.num_irqs_per_bank = 8,
+ .has_vm_support = false,
};
static const struct of_device_id tegra186_gpio_of_match[] = {
diff --git a/drivers/gpio/gpio-tpic2810.c b/drivers/gpio/gpio-tpic2810.c
index 349c5fbd9b02..effb7b8ff81f 100644
--- a/drivers/gpio/gpio-tpic2810.c
+++ b/drivers/gpio/gpio-tpic2810.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
- * Andrew F. Davis <afd@ti.com>
+ * Copyright (C) 2015-2023 Texas Instruments Incorporated - https://www.ti.com/
+ * Andrew Davis <afd@ti.com>
*/
#include <linux/gpio/driver.h>
@@ -101,14 +101,11 @@ MODULE_DEVICE_TABLE(of, tpic2810_of_match_table);
static int tpic2810_probe(struct i2c_client *client)
{
struct tpic2810 *gpio;
- int ret;
gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
return -ENOMEM;
- i2c_set_clientdata(client, gpio);
-
gpio->chip = template_chip;
gpio->chip.parent = &client->dev;
@@ -116,20 +113,7 @@ static int tpic2810_probe(struct i2c_client *client)
mutex_init(&gpio->lock);
- ret = gpiochip_add_data(&gpio->chip, gpio);
- if (ret < 0) {
- dev_err(&client->dev, "Unable to register gpiochip\n");
- return ret;
- }
-
- return 0;
-}
-
-static void tpic2810_remove(struct i2c_client *client)
-{
- struct tpic2810 *gpio = i2c_get_clientdata(client);
-
- gpiochip_remove(&gpio->chip);
+ return devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio);
}
static const struct i2c_device_id tpic2810_id_table[] = {
@@ -143,12 +127,11 @@ static struct i2c_driver tpic2810_driver = {
.name = "tpic2810",
.of_match_table = tpic2810_of_match_table,
},
- .probe_new = tpic2810_probe,
- .remove = tpic2810_remove,
+ .probe = tpic2810_probe,
.id_table = tpic2810_id_table,
};
module_i2c_driver(tpic2810_driver);
-MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
+MODULE_AUTHOR("Andrew Davis <afd@ti.com>");
MODULE_DESCRIPTION("TPIC2810 8-Bit LED Driver GPIO Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-tps65086.c b/drivers/gpio/gpio-tps65086.c
index 1e9d8262d0ff..8f5827554e1e 100644
--- a/drivers/gpio/gpio-tps65086.c
+++ b/drivers/gpio/gpio-tps65086.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
- * Andrew F. Davis <afd@ti.com>
+ * Copyright (C) 2015-2023 Texas Instruments Incorporated - https://www.ti.com/
+ * Andrew Davis <afd@ti.com>
*
* Based on the TPS65912 driver
*/
@@ -80,34 +80,16 @@ static const struct gpio_chip template_chip = {
static int tps65086_gpio_probe(struct platform_device *pdev)
{
struct tps65086_gpio *gpio;
- int ret;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
return -ENOMEM;
- platform_set_drvdata(pdev, gpio);
-
gpio->tps = dev_get_drvdata(pdev->dev.parent);
gpio->chip = template_chip;
gpio->chip.parent = gpio->tps->dev;
- ret = gpiochip_add_data(&gpio->chip, gpio);
- if (ret < 0) {
- dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-static int tps65086_gpio_remove(struct platform_device *pdev)
-{
- struct tps65086_gpio *gpio = platform_get_drvdata(pdev);
-
- gpiochip_remove(&gpio->chip);
-
- return 0;
+ return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
}
static const struct platform_device_id tps65086_gpio_id_table[] = {
@@ -121,11 +103,10 @@ static struct platform_driver tps65086_gpio_driver = {
.name = "tps65086-gpio",
},
.probe = tps65086_gpio_probe,
- .remove = tps65086_gpio_remove,
.id_table = tps65086_gpio_id_table,
};
module_platform_driver(tps65086_gpio_driver);
-MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
+MODULE_AUTHOR("Andrew Davis <afd@ti.com>");
MODULE_DESCRIPTION("TPS65086 GPIO driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-tps65219.c b/drivers/gpio/gpio-tps65219.c
new file mode 100644
index 000000000000..7b38aa360112
--- /dev/null
+++ b/drivers/gpio/gpio-tps65219.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * GPIO driver for TI TPS65219 PMICs
+ *
+ * Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include <linux/bits.h>
+#include <linux/gpio/driver.h>
+#include <linux/mfd/tps65219.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define TPS65219_GPIO0_DIR_MASK BIT(3)
+#define TPS65219_GPIO0_OFFSET 2
+#define TPS65219_GPIO0_IDX 0
+#define TPS65219_GPIO_DIR_IN 1
+#define TPS65219_GPIO_DIR_OUT 0
+
+struct tps65219_gpio {
+ struct gpio_chip gpio_chip;
+ struct tps65219 *tps;
+};
+
+static int tps65219_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+ struct tps65219_gpio *gpio = gpiochip_get_data(gc);
+ int ret, val;
+
+ if (offset != TPS65219_GPIO0_IDX)
+ return GPIO_LINE_DIRECTION_OUT;
+
+ ret = regmap_read(gpio->tps->regmap, TPS65219_REG_MFP_1_CONFIG, &val);
+ if (ret)
+ return ret;
+
+ return !!(val & TPS65219_GPIO0_DIR_MASK);
+}
+
+static int tps65219_gpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+ struct tps65219_gpio *gpio = gpiochip_get_data(gc);
+ struct device *dev = gpio->tps->dev;
+ int ret, val;
+
+ if (offset != TPS65219_GPIO0_IDX) {
+ dev_err(dev, "GPIO%d is output only, cannot get\n", offset);
+ return -ENOTSUPP;
+ }
+
+ ret = regmap_read(gpio->tps->regmap, TPS65219_REG_MFP_CTRL, &val);
+ if (ret)
+ return ret;
+
+ ret = !!(val & BIT(TPS65219_MFP_GPIO_STATUS_MASK));
+ dev_warn(dev, "GPIO%d = %d, MULTI_DEVICE_ENABLE, not a standard GPIO\n", offset, ret);
+
+ /*
+ * Depending on NVM config, return an error if direction is output, otherwise the GPIO0
+ * status bit.
+ */
+
+ if (tps65219_gpio_get_direction(gc, offset) == TPS65219_GPIO_DIR_OUT)
+ return -ENOTSUPP;
+
+ return ret;
+}
+
+static void tps65219_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
+{
+ struct tps65219_gpio *gpio = gpiochip_get_data(gc);
+ struct device *dev = gpio->tps->dev;
+ int v, mask, bit;
+
+ bit = (offset == TPS65219_GPIO0_IDX) ? TPS65219_GPIO0_OFFSET : offset - 1;
+
+ mask = BIT(bit);
+ v = value ? mask : 0;
+
+ if (regmap_update_bits(gpio->tps->regmap, TPS65219_REG_GENERAL_CONFIG, mask, v))
+ dev_err(dev, "GPIO%d, set to value %d failed.\n", offset, value);
+}
+
+static int tps65219_gpio_change_direction(struct gpio_chip *gc, unsigned int offset,
+ unsigned int direction)
+{
+ struct tps65219_gpio *gpio = gpiochip_get_data(gc);
+ struct device *dev = gpio->tps->dev;
+
+ /*
+ * Documentation is stating that GPIO0 direction must not be changed in Linux:
+ * Table 8-34. MFP_1_CONFIG(3): MULTI_DEVICE_ENABLE, should only be changed in INITIALIZE
+ * state (prior to ON Request).
+ * Set statically by NVM, changing direction in application can cause a hang.
+ * Below can be used for test purpose only.
+ */
+
+ if (IS_ENABLED(CONFIG_DEBUG_GPIO)) {
+ int ret = regmap_update_bits(gpio->tps->regmap, TPS65219_REG_MFP_1_CONFIG,
+ TPS65219_GPIO0_DIR_MASK, direction);
+ if (ret) {
+ dev_err(dev,
+ "GPIO DEBUG enabled: Fail to change direction to %u for GPIO%d.\n",
+ direction, offset);
+ return ret;
+ }
+ }
+
+ dev_err(dev,
+ "GPIO%d direction set by NVM, change to %u failed, not allowed by specification\n",
+ offset, direction);
+
+ return -ENOTSUPP;
+}
+
+static int tps65219_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
+{
+ struct tps65219_gpio *gpio = gpiochip_get_data(gc);
+ struct device *dev = gpio->tps->dev;
+
+ if (offset != TPS65219_GPIO0_IDX) {
+ dev_err(dev, "GPIO%d is output only, cannot change to input\n", offset);
+ return -ENOTSUPP;
+ }
+
+ if (tps65219_gpio_get_direction(gc, offset) == TPS65219_GPIO_DIR_IN)
+ return 0;
+
+ return tps65219_gpio_change_direction(gc, offset, TPS65219_GPIO_DIR_IN);
+}
+
+static int tps65219_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int value)
+{
+ tps65219_gpio_set(gc, offset, value);
+ if (offset != TPS65219_GPIO0_IDX)
+ return 0;
+
+ if (tps65219_gpio_get_direction(gc, offset) == TPS65219_GPIO_DIR_OUT)
+ return 0;
+
+ return tps65219_gpio_change_direction(gc, offset, TPS65219_GPIO_DIR_OUT);
+}
+
+static const struct gpio_chip tps65219_template_chip = {
+ .label = "tps65219-gpio",
+ .owner = THIS_MODULE,
+ .get_direction = tps65219_gpio_get_direction,
+ .direction_input = tps65219_gpio_direction_input,
+ .direction_output = tps65219_gpio_direction_output,
+ .get = tps65219_gpio_get,
+ .set = tps65219_gpio_set,
+ .base = -1,
+ .ngpio = 3,
+ .can_sleep = true,
+};
+
+static int tps65219_gpio_probe(struct platform_device *pdev)
+{
+ struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent);
+ struct tps65219_gpio *gpio;
+
+ gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+ if (!gpio)
+ return -ENOMEM;
+
+ gpio->tps = tps;
+ gpio->gpio_chip = tps65219_template_chip;
+ gpio->gpio_chip.parent = tps->dev;
+
+ return devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, gpio);
+}
+
+static struct platform_driver tps65219_gpio_driver = {
+ .driver = {
+ .name = "tps65219-gpio",
+ },
+ .probe = tps65219_gpio_probe,
+};
+module_platform_driver(tps65219_gpio_driver);
+
+MODULE_ALIAS("platform:tps65219-gpio");
+MODULE_AUTHOR("Jonathan Cormier <jcormier@criticallink.com>");
+MODULE_DESCRIPTION("TPS65219 GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-ts4900.c b/drivers/gpio/gpio-ts4900.c
index 43e8b66e04f7..eba96319dac2 100644
--- a/drivers/gpio/gpio-ts4900.c
+++ b/drivers/gpio/gpio-ts4900.c
@@ -185,7 +185,7 @@ static struct i2c_driver ts4900_gpio_driver = {
.name = "ts4900-gpio",
.of_match_table = ts4900_gpio_of_match_table,
},
- .probe_new = ts4900_gpio_probe,
+ .probe = ts4900_gpio_probe,
.id_table = ts4900_gpio_id_table,
};
module_i2c_driver(ts4900_gpio_driver);
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index c1bb2c3ca6f2..bcd692229c7c 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -17,7 +17,9 @@
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/irq.h>
+#include <linux/gpio/machine.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/irqdomain.h>
@@ -465,8 +467,7 @@ static int gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
REG_GPIO_DEBEN1, 3);
}
-static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev,
- struct twl4030_gpio_platform_data *pdata)
+static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
{
struct twl4030_gpio_platform_data *omap_twl_info;
@@ -474,9 +475,6 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev,
if (!omap_twl_info)
return NULL;
- if (pdata)
- *omap_twl_info = *pdata;
-
omap_twl_info->use_leds = of_property_read_bool(dev->of_node,
"ti,use-leds");
@@ -492,21 +490,18 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev,
return omap_twl_info;
}
-/* Cannot use as gpio_twl4030_probe() calls us */
-static int gpio_twl4030_remove(struct platform_device *pdev)
+/* Called from the registered devm action */
+static void gpio_twl4030_power_off_action(void *data)
{
- struct gpio_twl4030_priv *priv = platform_get_drvdata(pdev);
-
- gpiochip_remove(&priv->gpio_chip);
+ struct gpio_desc *d = data;
- /* REVISIT no support yet for deregistering all the IRQs */
- WARN_ON(!is_module());
- return 0;
+ gpiod_unexport(d);
+ gpiochip_free_own_desc(d);
}
static int gpio_twl4030_probe(struct platform_device *pdev)
{
- struct twl4030_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct twl4030_gpio_platform_data *pdata;
struct device_node *node = pdev->dev.of_node;
struct gpio_twl4030_priv *priv;
int ret, irq_base;
@@ -546,9 +541,7 @@ no_irqs:
mutex_init(&priv->mutex);
- if (node)
- pdata = of_gpio_twl4030(&pdev->dev, pdata);
-
+ pdata = of_gpio_twl4030(&pdev->dev);
if (pdata == NULL) {
dev_err(&pdev->dev, "Platform data is missing\n");
return -ENXIO;
@@ -577,27 +570,39 @@ no_irqs:
if (pdata->use_leds)
priv->gpio_chip.ngpio += 2;
- ret = gpiochip_add_data(&priv->gpio_chip, priv);
+ ret = devm_gpiochip_add_data(&pdev->dev, &priv->gpio_chip, priv);
if (ret < 0) {
dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
priv->gpio_chip.ngpio = 0;
- gpio_twl4030_remove(pdev);
- goto out;
+ return ret;
}
- platform_set_drvdata(pdev, priv);
+ /*
+ * Special quirk for the OMAP3 to hog and export a WLAN power
+ * GPIO.
+ */
+ if (IS_ENABLED(CONFIG_ARCH_OMAP3) &&
+ of_machine_is_compatible("compulab,omap3-sbc-t3730")) {
+ struct gpio_desc *d;
+
+ d = gpiochip_request_own_desc(&priv->gpio_chip,
+ 2, "wlan pwr",
+ GPIO_ACTIVE_HIGH,
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(d))
+ return dev_err_probe(&pdev->dev, PTR_ERR(d),
+ "unable to hog wlan pwr GPIO\n");
+
+ gpiod_export(d, 0);
- if (pdata->setup) {
- int status;
+ ret = devm_add_action_or_reset(&pdev->dev, gpio_twl4030_power_off_action, d);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to install power off handler\n");
- status = pdata->setup(&pdev->dev, priv->gpio_chip.base,
- TWL4030_GPIO_MAX);
- if (status)
- dev_dbg(&pdev->dev, "setup --> %d\n", status);
}
-out:
- return ret;
+ return 0;
}
static const struct of_device_id twl_gpio_match[] = {
@@ -615,7 +620,6 @@ static struct platform_driver gpio_twl4030_driver = {
.of_match_table = twl_gpio_match,
},
.probe = gpio_twl4030_probe,
- .remove = gpio_twl4030_remove,
};
static int __init gpio_twl4030_init(void)
diff --git a/drivers/gpio/gpio-xra1403.c b/drivers/gpio/gpio-xra1403.c
index 51d6119e1bb4..bbc06cdd9634 100644
--- a/drivers/gpio/gpio-xra1403.c
+++ b/drivers/gpio/gpio-xra1403.c
@@ -11,7 +11,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
#include <linux/seq_file.h>
#include <linux/spi/spi.h>
#include <linux/regmap.h>
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index 06c6401f02b8..0a7264aabe48 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -151,8 +151,8 @@ struct zynq_platform_data {
int bank_max[ZYNQMP_GPIO_MAX_BANK];
};
-static struct irq_chip zynq_gpio_level_irqchip;
-static struct irq_chip zynq_gpio_edge_irqchip;
+static const struct irq_chip zynq_gpio_level_irqchip;
+static const struct irq_chip zynq_gpio_edge_irqchip;
/**
* zynq_gpio_is_zynq - test if HW is zynq or zynqmp
@@ -404,9 +404,12 @@ static int zynq_gpio_get_direction(struct gpio_chip *chip, unsigned int pin)
static void zynq_gpio_irq_mask(struct irq_data *irq_data)
{
unsigned int device_pin_num, bank_num, bank_pin_num;
+ const unsigned long offset = irqd_to_hwirq(irq_data);
+ struct gpio_chip *chip = irq_data_get_irq_chip_data(irq_data);
struct zynq_gpio *gpio =
gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
+ gpiochip_disable_irq(chip, offset);
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
writel_relaxed(BIT(bank_pin_num),
@@ -425,9 +428,12 @@ static void zynq_gpio_irq_mask(struct irq_data *irq_data)
static void zynq_gpio_irq_unmask(struct irq_data *irq_data)
{
unsigned int device_pin_num, bank_num, bank_pin_num;
+ const unsigned long offset = irqd_to_hwirq(irq_data);
+ struct gpio_chip *chip = irq_data_get_irq_chip_data(irq_data);
struct zynq_gpio *gpio =
gpiochip_get_data(irq_data_get_irq_chip_data(irq_data));
+ gpiochip_enable_irq(chip, offset);
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
writel_relaxed(BIT(bank_pin_num),
@@ -569,28 +575,8 @@ static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
return 0;
}
-static int zynq_gpio_irq_reqres(struct irq_data *d)
-{
- struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
- int ret;
-
- ret = pm_runtime_resume_and_get(chip->parent);
- if (ret < 0)
- return ret;
-
- return gpiochip_reqres_irq(chip, d->hwirq);
-}
-
-static void zynq_gpio_irq_relres(struct irq_data *d)
-{
- struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
-
- gpiochip_relres_irq(chip, d->hwirq);
- pm_runtime_put(chip->parent);
-}
-
/* irq chip descriptor */
-static struct irq_chip zynq_gpio_level_irqchip = {
+static const struct irq_chip zynq_gpio_level_irqchip = {
.name = DRIVER_NAME,
.irq_enable = zynq_gpio_irq_enable,
.irq_eoi = zynq_gpio_irq_ack,
@@ -598,13 +584,12 @@ static struct irq_chip zynq_gpio_level_irqchip = {
.irq_unmask = zynq_gpio_irq_unmask,
.irq_set_type = zynq_gpio_set_irq_type,
.irq_set_wake = zynq_gpio_set_wake,
- .irq_request_resources = zynq_gpio_irq_reqres,
- .irq_release_resources = zynq_gpio_irq_relres,
.flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED |
- IRQCHIP_MASK_ON_SUSPEND,
+ IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
-static struct irq_chip zynq_gpio_edge_irqchip = {
+static const struct irq_chip zynq_gpio_edge_irqchip = {
.name = DRIVER_NAME,
.irq_enable = zynq_gpio_irq_enable,
.irq_ack = zynq_gpio_irq_ack,
@@ -612,9 +597,8 @@ static struct irq_chip zynq_gpio_edge_irqchip = {
.irq_unmask = zynq_gpio_irq_unmask,
.irq_set_type = zynq_gpio_set_irq_type,
.irq_set_wake = zynq_gpio_set_wake,
- .irq_request_resources = zynq_gpio_irq_reqres,
- .irq_release_resources = zynq_gpio_irq_relres,
- .flags = IRQCHIP_MASK_ON_SUSPEND,
+ .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio,
@@ -962,7 +946,7 @@ static int zynq_gpio_probe(struct platform_device *pdev)
/* Set up the GPIO irqchip */
girq = &chip->irq;
- girq->chip = &zynq_gpio_edge_irqchip;
+ gpio_irq_chip_set_chip(girq, &zynq_gpio_edge_irqchip);
girq->parent_handler = zynq_gpio_irqhandler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, 1,
diff --git a/drivers/gpio/gpiolib-legacy.c b/drivers/gpio/gpiolib-legacy.c
index 30e2476a6dc4..97f4b498e343 100644
--- a/drivers/gpio/gpiolib-legacy.c
+++ b/drivers/gpio/gpiolib-legacy.c
@@ -33,12 +33,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
if (err)
return err;
- if (flags & GPIOF_OPEN_DRAIN)
- set_bit(FLAG_OPEN_DRAIN, &desc->flags);
-
- if (flags & GPIOF_OPEN_SOURCE)
- set_bit(FLAG_OPEN_SOURCE, &desc->flags);
-
if (flags & GPIOF_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
@@ -51,12 +45,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
if (err)
goto free_gpio;
- if (flags & GPIOF_EXPORT) {
- err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);
- if (err)
- goto free_gpio;
- }
-
return 0;
free_gpio:
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 5be8ad61523e..251c875b5c34 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -465,6 +465,12 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *gc)
return p;
}
+static void gpiochip_free_mask(unsigned long **p)
+{
+ bitmap_free(*p);
+ *p = NULL;
+}
+
static unsigned int gpiochip_count_reserved_ranges(struct gpio_chip *gc)
{
struct device *dev = &gc->gpiodev->dev;
@@ -478,18 +484,6 @@ static unsigned int gpiochip_count_reserved_ranges(struct gpio_chip *gc)
return 0;
}
-static int gpiochip_alloc_valid_mask(struct gpio_chip *gc)
-{
- if (!(gpiochip_count_reserved_ranges(gc) || gc->init_valid_mask))
- return 0;
-
- gc->valid_mask = gpiochip_allocate_mask(gc);
- if (!gc->valid_mask)
- return -ENOMEM;
-
- return 0;
-}
-
static int gpiochip_apply_reserved_ranges(struct gpio_chip *gc)
{
struct device *dev = &gc->gpiodev->dev;
@@ -530,6 +524,13 @@ static int gpiochip_init_valid_mask(struct gpio_chip *gc)
{
int ret;
+ if (!(gpiochip_count_reserved_ranges(gc) || gc->init_valid_mask))
+ return 0;
+
+ gc->valid_mask = gpiochip_allocate_mask(gc);
+ if (!gc->valid_mask)
+ return -ENOMEM;
+
ret = gpiochip_apply_reserved_ranges(gc);
if (ret)
return ret;
@@ -544,8 +545,7 @@ static int gpiochip_init_valid_mask(struct gpio_chip *gc)
static void gpiochip_free_valid_mask(struct gpio_chip *gc)
{
- bitmap_free(gc->valid_mask);
- gc->valid_mask = NULL;
+ gpiochip_free_mask(&gc->valid_mask);
}
static int gpiochip_add_pin_ranges(struct gpio_chip *gc)
@@ -857,7 +857,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
if (ret)
goto err_remove_from_list;
- ret = gpiochip_alloc_valid_mask(gc);
+ ret = gpiochip_init_valid_mask(gc);
if (ret)
goto err_remove_from_list;
@@ -865,10 +865,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
if (ret)
goto err_free_gpiochip_mask;
- ret = gpiochip_init_valid_mask(gc);
- if (ret)
- goto err_remove_of_chip;
-
for (i = 0; i < gc->ngpio; i++) {
struct gpio_desc *desc = &gdev->descs[i];
@@ -1089,8 +1085,7 @@ static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc)
static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc)
{
- bitmap_free(gc->irq.valid_mask);
- gc->irq.valid_mask = NULL;
+ gpiochip_free_mask(&gc->irq.valid_mask);
}
bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gc,
@@ -1676,11 +1671,10 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
if (ret)
return ret;
} else {
- /* Some drivers provide custom irqdomain ops */
gc->irq.domain = irq_domain_create_simple(fwnode,
gc->ngpio,
gc->irq.first,
- gc->irq.domain_ops ?: &gpiochip_domain_ops,
+ &gpiochip_domain_ops,
gc);
if (!gc->irq.domain)
return -EINVAL;
@@ -2133,8 +2127,6 @@ static bool gpiod_free_commit(struct gpio_desc *desc)
might_sleep();
- gpiod_unexport(desc);
-
spin_lock_irqsave(&gpio_lock, flags);
gc = desc->gdev->chip;
@@ -4252,7 +4244,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
/* Mark GPIO as hogged so it can be identified and removed later */
set_bit(FLAG_IS_HOGGED, &desc->flags);
- gpiod_info(desc, "hogged as %s%s\n",
+ gpiod_dbg(desc, "hogged as %s%s\n",
(dflags & GPIOD_FLAGS_BIT_DIR_OUT) ? "output" : "input",
(dflags & GPIOD_FLAGS_BIT_DIR_OUT) ?
(dflags & GPIOD_FLAGS_BIT_DIR_VAL) ? "/high" : "/low" : "");
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index ba3fb04bb691..afb3b2f5f425 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -95,6 +95,7 @@ config DRM_KUNIT_TEST
config DRM_KMS_HELPER
tristate
depends on DRM
+ select FB_SYS_HELPERS_DEFERRED if DRM_FBDEV_EMULATION
help
CRTC helpers for KMS drivers.
@@ -132,14 +133,6 @@ config DRM_FBDEV_EMULATION
bool "Enable legacy fbdev support for your modesetting driver"
depends on DRM_KMS_HELPER
depends on FB=y || FB=DRM_KMS_HELPER
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_DEFERRED_IO
- select FB_SYS_FOPS
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
select FRAMEBUFFER_CONSOLE if !EXPERT
select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE
default y
@@ -223,6 +216,7 @@ config DRM_TTM_HELPER
config DRM_GEM_DMA_HELPER
tristate
depends on DRM
+ select FB_SYS_HELPERS if DRM_FBDEV_EMULATION
help
Choose this if you need the GEM DMA helper functions
@@ -295,9 +289,7 @@ source "drivers/gpu/drm/armada/Kconfig"
source "drivers/gpu/drm/atmel-hlcdc/Kconfig"
-source "drivers/gpu/drm/rcar-du/Kconfig"
-
-source "drivers/gpu/drm/shmobile/Kconfig"
+source "drivers/gpu/drm/renesas/Kconfig"
source "drivers/gpu/drm/sun4i/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index a33257d2bc7f..7a09a89b493b 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -140,6 +140,7 @@ obj-$(CONFIG_DRM_TTM) += ttm/
obj-$(CONFIG_DRM_SCHED) += scheduler/
obj-$(CONFIG_DRM_RADEON)+= radeon/
obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
+obj-$(CONFIG_DRM_AMDGPU)+= amd/amdxcp/
obj-$(CONFIG_DRM_I915) += i915/
obj-$(CONFIG_DRM_KMB_DISPLAY) += kmb/
obj-$(CONFIG_DRM_MGAG200) += mgag200/
@@ -156,8 +157,7 @@ obj-$(CONFIG_DRM_UDL) += udl/
obj-$(CONFIG_DRM_AST) += ast/
obj-$(CONFIG_DRM_ARMADA) += armada/
obj-$(CONFIG_DRM_ATMEL_HLCDC) += atmel-hlcdc/
-obj-y += rcar-du/
-obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
+obj-y += renesas/
obj-y += omapdrm/
obj-$(CONFIG_DRM_SUN4I) += sun4i/
obj-y += tilcdc/
diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig
index 12adca8c7819..b91e79c721e2 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -69,6 +69,16 @@ config DRM_AMDGPU_USERPTR
This option selects CONFIG_HMM and CONFIG_HMM_MIRROR if it
isn't already selected to enabled full userptr support.
+config DRM_AMDGPU_WERROR
+ bool "Force the compiler to throw an error instead of a warning when compiling"
+ depends on DRM_AMDGPU
+ depends on EXPERT
+ depends on !COMPILE_TEST
+ default n
+ help
+ Add -Werror to the build flags for amdgpu.ko.
+ Only enable this if you are warning code for amdgpu.ko.
+
source "drivers/gpu/drm/amd/acp/Kconfig"
source "drivers/gpu/drm/amd/display/Kconfig"
source "drivers/gpu/drm/amd/amdkfd/Kconfig"
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 415a7fa395c4..8d16f280b695 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -39,6 +39,26 @@ ccflags-y := -I$(FULL_AMD_PATH)/include/asic_reg \
-I$(FULL_AMD_DISPLAY_PATH)/amdgpu_dm \
-I$(FULL_AMD_PATH)/amdkfd
+subdir-ccflags-y := -Wextra
+subdir-ccflags-y += -Wunused
+subdir-ccflags-y += -Wmissing-prototypes
+subdir-ccflags-y += -Wmissing-declarations
+subdir-ccflags-y += -Wmissing-include-dirs
+subdir-ccflags-y += -Wold-style-definition
+subdir-ccflags-y += -Wmissing-format-attribute
+# Need this to avoid recursive variable evaluation issues
+cond-flags := $(call cc-option, -Wunused-but-set-variable) \
+ $(call cc-option, -Wunused-const-variable) \
+ $(call cc-option, -Wstringop-truncation) \
+ $(call cc-option, -Wpacked-not-aligned)
+subdir-ccflags-y += $(cond-flags)
+subdir-ccflags-y += -Wno-unused-parameter
+subdir-ccflags-y += -Wno-type-limits
+subdir-ccflags-y += -Wno-sign-compare
+subdir-ccflags-y += -Wno-missing-field-initializers
+subdir-ccflags-y += -Wno-override-init
+subdir-ccflags-$(CONFIG_DRM_AMDGPU_WERROR) += -Werror
+
amdgpu-y := amdgpu_drv.o
# add KMS driver
@@ -60,7 +80,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \
amdgpu_fw_attestation.o amdgpu_securedisplay.o \
amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o \
- amdgpu_ring_mux.o
+ amdgpu_ring_mux.o amdgpu_xcp.o
amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o
@@ -78,7 +98,7 @@ amdgpu-y += \
vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o arct_reg_init.o mxgpu_nv.o \
nbio_v7_2.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o soc21.o \
sienna_cichlid.o smu_v13_0_10.o nbio_v4_3.o hdp_v6_0.o nbio_v7_7.o hdp_v5_2.o lsdma_v6_0.o \
- nbio_v7_9.o
+ nbio_v7_9.o aqua_vanjaram_reg_init.o
# add DF block
amdgpu-y += \
@@ -183,12 +203,14 @@ amdgpu-y += \
vcn_v2_5.o \
vcn_v3_0.o \
vcn_v4_0.o \
+ vcn_v4_0_3.o \
amdgpu_jpeg.o \
jpeg_v1_0.o \
jpeg_v2_0.o \
jpeg_v2_5.o \
jpeg_v3_0.o \
- jpeg_v4_0.o
+ jpeg_v4_0.o \
+ jpeg_v4_0_3.o
# add ATHUB block
amdgpu-y += \
@@ -203,6 +225,7 @@ amdgpu-y += \
smuio_v11_0.o \
smuio_v11_0_6.o \
smuio_v13_0.o \
+ smuio_v13_0_3.o \
smuio_v13_0_6.o
# add reset block
@@ -228,6 +251,7 @@ amdgpu-y += \
amdgpu_amdkfd_gfx_v9.o \
amdgpu_amdkfd_arcturus.o \
amdgpu_amdkfd_aldebaran.o \
+ amdgpu_amdkfd_gc_9_4_3.o \
amdgpu_amdkfd_gfx_v10.o \
amdgpu_amdkfd_gfx_v10_3.o \
amdgpu_amdkfd_gfx_v11.o
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 02b827785e39..a84bd4a0c421 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -107,8 +107,9 @@
#include "amdgpu_fdinfo.h"
#include "amdgpu_mca.h"
#include "amdgpu_ras.h"
+#include "amdgpu_xcp.h"
-#define MAX_GPU_INSTANCE 16
+#define MAX_GPU_INSTANCE 64
struct amdgpu_gpu_instance
{
@@ -212,6 +213,8 @@ extern int amdgpu_noretry;
extern int amdgpu_force_asic_type;
extern int amdgpu_smartshift_bias;
extern int amdgpu_use_xgmi_p2p;
+extern int amdgpu_mtype_local;
+extern bool enforce_isolation;
#ifdef CONFIG_HSA_AMD
extern int sched_policy;
extern bool debug_evictions;
@@ -242,9 +245,10 @@ extern int amdgpu_num_kcq;
extern int amdgpu_vcnfw_log;
extern int amdgpu_sg_display;
+extern int amdgpu_user_partt_mode;
+
#define AMDGPU_VM_MAX_NUM_CTX 4096
#define AMDGPU_SG_THRESHOLD (256*1024*1024)
-#define AMDGPU_DEFAULT_GTT_SIZE_MB 3072ULL /* 3GB by default */
#define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000
#define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */
#define AMDGPU_FENCE_JIFFIES_TIMEOUT (HZ / 2)
@@ -282,6 +286,7 @@ extern int amdgpu_sg_display;
#define AMDGPU_SMARTSHIFT_MAX_BIAS (100)
#define AMDGPU_SMARTSHIFT_MIN_BIAS (-100)
+struct amdgpu_xcp_mgr;
struct amdgpu_device;
struct amdgpu_irq_src;
struct amdgpu_fpriv;
@@ -463,6 +468,8 @@ struct amdgpu_fpriv {
struct mutex bo_list_lock;
struct idr bo_list_handles;
struct amdgpu_ctx_mgr ctx_mgr;
+ /** GPU partition selection */
+ uint32_t xcp_id;
};
int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv);
@@ -573,6 +580,8 @@ struct amdgpu_asic_funcs {
/* query video codecs */
int (*query_video_codecs)(struct amdgpu_device *adev, bool encode,
const struct amdgpu_video_codecs **codecs);
+ /* encode "> 32bits" smn addressing */
+ u64 (*encode_ext_smn_addressing)(int ext_id);
};
/*
@@ -607,6 +616,9 @@ void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device);
typedef uint32_t (*amdgpu_rreg_t)(struct amdgpu_device*, uint32_t);
typedef void (*amdgpu_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
+typedef uint32_t (*amdgpu_rreg_ext_t)(struct amdgpu_device*, uint64_t);
+typedef void (*amdgpu_wreg_ext_t)(struct amdgpu_device*, uint64_t, uint32_t);
+
typedef uint64_t (*amdgpu_rreg64_t)(struct amdgpu_device*, uint32_t);
typedef void (*amdgpu_wreg64_t)(struct amdgpu_device*, uint32_t, uint64_t);
@@ -657,7 +669,7 @@ enum amd_hw_ip_block_type {
MAX_HWIP
};
-#define HWIP_MAX_INSTANCE 28
+#define HWIP_MAX_INSTANCE 44
#define HW_ID_MAX 300
#define IP_VERSION(mj, mn, rv) (((mj) << 16) | ((mn) << 8) | (rv))
@@ -665,6 +677,17 @@ enum amd_hw_ip_block_type {
#define IP_VERSION_MIN(ver) (((ver) >> 8) & 0xFF)
#define IP_VERSION_REV(ver) ((ver) & 0xFF)
+struct amdgpu_ip_map_info {
+ /* Map of logical to actual dev instances/mask */
+ uint32_t dev_inst[MAX_HWIP][HWIP_MAX_INSTANCE];
+ int8_t (*logical_to_dev_inst)(struct amdgpu_device *adev,
+ enum amd_hw_ip_block_type block,
+ int8_t inst);
+ uint32_t (*logical_to_dev_mask)(struct amdgpu_device *adev,
+ enum amd_hw_ip_block_type block,
+ uint32_t mask);
+};
+
struct amd_powerplay {
void *pp_handle;
const struct amd_pm_funcs *pp_funcs;
@@ -750,6 +773,7 @@ struct amdgpu_device {
struct amdgpu_acp acp;
#endif
struct amdgpu_hive_info *hive;
+ struct amdgpu_xcp_mgr *xcp_mgr;
/* ASIC */
enum amd_asic_type asic_type;
uint32_t family;
@@ -797,6 +821,8 @@ struct amdgpu_device {
amdgpu_wreg_t pcie_wreg;
amdgpu_rreg_t pciep_rreg;
amdgpu_wreg_t pciep_wreg;
+ amdgpu_rreg_ext_t pcie_rreg_ext;
+ amdgpu_wreg_ext_t pcie_wreg_ext;
amdgpu_rreg64_t pcie_rreg64;
amdgpu_wreg64_t pcie_wreg64;
/* protects concurrent UVD register access */
@@ -830,7 +856,7 @@ struct amdgpu_device {
dma_addr_t dummy_page_addr;
struct amdgpu_vm_manager vm_manager;
struct amdgpu_vmhub vmhub[AMDGPU_MAX_VMHUBS];
- unsigned num_vmhubs;
+ DECLARE_BITMAP(vmhubs_mask, AMDGPU_MAX_VMHUBS);
/* memory management */
struct amdgpu_mman mman;
@@ -962,6 +988,7 @@ struct amdgpu_device {
/* soc15 register offset based on ip, instance and segment */
uint32_t *reg_offset[MAX_HWIP][HWIP_MAX_INSTANCE];
+ struct amdgpu_ip_map_info ip_map;
/* delayed work_func for deferring clockgating during resume */
struct delayed_work delayed_init_work;
@@ -1020,6 +1047,9 @@ struct amdgpu_device {
struct pci_saved_state *pci_state;
pci_channel_state_t pci_channel_state;
+ /* Track auto wait count on s_barrier settings */
+ bool barrier_has_auto_waitcnt;
+
struct amdgpu_reset_control *reset_cntl;
uint32_t ip_versions[MAX_HWIP][HWIP_MAX_INSTANCE];
@@ -1050,6 +1080,8 @@ struct amdgpu_device {
bool job_hang;
bool dc_enabled;
+ /* Mask of active clusters */
+ uint32_t aid_mask;
};
static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev)
@@ -1081,11 +1113,18 @@ size_t amdgpu_device_aper_access(struct amdgpu_device *adev, loff_t pos,
void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
void *buf, size_t size, bool write);
+uint32_t amdgpu_device_wait_on_rreg(struct amdgpu_device *adev,
+ uint32_t inst, uint32_t reg_addr, char reg_name[],
+ uint32_t expected_value, uint32_t mask);
uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
uint32_t reg, uint32_t acc_flags);
+u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev,
+ u64 reg_addr);
void amdgpu_device_wreg(struct amdgpu_device *adev,
uint32_t reg, uint32_t v,
uint32_t acc_flags);
+void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev,
+ u64 reg_addr, u32 reg_data);
void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
uint32_t reg, uint32_t v);
void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value);
@@ -1137,6 +1176,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
#define WREG32_PCIE(reg, v) adev->pcie_wreg(adev, (reg), (v))
#define RREG32_PCIE_PORT(reg) adev->pciep_rreg(adev, (reg))
#define WREG32_PCIE_PORT(reg, v) adev->pciep_wreg(adev, (reg), (v))
+#define RREG32_PCIE_EXT(reg) adev->pcie_rreg_ext(adev, (reg))
+#define WREG32_PCIE_EXT(reg, v) adev->pcie_wreg_ext(adev, (reg), (v))
#define RREG64_PCIE(reg) adev->pcie_rreg64(adev, (reg))
#define WREG64_PCIE(reg, v) adev->pcie_wreg64(adev, (reg), (v))
#define RREG32_SMC(reg) adev->smc_rreg(adev, (reg))
@@ -1204,7 +1245,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
/*
* ASICs macro.
*/
-#define amdgpu_asic_set_vga_state(adev, state) (adev)->asic_funcs->set_vga_state((adev), (state))
+#define amdgpu_asic_set_vga_state(adev, state) \
+ ((adev)->asic_funcs->set_vga_state ? (adev)->asic_funcs->set_vga_state((adev), (state)) : 0)
#define amdgpu_asic_reset(adev) (adev)->asic_funcs->reset((adev))
#define amdgpu_asic_reset_method(adev) (adev)->asic_funcs->reset_method((adev))
#define amdgpu_asic_get_xclk(adev) (adev)->asic_funcs->get_xclk((adev))
@@ -1235,6 +1277,10 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
#define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter));
+#define for_each_inst(i, inst_mask) \
+ for (i = ffs(inst_mask) - 1; inst_mask; \
+ inst_mask &= ~(1U << i), i = ffs(inst_mask) - 1)
+
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
/* Common functions */
@@ -1348,6 +1394,12 @@ struct amdgpu_afmt_acr amdgpu_afmt_acr(uint32_t clock);
/* amdgpu_acpi.c */
+struct amdgpu_numa_info {
+ uint64_t size;
+ int pxm;
+ int nid;
+};
+
/* ATCS Device/Driver State */
#define AMDGPU_ATCS_PSC_DEV_STATE_D0 0
#define AMDGPU_ATCS_PSC_DEV_STATE_D3_HOT 3
@@ -1365,15 +1417,32 @@ int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
u8 dev_state, bool drv_state);
int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_state);
int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);
+int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev, u64 *tmr_offset,
+ u64 *tmr_size);
+int amdgpu_acpi_get_mem_info(struct amdgpu_device *adev, int xcc_id,
+ struct amdgpu_numa_info *numa_info);
void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps);
bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev);
void amdgpu_acpi_detect(void);
+void amdgpu_acpi_release(void);
#else
static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; }
+static inline int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev,
+ u64 *tmr_offset, u64 *tmr_size)
+{
+ return -EINVAL;
+}
+static inline int amdgpu_acpi_get_mem_info(struct amdgpu_device *adev,
+ int xcc_id,
+ struct amdgpu_numa_info *numa_info)
+{
+ return -EINVAL;
+}
static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { }
static inline bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) { return false; }
static inline void amdgpu_acpi_detect(void) { }
+static inline void amdgpu_acpi_release(void) { }
static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; }
static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
u8 dev_state, bool drv_state) { return 0; }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index fd6e83795873..385c6acb5728 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -26,6 +26,7 @@
#include <linux/acpi.h>
#include <linux/backlight.h>
#include <linux/slab.h>
+#include <linux/xarray.h>
#include <linux/power_supply.h>
#include <linux/pm_runtime.h>
#include <linux/suspend.h>
@@ -38,6 +39,45 @@
#include "amd_acpi.h"
#include "atom.h"
+/* Declare GUID for AMD _DSM method for XCCs */
+static const guid_t amd_xcc_dsm_guid = GUID_INIT(0x8267f5d5, 0xa556, 0x44f2,
+ 0xb8, 0xb4, 0x45, 0x56, 0x2e,
+ 0x8c, 0x5b, 0xec);
+
+#define AMD_XCC_HID_START 3000
+#define AMD_XCC_DSM_GET_NUM_FUNCS 0
+#define AMD_XCC_DSM_GET_SUPP_MODE 1
+#define AMD_XCC_DSM_GET_XCP_MODE 2
+#define AMD_XCC_DSM_GET_VF_XCC_MAPPING 4
+#define AMD_XCC_DSM_GET_TMR_INFO 5
+#define AMD_XCC_DSM_NUM_FUNCS 5
+
+#define AMD_XCC_MAX_HID 24
+
+struct xarray numa_info_xa;
+
+/* Encapsulates the XCD acpi object information */
+struct amdgpu_acpi_xcc_info {
+ struct list_head list;
+ struct amdgpu_numa_info *numa_info;
+ uint8_t xcp_node;
+ uint8_t phy_id;
+ acpi_handle handle;
+};
+
+struct amdgpu_acpi_dev_info {
+ struct list_head list;
+ struct list_head xcc_list;
+ uint16_t bdf;
+ uint16_t supp_xcp_mode;
+ uint16_t xcp_mode;
+ uint16_t mem_mode;
+ uint64_t tmr_base;
+ uint64_t tmr_size;
+};
+
+struct list_head amdgpu_acpi_dev_list;
+
struct amdgpu_atif_notification_cfg {
bool enabled;
int command_code;
@@ -801,6 +841,343 @@ int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_sta
return r;
}
+#ifdef CONFIG_ACPI_NUMA
+static inline uint64_t amdgpu_acpi_get_numa_size(int nid)
+{
+ /* This is directly using si_meminfo_node implementation as the
+ * function is not exported.
+ */
+ int zone_type;
+ uint64_t managed_pages = 0;
+
+ pg_data_t *pgdat = NODE_DATA(nid);
+
+ for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++)
+ managed_pages +=
+ zone_managed_pages(&pgdat->node_zones[zone_type]);
+ return managed_pages * PAGE_SIZE;
+}
+
+static struct amdgpu_numa_info *amdgpu_acpi_get_numa_info(uint32_t pxm)
+{
+ struct amdgpu_numa_info *numa_info;
+ int nid;
+
+ numa_info = xa_load(&numa_info_xa, pxm);
+
+ if (!numa_info) {
+ struct sysinfo info;
+
+ numa_info = kzalloc(sizeof *numa_info, GFP_KERNEL);
+ if (!numa_info)
+ return NULL;
+
+ nid = pxm_to_node(pxm);
+ numa_info->pxm = pxm;
+ numa_info->nid = nid;
+
+ if (numa_info->nid == NUMA_NO_NODE) {
+ si_meminfo(&info);
+ numa_info->size = info.totalram * info.mem_unit;
+ } else {
+ numa_info->size = amdgpu_acpi_get_numa_size(nid);
+ }
+ xa_store(&numa_info_xa, numa_info->pxm, numa_info, GFP_KERNEL);
+ }
+
+ return numa_info;
+}
+#endif
+
+/**
+ * amdgpu_acpi_get_node_id - obtain the NUMA node id for corresponding amdgpu
+ * acpi device handle
+ *
+ * @handle: acpi handle
+ * @numa_info: amdgpu_numa_info structure holding numa information
+ *
+ * Queries the ACPI interface to fetch the corresponding NUMA Node ID for a
+ * given amdgpu acpi device.
+ *
+ * Returns ACPI STATUS OK with Node ID on success or the corresponding failure reason
+ */
+static acpi_status amdgpu_acpi_get_node_id(acpi_handle handle,
+ struct amdgpu_numa_info **numa_info)
+{
+#ifdef CONFIG_ACPI_NUMA
+ u64 pxm;
+ acpi_status status;
+
+ if (!numa_info)
+ return_ACPI_STATUS(AE_ERROR);
+
+ status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm);
+
+ if (ACPI_FAILURE(status))
+ return status;
+
+ *numa_info = amdgpu_acpi_get_numa_info(pxm);
+
+ if (!*numa_info)
+ return_ACPI_STATUS(AE_ERROR);
+
+ return_ACPI_STATUS(AE_OK);
+#else
+ return_ACPI_STATUS(AE_NOT_EXIST);
+#endif
+}
+
+static struct amdgpu_acpi_dev_info *amdgpu_acpi_get_dev(u16 bdf)
+{
+ struct amdgpu_acpi_dev_info *acpi_dev;
+
+ if (list_empty(&amdgpu_acpi_dev_list))
+ return NULL;
+
+ list_for_each_entry(acpi_dev, &amdgpu_acpi_dev_list, list)
+ if (acpi_dev->bdf == bdf)
+ return acpi_dev;
+
+ return NULL;
+}
+
+static int amdgpu_acpi_dev_init(struct amdgpu_acpi_dev_info **dev_info,
+ struct amdgpu_acpi_xcc_info *xcc_info, u16 bdf)
+{
+ struct amdgpu_acpi_dev_info *tmp;
+ union acpi_object *obj;
+ int ret = -ENOENT;
+
+ *dev_info = NULL;
+ tmp = kzalloc(sizeof(struct amdgpu_acpi_dev_info), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&tmp->xcc_list);
+ INIT_LIST_HEAD(&tmp->list);
+ tmp->bdf = bdf;
+
+ obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
+ AMD_XCC_DSM_GET_SUPP_MODE, NULL,
+ ACPI_TYPE_INTEGER);
+
+ if (!obj) {
+ acpi_handle_debug(xcc_info->handle,
+ "_DSM function %d evaluation failed",
+ AMD_XCC_DSM_GET_SUPP_MODE);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ tmp->supp_xcp_mode = obj->integer.value & 0xFFFF;
+ ACPI_FREE(obj);
+
+ obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
+ AMD_XCC_DSM_GET_XCP_MODE, NULL,
+ ACPI_TYPE_INTEGER);
+
+ if (!obj) {
+ acpi_handle_debug(xcc_info->handle,
+ "_DSM function %d evaluation failed",
+ AMD_XCC_DSM_GET_XCP_MODE);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ tmp->xcp_mode = obj->integer.value & 0xFFFF;
+ tmp->mem_mode = (obj->integer.value >> 32) & 0xFFFF;
+ ACPI_FREE(obj);
+
+ /* Evaluate DSMs and fill XCC information */
+ obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
+ AMD_XCC_DSM_GET_TMR_INFO, NULL,
+ ACPI_TYPE_PACKAGE);
+
+ if (!obj || obj->package.count < 2) {
+ acpi_handle_debug(xcc_info->handle,
+ "_DSM function %d evaluation failed",
+ AMD_XCC_DSM_GET_TMR_INFO);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ tmp->tmr_base = obj->package.elements[0].integer.value;
+ tmp->tmr_size = obj->package.elements[1].integer.value;
+ ACPI_FREE(obj);
+
+ DRM_DEBUG_DRIVER(
+ "New dev(%x): Supported xcp mode: %x curr xcp_mode : %x mem mode : %x, tmr base: %llx tmr size: %llx ",
+ tmp->bdf, tmp->supp_xcp_mode, tmp->xcp_mode, tmp->mem_mode,
+ tmp->tmr_base, tmp->tmr_size);
+ list_add_tail(&tmp->list, &amdgpu_acpi_dev_list);
+ *dev_info = tmp;
+
+ return 0;
+
+out:
+ if (obj)
+ ACPI_FREE(obj);
+ kfree(tmp);
+
+ return ret;
+}
+
+static int amdgpu_acpi_get_xcc_info(struct amdgpu_acpi_xcc_info *xcc_info,
+ u16 *bdf)
+{
+ union acpi_object *obj;
+ acpi_status status;
+ int ret = -ENOENT;
+
+ obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
+ AMD_XCC_DSM_GET_NUM_FUNCS, NULL,
+ ACPI_TYPE_INTEGER);
+
+ if (!obj || obj->integer.value != AMD_XCC_DSM_NUM_FUNCS)
+ goto out;
+ ACPI_FREE(obj);
+
+ /* Evaluate DSMs and fill XCC information */
+ obj = acpi_evaluate_dsm_typed(xcc_info->handle, &amd_xcc_dsm_guid, 0,
+ AMD_XCC_DSM_GET_VF_XCC_MAPPING, NULL,
+ ACPI_TYPE_INTEGER);
+
+ if (!obj) {
+ acpi_handle_debug(xcc_info->handle,
+ "_DSM function %d evaluation failed",
+ AMD_XCC_DSM_GET_VF_XCC_MAPPING);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* PF xcc id [39:32] */
+ xcc_info->phy_id = (obj->integer.value >> 32) & 0xFF;
+ /* xcp node of this xcc [47:40] */
+ xcc_info->xcp_node = (obj->integer.value >> 40) & 0xFF;
+ /* PF bus/dev/fn of this xcc [63:48] */
+ *bdf = (obj->integer.value >> 48) & 0xFFFF;
+ ACPI_FREE(obj);
+ obj = NULL;
+
+ status =
+ amdgpu_acpi_get_node_id(xcc_info->handle, &xcc_info->numa_info);
+
+ /* TODO: check if this check is required */
+ if (ACPI_SUCCESS(status))
+ ret = 0;
+out:
+ if (obj)
+ ACPI_FREE(obj);
+
+ return ret;
+}
+
+static int amdgpu_acpi_enumerate_xcc(void)
+{
+ struct amdgpu_acpi_dev_info *dev_info = NULL;
+ struct amdgpu_acpi_xcc_info *xcc_info;
+ struct acpi_device *acpi_dev;
+ char hid[ACPI_ID_LEN];
+ int ret, id;
+ u16 bdf;
+
+ INIT_LIST_HEAD(&amdgpu_acpi_dev_list);
+ xa_init(&numa_info_xa);
+
+ for (id = 0; id < AMD_XCC_MAX_HID; id++) {
+ sprintf(hid, "%s%d", "AMD", AMD_XCC_HID_START + id);
+ acpi_dev = acpi_dev_get_first_match_dev(hid, NULL, -1);
+ /* These ACPI objects are expected to be in sequential order. If
+ * one is not found, no need to check the rest.
+ */
+ if (!acpi_dev) {
+ DRM_DEBUG_DRIVER("No matching acpi device found for %s",
+ hid);
+ break;
+ }
+
+ xcc_info = kzalloc(sizeof(struct amdgpu_acpi_xcc_info),
+ GFP_KERNEL);
+ if (!xcc_info) {
+ DRM_ERROR("Failed to allocate memory for xcc info\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&xcc_info->list);
+ xcc_info->handle = acpi_device_handle(acpi_dev);
+ acpi_dev_put(acpi_dev);
+
+ ret = amdgpu_acpi_get_xcc_info(xcc_info, &bdf);
+ if (ret) {
+ kfree(xcc_info);
+ continue;
+ }
+
+ dev_info = amdgpu_acpi_get_dev(bdf);
+
+ if (!dev_info)
+ ret = amdgpu_acpi_dev_init(&dev_info, xcc_info, bdf);
+
+ if (ret == -ENOMEM)
+ return ret;
+
+ if (!dev_info) {
+ kfree(xcc_info);
+ continue;
+ }
+
+ list_add_tail(&xcc_info->list, &dev_info->xcc_list);
+ }
+
+ return 0;
+}
+
+int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev, u64 *tmr_offset,
+ u64 *tmr_size)
+{
+ struct amdgpu_acpi_dev_info *dev_info;
+ u16 bdf;
+
+ if (!tmr_offset || !tmr_size)
+ return -EINVAL;
+
+ bdf = (adev->pdev->bus->number << 8) | adev->pdev->devfn;
+ dev_info = amdgpu_acpi_get_dev(bdf);
+ if (!dev_info)
+ return -ENOENT;
+
+ *tmr_offset = dev_info->tmr_base;
+ *tmr_size = dev_info->tmr_size;
+
+ return 0;
+}
+
+int amdgpu_acpi_get_mem_info(struct amdgpu_device *adev, int xcc_id,
+ struct amdgpu_numa_info *numa_info)
+{
+ struct amdgpu_acpi_dev_info *dev_info;
+ struct amdgpu_acpi_xcc_info *xcc_info;
+ u16 bdf;
+
+ if (!numa_info)
+ return -EINVAL;
+
+ bdf = (adev->pdev->bus->number << 8) | adev->pdev->devfn;
+ dev_info = amdgpu_acpi_get_dev(bdf);
+ if (!dev_info)
+ return -ENOENT;
+
+ list_for_each_entry(xcc_info, &dev_info->xcc_list, list) {
+ if (xcc_info->phy_id == xcc_id) {
+ memcpy(numa_info, xcc_info->numa_info,
+ sizeof(*numa_info));
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
/**
* amdgpu_acpi_event - handle notify events
*
@@ -1054,6 +1431,36 @@ void amdgpu_acpi_detect(void)
} else {
atif->backlight_caps.caps_valid = false;
}
+
+ amdgpu_acpi_enumerate_xcc();
+}
+
+void amdgpu_acpi_release(void)
+{
+ struct amdgpu_acpi_dev_info *dev_info, *dev_tmp;
+ struct amdgpu_acpi_xcc_info *xcc_info, *xcc_tmp;
+ struct amdgpu_numa_info *numa_info;
+ unsigned long index;
+
+ xa_for_each(&numa_info_xa, index, numa_info) {
+ kfree(numa_info);
+ xa_erase(&numa_info_xa, index);
+ }
+
+ if (list_empty(&amdgpu_acpi_dev_list))
+ return;
+
+ list_for_each_entry_safe(dev_info, dev_tmp, &amdgpu_acpi_dev_list,
+ list) {
+ list_for_each_entry_safe(xcc_info, xcc_tmp, &dev_info->xcc_list,
+ list) {
+ list_del(&xcc_info->list);
+ kfree(xcc_info);
+ }
+
+ list_del(&dev_info->list);
+ kfree(dev_info);
+ }
}
#if IS_ENABLED(CONFIG_SUSPEND)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index 0385f7f69278..b4fcad0e62f7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -53,7 +53,6 @@ int amdgpu_amdkfd_init(void)
amdgpu_amdkfd_total_mem_size *= si.mem_unit;
ret = kgd2kfd_init();
- amdgpu_amdkfd_gpuvm_init_mem_limits();
kfd_initialized = !ret;
return ret;
@@ -143,6 +142,8 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
int i;
int last_valid_bit;
+ amdgpu_amdkfd_gpuvm_init_mem_limits();
+
if (adev->kfd.dev) {
struct kgd2kfd_shared_resources gpu_resources = {
.compute_vmid_bitmap =
@@ -162,7 +163,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
* clear
*/
bitmap_complement(gpu_resources.cp_queue_bitmap,
- adev->gfx.mec.queue_bitmap,
+ adev->gfx.mec_bitmap[0].queue_bitmap,
KGD_MAX_QUEUES);
/* According to linux/bitmap.h we shouldn't use bitmap_clear if
@@ -427,14 +428,23 @@ uint32_t amdgpu_amdkfd_get_fw_version(struct amdgpu_device *adev,
}
void amdgpu_amdkfd_get_local_mem_info(struct amdgpu_device *adev,
- struct kfd_local_mem_info *mem_info)
+ struct kfd_local_mem_info *mem_info,
+ struct amdgpu_xcp *xcp)
{
memset(mem_info, 0, sizeof(*mem_info));
- mem_info->local_mem_size_public = adev->gmc.visible_vram_size;
- mem_info->local_mem_size_private = adev->gmc.real_vram_size -
+ if (xcp) {
+ if (adev->gmc.real_vram_size == adev->gmc.visible_vram_size)
+ mem_info->local_mem_size_public =
+ KFD_XCP_MEMORY_SIZE(adev, xcp->id);
+ else
+ mem_info->local_mem_size_private =
+ KFD_XCP_MEMORY_SIZE(adev, xcp->id);
+ } else {
+ mem_info->local_mem_size_public = adev->gmc.visible_vram_size;
+ mem_info->local_mem_size_private = adev->gmc.real_vram_size -
adev->gmc.visible_vram_size;
-
+ }
mem_info->vram_width = adev->gmc.vram_width;
pr_debug("Address base: %pap public 0x%llx private 0x%llx\n",
@@ -497,7 +507,7 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
struct amdgpu_device **dmabuf_adev,
uint64_t *bo_size, void *metadata_buffer,
size_t buffer_size, uint32_t *metadata_size,
- uint32_t *flags)
+ uint32_t *flags, int8_t *xcp_id)
{
struct dma_buf *dma_buf;
struct drm_gem_object *obj;
@@ -541,6 +551,8 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
if (bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
*flags |= KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC;
}
+ if (xcp_id)
+ *xcp_id = bo->xcp_id;
out_put:
dma_buf_put(dma_buf);
@@ -732,17 +744,19 @@ int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct amdgpu_device *adev,
if (adev->family == AMDGPU_FAMILY_AI) {
int i;
- for (i = 0; i < adev->num_vmhubs; i++)
+ for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
amdgpu_gmc_flush_gpu_tlb(adev, vmid, i, 0);
} else {
- amdgpu_gmc_flush_gpu_tlb(adev, vmid, AMDGPU_GFXHUB_0, 0);
+ amdgpu_gmc_flush_gpu_tlb(adev, vmid, AMDGPU_GFXHUB(0), 0);
}
return 0;
}
int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
- uint16_t pasid, enum TLB_FLUSH_TYPE flush_type)
+ uint16_t pasid,
+ enum TLB_FLUSH_TYPE flush_type,
+ uint32_t inst)
{
bool all_hub = false;
@@ -750,7 +764,7 @@ int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
adev->family == AMDGPU_FAMILY_RV)
all_hub = true;
- return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub);
+ return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub, inst);
}
bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev)
@@ -758,11 +772,32 @@ bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev)
return adev->have_atomics_support;
}
+void amdgpu_amdkfd_debug_mem_fence(struct amdgpu_device *adev)
+{
+ amdgpu_device_flush_hdp(adev, NULL);
+}
+
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bool reset)
{
amdgpu_umc_poison_handler(adev, reset);
}
+int amdgpu_amdkfd_send_close_event_drain_irq(struct amdgpu_device *adev,
+ uint32_t *payload)
+{
+ int ret;
+
+ /* Device or IH ring is not ready so bail. */
+ ret = amdgpu_ih_wait_on_checkpoint_process_ts(adev, &adev->irq.ih);
+ if (ret)
+ return ret;
+
+ /* Send payload to fence KFD interrupts */
+ amdgpu_amdkfd_interrupt(adev, payload);
+
+ return 0;
+}
+
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev)
{
if (adev->gfx.ras && adev->gfx.ras->query_utcl2_poison_status)
@@ -770,3 +805,28 @@ bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev)
else
return false;
}
+
+int amdgpu_amdkfd_check_and_lock_kfd(struct amdgpu_device *adev)
+{
+ return kgd2kfd_check_and_lock_kfd();
+}
+
+void amdgpu_amdkfd_unlock_kfd(struct amdgpu_device *adev)
+{
+ kgd2kfd_unlock_kfd();
+}
+
+
+u64 amdgpu_amdkfd_xcp_memory_size(struct amdgpu_device *adev, int xcp_id)
+{
+ u64 tmp;
+ s8 mem_id = KFD_XCP_MEM_ID(adev, xcp_id);
+
+ if (adev->gmc.num_mem_partitions && xcp_id >= 0 && mem_id >= 0) {
+ tmp = adev->gmc.mem_partitions[mem_id].size;
+ do_div(tmp, adev->xcp_mgr->num_xcp_per_mem_partition);
+ return ALIGN_DOWN(tmp, PAGE_SIZE);
+ } else {
+ return adev->gmc.real_vram_size;
+ }
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index 01ba3589b60a..2d0406bff84e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -30,10 +30,12 @@
#include <linux/kthread.h>
#include <linux/workqueue.h>
#include <linux/mmu_notifier.h>
+#include <linux/memremap.h>
#include <kgd_kfd_interface.h>
#include <drm/ttm/ttm_execbuf_util.h>
#include "amdgpu_sync.h"
#include "amdgpu_vm.h"
+#include "amdgpu_xcp.h"
extern uint64_t amdgpu_amdkfd_total_mem_size;
@@ -97,10 +99,13 @@ struct amdgpu_amdkfd_fence {
struct amdgpu_kfd_dev {
struct kfd_dev *dev;
- int64_t vram_used;
- uint64_t vram_used_aligned;
+ int64_t vram_used[MAX_XCP];
+ uint64_t vram_used_aligned[MAX_XCP];
bool init_complete;
struct work_struct reset_work;
+
+ /* HMM page migration MEMORY_DEVICE_PRIVATE mapping */
+ struct dev_pagemap pgmap;
};
enum kgd_engine_type {
@@ -151,6 +156,8 @@ void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev,
void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev);
void amdgpu_amdkfd_device_init(struct amdgpu_device *adev);
void amdgpu_amdkfd_device_fini_sw(struct amdgpu_device *adev);
+int amdgpu_amdkfd_check_and_lock_kfd(struct amdgpu_device *adev);
+void amdgpu_amdkfd_unlock_kfd(struct amdgpu_device *adev);
int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
enum kgd_engine_type engine,
uint32_t vmid, uint64_t gpu_addr,
@@ -160,7 +167,8 @@ bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev);
int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct amdgpu_device *adev,
uint16_t vmid);
int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
- uint16_t pasid, enum TLB_FLUSH_TYPE flush_type);
+ uint16_t pasid, enum TLB_FLUSH_TYPE flush_type,
+ uint32_t inst);
bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid);
@@ -224,7 +232,8 @@ int amdgpu_amdkfd_remove_gws_from_process(void *info, void *mem);
uint32_t amdgpu_amdkfd_get_fw_version(struct amdgpu_device *adev,
enum kgd_engine_type type);
void amdgpu_amdkfd_get_local_mem_info(struct amdgpu_device *adev,
- struct kfd_local_mem_info *mem_info);
+ struct kfd_local_mem_info *mem_info,
+ struct amdgpu_xcp *xcp);
uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct amdgpu_device *adev);
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev);
@@ -234,13 +243,15 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
struct amdgpu_device **dmabuf_adev,
uint64_t *bo_size, void *metadata_buffer,
size_t buffer_size, uint32_t *metadata_size,
- uint32_t *flags);
+ uint32_t *flags, int8_t *xcp_id);
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct amdgpu_device *dst,
struct amdgpu_device *src);
int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct amdgpu_device *dst,
struct amdgpu_device *src,
bool is_min);
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min);
+int amdgpu_amdkfd_send_close_event_drain_irq(struct amdgpu_device *adev,
+ uint32_t *payload);
/* Read user wptr from a specified user address space with page fault
* disabled. The memory must be pinned and mapped to the hardware when
@@ -279,7 +290,8 @@ int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev,
void amdgpu_amdkfd_gpuvm_release_process_vm(struct amdgpu_device *adev,
void *drm_priv);
uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv);
-size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev);
+size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev,
+ uint8_t xcp_id);
int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
struct amdgpu_device *adev, uint64_t va, uint64_t size,
void *drm_priv, struct kgd_mem **mem,
@@ -310,6 +322,7 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
uint64_t *mmap_offset);
int amdgpu_amdkfd_gpuvm_export_dmabuf(struct kgd_mem *mem,
struct dma_buf **dmabuf);
+void amdgpu_amdkfd_debug_mem_fence(struct amdgpu_device *adev);
int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev,
struct tile_config *config);
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev,
@@ -319,9 +332,18 @@ void amdgpu_amdkfd_block_mmu_notifications(void *p);
int amdgpu_amdkfd_criu_resume(void *p);
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev);
int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
- uint64_t size, u32 alloc_flag);
+ uint64_t size, u32 alloc_flag, int8_t xcp_id);
void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev,
- uint64_t size, u32 alloc_flag);
+ uint64_t size, u32 alloc_flag, int8_t xcp_id);
+
+u64 amdgpu_amdkfd_xcp_memory_size(struct amdgpu_device *adev, int xcp_id);
+
+#define KFD_XCP_MEM_ID(adev, xcp_id) \
+ ((adev)->xcp_mgr && (xcp_id) >= 0 ?\
+ (adev)->xcp_mgr->xcp[(xcp_id)].mem_id : -1)
+
+#define KFD_XCP_MEMORY_SIZE(adev, xcp_id) amdgpu_amdkfd_xcp_memory_size((adev), (xcp_id))
+
#if IS_ENABLED(CONFIG_HSA_AMD)
void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
@@ -352,6 +374,17 @@ void amdgpu_amdkfd_release_notify(struct amdgpu_bo *bo)
{
}
#endif
+
+#if IS_ENABLED(CONFIG_HSA_AMD_SVM)
+int kgd2kfd_init_zone_device(struct amdgpu_device *adev);
+#else
+static inline
+int kgd2kfd_init_zone_device(struct amdgpu_device *adev)
+{
+ return 0;
+}
+#endif
+
/* KGD2KFD callbacks */
int kgd2kfd_quiesce_mm(struct mm_struct *mm, uint32_t trigger);
int kgd2kfd_resume_mm(struct mm_struct *mm);
@@ -372,6 +405,8 @@ int kgd2kfd_post_reset(struct kfd_dev *kfd);
void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry);
void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd);
void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask);
+int kgd2kfd_check_and_lock_kfd(void);
+void kgd2kfd_unlock_kfd(void);
#else
static inline int kgd2kfd_init(void)
{
@@ -437,5 +472,14 @@ static inline
void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask)
{
}
+
+static inline int kgd2kfd_check_and_lock_kfd(void)
+{
+ return 0;
+}
+
+static inline void kgd2kfd_unlock_kfd(void)
+{
+}
#endif
#endif /* AMDGPU_AMDKFD_H_INCLUDED */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c
index 4485bb29bec9..60f9e027fb66 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c
@@ -23,6 +23,149 @@
#include "amdgpu_amdkfd.h"
#include "amdgpu_amdkfd_arcturus.h"
#include "amdgpu_amdkfd_gfx_v9.h"
+#include "gc/gc_9_4_2_offset.h"
+#include "gc/gc_9_4_2_sh_mask.h"
+#include <uapi/linux/kfd_ioctl.h>
+
+/*
+ * Returns TRAP_EN, EXCP_EN and EXCP_REPLACE.
+ *
+ * restore_dbg_registers is ignored here but is a general interface requirement
+ * for devices that support GFXOFF and where the RLC save/restore list
+ * does not support hw registers for debugging i.e. the driver has to manually
+ * initialize the debug mode registers after it has disabled GFX off during the
+ * debug session.
+ */
+static uint32_t kgd_aldebaran_enable_debug_trap(struct amdgpu_device *adev,
+ bool restore_dbg_registers,
+ uint32_t vmid)
+{
+ uint32_t data = 0;
+
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, 1);
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, 0);
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE, 0);
+
+ return data;
+}
+
+/* returns TRAP_EN, EXCP_EN and EXCP_REPLACE. */
+static uint32_t kgd_aldebaran_disable_debug_trap(struct amdgpu_device *adev,
+ bool keep_trap_enabled,
+ uint32_t vmid)
+{
+ uint32_t data = 0;
+
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, keep_trap_enabled);
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, 0);
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE, 0);
+
+ return data;
+}
+
+static int kgd_aldebaran_validate_trap_override_request(struct amdgpu_device *adev,
+ uint32_t trap_override,
+ uint32_t *trap_mask_supported)
+{
+ *trap_mask_supported &= KFD_DBG_TRAP_MASK_FP_INVALID |
+ KFD_DBG_TRAP_MASK_FP_INPUT_DENORMAL |
+ KFD_DBG_TRAP_MASK_FP_DIVIDE_BY_ZERO |
+ KFD_DBG_TRAP_MASK_FP_OVERFLOW |
+ KFD_DBG_TRAP_MASK_FP_UNDERFLOW |
+ KFD_DBG_TRAP_MASK_FP_INEXACT |
+ KFD_DBG_TRAP_MASK_INT_DIVIDE_BY_ZERO |
+ KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH |
+ KFD_DBG_TRAP_MASK_DBG_MEMORY_VIOLATION;
+
+ if (trap_override != KFD_DBG_TRAP_OVERRIDE_OR &&
+ trap_override != KFD_DBG_TRAP_OVERRIDE_REPLACE)
+ return -EPERM;
+
+ return 0;
+}
+
+/* returns TRAP_EN, EXCP_EN and EXCP_RPLACE. */
+static uint32_t kgd_aldebaran_set_wave_launch_trap_override(struct amdgpu_device *adev,
+ uint32_t vmid,
+ uint32_t trap_override,
+ uint32_t trap_mask_bits,
+ uint32_t trap_mask_request,
+ uint32_t *trap_mask_prev,
+ uint32_t kfd_dbg_trap_cntl_prev)
+
+{
+ uint32_t data = 0;
+
+ *trap_mask_prev = REG_GET_FIELD(kfd_dbg_trap_cntl_prev, SPI_GDBG_PER_VMID_CNTL, EXCP_EN);
+ trap_mask_bits = (trap_mask_bits & trap_mask_request) |
+ (*trap_mask_prev & ~trap_mask_request);
+
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, 1);
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, trap_mask_bits);
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE, trap_override);
+
+ return data;
+}
+
+static uint32_t kgd_aldebaran_set_wave_launch_mode(struct amdgpu_device *adev,
+ uint8_t wave_launch_mode,
+ uint32_t vmid)
+{
+ uint32_t data = 0;
+
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, LAUNCH_MODE, wave_launch_mode);
+
+ return data;
+}
+
+#define TCP_WATCH_STRIDE (regTCP_WATCH1_ADDR_H - regTCP_WATCH0_ADDR_H)
+static uint32_t kgd_gfx_aldebaran_set_address_watch(
+ struct amdgpu_device *adev,
+ uint64_t watch_address,
+ uint32_t watch_address_mask,
+ uint32_t watch_id,
+ uint32_t watch_mode,
+ uint32_t debug_vmid)
+{
+ uint32_t watch_address_high;
+ uint32_t watch_address_low;
+ uint32_t watch_address_cntl;
+
+ watch_address_cntl = 0;
+ watch_address_low = lower_32_bits(watch_address);
+ watch_address_high = upper_32_bits(watch_address) & 0xffff;
+
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ MODE,
+ watch_mode);
+
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ MASK,
+ watch_address_mask >> 6);
+
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ VALID,
+ 1);
+
+ WREG32_RLC((SOC15_REG_OFFSET(GC, 0, regTCP_WATCH0_ADDR_H) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_high);
+
+ WREG32_RLC((SOC15_REG_OFFSET(GC, 0, regTCP_WATCH0_ADDR_L) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_low);
+
+ return watch_address_cntl;
+}
+
+static uint32_t kgd_gfx_aldebaran_clear_address_watch(struct amdgpu_device *adev,
+ uint32_t watch_id)
+{
+ return 0;
+}
const struct kfd2kgd_calls aldebaran_kfd2kgd = {
.program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings,
@@ -42,5 +185,14 @@ const struct kfd2kgd_calls aldebaran_kfd2kgd = {
kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
.set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base,
.get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy,
- .program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings
+ .enable_debug_trap = kgd_aldebaran_enable_debug_trap,
+ .disable_debug_trap = kgd_aldebaran_disable_debug_trap,
+ .validate_trap_override_request = kgd_aldebaran_validate_trap_override_request,
+ .set_wave_launch_trap_override = kgd_aldebaran_set_wave_launch_trap_override,
+ .set_wave_launch_mode = kgd_aldebaran_set_wave_launch_mode,
+ .set_address_watch = kgd_gfx_aldebaran_set_address_watch,
+ .clear_address_watch = kgd_gfx_aldebaran_clear_address_watch,
+ .get_iq_wait_times = kgd_gfx_v9_get_iq_wait_times,
+ .build_grace_period_packet_info = kgd_gfx_v9_build_grace_period_packet_info,
+ .program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c
index 4191af5a3f13..625db444df1c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c
@@ -26,6 +26,7 @@
#include "amdgpu.h"
#include "amdgpu_amdkfd.h"
#include "amdgpu_amdkfd_arcturus.h"
+#include "amdgpu_reset.h"
#include "sdma0/sdma0_4_2_2_offset.h"
#include "sdma0/sdma0_4_2_2_sh_mask.h"
#include "sdma1/sdma1_4_2_2_offset.h"
@@ -48,6 +49,8 @@
#include "amdgpu_amdkfd_gfx_v9.h"
#include "gfxhub_v1_0.h"
#include "mmhub_v9_4.h"
+#include "gc/gc_9_0_offset.h"
+#include "gc/gc_9_0_sh_mask.h"
#define HQD_N_REGS 56
#define DUMP_REG(addr) do { \
@@ -276,6 +279,117 @@ int kgd_arcturus_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
return 0;
}
+/*
+ * Helper used to suspend/resume gfx pipe for image post process work to set
+ * barrier behaviour.
+ */
+static int suspend_resume_compute_scheduler(struct amdgpu_device *adev, bool suspend)
+{
+ int i, r = 0;
+
+ for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+ struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
+
+ if (!(ring && ring->sched.thread))
+ continue;
+
+ /* stop secheduler and drain ring. */
+ if (suspend) {
+ drm_sched_stop(&ring->sched, NULL);
+ r = amdgpu_fence_wait_empty(ring);
+ if (r)
+ goto out;
+ } else {
+ drm_sched_start(&ring->sched, false);
+ }
+ }
+
+out:
+ /* return on resume or failure to drain rings. */
+ if (!suspend || r)
+ return r;
+
+ return amdgpu_device_ip_wait_for_idle(adev, AMD_IP_BLOCK_TYPE_GFX);
+}
+
+static void set_barrier_auto_waitcnt(struct amdgpu_device *adev, bool enable_waitcnt)
+{
+ uint32_t data;
+
+ WRITE_ONCE(adev->barrier_has_auto_waitcnt, enable_waitcnt);
+
+ if (!down_read_trylock(&adev->reset_domain->sem))
+ return;
+
+ amdgpu_amdkfd_suspend(adev, false);
+
+ if (suspend_resume_compute_scheduler(adev, true))
+ goto out;
+
+ data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_CONFIG));
+ data = REG_SET_FIELD(data, SQ_CONFIG, DISABLE_BARRIER_WAITCNT,
+ !enable_waitcnt);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_CONFIG), data);
+
+out:
+ suspend_resume_compute_scheduler(adev, false);
+
+ amdgpu_amdkfd_resume(adev, false);
+
+ up_read(&adev->reset_domain->sem);
+}
+
+/*
+ * restore_dbg_registers is ignored here but is a general interface requirement
+ * for devices that support GFXOFF and where the RLC save/restore list
+ * does not support hw registers for debugging i.e. the driver has to manually
+ * initialize the debug mode registers after it has disabled GFX off during the
+ * debug session.
+ */
+static uint32_t kgd_arcturus_enable_debug_trap(struct amdgpu_device *adev,
+ bool restore_dbg_registers,
+ uint32_t vmid)
+{
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ kgd_gfx_v9_set_wave_launch_stall(adev, vmid, true);
+
+ set_barrier_auto_waitcnt(adev, true);
+
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
+
+ kgd_gfx_v9_set_wave_launch_stall(adev, vmid, false);
+
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return 0;
+}
+
+/*
+ * keep_trap_enabled is ignored here but is a general interface requirement
+ * for devices that support multi-process debugging where the performance
+ * overhead from trap temporary setup needs to be bypassed when the debug
+ * session has ended.
+ */
+static uint32_t kgd_arcturus_disable_debug_trap(struct amdgpu_device *adev,
+ bool keep_trap_enabled,
+ uint32_t vmid)
+{
+
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ kgd_gfx_v9_set_wave_launch_stall(adev, vmid, true);
+
+ set_barrier_auto_waitcnt(adev, false);
+
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
+
+ kgd_gfx_v9_set_wave_launch_stall(adev, vmid, false);
+
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return 0;
+}
const struct kfd2kgd_calls arcturus_kfd2kgd = {
.program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings,
.set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping,
@@ -294,6 +408,15 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = {
kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
.set_vm_context_page_table_base =
kgd_gfx_v9_set_vm_context_page_table_base,
+ .enable_debug_trap = kgd_arcturus_enable_debug_trap,
+ .disable_debug_trap = kgd_arcturus_disable_debug_trap,
+ .validate_trap_override_request = kgd_gfx_v9_validate_trap_override_request,
+ .set_wave_launch_trap_override = kgd_gfx_v9_set_wave_launch_trap_override,
+ .set_wave_launch_mode = kgd_gfx_v9_set_wave_launch_mode,
+ .set_address_watch = kgd_gfx_v9_set_address_watch,
+ .clear_address_watch = kgd_gfx_v9_clear_address_watch,
+ .get_iq_wait_times = kgd_gfx_v9_get_iq_wait_times,
+ .build_grace_period_packet_info = kgd_gfx_v9_build_grace_period_packet_info,
.get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy,
.program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c
new file mode 100644
index 000000000000..5b4b7f8b92a5
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "amdgpu.h"
+#include "amdgpu_amdkfd.h"
+#include "amdgpu_amdkfd_gfx_v9.h"
+#include "gc/gc_9_4_3_offset.h"
+#include "gc/gc_9_4_3_sh_mask.h"
+#include "athub/athub_1_8_0_offset.h"
+#include "athub/athub_1_8_0_sh_mask.h"
+#include "oss/osssys_4_4_2_offset.h"
+#include "oss/osssys_4_4_2_sh_mask.h"
+#include "v9_structs.h"
+#include "soc15.h"
+#include "sdma/sdma_4_4_2_offset.h"
+#include "sdma/sdma_4_4_2_sh_mask.h"
+
+static inline struct v9_sdma_mqd *get_sdma_mqd(void *mqd)
+{
+ return (struct v9_sdma_mqd *)mqd;
+}
+
+static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev,
+ unsigned int engine_id,
+ unsigned int queue_id)
+{
+ uint32_t sdma_engine_reg_base =
+ SOC15_REG_OFFSET(SDMA0, GET_INST(SDMA0, engine_id),
+ regSDMA_RLC0_RB_CNTL) -
+ regSDMA_RLC0_RB_CNTL;
+ uint32_t retval = sdma_engine_reg_base +
+ queue_id * (regSDMA_RLC1_RB_CNTL - regSDMA_RLC0_RB_CNTL);
+
+ pr_debug("RLC register offset for SDMA%d RLC%d: 0x%x\n", engine_id,
+ queue_id, retval);
+ return retval;
+}
+
+static int kgd_gfx_v9_4_3_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
+ uint32_t __user *wptr, struct mm_struct *mm)
+{
+ struct v9_sdma_mqd *m;
+ uint32_t sdma_rlc_reg_offset;
+ unsigned long end_jiffies;
+ uint32_t data;
+ uint64_t data64;
+ uint64_t __user *wptr64 = (uint64_t __user *)wptr;
+
+ m = get_sdma_mqd(mqd);
+ sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
+ m->sdma_queue_id);
+
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL,
+ m->sdmax_rlcx_rb_cntl & (~SDMA_RLC0_RB_CNTL__RB_ENABLE_MASK));
+
+ end_jiffies = msecs_to_jiffies(2000) + jiffies;
+ while (true) {
+ data = RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_CONTEXT_STATUS);
+ if (data & SDMA_RLC0_CONTEXT_STATUS__IDLE_MASK)
+ break;
+ if (time_after(jiffies, end_jiffies)) {
+ pr_err("SDMA RLC not idle in %s\n", __func__);
+ return -ETIME;
+ }
+ usleep_range(500, 1000);
+ }
+
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_DOORBELL_OFFSET,
+ m->sdmax_rlcx_doorbell_offset);
+
+ data = REG_SET_FIELD(m->sdmax_rlcx_doorbell, SDMA_RLC0_DOORBELL,
+ ENABLE, 1);
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_DOORBELL, data);
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_RPTR,
+ m->sdmax_rlcx_rb_rptr);
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_RPTR_HI,
+ m->sdmax_rlcx_rb_rptr_hi);
+
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_MINOR_PTR_UPDATE, 1);
+ if (read_user_wptr(mm, wptr64, data64)) {
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_WPTR,
+ lower_32_bits(data64));
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_WPTR_HI,
+ upper_32_bits(data64));
+ } else {
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_WPTR,
+ m->sdmax_rlcx_rb_rptr);
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_WPTR_HI,
+ m->sdmax_rlcx_rb_rptr_hi);
+ }
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_MINOR_PTR_UPDATE, 0);
+
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_BASE_HI,
+ m->sdmax_rlcx_rb_base_hi);
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_RPTR_ADDR_LO,
+ m->sdmax_rlcx_rb_rptr_addr_lo);
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_RPTR_ADDR_HI,
+ m->sdmax_rlcx_rb_rptr_addr_hi);
+
+ data = REG_SET_FIELD(m->sdmax_rlcx_rb_cntl, SDMA_RLC0_RB_CNTL,
+ RB_ENABLE, 1);
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL, data);
+
+ return 0;
+}
+
+static int kgd_gfx_v9_4_3_hqd_sdma_dump(struct amdgpu_device *adev,
+ uint32_t engine_id, uint32_t queue_id,
+ uint32_t (**dump)[2], uint32_t *n_regs)
+{
+ uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
+ engine_id, queue_id);
+ uint32_t i = 0, reg;
+#undef HQD_N_REGS
+#define HQD_N_REGS (19+6+7+12)
+#define DUMP_REG(addr) do { \
+ if (WARN_ON_ONCE(i >= HQD_N_REGS)) \
+ break; \
+ (*dump)[i][0] = (addr) << 2; \
+ (*dump)[i++][1] = RREG32(addr); \
+ } while (0)
+
+ *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL);
+ if (*dump == NULL)
+ return -ENOMEM;
+
+ for (reg = regSDMA_RLC0_RB_CNTL; reg <= regSDMA_RLC0_DOORBELL; reg++)
+ DUMP_REG(sdma_rlc_reg_offset + reg);
+ for (reg = regSDMA_RLC0_STATUS; reg <= regSDMA_RLC0_CSA_ADDR_HI; reg++)
+ DUMP_REG(sdma_rlc_reg_offset + reg);
+ for (reg = regSDMA_RLC0_IB_SUB_REMAIN;
+ reg <= regSDMA_RLC0_MINOR_PTR_UPDATE; reg++)
+ DUMP_REG(sdma_rlc_reg_offset + reg);
+ for (reg = regSDMA_RLC0_MIDCMD_DATA0;
+ reg <= regSDMA_RLC0_MIDCMD_CNTL; reg++)
+ DUMP_REG(sdma_rlc_reg_offset + reg);
+
+ WARN_ON_ONCE(i != HQD_N_REGS);
+ *n_regs = i;
+
+ return 0;
+}
+
+static bool kgd_gfx_v9_4_3_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
+{
+ struct v9_sdma_mqd *m;
+ uint32_t sdma_rlc_reg_offset;
+ uint32_t sdma_rlc_rb_cntl;
+
+ m = get_sdma_mqd(mqd);
+ sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
+ m->sdma_queue_id);
+
+ sdma_rlc_rb_cntl = RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL);
+
+ if (sdma_rlc_rb_cntl & SDMA_RLC0_RB_CNTL__RB_ENABLE_MASK)
+ return true;
+
+ return false;
+}
+
+static int kgd_gfx_v9_4_3_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
+ unsigned int utimeout)
+{
+ struct v9_sdma_mqd *m;
+ uint32_t sdma_rlc_reg_offset;
+ uint32_t temp;
+ unsigned long end_jiffies = (utimeout * HZ / 1000) + jiffies;
+
+ m = get_sdma_mqd(mqd);
+ sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
+ m->sdma_queue_id);
+
+ temp = RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL);
+ temp = temp & ~SDMA_RLC0_RB_CNTL__RB_ENABLE_MASK;
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL, temp);
+
+ while (true) {
+ temp = RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_CONTEXT_STATUS);
+ if (temp & SDMA_RLC0_CONTEXT_STATUS__IDLE_MASK)
+ break;
+ if (time_after(jiffies, end_jiffies)) {
+ pr_err("SDMA RLC not idle in %s\n", __func__);
+ return -ETIME;
+ }
+ usleep_range(500, 1000);
+ }
+
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_DOORBELL, 0);
+ WREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL,
+ RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_CNTL) |
+ SDMA_RLC0_RB_CNTL__RB_ENABLE_MASK);
+
+ m->sdmax_rlcx_rb_rptr =
+ RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_RPTR);
+ m->sdmax_rlcx_rb_rptr_hi =
+ RREG32(sdma_rlc_reg_offset + regSDMA_RLC0_RB_RPTR_HI);
+
+ return 0;
+}
+
+static int kgd_gfx_v9_4_3_set_pasid_vmid_mapping(struct amdgpu_device *adev,
+ u32 pasid, unsigned int vmid, uint32_t xcc_inst)
+{
+ unsigned long timeout;
+ unsigned int reg;
+ unsigned int phy_inst = GET_INST(GC, xcc_inst);
+ /* Every two XCCs share one AID */
+ unsigned int aid = phy_inst / 2;
+
+ /*
+ * We have to assume that there is no outstanding mapping.
+ * The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
+ * a mapping is in progress or because a mapping finished
+ * and the SW cleared it.
+ * So the protocol is to always wait & clear.
+ */
+ uint32_t pasid_mapping = (pasid == 0) ? 0 : (uint32_t)pasid |
+ ATC_VMID0_PASID_MAPPING__VALID_MASK;
+
+ WREG32(SOC15_REG_OFFSET(ATHUB, 0,
+ regATC_VMID0_PASID_MAPPING) + vmid, pasid_mapping);
+
+ timeout = jiffies + msecs_to_jiffies(10);
+ while (!(RREG32(SOC15_REG_OFFSET(ATHUB, 0,
+ regATC_VMID_PASID_MAPPING_UPDATE_STATUS)) &
+ (1U << vmid))) {
+ if (time_after(jiffies, timeout)) {
+ pr_err("Fail to program VMID-PASID mapping\n");
+ return -ETIME;
+ }
+ cpu_relax();
+ }
+
+ WREG32(SOC15_REG_OFFSET(ATHUB, 0,
+ regATC_VMID_PASID_MAPPING_UPDATE_STATUS),
+ 1U << vmid);
+
+ reg = RREG32(SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_LUT_INDEX));
+ /* Every 4 numbers is a cycle. 1st is AID, 2nd and 3rd are XCDs,
+ * and the 4th is reserved. Therefore "aid * 4 + (xcc_inst % 2) + 1"
+ * programs _LUT for XCC and "aid * 4" for AID where the XCC connects
+ * to.
+ */
+ WREG32(SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_LUT_INDEX),
+ aid * 4 + (phy_inst % 2) + 1);
+ WREG32(SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_0_LUT) + vmid,
+ pasid_mapping);
+ WREG32(SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_LUT_INDEX),
+ aid * 4);
+ WREG32(SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_0_LUT_MM) + vmid,
+ pasid_mapping);
+ WREG32(SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_LUT_INDEX), reg);
+
+ return 0;
+}
+
+static inline struct v9_mqd *get_mqd(void *mqd)
+{
+ return (struct v9_mqd *)mqd;
+}
+
+static int kgd_gfx_v9_4_3_hqd_load(struct amdgpu_device *adev, void *mqd,
+ uint32_t pipe_id, uint32_t queue_id,
+ uint32_t __user *wptr, uint32_t wptr_shift,
+ uint32_t wptr_mask, struct mm_struct *mm, uint32_t inst)
+{
+ struct v9_mqd *m;
+ uint32_t *mqd_hqd;
+ uint32_t reg, hqd_base, hqd_end, data;
+
+ m = get_mqd(mqd);
+
+ kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
+
+ /* HQD registers extend to CP_HQD_AQL_DISPATCH_ID_HI */
+ mqd_hqd = &m->cp_mqd_base_addr_lo;
+ hqd_base = SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_MQD_BASE_ADDR);
+ hqd_end = SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_AQL_DISPATCH_ID_HI);
+
+ for (reg = hqd_base; reg <= hqd_end; reg++)
+ WREG32_RLC(reg, mqd_hqd[reg - hqd_base]);
+
+
+ /* Activate doorbell logic before triggering WPTR poll. */
+ data = REG_SET_FIELD(m->cp_hqd_pq_doorbell_control,
+ CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1);
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_DOORBELL_CONTROL),
+ data);
+
+ if (wptr) {
+ /* Don't read wptr with get_user because the user
+ * context may not be accessible (if this function
+ * runs in a work queue). Instead trigger a one-shot
+ * polling read from memory in the CP. This assumes
+ * that wptr is GPU-accessible in the queue's VMID via
+ * ATC or SVM. WPTR==RPTR before starting the poll so
+ * the CP starts fetching new commands from the right
+ * place.
+ *
+ * Guessing a 64-bit WPTR from a 32-bit RPTR is a bit
+ * tricky. Assume that the queue didn't overflow. The
+ * number of valid bits in the 32-bit RPTR depends on
+ * the queue size. The remaining bits are taken from
+ * the saved 64-bit WPTR. If the WPTR wrapped, add the
+ * queue size.
+ */
+ uint32_t queue_size =
+ 2 << REG_GET_FIELD(m->cp_hqd_pq_control,
+ CP_HQD_PQ_CONTROL, QUEUE_SIZE);
+ uint64_t guessed_wptr = m->cp_hqd_pq_rptr & (queue_size - 1);
+
+ if ((m->cp_hqd_pq_wptr_lo & (queue_size - 1)) < guessed_wptr)
+ guessed_wptr += queue_size;
+ guessed_wptr += m->cp_hqd_pq_wptr_lo & ~(queue_size - 1);
+ guessed_wptr += (uint64_t)m->cp_hqd_pq_wptr_hi << 32;
+
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_LO),
+ lower_32_bits(guessed_wptr));
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_HI),
+ upper_32_bits(guessed_wptr));
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_PQ_WPTR_POLL_ADDR),
+ lower_32_bits((uintptr_t)wptr));
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
+ regCP_HQD_PQ_WPTR_POLL_ADDR_HI),
+ upper_32_bits((uintptr_t)wptr));
+ WREG32(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_PQ_WPTR_POLL_CNTL1),
+ (uint32_t)kgd_gfx_v9_get_queue_mask(adev, pipe_id,
+ queue_id));
+ }
+
+ /* Start the EOP fetcher */
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_EOP_RPTR),
+ REG_SET_FIELD(m->cp_hqd_eop_rptr,
+ CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
+
+ data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), regCP_HQD_ACTIVE), data);
+
+ kgd_gfx_v9_release_queue(adev, inst);
+
+ return 0;
+}
+
+const struct kfd2kgd_calls gc_9_4_3_kfd2kgd = {
+ .program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings,
+ .set_pasid_vmid_mapping = kgd_gfx_v9_4_3_set_pasid_vmid_mapping,
+ .init_interrupts = kgd_gfx_v9_init_interrupts,
+ .hqd_load = kgd_gfx_v9_4_3_hqd_load,
+ .hiq_mqd_load = kgd_gfx_v9_hiq_mqd_load,
+ .hqd_sdma_load = kgd_gfx_v9_4_3_hqd_sdma_load,
+ .hqd_dump = kgd_gfx_v9_hqd_dump,
+ .hqd_sdma_dump = kgd_gfx_v9_4_3_hqd_sdma_dump,
+ .hqd_is_occupied = kgd_gfx_v9_hqd_is_occupied,
+ .hqd_sdma_is_occupied = kgd_gfx_v9_4_3_hqd_sdma_is_occupied,
+ .hqd_destroy = kgd_gfx_v9_hqd_destroy,
+ .hqd_sdma_destroy = kgd_gfx_v9_4_3_hqd_sdma_destroy,
+ .wave_control_execute = kgd_gfx_v9_wave_control_execute,
+ .get_atc_vmid_pasid_mapping_info =
+ kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
+ .set_vm_context_page_table_base =
+ kgd_gfx_v9_set_vm_context_page_table_base,
+ .program_trap_handler_settings =
+ kgd_gfx_v9_program_trap_handler_settings
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
index 9378fc79e9ea..8ad7a7779e14 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
@@ -21,6 +21,7 @@
*/
#include "amdgpu.h"
#include "amdgpu_amdkfd.h"
+#include "amdgpu_amdkfd_gfx_v10.h"
#include "gc/gc_10_1_0_offset.h"
#include "gc/gc_10_1_0_sh_mask.h"
#include "athub/athub_2_0_0_offset.h"
@@ -31,6 +32,7 @@
#include "v10_structs.h"
#include "nv.h"
#include "nvd.h"
+#include <uapi/linux/kfd_ioctl.h>
enum hqd_dequeue_request_type {
NO_ACTION = 0,
@@ -79,7 +81,7 @@ static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
uint32_t sh_mem_config,
uint32_t sh_mem_ape1_base,
uint32_t sh_mem_ape1_limit,
- uint32_t sh_mem_bases)
+ uint32_t sh_mem_bases, uint32_t inst)
{
lock_srbm(adev, 0, 0, 0, vmid);
@@ -91,7 +93,7 @@ static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
}
static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
- unsigned int vmid)
+ unsigned int vmid, uint32_t inst)
{
/*
* We have to assume that there is no outstanding mapping.
@@ -135,7 +137,8 @@ static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
* but still works
*/
-static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
+static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id,
+ uint32_t inst)
{
uint32_t mec;
uint32_t pipe;
@@ -205,7 +208,7 @@ static inline struct v10_sdma_mqd *get_sdma_mqd(void *mqd)
static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
uint32_t pipe_id, uint32_t queue_id,
uint32_t __user *wptr, uint32_t wptr_shift,
- uint32_t wptr_mask, struct mm_struct *mm)
+ uint32_t wptr_mask, struct mm_struct *mm, uint32_t inst)
{
struct v10_compute_mqd *m;
uint32_t *mqd_hqd;
@@ -286,9 +289,9 @@ static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
static int kgd_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t doorbell_off)
+ uint32_t doorbell_off, uint32_t inst)
{
- struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
+ struct amdgpu_ring *kiq_ring = &adev->gfx.kiq[0].ring;
struct v10_compute_mqd *m;
uint32_t mec, pipe;
int r;
@@ -303,7 +306,7 @@ static int kgd_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
pr_debug("kfd: set HIQ, mec:%d, pipe:%d, queue:%d.\n",
mec, pipe, queue_id);
- spin_lock(&adev->gfx.kiq.ring_lock);
+ spin_lock(&adev->gfx.kiq[0].ring_lock);
r = amdgpu_ring_alloc(kiq_ring, 7);
if (r) {
pr_err("Failed to alloc KIQ (%d).\n", r);
@@ -330,7 +333,7 @@ static int kgd_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
amdgpu_ring_commit(kiq_ring);
out_unlock:
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&adev->gfx.kiq[0].ring_lock);
release_queue(adev);
return r;
@@ -338,7 +341,7 @@ out_unlock:
static int kgd_hqd_dump(struct amdgpu_device *adev,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t (**dump)[2], uint32_t *n_regs)
+ uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst)
{
uint32_t i = 0, reg;
#define HQD_N_REGS 56
@@ -469,7 +472,7 @@ static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
static bool kgd_hqd_is_occupied(struct amdgpu_device *adev,
uint64_t queue_address, uint32_t pipe_id,
- uint32_t queue_id)
+ uint32_t queue_id, uint32_t inst)
{
uint32_t act;
bool retval = false;
@@ -510,7 +513,7 @@ static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
static int kgd_hqd_destroy(struct amdgpu_device *adev, void *mqd,
enum kfd_preempt_type reset_type,
unsigned int utimeout, uint32_t pipe_id,
- uint32_t queue_id)
+ uint32_t queue_id, uint32_t inst)
{
enum hqd_dequeue_request_type type;
unsigned long end_jiffies;
@@ -673,7 +676,7 @@ static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
static int kgd_wave_control_execute(struct amdgpu_device *adev,
uint32_t gfx_index_val,
- uint32_t sq_cmd)
+ uint32_t sq_cmd, uint32_t inst)
{
uint32_t data = 0;
@@ -708,8 +711,295 @@ static void set_vm_context_page_table_base(struct amdgpu_device *adev,
adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base);
}
+/*
+ * GFX10 helper for wave launch stall requirements on debug trap setting.
+ *
+ * vmid:
+ * Target VMID to stall/unstall.
+ *
+ * stall:
+ * 0-unstall wave launch (enable), 1-stall wave launch (disable).
+ * After wavefront launch has been stalled, allocated waves must drain from
+ * SPI in order for debug trap settings to take effect on those waves.
+ * This is roughly a ~3500 clock cycle wait on SPI where a read on
+ * SPI_GDBG_WAVE_CNTL translates to ~32 clock cycles.
+ * KGD_GFX_V10_WAVE_LAUNCH_SPI_DRAIN_LATENCY indicates the number of reads required.
+ *
+ * NOTE: We can afford to clear the entire STALL_VMID field on unstall
+ * because current GFX10 chips cannot support multi-process debugging due to
+ * trap configuration and masking being limited to global scope. Always
+ * assume single process conditions.
+ *
+ */
+
+#define KGD_GFX_V10_WAVE_LAUNCH_SPI_DRAIN_LATENCY 110
+static void kgd_gfx_v10_set_wave_launch_stall(struct amdgpu_device *adev, uint32_t vmid, bool stall)
+{
+ uint32_t data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
+ int i;
+
+ data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_VMID,
+ stall ? 1 << vmid : 0);
+
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
+
+ if (!stall)
+ return;
+
+ for (i = 0; i < KGD_GFX_V10_WAVE_LAUNCH_SPI_DRAIN_LATENCY; i++)
+ RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
+}
+
+uint32_t kgd_gfx_v10_enable_debug_trap(struct amdgpu_device *adev,
+ bool restore_dbg_registers,
+ uint32_t vmid)
+{
+
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ kgd_gfx_v10_set_wave_launch_stall(adev, vmid, true);
+
+ /* assume gfx off is disabled for the debug session if rlc restore not supported. */
+ if (restore_dbg_registers) {
+ uint32_t data = 0;
+
+ data = REG_SET_FIELD(data, SPI_GDBG_TRAP_CONFIG,
+ VMID_SEL, 1 << vmid);
+ data = REG_SET_FIELD(data, SPI_GDBG_TRAP_CONFIG,
+ TRAP_EN, 1);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_CONFIG), data);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_DATA0), 0);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_DATA1), 0);
+
+ kgd_gfx_v10_set_wave_launch_stall(adev, vmid, false);
+
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return 0;
+ }
+
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
+
+ kgd_gfx_v10_set_wave_launch_stall(adev, vmid, false);
+
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return 0;
+}
+
+uint32_t kgd_gfx_v10_disable_debug_trap(struct amdgpu_device *adev,
+ bool keep_trap_enabled,
+ uint32_t vmid)
+{
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ kgd_gfx_v10_set_wave_launch_stall(adev, vmid, true);
+
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
+
+ kgd_gfx_v10_set_wave_launch_stall(adev, vmid, false);
+
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return 0;
+}
+
+int kgd_gfx_v10_validate_trap_override_request(struct amdgpu_device *adev,
+ uint32_t trap_override,
+ uint32_t *trap_mask_supported)
+{
+ *trap_mask_supported &= KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH;
+
+ /* The SPI_GDBG_TRAP_MASK register is global and affects all
+ * processes. Only allow OR-ing the address-watch bit, since
+ * this only affects processes under the debugger. Other bits
+ * should stay 0 to avoid the debugger interfering with other
+ * processes.
+ */
+ if (trap_override != KFD_DBG_TRAP_OVERRIDE_OR)
+ return -EINVAL;
+
+ return 0;
+}
+
+uint32_t kgd_gfx_v10_set_wave_launch_trap_override(struct amdgpu_device *adev,
+ uint32_t vmid,
+ uint32_t trap_override,
+ uint32_t trap_mask_bits,
+ uint32_t trap_mask_request,
+ uint32_t *trap_mask_prev,
+ uint32_t kfd_dbg_trap_cntl_prev)
+{
+ uint32_t data, wave_cntl_prev;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ wave_cntl_prev = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
+
+ kgd_gfx_v10_set_wave_launch_stall(adev, vmid, true);
+
+ data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK));
+ *trap_mask_prev = REG_GET_FIELD(data, SPI_GDBG_TRAP_MASK, EXCP_EN);
+
+ trap_mask_bits = (trap_mask_bits & trap_mask_request) |
+ (*trap_mask_prev & ~trap_mask_request);
+
+ data = REG_SET_FIELD(data, SPI_GDBG_TRAP_MASK, EXCP_EN, trap_mask_bits);
+ data = REG_SET_FIELD(data, SPI_GDBG_TRAP_MASK, REPLACE, trap_override);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), data);
+
+ /* We need to preserve wave launch mode stall settings. */
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), wave_cntl_prev);
+
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return 0;
+}
+
+uint32_t kgd_gfx_v10_set_wave_launch_mode(struct amdgpu_device *adev,
+ uint8_t wave_launch_mode,
+ uint32_t vmid)
+{
+ uint32_t data = 0;
+ bool is_mode_set = !!wave_launch_mode;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ kgd_gfx_v10_set_wave_launch_stall(adev, vmid, true);
+
+ data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL2,
+ VMID_MASK, is_mode_set ? 1 << vmid : 0);
+ data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL2,
+ MODE, is_mode_set ? wave_launch_mode : 0);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL2), data);
+
+ kgd_gfx_v10_set_wave_launch_stall(adev, vmid, false);
+
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return 0;
+}
+
+#define TCP_WATCH_STRIDE (mmTCP_WATCH1_ADDR_H - mmTCP_WATCH0_ADDR_H)
+uint32_t kgd_gfx_v10_set_address_watch(struct amdgpu_device *adev,
+ uint64_t watch_address,
+ uint32_t watch_address_mask,
+ uint32_t watch_id,
+ uint32_t watch_mode,
+ uint32_t debug_vmid)
+{
+ uint32_t watch_address_high;
+ uint32_t watch_address_low;
+ uint32_t watch_address_cntl;
+
+ watch_address_cntl = 0;
+
+ watch_address_low = lower_32_bits(watch_address);
+ watch_address_high = upper_32_bits(watch_address) & 0xffff;
+
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ VMID,
+ debug_vmid);
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ MODE,
+ watch_mode);
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ MASK,
+ watch_address_mask >> 7);
+
+ /* Turning off this watch point until we set all the registers */
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ VALID,
+ 0);
+
+ WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_cntl);
+
+ WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_H) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_high);
+
+ WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_L) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_low);
+
+ /* Enable the watch point */
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ VALID,
+ 1);
+
+ WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_cntl);
+
+ return 0;
+}
+
+uint32_t kgd_gfx_v10_clear_address_watch(struct amdgpu_device *adev,
+ uint32_t watch_id)
+{
+ uint32_t watch_address_cntl;
+
+ watch_address_cntl = 0;
+
+ WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_cntl);
+
+ return 0;
+}
+
+
+/* kgd_gfx_v10_get_iq_wait_times: Returns the mmCP_IQ_WAIT_TIME1/2 values
+ * The values read are:
+ * ib_offload_wait_time -- Wait Count for Indirect Buffer Offloads.
+ * atomic_offload_wait_time -- Wait Count for L2 and GDS Atomics Offloads.
+ * wrm_offload_wait_time -- Wait Count for WAIT_REG_MEM Offloads.
+ * gws_wait_time -- Wait Count for Global Wave Syncs.
+ * que_sleep_wait_time -- Wait Count for Dequeue Retry.
+ * sch_wave_wait_time -- Wait Count for Scheduling Wave Message.
+ * sem_rearm_wait_time -- Wait Count for Semaphore re-arm.
+ * deq_retry_wait_time -- Wait Count for Global Wave Syncs.
+ */
+void kgd_gfx_v10_get_iq_wait_times(struct amdgpu_device *adev,
+ uint32_t *wait_times)
+
+{
+ *wait_times = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2));
+}
+
+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)
+{
+ *reg_data = wait_times;
+
+ /*
+ * The CP cannont handle a 0 grace period input and will result in
+ * an infinite grace period being set so set to 1 to prevent this.
+ */
+ if (grace_period == 0)
+ grace_period = 1;
+
+ *reg_data = REG_SET_FIELD(*reg_data,
+ CP_IQ_WAIT_TIME2,
+ SCH_WAVE,
+ grace_period);
+
+ *reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2);
+}
+
static void program_trap_handler_settings(struct amdgpu_device *adev,
- uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
+ uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr,
+ uint32_t inst)
{
lock_srbm(adev, 0, 0, 0, vmid);
@@ -750,5 +1040,14 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = {
.get_atc_vmid_pasid_mapping_info =
get_atc_vmid_pasid_mapping_info,
.set_vm_context_page_table_base = set_vm_context_page_table_base,
+ .enable_debug_trap = kgd_gfx_v10_enable_debug_trap,
+ .disable_debug_trap = kgd_gfx_v10_disable_debug_trap,
+ .validate_trap_override_request = kgd_gfx_v10_validate_trap_override_request,
+ .set_wave_launch_trap_override = kgd_gfx_v10_set_wave_launch_trap_override,
+ .set_wave_launch_mode = kgd_gfx_v10_set_wave_launch_mode,
+ .set_address_watch = kgd_gfx_v10_set_address_watch,
+ .clear_address_watch = kgd_gfx_v10_clear_address_watch,
+ .get_iq_wait_times = kgd_gfx_v10_get_iq_wait_times,
+ .build_grace_period_packet_info = kgd_gfx_v10_build_grace_period_packet_info,
.program_trap_handler_settings = program_trap_handler_settings,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.h
new file mode 100644
index 000000000000..e6b70196071a
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+uint32_t kgd_gfx_v10_enable_debug_trap(struct amdgpu_device *adev,
+ bool restore_dbg_registers,
+ uint32_t vmid);
+uint32_t kgd_gfx_v10_disable_debug_trap(struct amdgpu_device *adev,
+ bool keep_trap_enabled,
+ uint32_t vmid);
+int kgd_gfx_v10_validate_trap_override_request(struct amdgpu_device *adev,
+ uint32_t trap_override,
+ uint32_t *trap_mask_supported);
+uint32_t kgd_gfx_v10_set_wave_launch_trap_override(struct amdgpu_device *adev,
+ uint32_t vmid,
+ uint32_t trap_override,
+ uint32_t trap_mask_bits,
+ uint32_t trap_mask_request,
+ uint32_t *trap_mask_prev,
+ uint32_t kfd_dbg_trap_cntl_prev);
+uint32_t kgd_gfx_v10_set_wave_launch_mode(struct amdgpu_device *adev,
+ uint8_t wave_launch_mode,
+ uint32_t vmid);
+uint32_t kgd_gfx_v10_set_address_watch(struct amdgpu_device *adev,
+ uint64_t watch_address,
+ uint32_t watch_address_mask,
+ uint32_t watch_id,
+ uint32_t watch_mode,
+ uint32_t debug_vmid);
+uint32_t kgd_gfx_v10_clear_address_watch(struct amdgpu_device *adev,
+ uint32_t watch_id);
+void kgd_gfx_v10_get_iq_wait_times(struct amdgpu_device *adev, uint32_t *wait_times);
+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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c
index ba21ec6b35e0..8c8437a4383f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c
@@ -22,6 +22,7 @@
#include <linux/mmu_context.h>
#include "amdgpu.h"
#include "amdgpu_amdkfd.h"
+#include "amdgpu_amdkfd_gfx_v10.h"
#include "gc/gc_10_3_0_offset.h"
#include "gc/gc_10_3_0_sh_mask.h"
#include "oss/osssys_5_0_0_offset.h"
@@ -80,7 +81,7 @@ static void program_sh_mem_settings_v10_3(struct amdgpu_device *adev, uint32_t v
uint32_t sh_mem_config,
uint32_t sh_mem_ape1_base,
uint32_t sh_mem_ape1_limit,
- uint32_t sh_mem_bases)
+ uint32_t sh_mem_bases, uint32_t inst)
{
lock_srbm(adev, 0, 0, 0, vmid);
@@ -93,7 +94,7 @@ static void program_sh_mem_settings_v10_3(struct amdgpu_device *adev, uint32_t v
/* ATC is defeatured on Sienna_Cichlid */
static int set_pasid_vmid_mapping_v10_3(struct amdgpu_device *adev, unsigned int pasid,
- unsigned int vmid)
+ unsigned int vmid, uint32_t inst)
{
uint32_t value = pasid << IH_VMID_0_LUT__PASID__SHIFT;
@@ -105,7 +106,8 @@ static int set_pasid_vmid_mapping_v10_3(struct amdgpu_device *adev, unsigned int
return 0;
}
-static int init_interrupts_v10_3(struct amdgpu_device *adev, uint32_t pipe_id)
+static int init_interrupts_v10_3(struct amdgpu_device *adev, uint32_t pipe_id,
+ uint32_t inst)
{
uint32_t mec;
uint32_t pipe;
@@ -177,7 +179,7 @@ static inline struct v10_sdma_mqd *get_sdma_mqd(void *mqd)
static int hqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
uint32_t pipe_id, uint32_t queue_id,
uint32_t __user *wptr, uint32_t wptr_shift,
- uint32_t wptr_mask, struct mm_struct *mm)
+ uint32_t wptr_mask, struct mm_struct *mm, uint32_t inst)
{
struct v10_compute_mqd *m;
uint32_t *mqd_hqd;
@@ -273,9 +275,9 @@ static int hqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
static int hiq_mqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t doorbell_off)
+ uint32_t doorbell_off, uint32_t inst)
{
- struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
+ struct amdgpu_ring *kiq_ring = &adev->gfx.kiq[0].ring;
struct v10_compute_mqd *m;
uint32_t mec, pipe;
int r;
@@ -290,7 +292,7 @@ static int hiq_mqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
pr_debug("kfd: set HIQ, mec:%d, pipe:%d, queue:%d.\n",
mec, pipe, queue_id);
- spin_lock(&adev->gfx.kiq.ring_lock);
+ spin_lock(&adev->gfx.kiq[0].ring_lock);
r = amdgpu_ring_alloc(kiq_ring, 7);
if (r) {
pr_err("Failed to alloc KIQ (%d).\n", r);
@@ -317,7 +319,7 @@ static int hiq_mqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
amdgpu_ring_commit(kiq_ring);
out_unlock:
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&adev->gfx.kiq[0].ring_lock);
release_queue(adev);
return r;
@@ -325,7 +327,7 @@ out_unlock:
static int hqd_dump_v10_3(struct amdgpu_device *adev,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t (**dump)[2], uint32_t *n_regs)
+ uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst)
{
uint32_t i = 0, reg;
#define HQD_N_REGS 56
@@ -456,7 +458,7 @@ static int hqd_sdma_dump_v10_3(struct amdgpu_device *adev,
static bool hqd_is_occupied_v10_3(struct amdgpu_device *adev,
uint64_t queue_address, uint32_t pipe_id,
- uint32_t queue_id)
+ uint32_t queue_id, uint32_t inst)
{
uint32_t act;
bool retval = false;
@@ -498,7 +500,7 @@ static bool hqd_sdma_is_occupied_v10_3(struct amdgpu_device *adev,
static int hqd_destroy_v10_3(struct amdgpu_device *adev, void *mqd,
enum kfd_preempt_type reset_type,
unsigned int utimeout, uint32_t pipe_id,
- uint32_t queue_id)
+ uint32_t queue_id, uint32_t inst)
{
enum hqd_dequeue_request_type type;
unsigned long end_jiffies;
@@ -586,7 +588,7 @@ static int hqd_sdma_destroy_v10_3(struct amdgpu_device *adev, void *mqd,
static int wave_control_execute_v10_3(struct amdgpu_device *adev,
uint32_t gfx_index_val,
- uint32_t sq_cmd)
+ uint32_t sq_cmd, uint32_t inst)
{
uint32_t data = 0;
@@ -628,7 +630,8 @@ static void set_vm_context_page_table_base_v10_3(struct amdgpu_device *adev,
}
static void program_trap_handler_settings_v10_3(struct amdgpu_device *adev,
- uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
+ uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr,
+ uint32_t inst)
{
lock_srbm(adev, 0, 0, 0, vmid);
@@ -652,142 +655,6 @@ static void program_trap_handler_settings_v10_3(struct amdgpu_device *adev,
unlock_srbm(adev);
}
-#if 0
-uint32_t enable_debug_trap_v10_3(struct amdgpu_device *adev,
- uint32_t trap_debug_wave_launch_mode,
- uint32_t vmid)
-{
- uint32_t data = 0;
- uint32_t orig_wave_cntl_value;
- uint32_t orig_stall_vmid;
-
- mutex_lock(&adev->grbm_idx_mutex);
-
- orig_wave_cntl_value = RREG32(SOC15_REG_OFFSET(GC,
- 0,
- mmSPI_GDBG_WAVE_CNTL));
- orig_stall_vmid = REG_GET_FIELD(orig_wave_cntl_value,
- SPI_GDBG_WAVE_CNTL,
- STALL_VMID);
-
- data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_RA, 1);
- WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
-
- data = 0;
- WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), data);
-
- WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), orig_stall_vmid);
-
- mutex_unlock(&adev->grbm_idx_mutex);
-
- return 0;
-}
-
-uint32_t disable_debug_trap_v10_3(struct amdgpu_device *adev)
-{
- mutex_lock(&adev->grbm_idx_mutex);
-
- WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
-
- mutex_unlock(&adev->grbm_idx_mutex);
-
- return 0;
-}
-
-uint32_t set_wave_launch_trap_override_v10_3(struct amdgpu_device *adev,
- uint32_t trap_override,
- uint32_t trap_mask)
-{
- uint32_t data = 0;
-
- mutex_lock(&adev->grbm_idx_mutex);
-
- data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
- data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_RA, 1);
- WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
-
- data = 0;
- data = REG_SET_FIELD(data, SPI_GDBG_TRAP_MASK,
- EXCP_EN, trap_mask);
- data = REG_SET_FIELD(data, SPI_GDBG_TRAP_MASK,
- REPLACE, trap_override);
- WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), data);
-
- data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
- data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_RA, 0);
- WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
-
- mutex_unlock(&adev->grbm_idx_mutex);
-
- return 0;
-}
-
-uint32_t set_wave_launch_mode_v10_3(struct amdgpu_device *adev,
- uint8_t wave_launch_mode,
- uint32_t vmid)
-{
- uint32_t data = 0;
- bool is_stall_mode;
- bool is_mode_set;
-
- is_stall_mode = (wave_launch_mode == 4);
- is_mode_set = (wave_launch_mode != 0 && wave_launch_mode != 4);
-
- mutex_lock(&adev->grbm_idx_mutex);
-
- data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL2,
- VMID_MASK, is_mode_set ? 1 << vmid : 0);
- data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL2,
- MODE, is_mode_set ? wave_launch_mode : 0);
- WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL2), data);
-
- data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
- data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL,
- STALL_VMID, is_stall_mode ? 1 << vmid : 0);
- data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL,
- STALL_RA, is_stall_mode ? 1 : 0);
- WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
-
- mutex_unlock(&adev->grbm_idx_mutex);
-
- return 0;
-}
-
-/* kgd_get_iq_wait_times: Returns the mmCP_IQ_WAIT_TIME1/2 values
- * The values read are:
- * ib_offload_wait_time -- Wait Count for Indirect Buffer Offloads.
- * atomic_offload_wait_time -- Wait Count for L2 and GDS Atomics Offloads.
- * wrm_offload_wait_time -- Wait Count for WAIT_REG_MEM Offloads.
- * gws_wait_time -- Wait Count for Global Wave Syncs.
- * que_sleep_wait_time -- Wait Count for Dequeue Retry.
- * sch_wave_wait_time -- Wait Count for Scheduling Wave Message.
- * sem_rearm_wait_time -- Wait Count for Semaphore re-arm.
- * deq_retry_wait_time -- Wait Count for Global Wave Syncs.
- */
-void get_iq_wait_times_v10_3(struct amdgpu_device *adev,
- uint32_t *wait_times)
-
-{
- *wait_times = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2));
-}
-
-void build_grace_period_packet_info_v10_3(struct amdgpu_device *adev,
- uint32_t wait_times,
- uint32_t grace_period,
- uint32_t *reg_offset,
- uint32_t *reg_data)
-{
- *reg_data = wait_times;
-
- *reg_data = REG_SET_FIELD(*reg_data,
- CP_IQ_WAIT_TIME2,
- SCH_WAVE,
- grace_period);
-
- *reg_offset = mmCP_IQ_WAIT_TIME2;
-}
-#endif
-
const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = {
.program_sh_mem_settings = program_sh_mem_settings_v10_3,
.set_pasid_vmid_mapping = set_pasid_vmid_mapping_v10_3,
@@ -805,12 +672,13 @@ const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = {
.get_atc_vmid_pasid_mapping_info = get_atc_vmid_pasid_mapping_info_v10_3,
.set_vm_context_page_table_base = set_vm_context_page_table_base_v10_3,
.program_trap_handler_settings = program_trap_handler_settings_v10_3,
-#if 0
- .enable_debug_trap = enable_debug_trap_v10_3,
- .disable_debug_trap = disable_debug_trap_v10_3,
- .set_wave_launch_trap_override = set_wave_launch_trap_override_v10_3,
- .set_wave_launch_mode = set_wave_launch_mode_v10_3,
- .get_iq_wait_times = get_iq_wait_times_v10_3,
- .build_grace_period_packet_info = build_grace_period_packet_info_v10_3,
-#endif
+ .get_iq_wait_times = kgd_gfx_v10_get_iq_wait_times,
+ .build_grace_period_packet_info = kgd_gfx_v10_build_grace_period_packet_info,
+ .enable_debug_trap = kgd_gfx_v10_enable_debug_trap,
+ .disable_debug_trap = kgd_gfx_v10_disable_debug_trap,
+ .validate_trap_override_request = kgd_gfx_v10_validate_trap_override_request,
+ .set_wave_launch_trap_override = kgd_gfx_v10_set_wave_launch_trap_override,
+ .set_wave_launch_mode = kgd_gfx_v10_set_wave_launch_mode,
+ .set_address_watch = kgd_gfx_v10_set_address_watch,
+ .clear_address_watch = kgd_gfx_v10_clear_address_watch
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c
index 7e80caa05060..91c3574ebed3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c
@@ -30,6 +30,7 @@
#include "soc15d.h"
#include "v11_structs.h"
#include "soc21.h"
+#include <uapi/linux/kfd_ioctl.h>
enum hqd_dequeue_request_type {
NO_ACTION = 0,
@@ -78,7 +79,7 @@ static void program_sh_mem_settings_v11(struct amdgpu_device *adev, uint32_t vmi
uint32_t sh_mem_config,
uint32_t sh_mem_ape1_base,
uint32_t sh_mem_ape1_limit,
- uint32_t sh_mem_bases)
+ uint32_t sh_mem_bases, uint32_t inst)
{
lock_srbm(adev, 0, 0, 0, vmid);
@@ -89,7 +90,7 @@ static void program_sh_mem_settings_v11(struct amdgpu_device *adev, uint32_t vmi
}
static int set_pasid_vmid_mapping_v11(struct amdgpu_device *adev, unsigned int pasid,
- unsigned int vmid)
+ unsigned int vmid, uint32_t inst)
{
uint32_t value = pasid << IH_VMID_0_LUT__PASID__SHIFT;
@@ -101,7 +102,8 @@ static int set_pasid_vmid_mapping_v11(struct amdgpu_device *adev, unsigned int p
return 0;
}
-static int init_interrupts_v11(struct amdgpu_device *adev, uint32_t pipe_id)
+static int init_interrupts_v11(struct amdgpu_device *adev, uint32_t pipe_id,
+ uint32_t inst)
{
uint32_t mec;
uint32_t pipe;
@@ -162,7 +164,7 @@ static inline struct v11_sdma_mqd *get_sdma_mqd(void *mqd)
static int hqd_load_v11(struct amdgpu_device *adev, void *mqd, uint32_t pipe_id,
uint32_t queue_id, uint32_t __user *wptr,
uint32_t wptr_shift, uint32_t wptr_mask,
- struct mm_struct *mm)
+ struct mm_struct *mm, uint32_t inst)
{
struct v11_compute_mqd *m;
uint32_t *mqd_hqd;
@@ -258,9 +260,9 @@ static int hqd_load_v11(struct amdgpu_device *adev, void *mqd, uint32_t pipe_id,
static int hiq_mqd_load_v11(struct amdgpu_device *adev, void *mqd,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t doorbell_off)
+ uint32_t doorbell_off, uint32_t inst)
{
- struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
+ struct amdgpu_ring *kiq_ring = &adev->gfx.kiq[0].ring;
struct v11_compute_mqd *m;
uint32_t mec, pipe;
int r;
@@ -275,7 +277,7 @@ static int hiq_mqd_load_v11(struct amdgpu_device *adev, void *mqd,
pr_debug("kfd: set HIQ, mec:%d, pipe:%d, queue:%d.\n",
mec, pipe, queue_id);
- spin_lock(&adev->gfx.kiq.ring_lock);
+ spin_lock(&adev->gfx.kiq[0].ring_lock);
r = amdgpu_ring_alloc(kiq_ring, 7);
if (r) {
pr_err("Failed to alloc KIQ (%d).\n", r);
@@ -302,7 +304,7 @@ static int hiq_mqd_load_v11(struct amdgpu_device *adev, void *mqd,
amdgpu_ring_commit(kiq_ring);
out_unlock:
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&adev->gfx.kiq[0].ring_lock);
release_queue(adev);
return r;
@@ -310,7 +312,7 @@ out_unlock:
static int hqd_dump_v11(struct amdgpu_device *adev,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t (**dump)[2], uint32_t *n_regs)
+ uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst)
{
uint32_t i = 0, reg;
#define HQD_N_REGS 56
@@ -445,7 +447,7 @@ static int hqd_sdma_dump_v11(struct amdgpu_device *adev,
}
static bool hqd_is_occupied_v11(struct amdgpu_device *adev, uint64_t queue_address,
- uint32_t pipe_id, uint32_t queue_id)
+ uint32_t pipe_id, uint32_t queue_id, uint32_t inst)
{
uint32_t act;
bool retval = false;
@@ -486,7 +488,7 @@ static bool hqd_sdma_is_occupied_v11(struct amdgpu_device *adev, void *mqd)
static int hqd_destroy_v11(struct amdgpu_device *adev, void *mqd,
enum kfd_preempt_type reset_type,
unsigned int utimeout, uint32_t pipe_id,
- uint32_t queue_id)
+ uint32_t queue_id, uint32_t inst)
{
enum hqd_dequeue_request_type type;
unsigned long end_jiffies;
@@ -571,7 +573,7 @@ static int hqd_sdma_destroy_v11(struct amdgpu_device *adev, void *mqd,
static int wave_control_execute_v11(struct amdgpu_device *adev,
uint32_t gfx_index_val,
- uint32_t sq_cmd)
+ uint32_t sq_cmd, uint32_t inst)
{
uint32_t data = 0;
@@ -606,6 +608,183 @@ static void set_vm_context_page_table_base_v11(struct amdgpu_device *adev,
adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base);
}
+/*
+ * Returns TRAP_EN, EXCP_EN and EXCP_REPLACE.
+ *
+ * restore_dbg_registers is ignored here but is a general interface requirement
+ * for devices that support GFXOFF and where the RLC save/restore list
+ * does not support hw registers for debugging i.e. the driver has to manually
+ * initialize the debug mode registers after it has disabled GFX off during the
+ * debug session.
+ */
+static uint32_t kgd_gfx_v11_enable_debug_trap(struct amdgpu_device *adev,
+ bool restore_dbg_registers,
+ uint32_t vmid)
+{
+ uint32_t data = 0;
+
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, 1);
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, 0);
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE, 0);
+
+ return data;
+}
+
+/* Returns TRAP_EN, EXCP_EN and EXCP_REPLACE. */
+static uint32_t kgd_gfx_v11_disable_debug_trap(struct amdgpu_device *adev,
+ bool keep_trap_enabled,
+ uint32_t vmid)
+{
+ uint32_t data = 0;
+
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, keep_trap_enabled);
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, 0);
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE, 0);
+
+ return data;
+}
+
+static int kgd_gfx_v11_validate_trap_override_request(struct amdgpu_device *adev,
+ uint32_t trap_override,
+ uint32_t *trap_mask_supported)
+{
+ *trap_mask_supported &= KFD_DBG_TRAP_MASK_FP_INVALID |
+ KFD_DBG_TRAP_MASK_FP_INPUT_DENORMAL |
+ KFD_DBG_TRAP_MASK_FP_DIVIDE_BY_ZERO |
+ KFD_DBG_TRAP_MASK_FP_OVERFLOW |
+ KFD_DBG_TRAP_MASK_FP_UNDERFLOW |
+ KFD_DBG_TRAP_MASK_FP_INEXACT |
+ KFD_DBG_TRAP_MASK_INT_DIVIDE_BY_ZERO |
+ KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH |
+ KFD_DBG_TRAP_MASK_DBG_MEMORY_VIOLATION;
+
+ if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(11, 0, 4))
+ *trap_mask_supported |= KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_START |
+ KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_END;
+
+ if (trap_override != KFD_DBG_TRAP_OVERRIDE_OR &&
+ trap_override != KFD_DBG_TRAP_OVERRIDE_REPLACE)
+ return -EPERM;
+
+ return 0;
+}
+
+static uint32_t trap_mask_map_sw_to_hw(uint32_t mask)
+{
+ uint32_t trap_on_start = (mask & KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_START) ? 1 : 0;
+ uint32_t trap_on_end = (mask & KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_END) ? 1 : 0;
+ uint32_t excp_en = mask & (KFD_DBG_TRAP_MASK_FP_INVALID |
+ KFD_DBG_TRAP_MASK_FP_INPUT_DENORMAL |
+ KFD_DBG_TRAP_MASK_FP_DIVIDE_BY_ZERO |
+ KFD_DBG_TRAP_MASK_FP_OVERFLOW |
+ KFD_DBG_TRAP_MASK_FP_UNDERFLOW |
+ KFD_DBG_TRAP_MASK_FP_INEXACT |
+ KFD_DBG_TRAP_MASK_INT_DIVIDE_BY_ZERO |
+ KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH |
+ KFD_DBG_TRAP_MASK_DBG_MEMORY_VIOLATION);
+ uint32_t ret;
+
+ ret = REG_SET_FIELD(0, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, excp_en);
+ ret = REG_SET_FIELD(ret, SPI_GDBG_PER_VMID_CNTL, TRAP_ON_START, trap_on_start);
+ ret = REG_SET_FIELD(ret, SPI_GDBG_PER_VMID_CNTL, TRAP_ON_END, trap_on_end);
+
+ return ret;
+}
+
+static uint32_t trap_mask_map_hw_to_sw(uint32_t mask)
+{
+ uint32_t ret = REG_GET_FIELD(mask, SPI_GDBG_PER_VMID_CNTL, EXCP_EN);
+
+ if (REG_GET_FIELD(mask, SPI_GDBG_PER_VMID_CNTL, TRAP_ON_START))
+ ret |= KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_START;
+
+ if (REG_GET_FIELD(mask, SPI_GDBG_PER_VMID_CNTL, TRAP_ON_END))
+ ret |= KFD_DBG_TRAP_MASK_TRAP_ON_WAVE_END;
+
+ return ret;
+}
+
+/* Returns TRAP_EN, EXCP_EN and EXCP_REPLACE. */
+static uint32_t kgd_gfx_v11_set_wave_launch_trap_override(struct amdgpu_device *adev,
+ uint32_t vmid,
+ uint32_t trap_override,
+ uint32_t trap_mask_bits,
+ uint32_t trap_mask_request,
+ uint32_t *trap_mask_prev,
+ uint32_t kfd_dbg_trap_cntl_prev)
+{
+ uint32_t data = 0;
+
+ *trap_mask_prev = trap_mask_map_hw_to_sw(kfd_dbg_trap_cntl_prev);
+
+ data = (trap_mask_bits & trap_mask_request) | (*trap_mask_prev & ~trap_mask_request);
+ data = trap_mask_map_sw_to_hw(data);
+
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, 1);
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE, trap_override);
+
+ return data;
+}
+
+static uint32_t kgd_gfx_v11_set_wave_launch_mode(struct amdgpu_device *adev,
+ uint8_t wave_launch_mode,
+ uint32_t vmid)
+{
+ uint32_t data = 0;
+
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, LAUNCH_MODE, wave_launch_mode);
+
+ return data;
+}
+
+#define TCP_WATCH_STRIDE (regTCP_WATCH1_ADDR_H - regTCP_WATCH0_ADDR_H)
+static uint32_t kgd_gfx_v11_set_address_watch(struct amdgpu_device *adev,
+ uint64_t watch_address,
+ uint32_t watch_address_mask,
+ uint32_t watch_id,
+ uint32_t watch_mode,
+ uint32_t debug_vmid)
+{
+ uint32_t watch_address_high;
+ uint32_t watch_address_low;
+ uint32_t watch_address_cntl;
+
+ watch_address_cntl = 0;
+ watch_address_low = lower_32_bits(watch_address);
+ watch_address_high = upper_32_bits(watch_address) & 0xffff;
+
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ MODE,
+ watch_mode);
+
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ MASK,
+ watch_address_mask >> 7);
+
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ VALID,
+ 1);
+
+ WREG32_RLC((SOC15_REG_OFFSET(GC, 0, regTCP_WATCH0_ADDR_H) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_high);
+
+ WREG32_RLC((SOC15_REG_OFFSET(GC, 0, regTCP_WATCH0_ADDR_L) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_low);
+
+ return watch_address_cntl;
+}
+
+static uint32_t kgd_gfx_v11_clear_address_watch(struct amdgpu_device *adev,
+ uint32_t watch_id)
+{
+ return 0;
+}
+
const struct kfd2kgd_calls gfx_v11_kfd2kgd = {
.program_sh_mem_settings = program_sh_mem_settings_v11,
.set_pasid_vmid_mapping = set_pasid_vmid_mapping_v11,
@@ -622,4 +801,11 @@ const struct kfd2kgd_calls gfx_v11_kfd2kgd = {
.wave_control_execute = wave_control_execute_v11,
.get_atc_vmid_pasid_mapping_info = NULL,
.set_vm_context_page_table_base = set_vm_context_page_table_base_v11,
+ .enable_debug_trap = kgd_gfx_v11_enable_debug_trap,
+ .disable_debug_trap = kgd_gfx_v11_disable_debug_trap,
+ .validate_trap_override_request = kgd_gfx_v11_validate_trap_override_request,
+ .set_wave_launch_trap_override = kgd_gfx_v11_set_wave_launch_trap_override,
+ .set_wave_launch_mode = kgd_gfx_v11_set_wave_launch_mode,
+ .set_address_watch = kgd_gfx_v11_set_address_watch,
+ .clear_address_watch = kgd_gfx_v11_clear_address_watch
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
index e83cb1c09610..6bf448ab3dff 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
@@ -78,7 +78,7 @@ static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
uint32_t sh_mem_config,
uint32_t sh_mem_ape1_base,
uint32_t sh_mem_ape1_limit,
- uint32_t sh_mem_bases)
+ uint32_t sh_mem_bases, uint32_t inst)
{
lock_srbm(adev, 0, 0, 0, vmid);
@@ -91,7 +91,7 @@ static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
}
static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
- unsigned int vmid)
+ unsigned int vmid, uint32_t inst)
{
/*
* We have to assume that there is no outstanding mapping.
@@ -114,7 +114,8 @@ static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
return 0;
}
-static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
+static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id,
+ uint32_t inst)
{
uint32_t mec;
uint32_t pipe;
@@ -158,7 +159,7 @@ static inline struct cik_sdma_rlc_registers *get_sdma_mqd(void *mqd)
static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
uint32_t pipe_id, uint32_t queue_id,
uint32_t __user *wptr, uint32_t wptr_shift,
- uint32_t wptr_mask, struct mm_struct *mm)
+ uint32_t wptr_mask, struct mm_struct *mm, uint32_t inst)
{
struct cik_mqd *m;
uint32_t *mqd_hqd;
@@ -202,7 +203,7 @@ static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
static int kgd_hqd_dump(struct amdgpu_device *adev,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t (**dump)[2], uint32_t *n_regs)
+ uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst)
{
uint32_t i = 0, reg;
#define HQD_N_REGS (35+4)
@@ -318,7 +319,7 @@ static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
static bool kgd_hqd_is_occupied(struct amdgpu_device *adev,
uint64_t queue_address, uint32_t pipe_id,
- uint32_t queue_id)
+ uint32_t queue_id, uint32_t inst)
{
uint32_t act;
bool retval = false;
@@ -358,7 +359,7 @@ static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
static int kgd_hqd_destroy(struct amdgpu_device *adev, void *mqd,
enum kfd_preempt_type reset_type,
unsigned int utimeout, uint32_t pipe_id,
- uint32_t queue_id)
+ uint32_t queue_id, uint32_t inst)
{
uint32_t temp;
enum hqd_dequeue_request_type type;
@@ -494,7 +495,7 @@ static int kgd_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
static int kgd_wave_control_execute(struct amdgpu_device *adev,
uint32_t gfx_index_val,
- uint32_t sq_cmd)
+ uint32_t sq_cmd, uint32_t inst)
{
uint32_t data;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
index 870f352837fc..cd06e4a6d1da 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
@@ -72,7 +72,7 @@ static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
uint32_t sh_mem_config,
uint32_t sh_mem_ape1_base,
uint32_t sh_mem_ape1_limit,
- uint32_t sh_mem_bases)
+ uint32_t sh_mem_bases, uint32_t inst)
{
lock_srbm(adev, 0, 0, 0, vmid);
@@ -85,7 +85,7 @@ static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmi
}
static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
- unsigned int vmid)
+ unsigned int vmid, uint32_t inst)
{
/*
* We have to assume that there is no outstanding mapping.
@@ -109,7 +109,8 @@ static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
return 0;
}
-static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
+static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id,
+ uint32_t inst)
{
uint32_t mec;
uint32_t pipe;
@@ -153,7 +154,7 @@ static inline struct vi_sdma_mqd *get_sdma_mqd(void *mqd)
static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
uint32_t pipe_id, uint32_t queue_id,
uint32_t __user *wptr, uint32_t wptr_shift,
- uint32_t wptr_mask, struct mm_struct *mm)
+ uint32_t wptr_mask, struct mm_struct *mm, uint32_t inst)
{
struct vi_mqd *m;
uint32_t *mqd_hqd;
@@ -226,7 +227,7 @@ static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
static int kgd_hqd_dump(struct amdgpu_device *adev,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t (**dump)[2], uint32_t *n_regs)
+ uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst)
{
uint32_t i = 0, reg;
#define HQD_N_REGS (54+4)
@@ -350,7 +351,7 @@ static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
static bool kgd_hqd_is_occupied(struct amdgpu_device *adev,
uint64_t queue_address, uint32_t pipe_id,
- uint32_t queue_id)
+ uint32_t queue_id, uint32_t inst)
{
uint32_t act;
bool retval = false;
@@ -390,7 +391,7 @@ static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
static int kgd_hqd_destroy(struct amdgpu_device *adev, void *mqd,
enum kfd_preempt_type reset_type,
unsigned int utimeout, uint32_t pipe_id,
- uint32_t queue_id)
+ uint32_t queue_id, uint32_t inst)
{
uint32_t temp;
enum hqd_dequeue_request_type type;
@@ -540,7 +541,7 @@ static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
static int kgd_wave_control_execute(struct amdgpu_device *adev,
uint32_t gfx_index_val,
- uint32_t sq_cmd)
+ uint32_t sq_cmd, uint32_t inst)
{
uint32_t data = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
index e92b93557c13..51d93fb13ea3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
@@ -38,6 +38,7 @@
#include "soc15d.h"
#include "gfx_v9_0.h"
#include "amdgpu_amdkfd_gfx_v9.h"
+#include <uapi/linux/kfd_ioctl.h>
enum hqd_dequeue_request_type {
NO_ACTION = 0,
@@ -46,29 +47,29 @@ enum hqd_dequeue_request_type {
SAVE_WAVES
};
-static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
- uint32_t queue, uint32_t vmid)
+static void kgd_gfx_v9_lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
+ uint32_t queue, uint32_t vmid, uint32_t inst)
{
mutex_lock(&adev->srbm_mutex);
- soc15_grbm_select(adev, mec, pipe, queue, vmid);
+ soc15_grbm_select(adev, mec, pipe, queue, vmid, GET_INST(GC, inst));
}
-static void unlock_srbm(struct amdgpu_device *adev)
+static void kgd_gfx_v9_unlock_srbm(struct amdgpu_device *adev, uint32_t inst)
{
- soc15_grbm_select(adev, 0, 0, 0, 0);
+ soc15_grbm_select(adev, 0, 0, 0, 0, GET_INST(GC, inst));
mutex_unlock(&adev->srbm_mutex);
}
-static void acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
- uint32_t queue_id)
+void kgd_gfx_v9_acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
+ uint32_t queue_id, uint32_t inst)
{
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
- lock_srbm(adev, mec, pipe, queue_id, 0);
+ kgd_gfx_v9_lock_srbm(adev, mec, pipe, queue_id, 0, inst);
}
-static uint64_t get_queue_mask(struct amdgpu_device *adev,
+uint64_t kgd_gfx_v9_get_queue_mask(struct amdgpu_device *adev,
uint32_t pipe_id, uint32_t queue_id)
{
unsigned int bit = pipe_id * adev->gfx.mec.num_queue_per_pipe +
@@ -77,28 +78,28 @@ static uint64_t get_queue_mask(struct amdgpu_device *adev,
return 1ull << bit;
}
-static void release_queue(struct amdgpu_device *adev)
+void kgd_gfx_v9_release_queue(struct amdgpu_device *adev, uint32_t inst)
{
- unlock_srbm(adev);
+ kgd_gfx_v9_unlock_srbm(adev, inst);
}
void kgd_gfx_v9_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
uint32_t sh_mem_config,
uint32_t sh_mem_ape1_base,
uint32_t sh_mem_ape1_limit,
- uint32_t sh_mem_bases)
+ uint32_t sh_mem_bases, uint32_t inst)
{
- lock_srbm(adev, 0, 0, 0, vmid);
+ kgd_gfx_v9_lock_srbm(adev, 0, 0, 0, vmid, inst);
- WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_CONFIG), sh_mem_config);
- WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_BASES), sh_mem_bases);
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmSH_MEM_CONFIG), sh_mem_config);
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmSH_MEM_BASES), sh_mem_bases);
/* APE1 no longer exists on GFX9 */
- unlock_srbm(adev);
+ kgd_gfx_v9_unlock_srbm(adev, inst);
}
int kgd_gfx_v9_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
- unsigned int vmid)
+ unsigned int vmid, uint32_t inst)
{
/*
* We have to assume that there is no outstanding mapping.
@@ -156,7 +157,8 @@ int kgd_gfx_v9_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
* but still works
*/
-int kgd_gfx_v9_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
+int kgd_gfx_v9_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id,
+ uint32_t inst)
{
uint32_t mec;
uint32_t pipe;
@@ -164,13 +166,13 @@ int kgd_gfx_v9_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
- lock_srbm(adev, mec, pipe, 0, 0);
+ kgd_gfx_v9_lock_srbm(adev, mec, pipe, 0, 0, inst);
- WREG32_SOC15(GC, 0, mmCPC_INT_CNTL,
+ WREG32_SOC15(GC, GET_INST(GC, inst), mmCPC_INT_CNTL,
CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
- unlock_srbm(adev);
+ kgd_gfx_v9_unlock_srbm(adev, inst);
return 0;
}
@@ -220,7 +222,8 @@ static inline struct v9_sdma_mqd *get_sdma_mqd(void *mqd)
int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd,
uint32_t pipe_id, uint32_t queue_id,
uint32_t __user *wptr, uint32_t wptr_shift,
- uint32_t wptr_mask, struct mm_struct *mm)
+ uint32_t wptr_mask, struct mm_struct *mm,
+ uint32_t inst)
{
struct v9_mqd *m;
uint32_t *mqd_hqd;
@@ -228,21 +231,22 @@ int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd,
m = get_mqd(mqd);
- acquire_queue(adev, pipe_id, queue_id);
+ kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
/* HQD registers extend from CP_MQD_BASE_ADDR to CP_HQD_EOP_WPTR_MEM. */
mqd_hqd = &m->cp_mqd_base_addr_lo;
- hqd_base = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
+ hqd_base = SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_MQD_BASE_ADDR);
for (reg = hqd_base;
- reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
+ reg <= SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_HI); reg++)
WREG32_RLC(reg, mqd_hqd[reg - hqd_base]);
/* Activate doorbell logic before triggering WPTR poll. */
data = REG_SET_FIELD(m->cp_hqd_pq_doorbell_control,
CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1);
- WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL), data);
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_DOORBELL_CONTROL),
+ data);
if (wptr) {
/* Don't read wptr with get_user because the user
@@ -271,43 +275,43 @@ int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd,
guessed_wptr += m->cp_hqd_pq_wptr_lo & ~(queue_size - 1);
guessed_wptr += (uint64_t)m->cp_hqd_pq_wptr_hi << 32;
- WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_LO),
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_LO),
lower_32_bits(guessed_wptr));
- WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI),
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_HI),
upper_32_bits(guessed_wptr));
- WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR),
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_POLL_ADDR),
lower_32_bits((uintptr_t)wptr));
- WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI),
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_POLL_ADDR_HI),
upper_32_bits((uintptr_t)wptr));
- WREG32_SOC15(GC, 0, mmCP_PQ_WPTR_POLL_CNTL1,
- (uint32_t)get_queue_mask(adev, pipe_id, queue_id));
+ WREG32_SOC15(GC, GET_INST(GC, inst), mmCP_PQ_WPTR_POLL_CNTL1,
+ (uint32_t)kgd_gfx_v9_get_queue_mask(adev, pipe_id, queue_id));
}
/* Start the EOP fetcher */
- WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_RPTR),
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_EOP_RPTR),
REG_SET_FIELD(m->cp_hqd_eop_rptr,
CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
- WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE), data);
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_ACTIVE), data);
- release_queue(adev);
+ kgd_gfx_v9_release_queue(adev, inst);
return 0;
}
int kgd_gfx_v9_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t doorbell_off)
+ uint32_t doorbell_off, uint32_t inst)
{
- struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
+ struct amdgpu_ring *kiq_ring = &adev->gfx.kiq[inst].ring;
struct v9_mqd *m;
uint32_t mec, pipe;
int r;
m = get_mqd(mqd);
- acquire_queue(adev, pipe_id, queue_id);
+ kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
@@ -315,7 +319,7 @@ int kgd_gfx_v9_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
pr_debug("kfd: set HIQ, mec:%d, pipe:%d, queue:%d.\n",
mec, pipe, queue_id);
- spin_lock(&adev->gfx.kiq.ring_lock);
+ spin_lock(&adev->gfx.kiq[inst].ring_lock);
r = amdgpu_ring_alloc(kiq_ring, 7);
if (r) {
pr_err("Failed to alloc KIQ (%d).\n", r);
@@ -342,15 +346,15 @@ int kgd_gfx_v9_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
amdgpu_ring_commit(kiq_ring);
out_unlock:
- spin_unlock(&adev->gfx.kiq.ring_lock);
- release_queue(adev);
+ spin_unlock(&adev->gfx.kiq[inst].ring_lock);
+ kgd_gfx_v9_release_queue(adev, inst);
return r;
}
int kgd_gfx_v9_hqd_dump(struct amdgpu_device *adev,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t (**dump)[2], uint32_t *n_regs)
+ uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst)
{
uint32_t i = 0, reg;
#define HQD_N_REGS 56
@@ -365,13 +369,13 @@ int kgd_gfx_v9_hqd_dump(struct amdgpu_device *adev,
if (*dump == NULL)
return -ENOMEM;
- acquire_queue(adev, pipe_id, queue_id);
+ kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
- for (reg = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
- reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
+ for (reg = SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_MQD_BASE_ADDR);
+ reg <= SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_PQ_WPTR_HI); reg++)
DUMP_REG(reg);
- release_queue(adev);
+ kgd_gfx_v9_release_queue(adev, inst);
WARN_ON_ONCE(i != HQD_N_REGS);
*n_regs = i;
@@ -481,23 +485,23 @@ static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
bool kgd_gfx_v9_hqd_is_occupied(struct amdgpu_device *adev,
uint64_t queue_address, uint32_t pipe_id,
- uint32_t queue_id)
+ uint32_t queue_id, uint32_t inst)
{
uint32_t act;
bool retval = false;
uint32_t low, high;
- acquire_queue(adev, pipe_id, queue_id);
- act = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
+ kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
+ act = RREG32_SOC15(GC, GET_INST(GC, inst), mmCP_HQD_ACTIVE);
if (act) {
low = lower_32_bits(queue_address >> 8);
high = upper_32_bits(queue_address >> 8);
- if (low == RREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE) &&
- high == RREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI))
+ if (low == RREG32_SOC15(GC, GET_INST(GC, inst), mmCP_HQD_PQ_BASE) &&
+ high == RREG32_SOC15(GC, GET_INST(GC, inst), mmCP_HQD_PQ_BASE_HI))
retval = true;
}
- release_queue(adev);
+ kgd_gfx_v9_release_queue(adev, inst);
return retval;
}
@@ -522,7 +526,7 @@ static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
int kgd_gfx_v9_hqd_destroy(struct amdgpu_device *adev, void *mqd,
enum kfd_preempt_type reset_type,
unsigned int utimeout, uint32_t pipe_id,
- uint32_t queue_id)
+ uint32_t queue_id, uint32_t inst)
{
enum hqd_dequeue_request_type type;
unsigned long end_jiffies;
@@ -532,10 +536,10 @@ int kgd_gfx_v9_hqd_destroy(struct amdgpu_device *adev, void *mqd,
if (amdgpu_in_reset(adev))
return -EIO;
- acquire_queue(adev, pipe_id, queue_id);
+ kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
if (m->cp_hqd_vmid == 0)
- WREG32_FIELD15_RLC(GC, 0, RLC_CP_SCHEDULERS, scheduler1, 0);
+ WREG32_FIELD15_RLC(GC, GET_INST(GC, inst), RLC_CP_SCHEDULERS, scheduler1, 0);
switch (reset_type) {
case KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN:
@@ -552,22 +556,22 @@ int kgd_gfx_v9_hqd_destroy(struct amdgpu_device *adev, void *mqd,
break;
}
- WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_DEQUEUE_REQUEST), type);
+ WREG32_RLC(SOC15_REG_OFFSET(GC, GET_INST(GC, inst), mmCP_HQD_DEQUEUE_REQUEST), type);
end_jiffies = (utimeout * HZ / 1000) + jiffies;
while (true) {
- temp = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
+ temp = RREG32_SOC15(GC, GET_INST(GC, inst), mmCP_HQD_ACTIVE);
if (!(temp & CP_HQD_ACTIVE__ACTIVE_MASK))
break;
if (time_after(jiffies, end_jiffies)) {
pr_err("cp queue preemption time out.\n");
- release_queue(adev);
+ kgd_gfx_v9_release_queue(adev, inst);
return -ETIME;
}
usleep_range(500, 1000);
}
- release_queue(adev);
+ kgd_gfx_v9_release_queue(adev, inst);
return 0;
}
@@ -624,14 +628,14 @@ bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev,
uint32_t gfx_index_val,
- uint32_t sq_cmd)
+ uint32_t sq_cmd, uint32_t inst)
{
uint32_t data = 0;
mutex_lock(&adev->grbm_idx_mutex);
- WREG32_SOC15_RLC_SHADOW(GC, 0, mmGRBM_GFX_INDEX, gfx_index_val);
- WREG32_SOC15(GC, 0, mmSQ_CMD, sq_cmd);
+ WREG32_SOC15_RLC_SHADOW(GC, GET_INST(GC, inst), mmGRBM_GFX_INDEX, gfx_index_val);
+ WREG32_SOC15(GC, GET_INST(GC, inst), mmSQ_CMD, sq_cmd);
data = REG_SET_FIELD(data, GRBM_GFX_INDEX,
INSTANCE_BROADCAST_WRITES, 1);
@@ -640,12 +644,271 @@ int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev,
data = REG_SET_FIELD(data, GRBM_GFX_INDEX,
SE_BROADCAST_WRITES, 1);
- WREG32_SOC15_RLC_SHADOW(GC, 0, mmGRBM_GFX_INDEX, data);
+ WREG32_SOC15_RLC_SHADOW(GC, GET_INST(GC, inst), mmGRBM_GFX_INDEX, data);
mutex_unlock(&adev->grbm_idx_mutex);
return 0;
}
+/*
+ * GFX9 helper for wave launch stall requirements on debug trap setting.
+ *
+ * vmid:
+ * Target VMID to stall/unstall.
+ *
+ * stall:
+ * 0-unstall wave launch (enable), 1-stall wave launch (disable).
+ * After wavefront launch has been stalled, allocated waves must drain from
+ * SPI in order for debug trap settings to take effect on those waves.
+ * This is roughly a ~96 clock cycle wait on SPI where a read on
+ * SPI_GDBG_WAVE_CNTL translates to ~32 clock cycles.
+ * KGD_GFX_V9_WAVE_LAUNCH_SPI_DRAIN_LATENCY indicates the number of reads required.
+ *
+ * NOTE: We can afford to clear the entire STALL_VMID field on unstall
+ * because GFX9.4.1 cannot support multi-process debugging due to trap
+ * configuration and masking being limited to global scope. Always assume
+ * single process conditions.
+ */
+#define KGD_GFX_V9_WAVE_LAUNCH_SPI_DRAIN_LATENCY 3
+void kgd_gfx_v9_set_wave_launch_stall(struct amdgpu_device *adev,
+ uint32_t vmid,
+ bool stall)
+{
+ int i;
+ uint32_t data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
+
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1))
+ data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_VMID,
+ stall ? 1 << vmid : 0);
+ else
+ data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_RA,
+ stall ? 1 : 0);
+
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
+
+ if (!stall)
+ return;
+
+ for (i = 0; i < KGD_GFX_V9_WAVE_LAUNCH_SPI_DRAIN_LATENCY; i++)
+ RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
+}
+
+/*
+ * restore_dbg_registers is ignored here but is a general interface requirement
+ * for devices that support GFXOFF and where the RLC save/restore list
+ * does not support hw registers for debugging i.e. the driver has to manually
+ * initialize the debug mode registers after it has disabled GFX off during the
+ * debug session.
+ */
+uint32_t kgd_gfx_v9_enable_debug_trap(struct amdgpu_device *adev,
+ bool restore_dbg_registers,
+ uint32_t vmid)
+{
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ kgd_gfx_v9_set_wave_launch_stall(adev, vmid, true);
+
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
+
+ kgd_gfx_v9_set_wave_launch_stall(adev, vmid, false);
+
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return 0;
+}
+
+/*
+ * keep_trap_enabled is ignored here but is a general interface requirement
+ * for devices that support multi-process debugging where the performance
+ * overhead from trap temporary setup needs to be bypassed when the debug
+ * session has ended.
+ */
+uint32_t kgd_gfx_v9_disable_debug_trap(struct amdgpu_device *adev,
+ bool keep_trap_enabled,
+ uint32_t vmid)
+{
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ kgd_gfx_v9_set_wave_launch_stall(adev, vmid, true);
+
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
+
+ kgd_gfx_v9_set_wave_launch_stall(adev, vmid, false);
+
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return 0;
+}
+
+int kgd_gfx_v9_validate_trap_override_request(struct amdgpu_device *adev,
+ uint32_t trap_override,
+ uint32_t *trap_mask_supported)
+{
+ *trap_mask_supported &= KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH;
+
+ /* The SPI_GDBG_TRAP_MASK register is global and affects all
+ * processes. Only allow OR-ing the address-watch bit, since
+ * this only affects processes under the debugger. Other bits
+ * should stay 0 to avoid the debugger interfering with other
+ * processes.
+ */
+ if (trap_override != KFD_DBG_TRAP_OVERRIDE_OR)
+ return -EINVAL;
+
+ return 0;
+}
+
+uint32_t kgd_gfx_v9_set_wave_launch_trap_override(struct amdgpu_device *adev,
+ uint32_t vmid,
+ uint32_t trap_override,
+ uint32_t trap_mask_bits,
+ uint32_t trap_mask_request,
+ uint32_t *trap_mask_prev,
+ uint32_t kfd_dbg_cntl_prev)
+{
+ uint32_t data, wave_cntl_prev;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ wave_cntl_prev = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
+
+ kgd_gfx_v9_set_wave_launch_stall(adev, vmid, true);
+
+ data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK));
+ *trap_mask_prev = REG_GET_FIELD(data, SPI_GDBG_TRAP_MASK, EXCP_EN);
+
+ trap_mask_bits = (trap_mask_bits & trap_mask_request) |
+ (*trap_mask_prev & ~trap_mask_request);
+
+ data = REG_SET_FIELD(data, SPI_GDBG_TRAP_MASK, EXCP_EN, trap_mask_bits);
+ data = REG_SET_FIELD(data, SPI_GDBG_TRAP_MASK, REPLACE, trap_override);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), data);
+
+ /* We need to preserve wave launch mode stall settings. */
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), wave_cntl_prev);
+
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return 0;
+}
+
+uint32_t kgd_gfx_v9_set_wave_launch_mode(struct amdgpu_device *adev,
+ uint8_t wave_launch_mode,
+ uint32_t vmid)
+{
+ uint32_t data = 0;
+ bool is_mode_set = !!wave_launch_mode;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ kgd_gfx_v9_set_wave_launch_stall(adev, vmid, true);
+
+ data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL2,
+ VMID_MASK, is_mode_set ? 1 << vmid : 0);
+ data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL2,
+ MODE, is_mode_set ? wave_launch_mode : 0);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL2), data);
+
+ kgd_gfx_v9_set_wave_launch_stall(adev, vmid, false);
+
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ return 0;
+}
+
+#define TCP_WATCH_STRIDE (mmTCP_WATCH1_ADDR_H - mmTCP_WATCH0_ADDR_H)
+uint32_t kgd_gfx_v9_set_address_watch(struct amdgpu_device *adev,
+ uint64_t watch_address,
+ uint32_t watch_address_mask,
+ uint32_t watch_id,
+ uint32_t watch_mode,
+ uint32_t debug_vmid)
+{
+ uint32_t watch_address_high;
+ uint32_t watch_address_low;
+ uint32_t watch_address_cntl;
+
+ watch_address_cntl = 0;
+
+ watch_address_low = lower_32_bits(watch_address);
+ watch_address_high = upper_32_bits(watch_address) & 0xffff;
+
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ VMID,
+ debug_vmid);
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ MODE,
+ watch_mode);
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ MASK,
+ watch_address_mask >> 6);
+
+ /* Turning off this watch point until we set all the registers */
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ VALID,
+ 0);
+
+ WREG32_RLC((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_cntl);
+
+ WREG32_RLC((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_H) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_high);
+
+ WREG32_RLC((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_L) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_low);
+
+ /* Enable the watch point */
+ watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+ TCP_WATCH0_CNTL,
+ VALID,
+ 1);
+
+ WREG32_RLC((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_cntl);
+
+ return 0;
+}
+
+uint32_t kgd_gfx_v9_clear_address_watch(struct amdgpu_device *adev,
+ uint32_t watch_id)
+{
+ uint32_t watch_address_cntl;
+
+ watch_address_cntl = 0;
+
+ WREG32_RLC((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
+ (watch_id * TCP_WATCH_STRIDE)),
+ watch_address_cntl);
+
+ return 0;
+}
+
+/* kgd_gfx_v9_get_iq_wait_times: Returns the mmCP_IQ_WAIT_TIME1/2 values
+ * The values read are:
+ * ib_offload_wait_time -- Wait Count for Indirect Buffer Offloads.
+ * atomic_offload_wait_time -- Wait Count for L2 and GDS Atomics Offloads.
+ * wrm_offload_wait_time -- Wait Count for WAIT_REG_MEM Offloads.
+ * gws_wait_time -- Wait Count for Global Wave Syncs.
+ * que_sleep_wait_time -- Wait Count for Dequeue Retry.
+ * sch_wave_wait_time -- Wait Count for Scheduling Wave Message.
+ * sem_rearm_wait_time -- Wait Count for Semaphore re-arm.
+ * deq_retry_wait_time -- Wait Count for Global Wave Syncs.
+ */
+void kgd_gfx_v9_get_iq_wait_times(struct amdgpu_device *adev,
+ uint32_t *wait_times)
+
+{
+ *wait_times = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2));
+}
+
void kgd_gfx_v9_set_vm_context_page_table_base(struct amdgpu_device *adev,
uint32_t vmid, uint64_t page_table_base)
{
@@ -682,10 +945,11 @@ static void unlock_spi_csq_mutexes(struct amdgpu_device *adev)
* @queue_idx: Index of queue in the queue-map bit-field
* @wave_cnt: Output parameter updated with number of waves in flight
* @vmid: Output parameter updated with VMID of queue whose wave count
- * is being collected
+ * is being collected
+ * @inst: xcc's instance number on a multi-XCC setup
*/
static void get_wave_count(struct amdgpu_device *adev, int queue_idx,
- int *wave_cnt, int *vmid)
+ int *wave_cnt, int *vmid, uint32_t inst)
{
int pipe_idx;
int queue_slot;
@@ -700,12 +964,12 @@ static void get_wave_count(struct amdgpu_device *adev, int queue_idx,
*wave_cnt = 0;
pipe_idx = queue_idx / adev->gfx.mec.num_queue_per_pipe;
queue_slot = queue_idx % adev->gfx.mec.num_queue_per_pipe;
- soc15_grbm_select(adev, 1, pipe_idx, queue_slot, 0);
- reg_val = RREG32_SOC15_IP(GC, SOC15_REG_OFFSET(GC, 0, mmSPI_CSQ_WF_ACTIVE_COUNT_0) +
+ soc15_grbm_select(adev, 1, pipe_idx, queue_slot, 0, inst);
+ reg_val = RREG32_SOC15_IP(GC, SOC15_REG_OFFSET(GC, inst, mmSPI_CSQ_WF_ACTIVE_COUNT_0) +
queue_slot);
*wave_cnt = reg_val & SPI_CSQ_WF_ACTIVE_COUNT_0__COUNT_MASK;
if (*wave_cnt != 0)
- *vmid = (RREG32_SOC15(GC, 0, mmCP_HQD_VMID) &
+ *vmid = (RREG32_SOC15(GC, inst, mmCP_HQD_VMID) &
CP_HQD_VMID__VMID_MASK) >> CP_HQD_VMID__VMID__SHIFT;
}
@@ -718,9 +982,10 @@ static void get_wave_count(struct amdgpu_device *adev, int queue_idx,
* @adev: Handle of device from which to get number of waves in flight
* @pasid: Identifies the process for which this query call is invoked
* @pasid_wave_cnt: Output parameter updated with number of waves in flight that
- * belong to process with given pasid
+ * belong to process with given pasid
* @max_waves_per_cu: Output parameter updated with maximum number of waves
- * possible per Compute Unit
+ * possible per Compute Unit
+ * @inst: xcc's instance number on a multi-XCC setup
*
* Note: It's possible that the device has too many queues (oversubscription)
* in which case a VMID could be remapped to a different PASID. This could lead
@@ -756,7 +1021,7 @@ static void get_wave_count(struct amdgpu_device *adev, int queue_idx,
* Reading registers referenced above involves programming GRBM appropriately
*/
void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
- int *pasid_wave_cnt, int *max_waves_per_cu)
+ int *pasid_wave_cnt, int *max_waves_per_cu, uint32_t inst)
{
int qidx;
int vmid;
@@ -772,13 +1037,13 @@ void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
DECLARE_BITMAP(cp_queue_bitmap, KGD_MAX_QUEUES);
lock_spi_csq_mutexes(adev);
- soc15_grbm_select(adev, 1, 0, 0, 0);
+ soc15_grbm_select(adev, 1, 0, 0, 0, inst);
/*
* Iterate through the shader engines and arrays of the device
* to get number of waves in flight
*/
- bitmap_complement(cp_queue_bitmap, adev->gfx.mec.queue_bitmap,
+ bitmap_complement(cp_queue_bitmap, adev->gfx.mec_bitmap[0].queue_bitmap,
KGD_MAX_QUEUES);
max_queue_cnt = adev->gfx.mec.num_pipe_per_mec *
adev->gfx.mec.num_queue_per_pipe;
@@ -787,8 +1052,8 @@ void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
for (se_idx = 0; se_idx < se_cnt; se_idx++) {
for (sh_idx = 0; sh_idx < sh_cnt; sh_idx++) {
- amdgpu_gfx_select_se_sh(adev, se_idx, sh_idx, 0xffffffff);
- queue_map = RREG32_SOC15(GC, 0, mmSPI_CSQ_WF_ACTIVE_STATUS);
+ amdgpu_gfx_select_se_sh(adev, se_idx, sh_idx, 0xffffffff, inst);
+ queue_map = RREG32_SOC15(GC, inst, mmSPI_CSQ_WF_ACTIVE_STATUS);
/*
* Assumption: queue map encodes following schema: four
@@ -808,10 +1073,11 @@ void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
continue;
/* Get number of waves in flight and aggregate them */
- get_wave_count(adev, qidx, &wave_cnt, &vmid);
+ get_wave_count(adev, qidx, &wave_cnt, &vmid,
+ inst);
if (wave_cnt != 0) {
pasid_tmp =
- RREG32(SOC15_REG_OFFSET(OSSSYS, 0,
+ RREG32(SOC15_REG_OFFSET(OSSSYS, inst,
mmIH_VMID_0_LUT) + vmid);
if (pasid_tmp == pasid)
vmid_wave_cnt += wave_cnt;
@@ -820,8 +1086,8 @@ void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
}
}
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
- soc15_grbm_select(adev, 0, 0, 0, 0);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, inst);
+ soc15_grbm_select(adev, 0, 0, 0, 0, inst);
unlock_spi_csq_mutexes(adev);
/* Update the output parameters and return */
@@ -830,28 +1096,51 @@ void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
adev->gfx.cu_info.max_waves_per_simd;
}
+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)
+{
+ *reg_data = wait_times;
+
+ /*
+ * The CP cannont handle a 0 grace period input and will result in
+ * an infinite grace period being set so set to 1 to prevent this.
+ */
+ if (grace_period == 0)
+ grace_period = 1;
+
+ *reg_data = REG_SET_FIELD(*reg_data,
+ CP_IQ_WAIT_TIME2,
+ SCH_WAVE,
+ grace_period);
+
+ *reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2);
+}
+
void kgd_gfx_v9_program_trap_handler_settings(struct amdgpu_device *adev,
- uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
+ uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr, uint32_t inst)
{
- lock_srbm(adev, 0, 0, 0, vmid);
+ kgd_gfx_v9_lock_srbm(adev, 0, 0, 0, vmid, inst);
/*
* Program TBA registers
*/
- WREG32_SOC15(GC, 0, mmSQ_SHADER_TBA_LO,
+ WREG32_SOC15(GC, GET_INST(GC, inst), mmSQ_SHADER_TBA_LO,
lower_32_bits(tba_addr >> 8));
- WREG32_SOC15(GC, 0, mmSQ_SHADER_TBA_HI,
+ WREG32_SOC15(GC, GET_INST(GC, inst), mmSQ_SHADER_TBA_HI,
upper_32_bits(tba_addr >> 8));
/*
* Program TMA registers
*/
- WREG32_SOC15(GC, 0, mmSQ_SHADER_TMA_LO,
+ WREG32_SOC15(GC, GET_INST(GC, inst), mmSQ_SHADER_TMA_LO,
lower_32_bits(tma_addr >> 8));
- WREG32_SOC15(GC, 0, mmSQ_SHADER_TMA_HI,
+ WREG32_SOC15(GC, GET_INST(GC, inst), mmSQ_SHADER_TMA_HI,
upper_32_bits(tma_addr >> 8));
- unlock_srbm(adev);
+ kgd_gfx_v9_unlock_srbm(adev, inst);
}
const struct kfd2kgd_calls gfx_v9_kfd2kgd = {
@@ -871,6 +1160,15 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = {
.get_atc_vmid_pasid_mapping_info =
kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
.set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base,
+ .enable_debug_trap = kgd_gfx_v9_enable_debug_trap,
+ .disable_debug_trap = kgd_gfx_v9_disable_debug_trap,
+ .validate_trap_override_request = kgd_gfx_v9_validate_trap_override_request,
+ .set_wave_launch_trap_override = kgd_gfx_v9_set_wave_launch_trap_override,
+ .set_wave_launch_mode = kgd_gfx_v9_set_wave_launch_mode,
+ .set_address_watch = kgd_gfx_v9_set_address_watch,
+ .clear_address_watch = kgd_gfx_v9_clear_address_watch,
+ .get_iq_wait_times = kgd_gfx_v9_get_iq_wait_times,
+ .build_grace_period_packet_info = kgd_gfx_v9_build_grace_period_packet_info,
.get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy,
.program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h
index c7ed3bc9053c..5f54bff0db49 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h
@@ -20,41 +20,81 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-
-
void kgd_gfx_v9_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
uint32_t sh_mem_config,
uint32_t sh_mem_ape1_base, uint32_t sh_mem_ape1_limit,
- uint32_t sh_mem_bases);
+ uint32_t sh_mem_bases, uint32_t inst);
int kgd_gfx_v9_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
- unsigned int vmid);
-int kgd_gfx_v9_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id);
+ unsigned int vmid, uint32_t inst);
+int kgd_gfx_v9_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id,
+ uint32_t inst);
int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd, uint32_t pipe_id,
uint32_t queue_id, uint32_t __user *wptr,
uint32_t wptr_shift, uint32_t wptr_mask,
- struct mm_struct *mm);
+ struct mm_struct *mm, uint32_t inst);
int kgd_gfx_v9_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t doorbell_off);
+ uint32_t doorbell_off, uint32_t inst);
int kgd_gfx_v9_hqd_dump(struct amdgpu_device *adev,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t (**dump)[2], uint32_t *n_regs);
+ uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst);
bool kgd_gfx_v9_hqd_is_occupied(struct amdgpu_device *adev,
uint64_t queue_address, uint32_t pipe_id,
- uint32_t queue_id);
+ uint32_t queue_id, uint32_t inst);
int kgd_gfx_v9_hqd_destroy(struct amdgpu_device *adev, void *mqd,
enum kfd_preempt_type reset_type,
unsigned int utimeout, uint32_t pipe_id,
- uint32_t queue_id);
+ uint32_t queue_id, uint32_t inst);
int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev,
uint32_t gfx_index_val,
- uint32_t sq_cmd);
+ uint32_t sq_cmd, uint32_t inst);
bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
uint8_t vmid, uint16_t *p_pasid);
-
void kgd_gfx_v9_set_vm_context_page_table_base(struct amdgpu_device *adev,
uint32_t vmid, uint64_t page_table_base);
void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
- int *pasid_wave_cnt, int *max_waves_per_cu);
+ int *pasid_wave_cnt, int *max_waves_per_cu, uint32_t inst);
void kgd_gfx_v9_program_trap_handler_settings(struct amdgpu_device *adev,
- uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr);
+ uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr,
+ uint32_t inst);
+void kgd_gfx_v9_acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
+ uint32_t queue_id, uint32_t inst);
+uint64_t kgd_gfx_v9_get_queue_mask(struct amdgpu_device *adev,
+ uint32_t pipe_id, uint32_t queue_id);
+void kgd_gfx_v9_release_queue(struct amdgpu_device *adev, uint32_t inst);
+void kgd_gfx_v9_set_wave_launch_stall(struct amdgpu_device *adev,
+ uint32_t vmid,
+ bool stall);
+uint32_t kgd_gfx_v9_enable_debug_trap(struct amdgpu_device *adev,
+ bool restore_dbg_registers,
+ uint32_t vmid);
+uint32_t kgd_gfx_v9_disable_debug_trap(struct amdgpu_device *adev,
+ bool keep_trap_enabled,
+ uint32_t vmid);
+int kgd_gfx_v9_validate_trap_override_request(struct amdgpu_device *adev,
+ uint32_t trap_override,
+ uint32_t *trap_mask_supported);
+uint32_t kgd_gfx_v9_set_wave_launch_mode(struct amdgpu_device *adev,
+ uint8_t wave_launch_mode,
+ uint32_t vmid);
+uint32_t kgd_gfx_v9_set_wave_launch_trap_override(struct amdgpu_device *adev,
+ uint32_t vmid,
+ uint32_t trap_override,
+ uint32_t trap_mask_bits,
+ uint32_t trap_mask_request,
+ uint32_t *trap_mask_prev,
+ uint32_t kfd_dbg_trap_cntl_prev);
+uint32_t kgd_gfx_v9_set_address_watch(struct amdgpu_device *adev,
+ uint64_t watch_address,
+ uint32_t watch_address_mask,
+ uint32_t watch_id,
+ uint32_t watch_mode,
+ uint32_t debug_vmid);
+uint32_t kgd_gfx_v9_clear_address_watch(struct amdgpu_device *adev,
+ uint32_t watch_id);
+void kgd_gfx_v9_get_iq_wait_times(struct amdgpu_device *adev, uint32_t *wait_times);
+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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 83a83ced2439..f61527b800e6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -35,7 +35,9 @@
#include "amdgpu_dma_buf.h"
#include <uapi/linux/kfd_ioctl.h>
#include "amdgpu_xgmi.h"
+#include "kfd_priv.h"
#include "kfd_smi_events.h"
+#include <drm/ttm/ttm_tt.h>
/* Userptr restore delay, just long enough to allow consecutive VM
* changes to accumulate
@@ -110,13 +112,16 @@ void amdgpu_amdkfd_gpuvm_init_mem_limits(void)
struct sysinfo si;
uint64_t mem;
+ if (kfd_mem_limit.max_system_mem_limit)
+ return;
+
si_meminfo(&si);
mem = si.freeram - si.freehigh;
mem *= si.mem_unit;
spin_lock_init(&kfd_mem_limit.mem_limit_lock);
kfd_mem_limit.max_system_mem_limit = mem - (mem >> 4);
- kfd_mem_limit.max_ttm_mem_limit = (mem >> 1) - (mem >> 3);
+ kfd_mem_limit.max_ttm_mem_limit = ttm_tt_pages_limit() << PAGE_SHIFT;
pr_debug("Kernel memory limit %lluM, TTM limit %lluM\n",
(kfd_mem_limit.max_system_mem_limit >> 20),
(kfd_mem_limit.max_ttm_mem_limit >> 20));
@@ -148,16 +153,20 @@ void amdgpu_amdkfd_reserve_system_mem(uint64_t size)
* @size: Size of buffer, in bytes, encapsulated by B0. This should be
* equivalent to amdgpu_bo_size(BO)
* @alloc_flag: Flag used in allocating a BO as noted above
+ * @xcp_id: xcp_id is used to get xcp from xcp manager, one xcp is
+ * managed as one compute node in driver for app
*
- * Return: returns -ENOMEM in case of error, ZERO otherwise
+ * Return:
+ * returns -ENOMEM in case of error, ZERO otherwise
*/
int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
- uint64_t size, u32 alloc_flag)
+ uint64_t size, u32 alloc_flag, int8_t xcp_id)
{
uint64_t reserved_for_pt =
ESTIMATE_PT_SIZE(amdgpu_amdkfd_total_mem_size);
size_t system_mem_needed, ttm_mem_needed, vram_needed;
int ret = 0;
+ uint64_t vram_size = 0;
system_mem_needed = 0;
ttm_mem_needed = 0;
@@ -172,6 +181,17 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
* 2M BO chunk.
*/
vram_needed = size;
+ /*
+ * For GFX 9.4.3, get the VRAM size from XCP structs
+ */
+ if (WARN_ONCE(xcp_id < 0, "invalid XCP ID %d", xcp_id))
+ return -EINVAL;
+
+ vram_size = KFD_XCP_MEMORY_SIZE(adev, xcp_id);
+ if (adev->gmc.is_app_apu) {
+ system_mem_needed = size;
+ ttm_mem_needed = size;
+ }
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) {
system_mem_needed = size;
} else if (!(alloc_flag &
@@ -191,8 +211,8 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
kfd_mem_limit.max_system_mem_limit && !no_system_mem_limit) ||
(kfd_mem_limit.ttm_mem_used + ttm_mem_needed >
kfd_mem_limit.max_ttm_mem_limit) ||
- (adev && adev->kfd.vram_used + vram_needed >
- adev->gmc.real_vram_size - reserved_for_pt)) {
+ (adev && xcp_id >= 0 && adev->kfd.vram_used[xcp_id] + vram_needed >
+ vram_size - reserved_for_pt)) {
ret = -ENOMEM;
goto release;
}
@@ -202,9 +222,11 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
*/
WARN_ONCE(vram_needed && !adev,
"adev reference can't be null when vram is used");
- if (adev) {
- adev->kfd.vram_used += vram_needed;
- adev->kfd.vram_used_aligned += ALIGN(vram_needed, VRAM_AVAILABLITY_ALIGN);
+ if (adev && xcp_id >= 0) {
+ adev->kfd.vram_used[xcp_id] += vram_needed;
+ adev->kfd.vram_used_aligned[xcp_id] += adev->gmc.is_app_apu ?
+ vram_needed :
+ ALIGN(vram_needed, VRAM_AVAILABLITY_ALIGN);
}
kfd_mem_limit.system_mem_used += system_mem_needed;
kfd_mem_limit.ttm_mem_used += ttm_mem_needed;
@@ -215,7 +237,7 @@ release:
}
void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev,
- uint64_t size, u32 alloc_flag)
+ uint64_t size, u32 alloc_flag, int8_t xcp_id)
{
spin_lock(&kfd_mem_limit.mem_limit_lock);
@@ -225,9 +247,19 @@ void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev,
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) {
WARN_ONCE(!adev,
"adev reference can't be null when alloc mem flags vram is set");
+ if (WARN_ONCE(xcp_id < 0, "invalid XCP ID %d", xcp_id))
+ goto release;
+
if (adev) {
- adev->kfd.vram_used -= size;
- adev->kfd.vram_used_aligned -= ALIGN(size, VRAM_AVAILABLITY_ALIGN);
+ adev->kfd.vram_used[xcp_id] -= size;
+ if (adev->gmc.is_app_apu) {
+ adev->kfd.vram_used_aligned[xcp_id] -= size;
+ kfd_mem_limit.system_mem_used -= size;
+ kfd_mem_limit.ttm_mem_used -= size;
+ } else {
+ adev->kfd.vram_used_aligned[xcp_id] -=
+ ALIGN(size, VRAM_AVAILABLITY_ALIGN);
+ }
}
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) {
kfd_mem_limit.system_mem_used -= size;
@@ -237,8 +269,8 @@ void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev,
pr_err("%s: Invalid BO type %#x\n", __func__, alloc_flag);
goto release;
}
- WARN_ONCE(adev && adev->kfd.vram_used < 0,
- "KFD VRAM memory accounting unbalanced");
+ WARN_ONCE(adev && xcp_id >= 0 && adev->kfd.vram_used[xcp_id] < 0,
+ "KFD VRAM memory accounting unbalanced for xcp: %d", xcp_id);
WARN_ONCE(kfd_mem_limit.ttm_mem_used < 0,
"KFD TTM memory accounting unbalanced");
WARN_ONCE(kfd_mem_limit.system_mem_used < 0,
@@ -254,14 +286,16 @@ void amdgpu_amdkfd_release_notify(struct amdgpu_bo *bo)
u32 alloc_flags = bo->kfd_bo->alloc_flags;
u64 size = amdgpu_bo_size(bo);
- amdgpu_amdkfd_unreserve_mem_limit(adev, size, alloc_flags);
+ amdgpu_amdkfd_unreserve_mem_limit(adev, size, alloc_flags,
+ bo->xcp_id);
kfree(bo->kfd_bo);
}
/**
- * @create_dmamap_sg_bo: Creates a amdgpu_bo object to reflect information
+ * create_dmamap_sg_bo() - Creates a amdgpu_bo object to reflect information
* about USERPTR or DOOREBELL or MMIO BO.
+ *
* @adev: Device for which dmamap BO is being created
* @mem: BO of peer device that is being DMA mapped. Provides parameters
* in building the dmamap BO
@@ -285,7 +319,7 @@ create_dmamap_sg_bo(struct amdgpu_device *adev,
ret = amdgpu_gem_object_create(adev, mem->bo->tbo.base.size, 1,
AMDGPU_GEM_DOMAIN_CPU, AMDGPU_GEM_CREATE_PREEMPTIBLE | flags,
- ttm_bo_type_sg, mem->bo->tbo.base.resv, &gem_obj);
+ ttm_bo_type_sg, mem->bo->tbo.base.resv, &gem_obj, 0);
amdgpu_bo_unreserve(mem->bo);
@@ -527,6 +561,12 @@ kfd_mem_dmamap_dmabuf(struct kfd_mem_attachment *attachment)
{
struct ttm_operation_ctx ctx = {.interruptible = true};
struct amdgpu_bo *bo = attachment->bo_va->base.bo;
+ int ret;
+
+ amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
+ ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
+ if (ret)
+ return ret;
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_GTT);
return ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
@@ -659,11 +699,10 @@ kfd_mem_dmaunmap_userptr(struct kgd_mem *mem,
static void
kfd_mem_dmaunmap_dmabuf(struct kfd_mem_attachment *attachment)
{
- struct ttm_operation_ctx ctx = {.interruptible = true};
- struct amdgpu_bo *bo = attachment->bo_va->base.bo;
-
- amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
- ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
+ /* This is a no-op. We don't want to trigger eviction fences when
+ * unmapping DMABufs. Therefore the invalidation (moving to system
+ * domain) is done in kfd_mem_dmamap_dmabuf.
+ */
}
/**
@@ -804,7 +843,7 @@ static int kfd_mem_attach(struct amdgpu_device *adev, struct kgd_mem *mem,
* if peer device has large BAR. In contrast, access over xGMI is
* allowed for both small and large BAR configurations of peer device
*/
- if ((adev != bo_adev) &&
+ if ((adev != bo_adev && !adev->gmc.is_app_apu) &&
((mem->domain == AMDGPU_GEM_DOMAIN_VRAM) ||
(mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) ||
(mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP))) {
@@ -1599,23 +1638,42 @@ out_unlock:
return ret;
}
-size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev)
+size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev,
+ uint8_t xcp_id)
{
uint64_t reserved_for_pt =
ESTIMATE_PT_SIZE(amdgpu_amdkfd_total_mem_size);
ssize_t available;
+ uint64_t vram_available, system_mem_available, ttm_mem_available;
spin_lock(&kfd_mem_limit.mem_limit_lock);
- available = adev->gmc.real_vram_size
- - adev->kfd.vram_used_aligned
+ vram_available = KFD_XCP_MEMORY_SIZE(adev, xcp_id)
+ - adev->kfd.vram_used_aligned[xcp_id]
- atomic64_read(&adev->vram_pin_size)
- reserved_for_pt;
+
+ if (adev->gmc.is_app_apu) {
+ system_mem_available = no_system_mem_limit ?
+ kfd_mem_limit.max_system_mem_limit :
+ kfd_mem_limit.max_system_mem_limit -
+ kfd_mem_limit.system_mem_used;
+
+ ttm_mem_available = kfd_mem_limit.max_ttm_mem_limit -
+ kfd_mem_limit.ttm_mem_used;
+
+ available = min3(system_mem_available, ttm_mem_available,
+ vram_available);
+ available = ALIGN_DOWN(available, PAGE_SIZE);
+ } else {
+ available = ALIGN_DOWN(vram_available, VRAM_AVAILABLITY_ALIGN);
+ }
+
spin_unlock(&kfd_mem_limit.mem_limit_lock);
if (available < 0)
available = 0;
- return ALIGN_DOWN(available, VRAM_AVAILABLITY_ALIGN);
+ return available;
}
int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
@@ -1624,6 +1682,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
uint64_t *offset, uint32_t flags, bool criu_resume)
{
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
+ struct amdgpu_fpriv *fpriv = container_of(avm, struct amdgpu_fpriv, vm);
enum ttm_bo_type bo_type = ttm_bo_type_device;
struct sg_table *sg = NULL;
uint64_t user_addr = 0;
@@ -1631,6 +1690,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
struct drm_gem_object *gobj = NULL;
u32 domain, alloc_domain;
uint64_t aligned_size;
+ int8_t xcp_id = -1;
u64 alloc_flags;
int ret;
@@ -1639,9 +1699,17 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
*/
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) {
domain = alloc_domain = AMDGPU_GEM_DOMAIN_VRAM;
- alloc_flags = AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
- alloc_flags |= (flags & KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC) ?
+
+ if (adev->gmc.is_app_apu) {
+ domain = AMDGPU_GEM_DOMAIN_GTT;
+ alloc_domain = AMDGPU_GEM_DOMAIN_GTT;
+ alloc_flags = 0;
+ } else {
+ alloc_flags = AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
+ alloc_flags |= (flags & KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC) ?
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED : 0;
+ }
+ xcp_id = fpriv->xcp_id == ~0 ? 0 : fpriv->xcp_id;
} else if (flags & KFD_IOC_ALLOC_MEM_FLAGS_GTT) {
domain = alloc_domain = AMDGPU_GEM_DOMAIN_GTT;
alloc_flags = 0;
@@ -1693,17 +1761,19 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
amdgpu_sync_create(&(*mem)->sync);
- ret = amdgpu_amdkfd_reserve_mem_limit(adev, aligned_size, flags);
+ ret = amdgpu_amdkfd_reserve_mem_limit(adev, aligned_size, flags,
+ xcp_id);
if (ret) {
pr_debug("Insufficient memory\n");
goto err_reserve_limit;
}
- pr_debug("\tcreate BO VA 0x%llx size 0x%llx domain %s\n",
- va, (*mem)->aql_queue ? size << 1 : size, domain_string(alloc_domain));
+ pr_debug("\tcreate BO VA 0x%llx size 0x%llx domain %s xcp_id %d\n",
+ va, (*mem)->aql_queue ? size << 1 : size,
+ domain_string(alloc_domain), xcp_id);
ret = amdgpu_gem_object_create(adev, aligned_size, 1, alloc_domain, alloc_flags,
- bo_type, NULL, &gobj);
+ bo_type, NULL, &gobj, xcp_id + 1);
if (ret) {
pr_debug("Failed to create BO on domain %s. ret %d\n",
domain_string(alloc_domain), ret);
@@ -1728,6 +1798,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
(*mem)->domain = domain;
(*mem)->mapped_to_gpu_memory = 0;
(*mem)->process_info = avm->process_info;
+
add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, user_addr);
if (user_addr) {
@@ -1759,7 +1830,7 @@ err_node_allow:
/* Don't unreserve system mem limit twice */
goto err_reserve_limit;
err_bo_create:
- amdgpu_amdkfd_unreserve_mem_limit(adev, aligned_size, flags);
+ amdgpu_amdkfd_unreserve_mem_limit(adev, aligned_size, flags, xcp_id);
err_reserve_limit:
mutex_destroy(&(*mem)->lock);
if (gobj)
@@ -1855,11 +1926,14 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
}
/* Update the size of the BO being freed if it was allocated from
- * VRAM and is not imported.
+ * VRAM and is not imported. For APP APU VRAM allocations are done
+ * in GTT domain
*/
if (size) {
- if ((mem->bo->preferred_domains == AMDGPU_GEM_DOMAIN_VRAM) &&
- (!is_imported))
+ if (!is_imported &&
+ (mem->bo->preferred_domains == AMDGPU_GEM_DOMAIN_VRAM ||
+ (adev->gmc.is_app_apu &&
+ mem->bo->preferred_domains == AMDGPU_GEM_DOMAIN_GTT)))
*size = bo_size;
else
*size = 0;
@@ -2282,8 +2356,9 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
(*mem)->dmabuf = dma_buf;
(*mem)->bo = bo;
(*mem)->va = va;
- (*mem)->domain = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ?
+ (*mem)->domain = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) && !adev->gmc.is_app_apu ?
AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT;
+
(*mem)->mapped_to_gpu_memory = 0;
(*mem)->process_info = avm->process_info;
add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, false);
@@ -2445,7 +2520,9 @@ static int update_invalid_user_pages(struct amdkfd_process_info *process_info,
ret = -EAGAIN;
goto unlock_out;
}
- mem->invalid = 0;
+ /* set mem valid if mem has hmm range associated */
+ if (mem->range)
+ mem->invalid = 0;
}
unlock_out:
@@ -2577,8 +2654,15 @@ static int confirm_valid_user_pages_locked(struct amdkfd_process_info *process_i
list_for_each_entry_safe(mem, tmp_mem,
&process_info->userptr_inval_list,
validate_list.head) {
- bool valid = amdgpu_ttm_tt_get_user_pages_done(
- mem->bo->tbo.ttm, mem->range);
+ bool valid;
+
+ /* keep mem without hmm range at userptr_inval_list */
+ if (!mem->range)
+ continue;
+
+ /* Only check mem with hmm range associated */
+ valid = amdgpu_ttm_tt_get_user_pages_done(
+ mem->bo->tbo.ttm, mem->range);
mem->range = NULL;
if (!valid) {
@@ -2586,7 +2670,12 @@ static int confirm_valid_user_pages_locked(struct amdkfd_process_info *process_i
ret = -EAGAIN;
continue;
}
- WARN(mem->invalid, "Valid BO is marked invalid");
+
+ if (mem->invalid) {
+ WARN(1, "Valid BO is marked invalid");
+ ret = -EAGAIN;
+ continue;
+ }
list_move_tail(&mem->validate_list.head,
&process_info->userptr_valid_list);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
index ac6fe0ae4609..ef4b9a41f20a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
@@ -272,6 +272,7 @@ static int convert_atom_mem_type_to_vram_type(struct amdgpu_device *adev,
break;
case ATOM_DGPU_VRAM_TYPE_HBM2:
case ATOM_DGPU_VRAM_TYPE_HBM2E:
+ case ATOM_DGPU_VRAM_TYPE_HBM3:
vram_type = AMDGPU_VRAM_TYPE_HBM;
break;
case ATOM_DGPU_VRAM_TYPE_GDDR6:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index 30c28a69e847..b582b83c4984 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -104,9 +104,8 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
adev->bios = NULL;
vram_base = pci_resource_start(adev->pdev, 0);
bios = ioremap_wc(vram_base, size);
- if (!bios) {
+ if (!bios)
return false;
- }
adev->bios = kmalloc(size, GFP_KERNEL);
if (!adev->bios) {
@@ -133,9 +132,8 @@ bool amdgpu_read_bios(struct amdgpu_device *adev)
adev->bios = NULL;
/* XXX: some cards may return 0 for rom size? ddx has a workaround */
bios = pci_map_rom(adev->pdev, &size);
- if (!bios) {
+ if (!bios)
return false;
- }
adev->bios = kzalloc(size, GFP_KERNEL);
if (adev->bios == NULL) {
@@ -168,9 +166,9 @@ static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
header[AMD_VBIOS_SIGNATURE_END] = 0;
if ((!AMD_IS_VALID_VBIOS(header)) ||
- 0 != memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET],
- AMD_VBIOS_SIGNATURE,
- strlen(AMD_VBIOS_SIGNATURE)))
+ memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET],
+ AMD_VBIOS_SIGNATURE,
+ strlen(AMD_VBIOS_SIGNATURE)) != 0)
return false;
/* valid vbios, go on */
@@ -264,7 +262,7 @@ static int amdgpu_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
if (ACPI_FAILURE(status)) {
- printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
+ DRM_ERROR("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
return -ENODEV;
}
@@ -363,7 +361,7 @@ static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
struct acpi_table_header *hdr;
acpi_size tbl_size;
UEFI_ACPI_VFCT *vfct;
- unsigned offset;
+ unsigned int offset;
if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
return false;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index 6be30dcb029d..d34037b85cf8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -593,11 +593,20 @@ static int amdgpu_connector_set_property(struct drm_connector *connector,
switch (val) {
default:
- case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
- case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
- case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
- case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
+ case DRM_MODE_SCALE_NONE:
+ rmx_type = RMX_OFF;
+ break;
+ case DRM_MODE_SCALE_CENTER:
+ rmx_type = RMX_CENTER;
+ break;
+ case DRM_MODE_SCALE_ASPECT:
+ rmx_type = RMX_ASPECT;
+ break;
+ case DRM_MODE_SCALE_FULLSCREEN:
+ rmx_type = RMX_FULL;
+ break;
}
+
if (amdgpu_encoder->rmx_type == rmx_type)
return 0;
@@ -799,12 +808,21 @@ static int amdgpu_connector_set_lcd_property(struct drm_connector *connector,
}
switch (value) {
- case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
- case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
- case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
+ case DRM_MODE_SCALE_NONE:
+ rmx_type = RMX_OFF;
+ break;
+ case DRM_MODE_SCALE_CENTER:
+ rmx_type = RMX_CENTER;
+ break;
+ case DRM_MODE_SCALE_ASPECT:
+ rmx_type = RMX_ASPECT;
+ break;
default:
- case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
+ case DRM_MODE_SCALE_FULLSCREEN:
+ rmx_type = RMX_FULL;
+ break;
}
+
if (amdgpu_encoder->rmx_type == rmx_type)
return 0;
@@ -1127,7 +1145,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
/* assume digital unless load detected otherwise */
amdgpu_connector->use_digital = true;
lret = encoder_funcs->detect(encoder, connector);
- DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret);
+ DRM_DEBUG_KMS("load_detect %x returned: %x\n",
+ encoder->encoder_type, lret);
if (lret == connector_status_connected)
amdgpu_connector->use_digital = false;
}
@@ -1991,7 +2010,7 @@ amdgpu_connector_add(struct amdgpu_device *adev,
if (amdgpu_connector->hpd.hpd == AMDGPU_HPD_NONE) {
if (i2c_bus->valid) {
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
- DRM_CONNECTOR_POLL_DISCONNECT;
+ DRM_CONNECTOR_POLL_DISCONNECT;
}
} else
connector->polled = DRM_CONNECTOR_POLL_HPD;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 2eb2c66843a8..d9503882ea97 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -112,6 +112,9 @@ static int amdgpu_cs_p1_ib(struct amdgpu_cs_parser *p,
if (r < 0)
return r;
+ if (num_ibs[r] >= amdgpu_ring_max_ibs(chunk_ib->ip_type))
+ return -EINVAL;
+
++(num_ibs[r]);
p->gang_leader_idx = r;
return 0;
@@ -192,7 +195,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
uint64_t *chunk_array_user;
uint64_t *chunk_array;
uint32_t uf_offset = 0;
- unsigned int size;
+ size_t size;
int ret;
int i;
@@ -285,6 +288,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
case AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES:
case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT:
case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL:
+ case AMDGPU_CHUNK_ID_CP_GFX_SHADOW:
break;
default:
@@ -305,7 +309,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
}
p->gang_leader = p->jobs[p->gang_leader_idx];
- if (p->ctx->vram_lost_counter != p->gang_leader->vram_lost_counter) {
+ if (p->ctx->generation != p->gang_leader->generation) {
ret = -ECANCELED;
goto free_all_kdata;
}
@@ -393,7 +397,7 @@ static int amdgpu_cs_p2_dependencies(struct amdgpu_cs_parser *p,
{
struct drm_amdgpu_cs_chunk_dep *deps = chunk->kdata;
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
- unsigned num_deps;
+ unsigned int num_deps;
int i, r;
num_deps = chunk->length_dw * 4 /
@@ -464,7 +468,7 @@ static int amdgpu_cs_p2_syncobj_in(struct amdgpu_cs_parser *p,
struct amdgpu_cs_chunk *chunk)
{
struct drm_amdgpu_cs_chunk_sem *deps = chunk->kdata;
- unsigned num_deps;
+ unsigned int num_deps;
int i, r;
num_deps = chunk->length_dw * 4 /
@@ -482,7 +486,7 @@ static int amdgpu_cs_p2_syncobj_timeline_wait(struct amdgpu_cs_parser *p,
struct amdgpu_cs_chunk *chunk)
{
struct drm_amdgpu_cs_chunk_syncobj *syncobj_deps = chunk->kdata;
- unsigned num_deps;
+ unsigned int num_deps;
int i, r;
num_deps = chunk->length_dw * 4 /
@@ -502,7 +506,7 @@ static int amdgpu_cs_p2_syncobj_out(struct amdgpu_cs_parser *p,
struct amdgpu_cs_chunk *chunk)
{
struct drm_amdgpu_cs_chunk_sem *deps = chunk->kdata;
- unsigned num_deps;
+ unsigned int num_deps;
int i;
num_deps = chunk->length_dw * 4 /
@@ -536,7 +540,7 @@ static int amdgpu_cs_p2_syncobj_timeline_signal(struct amdgpu_cs_parser *p,
struct amdgpu_cs_chunk *chunk)
{
struct drm_amdgpu_cs_chunk_syncobj *syncobj_deps = chunk->kdata;
- unsigned num_deps;
+ unsigned int num_deps;
int i;
num_deps = chunk->length_dw * 4 /
@@ -575,6 +579,26 @@ static int amdgpu_cs_p2_syncobj_timeline_signal(struct amdgpu_cs_parser *p,
return 0;
}
+static int amdgpu_cs_p2_shadow(struct amdgpu_cs_parser *p,
+ struct amdgpu_cs_chunk *chunk)
+{
+ struct drm_amdgpu_cs_chunk_cp_gfx_shadow *shadow = chunk->kdata;
+ int i;
+
+ if (shadow->flags & ~AMDGPU_CS_CHUNK_CP_GFX_SHADOW_FLAGS_INIT_SHADOW)
+ return -EINVAL;
+
+ for (i = 0; i < p->gang_size; ++i) {
+ p->jobs[i]->shadow_va = shadow->shadow_va;
+ p->jobs[i]->csa_va = shadow->csa_va;
+ p->jobs[i]->gds_va = shadow->gds_va;
+ p->jobs[i]->init_shadow =
+ shadow->flags & AMDGPU_CS_CHUNK_CP_GFX_SHADOW_FLAGS_INIT_SHADOW;
+ }
+
+ return 0;
+}
+
static int amdgpu_cs_pass2(struct amdgpu_cs_parser *p)
{
unsigned int ce_preempt = 0, de_preempt = 0;
@@ -617,6 +641,11 @@ static int amdgpu_cs_pass2(struct amdgpu_cs_parser *p)
if (r)
return r;
break;
+ case AMDGPU_CHUNK_ID_CP_GFX_SHADOW:
+ r = amdgpu_cs_p2_shadow(p, chunk);
+ if (r)
+ return r;
+ break;
}
}
@@ -729,6 +758,7 @@ static void amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev,
if (used_vis_vram < total_vis_vram) {
u64 free_vis_vram = total_vis_vram - used_vis_vram;
+
adev->mm_stats.accum_us_vis = min(adev->mm_stats.accum_us_vis +
increment_us, us_upper_bound);
@@ -1047,9 +1077,8 @@ static int amdgpu_cs_patch_ibs(struct amdgpu_cs_parser *p,
/* the IB should be reserved at this point */
r = amdgpu_bo_kmap(aobj, (void **)&kptr);
- if (r) {
+ if (r)
return r;
- }
kptr += va_start - (m->start * AMDGPU_GPU_PAGE_SIZE);
@@ -1356,7 +1385,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
/* Cleanup the parser structure */
static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser)
{
- unsigned i;
+ unsigned int i;
amdgpu_sync_free(&parser->sync);
for (i = 0; i < parser->num_post_deps; i++) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c
index c6d4d41c4393..23d054526e7c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c
@@ -106,3 +106,41 @@ int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm,
ttm_eu_backoff_reservation(&ticket, &list);
return 0;
}
+
+int amdgpu_unmap_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ struct amdgpu_bo *bo, struct amdgpu_bo_va *bo_va,
+ uint64_t csa_addr)
+{
+ struct ww_acquire_ctx ticket;
+ struct list_head list;
+ struct amdgpu_bo_list_entry pd;
+ struct ttm_validate_buffer csa_tv;
+ int r;
+
+ INIT_LIST_HEAD(&list);
+ INIT_LIST_HEAD(&csa_tv.head);
+ csa_tv.bo = &bo->tbo;
+ csa_tv.num_shared = 1;
+
+ list_add(&csa_tv.head, &list);
+ amdgpu_vm_get_pd_bo(vm, &list, &pd);
+
+ r = ttm_eu_reserve_buffers(&ticket, &list, true, NULL);
+ if (r) {
+ DRM_ERROR("failed to reserve CSA,PD BOs: err=%d\n", r);
+ return r;
+ }
+
+ r = amdgpu_vm_bo_unmap(adev, bo_va, csa_addr);
+ if (r) {
+ DRM_ERROR("failed to do bo_unmap on static CSA, err=%d\n", r);
+ ttm_eu_backoff_reservation(&ticket, &list);
+ return r;
+ }
+
+ amdgpu_vm_bo_del(adev, bo_va);
+
+ ttm_eu_backoff_reservation(&ticket, &list);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.h
index 524b4437a021..7dfc1f2012eb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.h
@@ -34,6 +34,9 @@ int amdgpu_allocate_static_csa(struct amdgpu_device *adev, struct amdgpu_bo **bo
int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm,
struct amdgpu_bo *bo, struct amdgpu_bo_va **bo_va,
uint64_t csa_addr, uint32_t size);
+int amdgpu_unmap_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ struct amdgpu_bo *bo, struct amdgpu_bo_va *bo_va,
+ uint64_t csa_addr);
void amdgpu_free_static_csa(struct amdgpu_bo **bo);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index d2139ac12159..0dc9c655c4fb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -222,8 +222,19 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip,
drm_prio = amdgpu_ctx_to_drm_sched_prio(ctx_prio);
hw_ip = array_index_nospec(hw_ip, AMDGPU_HW_IP_NUM);
- scheds = adev->gpu_sched[hw_ip][hw_prio].sched;
- num_scheds = adev->gpu_sched[hw_ip][hw_prio].num_scheds;
+
+ if (!(adev)->xcp_mgr) {
+ scheds = adev->gpu_sched[hw_ip][hw_prio].sched;
+ num_scheds = adev->gpu_sched[hw_ip][hw_prio].num_scheds;
+ } else {
+ struct amdgpu_fpriv *fpriv;
+
+ fpriv = container_of(ctx->ctx_mgr, struct amdgpu_fpriv, ctx_mgr);
+ r = amdgpu_xcp_select_scheds(adev, hw_ip, hw_prio, fpriv,
+ &num_scheds, &scheds);
+ if (r)
+ goto cleanup_entity;
+ }
/* disable load balance if the hw engine retains context among dependent jobs */
if (hw_ip == AMDGPU_HW_IP_VCN_ENC ||
@@ -255,7 +266,8 @@ error_free_entity:
return r;
}
-static ktime_t amdgpu_ctx_fini_entity(struct amdgpu_ctx_entity *entity)
+static ktime_t amdgpu_ctx_fini_entity(struct amdgpu_device *adev,
+ struct amdgpu_ctx_entity *entity)
{
ktime_t res = ns_to_ktime(0);
int i;
@@ -268,6 +280,8 @@ static ktime_t amdgpu_ctx_fini_entity(struct amdgpu_ctx_entity *entity)
dma_fence_put(entity->fences[i]);
}
+ amdgpu_xcp_release_sched(adev, entity);
+
kfree(entity);
return res;
}
@@ -303,6 +317,7 @@ static int amdgpu_ctx_get_stable_pstate(struct amdgpu_ctx *ctx,
static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority,
struct drm_file *filp, struct amdgpu_ctx *ctx)
{
+ struct amdgpu_fpriv *fpriv = filp->driver_priv;
u32 current_stable_pstate;
int r;
@@ -318,7 +333,7 @@ static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority,
ctx->reset_counter = atomic_read(&mgr->adev->gpu_reset_counter);
ctx->reset_counter_query = ctx->reset_counter;
- ctx->vram_lost_counter = atomic_read(&mgr->adev->vram_lost_counter);
+ ctx->generation = amdgpu_vm_generation(mgr->adev, &fpriv->vm);
ctx->init_priority = priority;
ctx->override_priority = AMDGPU_CTX_PRIORITY_UNSET;
@@ -331,6 +346,7 @@ static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority,
else
ctx->stable_pstate = current_stable_pstate;
+ ctx->ctx_mgr = &(fpriv->ctx_mgr);
return 0;
}
@@ -399,7 +415,7 @@ static void amdgpu_ctx_fini(struct kref *ref)
for (j = 0; j < AMDGPU_MAX_ENTITY_NUM; ++j) {
ktime_t spend;
- spend = amdgpu_ctx_fini_entity(ctx->entities[i][j]);
+ spend = amdgpu_ctx_fini_entity(adev, ctx->entities[i][j]);
atomic64_add(ktime_to_ns(spend), &mgr->time_spend[i]);
}
}
@@ -416,6 +432,7 @@ int amdgpu_ctx_get_entity(struct amdgpu_ctx *ctx, u32 hw_ip, u32 instance,
u32 ring, struct drm_sched_entity **entity)
{
int r;
+ struct drm_sched_entity *ctx_entity;
if (hw_ip >= AMDGPU_HW_IP_NUM) {
DRM_ERROR("unknown HW IP type: %d\n", hw_ip);
@@ -439,7 +456,14 @@ int amdgpu_ctx_get_entity(struct amdgpu_ctx *ctx, u32 hw_ip, u32 instance,
return r;
}
- *entity = &ctx->entities[hw_ip][ring]->entity;
+ ctx_entity = &ctx->entities[hw_ip][ring]->entity;
+ r = drm_sched_entity_error(ctx_entity);
+ if (r) {
+ DRM_DEBUG("error entity %p\n", ctx_entity);
+ return r;
+ }
+
+ *entity = ctx_entity;
return 0;
}
@@ -570,12 +594,15 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev,
if (ctx->reset_counter != atomic_read(&adev->gpu_reset_counter))
out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RESET;
- if (ctx->vram_lost_counter != atomic_read(&adev->vram_lost_counter))
+ if (ctx->generation != amdgpu_vm_generation(adev, &fpriv->vm))
out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST;
if (atomic_read(&ctx->guilty))
out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY;
+ if (amdgpu_in_reset(adev))
+ out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RESET_IN_PROGRESS;
+
if (adev->ras_enabled && con) {
/* Return the cached values in O(1),
* and schedule delayed work to cache
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h
index 0fa0e56daf67..85376baaa92f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h
@@ -47,7 +47,7 @@ struct amdgpu_ctx {
struct amdgpu_ctx_mgr *mgr;
unsigned reset_counter;
unsigned reset_counter_query;
- uint32_t vram_lost_counter;
+ uint64_t generation;
spinlock_t ring_lock;
struct amdgpu_ctx_entity *entities[AMDGPU_HW_IP_NUM][AMDGPU_MAX_ENTITY_NUM];
bool preamble_presented;
@@ -57,6 +57,7 @@ struct amdgpu_ctx {
unsigned long ras_counter_ce;
unsigned long ras_counter_ue;
uint32_t stable_pstate;
+ struct amdgpu_ctx_mgr *ctx_mgr;
};
struct amdgpu_ctx_mgr {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index f60753f97ac5..56e89e76ff17 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -56,14 +56,14 @@
*
* Bit 62: Indicates a GRBM bank switch is needed
* Bit 61: Indicates a SRBM bank switch is needed (implies bit 62 is
- * zero)
+ * zero)
* Bits 24..33: The SE or ME selector if needed
* Bits 34..43: The SH (or SA) or PIPE selector if needed
* Bits 44..53: The INSTANCE (or CU/WGP) or QUEUE selector if needed
*
* Bit 23: Indicates that the PM power gating lock should be held
- * This is necessary to read registers that might be
- * unreliable during a power gating transistion.
+ * This is necessary to read registers that might be
+ * unreliable during a power gating transistion.
*
* The lower bits are the BYTE offset of the register to read. This
* allows reading multiple registers in a single call and having
@@ -76,7 +76,7 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f,
ssize_t result = 0;
int r;
bool pm_pg_lock, use_bank, use_ring;
- unsigned instance_bank, sh_bank, se_bank, me, pipe, queue, vmid;
+ unsigned int instance_bank, sh_bank, se_bank, me, pipe, queue, vmid;
pm_pg_lock = use_bank = use_ring = false;
instance_bank = sh_bank = se_bank = me = pipe = queue = vmid = 0;
@@ -136,10 +136,10 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f,
}
mutex_lock(&adev->grbm_idx_mutex);
amdgpu_gfx_select_se_sh(adev, se_bank,
- sh_bank, instance_bank);
+ sh_bank, instance_bank, 0);
} else if (use_ring) {
mutex_lock(&adev->srbm_mutex);
- amdgpu_gfx_select_me_pipe_q(adev, me, pipe, queue, vmid);
+ amdgpu_gfx_select_me_pipe_q(adev, me, pipe, queue, vmid, 0);
}
if (pm_pg_lock)
@@ -169,10 +169,10 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f,
end:
if (use_bank) {
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
} else if (use_ring) {
- amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0);
+ amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
}
@@ -208,7 +208,7 @@ static int amdgpu_debugfs_regs2_open(struct inode *inode, struct file *file)
{
struct amdgpu_debugfs_regs2_data *rd;
- rd = kzalloc(sizeof *rd, GFP_KERNEL);
+ rd = kzalloc(sizeof(*rd), GFP_KERNEL);
if (!rd)
return -ENOMEM;
rd->adev = file_inode(file)->i_private;
@@ -221,6 +221,7 @@ static int amdgpu_debugfs_regs2_open(struct inode *inode, struct file *file)
static int amdgpu_debugfs_regs2_release(struct inode *inode, struct file *file)
{
struct amdgpu_debugfs_regs2_data *rd = file->private_data;
+
mutex_destroy(&rd->lock);
kfree(file->private_data);
return 0;
@@ -262,14 +263,14 @@ static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 off
}
mutex_lock(&adev->grbm_idx_mutex);
amdgpu_gfx_select_se_sh(adev, rd->id.grbm.se,
- rd->id.grbm.sh,
- rd->id.grbm.instance);
+ rd->id.grbm.sh,
+ rd->id.grbm.instance, rd->id.xcc_id);
}
if (rd->id.use_srbm) {
mutex_lock(&adev->srbm_mutex);
amdgpu_gfx_select_me_pipe_q(adev, rd->id.srbm.me, rd->id.srbm.pipe,
- rd->id.srbm.queue, rd->id.srbm.vmid);
+ rd->id.srbm.queue, rd->id.srbm.vmid, rd->id.xcc_id);
}
if (rd->id.pg_lock)
@@ -295,12 +296,12 @@ static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 off
}
end:
if (rd->id.use_grbm) {
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, rd->id.xcc_id);
mutex_unlock(&adev->grbm_idx_mutex);
}
if (rd->id.use_srbm) {
- amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0);
+ amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0, rd->id.xcc_id);
mutex_unlock(&adev->srbm_mutex);
}
@@ -319,18 +320,45 @@ end:
static long amdgpu_debugfs_regs2_ioctl(struct file *f, unsigned int cmd, unsigned long data)
{
struct amdgpu_debugfs_regs2_data *rd = f->private_data;
+ struct amdgpu_debugfs_regs2_iocdata v1_data;
int r;
+ mutex_lock(&rd->lock);
+
switch (cmd) {
+ case AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE_V2:
+ r = copy_from_user(&rd->id, (struct amdgpu_debugfs_regs2_iocdata_v2 *)data,
+ sizeof(rd->id));
+ if (r)
+ r = -EINVAL;
+ goto done;
case AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE:
- mutex_lock(&rd->lock);
- r = copy_from_user(&rd->id, (struct amdgpu_debugfs_regs2_iocdata *)data, sizeof rd->id);
- mutex_unlock(&rd->lock);
- return r ? -EINVAL : 0;
+ r = copy_from_user(&v1_data, (struct amdgpu_debugfs_regs2_iocdata *)data,
+ sizeof(v1_data));
+ if (r) {
+ r = -EINVAL;
+ goto done;
+ }
+ goto v1_copy;
default:
- return -EINVAL;
- }
- return 0;
+ r = -EINVAL;
+ goto done;
+ }
+
+v1_copy:
+ rd->id.use_srbm = v1_data.use_srbm;
+ rd->id.use_grbm = v1_data.use_grbm;
+ rd->id.pg_lock = v1_data.pg_lock;
+ rd->id.grbm.se = v1_data.grbm.se;
+ rd->id.grbm.sh = v1_data.grbm.sh;
+ rd->id.grbm.instance = v1_data.grbm.instance;
+ rd->id.srbm.me = v1_data.srbm.me;
+ rd->id.srbm.pipe = v1_data.srbm.pipe;
+ rd->id.srbm.queue = v1_data.srbm.queue;
+ rd->id.xcc_id = 0;
+done:
+ mutex_unlock(&rd->lock);
+ return r;
}
static ssize_t amdgpu_debugfs_regs2_read(struct file *f, char __user *buf, size_t size, loff_t *pos)
@@ -343,6 +371,136 @@ static ssize_t amdgpu_debugfs_regs2_write(struct file *f, const char __user *buf
return amdgpu_debugfs_regs2_op(f, (char __user *)buf, *pos, size, 1);
}
+static int amdgpu_debugfs_gprwave_open(struct inode *inode, struct file *file)
+{
+ struct amdgpu_debugfs_gprwave_data *rd;
+
+ rd = kzalloc(sizeof *rd, GFP_KERNEL);
+ if (!rd)
+ return -ENOMEM;
+ rd->adev = file_inode(file)->i_private;
+ file->private_data = rd;
+ mutex_init(&rd->lock);
+
+ return 0;
+}
+
+static int amdgpu_debugfs_gprwave_release(struct inode *inode, struct file *file)
+{
+ struct amdgpu_debugfs_gprwave_data *rd = file->private_data;
+ mutex_destroy(&rd->lock);
+ kfree(file->private_data);
+ return 0;
+}
+
+static ssize_t amdgpu_debugfs_gprwave_read(struct file *f, char __user *buf, size_t size, loff_t *pos)
+{
+ struct amdgpu_debugfs_gprwave_data *rd = f->private_data;
+ struct amdgpu_device *adev = rd->adev;
+ ssize_t result = 0;
+ int r;
+ uint32_t *data, x;
+
+ if (size & 0x3 || *pos & 0x3)
+ return -EINVAL;
+
+ r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
+ if (r < 0) {
+ pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+ return r;
+ }
+
+ r = amdgpu_virt_enable_access_debugfs(adev);
+ if (r < 0) {
+ pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+ return r;
+ }
+
+ data = kcalloc(1024, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+ amdgpu_virt_disable_access_debugfs(adev);
+ return -ENOMEM;
+ }
+
+ /* switch to the specific se/sh/cu */
+ mutex_lock(&adev->grbm_idx_mutex);
+ amdgpu_gfx_select_se_sh(adev, rd->id.se, rd->id.sh, rd->id.cu, rd->id.xcc_id);
+
+ if (!rd->id.gpr_or_wave) {
+ x = 0;
+ if (adev->gfx.funcs->read_wave_data)
+ adev->gfx.funcs->read_wave_data(adev, rd->id.xcc_id, rd->id.simd, rd->id.wave, data, &x);
+ } else {
+ x = size >> 2;
+ if (rd->id.gpr.vpgr_or_sgpr) {
+ if (adev->gfx.funcs->read_wave_vgprs)
+ adev->gfx.funcs->read_wave_vgprs(adev, rd->id.xcc_id, rd->id.simd, rd->id.wave, rd->id.gpr.thread, *pos, size>>2, data);
+ } else {
+ if (adev->gfx.funcs->read_wave_sgprs)
+ adev->gfx.funcs->read_wave_sgprs(adev, rd->id.xcc_id, rd->id.simd, rd->id.wave, *pos, size>>2, data);
+ }
+ }
+
+ amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, rd->id.xcc_id);
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
+ pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+
+ if (!x) {
+ result = -EINVAL;
+ goto done;
+ }
+
+ while (size && (*pos < x * 4)) {
+ uint32_t value;
+
+ value = data[*pos >> 2];
+ r = put_user(value, (uint32_t *)buf);
+ if (r) {
+ result = r;
+ goto done;
+ }
+
+ result += 4;
+ buf += 4;
+ *pos += 4;
+ size -= 4;
+ }
+
+done:
+ amdgpu_virt_disable_access_debugfs(adev);
+ kfree(data);
+ return result;
+}
+
+static long amdgpu_debugfs_gprwave_ioctl(struct file *f, unsigned int cmd, unsigned long data)
+{
+ struct amdgpu_debugfs_gprwave_data *rd = f->private_data;
+ int r = 0;
+
+ mutex_lock(&rd->lock);
+
+ switch (cmd) {
+ case AMDGPU_DEBUGFS_GPRWAVE_IOC_SET_STATE:
+ if (copy_from_user(&rd->id,
+ (struct amdgpu_debugfs_gprwave_iocdata *)data,
+ sizeof(rd->id)))
+ r = -EFAULT;
+ goto done;
+ default:
+ r = -EINVAL;
+ goto done;
+ }
+
+done:
+ mutex_unlock(&rd->lock);
+ return r;
+}
+
+
+
/**
* amdgpu_debugfs_regs_pcie_read - Read from a PCIE register
@@ -863,7 +1021,7 @@ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf,
* The offset being sought changes which wave that the status data
* will be returned for. The bits are used as follows:
*
- * Bits 0..6: Byte offset into data
+ * Bits 0..6: Byte offset into data
* Bits 7..14: SE selector
* Bits 15..22: SH/SA selector
* Bits 23..30: CU/{WGP+SIMD} selector
@@ -907,13 +1065,13 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf,
/* switch to the specific se/sh/cu */
mutex_lock(&adev->grbm_idx_mutex);
- amdgpu_gfx_select_se_sh(adev, se, sh, cu);
+ amdgpu_gfx_select_se_sh(adev, se, sh, cu, 0);
x = 0;
if (adev->gfx.funcs->read_wave_data)
- adev->gfx.funcs->read_wave_data(adev, simd, wave, data, &x);
+ adev->gfx.funcs->read_wave_data(adev, 0, simd, wave, data, &x);
- amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+ amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0);
mutex_unlock(&adev->grbm_idx_mutex);
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
@@ -1001,17 +1159,17 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf,
/* switch to the specific se/sh/cu */
mutex_lock(&adev->grbm_idx_mutex);
- amdgpu_gfx_select_se_sh(adev, se, sh, cu);
+ amdgpu_gfx_select_se_sh(adev, se, sh, cu, 0);
if (bank == 0) {
if (adev->gfx.funcs->read_wave_vgprs)
- adev->gfx.funcs->read_wave_vgprs(adev, simd, wave, thread, offset, size>>2, data);
+ adev->gfx.funcs->read_wave_vgprs(adev, 0, simd, wave, thread, offset, size>>2, data);
} else {
if (adev->gfx.funcs->read_wave_sgprs)
- adev->gfx.funcs->read_wave_sgprs(adev, simd, wave, offset, size>>2, data);
+ adev->gfx.funcs->read_wave_sgprs(adev, 0, simd, wave, offset, size>>2, data);
}
- amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+ amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0);
mutex_unlock(&adev->grbm_idx_mutex);
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
@@ -1339,6 +1497,15 @@ static const struct file_operations amdgpu_debugfs_regs2_fops = {
.llseek = default_llseek
};
+static const struct file_operations amdgpu_debugfs_gprwave_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = amdgpu_debugfs_gprwave_ioctl,
+ .read = amdgpu_debugfs_gprwave_read,
+ .open = amdgpu_debugfs_gprwave_open,
+ .release = amdgpu_debugfs_gprwave_release,
+ .llseek = default_llseek
+};
+
static const struct file_operations amdgpu_debugfs_regs_fops = {
.owner = THIS_MODULE,
.read = amdgpu_debugfs_regs_read,
@@ -1416,6 +1583,7 @@ static const struct file_operations amdgpu_debugfs_gfxoff_residency_fops = {
static const struct file_operations *debugfs_regs[] = {
&amdgpu_debugfs_regs_fops,
&amdgpu_debugfs_regs2_fops,
+ &amdgpu_debugfs_gprwave_fops,
&amdgpu_debugfs_regs_didt_fops,
&amdgpu_debugfs_regs_pcie_fops,
&amdgpu_debugfs_regs_smc_fops,
@@ -1429,9 +1597,10 @@ static const struct file_operations *debugfs_regs[] = {
&amdgpu_debugfs_gfxoff_residency_fops,
};
-static const char *debugfs_regs_names[] = {
+static const char * const debugfs_regs_names[] = {
"amdgpu_regs",
"amdgpu_regs2",
+ "amdgpu_gprwave",
"amdgpu_regs_didt",
"amdgpu_regs_pcie",
"amdgpu_regs_smc",
@@ -1447,7 +1616,7 @@ static const char *debugfs_regs_names[] = {
/**
* amdgpu_debugfs_regs_init - Initialize debugfs entries that provide
- * register access.
+ * register access.
*
* @adev: The device to attach the debugfs entries to
*/
@@ -1459,7 +1628,7 @@ int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) {
ent = debugfs_create_file(debugfs_regs_names[i],
- S_IFREG | S_IRUGO, root,
+ S_IFREG | 0444, root,
adev, debugfs_regs[i]);
if (!i && !IS_ERR_OR_NULL(ent))
i_size_write(ent->d_inode, adev->rmmio_size);
@@ -1470,7 +1639,7 @@ int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused)
{
- struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
+ struct amdgpu_device *adev = m->private;
struct drm_device *dev = adev_to_drm(adev);
int r = 0, i;
@@ -1494,12 +1663,12 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused)
kthread_park(ring->sched.thread);
}
- seq_printf(m, "run ib test:\n");
+ seq_puts(m, "run ib test:\n");
r = amdgpu_ib_ring_tests(adev);
if (r)
seq_printf(m, "ib ring tests failed (%d).\n", r);
else
- seq_printf(m, "ib ring tests passed.\n");
+ seq_puts(m, "ib ring tests passed.\n");
/* go on the scheduler */
for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
@@ -1581,7 +1750,7 @@ static int amdgpu_debugfs_benchmark(void *data, u64 val)
static int amdgpu_debugfs_vm_info_show(struct seq_file *m, void *unused)
{
- struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
+ struct amdgpu_device *adev = m->private;
struct drm_device *dev = adev_to_drm(adev);
struct drm_file *file;
int r;
@@ -1978,7 +2147,7 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
amdgpu_debugfs_ring_init(adev, ring);
}
- for ( i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
if (!amdgpu_vcnfw_log)
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 5c7d40873ee2..e25f085ee886 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -707,6 +707,48 @@ u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev,
return r;
}
+u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev,
+ u64 reg_addr)
+{
+ unsigned long flags, pcie_index, pcie_index_hi, pcie_data;
+ u32 r;
+ void __iomem *pcie_index_offset;
+ void __iomem *pcie_index_hi_offset;
+ void __iomem *pcie_data_offset;
+
+ pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
+ pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
+ if (adev->nbio.funcs->get_pcie_index_hi_offset)
+ pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);
+ else
+ pcie_index_hi = 0;
+
+ spin_lock_irqsave(&adev->pcie_idx_lock, flags);
+ pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
+ pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
+ if (pcie_index_hi != 0)
+ pcie_index_hi_offset = (void __iomem *)adev->rmmio +
+ pcie_index_hi * 4;
+
+ writel(reg_addr, pcie_index_offset);
+ readl(pcie_index_offset);
+ if (pcie_index_hi != 0) {
+ writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
+ readl(pcie_index_hi_offset);
+ }
+ r = readl(pcie_data_offset);
+
+ /* clear the high bits */
+ if (pcie_index_hi != 0) {
+ writel(0, pcie_index_hi_offset);
+ readl(pcie_index_hi_offset);
+ }
+
+ spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
+
+ return r;
+}
+
/**
* amdgpu_device_indirect_rreg64 - read a 64bits indirect register
*
@@ -747,8 +789,6 @@ u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev,
* amdgpu_device_indirect_wreg - write an indirect register address
*
* @adev: amdgpu_device pointer
- * @pcie_index: mmio register offset
- * @pcie_data: mmio register offset
* @reg_addr: indirect register offset
* @reg_data: indirect register data
*
@@ -774,12 +814,50 @@ void amdgpu_device_indirect_wreg(struct amdgpu_device *adev,
spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
}
+void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev,
+ u64 reg_addr, u32 reg_data)
+{
+ unsigned long flags, pcie_index, pcie_index_hi, pcie_data;
+ void __iomem *pcie_index_offset;
+ void __iomem *pcie_index_hi_offset;
+ void __iomem *pcie_data_offset;
+
+ pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
+ pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
+ if (adev->nbio.funcs->get_pcie_index_hi_offset)
+ pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);
+ else
+ pcie_index_hi = 0;
+
+ spin_lock_irqsave(&adev->pcie_idx_lock, flags);
+ pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
+ pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
+ if (pcie_index_hi != 0)
+ pcie_index_hi_offset = (void __iomem *)adev->rmmio +
+ pcie_index_hi * 4;
+
+ writel(reg_addr, pcie_index_offset);
+ readl(pcie_index_offset);
+ if (pcie_index_hi != 0) {
+ writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
+ readl(pcie_index_hi_offset);
+ }
+ writel(reg_data, pcie_data_offset);
+ readl(pcie_data_offset);
+
+ /* clear the high bits */
+ if (pcie_index_hi != 0) {
+ writel(0, pcie_index_hi_offset);
+ readl(pcie_index_hi_offset);
+ }
+
+ spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
+}
+
/**
* amdgpu_device_indirect_wreg64 - write a 64bits indirect register address
*
* @adev: amdgpu_device pointer
- * @pcie_index: mmio register offset
- * @pcie_data: mmio register offset
* @reg_addr: indirect register offset
* @reg_data: indirect register data
*
@@ -840,6 +918,13 @@ static uint32_t amdgpu_invalid_rreg(struct amdgpu_device *adev, uint32_t reg)
return 0;
}
+static uint32_t amdgpu_invalid_rreg_ext(struct amdgpu_device *adev, uint64_t reg)
+{
+ DRM_ERROR("Invalid callback to read register 0x%llX\n", reg);
+ BUG();
+ return 0;
+}
+
/**
* amdgpu_invalid_wreg - dummy reg write function
*
@@ -857,6 +942,13 @@ static void amdgpu_invalid_wreg(struct amdgpu_device *adev, uint32_t reg, uint32
BUG();
}
+static void amdgpu_invalid_wreg_ext(struct amdgpu_device *adev, uint64_t reg, uint32_t v)
+{
+ DRM_ERROR("Invalid callback to write register 0x%llX with 0x%08X\n",
+ reg, v);
+ BUG();
+}
+
/**
* amdgpu_invalid_rreg64 - dummy 64 bit reg read function
*
@@ -942,7 +1034,8 @@ static int amdgpu_device_asic_init(struct amdgpu_device *adev)
{
amdgpu_asic_pre_asic_init(adev);
- if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(11, 0, 0))
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3) ||
+ adev->ip_versions[GC_HWIP][0] >= IP_VERSION(11, 0, 0))
return amdgpu_atomfirmware_asic_init(adev, true);
else
return amdgpu_atom_asic_init(adev->mode_info.atom_context);
@@ -998,7 +1091,7 @@ void amdgpu_device_program_register_sequence(struct amdgpu_device *adev,
if (array_size % 3)
return;
- for (i = 0; i < array_size; i +=3) {
+ for (i = 0; i < array_size; i += 3) {
reg = registers[i + 0];
and_mask = registers[i + 1];
or_mask = registers[i + 2];
@@ -1090,7 +1183,8 @@ static int amdgpu_device_doorbell_init(struct amdgpu_device *adev)
* doorbells are in the first page. So with paging queue enabled,
* the max num_kernel_doorbells should + 1 page (0x400 in dword)
*/
- if (adev->asic_type >= CHIP_VEGA10)
+ if (adev->ip_versions[SDMA0_HWIP][0] >= IP_VERSION(4, 0, 0) &&
+ adev->ip_versions[SDMA0_HWIP][0] < IP_VERSION(4, 2, 0))
adev->doorbell.num_kernel_doorbells += 0x400;
}
@@ -1291,6 +1385,15 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
return 0;
}
+static bool amdgpu_device_read_bios(struct amdgpu_device *adev)
+{
+ if (hweight32(adev->aid_mask) && (adev->flags & AMD_IS_APU)) {
+ return false;
+ }
+
+ return true;
+}
+
/*
* GPU helpers function.
*/
@@ -1310,6 +1413,9 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev)
if (amdgpu_sriov_vf(adev))
return false;
+ if (!amdgpu_device_read_bios(adev))
+ return false;
+
if (amdgpu_passthrough(adev)) {
/* for FIJI: In whole GPU pass-through virtualization case, after VM reboot
* some old smc fw still need driver do vPost otherwise gpu hang, while
@@ -1547,7 +1653,7 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
dev_warn(adev->dev, "sched jobs (%d) must be at least 4\n",
amdgpu_sched_jobs);
amdgpu_sched_jobs = 4;
- } else if (!is_power_of_2(amdgpu_sched_jobs)){
+ } else if (!is_power_of_2(amdgpu_sched_jobs)) {
dev_warn(adev->dev, "sched jobs (%d) must be a power of 2\n",
amdgpu_sched_jobs);
amdgpu_sched_jobs = roundup_pow_of_two(amdgpu_sched_jobs);
@@ -2194,7 +2300,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
total = true;
for (i = 0; i < adev->num_ip_blocks; i++) {
if ((amdgpu_ip_block_mask & (1 << i)) == 0) {
- DRM_ERROR("disabled ip block: %d <%s>\n",
+ DRM_WARN("disabled ip block: %d <%s>\n",
i, adev->ip_blocks[i].version->funcs->name);
adev->ip_blocks[i].status.valid = false;
} else {
@@ -2220,14 +2326,16 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
return r;
/* Read BIOS */
- if (!amdgpu_get_bios(adev))
- return -EINVAL;
+ if (amdgpu_device_read_bios(adev)) {
+ if (!amdgpu_get_bios(adev))
+ return -EINVAL;
- r = amdgpu_atombios_init(adev);
- if (r) {
- dev_err(adev->dev, "amdgpu_atombios_init failed\n");
- amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_INIT_FAIL, 0, 0);
- return r;
+ r = amdgpu_atombios_init(adev);
+ if (r) {
+ dev_err(adev->dev, "amdgpu_atombios_init failed\n");
+ amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_INIT_FAIL, 0, 0);
+ return r;
+ }
}
/*get pf2vf msg info at it's earliest time*/
@@ -2376,6 +2484,8 @@ static int amdgpu_device_init_schedulers(struct amdgpu_device *adev)
}
}
+ amdgpu_xcp_update_partition_sched_list(adev);
+
return 0;
}
@@ -2533,8 +2643,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
goto init_failed;
/* Don't init kfd if whole hive need to be reset during init */
- if (!adev->gmc.xgmi.pending_reset)
+ if (!adev->gmc.xgmi.pending_reset) {
+ kgd2kfd_init_zone_device(adev);
amdgpu_amdkfd_device_init(adev);
+ }
amdgpu_fru_get_product_info(adev);
@@ -2759,8 +2871,9 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
DRM_ERROR("enable mgpu fan boost failed (%d).\n", r);
/* For passthrough configuration on arcturus and aldebaran, enable special handling SBR */
- if (amdgpu_passthrough(adev) && ((adev->asic_type == CHIP_ARCTURUS && adev->gmc.xgmi.num_physical_nodes > 1)||
- adev->asic_type == CHIP_ALDEBARAN ))
+ if (amdgpu_passthrough(adev) &&
+ ((adev->asic_type == CHIP_ARCTURUS && adev->gmc.xgmi.num_physical_nodes > 1) ||
+ adev->asic_type == CHIP_ALDEBARAN))
amdgpu_dpm_handle_passthrough_sbr(adev, true);
if (adev->gmc.xgmi.num_physical_nodes > 1) {
@@ -3089,7 +3202,7 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
}
adev->ip_blocks[i].status.hw = false;
/* handle putting the SMC in the appropriate state */
- if(!amdgpu_sriov_vf(adev)){
+ if (!amdgpu_sriov_vf(adev)) {
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
r = amdgpu_dpm_set_mp1_state(adev, adev->mp1_state);
if (r) {
@@ -3608,6 +3721,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
adev->smc_wreg = &amdgpu_invalid_wreg;
adev->pcie_rreg = &amdgpu_invalid_rreg;
adev->pcie_wreg = &amdgpu_invalid_wreg;
+ adev->pcie_rreg_ext = &amdgpu_invalid_rreg_ext;
+ adev->pcie_wreg_ext = &amdgpu_invalid_wreg_ext;
adev->pciep_rreg = &amdgpu_invalid_rreg;
adev->pciep_wreg = &amdgpu_invalid_wreg;
adev->pcie_rreg64 = &amdgpu_invalid_rreg64;
@@ -3633,6 +3748,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
mutex_init(&adev->srbm_mutex);
mutex_init(&adev->gfx.pipe_reserve_mutex);
mutex_init(&adev->gfx.gfx_off_mutex);
+ mutex_init(&adev->gfx.partition_mutex);
mutex_init(&adev->grbm_idx_mutex);
mutex_init(&adev->mn_lock);
mutex_init(&adev->virt.vf_errors.lock);
@@ -3708,8 +3824,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)adev->rmmio_base);
DRM_INFO("register mmio size: %u\n", (unsigned)adev->rmmio_size);
- amdgpu_device_get_pcie_info(adev);
-
if (amdgpu_mcbp)
DRM_INFO("MCBP is enabled\n");
@@ -3725,6 +3839,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
/* detect hw virtualization here */
amdgpu_detect_virtualization(adev);
+ amdgpu_device_get_pcie_info(adev);
+
r = amdgpu_device_get_job_timeout_settings(adev);
if (r) {
dev_err(adev->dev, "invalid lockup_timeout parameter syntax\n");
@@ -3753,21 +3869,24 @@ int amdgpu_device_init(struct amdgpu_device *adev,
}
/* enable PCIE atomic ops */
- if (amdgpu_sriov_vf(adev))
- adev->have_atomics_support = ((struct amd_sriov_msg_pf2vf_info *)
- adev->virt.fw_reserve.p_pf2vf)->pcie_atomic_ops_support_flags ==
- (PCI_EXP_DEVCAP2_ATOMIC_COMP32 | PCI_EXP_DEVCAP2_ATOMIC_COMP64);
+ if (amdgpu_sriov_vf(adev)) {
+ if (adev->virt.fw_reserve.p_pf2vf)
+ adev->have_atomics_support = ((struct amd_sriov_msg_pf2vf_info *)
+ adev->virt.fw_reserve.p_pf2vf)->pcie_atomic_ops_support_flags ==
+ (PCI_EXP_DEVCAP2_ATOMIC_COMP32 | PCI_EXP_DEVCAP2_ATOMIC_COMP64);
/* APUs w/ gfx9 onwards doesn't reply on PCIe atomics, rather it is a
* internal path natively support atomics, set have_atomics_support to true.
*/
- else if ((adev->flags & AMD_IS_APU) &&
- (adev->ip_versions[GC_HWIP][0] > IP_VERSION(9, 0, 0)))
+ } else if ((adev->flags & AMD_IS_APU) &&
+ (adev->ip_versions[GC_HWIP][0] > IP_VERSION(9, 0, 0))) {
adev->have_atomics_support = true;
- else
+ } else {
adev->have_atomics_support =
!pci_enable_atomic_ops_to_root(adev->pdev,
PCI_EXP_DEVCAP2_ATOMIC_COMP32 |
PCI_EXP_DEVCAP2_ATOMIC_COMP64);
+ }
+
if (!adev->have_atomics_support)
dev_info(adev->dev, "PCIE atomic ops is not supported\n");
@@ -3783,7 +3902,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
amdgpu_reset_init(adev);
/* detect if we are with an SRIOV vbios */
- amdgpu_device_detect_sriov_bios(adev);
+ if (adev->bios)
+ amdgpu_device_detect_sriov_bios(adev);
/* check if we need to reset the asic
* E.g., driver was not cleanly unloaded previously, etc.
@@ -3835,25 +3955,27 @@ int amdgpu_device_init(struct amdgpu_device *adev,
}
}
- if (adev->is_atom_fw) {
- /* Initialize clocks */
- r = amdgpu_atomfirmware_get_clock_info(adev);
- if (r) {
- dev_err(adev->dev, "amdgpu_atomfirmware_get_clock_info failed\n");
- amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0);
- goto failed;
- }
- } else {
- /* Initialize clocks */
- r = amdgpu_atombios_get_clock_info(adev);
- if (r) {
- dev_err(adev->dev, "amdgpu_atombios_get_clock_info failed\n");
- amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0);
- goto failed;
+ if (adev->bios) {
+ if (adev->is_atom_fw) {
+ /* Initialize clocks */
+ r = amdgpu_atomfirmware_get_clock_info(adev);
+ if (r) {
+ dev_err(adev->dev, "amdgpu_atomfirmware_get_clock_info failed\n");
+ amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0);
+ goto failed;
+ }
+ } else {
+ /* Initialize clocks */
+ r = amdgpu_atombios_get_clock_info(adev);
+ if (r) {
+ dev_err(adev->dev, "amdgpu_atombios_get_clock_info failed\n");
+ amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0);
+ goto failed;
+ }
+ /* init i2c buses */
+ if (!amdgpu_device_has_dc_support(adev))
+ amdgpu_atombios_i2c_init(adev);
}
- /* init i2c buses */
- if (!amdgpu_device_has_dc_support(adev))
- amdgpu_atombios_i2c_init(adev);
}
fence_driver_init:
@@ -4019,7 +4141,7 @@ static void amdgpu_device_unmap_mmio(struct amdgpu_device *adev)
adev->mman.aper_base_kaddr = NULL;
/* Memory manager related */
- if (!adev->gmc.xgmi.connected_to_cpu) {
+ if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) {
arch_phys_wc_del(adev->gmc.vram_mtrr);
arch_io_free_memtype_wc(adev->gmc.aper_base, adev->gmc.aper_size);
}
@@ -4049,7 +4171,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
/* disable all interrupts */
amdgpu_irq_disable_all(adev);
- if (adev->mode_info.mode_config_initialized){
+ if (adev->mode_info.mode_config_initialized) {
if (!drm_drv_uses_atomic_modeset(adev_to_drm(adev)))
drm_helper_force_disable_all(adev_to_drm(adev));
else
@@ -4714,42 +4836,42 @@ disabled:
int amdgpu_device_mode1_reset(struct amdgpu_device *adev)
{
- u32 i;
- int ret = 0;
+ u32 i;
+ int ret = 0;
- amdgpu_atombios_scratch_regs_engine_hung(adev, true);
+ amdgpu_atombios_scratch_regs_engine_hung(adev, true);
- dev_info(adev->dev, "GPU mode1 reset\n");
+ dev_info(adev->dev, "GPU mode1 reset\n");
- /* disable BM */
- pci_clear_master(adev->pdev);
+ /* disable BM */
+ pci_clear_master(adev->pdev);
- amdgpu_device_cache_pci_state(adev->pdev);
+ amdgpu_device_cache_pci_state(adev->pdev);
- if (amdgpu_dpm_is_mode1_reset_supported(adev)) {
- dev_info(adev->dev, "GPU smu mode1 reset\n");
- ret = amdgpu_dpm_mode1_reset(adev);
- } else {
- dev_info(adev->dev, "GPU psp mode1 reset\n");
- ret = psp_gpu_reset(adev);
- }
+ if (amdgpu_dpm_is_mode1_reset_supported(adev)) {
+ dev_info(adev->dev, "GPU smu mode1 reset\n");
+ ret = amdgpu_dpm_mode1_reset(adev);
+ } else {
+ dev_info(adev->dev, "GPU psp mode1 reset\n");
+ ret = psp_gpu_reset(adev);
+ }
- if (ret)
- dev_err(adev->dev, "GPU mode1 reset failed\n");
+ if (ret)
+ dev_err(adev->dev, "GPU mode1 reset failed\n");
- amdgpu_device_load_pci_state(adev->pdev);
+ amdgpu_device_load_pci_state(adev->pdev);
- /* wait for asic to come out of reset */
- for (i = 0; i < adev->usec_timeout; i++) {
- u32 memsize = adev->nbio.funcs->get_memsize(adev);
+ /* wait for asic to come out of reset */
+ for (i = 0; i < adev->usec_timeout; i++) {
+ u32 memsize = adev->nbio.funcs->get_memsize(adev);
- if (memsize != 0xffffffff)
- break;
- udelay(1);
- }
+ if (memsize != 0xffffffff)
+ break;
+ udelay(1);
+ }
- amdgpu_atombios_scratch_regs_engine_hung(adev, false);
- return ret;
+ amdgpu_atombios_scratch_regs_engine_hung(adev, false);
+ return ret;
}
int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
@@ -5478,7 +5600,7 @@ static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev)
adev->pm.pcie_mlw_mask = amdgpu_pcie_lane_cap;
/* covers APUs as well */
- if (pci_is_root_bus(adev->pdev->bus)) {
+ if (pci_is_root_bus(adev->pdev->bus) && !amdgpu_passthrough(adev)) {
if (adev->pm.pcie_gen_mask == 0)
adev->pm.pcie_gen_mask = AMDGPU_DEFAULT_PCIE_GEN_MASK;
if (adev->pm.pcie_mlw_mask == 0)
@@ -5959,6 +6081,7 @@ void amdgpu_device_halt(struct amdgpu_device *adev)
struct pci_dev *pdev = adev->pdev;
struct drm_device *ddev = adev_to_drm(adev);
+ amdgpu_xcp_dev_unplug(adev);
drm_dev_unplug(ddev);
amdgpu_irq_disable_all(adev);
@@ -6079,3 +6202,31 @@ bool amdgpu_device_has_display_hardware(struct amdgpu_device *adev)
return true;
}
}
+
+uint32_t amdgpu_device_wait_on_rreg(struct amdgpu_device *adev,
+ uint32_t inst, uint32_t reg_addr, char reg_name[],
+ uint32_t expected_value, uint32_t mask)
+{
+ uint32_t ret = 0;
+ uint32_t old_ = 0;
+ uint32_t tmp_ = RREG32(reg_addr);
+ uint32_t loop = adev->usec_timeout;
+
+ while ((tmp_ & (mask)) != (expected_value)) {
+ if (old_ != tmp_) {
+ loop = adev->usec_timeout;
+ old_ = tmp_;
+ } else
+ udelay(1);
+ tmp_ = RREG32(reg_addr);
+ loop--;
+ if (!loop) {
+ DRM_WARN("Register(%d) [%s] failed to reach value 0x%08x != 0x%08xn",
+ inst, reg_name, (uint32_t)expected_value,
+ (uint32_t)(tmp_ & (mask)));
+ ret = -ETIMEDOUT;
+ break;
+ }
+ }
+ return ret;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index 0ecce0b92b82..8e1cfc87122d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -30,6 +30,7 @@
#include "soc15.h"
#include "gfx_v9_0.h"
+#include "gfx_v9_4_3.h"
#include "gmc_v9_0.h"
#include "df_v1_7.h"
#include "df_v3_6.h"
@@ -76,12 +77,15 @@
#include "jpeg_v3_0.h"
#include "vcn_v4_0.h"
#include "jpeg_v4_0.h"
+#include "vcn_v4_0_3.h"
+#include "jpeg_v4_0_3.h"
#include "amdgpu_vkms.h"
#include "mes_v10_1.h"
#include "mes_v11_0.h"
#include "smuio_v11_0.h"
#include "smuio_v11_0_6.h"
#include "smuio_v13_0.h"
+#include "smuio_v13_0_3.h"
#include "smuio_v13_0_6.h"
#define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin"
@@ -200,14 +204,44 @@ static int hw_id_map[MAX_HWIP] = {
[PCIE_HWIP] = PCIE_HWID,
};
-static int amdgpu_discovery_read_binary_from_vram(struct amdgpu_device *adev, uint8_t *binary)
+static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev, uint8_t *binary)
+{
+ u64 tmr_offset, tmr_size, pos;
+ void *discv_regn;
+ int ret;
+
+ ret = amdgpu_acpi_get_tmr_info(adev, &tmr_offset, &tmr_size);
+ if (ret)
+ return ret;
+
+ pos = tmr_offset + tmr_size - DISCOVERY_TMR_OFFSET;
+
+ /* This region is read-only and reserved from system use */
+ discv_regn = memremap(pos, adev->mman.discovery_tmr_size, MEMREMAP_WC);
+ if (discv_regn) {
+ memcpy(binary, discv_regn, adev->mman.discovery_tmr_size);
+ memunmap(discv_regn);
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
+ uint8_t *binary)
{
uint64_t vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
- uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET;
+ int ret = 0;
- amdgpu_device_vram_access(adev, pos, (uint32_t *)binary,
- adev->mman.discovery_tmr_size, false);
- return 0;
+ if (vram_size) {
+ uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET;
+ amdgpu_device_vram_access(adev, pos, (uint32_t *)binary,
+ adev->mman.discovery_tmr_size, false);
+ } else {
+ ret = amdgpu_discovery_read_binary_from_sysmem(adev, binary);
+ }
+
+ return ret;
}
static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev, uint8_t *binary)
@@ -280,6 +314,7 @@ static void amdgpu_discovery_harvest_config_quirk(struct amdgpu_device *adev)
case 0xCF:
case 0xDF:
adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1;
+ adev->vcn.inst_mask &= ~AMDGPU_VCN_HARVEST_VCN1;
break;
default:
break;
@@ -301,33 +336,30 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
if (!adev->mman.discovery_bin)
return -ENOMEM;
- r = amdgpu_discovery_read_binary_from_vram(adev, adev->mman.discovery_bin);
- if (r) {
- dev_err(adev->dev, "failed to read ip discovery binary from vram\n");
- r = -EINVAL;
- goto out;
- }
-
- if (!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin) || amdgpu_discovery == 2) {
- /* ignore the discovery binary from vram if discovery=2 in kernel module parameter */
- if (amdgpu_discovery == 2)
- dev_info(adev->dev,"force read ip discovery binary from file");
- else
- dev_warn(adev->dev, "get invalid ip discovery binary signature from vram\n");
-
- /* retry read ip discovery binary from file */
+ /* Read from file if it is the preferred option */
+ if (amdgpu_discovery == 2) {
+ dev_info(adev->dev, "use ip discovery information from file");
r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin);
+
if (r) {
dev_err(adev->dev, "failed to read ip discovery binary from file\n");
r = -EINVAL;
goto out;
}
- /* check the ip discovery binary signature */
- if(!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) {
- dev_warn(adev->dev, "get invalid ip discovery binary signature from file\n");
- r = -EINVAL;
+
+ } else {
+ r = amdgpu_discovery_read_binary_from_mem(
+ adev, adev->mman.discovery_bin);
+ if (r)
goto out;
- }
+ }
+
+ /* check the ip discovery binary signature */
+ if (!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) {
+ dev_err(adev->dev,
+ "get invalid ip discovery binary signature\n");
+ r = -EINVAL;
+ goto out;
}
bhdr = (struct binary_header *)adev->mman.discovery_bin;
@@ -471,11 +503,11 @@ void amdgpu_discovery_fini(struct amdgpu_device *adev)
adev->mman.discovery_bin = NULL;
}
-static int amdgpu_discovery_validate_ip(const struct ip *ip)
+static int amdgpu_discovery_validate_ip(const struct ip_v4 *ip)
{
- if (ip->number_instance >= HWIP_MAX_INSTANCE) {
- DRM_ERROR("Unexpected number_instance (%d) from ip discovery blob\n",
- ip->number_instance);
+ if (ip->instance_number >= HWIP_MAX_INSTANCE) {
+ DRM_ERROR("Unexpected instance_number (%d) from ip discovery blob\n",
+ ip->instance_number);
return -EINVAL;
}
if (le16_to_cpu(ip->hw_id) >= HW_ID_MAX) {
@@ -493,7 +525,7 @@ static void amdgpu_discovery_read_harvest_bit_per_ip(struct amdgpu_device *adev,
struct binary_header *bhdr;
struct ip_discovery_header *ihdr;
struct die_header *dhdr;
- struct ip *ip;
+ struct ip_v4 *ip;
uint16_t die_offset, ip_offset, num_dies, num_ips;
int i, j;
@@ -510,29 +542,41 @@ static void amdgpu_discovery_read_harvest_bit_per_ip(struct amdgpu_device *adev,
ip_offset = die_offset + sizeof(*dhdr);
for (j = 0; j < num_ips; j++) {
- ip = (struct ip *)(adev->mman.discovery_bin + ip_offset);
+ ip = (struct ip_v4 *)(adev->mman.discovery_bin + ip_offset);
if (amdgpu_discovery_validate_ip(ip))
goto next_ip;
- if (le16_to_cpu(ip->harvest) == 1) {
+ if (le16_to_cpu(ip->variant) == 1) {
switch (le16_to_cpu(ip->hw_id)) {
case VCN_HWID:
(*vcn_harvest_count)++;
- if (ip->number_instance == 0)
+ if (ip->instance_number == 0) {
adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN0;
- else
+ adev->vcn.inst_mask &=
+ ~AMDGPU_VCN_HARVEST_VCN0;
+ adev->jpeg.inst_mask &=
+ ~AMDGPU_VCN_HARVEST_VCN0;
+ } else {
adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1;
+ adev->vcn.inst_mask &=
+ ~AMDGPU_VCN_HARVEST_VCN1;
+ adev->jpeg.inst_mask &=
+ ~AMDGPU_VCN_HARVEST_VCN1;
+ }
break;
case DMU_HWID:
adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK;
break;
default:
break;
- }
- }
+ }
+ }
next_ip:
- ip_offset += struct_size(ip, base_address, ip->num_base_address);
+ if (ihdr->base_addr_64_bit)
+ ip_offset += struct_size(ip, base_address_64, ip->num_base_address);
+ else
+ ip_offset += struct_size(ip, base_address, ip->num_base_address);
}
}
}
@@ -564,10 +608,15 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev,
switch (le16_to_cpu(harvest_info->list[i].hw_id)) {
case VCN_HWID:
(*vcn_harvest_count)++;
- if (harvest_info->list[i].number_instance == 0)
- adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN0;
- else
- adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1;
+ adev->vcn.harvest_config |=
+ (1 << harvest_info->list[i].number_instance);
+ adev->jpeg.harvest_config |=
+ (1 << harvest_info->list[i].number_instance);
+
+ adev->vcn.inst_mask &=
+ ~(1U << harvest_info->list[i].number_instance);
+ adev->jpeg.inst_mask &=
+ ~(1U << harvest_info->list[i].number_instance);
break;
case DMU_HWID:
adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK;
@@ -577,6 +626,14 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev,
1 << (le16_to_cpu(harvest_info->list[i].number_instance));
(*umc_harvest_count)++;
break;
+ case GC_HWID:
+ adev->gfx.xcc_mask &=
+ ~(1U << harvest_info->list[i].number_instance);
+ break;
+ case SDMA0_HWID:
+ adev->sdma.sdma_mask &=
+ ~(1U << harvest_info->list[i].number_instance);
+ break;
default:
break;
}
@@ -836,9 +893,40 @@ static void ip_disc_release(struct kobject *kobj)
kfree(ip_top);
}
+static uint8_t amdgpu_discovery_get_harvest_info(struct amdgpu_device *adev,
+ uint16_t hw_id, uint8_t inst)
+{
+ uint8_t harvest = 0;
+
+ /* Until a uniform way is figured, get mask based on hwid */
+ switch (hw_id) {
+ case VCN_HWID:
+ harvest = ((1 << inst) & adev->vcn.inst_mask) == 0;
+ break;
+ case DMU_HWID:
+ if (adev->harvest_ip_mask & AMD_HARVEST_IP_DMU_MASK)
+ harvest = 0x1;
+ break;
+ case UMC_HWID:
+ /* TODO: It needs another parsing; for now, ignore.*/
+ break;
+ case GC_HWID:
+ harvest = ((1 << inst) & adev->gfx.xcc_mask) == 0;
+ break;
+ case SDMA0_HWID:
+ harvest = ((1 << inst) & adev->sdma.sdma_mask) == 0;
+ break;
+ default:
+ break;
+ }
+
+ return harvest;
+}
+
static int amdgpu_discovery_sysfs_ips(struct amdgpu_device *adev,
struct ip_die_entry *ip_die_entry,
- const size_t _ip_offset, const int num_ips)
+ const size_t _ip_offset, const int num_ips,
+ bool reg_base_64)
{
int ii, jj, kk, res;
@@ -852,10 +940,10 @@ static int amdgpu_discovery_sysfs_ips(struct amdgpu_device *adev,
size_t ip_offset = _ip_offset;
for (jj = 0; jj < num_ips; jj++) {
- struct ip *ip;
+ struct ip_v4 *ip;
struct ip_hw_instance *ip_hw_instance;
- ip = (struct ip *)(adev->mman.discovery_bin + ip_offset);
+ ip = (struct ip_v4 *)(adev->mman.discovery_bin + ip_offset);
if (amdgpu_discovery_validate_ip(ip) ||
le16_to_cpu(ip->hw_id) != ii)
goto next_ip;
@@ -903,22 +991,35 @@ static int amdgpu_discovery_sysfs_ips(struct amdgpu_device *adev,
return -ENOMEM;
}
ip_hw_instance->hw_id = le16_to_cpu(ip->hw_id); /* == ii */
- ip_hw_instance->num_instance = ip->number_instance;
+ ip_hw_instance->num_instance = ip->instance_number;
ip_hw_instance->major = ip->major;
ip_hw_instance->minor = ip->minor;
ip_hw_instance->revision = ip->revision;
- ip_hw_instance->harvest = ip->harvest;
+ ip_hw_instance->harvest =
+ amdgpu_discovery_get_harvest_info(
+ adev, ip_hw_instance->hw_id,
+ ip_hw_instance->num_instance);
ip_hw_instance->num_base_addresses = ip->num_base_address;
- for (kk = 0; kk < ip_hw_instance->num_base_addresses; kk++)
- ip_hw_instance->base_addr[kk] = ip->base_address[kk];
+ for (kk = 0; kk < ip_hw_instance->num_base_addresses; kk++) {
+ if (reg_base_64)
+ ip_hw_instance->base_addr[kk] =
+ lower_32_bits(le64_to_cpu(ip->base_address_64[kk])) & 0x3FFFFFFF;
+ else
+ ip_hw_instance->base_addr[kk] = ip->base_address[kk];
+ }
kobject_init(&ip_hw_instance->kobj, &ip_hw_instance_ktype);
ip_hw_instance->kobj.kset = &ip_hw_id->hw_id_kset;
res = kobject_add(&ip_hw_instance->kobj, NULL,
"%d", ip_hw_instance->num_instance);
next_ip:
- ip_offset += struct_size(ip, base_address, ip->num_base_address);
+ if (reg_base_64)
+ ip_offset += struct_size(ip, base_address_64,
+ ip->num_base_address);
+ else
+ ip_offset += struct_size(ip, base_address,
+ ip->num_base_address);
}
}
@@ -972,7 +1073,7 @@ static int amdgpu_discovery_sysfs_recurse(struct amdgpu_device *adev)
return res;
}
- amdgpu_discovery_sysfs_ips(adev, ip_die_entry, ip_offset, num_ips);
+ amdgpu_discovery_sysfs_ips(adev, ip_die_entry, ip_offset, num_ips, !!ihdr->base_addr_64_bit);
}
return 0;
@@ -983,6 +1084,9 @@ static int amdgpu_discovery_sysfs_init(struct amdgpu_device *adev)
struct kset *die_kset;
int res, ii;
+ if (!adev->mman.discovery_bin)
+ return -EINVAL;
+
adev->ip_top = kzalloc(sizeof(*adev->ip_top), GFP_KERNEL);
if (!adev->ip_top)
return -ENOMEM;
@@ -1082,7 +1186,7 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
struct binary_header *bhdr;
struct ip_discovery_header *ihdr;
struct die_header *dhdr;
- struct ip *ip;
+ struct ip_v4 *ip;
uint16_t die_offset;
uint16_t ip_offset;
uint16_t num_dies;
@@ -1098,6 +1202,10 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
return r;
}
+ adev->gfx.xcc_mask = 0;
+ adev->sdma.sdma_mask = 0;
+ adev->vcn.inst_mask = 0;
+ adev->jpeg.inst_mask = 0;
bhdr = (struct binary_header *)adev->mman.discovery_bin;
ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin +
le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset));
@@ -1121,7 +1229,7 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
le16_to_cpu(dhdr->die_id), num_ips);
for (j = 0; j < num_ips; j++) {
- ip = (struct ip *)(adev->mman.discovery_bin + ip_offset);
+ ip = (struct ip_v4 *)(adev->mman.discovery_bin + ip_offset);
if (amdgpu_discovery_validate_ip(ip))
goto next_ip;
@@ -1131,7 +1239,7 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
DRM_DEBUG("%s(%d) #%d v%d.%d.%d:\n",
hw_id_names[le16_to_cpu(ip->hw_id)],
le16_to_cpu(ip->hw_id),
- ip->number_instance,
+ ip->instance_number,
ip->major, ip->minor,
ip->revision);
@@ -1145,23 +1253,33 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
adev->vcn.vcn_config[adev->vcn.num_vcn_inst] =
ip->revision & 0xc0;
ip->revision &= ~0xc0;
- if (adev->vcn.num_vcn_inst < AMDGPU_MAX_VCN_INSTANCES)
+ if (adev->vcn.num_vcn_inst <
+ AMDGPU_MAX_VCN_INSTANCES) {
adev->vcn.num_vcn_inst++;
- else
+ adev->vcn.inst_mask |=
+ (1U << ip->instance_number);
+ adev->jpeg.inst_mask |=
+ (1U << ip->instance_number);
+ } else {
dev_err(adev->dev, "Too many VCN instances: %d vs %d\n",
adev->vcn.num_vcn_inst + 1,
AMDGPU_MAX_VCN_INSTANCES);
+ }
}
if (le16_to_cpu(ip->hw_id) == SDMA0_HWID ||
le16_to_cpu(ip->hw_id) == SDMA1_HWID ||
le16_to_cpu(ip->hw_id) == SDMA2_HWID ||
le16_to_cpu(ip->hw_id) == SDMA3_HWID) {
- if (adev->sdma.num_instances < AMDGPU_MAX_SDMA_INSTANCES)
+ if (adev->sdma.num_instances <
+ AMDGPU_MAX_SDMA_INSTANCES) {
adev->sdma.num_instances++;
- else
+ adev->sdma.sdma_mask |=
+ (1U << ip->instance_number);
+ } else {
dev_err(adev->dev, "Too many SDMA instances: %d vs %d\n",
adev->sdma.num_instances + 1,
AMDGPU_MAX_SDMA_INSTANCES);
+ }
}
if (le16_to_cpu(ip->hw_id) == UMC_HWID) {
@@ -1169,20 +1287,38 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
adev->umc.node_inst_num++;
}
+ if (le16_to_cpu(ip->hw_id) == GC_HWID)
+ adev->gfx.xcc_mask |=
+ (1U << ip->instance_number);
+
for (k = 0; k < num_base_address; k++) {
/*
* convert the endianness of base addresses in place,
* so that we don't need to convert them when accessing adev->reg_offset.
*/
- ip->base_address[k] = le32_to_cpu(ip->base_address[k]);
+ if (ihdr->base_addr_64_bit)
+ /* Truncate the 64bit base address from ip discovery
+ * and only store lower 32bit ip base in reg_offset[].
+ * Bits > 32 follows ASIC specific format, thus just
+ * discard them and handle it within specific ASIC.
+ * By this way reg_offset[] and related helpers can
+ * stay unchanged.
+ * The base address is in dwords, thus clear the
+ * highest 2 bits to store.
+ */
+ ip->base_address[k] =
+ lower_32_bits(le64_to_cpu(ip->base_address_64[k])) & 0x3FFFFFFF;
+ else
+ ip->base_address[k] = le32_to_cpu(ip->base_address[k]);
DRM_DEBUG("\t0x%08x\n", ip->base_address[k]);
}
for (hw_ip = 0; hw_ip < MAX_HWIP; hw_ip++) {
- if (hw_id_map[hw_ip] == le16_to_cpu(ip->hw_id)) {
+ if (hw_id_map[hw_ip] == le16_to_cpu(ip->hw_id) &&
+ hw_id_map[hw_ip] != 0) {
DRM_DEBUG("set register base offset for %s\n",
hw_id_names[le16_to_cpu(ip->hw_id)]);
- adev->reg_offset[hw_ip][ip->number_instance] =
+ adev->reg_offset[hw_ip][ip->instance_number] =
ip->base_address;
/* Instance support is somewhat inconsistent.
* SDMA is a good example. Sienna cichlid has 4 total
@@ -1193,69 +1329,22 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
* example. On most chips there are multiple instances
* with the same HWID.
*/
- adev->ip_versions[hw_ip][ip->number_instance] =
+ adev->ip_versions[hw_ip][ip->instance_number] =
IP_VERSION(ip->major, ip->minor, ip->revision);
}
}
next_ip:
- ip_offset += struct_size(ip, base_address, ip->num_base_address);
+ if (ihdr->base_addr_64_bit)
+ ip_offset += struct_size(ip, base_address_64, ip->num_base_address);
+ else
+ ip_offset += struct_size(ip, base_address, ip->num_base_address);
}
}
- amdgpu_discovery_sysfs_init(adev);
-
return 0;
}
-int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int number_instance,
- int *major, int *minor, int *revision)
-{
- struct binary_header *bhdr;
- struct ip_discovery_header *ihdr;
- struct die_header *dhdr;
- struct ip *ip;
- uint16_t die_offset;
- uint16_t ip_offset;
- uint16_t num_dies;
- uint16_t num_ips;
- int i, j;
-
- if (!adev->mman.discovery_bin) {
- DRM_ERROR("ip discovery uninitialized\n");
- return -EINVAL;
- }
-
- bhdr = (struct binary_header *)adev->mman.discovery_bin;
- ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin +
- le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset));
- num_dies = le16_to_cpu(ihdr->num_dies);
-
- for (i = 0; i < num_dies; i++) {
- die_offset = le16_to_cpu(ihdr->die_info[i].die_offset);
- dhdr = (struct die_header *)(adev->mman.discovery_bin + die_offset);
- num_ips = le16_to_cpu(dhdr->num_ips);
- ip_offset = die_offset + sizeof(*dhdr);
-
- for (j = 0; j < num_ips; j++) {
- ip = (struct ip *)(adev->mman.discovery_bin + ip_offset);
-
- if ((le16_to_cpu(ip->hw_id) == hw_id) && (ip->number_instance == number_instance)) {
- if (major)
- *major = ip->major;
- if (minor)
- *minor = ip->minor;
- if (revision)
- *revision = ip->revision;
- return 0;
- }
- ip_offset += struct_size(ip, base_address, ip->num_base_address);
- }
- }
-
- return -EINVAL;
-}
-
static void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
{
int vcn_harvest_count = 0;
@@ -1266,7 +1355,8 @@ static void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
* so read harvest bit per IP data structure to set
* harvest configuration.
*/
- if (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 2, 0)) {
+ if (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 2, 0) &&
+ adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 3)) {
if ((adev->pdev->device == 0x731E &&
(adev->pdev->revision == 0xC6 ||
adev->pdev->revision == 0xC7)) ||
@@ -1425,6 +1515,7 @@ static int amdgpu_discovery_get_mall_info(struct amdgpu_device *adev)
mall_size += mall_size_per_umc;
}
adev->gmc.mall_size = mall_size;
+ adev->gmc.m_half_use = half_use;
break;
default:
dev_err(adev->dev,
@@ -1706,6 +1797,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 3):
case IP_VERSION(13, 0, 4):
case IP_VERSION(13, 0, 5):
+ case IP_VERSION(13, 0, 6):
case IP_VERSION(13, 0, 7):
case IP_VERSION(13, 0, 8):
case IP_VERSION(13, 0, 10):
@@ -1804,6 +1896,11 @@ static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(9, 4, 2):
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
break;
+ case IP_VERSION(9, 4, 3):
+ if (!amdgpu_exp_hw_support)
+ return -EINVAL;
+ amdgpu_device_ip_block_add(adev, &gfx_v9_4_3_ip_block);
+ break;
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 2):
case IP_VERSION(10, 1, 1):
@@ -1939,7 +2036,6 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(3, 1, 1):
case IP_VERSION(3, 1, 2):
case IP_VERSION(3, 0, 2):
- case IP_VERSION(3, 0, 192):
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
if (!amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
@@ -1952,7 +2048,11 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(4, 0, 4):
amdgpu_device_ip_block_add(adev, &vcn_v4_0_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v4_0_ip_block);
- return 0;
+ break;
+ case IP_VERSION(4, 0, 3):
+ amdgpu_device_ip_block_add(adev, &vcn_v4_0_3_ip_block);
+ amdgpu_device_ip_block_add(adev, &jpeg_v4_0_3_ip_block);
+ break;
default:
dev_err(adev->dev,
"Failed to add vcn/jpeg ip block(UVD_HWIP:0x%x)\n",
@@ -2000,6 +2100,17 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)
return 0;
}
+static void amdgpu_discovery_init_soc_config(struct amdgpu_device *adev)
+{
+ switch (adev->ip_versions[GC_HWIP][0]) {
+ case IP_VERSION(9, 4, 3):
+ aqua_vanjaram_init_soc_config(adev);
+ break;
+ default:
+ break;
+ }
+}
+
int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
{
int r;
@@ -2177,6 +2288,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
break;
}
+ amdgpu_discovery_init_soc_config(adev);
+ amdgpu_discovery_sysfs_init(adev);
+
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 2, 1):
@@ -2387,6 +2501,12 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 2):
adev->smuio.funcs = &smuio_v13_0_funcs;
break;
+ case IP_VERSION(13, 0, 3):
+ adev->smuio.funcs = &smuio_v13_0_3_funcs;
+ if (adev->smuio.funcs->get_pkg_type(adev) == AMDGPU_PKG_TYPE_APU) {
+ adev->flags |= AMD_IS_APU;
+ }
+ break;
case IP_VERSION(13, 0, 6):
case IP_VERSION(13, 0, 8):
adev->smuio.funcs = &smuio_v13_0_6_funcs;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
index 8563dd4a7dc2..3a2f347bd50d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
@@ -24,12 +24,10 @@
#ifndef __AMDGPU_DISCOVERY__
#define __AMDGPU_DISCOVERY__
-#define DISCOVERY_TMR_SIZE (4 << 10)
+#define DISCOVERY_TMR_SIZE (8 << 10)
#define DISCOVERY_TMR_OFFSET (64 << 10)
void amdgpu_discovery_fini(struct amdgpu_device *adev);
-int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int number_instance,
- int *major, int *minor, int *revision);
int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev);
#endif /* __AMDGPU_DISCOVERY__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index d60fe7eb5579..b702f499f5fb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -98,7 +98,7 @@ static void amdgpu_display_flip_callback(struct dma_fence *f,
static bool amdgpu_display_flip_handle_fence(struct amdgpu_flip_work *work,
struct dma_fence **f)
{
- struct dma_fence *fence= *f;
+ struct dma_fence *fence = *f;
if (fence == NULL)
return false;
@@ -1252,21 +1252,21 @@ const struct drm_mode_config_funcs amdgpu_mode_funcs = {
.fb_create = amdgpu_display_user_framebuffer_create,
};
-static const struct drm_prop_enum_list amdgpu_underscan_enum_list[] =
-{ { UNDERSCAN_OFF, "off" },
+static const struct drm_prop_enum_list amdgpu_underscan_enum_list[] = {
+ { UNDERSCAN_OFF, "off" },
{ UNDERSCAN_ON, "on" },
{ UNDERSCAN_AUTO, "auto" },
};
-static const struct drm_prop_enum_list amdgpu_audio_enum_list[] =
-{ { AMDGPU_AUDIO_DISABLE, "off" },
+static const struct drm_prop_enum_list amdgpu_audio_enum_list[] = {
+ { AMDGPU_AUDIO_DISABLE, "off" },
{ AMDGPU_AUDIO_ENABLE, "on" },
{ AMDGPU_AUDIO_AUTO, "auto" },
};
/* XXX support different dither options? spatial, temporal, both, etc. */
-static const struct drm_prop_enum_list amdgpu_dither_enum_list[] =
-{ { AMDGPU_FMT_DITHER_DISABLE, "off" },
+static const struct drm_prop_enum_list amdgpu_dither_enum_list[] = {
+ { AMDGPU_FMT_DITHER_DISABLE, "off" },
{ AMDGPU_FMT_DITHER_ENABLE, "on" },
};
@@ -1496,8 +1496,7 @@ int amdgpu_display_get_crtc_scanoutpos(struct drm_device *dev,
ret |= DRM_SCANOUTPOS_ACCURATE;
vbl_start = vbl & 0x1fff;
vbl_end = (vbl >> 16) & 0x1fff;
- }
- else {
+ } else {
/* No: Fake something reasonable which gives at least ok results. */
vbl_start = mode->crtc_vdisplay;
vbl_end = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 0c001bb8fc2b..12210598e5b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -149,7 +149,7 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
if (!bo->tbo.pin_count) {
/* move buffer into GTT or VRAM */
struct ttm_operation_ctx ctx = { false, false };
- unsigned domains = AMDGPU_GEM_DOMAIN_GTT;
+ unsigned int domains = AMDGPU_GEM_DOMAIN_GTT;
if (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM &&
attach->peer2peer) {
@@ -336,7 +336,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
ret = amdgpu_gem_object_create(adev, dma_buf->size, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_CPU, flags,
- ttm_bo_type_sg, resv, &gobj);
+ ttm_bo_type_sg, resv, &gobj, 0);
if (ret)
goto error;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell.h
index 8fd11497faba..f637574644c0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell.h
@@ -59,7 +59,7 @@ struct amdgpu_doorbell_index {
uint32_t gfx_ring1;
uint32_t gfx_userqueue_start;
uint32_t gfx_userqueue_end;
- uint32_t sdma_engine[8];
+ uint32_t sdma_engine[16];
uint32_t mes_ring0;
uint32_t mes_ring1;
uint32_t ih;
@@ -86,6 +86,8 @@ struct amdgpu_doorbell_index {
uint32_t max_assignment;
/* Per engine SDMA doorbell size in dword */
uint32_t sdma_doorbell_range;
+ /* Per xcc doorbell size for KIQ/KCQ */
+ uint32_t xcc_doorbell_range;
};
typedef enum _AMDGPU_DOORBELL_ASSIGNMENT
@@ -164,7 +166,15 @@ typedef enum _AMDGPU_VEGA20_DOORBELL_ASSIGNMENT
AMDGPU_VEGA20_DOORBELL64_FIRST_NON_CP = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE0,
AMDGPU_VEGA20_DOORBELL64_LAST_NON_CP = AMDGPU_VEGA20_DOORBELL64_VCE_RING6_7,
- AMDGPU_VEGA20_DOORBELL_MAX_ASSIGNMENT = 0x18F,
+ /* kiq/kcq from second XCD. Max 8 XCDs */
+ AMDGPU_VEGA20_DOORBELL_XCC1_KIQ_START = 0x190,
+ /* 8 compute rings per GC. Max to 0x1CE */
+ AMDGPU_VEGA20_DOORBELL_XCC1_MEC_RING0_START = 0x197,
+
+ /* AID1 SDMA: 0x1D0 ~ 0x1F7 */
+ AMDGPU_VEGA20_DOORBELL_AID1_sDMA_START = 0x1D0,
+
+ AMDGPU_VEGA20_DOORBELL_MAX_ASSIGNMENT = 0x1F7,
AMDGPU_VEGA20_DOORBELL_INVALID = 0xFFFF
} AMDGPU_VEGA20_DOORBELL_ASSIGNMENT;
@@ -301,6 +311,36 @@ typedef enum _AMDGPU_DOORBELL64_ASSIGNMENT
AMDGPU_DOORBELL64_INVALID = 0xFFFF
} AMDGPU_DOORBELL64_ASSIGNMENT;
+typedef enum _AMDGPU_DOORBELL_ASSIGNMENT_LAYOUT1 {
+ /* XCC0: 0x00 ~20, XCC1: 20 ~ 2F ... */
+
+ /* KIQ/HIQ/DIQ */
+ AMDGPU_DOORBELL_LAYOUT1_KIQ_START = 0x000,
+ AMDGPU_DOORBELL_LAYOUT1_HIQ = 0x001,
+ AMDGPU_DOORBELL_LAYOUT1_DIQ = 0x002,
+ /* Compute: 0x08 ~ 0x20 */
+ AMDGPU_DOORBELL_LAYOUT1_MEC_RING_START = 0x008,
+ AMDGPU_DOORBELL_LAYOUT1_MEC_RING_END = 0x00F,
+ AMDGPU_DOORBELL_LAYOUT1_USERQUEUE_START = 0x010,
+ AMDGPU_DOORBELL_LAYOUT1_USERQUEUE_END = 0x01F,
+ AMDGPU_DOORBELL_LAYOUT1_XCC_RANGE = 0x020,
+
+ /* SDMA: 0x100 ~ 0x19F */
+ AMDGPU_DOORBELL_LAYOUT1_sDMA_ENGINE_START = 0x100,
+ AMDGPU_DOORBELL_LAYOUT1_sDMA_ENGINE_END = 0x19F,
+ /* IH: 0x1A0 ~ 0x1AF */
+ AMDGPU_DOORBELL_LAYOUT1_IH = 0x1A0,
+ /* VCN: 0x1B0 ~ 0x1D4 */
+ AMDGPU_DOORBELL_LAYOUT1_VCN_START = 0x1B0,
+ AMDGPU_DOORBELL_LAYOUT1_VCN_END = 0x1D4,
+
+ AMDGPU_DOORBELL_LAYOUT1_FIRST_NON_CP = AMDGPU_DOORBELL_LAYOUT1_sDMA_ENGINE_START,
+ AMDGPU_DOORBELL_LAYOUT1_LAST_NON_CP = AMDGPU_DOORBELL_LAYOUT1_VCN_END,
+
+ AMDGPU_DOORBELL_LAYOUT1_MAX_ASSIGNMENT = 0x1D4,
+ AMDGPU_DOORBELL_LAYOUT1_INVALID = 0xFFFF
+} AMDGPU_DOORBELL_ASSIGNMENT_LAYOUT1;
+
u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index);
void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v);
u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 393b6fb7a71d..3b711babd4e2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -50,6 +50,7 @@
#include "amdgpu_ras.h"
#include "amdgpu_xgmi.h"
#include "amdgpu_reset.h"
+#include "../amdxcp/amdgpu_xcp_drv.h"
/*
* KMS wrapper.
@@ -110,9 +111,11 @@
* 3.52.0 - Add AMDGPU_IDS_FLAGS_CONFORMANT_TRUNC_COORD, add device_info fields:
* tcp_cache_size, num_sqc_per_wgp, sqc_data_cache_size, sqc_inst_cache_size,
* gl1c_cache_size, gl2c_cache_size, mall_size, enabled_rb_pipes_mask_hi
+ * 3.53.0 - Support for GFX11 CP GFX shadowing
+ * 3.54.0 - Add AMDGPU_CTX_QUERY2_FLAGS_RESET_IN_PROGRESS support
*/
#define KMS_DRIVER_MAJOR 3
-#define KMS_DRIVER_MINOR 52
+#define KMS_DRIVER_MINOR 54
#define KMS_DRIVER_PATCHLEVEL 0
unsigned int amdgpu_vram_limit = UINT_MAX;
@@ -150,7 +153,7 @@ uint amdgpu_pg_mask = 0xffffffff;
uint amdgpu_sdma_phase_quantum = 32;
char *amdgpu_disable_cu;
char *amdgpu_virtual_display;
-
+bool enforce_isolation;
/*
* OverDrive(bit 14) disabled by default
* GFX DCS(bit 19) disabled by default
@@ -191,6 +194,7 @@ int amdgpu_smartshift_bias;
int amdgpu_use_xgmi_p2p = 1;
int amdgpu_vcnfw_log;
int amdgpu_sg_display = -1; /* auto */
+int amdgpu_user_partt_mode = AMDGPU_AUTO_COMPUTE_PARTITION_MODE;
static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);
@@ -820,6 +824,13 @@ module_param_named(no_queue_eviction_on_vm_fault, amdgpu_no_queue_eviction_on_vm
#endif
/**
+ * DOC: mtype_local (int)
+ */
+int amdgpu_mtype_local;
+MODULE_PARM_DESC(mtype_local, "MTYPE for local memory (0 = MTYPE_RW (default), 1 = MTYPE_NC, 2 = MTYPE_CC)");
+module_param_named(mtype_local, amdgpu_mtype_local, int, 0444);
+
+/**
* DOC: pcie_p2p (bool)
* Enable PCIe P2P (requires large-BAR). Default value: true (on)
*/
@@ -948,6 +959,28 @@ MODULE_PARM_DESC(smu_pptable_id,
"specify pptable id to be used (-1 = auto(default) value, 0 = use pptable from vbios, > 0 = soft pptable id)");
module_param_named(smu_pptable_id, amdgpu_smu_pptable_id, int, 0444);
+/**
+ * DOC: partition_mode (int)
+ * Used to override the default SPX mode.
+ */
+MODULE_PARM_DESC(
+ user_partt_mode,
+ "specify partition mode to be used (-2 = AMDGPU_AUTO_COMPUTE_PARTITION_MODE(default value) \
+ 0 = AMDGPU_SPX_PARTITION_MODE, \
+ 1 = AMDGPU_DPX_PARTITION_MODE, \
+ 2 = AMDGPU_TPX_PARTITION_MODE, \
+ 3 = AMDGPU_QPX_PARTITION_MODE, \
+ 4 = AMDGPU_CPX_PARTITION_MODE)");
+module_param_named(user_partt_mode, amdgpu_user_partt_mode, uint, 0444);
+
+
+/**
+ * DOC: enforce_isolation (bool)
+ * enforce process isolation between graphics and compute via using the same reserved vmid.
+ */
+module_param(enforce_isolation, bool, 0444);
+MODULE_PARM_DESC(enforce_isolation, "enforce process isolation between graphics and compute . enforce_isolation = on");
+
/* These devices are not supported by amdgpu.
* They are supported by the mach64, r128, radeon drivers
*/
@@ -1661,7 +1694,7 @@ static const u16 amdgpu_unsupported_pciidlist[] = {
};
static const struct pci_device_id pciidlist[] = {
-#ifdef CONFIG_DRM_AMDGPU_SI
+#ifdef CONFIG_DRM_AMDGPU_SI
{0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x6784, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
{0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
@@ -2018,6 +2051,11 @@ static const struct pci_device_id pciidlist[] = {
.class_mask = 0xffffff,
.driver_data = CHIP_IP_DISCOVERY },
+ { PCI_DEVICE(0x1002, PCI_ANY_ID),
+ .class = PCI_CLASS_ACCELERATOR_PROCESSING << 8,
+ .class_mask = 0xffffff,
+ .driver_data = CHIP_IP_DISCOVERY },
+
{0, 0, 0}
};
@@ -2162,6 +2200,10 @@ retry_init:
goto err_pci;
}
+ ret = amdgpu_xcp_dev_register(adev, ent);
+ if (ret)
+ goto err_pci;
+
/*
* 1. don't init fbdev on hw without DCE
* 2. don't init fbdev if there are no connectors
@@ -2234,6 +2276,7 @@ amdgpu_pci_remove(struct pci_dev *pdev)
struct drm_device *dev = pci_get_drvdata(pdev);
struct amdgpu_device *adev = drm_to_adev(dev);
+ amdgpu_xcp_dev_unplug(adev);
drm_dev_unplug(dev);
if (adev->pm.rpm_mode != AMDGPU_RUNPM_NONE) {
@@ -2748,7 +2791,7 @@ static const struct file_operations amdgpu_driver_kms_fops = {
.compat_ioctl = amdgpu_kms_compat_ioctl,
#endif
#ifdef CONFIG_PROC_FS
- .show_fdinfo = amdgpu_show_fdinfo
+ .show_fdinfo = drm_show_fdinfo,
#endif
};
@@ -2803,6 +2846,36 @@ static const struct drm_driver amdgpu_kms_driver = {
.dumb_map_offset = amdgpu_mode_dumb_mmap,
.fops = &amdgpu_driver_kms_fops,
.release = &amdgpu_driver_release_kms,
+#ifdef CONFIG_PROC_FS
+ .show_fdinfo = amdgpu_show_fdinfo,
+#endif
+
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+ .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+ .gem_prime_import = amdgpu_gem_prime_import,
+ .gem_prime_mmap = drm_gem_prime_mmap,
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = KMS_DRIVER_MAJOR,
+ .minor = KMS_DRIVER_MINOR,
+ .patchlevel = KMS_DRIVER_PATCHLEVEL,
+};
+
+const struct drm_driver amdgpu_partition_driver = {
+ .driver_features =
+ DRIVER_GEM | DRIVER_RENDER | DRIVER_SYNCOBJ |
+ DRIVER_SYNCOBJ_TIMELINE,
+ .open = amdgpu_driver_open_kms,
+ .postclose = amdgpu_driver_postclose_kms,
+ .lastclose = amdgpu_driver_lastclose_kms,
+ .ioctls = amdgpu_ioctls_kms,
+ .num_ioctls = ARRAY_SIZE(amdgpu_ioctls_kms),
+ .dumb_create = amdgpu_mode_dumb_create,
+ .dumb_map_offset = amdgpu_mode_dumb_mmap,
+ .fops = &amdgpu_driver_kms_fops,
+ .release = &amdgpu_driver_release_kms,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
@@ -2884,9 +2957,11 @@ static void __exit amdgpu_exit(void)
amdgpu_amdkfd_fini();
pci_unregister_driver(&amdgpu_kms_pci_driver);
amdgpu_unregister_atpx_handler();
+ amdgpu_acpi_release();
amdgpu_sync_fini();
amdgpu_fence_slab_fini();
mmu_notifier_synchronize();
+ amdgpu_xcp_drv_release();
}
module_init(amdgpu_init);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.h
index 8178323e4bef..5bc2cb661af7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.h
@@ -42,6 +42,8 @@
#define DRIVER_DESC "AMD GPU"
#define DRIVER_DATE "20150101"
+extern const struct drm_driver amdgpu_partition_driver;
+
long amdgpu_drm_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c
index 27a782a9dc72..3aaeed2d3562 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c
@@ -70,6 +70,7 @@ void amdgpu_encoder_set_active_device(struct drm_encoder *encoder)
drm_for_each_connector_iter(connector, &iter) {
if (connector->encoder == encoder) {
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
+
amdgpu_encoder->active_device = amdgpu_encoder->devices & amdgpu_connector->devices;
DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n",
amdgpu_encoder->active_device, amdgpu_encoder->devices,
@@ -165,12 +166,12 @@ void amdgpu_panel_mode_fixup(struct drm_encoder *encoder,
{
struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
- unsigned hblank = native_mode->htotal - native_mode->hdisplay;
- unsigned vblank = native_mode->vtotal - native_mode->vdisplay;
- unsigned hover = native_mode->hsync_start - native_mode->hdisplay;
- unsigned vover = native_mode->vsync_start - native_mode->vdisplay;
- unsigned hsync_width = native_mode->hsync_end - native_mode->hsync_start;
- unsigned vsync_width = native_mode->vsync_end - native_mode->vsync_start;
+ unsigned int hblank = native_mode->htotal - native_mode->hdisplay;
+ unsigned int vblank = native_mode->vtotal - native_mode->vdisplay;
+ unsigned int hover = native_mode->hsync_start - native_mode->hdisplay;
+ unsigned int vover = native_mode->vsync_start - native_mode->vdisplay;
+ unsigned int hsync_width = native_mode->hsync_end - native_mode->hsync_start;
+ unsigned int vsync_width = native_mode->vsync_end - native_mode->vsync_start;
adjusted_mode->clock = native_mode->clock;
adjusted_mode->flags = native_mode->flags;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c
index c57252f004e8..13d7413d4ca3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c
@@ -53,9 +53,8 @@ static const char *amdgpu_ip_name[AMDGPU_HW_IP_NUM] = {
[AMDGPU_HW_IP_VCN_JPEG] = "jpeg",
};
-void amdgpu_show_fdinfo(struct seq_file *m, struct file *f)
+void amdgpu_show_fdinfo(struct drm_printer *p, struct drm_file *file)
{
- struct drm_file *file = f->private_data;
struct amdgpu_device *adev = drm_to_adev(file->minor->dev);
struct amdgpu_fpriv *fpriv = file->driver_priv;
struct amdgpu_vm *vm = &fpriv->vm;
@@ -87,31 +86,30 @@ void amdgpu_show_fdinfo(struct seq_file *m, struct file *f)
* ******************************************************************
*/
- seq_printf(m, "pasid:\t%u\n", fpriv->vm.pasid);
- seq_printf(m, "drm-driver:\t%s\n", file->minor->dev->driver->name);
- seq_printf(m, "drm-pdev:\t%04x:%02x:%02x.%d\n", domain, bus, dev, fn);
- seq_printf(m, "drm-client-id:\t%Lu\n", vm->immediate.fence_context);
- seq_printf(m, "drm-memory-vram:\t%llu KiB\n", stats.vram/1024UL);
- seq_printf(m, "drm-memory-gtt: \t%llu KiB\n", stats.gtt/1024UL);
- seq_printf(m, "drm-memory-cpu: \t%llu KiB\n", stats.cpu/1024UL);
- seq_printf(m, "amd-memory-visible-vram:\t%llu KiB\n",
+ drm_printf(p, "pasid:\t%u\n", fpriv->vm.pasid);
+ drm_printf(p, "drm-driver:\t%s\n", file->minor->dev->driver->name);
+ drm_printf(p, "drm-pdev:\t%04x:%02x:%02x.%d\n", domain, bus, dev, fn);
+ drm_printf(p, "drm-client-id:\t%Lu\n", vm->immediate.fence_context);
+ drm_printf(p, "drm-memory-vram:\t%llu KiB\n", stats.vram/1024UL);
+ drm_printf(p, "drm-memory-gtt: \t%llu KiB\n", stats.gtt/1024UL);
+ drm_printf(p, "drm-memory-cpu: \t%llu KiB\n", stats.cpu/1024UL);
+ drm_printf(p, "amd-memory-visible-vram:\t%llu KiB\n",
stats.visible_vram/1024UL);
- seq_printf(m, "amd-evicted-vram:\t%llu KiB\n",
+ drm_printf(p, "amd-evicted-vram:\t%llu KiB\n",
stats.evicted_vram/1024UL);
- seq_printf(m, "amd-evicted-visible-vram:\t%llu KiB\n",
+ drm_printf(p, "amd-evicted-visible-vram:\t%llu KiB\n",
stats.evicted_visible_vram/1024UL);
- seq_printf(m, "amd-requested-vram:\t%llu KiB\n",
+ drm_printf(p, "amd-requested-vram:\t%llu KiB\n",
stats.requested_vram/1024UL);
- seq_printf(m, "amd-requested-visible-vram:\t%llu KiB\n",
+ drm_printf(p, "amd-requested-visible-vram:\t%llu KiB\n",
stats.requested_visible_vram/1024UL);
- seq_printf(m, "amd-requested-gtt:\t%llu KiB\n",
+ drm_printf(p, "amd-requested-gtt:\t%llu KiB\n",
stats.requested_gtt/1024UL);
-
for (hw_ip = 0; hw_ip < AMDGPU_HW_IP_NUM; ++hw_ip) {
if (!usage[hw_ip])
continue;
- seq_printf(m, "drm-engine-%s:\t%Ld ns\n", amdgpu_ip_name[hw_ip],
+ drm_printf(p, "drm-engine-%s:\t%Ld ns\n", amdgpu_ip_name[hw_ip],
ktime_to_ns(usage[hw_ip]));
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.h
index e86834bfea1d..0398f5a159ef 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.h
@@ -37,6 +37,6 @@
#include "amdgpu_ids.h"
uint32_t amdgpu_get_ip_count(struct amdgpu_device *adev, int id);
-void amdgpu_show_fdinfo(struct seq_file *m, struct file *f);
+void amdgpu_show_fdinfo(struct drm_printer *p, struct drm_file *file);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index a7d250809da9..c694b41f6461 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -42,7 +42,6 @@
#include "amdgpu_reset.h"
/*
- * Fences
* Fences mark an event in the GPUs pipeline and are used
* for GPU/CPU synchronization. When the fence is written,
* it is expected that all buffers associated with that fence
@@ -140,7 +139,7 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring)
* Returns 0 on success, -ENOMEM on failure.
*/
int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amdgpu_job *job,
- unsigned flags)
+ unsigned int flags)
{
struct amdgpu_device *adev = ring->adev;
struct dma_fence *fence;
@@ -174,11 +173,11 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amd
adev->fence_context + ring->idx, seq);
/* Against remove in amdgpu_job_{free, free_cb} */
dma_fence_get(fence);
- }
- else
+ } else {
dma_fence_init(fence, &amdgpu_fence_ops,
&ring->fence_drv.lock,
adev->fence_context + ring->idx, seq);
+ }
}
amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
@@ -377,14 +376,11 @@ signed long amdgpu_fence_wait_polling(struct amdgpu_ring *ring,
uint32_t wait_seq,
signed long timeout)
{
- uint32_t seq;
-
- do {
- seq = amdgpu_fence_read(ring);
- udelay(5);
- timeout -= 5;
- } while ((int32_t)(wait_seq - seq) > 0 && timeout > 0);
+ while ((int32_t)(wait_seq - amdgpu_fence_read(ring)) > 0 && timeout > 0) {
+ udelay(2);
+ timeout -= 2;
+ }
return timeout > 0 ? timeout : 0;
}
/**
@@ -396,7 +392,7 @@ signed long amdgpu_fence_wait_polling(struct amdgpu_ring *ring,
* Returns the number of emitted fences on the ring. Used by the
* dynpm code to ring track activity.
*/
-unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring)
+unsigned int amdgpu_fence_count_emitted(struct amdgpu_ring *ring)
{
uint64_t emitted;
@@ -475,7 +471,7 @@ void amdgpu_fence_update_start_timestamp(struct amdgpu_ring *ring, uint32_t seq,
*/
int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
struct amdgpu_irq_src *irq_src,
- unsigned irq_type)
+ unsigned int irq_type)
{
struct amdgpu_device *adev = ring->adev;
uint64_t index;
@@ -654,6 +650,7 @@ void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev)
for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
struct amdgpu_ring *ring = adev->rings[i];
+
if (!ring || !ring->fence_drv.initialized)
continue;
@@ -695,6 +692,30 @@ void amdgpu_fence_driver_clear_job_fences(struct amdgpu_ring *ring)
}
/**
+ * amdgpu_fence_driver_set_error - set error code on fences
+ * @ring: the ring which contains the fences
+ * @error: the error code to set
+ *
+ * Set an error code to all the fences pending on the ring.
+ */
+void amdgpu_fence_driver_set_error(struct amdgpu_ring *ring, int error)
+{
+ struct amdgpu_fence_driver *drv = &ring->fence_drv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&drv->lock, flags);
+ for (unsigned int i = 0; i <= drv->num_fences_mask; ++i) {
+ struct dma_fence *fence;
+
+ fence = rcu_dereference_protected(drv->fences[i],
+ lockdep_is_held(&drv->lock));
+ if (fence && !dma_fence_is_signaled_locked(fence))
+ dma_fence_set_error(fence, error);
+ }
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+/**
* amdgpu_fence_driver_force_completion - force signal latest fence of ring
*
* @ring: fence of the ring to signal
@@ -702,6 +723,7 @@ void amdgpu_fence_driver_clear_job_fences(struct amdgpu_ring *ring)
*/
void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring)
{
+ amdgpu_fence_driver_set_error(ring, -ECANCELED);
amdgpu_fence_write(ring, ring->fence_drv.sync_seq);
amdgpu_fence_process(ring);
}
@@ -836,11 +858,12 @@ static const struct dma_fence_ops amdgpu_job_fence_ops = {
#if defined(CONFIG_DEBUG_FS)
static int amdgpu_debugfs_fence_info_show(struct seq_file *m, void *unused)
{
- struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
+ struct amdgpu_device *adev = m->private;
int i;
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
struct amdgpu_ring *ring = adev->rings[i];
+
if (!ring || !ring->fence_drv.initialized)
continue;
@@ -914,6 +937,7 @@ static void amdgpu_debugfs_reset_work(struct work_struct *work)
reset_work);
struct amdgpu_reset_context reset_context;
+
memset(&reset_context, 0, sizeof(reset_context));
reset_context.method = AMD_RESET_METHOD_NONE;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
index 01cb89ffbd56..73b8cca35bab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
@@ -35,6 +35,7 @@
#endif
#include "amdgpu.h"
#include <drm/drm_drv.h>
+#include <drm/ttm/ttm_tt.h>
/*
* GART
@@ -103,6 +104,142 @@ void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev)
}
/**
+ * amdgpu_gart_table_ram_alloc - allocate system ram for gart page table
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Allocate system memory for GART page table for ASICs that don't have
+ * dedicated VRAM.
+ * Returns 0 for success, error for failure.
+ */
+int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev)
+{
+ unsigned int order = get_order(adev->gart.table_size);
+ gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO;
+ struct amdgpu_bo *bo = NULL;
+ struct sg_table *sg = NULL;
+ struct amdgpu_bo_param bp;
+ dma_addr_t dma_addr;
+ struct page *p;
+ int ret;
+
+ if (adev->gart.bo != NULL)
+ return 0;
+
+ p = alloc_pages(gfp_flags, order);
+ if (!p)
+ return -ENOMEM;
+
+ /* If the hardware does not support UTCL2 snooping of the CPU caches
+ * then set_memory_wc() could be used as a workaround to mark the pages
+ * as write combine memory.
+ */
+ dma_addr = dma_map_page(&adev->pdev->dev, p, 0, adev->gart.table_size,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(&adev->pdev->dev, dma_addr)) {
+ dev_err(&adev->pdev->dev, "Failed to DMA MAP the GART BO page\n");
+ __free_pages(p, order);
+ p = NULL;
+ return -EFAULT;
+ }
+
+ dev_info(adev->dev, "%s dma_addr:%pad\n", __func__, &dma_addr);
+ /* Create SG table */
+ sg = kmalloc(sizeof(*sg), GFP_KERNEL);
+ if (!sg) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ ret = sg_alloc_table(sg, 1, GFP_KERNEL);
+ if (ret)
+ goto error;
+
+ sg_dma_address(sg->sgl) = dma_addr;
+ sg->sgl->length = adev->gart.table_size;
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+ sg->sgl->dma_length = adev->gart.table_size;
+#endif
+ /* Create SG BO */
+ memset(&bp, 0, sizeof(bp));
+ bp.size = adev->gart.table_size;
+ bp.byte_align = PAGE_SIZE;
+ bp.domain = AMDGPU_GEM_DOMAIN_CPU;
+ bp.type = ttm_bo_type_sg;
+ bp.resv = NULL;
+ bp.bo_ptr_size = sizeof(struct amdgpu_bo);
+ bp.flags = 0;
+ ret = amdgpu_bo_create(adev, &bp, &bo);
+ if (ret)
+ goto error;
+
+ bo->tbo.sg = sg;
+ bo->tbo.ttm->sg = sg;
+ bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
+ bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
+
+ ret = amdgpu_bo_reserve(bo, true);
+ if (ret) {
+ dev_err(adev->dev, "(%d) failed to reserve bo for GART system bo\n", ret);
+ goto error;
+ }
+
+ ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
+ WARN(ret, "Pinning the GART table failed");
+ if (ret)
+ goto error_resv;
+
+ adev->gart.bo = bo;
+ adev->gart.ptr = page_to_virt(p);
+ /* Make GART table accessible in VMID0 */
+ ret = amdgpu_ttm_alloc_gart(&adev->gart.bo->tbo);
+ if (ret)
+ amdgpu_gart_table_ram_free(adev);
+ amdgpu_bo_unreserve(bo);
+
+ return 0;
+
+error_resv:
+ amdgpu_bo_unreserve(bo);
+error:
+ amdgpu_bo_unref(&bo);
+ if (sg) {
+ sg_free_table(sg);
+ kfree(sg);
+ }
+ __free_pages(p, order);
+ return ret;
+}
+
+/**
+ * amdgpu_gart_table_ram_free - free gart page table system ram
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Free the system memory used for the GART page tableon ASICs that don't
+ * have dedicated VRAM.
+ */
+void amdgpu_gart_table_ram_free(struct amdgpu_device *adev)
+{
+ unsigned int order = get_order(adev->gart.table_size);
+ struct sg_table *sg = adev->gart.bo->tbo.sg;
+ struct page *p;
+ int ret;
+
+ ret = amdgpu_bo_reserve(adev->gart.bo, false);
+ if (!ret) {
+ amdgpu_bo_unpin(adev->gart.bo);
+ amdgpu_bo_unreserve(adev->gart.bo);
+ }
+ amdgpu_bo_unref(&adev->gart.bo);
+ sg_free_table(sg);
+ kfree(sg);
+ p = virt_to_page(adev->gart.ptr);
+ __free_pages(p, order);
+
+ adev->gart.ptr = NULL;
+}
+
+/**
* amdgpu_gart_table_vram_alloc - allocate vram for gart page table
*
* @adev: amdgpu_device pointer
@@ -182,7 +319,7 @@ void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
}
mb();
amdgpu_device_flush_hdp(adev, NULL);
- for (i = 0; i < adev->num_vmhubs; i++)
+ for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
drm_dev_exit(idx);
@@ -264,7 +401,7 @@ void amdgpu_gart_invalidate_tlb(struct amdgpu_device *adev)
mb();
amdgpu_device_flush_hdp(adev, NULL);
- for (i = 0; i < adev->num_vmhubs; i++)
+ for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h
index 8fea3e04e411..8283d682f543 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h
@@ -51,6 +51,8 @@ struct amdgpu_gart {
uint64_t gart_pte_flags;
};
+int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev);
+void amdgpu_gart_table_ram_free(struct amdgpu_device *adev);
int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev);
void amdgpu_gart_table_vram_free(struct amdgpu_device *adev);
int amdgpu_gart_table_vram_pin(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 863cb668e000..74055cba3dc9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -98,7 +98,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
int alignment, u32 initial_domain,
u64 flags, enum ttm_bo_type type,
struct dma_resv *resv,
- struct drm_gem_object **obj)
+ struct drm_gem_object **obj, int8_t xcp_id_plus1)
{
struct amdgpu_bo *bo;
struct amdgpu_bo_user *ubo;
@@ -116,6 +116,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
bp.flags = flags;
bp.domain = initial_domain;
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
+ bp.xcp_id_plus1 = xcp_id_plus1;
r = amdgpu_bo_create_user(adev, &bp, &ubo);
if (r)
@@ -336,7 +337,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
retry:
r = amdgpu_gem_object_create(adev, size, args->in.alignment,
initial_domain,
- flags, ttm_bo_type_device, resv, &gobj);
+ flags, ttm_bo_type_device, resv, &gobj, fpriv->xcp_id + 1);
if (r && r != -ERESTARTSYS) {
if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
@@ -379,6 +380,7 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
struct ttm_operation_ctx ctx = { true, false };
struct amdgpu_device *adev = drm_to_adev(dev);
struct drm_amdgpu_gem_userptr *args = data;
+ struct amdgpu_fpriv *fpriv = filp->driver_priv;
struct drm_gem_object *gobj;
struct hmm_range *range;
struct amdgpu_bo *bo;
@@ -405,7 +407,7 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
/* create a gem object to contain this object in */
r = amdgpu_gem_object_create(adev, args->size, 0, AMDGPU_GEM_DOMAIN_CPU,
- 0, ttm_bo_type_device, NULL, &gobj);
+ 0, ttm_bo_type_device, NULL, &gobj, fpriv->xcp_id + 1);
if (r)
return r;
@@ -908,6 +910,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
struct drm_mode_create_dumb *args)
{
struct amdgpu_device *adev = drm_to_adev(dev);
+ struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
struct drm_gem_object *gobj;
uint32_t handle;
u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
@@ -931,7 +934,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
domain = amdgpu_bo_get_preferred_domain(adev,
amdgpu_display_supported_domains(adev, flags));
r = amdgpu_gem_object_create(adev, args->size, 0, domain, flags,
- ttm_bo_type_device, NULL, &gobj);
+ ttm_bo_type_device, NULL, &gobj, fpriv->xcp_id + 1);
if (r)
return -ENOMEM;
@@ -948,7 +951,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
#if defined(CONFIG_DEBUG_FS)
static int amdgpu_debugfs_gem_info_show(struct seq_file *m, void *unused)
{
- struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
+ struct amdgpu_device *adev = m->private;
struct drm_device *dev = adev_to_drm(adev);
struct drm_file *file;
int r;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
index 637bf51dbf06..f30264782ba2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
@@ -43,8 +43,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
int alignment, u32 initial_domain,
u64 flags, enum ttm_bo_type type,
struct dma_resv *resv,
- struct drm_gem_object **obj);
-
+ struct drm_gem_object **obj, int8_t xcp_id_plus1);
int amdgpu_mode_dumb_create(struct drm_file *file_priv,
struct drm_device *dev,
struct drm_mode_create_dumb *args);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index f3f541ba0aca..a33d4bc34cee 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -28,6 +28,7 @@
#include "amdgpu_gfx.h"
#include "amdgpu_rlc.h"
#include "amdgpu_ras.h"
+#include "amdgpu_xcp.h"
/* delay 0.1 second to enable gfx off feature */
#define GFX_OFF_DELAY_ENABLE msecs_to_jiffies(100)
@@ -63,10 +64,10 @@ void amdgpu_queue_mask_bit_to_mec_queue(struct amdgpu_device *adev, int bit,
}
bool amdgpu_gfx_is_mec_queue_enabled(struct amdgpu_device *adev,
- int mec, int pipe, int queue)
+ int xcc_id, int mec, int pipe, int queue)
{
return test_bit(amdgpu_gfx_mec_queue_to_bit(adev, mec, pipe, queue),
- adev->gfx.mec.queue_bitmap);
+ adev->gfx.mec_bitmap[xcc_id].queue_bitmap);
}
int amdgpu_gfx_me_queue_to_bit(struct amdgpu_device *adev,
@@ -204,29 +205,38 @@ bool amdgpu_gfx_is_high_priority_compute_queue(struct amdgpu_device *adev,
void amdgpu_gfx_compute_queue_acquire(struct amdgpu_device *adev)
{
- int i, queue, pipe;
+ int i, j, queue, pipe;
bool multipipe_policy = amdgpu_gfx_is_compute_multipipe_capable(adev);
int max_queues_per_mec = min(adev->gfx.mec.num_pipe_per_mec *
adev->gfx.mec.num_queue_per_pipe,
adev->gfx.num_compute_rings);
+ int num_xcc = adev->gfx.xcc_mask ? NUM_XCC(adev->gfx.xcc_mask) : 1;
if (multipipe_policy) {
- /* policy: make queues evenly cross all pipes on MEC1 only */
- for (i = 0; i < max_queues_per_mec; i++) {
- pipe = i % adev->gfx.mec.num_pipe_per_mec;
- queue = (i / adev->gfx.mec.num_pipe_per_mec) %
- adev->gfx.mec.num_queue_per_pipe;
-
- set_bit(pipe * adev->gfx.mec.num_queue_per_pipe + queue,
- adev->gfx.mec.queue_bitmap);
+ /* policy: make queues evenly cross all pipes on MEC1 only
+ * for multiple xcc, just use the original policy for simplicity */
+ for (j = 0; j < num_xcc; j++) {
+ for (i = 0; i < max_queues_per_mec; i++) {
+ pipe = i % adev->gfx.mec.num_pipe_per_mec;
+ queue = (i / adev->gfx.mec.num_pipe_per_mec) %
+ adev->gfx.mec.num_queue_per_pipe;
+
+ set_bit(pipe * adev->gfx.mec.num_queue_per_pipe + queue,
+ adev->gfx.mec_bitmap[j].queue_bitmap);
+ }
}
} else {
/* policy: amdgpu owns all queues in the given pipe */
- for (i = 0; i < max_queues_per_mec; ++i)
- set_bit(i, adev->gfx.mec.queue_bitmap);
+ for (j = 0; j < num_xcc; j++) {
+ for (i = 0; i < max_queues_per_mec; ++i)
+ set_bit(i, adev->gfx.mec_bitmap[j].queue_bitmap);
+ }
}
- dev_dbg(adev->dev, "mec queue bitmap weight=%d\n", bitmap_weight(adev->gfx.mec.queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES));
+ for (j = 0; j < num_xcc; j++) {
+ dev_dbg(adev->dev, "mec queue bitmap weight=%d\n",
+ bitmap_weight(adev->gfx.mec_bitmap[j].queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES));
+ }
}
void amdgpu_gfx_graphics_queue_acquire(struct amdgpu_device *adev)
@@ -258,7 +268,7 @@ void amdgpu_gfx_graphics_queue_acquire(struct amdgpu_device *adev)
}
static int amdgpu_gfx_kiq_acquire(struct amdgpu_device *adev,
- struct amdgpu_ring *ring)
+ struct amdgpu_ring *ring, int xcc_id)
{
int queue_bit;
int mec, pipe, queue;
@@ -268,7 +278,7 @@ static int amdgpu_gfx_kiq_acquire(struct amdgpu_device *adev,
* adev->gfx.mec.num_queue_per_pipe;
while (--queue_bit >= 0) {
- if (test_bit(queue_bit, adev->gfx.mec.queue_bitmap))
+ if (test_bit(queue_bit, adev->gfx.mec_bitmap[xcc_id].queue_bitmap))
continue;
amdgpu_queue_mask_bit_to_mec_queue(adev, queue_bit, &mec, &pipe, &queue);
@@ -294,9 +304,9 @@ static int amdgpu_gfx_kiq_acquire(struct amdgpu_device *adev,
int amdgpu_gfx_kiq_init_ring(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
- struct amdgpu_irq_src *irq)
+ struct amdgpu_irq_src *irq, int xcc_id)
{
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
int r = 0;
spin_lock_init(&kiq->ring_lock);
@@ -304,16 +314,20 @@ int amdgpu_gfx_kiq_init_ring(struct amdgpu_device *adev,
ring->adev = NULL;
ring->ring_obj = NULL;
ring->use_doorbell = true;
- ring->doorbell_index = adev->doorbell_index.kiq;
- ring->vm_hub = AMDGPU_GFXHUB_0;
-
- r = amdgpu_gfx_kiq_acquire(adev, ring);
+ ring->xcc_id = xcc_id;
+ ring->vm_hub = AMDGPU_GFXHUB(xcc_id);
+ ring->doorbell_index =
+ (adev->doorbell_index.kiq +
+ xcc_id * adev->doorbell_index.xcc_doorbell_range)
+ << 1;
+
+ r = amdgpu_gfx_kiq_acquire(adev, ring, xcc_id);
if (r)
return r;
ring->eop_gpu_addr = kiq->eop_gpu_addr;
ring->no_scheduler = true;
- sprintf(ring->name, "kiq_%d.%d.%d", ring->me, ring->pipe, ring->queue);
+ sprintf(ring->name, "kiq_%d.%d.%d.%d", xcc_id, ring->me, ring->pipe, ring->queue);
r = amdgpu_ring_init(adev, ring, 1024, irq, AMDGPU_CP_KIQ_IRQ_DRIVER0,
AMDGPU_RING_PRIO_DEFAULT, NULL);
if (r)
@@ -327,19 +341,19 @@ void amdgpu_gfx_kiq_free_ring(struct amdgpu_ring *ring)
amdgpu_ring_fini(ring);
}
-void amdgpu_gfx_kiq_fini(struct amdgpu_device *adev)
+void amdgpu_gfx_kiq_fini(struct amdgpu_device *adev, int xcc_id)
{
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
amdgpu_bo_free_kernel(&kiq->eop_obj, &kiq->eop_gpu_addr, NULL);
}
int amdgpu_gfx_kiq_init(struct amdgpu_device *adev,
- unsigned hpd_size)
+ unsigned hpd_size, int xcc_id)
{
int r;
u32 *hpd;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
r = amdgpu_bo_create_kernel(adev, hpd_size, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_GTT, &kiq->eop_obj,
@@ -362,13 +376,18 @@ int amdgpu_gfx_kiq_init(struct amdgpu_device *adev,
/* create MQD for each compute/gfx queue */
int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
- unsigned mqd_size)
+ unsigned mqd_size, int xcc_id)
{
- struct amdgpu_ring *ring = NULL;
- int r, i;
+ int r, i, j;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
+ struct amdgpu_ring *ring = &kiq->ring;
+ u32 domain = AMDGPU_GEM_DOMAIN_GTT;
+
+ /* Only enable on gfx10 and 11 for now to avoid changing behavior on older chips */
+ if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 0, 0))
+ domain |= AMDGPU_GEM_DOMAIN_VRAM;
/* create MQD for KIQ */
- ring = &adev->gfx.kiq.ring;
if (!adev->enable_mes_kiq && !ring->mqd_obj) {
/* originaly the KIQ MQD is put in GTT domain, but for SRIOV VRAM domain is a must
* otherwise hypervisor trigger SAVE_VF fail after driver unloaded which mean MQD
@@ -387,8 +406,8 @@ int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
}
/* prepare MQD backup */
- adev->gfx.mec.mqd_backup[AMDGPU_MAX_COMPUTE_RINGS] = kmalloc(mqd_size, GFP_KERNEL);
- if (!adev->gfx.mec.mqd_backup[AMDGPU_MAX_COMPUTE_RINGS])
+ kiq->mqd_backup = kmalloc(mqd_size, GFP_KERNEL);
+ if (!kiq->mqd_backup)
dev_warn(adev->dev, "no memory to create MQD backup for ring %s\n", ring->name);
}
@@ -398,13 +417,14 @@ int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
ring = &adev->gfx.gfx_ring[i];
if (!ring->mqd_obj) {
r = amdgpu_bo_create_kernel(adev, mqd_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_GTT, &ring->mqd_obj,
+ domain, &ring->mqd_obj,
&ring->mqd_gpu_addr, &ring->mqd_ptr);
if (r) {
dev_warn(adev->dev, "failed to create ring mqd bo (%d)", r);
return r;
}
+ ring->mqd_size = mqd_size;
/* prepare MQD backup */
adev->gfx.me.mqd_backup[i] = kmalloc(mqd_size, GFP_KERNEL);
if (!adev->gfx.me.mqd_backup[i])
@@ -415,19 +435,21 @@ int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
/* create MQD for each KCQ */
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
- ring = &adev->gfx.compute_ring[i];
+ j = i + xcc_id * adev->gfx.num_compute_rings;
+ ring = &adev->gfx.compute_ring[j];
if (!ring->mqd_obj) {
r = amdgpu_bo_create_kernel(adev, mqd_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_GTT, &ring->mqd_obj,
+ domain, &ring->mqd_obj,
&ring->mqd_gpu_addr, &ring->mqd_ptr);
if (r) {
dev_warn(adev->dev, "failed to create ring mqd bo (%d)", r);
return r;
}
+ ring->mqd_size = mqd_size;
/* prepare MQD backup */
- adev->gfx.mec.mqd_backup[i] = kmalloc(mqd_size, GFP_KERNEL);
- if (!adev->gfx.mec.mqd_backup[i])
+ adev->gfx.mec.mqd_backup[j] = kmalloc(mqd_size, GFP_KERNEL);
+ if (!adev->gfx.mec.mqd_backup[j])
dev_warn(adev->dev, "no memory to create MQD backup for ring %s\n", ring->name);
}
}
@@ -435,10 +457,11 @@ int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
return 0;
}
-void amdgpu_gfx_mqd_sw_fini(struct amdgpu_device *adev)
+void amdgpu_gfx_mqd_sw_fini(struct amdgpu_device *adev, int xcc_id)
{
struct amdgpu_ring *ring = NULL;
- int i;
+ int i, j;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
if (adev->asic_type >= CHIP_NAVI10 && amdgpu_async_gfx_ring) {
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
@@ -451,43 +474,81 @@ void amdgpu_gfx_mqd_sw_fini(struct amdgpu_device *adev)
}
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
- ring = &adev->gfx.compute_ring[i];
- kfree(adev->gfx.mec.mqd_backup[i]);
+ j = i + xcc_id * adev->gfx.num_compute_rings;
+ ring = &adev->gfx.compute_ring[j];
+ kfree(adev->gfx.mec.mqd_backup[j]);
amdgpu_bo_free_kernel(&ring->mqd_obj,
&ring->mqd_gpu_addr,
&ring->mqd_ptr);
}
- ring = &adev->gfx.kiq.ring;
- kfree(adev->gfx.mec.mqd_backup[AMDGPU_MAX_COMPUTE_RINGS]);
+ ring = &kiq->ring;
+ kfree(kiq->mqd_backup);
amdgpu_bo_free_kernel(&ring->mqd_obj,
&ring->mqd_gpu_addr,
&ring->mqd_ptr);
}
-int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev)
+int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id)
{
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
struct amdgpu_ring *kiq_ring = &kiq->ring;
int i, r = 0;
+ int j;
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
- spin_lock(&adev->gfx.kiq.ring_lock);
+ spin_lock(&kiq->ring_lock);
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size *
adev->gfx.num_compute_rings)) {
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&kiq->ring_lock);
return -ENOMEM;
}
- for (i = 0; i < adev->gfx.num_compute_rings; i++)
- kiq->pmf->kiq_unmap_queues(kiq_ring, &adev->gfx.compute_ring[i],
+ for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+ j = i + xcc_id * adev->gfx.num_compute_rings;
+ kiq->pmf->kiq_unmap_queues(kiq_ring,
+ &adev->gfx.compute_ring[j],
RESET_QUEUES, 0, 0);
+ }
- if (adev->gfx.kiq.ring.sched.ready && !adev->job_hang)
+ if (kiq_ring->sched.ready && !adev->job_hang)
r = amdgpu_ring_test_helper(kiq_ring);
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&kiq->ring_lock);
+
+ return r;
+}
+
+int amdgpu_gfx_disable_kgq(struct amdgpu_device *adev, int xcc_id)
+{
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
+ struct amdgpu_ring *kiq_ring = &kiq->ring;
+ int i, r = 0;
+ int j;
+
+ if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
+ return -EINVAL;
+
+ spin_lock(&kiq->ring_lock);
+ if (amdgpu_gfx_is_master_xcc(adev, xcc_id)) {
+ if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size *
+ adev->gfx.num_gfx_rings)) {
+ spin_unlock(&kiq->ring_lock);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
+ j = i + xcc_id * adev->gfx.num_gfx_rings;
+ kiq->pmf->kiq_unmap_queues(kiq_ring,
+ &adev->gfx.gfx_ring[j],
+ PREEMPT_QUEUES, 0, 0);
+ }
+ }
+
+ if (adev->gfx.kiq[0].ring.sched.ready && !adev->job_hang)
+ r = amdgpu_ring_test_helper(kiq_ring);
+ spin_unlock(&kiq->ring_lock);
return r;
}
@@ -505,18 +566,18 @@ int amdgpu_queue_mask_bit_to_set_resource_bit(struct amdgpu_device *adev,
return set_resource_bit;
}
-int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev)
+int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev, int xcc_id)
{
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
- struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
+ struct amdgpu_ring *kiq_ring = &kiq->ring;
uint64_t queue_mask = 0;
- int r, i;
+ int r, i, j;
if (!kiq->pmf || !kiq->pmf->kiq_map_queues || !kiq->pmf->kiq_set_resources)
return -EINVAL;
for (i = 0; i < AMDGPU_MAX_COMPUTE_QUEUES; ++i) {
- if (!test_bit(i, adev->gfx.mec.queue_bitmap))
+ if (!test_bit(i, adev->gfx.mec_bitmap[xcc_id].queue_bitmap))
continue;
/* This situation may be hit in the future if a new HW
@@ -532,13 +593,15 @@ int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev)
DRM_INFO("kiq ring mec %d pipe %d q %d\n", kiq_ring->me, kiq_ring->pipe,
kiq_ring->queue);
- spin_lock(&adev->gfx.kiq.ring_lock);
+ amdgpu_device_flush_hdp(adev, NULL);
+
+ spin_lock(&kiq->ring_lock);
r = amdgpu_ring_alloc(kiq_ring, kiq->pmf->map_queues_size *
adev->gfx.num_compute_rings +
kiq->pmf->set_resources_size);
if (r) {
DRM_ERROR("Failed to lock KIQ (%d).\n", r);
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&kiq->ring_lock);
return r;
}
@@ -546,11 +609,51 @@ int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev)
queue_mask = ~0ULL;
kiq->pmf->kiq_set_resources(kiq_ring, queue_mask);
- for (i = 0; i < adev->gfx.num_compute_rings; i++)
- kiq->pmf->kiq_map_queues(kiq_ring, &adev->gfx.compute_ring[i]);
+ for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+ j = i + xcc_id * adev->gfx.num_compute_rings;
+ kiq->pmf->kiq_map_queues(kiq_ring,
+ &adev->gfx.compute_ring[j]);
+ }
r = amdgpu_ring_test_helper(kiq_ring);
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&kiq->ring_lock);
+ if (r)
+ DRM_ERROR("KCQ enable failed\n");
+
+ return r;
+}
+
+int amdgpu_gfx_enable_kgq(struct amdgpu_device *adev, int xcc_id)
+{
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
+ struct amdgpu_ring *kiq_ring = &kiq->ring;
+ int r, i, j;
+
+ if (!kiq->pmf || !kiq->pmf->kiq_map_queues)
+ return -EINVAL;
+
+ amdgpu_device_flush_hdp(adev, NULL);
+
+ spin_lock(&kiq->ring_lock);
+ /* No need to map kcq on the slave */
+ if (amdgpu_gfx_is_master_xcc(adev, xcc_id)) {
+ r = amdgpu_ring_alloc(kiq_ring, kiq->pmf->map_queues_size *
+ adev->gfx.num_gfx_rings);
+ if (r) {
+ DRM_ERROR("Failed to lock KIQ (%d).\n", r);
+ spin_unlock(&kiq->ring_lock);
+ return r;
+ }
+
+ for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
+ j = i + xcc_id * adev->gfx.num_gfx_rings;
+ kiq->pmf->kiq_map_queues(kiq_ring,
+ &adev->gfx.gfx_ring[j]);
+ }
+ }
+
+ r = amdgpu_ring_test_helper(kiq_ring);
+ spin_unlock(&kiq->ring_lock);
if (r)
DRM_ERROR("KCQ enable failed\n");
@@ -785,12 +888,31 @@ int amdgpu_gfx_cp_ecc_error_irq(struct amdgpu_device *adev,
return 0;
}
+void amdgpu_gfx_ras_error_func(struct amdgpu_device *adev,
+ void *ras_error_status,
+ void (*func)(struct amdgpu_device *adev, void *ras_error_status,
+ int xcc_id))
+{
+ int i;
+ int num_xcc = adev->gfx.xcc_mask ? NUM_XCC(adev->gfx.xcc_mask) : 1;
+ uint32_t xcc_mask = GENMASK(num_xcc - 1, 0);
+ struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
+
+ if (err_data) {
+ err_data->ue_count = 0;
+ err_data->ce_count = 0;
+ }
+
+ for_each_inst(i, xcc_mask)
+ func(adev, ras_error_status, i);
+}
+
uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg)
{
signed long r, cnt = 0;
unsigned long flags;
uint32_t seq, reg_val_offs = 0, value = 0;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
struct amdgpu_ring *ring = &kiq->ring;
if (amdgpu_device_skip_hw_access(adev))
@@ -858,7 +980,7 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v)
signed long r, cnt = 0;
unsigned long flags;
uint32_t seq;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
struct amdgpu_ring *ring = &kiq->ring;
BUG_ON(!ring->funcs->emit_wreg);
@@ -1062,3 +1184,125 @@ void amdgpu_gfx_cp_init_microcode(struct amdgpu_device *adev,
adev->firmware.fw_size += ALIGN(fw_size, PAGE_SIZE);
}
}
+
+bool amdgpu_gfx_is_master_xcc(struct amdgpu_device *adev, int xcc_id)
+{
+ return !(xcc_id % (adev->gfx.num_xcc_per_xcp ?
+ adev->gfx.num_xcc_per_xcp : 1));
+}
+
+static ssize_t amdgpu_gfx_get_current_compute_partition(struct device *dev,
+ struct device_attribute *addr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+ int mode;
+
+ mode = amdgpu_xcp_query_partition_mode(adev->xcp_mgr,
+ AMDGPU_XCP_FL_NONE);
+
+ return sysfs_emit(buf, "%s\n", amdgpu_gfx_compute_mode_desc(mode));
+}
+
+static ssize_t amdgpu_gfx_set_compute_partition(struct device *dev,
+ struct device_attribute *addr,
+ const char *buf, size_t count)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+ enum amdgpu_gfx_partition mode;
+ int ret = 0, num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ if (num_xcc % 2 != 0)
+ return -EINVAL;
+
+ if (!strncasecmp("SPX", buf, strlen("SPX"))) {
+ mode = AMDGPU_SPX_PARTITION_MODE;
+ } else if (!strncasecmp("DPX", buf, strlen("DPX"))) {
+ /*
+ * DPX mode needs AIDs to be in multiple of 2.
+ * Each AID connects 2 XCCs.
+ */
+ if (num_xcc%4)
+ return -EINVAL;
+ mode = AMDGPU_DPX_PARTITION_MODE;
+ } else if (!strncasecmp("TPX", buf, strlen("TPX"))) {
+ if (num_xcc != 6)
+ return -EINVAL;
+ mode = AMDGPU_TPX_PARTITION_MODE;
+ } else if (!strncasecmp("QPX", buf, strlen("QPX"))) {
+ if (num_xcc != 8)
+ return -EINVAL;
+ mode = AMDGPU_QPX_PARTITION_MODE;
+ } else if (!strncasecmp("CPX", buf, strlen("CPX"))) {
+ mode = AMDGPU_CPX_PARTITION_MODE;
+ } else {
+ return -EINVAL;
+ }
+
+ ret = amdgpu_xcp_switch_partition_mode(adev->xcp_mgr, mode);
+
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static ssize_t amdgpu_gfx_get_available_compute_partition(struct device *dev,
+ struct device_attribute *addr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+ char *supported_partition;
+
+ /* TBD */
+ switch (NUM_XCC(adev->gfx.xcc_mask)) {
+ case 8:
+ supported_partition = "SPX, DPX, QPX, CPX";
+ break;
+ case 6:
+ supported_partition = "SPX, TPX, CPX";
+ break;
+ case 4:
+ supported_partition = "SPX, DPX, CPX";
+ break;
+ /* this seems only existing in emulation phase */
+ case 2:
+ supported_partition = "SPX, CPX";
+ break;
+ default:
+ supported_partition = "Not supported";
+ break;
+ }
+
+ return sysfs_emit(buf, "%s\n", supported_partition);
+}
+
+static DEVICE_ATTR(current_compute_partition, S_IRUGO | S_IWUSR,
+ amdgpu_gfx_get_current_compute_partition,
+ amdgpu_gfx_set_compute_partition);
+
+static DEVICE_ATTR(available_compute_partition, S_IRUGO,
+ amdgpu_gfx_get_available_compute_partition, NULL);
+
+int amdgpu_gfx_sysfs_init(struct amdgpu_device *adev)
+{
+ int r;
+
+ r = device_create_file(adev->dev, &dev_attr_current_compute_partition);
+ if (r)
+ return r;
+
+ r = device_create_file(adev->dev, &dev_attr_available_compute_partition);
+
+ return r;
+}
+
+void amdgpu_gfx_sysfs_fini(struct amdgpu_device *adev)
+{
+ device_remove_file(adev->dev, &dev_attr_current_compute_partition);
+ device_remove_file(adev->dev, &dev_attr_available_compute_partition);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index bfabea76d166..ce0f7a8ad4b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -61,7 +61,42 @@ enum amdgpu_gfx_partition {
AMDGPU_TPX_PARTITION_MODE = 2,
AMDGPU_QPX_PARTITION_MODE = 3,
AMDGPU_CPX_PARTITION_MODE = 4,
- AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE,
+ AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE = -1,
+ /* Automatically choose the right mode */
+ AMDGPU_AUTO_COMPUTE_PARTITION_MODE = -2,
+};
+
+#define NUM_XCC(x) hweight16(x)
+
+enum amdgpu_pkg_type {
+ AMDGPU_PKG_TYPE_APU = 2,
+ AMDGPU_PKG_TYPE_UNKNOWN,
+};
+
+enum amdgpu_gfx_ras_mem_id_type {
+ AMDGPU_GFX_CP_MEM = 0,
+ AMDGPU_GFX_GCEA_MEM,
+ AMDGPU_GFX_GC_CANE_MEM,
+ AMDGPU_GFX_GCUTCL2_MEM,
+ AMDGPU_GFX_GDS_MEM,
+ AMDGPU_GFX_LDS_MEM,
+ AMDGPU_GFX_RLC_MEM,
+ AMDGPU_GFX_SP_MEM,
+ AMDGPU_GFX_SPI_MEM,
+ AMDGPU_GFX_SQC_MEM,
+ AMDGPU_GFX_SQ_MEM,
+ AMDGPU_GFX_TA_MEM,
+ AMDGPU_GFX_TCC_MEM,
+ AMDGPU_GFX_TCA_MEM,
+ AMDGPU_GFX_TCI_MEM,
+ AMDGPU_GFX_TCP_MEM,
+ AMDGPU_GFX_TD_MEM,
+ AMDGPU_GFX_TCX_MEM,
+ AMDGPU_GFX_ATC_L2_MEM,
+ AMDGPU_GFX_UTCL2_MEM,
+ AMDGPU_GFX_VML2_MEM,
+ AMDGPU_GFX_VML2_WALKER_MEM,
+ AMDGPU_GFX_MEM_TYPE_NUM
};
struct amdgpu_mec {
@@ -75,8 +110,10 @@ struct amdgpu_mec {
u32 num_mec;
u32 num_pipe_per_mec;
u32 num_queue_per_pipe;
- void *mqd_backup[AMDGPU_MAX_COMPUTE_RINGS + 1];
+ void *mqd_backup[AMDGPU_MAX_COMPUTE_RINGS * AMDGPU_MAX_GC_INSTANCES];
+};
+struct amdgpu_mec_bitmap {
/* These are the resources for which amdgpu takes ownership */
DECLARE_BITMAP(queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
};
@@ -120,6 +157,7 @@ struct amdgpu_kiq {
struct amdgpu_ring ring;
struct amdgpu_irq_src irq;
const struct kiq_pm4_funcs *pmf;
+ void *mqd_backup;
};
/*
@@ -230,23 +268,37 @@ struct amdgpu_gfx_ras {
struct amdgpu_iv_entry *entry);
};
+struct amdgpu_gfx_shadow_info {
+ u32 shadow_size;
+ u32 shadow_alignment;
+ u32 csa_size;
+ u32 csa_alignment;
+};
+
struct amdgpu_gfx_funcs {
/* get the gpu clock counter */
uint64_t (*get_gpu_clock_counter)(struct amdgpu_device *adev);
void (*select_se_sh)(struct amdgpu_device *adev, u32 se_num,
- u32 sh_num, u32 instance);
- void (*read_wave_data)(struct amdgpu_device *adev, uint32_t simd,
+ u32 sh_num, u32 instance, int xcc_id);
+ void (*read_wave_data)(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t *dst, int *no_fields);
- void (*read_wave_vgprs)(struct amdgpu_device *adev, uint32_t simd,
+ void (*read_wave_vgprs)(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t thread, uint32_t start,
uint32_t size, uint32_t *dst);
- void (*read_wave_sgprs)(struct amdgpu_device *adev, uint32_t simd,
+ void (*read_wave_sgprs)(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t start, uint32_t size,
uint32_t *dst);
void (*select_me_pipe_q)(struct amdgpu_device *adev, u32 me, u32 pipe,
- u32 queue, u32 vmid);
+ u32 queue, u32 vmid, u32 xcc_id);
void (*init_spm_golden)(struct amdgpu_device *adev);
void (*update_perfmon_mgcg)(struct amdgpu_device *adev, bool enable);
+ int (*get_gfx_shadow_info)(struct amdgpu_device *adev,
+ struct amdgpu_gfx_shadow_info *shadow_info);
+ enum amdgpu_gfx_partition
+ (*query_partition_mode)(struct amdgpu_device *adev);
+ int (*switch_partition_mode)(struct amdgpu_device *adev,
+ int num_xccs_per_xcp);
+ int (*ih_node_to_logical_xcc)(struct amdgpu_device *adev, int ih_node);
};
struct sq_work {
@@ -296,7 +348,8 @@ struct amdgpu_gfx {
struct amdgpu_ce ce;
struct amdgpu_me me;
struct amdgpu_mec mec;
- struct amdgpu_kiq kiq;
+ struct amdgpu_mec_bitmap mec_bitmap[AMDGPU_MAX_GC_INSTANCES];
+ struct amdgpu_kiq kiq[AMDGPU_MAX_GC_INSTANCES];
struct amdgpu_imu imu;
bool rs64_enable; /* firmware format */
const struct firmware *me_fw; /* ME firmware */
@@ -376,15 +429,31 @@ struct amdgpu_gfx {
struct amdgpu_ring sw_gfx_ring[AMDGPU_MAX_SW_GFX_RINGS];
struct amdgpu_ring_mux muxer;
- enum amdgpu_gfx_partition partition_mode;
- uint32_t num_xcd;
+ bool cp_gfx_shadow; /* for gfx11 */
+
+ uint16_t xcc_mask;
uint32_t num_xcc_per_xcp;
+ struct mutex partition_mutex;
};
+struct amdgpu_gfx_ras_reg_entry {
+ struct amdgpu_ras_err_status_reg_entry reg_entry;
+ enum amdgpu_gfx_ras_mem_id_type mem_id_type;
+ uint32_t se_num;
+};
+
+struct amdgpu_gfx_ras_mem_id_entry {
+ const struct amdgpu_ras_memory_id_entry *mem_id_ent;
+ uint32_t size;
+};
+
+#define AMDGPU_GFX_MEMID_ENT(x) {(x), ARRAY_SIZE(x)},
+
#define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev))
-#define amdgpu_gfx_select_se_sh(adev, se, sh, instance) (adev)->gfx.funcs->select_se_sh((adev), (se), (sh), (instance))
-#define amdgpu_gfx_select_me_pipe_q(adev, me, pipe, q, vmid) (adev)->gfx.funcs->select_me_pipe_q((adev), (me), (pipe), (q), (vmid))
+#define amdgpu_gfx_select_se_sh(adev, se, sh, instance, xcc_id) ((adev)->gfx.funcs->select_se_sh((adev), (se), (sh), (instance), (xcc_id)))
+#define amdgpu_gfx_select_me_pipe_q(adev, me, pipe, q, vmid, xcc_id) ((adev)->gfx.funcs->select_me_pipe_q((adev), (me), (pipe), (q), (vmid), (xcc_id)))
#define amdgpu_gfx_init_spm_golden(adev) (adev)->gfx.funcs->init_spm_golden((adev))
+#define amdgpu_gfx_get_gfx_shadow_info(adev, si) ((adev)->gfx.funcs->get_gfx_shadow_info((adev), (si)))
/**
* amdgpu_gfx_create_bitmask - create a bitmask
@@ -404,19 +473,21 @@ void amdgpu_gfx_parse_disable_cu(unsigned *mask, unsigned max_se,
int amdgpu_gfx_kiq_init_ring(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
- struct amdgpu_irq_src *irq);
+ struct amdgpu_irq_src *irq, int xcc_id);
void amdgpu_gfx_kiq_free_ring(struct amdgpu_ring *ring);
-void amdgpu_gfx_kiq_fini(struct amdgpu_device *adev);
+void amdgpu_gfx_kiq_fini(struct amdgpu_device *adev, int xcc_id);
int amdgpu_gfx_kiq_init(struct amdgpu_device *adev,
- unsigned hpd_size);
+ unsigned hpd_size, int xcc_id);
int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
- unsigned mqd_size);
-void amdgpu_gfx_mqd_sw_fini(struct amdgpu_device *adev);
-int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev);
-int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev);
+ unsigned mqd_size, int xcc_id);
+void amdgpu_gfx_mqd_sw_fini(struct amdgpu_device *adev, int xcc_id);
+int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id);
+int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev, int xcc_id);
+int amdgpu_gfx_disable_kgq(struct amdgpu_device *adev, int xcc_id);
+int amdgpu_gfx_enable_kgq(struct amdgpu_device *adev, int xcc_id);
void amdgpu_gfx_compute_queue_acquire(struct amdgpu_device *adev);
void amdgpu_gfx_graphics_queue_acquire(struct amdgpu_device *adev);
@@ -425,8 +496,8 @@ int amdgpu_gfx_mec_queue_to_bit(struct amdgpu_device *adev, int mec,
int pipe, int queue);
void amdgpu_queue_mask_bit_to_mec_queue(struct amdgpu_device *adev, int bit,
int *mec, int *pipe, int *queue);
-bool amdgpu_gfx_is_mec_queue_enabled(struct amdgpu_device *adev, int mec,
- int pipe, int queue);
+bool amdgpu_gfx_is_mec_queue_enabled(struct amdgpu_device *adev, int xcc_id,
+ int mec, int pipe, int queue);
bool amdgpu_gfx_is_high_priority_compute_queue(struct amdgpu_device *adev,
struct amdgpu_ring *ring);
bool amdgpu_gfx_is_high_priority_graphics_queue(struct amdgpu_device *adev,
@@ -458,4 +529,33 @@ void amdgpu_gfx_cp_init_microcode(struct amdgpu_device *adev, uint32_t ucode_id)
int amdgpu_gfx_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_gfx_poison_consumption_handler(struct amdgpu_device *adev,
struct amdgpu_iv_entry *entry);
+
+bool amdgpu_gfx_is_master_xcc(struct amdgpu_device *adev, int xcc_id);
+int amdgpu_gfx_sysfs_init(struct amdgpu_device *adev);
+void amdgpu_gfx_sysfs_fini(struct amdgpu_device *adev);
+void amdgpu_gfx_ras_error_func(struct amdgpu_device *adev,
+ void *ras_error_status,
+ void (*func)(struct amdgpu_device *adev, void *ras_error_status,
+ int xcc_id));
+
+static inline const char *amdgpu_gfx_compute_mode_desc(int mode)
+{
+ switch (mode) {
+ case AMDGPU_SPX_PARTITION_MODE:
+ return "SPX";
+ case AMDGPU_DPX_PARTITION_MODE:
+ return "DPX";
+ case AMDGPU_TPX_PARTITION_MODE:
+ return "TPX";
+ case AMDGPU_QPX_PARTITION_MODE:
+ return "QPX";
+ case AMDGPU_CPX_PARTITION_MODE:
+ return "CPX";
+ default:
+ return "UNKNOWN";
+ }
+
+ return "UNKNOWN";
+}
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index 95b0f984acbf..d78bd9732543 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -534,22 +534,21 @@ void amdgpu_gmc_ras_fini(struct amdgpu_device *adev)
* subject to change when ring number changes
* Engine 17: Gart flushes
*/
-#define GFXHUB_FREE_VM_INV_ENGS_BITMAP 0x1FFF3
-#define MMHUB_FREE_VM_INV_ENGS_BITMAP 0x1FFF3
+#define AMDGPU_VMHUB_INV_ENG_BITMAP 0x1FFF3
int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev)
{
struct amdgpu_ring *ring;
- unsigned vm_inv_engs[AMDGPU_MAX_VMHUBS] =
- {GFXHUB_FREE_VM_INV_ENGS_BITMAP, MMHUB_FREE_VM_INV_ENGS_BITMAP,
- GFXHUB_FREE_VM_INV_ENGS_BITMAP};
+ unsigned vm_inv_engs[AMDGPU_MAX_VMHUBS] = {0};
unsigned i;
unsigned vmhub, inv_eng;
- if (adev->enable_mes) {
+ /* init the vm inv eng for all vmhubs */
+ for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS) {
+ vm_inv_engs[i] = AMDGPU_VMHUB_INV_ENG_BITMAP;
/* reserve engine 5 for firmware */
- for (vmhub = 0; vmhub < AMDGPU_MAX_VMHUBS; vmhub++)
- vm_inv_engs[vmhub] &= ~(1 << 5);
+ if (adev->enable_mes)
+ vm_inv_engs[i] &= ~(1 << 5);
}
for (i = 0; i < adev->num_rings; ++i) {
@@ -671,7 +670,7 @@ void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type,
for (i = 0; i < 16; i++) {
reg = hub->vm_context0_cntl + hub->ctx_distance * i;
- tmp = (hub_type == AMDGPU_GFXHUB_0) ?
+ tmp = (hub_type == AMDGPU_GFXHUB(0)) ?
RREG32_SOC15_IP(GC, reg) :
RREG32_SOC15_IP(MMHUB, reg);
@@ -680,7 +679,7 @@ void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type,
else
tmp &= ~hub->vm_cntx_cntl_vm_fault;
- (hub_type == AMDGPU_GFXHUB_0) ?
+ (hub_type == AMDGPU_GFXHUB(0)) ?
WREG32_SOC15_IP(GC, reg, tmp) :
WREG32_SOC15_IP(MMHUB, reg, tmp);
}
@@ -893,3 +892,47 @@ int amdgpu_gmc_vram_checking(struct amdgpu_device *adev)
return 0;
}
+
+static ssize_t current_memory_partition_show(
+ struct device *dev, struct device_attribute *addr, char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+ enum amdgpu_memory_partition mode;
+
+ mode = adev->gmc.gmc_funcs->query_mem_partition_mode(adev);
+ switch (mode) {
+ case AMDGPU_NPS1_PARTITION_MODE:
+ return sysfs_emit(buf, "NPS1\n");
+ case AMDGPU_NPS2_PARTITION_MODE:
+ return sysfs_emit(buf, "NPS2\n");
+ case AMDGPU_NPS3_PARTITION_MODE:
+ return sysfs_emit(buf, "NPS3\n");
+ case AMDGPU_NPS4_PARTITION_MODE:
+ return sysfs_emit(buf, "NPS4\n");
+ case AMDGPU_NPS6_PARTITION_MODE:
+ return sysfs_emit(buf, "NPS6\n");
+ case AMDGPU_NPS8_PARTITION_MODE:
+ return sysfs_emit(buf, "NPS8\n");
+ default:
+ return sysfs_emit(buf, "UNKNOWN\n");
+ }
+
+ return sysfs_emit(buf, "UNKNOWN\n");
+}
+
+static DEVICE_ATTR_RO(current_memory_partition);
+
+int amdgpu_gmc_sysfs_init(struct amdgpu_device *adev)
+{
+ if (!adev->gmc.gmc_funcs->query_mem_partition_mode)
+ return 0;
+
+ return device_create_file(adev->dev,
+ &dev_attr_current_memory_partition);
+}
+
+void amdgpu_gmc_sysfs_fini(struct amdgpu_device *adev)
+{
+ device_remove_file(adev->dev, &dev_attr_current_memory_partition);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
index 6d105d7fb98b..56d73fade568 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
@@ -63,6 +63,16 @@
struct firmware;
+enum amdgpu_memory_partition {
+ UNKNOWN_MEMORY_PARTITION_MODE = 0,
+ AMDGPU_NPS1_PARTITION_MODE = 1,
+ AMDGPU_NPS2_PARTITION_MODE = 2,
+ AMDGPU_NPS3_PARTITION_MODE = 3,
+ AMDGPU_NPS4_PARTITION_MODE = 4,
+ AMDGPU_NPS6_PARTITION_MODE = 6,
+ AMDGPU_NPS8_PARTITION_MODE = 8,
+};
+
/*
* GMC page fault information
*/
@@ -119,7 +129,8 @@ struct amdgpu_gmc_funcs {
uint32_t vmhub, uint32_t flush_type);
/* flush the vm tlb via pasid */
int (*flush_gpu_tlb_pasid)(struct amdgpu_device *adev, uint16_t pasid,
- uint32_t flush_type, bool all_hub);
+ uint32_t flush_type, bool all_hub,
+ uint32_t inst);
/* flush the vm tlb via ring */
uint64_t (*emit_flush_gpu_tlb)(struct amdgpu_ring *ring, unsigned vmid,
uint64_t pd_addr);
@@ -137,8 +148,15 @@ struct amdgpu_gmc_funcs {
void (*get_vm_pte)(struct amdgpu_device *adev,
struct amdgpu_bo_va_mapping *mapping,
uint64_t *flags);
+ /* override per-page pte flags */
+ void (*override_vm_pte_flags)(struct amdgpu_device *dev,
+ struct amdgpu_vm *vm,
+ uint64_t addr, uint64_t *flags);
/* get the amount of memory used by the vbios for pre-OS console */
unsigned int (*get_vbios_fb_size)(struct amdgpu_device *adev);
+
+ enum amdgpu_memory_partition (*query_mem_partition_mode)(
+ struct amdgpu_device *adev);
};
struct amdgpu_xgmi_ras {
@@ -164,6 +182,21 @@ struct amdgpu_xgmi {
struct amdgpu_xgmi_ras *ras;
};
+struct amdgpu_mem_partition_info {
+ union {
+ struct {
+ uint32_t fpfn;
+ uint32_t lpfn;
+ } range;
+ struct {
+ int node;
+ } numa;
+ };
+ uint64_t size;
+};
+
+#define INVALID_PFN -1
+
struct amdgpu_gmc {
/* FB's physical address in MMIO space (for CPU to
* map FB). This is different compared to the agp/
@@ -250,7 +283,10 @@ struct amdgpu_gmc {
uint64_t last_fault:AMDGPU_GMC_FAULT_RING_ORDER;
bool tmz_enabled;
+ bool is_app_apu;
+ struct amdgpu_mem_partition_info *mem_partitions;
+ uint8_t num_mem_partitions;
const struct amdgpu_gmc_funcs *gmc_funcs;
struct amdgpu_xgmi xgmi;
@@ -265,6 +301,8 @@ struct amdgpu_gmc {
/* MALL size */
u64 mall_size;
+ uint32_t m_half_use;
+
/* number of UMC instances */
int num_umc;
/* mode2 save restore */
@@ -296,14 +334,17 @@ struct amdgpu_gmc {
};
#define amdgpu_gmc_flush_gpu_tlb(adev, vmid, vmhub, type) ((adev)->gmc.gmc_funcs->flush_gpu_tlb((adev), (vmid), (vmhub), (type)))
-#define amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, type, allhub) \
+#define amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, type, allhub, inst) \
((adev)->gmc.gmc_funcs->flush_gpu_tlb_pasid \
- ((adev), (pasid), (type), (allhub)))
+ ((adev), (pasid), (type), (allhub), (inst)))
#define amdgpu_gmc_emit_flush_gpu_tlb(r, vmid, addr) (r)->adev->gmc.gmc_funcs->emit_flush_gpu_tlb((r), (vmid), (addr))
#define amdgpu_gmc_emit_pasid_mapping(r, vmid, pasid) (r)->adev->gmc.gmc_funcs->emit_pasid_mapping((r), (vmid), (pasid))
#define amdgpu_gmc_map_mtype(adev, flags) (adev)->gmc.gmc_funcs->map_mtype((adev),(flags))
#define amdgpu_gmc_get_vm_pde(adev, level, dst, flags) (adev)->gmc.gmc_funcs->get_vm_pde((adev), (level), (dst), (flags))
#define amdgpu_gmc_get_vm_pte(adev, mapping, flags) (adev)->gmc.gmc_funcs->get_vm_pte((adev), (mapping), (flags))
+#define amdgpu_gmc_override_vm_pte_flags(adev, vm, addr, pte_flags) \
+ (adev)->gmc.gmc_funcs->override_vm_pte_flags \
+ ((adev), (vm), (addr), (pte_flags))
#define amdgpu_gmc_get_vbios_fb_size(adev) (adev)->gmc.gmc_funcs->get_vbios_fb_size((adev))
/**
@@ -373,4 +414,7 @@ uint64_t amdgpu_gmc_vram_mc2pa(struct amdgpu_device *adev, uint64_t mc_addr);
uint64_t amdgpu_gmc_vram_pa(struct amdgpu_device *adev, struct amdgpu_bo *bo);
uint64_t amdgpu_gmc_vram_cpu_pa(struct amdgpu_device *adev, struct amdgpu_bo *bo);
int amdgpu_gmc_vram_checking(struct amdgpu_device *adev);
+int amdgpu_gmc_sysfs_init(struct amdgpu_device *adev);
+void amdgpu_gmc_sysfs_fini(struct amdgpu_device *adev);
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
index 2dadcfe43d03..081267161d40 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
@@ -190,8 +190,8 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
pr_debug("hmm range: start = 0x%lx, end = 0x%lx",
hmm_range->start, hmm_range->end);
- /* Assuming 512MB takes maxmium 1 second to fault page address */
- timeout = max((hmm_range->end - hmm_range->start) >> 29, 1UL);
+ /* Assuming 128MB takes maximum 1 second to fault page address */
+ timeout = max((hmm_range->end - hmm_range->start) >> 27, 1UL);
timeout *= HMM_RANGE_DEFAULT_TIMEOUT;
timeout = jiffies + msecs_to_jiffies(timeout);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 4ff348e10e4d..ebeddc9a37e9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -136,7 +136,9 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
uint64_t fence_ctx;
uint32_t status = 0, alloc_size;
unsigned fence_flags = 0;
- bool secure;
+ bool secure, init_shadow;
+ u64 shadow_va, csa_va, gds_va;
+ int vmid = AMDGPU_JOB_GET_VMID(job);
unsigned i;
int r = 0;
@@ -150,9 +152,17 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
vm = job->vm;
fence_ctx = job->base.s_fence ?
job->base.s_fence->scheduled.context : 0;
+ shadow_va = job->shadow_va;
+ csa_va = job->csa_va;
+ gds_va = job->gds_va;
+ init_shadow = job->init_shadow;
} else {
vm = NULL;
fence_ctx = 0;
+ shadow_va = 0;
+ csa_va = 0;
+ gds_va = 0;
+ init_shadow = false;
}
if (!ring->sched.ready && !ring->is_mes_queue) {
@@ -212,7 +222,12 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
}
amdgpu_ring_ib_begin(ring);
- if (job && ring->funcs->init_cond_exec)
+
+ if (ring->funcs->emit_gfx_shadow)
+ amdgpu_ring_emit_gfx_shadow(ring, shadow_va, csa_va, gds_va,
+ init_shadow, vmid);
+
+ if (ring->funcs->init_cond_exec)
patch_offset = amdgpu_ring_init_cond_exec(ring);
amdgpu_device_flush_hdp(adev, ring);
@@ -263,6 +278,18 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
fence_flags | AMDGPU_FENCE_FLAG_64BIT);
}
+ if (ring->funcs->emit_gfx_shadow) {
+ amdgpu_ring_emit_gfx_shadow(ring, 0, 0, 0, false, 0);
+
+ if (ring->funcs->init_cond_exec) {
+ unsigned ce_offset = ~0;
+
+ ce_offset = amdgpu_ring_init_cond_exec(ring);
+ if (ce_offset != ~0 && ring->funcs->patch_cond_exec)
+ amdgpu_ring_patch_cond_exec(ring, ce_offset);
+ }
+ }
+
r = amdgpu_fence_emit(ring, f, job, fence_flags);
if (r) {
dev_err(adev->dev, "failed to emit fence (%d)\n", r);
@@ -436,7 +463,7 @@ int amdgpu_ib_ring_tests(struct amdgpu_device *adev)
static int amdgpu_debugfs_sa_info_show(struct seq_file *m, void *unused)
{
- struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
+ struct amdgpu_device *adev = m->private;
seq_printf(m, "--------------------- DELAYED --------------------- \n");
amdgpu_sa_bo_dump_debug_info(&adev->ib_pools[AMDGPU_IB_POOL_DELAYED],
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
index c991ca0b7a1c..ff1ea99292fb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
@@ -409,7 +409,7 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
if (r || !idle)
goto error;
- if (vm->reserved_vmid[vmhub]) {
+ if (vm->reserved_vmid[vmhub] || (enforce_isolation && (vmhub == AMDGPU_GFXHUB(0)))) {
r = amdgpu_vmid_grab_reserved(vm, ring, job, &id, fence);
if (r || !id)
goto error;
@@ -460,14 +460,11 @@ error:
}
int amdgpu_vmid_alloc_reserved(struct amdgpu_device *adev,
- struct amdgpu_vm *vm,
unsigned vmhub)
{
struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
mutex_lock(&id_mgr->lock);
- if (vm->reserved_vmid[vmhub])
- goto unlock;
++id_mgr->reserved_use_count;
if (!id_mgr->reserved) {
@@ -479,27 +476,23 @@ int amdgpu_vmid_alloc_reserved(struct amdgpu_device *adev,
list_del_init(&id->list);
id_mgr->reserved = id;
}
- vm->reserved_vmid[vmhub] = true;
-unlock:
mutex_unlock(&id_mgr->lock);
return 0;
}
void amdgpu_vmid_free_reserved(struct amdgpu_device *adev,
- struct amdgpu_vm *vm,
unsigned vmhub)
{
struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
mutex_lock(&id_mgr->lock);
- if (vm->reserved_vmid[vmhub] &&
- !--id_mgr->reserved_use_count) {
+ if (!--id_mgr->reserved_use_count) {
/* give the reserved ID back to normal round robin */
list_add(&id_mgr->reserved->list, &id_mgr->ids_lru);
id_mgr->reserved = NULL;
}
- vm->reserved_vmid[vmhub] = false;
+
mutex_unlock(&id_mgr->lock);
}
@@ -578,6 +571,10 @@ void amdgpu_vmid_mgr_init(struct amdgpu_device *adev)
list_add_tail(&id_mgr->ids[j].list, &id_mgr->ids_lru);
}
}
+ /* alloc a default reserved vmid to enforce isolation */
+ if (enforce_isolation)
+ amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(0));
+
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
index d1cc09b45da4..fa8c42c83d5d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
@@ -79,11 +79,9 @@ void amdgpu_pasid_free_delayed(struct dma_resv *resv,
bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
struct amdgpu_vmid *id);
int amdgpu_vmid_alloc_reserved(struct amdgpu_device *adev,
- struct amdgpu_vm *vm,
- unsigned vmhub);
+ unsigned vmhub);
void amdgpu_vmid_free_reserved(struct amdgpu_device *adev,
- struct amdgpu_vm *vm,
- unsigned vmhub);
+ unsigned vmhub);
int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
struct amdgpu_job *job, struct dma_fence **fence);
void amdgpu_vmid_reset(struct amdgpu_device *adev, unsigned vmhub,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
index 1d5af50331e4..fceb3b384955 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
@@ -270,7 +270,7 @@ void amdgpu_ih_decode_iv_helper(struct amdgpu_device *adev,
entry->timestamp = dw[1] | ((u64)(dw[2] & 0xffff) << 32);
entry->timestamp_src = dw[2] >> 31;
entry->pasid = dw[3] & 0xffff;
- entry->pasid_src = dw[3] >> 31;
+ entry->node_id = (dw[3] >> 16) & 0xff;
entry->src_data[0] = dw[4];
entry->src_data[1] = dw[5];
entry->src_data[2] = dw[6];
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index fafebec5b7b6..5273decc5753 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -99,6 +99,21 @@ const char *soc15_ih_clientid_name[] = {
"MP1"
};
+const int node_id_to_phys_map[NODEID_MAX] = {
+ [AID0_NODEID] = 0,
+ [XCD0_NODEID] = 0,
+ [XCD1_NODEID] = 1,
+ [AID1_NODEID] = 1,
+ [XCD2_NODEID] = 2,
+ [XCD3_NODEID] = 3,
+ [AID2_NODEID] = 2,
+ [XCD4_NODEID] = 4,
+ [XCD5_NODEID] = 5,
+ [AID3_NODEID] = 3,
+ [XCD6_NODEID] = 6,
+ [XCD7_NODEID] = 7,
+};
+
/**
* amdgpu_irq_disable_all - disable *all* interrupts
*
@@ -109,7 +124,7 @@ const char *soc15_ih_clientid_name[] = {
void amdgpu_irq_disable_all(struct amdgpu_device *adev)
{
unsigned long irqflags;
- unsigned i, j, k;
+ unsigned int i, j, k;
int r;
spin_lock_irqsave(&adev->irq.lock, irqflags);
@@ -124,7 +139,6 @@ void amdgpu_irq_disable_all(struct amdgpu_device *adev)
continue;
for (k = 0; k < src->num_types; ++k) {
- atomic_set(&src->enabled_types[k], 0);
r = src->funcs->set(adev, src, k,
AMDGPU_IRQ_STATE_DISABLE);
if (r)
@@ -268,11 +282,11 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
int nvec = pci_msix_vec_count(adev->pdev);
unsigned int flags;
- if (nvec <= 0) {
+ if (nvec <= 0)
flags = PCI_IRQ_MSI;
- } else {
+ else
flags = PCI_IRQ_MSI | PCI_IRQ_MSIX;
- }
+
/* we only need one vector */
nvec = pci_alloc_irq_vectors(adev->pdev, 1, 1, flags);
if (nvec > 0) {
@@ -331,7 +345,7 @@ void amdgpu_irq_fini_hw(struct amdgpu_device *adev)
*/
void amdgpu_irq_fini_sw(struct amdgpu_device *adev)
{
- unsigned i, j;
+ unsigned int i, j;
for (i = 0; i < AMDGPU_IRQ_CLIENTID_MAX; ++i) {
if (!adev->irq.client[i].sources)
@@ -365,7 +379,7 @@ void amdgpu_irq_fini_sw(struct amdgpu_device *adev)
* 0 on success or error code otherwise
*/
int amdgpu_irq_add_id(struct amdgpu_device *adev,
- unsigned client_id, unsigned src_id,
+ unsigned int client_id, unsigned int src_id,
struct amdgpu_irq_src *source)
{
if (client_id >= AMDGPU_IRQ_CLIENTID_MAX)
@@ -417,7 +431,7 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
{
u32 ring_index = ih->rptr >> 2;
struct amdgpu_iv_entry entry;
- unsigned client_id, src_id;
+ unsigned int client_id, src_id;
struct amdgpu_irq_src *src;
bool handled = false;
int r;
@@ -453,7 +467,8 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
handled = true;
} else {
- DRM_DEBUG("Unhandled interrupt src_id: %d\n", src_id);
+ DRM_DEBUG("Unregistered interrupt src_id: %d of client_id:%d\n",
+ src_id, client_id);
}
/* Send it to amdkfd as well if it isn't already handled */
@@ -492,7 +507,7 @@ void amdgpu_irq_delegate(struct amdgpu_device *adev,
* Updates interrupt state for the specific source (all ASICs).
*/
int amdgpu_irq_update(struct amdgpu_device *adev,
- struct amdgpu_irq_src *src, unsigned type)
+ struct amdgpu_irq_src *src, unsigned int type)
{
unsigned long irqflags;
enum amdgpu_interrupt_state state;
@@ -501,7 +516,8 @@ int amdgpu_irq_update(struct amdgpu_device *adev,
spin_lock_irqsave(&adev->irq.lock, irqflags);
/* We need to determine after taking the lock, otherwise
- we might disable just enabled interrupts again */
+ * we might disable just enabled interrupts again
+ */
if (amdgpu_irq_enabled(adev, src, type))
state = AMDGPU_IRQ_STATE_ENABLE;
else
@@ -555,7 +571,7 @@ void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev)
* 0 on success or error code otherwise
*/
int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
- unsigned type)
+ unsigned int type)
{
if (!adev->irq.installed)
return -ENOENT;
@@ -585,7 +601,7 @@ int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
* 0 on success or error code otherwise
*/
int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
- unsigned type)
+ unsigned int type)
{
if (!adev->irq.installed)
return -ENOENT;
@@ -619,7 +635,7 @@ int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
* invalid parameters
*/
bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
- unsigned type)
+ unsigned int type)
{
if (!adev->irq.installed)
return false;
@@ -732,7 +748,7 @@ void amdgpu_irq_remove_domain(struct amdgpu_device *adev)
* Returns:
* Linux IRQ
*/
-unsigned amdgpu_irq_create_mapping(struct amdgpu_device *adev, unsigned src_id)
+unsigned int amdgpu_irq_create_mapping(struct amdgpu_device *adev, unsigned int src_id)
{
adev->irq.virq[src_id] = irq_create_mapping(adev->irq.domain, src_id);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
index be243adf3e65..04c0b4fa17a4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
@@ -53,7 +53,7 @@ struct amdgpu_iv_entry {
uint64_t timestamp;
unsigned timestamp_src;
unsigned pasid;
- unsigned pasid_src;
+ unsigned node_id;
unsigned src_data[AMDGPU_IRQ_SRC_DATA_MAX_SIZE_DW];
const uint32_t *iv_entry;
};
@@ -102,6 +102,24 @@ struct amdgpu_irq {
bool retry_cam_enabled;
};
+enum interrupt_node_id_per_aid {
+ AID0_NODEID = 0,
+ XCD0_NODEID = 1,
+ XCD1_NODEID = 2,
+ AID1_NODEID = 4,
+ XCD2_NODEID = 5,
+ XCD3_NODEID = 6,
+ AID2_NODEID = 8,
+ XCD4_NODEID = 9,
+ XCD5_NODEID = 10,
+ AID3_NODEID = 12,
+ XCD6_NODEID = 13,
+ XCD7_NODEID = 14,
+ NODEID_MAX,
+};
+
+extern const int node_id_to_phys_map[NODEID_MAX];
+
void amdgpu_irq_disable_all(struct amdgpu_device *adev);
int amdgpu_irq_init(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index c3d9d75143f4..78476bc75b4e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -65,6 +65,8 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
DRM_ERROR("Process information: process %s pid %d thread %s pid %d\n",
ti.process_name, ti.tgid, ti.task_name, ti.pid);
+ dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
+
if (amdgpu_device_should_recover_gpu(ring->adev)) {
struct amdgpu_reset_context reset_context;
memset(&reset_context, 0, sizeof(reset_context));
@@ -107,7 +109,7 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
(*job)->vm = vm;
amdgpu_sync_create(&(*job)->explicit_sync);
- (*job)->vram_lost_counter = atomic_read(&adev->vram_lost_counter);
+ (*job)->generation = amdgpu_vm_generation(adev, vm);
(*job)->vm_pd_addr = AMDGPU_BO_INVALID_OFFSET;
if (!entity)
@@ -256,16 +258,27 @@ amdgpu_job_prepare_job(struct drm_sched_job *sched_job,
struct dma_fence *fence = NULL;
int r;
+ /* Ignore soft recovered fences here */
+ r = drm_sched_entity_error(s_entity);
+ if (r && r != -ENODATA)
+ goto error;
+
if (!fence && job->gang_submit)
fence = amdgpu_device_switch_gang(ring->adev, job->gang_submit);
while (!fence && job->vm && !job->vmid) {
r = amdgpu_vmid_grab(job->vm, ring, job, &fence);
- if (r)
+ if (r) {
DRM_ERROR("Error getting VM ID (%d)\n", r);
+ goto error;
+ }
}
return fence;
+
+error:
+ dma_fence_set_error(&job->base.s_fence->finished, r);
+ return NULL;
}
static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job)
@@ -282,7 +295,7 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job)
trace_amdgpu_sched_run_job(job);
/* Skip job if VRAM is lost and never resubmit gangs */
- if (job->vram_lost_counter != atomic_read(&adev->vram_lost_counter) ||
+ if (job->generation != amdgpu_vm_generation(adev, job->vm) ||
(job->job_run_counter && job->gang_submit))
dma_fence_set_error(finished, -ECANCELED);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
index 52f2e313ea17..a963a25ddd62 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
@@ -61,12 +61,18 @@ struct amdgpu_job {
uint32_t gds_base, gds_size;
uint32_t gws_base, gws_size;
uint32_t oa_base, oa_size;
- uint32_t vram_lost_counter;
+ uint64_t generation;
/* user fence handling */
uint64_t uf_addr;
uint64_t uf_sequence;
+ /* virtual addresses for shadow/GDS/CSA */
+ uint64_t shadow_va;
+ uint64_t csa_va;
+ uint64_t gds_va;
+ bool init_shadow;
+
/* job_run_counter >= 1 means a resubmit job */
uint32_t job_run_counter;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
index 4fa019c8aefc..3add4b4f0667 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
@@ -45,13 +45,14 @@ int amdgpu_jpeg_sw_init(struct amdgpu_device *adev)
int amdgpu_jpeg_sw_fini(struct amdgpu_device *adev)
{
- int i;
+ int i, j;
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
if (adev->jpeg.harvest_config & (1 << i))
continue;
- amdgpu_ring_fini(&adev->jpeg.inst[i].ring_dec);
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j)
+ amdgpu_ring_fini(&adev->jpeg.inst[i].ring_dec[j]);
}
mutex_destroy(&adev->jpeg.jpeg_pg_lock);
@@ -76,13 +77,14 @@ static void amdgpu_jpeg_idle_work_handler(struct work_struct *work)
struct amdgpu_device *adev =
container_of(work, struct amdgpu_device, jpeg.idle_work.work);
unsigned int fences = 0;
- unsigned int i;
+ unsigned int i, j;
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
if (adev->jpeg.harvest_config & (1 << i))
continue;
- fences += amdgpu_fence_count_emitted(&adev->jpeg.inst[i].ring_dec);
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j)
+ fences += amdgpu_fence_count_emitted(&adev->jpeg.inst[i].ring_dec[j]);
}
if (!fences && !atomic_read(&adev->jpeg.total_submission_cnt))
@@ -122,18 +124,21 @@ int amdgpu_jpeg_dec_ring_test_ring(struct amdgpu_ring *ring)
if (amdgpu_sriov_vf(adev))
return 0;
- WREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch, 0xCAFEDEAD);
r = amdgpu_ring_alloc(ring, 3);
if (r)
return r;
- amdgpu_ring_write(ring, PACKET0(adev->jpeg.internal.jpeg_pitch, 0));
- amdgpu_ring_write(ring, 0xDEADBEEF);
+ WREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch[ring->pipe], 0xCAFEDEAD);
+ /* Add a read register to make sure the write register is executed. */
+ RREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch[ring->pipe]);
+
+ amdgpu_ring_write(ring, PACKET0(adev->jpeg.internal.jpeg_pitch[ring->pipe], 0));
+ amdgpu_ring_write(ring, 0xABADCAFE);
amdgpu_ring_commit(ring);
for (i = 0; i < adev->usec_timeout; i++) {
- tmp = RREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch);
- if (tmp == 0xDEADBEEF)
+ tmp = RREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch[ring->pipe]);
+ if (tmp == 0xABADCAFE)
break;
udelay(1);
}
@@ -161,8 +166,7 @@ static int amdgpu_jpeg_dec_set_reg(struct amdgpu_ring *ring, uint32_t handle,
ib = &job->ibs[0];
- ib->ptr[0] = PACKETJ(adev->jpeg.internal.jpeg_pitch, 0, 0,
- PACKETJ_TYPE0);
+ ib->ptr[0] = PACKETJ(adev->jpeg.internal.jpeg_pitch[ring->pipe], 0, 0, PACKETJ_TYPE0);
ib->ptr[1] = 0xDEADBEEF;
for (i = 2; i < 16; i += 2) {
ib->ptr[i] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);
@@ -208,7 +212,7 @@ int amdgpu_jpeg_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout)
}
if (!amdgpu_sriov_vf(adev)) {
for (i = 0; i < adev->usec_timeout; i++) {
- tmp = RREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch);
+ tmp = RREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch[ring->pipe]);
if (tmp == 0xDEADBEEF)
break;
udelay(1);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
index 1471a1ebb034..ffe47e9f5bf2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
@@ -26,20 +26,22 @@
#include "amdgpu_ras.h"
-#define AMDGPU_MAX_JPEG_INSTANCES 2
+#define AMDGPU_MAX_JPEG_INSTANCES 4
+#define AMDGPU_MAX_JPEG_RINGS 8
#define AMDGPU_JPEG_HARVEST_JPEG0 (1 << 0)
#define AMDGPU_JPEG_HARVEST_JPEG1 (1 << 1)
struct amdgpu_jpeg_reg{
- unsigned jpeg_pitch;
+ unsigned jpeg_pitch[AMDGPU_MAX_JPEG_RINGS];
};
struct amdgpu_jpeg_inst {
- struct amdgpu_ring ring_dec;
+ struct amdgpu_ring ring_dec[AMDGPU_MAX_JPEG_RINGS];
struct amdgpu_irq_src irq;
struct amdgpu_irq_src ras_poison_irq;
struct amdgpu_jpeg_reg external;
+ uint8_t aid_id;
};
struct amdgpu_jpeg_ras {
@@ -49,6 +51,7 @@ struct amdgpu_jpeg_ras {
struct amdgpu_jpeg {
uint8_t num_jpeg_inst;
struct amdgpu_jpeg_inst inst[AMDGPU_MAX_JPEG_INSTANCES];
+ unsigned num_jpeg_rings;
struct amdgpu_jpeg_reg internal;
unsigned harvest_config;
struct delayed_work idle_work;
@@ -57,6 +60,9 @@ struct amdgpu_jpeg {
atomic_t total_submission_cnt;
struct ras_common_if *ras_if;
struct amdgpu_jpeg_ras *ras;
+
+ uint16_t inst_mask;
+ uint8_t num_inst_per_aid;
};
int amdgpu_jpeg_sw_init(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 0efb38539d70..e3531aa3c8bd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -462,8 +462,9 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
if (adev->jpeg.harvest_config & (1 << i))
continue;
- if (adev->jpeg.inst[i].ring_dec.sched.ready)
- ++num_rings;
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; j++)
+ if (adev->jpeg.inst[i].ring_dec[j].sched.ready)
+ ++num_rings;
}
ib_start_alignment = 16;
ib_size_alignment = 16;
@@ -876,6 +877,19 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
dev_info->gl2c_cache_size = adev->gfx.config.gc_gl2c_per_gpu;
dev_info->mall_size = adev->gmc.mall_size;
+
+ if (adev->gfx.funcs->get_gfx_shadow_info) {
+ struct amdgpu_gfx_shadow_info shadow_info;
+
+ ret = amdgpu_gfx_get_gfx_shadow_info(adev, &shadow_info);
+ if (!ret) {
+ dev_info->shadow_size = shadow_info.shadow_size;
+ dev_info->shadow_alignment = shadow_info.shadow_alignment;
+ dev_info->csa_size = shadow_info.csa_size;
+ dev_info->csa_alignment = shadow_info.csa_alignment;
+ }
+ }
+
ret = copy_to_user(out, dev_info,
min((size_t)size, sizeof(*dev_info))) ? -EFAULT : 0;
kfree(dev_info);
@@ -1140,6 +1154,15 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
kfree(caps);
return r;
}
+ case AMDGPU_INFO_MAX_IBS: {
+ uint32_t max_ibs[AMDGPU_HW_IP_NUM];
+
+ for (i = 0; i < AMDGPU_HW_IP_NUM; ++i)
+ max_ibs[i] = amdgpu_ring_max_ibs(i);
+
+ return copy_to_user(out, max_ibs,
+ min((size_t)size, sizeof(max_ibs))) ? -EFAULT : 0;
+ }
default:
DRM_DEBUG_KMS("Invalid request %d\n", info->query);
return -EINVAL;
@@ -1210,6 +1233,10 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
if (r)
goto error_pasid;
+ r = amdgpu_xcp_open_device(adev, fpriv, file_priv);
+ if (r)
+ goto error_vm;
+
r = amdgpu_vm_set_pasid(adev, &fpriv->vm, pasid);
if (r)
goto error_vm;
@@ -1284,12 +1311,12 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCE) != NULL)
amdgpu_vce_free_handles(adev, file_priv);
- if (amdgpu_mcbp) {
- /* TODO: how to handle reserve failure */
- BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, true));
- amdgpu_vm_bo_del(adev, fpriv->csa_va);
+ if (fpriv->csa_va) {
+ uint64_t csa_addr = amdgpu_csa_vaddr(adev) & AMDGPU_GMC_HOLE_MASK;
+
+ WARN_ON(amdgpu_unmap_static_csa(adev, &fpriv->vm, adev->virt.csa_obj,
+ fpriv->csa_va, csa_addr));
fpriv->csa_va = NULL;
- amdgpu_bo_unreserve(adev->virt.csa_obj);
}
pasid = fpriv->vm.pasid;
@@ -1441,7 +1468,7 @@ void amdgpu_disable_vblank_kms(struct drm_crtc *crtc)
static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused)
{
- struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
+ struct amdgpu_device *adev = m->private;
struct drm_amdgpu_info_firmware fw_info;
struct drm_amdgpu_query_fw query_fw;
struct atom_context *ctx = adev->mode_info.atom_context;
@@ -1449,7 +1476,7 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused)
int ret, i;
static const char *ta_fw_name[TA_FW_TYPE_MAX_INDEX] = {
-#define TA_FW_NAME(type) [TA_FW_TYPE_PSP_##type] = #type
+#define TA_FW_NAME(type)[TA_FW_TYPE_PSP_##type] = #type
TA_FW_NAME(XGMI),
TA_FW_NAME(RAS),
TA_FW_NAME(HDCP),
@@ -1548,7 +1575,7 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused)
fw_info.feature, fw_info.ver);
/* RLCV */
- query_fw.fw_type = AMDGPU_INFO_FW_GFX_RLCV;
+ query_fw.fw_type = AMDGPU_INFO_FW_GFX_RLCV;
ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
index f0f00466b59f..e9091ebfe230 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
@@ -924,6 +924,43 @@ error:
return r;
}
+int amdgpu_mes_set_shader_debugger(struct amdgpu_device *adev,
+ uint64_t process_context_addr,
+ uint32_t spi_gdbg_per_vmid_cntl,
+ const uint32_t *tcp_watch_cntl,
+ uint32_t flags,
+ bool trap_en)
+{
+ struct mes_misc_op_input op_input = {0};
+ int r;
+
+ if (!adev->mes.funcs->misc_op) {
+ DRM_ERROR("mes set shader debugger is not supported!\n");
+ return -EINVAL;
+ }
+
+ op_input.op = MES_MISC_OP_SET_SHADER_DEBUGGER;
+ op_input.set_shader_debugger.process_context_addr = process_context_addr;
+ op_input.set_shader_debugger.flags.u32all = flags;
+ op_input.set_shader_debugger.spi_gdbg_per_vmid_cntl = spi_gdbg_per_vmid_cntl;
+ memcpy(op_input.set_shader_debugger.tcp_watch_cntl, tcp_watch_cntl,
+ sizeof(op_input.set_shader_debugger.tcp_watch_cntl));
+
+ if (((adev->mes.sched_version & AMDGPU_MES_API_VERSION_MASK) >>
+ AMDGPU_MES_API_VERSION_SHIFT) >= 14)
+ op_input.set_shader_debugger.trap_en = trap_en;
+
+ amdgpu_mes_lock(&adev->mes);
+
+ r = adev->mes.funcs->misc_op(&adev->mes, &op_input);
+ if (r)
+ DRM_ERROR("failed to set_shader_debugger\n");
+
+ amdgpu_mes_unlock(&adev->mes);
+
+ return r;
+}
+
static void
amdgpu_mes_ring_to_queue_props(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
@@ -1305,14 +1342,9 @@ static int amdgpu_mes_test_queues(struct amdgpu_ring **added_rings)
if (!ring)
continue;
- r = amdgpu_ring_test_ring(ring);
- if (r) {
- DRM_DEV_ERROR(ring->adev->dev,
- "ring %s test failed (%d)\n",
- ring->name, r);
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
return r;
- } else
- DRM_INFO("ring %s test pass\n", ring->name);
r = amdgpu_ring_test_ib(ring, 1000 * 10);
if (r) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
index 547ec35691fa..2d6ac30b7135 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
@@ -219,6 +219,8 @@ struct mes_add_queue_input {
uint32_t gws_size;
uint64_t tba_addr;
uint64_t tma_addr;
+ uint32_t trap_en;
+ uint32_t skip_process_ctx_clear;
uint32_t is_kfd_process;
uint32_t is_aql_queue;
uint32_t queue_size;
@@ -256,6 +258,7 @@ enum mes_misc_opcode {
MES_MISC_OP_READ_REG,
MES_MISC_OP_WRM_REG_WAIT,
MES_MISC_OP_WRM_REG_WR_WAIT,
+ MES_MISC_OP_SET_SHADER_DEBUGGER,
};
struct mes_misc_op_input {
@@ -278,6 +281,21 @@ struct mes_misc_op_input {
uint32_t reg0;
uint32_t reg1;
} wrm_reg;
+
+ struct {
+ uint64_t process_context_addr;
+ union {
+ struct {
+ uint64_t single_memop : 1;
+ uint64_t single_alu_op : 1;
+ uint64_t reserved: 30;
+ };
+ uint32_t u32all;
+ } flags;
+ uint32_t spi_gdbg_per_vmid_cntl;
+ uint32_t tcp_watch_cntl[4];
+ uint32_t trap_en;
+ } set_shader_debugger;
};
};
@@ -340,6 +358,12 @@ int amdgpu_mes_reg_wait(struct amdgpu_device *adev, uint32_t reg,
int amdgpu_mes_reg_write_reg_wait(struct amdgpu_device *adev,
uint32_t reg0, uint32_t reg1,
uint32_t ref, uint32_t mask);
+int amdgpu_mes_set_shader_debugger(struct amdgpu_device *adev,
+ uint64_t process_context_addr,
+ uint32_t spi_gdbg_per_vmid_cntl,
+ const uint32_t *tcp_watch_cntl,
+ uint32_t flags,
+ bool trap_en);
int amdgpu_mes_add_ring(struct amdgpu_device *adev, int gang_id,
int queue_type, int idx,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h
index d21bb6dae56e..1ca9d4ed8063 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h
@@ -21,6 +21,29 @@
#ifndef __AMDGPU_MMHUB_H__
#define __AMDGPU_MMHUB_H__
+enum amdgpu_mmhub_ras_memory_id {
+ AMDGPU_MMHUB_WGMI_PAGEMEM = 0,
+ AMDGPU_MMHUB_RGMI_PAGEMEM = 1,
+ AMDGPU_MMHUB_WDRAM_PAGEMEM = 2,
+ AMDGPU_MMHUB_RDRAM_PAGEMEM = 3,
+ AMDGPU_MMHUB_WIO_CMDMEM = 4,
+ AMDGPU_MMHUB_RIO_CMDMEM = 5,
+ AMDGPU_MMHUB_WGMI_CMDMEM = 6,
+ AMDGPU_MMHUB_RGMI_CMDMEM = 7,
+ AMDGPU_MMHUB_WDRAM_CMDMEM = 8,
+ AMDGPU_MMHUB_RDRAM_CMDMEM = 9,
+ AMDGPU_MMHUB_MAM_DMEM0 = 10,
+ AMDGPU_MMHUB_MAM_DMEM1 = 11,
+ AMDGPU_MMHUB_MAM_DMEM2 = 12,
+ AMDGPU_MMHUB_MAM_DMEM3 = 13,
+ AMDGPU_MMHUB_WRET_TAGMEM = 19,
+ AMDGPU_MMHUB_RRET_TAGMEM = 20,
+ AMDGPU_MMHUB_WIO_DATAMEM = 21,
+ AMDGPU_MMHUB_WGMI_DATAMEM = 22,
+ AMDGPU_MMHUB_WDRAM_DATAMEM = 23,
+ AMDGPU_MMHUB_MEMORY_BLOCK_LAST,
+};
+
struct amdgpu_mmhub_ras {
struct amdgpu_ras_block_object ras_block;
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
index c686ff4bcc39..8ab8ae01f87c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
@@ -61,6 +61,7 @@ struct amdgpu_nbio_funcs {
u32 (*get_hdp_flush_done_offset)(struct amdgpu_device *adev);
u32 (*get_pcie_index_offset)(struct amdgpu_device *adev);
u32 (*get_pcie_data_offset)(struct amdgpu_device *adev);
+ u32 (*get_pcie_index_hi_offset)(struct amdgpu_device *adev);
u32 (*get_pcie_port_index_offset)(struct amdgpu_device *adev);
u32 (*get_pcie_port_data_offset)(struct amdgpu_device *adev);
u32 (*get_rev_id)(struct amdgpu_device *adev);
@@ -95,6 +96,9 @@ struct amdgpu_nbio_funcs {
void (*apply_l1_link_width_reconfig_wa)(struct amdgpu_device *adev);
void (*clear_doorbell_interrupt)(struct amdgpu_device *adev);
u32 (*get_rom_offset)(struct amdgpu_device *adev);
+ int (*get_compute_partition_mode)(struct amdgpu_device *adev);
+ u32 (*get_memory_partition_mode)(struct amdgpu_device *adev,
+ u32 *supp_modes);
};
struct amdgpu_nbio {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index a70103ac0026..f7905bce0de1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -131,15 +131,25 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
u32 c = 0;
if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
- unsigned visible_pfn = adev->gmc.visible_vram_size >> PAGE_SHIFT;
-
- places[c].fpfn = 0;
- places[c].lpfn = 0;
+ unsigned int visible_pfn = adev->gmc.visible_vram_size >> PAGE_SHIFT;
+ int8_t mem_id = KFD_XCP_MEM_ID(adev, abo->xcp_id);
+
+ if (adev->gmc.mem_partitions && mem_id >= 0) {
+ places[c].fpfn = adev->gmc.mem_partitions[mem_id].range.fpfn;
+ /*
+ * memory partition range lpfn is inclusive start + size - 1
+ * TTM place lpfn is exclusive start + size
+ */
+ places[c].lpfn = adev->gmc.mem_partitions[mem_id].range.lpfn + 1;
+ } else {
+ places[c].fpfn = 0;
+ places[c].lpfn = 0;
+ }
places[c].mem_type = TTM_PL_VRAM;
places[c].flags = 0;
if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
- places[c].lpfn = visible_pfn;
+ places[c].lpfn = min_not_zero(places[c].lpfn, visible_pfn);
else
places[c].flags |= TTM_PL_FLAG_TOPDOWN;
@@ -575,6 +585,13 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
bo->flags = bp->flags;
+ if (adev->gmc.mem_partitions)
+ /* For GPUs with spatial partitioning, bo->xcp_id=-1 means any partition */
+ bo->xcp_id = bp->xcp_id_plus1 - 1;
+ else
+ /* For GPUs without spatial partitioning */
+ bo->xcp_id = 0;
+
if (!amdgpu_bo_support_uswc(bo->flags))
bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
@@ -611,7 +628,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
bo->tbo.resource->mem_type == TTM_PL_VRAM) {
struct dma_fence *fence;
- r = amdgpu_fill_buffer(bo, 0, bo->tbo.base.resv, &fence);
+ r = amdgpu_fill_buffer(bo, 0, bo->tbo.base.resv, &fence, true);
if (unlikely(r))
goto fail_unreserve;
@@ -933,7 +950,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
amdgpu_bo_placement_from_domain(bo, domain);
for (i = 0; i < bo->placement.num_placement; i++) {
- unsigned fpfn, lpfn;
+ unsigned int fpfn, lpfn;
fpfn = min_offset >> PAGE_SHIFT;
lpfn = max_offset >> PAGE_SHIFT;
@@ -1014,7 +1031,7 @@ void amdgpu_bo_unpin(struct amdgpu_bo *bo)
}
}
-static const char *amdgpu_vram_names[] = {
+static const char * const amdgpu_vram_names[] = {
"UNKNOWN",
"GDDR1",
"DDR2",
@@ -1042,7 +1059,7 @@ static const char *amdgpu_vram_names[] = {
int amdgpu_bo_init(struct amdgpu_device *adev)
{
/* On A+A platform, VRAM can be mapped as WB */
- if (!adev->gmc.xgmi.connected_to_cpu) {
+ if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) {
/* reserve PAT memory space to WC for VRAM */
int r = arch_io_reserve_memtype_wc(adev->gmc.aper_base,
adev->gmc.aper_size);
@@ -1078,8 +1095,7 @@ void amdgpu_bo_fini(struct amdgpu_device *adev)
amdgpu_ttm_fini(adev);
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
-
- if (!adev->gmc.xgmi.connected_to_cpu) {
+ if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) {
arch_phys_wc_del(adev->gmc.vram_mtrr);
arch_io_free_memtype_wc(adev->gmc.aper_base, adev->gmc.aper_size);
}
@@ -1146,8 +1162,8 @@ void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags)
* Returns:
* 0 for success or a negative error code on failure.
*/
-int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata,
- uint32_t metadata_size, uint64_t flags)
+int amdgpu_bo_set_metadata(struct amdgpu_bo *bo, void *metadata,
+ u32 metadata_size, uint64_t flags)
{
struct amdgpu_bo_user *ubo;
void *buffer;
@@ -1266,8 +1282,12 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
void amdgpu_bo_get_memory(struct amdgpu_bo *bo,
struct amdgpu_mem_stats *stats)
{
- unsigned int domain;
uint64_t size = amdgpu_bo_size(bo);
+ unsigned int domain;
+
+ /* Abort if the BO doesn't currently have a backing store */
+ if (!bo->tbo.resource)
+ return;
domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type);
switch (domain) {
@@ -1336,7 +1356,7 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv)))
return;
- r = amdgpu_fill_buffer(abo, AMDGPU_POISON, bo->base.resv, &fence);
+ r = amdgpu_fill_buffer(abo, AMDGPU_POISON, bo->base.resv, &fence, true);
if (!WARN_ON(r)) {
amdgpu_bo_fence(abo, fence, false);
dma_fence_put(fence);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index 35b8106816a1..05496b97ef93 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -56,6 +56,8 @@ struct amdgpu_bo_param {
bool no_wait_gpu;
struct dma_resv *resv;
void (*destroy)(struct ttm_buffer_object *bo);
+ /* xcp partition number plus 1, 0 means any partition */
+ int8_t xcp_id_plus1;
};
/* bo virtual addresses in a vm */
@@ -108,6 +110,13 @@ struct amdgpu_bo {
struct mmu_interval_notifier notifier;
#endif
struct kgd_mem *kfd_bo;
+
+ /*
+ * For GPUs with spatial partitioning, xcp partition number, -1 means
+ * any partition. For other ASICs without spatial partition, always 0
+ * for memory accounting.
+ */
+ int8_t xcp_id;
};
struct amdgpu_bo_user {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index a150b7a4b4aa..e15c27e05564 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -146,6 +146,9 @@ static int psp_init_sriov_microcode(struct psp_context *psp)
case IP_VERSION(13, 0, 0):
adev->virt.autoload_ucode_id = 0;
break;
+ case IP_VERSION(13, 0, 6):
+ ret = psp_init_cap_microcode(psp, ucode_prefix);
+ break;
case IP_VERSION(13, 0, 10):
adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MES1_DATA;
ret = psp_init_cap_microcode(psp, ucode_prefix);
@@ -329,6 +332,9 @@ static bool psp_get_runtime_db_entry(struct amdgpu_device *adev,
bool ret = false;
int i;
+ if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 6))
+ return false;
+
db_header_pos = adev->gmc.mc_vram_size - PSP_RUNTIME_DB_OFFSET;
db_dir_pos = db_header_pos + sizeof(struct psp_runtime_data_header);
@@ -411,7 +417,7 @@ static int psp_sw_init(void *handle)
if ((psp_get_runtime_db_entry(adev,
PSP_RUNTIME_ENTRY_TYPE_PPTABLE_ERR_STATUS,
&scpm_entry)) &&
- (SCPM_DISABLE != scpm_entry.scpm_status)) {
+ (scpm_entry.scpm_status != SCPM_DISABLE)) {
adev->scpm_enabled = true;
adev->scpm_status = scpm_entry.scpm_status;
} else {
@@ -458,10 +464,9 @@ static int psp_sw_init(void *handle)
if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 0) ||
adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 7)) {
- ret= psp_sysfs_init(adev);
- if (ret) {
+ ret = psp_sysfs_init(adev);
+ if (ret)
return ret;
- }
}
ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG,
@@ -474,7 +479,8 @@ static int psp_sw_init(void *handle)
return ret;
ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
+ AMDGPU_GEM_DOMAIN_VRAM |
+ AMDGPU_GEM_DOMAIN_GTT,
&psp->fence_buf_bo,
&psp->fence_buf_mc_addr,
&psp->fence_buf);
@@ -482,7 +488,8 @@ static int psp_sw_init(void *handle)
goto failed1;
ret = amdgpu_bo_create_kernel(adev, PSP_CMD_BUFFER_SIZE, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
+ AMDGPU_GEM_DOMAIN_VRAM |
+ AMDGPU_GEM_DOMAIN_GTT,
&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr,
(void **)&psp->cmd_buf_mem);
if (ret)
@@ -520,6 +527,8 @@ static int psp_sw_fini(void *handle)
kfree(cmd);
cmd = NULL;
+ psp_free_shared_bufs(psp);
+
if (psp->km_ring.ring_mem)
amdgpu_bo_free_kernel(&adev->firmware.rbuf,
&psp->km_ring.ring_mem_mc_addr,
@@ -560,6 +569,26 @@ int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
return -ETIME;
}
+int psp_wait_for_spirom_update(struct psp_context *psp, uint32_t reg_index,
+ uint32_t reg_val, uint32_t mask, uint32_t msec_timeout)
+{
+ uint32_t val;
+ int i;
+ struct amdgpu_device *adev = psp->adev;
+
+ if (psp->adev->no_hw_access)
+ return 0;
+
+ for (i = 0; i < msec_timeout; i++) {
+ val = RREG32(reg_index);
+ if ((val & mask) == reg_val)
+ return 0;
+ msleep(1);
+ }
+
+ return -ETIME;
+}
+
static const char *psp_gfx_cmd_name(enum psp_gfx_cmd_id cmd_id)
{
switch (cmd_id) {
@@ -643,7 +672,7 @@ psp_cmd_submit_buf(struct psp_context *psp,
skip_unsupport = (psp->cmd_buf_mem->resp.status == TEE_ERROR_NOT_SUPPORTED ||
psp->cmd_buf_mem->resp.status == PSP_ERR_UNKNOWN_COMMAND) && amdgpu_sriov_vf(psp->adev);
- memcpy((void*)&cmd->resp, (void*)&psp->cmd_buf_mem->resp, sizeof(struct psp_gfx_resp));
+ memcpy(&cmd->resp, &psp->cmd_buf_mem->resp, sizeof(struct psp_gfx_resp));
/* In some cases, psp response status is not 0 even there is no
* problem while the command is submitted. Some version of PSP FW
@@ -699,8 +728,13 @@ static void psp_prep_tmr_cmd_buf(struct psp_context *psp,
uint64_t tmr_mc, struct amdgpu_bo *tmr_bo)
{
struct amdgpu_device *adev = psp->adev;
- uint32_t size = amdgpu_bo_size(tmr_bo);
- uint64_t tmr_pa = amdgpu_gmc_vram_pa(adev, tmr_bo);
+ uint32_t size = 0;
+ uint64_t tmr_pa = 0;
+
+ if (tmr_bo) {
+ size = amdgpu_bo_size(tmr_bo);
+ tmr_pa = amdgpu_gmc_vram_pa(adev, tmr_bo);
+ }
if (amdgpu_sriov_vf(psp->adev))
cmd->cmd_id = GFX_CMD_ID_SETUP_VMR;
@@ -745,6 +779,16 @@ static int psp_load_toc(struct psp_context *psp,
return ret;
}
+static bool psp_boottime_tmr(struct psp_context *psp)
+{
+ switch (psp->adev->ip_versions[MP0_HWIP][0]) {
+ case IP_VERSION(13, 0, 6):
+ return true;
+ default:
+ return false;
+ }
+}
+
/* Set up Trusted Memory Region */
static int psp_tmr_init(struct psp_context *psp)
{
@@ -816,8 +860,9 @@ static int psp_tmr_load(struct psp_context *psp)
cmd = acquire_psp_cmd_buf(psp);
psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr, psp->tmr_bo);
- DRM_INFO("reserve 0x%lx from 0x%llx for PSP TMR\n",
- amdgpu_bo_size(psp->tmr_bo), psp->tmr_mc_addr);
+ if (psp->tmr_bo)
+ DRM_INFO("reserve 0x%lx from 0x%llx for PSP TMR\n",
+ amdgpu_bo_size(psp->tmr_bo), psp->tmr_mc_addr);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
@@ -828,7 +873,7 @@ static int psp_tmr_load(struct psp_context *psp)
}
static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp,
- struct psp_gfx_cmd_resp *cmd)
+ struct psp_gfx_cmd_resp *cmd)
{
if (amdgpu_sriov_vf(psp->adev))
cmd->cmd_id = GFX_CMD_ID_DESTROY_VMR;
@@ -969,6 +1014,27 @@ static int psp_rl_load(struct amdgpu_device *adev)
return ret;
}
+int psp_spatial_partition(struct psp_context *psp, int mode)
+{
+ struct psp_gfx_cmd_resp *cmd;
+ int ret;
+
+ if (amdgpu_sriov_vf(psp->adev))
+ return 0;
+
+ cmd = acquire_psp_cmd_buf(psp);
+
+ cmd->cmd_id = GFX_CMD_ID_SRIOV_SPATIAL_PART;
+ cmd->cmd.cmd_spatial_part.mode = mode;
+
+ dev_info(psp->adev->dev, "Requesting %d partitions through PSP", mode);
+ ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+
+ release_psp_cmd_buf(psp);
+
+ return ret;
+}
+
static int psp_asd_initialize(struct psp_context *psp)
{
int ret;
@@ -1065,7 +1131,7 @@ static void psp_prep_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
struct ta_context *context)
{
cmd->cmd_id = context->ta_load_type;
- cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(ta_bin_mc);
+ cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(ta_bin_mc);
cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(ta_bin_mc);
cmd->cmd.cmd_load_ta.app_len = context->bin_desc.size_bytes;
@@ -1136,9 +1202,8 @@ int psp_ta_load(struct psp_context *psp, struct ta_context *context)
context->resp_status = cmd->resp.status;
- if (!ret) {
+ if (!ret)
context->session_id = cmd->resp.session_id;
- }
release_psp_cmd_buf(psp);
@@ -1254,8 +1319,9 @@ int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id)
static bool psp_xgmi_peer_link_info_supported(struct psp_context *psp)
{
- return psp->adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2) &&
- psp->xgmi_context.context.bin_desc.fw_version >= 0x2000000b;
+ return (psp->adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2) &&
+ psp->xgmi_context.context.bin_desc.fw_version >= 0x2000000b) ||
+ psp->adev->ip_versions[MP0_HWIP][0] >= IP_VERSION(13, 0, 6);
}
/*
@@ -1363,6 +1429,9 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
/* Invoke xgmi ta again to get the link information */
if (psp_xgmi_peer_link_info_supported(psp)) {
struct ta_xgmi_cmd_get_peer_link_info_output *link_info_output;
+ bool requires_reflection =
+ (psp->xgmi_context.supports_extended_data && get_extended_data) ||
+ psp->adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 6);
xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_PEER_LINKS;
@@ -1377,11 +1446,11 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
topology->nodes[i].num_links = get_extended_data ?
topology->nodes[i].num_links +
link_info_output->nodes[i].num_links :
- link_info_output->nodes[i].num_links;
+ ((requires_reflection && topology->nodes[i].num_links) ? topology->nodes[i].num_links :
+ link_info_output->nodes[i].num_links);
/* reflect the topology information for bi-directionality */
- if (psp->xgmi_context.supports_extended_data &&
- get_extended_data && topology->nodes[i].num_hops)
+ if (requires_reflection && topology->nodes[i].num_hops)
psp_xgmi_reflect_topology_info(psp, topology->nodes[i]);
}
}
@@ -1465,8 +1534,7 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
if (amdgpu_ras_intr_triggered())
return ret;
- if (ras_cmd->if_version > RAS_TA_HOST_IF_VER)
- {
+ if (ras_cmd->if_version > RAS_TA_HOST_IF_VER) {
DRM_WARN("RAS: Unsupported Interface");
return -EINVAL;
}
@@ -1476,8 +1544,7 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
dev_warn(psp->adev->dev, "ECC switch disabled\n");
ras_cmd->ras_status = TA_RAS_STATUS__ERROR_RAS_NOT_AVAILABLE;
- }
- else if (ras_cmd->ras_out_message.flags.reg_access_failure_flag)
+ } else if (ras_cmd->ras_out_message.flags.reg_access_failure_flag)
dev_warn(psp->adev->dev,
"RAS internal register access blocked\n");
@@ -1573,11 +1640,10 @@ int psp_ras_initialize(struct psp_context *psp)
if (ret)
dev_warn(adev->dev, "PSP set boot config failed\n");
else
- dev_warn(adev->dev, "GECC will be disabled in next boot cycle "
- "if set amdgpu_ras_enable and/or amdgpu_ras_mask to 0x0\n");
+ dev_warn(adev->dev, "GECC will be disabled in next boot cycle if set amdgpu_ras_enable and/or amdgpu_ras_mask to 0x0\n");
}
} else {
- if (1 == boot_cfg) {
+ if (boot_cfg == 1) {
dev_info(adev->dev, "GECC is enabled\n");
} else {
/* enable GECC in next boot cycle if it is disabled
@@ -1607,8 +1673,11 @@ int psp_ras_initialize(struct psp_context *psp)
if (amdgpu_ras_is_poison_mode_supported(adev))
ras_cmd->ras_in_message.init_flags.poison_mode_en = 1;
- if (!adev->gmc.xgmi.connected_to_cpu)
+ if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu)
ras_cmd->ras_in_message.init_flags.dgpu_mode = 1;
+ ras_cmd->ras_in_message.init_flags.xcc_mask =
+ adev->gfx.xcc_mask;
+ ras_cmd->ras_in_message.init_flags.channel_dis_num = hweight32(adev->gmc.m_half_use) * 2;
ret = psp_ta_load(psp, &psp->ras_context.context);
@@ -1626,14 +1695,37 @@ int psp_ras_initialize(struct psp_context *psp)
}
int psp_ras_trigger_error(struct psp_context *psp,
- struct ta_ras_trigger_error_input *info)
+ struct ta_ras_trigger_error_input *info, uint32_t instance_mask)
{
struct ta_ras_shared_memory *ras_cmd;
+ struct amdgpu_device *adev = psp->adev;
int ret;
+ uint32_t dev_mask;
if (!psp->ras_context.context.initialized)
return -EINVAL;
+ switch (info->block_id) {
+ case TA_RAS_BLOCK__GFX:
+ dev_mask = GET_MASK(GC, instance_mask);
+ break;
+ case TA_RAS_BLOCK__SDMA:
+ dev_mask = GET_MASK(SDMA0, instance_mask);
+ break;
+ case TA_RAS_BLOCK__VCN:
+ case TA_RAS_BLOCK__JPEG:
+ dev_mask = GET_MASK(VCN, instance_mask);
+ break;
+ default:
+ dev_mask = instance_mask;
+ break;
+ }
+
+ /* reuse sub_block_index for backward compatibility */
+ dev_mask <<= AMDGPU_RAS_INST_SHIFT;
+ dev_mask &= AMDGPU_RAS_INST_MASK;
+ info->sub_block_index |= dev_mask;
+
ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory));
@@ -2077,10 +2169,12 @@ static int psp_hw_start(struct psp_context *psp)
if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev))
goto skip_pin_bo;
- ret = psp_tmr_init(psp);
- if (ret) {
- DRM_ERROR("PSP tmr init failed!\n");
- return ret;
+ if (!psp_boottime_tmr(psp)) {
+ ret = psp_tmr_init(psp);
+ if (ret) {
+ DRM_ERROR("PSP tmr init failed!\n");
+ return ret;
+ }
}
skip_pin_bo:
@@ -2363,7 +2457,7 @@ static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode,
}
static int psp_execute_non_psp_fw_load(struct psp_context *psp,
- struct amdgpu_firmware_info *ucode)
+ struct amdgpu_firmware_info *ucode)
{
int ret = 0;
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
@@ -2402,9 +2496,8 @@ static int psp_load_smu_fw(struct psp_context *psp)
(adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 4) ||
adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 2)))) {
ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD);
- if (ret) {
+ if (ret)
DRM_WARN("Failed to set MP1 state prepare for reload\n");
- }
}
ret = psp_execute_non_psp_fw_load(psp, ucode);
@@ -2655,8 +2748,6 @@ static int psp_hw_fini(void *handle)
psp_ring_destroy(psp, PSP_RING_TYPE__KM);
- psp_free_shared_bufs(psp);
-
return 0;
}
@@ -2716,9 +2807,8 @@ static int psp_suspend(void *handle)
}
ret = psp_ring_stop(psp, PSP_RING_TYPE__KM);
- if (ret) {
+ if (ret)
DRM_ERROR("PSP ring stop failed\n");
- }
out:
return ret;
@@ -2967,7 +3057,7 @@ static int parse_sos_bin_descriptor(struct psp_context *psp,
psp->sos.fw_version = le32_to_cpu(desc->fw_version);
psp->sos.feature_version = le32_to_cpu(desc->fw_version);
psp->sos.size_bytes = le32_to_cpu(desc->size_bytes);
- psp->sos.start_addr = ucode_start_addr;
+ psp->sos.start_addr = ucode_start_addr;
break;
case PSP_FW_TYPE_PSP_SYS_DRV:
psp->sys.fw_version = le32_to_cpu(desc->fw_version);
@@ -3491,7 +3581,7 @@ void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size
drm_dev_exit(idx);
}
-static DEVICE_ATTR(usbc_pd_fw, S_IRUGO | S_IWUSR,
+static DEVICE_ATTR(usbc_pd_fw, 0644,
psp_usbc_pd_fw_sysfs_read,
psp_usbc_pd_fw_sysfs_write);
@@ -3621,6 +3711,7 @@ int amdgpu_psp_sysfs_init(struct amdgpu_device *adev)
switch (adev->ip_versions[MP0_HWIP][0]) {
case IP_VERSION(13, 0, 0):
case IP_VERSION(13, 0, 7):
+ case IP_VERSION(13, 0, 10):
if (!psp->adev) {
psp->adev = adev;
psp_v13_0_set_psp_funcs(psp);
@@ -3676,8 +3767,7 @@ static void psp_sysfs_fini(struct amdgpu_device *adev)
device_remove_file(adev->dev, &dev_attr_usbc_pd_fw);
}
-const struct amdgpu_ip_block_version psp_v3_1_ip_block =
-{
+const struct amdgpu_ip_block_version psp_v3_1_ip_block = {
.type = AMD_IP_BLOCK_TYPE_PSP,
.major = 3,
.minor = 1,
@@ -3685,8 +3775,7 @@ const struct amdgpu_ip_block_version psp_v3_1_ip_block =
.funcs = &psp_ip_funcs,
};
-const struct amdgpu_ip_block_version psp_v10_0_ip_block =
-{
+const struct amdgpu_ip_block_version psp_v10_0_ip_block = {
.type = AMD_IP_BLOCK_TYPE_PSP,
.major = 10,
.minor = 0,
@@ -3694,8 +3783,7 @@ const struct amdgpu_ip_block_version psp_v10_0_ip_block =
.funcs = &psp_ip_funcs,
};
-const struct amdgpu_ip_block_version psp_v11_0_ip_block =
-{
+const struct amdgpu_ip_block_version psp_v11_0_ip_block = {
.type = AMD_IP_BLOCK_TYPE_PSP,
.major = 11,
.minor = 0,
@@ -3711,8 +3799,7 @@ const struct amdgpu_ip_block_version psp_v11_0_8_ip_block = {
.funcs = &psp_ip_funcs,
};
-const struct amdgpu_ip_block_version psp_v12_0_ip_block =
-{
+const struct amdgpu_ip_block_version psp_v12_0_ip_block = {
.type = AMD_IP_BLOCK_TYPE_PSP,
.major = 12,
.minor = 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index cf4f60c66122..2cae0b1a0b8a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -455,6 +455,8 @@ extern const struct amdgpu_ip_block_version psp_v13_0_4_ip_block;
extern int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
uint32_t field_val, uint32_t mask, bool check_changed);
+extern int psp_wait_for_spirom_update(struct psp_context *psp, uint32_t reg_index,
+ uint32_t field_val, uint32_t mask, uint32_t msec_timeout);
int psp_gpu_reset(struct amdgpu_device *adev);
int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx,
@@ -486,7 +488,7 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
int psp_ras_enable_features(struct psp_context *psp,
union ta_ras_cmd_input *info, bool enable);
int psp_ras_trigger_error(struct psp_context *psp,
- struct ta_ras_trigger_error_input *info);
+ struct ta_ras_trigger_error_input *info, uint32_t instance_mask);
int psp_ras_terminate(struct psp_context *psp);
int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
@@ -519,6 +521,8 @@ int psp_load_fw_list(struct psp_context *psp,
struct amdgpu_firmware_info **ucode_list, int ucode_count);
void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size);
+int psp_spatial_partition(struct psp_context *psp, int mode);
+
int is_psp_fw_valid(struct psp_bin_desc bin);
int amdgpu_psp_sysfs_init(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 3ab8a88789c8..4769a18304d7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -171,8 +171,7 @@ static int amdgpu_reserve_page_direct(struct amdgpu_device *adev, uint64_t addre
memset(&err_rec, 0x0, sizeof(struct eeprom_table_record));
err_data.err_addr = &err_rec;
- amdgpu_umc_fill_error_record(&err_data, address,
- (address >> AMDGPU_GPU_PAGE_SHIFT), 0, 0);
+ amdgpu_umc_fill_error_record(&err_data, address, address, 0, 0);
if (amdgpu_bad_page_threshold != 0) {
amdgpu_ras_add_bad_pages(adev, err_data.err_addr,
@@ -256,6 +255,8 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
int block_id;
uint32_t sub_block;
u64 address, value;
+ /* default value is 0 if the mask is not set by user */
+ u32 instance_mask = 0;
if (*pos)
return -EINVAL;
@@ -306,7 +307,11 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
data->op = op;
if (op == 2) {
- if (sscanf(str, "%*s %*s %*s 0x%x 0x%llx 0x%llx",
+ if (sscanf(str, "%*s %*s %*s 0x%x 0x%llx 0x%llx 0x%x",
+ &sub_block, &address, &value, &instance_mask) != 4 &&
+ sscanf(str, "%*s %*s %*s %u %llu %llu %u",
+ &sub_block, &address, &value, &instance_mask) != 4 &&
+ sscanf(str, "%*s %*s %*s 0x%x 0x%llx 0x%llx",
&sub_block, &address, &value) != 3 &&
sscanf(str, "%*s %*s %*s %u %llu %llu",
&sub_block, &address, &value) != 3)
@@ -314,6 +319,7 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
data->head.sub_block_index = sub_block;
data->inject.address = address;
data->inject.value = value;
+ data->inject.instance_mask = instance_mask;
}
} else {
if (size < sizeof(*data))
@@ -326,6 +332,46 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
return 0;
}
+static void amdgpu_ras_instance_mask_check(struct amdgpu_device *adev,
+ struct ras_debug_if *data)
+{
+ int num_xcc = adev->gfx.xcc_mask ? NUM_XCC(adev->gfx.xcc_mask) : 1;
+ uint32_t mask, inst_mask = data->inject.instance_mask;
+
+ /* no need to set instance mask if there is only one instance */
+ if (num_xcc <= 1 && inst_mask) {
+ data->inject.instance_mask = 0;
+ dev_dbg(adev->dev,
+ "RAS inject mask(0x%x) isn't supported and force it to 0.\n",
+ inst_mask);
+
+ return;
+ }
+
+ switch (data->head.block) {
+ case AMDGPU_RAS_BLOCK__GFX:
+ mask = GENMASK(num_xcc - 1, 0);
+ break;
+ case AMDGPU_RAS_BLOCK__SDMA:
+ mask = GENMASK(adev->sdma.num_instances - 1, 0);
+ break;
+ case AMDGPU_RAS_BLOCK__VCN:
+ case AMDGPU_RAS_BLOCK__JPEG:
+ mask = GENMASK(adev->vcn.num_vcn_inst - 1, 0);
+ break;
+ default:
+ mask = inst_mask;
+ break;
+ }
+
+ /* remove invalid bits in instance mask */
+ data->inject.instance_mask &= mask;
+ if (inst_mask != data->inject.instance_mask)
+ dev_dbg(adev->dev,
+ "Adjust RAS inject mask 0x%x to 0x%x\n",
+ inst_mask, data->inject.instance_mask);
+}
+
/**
* DOC: AMDGPU RAS debugfs control interface
*
@@ -341,7 +387,7 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
* sub_block_index: some IPs have subcomponets. say, GFX, sDMA.
* name: the name of IP.
*
- * inject has two more members than head, they are address, value.
+ * inject has three more members than head, they are address, value and mask.
* As their names indicate, inject operation will write the
* value to the address.
*
@@ -365,7 +411,7 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
*
* echo "disable <block>" > /sys/kernel/debug/dri/<N>/ras/ras_ctrl
* echo "enable <block> <error>" > /sys/kernel/debug/dri/<N>/ras/ras_ctrl
- * echo "inject <block> <error> <sub-block> <address> <value> > /sys/kernel/debug/dri/<N>/ras/ras_ctrl
+ * echo "inject <block> <error> <sub-block> <address> <value> <mask>" > /sys/kernel/debug/dri/<N>/ras/ras_ctrl
*
* Where N, is the card which you want to affect.
*
@@ -382,13 +428,14 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
*
* The sub-block is a the sub-block index, pass 0 if there is no sub-block.
* The address and value are hexadecimal numbers, leading 0x is optional.
+ * The mask means instance mask, is optional, default value is 0x1.
*
* For instance,
*
* .. code-block:: bash
*
* echo inject umc ue 0x0 0x0 0x0 > /sys/kernel/debug/dri/0/ras/ras_ctrl
- * echo inject umc ce 0 0 0 > /sys/kernel/debug/dri/0/ras/ras_ctrl
+ * echo inject umc ce 0 0 0 3 > /sys/kernel/debug/dri/0/ras/ras_ctrl
* echo disable umc > /sys/kernel/debug/dri/0/ras/ras_ctrl
*
* How to check the result of the operation?
@@ -442,7 +489,8 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f,
ret = amdgpu_ras_feature_enable(adev, &data.head, 1);
break;
case 2:
- if ((data.inject.address >= adev->gmc.mc_vram_size) ||
+ if ((data.inject.address >= adev->gmc.mc_vram_size &&
+ adev->gmc.mc_vram_size) ||
(data.inject.address >= RAS_UMC_INJECT_ADDR_LIMIT)) {
dev_warn(adev->dev, "RAS WARN: input address "
"0x%llx is invalid.",
@@ -460,6 +508,8 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f,
break;
}
+ amdgpu_ras_instance_mask_check(adev, &data);
+
/* data.inject.address is offset instead of absolute gpu address */
ret = amdgpu_ras_error_inject(adev, &data.inject);
break;
@@ -1115,15 +1165,15 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
block_info.address);
}
- if (info->head.block == AMDGPU_RAS_BLOCK__GFX) {
- if (block_obj->hw_ops->ras_error_inject)
- ret = block_obj->hw_ops->ras_error_inject(adev, info);
+ if (block_obj->hw_ops->ras_error_inject) {
+ if (info->head.block == AMDGPU_RAS_BLOCK__GFX)
+ ret = block_obj->hw_ops->ras_error_inject(adev, info, info->instance_mask);
+ else /* Special ras_error_inject is defined (e.g: xgmi) */
+ ret = block_obj->hw_ops->ras_error_inject(adev, &block_info,
+ info->instance_mask);
} else {
- /* If defined special ras_error_inject(e.g: xgmi), implement special ras_error_inject */
- if (block_obj->hw_ops->ras_error_inject)
- ret = block_obj->hw_ops->ras_error_inject(adev, &block_info);
- else /*If not defined .ras_error_inject, use default ras_error_inject*/
- ret = psp_ras_trigger_error(&adev->psp, &block_info);
+ /* default path */
+ ret = psp_ras_trigger_error(&adev->psp, &block_info, info->instance_mask);
}
if (ret)
@@ -1441,6 +1491,7 @@ static int amdgpu_ras_sysfs_remove_all(struct amdgpu_device *adev)
static struct dentry *amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+ struct amdgpu_ras_eeprom_control *eeprom = &con->eeprom_control;
struct drm_minor *minor = adev_to_drm(adev)->primary;
struct dentry *dir;
@@ -1451,6 +1502,7 @@ static struct dentry *amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *
&amdgpu_ras_debugfs_eeprom_ops);
debugfs_create_u32("bad_page_cnt_threshold", 0444, dir,
&con->bad_page_cnt_threshold);
+ debugfs_create_u32("ras_num_recs", 0444, dir, &eeprom->ras_num_recs);
debugfs_create_x32("ras_hw_enabled", 0444, dir, &adev->ras_hw_enabled);
debugfs_create_x32("ras_enabled", 0444, dir, &adev->ras_enabled);
debugfs_create_file("ras_eeprom_size", S_IRUGO, dir, adev,
@@ -1597,8 +1649,7 @@ static int amdgpu_ras_fs_fini(struct amdgpu_device *adev)
void amdgpu_ras_interrupt_fatal_error_handler(struct amdgpu_device *adev)
{
/* Fatal error events are handled on host side */
- if (amdgpu_sriov_vf(adev) ||
- !amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__PCIE_BIF))
+ if (amdgpu_sriov_vf(adev))
return;
if (adev->nbio.ras &&
@@ -1636,8 +1687,7 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager *
}
}
- if (!adev->gmc.xgmi.connected_to_cpu)
- amdgpu_umc_poison_handler(adev, false);
+ amdgpu_umc_poison_handler(adev, false);
if (block_obj->hw_ops && block_obj->hw_ops->handle_poison_consumption)
poison_stat = block_obj->hw_ops->handle_poison_consumption(adev);
@@ -2008,9 +2058,15 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
/* Perform full reset in fatal error mode */
if (!amdgpu_ras_is_poison_mode_supported(ras->adev))
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
- else
+ else {
clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
+ if (ras->gpu_reset_flags & AMDGPU_RAS_GPU_RESET_MODE2_RESET) {
+ ras->gpu_reset_flags &= ~AMDGPU_RAS_GPU_RESET_MODE2_RESET;
+ reset_context.method = AMD_RESET_METHOD_MODE2;
+ }
+ }
+
amdgpu_device_gpu_recover(ras->adev, NULL, &reset_context);
}
atomic_set(&ras->in_recovery, 0);
@@ -2259,7 +2315,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
atomic_set(&con->in_recovery, 0);
con->eeprom_control.bad_channel_bitmap = 0;
- max_eeprom_records_count = amdgpu_ras_eeprom_max_record_count();
+ max_eeprom_records_count = amdgpu_ras_eeprom_max_record_count(&con->eeprom_control);
amdgpu_ras_validate_threshold(adev, max_eeprom_records_count);
/* Todo: During test the SMU might fail to read the eeprom through I2C
@@ -2396,11 +2452,10 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev)
{
adev->ras_hw_enabled = adev->ras_enabled = 0;
- if (!adev->is_atom_fw ||
- !amdgpu_ras_asic_supported(adev))
+ if (!amdgpu_ras_asic_supported(adev))
return;
- if (!adev->gmc.xgmi.connected_to_cpu) {
+ if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) {
if (amdgpu_atomfirmware_mem_ecc_supported(adev)) {
dev_info(adev->dev, "MEM ECC is active.\n");
adev->ras_hw_enabled |= (1 << AMDGPU_RAS_BLOCK__UMC |
@@ -2625,7 +2680,8 @@ release_con:
int amdgpu_persistent_edc_harvesting_supported(struct amdgpu_device *adev)
{
- if (adev->gmc.xgmi.connected_to_cpu)
+ if (adev->gmc.xgmi.connected_to_cpu ||
+ adev->gmc.is_app_apu)
return 1;
return 0;
}
@@ -3104,3 +3160,143 @@ int amdgpu_ras_register_ras_block(struct amdgpu_device *adev,
return 0;
}
+
+void amdgpu_ras_get_error_type_name(uint32_t err_type, char *err_type_name)
+{
+ if (!err_type_name)
+ return;
+
+ switch (err_type) {
+ case AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE:
+ sprintf(err_type_name, "correctable");
+ break;
+ case AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE:
+ sprintf(err_type_name, "uncorrectable");
+ break;
+ default:
+ sprintf(err_type_name, "unknown");
+ break;
+ }
+}
+
+bool amdgpu_ras_inst_get_memory_id_field(struct amdgpu_device *adev,
+ const struct amdgpu_ras_err_status_reg_entry *reg_entry,
+ uint32_t instance,
+ uint32_t *memory_id)
+{
+ uint32_t err_status_lo_data, err_status_lo_offset;
+
+ if (!reg_entry)
+ return false;
+
+ err_status_lo_offset =
+ AMDGPU_RAS_REG_ENTRY_OFFSET(reg_entry->hwip, instance,
+ reg_entry->seg_lo, reg_entry->reg_lo);
+ err_status_lo_data = RREG32(err_status_lo_offset);
+
+ if ((reg_entry->flags & AMDGPU_RAS_ERR_STATUS_VALID) &&
+ !REG_GET_FIELD(err_status_lo_data, ERR_STATUS_LO, ERR_STATUS_VALID_FLAG))
+ return false;
+
+ *memory_id = REG_GET_FIELD(err_status_lo_data, ERR_STATUS_LO, MEMORY_ID);
+
+ return true;
+}
+
+bool amdgpu_ras_inst_get_err_cnt_field(struct amdgpu_device *adev,
+ const struct amdgpu_ras_err_status_reg_entry *reg_entry,
+ uint32_t instance,
+ unsigned long *err_cnt)
+{
+ uint32_t err_status_hi_data, err_status_hi_offset;
+
+ if (!reg_entry)
+ return false;
+
+ err_status_hi_offset =
+ AMDGPU_RAS_REG_ENTRY_OFFSET(reg_entry->hwip, instance,
+ reg_entry->seg_hi, reg_entry->reg_hi);
+ err_status_hi_data = RREG32(err_status_hi_offset);
+
+ if ((reg_entry->flags & AMDGPU_RAS_ERR_INFO_VALID) &&
+ !REG_GET_FIELD(err_status_hi_data, ERR_STATUS_HI, ERR_INFO_VALID_FLAG))
+ /* keep the check here in case we need to refer to the result later */
+ dev_dbg(adev->dev, "Invalid err_info field\n");
+
+ /* read err count */
+ *err_cnt = REG_GET_FIELD(err_status_hi_data, ERR_STATUS, ERR_CNT);
+
+ return true;
+}
+
+void amdgpu_ras_inst_query_ras_error_count(struct amdgpu_device *adev,
+ const struct amdgpu_ras_err_status_reg_entry *reg_list,
+ uint32_t reg_list_size,
+ const struct amdgpu_ras_memory_id_entry *mem_list,
+ uint32_t mem_list_size,
+ uint32_t instance,
+ uint32_t err_type,
+ unsigned long *err_count)
+{
+ uint32_t memory_id;
+ unsigned long err_cnt;
+ char err_type_name[16];
+ uint32_t i, j;
+
+ for (i = 0; i < reg_list_size; i++) {
+ /* query memory_id from err_status_lo */
+ if (!amdgpu_ras_inst_get_memory_id_field(adev, &reg_list[i],
+ instance, &memory_id))
+ continue;
+
+ /* query err_cnt from err_status_hi */
+ if (!amdgpu_ras_inst_get_err_cnt_field(adev, &reg_list[i],
+ instance, &err_cnt) ||
+ !err_cnt)
+ continue;
+
+ *err_count += err_cnt;
+
+ /* log the errors */
+ amdgpu_ras_get_error_type_name(err_type, err_type_name);
+ if (!mem_list) {
+ /* memory_list is not supported */
+ dev_info(adev->dev,
+ "%ld %s hardware errors detected in %s, instance: %d, memory_id: %d\n",
+ err_cnt, err_type_name,
+ reg_list[i].block_name,
+ instance, memory_id);
+ } else {
+ for (j = 0; j < mem_list_size; j++) {
+ if (memory_id == mem_list[j].memory_id) {
+ dev_info(adev->dev,
+ "%ld %s hardware errors detected in %s, instance: %d, memory block: %s\n",
+ err_cnt, err_type_name,
+ reg_list[i].block_name,
+ instance, mem_list[j].name);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void amdgpu_ras_inst_reset_ras_error_count(struct amdgpu_device *adev,
+ const struct amdgpu_ras_err_status_reg_entry *reg_list,
+ uint32_t reg_list_size,
+ uint32_t instance)
+{
+ uint32_t err_status_lo_offset, err_status_hi_offset;
+ uint32_t i;
+
+ for (i = 0; i < reg_list_size; i++) {
+ err_status_lo_offset =
+ AMDGPU_RAS_REG_ENTRY_OFFSET(reg_list[i].hwip, instance,
+ reg_list[i].seg_lo, reg_list[i].reg_lo);
+ err_status_hi_offset =
+ AMDGPU_RAS_REG_ENTRY_OFFSET(reg_list[i].hwip, instance,
+ reg_list[i].seg_hi, reg_list[i].reg_hi);
+ WREG32(err_status_lo_offset, 0);
+ WREG32(err_status_hi_offset, 0);
+ }
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
index 17b3d1992e80..46bf1889a9d7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
@@ -32,6 +32,11 @@
struct amdgpu_iv_entry;
#define AMDGPU_RAS_FLAG_INIT_BY_VBIOS (0x1 << 0)
+/* position of instance value in sub_block_index of
+ * ta_ras_trigger_error_input, the sub block uses lower 12 bits
+ */
+#define AMDGPU_RAS_INST_MASK 0xfffff000
+#define AMDGPU_RAS_INST_SHIFT 0xc
enum amdgpu_ras_block {
AMDGPU_RAS_BLOCK__UMC = 0,
@@ -314,6 +319,45 @@ enum amdgpu_ras_ret {
AMDGPU_RAS_PT,
};
+/* ras error status reisger fields */
+#define ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+#define ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define ERR_STATUS__ERR_CNT__SHIFT 0x17
+#define ERR_STATUS__ERR_CNT_MASK 0x03800000L
+
+#define AMDGPU_RAS_REG_ENTRY(ip, inst, reg_lo, reg_hi) \
+ ip##_HWIP, inst, reg_lo##_BASE_IDX, reg_lo, reg_hi##_BASE_IDX, reg_hi
+
+#define AMDGPU_RAS_REG_ENTRY_OFFSET(hwip, ip_inst, segment, reg) \
+ (adev->reg_offset[hwip][ip_inst][segment] + (reg))
+
+#define AMDGPU_RAS_ERR_INFO_VALID (1 << 0)
+#define AMDGPU_RAS_ERR_STATUS_VALID (1 << 1)
+#define AMDGPU_RAS_ERR_ADDRESS_VALID (1 << 2)
+
+#define AMDGPU_RAS_GPU_RESET_MODE2_RESET (0x1 << 0)
+
+struct amdgpu_ras_err_status_reg_entry {
+ uint32_t hwip;
+ uint32_t ip_inst;
+ uint32_t seg_lo;
+ uint32_t reg_lo;
+ uint32_t seg_hi;
+ uint32_t reg_hi;
+ uint32_t reg_inst;
+ uint32_t flags;
+ const char *block_name;
+};
+
+struct amdgpu_ras_memory_id_entry {
+ uint32_t memory_id;
+ const char *name;
+};
+
struct ras_common_if {
enum amdgpu_ras_block block;
enum amdgpu_ras_error_type type;
@@ -385,6 +429,9 @@ struct amdgpu_ras {
/* Indicates smu whether need update bad channel info */
bool update_channel_flag;
+
+ /* Record special requirements of gpu reset caller */
+ uint32_t gpu_reset_flags;
};
struct ras_fs_data {
@@ -471,6 +518,7 @@ struct ras_inject_if {
struct ras_common_if head;
uint64_t address;
uint64_t value;
+ uint32_t instance_mask;
};
struct ras_cure_if {
@@ -508,7 +556,8 @@ struct amdgpu_ras_block_object {
};
struct amdgpu_ras_block_hw_ops {
- int (*ras_error_inject)(struct amdgpu_device *adev, void *inject_if);
+ int (*ras_error_inject)(struct amdgpu_device *adev,
+ void *inject_if, uint32_t instance_mask);
void (*query_ras_error_count)(struct amdgpu_device *adev, void *ras_error_status);
void (*query_ras_error_status)(struct amdgpu_device *adev);
void (*query_ras_error_address)(struct amdgpu_device *adev, void *ras_error_status);
@@ -696,4 +745,25 @@ int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras *ras_co
int amdgpu_ras_register_ras_block(struct amdgpu_device *adev,
struct amdgpu_ras_block_object *ras_block_obj);
void amdgpu_ras_interrupt_fatal_error_handler(struct amdgpu_device *adev);
+void amdgpu_ras_get_error_type_name(uint32_t err_type, char *err_type_name);
+bool amdgpu_ras_inst_get_memory_id_field(struct amdgpu_device *adev,
+ const struct amdgpu_ras_err_status_reg_entry *reg_entry,
+ uint32_t instance,
+ uint32_t *memory_id);
+bool amdgpu_ras_inst_get_err_cnt_field(struct amdgpu_device *adev,
+ const struct amdgpu_ras_err_status_reg_entry *reg_entry,
+ uint32_t instance,
+ unsigned long *err_cnt);
+void amdgpu_ras_inst_query_ras_error_count(struct amdgpu_device *adev,
+ const struct amdgpu_ras_err_status_reg_entry *reg_list,
+ uint32_t reg_list_size,
+ const struct amdgpu_ras_memory_id_entry *mem_list,
+ uint32_t mem_list_size,
+ uint32_t instance,
+ uint32_t err_type,
+ unsigned long *err_count);
+void amdgpu_ras_inst_reset_ras_error_count(struct amdgpu_device *adev,
+ const struct amdgpu_ras_err_status_reg_entry *reg_list,
+ uint32_t reg_list_size,
+ uint32_t instance);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index c2c2a7718613..0648dfe559af 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -68,11 +68,24 @@
/* Table hdr is 'AMDR' */
#define RAS_TABLE_HDR_VAL 0x414d4452
-#define RAS_TABLE_VER 0x00010000
/* Bad GPU tag ‘BADG’ */
#define RAS_TABLE_HDR_BAD 0x42414447
+/*
+ * EEPROM Table structure v1
+ * ---------------------------------
+ * | |
+ * | EEPROM TABLE HEADER |
+ * | ( size 20 Bytes ) |
+ * | |
+ * ---------------------------------
+ * | |
+ * | BAD PAGE RECORD AREA |
+ * | |
+ * ---------------------------------
+ */
+
/* Assume 2-Mbit size EEPROM and take up the whole space. */
#define RAS_TBL_SIZE_BYTES (256 * 1024)
#define RAS_TABLE_START 0
@@ -81,6 +94,35 @@
#define RAS_MAX_RECORD_COUNT ((RAS_TBL_SIZE_BYTES - RAS_TABLE_HEADER_SIZE) \
/ RAS_TABLE_RECORD_SIZE)
+/*
+ * EEPROM Table structrue v2.1
+ * ---------------------------------
+ * | |
+ * | EEPROM TABLE HEADER |
+ * | ( size 20 Bytes ) |
+ * | |
+ * ---------------------------------
+ * | |
+ * | EEPROM TABLE RAS INFO |
+ * | (available info size 4 Bytes) |
+ * | ( reserved size 252 Bytes ) |
+ * | |
+ * ---------------------------------
+ * | |
+ * | BAD PAGE RECORD AREA |
+ * | |
+ * ---------------------------------
+ */
+
+/* EEPROM Table V2_1 */
+#define RAS_TABLE_V2_1_INFO_SIZE 256
+#define RAS_TABLE_V2_1_INFO_START RAS_TABLE_HEADER_SIZE
+#define RAS_RECORD_START_V2_1 (RAS_HDR_START + RAS_TABLE_HEADER_SIZE + \
+ RAS_TABLE_V2_1_INFO_SIZE)
+#define RAS_MAX_RECORD_COUNT_V2_1 ((RAS_TBL_SIZE_BYTES - RAS_TABLE_HEADER_SIZE - \
+ RAS_TABLE_V2_1_INFO_SIZE) \
+ / RAS_TABLE_RECORD_SIZE)
+
/* Given a zero-based index of an EEPROM RAS record, yields the EEPROM
* offset off of RAS_TABLE_START. That is, this is something you can
* add to control->i2c_address, and then tell I2C layer to read
@@ -103,6 +145,10 @@
#define RAS_NUM_RECS(_tbl_hdr) (((_tbl_hdr)->tbl_size - \
RAS_TABLE_HEADER_SIZE) / RAS_TABLE_RECORD_SIZE)
+#define RAS_NUM_RECS_V2_1(_tbl_hdr) (((_tbl_hdr)->tbl_size - \
+ RAS_TABLE_HEADER_SIZE - \
+ RAS_TABLE_V2_1_INFO_SIZE) / RAS_TABLE_RECORD_SIZE)
+
#define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control))->adev
static bool __is_ras_eeprom_supported(struct amdgpu_device *adev)
@@ -230,6 +276,69 @@ static int __write_table_header(struct amdgpu_ras_eeprom_control *control)
return res;
}
+static void
+__encode_table_ras_info_to_buf(struct amdgpu_ras_eeprom_table_ras_info *rai,
+ unsigned char *buf)
+{
+ u32 *pp = (uint32_t *)buf;
+ u32 tmp;
+
+ tmp = ((uint32_t)(rai->rma_status) & 0xFF) |
+ (((uint32_t)(rai->health_percent) << 8) & 0xFF00) |
+ (((uint32_t)(rai->ecc_page_threshold) << 16) & 0xFFFF0000);
+ pp[0] = cpu_to_le32(tmp);
+}
+
+static void
+__decode_table_ras_info_from_buf(struct amdgpu_ras_eeprom_table_ras_info *rai,
+ unsigned char *buf)
+{
+ u32 *pp = (uint32_t *)buf;
+ u32 tmp;
+
+ tmp = le32_to_cpu(pp[0]);
+ rai->rma_status = tmp & 0xFF;
+ rai->health_percent = (tmp >> 8) & 0xFF;
+ rai->ecc_page_threshold = (tmp >> 16) & 0xFFFF;
+}
+
+static int __write_table_ras_info(struct amdgpu_ras_eeprom_control *control)
+{
+ struct amdgpu_device *adev = to_amdgpu_device(control);
+ u8 *buf;
+ int res;
+
+ buf = kzalloc(RAS_TABLE_V2_1_INFO_SIZE, GFP_KERNEL);
+ if (!buf) {
+ DRM_ERROR("Failed to alloc buf to write table ras info\n");
+ return -ENOMEM;
+ }
+
+ __encode_table_ras_info_to_buf(&control->tbl_rai, buf);
+
+ /* i2c may be unstable in gpu reset */
+ down_read(&adev->reset_domain->sem);
+ res = amdgpu_eeprom_write(adev->pm.ras_eeprom_i2c_bus,
+ control->i2c_address +
+ control->ras_info_offset,
+ buf, RAS_TABLE_V2_1_INFO_SIZE);
+ up_read(&adev->reset_domain->sem);
+
+ if (res < 0) {
+ DRM_ERROR("Failed to write EEPROM table ras info:%d", res);
+ } else if (res < RAS_TABLE_V2_1_INFO_SIZE) {
+ DRM_ERROR("Short write:%d out of %d\n",
+ res, RAS_TABLE_V2_1_INFO_SIZE);
+ res = -EIO;
+ } else {
+ res = 0;
+ }
+
+ kfree(buf);
+
+ return res;
+}
+
static u8 __calc_hdr_byte_sum(const struct amdgpu_ras_eeprom_control *control)
{
int ii;
@@ -246,6 +355,21 @@ static u8 __calc_hdr_byte_sum(const struct amdgpu_ras_eeprom_control *control)
return csum;
}
+static u8 __calc_ras_info_byte_sum(const struct amdgpu_ras_eeprom_control *control)
+{
+ int ii;
+ u8 *pp, csum;
+ size_t sz;
+
+ sz = sizeof(control->tbl_rai);
+ pp = (u8 *) &control->tbl_rai;
+ csum = 0;
+ for (ii = 0; ii < sz; ii++, pp++)
+ csum += *pp;
+
+ return csum;
+}
+
static int amdgpu_ras_eeprom_correct_header_tag(
struct amdgpu_ras_eeprom_control *control,
uint32_t header)
@@ -282,6 +406,7 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
+ struct amdgpu_ras_eeprom_table_ras_info *rai = &control->tbl_rai;
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
u8 csum;
int res;
@@ -289,14 +414,37 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
mutex_lock(&control->ras_tbl_mutex);
hdr->header = RAS_TABLE_HDR_VAL;
- hdr->version = RAS_TABLE_VER;
- hdr->first_rec_offset = RAS_RECORD_START;
- hdr->tbl_size = RAS_TABLE_HEADER_SIZE;
+ if (adev->umc.ras &&
+ adev->umc.ras->set_eeprom_table_version)
+ adev->umc.ras->set_eeprom_table_version(hdr);
+ else
+ hdr->version = RAS_TABLE_VER_V1;
+
+ if (hdr->version == RAS_TABLE_VER_V2_1) {
+ hdr->first_rec_offset = RAS_RECORD_START_V2_1;
+ hdr->tbl_size = RAS_TABLE_HEADER_SIZE +
+ RAS_TABLE_V2_1_INFO_SIZE;
+ rai->rma_status = GPU_HEALTH_USABLE;
+ /**
+ * GPU health represented as a percentage.
+ * 0 means worst health, 100 means fully health.
+ */
+ rai->health_percent = 100;
+ /* ecc_page_threshold = 0 means disable bad page retirement */
+ rai->ecc_page_threshold = con->bad_page_cnt_threshold;
+ } else {
+ hdr->first_rec_offset = RAS_RECORD_START;
+ hdr->tbl_size = RAS_TABLE_HEADER_SIZE;
+ }
csum = __calc_hdr_byte_sum(control);
+ if (hdr->version == RAS_TABLE_VER_V2_1)
+ csum += __calc_ras_info_byte_sum(control);
csum = -csum;
hdr->checksum = csum;
res = __write_table_header(control);
+ if (!res && hdr->version > RAS_TABLE_VER_V1)
+ res = __write_table_ras_info(control);
control->ras_num_recs = 0;
control->ras_fri = 0;
@@ -573,11 +721,19 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control)
"Saved bad pages %d reaches threshold value %d\n",
control->ras_num_recs, ras->bad_page_cnt_threshold);
control->tbl_hdr.header = RAS_TABLE_HDR_BAD;
+ if (control->tbl_hdr.version == RAS_TABLE_VER_V2_1) {
+ control->tbl_rai.rma_status = GPU_RETIRED__ECC_REACH_THRESHOLD;
+ control->tbl_rai.health_percent = 0;
+ }
}
- control->tbl_hdr.version = RAS_TABLE_VER;
- control->tbl_hdr.first_rec_offset = RAS_INDEX_TO_OFFSET(control, control->ras_fri);
- control->tbl_hdr.tbl_size = RAS_TABLE_HEADER_SIZE + control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
+ if (control->tbl_hdr.version == RAS_TABLE_VER_V2_1)
+ control->tbl_hdr.tbl_size = RAS_TABLE_HEADER_SIZE +
+ RAS_TABLE_V2_1_INFO_SIZE +
+ control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
+ else
+ control->tbl_hdr.tbl_size = RAS_TABLE_HEADER_SIZE +
+ control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
control->tbl_hdr.checksum = 0;
buf_size = control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
@@ -606,6 +762,17 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control)
goto Out;
}
+ /**
+ * bad page records have been stored in eeprom,
+ * now calculate gpu health percent
+ */
+ if (amdgpu_bad_page_threshold != 0 &&
+ control->tbl_hdr.version == RAS_TABLE_VER_V2_1 &&
+ control->ras_num_recs < ras->bad_page_cnt_threshold)
+ control->tbl_rai.health_percent = ((ras->bad_page_cnt_threshold -
+ control->ras_num_recs) * 100) /
+ ras->bad_page_cnt_threshold;
+
/* Recalc the checksum.
*/
csum = 0;
@@ -613,10 +780,14 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control)
csum += *pp;
csum += __calc_hdr_byte_sum(control);
+ if (control->tbl_hdr.version == RAS_TABLE_VER_V2_1)
+ csum += __calc_ras_info_byte_sum(control);
/* avoid sign extension when assigning to "checksum" */
csum = -csum;
control->tbl_hdr.checksum = csum;
res = __write_table_header(control);
+ if (!res && control->tbl_hdr.version > RAS_TABLE_VER_V1)
+ res = __write_table_ras_info(control);
Out:
kfree(buf);
return res;
@@ -807,9 +978,12 @@ Out:
return res;
}
-uint32_t amdgpu_ras_eeprom_max_record_count(void)
+uint32_t amdgpu_ras_eeprom_max_record_count(struct amdgpu_ras_eeprom_control *control)
{
- return RAS_MAX_RECORD_COUNT;
+ if (control->tbl_hdr.version == RAS_TABLE_VER_V2_1)
+ return RAS_MAX_RECORD_COUNT_V2_1;
+ else
+ return RAS_MAX_RECORD_COUNT;
}
static ssize_t
@@ -1051,8 +1225,14 @@ static int __verify_ras_table_checksum(struct amdgpu_ras_eeprom_control *control
int buf_size, res;
u8 csum, *buf, *pp;
- buf_size = RAS_TABLE_HEADER_SIZE +
- control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
+ if (control->tbl_hdr.version == RAS_TABLE_VER_V2_1)
+ buf_size = RAS_TABLE_HEADER_SIZE +
+ RAS_TABLE_V2_1_INFO_SIZE +
+ control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
+ else
+ buf_size = RAS_TABLE_HEADER_SIZE +
+ control->ras_num_recs * RAS_TABLE_RECORD_SIZE;
+
buf = kzalloc(buf_size, GFP_KERNEL);
if (!buf) {
DRM_ERROR("Out of memory checking RAS table checksum.\n");
@@ -1080,6 +1260,39 @@ Out:
return res < 0 ? res : csum;
}
+static int __read_table_ras_info(struct amdgpu_ras_eeprom_control *control)
+{
+ struct amdgpu_ras_eeprom_table_ras_info *rai = &control->tbl_rai;
+ struct amdgpu_device *adev = to_amdgpu_device(control);
+ unsigned char *buf;
+ int res;
+
+ buf = kzalloc(RAS_TABLE_V2_1_INFO_SIZE, GFP_KERNEL);
+ if (!buf) {
+ DRM_ERROR("Failed to alloc buf to read EEPROM table ras info\n");
+ return -ENOMEM;
+ }
+
+ /**
+ * EEPROM table V2_1 supports ras info,
+ * read EEPROM table ras info
+ */
+ res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus,
+ control->i2c_address + control->ras_info_offset,
+ buf, RAS_TABLE_V2_1_INFO_SIZE);
+ if (res < RAS_TABLE_V2_1_INFO_SIZE) {
+ DRM_ERROR("Failed to read EEPROM table ras info, res:%d", res);
+ res = res >= 0 ? -EIO : res;
+ goto Out;
+ }
+
+ __decode_table_ras_info_from_buf(rai, buf);
+
+Out:
+ kfree(buf);
+ return res == RAS_TABLE_V2_1_INFO_SIZE ? 0 : res;
+}
+
int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
bool *exceed_err_limit)
{
@@ -1102,8 +1315,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
return -EINVAL;
control->ras_header_offset = RAS_HDR_START;
- control->ras_record_offset = RAS_RECORD_START;
- control->ras_max_record_count = RAS_MAX_RECORD_COUNT;
+ control->ras_info_offset = RAS_TABLE_V2_1_INFO_START;
mutex_init(&control->ras_tbl_mutex);
/* Read the table header from EEPROM address */
@@ -1117,12 +1329,27 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
__decode_table_header_from_buf(hdr, buf);
- control->ras_num_recs = RAS_NUM_RECS(hdr);
+ if (hdr->version == RAS_TABLE_VER_V2_1) {
+ control->ras_num_recs = RAS_NUM_RECS_V2_1(hdr);
+ control->ras_record_offset = RAS_RECORD_START_V2_1;
+ control->ras_max_record_count = RAS_MAX_RECORD_COUNT_V2_1;
+ } else {
+ control->ras_num_recs = RAS_NUM_RECS(hdr);
+ control->ras_record_offset = RAS_RECORD_START;
+ control->ras_max_record_count = RAS_MAX_RECORD_COUNT;
+ }
control->ras_fri = RAS_OFFSET_TO_INDEX(control, hdr->first_rec_offset);
if (hdr->header == RAS_TABLE_HDR_VAL) {
DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records",
control->ras_num_recs);
+
+ if (hdr->version == RAS_TABLE_VER_V2_1) {
+ res = __read_table_ras_info(control);
+ if (res)
+ return res;
+ }
+
res = __verify_ras_table_checksum(control);
if (res)
DRM_ERROR("RAS table incorrect checksum or error:%d\n",
@@ -1136,6 +1363,12 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
ras->bad_page_cnt_threshold);
} else if (hdr->header == RAS_TABLE_HDR_BAD &&
amdgpu_bad_page_threshold != 0) {
+ if (hdr->version == RAS_TABLE_VER_V2_1) {
+ res = __read_table_ras_info(control);
+ if (res)
+ return res;
+ }
+
res = __verify_ras_table_checksum(control);
if (res)
DRM_ERROR("RAS Table incorrect checksum or error:%d\n",
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
index 54d9bfe0881d..6dfd667f3013 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
@@ -26,8 +26,16 @@
#include <linux/i2c.h>
+#define RAS_TABLE_VER_V1 0x00010000
+#define RAS_TABLE_VER_V2_1 0x00021000
+
struct amdgpu_device;
+enum amdgpu_ras_gpu_health_status {
+ GPU_HEALTH_USABLE = 0,
+ GPU_RETIRED__ECC_REACH_THRESHOLD = 2,
+};
+
enum amdgpu_ras_eeprom_err_type {
AMDGPU_RAS_EEPROM_ERR_NA,
AMDGPU_RAS_EEPROM_ERR_RECOVERABLE,
@@ -43,9 +51,18 @@ struct amdgpu_ras_eeprom_table_header {
uint32_t checksum;
} __packed;
+struct amdgpu_ras_eeprom_table_ras_info {
+ u8 rma_status;
+ u8 health_percent;
+ u16 ecc_page_threshold;
+ u32 padding[64 - 1];
+} __packed;
+
struct amdgpu_ras_eeprom_control {
struct amdgpu_ras_eeprom_table_header tbl_hdr;
+ struct amdgpu_ras_eeprom_table_ras_info tbl_rai;
+
/* Base I2C EEPPROM 19-bit memory address,
* where the table is located. For more information,
* see top of amdgpu_eeprom.c.
@@ -58,6 +75,7 @@ struct amdgpu_ras_eeprom_control {
* right after the header.
*/
u32 ras_header_offset;
+ u32 ras_info_offset;
u32 ras_record_offset;
/* Number of records in the table.
@@ -124,7 +142,7 @@ int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control,
struct eeprom_table_record *records, const u32 num);
-uint32_t amdgpu_ras_eeprom_max_record_count(void);
+uint32_t amdgpu_ras_eeprom_max_record_count(struct amdgpu_ras_eeprom_control *control);
void amdgpu_ras_debugfs_set_ret_size(struct amdgpu_ras_eeprom_control *control);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
index 6437ead87e5f..eec41ad30406 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
@@ -40,6 +40,7 @@ int amdgpu_reset_init(struct amdgpu_device *adev)
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 2):
+ case IP_VERSION(13, 0, 6):
ret = aldebaran_reset_init(adev);
break;
case IP_VERSION(11, 0, 7):
@@ -61,6 +62,7 @@ int amdgpu_reset_fini(struct amdgpu_device *adev)
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 2):
+ case IP_VERSION(13, 0, 6):
ret = aldebaran_reset_fini(adev);
break;
case IP_VERSION(11, 0, 7):
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index 49de3a3eebc7..80d6e132e409 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -50,6 +50,26 @@
*/
/**
+ * amdgpu_ring_max_ibs - Return max IBs that fit in a single submission.
+ *
+ * @type: ring type for which to return the limit.
+ */
+unsigned int amdgpu_ring_max_ibs(enum amdgpu_ring_type type)
+{
+ switch (type) {
+ case AMDGPU_RING_TYPE_GFX:
+ /* Need to keep at least 192 on GFX7+ for old radv. */
+ return 192;
+ case AMDGPU_RING_TYPE_COMPUTE:
+ return 125;
+ case AMDGPU_RING_TYPE_VCN_JPEG:
+ return 16;
+ default:
+ return 49;
+ }
+}
+
+/**
* amdgpu_ring_alloc - allocate space on the ring buffer
*
* @ring: amdgpu_ring structure holding ring information
@@ -58,7 +78,7 @@
* Allocate @ndw dwords in the ring buffer (all asics).
* Returns 0 on success, error on failure.
*/
-int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw)
+int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned int ndw)
{
/* Align requested size with padding so unlock_commit can
* pad safely */
@@ -182,6 +202,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
int sched_hw_submission = amdgpu_sched_hw_submission;
u32 *num_sched;
u32 hw_ip;
+ unsigned int max_ibs_dw;
/* Set the hw submission limit higher for KIQ because
* it's used for a number of gfx/compute tasks by both
@@ -290,6 +311,13 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
return r;
}
+ max_ibs_dw = ring->funcs->emit_frame_size +
+ amdgpu_ring_max_ibs(ring->funcs->type) * ring->funcs->emit_ib_size;
+ max_ibs_dw = (max_ibs_dw + ring->funcs->align_mask) & ~ring->funcs->align_mask;
+
+ if (WARN_ON(max_ibs_dw > max_dw))
+ max_dw = max_ibs_dw;
+
ring->ring_size = roundup_pow_of_two(max_dw * 4 * sched_hw_submission);
ring->buf_mask = (ring->ring_size / 4) - 1;
@@ -361,6 +389,8 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
amdgpu_bo_free_kernel(&ring->ring_obj,
&ring->gpu_addr,
(void **)&ring->ring);
+ } else {
+ kfree(ring->fence_drv.fences);
}
dma_fence_put(ring->vmid_wait);
@@ -403,11 +433,18 @@ void amdgpu_ring_emit_reg_write_reg_wait_helper(struct amdgpu_ring *ring,
bool amdgpu_ring_soft_recovery(struct amdgpu_ring *ring, unsigned int vmid,
struct dma_fence *fence)
{
+ unsigned long flags;
+
ktime_t deadline = ktime_add_us(ktime_get(), 10000);
if (amdgpu_sriov_vf(ring->adev) || !ring->funcs->soft_recovery || !fence)
return false;
+ spin_lock_irqsave(fence->lock, flags);
+ if (!dma_fence_is_signaled_locked(fence))
+ dma_fence_set_error(fence, -ENODATA);
+ spin_unlock_irqrestore(fence->lock, flags);
+
atomic_inc(&ring->adev->gpu_reset_counter);
while (!dma_fence_is_signaled(fence) &&
ktime_to_ns(ktime_sub(deadline, ktime_get())) > 0)
@@ -478,6 +515,70 @@ static const struct file_operations amdgpu_debugfs_ring_fops = {
.llseek = default_llseek
};
+static ssize_t amdgpu_debugfs_mqd_read(struct file *f, char __user *buf,
+ size_t size, loff_t *pos)
+{
+ struct amdgpu_ring *ring = file_inode(f)->i_private;
+ volatile u32 *mqd;
+ int r;
+ uint32_t value, result;
+
+ if (*pos & 3 || size & 3)
+ return -EINVAL;
+
+ result = 0;
+
+ r = amdgpu_bo_reserve(ring->mqd_obj, false);
+ if (unlikely(r != 0))
+ return r;
+
+ r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&mqd);
+ if (r) {
+ amdgpu_bo_unreserve(ring->mqd_obj);
+ return r;
+ }
+
+ while (size) {
+ if (*pos >= ring->mqd_size)
+ goto done;
+
+ value = mqd[*pos/4];
+ r = put_user(value, (uint32_t *)buf);
+ if (r)
+ goto done;
+ buf += 4;
+ result += 4;
+ size -= 4;
+ *pos += 4;
+ }
+
+done:
+ amdgpu_bo_kunmap(ring->mqd_obj);
+ mqd = NULL;
+ amdgpu_bo_unreserve(ring->mqd_obj);
+ if (r)
+ return r;
+
+ return result;
+}
+
+static const struct file_operations amdgpu_debugfs_mqd_fops = {
+ .owner = THIS_MODULE,
+ .read = amdgpu_debugfs_mqd_read,
+ .llseek = default_llseek
+};
+
+static int amdgpu_debugfs_ring_error(void *data, u64 val)
+{
+ struct amdgpu_ring *ring = data;
+
+ amdgpu_fence_driver_set_error(ring, val);
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(amdgpu_debugfs_error_fops, NULL,
+ amdgpu_debugfs_ring_error, "%lld\n");
+
#endif
void amdgpu_debugfs_ring_init(struct amdgpu_device *adev,
@@ -489,10 +590,21 @@ void amdgpu_debugfs_ring_init(struct amdgpu_device *adev,
char name[32];
sprintf(name, "amdgpu_ring_%s", ring->name);
- debugfs_create_file_size(name, S_IFREG | S_IRUGO, root, ring,
+ debugfs_create_file_size(name, S_IFREG | 0444, root, ring,
&amdgpu_debugfs_ring_fops,
ring->ring_size + 12);
+ if (ring->mqd_obj) {
+ sprintf(name, "amdgpu_mqd_%s", ring->name);
+ debugfs_create_file_size(name, S_IFREG | 0444, root, ring,
+ &amdgpu_debugfs_mqd_fops,
+ ring->mqd_size);
+ }
+
+ sprintf(name, "amdgpu_error_%s", ring->name);
+ debugfs_create_file(name, 0200, root, ring,
+ &amdgpu_debugfs_error_fops);
+
#endif
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index 2474cb71e476..028ff075db51 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -37,8 +37,8 @@ struct amdgpu_job;
struct amdgpu_vm;
/* max number of rings */
-#define AMDGPU_MAX_RINGS 28
-#define AMDGPU_MAX_HWIP_RINGS 8
+#define AMDGPU_MAX_RINGS 124
+#define AMDGPU_MAX_HWIP_RINGS 64
#define AMDGPU_MAX_GFX_RINGS 2
#define AMDGPU_MAX_SW_GFX_RINGS 2
#define AMDGPU_MAX_COMPUTE_RINGS 8
@@ -126,6 +126,7 @@ struct amdgpu_fence_driver {
extern const struct drm_sched_backend_ops amdgpu_sched_ops;
void amdgpu_fence_driver_clear_job_fences(struct amdgpu_ring *ring);
+void amdgpu_fence_driver_set_error(struct amdgpu_ring *ring, int error);
void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring);
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring);
@@ -212,6 +213,8 @@ struct amdgpu_ring_funcs {
void (*end_use)(struct amdgpu_ring *ring);
void (*emit_switch_buffer) (struct amdgpu_ring *ring);
void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags);
+ void (*emit_gfx_shadow)(struct amdgpu_ring *ring, u64 shadow_va, u64 csa_va,
+ u64 gds_va, bool init_shadow, int vmid);
void (*emit_rreg)(struct amdgpu_ring *ring, uint32_t reg,
uint32_t reg_val_offs);
void (*emit_wreg)(struct amdgpu_ring *ring, uint32_t reg, uint32_t val);
@@ -253,12 +256,14 @@ struct amdgpu_ring {
uint32_t buf_mask;
u32 idx;
u32 xcc_id;
+ u32 xcp_id;
u32 me;
u32 pipe;
u32 queue;
struct amdgpu_bo *mqd_obj;
uint64_t mqd_gpu_addr;
void *mqd_ptr;
+ unsigned mqd_size;
uint64_t eop_gpu_addr;
u32 doorbell_index;
bool use_doorbell;
@@ -312,6 +317,7 @@ struct amdgpu_ring {
#define amdgpu_ring_emit_hdp_flush(r) (r)->funcs->emit_hdp_flush((r))
#define amdgpu_ring_emit_switch_buffer(r) (r)->funcs->emit_switch_buffer((r))
#define amdgpu_ring_emit_cntxcntl(r, d) (r)->funcs->emit_cntxcntl((r), (d))
+#define amdgpu_ring_emit_gfx_shadow(r, s, c, g, i, v) ((r)->funcs->emit_gfx_shadow((r), (s), (c), (g), (i), (v)))
#define amdgpu_ring_emit_rreg(r, d, o) (r)->funcs->emit_rreg((r), (d), (o))
#define amdgpu_ring_emit_wreg(r, d, v) (r)->funcs->emit_wreg((r), (d), (v))
#define amdgpu_ring_emit_reg_wait(r, d, v, m) (r)->funcs->emit_reg_wait((r), (d), (v), (m))
@@ -325,6 +331,7 @@ struct amdgpu_ring {
#define amdgpu_ring_patch_ce(r, o) ((r)->funcs->patch_ce((r), (o)))
#define amdgpu_ring_patch_de(r, o) ((r)->funcs->patch_de((r), (o)))
+unsigned int amdgpu_ring_max_ibs(enum amdgpu_ring_type type);
int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw);
void amdgpu_ring_ib_begin(struct amdgpu_ring *ring);
void amdgpu_ring_ib_end(struct amdgpu_ring *ring);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.c
index 85fb730d9fc8..35e0ae9acadc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.c
@@ -31,12 +31,13 @@
* amdgpu_gfx_rlc_enter_safe_mode - Set RLC into safe mode
*
* @adev: amdgpu_device pointer
+ * @xcc_id: xcc accelerated compute core id
*
* Set RLC enter into safe mode if RLC is enabled and haven't in safe mode.
*/
-void amdgpu_gfx_rlc_enter_safe_mode(struct amdgpu_device *adev)
+void amdgpu_gfx_rlc_enter_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
- if (adev->gfx.rlc.in_safe_mode)
+ if (adev->gfx.rlc.in_safe_mode[xcc_id])
return;
/* if RLC is not enabled, do nothing */
@@ -46,8 +47,8 @@ void amdgpu_gfx_rlc_enter_safe_mode(struct amdgpu_device *adev)
if (adev->cg_flags &
(AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_MGCG |
AMD_CG_SUPPORT_GFX_3D_CGCG)) {
- adev->gfx.rlc.funcs->set_safe_mode(adev);
- adev->gfx.rlc.in_safe_mode = true;
+ adev->gfx.rlc.funcs->set_safe_mode(adev, xcc_id);
+ adev->gfx.rlc.in_safe_mode[xcc_id] = true;
}
}
@@ -55,12 +56,13 @@ void amdgpu_gfx_rlc_enter_safe_mode(struct amdgpu_device *adev)
* amdgpu_gfx_rlc_exit_safe_mode - Set RLC out of safe mode
*
* @adev: amdgpu_device pointer
+ * @xcc_id: xcc accelerated compute core id
*
* Set RLC exit safe mode if RLC is enabled and have entered into safe mode.
*/
-void amdgpu_gfx_rlc_exit_safe_mode(struct amdgpu_device *adev)
+void amdgpu_gfx_rlc_exit_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
- if (!(adev->gfx.rlc.in_safe_mode))
+ if (!(adev->gfx.rlc.in_safe_mode[xcc_id]))
return;
/* if RLC is not enabled, do nothing */
@@ -70,8 +72,8 @@ void amdgpu_gfx_rlc_exit_safe_mode(struct amdgpu_device *adev)
if (adev->cg_flags &
(AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_MGCG |
AMD_CG_SUPPORT_GFX_3D_CGCG)) {
- adev->gfx.rlc.funcs->unset_safe_mode(adev);
- adev->gfx.rlc.in_safe_mode = false;
+ adev->gfx.rlc.funcs->unset_safe_mode(adev, xcc_id);
+ adev->gfx.rlc.in_safe_mode[xcc_id] = false;
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h
index 23f060db9255..80b263646966 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h
@@ -157,8 +157,8 @@ typedef struct _RLC_TABLE_OF_CONTENT {
struct amdgpu_rlc_funcs {
bool (*is_rlc_enabled)(struct amdgpu_device *adev);
- void (*set_safe_mode)(struct amdgpu_device *adev);
- void (*unset_safe_mode)(struct amdgpu_device *adev);
+ void (*set_safe_mode)(struct amdgpu_device *adev, int xcc_id);
+ void (*unset_safe_mode)(struct amdgpu_device *adev, int xcc_id);
int (*init)(struct amdgpu_device *adev);
u32 (*get_csb_size)(struct amdgpu_device *adev);
void (*get_csb_buffer)(struct amdgpu_device *adev, volatile u32 *buffer);
@@ -201,7 +201,7 @@ struct amdgpu_rlc {
u32 cp_table_size;
/* safe mode for updating CG/PG state */
- bool in_safe_mode;
+ bool in_safe_mode[8];
const struct amdgpu_rlc_funcs *funcs;
/* for firmware data */
@@ -260,8 +260,8 @@ struct amdgpu_rlc {
struct amdgpu_rlcg_reg_access_ctrl reg_access_ctrl;
};
-void amdgpu_gfx_rlc_enter_safe_mode(struct amdgpu_device *adev);
-void amdgpu_gfx_rlc_exit_safe_mode(struct amdgpu_device *adev);
+void amdgpu_gfx_rlc_enter_safe_mode(struct amdgpu_device *adev, int xcc_id);
+void amdgpu_gfx_rlc_exit_safe_mode(struct amdgpu_device *adev, int xcc_id);
int amdgpu_gfx_rlc_init_sr(struct amdgpu_device *adev, u32 dws);
int amdgpu_gfx_rlc_init_csb(struct amdgpu_device *adev);
int amdgpu_gfx_rlc_init_cpt(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index 231ca06bc9c7..78ec3420ef85 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -64,7 +64,7 @@ int amdgpu_sdma_get_index_from_ring(struct amdgpu_ring *ring, uint32_t *index)
}
uint64_t amdgpu_sdma_get_csa_mc_addr(struct amdgpu_ring *ring,
- unsigned vmid)
+ unsigned int vmid)
{
struct amdgpu_device *adev = ring->adev;
uint64_t csa_mc_addr;
@@ -252,6 +252,13 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
if (!duplicate && (instance != i))
continue;
else {
+ /* Use a single copy per SDMA firmware type. PSP uses the same instance for all
+ * groups of SDMAs */
+ if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 4, 2) &&
+ adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
+ adev->sdma.num_inst_per_aid == i) {
+ break;
+ }
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
info->ucode_id = AMDGPU_UCODE_ID_SDMA0 + i;
info->fw = adev->sdma.instance[i].fw;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
index fc8528812598..513ac22120c1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
@@ -26,7 +26,7 @@
#include "amdgpu_ras.h"
/* max number of IP instances */
-#define AMDGPU_MAX_SDMA_INSTANCES 8
+#define AMDGPU_MAX_SDMA_INSTANCES 16
enum amdgpu_sdma_irq {
AMDGPU_SDMA_IRQ_INSTANCE0 = 0,
@@ -37,9 +37,19 @@ enum amdgpu_sdma_irq {
AMDGPU_SDMA_IRQ_INSTANCE5,
AMDGPU_SDMA_IRQ_INSTANCE6,
AMDGPU_SDMA_IRQ_INSTANCE7,
+ AMDGPU_SDMA_IRQ_INSTANCE8,
+ AMDGPU_SDMA_IRQ_INSTANCE9,
+ AMDGPU_SDMA_IRQ_INSTANCE10,
+ AMDGPU_SDMA_IRQ_INSTANCE11,
+ AMDGPU_SDMA_IRQ_INSTANCE12,
+ AMDGPU_SDMA_IRQ_INSTANCE13,
+ AMDGPU_SDMA_IRQ_INSTANCE14,
+ AMDGPU_SDMA_IRQ_INSTANCE15,
AMDGPU_SDMA_IRQ_LAST
};
+#define NUM_SDMA(x) hweight32(x)
+
struct amdgpu_sdma_instance {
/* SDMA firmware */
const struct firmware *fw;
@@ -49,6 +59,35 @@ struct amdgpu_sdma_instance {
struct amdgpu_ring ring;
struct amdgpu_ring page;
bool burst_nop;
+ uint32_t aid_id;
+};
+
+enum amdgpu_sdma_ras_memory_id {
+ AMDGPU_SDMA_MBANK_DATA_BUF0 = 1,
+ AMDGPU_SDMA_MBANK_DATA_BUF1 = 2,
+ AMDGPU_SDMA_MBANK_DATA_BUF2 = 3,
+ AMDGPU_SDMA_MBANK_DATA_BUF3 = 4,
+ AMDGPU_SDMA_MBANK_DATA_BUF4 = 5,
+ AMDGPU_SDMA_MBANK_DATA_BUF5 = 6,
+ AMDGPU_SDMA_MBANK_DATA_BUF6 = 7,
+ AMDGPU_SDMA_MBANK_DATA_BUF7 = 8,
+ AMDGPU_SDMA_MBANK_DATA_BUF8 = 9,
+ AMDGPU_SDMA_MBANK_DATA_BUF9 = 10,
+ AMDGPU_SDMA_MBANK_DATA_BUF10 = 11,
+ AMDGPU_SDMA_MBANK_DATA_BUF11 = 12,
+ AMDGPU_SDMA_MBANK_DATA_BUF12 = 13,
+ AMDGPU_SDMA_MBANK_DATA_BUF13 = 14,
+ AMDGPU_SDMA_MBANK_DATA_BUF14 = 15,
+ AMDGPU_SDMA_MBANK_DATA_BUF15 = 16,
+ AMDGPU_SDMA_UCODE_BUF = 17,
+ AMDGPU_SDMA_RB_CMD_BUF = 18,
+ AMDGPU_SDMA_IB_CMD_BUF = 19,
+ AMDGPU_SDMA_UTCL1_RD_FIFO = 20,
+ AMDGPU_SDMA_UTCL1_RDBST_FIFO = 21,
+ AMDGPU_SDMA_UTCL1_WR_FIFO = 22,
+ AMDGPU_SDMA_DATA_LUT_FIFO = 23,
+ AMDGPU_SDMA_SPLIT_DAT_BUF = 24,
+ AMDGPU_SDMA_MEMORY_BLOCK_LAST,
};
struct amdgpu_sdma_ras {
@@ -66,6 +105,8 @@ struct amdgpu_sdma {
struct amdgpu_irq_src srbm_write_irq;
int num_instances;
+ uint32_t sdma_mask;
+ int num_inst_per_aid;
uint32_t srbm_soft_reset;
bool has_page_queue;
struct ras_common_if *ras_if;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h
index c7a823f3f2c5..89c38d864471 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h
@@ -30,6 +30,7 @@ struct amdgpu_smuio_funcs {
void (*get_clock_gating_state)(struct amdgpu_device *adev, u64 *flags);
u32 (*get_die_id)(struct amdgpu_device *adev);
u32 (*get_socket_id)(struct amdgpu_device *adev);
+ enum amdgpu_pkg_type (*get_pkg_type)(struct amdgpu_device *adev);
bool (*is_host_gpu_xgmi_supported)(struct amdgpu_device *adev);
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 2cd081cbf706..0534ab716809 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -38,7 +38,6 @@
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/swap.h>
-#include <linux/swiotlb.h>
#include <linux/dma-buf.h>
#include <linux/sizes.h>
#include <linux/module.h>
@@ -65,7 +64,7 @@
MODULE_IMPORT_NS(DMA_BUF);
-#define AMDGPU_TTM_VRAM_MAX_DW_READ (size_t)128
+#define AMDGPU_TTM_VRAM_MAX_DW_READ ((size_t)128)
static int amdgpu_ttm_backend_bind(struct ttm_device *bdev,
struct ttm_tt *ttm,
@@ -184,11 +183,11 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo,
struct ttm_resource *mem,
struct amdgpu_res_cursor *mm_cur,
- unsigned window, struct amdgpu_ring *ring,
+ unsigned int window, struct amdgpu_ring *ring,
bool tmz, uint64_t *size, uint64_t *addr)
{
struct amdgpu_device *adev = ring->adev;
- unsigned offset, num_pages, num_dw, num_bytes;
+ unsigned int offset, num_pages, num_dw, num_bytes;
uint64_t src_addr, dst_addr;
struct amdgpu_job *job;
void *cpu_addr;
@@ -229,7 +228,7 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo,
num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8);
num_bytes = num_pages * 8 * AMDGPU_GPU_PAGES_IN_CPU_PAGE;
- r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity,
+ r = amdgpu_job_alloc_with_ib(adev, &adev->mman.high_pr,
AMDGPU_FENCE_OWNER_UNDEFINED,
num_dw * 4 + num_bytes,
AMDGPU_IB_POOL_DELAYED, &job);
@@ -384,7 +383,8 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE)) {
struct dma_fence *wipe_fence = NULL;
- r = amdgpu_fill_buffer(abo, AMDGPU_POISON, NULL, &wipe_fence);
+ r = amdgpu_fill_buffer(abo, AMDGPU_POISON, NULL, &wipe_fence,
+ false);
if (r) {
goto error;
} else if (wipe_fence) {
@@ -631,6 +631,7 @@ struct amdgpu_ttm_tt {
struct task_struct *usertask;
uint32_t userflags;
bool bound;
+ int32_t pool_id;
};
#define ttm_to_amdgpu_ttm_tt(ptr) container_of(ptr, struct amdgpu_ttm_tt, ttm)
@@ -800,6 +801,44 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_device *bdev,
sg_free_table(ttm->sg);
}
+/*
+ * total_pages is constructed as MQD0+CtrlStack0 + MQD1+CtrlStack1 + ...
+ * MQDn+CtrlStackn where n is the number of XCCs per partition.
+ * pages_per_xcc is the size of one MQD+CtrlStack. The first page is MQD
+ * and uses memory type default, UC. The rest of pages_per_xcc are
+ * Ctrl stack and modify their memory type to NC.
+ */
+static void amdgpu_ttm_gart_bind_gfx9_mqd(struct amdgpu_device *adev,
+ struct ttm_tt *ttm, uint64_t flags)
+{
+ struct amdgpu_ttm_tt *gtt = (void *)ttm;
+ uint64_t total_pages = ttm->num_pages;
+ int num_xcc = max(1U, adev->gfx.num_xcc_per_xcp);
+ uint64_t page_idx, pages_per_xcc;
+ int i;
+ uint64_t ctrl_flags = (flags & ~AMDGPU_PTE_MTYPE_VG10_MASK) |
+ AMDGPU_PTE_MTYPE_VG10(AMDGPU_MTYPE_NC);
+
+ pages_per_xcc = total_pages;
+ do_div(pages_per_xcc, num_xcc);
+
+ for (i = 0, page_idx = 0; i < num_xcc; i++, page_idx += pages_per_xcc) {
+ /* MQD page: use default flags */
+ amdgpu_gart_bind(adev,
+ gtt->offset + (page_idx << PAGE_SHIFT),
+ 1, &gtt->ttm.dma_address[page_idx], flags);
+ /*
+ * Ctrl pages - modify the memory type to NC (ctrl_flags) from
+ * the second page of the BO onward.
+ */
+ amdgpu_gart_bind(adev,
+ gtt->offset + ((page_idx + 1) << PAGE_SHIFT),
+ pages_per_xcc - 1,
+ &gtt->ttm.dma_address[page_idx + 1],
+ ctrl_flags);
+ }
+}
+
static void amdgpu_ttm_gart_bind(struct amdgpu_device *adev,
struct ttm_buffer_object *tbo,
uint64_t flags)
@@ -812,21 +851,7 @@ static void amdgpu_ttm_gart_bind(struct amdgpu_device *adev,
flags |= AMDGPU_PTE_TMZ;
if (abo->flags & AMDGPU_GEM_CREATE_CP_MQD_GFX9) {
- uint64_t page_idx = 1;
-
- amdgpu_gart_bind(adev, gtt->offset, page_idx,
- gtt->ttm.dma_address, flags);
-
- /* The memory type of the first page defaults to UC. Now
- * modify the memory type to NC from the second page of
- * the BO onward.
- */
- flags &= ~AMDGPU_PTE_MTYPE_VG10_MASK;
- flags |= AMDGPU_PTE_MTYPE_VG10(AMDGPU_MTYPE_NC);
-
- amdgpu_gart_bind(adev, gtt->offset + (page_idx << PAGE_SHIFT),
- ttm->num_pages - page_idx,
- &(gtt->ttm.dma_address[page_idx]), flags);
+ amdgpu_ttm_gart_bind_gfx9_mqd(adev, ttm, flags);
} else {
amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages,
gtt->ttm.dma_address, flags);
@@ -1029,15 +1054,20 @@ static void amdgpu_ttm_backend_destroy(struct ttm_device *bdev,
static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo,
uint32_t page_flags)
{
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
struct amdgpu_ttm_tt *gtt;
enum ttm_caching caching;
gtt = kzalloc(sizeof(struct amdgpu_ttm_tt), GFP_KERNEL);
- if (gtt == NULL) {
+ if (!gtt)
return NULL;
- }
+
gtt->gobj = &bo->base;
+ if (adev->gmc.mem_partitions && abo->xcp_id >= 0)
+ gtt->pool_id = KFD_XCP_MEM_ID(adev, abo->xcp_id);
+ else
+ gtt->pool_id = abo->xcp_id;
if (abo->flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
caching = ttm_write_combined;
@@ -1064,6 +1094,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_device *bdev,
{
struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm);
+ struct ttm_pool *pool;
pgoff_t i;
int ret;
@@ -1078,7 +1109,11 @@ static int amdgpu_ttm_tt_populate(struct ttm_device *bdev,
if (ttm->page_flags & TTM_TT_FLAG_EXTERNAL)
return 0;
- ret = ttm_pool_alloc(&adev->mman.bdev.pool, ttm, ctx);
+ if (adev->mman.ttm_pools && gtt->pool_id >= 0)
+ pool = &adev->mman.ttm_pools[gtt->pool_id];
+ else
+ pool = &adev->mman.bdev.pool;
+ ret = ttm_pool_alloc(pool, ttm, ctx);
if (ret)
return ret;
@@ -1099,6 +1134,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev,
{
struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm);
struct amdgpu_device *adev;
+ struct ttm_pool *pool;
pgoff_t i;
amdgpu_ttm_backend_unbind(bdev, ttm);
@@ -1117,7 +1153,13 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev,
ttm->pages[i]->mapping = NULL;
adev = amdgpu_ttm_adev(bdev);
- return ttm_pool_free(&adev->mman.bdev.pool, ttm);
+
+ if (adev->mman.ttm_pools && gtt->pool_id >= 0)
+ pool = &adev->mman.ttm_pools[gtt->pool_id];
+ else
+ pool = &adev->mman.bdev.pool;
+
+ return ttm_pool_free(pool, ttm);
}
/**
@@ -1414,7 +1456,7 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo,
memcpy(adev->mman.sdma_access_ptr, buf, len);
num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8);
- r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity,
+ r = amdgpu_job_alloc_with_ib(adev, &adev->mman.high_pr,
AMDGPU_FENCE_OWNER_UNDEFINED,
num_dw * 4, AMDGPU_IB_POOL_DELAYED,
&job);
@@ -1623,14 +1665,15 @@ static int amdgpu_ttm_training_reserve_vram_fini(struct amdgpu_device *adev)
return 0;
}
-static void amdgpu_ttm_training_data_block_init(struct amdgpu_device *adev)
+static void amdgpu_ttm_training_data_block_init(struct amdgpu_device *adev,
+ uint32_t reserve_size)
{
struct psp_memory_training_context *ctx = &adev->psp.mem_train_ctx;
memset(ctx, 0, sizeof(*ctx));
ctx->c2p_train_data_offset =
- ALIGN((adev->gmc.mc_vram_size - adev->mman.discovery_tmr_size - SZ_1M), SZ_1M);
+ ALIGN((adev->gmc.mc_vram_size - reserve_size - SZ_1M), SZ_1M);
ctx->p2c_train_data_offset =
(adev->gmc.mc_vram_size - GDDR6_MEM_TRAINING_OFFSET);
ctx->train_data_size =
@@ -1648,11 +1691,12 @@ static void amdgpu_ttm_training_data_block_init(struct amdgpu_device *adev)
*/
static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev)
{
- int ret;
struct psp_memory_training_context *ctx = &adev->psp.mem_train_ctx;
bool mem_train_support = false;
+ uint32_t reserve_size = 0;
+ int ret;
- if (!amdgpu_sriov_vf(adev)) {
+ if (adev->bios && !amdgpu_sriov_vf(adev)) {
if (amdgpu_atomfirmware_mem_training_supported(adev))
mem_train_support = true;
else
@@ -1666,14 +1710,18 @@ static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev)
* Otherwise, fallback to legacy approach to check and reserve tmr block for ip
* discovery data and G6 memory training data respectively
*/
- adev->mman.discovery_tmr_size =
- amdgpu_atomfirmware_get_fw_reserved_fb_size(adev);
- if (!adev->mman.discovery_tmr_size)
- adev->mman.discovery_tmr_size = DISCOVERY_TMR_OFFSET;
+ if (adev->bios)
+ reserve_size =
+ amdgpu_atomfirmware_get_fw_reserved_fb_size(adev);
+
+ if (!adev->bios && adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
+ reserve_size = max(reserve_size, (uint32_t)280 << 20);
+ else if (!reserve_size)
+ reserve_size = DISCOVERY_TMR_OFFSET;
if (mem_train_support) {
/* reserve vram for mem train according to TMR location */
- amdgpu_ttm_training_data_block_init(adev);
+ amdgpu_ttm_training_data_block_init(adev, reserve_size);
ret = amdgpu_bo_create_kernel_at(adev,
ctx->c2p_train_data_offset,
ctx->train_data_size,
@@ -1687,20 +1735,58 @@ static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev)
ctx->init = PSP_MEM_TRAIN_RESERVE_SUCCESS;
}
- ret = amdgpu_bo_create_kernel_at(adev,
- adev->gmc.real_vram_size - adev->mman.discovery_tmr_size,
- adev->mman.discovery_tmr_size,
- &adev->mman.discovery_memory,
- NULL);
- if (ret) {
- DRM_ERROR("alloc tmr failed(%d)!\n", ret);
- amdgpu_bo_free_kernel(&adev->mman.discovery_memory, NULL, NULL);
- return ret;
+ if (!adev->gmc.is_app_apu) {
+ ret = amdgpu_bo_create_kernel_at(
+ adev, adev->gmc.real_vram_size - reserve_size,
+ reserve_size, &adev->mman.fw_reserved_memory, NULL);
+ if (ret) {
+ DRM_ERROR("alloc tmr failed(%d)!\n", ret);
+ amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory,
+ NULL, NULL);
+ return ret;
+ }
+ } else {
+ DRM_DEBUG_DRIVER("backdoor fw loading path for PSP TMR, no reservation needed\n");
}
return 0;
}
+static int amdgpu_ttm_pools_init(struct amdgpu_device *adev)
+{
+ int i;
+
+ if (!adev->gmc.is_app_apu || !adev->gmc.num_mem_partitions)
+ return 0;
+
+ adev->mman.ttm_pools = kcalloc(adev->gmc.num_mem_partitions,
+ sizeof(*adev->mman.ttm_pools),
+ GFP_KERNEL);
+ if (!adev->mman.ttm_pools)
+ return -ENOMEM;
+
+ for (i = 0; i < adev->gmc.num_mem_partitions; i++) {
+ ttm_pool_init(&adev->mman.ttm_pools[i], adev->dev,
+ adev->gmc.mem_partitions[i].numa.node,
+ false, false);
+ }
+ return 0;
+}
+
+static void amdgpu_ttm_pools_fini(struct amdgpu_device *adev)
+{
+ int i;
+
+ if (!adev->gmc.is_app_apu || !adev->mman.ttm_pools)
+ return;
+
+ for (i = 0; i < adev->gmc.num_mem_partitions; i++)
+ ttm_pool_fini(&adev->mman.ttm_pools[i]);
+
+ kfree(adev->mman.ttm_pools);
+ adev->mman.ttm_pools = NULL;
+}
+
/*
* amdgpu_ttm_init - Init the memory management (ttm) as well as various
* gtt/vram related fields.
@@ -1727,6 +1813,12 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
return r;
}
+
+ r = amdgpu_ttm_pools_init(adev);
+ if (r) {
+ DRM_ERROR("failed to init ttm pools(%d).\n", r);
+ return r;
+ }
adev->mman.initialized = true;
/* Initialize VRAM pool with all of VRAM divided into pages */
@@ -1744,6 +1836,9 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
adev->mman.aper_base_kaddr = ioremap_cache(adev->gmc.aper_base,
adev->gmc.visible_vram_size);
+ else if (adev->gmc.is_app_apu)
+ DRM_DEBUG_DRIVER(
+ "No need to ioremap when real vram size is 0\n");
else
#endif
adev->mman.aper_base_kaddr = ioremap_wc(adev->gmc.aper_base,
@@ -1755,9 +1850,8 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
*place on the VRAM, so reserve it early.
*/
r = amdgpu_ttm_fw_reserve_vram_init(adev);
- if (r) {
+ if (r)
return r;
- }
/*
*The reserved vram for driver must be pinned to the specified
@@ -1781,49 +1875,46 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
/* allocate memory as required for VGA
* This is used for VGA emulation and pre-OS scanout buffers to
* avoid display artifacts while transitioning between pre-OS
- * and driver. */
- r = amdgpu_bo_create_kernel_at(adev, 0, adev->mman.stolen_vga_size,
- &adev->mman.stolen_vga_memory,
- NULL);
- if (r)
- return r;
- r = amdgpu_bo_create_kernel_at(adev, adev->mman.stolen_vga_size,
- adev->mman.stolen_extended_size,
- &adev->mman.stolen_extended_memory,
- NULL);
- if (r)
- return r;
- r = amdgpu_bo_create_kernel_at(adev, adev->mman.stolen_reserved_offset,
- adev->mman.stolen_reserved_size,
- &adev->mman.stolen_reserved_memory,
- NULL);
- if (r)
- return r;
+ * and driver.
+ */
+ if (!adev->gmc.is_app_apu) {
+ r = amdgpu_bo_create_kernel_at(adev, 0,
+ adev->mman.stolen_vga_size,
+ &adev->mman.stolen_vga_memory,
+ NULL);
+ if (r)
+ return r;
- DRM_INFO("amdgpu: %uM of VRAM memory ready\n",
- (unsigned) (adev->gmc.real_vram_size / (1024 * 1024)));
-
- /* Compute GTT size, either based on 1/2 the size of RAM size
- * or whatever the user passed on module init */
- if (amdgpu_gtt_size == -1) {
- struct sysinfo si;
-
- si_meminfo(&si);
- /* Certain GL unit tests for large textures can cause problems
- * with the OOM killer since there is no way to link this memory
- * to a process. This was originally mitigated (but not necessarily
- * eliminated) by limiting the GTT size. The problem is this limit
- * is often too low for many modern games so just make the limit 1/2
- * of system memory which aligns with TTM. The OOM accounting needs
- * to be addressed, but we shouldn't prevent common 3D applications
- * from being usable just to potentially mitigate that corner case.
- */
- gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20),
- (u64)si.totalram * si.mem_unit / 2);
+ r = amdgpu_bo_create_kernel_at(adev, adev->mman.stolen_vga_size,
+ adev->mman.stolen_extended_size,
+ &adev->mman.stolen_extended_memory,
+ NULL);
+
+ if (r)
+ return r;
+
+ r = amdgpu_bo_create_kernel_at(adev,
+ adev->mman.stolen_reserved_offset,
+ adev->mman.stolen_reserved_size,
+ &adev->mman.stolen_reserved_memory,
+ NULL);
+ if (r)
+ return r;
} else {
- gtt_size = (uint64_t)amdgpu_gtt_size << 20;
+ DRM_DEBUG_DRIVER("Skipped stolen memory reservation\n");
}
+ DRM_INFO("amdgpu: %uM of VRAM memory ready\n",
+ (unsigned int)(adev->gmc.real_vram_size / (1024 * 1024)));
+
+ /* Compute GTT size, either based on TTM limit
+ * or whatever the user passed on module init.
+ */
+ if (amdgpu_gtt_size == -1)
+ gtt_size = ttm_tt_pages_limit() << PAGE_SHIFT;
+ else
+ gtt_size = (uint64_t)amdgpu_gtt_size << 20;
+
/* Initialize GTT memory pool */
r = amdgpu_gtt_mgr_init(adev, gtt_size);
if (r) {
@@ -1831,7 +1922,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
return r;
}
DRM_INFO("amdgpu: %uM of GTT memory ready.\n",
- (unsigned)(gtt_size / (1024 * 1024)));
+ (unsigned int)(gtt_size / (1024 * 1024)));
/* Initialize preemptible memory pool */
r = amdgpu_preempt_mgr_init(adev);
@@ -1858,7 +1949,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
DRM_ERROR("Failed initializing oa heap.\n");
return r;
}
-
if (amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_GTT,
&adev->mman.sdma_access_bo, NULL,
@@ -1874,18 +1964,24 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
void amdgpu_ttm_fini(struct amdgpu_device *adev)
{
int idx;
+
if (!adev->mman.initialized)
return;
+ amdgpu_ttm_pools_fini(adev);
+
amdgpu_ttm_training_reserve_vram_fini(adev);
/* return the stolen vga memory back to VRAM */
- amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL);
- amdgpu_bo_free_kernel(&adev->mman.stolen_extended_memory, NULL, NULL);
- /* return the IP Discovery TMR memory back to VRAM */
- amdgpu_bo_free_kernel(&adev->mman.discovery_memory, NULL, NULL);
- if (adev->mman.stolen_reserved_size)
- amdgpu_bo_free_kernel(&adev->mman.stolen_reserved_memory,
- NULL, NULL);
+ if (!adev->gmc.is_app_apu) {
+ amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL);
+ amdgpu_bo_free_kernel(&adev->mman.stolen_extended_memory, NULL, NULL);
+ /* return the FW reserved memory back to VRAM */
+ amdgpu_bo_free_kernel(&adev->mman.fw_reserved_memory, NULL,
+ NULL);
+ if (adev->mman.stolen_reserved_size)
+ amdgpu_bo_free_kernel(&adev->mman.stolen_reserved_memory,
+ NULL, NULL);
+ }
amdgpu_bo_free_kernel(&adev->mman.sdma_access_bo, NULL,
&adev->mman.sdma_access_ptr);
amdgpu_ttm_fw_reserve_vram_fini(adev);
@@ -1927,7 +2023,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
int r;
if (!adev->mman.initialized || amdgpu_in_reset(adev) ||
- adev->mman.buffer_funcs_enabled == enable)
+ adev->mman.buffer_funcs_enabled == enable || adev->gmc.is_app_apu)
return;
if (enable) {
@@ -1936,7 +2032,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
ring = adev->mman.buffer_funcs_ring;
sched = &ring->sched;
- r = drm_sched_entity_init(&adev->mman.entity,
+ r = drm_sched_entity_init(&adev->mman.high_pr,
DRM_SCHED_PRIORITY_KERNEL, &sched,
1, NULL);
if (r) {
@@ -1944,8 +2040,18 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
r);
return;
}
+
+ r = drm_sched_entity_init(&adev->mman.low_pr,
+ DRM_SCHED_PRIORITY_NORMAL, &sched,
+ 1, NULL);
+ if (r) {
+ DRM_ERROR("Failed setting up TTM BO move entity (%d)\n",
+ r);
+ goto error_free_entity;
+ }
} else {
- drm_sched_entity_destroy(&adev->mman.entity);
+ drm_sched_entity_destroy(&adev->mman.high_pr);
+ drm_sched_entity_destroy(&adev->mman.low_pr);
dma_fence_put(man->move);
man->move = NULL;
}
@@ -1957,6 +2063,11 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
size = adev->gmc.visible_vram_size;
man->size = size;
adev->mman.buffer_funcs_enabled = enable;
+
+ return;
+
+error_free_entity:
+ drm_sched_entity_destroy(&adev->mman.high_pr);
}
static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev,
@@ -1964,14 +2075,16 @@ static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev,
unsigned int num_dw,
struct dma_resv *resv,
bool vm_needs_flush,
- struct amdgpu_job **job)
+ struct amdgpu_job **job,
+ bool delayed)
{
enum amdgpu_ib_pool_type pool = direct_submit ?
AMDGPU_IB_POOL_DIRECT :
AMDGPU_IB_POOL_DELAYED;
int r;
-
- r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity,
+ struct drm_sched_entity *entity = delayed ? &adev->mman.low_pr :
+ &adev->mman.high_pr;
+ r = amdgpu_job_alloc_with_ib(adev, entity,
AMDGPU_FENCE_OWNER_UNDEFINED,
num_dw * 4, pool, job);
if (r)
@@ -1997,10 +2110,10 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
bool vm_needs_flush, bool tmz)
{
struct amdgpu_device *adev = ring->adev;
- unsigned num_loops, num_dw;
+ unsigned int num_loops, num_dw;
struct amdgpu_job *job;
uint32_t max_bytes;
- unsigned i;
+ unsigned int i;
int r;
if (!direct_submit && !ring->sched.ready) {
@@ -2012,7 +2125,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
num_loops = DIV_ROUND_UP(byte_count, max_bytes);
num_dw = ALIGN(num_loops * adev->mman.buffer_funcs->copy_num_dw, 8);
r = amdgpu_ttm_prepare_job(adev, direct_submit, num_dw,
- resv, vm_needs_flush, &job);
+ resv, vm_needs_flush, &job, false);
if (r)
return r;
@@ -2048,7 +2161,7 @@ static int amdgpu_ttm_fill_mem(struct amdgpu_ring *ring, uint32_t src_data,
uint64_t dst_addr, uint32_t byte_count,
struct dma_resv *resv,
struct dma_fence **fence,
- bool vm_needs_flush)
+ bool vm_needs_flush, bool delayed)
{
struct amdgpu_device *adev = ring->adev;
unsigned int num_loops, num_dw;
@@ -2061,7 +2174,7 @@ static int amdgpu_ttm_fill_mem(struct amdgpu_ring *ring, uint32_t src_data,
num_loops = DIV_ROUND_UP_ULL(byte_count, max_bytes);
num_dw = ALIGN(num_loops * adev->mman.buffer_funcs->fill_num_dw, 8);
r = amdgpu_ttm_prepare_job(adev, false, num_dw, resv, vm_needs_flush,
- &job);
+ &job, delayed);
if (r)
return r;
@@ -2084,7 +2197,8 @@ static int amdgpu_ttm_fill_mem(struct amdgpu_ring *ring, uint32_t src_data,
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
uint32_t src_data,
struct dma_resv *resv,
- struct dma_fence **f)
+ struct dma_fence **f,
+ bool delayed)
{
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
@@ -2113,7 +2227,7 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo,
goto error;
r = amdgpu_ttm_fill_mem(ring, src_data, to, cur_size, resv,
- &next, true);
+ &next, true, delayed);
if (r)
goto error;
@@ -2164,7 +2278,7 @@ int amdgpu_ttm_evict_resources(struct amdgpu_device *adev, int mem_type)
static int amdgpu_ttm_page_pool_show(struct seq_file *m, void *unused)
{
- struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
+ struct amdgpu_device *adev = m->private;
return ttm_pool_debugfs(&adev->mman.bdev.pool, m);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
index e2cd5894afc9..6d0d66e40db9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
@@ -49,6 +49,7 @@ struct amdgpu_gtt_mgr {
struct amdgpu_mman {
struct ttm_device bdev;
+ struct ttm_pool *ttm_pools;
bool initialized;
void __iomem *aper_base_kaddr;
@@ -58,8 +59,10 @@ struct amdgpu_mman {
bool buffer_funcs_enabled;
struct mutex gtt_window_lock;
- /* Scheduler entity for buffer moves */
- struct drm_sched_entity entity;
+ /* High priority scheduler entity for buffer moves */
+ struct drm_sched_entity high_pr;
+ /* Low priority scheduler entity for VRAM clearing */
+ struct drm_sched_entity low_pr;
struct amdgpu_vram_mgr vram_mgr;
struct amdgpu_gtt_mgr gtt_mgr;
@@ -78,7 +81,8 @@ struct amdgpu_mman {
/* discovery */
uint8_t *discovery_bin;
uint32_t discovery_tmr_size;
- struct amdgpu_bo *discovery_memory;
+ /* fw reserved memory */
+ struct amdgpu_bo *fw_reserved_memory;
/* firmware VRAM reservation */
u64 fw_vram_usage_start_offset;
@@ -150,7 +154,8 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
uint32_t src_data,
struct dma_resv *resv,
- struct dma_fence **fence);
+ struct dma_fence **fence,
+ bool delayed);
int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo);
void amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index f76b1cb8baf8..16807ff96dc9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -748,7 +748,7 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
const struct imu_firmware_header_v1_0 *imu_hdr = NULL;
u8 *ucode_addr;
- if (NULL == ucode->fw)
+ if (!ucode->fw)
return 0;
ucode->mc_addr = mc_addr;
@@ -972,7 +972,7 @@ static int amdgpu_ucode_patch_jt(struct amdgpu_firmware_info *ucode,
uint8_t *src_addr = NULL;
uint8_t *dst_addr = NULL;
- if (NULL == ucode->fw)
+ if (!ucode->fw)
return 0;
comm_hdr = (const struct common_firmware_header *)ucode->fw->data;
@@ -1043,6 +1043,7 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
if (i == AMDGPU_UCODE_ID_CP_MEC1 &&
adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
const struct gfx_firmware_header_v1_0 *cp_hdr;
+
cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
amdgpu_ucode_patch_jt(ucode, adev->firmware.fw_buf_mc + fw_offset,
adev->firmware.fw_buf_ptr + fw_offset);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
index 1edf8e6aeb16..db0d94ca4ffc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
@@ -169,27 +169,31 @@ int amdgpu_umc_poison_handler(struct amdgpu_device *adev, bool reset)
{
int ret = AMDGPU_RAS_SUCCESS;
- if (!amdgpu_sriov_vf(adev)) {
- if (!adev->gmc.xgmi.connected_to_cpu) {
- struct ras_err_data err_data = {0, 0, 0, NULL};
- struct ras_common_if head = {
- .block = AMDGPU_RAS_BLOCK__UMC,
- };
- struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head);
-
- ret = amdgpu_umc_do_page_retirement(adev, &err_data, NULL, reset);
-
- if (ret == AMDGPU_RAS_SUCCESS && obj) {
- obj->err_data.ue_count += err_data.ue_count;
- obj->err_data.ce_count += err_data.ce_count;
- }
- } else if (reset) {
+ if (adev->gmc.xgmi.connected_to_cpu ||
+ adev->gmc.is_app_apu) {
+ if (reset) {
/* MCA poison handler is only responsible for GPU reset,
* let MCA notifier do page retirement.
*/
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
amdgpu_ras_reset_gpu(adev);
}
+ return ret;
+ }
+
+ if (!amdgpu_sriov_vf(adev)) {
+ struct ras_err_data err_data = {0, 0, 0, NULL};
+ struct ras_common_if head = {
+ .block = AMDGPU_RAS_BLOCK__UMC,
+ };
+ struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head);
+
+ ret = amdgpu_umc_do_page_retirement(adev, &err_data, NULL, reset);
+
+ if (ret == AMDGPU_RAS_SUCCESS && obj) {
+ obj->err_data.ue_count += err_data.ue_count;
+ obj->err_data.ce_count += err_data.ce_count;
+ }
} else {
if (adev->virt.ops && adev->virt.ops->ras_poison_handler)
adev->virt.ops->ras_poison_handler(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
index 86133f77a9a4..43321f57f557 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
@@ -59,6 +59,8 @@ struct amdgpu_umc_ras {
void *ras_error_status);
void (*ecc_info_query_ras_error_address)(struct amdgpu_device *adev,
void *ras_error_status);
+ /* support different eeprom table version for different asic */
+ void (*set_eeprom_table_version)(struct amdgpu_ras_eeprom_table_header *hdr);
};
struct amdgpu_umc_funcs {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umr.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umr.h
index 919d9d401750..107f9bb0e24f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umr.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umr.h
@@ -35,17 +35,51 @@ struct amdgpu_debugfs_regs2_iocdata {
} srbm;
};
+struct amdgpu_debugfs_regs2_iocdata_v2 {
+ __u32 use_srbm, use_grbm, pg_lock;
+ struct {
+ __u32 se, sh, instance;
+ } grbm;
+ struct {
+ __u32 me, pipe, queue, vmid;
+ } srbm;
+ u32 xcc_id;
+};
+
+struct amdgpu_debugfs_gprwave_iocdata {
+ u32 gpr_or_wave, se, sh, cu, wave, simd, xcc_id;
+ struct {
+ u32 thread, vpgr_or_sgpr;
+ } gpr;
+};
+
/*
* MMIO debugfs state data (per file* handle)
*/
struct amdgpu_debugfs_regs2_data {
struct amdgpu_device *adev;
struct mutex lock;
- struct amdgpu_debugfs_regs2_iocdata id;
+ struct amdgpu_debugfs_regs2_iocdata_v2 id;
+};
+
+struct amdgpu_debugfs_gprwave_data {
+ struct amdgpu_device *adev;
+ struct mutex lock;
+ struct amdgpu_debugfs_gprwave_iocdata id;
};
enum AMDGPU_DEBUGFS_REGS2_CMDS {
AMDGPU_DEBUGFS_REGS2_CMD_SET_STATE=0,
+ AMDGPU_DEBUGFS_REGS2_CMD_SET_STATE_V2,
+};
+
+enum AMDGPU_DEBUGFS_GPRWAVE_CMDS {
+ AMDGPU_DEBUGFS_GPRWAVE_CMD_SET_STATE=0,
};
+//reg2 interface
#define AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE _IOWR(0x20, AMDGPU_DEBUGFS_REGS2_CMD_SET_STATE, struct amdgpu_debugfs_regs2_iocdata)
+#define AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE_V2 _IOWR(0x20, AMDGPU_DEBUGFS_REGS2_CMD_SET_STATE_V2, struct amdgpu_debugfs_regs2_iocdata_v2)
+
+//gprwave interface
+#define AMDGPU_DEBUGFS_GPRWAVE_IOC_SET_STATE _IOWR(0x20, AMDGPU_DEBUGFS_GPRWAVE_CMD_SET_STATE, struct amdgpu_debugfs_gprwave_iocdata)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index 6887109abb13..b7441654e6fa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -96,16 +96,16 @@
*/
struct amdgpu_uvd_cs_ctx {
struct amdgpu_cs_parser *parser;
- unsigned reg, count;
- unsigned data0, data1;
- unsigned idx;
+ unsigned int reg, count;
+ unsigned int data0, data1;
+ unsigned int idx;
struct amdgpu_ib *ib;
/* does the IB has a msg command */
bool has_msg_cmd;
/* minimum buffer sizes */
- unsigned *buf_sizes;
+ unsigned int *buf_sizes;
};
#ifdef CONFIG_DRM_AMDGPU_SI
@@ -186,7 +186,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
unsigned long bo_size;
const char *fw_name;
const struct common_firmware_header *hdr;
- unsigned family_id;
+ unsigned int family_id;
int i, j, r;
INIT_DELAYED_WORK(&adev->uvd.idle_work, amdgpu_uvd_idle_work_handler);
@@ -275,7 +275,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
if (adev->asic_type < CHIP_VEGA20) {
- unsigned version_major, version_minor;
+ unsigned int version_major, version_minor;
version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
@@ -420,7 +420,7 @@ int amdgpu_uvd_entity_init(struct amdgpu_device *adev)
int amdgpu_uvd_suspend(struct amdgpu_device *adev)
{
- unsigned size;
+ unsigned int size;
void *ptr;
int i, j, idx;
bool in_ras_intr = amdgpu_ras_intr_triggered();
@@ -469,7 +469,7 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)
int amdgpu_uvd_resume(struct amdgpu_device *adev)
{
- unsigned size;
+ unsigned int size;
void *ptr;
int i, idx;
@@ -491,7 +491,7 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
adev->uvd.inst[i].saved_bo = NULL;
} else {
const struct common_firmware_header *hdr;
- unsigned offset;
+ unsigned int offset;
hdr = (const struct common_firmware_header *)adev->uvd.fw->data;
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
@@ -542,6 +542,7 @@ void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo)
{
int i;
+
for (i = 0; i < abo->placement.num_placement; ++i) {
abo->placements[i].fpfn = 0 >> PAGE_SHIFT;
abo->placements[i].lpfn = (256 * 1024 * 1024) >> PAGE_SHIFT;
@@ -579,7 +580,7 @@ static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx)
r = amdgpu_cs_find_mapping(ctx->parser, addr, &bo, &mapping);
if (r) {
- DRM_ERROR("Can't find BO for addr 0x%08Lx\n", addr);
+ DRM_ERROR("Can't find BO for addr 0x%08llx\n", addr);
return r;
}
@@ -589,6 +590,7 @@ static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx)
if (cmd == 0x0 || cmd == 0x3) {
/* yes, force it into VRAM */
uint32_t domain = AMDGPU_GEM_DOMAIN_VRAM;
+
amdgpu_bo_placement_from_domain(bo, domain);
}
amdgpu_uvd_force_into_uvd_segment(bo);
@@ -609,21 +611,21 @@ static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx)
* Peek into the decode message and calculate the necessary buffer sizes.
*/
static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
- unsigned buf_sizes[])
+ unsigned int buf_sizes[])
{
- unsigned stream_type = msg[4];
- unsigned width = msg[6];
- unsigned height = msg[7];
- unsigned dpb_size = msg[9];
- unsigned pitch = msg[28];
- unsigned level = msg[57];
+ unsigned int stream_type = msg[4];
+ unsigned int width = msg[6];
+ unsigned int height = msg[7];
+ unsigned int dpb_size = msg[9];
+ unsigned int pitch = msg[28];
+ unsigned int level = msg[57];
- unsigned width_in_mb = width / 16;
- unsigned height_in_mb = ALIGN(height / 16, 2);
- unsigned fs_in_mb = width_in_mb * height_in_mb;
+ unsigned int width_in_mb = width / 16;
+ unsigned int height_in_mb = ALIGN(height / 16, 2);
+ unsigned int fs_in_mb = width_in_mb * height_in_mb;
- unsigned image_size, tmp, min_dpb_size, num_dpb_buffer;
- unsigned min_ctx_size = ~0;
+ unsigned int image_size, tmp, min_dpb_size, num_dpb_buffer;
+ unsigned int min_ctx_size = ~0;
image_size = width * height;
image_size += image_size / 2;
@@ -631,7 +633,7 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
switch (stream_type) {
case 0: /* H264 */
- switch(level) {
+ switch (level) {
case 30:
num_dpb_buffer = 8100 / fs_in_mb;
break;
@@ -709,7 +711,7 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
break;
case 7: /* H264 Perf */
- switch(level) {
+ switch (level) {
case 30:
num_dpb_buffer = 8100 / fs_in_mb;
break;
@@ -742,7 +744,7 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
/* reference picture buffer */
min_dpb_size = image_size * num_dpb_buffer;
- if (!adev->uvd.use_ctx_buf){
+ if (!adev->uvd.use_ctx_buf) {
/* macroblock context buffer */
min_dpb_size +=
width_in_mb * height_in_mb * num_dpb_buffer * 192;
@@ -805,7 +807,7 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
* Make sure that we don't open up to many sessions.
*/
static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx,
- struct amdgpu_bo *bo, unsigned offset)
+ struct amdgpu_bo *bo, unsigned int offset)
{
struct amdgpu_device *adev = ctx->parser->adev;
int32_t *msg, msg_type, handle;
@@ -911,7 +913,7 @@ static int amdgpu_uvd_cs_pass2(struct amdgpu_uvd_cs_ctx *ctx)
r = amdgpu_cs_find_mapping(ctx->parser, addr, &bo, &mapping);
if (r) {
- DRM_ERROR("Can't find BO for addr 0x%08Lx\n", addr);
+ DRM_ERROR("Can't find BO for addr 0x%08llx\n", addr);
return r;
}
@@ -930,7 +932,7 @@ static int amdgpu_uvd_cs_pass2(struct amdgpu_uvd_cs_ctx *ctx)
if (cmd < 0x4) {
if ((end - start) < ctx->buf_sizes[cmd]) {
DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd,
- (unsigned)(end - start),
+ (unsigned int)(end - start),
ctx->buf_sizes[cmd]);
return -EINVAL;
}
@@ -938,7 +940,7 @@ static int amdgpu_uvd_cs_pass2(struct amdgpu_uvd_cs_ctx *ctx)
} else if (cmd == 0x206) {
if ((end - start) < ctx->buf_sizes[4]) {
DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd,
- (unsigned)(end - start),
+ (unsigned int)(end - start),
ctx->buf_sizes[4]);
return -EINVAL;
}
@@ -949,14 +951,14 @@ static int amdgpu_uvd_cs_pass2(struct amdgpu_uvd_cs_ctx *ctx)
if (!ctx->parser->adev->uvd.address_64_bit) {
if ((start >> 28) != ((end - 1) >> 28)) {
- DRM_ERROR("reloc %LX-%LX crossing 256MB boundary!\n",
+ DRM_ERROR("reloc %llx-%llx crossing 256MB boundary!\n",
start, end);
return -EINVAL;
}
if ((cmd == 0 || cmd == 0x3) &&
(start >> 28) != (ctx->parser->adev->uvd.inst->gpu_addr >> 28)) {
- DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n",
+ DRM_ERROR("msg/fb buffer %llx-%llx out of 256MB segment!\n",
start, end);
return -EINVAL;
}
@@ -990,7 +992,7 @@ static int amdgpu_uvd_cs_reg(struct amdgpu_uvd_cs_ctx *ctx,
ctx->idx++;
for (i = 0; i <= ctx->count; ++i) {
- unsigned reg = ctx->reg + i;
+ unsigned int reg = ctx->reg + i;
if (ctx->idx >= ctx->ib->length_dw) {
DRM_ERROR("Register command after end of CS!\n");
@@ -1036,7 +1038,8 @@ static int amdgpu_uvd_cs_packets(struct amdgpu_uvd_cs_ctx *ctx,
for (ctx->idx = 0 ; ctx->idx < ctx->ib->length_dw; ) {
uint32_t cmd = amdgpu_ib_get_value(ctx->ib, ctx->idx);
- unsigned type = CP_PACKET_GET_TYPE(cmd);
+ unsigned int type = CP_PACKET_GET_TYPE(cmd);
+
switch (type) {
case PACKET_TYPE0:
ctx->reg = CP_PACKET0_GET_REG(cmd);
@@ -1070,7 +1073,7 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser,
struct amdgpu_ib *ib)
{
struct amdgpu_uvd_cs_ctx ctx = {};
- unsigned buf_sizes[] = {
+ unsigned int buf_sizes[] = {
[0x00000000] = 2048,
[0x00000001] = 0xFFFFFFFF,
[0x00000002] = 0xFFFFFFFF,
@@ -1185,8 +1188,9 @@ err_free:
}
/* multiple fence commands without any stream commands in between can
- crash the vcpu so just try to emmit a dummy create/destroy msg to
- avoid this */
+ * crash the vcpu so just try to emmit a dummy create/destroy msg to
+ * avoid this
+ */
int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
struct dma_fence **fence)
{
@@ -1252,15 +1256,14 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work)
{
struct amdgpu_device *adev =
container_of(work, struct amdgpu_device, uvd.idle_work.work);
- unsigned fences = 0, i, j;
+ unsigned int fences = 0, i, j;
for (i = 0; i < adev->uvd.num_uvd_inst; ++i) {
if (adev->uvd.harvest_config & (1 << i))
continue;
fences += amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring);
- for (j = 0; j < adev->uvd.num_enc_rings; ++j) {
+ for (j = 0; j < adev->uvd.num_enc_rings; ++j)
fences += amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring_enc[j]);
- }
}
if (fences == 0) {
@@ -1356,7 +1359,7 @@ error:
*/
uint32_t amdgpu_uvd_used_handles(struct amdgpu_device *adev)
{
- unsigned i;
+ unsigned int i;
uint32_t used_handles = 0;
for (i = 0; i < adev->uvd.max_handles; ++i) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index e2b7324a70cb..1904edf68407 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -99,7 +99,7 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
{
const char *fw_name;
const struct common_firmware_header *hdr;
- unsigned ucode_version, version_major, version_minor, binary_id;
+ unsigned int ucode_version, version_major, version_minor, binary_id;
int i, r;
switch (adev->asic_type) {
@@ -207,7 +207,7 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
*/
int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
{
- unsigned i;
+ unsigned int i;
if (adev->vce.vcpu_bo == NULL)
return 0;
@@ -286,7 +286,7 @@ int amdgpu_vce_resume(struct amdgpu_device *adev)
{
void *cpu_addr;
const struct common_firmware_header *hdr;
- unsigned offset;
+ unsigned int offset;
int r, idx;
if (adev->vce.vcpu_bo == NULL)
@@ -332,7 +332,7 @@ static void amdgpu_vce_idle_work_handler(struct work_struct *work)
{
struct amdgpu_device *adev =
container_of(work, struct amdgpu_device, vce.idle_work.work);
- unsigned i, count = 0;
+ unsigned int i, count = 0;
for (i = 0; i < adev->vce.num_rings; i++)
count += amdgpu_fence_count_emitted(&adev->vce.ring[i]);
@@ -409,6 +409,7 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
{
struct amdgpu_ring *ring = &adev->vce.ring[0];
int i, r;
+
for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
uint32_t handle = atomic_read(&adev->vce.handles[i]);
@@ -436,7 +437,7 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
struct dma_fence **fence)
{
- const unsigned ib_size_dw = 1024;
+ const unsigned int ib_size_dw = 1024;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
struct amdgpu_ib ib_msg;
@@ -528,7 +529,7 @@ err:
static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
bool direct, struct dma_fence **fence)
{
- const unsigned ib_size_dw = 1024;
+ const unsigned int ib_size_dw = 1024;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
struct dma_fence *f = NULL;
@@ -596,12 +597,12 @@ err:
*/
static int amdgpu_vce_validate_bo(struct amdgpu_cs_parser *p,
struct amdgpu_ib *ib, int lo, int hi,
- unsigned size, int32_t index)
+ unsigned int size, int32_t index)
{
int64_t offset = ((uint64_t)size) * ((int64_t)index);
struct ttm_operation_ctx ctx = { false, false };
struct amdgpu_bo_va_mapping *mapping;
- unsigned i, fpfn, lpfn;
+ unsigned int i, fpfn, lpfn;
struct amdgpu_bo *bo;
uint64_t addr;
int r;
@@ -619,7 +620,7 @@ static int amdgpu_vce_validate_bo(struct amdgpu_cs_parser *p,
r = amdgpu_cs_find_mapping(p, addr, &bo, &mapping);
if (r) {
- DRM_ERROR("Can't find BO for addr 0x%010Lx %d %d %d %d\n",
+ DRM_ERROR("Can't find BO for addr 0x%010llx %d %d %d %d\n",
addr, lo, hi, size, index);
return r;
}
@@ -646,7 +647,7 @@ static int amdgpu_vce_validate_bo(struct amdgpu_cs_parser *p,
* Patch relocation inside command stream with real buffer address
*/
static int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, struct amdgpu_ib *ib,
- int lo, int hi, unsigned size, uint32_t index)
+ int lo, int hi, unsigned int size, uint32_t index)
{
struct amdgpu_bo_va_mapping *mapping;
struct amdgpu_bo *bo;
@@ -662,14 +663,14 @@ static int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, struct amdgpu_ib *ib,
r = amdgpu_cs_find_mapping(p, addr, &bo, &mapping);
if (r) {
- DRM_ERROR("Can't find BO for addr 0x%010Lx %d %d %d %d\n",
+ DRM_ERROR("Can't find BO for addr 0x%010llx %d %d %d %d\n",
addr, lo, hi, size, index);
return r;
}
if ((addr + (uint64_t)size) >
(mapping->last + 1) * AMDGPU_GPU_PAGE_SIZE) {
- DRM_ERROR("BO too small for addr 0x%010Lx %d %d\n",
+ DRM_ERROR("BO too small for addr 0x%010llx %d %d\n",
addr, lo, hi);
return -EINVAL;
}
@@ -692,12 +693,12 @@ static int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, struct amdgpu_ib *ib,
* @allocated: allocated a new handle?
*
* Validates the handle and return the found session index or -EINVAL
- * we we don't have another free session index.
+ * we don't have another free session index.
*/
static int amdgpu_vce_validate_handle(struct amdgpu_cs_parser *p,
uint32_t handle, uint32_t *allocated)
{
- unsigned i;
+ unsigned int i;
/* validate the handle */
for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
@@ -735,14 +736,14 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p,
struct amdgpu_job *job,
struct amdgpu_ib *ib)
{
- unsigned fb_idx = 0, bs_idx = 0;
+ unsigned int fb_idx = 0, bs_idx = 0;
int session_idx = -1;
uint32_t destroyed = 0;
uint32_t created = 0;
uint32_t allocated = 0;
uint32_t tmp, handle = 0;
uint32_t *size = &tmp;
- unsigned idx;
+ unsigned int idx;
int i, r = 0;
job->vm = NULL;
@@ -1084,7 +1085,7 @@ void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring,
*
*/
void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
- unsigned flags)
+ unsigned int flags)
{
WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
@@ -1106,7 +1107,7 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
uint32_t rptr;
- unsigned i;
+ unsigned int i;
int r, timeout = adev->usec_timeout;
/* skip ring test for sriov*/
@@ -1171,7 +1172,7 @@ error:
enum amdgpu_ring_priority_level amdgpu_vce_get_ring_prio(int ring)
{
- switch(ring) {
+ switch (ring) {
case 0:
return AMDGPU_RING_PRIO_0;
case 1:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 2d94f1b63bd6..acbef1a24b9c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -56,6 +56,7 @@
#define FIRMWARE_VCN_3_1_2 "amdgpu/vcn_3_1_2.bin"
#define FIRMWARE_VCN4_0_0 "amdgpu/vcn_4_0_0.bin"
#define FIRMWARE_VCN4_0_2 "amdgpu/vcn_4_0_2.bin"
+#define FIRMWARE_VCN4_0_3 "amdgpu/vcn_4_0_3.bin"
#define FIRMWARE_VCN4_0_4 "amdgpu/vcn_4_0_4.bin"
MODULE_FIRMWARE(FIRMWARE_RAVEN);
@@ -77,6 +78,7 @@ MODULE_FIRMWARE(FIRMWARE_YELLOW_CARP);
MODULE_FIRMWARE(FIRMWARE_VCN_3_1_2);
MODULE_FIRMWARE(FIRMWARE_VCN4_0_0);
MODULE_FIRMWARE(FIRMWARE_VCN4_0_2);
+MODULE_FIRMWARE(FIRMWARE_VCN4_0_3);
MODULE_FIRMWARE(FIRMWARE_VCN4_0_4);
static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
@@ -167,7 +169,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
- if (adev->ip_versions[UVD_HWIP][0] >= IP_VERSION(4, 0, 0)){
+ if (adev->ip_versions[UVD_HWIP][0] >= IP_VERSION(4, 0, 0)) {
fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
} else {
@@ -233,11 +235,11 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
if (adev->vcn.harvest_config & (1 << j))
continue;
- if (adev->vcn.indirect_sram) {
- amdgpu_bo_free_kernel(&adev->vcn.inst[j].dpg_sram_bo,
- &adev->vcn.inst[j].dpg_sram_gpu_addr,
- (void **)&adev->vcn.inst[j].dpg_sram_cpu_addr);
- }
+ amdgpu_bo_free_kernel(
+ &adev->vcn.inst[j].dpg_sram_bo,
+ &adev->vcn.inst[j].dpg_sram_gpu_addr,
+ (void **)&adev->vcn.inst[j].dpg_sram_cpu_addr);
+
kvfree(adev->vcn.inst[j].saved_bo);
amdgpu_bo_free_kernel(&adev->vcn.inst[j].vcpu_bo,
@@ -274,20 +276,19 @@ bool amdgpu_vcn_is_disabled_vcn(struct amdgpu_device *adev, enum vcn_ring_type t
bool ret = false;
int vcn_config = adev->vcn.vcn_config[vcn_instance];
- if ((type == VCN_ENCODE_RING) && (vcn_config & VCN_BLOCK_ENCODE_DISABLE_MASK)) {
+ if ((type == VCN_ENCODE_RING) && (vcn_config & VCN_BLOCK_ENCODE_DISABLE_MASK))
ret = true;
- } else if ((type == VCN_DECODE_RING) && (vcn_config & VCN_BLOCK_DECODE_DISABLE_MASK)) {
+ else if ((type == VCN_DECODE_RING) && (vcn_config & VCN_BLOCK_DECODE_DISABLE_MASK))
ret = true;
- } else if ((type == VCN_UNIFIED_RING) && (vcn_config & VCN_BLOCK_QUEUE_DISABLE_MASK)) {
+ else if ((type == VCN_UNIFIED_RING) && (vcn_config & VCN_BLOCK_QUEUE_DISABLE_MASK))
ret = true;
- }
return ret;
}
int amdgpu_vcn_suspend(struct amdgpu_device *adev)
{
- unsigned size;
+ unsigned int size;
void *ptr;
int i, idx;
@@ -316,7 +317,7 @@ int amdgpu_vcn_suspend(struct amdgpu_device *adev)
int amdgpu_vcn_resume(struct amdgpu_device *adev)
{
- unsigned size;
+ unsigned int size;
void *ptr;
int i, idx;
@@ -338,7 +339,7 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev)
adev->vcn.inst[i].saved_bo = NULL;
} else {
const struct common_firmware_header *hdr;
- unsigned offset;
+ unsigned int offset;
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
@@ -369,9 +370,8 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
if (adev->vcn.harvest_config & (1 << j))
continue;
- for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
+ for (i = 0; i < adev->vcn.num_enc_rings; ++i)
fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_enc[i]);
- }
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
struct dpg_pause_state new_state;
@@ -458,7 +458,7 @@ int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
uint32_t tmp = 0;
- unsigned i;
+ unsigned int i;
int r;
/* VCN in SRIOV does not support direct register read/write */
@@ -795,7 +795,7 @@ int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
uint32_t rptr;
- unsigned i;
+ unsigned int i;
int r;
if (amdgpu_sriov_vf(adev))
@@ -993,11 +993,14 @@ error:
int amdgpu_vcn_unified_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
+ struct amdgpu_device *adev = ring->adev;
long r;
- r = amdgpu_vcn_enc_ring_test_ib(ring, timeout);
- if (r)
- goto error;
+ if (adev->ip_versions[UVD_HWIP][0] != IP_VERSION(4, 0, 3)) {
+ r = amdgpu_vcn_enc_ring_test_ib(ring, timeout);
+ if (r)
+ goto error;
+ }
r = amdgpu_vcn_dec_sw_ring_test_ib(ring, timeout);
@@ -1007,7 +1010,7 @@ error:
enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring)
{
- switch(ring) {
+ switch (ring) {
case 0:
return AMDGPU_RING_PRIO_0;
case 1:
@@ -1026,6 +1029,7 @@ void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev)
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
const struct common_firmware_header *hdr;
+
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
@@ -1041,6 +1045,9 @@ void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev)
adev->firmware.ucode[idx].fw = adev->vcn.fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
+
+ if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(4, 0, 3))
+ break;
}
dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
}
@@ -1051,7 +1058,7 @@ void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev)
*/
#if defined(CONFIG_DEBUG_FS)
static ssize_t amdgpu_debugfs_vcn_fwlog_read(struct file *f, char __user *buf,
- size_t size, loff_t *pos)
+ size_t size, loff_t *pos)
{
struct amdgpu_vcn_inst *vcn;
void *log_buf;
@@ -1097,7 +1104,7 @@ static ssize_t amdgpu_debugfs_vcn_fwlog_read(struct file *f, char __user *buf,
if (read_pos == AMDGPU_VCNFW_LOG_SIZE)
read_pos = plog->header_size;
if (read_num[i] == copy_to_user((buf + read_bytes),
- (log_buf + read_pos), read_num[i]))
+ (log_buf + read_pos), read_num[i]))
return -EFAULT;
read_bytes += read_num[i];
@@ -1118,7 +1125,7 @@ static const struct file_operations amdgpu_debugfs_vcnfwlog_fops = {
#endif
void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev, uint8_t i,
- struct amdgpu_vcn_inst *vcn)
+ struct amdgpu_vcn_inst *vcn)
{
#if defined(CONFIG_DEBUG_FS)
struct drm_minor *minor = adev_to_drm(adev)->primary;
@@ -1126,7 +1133,7 @@ void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev, uint8_t i,
char name[32];
sprintf(name, "amdgpu_vcn_%d_fwlog", i);
- debugfs_create_file_size(name, S_IFREG | S_IRUGO, root, vcn,
+ debugfs_create_file_size(name, S_IFREG | 0444, root, vcn,
&amdgpu_debugfs_vcnfwlog_fops,
AMDGPU_VCNFW_LOG_SIZE);
#endif
@@ -1140,7 +1147,7 @@ void amdgpu_vcn_fwlog_init(struct amdgpu_vcn_inst *vcn)
uint64_t fw_log_gpu_addr = vcn->fw_shared.gpu_addr + vcn->fw_shared.mem_size;
volatile struct amdgpu_vcn_fwlog *log_buf = fw_log_cpu_addr;
volatile struct amdgpu_fw_shared_fw_logging *fw_log = vcn->fw_shared.cpu_addr
- + vcn->fw_shared.log_offset;
+ + vcn->fw_shared.log_offset;
*flag |= cpu_to_le32(AMDGPU_VCN_FW_LOGGING_FLAG);
fw_log->is_enabled = 1;
fw_log->addr_lo = cpu_to_le32(fw_log_gpu_addr & 0xFFFFFFFF);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index f1397ef66fd7..92d5534df5f4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -32,7 +32,7 @@
#define AMDGPU_VCN_FIRMWARE_OFFSET 256
#define AMDGPU_VCN_MAX_ENC_RINGS 3
-#define AMDGPU_MAX_VCN_INSTANCES 2
+#define AMDGPU_MAX_VCN_INSTANCES 4
#define AMDGPU_MAX_VCN_ENC_RINGS AMDGPU_VCN_MAX_ENC_RINGS * AMDGPU_MAX_VCN_INSTANCES
#define AMDGPU_VCN_HARVEST_VCN0 (1 << 0)
@@ -141,18 +141,23 @@
RREG32_SOC15(VCN, inst_idx, mmUVD_DPG_LMA_DATA); \
})
-#define WREG32_SOC15_DPG_MODE(inst_idx, offset, value, mask_en, indirect) \
- do { \
- if (!indirect) { \
- WREG32_SOC15(VCN, inst_idx, mmUVD_DPG_LMA_DATA, value); \
- WREG32_SOC15(VCN, inst_idx, mmUVD_DPG_LMA_CTL, \
- (0x1 << UVD_DPG_LMA_CTL__READ_WRITE__SHIFT | \
- mask_en << UVD_DPG_LMA_CTL__MASK_EN__SHIFT | \
- offset << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT)); \
- } else { \
- *adev->vcn.inst[inst_idx].dpg_sram_curr_addr++ = offset; \
- *adev->vcn.inst[inst_idx].dpg_sram_curr_addr++ = value; \
- } \
+#define WREG32_SOC15_DPG_MODE(inst_idx, offset, value, mask_en, indirect) \
+ do { \
+ if (!indirect) { \
+ WREG32_SOC15(VCN, GET_INST(VCN, inst_idx), \
+ mmUVD_DPG_LMA_DATA, value); \
+ WREG32_SOC15( \
+ VCN, GET_INST(VCN, inst_idx), \
+ mmUVD_DPG_LMA_CTL, \
+ (0x1 << UVD_DPG_LMA_CTL__READ_WRITE__SHIFT | \
+ mask_en << UVD_DPG_LMA_CTL__MASK_EN__SHIFT | \
+ offset << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT)); \
+ } else { \
+ *adev->vcn.inst[inst_idx].dpg_sram_curr_addr++ = \
+ offset; \
+ *adev->vcn.inst[inst_idx].dpg_sram_curr_addr++ = \
+ value; \
+ } \
} while (0)
#define AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE (1 << 2)
@@ -243,6 +248,7 @@ struct amdgpu_vcn_inst {
uint32_t *dpg_sram_curr_addr;
atomic_t dpg_enc_submission_cnt;
struct amdgpu_vcn_fw_shared fw_shared;
+ uint8_t aid_id;
};
struct amdgpu_vcn_ras {
@@ -272,6 +278,9 @@ struct amdgpu_vcn {
struct ras_common_if *ras_if;
struct amdgpu_vcn_ras *ras;
+
+ uint16_t inst_mask;
+ uint8_t num_inst_per_aid;
};
struct amdgpu_fw_shared_rb_ptrs_struct {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
index f2e2cbaa7fde..25b4d7f0bd35 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -56,7 +56,8 @@ void amdgpu_virt_init_setting(struct amdgpu_device *adev)
/* enable virtual display */
if (adev->asic_type != CHIP_ALDEBARAN &&
- adev->asic_type != CHIP_ARCTURUS) {
+ adev->asic_type != CHIP_ARCTURUS &&
+ ((adev->pdev->class >> 8) != PCI_CLASS_ACCELERATOR_PROCESSING)) {
if (adev->mode_info.num_crtc == 0)
adev->mode_info.num_crtc = 1;
adev->enable_virtual_display = true;
@@ -65,16 +66,19 @@ void amdgpu_virt_init_setting(struct amdgpu_device *adev)
adev->cg_flags = 0;
adev->pg_flags = 0;
- /* enable mcbp for sriov asic_type before soc21 */
- amdgpu_mcbp = (adev->asic_type < CHIP_IP_DISCOVERY) ? 1 : 0;
+ /* enable mcbp for sriov */
+ amdgpu_mcbp = 1;
+ /* Reduce kcq number to 2 to reduce latency */
+ if (amdgpu_num_kcq == -1)
+ amdgpu_num_kcq = 2;
}
void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
uint32_t reg0, uint32_t reg1,
uint32_t ref, uint32_t mask)
{
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
struct amdgpu_ring *ring = &kiq->ring;
signed long r, cnt = 0;
unsigned long flags;
@@ -557,7 +561,6 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev)
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLS, adev->gfx.rlc_srls_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC, adev->gfx.mec_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2, adev->gfx.mec2_fw_version);
- POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_IMU, adev->gfx.imu_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS, adev->psp.sos.fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD,
adev->psp.asd_context.bin_desc.fw_version);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 3c0310576b3b..143d11afe0e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -267,6 +267,32 @@ static void amdgpu_vm_bo_done(struct amdgpu_vm_bo_base *vm_bo)
}
/**
+ * amdgpu_vm_bo_reset_state_machine - reset the vm_bo state machine
+ * @vm: the VM which state machine to reset
+ *
+ * Move all vm_bo object in the VM into a state where they will be updated
+ * again during validation.
+ */
+static void amdgpu_vm_bo_reset_state_machine(struct amdgpu_vm *vm)
+{
+ struct amdgpu_vm_bo_base *vm_bo, *tmp;
+
+ spin_lock(&vm->status_lock);
+ list_splice_init(&vm->done, &vm->invalidated);
+ list_for_each_entry(vm_bo, &vm->invalidated, vm_status)
+ vm_bo->moved = true;
+ list_for_each_entry_safe(vm_bo, tmp, &vm->idle, vm_status) {
+ struct amdgpu_bo *bo = vm_bo->bo;
+
+ if (!bo || bo->tbo.type != ttm_bo_type_kernel)
+ list_move(&vm_bo->vm_status, &vm_bo->vm->moved);
+ else if (bo->parent)
+ list_move(&vm_bo->vm_status, &vm_bo->vm->relocated);
+ }
+ spin_unlock(&vm->status_lock);
+}
+
+/**
* amdgpu_vm_bo_base_init - Adds bo to the list of bos associated with the vm
*
* @base: base structure for tracking BO usage in a VM
@@ -351,6 +377,58 @@ void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev,
spin_unlock(&adev->mman.bdev.lru_lock);
}
+/* Create scheduler entities for page table updates */
+static int amdgpu_vm_init_entities(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm)
+{
+ int r;
+
+ r = drm_sched_entity_init(&vm->immediate, DRM_SCHED_PRIORITY_NORMAL,
+ adev->vm_manager.vm_pte_scheds,
+ adev->vm_manager.vm_pte_num_scheds, NULL);
+ if (r)
+ goto error;
+
+ return drm_sched_entity_init(&vm->delayed, DRM_SCHED_PRIORITY_NORMAL,
+ adev->vm_manager.vm_pte_scheds,
+ adev->vm_manager.vm_pte_num_scheds, NULL);
+
+error:
+ drm_sched_entity_destroy(&vm->immediate);
+ return r;
+}
+
+/* Destroy the entities for page table updates again */
+static void amdgpu_vm_fini_entities(struct amdgpu_vm *vm)
+{
+ drm_sched_entity_destroy(&vm->immediate);
+ drm_sched_entity_destroy(&vm->delayed);
+}
+
+/**
+ * amdgpu_vm_generation - return the page table re-generation counter
+ * @adev: the amdgpu_device
+ * @vm: optional VM to check, might be NULL
+ *
+ * Returns a page table re-generation token to allow checking if submissions
+ * are still valid to use this VM. The VM parameter might be NULL in which case
+ * just the VRAM lost counter will be used.
+ */
+uint64_t amdgpu_vm_generation(struct amdgpu_device *adev, struct amdgpu_vm *vm)
+{
+ uint64_t result = (u64)atomic_read(&adev->vram_lost_counter) << 32;
+
+ if (!vm)
+ return result;
+
+ result += vm->generation;
+ /* Add one if the page tables will be re-generated on next CS */
+ if (drm_sched_entity_error(&vm->delayed))
+ ++result;
+
+ return result;
+}
+
/**
* amdgpu_vm_validate_pt_bos - validate the page table BOs
*
@@ -373,6 +451,15 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
struct amdgpu_bo *bo;
int r;
+ if (drm_sched_entity_error(&vm->delayed)) {
+ ++vm->generation;
+ amdgpu_vm_bo_reset_state_machine(vm);
+ amdgpu_vm_fini_entities(vm);
+ r = amdgpu_vm_init_entities(adev, vm);
+ if (r)
+ return r;
+ }
+
spin_lock(&vm->status_lock);
while (!list_empty(&vm->evicted)) {
bo_base = list_first_entry(&vm->evicted,
@@ -920,42 +1007,51 @@ error_unlock:
return r;
}
+static void amdgpu_vm_bo_get_memory(struct amdgpu_bo_va *bo_va,
+ struct amdgpu_mem_stats *stats)
+{
+ struct amdgpu_vm *vm = bo_va->base.vm;
+ struct amdgpu_bo *bo = bo_va->base.bo;
+
+ if (!bo)
+ return;
+
+ /*
+ * For now ignore BOs which are currently locked and potentially
+ * changing their location.
+ */
+ if (bo->tbo.base.resv != vm->root.bo->tbo.base.resv &&
+ !dma_resv_trylock(bo->tbo.base.resv))
+ return;
+
+ amdgpu_bo_get_memory(bo, stats);
+ if (bo->tbo.base.resv != vm->root.bo->tbo.base.resv)
+ dma_resv_unlock(bo->tbo.base.resv);
+}
+
void amdgpu_vm_get_memory(struct amdgpu_vm *vm,
struct amdgpu_mem_stats *stats)
{
struct amdgpu_bo_va *bo_va, *tmp;
spin_lock(&vm->status_lock);
- list_for_each_entry_safe(bo_va, tmp, &vm->idle, base.vm_status) {
- if (!bo_va->base.bo)
- continue;
- amdgpu_bo_get_memory(bo_va->base.bo, stats);
- }
- list_for_each_entry_safe(bo_va, tmp, &vm->evicted, base.vm_status) {
- if (!bo_va->base.bo)
- continue;
- amdgpu_bo_get_memory(bo_va->base.bo, stats);
- }
- list_for_each_entry_safe(bo_va, tmp, &vm->relocated, base.vm_status) {
- if (!bo_va->base.bo)
- continue;
- amdgpu_bo_get_memory(bo_va->base.bo, stats);
- }
- list_for_each_entry_safe(bo_va, tmp, &vm->moved, base.vm_status) {
- if (!bo_va->base.bo)
- continue;
- amdgpu_bo_get_memory(bo_va->base.bo, stats);
- }
- list_for_each_entry_safe(bo_va, tmp, &vm->invalidated, base.vm_status) {
- if (!bo_va->base.bo)
- continue;
- amdgpu_bo_get_memory(bo_va->base.bo, stats);
- }
- list_for_each_entry_safe(bo_va, tmp, &vm->done, base.vm_status) {
- if (!bo_va->base.bo)
- continue;
- amdgpu_bo_get_memory(bo_va->base.bo, stats);
- }
+ list_for_each_entry_safe(bo_va, tmp, &vm->idle, base.vm_status)
+ amdgpu_vm_bo_get_memory(bo_va, stats);
+
+ list_for_each_entry_safe(bo_va, tmp, &vm->evicted, base.vm_status)
+ amdgpu_vm_bo_get_memory(bo_va, stats);
+
+ list_for_each_entry_safe(bo_va, tmp, &vm->relocated, base.vm_status)
+ amdgpu_vm_bo_get_memory(bo_va, stats);
+
+ list_for_each_entry_safe(bo_va, tmp, &vm->moved, base.vm_status)
+ amdgpu_vm_bo_get_memory(bo_va, stats);
+
+ list_for_each_entry_safe(bo_va, tmp, &vm->invalidated, base.vm_status)
+ amdgpu_vm_bo_get_memory(bo_va, stats);
+
+ list_for_each_entry_safe(bo_va, tmp, &vm->done, base.vm_status)
+ amdgpu_vm_bo_get_memory(bo_va, stats);
spin_unlock(&vm->status_lock);
}
@@ -1358,6 +1454,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
amdgpu_vm_bo_base_init(&bo_va->base, vm, bo);
bo_va->ref_count = 1;
+ bo_va->last_pt_update = dma_fence_get_stub();
INIT_LIST_HEAD(&bo_va->valids);
INIT_LIST_HEAD(&bo_va->invalids);
@@ -1433,14 +1530,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
uint64_t eaddr;
/* validate the parameters */
- if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK ||
- size == 0 || size & ~PAGE_MASK)
+ if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
+ return -EINVAL;
+ if (saddr + size <= saddr || offset + size <= offset)
return -EINVAL;
/* make sure object fit at this offset */
eaddr = saddr + size - 1;
- if (saddr >= eaddr ||
- (bo && offset + size > amdgpu_bo_size(bo)) ||
+ if ((bo && offset + size > amdgpu_bo_size(bo)) ||
(eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT))
return -EINVAL;
@@ -1499,14 +1596,14 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
int r;
/* validate the parameters */
- if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK ||
- size == 0 || size & ~PAGE_MASK)
+ if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
+ return -EINVAL;
+ if (saddr + size <= saddr || offset + size <= offset)
return -EINVAL;
/* make sure object fit at this offset */
eaddr = saddr + size - 1;
- if (saddr >= eaddr ||
- (bo && offset + size > amdgpu_bo_size(bo)) ||
+ if ((bo && offset + size > amdgpu_bo_size(bo)) ||
(eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT))
return -EINVAL;
@@ -2038,19 +2135,10 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
INIT_LIST_HEAD(&vm->pt_freed);
INIT_WORK(&vm->pt_free_work, amdgpu_vm_pt_free_work);
- /* create scheduler entities for page table updates */
- r = drm_sched_entity_init(&vm->immediate, DRM_SCHED_PRIORITY_NORMAL,
- adev->vm_manager.vm_pte_scheds,
- adev->vm_manager.vm_pte_num_scheds, NULL);
+ r = amdgpu_vm_init_entities(adev, vm);
if (r)
return r;
- r = drm_sched_entity_init(&vm->delayed, DRM_SCHED_PRIORITY_NORMAL,
- adev->vm_manager.vm_pte_scheds,
- adev->vm_manager.vm_pte_num_scheds, NULL);
- if (r)
- goto error_free_immediate;
-
vm->pte_support_ats = false;
vm->is_compute_context = false;
@@ -2067,9 +2155,11 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
vm->update_funcs = &amdgpu_vm_cpu_funcs;
else
vm->update_funcs = &amdgpu_vm_sdma_funcs;
- vm->last_update = NULL;
+
+ vm->last_update = dma_fence_get_stub();
vm->last_unlocked = dma_fence_get_stub();
vm->last_tlb_flush = dma_fence_get_stub();
+ vm->generation = 0;
mutex_init(&vm->eviction_lock);
vm->evicting = false;
@@ -2110,10 +2200,7 @@ error_free_root:
error_free_delayed:
dma_fence_put(vm->last_tlb_flush);
dma_fence_put(vm->last_unlocked);
- drm_sched_entity_destroy(&vm->delayed);
-
-error_free_immediate:
- drm_sched_entity_destroy(&vm->immediate);
+ amdgpu_vm_fini_entities(vm);
return r;
}
@@ -2192,7 +2279,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
goto unreserve_bo;
dma_fence_put(vm->last_update);
- vm->last_update = NULL;
+ vm->last_update = dma_fence_get_stub();
vm->is_compute_context = true;
/* Free the shadow bo for compute VM */
@@ -2266,8 +2353,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
amdgpu_bo_unref(&root);
WARN_ON(vm->root.bo);
- drm_sched_entity_destroy(&vm->immediate);
- drm_sched_entity_destroy(&vm->delayed);
+ amdgpu_vm_fini_entities(vm);
if (!RB_EMPTY_ROOT(&vm->va.rb_root)) {
dev_err(adev->dev, "still active bo inside vm\n");
@@ -2282,8 +2368,14 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
}
dma_fence_put(vm->last_update);
- for (i = 0; i < AMDGPU_MAX_VMHUBS; i++)
- amdgpu_vmid_free_reserved(adev, vm, i);
+
+ for (i = 0; i < AMDGPU_MAX_VMHUBS; i++) {
+ if (vm->reserved_vmid[i]) {
+ amdgpu_vmid_free_reserved(adev, i);
+ vm->reserved_vmid[i] = false;
+ }
+ }
+
}
/**
@@ -2366,18 +2458,25 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
union drm_amdgpu_vm *args = data;
struct amdgpu_device *adev = drm_to_adev(dev);
struct amdgpu_fpriv *fpriv = filp->driver_priv;
- int r;
+
+ /* No valid flags defined yet */
+ if (args->in.flags)
+ return -EINVAL;
switch (args->in.op) {
case AMDGPU_VM_OP_RESERVE_VMID:
/* We only have requirement to reserve vmid from gfxhub */
- r = amdgpu_vmid_alloc_reserved(adev, &fpriv->vm,
- AMDGPU_GFXHUB_0);
- if (r)
- return r;
+ if (!fpriv->vm.reserved_vmid[AMDGPU_GFXHUB(0)]) {
+ amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(0));
+ fpriv->vm.reserved_vmid[AMDGPU_GFXHUB(0)] = true;
+ }
+
break;
case AMDGPU_VM_OP_UNRESERVE_VMID:
- amdgpu_vmid_free_reserved(adev, &fpriv->vm, AMDGPU_GFXHUB_0);
+ if (fpriv->vm.reserved_vmid[AMDGPU_GFXHUB(0)]) {
+ amdgpu_vmid_free_reserved(adev, AMDGPU_GFXHUB(0));
+ fpriv->vm.reserved_vmid[AMDGPU_GFXHUB(0)] = false;
+ }
break;
default:
return -EINVAL;
@@ -2432,6 +2531,9 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm)
* amdgpu_vm_handle_fault - graceful handling of VM faults.
* @adev: amdgpu device pointer
* @pasid: PASID of the VM
+ * @vmid: VMID, only used for GFX 9.4.3.
+ * @node_id: Node_id received in IH cookie. Only applicable for
+ * GFX 9.4.3.
* @addr: Address of the fault
* @write_fault: true is write fault, false is read fault
*
@@ -2439,7 +2541,8 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm)
* shouldn't be reported any more.
*/
bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
- uint64_t addr, bool write_fault)
+ u32 vmid, u32 node_id, uint64_t addr,
+ bool write_fault)
{
bool is_compute_context = false;
struct amdgpu_bo *root;
@@ -2463,8 +2566,8 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
addr /= AMDGPU_GPU_PAGE_SIZE;
- if (is_compute_context &&
- !svm_range_restore_pages(adev, pasid, addr, write_fault)) {
+ if (is_compute_context && !svm_range_restore_pages(adev, pasid, vmid,
+ node_id, addr, write_fault)) {
amdgpu_bo_unref(&root);
return true;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 6f085f0b4ef3..9c85d494f2a2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -111,11 +111,14 @@ struct amdgpu_mem_stats;
/* Reserve 4MB VRAM for page tables */
#define AMDGPU_VM_RESERVED_VRAM (8ULL << 20)
-/* max number of VMHUB */
-#define AMDGPU_MAX_VMHUBS 3
-#define AMDGPU_GFXHUB_0 0
-#define AMDGPU_MMHUB_0 1
-#define AMDGPU_MMHUB_1 2
+/*
+ * max number of VMHUB
+ * layout: max 8 GFXHUB + 4 MMHUB0 + 1 MMHUB1
+ */
+#define AMDGPU_MAX_VMHUBS 13
+#define AMDGPU_GFXHUB(x) (x)
+#define AMDGPU_MMHUB0(x) (8 + x)
+#define AMDGPU_MMHUB1(x) (8 + 4 + x)
/* Reserve 2MB at top/bottom of address space for kernel use */
#define AMDGPU_VA_RESERVED_SIZE (2ULL << 20)
@@ -292,6 +295,9 @@ struct amdgpu_vm {
atomic64_t tlb_seq;
struct dma_fence *last_tlb_flush;
+ /* How many times we had to re-generate the page tables */
+ uint64_t generation;
+
/* Last unlocked submission to the scheduler entities */
struct dma_fence *last_unlocked;
@@ -326,6 +332,9 @@ struct amdgpu_vm {
struct ttm_lru_bulk_move lru_bulk_move;
/* Flag to indicate if VM is used for compute */
bool is_compute_context;
+
+ /* Memory partition number, -1 means any partition */
+ int8_t mem_id;
};
struct amdgpu_vm_manager {
@@ -391,6 +400,7 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
struct list_head *validated,
struct amdgpu_bo_list_entry *entry);
bool amdgpu_vm_ready(struct amdgpu_vm *vm);
+uint64_t amdgpu_vm_generation(struct amdgpu_device *adev, struct amdgpu_vm *vm);
int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
int (*callback)(void *p, struct amdgpu_bo *bo),
void *param);
@@ -452,7 +462,8 @@ void amdgpu_vm_check_compute_bug(struct amdgpu_device *adev);
void amdgpu_vm_get_task_info(struct amdgpu_device *adev, u32 pasid,
struct amdgpu_task_info *task_info);
bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
- uint64_t addr, bool write_fault);
+ u32 vmid, u32 node_id, uint64_t addr,
+ bool write_fault);
void amdgpu_vm_set_task_info(struct amdgpu_vm *vm);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
index 051c7194ab4f..dea1a64be44d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
@@ -502,6 +502,7 @@ exit:
int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
int level, bool immediate, struct amdgpu_bo_vm **vmbo)
{
+ struct amdgpu_fpriv *fpriv = container_of(vm, struct amdgpu_fpriv, vm);
struct amdgpu_bo_param bp;
struct amdgpu_bo *bo;
struct dma_resv *resv;
@@ -512,7 +513,12 @@ int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
bp.size = amdgpu_vm_pt_size(adev, level);
bp.byte_align = AMDGPU_GPU_PAGE_SIZE;
- bp.domain = AMDGPU_GEM_DOMAIN_VRAM;
+
+ if (!adev->gmc.is_app_apu)
+ bp.domain = AMDGPU_GEM_DOMAIN_VRAM;
+ else
+ bp.domain = AMDGPU_GEM_DOMAIN_GTT;
+
bp.domain = amdgpu_bo_get_preferred_domain(adev, bp.domain);
bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
AMDGPU_GEM_CREATE_CPU_GTT_USWC;
@@ -529,6 +535,8 @@ int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
bp.type = ttm_bo_type_kernel;
bp.no_wait_gpu = immediate;
+ bp.xcp_id_plus1 = fpriv->xcp_id == ~0 ? 0 : fpriv->xcp_id + 1;
+
if (vm->root.bo)
bp.resv = vm->root.bo->tbo.base.resv;
@@ -553,6 +561,7 @@ int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
bp.type = ttm_bo_type_kernel;
bp.resv = bo->tbo.base.resv;
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
+ bp.xcp_id_plus1 = fpriv->xcp_id == ~0 ? 0 : fpriv->xcp_id + 1;
r = amdgpu_bo_create(adev, &bp, &(*vmbo)->shadow);
@@ -780,13 +789,14 @@ static void amdgpu_vm_pte_update_flags(struct amdgpu_vm_update_params *params,
uint64_t pe, uint64_t addr,
unsigned int count, uint32_t incr,
uint64_t flags)
-
{
+ struct amdgpu_device *adev = params->adev;
+
if (level != AMDGPU_VM_PTB) {
flags |= AMDGPU_PDE_PTE;
- amdgpu_gmc_get_vm_pde(params->adev, level, &addr, &flags);
+ amdgpu_gmc_get_vm_pde(adev, level, &addr, &flags);
- } else if (params->adev->asic_type >= CHIP_VEGA10 &&
+ } else if (adev->asic_type >= CHIP_VEGA10 &&
!(flags & AMDGPU_PTE_VALID) &&
!(flags & AMDGPU_PTE_PRT)) {
@@ -794,6 +804,21 @@ static void amdgpu_vm_pte_update_flags(struct amdgpu_vm_update_params *params,
flags |= AMDGPU_PTE_EXECUTABLE;
}
+ /* APUs mapping system memory may need different MTYPEs on different
+ * NUMA nodes. Only do this for contiguous ranges that can be assumed
+ * to be on the same NUMA node.
+ */
+ if ((flags & AMDGPU_PTE_SYSTEM) && (adev->flags & AMD_IS_APU) &&
+ adev->gmc.gmc_funcs->override_vm_pte_flags &&
+ num_possible_nodes() > 1) {
+ if (!params->pages_addr)
+ amdgpu_gmc_override_vm_pte_flags(adev, params->vm,
+ addr, &flags);
+ else
+ dev_dbg(adev->dev,
+ "override_vm_pte_flags skipped: non-contiguous\n");
+ }
+
params->vm->update_funcs->update(params, pt, pe, addr, count, incr,
flags);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
index afacfb9b5bf6..c7085a747b03 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -370,6 +370,45 @@ out:
return ret;
}
+static void amdgpu_dummy_vram_mgr_debug(struct ttm_resource_manager *man,
+ struct drm_printer *printer)
+{
+ DRM_DEBUG_DRIVER("Dummy vram mgr debug\n");
+}
+
+static bool amdgpu_dummy_vram_mgr_compatible(struct ttm_resource_manager *man,
+ struct ttm_resource *res,
+ const struct ttm_place *place,
+ size_t size)
+{
+ DRM_DEBUG_DRIVER("Dummy vram mgr compatible\n");
+ return false;
+}
+
+static bool amdgpu_dummy_vram_mgr_intersects(struct ttm_resource_manager *man,
+ struct ttm_resource *res,
+ const struct ttm_place *place,
+ size_t size)
+{
+ DRM_DEBUG_DRIVER("Dummy vram mgr intersects\n");
+ return true;
+}
+
+static void amdgpu_dummy_vram_mgr_del(struct ttm_resource_manager *man,
+ struct ttm_resource *res)
+{
+ DRM_DEBUG_DRIVER("Dummy vram mgr deleted\n");
+}
+
+static int amdgpu_dummy_vram_mgr_new(struct ttm_resource_manager *man,
+ struct ttm_buffer_object *tbo,
+ const struct ttm_place *place,
+ struct ttm_resource **res)
+{
+ DRM_DEBUG_DRIVER("Dummy vram mgr new\n");
+ return -ENOSPC;
+}
+
/**
* amdgpu_vram_mgr_new - allocate new ranges
*
@@ -818,6 +857,14 @@ static void amdgpu_vram_mgr_debug(struct ttm_resource_manager *man,
mutex_unlock(&mgr->lock);
}
+static const struct ttm_resource_manager_func amdgpu_dummy_vram_mgr_func = {
+ .alloc = amdgpu_dummy_vram_mgr_new,
+ .free = amdgpu_dummy_vram_mgr_del,
+ .intersects = amdgpu_dummy_vram_mgr_intersects,
+ .compatible = amdgpu_dummy_vram_mgr_compatible,
+ .debug = amdgpu_dummy_vram_mgr_debug
+};
+
static const struct ttm_resource_manager_func amdgpu_vram_mgr_func = {
.alloc = amdgpu_vram_mgr_new,
.free = amdgpu_vram_mgr_del,
@@ -842,17 +889,22 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev)
ttm_resource_manager_init(man, &adev->mman.bdev,
adev->gmc.real_vram_size);
- man->func = &amdgpu_vram_mgr_func;
-
- err = drm_buddy_init(&mgr->mm, man->size, PAGE_SIZE);
- if (err)
- return err;
-
mutex_init(&mgr->lock);
INIT_LIST_HEAD(&mgr->reservations_pending);
INIT_LIST_HEAD(&mgr->reserved_pages);
mgr->default_page_size = PAGE_SIZE;
+ if (!adev->gmc.is_app_apu) {
+ man->func = &amdgpu_vram_mgr_func;
+
+ err = drm_buddy_init(&mgr->mm, man->size, PAGE_SIZE);
+ if (err)
+ return err;
+ } else {
+ man->func = &amdgpu_dummy_vram_mgr_func;
+ DRM_INFO("Setup dummy vram mgr\n");
+ }
+
ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_VRAM, &mgr->manager);
ttm_resource_manager_set_used(man, true);
return 0;
@@ -887,7 +939,8 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev)
drm_buddy_free_list(&mgr->mm, &rsv->allocated);
kfree(rsv);
}
- drm_buddy_fini(&mgr->mm);
+ if (!adev->gmc.is_app_apu)
+ drm_buddy_fini(&mgr->mm);
mutex_unlock(&mgr->lock);
ttm_resource_manager_cleanup(man);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
new file mode 100644
index 000000000000..d733fa6e7477
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "amdgpu_xcp.h"
+#include "amdgpu_drv.h"
+
+#include <drm/drm_drv.h>
+#include "../amdxcp/amdgpu_xcp_drv.h"
+
+static int __amdgpu_xcp_run(struct amdgpu_xcp_mgr *xcp_mgr,
+ struct amdgpu_xcp_ip *xcp_ip, int xcp_state)
+{
+ int (*run_func)(void *handle, uint32_t inst_mask);
+ int ret = 0;
+
+ if (!xcp_ip || !xcp_ip->valid || !xcp_ip->ip_funcs)
+ return 0;
+
+ run_func = NULL;
+
+ switch (xcp_state) {
+ case AMDGPU_XCP_PREPARE_SUSPEND:
+ run_func = xcp_ip->ip_funcs->prepare_suspend;
+ break;
+ case AMDGPU_XCP_SUSPEND:
+ run_func = xcp_ip->ip_funcs->suspend;
+ break;
+ case AMDGPU_XCP_PREPARE_RESUME:
+ run_func = xcp_ip->ip_funcs->prepare_resume;
+ break;
+ case AMDGPU_XCP_RESUME:
+ run_func = xcp_ip->ip_funcs->resume;
+ break;
+ }
+
+ if (run_func)
+ ret = run_func(xcp_mgr->adev, xcp_ip->inst_mask);
+
+ return ret;
+}
+
+static int amdgpu_xcp_run_transition(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id,
+ int state)
+{
+ struct amdgpu_xcp_ip *xcp_ip;
+ struct amdgpu_xcp *xcp;
+ int i, ret;
+
+ if (xcp_id >= MAX_XCP || !xcp_mgr->xcp[xcp_id].valid)
+ return -EINVAL;
+
+ xcp = &xcp_mgr->xcp[xcp_id];
+ for (i = 0; i < AMDGPU_XCP_MAX_BLOCKS; ++i) {
+ xcp_ip = &xcp->ip[i];
+ ret = __amdgpu_xcp_run(xcp_mgr, xcp_ip, state);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+int amdgpu_xcp_prepare_suspend(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id)
+{
+ return amdgpu_xcp_run_transition(xcp_mgr, xcp_id,
+ AMDGPU_XCP_PREPARE_SUSPEND);
+}
+
+int amdgpu_xcp_suspend(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id)
+{
+ return amdgpu_xcp_run_transition(xcp_mgr, xcp_id, AMDGPU_XCP_SUSPEND);
+}
+
+int amdgpu_xcp_prepare_resume(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id)
+{
+ return amdgpu_xcp_run_transition(xcp_mgr, xcp_id,
+ AMDGPU_XCP_PREPARE_RESUME);
+}
+
+int amdgpu_xcp_resume(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id)
+{
+ return amdgpu_xcp_run_transition(xcp_mgr, xcp_id, AMDGPU_XCP_RESUME);
+}
+
+static void __amdgpu_xcp_add_block(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id,
+ struct amdgpu_xcp_ip *ip)
+{
+ struct amdgpu_xcp *xcp;
+
+ if (!ip)
+ return;
+
+ xcp = &xcp_mgr->xcp[xcp_id];
+ xcp->ip[ip->ip_id] = *ip;
+ xcp->ip[ip->ip_id].valid = true;
+
+ xcp->valid = true;
+}
+
+int amdgpu_xcp_init(struct amdgpu_xcp_mgr *xcp_mgr, int num_xcps, int mode)
+{
+ struct amdgpu_device *adev = xcp_mgr->adev;
+ struct amdgpu_xcp_ip ip;
+ uint8_t mem_id;
+ int i, j, ret;
+
+ if (!num_xcps || num_xcps > MAX_XCP)
+ return -EINVAL;
+
+ xcp_mgr->mode = mode;
+
+ for (i = 0; i < MAX_XCP; ++i)
+ xcp_mgr->xcp[i].valid = false;
+
+ for (i = 0; i < num_xcps; ++i) {
+ for (j = AMDGPU_XCP_GFXHUB; j < AMDGPU_XCP_MAX_BLOCKS; ++j) {
+ ret = xcp_mgr->funcs->get_ip_details(xcp_mgr, i, j,
+ &ip);
+ if (ret)
+ continue;
+
+ __amdgpu_xcp_add_block(xcp_mgr, i, &ip);
+ }
+
+ xcp_mgr->xcp[i].id = i;
+
+ if (xcp_mgr->funcs->get_xcp_mem_id) {
+ ret = xcp_mgr->funcs->get_xcp_mem_id(
+ xcp_mgr, &xcp_mgr->xcp[i], &mem_id);
+ if (ret)
+ continue;
+ else
+ xcp_mgr->xcp[i].mem_id = mem_id;
+ }
+ }
+
+ xcp_mgr->num_xcps = num_xcps;
+ amdgpu_xcp_update_partition_sched_list(adev);
+
+ xcp_mgr->num_xcp_per_mem_partition = num_xcps / xcp_mgr->adev->gmc.num_mem_partitions;
+ return 0;
+}
+
+int amdgpu_xcp_switch_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, int mode)
+{
+ int ret, curr_mode, num_xcps = 0;
+
+ if (!xcp_mgr || mode == AMDGPU_XCP_MODE_NONE)
+ return -EINVAL;
+
+ if (xcp_mgr->mode == mode)
+ return 0;
+
+ if (!xcp_mgr->funcs || !xcp_mgr->funcs->switch_partition_mode)
+ return 0;
+
+ mutex_lock(&xcp_mgr->xcp_lock);
+
+ curr_mode = xcp_mgr->mode;
+ /* State set to transient mode */
+ xcp_mgr->mode = AMDGPU_XCP_MODE_TRANS;
+
+ ret = xcp_mgr->funcs->switch_partition_mode(xcp_mgr, mode, &num_xcps);
+
+ if (ret) {
+ /* Failed, get whatever mode it's at now */
+ if (xcp_mgr->funcs->query_partition_mode)
+ xcp_mgr->mode = amdgpu_xcp_query_partition_mode(
+ xcp_mgr, AMDGPU_XCP_FL_LOCKED);
+ else
+ xcp_mgr->mode = curr_mode;
+
+ goto out;
+ }
+
+out:
+ mutex_unlock(&xcp_mgr->xcp_lock);
+
+ return ret;
+}
+
+int amdgpu_xcp_query_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, u32 flags)
+{
+ int mode;
+
+ if (xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
+ return xcp_mgr->mode;
+
+ if (!xcp_mgr->funcs || !xcp_mgr->funcs->query_partition_mode)
+ return xcp_mgr->mode;
+
+ if (!(flags & AMDGPU_XCP_FL_LOCKED))
+ mutex_lock(&xcp_mgr->xcp_lock);
+ mode = xcp_mgr->funcs->query_partition_mode(xcp_mgr);
+ if (xcp_mgr->mode != AMDGPU_XCP_MODE_TRANS && mode != xcp_mgr->mode)
+ dev_WARN(
+ xcp_mgr->adev->dev,
+ "Cached partition mode %d not matching with device mode %d",
+ xcp_mgr->mode, mode);
+
+ if (!(flags & AMDGPU_XCP_FL_LOCKED))
+ mutex_unlock(&xcp_mgr->xcp_lock);
+
+ return mode;
+}
+
+static int amdgpu_xcp_dev_alloc(struct amdgpu_device *adev)
+{
+ struct drm_device *p_ddev;
+ struct drm_device *ddev;
+ int i, ret;
+
+ ddev = adev_to_drm(adev);
+
+ for (i = 0; i < MAX_XCP; i++) {
+ ret = amdgpu_xcp_drm_dev_alloc(&p_ddev);
+ if (ret)
+ return ret;
+
+ /* Redirect all IOCTLs to the primary device */
+ adev->xcp_mgr->xcp[i].rdev = p_ddev->render->dev;
+ adev->xcp_mgr->xcp[i].pdev = p_ddev->primary->dev;
+ adev->xcp_mgr->xcp[i].driver = (struct drm_driver *)p_ddev->driver;
+ adev->xcp_mgr->xcp[i].vma_offset_manager = p_ddev->vma_offset_manager;
+ p_ddev->render->dev = ddev;
+ p_ddev->primary->dev = ddev;
+ p_ddev->vma_offset_manager = ddev->vma_offset_manager;
+ p_ddev->driver = &amdgpu_partition_driver;
+ adev->xcp_mgr->xcp[i].ddev = p_ddev;
+ }
+
+ return 0;
+}
+
+int amdgpu_xcp_mgr_init(struct amdgpu_device *adev, int init_mode,
+ int init_num_xcps,
+ struct amdgpu_xcp_mgr_funcs *xcp_funcs)
+{
+ struct amdgpu_xcp_mgr *xcp_mgr;
+
+ if (!xcp_funcs || !xcp_funcs->switch_partition_mode ||
+ !xcp_funcs->get_ip_details)
+ return -EINVAL;
+
+ xcp_mgr = kzalloc(sizeof(*xcp_mgr), GFP_KERNEL);
+
+ if (!xcp_mgr)
+ return -ENOMEM;
+
+ xcp_mgr->adev = adev;
+ xcp_mgr->funcs = xcp_funcs;
+ xcp_mgr->mode = init_mode;
+ mutex_init(&xcp_mgr->xcp_lock);
+
+ if (init_mode != AMDGPU_XCP_MODE_NONE)
+ amdgpu_xcp_init(xcp_mgr, init_num_xcps, init_mode);
+
+ adev->xcp_mgr = xcp_mgr;
+
+ return amdgpu_xcp_dev_alloc(adev);
+}
+
+int amdgpu_xcp_get_partition(struct amdgpu_xcp_mgr *xcp_mgr,
+ enum AMDGPU_XCP_IP_BLOCK ip, int instance)
+{
+ struct amdgpu_xcp *xcp;
+ int i, id_mask = 0;
+
+ if (ip >= AMDGPU_XCP_MAX_BLOCKS)
+ return -EINVAL;
+
+ for (i = 0; i < xcp_mgr->num_xcps; ++i) {
+ xcp = &xcp_mgr->xcp[i];
+ if ((xcp->valid) && (xcp->ip[ip].valid) &&
+ (xcp->ip[ip].inst_mask & BIT(instance)))
+ id_mask |= BIT(i);
+ }
+
+ if (!id_mask)
+ id_mask = -ENXIO;
+
+ return id_mask;
+}
+
+int amdgpu_xcp_get_inst_details(struct amdgpu_xcp *xcp,
+ enum AMDGPU_XCP_IP_BLOCK ip,
+ uint32_t *inst_mask)
+{
+ if (!xcp->valid || !inst_mask || !(xcp->ip[ip].valid))
+ return -EINVAL;
+
+ *inst_mask = xcp->ip[ip].inst_mask;
+
+ return 0;
+}
+
+int amdgpu_xcp_dev_register(struct amdgpu_device *adev,
+ const struct pci_device_id *ent)
+{
+ int i, ret;
+
+ if (!adev->xcp_mgr)
+ return 0;
+
+ for (i = 0; i < MAX_XCP; i++) {
+ ret = drm_dev_register(adev->xcp_mgr->xcp[i].ddev, ent->driver_data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+void amdgpu_xcp_dev_unplug(struct amdgpu_device *adev)
+{
+ struct drm_device *p_ddev;
+ int i;
+
+ if (!adev->xcp_mgr)
+ return;
+
+ for (i = 0; i < MAX_XCP; i++) {
+ p_ddev = adev->xcp_mgr->xcp[i].ddev;
+ drm_dev_unplug(p_ddev);
+ p_ddev->render->dev = adev->xcp_mgr->xcp[i].rdev;
+ p_ddev->primary->dev = adev->xcp_mgr->xcp[i].pdev;
+ p_ddev->driver = adev->xcp_mgr->xcp[i].driver;
+ p_ddev->vma_offset_manager = adev->xcp_mgr->xcp[i].vma_offset_manager;
+ }
+}
+
+int amdgpu_xcp_open_device(struct amdgpu_device *adev,
+ struct amdgpu_fpriv *fpriv,
+ struct drm_file *file_priv)
+{
+ int i;
+
+ if (!adev->xcp_mgr)
+ return 0;
+
+ fpriv->xcp_id = ~0;
+ for (i = 0; i < MAX_XCP; ++i) {
+ if (!adev->xcp_mgr->xcp[i].ddev)
+ break;
+
+ if (file_priv->minor == adev->xcp_mgr->xcp[i].ddev->render) {
+ if (adev->xcp_mgr->xcp[i].valid == FALSE) {
+ dev_err(adev->dev, "renderD%d partition %d not valid!",
+ file_priv->minor->index, i);
+ return -ENOENT;
+ }
+ dev_dbg(adev->dev, "renderD%d partition %d opened!",
+ file_priv->minor->index, i);
+ fpriv->xcp_id = i;
+ break;
+ }
+ }
+
+ fpriv->vm.mem_id = fpriv->xcp_id == ~0 ? -1 :
+ adev->xcp_mgr->xcp[fpriv->xcp_id].mem_id;
+ return 0;
+}
+
+void amdgpu_xcp_release_sched(struct amdgpu_device *adev,
+ struct amdgpu_ctx_entity *entity)
+{
+ struct drm_gpu_scheduler *sched;
+ struct amdgpu_ring *ring;
+
+ if (!adev->xcp_mgr)
+ return;
+
+ sched = entity->entity.rq->sched;
+ if (sched->ready) {
+ ring = to_amdgpu_ring(entity->entity.rq->sched);
+ atomic_dec(&adev->xcp_mgr->xcp[ring->xcp_id].ref_cnt);
+ }
+}
+
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
new file mode 100644
index 000000000000..0f8026d64ea5
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef AMDGPU_XCP_H
+#define AMDGPU_XCP_H
+
+#include <linux/pci.h>
+#include <linux/xarray.h>
+
+#include "amdgpu_ctx.h"
+
+#define MAX_XCP 8
+
+#define AMDGPU_XCP_MODE_NONE -1
+#define AMDGPU_XCP_MODE_TRANS -2
+
+#define AMDGPU_XCP_FL_NONE 0
+#define AMDGPU_XCP_FL_LOCKED (1 << 0)
+
+struct amdgpu_fpriv;
+
+enum AMDGPU_XCP_IP_BLOCK {
+ AMDGPU_XCP_GFXHUB,
+ AMDGPU_XCP_GFX,
+ AMDGPU_XCP_SDMA,
+ AMDGPU_XCP_VCN,
+ AMDGPU_XCP_MAX_BLOCKS
+};
+
+enum AMDGPU_XCP_STATE {
+ AMDGPU_XCP_PREPARE_SUSPEND,
+ AMDGPU_XCP_SUSPEND,
+ AMDGPU_XCP_PREPARE_RESUME,
+ AMDGPU_XCP_RESUME,
+};
+
+struct amdgpu_xcp_ip_funcs {
+ int (*prepare_suspend)(void *handle, uint32_t inst_mask);
+ int (*suspend)(void *handle, uint32_t inst_mask);
+ int (*prepare_resume)(void *handle, uint32_t inst_mask);
+ int (*resume)(void *handle, uint32_t inst_mask);
+};
+
+struct amdgpu_xcp_ip {
+ struct amdgpu_xcp_ip_funcs *ip_funcs;
+ uint32_t inst_mask;
+
+ enum AMDGPU_XCP_IP_BLOCK ip_id;
+ bool valid;
+};
+
+struct amdgpu_xcp {
+ struct amdgpu_xcp_ip ip[AMDGPU_XCP_MAX_BLOCKS];
+
+ uint8_t id;
+ uint8_t mem_id;
+ bool valid;
+ atomic_t ref_cnt;
+ struct drm_device *ddev;
+ struct drm_device *rdev;
+ struct drm_device *pdev;
+ struct drm_driver *driver;
+ struct drm_vma_offset_manager *vma_offset_manager;
+ struct amdgpu_sched gpu_sched[AMDGPU_HW_IP_NUM][AMDGPU_RING_PRIO_MAX];
+};
+
+struct amdgpu_xcp_mgr {
+ struct amdgpu_device *adev;
+ struct mutex xcp_lock;
+ struct amdgpu_xcp_mgr_funcs *funcs;
+
+ struct amdgpu_xcp xcp[MAX_XCP];
+ uint8_t num_xcps;
+ int8_t mode;
+
+ /* Used to determine KFD memory size limits per XCP */
+ unsigned int num_xcp_per_mem_partition;
+};
+
+struct amdgpu_xcp_mgr_funcs {
+ int (*switch_partition_mode)(struct amdgpu_xcp_mgr *xcp_mgr, int mode,
+ int *num_xcps);
+ int (*query_partition_mode)(struct amdgpu_xcp_mgr *xcp_mgr);
+ int (*get_ip_details)(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id,
+ enum AMDGPU_XCP_IP_BLOCK ip_id,
+ struct amdgpu_xcp_ip *ip);
+ int (*get_xcp_mem_id)(struct amdgpu_xcp_mgr *xcp_mgr,
+ struct amdgpu_xcp *xcp, uint8_t *mem_id);
+
+ int (*prepare_suspend)(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id);
+ int (*suspend)(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id);
+ int (*prepare_resume)(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id);
+ int (*resume)(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id);
+ int (*select_scheds)(struct amdgpu_device *adev,
+ u32 hw_ip, u32 hw_prio, struct amdgpu_fpriv *fpriv,
+ unsigned int *num_scheds, struct drm_gpu_scheduler ***scheds);
+ int (*update_partition_sched_list)(struct amdgpu_device *adev);
+};
+
+int amdgpu_xcp_prepare_suspend(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id);
+int amdgpu_xcp_suspend(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id);
+int amdgpu_xcp_prepare_resume(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id);
+int amdgpu_xcp_resume(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id);
+
+int amdgpu_xcp_mgr_init(struct amdgpu_device *adev, int init_mode,
+ int init_xcps, struct amdgpu_xcp_mgr_funcs *xcp_funcs);
+int amdgpu_xcp_init(struct amdgpu_xcp_mgr *xcp_mgr, int num_xcps, int mode);
+int amdgpu_xcp_query_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, u32 flags);
+int amdgpu_xcp_switch_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, int mode);
+int amdgpu_xcp_get_partition(struct amdgpu_xcp_mgr *xcp_mgr,
+ enum AMDGPU_XCP_IP_BLOCK ip, int instance);
+
+int amdgpu_xcp_get_inst_details(struct amdgpu_xcp *xcp,
+ enum AMDGPU_XCP_IP_BLOCK ip,
+ uint32_t *inst_mask);
+
+int amdgpu_xcp_dev_register(struct amdgpu_device *adev,
+ const struct pci_device_id *ent);
+void amdgpu_xcp_dev_unplug(struct amdgpu_device *adev);
+int amdgpu_xcp_open_device(struct amdgpu_device *adev,
+ struct amdgpu_fpriv *fpriv,
+ struct drm_file *file_priv);
+void amdgpu_xcp_release_sched(struct amdgpu_device *adev,
+ struct amdgpu_ctx_entity *entity);
+
+#define amdgpu_xcp_select_scheds(adev, e, c, d, x, y) \
+ ((adev)->xcp_mgr && (adev)->xcp_mgr->funcs && \
+ (adev)->xcp_mgr->funcs->select_scheds ? \
+ (adev)->xcp_mgr->funcs->select_scheds((adev), (e), (c), (d), (x), (y)) : -ENOENT)
+#define amdgpu_xcp_update_partition_sched_list(adev) \
+ ((adev)->xcp_mgr && (adev)->xcp_mgr->funcs && \
+ (adev)->xcp_mgr->funcs->update_partition_sched_list ? \
+ (adev)->xcp_mgr->funcs->update_partition_sched_list(adev) : 0)
+
+static inline int amdgpu_xcp_get_num_xcp(struct amdgpu_xcp_mgr *xcp_mgr)
+{
+ if (!xcp_mgr)
+ return 1;
+ else
+ return xcp_mgr->num_xcps;
+}
+
+static inline struct amdgpu_xcp *
+amdgpu_get_next_xcp(struct amdgpu_xcp_mgr *xcp_mgr, int *from)
+{
+ if (!xcp_mgr)
+ return NULL;
+
+ while (*from < MAX_XCP) {
+ if (xcp_mgr->xcp[*from].valid)
+ return &xcp_mgr->xcp[*from];
+ ++(*from);
+ }
+
+ return NULL;
+}
+
+#define for_each_xcp(xcp_mgr, xcp, i) \
+ for (i = 0, xcp = amdgpu_get_next_xcp(xcp_mgr, &i); xcp; \
+ xcp = amdgpu_get_next_xcp(xcp_mgr, &i))
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
index 439925477fb8..03dc59cbe8aa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -325,6 +325,36 @@ static ssize_t amdgpu_xgmi_show_device_id(struct device *dev,
}
+static ssize_t amdgpu_xgmi_show_num_hops(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+ struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info;
+ int i;
+
+ for (i = 0; i < top->num_nodes; i++)
+ sprintf(buf + 3 * i, "%02x ", top->nodes[i].num_hops);
+
+ return sysfs_emit(buf, "%s\n", buf);
+}
+
+static ssize_t amdgpu_xgmi_show_num_links(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+ struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info;
+ int i;
+
+ for (i = 0; i < top->num_nodes; i++)
+ sprintf(buf + 3 * i, "%02x ", top->nodes[i].num_links);
+
+ return sysfs_emit(buf, "%s\n", buf);
+}
+
#define AMDGPU_XGMI_SET_FICAA(o) ((o) | 0x456801)
static ssize_t amdgpu_xgmi_show_error(struct device *dev,
struct device_attribute *attr,
@@ -361,6 +391,8 @@ static ssize_t amdgpu_xgmi_show_error(struct device *dev,
static DEVICE_ATTR(xgmi_device_id, S_IRUGO, amdgpu_xgmi_show_device_id, NULL);
static DEVICE_ATTR(xgmi_error, S_IRUGO, amdgpu_xgmi_show_error, NULL);
+static DEVICE_ATTR(xgmi_num_hops, S_IRUGO, amdgpu_xgmi_show_num_hops, NULL);
+static DEVICE_ATTR(xgmi_num_links, S_IRUGO, amdgpu_xgmi_show_num_links, NULL);
static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev,
struct amdgpu_hive_info *hive)
@@ -380,6 +412,15 @@ static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev,
if (ret)
pr_err("failed to create xgmi_error\n");
+ /* Create xgmi num hops file */
+ ret = device_create_file(adev->dev, &dev_attr_xgmi_num_hops);
+ if (ret)
+ pr_err("failed to create xgmi_num_hops\n");
+
+ /* Create xgmi num links file */
+ ret = device_create_file(adev->dev, &dev_attr_xgmi_num_links);
+ if (ret)
+ pr_err("failed to create xgmi_num_links\n");
/* Create sysfs link to hive info folder on the first device */
if (hive->kobj.parent != (&adev->dev->kobj)) {
@@ -407,6 +448,9 @@ remove_link:
remove_file:
device_remove_file(adev->dev, &dev_attr_xgmi_device_id);
+ device_remove_file(adev->dev, &dev_attr_xgmi_error);
+ device_remove_file(adev->dev, &dev_attr_xgmi_num_hops);
+ device_remove_file(adev->dev, &dev_attr_xgmi_num_links);
success:
return ret;
@@ -420,6 +464,8 @@ static void amdgpu_xgmi_sysfs_rem_dev_info(struct amdgpu_device *adev,
device_remove_file(adev->dev, &dev_attr_xgmi_device_id);
device_remove_file(adev->dev, &dev_attr_xgmi_error);
+ device_remove_file(adev->dev, &dev_attr_xgmi_num_hops);
+ device_remove_file(adev->dev, &dev_attr_xgmi_num_links);
if (hive->kobj.parent != (&adev->dev->kobj))
sysfs_remove_link(&adev->dev->kobj,"xgmi_hive_info");
@@ -1014,7 +1060,8 @@ static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
}
/* Trigger XGMI/WAFL error */
-static int amdgpu_ras_error_inject_xgmi(struct amdgpu_device *adev, void *inject_if)
+static int amdgpu_ras_error_inject_xgmi(struct amdgpu_device *adev,
+ void *inject_if, uint32_t instance_mask)
{
int ret = 0;
struct ta_ras_trigger_error_input *block_info =
@@ -1026,7 +1073,7 @@ static int amdgpu_ras_error_inject_xgmi(struct amdgpu_device *adev, void *injec
if (amdgpu_dpm_allow_xgmi_power_down(adev, false))
dev_warn(adev->dev, "Failed to disallow XGMI power down");
- ret = psp_ras_trigger_error(&adev->psp, block_info);
+ ret = psp_ras_trigger_error(&adev->psp, block_info, instance_mask);
if (amdgpu_ras_intr_triggered())
return ret;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
index 24d42d24e6a0..104a5ad8397d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
@@ -70,7 +70,6 @@ enum amd_sriov_ucode_engine_id {
AMD_SRIOV_UCODE_ID_RLC_SRLS,
AMD_SRIOV_UCODE_ID_MEC,
AMD_SRIOV_UCODE_ID_MEC2,
- AMD_SRIOV_UCODE_ID_IMU,
AMD_SRIOV_UCODE_ID_SOS,
AMD_SRIOV_UCODE_ID_ASD,
AMD_SRIOV_UCODE_ID_TA_RAS,
diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram_reg_init.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram_reg_init.c
new file mode 100644
index 000000000000..16471b81a1f5
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram_reg_init.c
@@ -0,0 +1,658 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "soc15.h"
+
+#include "soc15_common.h"
+#include "amdgpu_xcp.h"
+#include "gfx_v9_4_3.h"
+#include "gfxhub_v1_2.h"
+#include "sdma_v4_4_2.h"
+
+#define XCP_INST_MASK(num_inst, xcp_id) \
+ (num_inst ? GENMASK(num_inst - 1, 0) << (xcp_id * num_inst) : 0)
+
+#define AMDGPU_XCP_OPS_KFD (1 << 0)
+
+void aqua_vanjaram_doorbell_index_init(struct amdgpu_device *adev)
+{
+ int i;
+
+ adev->doorbell_index.kiq = AMDGPU_DOORBELL_LAYOUT1_KIQ_START;
+
+ adev->doorbell_index.mec_ring0 = AMDGPU_DOORBELL_LAYOUT1_MEC_RING_START;
+
+ adev->doorbell_index.userqueue_start = AMDGPU_DOORBELL_LAYOUT1_USERQUEUE_START;
+ adev->doorbell_index.userqueue_end = AMDGPU_DOORBELL_LAYOUT1_USERQUEUE_END;
+ adev->doorbell_index.xcc_doorbell_range = AMDGPU_DOORBELL_LAYOUT1_XCC_RANGE;
+
+ adev->doorbell_index.sdma_doorbell_range = 20;
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ adev->doorbell_index.sdma_engine[i] =
+ AMDGPU_DOORBELL_LAYOUT1_sDMA_ENGINE_START +
+ i * (adev->doorbell_index.sdma_doorbell_range >> 1);
+
+ adev->doorbell_index.ih = AMDGPU_DOORBELL_LAYOUT1_IH;
+ adev->doorbell_index.vcn.vcn_ring0_1 = AMDGPU_DOORBELL_LAYOUT1_VCN_START;
+
+ adev->doorbell_index.first_non_cp = AMDGPU_DOORBELL_LAYOUT1_FIRST_NON_CP;
+ adev->doorbell_index.last_non_cp = AMDGPU_DOORBELL_LAYOUT1_LAST_NON_CP;
+
+ adev->doorbell_index.max_assignment = AMDGPU_DOORBELL_LAYOUT1_MAX_ASSIGNMENT << 1;
+}
+
+static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev,
+ uint32_t inst_idx, struct amdgpu_ring *ring)
+{
+ int xcp_id;
+ enum AMDGPU_XCP_IP_BLOCK ip_blk;
+ uint32_t inst_mask;
+
+ ring->xcp_id = ~0;
+ if (adev->xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
+ return;
+
+ inst_mask = 1 << inst_idx;
+
+ switch (ring->funcs->type) {
+ case AMDGPU_HW_IP_GFX:
+ case AMDGPU_RING_TYPE_COMPUTE:
+ case AMDGPU_RING_TYPE_KIQ:
+ ip_blk = AMDGPU_XCP_GFX;
+ break;
+ case AMDGPU_RING_TYPE_SDMA:
+ ip_blk = AMDGPU_XCP_SDMA;
+ break;
+ case AMDGPU_RING_TYPE_VCN_ENC:
+ case AMDGPU_RING_TYPE_VCN_JPEG:
+ ip_blk = AMDGPU_XCP_VCN;
+ if (adev->xcp_mgr->mode == AMDGPU_CPX_PARTITION_MODE)
+ inst_mask = 1 << (inst_idx * 2);
+ break;
+ default:
+ DRM_ERROR("Not support ring type %d!", ring->funcs->type);
+ return;
+ }
+
+ for (xcp_id = 0; xcp_id < adev->xcp_mgr->num_xcps; xcp_id++) {
+ if (adev->xcp_mgr->xcp[xcp_id].ip[ip_blk].inst_mask & inst_mask) {
+ ring->xcp_id = xcp_id;
+ break;
+ }
+ }
+}
+
+static void aqua_vanjaram_xcp_gpu_sched_update(
+ struct amdgpu_device *adev,
+ struct amdgpu_ring *ring,
+ unsigned int sel_xcp_id)
+{
+ unsigned int *num_gpu_sched;
+
+ num_gpu_sched = &adev->xcp_mgr->xcp[sel_xcp_id]
+ .gpu_sched[ring->funcs->type][ring->hw_prio].num_scheds;
+ adev->xcp_mgr->xcp[sel_xcp_id].gpu_sched[ring->funcs->type][ring->hw_prio]
+ .sched[(*num_gpu_sched)++] = &ring->sched;
+ DRM_DEBUG("%s :[%d] gpu_sched[%d][%d] = %d", ring->name,
+ sel_xcp_id, ring->funcs->type,
+ ring->hw_prio, *num_gpu_sched);
+}
+
+static int aqua_vanjaram_xcp_sched_list_update(
+ struct amdgpu_device *adev)
+{
+ struct amdgpu_ring *ring;
+ int i;
+
+ for (i = 0; i < MAX_XCP; i++) {
+ atomic_set(&adev->xcp_mgr->xcp[i].ref_cnt, 0);
+ memset(adev->xcp_mgr->xcp[i].gpu_sched, 0, sizeof(adev->xcp_mgr->xcp->gpu_sched));
+ }
+
+ if (adev->xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
+ return 0;
+
+ for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
+ ring = adev->rings[i];
+ if (!ring || !ring->sched.ready)
+ continue;
+
+ aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id);
+
+ /* VCN is shared by two partitions under CPX MODE */
+ if ((ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC ||
+ ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) &&
+ adev->xcp_mgr->mode == AMDGPU_CPX_PARTITION_MODE)
+ aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id + 1);
+ }
+
+ return 0;
+}
+
+static int aqua_vanjaram_update_partition_sched_list(struct amdgpu_device *adev)
+{
+ int i;
+
+ for (i = 0; i < adev->num_rings; i++) {
+ struct amdgpu_ring *ring = adev->rings[i];
+
+ if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE ||
+ ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
+ aqua_vanjaram_set_xcp_id(adev, ring->xcc_id, ring);
+ else
+ aqua_vanjaram_set_xcp_id(adev, ring->me, ring);
+ }
+
+ return aqua_vanjaram_xcp_sched_list_update(adev);
+}
+
+static int aqua_vanjaram_select_scheds(
+ struct amdgpu_device *adev,
+ u32 hw_ip,
+ u32 hw_prio,
+ struct amdgpu_fpriv *fpriv,
+ unsigned int *num_scheds,
+ struct drm_gpu_scheduler ***scheds)
+{
+ u32 sel_xcp_id;
+ int i;
+
+ if (fpriv->xcp_id == ~0) {
+ u32 least_ref_cnt = ~0;
+
+ fpriv->xcp_id = 0;
+ for (i = 0; i < adev->xcp_mgr->num_xcps; i++) {
+ u32 total_ref_cnt;
+
+ total_ref_cnt = atomic_read(&adev->xcp_mgr->xcp[i].ref_cnt);
+ if (total_ref_cnt < least_ref_cnt) {
+ fpriv->xcp_id = i;
+ least_ref_cnt = total_ref_cnt;
+ }
+ }
+ }
+ sel_xcp_id = fpriv->xcp_id;
+
+ if (adev->xcp_mgr->xcp[sel_xcp_id].gpu_sched[hw_ip][hw_prio].num_scheds) {
+ *num_scheds = adev->xcp_mgr->xcp[fpriv->xcp_id].gpu_sched[hw_ip][hw_prio].num_scheds;
+ *scheds = adev->xcp_mgr->xcp[fpriv->xcp_id].gpu_sched[hw_ip][hw_prio].sched;
+ atomic_inc(&adev->xcp_mgr->xcp[sel_xcp_id].ref_cnt);
+ DRM_DEBUG("Selected partition #%d", sel_xcp_id);
+ } else {
+ DRM_ERROR("Failed to schedule partition #%d.", sel_xcp_id);
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+static int8_t aqua_vanjaram_logical_to_dev_inst(struct amdgpu_device *adev,
+ enum amd_hw_ip_block_type block,
+ int8_t inst)
+{
+ int8_t dev_inst;
+
+ switch (block) {
+ case GC_HWIP:
+ case SDMA0_HWIP:
+ /* Both JPEG and VCN as JPEG is only alias of VCN */
+ case VCN_HWIP:
+ dev_inst = adev->ip_map.dev_inst[block][inst];
+ break;
+ default:
+ /* For rest of the IPs, no look up required.
+ * Assume 'logical instance == physical instance' for all configs. */
+ dev_inst = inst;
+ break;
+ }
+
+ return dev_inst;
+}
+
+static uint32_t aqua_vanjaram_logical_to_dev_mask(struct amdgpu_device *adev,
+ enum amd_hw_ip_block_type block,
+ uint32_t mask)
+{
+ uint32_t dev_mask = 0;
+ int8_t log_inst, dev_inst;
+
+ while (mask) {
+ log_inst = ffs(mask) - 1;
+ dev_inst = aqua_vanjaram_logical_to_dev_inst(adev, block, log_inst);
+ dev_mask |= (1 << dev_inst);
+ mask &= ~(1 << log_inst);
+ }
+
+ return dev_mask;
+}
+
+static void aqua_vanjaram_populate_ip_map(struct amdgpu_device *adev,
+ enum amd_hw_ip_block_type ip_block,
+ uint32_t inst_mask)
+{
+ int l = 0, i;
+
+ while (inst_mask) {
+ i = ffs(inst_mask) - 1;
+ adev->ip_map.dev_inst[ip_block][l++] = i;
+ inst_mask &= ~(1 << i);
+ }
+ for (; l < HWIP_MAX_INSTANCE; l++)
+ adev->ip_map.dev_inst[ip_block][l] = -1;
+}
+
+void aqua_vanjaram_ip_map_init(struct amdgpu_device *adev)
+{
+ u32 ip_map[][2] = {
+ { GC_HWIP, adev->gfx.xcc_mask },
+ { SDMA0_HWIP, adev->sdma.sdma_mask },
+ { VCN_HWIP, adev->vcn.inst_mask },
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ip_map); ++i)
+ aqua_vanjaram_populate_ip_map(adev, ip_map[i][0], ip_map[i][1]);
+
+ adev->ip_map.logical_to_dev_inst = aqua_vanjaram_logical_to_dev_inst;
+ adev->ip_map.logical_to_dev_mask = aqua_vanjaram_logical_to_dev_mask;
+}
+
+/* Fixed pattern for smn addressing on different AIDs:
+ * bit[34]: indicate cross AID access
+ * bit[33:32]: indicate target AID id
+ * AID id range is 0 ~ 3 as maximum AID number is 4.
+ */
+u64 aqua_vanjaram_encode_ext_smn_addressing(int ext_id)
+{
+ u64 ext_offset;
+
+ /* local routing and bit[34:32] will be zeros */
+ if (ext_id == 0)
+ return 0;
+
+ /* Initiated from host, accessing to all non-zero aids are cross traffic */
+ ext_offset = ((u64)(ext_id & 0x3) << 32) | (1ULL << 34);
+
+ return ext_offset;
+}
+
+static int aqua_vanjaram_query_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr)
+{
+ enum amdgpu_gfx_partition mode = AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE;
+ struct amdgpu_device *adev = xcp_mgr->adev;
+
+ if (adev->nbio.funcs->get_compute_partition_mode)
+ mode = adev->nbio.funcs->get_compute_partition_mode(adev);
+
+ return mode;
+}
+
+static int __aqua_vanjaram_get_xcc_per_xcp(struct amdgpu_xcp_mgr *xcp_mgr, int mode)
+{
+ int num_xcc, num_xcc_per_xcp = 0;
+
+ num_xcc = NUM_XCC(xcp_mgr->adev->gfx.xcc_mask);
+
+ switch (mode) {
+ case AMDGPU_SPX_PARTITION_MODE:
+ num_xcc_per_xcp = num_xcc;
+ break;
+ case AMDGPU_DPX_PARTITION_MODE:
+ num_xcc_per_xcp = num_xcc / 2;
+ break;
+ case AMDGPU_TPX_PARTITION_MODE:
+ num_xcc_per_xcp = num_xcc / 3;
+ break;
+ case AMDGPU_QPX_PARTITION_MODE:
+ num_xcc_per_xcp = num_xcc / 4;
+ break;
+ case AMDGPU_CPX_PARTITION_MODE:
+ num_xcc_per_xcp = 1;
+ break;
+ }
+
+ return num_xcc_per_xcp;
+}
+
+static int __aqua_vanjaram_get_xcp_ip_info(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id,
+ enum AMDGPU_XCP_IP_BLOCK ip_id,
+ struct amdgpu_xcp_ip *ip)
+{
+ struct amdgpu_device *adev = xcp_mgr->adev;
+ int num_xcc_xcp, num_sdma_xcp, num_vcn_xcp;
+ int num_sdma, num_vcn;
+
+ num_sdma = adev->sdma.num_instances;
+ num_vcn = adev->vcn.num_vcn_inst;
+
+ switch (xcp_mgr->mode) {
+ case AMDGPU_SPX_PARTITION_MODE:
+ num_sdma_xcp = num_sdma;
+ num_vcn_xcp = num_vcn;
+ break;
+ case AMDGPU_DPX_PARTITION_MODE:
+ num_sdma_xcp = num_sdma / 2;
+ num_vcn_xcp = num_vcn / 2;
+ break;
+ case AMDGPU_TPX_PARTITION_MODE:
+ num_sdma_xcp = num_sdma / 3;
+ num_vcn_xcp = num_vcn / 3;
+ break;
+ case AMDGPU_QPX_PARTITION_MODE:
+ num_sdma_xcp = num_sdma / 4;
+ num_vcn_xcp = num_vcn / 4;
+ break;
+ case AMDGPU_CPX_PARTITION_MODE:
+ num_sdma_xcp = 2;
+ num_vcn_xcp = num_vcn ? 1 : 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ num_xcc_xcp = adev->gfx.num_xcc_per_xcp;
+
+ switch (ip_id) {
+ case AMDGPU_XCP_GFXHUB:
+ ip->inst_mask = XCP_INST_MASK(num_xcc_xcp, xcp_id);
+ ip->ip_funcs = &gfxhub_v1_2_xcp_funcs;
+ break;
+ case AMDGPU_XCP_GFX:
+ ip->inst_mask = XCP_INST_MASK(num_xcc_xcp, xcp_id);
+ ip->ip_funcs = &gfx_v9_4_3_xcp_funcs;
+ break;
+ case AMDGPU_XCP_SDMA:
+ ip->inst_mask = XCP_INST_MASK(num_sdma_xcp, xcp_id);
+ ip->ip_funcs = &sdma_v4_4_2_xcp_funcs;
+ break;
+ case AMDGPU_XCP_VCN:
+ ip->inst_mask = XCP_INST_MASK(num_vcn_xcp, xcp_id);
+ /* TODO : Assign IP funcs */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ip->ip_id = ip_id;
+
+ return 0;
+}
+
+static enum amdgpu_gfx_partition
+__aqua_vanjaram_get_auto_mode(struct amdgpu_xcp_mgr *xcp_mgr)
+{
+ struct amdgpu_device *adev = xcp_mgr->adev;
+ int num_xcc;
+
+ num_xcc = NUM_XCC(xcp_mgr->adev->gfx.xcc_mask);
+
+ if (adev->gmc.num_mem_partitions == 1)
+ return AMDGPU_SPX_PARTITION_MODE;
+
+ if (adev->gmc.num_mem_partitions == num_xcc)
+ return AMDGPU_CPX_PARTITION_MODE;
+
+ if (adev->gmc.num_mem_partitions == num_xcc / 2)
+ return (adev->flags & AMD_IS_APU) ? AMDGPU_TPX_PARTITION_MODE :
+ AMDGPU_QPX_PARTITION_MODE;
+
+ if (adev->gmc.num_mem_partitions == 2 && !(adev->flags & AMD_IS_APU))
+ return AMDGPU_DPX_PARTITION_MODE;
+
+ return AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE;
+}
+
+static bool __aqua_vanjaram_is_valid_mode(struct amdgpu_xcp_mgr *xcp_mgr,
+ enum amdgpu_gfx_partition mode)
+{
+ struct amdgpu_device *adev = xcp_mgr->adev;
+ int num_xcc, num_xccs_per_xcp;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ switch (mode) {
+ case AMDGPU_SPX_PARTITION_MODE:
+ return adev->gmc.num_mem_partitions == 1 && num_xcc > 0;
+ case AMDGPU_DPX_PARTITION_MODE:
+ return adev->gmc.num_mem_partitions != 8 && (num_xcc % 4) == 0;
+ case AMDGPU_TPX_PARTITION_MODE:
+ return (adev->gmc.num_mem_partitions == 1 ||
+ adev->gmc.num_mem_partitions == 3) &&
+ ((num_xcc % 3) == 0);
+ case AMDGPU_QPX_PARTITION_MODE:
+ num_xccs_per_xcp = num_xcc / 4;
+ return (adev->gmc.num_mem_partitions == 1 ||
+ adev->gmc.num_mem_partitions == 4) &&
+ (num_xccs_per_xcp >= 2);
+ case AMDGPU_CPX_PARTITION_MODE:
+ return ((num_xcc > 1) &&
+ (adev->gmc.num_mem_partitions == 1 || adev->gmc.num_mem_partitions == 4) &&
+ (num_xcc % adev->gmc.num_mem_partitions) == 0);
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+static int __aqua_vanjaram_pre_partition_switch(struct amdgpu_xcp_mgr *xcp_mgr, u32 flags)
+{
+ /* TODO:
+ * Stop user queues and threads, and make sure GPU is empty of work.
+ */
+
+ if (flags & AMDGPU_XCP_OPS_KFD)
+ amdgpu_amdkfd_device_fini_sw(xcp_mgr->adev);
+
+ return 0;
+}
+
+static int __aqua_vanjaram_post_partition_switch(struct amdgpu_xcp_mgr *xcp_mgr, u32 flags)
+{
+ int ret = 0;
+
+ if (flags & AMDGPU_XCP_OPS_KFD) {
+ amdgpu_amdkfd_device_probe(xcp_mgr->adev);
+ amdgpu_amdkfd_device_init(xcp_mgr->adev);
+ /* If KFD init failed, return failure */
+ if (!xcp_mgr->adev->kfd.init_complete)
+ ret = -EIO;
+ }
+
+ return ret;
+}
+
+static int aqua_vanjaram_switch_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr,
+ int mode, int *num_xcps)
+{
+ int num_xcc_per_xcp, num_xcc, ret;
+ struct amdgpu_device *adev;
+ u32 flags = 0;
+
+ adev = xcp_mgr->adev;
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+
+ if (mode == AMDGPU_AUTO_COMPUTE_PARTITION_MODE) {
+ mode = __aqua_vanjaram_get_auto_mode(xcp_mgr);
+ } else if (!__aqua_vanjaram_is_valid_mode(xcp_mgr, mode)) {
+ dev_err(adev->dev,
+ "Invalid compute partition mode requested, requested: %s, available memory partitions: %d",
+ amdgpu_gfx_compute_mode_desc(mode), adev->gmc.num_mem_partitions);
+ return -EINVAL;
+ }
+
+ if (adev->kfd.init_complete)
+ flags |= AMDGPU_XCP_OPS_KFD;
+
+ if (flags & AMDGPU_XCP_OPS_KFD) {
+ ret = amdgpu_amdkfd_check_and_lock_kfd(adev);
+ if (ret)
+ goto out;
+ }
+
+ ret = __aqua_vanjaram_pre_partition_switch(xcp_mgr, flags);
+ if (ret)
+ goto unlock;
+
+ num_xcc_per_xcp = __aqua_vanjaram_get_xcc_per_xcp(xcp_mgr, mode);
+ if (adev->gfx.funcs->switch_partition_mode)
+ adev->gfx.funcs->switch_partition_mode(xcp_mgr->adev,
+ num_xcc_per_xcp);
+
+ /* Init info about new xcps */
+ *num_xcps = num_xcc / num_xcc_per_xcp;
+ amdgpu_xcp_init(xcp_mgr, *num_xcps, mode);
+
+ ret = __aqua_vanjaram_post_partition_switch(xcp_mgr, flags);
+unlock:
+ if (flags & AMDGPU_XCP_OPS_KFD)
+ amdgpu_amdkfd_unlock_kfd(adev);
+out:
+ return ret;
+}
+
+static int __aqua_vanjaram_get_xcp_mem_id(struct amdgpu_device *adev,
+ int xcc_id, uint8_t *mem_id)
+{
+ /* memory/spatial modes validation check is already done */
+ *mem_id = xcc_id / adev->gfx.num_xcc_per_xcp;
+ *mem_id /= adev->xcp_mgr->num_xcp_per_mem_partition;
+
+ return 0;
+}
+
+static int aqua_vanjaram_get_xcp_mem_id(struct amdgpu_xcp_mgr *xcp_mgr,
+ struct amdgpu_xcp *xcp, uint8_t *mem_id)
+{
+ struct amdgpu_numa_info numa_info;
+ struct amdgpu_device *adev;
+ uint32_t xcc_mask;
+ int r, i, xcc_id;
+
+ adev = xcp_mgr->adev;
+ /* TODO: BIOS is not returning the right info now
+ * Check on this later
+ */
+ /*
+ if (adev->gmc.gmc_funcs->query_mem_partition_mode)
+ mode = adev->gmc.gmc_funcs->query_mem_partition_mode(adev);
+ */
+ if (adev->gmc.num_mem_partitions == 1) {
+ /* Only one range */
+ *mem_id = 0;
+ return 0;
+ }
+
+ r = amdgpu_xcp_get_inst_details(xcp, AMDGPU_XCP_GFX, &xcc_mask);
+ if (r || !xcc_mask)
+ return -EINVAL;
+
+ xcc_id = ffs(xcc_mask) - 1;
+ if (!adev->gmc.is_app_apu)
+ return __aqua_vanjaram_get_xcp_mem_id(adev, xcc_id, mem_id);
+
+ r = amdgpu_acpi_get_mem_info(adev, xcc_id, &numa_info);
+
+ if (r)
+ return r;
+
+ r = -EINVAL;
+ for (i = 0; i < adev->gmc.num_mem_partitions; ++i) {
+ if (adev->gmc.mem_partitions[i].numa.node == numa_info.nid) {
+ *mem_id = i;
+ r = 0;
+ break;
+ }
+ }
+
+ return r;
+}
+
+static int aqua_vanjaram_get_xcp_ip_details(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id,
+ enum AMDGPU_XCP_IP_BLOCK ip_id,
+ struct amdgpu_xcp_ip *ip)
+{
+ if (!ip)
+ return -EINVAL;
+
+ return __aqua_vanjaram_get_xcp_ip_info(xcp_mgr, xcp_id, ip_id, ip);
+}
+
+struct amdgpu_xcp_mgr_funcs aqua_vanjaram_xcp_funcs = {
+ .switch_partition_mode = &aqua_vanjaram_switch_partition_mode,
+ .query_partition_mode = &aqua_vanjaram_query_partition_mode,
+ .get_ip_details = &aqua_vanjaram_get_xcp_ip_details,
+ .get_xcp_mem_id = &aqua_vanjaram_get_xcp_mem_id,
+ .select_scheds = &aqua_vanjaram_select_scheds,
+ .update_partition_sched_list = &aqua_vanjaram_update_partition_sched_list
+};
+
+static int aqua_vanjaram_xcp_mgr_init(struct amdgpu_device *adev)
+{
+ int ret;
+
+ ret = amdgpu_xcp_mgr_init(adev, AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE, 1,
+ &aqua_vanjaram_xcp_funcs);
+ if (ret)
+ return ret;
+
+ /* TODO: Default memory node affinity init */
+
+ return ret;
+}
+
+int aqua_vanjaram_init_soc_config(struct amdgpu_device *adev)
+{
+ u32 mask, inst_mask = adev->sdma.sdma_mask;
+ int ret, i;
+
+ /* generally 1 AID supports 4 instances */
+ adev->sdma.num_inst_per_aid = 4;
+ adev->sdma.num_instances = NUM_SDMA(adev->sdma.sdma_mask);
+
+ adev->aid_mask = i = 1;
+ inst_mask >>= adev->sdma.num_inst_per_aid;
+
+ for (mask = (1 << adev->sdma.num_inst_per_aid) - 1; inst_mask;
+ inst_mask >>= adev->sdma.num_inst_per_aid, ++i) {
+ if ((inst_mask & mask) == mask)
+ adev->aid_mask |= (1 << i);
+ }
+
+ /* Harvest config is not used for aqua vanjaram. VCN and JPEGs will be
+ * addressed based on logical instance ids.
+ */
+ adev->vcn.harvest_config = 0;
+ adev->vcn.num_inst_per_aid = 1;
+ adev->vcn.num_vcn_inst = hweight32(adev->vcn.inst_mask);
+ adev->jpeg.harvest_config = 0;
+ adev->jpeg.num_inst_per_aid = 1;
+ adev->jpeg.num_jpeg_inst = hweight32(adev->jpeg.inst_mask);
+
+ ret = aqua_vanjaram_xcp_mgr_init(adev);
+ if (ret)
+ return ret;
+
+ aqua_vanjaram_ip_map_init(adev);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index de6d10390ab2..5641cf05d856 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1141,12 +1141,12 @@ static uint32_t cik_get_register_value(struct amdgpu_device *adev,
mutex_lock(&adev->grbm_idx_mutex);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff, 0);
val = RREG32(reg_offset);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
return val;
} else {
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index 67d16236b216..52598fbc9b39 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -489,8 +489,6 @@ static int cik_sdma_gfx_resume(struct amdgpu_device *adev)
#endif
/* enable DMA IBs */
WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
-
- ring->sched.ready = true;
}
cik_sdma_enable(adev, true);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index ab44c1391d52..be984f8c71c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -3490,7 +3490,7 @@ static int gfx_v10_0_get_cu_info(struct amdgpu_device *adev,
struct amdgpu_cu_info *cu_info);
static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev);
static void gfx_v10_0_select_se_sh(struct amdgpu_device *adev, u32 se_num,
- u32 sh_num, u32 instance);
+ u32 sh_num, u32 instance, int xcc_id);
static u32 gfx_v10_0_get_wgp_active_bitmap_per_sh(struct amdgpu_device *adev);
static int gfx_v10_0_rlc_backdoor_autoload_buffer_init(struct amdgpu_device *adev);
@@ -3568,7 +3568,7 @@ static void gfx10_kiq_unmap_queues(struct amdgpu_ring *kiq_ring,
struct amdgpu_device *adev = kiq_ring->adev;
uint32_t eng_sel = ring->funcs->type == AMDGPU_RING_TYPE_GFX ? 4 : 0;
- if (adev->enable_mes && !adev->gfx.kiq.ring.sched.ready) {
+ if (adev->enable_mes && !adev->gfx.kiq[0].ring.sched.ready) {
amdgpu_mes_unmap_legacy_queue(adev, ring, action, gpu_addr, seq);
return;
}
@@ -3636,7 +3636,7 @@ static const struct kiq_pm4_funcs gfx_v10_0_kiq_pm4_funcs = {
static void gfx_v10_0_set_kiq_pm4_funcs(struct amdgpu_device *adev)
{
- adev->gfx.kiq.pmf = &gfx_v10_0_kiq_pm4_funcs;
+ adev->gfx.kiq[0].pmf = &gfx_v10_0_kiq_pm4_funcs;
}
static void gfx_v10_0_init_spm_golden_registers(struct amdgpu_device *adev)
@@ -4219,7 +4219,7 @@ static int gfx_v10_0_mec_init(struct amdgpu_device *adev)
const struct gfx_firmware_header_v1_0 *mec_hdr = NULL;
- bitmap_zero(adev->gfx.mec.queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
+ bitmap_zero(adev->gfx.mec_bitmap[0].queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
/* take ownership of the relevant compute queues */
amdgpu_gfx_compute_queue_acquire(adev);
@@ -4291,7 +4291,7 @@ static void wave_read_regs(struct amdgpu_device *adev, uint32_t wave,
*(out++) = RREG32_SOC15(GC, 0, mmSQ_IND_DATA);
}
-static void gfx_v10_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
+static void gfx_v10_0_read_wave_data(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
{
/* in gfx10 the SIMD_ID is specified as part of the INSTANCE
* field when performing a select_se_sh so it should be
@@ -4318,7 +4318,7 @@ static void gfx_v10_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd,
dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_MODE);
}
-static void gfx_v10_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+static void gfx_v10_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t start,
uint32_t size, uint32_t *dst)
{
@@ -4329,7 +4329,7 @@ static void gfx_v10_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
dst);
}
-static void gfx_v10_0_read_wave_vgprs(struct amdgpu_device *adev, uint32_t simd,
+static void gfx_v10_0_read_wave_vgprs(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t thread,
uint32_t start, uint32_t size,
uint32_t *dst)
@@ -4340,7 +4340,7 @@ static void gfx_v10_0_read_wave_vgprs(struct amdgpu_device *adev, uint32_t simd,
}
static void gfx_v10_0_select_me_pipe_q(struct amdgpu_device *adev,
- u32 me, u32 pipe, u32 q, u32 vm)
+ u32 me, u32 pipe, u32 q, u32 vm, u32 xcc_id)
{
nv_grbm_select(adev, me, pipe, q, vm);
}
@@ -4461,7 +4461,7 @@ static int gfx_v10_0_gfx_ring_init(struct amdgpu_device *adev, int ring_id,
ring->doorbell_index = adev->doorbell_index.gfx_ring0 << 1;
else
ring->doorbell_index = adev->doorbell_index.gfx_ring1 << 1;
- ring->vm_hub = AMDGPU_GFXHUB_0;
+ ring->vm_hub = AMDGPU_GFXHUB(0);
sprintf(ring->name, "gfx_%d.%d.%d", ring->me, ring->pipe, ring->queue);
irq_type = AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP + ring->pipe;
@@ -4490,7 +4490,7 @@ static int gfx_v10_0_compute_ring_init(struct amdgpu_device *adev, int ring_id,
ring->doorbell_index = (adev->doorbell_index.mec_ring0 + ring_id) << 1;
ring->eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr
+ (ring_id * GFX10_MEC_HPD_SIZE);
- ring->vm_hub = AMDGPU_GFXHUB_0;
+ ring->vm_hub = AMDGPU_GFXHUB(0);
sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue);
irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP
@@ -4550,7 +4550,7 @@ static int gfx_v10_0_sw_init(void *handle)
/* KIQ event */
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP,
GFX_10_1__SRCID__CP_IB2_INTERRUPT_PKT,
- &adev->gfx.kiq.irq);
+ &adev->gfx.kiq[0].irq);
if (r)
return r;
@@ -4614,8 +4614,8 @@ static int gfx_v10_0_sw_init(void *handle)
for (i = 0; i < adev->gfx.mec.num_mec; ++i) {
for (j = 0; j < adev->gfx.mec.num_queue_per_pipe; j++) {
for (k = 0; k < adev->gfx.mec.num_pipe_per_mec; k++) {
- if (!amdgpu_gfx_is_mec_queue_enabled(adev, i, k,
- j))
+ if (!amdgpu_gfx_is_mec_queue_enabled(adev, 0, i,
+ k, j))
continue;
r = gfx_v10_0_compute_ring_init(adev, ring_id,
@@ -4629,19 +4629,19 @@ static int gfx_v10_0_sw_init(void *handle)
}
if (!adev->enable_mes_kiq) {
- r = amdgpu_gfx_kiq_init(adev, GFX10_MEC_HPD_SIZE);
+ r = amdgpu_gfx_kiq_init(adev, GFX10_MEC_HPD_SIZE, 0);
if (r) {
DRM_ERROR("Failed to init KIQ BOs!\n");
return r;
}
- kiq = &adev->gfx.kiq;
- r = amdgpu_gfx_kiq_init_ring(adev, &kiq->ring, &kiq->irq);
+ kiq = &adev->gfx.kiq[0];
+ r = amdgpu_gfx_kiq_init_ring(adev, &kiq->ring, &kiq->irq, 0);
if (r)
return r;
}
- r = amdgpu_gfx_mqd_sw_init(adev, sizeof(struct v10_compute_mqd));
+ r = amdgpu_gfx_mqd_sw_init(adev, sizeof(struct v10_compute_mqd), 0);
if (r)
return r;
@@ -4690,11 +4690,11 @@ static int gfx_v10_0_sw_fini(void *handle)
for (i = 0; i < adev->gfx.num_compute_rings; i++)
amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
- amdgpu_gfx_mqd_sw_fini(adev);
+ amdgpu_gfx_mqd_sw_fini(adev, 0);
if (!adev->enable_mes_kiq) {
- amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq.ring);
- amdgpu_gfx_kiq_fini(adev);
+ amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq[0].ring);
+ amdgpu_gfx_kiq_fini(adev, 0);
}
gfx_v10_0_pfp_fini(adev);
@@ -4712,7 +4712,7 @@ static int gfx_v10_0_sw_fini(void *handle)
}
static void gfx_v10_0_select_se_sh(struct amdgpu_device *adev, u32 se_num,
- u32 sh_num, u32 instance)
+ u32 sh_num, u32 instance, int xcc_id)
{
u32 data;
@@ -4772,13 +4772,13 @@ static void gfx_v10_0_setup_rb(struct amdgpu_device *adev)
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 6))) &&
((gfx_v10_3_get_disabled_sa(adev) >> bitmap) & 1))
continue;
- gfx_v10_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v10_0_select_se_sh(adev, i, j, 0xffffffff, 0);
data = gfx_v10_0_get_rb_active_bitmap(adev);
active_rbs |= data << ((i * adev->gfx.config.max_sh_per_se + j) *
rb_bitmap_width_per_sh);
}
}
- gfx_v10_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v10_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
adev->gfx.config.backend_enable_mask = active_rbs;
@@ -4825,6 +4825,29 @@ static u32 gfx_v10_0_init_pa_sc_tile_steering_override(struct amdgpu_device *ade
#define DEFAULT_SH_MEM_BASES (0x6000)
+static void gfx_v10_0_debug_trap_config_init(struct amdgpu_device *adev,
+ uint32_t first_vmid,
+ uint32_t last_vmid)
+{
+ uint32_t data;
+ uint32_t trap_config_vmid_mask = 0;
+ int i;
+
+ /* Calculate trap config vmid mask */
+ for (i = first_vmid; i < last_vmid; i++)
+ trap_config_vmid_mask |= (1 << i);
+
+ data = REG_SET_FIELD(0, SPI_GDBG_TRAP_CONFIG,
+ VMID_SEL, trap_config_vmid_mask);
+ data = REG_SET_FIELD(data, SPI_GDBG_TRAP_CONFIG,
+ TRAP_EN, 1);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_CONFIG), data);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
+
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_DATA0), 0);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_DATA1), 0);
+}
+
static void gfx_v10_0_init_compute_vmid(struct amdgpu_device *adev)
{
int i;
@@ -4856,6 +4879,9 @@ static void gfx_v10_0_init_compute_vmid(struct amdgpu_device *adev)
WREG32_SOC15_OFFSET(GC, 0, mmGDS_GWS_VMID0, i, 0);
WREG32_SOC15_OFFSET(GC, 0, mmGDS_OA_VMID0, i, 0);
}
+
+ gfx_v10_0_debug_trap_config_init(adev, adev->vm_manager.first_kfd_vmid,
+ AMDGPU_NUM_VMID);
}
static void gfx_v10_0_init_gds_vmid(struct amdgpu_device *adev)
@@ -4907,7 +4933,7 @@ static void gfx_v10_0_tcp_harvest(struct amdgpu_device *adev)
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++) {
- gfx_v10_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v10_0_select_se_sh(adev, i, j, 0xffffffff, 0);
wgp_active_bitmap = gfx_v10_0_get_wgp_active_bitmap_per_sh(adev);
/*
* Set corresponding TCP bits for the inactive WGPs in
@@ -4940,7 +4966,7 @@ static void gfx_v10_0_tcp_harvest(struct amdgpu_device *adev)
}
}
- gfx_v10_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v10_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
}
@@ -4978,7 +5004,7 @@ static void gfx_v10_0_constants_init(struct amdgpu_device *adev)
/* XXX SH_MEM regs */
/* where to put LDS, scratch, GPUVM in FSA64 space */
mutex_lock(&adev->srbm_mutex);
- for (i = 0; i < adev->vm_manager.id_mgr[AMDGPU_GFXHUB_0].num_ids; i++) {
+ for (i = 0; i < adev->vm_manager.id_mgr[AMDGPU_GFXHUB(0)].num_ids; i++) {
nv_grbm_select(adev, 0, 0, 0, i);
/* CP and shaders */
WREG32_SOC15(GC, 0, mmSH_MEM_CONFIG, DEFAULT_SH_MEM_CONFIG);
@@ -6073,7 +6099,6 @@ static int gfx_v10_0_cp_gfx_resume(struct amdgpu_device *adev)
u32 tmp;
u32 rb_bufsz;
u64 rb_addr, rptr_addr, wptr_gpu_addr;
- u32 i;
/* Set the write pointer delay */
WREG32_SOC15(GC, 0, mmCP_RB_WPTR_DELAY, 0);
@@ -6168,11 +6193,6 @@ static int gfx_v10_0_cp_gfx_resume(struct amdgpu_device *adev)
/* start the ring */
gfx_v10_0_cp_gfx_start(adev);
- for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
- ring = &adev->gfx.gfx_ring[i];
- ring->sched.ready = true;
- }
-
return 0;
}
@@ -6214,7 +6234,7 @@ static void gfx_v10_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
CP_MEC_CNTL__MEC_ME2_HALT_MASK));
break;
}
- adev->gfx.kiq.ring.sched.ready = false;
+ adev->gfx.kiq[0].ring.sched.ready = false;
}
udelay(50);
}
@@ -6423,55 +6443,6 @@ static int gfx_v10_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
return 0;
}
-#ifdef BRING_UP_DEBUG
-static int gfx_v10_0_gfx_queue_init_register(struct amdgpu_ring *ring)
-{
- struct amdgpu_device *adev = ring->adev;
- struct v10_gfx_mqd *mqd = ring->mqd_ptr;
-
- /* set mmCP_GFX_HQD_WPTR/_HI to 0 */
- WREG32_SOC15(GC, 0, mmCP_GFX_HQD_WPTR, mqd->cp_gfx_hqd_wptr);
- WREG32_SOC15(GC, 0, mmCP_GFX_HQD_WPTR_HI, mqd->cp_gfx_hqd_wptr_hi);
-
- /* set GFX_MQD_BASE */
- WREG32_SOC15(GC, 0, mmCP_MQD_BASE_ADDR, mqd->cp_mqd_base_addr);
- WREG32_SOC15(GC, 0, mmCP_MQD_BASE_ADDR_HI, mqd->cp_mqd_base_addr_hi);
-
- /* set GFX_MQD_CONTROL */
- WREG32_SOC15(GC, 0, mmCP_GFX_MQD_CONTROL, mqd->cp_gfx_mqd_control);
-
- /* set GFX_HQD_VMID to 0 */
- WREG32_SOC15(GC, 0, mmCP_GFX_HQD_VMID, mqd->cp_gfx_hqd_vmid);
-
- WREG32_SOC15(GC, 0, mmCP_GFX_HQD_QUEUE_PRIORITY,
- mqd->cp_gfx_hqd_queue_priority);
- WREG32_SOC15(GC, 0, mmCP_GFX_HQD_QUANTUM, mqd->cp_gfx_hqd_quantum);
-
- /* set GFX_HQD_BASE, similar as CP_RB_BASE */
- WREG32_SOC15(GC, 0, mmCP_GFX_HQD_BASE, mqd->cp_gfx_hqd_base);
- WREG32_SOC15(GC, 0, mmCP_GFX_HQD_BASE_HI, mqd->cp_gfx_hqd_base_hi);
-
- /* set GFX_HQD_RPTR_ADDR, similar as CP_RB_RPTR */
- WREG32_SOC15(GC, 0, mmCP_GFX_HQD_RPTR_ADDR, mqd->cp_gfx_hqd_rptr_addr);
- WREG32_SOC15(GC, 0, mmCP_GFX_HQD_RPTR_ADDR_HI, mqd->cp_gfx_hqd_rptr_addr_hi);
-
- /* set GFX_HQD_CNTL, similar as CP_RB_CNTL */
- WREG32_SOC15(GC, 0, mmCP_GFX_HQD_CNTL, mqd->cp_gfx_hqd_cntl);
-
- /* set RB_WPTR_POLL_ADDR */
- WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_LO, mqd->cp_rb_wptr_poll_addr_lo);
- WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_HI, mqd->cp_rb_wptr_poll_addr_hi);
-
- /* set RB_DOORBELL_CONTROL */
- WREG32_SOC15(GC, 0, mmCP_RB_DOORBELL_CONTROL, mqd->cp_rb_doorbell_control);
-
- /* active the queue */
- WREG32_SOC15(GC, 0, mmCP_GFX_HQD_ACTIVE, mqd->cp_gfx_hqd_active);
-
- return 0;
-}
-#endif
-
static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
@@ -6492,59 +6463,23 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring)
if (ring->doorbell_index == adev->doorbell_index.gfx_ring0 << 1)
gfx_v10_0_cp_gfx_set_doorbell(adev, ring);
-#ifdef BRING_UP_DEBUG
- gfx_v10_0_gfx_queue_init_register(ring);
-#endif
nv_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.me.mqd_backup[mqd_idx])
memcpy(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
- } else if (amdgpu_in_reset(adev)) {
- /* reset mqd with the backup copy */
+ } else {
+ /* restore mqd with the backup copy */
if (adev->gfx.me.mqd_backup[mqd_idx])
memcpy(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd));
/* reset the ring */
ring->wptr = 0;
*ring->wptr_cpu_addr = 0;
amdgpu_ring_clear_ring(ring);
-#ifdef BRING_UP_DEBUG
- mutex_lock(&adev->srbm_mutex);
- nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
- gfx_v10_0_gfx_queue_init_register(ring);
- nv_grbm_select(adev, 0, 0, 0, 0);
- mutex_unlock(&adev->srbm_mutex);
-#endif
- } else {
- amdgpu_ring_clear_ring(ring);
}
return 0;
}
-#ifndef BRING_UP_DEBUG
-static int gfx_v10_0_kiq_enable_kgq(struct amdgpu_device *adev)
-{
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
- struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
- int r, i;
-
- if (!kiq->pmf || !kiq->pmf->kiq_map_queues)
- return -EINVAL;
-
- r = amdgpu_ring_alloc(kiq_ring, kiq->pmf->map_queues_size *
- adev->gfx.num_gfx_rings);
- if (r) {
- DRM_ERROR("Failed to lock KIQ (%d).\n", r);
- return r;
- }
-
- for (i = 0; i < adev->gfx.num_gfx_rings; i++)
- kiq->pmf->kiq_map_queues(kiq_ring, &adev->gfx.gfx_ring[i]);
-
- return amdgpu_ring_test_helper(kiq_ring);
-}
-#endif
-
static int gfx_v10_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev)
{
int r, i;
@@ -6555,7 +6490,7 @@ static int gfx_v10_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev)
r = amdgpu_bo_reserve(ring->mqd_obj, false);
if (unlikely(r != 0))
- goto done;
+ return r;
r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
if (!r) {
@@ -6565,23 +6500,14 @@ static int gfx_v10_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev)
}
amdgpu_bo_unreserve(ring->mqd_obj);
if (r)
- goto done;
+ return r;
}
-#ifndef BRING_UP_DEBUG
- r = gfx_v10_0_kiq_enable_kgq(adev);
- if (r)
- goto done;
-#endif
- r = gfx_v10_0_cp_gfx_start(adev);
+
+ r = amdgpu_gfx_enable_kgq(adev, 0);
if (r)
- goto done;
+ return r;
- for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
- ring = &adev->gfx.gfx_ring[i];
- ring->sched.ready = true;
- }
-done:
- return r;
+ return gfx_v10_0_cp_gfx_start(adev);
}
static int gfx_v10_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
@@ -6812,14 +6738,13 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
struct v10_compute_mqd *mqd = ring->mqd_ptr;
- int mqd_idx = AMDGPU_MAX_COMPUTE_RINGS;
gfx_v10_0_kiq_setting(ring);
if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */
/* reset MQD to a clean status */
- if (adev->gfx.mec.mqd_backup[mqd_idx])
- memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd));
+ if (adev->gfx.kiq[0].mqd_backup)
+ memcpy(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(*mqd));
/* reset ring buffer */
ring->wptr = 0;
@@ -6841,8 +6766,8 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring)
nv_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
- if (adev->gfx.mec.mqd_backup[mqd_idx])
- memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
+ if (adev->gfx.kiq[0].mqd_backup)
+ memcpy(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(*mqd));
}
return 0;
@@ -6864,17 +6789,14 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring)
if (adev->gfx.mec.mqd_backup[mqd_idx])
memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
- } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */
- /* reset MQD to a clean status */
+ } else {
+ /* restore MQD to a clean status */
if (adev->gfx.mec.mqd_backup[mqd_idx])
memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd));
-
/* reset ring buffer */
ring->wptr = 0;
atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0);
amdgpu_ring_clear_ring(ring);
- } else {
- amdgpu_ring_clear_ring(ring);
}
return 0;
@@ -6885,7 +6807,7 @@ static int gfx_v10_0_kiq_resume(struct amdgpu_device *adev)
struct amdgpu_ring *ring;
int r;
- ring = &adev->gfx.kiq.ring;
+ ring = &adev->gfx.kiq[0].ring;
r = amdgpu_bo_reserve(ring->mqd_obj, false);
if (unlikely(r != 0))
@@ -6901,7 +6823,6 @@ static int gfx_v10_0_kiq_resume(struct amdgpu_device *adev)
amdgpu_bo_kunmap(ring->mqd_obj);
ring->mqd_ptr = NULL;
amdgpu_bo_unreserve(ring->mqd_obj);
- ring->sched.ready = true;
return 0;
}
@@ -6929,7 +6850,7 @@ static int gfx_v10_0_kcq_resume(struct amdgpu_device *adev)
goto done;
}
- r = amdgpu_gfx_enable_kcq(adev);
+ r = amdgpu_gfx_enable_kcq(adev, 0);
done:
return r;
}
@@ -7242,47 +7163,20 @@ static int gfx_v10_0_hw_init(void *handle)
return r;
}
-#ifndef BRING_UP_DEBUG
-static int gfx_v10_0_kiq_disable_kgq(struct amdgpu_device *adev)
-{
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
- struct amdgpu_ring *kiq_ring = &kiq->ring;
- int i;
-
- if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
- return -EINVAL;
-
- if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size *
- adev->gfx.num_gfx_rings))
- return -ENOMEM;
-
- for (i = 0; i < adev->gfx.num_gfx_rings; i++)
- kiq->pmf->kiq_unmap_queues(kiq_ring, &adev->gfx.gfx_ring[i],
- PREEMPT_QUEUES, 0, 0);
- if (!adev->job_hang)
- return amdgpu_ring_test_helper(kiq_ring);
- else
- return 0;
-}
-#endif
-
static int gfx_v10_0_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- int r;
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
if (!adev->no_hw_access) {
-#ifndef BRING_UP_DEBUG
if (amdgpu_async_gfx_ring) {
- r = gfx_v10_0_kiq_disable_kgq(adev);
- if (r)
+ if (amdgpu_gfx_disable_kgq(adev, 0))
DRM_ERROR("KGQ disable failed\n");
}
-#endif
- if (amdgpu_gfx_disable_kcq(adev))
+
+ if (amdgpu_gfx_disable_kcq(adev, 0))
DRM_ERROR("KCQ disable failed\n");
}
@@ -7574,7 +7468,7 @@ static bool gfx_v10_0_is_rlc_enabled(struct amdgpu_device *adev)
return (REG_GET_FIELD(rlc_cntl, RLC_CNTL, RLC_ENABLE_F32)) ? true : false;
}
-static void gfx_v10_0_set_safe_mode(struct amdgpu_device *adev)
+static void gfx_v10_0_set_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
uint32_t data;
unsigned i;
@@ -7615,7 +7509,7 @@ static void gfx_v10_0_set_safe_mode(struct amdgpu_device *adev)
}
}
-static void gfx_v10_0_unset_safe_mode(struct amdgpu_device *adev)
+static void gfx_v10_0_unset_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
uint32_t data;
@@ -7962,7 +7856,7 @@ static void gfx_v10_0_apply_medium_grain_clock_gating_workaround(struct amdgpu_d
static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev,
bool enable)
{
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
if (enable) {
/* enable FGCG firstly*/
@@ -8001,7 +7895,7 @@ static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev,
AMD_CG_SUPPORT_GFX_3D_CGLS))
gfx_v10_0_enable_gui_idle_interrupt(adev, enable);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return 0;
}
@@ -8095,11 +7989,11 @@ static void gfx_v10_cntl_power_gating(struct amdgpu_device *adev, bool enable)
static void gfx_v10_cntl_pg(struct amdgpu_device *adev, bool enable)
{
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
gfx_v10_cntl_power_gating(adev, enable);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static const struct amdgpu_rlc_funcs gfx_v10_0_rlc_funcs = {
@@ -8648,7 +8542,7 @@ static int gfx_v10_0_ring_preempt_ib(struct amdgpu_ring *ring)
{
int i, r = 0;
struct amdgpu_device *adev = ring->adev;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
struct amdgpu_ring *kiq_ring = &kiq->ring;
unsigned long flags;
@@ -9156,7 +9050,7 @@ static int gfx_v10_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
enum amdgpu_interrupt_state state)
{
uint32_t tmp, target;
- struct amdgpu_ring *ring = &(adev->gfx.kiq.ring);
+ struct amdgpu_ring *ring = &(adev->gfx.kiq[0].ring);
if (ring->me == 1)
target = SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE0_INT_CNTL);
@@ -9200,7 +9094,7 @@ static int gfx_v10_0_kiq_irq(struct amdgpu_device *adev,
struct amdgpu_iv_entry *entry)
{
u8 me_id, pipe_id, queue_id;
- struct amdgpu_ring *ring = &(adev->gfx.kiq.ring);
+ struct amdgpu_ring *ring = &(adev->gfx.kiq[0].ring);
me_id = (entry->ring_id & 0x0c) >> 2;
pipe_id = (entry->ring_id & 0x03) >> 0;
@@ -9377,7 +9271,7 @@ static void gfx_v10_0_set_ring_funcs(struct amdgpu_device *adev)
{
int i;
- adev->gfx.kiq.ring.funcs = &gfx_v10_0_ring_funcs_kiq;
+ adev->gfx.kiq[0].ring.funcs = &gfx_v10_0_ring_funcs_kiq;
for (i = 0; i < adev->gfx.num_gfx_rings; i++)
adev->gfx.gfx_ring[i].funcs = &gfx_v10_0_ring_funcs_gfx;
@@ -9411,8 +9305,8 @@ static void gfx_v10_0_set_irq_funcs(struct amdgpu_device *adev)
adev->gfx.eop_irq.num_types = AMDGPU_CP_IRQ_LAST;
adev->gfx.eop_irq.funcs = &gfx_v10_0_eop_irq_funcs;
- adev->gfx.kiq.irq.num_types = AMDGPU_CP_KIQ_IRQ_LAST;
- adev->gfx.kiq.irq.funcs = &gfx_v10_0_kiq_irq_funcs;
+ adev->gfx.kiq[0].irq.num_types = AMDGPU_CP_KIQ_IRQ_LAST;
+ adev->gfx.kiq[0].irq.funcs = &gfx_v10_0_kiq_irq_funcs;
adev->gfx.priv_reg_irq.num_types = 1;
adev->gfx.priv_reg_irq.funcs = &gfx_v10_0_priv_reg_irq_funcs;
@@ -9549,7 +9443,7 @@ static int gfx_v10_0_get_cu_info(struct amdgpu_device *adev,
mask = 1;
ao_bitmap = 0;
counter = 0;
- gfx_v10_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v10_0_select_se_sh(adev, i, j, 0xffffffff, 0);
if (i < 4 && j < 2)
gfx_v10_0_set_user_wgp_inactive_bitmap_per_sh(
adev, disable_masks[i * 2 + j]);
@@ -9570,7 +9464,7 @@ static int gfx_v10_0_get_cu_info(struct amdgpu_device *adev,
cu_info->ao_cu_bitmap[i][j] = ao_bitmap;
}
}
- gfx_v10_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v10_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
cu_info->number = active_cu_number;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index c4940b6ea1c4..690e121d9dda 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -112,7 +112,7 @@ static int gfx_v11_0_get_cu_info(struct amdgpu_device *adev,
struct amdgpu_cu_info *cu_info);
static uint64_t gfx_v11_0_get_gpu_clock_counter(struct amdgpu_device *adev);
static void gfx_v11_0_select_se_sh(struct amdgpu_device *adev, u32 se_num,
- u32 sh_num, u32 instance);
+ u32 sh_num, u32 instance, int xcc_id);
static u32 gfx_v11_0_get_wgp_active_bitmap_per_sh(struct amdgpu_device *adev);
static void gfx_v11_0_ring_emit_de_meta(struct amdgpu_ring *ring, bool resume);
@@ -123,8 +123,8 @@ static int gfx_v11_0_wait_for_rlc_autoload_complete(struct amdgpu_device *adev);
static void gfx_v11_0_ring_invalidate_tlbs(struct amdgpu_ring *ring,
uint16_t pasid, uint32_t flush_type,
bool all_hub, uint8_t dst_sel);
-static void gfx_v11_0_set_safe_mode(struct amdgpu_device *adev);
-static void gfx_v11_0_unset_safe_mode(struct amdgpu_device *adev);
+static void gfx_v11_0_set_safe_mode(struct amdgpu_device *adev, int xcc_id);
+static void gfx_v11_0_unset_safe_mode(struct amdgpu_device *adev, int xcc_id);
static void gfx_v11_0_update_perf_clk(struct amdgpu_device *adev,
bool enable);
@@ -192,7 +192,7 @@ static void gfx11_kiq_unmap_queues(struct amdgpu_ring *kiq_ring,
struct amdgpu_device *adev = kiq_ring->adev;
uint32_t eng_sel = ring->funcs->type == AMDGPU_RING_TYPE_GFX ? 4 : 0;
- if (adev->enable_mes && !adev->gfx.kiq.ring.sched.ready) {
+ if (adev->enable_mes && !adev->gfx.kiq[0].ring.sched.ready) {
amdgpu_mes_unmap_legacy_queue(adev, ring, action, gpu_addr, seq);
return;
}
@@ -260,7 +260,7 @@ static const struct kiq_pm4_funcs gfx_v11_0_kiq_pm4_funcs = {
static void gfx_v11_0_set_kiq_pm4_funcs(struct amdgpu_device *adev)
{
- adev->gfx.kiq.pmf = &gfx_v11_0_kiq_pm4_funcs;
+ adev->gfx.kiq[0].pmf = &gfx_v11_0_kiq_pm4_funcs;
}
static void gfx_v11_0_init_golden_registers(struct amdgpu_device *adev)
@@ -463,6 +463,23 @@ out:
return err;
}
+static void gfx_v11_0_check_fw_cp_gfx_shadow(struct amdgpu_device *adev)
+{
+ switch (adev->ip_versions[GC_HWIP][0]) {
+ case IP_VERSION(11, 0, 0):
+ case IP_VERSION(11, 0, 2):
+ case IP_VERSION(11, 0, 3):
+ if ((adev->gfx.me_fw_version >= 1505) &&
+ (adev->gfx.pfp_fw_version >= 1600) &&
+ (adev->gfx.mec_fw_version >= 512))
+ adev->gfx.cp_gfx_shadow = true;
+ break;
+ default:
+ adev->gfx.cp_gfx_shadow = false;
+ break;
+ }
+}
+
static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
{
char fw_name[40];
@@ -539,6 +556,7 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
/* only one MEC for gfx 11.0.0. */
adev->gfx.mec2_fw = NULL;
+ gfx_v11_0_check_fw_cp_gfx_shadow(adev);
out:
if (err) {
amdgpu_ucode_release(&adev->gfx.pfp_fw);
@@ -699,7 +717,7 @@ static int gfx_v11_0_mec_init(struct amdgpu_device *adev)
u32 *hpd;
size_t mec_hpd_size;
- bitmap_zero(adev->gfx.mec.queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
+ bitmap_zero(adev->gfx.mec_bitmap[0].queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
/* take ownership of the relevant compute queues */
amdgpu_gfx_compute_queue_acquire(adev);
@@ -747,7 +765,7 @@ static void wave_read_regs(struct amdgpu_device *adev, uint32_t wave,
*(out++) = RREG32_SOC15(GC, 0, regSQ_IND_DATA);
}
-static void gfx_v11_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
+static void gfx_v11_0_read_wave_data(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
{
/* in gfx11 the SIMD_ID is specified as part of the INSTANCE
* field when performing a select_se_sh so it should be
@@ -773,7 +791,7 @@ static void gfx_v11_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd,
dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_MODE);
}
-static void gfx_v11_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+static void gfx_v11_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t start,
uint32_t size, uint32_t *dst)
{
@@ -784,7 +802,7 @@ static void gfx_v11_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
dst);
}
-static void gfx_v11_0_read_wave_vgprs(struct amdgpu_device *adev, uint32_t simd,
+static void gfx_v11_0_read_wave_vgprs(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t thread,
uint32_t start, uint32_t size,
uint32_t *dst)
@@ -795,11 +813,32 @@ static void gfx_v11_0_read_wave_vgprs(struct amdgpu_device *adev, uint32_t simd,
}
static void gfx_v11_0_select_me_pipe_q(struct amdgpu_device *adev,
- u32 me, u32 pipe, u32 q, u32 vm)
+ u32 me, u32 pipe, u32 q, u32 vm, u32 xcc_id)
{
soc21_grbm_select(adev, me, pipe, q, vm);
}
+/* all sizes are in bytes */
+#define MQD_SHADOW_BASE_SIZE 73728
+#define MQD_SHADOW_BASE_ALIGNMENT 256
+#define MQD_FWWORKAREA_SIZE 484
+#define MQD_FWWORKAREA_ALIGNMENT 256
+
+static int gfx_v11_0_get_gfx_shadow_info(struct amdgpu_device *adev,
+ struct amdgpu_gfx_shadow_info *shadow_info)
+{
+ if (adev->gfx.cp_gfx_shadow) {
+ shadow_info->shadow_size = MQD_SHADOW_BASE_SIZE;
+ shadow_info->shadow_alignment = MQD_SHADOW_BASE_ALIGNMENT;
+ shadow_info->csa_size = MQD_FWWORKAREA_SIZE;
+ shadow_info->csa_alignment = MQD_FWWORKAREA_ALIGNMENT;
+ return 0;
+ } else {
+ memset(shadow_info, 0, sizeof(struct amdgpu_gfx_shadow_info));
+ return -ENOTSUPP;
+ }
+}
+
static const struct amdgpu_gfx_funcs gfx_v11_0_gfx_funcs = {
.get_gpu_clock_counter = &gfx_v11_0_get_gpu_clock_counter,
.select_se_sh = &gfx_v11_0_select_se_sh,
@@ -808,6 +847,7 @@ static const struct amdgpu_gfx_funcs gfx_v11_0_gfx_funcs = {
.read_wave_vgprs = &gfx_v11_0_read_wave_vgprs,
.select_me_pipe_q = &gfx_v11_0_select_me_pipe_q,
.update_perfmon_mgcg = &gfx_v11_0_update_perf_clk,
+ .get_gfx_shadow_info = &gfx_v11_0_get_gfx_shadow_info,
};
static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
@@ -866,7 +906,7 @@ static int gfx_v11_0_gfx_ring_init(struct amdgpu_device *adev, int ring_id,
ring->doorbell_index = adev->doorbell_index.gfx_ring0 << 1;
else
ring->doorbell_index = adev->doorbell_index.gfx_ring1 << 1;
- ring->vm_hub = AMDGPU_GFXHUB_0;
+ ring->vm_hub = AMDGPU_GFXHUB(0);
sprintf(ring->name, "gfx_%d.%d.%d", ring->me, ring->pipe, ring->queue);
irq_type = AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP + ring->pipe;
@@ -897,7 +937,7 @@ static int gfx_v11_0_compute_ring_init(struct amdgpu_device *adev, int ring_id,
ring->doorbell_index = (adev->doorbell_index.mec_ring0 + ring_id) << 1;
ring->eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr
+ (ring_id * GFX11_MEC_HPD_SIZE);
- ring->vm_hub = AMDGPU_GFXHUB_0;
+ ring->vm_hub = AMDGPU_GFXHUB(0);
sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue);
irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP
@@ -1367,8 +1407,8 @@ static int gfx_v11_0_sw_init(void *handle)
for (i = 0; i < adev->gfx.mec.num_mec; ++i) {
for (j = 0; j < adev->gfx.mec.num_queue_per_pipe; j++) {
for (k = 0; k < adev->gfx.mec.num_pipe_per_mec; k++) {
- if (!amdgpu_gfx_is_mec_queue_enabled(adev, i, k,
- j))
+ if (!amdgpu_gfx_is_mec_queue_enabled(adev, 0, i,
+ k, j))
continue;
r = gfx_v11_0_compute_ring_init(adev, ring_id,
@@ -1382,19 +1422,19 @@ static int gfx_v11_0_sw_init(void *handle)
}
if (!adev->enable_mes_kiq) {
- r = amdgpu_gfx_kiq_init(adev, GFX11_MEC_HPD_SIZE);
+ r = amdgpu_gfx_kiq_init(adev, GFX11_MEC_HPD_SIZE, 0);
if (r) {
DRM_ERROR("Failed to init KIQ BOs!\n");
return r;
}
- kiq = &adev->gfx.kiq;
- r = amdgpu_gfx_kiq_init_ring(adev, &kiq->ring, &kiq->irq);
+ kiq = &adev->gfx.kiq[0];
+ r = amdgpu_gfx_kiq_init_ring(adev, &kiq->ring, &kiq->irq, 0);
if (r)
return r;
}
- r = amdgpu_gfx_mqd_sw_init(adev, sizeof(struct v11_compute_mqd));
+ r = amdgpu_gfx_mqd_sw_init(adev, sizeof(struct v11_compute_mqd), 0);
if (r)
return r;
@@ -1456,11 +1496,11 @@ static int gfx_v11_0_sw_fini(void *handle)
for (i = 0; i < adev->gfx.num_compute_rings; i++)
amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
- amdgpu_gfx_mqd_sw_fini(adev);
+ amdgpu_gfx_mqd_sw_fini(adev, 0);
if (!adev->enable_mes_kiq) {
- amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq.ring);
- amdgpu_gfx_kiq_fini(adev);
+ amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq[0].ring);
+ amdgpu_gfx_kiq_fini(adev, 0);
}
gfx_v11_0_pfp_fini(adev);
@@ -1477,7 +1517,7 @@ static int gfx_v11_0_sw_fini(void *handle)
}
static void gfx_v11_0_select_se_sh(struct amdgpu_device *adev, u32 se_num,
- u32 sh_num, u32 instance)
+ u32 sh_num, u32 instance, int xcc_id)
{
u32 data;
@@ -1598,6 +1638,7 @@ static void gfx_v11_0_init_compute_vmid(struct amdgpu_device *adev)
/* Enable trap for each kfd vmid. */
data = RREG32_SOC15(GC, 0, regSPI_GDBG_PER_VMID_CNTL);
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, 1);
+ WREG32_SOC15(GC, 0, regSPI_GDBG_PER_VMID_CNTL, data);
}
soc21_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
@@ -1667,7 +1708,7 @@ static void gfx_v11_0_constants_init(struct amdgpu_device *adev)
/* XXX SH_MEM regs */
/* where to put LDS, scratch, GPUVM in FSA64 space */
mutex_lock(&adev->srbm_mutex);
- for (i = 0; i < adev->vm_manager.id_mgr[AMDGPU_GFXHUB_0].num_ids; i++) {
+ for (i = 0; i < adev->vm_manager.id_mgr[AMDGPU_GFXHUB(0)].num_ids; i++) {
soc21_grbm_select(adev, 0, 0, 0, i);
/* CP and shaders */
WREG32_SOC15(GC, 0, regSH_MEM_CONFIG, DEFAULT_SH_MEM_CONFIG);
@@ -3188,7 +3229,6 @@ static int gfx_v11_0_cp_gfx_resume(struct amdgpu_device *adev)
u32 tmp;
u32 rb_bufsz;
u64 rb_addr, rptr_addr, wptr_gpu_addr;
- u32 i;
/* Set the write pointer delay */
WREG32_SOC15(GC, 0, regCP_RB_WPTR_DELAY, 0);
@@ -3280,11 +3320,6 @@ static int gfx_v11_0_cp_gfx_resume(struct amdgpu_device *adev)
/* start the ring */
gfx_v11_0_cp_gfx_start(adev);
- for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
- ring = &adev->gfx.gfx_ring[i];
- ring->sched.ready = true;
- }
-
return 0;
}
@@ -3330,8 +3365,6 @@ static void gfx_v11_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
WREG32_SOC15(GC, 0, regCP_MEC_CNTL, data);
}
- adev->gfx.kiq.ring.sched.ready = enable;
-
udelay(50);
}
@@ -3633,55 +3666,6 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
return 0;
}
-#ifdef BRING_UP_DEBUG
-static int gfx_v11_0_gfx_queue_init_register(struct amdgpu_ring *ring)
-{
- struct amdgpu_device *adev = ring->adev;
- struct v11_gfx_mqd *mqd = ring->mqd_ptr;
-
- /* set mmCP_GFX_HQD_WPTR/_HI to 0 */
- WREG32_SOC15(GC, 0, regCP_GFX_HQD_WPTR, mqd->cp_gfx_hqd_wptr);
- WREG32_SOC15(GC, 0, regCP_GFX_HQD_WPTR_HI, mqd->cp_gfx_hqd_wptr_hi);
-
- /* set GFX_MQD_BASE */
- WREG32_SOC15(GC, 0, regCP_MQD_BASE_ADDR, mqd->cp_mqd_base_addr);
- WREG32_SOC15(GC, 0, regCP_MQD_BASE_ADDR_HI, mqd->cp_mqd_base_addr_hi);
-
- /* set GFX_MQD_CONTROL */
- WREG32_SOC15(GC, 0, regCP_GFX_MQD_CONTROL, mqd->cp_gfx_mqd_control);
-
- /* set GFX_HQD_VMID to 0 */
- WREG32_SOC15(GC, 0, regCP_GFX_HQD_VMID, mqd->cp_gfx_hqd_vmid);
-
- WREG32_SOC15(GC, 0, regCP_GFX_HQD_QUEUE_PRIORITY,
- mqd->cp_gfx_hqd_queue_priority);
- WREG32_SOC15(GC, 0, regCP_GFX_HQD_QUANTUM, mqd->cp_gfx_hqd_quantum);
-
- /* set GFX_HQD_BASE, similar as CP_RB_BASE */
- WREG32_SOC15(GC, 0, regCP_GFX_HQD_BASE, mqd->cp_gfx_hqd_base);
- WREG32_SOC15(GC, 0, regCP_GFX_HQD_BASE_HI, mqd->cp_gfx_hqd_base_hi);
-
- /* set GFX_HQD_RPTR_ADDR, similar as CP_RB_RPTR */
- WREG32_SOC15(GC, 0, regCP_GFX_HQD_RPTR_ADDR, mqd->cp_gfx_hqd_rptr_addr);
- WREG32_SOC15(GC, 0, regCP_GFX_HQD_RPTR_ADDR_HI, mqd->cp_gfx_hqd_rptr_addr_hi);
-
- /* set GFX_HQD_CNTL, similar as CP_RB_CNTL */
- WREG32_SOC15(GC, 0, regCP_GFX_HQD_CNTL, mqd->cp_gfx_hqd_cntl);
-
- /* set RB_WPTR_POLL_ADDR */
- WREG32_SOC15(GC, 0, regCP_RB_WPTR_POLL_ADDR_LO, mqd->cp_rb_wptr_poll_addr_lo);
- WREG32_SOC15(GC, 0, regCP_RB_WPTR_POLL_ADDR_HI, mqd->cp_rb_wptr_poll_addr_hi);
-
- /* set RB_DOORBELL_CONTROL */
- WREG32_SOC15(GC, 0, regCP_RB_DOORBELL_CONTROL, mqd->cp_rb_doorbell_control);
-
- /* active the queue */
- WREG32_SOC15(GC, 0, regCP_GFX_HQD_ACTIVE, mqd->cp_gfx_hqd_active);
-
- return 0;
-}
-#endif
-
static int gfx_v11_0_gfx_init_queue(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
@@ -3693,59 +3677,23 @@ static int gfx_v11_0_gfx_init_queue(struct amdgpu_ring *ring)
mutex_lock(&adev->srbm_mutex);
soc21_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
amdgpu_ring_init_mqd(ring);
-#ifdef BRING_UP_DEBUG
- gfx_v11_0_gfx_queue_init_register(ring);
-#endif
soc21_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.me.mqd_backup[mqd_idx])
memcpy(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
- } else if (amdgpu_in_reset(adev)) {
- /* reset mqd with the backup copy */
+ } else {
+ /* restore mqd with the backup copy */
if (adev->gfx.me.mqd_backup[mqd_idx])
memcpy(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd));
/* reset the ring */
ring->wptr = 0;
*ring->wptr_cpu_addr = 0;
amdgpu_ring_clear_ring(ring);
-#ifdef BRING_UP_DEBUG
- mutex_lock(&adev->srbm_mutex);
- soc21_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
- gfx_v11_0_gfx_queue_init_register(ring);
- soc21_grbm_select(adev, 0, 0, 0, 0);
- mutex_unlock(&adev->srbm_mutex);
-#endif
- } else {
- amdgpu_ring_clear_ring(ring);
}
return 0;
}
-#ifndef BRING_UP_DEBUG
-static int gfx_v11_0_kiq_enable_kgq(struct amdgpu_device *adev)
-{
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
- struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
- int r, i;
-
- if (!kiq->pmf || !kiq->pmf->kiq_map_queues)
- return -EINVAL;
-
- r = amdgpu_ring_alloc(kiq_ring, kiq->pmf->map_queues_size *
- adev->gfx.num_gfx_rings);
- if (r) {
- DRM_ERROR("Failed to lock KIQ (%d).\n", r);
- return r;
- }
-
- for (i = 0; i < adev->gfx.num_gfx_rings; i++)
- kiq->pmf->kiq_map_queues(kiq_ring, &adev->gfx.gfx_ring[i]);
-
- return amdgpu_ring_test_helper(kiq_ring);
-}
-#endif
-
static int gfx_v11_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev)
{
int r, i;
@@ -3756,7 +3704,7 @@ static int gfx_v11_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev)
r = amdgpu_bo_reserve(ring->mqd_obj, false);
if (unlikely(r != 0))
- goto done;
+ return r;
r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
if (!r) {
@@ -3766,23 +3714,14 @@ static int gfx_v11_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev)
}
amdgpu_bo_unreserve(ring->mqd_obj);
if (r)
- goto done;
+ return r;
}
-#ifndef BRING_UP_DEBUG
- r = gfx_v11_0_kiq_enable_kgq(adev);
- if (r)
- goto done;
-#endif
- r = gfx_v11_0_cp_gfx_start(adev);
+
+ r = amdgpu_gfx_enable_kgq(adev, 0);
if (r)
- goto done;
+ return r;
- for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
- ring = &adev->gfx.gfx_ring[i];
- ring->sched.ready = true;
- }
-done:
- return r;
+ return gfx_v11_0_cp_gfx_start(adev);
}
static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m,
@@ -4028,14 +3967,13 @@ static int gfx_v11_0_kiq_init_queue(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
struct v11_compute_mqd *mqd = ring->mqd_ptr;
- int mqd_idx = AMDGPU_MAX_COMPUTE_RINGS;
gfx_v11_0_kiq_setting(ring);
if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */
/* reset MQD to a clean status */
- if (adev->gfx.mec.mqd_backup[mqd_idx])
- memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd));
+ if (adev->gfx.kiq[0].mqd_backup)
+ memcpy(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(*mqd));
/* reset ring buffer */
ring->wptr = 0;
@@ -4057,8 +3995,8 @@ static int gfx_v11_0_kiq_init_queue(struct amdgpu_ring *ring)
soc21_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
- if (adev->gfx.mec.mqd_backup[mqd_idx])
- memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
+ if (adev->gfx.kiq[0].mqd_backup)
+ memcpy(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(*mqd));
}
return 0;
@@ -4080,17 +4018,14 @@ static int gfx_v11_0_kcq_init_queue(struct amdgpu_ring *ring)
if (adev->gfx.mec.mqd_backup[mqd_idx])
memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
- } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */
- /* reset MQD to a clean status */
+ } else {
+ /* restore MQD to a clean status */
if (adev->gfx.mec.mqd_backup[mqd_idx])
memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd));
-
/* reset ring buffer */
ring->wptr = 0;
atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0);
amdgpu_ring_clear_ring(ring);
- } else {
- amdgpu_ring_clear_ring(ring);
}
return 0;
@@ -4101,7 +4036,7 @@ static int gfx_v11_0_kiq_resume(struct amdgpu_device *adev)
struct amdgpu_ring *ring;
int r;
- ring = &adev->gfx.kiq.ring;
+ ring = &adev->gfx.kiq[0].ring;
r = amdgpu_bo_reserve(ring->mqd_obj, false);
if (unlikely(r != 0))
@@ -4146,7 +4081,7 @@ static int gfx_v11_0_kcq_resume(struct amdgpu_device *adev)
goto done;
}
- r = amdgpu_gfx_enable_kcq(adev);
+ r = amdgpu_gfx_enable_kcq(adev, 0);
done:
return r;
}
@@ -4239,7 +4174,7 @@ static int gfx_v11_0_gfxhub_enable(struct amdgpu_device *adev)
false : true;
adev->gfxhub.funcs->set_fault_enable_default(adev, value);
- amdgpu_gmc_flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB_0, 0);
+ amdgpu_gmc_flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB(0), 0);
return 0;
}
@@ -4407,48 +4342,20 @@ static int gfx_v11_0_hw_init(void *handle)
return r;
}
-#ifndef BRING_UP_DEBUG
-static int gfx_v11_0_kiq_disable_kgq(struct amdgpu_device *adev)
-{
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
- struct amdgpu_ring *kiq_ring = &kiq->ring;
- int i, r = 0;
-
- if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
- return -EINVAL;
-
- if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size *
- adev->gfx.num_gfx_rings))
- return -ENOMEM;
-
- for (i = 0; i < adev->gfx.num_gfx_rings; i++)
- kiq->pmf->kiq_unmap_queues(kiq_ring, &adev->gfx.gfx_ring[i],
- PREEMPT_QUEUES, 0, 0);
-
- if (adev->gfx.kiq.ring.sched.ready)
- r = amdgpu_ring_test_helper(kiq_ring);
-
- return r;
-}
-#endif
-
static int gfx_v11_0_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- int r;
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
if (!adev->no_hw_access) {
-#ifndef BRING_UP_DEBUG
if (amdgpu_async_gfx_ring) {
- r = gfx_v11_0_kiq_disable_kgq(adev);
- if (r)
+ if (amdgpu_gfx_disable_kgq(adev, 0))
DRM_ERROR("KGQ disable failed\n");
}
-#endif
- if (amdgpu_gfx_disable_kcq(adev))
+
+ if (amdgpu_gfx_disable_kcq(adev, 0))
DRM_ERROR("KCQ disable failed\n");
amdgpu_mes_kiq_hw_fini(adev);
@@ -4525,7 +4432,7 @@ static int gfx_v11_0_soft_reset(void *handle)
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL, GFX_IDLE_INT_ENABLE, 0);
WREG32_SOC15(GC, 0, regCP_INT_CNTL, tmp);
- gfx_v11_0_set_safe_mode(adev);
+ gfx_v11_0_set_safe_mode(adev, 0);
for (i = 0; i < adev->gfx.mec.num_mec; ++i) {
for (j = 0; j < adev->gfx.mec.num_queue_per_pipe; j++) {
@@ -4625,7 +4532,7 @@ static int gfx_v11_0_soft_reset(void *handle)
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL, GFX_IDLE_INT_ENABLE, 1);
WREG32_SOC15(GC, 0, regCP_INT_CNTL, tmp);
- gfx_v11_0_unset_safe_mode(adev);
+ gfx_v11_0_unset_safe_mode(adev, 0);
return gfx_v11_0_cp_resume(adev);
}
@@ -4794,7 +4701,7 @@ static bool gfx_v11_0_is_rlc_enabled(struct amdgpu_device *adev)
return (REG_GET_FIELD(rlc_cntl, RLC_CNTL, RLC_ENABLE_F32)) ? true : false;
}
-static void gfx_v11_0_set_safe_mode(struct amdgpu_device *adev)
+static void gfx_v11_0_set_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
uint32_t data;
unsigned i;
@@ -4813,7 +4720,7 @@ static void gfx_v11_0_set_safe_mode(struct amdgpu_device *adev)
}
}
-static void gfx_v11_0_unset_safe_mode(struct amdgpu_device *adev)
+static void gfx_v11_0_unset_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
WREG32_SOC15(GC, 0, regRLC_SAFE_MODE, RLC_SAFE_MODE__CMD_MASK);
}
@@ -5041,7 +4948,7 @@ static void gfx_v11_0_update_coarse_grain_clock_gating(struct amdgpu_device *ade
static int gfx_v11_0_update_gfx_clock_gating(struct amdgpu_device *adev,
bool enable)
{
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
gfx_v11_0_update_coarse_grain_clock_gating(adev, enable);
@@ -5061,7 +4968,7 @@ static int gfx_v11_0_update_gfx_clock_gating(struct amdgpu_device *adev,
AMD_CG_SUPPORT_GFX_3D_CGLS))
gfx_v11_0_enable_gui_idle_interrupt(adev, enable);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return 0;
}
@@ -5129,11 +5036,11 @@ static void gfx_v11_cntl_power_gating(struct amdgpu_device *adev, bool enable)
static void gfx_v11_cntl_pg(struct amdgpu_device *adev, bool enable)
{
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
gfx_v11_cntl_power_gating(adev, enable);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static int gfx_v11_0_set_powergating_state(void *handle,
@@ -5592,6 +5499,29 @@ static void gfx_v11_0_ring_emit_cntxcntl(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, 0);
}
+static void gfx_v11_0_ring_emit_gfx_shadow(struct amdgpu_ring *ring,
+ u64 shadow_va, u64 csa_va,
+ u64 gds_va, bool init_shadow,
+ int vmid)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (!adev->gfx.cp_gfx_shadow)
+ return;
+
+ amdgpu_ring_write(ring, PACKET3(PACKET3_SET_Q_PREEMPTION_MODE, 7));
+ amdgpu_ring_write(ring, lower_32_bits(shadow_va));
+ amdgpu_ring_write(ring, upper_32_bits(shadow_va));
+ amdgpu_ring_write(ring, lower_32_bits(gds_va));
+ amdgpu_ring_write(ring, upper_32_bits(gds_va));
+ amdgpu_ring_write(ring, lower_32_bits(csa_va));
+ amdgpu_ring_write(ring, upper_32_bits(csa_va));
+ amdgpu_ring_write(ring, shadow_va ?
+ PACKET3_SET_Q_PREEMPTION_MODE_IB_VMID(vmid) : 0);
+ amdgpu_ring_write(ring, init_shadow ?
+ PACKET3_SET_Q_PREEMPTION_MODE_INIT_SHADOW_MEM : 0);
+}
+
static unsigned gfx_v11_0_ring_emit_init_cond_exec(struct amdgpu_ring *ring)
{
unsigned ret;
@@ -5623,7 +5553,7 @@ static int gfx_v11_0_ring_preempt_ib(struct amdgpu_ring *ring)
{
int i, r = 0;
struct amdgpu_device *adev = ring->adev;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
struct amdgpu_ring *kiq_ring = &kiq->ring;
unsigned long flags;
@@ -6091,7 +6021,7 @@ static int gfx_v11_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
enum amdgpu_interrupt_state state)
{
uint32_t tmp, target;
- struct amdgpu_ring *ring = &(adev->gfx.kiq.ring);
+ struct amdgpu_ring *ring = &(adev->gfx.kiq[0].ring);
target = SOC15_REG_OFFSET(GC, 0, regCP_ME1_PIPE0_INT_CNTL);
target += ring->pipe;
@@ -6182,6 +6112,7 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = {
.set_wptr = gfx_v11_0_ring_set_wptr_gfx,
.emit_frame_size = /* totally 242 maximum if 16 IBs */
5 + /* COND_EXEC */
+ 9 + /* SET_Q_PREEMPTION_MODE */
7 + /* PIPELINE_SYNC */
SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
@@ -6208,6 +6139,7 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = {
.insert_nop = amdgpu_ring_insert_nop,
.pad_ib = amdgpu_ring_generic_pad_ib,
.emit_cntxcntl = gfx_v11_0_ring_emit_cntxcntl,
+ .emit_gfx_shadow = gfx_v11_0_ring_emit_gfx_shadow,
.init_cond_exec = gfx_v11_0_ring_emit_init_cond_exec,
.patch_cond_exec = gfx_v11_0_ring_emit_patch_cond_exec,
.preempt_ib = gfx_v11_0_ring_preempt_ib,
@@ -6288,7 +6220,7 @@ static void gfx_v11_0_set_ring_funcs(struct amdgpu_device *adev)
{
int i;
- adev->gfx.kiq.ring.funcs = &gfx_v11_0_ring_funcs_kiq;
+ adev->gfx.kiq[0].ring.funcs = &gfx_v11_0_ring_funcs_kiq;
for (i = 0; i < adev->gfx.num_gfx_rings; i++)
adev->gfx.gfx_ring[i].funcs = &gfx_v11_0_ring_funcs_gfx;
@@ -6437,7 +6369,7 @@ static int gfx_v11_0_get_cu_info(struct amdgpu_device *adev,
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
mask = 1;
counter = 0;
- gfx_v11_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v11_0_select_se_sh(adev, i, j, 0xffffffff, 0);
if (i < 8 && j < 2)
gfx_v11_0_set_user_wgp_inactive_bitmap_per_sh(
adev, disable_masks[i * 2 + j]);
@@ -6469,7 +6401,7 @@ static int gfx_v11_0_get_cu_info(struct amdgpu_device *adev,
active_cu_number += counter;
}
}
- gfx_v11_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v11_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
cu_info->number = active_cu_number;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3.c
index 068b9586a223..26d6286d86c9 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3.c
@@ -84,8 +84,20 @@ static int gfx_v11_0_3_poison_consumption_handler(struct amdgpu_device *adev,
/* Workaround: when vmid and pasid are both zero, trigger gpu reset in KGD. */
if (entry && (entry->client_id == SOC21_IH_CLIENTID_GFX) &&
(entry->src_id == GFX_11_0_0__SRCID__RLC_GC_FED_INTERRUPT) &&
- !entry->vmid && !entry->pasid)
+ !entry->vmid && !entry->pasid) {
+ uint32_t rlc_status0 = 0;
+
+ rlc_status0 = RREG32_SOC15(GC, 0, regRLC_RLCS_FED_STATUS_0);
+
+ if (REG_GET_FIELD(rlc_status0, RLC_RLCS_FED_STATUS_0, SDMA0_FED_ERR) ||
+ REG_GET_FIELD(rlc_status0, RLC_RLCS_FED_STATUS_0, SDMA1_FED_ERR)) {
+ struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+
+ ras->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE2_RESET;
+ }
+
amdgpu_ras_reset_gpu(adev);
+ }
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index c41219e23151..da6caff78c22 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -1285,7 +1285,7 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
}
static void gfx_v6_0_select_se_sh(struct amdgpu_device *adev, u32 se_num,
- u32 sh_num, u32 instance)
+ u32 sh_num, u32 instance, int xcc_id)
{
u32 data;
@@ -1438,12 +1438,12 @@ static void gfx_v6_0_write_harvested_raster_configs(struct amdgpu_device *adev,
}
/* GRBM_GFX_INDEX has a different offset on SI */
- gfx_v6_0_select_se_sh(adev, se, 0xffffffff, 0xffffffff);
+ gfx_v6_0_select_se_sh(adev, se, 0xffffffff, 0xffffffff, 0);
WREG32(mmPA_SC_RASTER_CONFIG, raster_config_se);
}
/* GRBM_GFX_INDEX has a different offset on SI */
- gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
}
static void gfx_v6_0_setup_rb(struct amdgpu_device *adev)
@@ -1459,14 +1459,14 @@ static void gfx_v6_0_setup_rb(struct amdgpu_device *adev)
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++) {
- gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff, 0);
data = gfx_v6_0_get_rb_active_bitmap(adev);
active_rbs |= data <<
((i * adev->gfx.config.max_sh_per_se + j) *
rb_bitmap_width_per_sh);
}
}
- gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
adev->gfx.config.backend_enable_mask = active_rbs;
adev->gfx.config.num_rbs = hweight32(active_rbs);
@@ -1487,7 +1487,7 @@ static void gfx_v6_0_setup_rb(struct amdgpu_device *adev)
/* cache the values for userspace */
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
- gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff, 0);
adev->gfx.config.rb_config[i][j].rb_backend_disable =
RREG32(mmCC_RB_BACKEND_DISABLE);
adev->gfx.config.rb_config[i][j].user_rb_backend_disable =
@@ -1496,7 +1496,7 @@ static void gfx_v6_0_setup_rb(struct amdgpu_device *adev)
RREG32(mmPA_SC_RASTER_CONFIG);
}
}
- gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
}
@@ -1535,7 +1535,7 @@ static void gfx_v6_0_setup_spi(struct amdgpu_device *adev)
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++) {
- gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff, 0);
data = RREG32(mmSPI_STATIC_THREAD_MGMT_3);
active_cu = gfx_v6_0_get_cu_enabled(adev);
@@ -1550,7 +1550,7 @@ static void gfx_v6_0_setup_spi(struct amdgpu_device *adev)
}
}
}
- gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
}
@@ -2391,7 +2391,7 @@ static void gfx_v6_0_enable_lbpw(struct amdgpu_device *adev, bool enable)
WREG32_FIELD(RLC_LB_CNTL, LOAD_BALANCE_ENABLE, enable ? 1 : 0);
if (!enable) {
- gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
WREG32(mmSPI_LB_CU_MASK, 0x00ff);
}
}
@@ -2968,7 +2968,7 @@ static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
*(out++) = RREG32(mmSQ_IND_DATA);
}
-static void gfx_v6_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
+static void gfx_v6_0_read_wave_data(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
{
/* type 0 wave data */
dst[(*no_fields)++] = 0;
@@ -2993,7 +2993,7 @@ static void gfx_v6_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
}
-static void gfx_v6_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+static void gfx_v6_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t start,
uint32_t size, uint32_t *dst)
{
@@ -3003,7 +3003,7 @@ static void gfx_v6_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
}
static void gfx_v6_0_select_me_pipe_q(struct amdgpu_device *adev,
- u32 me, u32 pipe, u32 q, u32 vm)
+ u32 me, u32 pipe, u32 q, u32 vm, u32 xcc_id)
{
DRM_INFO("Not implemented\n");
}
@@ -3028,6 +3028,7 @@ static int gfx_v6_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ adev->gfx.xcc_mask = 1;
adev->gfx.num_gfx_rings = GFX6_NUM_GFX_RINGS;
adev->gfx.num_compute_rings = min(amdgpu_gfx_get_num_kcq(adev),
GFX6_NUM_COMPUTE_RINGS);
@@ -3073,7 +3074,7 @@ static int gfx_v6_0_sw_init(void *handle)
ring = &adev->gfx.gfx_ring[i];
ring->ring_obj = NULL;
sprintf(ring->name, "gfx");
- r = amdgpu_ring_init(adev, ring, 1024,
+ r = amdgpu_ring_init(adev, ring, 2048,
&adev->gfx.eop_irq,
AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP,
AMDGPU_RING_PRIO_DEFAULT, NULL);
@@ -3571,7 +3572,7 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev)
mask = 1;
ao_bitmap = 0;
counter = 0;
- gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff, 0);
if (i < 4 && j < 2)
gfx_v6_0_set_user_cu_inactive_bitmap(
adev, disable_masks[i * 2 + j]);
@@ -3593,7 +3594,7 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev)
}
}
- gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
cu_info->number = active_cu_number;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index 9d5c1e29b4a3..8c174c11eaee 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -1548,11 +1548,12 @@ static void gfx_v7_0_tiling_mode_table_init(struct amdgpu_device *adev)
* @sh_num: sh block to address
* @instance: Certain registers are instanced per SE or SH.
* 0xffffffff means broadcast to all SEs or SHs (CIK).
- *
+ * @xcc_id: xcc accelerated compute core id
* Select which SE, SH combinations to address.
*/
static void gfx_v7_0_select_se_sh(struct amdgpu_device *adev,
- u32 se_num, u32 sh_num, u32 instance)
+ u32 se_num, u32 sh_num, u32 instance,
+ int xcc_id)
{
u32 data;
@@ -1732,13 +1733,13 @@ gfx_v7_0_write_harvested_raster_configs(struct amdgpu_device *adev,
}
/* GRBM_GFX_INDEX has a different offset on CI+ */
- gfx_v7_0_select_se_sh(adev, se, 0xffffffff, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, se, 0xffffffff, 0xffffffff, 0);
WREG32(mmPA_SC_RASTER_CONFIG, raster_config_se);
WREG32(mmPA_SC_RASTER_CONFIG_1, raster_config_1);
}
/* GRBM_GFX_INDEX has a different offset on CI+ */
- gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
}
/**
@@ -1761,13 +1762,13 @@ static void gfx_v7_0_setup_rb(struct amdgpu_device *adev)
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++) {
- gfx_v7_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, i, j, 0xffffffff, 0);
data = gfx_v7_0_get_rb_active_bitmap(adev);
active_rbs |= data << ((i * adev->gfx.config.max_sh_per_se + j) *
rb_bitmap_width_per_sh);
}
}
- gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
adev->gfx.config.backend_enable_mask = active_rbs;
adev->gfx.config.num_rbs = hweight32(active_rbs);
@@ -1790,7 +1791,7 @@ static void gfx_v7_0_setup_rb(struct amdgpu_device *adev)
/* cache the values for userspace */
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
- gfx_v7_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, i, j, 0xffffffff, 0);
adev->gfx.config.rb_config[i][j].rb_backend_disable =
RREG32(mmCC_RB_BACKEND_DISABLE);
adev->gfx.config.rb_config[i][j].user_rb_backend_disable =
@@ -1801,7 +1802,7 @@ static void gfx_v7_0_setup_rb(struct amdgpu_device *adev)
RREG32(mmPA_SC_RASTER_CONFIG_1);
}
}
- gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
}
@@ -1911,7 +1912,7 @@ static void gfx_v7_0_constants_init(struct amdgpu_device *adev)
* making sure that the following register writes will be broadcasted
* to all the shaders
*/
- gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
/* XXX SH_MEM regs */
/* where to put LDS, scratch, GPUVM in FSA64 space */
@@ -2728,7 +2729,7 @@ static int gfx_v7_0_mec_init(struct amdgpu_device *adev)
u32 *hpd;
size_t mec_hpd_size;
- bitmap_zero(adev->gfx.mec.queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
+ bitmap_zero(adev->gfx.mec_bitmap[0].queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
/* take ownership of the relevant compute queues */
amdgpu_gfx_compute_queue_acquire(adev);
@@ -3301,7 +3302,7 @@ static void gfx_v7_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
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++) {
- gfx_v7_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, i, j, 0xffffffff, 0);
for (k = 0; k < adev->usec_timeout; k++) {
if (RREG32(mmRLC_SERDES_CU_MASTER_BUSY) == 0)
break;
@@ -3309,7 +3310,7 @@ static void gfx_v7_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
}
}
}
- gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
mask = RLC_SERDES_NONCU_MASTER_BUSY__SE_MASTER_BUSY_MASK |
@@ -3361,7 +3362,7 @@ static bool gfx_v7_0_is_rlc_enabled(struct amdgpu_device *adev)
return true;
}
-static void gfx_v7_0_set_safe_mode(struct amdgpu_device *adev)
+static void gfx_v7_0_set_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
u32 tmp, i, mask;
@@ -3383,7 +3384,7 @@ static void gfx_v7_0_set_safe_mode(struct amdgpu_device *adev)
}
}
-static void gfx_v7_0_unset_safe_mode(struct amdgpu_device *adev)
+static void gfx_v7_0_unset_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
u32 tmp;
@@ -3474,7 +3475,7 @@ static int gfx_v7_0_rlc_resume(struct amdgpu_device *adev)
WREG32(mmRLC_LB_CNTR_MAX, 0x00008000);
mutex_lock(&adev->grbm_idx_mutex);
- gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
WREG32(mmRLC_LB_INIT_CU_MASK, 0xffffffff);
WREG32(mmRLC_LB_PARAMS, 0x00600408);
WREG32(mmRLC_LB_CNTL, 0x80000004);
@@ -3530,7 +3531,7 @@ static void gfx_v7_0_enable_cgcg(struct amdgpu_device *adev, bool enable)
tmp = gfx_v7_0_halt_rlc(adev);
mutex_lock(&adev->grbm_idx_mutex);
- gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
WREG32(mmRLC_SERDES_WR_CU_MASTER_MASK, 0xffffffff);
WREG32(mmRLC_SERDES_WR_NONCU_MASTER_MASK, 0xffffffff);
tmp2 = RLC_SERDES_WR_CTRL__BPM_ADDR_MASK |
@@ -3584,7 +3585,7 @@ static void gfx_v7_0_enable_mgcg(struct amdgpu_device *adev, bool enable)
tmp = gfx_v7_0_halt_rlc(adev);
mutex_lock(&adev->grbm_idx_mutex);
- gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
WREG32(mmRLC_SERDES_WR_CU_MASTER_MASK, 0xffffffff);
WREG32(mmRLC_SERDES_WR_NONCU_MASTER_MASK, 0xffffffff);
data = RLC_SERDES_WR_CTRL__BPM_ADDR_MASK |
@@ -3635,7 +3636,7 @@ static void gfx_v7_0_enable_mgcg(struct amdgpu_device *adev, bool enable)
tmp = gfx_v7_0_halt_rlc(adev);
mutex_lock(&adev->grbm_idx_mutex);
- gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
WREG32(mmRLC_SERDES_WR_CU_MASTER_MASK, 0xffffffff);
WREG32(mmRLC_SERDES_WR_NONCU_MASTER_MASK, 0xffffffff);
data = RLC_SERDES_WR_CTRL__BPM_ADDR_MASK | RLC_SERDES_WR_CTRL__MGCG_OVERRIDE_1_MASK;
@@ -4111,7 +4112,7 @@ static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
*(out++) = RREG32(mmSQ_IND_DATA);
}
-static void gfx_v7_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
+static void gfx_v7_0_read_wave_data(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
{
/* type 0 wave data */
dst[(*no_fields)++] = 0;
@@ -4136,7 +4137,7 @@ static void gfx_v7_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
}
-static void gfx_v7_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+static void gfx_v7_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t start,
uint32_t size, uint32_t *dst)
{
@@ -4146,7 +4147,7 @@ static void gfx_v7_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
}
static void gfx_v7_0_select_me_pipe_q(struct amdgpu_device *adev,
- u32 me, u32 pipe, u32 q, u32 vm)
+ u32 me, u32 pipe, u32 q, u32 vm, u32 xcc_id)
{
cik_srbm_select(adev, me, pipe, q, vm);
}
@@ -4178,6 +4179,7 @@ static int gfx_v7_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ adev->gfx.xcc_mask = 1;
adev->gfx.num_gfx_rings = GFX7_NUM_GFX_RINGS;
adev->gfx.num_compute_rings = min(amdgpu_gfx_get_num_kcq(adev),
AMDGPU_MAX_COMPUTE_RINGS);
@@ -4456,7 +4458,8 @@ static int gfx_v7_0_sw_init(void *handle)
for (i = 0; i < adev->gfx.mec.num_mec; ++i) {
for (j = 0; j < adev->gfx.mec.num_queue_per_pipe; j++) {
for (k = 0; k < adev->gfx.mec.num_pipe_per_mec; k++) {
- if (!amdgpu_gfx_is_mec_queue_enabled(adev, i, k, j))
+ if (!amdgpu_gfx_is_mec_queue_enabled(adev, 0, i,
+ k, j))
continue;
r = gfx_v7_0_compute_ring_init(adev,
@@ -5114,7 +5117,7 @@ static void gfx_v7_0_get_cu_info(struct amdgpu_device *adev)
mask = 1;
ao_bitmap = 0;
counter = 0;
- gfx_v7_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, i, j, 0xffffffff, 0);
if (i < 4 && j < 2)
gfx_v7_0_set_user_cu_inactive_bitmap(
adev, disable_masks[i * 2 + j]);
@@ -5135,7 +5138,7 @@ static void gfx_v7_0_get_cu_info(struct amdgpu_device *adev)
cu_info->ao_cu_bitmap[i][j] = ao_bitmap;
}
}
- gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
cu_info->number = active_cu_number;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index b1f2684d854a..51c1745c8369 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -1304,7 +1304,7 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
u32 *hpd;
size_t mec_hpd_size;
- bitmap_zero(adev->gfx.mec.queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
+ bitmap_zero(adev->gfx.mec_bitmap[0].queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
/* take ownership of the relevant compute queues */
amdgpu_gfx_compute_queue_acquire(adev);
@@ -2001,7 +2001,8 @@ static int gfx_v8_0_sw_init(void *handle)
for (i = 0; i < adev->gfx.mec.num_mec; ++i) {
for (j = 0; j < adev->gfx.mec.num_queue_per_pipe; j++) {
for (k = 0; k < adev->gfx.mec.num_pipe_per_mec; k++) {
- if (!amdgpu_gfx_is_mec_queue_enabled(adev, i, k, j))
+ if (!amdgpu_gfx_is_mec_queue_enabled(adev, 0, i,
+ k, j))
continue;
r = gfx_v8_0_compute_ring_init(adev,
@@ -2015,19 +2016,19 @@ static int gfx_v8_0_sw_init(void *handle)
}
}
- r = amdgpu_gfx_kiq_init(adev, GFX8_MEC_HPD_SIZE);
+ r = amdgpu_gfx_kiq_init(adev, GFX8_MEC_HPD_SIZE, 0);
if (r) {
DRM_ERROR("Failed to init KIQ BOs!\n");
return r;
}
- kiq = &adev->gfx.kiq;
- r = amdgpu_gfx_kiq_init_ring(adev, &kiq->ring, &kiq->irq);
+ kiq = &adev->gfx.kiq[0];
+ r = amdgpu_gfx_kiq_init_ring(adev, &kiq->ring, &kiq->irq, 0);
if (r)
return r;
/* create MQD for all compute queues as well as KIQ for SRIOV case */
- r = amdgpu_gfx_mqd_sw_init(adev, sizeof(struct vi_mqd_allocation));
+ r = amdgpu_gfx_mqd_sw_init(adev, sizeof(struct vi_mqd_allocation), 0);
if (r)
return r;
@@ -2050,9 +2051,9 @@ static int gfx_v8_0_sw_fini(void *handle)
for (i = 0; i < adev->gfx.num_compute_rings; i++)
amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
- amdgpu_gfx_mqd_sw_fini(adev);
- amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq.ring);
- amdgpu_gfx_kiq_fini(adev);
+ amdgpu_gfx_mqd_sw_fini(adev, 0);
+ amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq[0].ring);
+ amdgpu_gfx_kiq_fini(adev, 0);
gfx_v8_0_mec_fini(adev);
amdgpu_gfx_rlc_fini(adev);
@@ -3394,7 +3395,8 @@ static void gfx_v8_0_tiling_mode_table_init(struct amdgpu_device *adev)
}
static void gfx_v8_0_select_se_sh(struct amdgpu_device *adev,
- u32 se_num, u32 sh_num, u32 instance)
+ u32 se_num, u32 sh_num, u32 instance,
+ int xcc_id)
{
u32 data;
@@ -3417,7 +3419,7 @@ static void gfx_v8_0_select_se_sh(struct amdgpu_device *adev,
}
static void gfx_v8_0_select_me_pipe_q(struct amdgpu_device *adev,
- u32 me, u32 pipe, u32 q, u32 vm)
+ u32 me, u32 pipe, u32 q, u32 vm, u32 xcc_id)
{
vi_srbm_select(adev, me, pipe, q, vm);
}
@@ -3578,13 +3580,13 @@ gfx_v8_0_write_harvested_raster_configs(struct amdgpu_device *adev,
}
/* GRBM_GFX_INDEX has a different offset on VI */
- gfx_v8_0_select_se_sh(adev, se, 0xffffffff, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, se, 0xffffffff, 0xffffffff, 0);
WREG32(mmPA_SC_RASTER_CONFIG, raster_config_se);
WREG32(mmPA_SC_RASTER_CONFIG_1, raster_config_1);
}
/* GRBM_GFX_INDEX has a different offset on VI */
- gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
}
static void gfx_v8_0_setup_rb(struct amdgpu_device *adev)
@@ -3600,13 +3602,13 @@ static void gfx_v8_0_setup_rb(struct amdgpu_device *adev)
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++) {
- gfx_v8_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, i, j, 0xffffffff, 0);
data = gfx_v8_0_get_rb_active_bitmap(adev);
active_rbs |= data << ((i * adev->gfx.config.max_sh_per_se + j) *
rb_bitmap_width_per_sh);
}
}
- gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
adev->gfx.config.backend_enable_mask = active_rbs;
adev->gfx.config.num_rbs = hweight32(active_rbs);
@@ -3629,7 +3631,7 @@ static void gfx_v8_0_setup_rb(struct amdgpu_device *adev)
/* cache the values for userspace */
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
- gfx_v8_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, i, j, 0xffffffff, 0);
adev->gfx.config.rb_config[i][j].rb_backend_disable =
RREG32(mmCC_RB_BACKEND_DISABLE);
adev->gfx.config.rb_config[i][j].user_rb_backend_disable =
@@ -3640,7 +3642,7 @@ static void gfx_v8_0_setup_rb(struct amdgpu_device *adev)
RREG32(mmPA_SC_RASTER_CONFIG_1);
}
}
- gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
}
@@ -3787,7 +3789,7 @@ static void gfx_v8_0_constants_init(struct amdgpu_device *adev)
* making sure that the following register writes will be broadcasted
* to all the shaders
*/
- gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
WREG32(mmPA_SC_FIFO_SIZE,
(adev->gfx.config.sc_prim_fifo_size_frontend <<
@@ -3818,7 +3820,7 @@ static void gfx_v8_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
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++) {
- gfx_v8_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, i, j, 0xffffffff, 0);
for (k = 0; k < adev->usec_timeout; k++) {
if (RREG32(mmRLC_SERDES_CU_MASTER_BUSY) == 0)
break;
@@ -3826,7 +3828,7 @@ static void gfx_v8_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
}
if (k == adev->usec_timeout) {
gfx_v8_0_select_se_sh(adev, 0xffffffff,
- 0xffffffff, 0xffffffff);
+ 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
DRM_INFO("Timeout wait for RLC serdes %u,%u\n",
i, j);
@@ -3834,7 +3836,7 @@ static void gfx_v8_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
}
}
}
- gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
mask = RLC_SERDES_NONCU_MASTER_BUSY__SE_MASTER_BUSY_MASK |
@@ -4281,7 +4283,6 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
/* start the ring */
amdgpu_ring_clear_ring(ring);
gfx_v8_0_cp_gfx_start(adev);
- ring->sched.ready = true;
return 0;
}
@@ -4292,7 +4293,7 @@ static void gfx_v8_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
WREG32(mmCP_MEC_CNTL, 0);
} else {
WREG32(mmCP_MEC_CNTL, (CP_MEC_CNTL__MEC_ME1_HALT_MASK | CP_MEC_CNTL__MEC_ME2_HALT_MASK));
- adev->gfx.kiq.ring.sched.ready = false;
+ adev->gfx.kiq[0].ring.sched.ready = false;
}
udelay(50);
}
@@ -4314,12 +4315,12 @@ static void gfx_v8_0_kiq_setting(struct amdgpu_ring *ring)
static int gfx_v8_0_kiq_kcq_enable(struct amdgpu_device *adev)
{
- struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
+ struct amdgpu_ring *kiq_ring = &adev->gfx.kiq[0].ring;
uint64_t queue_mask = 0;
int r, i;
for (i = 0; i < AMDGPU_MAX_COMPUTE_QUEUES; ++i) {
- if (!test_bit(i, adev->gfx.mec.queue_bitmap))
+ if (!test_bit(i, adev->gfx.mec_bitmap[0].queue_bitmap))
continue;
/* This situation may be hit in the future if a new HW
@@ -4595,14 +4596,13 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
struct vi_mqd *mqd = ring->mqd_ptr;
- int mqd_idx = AMDGPU_MAX_COMPUTE_RINGS;
gfx_v8_0_kiq_setting(ring);
if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */
/* reset MQD to a clean status */
- if (adev->gfx.mec.mqd_backup[mqd_idx])
- memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation));
+ if (adev->gfx.kiq[0].mqd_backup)
+ memcpy(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(struct vi_mqd_allocation));
/* reset ring buffer */
ring->wptr = 0;
@@ -4625,8 +4625,8 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring)
vi_srbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
- if (adev->gfx.mec.mqd_backup[mqd_idx])
- memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct vi_mqd_allocation));
+ if (adev->gfx.kiq[0].mqd_backup)
+ memcpy(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(struct vi_mqd_allocation));
}
return 0;
@@ -4650,15 +4650,13 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring)
if (adev->gfx.mec.mqd_backup[mqd_idx])
memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct vi_mqd_allocation));
- } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */
- /* reset MQD to a clean status */
+ } else {
+ /* restore MQD to a clean status */
if (adev->gfx.mec.mqd_backup[mqd_idx])
memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation));
/* reset ring buffer */
ring->wptr = 0;
amdgpu_ring_clear_ring(ring);
- } else {
- amdgpu_ring_clear_ring(ring);
}
return 0;
}
@@ -4678,21 +4676,22 @@ static int gfx_v8_0_kiq_resume(struct amdgpu_device *adev)
struct amdgpu_ring *ring;
int r;
- ring = &adev->gfx.kiq.ring;
+ ring = &adev->gfx.kiq[0].ring;
r = amdgpu_bo_reserve(ring->mqd_obj, false);
if (unlikely(r != 0))
return r;
r = amdgpu_bo_kmap(ring->mqd_obj, &ring->mqd_ptr);
- if (unlikely(r != 0))
+ if (unlikely(r != 0)) {
+ amdgpu_bo_unreserve(ring->mqd_obj);
return r;
+ }
gfx_v8_0_kiq_init_queue(ring);
amdgpu_bo_kunmap(ring->mqd_obj);
ring->mqd_ptr = NULL;
amdgpu_bo_unreserve(ring->mqd_obj);
- ring->sched.ready = true;
return 0;
}
@@ -4741,7 +4740,7 @@ static int gfx_v8_0_cp_test_all_rings(struct amdgpu_device *adev)
if (r)
return r;
- ring = &adev->gfx.kiq.ring;
+ ring = &adev->gfx.kiq[0].ring;
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
@@ -4808,7 +4807,7 @@ static int gfx_v8_0_hw_init(void *handle)
static int gfx_v8_0_kcq_disable(struct amdgpu_device *adev)
{
int r, i;
- struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
+ struct amdgpu_ring *kiq_ring = &adev->gfx.kiq[0].ring;
r = amdgpu_ring_alloc(kiq_ring, 6 * adev->gfx.num_compute_rings);
if (r)
@@ -4902,7 +4901,7 @@ static int gfx_v8_0_hw_fini(void *handle)
pr_debug("For SRIOV client, shouldn't do anything.\n");
return 0;
}
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
if (!gfx_v8_0_wait_for_idle(adev))
gfx_v8_0_cp_enable(adev, false);
else
@@ -4911,7 +4910,7 @@ static int gfx_v8_0_hw_fini(void *handle)
adev->gfx.rlc.funcs->stop(adev);
else
pr_err("rlc is busy, skip halt rlc\n");
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return 0;
}
@@ -5216,7 +5215,7 @@ static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
*(out++) = RREG32(mmSQ_IND_DATA);
}
-static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
+static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
{
/* type 0 wave data */
dst[(*no_fields)++] = 0;
@@ -5241,7 +5240,7 @@ static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
}
-static void gfx_v8_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+static void gfx_v8_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t start,
uint32_t size, uint32_t *dst)
{
@@ -5263,6 +5262,7 @@ static int gfx_v8_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ adev->gfx.xcc_mask = 1;
adev->gfx.num_gfx_rings = GFX8_NUM_GFX_RINGS;
adev->gfx.num_compute_rings = min(amdgpu_gfx_get_num_kcq(adev),
AMDGPU_MAX_COMPUTE_RINGS);
@@ -5376,7 +5376,7 @@ static int gfx_v8_0_set_powergating_state(void *handle,
AMD_PG_SUPPORT_RLC_SMU_HS |
AMD_PG_SUPPORT_CP |
AMD_PG_SUPPORT_GFX_DMG))
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
switch (adev->asic_type) {
case CHIP_CARRIZO:
case CHIP_STONEY:
@@ -5430,7 +5430,7 @@ static int gfx_v8_0_set_powergating_state(void *handle,
AMD_PG_SUPPORT_RLC_SMU_HS |
AMD_PG_SUPPORT_CP |
AMD_PG_SUPPORT_GFX_DMG))
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return 0;
}
@@ -5481,7 +5481,7 @@ static void gfx_v8_0_send_serdes_cmd(struct amdgpu_device *adev,
{
uint32_t data;
- gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
WREG32(mmRLC_SERDES_WR_CU_MASTER_MASK, 0xffffffff);
WREG32(mmRLC_SERDES_WR_NONCU_MASTER_MASK, 0xffffffff);
@@ -5535,7 +5535,7 @@ static bool gfx_v8_0_is_rlc_enabled(struct amdgpu_device *adev)
return true;
}
-static void gfx_v8_0_set_safe_mode(struct amdgpu_device *adev)
+static void gfx_v8_0_set_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
uint32_t data;
unsigned i;
@@ -5562,7 +5562,7 @@ static void gfx_v8_0_set_safe_mode(struct amdgpu_device *adev)
}
}
-static void gfx_v8_0_unset_safe_mode(struct amdgpu_device *adev)
+static void gfx_v8_0_unset_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
uint32_t data;
unsigned i;
@@ -5621,7 +5621,7 @@ static void gfx_v8_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
{
uint32_t temp, data;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
/* It is disabled by HW by default */
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
@@ -5717,7 +5717,7 @@ static void gfx_v8_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
gfx_v8_0_wait_for_rlc_serdes(adev);
}
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static void gfx_v8_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev,
@@ -5727,7 +5727,7 @@ static void gfx_v8_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
temp = data = RREG32(mmRLC_CGCG_CGLS_CTRL);
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
temp1 = data1 = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
@@ -5810,7 +5810,7 @@ static void gfx_v8_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
gfx_v8_0_wait_for_rlc_serdes(adev);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static int gfx_v8_0_update_gfx_clock_gating(struct amdgpu_device *adev,
bool enable)
@@ -6723,11 +6723,11 @@ static void gfx_v8_0_parse_sq_irq(struct amdgpu_device *adev, unsigned ih_data,
*/
if (from_wq) {
mutex_lock(&adev->grbm_idx_mutex);
- gfx_v8_0_select_se_sh(adev, se_id, sh_id, cu_id);
+ gfx_v8_0_select_se_sh(adev, se_id, sh_id, cu_id, 0);
sq_edc_source = REG_GET_FIELD(RREG32(mmSQ_EDC_INFO), SQ_EDC_INFO, SOURCE);
- gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
}
@@ -7001,7 +7001,7 @@ static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev)
{
int i;
- adev->gfx.kiq.ring.funcs = &gfx_v8_0_ring_funcs_kiq;
+ adev->gfx.kiq[0].ring.funcs = &gfx_v8_0_ring_funcs_kiq;
for (i = 0; i < adev->gfx.num_gfx_rings; i++)
adev->gfx.gfx_ring[i].funcs = &gfx_v8_0_ring_funcs_gfx;
@@ -7116,7 +7116,7 @@ static void gfx_v8_0_get_cu_info(struct amdgpu_device *adev)
mask = 1;
ao_bitmap = 0;
counter = 0;
- gfx_v8_0_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, i, j, 0xffffffff, 0);
if (i < 4 && j < 2)
gfx_v8_0_set_user_cu_inactive_bitmap(
adev, disable_masks[i * 2 + j]);
@@ -7137,7 +7137,7 @@ static void gfx_v8_0_get_cu_info(struct amdgpu_device *adev)
cu_info->ao_cu_bitmap[i][j] = ao_bitmap;
}
}
- gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
cu_info->number = active_cu_number;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index a674c8a58dc2..65577eca58f1 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -760,7 +760,7 @@ static u64 gfx_v9_0_ring_get_rptr_compute(struct amdgpu_ring *ring);
static void gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
void *ras_error_status);
static int gfx_v9_0_ras_error_inject(struct amdgpu_device *adev,
- void *inject_if);
+ void *inject_if, uint32_t instance_mask);
static void gfx_v9_0_reset_ras_error_count(struct amdgpu_device *adev);
static void gfx_v9_0_kiq_set_resources(struct amdgpu_ring *kiq_ring,
@@ -888,7 +888,7 @@ static const struct kiq_pm4_funcs gfx_v9_0_kiq_pm4_funcs = {
static void gfx_v9_0_set_kiq_pm4_funcs(struct amdgpu_device *adev)
{
- adev->gfx.kiq.pmf = &gfx_v9_0_kiq_pm4_funcs;
+ adev->gfx.kiq[0].pmf = &gfx_v9_0_kiq_pm4_funcs;
}
static void gfx_v9_0_init_golden_registers(struct amdgpu_device *adev)
@@ -1494,7 +1494,7 @@ static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev)
mask = 1;
cu_bitmap = 0;
counter = 0;
- amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff);
+ 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) {
@@ -1513,7 +1513,7 @@ static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev)
cu_info->ao_cu_bitmap[i][j] = cu_bitmap;
}
}
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
}
@@ -1535,7 +1535,7 @@ static void gfx_v9_0_init_lbpw(struct amdgpu_device *adev)
mutex_lock(&adev->grbm_idx_mutex);
/* set mmRLC_LB_INIT_CU_MASK thru broadcast mode to enable all SE/SH*/
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
WREG32_SOC15(GC, 0, mmRLC_LB_INIT_CU_MASK, 0xffffffff);
/* set mmRLC_LB_PARAMS = 0x003F_1006 */
@@ -1584,7 +1584,7 @@ static void gfx_v9_4_init_lbpw(struct amdgpu_device *adev)
mutex_lock(&adev->grbm_idx_mutex);
/* set mmRLC_LB_INIT_CU_MASK thru broadcast mode to enable all SE/SH*/
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
WREG32_SOC15(GC, 0, mmRLC_LB_INIT_CU_MASK, 0xffffffff);
/* set mmRLC_LB_PARAMS = 0x003F_1006 */
@@ -1703,7 +1703,7 @@ static int gfx_v9_0_mec_init(struct amdgpu_device *adev)
const struct gfx_firmware_header_v1_0 *mec_hdr;
- bitmap_zero(adev->gfx.mec.queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
+ bitmap_zero(adev->gfx.mec_bitmap[0].queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
/* take ownership of the relevant compute queues */
amdgpu_gfx_compute_queue_acquire(adev);
@@ -1778,7 +1778,7 @@ static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
*(out++) = RREG32_SOC15(GC, 0, mmSQ_IND_DATA);
}
-static void gfx_v9_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
+static void gfx_v9_0_read_wave_data(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
{
/* type 1 wave data */
dst[(*no_fields)++] = 1;
@@ -1799,7 +1799,7 @@ static void gfx_v9_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
}
-static void gfx_v9_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+static void gfx_v9_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t start,
uint32_t size, uint32_t *dst)
{
@@ -1808,7 +1808,7 @@ static void gfx_v9_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
start + SQIND_WAVE_SGPRS_OFFSET, size, dst);
}
-static void gfx_v9_0_read_wave_vgprs(struct amdgpu_device *adev, uint32_t simd,
+static void gfx_v9_0_read_wave_vgprs(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t thread,
uint32_t start, uint32_t size,
uint32_t *dst)
@@ -1819,9 +1819,9 @@ static void gfx_v9_0_read_wave_vgprs(struct amdgpu_device *adev, uint32_t simd,
}
static void gfx_v9_0_select_me_pipe_q(struct amdgpu_device *adev,
- u32 me, u32 pipe, u32 q, u32 vm)
+ u32 me, u32 pipe, u32 q, u32 vm, u32 xcc_id)
{
- soc15_grbm_select(adev, me, pipe, q, vm);
+ soc15_grbm_select(adev, me, pipe, q, vm, 0);
}
static const struct amdgpu_gfx_funcs gfx_v9_0_gfx_funcs = {
@@ -1995,7 +1995,7 @@ static int gfx_v9_0_compute_ring_init(struct amdgpu_device *adev, int ring_id,
ring->doorbell_index = (adev->doorbell_index.mec_ring0 + ring_id) << 1;
ring->eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr
+ (ring_id * GFX9_MEC_HPD_SIZE);
- ring->vm_hub = AMDGPU_GFXHUB_0;
+ ring->vm_hub = AMDGPU_GFXHUB(0);
sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue);
irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP
@@ -2095,7 +2095,7 @@ static int gfx_v9_0_sw_init(void *handle)
/* disable scheduler on the real ring */
ring->no_scheduler = true;
- ring->vm_hub = AMDGPU_GFXHUB_0;
+ ring->vm_hub = AMDGPU_GFXHUB(0);
r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq,
AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP,
AMDGPU_RING_PRIO_DEFAULT, NULL);
@@ -2113,7 +2113,7 @@ static int gfx_v9_0_sw_init(void *handle)
ring->doorbell_index = adev->doorbell_index.gfx_ring0 << 1;
ring->is_sw_ring = true;
hw_prio = amdgpu_sw_ring_priority(i);
- ring->vm_hub = AMDGPU_GFXHUB_0;
+ ring->vm_hub = AMDGPU_GFXHUB(0);
r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq,
AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP, hw_prio,
NULL);
@@ -2144,7 +2144,8 @@ static int gfx_v9_0_sw_init(void *handle)
for (i = 0; i < adev->gfx.mec.num_mec; ++i) {
for (j = 0; j < adev->gfx.mec.num_queue_per_pipe; j++) {
for (k = 0; k < adev->gfx.mec.num_pipe_per_mec; k++) {
- if (!amdgpu_gfx_is_mec_queue_enabled(adev, i, k, j))
+ if (!amdgpu_gfx_is_mec_queue_enabled(adev, 0, i,
+ k, j))
continue;
r = gfx_v9_0_compute_ring_init(adev,
@@ -2158,19 +2159,19 @@ static int gfx_v9_0_sw_init(void *handle)
}
}
- r = amdgpu_gfx_kiq_init(adev, GFX9_MEC_HPD_SIZE);
+ r = amdgpu_gfx_kiq_init(adev, GFX9_MEC_HPD_SIZE, 0);
if (r) {
DRM_ERROR("Failed to init KIQ BOs!\n");
return r;
}
- kiq = &adev->gfx.kiq;
- r = amdgpu_gfx_kiq_init_ring(adev, &kiq->ring, &kiq->irq);
+ kiq = &adev->gfx.kiq[0];
+ r = amdgpu_gfx_kiq_init_ring(adev, &kiq->ring, &kiq->irq, 0);
if (r)
return r;
/* create MQD for all compute queues as wel as KIQ for SRIOV case */
- r = amdgpu_gfx_mqd_sw_init(adev, sizeof(struct v9_mqd_allocation));
+ r = amdgpu_gfx_mqd_sw_init(adev, sizeof(struct v9_mqd_allocation), 0);
if (r)
return r;
@@ -2205,9 +2206,9 @@ static int gfx_v9_0_sw_fini(void *handle)
for (i = 0; i < adev->gfx.num_compute_rings; i++)
amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
- amdgpu_gfx_mqd_sw_fini(adev);
- amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq.ring);
- amdgpu_gfx_kiq_fini(adev);
+ amdgpu_gfx_mqd_sw_fini(adev, 0);
+ amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq[0].ring);
+ amdgpu_gfx_kiq_fini(adev, 0);
gfx_v9_0_mec_fini(adev);
amdgpu_bo_free_kernel(&adev->gfx.rlc.clear_state_obj,
@@ -2230,7 +2231,7 @@ static void gfx_v9_0_tiling_mode_table_init(struct amdgpu_device *adev)
}
void gfx_v9_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num,
- u32 instance)
+ u32 instance, int xcc_id)
{
u32 data;
@@ -2279,19 +2280,42 @@ static void gfx_v9_0_setup_rb(struct amdgpu_device *adev)
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++) {
- amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff, 0);
data = gfx_v9_0_get_rb_active_bitmap(adev);
active_rbs |= data << ((i * adev->gfx.config.max_sh_per_se + j) *
rb_bitmap_width_per_sh);
}
}
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
adev->gfx.config.backend_enable_mask = active_rbs;
adev->gfx.config.num_rbs = hweight32(active_rbs);
}
+static void gfx_v9_0_debug_trap_config_init(struct amdgpu_device *adev,
+ uint32_t first_vmid,
+ uint32_t last_vmid)
+{
+ uint32_t data;
+ uint32_t trap_config_vmid_mask = 0;
+ int i;
+
+ /* Calculate trap config vmid mask */
+ for (i = first_vmid; i < last_vmid; i++)
+ trap_config_vmid_mask |= (1 << i);
+
+ data = REG_SET_FIELD(0, SPI_GDBG_TRAP_CONFIG,
+ VMID_SEL, trap_config_vmid_mask);
+ data = REG_SET_FIELD(data, SPI_GDBG_TRAP_CONFIG,
+ TRAP_EN, 1);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_CONFIG), data);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
+
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_DATA0), 0);
+ WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_DATA1), 0);
+}
+
#define DEFAULT_SH_MEM_BASES (0x6000)
static void gfx_v9_0_init_compute_vmid(struct amdgpu_device *adev)
{
@@ -2313,12 +2337,12 @@ static void gfx_v9_0_init_compute_vmid(struct amdgpu_device *adev)
mutex_lock(&adev->srbm_mutex);
for (i = adev->vm_manager.first_kfd_vmid; i < AMDGPU_NUM_VMID; i++) {
- soc15_grbm_select(adev, 0, 0, 0, i);
+ soc15_grbm_select(adev, 0, 0, 0, i, 0);
/* CP and shaders */
WREG32_SOC15_RLC(GC, 0, mmSH_MEM_CONFIG, sh_mem_config);
WREG32_SOC15_RLC(GC, 0, mmSH_MEM_BASES, sh_mem_bases);
}
- soc15_grbm_select(adev, 0, 0, 0, 0);
+ soc15_grbm_select(adev, 0, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
/* Initialize all compute VMIDs to have no GDS, GWS, or OA
@@ -2356,8 +2380,8 @@ static void gfx_v9_0_init_sq_config(struct amdgpu_device *adev)
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 4, 1):
tmp = RREG32_SOC15(GC, 0, mmSQ_CONFIG);
- tmp = REG_SET_FIELD(tmp, SQ_CONFIG,
- DISABLE_BARRIER_WAITCNT, 1);
+ tmp = REG_SET_FIELD(tmp, SQ_CONFIG, DISABLE_BARRIER_WAITCNT,
+ !READ_ONCE(adev->barrier_has_auto_waitcnt));
WREG32_SOC15(GC, 0, mmSQ_CONFIG, tmp);
break;
default:
@@ -2382,8 +2406,8 @@ static void gfx_v9_0_constants_init(struct amdgpu_device *adev)
/* XXX SH_MEM regs */
/* where to put LDS, scratch, GPUVM in FSA64 space */
mutex_lock(&adev->srbm_mutex);
- for (i = 0; i < adev->vm_manager.id_mgr[AMDGPU_GFXHUB_0].num_ids; i++) {
- soc15_grbm_select(adev, 0, 0, 0, i);
+ for (i = 0; i < adev->vm_manager.id_mgr[AMDGPU_GFXHUB(0)].num_ids; i++) {
+ soc15_grbm_select(adev, 0, 0, 0, i, 0);
/* CP and shaders */
if (i == 0) {
tmp = REG_SET_FIELD(0, SH_MEM_CONFIG, ALIGNMENT_MODE,
@@ -2405,7 +2429,7 @@ static void gfx_v9_0_constants_init(struct amdgpu_device *adev)
WREG32_SOC15_RLC(GC, 0, mmSH_MEM_BASES, tmp);
}
}
- soc15_grbm_select(adev, 0, 0, 0, 0);
+ soc15_grbm_select(adev, 0, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
@@ -2422,7 +2446,7 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
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++) {
- amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff, 0);
for (k = 0; k < adev->usec_timeout; k++) {
if (RREG32_SOC15(GC, 0, mmRLC_SERDES_CU_MASTER_BUSY) == 0)
break;
@@ -2430,7 +2454,7 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
}
if (k == adev->usec_timeout) {
amdgpu_gfx_select_se_sh(adev, 0xffffffff,
- 0xffffffff, 0xffffffff);
+ 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
DRM_INFO("Timeout wait for RLC serdes %u,%u\n",
i, j);
@@ -2438,7 +2462,7 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
}
}
}
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
mask = RLC_SERDES_NONCU_MASTER_BUSY__SE_MASTER_BUSY_MASK |
@@ -3133,7 +3157,6 @@ static int gfx_v9_0_cp_gfx_resume(struct amdgpu_device *adev)
/* start the ring */
gfx_v9_0_cp_gfx_start(adev);
- ring->sched.ready = true;
return 0;
}
@@ -3145,7 +3168,7 @@ static void gfx_v9_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
} else {
WREG32_SOC15_RLC(GC, 0, mmCP_MEC_CNTL,
(CP_MEC_CNTL__MEC_ME1_HALT_MASK | CP_MEC_CNTL__MEC_ME2_HALT_MASK));
- adev->gfx.kiq.ring.sched.ready = false;
+ adev->gfx.kiq[0].ring.sched.ready = false;
}
udelay(50);
}
@@ -3509,7 +3532,6 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
struct v9_mqd *mqd = ring->mqd_ptr;
- int mqd_idx = AMDGPU_MAX_COMPUTE_RINGS;
struct v9_mqd *tmp_mqd;
gfx_v9_0_kiq_setting(ring);
@@ -3519,20 +3541,20 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring)
* driver need to re-init the mqd.
* check mqd->cp_hqd_pq_control since this value should not be 0
*/
- tmp_mqd = (struct v9_mqd *)adev->gfx.mec.mqd_backup[mqd_idx];
+ tmp_mqd = (struct v9_mqd *)adev->gfx.kiq[0].mqd_backup;
if (amdgpu_in_reset(adev) && tmp_mqd->cp_hqd_pq_control){
/* for GPU_RESET case , reset MQD to a clean status */
- if (adev->gfx.mec.mqd_backup[mqd_idx])
- memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation));
+ if (adev->gfx.kiq[0].mqd_backup)
+ memcpy(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(struct v9_mqd_allocation));
/* reset ring buffer */
ring->wptr = 0;
amdgpu_ring_clear_ring(ring);
mutex_lock(&adev->srbm_mutex);
- soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
+ soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, 0);
gfx_v9_0_kiq_init_register(ring);
- soc15_grbm_select(adev, 0, 0, 0, 0);
+ soc15_grbm_select(adev, 0, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
} else {
memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation));
@@ -3541,14 +3563,14 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring)
if (amdgpu_sriov_vf(adev) && adev->in_suspend)
amdgpu_ring_clear_ring(ring);
mutex_lock(&adev->srbm_mutex);
- soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
+ soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, 0);
gfx_v9_0_mqd_init(ring);
gfx_v9_0_kiq_init_register(ring);
- soc15_grbm_select(adev, 0, 0, 0, 0);
+ soc15_grbm_select(adev, 0, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
- if (adev->gfx.mec.mqd_backup[mqd_idx])
- memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct v9_mqd_allocation));
+ if (adev->gfx.kiq[0].mqd_backup)
+ memcpy(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(struct v9_mqd_allocation));
}
return 0;
@@ -3572,24 +3594,21 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring)
((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF;
((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF;
mutex_lock(&adev->srbm_mutex);
- soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
+ soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, 0);
gfx_v9_0_mqd_init(ring);
- soc15_grbm_select(adev, 0, 0, 0, 0);
+ soc15_grbm_select(adev, 0, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.mec.mqd_backup[mqd_idx])
memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct v9_mqd_allocation));
- } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */
- /* reset MQD to a clean status */
+ } else {
+ /* restore MQD to a clean status */
if (adev->gfx.mec.mqd_backup[mqd_idx])
memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation));
-
/* reset ring buffer */
ring->wptr = 0;
atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0);
amdgpu_ring_clear_ring(ring);
- } else {
- amdgpu_ring_clear_ring(ring);
}
return 0;
@@ -3600,7 +3619,7 @@ static int gfx_v9_0_kiq_resume(struct amdgpu_device *adev)
struct amdgpu_ring *ring;
int r;
- ring = &adev->gfx.kiq.ring;
+ ring = &adev->gfx.kiq[0].ring;
r = amdgpu_bo_reserve(ring->mqd_obj, false);
if (unlikely(r != 0))
@@ -3616,7 +3635,6 @@ static int gfx_v9_0_kiq_resume(struct amdgpu_device *adev)
amdgpu_bo_kunmap(ring->mqd_obj);
ring->mqd_ptr = NULL;
amdgpu_bo_unreserve(ring->mqd_obj);
- ring->sched.ready = true;
return 0;
}
@@ -3644,7 +3662,7 @@ static int gfx_v9_0_kcq_resume(struct amdgpu_device *adev)
goto done;
}
- r = amdgpu_gfx_enable_kcq(adev);
+ r = amdgpu_gfx_enable_kcq(adev, 0);
done:
return r;
}
@@ -3764,7 +3782,7 @@ static int gfx_v9_0_hw_fini(void *handle)
/* DF freeze and kcq disable will fail */
if (!amdgpu_ras_intr_triggered())
/* disable KCQ to avoid CPC touch memory not valid anymore */
- amdgpu_gfx_disable_kcq(adev);
+ amdgpu_gfx_disable_kcq(adev, 0);
if (amdgpu_sriov_vf(adev)) {
gfx_v9_0_cp_gfx_enable(adev, false);
@@ -3782,11 +3800,11 @@ static int gfx_v9_0_hw_fini(void *handle)
*/
if (!amdgpu_in_reset(adev) && !adev->in_suspend) {
mutex_lock(&adev->srbm_mutex);
- soc15_grbm_select(adev, adev->gfx.kiq.ring.me,
- adev->gfx.kiq.ring.pipe,
- adev->gfx.kiq.ring.queue, 0);
- gfx_v9_0_kiq_fini_register(&adev->gfx.kiq.ring);
- soc15_grbm_select(adev, 0, 0, 0, 0);
+ soc15_grbm_select(adev, adev->gfx.kiq[0].ring.me,
+ adev->gfx.kiq[0].ring.pipe,
+ adev->gfx.kiq[0].ring.queue, 0, 0);
+ gfx_v9_0_kiq_fini_register(&adev->gfx.kiq[0].ring);
+ soc15_grbm_select(adev, 0, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
}
@@ -3906,7 +3924,7 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev)
unsigned long flags;
uint32_t seq, reg_val_offs = 0;
uint64_t value = 0;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
struct amdgpu_ring *ring = &kiq->ring;
BUG_ON(!ring->funcs->emit_rreg);
@@ -4506,6 +4524,7 @@ static int gfx_v9_0_early_init(void *handle)
adev->gfx.num_gfx_rings = 0;
else
adev->gfx.num_gfx_rings = GFX9_NUM_GFX_RINGS;
+ adev->gfx.xcc_mask = 1;
adev->gfx.num_compute_rings = min(amdgpu_gfx_get_num_kcq(adev),
AMDGPU_MAX_COMPUTE_RINGS);
gfx_v9_0_set_kiq_pm4_funcs(adev);
@@ -4571,6 +4590,13 @@ static int gfx_v9_0_late_init(void *handle)
if (r)
return r;
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2))
+ gfx_v9_4_2_debug_trap_config_init(adev,
+ adev->vm_manager.first_kfd_vmid, AMDGPU_NUM_VMID);
+ else
+ gfx_v9_0_debug_trap_config_init(adev,
+ adev->vm_manager.first_kfd_vmid, AMDGPU_NUM_VMID);
+
return 0;
}
@@ -4586,7 +4612,7 @@ static bool gfx_v9_0_is_rlc_enabled(struct amdgpu_device *adev)
return true;
}
-static void gfx_v9_0_set_safe_mode(struct amdgpu_device *adev)
+static void gfx_v9_0_set_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
uint32_t data;
unsigned i;
@@ -4603,7 +4629,7 @@ static void gfx_v9_0_set_safe_mode(struct amdgpu_device *adev)
}
}
-static void gfx_v9_0_unset_safe_mode(struct amdgpu_device *adev)
+static void gfx_v9_0_unset_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
uint32_t data;
@@ -4614,7 +4640,7 @@ static void gfx_v9_0_unset_safe_mode(struct amdgpu_device *adev)
static void gfx_v9_0_update_gfx_cg_power_gating(struct amdgpu_device *adev,
bool enable)
{
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
if ((adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) && enable) {
gfx_v9_0_enable_gfx_cg_power_gating(adev, true);
@@ -4626,7 +4652,7 @@ static void gfx_v9_0_update_gfx_cg_power_gating(struct amdgpu_device *adev,
gfx_v9_0_enable_gfx_pipeline_powergating(adev, false);
}
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static void gfx_v9_0_update_gfx_mg_power_gating(struct amdgpu_device *adev,
@@ -4653,7 +4679,7 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
{
uint32_t data, def;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
/* It is disabled by HW by default */
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
@@ -4720,7 +4746,7 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
}
}
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
@@ -4731,7 +4757,7 @@ static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
if (!adev->gfx.num_gfx_rings)
return;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
/* Enable 3D CGCG/CGLS */
if (enable) {
@@ -4775,7 +4801,7 @@ static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D, data);
}
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static void gfx_v9_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev,
@@ -4783,7 +4809,7 @@ static void gfx_v9_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
{
uint32_t def, data;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
@@ -4827,7 +4853,7 @@ static void gfx_v9_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, data);
}
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static int gfx_v9_0_update_gfx_clock_gating(struct amdgpu_device *adev,
@@ -5425,7 +5451,7 @@ static int gfx_v9_0_ring_preempt_ib(struct amdgpu_ring *ring)
{
int i, r = 0;
struct amdgpu_device *adev = ring->adev;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
struct amdgpu_ring *kiq_ring = &kiq->ring;
unsigned long flags;
@@ -6384,7 +6410,7 @@ static const struct soc15_ras_field_entry gfx_v9_0_ras_fields[] = {
};
static int gfx_v9_0_ras_error_inject(struct amdgpu_device *adev,
- void *inject_if)
+ void *inject_if, uint32_t instance_mask)
{
struct ras_inject_if *info = (struct ras_inject_if *)inject_if;
int ret;
@@ -6423,7 +6449,7 @@ static int gfx_v9_0_ras_error_inject(struct amdgpu_device *adev,
block_info.value = info->value;
mutex_lock(&adev->grbm_idx_mutex);
- ret = psp_ras_trigger_error(&adev->psp, &block_info);
+ ret = psp_ras_trigger_error(&adev->psp, &block_info, instance_mask);
mutex_unlock(&adev->grbm_idx_mutex);
return ret;
@@ -6651,7 +6677,7 @@ static void gfx_v9_0_reset_ras_error_count(struct amdgpu_device *adev)
for (i = 0; i < ARRAY_SIZE(gfx_v9_0_edc_counter_regs); i++) {
for (j = 0; j < gfx_v9_0_edc_counter_regs[i].se_num; j++) {
for (k = 0; k < gfx_v9_0_edc_counter_regs[i].instance; k++) {
- amdgpu_gfx_select_se_sh(adev, j, 0x0, k);
+ amdgpu_gfx_select_se_sh(adev, j, 0x0, k, 0);
RREG32(SOC15_REG_ENTRY_OFFSET(gfx_v9_0_edc_counter_regs[i]));
}
}
@@ -6713,7 +6739,7 @@ static void gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
for (i = 0; i < ARRAY_SIZE(gfx_v9_0_edc_counter_regs); i++) {
for (j = 0; j < gfx_v9_0_edc_counter_regs[i].se_num; j++) {
for (k = 0; k < gfx_v9_0_edc_counter_regs[i].instance; k++) {
- amdgpu_gfx_select_se_sh(adev, j, 0, k);
+ amdgpu_gfx_select_se_sh(adev, j, 0, k, 0);
reg_value =
RREG32(SOC15_REG_ENTRY_OFFSET(gfx_v9_0_edc_counter_regs[i]));
if (reg_value)
@@ -6728,7 +6754,7 @@ static void gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
err_data->ce_count += sec_count;
err_data->ue_count += ded_count;
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
gfx_v9_0_query_utc_edc_status(adev, err_data);
@@ -7010,7 +7036,7 @@ static void gfx_v9_0_set_ring_funcs(struct amdgpu_device *adev)
{
int i;
- adev->gfx.kiq.ring.funcs = &gfx_v9_0_ring_funcs_kiq;
+ adev->gfx.kiq[0].ring.funcs = &gfx_v9_0_ring_funcs_kiq;
for (i = 0; i < adev->gfx.num_gfx_rings; i++)
adev->gfx.gfx_ring[i].funcs = &gfx_v9_0_ring_funcs_gfx;
@@ -7191,7 +7217,7 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev,
mask = 1;
ao_bitmap = 0;
counter = 0;
- amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff, 0);
gfx_v9_0_set_user_cu_inactive_bitmap(
adev, disable_masks[i * adev->gfx.config.max_sh_per_se + j]);
bitmap = gfx_v9_0_get_cu_active_bitmap(adev);
@@ -7224,7 +7250,7 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev,
cu_info->ao_cu_bitmap[i % 4][j + i / 4] = ao_bitmap;
}
}
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
cu_info->number = active_cu_number;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h
index dfe8d4841f58..f9f6edc5e558 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h
@@ -27,6 +27,6 @@
extern const struct amdgpu_ip_block_version gfx_v9_0_ip_block;
void gfx_v9_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num,
- u32 instance);
+ u32 instance, int xcc_id);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c
index c67e387a97f5..bc8416afb62c 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c
@@ -970,29 +970,6 @@ static void gfx_v9_4_reset_ras_error_count(struct amdgpu_device *adev)
WREG32_SOC15(GC, 0, mmATC_L2_CACHE_4K_DSM_INDEX, 255);
}
-static int gfx_v9_4_ras_error_inject(struct amdgpu_device *adev,
- void *inject_if)
-{
- struct ras_inject_if *info = (struct ras_inject_if *)inject_if;
- int ret;
- struct ta_ras_trigger_error_input block_info = { 0 };
-
- if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
- return -EINVAL;
-
- block_info.block_id = amdgpu_ras_block_to_ta(info->head.block);
- block_info.sub_block_index = info->head.sub_block_index;
- block_info.inject_error_type = amdgpu_ras_error_to_ta(info->head.type);
- block_info.address = info->address;
- block_info.value = info->value;
-
- mutex_lock(&adev->grbm_idx_mutex);
- ret = psp_ras_trigger_error(&adev->psp, &block_info);
- mutex_unlock(&adev->grbm_idx_mutex);
-
- return ret;
-}
-
static const struct soc15_reg_entry gfx_v9_4_ea_err_status_regs =
{ SOC15_REG_ENTRY(GC, 0, mmGCEA_ERR_STATUS), 0, 1, 32 };
@@ -1030,7 +1007,6 @@ static void gfx_v9_4_query_ras_error_status(struct amdgpu_device *adev)
const struct amdgpu_ras_block_hw_ops gfx_v9_4_ras_ops = {
- .ras_error_inject = &gfx_v9_4_ras_error_inject,
.query_ras_error_count = &gfx_v9_4_query_ras_error_count,
.reset_ras_error_count = &gfx_v9_4_reset_ras_error_count,
.query_ras_error_status = &gfx_v9_4_query_ras_error_status,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c
index 3a797424579c..63f6843a069e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c
@@ -761,7 +761,7 @@ void gfx_v9_4_2_debug_trap_config_init(struct amdgpu_device *adev,
for (i = first_vmid; i < last_vmid; i++) {
data = 0;
- soc15_grbm_select(adev, 0, 0, 0, i);
+ soc15_grbm_select(adev, 0, 0, 0, i, 0);
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, 1);
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_EN, 0);
data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, EXCP_REPLACE,
@@ -769,15 +769,18 @@ void gfx_v9_4_2_debug_trap_config_init(struct amdgpu_device *adev,
WREG32(SOC15_REG_OFFSET(GC, 0, regSPI_GDBG_PER_VMID_CNTL), data);
}
- soc15_grbm_select(adev, 0, 0, 0, 0);
+ soc15_grbm_select(adev, 0, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
+
+ WREG32(SOC15_REG_OFFSET(GC, 0, regSPI_GDBG_TRAP_DATA0), 0);
+ WREG32(SOC15_REG_OFFSET(GC, 0, regSPI_GDBG_TRAP_DATA1), 0);
}
void gfx_v9_4_2_set_power_brake_sequence(struct amdgpu_device *adev)
{
u32 tmp;
- gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
tmp = 0;
tmp = REG_SET_FIELD(tmp, GC_THROTTLE_CTRL, PATTERN_MODE, 1);
@@ -1699,28 +1702,6 @@ static void gfx_v9_4_2_reset_ras_error_count(struct amdgpu_device *adev)
gfx_v9_4_2_query_utc_edc_count(adev, NULL, NULL);
}
-static int gfx_v9_4_2_ras_error_inject(struct amdgpu_device *adev, void *inject_if)
-{
- struct ras_inject_if *info = (struct ras_inject_if *)inject_if;
- int ret;
- struct ta_ras_trigger_error_input block_info = { 0 };
-
- if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
- return -EINVAL;
-
- block_info.block_id = amdgpu_ras_block_to_ta(info->head.block);
- block_info.sub_block_index = info->head.sub_block_index;
- block_info.inject_error_type = amdgpu_ras_error_to_ta(info->head.type);
- block_info.address = info->address;
- block_info.value = info->value;
-
- mutex_lock(&adev->grbm_idx_mutex);
- ret = psp_ras_trigger_error(&adev->psp, &block_info);
- mutex_unlock(&adev->grbm_idx_mutex);
-
- return ret;
-}
-
static void gfx_v9_4_2_query_ea_err_status(struct amdgpu_device *adev)
{
uint32_t i, j;
@@ -1935,7 +1916,7 @@ static bool gfx_v9_4_2_query_uctl2_poison_status(struct amdgpu_device *adev)
u32 status = 0;
struct amdgpu_vmhub *hub;
- hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
status = RREG32(hub->vm_l2_pro_fault_status);
/* reset page fault status */
WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
@@ -1944,7 +1925,6 @@ static bool gfx_v9_4_2_query_uctl2_poison_status(struct amdgpu_device *adev)
}
struct amdgpu_ras_block_hw_ops gfx_v9_4_2_ras_ops = {
- .ras_error_inject = &gfx_v9_4_2_ras_error_inject,
.query_ras_error_count = &gfx_v9_4_2_query_ras_error_count,
.reset_ras_error_count = &gfx_v9_4_2_reset_ras_error_count,
.query_ras_error_status = &gfx_v9_4_2_query_ras_error_status,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
index 5f8500577c02..c1ee54d4c3d3 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
@@ -25,35 +25,504 @@
#include "amdgpu.h"
#include "amdgpu_gfx.h"
#include "soc15.h"
+#include "soc15d.h"
#include "soc15_common.h"
#include "vega10_enum.h"
+#include "v9_structs.h"
+
+#include "ivsrcid/gfx/irqsrcs_gfx_9_0.h"
+
#include "gc/gc_9_4_3_offset.h"
#include "gc/gc_9_4_3_sh_mask.h"
#include "gfx_v9_4_3.h"
+#include "amdgpu_xcp.h"
+
+MODULE_FIRMWARE("amdgpu/gc_9_4_3_mec.bin");
+MODULE_FIRMWARE("amdgpu/gc_9_4_3_rlc.bin");
+#define GFX9_MEC_HPD_SIZE 4096
#define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L
+#define GOLDEN_GB_ADDR_CONFIG 0x2a114042
+
+struct amdgpu_gfx_ras gfx_v9_4_3_ras;
+
+static void gfx_v9_4_3_set_ring_funcs(struct amdgpu_device *adev);
+static void gfx_v9_4_3_set_irq_funcs(struct amdgpu_device *adev);
+static void gfx_v9_4_3_set_gds_init(struct amdgpu_device *adev);
+static void gfx_v9_4_3_set_rlc_funcs(struct amdgpu_device *adev);
+static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev,
+ struct amdgpu_cu_info *cu_info);
+
+static void gfx_v9_4_3_kiq_set_resources(struct amdgpu_ring *kiq_ring,
+ uint64_t queue_mask)
+{
+ amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_SET_RESOURCES, 6));
+ amdgpu_ring_write(kiq_ring,
+ PACKET3_SET_RESOURCES_VMID_MASK(0) |
+ /* vmid_mask:0* queue_type:0 (KIQ) */
+ PACKET3_SET_RESOURCES_QUEUE_TYPE(0));
+ amdgpu_ring_write(kiq_ring,
+ lower_32_bits(queue_mask)); /* queue mask lo */
+ amdgpu_ring_write(kiq_ring,
+ upper_32_bits(queue_mask)); /* queue mask hi */
+ amdgpu_ring_write(kiq_ring, 0); /* gws mask lo */
+ amdgpu_ring_write(kiq_ring, 0); /* gws mask hi */
+ amdgpu_ring_write(kiq_ring, 0); /* oac mask */
+ amdgpu_ring_write(kiq_ring, 0); /* gds heap base:0, gds heap size:0 */
+}
+
+static void gfx_v9_4_3_kiq_map_queues(struct amdgpu_ring *kiq_ring,
+ struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = kiq_ring->adev;
+ uint64_t mqd_addr = amdgpu_bo_gpu_offset(ring->mqd_obj);
+ uint64_t wptr_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
+ uint32_t eng_sel = ring->funcs->type == AMDGPU_RING_TYPE_GFX ? 4 : 0;
+
+ amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_MAP_QUEUES, 5));
+ /* Q_sel:0, vmid:0, vidmem: 1, engine:0, num_Q:1*/
+ amdgpu_ring_write(kiq_ring, /* Q_sel: 0, vmid: 0, engine: 0, num_Q: 1 */
+ PACKET3_MAP_QUEUES_QUEUE_SEL(0) | /* Queue_Sel */
+ PACKET3_MAP_QUEUES_VMID(0) | /* VMID */
+ PACKET3_MAP_QUEUES_QUEUE(ring->queue) |
+ PACKET3_MAP_QUEUES_PIPE(ring->pipe) |
+ PACKET3_MAP_QUEUES_ME((ring->me == 1 ? 0 : 1)) |
+ /*queue_type: normal compute queue */
+ PACKET3_MAP_QUEUES_QUEUE_TYPE(0) |
+ /* alloc format: all_on_one_pipe */
+ PACKET3_MAP_QUEUES_ALLOC_FORMAT(0) |
+ PACKET3_MAP_QUEUES_ENGINE_SEL(eng_sel) |
+ /* num_queues: must be 1 */
+ PACKET3_MAP_QUEUES_NUM_QUEUES(1));
+ amdgpu_ring_write(kiq_ring,
+ PACKET3_MAP_QUEUES_DOORBELL_OFFSET(ring->doorbell_index));
+ amdgpu_ring_write(kiq_ring, lower_32_bits(mqd_addr));
+ amdgpu_ring_write(kiq_ring, upper_32_bits(mqd_addr));
+ amdgpu_ring_write(kiq_ring, lower_32_bits(wptr_addr));
+ amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr));
+}
+
+static void gfx_v9_4_3_kiq_unmap_queues(struct amdgpu_ring *kiq_ring,
+ struct amdgpu_ring *ring,
+ enum amdgpu_unmap_queues_action action,
+ u64 gpu_addr, u64 seq)
+{
+ uint32_t eng_sel = ring->funcs->type == AMDGPU_RING_TYPE_GFX ? 4 : 0;
+
+ amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_UNMAP_QUEUES, 4));
+ amdgpu_ring_write(kiq_ring, /* Q_sel: 0, vmid: 0, engine: 0, num_Q: 1 */
+ PACKET3_UNMAP_QUEUES_ACTION(action) |
+ PACKET3_UNMAP_QUEUES_QUEUE_SEL(0) |
+ PACKET3_UNMAP_QUEUES_ENGINE_SEL(eng_sel) |
+ PACKET3_UNMAP_QUEUES_NUM_QUEUES(1));
+ amdgpu_ring_write(kiq_ring,
+ PACKET3_UNMAP_QUEUES_DOORBELL_OFFSET0(ring->doorbell_index));
+
+ if (action == PREEMPT_QUEUES_NO_UNMAP) {
+ amdgpu_ring_write(kiq_ring, lower_32_bits(gpu_addr));
+ amdgpu_ring_write(kiq_ring, upper_32_bits(gpu_addr));
+ amdgpu_ring_write(kiq_ring, seq);
+ } else {
+ amdgpu_ring_write(kiq_ring, 0);
+ amdgpu_ring_write(kiq_ring, 0);
+ amdgpu_ring_write(kiq_ring, 0);
+ }
+}
+
+static void gfx_v9_4_3_kiq_query_status(struct amdgpu_ring *kiq_ring,
+ struct amdgpu_ring *ring,
+ u64 addr,
+ u64 seq)
+{
+ uint32_t eng_sel = ring->funcs->type == AMDGPU_RING_TYPE_GFX ? 4 : 0;
+
+ amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_QUERY_STATUS, 5));
+ amdgpu_ring_write(kiq_ring,
+ PACKET3_QUERY_STATUS_CONTEXT_ID(0) |
+ PACKET3_QUERY_STATUS_INTERRUPT_SEL(0) |
+ PACKET3_QUERY_STATUS_COMMAND(2));
+ /* Q_sel: 0, vmid: 0, engine: 0, num_Q: 1 */
+ amdgpu_ring_write(kiq_ring,
+ PACKET3_QUERY_STATUS_DOORBELL_OFFSET(ring->doorbell_index) |
+ PACKET3_QUERY_STATUS_ENG_SEL(eng_sel));
+ amdgpu_ring_write(kiq_ring, lower_32_bits(addr));
+ amdgpu_ring_write(kiq_ring, upper_32_bits(addr));
+ amdgpu_ring_write(kiq_ring, lower_32_bits(seq));
+ amdgpu_ring_write(kiq_ring, upper_32_bits(seq));
+}
+
+static void gfx_v9_4_3_kiq_invalidate_tlbs(struct amdgpu_ring *kiq_ring,
+ uint16_t pasid, uint32_t flush_type,
+ bool all_hub)
+{
+ amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_INVALIDATE_TLBS, 0));
+ amdgpu_ring_write(kiq_ring,
+ PACKET3_INVALIDATE_TLBS_DST_SEL(1) |
+ PACKET3_INVALIDATE_TLBS_ALL_HUB(all_hub) |
+ PACKET3_INVALIDATE_TLBS_PASID(pasid) |
+ PACKET3_INVALIDATE_TLBS_FLUSH_TYPE(flush_type));
+}
+
+static const struct kiq_pm4_funcs gfx_v9_4_3_kiq_pm4_funcs = {
+ .kiq_set_resources = gfx_v9_4_3_kiq_set_resources,
+ .kiq_map_queues = gfx_v9_4_3_kiq_map_queues,
+ .kiq_unmap_queues = gfx_v9_4_3_kiq_unmap_queues,
+ .kiq_query_status = gfx_v9_4_3_kiq_query_status,
+ .kiq_invalidate_tlbs = gfx_v9_4_3_kiq_invalidate_tlbs,
+ .set_resources_size = 8,
+ .map_queues_size = 7,
+ .unmap_queues_size = 6,
+ .query_status_size = 7,
+ .invalidate_tlbs_size = 2,
+};
+
+static void gfx_v9_4_3_set_kiq_pm4_funcs(struct amdgpu_device *adev)
+{
+ int i, num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++)
+ adev->gfx.kiq[i].pmf = &gfx_v9_4_3_kiq_pm4_funcs;
+}
+
+static void gfx_v9_4_3_init_golden_registers(struct amdgpu_device *adev)
+{
+ int i, num_xcc, dev_inst;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++) {
+ dev_inst = GET_INST(GC, i);
+ if (dev_inst >= 2)
+ WREG32_SOC15(GC, dev_inst, regGRBM_MCM_ADDR, 0x4);
+
+ /* Golden settings applied by driver for ASIC with rev_id 0 */
+ if (adev->rev_id == 0) {
+ WREG32_SOC15(GC, dev_inst, regGB_ADDR_CONFIG,
+ GOLDEN_GB_ADDR_CONFIG);
+
+ WREG32_FIELD15_PREREG(GC, dev_inst, TCP_UTCL1_CNTL1,
+ REDUCE_FIFO_DEPTH_BY_2, 2);
+ }
+ }
+}
+
+static void gfx_v9_4_3_write_data_to_reg(struct amdgpu_ring *ring, int eng_sel,
+ bool wc, uint32_t reg, uint32_t val)
+{
+ amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+ amdgpu_ring_write(ring, WRITE_DATA_ENGINE_SEL(eng_sel) |
+ WRITE_DATA_DST_SEL(0) |
+ (wc ? WR_CONFIRM : 0));
+ amdgpu_ring_write(ring, reg);
+ amdgpu_ring_write(ring, 0);
+ amdgpu_ring_write(ring, val);
+}
+
+static void gfx_v9_4_3_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
+ int mem_space, int opt, uint32_t addr0,
+ uint32_t addr1, uint32_t ref, uint32_t mask,
+ uint32_t inv)
+{
+ amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
+ amdgpu_ring_write(ring,
+ /* memory (1) or register (0) */
+ (WAIT_REG_MEM_MEM_SPACE(mem_space) |
+ WAIT_REG_MEM_OPERATION(opt) | /* wait */
+ WAIT_REG_MEM_FUNCTION(3) | /* equal */
+ WAIT_REG_MEM_ENGINE(eng_sel)));
+
+ if (mem_space)
+ BUG_ON(addr0 & 0x3); /* Dword align */
+ amdgpu_ring_write(ring, addr0);
+ amdgpu_ring_write(ring, addr1);
+ amdgpu_ring_write(ring, ref);
+ amdgpu_ring_write(ring, mask);
+ amdgpu_ring_write(ring, inv); /* poll interval */
+}
+
+static int gfx_v9_4_3_ring_test_ring(struct amdgpu_ring *ring)
+{
+ uint32_t scratch_reg0_offset, xcc_offset;
+ struct amdgpu_device *adev = ring->adev;
+ uint32_t tmp = 0;
+ unsigned i;
+ int r;
+
+ /* Use register offset which is local to XCC in the packet */
+ xcc_offset = SOC15_REG_OFFSET(GC, 0, regSCRATCH_REG0);
+ scratch_reg0_offset = SOC15_REG_OFFSET(GC, GET_INST(GC, ring->xcc_id), regSCRATCH_REG0);
+ WREG32(scratch_reg0_offset, 0xCAFEDEAD);
+
+ r = amdgpu_ring_alloc(ring, 3);
+ if (r)
+ return r;
+
+ amdgpu_ring_write(ring, PACKET3(PACKET3_SET_UCONFIG_REG, 1));
+ amdgpu_ring_write(ring, xcc_offset - PACKET3_SET_UCONFIG_REG_START);
+ amdgpu_ring_write(ring, 0xDEADBEEF);
+ amdgpu_ring_commit(ring);
+
+ for (i = 0; i < adev->usec_timeout; i++) {
+ tmp = RREG32(scratch_reg0_offset);
+ if (tmp == 0xDEADBEEF)
+ break;
+ udelay(1);
+ }
+
+ if (i >= adev->usec_timeout)
+ r = -ETIMEDOUT;
+ return r;
+}
+
+static int gfx_v9_4_3_ring_test_ib(struct amdgpu_ring *ring, long timeout)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_ib ib;
+ struct dma_fence *f = NULL;
+
+ unsigned index;
+ uint64_t gpu_addr;
+ uint32_t tmp;
+ long r;
+
+ r = amdgpu_device_wb_get(adev, &index);
+ if (r)
+ return r;
+
+ gpu_addr = adev->wb.gpu_addr + (index * 4);
+ adev->wb.wb[index] = cpu_to_le32(0xCAFEDEAD);
+ memset(&ib, 0, sizeof(ib));
+ r = amdgpu_ib_get(adev, NULL, 16,
+ AMDGPU_IB_POOL_DIRECT, &ib);
+ if (r)
+ goto err1;
+
+ ib.ptr[0] = PACKET3(PACKET3_WRITE_DATA, 3);
+ ib.ptr[1] = WRITE_DATA_DST_SEL(5) | WR_CONFIRM;
+ ib.ptr[2] = lower_32_bits(gpu_addr);
+ ib.ptr[3] = upper_32_bits(gpu_addr);
+ ib.ptr[4] = 0xDEADBEEF;
+ ib.length_dw = 5;
+
+ r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
+ if (r)
+ goto err2;
+
+ r = dma_fence_wait_timeout(f, false, timeout);
+ if (r == 0) {
+ r = -ETIMEDOUT;
+ goto err2;
+ } else if (r < 0) {
+ goto err2;
+ }
+
+ tmp = adev->wb.wb[index];
+ if (tmp == 0xDEADBEEF)
+ r = 0;
+ else
+ r = -EINVAL;
+
+err2:
+ amdgpu_ib_free(adev, &ib, NULL);
+ dma_fence_put(f);
+err1:
+ amdgpu_device_wb_free(adev, index);
+ return r;
+}
+
+
+/* This value might differs per partition */
static uint64_t gfx_v9_4_3_get_gpu_clock_counter(struct amdgpu_device *adev)
{
uint64_t clock;
amdgpu_gfx_off_ctrl(adev, false);
mutex_lock(&adev->gfx.gpu_clock_mutex);
- WREG32_SOC15(GC, 0, regRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
- clock = (uint64_t)RREG32_SOC15(GC, 0, regRLC_GPU_CLOCK_COUNT_LSB) |
- ((uint64_t)RREG32_SOC15(GC, 0, regRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
+ WREG32_SOC15(GC, GET_INST(GC, 0), regRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
+ clock = (uint64_t)RREG32_SOC15(GC, GET_INST(GC, 0), regRLC_GPU_CLOCK_COUNT_LSB) |
+ ((uint64_t)RREG32_SOC15(GC, GET_INST(GC, 0), regRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
mutex_unlock(&adev->gfx.gpu_clock_mutex);
amdgpu_gfx_off_ctrl(adev, true);
return clock;
}
-static void gfx_v9_4_3_select_se_sh(struct amdgpu_device *adev,
- u32 se_num,
- u32 sh_num,
- u32 instance)
+static void gfx_v9_4_3_free_microcode(struct amdgpu_device *adev)
+{
+ amdgpu_ucode_release(&adev->gfx.pfp_fw);
+ amdgpu_ucode_release(&adev->gfx.me_fw);
+ amdgpu_ucode_release(&adev->gfx.ce_fw);
+ amdgpu_ucode_release(&adev->gfx.rlc_fw);
+ amdgpu_ucode_release(&adev->gfx.mec_fw);
+ amdgpu_ucode_release(&adev->gfx.mec2_fw);
+
+ kfree(adev->gfx.rlc.register_list_format);
+}
+
+static int gfx_v9_4_3_init_rlc_microcode(struct amdgpu_device *adev,
+ const char *chip_name)
+{
+ char fw_name[30];
+ int err;
+ const struct rlc_firmware_header_v2_0 *rlc_hdr;
+ uint16_t version_major;
+ uint16_t version_minor;
+
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
+
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
+ if (err)
+ goto out;
+ rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
+
+ version_major = le16_to_cpu(rlc_hdr->header.header_version_major);
+ version_minor = le16_to_cpu(rlc_hdr->header.header_version_minor);
+ err = amdgpu_gfx_rlc_init_microcode(adev, version_major, version_minor);
+out:
+ if (err)
+ amdgpu_ucode_release(&adev->gfx.rlc_fw);
+
+ return err;
+}
+
+static bool gfx_v9_4_3_should_disable_gfxoff(struct pci_dev *pdev)
+{
+ return true;
+}
+
+static void gfx_v9_4_3_check_if_need_gfxoff(struct amdgpu_device *adev)
+{
+ if (gfx_v9_4_3_should_disable_gfxoff(adev->pdev))
+ adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
+}
+
+static int gfx_v9_4_3_init_cp_compute_microcode(struct amdgpu_device *adev,
+ const char *chip_name)
+{
+ char fw_name[30];
+ int err;
+
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
+
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
+ if (err)
+ goto out;
+ amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
+ amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1_JT);
+
+ adev->gfx.mec2_fw_version = adev->gfx.mec_fw_version;
+ adev->gfx.mec2_feature_version = adev->gfx.mec_feature_version;
+
+ gfx_v9_4_3_check_if_need_gfxoff(adev);
+
+out:
+ if (err)
+ amdgpu_ucode_release(&adev->gfx.mec_fw);
+ return err;
+}
+
+static int gfx_v9_4_3_init_microcode(struct amdgpu_device *adev)
+{
+ const char *chip_name;
+ int r;
+
+ chip_name = "gc_9_4_3";
+
+ r = gfx_v9_4_3_init_rlc_microcode(adev, chip_name);
+ if (r)
+ return r;
+
+ r = gfx_v9_4_3_init_cp_compute_microcode(adev, chip_name);
+ if (r)
+ return r;
+
+ return r;
+}
+
+static void gfx_v9_4_3_mec_fini(struct amdgpu_device *adev)
+{
+ amdgpu_bo_free_kernel(&adev->gfx.mec.hpd_eop_obj, NULL, NULL);
+ amdgpu_bo_free_kernel(&adev->gfx.mec.mec_fw_obj, NULL, NULL);
+}
+
+static int gfx_v9_4_3_mec_init(struct amdgpu_device *adev)
+{
+ int r, i, num_xcc;
+ u32 *hpd;
+ const __le32 *fw_data;
+ unsigned fw_size;
+ u32 *fw;
+ size_t mec_hpd_size;
+
+ const struct gfx_firmware_header_v1_0 *mec_hdr;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++)
+ bitmap_zero(adev->gfx.mec_bitmap[i].queue_bitmap,
+ AMDGPU_MAX_COMPUTE_QUEUES);
+
+ /* take ownership of the relevant compute queues */
+ amdgpu_gfx_compute_queue_acquire(adev);
+ mec_hpd_size =
+ adev->gfx.num_compute_rings * num_xcc * GFX9_MEC_HPD_SIZE;
+ if (mec_hpd_size) {
+ r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM |
+ AMDGPU_GEM_DOMAIN_GTT,
+ &adev->gfx.mec.hpd_eop_obj,
+ &adev->gfx.mec.hpd_eop_gpu_addr,
+ (void **)&hpd);
+ if (r) {
+ dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r);
+ gfx_v9_4_3_mec_fini(adev);
+ return r;
+ }
+
+ if (amdgpu_emu_mode == 1) {
+ for (i = 0; i < mec_hpd_size / 4; i++) {
+ memset((void *)(hpd + i), 0, 4);
+ if (i % 50 == 0)
+ msleep(1);
+ }
+ } else {
+ memset(hpd, 0, mec_hpd_size);
+ }
+
+ amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj);
+ amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj);
+ }
+
+ mec_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
+
+ fw_data = (const __le32 *)
+ (adev->gfx.mec_fw->data +
+ le32_to_cpu(mec_hdr->header.ucode_array_offset_bytes));
+ fw_size = le32_to_cpu(mec_hdr->header.ucode_size_bytes);
+
+ r = amdgpu_bo_create_reserved(adev, mec_hdr->header.ucode_size_bytes,
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
+ &adev->gfx.mec.mec_fw_obj,
+ &adev->gfx.mec.mec_fw_gpu_addr,
+ (void **)&fw);
+ if (r) {
+ dev_warn(adev->dev, "(%d) create mec firmware bo failed\n", r);
+ gfx_v9_4_3_mec_fini(adev);
+ return r;
+ }
+
+ memcpy(fw, fw_data, fw_size);
+
+ amdgpu_bo_kunmap(adev->gfx.mec.mec_fw_obj);
+ amdgpu_bo_unreserve(adev->gfx.mec.mec_fw_obj);
+
+ return 0;
+}
+
+static void gfx_v9_4_3_xcc_select_se_sh(struct amdgpu_device *adev, u32 se_num,
+ u32 sh_num, u32 instance, int xcc_id)
{
u32 data;
@@ -76,24 +545,24 @@ static void gfx_v9_4_3_select_se_sh(struct amdgpu_device *adev,
else
data = REG_SET_FIELD(data, GRBM_GFX_INDEX, SH_INDEX, sh_num);
- WREG32_SOC15_RLC_SHADOW_EX(reg, GC, 0, regGRBM_GFX_INDEX, data);
+ WREG32_SOC15_RLC_SHADOW_EX(reg, GC, GET_INST(GC, xcc_id), regGRBM_GFX_INDEX, data);
}
-static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t address)
+static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd, uint32_t wave, uint32_t address)
{
- WREG32_SOC15_RLC(GC, 0, regSQ_IND_INDEX,
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regSQ_IND_INDEX,
(wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
(simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
(address << SQ_IND_INDEX__INDEX__SHIFT) |
(SQ_IND_INDEX__FORCE_READ_MASK));
- return RREG32_SOC15(GC, 0, regSQ_IND_DATA);
+ return RREG32_SOC15(GC, GET_INST(GC, xcc_id), regSQ_IND_DATA);
}
-static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
+static void wave_read_regs(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t thread,
uint32_t regno, uint32_t num, uint32_t *out)
{
- WREG32_SOC15_RLC(GC, 0, regSQ_IND_INDEX,
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regSQ_IND_INDEX,
(wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
(simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
(regno << SQ_IND_INDEX__INDEX__SHIFT) |
@@ -101,53 +570,481 @@ static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
(SQ_IND_INDEX__FORCE_READ_MASK) |
(SQ_IND_INDEX__AUTO_INCR_MASK));
while (num--)
- *(out++) = RREG32_SOC15(GC, 0, regSQ_IND_DATA);
+ *(out++) = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regSQ_IND_DATA);
}
static void gfx_v9_4_3_read_wave_data(struct amdgpu_device *adev,
- uint32_t simd, uint32_t wave,
+ uint32_t xcc_id, uint32_t simd, uint32_t wave,
uint32_t *dst, int *no_fields)
{
/* type 1 wave data */
dst[(*no_fields)++] = 1;
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_STATUS);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_LO);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_HI);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_LO);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_HI);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_HW_ID);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW0);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW1);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_GPR_ALLOC);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_LDS_ALLOC);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TRAPSTS);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
- dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
-}
-
-static void gfx_v9_4_3_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_STATUS);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_PC_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_PC_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_EXEC_LO);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_EXEC_HI);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_HW_ID);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_INST_DW0);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_INST_DW1);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_GPR_ALLOC);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_LDS_ALLOC);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_TRAPSTS);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_IB_STS);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_IB_DBG0);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_M0);
+ dst[(*no_fields)++] = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_MODE);
+}
+
+static void gfx_v9_4_3_read_wave_sgprs(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t start,
uint32_t size, uint32_t *dst)
{
- wave_read_regs(adev, simd, wave, 0,
+ wave_read_regs(adev, xcc_id, simd, wave, 0,
start + SQIND_WAVE_SGPRS_OFFSET, size, dst);
}
-static void gfx_v9_4_3_read_wave_vgprs(struct amdgpu_device *adev, uint32_t simd,
+static void gfx_v9_4_3_read_wave_vgprs(struct amdgpu_device *adev, uint32_t xcc_id, uint32_t simd,
uint32_t wave, uint32_t thread,
uint32_t start, uint32_t size,
uint32_t *dst)
{
- wave_read_regs(adev, simd, wave, thread,
+ wave_read_regs(adev, xcc_id, simd, wave, thread,
start + SQIND_WAVE_VGPRS_OFFSET, size, dst);
}
static void gfx_v9_4_3_select_me_pipe_q(struct amdgpu_device *adev,
- u32 me, u32 pipe, u32 q, u32 vm)
+ u32 me, u32 pipe, u32 q, u32 vm, u32 xcc_id)
+{
+ soc15_grbm_select(adev, me, pipe, q, vm, GET_INST(GC, xcc_id));
+}
+
+
+static int gfx_v9_4_3_switch_compute_partition(struct amdgpu_device *adev,
+ int num_xccs_per_xcp)
+{
+ int ret;
+
+ ret = psp_spatial_partition(&adev->psp, NUM_XCC(adev->gfx.xcc_mask) /
+ num_xccs_per_xcp);
+ if (ret)
+ return ret;
+
+ adev->gfx.num_xcc_per_xcp = num_xccs_per_xcp;
+
+ return ret;
+}
+
+static int gfx_v9_4_3_ih_to_xcc_inst(struct amdgpu_device *adev, int ih_node)
+{
+ int xcc;
+
+ xcc = hweight8(adev->gfx.xcc_mask & GENMASK(ih_node / 2, 0));
+ if (!xcc) {
+ dev_err(adev->dev, "Couldn't find xcc mapping from IH node");
+ return -EINVAL;
+ }
+
+ return xcc - 1;
+}
+
+static const struct amdgpu_gfx_funcs gfx_v9_4_3_gfx_funcs = {
+ .get_gpu_clock_counter = &gfx_v9_4_3_get_gpu_clock_counter,
+ .select_se_sh = &gfx_v9_4_3_xcc_select_se_sh,
+ .read_wave_data = &gfx_v9_4_3_read_wave_data,
+ .read_wave_sgprs = &gfx_v9_4_3_read_wave_sgprs,
+ .read_wave_vgprs = &gfx_v9_4_3_read_wave_vgprs,
+ .select_me_pipe_q = &gfx_v9_4_3_select_me_pipe_q,
+ .switch_partition_mode = &gfx_v9_4_3_switch_compute_partition,
+ .ih_node_to_logical_xcc = &gfx_v9_4_3_ih_to_xcc_inst,
+};
+
+static int gfx_v9_4_3_gpu_early_init(struct amdgpu_device *adev)
+{
+ u32 gb_addr_config;
+
+ adev->gfx.funcs = &gfx_v9_4_3_gfx_funcs;
+ adev->gfx.ras = &gfx_v9_4_3_ras;
+
+ switch (adev->ip_versions[GC_HWIP][0]) {
+ case IP_VERSION(9, 4, 3):
+ adev->gfx.config.max_hw_contexts = 8;
+ adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
+ adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
+ adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
+ adev->gfx.config.sc_earlyz_tile_fifo_size = 0x4C0;
+ gb_addr_config = RREG32_SOC15(GC, GET_INST(GC, 0), regGB_ADDR_CONFIG);
+ break;
+ default:
+ BUG();
+ break;
+ }
+
+ adev->gfx.config.gb_addr_config = gb_addr_config;
+
+ adev->gfx.config.gb_addr_config_fields.num_pipes = 1 <<
+ REG_GET_FIELD(
+ adev->gfx.config.gb_addr_config,
+ GB_ADDR_CONFIG,
+ NUM_PIPES);
+
+ adev->gfx.config.max_tile_pipes =
+ adev->gfx.config.gb_addr_config_fields.num_pipes;
+
+ adev->gfx.config.gb_addr_config_fields.num_banks = 1 <<
+ REG_GET_FIELD(
+ adev->gfx.config.gb_addr_config,
+ GB_ADDR_CONFIG,
+ NUM_BANKS);
+ adev->gfx.config.gb_addr_config_fields.max_compress_frags = 1 <<
+ REG_GET_FIELD(
+ adev->gfx.config.gb_addr_config,
+ GB_ADDR_CONFIG,
+ MAX_COMPRESSED_FRAGS);
+ adev->gfx.config.gb_addr_config_fields.num_rb_per_se = 1 <<
+ REG_GET_FIELD(
+ adev->gfx.config.gb_addr_config,
+ GB_ADDR_CONFIG,
+ NUM_RB_PER_SE);
+ adev->gfx.config.gb_addr_config_fields.num_se = 1 <<
+ REG_GET_FIELD(
+ adev->gfx.config.gb_addr_config,
+ GB_ADDR_CONFIG,
+ NUM_SHADER_ENGINES);
+ adev->gfx.config.gb_addr_config_fields.pipe_interleave_size = 1 << (8 +
+ REG_GET_FIELD(
+ adev->gfx.config.gb_addr_config,
+ GB_ADDR_CONFIG,
+ PIPE_INTERLEAVE_SIZE));
+
+ return 0;
+}
+
+static int gfx_v9_4_3_compute_ring_init(struct amdgpu_device *adev, int ring_id,
+ int xcc_id, int mec, int pipe, int queue)
+{
+ unsigned irq_type;
+ struct amdgpu_ring *ring = &adev->gfx.compute_ring[ring_id];
+ unsigned int hw_prio;
+ uint32_t xcc_doorbell_start;
+
+ ring = &adev->gfx.compute_ring[xcc_id * adev->gfx.num_compute_rings +
+ ring_id];
+
+ /* mec0 is me1 */
+ ring->xcc_id = xcc_id;
+ ring->me = mec + 1;
+ ring->pipe = pipe;
+ ring->queue = queue;
+
+ ring->ring_obj = NULL;
+ ring->use_doorbell = true;
+ xcc_doorbell_start = adev->doorbell_index.mec_ring0 +
+ xcc_id * adev->doorbell_index.xcc_doorbell_range;
+ ring->doorbell_index = (xcc_doorbell_start + ring_id) << 1;
+ ring->eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr +
+ (ring_id + xcc_id * adev->gfx.num_compute_rings) *
+ GFX9_MEC_HPD_SIZE;
+ ring->vm_hub = AMDGPU_GFXHUB(xcc_id);
+ sprintf(ring->name, "comp_%d.%d.%d.%d",
+ ring->xcc_id, ring->me, ring->pipe, ring->queue);
+
+ irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP
+ + ((ring->me - 1) * adev->gfx.mec.num_pipe_per_mec)
+ + ring->pipe;
+ hw_prio = amdgpu_gfx_is_high_priority_compute_queue(adev, ring) ?
+ AMDGPU_GFX_PIPE_PRIO_HIGH : AMDGPU_GFX_PIPE_PRIO_NORMAL;
+ /* type-2 packets are deprecated on MEC, use type-3 instead */
+ return amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq, irq_type,
+ hw_prio, NULL);
+}
+
+static int gfx_v9_4_3_sw_init(void *handle)
+{
+ int i, j, k, r, ring_id, xcc_id, num_xcc;
+ struct amdgpu_kiq *kiq;
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ adev->gfx.mec.num_mec = 2;
+ adev->gfx.mec.num_pipe_per_mec = 4;
+ adev->gfx.mec.num_queue_per_pipe = 8;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+
+ /* EOP Event */
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP, GFX_9_0__SRCID__CP_EOP_INTERRUPT, &adev->gfx.eop_irq);
+ if (r)
+ return r;
+
+ /* Privileged reg */
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP, GFX_9_0__SRCID__CP_PRIV_REG_FAULT,
+ &adev->gfx.priv_reg_irq);
+ if (r)
+ return r;
+
+ /* Privileged inst */
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP, GFX_9_0__SRCID__CP_PRIV_INSTR_FAULT,
+ &adev->gfx.priv_inst_irq);
+ if (r)
+ return r;
+
+ adev->gfx.gfx_current_status = AMDGPU_GFX_NORMAL_MODE;
+
+ r = adev->gfx.rlc.funcs->init(adev);
+ if (r) {
+ DRM_ERROR("Failed to init rlc BOs!\n");
+ return r;
+ }
+
+ r = gfx_v9_4_3_mec_init(adev);
+ if (r) {
+ DRM_ERROR("Failed to init MEC BOs!\n");
+ return r;
+ }
+
+ /* set up the compute queues - allocate horizontally across pipes */
+ for (xcc_id = 0; xcc_id < num_xcc; xcc_id++) {
+ ring_id = 0;
+ for (i = 0; i < adev->gfx.mec.num_mec; ++i) {
+ for (j = 0; j < adev->gfx.mec.num_queue_per_pipe; j++) {
+ for (k = 0; k < adev->gfx.mec.num_pipe_per_mec;
+ k++) {
+ if (!amdgpu_gfx_is_mec_queue_enabled(
+ adev, xcc_id, i, k, j))
+ continue;
+
+ r = gfx_v9_4_3_compute_ring_init(adev,
+ ring_id,
+ xcc_id,
+ i, k, j);
+ if (r)
+ return r;
+
+ ring_id++;
+ }
+ }
+ }
+
+ r = amdgpu_gfx_kiq_init(adev, GFX9_MEC_HPD_SIZE, xcc_id);
+ if (r) {
+ DRM_ERROR("Failed to init KIQ BOs!\n");
+ return r;
+ }
+
+ kiq = &adev->gfx.kiq[xcc_id];
+ r = amdgpu_gfx_kiq_init_ring(adev, &kiq->ring, &kiq->irq, xcc_id);
+ if (r)
+ return r;
+
+ /* create MQD for all compute queues as wel as KIQ for SRIOV case */
+ r = amdgpu_gfx_mqd_sw_init(adev,
+ sizeof(struct v9_mqd_allocation), xcc_id);
+ if (r)
+ return r;
+ }
+
+ r = gfx_v9_4_3_gpu_early_init(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_gfx_sysfs_init(adev);
+ if (r)
+ return r;
+
+ return amdgpu_gfx_ras_sw_init(adev);
+}
+
+static int gfx_v9_4_3_sw_fini(void *handle)
{
- soc15_grbm_select(adev, me, pipe, q, vm);
+ int i, num_xcc;
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < adev->gfx.num_compute_rings * num_xcc; i++)
+ amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
+
+ for (i = 0; i < num_xcc; i++) {
+ amdgpu_gfx_mqd_sw_fini(adev, i);
+ amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq[i].ring);
+ amdgpu_gfx_kiq_fini(adev, i);
+ }
+
+ gfx_v9_4_3_mec_fini(adev);
+ amdgpu_bo_unref(&adev->gfx.rlc.clear_state_obj);
+ gfx_v9_4_3_free_microcode(adev);
+ amdgpu_gfx_sysfs_fini(adev);
+
+ return 0;
+}
+
+#define DEFAULT_SH_MEM_BASES (0x6000)
+static void gfx_v9_4_3_xcc_init_compute_vmid(struct amdgpu_device *adev,
+ int xcc_id)
+{
+ int i;
+ uint32_t sh_mem_config;
+ uint32_t sh_mem_bases;
+
+ /*
+ * Configure apertures:
+ * LDS: 0x60000000'00000000 - 0x60000001'00000000 (4GB)
+ * Scratch: 0x60000001'00000000 - 0x60000002'00000000 (4GB)
+ * GPUVM: 0x60010000'00000000 - 0x60020000'00000000 (1TB)
+ */
+ sh_mem_bases = DEFAULT_SH_MEM_BASES | (DEFAULT_SH_MEM_BASES << 16);
+
+ sh_mem_config = SH_MEM_ADDRESS_MODE_64 |
+ SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
+ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT;
+
+ mutex_lock(&adev->srbm_mutex);
+ for (i = adev->vm_manager.first_kfd_vmid; i < AMDGPU_NUM_VMID; i++) {
+ soc15_grbm_select(adev, 0, 0, 0, i, GET_INST(GC, xcc_id));
+ /* CP and shaders */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regSH_MEM_CONFIG, sh_mem_config);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regSH_MEM_BASES, sh_mem_bases);
+ }
+ soc15_grbm_select(adev, 0, 0, 0, 0, GET_INST(GC, xcc_id));
+ mutex_unlock(&adev->srbm_mutex);
+
+ /* Initialize all compute VMIDs to have no GDS, GWS, or OA
+ acccess. These should be enabled by FW for target VMIDs. */
+ for (i = adev->vm_manager.first_kfd_vmid; i < AMDGPU_NUM_VMID; i++) {
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, xcc_id), regGDS_VMID0_BASE, 2 * i, 0);
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, xcc_id), regGDS_VMID0_SIZE, 2 * i, 0);
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, xcc_id), regGDS_GWS_VMID0, i, 0);
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, xcc_id), regGDS_OA_VMID0, i, 0);
+ }
+}
+
+static void gfx_v9_4_3_xcc_init_gds_vmid(struct amdgpu_device *adev, int xcc_id)
+{
+ int vmid;
+
+ /*
+ * Initialize all compute and user-gfx VMIDs to have no GDS, GWS, or OA
+ * access. Compute VMIDs should be enabled by FW for target VMIDs,
+ * the driver can enable them for graphics. VMID0 should maintain
+ * access so that HWS firmware can save/restore entries.
+ */
+ for (vmid = 1; vmid < AMDGPU_NUM_VMID; vmid++) {
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, xcc_id), regGDS_VMID0_BASE, 2 * vmid, 0);
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, xcc_id), regGDS_VMID0_SIZE, 2 * vmid, 0);
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, xcc_id), regGDS_GWS_VMID0, vmid, 0);
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, xcc_id), regGDS_OA_VMID0, vmid, 0);
+ }
+}
+
+static void gfx_v9_4_3_xcc_constants_init(struct amdgpu_device *adev,
+ int xcc_id)
+{
+ u32 tmp;
+ int i;
+
+ /* XXX SH_MEM regs */
+ /* where to put LDS, scratch, GPUVM in FSA64 space */
+ mutex_lock(&adev->srbm_mutex);
+ for (i = 0; i < adev->vm_manager.id_mgr[AMDGPU_GFXHUB(0)].num_ids; i++) {
+ soc15_grbm_select(adev, 0, 0, 0, i, GET_INST(GC, xcc_id));
+ /* CP and shaders */
+ if (i == 0) {
+ tmp = REG_SET_FIELD(0, SH_MEM_CONFIG, ALIGNMENT_MODE,
+ SH_MEM_ALIGNMENT_MODE_UNALIGNED);
+ tmp = REG_SET_FIELD(tmp, SH_MEM_CONFIG, RETRY_DISABLE,
+ !!adev->gmc.noretry);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id),
+ regSH_MEM_CONFIG, tmp);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id),
+ regSH_MEM_BASES, 0);
+ } else {
+ tmp = REG_SET_FIELD(0, SH_MEM_CONFIG, ALIGNMENT_MODE,
+ SH_MEM_ALIGNMENT_MODE_UNALIGNED);
+ tmp = REG_SET_FIELD(tmp, SH_MEM_CONFIG, RETRY_DISABLE,
+ !!adev->gmc.noretry);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id),
+ regSH_MEM_CONFIG, tmp);
+ tmp = REG_SET_FIELD(0, SH_MEM_BASES, PRIVATE_BASE,
+ (adev->gmc.private_aperture_start >>
+ 48));
+ tmp = REG_SET_FIELD(tmp, SH_MEM_BASES, SHARED_BASE,
+ (adev->gmc.shared_aperture_start >>
+ 48));
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id),
+ regSH_MEM_BASES, tmp);
+ }
+ }
+ soc15_grbm_select(adev, 0, 0, 0, 0, GET_INST(GC, 0));
+
+ mutex_unlock(&adev->srbm_mutex);
+
+ gfx_v9_4_3_xcc_init_compute_vmid(adev, xcc_id);
+ gfx_v9_4_3_xcc_init_gds_vmid(adev, xcc_id);
+}
+
+static void gfx_v9_4_3_constants_init(struct amdgpu_device *adev)
+{
+ int i, num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+
+ gfx_v9_4_3_get_cu_info(adev, &adev->gfx.cu_info);
+ adev->gfx.config.db_debug2 =
+ RREG32_SOC15(GC, GET_INST(GC, 0), regDB_DEBUG2);
+
+ for (i = 0; i < num_xcc; i++)
+ gfx_v9_4_3_xcc_constants_init(adev, i);
+}
+
+static void
+gfx_v9_4_3_xcc_enable_save_restore_machine(struct amdgpu_device *adev,
+ int xcc_id)
+{
+ WREG32_FIELD15_PREREG(GC, GET_INST(GC, xcc_id), RLC_SRM_CNTL, SRM_ENABLE, 1);
+}
+
+static void gfx_v9_4_3_xcc_init_pg(struct amdgpu_device *adev, int xcc_id)
+{
+ /*
+ * Rlc save restore list is workable since v2_1.
+ * And it's needed by gfxoff feature.
+ */
+ if (adev->gfx.rlc.is_rlc_v2_1)
+ gfx_v9_4_3_xcc_enable_save_restore_machine(adev, xcc_id);
+}
+
+static void gfx_v9_4_3_xcc_disable_gpa_mode(struct amdgpu_device *adev, int xcc_id)
+{
+ uint32_t data;
+
+ data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCPC_PSP_DEBUG);
+ data |= CPC_PSP_DEBUG__UTCL2IUGPAOVERRIDE_MASK;
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCPC_PSP_DEBUG, data);
+}
+
+static void gfx_v9_4_3_xcc_program_xcc_id(struct amdgpu_device *adev,
+ int xcc_id)
+{
+ uint32_t tmp = 0;
+ int num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ switch (num_xcc) {
+ /* directly config VIRTUAL_XCC_ID to 0 for 1-XCC */
+ case 1:
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HYP_XCP_CTL, 0x8);
+ break;
+ case 2:
+ case 4:
+ case 6:
+ case 8:
+ tmp = (xcc_id % adev->gfx.num_xcc_per_xcp) << REG_FIELD_SHIFT(CP_HYP_XCP_CTL, VIRTUAL_XCC_ID);
+ tmp = tmp | (adev->gfx.num_xcc_per_xcp << REG_FIELD_SHIFT(CP_HYP_XCP_CTL, NUM_XCC_IN_XCP));
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HYP_XCP_CTL, tmp);
+
+ break;
+ default:
+ break;
+ }
}
static bool gfx_v9_4_3_is_rlc_enabled(struct amdgpu_device *adev)
@@ -155,36 +1052,37 @@ static bool gfx_v9_4_3_is_rlc_enabled(struct amdgpu_device *adev)
uint32_t rlc_setting;
/* if RLC is not enabled, do nothing */
- rlc_setting = RREG32_SOC15(GC, 0, regRLC_CNTL);
+ rlc_setting = RREG32_SOC15(GC, GET_INST(GC, 0), regRLC_CNTL);
if (!(rlc_setting & RLC_CNTL__RLC_ENABLE_F32_MASK))
return false;
return true;
}
-static void gfx_v9_4_3_set_safe_mode(struct amdgpu_device *adev)
+static void gfx_v9_4_3_xcc_set_safe_mode(struct amdgpu_device *adev, int xcc_id)
{
uint32_t data;
unsigned i;
data = RLC_SAFE_MODE__CMD_MASK;
data |= (1 << RLC_SAFE_MODE__MESSAGE__SHIFT);
- WREG32_SOC15(GC, 0, regRLC_SAFE_MODE, data);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_SAFE_MODE, data);
/* wait for RLC_SAFE_MODE */
for (i = 0; i < adev->usec_timeout; i++) {
- if (!REG_GET_FIELD(RREG32_SOC15(GC, 0, regRLC_SAFE_MODE), RLC_SAFE_MODE, CMD))
+ if (!REG_GET_FIELD(RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_SAFE_MODE), RLC_SAFE_MODE, CMD))
break;
udelay(1);
}
}
-static void gfx_v9_4_3_unset_safe_mode(struct amdgpu_device *adev)
+static void gfx_v9_4_3_xcc_unset_safe_mode(struct amdgpu_device *adev,
+ int xcc_id)
{
uint32_t data;
data = RLC_SAFE_MODE__CMD_MASK;
- WREG32_SOC15(GC, 0, regRLC_SAFE_MODE, data);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_SAFE_MODE, data);
}
static int gfx_v9_4_3_rlc_init(struct amdgpu_device *adev)
@@ -196,7 +1094,8 @@ static int gfx_v9_4_3_rlc_init(struct amdgpu_device *adev)
return 0;
}
-static void gfx_v9_4_3_wait_for_rlc_serdes(struct amdgpu_device *adev)
+static void gfx_v9_4_3_xcc_wait_for_rlc_serdes(struct amdgpu_device *adev,
+ int xcc_id)
{
u32 i, j, k;
u32 mask;
@@ -204,15 +1103,17 @@ static void gfx_v9_4_3_wait_for_rlc_serdes(struct amdgpu_device *adev)
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++) {
- gfx_v9_4_3_select_se_sh(adev, i, j, 0xffffffff);
+ gfx_v9_4_3_xcc_select_se_sh(adev, i, j, 0xffffffff,
+ xcc_id);
for (k = 0; k < adev->usec_timeout; k++) {
- if (RREG32_SOC15(GC, 0, regRLC_SERDES_CU_MASTER_BUSY) == 0)
+ if (RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_SERDES_CU_MASTER_BUSY) == 0)
break;
udelay(1);
}
if (k == adev->usec_timeout) {
- gfx_v9_4_3_select_se_sh(adev, 0xffffffff,
- 0xffffffff, 0xffffffff);
+ gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff,
+ 0xffffffff,
+ 0xffffffff, xcc_id);
mutex_unlock(&adev->grbm_idx_mutex);
DRM_INFO("Timeout wait for RLC serdes %u,%u\n",
i, j);
@@ -220,7 +1121,8 @@ static void gfx_v9_4_3_wait_for_rlc_serdes(struct amdgpu_device *adev)
}
}
}
- gfx_v9_4_3_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
+ xcc_id);
mutex_unlock(&adev->grbm_idx_mutex);
mask = RLC_SERDES_NONCU_MASTER_BUSY__SE_MASTER_BUSY_MASK |
@@ -228,79 +1130,108 @@ static void gfx_v9_4_3_wait_for_rlc_serdes(struct amdgpu_device *adev)
RLC_SERDES_NONCU_MASTER_BUSY__TC0_MASTER_BUSY_MASK |
RLC_SERDES_NONCU_MASTER_BUSY__TC1_MASTER_BUSY_MASK;
for (k = 0; k < adev->usec_timeout; k++) {
- if ((RREG32_SOC15(GC, 0, regRLC_SERDES_NONCU_MASTER_BUSY) & mask) == 0)
+ if ((RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_SERDES_NONCU_MASTER_BUSY) & mask) == 0)
break;
udelay(1);
}
}
-static void gfx_v9_4_3_enable_gui_idle_interrupt(struct amdgpu_device *adev,
- bool enable)
+static void gfx_v9_4_3_xcc_enable_gui_idle_interrupt(struct amdgpu_device *adev,
+ bool enable, int xcc_id)
{
u32 tmp;
/* These interrupts should be enabled to drive DS clock */
- tmp = RREG32_SOC15(GC, 0, regCP_INT_CNTL_RING0);
+ tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_INT_CNTL_RING0);
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE, enable ? 1 : 0);
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE, enable ? 1 : 0);
tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE, enable ? 1 : 0);
- if (adev->gfx.num_gfx_rings)
- tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE, enable ? 1 : 0);
- WREG32_SOC15(GC, 0, regCP_INT_CNTL_RING0, tmp);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_INT_CNTL_RING0, tmp);
+}
+
+static void gfx_v9_4_3_xcc_rlc_stop(struct amdgpu_device *adev, int xcc_id)
+{
+ WREG32_FIELD15_PREREG(GC, GET_INST(GC, xcc_id), RLC_CNTL,
+ RLC_ENABLE_F32, 0);
+ gfx_v9_4_3_xcc_enable_gui_idle_interrupt(adev, false, xcc_id);
+ gfx_v9_4_3_xcc_wait_for_rlc_serdes(adev, xcc_id);
}
static void gfx_v9_4_3_rlc_stop(struct amdgpu_device *adev)
{
- WREG32_FIELD15_PREREG(GC, 0, RLC_CNTL, RLC_ENABLE_F32, 0);
- gfx_v9_4_3_enable_gui_idle_interrupt(adev, false);
- gfx_v9_4_3_wait_for_rlc_serdes(adev);
+ int i, num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++)
+ gfx_v9_4_3_xcc_rlc_stop(adev, i);
}
-static void gfx_v9_4_3_rlc_reset(struct amdgpu_device *adev)
+static void gfx_v9_4_3_xcc_rlc_reset(struct amdgpu_device *adev, int xcc_id)
{
- WREG32_FIELD15_PREREG(GC, 0, GRBM_SOFT_RESET, SOFT_RESET_RLC, 1);
+ WREG32_FIELD15_PREREG(GC, GET_INST(GC, xcc_id), GRBM_SOFT_RESET,
+ SOFT_RESET_RLC, 1);
udelay(50);
- WREG32_FIELD15_PREREG(GC, 0, GRBM_SOFT_RESET, SOFT_RESET_RLC, 0);
+ WREG32_FIELD15_PREREG(GC, GET_INST(GC, xcc_id), GRBM_SOFT_RESET,
+ SOFT_RESET_RLC, 0);
udelay(50);
}
-static void gfx_v9_4_3_rlc_start(struct amdgpu_device *adev)
+static void gfx_v9_4_3_rlc_reset(struct amdgpu_device *adev)
{
-#ifdef AMDGPU_RLC_DEBUG_RETRY
- u32 rlc_ucode_ver;
-#endif
+ int i, num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++)
+ gfx_v9_4_3_xcc_rlc_reset(adev, i);
+}
- WREG32_FIELD15_PREREG(GC, 0, RLC_CNTL, RLC_ENABLE_F32, 1);
+static void gfx_v9_4_3_xcc_rlc_start(struct amdgpu_device *adev, int xcc_id)
+{
+ WREG32_FIELD15_PREREG(GC, GET_INST(GC, xcc_id), RLC_CNTL,
+ RLC_ENABLE_F32, 1);
udelay(50);
/* carrizo do enable cp interrupt after cp inited */
if (!(adev->flags & AMD_IS_APU)) {
- gfx_v9_4_3_enable_gui_idle_interrupt(adev, true);
+ gfx_v9_4_3_xcc_enable_gui_idle_interrupt(adev, true, xcc_id);
udelay(50);
}
+}
+static void gfx_v9_4_3_rlc_start(struct amdgpu_device *adev)
+{
#ifdef AMDGPU_RLC_DEBUG_RETRY
- /* RLC_GPM_GENERAL_6 : RLC Ucode version */
- rlc_ucode_ver = RREG32_SOC15(GC, 0, regRLC_GPM_GENERAL_6);
- if (rlc_ucode_ver == 0x108) {
- dev_info(adev->dev,
- "Using rlc debug ucode. regRLC_GPM_GENERAL_6 ==0x08%x / fw_ver == %i \n",
- rlc_ucode_ver, adev->gfx.rlc_fw_version);
- /* RLC_GPM_TIMER_INT_3 : Timer interval in RefCLK cycles,
- * default is 0x9C4 to create a 100us interval */
- WREG32_SOC15(GC, 0, regRLC_GPM_TIMER_INT_3, 0x9C4);
- /* RLC_GPM_GENERAL_12 : Minimum gap between wptr and rptr
- * to disable the page fault retry interrupts, default is
- * 0x100 (256) */
- WREG32_SOC15(GC, 0, regRLC_GPM_GENERAL_12, 0x100);
- }
+ u32 rlc_ucode_ver;
+#endif
+ int i, num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++) {
+ gfx_v9_4_3_xcc_rlc_start(adev, i);
+#ifdef AMDGPU_RLC_DEBUG_RETRY
+ /* RLC_GPM_GENERAL_6 : RLC Ucode version */
+ rlc_ucode_ver = RREG32_SOC15(GC, GET_INST(GC, i), regRLC_GPM_GENERAL_6);
+ if (rlc_ucode_ver == 0x108) {
+ dev_info(adev->dev,
+ "Using rlc debug ucode. regRLC_GPM_GENERAL_6 ==0x08%x / fw_ver == %i \n",
+ rlc_ucode_ver, adev->gfx.rlc_fw_version);
+ /* RLC_GPM_TIMER_INT_3 : Timer interval in RefCLK cycles,
+ * default is 0x9C4 to create a 100us interval */
+ WREG32_SOC15(GC, GET_INST(GC, i), regRLC_GPM_TIMER_INT_3, 0x9C4);
+ /* RLC_GPM_GENERAL_12 : Minimum gap between wptr and rptr
+ * to disable the page fault retry interrupts, default is
+ * 0x100 (256) */
+ WREG32_SOC15(GC, GET_INST(GC, i), regRLC_GPM_GENERAL_12, 0x100);
+ }
#endif
+ }
}
-static int gfx_v9_4_3_rlc_load_microcode(struct amdgpu_device *adev)
+static int gfx_v9_4_3_xcc_rlc_load_microcode(struct amdgpu_device *adev,
+ int xcc_id)
{
const struct rlc_firmware_header_v2_0 *hdr;
const __le32 *fw_data;
@@ -316,49 +1247,65 @@ static int gfx_v9_4_3_rlc_load_microcode(struct amdgpu_device *adev)
le32_to_cpu(hdr->header.ucode_array_offset_bytes));
fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
- WREG32_SOC15(GC, 0, regRLC_GPM_UCODE_ADDR,
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_GPM_UCODE_ADDR,
RLCG_UCODE_LOADING_START_ADDRESS);
for (i = 0; i < fw_size; i++) {
if (amdgpu_emu_mode == 1 && i % 100 == 0) {
dev_info(adev->dev, "Write RLC ucode data %u DWs\n", i);
msleep(1);
}
- WREG32_SOC15(GC, 0, regRLC_GPM_UCODE_DATA, le32_to_cpup(fw_data++));
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_GPM_UCODE_DATA, le32_to_cpup(fw_data++));
}
- WREG32_SOC15(GC, 0, regRLC_GPM_UCODE_ADDR, adev->gfx.rlc_fw_version);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_GPM_UCODE_ADDR, adev->gfx.rlc_fw_version);
return 0;
}
-static int gfx_v9_4_3_rlc_resume(struct amdgpu_device *adev)
+static int gfx_v9_4_3_xcc_rlc_resume(struct amdgpu_device *adev, int xcc_id)
{
int r;
- adev->gfx.rlc.funcs->stop(adev);
+ if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
+ gfx_v9_4_3_xcc_rlc_stop(adev, xcc_id);
+ /* legacy rlc firmware loading */
+ r = gfx_v9_4_3_xcc_rlc_load_microcode(adev, xcc_id);
+ if (r)
+ return r;
+ gfx_v9_4_3_xcc_rlc_start(adev, xcc_id);
+ }
+ amdgpu_gfx_rlc_enter_safe_mode(adev, xcc_id);
/* disable CG */
- WREG32_SOC15(GC, 0, regRLC_CGCG_CGLS_CTRL, 0);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGCG_CGLS_CTRL, 0);
+ gfx_v9_4_3_xcc_init_pg(adev, xcc_id);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, xcc_id);
- /* TODO: revisit pg function */
- /* gfx_v9_4_3_init_pg(adev);*/
+ return 0;
+}
- if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
- /* legacy rlc firmware loading */
- r = gfx_v9_4_3_rlc_load_microcode(adev);
+static int gfx_v9_4_3_rlc_resume(struct amdgpu_device *adev)
+{
+ int r, i, num_xcc;
+
+ if (amdgpu_sriov_vf(adev))
+ return 0;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++) {
+ r = gfx_v9_4_3_xcc_rlc_resume(adev, i);
if (r)
return r;
}
- adev->gfx.rlc.funcs->start(adev);
-
return 0;
}
-static void gfx_v9_4_3_update_spm_vmid(struct amdgpu_device *adev, unsigned vmid)
+static void gfx_v9_4_3_update_spm_vmid(struct amdgpu_device *adev,
+ unsigned vmid)
{
u32 reg, data;
- reg = SOC15_REG_OFFSET(GC, 0, regRLC_SPM_MC_CNTL);
+ reg = SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regRLC_SPM_MC_CNTL);
if (amdgpu_sriov_is_pp_one_vf(adev))
data = RREG32_NO_KIQ(reg);
else
@@ -368,9 +1315,9 @@ static void gfx_v9_4_3_update_spm_vmid(struct amdgpu_device *adev, unsigned vmid
data |= (vmid & RLC_SPM_MC_CNTL__RLC_SPM_VMID_MASK) << RLC_SPM_MC_CNTL__RLC_SPM_VMID__SHIFT;
if (amdgpu_sriov_is_pp_one_vf(adev))
- WREG32_SOC15_NO_KIQ(GC, 0, regRLC_SPM_MC_CNTL, data);
+ WREG32_SOC15_NO_KIQ(GC, GET_INST(GC, 0), regRLC_SPM_MC_CNTL, data);
else
- WREG32_SOC15(GC, 0, regRLC_SPM_MC_CNTL, data);
+ WREG32_SOC15(GC, GET_INST(GC, 0), regRLC_SPM_MC_CNTL, data);
}
static const struct soc15_reg_rlcg rlcg_access_gc_9_4_3[] = {
@@ -382,7 +1329,7 @@ static bool gfx_v9_4_3_check_rlcg_range(struct amdgpu_device *adev,
uint32_t offset,
struct soc15_reg_rlcg *entries, int arr_size)
{
- int i;
+ int i, inst;
uint32_t reg;
if (!entries)
@@ -392,7 +1339,12 @@ static bool gfx_v9_4_3_check_rlcg_range(struct amdgpu_device *adev,
const struct soc15_reg_rlcg *entry;
entry = &entries[i];
- reg = adev->reg_offset[entry->hwip][entry->instance][entry->segment] + entry->reg;
+ inst = adev->ip_map.logical_to_dev_inst ?
+ adev->ip_map.logical_to_dev_inst(
+ adev, entry->hwip, entry->instance) :
+ entry->instance;
+ reg = adev->reg_offset[entry->hwip][inst][entry->segment] +
+ entry->reg;
if (offset == reg)
return true;
}
@@ -407,19 +1359,1025 @@ static bool gfx_v9_4_3_is_rlcg_access_range(struct amdgpu_device *adev, u32 offs
ARRAY_SIZE(rlcg_access_gc_9_4_3));
}
-const struct amdgpu_gfx_funcs gfx_v9_4_3_gfx_funcs = {
- .get_gpu_clock_counter = &gfx_v9_4_3_get_gpu_clock_counter,
- .select_se_sh = &gfx_v9_4_3_select_se_sh,
- .read_wave_data = &gfx_v9_4_3_read_wave_data,
- .read_wave_sgprs = &gfx_v9_4_3_read_wave_sgprs,
- .read_wave_vgprs = &gfx_v9_4_3_read_wave_vgprs,
- .select_me_pipe_q = &gfx_v9_4_3_select_me_pipe_q,
-};
+static void gfx_v9_4_3_xcc_cp_compute_enable(struct amdgpu_device *adev,
+ bool enable, int xcc_id)
+{
+ if (enable) {
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_MEC_CNTL, 0);
+ } else {
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_MEC_CNTL,
+ (CP_MEC_CNTL__MEC_ME1_HALT_MASK | CP_MEC_CNTL__MEC_ME2_HALT_MASK));
+ adev->gfx.kiq[xcc_id].ring.sched.ready = false;
+ }
+ udelay(50);
+}
+
+static int gfx_v9_4_3_xcc_cp_compute_load_microcode(struct amdgpu_device *adev,
+ int xcc_id)
+{
+ const struct gfx_firmware_header_v1_0 *mec_hdr;
+ const __le32 *fw_data;
+ unsigned i;
+ u32 tmp;
+ u32 mec_ucode_addr_offset;
+ u32 mec_ucode_data_offset;
+
+ if (!adev->gfx.mec_fw)
+ return -EINVAL;
+
+ gfx_v9_4_3_xcc_cp_compute_enable(adev, false, xcc_id);
+
+ mec_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
+ amdgpu_ucode_print_gfx_hdr(&mec_hdr->header);
+
+ fw_data = (const __le32 *)
+ (adev->gfx.mec_fw->data +
+ le32_to_cpu(mec_hdr->header.ucode_array_offset_bytes));
+ tmp = 0;
+ tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0);
+ tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_CPC_IC_BASE_CNTL, tmp);
+
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_CPC_IC_BASE_LO,
+ adev->gfx.mec.mec_fw_gpu_addr & 0xFFFFF000);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_CPC_IC_BASE_HI,
+ upper_32_bits(adev->gfx.mec.mec_fw_gpu_addr));
+
+ mec_ucode_addr_offset =
+ SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_MEC_ME1_UCODE_ADDR);
+ mec_ucode_data_offset =
+ SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_MEC_ME1_UCODE_DATA);
+
+ /* MEC1 */
+ WREG32(mec_ucode_addr_offset, mec_hdr->jt_offset);
+ for (i = 0; i < mec_hdr->jt_size; i++)
+ WREG32(mec_ucode_data_offset,
+ le32_to_cpup(fw_data + mec_hdr->jt_offset + i));
+
+ WREG32(mec_ucode_addr_offset, adev->gfx.mec_fw_version);
+ /* Todo : Loading MEC2 firmware is only necessary if MEC2 should run different microcode than MEC1. */
+
+ return 0;
+}
+
+/* KIQ functions */
+static void gfx_v9_4_3_xcc_kiq_setting(struct amdgpu_ring *ring, int xcc_id)
+{
+ uint32_t tmp;
+ struct amdgpu_device *adev = ring->adev;
+
+ /* tell RLC which is KIQ queue */
+ tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CP_SCHEDULERS);
+ tmp &= 0xffffff00;
+ tmp |= (ring->me << 5) | (ring->pipe << 3) | (ring->queue);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regRLC_CP_SCHEDULERS, tmp);
+ tmp |= 0x80;
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regRLC_CP_SCHEDULERS, tmp);
+}
+
+static void gfx_v9_4_3_mqd_set_priority(struct amdgpu_ring *ring, struct v9_mqd *mqd)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
+ if (amdgpu_gfx_is_high_priority_compute_queue(adev, ring)) {
+ mqd->cp_hqd_pipe_priority = AMDGPU_GFX_PIPE_PRIO_HIGH;
+ mqd->cp_hqd_queue_priority =
+ AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM;
+ }
+ }
+}
+
+static int gfx_v9_4_3_xcc_mqd_init(struct amdgpu_ring *ring, int xcc_id)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct v9_mqd *mqd = ring->mqd_ptr;
+ uint64_t hqd_gpu_addr, wb_gpu_addr, eop_base_addr;
+ uint32_t tmp;
+
+ mqd->header = 0xC0310800;
+ mqd->compute_pipelinestat_enable = 0x00000001;
+ mqd->compute_static_thread_mgmt_se0 = 0xffffffff;
+ mqd->compute_static_thread_mgmt_se1 = 0xffffffff;
+ mqd->compute_static_thread_mgmt_se2 = 0xffffffff;
+ mqd->compute_static_thread_mgmt_se3 = 0xffffffff;
+ mqd->compute_misc_reserved = 0x00000003;
+
+ mqd->dynamic_cu_mask_addr_lo =
+ lower_32_bits(ring->mqd_gpu_addr
+ + offsetof(struct v9_mqd_allocation, dynamic_cu_mask));
+ mqd->dynamic_cu_mask_addr_hi =
+ upper_32_bits(ring->mqd_gpu_addr
+ + offsetof(struct v9_mqd_allocation, dynamic_cu_mask));
+
+ eop_base_addr = ring->eop_gpu_addr >> 8;
+ mqd->cp_hqd_eop_base_addr_lo = eop_base_addr;
+ mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr);
+
+ /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
+ tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_EOP_CONTROL);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
+ (order_base_2(GFX9_MEC_HPD_SIZE / 4) - 1));
+
+ mqd->cp_hqd_eop_control = tmp;
+
+ /* enable doorbell? */
+ tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_DOORBELL_CONTROL);
+
+ if (ring->use_doorbell) {
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_OFFSET, ring->doorbell_index);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_EN, 1);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_SOURCE, 0);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_HIT, 0);
+ } else {
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_EN, 0);
+ }
+
+ mqd->cp_hqd_pq_doorbell_control = tmp;
+
+ /* disable the queue if it's active */
+ ring->wptr = 0;
+ mqd->cp_hqd_dequeue_request = 0;
+ mqd->cp_hqd_pq_rptr = 0;
+ mqd->cp_hqd_pq_wptr_lo = 0;
+ mqd->cp_hqd_pq_wptr_hi = 0;
+
+ /* set the pointer to the MQD */
+ mqd->cp_mqd_base_addr_lo = ring->mqd_gpu_addr & 0xfffffffc;
+ mqd->cp_mqd_base_addr_hi = upper_32_bits(ring->mqd_gpu_addr);
+
+ /* set MQD vmid to 0 */
+ tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_MQD_CONTROL);
+ tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0);
+ mqd->cp_mqd_control = tmp;
+
+ /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
+ hqd_gpu_addr = ring->gpu_addr >> 8;
+ mqd->cp_hqd_pq_base_lo = hqd_gpu_addr;
+ mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr);
+
+ /* set up the HQD, this is similar to CP_RB0_CNTL */
+ tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_CONTROL);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE,
+ (order_base_2(ring->ring_size / 4) - 1));
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE,
+ ((order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1) << 8));
+#ifdef __BIG_ENDIAN
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP, 1);
+#endif
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ROQ_PQ_IB_FLIP, 0);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1);
+ mqd->cp_hqd_pq_control = tmp;
+
+ /* set the wb address whether it's enabled or not */
+ wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
+ mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr & 0xfffffffc;
+ mqd->cp_hqd_pq_rptr_report_addr_hi =
+ upper_32_bits(wb_gpu_addr) & 0xffff;
+
+ /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
+ wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
+ mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffffc;
+ mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff;
+
+ /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
+ ring->wptr = 0;
+ mqd->cp_hqd_pq_rptr = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_RPTR);
+
+ /* set the vmid for the queue */
+ mqd->cp_hqd_vmid = 0;
+
+ tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_PERSISTENT_STATE);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53);
+ mqd->cp_hqd_persistent_state = tmp;
+
+ /* set MIN_IB_AVAIL_SIZE */
+ tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_IB_CONTROL);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_IB_CONTROL, MIN_IB_AVAIL_SIZE, 3);
+ mqd->cp_hqd_ib_control = tmp;
+
+ /* set static priority for a queue/ring */
+ gfx_v9_4_3_mqd_set_priority(ring, mqd);
+ mqd->cp_hqd_quantum = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_QUANTUM);
+
+ /* map_queues packet doesn't need activate the queue,
+ * so only kiq need set this field.
+ */
+ if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
+ mqd->cp_hqd_active = 1;
+
+ return 0;
+}
+
+static int gfx_v9_4_3_xcc_kiq_init_register(struct amdgpu_ring *ring,
+ int xcc_id)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct v9_mqd *mqd = ring->mqd_ptr;
+ int j;
+
+ /* disable wptr polling */
+ WREG32_FIELD15_PREREG(GC, GET_INST(GC, xcc_id), CP_PQ_WPTR_POLL_CNTL, EN, 0);
+
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_EOP_BASE_ADDR,
+ mqd->cp_hqd_eop_base_addr_lo);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_EOP_BASE_ADDR_HI,
+ mqd->cp_hqd_eop_base_addr_hi);
+
+ /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_EOP_CONTROL,
+ mqd->cp_hqd_eop_control);
+
+ /* enable doorbell? */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_DOORBELL_CONTROL,
+ mqd->cp_hqd_pq_doorbell_control);
+
+ /* disable the queue if it's active */
+ if (RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_ACTIVE) & 1) {
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_DEQUEUE_REQUEST, 1);
+ for (j = 0; j < adev->usec_timeout; j++) {
+ if (!(RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_ACTIVE) & 1))
+ break;
+ udelay(1);
+ }
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_DEQUEUE_REQUEST,
+ mqd->cp_hqd_dequeue_request);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_RPTR,
+ mqd->cp_hqd_pq_rptr);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_WPTR_LO,
+ mqd->cp_hqd_pq_wptr_lo);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_WPTR_HI,
+ mqd->cp_hqd_pq_wptr_hi);
+ }
+
+ /* set the pointer to the MQD */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_MQD_BASE_ADDR,
+ mqd->cp_mqd_base_addr_lo);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_MQD_BASE_ADDR_HI,
+ mqd->cp_mqd_base_addr_hi);
+
+ /* set MQD vmid to 0 */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_MQD_CONTROL,
+ mqd->cp_mqd_control);
+
+ /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_BASE,
+ mqd->cp_hqd_pq_base_lo);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_BASE_HI,
+ mqd->cp_hqd_pq_base_hi);
+
+ /* set up the HQD, this is similar to CP_RB0_CNTL */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_CONTROL,
+ mqd->cp_hqd_pq_control);
+
+ /* set the wb address whether it's enabled or not */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_RPTR_REPORT_ADDR,
+ mqd->cp_hqd_pq_rptr_report_addr_lo);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_RPTR_REPORT_ADDR_HI,
+ mqd->cp_hqd_pq_rptr_report_addr_hi);
+
+ /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_WPTR_POLL_ADDR,
+ mqd->cp_hqd_pq_wptr_poll_addr_lo);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_WPTR_POLL_ADDR_HI,
+ mqd->cp_hqd_pq_wptr_poll_addr_hi);
+
+ /* enable the doorbell if requested */
+ if (ring->use_doorbell) {
+ WREG32_SOC15(
+ GC, GET_INST(GC, xcc_id),
+ regCP_MEC_DOORBELL_RANGE_LOWER,
+ ((adev->doorbell_index.kiq +
+ xcc_id * adev->doorbell_index.xcc_doorbell_range) *
+ 2) << 2);
+ WREG32_SOC15(
+ GC, GET_INST(GC, xcc_id),
+ regCP_MEC_DOORBELL_RANGE_UPPER,
+ ((adev->doorbell_index.userqueue_end +
+ xcc_id * adev->doorbell_index.xcc_doorbell_range) *
+ 2) << 2);
+ }
+
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_DOORBELL_CONTROL,
+ mqd->cp_hqd_pq_doorbell_control);
+
+ /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_WPTR_LO,
+ mqd->cp_hqd_pq_wptr_lo);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_WPTR_HI,
+ mqd->cp_hqd_pq_wptr_hi);
+
+ /* set the vmid for the queue */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_VMID, mqd->cp_hqd_vmid);
+
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PERSISTENT_STATE,
+ mqd->cp_hqd_persistent_state);
+
+ /* activate the queue */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_ACTIVE,
+ mqd->cp_hqd_active);
+
+ if (ring->use_doorbell)
+ WREG32_FIELD15_PREREG(GC, GET_INST(GC, xcc_id), CP_PQ_STATUS, DOORBELL_ENABLE, 1);
+
+ return 0;
+}
+
+static int gfx_v9_4_3_xcc_q_fini_register(struct amdgpu_ring *ring,
+ int xcc_id)
+{
+ struct amdgpu_device *adev = ring->adev;
+ int j;
+
+ /* disable the queue if it's active */
+ if (RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_ACTIVE) & 1) {
+
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_DEQUEUE_REQUEST, 1);
+
+ for (j = 0; j < adev->usec_timeout; j++) {
+ if (!(RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_HQD_ACTIVE) & 1))
+ break;
+ udelay(1);
+ }
+
+ if (j == AMDGPU_MAX_USEC_TIMEOUT) {
+ DRM_DEBUG("%s dequeue request failed.\n", ring->name);
+
+ /* Manual disable if dequeue request times out */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_ACTIVE, 0);
+ }
+
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_DEQUEUE_REQUEST,
+ 0);
+ }
+
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_IQ_TIMER, 0);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_IB_CONTROL, 0);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PERSISTENT_STATE, 0);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_DOORBELL_CONTROL, 0x40000000);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_DOORBELL_CONTROL, 0);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_RPTR, 0);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_WPTR_HI, 0);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_WPTR_LO, 0);
+
+ return 0;
+}
+
+static int gfx_v9_4_3_xcc_kiq_init_queue(struct amdgpu_ring *ring, int xcc_id)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct v9_mqd *mqd = ring->mqd_ptr;
+ struct v9_mqd *tmp_mqd;
+
+ gfx_v9_4_3_xcc_kiq_setting(ring, xcc_id);
+
+ /* GPU could be in bad state during probe, driver trigger the reset
+ * after load the SMU, in this case , the mqd is not be initialized.
+ * driver need to re-init the mqd.
+ * check mqd->cp_hqd_pq_control since this value should not be 0
+ */
+ tmp_mqd = (struct v9_mqd *)adev->gfx.kiq[xcc_id].mqd_backup;
+ if (amdgpu_in_reset(adev) && tmp_mqd->cp_hqd_pq_control) {
+ /* for GPU_RESET case , reset MQD to a clean status */
+ if (adev->gfx.kiq[xcc_id].mqd_backup)
+ memcpy(mqd, adev->gfx.kiq[xcc_id].mqd_backup, sizeof(struct v9_mqd_allocation));
+
+ /* reset ring buffer */
+ ring->wptr = 0;
+ amdgpu_ring_clear_ring(ring);
+ mutex_lock(&adev->srbm_mutex);
+ soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, GET_INST(GC, xcc_id));
+ gfx_v9_4_3_xcc_kiq_init_register(ring, xcc_id);
+ soc15_grbm_select(adev, 0, 0, 0, 0, GET_INST(GC, xcc_id));
+ mutex_unlock(&adev->srbm_mutex);
+ } else {
+ memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation));
+ ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF;
+ ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF;
+ mutex_lock(&adev->srbm_mutex);
+ soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, GET_INST(GC, xcc_id));
+ gfx_v9_4_3_xcc_mqd_init(ring, xcc_id);
+ gfx_v9_4_3_xcc_kiq_init_register(ring, xcc_id);
+ soc15_grbm_select(adev, 0, 0, 0, 0, GET_INST(GC, xcc_id));
+ mutex_unlock(&adev->srbm_mutex);
+
+ if (adev->gfx.kiq[xcc_id].mqd_backup)
+ memcpy(adev->gfx.kiq[xcc_id].mqd_backup, mqd, sizeof(struct v9_mqd_allocation));
+ }
+
+ return 0;
+}
+
+static int gfx_v9_4_3_xcc_kcq_init_queue(struct amdgpu_ring *ring, int xcc_id)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct v9_mqd *mqd = ring->mqd_ptr;
+ int mqd_idx = ring - &adev->gfx.compute_ring[0];
+ struct v9_mqd *tmp_mqd;
+
+ /* Same as above kiq init, driver need to re-init the mqd if mqd->cp_hqd_pq_control
+ * is not be initialized before
+ */
+ tmp_mqd = (struct v9_mqd *)adev->gfx.mec.mqd_backup[mqd_idx];
+
+ if (!tmp_mqd->cp_hqd_pq_control ||
+ (!amdgpu_in_reset(adev) && !adev->in_suspend)) {
+ memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation));
+ ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF;
+ ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF;
+ mutex_lock(&adev->srbm_mutex);
+ soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, GET_INST(GC, xcc_id));
+ gfx_v9_4_3_xcc_mqd_init(ring, xcc_id);
+ soc15_grbm_select(adev, 0, 0, 0, 0, GET_INST(GC, xcc_id));
+ mutex_unlock(&adev->srbm_mutex);
+
+ if (adev->gfx.mec.mqd_backup[mqd_idx])
+ memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct v9_mqd_allocation));
+ } else {
+ /* restore MQD to a clean status */
+ if (adev->gfx.mec.mqd_backup[mqd_idx])
+ memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation));
+ /* reset ring buffer */
+ ring->wptr = 0;
+ atomic64_set((atomic64_t *)&adev->wb.wb[ring->wptr_offs], 0);
+ amdgpu_ring_clear_ring(ring);
+ }
+
+ return 0;
+}
+
+static int gfx_v9_4_3_xcc_kcq_fini_register(struct amdgpu_device *adev, int xcc_id)
+{
+ struct amdgpu_ring *ring;
+ int j;
+
+ for (j = 0; j < adev->gfx.num_compute_rings; j++) {
+ ring = &adev->gfx.compute_ring[j + xcc_id * adev->gfx.num_compute_rings];
+ if (!amdgpu_in_reset(adev) && !adev->in_suspend) {
+ mutex_lock(&adev->srbm_mutex);
+ soc15_grbm_select(adev, ring->me,
+ ring->pipe,
+ ring->queue, 0, GET_INST(GC, xcc_id));
+ gfx_v9_4_3_xcc_q_fini_register(ring, xcc_id);
+ soc15_grbm_select(adev, 0, 0, 0, 0, GET_INST(GC, xcc_id));
+ mutex_unlock(&adev->srbm_mutex);
+ }
+ }
+
+ return 0;
+}
+
+static int gfx_v9_4_3_xcc_kiq_resume(struct amdgpu_device *adev, int xcc_id)
+{
+ struct amdgpu_ring *ring;
+ int r;
+
+ ring = &adev->gfx.kiq[xcc_id].ring;
+
+ r = amdgpu_bo_reserve(ring->mqd_obj, false);
+ if (unlikely(r != 0))
+ return r;
+
+ r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
+ if (unlikely(r != 0)) {
+ amdgpu_bo_unreserve(ring->mqd_obj);
+ return r;
+ }
+
+ gfx_v9_4_3_xcc_kiq_init_queue(ring, xcc_id);
+ amdgpu_bo_kunmap(ring->mqd_obj);
+ ring->mqd_ptr = NULL;
+ amdgpu_bo_unreserve(ring->mqd_obj);
+ return 0;
+}
+
+static int gfx_v9_4_3_xcc_kcq_resume(struct amdgpu_device *adev, int xcc_id)
+{
+ struct amdgpu_ring *ring = NULL;
+ int r = 0, i;
+
+ gfx_v9_4_3_xcc_cp_compute_enable(adev, true, xcc_id);
+
+ for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+ ring = &adev->gfx.compute_ring[i + xcc_id * adev->gfx.num_compute_rings];
+
+ r = amdgpu_bo_reserve(ring->mqd_obj, false);
+ if (unlikely(r != 0))
+ goto done;
+ r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
+ if (!r) {
+ r = gfx_v9_4_3_xcc_kcq_init_queue(ring, xcc_id);
+ amdgpu_bo_kunmap(ring->mqd_obj);
+ ring->mqd_ptr = NULL;
+ }
+ amdgpu_bo_unreserve(ring->mqd_obj);
+ if (r)
+ goto done;
+ }
+
+ r = amdgpu_gfx_enable_kcq(adev, xcc_id);
+done:
+ return r;
+}
+
+static int gfx_v9_4_3_xcc_cp_resume(struct amdgpu_device *adev, int xcc_id)
+{
+ struct amdgpu_ring *ring;
+ int r, j;
+
+ gfx_v9_4_3_xcc_enable_gui_idle_interrupt(adev, false, xcc_id);
+
+ if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
+ gfx_v9_4_3_xcc_disable_gpa_mode(adev, xcc_id);
+
+ r = gfx_v9_4_3_xcc_cp_compute_load_microcode(adev, xcc_id);
+ if (r)
+ return r;
+ }
+
+ /* set the virtual and physical id based on partition_mode */
+ gfx_v9_4_3_xcc_program_xcc_id(adev, xcc_id);
+
+ r = gfx_v9_4_3_xcc_kiq_resume(adev, xcc_id);
+ if (r)
+ return r;
+
+ r = gfx_v9_4_3_xcc_kcq_resume(adev, xcc_id);
+ if (r)
+ return r;
+
+ for (j = 0; j < adev->gfx.num_compute_rings; j++) {
+ ring = &adev->gfx.compute_ring
+ [j + xcc_id * adev->gfx.num_compute_rings];
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ }
+
+ gfx_v9_4_3_xcc_enable_gui_idle_interrupt(adev, true, xcc_id);
+
+ return 0;
+}
+
+static int gfx_v9_4_3_cp_resume(struct amdgpu_device *adev)
+{
+ int r = 0, i, num_xcc;
+
+ if (amdgpu_xcp_query_partition_mode(adev->xcp_mgr,
+ AMDGPU_XCP_FL_NONE) ==
+ AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE)
+ r = amdgpu_xcp_switch_partition_mode(adev->xcp_mgr,
+ amdgpu_user_partt_mode);
+
+ if (r)
+ return r;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++) {
+ r = gfx_v9_4_3_xcc_cp_resume(adev, i);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static void gfx_v9_4_3_xcc_cp_enable(struct amdgpu_device *adev, bool enable,
+ int xcc_id)
+{
+ gfx_v9_4_3_xcc_cp_compute_enable(adev, enable, xcc_id);
+}
+
+static void gfx_v9_4_3_xcc_fini(struct amdgpu_device *adev, int xcc_id)
+{
+ if (amdgpu_gfx_disable_kcq(adev, xcc_id))
+ DRM_ERROR("XCD %d KCQ disable failed\n", xcc_id);
+
+ /* Use deinitialize sequence from CAIL when unbinding device
+ * from driver, otherwise KIQ is hanging when binding back
+ */
+ if (!amdgpu_in_reset(adev) && !adev->in_suspend) {
+ mutex_lock(&adev->srbm_mutex);
+ soc15_grbm_select(adev, adev->gfx.kiq[xcc_id].ring.me,
+ adev->gfx.kiq[xcc_id].ring.pipe,
+ adev->gfx.kiq[xcc_id].ring.queue, 0,
+ GET_INST(GC, xcc_id));
+ gfx_v9_4_3_xcc_q_fini_register(&adev->gfx.kiq[xcc_id].ring,
+ xcc_id);
+ soc15_grbm_select(adev, 0, 0, 0, 0, GET_INST(GC, xcc_id));
+ mutex_unlock(&adev->srbm_mutex);
+ }
+
+ gfx_v9_4_3_xcc_kcq_fini_register(adev, xcc_id);
+ gfx_v9_4_3_xcc_cp_enable(adev, false, xcc_id);
+}
+
+static int gfx_v9_4_3_hw_init(void *handle)
+{
+ int r;
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ gfx_v9_4_3_init_golden_registers(adev);
+
+ gfx_v9_4_3_constants_init(adev);
+
+ r = adev->gfx.rlc.funcs->resume(adev);
+ if (r)
+ return r;
+
+ r = gfx_v9_4_3_cp_resume(adev);
+ if (r)
+ return r;
+
+ return r;
+}
+
+static int gfx_v9_4_3_hw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i, num_xcc;
+
+ amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
+ amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++) {
+ gfx_v9_4_3_xcc_fini(adev, i);
+ }
+
+ return 0;
+}
+
+static int gfx_v9_4_3_suspend(void *handle)
+{
+ return gfx_v9_4_3_hw_fini(handle);
+}
+
+static int gfx_v9_4_3_resume(void *handle)
+{
+ return gfx_v9_4_3_hw_init(handle);
+}
+
+static bool gfx_v9_4_3_is_idle(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i, num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++) {
+ if (REG_GET_FIELD(RREG32_SOC15(GC, GET_INST(GC, i), regGRBM_STATUS),
+ GRBM_STATUS, GUI_ACTIVE))
+ return false;
+ }
+ return true;
+}
+
+static int gfx_v9_4_3_wait_for_idle(void *handle)
+{
+ unsigned i;
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ for (i = 0; i < adev->usec_timeout; i++) {
+ if (gfx_v9_4_3_is_idle(handle))
+ return 0;
+ udelay(1);
+ }
+ return -ETIMEDOUT;
+}
+
+static int gfx_v9_4_3_soft_reset(void *handle)
+{
+ u32 grbm_soft_reset = 0;
+ u32 tmp;
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ /* GRBM_STATUS */
+ tmp = RREG32_SOC15(GC, GET_INST(GC, 0), regGRBM_STATUS);
+ if (tmp & (GRBM_STATUS__PA_BUSY_MASK | GRBM_STATUS__SC_BUSY_MASK |
+ GRBM_STATUS__BCI_BUSY_MASK | GRBM_STATUS__SX_BUSY_MASK |
+ GRBM_STATUS__TA_BUSY_MASK | GRBM_STATUS__VGT_BUSY_MASK |
+ GRBM_STATUS__DB_BUSY_MASK | GRBM_STATUS__CB_BUSY_MASK |
+ GRBM_STATUS__GDS_BUSY_MASK | GRBM_STATUS__SPI_BUSY_MASK |
+ GRBM_STATUS__IA_BUSY_MASK | GRBM_STATUS__IA_BUSY_NO_DMA_MASK)) {
+ grbm_soft_reset = REG_SET_FIELD(grbm_soft_reset,
+ GRBM_SOFT_RESET, SOFT_RESET_CP, 1);
+ grbm_soft_reset = REG_SET_FIELD(grbm_soft_reset,
+ GRBM_SOFT_RESET, SOFT_RESET_GFX, 1);
+ }
+
+ if (tmp & (GRBM_STATUS__CP_BUSY_MASK | GRBM_STATUS__CP_COHERENCY_BUSY_MASK)) {
+ grbm_soft_reset = REG_SET_FIELD(grbm_soft_reset,
+ GRBM_SOFT_RESET, SOFT_RESET_CP, 1);
+ }
+
+ /* GRBM_STATUS2 */
+ tmp = RREG32_SOC15(GC, GET_INST(GC, 0), regGRBM_STATUS2);
+ if (REG_GET_FIELD(tmp, GRBM_STATUS2, RLC_BUSY))
+ grbm_soft_reset = REG_SET_FIELD(grbm_soft_reset,
+ GRBM_SOFT_RESET, SOFT_RESET_RLC, 1);
+
+
+ if (grbm_soft_reset) {
+ /* stop the rlc */
+ adev->gfx.rlc.funcs->stop(adev);
+
+ /* Disable MEC parsing/prefetching */
+ gfx_v9_4_3_xcc_cp_compute_enable(adev, false, 0);
+
+ if (grbm_soft_reset) {
+ tmp = RREG32_SOC15(GC, GET_INST(GC, 0), regGRBM_SOFT_RESET);
+ tmp |= grbm_soft_reset;
+ dev_info(adev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp);
+ WREG32_SOC15(GC, GET_INST(GC, 0), regGRBM_SOFT_RESET, tmp);
+ tmp = RREG32_SOC15(GC, GET_INST(GC, 0), regGRBM_SOFT_RESET);
+
+ udelay(50);
+
+ tmp &= ~grbm_soft_reset;
+ WREG32_SOC15(GC, GET_INST(GC, 0), regGRBM_SOFT_RESET, tmp);
+ tmp = RREG32_SOC15(GC, GET_INST(GC, 0), regGRBM_SOFT_RESET);
+ }
+
+ /* Wait a little for things to settle down */
+ udelay(50);
+ }
+ return 0;
+}
+
+static void gfx_v9_4_3_ring_emit_gds_switch(struct amdgpu_ring *ring,
+ uint32_t vmid,
+ uint32_t gds_base, uint32_t gds_size,
+ uint32_t gws_base, uint32_t gws_size,
+ uint32_t oa_base, uint32_t oa_size)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ /* GDS Base */
+ gfx_v9_4_3_write_data_to_reg(ring, 0, false,
+ SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regGDS_VMID0_BASE) + 2 * vmid,
+ gds_base);
+
+ /* GDS Size */
+ gfx_v9_4_3_write_data_to_reg(ring, 0, false,
+ SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regGDS_VMID0_SIZE) + 2 * vmid,
+ gds_size);
+
+ /* GWS */
+ gfx_v9_4_3_write_data_to_reg(ring, 0, false,
+ SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regGDS_GWS_VMID0) + vmid,
+ gws_size << GDS_GWS_VMID0__SIZE__SHIFT | gws_base);
+
+ /* OA */
+ gfx_v9_4_3_write_data_to_reg(ring, 0, false,
+ SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regGDS_OA_VMID0) + vmid,
+ (1 << (oa_size + oa_base)) - (1 << oa_base));
+}
+
+static int gfx_v9_4_3_early_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ adev->gfx.num_compute_rings = min(amdgpu_gfx_get_num_kcq(adev),
+ AMDGPU_MAX_COMPUTE_RINGS);
+ gfx_v9_4_3_set_kiq_pm4_funcs(adev);
+ gfx_v9_4_3_set_ring_funcs(adev);
+ gfx_v9_4_3_set_irq_funcs(adev);
+ gfx_v9_4_3_set_gds_init(adev);
+ gfx_v9_4_3_set_rlc_funcs(adev);
+
+ return gfx_v9_4_3_init_microcode(adev);
+}
+
+static int gfx_v9_4_3_late_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = amdgpu_irq_get(adev, &adev->gfx.priv_reg_irq, 0);
+ if (r)
+ return r;
+
+ r = amdgpu_irq_get(adev, &adev->gfx.priv_inst_irq, 0);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static void gfx_v9_4_3_xcc_update_sram_fgcg(struct amdgpu_device *adev,
+ bool enable, int xcc_id)
+{
+ uint32_t def, data;
+
+ if (!(adev->cg_flags & AMD_CG_SUPPORT_GFX_FGCG))
+ return;
+
+ def = data = RREG32_SOC15(GC, GET_INST(GC, xcc_id),
+ regRLC_CGTT_MGCG_OVERRIDE);
+
+ if (enable)
+ data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK;
+ else
+ data |= RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK;
+
+ if (def != data)
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id),
+ regRLC_CGTT_MGCG_OVERRIDE, data);
+
+ def = data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CLK_CNTL);
+
+ if (enable)
+ data &= ~RLC_CLK_CNTL__RLC_SRAM_CLK_GATER_OVERRIDE_MASK;
+ else
+ data |= RLC_CLK_CNTL__RLC_SRAM_CLK_GATER_OVERRIDE_MASK;
+
+ if (def != data)
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CLK_CNTL, data);
+}
+
+static void gfx_v9_4_3_xcc_update_repeater_fgcg(struct amdgpu_device *adev,
+ bool enable, int xcc_id)
+{
+ uint32_t def, data;
+
+ if (!(adev->cg_flags & AMD_CG_SUPPORT_REPEATER_FGCG))
+ return;
+
+ def = data = RREG32_SOC15(GC, GET_INST(GC, xcc_id),
+ regRLC_CGTT_MGCG_OVERRIDE);
+
+ if (enable)
+ data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_REP_FGCG_OVERRIDE_MASK;
+ else
+ data |= RLC_CGTT_MGCG_OVERRIDE__GFXIP_REP_FGCG_OVERRIDE_MASK;
+
+ if (def != data)
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id),
+ regRLC_CGTT_MGCG_OVERRIDE, data);
+}
+
+static void
+gfx_v9_4_3_xcc_update_medium_grain_clock_gating(struct amdgpu_device *adev,
+ bool enable, int xcc_id)
+{
+ uint32_t data, def;
+
+ /* It is disabled by HW by default */
+ if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
+ /* 1 - RLC_CGTT_MGCG_OVERRIDE */
+ def = data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGTT_MGCG_OVERRIDE);
+
+ data &= ~(RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK |
+ RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK |
+ RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK |
+ RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK);
+
+ if (def != data)
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGTT_MGCG_OVERRIDE, data);
+
+ /* MGLS is a global flag to control all MGLS in GFX */
+ if (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGLS) {
+ /* 2 - RLC memory Light sleep */
+ if (adev->cg_flags & AMD_CG_SUPPORT_GFX_RLC_LS) {
+ def = data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_MEM_SLP_CNTL);
+ data |= RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK;
+ if (def != data)
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_MEM_SLP_CNTL, data);
+ }
+ /* 3 - CP memory Light sleep */
+ if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CP_LS) {
+ def = data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_MEM_SLP_CNTL);
+ data |= CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
+ if (def != data)
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_MEM_SLP_CNTL, data);
+ }
+ }
+ } else {
+ /* 1 - MGCG_OVERRIDE */
+ def = data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGTT_MGCG_OVERRIDE);
+
+ data |= (RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK |
+ RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK |
+ RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK |
+ RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK);
+
+ if (def != data)
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGTT_MGCG_OVERRIDE, data);
+
+ /* 2 - disable MGLS in RLC */
+ data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_MEM_SLP_CNTL);
+ if (data & RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK) {
+ data &= ~RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK;
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_MEM_SLP_CNTL, data);
+ }
+
+ /* 3 - disable MGLS in CP */
+ data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_MEM_SLP_CNTL);
+ if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK) {
+ data &= ~CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_MEM_SLP_CNTL, data);
+ }
+ }
+
+}
+
+static void
+gfx_v9_4_3_xcc_update_coarse_grain_clock_gating(struct amdgpu_device *adev,
+ bool enable, int xcc_id)
+{
+ uint32_t def, data;
+
+ if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
+
+ def = data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGTT_MGCG_OVERRIDE);
+ /* unset CGCG override */
+ data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGCG_OVERRIDE_MASK;
+ if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS)
+ data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGLS_OVERRIDE_MASK;
+ else
+ data |= RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGLS_OVERRIDE_MASK;
+ /* update CGCG and CGLS override bits */
+ if (def != data)
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGTT_MGCG_OVERRIDE, data);
+
+ /* enable cgcg FSM(0x0000363F) */
+ def = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGCG_CGLS_CTRL);
+
+ data = (0x36
+ << RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD__SHIFT) |
+ RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK;
+ if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS)
+ data |= (0x000F << RLC_CGCG_CGLS_CTRL__CGLS_REP_COMPANSAT_DELAY__SHIFT) |
+ RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK;
+ if (def != data)
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGCG_CGLS_CTRL, data);
+
+ /* set IDLE_POLL_COUNT(0x00900100) */
+ def = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_RB_WPTR_POLL_CNTL);
+ data = (0x0100 << CP_RB_WPTR_POLL_CNTL__POLL_FREQUENCY__SHIFT) |
+ (0x0090 << CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT__SHIFT);
+ if (def != data)
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_RB_WPTR_POLL_CNTL, data);
+ } else {
+ def = data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGCG_CGLS_CTRL);
+ /* reset CGCG/CGLS bits */
+ data &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK | RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
+ /* disable cgcg and cgls in FSM */
+ if (def != data)
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGCG_CGLS_CTRL, data);
+ }
+
+}
-const struct amdgpu_rlc_funcs gfx_v9_4_3_rlc_funcs = {
+static int gfx_v9_4_3_xcc_update_gfx_clock_gating(struct amdgpu_device *adev,
+ bool enable, int xcc_id)
+{
+ amdgpu_gfx_rlc_enter_safe_mode(adev, xcc_id);
+
+ if (enable) {
+ /* FGCG */
+ gfx_v9_4_3_xcc_update_sram_fgcg(adev, enable, xcc_id);
+ gfx_v9_4_3_xcc_update_repeater_fgcg(adev, enable, xcc_id);
+
+ /* CGCG/CGLS should be enabled after MGCG/MGLS
+ * === MGCG + MGLS ===
+ */
+ gfx_v9_4_3_xcc_update_medium_grain_clock_gating(adev, enable,
+ xcc_id);
+ /* === CGCG + CGLS === */
+ gfx_v9_4_3_xcc_update_coarse_grain_clock_gating(adev, enable,
+ xcc_id);
+ } else {
+ /* CGCG/CGLS should be disabled before MGCG/MGLS
+ * === CGCG + CGLS ===
+ */
+ gfx_v9_4_3_xcc_update_coarse_grain_clock_gating(adev, enable,
+ xcc_id);
+ /* === MGCG + MGLS === */
+ gfx_v9_4_3_xcc_update_medium_grain_clock_gating(adev, enable,
+ xcc_id);
+
+ /* FGCG */
+ gfx_v9_4_3_xcc_update_sram_fgcg(adev, enable, xcc_id);
+ gfx_v9_4_3_xcc_update_repeater_fgcg(adev, enable, xcc_id);
+ }
+
+ amdgpu_gfx_rlc_exit_safe_mode(adev, xcc_id);
+
+ return 0;
+}
+
+static const struct amdgpu_rlc_funcs gfx_v9_4_3_rlc_funcs = {
.is_rlc_enabled = gfx_v9_4_3_is_rlc_enabled,
- .set_safe_mode = gfx_v9_4_3_set_safe_mode,
- .unset_safe_mode = gfx_v9_4_3_unset_safe_mode,
+ .set_safe_mode = gfx_v9_4_3_xcc_set_safe_mode,
+ .unset_safe_mode = gfx_v9_4_3_xcc_unset_safe_mode,
.init = gfx_v9_4_3_rlc_init,
.resume = gfx_v9_4_3_rlc_resume,
.stop = gfx_v9_4_3_rlc_stop,
@@ -428,3 +2386,1982 @@ const struct amdgpu_rlc_funcs gfx_v9_4_3_rlc_funcs = {
.update_spm_vmid = gfx_v9_4_3_update_spm_vmid,
.is_rlcg_access_range = gfx_v9_4_3_is_rlcg_access_range,
};
+
+static int gfx_v9_4_3_set_powergating_state(void *handle,
+ enum amd_powergating_state state)
+{
+ return 0;
+}
+
+static int gfx_v9_4_3_set_clockgating_state(void *handle,
+ enum amd_clockgating_state state)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i, num_xcc;
+
+ if (amdgpu_sriov_vf(adev))
+ return 0;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ switch (adev->ip_versions[GC_HWIP][0]) {
+ case IP_VERSION(9, 4, 3):
+ for (i = 0; i < num_xcc; i++)
+ gfx_v9_4_3_xcc_update_gfx_clock_gating(
+ adev, state == AMD_CG_STATE_GATE, i);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void gfx_v9_4_3_get_clockgating_state(void *handle, u64 *flags)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int data;
+
+ if (amdgpu_sriov_vf(adev))
+ *flags = 0;
+
+ /* AMD_CG_SUPPORT_GFX_MGCG */
+ data = RREG32_KIQ(SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regRLC_CGTT_MGCG_OVERRIDE));
+ if (!(data & RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK))
+ *flags |= AMD_CG_SUPPORT_GFX_MGCG;
+
+ /* AMD_CG_SUPPORT_GFX_CGCG */
+ data = RREG32_KIQ(SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regRLC_CGCG_CGLS_CTRL));
+ if (data & RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK)
+ *flags |= AMD_CG_SUPPORT_GFX_CGCG;
+
+ /* AMD_CG_SUPPORT_GFX_CGLS */
+ if (data & RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK)
+ *flags |= AMD_CG_SUPPORT_GFX_CGLS;
+
+ /* AMD_CG_SUPPORT_GFX_RLC_LS */
+ data = RREG32_KIQ(SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regRLC_MEM_SLP_CNTL));
+ if (data & RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK)
+ *flags |= AMD_CG_SUPPORT_GFX_RLC_LS | AMD_CG_SUPPORT_GFX_MGLS;
+
+ /* AMD_CG_SUPPORT_GFX_CP_LS */
+ data = RREG32_KIQ(SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regCP_MEM_SLP_CNTL));
+ if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK)
+ *flags |= AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_MGLS;
+}
+
+static void gfx_v9_4_3_ring_emit_hdp_flush(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ u32 ref_and_mask, reg_mem_engine;
+ const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
+
+ if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
+ switch (ring->me) {
+ case 1:
+ ref_and_mask = nbio_hf_reg->ref_and_mask_cp2 << ring->pipe;
+ break;
+ case 2:
+ ref_and_mask = nbio_hf_reg->ref_and_mask_cp6 << ring->pipe;
+ break;
+ default:
+ return;
+ }
+ reg_mem_engine = 0;
+ } else {
+ ref_and_mask = nbio_hf_reg->ref_and_mask_cp0;
+ reg_mem_engine = 1; /* pfp */
+ }
+
+ gfx_v9_4_3_wait_reg_mem(ring, reg_mem_engine, 0, 1,
+ adev->nbio.funcs->get_hdp_flush_req_offset(adev),
+ adev->nbio.funcs->get_hdp_flush_done_offset(adev),
+ ref_and_mask, ref_and_mask, 0x20);
+}
+
+static void gfx_v9_4_3_ring_emit_ib_compute(struct amdgpu_ring *ring,
+ struct amdgpu_job *job,
+ struct amdgpu_ib *ib,
+ uint32_t flags)
+{
+ unsigned vmid = AMDGPU_JOB_GET_VMID(job);
+ u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24);
+
+ /* Currently, there is a high possibility to get wave ID mismatch
+ * between ME and GDS, leading to a hw deadlock, because ME generates
+ * different wave IDs than the GDS expects. This situation happens
+ * randomly when at least 5 compute pipes use GDS ordered append.
+ * The wave IDs generated by ME are also wrong after suspend/resume.
+ * Those are probably bugs somewhere else in the kernel driver.
+ *
+ * Writing GDS_COMPUTE_MAX_WAVE_ID resets wave ID counters in ME and
+ * GDS to 0 for this ring (me/pipe).
+ */
+ if (ib->flags & AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID) {
+ amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
+ amdgpu_ring_write(ring, regGDS_COMPUTE_MAX_WAVE_ID);
+ amdgpu_ring_write(ring, ring->adev->gds.gds_compute_max_wave_id);
+ }
+
+ amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
+ BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+ amdgpu_ring_write(ring,
+#ifdef __BIG_ENDIAN
+ (2 << 0) |
+#endif
+ lower_32_bits(ib->gpu_addr));
+ amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
+ amdgpu_ring_write(ring, control);
+}
+
+static void gfx_v9_4_3_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
+ u64 seq, unsigned flags)
+{
+ bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
+ bool int_sel = flags & AMDGPU_FENCE_FLAG_INT;
+ bool writeback = flags & AMDGPU_FENCE_FLAG_TC_WB_ONLY;
+
+ /* RELEASE_MEM - flush caches, send int */
+ amdgpu_ring_write(ring, PACKET3(PACKET3_RELEASE_MEM, 6));
+ amdgpu_ring_write(ring, ((writeback ? (EOP_TC_WB_ACTION_EN |
+ EOP_TC_NC_ACTION_EN) :
+ (EOP_TCL1_ACTION_EN |
+ EOP_TC_ACTION_EN |
+ EOP_TC_WB_ACTION_EN |
+ EOP_TC_MD_ACTION_EN)) |
+ EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
+ EVENT_INDEX(5)));
+ amdgpu_ring_write(ring, DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0));
+
+ /*
+ * the address should be Qword aligned if 64bit write, Dword
+ * aligned if only send 32bit data low (discard data high)
+ */
+ if (write64bit)
+ BUG_ON(addr & 0x7);
+ else
+ BUG_ON(addr & 0x3);
+ amdgpu_ring_write(ring, lower_32_bits(addr));
+ amdgpu_ring_write(ring, upper_32_bits(addr));
+ amdgpu_ring_write(ring, lower_32_bits(seq));
+ amdgpu_ring_write(ring, upper_32_bits(seq));
+ amdgpu_ring_write(ring, 0);
+}
+
+static void gfx_v9_4_3_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
+{
+ int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
+ uint32_t seq = ring->fence_drv.sync_seq;
+ uint64_t addr = ring->fence_drv.gpu_addr;
+
+ gfx_v9_4_3_wait_reg_mem(ring, usepfp, 1, 0,
+ lower_32_bits(addr), upper_32_bits(addr),
+ seq, 0xffffffff, 4);
+}
+
+static void gfx_v9_4_3_ring_emit_vm_flush(struct amdgpu_ring *ring,
+ unsigned vmid, uint64_t pd_addr)
+{
+ amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
+}
+
+static u64 gfx_v9_4_3_ring_get_rptr_compute(struct amdgpu_ring *ring)
+{
+ return ring->adev->wb.wb[ring->rptr_offs]; /* gfx9 hardware is 32bit rptr */
+}
+
+static u64 gfx_v9_4_3_ring_get_wptr_compute(struct amdgpu_ring *ring)
+{
+ u64 wptr;
+
+ /* XXX check if swapping is necessary on BE */
+ if (ring->use_doorbell)
+ wptr = atomic64_read((atomic64_t *)&ring->adev->wb.wb[ring->wptr_offs]);
+ else
+ BUG();
+ return wptr;
+}
+
+static void gfx_v9_4_3_ring_set_wptr_compute(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ /* XXX check if swapping is necessary on BE */
+ if (ring->use_doorbell) {
+ atomic64_set((atomic64_t *)&adev->wb.wb[ring->wptr_offs], ring->wptr);
+ WDOORBELL64(ring->doorbell_index, ring->wptr);
+ } else {
+ BUG(); /* only DOORBELL method supported on gfx9 now */
+ }
+}
+
+static void gfx_v9_4_3_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
+ u64 seq, unsigned int flags)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ /* we only allocate 32bit for each seq wb address */
+ BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
+
+ /* write fence seq to the "addr" */
+ amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+ amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+ WRITE_DATA_DST_SEL(5) | WR_CONFIRM));
+ amdgpu_ring_write(ring, lower_32_bits(addr));
+ amdgpu_ring_write(ring, upper_32_bits(addr));
+ amdgpu_ring_write(ring, lower_32_bits(seq));
+
+ if (flags & AMDGPU_FENCE_FLAG_INT) {
+ /* set register to trigger INT */
+ amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+ amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+ WRITE_DATA_DST_SEL(0) | WR_CONFIRM));
+ amdgpu_ring_write(ring, SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regCPC_INT_STATUS));
+ amdgpu_ring_write(ring, 0);
+ amdgpu_ring_write(ring, 0x20000000); /* src_id is 178 */
+ }
+}
+
+static void gfx_v9_4_3_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg,
+ uint32_t reg_val_offs)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ amdgpu_ring_write(ring, PACKET3(PACKET3_COPY_DATA, 4));
+ amdgpu_ring_write(ring, 0 | /* src: register*/
+ (5 << 8) | /* dst: memory */
+ (1 << 20)); /* write confirm */
+ amdgpu_ring_write(ring, reg);
+ amdgpu_ring_write(ring, 0);
+ amdgpu_ring_write(ring, lower_32_bits(adev->wb.gpu_addr +
+ reg_val_offs * 4));
+ amdgpu_ring_write(ring, upper_32_bits(adev->wb.gpu_addr +
+ reg_val_offs * 4));
+}
+
+static void gfx_v9_4_3_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg,
+ uint32_t val)
+{
+ uint32_t cmd = 0;
+
+ switch (ring->funcs->type) {
+ case AMDGPU_RING_TYPE_GFX:
+ cmd = WRITE_DATA_ENGINE_SEL(1) | WR_CONFIRM;
+ break;
+ case AMDGPU_RING_TYPE_KIQ:
+ cmd = (1 << 16); /* no inc addr */
+ break;
+ default:
+ cmd = WR_CONFIRM;
+ break;
+ }
+ amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+ amdgpu_ring_write(ring, cmd);
+ amdgpu_ring_write(ring, reg);
+ amdgpu_ring_write(ring, 0);
+ amdgpu_ring_write(ring, val);
+}
+
+static void gfx_v9_4_3_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
+ uint32_t val, uint32_t mask)
+{
+ gfx_v9_4_3_wait_reg_mem(ring, 0, 0, 0, reg, 0, val, mask, 0x20);
+}
+
+static void gfx_v9_4_3_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
+ uint32_t reg0, uint32_t reg1,
+ uint32_t ref, uint32_t mask)
+{
+ amdgpu_ring_emit_reg_write_reg_wait_helper(ring, reg0, reg1,
+ ref, mask);
+}
+
+static void gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
+ struct amdgpu_device *adev, int me, int pipe,
+ enum amdgpu_interrupt_state state, int xcc_id)
+{
+ u32 mec_int_cntl, mec_int_cntl_reg;
+
+ /*
+ * amdgpu controls only the first MEC. That's why this function only
+ * handles the setting of interrupts for this specific MEC. All other
+ * pipes' interrupts are set by amdkfd.
+ */
+
+ if (me == 1) {
+ switch (pipe) {
+ case 0:
+ mec_int_cntl_reg = SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_ME1_PIPE0_INT_CNTL);
+ break;
+ case 1:
+ mec_int_cntl_reg = SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_ME1_PIPE1_INT_CNTL);
+ break;
+ case 2:
+ mec_int_cntl_reg = SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_ME1_PIPE2_INT_CNTL);
+ break;
+ case 3:
+ mec_int_cntl_reg = SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_ME1_PIPE3_INT_CNTL);
+ break;
+ default:
+ DRM_DEBUG("invalid pipe %d\n", pipe);
+ return;
+ }
+ } else {
+ DRM_DEBUG("invalid me %d\n", me);
+ return;
+ }
+
+ switch (state) {
+ case AMDGPU_IRQ_STATE_DISABLE:
+ mec_int_cntl = RREG32(mec_int_cntl_reg);
+ mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL,
+ TIME_STAMP_INT_ENABLE, 0);
+ WREG32(mec_int_cntl_reg, mec_int_cntl);
+ break;
+ case AMDGPU_IRQ_STATE_ENABLE:
+ mec_int_cntl = RREG32(mec_int_cntl_reg);
+ mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL,
+ TIME_STAMP_INT_ENABLE, 1);
+ WREG32(mec_int_cntl_reg, mec_int_cntl);
+ break;
+ default:
+ break;
+ }
+}
+
+static int gfx_v9_4_3_set_priv_reg_fault_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ unsigned type,
+ enum amdgpu_interrupt_state state)
+{
+ int i, num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ switch (state) {
+ case AMDGPU_IRQ_STATE_DISABLE:
+ case AMDGPU_IRQ_STATE_ENABLE:
+ for (i = 0; i < num_xcc; i++)
+ WREG32_FIELD15_PREREG(GC, GET_INST(GC, i), CP_INT_CNTL_RING0,
+ PRIV_REG_INT_ENABLE,
+ state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int gfx_v9_4_3_set_priv_inst_fault_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ unsigned type,
+ enum amdgpu_interrupt_state state)
+{
+ int i, num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ switch (state) {
+ case AMDGPU_IRQ_STATE_DISABLE:
+ case AMDGPU_IRQ_STATE_ENABLE:
+ for (i = 0; i < num_xcc; i++)
+ WREG32_FIELD15_PREREG(GC, GET_INST(GC, i), CP_INT_CNTL_RING0,
+ PRIV_INSTR_INT_ENABLE,
+ state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int gfx_v9_4_3_set_eop_interrupt_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *src,
+ unsigned type,
+ enum amdgpu_interrupt_state state)
+{
+ int i, num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++) {
+ switch (type) {
+ case AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP:
+ gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
+ adev, 1, 0, state, i);
+ break;
+ case AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE1_EOP:
+ gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
+ adev, 1, 1, state, i);
+ break;
+ case AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE2_EOP:
+ gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
+ adev, 1, 2, state, i);
+ break;
+ case AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE3_EOP:
+ gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
+ adev, 1, 3, state, i);
+ break;
+ case AMDGPU_CP_IRQ_COMPUTE_MEC2_PIPE0_EOP:
+ gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
+ adev, 2, 0, state, i);
+ break;
+ case AMDGPU_CP_IRQ_COMPUTE_MEC2_PIPE1_EOP:
+ gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
+ adev, 2, 1, state, i);
+ break;
+ case AMDGPU_CP_IRQ_COMPUTE_MEC2_PIPE2_EOP:
+ gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
+ adev, 2, 2, state, i);
+ break;
+ case AMDGPU_CP_IRQ_COMPUTE_MEC2_PIPE3_EOP:
+ gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
+ adev, 2, 3, state, i);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int gfx_v9_4_3_eop_irq(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ int i, xcc_id;
+ u8 me_id, pipe_id, queue_id;
+ struct amdgpu_ring *ring;
+
+ DRM_DEBUG("IH: CP EOP\n");
+ me_id = (entry->ring_id & 0x0c) >> 2;
+ pipe_id = (entry->ring_id & 0x03) >> 0;
+ queue_id = (entry->ring_id & 0x70) >> 4;
+
+ xcc_id = gfx_v9_4_3_ih_to_xcc_inst(adev, entry->node_id);
+
+ if (xcc_id == -EINVAL)
+ return -EINVAL;
+
+ switch (me_id) {
+ case 0:
+ case 1:
+ case 2:
+ for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+ ring = &adev->gfx.compute_ring
+ [i +
+ xcc_id * adev->gfx.num_compute_rings];
+ /* Per-queue interrupt is supported for MEC starting from VI.
+ * The interrupt can only be enabled/disabled per pipe instead of per queue.
+ */
+
+ if ((ring->me == me_id) && (ring->pipe == pipe_id) && (ring->queue == queue_id))
+ amdgpu_fence_process(ring);
+ }
+ break;
+ }
+ return 0;
+}
+
+static void gfx_v9_4_3_fault(struct amdgpu_device *adev,
+ struct amdgpu_iv_entry *entry)
+{
+ u8 me_id, pipe_id, queue_id;
+ struct amdgpu_ring *ring;
+ int i, xcc_id;
+
+ me_id = (entry->ring_id & 0x0c) >> 2;
+ pipe_id = (entry->ring_id & 0x03) >> 0;
+ queue_id = (entry->ring_id & 0x70) >> 4;
+
+ xcc_id = gfx_v9_4_3_ih_to_xcc_inst(adev, entry->node_id);
+
+ if (xcc_id == -EINVAL)
+ return;
+
+ switch (me_id) {
+ case 0:
+ case 1:
+ case 2:
+ for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+ ring = &adev->gfx.compute_ring
+ [i +
+ xcc_id * adev->gfx.num_compute_rings];
+ if (ring->me == me_id && ring->pipe == pipe_id &&
+ ring->queue == queue_id)
+ drm_sched_fault(&ring->sched);
+ }
+ break;
+ }
+}
+
+static int gfx_v9_4_3_priv_reg_irq(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ DRM_ERROR("Illegal register access in command stream\n");
+ gfx_v9_4_3_fault(adev, entry);
+ return 0;
+}
+
+static int gfx_v9_4_3_priv_inst_irq(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ DRM_ERROR("Illegal instruction in command stream\n");
+ gfx_v9_4_3_fault(adev, entry);
+ return 0;
+}
+
+static void gfx_v9_4_3_emit_mem_sync(struct amdgpu_ring *ring)
+{
+ const unsigned int cp_coher_cntl =
+ PACKET3_ACQUIRE_MEM_CP_COHER_CNTL_SH_ICACHE_ACTION_ENA(1) |
+ PACKET3_ACQUIRE_MEM_CP_COHER_CNTL_SH_KCACHE_ACTION_ENA(1) |
+ PACKET3_ACQUIRE_MEM_CP_COHER_CNTL_TC_ACTION_ENA(1) |
+ PACKET3_ACQUIRE_MEM_CP_COHER_CNTL_TCL1_ACTION_ENA(1) |
+ PACKET3_ACQUIRE_MEM_CP_COHER_CNTL_TC_WB_ACTION_ENA(1);
+
+ /* ACQUIRE_MEM -make one or more surfaces valid for use by the subsequent operations */
+ amdgpu_ring_write(ring, PACKET3(PACKET3_ACQUIRE_MEM, 5));
+ amdgpu_ring_write(ring, cp_coher_cntl); /* CP_COHER_CNTL */
+ amdgpu_ring_write(ring, 0xffffffff); /* CP_COHER_SIZE */
+ amdgpu_ring_write(ring, 0xffffff); /* CP_COHER_SIZE_HI */
+ amdgpu_ring_write(ring, 0); /* CP_COHER_BASE */
+ amdgpu_ring_write(ring, 0); /* CP_COHER_BASE_HI */
+ amdgpu_ring_write(ring, 0x0000000A); /* POLL_INTERVAL */
+}
+
+static void gfx_v9_4_3_emit_wave_limit_cs(struct amdgpu_ring *ring,
+ uint32_t pipe, bool enable)
+{
+ struct amdgpu_device *adev = ring->adev;
+ uint32_t val;
+ uint32_t wcl_cs_reg;
+
+ /* regSPI_WCL_PIPE_PERCENT_CS[0-7]_DEFAULT values are same */
+ val = enable ? 0x1 : 0x7f;
+
+ switch (pipe) {
+ case 0:
+ wcl_cs_reg = SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regSPI_WCL_PIPE_PERCENT_CS0);
+ break;
+ case 1:
+ wcl_cs_reg = SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regSPI_WCL_PIPE_PERCENT_CS1);
+ break;
+ case 2:
+ wcl_cs_reg = SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regSPI_WCL_PIPE_PERCENT_CS2);
+ break;
+ case 3:
+ wcl_cs_reg = SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regSPI_WCL_PIPE_PERCENT_CS3);
+ break;
+ default:
+ DRM_DEBUG("invalid pipe %d\n", pipe);
+ return;
+ }
+
+ amdgpu_ring_emit_wreg(ring, wcl_cs_reg, val);
+
+}
+static void gfx_v9_4_3_emit_wave_limit(struct amdgpu_ring *ring, bool enable)
+{
+ struct amdgpu_device *adev = ring->adev;
+ uint32_t val;
+ int i;
+
+ /* regSPI_WCL_PIPE_PERCENT_GFX is 7 bit multiplier register to limit
+ * number of gfx waves. Setting 5 bit will make sure gfx only gets
+ * around 25% of gpu resources.
+ */
+ val = enable ? 0x1f : 0x07ffffff;
+ amdgpu_ring_emit_wreg(ring,
+ SOC15_REG_OFFSET(GC, GET_INST(GC, 0), regSPI_WCL_PIPE_PERCENT_GFX),
+ val);
+
+ /* Restrict waves for normal/low priority compute queues as well
+ * to get best QoS for high priority compute jobs.
+ *
+ * amdgpu controls only 1st ME(0-3 CS pipes).
+ */
+ for (i = 0; i < adev->gfx.mec.num_pipe_per_mec; i++) {
+ if (i != ring->pipe)
+ gfx_v9_4_3_emit_wave_limit_cs(ring, i, enable);
+
+ }
+}
+
+enum amdgpu_gfx_cp_ras_mem_id {
+ AMDGPU_GFX_CP_MEM1 = 1,
+ AMDGPU_GFX_CP_MEM2,
+ AMDGPU_GFX_CP_MEM3,
+ AMDGPU_GFX_CP_MEM4,
+ AMDGPU_GFX_CP_MEM5,
+};
+
+enum amdgpu_gfx_gcea_ras_mem_id {
+ AMDGPU_GFX_GCEA_IOWR_CMDMEM = 4,
+ AMDGPU_GFX_GCEA_IORD_CMDMEM,
+ AMDGPU_GFX_GCEA_GMIWR_CMDMEM,
+ AMDGPU_GFX_GCEA_GMIRD_CMDMEM,
+ AMDGPU_GFX_GCEA_DRAMWR_CMDMEM,
+ AMDGPU_GFX_GCEA_DRAMRD_CMDMEM,
+ AMDGPU_GFX_GCEA_MAM_DMEM0,
+ AMDGPU_GFX_GCEA_MAM_DMEM1,
+ AMDGPU_GFX_GCEA_MAM_DMEM2,
+ AMDGPU_GFX_GCEA_MAM_DMEM3,
+ AMDGPU_GFX_GCEA_MAM_AMEM0,
+ AMDGPU_GFX_GCEA_MAM_AMEM1,
+ AMDGPU_GFX_GCEA_MAM_AMEM2,
+ AMDGPU_GFX_GCEA_MAM_AMEM3,
+ AMDGPU_GFX_GCEA_MAM_AFLUSH_BUFFER,
+ AMDGPU_GFX_GCEA_WRET_TAGMEM,
+ AMDGPU_GFX_GCEA_RRET_TAGMEM,
+ AMDGPU_GFX_GCEA_IOWR_DATAMEM,
+ AMDGPU_GFX_GCEA_GMIWR_DATAMEM,
+ AMDGPU_GFX_GCEA_DRAM_DATAMEM,
+};
+
+enum amdgpu_gfx_gc_cane_ras_mem_id {
+ AMDGPU_GFX_GC_CANE_MEM0 = 0,
+};
+
+enum amdgpu_gfx_gcutcl2_ras_mem_id {
+ AMDGPU_GFX_GCUTCL2_MEM2P512X95 = 160,
+};
+
+enum amdgpu_gfx_gds_ras_mem_id {
+ AMDGPU_GFX_GDS_MEM0 = 0,
+};
+
+enum amdgpu_gfx_lds_ras_mem_id {
+ AMDGPU_GFX_LDS_BANK0 = 0,
+ AMDGPU_GFX_LDS_BANK1,
+ AMDGPU_GFX_LDS_BANK2,
+ AMDGPU_GFX_LDS_BANK3,
+ AMDGPU_GFX_LDS_BANK4,
+ AMDGPU_GFX_LDS_BANK5,
+ AMDGPU_GFX_LDS_BANK6,
+ AMDGPU_GFX_LDS_BANK7,
+ AMDGPU_GFX_LDS_BANK8,
+ AMDGPU_GFX_LDS_BANK9,
+ AMDGPU_GFX_LDS_BANK10,
+ AMDGPU_GFX_LDS_BANK11,
+ AMDGPU_GFX_LDS_BANK12,
+ AMDGPU_GFX_LDS_BANK13,
+ AMDGPU_GFX_LDS_BANK14,
+ AMDGPU_GFX_LDS_BANK15,
+ AMDGPU_GFX_LDS_BANK16,
+ AMDGPU_GFX_LDS_BANK17,
+ AMDGPU_GFX_LDS_BANK18,
+ AMDGPU_GFX_LDS_BANK19,
+ AMDGPU_GFX_LDS_BANK20,
+ AMDGPU_GFX_LDS_BANK21,
+ AMDGPU_GFX_LDS_BANK22,
+ AMDGPU_GFX_LDS_BANK23,
+ AMDGPU_GFX_LDS_BANK24,
+ AMDGPU_GFX_LDS_BANK25,
+ AMDGPU_GFX_LDS_BANK26,
+ AMDGPU_GFX_LDS_BANK27,
+ AMDGPU_GFX_LDS_BANK28,
+ AMDGPU_GFX_LDS_BANK29,
+ AMDGPU_GFX_LDS_BANK30,
+ AMDGPU_GFX_LDS_BANK31,
+ AMDGPU_GFX_LDS_SP_BUFFER_A,
+ AMDGPU_GFX_LDS_SP_BUFFER_B,
+};
+
+enum amdgpu_gfx_rlc_ras_mem_id {
+ AMDGPU_GFX_RLC_GPMF32 = 1,
+ AMDGPU_GFX_RLC_RLCVF32,
+ AMDGPU_GFX_RLC_SCRATCH,
+ AMDGPU_GFX_RLC_SRM_ARAM,
+ AMDGPU_GFX_RLC_SRM_DRAM,
+ AMDGPU_GFX_RLC_TCTAG,
+ AMDGPU_GFX_RLC_SPM_SE,
+ AMDGPU_GFX_RLC_SPM_GRBMT,
+};
+
+enum amdgpu_gfx_sp_ras_mem_id {
+ AMDGPU_GFX_SP_SIMDID0 = 0,
+};
+
+enum amdgpu_gfx_spi_ras_mem_id {
+ AMDGPU_GFX_SPI_MEM0 = 0,
+ AMDGPU_GFX_SPI_MEM1,
+ AMDGPU_GFX_SPI_MEM2,
+ AMDGPU_GFX_SPI_MEM3,
+};
+
+enum amdgpu_gfx_sqc_ras_mem_id {
+ AMDGPU_GFX_SQC_INST_CACHE_A = 100,
+ AMDGPU_GFX_SQC_INST_CACHE_B = 101,
+ AMDGPU_GFX_SQC_INST_CACHE_TAG_A = 102,
+ AMDGPU_GFX_SQC_INST_CACHE_TAG_B = 103,
+ AMDGPU_GFX_SQC_INST_CACHE_MISS_FIFO_A = 104,
+ AMDGPU_GFX_SQC_INST_CACHE_MISS_FIFO_B = 105,
+ AMDGPU_GFX_SQC_INST_CACHE_GATCL1_MISS_FIFO_A = 106,
+ AMDGPU_GFX_SQC_INST_CACHE_GATCL1_MISS_FIFO_B = 107,
+ AMDGPU_GFX_SQC_DATA_CACHE_A = 200,
+ AMDGPU_GFX_SQC_DATA_CACHE_B = 201,
+ AMDGPU_GFX_SQC_DATA_CACHE_TAG_A = 202,
+ AMDGPU_GFX_SQC_DATA_CACHE_TAG_B = 203,
+ AMDGPU_GFX_SQC_DATA_CACHE_MISS_FIFO_A = 204,
+ AMDGPU_GFX_SQC_DATA_CACHE_MISS_FIFO_B = 205,
+ AMDGPU_GFX_SQC_DATA_CACHE_HIT_FIFO_A = 206,
+ AMDGPU_GFX_SQC_DATA_CACHE_HIT_FIFO_B = 207,
+ AMDGPU_GFX_SQC_DIRTY_BIT_A = 208,
+ AMDGPU_GFX_SQC_DIRTY_BIT_B = 209,
+ AMDGPU_GFX_SQC_WRITE_DATA_BUFFER_CU0 = 210,
+ AMDGPU_GFX_SQC_WRITE_DATA_BUFFER_CU1 = 211,
+ AMDGPU_GFX_SQC_UTCL1_MISS_LFIFO_DATA_CACHE_A = 212,
+ AMDGPU_GFX_SQC_UTCL1_MISS_LFIFO_DATA_CACHE_B = 213,
+ AMDGPU_GFX_SQC_UTCL1_MISS_LFIFO_INST_CACHE = 108,
+};
+
+enum amdgpu_gfx_sq_ras_mem_id {
+ AMDGPU_GFX_SQ_SGPR_MEM0 = 0,
+ AMDGPU_GFX_SQ_SGPR_MEM1,
+ AMDGPU_GFX_SQ_SGPR_MEM2,
+ AMDGPU_GFX_SQ_SGPR_MEM3,
+};
+
+enum amdgpu_gfx_ta_ras_mem_id {
+ AMDGPU_GFX_TA_FS_AFIFO_RAM_LO = 1,
+ AMDGPU_GFX_TA_FS_AFIFO_RAM_HI,
+ AMDGPU_GFX_TA_FS_CFIFO_RAM,
+ AMDGPU_GFX_TA_FSX_LFIFO,
+ AMDGPU_GFX_TA_FS_DFIFO_RAM,
+};
+
+enum amdgpu_gfx_tcc_ras_mem_id {
+ AMDGPU_GFX_TCC_MEM1 = 1,
+};
+
+enum amdgpu_gfx_tca_ras_mem_id {
+ AMDGPU_GFX_TCA_MEM1 = 1,
+};
+
+enum amdgpu_gfx_tci_ras_mem_id {
+ AMDGPU_GFX_TCIW_MEM = 1,
+};
+
+enum amdgpu_gfx_tcp_ras_mem_id {
+ AMDGPU_GFX_TCP_LFIFO0 = 1,
+ AMDGPU_GFX_TCP_SET0BANK0_RAM,
+ AMDGPU_GFX_TCP_SET0BANK1_RAM,
+ AMDGPU_GFX_TCP_SET0BANK2_RAM,
+ AMDGPU_GFX_TCP_SET0BANK3_RAM,
+ AMDGPU_GFX_TCP_SET1BANK0_RAM,
+ AMDGPU_GFX_TCP_SET1BANK1_RAM,
+ AMDGPU_GFX_TCP_SET1BANK2_RAM,
+ AMDGPU_GFX_TCP_SET1BANK3_RAM,
+ AMDGPU_GFX_TCP_SET2BANK0_RAM,
+ AMDGPU_GFX_TCP_SET2BANK1_RAM,
+ AMDGPU_GFX_TCP_SET2BANK2_RAM,
+ AMDGPU_GFX_TCP_SET2BANK3_RAM,
+ AMDGPU_GFX_TCP_SET3BANK0_RAM,
+ AMDGPU_GFX_TCP_SET3BANK1_RAM,
+ AMDGPU_GFX_TCP_SET3BANK2_RAM,
+ AMDGPU_GFX_TCP_SET3BANK3_RAM,
+ AMDGPU_GFX_TCP_VM_FIFO,
+ AMDGPU_GFX_TCP_DB_TAGRAM0,
+ AMDGPU_GFX_TCP_DB_TAGRAM1,
+ AMDGPU_GFX_TCP_DB_TAGRAM2,
+ AMDGPU_GFX_TCP_DB_TAGRAM3,
+ AMDGPU_GFX_TCP_UTCL1_LFIFO_PROBE0,
+ AMDGPU_GFX_TCP_UTCL1_LFIFO_PROBE1,
+ AMDGPU_GFX_TCP_CMD_FIFO,
+};
+
+enum amdgpu_gfx_td_ras_mem_id {
+ AMDGPU_GFX_TD_UTD_CS_FIFO_MEM = 1,
+ AMDGPU_GFX_TD_UTD_SS_FIFO_LO_MEM,
+ AMDGPU_GFX_TD_UTD_SS_FIFO_HI_MEM,
+};
+
+enum amdgpu_gfx_tcx_ras_mem_id {
+ AMDGPU_GFX_TCX_FIFOD0 = 0,
+ AMDGPU_GFX_TCX_FIFOD1,
+ AMDGPU_GFX_TCX_FIFOD2,
+ AMDGPU_GFX_TCX_FIFOD3,
+ AMDGPU_GFX_TCX_FIFOD4,
+ AMDGPU_GFX_TCX_FIFOD5,
+ AMDGPU_GFX_TCX_FIFOD6,
+ AMDGPU_GFX_TCX_FIFOD7,
+ AMDGPU_GFX_TCX_FIFOB0,
+ AMDGPU_GFX_TCX_FIFOB1,
+ AMDGPU_GFX_TCX_FIFOB2,
+ AMDGPU_GFX_TCX_FIFOB3,
+ AMDGPU_GFX_TCX_FIFOB4,
+ AMDGPU_GFX_TCX_FIFOB5,
+ AMDGPU_GFX_TCX_FIFOB6,
+ AMDGPU_GFX_TCX_FIFOB7,
+ AMDGPU_GFX_TCX_FIFOA0,
+ AMDGPU_GFX_TCX_FIFOA1,
+ AMDGPU_GFX_TCX_FIFOA2,
+ AMDGPU_GFX_TCX_FIFOA3,
+ AMDGPU_GFX_TCX_FIFOA4,
+ AMDGPU_GFX_TCX_FIFOA5,
+ AMDGPU_GFX_TCX_FIFOA6,
+ AMDGPU_GFX_TCX_FIFOA7,
+ AMDGPU_GFX_TCX_CFIFO0,
+ AMDGPU_GFX_TCX_CFIFO1,
+ AMDGPU_GFX_TCX_CFIFO2,
+ AMDGPU_GFX_TCX_CFIFO3,
+ AMDGPU_GFX_TCX_CFIFO4,
+ AMDGPU_GFX_TCX_CFIFO5,
+ AMDGPU_GFX_TCX_CFIFO6,
+ AMDGPU_GFX_TCX_CFIFO7,
+ AMDGPU_GFX_TCX_FIFO_ACKB0,
+ AMDGPU_GFX_TCX_FIFO_ACKB1,
+ AMDGPU_GFX_TCX_FIFO_ACKB2,
+ AMDGPU_GFX_TCX_FIFO_ACKB3,
+ AMDGPU_GFX_TCX_FIFO_ACKB4,
+ AMDGPU_GFX_TCX_FIFO_ACKB5,
+ AMDGPU_GFX_TCX_FIFO_ACKB6,
+ AMDGPU_GFX_TCX_FIFO_ACKB7,
+ AMDGPU_GFX_TCX_FIFO_ACKD0,
+ AMDGPU_GFX_TCX_FIFO_ACKD1,
+ AMDGPU_GFX_TCX_FIFO_ACKD2,
+ AMDGPU_GFX_TCX_FIFO_ACKD3,
+ AMDGPU_GFX_TCX_FIFO_ACKD4,
+ AMDGPU_GFX_TCX_FIFO_ACKD5,
+ AMDGPU_GFX_TCX_FIFO_ACKD6,
+ AMDGPU_GFX_TCX_FIFO_ACKD7,
+ AMDGPU_GFX_TCX_DST_FIFOA0,
+ AMDGPU_GFX_TCX_DST_FIFOA1,
+ AMDGPU_GFX_TCX_DST_FIFOA2,
+ AMDGPU_GFX_TCX_DST_FIFOA3,
+ AMDGPU_GFX_TCX_DST_FIFOA4,
+ AMDGPU_GFX_TCX_DST_FIFOA5,
+ AMDGPU_GFX_TCX_DST_FIFOA6,
+ AMDGPU_GFX_TCX_DST_FIFOA7,
+ AMDGPU_GFX_TCX_DST_FIFOB0,
+ AMDGPU_GFX_TCX_DST_FIFOB1,
+ AMDGPU_GFX_TCX_DST_FIFOB2,
+ AMDGPU_GFX_TCX_DST_FIFOB3,
+ AMDGPU_GFX_TCX_DST_FIFOB4,
+ AMDGPU_GFX_TCX_DST_FIFOB5,
+ AMDGPU_GFX_TCX_DST_FIFOB6,
+ AMDGPU_GFX_TCX_DST_FIFOB7,
+ AMDGPU_GFX_TCX_DST_FIFOD0,
+ AMDGPU_GFX_TCX_DST_FIFOD1,
+ AMDGPU_GFX_TCX_DST_FIFOD2,
+ AMDGPU_GFX_TCX_DST_FIFOD3,
+ AMDGPU_GFX_TCX_DST_FIFOD4,
+ AMDGPU_GFX_TCX_DST_FIFOD5,
+ AMDGPU_GFX_TCX_DST_FIFOD6,
+ AMDGPU_GFX_TCX_DST_FIFOD7,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKB0,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKB1,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKB2,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKB3,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKB4,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKB5,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKB6,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKB7,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKD0,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKD1,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKD2,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKD3,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKD4,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKD5,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKD6,
+ AMDGPU_GFX_TCX_DST_FIFO_ACKD7,
+};
+
+enum amdgpu_gfx_atc_l2_ras_mem_id {
+ AMDGPU_GFX_ATC_L2_MEM0 = 0,
+};
+
+enum amdgpu_gfx_utcl2_ras_mem_id {
+ AMDGPU_GFX_UTCL2_MEM0 = 0,
+};
+
+enum amdgpu_gfx_vml2_ras_mem_id {
+ AMDGPU_GFX_VML2_MEM0 = 0,
+};
+
+enum amdgpu_gfx_vml2_walker_ras_mem_id {
+ AMDGPU_GFX_VML2_WALKER_MEM0 = 0,
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_cp_mem_list[] = {
+ {AMDGPU_GFX_CP_MEM1, "CP_MEM1"},
+ {AMDGPU_GFX_CP_MEM2, "CP_MEM2"},
+ {AMDGPU_GFX_CP_MEM3, "CP_MEM3"},
+ {AMDGPU_GFX_CP_MEM4, "CP_MEM4"},
+ {AMDGPU_GFX_CP_MEM5, "CP_MEM5"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_gcea_mem_list[] = {
+ {AMDGPU_GFX_GCEA_IOWR_CMDMEM, "GCEA_IOWR_CMDMEM"},
+ {AMDGPU_GFX_GCEA_IORD_CMDMEM, "GCEA_IORD_CMDMEM"},
+ {AMDGPU_GFX_GCEA_GMIWR_CMDMEM, "GCEA_GMIWR_CMDMEM"},
+ {AMDGPU_GFX_GCEA_GMIRD_CMDMEM, "GCEA_GMIRD_CMDMEM"},
+ {AMDGPU_GFX_GCEA_DRAMWR_CMDMEM, "GCEA_DRAMWR_CMDMEM"},
+ {AMDGPU_GFX_GCEA_DRAMRD_CMDMEM, "GCEA_DRAMRD_CMDMEM"},
+ {AMDGPU_GFX_GCEA_MAM_DMEM0, "GCEA_MAM_DMEM0"},
+ {AMDGPU_GFX_GCEA_MAM_DMEM1, "GCEA_MAM_DMEM1"},
+ {AMDGPU_GFX_GCEA_MAM_DMEM2, "GCEA_MAM_DMEM2"},
+ {AMDGPU_GFX_GCEA_MAM_DMEM3, "GCEA_MAM_DMEM3"},
+ {AMDGPU_GFX_GCEA_MAM_AMEM0, "GCEA_MAM_AMEM0"},
+ {AMDGPU_GFX_GCEA_MAM_AMEM1, "GCEA_MAM_AMEM1"},
+ {AMDGPU_GFX_GCEA_MAM_AMEM2, "GCEA_MAM_AMEM2"},
+ {AMDGPU_GFX_GCEA_MAM_AMEM3, "GCEA_MAM_AMEM3"},
+ {AMDGPU_GFX_GCEA_MAM_AFLUSH_BUFFER, "GCEA_MAM_AFLUSH_BUFFER"},
+ {AMDGPU_GFX_GCEA_WRET_TAGMEM, "GCEA_WRET_TAGMEM"},
+ {AMDGPU_GFX_GCEA_RRET_TAGMEM, "GCEA_RRET_TAGMEM"},
+ {AMDGPU_GFX_GCEA_IOWR_DATAMEM, "GCEA_IOWR_DATAMEM"},
+ {AMDGPU_GFX_GCEA_GMIWR_DATAMEM, "GCEA_GMIWR_DATAMEM"},
+ {AMDGPU_GFX_GCEA_DRAM_DATAMEM, "GCEA_DRAM_DATAMEM"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_gc_cane_mem_list[] = {
+ {AMDGPU_GFX_GC_CANE_MEM0, "GC_CANE_MEM0"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_gcutcl2_mem_list[] = {
+ {AMDGPU_GFX_GCUTCL2_MEM2P512X95, "GCUTCL2_MEM2P512X95"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_gds_mem_list[] = {
+ {AMDGPU_GFX_GDS_MEM0, "GDS_MEM"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_lds_mem_list[] = {
+ {AMDGPU_GFX_LDS_BANK0, "LDS_BANK0"},
+ {AMDGPU_GFX_LDS_BANK1, "LDS_BANK1"},
+ {AMDGPU_GFX_LDS_BANK2, "LDS_BANK2"},
+ {AMDGPU_GFX_LDS_BANK3, "LDS_BANK3"},
+ {AMDGPU_GFX_LDS_BANK4, "LDS_BANK4"},
+ {AMDGPU_GFX_LDS_BANK5, "LDS_BANK5"},
+ {AMDGPU_GFX_LDS_BANK6, "LDS_BANK6"},
+ {AMDGPU_GFX_LDS_BANK7, "LDS_BANK7"},
+ {AMDGPU_GFX_LDS_BANK8, "LDS_BANK8"},
+ {AMDGPU_GFX_LDS_BANK9, "LDS_BANK9"},
+ {AMDGPU_GFX_LDS_BANK10, "LDS_BANK10"},
+ {AMDGPU_GFX_LDS_BANK11, "LDS_BANK11"},
+ {AMDGPU_GFX_LDS_BANK12, "LDS_BANK12"},
+ {AMDGPU_GFX_LDS_BANK13, "LDS_BANK13"},
+ {AMDGPU_GFX_LDS_BANK14, "LDS_BANK14"},
+ {AMDGPU_GFX_LDS_BANK15, "LDS_BANK15"},
+ {AMDGPU_GFX_LDS_BANK16, "LDS_BANK16"},
+ {AMDGPU_GFX_LDS_BANK17, "LDS_BANK17"},
+ {AMDGPU_GFX_LDS_BANK18, "LDS_BANK18"},
+ {AMDGPU_GFX_LDS_BANK19, "LDS_BANK19"},
+ {AMDGPU_GFX_LDS_BANK20, "LDS_BANK20"},
+ {AMDGPU_GFX_LDS_BANK21, "LDS_BANK21"},
+ {AMDGPU_GFX_LDS_BANK22, "LDS_BANK22"},
+ {AMDGPU_GFX_LDS_BANK23, "LDS_BANK23"},
+ {AMDGPU_GFX_LDS_BANK24, "LDS_BANK24"},
+ {AMDGPU_GFX_LDS_BANK25, "LDS_BANK25"},
+ {AMDGPU_GFX_LDS_BANK26, "LDS_BANK26"},
+ {AMDGPU_GFX_LDS_BANK27, "LDS_BANK27"},
+ {AMDGPU_GFX_LDS_BANK28, "LDS_BANK28"},
+ {AMDGPU_GFX_LDS_BANK29, "LDS_BANK29"},
+ {AMDGPU_GFX_LDS_BANK30, "LDS_BANK30"},
+ {AMDGPU_GFX_LDS_BANK31, "LDS_BANK31"},
+ {AMDGPU_GFX_LDS_SP_BUFFER_A, "LDS_SP_BUFFER_A"},
+ {AMDGPU_GFX_LDS_SP_BUFFER_B, "LDS_SP_BUFFER_B"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_rlc_mem_list[] = {
+ {AMDGPU_GFX_RLC_GPMF32, "RLC_GPMF32"},
+ {AMDGPU_GFX_RLC_RLCVF32, "RLC_RLCVF32"},
+ {AMDGPU_GFX_RLC_SCRATCH, "RLC_SCRATCH"},
+ {AMDGPU_GFX_RLC_SRM_ARAM, "RLC_SRM_ARAM"},
+ {AMDGPU_GFX_RLC_SRM_DRAM, "RLC_SRM_DRAM"},
+ {AMDGPU_GFX_RLC_TCTAG, "RLC_TCTAG"},
+ {AMDGPU_GFX_RLC_SPM_SE, "RLC_SPM_SE"},
+ {AMDGPU_GFX_RLC_SPM_GRBMT, "RLC_SPM_GRBMT"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_sp_mem_list[] = {
+ {AMDGPU_GFX_SP_SIMDID0, "SP_SIMDID0"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_spi_mem_list[] = {
+ {AMDGPU_GFX_SPI_MEM0, "SPI_MEM0"},
+ {AMDGPU_GFX_SPI_MEM1, "SPI_MEM1"},
+ {AMDGPU_GFX_SPI_MEM2, "SPI_MEM2"},
+ {AMDGPU_GFX_SPI_MEM3, "SPI_MEM3"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_sqc_mem_list[] = {
+ {AMDGPU_GFX_SQC_INST_CACHE_A, "SQC_INST_CACHE_A"},
+ {AMDGPU_GFX_SQC_INST_CACHE_B, "SQC_INST_CACHE_B"},
+ {AMDGPU_GFX_SQC_INST_CACHE_TAG_A, "SQC_INST_CACHE_TAG_A"},
+ {AMDGPU_GFX_SQC_INST_CACHE_TAG_B, "SQC_INST_CACHE_TAG_B"},
+ {AMDGPU_GFX_SQC_INST_CACHE_MISS_FIFO_A, "SQC_INST_CACHE_MISS_FIFO_A"},
+ {AMDGPU_GFX_SQC_INST_CACHE_MISS_FIFO_B, "SQC_INST_CACHE_MISS_FIFO_B"},
+ {AMDGPU_GFX_SQC_INST_CACHE_GATCL1_MISS_FIFO_A, "SQC_INST_CACHE_GATCL1_MISS_FIFO_A"},
+ {AMDGPU_GFX_SQC_INST_CACHE_GATCL1_MISS_FIFO_B, "SQC_INST_CACHE_GATCL1_MISS_FIFO_B"},
+ {AMDGPU_GFX_SQC_DATA_CACHE_A, "SQC_DATA_CACHE_A"},
+ {AMDGPU_GFX_SQC_DATA_CACHE_B, "SQC_DATA_CACHE_B"},
+ {AMDGPU_GFX_SQC_DATA_CACHE_TAG_A, "SQC_DATA_CACHE_TAG_A"},
+ {AMDGPU_GFX_SQC_DATA_CACHE_TAG_B, "SQC_DATA_CACHE_TAG_B"},
+ {AMDGPU_GFX_SQC_DATA_CACHE_MISS_FIFO_A, "SQC_DATA_CACHE_MISS_FIFO_A"},
+ {AMDGPU_GFX_SQC_DATA_CACHE_MISS_FIFO_B, "SQC_DATA_CACHE_MISS_FIFO_B"},
+ {AMDGPU_GFX_SQC_DATA_CACHE_HIT_FIFO_A, "SQC_DATA_CACHE_HIT_FIFO_A"},
+ {AMDGPU_GFX_SQC_DATA_CACHE_HIT_FIFO_B, "SQC_DATA_CACHE_HIT_FIFO_B"},
+ {AMDGPU_GFX_SQC_DIRTY_BIT_A, "SQC_DIRTY_BIT_A"},
+ {AMDGPU_GFX_SQC_DIRTY_BIT_B, "SQC_DIRTY_BIT_B"},
+ {AMDGPU_GFX_SQC_WRITE_DATA_BUFFER_CU0, "SQC_WRITE_DATA_BUFFER_CU0"},
+ {AMDGPU_GFX_SQC_WRITE_DATA_BUFFER_CU1, "SQC_WRITE_DATA_BUFFER_CU1"},
+ {AMDGPU_GFX_SQC_UTCL1_MISS_LFIFO_DATA_CACHE_A, "SQC_UTCL1_MISS_LFIFO_DATA_CACHE_A"},
+ {AMDGPU_GFX_SQC_UTCL1_MISS_LFIFO_DATA_CACHE_B, "SQC_UTCL1_MISS_LFIFO_DATA_CACHE_B"},
+ {AMDGPU_GFX_SQC_UTCL1_MISS_LFIFO_INST_CACHE, "SQC_UTCL1_MISS_LFIFO_INST_CACHE"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_sq_mem_list[] = {
+ {AMDGPU_GFX_SQ_SGPR_MEM0, "SQ_SGPR_MEM0"},
+ {AMDGPU_GFX_SQ_SGPR_MEM1, "SQ_SGPR_MEM1"},
+ {AMDGPU_GFX_SQ_SGPR_MEM2, "SQ_SGPR_MEM2"},
+ {AMDGPU_GFX_SQ_SGPR_MEM3, "SQ_SGPR_MEM3"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_ta_mem_list[] = {
+ {AMDGPU_GFX_TA_FS_AFIFO_RAM_LO, "TA_FS_AFIFO_RAM_LO"},
+ {AMDGPU_GFX_TA_FS_AFIFO_RAM_HI, "TA_FS_AFIFO_RAM_HI"},
+ {AMDGPU_GFX_TA_FS_CFIFO_RAM, "TA_FS_CFIFO_RAM"},
+ {AMDGPU_GFX_TA_FSX_LFIFO, "TA_FSX_LFIFO"},
+ {AMDGPU_GFX_TA_FS_DFIFO_RAM, "TA_FS_DFIFO_RAM"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_tcc_mem_list[] = {
+ {AMDGPU_GFX_TCC_MEM1, "TCC_MEM1"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_tca_mem_list[] = {
+ {AMDGPU_GFX_TCA_MEM1, "TCA_MEM1"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_tci_mem_list[] = {
+ {AMDGPU_GFX_TCIW_MEM, "TCIW_MEM"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_tcp_mem_list[] = {
+ {AMDGPU_GFX_TCP_LFIFO0, "TCP_LFIFO0"},
+ {AMDGPU_GFX_TCP_SET0BANK0_RAM, "TCP_SET0BANK0_RAM"},
+ {AMDGPU_GFX_TCP_SET0BANK1_RAM, "TCP_SET0BANK1_RAM"},
+ {AMDGPU_GFX_TCP_SET0BANK2_RAM, "TCP_SET0BANK2_RAM"},
+ {AMDGPU_GFX_TCP_SET0BANK3_RAM, "TCP_SET0BANK3_RAM"},
+ {AMDGPU_GFX_TCP_SET1BANK0_RAM, "TCP_SET1BANK0_RAM"},
+ {AMDGPU_GFX_TCP_SET1BANK1_RAM, "TCP_SET1BANK1_RAM"},
+ {AMDGPU_GFX_TCP_SET1BANK2_RAM, "TCP_SET1BANK2_RAM"},
+ {AMDGPU_GFX_TCP_SET1BANK3_RAM, "TCP_SET1BANK3_RAM"},
+ {AMDGPU_GFX_TCP_SET2BANK0_RAM, "TCP_SET2BANK0_RAM"},
+ {AMDGPU_GFX_TCP_SET2BANK1_RAM, "TCP_SET2BANK1_RAM"},
+ {AMDGPU_GFX_TCP_SET2BANK2_RAM, "TCP_SET2BANK2_RAM"},
+ {AMDGPU_GFX_TCP_SET2BANK3_RAM, "TCP_SET2BANK3_RAM"},
+ {AMDGPU_GFX_TCP_SET3BANK0_RAM, "TCP_SET3BANK0_RAM"},
+ {AMDGPU_GFX_TCP_SET3BANK1_RAM, "TCP_SET3BANK1_RAM"},
+ {AMDGPU_GFX_TCP_SET3BANK2_RAM, "TCP_SET3BANK2_RAM"},
+ {AMDGPU_GFX_TCP_SET3BANK3_RAM, "TCP_SET3BANK3_RAM"},
+ {AMDGPU_GFX_TCP_VM_FIFO, "TCP_VM_FIFO"},
+ {AMDGPU_GFX_TCP_DB_TAGRAM0, "TCP_DB_TAGRAM0"},
+ {AMDGPU_GFX_TCP_DB_TAGRAM1, "TCP_DB_TAGRAM1"},
+ {AMDGPU_GFX_TCP_DB_TAGRAM2, "TCP_DB_TAGRAM2"},
+ {AMDGPU_GFX_TCP_DB_TAGRAM3, "TCP_DB_TAGRAM3"},
+ {AMDGPU_GFX_TCP_UTCL1_LFIFO_PROBE0, "TCP_UTCL1_LFIFO_PROBE0"},
+ {AMDGPU_GFX_TCP_UTCL1_LFIFO_PROBE1, "TCP_UTCL1_LFIFO_PROBE1"},
+ {AMDGPU_GFX_TCP_CMD_FIFO, "TCP_CMD_FIFO"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_td_mem_list[] = {
+ {AMDGPU_GFX_TD_UTD_CS_FIFO_MEM, "TD_UTD_CS_FIFO_MEM"},
+ {AMDGPU_GFX_TD_UTD_SS_FIFO_LO_MEM, "TD_UTD_SS_FIFO_LO_MEM"},
+ {AMDGPU_GFX_TD_UTD_SS_FIFO_HI_MEM, "TD_UTD_SS_FIFO_HI_MEM"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_tcx_mem_list[] = {
+ {AMDGPU_GFX_TCX_FIFOD0, "TCX_FIFOD0"},
+ {AMDGPU_GFX_TCX_FIFOD1, "TCX_FIFOD1"},
+ {AMDGPU_GFX_TCX_FIFOD2, "TCX_FIFOD2"},
+ {AMDGPU_GFX_TCX_FIFOD3, "TCX_FIFOD3"},
+ {AMDGPU_GFX_TCX_FIFOD4, "TCX_FIFOD4"},
+ {AMDGPU_GFX_TCX_FIFOD5, "TCX_FIFOD5"},
+ {AMDGPU_GFX_TCX_FIFOD6, "TCX_FIFOD6"},
+ {AMDGPU_GFX_TCX_FIFOD7, "TCX_FIFOD7"},
+ {AMDGPU_GFX_TCX_FIFOB0, "TCX_FIFOB0"},
+ {AMDGPU_GFX_TCX_FIFOB1, "TCX_FIFOB1"},
+ {AMDGPU_GFX_TCX_FIFOB2, "TCX_FIFOB2"},
+ {AMDGPU_GFX_TCX_FIFOB3, "TCX_FIFOB3"},
+ {AMDGPU_GFX_TCX_FIFOB4, "TCX_FIFOB4"},
+ {AMDGPU_GFX_TCX_FIFOB5, "TCX_FIFOB5"},
+ {AMDGPU_GFX_TCX_FIFOB6, "TCX_FIFOB6"},
+ {AMDGPU_GFX_TCX_FIFOB7, "TCX_FIFOB7"},
+ {AMDGPU_GFX_TCX_FIFOA0, "TCX_FIFOA0"},
+ {AMDGPU_GFX_TCX_FIFOA1, "TCX_FIFOA1"},
+ {AMDGPU_GFX_TCX_FIFOA2, "TCX_FIFOA2"},
+ {AMDGPU_GFX_TCX_FIFOA3, "TCX_FIFOA3"},
+ {AMDGPU_GFX_TCX_FIFOA4, "TCX_FIFOA4"},
+ {AMDGPU_GFX_TCX_FIFOA5, "TCX_FIFOA5"},
+ {AMDGPU_GFX_TCX_FIFOA6, "TCX_FIFOA6"},
+ {AMDGPU_GFX_TCX_FIFOA7, "TCX_FIFOA7"},
+ {AMDGPU_GFX_TCX_CFIFO0, "TCX_CFIFO0"},
+ {AMDGPU_GFX_TCX_CFIFO1, "TCX_CFIFO1"},
+ {AMDGPU_GFX_TCX_CFIFO2, "TCX_CFIFO2"},
+ {AMDGPU_GFX_TCX_CFIFO3, "TCX_CFIFO3"},
+ {AMDGPU_GFX_TCX_CFIFO4, "TCX_CFIFO4"},
+ {AMDGPU_GFX_TCX_CFIFO5, "TCX_CFIFO5"},
+ {AMDGPU_GFX_TCX_CFIFO6, "TCX_CFIFO6"},
+ {AMDGPU_GFX_TCX_CFIFO7, "TCX_CFIFO7"},
+ {AMDGPU_GFX_TCX_FIFO_ACKB0, "TCX_FIFO_ACKB0"},
+ {AMDGPU_GFX_TCX_FIFO_ACKB1, "TCX_FIFO_ACKB1"},
+ {AMDGPU_GFX_TCX_FIFO_ACKB2, "TCX_FIFO_ACKB2"},
+ {AMDGPU_GFX_TCX_FIFO_ACKB3, "TCX_FIFO_ACKB3"},
+ {AMDGPU_GFX_TCX_FIFO_ACKB4, "TCX_FIFO_ACKB4"},
+ {AMDGPU_GFX_TCX_FIFO_ACKB5, "TCX_FIFO_ACKB5"},
+ {AMDGPU_GFX_TCX_FIFO_ACKB6, "TCX_FIFO_ACKB6"},
+ {AMDGPU_GFX_TCX_FIFO_ACKB7, "TCX_FIFO_ACKB7"},
+ {AMDGPU_GFX_TCX_FIFO_ACKD0, "TCX_FIFO_ACKD0"},
+ {AMDGPU_GFX_TCX_FIFO_ACKD1, "TCX_FIFO_ACKD1"},
+ {AMDGPU_GFX_TCX_FIFO_ACKD2, "TCX_FIFO_ACKD2"},
+ {AMDGPU_GFX_TCX_FIFO_ACKD3, "TCX_FIFO_ACKD3"},
+ {AMDGPU_GFX_TCX_FIFO_ACKD4, "TCX_FIFO_ACKD4"},
+ {AMDGPU_GFX_TCX_FIFO_ACKD5, "TCX_FIFO_ACKD5"},
+ {AMDGPU_GFX_TCX_FIFO_ACKD6, "TCX_FIFO_ACKD6"},
+ {AMDGPU_GFX_TCX_FIFO_ACKD7, "TCX_FIFO_ACKD7"},
+ {AMDGPU_GFX_TCX_DST_FIFOA0, "TCX_DST_FIFOA0"},
+ {AMDGPU_GFX_TCX_DST_FIFOA1, "TCX_DST_FIFOA1"},
+ {AMDGPU_GFX_TCX_DST_FIFOA2, "TCX_DST_FIFOA2"},
+ {AMDGPU_GFX_TCX_DST_FIFOA3, "TCX_DST_FIFOA3"},
+ {AMDGPU_GFX_TCX_DST_FIFOA4, "TCX_DST_FIFOA4"},
+ {AMDGPU_GFX_TCX_DST_FIFOA5, "TCX_DST_FIFOA5"},
+ {AMDGPU_GFX_TCX_DST_FIFOA6, "TCX_DST_FIFOA6"},
+ {AMDGPU_GFX_TCX_DST_FIFOA7, "TCX_DST_FIFOA7"},
+ {AMDGPU_GFX_TCX_DST_FIFOB0, "TCX_DST_FIFOB0"},
+ {AMDGPU_GFX_TCX_DST_FIFOB1, "TCX_DST_FIFOB1"},
+ {AMDGPU_GFX_TCX_DST_FIFOB2, "TCX_DST_FIFOB2"},
+ {AMDGPU_GFX_TCX_DST_FIFOB3, "TCX_DST_FIFOB3"},
+ {AMDGPU_GFX_TCX_DST_FIFOB4, "TCX_DST_FIFOB4"},
+ {AMDGPU_GFX_TCX_DST_FIFOB5, "TCX_DST_FIFOB5"},
+ {AMDGPU_GFX_TCX_DST_FIFOB6, "TCX_DST_FIFOB6"},
+ {AMDGPU_GFX_TCX_DST_FIFOB7, "TCX_DST_FIFOB7"},
+ {AMDGPU_GFX_TCX_DST_FIFOD0, "TCX_DST_FIFOD0"},
+ {AMDGPU_GFX_TCX_DST_FIFOD1, "TCX_DST_FIFOD1"},
+ {AMDGPU_GFX_TCX_DST_FIFOD2, "TCX_DST_FIFOD2"},
+ {AMDGPU_GFX_TCX_DST_FIFOD3, "TCX_DST_FIFOD3"},
+ {AMDGPU_GFX_TCX_DST_FIFOD4, "TCX_DST_FIFOD4"},
+ {AMDGPU_GFX_TCX_DST_FIFOD5, "TCX_DST_FIFOD5"},
+ {AMDGPU_GFX_TCX_DST_FIFOD6, "TCX_DST_FIFOD6"},
+ {AMDGPU_GFX_TCX_DST_FIFOD7, "TCX_DST_FIFOD7"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKB0, "TCX_DST_FIFO_ACKB0"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKB1, "TCX_DST_FIFO_ACKB1"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKB2, "TCX_DST_FIFO_ACKB2"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKB3, "TCX_DST_FIFO_ACKB3"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKB4, "TCX_DST_FIFO_ACKB4"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKB5, "TCX_DST_FIFO_ACKB5"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKB6, "TCX_DST_FIFO_ACKB6"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKB7, "TCX_DST_FIFO_ACKB7"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKD0, "TCX_DST_FIFO_ACKD0"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKD1, "TCX_DST_FIFO_ACKD1"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKD2, "TCX_DST_FIFO_ACKD2"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKD3, "TCX_DST_FIFO_ACKD3"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKD4, "TCX_DST_FIFO_ACKD4"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKD5, "TCX_DST_FIFO_ACKD5"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKD6, "TCX_DST_FIFO_ACKD6"},
+ {AMDGPU_GFX_TCX_DST_FIFO_ACKD7, "TCX_DST_FIFO_ACKD7"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_atc_l2_mem_list[] = {
+ {AMDGPU_GFX_ATC_L2_MEM, "ATC_L2_MEM"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_utcl2_mem_list[] = {
+ {AMDGPU_GFX_UTCL2_MEM, "UTCL2_MEM"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_vml2_mem_list[] = {
+ {AMDGPU_GFX_VML2_MEM, "VML2_MEM"},
+};
+
+static const struct amdgpu_ras_memory_id_entry gfx_v9_4_3_ras_vml2_walker_mem_list[] = {
+ {AMDGPU_GFX_VML2_WALKER_MEM, "VML2_WALKER_MEM"},
+};
+
+static const struct amdgpu_gfx_ras_mem_id_entry gfx_v9_4_3_ras_mem_list_array[AMDGPU_GFX_MEM_TYPE_NUM] = {
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_cp_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_gcea_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_gc_cane_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_gcutcl2_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_gds_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_lds_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_rlc_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_sp_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_spi_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_sqc_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_sq_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_ta_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_tcc_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_tca_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_tci_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_tcp_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_td_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_tcx_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_atc_l2_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_utcl2_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_vml2_mem_list)
+ AMDGPU_GFX_MEMID_ENT(gfx_v9_4_3_ras_vml2_walker_mem_list)
+};
+
+static const struct amdgpu_gfx_ras_reg_entry gfx_v9_4_3_ce_reg_list[] = {
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regRLC_CE_ERR_STATUS_LOW, regRLC_CE_ERR_STATUS_HIGH),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "RLC"},
+ AMDGPU_GFX_RLC_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regCPC_CE_ERR_STATUS_LO, regCPC_CE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "CPC"},
+ AMDGPU_GFX_CP_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regCPF_CE_ERR_STATUS_LO, regCPF_CE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "CPF"},
+ AMDGPU_GFX_CP_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regCPG_CE_ERR_STATUS_LO, regCPG_CE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "CPG"},
+ AMDGPU_GFX_CP_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regGDS_CE_ERR_STATUS_LO, regGDS_CE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "GDS"},
+ AMDGPU_GFX_GDS_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regGC_CANE_CE_ERR_STATUS_LO, regGC_CANE_CE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "CANE"},
+ AMDGPU_GFX_GC_CANE_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regSPI_CE_ERR_STATUS_LO, regSPI_CE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SPI"},
+ AMDGPU_GFX_SPI_MEM, 8},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regSP0_CE_ERR_STATUS_LO, regSP0_CE_ERR_STATUS_HI),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SP0"},
+ AMDGPU_GFX_SP_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regSP1_CE_ERR_STATUS_LO, regSP1_CE_ERR_STATUS_HI),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SP1"},
+ AMDGPU_GFX_SP_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regSQ_CE_ERR_STATUS_LO, regSQ_CE_ERR_STATUS_HI),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SQ"},
+ AMDGPU_GFX_SQ_MEM, 8},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regSQC_CE_EDC_LO, regSQC_CE_EDC_HI),
+ 5, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SQC"},
+ AMDGPU_GFX_SQC_MEM, 8},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCX_CE_ERR_STATUS_LO, regTCX_CE_ERR_STATUS_HI),
+ 2, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCX"},
+ AMDGPU_GFX_TCX_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCC_CE_ERR_STATUS_LO, regTCC_CE_ERR_STATUS_HI),
+ 16, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCC"},
+ AMDGPU_GFX_TCC_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTA_CE_EDC_LO, regTA_CE_EDC_HI),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TA"},
+ AMDGPU_GFX_TA_MEM, 8},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCI_CE_EDC_LO_REG, regTCI_CE_EDC_HI_REG),
+ 31, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCI"},
+ AMDGPU_GFX_TCI_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCP_CE_EDC_LO_REG, regTCP_CE_EDC_HI_REG),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCP"},
+ AMDGPU_GFX_TCP_MEM, 8},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTD_CE_EDC_LO, regTD_CE_EDC_HI),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TD"},
+ AMDGPU_GFX_TD_MEM, 8},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regGCEA_CE_ERR_STATUS_LO, regGCEA_CE_ERR_STATUS_HI),
+ 16, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "GCEA"},
+ AMDGPU_GFX_GCEA_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regLDS_CE_ERR_STATUS_LO, regLDS_CE_ERR_STATUS_HI),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "LDS"},
+ AMDGPU_GFX_LDS_MEM, 1},
+};
+
+static const struct amdgpu_gfx_ras_reg_entry gfx_v9_4_3_ue_reg_list[] = {
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regRLC_UE_ERR_STATUS_LOW, regRLC_UE_ERR_STATUS_HIGH),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "RLC"},
+ AMDGPU_GFX_RLC_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regCPC_UE_ERR_STATUS_LO, regCPC_UE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "CPC"},
+ AMDGPU_GFX_CP_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regCPF_UE_ERR_STATUS_LO, regCPF_UE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "CPF"},
+ AMDGPU_GFX_CP_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regCPG_UE_ERR_STATUS_LO, regCPG_UE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "CPG"},
+ AMDGPU_GFX_CP_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regGDS_UE_ERR_STATUS_LO, regGDS_UE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "GDS"},
+ AMDGPU_GFX_GDS_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regGC_CANE_UE_ERR_STATUS_LO, regGC_CANE_UE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "CANE"},
+ AMDGPU_GFX_GC_CANE_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regSPI_UE_ERR_STATUS_LO, regSPI_UE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SPI"},
+ AMDGPU_GFX_SPI_MEM, 8},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regSP0_UE_ERR_STATUS_LO, regSP0_UE_ERR_STATUS_HI),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SP0"},
+ AMDGPU_GFX_SP_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regSP1_UE_ERR_STATUS_LO, regSP1_UE_ERR_STATUS_HI),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SP1"},
+ AMDGPU_GFX_SP_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regSQ_UE_ERR_STATUS_LO, regSQ_UE_ERR_STATUS_HI),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SQ"},
+ AMDGPU_GFX_SQ_MEM, 8},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regSQC_UE_EDC_LO, regSQC_UE_EDC_HI),
+ 5, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SQC"},
+ AMDGPU_GFX_SQC_MEM, 8},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCX_UE_ERR_STATUS_LO, regTCX_UE_ERR_STATUS_HI),
+ 2, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCX"},
+ AMDGPU_GFX_TCX_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCC_UE_ERR_STATUS_LO, regTCC_UE_ERR_STATUS_HI),
+ 16, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCC"},
+ AMDGPU_GFX_TCC_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTA_UE_EDC_LO, regTA_UE_EDC_HI),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TA"},
+ AMDGPU_GFX_TA_MEM, 8},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCI_UE_EDC_LO_REG, regTCI_UE_EDC_HI_REG),
+ 31, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCI"},
+ AMDGPU_GFX_TCI_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCP_UE_EDC_LO_REG, regTCP_UE_EDC_HI_REG),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCP"},
+ AMDGPU_GFX_TCP_MEM, 8},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTD_UE_EDC_LO, regTD_UE_EDC_HI),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TD"},
+ AMDGPU_GFX_TD_MEM, 8},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regTCA_UE_ERR_STATUS_LO, regTCA_UE_ERR_STATUS_HI),
+ 2, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "TCA"},
+ AMDGPU_GFX_TCA_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regGCEA_UE_ERR_STATUS_LO, regGCEA_UE_ERR_STATUS_HI),
+ 16, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "GCEA"},
+ AMDGPU_GFX_GCEA_MEM, 1},
+ {{AMDGPU_RAS_REG_ENTRY(GC, 0, regLDS_UE_ERR_STATUS_LO, regLDS_UE_ERR_STATUS_HI),
+ 10, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "LDS"},
+ AMDGPU_GFX_LDS_MEM, 1},
+};
+
+static const struct soc15_reg_entry gfx_v9_4_3_ea_err_status_regs = {
+ SOC15_REG_ENTRY(GC, 0, regGCEA_ERR_STATUS), 0, 1, 16
+};
+
+static void gfx_v9_4_3_inst_query_ras_err_count(struct amdgpu_device *adev,
+ void *ras_error_status, int xcc_id)
+{
+ struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
+ unsigned long ce_count = 0, ue_count = 0;
+ uint32_t i, j, k;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ for (i = 0; i < ARRAY_SIZE(gfx_v9_4_3_ce_reg_list); i++) {
+ for (j = 0; j < gfx_v9_4_3_ce_reg_list[i].se_num; j++) {
+ for (k = 0; k < gfx_v9_4_3_ce_reg_list[i].reg_entry.reg_inst; k++) {
+ /* no need to select if instance number is 1 */
+ if (gfx_v9_4_3_ce_reg_list[i].se_num > 1 ||
+ gfx_v9_4_3_ce_reg_list[i].reg_entry.reg_inst > 1)
+ gfx_v9_4_3_xcc_select_se_sh(adev, j, 0, k, xcc_id);
+
+ amdgpu_ras_inst_query_ras_error_count(adev,
+ &(gfx_v9_4_3_ce_reg_list[i].reg_entry),
+ 1,
+ gfx_v9_4_3_ras_mem_list_array[gfx_v9_4_3_ce_reg_list[i].mem_id_type].mem_id_ent,
+ gfx_v9_4_3_ras_mem_list_array[gfx_v9_4_3_ce_reg_list[i].mem_id_type].size,
+ GET_INST(GC, xcc_id),
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE,
+ &ce_count);
+
+ amdgpu_ras_inst_query_ras_error_count(adev,
+ &(gfx_v9_4_3_ue_reg_list[i].reg_entry),
+ 1,
+ gfx_v9_4_3_ras_mem_list_array[gfx_v9_4_3_ue_reg_list[i].mem_id_type].mem_id_ent,
+ gfx_v9_4_3_ras_mem_list_array[gfx_v9_4_3_ue_reg_list[i].mem_id_type].size,
+ GET_INST(GC, xcc_id),
+ AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
+ &ue_count);
+ }
+ }
+ }
+
+ gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
+ xcc_id);
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ /* the caller should make sure initialize value of
+ * err_data->ue_count and err_data->ce_count
+ */
+ err_data->ce_count += ce_count;
+ err_data->ue_count += ue_count;
+}
+
+static void gfx_v9_4_3_inst_reset_ras_err_count(struct amdgpu_device *adev,
+ void *ras_error_status, int xcc_id)
+{
+ uint32_t i, j, k;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ for (i = 0; i < ARRAY_SIZE(gfx_v9_4_3_ce_reg_list); i++) {
+ for (j = 0; j < gfx_v9_4_3_ce_reg_list[i].se_num; j++) {
+ for (k = 0; k < gfx_v9_4_3_ce_reg_list[i].reg_entry.reg_inst; k++) {
+ /* no need to select if instance number is 1 */
+ if (gfx_v9_4_3_ce_reg_list[i].se_num > 1 ||
+ gfx_v9_4_3_ce_reg_list[i].reg_entry.reg_inst > 1)
+ gfx_v9_4_3_xcc_select_se_sh(adev, j, 0, k, xcc_id);
+
+ amdgpu_ras_inst_reset_ras_error_count(adev,
+ &(gfx_v9_4_3_ce_reg_list[i].reg_entry),
+ 1,
+ GET_INST(GC, xcc_id));
+
+ amdgpu_ras_inst_reset_ras_error_count(adev,
+ &(gfx_v9_4_3_ue_reg_list[i].reg_entry),
+ 1,
+ GET_INST(GC, xcc_id));
+ }
+ }
+ }
+
+ gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
+ xcc_id);
+ mutex_unlock(&adev->grbm_idx_mutex);
+}
+
+static void gfx_v9_4_3_inst_query_ea_err_status(struct amdgpu_device *adev,
+ int xcc_id)
+{
+ uint32_t i, j;
+ uint32_t reg_value;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+
+ for (i = 0; i < gfx_v9_4_3_ea_err_status_regs.se_num; i++) {
+ for (j = 0; j < gfx_v9_4_3_ea_err_status_regs.instance; j++) {
+ gfx_v9_4_3_xcc_select_se_sh(adev, i, 0, j, xcc_id);
+ reg_value = RREG32_SOC15(GC, GET_INST(GC, xcc_id),
+ regGCEA_ERR_STATUS);
+ if (REG_GET_FIELD(reg_value, GCEA_ERR_STATUS, SDP_RDRSP_STATUS) ||
+ REG_GET_FIELD(reg_value, GCEA_ERR_STATUS, SDP_WRRSP_STATUS) ||
+ REG_GET_FIELD(reg_value, GCEA_ERR_STATUS, SDP_RDRSP_DATAPARITY_ERROR)) {
+ dev_warn(adev->dev,
+ "GCEA err detected at instance: %d, status: 0x%x!\n",
+ j, reg_value);
+ }
+ /* clear after read */
+ reg_value = REG_SET_FIELD(reg_value, GCEA_ERR_STATUS,
+ CLEAR_ERROR_STATUS, 0x1);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regGCEA_ERR_STATUS,
+ reg_value);
+ }
+ }
+
+ gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
+ xcc_id);
+ mutex_unlock(&adev->grbm_idx_mutex);
+}
+
+static void gfx_v9_4_3_inst_query_utc_err_status(struct amdgpu_device *adev,
+ int xcc_id)
+{
+ uint32_t data;
+
+ data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regUTCL2_MEM_ECC_STATUS);
+ if (data) {
+ dev_warn(adev->dev, "GFX UTCL2 Mem Ecc Status: 0x%x!\n", data);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regUTCL2_MEM_ECC_STATUS, 0x3);
+ }
+
+ data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regVML2_MEM_ECC_STATUS);
+ if (data) {
+ dev_warn(adev->dev, "GFX VML2 Mem Ecc Status: 0x%x!\n", data);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regVML2_MEM_ECC_STATUS, 0x3);
+ }
+
+ data = RREG32_SOC15(GC, GET_INST(GC, xcc_id),
+ regVML2_WALKER_MEM_ECC_STATUS);
+ if (data) {
+ dev_warn(adev->dev, "GFX VML2 Walker Mem Ecc Status: 0x%x!\n", data);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regVML2_WALKER_MEM_ECC_STATUS,
+ 0x3);
+ }
+}
+
+static void gfx_v9_4_3_log_cu_timeout_status(struct amdgpu_device *adev,
+ uint32_t status, int xcc_id)
+{
+ struct amdgpu_cu_info *cu_info = &adev->gfx.cu_info;
+ uint32_t i, simd, wave;
+ uint32_t wave_status;
+ uint32_t wave_pc_lo, wave_pc_hi;
+ uint32_t wave_exec_lo, wave_exec_hi;
+ uint32_t wave_inst_dw0, wave_inst_dw1;
+ uint32_t wave_ib_sts;
+
+ for (i = 0; i < 32; i++) {
+ if (!((i << 1) & status))
+ continue;
+
+ simd = i / cu_info->max_waves_per_simd;
+ wave = i % cu_info->max_waves_per_simd;
+
+ wave_status = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_STATUS);
+ wave_pc_lo = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_PC_LO);
+ wave_pc_hi = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_PC_HI);
+ wave_exec_lo =
+ wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_EXEC_LO);
+ wave_exec_hi =
+ wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_EXEC_HI);
+ wave_inst_dw0 =
+ wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_INST_DW0);
+ wave_inst_dw1 =
+ wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_INST_DW1);
+ wave_ib_sts = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_IB_STS);
+
+ dev_info(
+ adev->dev,
+ "\t SIMD %d, Wave %d: status 0x%x, pc 0x%llx, exec 0x%llx, inst 0x%llx, ib_sts 0x%x\n",
+ simd, wave, wave_status,
+ ((uint64_t)wave_pc_hi << 32 | wave_pc_lo),
+ ((uint64_t)wave_exec_hi << 32 | wave_exec_lo),
+ ((uint64_t)wave_inst_dw1 << 32 | wave_inst_dw0),
+ wave_ib_sts);
+ }
+}
+
+static void gfx_v9_4_3_inst_query_sq_timeout_status(struct amdgpu_device *adev,
+ int xcc_id)
+{
+ uint32_t se_idx, sh_idx, cu_idx;
+ uint32_t status;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+ for (se_idx = 0; se_idx < adev->gfx.config.max_shader_engines; se_idx++) {
+ for (sh_idx = 0; sh_idx < adev->gfx.config.max_sh_per_se; sh_idx++) {
+ for (cu_idx = 0; cu_idx < adev->gfx.config.max_cu_per_sh; cu_idx++) {
+ gfx_v9_4_3_xcc_select_se_sh(adev, se_idx, sh_idx,
+ cu_idx, xcc_id);
+ status = RREG32_SOC15(GC, GET_INST(GC, xcc_id),
+ regSQ_TIMEOUT_STATUS);
+ if (status != 0) {
+ dev_info(
+ adev->dev,
+ "GFX Watchdog Timeout: SE %d, SH %d, CU %d\n",
+ se_idx, sh_idx, cu_idx);
+ gfx_v9_4_3_log_cu_timeout_status(
+ adev, status, xcc_id);
+ }
+ /* clear old status */
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id),
+ regSQ_TIMEOUT_STATUS, 0);
+ }
+ }
+ }
+ gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
+ xcc_id);
+ mutex_unlock(&adev->grbm_idx_mutex);
+}
+
+static void gfx_v9_4_3_inst_query_ras_err_status(struct amdgpu_device *adev,
+ void *ras_error_status, int xcc_id)
+{
+ gfx_v9_4_3_inst_query_ea_err_status(adev, xcc_id);
+ gfx_v9_4_3_inst_query_utc_err_status(adev, xcc_id);
+ gfx_v9_4_3_inst_query_sq_timeout_status(adev, xcc_id);
+}
+
+static void gfx_v9_4_3_inst_reset_utc_err_status(struct amdgpu_device *adev,
+ int xcc_id)
+{
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regUTCL2_MEM_ECC_STATUS, 0x3);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regVML2_MEM_ECC_STATUS, 0x3);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regVML2_WALKER_MEM_ECC_STATUS, 0x3);
+}
+
+static void gfx_v9_4_3_inst_reset_ea_err_status(struct amdgpu_device *adev,
+ int xcc_id)
+{
+ uint32_t i, j;
+ uint32_t value;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+ for (i = 0; i < gfx_v9_4_3_ea_err_status_regs.se_num; i++) {
+ for (j = 0; j < gfx_v9_4_3_ea_err_status_regs.instance; j++) {
+ gfx_v9_4_3_xcc_select_se_sh(adev, i, 0, j, xcc_id);
+ value = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regGCEA_ERR_STATUS);
+ value = REG_SET_FIELD(value, GCEA_ERR_STATUS,
+ CLEAR_ERROR_STATUS, 0x1);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regGCEA_ERR_STATUS, value);
+ }
+ }
+ gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
+ xcc_id);
+ mutex_unlock(&adev->grbm_idx_mutex);
+}
+
+static void gfx_v9_4_3_inst_reset_sq_timeout_status(struct amdgpu_device *adev,
+ int xcc_id)
+{
+ uint32_t se_idx, sh_idx, cu_idx;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+ for (se_idx = 0; se_idx < adev->gfx.config.max_shader_engines; se_idx++) {
+ for (sh_idx = 0; sh_idx < adev->gfx.config.max_sh_per_se; sh_idx++) {
+ for (cu_idx = 0; cu_idx < adev->gfx.config.max_cu_per_sh; cu_idx++) {
+ gfx_v9_4_3_xcc_select_se_sh(adev, se_idx, sh_idx,
+ cu_idx, xcc_id);
+ WREG32_SOC15(GC, GET_INST(GC, xcc_id),
+ regSQ_TIMEOUT_STATUS, 0);
+ }
+ }
+ }
+ gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
+ xcc_id);
+ mutex_unlock(&adev->grbm_idx_mutex);
+}
+
+static void gfx_v9_4_3_inst_reset_ras_err_status(struct amdgpu_device *adev,
+ void *ras_error_status, int xcc_id)
+{
+ gfx_v9_4_3_inst_reset_utc_err_status(adev, xcc_id);
+ gfx_v9_4_3_inst_reset_ea_err_status(adev, xcc_id);
+ gfx_v9_4_3_inst_reset_sq_timeout_status(adev, xcc_id);
+}
+
+static void gfx_v9_4_3_query_ras_error_count(struct amdgpu_device *adev,
+ void *ras_error_status)
+{
+ amdgpu_gfx_ras_error_func(adev, ras_error_status,
+ gfx_v9_4_3_inst_query_ras_err_count);
+}
+
+static void gfx_v9_4_3_reset_ras_error_count(struct amdgpu_device *adev)
+{
+ amdgpu_gfx_ras_error_func(adev, NULL, gfx_v9_4_3_inst_reset_ras_err_count);
+}
+
+static void gfx_v9_4_3_query_ras_error_status(struct amdgpu_device *adev)
+{
+ amdgpu_gfx_ras_error_func(adev, NULL, gfx_v9_4_3_inst_query_ras_err_status);
+}
+
+static void gfx_v9_4_3_reset_ras_error_status(struct amdgpu_device *adev)
+{
+ amdgpu_gfx_ras_error_func(adev, NULL, gfx_v9_4_3_inst_reset_ras_err_status);
+}
+
+static const struct amd_ip_funcs gfx_v9_4_3_ip_funcs = {
+ .name = "gfx_v9_4_3",
+ .early_init = gfx_v9_4_3_early_init,
+ .late_init = gfx_v9_4_3_late_init,
+ .sw_init = gfx_v9_4_3_sw_init,
+ .sw_fini = gfx_v9_4_3_sw_fini,
+ .hw_init = gfx_v9_4_3_hw_init,
+ .hw_fini = gfx_v9_4_3_hw_fini,
+ .suspend = gfx_v9_4_3_suspend,
+ .resume = gfx_v9_4_3_resume,
+ .is_idle = gfx_v9_4_3_is_idle,
+ .wait_for_idle = gfx_v9_4_3_wait_for_idle,
+ .soft_reset = gfx_v9_4_3_soft_reset,
+ .set_clockgating_state = gfx_v9_4_3_set_clockgating_state,
+ .set_powergating_state = gfx_v9_4_3_set_powergating_state,
+ .get_clockgating_state = gfx_v9_4_3_get_clockgating_state,
+};
+
+static const struct amdgpu_ring_funcs gfx_v9_4_3_ring_funcs_compute = {
+ .type = AMDGPU_RING_TYPE_COMPUTE,
+ .align_mask = 0xff,
+ .nop = PACKET3(PACKET3_NOP, 0x3FFF),
+ .support_64bit_ptrs = true,
+ .get_rptr = gfx_v9_4_3_ring_get_rptr_compute,
+ .get_wptr = gfx_v9_4_3_ring_get_wptr_compute,
+ .set_wptr = gfx_v9_4_3_ring_set_wptr_compute,
+ .emit_frame_size =
+ 20 + /* gfx_v9_4_3_ring_emit_gds_switch */
+ 7 + /* gfx_v9_4_3_ring_emit_hdp_flush */
+ 5 + /* hdp invalidate */
+ 7 + /* gfx_v9_4_3_ring_emit_pipeline_sync */
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
+ 2 + /* gfx_v9_4_3_ring_emit_vm_flush */
+ 8 + 8 + 8 + /* gfx_v9_4_3_ring_emit_fence x3 for user fence, vm fence */
+ 7 + /* gfx_v9_4_3_emit_mem_sync */
+ 5 + /* gfx_v9_4_3_emit_wave_limit for updating regSPI_WCL_PIPE_PERCENT_GFX register */
+ 15, /* for updating 3 regSPI_WCL_PIPE_PERCENT_CS registers */
+ .emit_ib_size = 7, /* gfx_v9_4_3_ring_emit_ib_compute */
+ .emit_ib = gfx_v9_4_3_ring_emit_ib_compute,
+ .emit_fence = gfx_v9_4_3_ring_emit_fence,
+ .emit_pipeline_sync = gfx_v9_4_3_ring_emit_pipeline_sync,
+ .emit_vm_flush = gfx_v9_4_3_ring_emit_vm_flush,
+ .emit_gds_switch = gfx_v9_4_3_ring_emit_gds_switch,
+ .emit_hdp_flush = gfx_v9_4_3_ring_emit_hdp_flush,
+ .test_ring = gfx_v9_4_3_ring_test_ring,
+ .test_ib = gfx_v9_4_3_ring_test_ib,
+ .insert_nop = amdgpu_ring_insert_nop,
+ .pad_ib = amdgpu_ring_generic_pad_ib,
+ .emit_wreg = gfx_v9_4_3_ring_emit_wreg,
+ .emit_reg_wait = gfx_v9_4_3_ring_emit_reg_wait,
+ .emit_reg_write_reg_wait = gfx_v9_4_3_ring_emit_reg_write_reg_wait,
+ .emit_mem_sync = gfx_v9_4_3_emit_mem_sync,
+ .emit_wave_limit = gfx_v9_4_3_emit_wave_limit,
+};
+
+static const struct amdgpu_ring_funcs gfx_v9_4_3_ring_funcs_kiq = {
+ .type = AMDGPU_RING_TYPE_KIQ,
+ .align_mask = 0xff,
+ .nop = PACKET3(PACKET3_NOP, 0x3FFF),
+ .support_64bit_ptrs = true,
+ .get_rptr = gfx_v9_4_3_ring_get_rptr_compute,
+ .get_wptr = gfx_v9_4_3_ring_get_wptr_compute,
+ .set_wptr = gfx_v9_4_3_ring_set_wptr_compute,
+ .emit_frame_size =
+ 20 + /* gfx_v9_4_3_ring_emit_gds_switch */
+ 7 + /* gfx_v9_4_3_ring_emit_hdp_flush */
+ 5 + /* hdp invalidate */
+ 7 + /* gfx_v9_4_3_ring_emit_pipeline_sync */
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
+ 2 + /* gfx_v9_4_3_ring_emit_vm_flush */
+ 8 + 8 + 8, /* gfx_v9_4_3_ring_emit_fence_kiq x3 for user fence, vm fence */
+ .emit_ib_size = 7, /* gfx_v9_4_3_ring_emit_ib_compute */
+ .emit_fence = gfx_v9_4_3_ring_emit_fence_kiq,
+ .test_ring = gfx_v9_4_3_ring_test_ring,
+ .insert_nop = amdgpu_ring_insert_nop,
+ .pad_ib = amdgpu_ring_generic_pad_ib,
+ .emit_rreg = gfx_v9_4_3_ring_emit_rreg,
+ .emit_wreg = gfx_v9_4_3_ring_emit_wreg,
+ .emit_reg_wait = gfx_v9_4_3_ring_emit_reg_wait,
+ .emit_reg_write_reg_wait = gfx_v9_4_3_ring_emit_reg_write_reg_wait,
+};
+
+static void gfx_v9_4_3_set_ring_funcs(struct amdgpu_device *adev)
+{
+ int i, j, num_xcc;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ for (i = 0; i < num_xcc; i++) {
+ adev->gfx.kiq[i].ring.funcs = &gfx_v9_4_3_ring_funcs_kiq;
+
+ for (j = 0; j < adev->gfx.num_compute_rings; j++)
+ adev->gfx.compute_ring[j + i * adev->gfx.num_compute_rings].funcs
+ = &gfx_v9_4_3_ring_funcs_compute;
+ }
+}
+
+static const struct amdgpu_irq_src_funcs gfx_v9_4_3_eop_irq_funcs = {
+ .set = gfx_v9_4_3_set_eop_interrupt_state,
+ .process = gfx_v9_4_3_eop_irq,
+};
+
+static const struct amdgpu_irq_src_funcs gfx_v9_4_3_priv_reg_irq_funcs = {
+ .set = gfx_v9_4_3_set_priv_reg_fault_state,
+ .process = gfx_v9_4_3_priv_reg_irq,
+};
+
+static const struct amdgpu_irq_src_funcs gfx_v9_4_3_priv_inst_irq_funcs = {
+ .set = gfx_v9_4_3_set_priv_inst_fault_state,
+ .process = gfx_v9_4_3_priv_inst_irq,
+};
+
+static void gfx_v9_4_3_set_irq_funcs(struct amdgpu_device *adev)
+{
+ adev->gfx.eop_irq.num_types = AMDGPU_CP_IRQ_LAST;
+ adev->gfx.eop_irq.funcs = &gfx_v9_4_3_eop_irq_funcs;
+
+ adev->gfx.priv_reg_irq.num_types = 1;
+ adev->gfx.priv_reg_irq.funcs = &gfx_v9_4_3_priv_reg_irq_funcs;
+
+ adev->gfx.priv_inst_irq.num_types = 1;
+ adev->gfx.priv_inst_irq.funcs = &gfx_v9_4_3_priv_inst_irq_funcs;
+}
+
+static void gfx_v9_4_3_set_rlc_funcs(struct amdgpu_device *adev)
+{
+ adev->gfx.rlc.funcs = &gfx_v9_4_3_rlc_funcs;
+}
+
+
+static void gfx_v9_4_3_set_gds_init(struct amdgpu_device *adev)
+{
+ /* init asci gds info */
+ switch (adev->ip_versions[GC_HWIP][0]) {
+ case IP_VERSION(9, 4, 3):
+ /* 9.4.3 removed all the GDS internal memory,
+ * only support GWS opcode in kernel, like barrier
+ * semaphore.etc */
+ adev->gds.gds_size = 0;
+ break;
+ default:
+ adev->gds.gds_size = 0x10000;
+ break;
+ }
+
+ switch (adev->ip_versions[GC_HWIP][0]) {
+ case IP_VERSION(9, 4, 3):
+ /* deprecated for 9.4.3, no usage at all */
+ adev->gds.gds_compute_max_wave_id = 0;
+ break;
+ default:
+ /* this really depends on the chip */
+ adev->gds.gds_compute_max_wave_id = 0x7ff;
+ break;
+ }
+
+ adev->gds.gws_size = 64;
+ adev->gds.oa_size = 16;
+}
+
+static void gfx_v9_4_3_set_user_cu_inactive_bitmap(struct amdgpu_device *adev,
+ u32 bitmap)
+{
+ u32 data;
+
+ if (!bitmap)
+ return;
+
+ 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);
+}
+
+static u32 gfx_v9_4_3_get_cu_active_bitmap(struct amdgpu_device *adev)
+{
+ 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 &= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK;
+ data >>= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT;
+
+ mask = amdgpu_gfx_create_bitmask(adev->gfx.config.max_cu_per_sh);
+
+ return (~data) & mask;
+}
+
+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;
+ u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0;
+ unsigned disable_masks[4 * 4];
+
+ if (!adev || !cu_info)
+ return -EINVAL;
+
+ /*
+ * 16 comes from bitmap array size 4*4, and it can cover all gfx9 ASICs
+ */
+ if (adev->gfx.config.max_shader_engines *
+ adev->gfx.config.max_sh_per_se > 16)
+ return -EINVAL;
+
+ amdgpu_gfx_parse_disable_cu(disable_masks,
+ adev->gfx.config.max_shader_engines,
+ 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++;
+ }
+ 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 % 4][j + i / 4] = ao_bitmap;
+ }
+ }
+ 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;
+ cu_info->ao_cu_mask = ao_cu_mask;
+ cu_info->simd_per_cu = NUM_SIMD_PER_CU;
+
+ return 0;
+}
+
+const struct amdgpu_ip_block_version gfx_v9_4_3_ip_block = {
+ .type = AMD_IP_BLOCK_TYPE_GFX,
+ .major = 9,
+ .minor = 4,
+ .rev = 0,
+ .funcs = &gfx_v9_4_3_ip_funcs,
+};
+
+static int gfx_v9_4_3_xcp_resume(void *handle, uint32_t inst_mask)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ uint32_t tmp_mask;
+ int i, r;
+
+ /* TODO : Initialize golden regs */
+ /* gfx_v9_4_3_init_golden_registers(adev); */
+
+ tmp_mask = inst_mask;
+ for_each_inst(i, tmp_mask)
+ gfx_v9_4_3_xcc_constants_init(adev, i);
+
+ if (!amdgpu_sriov_vf(adev)) {
+ tmp_mask = inst_mask;
+ for_each_inst(i, tmp_mask) {
+ r = gfx_v9_4_3_xcc_rlc_resume(adev, i);
+ if (r)
+ return r;
+ }
+ }
+
+ tmp_mask = inst_mask;
+ for_each_inst(i, tmp_mask) {
+ r = gfx_v9_4_3_xcc_cp_resume(adev, i);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static int gfx_v9_4_3_xcp_suspend(void *handle, uint32_t inst_mask)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i;
+
+ for_each_inst(i, inst_mask)
+ gfx_v9_4_3_xcc_fini(adev, i);
+
+ return 0;
+}
+
+struct amdgpu_xcp_ip_funcs gfx_v9_4_3_xcp_funcs = {
+ .suspend = &gfx_v9_4_3_xcp_suspend,
+ .resume = &gfx_v9_4_3_xcp_resume
+};
+
+struct amdgpu_ras_block_hw_ops gfx_v9_4_3_ras_ops = {
+ .query_ras_error_count = &gfx_v9_4_3_query_ras_error_count,
+ .reset_ras_error_count = &gfx_v9_4_3_reset_ras_error_count,
+ .query_ras_error_status = &gfx_v9_4_3_query_ras_error_status,
+ .reset_ras_error_status = &gfx_v9_4_3_reset_ras_error_status,
+};
+
+struct amdgpu_gfx_ras gfx_v9_4_3_ras = {
+ .ras_block = {
+ .hw_ops = &gfx_v9_4_3_ras_ops,
+ },
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.h b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.h
index 84e69701b81a..42d67ee0e7ef 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.h
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.h
@@ -24,7 +24,8 @@
#ifndef __GFX_V9_4_3_H__
#define __GFX_V9_4_3_H__
-extern const struct amdgpu_gfx_funcs gfx_v9_4_3_gfx_funcs;
-extern const struct amdgpu_rlc_funcs gfx_v9_4_3_rlc_funcs;
+extern const struct amdgpu_ip_block_version gfx_v9_4_3_ip_block;
+
+extern struct amdgpu_xcp_ip_funcs gfx_v9_4_3_xcp_funcs;
#endif /* __GFX_V9_4_3_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
index ab2325f6c7ac..d94cc1ec7242 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
@@ -40,7 +40,7 @@ static void gfxhub_v1_0_setup_vm_pt_regs(struct amdgpu_device *adev,
uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
WREG32_SOC15_OFFSET(GC, 0, mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
hub->ctx_addr_distance * vmid,
@@ -247,7 +247,7 @@ static void gfxhub_v1_0_disable_identity_aperture(struct amdgpu_device *adev)
static void gfxhub_v1_0_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
unsigned num_level, block_size;
uint32_t tmp;
int i;
@@ -307,7 +307,7 @@ static void gfxhub_v1_0_setup_vmid_config(struct amdgpu_device *adev)
static void gfxhub_v1_0_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
unsigned i;
for (i = 0 ; i < 18; ++i) {
@@ -338,7 +338,7 @@ static int gfxhub_v1_0_gart_enable(struct amdgpu_device *adev)
static void gfxhub_v1_0_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
u32 tmp;
u32 i;
@@ -411,7 +411,7 @@ static void gfxhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev,
static void gfxhub_v1_0_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
hub->ctx0_ptb_addr_lo32 =
SOC15_REG_OFFSET(GC, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
index c59c6c85fbff..4dabf910334b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
@@ -21,6 +21,7 @@
*
*/
#include "amdgpu.h"
+#include "amdgpu_xcp.h"
#include "gfxhub_v1_2.h"
#include "gfxhub_v1_1.h"
@@ -35,227 +36,288 @@
static u64 gfxhub_v1_2_get_mc_fb_offset(struct amdgpu_device *adev)
{
- return (u64)RREG32_SOC15(GC, 0, regMC_VM_FB_OFFSET) << 24;
+ return (u64)RREG32_SOC15(GC, GET_INST(GC, 0), regMC_VM_FB_OFFSET) << 24;
+}
+
+static void gfxhub_v1_2_xcc_setup_vm_pt_regs(struct amdgpu_device *adev,
+ uint32_t vmid,
+ uint64_t page_table_base,
+ uint32_t xcc_mask)
+{
+ struct amdgpu_vmhub *hub;
+ int i;
+
+ for_each_inst(i, xcc_mask) {
+ hub = &adev->vmhub[AMDGPU_GFXHUB(i)];
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, i),
+ regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
+ hub->ctx_addr_distance * vmid,
+ lower_32_bits(page_table_base));
+
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, i),
+ regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
+ hub->ctx_addr_distance * vmid,
+ upper_32_bits(page_table_base));
+ }
}
static void gfxhub_v1_2_setup_vm_pt_regs(struct amdgpu_device *adev,
uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
-
- WREG32_SOC15_OFFSET(GC, 0, regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
- hub->ctx_addr_distance * vmid,
- lower_32_bits(page_table_base));
+ uint32_t xcc_mask;
- WREG32_SOC15_OFFSET(GC, 0, regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
- hub->ctx_addr_distance * vmid,
- upper_32_bits(page_table_base));
+ xcc_mask = GENMASK(NUM_XCC(adev->gfx.xcc_mask) - 1, 0);
+ gfxhub_v1_2_xcc_setup_vm_pt_regs(adev, vmid, page_table_base, xcc_mask);
}
-static void gfxhub_v1_2_init_gart_aperture_regs(struct amdgpu_device *adev)
+static void gfxhub_v1_2_xcc_init_gart_aperture_regs(struct amdgpu_device *adev,
+ uint32_t xcc_mask)
{
uint64_t pt_base;
+ int i;
if (adev->gmc.pdb0_bo)
pt_base = amdgpu_gmc_pd_addr(adev->gmc.pdb0_bo);
else
pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
- gfxhub_v1_2_setup_vm_pt_regs(adev, 0, pt_base);
+ gfxhub_v1_2_xcc_setup_vm_pt_regs(adev, 0, pt_base, xcc_mask);
/* If use GART for FB translation, vmid0 page table covers both
* vram and system memory (gart)
*/
- if (adev->gmc.pdb0_bo) {
- WREG32_SOC15(GC, 0, regVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
- (u32)(adev->gmc.fb_start >> 12));
- WREG32_SOC15(GC, 0, regVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
- (u32)(adev->gmc.fb_start >> 44));
-
- WREG32_SOC15(GC, 0, regVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
- (u32)(adev->gmc.gart_end >> 12));
- WREG32_SOC15(GC, 0, regVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
- (u32)(adev->gmc.gart_end >> 44));
- } else {
- WREG32_SOC15(GC, 0, regVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
- (u32)(adev->gmc.gart_start >> 12));
- WREG32_SOC15(GC, 0, regVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
- (u32)(adev->gmc.gart_start >> 44));
-
- WREG32_SOC15(GC, 0, regVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
- (u32)(adev->gmc.gart_end >> 12));
- WREG32_SOC15(GC, 0, regVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
- (u32)(adev->gmc.gart_end >> 44));
+ for_each_inst(i, xcc_mask) {
+ if (adev->gmc.pdb0_bo) {
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
+ (u32)(adev->gmc.fb_start >> 12));
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
+ (u32)(adev->gmc.fb_start >> 44));
+
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
+ (u32)(adev->gmc.gart_end >> 12));
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
+ (u32)(adev->gmc.gart_end >> 44));
+ } else {
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
+ (u32)(adev->gmc.gart_start >> 12));
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
+ (u32)(adev->gmc.gart_start >> 44));
+
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
+ (u32)(adev->gmc.gart_end >> 12));
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
+ (u32)(adev->gmc.gart_end >> 44));
+ }
}
}
-static void gfxhub_v1_2_init_system_aperture_regs(struct amdgpu_device *adev)
+static void
+gfxhub_v1_2_xcc_init_system_aperture_regs(struct amdgpu_device *adev,
+ uint32_t xcc_mask)
{
uint64_t value;
uint32_t tmp;
+ int i;
- /* Program the AGP BAR */
- WREG32_SOC15_RLC(GC, 0, regMC_VM_AGP_BASE, 0);
- WREG32_SOC15_RLC(GC, 0, regMC_VM_AGP_BOT, adev->gmc.agp_start >> 24);
- WREG32_SOC15_RLC(GC, 0, regMC_VM_AGP_TOP, adev->gmc.agp_end >> 24);
-
- if (!amdgpu_sriov_vf(adev) || adev->asic_type <= CHIP_VEGA10) {
- /* Program the system aperture low logical page number. */
- WREG32_SOC15_RLC(GC, 0, regMC_VM_SYSTEM_APERTURE_LOW_ADDR,
- min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
-
- if (adev->apu_flags & AMD_APU_IS_RAVEN2)
- /*
- * Raven2 has a HW issue that it is unable to use the
- * vram which is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR.
- * So here is the workaround that increase system
- * aperture high address (add 1) to get rid of the VM
- * fault and hardware hang.
- */
- WREG32_SOC15_RLC(GC, 0,
- regMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
- max((adev->gmc.fb_end >> 18) + 0x1,
- adev->gmc.agp_end >> 18));
- else
- WREG32_SOC15_RLC(GC, 0,
- regMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
- max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
-
- /* Set default page address. */
- value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
- WREG32_SOC15(GC, 0, regMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
- (u32)(value >> 12));
- WREG32_SOC15(GC, 0, regMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
- (u32)(value >> 44));
-
- /* Program "protection fault". */
- WREG32_SOC15(GC, 0, regVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
- (u32)(adev->dummy_page_addr >> 12));
- WREG32_SOC15(GC, 0, regVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
- (u32)((u64)adev->dummy_page_addr >> 44));
-
- tmp = RREG32_SOC15(GC, 0, regVM_L2_PROTECTION_FAULT_CNTL2);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL2,
- ACTIVE_PAGE_MIGRATION_PTE_READ_RETRY, 1);
- WREG32_SOC15(GC, 0, regVM_L2_PROTECTION_FAULT_CNTL2, tmp);
- }
-
- /* In the case squeezing vram into GART aperture, we don't use
- * FB aperture and AGP aperture. Disable them.
- */
- if (adev->gmc.pdb0_bo) {
- WREG32_SOC15(GC, 0, regMC_VM_FB_LOCATION_TOP, 0);
- WREG32_SOC15(GC, 0, regMC_VM_FB_LOCATION_BASE, 0x00FFFFFF);
- WREG32_SOC15(GC, 0, regMC_VM_AGP_TOP, 0);
- WREG32_SOC15(GC, 0, regMC_VM_AGP_BOT, 0xFFFFFF);
- WREG32_SOC15(GC, 0, regMC_VM_SYSTEM_APERTURE_LOW_ADDR, 0x3FFFFFFF);
- WREG32_SOC15(GC, 0, regMC_VM_SYSTEM_APERTURE_HIGH_ADDR, 0);
+ for_each_inst(i, xcc_mask) {
+ /* Program the AGP BAR */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_AGP_BASE, 0);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_AGP_BOT, adev->gmc.agp_start >> 24);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_AGP_TOP, adev->gmc.agp_end >> 24);
+
+ if (!amdgpu_sriov_vf(adev) || adev->asic_type <= CHIP_VEGA10) {
+ /* Program the system aperture low logical page number. */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_SYSTEM_APERTURE_LOW_ADDR,
+ min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
+
+ if (adev->apu_flags & AMD_APU_IS_RAVEN2)
+ /*
+ * Raven2 has a HW issue that it is unable to use the
+ * vram which is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR.
+ * So here is the workaround that increase system
+ * aperture high address (add 1) to get rid of the VM
+ * fault and hardware hang.
+ */
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i),
+ regMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+ max((adev->gmc.fb_end >> 18) + 0x1,
+ adev->gmc.agp_end >> 18));
+ else
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i),
+ regMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+ max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
+
+ /* Set default page address. */
+ value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
+ WREG32_SOC15(GC, GET_INST(GC, i), regMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
+ (u32)(value >> 12));
+ WREG32_SOC15(GC, GET_INST(GC, i), regMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
+ (u32)(value >> 44));
+
+ /* Program "protection fault". */
+ WREG32_SOC15(GC, GET_INST(GC, i), regVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
+ (u32)(adev->dummy_page_addr >> 12));
+ WREG32_SOC15(GC, GET_INST(GC, i), regVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
+ (u32)((u64)adev->dummy_page_addr >> 44));
+
+ tmp = RREG32_SOC15(GC, GET_INST(GC, i), regVM_L2_PROTECTION_FAULT_CNTL2);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL2,
+ ACTIVE_PAGE_MIGRATION_PTE_READ_RETRY, 1);
+ WREG32_SOC15(GC, GET_INST(GC, i), regVM_L2_PROTECTION_FAULT_CNTL2, tmp);
+ }
+
+ /* In the case squeezing vram into GART aperture, we don't use
+ * FB aperture and AGP aperture. Disable them.
+ */
+ if (adev->gmc.pdb0_bo) {
+ WREG32_SOC15(GC, GET_INST(GC, i), regMC_VM_FB_LOCATION_TOP, 0);
+ WREG32_SOC15(GC, GET_INST(GC, i), regMC_VM_FB_LOCATION_BASE, 0x00FFFFFF);
+ WREG32_SOC15(GC, GET_INST(GC, i), regMC_VM_AGP_TOP, 0);
+ WREG32_SOC15(GC, GET_INST(GC, i), regMC_VM_AGP_BOT, 0xFFFFFF);
+ WREG32_SOC15(GC, GET_INST(GC, i), regMC_VM_SYSTEM_APERTURE_LOW_ADDR, 0x3FFFFFFF);
+ WREG32_SOC15(GC, GET_INST(GC, i), regMC_VM_SYSTEM_APERTURE_HIGH_ADDR, 0);
+ }
}
}
-static void gfxhub_v1_2_init_tlb_regs(struct amdgpu_device *adev)
+static void gfxhub_v1_2_xcc_init_tlb_regs(struct amdgpu_device *adev,
+ uint32_t xcc_mask)
{
uint32_t tmp;
+ int i;
- /* Setup TLB control */
- tmp = RREG32_SOC15(GC, 0, regMC_VM_MX_L1_TLB_CNTL);
-
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 1);
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, 3);
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
- ENABLE_ADVANCED_DRIVER_MODEL, 1);
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
- SYSTEM_APERTURE_UNMAPPED_ACCESS, 0);
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
- MTYPE, MTYPE_UC);/* XXX for emulation. */
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ATC_EN, 1);
-
- WREG32_SOC15_RLC(GC, 0, regMC_VM_MX_L1_TLB_CNTL, tmp);
+ for_each_inst(i, xcc_mask) {
+ /* Setup TLB control */
+ tmp = RREG32_SOC15(GC, GET_INST(GC, i), regMC_VM_MX_L1_TLB_CNTL);
+
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
+ ENABLE_L1_TLB, 1);
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
+ SYSTEM_ACCESS_MODE, 3);
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
+ ENABLE_ADVANCED_DRIVER_MODEL, 1);
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
+ SYSTEM_APERTURE_UNMAPPED_ACCESS, 0);
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
+ MTYPE, MTYPE_UC);/* XXX for emulation. */
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ATC_EN, 1);
+
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_MX_L1_TLB_CNTL, tmp);
+ }
}
-static void gfxhub_v1_2_init_cache_regs(struct amdgpu_device *adev)
+static void gfxhub_v1_2_xcc_init_cache_regs(struct amdgpu_device *adev,
+ uint32_t xcc_mask)
{
uint32_t tmp;
+ int i;
- /* Setup L2 cache */
- tmp = RREG32_SOC15(GC, 0, regVM_L2_CNTL);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_CACHE, 1);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING, 1);
- /* XXX for emulation, Refer to closed source code.*/
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, L2_PDE0_CACHE_TAG_GENERATION_MODE,
- 0);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, PDE_FAULT_CLASSIFICATION, 0);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, IDENTITY_MODE_FRAGMENT_SIZE, 0);
- WREG32_SOC15_RLC(GC, 0, regVM_L2_CNTL, tmp);
-
- tmp = RREG32_SOC15(GC, 0, regVM_L2_CNTL2);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
- WREG32_SOC15_RLC(GC, 0, regVM_L2_CNTL2, tmp);
-
- tmp = regVM_L2_CNTL3_DEFAULT;
- if (adev->gmc.translate_further) {
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3, BANK_SELECT, 12);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3,
- L2_CACHE_BIGK_FRAGMENT_SIZE, 9);
- } else {
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3, BANK_SELECT, 9);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3,
- L2_CACHE_BIGK_FRAGMENT_SIZE, 6);
+ for_each_inst(i, xcc_mask) {
+ /* Setup L2 cache */
+ tmp = RREG32_SOC15(GC, GET_INST(GC, i), regVM_L2_CNTL);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_CACHE, 1);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING, 1);
+ /* XXX for emulation, Refer to closed source code.*/
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, L2_PDE0_CACHE_TAG_GENERATION_MODE,
+ 0);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, PDE_FAULT_CLASSIFICATION, 0);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, IDENTITY_MODE_FRAGMENT_SIZE, 0);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i), regVM_L2_CNTL, tmp);
+
+ tmp = RREG32_SOC15(GC, GET_INST(GC, i), regVM_L2_CNTL2);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i), regVM_L2_CNTL2, tmp);
+
+ tmp = regVM_L2_CNTL3_DEFAULT;
+ if (adev->gmc.translate_further) {
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3, BANK_SELECT, 12);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3,
+ L2_CACHE_BIGK_FRAGMENT_SIZE, 9);
+ } else {
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3, BANK_SELECT, 9);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3,
+ L2_CACHE_BIGK_FRAGMENT_SIZE, 6);
+ }
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i), regVM_L2_CNTL3, tmp);
+
+ tmp = regVM_L2_CNTL4_DEFAULT;
+ /* For AMD APP APUs setup WC memory */
+ if (adev->gmc.xgmi.connected_to_cpu || adev->gmc.is_app_apu) {
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4, VMC_TAP_PDE_REQUEST_PHYSICAL, 1);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4, VMC_TAP_PTE_REQUEST_PHYSICAL, 1);
+ } else {
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4, VMC_TAP_PDE_REQUEST_PHYSICAL, 0);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4, VMC_TAP_PTE_REQUEST_PHYSICAL, 0);
+ }
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i), regVM_L2_CNTL4, tmp);
}
- WREG32_SOC15_RLC(GC, 0, regVM_L2_CNTL3, tmp);
-
- tmp = regVM_L2_CNTL4_DEFAULT;
- if (adev->gmc.xgmi.connected_to_cpu) {
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4, VMC_TAP_PDE_REQUEST_PHYSICAL, 1);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4, VMC_TAP_PTE_REQUEST_PHYSICAL, 1);
- } else {
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4, VMC_TAP_PDE_REQUEST_PHYSICAL, 0);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4, VMC_TAP_PTE_REQUEST_PHYSICAL, 0);
- }
- WREG32_SOC15_RLC(GC, 0, regVM_L2_CNTL4, tmp);
}
-static void gfxhub_v1_2_enable_system_domain(struct amdgpu_device *adev)
+static void gfxhub_v1_2_xcc_enable_system_domain(struct amdgpu_device *adev,
+ uint32_t xcc_mask)
{
uint32_t tmp;
+ int i;
- tmp = RREG32_SOC15(GC, 0, regVM_CONTEXT0_CNTL);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH,
- adev->gmc.vmid0_page_table_depth);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, PAGE_TABLE_BLOCK_SIZE,
- adev->gmc.vmid0_page_table_block_size);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL,
- RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
- WREG32_SOC15(GC, 0, regVM_CONTEXT0_CNTL, tmp);
+ for_each_inst(i, xcc_mask) {
+ tmp = RREG32_SOC15(GC, GET_INST(GC, i), regVM_CONTEXT0_CNTL);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH,
+ adev->gmc.vmid0_page_table_depth);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, PAGE_TABLE_BLOCK_SIZE,
+ adev->gmc.vmid0_page_table_block_size);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL,
+ RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
+ WREG32_SOC15(GC, GET_INST(GC, i), regVM_CONTEXT0_CNTL, tmp);
+ }
}
-static void gfxhub_v1_2_disable_identity_aperture(struct amdgpu_device *adev)
+static void
+gfxhub_v1_2_xcc_disable_identity_aperture(struct amdgpu_device *adev,
+ uint32_t xcc_mask)
{
- WREG32_SOC15(GC, 0, regVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32,
- 0XFFFFFFFF);
- WREG32_SOC15(GC, 0, regVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32,
- 0x0000000F);
-
- WREG32_SOC15(GC, 0, regVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_LO32,
- 0);
- WREG32_SOC15(GC, 0, regVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_HI32,
- 0);
-
- WREG32_SOC15(GC, 0, regVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_LO32, 0);
- WREG32_SOC15(GC, 0, regVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_HI32, 0);
+ int i;
+ for_each_inst(i, xcc_mask) {
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32,
+ 0XFFFFFFFF);
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32,
+ 0x0000000F);
+
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_LO32,
+ 0);
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_HI32,
+ 0);
+
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_LO32, 0);
+ WREG32_SOC15(GC, GET_INST(GC, i),
+ regVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_HI32, 0);
+ }
}
-static void gfxhub_v1_2_setup_vmid_config(struct amdgpu_device *adev)
+static void gfxhub_v1_2_xcc_setup_vmid_config(struct amdgpu_device *adev,
+ uint32_t xcc_mask)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub;
unsigned num_level, block_size;
uint32_t tmp;
- int i;
+ int i, j;
num_level = adev->vm_manager.num_level;
block_size = adev->vm_manager.block_size;
@@ -264,124 +326,205 @@ static void gfxhub_v1_2_setup_vmid_config(struct amdgpu_device *adev)
else
block_size -= 9;
- for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(GC, 0, regVM_CONTEXT1_CNTL, i);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
- num_level);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT,
- 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- PAGE_TABLE_BLOCK_SIZE,
- block_size);
- /* Send no-retry XNACK on fault to suppress VM fault storm.
- * On Aldebaran, XNACK can be enabled in the SQ per-process.
- * Retry faults need to be enabled for that to work.
- */
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
- !adev->gmc.noretry ||
- adev->asic_type == CHIP_ALDEBARAN);
- WREG32_SOC15_OFFSET(GC, 0, regVM_CONTEXT1_CNTL,
- i * hub->ctx_distance, tmp);
- WREG32_SOC15_OFFSET(GC, 0,
- regVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
- i * hub->ctx_addr_distance, 0);
- WREG32_SOC15_OFFSET(GC, 0,
- regVM_CONTEXT1_PAGE_TABLE_START_ADDR_HI32,
- i * hub->ctx_addr_distance, 0);
- WREG32_SOC15_OFFSET(GC, 0,
- regVM_CONTEXT1_PAGE_TABLE_END_ADDR_LO32,
- i * hub->ctx_addr_distance,
- lower_32_bits(adev->vm_manager.max_pfn - 1));
- WREG32_SOC15_OFFSET(GC, 0,
- regVM_CONTEXT1_PAGE_TABLE_END_ADDR_HI32,
- i * hub->ctx_addr_distance,
- upper_32_bits(adev->vm_manager.max_pfn - 1));
+ for_each_inst(j, xcc_mask) {
+ hub = &adev->vmhub[AMDGPU_GFXHUB(j)];
+ for (i = 0; i <= 14; i++) {
+ tmp = RREG32_SOC15_OFFSET(GC, GET_INST(GC, j), regVM_CONTEXT1_CNTL, i);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
+ num_level);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT,
+ 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ PAGE_TABLE_BLOCK_SIZE,
+ block_size);
+ /* Send no-retry XNACK on fault to suppress VM fault storm.
+ * On 9.4.2 and 9.4.3, XNACK can be enabled in
+ * the SQ per-process.
+ * Retry faults need to be enabled for that to work.
+ */
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
+ !adev->gmc.noretry ||
+ adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2) ||
+ adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3));
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, j), regVM_CONTEXT1_CNTL,
+ i * hub->ctx_distance, tmp);
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, j),
+ regVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
+ i * hub->ctx_addr_distance, 0);
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, j),
+ regVM_CONTEXT1_PAGE_TABLE_START_ADDR_HI32,
+ i * hub->ctx_addr_distance, 0);
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, j),
+ regVM_CONTEXT1_PAGE_TABLE_END_ADDR_LO32,
+ i * hub->ctx_addr_distance,
+ lower_32_bits(adev->vm_manager.max_pfn - 1));
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, j),
+ regVM_CONTEXT1_PAGE_TABLE_END_ADDR_HI32,
+ i * hub->ctx_addr_distance,
+ upper_32_bits(adev->vm_manager.max_pfn - 1));
+ }
}
}
-static void gfxhub_v1_2_program_invalidation(struct amdgpu_device *adev)
+static void gfxhub_v1_2_xcc_program_invalidation(struct amdgpu_device *adev,
+ uint32_t xcc_mask)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
- unsigned i;
-
- for (i = 0 ; i < 18; ++i) {
- WREG32_SOC15_OFFSET(GC, 0, regVM_INVALIDATE_ENG0_ADDR_RANGE_LO32,
- i * hub->eng_addr_distance, 0xffffffff);
- WREG32_SOC15_OFFSET(GC, 0, regVM_INVALIDATE_ENG0_ADDR_RANGE_HI32,
- i * hub->eng_addr_distance, 0x1f);
+ struct amdgpu_vmhub *hub;
+ unsigned int i, j;
+
+ for_each_inst(j, xcc_mask) {
+ hub = &adev->vmhub[AMDGPU_GFXHUB(j)];
+
+ for (i = 0 ; i < 18; ++i) {
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, j), regVM_INVALIDATE_ENG0_ADDR_RANGE_LO32,
+ i * hub->eng_addr_distance, 0xffffffff);
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, j), regVM_INVALIDATE_ENG0_ADDR_RANGE_HI32,
+ i * hub->eng_addr_distance, 0x1f);
+ }
}
}
-static int gfxhub_v1_2_gart_enable(struct amdgpu_device *adev)
+static int gfxhub_v1_2_xcc_gart_enable(struct amdgpu_device *adev,
+ uint32_t xcc_mask)
{
- if (amdgpu_sriov_vf(adev) && adev->asic_type != CHIP_ARCTURUS) {
- /*
- * MC_VM_FB_LOCATION_BASE/TOP is NULL for VF, becuase they are
- * VF copy registers so vbios post doesn't program them, for
- * SRIOV driver need to program them
- */
- WREG32_SOC15_RLC(GC, 0, regMC_VM_FB_LOCATION_BASE,
- adev->gmc.vram_start >> 24);
- WREG32_SOC15_RLC(GC, 0, regMC_VM_FB_LOCATION_TOP,
- adev->gmc.vram_end >> 24);
+ uint32_t tmp_mask;
+ int i;
+
+ tmp_mask = xcc_mask;
+ /*
+ * MC_VM_FB_LOCATION_BASE/TOP is NULL for VF, because they are
+ * VF copy registers so vbios post doesn't program them, for
+ * SRIOV driver need to program them
+ */
+ if (amdgpu_sriov_vf(adev)) {
+ for_each_inst(i, tmp_mask) {
+ i = ffs(tmp_mask) - 1;
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_FB_LOCATION_BASE,
+ adev->gmc.vram_start >> 24);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_FB_LOCATION_TOP,
+ adev->gmc.vram_end >> 24);
+ }
}
/* GART Enable. */
- gfxhub_v1_2_init_gart_aperture_regs(adev);
- gfxhub_v1_2_init_system_aperture_regs(adev);
- gfxhub_v1_2_init_tlb_regs(adev);
+ gfxhub_v1_2_xcc_init_gart_aperture_regs(adev, xcc_mask);
+ gfxhub_v1_2_xcc_init_system_aperture_regs(adev, xcc_mask);
+ gfxhub_v1_2_xcc_init_tlb_regs(adev, xcc_mask);
if (!amdgpu_sriov_vf(adev))
- gfxhub_v1_2_init_cache_regs(adev);
+ gfxhub_v1_2_xcc_init_cache_regs(adev, xcc_mask);
- gfxhub_v1_2_enable_system_domain(adev);
+ gfxhub_v1_2_xcc_enable_system_domain(adev, xcc_mask);
if (!amdgpu_sriov_vf(adev))
- gfxhub_v1_2_disable_identity_aperture(adev);
- gfxhub_v1_2_setup_vmid_config(adev);
- gfxhub_v1_2_program_invalidation(adev);
+ gfxhub_v1_2_xcc_disable_identity_aperture(adev, xcc_mask);
+ gfxhub_v1_2_xcc_setup_vmid_config(adev, xcc_mask);
+ gfxhub_v1_2_xcc_program_invalidation(adev, xcc_mask);
return 0;
}
+static int gfxhub_v1_2_gart_enable(struct amdgpu_device *adev)
+{
+ uint32_t xcc_mask;
+
+ xcc_mask = GENMASK(NUM_XCC(adev->gfx.xcc_mask) - 1, 0);
+ return gfxhub_v1_2_xcc_gart_enable(adev, xcc_mask);
+}
+
+static void gfxhub_v1_2_xcc_gart_disable(struct amdgpu_device *adev,
+ uint32_t xcc_mask)
+{
+ struct amdgpu_vmhub *hub;
+ u32 tmp;
+ u32 i, j;
+
+ for_each_inst(j, xcc_mask) {
+ hub = &adev->vmhub[AMDGPU_GFXHUB(j)];
+ /* Disable all tables */
+ for (i = 0; i < 16; i++)
+ WREG32_SOC15_OFFSET(GC, GET_INST(GC, j), regVM_CONTEXT0_CNTL,
+ i * hub->ctx_distance, 0);
+
+ /* Setup TLB control */
+ tmp = RREG32_SOC15(GC, GET_INST(GC, j), regMC_VM_MX_L1_TLB_CNTL);
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 0);
+ tmp = REG_SET_FIELD(tmp,
+ MC_VM_MX_L1_TLB_CNTL,
+ ENABLE_ADVANCED_DRIVER_MODEL,
+ 0);
+ WREG32_SOC15_RLC(GC, GET_INST(GC, j), regMC_VM_MX_L1_TLB_CNTL, tmp);
+
+ /* Setup L2 cache */
+ tmp = RREG32_SOC15(GC, GET_INST(GC, j), regVM_L2_CNTL);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_CACHE, 0);
+ WREG32_SOC15(GC, GET_INST(GC, j), regVM_L2_CNTL, tmp);
+ WREG32_SOC15(GC, GET_INST(GC, j), regVM_L2_CNTL3, 0);
+ }
+}
+
static void gfxhub_v1_2_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ uint32_t xcc_mask;
+
+ xcc_mask = GENMASK(NUM_XCC(adev->gfx.xcc_mask) - 1, 0);
+ gfxhub_v1_2_xcc_gart_disable(adev, xcc_mask);
+}
+
+static void gfxhub_v1_2_xcc_set_fault_enable_default(struct amdgpu_device *adev,
+ bool value,
+ uint32_t xcc_mask)
+{
u32 tmp;
- u32 i;
-
- /* Disable all tables */
- for (i = 0; i < 16; i++)
- WREG32_SOC15_OFFSET(GC, 0, regVM_CONTEXT0_CNTL,
- i * hub->ctx_distance, 0);
-
- /* Setup TLB control */
- tmp = RREG32_SOC15(GC, 0, regMC_VM_MX_L1_TLB_CNTL);
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 0);
- tmp = REG_SET_FIELD(tmp,
- MC_VM_MX_L1_TLB_CNTL,
- ENABLE_ADVANCED_DRIVER_MODEL,
- 0);
- WREG32_SOC15_RLC(GC, 0, regMC_VM_MX_L1_TLB_CNTL, tmp);
-
- /* Setup L2 cache */
- tmp = RREG32_SOC15(GC, 0, regVM_L2_CNTL);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_CACHE, 0);
- WREG32_SOC15(GC, 0, regVM_L2_CNTL, tmp);
- WREG32_SOC15(GC, 0, regVM_L2_CNTL3, 0);
+ int i;
+
+ for_each_inst(i, xcc_mask) {
+ tmp = RREG32_SOC15(GC, GET_INST(GC, i), regVM_L2_PROTECTION_FAULT_CNTL);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ PDE1_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ PDE2_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp,
+ VM_L2_PROTECTION_FAULT_CNTL,
+ TRANSLATE_FURTHER_PROTECTION_FAULT_ENABLE_DEFAULT,
+ value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ NACK_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ if (!value) {
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ CRASH_ON_NO_RETRY_FAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ CRASH_ON_RETRY_FAULT, 1);
+ }
+ WREG32_SOC15(GC, GET_INST(GC, i), regVM_L2_PROTECTION_FAULT_CNTL, tmp);
+ }
}
/**
@@ -393,72 +536,100 @@ static void gfxhub_v1_2_gart_disable(struct amdgpu_device *adev)
static void gfxhub_v1_2_set_fault_enable_default(struct amdgpu_device *adev,
bool value)
{
- u32 tmp;
- tmp = RREG32_SOC15(GC, 0, regVM_L2_PROTECTION_FAULT_CNTL);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- PDE1_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- PDE2_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp,
- VM_L2_PROTECTION_FAULT_CNTL,
- TRANSLATE_FURTHER_PROTECTION_FAULT_ENABLE_DEFAULT,
- value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- NACK_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- if (!value) {
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- CRASH_ON_NO_RETRY_FAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- CRASH_ON_RETRY_FAULT, 1);
- }
- WREG32_SOC15(GC, 0, regVM_L2_PROTECTION_FAULT_CNTL, tmp);
+ uint32_t xcc_mask;
+
+ xcc_mask = GENMASK(NUM_XCC(adev->gfx.xcc_mask) - 1, 0);
+ gfxhub_v1_2_xcc_set_fault_enable_default(adev, value, xcc_mask);
}
-static void gfxhub_v1_2_init(struct amdgpu_device *adev)
+static void gfxhub_v1_2_xcc_init(struct amdgpu_device *adev, uint32_t xcc_mask)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub;
+ int i;
+
+ for_each_inst(i, xcc_mask) {
+ hub = &adev->vmhub[AMDGPU_GFXHUB(i)];
- hub->ctx0_ptb_addr_lo32 =
- SOC15_REG_OFFSET(GC, 0,
+ hub->ctx0_ptb_addr_lo32 =
+ SOC15_REG_OFFSET(GC, GET_INST(GC, i),
regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32);
- hub->ctx0_ptb_addr_hi32 =
- SOC15_REG_OFFSET(GC, 0,
+ hub->ctx0_ptb_addr_hi32 =
+ SOC15_REG_OFFSET(GC, GET_INST(GC, i),
regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
- hub->vm_inv_eng0_sem =
- SOC15_REG_OFFSET(GC, 0, regVM_INVALIDATE_ENG0_SEM);
- hub->vm_inv_eng0_req =
- SOC15_REG_OFFSET(GC, 0, regVM_INVALIDATE_ENG0_REQ);
- hub->vm_inv_eng0_ack =
- SOC15_REG_OFFSET(GC, 0, regVM_INVALIDATE_ENG0_ACK);
- hub->vm_context0_cntl =
- SOC15_REG_OFFSET(GC, 0, regVM_CONTEXT0_CNTL);
- hub->vm_l2_pro_fault_status =
- SOC15_REG_OFFSET(GC, 0, regVM_L2_PROTECTION_FAULT_STATUS);
- hub->vm_l2_pro_fault_cntl =
- SOC15_REG_OFFSET(GC, 0, regVM_L2_PROTECTION_FAULT_CNTL);
-
- hub->ctx_distance = regVM_CONTEXT1_CNTL - regVM_CONTEXT0_CNTL;
- hub->ctx_addr_distance = regVM_CONTEXT1_PAGE_TABLE_BASE_ADDR_LO32 -
- regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32;
- hub->eng_distance = regVM_INVALIDATE_ENG1_REQ - regVM_INVALIDATE_ENG0_REQ;
- hub->eng_addr_distance = regVM_INVALIDATE_ENG1_ADDR_RANGE_LO32 -
- regVM_INVALIDATE_ENG0_ADDR_RANGE_LO32;
+ hub->vm_inv_eng0_sem =
+ SOC15_REG_OFFSET(GC, GET_INST(GC, i), regVM_INVALIDATE_ENG0_SEM);
+ hub->vm_inv_eng0_req =
+ SOC15_REG_OFFSET(GC, GET_INST(GC, i), regVM_INVALIDATE_ENG0_REQ);
+ hub->vm_inv_eng0_ack =
+ SOC15_REG_OFFSET(GC, GET_INST(GC, i), regVM_INVALIDATE_ENG0_ACK);
+ hub->vm_context0_cntl =
+ SOC15_REG_OFFSET(GC, GET_INST(GC, i), regVM_CONTEXT0_CNTL);
+ hub->vm_l2_pro_fault_status =
+ SOC15_REG_OFFSET(GC, GET_INST(GC, i),
+ regVM_L2_PROTECTION_FAULT_STATUS);
+ hub->vm_l2_pro_fault_cntl =
+ SOC15_REG_OFFSET(GC, GET_INST(GC, i), regVM_L2_PROTECTION_FAULT_CNTL);
+
+ hub->ctx_distance = regVM_CONTEXT1_CNTL -
+ regVM_CONTEXT0_CNTL;
+ hub->ctx_addr_distance =
+ regVM_CONTEXT1_PAGE_TABLE_BASE_ADDR_LO32 -
+ regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32;
+ hub->eng_distance = regVM_INVALIDATE_ENG1_REQ -
+ regVM_INVALIDATE_ENG0_REQ;
+ hub->eng_addr_distance =
+ regVM_INVALIDATE_ENG1_ADDR_RANGE_LO32 -
+ regVM_INVALIDATE_ENG0_ADDR_RANGE_LO32;
+ }
}
+static void gfxhub_v1_2_init(struct amdgpu_device *adev)
+{
+ uint32_t xcc_mask;
+
+ xcc_mask = GENMASK(NUM_XCC(adev->gfx.xcc_mask) - 1, 0);
+ gfxhub_v1_2_xcc_init(adev, xcc_mask);
+}
+
+static int gfxhub_v1_2_get_xgmi_info(struct amdgpu_device *adev)
+{
+ u32 max_num_physical_nodes;
+ u32 max_physical_node_id;
+ u32 xgmi_lfb_cntl;
+ u32 max_region;
+ u64 seg_size;
+
+ xgmi_lfb_cntl = RREG32_SOC15(GC, GET_INST(GC, 0), regMC_VM_XGMI_LFB_CNTL);
+ seg_size = REG_GET_FIELD(
+ RREG32_SOC15(GC, GET_INST(GC, 0), regMC_VM_XGMI_LFB_SIZE),
+ MC_VM_XGMI_LFB_SIZE, PF_LFB_SIZE) << 24;
+ max_region =
+ REG_GET_FIELD(xgmi_lfb_cntl, MC_VM_XGMI_LFB_CNTL, PF_MAX_REGION);
+
+
+
+ max_num_physical_nodes = 8;
+ max_physical_node_id = 7;
+
+ /* PF_MAX_REGION=0 means xgmi is disabled */
+ if (max_region || adev->gmc.xgmi.connected_to_cpu) {
+ adev->gmc.xgmi.num_physical_nodes = max_region + 1;
+
+ if (adev->gmc.xgmi.num_physical_nodes > max_num_physical_nodes)
+ return -EINVAL;
+
+ adev->gmc.xgmi.physical_node_id =
+ REG_GET_FIELD(xgmi_lfb_cntl, MC_VM_XGMI_LFB_CNTL,
+ PF_LFB_REGION);
+
+ if (adev->gmc.xgmi.physical_node_id > max_physical_node_id)
+ return -EINVAL;
+
+ adev->gmc.xgmi.node_segment_size = seg_size;
+ }
+
+ return 0;
+}
const struct amdgpu_gfxhub_funcs gfxhub_v1_2_funcs = {
.get_mc_fb_offset = gfxhub_v1_2_get_mc_fb_offset,
@@ -467,5 +638,38 @@ const struct amdgpu_gfxhub_funcs gfxhub_v1_2_funcs = {
.gart_disable = gfxhub_v1_2_gart_disable,
.set_fault_enable_default = gfxhub_v1_2_set_fault_enable_default,
.init = gfxhub_v1_2_init,
- .get_xgmi_info = gfxhub_v1_1_get_xgmi_info,
+ .get_xgmi_info = gfxhub_v1_2_get_xgmi_info,
+};
+
+static int gfxhub_v1_2_xcp_resume(void *handle, uint32_t inst_mask)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ bool value;
+
+ if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS)
+ value = false;
+ else
+ value = true;
+
+ gfxhub_v1_2_xcc_set_fault_enable_default(adev, value, inst_mask);
+
+ if (!amdgpu_sriov_vf(adev))
+ return gfxhub_v1_2_xcc_gart_enable(adev, inst_mask);
+
+ return 0;
+}
+
+static int gfxhub_v1_2_xcp_suspend(void *handle, uint32_t inst_mask)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ if (!amdgpu_sriov_vf(adev))
+ gfxhub_v1_2_xcc_gart_disable(adev, inst_mask);
+
+ return 0;
+}
+
+struct amdgpu_xcp_ip_funcs gfxhub_v1_2_xcp_funcs = {
+ .suspend = &gfxhub_v1_2_xcp_suspend,
+ .resume = &gfxhub_v1_2_xcp_resume
};
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.h b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.h
index e2d508f5a7ee..997e9f90c990 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.h
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.h
@@ -26,4 +26,6 @@
extern const struct amdgpu_gfxhub_funcs gfxhub_v1_2_funcs;
+extern struct amdgpu_xcp_ip_funcs gfxhub_v1_2_xcp_funcs;
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c
index 9b3a02527318..f173a61c6c15 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c
@@ -120,7 +120,7 @@ static u64 gfxhub_v2_0_get_mc_fb_offset(struct amdgpu_device *adev)
static void gfxhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
hub->ctx_addr_distance * vmid,
@@ -282,7 +282,7 @@ static void gfxhub_v2_0_disable_identity_aperture(struct amdgpu_device *adev)
static void gfxhub_v2_0_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
int i;
uint32_t tmp;
@@ -331,7 +331,7 @@ static void gfxhub_v2_0_setup_vmid_config(struct amdgpu_device *adev)
static void gfxhub_v2_0_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
unsigned i;
for (i = 0 ; i < 18; ++i) {
@@ -360,7 +360,7 @@ static int gfxhub_v2_0_gart_enable(struct amdgpu_device *adev)
static void gfxhub_v2_0_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
u32 tmp;
u32 i;
@@ -433,7 +433,7 @@ static const struct amdgpu_vmhub_funcs gfxhub_v2_0_vmhub_funcs = {
static void gfxhub_v2_0_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
hub->ctx0_ptb_addr_lo32 =
SOC15_REG_OFFSET(GC, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c
index 4aacbbec31e2..d8fc3e8088cd 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c
@@ -123,7 +123,7 @@ static u64 gfxhub_v2_1_get_mc_fb_offset(struct amdgpu_device *adev)
static void gfxhub_v2_1_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
hub->ctx_addr_distance * vmid,
@@ -291,7 +291,7 @@ static void gfxhub_v2_1_disable_identity_aperture(struct amdgpu_device *adev)
static void gfxhub_v2_1_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
int i;
uint32_t tmp;
@@ -340,7 +340,7 @@ static void gfxhub_v2_1_setup_vmid_config(struct amdgpu_device *adev)
static void gfxhub_v2_1_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
unsigned i;
for (i = 0 ; i < 18; ++i) {
@@ -381,7 +381,7 @@ static int gfxhub_v2_1_gart_enable(struct amdgpu_device *adev)
static void gfxhub_v2_1_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
u32 tmp;
u32 i;
@@ -462,7 +462,7 @@ static const struct amdgpu_vmhub_funcs gfxhub_v2_1_vmhub_funcs = {
static void gfxhub_v2_1_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
hub->ctx0_ptb_addr_lo32 =
SOC15_REG_OFFSET(GC, 0,
@@ -651,7 +651,7 @@ static void gfxhub_v2_1_restore_regs(struct amdgpu_device *adev)
static void gfxhub_v2_1_halt(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
int i;
uint32_t tmp;
int time = 1000;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c
index 13712640fa46..c53147f9c9fc 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c
@@ -119,7 +119,7 @@ static u64 gfxhub_v3_0_get_mc_fb_offset(struct amdgpu_device *adev)
static void gfxhub_v3_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
hub->ctx_addr_distance * vmid,
@@ -290,7 +290,7 @@ static void gfxhub_v3_0_disable_identity_aperture(struct amdgpu_device *adev)
static void gfxhub_v3_0_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
int i;
uint32_t tmp;
@@ -339,7 +339,7 @@ static void gfxhub_v3_0_setup_vmid_config(struct amdgpu_device *adev)
static void gfxhub_v3_0_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
unsigned i;
for (i = 0 ; i < 18; ++i) {
@@ -380,7 +380,7 @@ static int gfxhub_v3_0_gart_enable(struct amdgpu_device *adev)
static void gfxhub_v3_0_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
u32 tmp;
u32 i;
@@ -463,7 +463,7 @@ static const struct amdgpu_vmhub_funcs gfxhub_v3_0_vmhub_funcs = {
static void gfxhub_v3_0_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
hub->ctx0_ptb_addr_lo32 =
SOC15_REG_OFFSET(GC, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c
index 6e0bd628c889..ae777487d72e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c
@@ -122,7 +122,7 @@ static u64 gfxhub_v3_0_3_get_mc_fb_offset(struct amdgpu_device *adev)
static void gfxhub_v3_0_3_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
hub->ctx_addr_distance * vmid,
@@ -295,7 +295,7 @@ static void gfxhub_v3_0_3_disable_identity_aperture(struct amdgpu_device *adev)
static void gfxhub_v3_0_3_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
int i;
uint32_t tmp;
@@ -344,7 +344,7 @@ static void gfxhub_v3_0_3_setup_vmid_config(struct amdgpu_device *adev)
static void gfxhub_v3_0_3_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
unsigned i;
for (i = 0 ; i < 18; ++i) {
@@ -373,7 +373,7 @@ static int gfxhub_v3_0_3_gart_enable(struct amdgpu_device *adev)
static void gfxhub_v3_0_3_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
u32 tmp;
u32 i;
@@ -451,7 +451,7 @@ static const struct amdgpu_vmhub_funcs gfxhub_v3_0_3_vmhub_funcs = {
static void gfxhub_v3_0_3_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
hub->ctx0_ptb_addr_lo32 =
SOC15_REG_OFFSET(GC, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
index b213dcf8ca06..0c8a47989576 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -76,7 +76,7 @@ gmc_v10_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
/* MM HUB */
- amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_MMHUB_0, false);
+ amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_MMHUB0(0), false);
/* GFX HUB */
/* This works because this interrupt is only
* enabled at init/resume and disabled in
@@ -84,11 +84,11 @@ gmc_v10_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
* change over the course of suspend/resume.
*/
if (!adev->in_s0ix)
- amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB_0, false);
+ amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB(0), false);
break;
case AMDGPU_IRQ_STATE_ENABLE:
/* MM HUB */
- amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_MMHUB_0, true);
+ amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_MMHUB0(0), true);
/* GFX HUB */
/* This works because this interrupt is only
* enabled at init/resume and disabled in
@@ -96,7 +96,7 @@ gmc_v10_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
* change over the course of suspend/resume.
*/
if (!adev->in_s0ix)
- amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB_0, true);
+ amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB(0), true);
break;
default:
break;
@@ -139,7 +139,7 @@ static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev,
/* Try to handle the recoverable page faults by filling page
* tables
*/
- if (amdgpu_vm_handle_fault(adev, entry->pasid, addr, write_fault))
+ if (amdgpu_vm_handle_fault(adev, entry->pasid, 0, 0, addr, write_fault))
return 1;
}
@@ -149,7 +149,7 @@ static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev,
* be updated to avoid reading an incorrect value due to
* the new fast GRBM interface.
*/
- if ((entry->vmid_src == AMDGPU_GFXHUB_0) &&
+ if ((entry->vmid_src == AMDGPU_GFXHUB(0)) &&
(adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 3, 0)))
RREG32(hub->vm_l2_pro_fault_status);
@@ -212,8 +212,7 @@ static void gmc_v10_0_set_irq_funcs(struct amdgpu_device *adev)
static bool gmc_v10_0_use_invalidate_semaphore(struct amdgpu_device *adev,
uint32_t vmhub)
{
- return ((vmhub == AMDGPU_MMHUB_0 ||
- vmhub == AMDGPU_MMHUB_1) &&
+ return ((vmhub == AMDGPU_MMHUB0(0)) &&
(!amdgpu_sriov_vf(adev)));
}
@@ -249,7 +248,7 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
unsigned int i;
unsigned char hub_ip = 0;
- hub_ip = (vmhub == AMDGPU_GFXHUB_0) ?
+ hub_ip = (vmhub == AMDGPU_GFXHUB(0)) ?
GC_HWIP : MMHUB_HWIP;
spin_lock(&adev->gmc.invalidate_lock);
@@ -284,7 +283,7 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
* Issue a dummy read to wait for the ACK register to be cleared
* to avoid a false ACK due to the new fast GRBM interface.
*/
- if ((vmhub == AMDGPU_GFXHUB_0) &&
+ if ((vmhub == AMDGPU_GFXHUB(0)) &&
(adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 3, 0)))
RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_req +
hub->eng_distance * eng, hub_ip);
@@ -343,7 +342,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
/* For SRIOV run time, driver shouldn't access the register through MMIO
* Directly use kiq to do the vm invalidation instead
*/
- if (adev->gfx.kiq.ring.sched.ready && !adev->enable_mes &&
+ if (adev->gfx.kiq[0].ring.sched.ready && !adev->enable_mes &&
(amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) &&
down_read_trylock(&adev->reset_domain->sem)) {
struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
@@ -361,19 +360,19 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
mutex_lock(&adev->mman.gtt_window_lock);
- if (vmhub == AMDGPU_MMHUB_0) {
- gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_MMHUB_0, 0);
+ if (vmhub == AMDGPU_MMHUB0(0)) {
+ gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_MMHUB0(0), 0);
mutex_unlock(&adev->mman.gtt_window_lock);
return;
}
- BUG_ON(vmhub != AMDGPU_GFXHUB_0);
+ BUG_ON(vmhub != AMDGPU_GFXHUB(0));
if (!adev->mman.buffer_funcs_enabled ||
!adev->ib_pool_ready ||
amdgpu_in_reset(adev) ||
ring->sched.ready == false) {
- gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_GFXHUB_0, 0);
+ gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_GFXHUB(0), 0);
mutex_unlock(&adev->mman.gtt_window_lock);
return;
}
@@ -383,7 +382,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
* translation. Avoid this by doing the invalidation from the SDMA
* itself.
*/
- r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.entity,
+ r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.high_pr,
AMDGPU_FENCE_OWNER_UNDEFINED,
16 * 4, AMDGPU_IB_POOL_IMMEDIATE,
&job);
@@ -415,12 +414,13 @@ error_alloc:
* @pasid: pasid to be flush
* @flush_type: the flush type
* @all_hub: Used with PACKET3_INVALIDATE_TLBS_ALL_HUB()
+ * @inst: is used to select which instance of KIQ to use for the invalidation
*
* Flush the TLB for the requested pasid.
*/
static int gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
uint16_t pasid, uint32_t flush_type,
- bool all_hub)
+ bool all_hub, uint32_t inst)
{
int vmid, i;
signed long r;
@@ -428,11 +428,11 @@ static int gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
uint16_t queried_pasid;
bool ret;
u32 usec_timeout = amdgpu_sriov_vf(adev) ? SRIOV_USEC_TIMEOUT : adev->usec_timeout;
- struct amdgpu_ring *ring = &adev->gfx.kiq.ring;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_ring *ring = &adev->gfx.kiq[0].ring;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
if (amdgpu_emu_mode == 0 && ring->sched.ready) {
- spin_lock(&adev->gfx.kiq.ring_lock);
+ spin_lock(&adev->gfx.kiq[0].ring_lock);
/* 2 dwords flush + 8 dwords fence */
amdgpu_ring_alloc(ring, kiq->pmf->invalidate_tlbs_size + 8);
kiq->pmf->kiq_invalidate_tlbs(ring,
@@ -440,12 +440,12 @@ static int gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
if (r) {
amdgpu_ring_undo(ring);
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&adev->gfx.kiq[0].ring_lock);
return -ETIME;
}
amdgpu_ring_commit(ring);
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&adev->gfx.kiq[0].ring_lock);
r = amdgpu_fence_wait_polling(ring, seq, usec_timeout);
if (r < 1) {
dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
@@ -461,12 +461,12 @@ static int gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
&queried_pasid);
if (ret && queried_pasid == pasid) {
if (all_hub) {
- for (i = 0; i < adev->num_vmhubs; i++)
+ for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
gmc_v10_0_flush_gpu_tlb(adev, vmid,
i, flush_type);
} else {
gmc_v10_0_flush_gpu_tlb(adev, vmid,
- AMDGPU_GFXHUB_0, flush_type);
+ AMDGPU_GFXHUB(0), flush_type);
}
if (!adev->enable_mes)
break;
@@ -534,7 +534,7 @@ static void gmc_v10_0_emit_pasid_mapping(struct amdgpu_ring *ring, unsigned vmid
if (ring->is_mes_queue)
return;
- if (ring->vm_hub == AMDGPU_GFXHUB_0)
+ if (ring->vm_hub == AMDGPU_GFXHUB(0))
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT) + vmid;
else
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT_MM) + vmid;
@@ -929,7 +929,8 @@ static int gmc_v10_0_sw_init(void *handle)
case IP_VERSION(10, 3, 6):
case IP_VERSION(10, 3, 3):
case IP_VERSION(10, 3, 7):
- adev->num_vmhubs = 2;
+ set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
+ set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
/*
* To fulfill 4-level page support,
* vm size is 256TB (48bit), maximum size of Navi10/Navi14/Navi12,
@@ -1075,9 +1076,9 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev)
if (!adev->in_s0ix)
adev->gfxhub.funcs->set_fault_enable_default(adev, value);
adev->mmhub.funcs->set_fault_enable_default(adev, value);
- gmc_v10_0_flush_gpu_tlb(adev, 0, AMDGPU_MMHUB_0, 0);
+ gmc_v10_0_flush_gpu_tlb(adev, 0, AMDGPU_MMHUB0(0), 0);
if (!adev->in_s0ix)
- gmc_v10_0_flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB_0, 0);
+ gmc_v10_0_flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB(0), 0);
DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
(unsigned)(adev->gmc.gart_size >> 20),
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
index 4116c112e8a0..c571f0d95994 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
@@ -64,7 +64,7 @@ gmc_v11_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
/* MM HUB */
- amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_MMHUB_0, false);
+ amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_MMHUB0(0), false);
/* GFX HUB */
/* This works because this interrupt is only
* enabled at init/resume and disabled in
@@ -72,11 +72,11 @@ gmc_v11_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
* change over the course of suspend/resume.
*/
if (!adev->in_s0ix)
- amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB_0, false);
+ amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB(0), false);
break;
case AMDGPU_IRQ_STATE_ENABLE:
/* MM HUB */
- amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_MMHUB_0, true);
+ amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_MMHUB0(0), true);
/* GFX HUB */
/* This works because this interrupt is only
* enabled at init/resume and disabled in
@@ -84,7 +84,7 @@ gmc_v11_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
* change over the course of suspend/resume.
*/
if (!adev->in_s0ix)
- amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB_0, true);
+ amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB(0), true);
break;
default:
break;
@@ -110,7 +110,7 @@ static int gmc_v11_0_process_interrupt(struct amdgpu_device *adev,
* be updated to avoid reading an incorrect value due to
* the new fast GRBM interface.
*/
- if (entry->vmid_src == AMDGPU_GFXHUB_0)
+ if (entry->vmid_src == AMDGPU_GFXHUB(0))
RREG32(hub->vm_l2_pro_fault_status);
status = RREG32(hub->vm_l2_pro_fault_status);
@@ -170,7 +170,7 @@ static void gmc_v11_0_set_irq_funcs(struct amdgpu_device *adev)
static bool gmc_v11_0_use_invalidate_semaphore(struct amdgpu_device *adev,
uint32_t vmhub)
{
- return ((vmhub == AMDGPU_MMHUB_0) &&
+ return ((vmhub == AMDGPU_MMHUB0(0)) &&
(!amdgpu_sriov_vf(adev)));
}
@@ -202,7 +202,7 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
unsigned int i;
unsigned char hub_ip = 0;
- hub_ip = (vmhub == AMDGPU_GFXHUB_0) ?
+ hub_ip = (vmhub == AMDGPU_GFXHUB(0)) ?
GC_HWIP : MMHUB_HWIP;
spin_lock(&adev->gmc.invalidate_lock);
@@ -251,7 +251,7 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
hub->eng_distance * eng, 0, hub_ip);
/* Issue additional private vm invalidation to MMHUB */
- if ((vmhub != AMDGPU_GFXHUB_0) &&
+ if ((vmhub != AMDGPU_GFXHUB(0)) &&
(hub->vm_l2_bank_select_reserved_cid2) &&
!amdgpu_sriov_vf(adev)) {
inv_req = RREG32_NO_KIQ(hub->vm_l2_bank_select_reserved_cid2);
@@ -284,7 +284,7 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
static void gmc_v11_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
uint32_t vmhub, uint32_t flush_type)
{
- if ((vmhub == AMDGPU_GFXHUB_0) && !adev->gfx.is_poweron)
+ if ((vmhub == AMDGPU_GFXHUB(0)) && !adev->gfx.is_poweron)
return;
/* flush hdp cache */
@@ -293,7 +293,7 @@ static void gmc_v11_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
/* For SRIOV run time, driver shouldn't access the register through MMIO
* Directly use kiq to do the vm invalidation instead
*/
- if ((adev->gfx.kiq.ring.sched.ready || adev->mes.ring.sched.ready) &&
+ if ((adev->gfx.kiq[0].ring.sched.ready || adev->mes.ring.sched.ready) &&
(amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) {
struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
const unsigned eng = 17;
@@ -319,23 +319,24 @@ static void gmc_v11_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
* @pasid: pasid to be flush
* @flush_type: the flush type
* @all_hub: flush all hubs
+ * @inst: is used to select which instance of KIQ to use for the invalidation
*
* Flush the TLB for the requested pasid.
*/
static int gmc_v11_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
uint16_t pasid, uint32_t flush_type,
- bool all_hub)
+ bool all_hub, uint32_t inst)
{
int vmid, i;
signed long r;
uint32_t seq;
uint16_t queried_pasid;
bool ret;
- struct amdgpu_ring *ring = &adev->gfx.kiq.ring;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_ring *ring = &adev->gfx.kiq[0].ring;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
if (amdgpu_emu_mode == 0 && ring->sched.ready) {
- spin_lock(&adev->gfx.kiq.ring_lock);
+ spin_lock(&adev->gfx.kiq[0].ring_lock);
/* 2 dwords flush + 8 dwords fence */
amdgpu_ring_alloc(ring, kiq->pmf->invalidate_tlbs_size + 8);
kiq->pmf->kiq_invalidate_tlbs(ring,
@@ -343,12 +344,12 @@ static int gmc_v11_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
if (r) {
amdgpu_ring_undo(ring);
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&adev->gfx.kiq[0].ring_lock);
return -ETIME;
}
amdgpu_ring_commit(ring);
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&adev->gfx.kiq[0].ring_lock);
r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout);
if (r < 1) {
dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
@@ -364,12 +365,12 @@ static int gmc_v11_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
&queried_pasid);
if (ret && queried_pasid == pasid) {
if (all_hub) {
- for (i = 0; i < adev->num_vmhubs; i++)
+ for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
gmc_v11_0_flush_gpu_tlb(adev, vmid,
i, flush_type);
} else {
gmc_v11_0_flush_gpu_tlb(adev, vmid,
- AMDGPU_GFXHUB_0, flush_type);
+ AMDGPU_GFXHUB(0), flush_type);
}
}
}
@@ -435,7 +436,7 @@ static void gmc_v11_0_emit_pasid_mapping(struct amdgpu_ring *ring, unsigned vmid
if (ring->is_mes_queue)
return;
- if (ring->vm_hub == AMDGPU_GFXHUB_0)
+ if (ring->vm_hub == AMDGPU_GFXHUB(0))
reg = SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_0_LUT) + vmid;
else
reg = SOC15_REG_OFFSET(OSSSYS, 0, regIH_VMID_0_LUT_MM) + vmid;
@@ -779,7 +780,8 @@ static int gmc_v11_0_sw_init(void *handle)
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
case IP_VERSION(11, 0, 4):
- adev->num_vmhubs = 2;
+ set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
+ set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
/*
* To fulfill 4-level page support,
* vm size is 256TB (48bit), maximum size,
@@ -886,7 +888,7 @@ static int gmc_v11_0_sw_fini(void *handle)
static void gmc_v11_0_init_golden_registers(struct amdgpu_device *adev)
{
if (amdgpu_sriov_vf(adev)) {
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
WREG32(hub->vm_contexts_disable, 0);
return;
@@ -921,7 +923,7 @@ static int gmc_v11_0_gart_enable(struct amdgpu_device *adev)
false : true;
adev->mmhub.funcs->set_fault_enable_default(adev, value);
- gmc_v11_0_flush_gpu_tlb(adev, 0, AMDGPU_MMHUB_0, 0);
+ gmc_v11_0_flush_gpu_tlb(adev, 0, AMDGPU_MMHUB0(0), 0);
DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
(unsigned)(adev->gmc.gart_size >> 20),
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
index b7dad4e67813..aa754c95a0b3 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
@@ -808,7 +808,7 @@ static int gmc_v6_0_sw_init(void *handle)
int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- adev->num_vmhubs = 1;
+ set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
if (adev->flags & AMD_IS_APU) {
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index 402960b0174e..acd2b407860f 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -419,12 +419,13 @@ static int gmc_v7_0_mc_init(struct amdgpu_device *adev)
* @pasid: pasid to be flush
* @flush_type: type of flush
* @all_hub: flush all hubs
+ * @inst: is used to select which instance of KIQ to use for the invalidation
*
* Flush the TLB for the requested pasid.
*/
static int gmc_v7_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
uint16_t pasid, uint32_t flush_type,
- bool all_hub)
+ bool all_hub, uint32_t inst)
{
int vmid;
unsigned int tmp;
@@ -977,7 +978,7 @@ static int gmc_v7_0_sw_init(void *handle)
int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- adev->num_vmhubs = 1;
+ set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
if (adev->flags & AMD_IS_APU) {
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index 504c1b34dab7..85dead2a5702 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -617,12 +617,13 @@ static int gmc_v8_0_mc_init(struct amdgpu_device *adev)
* @pasid: pasid to be flush
* @flush_type: type of flush
* @all_hub: flush all hubs
+ * @inst: is used to select which instance of KIQ to use for the invalidation
*
* Flush the TLB for the requested pasid.
*/
static int gmc_v8_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
uint16_t pasid, uint32_t flush_type,
- bool all_hub)
+ bool all_hub, uint32_t inst)
{
int vmid;
unsigned int tmp;
@@ -1093,7 +1094,7 @@ static int gmc_v8_0_sw_init(void *handle)
int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- adev->num_vmhubs = 1;
+ set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
if (adev->flags & AMD_IS_APU) {
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 2fe21cefd772..67e669e0141c 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -79,6 +79,7 @@
#define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_DCN2 0x05ea
#define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_DCN2_BASE_IDX 2
+#define MAX_MEM_RANGES 8
static const char *gfxhub_client_ids[] = {
"CB",
@@ -481,7 +482,7 @@ static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
switch (state) {
case AMDGPU_IRQ_STATE_DISABLE:
- for (j = 0; j < adev->num_vmhubs; j++) {
+ for_each_set_bit(j, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS) {
hub = &adev->vmhub[j];
for (i = 0; i < 16; i++) {
reg = hub->vm_context0_cntl + i;
@@ -491,25 +492,25 @@ static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
* fini/suspend, so the overall state doesn't
* change over the course of suspend/resume.
*/
- if (adev->in_s0ix && (j == AMDGPU_GFXHUB_0))
+ if (adev->in_s0ix && (j == AMDGPU_GFXHUB(0)))
continue;
- if (j == AMDGPU_GFXHUB_0)
- tmp = RREG32_SOC15_IP(GC, reg);
- else
+ if (j >= AMDGPU_MMHUB0(0))
tmp = RREG32_SOC15_IP(MMHUB, reg);
+ else
+ tmp = RREG32_SOC15_IP(GC, reg);
tmp &= ~bits;
- if (j == AMDGPU_GFXHUB_0)
- WREG32_SOC15_IP(GC, reg, tmp);
- else
+ if (j >= AMDGPU_MMHUB0(0))
WREG32_SOC15_IP(MMHUB, reg, tmp);
+ else
+ WREG32_SOC15_IP(GC, reg, tmp);
}
}
break;
case AMDGPU_IRQ_STATE_ENABLE:
- for (j = 0; j < adev->num_vmhubs; j++) {
+ for_each_set_bit(j, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS) {
hub = &adev->vmhub[j];
for (i = 0; i < 16; i++) {
reg = hub->vm_context0_cntl + i;
@@ -519,20 +520,20 @@ static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
* fini/suspend, so the overall state doesn't
* change over the course of suspend/resume.
*/
- if (adev->in_s0ix && (j == AMDGPU_GFXHUB_0))
+ if (adev->in_s0ix && (j == AMDGPU_GFXHUB(0)))
continue;
- if (j == AMDGPU_GFXHUB_0)
- tmp = RREG32_SOC15_IP(GC, reg);
- else
+ if (j >= AMDGPU_MMHUB0(0))
tmp = RREG32_SOC15_IP(MMHUB, reg);
+ else
+ tmp = RREG32_SOC15_IP(GC, reg);
tmp |= bits;
- if (j == AMDGPU_GFXHUB_0)
- WREG32_SOC15_IP(GC, reg, tmp);
- else
+ if (j >= AMDGPU_MMHUB0(0))
WREG32_SOC15_IP(MMHUB, reg, tmp);
+ else
+ WREG32_SOC15_IP(GC, reg, tmp);
}
}
break;
@@ -556,11 +557,31 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
const char *hub_name;
u64 addr;
uint32_t cam_index = 0;
- int ret;
+ int ret, xcc_id = 0;
+ uint32_t node_id;
+
+ node_id = entry->node_id;
addr = (u64)entry->src_data[0] << 12;
addr |= ((u64)entry->src_data[1] & 0xf) << 44;
+ if (entry->client_id == SOC15_IH_CLIENTID_VMC) {
+ hub_name = "mmhub0";
+ hub = &adev->vmhub[AMDGPU_MMHUB0(node_id / 4)];
+ } else if (entry->client_id == SOC15_IH_CLIENTID_VMC1) {
+ hub_name = "mmhub1";
+ hub = &adev->vmhub[AMDGPU_MMHUB1(0)];
+ } else {
+ hub_name = "gfxhub0";
+ if (adev->gfx.funcs->ih_node_to_logical_xcc) {
+ xcc_id = adev->gfx.funcs->ih_node_to_logical_xcc(adev,
+ node_id);
+ if (xcc_id < 0)
+ xcc_id = 0;
+ }
+ hub = &adev->vmhub[xcc_id];
+ }
+
if (retry_fault) {
if (adev->irq.retry_cam_enabled) {
/* Delegate it to a different ring if the hardware hasn't
@@ -573,7 +594,8 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
cam_index = entry->src_data[2] & 0x3ff;
- ret = amdgpu_vm_handle_fault(adev, entry->pasid, addr, write_fault);
+ ret = amdgpu_vm_handle_fault(adev, entry->pasid, entry->vmid, node_id,
+ addr, write_fault);
WDOORBELL32(adev->irq.retry_cam_doorbell_index, cam_index);
if (ret)
return 1;
@@ -595,7 +617,8 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
/* Try to handle the recoverable page faults by filling page
* tables
*/
- if (amdgpu_vm_handle_fault(adev, entry->pasid, addr, write_fault))
+ if (amdgpu_vm_handle_fault(adev, entry->pasid, entry->vmid, node_id,
+ addr, write_fault))
return 1;
}
}
@@ -603,16 +626,6 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
if (!printk_ratelimit())
return 0;
- if (entry->client_id == SOC15_IH_CLIENTID_VMC) {
- hub_name = "mmhub0";
- hub = &adev->vmhub[AMDGPU_MMHUB_0];
- } else if (entry->client_id == SOC15_IH_CLIENTID_VMC1) {
- hub_name = "mmhub1";
- hub = &adev->vmhub[AMDGPU_MMHUB_1];
- } else {
- hub_name = "gfxhub0";
- hub = &adev->vmhub[AMDGPU_GFXHUB_0];
- }
memset(&task_info, 0, sizeof(struct amdgpu_task_info));
amdgpu_vm_get_task_info(adev, entry->pasid, &task_info);
@@ -628,6 +641,11 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
addr, entry->client_id,
soc15_ih_clientid_name[entry->client_id]);
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
+ dev_err(adev->dev, " cookie node_id %d fault from die %s%d%s\n",
+ node_id, node_id % 4 == 3 ? "RSV" : "AID", node_id / 4,
+ node_id % 4 == 1 ? ".XCD0" : node_id % 4 == 2 ? ".XCD1" : "");
+
if (amdgpu_sriov_vf(adev))
return 0;
@@ -636,7 +654,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
* be updated to avoid reading an incorrect value due to
* the new fast GRBM interface.
*/
- if ((entry->vmid_src == AMDGPU_GFXHUB_0) &&
+ if ((entry->vmid_src == AMDGPU_GFXHUB(0)) &&
(adev->ip_versions[GC_HWIP][0] < IP_VERSION(9, 4, 2)))
RREG32(hub->vm_l2_pro_fault_status);
@@ -645,11 +663,10 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
rw = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, RW);
WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
-
dev_err(adev->dev,
"VM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
- if (hub == &adev->vmhub[AMDGPU_GFXHUB_0]) {
+ if (entry->vmid_src == AMDGPU_GFXHUB(0)) {
dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" :
gfxhub_client_ids[cid],
@@ -759,8 +776,8 @@ static bool gmc_v9_0_use_invalidate_semaphore(struct amdgpu_device *adev,
adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
return false;
- return ((vmhub == AMDGPU_MMHUB_0 ||
- vmhub == AMDGPU_MMHUB_1) &&
+ return ((vmhub == AMDGPU_MMHUB0(0) ||
+ vmhub == AMDGPU_MMHUB1(0)) &&
(!amdgpu_sriov_vf(adev)) &&
(!(!(adev->apu_flags & AMD_APU_IS_RAVEN2) &&
(adev->apu_flags & AMD_APU_IS_PICASSO))));
@@ -803,7 +820,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
u32 j, inv_req, inv_req2, tmp;
struct amdgpu_vmhub *hub;
- BUG_ON(vmhub >= adev->num_vmhubs);
+ BUG_ON(vmhub >= AMDGPU_MAX_VMHUBS);
hub = &adev->vmhub[vmhub];
if (adev->gmc.xgmi.num_physical_nodes &&
@@ -816,6 +833,11 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
*/
inv_req = gmc_v9_0_get_invalidate_req(vmid, 2);
inv_req2 = gmc_v9_0_get_invalidate_req(vmid, flush_type);
+ } else if (flush_type == 2 &&
+ adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3) &&
+ adev->rev_id == 0) {
+ inv_req = gmc_v9_0_get_invalidate_req(vmid, 0);
+ inv_req2 = gmc_v9_0_get_invalidate_req(vmid, flush_type);
} else {
inv_req = gmc_v9_0_get_invalidate_req(vmid, flush_type);
inv_req2 = 0;
@@ -824,7 +846,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
/* This is necessary for a HW workaround under SRIOV as well
* as GFXOFF under bare metal
*/
- if (adev->gfx.kiq.ring.sched.ready &&
+ if (adev->gfx.kiq[0].ring.sched.ready &&
(amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) &&
down_read_trylock(&adev->reset_domain->sem)) {
uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
@@ -849,11 +871,10 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
if (use_semaphore) {
for (j = 0; j < adev->usec_timeout; j++) {
/* a read return value of 1 means semaphore acquire */
- if (vmhub == AMDGPU_GFXHUB_0)
- tmp = RREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_sem + hub->eng_distance * eng);
- else
+ if (vmhub >= AMDGPU_MMHUB0(0))
tmp = RREG32_SOC15_IP_NO_KIQ(MMHUB, hub->vm_inv_eng0_sem + hub->eng_distance * eng);
-
+ else
+ tmp = RREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_sem + hub->eng_distance * eng);
if (tmp & 0x1)
break;
udelay(1);
@@ -864,27 +885,26 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
}
do {
- if (vmhub == AMDGPU_GFXHUB_0)
- WREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req);
- else
+ if (vmhub >= AMDGPU_MMHUB0(0))
WREG32_SOC15_IP_NO_KIQ(MMHUB, hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req);
+ else
+ WREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req);
/*
* Issue a dummy read to wait for the ACK register to
* be cleared to avoid a false ACK due to the new fast
* GRBM interface.
*/
- if ((vmhub == AMDGPU_GFXHUB_0) &&
+ if ((vmhub == AMDGPU_GFXHUB(0)) &&
(adev->ip_versions[GC_HWIP][0] < IP_VERSION(9, 4, 2)))
RREG32_NO_KIQ(hub->vm_inv_eng0_req +
hub->eng_distance * eng);
for (j = 0; j < adev->usec_timeout; j++) {
- if (vmhub == AMDGPU_GFXHUB_0)
- tmp = RREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_ack + hub->eng_distance * eng);
- else
+ if (vmhub >= AMDGPU_MMHUB0(0))
tmp = RREG32_SOC15_IP_NO_KIQ(MMHUB, hub->vm_inv_eng0_ack + hub->eng_distance * eng);
-
+ else
+ tmp = RREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_ack + hub->eng_distance * eng);
if (tmp & (1 << vmid))
break;
udelay(1);
@@ -900,10 +920,10 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
* add semaphore release after invalidation,
* write with 0 means semaphore release
*/
- if (vmhub == AMDGPU_GFXHUB_0)
- WREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_sem + hub->eng_distance * eng, 0);
- else
+ if (vmhub >= AMDGPU_MMHUB0(0))
WREG32_SOC15_IP_NO_KIQ(MMHUB, hub->vm_inv_eng0_sem + hub->eng_distance * eng, 0);
+ else
+ WREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_sem + hub->eng_distance * eng, 0);
}
spin_unlock(&adev->gmc.invalidate_lock);
@@ -921,12 +941,13 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
* @pasid: pasid to be flush
* @flush_type: the flush type
* @all_hub: flush all hubs
+ * @inst: is used to select which instance of KIQ to use for the invalidation
*
* Flush the TLB for the requested pasid.
*/
static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
uint16_t pasid, uint32_t flush_type,
- bool all_hub)
+ bool all_hub, uint32_t inst)
{
int vmid, i;
signed long r;
@@ -934,8 +955,8 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
uint16_t queried_pasid;
bool ret;
u32 usec_timeout = amdgpu_sriov_vf(adev) ? SRIOV_USEC_TIMEOUT : adev->usec_timeout;
- struct amdgpu_ring *ring = &adev->gfx.kiq.ring;
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_ring *ring = &adev->gfx.kiq[inst].ring;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[inst];
if (amdgpu_in_reset(adev))
return -EIO;
@@ -955,24 +976,31 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
if (vega20_xgmi_wa)
ndw += kiq->pmf->invalidate_tlbs_size;
- spin_lock(&adev->gfx.kiq.ring_lock);
+ spin_lock(&adev->gfx.kiq[inst].ring_lock);
/* 2 dwords flush + 8 dwords fence */
amdgpu_ring_alloc(ring, ndw);
if (vega20_xgmi_wa)
kiq->pmf->kiq_invalidate_tlbs(ring,
pasid, 2, all_hub);
+
+ if (flush_type == 2 &&
+ adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3) &&
+ adev->rev_id == 0)
+ kiq->pmf->kiq_invalidate_tlbs(ring,
+ pasid, 0, all_hub);
+
kiq->pmf->kiq_invalidate_tlbs(ring,
pasid, flush_type, all_hub);
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
if (r) {
amdgpu_ring_undo(ring);
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&adev->gfx.kiq[inst].ring_lock);
up_read(&adev->reset_domain->sem);
return -ETIME;
}
amdgpu_ring_commit(ring);
- spin_unlock(&adev->gfx.kiq.ring_lock);
+ spin_unlock(&adev->gfx.kiq[inst].ring_lock);
r = amdgpu_fence_wait_polling(ring, seq, usec_timeout);
if (r < 1) {
dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
@@ -989,12 +1017,12 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
&queried_pasid);
if (ret && queried_pasid == pasid) {
if (all_hub) {
- for (i = 0; i < adev->num_vmhubs; i++)
+ for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
gmc_v9_0_flush_gpu_tlb(adev, vmid,
i, flush_type);
} else {
gmc_v9_0_flush_gpu_tlb(adev, vmid,
- AMDGPU_GFXHUB_0, flush_type);
+ AMDGPU_GFXHUB(0), flush_type);
}
break;
}
@@ -1060,10 +1088,10 @@ static void gmc_v9_0_emit_pasid_mapping(struct amdgpu_ring *ring, unsigned vmid,
uint32_t reg;
/* Do nothing because there's no lut register for mmhub1. */
- if (ring->vm_hub == AMDGPU_MMHUB_1)
+ if (ring->vm_hub == AMDGPU_MMHUB1(0))
return;
- if (ring->vm_hub == AMDGPU_GFXHUB_0)
+ if (ring->vm_hub == AMDGPU_GFXHUB(0))
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT) + vmid;
else
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT_MM) + vmid;
@@ -1159,13 +1187,14 @@ static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
bool is_vram = bo->tbo.resource->mem_type == TTM_PL_VRAM;
bool coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT;
bool uncached = bo->flags & AMDGPU_GEM_CREATE_UNCACHED;
- unsigned int mtype;
+ struct amdgpu_vm *vm = mapping->bo_va->base.vm;
+ unsigned int mtype_local, mtype;
bool snoop = false;
+ bool is_local;
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 4, 1):
case IP_VERSION(9, 4, 2):
- case IP_VERSION(9, 4, 3):
if (is_vram) {
if (bo_adev == adev) {
if (uncached)
@@ -1200,6 +1229,43 @@ static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
snoop = true;
}
break;
+ case IP_VERSION(9, 4, 3):
+ /* Only local VRAM BOs or system memory on non-NUMA APUs
+ * can be assumed to be local in their entirety. Choose
+ * MTYPE_NC as safe fallback for all system memory BOs on
+ * NUMA systems. Their MTYPE can be overridden per-page in
+ * gmc_v9_0_override_vm_pte_flags.
+ */
+ mtype_local = MTYPE_RW;
+ if (amdgpu_mtype_local == 1) {
+ DRM_INFO_ONCE("Using MTYPE_NC for local memory\n");
+ mtype_local = MTYPE_NC;
+ } else if (amdgpu_mtype_local == 2) {
+ DRM_INFO_ONCE("Using MTYPE_CC for local memory\n");
+ mtype_local = MTYPE_CC;
+ } else {
+ DRM_INFO_ONCE("Using MTYPE_RW for local memory\n");
+ }
+ is_local = (!is_vram && (adev->flags & AMD_IS_APU) &&
+ num_possible_nodes() <= 1) ||
+ (is_vram && adev == bo_adev &&
+ KFD_XCP_MEM_ID(adev, bo->xcp_id) == vm->mem_id);
+ snoop = true;
+ if (uncached) {
+ mtype = MTYPE_UC;
+ } else if (adev->flags & AMD_IS_APU) {
+ mtype = is_local ? mtype_local : MTYPE_NC;
+ } else {
+ /* dGPU */
+ if (is_local)
+ mtype = mtype_local;
+ else if (is_vram)
+ mtype = MTYPE_NC;
+ else
+ mtype = MTYPE_UC;
+ }
+
+ break;
default:
if (uncached || coherent)
mtype = MTYPE_UC;
@@ -1241,6 +1307,72 @@ static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev,
mapping, flags);
}
+static void gmc_v9_0_override_vm_pte_flags(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm,
+ uint64_t addr, uint64_t *flags)
+{
+ int local_node, nid;
+
+ /* Only GFX 9.4.3 APUs associate GPUs with NUMA nodes. Local system
+ * memory can use more efficient MTYPEs.
+ */
+ if (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 3))
+ return;
+
+ /* Only direct-mapped memory allows us to determine the NUMA node from
+ * the DMA address.
+ */
+ if (!adev->ram_is_direct_mapped) {
+ dev_dbg(adev->dev, "RAM is not direct mapped\n");
+ return;
+ }
+
+ /* Only override mappings with MTYPE_NC, which is the safe default for
+ * cacheable memory.
+ */
+ if ((*flags & AMDGPU_PTE_MTYPE_VG10_MASK) !=
+ AMDGPU_PTE_MTYPE_VG10(MTYPE_NC)) {
+ dev_dbg(adev->dev, "MTYPE is not NC\n");
+ return;
+ }
+
+ /* FIXME: Only supported on native mode for now. For carve-out, the
+ * NUMA affinity of the GPU/VM needs to come from the PCI info because
+ * memory partitions are not associated with different NUMA nodes.
+ */
+ if (adev->gmc.is_app_apu && vm->mem_id >= 0) {
+ local_node = adev->gmc.mem_partitions[vm->mem_id].numa.node;
+ } else {
+ dev_dbg(adev->dev, "Only native mode APU is supported.\n");
+ return;
+ }
+
+ /* Only handle real RAM. Mappings of PCIe resources don't have struct
+ * page or NUMA nodes.
+ */
+ if (!page_is_ram(addr >> PAGE_SHIFT)) {
+ dev_dbg(adev->dev, "Page is not RAM.\n");
+ return;
+ }
+ nid = pfn_to_nid(addr >> PAGE_SHIFT);
+ dev_dbg(adev->dev, "vm->mem_id=%d, local_node=%d, nid=%d\n",
+ vm->mem_id, local_node, nid);
+ if (nid == local_node) {
+ uint64_t old_flags = *flags;
+ unsigned int mtype_local = MTYPE_RW;
+
+ if (amdgpu_mtype_local == 1)
+ mtype_local = MTYPE_NC;
+ else if (amdgpu_mtype_local == 2)
+ mtype_local = MTYPE_CC;
+
+ *flags = (*flags & ~AMDGPU_PTE_MTYPE_VG10_MASK) |
+ AMDGPU_PTE_MTYPE_VG10(mtype_local);
+ dev_dbg(adev->dev, "flags updated from %llx to %llx\n",
+ old_flags, *flags);
+ }
+}
+
static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev)
{
u32 d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL);
@@ -1283,6 +1415,27 @@ static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev)
return size;
}
+static enum amdgpu_memory_partition
+gmc_v9_0_get_memory_partition(struct amdgpu_device *adev, u32 *supp_modes)
+{
+ enum amdgpu_memory_partition mode = UNKNOWN_MEMORY_PARTITION_MODE;
+
+ if (adev->nbio.funcs->get_memory_partition_mode)
+ mode = adev->nbio.funcs->get_memory_partition_mode(adev,
+ supp_modes);
+
+ return mode;
+}
+
+static enum amdgpu_memory_partition
+gmc_v9_0_query_memory_partition(struct amdgpu_device *adev)
+{
+ if (amdgpu_sriov_vf(adev))
+ return AMDGPU_NPS1_PARTITION_MODE;
+
+ return gmc_v9_0_get_memory_partition(adev, NULL);
+}
+
static const struct amdgpu_gmc_funcs gmc_v9_0_gmc_funcs = {
.flush_gpu_tlb = gmc_v9_0_flush_gpu_tlb,
.flush_gpu_tlb_pasid = gmc_v9_0_flush_gpu_tlb_pasid,
@@ -1291,7 +1444,9 @@ static const struct amdgpu_gmc_funcs gmc_v9_0_gmc_funcs = {
.map_mtype = gmc_v9_0_map_mtype,
.get_vm_pde = gmc_v9_0_get_vm_pde,
.get_vm_pte = gmc_v9_0_get_vm_pte,
+ .override_vm_pte_flags = gmc_v9_0_override_vm_pte_flags,
.get_vbios_fb_size = gmc_v9_0_get_vbios_fb_size,
+ .query_mem_partition_mode = &gmc_v9_0_query_memory_partition,
};
static void gmc_v9_0_set_gmc_funcs(struct amdgpu_device *adev)
@@ -1372,6 +1527,9 @@ static void gmc_v9_0_set_mmhub_ras_funcs(struct amdgpu_device *adev)
case IP_VERSION(9, 4, 2):
adev->mmhub.ras = &mmhub_v1_7_ras;
break;
+ case IP_VERSION(1, 8, 0):
+ adev->mmhub.ras = &mmhub_v1_8_ras;
+ break;
default:
/* mmhub ras is not available */
break;
@@ -1419,9 +1577,13 @@ static int gmc_v9_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- /* ARCT and VEGA20 don't have XGMI defined in their IP discovery tables */
- if (adev->asic_type == CHIP_VEGA20 ||
- adev->asic_type == CHIP_ARCTURUS)
+ /*
+ * 9.4.0, 9.4.1 and 9.4.3 don't have XGMI defined
+ * in their IP discovery tables
+ */
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 0) ||
+ adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) ||
+ adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
adev->gmc.xgmi.supported = true;
if (adev->ip_versions[XGMI_HWIP][0] == IP_VERSION(6, 1, 0)) {
@@ -1430,6 +1592,20 @@ static int gmc_v9_0_early_init(void *handle)
adev->smuio.funcs->is_host_gpu_xgmi_supported(adev);
}
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) {
+ enum amdgpu_pkg_type pkg_type =
+ adev->smuio.funcs->get_pkg_type(adev);
+ /* On GFXIP 9.4.3. APU, there is no physical VRAM domain present
+ * and the APU, can be in used two possible modes:
+ * - carveout mode
+ * - native APU mode
+ * "is_app_apu" can be used to identify the APU in the native
+ * mode.
+ */
+ adev->gmc.is_app_apu = (pkg_type == AMDGPU_PKG_TYPE_APU &&
+ !pci_resource_len(adev->pdev, 0));
+ }
+
gmc_v9_0_set_gmc_funcs(adev);
gmc_v9_0_set_irq_funcs(adev);
gmc_v9_0_set_umc_funcs(adev);
@@ -1525,8 +1701,13 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev)
int r;
/* size in MB on si */
- adev->gmc.mc_vram_size =
- adev->nbio.funcs->get_memsize(adev) * 1024ULL * 1024ULL;
+ if (!adev->gmc.is_app_apu) {
+ adev->gmc.mc_vram_size =
+ adev->nbio.funcs->get_memsize(adev) * 1024ULL * 1024ULL;
+ } else {
+ DRM_DEBUG("Set mc_vram_size = 0 for APP APU\n");
+ adev->gmc.mc_vram_size = 0;
+ }
adev->gmc.real_vram_size = adev->gmc.mc_vram_size;
if (!(adev->flags & AMD_IS_APU) &&
@@ -1551,7 +1732,8 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev)
*/
/* check whether both host-gpu and gpu-gpu xgmi links exist */
- if (((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev)) ||
+ if ((!amdgpu_sriov_vf(adev) &&
+ (adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev)) ||
(adev->gmc.xgmi.supported &&
adev->gmc.xgmi.connected_to_cpu)) {
adev->gmc.aper_base =
@@ -1618,12 +1800,18 @@ static int gmc_v9_0_gart_init(struct amdgpu_device *adev)
adev->gart.gart_pte_flags = AMDGPU_PTE_MTYPE_VG10(MTYPE_UC) |
AMDGPU_PTE_EXECUTABLE;
- r = amdgpu_gart_table_vram_alloc(adev);
- if (r)
- return r;
+ if (!adev->gmc.real_vram_size) {
+ dev_info(adev->dev, "Put GART in system memory for APU\n");
+ r = amdgpu_gart_table_ram_alloc(adev);
+ if (r)
+ dev_err(adev->dev, "Failed to allocate GART in system memory\n");
+ } else {
+ r = amdgpu_gart_table_vram_alloc(adev);
+ if (r)
+ return r;
- if (adev->gmc.xgmi.connected_to_cpu) {
- r = amdgpu_gmc_pdb0_alloc(adev);
+ if (adev->gmc.xgmi.connected_to_cpu)
+ r = amdgpu_gmc_pdb0_alloc(adev);
}
return r;
@@ -1644,10 +1832,178 @@ static void gmc_v9_0_save_registers(struct amdgpu_device *adev)
adev->gmc.sdpif_register = RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0);
}
+static bool gmc_v9_0_validate_partition_info(struct amdgpu_device *adev)
+{
+ enum amdgpu_memory_partition mode;
+ u32 supp_modes;
+ bool valid;
+
+ mode = gmc_v9_0_get_memory_partition(adev, &supp_modes);
+
+ /* Mode detected by hardware not present in supported modes */
+ if ((mode != UNKNOWN_MEMORY_PARTITION_MODE) &&
+ !(BIT(mode - 1) & supp_modes))
+ return false;
+
+ switch (mode) {
+ case UNKNOWN_MEMORY_PARTITION_MODE:
+ case AMDGPU_NPS1_PARTITION_MODE:
+ valid = (adev->gmc.num_mem_partitions == 1);
+ break;
+ case AMDGPU_NPS2_PARTITION_MODE:
+ valid = (adev->gmc.num_mem_partitions == 2);
+ break;
+ case AMDGPU_NPS4_PARTITION_MODE:
+ valid = (adev->gmc.num_mem_partitions == 3 ||
+ adev->gmc.num_mem_partitions == 4);
+ break;
+ default:
+ valid = false;
+ }
+
+ return valid;
+}
+
+static bool gmc_v9_0_is_node_present(int *node_ids, int num_ids, int nid)
+{
+ int i;
+
+ /* Check if node with id 'nid' is present in 'node_ids' array */
+ for (i = 0; i < num_ids; ++i)
+ if (node_ids[i] == nid)
+ return true;
+
+ return false;
+}
+
+static void
+gmc_v9_0_init_acpi_mem_ranges(struct amdgpu_device *adev,
+ struct amdgpu_mem_partition_info *mem_ranges)
+{
+ int num_ranges = 0, ret, mem_groups;
+ struct amdgpu_numa_info numa_info;
+ int node_ids[MAX_MEM_RANGES];
+ int num_xcc, xcc_id;
+ uint32_t xcc_mask;
+
+ num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+ xcc_mask = (1U << num_xcc) - 1;
+ mem_groups = hweight32(adev->aid_mask);
+
+ for_each_inst(xcc_id, xcc_mask) {
+ ret = amdgpu_acpi_get_mem_info(adev, xcc_id, &numa_info);
+ if (ret)
+ continue;
+
+ if (numa_info.nid == NUMA_NO_NODE) {
+ mem_ranges[0].size = numa_info.size;
+ mem_ranges[0].numa.node = numa_info.nid;
+ num_ranges = 1;
+ break;
+ }
+
+ if (gmc_v9_0_is_node_present(node_ids, num_ranges,
+ numa_info.nid))
+ continue;
+
+ node_ids[num_ranges] = numa_info.nid;
+ mem_ranges[num_ranges].numa.node = numa_info.nid;
+ mem_ranges[num_ranges].size = numa_info.size;
+ ++num_ranges;
+ }
+
+ adev->gmc.num_mem_partitions = num_ranges;
+
+ /* If there is only partition, don't use entire size */
+ if (adev->gmc.num_mem_partitions == 1) {
+ mem_ranges[0].size = mem_ranges[0].size * (mem_groups - 1);
+ do_div(mem_ranges[0].size, mem_groups);
+ }
+}
+
+static void
+gmc_v9_0_init_sw_mem_ranges(struct amdgpu_device *adev,
+ struct amdgpu_mem_partition_info *mem_ranges)
+{
+ enum amdgpu_memory_partition mode;
+ u32 start_addr = 0, size;
+ int i;
+
+ mode = gmc_v9_0_query_memory_partition(adev);
+
+ switch (mode) {
+ case UNKNOWN_MEMORY_PARTITION_MODE:
+ case AMDGPU_NPS1_PARTITION_MODE:
+ adev->gmc.num_mem_partitions = 1;
+ break;
+ case AMDGPU_NPS2_PARTITION_MODE:
+ adev->gmc.num_mem_partitions = 2;
+ break;
+ case AMDGPU_NPS4_PARTITION_MODE:
+ if (adev->flags & AMD_IS_APU)
+ adev->gmc.num_mem_partitions = 3;
+ else
+ adev->gmc.num_mem_partitions = 4;
+ break;
+ default:
+ adev->gmc.num_mem_partitions = 1;
+ break;
+ }
+
+ size = adev->gmc.real_vram_size >> AMDGPU_GPU_PAGE_SHIFT;
+ size /= adev->gmc.num_mem_partitions;
+
+ for (i = 0; i < adev->gmc.num_mem_partitions; ++i) {
+ mem_ranges[i].range.fpfn = start_addr;
+ mem_ranges[i].size = ((u64)size << AMDGPU_GPU_PAGE_SHIFT);
+ mem_ranges[i].range.lpfn = start_addr + size - 1;
+ start_addr += size;
+ }
+
+ /* Adjust the last one */
+ mem_ranges[adev->gmc.num_mem_partitions - 1].range.lpfn =
+ (adev->gmc.real_vram_size >> AMDGPU_GPU_PAGE_SHIFT) - 1;
+ mem_ranges[adev->gmc.num_mem_partitions - 1].size =
+ adev->gmc.real_vram_size -
+ ((u64)mem_ranges[adev->gmc.num_mem_partitions - 1].range.fpfn
+ << AMDGPU_GPU_PAGE_SHIFT);
+}
+
+static int gmc_v9_0_init_mem_ranges(struct amdgpu_device *adev)
+{
+ bool valid;
+
+ adev->gmc.mem_partitions = kzalloc(
+ MAX_MEM_RANGES * sizeof(struct amdgpu_mem_partition_info),
+ GFP_KERNEL);
+
+ if (!adev->gmc.mem_partitions)
+ return -ENOMEM;
+
+ /* TODO : Get the range from PSP/Discovery for dGPU */
+ if (adev->gmc.is_app_apu)
+ gmc_v9_0_init_acpi_mem_ranges(adev, adev->gmc.mem_partitions);
+ else
+ gmc_v9_0_init_sw_mem_ranges(adev, adev->gmc.mem_partitions);
+
+ if (amdgpu_sriov_vf(adev))
+ valid = true;
+ else
+ valid = gmc_v9_0_validate_partition_info(adev);
+ if (!valid) {
+ /* TODO: handle invalid case */
+ dev_WARN(adev->dev,
+ "Mem ranges not matching with hardware config");
+ }
+
+ return 0;
+}
+
static int gmc_v9_0_sw_init(void *handle)
{
int r, vram_width = 0, vram_type = 0, vram_vendor = 0, dma_addr_bits;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ unsigned long inst_mask = adev->aid_mask;
adev->gfxhub.funcs->init(adev);
@@ -1655,38 +2011,54 @@ static int gmc_v9_0_sw_init(void *handle)
spin_lock_init(&adev->gmc.invalidate_lock);
- r = amdgpu_atomfirmware_get_vram_info(adev,
- &vram_width, &vram_type, &vram_vendor);
- if (amdgpu_sriov_vf(adev))
- /* For Vega10 SR-IOV, vram_width can't be read from ATOM as RAVEN,
- * and DF related registers is not readable, seems hardcord is the
- * only way to set the correct vram_width
- */
- adev->gmc.vram_width = 2048;
- else if (amdgpu_emu_mode != 1)
- adev->gmc.vram_width = vram_width;
+ if (!(adev->bios) || adev->gmc.is_app_apu) {
+ if (adev->flags & AMD_IS_APU) {
+ if (adev->gmc.is_app_apu) {
+ adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM;
+ adev->gmc.vram_width = 128 * 64;
+ } else {
+ adev->gmc.vram_type = AMDGPU_VRAM_TYPE_DDR4;
+ adev->gmc.vram_width = 64 * 64;
+ }
+ } else {
+ adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM;
+ adev->gmc.vram_width = 128 * 64;
+ }
+ } else {
+ r = amdgpu_atomfirmware_get_vram_info(adev,
+ &vram_width, &vram_type, &vram_vendor);
+ if (amdgpu_sriov_vf(adev))
+ /* For Vega10 SR-IOV, vram_width can't be read from ATOM as RAVEN,
+ * and DF related registers is not readable, seems hardcord is the
+ * only way to set the correct vram_width
+ */
+ adev->gmc.vram_width = 2048;
+ else if (amdgpu_emu_mode != 1)
+ adev->gmc.vram_width = vram_width;
- if (!adev->gmc.vram_width) {
- int chansize, numchan;
+ if (!adev->gmc.vram_width) {
+ int chansize, numchan;
- /* hbm memory channel size */
- if (adev->flags & AMD_IS_APU)
- chansize = 64;
- else
- chansize = 128;
- if (adev->df.funcs &&
- adev->df.funcs->get_hbm_channel_number) {
- numchan = adev->df.funcs->get_hbm_channel_number(adev);
- adev->gmc.vram_width = numchan * chansize;
+ /* hbm memory channel size */
+ if (adev->flags & AMD_IS_APU)
+ chansize = 64;
+ else
+ chansize = 128;
+ if (adev->df.funcs &&
+ adev->df.funcs->get_hbm_channel_number) {
+ numchan = adev->df.funcs->get_hbm_channel_number(adev);
+ adev->gmc.vram_width = numchan * chansize;
+ }
}
- }
- adev->gmc.vram_type = vram_type;
- adev->gmc.vram_vendor = vram_vendor;
+ adev->gmc.vram_type = vram_type;
+ adev->gmc.vram_vendor = vram_vendor;
+ }
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 2):
- adev->num_vmhubs = 2;
+ set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
+ set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
if (adev->rev_id == 0x0 || adev->rev_id == 0x1) {
amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
@@ -1702,9 +2074,8 @@ static int gmc_v9_0_sw_init(void *handle)
case IP_VERSION(9, 4, 0):
case IP_VERSION(9, 3, 0):
case IP_VERSION(9, 4, 2):
- case IP_VERSION(9, 4, 3):
- adev->num_vmhubs = 2;
-
+ set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
+ set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
/*
* To fulfill 4-level page support,
@@ -1720,12 +2091,24 @@ static int gmc_v9_0_sw_init(void *handle)
adev->gmc.translate_further = adev->vm_manager.num_level > 1;
break;
case IP_VERSION(9, 4, 1):
- adev->num_vmhubs = 3;
+ set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
+ set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
+ set_bit(AMDGPU_MMHUB1(0), adev->vmhubs_mask);
/* Keep the vm size same with Vega20 */
amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
adev->gmc.translate_further = adev->vm_manager.num_level > 1;
break;
+ case IP_VERSION(9, 4, 3):
+ bitmap_set(adev->vmhubs_mask, AMDGPU_GFXHUB(0),
+ NUM_XCC(adev->gfx.xcc_mask));
+
+ inst_mask <<= AMDGPU_MMHUB0(0);
+ bitmap_or(adev->vmhubs_mask, adev->vmhubs_mask, &inst_mask, 32);
+
+ amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
+ adev->gmc.translate_further = adev->vm_manager.num_level > 1;
+ break;
default:
break;
}
@@ -1764,7 +2147,7 @@ static int gmc_v9_0_sw_init(void *handle)
*/
adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
- dma_addr_bits = adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2) ? 48:44;
+ dma_addr_bits = adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 4, 2) ? 48:44;
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(dma_addr_bits));
if (r) {
printk(KERN_WARNING "amdgpu: No suitable DMA available.\n");
@@ -1778,6 +2161,12 @@ static int gmc_v9_0_sw_init(void *handle)
amdgpu_gmc_get_vbios_allocations(adev);
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) {
+ r = gmc_v9_0_init_mem_ranges(adev);
+ if (r)
+ return r;
+ }
+
/* Memory manager */
r = amdgpu_bo_init(adev);
if (r)
@@ -1810,6 +2199,9 @@ static int gmc_v9_0_sw_init(void *handle)
if (r)
return r;
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
+ amdgpu_gmc_sysfs_init(adev);
+
return 0;
}
@@ -1817,10 +2209,20 @@ static int gmc_v9_0_sw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
+ amdgpu_gmc_sysfs_fini(adev);
+ adev->gmc.num_mem_partitions = 0;
+ kfree(adev->gmc.mem_partitions);
+
amdgpu_gmc_ras_fini(adev);
amdgpu_gem_force_release(adev);
amdgpu_vm_manager_fini(adev);
- amdgpu_gart_table_vram_free(adev);
+ if (!adev->gmc.real_vram_size) {
+ dev_info(adev->dev, "Put GART in system memory for APU free\n");
+ amdgpu_gart_table_ram_free(adev);
+ } else {
+ amdgpu_gart_table_vram_free(adev);
+ }
amdgpu_bo_free_kernel(&adev->gmc.pdb0_bo, NULL, &adev->gmc.ptr_pdb0);
amdgpu_bo_fini(adev);
@@ -1946,8 +2348,8 @@ static int gmc_v9_0_hw_init(void *handle)
adev->gfxhub.funcs->set_fault_enable_default(adev, value);
adev->mmhub.funcs->set_fault_enable_default(adev, value);
}
- for (i = 0; i < adev->num_vmhubs; ++i) {
- if (adev->in_s0ix && (i == AMDGPU_GFXHUB_0))
+ for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS) {
+ if (adev->in_s0ix && (i == AMDGPU_GFXHUB(0)))
continue;
gmc_v9_0_flush_gpu_tlb(adev, 0, i, 0);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
index a3076eb8af6a..77595e9622da 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
@@ -437,7 +437,7 @@ static int jpeg_v1_0_process_interrupt(struct amdgpu_device *adev,
switch (entry->src_id) {
case 126:
- amdgpu_fence_process(&adev->jpeg.inst->ring_dec);
+ amdgpu_fence_process(adev->jpeg.inst->ring_dec);
break;
default:
DRM_ERROR("Unhandled interrupt: %d %d\n",
@@ -460,6 +460,7 @@ int jpeg_v1_0_early_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
adev->jpeg.num_jpeg_inst = 1;
+ adev->jpeg.num_jpeg_rings = 1;
jpeg_v1_0_set_dec_ring_funcs(adev);
jpeg_v1_0_set_irq_funcs(adev);
@@ -484,15 +485,15 @@ int jpeg_v1_0_sw_init(void *handle)
if (r)
return r;
- ring = &adev->jpeg.inst->ring_dec;
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring = adev->jpeg.inst->ring_dec;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "jpeg_dec");
r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq,
0, AMDGPU_RING_PRIO_DEFAULT, NULL);
if (r)
return r;
- adev->jpeg.internal.jpeg_pitch = adev->jpeg.inst->external.jpeg_pitch =
+ adev->jpeg.internal.jpeg_pitch[0] = adev->jpeg.inst->external.jpeg_pitch[0] =
SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH);
return 0;
@@ -509,7 +510,7 @@ void jpeg_v1_0_sw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- amdgpu_ring_fini(&adev->jpeg.inst[0].ring_dec);
+ amdgpu_ring_fini(adev->jpeg.inst->ring_dec);
}
/**
@@ -522,7 +523,7 @@ void jpeg_v1_0_sw_fini(void *handle)
*/
void jpeg_v1_0_start(struct amdgpu_device *adev, int mode)
{
- struct amdgpu_ring *ring = &adev->jpeg.inst->ring_dec;
+ struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
if (mode == 0) {
WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
@@ -579,7 +580,7 @@ static const struct amdgpu_ring_funcs jpeg_v1_0_decode_ring_vm_funcs = {
static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev)
{
- adev->jpeg.inst->ring_dec.funcs = &jpeg_v1_0_decode_ring_vm_funcs;
+ adev->jpeg.inst->ring_dec->funcs = &jpeg_v1_0_decode_ring_vm_funcs;
DRM_INFO("JPEG decode is enabled in VM mode\n");
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
index 0eddf7c824a7..c25d4a07350b 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
@@ -49,6 +49,7 @@ static int jpeg_v2_0_early_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
adev->jpeg.num_jpeg_inst = 1;
+ adev->jpeg.num_jpeg_rings = 1;
jpeg_v2_0_set_dec_ring_funcs(adev);
jpeg_v2_0_set_irq_funcs(adev);
@@ -83,18 +84,18 @@ static int jpeg_v2_0_sw_init(void *handle)
if (r)
return r;
- ring = &adev->jpeg.inst->ring_dec;
+ ring = adev->jpeg.inst->ring_dec;
ring->use_doorbell = true;
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1;
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "jpeg_dec");
r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq,
0, AMDGPU_RING_PRIO_DEFAULT, NULL);
if (r)
return r;
- adev->jpeg.internal.jpeg_pitch = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
- adev->jpeg.inst->external.jpeg_pitch = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH);
+ adev->jpeg.internal.jpeg_pitch[0] = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
+ adev->jpeg.inst->external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH);
return 0;
}
@@ -129,7 +130,7 @@ static int jpeg_v2_0_sw_fini(void *handle)
static int jpeg_v2_0_hw_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- struct amdgpu_ring *ring = &adev->jpeg.inst->ring_dec;
+ struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
int r;
adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
@@ -312,7 +313,7 @@ static void jpeg_v2_0_enable_clock_gating(struct amdgpu_device *adev)
*/
static int jpeg_v2_0_start(struct amdgpu_device *adev)
{
- struct amdgpu_ring *ring = &adev->jpeg.inst->ring_dec;
+ struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
int r;
if (adev->pm.dpm_enabled)
@@ -729,7 +730,7 @@ static int jpeg_v2_0_process_interrupt(struct amdgpu_device *adev,
switch (entry->src_id) {
case VCN_2_0__SRCID__JPEG_DECODE:
- amdgpu_fence_process(&adev->jpeg.inst->ring_dec);
+ amdgpu_fence_process(adev->jpeg.inst->ring_dec);
break;
default:
DRM_ERROR("Unhandled interrupt: %d %d\n",
@@ -791,7 +792,7 @@ static const struct amdgpu_ring_funcs jpeg_v2_0_dec_ring_vm_funcs = {
static void jpeg_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev)
{
- adev->jpeg.inst->ring_dec.funcs = &jpeg_v2_0_dec_ring_vm_funcs;
+ adev->jpeg.inst->ring_dec->funcs = &jpeg_v2_0_dec_ring_vm_funcs;
DRM_INFO("JPEG decode is enabled in VM mode\n");
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
index 73e0dc5a10cd..aadb74de52bc 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
@@ -60,6 +60,7 @@ static int jpeg_v2_5_early_init(void *handle)
u32 harvest;
int i;
+ adev->jpeg.num_jpeg_rings = 1;
adev->jpeg.num_jpeg_inst = JPEG25_MAX_HW_INSTANCES_ARCTURUS;
for (i = 0; i < adev->jpeg.num_jpeg_inst; i++) {
harvest = RREG32_SOC15(JPEG, i, mmCC_UVD_HARVESTING);
@@ -125,12 +126,12 @@ static int jpeg_v2_5_sw_init(void *handle)
if (adev->jpeg.harvest_config & (1 << i))
continue;
- ring = &adev->jpeg.inst[i].ring_dec;
+ ring = adev->jpeg.inst[i].ring_dec;
ring->use_doorbell = true;
if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(2, 5, 0))
- ring->vm_hub = AMDGPU_MMHUB_1;
+ ring->vm_hub = AMDGPU_MMHUB1(0);
else
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1 + 8 * i;
sprintf(ring->name, "jpeg_dec_%d", i);
r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst[i].irq,
@@ -138,8 +139,8 @@ static int jpeg_v2_5_sw_init(void *handle)
if (r)
return r;
- adev->jpeg.internal.jpeg_pitch = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
- adev->jpeg.inst[i].external.jpeg_pitch = SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_PITCH);
+ adev->jpeg.internal.jpeg_pitch[0] = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
+ adev->jpeg.inst[i].external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_PITCH);
}
r = amdgpu_jpeg_ras_sw_init(adev);
@@ -186,7 +187,7 @@ static int jpeg_v2_5_hw_init(void *handle)
if (adev->jpeg.harvest_config & (1 << i))
continue;
- ring = &adev->jpeg.inst[i].ring_dec;
+ ring = adev->jpeg.inst[i].ring_dec;
adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
(adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i, i);
@@ -329,7 +330,7 @@ static int jpeg_v2_5_start(struct amdgpu_device *adev)
if (adev->jpeg.harvest_config & (1 << i))
continue;
- ring = &adev->jpeg.inst[i].ring_dec;
+ ring = adev->jpeg.inst[i].ring_dec;
/* disable anti hang mechanism */
WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_POWER_STATUS), 0,
~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
@@ -602,7 +603,7 @@ static int jpeg_v2_5_process_interrupt(struct amdgpu_device *adev,
switch (entry->src_id) {
case VCN_2_0__SRCID__JPEG_DECODE:
- amdgpu_fence_process(&adev->jpeg.inst[ip_instance].ring_dec);
+ amdgpu_fence_process(adev->jpeg.inst[ip_instance].ring_dec);
break;
default:
DRM_ERROR("Unhandled interrupt: %d %d\n",
@@ -719,10 +720,10 @@ static void jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev)
if (adev->jpeg.harvest_config & (1 << i))
continue;
if (adev->asic_type == CHIP_ARCTURUS)
- adev->jpeg.inst[i].ring_dec.funcs = &jpeg_v2_5_dec_ring_vm_funcs;
+ adev->jpeg.inst[i].ring_dec->funcs = &jpeg_v2_5_dec_ring_vm_funcs;
else /* CHIP_ALDEBARAN */
- adev->jpeg.inst[i].ring_dec.funcs = &jpeg_v2_6_dec_ring_vm_funcs;
- adev->jpeg.inst[i].ring_dec.me = i;
+ adev->jpeg.inst[i].ring_dec->funcs = &jpeg_v2_6_dec_ring_vm_funcs;
+ adev->jpeg.inst[i].ring_dec->me = i;
DRM_INFO("JPEG(%d) JPEG decode is enabled in VM mode\n", i);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
index 1c2292cc5f2c..79791379fc2b 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
@@ -64,6 +64,7 @@ static int jpeg_v3_0_early_init(void *handle)
}
adev->jpeg.num_jpeg_inst = 1;
+ adev->jpeg.num_jpeg_rings = 1;
jpeg_v3_0_set_dec_ring_funcs(adev);
jpeg_v3_0_set_irq_funcs(adev);
@@ -98,18 +99,18 @@ static int jpeg_v3_0_sw_init(void *handle)
if (r)
return r;
- ring = &adev->jpeg.inst->ring_dec;
+ ring = adev->jpeg.inst->ring_dec;
ring->use_doorbell = true;
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1;
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "jpeg_dec");
r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0,
AMDGPU_RING_PRIO_DEFAULT, NULL);
if (r)
return r;
- adev->jpeg.internal.jpeg_pitch = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
- adev->jpeg.inst->external.jpeg_pitch = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH);
+ adev->jpeg.internal.jpeg_pitch[0] = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
+ adev->jpeg.inst->external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH);
return 0;
}
@@ -144,7 +145,7 @@ static int jpeg_v3_0_sw_fini(void *handle)
static int jpeg_v3_0_hw_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- struct amdgpu_ring *ring = &adev->jpeg.inst->ring_dec;
+ struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
int r;
adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
@@ -330,7 +331,7 @@ static int jpeg_v3_0_enable_static_power_gating(struct amdgpu_device *adev)
*/
static int jpeg_v3_0_start(struct amdgpu_device *adev)
{
- struct amdgpu_ring *ring = &adev->jpeg.inst->ring_dec;
+ struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
int r;
if (adev->pm.dpm_enabled)
@@ -527,7 +528,7 @@ static int jpeg_v3_0_process_interrupt(struct amdgpu_device *adev,
switch (entry->src_id) {
case VCN_2_0__SRCID__JPEG_DECODE:
- amdgpu_fence_process(&adev->jpeg.inst->ring_dec);
+ amdgpu_fence_process(adev->jpeg.inst->ring_dec);
break;
default:
DRM_ERROR("Unhandled interrupt: %d %d\n",
@@ -589,7 +590,7 @@ static const struct amdgpu_ring_funcs jpeg_v3_0_dec_ring_vm_funcs = {
static void jpeg_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev)
{
- adev->jpeg.inst->ring_dec.funcs = &jpeg_v3_0_dec_ring_vm_funcs;
+ adev->jpeg.inst->ring_dec->funcs = &jpeg_v3_0_dec_ring_vm_funcs;
DRM_INFO("JPEG decode is enabled in VM mode\n");
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index a3d83c9f2c9a..a707d407fbd0 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -58,6 +58,7 @@ static int jpeg_v4_0_early_init(void *handle)
adev->jpeg.num_jpeg_inst = 1;
+ adev->jpeg.num_jpeg_rings = 1;
jpeg_v4_0_set_dec_ring_funcs(adev);
jpeg_v4_0_set_irq_funcs(adev);
@@ -105,10 +106,10 @@ static int jpeg_v4_0_sw_init(void *handle)
if (r)
return r;
- ring = &adev->jpeg.inst->ring_dec;
+ ring = adev->jpeg.inst->ring_dec;
ring->use_doorbell = true;
ring->doorbell_index = amdgpu_sriov_vf(adev) ? (((adev->doorbell_index.vcn.vcn_ring0_1) << 1) + 4) : ((adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1);
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "jpeg_dec");
r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0,
@@ -116,8 +117,8 @@ static int jpeg_v4_0_sw_init(void *handle)
if (r)
return r;
- adev->jpeg.internal.jpeg_pitch = regUVD_JPEG_PITCH_INTERNAL_OFFSET;
- adev->jpeg.inst->external.jpeg_pitch = SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_PITCH);
+ adev->jpeg.internal.jpeg_pitch[0] = regUVD_JPEG_PITCH_INTERNAL_OFFSET;
+ adev->jpeg.inst->external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_PITCH);
r = amdgpu_jpeg_ras_sw_init(adev);
if (r)
@@ -156,7 +157,7 @@ static int jpeg_v4_0_sw_fini(void *handle)
static int jpeg_v4_0_hw_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- struct amdgpu_ring *ring = &adev->jpeg.inst->ring_dec;
+ struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
int r;
if (amdgpu_sriov_vf(adev)) {
@@ -364,7 +365,7 @@ static int jpeg_v4_0_enable_static_power_gating(struct amdgpu_device *adev)
*/
static int jpeg_v4_0_start(struct amdgpu_device *adev)
{
- struct amdgpu_ring *ring = &adev->jpeg.inst->ring_dec;
+ struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
int r;
if (adev->pm.dpm_enabled)
@@ -442,7 +443,7 @@ static int jpeg_v4_0_start_sriov(struct amdgpu_device *adev)
table_size = 0;
- ring = &adev->jpeg.inst->ring_dec;
+ ring = adev->jpeg.inst->ring_dec;
MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(JPEG, 0,
regUVD_LMI_JRBC_RB_64BIT_BAR_LOW),
@@ -687,7 +688,7 @@ static int jpeg_v4_0_process_interrupt(struct amdgpu_device *adev,
switch (entry->src_id) {
case VCN_4_0__SRCID__JPEG_DECODE:
- amdgpu_fence_process(&adev->jpeg.inst->ring_dec);
+ amdgpu_fence_process(adev->jpeg.inst->ring_dec);
break;
default:
DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",
@@ -749,7 +750,7 @@ static const struct amdgpu_ring_funcs jpeg_v4_0_dec_ring_vm_funcs = {
static void jpeg_v4_0_set_dec_ring_funcs(struct amdgpu_device *adev)
{
- adev->jpeg.inst->ring_dec.funcs = &jpeg_v4_0_dec_ring_vm_funcs;
+ adev->jpeg.inst->ring_dec->funcs = &jpeg_v4_0_dec_ring_vm_funcs;
DRM_DEV_INFO(adev->dev, "JPEG decode is enabled in VM mode\n");
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
new file mode 100644
index 000000000000..ce2b22f7e4e4
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
@@ -0,0 +1,1074 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "amdgpu.h"
+#include "amdgpu_jpeg.h"
+#include "soc15.h"
+#include "soc15d.h"
+#include "jpeg_v4_0_3.h"
+
+#include "vcn/vcn_4_0_3_offset.h"
+#include "vcn/vcn_4_0_3_sh_mask.h"
+#include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"
+
+enum jpeg_engin_status {
+ UVD_PGFSM_STATUS__UVDJ_PWR_ON = 0,
+ UVD_PGFSM_STATUS__UVDJ_PWR_OFF = 2,
+};
+
+static void jpeg_v4_0_3_set_dec_ring_funcs(struct amdgpu_device *adev);
+static void jpeg_v4_0_3_set_irq_funcs(struct amdgpu_device *adev);
+static int jpeg_v4_0_3_set_powergating_state(void *handle,
+ enum amd_powergating_state state);
+static void jpeg_v4_0_3_set_ras_funcs(struct amdgpu_device *adev);
+
+static int amdgpu_ih_srcid_jpeg[] = {
+ VCN_4_0__SRCID__JPEG_DECODE,
+ VCN_4_0__SRCID__JPEG1_DECODE,
+ VCN_4_0__SRCID__JPEG2_DECODE,
+ VCN_4_0__SRCID__JPEG3_DECODE,
+ VCN_4_0__SRCID__JPEG4_DECODE,
+ VCN_4_0__SRCID__JPEG5_DECODE,
+ VCN_4_0__SRCID__JPEG6_DECODE,
+ VCN_4_0__SRCID__JPEG7_DECODE
+};
+
+/**
+ * jpeg_v4_0_3_early_init - set function pointers
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Set ring and irq function pointers
+ */
+static int jpeg_v4_0_3_early_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ adev->jpeg.num_jpeg_rings = AMDGPU_MAX_JPEG_RINGS;
+
+ jpeg_v4_0_3_set_dec_ring_funcs(adev);
+ jpeg_v4_0_3_set_irq_funcs(adev);
+ jpeg_v4_0_3_set_ras_funcs(adev);
+
+ return 0;
+}
+
+/**
+ * jpeg_v4_0_3_sw_init - sw init for JPEG block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Load firmware and sw initialization
+ */
+static int jpeg_v4_0_3_sw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_ring *ring;
+ int i, j, r, jpeg_inst;
+
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ /* JPEG TRAP */
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
+ amdgpu_ih_srcid_jpeg[j], &adev->jpeg.inst->irq);
+ if (r)
+ return r;
+ }
+
+ r = amdgpu_jpeg_sw_init(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_jpeg_resume(adev);
+ if (r)
+ return r;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ jpeg_inst = GET_INST(JPEG, i);
+
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ ring = &adev->jpeg.inst[i].ring_dec[j];
+ ring->use_doorbell = true;
+ ring->vm_hub = AMDGPU_MMHUB0(adev->jpeg.inst[i].aid_id);
+ ring->doorbell_index =
+ (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
+ 1 + j + 9 * jpeg_inst;
+ sprintf(ring->name, "jpeg_dec_%d.%d", adev->jpeg.inst[i].aid_id, j);
+ r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0,
+ AMDGPU_RING_PRIO_DEFAULT, NULL);
+ if (r)
+ return r;
+
+ adev->jpeg.internal.jpeg_pitch[j] =
+ regUVD_JRBC0_UVD_JRBC_SCRATCH0_INTERNAL_OFFSET;
+ adev->jpeg.inst[i].external.jpeg_pitch[j] =
+ SOC15_REG_OFFSET1(
+ JPEG, jpeg_inst,
+ regUVD_JRBC0_UVD_JRBC_SCRATCH0,
+ (j ? (0x40 * j - 0xc80) : 0));
+ }
+ }
+
+ if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__JPEG)) {
+ r = amdgpu_jpeg_ras_sw_init(adev);
+ if (r) {
+ dev_err(adev->dev, "Failed to initialize jpeg ras block!\n");
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * jpeg_v4_0_3_sw_fini - sw fini for JPEG block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * JPEG suspend and free up sw allocation
+ */
+static int jpeg_v4_0_3_sw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = amdgpu_jpeg_suspend(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_jpeg_sw_fini(adev);
+
+ return r;
+}
+
+/**
+ * jpeg_v4_0_3_hw_init - start and test JPEG block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ */
+static int jpeg_v4_0_3_hw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_ring *ring;
+ int i, j, r, jpeg_inst;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ jpeg_inst = GET_INST(JPEG, i);
+
+ ring = adev->jpeg.inst[i].ring_dec;
+
+ if (ring->use_doorbell)
+ adev->nbio.funcs->vcn_doorbell_range(
+ adev, ring->use_doorbell,
+ (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
+ 9 * jpeg_inst,
+ adev->jpeg.inst[i].aid_id);
+
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ ring = &adev->jpeg.inst[i].ring_dec[j];
+ if (ring->use_doorbell)
+ WREG32_SOC15_OFFSET(
+ VCN, GET_INST(VCN, i),
+ regVCN_JPEG_DB_CTRL,
+ (ring->pipe ? (ring->pipe - 0x15) : 0),
+ ring->doorbell_index
+ << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
+ VCN_JPEG_DB_CTRL__EN_MASK);
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ }
+ }
+ DRM_DEV_INFO(adev->dev, "JPEG decode initialized successfully.\n");
+
+ return 0;
+}
+
+/**
+ * jpeg_v4_0_3_hw_fini - stop the hardware block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Stop the JPEG block, mark ring as not ready any more
+ */
+static int jpeg_v4_0_3_hw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret = 0;
+
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
+
+ if (adev->jpeg.cur_state != AMD_PG_STATE_GATE)
+ ret = jpeg_v4_0_3_set_powergating_state(adev, AMD_PG_STATE_GATE);
+
+ return ret;
+}
+
+/**
+ * jpeg_v4_0_3_suspend - suspend JPEG block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * HW fini and suspend JPEG block
+ */
+static int jpeg_v4_0_3_suspend(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = jpeg_v4_0_3_hw_fini(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_jpeg_suspend(adev);
+
+ return r;
+}
+
+/**
+ * jpeg_v4_0_3_resume - resume JPEG block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Resume firmware and hw init JPEG block
+ */
+static int jpeg_v4_0_3_resume(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = amdgpu_jpeg_resume(adev);
+ if (r)
+ return r;
+
+ r = jpeg_v4_0_3_hw_init(adev);
+
+ return r;
+}
+
+static void jpeg_v4_0_3_disable_clock_gating(struct amdgpu_device *adev, int inst_idx)
+{
+ int i, jpeg_inst;
+ uint32_t data;
+
+ jpeg_inst = GET_INST(JPEG, inst_idx);
+ data = RREG32_SOC15(JPEG, jpeg_inst, regJPEG_CGC_CTRL);
+ if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) {
+ data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ data &= (~(JPEG_CGC_CTRL__JPEG0_DEC_MODE_MASK << 1));
+ } else {
+ data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ }
+
+ data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+ data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+ WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CGC_CTRL, data);
+
+ data = RREG32_SOC15(JPEG, jpeg_inst, regJPEG_CGC_GATE);
+ data &= ~(JPEG_CGC_GATE__JMCIF_MASK | JPEG_CGC_GATE__JRBBM_MASK);
+ for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i)
+ data &= ~(JPEG_CGC_GATE__JPEG0_DEC_MASK << i);
+ WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CGC_GATE, data);
+}
+
+static void jpeg_v4_0_3_enable_clock_gating(struct amdgpu_device *adev, int inst_idx)
+{
+ int i, jpeg_inst;
+ uint32_t data;
+
+ jpeg_inst = GET_INST(JPEG, inst_idx);
+ data = RREG32_SOC15(JPEG, jpeg_inst, regJPEG_CGC_CTRL);
+ if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) {
+ data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ data |= (JPEG_CGC_CTRL__JPEG0_DEC_MODE_MASK << 1);
+ } else {
+ data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ }
+
+ data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+ data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+ WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CGC_CTRL, data);
+
+ data = RREG32_SOC15(JPEG, jpeg_inst, regJPEG_CGC_GATE);
+ data |= (JPEG_CGC_GATE__JMCIF_MASK | JPEG_CGC_GATE__JRBBM_MASK);
+ for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i)
+ data |= (JPEG_CGC_GATE__JPEG0_DEC_MASK << i);
+ WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CGC_GATE, data);
+}
+
+/**
+ * jpeg_v4_0_3_start - start JPEG block
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Setup and start the JPEG block
+ */
+static int jpeg_v4_0_3_start(struct amdgpu_device *adev)
+{
+ struct amdgpu_ring *ring;
+ int i, j, jpeg_inst;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ jpeg_inst = GET_INST(JPEG, i);
+
+ WREG32_SOC15(JPEG, jpeg_inst, regUVD_PGFSM_CONFIG,
+ 1 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(
+ JPEG, jpeg_inst, regUVD_PGFSM_STATUS,
+ UVD_PGFSM_STATUS__UVDJ_PWR_ON
+ << UVD_PGFSM_STATUS__UVDJ_PWR_STATUS__SHIFT,
+ UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK);
+
+ /* disable anti hang mechanism */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst,
+ regUVD_JPEG_POWER_STATUS),
+ 0, ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
+
+ /* JPEG disable CGC */
+ jpeg_v4_0_3_disable_clock_gating(adev, i);
+
+ /* MJPEG global tiling registers */
+ WREG32_SOC15(JPEG, jpeg_inst, regJPEG_DEC_GFX8_ADDR_CONFIG,
+ adev->gfx.config.gb_addr_config);
+ WREG32_SOC15(JPEG, jpeg_inst, regJPEG_DEC_GFX10_ADDR_CONFIG,
+ adev->gfx.config.gb_addr_config);
+
+ /* enable JMI channel */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL), 0,
+ ~UVD_JMI_CNTL__SOFT_RESET_MASK);
+
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ unsigned int reg_offset = (j?(0x40 * j - 0xc80):0);
+
+ ring = &adev->jpeg.inst[i].ring_dec[j];
+
+ /* enable System Interrupt for JRBC */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst,
+ regJPEG_SYS_INT_EN),
+ JPEG_SYS_INT_EN__DJRBC0_MASK << j,
+ ~(JPEG_SYS_INT_EN__DJRBC0_MASK << j));
+
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JMI0_UVD_LMI_JRBC_RB_VMID,
+ reg_offset, 0);
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JRBC0_UVD_JRBC_RB_CNTL,
+ reg_offset,
+ (0x00000001L | 0x00000002L));
+ WREG32_SOC15_OFFSET(
+ JPEG, jpeg_inst,
+ regUVD_JMI0_UVD_LMI_JRBC_RB_64BIT_BAR_LOW,
+ reg_offset, lower_32_bits(ring->gpu_addr));
+ WREG32_SOC15_OFFSET(
+ JPEG, jpeg_inst,
+ regUVD_JMI0_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
+ reg_offset, upper_32_bits(ring->gpu_addr));
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JRBC0_UVD_JRBC_RB_RPTR,
+ reg_offset, 0);
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JRBC0_UVD_JRBC_RB_WPTR,
+ reg_offset, 0);
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JRBC0_UVD_JRBC_RB_CNTL,
+ reg_offset, 0x00000002L);
+ WREG32_SOC15_OFFSET(JPEG, jpeg_inst,
+ regUVD_JRBC0_UVD_JRBC_RB_SIZE,
+ reg_offset, ring->ring_size / 4);
+ ring->wptr = RREG32_SOC15_OFFSET(
+ JPEG, jpeg_inst, regUVD_JRBC0_UVD_JRBC_RB_WPTR,
+ reg_offset);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * jpeg_v4_0_3_stop - stop JPEG block
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * stop the JPEG block
+ */
+static int jpeg_v4_0_3_stop(struct amdgpu_device *adev)
+{
+ int i, jpeg_inst;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ jpeg_inst = GET_INST(JPEG, i);
+ /* reset JMI */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst, regUVD_JMI_CNTL),
+ UVD_JMI_CNTL__SOFT_RESET_MASK,
+ ~UVD_JMI_CNTL__SOFT_RESET_MASK);
+
+ jpeg_v4_0_3_enable_clock_gating(adev, i);
+
+ /* enable anti hang mechanism */
+ WREG32_P(SOC15_REG_OFFSET(JPEG, jpeg_inst,
+ regUVD_JPEG_POWER_STATUS),
+ UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
+ ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
+
+ WREG32_SOC15(JPEG, jpeg_inst, regUVD_PGFSM_CONFIG,
+ 2 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT);
+ SOC15_WAIT_ON_RREG(
+ JPEG, jpeg_inst, regUVD_PGFSM_STATUS,
+ UVD_PGFSM_STATUS__UVDJ_PWR_OFF
+ << UVD_PGFSM_STATUS__UVDJ_PWR_STATUS__SHIFT,
+ UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK);
+ }
+
+ return 0;
+}
+
+/**
+ * jpeg_v4_0_3_dec_ring_get_rptr - get read pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Returns the current hardware read pointer
+ */
+static uint64_t jpeg_v4_0_3_dec_ring_get_rptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ return RREG32_SOC15_OFFSET(
+ JPEG, GET_INST(JPEG, ring->me), regUVD_JRBC0_UVD_JRBC_RB_RPTR,
+ ring->pipe ? (0x40 * ring->pipe - 0xc80) : 0);
+}
+
+/**
+ * jpeg_v4_0_3_dec_ring_get_wptr - get write pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Returns the current hardware write pointer
+ */
+static uint64_t jpeg_v4_0_3_dec_ring_get_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring->use_doorbell)
+ return adev->wb.wb[ring->wptr_offs];
+ else
+ return RREG32_SOC15_OFFSET(
+ JPEG, GET_INST(JPEG, ring->me),
+ regUVD_JRBC0_UVD_JRBC_RB_WPTR,
+ ring->pipe ? (0x40 * ring->pipe - 0xc80) : 0);
+}
+
+/**
+ * jpeg_v4_0_3_dec_ring_set_wptr - set write pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Commits the write pointer to the hardware
+ */
+static void jpeg_v4_0_3_dec_ring_set_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring->use_doorbell) {
+ adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr);
+ WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
+ } else {
+ WREG32_SOC15_OFFSET(JPEG, GET_INST(JPEG, ring->me),
+ regUVD_JRBC0_UVD_JRBC_RB_WPTR,
+ (ring->pipe ? (0x40 * ring->pipe - 0xc80) :
+ 0),
+ lower_32_bits(ring->wptr));
+ }
+}
+
+/**
+ * jpeg_v4_0_3_dec_ring_insert_start - insert a start command
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Write a start command to the ring.
+ */
+static void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring)
+{
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x62a04); /* PCTL0_MMHUB_DEEPSLEEP_IB */
+
+ amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x80004000);
+}
+
+/**
+ * jpeg_v4_0_3_dec_ring_insert_end - insert a end command
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Write a end command to the ring.
+ */
+static void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring)
+{
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x62a04);
+
+ amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x00004000);
+}
+
+/**
+ * jpeg_v4_0_3_dec_ring_emit_fence - emit an fence & trap command
+ *
+ * @ring: amdgpu_ring pointer
+ * @addr: address
+ * @seq: sequence number
+ * @flags: fence related flags
+ *
+ * Write a fence and a trap command to the ring.
+ */
+static void jpeg_v4_0_3_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
+ unsigned int flags)
+{
+ WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JPEG_GPCOM_DATA0_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, seq);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JPEG_GPCOM_DATA1_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, seq);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, lower_32_bits(addr));
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, upper_32_bits(addr));
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JPEG_GPCOM_CMD_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x8);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JPEG_GPCOM_CMD_INTERNAL_OFFSET,
+ 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE4));
+ amdgpu_ring_write(ring, 0);
+
+ if (ring->adev->jpeg.inst[ring->me].aid_id) {
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_MCM_ADDR_INTERNAL_OFFSET,
+ 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x4);
+ } else {
+ amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE6));
+ amdgpu_ring_write(ring, 0);
+ }
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x3fbc);
+
+ if (ring->adev->jpeg.inst[ring->me].aid_id) {
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_MCM_ADDR_INTERNAL_OFFSET,
+ 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x0);
+ } else {
+ amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE6));
+ amdgpu_ring_write(ring, 0);
+ }
+
+ amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x1);
+
+ amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE7));
+ amdgpu_ring_write(ring, 0);
+}
+
+/**
+ * jpeg_v4_0_3_dec_ring_emit_ib - execute indirect buffer
+ *
+ * @ring: amdgpu_ring pointer
+ * @job: job to retrieve vmid from
+ * @ib: indirect buffer to execute
+ * @flags: unused
+ *
+ * Write ring commands to execute the indirect buffer.
+ */
+static void jpeg_v4_0_3_dec_ring_emit_ib(struct amdgpu_ring *ring,
+ struct amdgpu_job *job,
+ struct amdgpu_ib *ib,
+ uint32_t flags)
+{
+ unsigned int vmid = AMDGPU_JOB_GET_VMID(job);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, (vmid | (vmid << 4)));
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JPEG_VMID_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, (vmid | (vmid << 4)));
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JRBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_IB_SIZE_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, ib->length_dw);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, lower_32_bits(ring->gpu_addr));
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, upper_32_bits(ring->gpu_addr));
+
+ amdgpu_ring_write(ring, PACKETJ(0, 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE2));
+ amdgpu_ring_write(ring, 0);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_RB_COND_RD_TIMER_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x01400200);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_RB_REF_DATA_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x2);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_STATUS_INTERNAL_OFFSET,
+ 0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE3));
+ amdgpu_ring_write(ring, 0x2);
+}
+
+static void jpeg_v4_0_3_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
+ uint32_t val, uint32_t mask)
+{
+ uint32_t reg_offset = (reg << 2);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_RB_COND_RD_TIMER_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, 0x01400200);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_RB_REF_DATA_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ amdgpu_ring_write(ring, val);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ if (reg_offset >= 0x10000 && reg_offset <= 0x105ff) {
+ amdgpu_ring_write(ring, 0);
+ amdgpu_ring_write(ring,
+ PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3));
+ } else {
+ amdgpu_ring_write(ring, reg_offset);
+ amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
+ 0, 0, PACKETJ_TYPE3));
+ }
+ amdgpu_ring_write(ring, mask);
+}
+
+static void jpeg_v4_0_3_dec_ring_emit_vm_flush(struct amdgpu_ring *ring,
+ unsigned int vmid, uint64_t pd_addr)
+{
+ struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub];
+ uint32_t data0, data1, mask;
+
+ pd_addr = amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
+
+ /* wait for register write */
+ data0 = hub->ctx0_ptb_addr_lo32 + vmid * hub->ctx_addr_distance;
+ data1 = lower_32_bits(pd_addr);
+ mask = 0xffffffff;
+ jpeg_v4_0_3_dec_ring_emit_reg_wait(ring, data0, data1, mask);
+}
+
+static void jpeg_v4_0_3_dec_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val)
+{
+ uint32_t reg_offset = (reg << 2);
+
+ amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
+ 0, 0, PACKETJ_TYPE0));
+ if (reg_offset >= 0x10000 && reg_offset <= 0x105ff) {
+ amdgpu_ring_write(ring, 0);
+ amdgpu_ring_write(ring,
+ PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0));
+ } else {
+ amdgpu_ring_write(ring, reg_offset);
+ amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
+ 0, 0, PACKETJ_TYPE0));
+ }
+ amdgpu_ring_write(ring, val);
+}
+
+static void jpeg_v4_0_3_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count)
+{
+ int i;
+
+ WARN_ON(ring->wptr % 2 || count % 2);
+
+ for (i = 0; i < count / 2; i++) {
+ amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE6));
+ amdgpu_ring_write(ring, 0);
+ }
+}
+
+static bool jpeg_v4_0_3_is_idle(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ bool ret = false;
+ int i, j;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ unsigned int reg_offset = (j?(0x40 * j - 0xc80):0);
+
+ ret &= ((RREG32_SOC15_OFFSET(
+ JPEG, GET_INST(JPEG, i),
+ regUVD_JRBC0_UVD_JRBC_STATUS,
+ reg_offset) &
+ UVD_JRBC0_UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==
+ UVD_JRBC0_UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
+ }
+ }
+
+ return ret;
+}
+
+static int jpeg_v4_0_3_wait_for_idle(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret = 0;
+ int i, j;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ unsigned int reg_offset = (j?(0x40 * j - 0xc80):0);
+
+ ret &= SOC15_WAIT_ON_RREG_OFFSET(
+ JPEG, GET_INST(JPEG, i),
+ regUVD_JRBC0_UVD_JRBC_STATUS, reg_offset,
+ UVD_JRBC0_UVD_JRBC_STATUS__RB_JOB_DONE_MASK,
+ UVD_JRBC0_UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
+ }
+ }
+ return ret;
+}
+
+static int jpeg_v4_0_3_set_clockgating_state(void *handle,
+ enum amd_clockgating_state state)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
+ int i;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ if (enable) {
+ if (!jpeg_v4_0_3_is_idle(handle))
+ return -EBUSY;
+ jpeg_v4_0_3_enable_clock_gating(adev, i);
+ } else {
+ jpeg_v4_0_3_disable_clock_gating(adev, i);
+ }
+ }
+ return 0;
+}
+
+static int jpeg_v4_0_3_set_powergating_state(void *handle,
+ enum amd_powergating_state state)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
+
+ if (state == adev->jpeg.cur_state)
+ return 0;
+
+ if (state == AMD_PG_STATE_GATE)
+ ret = jpeg_v4_0_3_stop(adev);
+ else
+ ret = jpeg_v4_0_3_start(adev);
+
+ if (!ret)
+ adev->jpeg.cur_state = state;
+
+ return ret;
+}
+
+static int jpeg_v4_0_3_set_interrupt_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ unsigned int type,
+ enum amdgpu_interrupt_state state)
+{
+ return 0;
+}
+
+static int jpeg_v4_0_3_process_interrupt(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ uint32_t i, inst;
+
+ i = node_id_to_phys_map[entry->node_id];
+ DRM_DEV_DEBUG(adev->dev, "IH: JPEG TRAP\n");
+
+ for (inst = 0; inst < adev->jpeg.num_jpeg_inst; ++inst)
+ if (adev->jpeg.inst[inst].aid_id == i)
+ break;
+
+ if (inst >= adev->jpeg.num_jpeg_inst) {
+ dev_WARN_ONCE(adev->dev, 1,
+ "Interrupt received for unknown JPEG instance %d",
+ entry->node_id);
+ return 0;
+ }
+
+ switch (entry->src_id) {
+ case VCN_4_0__SRCID__JPEG_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[0]);
+ break;
+ case VCN_4_0__SRCID__JPEG1_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[1]);
+ break;
+ case VCN_4_0__SRCID__JPEG2_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[2]);
+ break;
+ case VCN_4_0__SRCID__JPEG3_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[3]);
+ break;
+ case VCN_4_0__SRCID__JPEG4_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[4]);
+ break;
+ case VCN_4_0__SRCID__JPEG5_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[5]);
+ break;
+ case VCN_4_0__SRCID__JPEG6_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[6]);
+ break;
+ case VCN_4_0__SRCID__JPEG7_DECODE:
+ amdgpu_fence_process(&adev->jpeg.inst[inst].ring_dec[7]);
+ break;
+ default:
+ DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",
+ entry->src_id, entry->src_data[0]);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct amd_ip_funcs jpeg_v4_0_3_ip_funcs = {
+ .name = "jpeg_v4_0_3",
+ .early_init = jpeg_v4_0_3_early_init,
+ .late_init = NULL,
+ .sw_init = jpeg_v4_0_3_sw_init,
+ .sw_fini = jpeg_v4_0_3_sw_fini,
+ .hw_init = jpeg_v4_0_3_hw_init,
+ .hw_fini = jpeg_v4_0_3_hw_fini,
+ .suspend = jpeg_v4_0_3_suspend,
+ .resume = jpeg_v4_0_3_resume,
+ .is_idle = jpeg_v4_0_3_is_idle,
+ .wait_for_idle = jpeg_v4_0_3_wait_for_idle,
+ .check_soft_reset = NULL,
+ .pre_soft_reset = NULL,
+ .soft_reset = NULL,
+ .post_soft_reset = NULL,
+ .set_clockgating_state = jpeg_v4_0_3_set_clockgating_state,
+ .set_powergating_state = jpeg_v4_0_3_set_powergating_state,
+};
+
+static const struct amdgpu_ring_funcs jpeg_v4_0_3_dec_ring_vm_funcs = {
+ .type = AMDGPU_RING_TYPE_VCN_JPEG,
+ .align_mask = 0xf,
+ .get_rptr = jpeg_v4_0_3_dec_ring_get_rptr,
+ .get_wptr = jpeg_v4_0_3_dec_ring_get_wptr,
+ .set_wptr = jpeg_v4_0_3_dec_ring_set_wptr,
+ .emit_frame_size =
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
+ 8 + /* jpeg_v4_0_3_dec_ring_emit_vm_flush */
+ 22 + 22 + /* jpeg_v4_0_3_dec_ring_emit_fence x2 vm fence */
+ 8 + 16,
+ .emit_ib_size = 22, /* jpeg_v4_0_3_dec_ring_emit_ib */
+ .emit_ib = jpeg_v4_0_3_dec_ring_emit_ib,
+ .emit_fence = jpeg_v4_0_3_dec_ring_emit_fence,
+ .emit_vm_flush = jpeg_v4_0_3_dec_ring_emit_vm_flush,
+ .test_ring = amdgpu_jpeg_dec_ring_test_ring,
+ .test_ib = amdgpu_jpeg_dec_ring_test_ib,
+ .insert_nop = jpeg_v4_0_3_dec_ring_nop,
+ .insert_start = jpeg_v4_0_3_dec_ring_insert_start,
+ .insert_end = jpeg_v4_0_3_dec_ring_insert_end,
+ .pad_ib = amdgpu_ring_generic_pad_ib,
+ .begin_use = amdgpu_jpeg_ring_begin_use,
+ .end_use = amdgpu_jpeg_ring_end_use,
+ .emit_wreg = jpeg_v4_0_3_dec_ring_emit_wreg,
+ .emit_reg_wait = jpeg_v4_0_3_dec_ring_emit_reg_wait,
+ .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+};
+
+static void jpeg_v4_0_3_set_dec_ring_funcs(struct amdgpu_device *adev)
+{
+ int i, j, jpeg_inst;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
+ adev->jpeg.inst[i].ring_dec[j].funcs = &jpeg_v4_0_3_dec_ring_vm_funcs;
+ adev->jpeg.inst[i].ring_dec[j].me = i;
+ adev->jpeg.inst[i].ring_dec[j].pipe = j;
+ }
+ jpeg_inst = GET_INST(JPEG, i);
+ adev->jpeg.inst[i].aid_id =
+ jpeg_inst / adev->jpeg.num_inst_per_aid;
+ }
+ DRM_DEV_INFO(adev->dev, "JPEG decode is enabled in VM mode\n");
+}
+
+static const struct amdgpu_irq_src_funcs jpeg_v4_0_3_irq_funcs = {
+ .set = jpeg_v4_0_3_set_interrupt_state,
+ .process = jpeg_v4_0_3_process_interrupt,
+};
+
+static void jpeg_v4_0_3_set_irq_funcs(struct amdgpu_device *adev)
+{
+ int i;
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
+ adev->jpeg.inst->irq.num_types += adev->jpeg.num_jpeg_rings;
+ }
+ adev->jpeg.inst->irq.funcs = &jpeg_v4_0_3_irq_funcs;
+}
+
+const struct amdgpu_ip_block_version jpeg_v4_0_3_ip_block = {
+ .type = AMD_IP_BLOCK_TYPE_JPEG,
+ .major = 4,
+ .minor = 0,
+ .rev = 3,
+ .funcs = &jpeg_v4_0_3_ip_funcs,
+};
+
+static const struct amdgpu_ras_err_status_reg_entry jpeg_v4_0_3_ue_reg_list[] = {
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG0S, regVCN_UE_ERR_STATUS_HI_JPEG0S),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG0S"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG0D, regVCN_UE_ERR_STATUS_HI_JPEG0D),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG0D"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG1S, regVCN_UE_ERR_STATUS_HI_JPEG1S),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG1S"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG1D, regVCN_UE_ERR_STATUS_HI_JPEG1D),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG1D"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG2S, regVCN_UE_ERR_STATUS_HI_JPEG2S),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG2S"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG2D, regVCN_UE_ERR_STATUS_HI_JPEG2D),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG2D"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG3S, regVCN_UE_ERR_STATUS_HI_JPEG3S),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG3S"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG3D, regVCN_UE_ERR_STATUS_HI_JPEG3D),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG3D"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG4S, regVCN_UE_ERR_STATUS_HI_JPEG4S),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG4S"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG4D, regVCN_UE_ERR_STATUS_HI_JPEG4D),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG4D"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG5S, regVCN_UE_ERR_STATUS_HI_JPEG5S),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG5S"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG5D, regVCN_UE_ERR_STATUS_HI_JPEG5D),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG5D"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG6S, regVCN_UE_ERR_STATUS_HI_JPEG6S),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG6S"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG6D, regVCN_UE_ERR_STATUS_HI_JPEG6D),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG6D"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG7S, regVCN_UE_ERR_STATUS_HI_JPEG7S),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG7S"},
+ {AMDGPU_RAS_REG_ENTRY(JPEG, 0, regVCN_UE_ERR_STATUS_LO_JPEG7D, regVCN_UE_ERR_STATUS_HI_JPEG7D),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "JPEG7D"},
+};
+
+static void jpeg_v4_0_3_inst_query_ras_error_count(struct amdgpu_device *adev,
+ uint32_t jpeg_inst,
+ void *ras_err_status)
+{
+ struct ras_err_data *err_data = (struct ras_err_data *)ras_err_status;
+
+ /* jpeg v4_0_3 only support uncorrectable errors */
+ amdgpu_ras_inst_query_ras_error_count(adev,
+ jpeg_v4_0_3_ue_reg_list,
+ ARRAY_SIZE(jpeg_v4_0_3_ue_reg_list),
+ NULL, 0, GET_INST(VCN, jpeg_inst),
+ AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
+ &err_data->ue_count);
+}
+
+static void jpeg_v4_0_3_query_ras_error_count(struct amdgpu_device *adev,
+ void *ras_err_status)
+{
+ uint32_t i;
+
+ if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__JPEG)) {
+ dev_warn(adev->dev, "JPEG RAS is not supported\n");
+ return;
+ }
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; i++)
+ jpeg_v4_0_3_inst_query_ras_error_count(adev, i, ras_err_status);
+}
+
+static void jpeg_v4_0_3_inst_reset_ras_error_count(struct amdgpu_device *adev,
+ uint32_t jpeg_inst)
+{
+ amdgpu_ras_inst_reset_ras_error_count(adev,
+ jpeg_v4_0_3_ue_reg_list,
+ ARRAY_SIZE(jpeg_v4_0_3_ue_reg_list),
+ GET_INST(VCN, jpeg_inst));
+}
+
+static void jpeg_v4_0_3_reset_ras_error_count(struct amdgpu_device *adev)
+{
+ uint32_t i;
+
+ if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__JPEG)) {
+ dev_warn(adev->dev, "JPEG RAS is not supported\n");
+ return;
+ }
+
+ for (i = 0; i < adev->jpeg.num_jpeg_inst; i++)
+ jpeg_v4_0_3_inst_reset_ras_error_count(adev, i);
+}
+
+static const struct amdgpu_ras_block_hw_ops jpeg_v4_0_3_ras_hw_ops = {
+ .query_ras_error_count = jpeg_v4_0_3_query_ras_error_count,
+ .reset_ras_error_count = jpeg_v4_0_3_reset_ras_error_count,
+};
+
+static struct amdgpu_jpeg_ras jpeg_v4_0_3_ras = {
+ .ras_block = {
+ .hw_ops = &jpeg_v4_0_3_ras_hw_ops,
+ },
+};
+
+static void jpeg_v4_0_3_set_ras_funcs(struct amdgpu_device *adev)
+{
+ adev->jpeg.ras = &jpeg_v4_0_3_ras;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h
new file mode 100644
index 000000000000..22483dc66351
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __JPEG_V4_0_3_H__
+#define __JPEG_V4_0_3_H__
+
+#define regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET 0x1bfff
+#define regUVD_JPEG_GPCOM_CMD_INTERNAL_OFFSET 0x404d
+#define regUVD_JPEG_GPCOM_DATA0_INTERNAL_OFFSET 0x404e
+#define regUVD_JPEG_GPCOM_DATA1_INTERNAL_OFFSET 0x404f
+#define regUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_INTERNAL_OFFSET 0x40ab
+#define regUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_INTERNAL_OFFSET 0x40ac
+#define regUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET 0x40a4
+#define regUVD_LMI_JPEG_VMID_INTERNAL_OFFSET 0x40a6
+#define regUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET 0x40b6
+#define regUVD_LMI_JRBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET 0x40b7
+#define regUVD_JRBC_IB_SIZE_INTERNAL_OFFSET 0x4082
+#define regUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW_INTERNAL_OFFSET 0x42d4
+#define regUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH_INTERNAL_OFFSET 0x42d5
+#define regUVD_JRBC_RB_COND_RD_TIMER_INTERNAL_OFFSET 0x4085
+#define regUVD_JRBC_RB_REF_DATA_INTERNAL_OFFSET 0x4084
+#define regUVD_JRBC_STATUS_INTERNAL_OFFSET 0x4089
+#define regUVD_JPEG_PITCH_INTERNAL_OFFSET 0x4043
+#define regUVD_JRBC0_UVD_JRBC_SCRATCH0_INTERNAL_OFFSET 0x4094
+#define regUVD_JRBC_EXTERNAL_MCM_ADDR_INTERNAL_OFFSET 0x1bffe
+
+#define JRBC_DEC_EXTERNAL_REG_WRITE_ADDR 0x18000
+
+extern const struct amdgpu_ip_block_version jpeg_v4_0_3_ip_block;
+
+#endif /* __JPEG_V4_0_3_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
index 2e2062636d5f..36a123e6c8ee 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
@@ -149,7 +149,7 @@ static int mes_v10_1_add_hw_queue(struct amdgpu_mes *mes,
{
struct amdgpu_device *adev = mes->adev;
union MESAPI__ADD_QUEUE mes_add_queue_pkt;
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
uint32_t vm_cntx_cntl = hub->vm_cntx_cntl;
memset(&mes_add_queue_pkt, 0, sizeof(mes_add_queue_pkt));
@@ -632,6 +632,8 @@ static int mes_v10_1_mqd_init(struct amdgpu_ring *ring)
uint64_t hqd_gpu_addr, wb_gpu_addr, eop_base_addr;
uint32_t tmp;
+ memset(mqd, 0, sizeof(*mqd));
+
mqd->header = 0xC0310800;
mqd->compute_pipelinestat_enable = 0x00000001;
mqd->compute_static_thread_mgmt_se0 = 0xffffffff;
@@ -728,6 +730,7 @@ static int mes_v10_1_mqd_init(struct amdgpu_ring *ring)
/* offset: 184 - this is used for CP_HQD_GFX_CONTROL */
mqd->cp_hqd_suspend_cntl_stack_offset = tmp;
+ amdgpu_device_flush_hdp(ring->adev, NULL);
return 0;
}
@@ -797,8 +800,8 @@ static void mes_v10_1_queue_init_register(struct amdgpu_ring *ring)
static int mes_v10_1_kiq_enable_queue(struct amdgpu_device *adev)
{
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
- struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
+ struct amdgpu_ring *kiq_ring = &adev->gfx.kiq[0].ring;
int r;
if (!kiq->pmf || !kiq->pmf->kiq_map_queues)
@@ -812,13 +815,7 @@ static int mes_v10_1_kiq_enable_queue(struct amdgpu_device *adev)
kiq->pmf->kiq_map_queues(kiq_ring, &adev->mes.ring);
- r = amdgpu_ring_test_ring(kiq_ring);
- if (r) {
- DRM_ERROR("kfq enable failed\n");
- kiq_ring->sched.ready = false;
- }
-
- return r;
+ return amdgpu_ring_test_helper(kiq_ring);
}
static int mes_v10_1_queue_init(struct amdgpu_device *adev)
@@ -863,9 +860,9 @@ static int mes_v10_1_kiq_ring_init(struct amdgpu_device *adev)
{
struct amdgpu_ring *ring;
- spin_lock_init(&adev->gfx.kiq.ring_lock);
+ spin_lock_init(&adev->gfx.kiq[0].ring_lock);
- ring = &adev->gfx.kiq.ring;
+ ring = &adev->gfx.kiq[0].ring;
ring->me = 3;
ring->pipe = 1;
@@ -891,7 +888,7 @@ static int mes_v10_1_mqd_sw_init(struct amdgpu_device *adev,
struct amdgpu_ring *ring;
if (pipe == AMDGPU_MES_KIQ_PIPE)
- ring = &adev->gfx.kiq.ring;
+ ring = &adev->gfx.kiq[0].ring;
else if (pipe == AMDGPU_MES_SCHED_PIPE)
ring = &adev->mes.ring;
else
@@ -901,6 +898,7 @@ static int mes_v10_1_mqd_sw_init(struct amdgpu_device *adev,
return 0;
r = amdgpu_bo_create_kernel(adev, mqd_size, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM |
AMDGPU_GEM_DOMAIN_GTT, &ring->mqd_obj,
&ring->mqd_gpu_addr, &ring->mqd_ptr);
if (r) {
@@ -974,15 +972,15 @@ static int mes_v10_1_sw_fini(void *handle)
amdgpu_ucode_release(&adev->mes.fw[pipe]);
}
- amdgpu_bo_free_kernel(&adev->gfx.kiq.ring.mqd_obj,
- &adev->gfx.kiq.ring.mqd_gpu_addr,
- &adev->gfx.kiq.ring.mqd_ptr);
+ amdgpu_bo_free_kernel(&adev->gfx.kiq[0].ring.mqd_obj,
+ &adev->gfx.kiq[0].ring.mqd_gpu_addr,
+ &adev->gfx.kiq[0].ring.mqd_ptr);
amdgpu_bo_free_kernel(&adev->mes.ring.mqd_obj,
&adev->mes.ring.mqd_gpu_addr,
&adev->mes.ring.mqd_ptr);
- amdgpu_ring_fini(&adev->gfx.kiq.ring);
+ amdgpu_ring_fini(&adev->gfx.kiq[0].ring);
amdgpu_ring_fini(&adev->mes.ring);
amdgpu_mes_fini(adev);
@@ -1038,7 +1036,7 @@ static int mes_v10_1_kiq_hw_init(struct amdgpu_device *adev)
mes_v10_1_enable(adev, true);
- mes_v10_1_kiq_setting(&adev->gfx.kiq.ring);
+ mes_v10_1_kiq_setting(&adev->gfx.kiq[0].ring);
r = mes_v10_1_queue_init(adev);
if (r)
@@ -1090,7 +1088,7 @@ static int mes_v10_1_hw_init(void *handle)
* MES uses KIQ ring exclusively so driver cannot access KIQ ring
* with MES enabled.
*/
- adev->gfx.kiq.ring.sched.ready = false;
+ adev->gfx.kiq[0].ring.sched.ready = false;
adev->mes.ring.sched.ready = true;
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index 45280f047180..1bdaa00c0b46 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -164,7 +164,7 @@ static int mes_v11_0_add_hw_queue(struct amdgpu_mes *mes,
{
struct amdgpu_device *adev = mes->adev;
union MESAPI__ADD_QUEUE mes_add_queue_pkt;
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
uint32_t vm_cntx_cntl = hub->vm_cntx_cntl;
memset(&mes_add_queue_pkt, 0, sizeof(mes_add_queue_pkt));
@@ -202,17 +202,14 @@ static int mes_v11_0_add_hw_queue(struct amdgpu_mes *mes,
mes_add_queue_pkt.gws_size = input->gws_size;
mes_add_queue_pkt.trap_handler_addr = input->tba_addr;
mes_add_queue_pkt.tma_addr = input->tma_addr;
+ mes_add_queue_pkt.trap_en = input->trap_en;
+ mes_add_queue_pkt.skip_process_ctx_clear = input->skip_process_ctx_clear;
mes_add_queue_pkt.is_kfd_process = input->is_kfd_process;
/* For KFD, gds_size is re-used for queue size (needed in MES for AQL queues) */
mes_add_queue_pkt.is_aql_queue = input->is_aql_queue;
mes_add_queue_pkt.gds_size = input->queue_size;
- if (!(((adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 4) &&
- (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(11, 0, 0)) &&
- (adev->ip_versions[GC_HWIP][0] <= IP_VERSION(11, 0, 3))))
- mes_add_queue_pkt.trap_en = 1;
-
/* For KFD, gds_size is re-used for queue size (needed in MES for AQL queues) */
mes_add_queue_pkt.is_aql_queue = input->is_aql_queue;
mes_add_queue_pkt.gds_size = input->queue_size;
@@ -339,6 +336,19 @@ static int mes_v11_0_misc_op(struct amdgpu_mes *mes,
misc_pkt.wait_reg_mem.reg_offset1 = input->wrm_reg.reg0;
misc_pkt.wait_reg_mem.reg_offset2 = input->wrm_reg.reg1;
break;
+ case MES_MISC_OP_SET_SHADER_DEBUGGER:
+ misc_pkt.opcode = MESAPI_MISC__SET_SHADER_DEBUGGER;
+ misc_pkt.set_shader_debugger.process_context_addr =
+ input->set_shader_debugger.process_context_addr;
+ misc_pkt.set_shader_debugger.flags.u32all =
+ input->set_shader_debugger.flags.u32all;
+ misc_pkt.set_shader_debugger.spi_gdbg_per_vmid_cntl =
+ input->set_shader_debugger.spi_gdbg_per_vmid_cntl;
+ memcpy(misc_pkt.set_shader_debugger.tcp_watch_cntl,
+ input->set_shader_debugger.tcp_watch_cntl,
+ sizeof(misc_pkt.set_shader_debugger.tcp_watch_cntl));
+ misc_pkt.set_shader_debugger.trap_en = input->set_shader_debugger.trap_en;
+ break;
default:
DRM_ERROR("unsupported misc op (%d) \n", input->op);
return -EINVAL;
@@ -704,6 +714,8 @@ static int mes_v11_0_mqd_init(struct amdgpu_ring *ring)
uint64_t hqd_gpu_addr, wb_gpu_addr, eop_base_addr;
uint32_t tmp;
+ memset(mqd, 0, sizeof(*mqd));
+
mqd->header = 0xC0310800;
mqd->compute_pipelinestat_enable = 0x00000001;
mqd->compute_static_thread_mgmt_se0 = 0xffffffff;
@@ -797,6 +809,7 @@ static int mes_v11_0_mqd_init(struct amdgpu_ring *ring)
mqd->cp_hqd_iq_timer = regCP_HQD_IQ_TIMER_DEFAULT;
mqd->cp_hqd_quantum = regCP_HQD_QUANTUM_DEFAULT;
+ amdgpu_device_flush_hdp(ring->adev, NULL);
return 0;
}
@@ -864,8 +877,8 @@ static void mes_v11_0_queue_init_register(struct amdgpu_ring *ring)
static int mes_v11_0_kiq_enable_queue(struct amdgpu_device *adev)
{
- struct amdgpu_kiq *kiq = &adev->gfx.kiq;
- struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
+ struct amdgpu_ring *kiq_ring = &adev->gfx.kiq[0].ring;
int r;
if (!kiq->pmf || !kiq->pmf->kiq_map_queues)
@@ -879,12 +892,7 @@ static int mes_v11_0_kiq_enable_queue(struct amdgpu_device *adev)
kiq->pmf->kiq_map_queues(kiq_ring, &adev->mes.ring);
- r = amdgpu_ring_test_ring(kiq_ring);
- if (r) {
- DRM_ERROR("kfq enable failed\n");
- kiq_ring->sched.ready = false;
- }
- return r;
+ return amdgpu_ring_test_helper(kiq_ring);
}
static int mes_v11_0_queue_init(struct amdgpu_device *adev,
@@ -894,7 +902,7 @@ static int mes_v11_0_queue_init(struct amdgpu_device *adev,
int r;
if (pipe == AMDGPU_MES_KIQ_PIPE)
- ring = &adev->gfx.kiq.ring;
+ ring = &adev->gfx.kiq[0].ring;
else if (pipe == AMDGPU_MES_SCHED_PIPE)
ring = &adev->mes.ring;
else
@@ -961,9 +969,9 @@ static int mes_v11_0_kiq_ring_init(struct amdgpu_device *adev)
{
struct amdgpu_ring *ring;
- spin_lock_init(&adev->gfx.kiq.ring_lock);
+ spin_lock_init(&adev->gfx.kiq[0].ring_lock);
- ring = &adev->gfx.kiq.ring;
+ ring = &adev->gfx.kiq[0].ring;
ring->me = 3;
ring->pipe = 1;
@@ -989,7 +997,7 @@ static int mes_v11_0_mqd_sw_init(struct amdgpu_device *adev,
struct amdgpu_ring *ring;
if (pipe == AMDGPU_MES_KIQ_PIPE)
- ring = &adev->gfx.kiq.ring;
+ ring = &adev->gfx.kiq[0].ring;
else if (pipe == AMDGPU_MES_SCHED_PIPE)
ring = &adev->mes.ring;
else
@@ -999,6 +1007,7 @@ static int mes_v11_0_mqd_sw_init(struct amdgpu_device *adev,
return 0;
r = amdgpu_bo_create_kernel(adev, mqd_size, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM |
AMDGPU_GEM_DOMAIN_GTT, &ring->mqd_obj,
&ring->mqd_gpu_addr, &ring->mqd_ptr);
if (r) {
@@ -1074,15 +1083,15 @@ static int mes_v11_0_sw_fini(void *handle)
amdgpu_ucode_release(&adev->mes.fw[pipe]);
}
- amdgpu_bo_free_kernel(&adev->gfx.kiq.ring.mqd_obj,
- &adev->gfx.kiq.ring.mqd_gpu_addr,
- &adev->gfx.kiq.ring.mqd_ptr);
+ amdgpu_bo_free_kernel(&adev->gfx.kiq[0].ring.mqd_obj,
+ &adev->gfx.kiq[0].ring.mqd_gpu_addr,
+ &adev->gfx.kiq[0].ring.mqd_ptr);
amdgpu_bo_free_kernel(&adev->mes.ring.mqd_obj,
&adev->mes.ring.mqd_gpu_addr,
&adev->mes.ring.mqd_ptr);
- amdgpu_ring_fini(&adev->gfx.kiq.ring);
+ amdgpu_ring_fini(&adev->gfx.kiq[0].ring);
amdgpu_ring_fini(&adev->mes.ring);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
@@ -1175,7 +1184,7 @@ static int mes_v11_0_kiq_hw_init(struct amdgpu_device *adev)
mes_v11_0_enable(adev, true);
- mes_v11_0_kiq_setting(&adev->gfx.kiq.ring);
+ mes_v11_0_kiq_setting(&adev->gfx.kiq[0].ring);
r = mes_v11_0_queue_init(adev, AMDGPU_MES_KIQ_PIPE);
if (r)
@@ -1196,7 +1205,7 @@ static int mes_v11_0_kiq_hw_fini(struct amdgpu_device *adev)
}
if (amdgpu_sriov_vf(adev)) {
- mes_v11_0_kiq_dequeue(&adev->gfx.kiq.ring);
+ mes_v11_0_kiq_dequeue(&adev->gfx.kiq[0].ring);
mes_v11_0_kiq_clear(adev);
}
@@ -1244,7 +1253,7 @@ static int mes_v11_0_hw_init(void *handle)
* MES uses KIQ ring exclusively so driver cannot access KIQ ring
* with MES enabled.
*/
- adev->gfx.kiq.ring.sched.ready = false;
+ adev->gfx.kiq[0].ring.sched.ready = false;
adev->mes.ring.sched.ready = true;
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
index 15e7cbeae75b..fb91b31056ca 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
@@ -54,7 +54,7 @@ static u64 mmhub_v1_0_get_fb_location(struct amdgpu_device *adev)
static void mmhub_v1_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
WREG32_SOC15_OFFSET(MMHUB, 0, mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
hub->ctx_addr_distance * vmid,
@@ -229,7 +229,7 @@ static void mmhub_v1_0_disable_identity_aperture(struct amdgpu_device *adev)
static void mmhub_v1_0_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
unsigned num_level, block_size;
uint32_t tmp;
int i;
@@ -285,7 +285,7 @@ static void mmhub_v1_0_setup_vmid_config(struct amdgpu_device *adev)
static void mmhub_v1_0_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
unsigned i;
for (i = 0; i < 18; ++i) {
@@ -338,7 +338,7 @@ static int mmhub_v1_0_gart_enable(struct amdgpu_device *adev)
static void mmhub_v1_0_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
u32 tmp;
u32 i;
@@ -415,7 +415,7 @@ static void mmhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev, bool
static void mmhub_v1_0_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
hub->ctx0_ptb_addr_lo32 =
SOC15_REG_OFFSET(MMHUB, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c
index 73afbf2facc9..9086f2fdfaf4 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c
@@ -54,7 +54,7 @@ static u64 mmhub_v1_7_get_fb_location(struct amdgpu_device *adev)
static void mmhub_v1_7_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
WREG32_SOC15_OFFSET(MMHUB, 0, regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
hub->ctx_addr_distance * vmid, lower_32_bits(page_table_base));
@@ -261,7 +261,7 @@ static void mmhub_v1_7_disable_identity_aperture(struct amdgpu_device *adev)
static void mmhub_v1_7_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
unsigned num_level, block_size;
uint32_t tmp;
int i;
@@ -319,7 +319,7 @@ static void mmhub_v1_7_setup_vmid_config(struct amdgpu_device *adev)
static void mmhub_v1_7_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
unsigned i;
for (i = 0; i < 18; ++i) {
@@ -348,7 +348,7 @@ static int mmhub_v1_7_gart_enable(struct amdgpu_device *adev)
static void mmhub_v1_7_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
u32 tmp;
u32 i;
@@ -425,7 +425,7 @@ static void mmhub_v1_7_set_fault_enable_default(struct amdgpu_device *adev, bool
static void mmhub_v1_7_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
hub->ctx0_ptb_addr_lo32 =
SOC15_REG_OFFSET(MMHUB, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
index 342d1702104c..5e8b493f8699 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
@@ -29,6 +29,7 @@
#include "soc15_common.h"
#include "soc15.h"
+#include "amdgpu_ras.h"
#define regVM_L2_CNTL3_DEFAULT 0x80100007
#define regVM_L2_CNTL4_DEFAULT 0x000000c1
@@ -53,18 +54,30 @@ static u64 mmhub_v1_8_get_fb_location(struct amdgpu_device *adev)
static void mmhub_v1_8_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
-
- WREG32_SOC15_OFFSET(MMHUB, 0, regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
- hub->ctx_addr_distance * vmid, lower_32_bits(page_table_base));
+ struct amdgpu_vmhub *hub;
+ u32 inst_mask;
+ int i;
- WREG32_SOC15_OFFSET(MMHUB, 0, regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
- hub->ctx_addr_distance * vmid, upper_32_bits(page_table_base));
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask) {
+ hub = &adev->vmhub[AMDGPU_MMHUB0(i)];
+ WREG32_SOC15_OFFSET(MMHUB, i,
+ regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
+ hub->ctx_addr_distance * vmid,
+ lower_32_bits(page_table_base));
+
+ WREG32_SOC15_OFFSET(MMHUB, i,
+ regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
+ hub->ctx_addr_distance * vmid,
+ upper_32_bits(page_table_base));
+ }
}
static void mmhub_v1_8_init_gart_aperture_regs(struct amdgpu_device *adev)
{
uint64_t pt_base;
+ u32 inst_mask;
+ int i;
if (adev->gmc.pdb0_bo)
pt_base = amdgpu_gmc_pd_addr(adev->gmc.pdb0_bo);
@@ -76,187 +89,248 @@ static void mmhub_v1_8_init_gart_aperture_regs(struct amdgpu_device *adev)
/* If use GART for FB translation, vmid0 page table covers both
* vram and system memory (gart)
*/
- if (adev->gmc.pdb0_bo) {
- WREG32_SOC15(MMHUB, 0, regVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
- (u32)(adev->gmc.fb_start >> 12));
- WREG32_SOC15(MMHUB, 0, regVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
- (u32)(adev->gmc.fb_start >> 44));
-
- WREG32_SOC15(MMHUB, 0, regVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
- (u32)(adev->gmc.gart_end >> 12));
- WREG32_SOC15(MMHUB, 0, regVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
- (u32)(adev->gmc.gart_end >> 44));
-
- } else {
- WREG32_SOC15(MMHUB, 0, regVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
- (u32)(adev->gmc.gart_start >> 12));
- WREG32_SOC15(MMHUB, 0, regVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
- (u32)(adev->gmc.gart_start >> 44));
-
- WREG32_SOC15(MMHUB, 0, regVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
- (u32)(adev->gmc.gart_end >> 12));
- WREG32_SOC15(MMHUB, 0, regVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
- (u32)(adev->gmc.gart_end >> 44));
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask) {
+ if (adev->gmc.pdb0_bo) {
+ WREG32_SOC15(MMHUB, i,
+ regVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
+ (u32)(adev->gmc.fb_start >> 12));
+ WREG32_SOC15(MMHUB, i,
+ regVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
+ (u32)(adev->gmc.fb_start >> 44));
+
+ WREG32_SOC15(MMHUB, i,
+ regVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
+ (u32)(adev->gmc.gart_end >> 12));
+ WREG32_SOC15(MMHUB, i,
+ regVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
+ (u32)(adev->gmc.gart_end >> 44));
+
+ } else {
+ WREG32_SOC15(MMHUB, i,
+ regVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
+ (u32)(adev->gmc.gart_start >> 12));
+ WREG32_SOC15(MMHUB, i,
+ regVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
+ (u32)(adev->gmc.gart_start >> 44));
+
+ WREG32_SOC15(MMHUB, i,
+ regVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
+ (u32)(adev->gmc.gart_end >> 12));
+ WREG32_SOC15(MMHUB, i,
+ regVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
+ (u32)(adev->gmc.gart_end >> 44));
+ }
}
}
static void mmhub_v1_8_init_system_aperture_regs(struct amdgpu_device *adev)
{
+ uint32_t tmp, inst_mask;
uint64_t value;
- uint32_t tmp;
+ int i;
- /* Program the AGP BAR */
- WREG32_SOC15(MMHUB, 0, regMC_VM_AGP_BASE, 0);
- WREG32_SOC15(MMHUB, 0, regMC_VM_AGP_BOT, adev->gmc.agp_start >> 24);
- WREG32_SOC15(MMHUB, 0, regMC_VM_AGP_TOP, adev->gmc.agp_end >> 24);
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask) {
+ /* Program the AGP BAR */
+ WREG32_SOC15(MMHUB, i, regMC_VM_AGP_BASE, 0);
+ WREG32_SOC15(MMHUB, i, regMC_VM_AGP_BOT,
+ adev->gmc.agp_start >> 24);
+ WREG32_SOC15(MMHUB, i, regMC_VM_AGP_TOP,
+ adev->gmc.agp_end >> 24);
- /* Program the system aperture low logical page number. */
- WREG32_SOC15(MMHUB, 0, regMC_VM_SYSTEM_APERTURE_LOW_ADDR,
- min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
+ if (amdgpu_sriov_vf(adev))
+ return;
- WREG32_SOC15(MMHUB, 0, regMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
- max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
+ /* Program the system aperture low logical page number. */
+ WREG32_SOC15(MMHUB, i, regMC_VM_SYSTEM_APERTURE_LOW_ADDR,
+ min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
- /* In the case squeezing vram into GART aperture, we don't use
- * FB aperture and AGP aperture. Disable them.
- */
- if (adev->gmc.pdb0_bo) {
- WREG32_SOC15(MMHUB, 0, regMC_VM_AGP_BOT, 0xFFFFFF);
- WREG32_SOC15(MMHUB, 0, regMC_VM_AGP_TOP, 0);
- WREG32_SOC15(MMHUB, 0, regMC_VM_FB_LOCATION_TOP, 0);
- WREG32_SOC15(MMHUB, 0, regMC_VM_FB_LOCATION_BASE, 0x00FFFFFF);
- WREG32_SOC15(MMHUB, 0, regMC_VM_SYSTEM_APERTURE_LOW_ADDR, 0x3FFFFFFF);
- WREG32_SOC15(MMHUB, 0, regMC_VM_SYSTEM_APERTURE_HIGH_ADDR, 0);
- }
- if (amdgpu_sriov_vf(adev))
- return;
+ WREG32_SOC15(MMHUB, i, regMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+ max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
- /* Set default page address. */
- value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
- WREG32_SOC15(MMHUB, 0, regMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
- (u32)(value >> 12));
- WREG32_SOC15(MMHUB, 0, regMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
- (u32)(value >> 44));
-
- /* Program "protection fault". */
- WREG32_SOC15(MMHUB, 0, regVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
- (u32)(adev->dummy_page_addr >> 12));
- WREG32_SOC15(MMHUB, 0, regVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
- (u32)((u64)adev->dummy_page_addr >> 44));
-
- tmp = RREG32_SOC15(MMHUB, 0, regVM_L2_PROTECTION_FAULT_CNTL2);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL2,
- ACTIVE_PAGE_MIGRATION_PTE_READ_RETRY, 1);
- WREG32_SOC15(MMHUB, 0, regVM_L2_PROTECTION_FAULT_CNTL2, tmp);
+ /* In the case squeezing vram into GART aperture, we don't use
+ * FB aperture and AGP aperture. Disable them.
+ */
+ if (adev->gmc.pdb0_bo) {
+ WREG32_SOC15(MMHUB, i, regMC_VM_AGP_BOT, 0xFFFFFF);
+ WREG32_SOC15(MMHUB, i, regMC_VM_AGP_TOP, 0);
+ WREG32_SOC15(MMHUB, i, regMC_VM_FB_LOCATION_TOP, 0);
+ WREG32_SOC15(MMHUB, i, regMC_VM_FB_LOCATION_BASE,
+ 0x00FFFFFF);
+ WREG32_SOC15(MMHUB, i,
+ regMC_VM_SYSTEM_APERTURE_LOW_ADDR,
+ 0x3FFFFFFF);
+ WREG32_SOC15(MMHUB, i,
+ regMC_VM_SYSTEM_APERTURE_HIGH_ADDR, 0);
+ }
+
+ /* Set default page address. */
+ value = amdgpu_gmc_vram_mc2pa(adev, adev->mem_scratch.gpu_addr);
+ WREG32_SOC15(MMHUB, i, regMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
+ (u32)(value >> 12));
+ WREG32_SOC15(MMHUB, i, regMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
+ (u32)(value >> 44));
+
+ /* Program "protection fault". */
+ WREG32_SOC15(MMHUB, i,
+ regVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
+ (u32)(adev->dummy_page_addr >> 12));
+ WREG32_SOC15(MMHUB, i,
+ regVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
+ (u32)((u64)adev->dummy_page_addr >> 44));
+
+ tmp = RREG32_SOC15(MMHUB, i, regVM_L2_PROTECTION_FAULT_CNTL2);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL2,
+ ACTIVE_PAGE_MIGRATION_PTE_READ_RETRY, 1);
+ WREG32_SOC15(MMHUB, i, regVM_L2_PROTECTION_FAULT_CNTL2, tmp);
+ }
}
static void mmhub_v1_8_init_tlb_regs(struct amdgpu_device *adev)
{
- uint32_t tmp;
+ uint32_t tmp, inst_mask;
+ int i;
/* Setup TLB control */
- tmp = RREG32_SOC15(MMHUB, 0, regMC_VM_MX_L1_TLB_CNTL);
-
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 1);
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, 3);
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
- ENABLE_ADVANCED_DRIVER_MODEL, 1);
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
- SYSTEM_APERTURE_UNMAPPED_ACCESS, 0);
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
- MTYPE, MTYPE_UC);/* XXX for emulation. */
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ATC_EN, 1);
-
- WREG32_SOC15(MMHUB, 0, regMC_VM_MX_L1_TLB_CNTL, tmp);
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask) {
+ tmp = RREG32_SOC15(MMHUB, i, regMC_VM_MX_L1_TLB_CNTL);
+
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB,
+ 1);
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
+ SYSTEM_ACCESS_MODE, 3);
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
+ ENABLE_ADVANCED_DRIVER_MODEL, 1);
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
+ SYSTEM_APERTURE_UNMAPPED_ACCESS, 0);
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
+ MTYPE, MTYPE_UC);/* XXX for emulation. */
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ATC_EN, 1);
+
+ WREG32_SOC15(MMHUB, i, regMC_VM_MX_L1_TLB_CNTL, tmp);
+ }
}
static void mmhub_v1_8_init_cache_regs(struct amdgpu_device *adev)
{
- uint32_t tmp;
+ uint32_t tmp, inst_mask;
+ int i;
if (amdgpu_sriov_vf(adev))
return;
/* Setup L2 cache */
- tmp = RREG32_SOC15(MMHUB, 0, regVM_L2_CNTL);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_CACHE, 1);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING, 1);
- /* XXX for emulation, Refer to closed source code.*/
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, L2_PDE0_CACHE_TAG_GENERATION_MODE,
- 0);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, PDE_FAULT_CLASSIFICATION, 0);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, IDENTITY_MODE_FRAGMENT_SIZE, 0);
- WREG32_SOC15(MMHUB, 0, regVM_L2_CNTL, tmp);
-
- tmp = RREG32_SOC15(MMHUB, 0, regVM_L2_CNTL2);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
- WREG32_SOC15(MMHUB, 0, regVM_L2_CNTL2, tmp);
-
- tmp = regVM_L2_CNTL3_DEFAULT;
- if (adev->gmc.translate_further) {
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3, BANK_SELECT, 12);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3,
- L2_CACHE_BIGK_FRAGMENT_SIZE, 9);
- } else {
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3, BANK_SELECT, 9);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3,
- L2_CACHE_BIGK_FRAGMENT_SIZE, 6);
- }
- WREG32_SOC15(MMHUB, 0, regVM_L2_CNTL3, tmp);
-
- tmp = regVM_L2_CNTL4_DEFAULT;
- if (adev->gmc.xgmi.connected_to_cpu) {
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4,
- VMC_TAP_PDE_REQUEST_PHYSICAL, 1);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4,
- VMC_TAP_PTE_REQUEST_PHYSICAL, 1);
- } else {
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4,
- VMC_TAP_PDE_REQUEST_PHYSICAL, 0);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4,
- VMC_TAP_PTE_REQUEST_PHYSICAL, 0);
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask) {
+ tmp = RREG32_SOC15(MMHUB, i, regVM_L2_CNTL);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_CACHE, 1);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL,
+ ENABLE_L2_FRAGMENT_PROCESSING, 1);
+ /* XXX for emulation, Refer to closed source code.*/
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL,
+ L2_PDE0_CACHE_TAG_GENERATION_MODE, 0);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, PDE_FAULT_CLASSIFICATION,
+ 0);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL,
+ CONTEXT1_IDENTITY_ACCESS_MODE, 1);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL,
+ IDENTITY_MODE_FRAGMENT_SIZE, 0);
+ WREG32_SOC15(MMHUB, i, regVM_L2_CNTL, tmp);
+
+ tmp = RREG32_SOC15(MMHUB, i, regVM_L2_CNTL2);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS,
+ 1);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
+ WREG32_SOC15(MMHUB, i, regVM_L2_CNTL2, tmp);
+
+ tmp = regVM_L2_CNTL3_DEFAULT;
+ if (adev->gmc.translate_further) {
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3, BANK_SELECT, 12);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3,
+ L2_CACHE_BIGK_FRAGMENT_SIZE, 9);
+ } else {
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3, BANK_SELECT, 9);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3,
+ L2_CACHE_BIGK_FRAGMENT_SIZE, 6);
+ }
+ WREG32_SOC15(MMHUB, i, regVM_L2_CNTL3, tmp);
+
+ tmp = regVM_L2_CNTL4_DEFAULT;
+ /* For AMD APP APUs setup WC memory */
+ if (adev->gmc.xgmi.connected_to_cpu || adev->gmc.is_app_apu) {
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4,
+ VMC_TAP_PDE_REQUEST_PHYSICAL, 1);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4,
+ VMC_TAP_PTE_REQUEST_PHYSICAL, 1);
+ } else {
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4,
+ VMC_TAP_PDE_REQUEST_PHYSICAL, 0);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL4,
+ VMC_TAP_PTE_REQUEST_PHYSICAL, 0);
+ }
+ WREG32_SOC15(MMHUB, i, regVM_L2_CNTL4, tmp);
}
- WREG32_SOC15(MMHUB, 0, regVM_L2_CNTL4, tmp);
}
static void mmhub_v1_8_enable_system_domain(struct amdgpu_device *adev)
{
- uint32_t tmp;
-
- tmp = RREG32_SOC15(MMHUB, 0, regVM_CONTEXT0_CNTL);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH,
- adev->gmc.vmid0_page_table_depth);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, PAGE_TABLE_BLOCK_SIZE,
- adev->gmc.vmid0_page_table_block_size);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL,
- RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
- WREG32_SOC15(MMHUB, 0, regVM_CONTEXT0_CNTL, tmp);
+ uint32_t tmp, inst_mask;
+ int i;
+
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask) {
+ tmp = RREG32_SOC15(MMHUB, i, regVM_CONTEXT0_CNTL);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH,
+ adev->gmc.vmid0_page_table_depth);
+ tmp = REG_SET_FIELD(tmp,
+ VM_CONTEXT0_CNTL, PAGE_TABLE_BLOCK_SIZE,
+ adev->gmc.vmid0_page_table_block_size);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL,
+ RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
+ WREG32_SOC15(MMHUB, i, regVM_CONTEXT0_CNTL, tmp);
+ }
}
static void mmhub_v1_8_disable_identity_aperture(struct amdgpu_device *adev)
{
+ u32 inst_mask;
+ int i;
+
if (amdgpu_sriov_vf(adev))
return;
- WREG32_SOC15(MMHUB, 0, regVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32, 0xFFFFFFFF);
- WREG32_SOC15(MMHUB, 0, regVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32, 0x0000000F);
-
- WREG32_SOC15(MMHUB, 0, regVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_LO32, 0);
- WREG32_SOC15(MMHUB, 0, regVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_HI32, 0);
-
- WREG32_SOC15(MMHUB, 0, regVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_LO32, 0);
- WREG32_SOC15(MMHUB, 0, regVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_HI32, 0);
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask) {
+ WREG32_SOC15(MMHUB, i,
+ regVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32,
+ 0XFFFFFFFF);
+ WREG32_SOC15(MMHUB, i,
+ regVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32,
+ 0x0000000F);
+
+ WREG32_SOC15(MMHUB, i,
+ regVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_LO32,
+ 0);
+ WREG32_SOC15(MMHUB, i,
+ regVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_HI32,
+ 0);
+
+ WREG32_SOC15(MMHUB, i,
+ regVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_LO32, 0);
+ WREG32_SOC15(MMHUB, i,
+ regVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_HI32, 0);
+ }
}
static void mmhub_v1_8_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
- unsigned num_level, block_size;
- uint32_t tmp;
- int i;
+ struct amdgpu_vmhub *hub;
+ unsigned int num_level, block_size;
+ uint32_t tmp, inst_mask;
+ int i, j;
num_level = adev->vm_manager.num_level;
block_size = adev->vm_manager.block_size;
@@ -265,60 +339,75 @@ static void mmhub_v1_8_setup_vmid_config(struct amdgpu_device *adev)
else
block_size -= 9;
- for (i = 0; i <= 14; i++) {
- tmp = RREG32_SOC15_OFFSET(MMHUB, 0, regVM_CONTEXT1_CNTL, i);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
- num_level);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT,
- 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- PAGE_TABLE_BLOCK_SIZE,
- block_size);
- /* On Aldebaran, XNACK can be enabled in the SQ per-process.
- * Retry faults need to be enabled for that to work.
- */
- tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
- RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
- 1);
- WREG32_SOC15_OFFSET(MMHUB, 0, regVM_CONTEXT1_CNTL,
- i * hub->ctx_distance, tmp);
- WREG32_SOC15_OFFSET(MMHUB, 0, regVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
- i * hub->ctx_addr_distance, 0);
- WREG32_SOC15_OFFSET(MMHUB, 0, regVM_CONTEXT1_PAGE_TABLE_START_ADDR_HI32,
- i * hub->ctx_addr_distance, 0);
- WREG32_SOC15_OFFSET(MMHUB, 0, regVM_CONTEXT1_PAGE_TABLE_END_ADDR_LO32,
- i * hub->ctx_addr_distance,
- lower_32_bits(adev->vm_manager.max_pfn - 1));
- WREG32_SOC15_OFFSET(MMHUB, 0, regVM_CONTEXT1_PAGE_TABLE_END_ADDR_HI32,
- i * hub->ctx_addr_distance,
- upper_32_bits(adev->vm_manager.max_pfn - 1));
+ inst_mask = adev->aid_mask;
+ for_each_inst(j, inst_mask) {
+ hub = &adev->vmhub[AMDGPU_MMHUB0(j)];
+ for (i = 0; i <= 14; i++) {
+ tmp = RREG32_SOC15_OFFSET(MMHUB, j, regVM_CONTEXT1_CNTL,
+ i);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ ENABLE_CONTEXT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ PAGE_TABLE_DEPTH, num_level);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ PAGE_TABLE_BLOCK_SIZE,
+ block_size);
+ /* On 9.4.3, XNACK can be enabled in the SQ
+ * per-process. Retry faults need to be enabled for
+ * that to work.
+ */
+ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+ RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 1);
+ WREG32_SOC15_OFFSET(MMHUB, j, regVM_CONTEXT1_CNTL,
+ i * hub->ctx_distance, tmp);
+ WREG32_SOC15_OFFSET(MMHUB, j,
+ regVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
+ i * hub->ctx_addr_distance, 0);
+ WREG32_SOC15_OFFSET(MMHUB, j,
+ regVM_CONTEXT1_PAGE_TABLE_START_ADDR_HI32,
+ i * hub->ctx_addr_distance, 0);
+ WREG32_SOC15_OFFSET(MMHUB, j,
+ regVM_CONTEXT1_PAGE_TABLE_END_ADDR_LO32,
+ i * hub->ctx_addr_distance,
+ lower_32_bits(adev->vm_manager.max_pfn - 1));
+ WREG32_SOC15_OFFSET(MMHUB, j,
+ regVM_CONTEXT1_PAGE_TABLE_END_ADDR_HI32,
+ i * hub->ctx_addr_distance,
+ upper_32_bits(adev->vm_manager.max_pfn - 1));
+ }
}
}
static void mmhub_v1_8_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
- unsigned i;
-
- for (i = 0; i < 18; ++i) {
- WREG32_SOC15_OFFSET(MMHUB, 0, regVM_INVALIDATE_ENG0_ADDR_RANGE_LO32,
- i * hub->eng_addr_distance, 0xffffffff);
- WREG32_SOC15_OFFSET(MMHUB, 0, regVM_INVALIDATE_ENG0_ADDR_RANGE_HI32,
- i * hub->eng_addr_distance, 0x1f);
+ struct amdgpu_vmhub *hub;
+ u32 i, j, inst_mask;
+
+ inst_mask = adev->aid_mask;
+ for_each_inst(j, inst_mask) {
+ hub = &adev->vmhub[AMDGPU_MMHUB0(j)];
+ for (i = 0; i < 18; ++i) {
+ WREG32_SOC15_OFFSET(MMHUB, j,
+ regVM_INVALIDATE_ENG0_ADDR_RANGE_LO32,
+ i * hub->eng_addr_distance, 0xffffffff);
+ WREG32_SOC15_OFFSET(MMHUB, j,
+ regVM_INVALIDATE_ENG0_ADDR_RANGE_HI32,
+ i * hub->eng_addr_distance, 0x1f);
+ }
}
}
@@ -352,28 +441,34 @@ static int mmhub_v1_8_gart_enable(struct amdgpu_device *adev)
static void mmhub_v1_8_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub;
u32 tmp;
- u32 i;
+ u32 i, j, inst_mask;
/* Disable all tables */
- for (i = 0; i < 16; i++)
- WREG32_SOC15_OFFSET(MMHUB, 0, regVM_CONTEXT0_CNTL,
- i * hub->ctx_distance, 0);
-
- /* Setup TLB control */
- tmp = RREG32_SOC15(MMHUB, 0, regMC_VM_MX_L1_TLB_CNTL);
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 0);
- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
- ENABLE_ADVANCED_DRIVER_MODEL, 0);
- WREG32_SOC15(MMHUB, 0, regMC_VM_MX_L1_TLB_CNTL, tmp);
-
- if (!amdgpu_sriov_vf(adev)) {
- /* Setup L2 cache */
- tmp = RREG32_SOC15(MMHUB, 0, regVM_L2_CNTL);
- tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_CACHE, 0);
- WREG32_SOC15(MMHUB, 0, regVM_L2_CNTL, tmp);
- WREG32_SOC15(MMHUB, 0, regVM_L2_CNTL3, 0);
+ inst_mask = adev->aid_mask;
+ for_each_inst(j, inst_mask) {
+ hub = &adev->vmhub[AMDGPU_MMHUB0(j)];
+ for (i = 0; i < 16; i++)
+ WREG32_SOC15_OFFSET(MMHUB, j, regVM_CONTEXT0_CNTL,
+ i * hub->ctx_distance, 0);
+
+ /* Setup TLB control */
+ tmp = RREG32_SOC15(MMHUB, j, regMC_VM_MX_L1_TLB_CNTL);
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB,
+ 0);
+ tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL,
+ ENABLE_ADVANCED_DRIVER_MODEL, 0);
+ WREG32_SOC15(MMHUB, j, regMC_VM_MX_L1_TLB_CNTL, tmp);
+
+ if (!amdgpu_sriov_vf(adev)) {
+ /* Setup L2 cache */
+ tmp = RREG32_SOC15(MMHUB, j, regVM_L2_CNTL);
+ tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_CACHE,
+ 0);
+ WREG32_SOC15(MMHUB, j, regVM_L2_CNTL, tmp);
+ WREG32_SOC15(MMHUB, j, regVM_L2_CNTL3, 0);
+ }
}
}
@@ -385,73 +480,83 @@ static void mmhub_v1_8_gart_disable(struct amdgpu_device *adev)
*/
static void mmhub_v1_8_set_fault_enable_default(struct amdgpu_device *adev, bool value)
{
- u32 tmp;
+ u32 tmp, inst_mask;
+ int i;
if (amdgpu_sriov_vf(adev))
return;
- tmp = RREG32_SOC15(MMHUB, 0, regVM_L2_PROTECTION_FAULT_CNTL);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- PDE1_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- PDE2_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- TRANSLATE_FURTHER_PROTECTION_FAULT_ENABLE_DEFAULT,
- value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- NACK_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
- if (!value) {
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask) {
+ tmp = RREG32_SOC15(MMHUB, i, regVM_L2_PROTECTION_FAULT_CNTL);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ PDE1_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ PDE2_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ TRANSLATE_FURTHER_PROTECTION_FAULT_ENABLE_DEFAULT,
+ value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ NACK_PROTECTION_FAULT_ENABLE_DEFAULT, value);
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- CRASH_ON_NO_RETRY_FAULT, 1);
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
- CRASH_ON_RETRY_FAULT, 1);
+ VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+ if (!value) {
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ CRASH_ON_NO_RETRY_FAULT, 1);
+ tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
+ CRASH_ON_RETRY_FAULT, 1);
+ }
+
+ WREG32_SOC15(MMHUB, i, regVM_L2_PROTECTION_FAULT_CNTL, tmp);
}
-
- WREG32_SOC15(MMHUB, 0, regVM_L2_PROTECTION_FAULT_CNTL, tmp);
}
static void mmhub_v1_8_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
-
- hub->ctx0_ptb_addr_lo32 =
- SOC15_REG_OFFSET(MMHUB, 0,
- regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32);
- hub->ctx0_ptb_addr_hi32 =
- SOC15_REG_OFFSET(MMHUB, 0,
- regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
- hub->vm_inv_eng0_req =
- SOC15_REG_OFFSET(MMHUB, 0, regVM_INVALIDATE_ENG0_REQ);
- hub->vm_inv_eng0_ack =
- SOC15_REG_OFFSET(MMHUB, 0, regVM_INVALIDATE_ENG0_ACK);
- hub->vm_context0_cntl =
- SOC15_REG_OFFSET(MMHUB, 0, regVM_CONTEXT0_CNTL);
- hub->vm_l2_pro_fault_status =
- SOC15_REG_OFFSET(MMHUB, 0, regVM_L2_PROTECTION_FAULT_STATUS);
- hub->vm_l2_pro_fault_cntl =
- SOC15_REG_OFFSET(MMHUB, 0, regVM_L2_PROTECTION_FAULT_CNTL);
-
- hub->ctx_distance = regVM_CONTEXT1_CNTL - regVM_CONTEXT0_CNTL;
- hub->ctx_addr_distance = regVM_CONTEXT1_PAGE_TABLE_BASE_ADDR_LO32 -
- regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32;
- hub->eng_distance = regVM_INVALIDATE_ENG1_REQ - regVM_INVALIDATE_ENG0_REQ;
- hub->eng_addr_distance = regVM_INVALIDATE_ENG1_ADDR_RANGE_LO32 -
- regVM_INVALIDATE_ENG0_ADDR_RANGE_LO32;
+ struct amdgpu_vmhub *hub;
+ u32 inst_mask;
+ int i;
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask) {
+ hub = &adev->vmhub[AMDGPU_MMHUB0(i)];
+
+ hub->ctx0_ptb_addr_lo32 = SOC15_REG_OFFSET(MMHUB, i,
+ regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32);
+ hub->ctx0_ptb_addr_hi32 = SOC15_REG_OFFSET(MMHUB, i,
+ regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
+ hub->vm_inv_eng0_req =
+ SOC15_REG_OFFSET(MMHUB, i, regVM_INVALIDATE_ENG0_REQ);
+ hub->vm_inv_eng0_ack =
+ SOC15_REG_OFFSET(MMHUB, i, regVM_INVALIDATE_ENG0_ACK);
+ hub->vm_context0_cntl =
+ SOC15_REG_OFFSET(MMHUB, i, regVM_CONTEXT0_CNTL);
+ hub->vm_l2_pro_fault_status = SOC15_REG_OFFSET(MMHUB, i,
+ regVM_L2_PROTECTION_FAULT_STATUS);
+ hub->vm_l2_pro_fault_cntl = SOC15_REG_OFFSET(MMHUB, i,
+ regVM_L2_PROTECTION_FAULT_CNTL);
+
+ hub->ctx_distance = regVM_CONTEXT1_CNTL - regVM_CONTEXT0_CNTL;
+ hub->ctx_addr_distance =
+ regVM_CONTEXT1_PAGE_TABLE_BASE_ADDR_LO32 -
+ regVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32;
+ hub->eng_distance = regVM_INVALIDATE_ENG1_REQ -
+ regVM_INVALIDATE_ENG0_REQ;
+ hub->eng_addr_distance = regVM_INVALIDATE_ENG1_ADDR_RANGE_LO32 -
+ regVM_INVALIDATE_ENG0_ADDR_RANGE_LO32;
+ }
}
static int mmhub_v1_8_set_clockgating(struct amdgpu_device *adev,
@@ -475,3 +580,277 @@ const struct amdgpu_mmhub_funcs mmhub_v1_8_funcs = {
.set_clockgating = mmhub_v1_8_set_clockgating,
.get_clockgating = mmhub_v1_8_get_clockgating,
};
+
+static const struct amdgpu_ras_err_status_reg_entry mmhub_v1_8_ce_reg_list[] = {
+ {AMDGPU_RAS_REG_ENTRY(MMHUB, 0, regMMEA0_CE_ERR_STATUS_LO, regMMEA0_CE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "MMEA0"},
+ {AMDGPU_RAS_REG_ENTRY(MMHUB, 0, regMMEA1_CE_ERR_STATUS_LO, regMMEA1_CE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "MMEA1"},
+ {AMDGPU_RAS_REG_ENTRY(MMHUB, 0, regMMEA2_CE_ERR_STATUS_LO, regMMEA2_CE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "MMEA2"},
+ {AMDGPU_RAS_REG_ENTRY(MMHUB, 0, regMMEA3_CE_ERR_STATUS_LO, regMMEA3_CE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "MMEA3"},
+ {AMDGPU_RAS_REG_ENTRY(MMHUB, 0, regMMEA4_CE_ERR_STATUS_LO, regMMEA4_CE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "MMEA4"},
+ {AMDGPU_RAS_REG_ENTRY(MMHUB, 0, regMM_CANE_CE_ERR_STATUS_LO, regMM_CANE_CE_ERR_STATUS_HI),
+ 1, 0, "MM_CANE"},
+};
+
+static const struct amdgpu_ras_err_status_reg_entry mmhub_v1_8_ue_reg_list[] = {
+ {AMDGPU_RAS_REG_ENTRY(MMHUB, 0, regMMEA0_UE_ERR_STATUS_LO, regMMEA0_UE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "MMEA0"},
+ {AMDGPU_RAS_REG_ENTRY(MMHUB, 0, regMMEA1_UE_ERR_STATUS_LO, regMMEA1_UE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "MMEA1"},
+ {AMDGPU_RAS_REG_ENTRY(MMHUB, 0, regMMEA2_UE_ERR_STATUS_LO, regMMEA2_UE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "MMEA2"},
+ {AMDGPU_RAS_REG_ENTRY(MMHUB, 0, regMMEA3_UE_ERR_STATUS_LO, regMMEA3_UE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "MMEA3"},
+ {AMDGPU_RAS_REG_ENTRY(MMHUB, 0, regMMEA4_UE_ERR_STATUS_LO, regMMEA4_UE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "MMEA4"},
+ {AMDGPU_RAS_REG_ENTRY(MMHUB, 0, regMM_CANE_UE_ERR_STATUS_LO, regMM_CANE_UE_ERR_STATUS_HI),
+ 1, 0, "MM_CANE"},
+};
+
+static const struct amdgpu_ras_memory_id_entry mmhub_v1_8_ras_memory_list[] = {
+ {AMDGPU_MMHUB_WGMI_PAGEMEM, "MMEA_WGMI_PAGEMEM"},
+ {AMDGPU_MMHUB_RGMI_PAGEMEM, "MMEA_RGMI_PAGEMEM"},
+ {AMDGPU_MMHUB_WDRAM_PAGEMEM, "MMEA_WDRAM_PAGEMEM"},
+ {AMDGPU_MMHUB_RDRAM_PAGEMEM, "MMEA_RDRAM_PAGEMEM"},
+ {AMDGPU_MMHUB_WIO_CMDMEM, "MMEA_WIO_CMDMEM"},
+ {AMDGPU_MMHUB_RIO_CMDMEM, "MMEA_RIO_CMDMEM"},
+ {AMDGPU_MMHUB_WGMI_CMDMEM, "MMEA_WGMI_CMDMEM"},
+ {AMDGPU_MMHUB_RGMI_CMDMEM, "MMEA_RGMI_CMDMEM"},
+ {AMDGPU_MMHUB_WDRAM_CMDMEM, "MMEA_WDRAM_CMDMEM"},
+ {AMDGPU_MMHUB_RDRAM_CMDMEM, "MMEA_RDRAM_CMDMEM"},
+ {AMDGPU_MMHUB_MAM_DMEM0, "MMEA_MAM_DMEM0"},
+ {AMDGPU_MMHUB_MAM_DMEM1, "MMEA_MAM_DMEM1"},
+ {AMDGPU_MMHUB_MAM_DMEM2, "MMEA_MAM_DMEM2"},
+ {AMDGPU_MMHUB_MAM_DMEM3, "MMEA_MAM_DMEM3"},
+ {AMDGPU_MMHUB_WRET_TAGMEM, "MMEA_WRET_TAGMEM"},
+ {AMDGPU_MMHUB_RRET_TAGMEM, "MMEA_RRET_TAGMEM"},
+ {AMDGPU_MMHUB_WIO_DATAMEM, "MMEA_WIO_DATAMEM"},
+ {AMDGPU_MMHUB_WGMI_DATAMEM, "MMEA_WGMI_DATAMEM"},
+ {AMDGPU_MMHUB_WDRAM_DATAMEM, "MMEA_WDRAM_DATAMEM"},
+};
+
+static void mmhub_v1_8_inst_query_ras_error_count(struct amdgpu_device *adev,
+ uint32_t mmhub_inst,
+ void *ras_err_status)
+{
+ struct ras_err_data *err_data = (struct ras_err_data *)ras_err_status;
+
+ amdgpu_ras_inst_query_ras_error_count(adev,
+ mmhub_v1_8_ce_reg_list,
+ ARRAY_SIZE(mmhub_v1_8_ce_reg_list),
+ mmhub_v1_8_ras_memory_list,
+ ARRAY_SIZE(mmhub_v1_8_ras_memory_list),
+ mmhub_inst,
+ AMDGPU_RAS_ERROR__SINGLE_CORRECTABLE,
+ &err_data->ce_count);
+ amdgpu_ras_inst_query_ras_error_count(adev,
+ mmhub_v1_8_ue_reg_list,
+ ARRAY_SIZE(mmhub_v1_8_ue_reg_list),
+ mmhub_v1_8_ras_memory_list,
+ ARRAY_SIZE(mmhub_v1_8_ras_memory_list),
+ mmhub_inst,
+ AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
+ &err_data->ue_count);
+}
+
+static void mmhub_v1_8_query_ras_error_count(struct amdgpu_device *adev,
+ void *ras_err_status)
+{
+ uint32_t inst_mask;
+ uint32_t i;
+
+ if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__MMHUB)) {
+ dev_warn(adev->dev, "MMHUB RAS is not supported\n");
+ return;
+ }
+
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask)
+ mmhub_v1_8_inst_query_ras_error_count(adev, i, ras_err_status);
+}
+
+static void mmhub_v1_8_inst_reset_ras_error_count(struct amdgpu_device *adev,
+ uint32_t mmhub_inst)
+{
+ amdgpu_ras_inst_reset_ras_error_count(adev,
+ mmhub_v1_8_ce_reg_list,
+ ARRAY_SIZE(mmhub_v1_8_ce_reg_list),
+ mmhub_inst);
+ amdgpu_ras_inst_reset_ras_error_count(adev,
+ mmhub_v1_8_ue_reg_list,
+ ARRAY_SIZE(mmhub_v1_8_ue_reg_list),
+ mmhub_inst);
+}
+
+static void mmhub_v1_8_reset_ras_error_count(struct amdgpu_device *adev)
+{
+ uint32_t inst_mask;
+ uint32_t i;
+
+ if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__MMHUB)) {
+ dev_warn(adev->dev, "MMHUB RAS is not supported\n");
+ return;
+ }
+
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask)
+ mmhub_v1_8_inst_reset_ras_error_count(adev, i);
+}
+
+static const u32 mmhub_v1_8_mmea_err_status_reg[] __maybe_unused = {
+ regMMEA0_ERR_STATUS,
+ regMMEA1_ERR_STATUS,
+ regMMEA2_ERR_STATUS,
+ regMMEA3_ERR_STATUS,
+ regMMEA4_ERR_STATUS,
+};
+
+static void mmhub_v1_8_inst_query_ras_err_status(struct amdgpu_device *adev,
+ uint32_t mmhub_inst)
+{
+ uint32_t reg_value;
+ uint32_t mmea_err_status_addr_dist;
+ uint32_t i;
+
+ /* query mmea ras err status */
+ mmea_err_status_addr_dist = regMMEA1_ERR_STATUS - regMMEA0_ERR_STATUS;
+ for (i = 0; i < ARRAY_SIZE(mmhub_v1_8_mmea_err_status_reg); i++) {
+ reg_value = RREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
+ regMMEA0_ERR_STATUS,
+ i * mmea_err_status_addr_dist);
+ if (REG_GET_FIELD(reg_value, MMEA0_ERR_STATUS, SDP_RDRSP_STATUS) ||
+ REG_GET_FIELD(reg_value, MMEA0_ERR_STATUS, SDP_WRRSP_STATUS) ||
+ REG_GET_FIELD(reg_value, MMEA0_ERR_STATUS, SDP_RDRSP_DATAPARITY_ERROR)) {
+ dev_warn(adev->dev,
+ "Detected MMEA%d err in MMHUB%d, status: 0x%x\n",
+ i, mmhub_inst, reg_value);
+ }
+ }
+
+ /* query mm_cane ras err status */
+ reg_value = RREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ERR_STATUS);
+ if (REG_GET_FIELD(reg_value, MM_CANE_ERR_STATUS, SDPM_RDRSP_STATUS) ||
+ REG_GET_FIELD(reg_value, MM_CANE_ERR_STATUS, SDPM_WRRSP_STATUS) ||
+ REG_GET_FIELD(reg_value, MM_CANE_ERR_STATUS, SDPM_RDRSP_DATAPARITY_ERROR)) {
+ dev_warn(adev->dev,
+ "Detected MM CANE err in MMHUB%d, status: 0x%x\n",
+ mmhub_inst, reg_value);
+ }
+}
+
+static void mmhub_v1_8_query_ras_error_status(struct amdgpu_device *adev)
+{
+ uint32_t inst_mask;
+ uint32_t i;
+
+ if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__MMHUB)) {
+ dev_warn(adev->dev, "MMHUB RAS is not supported\n");
+ return;
+ }
+
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask)
+ mmhub_v1_8_inst_query_ras_err_status(adev, i);
+}
+
+static void mmhub_v1_8_inst_reset_ras_err_status(struct amdgpu_device *adev,
+ uint32_t mmhub_inst)
+{
+ uint32_t mmea_cgtt_clk_cntl_addr_dist;
+ uint32_t mmea_err_status_addr_dist;
+ uint32_t reg_value;
+ uint32_t i;
+
+ /* reset mmea ras err status */
+ mmea_cgtt_clk_cntl_addr_dist = regMMEA1_CGTT_CLK_CTRL - regMMEA0_CGTT_CLK_CTRL;
+ mmea_err_status_addr_dist = regMMEA1_ERR_STATUS - regMMEA0_ERR_STATUS;
+ for (i = 0; i < ARRAY_SIZE(mmhub_v1_8_mmea_err_status_reg); i++) {
+ /* force clk branch on for response path
+ * set MMEA0_CGTT_CLK_CTRL.SOFT_OVERRIDE_RETURN = 1
+ */
+ reg_value = RREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
+ regMMEA0_CGTT_CLK_CTRL,
+ i * mmea_cgtt_clk_cntl_addr_dist);
+ reg_value = REG_SET_FIELD(reg_value, MMEA0_CGTT_CLK_CTRL,
+ SOFT_OVERRIDE_RETURN, 1);
+ WREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
+ regMMEA0_CGTT_CLK_CTRL,
+ i * mmea_cgtt_clk_cntl_addr_dist,
+ reg_value);
+
+ /* set MMEA0_ERR_STATUS.CLEAR_ERROR_STATUS = 1 */
+ reg_value = RREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
+ regMMEA0_ERR_STATUS,
+ i * mmea_err_status_addr_dist);
+ reg_value = REG_SET_FIELD(reg_value, MMEA0_ERR_STATUS,
+ CLEAR_ERROR_STATUS, 1);
+ WREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
+ regMMEA0_ERR_STATUS,
+ i * mmea_err_status_addr_dist,
+ reg_value);
+
+ /* set MMEA0_CGTT_CLK_CTRL.SOFT_OVERRIDE_RETURN = 0 */
+ reg_value = RREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
+ regMMEA0_CGTT_CLK_CTRL,
+ i * mmea_cgtt_clk_cntl_addr_dist);
+ reg_value = REG_SET_FIELD(reg_value, MMEA0_CGTT_CLK_CTRL,
+ SOFT_OVERRIDE_RETURN, 0);
+ WREG32_SOC15_OFFSET(MMHUB, mmhub_inst,
+ regMMEA0_CGTT_CLK_CTRL,
+ i * mmea_cgtt_clk_cntl_addr_dist,
+ reg_value);
+ }
+
+ /* reset mm_cane ras err status
+ * force clk branch on for response path
+ * set MM_CANE_ICG_CTRL.SOFT_OVERRIDE_ATRET = 1
+ */
+ reg_value = RREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ICG_CTRL);
+ reg_value = REG_SET_FIELD(reg_value, MM_CANE_ICG_CTRL,
+ SOFT_OVERRIDE_ATRET, 1);
+ WREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ICG_CTRL, reg_value);
+
+ /* set MM_CANE_ERR_STATUS.CLEAR_ERROR_STATUS = 1 */
+ reg_value = RREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ERR_STATUS);
+ reg_value = REG_SET_FIELD(reg_value, MM_CANE_ERR_STATUS,
+ CLEAR_ERROR_STATUS, 1);
+ WREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ERR_STATUS, reg_value);
+
+ /* set MM_CANE_ICG_CTRL.SOFT_OVERRIDE_ATRET = 0 */
+ reg_value = RREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ICG_CTRL);
+ reg_value = REG_SET_FIELD(reg_value, MM_CANE_ICG_CTRL,
+ SOFT_OVERRIDE_ATRET, 0);
+ WREG32_SOC15(MMHUB, mmhub_inst, regMM_CANE_ICG_CTRL, reg_value);
+}
+
+static void mmhub_v1_8_reset_ras_error_status(struct amdgpu_device *adev)
+{
+ uint32_t inst_mask;
+ uint32_t i;
+
+ if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__MMHUB)) {
+ dev_warn(adev->dev, "MMHUB RAS is not supported\n");
+ return;
+ }
+
+ inst_mask = adev->aid_mask;
+ for_each_inst(i, inst_mask)
+ mmhub_v1_8_inst_reset_ras_err_status(adev, i);
+}
+
+static const struct amdgpu_ras_block_hw_ops mmhub_v1_8_ras_hw_ops = {
+ .query_ras_error_count = mmhub_v1_8_query_ras_error_count,
+ .reset_ras_error_count = mmhub_v1_8_reset_ras_error_count,
+ .query_ras_error_status = mmhub_v1_8_query_ras_error_status,
+ .reset_ras_error_status = mmhub_v1_8_reset_ras_error_status,
+};
+
+struct amdgpu_mmhub_ras mmhub_v1_8_ras = {
+ .ras_block = {
+ .hw_ops = &mmhub_v1_8_ras_hw_ops,
+ },
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.h b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.h
index 0bb36200e4e5..126f0075ac50 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.h
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.h
@@ -24,5 +24,6 @@
#define __MMHUB_V1_8_H__
extern const struct amdgpu_mmhub_funcs mmhub_v1_8_funcs;
+extern struct amdgpu_mmhub_ras mmhub_v1_8_ras;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
index 278e32db878d..8f76c6ecf50a 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
@@ -187,7 +187,7 @@ mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
static void mmhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
WREG32_SOC15_OFFSET_RLC(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
hub->ctx_addr_distance * vmid,
@@ -362,7 +362,7 @@ static void mmhub_v2_0_disable_identity_aperture(struct amdgpu_device *adev)
static void mmhub_v2_0_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
int i;
uint32_t tmp;
@@ -412,7 +412,7 @@ static void mmhub_v2_0_setup_vmid_config(struct amdgpu_device *adev)
static void mmhub_v2_0_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
unsigned i;
for (i = 0; i < 18; ++i) {
@@ -441,7 +441,7 @@ static int mmhub_v2_0_gart_enable(struct amdgpu_device *adev)
static void mmhub_v2_0_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
u32 tmp;
u32 i;
@@ -520,7 +520,7 @@ static const struct amdgpu_vmhub_funcs mmhub_v2_0_vmhub_funcs = {
static void mmhub_v2_0_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
hub->ctx0_ptb_addr_lo32 =
SOC15_REG_OFFSET(MMHUB, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
index fcf2813e70db..8bd0fc8d9d25 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
@@ -121,7 +121,7 @@ static void mmhub_v2_3_setup_vm_pt_regs(struct amdgpu_device *adev,
uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
hub->ctx_addr_distance * vmid, lower_32_bits(page_table_base));
@@ -280,7 +280,7 @@ static void mmhub_v2_3_disable_identity_aperture(struct amdgpu_device *adev)
static void mmhub_v2_3_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
int i;
uint32_t tmp;
@@ -330,7 +330,7 @@ static void mmhub_v2_3_setup_vmid_config(struct amdgpu_device *adev)
static void mmhub_v2_3_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
unsigned i;
for (i = 0; i < 18; ++i) {
@@ -373,7 +373,7 @@ static int mmhub_v2_3_gart_enable(struct amdgpu_device *adev)
static void mmhub_v2_3_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
u32 tmp;
u32 i;
@@ -446,7 +446,7 @@ static const struct amdgpu_vmhub_funcs mmhub_v2_3_vmhub_funcs = {
static void mmhub_v2_3_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
hub->ctx0_ptb_addr_lo32 =
SOC15_REG_OFFSET(MMHUB, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c
index 17a792616979..441379e91cfa 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c
@@ -136,7 +136,7 @@ mmhub_v3_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
static void mmhub_v3_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
hub->ctx_addr_distance * vmid,
@@ -319,7 +319,7 @@ static void mmhub_v3_0_disable_identity_aperture(struct amdgpu_device *adev)
static void mmhub_v3_0_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
int i;
uint32_t tmp;
@@ -369,7 +369,7 @@ static void mmhub_v3_0_setup_vmid_config(struct amdgpu_device *adev)
static void mmhub_v3_0_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
unsigned i;
for (i = 0; i < 18; ++i) {
@@ -398,7 +398,7 @@ static int mmhub_v3_0_gart_enable(struct amdgpu_device *adev)
static void mmhub_v3_0_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
u32 tmp;
u32 i;
@@ -477,7 +477,7 @@ static const struct amdgpu_vmhub_funcs mmhub_v3_0_vmhub_funcs = {
static void mmhub_v3_0_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
hub->ctx0_ptb_addr_lo32 =
SOC15_REG_OFFSET(MMHUB, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c
index 26509b6b8c24..12c7f4b46ea9 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c
@@ -138,7 +138,7 @@ static void mmhub_v3_0_1_setup_vm_pt_regs(struct amdgpu_device *adev,
uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
hub->ctx_addr_distance * vmid,
@@ -306,7 +306,7 @@ static void mmhub_v3_0_1_disable_identity_aperture(struct amdgpu_device *adev)
static void mmhub_v3_0_1_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
int i;
uint32_t tmp;
@@ -356,7 +356,7 @@ static void mmhub_v3_0_1_setup_vmid_config(struct amdgpu_device *adev)
static void mmhub_v3_0_1_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
unsigned i;
for (i = 0; i < 18; ++i) {
@@ -385,7 +385,7 @@ static int mmhub_v3_0_1_gart_enable(struct amdgpu_device *adev)
static void mmhub_v3_0_1_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
u32 tmp;
u32 i;
@@ -459,7 +459,7 @@ static const struct amdgpu_vmhub_funcs mmhub_v3_0_1_vmhub_funcs = {
static void mmhub_v3_0_1_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
hub->ctx0_ptb_addr_lo32 =
SOC15_REG_OFFSET(MMHUB, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c
index 26abbc6a47ab..5dadc85abf7e 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c
@@ -129,7 +129,7 @@ mmhub_v3_0_2_print_l2_protection_fault_status(struct amdgpu_device *adev,
static void mmhub_v3_0_2_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
uint64_t page_table_base)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
hub->ctx_addr_distance * vmid,
@@ -311,7 +311,7 @@ static void mmhub_v3_0_2_disable_identity_aperture(struct amdgpu_device *adev)
static void mmhub_v3_0_2_setup_vmid_config(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
int i;
uint32_t tmp;
@@ -361,7 +361,7 @@ static void mmhub_v3_0_2_setup_vmid_config(struct amdgpu_device *adev)
static void mmhub_v3_0_2_program_invalidation(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
unsigned i;
for (i = 0; i < 18; ++i) {
@@ -390,7 +390,7 @@ static int mmhub_v3_0_2_gart_enable(struct amdgpu_device *adev)
static void mmhub_v3_0_2_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
u32 tmp;
u32 i;
@@ -469,7 +469,7 @@ static const struct amdgpu_vmhub_funcs mmhub_v3_0_2_vmhub_funcs = {
static void mmhub_v3_0_2_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
hub->ctx0_ptb_addr_lo32 =
SOC15_REG_OFFSET(MMHUB, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
index 72083e96222f..e790f890aec6 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
@@ -57,7 +57,7 @@ static u64 mmhub_v9_4_get_fb_location(struct amdgpu_device *adev)
static void mmhub_v9_4_setup_hubid_vm_pt_regs(struct amdgpu_device *adev, int hubid,
uint32_t vmid, uint64_t value)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
WREG32_SOC15_OFFSET(MMHUB, 0,
mmVML2VC0_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
@@ -294,7 +294,7 @@ static void mmhub_v9_4_disable_identity_aperture(struct amdgpu_device *adev,
static void mmhub_v9_4_setup_vmid_config(struct amdgpu_device *adev, int hubid)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
unsigned int num_level, block_size;
uint32_t tmp;
int i;
@@ -363,7 +363,7 @@ static void mmhub_v9_4_setup_vmid_config(struct amdgpu_device *adev, int hubid)
static void mmhub_v9_4_program_invalidation(struct amdgpu_device *adev,
int hubid)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
unsigned i;
for (i = 0; i < 18; ++i) {
@@ -404,7 +404,7 @@ static int mmhub_v9_4_gart_enable(struct amdgpu_device *adev)
static void mmhub_v9_4_gart_disable(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+ struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB0(0)];
u32 tmp;
u32 i, j;
@@ -507,8 +507,8 @@ static void mmhub_v9_4_set_fault_enable_default(struct amdgpu_device *adev, bool
static void mmhub_v9_4_init(struct amdgpu_device *adev)
{
- struct amdgpu_vmhub *hub[MMHUB_NUM_INSTANCES] =
- {&adev->vmhub[AMDGPU_MMHUB_0], &adev->vmhub[AMDGPU_MMHUB_1]};
+ struct amdgpu_vmhub *hub[MMHUB_NUM_INSTANCES] = {
+ &adev->vmhub[AMDGPU_MMHUB0(0)], &adev->vmhub[AMDGPU_MMHUB1(0)]};
int i;
for (i = 0; i < MMHUB_NUM_INSTANCES; i++) {
diff --git a/drivers/gpu/drm/amd/amdgpu/mmsch_v3_0.h b/drivers/gpu/drm/amd/amdgpu/mmsch_v3_0.h
index 3e4e858a6965..a773ef61b78c 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmsch_v3_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/mmsch_v3_0.h
@@ -30,6 +30,8 @@
#define MMSCH_VERSION_MINOR 0
#define MMSCH_VERSION (MMSCH_VERSION_MAJOR << 16 | MMSCH_VERSION_MINOR)
+#define MMSCH_V3_0_VCN_INSTANCES 0x2
+
enum mmsch_v3_0_command_type {
MMSCH_COMMAND__DIRECT_REG_WRITE = 0,
MMSCH_COMMAND__DIRECT_REG_POLLING = 2,
@@ -47,7 +49,7 @@ struct mmsch_v3_0_table_info {
struct mmsch_v3_0_init_header {
uint32_t version;
uint32_t total_size;
- struct mmsch_v3_0_table_info inst[AMDGPU_MAX_VCN_INSTANCES];
+ struct mmsch_v3_0_table_info inst[MMSCH_V3_0_VCN_INSTANCES];
};
struct mmsch_v3_0_cmd_direct_reg_header {
diff --git a/drivers/gpu/drm/amd/amdgpu/mmsch_v4_0.h b/drivers/gpu/drm/amd/amdgpu/mmsch_v4_0.h
index 83653a50a1a2..796d4f8791e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmsch_v4_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/mmsch_v4_0.h
@@ -43,6 +43,8 @@
#define MMSCH_VF_MAILBOX_RESP__OK 0x1
#define MMSCH_VF_MAILBOX_RESP__INCOMPLETE 0x2
+#define MMSCH_V4_0_VCN_INSTANCES 0x2
+
enum mmsch_v4_0_command_type {
MMSCH_COMMAND__DIRECT_REG_WRITE = 0,
MMSCH_COMMAND__DIRECT_REG_POLLING = 2,
@@ -60,7 +62,7 @@ struct mmsch_v4_0_table_info {
struct mmsch_v4_0_init_header {
uint32_t version;
uint32_t total_size;
- struct mmsch_v4_0_table_info inst[AMDGPU_MAX_VCN_INSTANCES];
+ struct mmsch_v4_0_table_info inst[MMSCH_V4_0_VCN_INSTANCES];
struct mmsch_v4_0_table_info jpegdec;
};
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c
index 24d12075ca3a..cd1a02d30420 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c
@@ -30,6 +30,8 @@
#include "ivsrcid/nbio/irqsrcs_nbif_7_4.h"
#include <uapi/linux/kfd_ioctl.h>
+#define NPS_MODE_MASK 0x000000FFL
+
static void nbio_v7_9_remap_hdp_registers(struct amdgpu_device *adev)
{
WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL,
@@ -66,6 +68,13 @@ static void nbio_v7_9_sdma_doorbell_range(struct amdgpu_device *adev, int instan
bool use_doorbell, int doorbell_index, int doorbell_size)
{
u32 doorbell_range = 0, doorbell_ctrl = 0;
+ int aid_id, dev_inst;
+
+ dev_inst = GET_INST(SDMA0, instance);
+ aid_id = adev->sdma.instance[instance].aid_id;
+
+ if (use_doorbell == false)
+ return;
doorbell_range =
REG_SET_FIELD(doorbell_range, DOORBELL0_CTRL_ENTRY_0,
@@ -80,9 +89,10 @@ static void nbio_v7_9_sdma_doorbell_range(struct amdgpu_device *adev, int instan
REG_SET_FIELD(doorbell_ctrl, S2A_DOORBELL_ENTRY_1_CTRL,
S2A_DOORBELL_PORT1_RANGE_SIZE, doorbell_size);
- switch (instance) {
+ switch (dev_inst % adev->sdma.num_inst_per_aid) {
case 0:
- WREG32_SOC15(NBIO, 0, regDOORBELL0_CTRL_ENTRY_1, doorbell_range);
+ WREG32_SOC15_OFFSET(NBIO, 0, regDOORBELL0_CTRL_ENTRY_1,
+ 4 * aid_id, doorbell_range);
doorbell_ctrl = REG_SET_FIELD(doorbell_ctrl,
S2A_DOORBELL_ENTRY_1_CTRL,
@@ -94,10 +104,12 @@ static void nbio_v7_9_sdma_doorbell_range(struct amdgpu_device *adev, int instan
S2A_DOORBELL_ENTRY_1_CTRL,
S2A_DOORBELL_PORT1_AWADDR_31_28_VALUE,
0x1);
- WREG32_SOC15(NBIO, 0, regS2A_DOORBELL_ENTRY_1_CTRL, doorbell_ctrl);
+ WREG32_SOC15_EXT(NBIO, aid_id, regS2A_DOORBELL_ENTRY_1_CTRL,
+ aid_id, doorbell_ctrl);
break;
case 1:
- WREG32_SOC15(NBIO, 0, regDOORBELL0_CTRL_ENTRY_2, doorbell_range);
+ WREG32_SOC15_OFFSET(NBIO, 0, regDOORBELL0_CTRL_ENTRY_2,
+ 4 * aid_id, doorbell_range);
doorbell_ctrl = REG_SET_FIELD(doorbell_ctrl,
S2A_DOORBELL_ENTRY_1_CTRL,
@@ -109,10 +121,12 @@ static void nbio_v7_9_sdma_doorbell_range(struct amdgpu_device *adev, int instan
S2A_DOORBELL_ENTRY_1_CTRL,
S2A_DOORBELL_PORT1_AWADDR_31_28_VALUE,
0x2);
- WREG32_SOC15(NBIO, 0, regS2A_DOORBELL_ENTRY_2_CTRL, doorbell_ctrl);
+ WREG32_SOC15_EXT(NBIO, aid_id, regS2A_DOORBELL_ENTRY_2_CTRL,
+ aid_id, doorbell_ctrl);
break;
case 2:
- WREG32_SOC15(NBIO, 0, regDOORBELL0_CTRL_ENTRY_3, doorbell_range);
+ WREG32_SOC15_OFFSET(NBIO, 0, regDOORBELL0_CTRL_ENTRY_3,
+ 4 * aid_id, doorbell_range);
doorbell_ctrl = REG_SET_FIELD(doorbell_ctrl,
S2A_DOORBELL_ENTRY_1_CTRL,
@@ -124,10 +138,12 @@ static void nbio_v7_9_sdma_doorbell_range(struct amdgpu_device *adev, int instan
S2A_DOORBELL_ENTRY_1_CTRL,
S2A_DOORBELL_PORT1_AWADDR_31_28_VALUE,
0x8);
- WREG32_SOC15(NBIO, 0, regS2A_DOORBELL_ENTRY_5_CTRL, doorbell_ctrl);
+ WREG32_SOC15_EXT(NBIO, aid_id, regS2A_DOORBELL_ENTRY_5_CTRL,
+ aid_id, doorbell_ctrl);
break;
case 3:
- WREG32_SOC15(NBIO, 0, regDOORBELL0_CTRL_ENTRY_4, doorbell_range);
+ WREG32_SOC15_OFFSET(NBIO, 0, regDOORBELL0_CTRL_ENTRY_4,
+ 4 * aid_id, doorbell_range);
doorbell_ctrl = REG_SET_FIELD(doorbell_ctrl,
S2A_DOORBELL_ENTRY_1_CTRL,
@@ -139,11 +155,12 @@ static void nbio_v7_9_sdma_doorbell_range(struct amdgpu_device *adev, int instan
S2A_DOORBELL_ENTRY_1_CTRL,
S2A_DOORBELL_PORT1_AWADDR_31_28_VALUE,
0x9);
- WREG32_SOC15(NBIO, 0, regS2A_DOORBELL_ENTRY_6_CTRL, doorbell_ctrl);
+ WREG32_SOC15_EXT(NBIO, aid_id, regS2A_DOORBELL_ENTRY_6_CTRL,
+ aid_id, doorbell_ctrl);
break;
default:
break;
- };
+ }
return;
}
@@ -152,6 +169,7 @@ static void nbio_v7_9_vcn_doorbell_range(struct amdgpu_device *adev, bool use_do
int doorbell_index, int instance)
{
u32 doorbell_range = 0, doorbell_ctrl = 0;
+ u32 aid_id = instance;
if (use_doorbell) {
doorbell_range = REG_SET_FIELD(doorbell_range,
@@ -161,7 +179,12 @@ static void nbio_v7_9_vcn_doorbell_range(struct amdgpu_device *adev, bool use_do
doorbell_range = REG_SET_FIELD(doorbell_range,
DOORBELL0_CTRL_ENTRY_0,
BIF_DOORBELL0_RANGE_SIZE_ENTRY,
- 0x8);
+ 0x9);
+ if (aid_id)
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ DOORBELL0_CTRL_ENTRY_0,
+ DOORBELL0_FENCE_ENABLE_ENTRY,
+ 0x4);
doorbell_ctrl = REG_SET_FIELD(doorbell_ctrl,
S2A_DOORBELL_ENTRY_1_CTRL,
@@ -174,10 +197,15 @@ static void nbio_v7_9_vcn_doorbell_range(struct amdgpu_device *adev, bool use_do
S2A_DOORBELL_PORT1_RANGE_OFFSET, 0x4);
doorbell_ctrl = REG_SET_FIELD(doorbell_ctrl,
S2A_DOORBELL_ENTRY_1_CTRL,
- S2A_DOORBELL_PORT1_RANGE_SIZE, 0x8);
+ S2A_DOORBELL_PORT1_RANGE_SIZE, 0x9);
doorbell_ctrl = REG_SET_FIELD(doorbell_ctrl,
S2A_DOORBELL_ENTRY_1_CTRL,
S2A_DOORBELL_PORT1_AWADDR_31_28_VALUE, 0x4);
+
+ WREG32_SOC15_OFFSET(NBIO, 0, regDOORBELL0_CTRL_ENTRY_17,
+ aid_id, doorbell_range);
+ WREG32_SOC15_EXT(NBIO, aid_id, regS2A_DOORBELL_ENTRY_4_CTRL,
+ aid_id, doorbell_ctrl);
} else {
doorbell_range = REG_SET_FIELD(doorbell_range,
DOORBELL0_CTRL_ENTRY_0,
@@ -185,10 +213,12 @@ static void nbio_v7_9_vcn_doorbell_range(struct amdgpu_device *adev, bool use_do
doorbell_ctrl = REG_SET_FIELD(doorbell_ctrl,
S2A_DOORBELL_ENTRY_1_CTRL,
S2A_DOORBELL_PORT1_RANGE_SIZE, 0);
- }
- WREG32_SOC15(NBIO, 0, regDOORBELL0_CTRL_ENTRY_17, doorbell_range);
- WREG32_SOC15(NBIO, 0, regS2A_DOORBELL_ENTRY_4_CTRL, doorbell_ctrl);
+ WREG32_SOC15_OFFSET(NBIO, 0, regDOORBELL0_CTRL_ENTRY_17,
+ aid_id, doorbell_range);
+ WREG32_SOC15_EXT(NBIO, aid_id, regS2A_DOORBELL_ENTRY_4_CTRL,
+ aid_id, doorbell_ctrl);
+ }
}
static void nbio_v7_9_enable_doorbell_aperture(struct amdgpu_device *adev,
@@ -235,7 +265,7 @@ static void nbio_v7_9_ih_doorbell_range(struct amdgpu_device *adev,
ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
DOORBELL0_CTRL_ENTRY_0,
BIF_DOORBELL0_RANGE_SIZE_ENTRY,
- 0x4);
+ 0x8);
ih_doorbell_ctrl = REG_SET_FIELD(ih_doorbell_ctrl,
S2A_DOORBELL_ENTRY_1_CTRL,
@@ -248,7 +278,7 @@ static void nbio_v7_9_ih_doorbell_range(struct amdgpu_device *adev,
S2A_DOORBELL_PORT1_RANGE_OFFSET, 0);
ih_doorbell_ctrl = REG_SET_FIELD(ih_doorbell_ctrl,
S2A_DOORBELL_ENTRY_1_CTRL,
- S2A_DOORBELL_PORT1_RANGE_SIZE, 0x4);
+ S2A_DOORBELL_PORT1_RANGE_SIZE, 0x8);
ih_doorbell_ctrl = REG_SET_FIELD(ih_doorbell_ctrl,
S2A_DOORBELL_ENTRY_1_CTRL,
S2A_DOORBELL_PORT1_AWADDR_31_28_VALUE, 0);
@@ -319,6 +349,11 @@ static u32 nbio_v7_9_get_pcie_data_offset(struct amdgpu_device *adev)
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX0_PCIE_DATA2);
}
+static u32 nbio_v7_9_get_pcie_index_hi_offset(struct amdgpu_device *adev)
+{
+ return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX0_PCIE_INDEX2_HI);
+}
+
const struct nbio_hdp_flush_reg nbio_v7_9_hdp_flush_reg = {
.ref_and_mask_cp0 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP0_MASK,
.ref_and_mask_cp1 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP1_MASK,
@@ -347,11 +382,57 @@ static void nbio_v7_9_enable_doorbell_interrupt(struct amdgpu_device *adev,
DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1);
}
+static int nbio_v7_9_get_compute_partition_mode(struct amdgpu_device *adev)
+{
+ u32 tmp, px;
+
+ tmp = RREG32_SOC15(NBIO, 0, regBIF_BX_PF0_PARTITION_COMPUTE_STATUS);
+ px = REG_GET_FIELD(tmp, BIF_BX_PF0_PARTITION_COMPUTE_STATUS,
+ PARTITION_MODE);
+
+ return px;
+}
+
+static u32 nbio_v7_9_get_memory_partition_mode(struct amdgpu_device *adev,
+ u32 *supp_modes)
+{
+ u32 tmp;
+
+ tmp = RREG32_SOC15(NBIO, 0, regBIF_BX_PF0_PARTITION_MEM_STATUS);
+ tmp = REG_GET_FIELD(tmp, BIF_BX_PF0_PARTITION_MEM_STATUS, NPS_MODE);
+
+ if (supp_modes) {
+ *supp_modes =
+ RREG32_SOC15(NBIO, 0, regBIF_BX_PF0_PARTITION_MEM_CAP);
+ }
+
+ return ffs(tmp);
+}
+
+static void nbio_v7_9_init_registers(struct amdgpu_device *adev)
+{
+ u32 inst_mask;
+ int i;
+
+ WREG32_SOC15(NBIO, 0, regXCC_DOORBELL_FENCE,
+ 0xff & ~(adev->gfx.xcc_mask));
+
+ WREG32_SOC15(NBIO, 0, regBIFC_GFX_INT_MONITOR_MASK, 0x7ff);
+
+ inst_mask = adev->aid_mask & ~1U;
+ for_each_inst(i, inst_mask) {
+ WREG32_SOC15_EXT(NBIO, i, regXCC_DOORBELL_FENCE, i,
+ XCC_DOORBELL_FENCE__SHUB_SLV_MODE_MASK);
+
+ }
+}
+
const struct amdgpu_nbio_funcs nbio_v7_9_funcs = {
.get_hdp_flush_req_offset = nbio_v7_9_get_hdp_flush_req_offset,
.get_hdp_flush_done_offset = nbio_v7_9_get_hdp_flush_done_offset,
.get_pcie_index_offset = nbio_v7_9_get_pcie_index_offset,
.get_pcie_data_offset = nbio_v7_9_get_pcie_data_offset,
+ .get_pcie_index_hi_offset = nbio_v7_9_get_pcie_index_hi_offset,
.get_rev_id = nbio_v7_9_get_rev_id,
.mc_access_enable = nbio_v7_9_mc_access_enable,
.get_memsize = nbio_v7_9_get_memsize,
@@ -366,4 +447,7 @@ const struct amdgpu_nbio_funcs nbio_v7_9_funcs = {
.get_clockgating_state = nbio_v7_9_get_clockgating_state,
.ih_control = nbio_v7_9_ih_control,
.remap_hdp_registers = nbio_v7_9_remap_hdp_registers,
+ .get_compute_partition_mode = nbio_v7_9_get_compute_partition_mode,
+ .get_memory_partition_mode = nbio_v7_9_get_memory_partition_mode,
+ .init_registers = nbio_v7_9_init_registers,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
index 0fb6013441f0..51523b27a186 100644
--- a/drivers/gpu/drm/amd/amdgpu/nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/nv.c
@@ -341,11 +341,6 @@ void nv_grbm_select(struct amdgpu_device *adev,
WREG32_SOC15(GC, 0, mmGRBM_GFX_CNTL, grbm_gfx_cntl);
}
-static void nv_vga_set_state(struct amdgpu_device *adev, bool state)
-{
- /* todo */
-}
-
static bool nv_read_disabled_bios(struct amdgpu_device *adev)
{
/* todo */
@@ -381,12 +376,12 @@ static uint32_t nv_read_indexed_register(struct amdgpu_device *adev, u32 se_num,
mutex_lock(&adev->grbm_idx_mutex);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff, 0);
val = RREG32(reg_offset);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
return val;
}
@@ -632,9 +627,9 @@ static int nv_update_umd_stable_pstate(struct amdgpu_device *adev,
bool enter)
{
if (enter)
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
else
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
if (adev->gfx.funcs->update_perfmon_mgcg)
adev->gfx.funcs->update_perfmon_mgcg(adev, !enter);
@@ -654,7 +649,6 @@ static const struct amdgpu_asic_funcs nv_asic_funcs =
.read_register = &nv_read_register,
.reset = &nv_asic_reset,
.reset_method = &nv_asic_reset_method,
- .set_vga_state = &nv_vga_set_state,
.get_xclk = &nv_get_xclk,
.set_uvd_clocks = &nv_set_uvd_clocks,
.set_vce_clocks = &nv_set_vce_clocks,
diff --git a/drivers/gpu/drm/amd/amdgpu/nvd.h b/drivers/gpu/drm/amd/amdgpu/nvd.h
index fd6b58243b03..631dafb92299 100644
--- a/drivers/gpu/drm/amd/amdgpu/nvd.h
+++ b/drivers/gpu/drm/amd/amdgpu/nvd.h
@@ -462,6 +462,9 @@
# define PACKET3_QUERY_STATUS_ENG_SEL(x) ((x) << 25)
#define PACKET3_RUN_LIST 0xA5
#define PACKET3_MAP_PROCESS_VM 0xA6
-
+/* GFX11 */
+#define PACKET3_SET_Q_PREEMPTION_MODE 0xF0
+# define PACKET3_SET_Q_PREEMPTION_MODE_IB_VMID(x) ((x) << 0)
+# define PACKET3_SET_Q_PREEMPTION_MODE_INIT_SHADOW_MEM (1 << 0)
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
index 22c775f39119..18917df785ec 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
+++ b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
@@ -102,6 +102,7 @@ enum psp_gfx_cmd_id
GFX_CMD_ID_LOAD_TOC = 0x00000020, /* Load TOC and obtain TMR size */
GFX_CMD_ID_AUTOLOAD_RLC = 0x00000021, /* Indicates all graphics fw loaded, start RLC autoload */
GFX_CMD_ID_BOOT_CFG = 0x00000022, /* Boot Config */
+ GFX_CMD_ID_SRIOV_SPATIAL_PART = 0x00000027, /* Configure spatial partitioning mode */
};
/* PSP boot config sub-commands */
@@ -338,6 +339,13 @@ struct psp_gfx_cmd_boot_cfg
uint32_t boot_config_valid; /* dynamic boot configuration valid bits bitmask */
};
+struct psp_gfx_cmd_sriov_spatial_part {
+ uint32_t mode;
+ uint32_t override_ips;
+ uint32_t override_xcds_avail;
+ uint32_t override_this_aid;
+};
+
/* All GFX ring buffer commands. */
union psp_gfx_commands
{
@@ -351,6 +359,7 @@ union psp_gfx_commands
struct psp_gfx_cmd_setup_tmr cmd_setup_vmr;
struct psp_gfx_cmd_load_toc cmd_load_toc;
struct psp_gfx_cmd_boot_cfg boot_cfg;
+ struct psp_gfx_cmd_sriov_spatial_part cmd_spatial_part;
};
struct psp_gfx_uresp_reserved
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
index caee76ab7110..f9cb0d2c89d1 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
@@ -624,10 +624,11 @@ static int psp_v13_0_exec_spi_cmd(struct psp_context *psp, int cmd)
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_73, 1);
if (cmd == C2PMSG_CMD_SPI_UPDATE_FLASH_IMAGE)
- return 0;
-
- ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_115),
- MBOX_READY_FLAG, MBOX_READY_MASK, false);
+ ret = psp_wait_for_spirom_update(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_115),
+ MBOX_READY_FLAG, MBOX_READY_MASK, PSP_SPIROM_UPDATE_TIMEOUT);
+ else
+ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_115),
+ MBOX_READY_FLAG, MBOX_READY_MASK, false);
if (ret) {
dev_err(adev->dev, "SPI cmd %x timed out, ret = %d", cmd, ret);
return ret;
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.h b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.h
index b2414a729ca1..de5677ce4330 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.h
@@ -25,6 +25,8 @@
#include "amdgpu_psp.h"
+#define PSP_SPIROM_UPDATE_TIMEOUT 60000 /* 60s */
+
void psp_v13_0_set_psp_funcs(struct psp_context *psp);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index fd2a7b66ac56..51afc92994a8 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -466,8 +466,6 @@ static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev)
#endif
/* enable DMA IBs */
WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
-
- ring->sched.ready = true;
}
sdma_v2_4_enable(adev, true);
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index e572389089d2..344202870aeb 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -734,8 +734,6 @@ static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev)
#endif
/* enable DMA IBs */
WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
-
- ring->sched.ready = true;
}
/* unhalt the MEs */
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
index 9295ac7edd56..cd37f45e01a1 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
@@ -1114,8 +1114,6 @@ static void sdma_v4_0_gfx_resume(struct amdgpu_device *adev, unsigned int i)
#endif
/* enable DMA IBs */
WREG32_SDMA(i, mmSDMA0_GFX_IB_CNTL, ib_cntl);
-
- ring->sched.ready = true;
}
/**
@@ -1202,8 +1200,6 @@ static void sdma_v4_0_page_resume(struct amdgpu_device *adev, unsigned int i)
#endif
/* enable DMA IBs */
WREG32_SDMA(i, mmSDMA0_PAGE_IB_CNTL, ib_cntl);
-
- ring->sched.ready = true;
}
static void
@@ -1825,12 +1821,12 @@ static int sdma_v4_0_sw_init(void *handle)
/*
* On Arcturus, SDMA instance 5~7 has a different vmhub
- * type(AMDGPU_MMHUB_1).
+ * type(AMDGPU_MMHUB1).
*/
if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 2, 2) && i >= 5)
- ring->vm_hub = AMDGPU_MMHUB_1;
+ ring->vm_hub = AMDGPU_MMHUB1(0);
else
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "sdma%d", i);
r = amdgpu_ring_init(adev, ring, 1024, &adev->sdma.trap_irq,
@@ -1847,13 +1843,23 @@ static int sdma_v4_0_sw_init(void *handle)
/* paging queue use same doorbell index/routing as gfx queue
* with 0x400 (4096 dwords) offset on second doorbell page
*/
- ring->doorbell_index = adev->doorbell_index.sdma_engine[i] << 1;
- ring->doorbell_index += 0x400;
+ if (adev->ip_versions[SDMA0_HWIP][0] >= IP_VERSION(4, 0, 0) &&
+ adev->ip_versions[SDMA0_HWIP][0] < IP_VERSION(4, 2, 0)) {
+ ring->doorbell_index =
+ adev->doorbell_index.sdma_engine[i] << 1;
+ ring->doorbell_index += 0x400;
+ } else {
+ /* From vega20, the sdma_doorbell_range in 1st
+ * doorbell page is reserved for page queue.
+ */
+ ring->doorbell_index =
+ (adev->doorbell_index.sdma_engine[i] + 1) << 1;
+ }
if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 2, 2) && i >= 5)
- ring->vm_hub = AMDGPU_MMHUB_1;
+ ring->vm_hub = AMDGPU_MMHUB1(0);
else
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "page%d", i);
r = amdgpu_ring_init(adev, ring, 1024,
@@ -2306,7 +2312,7 @@ const struct amd_ip_funcs sdma_v4_0_ip_funcs = {
static const struct amdgpu_ring_funcs sdma_v4_0_ring_funcs = {
.type = AMDGPU_RING_TYPE_SDMA,
- .align_mask = 0xf,
+ .align_mask = 0xff,
.nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
.support_64bit_ptrs = true,
.secure_submission_supported = true,
@@ -2338,7 +2344,7 @@ static const struct amdgpu_ring_funcs sdma_v4_0_ring_funcs = {
static const struct amdgpu_ring_funcs sdma_v4_0_page_ring_funcs = {
.type = AMDGPU_RING_TYPE_SDMA,
- .align_mask = 0xf,
+ .align_mask = 0xff,
.nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
.support_64bit_ptrs = true,
.secure_submission_supported = true,
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c
index 6f9895cdddb1..0ddb6955a6d3 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c
@@ -141,6 +141,10 @@ static const struct soc15_ras_field_entry sdma_v4_4_ras_fields[] = {
SOC15_REG_FIELD(SDMA0_EDC_COUNTER2, SDMA_UTCL1_RDBST_FIFO_SED),
0, 0,
},
+ { "SDMA_UTCL1_WR_FIFO_SED", SOC15_REG_ENTRY(SDMA0, 0, regSDMA0_EDC_COUNTER2),
+ SOC15_REG_FIELD(SDMA0_EDC_COUNTER2, SDMA_UTCL1_WR_FIFO_SED),
+ 0, 0,
+ },
{ "SDMA_DATA_LUT_FIFO_SED", SOC15_REG_ENTRY(SDMA0, 0, regSDMA0_EDC_COUNTER2),
SOC15_REG_FIELD(SDMA0_EDC_COUNTER2, SDMA_DATA_LUT_FIFO_SED),
0, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
index 64dcaa2670dd..ea5e12390d18 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include "amdgpu.h"
+#include "amdgpu_xcp.h"
#include "amdgpu_ucode.h"
#include "amdgpu_trace.h"
@@ -53,11 +54,14 @@ static void sdma_v4_4_2_set_ring_funcs(struct amdgpu_device *adev);
static void sdma_v4_4_2_set_buffer_funcs(struct amdgpu_device *adev);
static void sdma_v4_4_2_set_vm_pte_funcs(struct amdgpu_device *adev);
static void sdma_v4_4_2_set_irq_funcs(struct amdgpu_device *adev);
+static void sdma_v4_4_2_set_ras_funcs(struct amdgpu_device *adev);
static u32 sdma_v4_4_2_get_reg_offset(struct amdgpu_device *adev,
u32 instance, u32 offset)
{
- return (adev->reg_offset[SDMA0_HWIP][instance][0] + offset);
+ u32 dev_inst = GET_INST(SDMA0, instance);
+
+ return (adev->reg_offset[SDMA0_HWIP][dev_inst][0] + offset);
}
static unsigned sdma_v4_4_2_seq_to_irq_id(int seq_num)
@@ -92,13 +96,25 @@ static int sdma_v4_4_2_irq_id_to_seq(unsigned client_id)
}
}
-static void sdma_v4_4_2_init_golden_registers(struct amdgpu_device *adev)
+static void sdma_v4_4_2_inst_init_golden_registers(struct amdgpu_device *adev,
+ uint32_t inst_mask)
{
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
- case IP_VERSION(4, 4, 2):
- break;
- default:
- break;
+ u32 val;
+ int i;
+
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ val = RREG32_SDMA(i, regSDMA_GB_ADDR_CONFIG);
+ val = REG_SET_FIELD(val, SDMA_GB_ADDR_CONFIG, NUM_BANKS, 4);
+ val = REG_SET_FIELD(val, SDMA_GB_ADDR_CONFIG,
+ PIPE_INTERLEAVE_SIZE, 0);
+ WREG32_SDMA(i, regSDMA_GB_ADDR_CONFIG, val);
+
+ val = RREG32_SDMA(i, regSDMA_GB_ADDR_CONFIG_READ);
+ val = REG_SET_FIELD(val, SDMA_GB_ADDR_CONFIG_READ, NUM_BANKS,
+ 4);
+ val = REG_SET_FIELD(val, SDMA_GB_ADDR_CONFIG_READ,
+ PIPE_INTERLEAVE_SIZE, 0);
+ WREG32_SDMA(i, regSDMA_GB_ADDR_CONFIG_READ, val);
}
}
@@ -399,19 +415,21 @@ static void sdma_v4_4_2_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
/**
- * sdma_v4_4_2_gfx_stop - stop the gfx async dma engines
+ * sdma_v4_4_2_inst_gfx_stop - stop the gfx async dma engines
*
* @adev: amdgpu_device pointer
+ * @inst_mask: mask of dma engine instances to be disabled
*
* Stop the gfx async dma ring buffers.
*/
-static void sdma_v4_4_2_gfx_stop(struct amdgpu_device *adev)
+static void sdma_v4_4_2_inst_gfx_stop(struct amdgpu_device *adev,
+ uint32_t inst_mask)
{
struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES];
u32 rb_cntl, ib_cntl;
int i, unset = 0;
- for (i = 0; i < adev->sdma.num_instances; i++) {
+ for_each_inst(i, inst_mask) {
sdma[i] = &adev->sdma.instance[i].ring;
if ((adev->mman.buffer_funcs_ring == sdma[i]) && unset != 1) {
@@ -429,32 +447,36 @@ static void sdma_v4_4_2_gfx_stop(struct amdgpu_device *adev)
}
/**
- * sdma_v4_4_2_rlc_stop - stop the compute async dma engines
+ * sdma_v4_4_2_inst_rlc_stop - stop the compute async dma engines
*
* @adev: amdgpu_device pointer
+ * @inst_mask: mask of dma engine instances to be disabled
*
* Stop the compute async dma queues.
*/
-static void sdma_v4_4_2_rlc_stop(struct amdgpu_device *adev)
+static void sdma_v4_4_2_inst_rlc_stop(struct amdgpu_device *adev,
+ uint32_t inst_mask)
{
/* XXX todo */
}
/**
- * sdma_v4_4_2_page_stop - stop the page async dma engines
+ * sdma_v4_4_2_inst_page_stop - stop the page async dma engines
*
* @adev: amdgpu_device pointer
+ * @inst_mask: mask of dma engine instances to be disabled
*
* Stop the page async dma ring buffers.
*/
-static void sdma_v4_4_2_page_stop(struct amdgpu_device *adev)
+static void sdma_v4_4_2_inst_page_stop(struct amdgpu_device *adev,
+ uint32_t inst_mask)
{
struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES];
u32 rb_cntl, ib_cntl;
int i;
bool unset = false;
- for (i = 0; i < adev->sdma.num_instances; i++) {
+ for_each_inst(i, inst_mask) {
sdma[i] = &adev->sdma.instance[i].page;
if ((adev->mman.buffer_funcs_ring == sdma[i]) &&
@@ -475,14 +497,16 @@ static void sdma_v4_4_2_page_stop(struct amdgpu_device *adev)
}
/**
- * sdma_v4_4_2_ctx_switch_enable - stop the async dma engines context switch
+ * sdma_v4_4_2_inst_ctx_switch_enable - stop the async dma engines context switch
*
* @adev: amdgpu_device pointer
* @enable: enable/disable the DMA MEs context switch.
+ * @inst_mask: mask of dma engine instances to be enabled
*
* Halt or unhalt the async dma engines context switch.
*/
-static void sdma_v4_4_2_ctx_switch_enable(struct amdgpu_device *adev, bool enable)
+static void sdma_v4_4_2_inst_ctx_switch_enable(struct amdgpu_device *adev,
+ bool enable, uint32_t inst_mask)
{
u32 f32_cntl, phase_quantum = 0;
int i;
@@ -511,7 +535,7 @@ static void sdma_v4_4_2_ctx_switch_enable(struct amdgpu_device *adev, bool enabl
unit << SDMA_PHASE0_QUANTUM__UNIT__SHIFT;
}
- for (i = 0; i < adev->sdma.num_instances; i++) {
+ for_each_inst(i, inst_mask) {
f32_cntl = RREG32_SDMA(i, regSDMA_CNTL);
f32_cntl = REG_SET_FIELD(f32_cntl, SDMA_CNTL,
AUTO_CTXSW_ENABLE, enable ? 1 : 0);
@@ -525,30 +549,36 @@ static void sdma_v4_4_2_ctx_switch_enable(struct amdgpu_device *adev, bool enabl
/* Extend page fault timeout to avoid interrupt storm */
WREG32_SDMA(i, regSDMA_UTCL1_TIMEOUT, 0x00800080);
}
-
}
/**
- * sdma_v4_4_2_enable - stop the async dma engines
+ * sdma_v4_4_2_inst_enable - stop the async dma engines
*
* @adev: amdgpu_device pointer
* @enable: enable/disable the DMA MEs.
+ * @inst_mask: mask of dma engine instances to be enabled
*
* Halt or unhalt the async dma engines.
*/
-static void sdma_v4_4_2_enable(struct amdgpu_device *adev, bool enable)
+static void sdma_v4_4_2_inst_enable(struct amdgpu_device *adev, bool enable,
+ uint32_t inst_mask)
{
u32 f32_cntl;
int i;
if (!enable) {
- sdma_v4_4_2_gfx_stop(adev);
- sdma_v4_4_2_rlc_stop(adev);
+ sdma_v4_4_2_inst_gfx_stop(adev, inst_mask);
+ sdma_v4_4_2_inst_rlc_stop(adev, inst_mask);
if (adev->sdma.has_page_queue)
- sdma_v4_4_2_page_stop(adev);
+ sdma_v4_4_2_inst_page_stop(adev, inst_mask);
+
+ /* SDMA FW needs to respond to FREEZE requests during reset.
+ * Keep it running during reset */
+ if (!amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev))
+ return;
}
- for (i = 0; i < adev->sdma.num_instances; i++) {
+ for_each_inst(i, inst_mask) {
f32_cntl = RREG32_SDMA(i, regSDMA_F32_CNTL);
f32_cntl = REG_SET_FIELD(f32_cntl, SDMA_F32_CNTL, HALT, enable ? 0 : 1);
WREG32_SDMA(i, regSDMA_F32_CNTL, f32_cntl);
@@ -659,8 +689,6 @@ static void sdma_v4_4_2_gfx_resume(struct amdgpu_device *adev, unsigned int i)
#endif
/* enable DMA IBs */
WREG32_SDMA(i, regSDMA_GFX_IB_CNTL, ib_cntl);
-
- ring->sched.ready = true;
}
/**
@@ -750,8 +778,6 @@ static void sdma_v4_4_2_page_resume(struct amdgpu_device *adev, unsigned int i)
#endif
/* enable DMA IBs */
WREG32_SDMA(i, regSDMA_PAGE_IB_CNTL, ib_cntl);
-
- ring->sched.ready = true;
}
static void sdma_v4_4_2_init_pg(struct amdgpu_device *adev)
@@ -760,14 +786,16 @@ static void sdma_v4_4_2_init_pg(struct amdgpu_device *adev)
}
/**
- * sdma_v4_4_2_rlc_resume - setup and start the async dma engines
+ * sdma_v4_4_2_inst_rlc_resume - setup and start the async dma engines
*
* @adev: amdgpu_device pointer
+ * @inst_mask: mask of dma engine instances to be enabled
*
* Set up the compute DMA queues and enable them.
* Returns 0 for success, error for failure.
*/
-static int sdma_v4_4_2_rlc_resume(struct amdgpu_device *adev)
+static int sdma_v4_4_2_inst_rlc_resume(struct amdgpu_device *adev,
+ uint32_t inst_mask)
{
sdma_v4_4_2_init_pg(adev);
@@ -775,14 +803,16 @@ static int sdma_v4_4_2_rlc_resume(struct amdgpu_device *adev)
}
/**
- * sdma_v4_4_2_load_microcode - load the sDMA ME ucode
+ * sdma_v4_4_2_inst_load_microcode - load the sDMA ME ucode
*
* @adev: amdgpu_device pointer
+ * @inst_mask: mask of dma engine instances to be enabled
*
* Loads the sDMA0/1 ucode.
* Returns 0 for success, -EINVAL if the ucode is not available.
*/
-static int sdma_v4_4_2_load_microcode(struct amdgpu_device *adev)
+static int sdma_v4_4_2_inst_load_microcode(struct amdgpu_device *adev,
+ uint32_t inst_mask)
{
const struct sdma_firmware_header_v1_0 *hdr;
const __le32 *fw_data;
@@ -790,9 +820,9 @@ static int sdma_v4_4_2_load_microcode(struct amdgpu_device *adev)
int i, j;
/* halt the MEs */
- sdma_v4_4_2_enable(adev, false);
+ sdma_v4_4_2_inst_enable(adev, false, inst_mask);
- for (i = 0; i < adev->sdma.num_instances; i++) {
+ for_each_inst(i, inst_mask) {
if (!adev->sdma.instance[i].fw)
return -EINVAL;
@@ -818,38 +848,42 @@ static int sdma_v4_4_2_load_microcode(struct amdgpu_device *adev)
}
/**
- * sdma_v4_4_2_start - setup and start the async dma engines
+ * sdma_v4_4_2_inst_start - setup and start the async dma engines
*
* @adev: amdgpu_device pointer
+ * @inst_mask: mask of dma engine instances to be enabled
*
* Set up the DMA engines and enable them.
* Returns 0 for success, error for failure.
*/
-static int sdma_v4_4_2_start(struct amdgpu_device *adev)
+static int sdma_v4_4_2_inst_start(struct amdgpu_device *adev,
+ uint32_t inst_mask)
{
struct amdgpu_ring *ring;
+ uint32_t tmp_mask;
int i, r = 0;
if (amdgpu_sriov_vf(adev)) {
- sdma_v4_4_2_ctx_switch_enable(adev, false);
- sdma_v4_4_2_enable(adev, false);
+ sdma_v4_4_2_inst_ctx_switch_enable(adev, false, inst_mask);
+ sdma_v4_4_2_inst_enable(adev, false, inst_mask);
} else {
/* bypass sdma microcode loading on Gopher */
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP &&
- !(adev->pdev->device == 0x49) && !(adev->pdev->device == 0x50)) {
- r = sdma_v4_4_2_load_microcode(adev);
+ adev->sdma.instance[0].fw) {
+ r = sdma_v4_4_2_inst_load_microcode(adev, inst_mask);
if (r)
return r;
}
/* unhalt the MEs */
- sdma_v4_4_2_enable(adev, true);
+ sdma_v4_4_2_inst_enable(adev, true, inst_mask);
/* enable sdma ring preemption */
- sdma_v4_4_2_ctx_switch_enable(adev, true);
+ sdma_v4_4_2_inst_ctx_switch_enable(adev, true, inst_mask);
}
/* start the gfx rings and rlc compute queues */
- for (i = 0; i < adev->sdma.num_instances; i++) {
+ tmp_mask = inst_mask;
+ for_each_inst(i, tmp_mask) {
uint32_t temp;
WREG32_SDMA(i, regSDMA_SEM_WAIT_FAIL_TIMER_CNTL, 0);
@@ -860,6 +894,8 @@ static int sdma_v4_4_2_start(struct amdgpu_device *adev)
/* set utc l1 enable flag always to 1 */
temp = RREG32_SDMA(i, regSDMA_CNTL);
temp = REG_SET_FIELD(temp, SDMA_CNTL, UTC_L1_ENABLE, 1);
+ /* enable context empty interrupt during initialization */
+ temp = REG_SET_FIELD(temp, SDMA_CNTL, CTXEMPTY_INT_ENABLE, 1);
WREG32_SDMA(i, regSDMA_CNTL, temp);
if (!amdgpu_sriov_vf(adev)) {
@@ -876,15 +912,16 @@ static int sdma_v4_4_2_start(struct amdgpu_device *adev)
}
if (amdgpu_sriov_vf(adev)) {
- sdma_v4_4_2_ctx_switch_enable(adev, true);
- sdma_v4_4_2_enable(adev, true);
+ sdma_v4_4_2_inst_ctx_switch_enable(adev, true, inst_mask);
+ sdma_v4_4_2_inst_enable(adev, true, inst_mask);
} else {
- r = sdma_v4_4_2_rlc_resume(adev);
+ r = sdma_v4_4_2_inst_rlc_resume(adev, inst_mask);
if (r)
return r;
}
- for (i = 0; i < adev->sdma.num_instances; i++) {
+ tmp_mask = inst_mask;
+ for_each_inst(i, tmp_mask) {
ring = &adev->sdma.instance[i].ring;
r = amdgpu_ring_test_helper(ring);
@@ -1221,6 +1258,7 @@ static int sdma_v4_4_2_early_init(void *handle)
sdma_v4_4_2_set_buffer_funcs(adev);
sdma_v4_4_2_set_vm_pte_funcs(adev);
sdma_v4_4_2_set_irq_funcs(adev);
+ sdma_v4_4_2_set_ras_funcs(adev);
return 0;
}
@@ -1253,9 +1291,10 @@ static int sdma_v4_4_2_sw_init(void *handle)
struct amdgpu_ring *ring;
int r, i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ u32 aid_id;
/* SDMA trap event */
- for (i = 0; i < adev->sdma.num_instances; i++) {
+ for (i = 0; i < adev->sdma.num_inst_per_aid; i++) {
r = amdgpu_irq_add_id(adev, sdma_v4_4_2_seq_to_irq_id(i),
SDMA0_4_0__SRCID__SDMA_TRAP,
&adev->sdma.trap_irq);
@@ -1264,7 +1303,7 @@ static int sdma_v4_4_2_sw_init(void *handle)
}
/* SDMA SRAM ECC event */
- for (i = 0; i < adev->sdma.num_instances; i++) {
+ for (i = 0; i < adev->sdma.num_inst_per_aid; i++) {
r = amdgpu_irq_add_id(adev, sdma_v4_4_2_seq_to_irq_id(i),
SDMA0_4_0__SRCID__SDMA_SRAM_ECC,
&adev->sdma.ecc_irq);
@@ -1273,7 +1312,7 @@ static int sdma_v4_4_2_sw_init(void *handle)
}
/* SDMA VM_HOLE/DOORBELL_INV/POLL_TIMEOUT/SRBM_WRITE_PROTECTION event*/
- for (i = 0; i < adev->sdma.num_instances; i++) {
+ for (i = 0; i < adev->sdma.num_inst_per_aid; i++) {
r = amdgpu_irq_add_id(adev, sdma_v4_4_2_seq_to_irq_id(i),
SDMA0_4_0__SRCID__SDMA_VM_HOLE,
&adev->sdma.vm_hole_irq);
@@ -1303,15 +1342,17 @@ static int sdma_v4_4_2_sw_init(void *handle)
ring = &adev->sdma.instance[i].ring;
ring->ring_obj = NULL;
ring->use_doorbell = true;
+ aid_id = adev->sdma.instance[i].aid_id;
DRM_DEBUG("SDMA %d use_doorbell being set to: [%s]\n", i,
ring->use_doorbell?"true":"false");
/* doorbell size is 2 dwords, get DWORD offset */
ring->doorbell_index = adev->doorbell_index.sdma_engine[i] << 1;
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(aid_id);
- sprintf(ring->name, "sdma%d", i);
+ sprintf(ring->name, "sdma%d.%d", aid_id,
+ i % adev->sdma.num_inst_per_aid);
r = amdgpu_ring_init(adev, ring, 1024, &adev->sdma.trap_irq,
AMDGPU_SDMA_IRQ_INSTANCE0 + i,
AMDGPU_RING_PRIO_DEFAULT, NULL);
@@ -1323,14 +1364,15 @@ static int sdma_v4_4_2_sw_init(void *handle)
ring->ring_obj = NULL;
ring->use_doorbell = true;
- /* paging queue use same doorbell index/routing as gfx queue
- * with 0x400 (4096 dwords) offset on second doorbell page
+ /* doorbell index of page queue is assigned right after
+ * gfx queue on the same instance
*/
- ring->doorbell_index = adev->doorbell_index.sdma_engine[i] << 1;
- ring->doorbell_index += 0x400;
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->doorbell_index =
+ (adev->doorbell_index.sdma_engine[i] + 1) << 1;
+ ring->vm_hub = AMDGPU_MMHUB0(aid_id);
- sprintf(ring->name, "page%d", i);
+ sprintf(ring->name, "page%d.%d", aid_id,
+ i % adev->sdma.num_inst_per_aid);
r = amdgpu_ring_init(adev, ring, 1024,
&adev->sdma.trap_irq,
AMDGPU_SDMA_IRQ_INSTANCE0 + i,
@@ -1340,6 +1382,11 @@ static int sdma_v4_4_2_sw_init(void *handle)
}
}
+ if (amdgpu_sdma_ras_sw_init(adev)) {
+ dev_err(adev->dev, "fail to initialize sdma ras block\n");
+ return -EINVAL;
+ }
+
return r;
}
@@ -1366,14 +1413,13 @@ static int sdma_v4_4_2_hw_init(void *handle)
{
int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ uint32_t inst_mask;
- if (adev->flags & AMD_IS_APU)
- amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, false);
-
+ inst_mask = GENMASK(adev->sdma.num_instances - 1, 0);
if (!amdgpu_sriov_vf(adev))
- sdma_v4_4_2_init_golden_registers(adev);
+ sdma_v4_4_2_inst_init_golden_registers(adev, inst_mask);
- r = sdma_v4_4_2_start(adev);
+ r = sdma_v4_4_2_inst_start(adev, inst_mask);
return r;
}
@@ -1381,26 +1427,36 @@ static int sdma_v4_4_2_hw_init(void *handle)
static int sdma_v4_4_2_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ uint32_t inst_mask;
int i;
if (amdgpu_sriov_vf(adev))
return 0;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- amdgpu_irq_put(adev, &adev->sdma.ecc_irq,
- AMDGPU_SDMA_IRQ_INSTANCE0 + i);
+ inst_mask = GENMASK(adev->sdma.num_instances - 1, 0);
+ if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA)) {
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ amdgpu_irq_put(adev, &adev->sdma.ecc_irq,
+ AMDGPU_SDMA_IRQ_INSTANCE0 + i);
+ }
}
- sdma_v4_4_2_ctx_switch_enable(adev, false);
- sdma_v4_4_2_enable(adev, false);
+ sdma_v4_4_2_inst_ctx_switch_enable(adev, false, inst_mask);
+ sdma_v4_4_2_inst_enable(adev, false, inst_mask);
return 0;
}
+static int sdma_v4_4_2_set_clockgating_state(void *handle,
+ enum amd_clockgating_state state);
+
static int sdma_v4_4_2_suspend(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ if (amdgpu_in_reset(adev))
+ sdma_v4_4_2_set_clockgating_state(adev, AMD_CG_STATE_UNGATE);
+
return sdma_v4_4_2_hw_fini(adev);
}
@@ -1471,13 +1527,31 @@ static int sdma_v4_4_2_process_trap_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
{
- uint32_t instance;
+ uint32_t instance, i;
DRM_DEBUG("IH: SDMA trap\n");
instance = sdma_v4_4_2_irq_id_to_seq(entry->client_id);
+
+ /* Client id gives the SDMA instance in AID. To know the exact SDMA
+ * instance, interrupt entry gives the node id which corresponds to the AID instance.
+ * Match node id with the AID id associated with the SDMA instance. */
+ for (i = instance; i < adev->sdma.num_instances;
+ i += adev->sdma.num_inst_per_aid) {
+ if (adev->sdma.instance[i].aid_id ==
+ node_id_to_phys_map[entry->node_id])
+ break;
+ }
+
+ if (i >= adev->sdma.num_instances) {
+ dev_WARN_ONCE(
+ adev->dev, 1,
+ "Couldn't find the right sdma instance in trap handler");
+ return 0;
+ }
+
switch (entry->ring_id) {
case 0:
- amdgpu_fence_process(&adev->sdma.instance[instance].ring);
+ amdgpu_fence_process(&adev->sdma.instance[i].ring);
break;
default:
break;
@@ -1496,7 +1570,7 @@ static int sdma_v4_4_2_process_ras_data_cb(struct amdgpu_device *adev,
* be disabled and the driver should only look for the aggregated
* interrupt via sync flood
*/
- if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
+ if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA))
goto out;
instance = sdma_v4_4_2_irq_id_to_seq(entry->client_id);
@@ -1535,15 +1609,22 @@ static int sdma_v4_4_2_set_ecc_irq_state(struct amdgpu_device *adev,
unsigned type,
enum amdgpu_interrupt_state state)
{
- u32 sdma_edc_config;
+ u32 sdma_cntl;
- sdma_edc_config = RREG32_SDMA(type, regCC_SDMA_EDC_CONFIG);
- /*
- * FIXME: This was inherited from Aldebaran, but no this field
- * definition in the regspec of both Aldebaran and SDMA 4.4.2
- */
- sdma_edc_config |= (state == AMDGPU_IRQ_STATE_ENABLE) ? (1 << 2) : 0;
- WREG32_SDMA(type, regCC_SDMA_EDC_CONFIG, sdma_edc_config);
+ sdma_cntl = RREG32_SDMA(type, regSDMA_CNTL);
+ switch (state) {
+ case AMDGPU_IRQ_STATE_DISABLE:
+ sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL,
+ DRAM_ECC_INT_ENABLE, 0);
+ WREG32_SDMA(type, regSDMA_CNTL, sdma_cntl);
+ break;
+ /* sdma ecc interrupt is enabled by default
+ * driver doesn't need to do anything to
+ * enable the interrupt */
+ case AMDGPU_IRQ_STATE_ENABLE:
+ default:
+ break;
+ }
return 0;
}
@@ -1615,19 +1696,49 @@ static int sdma_v4_4_2_process_srbm_write_irq(struct amdgpu_device *adev,
return 0;
}
-static void sdma_v4_4_2_update_medium_grain_clock_gating(
- struct amdgpu_device *adev,
- bool enable)
+static void sdma_v4_4_2_inst_update_medium_grain_light_sleep(
+ struct amdgpu_device *adev, bool enable, uint32_t inst_mask)
{
uint32_t data, def;
int i;
- if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_MGCG)) {
- for (i = 0; i < adev->sdma.num_instances; i++) {
+ /* leave as default if it is not driver controlled */
+ if (!(adev->cg_flags & AMD_CG_SUPPORT_SDMA_LS))
+ return;
+
+ if (enable) {
+ for_each_inst(i, inst_mask) {
+ /* 1-not override: enable sdma mem light sleep */
+ def = data = RREG32_SDMA(i, regSDMA_POWER_CNTL);
+ data |= SDMA_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+ if (def != data)
+ WREG32_SDMA(i, regSDMA_POWER_CNTL, data);
+ }
+ } else {
+ for_each_inst(i, inst_mask) {
+ /* 0-override:disable sdma mem light sleep */
+ def = data = RREG32_SDMA(i, regSDMA_POWER_CNTL);
+ data &= ~SDMA_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+ if (def != data)
+ WREG32_SDMA(i, regSDMA_POWER_CNTL, data);
+ }
+ }
+}
+
+static void sdma_v4_4_2_inst_update_medium_grain_clock_gating(
+ struct amdgpu_device *adev, bool enable, uint32_t inst_mask)
+{
+ uint32_t data, def;
+ int i;
+
+ /* leave as default if it is not driver controlled */
+ if (!(adev->cg_flags & AMD_CG_SUPPORT_SDMA_MGCG))
+ return;
+
+ if (enable) {
+ for_each_inst(i, inst_mask) {
def = data = RREG32_SDMA(i, regSDMA_CLK_CTRL);
- data &= ~(SDMA_CLK_CTRL__SOFT_OVERRIDE7_MASK |
- SDMA_CLK_CTRL__SOFT_OVERRIDE6_MASK |
- SDMA_CLK_CTRL__SOFT_OVERRIDE5_MASK |
+ data &= ~(SDMA_CLK_CTRL__SOFT_OVERRIDE5_MASK |
SDMA_CLK_CTRL__SOFT_OVERRIDE4_MASK |
SDMA_CLK_CTRL__SOFT_OVERRIDE3_MASK |
SDMA_CLK_CTRL__SOFT_OVERRIDE2_MASK |
@@ -1637,11 +1748,9 @@ static void sdma_v4_4_2_update_medium_grain_clock_gating(
WREG32_SDMA(i, regSDMA_CLK_CTRL, data);
}
} else {
- for (i = 0; i < adev->sdma.num_instances; i++) {
+ for_each_inst(i, inst_mask) {
def = data = RREG32_SDMA(i, regSDMA_CLK_CTRL);
- data |= (SDMA_CLK_CTRL__SOFT_OVERRIDE7_MASK |
- SDMA_CLK_CTRL__SOFT_OVERRIDE6_MASK |
- SDMA_CLK_CTRL__SOFT_OVERRIDE5_MASK |
+ data |= (SDMA_CLK_CTRL__SOFT_OVERRIDE5_MASK |
SDMA_CLK_CTRL__SOFT_OVERRIDE4_MASK |
SDMA_CLK_CTRL__SOFT_OVERRIDE3_MASK |
SDMA_CLK_CTRL__SOFT_OVERRIDE2_MASK |
@@ -1653,45 +1762,21 @@ static void sdma_v4_4_2_update_medium_grain_clock_gating(
}
}
-
-static void sdma_v4_4_2_update_medium_grain_light_sleep(
- struct amdgpu_device *adev,
- bool enable)
-{
- uint32_t data, def;
- int i;
-
- if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_LS)) {
- for (i = 0; i < adev->sdma.num_instances; i++) {
- /* 1-not override: enable sdma mem light sleep */
- def = data = RREG32_SDMA(0, regSDMA_POWER_CNTL);
- data |= SDMA_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
- if (def != data)
- WREG32_SDMA(0, regSDMA_POWER_CNTL, data);
- }
- } else {
- for (i = 0; i < adev->sdma.num_instances; i++) {
- /* 0-override:disable sdma mem light sleep */
- def = data = RREG32_SDMA(0, regSDMA_POWER_CNTL);
- data &= ~SDMA_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
- if (def != data)
- WREG32_SDMA(0, regSDMA_POWER_CNTL, data);
- }
- }
-}
-
static int sdma_v4_4_2_set_clockgating_state(void *handle,
enum amd_clockgating_state state)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ uint32_t inst_mask;
if (amdgpu_sriov_vf(adev))
return 0;
- sdma_v4_4_2_update_medium_grain_clock_gating(adev,
- state == AMD_CG_STATE_GATE);
- sdma_v4_4_2_update_medium_grain_light_sleep(adev,
- state == AMD_CG_STATE_GATE);
+ inst_mask = GENMASK(adev->sdma.num_instances - 1, 0);
+
+ sdma_v4_4_2_inst_update_medium_grain_clock_gating(
+ adev, state == AMD_CG_STATE_GATE, inst_mask);
+ sdma_v4_4_2_inst_update_medium_grain_light_sleep(
+ adev, state == AMD_CG_STATE_GATE, inst_mask);
return 0;
}
@@ -1710,12 +1795,12 @@ static void sdma_v4_4_2_get_clockgating_state(void *handle, u64 *flags)
*flags = 0;
/* AMD_CG_SUPPORT_SDMA_MGCG */
- data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, regSDMA_CLK_CTRL));
- if (!(data & SDMA_CLK_CTRL__SOFT_OVERRIDE7_MASK))
+ data = RREG32(SOC15_REG_OFFSET(SDMA0, GET_INST(SDMA0, 0), regSDMA_CLK_CTRL));
+ if (!(data & SDMA_CLK_CTRL__SOFT_OVERRIDE5_MASK))
*flags |= AMD_CG_SUPPORT_SDMA_MGCG;
/* AMD_CG_SUPPORT_SDMA_LS */
- data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, regSDMA_POWER_CNTL));
+ data = RREG32(SOC15_REG_OFFSET(SDMA0, GET_INST(SDMA0, 0), regSDMA_POWER_CNTL));
if (data & SDMA_POWER_CNTL__MEM_POWER_OVERRIDE_MASK)
*flags |= AMD_CG_SUPPORT_SDMA_LS;
}
@@ -1740,7 +1825,7 @@ const struct amd_ip_funcs sdma_v4_4_2_ip_funcs = {
static const struct amdgpu_ring_funcs sdma_v4_4_2_ring_funcs = {
.type = AMDGPU_RING_TYPE_SDMA,
- .align_mask = 0xf,
+ .align_mask = 0xff,
.nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
.support_64bit_ptrs = true,
.get_rptr = sdma_v4_4_2_ring_get_rptr,
@@ -1771,7 +1856,7 @@ static const struct amdgpu_ring_funcs sdma_v4_4_2_ring_funcs = {
static const struct amdgpu_ring_funcs sdma_v4_4_2_page_ring_funcs = {
.type = AMDGPU_RING_TYPE_SDMA,
- .align_mask = 0xf,
+ .align_mask = 0xff,
.nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
.support_64bit_ptrs = true,
.get_rptr = sdma_v4_4_2_ring_get_rptr,
@@ -1802,7 +1887,7 @@ static const struct amdgpu_ring_funcs sdma_v4_4_2_page_ring_funcs = {
static void sdma_v4_4_2_set_ring_funcs(struct amdgpu_device *adev)
{
- int i;
+ int i, dev_inst;
for (i = 0; i < adev->sdma.num_instances; i++) {
adev->sdma.instance[i].ring.funcs = &sdma_v4_4_2_ring_funcs;
@@ -1812,6 +1897,11 @@ static void sdma_v4_4_2_set_ring_funcs(struct amdgpu_device *adev)
&sdma_v4_4_2_page_ring_funcs;
adev->sdma.instance[i].page.me = i;
}
+
+ dev_inst = GET_INST(SDMA0, i);
+ /* AID to which SDMA belongs depends on physical instance */
+ adev->sdma.instance[i].aid_id =
+ dev_inst / adev->sdma.num_inst_per_aid;
}
}
@@ -1965,3 +2055,146 @@ const struct amdgpu_ip_block_version sdma_v4_4_2_ip_block = {
.rev = 0,
.funcs = &sdma_v4_4_2_ip_funcs,
};
+
+static int sdma_v4_4_2_xcp_resume(void *handle, uint32_t inst_mask)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ if (!amdgpu_sriov_vf(adev))
+ sdma_v4_4_2_inst_init_golden_registers(adev, inst_mask);
+
+ r = sdma_v4_4_2_inst_start(adev, inst_mask);
+
+ return r;
+}
+
+static int sdma_v4_4_2_xcp_suspend(void *handle, uint32_t inst_mask)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ uint32_t tmp_mask = inst_mask;
+ int i;
+
+ if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA)) {
+ for_each_inst(i, tmp_mask) {
+ amdgpu_irq_put(adev, &adev->sdma.ecc_irq,
+ AMDGPU_SDMA_IRQ_INSTANCE0 + i);
+ }
+ }
+
+ sdma_v4_4_2_inst_ctx_switch_enable(adev, false, inst_mask);
+ sdma_v4_4_2_inst_enable(adev, false, inst_mask);
+
+ return 0;
+}
+
+struct amdgpu_xcp_ip_funcs sdma_v4_4_2_xcp_funcs = {
+ .suspend = &sdma_v4_4_2_xcp_suspend,
+ .resume = &sdma_v4_4_2_xcp_resume
+};
+
+static const struct amdgpu_ras_err_status_reg_entry sdma_v4_2_2_ue_reg_list[] = {
+ {AMDGPU_RAS_REG_ENTRY(SDMA0, 0, regSDMA_UE_ERR_STATUS_LO, regSDMA_UE_ERR_STATUS_HI),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "SDMA"},
+};
+
+static const struct amdgpu_ras_memory_id_entry sdma_v4_4_2_ras_memory_list[] = {
+ {AMDGPU_SDMA_MBANK_DATA_BUF0, "SDMA_MBANK_DATA_BUF0"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF1, "SDMA_MBANK_DATA_BUF1"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF2, "SDMA_MBANK_DATA_BUF2"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF3, "SDMA_MBANK_DATA_BUF3"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF4, "SDMA_MBANK_DATA_BUF4"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF5, "SDMA_MBANK_DATA_BUF5"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF6, "SDMA_MBANK_DATA_BUF6"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF7, "SDMA_MBANK_DATA_BUF7"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF8, "SDMA_MBANK_DATA_BUF8"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF9, "SDMA_MBANK_DATA_BUF9"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF10, "SDMA_MBANK_DATA_BUF10"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF11, "SDMA_MBANK_DATA_BUF11"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF12, "SDMA_MBANK_DATA_BUF12"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF13, "SDMA_MBANK_DATA_BUF13"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF14, "SDMA_MBANK_DATA_BUF14"},
+ {AMDGPU_SDMA_MBANK_DATA_BUF15, "SDMA_MBANK_DATA_BUF15"},
+ {AMDGPU_SDMA_UCODE_BUF, "SDMA_UCODE_BUF"},
+ {AMDGPU_SDMA_RB_CMD_BUF, "SDMA_RB_CMD_BUF"},
+ {AMDGPU_SDMA_IB_CMD_BUF, "SDMA_IB_CMD_BUF"},
+ {AMDGPU_SDMA_UTCL1_RD_FIFO, "SDMA_UTCL1_RD_FIFO"},
+ {AMDGPU_SDMA_UTCL1_RDBST_FIFO, "SDMA_UTCL1_RDBST_FIFO"},
+ {AMDGPU_SDMA_UTCL1_WR_FIFO, "SDMA_UTCL1_WR_FIFO"},
+ {AMDGPU_SDMA_DATA_LUT_FIFO, "SDMA_DATA_LUT_FIFO"},
+ {AMDGPU_SDMA_SPLIT_DAT_BUF, "SDMA_SPLIT_DAT_BUF"},
+};
+
+static void sdma_v4_4_2_inst_query_ras_error_count(struct amdgpu_device *adev,
+ uint32_t sdma_inst,
+ void *ras_err_status)
+{
+ struct ras_err_data *err_data = (struct ras_err_data *)ras_err_status;
+ uint32_t sdma_dev_inst = GET_INST(SDMA0, sdma_inst);
+
+ /* sdma v4_4_2 doesn't support query ce counts */
+ amdgpu_ras_inst_query_ras_error_count(adev,
+ sdma_v4_2_2_ue_reg_list,
+ ARRAY_SIZE(sdma_v4_2_2_ue_reg_list),
+ sdma_v4_4_2_ras_memory_list,
+ ARRAY_SIZE(sdma_v4_4_2_ras_memory_list),
+ sdma_dev_inst,
+ AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
+ &err_data->ue_count);
+}
+
+static void sdma_v4_4_2_query_ras_error_count(struct amdgpu_device *adev,
+ void *ras_err_status)
+{
+ uint32_t inst_mask;
+ int i = 0;
+
+ inst_mask = GENMASK(adev->sdma.num_instances - 1, 0);
+ if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA)) {
+ for_each_inst(i, inst_mask)
+ sdma_v4_4_2_inst_query_ras_error_count(adev, i, ras_err_status);
+ } else {
+ dev_warn(adev->dev, "SDMA RAS is not supported\n");
+ }
+}
+
+static void sdma_v4_4_2_inst_reset_ras_error_count(struct amdgpu_device *adev,
+ uint32_t sdma_inst)
+{
+ uint32_t sdma_dev_inst = GET_INST(SDMA0, sdma_inst);
+
+ amdgpu_ras_inst_reset_ras_error_count(adev,
+ sdma_v4_2_2_ue_reg_list,
+ ARRAY_SIZE(sdma_v4_2_2_ue_reg_list),
+ sdma_dev_inst);
+}
+
+static void sdma_v4_4_2_reset_ras_error_count(struct amdgpu_device *adev)
+{
+ uint32_t inst_mask;
+ int i = 0;
+
+ inst_mask = GENMASK(adev->sdma.num_instances - 1, 0);
+ if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA)) {
+ for_each_inst(i, inst_mask)
+ sdma_v4_4_2_inst_reset_ras_error_count(adev, i);
+ } else {
+ dev_warn(adev->dev, "SDMA RAS is not supported\n");
+ }
+}
+
+static const struct amdgpu_ras_block_hw_ops sdma_v4_4_2_ras_hw_ops = {
+ .query_ras_error_count = sdma_v4_4_2_query_ras_error_count,
+ .reset_ras_error_count = sdma_v4_4_2_reset_ras_error_count,
+};
+
+static struct amdgpu_sdma_ras sdma_v4_4_2_ras = {
+ .ras_block = {
+ .hw_ops = &sdma_v4_4_2_ras_hw_ops,
+ },
+};
+
+static void sdma_v4_4_2_set_ras_funcs(struct amdgpu_device *adev)
+{
+ adev->sdma.ras = &sdma_v4_4_2_ras;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.h b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.h
index 4814e8a074d6..d516145529bb 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.h
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.h
@@ -27,4 +27,6 @@
extern const struct amd_ip_funcs sdma_v4_4_2_ip_funcs;
extern const struct amdgpu_ip_block_version sdma_v4_4_2_ip_block;
+extern struct amdgpu_xcp_ip_funcs sdma_v4_4_2_xcp_funcs;
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
index 92e1299be021..5c4d4df9cf94 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
@@ -819,8 +819,6 @@ static int sdma_v5_0_gfx_resume(struct amdgpu_device *adev)
/* enable DMA IBs */
WREG32_SOC15_IP(GC, sdma_v5_0_get_reg_offset(adev, i, mmSDMA0_GFX_IB_CNTL), ib_cntl);
- ring->sched.ready = true;
-
if (amdgpu_sriov_vf(adev)) { /* bare-metal sequence doesn't need below to lines */
sdma_v5_0_ctx_switch_enable(adev, true);
sdma_v5_0_enable(adev, true);
@@ -1389,7 +1387,7 @@ static int sdma_v5_0_sw_init(void *handle)
(adev->doorbell_index.sdma_engine[0] << 1) //get DWORD offset
: (adev->doorbell_index.sdma_engine[1] << 1); // get DWORD offset
- ring->vm_hub = AMDGPU_GFXHUB_0;
+ ring->vm_hub = AMDGPU_GFXHUB(0);
sprintf(ring->name, "sdma%d", i);
r = amdgpu_ring_init(adev, ring, 1024, &adev->sdma.trap_irq,
(i == 0) ? AMDGPU_SDMA_IRQ_INSTANCE0 :
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
index ca7e8757d78e..a7b230e5a26d 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
@@ -617,18 +617,14 @@ static int sdma_v5_2_gfx_resume(struct amdgpu_device *adev)
/* enable DMA IBs */
WREG32_SOC15_IP(GC, sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_GFX_IB_CNTL), ib_cntl);
- ring->sched.ready = true;
-
if (amdgpu_sriov_vf(adev)) { /* bare-metal sequence doesn't need below to lines */
sdma_v5_2_ctx_switch_enable(adev, true);
sdma_v5_2_enable(adev, true);
}
- r = amdgpu_ring_test_ring(ring);
- if (r) {
- ring->sched.ready = false;
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
return r;
- }
if (adev->mman.buffer_funcs_ring == ring)
amdgpu_ttm_set_buffer_funcs_status(adev, true);
@@ -1253,7 +1249,7 @@ static int sdma_v5_2_sw_init(void *handle)
ring->doorbell_index =
(adev->doorbell_index.sdma_engine[i] << 1); //get DWORD offset
- ring->vm_hub = AMDGPU_GFXHUB_0;
+ ring->vm_hub = AMDGPU_GFXHUB(0);
sprintf(ring->name, "sdma%d", i);
r = amdgpu_ring_init(adev, ring, 1024, &adev->sdma.trap_irq,
AMDGPU_SDMA_IRQ_INSTANCE0 + i,
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index 3d9a80511a45..3b03dda854fd 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -238,6 +238,8 @@ static void sdma_v6_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
*
* @ring: amdgpu ring pointer
* @ib: IB object to schedule
+ * @flags: unused
+ * @job: job to retrieve vmid from
*
* Schedule an IB in the DMA ring.
*/
@@ -585,16 +587,12 @@ static int sdma_v6_0_gfx_resume(struct amdgpu_device *adev)
/* enable DMA IBs */
WREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev, i, regSDMA0_QUEUE0_IB_CNTL), ib_cntl);
- ring->sched.ready = true;
-
if (amdgpu_sriov_vf(adev))
sdma_v6_0_enable(adev, true);
r = amdgpu_ring_test_helper(ring);
- if (r) {
- ring->sched.ready = false;
+ if (r)
return r;
- }
if (adev->mman.buffer_funcs_ring == ring)
amdgpu_ttm_set_buffer_funcs_status(adev, true);
@@ -942,6 +940,7 @@ static int sdma_v6_0_ring_test_ring(struct amdgpu_ring *ring)
* sdma_v6_0_ring_test_ib - test an IB on the DMA engine
*
* @ring: amdgpu_ring structure holding ring information
+ * @timeout: timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
*
* Test a simple IB in the DMA ring.
* Returns 0 on success, error on failure.
@@ -1122,6 +1121,7 @@ static void sdma_v6_0_vm_set_pte_pde(struct amdgpu_ib *ib,
/**
* sdma_v6_0_ring_pad_ib - pad the IB
* @ib: indirect buffer to fill with padding
+ * @ring: amdgpu ring pointer
*
* Pad the IB with NOPs to a boundary multiple of 8.
*/
@@ -1171,6 +1171,8 @@ static void sdma_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
* sdma_v6_0_ring_emit_vm_flush - vm flush using sDMA
*
* @ring: amdgpu_ring pointer
+ * @vmid: vmid number to use
+ * @pd_addr: address
*
* Update the page table base and flush the VM TLB
* using sDMA.
@@ -1298,7 +1300,7 @@ static int sdma_v6_0_sw_init(void *handle)
ring->doorbell_index =
(adev->doorbell_index.sdma_engine[i] << 1); // get DWORD offset
- ring->vm_hub = AMDGPU_GFXHUB_0;
+ ring->vm_hub = AMDGPU_GFXHUB(0);
sprintf(ring->name, "sdma%d", i);
r = amdgpu_ring_init(adev, ring, 1024,
&adev->sdma.trap_irq,
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index 7f99e130acd0..f64b87b11b1b 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -1181,12 +1181,12 @@ static uint32_t si_get_register_value(struct amdgpu_device *adev,
mutex_lock(&adev->grbm_idx_mutex);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff, 0);
val = RREG32(reg_offset);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
return val;
} else {
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c
index abca8b529721..42c4547f32ec 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dma.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c
@@ -174,8 +174,6 @@ static int si_dma_start(struct amdgpu_device *adev)
WREG32(DMA_RB_WPTR + sdma_offsets[i], ring->wptr << 2);
WREG32(DMA_RB_CNTL + sdma_offsets[i], rb_cntl | DMA_RB_ENABLE);
- ring->sched.ready = true;
-
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.c b/drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.c
new file mode 100644
index 000000000000..4368a5891eeb
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "smuio_v13_0_3.h"
+#include "soc15_common.h"
+#include "smuio/smuio_13_0_3_offset.h"
+#include "smuio/smuio_13_0_3_sh_mask.h"
+
+#define PKG_TYPE_MASK 0x00000003L
+
+/**
+ * smuio_v13_0_3_get_die_id - query die id from FCH.
+ *
+ * @adev: amdgpu device pointer
+ *
+ * Returns die id
+ */
+static u32 smuio_v13_0_3_get_die_id(struct amdgpu_device *adev)
+{
+ u32 data, die_id;
+
+ data = RREG32_SOC15(SMUIO, 0, regSMUIO_MCM_CONFIG);
+ die_id = REG_GET_FIELD(data, SMUIO_MCM_CONFIG, DIE_ID);
+
+ return die_id;
+}
+
+/**
+ * smuio_v13_0_3_get_socket_id - query socket id from FCH
+ *
+ * @adev: amdgpu device pointer
+ *
+ * Returns socket id
+ */
+static u32 smuio_v13_0_3_get_socket_id(struct amdgpu_device *adev)
+{
+ u32 data, socket_id;
+
+ data = RREG32_SOC15(SMUIO, 0, regSMUIO_MCM_CONFIG);
+ socket_id = REG_GET_FIELD(data, SMUIO_MCM_CONFIG, SOCKET_ID);
+
+ return socket_id;
+}
+
+/**
+ * smuio_v13_0_3_get_pkg_type - query package type set by MP1/bootcode
+ *
+ * @adev: amdgpu device pointer
+ *
+ * Returns package type
+ */
+
+static enum amdgpu_pkg_type smuio_v13_0_3_get_pkg_type(struct amdgpu_device *adev)
+{
+ enum amdgpu_pkg_type pkg_type;
+ u32 data;
+
+ data = RREG32_SOC15(SMUIO, 0, regSMUIO_MCM_CONFIG);
+ data = REG_GET_FIELD(data, SMUIO_MCM_CONFIG, PKG_TYPE);
+ /* pkg_type[4:0]
+ *
+ * bit 1 == 1 APU form factor
+ *
+ * b0100 - b1111 - Reserved
+ */
+ switch (data & PKG_TYPE_MASK) {
+ case 0x2:
+ pkg_type = AMDGPU_PKG_TYPE_APU;
+ break;
+ default:
+ pkg_type = AMDGPU_PKG_TYPE_UNKNOWN;
+ break;
+ }
+
+ return pkg_type;
+}
+
+
+const struct amdgpu_smuio_funcs smuio_v13_0_3_funcs = {
+ .get_die_id = smuio_v13_0_3_get_die_id,
+ .get_socket_id = smuio_v13_0_3_get_socket_id,
+ .get_pkg_type = smuio_v13_0_3_get_pkg_type,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.h b/drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.h
new file mode 100644
index 000000000000..795f66c5a58b
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/smuio_v13_0_3.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __SMUIO_V13_0_3_H__
+#define __SMUIO_V13_0_3_H__
+
+#include "soc15_common.h"
+
+extern const struct amdgpu_smuio_funcs smuio_v13_0_3_funcs;
+
+#endif /* __SMUIO_V13_0_3_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
index a2fd1ffadb59..afcaeadda4c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -153,6 +153,24 @@ static const struct amdgpu_video_codecs rn_video_codecs_decode =
.codec_array = rn_video_codecs_decode_array,
};
+static const struct amdgpu_video_codec_info vcn_4_0_3_video_codecs_decode_array[] = {
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
+};
+
+static const struct amdgpu_video_codecs vcn_4_0_3_video_codecs_decode = {
+ .codec_count = ARRAY_SIZE(vcn_4_0_3_video_codecs_decode_array),
+ .codec_array = vcn_4_0_3_video_codecs_decode_array,
+};
+
+static const struct amdgpu_video_codecs vcn_4_0_3_video_codecs_encode = {
+ .codec_count = 0,
+ .codec_array = NULL,
+};
+
static int soc15_query_video_codecs(struct amdgpu_device *adev, bool encode,
const struct amdgpu_video_codecs **codecs)
{
@@ -185,6 +203,12 @@ static int soc15_query_video_codecs(struct amdgpu_device *adev, bool encode,
else
*codecs = &rn_video_codecs_decode;
return 0;
+ case IP_VERSION(4, 0, 3):
+ if (encode)
+ *codecs = &vcn_4_0_3_video_codecs_encode;
+ else
+ *codecs = &vcn_4_0_3_video_codecs_decode;
+ return 0;
default:
return -EINVAL;
}
@@ -312,7 +336,7 @@ static u32 soc15_get_xclk(struct amdgpu_device *adev)
void soc15_grbm_select(struct amdgpu_device *adev,
- u32 me, u32 pipe, u32 queue, u32 vmid)
+ u32 me, u32 pipe, u32 queue, u32 vmid, int xcc_id)
{
u32 grbm_gfx_cntl = 0;
grbm_gfx_cntl = REG_SET_FIELD(grbm_gfx_cntl, GRBM_GFX_CNTL, PIPEID, pipe);
@@ -320,12 +344,7 @@ void soc15_grbm_select(struct amdgpu_device *adev,
grbm_gfx_cntl = REG_SET_FIELD(grbm_gfx_cntl, GRBM_GFX_CNTL, VMID, vmid);
grbm_gfx_cntl = REG_SET_FIELD(grbm_gfx_cntl, GRBM_GFX_CNTL, QUEUEID, queue);
- WREG32_SOC15_RLC_SHADOW(GC, 0, mmGRBM_GFX_CNTL, grbm_gfx_cntl);
-}
-
-static void soc15_vga_set_state(struct amdgpu_device *adev, bool state)
-{
- /* todo */
+ WREG32_SOC15_RLC_SHADOW(GC, xcc_id, mmGRBM_GFX_CNTL, grbm_gfx_cntl);
}
static bool soc15_read_disabled_bios(struct amdgpu_device *adev)
@@ -364,12 +383,12 @@ static uint32_t soc15_read_indexed_register(struct amdgpu_device *adev, u32 se_n
mutex_lock(&adev->grbm_idx_mutex);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff, 0);
val = RREG32(reg_offset);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
return val;
}
@@ -533,6 +552,15 @@ soc15_asic_reset_method(struct amdgpu_device *adev)
if (connected_to_cpu)
return AMD_RESET_METHOD_MODE2;
break;
+ case IP_VERSION(13, 0, 6):
+ /* Use gpu_recovery param to target a reset method.
+ * Enable triggering of GPU reset only if specified
+ * by module parameter.
+ */
+ if (amdgpu_gpu_recovery == 4 || amdgpu_gpu_recovery == 5)
+ return AMD_RESET_METHOD_MODE2;
+ else
+ return AMD_RESET_METHOD_NONE;
default:
break;
}
@@ -817,7 +845,6 @@ static const struct amdgpu_asic_funcs soc15_asic_funcs =
.read_register = &soc15_read_register,
.reset = &soc15_asic_reset,
.reset_method = &soc15_asic_reset_method,
- .set_vga_state = &soc15_vga_set_state,
.get_xclk = &soc15_get_xclk,
.set_uvd_clocks = &soc15_set_uvd_clocks,
.set_vce_clocks = &soc15_set_vce_clocks,
@@ -839,7 +866,6 @@ static const struct amdgpu_asic_funcs vega20_asic_funcs =
.read_register = &soc15_read_register,
.reset = &soc15_asic_reset,
.reset_method = &soc15_asic_reset_method,
- .set_vga_state = &soc15_vga_set_state,
.get_xclk = &soc15_get_xclk,
.set_uvd_clocks = &soc15_set_uvd_clocks,
.set_vce_clocks = &soc15_set_vce_clocks,
@@ -854,6 +880,28 @@ static const struct amdgpu_asic_funcs vega20_asic_funcs =
.query_video_codecs = &soc15_query_video_codecs,
};
+static const struct amdgpu_asic_funcs aqua_vanjaram_asic_funcs =
+{
+ .read_disabled_bios = &soc15_read_disabled_bios,
+ .read_bios_from_rom = &amdgpu_soc15_read_bios_from_rom,
+ .read_register = &soc15_read_register,
+ .reset = &soc15_asic_reset,
+ .reset_method = &soc15_asic_reset_method,
+ .get_xclk = &soc15_get_xclk,
+ .set_uvd_clocks = &soc15_set_uvd_clocks,
+ .set_vce_clocks = &soc15_set_vce_clocks,
+ .get_config_memsize = &soc15_get_config_memsize,
+ .need_full_reset = &soc15_need_full_reset,
+ .init_doorbell_index = &aqua_vanjaram_doorbell_index_init,
+ .get_pcie_usage = &vega20_get_pcie_usage,
+ .need_reset_on_init = &soc15_need_reset_on_init,
+ .get_pcie_replay_count = &soc15_get_pcie_replay_count,
+ .supports_baco = &soc15_supports_baco,
+ .pre_asic_init = &soc15_pre_asic_init,
+ .query_video_codecs = &soc15_query_video_codecs,
+ .encode_ext_smn_addressing = &aqua_vanjaram_encode_ext_smn_addressing,
+};
+
static int soc15_common_early_init(void *handle)
{
#define MMIO_REG_HOLE_OFFSET (0x80000 - PAGE_SIZE)
@@ -867,6 +915,8 @@ static int soc15_common_early_init(void *handle)
adev->smc_wreg = NULL;
adev->pcie_rreg = &amdgpu_device_indirect_rreg;
adev->pcie_wreg = &amdgpu_device_indirect_wreg;
+ adev->pcie_rreg_ext = &amdgpu_device_indirect_rreg_ext;
+ adev->pcie_wreg_ext = &amdgpu_device_indirect_wreg_ext;
adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64;
adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64;
adev->uvd_ctx_rreg = &soc15_uvd_ctx_rreg;
@@ -1095,9 +1145,18 @@ static int soc15_common_early_init(void *handle)
adev->external_rev_id = adev->rev_id + 0x3c;
break;
case IP_VERSION(9, 4, 3):
- adev->asic_funcs = &vega20_asic_funcs;
- adev->cg_flags = 0;
- adev->pg_flags = 0;
+ adev->asic_funcs = &aqua_vanjaram_asic_funcs;
+ adev->cg_flags =
+ AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_CGCG |
+ AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_SDMA_MGCG |
+ AMD_CG_SUPPORT_GFX_FGCG | AMD_CG_SUPPORT_REPEATER_FGCG |
+ AMD_CG_SUPPORT_VCN_MGCG | AMD_CG_SUPPORT_JPEG_MGCG |
+ AMD_CG_SUPPORT_IH_CG;
+ adev->pg_flags =
+ AMD_PG_SUPPORT_VCN |
+ AMD_PG_SUPPORT_VCN_DPG |
+ AMD_PG_SUPPORT_JPEG;
+ adev->external_rev_id = adev->rev_id + 0x46;
break;
default:
/* FIXME: not supported yet */
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.h b/drivers/gpu/drm/amd/amdgpu/soc15.h
index efc2a253e8db..eac54042c6c0 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.h
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.h
@@ -100,7 +100,7 @@ struct soc15_ras_field_entry {
#define SOC15_RAS_REG_FIELD_VAL(val, entry, field) SOC15_REG_FIELD_VAL((val), (entry).field##_count_mask, (entry).field##_count_shift)
void soc15_grbm_select(struct amdgpu_device *adev,
- u32 me, u32 pipe, u32 queue, u32 vmid);
+ u32 me, u32 pipe, u32 queue, u32 vmid, int xcc_id);
void soc15_set_virt_ops(struct amdgpu_device *adev);
void soc15_program_register_sequence(struct amdgpu_device *adev,
@@ -111,7 +111,11 @@ int vega10_reg_base_init(struct amdgpu_device *adev);
int vega20_reg_base_init(struct amdgpu_device *adev);
int arct_reg_base_init(struct amdgpu_device *adev);
int aldebaran_reg_base_init(struct amdgpu_device *adev);
+void aqua_vanjaram_ip_map_init(struct amdgpu_device *adev);
+u64 aqua_vanjaram_encode_ext_smn_addressing(int ext_id);
+int aqua_vanjaram_init_soc_config(struct amdgpu_device *adev);
void vega10_doorbell_index_init(struct amdgpu_device *adev);
void vega20_doorbell_index_init(struct amdgpu_device *adev);
+void aqua_vanjaram_doorbell_index_init(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15_common.h b/drivers/gpu/drm/amd/amdgpu/soc15_common.h
index 9fefd403e14f..96948a59f8dd 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15_common.h
+++ b/drivers/gpu/drm/amd/amdgpu/soc15_common.h
@@ -24,8 +24,18 @@
#ifndef __SOC15_COMMON_H__
#define __SOC15_COMMON_H__
+/* GET_INST returns the physical instance corresponding to a logical instance */
+#define GET_INST(ip, inst) \
+ (adev->ip_map.logical_to_dev_inst ? \
+ adev->ip_map.logical_to_dev_inst(adev, ip##_HWIP, inst) : inst)
+#define GET_MASK(ip, mask) \
+ (adev->ip_map.logical_to_dev_mask ? \
+ adev->ip_map.logical_to_dev_mask(adev, ip##_HWIP, mask) : mask)
+
/* Register Access Macros */
#define SOC15_REG_OFFSET(ip, inst, reg) (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg)
+#define SOC15_REG_OFFSET1(ip, inst, reg, offset) \
+ (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + (reg)+(offset))
#define __WREG32_SOC15_RLC__(reg, value, flag, hwip) \
((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.rlcg_reg_access_supported) ? \
@@ -66,7 +76,8 @@
AMDGPU_REGS_NO_KIQ, ip##_HWIP)
#define RREG32_SOC15_OFFSET(ip, inst, reg, offset) \
- __RREG32_SOC15_RLC__((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + offset, 0, ip##_HWIP)
+ __RREG32_SOC15_RLC__((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + (reg)) + \
+ (offset), 0, ip##_HWIP)
#define WREG32_SOC15(ip, inst, reg, value) \
__WREG32_SOC15_RLC__((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg), \
@@ -86,31 +97,15 @@
__WREG32_SOC15_RLC__((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + offset, \
value, 0, ip##_HWIP)
-#define SOC15_WAIT_ON_RREG(ip, inst, reg, expected_value, mask) \
-({ int ret = 0; \
- do { \
- uint32_t old_ = 0; \
- uint32_t tmp_ = RREG32(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg); \
- uint32_t loop = adev->usec_timeout; \
- ret = 0; \
- while ((tmp_ & (mask)) != (expected_value)) { \
- if (old_ != tmp_) { \
- loop = adev->usec_timeout; \
- old_ = tmp_; \
- } else \
- udelay(1); \
- tmp_ = RREG32(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg); \
- loop--; \
- if (!loop) { \
- DRM_WARN("Register(%d) [%s] failed to reach value 0x%08x != 0x%08x\n", \
- inst, #reg, (unsigned)expected_value, (unsigned)(tmp_ & (mask))); \
- ret = -ETIMEDOUT; \
- break; \
- } \
- } \
- } while (0); \
- ret; \
-})
+#define SOC15_WAIT_ON_RREG(ip, inst, reg, expected_value, mask) \
+ amdgpu_device_wait_on_rreg(adev, inst, \
+ (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + (reg)), \
+ #reg, expected_value, mask)
+
+#define SOC15_WAIT_ON_RREG_OFFSET(ip, inst, reg, offset, expected_value, mask) \
+ amdgpu_device_wait_on_rreg(adev, inst, \
+ (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + (reg) + (offset)), \
+ #reg, expected_value, mask)
#define WREG32_RLC(reg, value) \
__WREG32_SOC15_RLC__(reg, value, AMDGPU_REGS_RLC, GC_HWIP)
@@ -157,10 +152,10 @@
do { \
uint32_t target_reg = adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg;\
if (amdgpu_sriov_fullaccess(adev)) { \
- uint32_t r2 = adev->reg_offset[GC_HWIP][0][prefix##SCRATCH_REG1_BASE_IDX] + prefix##SCRATCH_REG2; \
- uint32_t r3 = adev->reg_offset[GC_HWIP][0][prefix##SCRATCH_REG1_BASE_IDX] + prefix##SCRATCH_REG3; \
- uint32_t grbm_cntl = adev->reg_offset[GC_HWIP][0][prefix##GRBM_GFX_CNTL_BASE_IDX] + prefix##GRBM_GFX_CNTL; \
- uint32_t grbm_idx = adev->reg_offset[GC_HWIP][0][prefix##GRBM_GFX_INDEX_BASE_IDX] + prefix##GRBM_GFX_INDEX; \
+ uint32_t r2 = adev->reg_offset[GC_HWIP][inst][prefix##SCRATCH_REG1_BASE_IDX] + prefix##SCRATCH_REG2; \
+ uint32_t r3 = adev->reg_offset[GC_HWIP][inst][prefix##SCRATCH_REG1_BASE_IDX] + prefix##SCRATCH_REG3; \
+ uint32_t grbm_cntl = adev->reg_offset[GC_HWIP][inst][prefix##GRBM_GFX_CNTL_BASE_IDX] + prefix##GRBM_GFX_CNTL; \
+ uint32_t grbm_idx = adev->reg_offset[GC_HWIP][inst][prefix##GRBM_GFX_INDEX_BASE_IDX] + prefix##GRBM_GFX_INDEX; \
if (target_reg == grbm_cntl) \
WREG32(r2, value); \
else if (target_reg == grbm_idx) \
@@ -176,13 +171,13 @@
#define WREG32_SOC15_RLC(ip, inst, reg, value) \
do { \
- uint32_t target_reg = adev->reg_offset[ip##_HWIP][0][reg##_BASE_IDX] + reg;\
+ uint32_t target_reg = adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg;\
__WREG32_SOC15_RLC__(target_reg, value, AMDGPU_REGS_RLC, ip##_HWIP); \
} while (0)
#define WREG32_SOC15_RLC_EX(prefix, ip, inst, reg, value) \
do { \
- uint32_t target_reg = adev->reg_offset[GC_HWIP][0][reg##_BASE_IDX] + reg;\
+ uint32_t target_reg = adev->reg_offset[GC_HWIP][inst][reg##_BASE_IDX] + reg;\
WREG32_RLC_EX(prefix, target_reg, value); \
} while (0)
@@ -199,4 +194,14 @@
#define RREG32_SOC15_OFFSET_RLC(ip, inst, reg, offset) \
__RREG32_SOC15_RLC__((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + offset, AMDGPU_REGS_RLC, ip##_HWIP)
+/* inst equals to ext for some IPs */
+#define RREG32_SOC15_EXT(ip, inst, reg, ext) \
+ RREG32_PCIE_EXT((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) * 4 \
+ + adev->asic_funcs->encode_ext_smn_addressing(ext)) \
+
+#define WREG32_SOC15_EXT(ip, inst, reg, ext, value) \
+ WREG32_PCIE_EXT((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) * 4 \
+ + adev->asic_funcs->encode_ext_smn_addressing(ext), \
+ value) \
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c
index d77162536514..e5e5d68a4d70 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc21.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc21.c
@@ -248,11 +248,6 @@ void soc21_grbm_select(struct amdgpu_device *adev,
WREG32_SOC15(GC, 0, regGRBM_GFX_CNTL, grbm_gfx_cntl);
}
-static void soc21_vga_set_state(struct amdgpu_device *adev, bool state)
-{
- /* todo */
-}
-
static bool soc21_read_disabled_bios(struct amdgpu_device *adev)
{
/* todo */
@@ -288,12 +283,12 @@ static uint32_t soc21_read_indexed_register(struct amdgpu_device *adev, u32 se_n
mutex_lock(&adev->grbm_idx_mutex);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff, 0);
val = RREG32(reg_offset);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
return val;
}
@@ -542,9 +537,9 @@ static int soc21_update_umd_stable_pstate(struct amdgpu_device *adev,
bool enter)
{
if (enter)
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
else
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
if (adev->gfx.funcs->update_perfmon_mgcg)
adev->gfx.funcs->update_perfmon_mgcg(adev, !enter);
@@ -559,7 +554,6 @@ static const struct amdgpu_asic_funcs soc21_asic_funcs =
.read_register = &soc21_read_register,
.reset = &soc21_asic_reset,
.reset_method = &soc21_asic_reset_method,
- .set_vga_state = &soc21_vga_set_state,
.get_xclk = &soc21_get_xclk,
.set_uvd_clocks = &soc21_set_uvd_clocks,
.set_vce_clocks = &soc21_set_vce_clocks,
diff --git a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h
index 30d0482ac466..879bb7af297c 100644
--- a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h
+++ b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h
@@ -129,6 +129,8 @@ struct ta_ras_trigger_error_input {
struct ta_ras_init_flags {
uint8_t poison_mode_en;
uint8_t dgpu_mode;
+ uint16_t xcc_mask;
+ uint8_t channel_dis_num;
};
struct ta_ras_output_flags {
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
index d51ae0bc36f7..46bfdee79bfd 100644
--- a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
@@ -444,6 +444,11 @@ static void umc_v8_10_ecc_info_query_ras_error_address(struct amdgpu_device *ade
umc_v8_10_ecc_info_query_error_address, ras_error_status);
}
+static void umc_v8_10_set_eeprom_table_version(struct amdgpu_ras_eeprom_table_header *hdr)
+{
+ hdr->version = RAS_TABLE_VER_V2_1;
+}
+
const struct amdgpu_ras_block_hw_ops umc_v8_10_ras_hw_ops = {
.query_ras_error_count = umc_v8_10_query_ras_error_count,
.query_ras_error_address = umc_v8_10_query_ras_error_address,
@@ -457,4 +462,5 @@ struct amdgpu_umc_ras umc_v8_10_ras = {
.query_ras_poison_mode = umc_v8_10_query_ras_poison_mode,
.ecc_info_query_ras_error_count = umc_v8_10_ecc_info_query_ras_error_count,
.ecc_info_query_ras_error_address = umc_v8_10_ecc_info_query_ras_error_address,
+ .set_eeprom_table_version = umc_v8_10_set_eeprom_table_version,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h
index c6dfd433fec7..dc12e0af5451 100644
--- a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h
@@ -33,7 +33,8 @@
/* Total channel instances for all available umc nodes */
#define UMC_V8_10_TOTAL_CHANNEL_NUM(adev) \
- (UMC_V8_10_CHANNEL_INSTANCE_NUM * UMC_V8_10_UMC_INSTANCE_NUM * (adev)->gmc.num_umc)
+ (UMC_V8_10_CHANNEL_INSTANCE_NUM * UMC_V8_10_UMC_INSTANCE_NUM * \
+ (adev)->gmc.num_umc - hweight32((adev)->gmc.m_half_use) * 2)
/* UMC regiser per channel offset */
#define UMC_V8_10_PER_CHANNEL_OFFSET 0x400
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
index e32b656b3dab..abaa4463e906 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
@@ -444,7 +444,7 @@ static int uvd_v7_0_sw_init(void *handle)
continue;
if (!amdgpu_sriov_vf(adev)) {
ring = &adev->uvd.inst[j].ring;
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "uvd_%d", ring->me);
r = amdgpu_ring_init(adev, ring, 512,
&adev->uvd.inst[j].irq, 0,
@@ -455,7 +455,7 @@ static int uvd_v7_0_sw_init(void *handle)
for (i = 0; i < adev->uvd.num_enc_rings; ++i) {
ring = &adev->uvd.inst[j].ring_enc[i];
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "uvd_enc_%d.%d", ring->me, i);
if (amdgpu_sriov_vf(adev)) {
ring->use_doorbell = true;
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
index 57b85bb6a1e4..e0b70cd3b697 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
@@ -466,7 +466,7 @@ static int vce_v4_0_sw_init(void *handle)
enum amdgpu_ring_priority_level hw_prio = amdgpu_vce_get_ring_prio(i);
ring = &adev->vce.ring[i];
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "vce%d", i);
if (amdgpu_sriov_vf(adev)) {
/* DOORBELL only works under SRIOV */
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index 761c28fa6ec1..16feb491adf5 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -120,7 +120,7 @@ static int vcn_v1_0_sw_init(void *handle)
return r;
ring = &adev->vcn.inst->ring_dec;
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "vcn_dec");
r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst->irq, 0,
AMDGPU_RING_PRIO_DEFAULT, NULL);
@@ -142,7 +142,7 @@ static int vcn_v1_0_sw_init(void *handle)
enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
ring = &adev->vcn.inst->ring_enc[i];
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "vcn_enc%d", i);
r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst->irq, 0,
hw_prio, NULL);
@@ -211,7 +211,7 @@ static int vcn_v1_0_hw_init(void *handle)
goto done;
}
- ring = &adev->jpeg.inst->ring_dec;
+ ring = adev->jpeg.inst->ring_dec;
r = amdgpu_ring_test_helper(ring);
if (r)
goto done;
@@ -1304,7 +1304,7 @@ static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev,
UVD_DPG_PAUSE__JPEG_PAUSE_DPG_ACK_MASK);
/* Restore */
- ring = &adev->jpeg.inst->ring_dec;
+ ring = adev->jpeg.inst->ring_dec;
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL,
UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK |
@@ -1802,7 +1802,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
else
new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
- if (amdgpu_fence_count_emitted(&adev->jpeg.inst->ring_dec))
+ if (amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec))
new_state.jpeg = VCN_DPG_STATE__PAUSE;
else
new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
@@ -1810,7 +1810,7 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work)
adev->vcn.pause_dpg_mode(adev, 0, &new_state);
}
- fences += amdgpu_fence_count_emitted(&adev->jpeg.inst->ring_dec);
+ fences += amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec);
fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_dec);
if (fences == 0) {
@@ -1832,7 +1832,7 @@ static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
- if (amdgpu_fence_wait_empty(&ring->adev->jpeg.inst->ring_dec))
+ if (amdgpu_fence_wait_empty(ring->adev->jpeg.inst->ring_dec))
DRM_ERROR("VCN dec: jpeg dec ring may not be empty\n");
vcn_v1_0_set_pg_for_begin_use(ring, set_clocks);
@@ -1864,7 +1864,7 @@ void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
else
new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
- if (amdgpu_fence_count_emitted(&adev->jpeg.inst->ring_dec))
+ if (amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec))
new_state.jpeg = VCN_DPG_STATE__PAUSE;
else
new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index 7c2b3aa48083..c975aed2f6c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -129,7 +129,7 @@ static int vcn_v2_0_sw_init(void *handle)
ring->use_doorbell = true;
ring->doorbell_index = adev->doorbell_index.vcn.vcn_ring0_1 << 1;
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "vcn_dec");
r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst->irq, 0,
@@ -160,7 +160,7 @@ static int vcn_v2_0_sw_init(void *handle)
ring = &adev->vcn.inst->ring_enc[i];
ring->use_doorbell = true;
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
if (!amdgpu_sriov_vf(adev))
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + i;
else
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index 515681c88dcb..bb1875f926f1 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -188,9 +188,9 @@ static int vcn_v2_5_sw_init(void *handle)
(amdgpu_sriov_vf(adev) ? 2*j : 8*j);
if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(2, 5, 0))
- ring->vm_hub = AMDGPU_MMHUB_1;
+ ring->vm_hub = AMDGPU_MMHUB1(0);
else
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "vcn_dec_%d", j);
r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[j].irq,
@@ -208,9 +208,9 @@ static int vcn_v2_5_sw_init(void *handle)
(amdgpu_sriov_vf(adev) ? (1 + i + 2*j) : (2 + i + 8*j));
if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(2, 5, 0))
- ring->vm_hub = AMDGPU_MMHUB_1;
+ ring->vm_hub = AMDGPU_MMHUB1(0);
else
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "vcn_enc_%d.%d", j, i);
r = amdgpu_ring_init(adev, ring, 512,
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 3eab186261aa..c8f63b3c6f69 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -189,7 +189,7 @@ static int vcn_v3_0_sw_init(void *handle)
} else {
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i;
}
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "vcn_dec_%d", i);
r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0,
AMDGPU_RING_PRIO_DEFAULT,
@@ -213,7 +213,7 @@ static int vcn_v3_0_sw_init(void *handle)
} else {
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + j + 8 * i;
}
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "vcn_enc_%d.%d", i, j);
r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0,
hw_prio, &adev->vcn.inst[i].sched_score);
@@ -1313,7 +1313,7 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
header.version = MMSCH_VERSION;
header.total_size = sizeof(struct mmsch_v3_0_init_header) >> 2;
- for (i = 0; i < AMDGPU_MAX_VCN_INSTANCES; i++) {
+ for (i = 0; i < MMSCH_V3_0_VCN_INSTANCES; i++) {
header.inst[i].init_status = 0;
header.inst[i].table_offset = 0;
header.inst[i].table_size = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index da126ff8bcbc..b48bb5212488 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -153,7 +153,7 @@ static int vcn_v4_0_sw_init(void *handle)
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + i * (adev->vcn.num_enc_rings + 1) + 1;
else
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + 8 * i;
- ring->vm_hub = AMDGPU_MMHUB_0;
+ ring->vm_hub = AMDGPU_MMHUB0(0);
sprintf(ring->name, "vcn_unified_%d", i);
r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0,
@@ -1243,7 +1243,7 @@ static int vcn_v4_0_start_sriov(struct amdgpu_device *adev)
header.version = MMSCH_VERSION;
header.total_size = sizeof(struct mmsch_v4_0_init_header) >> 2;
- for (i = 0; i < AMDGPU_MAX_VCN_INSTANCES; i++) {
+ for (i = 0; i < MMSCH_V4_0_VCN_INSTANCES; i++) {
header.inst[i].init_status = 0;
header.inst[i].table_offset = 0;
header.inst[i].table_size = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
new file mode 100644
index 000000000000..5d67b8b8a3d6
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -0,0 +1,1541 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/firmware.h>
+#include <drm/drm_drv.h>
+
+#include "amdgpu.h"
+#include "amdgpu_vcn.h"
+#include "amdgpu_pm.h"
+#include "soc15.h"
+#include "soc15d.h"
+#include "soc15_hw_ip.h"
+#include "vcn_v2_0.h"
+
+#include "vcn/vcn_4_0_3_offset.h"
+#include "vcn/vcn_4_0_3_sh_mask.h"
+#include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"
+
+#define mmUVD_DPG_LMA_CTL regUVD_DPG_LMA_CTL
+#define mmUVD_DPG_LMA_CTL_BASE_IDX regUVD_DPG_LMA_CTL_BASE_IDX
+#define mmUVD_DPG_LMA_DATA regUVD_DPG_LMA_DATA
+#define mmUVD_DPG_LMA_DATA_BASE_IDX regUVD_DPG_LMA_DATA_BASE_IDX
+
+#define VCN_VID_SOC_ADDRESS_2_0 0x1fb00
+#define VCN1_VID_SOC_ADDRESS_3_0 0x48300
+
+static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev);
+static void vcn_v4_0_3_set_irq_funcs(struct amdgpu_device *adev);
+static int vcn_v4_0_3_set_powergating_state(void *handle,
+ enum amd_powergating_state state);
+static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_device *adev,
+ int inst_idx, struct dpg_pause_state *new_state);
+static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring);
+static void vcn_v4_0_3_set_ras_funcs(struct amdgpu_device *adev);
+static void vcn_v4_0_3_enable_ras(struct amdgpu_device *adev,
+ int inst_idx, bool indirect);
+/**
+ * vcn_v4_0_3_early_init - set function pointers
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Set ring and irq function pointers
+ */
+static int vcn_v4_0_3_early_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ /* re-use enc ring as unified ring */
+ adev->vcn.num_enc_rings = 1;
+
+ vcn_v4_0_3_set_unified_ring_funcs(adev);
+ vcn_v4_0_3_set_irq_funcs(adev);
+ vcn_v4_0_3_set_ras_funcs(adev);
+
+ return amdgpu_vcn_early_init(adev);
+}
+
+/**
+ * vcn_v4_0_3_sw_init - sw init for VCN block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Load firmware and sw initialization
+ */
+static int vcn_v4_0_3_sw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_ring *ring;
+ int i, r, vcn_inst;
+
+ r = amdgpu_vcn_sw_init(adev);
+ if (r)
+ return r;
+
+ amdgpu_vcn_setup_ucode(adev);
+
+ r = amdgpu_vcn_resume(adev);
+ if (r)
+ return r;
+
+ /* VCN DEC TRAP */
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
+ VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst->irq);
+ if (r)
+ return r;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ volatile struct amdgpu_vcn4_fw_shared *fw_shared;
+
+ vcn_inst = GET_INST(VCN, i);
+
+ ring = &adev->vcn.inst[i].ring_enc[0];
+ ring->use_doorbell = true;
+ ring->doorbell_index =
+ (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
+ 9 * vcn_inst;
+ ring->vm_hub = AMDGPU_MMHUB0(adev->vcn.inst[i].aid_id);
+ sprintf(ring->name, "vcn_unified_%d", adev->vcn.inst[i].aid_id);
+ r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst->irq, 0,
+ AMDGPU_RING_PRIO_DEFAULT,
+ &adev->vcn.inst[i].sched_score);
+ if (r)
+ return r;
+
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+ fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
+ fw_shared->sq.is_enabled = true;
+
+ if (amdgpu_vcnfw_log)
+ amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
+ }
+
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+ adev->vcn.pause_dpg_mode = vcn_v4_0_3_pause_dpg_mode;
+
+ if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) {
+ r = amdgpu_vcn_ras_sw_init(adev);
+ if (r) {
+ dev_err(adev->dev, "Failed to initialize vcn ras block!\n");
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * vcn_v4_0_3_sw_fini - sw fini for VCN block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * VCN suspend and free up sw allocation
+ */
+static int vcn_v4_0_3_sw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i, r, idx;
+
+ if (drm_dev_enter(&adev->ddev, &idx)) {
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ volatile struct amdgpu_vcn4_fw_shared *fw_shared;
+
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+ fw_shared->present_flag_0 = 0;
+ fw_shared->sq.is_enabled = cpu_to_le32(false);
+ }
+ drm_dev_exit(idx);
+ }
+
+ r = amdgpu_vcn_suspend(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_vcn_sw_fini(adev);
+
+ return r;
+}
+
+/**
+ * vcn_v4_0_3_hw_init - start and test VCN block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Initialize the hardware, boot up the VCPU and do some testing
+ */
+static int vcn_v4_0_3_hw_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_ring *ring;
+ int i, r, vcn_inst;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ vcn_inst = GET_INST(VCN, i);
+ ring = &adev->vcn.inst[i].ring_enc[0];
+
+ if (ring->use_doorbell) {
+ adev->nbio.funcs->vcn_doorbell_range(
+ adev, ring->use_doorbell,
+ (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +
+ 9 * vcn_inst,
+ adev->vcn.inst[i].aid_id);
+
+ WREG32_SOC15(
+ VCN, GET_INST(VCN, ring->me),
+ regVCN_RB1_DB_CTRL,
+ ring->doorbell_index
+ << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
+ VCN_RB1_DB_CTRL__EN_MASK);
+
+ /* Read DB_CTRL to flush the write DB_CTRL command. */
+ RREG32_SOC15(
+ VCN, GET_INST(VCN, ring->me),
+ regVCN_RB1_DB_CTRL);
+ }
+
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ goto done;
+ }
+
+done:
+ if (!r)
+ DRM_DEV_INFO(adev->dev, "VCN decode initialized successfully(under %s).\n",
+ (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
+
+ return r;
+}
+
+/**
+ * vcn_v4_0_3_hw_fini - stop the hardware block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Stop the VCN block, mark ring as not ready any more
+ */
+static int vcn_v4_0_3_hw_fini(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ cancel_delayed_work_sync(&adev->vcn.idle_work);
+
+ if (adev->vcn.cur_state != AMD_PG_STATE_GATE)
+ vcn_v4_0_3_set_powergating_state(adev, AMD_PG_STATE_GATE);
+
+ return 0;
+}
+
+/**
+ * vcn_v4_0_3_suspend - suspend VCN block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * HW fini and suspend VCN block
+ */
+static int vcn_v4_0_3_suspend(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = vcn_v4_0_3_hw_fini(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_vcn_suspend(adev);
+
+ return r;
+}
+
+/**
+ * vcn_v4_0_3_resume - resume VCN block
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Resume firmware and hw init VCN block
+ */
+static int vcn_v4_0_3_resume(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int r;
+
+ r = amdgpu_vcn_resume(adev);
+ if (r)
+ return r;
+
+ r = vcn_v4_0_3_hw_init(adev);
+
+ return r;
+}
+
+/**
+ * vcn_v4_0_3_mc_resume - memory controller programming
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number
+ *
+ * Let the VCN memory controller know it's offsets
+ */
+static void vcn_v4_0_3_mc_resume(struct amdgpu_device *adev, int inst_idx)
+{
+ uint32_t offset, size, vcn_inst;
+ const struct common_firmware_header *hdr;
+
+ hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
+ size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
+
+ vcn_inst = GET_INST(VCN, inst_idx);
+ /* cache window 0: fw */
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+ WREG32_SOC15(
+ VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
+ (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx]
+ .tmr_mc_addr_lo));
+ WREG32_SOC15(
+ VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
+ (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx]
+ .tmr_mc_addr_hi));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET0, 0);
+ offset = 0;
+ } else {
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
+ lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr));
+ WREG32_SOC15(VCN, vcn_inst,
+ regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
+ upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr));
+ offset = size;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET0,
+ AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
+ }
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_SIZE0, size);
+
+ /* cache window 1: stack */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
+ lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
+ upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET1, 0);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_SIZE1,
+ AMDGPU_VCN_STACK_SIZE);
+
+ /* cache window 2: context */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
+ lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset +
+ AMDGPU_VCN_STACK_SIZE));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
+ upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset +
+ AMDGPU_VCN_STACK_SIZE));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET2, 0);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_SIZE2,
+ AMDGPU_VCN_CONTEXT_SIZE);
+
+ /* non-cache window */
+ WREG32_SOC15(
+ VCN, vcn_inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW,
+ lower_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr));
+ WREG32_SOC15(
+ VCN, vcn_inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH,
+ upper_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_NONCACHE_OFFSET0, 0);
+ WREG32_SOC15(
+ VCN, vcn_inst, regUVD_VCPU_NONCACHE_SIZE0,
+ AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)));
+}
+
+/**
+ * vcn_v4_0_3_mc_resume_dpg_mode - memory controller programming for dpg mode
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number index
+ * @indirect: indirectly write sram
+ *
+ * Let the VCN memory controller know it's offsets with dpg mode
+ */
+static void vcn_v4_0_3_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+{
+ uint32_t offset, size;
+ const struct common_firmware_header *hdr;
+
+ hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
+ size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
+
+ /* cache window 0: fw */
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+ if (!indirect) {
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
+ (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN +
+ inst_idx].tmr_mc_addr_lo), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
+ (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN +
+ inst_idx].tmr_mc_addr_hi), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);
+ } else {
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 0, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 0, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);
+ }
+ offset = 0;
+ } else {
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
+ lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
+ upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);
+ offset = size;
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_OFFSET0),
+ AMDGPU_UVD_FIRMWARE_OFFSET >> 3, 0, indirect);
+ }
+
+ if (!indirect)
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_SIZE0), size, 0, indirect);
+ else
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_SIZE0), 0, 0, indirect);
+
+ /* cache window 1: stack */
+ if (!indirect) {
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW),
+ lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH),
+ upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);
+ } else {
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), 0, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), 0, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);
+ }
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_SIZE1), AMDGPU_VCN_STACK_SIZE, 0, indirect);
+
+ /* cache window 2: context */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW),
+ lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset +
+ AMDGPU_VCN_STACK_SIZE), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH),
+ upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset +
+ AMDGPU_VCN_STACK_SIZE), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_OFFSET2), 0, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE, 0, indirect);
+
+ /* non-cache window */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW),
+ lower_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH),
+ upper_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_NONCACHE_OFFSET0), 0, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_NONCACHE_SIZE0),
+ AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)), 0, indirect);
+
+ /* VCN global tiling registers */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_GFX8_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect);
+}
+
+/**
+ * vcn_v4_0_3_disable_clock_gating - disable VCN clock gating
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number
+ *
+ * Disable clock gating for VCN block
+ */
+static void vcn_v4_0_3_disable_clock_gating(struct amdgpu_device *adev, int inst_idx)
+{
+ uint32_t data;
+ int vcn_inst;
+
+ if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
+ return;
+
+ vcn_inst = GET_INST(VCN, inst_idx);
+
+ /* VCN disable CGC */
+ data = RREG32_SOC15(VCN, vcn_inst, regUVD_CGC_CTRL);
+ data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+ data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+ data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_CGC_CTRL, data);
+
+ data = RREG32_SOC15(VCN, vcn_inst, regUVD_CGC_GATE);
+ data &= ~(UVD_CGC_GATE__SYS_MASK
+ | UVD_CGC_GATE__MPEG2_MASK
+ | UVD_CGC_GATE__REGS_MASK
+ | UVD_CGC_GATE__RBC_MASK
+ | UVD_CGC_GATE__LMI_MC_MASK
+ | UVD_CGC_GATE__LMI_UMC_MASK
+ | UVD_CGC_GATE__MPC_MASK
+ | UVD_CGC_GATE__LBSI_MASK
+ | UVD_CGC_GATE__LRBBM_MASK
+ | UVD_CGC_GATE__WCB_MASK
+ | UVD_CGC_GATE__VCPU_MASK
+ | UVD_CGC_GATE__MMSCH_MASK);
+
+ WREG32_SOC15(VCN, vcn_inst, regUVD_CGC_GATE, data);
+ SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_CGC_GATE, 0, 0xFFFFFFFF);
+
+ data = RREG32_SOC15(VCN, vcn_inst, regUVD_CGC_CTRL);
+ data &= ~(UVD_CGC_CTRL__SYS_MODE_MASK
+ | UVD_CGC_CTRL__MPEG2_MODE_MASK
+ | UVD_CGC_CTRL__REGS_MODE_MASK
+ | UVD_CGC_CTRL__RBC_MODE_MASK
+ | UVD_CGC_CTRL__LMI_MC_MODE_MASK
+ | UVD_CGC_CTRL__LMI_UMC_MODE_MASK
+ | UVD_CGC_CTRL__MPC_MODE_MASK
+ | UVD_CGC_CTRL__LBSI_MODE_MASK
+ | UVD_CGC_CTRL__LRBBM_MODE_MASK
+ | UVD_CGC_CTRL__WCB_MODE_MASK
+ | UVD_CGC_CTRL__VCPU_MODE_MASK
+ | UVD_CGC_CTRL__MMSCH_MODE_MASK);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_CGC_CTRL, data);
+
+ data = RREG32_SOC15(VCN, vcn_inst, regUVD_SUVD_CGC_GATE);
+ data |= (UVD_SUVD_CGC_GATE__SRE_MASK
+ | UVD_SUVD_CGC_GATE__SIT_MASK
+ | UVD_SUVD_CGC_GATE__SMP_MASK
+ | UVD_SUVD_CGC_GATE__SCM_MASK
+ | UVD_SUVD_CGC_GATE__SDB_MASK
+ | UVD_SUVD_CGC_GATE__SRE_H264_MASK
+ | UVD_SUVD_CGC_GATE__SRE_HEVC_MASK
+ | UVD_SUVD_CGC_GATE__SIT_H264_MASK
+ | UVD_SUVD_CGC_GATE__SIT_HEVC_MASK
+ | UVD_SUVD_CGC_GATE__SCM_H264_MASK
+ | UVD_SUVD_CGC_GATE__SCM_HEVC_MASK
+ | UVD_SUVD_CGC_GATE__SDB_H264_MASK
+ | UVD_SUVD_CGC_GATE__SDB_HEVC_MASK
+ | UVD_SUVD_CGC_GATE__ENT_MASK
+ | UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK
+ | UVD_SUVD_CGC_GATE__SITE_MASK
+ | UVD_SUVD_CGC_GATE__SRE_VP9_MASK
+ | UVD_SUVD_CGC_GATE__SCM_VP9_MASK
+ | UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK
+ | UVD_SUVD_CGC_GATE__SDB_VP9_MASK
+ | UVD_SUVD_CGC_GATE__IME_HEVC_MASK);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_SUVD_CGC_GATE, data);
+
+ data = RREG32_SOC15(VCN, vcn_inst, regUVD_SUVD_CGC_CTRL);
+ data &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__IME_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_SUVD_CGC_CTRL, data);
+}
+
+/**
+ * vcn_v4_0_3_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode
+ *
+ * @adev: amdgpu_device pointer
+ * @sram_sel: sram select
+ * @inst_idx: instance number index
+ * @indirect: indirectly write sram
+ *
+ * Disable clock gating for VCN block with dpg mode
+ */
+static void vcn_v4_0_3_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,
+ int inst_idx, uint8_t indirect)
+{
+ uint32_t reg_data = 0;
+
+ if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
+ return;
+
+ /* enable sw clock gating control */
+ reg_data = 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ reg_data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+ reg_data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+ reg_data &= ~(UVD_CGC_CTRL__SYS_MODE_MASK |
+ UVD_CGC_CTRL__MPEG2_MODE_MASK |
+ UVD_CGC_CTRL__REGS_MODE_MASK |
+ UVD_CGC_CTRL__RBC_MODE_MASK |
+ UVD_CGC_CTRL__LMI_MC_MODE_MASK |
+ UVD_CGC_CTRL__LMI_UMC_MODE_MASK |
+ UVD_CGC_CTRL__IDCT_MODE_MASK |
+ UVD_CGC_CTRL__MPRD_MODE_MASK |
+ UVD_CGC_CTRL__MPC_MODE_MASK |
+ UVD_CGC_CTRL__LBSI_MODE_MASK |
+ UVD_CGC_CTRL__LRBBM_MODE_MASK |
+ UVD_CGC_CTRL__WCB_MODE_MASK |
+ UVD_CGC_CTRL__VCPU_MODE_MASK);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_CGC_CTRL), reg_data, sram_sel, indirect);
+
+ /* turn off clock gating */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_CGC_GATE), 0, sram_sel, indirect);
+
+ /* turn on SUVD clock gating */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_SUVD_CGC_GATE), 1, sram_sel, indirect);
+
+ /* turn on sw mode in UVD_SUVD_CGC_CTRL */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_SUVD_CGC_CTRL), 0, sram_sel, indirect);
+}
+
+/**
+ * vcn_v4_0_3_enable_clock_gating - enable VCN clock gating
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number
+ *
+ * Enable clock gating for VCN block
+ */
+static void vcn_v4_0_3_enable_clock_gating(struct amdgpu_device *adev, int inst_idx)
+{
+ uint32_t data;
+ int vcn_inst;
+
+ if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
+ return;
+
+ vcn_inst = GET_INST(VCN, inst_idx);
+
+ /* enable VCN CGC */
+ data = RREG32_SOC15(VCN, vcn_inst, regUVD_CGC_CTRL);
+ data |= 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+ data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+ data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_CGC_CTRL, data);
+
+ data = RREG32_SOC15(VCN, vcn_inst, regUVD_CGC_CTRL);
+ data |= (UVD_CGC_CTRL__SYS_MODE_MASK
+ | UVD_CGC_CTRL__MPEG2_MODE_MASK
+ | UVD_CGC_CTRL__REGS_MODE_MASK
+ | UVD_CGC_CTRL__RBC_MODE_MASK
+ | UVD_CGC_CTRL__LMI_MC_MODE_MASK
+ | UVD_CGC_CTRL__LMI_UMC_MODE_MASK
+ | UVD_CGC_CTRL__MPC_MODE_MASK
+ | UVD_CGC_CTRL__LBSI_MODE_MASK
+ | UVD_CGC_CTRL__LRBBM_MODE_MASK
+ | UVD_CGC_CTRL__WCB_MODE_MASK
+ | UVD_CGC_CTRL__VCPU_MODE_MASK);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_CGC_CTRL, data);
+
+ data = RREG32_SOC15(VCN, vcn_inst, regUVD_SUVD_CGC_CTRL);
+ data |= (UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__IME_MODE_MASK
+ | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_SUVD_CGC_CTRL, data);
+}
+
+/**
+ * vcn_v4_0_3_start_dpg_mode - VCN start with dpg mode
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number index
+ * @indirect: indirectly write sram
+ *
+ * Start VCN block with dpg mode
+ */
+static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
+{
+ volatile struct amdgpu_vcn4_fw_shared *fw_shared =
+ adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
+ struct amdgpu_ring *ring;
+ int vcn_inst;
+ uint32_t tmp;
+
+ vcn_inst = GET_INST(VCN, inst_idx);
+ /* disable register anti-hang mechanism */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_POWER_STATUS), 1,
+ ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+ /* enable dynamic power gating mode */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_POWER_STATUS);
+ tmp |= UVD_POWER_STATUS__UVD_PG_MODE_MASK;
+ tmp |= UVD_POWER_STATUS__UVD_PG_EN_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_POWER_STATUS, tmp);
+
+ if (indirect) {
+ DRM_DEV_DEBUG(adev->dev, "VCN %d start: on AID %d",
+ inst_idx, adev->vcn.inst[inst_idx].aid_id);
+ adev->vcn.inst[inst_idx].dpg_sram_curr_addr =
+ (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
+ /* Use dummy register 0xDEADBEEF passing AID selection to PSP FW */
+ WREG32_SOC15_DPG_MODE(inst_idx, 0xDEADBEEF,
+ adev->vcn.inst[inst_idx].aid_id, 0, true);
+ }
+
+ /* enable clock gating */
+ vcn_v4_0_3_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
+
+ /* enable VCPU clock */
+ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
+ tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
+ tmp |= UVD_VCPU_CNTL__BLK_RST_MASK;
+
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CNTL), tmp, 0, indirect);
+
+ /* disable master interrupt */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_MASTINT_EN), 0, 0, indirect);
+
+ /* setup regUVD_LMI_CTRL */
+ tmp = (UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+ UVD_LMI_CTRL__REQ_MODE_MASK |
+ UVD_LMI_CTRL__CRC_RESET_MASK |
+ UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+ UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+ UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK |
+ (8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |
+ 0x00100000L);
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_CTRL), tmp, 0, indirect);
+
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_MPC_CNTL),
+ 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT, 0, indirect);
+
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_MPC_SET_MUXA0),
+ ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
+ (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
+ (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
+ (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)), 0, indirect);
+
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_MPC_SET_MUXB0),
+ ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
+ (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
+ (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
+ (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)), 0, indirect);
+
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_MPC_SET_MUX),
+ ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
+ (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
+ (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
+
+ vcn_v4_0_3_mc_resume_dpg_mode(adev, inst_idx, indirect);
+
+ tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
+ tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_VCPU_CNTL), tmp, 0, indirect);
+
+ /* enable LMI MC and UMC channels */
+ tmp = 0x1f << UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM__SHIFT;
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_LMI_CTRL2), tmp, 0, indirect);
+
+ vcn_v4_0_3_enable_ras(adev, inst_idx, indirect);
+
+ /* enable master interrupt */
+ WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
+ VCN, 0, regUVD_MASTINT_EN),
+ UVD_MASTINT_EN__VCPU_EN_MASK, 0, indirect);
+
+ if (indirect)
+ psp_update_vcn_sram(adev, 0, adev->vcn.inst[inst_idx].dpg_sram_gpu_addr,
+ (uint32_t)((uintptr_t)adev->vcn.inst[inst_idx].dpg_sram_curr_addr -
+ (uintptr_t)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr));
+
+ ring = &adev->vcn.inst[inst_idx].ring_enc[0];
+
+ /* program the RB_BASE for ring buffer */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO,
+ lower_32_bits(ring->gpu_addr));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI,
+ upper_32_bits(ring->gpu_addr));
+
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE,
+ ring->ring_size / sizeof(uint32_t));
+
+ /* resetting ring, fw should not check RB ring */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
+ tmp &= ~(VCN_RB_ENABLE__RB_EN_MASK);
+ WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
+ fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
+
+ /* Initialize the ring buffer's read and write pointers */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
+ ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
+
+ tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
+ tmp |= VCN_RB_ENABLE__RB_EN_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
+ fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
+
+ /*resetting done, fw can check RB ring */
+ fw_shared->sq.queue_mode &= cpu_to_le32(~FW_QUEUE_RING_RESET);
+
+ return 0;
+}
+
+/**
+ * vcn_v4_0_3_start - VCN start
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Start VCN block
+ */
+static int vcn_v4_0_3_start(struct amdgpu_device *adev)
+{
+ volatile struct amdgpu_vcn4_fw_shared *fw_shared;
+ struct amdgpu_ring *ring;
+ int i, j, k, r, vcn_inst;
+ uint32_t tmp;
+
+ if (adev->pm.dpm_enabled)
+ amdgpu_dpm_enable_uvd(adev, true);
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+ r = vcn_v4_0_3_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
+ continue;
+ }
+
+ vcn_inst = GET_INST(VCN, i);
+ /* set VCN status busy */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) |
+ UVD_STATUS__UVD_BUSY;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp);
+
+ /*SW clock gating */
+ vcn_v4_0_3_disable_clock_gating(adev, i);
+
+ /* enable VCPU clock */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
+ UVD_VCPU_CNTL__CLK_EN_MASK,
+ ~UVD_VCPU_CNTL__CLK_EN_MASK);
+
+ /* disable master interrupt */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0,
+ ~UVD_MASTINT_EN__VCPU_EN_MASK);
+
+ /* enable LMI MC and UMC channels */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0,
+ ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
+
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
+ tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+ tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
+
+ /* setup regUVD_LMI_CTRL */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL,
+ tmp | UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+ UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+ UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+ UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
+
+ /* setup regUVD_MPC_CNTL */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL);
+ tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
+ tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_CNTL, tmp);
+
+ /* setup UVD_MPC_SET_MUXA0 */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXA0,
+ ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
+ (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
+ (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
+ (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
+
+ /* setup UVD_MPC_SET_MUXB0 */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUXB0,
+ ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
+ (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
+ (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
+ (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
+
+ /* setup UVD_MPC_SET_MUX */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_MPC_SET_MUX,
+ ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
+ (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
+ (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
+
+ vcn_v4_0_3_mc_resume(adev, i);
+
+ /* VCN global tiling registers */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_GFX8_ADDR_CONFIG,
+ adev->gfx.config.gb_addr_config);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG,
+ adev->gfx.config.gb_addr_config);
+
+ /* unblock VCPU register access */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0,
+ ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+ /* release VCPU reset to boot */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
+ ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+ for (j = 0; j < 10; ++j) {
+ uint32_t status;
+
+ for (k = 0; k < 100; ++k) {
+ status = RREG32_SOC15(VCN, vcn_inst,
+ regUVD_STATUS);
+ if (status & 2)
+ break;
+ mdelay(10);
+ }
+ r = 0;
+ if (status & 2)
+ break;
+
+ DRM_DEV_ERROR(adev->dev,
+ "VCN decode not responding, trying to reset the VCPU!!!\n");
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst,
+ regUVD_VCPU_CNTL),
+ UVD_VCPU_CNTL__BLK_RST_MASK,
+ ~UVD_VCPU_CNTL__BLK_RST_MASK);
+ mdelay(10);
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst,
+ regUVD_VCPU_CNTL),
+ 0, ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+ mdelay(10);
+ r = -1;
+ }
+
+ if (r) {
+ DRM_DEV_ERROR(adev->dev, "VCN decode not responding, giving up!!!\n");
+ return r;
+ }
+
+ /* enable master interrupt */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN),
+ UVD_MASTINT_EN__VCPU_EN_MASK,
+ ~UVD_MASTINT_EN__VCPU_EN_MASK);
+
+ /* clear the busy bit of VCN_STATUS */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0,
+ ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
+
+ ring = &adev->vcn.inst[i].ring_enc[0];
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+
+ /* program the RB_BASE for ring buffer */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO,
+ lower_32_bits(ring->gpu_addr));
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI,
+ upper_32_bits(ring->gpu_addr));
+
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE,
+ ring->ring_size / sizeof(uint32_t));
+
+ /* resetting ring, fw should not check RB ring */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
+ tmp &= ~(VCN_RB_ENABLE__RB_EN_MASK);
+ WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
+
+ /* Initialize the ring buffer's read and write pointers */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
+ WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
+
+ tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
+ tmp |= VCN_RB_ENABLE__RB_EN_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
+
+ ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
+ fw_shared->sq.queue_mode &=
+ cpu_to_le32(~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF));
+
+ }
+ return 0;
+}
+
+/**
+ * vcn_v4_0_3_stop_dpg_mode - VCN stop with dpg mode
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number index
+ *
+ * Stop VCN block with dpg mode
+ */
+static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
+{
+ uint32_t tmp;
+ int vcn_inst;
+
+ vcn_inst = GET_INST(VCN, inst_idx);
+
+ /* Wait for power status to be 1 */
+ SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1,
+ UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+
+ /* wait for read ptr to be equal to write ptr */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR);
+ SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_RB_RPTR, tmp, 0xFFFFFFFF);
+
+ SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1,
+ UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+
+ /* disable dynamic power gating mode */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_POWER_STATUS), 0,
+ ~UVD_POWER_STATUS__UVD_PG_MODE_MASK);
+ return 0;
+}
+
+/**
+ * vcn_v4_0_3_stop - VCN stop
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Stop VCN block
+ */
+static int vcn_v4_0_3_stop(struct amdgpu_device *adev)
+{
+ volatile struct amdgpu_vcn4_fw_shared *fw_shared;
+ int i, r = 0, vcn_inst;
+ uint32_t tmp;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ vcn_inst = GET_INST(VCN, i);
+
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+ fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
+
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+ vcn_v4_0_3_stop_dpg_mode(adev, i);
+ continue;
+ }
+
+ /* wait for vcn idle */
+ r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS,
+ UVD_STATUS__IDLE, 0x7);
+ if (r)
+ goto Done;
+
+ tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
+ UVD_LMI_STATUS__READ_CLEAN_MASK |
+ UVD_LMI_STATUS__WRITE_CLEAN_MASK |
+ UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
+ r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp,
+ tmp);
+ if (r)
+ goto Done;
+
+ /* stall UMC channel */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2);
+ tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp);
+ tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
+ UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
+ r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp,
+ tmp);
+ if (r)
+ goto Done;
+
+ /* Unblock VCPU Register access */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL),
+ UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
+ ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+
+ /* release VCPU reset to boot */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL),
+ UVD_VCPU_CNTL__BLK_RST_MASK,
+ ~UVD_VCPU_CNTL__BLK_RST_MASK);
+
+ /* disable VCPU clock */
+ WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0,
+ ~(UVD_VCPU_CNTL__CLK_EN_MASK));
+
+ /* reset LMI UMC/LMI/VCPU */
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
+ tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
+
+ tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET);
+ tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+ WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp);
+
+ /* clear VCN status */
+ WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0);
+
+ /* apply HW clock gating */
+ vcn_v4_0_3_enable_clock_gating(adev, i);
+ }
+Done:
+ if (adev->pm.dpm_enabled)
+ amdgpu_dpm_enable_uvd(adev, false);
+
+ return 0;
+}
+
+/**
+ * vcn_v4_0_3_pause_dpg_mode - VCN pause with dpg mode
+ *
+ * @adev: amdgpu_device pointer
+ * @inst_idx: instance number index
+ * @new_state: pause state
+ *
+ * Pause dpg mode for VCN block
+ */
+static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,
+ struct dpg_pause_state *new_state)
+{
+
+ return 0;
+}
+
+/**
+ * vcn_v4_0_3_unified_ring_get_rptr - get unified read pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Returns the current hardware unified read pointer
+ */
+static uint64_t vcn_v4_0_3_unified_ring_get_rptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
+ DRM_ERROR("wrong ring id is identified in %s", __func__);
+
+ return RREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_RPTR);
+}
+
+/**
+ * vcn_v4_0_3_unified_ring_get_wptr - get unified write pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Returns the current hardware unified write pointer
+ */
+static uint64_t vcn_v4_0_3_unified_ring_get_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
+ DRM_ERROR("wrong ring id is identified in %s", __func__);
+
+ if (ring->use_doorbell)
+ return *ring->wptr_cpu_addr;
+ else
+ return RREG32_SOC15(VCN, GET_INST(VCN, ring->me),
+ regUVD_RB_WPTR);
+}
+
+/**
+ * vcn_v4_0_3_unified_ring_set_wptr - set enc write pointer
+ *
+ * @ring: amdgpu_ring pointer
+ *
+ * Commits the enc write pointer to the hardware
+ */
+static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
+ DRM_ERROR("wrong ring id is identified in %s", __func__);
+
+ if (ring->use_doorbell) {
+ *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);
+ WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
+ } else {
+ WREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_WPTR,
+ lower_32_bits(ring->wptr));
+ }
+}
+
+static const struct amdgpu_ring_funcs vcn_v4_0_3_unified_ring_vm_funcs = {
+ .type = AMDGPU_RING_TYPE_VCN_ENC,
+ .align_mask = 0x3f,
+ .nop = VCN_ENC_CMD_NO_OP,
+ .get_rptr = vcn_v4_0_3_unified_ring_get_rptr,
+ .get_wptr = vcn_v4_0_3_unified_ring_get_wptr,
+ .set_wptr = vcn_v4_0_3_unified_ring_set_wptr,
+ .emit_frame_size =
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 +
+ 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */
+ 5 + 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */
+ 1, /* vcn_v2_0_enc_ring_insert_end */
+ .emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */
+ .emit_ib = vcn_v2_0_enc_ring_emit_ib,
+ .emit_fence = vcn_v2_0_enc_ring_emit_fence,
+ .emit_vm_flush = vcn_v2_0_enc_ring_emit_vm_flush,
+ .test_ring = amdgpu_vcn_enc_ring_test_ring,
+ .test_ib = amdgpu_vcn_unified_ring_test_ib,
+ .insert_nop = amdgpu_ring_insert_nop,
+ .insert_end = vcn_v2_0_enc_ring_insert_end,
+ .pad_ib = amdgpu_ring_generic_pad_ib,
+ .begin_use = amdgpu_vcn_ring_begin_use,
+ .end_use = amdgpu_vcn_ring_end_use,
+ .emit_wreg = vcn_v2_0_enc_ring_emit_wreg,
+ .emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,
+ .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+};
+
+/**
+ * vcn_v4_0_3_set_unified_ring_funcs - set unified ring functions
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Set unified ring functions
+ */
+static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev)
+{
+ int i, vcn_inst;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v4_0_3_unified_ring_vm_funcs;
+ adev->vcn.inst[i].ring_enc[0].me = i;
+ vcn_inst = GET_INST(VCN, i);
+ adev->vcn.inst[i].aid_id =
+ vcn_inst / adev->vcn.num_inst_per_aid;
+ }
+ DRM_DEV_INFO(adev->dev, "VCN decode is enabled in VM mode\n");
+}
+
+/**
+ * vcn_v4_0_3_is_idle - check VCN block is idle
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Check whether VCN block is idle
+ */
+static bool vcn_v4_0_3_is_idle(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i, ret = 1;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ ret &= (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) ==
+ UVD_STATUS__IDLE);
+ }
+
+ return ret;
+}
+
+/**
+ * vcn_v4_0_3_wait_for_idle - wait for VCN block idle
+ *
+ * @handle: amdgpu_device pointer
+ *
+ * Wait for VCN block idle
+ */
+static int vcn_v4_0_3_wait_for_idle(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int i, ret = 0;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ ret = SOC15_WAIT_ON_RREG(VCN, GET_INST(VCN, i), regUVD_STATUS,
+ UVD_STATUS__IDLE, UVD_STATUS__IDLE);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+/* vcn_v4_0_3_set_clockgating_state - set VCN block clockgating state
+ *
+ * @handle: amdgpu_device pointer
+ * @state: clock gating state
+ *
+ * Set VCN block clockgating state
+ */
+static int vcn_v4_0_3_set_clockgating_state(void *handle,
+ enum amd_clockgating_state state)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
+ int i;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (enable) {
+ if (RREG32_SOC15(VCN, GET_INST(VCN, i),
+ regUVD_STATUS) != UVD_STATUS__IDLE)
+ return -EBUSY;
+ vcn_v4_0_3_enable_clock_gating(adev, i);
+ } else {
+ vcn_v4_0_3_disable_clock_gating(adev, i);
+ }
+ }
+ return 0;
+}
+
+/**
+ * vcn_v4_0_3_set_powergating_state - set VCN block powergating state
+ *
+ * @handle: amdgpu_device pointer
+ * @state: power gating state
+ *
+ * Set VCN block powergating state
+ */
+static int vcn_v4_0_3_set_powergating_state(void *handle,
+ enum amd_powergating_state state)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
+
+ if (state == adev->vcn.cur_state)
+ return 0;
+
+ if (state == AMD_PG_STATE_GATE)
+ ret = vcn_v4_0_3_stop(adev);
+ else
+ ret = vcn_v4_0_3_start(adev);
+
+ if (!ret)
+ adev->vcn.cur_state = state;
+
+ return ret;
+}
+
+/**
+ * vcn_v4_0_3_set_interrupt_state - set VCN block interrupt state
+ *
+ * @adev: amdgpu_device pointer
+ * @source: interrupt sources
+ * @type: interrupt types
+ * @state: interrupt states
+ *
+ * Set VCN block interrupt state
+ */
+static int vcn_v4_0_3_set_interrupt_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ unsigned int type,
+ enum amdgpu_interrupt_state state)
+{
+ return 0;
+}
+
+/**
+ * vcn_v4_0_3_process_interrupt - process VCN block interrupt
+ *
+ * @adev: amdgpu_device pointer
+ * @source: interrupt sources
+ * @entry: interrupt entry from clients and sources
+ *
+ * Process VCN block interrupt
+ */
+static int vcn_v4_0_3_process_interrupt(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ uint32_t i, inst;
+
+ i = node_id_to_phys_map[entry->node_id];
+
+ DRM_DEV_DEBUG(adev->dev, "IH: VCN TRAP\n");
+
+ for (inst = 0; inst < adev->vcn.num_vcn_inst; ++inst)
+ if (adev->vcn.inst[inst].aid_id == i)
+ break;
+
+ if (inst >= adev->vcn.num_vcn_inst) {
+ dev_WARN_ONCE(adev->dev, 1,
+ "Interrupt received for unknown VCN instance %d",
+ entry->node_id);
+ return 0;
+ }
+
+ switch (entry->src_id) {
+ case VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE:
+ amdgpu_fence_process(&adev->vcn.inst[inst].ring_enc[0]);
+ break;
+ default:
+ DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",
+ entry->src_id, entry->src_data[0]);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct amdgpu_irq_src_funcs vcn_v4_0_3_irq_funcs = {
+ .set = vcn_v4_0_3_set_interrupt_state,
+ .process = vcn_v4_0_3_process_interrupt,
+};
+
+/**
+ * vcn_v4_0_3_set_irq_funcs - set VCN block interrupt irq functions
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Set VCN block interrupt irq functions
+ */
+static void vcn_v4_0_3_set_irq_funcs(struct amdgpu_device *adev)
+{
+ int i;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ adev->vcn.inst->irq.num_types++;
+ }
+ adev->vcn.inst->irq.funcs = &vcn_v4_0_3_irq_funcs;
+}
+
+static const struct amd_ip_funcs vcn_v4_0_3_ip_funcs = {
+ .name = "vcn_v4_0_3",
+ .early_init = vcn_v4_0_3_early_init,
+ .late_init = NULL,
+ .sw_init = vcn_v4_0_3_sw_init,
+ .sw_fini = vcn_v4_0_3_sw_fini,
+ .hw_init = vcn_v4_0_3_hw_init,
+ .hw_fini = vcn_v4_0_3_hw_fini,
+ .suspend = vcn_v4_0_3_suspend,
+ .resume = vcn_v4_0_3_resume,
+ .is_idle = vcn_v4_0_3_is_idle,
+ .wait_for_idle = vcn_v4_0_3_wait_for_idle,
+ .check_soft_reset = NULL,
+ .pre_soft_reset = NULL,
+ .soft_reset = NULL,
+ .post_soft_reset = NULL,
+ .set_clockgating_state = vcn_v4_0_3_set_clockgating_state,
+ .set_powergating_state = vcn_v4_0_3_set_powergating_state,
+};
+
+const struct amdgpu_ip_block_version vcn_v4_0_3_ip_block = {
+ .type = AMD_IP_BLOCK_TYPE_VCN,
+ .major = 4,
+ .minor = 0,
+ .rev = 3,
+ .funcs = &vcn_v4_0_3_ip_funcs,
+};
+
+static const struct amdgpu_ras_err_status_reg_entry vcn_v4_0_3_ue_reg_list[] = {
+ {AMDGPU_RAS_REG_ENTRY(VCN, 0, regVCN_UE_ERR_STATUS_LO_VIDD, regVCN_UE_ERR_STATUS_HI_VIDD),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "VIDD"},
+ {AMDGPU_RAS_REG_ENTRY(VCN, 0, regVCN_UE_ERR_STATUS_LO_VIDV, regVCN_UE_ERR_STATUS_HI_VIDV),
+ 1, (AMDGPU_RAS_ERR_INFO_VALID | AMDGPU_RAS_ERR_STATUS_VALID), "VIDV"},
+};
+
+static void vcn_v4_0_3_inst_query_ras_error_count(struct amdgpu_device *adev,
+ uint32_t vcn_inst,
+ void *ras_err_status)
+{
+ struct ras_err_data *err_data = (struct ras_err_data *)ras_err_status;
+
+ /* vcn v4_0_3 only support query uncorrectable errors */
+ amdgpu_ras_inst_query_ras_error_count(adev,
+ vcn_v4_0_3_ue_reg_list,
+ ARRAY_SIZE(vcn_v4_0_3_ue_reg_list),
+ NULL, 0, GET_INST(VCN, vcn_inst),
+ AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
+ &err_data->ue_count);
+}
+
+static void vcn_v4_0_3_query_ras_error_count(struct amdgpu_device *adev,
+ void *ras_err_status)
+{
+ uint32_t i;
+
+ if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) {
+ dev_warn(adev->dev, "VCN RAS is not supported\n");
+ return;
+ }
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++)
+ vcn_v4_0_3_inst_query_ras_error_count(adev, i, ras_err_status);
+}
+
+static void vcn_v4_0_3_inst_reset_ras_error_count(struct amdgpu_device *adev,
+ uint32_t vcn_inst)
+{
+ amdgpu_ras_inst_reset_ras_error_count(adev,
+ vcn_v4_0_3_ue_reg_list,
+ ARRAY_SIZE(vcn_v4_0_3_ue_reg_list),
+ GET_INST(VCN, vcn_inst));
+}
+
+static void vcn_v4_0_3_reset_ras_error_count(struct amdgpu_device *adev)
+{
+ uint32_t i;
+
+ if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) {
+ dev_warn(adev->dev, "VCN RAS is not supported\n");
+ return;
+ }
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++)
+ vcn_v4_0_3_inst_reset_ras_error_count(adev, i);
+}
+
+static const struct amdgpu_ras_block_hw_ops vcn_v4_0_3_ras_hw_ops = {
+ .query_ras_error_count = vcn_v4_0_3_query_ras_error_count,
+ .reset_ras_error_count = vcn_v4_0_3_reset_ras_error_count,
+};
+
+static struct amdgpu_vcn_ras vcn_v4_0_3_ras = {
+ .ras_block = {
+ .hw_ops = &vcn_v4_0_3_ras_hw_ops,
+ },
+};
+
+static void vcn_v4_0_3_set_ras_funcs(struct amdgpu_device *adev)
+{
+ adev->vcn.ras = &vcn_v4_0_3_ras;
+}
+
+static void vcn_v4_0_3_enable_ras(struct amdgpu_device *adev,
+ int inst_idx, bool indirect)
+{
+ uint32_t tmp;
+
+ if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN))
+ return;
+
+ tmp = VCN_RAS_CNTL__VCPU_VCODEC_REARM_MASK |
+ VCN_RAS_CNTL__VCPU_VCODEC_IH_EN_MASK |
+ VCN_RAS_CNTL__VCPU_VCODEC_PMI_EN_MASK |
+ VCN_RAS_CNTL__VCPU_VCODEC_STALL_EN_MASK;
+ WREG32_SOC15_DPG_MODE(inst_idx,
+ SOC15_DPG_MODE_OFFSET(VCN, 0, regVCN_RAS_CNTL),
+ tmp, 0, indirect);
+
+ tmp = UVD_SYS_INT_EN__RASCNTL_VCPU_VCODEC_EN_MASK;
+ WREG32_SOC15_DPG_MODE(inst_idx,
+ SOC15_DPG_MODE_OFFSET(VCN, 0, regUVD_SYS_INT_EN),
+ tmp, 0, indirect);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h
new file mode 100644
index 000000000000..0b046114373a
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __VCN_V4_0_3_H__
+#define __VCN_V4_0_3_H__
+
+extern const struct amdgpu_ip_block_version vcn_v4_0_3_ip_block;
+
+#endif /* __VCN_V4_0_3_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
index 536128447b71..4d719df376a7 100644
--- a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
@@ -334,7 +334,8 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)
vega20_setup_retry_doorbell(adev->irq.retry_cam_doorbell_index));
/* Enable IH Retry CAM */
- if (adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 0))
+ if (adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 0) ||
+ adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 2))
WREG32_FIELD15(OSSSYS, 0, IH_RETRY_INT_CAM_CNTL_ALDEBARAN,
ENABLE, 1);
else
@@ -526,6 +527,7 @@ static int vega20_ih_early_init(void *handle)
static int vega20_ih_sw_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ bool use_bus_addr = true;
int r;
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0,
@@ -533,14 +535,18 @@ static int vega20_ih_sw_init(void *handle)
if (r)
return r;
- r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, true);
+ if ((adev->flags & AMD_IS_APU) &&
+ (adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 2)))
+ use_bus_addr = false;
+
+ r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, use_bus_addr);
if (r)
return r;
adev->irq.ih.use_doorbell = true;
adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
- r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
+ r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, use_bus_addr);
if (r)
return r;
@@ -559,7 +565,7 @@ static int vega20_ih_sw_init(void *handle)
/* initialize ih control registers offset */
vega20_ih_init_register_offset(adev);
- r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, PAGE_SIZE, true);
+ r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, PAGE_SIZE, use_bus_addr);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index c0360dbebd4b..6a8494f98d3e 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -587,11 +587,6 @@ void vi_srbm_select(struct amdgpu_device *adev,
WREG32(mmSRBM_GFX_CNTL, srbm_gfx_cntl);
}
-static void vi_vga_set_state(struct amdgpu_device *adev, bool state)
-{
- /* todo */
-}
-
static bool vi_read_disabled_bios(struct amdgpu_device *adev)
{
u32 bus_cntl;
@@ -769,12 +764,12 @@ static uint32_t vi_get_register_value(struct amdgpu_device *adev,
mutex_lock(&adev->grbm_idx_mutex);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff, 0);
val = RREG32(reg_offset);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
- amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
return val;
} else {
@@ -1442,7 +1437,6 @@ static const struct amdgpu_asic_funcs vi_asic_funcs =
.read_register = &vi_read_register,
.reset = &vi_asic_reset,
.reset_method = &vi_asic_reset_method,
- .set_vga_state = &vi_vga_set_state,
.get_xclk = &vi_get_xclk,
.set_uvd_clocks = &vi_set_uvd_clocks,
.set_vce_clocks = &vi_set_vce_clocks,
diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile
index e758c2a24cd0..2ec8f27c5366 100644
--- a/drivers/gpu/drm/amd/amdkfd/Makefile
+++ b/drivers/gpu/drm/amd/amdkfd/Makefile
@@ -53,9 +53,11 @@ AMDKFD_FILES := $(AMDKFD_PATH)/kfd_module.o \
$(AMDKFD_PATH)/kfd_events.o \
$(AMDKFD_PATH)/cik_event_interrupt.o \
$(AMDKFD_PATH)/kfd_int_process_v9.o \
+ $(AMDKFD_PATH)/kfd_int_process_v10.o \
$(AMDKFD_PATH)/kfd_int_process_v11.o \
$(AMDKFD_PATH)/kfd_smi_events.o \
- $(AMDKFD_PATH)/kfd_crat.o
+ $(AMDKFD_PATH)/kfd_crat.o \
+ $(AMDKFD_PATH)/kfd_debug.o
ifneq ($(CONFIG_AMD_IOMMU_V2),)
AMDKFD_FILES += $(AMDKFD_PATH)/kfd_iommu.o
diff --git a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
index 5c8023cba196..795382b55e0a 100644
--- a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
+++ b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
@@ -26,7 +26,7 @@
#include "amdgpu_amdkfd.h"
#include "kfd_smi_events.h"
-static bool cik_event_interrupt_isr(struct kfd_dev *dev,
+static bool cik_event_interrupt_isr(struct kfd_node *dev,
const uint32_t *ih_ring_entry,
uint32_t *patched_ihre,
bool *patched_flag)
@@ -85,7 +85,7 @@ static bool cik_event_interrupt_isr(struct kfd_dev *dev,
!amdgpu_no_queue_eviction_on_vm_fault);
}
-static void cik_event_interrupt_wq(struct kfd_dev *dev,
+static void cik_event_interrupt_wq(struct kfd_node *dev,
const uint32_t *ih_ring_entry)
{
const struct cik_ih_ring_entry *ihre =
@@ -118,9 +118,9 @@ static void cik_event_interrupt_wq(struct kfd_dev *dev,
return;
if (info.vmid == vmid)
- kfd_signal_vm_fault_event(dev, pasid, &info);
+ kfd_signal_vm_fault_event(dev, pasid, &info, NULL);
else
- kfd_signal_vm_fault_event(dev, pasid, NULL);
+ kfd_signal_vm_fault_event(dev, pasid, NULL, NULL);
}
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 1b54a9aaae70..6a27b000a246 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -44,6 +44,7 @@
#include "amdgpu_amdkfd.h"
#include "kfd_smi_events.h"
#include "amdgpu_dma_buf.h"
+#include "kfd_debug.h"
static long kfd_ioctl(struct file *, unsigned int, unsigned long);
static int kfd_open(struct inode *, struct file *);
@@ -142,15 +143,13 @@ static int kfd_open(struct inode *inode, struct file *filep)
return -EPERM;
}
- process = kfd_create_process(filep);
+ process = kfd_create_process(current);
if (IS_ERR(process))
return PTR_ERR(process);
- if (kfd_is_locked()) {
- dev_dbg(kfd_device, "kfd is locked!\n"
- "process %d unreferenced", process->pasid);
+ if (kfd_process_init_cwsr_apu(process, filep)) {
kfd_unref_process(process);
- return -EAGAIN;
+ return -EFAULT;
}
/* filep now owns the reference returned by kfd_create_process */
@@ -186,7 +185,12 @@ static int kfd_ioctl_get_version(struct file *filep, struct kfd_process *p,
static int set_queue_properties_from_user(struct queue_properties *q_properties,
struct kfd_ioctl_create_queue_args *args)
{
- if (args->queue_percentage > KFD_MAX_QUEUE_PERCENTAGE) {
+ /*
+ * Repurpose queue percentage to accommodate new features:
+ * bit 0-7: queue percentage
+ * bit 8-15: pm4_target_xcc
+ */
+ if ((args->queue_percentage & 0xFF) > KFD_MAX_QUEUE_PERCENTAGE) {
pr_err("Queue percentage must be between 0 to KFD_MAX_QUEUE_PERCENTAGE\n");
return -EINVAL;
}
@@ -236,7 +240,9 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties,
q_properties->is_interop = false;
q_properties->is_gws = false;
- q_properties->queue_percent = args->queue_percentage;
+ q_properties->queue_percent = args->queue_percentage & 0xFF;
+ /* bit 8-15 are repurposed to be PM4 target XCC */
+ q_properties->pm4_target_xcc = (args->queue_percentage >> 8) & 0xFF;
q_properties->priority = args->queue_priority;
q_properties->queue_address = args->ring_base_address;
q_properties->queue_size = args->ring_size;
@@ -293,7 +299,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
void *data)
{
struct kfd_ioctl_create_queue_args *args = data;
- struct kfd_dev *dev;
+ struct kfd_node *dev;
int err = 0;
unsigned int queue_id;
struct kfd_process_device *pdd;
@@ -328,7 +334,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
}
if (!pdd->doorbell_index &&
- kfd_alloc_process_doorbells(dev, &pdd->doorbell_index) < 0) {
+ kfd_alloc_process_doorbells(dev->kfd, &pdd->doorbell_index) < 0) {
err = -ENOMEM;
goto err_alloc_doorbells;
}
@@ -336,7 +342,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
/* Starting with GFX11, wptr BOs must be mapped to GART for MES to determine work
* on unmapped queues for usermode queue oversubscription (no aggregated doorbell)
*/
- if (dev->shared_resources.enable_mes &&
+ if (dev->kfd->shared_resources.enable_mes &&
((dev->adev->mes.sched_version & AMDGPU_MES_API_VERSION_MASK)
>> AMDGPU_MES_API_VERSION_SHIFT) >= 2) {
struct amdgpu_bo_va_mapping *wptr_mapping;
@@ -404,6 +410,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
pr_debug("Write ptr address == 0x%016llX\n",
args->write_pointer_address);
+ kfd_dbg_ev_raise(KFD_EC_MASK(EC_QUEUE_NEW), p, dev, queue_id, false, NULL, 0);
return 0;
err_create_queue:
@@ -442,7 +449,12 @@ static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p,
struct kfd_ioctl_update_queue_args *args = data;
struct queue_properties properties;
- if (args->queue_percentage > KFD_MAX_QUEUE_PERCENTAGE) {
+ /*
+ * Repurpose queue percentage to accommodate new features:
+ * bit 0-7: queue percentage
+ * bit 8-15: pm4_target_xcc
+ */
+ if ((args->queue_percentage & 0xFF) > KFD_MAX_QUEUE_PERCENTAGE) {
pr_err("Queue percentage must be between 0 to KFD_MAX_QUEUE_PERCENTAGE\n");
return -EINVAL;
}
@@ -466,7 +478,9 @@ static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p,
properties.queue_address = args->ring_base_address;
properties.queue_size = args->ring_size;
- properties.queue_percent = args->queue_percentage;
+ properties.queue_percent = args->queue_percentage & 0xFF;
+ /* bit 8-15 are repurposed to be PM4 target XCC */
+ properties.pm4_target_xcc = (args->queue_percentage >> 8) & 0xFF;
properties.priority = args->queue_priority;
pr_debug("Updating queue id %d for pasid 0x%x\n",
@@ -524,8 +538,6 @@ static int kfd_ioctl_set_cu_mask(struct file *filp, struct kfd_process *p,
goto out;
}
- minfo.update_flag = UPDATE_FLAG_CU_MASK;
-
mutex_lock(&p->mutex);
retval = pqm_update_mqd(&p->pqm, args->queue_id, &minfo);
@@ -887,7 +899,7 @@ static int kfd_ioctl_set_scratch_backing_va(struct file *filep,
{
struct kfd_ioctl_set_scratch_backing_va_args *args = data;
struct kfd_process_device *pdd;
- struct kfd_dev *dev;
+ struct kfd_node *dev;
long err;
mutex_lock(&p->mutex);
@@ -1006,19 +1018,26 @@ err_drm_file:
return ret;
}
-bool kfd_dev_is_large_bar(struct kfd_dev *dev)
+bool kfd_dev_is_large_bar(struct kfd_node *dev)
{
if (debug_largebar) {
pr_debug("Simulate large-bar allocation on non large-bar machine\n");
return true;
}
- if (dev->use_iommu_v2)
+ if (dev->kfd->use_iommu_v2)
return false;
if (dev->local_mem_info.local_mem_size_private == 0 &&
- dev->local_mem_info.local_mem_size_public > 0)
+ dev->local_mem_info.local_mem_size_public > 0)
+ return true;
+
+ if (dev->local_mem_info.local_mem_size_public == 0 &&
+ dev->kfd->adev->gmc.is_app_apu) {
+ pr_debug("APP APU, Consider like a large bar system\n");
return true;
+ }
+
return false;
}
@@ -1030,7 +1049,8 @@ static int kfd_ioctl_get_available_memory(struct file *filep,
if (!pdd)
return -EINVAL;
- args->available = amdgpu_amdkfd_get_available_memory(pdd->dev->adev);
+ args->available = amdgpu_amdkfd_get_available_memory(pdd->dev->adev,
+ pdd->dev->node_id);
kfd_unlock_pdd(pdd);
return 0;
}
@@ -1041,7 +1061,7 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep,
struct kfd_ioctl_alloc_memory_of_gpu_args *args = data;
struct kfd_process_device *pdd;
void *mem;
- struct kfd_dev *dev;
+ struct kfd_node *dev;
int idr_handle;
long err;
uint64_t offset = args->mmap_offset;
@@ -1105,7 +1125,7 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep,
}
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) {
- if (args->size != kfd_doorbell_process_slice(dev)) {
+ if (args->size != kfd_doorbell_process_slice(dev->kfd)) {
err = -EINVAL;
goto err_unlock;
}
@@ -1231,7 +1251,7 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
struct kfd_ioctl_map_memory_to_gpu_args *args = data;
struct kfd_process_device *pdd, *peer_pdd;
void *mem;
- struct kfd_dev *dev;
+ struct kfd_node *dev;
long err = 0;
int i;
uint32_t *devices_arr = NULL;
@@ -1405,7 +1425,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
args->n_success = i+1;
}
- flush_tlb = kfd_flush_tlb_after_unmap(pdd->dev);
+ flush_tlb = kfd_flush_tlb_after_unmap(pdd->dev->kfd);
if (flush_tlb) {
err = amdgpu_amdkfd_gpuvm_sync_memory(pdd->dev->adev,
(struct kgd_mem *) mem, true);
@@ -1445,7 +1465,7 @@ static int kfd_ioctl_alloc_queue_gws(struct file *filep,
int retval;
struct kfd_ioctl_alloc_queue_gws_args *args = data;
struct queue *q;
- struct kfd_dev *dev;
+ struct kfd_node *dev;
mutex_lock(&p->mutex);
q = pqm_get_user_queue(&p->pqm, args->queue_id);
@@ -1467,6 +1487,11 @@ static int kfd_ioctl_alloc_queue_gws(struct file *filep,
goto out_unlock;
}
+ if (!kfd_dbg_has_gws_support(dev) && p->debug_trap_enabled) {
+ retval = -EBUSY;
+ goto out_unlock;
+ }
+
retval = pqm_set_gws(&p->pqm, args->queue_id, args->num_gws ? dev->gws : NULL);
mutex_unlock(&p->mutex);
@@ -1482,10 +1507,11 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
struct kfd_process *p, void *data)
{
struct kfd_ioctl_get_dmabuf_info_args *args = data;
- struct kfd_dev *dev = NULL;
+ struct kfd_node *dev = NULL;
struct amdgpu_device *dmabuf_adev;
void *metadata_buffer = NULL;
uint32_t flags;
+ int8_t xcp_id;
unsigned int i;
int r;
@@ -1506,17 +1532,14 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
r = amdgpu_amdkfd_get_dmabuf_info(dev->adev, args->dmabuf_fd,
&dmabuf_adev, &args->size,
metadata_buffer, args->metadata_size,
- &args->metadata_size, &flags);
+ &args->metadata_size, &flags, &xcp_id);
if (r)
goto exit;
- /* Reverse-lookup gpu_id from kgd pointer */
- dev = kfd_device_by_adev(dmabuf_adev);
- if (!dev) {
- r = -EINVAL;
- goto exit;
- }
- args->gpu_id = dev->id;
+ if (xcp_id >= 0)
+ args->gpu_id = dmabuf_adev->kfd.dev->nodes[xcp_id]->id;
+ else
+ args->gpu_id = dmabuf_adev->kfd.dev->nodes[0]->id;
args->flags = flags;
/* Copy metadata buffer to user mode */
@@ -1596,7 +1619,7 @@ static int kfd_ioctl_export_dmabuf(struct file *filep,
struct kfd_ioctl_export_dmabuf_args *args = data;
struct kfd_process_device *pdd;
struct dma_buf *dmabuf;
- struct kfd_dev *dev;
+ struct kfd_node *dev;
void *mem;
int ret = 0;
@@ -2178,7 +2201,7 @@ static int criu_restore_devices(struct kfd_process *p,
}
for (i = 0; i < args->num_devices; i++) {
- struct kfd_dev *dev;
+ struct kfd_node *dev;
struct kfd_process_device *pdd;
struct file *drm_file;
@@ -2240,7 +2263,7 @@ static int criu_restore_devices(struct kfd_process *p,
}
if (!pdd->doorbell_index &&
- kfd_alloc_process_doorbells(pdd->dev, &pdd->doorbell_index) < 0) {
+ kfd_alloc_process_doorbells(pdd->dev->kfd, &pdd->doorbell_index) < 0) {
ret = -ENOMEM;
goto exit;
}
@@ -2268,7 +2291,8 @@ static int criu_restore_memory_of_gpu(struct kfd_process_device *pdd,
u64 offset;
if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) {
- if (bo_bucket->size != kfd_doorbell_process_slice(pdd->dev))
+ if (bo_bucket->size !=
+ kfd_doorbell_process_slice(pdd->dev->kfd))
return -EINVAL;
offset = kfd_get_process_doorbells(pdd);
@@ -2350,7 +2374,7 @@ static int criu_restore_bo(struct kfd_process *p,
/* now map these BOs to GPU/s */
for (j = 0; j < p->n_pdds; j++) {
- struct kfd_dev *peer;
+ struct kfd_node *peer;
struct kfd_process_device *peer_pdd;
if (!bo_priv->mapped_gpuids[j])
@@ -2715,6 +2739,356 @@ static int kfd_ioctl_criu(struct file *filep, struct kfd_process *p, void *data)
return ret;
}
+static int runtime_enable(struct kfd_process *p, uint64_t r_debug,
+ bool enable_ttmp_setup)
+{
+ int i = 0, ret = 0;
+
+ if (p->is_runtime_retry)
+ goto retry;
+
+ if (p->runtime_info.runtime_state != DEBUG_RUNTIME_STATE_DISABLED)
+ return -EBUSY;
+
+ for (i = 0; i < p->n_pdds; i++) {
+ struct kfd_process_device *pdd = p->pdds[i];
+
+ if (pdd->qpd.queue_count)
+ return -EEXIST;
+ }
+
+ p->runtime_info.runtime_state = DEBUG_RUNTIME_STATE_ENABLED;
+ p->runtime_info.r_debug = r_debug;
+ p->runtime_info.ttmp_setup = enable_ttmp_setup;
+
+ if (p->runtime_info.ttmp_setup) {
+ for (i = 0; i < p->n_pdds; i++) {
+ struct kfd_process_device *pdd = p->pdds[i];
+
+ if (!kfd_dbg_is_rlc_restore_supported(pdd->dev)) {
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, false);
+ pdd->dev->kfd2kgd->enable_debug_trap(
+ pdd->dev->adev,
+ true,
+ pdd->dev->vm_info.last_vmid_kfd);
+ } else if (kfd_dbg_is_per_vmid_supported(pdd->dev)) {
+ pdd->spi_dbg_override = pdd->dev->kfd2kgd->enable_debug_trap(
+ pdd->dev->adev,
+ false,
+ 0);
+ }
+ }
+ }
+
+retry:
+ if (p->debug_trap_enabled) {
+ if (!p->is_runtime_retry) {
+ kfd_dbg_trap_activate(p);
+ kfd_dbg_ev_raise(KFD_EC_MASK(EC_PROCESS_RUNTIME),
+ p, NULL, 0, false, NULL, 0);
+ }
+
+ mutex_unlock(&p->mutex);
+ ret = down_interruptible(&p->runtime_enable_sema);
+ mutex_lock(&p->mutex);
+
+ p->is_runtime_retry = !!ret;
+ }
+
+ return ret;
+}
+
+static int runtime_disable(struct kfd_process *p)
+{
+ int i = 0, ret;
+ bool was_enabled = p->runtime_info.runtime_state == DEBUG_RUNTIME_STATE_ENABLED;
+
+ p->runtime_info.runtime_state = DEBUG_RUNTIME_STATE_DISABLED;
+ p->runtime_info.r_debug = 0;
+
+ if (p->debug_trap_enabled) {
+ if (was_enabled)
+ kfd_dbg_trap_deactivate(p, false, 0);
+
+ if (!p->is_runtime_retry)
+ kfd_dbg_ev_raise(KFD_EC_MASK(EC_PROCESS_RUNTIME),
+ p, NULL, 0, false, NULL, 0);
+
+ mutex_unlock(&p->mutex);
+ ret = down_interruptible(&p->runtime_enable_sema);
+ mutex_lock(&p->mutex);
+
+ p->is_runtime_retry = !!ret;
+ if (ret)
+ return ret;
+ }
+
+ if (was_enabled && p->runtime_info.ttmp_setup) {
+ for (i = 0; i < p->n_pdds; i++) {
+ struct kfd_process_device *pdd = p->pdds[i];
+
+ if (!kfd_dbg_is_rlc_restore_supported(pdd->dev))
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
+ }
+ }
+
+ p->runtime_info.ttmp_setup = false;
+
+ /* disable ttmp setup */
+ for (i = 0; i < p->n_pdds; i++) {
+ struct kfd_process_device *pdd = p->pdds[i];
+
+ if (kfd_dbg_is_per_vmid_supported(pdd->dev)) {
+ pdd->spi_dbg_override =
+ pdd->dev->kfd2kgd->disable_debug_trap(
+ pdd->dev->adev,
+ false,
+ pdd->dev->vm_info.last_vmid_kfd);
+
+ if (!pdd->dev->kfd->shared_resources.enable_mes)
+ debug_refresh_runlist(pdd->dev->dqm);
+ else
+ kfd_dbg_set_mes_debug_mode(pdd);
+ }
+ }
+
+ return 0;
+}
+
+static int kfd_ioctl_runtime_enable(struct file *filep, struct kfd_process *p, void *data)
+{
+ struct kfd_ioctl_runtime_enable_args *args = data;
+ int r;
+
+ mutex_lock(&p->mutex);
+
+ if (args->mode_mask & KFD_RUNTIME_ENABLE_MODE_ENABLE_MASK)
+ r = runtime_enable(p, args->r_debug,
+ !!(args->mode_mask & KFD_RUNTIME_ENABLE_MODE_TTMP_SAVE_MASK));
+ else
+ r = runtime_disable(p);
+
+ mutex_unlock(&p->mutex);
+
+ return r;
+}
+
+static int kfd_ioctl_set_debug_trap(struct file *filep, struct kfd_process *p, void *data)
+{
+ struct kfd_ioctl_dbg_trap_args *args = data;
+ struct task_struct *thread = NULL;
+ struct mm_struct *mm = NULL;
+ struct pid *pid = NULL;
+ struct kfd_process *target = NULL;
+ struct kfd_process_device *pdd = NULL;
+ int r = 0;
+
+ if (sched_policy == KFD_SCHED_POLICY_NO_HWS) {
+ pr_err("Debugging does not support sched_policy %i", sched_policy);
+ return -EINVAL;
+ }
+
+ pid = find_get_pid(args->pid);
+ if (!pid) {
+ pr_debug("Cannot find pid info for %i\n", args->pid);
+ r = -ESRCH;
+ goto out;
+ }
+
+ thread = get_pid_task(pid, PIDTYPE_PID);
+ if (!thread) {
+ r = -ESRCH;
+ goto out;
+ }
+
+ mm = get_task_mm(thread);
+ if (!mm) {
+ r = -ESRCH;
+ goto out;
+ }
+
+ if (args->op == KFD_IOC_DBG_TRAP_ENABLE) {
+ bool create_process;
+
+ rcu_read_lock();
+ create_process = thread && thread != current && ptrace_parent(thread) == current;
+ rcu_read_unlock();
+
+ target = create_process ? kfd_create_process(thread) :
+ kfd_lookup_process_by_pid(pid);
+ } else {
+ target = kfd_lookup_process_by_pid(pid);
+ }
+
+ if (IS_ERR_OR_NULL(target)) {
+ pr_debug("Cannot find process PID %i to debug\n", args->pid);
+ r = target ? PTR_ERR(target) : -ESRCH;
+ goto out;
+ }
+
+ /* Check if target is still PTRACED. */
+ rcu_read_lock();
+ if (target != p && args->op != KFD_IOC_DBG_TRAP_DISABLE
+ && ptrace_parent(target->lead_thread) != current) {
+ pr_err("PID %i is not PTRACED and cannot be debugged\n", args->pid);
+ r = -EPERM;
+ }
+ rcu_read_unlock();
+
+ if (r)
+ goto out;
+
+ mutex_lock(&target->mutex);
+
+ if (args->op != KFD_IOC_DBG_TRAP_ENABLE && !target->debug_trap_enabled) {
+ pr_err("PID %i not debug enabled for op %i\n", args->pid, args->op);
+ r = -EINVAL;
+ goto unlock_out;
+ }
+
+ if (target->runtime_info.runtime_state != DEBUG_RUNTIME_STATE_ENABLED &&
+ (args->op == KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_OVERRIDE ||
+ args->op == KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_MODE ||
+ args->op == KFD_IOC_DBG_TRAP_SUSPEND_QUEUES ||
+ args->op == KFD_IOC_DBG_TRAP_RESUME_QUEUES ||
+ args->op == KFD_IOC_DBG_TRAP_SET_NODE_ADDRESS_WATCH ||
+ args->op == KFD_IOC_DBG_TRAP_CLEAR_NODE_ADDRESS_WATCH ||
+ args->op == KFD_IOC_DBG_TRAP_SET_FLAGS)) {
+ r = -EPERM;
+ goto unlock_out;
+ }
+
+ if (args->op == KFD_IOC_DBG_TRAP_SET_NODE_ADDRESS_WATCH ||
+ args->op == KFD_IOC_DBG_TRAP_CLEAR_NODE_ADDRESS_WATCH) {
+ int user_gpu_id = kfd_process_get_user_gpu_id(target,
+ args->op == KFD_IOC_DBG_TRAP_SET_NODE_ADDRESS_WATCH ?
+ args->set_node_address_watch.gpu_id :
+ args->clear_node_address_watch.gpu_id);
+
+ pdd = kfd_process_device_data_by_id(target, user_gpu_id);
+ if (user_gpu_id == -EINVAL || !pdd) {
+ r = -ENODEV;
+ goto unlock_out;
+ }
+ }
+
+ switch (args->op) {
+ case KFD_IOC_DBG_TRAP_ENABLE:
+ if (target != p)
+ target->debugger_process = p;
+
+ r = kfd_dbg_trap_enable(target,
+ args->enable.dbg_fd,
+ (void __user *)args->enable.rinfo_ptr,
+ &args->enable.rinfo_size);
+ if (!r)
+ target->exception_enable_mask = args->enable.exception_mask;
+
+ break;
+ case KFD_IOC_DBG_TRAP_DISABLE:
+ r = kfd_dbg_trap_disable(target);
+ break;
+ case KFD_IOC_DBG_TRAP_SEND_RUNTIME_EVENT:
+ r = kfd_dbg_send_exception_to_runtime(target,
+ args->send_runtime_event.gpu_id,
+ args->send_runtime_event.queue_id,
+ args->send_runtime_event.exception_mask);
+ break;
+ case KFD_IOC_DBG_TRAP_SET_EXCEPTIONS_ENABLED:
+ kfd_dbg_set_enabled_debug_exception_mask(target,
+ args->set_exceptions_enabled.exception_mask);
+ break;
+ case KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_OVERRIDE:
+ r = kfd_dbg_trap_set_wave_launch_override(target,
+ args->launch_override.override_mode,
+ args->launch_override.enable_mask,
+ args->launch_override.support_request_mask,
+ &args->launch_override.enable_mask,
+ &args->launch_override.support_request_mask);
+ break;
+ case KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_MODE:
+ r = kfd_dbg_trap_set_wave_launch_mode(target,
+ args->launch_mode.launch_mode);
+ break;
+ case KFD_IOC_DBG_TRAP_SUSPEND_QUEUES:
+ r = suspend_queues(target,
+ args->suspend_queues.num_queues,
+ args->suspend_queues.grace_period,
+ args->suspend_queues.exception_mask,
+ (uint32_t *)args->suspend_queues.queue_array_ptr);
+
+ break;
+ case KFD_IOC_DBG_TRAP_RESUME_QUEUES:
+ r = resume_queues(target, args->resume_queues.num_queues,
+ (uint32_t *)args->resume_queues.queue_array_ptr);
+ break;
+ case KFD_IOC_DBG_TRAP_SET_NODE_ADDRESS_WATCH:
+ r = kfd_dbg_trap_set_dev_address_watch(pdd,
+ args->set_node_address_watch.address,
+ args->set_node_address_watch.mask,
+ &args->set_node_address_watch.id,
+ args->set_node_address_watch.mode);
+ break;
+ case KFD_IOC_DBG_TRAP_CLEAR_NODE_ADDRESS_WATCH:
+ r = kfd_dbg_trap_clear_dev_address_watch(pdd,
+ args->clear_node_address_watch.id);
+ break;
+ case KFD_IOC_DBG_TRAP_SET_FLAGS:
+ r = kfd_dbg_trap_set_flags(target, &args->set_flags.flags);
+ break;
+ case KFD_IOC_DBG_TRAP_QUERY_DEBUG_EVENT:
+ r = kfd_dbg_ev_query_debug_event(target,
+ &args->query_debug_event.queue_id,
+ &args->query_debug_event.gpu_id,
+ args->query_debug_event.exception_mask,
+ &args->query_debug_event.exception_mask);
+ break;
+ case KFD_IOC_DBG_TRAP_QUERY_EXCEPTION_INFO:
+ r = kfd_dbg_trap_query_exception_info(target,
+ args->query_exception_info.source_id,
+ args->query_exception_info.exception_code,
+ args->query_exception_info.clear_exception,
+ (void __user *)args->query_exception_info.info_ptr,
+ &args->query_exception_info.info_size);
+ break;
+ case KFD_IOC_DBG_TRAP_GET_QUEUE_SNAPSHOT:
+ r = pqm_get_queue_snapshot(&target->pqm,
+ args->queue_snapshot.exception_mask,
+ (void __user *)args->queue_snapshot.snapshot_buf_ptr,
+ &args->queue_snapshot.num_queues,
+ &args->queue_snapshot.entry_size);
+ break;
+ case KFD_IOC_DBG_TRAP_GET_DEVICE_SNAPSHOT:
+ r = kfd_dbg_trap_device_snapshot(target,
+ args->device_snapshot.exception_mask,
+ (void __user *)args->device_snapshot.snapshot_buf_ptr,
+ &args->device_snapshot.num_devices,
+ &args->device_snapshot.entry_size);
+ break;
+ default:
+ pr_err("Invalid option: %i\n", args->op);
+ r = -EINVAL;
+ }
+
+unlock_out:
+ mutex_unlock(&target->mutex);
+
+out:
+ if (thread)
+ put_task_struct(thread);
+
+ if (mm)
+ mmput(mm);
+
+ if (pid)
+ put_pid(pid);
+
+ if (target)
+ kfd_unref_process(target);
+
+ return r;
+}
+
#define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \
[_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \
.cmd_drv = 0, .name = #ioctl}
@@ -2827,6 +3201,12 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = {
AMDKFD_IOCTL_DEF(AMDKFD_IOC_EXPORT_DMABUF,
kfd_ioctl_export_dmabuf, 0),
+
+ AMDKFD_IOCTL_DEF(AMDKFD_IOC_RUNTIME_ENABLE,
+ kfd_ioctl_runtime_enable, 0),
+
+ AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_TRAP,
+ kfd_ioctl_set_debug_trap, 0),
};
#define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls)
@@ -2947,7 +3327,7 @@ err_i1:
return retcode;
}
-static int kfd_mmio_mmap(struct kfd_dev *dev, struct kfd_process *process,
+static int kfd_mmio_mmap(struct kfd_node *dev, struct kfd_process *process,
struct vm_area_struct *vma)
{
phys_addr_t address;
@@ -2981,7 +3361,7 @@ static int kfd_mmio_mmap(struct kfd_dev *dev, struct kfd_process *process,
static int kfd_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct kfd_process *process;
- struct kfd_dev *dev = NULL;
+ struct kfd_node *dev = NULL;
unsigned long mmap_offset;
unsigned int gpu_id;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index 475e47027354..49f40d9f16e8 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -1166,7 +1166,7 @@ static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink,
if (props->iolink_type == CRAT_IOLINK_TYPE_PCIEXPRESS)
props->weight = 20;
else if (props->iolink_type == CRAT_IOLINK_TYPE_XGMI)
- props->weight = 15 * iolink->num_hops_xgmi;
+ props->weight = iolink->weight_xgmi;
else
props->weight = node_distance(id_from, id_to);
@@ -1405,7 +1405,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
return i;
}
-int kfd_get_gpu_cache_info(struct kfd_dev *kdev, struct kfd_gpu_cache_info **pcache_info)
+int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pcache_info)
{
int num_of_cache_types = 0;
@@ -1524,7 +1524,7 @@ int kfd_get_gpu_cache_info(struct kfd_dev *kdev, struct kfd_gpu_cache_info **pca
case IP_VERSION(11, 0, 3):
case IP_VERSION(11, 0, 4):
num_of_cache_types =
- kfd_fill_gpu_cache_info_from_gfx_config(kdev, *pcache_info);
+ kfd_fill_gpu_cache_info_from_gfx_config(kdev->kfd, *pcache_info);
break;
default:
*pcache_info = dummy_cache_info;
@@ -1858,7 +1858,7 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
}
static int kfd_fill_gpu_memory_affinity(int *avail_size,
- struct kfd_dev *kdev, uint8_t type, uint64_t size,
+ struct kfd_node *kdev, uint8_t type, uint64_t size,
struct crat_subtype_memory *sub_type_hdr,
uint32_t proximity_domain,
const struct kfd_local_mem_info *local_mem_info)
@@ -1887,7 +1887,7 @@ static int kfd_fill_gpu_memory_affinity(int *avail_size,
}
#ifdef CONFIG_ACPI_NUMA
-static void kfd_find_numa_node_in_srat(struct kfd_dev *kdev)
+static void kfd_find_numa_node_in_srat(struct kfd_node *kdev)
{
struct acpi_table_header *table_header = NULL;
struct acpi_subtable_header *sub_header = NULL;
@@ -1972,6 +1972,9 @@ static void kfd_find_numa_node_in_srat(struct kfd_dev *kdev)
}
#endif
+#define KFD_CRAT_INTRA_SOCKET_WEIGHT 13
+#define KFD_CRAT_XGMI_WEIGHT 15
+
/* kfd_fill_gpu_direct_io_link - Fill in direct io link from GPU
* to its NUMA node
* @avail_size: Available size in the memory
@@ -1982,7 +1985,7 @@ static void kfd_find_numa_node_in_srat(struct kfd_dev *kdev)
* Return 0 if successful else return -ve value
*/
static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size,
- struct kfd_dev *kdev,
+ struct kfd_node *kdev,
struct crat_subtype_iolink *sub_type_hdr,
uint32_t proximity_domain)
{
@@ -2002,7 +2005,16 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size,
/* Fill in IOLINK subtype.
* TODO: Fill-in other fields of iolink subtype
*/
- if (kdev->adev->gmc.xgmi.connected_to_cpu) {
+ if (kdev->adev->gmc.xgmi.connected_to_cpu ||
+ (KFD_GC_VERSION(kdev) == IP_VERSION(9, 4, 3) &&
+ kdev->adev->smuio.funcs->get_pkg_type(kdev->adev) ==
+ AMDGPU_PKG_TYPE_APU)) {
+ bool ext_cpu = KFD_GC_VERSION(kdev) != IP_VERSION(9, 4, 3);
+ int mem_bw = 819200, weight = ext_cpu ? KFD_CRAT_XGMI_WEIGHT :
+ KFD_CRAT_INTRA_SOCKET_WEIGHT;
+ uint32_t bandwidth = ext_cpu ? amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(
+ kdev->adev, NULL, true) : mem_bw;
+
/*
* with host gpu xgmi link, host can access gpu memory whether
* or not pcie bar type is large, so always create bidirectional
@@ -2010,14 +2022,9 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size,
*/
sub_type_hdr->flags |= CRAT_IOLINK_FLAGS_BI_DIRECTIONAL;
sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_XGMI;
- sub_type_hdr->num_hops_xgmi = 1;
- if (KFD_GC_VERSION(kdev) == IP_VERSION(9, 4, 2)) {
- sub_type_hdr->minimum_bandwidth_mbs =
- amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(
- kdev->adev, NULL, true);
- sub_type_hdr->maximum_bandwidth_mbs =
- sub_type_hdr->minimum_bandwidth_mbs;
- }
+ sub_type_hdr->weight_xgmi = weight;
+ sub_type_hdr->minimum_bandwidth_mbs = bandwidth;
+ sub_type_hdr->maximum_bandwidth_mbs = bandwidth;
} else {
sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_PCIEXPRESS;
sub_type_hdr->minimum_bandwidth_mbs =
@@ -2029,7 +2036,8 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size,
sub_type_hdr->proximity_domain_from = proximity_domain;
#ifdef CONFIG_ACPI_NUMA
- if (kdev->adev->pdev->dev.numa_node == NUMA_NO_NODE)
+ if (kdev->adev->pdev->dev.numa_node == NUMA_NO_NODE &&
+ num_possible_nodes() > 1)
kfd_find_numa_node_in_srat(kdev);
#endif
#ifdef CONFIG_NUMA
@@ -2044,12 +2052,14 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size,
}
static int kfd_fill_gpu_xgmi_link_to_gpu(int *avail_size,
- struct kfd_dev *kdev,
- struct kfd_dev *peer_kdev,
+ struct kfd_node *kdev,
+ struct kfd_node *peer_kdev,
struct crat_subtype_iolink *sub_type_hdr,
uint32_t proximity_domain_from,
uint32_t proximity_domain_to)
{
+ bool use_ta_info = kdev->kfd->num_nodes == 1;
+
*avail_size -= sizeof(struct crat_subtype_iolink);
if (*avail_size < 0)
return -ENOMEM;
@@ -2064,12 +2074,25 @@ static int kfd_fill_gpu_xgmi_link_to_gpu(int *avail_size,
sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_XGMI;
sub_type_hdr->proximity_domain_from = proximity_domain_from;
sub_type_hdr->proximity_domain_to = proximity_domain_to;
- sub_type_hdr->num_hops_xgmi =
- amdgpu_amdkfd_get_xgmi_hops_count(kdev->adev, peer_kdev->adev);
- sub_type_hdr->maximum_bandwidth_mbs =
- amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->adev, peer_kdev->adev, false);
- sub_type_hdr->minimum_bandwidth_mbs = sub_type_hdr->maximum_bandwidth_mbs ?
- amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->adev, NULL, true) : 0;
+
+ if (use_ta_info) {
+ sub_type_hdr->weight_xgmi = KFD_CRAT_XGMI_WEIGHT *
+ amdgpu_amdkfd_get_xgmi_hops_count(kdev->adev, peer_kdev->adev);
+ sub_type_hdr->maximum_bandwidth_mbs =
+ amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->adev,
+ peer_kdev->adev, false);
+ sub_type_hdr->minimum_bandwidth_mbs = sub_type_hdr->maximum_bandwidth_mbs ?
+ amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->adev, NULL, true) : 0;
+ } else {
+ bool is_single_hop = kdev->kfd == peer_kdev->kfd;
+ int weight = is_single_hop ? KFD_CRAT_INTRA_SOCKET_WEIGHT :
+ (2 * KFD_CRAT_INTRA_SOCKET_WEIGHT) + KFD_CRAT_XGMI_WEIGHT;
+ int mem_bw = 819200;
+
+ sub_type_hdr->weight_xgmi = weight;
+ sub_type_hdr->maximum_bandwidth_mbs = is_single_hop ? mem_bw : 0;
+ sub_type_hdr->minimum_bandwidth_mbs = is_single_hop ? mem_bw : 0;
+ }
return 0;
}
@@ -2081,7 +2104,7 @@ static int kfd_fill_gpu_xgmi_link_to_gpu(int *avail_size,
* [OUT] actual size of data filled in crat_image
*/
static int kfd_create_vcrat_image_gpu(void *pcrat_image,
- size_t *size, struct kfd_dev *kdev,
+ size_t *size, struct kfd_node *kdev,
uint32_t proximity_domain)
{
struct crat_header *crat_table = (struct crat_header *)pcrat_image;
@@ -2153,7 +2176,7 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
/* Check if this node supports IOMMU. During parsing this flag will
* translate to HSA_CAP_ATS_PRESENT
*/
- if (!kfd_iommu_check_device(kdev))
+ if (!kfd_iommu_check_device(kdev->kfd))
cu->hsa_capability |= CRAT_CU_FLAGS_IOMMU_PRESENT;
crat_table->length += sub_type_hdr->length;
@@ -2216,12 +2239,12 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
* (from other GPU to this GPU) will be added
* in kfd_parse_subtype_iolink.
*/
- if (kdev->hive_id) {
+ if (kdev->kfd->hive_id) {
for (nid = 0; nid < proximity_domain; ++nid) {
peer_dev = kfd_topology_device_by_proximity_domain_no_lock(nid);
if (!peer_dev->gpu)
continue;
- if (peer_dev->gpu->hive_id != kdev->hive_id)
+ if (peer_dev->gpu->kfd->hive_id != kdev->kfd->hive_id)
continue;
sub_type_hdr = (typeof(sub_type_hdr))(
(char *)sub_type_hdr +
@@ -2255,12 +2278,12 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
* (COMPUTE_UNIT_CPU | COMPUTE_UNIT_GPU) - Create VCRAT for APU
* -- this option is not currently implemented.
* The assumption is that all AMD APUs will have CRAT
- * @kdev: Valid kfd_device required if flags contain COMPUTE_UNIT_GPU
+ * @kdev: Valid kfd_node required if flags contain COMPUTE_UNIT_GPU
*
* Return 0 if successful else return -ve value
*/
int kfd_create_crat_image_virtual(void **crat_image, size_t *size,
- int flags, struct kfd_dev *kdev,
+ int flags, struct kfd_node *kdev,
uint32_t proximity_domain)
{
void *pcrat_image = NULL;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
index 8d1e8ba58dee..fc719389b5d6 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
@@ -275,7 +275,7 @@ struct crat_subtype_iolink {
uint32_t maximum_bandwidth_mbs;
uint32_t recommended_transfer_size;
uint8_t reserved2[CRAT_IOLINK_RESERVED_LENGTH - 1];
- uint8_t num_hops_xgmi;
+ uint8_t weight_xgmi;
};
/*
@@ -293,7 +293,7 @@ struct crat_subtype_generic {
#pragma pack()
-struct kfd_dev;
+struct kfd_node;
/* Static table to describe GPU Cache information */
struct kfd_gpu_cache_info {
@@ -305,14 +305,14 @@ struct kfd_gpu_cache_info {
*/
uint32_t num_cu_shared;
};
-int kfd_get_gpu_cache_info(struct kfd_dev *kdev, struct kfd_gpu_cache_info **pcache_info);
+int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pcache_info);
int kfd_create_crat_image_acpi(void **crat_image, size_t *size);
void kfd_destroy_crat_image(void *crat_image);
int kfd_parse_crat_table(void *crat_image, struct list_head *device_list,
uint32_t proximity_domain);
int kfd_create_crat_image_virtual(void **crat_image, size_t *size,
- int flags, struct kfd_dev *kdev,
+ int flags, struct kfd_node *kdev,
uint32_t proximity_domain);
#endif /* KFD_CRAT_H_INCLUDED */
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debug.c b/drivers/gpu/drm/amd/amdkfd/kfd_debug.c
new file mode 100644
index 000000000000..fff3ccc04fa9
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_debug.c
@@ -0,0 +1,1118 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "kfd_debug.h"
+#include "kfd_device_queue_manager.h"
+#include "kfd_topology.h"
+#include <linux/file.h>
+#include <uapi/linux/kfd_ioctl.h>
+
+#define MAX_WATCH_ADDRESSES 4
+
+int kfd_dbg_ev_query_debug_event(struct kfd_process *process,
+ unsigned int *queue_id,
+ unsigned int *gpu_id,
+ uint64_t exception_clear_mask,
+ uint64_t *event_status)
+{
+ struct process_queue_manager *pqm;
+ struct process_queue_node *pqn;
+ int i;
+
+ if (!(process && process->debug_trap_enabled))
+ return -ENODATA;
+
+ mutex_lock(&process->event_mutex);
+ *event_status = 0;
+ *queue_id = 0;
+ *gpu_id = 0;
+
+ /* find and report queue events */
+ pqm = &process->pqm;
+ list_for_each_entry(pqn, &pqm->queues, process_queue_list) {
+ uint64_t tmp = process->exception_enable_mask;
+
+ if (!pqn->q)
+ continue;
+
+ tmp &= pqn->q->properties.exception_status;
+
+ if (!tmp)
+ continue;
+
+ *event_status = pqn->q->properties.exception_status;
+ *queue_id = pqn->q->properties.queue_id;
+ *gpu_id = pqn->q->device->id;
+ pqn->q->properties.exception_status &= ~exception_clear_mask;
+ goto out;
+ }
+
+ /* find and report device events */
+ for (i = 0; i < process->n_pdds; i++) {
+ struct kfd_process_device *pdd = process->pdds[i];
+ uint64_t tmp = process->exception_enable_mask
+ & pdd->exception_status;
+
+ if (!tmp)
+ continue;
+
+ *event_status = pdd->exception_status;
+ *gpu_id = pdd->dev->id;
+ pdd->exception_status &= ~exception_clear_mask;
+ goto out;
+ }
+
+ /* report process events */
+ if (process->exception_enable_mask & process->exception_status) {
+ *event_status = process->exception_status;
+ process->exception_status &= ~exception_clear_mask;
+ }
+
+out:
+ mutex_unlock(&process->event_mutex);
+ return *event_status ? 0 : -EAGAIN;
+}
+
+void debug_event_write_work_handler(struct work_struct *work)
+{
+ struct kfd_process *process;
+
+ static const char write_data = '.';
+ loff_t pos = 0;
+
+ process = container_of(work,
+ struct kfd_process,
+ debug_event_workarea);
+
+ kernel_write(process->dbg_ev_file, &write_data, 1, &pos);
+}
+
+/* update process/device/queue exception status, write to descriptor
+ * only if exception_status is enabled.
+ */
+bool kfd_dbg_ev_raise(uint64_t event_mask,
+ struct kfd_process *process, struct kfd_node *dev,
+ unsigned int source_id, bool use_worker,
+ void *exception_data, size_t exception_data_size)
+{
+ struct process_queue_manager *pqm;
+ struct process_queue_node *pqn;
+ int i;
+ static const char write_data = '.';
+ loff_t pos = 0;
+ bool is_subscribed = true;
+
+ if (!(process && process->debug_trap_enabled))
+ return false;
+
+ mutex_lock(&process->event_mutex);
+
+ if (event_mask & KFD_EC_MASK_DEVICE) {
+ for (i = 0; i < process->n_pdds; i++) {
+ struct kfd_process_device *pdd = process->pdds[i];
+
+ if (pdd->dev != dev)
+ continue;
+
+ pdd->exception_status |= event_mask & KFD_EC_MASK_DEVICE;
+
+ if (event_mask & KFD_EC_MASK(EC_DEVICE_MEMORY_VIOLATION)) {
+ if (!pdd->vm_fault_exc_data) {
+ pdd->vm_fault_exc_data = kmemdup(
+ exception_data,
+ exception_data_size,
+ GFP_KERNEL);
+ if (!pdd->vm_fault_exc_data)
+ pr_debug("Failed to allocate exception data memory");
+ } else {
+ pr_debug("Debugger exception data not saved\n");
+ print_hex_dump_bytes("exception data: ",
+ DUMP_PREFIX_OFFSET,
+ exception_data,
+ exception_data_size);
+ }
+ }
+ break;
+ }
+ } else if (event_mask & KFD_EC_MASK_PROCESS) {
+ process->exception_status |= event_mask & KFD_EC_MASK_PROCESS;
+ } else {
+ pqm = &process->pqm;
+ list_for_each_entry(pqn, &pqm->queues,
+ process_queue_list) {
+ int target_id;
+
+ if (!pqn->q)
+ continue;
+
+ target_id = event_mask & KFD_EC_MASK(EC_QUEUE_NEW) ?
+ pqn->q->properties.queue_id :
+ pqn->q->doorbell_id;
+
+ if (pqn->q->device != dev || target_id != source_id)
+ continue;
+
+ pqn->q->properties.exception_status |= event_mask;
+ break;
+ }
+ }
+
+ if (process->exception_enable_mask & event_mask) {
+ if (use_worker)
+ schedule_work(&process->debug_event_workarea);
+ else
+ kernel_write(process->dbg_ev_file,
+ &write_data,
+ 1,
+ &pos);
+ } else {
+ is_subscribed = false;
+ }
+
+ mutex_unlock(&process->event_mutex);
+
+ return is_subscribed;
+}
+
+/* set pending event queue entry from ring entry */
+bool kfd_set_dbg_ev_from_interrupt(struct kfd_node *dev,
+ unsigned int pasid,
+ uint32_t doorbell_id,
+ uint64_t trap_mask,
+ void *exception_data,
+ size_t exception_data_size)
+{
+ struct kfd_process *p;
+ bool signaled_to_debugger_or_runtime = false;
+
+ p = kfd_lookup_process_by_pasid(pasid);
+
+ if (!p)
+ return false;
+
+ if (!kfd_dbg_ev_raise(trap_mask, p, dev, doorbell_id, true,
+ exception_data, exception_data_size)) {
+ struct process_queue_manager *pqm;
+ struct process_queue_node *pqn;
+
+ if (!!(trap_mask & KFD_EC_MASK_QUEUE) &&
+ p->runtime_info.runtime_state == DEBUG_RUNTIME_STATE_ENABLED) {
+ mutex_lock(&p->mutex);
+
+ pqm = &p->pqm;
+ list_for_each_entry(pqn, &pqm->queues,
+ process_queue_list) {
+
+ if (!(pqn->q && pqn->q->device == dev &&
+ pqn->q->doorbell_id == doorbell_id))
+ continue;
+
+ kfd_send_exception_to_runtime(p, pqn->q->properties.queue_id,
+ trap_mask);
+
+ signaled_to_debugger_or_runtime = true;
+
+ break;
+ }
+
+ mutex_unlock(&p->mutex);
+ } else if (trap_mask & KFD_EC_MASK(EC_DEVICE_MEMORY_VIOLATION)) {
+ kfd_dqm_evict_pasid(dev->dqm, p->pasid);
+ kfd_signal_vm_fault_event(dev, p->pasid, NULL,
+ exception_data);
+
+ signaled_to_debugger_or_runtime = true;
+ }
+ } else {
+ signaled_to_debugger_or_runtime = true;
+ }
+
+ kfd_unref_process(p);
+
+ return signaled_to_debugger_or_runtime;
+}
+
+int kfd_dbg_send_exception_to_runtime(struct kfd_process *p,
+ unsigned int dev_id,
+ unsigned int queue_id,
+ uint64_t error_reason)
+{
+ if (error_reason & KFD_EC_MASK(EC_DEVICE_MEMORY_VIOLATION)) {
+ struct kfd_process_device *pdd = NULL;
+ struct kfd_hsa_memory_exception_data *data;
+ int i;
+
+ for (i = 0; i < p->n_pdds; i++) {
+ if (p->pdds[i]->dev->id == dev_id) {
+ pdd = p->pdds[i];
+ break;
+ }
+ }
+
+ if (!pdd)
+ return -ENODEV;
+
+ data = (struct kfd_hsa_memory_exception_data *)
+ pdd->vm_fault_exc_data;
+
+ kfd_dqm_evict_pasid(pdd->dev->dqm, p->pasid);
+ kfd_signal_vm_fault_event(pdd->dev, p->pasid, NULL, data);
+ error_reason &= ~KFD_EC_MASK(EC_DEVICE_MEMORY_VIOLATION);
+ }
+
+ if (error_reason & (KFD_EC_MASK(EC_PROCESS_RUNTIME))) {
+ /*
+ * block should only happen after the debugger receives runtime
+ * enable notice.
+ */
+ up(&p->runtime_enable_sema);
+ error_reason &= ~KFD_EC_MASK(EC_PROCESS_RUNTIME);
+ }
+
+ if (error_reason)
+ return kfd_send_exception_to_runtime(p, queue_id, error_reason);
+
+ return 0;
+}
+
+static int kfd_dbg_set_queue_workaround(struct queue *q, bool enable)
+{
+ struct mqd_update_info minfo = {0};
+ int err;
+
+ if (!q)
+ return 0;
+
+ if (KFD_GC_VERSION(q->device) < IP_VERSION(11, 0, 0) ||
+ KFD_GC_VERSION(q->device) >= IP_VERSION(12, 0, 0))
+ return 0;
+
+ if (enable && q->properties.is_user_cu_masked)
+ return -EBUSY;
+
+ minfo.update_flag = enable ? UPDATE_FLAG_DBG_WA_ENABLE : UPDATE_FLAG_DBG_WA_DISABLE;
+
+ q->properties.is_dbg_wa = enable;
+ err = q->device->dqm->ops.update_queue(q->device->dqm, q, &minfo);
+ if (err)
+ q->properties.is_dbg_wa = false;
+
+ return err;
+}
+
+static int kfd_dbg_set_workaround(struct kfd_process *target, bool enable)
+{
+ struct process_queue_manager *pqm = &target->pqm;
+ struct process_queue_node *pqn;
+ int r = 0;
+
+ list_for_each_entry(pqn, &pqm->queues, process_queue_list) {
+ r = kfd_dbg_set_queue_workaround(pqn->q, enable);
+ if (enable && r)
+ goto unwind;
+ }
+
+ return 0;
+
+unwind:
+ list_for_each_entry(pqn, &pqm->queues, process_queue_list)
+ kfd_dbg_set_queue_workaround(pqn->q, false);
+
+ if (enable)
+ target->runtime_info.runtime_state = r == -EBUSY ?
+ DEBUG_RUNTIME_STATE_ENABLED_BUSY :
+ DEBUG_RUNTIME_STATE_ENABLED_ERROR;
+
+ return r;
+}
+
+int kfd_dbg_set_mes_debug_mode(struct kfd_process_device *pdd)
+{
+ uint32_t spi_dbg_cntl = pdd->spi_dbg_override | pdd->spi_dbg_launch_mode;
+ uint32_t flags = pdd->process->dbg_flags;
+ bool sq_trap_en = !!spi_dbg_cntl;
+
+ if (!kfd_dbg_is_per_vmid_supported(pdd->dev))
+ return 0;
+
+ return amdgpu_mes_set_shader_debugger(pdd->dev->adev, pdd->proc_ctx_gpu_addr, spi_dbg_cntl,
+ pdd->watch_points, flags, sq_trap_en);
+}
+
+#define KFD_DEBUGGER_INVALID_WATCH_POINT_ID -1
+static int kfd_dbg_get_dev_watch_id(struct kfd_process_device *pdd, int *watch_id)
+{
+ int i;
+
+ *watch_id = KFD_DEBUGGER_INVALID_WATCH_POINT_ID;
+
+ spin_lock(&pdd->dev->kfd->watch_points_lock);
+
+ for (i = 0; i < MAX_WATCH_ADDRESSES; i++) {
+ /* device watchpoint in use so skip */
+ if ((pdd->dev->kfd->alloc_watch_ids >> i) & 0x1)
+ continue;
+
+ pdd->alloc_watch_ids |= 0x1 << i;
+ pdd->dev->kfd->alloc_watch_ids |= 0x1 << i;
+ *watch_id = i;
+ spin_unlock(&pdd->dev->kfd->watch_points_lock);
+ return 0;
+ }
+
+ spin_unlock(&pdd->dev->kfd->watch_points_lock);
+
+ return -ENOMEM;
+}
+
+static void kfd_dbg_clear_dev_watch_id(struct kfd_process_device *pdd, int watch_id)
+{
+ spin_lock(&pdd->dev->kfd->watch_points_lock);
+
+ /* process owns device watch point so safe to clear */
+ if ((pdd->alloc_watch_ids >> watch_id) & 0x1) {
+ pdd->alloc_watch_ids &= ~(0x1 << watch_id);
+ pdd->dev->kfd->alloc_watch_ids &= ~(0x1 << watch_id);
+ }
+
+ spin_unlock(&pdd->dev->kfd->watch_points_lock);
+}
+
+static bool kfd_dbg_owns_dev_watch_id(struct kfd_process_device *pdd, int watch_id)
+{
+ bool owns_watch_id = false;
+
+ spin_lock(&pdd->dev->kfd->watch_points_lock);
+ owns_watch_id = watch_id < MAX_WATCH_ADDRESSES &&
+ ((pdd->alloc_watch_ids >> watch_id) & 0x1);
+
+ spin_unlock(&pdd->dev->kfd->watch_points_lock);
+
+ return owns_watch_id;
+}
+
+int kfd_dbg_trap_clear_dev_address_watch(struct kfd_process_device *pdd,
+ uint32_t watch_id)
+{
+ int r;
+
+ if (!kfd_dbg_owns_dev_watch_id(pdd, watch_id))
+ return -EINVAL;
+
+ if (!pdd->dev->kfd->shared_resources.enable_mes) {
+ r = debug_lock_and_unmap(pdd->dev->dqm);
+ if (r)
+ return r;
+ }
+
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, false);
+ pdd->watch_points[watch_id] = pdd->dev->kfd2kgd->clear_address_watch(
+ pdd->dev->adev,
+ watch_id);
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
+
+ if (!pdd->dev->kfd->shared_resources.enable_mes)
+ r = debug_map_and_unlock(pdd->dev->dqm);
+ else
+ r = kfd_dbg_set_mes_debug_mode(pdd);
+
+ kfd_dbg_clear_dev_watch_id(pdd, watch_id);
+
+ return r;
+}
+
+int kfd_dbg_trap_set_dev_address_watch(struct kfd_process_device *pdd,
+ uint64_t watch_address,
+ uint32_t watch_address_mask,
+ uint32_t *watch_id,
+ uint32_t watch_mode)
+{
+ int r = kfd_dbg_get_dev_watch_id(pdd, watch_id);
+
+ if (r)
+ return r;
+
+ if (!pdd->dev->kfd->shared_resources.enable_mes) {
+ r = debug_lock_and_unmap(pdd->dev->dqm);
+ if (r) {
+ kfd_dbg_clear_dev_watch_id(pdd, *watch_id);
+ return r;
+ }
+ }
+
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, false);
+ pdd->watch_points[*watch_id] = pdd->dev->kfd2kgd->set_address_watch(
+ pdd->dev->adev,
+ watch_address,
+ watch_address_mask,
+ *watch_id,
+ watch_mode,
+ pdd->dev->vm_info.last_vmid_kfd);
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
+
+ if (!pdd->dev->kfd->shared_resources.enable_mes)
+ r = debug_map_and_unlock(pdd->dev->dqm);
+ else
+ r = kfd_dbg_set_mes_debug_mode(pdd);
+
+ /* HWS is broken so no point in HW rollback but release the watchpoint anyways */
+ if (r)
+ kfd_dbg_clear_dev_watch_id(pdd, *watch_id);
+
+ return 0;
+}
+
+static void kfd_dbg_clear_process_address_watch(struct kfd_process *target)
+{
+ int i, j;
+
+ for (i = 0; i < target->n_pdds; i++)
+ for (j = 0; j < MAX_WATCH_ADDRESSES; j++)
+ kfd_dbg_trap_clear_dev_address_watch(target->pdds[i], j);
+}
+
+int kfd_dbg_trap_set_flags(struct kfd_process *target, uint32_t *flags)
+{
+ uint32_t prev_flags = target->dbg_flags;
+ int i, r = 0, rewind_count = 0;
+
+ for (i = 0; i < target->n_pdds; i++) {
+ if (!kfd_dbg_is_per_vmid_supported(target->pdds[i]->dev) &&
+ (*flags & KFD_DBG_TRAP_FLAG_SINGLE_MEM_OP)) {
+ *flags = prev_flags;
+ return -EACCES;
+ }
+ }
+
+ target->dbg_flags = *flags & KFD_DBG_TRAP_FLAG_SINGLE_MEM_OP;
+ *flags = prev_flags;
+ for (i = 0; i < target->n_pdds; i++) {
+ struct kfd_process_device *pdd = target->pdds[i];
+
+ if (!kfd_dbg_is_per_vmid_supported(pdd->dev))
+ continue;
+
+ if (!pdd->dev->kfd->shared_resources.enable_mes)
+ r = debug_refresh_runlist(pdd->dev->dqm);
+ else
+ r = kfd_dbg_set_mes_debug_mode(pdd);
+
+ if (r) {
+ target->dbg_flags = prev_flags;
+ break;
+ }
+
+ rewind_count++;
+ }
+
+ /* Rewind flags */
+ if (r) {
+ target->dbg_flags = prev_flags;
+
+ for (i = 0; i < rewind_count; i++) {
+ struct kfd_process_device *pdd = target->pdds[i];
+
+ if (!kfd_dbg_is_per_vmid_supported(pdd->dev))
+ continue;
+
+ if (!pdd->dev->kfd->shared_resources.enable_mes)
+ debug_refresh_runlist(pdd->dev->dqm);
+ else
+ kfd_dbg_set_mes_debug_mode(pdd);
+ }
+ }
+
+ return r;
+}
+
+/* kfd_dbg_trap_deactivate:
+ * target: target process
+ * unwind: If this is unwinding a failed kfd_dbg_trap_enable()
+ * unwind_count:
+ * If unwind == true, how far down the pdd list we need
+ * to unwind
+ * else: ignored
+ */
+void kfd_dbg_trap_deactivate(struct kfd_process *target, bool unwind, int unwind_count)
+{
+ int i;
+
+ if (!unwind) {
+ uint32_t flags = 0;
+ int resume_count = resume_queues(target, 0, NULL);
+
+ if (resume_count)
+ pr_debug("Resumed %d queues\n", resume_count);
+
+ cancel_work_sync(&target->debug_event_workarea);
+ kfd_dbg_clear_process_address_watch(target);
+ kfd_dbg_trap_set_wave_launch_mode(target, 0);
+
+ kfd_dbg_trap_set_flags(target, &flags);
+ }
+
+ for (i = 0; i < target->n_pdds; i++) {
+ struct kfd_process_device *pdd = target->pdds[i];
+
+ /* If this is an unwind, and we have unwound the required
+ * enable calls on the pdd list, we need to stop now
+ * otherwise we may mess up another debugger session.
+ */
+ if (unwind && i == unwind_count)
+ break;
+
+ kfd_process_set_trap_debug_flag(&pdd->qpd, false);
+
+ /* GFX off is already disabled by debug activate if not RLC restore supported. */
+ if (kfd_dbg_is_rlc_restore_supported(pdd->dev))
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, false);
+ pdd->spi_dbg_override =
+ pdd->dev->kfd2kgd->disable_debug_trap(
+ pdd->dev->adev,
+ target->runtime_info.ttmp_setup,
+ pdd->dev->vm_info.last_vmid_kfd);
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
+
+ if (!kfd_dbg_is_per_vmid_supported(pdd->dev) &&
+ release_debug_trap_vmid(pdd->dev->dqm, &pdd->qpd))
+ pr_err("Failed to release debug vmid on [%i]\n", pdd->dev->id);
+
+ if (!pdd->dev->kfd->shared_resources.enable_mes)
+ debug_refresh_runlist(pdd->dev->dqm);
+ else
+ kfd_dbg_set_mes_debug_mode(pdd);
+ }
+
+ kfd_dbg_set_workaround(target, false);
+}
+
+static void kfd_dbg_clean_exception_status(struct kfd_process *target)
+{
+ struct process_queue_manager *pqm;
+ struct process_queue_node *pqn;
+ int i;
+
+ for (i = 0; i < target->n_pdds; i++) {
+ struct kfd_process_device *pdd = target->pdds[i];
+
+ kfd_process_drain_interrupts(pdd);
+
+ pdd->exception_status = 0;
+ }
+
+ pqm = &target->pqm;
+ list_for_each_entry(pqn, &pqm->queues, process_queue_list) {
+ if (!pqn->q)
+ continue;
+
+ pqn->q->properties.exception_status = 0;
+ }
+
+ target->exception_status = 0;
+}
+
+int kfd_dbg_trap_disable(struct kfd_process *target)
+{
+ if (!target->debug_trap_enabled)
+ return 0;
+
+ /*
+ * Defer deactivation to runtime if runtime not enabled otherwise reset
+ * attached running target runtime state to enable for re-attach.
+ */
+ if (target->runtime_info.runtime_state == DEBUG_RUNTIME_STATE_ENABLED)
+ kfd_dbg_trap_deactivate(target, false, 0);
+ else if (target->runtime_info.runtime_state != DEBUG_RUNTIME_STATE_DISABLED)
+ target->runtime_info.runtime_state = DEBUG_RUNTIME_STATE_ENABLED;
+
+ fput(target->dbg_ev_file);
+ target->dbg_ev_file = NULL;
+
+ if (target->debugger_process) {
+ atomic_dec(&target->debugger_process->debugged_process_count);
+ target->debugger_process = NULL;
+ }
+
+ target->debug_trap_enabled = false;
+ kfd_dbg_clean_exception_status(target);
+ kfd_unref_process(target);
+
+ return 0;
+}
+
+int kfd_dbg_trap_activate(struct kfd_process *target)
+{
+ int i, r = 0;
+
+ r = kfd_dbg_set_workaround(target, true);
+ if (r)
+ return r;
+
+ for (i = 0; i < target->n_pdds; i++) {
+ struct kfd_process_device *pdd = target->pdds[i];
+
+ if (!kfd_dbg_is_per_vmid_supported(pdd->dev)) {
+ r = reserve_debug_trap_vmid(pdd->dev->dqm, &pdd->qpd);
+
+ if (r) {
+ target->runtime_info.runtime_state = (r == -EBUSY) ?
+ DEBUG_RUNTIME_STATE_ENABLED_BUSY :
+ DEBUG_RUNTIME_STATE_ENABLED_ERROR;
+
+ goto unwind_err;
+ }
+ }
+
+ /* Disable GFX OFF to prevent garbage read/writes to debug registers.
+ * If RLC restore of debug registers is not supported and runtime enable
+ * hasn't done so already on ttmp setup request, restore the trap config registers.
+ *
+ * If RLC restore of debug registers is not supported, keep gfx off disabled for
+ * the debug session.
+ */
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, false);
+ if (!(kfd_dbg_is_rlc_restore_supported(pdd->dev) ||
+ target->runtime_info.ttmp_setup))
+ pdd->dev->kfd2kgd->enable_debug_trap(pdd->dev->adev, true,
+ pdd->dev->vm_info.last_vmid_kfd);
+
+ pdd->spi_dbg_override = pdd->dev->kfd2kgd->enable_debug_trap(
+ pdd->dev->adev,
+ false,
+ pdd->dev->vm_info.last_vmid_kfd);
+
+ if (kfd_dbg_is_rlc_restore_supported(pdd->dev))
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
+
+ /*
+ * Setting the debug flag in the trap handler requires that the TMA has been
+ * allocated, which occurs during CWSR initialization.
+ * In the event that CWSR has not been initialized at this point, setting the
+ * flag will be called again during CWSR initialization if the target process
+ * is still debug enabled.
+ */
+ kfd_process_set_trap_debug_flag(&pdd->qpd, true);
+
+ if (!pdd->dev->kfd->shared_resources.enable_mes)
+ r = debug_refresh_runlist(pdd->dev->dqm);
+ else
+ r = kfd_dbg_set_mes_debug_mode(pdd);
+
+ if (r) {
+ target->runtime_info.runtime_state =
+ DEBUG_RUNTIME_STATE_ENABLED_ERROR;
+ goto unwind_err;
+ }
+ }
+
+ return 0;
+
+unwind_err:
+ /* Enabling debug failed, we need to disable on
+ * all GPUs so the enable is all or nothing.
+ */
+ kfd_dbg_trap_deactivate(target, true, i);
+ return r;
+}
+
+int kfd_dbg_trap_enable(struct kfd_process *target, uint32_t fd,
+ void __user *runtime_info, uint32_t *runtime_size)
+{
+ struct file *f;
+ uint32_t copy_size;
+ int i, r = 0;
+
+ if (target->debug_trap_enabled)
+ return -EALREADY;
+
+ /* Enable pre-checks */
+ for (i = 0; i < target->n_pdds; i++) {
+ struct kfd_process_device *pdd = target->pdds[i];
+
+ if (!KFD_IS_SOC15(pdd->dev))
+ return -ENODEV;
+
+ if (!kfd_dbg_has_gws_support(pdd->dev) && pdd->qpd.num_gws)
+ return -EBUSY;
+ }
+
+ copy_size = min((size_t)(*runtime_size), sizeof(target->runtime_info));
+
+ f = fget(fd);
+ if (!f) {
+ pr_err("Failed to get file for (%i)\n", fd);
+ return -EBADF;
+ }
+
+ target->dbg_ev_file = f;
+
+ /* defer activation to runtime if not runtime enabled */
+ if (target->runtime_info.runtime_state == DEBUG_RUNTIME_STATE_ENABLED)
+ kfd_dbg_trap_activate(target);
+
+ /* We already hold the process reference but hold another one for the
+ * debug session.
+ */
+ kref_get(&target->ref);
+ target->debug_trap_enabled = true;
+
+ if (target->debugger_process)
+ atomic_inc(&target->debugger_process->debugged_process_count);
+
+ if (copy_to_user(runtime_info, (void *)&target->runtime_info, copy_size)) {
+ kfd_dbg_trap_deactivate(target, false, 0);
+ r = -EFAULT;
+ }
+
+ *runtime_size = sizeof(target->runtime_info);
+
+ return r;
+}
+
+static int kfd_dbg_validate_trap_override_request(struct kfd_process *p,
+ uint32_t trap_override,
+ uint32_t trap_mask_request,
+ uint32_t *trap_mask_supported)
+{
+ int i = 0;
+
+ *trap_mask_supported = 0xffffffff;
+
+ for (i = 0; i < p->n_pdds; i++) {
+ struct kfd_process_device *pdd = p->pdds[i];
+ int err = pdd->dev->kfd2kgd->validate_trap_override_request(
+ pdd->dev->adev,
+ trap_override,
+ trap_mask_supported);
+
+ if (err)
+ return err;
+ }
+
+ if (trap_mask_request & ~*trap_mask_supported)
+ return -EACCES;
+
+ return 0;
+}
+
+int kfd_dbg_trap_set_wave_launch_override(struct kfd_process *target,
+ uint32_t trap_override,
+ uint32_t trap_mask_bits,
+ uint32_t trap_mask_request,
+ uint32_t *trap_mask_prev,
+ uint32_t *trap_mask_supported)
+{
+ int r = 0, i;
+
+ r = kfd_dbg_validate_trap_override_request(target,
+ trap_override,
+ trap_mask_request,
+ trap_mask_supported);
+
+ if (r)
+ return r;
+
+ for (i = 0; i < target->n_pdds; i++) {
+ struct kfd_process_device *pdd = target->pdds[i];
+
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, false);
+ pdd->spi_dbg_override = pdd->dev->kfd2kgd->set_wave_launch_trap_override(
+ pdd->dev->adev,
+ pdd->dev->vm_info.last_vmid_kfd,
+ trap_override,
+ trap_mask_bits,
+ trap_mask_request,
+ trap_mask_prev,
+ pdd->spi_dbg_override);
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
+
+ if (!pdd->dev->kfd->shared_resources.enable_mes)
+ r = debug_refresh_runlist(pdd->dev->dqm);
+ else
+ r = kfd_dbg_set_mes_debug_mode(pdd);
+
+ if (r)
+ break;
+ }
+
+ return r;
+}
+
+int kfd_dbg_trap_set_wave_launch_mode(struct kfd_process *target,
+ uint8_t wave_launch_mode)
+{
+ int r = 0, i;
+
+ if (wave_launch_mode != KFD_DBG_TRAP_WAVE_LAUNCH_MODE_NORMAL &&
+ wave_launch_mode != KFD_DBG_TRAP_WAVE_LAUNCH_MODE_HALT &&
+ wave_launch_mode != KFD_DBG_TRAP_WAVE_LAUNCH_MODE_DEBUG)
+ return -EINVAL;
+
+ for (i = 0; i < target->n_pdds; i++) {
+ struct kfd_process_device *pdd = target->pdds[i];
+
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, false);
+ pdd->spi_dbg_launch_mode = pdd->dev->kfd2kgd->set_wave_launch_mode(
+ pdd->dev->adev,
+ wave_launch_mode,
+ pdd->dev->vm_info.last_vmid_kfd);
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
+
+ if (!pdd->dev->kfd->shared_resources.enable_mes)
+ r = debug_refresh_runlist(pdd->dev->dqm);
+ else
+ r = kfd_dbg_set_mes_debug_mode(pdd);
+
+ if (r)
+ break;
+ }
+
+ return r;
+}
+
+int kfd_dbg_trap_query_exception_info(struct kfd_process *target,
+ uint32_t source_id,
+ uint32_t exception_code,
+ bool clear_exception,
+ void __user *info,
+ uint32_t *info_size)
+{
+ bool found = false;
+ int r = 0;
+ uint32_t copy_size, actual_info_size = 0;
+ uint64_t *exception_status_ptr = NULL;
+
+ if (!target)
+ return -EINVAL;
+
+ if (!info || !info_size)
+ return -EINVAL;
+
+ mutex_lock(&target->event_mutex);
+
+ if (KFD_DBG_EC_TYPE_IS_QUEUE(exception_code)) {
+ /* Per queue exceptions */
+ struct queue *queue = NULL;
+ int i;
+
+ for (i = 0; i < target->n_pdds; i++) {
+ struct kfd_process_device *pdd = target->pdds[i];
+ struct qcm_process_device *qpd = &pdd->qpd;
+
+ list_for_each_entry(queue, &qpd->queues_list, list) {
+ if (!found && queue->properties.queue_id == source_id) {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+
+ if (!found) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (!(queue->properties.exception_status & KFD_EC_MASK(exception_code))) {
+ r = -ENODATA;
+ goto out;
+ }
+ exception_status_ptr = &queue->properties.exception_status;
+ } else if (KFD_DBG_EC_TYPE_IS_DEVICE(exception_code)) {
+ /* Per device exceptions */
+ struct kfd_process_device *pdd = NULL;
+ int i;
+
+ for (i = 0; i < target->n_pdds; i++) {
+ pdd = target->pdds[i];
+ if (pdd->dev->id == source_id) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (!(pdd->exception_status & KFD_EC_MASK(exception_code))) {
+ r = -ENODATA;
+ goto out;
+ }
+
+ if (exception_code == EC_DEVICE_MEMORY_VIOLATION) {
+ copy_size = min((size_t)(*info_size), pdd->vm_fault_exc_data_size);
+
+ if (copy_to_user(info, pdd->vm_fault_exc_data, copy_size)) {
+ r = -EFAULT;
+ goto out;
+ }
+ actual_info_size = pdd->vm_fault_exc_data_size;
+ if (clear_exception) {
+ kfree(pdd->vm_fault_exc_data);
+ pdd->vm_fault_exc_data = NULL;
+ pdd->vm_fault_exc_data_size = 0;
+ }
+ }
+ exception_status_ptr = &pdd->exception_status;
+ } else if (KFD_DBG_EC_TYPE_IS_PROCESS(exception_code)) {
+ /* Per process exceptions */
+ if (!(target->exception_status & KFD_EC_MASK(exception_code))) {
+ r = -ENODATA;
+ goto out;
+ }
+
+ if (exception_code == EC_PROCESS_RUNTIME) {
+ copy_size = min((size_t)(*info_size), sizeof(target->runtime_info));
+
+ if (copy_to_user(info, (void *)&target->runtime_info, copy_size)) {
+ r = -EFAULT;
+ goto out;
+ }
+
+ actual_info_size = sizeof(target->runtime_info);
+ }
+
+ exception_status_ptr = &target->exception_status;
+ } else {
+ pr_debug("Bad exception type [%i]\n", exception_code);
+ r = -EINVAL;
+ goto out;
+ }
+
+ *info_size = actual_info_size;
+ if (clear_exception)
+ *exception_status_ptr &= ~KFD_EC_MASK(exception_code);
+out:
+ mutex_unlock(&target->event_mutex);
+ return r;
+}
+
+int kfd_dbg_trap_device_snapshot(struct kfd_process *target,
+ uint64_t exception_clear_mask,
+ void __user *user_info,
+ uint32_t *number_of_device_infos,
+ uint32_t *entry_size)
+{
+ struct kfd_dbg_device_info_entry device_info;
+ uint32_t tmp_entry_size = *entry_size, tmp_num_devices;
+ int i, r = 0;
+
+ if (!(target && user_info && number_of_device_infos && entry_size))
+ return -EINVAL;
+
+ tmp_num_devices = min_t(size_t, *number_of_device_infos, target->n_pdds);
+ *number_of_device_infos = target->n_pdds;
+ *entry_size = min_t(size_t, *entry_size, sizeof(device_info));
+
+ if (!tmp_num_devices)
+ return 0;
+
+ memset(&device_info, 0, sizeof(device_info));
+
+ mutex_lock(&target->event_mutex);
+
+ /* Run over all pdd of the process */
+ for (i = 0; i < tmp_num_devices; i++) {
+ struct kfd_process_device *pdd = target->pdds[i];
+ struct kfd_topology_device *topo_dev = kfd_topology_device_by_id(pdd->dev->id);
+
+ device_info.gpu_id = pdd->dev->id;
+ device_info.exception_status = pdd->exception_status;
+ device_info.lds_base = pdd->lds_base;
+ device_info.lds_limit = pdd->lds_limit;
+ device_info.scratch_base = pdd->scratch_base;
+ device_info.scratch_limit = pdd->scratch_limit;
+ device_info.gpuvm_base = pdd->gpuvm_base;
+ device_info.gpuvm_limit = pdd->gpuvm_limit;
+ device_info.location_id = topo_dev->node_props.location_id;
+ device_info.vendor_id = topo_dev->node_props.vendor_id;
+ device_info.device_id = topo_dev->node_props.device_id;
+ device_info.revision_id = pdd->dev->adev->pdev->revision;
+ device_info.subsystem_vendor_id = pdd->dev->adev->pdev->subsystem_vendor;
+ device_info.subsystem_device_id = pdd->dev->adev->pdev->subsystem_device;
+ device_info.fw_version = pdd->dev->kfd->mec_fw_version;
+ device_info.gfx_target_version =
+ topo_dev->node_props.gfx_target_version;
+ device_info.simd_count = topo_dev->node_props.simd_count;
+ device_info.max_waves_per_simd =
+ topo_dev->node_props.max_waves_per_simd;
+ device_info.array_count = topo_dev->node_props.array_count;
+ device_info.simd_arrays_per_engine =
+ topo_dev->node_props.simd_arrays_per_engine;
+ device_info.num_xcc = NUM_XCC(pdd->dev->xcc_mask);
+ device_info.capability = topo_dev->node_props.capability;
+ device_info.debug_prop = topo_dev->node_props.debug_prop;
+
+ if (exception_clear_mask)
+ pdd->exception_status &= ~exception_clear_mask;
+
+ if (copy_to_user(user_info, &device_info, *entry_size)) {
+ r = -EFAULT;
+ break;
+ }
+
+ user_info += tmp_entry_size;
+ }
+
+ mutex_unlock(&target->event_mutex);
+
+ return r;
+}
+
+void kfd_dbg_set_enabled_debug_exception_mask(struct kfd_process *target,
+ uint64_t exception_set_mask)
+{
+ uint64_t found_mask = 0;
+ struct process_queue_manager *pqm;
+ struct process_queue_node *pqn;
+ static const char write_data = '.';
+ loff_t pos = 0;
+ int i;
+
+ mutex_lock(&target->event_mutex);
+
+ found_mask |= target->exception_status;
+
+ pqm = &target->pqm;
+ list_for_each_entry(pqn, &pqm->queues, process_queue_list) {
+ if (!pqn->q)
+ continue;
+
+ found_mask |= pqn->q->properties.exception_status;
+ }
+
+ for (i = 0; i < target->n_pdds; i++) {
+ struct kfd_process_device *pdd = target->pdds[i];
+
+ found_mask |= pdd->exception_status;
+ }
+
+ if (exception_set_mask & found_mask)
+ kernel_write(target->dbg_ev_file, &write_data, 1, &pos);
+
+ target->exception_enable_mask = exception_set_mask;
+
+ mutex_unlock(&target->event_mutex);
+}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debug.h b/drivers/gpu/drm/amd/amdkfd/kfd_debug.h
new file mode 100644
index 000000000000..a289e59ceb79
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_debug.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef KFD_DEBUG_EVENTS_H_INCLUDED
+#define KFD_DEBUG_EVENTS_H_INCLUDED
+
+#include "kfd_priv.h"
+
+void kfd_dbg_trap_deactivate(struct kfd_process *target, bool unwind, int unwind_count);
+int kfd_dbg_trap_activate(struct kfd_process *target);
+int kfd_dbg_ev_query_debug_event(struct kfd_process *process,
+ unsigned int *queue_id,
+ unsigned int *gpu_id,
+ uint64_t exception_clear_mask,
+ uint64_t *event_status);
+bool kfd_set_dbg_ev_from_interrupt(struct kfd_node *dev,
+ unsigned int pasid,
+ uint32_t doorbell_id,
+ uint64_t trap_mask,
+ void *exception_data,
+ size_t exception_data_size);
+bool kfd_dbg_ev_raise(uint64_t event_mask,
+ struct kfd_process *process, struct kfd_node *dev,
+ unsigned int source_id, bool use_worker,
+ void *exception_data,
+ size_t exception_data_size);
+int kfd_dbg_trap_disable(struct kfd_process *target);
+int kfd_dbg_trap_enable(struct kfd_process *target, uint32_t fd,
+ void __user *runtime_info,
+ uint32_t *runtime_info_size);
+int kfd_dbg_trap_set_wave_launch_override(struct kfd_process *target,
+ uint32_t trap_override,
+ uint32_t trap_mask_bits,
+ uint32_t trap_mask_request,
+ uint32_t *trap_mask_prev,
+ uint32_t *trap_mask_supported);
+int kfd_dbg_trap_set_wave_launch_mode(struct kfd_process *target,
+ uint8_t wave_launch_mode);
+int kfd_dbg_trap_clear_dev_address_watch(struct kfd_process_device *pdd,
+ uint32_t watch_id);
+int kfd_dbg_trap_set_dev_address_watch(struct kfd_process_device *pdd,
+ uint64_t watch_address,
+ uint32_t watch_address_mask,
+ uint32_t *watch_id,
+ uint32_t watch_mode);
+int kfd_dbg_trap_set_flags(struct kfd_process *target, uint32_t *flags);
+int kfd_dbg_trap_query_exception_info(struct kfd_process *target,
+ uint32_t source_id,
+ uint32_t exception_code,
+ bool clear_exception,
+ void __user *info,
+ uint32_t *info_size);
+int kfd_dbg_send_exception_to_runtime(struct kfd_process *p,
+ unsigned int dev_id,
+ unsigned int queue_id,
+ uint64_t error_reason);
+
+static inline bool kfd_dbg_is_per_vmid_supported(struct kfd_node *dev)
+{
+ return KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 2) ||
+ KFD_GC_VERSION(dev) >= IP_VERSION(11, 0, 0);
+}
+
+void debug_event_write_work_handler(struct work_struct *work);
+int kfd_dbg_trap_device_snapshot(struct kfd_process *target,
+ uint64_t exception_clear_mask,
+ void __user *user_info,
+ uint32_t *number_of_device_infos,
+ uint32_t *entry_size);
+
+void kfd_dbg_set_enabled_debug_exception_mask(struct kfd_process *target,
+ uint64_t exception_set_mask);
+/*
+ * If GFX off is enabled, chips that do not support RLC restore for the debug
+ * registers will disable GFX off temporarily for the entire debug session.
+ * See disable_on_trap_action_entry and enable_on_trap_action_exit for details.
+ */
+static inline bool kfd_dbg_is_rlc_restore_supported(struct kfd_node *dev)
+{
+ return !(KFD_GC_VERSION(dev) == IP_VERSION(10, 1, 10) ||
+ KFD_GC_VERSION(dev) == IP_VERSION(10, 1, 1));
+}
+
+static inline bool kfd_dbg_has_gws_support(struct kfd_node *dev)
+{
+ if ((KFD_GC_VERSION(dev) == IP_VERSION(9, 0, 1)
+ && dev->kfd->mec2_fw_version < 0x81b6) ||
+ (KFD_GC_VERSION(dev) >= IP_VERSION(9, 1, 0)
+ && KFD_GC_VERSION(dev) <= IP_VERSION(9, 2, 2)
+ && dev->kfd->mec2_fw_version < 0x1b6) ||
+ (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 0)
+ && dev->kfd->mec2_fw_version < 0x1b6) ||
+ (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 1)
+ && dev->kfd->mec2_fw_version < 0x30) ||
+ (KFD_GC_VERSION(dev) >= IP_VERSION(11, 0, 0) &&
+ KFD_GC_VERSION(dev) < IP_VERSION(12, 0, 0)))
+ return false;
+
+ /* Assume debugging and cooperative launch supported otherwise. */
+ return true;
+}
+
+int kfd_dbg_set_mes_debug_mode(struct kfd_process_device *pdd);
+#endif
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c b/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c
index ad5a40a685ac..4a5a0a4e00f2 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c
@@ -43,7 +43,7 @@ static int kfd_debugfs_hang_hws_read(struct seq_file *m, void *data)
static ssize_t kfd_debugfs_hang_hws_write(struct file *file,
const char __user *user_buf, size_t size, loff_t *ppos)
{
- struct kfd_dev *dev;
+ struct kfd_node *dev;
char tmp[16];
uint32_t gpu_id;
int ret = -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
index 00f528eb9812..9d4abfd8b55e 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
@@ -32,8 +32,10 @@
#include "kfd_iommu.h"
#include "amdgpu_amdkfd.h"
#include "kfd_smi_events.h"
+#include "kfd_svm.h"
#include "kfd_migrate.h"
#include "amdgpu.h"
+#include "amdgpu_xcp.h"
#define MQD_SIZE_ALIGNED 768
@@ -42,7 +44,7 @@
* once locked, kfd driver will stop any further GPU execution.
* create process (open) will return -EAGAIN.
*/
-static atomic_t kfd_locked = ATOMIC_INIT(0);
+static int kfd_locked;
#ifdef CONFIG_DRM_AMDGPU_CIK
extern const struct kfd2kgd_calls gfx_v7_kfd2kgd;
@@ -51,6 +53,7 @@ extern const struct kfd2kgd_calls gfx_v8_kfd2kgd;
extern const struct kfd2kgd_calls gfx_v9_kfd2kgd;
extern const struct kfd2kgd_calls arcturus_kfd2kgd;
extern const struct kfd2kgd_calls aldebaran_kfd2kgd;
+extern const struct kfd2kgd_calls gc_9_4_3_kfd2kgd;
extern const struct kfd2kgd_calls gfx_v10_kfd2kgd;
extern const struct kfd2kgd_calls gfx_v10_3_kfd2kgd;
extern const struct kfd2kgd_calls gfx_v11_kfd2kgd;
@@ -60,7 +63,7 @@ static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,
static void kfd_gtt_sa_fini(struct kfd_dev *kfd);
static int kfd_resume_iommu(struct kfd_dev *kfd);
-static int kfd_resume(struct kfd_dev *kfd);
+static int kfd_resume(struct kfd_node *kfd);
static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd)
{
@@ -81,6 +84,7 @@ static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd)
case IP_VERSION(4, 2, 0):/* VEGA20 */
case IP_VERSION(4, 2, 2):/* ARCTURUS */
case IP_VERSION(4, 4, 0):/* ALDEBARAN */
+ case IP_VERSION(4, 4, 2):
case IP_VERSION(5, 0, 0):/* NAVI10 */
case IP_VERSION(5, 0, 1):/* CYAN_SKILLFISH */
case IP_VERSION(5, 0, 2):/* NAVI14 */
@@ -102,20 +106,19 @@ static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd)
kfd->device_info.num_sdma_queues_per_engine = 8;
}
+ bitmap_zero(kfd->device_info.reserved_sdma_queues_bitmap, KFD_MAX_SDMA_QUEUES);
+
switch (sdma_version) {
case IP_VERSION(6, 0, 0):
+ case IP_VERSION(6, 0, 1):
case IP_VERSION(6, 0, 2):
case IP_VERSION(6, 0, 3):
/* Reserve 1 for paging and 1 for gfx */
kfd->device_info.num_reserved_sdma_queues_per_engine = 2;
/* BIT(0)=engine-0 queue-0; BIT(1)=engine-1 queue-0; BIT(2)=engine-0 queue-1; ... */
- kfd->device_info.reserved_sdma_queues_bitmap = 0xFULL;
- break;
- case IP_VERSION(6, 0, 1):
- /* Reserve 1 for paging and 1 for gfx */
- kfd->device_info.num_reserved_sdma_queues_per_engine = 2;
- /* BIT(0)=engine-0 queue-0; BIT(1)=engine-0 queue-1; ... */
- kfd->device_info.reserved_sdma_queues_bitmap = 0x3ULL;
+ bitmap_set(kfd->device_info.reserved_sdma_queues_bitmap, 0,
+ kfd->adev->sdma.num_instances *
+ kfd->device_info.num_reserved_sdma_queues_per_engine);
break;
default:
break;
@@ -135,6 +138,9 @@ static void kfd_device_info_set_event_interrupt_class(struct kfd_dev *kfd)
case IP_VERSION(9, 4, 0): /* VEGA20 */
case IP_VERSION(9, 4, 1): /* ARCTURUS */
case IP_VERSION(9, 4, 2): /* ALDEBARAN */
+ case IP_VERSION(9, 4, 3): /* GC 9.4.3 */
+ kfd->device_info.event_interrupt_class = &event_interrupt_class_v9;
+ break;
case IP_VERSION(10, 3, 1): /* VANGOGH */
case IP_VERSION(10, 3, 3): /* YELLOW_CARP */
case IP_VERSION(10, 3, 6): /* GC 10.3.6 */
@@ -148,7 +154,7 @@ static void kfd_device_info_set_event_interrupt_class(struct kfd_dev *kfd)
case IP_VERSION(10, 3, 2): /* NAVY_FLOUNDER */
case IP_VERSION(10, 3, 4): /* DIMGREY_CAVEFISH */
case IP_VERSION(10, 3, 5): /* BEIGE_GOBY */
- kfd->device_info.event_interrupt_class = &event_interrupt_class_v9;
+ kfd->device_info.event_interrupt_class = &event_interrupt_class_v10;
break;
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 1):
@@ -327,8 +333,10 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
f2g = &aldebaran_kfd2kgd;
break;
case IP_VERSION(9, 4, 3):
- gfx_target_version = 90400;
- f2g = &aldebaran_kfd2kgd;
+ gfx_target_version = adev->rev_id >= 1 ? 90402
+ : adev->flags & AMD_IS_APU ? 90400
+ : 90401;
+ f2g = &gc_9_4_3_kfd2kgd;
break;
/* Navi10 */
case IP_VERSION(10, 1, 10):
@@ -406,8 +414,15 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
f2g = &gfx_v11_kfd2kgd;
break;
case IP_VERSION(11, 0, 3):
- /* Note: Compiler version is 11.0.1 while HW version is 11.0.3 */
- gfx_target_version = 110001;
+ if ((adev->pdev->device == 0x7460 &&
+ adev->pdev->revision == 0x00) ||
+ (adev->pdev->device == 0x7461 &&
+ adev->pdev->revision == 0x00))
+ /* Note: Compiler version is 11.0.5 while HW version is 11.0.3 */
+ gfx_target_version = 110005;
+ else
+ /* Note: Compiler version is 11.0.1 while HW version is 11.0.3 */
+ gfx_target_version = 110001;
f2g = &gfx_v11_kfd2kgd;
break;
default:
@@ -440,8 +455,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
memset(&kfd->doorbell_available_index, 0,
sizeof(kfd->doorbell_available_index));
- atomic_set(&kfd->sram_ecc_flag, 0);
-
ida_init(&kfd->doorbell_ida);
return kfd;
@@ -488,41 +501,112 @@ static void kfd_cwsr_init(struct kfd_dev *kfd)
}
}
-static int kfd_gws_init(struct kfd_dev *kfd)
+static int kfd_gws_init(struct kfd_node *node)
{
int ret = 0;
+ struct kfd_dev *kfd = node->kfd;
- if (kfd->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS)
+ if (node->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS)
return 0;
- if (hws_gws_support || (KFD_IS_SOC15(kfd) &&
- ((KFD_GC_VERSION(kfd) == IP_VERSION(9, 0, 1)
+ if (hws_gws_support || (KFD_IS_SOC15(node) &&
+ ((KFD_GC_VERSION(node) == IP_VERSION(9, 0, 1)
&& kfd->mec2_fw_version >= 0x81b3) ||
- (KFD_GC_VERSION(kfd) <= IP_VERSION(9, 4, 0)
+ (KFD_GC_VERSION(node) <= IP_VERSION(9, 4, 0)
&& kfd->mec2_fw_version >= 0x1b3) ||
- (KFD_GC_VERSION(kfd) == IP_VERSION(9, 4, 1)
+ (KFD_GC_VERSION(node) == IP_VERSION(9, 4, 1)
&& kfd->mec2_fw_version >= 0x30) ||
- (KFD_GC_VERSION(kfd) == IP_VERSION(9, 4, 2)
+ (KFD_GC_VERSION(node) == IP_VERSION(9, 4, 2)
&& kfd->mec2_fw_version >= 0x28) ||
- (KFD_GC_VERSION(kfd) >= IP_VERSION(10, 3, 0)
- && KFD_GC_VERSION(kfd) < IP_VERSION(11, 0, 0)
+ (KFD_GC_VERSION(node) >= IP_VERSION(10, 3, 0)
+ && KFD_GC_VERSION(node) < IP_VERSION(11, 0, 0)
&& kfd->mec2_fw_version >= 0x6b))))
- ret = amdgpu_amdkfd_alloc_gws(kfd->adev,
- kfd->adev->gds.gws_size, &kfd->gws);
+ ret = amdgpu_amdkfd_alloc_gws(node->adev,
+ node->adev->gds.gws_size, &node->gws);
return ret;
}
-static void kfd_smi_init(struct kfd_dev *dev)
+static void kfd_smi_init(struct kfd_node *dev)
{
INIT_LIST_HEAD(&dev->smi_clients);
spin_lock_init(&dev->smi_lock);
}
+static int kfd_init_node(struct kfd_node *node)
+{
+ int err = -1;
+
+ if (kfd_interrupt_init(node)) {
+ dev_err(kfd_device, "Error initializing interrupts\n");
+ goto kfd_interrupt_error;
+ }
+
+ node->dqm = device_queue_manager_init(node);
+ if (!node->dqm) {
+ dev_err(kfd_device, "Error initializing queue manager\n");
+ goto device_queue_manager_error;
+ }
+
+ if (kfd_gws_init(node)) {
+ dev_err(kfd_device, "Could not allocate %d gws\n",
+ node->adev->gds.gws_size);
+ goto gws_error;
+ }
+
+ if (kfd_resume(node))
+ goto kfd_resume_error;
+
+ if (kfd_topology_add_device(node)) {
+ dev_err(kfd_device, "Error adding device to topology\n");
+ goto kfd_topology_add_device_error;
+ }
+
+ kfd_smi_init(node);
+
+ return 0;
+
+kfd_topology_add_device_error:
+kfd_resume_error:
+gws_error:
+ device_queue_manager_uninit(node->dqm);
+device_queue_manager_error:
+ kfd_interrupt_exit(node);
+kfd_interrupt_error:
+ if (node->gws)
+ amdgpu_amdkfd_free_gws(node->adev, node->gws);
+
+ /* Cleanup the node memory here */
+ kfree(node);
+ return err;
+}
+
+static void kfd_cleanup_nodes(struct kfd_dev *kfd, unsigned int num_nodes)
+{
+ struct kfd_node *knode;
+ unsigned int i;
+
+ for (i = 0; i < num_nodes; i++) {
+ knode = kfd->nodes[i];
+ device_queue_manager_uninit(knode->dqm);
+ kfd_interrupt_exit(knode);
+ kfd_topology_remove_device(knode);
+ if (knode->gws)
+ amdgpu_amdkfd_free_gws(knode->adev, knode->gws);
+ kfree(knode);
+ kfd->nodes[i] = NULL;
+ }
+}
+
bool kgd2kfd_device_init(struct kfd_dev *kfd,
const struct kgd2kfd_shared_resources *gpu_resources)
{
- unsigned int size, map_process_packet_size;
+ unsigned int size, map_process_packet_size, i;
+ struct kfd_node *node;
+ uint32_t first_vmid_kfd, last_vmid_kfd, vmid_num_kfd;
+ unsigned int max_proc_per_quantum;
+ int partition_mode;
+ int xcp_idx;
kfd->mec_fw_version = amdgpu_amdkfd_get_fw_version(kfd->adev,
KGD_ENGINE_MEC1);
@@ -532,10 +616,14 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
KGD_ENGINE_SDMA1);
kfd->shared_resources = *gpu_resources;
- kfd->vm_info.first_vmid_kfd = ffs(gpu_resources->compute_vmid_bitmap)-1;
- kfd->vm_info.last_vmid_kfd = fls(gpu_resources->compute_vmid_bitmap)-1;
- kfd->vm_info.vmid_num_kfd = kfd->vm_info.last_vmid_kfd
- - kfd->vm_info.first_vmid_kfd + 1;
+ kfd->num_nodes = amdgpu_xcp_get_num_xcp(kfd->adev->xcp_mgr);
+
+ if (kfd->num_nodes == 0) {
+ dev_err(kfd_device,
+ "KFD num nodes cannot be 0, num_xcc_in_node: %d\n",
+ kfd->adev->gfx.num_xcc_per_xcp);
+ goto out;
+ }
/* Allow BIF to recode atomics to PCIe 3.0 AtomicOps.
* 32 and 64-bit requests are possible and must be
@@ -554,11 +642,34 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
return false;
}
+ first_vmid_kfd = ffs(gpu_resources->compute_vmid_bitmap)-1;
+ last_vmid_kfd = fls(gpu_resources->compute_vmid_bitmap)-1;
+ vmid_num_kfd = last_vmid_kfd - first_vmid_kfd + 1;
+
+ /* For GFX9.4.3, we need special handling for VMIDs depending on
+ * partition mode.
+ * In CPX mode, the VMID range needs to be shared between XCDs.
+ * Additionally, there are 13 VMIDs (3-15) available for KFD. To
+ * divide them equally, we change starting VMID to 4 and not use
+ * VMID 3.
+ * If the VMID range changes for GFX9.4.3, then this code MUST be
+ * revisited.
+ */
+ if (kfd->adev->xcp_mgr) {
+ partition_mode = amdgpu_xcp_query_partition_mode(kfd->adev->xcp_mgr,
+ AMDGPU_XCP_FL_LOCKED);
+ if (partition_mode == AMDGPU_CPX_PARTITION_MODE &&
+ kfd->num_nodes != 1) {
+ vmid_num_kfd /= 2;
+ first_vmid_kfd = last_vmid_kfd + 1 - vmid_num_kfd*2;
+ }
+ }
+
/* Verify module parameters regarding mapped process number*/
if (hws_max_conc_proc >= 0)
- kfd->max_proc_per_quantum = min((u32)hws_max_conc_proc, kfd->vm_info.vmid_num_kfd);
+ max_proc_per_quantum = min((u32)hws_max_conc_proc, vmid_num_kfd);
else
- kfd->max_proc_per_quantum = kfd->vm_info.vmid_num_kfd;
+ max_proc_per_quantum = vmid_num_kfd;
/* calculate max size of mqds needed for queues */
size = max_num_of_queues_per_device *
@@ -606,27 +717,15 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
if (amdgpu_use_xgmi_p2p)
kfd->hive_id = kfd->adev->gmc.xgmi.hive_id;
- kfd->noretry = kfd->adev->gmc.noretry;
-
- if (kfd_interrupt_init(kfd)) {
- dev_err(kfd_device, "Error initializing interrupts\n");
- goto kfd_interrupt_error;
- }
-
- kfd->dqm = device_queue_manager_init(kfd);
- if (!kfd->dqm) {
- dev_err(kfd_device, "Error initializing queue manager\n");
- goto device_queue_manager_error;
- }
-
- /* If supported on this device, allocate global GWS that is shared
- * by all KFD processes
+ /*
+ * For GFX9.4.3, the KFD abstracts all partitions within a socket as
+ * xGMI connected in the topology so assign a unique hive id per
+ * device based on the pci device location if device is in PCIe mode.
*/
- if (kfd_gws_init(kfd)) {
- dev_err(kfd_device, "Could not allocate %d gws\n",
- kfd->adev->gds.gws_size);
- goto gws_error;
- }
+ if (!kfd->hive_id && (KFD_GC_VERSION(kfd) == IP_VERSION(9, 4, 3)) && kfd->num_nodes > 1)
+ kfd->hive_id = pci_dev_id(kfd->adev->pdev);
+
+ kfd->noretry = kfd->adev->gmc.noretry;
/* If CRAT is broken, won't set iommu enabled */
kfd_double_confirm_iommu_support(kfd);
@@ -639,48 +738,100 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
kfd_cwsr_init(kfd);
- svm_migrate_init(kfd->adev);
+ dev_info(kfd_device, "Total number of KFD nodes to be created: %d\n",
+ kfd->num_nodes);
+
+ /* Allocate the KFD nodes */
+ for (i = 0, xcp_idx = 0; i < kfd->num_nodes; i++) {
+ node = kzalloc(sizeof(struct kfd_node), GFP_KERNEL);
+ if (!node)
+ goto node_alloc_error;
+
+ node->node_id = i;
+ node->adev = kfd->adev;
+ node->kfd = kfd;
+ node->kfd2kgd = kfd->kfd2kgd;
+ node->vm_info.vmid_num_kfd = vmid_num_kfd;
+ node->xcp = amdgpu_get_next_xcp(kfd->adev->xcp_mgr, &xcp_idx);
+ /* TODO : Check if error handling is needed */
+ if (node->xcp) {
+ amdgpu_xcp_get_inst_details(node->xcp, AMDGPU_XCP_GFX,
+ &node->xcc_mask);
+ ++xcp_idx;
+ } else {
+ node->xcc_mask =
+ (1U << NUM_XCC(kfd->adev->gfx.xcc_mask)) - 1;
+ }
- if (kfd_resume_iommu(kfd))
- goto device_iommu_error;
+ if (node->xcp) {
+ dev_info(kfd_device, "KFD node %d partition %d size %lldM\n",
+ node->node_id, node->xcp->mem_id,
+ KFD_XCP_MEMORY_SIZE(node->adev, node->node_id) >> 20);
+ }
- if (kfd_resume(kfd))
- goto kfd_resume_error;
+ if (KFD_GC_VERSION(kfd) == IP_VERSION(9, 4, 3) &&
+ partition_mode == AMDGPU_CPX_PARTITION_MODE &&
+ kfd->num_nodes != 1) {
+ /* For GFX9.4.3 and CPX mode, first XCD gets VMID range
+ * 4-9 and second XCD gets VMID range 10-15.
+ */
- amdgpu_amdkfd_get_local_mem_info(kfd->adev, &kfd->local_mem_info);
+ node->vm_info.first_vmid_kfd = (i%2 == 0) ?
+ first_vmid_kfd :
+ first_vmid_kfd+vmid_num_kfd;
+ node->vm_info.last_vmid_kfd = (i%2 == 0) ?
+ last_vmid_kfd-vmid_num_kfd :
+ last_vmid_kfd;
+ node->compute_vmid_bitmap =
+ ((0x1 << (node->vm_info.last_vmid_kfd + 1)) - 1) -
+ ((0x1 << (node->vm_info.first_vmid_kfd)) - 1);
+ } else {
+ node->vm_info.first_vmid_kfd = first_vmid_kfd;
+ node->vm_info.last_vmid_kfd = last_vmid_kfd;
+ node->compute_vmid_bitmap =
+ gpu_resources->compute_vmid_bitmap;
+ }
+ node->max_proc_per_quantum = max_proc_per_quantum;
+ atomic_set(&node->sram_ecc_flag, 0);
- if (kfd_topology_add_device(kfd)) {
- dev_err(kfd_device, "Error adding device to topology\n");
- goto kfd_topology_add_device_error;
+ amdgpu_amdkfd_get_local_mem_info(kfd->adev,
+ &node->local_mem_info, node->xcp);
+
+ /* Initialize the KFD node */
+ if (kfd_init_node(node)) {
+ dev_err(kfd_device, "Error initializing KFD node\n");
+ goto node_init_error;
+ }
+ kfd->nodes[i] = node;
}
- kfd_smi_init(kfd);
+ svm_range_set_max_pages(kfd->adev);
+
+ if (kfd_resume_iommu(kfd))
+ goto kfd_resume_iommu_error;
+
+ spin_lock_init(&kfd->watch_points_lock);
kfd->init_complete = true;
dev_info(kfd_device, "added device %x:%x\n", kfd->adev->pdev->vendor,
kfd->adev->pdev->device);
pr_debug("Starting kfd with the following scheduling policy %d\n",
- kfd->dqm->sched_policy);
+ node->dqm->sched_policy);
goto out;
-kfd_topology_add_device_error:
-kfd_resume_error:
+kfd_resume_iommu_error:
+node_init_error:
+node_alloc_error:
+ kfd_cleanup_nodes(kfd, i);
device_iommu_error:
-gws_error:
- device_queue_manager_uninit(kfd->dqm);
-device_queue_manager_error:
- kfd_interrupt_exit(kfd);
-kfd_interrupt_error:
kfd_doorbell_fini(kfd);
kfd_doorbell_error:
kfd_gtt_sa_fini(kfd);
kfd_gtt_sa_init_error:
amdgpu_amdkfd_free_gtt_mem(kfd->adev, kfd->gtt_mem);
alloc_gtt_mem_failure:
- if (kfd->gws)
- amdgpu_amdkfd_free_gws(kfd->adev, kfd->gws);
dev_err(kfd_device,
"device %x:%x NOT added due to errors\n",
kfd->adev->pdev->vendor, kfd->adev->pdev->device);
@@ -691,15 +842,13 @@ out:
void kgd2kfd_device_exit(struct kfd_dev *kfd)
{
if (kfd->init_complete) {
- device_queue_manager_uninit(kfd->dqm);
- kfd_interrupt_exit(kfd);
- kfd_topology_remove_device(kfd);
+ /* Cleanup KFD nodes */
+ kfd_cleanup_nodes(kfd, kfd->num_nodes);
+ /* Cleanup common/shared resources */
kfd_doorbell_fini(kfd);
ida_destroy(&kfd->doorbell_ida);
kfd_gtt_sa_fini(kfd);
amdgpu_amdkfd_free_gtt_mem(kfd->adev, kfd->gtt_mem);
- if (kfd->gws)
- amdgpu_amdkfd_free_gws(kfd->adev, kfd->gws);
}
kfree(kfd);
@@ -707,16 +856,23 @@ void kgd2kfd_device_exit(struct kfd_dev *kfd)
int kgd2kfd_pre_reset(struct kfd_dev *kfd)
{
+ struct kfd_node *node;
+ int i;
+
if (!kfd->init_complete)
return 0;
- kfd_smi_event_update_gpu_reset(kfd, false);
-
- kfd->dqm->ops.pre_reset(kfd->dqm);
+ for (i = 0; i < kfd->num_nodes; i++) {
+ node = kfd->nodes[i];
+ kfd_smi_event_update_gpu_reset(node, false);
+ node->dqm->ops.pre_reset(node->dqm);
+ }
kgd2kfd_suspend(kfd, false);
- kfd_signal_reset_event(kfd);
+ for (i = 0; i < kfd->num_nodes; i++)
+ kfd_signal_reset_event(kfd->nodes[i]);
+
return 0;
}
@@ -729,57 +885,83 @@ int kgd2kfd_pre_reset(struct kfd_dev *kfd)
int kgd2kfd_post_reset(struct kfd_dev *kfd)
{
int ret;
+ struct kfd_node *node;
+ int i;
if (!kfd->init_complete)
return 0;
- ret = kfd_resume(kfd);
- if (ret)
- return ret;
- atomic_dec(&kfd_locked);
+ for (i = 0; i < kfd->num_nodes; i++) {
+ ret = kfd_resume(kfd->nodes[i]);
+ if (ret)
+ return ret;
+ }
- atomic_set(&kfd->sram_ecc_flag, 0);
+ mutex_lock(&kfd_processes_mutex);
+ --kfd_locked;
+ mutex_unlock(&kfd_processes_mutex);
- kfd_smi_event_update_gpu_reset(kfd, true);
+ for (i = 0; i < kfd->num_nodes; i++) {
+ node = kfd->nodes[i];
+ atomic_set(&node->sram_ecc_flag, 0);
+ kfd_smi_event_update_gpu_reset(node, true);
+ }
return 0;
}
bool kfd_is_locked(void)
{
- return (atomic_read(&kfd_locked) > 0);
+ lockdep_assert_held(&kfd_processes_mutex);
+ return (kfd_locked > 0);
}
void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm)
{
+ struct kfd_node *node;
+ int i;
+ int count;
+
if (!kfd->init_complete)
return;
/* for runtime suspend, skip locking kfd */
if (!run_pm) {
+ mutex_lock(&kfd_processes_mutex);
+ count = ++kfd_locked;
+ mutex_unlock(&kfd_processes_mutex);
+
/* For first KFD device suspend all the KFD processes */
- if (atomic_inc_return(&kfd_locked) == 1)
+ if (count == 1)
kfd_suspend_all_processes();
}
- kfd->dqm->ops.stop(kfd->dqm);
+ for (i = 0; i < kfd->num_nodes; i++) {
+ node = kfd->nodes[i];
+ node->dqm->ops.stop(node->dqm);
+ }
kfd_iommu_suspend(kfd);
}
int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm)
{
- int ret, count;
+ int ret, count, i;
if (!kfd->init_complete)
return 0;
- ret = kfd_resume(kfd);
- if (ret)
- return ret;
+ for (i = 0; i < kfd->num_nodes; i++) {
+ ret = kfd_resume(kfd->nodes[i]);
+ if (ret)
+ return ret;
+ }
/* for runtime resume, skip unlocking kfd */
if (!run_pm) {
- count = atomic_dec_return(&kfd_locked);
+ mutex_lock(&kfd_processes_mutex);
+ count = --kfd_locked;
+ mutex_unlock(&kfd_processes_mutex);
+
WARN_ONCE(count < 0, "KFD suspend / resume ref. error");
if (count == 0)
ret = kfd_resume_all_processes();
@@ -808,15 +990,15 @@ static int kfd_resume_iommu(struct kfd_dev *kfd)
return err;
}
-static int kfd_resume(struct kfd_dev *kfd)
+static int kfd_resume(struct kfd_node *node)
{
int err = 0;
- err = kfd->dqm->ops.start(kfd->dqm);
+ err = node->dqm->ops.start(node->dqm);
if (err)
dev_err(kfd_device,
"Error starting queue manager for device %x:%x\n",
- kfd->adev->pdev->vendor, kfd->adev->pdev->device);
+ node->adev->pdev->vendor, node->adev->pdev->device);
return err;
}
@@ -839,9 +1021,10 @@ static inline void kfd_queue_work(struct workqueue_struct *wq,
/* This is called directly from KGD at ISR. */
void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
{
- uint32_t patched_ihre[KFD_MAX_RING_ENTRY_SIZE];
+ uint32_t patched_ihre[KFD_MAX_RING_ENTRY_SIZE], i;
bool is_patched = false;
unsigned long flags;
+ struct kfd_node *node;
if (!kfd->init_complete)
return;
@@ -851,16 +1034,22 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
return;
}
- spin_lock_irqsave(&kfd->interrupt_lock, flags);
-
- if (kfd->interrupts_active
- && interrupt_is_wanted(kfd, ih_ring_entry,
- patched_ihre, &is_patched)
- && enqueue_ih_ring_entry(kfd,
- is_patched ? patched_ihre : ih_ring_entry))
- kfd_queue_work(kfd->ih_wq, &kfd->interrupt_work);
+ for (i = 0; i < kfd->num_nodes; i++) {
+ node = kfd->nodes[i];
+ spin_lock_irqsave(&node->interrupt_lock, flags);
+
+ if (node->interrupts_active
+ && interrupt_is_wanted(node, ih_ring_entry,
+ patched_ihre, &is_patched)
+ && enqueue_ih_ring_entry(node,
+ is_patched ? patched_ihre : ih_ring_entry)) {
+ kfd_queue_work(node->ih_wq, &node->interrupt_work);
+ spin_unlock_irqrestore(&node->interrupt_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&node->interrupt_lock, flags);
+ }
- spin_unlock_irqrestore(&kfd->interrupt_lock, flags);
}
int kgd2kfd_quiesce_mm(struct mm_struct *mm, uint32_t trigger)
@@ -998,10 +1187,11 @@ static inline uint32_t *kfd_gtt_sa_calc_cpu_addr(void *start_addr,
return (uint32_t *) ((uint64_t) start_addr + bit_num * chunk_size);
}
-int kfd_gtt_sa_allocate(struct kfd_dev *kfd, unsigned int size,
+int kfd_gtt_sa_allocate(struct kfd_node *node, unsigned int size,
struct kfd_mem_obj **mem_obj)
{
unsigned int found, start_search, cur_size;
+ struct kfd_dev *kfd = node->kfd;
if (size == 0)
return -EINVAL;
@@ -1101,8 +1291,10 @@ kfd_gtt_no_free_chunk:
return -ENOMEM;
}
-int kfd_gtt_sa_free(struct kfd_dev *kfd, struct kfd_mem_obj *mem_obj)
+int kfd_gtt_sa_free(struct kfd_node *node, struct kfd_mem_obj *mem_obj)
{
+ struct kfd_dev *kfd = node->kfd;
+
/* Act like kfree when trying to free a NULL object */
if (!mem_obj)
return 0;
@@ -1124,29 +1316,40 @@ int kfd_gtt_sa_free(struct kfd_dev *kfd, struct kfd_mem_obj *mem_obj)
void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd)
{
+ /*
+ * TODO: Currently update SRAM ECC flag for first node.
+ * This needs to be updated later when we can
+ * identify SRAM ECC error on other nodes also.
+ */
if (kfd)
- atomic_inc(&kfd->sram_ecc_flag);
+ atomic_inc(&kfd->nodes[0]->sram_ecc_flag);
}
-void kfd_inc_compute_active(struct kfd_dev *kfd)
+void kfd_inc_compute_active(struct kfd_node *node)
{
- if (atomic_inc_return(&kfd->compute_profile) == 1)
- amdgpu_amdkfd_set_compute_idle(kfd->adev, false);
+ if (atomic_inc_return(&node->kfd->compute_profile) == 1)
+ amdgpu_amdkfd_set_compute_idle(node->adev, false);
}
-void kfd_dec_compute_active(struct kfd_dev *kfd)
+void kfd_dec_compute_active(struct kfd_node *node)
{
- int count = atomic_dec_return(&kfd->compute_profile);
+ int count = atomic_dec_return(&node->kfd->compute_profile);
if (count == 0)
- amdgpu_amdkfd_set_compute_idle(kfd->adev, true);
+ amdgpu_amdkfd_set_compute_idle(node->adev, true);
WARN_ONCE(count < 0, "Compute profile ref. count error");
}
void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask)
{
+ /*
+ * TODO: For now, raise the throttling event only on first node.
+ * This will need to change after we are able to determine
+ * which node raised the throttling event.
+ */
if (kfd && kfd->init_complete)
- kfd_smi_event_update_thermal_throttling(kfd, throttle_bitmask);
+ kfd_smi_event_update_thermal_throttling(kfd->nodes[0],
+ throttle_bitmask);
}
/* kfd_get_num_sdma_engines returns the number of PCIe optimized SDMA and
@@ -1154,19 +1357,41 @@ void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask)
* When the device has more than two engines, we reserve two for PCIe to enable
* full-duplex and the rest are used as XGMI.
*/
-unsigned int kfd_get_num_sdma_engines(struct kfd_dev *kdev)
+unsigned int kfd_get_num_sdma_engines(struct kfd_node *node)
{
/* If XGMI is not supported, all SDMA engines are PCIe */
- if (!kdev->adev->gmc.xgmi.supported)
- return kdev->adev->sdma.num_instances;
+ if (!node->adev->gmc.xgmi.supported)
+ return node->adev->sdma.num_instances/(int)node->kfd->num_nodes;
- return min(kdev->adev->sdma.num_instances, 2);
+ return min(node->adev->sdma.num_instances/(int)node->kfd->num_nodes, 2);
}
-unsigned int kfd_get_num_xgmi_sdma_engines(struct kfd_dev *kdev)
+unsigned int kfd_get_num_xgmi_sdma_engines(struct kfd_node *node)
{
/* After reserved for PCIe, the rest of engines are XGMI */
- return kdev->adev->sdma.num_instances - kfd_get_num_sdma_engines(kdev);
+ return node->adev->sdma.num_instances/(int)node->kfd->num_nodes -
+ kfd_get_num_sdma_engines(node);
+}
+
+int kgd2kfd_check_and_lock_kfd(void)
+{
+ mutex_lock(&kfd_processes_mutex);
+ if (!hash_empty(kfd_processes_table) || kfd_is_locked()) {
+ mutex_unlock(&kfd_processes_mutex);
+ return -EBUSY;
+ }
+
+ ++kfd_locked;
+ mutex_unlock(&kfd_processes_mutex);
+
+ return 0;
+}
+
+void kgd2kfd_unlock_kfd(void)
+{
+ mutex_lock(&kfd_processes_mutex);
+ --kfd_locked;
+ mutex_unlock(&kfd_processes_mutex);
}
#if defined(CONFIG_DEBUG_FS)
@@ -1174,7 +1399,7 @@ unsigned int kfd_get_num_xgmi_sdma_engines(struct kfd_dev *kdev)
/* This function will send a package to HIQ to hang the HWS
* which will trigger a GPU reset and bring the HWS back to normal state
*/
-int kfd_debugfs_hang_hws(struct kfd_dev *dev)
+int kfd_debugfs_hang_hws(struct kfd_node *dev)
{
if (dev->dqm->sched_policy != KFD_SCHED_POLICY_HWS) {
pr_err("HWS is not enabled");
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index 7a95698d83f7..f515cb8f30ca 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -36,6 +36,7 @@
#include "kfd_kernel_queue.h"
#include "amdgpu_amdkfd.h"
#include "mes_api_def.h"
+#include "kfd_debug.h"
/* Size of the per-pipe EOP queue */
#define CIK_HPD_EOP_BYTES_LOG2 11
@@ -46,10 +47,13 @@ static int set_pasid_vmid_mapping(struct device_queue_manager *dqm,
static int execute_queues_cpsch(struct device_queue_manager *dqm,
enum kfd_unmap_queues_filter filter,
- uint32_t filter_param);
+ uint32_t filter_param,
+ uint32_t grace_period);
static int unmap_queues_cpsch(struct device_queue_manager *dqm,
enum kfd_unmap_queues_filter filter,
- uint32_t filter_param, bool reset);
+ uint32_t filter_param,
+ uint32_t grace_period,
+ bool reset);
static int map_queues_cpsch(struct device_queue_manager *dqm);
@@ -74,31 +78,31 @@ enum KFD_MQD_TYPE get_mqd_type_from_queue_type(enum kfd_queue_type type)
static bool is_pipe_enabled(struct device_queue_manager *dqm, int mec, int pipe)
{
int i;
- int pipe_offset = (mec * dqm->dev->shared_resources.num_pipe_per_mec
- + pipe) * dqm->dev->shared_resources.num_queue_per_pipe;
+ int pipe_offset = (mec * dqm->dev->kfd->shared_resources.num_pipe_per_mec
+ + pipe) * dqm->dev->kfd->shared_resources.num_queue_per_pipe;
/* queue is available for KFD usage if bit is 1 */
- for (i = 0; i < dqm->dev->shared_resources.num_queue_per_pipe; ++i)
+ for (i = 0; i < dqm->dev->kfd->shared_resources.num_queue_per_pipe; ++i)
if (test_bit(pipe_offset + i,
- dqm->dev->shared_resources.cp_queue_bitmap))
+ dqm->dev->kfd->shared_resources.cp_queue_bitmap))
return true;
return false;
}
unsigned int get_cp_queues_num(struct device_queue_manager *dqm)
{
- return bitmap_weight(dqm->dev->shared_resources.cp_queue_bitmap,
+ return bitmap_weight(dqm->dev->kfd->shared_resources.cp_queue_bitmap,
KGD_MAX_QUEUES);
}
unsigned int get_queues_per_pipe(struct device_queue_manager *dqm)
{
- return dqm->dev->shared_resources.num_queue_per_pipe;
+ return dqm->dev->kfd->shared_resources.num_queue_per_pipe;
}
unsigned int get_pipes_per_mec(struct device_queue_manager *dqm)
{
- return dqm->dev->shared_resources.num_pipe_per_mec;
+ return dqm->dev->kfd->shared_resources.num_pipe_per_mec;
}
static unsigned int get_num_all_sdma_engines(struct device_queue_manager *dqm)
@@ -110,29 +114,40 @@ static unsigned int get_num_all_sdma_engines(struct device_queue_manager *dqm)
unsigned int get_num_sdma_queues(struct device_queue_manager *dqm)
{
return kfd_get_num_sdma_engines(dqm->dev) *
- dqm->dev->device_info.num_sdma_queues_per_engine;
+ dqm->dev->kfd->device_info.num_sdma_queues_per_engine;
}
unsigned int get_num_xgmi_sdma_queues(struct device_queue_manager *dqm)
{
return kfd_get_num_xgmi_sdma_engines(dqm->dev) *
- dqm->dev->device_info.num_sdma_queues_per_engine;
+ dqm->dev->kfd->device_info.num_sdma_queues_per_engine;
}
-static inline uint64_t get_reserved_sdma_queues_bitmap(struct device_queue_manager *dqm)
+static void init_sdma_bitmaps(struct device_queue_manager *dqm)
{
- return dqm->dev->device_info.reserved_sdma_queues_bitmap;
+ bitmap_zero(dqm->sdma_bitmap, KFD_MAX_SDMA_QUEUES);
+ bitmap_set(dqm->sdma_bitmap, 0, get_num_sdma_queues(dqm));
+
+ bitmap_zero(dqm->xgmi_sdma_bitmap, KFD_MAX_SDMA_QUEUES);
+ bitmap_set(dqm->xgmi_sdma_bitmap, 0, get_num_xgmi_sdma_queues(dqm));
+
+ /* Mask out the reserved queues */
+ bitmap_andnot(dqm->sdma_bitmap, dqm->sdma_bitmap,
+ dqm->dev->kfd->device_info.reserved_sdma_queues_bitmap,
+ KFD_MAX_SDMA_QUEUES);
}
void program_sh_mem_settings(struct device_queue_manager *dqm,
struct qcm_process_device *qpd)
{
- return dqm->dev->kfd2kgd->program_sh_mem_settings(
- dqm->dev->adev, qpd->vmid,
- qpd->sh_mem_config,
- qpd->sh_mem_ape1_base,
- qpd->sh_mem_ape1_limit,
- qpd->sh_mem_bases);
+ uint32_t xcc_mask = dqm->dev->xcc_mask;
+ int xcc_id;
+
+ for_each_inst(xcc_id, xcc_mask)
+ dqm->dev->kfd2kgd->program_sh_mem_settings(
+ dqm->dev->adev, qpd->vmid, qpd->sh_mem_config,
+ qpd->sh_mem_ape1_base, qpd->sh_mem_ape1_limit,
+ qpd->sh_mem_bases, xcc_id);
}
static void kfd_hws_hang(struct device_queue_manager *dqm)
@@ -211,6 +226,9 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
queue_input.paging = false;
queue_input.tba_addr = qpd->tba_addr;
queue_input.tma_addr = qpd->tma_addr;
+ queue_input.trap_en = KFD_GC_VERSION(q->device) < IP_VERSION(11, 0, 0) ||
+ KFD_GC_VERSION(q->device) > IP_VERSION(11, 0, 3);
+ queue_input.skip_process_ctx_clear = qpd->pqm->process->debug_trap_enabled;
queue_type = convert_to_mes_queue_type(q->properties.type);
if (queue_type < 0) {
@@ -330,7 +348,7 @@ static int allocate_doorbell(struct qcm_process_device *qpd,
struct queue *q,
uint32_t const *restore_id)
{
- struct kfd_dev *dev = qpd->dqm->dev;
+ struct kfd_node *dev = qpd->dqm->dev;
if (!KFD_IS_SOC15(dev)) {
/* On pre-SOC15 chips we need to use the queue ID to
@@ -349,8 +367,17 @@ static int allocate_doorbell(struct qcm_process_device *qpd,
* for a SDMA engine is 512.
*/
- uint32_t *idx_offset = dev->shared_resources.sdma_doorbell_idx;
- uint32_t valid_id = idx_offset[q->properties.sdma_engine_id]
+ uint32_t *idx_offset = dev->kfd->shared_resources.sdma_doorbell_idx;
+
+ /*
+ * q->properties.sdma_engine_id corresponds to the virtual
+ * sdma engine number. However, for doorbell allocation,
+ * we need the physical sdma engine id in order to get the
+ * correct doorbell offset.
+ */
+ uint32_t valid_id = idx_offset[qpd->dqm->dev->node_id *
+ get_num_all_sdma_engines(qpd->dqm) +
+ q->properties.sdma_engine_id]
+ (q->properties.sdma_queue_id & 1)
* KFD_QUEUE_DOORBELL_MIRROR_OFFSET
+ (q->properties.sdma_queue_id >> 1);
@@ -382,7 +409,7 @@ static int allocate_doorbell(struct qcm_process_device *qpd,
}
q->properties.doorbell_off =
- kfd_get_doorbell_dw_offset_in_bar(dev, qpd_to_pdd(qpd),
+ kfd_get_doorbell_dw_offset_in_bar(dev->kfd, qpd_to_pdd(qpd),
q->doorbell_id);
return 0;
}
@@ -391,7 +418,7 @@ static void deallocate_doorbell(struct qcm_process_device *qpd,
struct queue *q)
{
unsigned int old;
- struct kfd_dev *dev = qpd->dqm->dev;
+ struct kfd_node *dev = qpd->dqm->dev;
if (!KFD_IS_SOC15(dev) ||
q->properties.type == KFD_QUEUE_TYPE_SDMA ||
@@ -405,10 +432,14 @@ static void deallocate_doorbell(struct qcm_process_device *qpd,
static void program_trap_handler_settings(struct device_queue_manager *dqm,
struct qcm_process_device *qpd)
{
+ uint32_t xcc_mask = dqm->dev->xcc_mask;
+ int xcc_id;
+
if (dqm->dev->kfd2kgd->program_trap_handler_settings)
- dqm->dev->kfd2kgd->program_trap_handler_settings(
- dqm->dev->adev, qpd->vmid,
- qpd->tba_addr, qpd->tma_addr);
+ for_each_inst(xcc_id, xcc_mask)
+ dqm->dev->kfd2kgd->program_trap_handler_settings(
+ dqm->dev->adev, qpd->vmid, qpd->tba_addr,
+ qpd->tma_addr, xcc_id);
}
static int allocate_vmid(struct device_queue_manager *dqm,
@@ -441,7 +472,7 @@ static int allocate_vmid(struct device_queue_manager *dqm,
program_sh_mem_settings(dqm, qpd);
- if (KFD_IS_SOC15(dqm->dev) && dqm->dev->cwsr_enabled)
+ if (KFD_IS_SOC15(dqm->dev) && dqm->dev->kfd->cwsr_enabled)
program_trap_handler_settings(dqm, qpd);
/* qpd->page_table_base is set earlier when register_process()
@@ -460,7 +491,7 @@ static int allocate_vmid(struct device_queue_manager *dqm,
return 0;
}
-static int flush_texture_cache_nocpsch(struct kfd_dev *kdev,
+static int flush_texture_cache_nocpsch(struct kfd_node *kdev,
struct qcm_process_device *qpd)
{
const struct packet_manager_funcs *pmf = qpd->dqm->packet_mgr.pmf;
@@ -661,7 +692,7 @@ static inline void deallocate_hqd(struct device_queue_manager *dqm,
#define SQ_IND_CMD_CMD_KILL 0x00000003
#define SQ_IND_CMD_MODE_BROADCAST 0x00000001
-static int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process *p)
+static int dbgdev_wave_reset_wavefronts(struct kfd_node *dev, struct kfd_process *p)
{
int status = 0;
unsigned int vmid;
@@ -671,6 +702,8 @@ static int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process
struct kfd_process_device *pdd;
int first_vmid_to_scan = dev->vm_info.first_vmid_kfd;
int last_vmid_to_scan = dev->vm_info.last_vmid_kfd;
+ uint32_t xcc_mask = dev->xcc_mask;
+ int xcc_id;
reg_sq_cmd.u32All = 0;
reg_gfx_index.u32All = 0;
@@ -715,9 +748,10 @@ static int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process
reg_sq_cmd.bits.cmd = SQ_IND_CMD_CMD_KILL;
reg_sq_cmd.bits.vm_id = vmid;
- dev->kfd2kgd->wave_control_execute(dev->adev,
- reg_gfx_index.u32All,
- reg_sq_cmd.u32All);
+ for_each_inst(xcc_id, xcc_mask)
+ dev->kfd2kgd->wave_control_execute(
+ dev->adev, reg_gfx_index.u32All,
+ reg_sq_cmd.u32All, xcc_id);
return 0;
}
@@ -837,9 +871,9 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q,
/* Make sure the queue is unmapped before updating the MQD */
if (dqm->sched_policy != KFD_SCHED_POLICY_NO_HWS) {
- if (!dqm->dev->shared_resources.enable_mes)
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
retval = unmap_queues_cpsch(dqm,
- KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0, false);
+ KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0, USE_DEFAULT_GRACE_PERIOD, false);
else if (prev_active)
retval = remove_queue_mes(dqm, q, &pdd->qpd);
@@ -858,7 +892,7 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q,
}
retval = mqd_mgr->destroy_mqd(mqd_mgr, q->mqd,
- (dqm->dev->cwsr_enabled ?
+ (dqm->dev->kfd->cwsr_enabled ?
KFD_PREEMPT_TYPE_WAVEFRONT_SAVE :
KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN),
KFD_UNMAP_LATENCY_MS, q->pipe, q->queue);
@@ -895,7 +929,7 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q,
}
if (dqm->sched_policy != KFD_SCHED_POLICY_NO_HWS) {
- if (!dqm->dev->shared_resources.enable_mes)
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
retval = map_queues_cpsch(dqm);
else if (q->properties.is_active)
retval = add_queue_mes(dqm, q, &pdd->qpd);
@@ -917,6 +951,92 @@ out_unlock:
return retval;
}
+/* suspend_single_queue does not lock the dqm like the
+ * evict_process_queues_cpsch or evict_process_queues_nocpsch. You should
+ * lock the dqm before calling, and unlock after calling.
+ *
+ * The reason we don't lock the dqm is because this function may be
+ * called on multiple queues in a loop, so rather than locking/unlocking
+ * multiple times, we will just keep the dqm locked for all of the calls.
+ */
+static int suspend_single_queue(struct device_queue_manager *dqm,
+ struct kfd_process_device *pdd,
+ struct queue *q)
+{
+ bool is_new;
+
+ if (q->properties.is_suspended)
+ return 0;
+
+ pr_debug("Suspending PASID %u queue [%i]\n",
+ pdd->process->pasid,
+ q->properties.queue_id);
+
+ is_new = q->properties.exception_status & KFD_EC_MASK(EC_QUEUE_NEW);
+
+ if (is_new || q->properties.is_being_destroyed) {
+ pr_debug("Suspend: skip %s queue id %i\n",
+ is_new ? "new" : "destroyed",
+ q->properties.queue_id);
+ return -EBUSY;
+ }
+
+ q->properties.is_suspended = true;
+ if (q->properties.is_active) {
+ if (dqm->dev->kfd->shared_resources.enable_mes) {
+ int r = remove_queue_mes(dqm, q, &pdd->qpd);
+
+ if (r)
+ return r;
+ }
+
+ decrement_queue_count(dqm, &pdd->qpd, q);
+ q->properties.is_active = false;
+ }
+
+ return 0;
+}
+
+/* resume_single_queue does not lock the dqm like the functions
+ * restore_process_queues_cpsch or restore_process_queues_nocpsch. You should
+ * lock the dqm before calling, and unlock after calling.
+ *
+ * The reason we don't lock the dqm is because this function may be
+ * called on multiple queues in a loop, so rather than locking/unlocking
+ * multiple times, we will just keep the dqm locked for all of the calls.
+ */
+static int resume_single_queue(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd,
+ struct queue *q)
+{
+ struct kfd_process_device *pdd;
+
+ if (!q->properties.is_suspended)
+ return 0;
+
+ pdd = qpd_to_pdd(qpd);
+
+ pr_debug("Restoring from suspend PASID %u queue [%i]\n",
+ pdd->process->pasid,
+ q->properties.queue_id);
+
+ q->properties.is_suspended = false;
+
+ if (QUEUE_IS_ACTIVE(q->properties)) {
+ if (dqm->dev->kfd->shared_resources.enable_mes) {
+ int r = add_queue_mes(dqm, q, &pdd->qpd);
+
+ if (r)
+ return r;
+ }
+
+ q->properties.is_active = true;
+ increment_queue_count(dqm, qpd, q);
+ }
+
+ return 0;
+}
+
static int evict_process_queues_nocpsch(struct device_queue_manager *dqm,
struct qcm_process_device *qpd)
{
@@ -951,7 +1071,7 @@ static int evict_process_queues_nocpsch(struct device_queue_manager *dqm,
continue;
retval = mqd_mgr->destroy_mqd(mqd_mgr, q->mqd,
- (dqm->dev->cwsr_enabled ?
+ (dqm->dev->kfd->cwsr_enabled ?
KFD_PREEMPT_TYPE_WAVEFRONT_SAVE :
KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN),
KFD_UNMAP_LATENCY_MS, q->pipe, q->queue);
@@ -979,6 +1099,14 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
goto out;
pdd = qpd_to_pdd(qpd);
+
+ /* The debugger creates processes that temporarily have not acquired
+ * all VMs for all devices and has no VMs itself.
+ * Skip queue eviction on process eviction.
+ */
+ if (!pdd->drm_priv)
+ goto out;
+
pr_debug_ratelimited("Evicting PASID 0x%x queues\n",
pdd->process->pasid);
@@ -993,7 +1121,7 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
q->properties.is_active = false;
decrement_queue_count(dqm, qpd, q);
- if (dqm->dev->shared_resources.enable_mes) {
+ if (dqm->dev->kfd->shared_resources.enable_mes) {
retval = remove_queue_mes(dqm, q, qpd);
if (retval) {
pr_err("Failed to evict queue %d\n",
@@ -1003,11 +1131,12 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
}
}
pdd->last_evict_timestamp = get_jiffies_64();
- if (!dqm->dev->shared_resources.enable_mes)
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
retval = execute_queues_cpsch(dqm,
qpd->is_debug ?
KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES :
- KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0);
+ KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0,
+ USE_DEFAULT_GRACE_PERIOD);
out:
dqm_unlock(dqm);
@@ -1100,13 +1229,10 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm,
{
struct queue *q;
struct kfd_process_device *pdd;
- uint64_t pd_base;
uint64_t eviction_duration;
int retval = 0;
pdd = qpd_to_pdd(qpd);
- /* Retrieve PD base */
- pd_base = amdgpu_amdkfd_gpuvm_get_process_page_dir(pdd->drm_priv);
dqm_lock(dqm);
if (WARN_ON_ONCE(!qpd->evicted)) /* already restored, do nothing */
@@ -1116,12 +1242,19 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm,
goto out;
}
+ /* The debugger creates processes that temporarily have not acquired
+ * all VMs for all devices and has no VMs itself.
+ * Skip queue restore on process restore.
+ */
+ if (!pdd->drm_priv)
+ goto vm_not_acquired;
+
pr_debug_ratelimited("Restoring PASID 0x%x queues\n",
pdd->process->pasid);
/* Update PD Base in QPD */
- qpd->page_table_base = pd_base;
- pr_debug("Updated PD address to 0x%llx\n", pd_base);
+ qpd->page_table_base = amdgpu_amdkfd_gpuvm_get_process_page_dir(pdd->drm_priv);
+ pr_debug("Updated PD address to 0x%llx\n", qpd->page_table_base);
/* activate all active queues on the qpd */
list_for_each_entry(q, &qpd->queues_list, list) {
@@ -1132,7 +1265,7 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm,
q->properties.is_active = true;
increment_queue_count(dqm, &pdd->qpd, q);
- if (dqm->dev->shared_resources.enable_mes) {
+ if (dqm->dev->kfd->shared_resources.enable_mes) {
retval = add_queue_mes(dqm, q, qpd);
if (retval) {
pr_err("Failed to restore queue %d\n",
@@ -1141,12 +1274,13 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm,
}
}
}
- if (!dqm->dev->shared_resources.enable_mes)
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
retval = execute_queues_cpsch(dqm,
- KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0);
- qpd->evicted = 0;
+ KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0, USE_DEFAULT_GRACE_PERIOD);
eviction_duration = get_jiffies_64() - pdd->last_evict_timestamp;
atomic64_add(eviction_duration, &pdd->evict_duration_counter);
+vm_not_acquired:
+ qpd->evicted = 0;
out:
dqm_unlock(dqm);
return retval;
@@ -1229,35 +1363,32 @@ static int
set_pasid_vmid_mapping(struct device_queue_manager *dqm, u32 pasid,
unsigned int vmid)
{
- return dqm->dev->kfd2kgd->set_pasid_vmid_mapping(
- dqm->dev->adev, pasid, vmid);
-}
+ uint32_t xcc_mask = dqm->dev->xcc_mask;
+ int xcc_id, ret;
-static void init_interrupts(struct device_queue_manager *dqm)
-{
- unsigned int i;
+ for_each_inst(xcc_id, xcc_mask) {
+ ret = dqm->dev->kfd2kgd->set_pasid_vmid_mapping(
+ dqm->dev->adev, pasid, vmid, xcc_id);
+ if (ret)
+ break;
+ }
- for (i = 0 ; i < get_pipes_per_mec(dqm) ; i++)
- if (is_pipe_enabled(dqm, 0, i))
- dqm->dev->kfd2kgd->init_interrupts(dqm->dev->adev, i);
+ return ret;
}
-static void init_sdma_bitmaps(struct device_queue_manager *dqm)
+static void init_interrupts(struct device_queue_manager *dqm)
{
- unsigned int num_sdma_queues =
- min_t(unsigned int, sizeof(dqm->sdma_bitmap)*8,
- get_num_sdma_queues(dqm));
- unsigned int num_xgmi_sdma_queues =
- min_t(unsigned int, sizeof(dqm->xgmi_sdma_bitmap)*8,
- get_num_xgmi_sdma_queues(dqm));
-
- if (num_sdma_queues)
- dqm->sdma_bitmap = GENMASK_ULL(num_sdma_queues-1, 0);
- if (num_xgmi_sdma_queues)
- dqm->xgmi_sdma_bitmap = GENMASK_ULL(num_xgmi_sdma_queues-1, 0);
+ uint32_t xcc_mask = dqm->dev->xcc_mask;
+ unsigned int i, xcc_id;
- dqm->sdma_bitmap &= ~get_reserved_sdma_queues_bitmap(dqm);
- pr_info("sdma_bitmap: %llx\n", dqm->sdma_bitmap);
+ for_each_inst(xcc_id, xcc_mask) {
+ for (i = 0 ; i < get_pipes_per_mec(dqm) ; i++) {
+ if (is_pipe_enabled(dqm, 0, i)) {
+ dqm->dev->kfd2kgd->init_interrupts(
+ dqm->dev->adev, i, xcc_id);
+ }
+ }
+ }
}
static int initialize_nocpsch(struct device_queue_manager *dqm)
@@ -1282,7 +1413,7 @@ static int initialize_nocpsch(struct device_queue_manager *dqm)
for (queue = 0; queue < get_queues_per_pipe(dqm); queue++)
if (test_bit(pipe_offset + queue,
- dqm->dev->shared_resources.cp_queue_bitmap))
+ dqm->dev->kfd->shared_resources.cp_queue_bitmap))
dqm->allocated_queues[pipe] |= 1 << queue;
}
@@ -1322,9 +1453,16 @@ static int start_nocpsch(struct device_queue_manager *dqm)
static int stop_nocpsch(struct device_queue_manager *dqm)
{
+ dqm_lock(dqm);
+ if (!dqm->sched_running) {
+ dqm_unlock(dqm);
+ return 0;
+ }
+
if (dqm->dev->adev->asic_type == CHIP_HAWAII)
pm_uninit(&dqm->packet_mgr, false);
dqm->sched_running = false;
+ dqm_unlock(dqm);
return 0;
}
@@ -1342,46 +1480,48 @@ static int allocate_sdma_queue(struct device_queue_manager *dqm,
int bit;
if (q->properties.type == KFD_QUEUE_TYPE_SDMA) {
- if (dqm->sdma_bitmap == 0) {
+ if (bitmap_empty(dqm->sdma_bitmap, KFD_MAX_SDMA_QUEUES)) {
pr_err("No more SDMA queue to allocate\n");
return -ENOMEM;
}
if (restore_sdma_id) {
/* Re-use existing sdma_id */
- if (!(dqm->sdma_bitmap & (1ULL << *restore_sdma_id))) {
+ if (!test_bit(*restore_sdma_id, dqm->sdma_bitmap)) {
pr_err("SDMA queue already in use\n");
return -EBUSY;
}
- dqm->sdma_bitmap &= ~(1ULL << *restore_sdma_id);
+ clear_bit(*restore_sdma_id, dqm->sdma_bitmap);
q->sdma_id = *restore_sdma_id;
} else {
/* Find first available sdma_id */
- bit = __ffs64(dqm->sdma_bitmap);
- dqm->sdma_bitmap &= ~(1ULL << bit);
+ bit = find_first_bit(dqm->sdma_bitmap,
+ get_num_sdma_queues(dqm));
+ clear_bit(bit, dqm->sdma_bitmap);
q->sdma_id = bit;
}
- q->properties.sdma_engine_id = q->sdma_id %
- kfd_get_num_sdma_engines(dqm->dev);
+ q->properties.sdma_engine_id =
+ q->sdma_id % kfd_get_num_sdma_engines(dqm->dev);
q->properties.sdma_queue_id = q->sdma_id /
kfd_get_num_sdma_engines(dqm->dev);
} else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) {
- if (dqm->xgmi_sdma_bitmap == 0) {
+ if (bitmap_empty(dqm->xgmi_sdma_bitmap, KFD_MAX_SDMA_QUEUES)) {
pr_err("No more XGMI SDMA queue to allocate\n");
return -ENOMEM;
}
if (restore_sdma_id) {
/* Re-use existing sdma_id */
- if (!(dqm->xgmi_sdma_bitmap & (1ULL << *restore_sdma_id))) {
+ if (!test_bit(*restore_sdma_id, dqm->xgmi_sdma_bitmap)) {
pr_err("SDMA queue already in use\n");
return -EBUSY;
}
- dqm->xgmi_sdma_bitmap &= ~(1ULL << *restore_sdma_id);
+ clear_bit(*restore_sdma_id, dqm->xgmi_sdma_bitmap);
q->sdma_id = *restore_sdma_id;
} else {
- bit = __ffs64(dqm->xgmi_sdma_bitmap);
- dqm->xgmi_sdma_bitmap &= ~(1ULL << bit);
+ bit = find_first_bit(dqm->xgmi_sdma_bitmap,
+ get_num_xgmi_sdma_queues(dqm));
+ clear_bit(bit, dqm->xgmi_sdma_bitmap);
q->sdma_id = bit;
}
/* sdma_engine_id is sdma id including
@@ -1409,11 +1549,11 @@ static void deallocate_sdma_queue(struct device_queue_manager *dqm,
if (q->properties.type == KFD_QUEUE_TYPE_SDMA) {
if (q->sdma_id >= get_num_sdma_queues(dqm))
return;
- dqm->sdma_bitmap |= (1ULL << q->sdma_id);
+ set_bit(q->sdma_id, dqm->sdma_bitmap);
} else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) {
if (q->sdma_id >= get_num_xgmi_sdma_queues(dqm))
return;
- dqm->xgmi_sdma_bitmap |= (1ULL << q->sdma_id);
+ set_bit(q->sdma_id, dqm->xgmi_sdma_bitmap);
}
}
@@ -1426,14 +1566,14 @@ static int set_sched_resources(struct device_queue_manager *dqm)
int i, mec;
struct scheduling_resources res;
- res.vmid_mask = dqm->dev->shared_resources.compute_vmid_bitmap;
+ res.vmid_mask = dqm->dev->compute_vmid_bitmap;
res.queue_mask = 0;
for (i = 0; i < KGD_MAX_QUEUES; ++i) {
- mec = (i / dqm->dev->shared_resources.num_queue_per_pipe)
- / dqm->dev->shared_resources.num_pipe_per_mec;
+ mec = (i / dqm->dev->kfd->shared_resources.num_queue_per_pipe)
+ / dqm->dev->kfd->shared_resources.num_pipe_per_mec;
- if (!test_bit(i, dqm->dev->shared_resources.cp_queue_bitmap))
+ if (!test_bit(i, dqm->dev->kfd->shared_resources.cp_queue_bitmap))
continue;
/* only acquire queues from the first MEC */
@@ -1475,9 +1615,13 @@ static int initialize_cpsch(struct device_queue_manager *dqm)
dqm->gws_queue_count = 0;
dqm->active_runlist = false;
INIT_WORK(&dqm->hw_exception_work, kfd_process_hw_exception);
+ dqm->trap_debug_vmid = 0;
init_sdma_bitmaps(dqm);
+ if (dqm->dev->kfd2kgd->get_iq_wait_times)
+ dqm->dev->kfd2kgd->get_iq_wait_times(dqm->dev->adev,
+ &dqm->wait_times);
return 0;
}
@@ -1489,7 +1633,7 @@ static int start_cpsch(struct device_queue_manager *dqm)
dqm_lock(dqm);
- if (!dqm->dev->shared_resources.enable_mes) {
+ if (!dqm->dev->kfd->shared_resources.enable_mes) {
retval = pm_init(&dqm->packet_mgr, dqm);
if (retval)
goto fail_packet_manager_init;
@@ -1516,14 +1660,15 @@ static int start_cpsch(struct device_queue_manager *dqm)
dqm->is_hws_hang = false;
dqm->is_resetting = false;
dqm->sched_running = true;
- if (!dqm->dev->shared_resources.enable_mes)
- execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0);
+
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
+ execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0, USE_DEFAULT_GRACE_PERIOD);
dqm_unlock(dqm);
return 0;
fail_allocate_vidmem:
fail_set_sched_resources:
- if (!dqm->dev->shared_resources.enable_mes)
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
pm_uninit(&dqm->packet_mgr, false);
fail_packet_manager_init:
dqm_unlock(dqm);
@@ -1541,8 +1686,8 @@ static int stop_cpsch(struct device_queue_manager *dqm)
}
if (!dqm->is_hws_hang) {
- if (!dqm->dev->shared_resources.enable_mes)
- unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0, false);
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
+ unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0, USE_DEFAULT_GRACE_PERIOD, false);
else
remove_all_queues_mes(dqm);
}
@@ -1550,11 +1695,11 @@ static int stop_cpsch(struct device_queue_manager *dqm)
hanging = dqm->is_hws_hang || dqm->is_resetting;
dqm->sched_running = false;
- if (!dqm->dev->shared_resources.enable_mes)
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
pm_release_ib(&dqm->packet_mgr);
kfd_gtt_sa_free(dqm->dev, dqm->fence_mem);
- if (!dqm->dev->shared_resources.enable_mes)
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
pm_uninit(&dqm->packet_mgr, hanging);
dqm_unlock(dqm);
@@ -1584,7 +1729,8 @@ static int create_kernel_queue_cpsch(struct device_queue_manager *dqm,
list_add(&kq->list, &qpd->priv_queue_list);
increment_queue_count(dqm, qpd, kq->queue);
qpd->is_debug = true;
- execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0);
+ execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0,
+ USE_DEFAULT_GRACE_PERIOD);
dqm_unlock(dqm);
return 0;
@@ -1598,7 +1744,8 @@ static void destroy_kernel_queue_cpsch(struct device_queue_manager *dqm,
list_del(&kq->list);
decrement_queue_count(dqm, qpd, kq->queue);
qpd->is_debug = false;
- execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0);
+ execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0,
+ USE_DEFAULT_GRACE_PERIOD);
/*
* Unconditionally decrement this counter, regardless of the queue's
* type.
@@ -1658,6 +1805,9 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q,
* updates the is_evicted flag but is a no-op otherwise.
*/
q->properties.is_evicted = !!qpd->evicted;
+ q->properties.is_dbg_wa = qpd->pqm->process->debug_trap_enabled &&
+ KFD_GC_VERSION(q->device) >= IP_VERSION(11, 0, 0) &&
+ KFD_GC_VERSION(q->device) <= IP_VERSION(11, 0, 3);
if (qd)
mqd_mgr->restore_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, &q->gart_mqd_addr,
@@ -1673,9 +1823,9 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q,
if (q->properties.is_active) {
increment_queue_count(dqm, qpd, q);
- if (!dqm->dev->shared_resources.enable_mes)
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
retval = execute_queues_cpsch(dqm,
- KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0);
+ KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0, USE_DEFAULT_GRACE_PERIOD);
else
retval = add_queue_mes(dqm, q, qpd);
if (retval)
@@ -1764,7 +1914,9 @@ static int map_queues_cpsch(struct device_queue_manager *dqm)
/* dqm->lock mutex has to be locked before calling this function */
static int unmap_queues_cpsch(struct device_queue_manager *dqm,
enum kfd_unmap_queues_filter filter,
- uint32_t filter_param, bool reset)
+ uint32_t filter_param,
+ uint32_t grace_period,
+ bool reset)
{
int retval = 0;
struct mqd_manager *mqd_mgr;
@@ -1776,6 +1928,12 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
if (!dqm->active_runlist)
return retval;
+ if (grace_period != USE_DEFAULT_GRACE_PERIOD) {
+ retval = pm_update_grace_period(&dqm->packet_mgr, grace_period);
+ if (retval)
+ return retval;
+ }
+
retval = pm_send_unmap_queue(&dqm->packet_mgr, filter, filter_param, reset);
if (retval)
return retval;
@@ -1808,6 +1966,13 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
return -ETIME;
}
+ /* We need to reset the grace period value for this device */
+ if (grace_period != USE_DEFAULT_GRACE_PERIOD) {
+ if (pm_update_grace_period(&dqm->packet_mgr,
+ USE_DEFAULT_GRACE_PERIOD))
+ pr_err("Failed to reset grace period\n");
+ }
+
pm_release_ib(&dqm->packet_mgr);
dqm->active_runlist = false;
@@ -1823,7 +1988,7 @@ static int reset_queues_cpsch(struct device_queue_manager *dqm,
dqm_lock(dqm);
retval = unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_BY_PASID,
- pasid, true);
+ pasid, USE_DEFAULT_GRACE_PERIOD, true);
dqm_unlock(dqm);
return retval;
@@ -1832,19 +1997,45 @@ static int reset_queues_cpsch(struct device_queue_manager *dqm,
/* dqm->lock mutex has to be locked before calling this function */
static int execute_queues_cpsch(struct device_queue_manager *dqm,
enum kfd_unmap_queues_filter filter,
- uint32_t filter_param)
+ uint32_t filter_param,
+ uint32_t grace_period)
{
int retval;
if (dqm->is_hws_hang)
return -EIO;
- retval = unmap_queues_cpsch(dqm, filter, filter_param, false);
+ retval = unmap_queues_cpsch(dqm, filter, filter_param, grace_period, false);
if (retval)
return retval;
return map_queues_cpsch(dqm);
}
+static int wait_on_destroy_queue(struct device_queue_manager *dqm,
+ struct queue *q)
+{
+ struct kfd_process_device *pdd = kfd_get_process_device_data(q->device,
+ q->process);
+ int ret = 0;
+
+ if (pdd->qpd.is_debug)
+ return ret;
+
+ q->properties.is_being_destroyed = true;
+
+ if (pdd->process->debug_trap_enabled && q->properties.is_suspended) {
+ dqm_unlock(dqm);
+ mutex_unlock(&q->process->mutex);
+ ret = wait_event_interruptible(dqm->destroy_wait,
+ !q->properties.is_suspended);
+
+ mutex_lock(&q->process->mutex);
+ dqm_lock(dqm);
+ }
+
+ return ret;
+}
+
static int destroy_queue_cpsch(struct device_queue_manager *dqm,
struct qcm_process_device *qpd,
struct queue *q)
@@ -1864,11 +2055,16 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
q->properties.queue_id);
}
- retval = 0;
-
/* remove queue from list to prevent rescheduling after preemption */
dqm_lock(dqm);
+ retval = wait_on_destroy_queue(dqm, q);
+
+ if (retval) {
+ dqm_unlock(dqm);
+ return retval;
+ }
+
if (qpd->is_debug) {
/*
* error, currently we do not allow to destroy a queue
@@ -1893,10 +2089,11 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
list_del(&q->list);
qpd->queue_count--;
if (q->properties.is_active) {
- if (!dqm->dev->shared_resources.enable_mes) {
- decrement_queue_count(dqm, qpd, q);
+ decrement_queue_count(dqm, qpd, q);
+ if (!dqm->dev->kfd->shared_resources.enable_mes) {
retval = execute_queues_cpsch(dqm,
- KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0);
+ KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0,
+ USE_DEFAULT_GRACE_PERIOD);
if (retval == -ETIME)
qpd->reset_wavefronts = true;
} else {
@@ -1914,7 +2111,14 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
dqm_unlock(dqm);
- /* Do free_mqd after dqm_unlock(dqm) to avoid circular locking */
+ /*
+ * Do free_mqd and raise delete event after dqm_unlock(dqm) to avoid
+ * circular locking
+ */
+ kfd_dbg_ev_raise(KFD_EC_MASK(EC_DEVICE_QUEUE_DELETE),
+ qpd->pqm->process, q->device,
+ -1, false, NULL, 0);
+
mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj);
return retval;
@@ -2056,7 +2260,7 @@ static int get_wave_state(struct device_queue_manager *dqm,
mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_CP];
if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE ||
- q->properties.is_active || !q->device->cwsr_enabled ||
+ q->properties.is_active || !q->device->kfd->cwsr_enabled ||
!mqd_mgr->get_wave_state) {
dqm_unlock(dqm);
return -EINVAL;
@@ -2069,8 +2273,8 @@ static int get_wave_state(struct device_queue_manager *dqm,
* and the queue should be protected against destruction by the process
* lock.
*/
- return mqd_mgr->get_wave_state(mqd_mgr, q->mqd, ctl_stack,
- ctl_stack_used_size, save_area_used_size);
+ return mqd_mgr->get_wave_state(mqd_mgr, q->mqd, &q->properties,
+ ctl_stack, ctl_stack_used_size, save_area_used_size);
}
static void get_queue_checkpoint_info(struct device_queue_manager *dqm,
@@ -2105,7 +2309,7 @@ static int checkpoint_mqd(struct device_queue_manager *dqm,
dqm_lock(dqm);
- if (q->properties.is_active || !q->device->cwsr_enabled) {
+ if (q->properties.is_active || !q->device->kfd->cwsr_enabled) {
r = -EINVAL;
goto dqm_unlock;
}
@@ -2158,7 +2362,7 @@ static int process_termination_cpsch(struct device_queue_manager *dqm,
if (q->properties.is_active) {
decrement_queue_count(dqm, qpd, q);
- if (dqm->dev->shared_resources.enable_mes) {
+ if (dqm->dev->kfd->shared_resources.enable_mes) {
retval = remove_queue_mes(dqm, q, qpd);
if (retval)
pr_err("Failed to remove queue %d\n",
@@ -2180,8 +2384,8 @@ static int process_termination_cpsch(struct device_queue_manager *dqm,
}
}
- if (!dqm->dev->shared_resources.enable_mes)
- retval = execute_queues_cpsch(dqm, filter, 0);
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
+ retval = execute_queues_cpsch(dqm, filter, 0, USE_DEFAULT_GRACE_PERIOD);
if ((!dqm->is_hws_hang) && (retval || qpd->reset_wavefronts)) {
pr_warn("Resetting wave fronts (cpsch) on dev %p\n", dqm->dev);
@@ -2242,12 +2446,13 @@ out_free:
static int allocate_hiq_sdma_mqd(struct device_queue_manager *dqm)
{
int retval;
- struct kfd_dev *dev = dqm->dev;
+ struct kfd_node *dev = dqm->dev;
struct kfd_mem_obj *mem_obj = &dqm->hiq_sdma_mqd;
uint32_t size = dqm->mqd_mgrs[KFD_MQD_TYPE_SDMA]->mqd_size *
get_num_all_sdma_engines(dqm) *
- dev->device_info.num_sdma_queues_per_engine +
- dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]->mqd_size;
+ dev->kfd->device_info.num_sdma_queues_per_engine +
+ (dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]->mqd_size *
+ NUM_XCC(dqm->dev->xcc_mask));
retval = amdgpu_amdkfd_alloc_gtt_mem(dev->adev, size,
&(mem_obj->gtt_mem), &(mem_obj->gpu_addr),
@@ -2256,7 +2461,7 @@ static int allocate_hiq_sdma_mqd(struct device_queue_manager *dqm)
return retval;
}
-struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev)
+struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
{
struct device_queue_manager *dqm;
@@ -2373,20 +2578,22 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev)
if (init_mqd_managers(dqm))
goto out_free;
- if (!dev->shared_resources.enable_mes && allocate_hiq_sdma_mqd(dqm)) {
+ if (!dev->kfd->shared_resources.enable_mes && allocate_hiq_sdma_mqd(dqm)) {
pr_err("Failed to allocate hiq sdma mqd trunk buffer\n");
goto out_free;
}
- if (!dqm->ops.initialize(dqm))
+ if (!dqm->ops.initialize(dqm)) {
+ init_waitqueue_head(&dqm->destroy_wait);
return dqm;
+ }
out_free:
kfree(dqm);
return NULL;
}
-static void deallocate_hiq_sdma_mqd(struct kfd_dev *dev,
+static void deallocate_hiq_sdma_mqd(struct kfd_node *dev,
struct kfd_mem_obj *mqd)
{
WARN(!mqd, "No hiq sdma mqd trunk to free");
@@ -2396,8 +2603,9 @@ static void deallocate_hiq_sdma_mqd(struct kfd_dev *dev,
void device_queue_manager_uninit(struct device_queue_manager *dqm)
{
+ dqm->ops.stop(dqm);
dqm->ops.uninitialize(dqm);
- if (!dqm->dev->shared_resources.enable_mes)
+ if (!dqm->dev->kfd->shared_resources.enable_mes)
deallocate_hiq_sdma_mqd(dqm->dev, &dqm->hiq_sdma_mqd);
kfree(dqm);
}
@@ -2426,6 +2634,498 @@ static void kfd_process_hw_exception(struct work_struct *work)
amdgpu_amdkfd_gpu_reset(dqm->dev->adev);
}
+int reserve_debug_trap_vmid(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd)
+{
+ int r;
+ int updated_vmid_mask;
+
+ if (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) {
+ pr_err("Unsupported on sched_policy: %i\n", dqm->sched_policy);
+ return -EINVAL;
+ }
+
+ dqm_lock(dqm);
+
+ if (dqm->trap_debug_vmid != 0) {
+ pr_err("Trap debug id already reserved\n");
+ r = -EBUSY;
+ goto out_unlock;
+ }
+
+ r = unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0,
+ USE_DEFAULT_GRACE_PERIOD, false);
+ if (r)
+ goto out_unlock;
+
+ updated_vmid_mask = dqm->dev->kfd->shared_resources.compute_vmid_bitmap;
+ updated_vmid_mask &= ~(1 << dqm->dev->vm_info.last_vmid_kfd);
+
+ dqm->dev->kfd->shared_resources.compute_vmid_bitmap = updated_vmid_mask;
+ dqm->trap_debug_vmid = dqm->dev->vm_info.last_vmid_kfd;
+ r = set_sched_resources(dqm);
+ if (r)
+ goto out_unlock;
+
+ r = map_queues_cpsch(dqm);
+ if (r)
+ goto out_unlock;
+
+ pr_debug("Reserved VMID for trap debug: %i\n", dqm->trap_debug_vmid);
+
+out_unlock:
+ dqm_unlock(dqm);
+ return r;
+}
+
+/*
+ * Releases vmid for the trap debugger
+ */
+int release_debug_trap_vmid(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd)
+{
+ int r;
+ int updated_vmid_mask;
+ uint32_t trap_debug_vmid;
+
+ if (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) {
+ pr_err("Unsupported on sched_policy: %i\n", dqm->sched_policy);
+ return -EINVAL;
+ }
+
+ dqm_lock(dqm);
+ trap_debug_vmid = dqm->trap_debug_vmid;
+ if (dqm->trap_debug_vmid == 0) {
+ pr_err("Trap debug id is not reserved\n");
+ r = -EINVAL;
+ goto out_unlock;
+ }
+
+ r = unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0,
+ USE_DEFAULT_GRACE_PERIOD, false);
+ if (r)
+ goto out_unlock;
+
+ updated_vmid_mask = dqm->dev->kfd->shared_resources.compute_vmid_bitmap;
+ updated_vmid_mask |= (1 << dqm->dev->vm_info.last_vmid_kfd);
+
+ dqm->dev->kfd->shared_resources.compute_vmid_bitmap = updated_vmid_mask;
+ dqm->trap_debug_vmid = 0;
+ r = set_sched_resources(dqm);
+ if (r)
+ goto out_unlock;
+
+ r = map_queues_cpsch(dqm);
+ if (r)
+ goto out_unlock;
+
+ pr_debug("Released VMID for trap debug: %i\n", trap_debug_vmid);
+
+out_unlock:
+ dqm_unlock(dqm);
+ return r;
+}
+
+#define QUEUE_NOT_FOUND -1
+/* invalidate queue operation in array */
+static void q_array_invalidate(uint32_t num_queues, uint32_t *queue_ids)
+{
+ int i;
+
+ for (i = 0; i < num_queues; i++)
+ queue_ids[i] |= KFD_DBG_QUEUE_INVALID_MASK;
+}
+
+/* find queue index in array */
+static int q_array_get_index(unsigned int queue_id,
+ uint32_t num_queues,
+ uint32_t *queue_ids)
+{
+ int i;
+
+ for (i = 0; i < num_queues; i++)
+ if (queue_id == (queue_ids[i] & ~KFD_DBG_QUEUE_INVALID_MASK))
+ return i;
+
+ return QUEUE_NOT_FOUND;
+}
+
+struct copy_context_work_handler_workarea {
+ struct work_struct copy_context_work;
+ struct kfd_process *p;
+};
+
+static void copy_context_work_handler (struct work_struct *work)
+{
+ struct copy_context_work_handler_workarea *workarea;
+ struct mqd_manager *mqd_mgr;
+ struct queue *q;
+ struct mm_struct *mm;
+ struct kfd_process *p;
+ uint32_t tmp_ctl_stack_used_size, tmp_save_area_used_size;
+ int i;
+
+ workarea = container_of(work,
+ struct copy_context_work_handler_workarea,
+ copy_context_work);
+
+ p = workarea->p;
+ mm = get_task_mm(p->lead_thread);
+
+ if (!mm)
+ return;
+
+ kthread_use_mm(mm);
+ for (i = 0; i < p->n_pdds; i++) {
+ struct kfd_process_device *pdd = p->pdds[i];
+ struct device_queue_manager *dqm = pdd->dev->dqm;
+ struct qcm_process_device *qpd = &pdd->qpd;
+
+ list_for_each_entry(q, &qpd->queues_list, list) {
+ mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_CP];
+
+ /* We ignore the return value from get_wave_state
+ * because
+ * i) right now, it always returns 0, and
+ * ii) if we hit an error, we would continue to the
+ * next queue anyway.
+ */
+ mqd_mgr->get_wave_state(mqd_mgr,
+ q->mqd,
+ &q->properties,
+ (void __user *) q->properties.ctx_save_restore_area_address,
+ &tmp_ctl_stack_used_size,
+ &tmp_save_area_used_size);
+ }
+ }
+ kthread_unuse_mm(mm);
+ mmput(mm);
+}
+
+static uint32_t *get_queue_ids(uint32_t num_queues, uint32_t *usr_queue_id_array)
+{
+ size_t array_size = num_queues * sizeof(uint32_t);
+ uint32_t *queue_ids = NULL;
+
+ if (!usr_queue_id_array)
+ return NULL;
+
+ queue_ids = kzalloc(array_size, GFP_KERNEL);
+ if (!queue_ids)
+ return ERR_PTR(-ENOMEM);
+
+ if (copy_from_user(queue_ids, usr_queue_id_array, array_size))
+ return ERR_PTR(-EFAULT);
+
+ return queue_ids;
+}
+
+int resume_queues(struct kfd_process *p,
+ uint32_t num_queues,
+ uint32_t *usr_queue_id_array)
+{
+ uint32_t *queue_ids = NULL;
+ int total_resumed = 0;
+ int i;
+
+ if (usr_queue_id_array) {
+ queue_ids = get_queue_ids(num_queues, usr_queue_id_array);
+
+ if (IS_ERR(queue_ids))
+ return PTR_ERR(queue_ids);
+
+ /* mask all queues as invalid. unmask per successful request */
+ q_array_invalidate(num_queues, queue_ids);
+ }
+
+ for (i = 0; i < p->n_pdds; i++) {
+ struct kfd_process_device *pdd = p->pdds[i];
+ struct device_queue_manager *dqm = pdd->dev->dqm;
+ struct qcm_process_device *qpd = &pdd->qpd;
+ struct queue *q;
+ int r, per_device_resumed = 0;
+
+ dqm_lock(dqm);
+
+ /* unmask queues that resume or already resumed as valid */
+ list_for_each_entry(q, &qpd->queues_list, list) {
+ int q_idx = QUEUE_NOT_FOUND;
+
+ if (queue_ids)
+ q_idx = q_array_get_index(
+ q->properties.queue_id,
+ num_queues,
+ queue_ids);
+
+ if (!queue_ids || q_idx != QUEUE_NOT_FOUND) {
+ int err = resume_single_queue(dqm, &pdd->qpd, q);
+
+ if (queue_ids) {
+ if (!err) {
+ queue_ids[q_idx] &=
+ ~KFD_DBG_QUEUE_INVALID_MASK;
+ } else {
+ queue_ids[q_idx] |=
+ KFD_DBG_QUEUE_ERROR_MASK;
+ break;
+ }
+ }
+
+ if (dqm->dev->kfd->shared_resources.enable_mes) {
+ wake_up_all(&dqm->destroy_wait);
+ if (!err)
+ total_resumed++;
+ } else {
+ per_device_resumed++;
+ }
+ }
+ }
+
+ if (!per_device_resumed) {
+ dqm_unlock(dqm);
+ continue;
+ }
+
+ r = execute_queues_cpsch(dqm,
+ KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES,
+ 0,
+ USE_DEFAULT_GRACE_PERIOD);
+ if (r) {
+ pr_err("Failed to resume process queues\n");
+ if (queue_ids) {
+ list_for_each_entry(q, &qpd->queues_list, list) {
+ int q_idx = q_array_get_index(
+ q->properties.queue_id,
+ num_queues,
+ queue_ids);
+
+ /* mask queue as error on resume fail */
+ if (q_idx != QUEUE_NOT_FOUND)
+ queue_ids[q_idx] |=
+ KFD_DBG_QUEUE_ERROR_MASK;
+ }
+ }
+ } else {
+ wake_up_all(&dqm->destroy_wait);
+ total_resumed += per_device_resumed;
+ }
+
+ dqm_unlock(dqm);
+ }
+
+ if (queue_ids) {
+ if (copy_to_user((void __user *)usr_queue_id_array, queue_ids,
+ num_queues * sizeof(uint32_t)))
+ pr_err("copy_to_user failed on queue resume\n");
+
+ kfree(queue_ids);
+ }
+
+ return total_resumed;
+}
+
+int suspend_queues(struct kfd_process *p,
+ uint32_t num_queues,
+ uint32_t grace_period,
+ uint64_t exception_clear_mask,
+ uint32_t *usr_queue_id_array)
+{
+ uint32_t *queue_ids = get_queue_ids(num_queues, usr_queue_id_array);
+ int total_suspended = 0;
+ int i;
+
+ if (IS_ERR(queue_ids))
+ return PTR_ERR(queue_ids);
+
+ /* mask all queues as invalid. umask on successful request */
+ q_array_invalidate(num_queues, queue_ids);
+
+ for (i = 0; i < p->n_pdds; i++) {
+ struct kfd_process_device *pdd = p->pdds[i];
+ struct device_queue_manager *dqm = pdd->dev->dqm;
+ struct qcm_process_device *qpd = &pdd->qpd;
+ struct queue *q;
+ int r, per_device_suspended = 0;
+
+ mutex_lock(&p->event_mutex);
+ dqm_lock(dqm);
+
+ /* unmask queues that suspend or already suspended */
+ list_for_each_entry(q, &qpd->queues_list, list) {
+ int q_idx = q_array_get_index(q->properties.queue_id,
+ num_queues,
+ queue_ids);
+
+ if (q_idx != QUEUE_NOT_FOUND) {
+ int err = suspend_single_queue(dqm, pdd, q);
+ bool is_mes = dqm->dev->kfd->shared_resources.enable_mes;
+
+ if (!err) {
+ queue_ids[q_idx] &= ~KFD_DBG_QUEUE_INVALID_MASK;
+ if (exception_clear_mask && is_mes)
+ q->properties.exception_status &=
+ ~exception_clear_mask;
+
+ if (is_mes)
+ total_suspended++;
+ else
+ per_device_suspended++;
+ } else if (err != -EBUSY) {
+ r = err;
+ queue_ids[q_idx] |= KFD_DBG_QUEUE_ERROR_MASK;
+ break;
+ }
+ }
+ }
+
+ if (!per_device_suspended) {
+ dqm_unlock(dqm);
+ mutex_unlock(&p->event_mutex);
+ if (total_suspended)
+ amdgpu_amdkfd_debug_mem_fence(dqm->dev->adev);
+ continue;
+ }
+
+ r = execute_queues_cpsch(dqm,
+ KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0,
+ grace_period);
+
+ if (r)
+ pr_err("Failed to suspend process queues.\n");
+ else
+ total_suspended += per_device_suspended;
+
+ list_for_each_entry(q, &qpd->queues_list, list) {
+ int q_idx = q_array_get_index(q->properties.queue_id,
+ num_queues, queue_ids);
+
+ if (q_idx == QUEUE_NOT_FOUND)
+ continue;
+
+ /* mask queue as error on suspend fail */
+ if (r)
+ queue_ids[q_idx] |= KFD_DBG_QUEUE_ERROR_MASK;
+ else if (exception_clear_mask)
+ q->properties.exception_status &=
+ ~exception_clear_mask;
+ }
+
+ dqm_unlock(dqm);
+ mutex_unlock(&p->event_mutex);
+ amdgpu_device_flush_hdp(dqm->dev->adev, NULL);
+ }
+
+ if (total_suspended) {
+ struct copy_context_work_handler_workarea copy_context_worker;
+
+ INIT_WORK_ONSTACK(
+ &copy_context_worker.copy_context_work,
+ copy_context_work_handler);
+
+ copy_context_worker.p = p;
+
+ schedule_work(&copy_context_worker.copy_context_work);
+
+
+ flush_work(&copy_context_worker.copy_context_work);
+ destroy_work_on_stack(&copy_context_worker.copy_context_work);
+ }
+
+ if (copy_to_user((void __user *)usr_queue_id_array, queue_ids,
+ num_queues * sizeof(uint32_t)))
+ pr_err("copy_to_user failed on queue suspend\n");
+
+ kfree(queue_ids);
+
+ return total_suspended;
+}
+
+static uint32_t set_queue_type_for_user(struct queue_properties *q_props)
+{
+ switch (q_props->type) {
+ case KFD_QUEUE_TYPE_COMPUTE:
+ return q_props->format == KFD_QUEUE_FORMAT_PM4
+ ? KFD_IOC_QUEUE_TYPE_COMPUTE
+ : KFD_IOC_QUEUE_TYPE_COMPUTE_AQL;
+ case KFD_QUEUE_TYPE_SDMA:
+ return KFD_IOC_QUEUE_TYPE_SDMA;
+ case KFD_QUEUE_TYPE_SDMA_XGMI:
+ return KFD_IOC_QUEUE_TYPE_SDMA_XGMI;
+ default:
+ WARN_ONCE(true, "queue type not recognized!");
+ return 0xffffffff;
+ };
+}
+
+void set_queue_snapshot_entry(struct queue *q,
+ uint64_t exception_clear_mask,
+ struct kfd_queue_snapshot_entry *qss_entry)
+{
+ qss_entry->ring_base_address = q->properties.queue_address;
+ qss_entry->write_pointer_address = (uint64_t)q->properties.write_ptr;
+ qss_entry->read_pointer_address = (uint64_t)q->properties.read_ptr;
+ qss_entry->ctx_save_restore_address =
+ q->properties.ctx_save_restore_area_address;
+ qss_entry->ctx_save_restore_area_size =
+ q->properties.ctx_save_restore_area_size;
+ qss_entry->exception_status = q->properties.exception_status;
+ qss_entry->queue_id = q->properties.queue_id;
+ qss_entry->gpu_id = q->device->id;
+ qss_entry->ring_size = (uint32_t)q->properties.queue_size;
+ qss_entry->queue_type = set_queue_type_for_user(&q->properties);
+ q->properties.exception_status &= ~exception_clear_mask;
+}
+
+int debug_lock_and_unmap(struct device_queue_manager *dqm)
+{
+ int r;
+
+ if (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) {
+ pr_err("Unsupported on sched_policy: %i\n", dqm->sched_policy);
+ return -EINVAL;
+ }
+
+ if (!kfd_dbg_is_per_vmid_supported(dqm->dev))
+ return 0;
+
+ dqm_lock(dqm);
+
+ r = unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0, 0, false);
+ if (r)
+ dqm_unlock(dqm);
+
+ return r;
+}
+
+int debug_map_and_unlock(struct device_queue_manager *dqm)
+{
+ int r;
+
+ if (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) {
+ pr_err("Unsupported on sched_policy: %i\n", dqm->sched_policy);
+ return -EINVAL;
+ }
+
+ if (!kfd_dbg_is_per_vmid_supported(dqm->dev))
+ return 0;
+
+ r = map_queues_cpsch(dqm);
+
+ dqm_unlock(dqm);
+
+ return r;
+}
+
+int debug_refresh_runlist(struct device_queue_manager *dqm)
+{
+ int r = debug_lock_and_unmap(dqm);
+
+ if (r)
+ return r;
+
+ return debug_map_and_unlock(dqm);
+}
+
#if defined(CONFIG_DEBUG_FS)
static void seq_reg_dump(struct seq_file *m,
@@ -2452,52 +3152,66 @@ static void seq_reg_dump(struct seq_file *m,
int dqm_debugfs_hqds(struct seq_file *m, void *data)
{
struct device_queue_manager *dqm = data;
+ uint32_t xcc_mask = dqm->dev->xcc_mask;
uint32_t (*dump)[2], n_regs;
int pipe, queue;
- int r = 0;
+ int r = 0, xcc_id;
+ uint32_t sdma_engine_start;
if (!dqm->sched_running) {
seq_puts(m, " Device is stopped\n");
return 0;
}
- r = dqm->dev->kfd2kgd->hqd_dump(dqm->dev->adev,
- KFD_CIK_HIQ_PIPE, KFD_CIK_HIQ_QUEUE,
- &dump, &n_regs);
- if (!r) {
- seq_printf(m, " HIQ on MEC %d Pipe %d Queue %d\n",
- KFD_CIK_HIQ_PIPE/get_pipes_per_mec(dqm)+1,
- KFD_CIK_HIQ_PIPE%get_pipes_per_mec(dqm),
- KFD_CIK_HIQ_QUEUE);
- seq_reg_dump(m, dump, n_regs);
+ for_each_inst(xcc_id, xcc_mask) {
+ r = dqm->dev->kfd2kgd->hqd_dump(dqm->dev->adev,
+ KFD_CIK_HIQ_PIPE,
+ KFD_CIK_HIQ_QUEUE, &dump,
+ &n_regs, xcc_id);
+ if (!r) {
+ seq_printf(
+ m,
+ " Inst %d, HIQ on MEC %d Pipe %d Queue %d\n",
+ xcc_id,
+ KFD_CIK_HIQ_PIPE / get_pipes_per_mec(dqm) + 1,
+ KFD_CIK_HIQ_PIPE % get_pipes_per_mec(dqm),
+ KFD_CIK_HIQ_QUEUE);
+ seq_reg_dump(m, dump, n_regs);
- kfree(dump);
- }
+ kfree(dump);
+ }
- for (pipe = 0; pipe < get_pipes_per_mec(dqm); pipe++) {
- int pipe_offset = pipe * get_queues_per_pipe(dqm);
+ for (pipe = 0; pipe < get_pipes_per_mec(dqm); pipe++) {
+ int pipe_offset = pipe * get_queues_per_pipe(dqm);
- for (queue = 0; queue < get_queues_per_pipe(dqm); queue++) {
- if (!test_bit(pipe_offset + queue,
- dqm->dev->shared_resources.cp_queue_bitmap))
- continue;
+ for (queue = 0; queue < get_queues_per_pipe(dqm); queue++) {
+ if (!test_bit(pipe_offset + queue,
+ dqm->dev->kfd->shared_resources.cp_queue_bitmap))
+ continue;
- r = dqm->dev->kfd2kgd->hqd_dump(
- dqm->dev->adev, pipe, queue, &dump, &n_regs);
- if (r)
- break;
+ r = dqm->dev->kfd2kgd->hqd_dump(dqm->dev->adev,
+ pipe, queue,
+ &dump, &n_regs,
+ xcc_id);
+ if (r)
+ break;
- seq_printf(m, " CP Pipe %d, Queue %d\n",
- pipe, queue);
- seq_reg_dump(m, dump, n_regs);
+ seq_printf(m,
+ " Inst %d, CP Pipe %d, Queue %d\n",
+ xcc_id, pipe, queue);
+ seq_reg_dump(m, dump, n_regs);
- kfree(dump);
+ kfree(dump);
+ }
}
}
- for (pipe = 0; pipe < get_num_all_sdma_engines(dqm); pipe++) {
+ sdma_engine_start = dqm->dev->node_id * get_num_all_sdma_engines(dqm);
+ for (pipe = sdma_engine_start;
+ pipe < (sdma_engine_start + get_num_all_sdma_engines(dqm));
+ pipe++) {
for (queue = 0;
- queue < dqm->dev->device_info.num_sdma_queues_per_engine;
+ queue < dqm->dev->kfd->device_info.num_sdma_queues_per_engine;
queue++) {
r = dqm->dev->kfd2kgd->hqd_sdma_dump(
dqm->dev->adev, pipe, queue, &dump, &n_regs);
@@ -2526,7 +3240,8 @@ int dqm_debugfs_hang_hws(struct device_queue_manager *dqm)
return r;
}
dqm->active_runlist = true;
- r = execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0);
+ r = execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES,
+ 0, USE_DEFAULT_GRACE_PERIOD);
dqm_unlock(dqm);
return r;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
index a537b9ef3e16..7dd4b177219d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
@@ -37,6 +37,7 @@
#define KFD_MES_PROCESS_QUANTUM 100000
#define KFD_MES_GANG_QUANTUM 10000
+#define USE_DEFAULT_GRACE_PERIOD 0xffffffff
struct device_process_node {
struct qcm_process_device *qpd;
@@ -207,7 +208,7 @@ struct device_queue_manager_asic_ops {
struct queue *q,
struct qcm_process_device *qpd);
struct mqd_manager * (*mqd_manager_init)(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev);
+ struct kfd_node *dev);
};
/**
@@ -228,7 +229,7 @@ struct device_queue_manager {
struct mqd_manager *mqd_mgrs[KFD_MQD_TYPE_MAX];
struct packet_manager packet_mgr;
- struct kfd_dev *dev;
+ struct kfd_node *dev;
struct mutex lock_hidden; /* use dqm_lock/unlock(dqm) */
struct list_head queues;
unsigned int saved_flags;
@@ -239,8 +240,8 @@ struct device_queue_manager {
unsigned int total_queue_count;
unsigned int next_pipe_to_allocate;
unsigned int *allocated_queues;
- uint64_t sdma_bitmap;
- uint64_t xgmi_sdma_bitmap;
+ DECLARE_BITMAP(sdma_bitmap, KFD_MAX_SDMA_QUEUES);
+ DECLARE_BITMAP(xgmi_sdma_bitmap, KFD_MAX_SDMA_QUEUES);
/* the pasid mapping for each kfd vmid */
uint16_t vmid_pasid[VMID_NUM];
uint64_t pipelines_addr;
@@ -249,6 +250,7 @@ struct device_queue_manager {
struct kfd_mem_obj *fence_mem;
bool active_runlist;
int sched_policy;
+ uint32_t trap_debug_vmid;
/* hw exception */
bool is_hws_hang;
@@ -256,6 +258,13 @@ struct device_queue_manager {
struct work_struct hw_exception_work;
struct kfd_mem_obj hiq_sdma_mqd;
bool sched_running;
+
+ /* used for GFX 9.4.3 only */
+ uint32_t current_logical_xcc_start;
+
+ uint32_t wait_times;
+
+ wait_queue_head_t destroy_wait;
};
void device_queue_manager_init_cik(
@@ -279,6 +288,24 @@ unsigned int get_queues_per_pipe(struct device_queue_manager *dqm);
unsigned int get_pipes_per_mec(struct device_queue_manager *dqm);
unsigned int get_num_sdma_queues(struct device_queue_manager *dqm);
unsigned int get_num_xgmi_sdma_queues(struct device_queue_manager *dqm);
+int reserve_debug_trap_vmid(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd);
+int release_debug_trap_vmid(struct device_queue_manager *dqm,
+ struct qcm_process_device *qpd);
+int suspend_queues(struct kfd_process *p,
+ uint32_t num_queues,
+ uint32_t grace_period,
+ uint64_t exception_clear_mask,
+ uint32_t *usr_queue_id_array);
+int resume_queues(struct kfd_process *p,
+ uint32_t num_queues,
+ uint32_t *usr_queue_id_array);
+void set_queue_snapshot_entry(struct queue *q,
+ uint64_t exception_clear_mask,
+ struct kfd_queue_snapshot_entry *qss_entry);
+int debug_lock_and_unmap(struct device_queue_manager *dqm);
+int debug_map_and_unlock(struct device_queue_manager *dqm);
+int debug_refresh_runlist(struct device_queue_manager *dqm);
static inline unsigned int get_sh_mem_bases_32(struct kfd_process_device *pdd)
{
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c
index 8b2dd2670ab7..8af643388768 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c
@@ -24,9 +24,7 @@
#include "kfd_device_queue_manager.h"
#include "vega10_enum.h"
-#include "gc/gc_9_0_offset.h"
-#include "gc/gc_9_0_sh_mask.h"
-#include "sdma0/sdma0_4_0_sh_mask.h"
+#include "gc/gc_9_4_3_sh_mask.h"
static int update_qpd_v9(struct device_queue_manager *dqm,
struct qcm_process_device *qpd);
@@ -62,9 +60,13 @@ static int update_qpd_v9(struct device_queue_manager *dqm,
qpd->sh_mem_config = SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT;
- if (dqm->dev->noretry && !dqm->dev->use_iommu_v2)
+ if (dqm->dev->kfd->noretry && !dqm->dev->kfd->use_iommu_v2)
qpd->sh_mem_config |= 1 << SH_MEM_CONFIG__RETRY_DISABLE__SHIFT;
+ if (KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 3))
+ qpd->sh_mem_config |=
+ (1 << SH_MEM_CONFIG__F8_MODE__SHIFT);
+
qpd->sh_mem_ape1_limit = 0;
qpd->sh_mem_ape1_base = 0;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
index 38c9e1ca6691..6421b620388d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
@@ -138,7 +138,7 @@ void kfd_doorbell_fini(struct kfd_dev *kfd)
iounmap(kfd->doorbell_kernel_ptr);
}
-int kfd_doorbell_mmap(struct kfd_dev *dev, struct kfd_process *process,
+int kfd_doorbell_mmap(struct kfd_node *dev, struct kfd_process *process,
struct vm_area_struct *vma)
{
phys_addr_t address;
@@ -148,7 +148,7 @@ int kfd_doorbell_mmap(struct kfd_dev *dev, struct kfd_process *process,
* For simplicitly we only allow mapping of the entire doorbell
* allocation of a single device & process.
*/
- if (vma->vm_end - vma->vm_start != kfd_doorbell_process_slice(dev))
+ if (vma->vm_end - vma->vm_start != kfd_doorbell_process_slice(dev->kfd))
return -EINVAL;
pdd = kfd_get_process_device_data(dev, process);
@@ -170,13 +170,13 @@ int kfd_doorbell_mmap(struct kfd_dev *dev, struct kfd_process *process,
" vm_flags == 0x%04lX\n"
" size == 0x%04lX\n",
(unsigned long long) vma->vm_start, address, vma->vm_flags,
- kfd_doorbell_process_slice(dev));
+ kfd_doorbell_process_slice(dev->kfd));
return io_remap_pfn_range(vma,
vma->vm_start,
address >> PAGE_SHIFT,
- kfd_doorbell_process_slice(dev),
+ kfd_doorbell_process_slice(dev->kfd),
vma->vm_page_prot);
}
@@ -278,14 +278,14 @@ uint64_t kfd_get_number_elems(struct kfd_dev *kfd)
phys_addr_t kfd_get_process_doorbells(struct kfd_process_device *pdd)
{
if (!pdd->doorbell_index) {
- int r = kfd_alloc_process_doorbells(pdd->dev,
+ int r = kfd_alloc_process_doorbells(pdd->dev->kfd,
&pdd->doorbell_index);
if (r < 0)
return 0;
}
- return pdd->dev->doorbell_base +
- pdd->doorbell_index * kfd_doorbell_process_slice(pdd->dev);
+ return pdd->dev->kfd->doorbell_base +
+ pdd->doorbell_index * kfd_doorbell_process_slice(pdd->dev->kfd);
}
int kfd_alloc_process_doorbells(struct kfd_dev *kfd, unsigned int *doorbell_index)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
index c894cf8f7c50..8081a9408006 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
@@ -41,6 +41,7 @@ struct kfd_event_waiter {
wait_queue_entry_t wait;
struct kfd_event *event; /* Event to wait for */
bool activated; /* Becomes true when event is signaled */
+ bool event_age_enabled; /* set to true when last_event_age is non-zero */
};
/*
@@ -348,7 +349,7 @@ static int kfd_event_page_set(struct kfd_process *p, void *kernel_address,
int kfd_kmap_event_page(struct kfd_process *p, uint64_t event_page_offset)
{
- struct kfd_dev *kfd;
+ struct kfd_node *kfd;
struct kfd_process_device *pdd;
void *mem, *kern_addr;
uint64_t size;
@@ -431,6 +432,7 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p,
if (!ret) {
*event_id = ev->event_id;
*event_trigger_data = ev->event_id;
+ ev->event_age = 1;
} else {
kfree(ev);
}
@@ -629,6 +631,11 @@ static void set_event(struct kfd_event *ev)
* updating the wait queues in kfd_wait_on_events.
*/
ev->signaled = !ev->auto_reset || !waitqueue_active(&ev->wq);
+ if (!(++ev->event_age)) {
+ /* Never wrap back to reserved/default event age 0/1 */
+ ev->event_age = 2;
+ WARN_ONCE(1, "event_age wrap back!");
+ }
list_for_each_entry(waiter, &ev->wq.head, wait.entry)
WRITE_ONCE(waiter->activated, true);
@@ -791,9 +798,9 @@ static struct kfd_event_waiter *alloc_event_waiters(uint32_t num_events)
static int init_event_waiter(struct kfd_process *p,
struct kfd_event_waiter *waiter,
- uint32_t event_id)
+ struct kfd_event_data *event_data)
{
- struct kfd_event *ev = lookup_event_by_id(p, event_id);
+ struct kfd_event *ev = lookup_event_by_id(p, event_data->event_id);
if (!ev)
return -EINVAL;
@@ -802,6 +809,15 @@ static int init_event_waiter(struct kfd_process *p,
waiter->event = ev;
waiter->activated = ev->signaled;
ev->signaled = ev->signaled && !ev->auto_reset;
+
+ /* last_event_age = 0 reserved for backward compatible */
+ if (waiter->event->type == KFD_EVENT_TYPE_SIGNAL &&
+ event_data->signal_event_data.last_event_age) {
+ waiter->event_age_enabled = true;
+ if (ev->event_age != event_data->signal_event_data.last_event_age)
+ waiter->activated = true;
+ }
+
if (!waiter->activated)
add_wait_queue(&ev->wq, &waiter->wait);
spin_unlock(&ev->lock);
@@ -849,22 +865,29 @@ static int copy_signaled_event_data(uint32_t num_events,
struct kfd_event_waiter *event_waiters,
struct kfd_event_data __user *data)
{
- struct kfd_hsa_memory_exception_data *src;
- struct kfd_hsa_memory_exception_data __user *dst;
+ void *src;
+ void __user *dst;
struct kfd_event_waiter *waiter;
struct kfd_event *event;
- uint32_t i;
+ uint32_t i, size = 0;
for (i = 0; i < num_events; i++) {
waiter = &event_waiters[i];
event = waiter->event;
if (!event)
return -EINVAL; /* event was destroyed */
- if (waiter->activated && event->type == KFD_EVENT_TYPE_MEMORY) {
- dst = &data[i].memory_exception_data;
- src = &event->memory_exception_data;
- if (copy_to_user(dst, src,
- sizeof(struct kfd_hsa_memory_exception_data)))
+ if (waiter->activated) {
+ if (event->type == KFD_EVENT_TYPE_MEMORY) {
+ dst = &data[i].memory_exception_data;
+ src = &event->memory_exception_data;
+ size = sizeof(struct kfd_hsa_memory_exception_data);
+ } else if (event->type == KFD_EVENT_TYPE_SIGNAL &&
+ waiter->event_age_enabled) {
+ dst = &data[i].signal_event_data.last_event_age;
+ src = &event->event_age;
+ size = sizeof(u64);
+ }
+ if (size && copy_to_user(dst, src, size))
return -EFAULT;
}
}
@@ -942,8 +965,7 @@ int kfd_wait_on_events(struct kfd_process *p,
goto out_unlock;
}
- ret = init_event_waiter(p, &event_waiters[i],
- event_data.event_id);
+ ret = init_event_waiter(p, &event_waiters[i], &event_data);
if (ret)
goto out_unlock;
}
@@ -1125,7 +1147,7 @@ static void lookup_events_by_type_and_signal(struct kfd_process *p,
}
#ifdef KFD_SUPPORT_IOMMU_V2
-void kfd_signal_iommu_event(struct kfd_dev *dev, u32 pasid,
+void kfd_signal_iommu_event(struct kfd_node *dev, u32 pasid,
unsigned long address, bool is_write_requested,
bool is_execute_requested)
{
@@ -1221,8 +1243,9 @@ void kfd_signal_hw_exception_event(u32 pasid)
kfd_unref_process(p);
}
-void kfd_signal_vm_fault_event(struct kfd_dev *dev, u32 pasid,
- struct kfd_vm_fault_info *info)
+void kfd_signal_vm_fault_event(struct kfd_node *dev, u32 pasid,
+ struct kfd_vm_fault_info *info,
+ struct kfd_hsa_memory_exception_data *data)
{
struct kfd_event *ev;
uint32_t id;
@@ -1239,19 +1262,24 @@ void kfd_signal_vm_fault_event(struct kfd_dev *dev, u32 pasid,
return;
}
- memset(&memory_exception_data, 0, sizeof(memory_exception_data));
- memory_exception_data.gpu_id = user_gpu_id;
- memory_exception_data.failure.imprecise = true;
- /* Set failure reason */
- if (info) {
- memory_exception_data.va = (info->page_addr) << PAGE_SHIFT;
- memory_exception_data.failure.NotPresent =
- info->prot_valid ? 1 : 0;
- memory_exception_data.failure.NoExecute =
- info->prot_exec ? 1 : 0;
- memory_exception_data.failure.ReadOnly =
- info->prot_write ? 1 : 0;
- memory_exception_data.failure.imprecise = 0;
+ /* SoC15 chips and onwards will pass in data from now on. */
+ if (!data) {
+ memset(&memory_exception_data, 0, sizeof(memory_exception_data));
+ memory_exception_data.gpu_id = user_gpu_id;
+ memory_exception_data.failure.imprecise = true;
+
+ /* Set failure reason */
+ if (info) {
+ memory_exception_data.va = (info->page_addr) <<
+ PAGE_SHIFT;
+ memory_exception_data.failure.NotPresent =
+ info->prot_valid ? 1 : 0;
+ memory_exception_data.failure.NoExecute =
+ info->prot_exec ? 1 : 0;
+ memory_exception_data.failure.ReadOnly =
+ info->prot_write ? 1 : 0;
+ memory_exception_data.failure.imprecise = 0;
+ }
}
rcu_read_lock();
@@ -1260,7 +1288,8 @@ void kfd_signal_vm_fault_event(struct kfd_dev *dev, u32 pasid,
idr_for_each_entry_continue(&p->event_idr, ev, id)
if (ev->type == KFD_EVENT_TYPE_MEMORY) {
spin_lock(&ev->lock);
- ev->memory_exception_data = memory_exception_data;
+ ev->memory_exception_data = data ? *data :
+ memory_exception_data;
set_event(ev);
spin_unlock(&ev->lock);
}
@@ -1269,7 +1298,7 @@ void kfd_signal_vm_fault_event(struct kfd_dev *dev, u32 pasid,
kfd_unref_process(p);
}
-void kfd_signal_reset_event(struct kfd_dev *dev)
+void kfd_signal_reset_event(struct kfd_node *dev)
{
struct kfd_hsa_hw_exception_data hw_exception_data;
struct kfd_hsa_memory_exception_data memory_exception_data;
@@ -1325,7 +1354,7 @@ void kfd_signal_reset_event(struct kfd_dev *dev)
srcu_read_unlock(&kfd_processes_srcu, idx);
}
-void kfd_signal_poison_consumed_event(struct kfd_dev *dev, u32 pasid)
+void kfd_signal_poison_consumed_event(struct kfd_node *dev, u32 pasid)
{
struct kfd_process *p = kfd_lookup_process_by_pasid(pasid);
struct kfd_hsa_memory_exception_data memory_exception_data;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.h b/drivers/gpu/drm/amd/amdkfd/kfd_events.h
index 1c62c8dd6460..52ccfd397c2b 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.h
@@ -53,6 +53,7 @@ struct signal_page;
struct kfd_event {
u32 event_id;
+ u64 event_age;
bool signaled;
bool auto_reset;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
index 8aebe408c544..da2ca00d79e5 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
@@ -322,21 +322,21 @@ static void kfd_init_apertures_vi(struct kfd_process_device *pdd, uint8_t id)
pdd->lds_base = MAKE_LDS_APP_BASE_VI();
pdd->lds_limit = MAKE_LDS_APP_LIMIT(pdd->lds_base);
- if (!pdd->dev->use_iommu_v2) {
+ if (!pdd->dev->kfd->use_iommu_v2) {
/* dGPUs: SVM aperture starting at 0
* with small reserved space for kernel.
* Set them to CANONICAL addresses.
*/
pdd->gpuvm_base = SVM_USER_BASE;
pdd->gpuvm_limit =
- pdd->dev->shared_resources.gpuvm_size - 1;
+ pdd->dev->kfd->shared_resources.gpuvm_size - 1;
} else {
/* set them to non CANONICAL addresses, and no SVM is
* allocated.
*/
pdd->gpuvm_base = MAKE_GPUVM_APP_BASE_VI(id + 1);
pdd->gpuvm_limit = MAKE_GPUVM_APP_LIMIT(pdd->gpuvm_base,
- pdd->dev->shared_resources.gpuvm_size);
+ pdd->dev->kfd->shared_resources.gpuvm_size);
}
pdd->scratch_base = MAKE_SCRATCH_APP_BASE_VI();
@@ -356,7 +356,7 @@ static void kfd_init_apertures_v9(struct kfd_process_device *pdd, uint8_t id)
*/
pdd->gpuvm_base = SVM_USER_BASE;
pdd->gpuvm_limit =
- pdd->dev->shared_resources.gpuvm_size - 1;
+ pdd->dev->kfd->shared_resources.gpuvm_size - 1;
pdd->scratch_base = MAKE_SCRATCH_APP_BASE_V9();
pdd->scratch_limit = MAKE_SCRATCH_APP_LIMIT(pdd->scratch_base);
@@ -365,7 +365,7 @@ static void kfd_init_apertures_v9(struct kfd_process_device *pdd, uint8_t id)
int kfd_init_apertures(struct kfd_process *process)
{
uint8_t id = 0;
- struct kfd_dev *dev;
+ struct kfd_node *dev;
struct kfd_process_device *pdd;
/*Iterating over all devices*/
@@ -417,7 +417,7 @@ int kfd_init_apertures(struct kfd_process *process)
}
}
- if (!dev->use_iommu_v2) {
+ if (!dev->kfd->use_iommu_v2) {
/* dGPUs: the reserved space for kernel
* before SVM
*/
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c
new file mode 100644
index 000000000000..c7991e07b6be
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "kfd_events.h"
+#include "kfd_debug.h"
+#include "soc15_int.h"
+#include "kfd_device_queue_manager.h"
+
+/*
+ * GFX10 SQ Interrupts
+ *
+ * There are 3 encoding types of interrupts sourced from SQ sent as a 44-bit
+ * packet to the Interrupt Handler:
+ * Auto - Generated by the SQG (various cmd overflows, timestamps etc)
+ * Wave - Generated by S_SENDMSG through a shader program
+ * Error - HW generated errors (Illegal instructions, Memviols, EDC etc)
+ *
+ * The 44-bit packet is mapped as {context_id1[7:0],context_id0[31:0]} plus
+ * 4-bits for VMID (SOC15_VMID_FROM_IH_ENTRY) as such:
+ *
+ * - context_id1[7:6]
+ * Encoding type (0 = Auto, 1 = Wave, 2 = Error)
+ *
+ * - context_id0[24]
+ * PRIV bit indicates that Wave S_SEND or error occurred within trap
+ *
+ * - context_id0[22:0]
+ * 23-bit data with the following layout per encoding type:
+ * Auto - only context_id0[8:0] is used, which reports various interrupts
+ * generated by SQG. The rest is 0.
+ * Wave - user data sent from m0 via S_SENDMSG
+ * Error - Error type (context_id0[22:19]), Error Details (rest of bits)
+ *
+ * The other context_id bits show coordinates (SE/SH/CU/SIMD/WGP) for wave
+ * S_SENDMSG and Errors. These are 0 for Auto.
+ */
+
+enum SQ_INTERRUPT_WORD_ENCODING {
+ SQ_INTERRUPT_WORD_ENCODING_AUTO = 0x0,
+ SQ_INTERRUPT_WORD_ENCODING_INST,
+ SQ_INTERRUPT_WORD_ENCODING_ERROR,
+};
+
+enum SQ_INTERRUPT_ERROR_TYPE {
+ SQ_INTERRUPT_ERROR_TYPE_EDC_FUE = 0x0,
+ SQ_INTERRUPT_ERROR_TYPE_ILLEGAL_INST,
+ SQ_INTERRUPT_ERROR_TYPE_MEMVIOL,
+ SQ_INTERRUPT_ERROR_TYPE_EDC_FED,
+};
+
+/* SQ_INTERRUPT_WORD_AUTO_CTXID */
+#define SQ_INTERRUPT_WORD_AUTO_CTXID0__THREAD_TRACE__SHIFT 0
+#define SQ_INTERRUPT_WORD_AUTO_CTXID0__WLT__SHIFT 1
+#define SQ_INTERRUPT_WORD_AUTO_CTXID0__THREAD_TRACE_BUF0_FULL__SHIFT 2
+#define SQ_INTERRUPT_WORD_AUTO_CTXID0__THREAD_TRACE_BUF1_FULL__SHIFT 3
+#define SQ_INTERRUPT_WORD_AUTO_CTXID0__THREAD_TRACE_UTC_ERROR__SHIFT 7
+#define SQ_INTERRUPT_WORD_AUTO_CTXID1__SE_ID__SHIFT 4
+#define SQ_INTERRUPT_WORD_AUTO_CTXID1__ENCODING__SHIFT 6
+
+#define SQ_INTERRUPT_WORD_AUTO_CTXID0__THREAD_TRACE_MASK 0x00000001
+#define SQ_INTERRUPT_WORD_AUTO_CTXID0__WLT_MASK 0x00000002
+#define SQ_INTERRUPT_WORD_AUTO_CTXID0__THREAD_TRACE_BUF0_FULL_MASK 0x00000004
+#define SQ_INTERRUPT_WORD_AUTO_CTXID0__THREAD_TRACE_BUF1_FULL_MASK 0x00000008
+#define SQ_INTERRUPT_WORD_AUTO_CTXID0__THREAD_TRACE_UTC_ERROR_MASK 0x00000080
+#define SQ_INTERRUPT_WORD_AUTO_CTXID1__SE_ID_MASK 0x030
+#define SQ_INTERRUPT_WORD_AUTO_CTXID1__ENCODING_MASK 0x0c0
+
+/* SQ_INTERRUPT_WORD_WAVE_CTXID */
+#define SQ_INTERRUPT_WORD_WAVE_CTXID0__DATA__SHIFT 0
+#define SQ_INTERRUPT_WORD_WAVE_CTXID0__SA_ID__SHIFT 23
+#define SQ_INTERRUPT_WORD_WAVE_CTXID0__PRIV__SHIFT 24
+#define SQ_INTERRUPT_WORD_WAVE_CTXID0__WAVE_ID__SHIFT 25
+#define SQ_INTERRUPT_WORD_WAVE_CTXID0__SIMD_ID__SHIFT 30
+#define SQ_INTERRUPT_WORD_WAVE_CTXID1__WGP_ID__SHIFT 0
+#define SQ_INTERRUPT_WORD_WAVE_CTXID1__SE_ID__SHIFT 4
+#define SQ_INTERRUPT_WORD_WAVE_CTXID1__ENCODING__SHIFT 6
+
+#define SQ_INTERRUPT_WORD_WAVE_CTXID0__DATA_MASK 0x000007fffff
+#define SQ_INTERRUPT_WORD_WAVE_CTXID0__SA_ID_MASK 0x0000800000
+#define SQ_INTERRUPT_WORD_WAVE_CTXID0__PRIV_MASK 0x00001000000
+#define SQ_INTERRUPT_WORD_WAVE_CTXID0__WAVE_ID_MASK 0x0003e000000
+#define SQ_INTERRUPT_WORD_WAVE_CTXID0__SIMD_ID_MASK 0x000c0000000
+#define SQ_INTERRUPT_WORD_WAVE_CTXID1__WGP_ID_MASK 0x00f
+#define SQ_INTERRUPT_WORD_WAVE_CTXID1__SE_ID_MASK 0x030
+#define SQ_INTERRUPT_WORD_WAVE_CTXID1__ENCODING_MASK 0x0c0
+
+#define KFD_CTXID0__ERR_TYPE_MASK 0x780000
+#define KFD_CTXID0__ERR_TYPE__SHIFT 19
+
+/* GFX10 SQ interrupt ENC type bit (context_id1[7:6]) for wave s_sendmsg */
+#define KFD_CONTEXT_ID1_ENC_TYPE_WAVE_MASK 0x40
+/* GFX10 SQ interrupt PRIV bit (context_id0[24]) for s_sendmsg inside trap */
+#define KFD_CONTEXT_ID0_PRIV_MASK 0x1000000
+/*
+ * The debugger will send user data(m0) with PRIV=1 to indicate it requires
+ * notification from the KFD with the following queue id (DOORBELL_ID) and
+ * trap code (TRAP_CODE).
+ */
+#define KFD_CONTEXT_ID0_DEBUG_DOORBELL_MASK 0x0003ff
+#define KFD_CONTEXT_ID0_DEBUG_TRAP_CODE_SHIFT 10
+#define KFD_CONTEXT_ID0_DEBUG_TRAP_CODE_MASK 0x07fc00
+#define KFD_DEBUG_DOORBELL_ID(ctxid0) ((ctxid0) & \
+ KFD_CONTEXT_ID0_DEBUG_DOORBELL_MASK)
+#define KFD_DEBUG_TRAP_CODE(ctxid0) (((ctxid0) & \
+ KFD_CONTEXT_ID0_DEBUG_TRAP_CODE_MASK) \
+ >> KFD_CONTEXT_ID0_DEBUG_TRAP_CODE_SHIFT)
+#define KFD_DEBUG_CP_BAD_OP_ECODE_MASK 0x3fffc00
+#define KFD_DEBUG_CP_BAD_OP_ECODE_SHIFT 10
+#define KFD_DEBUG_CP_BAD_OP_ECODE(ctxid0) (((ctxid0) & \
+ KFD_DEBUG_CP_BAD_OP_ECODE_MASK) \
+ >> KFD_DEBUG_CP_BAD_OP_ECODE_SHIFT)
+
+static void event_interrupt_poison_consumption(struct kfd_node *dev,
+ uint16_t pasid, uint16_t client_id)
+{
+ int old_poison, ret = -EINVAL;
+ struct kfd_process *p = kfd_lookup_process_by_pasid(pasid);
+
+ if (!p)
+ return;
+
+ /* all queues of a process will be unmapped in one time */
+ old_poison = atomic_cmpxchg(&p->poison, 0, 1);
+ kfd_unref_process(p);
+ if (old_poison)
+ return;
+
+ switch (client_id) {
+ case SOC15_IH_CLIENTID_SE0SH:
+ case SOC15_IH_CLIENTID_SE1SH:
+ case SOC15_IH_CLIENTID_SE2SH:
+ case SOC15_IH_CLIENTID_SE3SH:
+ case SOC15_IH_CLIENTID_UTCL2:
+ ret = kfd_dqm_evict_pasid(dev->dqm, pasid);
+ break;
+ case SOC15_IH_CLIENTID_SDMA0:
+ case SOC15_IH_CLIENTID_SDMA1:
+ case SOC15_IH_CLIENTID_SDMA2:
+ case SOC15_IH_CLIENTID_SDMA3:
+ case SOC15_IH_CLIENTID_SDMA4:
+ break;
+ default:
+ break;
+ }
+
+ kfd_signal_poison_consumed_event(dev, pasid);
+
+ /* resetting queue passes, do page retirement without gpu reset
+ * resetting queue fails, fallback to gpu reset solution
+ */
+ if (!ret) {
+ dev_warn(dev->adev->dev,
+ "RAS poison consumption, unmap queue flow succeeded: client id %d\n",
+ client_id);
+ amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, false);
+ } else {
+ dev_warn(dev->adev->dev,
+ "RAS poison consumption, fall back to gpu reset flow: client id %d\n",
+ client_id);
+ amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, true);
+ }
+}
+
+static bool event_interrupt_isr_v10(struct kfd_node *dev,
+ const uint32_t *ih_ring_entry,
+ uint32_t *patched_ihre,
+ bool *patched_flag)
+{
+ uint16_t source_id, client_id, pasid, vmid;
+ const uint32_t *data = ih_ring_entry;
+
+ source_id = SOC15_SOURCE_ID_FROM_IH_ENTRY(ih_ring_entry);
+ client_id = SOC15_CLIENT_ID_FROM_IH_ENTRY(ih_ring_entry);
+
+ /* Only handle interrupts from KFD VMIDs */
+ vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry);
+ if (!KFD_IRQ_IS_FENCE(client_id, source_id) &&
+ (vmid < dev->vm_info.first_vmid_kfd ||
+ vmid > dev->vm_info.last_vmid_kfd))
+ return false;
+
+ pasid = SOC15_PASID_FROM_IH_ENTRY(ih_ring_entry);
+
+ /* Only handle clients we care about */
+ if (client_id != SOC15_IH_CLIENTID_GRBM_CP &&
+ client_id != SOC15_IH_CLIENTID_SDMA0 &&
+ client_id != SOC15_IH_CLIENTID_SDMA1 &&
+ client_id != SOC15_IH_CLIENTID_SDMA2 &&
+ client_id != SOC15_IH_CLIENTID_SDMA3 &&
+ client_id != SOC15_IH_CLIENTID_SDMA4 &&
+ client_id != SOC15_IH_CLIENTID_SDMA5 &&
+ client_id != SOC15_IH_CLIENTID_SDMA6 &&
+ client_id != SOC15_IH_CLIENTID_SDMA7 &&
+ client_id != SOC15_IH_CLIENTID_VMC &&
+ client_id != SOC15_IH_CLIENTID_VMC1 &&
+ client_id != SOC15_IH_CLIENTID_UTCL2 &&
+ client_id != SOC15_IH_CLIENTID_SE0SH &&
+ client_id != SOC15_IH_CLIENTID_SE1SH &&
+ client_id != SOC15_IH_CLIENTID_SE2SH &&
+ client_id != SOC15_IH_CLIENTID_SE3SH)
+ return false;
+
+ pr_debug("client id 0x%x, source id %d, vmid %d, pasid 0x%x. raw data:\n",
+ client_id, source_id, vmid, pasid);
+ pr_debug("%8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X.\n",
+ data[0], data[1], data[2], data[3],
+ data[4], data[5], data[6], data[7]);
+
+ /* If there is no valid PASID, it's likely a bug */
+ if (WARN_ONCE(pasid == 0, "Bug: No PASID in KFD interrupt"))
+ return 0;
+
+ /* Interrupt types we care about: various signals and faults.
+ * They will be forwarded to a work queue (see below).
+ */
+ return source_id == SOC15_INTSRC_CP_END_OF_PIPE ||
+ source_id == SOC15_INTSRC_SDMA_TRAP ||
+ source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG ||
+ source_id == SOC15_INTSRC_CP_BAD_OPCODE ||
+ client_id == SOC15_IH_CLIENTID_VMC ||
+ client_id == SOC15_IH_CLIENTID_VMC1 ||
+ client_id == SOC15_IH_CLIENTID_UTCL2 ||
+ KFD_IRQ_IS_FENCE(client_id, source_id);
+}
+
+static void event_interrupt_wq_v10(struct kfd_node *dev,
+ const uint32_t *ih_ring_entry)
+{
+ uint16_t source_id, client_id, pasid, vmid;
+ uint32_t context_id0, context_id1;
+ uint32_t encoding, sq_intr_err_type;
+
+ source_id = SOC15_SOURCE_ID_FROM_IH_ENTRY(ih_ring_entry);
+ client_id = SOC15_CLIENT_ID_FROM_IH_ENTRY(ih_ring_entry);
+ pasid = SOC15_PASID_FROM_IH_ENTRY(ih_ring_entry);
+ vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry);
+ context_id0 = SOC15_CONTEXT_ID0_FROM_IH_ENTRY(ih_ring_entry);
+ context_id1 = SOC15_CONTEXT_ID1_FROM_IH_ENTRY(ih_ring_entry);
+
+ if (client_id == SOC15_IH_CLIENTID_GRBM_CP ||
+ client_id == SOC15_IH_CLIENTID_SE0SH ||
+ client_id == SOC15_IH_CLIENTID_SE1SH ||
+ client_id == SOC15_IH_CLIENTID_SE2SH ||
+ client_id == SOC15_IH_CLIENTID_SE3SH) {
+ if (source_id == SOC15_INTSRC_CP_END_OF_PIPE)
+ kfd_signal_event_interrupt(pasid, context_id0, 32);
+ else if (source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG) {
+ encoding = REG_GET_FIELD(context_id1,
+ SQ_INTERRUPT_WORD_WAVE_CTXID1, ENCODING);
+ switch (encoding) {
+ case SQ_INTERRUPT_WORD_ENCODING_AUTO:
+ pr_debug(
+ "sq_intr: auto, se %d, ttrace %d, wlt %d, ttrac_buf0_full %d, ttrac_buf1_full %d, ttrace_utc_err %d\n",
+ REG_GET_FIELD(context_id1, SQ_INTERRUPT_WORD_AUTO_CTXID1,
+ SE_ID),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0,
+ THREAD_TRACE),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0,
+ WLT),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0,
+ THREAD_TRACE_BUF0_FULL),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0,
+ THREAD_TRACE_BUF1_FULL),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0,
+ THREAD_TRACE_UTC_ERROR));
+ break;
+ case SQ_INTERRUPT_WORD_ENCODING_INST:
+ pr_debug("sq_intr: inst, se %d, data 0x%x, sa %d, priv %d, wave_id %d, simd_id %d, wgp_id %d\n",
+ REG_GET_FIELD(context_id1, SQ_INTERRUPT_WORD_WAVE_CTXID1,
+ SE_ID),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0,
+ DATA),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0,
+ SA_ID),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0,
+ PRIV),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0,
+ WAVE_ID),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0,
+ SIMD_ID),
+ REG_GET_FIELD(context_id1, SQ_INTERRUPT_WORD_WAVE_CTXID1,
+ WGP_ID));
+ if (context_id0 & SQ_INTERRUPT_WORD_WAVE_CTXID0__PRIV_MASK) {
+ if (kfd_set_dbg_ev_from_interrupt(dev, pasid,
+ KFD_DEBUG_DOORBELL_ID(context_id0),
+ KFD_DEBUG_TRAP_CODE(context_id0),
+ NULL, 0))
+ return;
+ }
+ break;
+ case SQ_INTERRUPT_WORD_ENCODING_ERROR:
+ sq_intr_err_type = REG_GET_FIELD(context_id0, KFD_CTXID0,
+ ERR_TYPE);
+ pr_warn("sq_intr: error, se %d, data 0x%x, sa %d, priv %d, wave_id %d, simd_id %d, wgp_id %d, err_type %d\n",
+ REG_GET_FIELD(context_id1, SQ_INTERRUPT_WORD_WAVE_CTXID1,
+ SE_ID),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0,
+ DATA),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0,
+ SA_ID),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0,
+ PRIV),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0,
+ WAVE_ID),
+ REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0,
+ SIMD_ID),
+ REG_GET_FIELD(context_id1, SQ_INTERRUPT_WORD_WAVE_CTXID1,
+ WGP_ID),
+ sq_intr_err_type);
+ if (sq_intr_err_type != SQ_INTERRUPT_ERROR_TYPE_ILLEGAL_INST &&
+ sq_intr_err_type != SQ_INTERRUPT_ERROR_TYPE_MEMVIOL) {
+ event_interrupt_poison_consumption(dev, pasid, source_id);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ kfd_signal_event_interrupt(pasid, context_id0 & 0x7fffff, 23);
+ } else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE) {
+ kfd_set_dbg_ev_from_interrupt(dev, pasid,
+ KFD_DEBUG_DOORBELL_ID(context_id0),
+ KFD_EC_MASK(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0)),
+ NULL,
+ 0);
+ }
+ } else if (client_id == SOC15_IH_CLIENTID_SDMA0 ||
+ client_id == SOC15_IH_CLIENTID_SDMA1 ||
+ client_id == SOC15_IH_CLIENTID_SDMA2 ||
+ client_id == SOC15_IH_CLIENTID_SDMA3 ||
+ (client_id == SOC15_IH_CLIENTID_SDMA3_Sienna_Cichlid &&
+ KFD_GC_VERSION(dev) == IP_VERSION(10, 3, 0)) ||
+ client_id == SOC15_IH_CLIENTID_SDMA4 ||
+ client_id == SOC15_IH_CLIENTID_SDMA5 ||
+ client_id == SOC15_IH_CLIENTID_SDMA6 ||
+ client_id == SOC15_IH_CLIENTID_SDMA7) {
+ if (source_id == SOC15_INTSRC_SDMA_TRAP) {
+ kfd_signal_event_interrupt(pasid, context_id0 & 0xfffffff, 28);
+ } else if (source_id == SOC15_INTSRC_SDMA_ECC) {
+ event_interrupt_poison_consumption(dev, pasid, source_id);
+ return;
+ }
+ } else if (client_id == SOC15_IH_CLIENTID_VMC ||
+ client_id == SOC15_IH_CLIENTID_VMC1 ||
+ client_id == SOC15_IH_CLIENTID_UTCL2) {
+ struct kfd_vm_fault_info info = {0};
+ uint16_t ring_id = SOC15_RING_ID_FROM_IH_ENTRY(ih_ring_entry);
+ struct kfd_hsa_memory_exception_data exception_data;
+
+ if (client_id == SOC15_IH_CLIENTID_UTCL2 &&
+ amdgpu_amdkfd_ras_query_utcl2_poison_status(dev->adev)) {
+ event_interrupt_poison_consumption(dev, pasid, client_id);
+ return;
+ }
+
+ info.vmid = vmid;
+ info.mc_id = client_id;
+ info.page_addr = ih_ring_entry[4] |
+ (uint64_t)(ih_ring_entry[5] & 0xf) << 32;
+ info.prot_valid = ring_id & 0x08;
+ info.prot_read = ring_id & 0x10;
+ info.prot_write = ring_id & 0x20;
+
+ memset(&exception_data, 0, sizeof(exception_data));
+ exception_data.gpu_id = dev->id;
+ exception_data.va = (info.page_addr) << PAGE_SHIFT;
+ exception_data.failure.NotPresent = info.prot_valid ? 1 : 0;
+ exception_data.failure.NoExecute = info.prot_exec ? 1 : 0;
+ exception_data.failure.ReadOnly = info.prot_write ? 1 : 0;
+ exception_data.failure.imprecise = 0;
+
+ kfd_set_dbg_ev_from_interrupt(dev,
+ pasid,
+ -1,
+ KFD_EC_MASK(EC_DEVICE_MEMORY_VIOLATION),
+ &exception_data,
+ sizeof(exception_data));
+ } else if (KFD_IRQ_IS_FENCE(client_id, source_id)) {
+ kfd_process_close_interrupt_drain(pasid);
+ }
+}
+
+const struct kfd_event_interrupt_class event_interrupt_class_v10 = {
+ .interrupt_isr = event_interrupt_isr_v10,
+ .interrupt_wq = event_interrupt_wq_v10,
+};
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
index 0d53f6067422..f933bd231fb9 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
@@ -26,6 +26,7 @@
#include "kfd_device_queue_manager.h"
#include "ivsrcid/vmc/irqsrcs_vmc_1_0.h"
#include "kfd_smi_events.h"
+#include "kfd_debug.h"
/*
* GFX11 SQ Interrupts
@@ -187,7 +188,7 @@ static void print_sq_intr_info_error(uint32_t context_id0, uint32_t context_id1)
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_ERROR_CTXID1, WGP_ID));
}
-static void event_interrupt_poison_consumption_v11(struct kfd_dev *dev,
+static void event_interrupt_poison_consumption_v11(struct kfd_node *dev,
uint16_t pasid, uint16_t source_id)
{
int ret = -EINVAL;
@@ -225,7 +226,7 @@ static void event_interrupt_poison_consumption_v11(struct kfd_dev *dev,
amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, true);
}
-static bool event_interrupt_isr_v11(struct kfd_dev *dev,
+static bool event_interrupt_isr_v11(struct kfd_node *dev,
const uint32_t *ih_ring_entry,
uint32_t *patched_ihre,
bool *patched_flag)
@@ -238,7 +239,7 @@ static bool event_interrupt_isr_v11(struct kfd_dev *dev,
client_id = SOC15_CLIENT_ID_FROM_IH_ENTRY(ih_ring_entry);
/* Only handle interrupts from KFD VMIDs */
vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry);
- if (/*!KFD_IRQ_IS_FENCE(client_id, source_id) &&*/
+ if (!KFD_IRQ_IS_FENCE(client_id, source_id) &&
(vmid < dev->vm_info.first_vmid_kfd ||
vmid > dev->vm_info.last_vmid_kfd))
return false;
@@ -267,19 +268,19 @@ static bool event_interrupt_isr_v11(struct kfd_dev *dev,
source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG ||
source_id == SOC15_INTSRC_CP_BAD_OPCODE ||
source_id == SOC21_INTSRC_SDMA_TRAP ||
- /* KFD_IRQ_IS_FENCE(client_id, source_id) || */
+ KFD_IRQ_IS_FENCE(client_id, source_id) ||
(((client_id == SOC21_IH_CLIENTID_VMC) ||
((client_id == SOC21_IH_CLIENTID_GFX) &&
(source_id == UTCL2_1_0__SRCID__FAULT))) &&
!amdgpu_no_queue_eviction_on_vm_fault);
}
-static void event_interrupt_wq_v11(struct kfd_dev *dev,
+static void event_interrupt_wq_v11(struct kfd_node *dev,
const uint32_t *ih_ring_entry)
{
uint16_t source_id, client_id, ring_id, pasid, vmid;
uint32_t context_id0, context_id1;
- uint8_t sq_int_enc, sq_int_errtype, sq_int_priv;
+ uint8_t sq_int_enc, sq_int_priv, sq_int_errtype;
struct kfd_vm_fault_info info = {0};
struct kfd_hsa_memory_exception_data exception_data;
@@ -312,9 +313,9 @@ static void event_interrupt_wq_v11(struct kfd_dev *dev,
exception_data.failure.ReadOnly = info.prot_write ? 1 : 0;
exception_data.failure.imprecise = 0;
- /*kfd_set_dbg_ev_from_interrupt(dev, pasid, -1,
+ kfd_set_dbg_ev_from_interrupt(dev, pasid, -1,
KFD_EC_MASK(EC_DEVICE_MEMORY_VIOLATION),
- &exception_data, sizeof(exception_data));*/
+ &exception_data, sizeof(exception_data));
kfd_smi_event_update_vmfault(dev, pasid);
/* GRBM, SDMA, SE, PMM */
@@ -324,11 +325,11 @@ static void event_interrupt_wq_v11(struct kfd_dev *dev,
/* CP */
if (source_id == SOC15_INTSRC_CP_END_OF_PIPE)
kfd_signal_event_interrupt(pasid, context_id0, 32);
- /*else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE)
+ else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE)
kfd_set_dbg_ev_from_interrupt(dev, pasid,
KFD_CTXID0_DOORBELL_ID(context_id0),
KFD_EC_MASK(KFD_CTXID0_CP_BAD_OP_ECODE(context_id0)),
- NULL, 0);*/
+ NULL, 0);
/* SDMA */
else if (source_id == SOC21_INTSRC_SDMA_TRAP)
@@ -350,11 +351,11 @@ static void event_interrupt_wq_v11(struct kfd_dev *dev,
print_sq_intr_info_inst(context_id0, context_id1);
sq_int_priv = REG_GET_FIELD(context_id0,
SQ_INTERRUPT_WORD_WAVE_CTXID0, PRIV);
- /*if (sq_int_priv && (kfd_set_dbg_ev_from_interrupt(dev, pasid,
+ if (sq_int_priv && (kfd_set_dbg_ev_from_interrupt(dev, pasid,
KFD_CTXID0_DOORBELL_ID(context_id0),
KFD_CTXID0_TRAP_CODE(context_id0),
NULL, 0)))
- return;*/
+ return;
break;
case SQ_INTERRUPT_WORD_ENCODING_ERROR:
print_sq_intr_info_error(context_id0, context_id1);
@@ -373,8 +374,8 @@ static void event_interrupt_wq_v11(struct kfd_dev *dev,
kfd_signal_event_interrupt(pasid, context_id0 & 0xffffff, 24);
}
- /*} else if (KFD_IRQ_IS_FENCE(client_id, source_id)) {
- kfd_process_close_interrupt_drain(pasid);*/
+ } else if (KFD_IRQ_IS_FENCE(client_id, source_id)) {
+ kfd_process_close_interrupt_drain(pasid);
}
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
index 0b75a37b689b..d5c9f30552e3 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
@@ -23,10 +23,40 @@
#include "kfd_priv.h"
#include "kfd_events.h"
+#include "kfd_debug.h"
#include "soc15_int.h"
#include "kfd_device_queue_manager.h"
#include "kfd_smi_events.h"
+/*
+ * GFX9 SQ Interrupts
+ *
+ * There are 3 encoding types of interrupts sourced from SQ sent as a 44-bit
+ * packet to the Interrupt Handler:
+ * Auto - Generated by the SQG (various cmd overflows, timestamps etc)
+ * Wave - Generated by S_SENDMSG through a shader program
+ * Error - HW generated errors (Illegal instructions, Memviols, EDC etc)
+ *
+ * The 44-bit packet is mapped as {context_id1[7:0],context_id0[31:0]} plus
+ * 4-bits for VMID (SOC15_VMID_FROM_IH_ENTRY) as such:
+ *
+ * - context_id0[27:26]
+ * Encoding type (0 = Auto, 1 = Wave, 2 = Error)
+ *
+ * - context_id0[13]
+ * PRIV bit indicates that Wave S_SEND or error occurred within trap
+ *
+ * - {context_id1[7:0],context_id0[31:28],context_id0[11:0]}
+ * 24-bit data with the following layout per encoding type:
+ * Auto - only context_id0[8:0] is used, which reports various interrupts
+ * generated by SQG. The rest is 0.
+ * Wave - user data sent from m0 via S_SENDMSG
+ * Error - Error type (context_id1[7:4]), Error Details (rest of bits)
+ *
+ * The other context_id bits show coordinates (SE/SH/CU/SIMD/WAVE) for wave
+ * S_SENDMSG and Errors. These are 0 for Auto.
+ */
+
enum SQ_INTERRUPT_WORD_ENCODING {
SQ_INTERRUPT_WORD_ENCODING_AUTO = 0x0,
SQ_INTERRUPT_WORD_ENCODING_INST,
@@ -84,13 +114,33 @@ enum SQ_INTERRUPT_ERROR_TYPE {
#define SQ_INTERRUPT_WORD_WAVE_CTXID__SE_ID_MASK 0x03000000
#define SQ_INTERRUPT_WORD_WAVE_CTXID__ENCODING_MASK 0x0c000000
+/* GFX9 SQ interrupt 24-bit data from context_id<0,1> */
#define KFD_CONTEXT_ID_GET_SQ_INT_DATA(ctx0, ctx1) \
((ctx0 & 0xfff) | ((ctx0 >> 16) & 0xf000) | ((ctx1 << 16) & 0xff0000))
#define KFD_SQ_INT_DATA__ERR_TYPE_MASK 0xF00000
#define KFD_SQ_INT_DATA__ERR_TYPE__SHIFT 20
-static void event_interrupt_poison_consumption_v9(struct kfd_dev *dev,
+/*
+ * The debugger will send user data(m0) with PRIV=1 to indicate it requires
+ * notification from the KFD with the following queue id (DOORBELL_ID) and
+ * trap code (TRAP_CODE).
+ */
+#define KFD_INT_DATA_DEBUG_DOORBELL_MASK 0x0003ff
+#define KFD_INT_DATA_DEBUG_TRAP_CODE_SHIFT 10
+#define KFD_INT_DATA_DEBUG_TRAP_CODE_MASK 0x07fc00
+#define KFD_DEBUG_DOORBELL_ID(sq_int_data) ((sq_int_data) & \
+ KFD_INT_DATA_DEBUG_DOORBELL_MASK)
+#define KFD_DEBUG_TRAP_CODE(sq_int_data) (((sq_int_data) & \
+ KFD_INT_DATA_DEBUG_TRAP_CODE_MASK) \
+ >> KFD_INT_DATA_DEBUG_TRAP_CODE_SHIFT)
+#define KFD_DEBUG_CP_BAD_OP_ECODE_MASK 0x3fffc00
+#define KFD_DEBUG_CP_BAD_OP_ECODE_SHIFT 10
+#define KFD_DEBUG_CP_BAD_OP_ECODE(ctxid0) (((ctxid0) & \
+ KFD_DEBUG_CP_BAD_OP_ECODE_MASK) \
+ >> KFD_DEBUG_CP_BAD_OP_ECODE_SHIFT)
+
+static void event_interrupt_poison_consumption_v9(struct kfd_node *dev,
uint16_t pasid, uint16_t client_id)
{
int old_poison, ret = -EINVAL;
@@ -160,7 +210,7 @@ static bool context_id_expected(struct kfd_dev *dev)
}
}
-static bool event_interrupt_isr_v9(struct kfd_dev *dev,
+static bool event_interrupt_isr_v9(struct kfd_node *dev,
const uint32_t *ih_ring_entry,
uint32_t *patched_ihre,
bool *patched_flag)
@@ -168,14 +218,16 @@ static bool event_interrupt_isr_v9(struct kfd_dev *dev,
uint16_t source_id, client_id, pasid, vmid;
const uint32_t *data = ih_ring_entry;
+ source_id = SOC15_SOURCE_ID_FROM_IH_ENTRY(ih_ring_entry);
+ client_id = SOC15_CLIENT_ID_FROM_IH_ENTRY(ih_ring_entry);
+
/* Only handle interrupts from KFD VMIDs */
vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry);
- if (vmid < dev->vm_info.first_vmid_kfd ||
- vmid > dev->vm_info.last_vmid_kfd)
+ if (!KFD_IRQ_IS_FENCE(client_id, source_id) &&
+ (vmid < dev->vm_info.first_vmid_kfd ||
+ vmid > dev->vm_info.last_vmid_kfd))
return false;
- source_id = SOC15_SOURCE_ID_FROM_IH_ENTRY(ih_ring_entry);
- client_id = SOC15_CLIENT_ID_FROM_IH_ENTRY(ih_ring_entry);
pasid = SOC15_PASID_FROM_IH_ENTRY(ih_ring_entry);
/* Only handle clients we care about */
@@ -194,7 +246,8 @@ static bool event_interrupt_isr_v9(struct kfd_dev *dev,
client_id != SOC15_IH_CLIENTID_SE0SH &&
client_id != SOC15_IH_CLIENTID_SE1SH &&
client_id != SOC15_IH_CLIENTID_SE2SH &&
- client_id != SOC15_IH_CLIENTID_SE3SH)
+ client_id != SOC15_IH_CLIENTID_SE3SH &&
+ !KFD_IRQ_IS_FENCE(client_id, source_id))
return false;
/* This is a known issue for gfx9. Under non HWS, pasid is not set
@@ -206,7 +259,7 @@ static bool event_interrupt_isr_v9(struct kfd_dev *dev,
*patched_flag = true;
memcpy(patched_ihre, ih_ring_entry,
- dev->device_info.ih_ring_entry_size);
+ dev->kfd->device_info.ih_ring_entry_size);
pasid = dev->dqm->vmid_pasid[vmid];
@@ -235,7 +288,7 @@ static bool event_interrupt_isr_v9(struct kfd_dev *dev,
uint32_t context_id =
SOC15_CONTEXT_ID0_FROM_IH_ENTRY(ih_ring_entry);
- if (context_id == 0 && context_id_expected(dev))
+ if (context_id == 0 && context_id_expected(dev->kfd))
return false;
}
@@ -247,13 +300,14 @@ static bool event_interrupt_isr_v9(struct kfd_dev *dev,
source_id == SOC15_INTSRC_SDMA_ECC ||
source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG ||
source_id == SOC15_INTSRC_CP_BAD_OPCODE ||
+ KFD_IRQ_IS_FENCE(client_id, source_id) ||
((client_id == SOC15_IH_CLIENTID_VMC ||
client_id == SOC15_IH_CLIENTID_VMC1 ||
client_id == SOC15_IH_CLIENTID_UTCL2) &&
!amdgpu_no_queue_eviction_on_vm_fault);
}
-static void event_interrupt_wq_v9(struct kfd_dev *dev,
+static void event_interrupt_wq_v9(struct kfd_node *dev,
const uint32_t *ih_ring_entry)
{
uint16_t source_id, client_id, pasid, vmid;
@@ -302,6 +356,13 @@ static void event_interrupt_wq_v9(struct kfd_dev *dev,
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID, SIMD_ID),
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID, CU_ID),
sq_int_data);
+ if (context_id0 & SQ_INTERRUPT_WORD_WAVE_CTXID__PRIV_MASK) {
+ if (kfd_set_dbg_ev_from_interrupt(dev, pasid,
+ KFD_DEBUG_DOORBELL_ID(sq_int_data),
+ KFD_DEBUG_TRAP_CODE(sq_int_data),
+ NULL, 0))
+ return;
+ }
break;
case SQ_INTERRUPT_WORD_ENCODING_ERROR:
sq_intr_err = REG_GET_FIELD(sq_int_data, KFD_SQ_INT_DATA, ERR_TYPE);
@@ -324,8 +385,12 @@ static void event_interrupt_wq_v9(struct kfd_dev *dev,
break;
}
kfd_signal_event_interrupt(pasid, context_id0 & 0xffffff, 24);
- } else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE)
- kfd_signal_hw_exception_event(pasid);
+ } else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE) {
+ kfd_set_dbg_ev_from_interrupt(dev, pasid,
+ KFD_DEBUG_DOORBELL_ID(context_id0),
+ KFD_EC_MASK(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0)),
+ NULL, 0);
+ }
} else if (client_id == SOC15_IH_CLIENTID_SDMA0 ||
client_id == SOC15_IH_CLIENTID_SDMA1 ||
client_id == SOC15_IH_CLIENTID_SDMA2 ||
@@ -345,6 +410,7 @@ static void event_interrupt_wq_v9(struct kfd_dev *dev,
client_id == SOC15_IH_CLIENTID_UTCL2) {
struct kfd_vm_fault_info info = {0};
uint16_t ring_id = SOC15_RING_ID_FROM_IH_ENTRY(ih_ring_entry);
+ struct kfd_hsa_memory_exception_data exception_data;
if (client_id == SOC15_IH_CLIENTID_UTCL2 &&
amdgpu_amdkfd_ras_query_utcl2_poison_status(dev->adev)) {
@@ -360,9 +426,23 @@ static void event_interrupt_wq_v9(struct kfd_dev *dev,
info.prot_read = ring_id & 0x10;
info.prot_write = ring_id & 0x20;
+ memset(&exception_data, 0, sizeof(exception_data));
+ exception_data.gpu_id = dev->id;
+ exception_data.va = (info.page_addr) << PAGE_SHIFT;
+ exception_data.failure.NotPresent = info.prot_valid ? 1 : 0;
+ exception_data.failure.NoExecute = info.prot_exec ? 1 : 0;
+ exception_data.failure.ReadOnly = info.prot_write ? 1 : 0;
+ exception_data.failure.imprecise = 0;
+
+ kfd_set_dbg_ev_from_interrupt(dev,
+ pasid,
+ -1,
+ KFD_EC_MASK(EC_DEVICE_MEMORY_VIOLATION),
+ &exception_data,
+ sizeof(exception_data));
kfd_smi_event_update_vmfault(dev, pasid);
- kfd_dqm_evict_pasid(dev->dqm, pasid);
- kfd_signal_vm_fault_event(dev, pasid, &info);
+ } else if (KFD_IRQ_IS_FENCE(client_id, source_id)) {
+ kfd_process_close_interrupt_drain(pasid);
}
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c
index 34772fe74296..dd3c43c1ad70 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c
@@ -50,29 +50,29 @@
static void interrupt_wq(struct work_struct *);
-int kfd_interrupt_init(struct kfd_dev *kfd)
+int kfd_interrupt_init(struct kfd_node *node)
{
int r;
- r = kfifo_alloc(&kfd->ih_fifo,
- KFD_IH_NUM_ENTRIES * kfd->device_info.ih_ring_entry_size,
+ r = kfifo_alloc(&node->ih_fifo,
+ KFD_IH_NUM_ENTRIES * node->kfd->device_info.ih_ring_entry_size,
GFP_KERNEL);
if (r) {
- dev_err(kfd->adev->dev, "Failed to allocate IH fifo\n");
+ dev_err(node->adev->dev, "Failed to allocate IH fifo\n");
return r;
}
- kfd->ih_wq = alloc_workqueue("KFD IH", WQ_HIGHPRI, 1);
- if (unlikely(!kfd->ih_wq)) {
- kfifo_free(&kfd->ih_fifo);
- dev_err(kfd->adev->dev, "Failed to allocate KFD IH workqueue\n");
+ node->ih_wq = alloc_workqueue("KFD IH", WQ_HIGHPRI, 1);
+ if (unlikely(!node->ih_wq)) {
+ kfifo_free(&node->ih_fifo);
+ dev_err(node->adev->dev, "Failed to allocate KFD IH workqueue\n");
return -ENOMEM;
}
- spin_lock_init(&kfd->interrupt_lock);
+ spin_lock_init(&node->interrupt_lock);
- INIT_WORK(&kfd->interrupt_work, interrupt_wq);
+ INIT_WORK(&node->interrupt_work, interrupt_wq);
- kfd->interrupts_active = true;
+ node->interrupts_active = true;
/*
* After this function returns, the interrupt will be enabled. This
@@ -84,7 +84,7 @@ int kfd_interrupt_init(struct kfd_dev *kfd)
return 0;
}
-void kfd_interrupt_exit(struct kfd_dev *kfd)
+void kfd_interrupt_exit(struct kfd_node *node)
{
/*
* Stop the interrupt handler from writing to the ring and scheduling
@@ -93,31 +93,31 @@ void kfd_interrupt_exit(struct kfd_dev *kfd)
*/
unsigned long flags;
- spin_lock_irqsave(&kfd->interrupt_lock, flags);
- kfd->interrupts_active = false;
- spin_unlock_irqrestore(&kfd->interrupt_lock, flags);
+ spin_lock_irqsave(&node->interrupt_lock, flags);
+ node->interrupts_active = false;
+ spin_unlock_irqrestore(&node->interrupt_lock, flags);
/*
* flush_work ensures that there are no outstanding
* work-queue items that will access interrupt_ring. New work items
* can't be created because we stopped interrupt handling above.
*/
- flush_workqueue(kfd->ih_wq);
+ flush_workqueue(node->ih_wq);
- kfifo_free(&kfd->ih_fifo);
+ kfifo_free(&node->ih_fifo);
}
/*
* Assumption: single reader/writer. This function is not re-entrant
*/
-bool enqueue_ih_ring_entry(struct kfd_dev *kfd, const void *ih_ring_entry)
+bool enqueue_ih_ring_entry(struct kfd_node *node, const void *ih_ring_entry)
{
int count;
- count = kfifo_in(&kfd->ih_fifo, ih_ring_entry,
- kfd->device_info.ih_ring_entry_size);
- if (count != kfd->device_info.ih_ring_entry_size) {
- dev_dbg_ratelimited(kfd->adev->dev,
+ count = kfifo_in(&node->ih_fifo, ih_ring_entry,
+ node->kfd->device_info.ih_ring_entry_size);
+ if (count != node->kfd->device_info.ih_ring_entry_size) {
+ dev_dbg_ratelimited(node->adev->dev,
"Interrupt ring overflow, dropping interrupt %d\n",
count);
return false;
@@ -129,32 +129,32 @@ bool enqueue_ih_ring_entry(struct kfd_dev *kfd, const void *ih_ring_entry)
/*
* Assumption: single reader/writer. This function is not re-entrant
*/
-static bool dequeue_ih_ring_entry(struct kfd_dev *kfd, void *ih_ring_entry)
+static bool dequeue_ih_ring_entry(struct kfd_node *node, void *ih_ring_entry)
{
int count;
- count = kfifo_out(&kfd->ih_fifo, ih_ring_entry,
- kfd->device_info.ih_ring_entry_size);
+ count = kfifo_out(&node->ih_fifo, ih_ring_entry,
+ node->kfd->device_info.ih_ring_entry_size);
- WARN_ON(count && count != kfd->device_info.ih_ring_entry_size);
+ WARN_ON(count && count != node->kfd->device_info.ih_ring_entry_size);
- return count == kfd->device_info.ih_ring_entry_size;
+ return count == node->kfd->device_info.ih_ring_entry_size;
}
static void interrupt_wq(struct work_struct *work)
{
- struct kfd_dev *dev = container_of(work, struct kfd_dev,
+ struct kfd_node *dev = container_of(work, struct kfd_node,
interrupt_work);
uint32_t ih_ring_entry[KFD_MAX_RING_ENTRY_SIZE];
unsigned long start_jiffies = jiffies;
- if (dev->device_info.ih_ring_entry_size > sizeof(ih_ring_entry)) {
+ if (dev->kfd->device_info.ih_ring_entry_size > sizeof(ih_ring_entry)) {
dev_err_once(dev->adev->dev, "Ring entry too small\n");
return;
}
while (dequeue_ih_ring_entry(dev, ih_ring_entry)) {
- dev->device_info.event_interrupt_class->interrupt_wq(dev,
+ dev->kfd->device_info.event_interrupt_class->interrupt_wq(dev,
ih_ring_entry);
if (time_is_before_jiffies(start_jiffies + HZ)) {
/* If we spent more than a second processing signals,
@@ -166,14 +166,14 @@ static void interrupt_wq(struct work_struct *work)
}
}
-bool interrupt_is_wanted(struct kfd_dev *dev,
+bool interrupt_is_wanted(struct kfd_node *dev,
const uint32_t *ih_ring_entry,
uint32_t *patched_ihre, bool *flag)
{
/* integer and bitwise OR so there is no boolean short-circuiting */
unsigned int wanted = 0;
- wanted |= dev->device_info.event_interrupt_class->interrupt_isr(dev,
+ wanted |= dev->kfd->device_info.event_interrupt_class->interrupt_isr(dev,
ih_ring_entry, patched_ihre, flag);
return wanted != 0;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c
index ec1bf611624e..808ee010520a 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c
@@ -109,11 +109,11 @@ int kfd_iommu_device_init(struct kfd_dev *kfd)
*/
int kfd_iommu_bind_process_to_device(struct kfd_process_device *pdd)
{
- struct kfd_dev *dev = pdd->dev;
+ struct kfd_node *dev = pdd->dev;
struct kfd_process *p = pdd->process;
int err;
- if (!dev->use_iommu_v2 || pdd->bound == PDD_BOUND)
+ if (!dev->kfd->use_iommu_v2 || pdd->bound == PDD_BOUND)
return 0;
if (unlikely(pdd->bound == PDD_BOUND_SUSPENDED)) {
@@ -121,6 +121,12 @@ int kfd_iommu_bind_process_to_device(struct kfd_process_device *pdd)
return -EINVAL;
}
+ if (!kfd_is_first_node(dev)) {
+ dev_warn_once(kfd_device,
+ "IOMMU supported only on first node\n");
+ return 0;
+ }
+
err = amd_iommu_bind_pasid(dev->adev->pdev, p->pasid, p->lead_thread);
if (!err)
pdd->bound = PDD_BOUND;
@@ -138,7 +144,8 @@ void kfd_iommu_unbind_process(struct kfd_process *p)
int i;
for (i = 0; i < p->n_pdds; i++)
- if (p->pdds[i]->bound == PDD_BOUND)
+ if ((p->pdds[i]->bound == PDD_BOUND) &&
+ (kfd_is_first_node((p->pdds[i]->dev))))
amd_iommu_unbind_pasid(p->pdds[i]->dev->adev->pdev,
p->pasid);
}
@@ -146,7 +153,7 @@ void kfd_iommu_unbind_process(struct kfd_process *p)
/* Callback for process shutdown invoked by the IOMMU driver */
static void iommu_pasid_shutdown_callback(struct pci_dev *pdev, u32 pasid)
{
- struct kfd_dev *dev = kfd_device_by_pci_dev(pdev);
+ struct kfd_node *dev = kfd_device_by_pci_dev(pdev);
struct kfd_process *p;
struct kfd_process_device *pdd;
@@ -182,7 +189,7 @@ static void iommu_pasid_shutdown_callback(struct pci_dev *pdev, u32 pasid)
static int iommu_invalid_ppr_cb(struct pci_dev *pdev, u32 pasid,
unsigned long address, u16 flags)
{
- struct kfd_dev *dev;
+ struct kfd_node *dev;
dev_warn_ratelimited(kfd_device,
"Invalid PPR device %x:%x.%x pasid 0x%x address 0x%lX flags 0x%X",
@@ -205,7 +212,7 @@ static int iommu_invalid_ppr_cb(struct pci_dev *pdev, u32 pasid,
* Bind processes do the device that have been temporarily unbound
* (PDD_BOUND_SUSPENDED) in kfd_unbind_processes_from_device.
*/
-static int kfd_bind_processes_to_device(struct kfd_dev *kfd)
+static int kfd_bind_processes_to_device(struct kfd_node *knode)
{
struct kfd_process_device *pdd;
struct kfd_process *p;
@@ -216,14 +223,14 @@ static int kfd_bind_processes_to_device(struct kfd_dev *kfd)
hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) {
mutex_lock(&p->mutex);
- pdd = kfd_get_process_device_data(kfd, p);
+ pdd = kfd_get_process_device_data(knode, p);
if (WARN_ON(!pdd) || pdd->bound != PDD_BOUND_SUSPENDED) {
mutex_unlock(&p->mutex);
continue;
}
- err = amd_iommu_bind_pasid(kfd->adev->pdev, p->pasid,
+ err = amd_iommu_bind_pasid(knode->adev->pdev, p->pasid,
p->lead_thread);
if (err < 0) {
pr_err("Unexpected pasid 0x%x binding failure\n",
@@ -246,7 +253,7 @@ static int kfd_bind_processes_to_device(struct kfd_dev *kfd)
* processes will be restored to PDD_BOUND state in
* kfd_bind_processes_to_device.
*/
-static void kfd_unbind_processes_from_device(struct kfd_dev *kfd)
+static void kfd_unbind_processes_from_device(struct kfd_node *knode)
{
struct kfd_process_device *pdd;
struct kfd_process *p;
@@ -256,7 +263,7 @@ static void kfd_unbind_processes_from_device(struct kfd_dev *kfd)
hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) {
mutex_lock(&p->mutex);
- pdd = kfd_get_process_device_data(kfd, p);
+ pdd = kfd_get_process_device_data(knode, p);
if (WARN_ON(!pdd)) {
mutex_unlock(&p->mutex);
@@ -281,7 +288,7 @@ void kfd_iommu_suspend(struct kfd_dev *kfd)
if (!kfd->use_iommu_v2)
return;
- kfd_unbind_processes_from_device(kfd);
+ kfd_unbind_processes_from_device(kfd->nodes[0]);
amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, NULL);
amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, NULL);
@@ -312,7 +319,7 @@ int kfd_iommu_resume(struct kfd_dev *kfd)
amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev,
iommu_invalid_ppr_cb);
- err = kfd_bind_processes_to_device(kfd);
+ err = kfd_bind_processes_to_device(kfd->nodes[0]);
if (err) {
amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, NULL);
amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, NULL);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
index bcf7bc3302c9..1bea629c49ca 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
@@ -38,7 +38,7 @@
/* Initialize a kernel queue, including allocations of GART memory
* needed for the queue.
*/
-static bool kq_initialize(struct kernel_queue *kq, struct kfd_dev *dev,
+static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev,
enum kfd_queue_type type, unsigned int queue_size)
{
struct queue_properties prop;
@@ -75,7 +75,7 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_dev *dev,
if (!kq->mqd_mgr)
return false;
- prop.doorbell_ptr = kfd_get_kernel_doorbell(dev, &prop.doorbell_off);
+ prop.doorbell_ptr = kfd_get_kernel_doorbell(dev->kfd, &prop.doorbell_off);
if (!prop.doorbell_ptr) {
pr_err("Failed to initialize doorbell");
@@ -112,7 +112,7 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_dev *dev,
kq->rptr_kernel = kq->rptr_mem->cpu_ptr;
kq->rptr_gpu_addr = kq->rptr_mem->gpu_addr;
- retval = kfd_gtt_sa_allocate(dev, dev->device_info.doorbell_size,
+ retval = kfd_gtt_sa_allocate(dev, dev->kfd->device_info.doorbell_size,
&kq->wptr_mem);
if (retval != 0)
@@ -189,7 +189,7 @@ err_rptr_allocate_vidmem:
err_eop_allocate_vidmem:
kfd_gtt_sa_free(dev, kq->pq);
err_pq_allocate_vidmem:
- kfd_release_kernel_doorbell(dev, prop.doorbell_ptr);
+ kfd_release_kernel_doorbell(dev->kfd, prop.doorbell_ptr);
err_get_kernel_doorbell:
return false;
@@ -220,7 +220,7 @@ static void kq_uninitialize(struct kernel_queue *kq, bool hanging)
kfd_gtt_sa_free(kq->dev, kq->eop_mem);
kfd_gtt_sa_free(kq->dev, kq->pq);
- kfd_release_kernel_doorbell(kq->dev,
+ kfd_release_kernel_doorbell(kq->dev->kfd,
kq->queue->properties.doorbell_ptr);
uninit_queue(kq->queue);
}
@@ -298,7 +298,7 @@ void kq_submit_packet(struct kernel_queue *kq)
}
pr_debug("\n");
#endif
- if (kq->dev->device_info.doorbell_size == 8) {
+ if (kq->dev->kfd->device_info.doorbell_size == 8) {
*kq->wptr64_kernel = kq->pending_wptr64;
write_kernel_doorbell64(kq->queue->properties.doorbell_ptr,
kq->pending_wptr64);
@@ -311,7 +311,7 @@ void kq_submit_packet(struct kernel_queue *kq)
void kq_rollback_packet(struct kernel_queue *kq)
{
- if (kq->dev->device_info.doorbell_size == 8) {
+ if (kq->dev->kfd->device_info.doorbell_size == 8) {
kq->pending_wptr64 = *kq->wptr64_kernel;
kq->pending_wptr = *kq->wptr_kernel %
(kq->queue->properties.queue_size / 4);
@@ -320,7 +320,7 @@ void kq_rollback_packet(struct kernel_queue *kq)
}
}
-struct kernel_queue *kernel_queue_init(struct kfd_dev *dev,
+struct kernel_queue *kernel_queue_init(struct kfd_node *dev,
enum kfd_queue_type type)
{
struct kernel_queue *kq;
@@ -345,7 +345,7 @@ void kernel_queue_uninit(struct kernel_queue *kq, bool hanging)
}
/* FIXME: Can this test be removed? */
-static __attribute__((unused)) void test_kq(struct kfd_dev *dev)
+static __attribute__((unused)) void test_kq(struct kfd_node *dev)
{
struct kernel_queue *kq;
uint32_t *buffer, i;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h
index 383202fd1ea2..9a6244430845 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h
@@ -53,7 +53,7 @@ void kq_rollback_packet(struct kernel_queue *kq);
struct kernel_queue {
/* data */
- struct kfd_dev *dev;
+ struct kfd_node *dev;
struct mqd_manager *mqd_mgr;
struct queue *queue;
uint64_t pending_wptr64;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 54933903bcb8..709ac885ca6d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -64,7 +64,7 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, uint64_t npages,
num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8);
num_bytes = npages * 8;
- r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity,
+ r = amdgpu_job_alloc_with_ib(adev, &adev->mman.high_pr,
AMDGPU_FENCE_OWNER_UNDEFINED,
num_dw * 4 + num_bytes,
AMDGPU_IB_POOL_DELAYED,
@@ -206,7 +206,7 @@ svm_migrate_copy_done(struct amdgpu_device *adev, struct dma_fence *mfence)
unsigned long
svm_migrate_addr_to_pfn(struct amdgpu_device *adev, unsigned long addr)
{
- return (addr + adev->kfd.dev->pgmap.range.start) >> PAGE_SHIFT;
+ return (addr + adev->kfd.pgmap.range.start) >> PAGE_SHIFT;
}
static void
@@ -236,7 +236,7 @@ svm_migrate_addr(struct amdgpu_device *adev, struct page *page)
unsigned long addr;
addr = page_to_pfn(page) << PAGE_SHIFT;
- return (addr - adev->kfd.dev->pgmap.range.start);
+ return (addr - adev->kfd.pgmap.range.start);
}
static struct page *
@@ -287,11 +287,12 @@ static unsigned long svm_migrate_unsuccessful_pages(struct migrate_vma *migrate)
}
static int
-svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
+svm_migrate_copy_to_vram(struct kfd_node *node, struct svm_range *prange,
struct migrate_vma *migrate, struct dma_fence **mfence,
dma_addr_t *scratch, uint64_t ttm_res_offset)
{
- uint64_t npages = migrate->npages;
+ uint64_t npages = migrate->cpages;
+ struct amdgpu_device *adev = node->adev;
struct device *dev = adev->dev;
struct amdgpu_res_cursor cursor;
dma_addr_t *src;
@@ -321,7 +322,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
DMA_TO_DEVICE);
r = dma_mapping_error(dev, src[i]);
if (r) {
- dev_err(adev->dev, "%s: fail %d dma_map_page\n",
+ dev_err(dev, "%s: fail %d dma_map_page\n",
__func__, r);
goto out_free_vram_pages;
}
@@ -390,12 +391,13 @@ out_free_vram_pages:
}
static long
-svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
+svm_migrate_vma_to_vram(struct kfd_node *node, struct svm_range *prange,
struct vm_area_struct *vma, uint64_t start,
uint64_t end, uint32_t trigger, uint64_t ttm_res_offset)
{
struct kfd_process *p = container_of(prange->svms, struct kfd_process, svms);
uint64_t npages = (end - start) >> PAGE_SHIFT;
+ struct amdgpu_device *adev = node->adev;
struct kfd_process_device *pdd;
struct dma_fence *mfence = NULL;
struct migrate_vma migrate = { 0 };
@@ -421,9 +423,9 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
migrate.dst = migrate.src + npages;
scratch = (dma_addr_t *)(migrate.dst + npages);
- kfd_smi_event_migration_start(adev->kfd.dev, p->lead_thread->pid,
+ kfd_smi_event_migration_start(node, p->lead_thread->pid,
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
- 0, adev->kfd.dev->id, prange->prefetch_loc,
+ 0, node->id, prange->prefetch_loc,
prange->preferred_loc, trigger);
r = migrate_vma_setup(&migrate);
@@ -445,7 +447,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
else
pr_debug("0x%lx pages migrated\n", cpages);
- r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch, ttm_res_offset);
+ r = svm_migrate_copy_to_vram(node, prange, &migrate, &mfence, scratch, ttm_res_offset);
migrate_vma_pages(&migrate);
pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n",
@@ -454,9 +456,9 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
svm_migrate_copy_done(adev, mfence);
migrate_vma_finalize(&migrate);
- kfd_smi_event_migration_end(adev->kfd.dev, p->lead_thread->pid,
+ kfd_smi_event_migration_end(node, p->lead_thread->pid,
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
- 0, adev->kfd.dev->id, trigger);
+ 0, node->id, trigger);
svm_range_dma_unmap(adev->dev, scratch, 0, npages);
svm_range_free_dma_mappings(prange);
@@ -465,7 +467,7 @@ out_free:
kvfree(buf);
out:
if (!r && cpages) {
- pdd = svm_range_get_pdd_by_adev(prange, adev);
+ pdd = svm_range_get_pdd_by_node(prange, node);
if (pdd)
WRITE_ONCE(pdd->page_in, pdd->page_in + cpages);
@@ -492,8 +494,8 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
{
unsigned long addr, start, end;
struct vm_area_struct *vma;
- struct amdgpu_device *adev;
uint64_t ttm_res_offset;
+ struct kfd_node *node;
unsigned long cpages = 0;
long r = 0;
@@ -503,9 +505,9 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
return 0;
}
- adev = svm_range_get_adev_by_id(prange, best_loc);
- if (!adev) {
- pr_debug("failed to get device by id 0x%x\n", best_loc);
+ node = svm_range_get_node_by_id(prange, best_loc);
+ if (!node) {
+ pr_debug("failed to get kfd node by id 0x%x\n", best_loc);
return -ENODEV;
}
@@ -515,9 +517,9 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
start = prange->start << PAGE_SHIFT;
end = (prange->last + 1) << PAGE_SHIFT;
- r = svm_range_vram_node_new(adev, prange, true);
+ r = svm_range_vram_node_new(node, prange, true);
if (r) {
- dev_dbg(adev->dev, "fail %ld to alloc vram\n", r);
+ dev_dbg(node->adev->dev, "fail %ld to alloc vram\n", r);
return r;
}
ttm_res_offset = prange->offset << PAGE_SHIFT;
@@ -530,7 +532,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
break;
next = min(vma->vm_end, end);
- r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next, trigger, ttm_res_offset);
+ r = svm_migrate_vma_to_vram(node, prange, vma, addr, next, trigger, ttm_res_offset);
if (r < 0) {
pr_debug("failed %ld to migrate\n", r);
break;
@@ -649,11 +651,13 @@ out_oom:
/**
* svm_migrate_vma_to_ram - migrate range inside one vma from device to system
*
- * @adev: amdgpu device to migrate from
* @prange: svm range structure
* @vma: vm_area_struct that range [start, end] belongs to
* @start: range start virtual address in pages
* @end: range end virtual address in pages
+ * @node: kfd node device to migrate from
+ * @trigger: reason of migration
+ * @fault_page: is from vmf->page, svm_migrate_to_ram(), this is CPU page fault callback
*
* Context: Process context, caller hold mmap read lock, prange->migrate_mutex
*
@@ -663,7 +667,7 @@ out_oom:
* positive values - partial migration, number of pages not migrated
*/
static long
-svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
+svm_migrate_vma_to_ram(struct kfd_node *node, struct svm_range *prange,
struct vm_area_struct *vma, uint64_t start, uint64_t end,
uint32_t trigger, struct page *fault_page)
{
@@ -671,6 +675,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
uint64_t npages = (end - start) >> PAGE_SHIFT;
unsigned long upages = npages;
unsigned long cpages = 0;
+ struct amdgpu_device *adev = node->adev;
struct kfd_process_device *pdd;
struct dma_fence *mfence = NULL;
struct migrate_vma migrate = { 0 };
@@ -699,9 +704,9 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
migrate.fault_page = fault_page;
scratch = (dma_addr_t *)(migrate.dst + npages);
- kfd_smi_event_migration_start(adev->kfd.dev, p->lead_thread->pid,
+ kfd_smi_event_migration_start(node, p->lead_thread->pid,
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
- adev->kfd.dev->id, 0, prange->prefetch_loc,
+ node->id, 0, prange->prefetch_loc,
prange->preferred_loc, trigger);
r = migrate_vma_setup(&migrate);
@@ -735,9 +740,9 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
svm_migrate_copy_done(adev, mfence);
migrate_vma_finalize(&migrate);
- kfd_smi_event_migration_end(adev->kfd.dev, p->lead_thread->pid,
+ kfd_smi_event_migration_end(node, p->lead_thread->pid,
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
- adev->kfd.dev->id, 0, trigger);
+ node->id, 0, trigger);
svm_range_dma_unmap(adev->dev, scratch, 0, npages);
@@ -745,7 +750,7 @@ out_free:
kvfree(buf);
out:
if (!r && cpages) {
- pdd = svm_range_get_pdd_by_adev(prange, adev);
+ pdd = svm_range_get_pdd_by_node(prange, node);
if (pdd)
WRITE_ONCE(pdd->page_out, pdd->page_out + cpages);
}
@@ -757,6 +762,7 @@ out:
* @prange: range structure
* @mm: process mm, use current->mm if NULL
* @trigger: reason of migration
+ * @fault_page: is from vmf->page, svm_migrate_to_ram(), this is CPU page fault callback
*
* Context: Process context, caller hold mmap read lock, prange->migrate_mutex
*
@@ -766,7 +772,7 @@ out:
int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm,
uint32_t trigger, struct page *fault_page)
{
- struct amdgpu_device *adev;
+ struct kfd_node *node;
struct vm_area_struct *vma;
unsigned long addr;
unsigned long start;
@@ -780,13 +786,11 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm,
return 0;
}
- adev = svm_range_get_adev_by_id(prange, prange->actual_loc);
- if (!adev) {
- pr_debug("failed to get device by id 0x%x\n",
- prange->actual_loc);
+ node = svm_range_get_node_by_id(prange, prange->actual_loc);
+ if (!node) {
+ pr_debug("failed to get kfd node by id 0x%x\n", prange->actual_loc);
return -ENODEV;
}
-
pr_debug("svms 0x%p prange 0x%p [0x%lx 0x%lx] from gpu 0x%x to ram\n",
prange->svms, prange, prange->start, prange->last,
prange->actual_loc);
@@ -805,7 +809,7 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm,
}
next = min(vma->vm_end, end);
- r = svm_migrate_vma_to_ram(adev, prange, vma, addr, next, trigger,
+ r = svm_migrate_vma_to_ram(node, prange, vma, addr, next, trigger,
fault_page);
if (r < 0) {
pr_debug("failed %ld to migrate prange %p\n", r, prange);
@@ -987,18 +991,21 @@ static const struct dev_pagemap_ops svm_migrate_pgmap_ops = {
/* Each VRAM page uses sizeof(struct page) on system memory */
#define SVM_HMM_PAGE_STRUCT_SIZE(size) ((size)/PAGE_SIZE * sizeof(struct page))
-int svm_migrate_init(struct amdgpu_device *adev)
+int kgd2kfd_init_zone_device(struct amdgpu_device *adev)
{
- struct kfd_dev *kfddev = adev->kfd.dev;
+ struct amdgpu_kfd_dev *kfddev = &adev->kfd;
struct dev_pagemap *pgmap;
struct resource *res = NULL;
unsigned long size;
void *r;
- /* Page migration works on Vega10 or newer */
- if (!KFD_IS_SOC15(kfddev))
+ /* Page migration works on gfx9 or newer */
+ if (adev->ip_versions[GC_HWIP][0] < IP_VERSION(9, 0, 1))
return -EINVAL;
+ if (adev->gmc.is_app_apu)
+ return 0;
+
pgmap = &kfddev->pgmap;
memset(pgmap, 0, sizeof(*pgmap));
@@ -1041,8 +1048,6 @@ int svm_migrate_init(struct amdgpu_device *adev)
amdgpu_amdkfd_reserve_system_mem(SVM_HMM_PAGE_STRUCT_SIZE(size));
- svm_range_set_max_pages(adev);
-
pr_info("HMM registered %ldMB device memory\n", size >> 20);
return 0;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h
index a5d7e6d22264..487f26368164 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h
@@ -47,15 +47,6 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm,
unsigned long
svm_migrate_addr_to_pfn(struct amdgpu_device *adev, unsigned long addr);
-int svm_migrate_init(struct amdgpu_device *adev);
-
-#else
-
-static inline int svm_migrate_init(struct amdgpu_device *adev)
-{
- return 0;
-}
-
#endif /* IS_ENABLED(CONFIG_HSA_AMD_SVM) */
#endif /* KFD_MIGRATE_H_ */
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
index 623ccd227b7d..863cf060af48 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
@@ -46,7 +46,7 @@ int pipe_priority_map[] = {
KFD_PIPE_PRIORITY_CS_HIGH
};
-struct kfd_mem_obj *allocate_hiq_mqd(struct kfd_dev *dev, struct queue_properties *q)
+struct kfd_mem_obj *allocate_hiq_mqd(struct kfd_node *dev, struct queue_properties *q)
{
struct kfd_mem_obj *mqd_mem_obj = NULL;
@@ -61,7 +61,7 @@ struct kfd_mem_obj *allocate_hiq_mqd(struct kfd_dev *dev, struct queue_propertie
return mqd_mem_obj;
}
-struct kfd_mem_obj *allocate_sdma_mqd(struct kfd_dev *dev,
+struct kfd_mem_obj *allocate_sdma_mqd(struct kfd_node *dev,
struct queue_properties *q)
{
struct kfd_mem_obj *mqd_mem_obj = NULL;
@@ -72,11 +72,12 @@ struct kfd_mem_obj *allocate_sdma_mqd(struct kfd_dev *dev,
return NULL;
offset = (q->sdma_engine_id *
- dev->device_info.num_sdma_queues_per_engine +
+ dev->kfd->device_info.num_sdma_queues_per_engine +
q->sdma_queue_id) *
dev->dqm->mqd_mgrs[KFD_MQD_TYPE_SDMA]->mqd_size;
- offset += dev->dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]->mqd_size;
+ offset += dev->dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]->mqd_size *
+ NUM_XCC(dev->xcc_mask);
mqd_mem_obj->gtt_mem = (void *)((uint64_t)dev->dqm->hiq_sdma_mqd.gtt_mem
+ offset);
@@ -189,7 +190,7 @@ int kfd_hiq_load_mqd_kiq(struct mqd_manager *mm, void *mqd,
struct queue_properties *p, struct mm_struct *mms)
{
return mm->dev->kfd2kgd->hiq_mqd_load(mm->dev->adev, mqd, pipe_id,
- queue_id, p->doorbell_off);
+ queue_id, p->doorbell_off, 0);
}
int kfd_destroy_mqd_cp(struct mqd_manager *mm, void *mqd,
@@ -197,7 +198,7 @@ int kfd_destroy_mqd_cp(struct mqd_manager *mm, void *mqd,
uint32_t pipe_id, uint32_t queue_id)
{
return mm->dev->kfd2kgd->hqd_destroy(mm->dev->adev, mqd, type, timeout,
- pipe_id, queue_id);
+ pipe_id, queue_id, 0);
}
void kfd_free_mqd_cp(struct mqd_manager *mm, void *mqd,
@@ -216,7 +217,7 @@ bool kfd_is_occupied_cp(struct mqd_manager *mm, void *mqd,
uint32_t queue_id)
{
return mm->dev->kfd2kgd->hqd_is_occupied(mm->dev->adev, queue_address,
- pipe_id, queue_id);
+ pipe_id, queue_id, 0);
}
int kfd_load_mqd_sdma(struct mqd_manager *mm, void *mqd,
@@ -246,3 +247,28 @@ bool kfd_is_occupied_sdma(struct mqd_manager *mm, void *mqd,
{
return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->adev, mqd);
}
+
+uint64_t kfd_hiq_mqd_stride(struct kfd_node *dev)
+{
+ return dev->dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]->mqd_size;
+}
+
+void kfd_get_hiq_xcc_mqd(struct kfd_node *dev, struct kfd_mem_obj *mqd_mem_obj,
+ uint32_t virtual_xcc_id)
+{
+ uint64_t offset;
+
+ offset = kfd_hiq_mqd_stride(dev) * virtual_xcc_id;
+
+ mqd_mem_obj->gtt_mem = (virtual_xcc_id == 0) ?
+ dev->dqm->hiq_sdma_mqd.gtt_mem : NULL;
+ mqd_mem_obj->gpu_addr = dev->dqm->hiq_sdma_mqd.gpu_addr + offset;
+ mqd_mem_obj->cpu_ptr = (uint32_t *)((uintptr_t)
+ dev->dqm->hiq_sdma_mqd.cpu_ptr + offset);
+}
+
+uint64_t kfd_mqd_stride(struct mqd_manager *mm,
+ struct queue_properties *q)
+{
+ return mm->mqd_size;
+}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
index 57f900ccaa10..23158db7da03 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
@@ -68,7 +68,7 @@
*/
extern int pipe_priority_map[];
struct mqd_manager {
- struct kfd_mem_obj* (*allocate_mqd)(struct kfd_dev *kfd,
+ struct kfd_mem_obj* (*allocate_mqd)(struct kfd_node *kfd,
struct queue_properties *q);
void (*init_mqd)(struct mqd_manager *mm, void **mqd,
@@ -97,6 +97,7 @@ struct mqd_manager {
uint32_t queue_id);
int (*get_wave_state)(struct mqd_manager *mm, void *mqd,
+ struct queue_properties *q,
void __user *ctl_stack,
u32 *ctl_stack_used_size,
u32 *save_area_used_size);
@@ -119,16 +120,18 @@ struct mqd_manager {
int (*debugfs_show_mqd)(struct seq_file *m, void *data);
#endif
uint32_t (*read_doorbell_id)(void *mqd);
+ uint64_t (*mqd_stride)(struct mqd_manager *mm,
+ struct queue_properties *p);
struct mutex mqd_mutex;
- struct kfd_dev *dev;
+ struct kfd_node *dev;
uint32_t mqd_size;
};
-struct kfd_mem_obj *allocate_hiq_mqd(struct kfd_dev *dev,
+struct kfd_mem_obj *allocate_hiq_mqd(struct kfd_node *dev,
struct queue_properties *q);
-struct kfd_mem_obj *allocate_sdma_mqd(struct kfd_dev *dev,
+struct kfd_mem_obj *allocate_sdma_mqd(struct kfd_node *dev,
struct queue_properties *q);
void free_mqd_hiq_sdma(struct mqd_manager *mm, void *mqd,
struct kfd_mem_obj *mqd_mem_obj);
@@ -164,4 +167,10 @@ bool kfd_is_occupied_sdma(struct mqd_manager *mm, void *mqd,
uint64_t queue_address, uint32_t pipe_id,
uint32_t queue_id);
+void kfd_get_hiq_xcc_mqd(struct kfd_node *dev,
+ struct kfd_mem_obj *mqd_mem_obj, uint32_t virtual_xcc_id);
+
+uint64_t kfd_hiq_mqd_stride(struct kfd_node *dev);
+uint64_t kfd_mqd_stride(struct mqd_manager *mm,
+ struct queue_properties *q);
#endif /* KFD_MQD_MANAGER_H_ */
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c
index 4889865c725c..65c9f01a1f86 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c
@@ -48,8 +48,7 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
struct cik_mqd *m;
uint32_t se_mask[4] = {0}; /* 4 is the max # of SEs */
- if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
- !minfo->cu_mask.ptr)
+ if (!minfo || !minfo->cu_mask.ptr)
return;
mqd_symmetrically_map_cu_mask(mm,
@@ -74,7 +73,7 @@ static void set_priority(struct cik_mqd *m, struct queue_properties *q)
m->cp_hqd_queue_priority = q->priority;
}
-static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd,
+static struct kfd_mem_obj *allocate_mqd(struct kfd_node *kfd,
struct queue_properties *q)
{
struct kfd_mem_obj *mqd_mem_obj;
@@ -167,7 +166,7 @@ static int load_mqd(struct mqd_manager *mm, void *mqd, uint32_t pipe_id,
return mm->dev->kfd2kgd->hqd_load(mm->dev->adev, mqd, pipe_id, queue_id,
(uint32_t __user *)p->write_ptr,
- wptr_shift, wptr_mask, mms);
+ wptr_shift, wptr_mask, mms, 0);
}
static void __update_mqd(struct mqd_manager *mm, void *mqd,
@@ -390,7 +389,7 @@ static int debugfs_show_mqd_sdma(struct seq_file *m, void *data)
struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev)
+ struct kfd_node *dev)
{
struct mqd_manager *mqd;
@@ -428,6 +427,7 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type,
mqd->destroy_mqd = kfd_destroy_mqd_cp;
mqd->is_occupied = kfd_is_occupied_cp;
mqd->mqd_size = sizeof(struct cik_mqd);
+ mqd->mqd_stride = kfd_mqd_stride;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd;
#endif
@@ -442,6 +442,7 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type,
mqd->destroy_mqd = kfd_destroy_mqd_cp;
mqd->is_occupied = kfd_is_occupied_cp;
mqd->mqd_size = sizeof(struct cik_mqd);
+ mqd->mqd_stride = kfd_mqd_stride;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd;
#endif
@@ -457,6 +458,7 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type,
mqd->checkpoint_mqd = checkpoint_mqd_sdma;
mqd->restore_mqd = restore_mqd_sdma;
mqd->mqd_size = sizeof(struct cik_sdma_rlc_registers);
+ mqd->mqd_stride = kfd_mqd_stride;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd_sdma;
#endif
@@ -470,7 +472,7 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type,
}
struct mqd_manager *mqd_manager_init_cik_hawaii(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev)
+ struct kfd_node *dev)
{
struct mqd_manager *mqd;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
index d3e2b6a599a4..94c0fc2e57b7 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
@@ -48,8 +48,7 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
struct v10_compute_mqd *m;
uint32_t se_mask[4] = {0}; /* 4 is the max # of SEs */
- if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
- !minfo->cu_mask.ptr)
+ if (!minfo || !minfo->cu_mask.ptr)
return;
mqd_symmetrically_map_cu_mask(mm,
@@ -74,7 +73,7 @@ static void set_priority(struct v10_compute_mqd *m, struct queue_properties *q)
m->cp_hqd_queue_priority = q->priority;
}
-static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd,
+static struct kfd_mem_obj *allocate_mqd(struct kfd_node *kfd,
struct queue_properties *q)
{
struct kfd_mem_obj *mqd_mem_obj;
@@ -117,12 +116,17 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
1 << CP_HQD_QUANTUM__QUANTUM_SCALE__SHIFT |
1 << CP_HQD_QUANTUM__QUANTUM_DURATION__SHIFT;
+ /* Set cp_hqd_hq_scheduler0 bit 14 to 1 to have the CP set up the
+ * DISPATCH_PTR. This is required for the kfd debugger
+ */
+ m->cp_hqd_hq_scheduler0 = 1 << 14;
+
if (q->format == KFD_QUEUE_FORMAT_AQL) {
m->cp_hqd_aql_control =
1 << CP_HQD_AQL_CONTROL__CONTROL0__SHIFT;
}
- if (mm->dev->cwsr_enabled) {
+ if (mm->dev->kfd->cwsr_enabled) {
m->cp_hqd_persistent_state |=
(1 << CP_HQD_PERSISTENT_STATE__QSWITCH_MODE__SHIFT);
m->cp_hqd_ctx_save_base_addr_lo =
@@ -151,7 +155,7 @@ static int load_mqd(struct mqd_manager *mm, void *mqd,
r = mm->dev->kfd2kgd->hqd_load(mm->dev->adev, mqd, pipe_id, queue_id,
(uint32_t __user *)p->write_ptr,
- wptr_shift, 0, mms);
+ wptr_shift, 0, mms, 0);
return r;
}
@@ -210,7 +214,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
m->cp_hqd_pq_doorbell_control |=
1 << CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_BIF_DROP__SHIFT;
}
- if (mm->dev->cwsr_enabled)
+ if (mm->dev->kfd->cwsr_enabled)
m->cp_hqd_ctx_save_control = 0;
update_cu_mask(mm, mqd, minfo);
@@ -227,11 +231,13 @@ static uint32_t read_doorbell_id(void *mqd)
}
static int get_wave_state(struct mqd_manager *mm, void *mqd,
+ struct queue_properties *q,
void __user *ctl_stack,
u32 *ctl_stack_used_size,
u32 *save_area_used_size)
{
struct v10_compute_mqd *m;
+ struct kfd_context_save_area_header header;
m = get_mqd(mqd);
@@ -250,6 +256,15 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
* accessible to user mode
*/
+ header.wave_state.control_stack_size = *ctl_stack_used_size;
+ header.wave_state.wave_state_size = *save_area_used_size;
+
+ header.wave_state.wave_state_offset = m->cp_hqd_wg_state_offset;
+ header.wave_state.control_stack_offset = m->cp_hqd_cntl_stack_offset;
+
+ if (copy_to_user(ctl_stack, &header, sizeof(header.wave_state)))
+ return -EFAULT;
+
return 0;
}
@@ -405,7 +420,7 @@ static int debugfs_show_mqd_sdma(struct seq_file *m, void *data)
#endif
struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev)
+ struct kfd_node *dev)
{
struct mqd_manager *mqd;
@@ -432,6 +447,7 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type,
mqd->get_wave_state = get_wave_state;
mqd->checkpoint_mqd = checkpoint_mqd;
mqd->restore_mqd = restore_mqd;
+ mqd->mqd_stride = kfd_mqd_stride;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd;
#endif
@@ -447,6 +463,7 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type,
mqd->destroy_mqd = kfd_destroy_mqd_cp;
mqd->is_occupied = kfd_is_occupied_cp;
mqd->mqd_size = sizeof(struct v10_compute_mqd);
+ mqd->mqd_stride = kfd_mqd_stride;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd;
#endif
@@ -478,6 +495,7 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type,
mqd->checkpoint_mqd = checkpoint_mqd_sdma;
mqd->restore_mqd = restore_mqd_sdma;
mqd->mqd_size = sizeof(struct v10_sdma_mqd);
+ mqd->mqd_stride = kfd_mqd_stride;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd_sdma;
#endif
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
index 5aa75f72caa1..31fec5e70d13 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
@@ -46,15 +46,33 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
{
struct v11_compute_mqd *m;
uint32_t se_mask[KFD_MAX_NUM_SE] = {0};
+ bool has_wa_flag = minfo && (minfo->update_flag & (UPDATE_FLAG_DBG_WA_ENABLE |
+ UPDATE_FLAG_DBG_WA_DISABLE));
- if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
- !minfo->cu_mask.ptr)
+ if (!minfo || !(has_wa_flag || minfo->cu_mask.ptr))
return;
+ m = get_mqd(mqd);
+
+ if (has_wa_flag) {
+ uint32_t wa_mask = minfo->update_flag == UPDATE_FLAG_DBG_WA_ENABLE ?
+ 0xffff : 0xffffffff;
+
+ m->compute_static_thread_mgmt_se0 = wa_mask;
+ m->compute_static_thread_mgmt_se1 = wa_mask;
+ m->compute_static_thread_mgmt_se2 = wa_mask;
+ m->compute_static_thread_mgmt_se3 = wa_mask;
+ m->compute_static_thread_mgmt_se4 = wa_mask;
+ m->compute_static_thread_mgmt_se5 = wa_mask;
+ m->compute_static_thread_mgmt_se6 = wa_mask;
+ m->compute_static_thread_mgmt_se7 = wa_mask;
+
+ return;
+ }
+
mqd_symmetrically_map_cu_mask(mm,
minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
- 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];
@@ -81,7 +99,7 @@ static void set_priority(struct v11_compute_mqd *m, struct queue_properties *q)
m->cp_hqd_queue_priority = q->priority;
}
-static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd,
+static struct kfd_mem_obj *allocate_mqd(struct kfd_node *node,
struct queue_properties *q)
{
struct kfd_mem_obj *mqd_mem_obj;
@@ -91,12 +109,12 @@ static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd,
* MES write to areas beyond MQD size. So allocate
* 1 PAGE_SIZE memory for MQD is MES is enabled.
*/
- if (kfd->shared_resources.enable_mes)
+ if (node->kfd->shared_resources.enable_mes)
size = PAGE_SIZE;
else
size = sizeof(struct v11_compute_mqd);
- if (kfd_gtt_sa_allocate(kfd, size, &mqd_mem_obj))
+ if (kfd_gtt_sa_allocate(node, size, &mqd_mem_obj))
return NULL;
return mqd_mem_obj;
@@ -109,11 +127,12 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
uint64_t addr;
struct v11_compute_mqd *m;
int size;
+ uint32_t wa_mask = q->is_dbg_wa ? 0xffff : 0xffffffff;
m = (struct v11_compute_mqd *) mqd_mem_obj->cpu_ptr;
addr = mqd_mem_obj->gpu_addr;
- if (mm->dev->shared_resources.enable_mes)
+ if (mm->dev->kfd->shared_resources.enable_mes)
size = PAGE_SIZE;
else
size = sizeof(struct v11_compute_mqd);
@@ -122,14 +141,15 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
m->header = 0xC0310800;
m->compute_pipelinestat_enable = 1;
- m->compute_static_thread_mgmt_se0 = 0xFFFFFFFF;
- m->compute_static_thread_mgmt_se1 = 0xFFFFFFFF;
- m->compute_static_thread_mgmt_se2 = 0xFFFFFFFF;
- m->compute_static_thread_mgmt_se3 = 0xFFFFFFFF;
- m->compute_static_thread_mgmt_se4 = 0xFFFFFFFF;
- m->compute_static_thread_mgmt_se5 = 0xFFFFFFFF;
- m->compute_static_thread_mgmt_se6 = 0xFFFFFFFF;
- m->compute_static_thread_mgmt_se7 = 0xFFFFFFFF;
+
+ m->compute_static_thread_mgmt_se0 = wa_mask;
+ m->compute_static_thread_mgmt_se1 = wa_mask;
+ m->compute_static_thread_mgmt_se2 = wa_mask;
+ m->compute_static_thread_mgmt_se3 = wa_mask;
+ m->compute_static_thread_mgmt_se4 = wa_mask;
+ m->compute_static_thread_mgmt_se5 = wa_mask;
+ m->compute_static_thread_mgmt_se6 = wa_mask;
+ m->compute_static_thread_mgmt_se7 = wa_mask;
m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK |
0x55 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT;
@@ -143,6 +163,11 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
1 << CP_HQD_QUANTUM__QUANTUM_SCALE__SHIFT |
1 << CP_HQD_QUANTUM__QUANTUM_DURATION__SHIFT;
+ /* Set cp_hqd_hq_scheduler0 bit 14 to 1 to have the CP set up the
+ * DISPATCH_PTR. This is required for the kfd debugger
+ */
+ m->cp_hqd_hq_status0 = 1 << 14;
+
/*
* GFX11 RS64 CPFW version >= 509 supports PCIe atomics support
* acknowledgment.
@@ -155,7 +180,7 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
1 << CP_HQD_AQL_CONTROL__CONTROL0__SHIFT;
}
- if (mm->dev->cwsr_enabled) {
+ if (mm->dev->kfd->cwsr_enabled) {
m->cp_hqd_persistent_state |=
(1 << CP_HQD_PERSISTENT_STATE__QSWITCH_MODE__SHIFT);
m->cp_hqd_ctx_save_base_addr_lo =
@@ -184,7 +209,7 @@ static int load_mqd(struct mqd_manager *mm, void *mqd,
r = mm->dev->kfd2kgd->hqd_load(mm->dev->adev, mqd, pipe_id, queue_id,
(uint32_t __user *)p->write_ptr,
- wptr_shift, 0, mms);
+ wptr_shift, 0, mms, 0);
return r;
}
@@ -243,7 +268,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
m->cp_hqd_pq_doorbell_control |=
1 << CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_BIF_DROP__SHIFT;
}
- if (mm->dev->cwsr_enabled)
+ if (mm->dev->kfd->cwsr_enabled)
m->cp_hqd_ctx_save_control = 0;
update_cu_mask(mm, mqd, minfo);
@@ -260,12 +285,13 @@ static uint32_t read_doorbell_id(void *mqd)
}
static int get_wave_state(struct mqd_manager *mm, void *mqd,
+ struct queue_properties *q,
void __user *ctl_stack,
u32 *ctl_stack_used_size,
u32 *save_area_used_size)
{
struct v11_compute_mqd *m;
- /*struct mqd_user_context_save_area_header header;*/
+ struct kfd_context_save_area_header header;
m = get_mqd(mqd);
@@ -283,16 +309,15 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
* it's part of the context save area that is already
* accessible to user mode
*/
-/*
- header.control_stack_size = *ctl_stack_used_size;
- header.wave_state_size = *save_area_used_size;
+ header.wave_state.control_stack_size = *ctl_stack_used_size;
+ header.wave_state.wave_state_size = *save_area_used_size;
- header.wave_state_offset = m->cp_hqd_wg_state_offset;
- header.control_stack_offset = m->cp_hqd_cntl_stack_offset;
+ header.wave_state.wave_state_offset = m->cp_hqd_wg_state_offset;
+ header.wave_state.control_stack_offset = m->cp_hqd_cntl_stack_offset;
- if (copy_to_user(ctl_stack, &header, sizeof(header)))
+ if (copy_to_user(ctl_stack, &header, sizeof(header.wave_state)))
return -EFAULT;
-*/
+
return 0;
}
@@ -319,7 +344,7 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
m = (struct v11_sdma_mqd *) mqd_mem_obj->cpu_ptr;
- if (mm->dev->shared_resources.enable_mes)
+ if (mm->dev->kfd->shared_resources.enable_mes)
size = PAGE_SIZE;
else
size = sizeof(struct v11_sdma_mqd);
@@ -387,7 +412,7 @@ static int debugfs_show_mqd_sdma(struct seq_file *m, void *data)
#endif
struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev)
+ struct kfd_node *dev)
{
struct mqd_manager *mqd;
@@ -463,7 +488,7 @@ struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type,
* To allocate SDMA MQDs by generic functions
* when MES is enabled.
*/
- if (dev->shared_resources.enable_mes) {
+ if (dev->kfd->shared_resources.enable_mes) {
mqd->allocate_mqd = allocate_mqd;
mqd->free_mqd = kfd_free_mqd_cp;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
index fdbfd725841f..601bb9f68048 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
@@ -32,6 +32,22 @@
#include "gc/gc_9_0_sh_mask.h"
#include "sdma0/sdma0_4_0_sh_mask.h"
#include "amdgpu_amdkfd.h"
+#include "kfd_device_queue_manager.h"
+
+static void update_mqd(struct mqd_manager *mm, void *mqd,
+ struct queue_properties *q,
+ struct mqd_update_info *minfo);
+
+static uint64_t mqd_stride_v9(struct mqd_manager *mm,
+ struct queue_properties *q)
+{
+ if (mm->dev->kfd->cwsr_enabled &&
+ q->type == KFD_QUEUE_TYPE_COMPUTE)
+ return ALIGN(q->ctl_stack_size, PAGE_SIZE) +
+ ALIGN(sizeof(struct v9_mqd), PAGE_SIZE);
+
+ return mm->mqd_size;
+}
static inline struct v9_mqd *get_mqd(void *mqd)
{
@@ -49,8 +65,7 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
struct v9_mqd *m;
uint32_t se_mask[KFD_MAX_NUM_SE] = {0};
- if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
- !minfo->cu_mask.ptr)
+ if (!minfo || !minfo->cu_mask.ptr)
return;
mqd_symmetrically_map_cu_mask(mm,
@@ -83,7 +98,7 @@ static void set_priority(struct v9_mqd *m, struct queue_properties *q)
m->cp_hqd_queue_priority = q->priority;
}
-static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd,
+static struct kfd_mem_obj *allocate_mqd(struct kfd_node *node,
struct queue_properties *q)
{
int retval;
@@ -105,28 +120,30 @@ static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd,
* pass a special bo flag AMDGPU_GEM_CREATE_CP_MQD_GFX9 to instruct
* amdgpu memory functions to do so.
*/
- if (kfd->cwsr_enabled && (q->type == KFD_QUEUE_TYPE_COMPUTE)) {
+ if (node->kfd->cwsr_enabled && (q->type == KFD_QUEUE_TYPE_COMPUTE)) {
mqd_mem_obj = kzalloc(sizeof(struct kfd_mem_obj), GFP_KERNEL);
if (!mqd_mem_obj)
return NULL;
- retval = amdgpu_amdkfd_alloc_gtt_mem(kfd->adev,
- ALIGN(q->ctl_stack_size, PAGE_SIZE) +
- ALIGN(sizeof(struct v9_mqd), PAGE_SIZE),
+ retval = amdgpu_amdkfd_alloc_gtt_mem(node->adev,
+ (ALIGN(q->ctl_stack_size, PAGE_SIZE) +
+ ALIGN(sizeof(struct v9_mqd), PAGE_SIZE)) *
+ NUM_XCC(node->xcc_mask),
&(mqd_mem_obj->gtt_mem),
&(mqd_mem_obj->gpu_addr),
(void *)&(mqd_mem_obj->cpu_ptr), true);
+
+ if (retval) {
+ kfree(mqd_mem_obj);
+ return NULL;
+ }
} else {
- retval = kfd_gtt_sa_allocate(kfd, sizeof(struct v9_mqd),
+ retval = kfd_gtt_sa_allocate(node, sizeof(struct v9_mqd),
&mqd_mem_obj);
- }
-
- if (retval) {
- kfree(mqd_mem_obj);
- return NULL;
+ if (retval)
+ return NULL;
}
return mqd_mem_obj;
-
}
static void init_mqd(struct mqd_manager *mm, void **mqd,
@@ -135,7 +152,6 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
{
uint64_t addr;
struct v9_mqd *m;
- struct amdgpu_device *adev = (struct amdgpu_device *)mm->dev->adev;
m = (struct v9_mqd *) mqd_mem_obj->cpu_ptr;
addr = mqd_mem_obj->gpu_addr;
@@ -165,31 +181,21 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
1 << CP_HQD_QUANTUM__QUANTUM_SCALE__SHIFT |
1 << CP_HQD_QUANTUM__QUANTUM_DURATION__SHIFT;
- if (q->format == KFD_QUEUE_FORMAT_AQL) {
+ /* Set cp_hqd_hq_scheduler0 bit 14 to 1 to have the CP set up the
+ * DISPATCH_PTR. This is required for the kfd debugger
+ */
+ m->cp_hqd_hq_status0 = 1 << 14;
+
+ if (q->format == KFD_QUEUE_FORMAT_AQL)
m->cp_hqd_aql_control =
1 << CP_HQD_AQL_CONTROL__CONTROL0__SHIFT;
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) {
- /* On GC 9.4.3, DW 41 is re-purposed as
- * compute_tg_chunk_size.
- * TODO: review this setting when active CUs in the
- * partition play a role
- */
- m->compute_static_thread_mgmt_se6 = 1;
- }
- } else {
- /* PM4 queue */
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) {
- m->compute_static_thread_mgmt_se6 = 0;
- /* TODO: program pm4_target_xcc */
- }
- }
if (q->tba_addr) {
m->compute_pgm_rsrc2 |=
(1 << COMPUTE_PGM_RSRC2__TRAP_PRESENT__SHIFT);
}
- if (mm->dev->cwsr_enabled && q->ctx_save_restore_area_address) {
+ if (mm->dev->kfd->cwsr_enabled && q->ctx_save_restore_area_address) {
m->cp_hqd_persistent_state |=
(1 << CP_HQD_PERSISTENT_STATE__QSWITCH_MODE__SHIFT);
m->cp_hqd_ctx_save_base_addr_lo =
@@ -205,7 +211,7 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
*mqd = m;
if (gart_addr)
*gart_addr = addr;
- mm->update_mqd(mm, m, q, NULL);
+ update_mqd(mm, m, q, NULL);
}
static int load_mqd(struct mqd_manager *mm, void *mqd,
@@ -217,14 +223,13 @@ static int load_mqd(struct mqd_manager *mm, void *mqd,
return mm->dev->kfd2kgd->hqd_load(mm->dev->adev, mqd, pipe_id, queue_id,
(uint32_t __user *)p->write_ptr,
- wptr_shift, 0, mms);
+ wptr_shift, 0, mms, 0);
}
static void update_mqd(struct mqd_manager *mm, void *mqd,
struct queue_properties *q,
struct mqd_update_info *minfo)
{
- struct amdgpu_device *adev = (struct amdgpu_device *)mm->dev->adev;
struct v9_mqd *m;
m = get_mqd(mqd);
@@ -257,9 +262,14 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
* Limit is 0xFF EOP entries (= 0x7F8 dwords). CP will not submit
* more than (EOP entry count - 1) so a queue size of 0x800 dwords
* is safe, giving a maximum field value of 0xA.
+ *
+ * Also, do calculation only if EOP is used (size > 0), otherwise
+ * the order_base_2 calculation provides incorrect result.
+ *
*/
- m->cp_hqd_eop_control = min(0xA,
- order_base_2(q->eop_ring_buffer_size / 4) - 1);
+ m->cp_hqd_eop_control = q->eop_ring_buffer_size ?
+ min(0xA, order_base_2(q->eop_ring_buffer_size / 4) - 1) : 0;
+
m->cp_hqd_eop_base_addr_lo =
lower_32_bits(q->eop_ring_buffer_address >> 8);
m->cp_hqd_eop_base_addr_hi =
@@ -270,17 +280,14 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
m->cp_hqd_vmid = q->vmid;
if (q->format == KFD_QUEUE_FORMAT_AQL) {
- m->cp_hqd_pq_control |=
+ m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__NO_UPDATE_RPTR_MASK |
2 << CP_HQD_PQ_CONTROL__SLOT_BASED_WPTR__SHIFT |
1 << CP_HQD_PQ_CONTROL__QUEUE_FULL_EN__SHIFT |
1 << CP_HQD_PQ_CONTROL__WPP_CLAMP_EN__SHIFT;
- if (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 3))
- m->cp_hqd_pq_control |=
- CP_HQD_PQ_CONTROL__NO_UPDATE_RPTR_MASK;
m->cp_hqd_pq_doorbell_control |= 1 <<
CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_BIF_DROP__SHIFT;
}
- if (mm->dev->cwsr_enabled && q->ctx_save_restore_area_address)
+ 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);
@@ -298,11 +305,13 @@ static uint32_t read_doorbell_id(void *mqd)
}
static int get_wave_state(struct mqd_manager *mm, void *mqd,
+ struct queue_properties *q,
void __user *ctl_stack,
u32 *ctl_stack_used_size,
u32 *save_area_used_size)
{
struct v9_mqd *m;
+ struct kfd_context_save_area_header header;
/* Control stack is located one page after MQD. */
void *mqd_ctl_stack = (void *)((uintptr_t)mqd + PAGE_SIZE);
@@ -314,7 +323,18 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
*save_area_used_size = m->cp_hqd_wg_state_offset -
m->cp_hqd_cntl_stack_size;
- if (copy_to_user(ctl_stack, mqd_ctl_stack, m->cp_hqd_cntl_stack_size))
+ header.wave_state.control_stack_size = *ctl_stack_used_size;
+ header.wave_state.wave_state_size = *save_area_used_size;
+
+ header.wave_state.wave_state_offset = m->cp_hqd_wg_state_offset;
+ header.wave_state.control_stack_offset = m->cp_hqd_cntl_stack_offset;
+
+ if (copy_to_user(ctl_stack, &header, sizeof(header.wave_state)))
+ return -EFAULT;
+
+ if (copy_to_user(ctl_stack + m->cp_hqd_cntl_stack_offset,
+ mqd_ctl_stack + m->cp_hqd_cntl_stack_offset,
+ *ctl_stack_used_size))
return -EFAULT;
return 0;
@@ -467,6 +487,288 @@ static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd,
qp->is_active = 0;
}
+static void init_mqd_hiq_v9_4_3(struct mqd_manager *mm, void **mqd,
+ struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
+ struct queue_properties *q)
+{
+ struct v9_mqd *m;
+ int xcc = 0;
+ struct kfd_mem_obj xcc_mqd_mem_obj;
+ uint64_t xcc_gart_addr = 0;
+
+ memset(&xcc_mqd_mem_obj, 0x0, sizeof(struct kfd_mem_obj));
+
+ for (xcc = 0; xcc < NUM_XCC(mm->dev->xcc_mask); xcc++) {
+ kfd_get_hiq_xcc_mqd(mm->dev, &xcc_mqd_mem_obj, xcc);
+
+ init_mqd(mm, (void **)&m, &xcc_mqd_mem_obj, &xcc_gart_addr, q);
+
+ m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__NO_UPDATE_RPTR_MASK |
+ 1 << CP_HQD_PQ_CONTROL__PRIV_STATE__SHIFT |
+ 1 << CP_HQD_PQ_CONTROL__KMD_QUEUE__SHIFT;
+ m->cp_mqd_stride_size = kfd_hiq_mqd_stride(mm->dev);
+ if (xcc == 0) {
+ /* Set no_update_rptr = 0 in Master XCC */
+ m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__NO_UPDATE_RPTR_MASK;
+
+ /* Set the MQD pointer and gart address to XCC0 MQD */
+ *mqd = m;
+ *gart_addr = xcc_gart_addr;
+ }
+ }
+}
+
+static int hiq_load_mqd_kiq_v9_4_3(struct mqd_manager *mm, void *mqd,
+ uint32_t pipe_id, uint32_t queue_id,
+ struct queue_properties *p, struct mm_struct *mms)
+{
+ uint32_t xcc_mask = mm->dev->xcc_mask;
+ int xcc_id, err, inst = 0;
+ void *xcc_mqd;
+ uint64_t hiq_mqd_size = kfd_hiq_mqd_stride(mm->dev);
+
+ for_each_inst(xcc_id, xcc_mask) {
+ xcc_mqd = mqd + hiq_mqd_size * inst;
+ err = mm->dev->kfd2kgd->hiq_mqd_load(mm->dev->adev, xcc_mqd,
+ pipe_id, queue_id,
+ p->doorbell_off, xcc_id);
+ if (err) {
+ pr_debug("Failed to load HIQ MQD for XCC: %d\n", inst);
+ break;
+ }
+ ++inst;
+ }
+
+ return err;
+}
+
+static int destroy_hiq_mqd_v9_4_3(struct mqd_manager *mm, void *mqd,
+ enum kfd_preempt_type type, unsigned int timeout,
+ uint32_t pipe_id, uint32_t queue_id)
+{
+ uint32_t xcc_mask = mm->dev->xcc_mask;
+ int xcc_id, err, inst = 0;
+ void *xcc_mqd;
+ uint64_t hiq_mqd_size = kfd_hiq_mqd_stride(mm->dev);
+
+ for_each_inst(xcc_id, xcc_mask) {
+ xcc_mqd = mqd + hiq_mqd_size * inst;
+ err = mm->dev->kfd2kgd->hqd_destroy(mm->dev->adev, xcc_mqd,
+ type, timeout, pipe_id,
+ queue_id, xcc_id);
+ if (err) {
+ pr_debug("Destroy MQD failed for xcc: %d\n", inst);
+ break;
+ }
+ ++inst;
+ }
+
+ return err;
+}
+
+static void get_xcc_mqd(struct kfd_mem_obj *mqd_mem_obj,
+ struct kfd_mem_obj *xcc_mqd_mem_obj,
+ uint64_t offset)
+{
+ xcc_mqd_mem_obj->gtt_mem = (offset == 0) ?
+ mqd_mem_obj->gtt_mem : NULL;
+ xcc_mqd_mem_obj->gpu_addr = mqd_mem_obj->gpu_addr + offset;
+ xcc_mqd_mem_obj->cpu_ptr = (uint32_t *)((uintptr_t)mqd_mem_obj->cpu_ptr
+ + offset);
+}
+
+static void init_mqd_v9_4_3(struct mqd_manager *mm, void **mqd,
+ struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
+ struct queue_properties *q)
+{
+ struct v9_mqd *m;
+ int xcc = 0;
+ struct kfd_mem_obj xcc_mqd_mem_obj;
+ uint64_t xcc_gart_addr = 0;
+ uint64_t xcc_ctx_save_restore_area_address;
+ uint64_t offset = mm->mqd_stride(mm, q);
+ uint32_t local_xcc_start = mm->dev->dqm->current_logical_xcc_start++;
+
+ memset(&xcc_mqd_mem_obj, 0x0, sizeof(struct kfd_mem_obj));
+ for (xcc = 0; xcc < NUM_XCC(mm->dev->xcc_mask); xcc++) {
+ get_xcc_mqd(mqd_mem_obj, &xcc_mqd_mem_obj, offset*xcc);
+
+ init_mqd(mm, (void **)&m, &xcc_mqd_mem_obj, &xcc_gart_addr, q);
+
+ m->cp_mqd_stride_size = offset;
+
+ /*
+ * Update the CWSR address for each XCC if CWSR is enabled
+ * and CWSR area is allocated in thunk
+ */
+ if (mm->dev->kfd->cwsr_enabled &&
+ q->ctx_save_restore_area_address) {
+ xcc_ctx_save_restore_area_address =
+ q->ctx_save_restore_area_address +
+ (xcc * q->ctx_save_restore_area_size);
+
+ m->cp_hqd_ctx_save_base_addr_lo =
+ lower_32_bits(xcc_ctx_save_restore_area_address);
+ m->cp_hqd_ctx_save_base_addr_hi =
+ upper_32_bits(xcc_ctx_save_restore_area_address);
+ }
+
+ if (q->format == KFD_QUEUE_FORMAT_AQL) {
+ m->compute_tg_chunk_size = 1;
+ m->compute_current_logic_xcc_id =
+ (local_xcc_start + xcc) %
+ NUM_XCC(mm->dev->xcc_mask);
+
+ switch (xcc) {
+ case 0:
+ /* Master XCC */
+ m->cp_hqd_pq_control &=
+ ~CP_HQD_PQ_CONTROL__NO_UPDATE_RPTR_MASK;
+ break;
+ default:
+ break;
+ }
+ } else {
+ /* PM4 Queue */
+ m->compute_current_logic_xcc_id = 0;
+ m->compute_tg_chunk_size = 0;
+ m->pm4_target_xcc_in_xcp = q->pm4_target_xcc;
+ }
+
+ if (xcc == 0) {
+ /* Set the MQD pointer and gart address to XCC0 MQD */
+ *mqd = m;
+ *gart_addr = xcc_gart_addr;
+ }
+ }
+}
+
+static void update_mqd_v9_4_3(struct mqd_manager *mm, void *mqd,
+ struct queue_properties *q, struct mqd_update_info *minfo)
+{
+ struct v9_mqd *m;
+ int xcc = 0;
+ uint64_t size = mm->mqd_stride(mm, q);
+
+ for (xcc = 0; xcc < NUM_XCC(mm->dev->xcc_mask); xcc++) {
+ m = get_mqd(mqd + size * xcc);
+ update_mqd(mm, m, q, minfo);
+
+ if (q->format == KFD_QUEUE_FORMAT_AQL) {
+ switch (xcc) {
+ case 0:
+ /* Master XCC */
+ m->cp_hqd_pq_control &=
+ ~CP_HQD_PQ_CONTROL__NO_UPDATE_RPTR_MASK;
+ break;
+ default:
+ break;
+ }
+ m->compute_tg_chunk_size = 1;
+ } else {
+ /* PM4 Queue */
+ m->compute_current_logic_xcc_id = 0;
+ m->compute_tg_chunk_size = 0;
+ m->pm4_target_xcc_in_xcp = q->pm4_target_xcc;
+ }
+ }
+}
+
+static int destroy_mqd_v9_4_3(struct mqd_manager *mm, void *mqd,
+ enum kfd_preempt_type type, unsigned int timeout,
+ uint32_t pipe_id, uint32_t queue_id)
+{
+ uint32_t xcc_mask = mm->dev->xcc_mask;
+ int xcc_id, err, inst = 0;
+ void *xcc_mqd;
+ struct v9_mqd *m;
+ uint64_t mqd_offset;
+
+ m = get_mqd(mqd);
+ mqd_offset = m->cp_mqd_stride_size;
+
+ for_each_inst(xcc_id, xcc_mask) {
+ xcc_mqd = mqd + mqd_offset * inst;
+ err = mm->dev->kfd2kgd->hqd_destroy(mm->dev->adev, xcc_mqd,
+ type, timeout, pipe_id,
+ queue_id, xcc_id);
+ if (err) {
+ pr_debug("Destroy MQD failed for xcc: %d\n", inst);
+ break;
+ }
+ ++inst;
+ }
+
+ return err;
+}
+
+static int load_mqd_v9_4_3(struct mqd_manager *mm, void *mqd,
+ uint32_t pipe_id, uint32_t queue_id,
+ struct queue_properties *p, struct mm_struct *mms)
+{
+ /* AQL write pointer counts in 64B packets, PM4/CP counts in dwords. */
+ uint32_t wptr_shift = (p->format == KFD_QUEUE_FORMAT_AQL ? 4 : 0);
+ uint32_t xcc_mask = mm->dev->xcc_mask;
+ int xcc_id, err, inst = 0;
+ void *xcc_mqd;
+ uint64_t mqd_stride_size = mm->mqd_stride(mm, p);
+
+ for_each_inst(xcc_id, xcc_mask) {
+ xcc_mqd = mqd + mqd_stride_size * inst;
+ err = mm->dev->kfd2kgd->hqd_load(
+ mm->dev->adev, xcc_mqd, pipe_id, queue_id,
+ (uint32_t __user *)p->write_ptr, wptr_shift, 0, mms,
+ xcc_id);
+ if (err) {
+ pr_debug("Load MQD failed for xcc: %d\n", inst);
+ break;
+ }
+ ++inst;
+ }
+
+ return err;
+}
+
+static int get_wave_state_v9_4_3(struct mqd_manager *mm, void *mqd,
+ struct queue_properties *q,
+ void __user *ctl_stack,
+ u32 *ctl_stack_used_size,
+ u32 *save_area_used_size)
+{
+ int xcc, err = 0;
+ void *xcc_mqd;
+ void __user *xcc_ctl_stack;
+ uint64_t mqd_stride_size = mm->mqd_stride(mm, q);
+ u32 tmp_ctl_stack_used_size = 0, tmp_save_area_used_size = 0;
+
+ for (xcc = 0; xcc < NUM_XCC(mm->dev->xcc_mask); xcc++) {
+ xcc_mqd = mqd + mqd_stride_size * xcc;
+ xcc_ctl_stack = (void __user *)((uintptr_t)ctl_stack +
+ q->ctx_save_restore_area_size * xcc);
+
+ err = get_wave_state(mm, xcc_mqd, q, xcc_ctl_stack,
+ &tmp_ctl_stack_used_size,
+ &tmp_save_area_used_size);
+ if (err)
+ break;
+
+ /*
+ * Set the ctl_stack_used_size and save_area_used_size to
+ * ctl_stack_used_size and save_area_used_size of XCC 0 when
+ * passing the info the user-space.
+ * For multi XCC, user-space would have to look at the header
+ * info of each Control stack area to determine the control
+ * stack size and save area used.
+ */
+ if (xcc == 0) {
+ *ctl_stack_used_size = tmp_ctl_stack_used_size;
+ *save_area_used_size = tmp_save_area_used_size;
+ }
+ }
+
+ return err;
+}
+
#if defined(CONFIG_DEBUG_FS)
static int debugfs_show_mqd(struct seq_file *m, void *data)
@@ -486,7 +788,7 @@ static int debugfs_show_mqd_sdma(struct seq_file *m, void *data)
#endif
struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev)
+ struct kfd_node *dev)
{
struct mqd_manager *mqd;
@@ -502,34 +804,50 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type,
switch (type) {
case KFD_MQD_TYPE_CP:
mqd->allocate_mqd = allocate_mqd;
- mqd->init_mqd = init_mqd;
mqd->free_mqd = kfd_free_mqd_cp;
- mqd->load_mqd = load_mqd;
- mqd->update_mqd = update_mqd;
- mqd->destroy_mqd = kfd_destroy_mqd_cp;
mqd->is_occupied = kfd_is_occupied_cp;
- mqd->get_wave_state = get_wave_state;
mqd->get_checkpoint_info = get_checkpoint_info;
mqd->checkpoint_mqd = checkpoint_mqd;
mqd->restore_mqd = restore_mqd;
mqd->mqd_size = sizeof(struct v9_mqd);
+ mqd->mqd_stride = mqd_stride_v9;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd;
#endif
+ if (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 3)) {
+ mqd->init_mqd = init_mqd_v9_4_3;
+ mqd->load_mqd = load_mqd_v9_4_3;
+ mqd->update_mqd = update_mqd_v9_4_3;
+ mqd->destroy_mqd = destroy_mqd_v9_4_3;
+ mqd->get_wave_state = get_wave_state_v9_4_3;
+ } else {
+ mqd->init_mqd = init_mqd;
+ mqd->load_mqd = load_mqd;
+ mqd->update_mqd = update_mqd;
+ mqd->destroy_mqd = kfd_destroy_mqd_cp;
+ mqd->get_wave_state = get_wave_state;
+ }
break;
case KFD_MQD_TYPE_HIQ:
mqd->allocate_mqd = allocate_hiq_mqd;
- mqd->init_mqd = init_mqd_hiq;
mqd->free_mqd = free_mqd_hiq_sdma;
- mqd->load_mqd = kfd_hiq_load_mqd_kiq;
mqd->update_mqd = update_mqd;
- mqd->destroy_mqd = kfd_destroy_mqd_cp;
mqd->is_occupied = kfd_is_occupied_cp;
mqd->mqd_size = sizeof(struct v9_mqd);
+ mqd->mqd_stride = kfd_mqd_stride;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd;
#endif
mqd->read_doorbell_id = read_doorbell_id;
+ if (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 3)) {
+ mqd->init_mqd = init_mqd_hiq_v9_4_3;
+ mqd->load_mqd = hiq_load_mqd_kiq_v9_4_3;
+ mqd->destroy_mqd = destroy_hiq_mqd_v9_4_3;
+ } else {
+ mqd->init_mqd = init_mqd_hiq;
+ mqd->load_mqd = kfd_hiq_load_mqd_kiq;
+ mqd->destroy_mqd = kfd_destroy_mqd_cp;
+ }
break;
case KFD_MQD_TYPE_DIQ:
mqd->allocate_mqd = allocate_mqd;
@@ -555,6 +873,7 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type,
mqd->checkpoint_mqd = checkpoint_mqd_sdma;
mqd->restore_mqd = restore_mqd_sdma;
mqd->mqd_size = sizeof(struct v9_sdma_mqd);
+ mqd->mqd_stride = kfd_mqd_stride;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd_sdma;
#endif
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c
index 530ba6f5b57e..d1e962da51dd 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c
@@ -51,8 +51,7 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
struct vi_mqd *m;
uint32_t se_mask[4] = {0}; /* 4 is the max # of SEs */
- if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
- !minfo->cu_mask.ptr)
+ if (!minfo || !minfo->cu_mask.ptr)
return;
mqd_symmetrically_map_cu_mask(mm,
@@ -77,7 +76,7 @@ static void set_priority(struct vi_mqd *m, struct queue_properties *q)
m->cp_hqd_queue_priority = q->priority;
}
-static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd,
+static struct kfd_mem_obj *allocate_mqd(struct kfd_node *kfd,
struct queue_properties *q)
{
struct kfd_mem_obj *mqd_mem_obj;
@@ -136,7 +135,7 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
(1 << COMPUTE_PGM_RSRC2__TRAP_PRESENT__SHIFT);
}
- if (mm->dev->cwsr_enabled && q->ctx_save_restore_area_address) {
+ if (mm->dev->kfd->cwsr_enabled && q->ctx_save_restore_area_address) {
m->cp_hqd_persistent_state |=
(1 << CP_HQD_PERSISTENT_STATE__QSWITCH_MODE__SHIFT);
m->cp_hqd_ctx_save_base_addr_lo =
@@ -165,7 +164,7 @@ static int load_mqd(struct mqd_manager *mm, void *mqd,
return mm->dev->kfd2kgd->hqd_load(mm->dev->adev, mqd, pipe_id, queue_id,
(uint32_t __user *)p->write_ptr,
- wptr_shift, wptr_mask, mms);
+ wptr_shift, wptr_mask, mms, 0);
}
static void __update_mqd(struct mqd_manager *mm, void *mqd,
@@ -227,7 +226,7 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
2 << CP_HQD_PQ_CONTROL__SLOT_BASED_WPTR__SHIFT;
}
- if (mm->dev->cwsr_enabled && q->ctx_save_restore_area_address)
+ if (mm->dev->kfd->cwsr_enabled && q->ctx_save_restore_area_address)
m->cp_hqd_ctx_save_control =
atc_bit << CP_HQD_CTX_SAVE_CONTROL__ATC__SHIFT |
mtype << CP_HQD_CTX_SAVE_CONTROL__MTYPE__SHIFT;
@@ -261,6 +260,7 @@ static void update_mqd_tonga(struct mqd_manager *mm, void *mqd,
}
static int get_wave_state(struct mqd_manager *mm, void *mqd,
+ struct queue_properties *q,
void __user *ctl_stack,
u32 *ctl_stack_used_size,
u32 *save_area_used_size)
@@ -446,7 +446,7 @@ static int debugfs_show_mqd_sdma(struct seq_file *m, void *data)
#endif
struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev)
+ struct kfd_node *dev)
{
struct mqd_manager *mqd;
@@ -486,6 +486,7 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type,
mqd->destroy_mqd = kfd_destroy_mqd_cp;
mqd->is_occupied = kfd_is_occupied_cp;
mqd->mqd_size = sizeof(struct vi_mqd);
+ mqd->mqd_stride = kfd_mqd_stride;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd;
#endif
@@ -500,6 +501,7 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type,
mqd->destroy_mqd = kfd_destroy_mqd_cp;
mqd->is_occupied = kfd_is_occupied_cp;
mqd->mqd_size = sizeof(struct vi_mqd);
+ mqd->mqd_stride = kfd_mqd_stride;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd;
#endif
@@ -515,6 +517,7 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type,
mqd->checkpoint_mqd = checkpoint_mqd_sdma;
mqd->restore_mqd = restore_mqd_sdma;
mqd->mqd_size = sizeof(struct vi_sdma_mqd);
+ mqd->mqd_stride = kfd_mqd_stride;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd_sdma;
#endif
@@ -528,7 +531,7 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type,
}
struct mqd_manager *mqd_manager_init_vi_tonga(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev)
+ struct kfd_node *dev)
{
struct mqd_manager *mqd;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
index f612325241aa..401096c103b2 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
@@ -45,7 +45,7 @@ static void pm_calc_rlib_size(struct packet_manager *pm,
unsigned int process_count, queue_count, compute_queue_count, gws_queue_count;
unsigned int map_queue_size;
unsigned int max_proc_per_quantum = 1;
- struct kfd_dev *dev = pm->dqm->dev;
+ struct kfd_node *dev = pm->dqm->dev;
process_count = pm->dqm->processes_count;
queue_count = pm->dqm->active_queue_count;
@@ -370,6 +370,38 @@ out:
return retval;
}
+int pm_update_grace_period(struct packet_manager *pm, uint32_t grace_period)
+{
+ int retval = 0;
+ uint32_t *buffer, size;
+
+ size = pm->pmf->set_grace_period_size;
+
+ mutex_lock(&pm->lock);
+
+ if (size) {
+ kq_acquire_packet_buffer(pm->priv_queue,
+ size / sizeof(uint32_t),
+ (unsigned int **)&buffer);
+
+ if (!buffer) {
+ pr_err("Failed to allocate buffer on kernel queue\n");
+ retval = -ENOMEM;
+ goto out;
+ }
+
+ retval = pm->pmf->set_grace_period(pm, buffer, grace_period);
+ if (!retval)
+ kq_submit_packet(pm->priv_queue);
+ else
+ kq_rollback_packet(pm->priv_queue);
+ }
+
+out:
+ mutex_unlock(&pm->lock);
+ return retval;
+}
+
int pm_send_unmap_queue(struct packet_manager *pm,
enum kfd_unmap_queues_filter filter,
uint32_t filter_param, bool reset)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c
index 18250845a989..29a2d0499b67 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c
@@ -34,6 +34,9 @@ static int pm_map_process_v9(struct packet_manager *pm,
{
struct pm4_mes_map_process *packet;
uint64_t vm_page_table_base_addr = qpd->page_table_base;
+ struct kfd_node *kfd = pm->dqm->dev;
+ struct kfd_process_device *pdd =
+ container_of(qpd, struct kfd_process_device, qpd);
packet = (struct pm4_mes_map_process *)buffer;
memset(buffer, 0, sizeof(struct pm4_mes_map_process));
@@ -49,6 +52,12 @@ static int pm_map_process_v9(struct packet_manager *pm,
packet->bitfields14.sdma_enable = 1;
packet->bitfields14.num_queues = (qpd->is_debug) ? 0 : qpd->queue_count;
+ if (kfd->dqm->trap_debug_vmid && pdd->process->debug_trap_enabled &&
+ pdd->process->runtime_info.runtime_state == DEBUG_RUNTIME_STATE_ENABLED) {
+ packet->bitfields2.debug_vmid = kfd->dqm->trap_debug_vmid;
+ packet->bitfields2.new_debug = 1;
+ }
+
packet->sh_mem_config = qpd->sh_mem_config;
packet->sh_mem_bases = qpd->sh_mem_bases;
if (qpd->tba_addr) {
@@ -79,6 +88,10 @@ static int pm_map_process_aldebaran(struct packet_manager *pm,
{
struct pm4_mes_map_process_aldebaran *packet;
uint64_t vm_page_table_base_addr = qpd->page_table_base;
+ struct kfd_dev *kfd = pm->dqm->dev->kfd;
+ struct kfd_process_device *pdd =
+ container_of(qpd, struct kfd_process_device, qpd);
+ int i;
packet = (struct pm4_mes_map_process_aldebaran *)buffer;
memset(buffer, 0, sizeof(struct pm4_mes_map_process_aldebaran));
@@ -93,6 +106,16 @@ static int pm_map_process_aldebaran(struct packet_manager *pm,
packet->bitfields14.num_oac = qpd->num_oac;
packet->bitfields14.sdma_enable = 1;
packet->bitfields14.num_queues = (qpd->is_debug) ? 0 : qpd->queue_count;
+ packet->spi_gdbg_per_vmid_cntl = pdd->spi_dbg_override |
+ pdd->spi_dbg_launch_mode;
+
+ if (pdd->process->debug_trap_enabled) {
+ for (i = 0; i < kfd->device_info.num_of_watch_points; i++)
+ packet->tcp_watch_cntl[i] = pdd->watch_points[i];
+
+ packet->bitfields2.single_memops =
+ !!(pdd->process->dbg_flags & KFD_DBG_TRAP_FLAG_SINGLE_MEM_OP);
+ }
packet->sh_mem_config = qpd->sh_mem_config;
packet->sh_mem_bases = qpd->sh_mem_bases;
@@ -119,7 +142,7 @@ static int pm_runlist_v9(struct packet_manager *pm, uint32_t *buffer,
struct pm4_mes_runlist *packet;
int concurrent_proc_cnt = 0;
- struct kfd_dev *kfd = pm->dqm->dev;
+ struct kfd_node *kfd = pm->dqm->dev;
/* Determine the number of processes to map together to HW:
* it can not exceed the number of VMIDs available to the
@@ -220,13 +243,24 @@ static int pm_map_queues_v9(struct packet_manager *pm, uint32_t *buffer,
case KFD_QUEUE_TYPE_SDMA:
case KFD_QUEUE_TYPE_SDMA_XGMI:
use_static = false; /* no static queues under SDMA */
- if (q->properties.sdma_engine_id < 2 && !pm_use_ext_eng(q->device))
+ if (q->properties.sdma_engine_id < 2 &&
+ !pm_use_ext_eng(q->device->kfd))
packet->bitfields2.engine_sel = q->properties.sdma_engine_id +
engine_sel__mes_map_queues__sdma0_vi;
else {
- packet->bitfields2.extended_engine_sel =
- extended_engine_sel__mes_map_queues__sdma0_to_7_sel;
- packet->bitfields2.engine_sel = q->properties.sdma_engine_id;
+ /*
+ * For GFX9.4.3, SDMA engine id can be greater than 8.
+ * For such cases, set extended_engine_sel to 2 and
+ * ensure engine_sel lies between 0-7.
+ */
+ if (q->properties.sdma_engine_id >= 8)
+ packet->bitfields2.extended_engine_sel =
+ extended_engine_sel__mes_map_queues__sdma8_to_15_sel;
+ else
+ packet->bitfields2.extended_engine_sel =
+ extended_engine_sel__mes_map_queues__sdma0_to_7_sel;
+
+ packet->bitfields2.engine_sel = q->properties.sdma_engine_id % 8;
}
break;
default:
@@ -251,6 +285,41 @@ static int pm_map_queues_v9(struct packet_manager *pm, uint32_t *buffer,
return 0;
}
+static int pm_set_grace_period_v9(struct packet_manager *pm,
+ uint32_t *buffer,
+ uint32_t grace_period)
+{
+ struct pm4_mec_write_data_mmio *packet;
+ uint32_t reg_offset = 0;
+ uint32_t reg_data = 0;
+
+ pm->dqm->dev->kfd2kgd->build_grace_period_packet_info(
+ pm->dqm->dev->adev,
+ pm->dqm->wait_times,
+ grace_period,
+ &reg_offset,
+ &reg_data);
+
+ if (grace_period == USE_DEFAULT_GRACE_PERIOD)
+ reg_data = pm->dqm->wait_times;
+
+ packet = (struct pm4_mec_write_data_mmio *)buffer;
+ memset(buffer, 0, sizeof(struct pm4_mec_write_data_mmio));
+
+ packet->header.u32All = pm_build_pm4_header(IT_WRITE_DATA,
+ sizeof(struct pm4_mec_write_data_mmio));
+
+ packet->bitfields2.dst_sel = dst_sel___write_data__mem_mapped_register;
+ packet->bitfields2.addr_incr =
+ addr_incr___write_data__do_not_increment_address;
+
+ packet->bitfields3.dst_mmreg_addr = reg_offset;
+
+ packet->data = reg_data;
+
+ return 0;
+}
+
static int pm_unmap_queues_v9(struct packet_manager *pm, uint32_t *buffer,
enum kfd_unmap_queues_filter filter,
uint32_t filter_param, bool reset)
@@ -263,7 +332,8 @@ static int pm_unmap_queues_v9(struct packet_manager *pm, uint32_t *buffer,
packet->header.u32All = pm_build_pm4_header(IT_UNMAP_QUEUES,
sizeof(struct pm4_mes_unmap_queues));
- packet->bitfields2.extended_engine_sel = pm_use_ext_eng(pm->dqm->dev) ?
+ packet->bitfields2.extended_engine_sel =
+ pm_use_ext_eng(pm->dqm->dev->kfd) ?
extended_engine_sel__mes_unmap_queues__sdma0_to_7_sel :
extended_engine_sel__mes_unmap_queues__legacy_engine_sel;
@@ -333,6 +403,7 @@ const struct packet_manager_funcs kfd_v9_pm_funcs = {
.set_resources = pm_set_resources_v9,
.map_queues = pm_map_queues_v9,
.unmap_queues = pm_unmap_queues_v9,
+ .set_grace_period = pm_set_grace_period_v9,
.query_status = pm_query_status_v9,
.release_mem = NULL,
.map_process_size = sizeof(struct pm4_mes_map_process),
@@ -340,6 +411,7 @@ const struct packet_manager_funcs kfd_v9_pm_funcs = {
.set_resources_size = sizeof(struct pm4_mes_set_resources),
.map_queues_size = sizeof(struct pm4_mes_map_queues),
.unmap_queues_size = sizeof(struct pm4_mes_unmap_queues),
+ .set_grace_period_size = sizeof(struct pm4_mec_write_data_mmio),
.query_status_size = sizeof(struct pm4_mes_query_status),
.release_mem_size = 0,
};
@@ -350,6 +422,7 @@ const struct packet_manager_funcs kfd_aldebaran_pm_funcs = {
.set_resources = pm_set_resources_v9,
.map_queues = pm_map_queues_v9,
.unmap_queues = pm_unmap_queues_v9,
+ .set_grace_period = pm_set_grace_period_v9,
.query_status = pm_query_status_v9,
.release_mem = NULL,
.map_process_size = sizeof(struct pm4_mes_map_process_aldebaran),
@@ -357,6 +430,7 @@ const struct packet_manager_funcs kfd_aldebaran_pm_funcs = {
.set_resources_size = sizeof(struct pm4_mes_set_resources),
.map_queues_size = sizeof(struct pm4_mes_map_queues),
.unmap_queues_size = sizeof(struct pm4_mes_unmap_queues),
+ .set_grace_period_size = sizeof(struct pm4_mec_write_data_mmio),
.query_status_size = sizeof(struct pm4_mes_query_status),
.release_mem_size = 0,
};
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c
index 4f951eaa6ee8..c1199d06d131 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c
@@ -77,7 +77,7 @@ static int pm_runlist_vi(struct packet_manager *pm, uint32_t *buffer,
{
struct pm4_mes_runlist *packet;
int concurrent_proc_cnt = 0;
- struct kfd_dev *kfd = pm->dqm->dev;
+ struct kfd_node *kfd = pm->dqm->dev;
if (WARN_ON(!ib))
return -EFAULT;
@@ -303,6 +303,7 @@ const struct packet_manager_funcs kfd_vi_pm_funcs = {
.set_resources = pm_set_resources_vi,
.map_queues = pm_map_queues_vi,
.unmap_queues = pm_unmap_queues_vi,
+ .set_grace_period = NULL,
.query_status = pm_query_status_vi,
.release_mem = pm_release_mem_vi,
.map_process_size = sizeof(struct pm4_mes_map_process),
@@ -310,6 +311,7 @@ const struct packet_manager_funcs kfd_vi_pm_funcs = {
.set_resources_size = sizeof(struct pm4_mes_set_resources),
.map_queues_size = sizeof(struct pm4_mes_map_queues),
.unmap_queues_size = sizeof(struct pm4_mes_unmap_queues),
+ .set_grace_period_size = 0,
.query_status_size = sizeof(struct pm4_mes_query_status),
.release_mem_size = sizeof(struct pm4_mec_release_mem)
};
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_ai.h b/drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_ai.h
index a666710ed403..8b6b2bd5c148 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_ai.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_ai.h
@@ -146,7 +146,10 @@ struct pm4_mes_map_process {
union {
struct {
uint32_t pasid:16;
- uint32_t reserved1:8;
+ uint32_t reserved1:2;
+ uint32_t debug_vmid:4;
+ uint32_t new_debug:1;
+ uint32_t reserved2:1;
uint32_t diq_enable:1;
uint32_t process_quantum:7;
} bitfields2;
@@ -263,7 +266,8 @@ enum mes_map_queues_engine_sel_enum {
enum mes_map_queues_extended_engine_sel_enum {
extended_engine_sel__mes_map_queues__legacy_engine_sel = 0,
- extended_engine_sel__mes_map_queues__sdma0_to_7_sel = 1
+ extended_engine_sel__mes_map_queues__sdma0_to_7_sel = 1,
+ extended_engine_sel__mes_map_queues__sdma8_to_15_sel = 2
};
struct pm4_mes_map_queues {
@@ -583,6 +587,71 @@ struct pm4_mec_release_mem {
#endif
+#ifndef PM4_MEC_WRITE_DATA_DEFINED
+#define PM4_MEC_WRITE_DATA_DEFINED
+
+enum WRITE_DATA_dst_sel_enum {
+ dst_sel___write_data__mem_mapped_register = 0,
+ dst_sel___write_data__tc_l2 = 2,
+ dst_sel___write_data__gds = 3,
+ dst_sel___write_data__memory = 5,
+ dst_sel___write_data__memory_mapped_adc_persistent_state = 6,
+};
+
+enum WRITE_DATA_addr_incr_enum {
+ addr_incr___write_data__increment_address = 0,
+ addr_incr___write_data__do_not_increment_address = 1
+};
+
+enum WRITE_DATA_wr_confirm_enum {
+ wr_confirm___write_data__do_not_wait_for_write_confirmation = 0,
+ wr_confirm___write_data__wait_for_write_confirmation = 1
+};
+
+enum WRITE_DATA_cache_policy_enum {
+ cache_policy___write_data__lru = 0,
+ cache_policy___write_data__stream = 1
+};
+
+
+struct pm4_mec_write_data_mmio {
+ union {
+ union PM4_MES_TYPE_3_HEADER header; /*header */
+ unsigned int ordinal1;
+ };
+
+ union {
+ struct {
+ unsigned int reserved1:8;
+ unsigned int dst_sel:4;
+ unsigned int reserved2:4;
+ unsigned int addr_incr:1;
+ unsigned int reserved3:2;
+ unsigned int resume_vf:1;
+ unsigned int wr_confirm:1;
+ unsigned int reserved4:4;
+ unsigned int cache_policy:2;
+ unsigned int reserved5:5;
+ } bitfields2;
+ unsigned int ordinal2;
+ };
+
+ union {
+ struct {
+ unsigned int dst_mmreg_addr:18;
+ unsigned int reserved6:14;
+ } bitfields3;
+ unsigned int ordinal3;
+ };
+
+ uint32_t reserved7;
+
+ uint32_t data;
+
+};
+
+#endif
+
enum {
CACHE_FLUSH_AND_INV_TS_EVENT = 0x00000014
};
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index 94a438956868..7364a5d77c6e 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -113,6 +113,8 @@
#define KFD_UNMAP_LATENCY_MS (4000)
+#define KFD_MAX_SDMA_QUEUES 128
+
/*
* 512 = 0x200
* The doorbell index distance between SDMA RLC (2*i) and (2*i+1) in the
@@ -199,6 +201,8 @@ extern int amdgpu_no_queue_eviction_on_vm_fault;
/* Enable eviction debug messages */
extern bool debug_evictions;
+extern struct mutex kfd_processes_mutex;
+
enum cache_policy {
cache_policy_coherent,
cache_policy_noncoherent
@@ -210,11 +214,13 @@ enum cache_policy {
((KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 2)) || \
(KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 3)))
+struct kfd_node;
+
struct kfd_event_interrupt_class {
- bool (*interrupt_isr)(struct kfd_dev *dev,
+ bool (*interrupt_isr)(struct kfd_node *dev,
const uint32_t *ih_ring_entry, uint32_t *patched_ihre,
bool *patched_flag);
- void (*interrupt_wq)(struct kfd_dev *dev,
+ void (*interrupt_wq)(struct kfd_node *dev,
const uint32_t *ih_ring_entry);
};
@@ -233,11 +239,11 @@ struct kfd_device_info {
uint32_t no_atomic_fw_version;
unsigned int num_sdma_queues_per_engine;
unsigned int num_reserved_sdma_queues_per_engine;
- uint64_t reserved_sdma_queues_bitmap;
+ DECLARE_BITMAP(reserved_sdma_queues_bitmap, KFD_MAX_SDMA_QUEUES);
};
-unsigned int kfd_get_num_sdma_engines(struct kfd_dev *kdev);
-unsigned int kfd_get_num_xgmi_sdma_engines(struct kfd_dev *kdev);
+unsigned int kfd_get_num_sdma_engines(struct kfd_node *kdev);
+unsigned int kfd_get_num_xgmi_sdma_engines(struct kfd_node *kdev);
struct kfd_mem_obj {
uint32_t range_start;
@@ -253,13 +259,70 @@ struct kfd_vmid_info {
uint32_t vmid_num_kfd;
};
+#define MAX_KFD_NODES 8
+
+struct kfd_dev;
+
+struct kfd_node {
+ unsigned int node_id;
+ struct amdgpu_device *adev; /* Duplicated here along with keeping
+ * a copy in kfd_dev to save a hop
+ */
+ const struct kfd2kgd_calls *kfd2kgd; /* Duplicated here along with
+ * keeping a copy in kfd_dev to
+ * save a hop
+ */
+ struct kfd_vmid_info vm_info;
+ unsigned int id; /* topology stub index */
+ uint32_t xcc_mask; /* Instance mask of XCCs present */
+ struct amdgpu_xcp *xcp;
+
+ /* Interrupts */
+ struct kfifo ih_fifo;
+ struct workqueue_struct *ih_wq;
+ struct work_struct interrupt_work;
+ spinlock_t interrupt_lock;
+
+ /*
+ * Interrupts of interest to KFD are copied
+ * from the HW ring into a SW ring.
+ */
+ bool interrupts_active;
+ uint32_t interrupt_bitmap; /* Only used for GFX 9.4.3 */
+
+ /* QCM Device instance */
+ struct device_queue_manager *dqm;
+
+ /* Global GWS resource shared between processes */
+ void *gws;
+ bool gws_debug_workaround;
+
+ /* Clients watching SMI events */
+ struct list_head smi_clients;
+ spinlock_t smi_lock;
+ uint32_t reset_seq_num;
+
+ /* SRAM ECC flag */
+ atomic_t sram_ecc_flag;
+
+ /*spm process id */
+ unsigned int spm_pasid;
+
+ /* Maximum process number mapped to HW scheduler */
+ unsigned int max_proc_per_quantum;
+
+ unsigned int compute_vmid_bitmap;
+
+ struct kfd_local_mem_info local_mem_info;
+
+ struct kfd_dev *kfd;
+};
+
struct kfd_dev {
struct amdgpu_device *adev;
struct kfd_device_info device_info;
- unsigned int id; /* topology stub index */
-
phys_addr_t doorbell_base; /* Start of actual doorbells used by
* KFD. It is aligned for mapping
* into user mode
@@ -274,8 +337,6 @@ struct kfd_dev {
*/
struct kgd2kfd_shared_resources shared_resources;
- struct kfd_vmid_info vm_info;
- struct kfd_local_mem_info local_mem_info;
const struct kfd2kgd_calls *kfd2kgd;
struct mutex doorbell_mutex;
@@ -290,30 +351,13 @@ struct kfd_dev {
unsigned int gtt_sa_chunk_size;
unsigned int gtt_sa_num_of_chunks;
- /* Interrupts */
- struct kfifo ih_fifo;
- struct workqueue_struct *ih_wq;
- struct work_struct interrupt_work;
- spinlock_t interrupt_lock;
-
- /* QCM Device instance */
- struct device_queue_manager *dqm;
-
bool init_complete;
- /*
- * Interrupts of interest to KFD are copied
- * from the HW ring into a SW ring.
- */
- bool interrupts_active;
/* Firmware versions */
uint16_t mec_fw_version;
uint16_t mec2_fw_version;
uint16_t sdma_fw_version;
- /* Maximum process number mapped to HW scheduler */
- unsigned int max_proc_per_quantum;
-
/* CWSR */
bool cwsr_enabled;
const void *cwsr_isa;
@@ -327,28 +371,20 @@ struct kfd_dev {
/* Use IOMMU v2 flag */
bool use_iommu_v2;
- /* SRAM ECC flag */
- atomic_t sram_ecc_flag;
-
/* Compute Profile ref. count */
atomic_t compute_profile;
- /* Global GWS resource shared between processes */
- void *gws;
-
- /* Clients watching SMI events */
- struct list_head smi_clients;
- spinlock_t smi_lock;
-
- uint32_t reset_seq_num;
-
struct ida doorbell_ida;
unsigned int max_doorbell_slices;
int noretry;
- /* HMM page migration MEMORY_DEVICE_PRIVATE mapping */
- struct dev_pagemap pgmap;
+ struct kfd_node *nodes[MAX_KFD_NODES];
+ unsigned int num_nodes;
+
+ /* Track per device allocated watch points */
+ uint32_t alloc_watch_ids;
+ spinlock_t watch_points_lock;
};
enum kfd_mempool {
@@ -478,8 +514,13 @@ struct queue_properties {
uint32_t doorbell_off;
bool is_interop;
bool is_evicted;
+ bool is_suspended;
+ bool is_being_destroyed;
bool is_active;
bool is_gws;
+ uint32_t pm4_target_xcc;
+ bool is_dbg_wa;
+ bool is_user_cu_masked;
/* Not relevant for user mode queues in cp scheduling */
unsigned int vmid;
/* Relevant only for sdma queues*/
@@ -494,15 +535,18 @@ struct queue_properties {
uint32_t ctl_stack_size;
uint64_t tba_addr;
uint64_t tma_addr;
+ uint64_t exception_status;
};
#define QUEUE_IS_ACTIVE(q) ((q).queue_size > 0 && \
(q).queue_address != 0 && \
(q).queue_percent > 0 && \
- !(q).is_evicted)
+ !(q).is_evicted && \
+ !(q).is_suspended)
enum mqd_update_flag {
- UPDATE_FLAG_CU_MASK = 0,
+ UPDATE_FLAG_DBG_WA_ENABLE = 1,
+ UPDATE_FLAG_DBG_WA_DISABLE = 2,
};
struct mqd_update_info {
@@ -563,7 +607,7 @@ struct queue {
unsigned int doorbell_id;
struct kfd_process *process;
- struct kfd_dev *device;
+ struct kfd_node *device;
void *gws;
/* procfs */
@@ -697,7 +741,7 @@ enum kfd_pdd_bound {
/* Data that is per-process-per device. */
struct kfd_process_device {
/* The device that owns this data. */
- struct kfd_dev *dev;
+ struct kfd_node *dev;
/* The process that owns this kfd_process_device. */
struct kfd_process *process;
@@ -783,6 +827,18 @@ struct kfd_process_device {
uint64_t faults;
uint64_t page_in;
uint64_t page_out;
+
+ /* Exception code status*/
+ uint64_t exception_status;
+ void *vm_fault_exc_data;
+ size_t vm_fault_exc_data_size;
+
+ /* Tracks debug per-vmid request settings */
+ uint32_t spi_dbg_override;
+ uint32_t spi_dbg_launch_mode;
+ uint32_t watch_points[4];
+ uint32_t alloc_watch_ids;
+
/*
* If this process has been checkpointed before, then the user
* application will use the original gpu_id on the
@@ -887,19 +943,57 @@ struct kfd_process {
*/
unsigned long last_restore_timestamp;
+ /* Indicates device process is debug attached with reserved vmid. */
+ bool debug_trap_enabled;
+
+ /* per-process-per device debug event fd file */
+ struct file *dbg_ev_file;
+
+ /* If the process is a kfd debugger, we need to know so we can clean
+ * up at exit time. If a process enables debugging on itself, it does
+ * its own clean-up, so we don't set the flag here. We track this by
+ * counting the number of processes this process is debugging.
+ */
+ atomic_t debugged_process_count;
+
+ /* If the process is a debugged, this is the debugger process */
+ struct kfd_process *debugger_process;
+
/* Kobj for our procfs */
struct kobject *kobj;
struct kobject *kobj_queues;
struct attribute attr_pasid;
+ /* Keep track cwsr init */
+ bool has_cwsr;
+
+ /* Exception code enable mask and status */
+ uint64_t exception_enable_mask;
+ uint64_t exception_status;
+
+ /* Used to drain stale interrupts */
+ wait_queue_head_t wait_irq_drain;
+ bool irq_drain_is_open;
+
/* shared virtual memory registered by this process */
struct svm_range_list svms;
bool xnack_enabled;
+ /* Work area for debugger event writer worker. */
+ struct work_struct debug_event_workarea;
+
+ /* Tracks debug per-vmid request for debug flags */
+ bool dbg_flags;
+
atomic_t poison;
/* Queues are in paused stated because we are in the process of doing a CRIU checkpoint */
bool queues_paused;
+
+ /* Tracks runtime enable status */
+ struct semaphore runtime_enable_sema;
+ bool is_runtime_retry;
+ struct kfd_runtime_info runtime_info;
};
#define KFD_PROCESS_TABLE_SIZE 5 /* bits: 32 entries */
@@ -925,20 +1019,19 @@ struct amdkfd_ioctl_desc {
unsigned int cmd_drv;
const char *name;
};
-bool kfd_dev_is_large_bar(struct kfd_dev *dev);
+bool kfd_dev_is_large_bar(struct kfd_node *dev);
int kfd_process_create_wq(void);
void kfd_process_destroy_wq(void);
void kfd_cleanup_processes(void);
-struct kfd_process *kfd_create_process(struct file *filep);
+struct kfd_process *kfd_create_process(struct task_struct *thread);
struct kfd_process *kfd_get_process(const struct task_struct *task);
struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid);
struct kfd_process *kfd_lookup_process_by_mm(const struct mm_struct *mm);
int kfd_process_gpuidx_from_gpuid(struct kfd_process *p, uint32_t gpu_id);
-int kfd_process_gpuid_from_adev(struct kfd_process *p,
- struct amdgpu_device *adev, uint32_t *gpuid,
- uint32_t *gpuidx);
+int kfd_process_gpuid_from_node(struct kfd_process *p, struct kfd_node *node,
+ uint32_t *gpuid, uint32_t *gpuidx);
static inline int kfd_process_gpuid_from_gpuidx(struct kfd_process *p,
uint32_t gpuidx, uint32_t *gpuid) {
return gpuidx < p->n_pdds ? p->pdds[gpuidx]->dev->id : -EINVAL;
@@ -961,16 +1054,16 @@ int kfd_process_get_user_gpu_id(struct kfd_process *p, uint32_t actual_gpu_id);
int kfd_process_device_init_vm(struct kfd_process_device *pdd,
struct file *drm_file);
-struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev,
+struct kfd_process_device *kfd_bind_process_to_device(struct kfd_node *dev,
struct kfd_process *p);
-struct kfd_process_device *kfd_get_process_device_data(struct kfd_dev *dev,
+struct kfd_process_device *kfd_get_process_device_data(struct kfd_node *dev,
struct kfd_process *p);
-struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev,
+struct kfd_process_device *kfd_create_process_device_data(struct kfd_node *dev,
struct kfd_process *p);
bool kfd_process_xnack_mode(struct kfd_process *p, bool supported);
-int kfd_reserved_mem_mmap(struct kfd_dev *dev, struct kfd_process *process,
+int kfd_reserved_mem_mmap(struct kfd_node *dev, struct kfd_process *process,
struct vm_area_struct *vma);
/* KFD process API for creating and translating handles */
@@ -994,7 +1087,7 @@ void kfd_pasid_free(u32 pasid);
size_t kfd_doorbell_process_slice(struct kfd_dev *kfd);
int kfd_doorbell_init(struct kfd_dev *kfd);
void kfd_doorbell_fini(struct kfd_dev *kfd);
-int kfd_doorbell_mmap(struct kfd_dev *dev, struct kfd_process *process,
+int kfd_doorbell_mmap(struct kfd_node *dev, struct kfd_process *process,
struct vm_area_struct *vma);
void __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd,
unsigned int *doorbell_off);
@@ -1012,10 +1105,10 @@ void kfd_free_process_doorbells(struct kfd_dev *kfd,
unsigned int doorbell_index);
/* GTT Sub-Allocator */
-int kfd_gtt_sa_allocate(struct kfd_dev *kfd, unsigned int size,
+int kfd_gtt_sa_allocate(struct kfd_node *node, unsigned int size,
struct kfd_mem_obj **mem_obj);
-int kfd_gtt_sa_free(struct kfd_dev *kfd, struct kfd_mem_obj *mem_obj);
+int kfd_gtt_sa_free(struct kfd_node *node, struct kfd_mem_obj *mem_obj);
extern struct device *kfd_device;
@@ -1028,27 +1121,53 @@ void kfd_procfs_del_queue(struct queue *q);
/* Topology */
int kfd_topology_init(void);
void kfd_topology_shutdown(void);
-int kfd_topology_add_device(struct kfd_dev *gpu);
-int kfd_topology_remove_device(struct kfd_dev *gpu);
+int kfd_topology_add_device(struct kfd_node *gpu);
+int kfd_topology_remove_device(struct kfd_node *gpu);
struct kfd_topology_device *kfd_topology_device_by_proximity_domain(
uint32_t proximity_domain);
struct kfd_topology_device *kfd_topology_device_by_proximity_domain_no_lock(
uint32_t proximity_domain);
struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id);
-struct kfd_dev *kfd_device_by_id(uint32_t gpu_id);
-struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev);
-struct kfd_dev *kfd_device_by_adev(const struct amdgpu_device *adev);
-int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev);
+struct kfd_node *kfd_device_by_id(uint32_t gpu_id);
+struct kfd_node *kfd_device_by_pci_dev(const struct pci_dev *pdev);
+static inline bool kfd_irq_is_from_node(struct kfd_node *node, uint32_t node_id,
+ uint32_t vmid)
+{
+ return (node->interrupt_bitmap & (1 << node_id)) != 0 &&
+ (node->compute_vmid_bitmap & (1 << vmid)) != 0;
+}
+static inline struct kfd_node *kfd_node_by_irq_ids(struct amdgpu_device *adev,
+ uint32_t node_id, uint32_t vmid) {
+ struct kfd_dev *dev = adev->kfd.dev;
+ uint32_t i;
+
+ if (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 3))
+ return dev->nodes[0];
+
+ for (i = 0; i < dev->num_nodes; i++)
+ if (kfd_irq_is_from_node(dev->nodes[i], node_id, vmid))
+ return dev->nodes[i];
+
+ return NULL;
+}
+int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_node **kdev);
int kfd_numa_node_to_apic_id(int numa_node_id);
void kfd_double_confirm_iommu_support(struct kfd_dev *gpu);
/* Interrupts */
-int kfd_interrupt_init(struct kfd_dev *dev);
-void kfd_interrupt_exit(struct kfd_dev *dev);
-bool enqueue_ih_ring_entry(struct kfd_dev *kfd, const void *ih_ring_entry);
-bool interrupt_is_wanted(struct kfd_dev *dev,
+#define KFD_IRQ_FENCE_CLIENTID 0xff
+#define KFD_IRQ_FENCE_SOURCEID 0xff
+#define KFD_IRQ_IS_FENCE(client, source) \
+ ((client) == KFD_IRQ_FENCE_CLIENTID && \
+ (source) == KFD_IRQ_FENCE_SOURCEID)
+int kfd_interrupt_init(struct kfd_node *dev);
+void kfd_interrupt_exit(struct kfd_node *dev);
+bool enqueue_ih_ring_entry(struct kfd_node *kfd, const void *ih_ring_entry);
+bool interrupt_is_wanted(struct kfd_node *dev,
const uint32_t *ih_ring_entry,
uint32_t *patched_ihre, bool *flag);
+int kfd_process_drain_interrupts(struct kfd_process_device *pdd);
+void kfd_process_close_interrupt_drain(unsigned int pasid);
/* amdkfd Apertures */
int kfd_init_apertures(struct kfd_process *process);
@@ -1056,6 +1175,11 @@ int kfd_init_apertures(struct kfd_process *process);
void kfd_process_set_trap_handler(struct qcm_process_device *qpd,
uint64_t tba_addr,
uint64_t tma_addr);
+void kfd_process_set_trap_debug_flag(struct qcm_process_device *qpd,
+ bool enabled);
+
+/* CWSR initialization */
+int kfd_process_init_cwsr_apu(struct kfd_process *process, struct file *filep);
/* CRIU */
/*
@@ -1174,22 +1298,22 @@ void print_queue_properties(struct queue_properties *q);
void print_queue(struct queue *q);
struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev);
+ struct kfd_node *dev);
struct mqd_manager *mqd_manager_init_cik_hawaii(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev);
+ struct kfd_node *dev);
struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev);
+ struct kfd_node *dev);
struct mqd_manager *mqd_manager_init_vi_tonga(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev);
+ struct kfd_node *dev);
struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev);
+ struct kfd_node *dev);
struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev);
+ struct kfd_node *dev);
struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type,
- struct kfd_dev *dev);
-struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev);
+ struct kfd_node *dev);
+struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev);
void device_queue_manager_uninit(struct device_queue_manager *dqm);
-struct kernel_queue *kernel_queue_init(struct kfd_dev *dev,
+struct kernel_queue *kernel_queue_init(struct kfd_node *dev,
enum kfd_queue_type type);
void kernel_queue_uninit(struct kernel_queue *kq, bool hanging);
int kfd_dqm_evict_pasid(struct device_queue_manager *dqm, u32 pasid);
@@ -1206,7 +1330,7 @@ void kfd_process_dequeue_from_all_devices(struct kfd_process *p);
int pqm_init(struct process_queue_manager *pqm, struct kfd_process *p);
void pqm_uninit(struct process_queue_manager *pqm);
int pqm_create_queue(struct process_queue_manager *pqm,
- struct kfd_dev *dev,
+ struct kfd_node *dev,
struct file *f,
struct queue_properties *properties,
unsigned int *qid,
@@ -1231,6 +1355,11 @@ int pqm_get_wave_state(struct process_queue_manager *pqm,
void __user *ctl_stack,
u32 *ctl_stack_used_size,
u32 *save_area_used_size);
+int pqm_get_queue_snapshot(struct process_queue_manager *pqm,
+ uint64_t exception_clear_mask,
+ void __user *buf,
+ int *num_qss_entries,
+ uint32_t *entry_size);
int amdkfd_fence_wait_timeout(uint64_t *fence_addr,
uint64_t fence_value,
@@ -1270,6 +1399,8 @@ struct packet_manager_funcs {
int (*unmap_queues)(struct packet_manager *pm, uint32_t *buffer,
enum kfd_unmap_queues_filter mode,
uint32_t filter_param, bool reset);
+ int (*set_grace_period)(struct packet_manager *pm, uint32_t *buffer,
+ uint32_t grace_period);
int (*query_status)(struct packet_manager *pm, uint32_t *buffer,
uint64_t fence_address, uint64_t fence_value);
int (*release_mem)(uint64_t gpu_addr, uint32_t *buffer);
@@ -1280,6 +1411,7 @@ struct packet_manager_funcs {
int set_resources_size;
int map_queues_size;
int unmap_queues_size;
+ int set_grace_period_size;
int query_status_size;
int release_mem_size;
};
@@ -1302,6 +1434,8 @@ int pm_send_unmap_queue(struct packet_manager *pm,
void pm_release_ib(struct packet_manager *pm);
+int pm_update_grace_period(struct packet_manager *pm, uint32_t grace_period);
+
/* Following PM funcs can be shared among VI and AI */
unsigned int pm_build_pm4_header(unsigned int opcode, size_t packet_size);
@@ -1310,6 +1444,7 @@ uint64_t kfd_get_number_elems(struct kfd_dev *kfd);
/* Events */
extern const struct kfd_event_interrupt_class event_interrupt_class_cik;
extern const struct kfd_event_interrupt_class event_interrupt_class_v9;
+extern const struct kfd_event_interrupt_class event_interrupt_class_v10;
extern const struct kfd_event_interrupt_class event_interrupt_class_v11;
extern const struct kfd_device_global_init_class device_global_init_class_cik;
@@ -1323,7 +1458,7 @@ int kfd_wait_on_events(struct kfd_process *p,
uint32_t *wait_result);
void kfd_signal_event_interrupt(u32 pasid, uint32_t partial_id,
uint32_t valid_id_bits);
-void kfd_signal_iommu_event(struct kfd_dev *dev,
+void kfd_signal_iommu_event(struct kfd_node *dev,
u32 pasid, unsigned long address,
bool is_write_requested, bool is_execute_requested);
void kfd_signal_hw_exception_event(u32 pasid);
@@ -1339,32 +1474,36 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p,
int kfd_get_num_events(struct kfd_process *p);
int kfd_event_destroy(struct kfd_process *p, uint32_t event_id);
-void kfd_signal_vm_fault_event(struct kfd_dev *dev, u32 pasid,
- struct kfd_vm_fault_info *info);
+void kfd_signal_vm_fault_event(struct kfd_node *dev, u32 pasid,
+ struct kfd_vm_fault_info *info,
+ struct kfd_hsa_memory_exception_data *data);
-void kfd_signal_reset_event(struct kfd_dev *dev);
+void kfd_signal_reset_event(struct kfd_node *dev);
-void kfd_signal_poison_consumed_event(struct kfd_dev *dev, u32 pasid);
+void kfd_signal_poison_consumed_event(struct kfd_node *dev, u32 pasid);
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, 2) ||
- (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 1) &&
- dev->adev->sdma.instance[0].fw_version >= 18) ||
+ return KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 3) ||
+ 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);
}
+int kfd_send_exception_to_runtime(struct kfd_process *p,
+ unsigned int queue_id,
+ uint64_t error_reason);
bool kfd_is_locked(void);
/* Compute profile */
-void kfd_inc_compute_active(struct kfd_dev *dev);
-void kfd_dec_compute_active(struct kfd_dev *dev);
+void kfd_inc_compute_active(struct kfd_node *dev);
+void kfd_dec_compute_active(struct kfd_node *dev);
/* Cgroup Support */
/* Check with device cgroup if @kfd device is accessible */
-static inline int kfd_devcgroup_check_permission(struct kfd_dev *kfd)
+static inline int kfd_devcgroup_check_permission(struct kfd_node *kfd)
{
#if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF)
struct drm_device *ddev = adev_to_drm(kfd->adev);
@@ -1377,6 +1516,11 @@ static inline int kfd_devcgroup_check_permission(struct kfd_dev *kfd)
#endif
}
+static inline bool kfd_is_first_node(struct kfd_node *node)
+{
+ return (node == node->kfd->nodes[0]);
+}
+
/* Debugfs */
#if defined(CONFIG_DEBUG_FS)
@@ -1389,7 +1533,7 @@ int dqm_debugfs_hqds(struct seq_file *m, void *data);
int kfd_debugfs_rls_by_device(struct seq_file *m, void *data);
int pm_debugfs_runlist(struct seq_file *m, void *data);
-int kfd_debugfs_hang_hws(struct kfd_dev *dev);
+int kfd_debugfs_hang_hws(struct kfd_node *dev);
int pm_debugfs_hang_hws(struct packet_manager *pm);
int dqm_debugfs_hang_hws(struct device_queue_manager *dqm);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 07a9eaf9b7d8..3d3611705d41 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -44,13 +44,14 @@ struct mm_struct;
#include "kfd_iommu.h"
#include "kfd_svm.h"
#include "kfd_smi_events.h"
+#include "kfd_debug.h"
/*
* List of struct kfd_process (field kfd_process).
* Unique/indexed by mm_struct*
*/
DEFINE_HASHTABLE(kfd_processes_table, KFD_PROCESS_TABLE_SIZE);
-static DEFINE_MUTEX(kfd_processes_mutex);
+DEFINE_MUTEX(kfd_processes_mutex);
DEFINE_SRCU(kfd_processes_srcu);
@@ -69,7 +70,6 @@ static struct kfd_process *find_process(const struct task_struct *thread,
bool ref);
static void kfd_process_ref_release(struct kref *ref);
static struct kfd_process *create_process(const struct task_struct *thread);
-static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep);
static void evict_process_worker(struct work_struct *work);
static void restore_process_worker(struct work_struct *work);
@@ -269,7 +269,7 @@ static int kfd_get_cu_occupancy(struct attribute *attr, char *buffer)
int cu_cnt;
int wave_cnt;
int max_waves_per_cu;
- struct kfd_dev *dev = NULL;
+ struct kfd_node *dev = NULL;
struct kfd_process *proc = NULL;
struct kfd_process_device *pdd = NULL;
@@ -290,7 +290,7 @@ static int kfd_get_cu_occupancy(struct attribute *attr, char *buffer)
wave_cnt = 0;
max_waves_per_cu = 0;
dev->kfd2kgd->get_cu_occupancy(dev->adev, proc->pasid, &wave_cnt,
- &max_waves_per_cu);
+ &max_waves_per_cu, 0);
/* Translate wave count to number of compute units */
cu_cnt = (wave_cnt + (max_waves_per_cu - 1)) / max_waves_per_cu;
@@ -691,7 +691,7 @@ void kfd_process_destroy_wq(void)
static void kfd_process_free_gpuvm(struct kgd_mem *mem,
struct kfd_process_device *pdd, void **kptr)
{
- struct kfd_dev *dev = pdd->dev;
+ struct kfd_node *dev = pdd->dev;
if (kptr && *kptr) {
amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(mem);
@@ -713,7 +713,7 @@ static int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd,
uint64_t gpu_va, uint32_t size,
uint32_t flags, struct kgd_mem **mem, void **kptr)
{
- struct kfd_dev *kdev = pdd->dev;
+ struct kfd_node *kdev = pdd->dev;
int err;
err = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(kdev->adev, gpu_va, size,
@@ -798,18 +798,19 @@ static void kfd_process_device_destroy_ib_mem(struct kfd_process_device *pdd)
kfd_process_free_gpuvm(qpd->ib_mem, pdd, &qpd->ib_kaddr);
}
-struct kfd_process *kfd_create_process(struct file *filep)
+struct kfd_process *kfd_create_process(struct task_struct *thread)
{
struct kfd_process *process;
- struct task_struct *thread = current;
int ret;
- if (!thread->mm)
+ if (!(thread->mm && mmget_not_zero(thread->mm)))
return ERR_PTR(-EINVAL);
/* Only the pthreads threading model is supported. */
- if (thread->group_leader->mm != thread->mm)
+ if (thread->group_leader->mm != thread->mm) {
+ mmput(thread->mm);
return ERR_PTR(-EINVAL);
+ }
/*
* take kfd processes mutex before starting of process creation
@@ -818,6 +819,12 @@ struct kfd_process *kfd_create_process(struct file *filep)
*/
mutex_lock(&kfd_processes_mutex);
+ if (kfd_is_locked()) {
+ mutex_unlock(&kfd_processes_mutex);
+ pr_debug("KFD is locked! Cannot create process");
+ return ERR_PTR(-EINVAL);
+ }
+
/* A prior open of /dev/kfd could have already created the process. */
process = find_process(thread, false);
if (process) {
@@ -827,10 +834,6 @@ struct kfd_process *kfd_create_process(struct file *filep)
if (IS_ERR(process))
goto out;
- ret = kfd_process_init_cwsr_apu(process, filep);
- if (ret)
- goto out_destroy;
-
if (!procfs.kobj)
goto out;
@@ -859,21 +862,16 @@ struct kfd_process *kfd_create_process(struct file *filep)
kfd_procfs_add_sysfs_stats(process);
kfd_procfs_add_sysfs_files(process);
kfd_procfs_add_sysfs_counters(process);
+
+ init_waitqueue_head(&process->wait_irq_drain);
}
out:
if (!IS_ERR(process))
kref_get(&process->ref);
mutex_unlock(&kfd_processes_mutex);
+ mmput(thread->mm);
return process;
-
-out_destroy:
- hash_del_rcu(&process->kfd_processes);
- mutex_unlock(&kfd_processes_mutex);
- synchronize_srcu(&kfd_processes_srcu);
- /* kfd_process_free_notifier will trigger the cleanup */
- mmu_notifier_put(&process->mmu_notifier);
- return ERR_PTR(ret);
}
struct kfd_process *kfd_get_process(const struct task_struct *thread)
@@ -982,7 +980,7 @@ static void kfd_process_device_free_bos(struct kfd_process_device *pdd)
static void kfd_process_kunmap_signal_bo(struct kfd_process *p)
{
struct kfd_process_device *pdd;
- struct kfd_dev *kdev;
+ struct kfd_node *kdev;
void *mem;
kdev = kfd_device_by_id(GET_GPU_ID(p->signal_handle));
@@ -1040,9 +1038,9 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
bitmap_free(pdd->qpd.doorbell_bitmap);
idr_destroy(&pdd->alloc_idr);
- kfd_free_process_doorbells(pdd->dev, pdd->doorbell_index);
+ kfd_free_process_doorbells(pdd->dev->kfd, pdd->doorbell_index);
- if (pdd->dev->shared_resources.enable_mes)
+ if (pdd->dev->kfd->shared_resources.enable_mes)
amdgpu_amdkfd_free_gtt_mem(pdd->dev->adev,
pdd->proc_ctx_bo);
/*
@@ -1169,11 +1167,40 @@ static void kfd_process_free_notifier(struct mmu_notifier *mn)
static void kfd_process_notifier_release_internal(struct kfd_process *p)
{
+ int i;
+
cancel_delayed_work_sync(&p->eviction_work);
cancel_delayed_work_sync(&p->restore_work);
+ for (i = 0; i < p->n_pdds; i++) {
+ struct kfd_process_device *pdd = p->pdds[i];
+
+ /* re-enable GFX OFF since runtime enable with ttmp setup disabled it. */
+ if (!kfd_dbg_is_rlc_restore_supported(pdd->dev) && p->runtime_info.ttmp_setup)
+ amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
+ }
+
/* Indicate to other users that MM is no longer valid */
p->mm = NULL;
+ kfd_dbg_trap_disable(p);
+
+ if (atomic_read(&p->debugged_process_count) > 0) {
+ struct kfd_process *target;
+ unsigned int temp;
+ int idx = srcu_read_lock(&kfd_processes_srcu);
+
+ hash_for_each_rcu(kfd_processes_table, temp, target, kfd_processes) {
+ if (target->debugger_process && target->debugger_process == p) {
+ mutex_lock_nested(&target->mutex, 1);
+ kfd_dbg_trap_disable(target);
+ mutex_unlock(&target->mutex);
+ if (atomic_read(&p->debugged_process_count) == 0)
+ break;
+ }
+ }
+
+ srcu_read_unlock(&kfd_processes_srcu, idx);
+ }
mmu_notifier_put(&p->mmu_notifier);
}
@@ -1253,16 +1280,19 @@ void kfd_cleanup_processes(void)
mmu_notifier_synchronize();
}
-static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep)
+int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep)
{
unsigned long offset;
int i;
+ if (p->has_cwsr)
+ return 0;
+
for (i = 0; i < p->n_pdds; i++) {
- struct kfd_dev *dev = p->pdds[i]->dev;
+ struct kfd_node *dev = p->pdds[i]->dev;
struct qcm_process_device *qpd = &p->pdds[i]->qpd;
- if (!dev->cwsr_enabled || qpd->cwsr_kaddr || qpd->cwsr_base)
+ if (!dev->kfd->cwsr_enabled || qpd->cwsr_kaddr || qpd->cwsr_base)
continue;
offset = KFD_MMAP_TYPE_RESERVED_MEM | KFD_MMAP_GPU_ID(dev->id);
@@ -1279,19 +1309,23 @@ static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep)
return err;
}
- memcpy(qpd->cwsr_kaddr, dev->cwsr_isa, dev->cwsr_isa_size);
+ memcpy(qpd->cwsr_kaddr, dev->kfd->cwsr_isa, dev->kfd->cwsr_isa_size);
+
+ kfd_process_set_trap_debug_flag(qpd, p->debug_trap_enabled);
qpd->tma_addr = qpd->tba_addr + KFD_CWSR_TMA_OFFSET;
pr_debug("set tba :0x%llx, tma:0x%llx, cwsr_kaddr:%p for pqm.\n",
qpd->tba_addr, qpd->tma_addr, qpd->cwsr_kaddr);
}
+ p->has_cwsr = true;
+
return 0;
}
static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd)
{
- struct kfd_dev *dev = pdd->dev;
+ struct kfd_node *dev = pdd->dev;
struct qcm_process_device *qpd = &pdd->qpd;
uint32_t flags = KFD_IOC_ALLOC_MEM_FLAGS_GTT
| KFD_IOC_ALLOC_MEM_FLAGS_NO_SUBSTITUTE
@@ -1300,7 +1334,7 @@ static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd)
void *kaddr;
int ret;
- if (!dev->cwsr_enabled || qpd->cwsr_kaddr || !qpd->cwsr_base)
+ if (!dev->kfd->cwsr_enabled || qpd->cwsr_kaddr || !qpd->cwsr_base)
return 0;
/* cwsr_base is only set for dGPU */
@@ -1313,7 +1347,10 @@ static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd)
qpd->cwsr_kaddr = kaddr;
qpd->tba_addr = qpd->cwsr_base;
- memcpy(qpd->cwsr_kaddr, dev->cwsr_isa, dev->cwsr_isa_size);
+ memcpy(qpd->cwsr_kaddr, dev->kfd->cwsr_isa, dev->kfd->cwsr_isa_size);
+
+ kfd_process_set_trap_debug_flag(&pdd->qpd,
+ pdd->process->debug_trap_enabled);
qpd->tma_addr = qpd->tba_addr + KFD_CWSR_TMA_OFFSET;
pr_debug("set tba :0x%llx, tma:0x%llx, cwsr_kaddr:%p for pqm.\n",
@@ -1324,10 +1361,10 @@ static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd)
static void kfd_process_device_destroy_cwsr_dgpu(struct kfd_process_device *pdd)
{
- struct kfd_dev *dev = pdd->dev;
+ struct kfd_node *dev = pdd->dev;
struct qcm_process_device *qpd = &pdd->qpd;
- if (!dev->cwsr_enabled || !qpd->cwsr_kaddr || !qpd->cwsr_base)
+ if (!dev->kfd->cwsr_enabled || !qpd->cwsr_kaddr || !qpd->cwsr_base)
return;
kfd_process_free_gpuvm(qpd->cwsr_mem, pdd, &qpd->cwsr_kaddr);
@@ -1371,7 +1408,7 @@ bool kfd_process_xnack_mode(struct kfd_process *p, bool supported)
* support retry.
*/
for (i = 0; i < p->n_pdds; i++) {
- struct kfd_dev *dev = p->pdds[i]->dev;
+ struct kfd_node *dev = p->pdds[i]->dev;
/* Only consider GFXv9 and higher GPUs. Older GPUs don't
* support the SVM APIs and don't need to be considered
@@ -1394,13 +1431,23 @@ bool kfd_process_xnack_mode(struct kfd_process *p, bool supported)
if (KFD_GC_VERSION(dev) >= IP_VERSION(10, 1, 1))
return false;
- if (dev->noretry)
+ if (dev->kfd->noretry)
return false;
}
return true;
}
+void kfd_process_set_trap_debug_flag(struct qcm_process_device *qpd,
+ bool enabled)
+{
+ if (qpd->cwsr_kaddr) {
+ uint64_t *tma =
+ (uint64_t *)(qpd->cwsr_kaddr + KFD_CWSR_TMA_OFFSET);
+ tma[2] = enabled;
+ }
+}
+
/*
* On return the kfd_process is fully operational and will be freed when the
* mm is released
@@ -1428,6 +1475,11 @@ static struct kfd_process *create_process(const struct task_struct *thread)
if (err)
goto err_event_init;
process->is_32bit_user_mode = in_compat_syscall();
+ process->debug_trap_enabled = false;
+ process->debugger_process = NULL;
+ process->exception_enable_mask = 0;
+ atomic_set(&process->debugged_process_count, 0);
+ sema_init(&process->runtime_enable_sema, 0);
process->pasid = kfd_pasid_alloc();
if (process->pasid == 0) {
@@ -1475,6 +1527,8 @@ static struct kfd_process *create_process(const struct task_struct *thread)
kfd_unref_process(process);
get_task_struct(process->lead_thread);
+ INIT_WORK(&process->debug_event_workarea, debug_event_write_work_handler);
+
return process;
err_register_notifier:
@@ -1528,7 +1582,7 @@ static int init_doorbell_bitmap(struct qcm_process_device *qpd,
return 0;
}
-struct kfd_process_device *kfd_get_process_device_data(struct kfd_dev *dev,
+struct kfd_process_device *kfd_get_process_device_data(struct kfd_node *dev,
struct kfd_process *p)
{
int i;
@@ -1540,7 +1594,7 @@ struct kfd_process_device *kfd_get_process_device_data(struct kfd_dev *dev,
return NULL;
}
-struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev,
+struct kfd_process_device *kfd_create_process_device_data(struct kfd_node *dev,
struct kfd_process *p)
{
struct kfd_process_device *pdd = NULL;
@@ -1552,7 +1606,7 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev,
if (!pdd)
return NULL;
- if (init_doorbell_bitmap(&pdd->qpd, dev)) {
+ if (init_doorbell_bitmap(&pdd->qpd, dev->kfd)) {
pr_err("Failed to init doorbell for process\n");
goto err_free_pdd;
}
@@ -1573,7 +1627,7 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev,
pdd->user_gpu_id = dev->id;
atomic64_set(&pdd->evict_duration_counter, 0);
- if (dev->shared_resources.enable_mes) {
+ if (dev->kfd->shared_resources.enable_mes) {
retval = amdgpu_amdkfd_alloc_gtt_mem(dev->adev,
AMDGPU_MES_PROC_CTX_SIZE,
&pdd->proc_ctx_bo,
@@ -1588,6 +1642,11 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev,
}
p->pdds[p->n_pdds++] = pdd;
+ if (kfd_dbg_is_per_vmid_supported(pdd->dev))
+ pdd->spi_dbg_override = pdd->dev->kfd2kgd->disable_debug_trap(
+ pdd->dev->adev,
+ false,
+ 0);
/* Init idr used for memory handle translation */
idr_init(&pdd->alloc_idr);
@@ -1619,7 +1678,7 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd,
struct amdgpu_fpriv *drv_priv;
struct amdgpu_vm *avm;
struct kfd_process *p;
- struct kfd_dev *dev;
+ struct kfd_node *dev;
int ret;
if (!drm_file)
@@ -1679,7 +1738,7 @@ err_reserve_ib_mem:
*
* Assumes that the process lock is held.
*/
-struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev,
+struct kfd_process_device *kfd_bind_process_to_device(struct kfd_node *dev,
struct kfd_process *p)
{
struct kfd_process_device *pdd;
@@ -1885,13 +1944,13 @@ int kfd_process_gpuidx_from_gpuid(struct kfd_process *p, uint32_t gpu_id)
}
int
-kfd_process_gpuid_from_adev(struct kfd_process *p, struct amdgpu_device *adev,
- uint32_t *gpuid, uint32_t *gpuidx)
+kfd_process_gpuid_from_node(struct kfd_process *p, struct kfd_node *node,
+ uint32_t *gpuid, uint32_t *gpuidx)
{
int i;
for (i = 0; i < p->n_pdds; i++)
- if (p->pdds[i] && p->pdds[i]->dev->adev == adev) {
+ if (p->pdds[i] && p->pdds[i]->dev == node) {
*gpuid = p->pdds[i]->user_gpu_id;
*gpuidx = i;
return 0;
@@ -1961,8 +2020,10 @@ static void restore_process_worker(struct work_struct *work)
*/
p->last_restore_timestamp = get_jiffies_64();
- ret = amdgpu_amdkfd_gpuvm_restore_process_bos(p->kgd_process_info,
- &p->ef);
+ /* VMs may not have been acquired yet during debugging. */
+ if (p->kgd_process_info)
+ ret = amdgpu_amdkfd_gpuvm_restore_process_bos(p->kgd_process_info,
+ &p->ef);
if (ret) {
pr_debug("Failed to restore BOs of pasid 0x%x, retry after %d ms\n",
p->pasid, PROCESS_BACK_OFF_TIME_MS);
@@ -1988,7 +2049,7 @@ void kfd_suspend_all_processes(void)
WARN(debug_evictions, "Evicting all processes");
hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) {
cancel_delayed_work_sync(&p->eviction_work);
- cancel_delayed_work_sync(&p->restore_work);
+ flush_delayed_work(&p->restore_work);
if (kfd_process_evict_queues(p, KFD_QUEUE_EVICTION_TRIGGER_SUSPEND))
pr_err("Failed to suspend process 0x%x\n", p->pasid);
@@ -2016,7 +2077,7 @@ int kfd_resume_all_processes(void)
return ret;
}
-int kfd_reserved_mem_mmap(struct kfd_dev *dev, struct kfd_process *process,
+int kfd_reserved_mem_mmap(struct kfd_node *dev, struct kfd_process *process,
struct vm_area_struct *vma)
{
struct kfd_process_device *pdd;
@@ -2051,7 +2112,9 @@ void kfd_flush_tlb(struct kfd_process_device *pdd, enum TLB_FLUSH_TYPE type)
{
struct amdgpu_vm *vm = drm_priv_to_vm(pdd->drm_priv);
uint64_t tlb_seq = amdgpu_vm_tlb_seq(vm);
- struct kfd_dev *dev = pdd->dev;
+ struct kfd_node *dev = pdd->dev;
+ uint32_t xcc_mask = dev->xcc_mask;
+ int xcc = 0;
/*
* It can be that we race and lose here, but that is extremely unlikely
@@ -2069,11 +2132,126 @@ void kfd_flush_tlb(struct kfd_process_device *pdd, enum TLB_FLUSH_TYPE type)
amdgpu_amdkfd_flush_gpu_tlb_vmid(dev->adev,
pdd->qpd.vmid);
} else {
- amdgpu_amdkfd_flush_gpu_tlb_pasid(dev->adev,
- pdd->process->pasid, type);
+ for_each_inst(xcc, xcc_mask)
+ amdgpu_amdkfd_flush_gpu_tlb_pasid(
+ dev->adev, pdd->process->pasid, type, xcc);
}
}
+/* assumes caller holds process lock. */
+int kfd_process_drain_interrupts(struct kfd_process_device *pdd)
+{
+ uint32_t irq_drain_fence[8];
+ int r = 0;
+
+ if (!KFD_IS_SOC15(pdd->dev))
+ return 0;
+
+ pdd->process->irq_drain_is_open = true;
+
+ memset(irq_drain_fence, 0, sizeof(irq_drain_fence));
+ irq_drain_fence[0] = (KFD_IRQ_FENCE_SOURCEID << 8) |
+ KFD_IRQ_FENCE_CLIENTID;
+ irq_drain_fence[3] = pdd->process->pasid;
+
+ /* ensure stale irqs scheduled KFD interrupts and send drain fence. */
+ if (amdgpu_amdkfd_send_close_event_drain_irq(pdd->dev->adev,
+ irq_drain_fence)) {
+ pdd->process->irq_drain_is_open = false;
+ return 0;
+ }
+
+ r = wait_event_interruptible(pdd->process->wait_irq_drain,
+ !READ_ONCE(pdd->process->irq_drain_is_open));
+ if (r)
+ pdd->process->irq_drain_is_open = false;
+
+ return r;
+}
+
+void kfd_process_close_interrupt_drain(unsigned int pasid)
+{
+ struct kfd_process *p;
+
+ p = kfd_lookup_process_by_pasid(pasid);
+
+ if (!p)
+ return;
+
+ WRITE_ONCE(p->irq_drain_is_open, false);
+ wake_up_all(&p->wait_irq_drain);
+ kfd_unref_process(p);
+}
+
+struct send_exception_work_handler_workarea {
+ struct work_struct work;
+ struct kfd_process *p;
+ unsigned int queue_id;
+ uint64_t error_reason;
+};
+
+static void send_exception_work_handler(struct work_struct *work)
+{
+ struct send_exception_work_handler_workarea *workarea;
+ struct kfd_process *p;
+ struct queue *q;
+ struct mm_struct *mm;
+ struct kfd_context_save_area_header __user *csa_header;
+ uint64_t __user *err_payload_ptr;
+ uint64_t cur_err;
+ uint32_t ev_id;
+
+ workarea = container_of(work,
+ struct send_exception_work_handler_workarea,
+ work);
+ p = workarea->p;
+
+ mm = get_task_mm(p->lead_thread);
+
+ if (!mm)
+ return;
+
+ kthread_use_mm(mm);
+
+ q = pqm_get_user_queue(&p->pqm, workarea->queue_id);
+
+ if (!q)
+ goto out;
+
+ csa_header = (void __user *)q->properties.ctx_save_restore_area_address;
+
+ get_user(err_payload_ptr, (uint64_t __user **)&csa_header->err_payload_addr);
+ get_user(cur_err, err_payload_ptr);
+ cur_err |= workarea->error_reason;
+ put_user(cur_err, err_payload_ptr);
+ get_user(ev_id, &csa_header->err_event_id);
+
+ kfd_set_event(p, ev_id);
+
+out:
+ kthread_unuse_mm(mm);
+ mmput(mm);
+}
+
+int kfd_send_exception_to_runtime(struct kfd_process *p,
+ unsigned int queue_id,
+ uint64_t error_reason)
+{
+ struct send_exception_work_handler_workarea worker;
+
+ INIT_WORK_ONSTACK(&worker.work, send_exception_work_handler);
+
+ worker.p = p;
+ worker.queue_id = queue_id;
+ worker.error_reason = error_reason;
+
+ schedule_work(&worker.work);
+ flush_work(&worker.work);
+ destroy_work_on_stack(&worker.work);
+
+ return 0;
+}
+
struct kfd_process_device *kfd_process_device_data_by_id(struct kfd_process *p, uint32_t gpu_id)
{
int i;
@@ -2133,4 +2311,3 @@ int kfd_debugfs_mqds_by_process(struct seq_file *m, void *data)
}
#endif
-
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
index 4236539d9f93..9ad1a2186a24 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
@@ -81,7 +81,7 @@ static int find_available_queue_slot(struct process_queue_manager *pqm,
void kfd_process_dequeue_from_device(struct kfd_process_device *pdd)
{
- struct kfd_dev *dev = pdd->dev;
+ struct kfd_node *dev = pdd->dev;
if (pdd->already_dequeued)
return;
@@ -93,7 +93,7 @@ void kfd_process_dequeue_from_device(struct kfd_process_device *pdd)
int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid,
void *gws)
{
- struct kfd_dev *dev = NULL;
+ struct kfd_node *dev = NULL;
struct process_queue_node *pqn;
struct kfd_process_device *pdd;
struct kgd_mem *mem = NULL;
@@ -178,7 +178,7 @@ void pqm_uninit(struct process_queue_manager *pqm)
}
static int init_user_queue(struct process_queue_manager *pqm,
- struct kfd_dev *dev, struct queue **q,
+ struct kfd_node *dev, struct queue **q,
struct queue_properties *q_properties,
struct file *f, struct amdgpu_bo *wptr_bo,
unsigned int qid)
@@ -187,6 +187,7 @@ static int init_user_queue(struct process_queue_manager *pqm,
/* Doorbell initialized in user space*/
q_properties->doorbell_ptr = NULL;
+ q_properties->exception_status = KFD_EC_MASK(EC_QUEUE_NEW);
/* let DQM handle it*/
q_properties->vmid = 0;
@@ -199,7 +200,7 @@ static int init_user_queue(struct process_queue_manager *pqm,
(*q)->device = dev;
(*q)->process = pqm->process;
- if (dev->shared_resources.enable_mes) {
+ if (dev->kfd->shared_resources.enable_mes) {
retval = amdgpu_amdkfd_alloc_gtt_mem(dev->adev,
AMDGPU_MES_GANG_CTX_SIZE,
&(*q)->gang_ctx_bo,
@@ -224,7 +225,7 @@ cleanup:
}
int pqm_create_queue(struct process_queue_manager *pqm,
- struct kfd_dev *dev,
+ struct kfd_node *dev,
struct file *f,
struct queue_properties *properties,
unsigned int *qid,
@@ -242,6 +243,13 @@ int pqm_create_queue(struct process_queue_manager *pqm,
enum kfd_queue_type type = properties->type;
unsigned int max_queues = 127; /* HWS limit */
+ /*
+ * On GFX 9.4.3, increase the number of queues that
+ * can be created to 255. No HWS limit on GFX 9.4.3.
+ */
+ if (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 3))
+ max_queues = 255;
+
q = NULL;
kq = NULL;
@@ -258,7 +266,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,
* Hence we also check the type as well
*/
if ((pdd->qpd.is_debug) || (type == KFD_QUEUE_TYPE_DIQ))
- max_queues = dev->device_info.max_no_of_hqd/2;
+ max_queues = dev->kfd->device_info.max_no_of_hqd/2;
if (pdd->qpd.queue_count >= max_queues)
return -ENOSPC;
@@ -330,6 +338,10 @@ int pqm_create_queue(struct process_queue_manager *pqm,
kq->queue->properties.queue_id = *qid;
pqn->kq = kq;
pqn->q = NULL;
+ retval = kfd_process_drain_interrupts(pdd);
+ if (retval)
+ break;
+
retval = dev->dqm->ops.create_kernel_queue(dev->dqm,
kq, &pdd->qpd);
break;
@@ -354,7 +366,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,
*/
*p_doorbell_offset_in_process =
(q->properties.doorbell_off * sizeof(uint32_t)) &
- (kfd_doorbell_process_slice(dev) - 1);
+ (kfd_doorbell_process_slice(dev->kfd) - 1);
pr_debug("PQM After DQM create queue\n");
@@ -387,7 +399,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid)
struct process_queue_node *pqn;
struct kfd_process_device *pdd;
struct device_queue_manager *dqm;
- struct kfd_dev *dev;
+ struct kfd_node *dev;
int retval;
dqm = NULL;
@@ -439,7 +451,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid)
pdd->qpd.num_gws = 0;
}
- if (dev->shared_resources.enable_mes) {
+ if (dev->kfd->shared_resources.enable_mes) {
amdgpu_amdkfd_free_gtt_mem(dev->adev,
pqn->q->gang_ctx_bo);
if (pqn->q->wptr_bo)
@@ -477,6 +489,7 @@ int pqm_update_queue_properties(struct process_queue_manager *pqm,
pqn->q->properties.queue_size = p->queue_size;
pqn->q->properties.queue_percent = p->queue_percent;
pqn->q->properties.priority = p->priority;
+ pqn->q->properties.pm4_target_xcc = p->pm4_target_xcc;
retval = pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm,
pqn->q, NULL);
@@ -498,8 +511,12 @@ int pqm_update_mqd(struct process_queue_manager *pqm,
return -EFAULT;
}
+ /* CUs are masked for debugger requirements so deny user mask */
+ if (pqn->q->properties.is_dbg_wa && minfo && minfo->cu_mask.ptr)
+ return -EBUSY;
+
/* ASICs that have WGPs must enforce pairwise enabled mask checks. */
- if (minfo && minfo->update_flag == UPDATE_FLAG_CU_MASK && minfo->cu_mask.ptr &&
+ if (minfo && minfo->cu_mask.ptr &&
KFD_GC_VERSION(pqn->q->device) >= IP_VERSION(10, 0, 0)) {
int i;
@@ -518,6 +535,9 @@ int pqm_update_mqd(struct process_queue_manager *pqm,
if (retval != 0)
return retval;
+ if (minfo && minfo->cu_mask.ptr)
+ pqn->q->properties.is_user_cu_masked = true;
+
return 0;
}
@@ -565,6 +585,46 @@ int pqm_get_wave_state(struct process_queue_manager *pqm,
save_area_used_size);
}
+int pqm_get_queue_snapshot(struct process_queue_manager *pqm,
+ uint64_t exception_clear_mask,
+ void __user *buf,
+ int *num_qss_entries,
+ uint32_t *entry_size)
+{
+ struct process_queue_node *pqn;
+ struct kfd_queue_snapshot_entry src;
+ uint32_t tmp_entry_size = *entry_size, tmp_qss_entries = *num_qss_entries;
+ int r = 0;
+
+ *num_qss_entries = 0;
+ if (!(*entry_size))
+ return -EINVAL;
+
+ *entry_size = min_t(size_t, *entry_size, sizeof(struct kfd_queue_snapshot_entry));
+ mutex_lock(&pqm->process->event_mutex);
+
+ memset(&src, 0, sizeof(src));
+
+ list_for_each_entry(pqn, &pqm->queues, process_queue_list) {
+ if (!pqn->q)
+ continue;
+
+ if (*num_qss_entries < tmp_qss_entries) {
+ set_queue_snapshot_entry(pqn->q, exception_clear_mask, &src);
+
+ if (copy_to_user(buf, &src, *entry_size)) {
+ r = -EFAULT;
+ break;
+ }
+ buf += tmp_entry_size;
+ }
+ *num_qss_entries += 1;
+ }
+
+ mutex_unlock(&pqm->process->event_mutex);
+ return r;
+}
+
static int get_queue_data_sizes(struct kfd_process_device *pdd,
struct queue *q,
uint32_t *mqd_size,
@@ -859,7 +919,7 @@ int kfd_criu_restore_queue(struct kfd_process *p,
}
if (!pdd->doorbell_index &&
- kfd_alloc_process_doorbells(pdd->dev, &pdd->doorbell_index) < 0) {
+ kfd_alloc_process_doorbells(pdd->dev->kfd, &pdd->doorbell_index) < 0) {
ret = -ENOMEM;
goto exit;
}
@@ -927,7 +987,9 @@ int pqm_debugfs_mqds(struct seq_file *m, void *data)
struct queue *q;
enum KFD_MQD_TYPE mqd_type;
struct mqd_manager *mqd_mgr;
- int r = 0;
+ int r = 0, xcc, num_xccs = 1;
+ void *mqd;
+ uint64_t size = 0;
list_for_each_entry(pqn, &pqm->queues, process_queue_list) {
if (pqn->q) {
@@ -943,6 +1005,7 @@ int pqm_debugfs_mqds(struct seq_file *m, void *data)
seq_printf(m, " Compute queue on device %x\n",
q->device->id);
mqd_type = KFD_MQD_TYPE_CP;
+ num_xccs = NUM_XCC(q->device->xcc_mask);
break;
default:
seq_printf(m,
@@ -951,6 +1014,8 @@ int pqm_debugfs_mqds(struct seq_file *m, void *data)
continue;
}
mqd_mgr = q->device->dqm->mqd_mgrs[mqd_type];
+ size = mqd_mgr->mqd_stride(mqd_mgr,
+ &q->properties);
} else if (pqn->kq) {
q = pqn->kq->queue;
mqd_mgr = pqn->kq->mqd_mgr;
@@ -972,9 +1037,12 @@ int pqm_debugfs_mqds(struct seq_file *m, void *data)
continue;
}
- r = mqd_mgr->debugfs_show_mqd(m, q->mqd);
- if (r != 0)
- break;
+ for (xcc = 0; xcc < num_xccs; xcc++) {
+ mqd = q->mqd + size * xcc;
+ r = mqd_mgr->debugfs_show_mqd(m, mqd);
+ if (r != 0)
+ break;
+ }
}
return r;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
index 0472b56de245..d9953c2b2661 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
@@ -36,7 +36,7 @@ struct kfd_smi_client {
wait_queue_head_t wait_queue;
/* events enabled */
uint64_t events;
- struct kfd_dev *dev;
+ struct kfd_node *dev;
spinlock_t lock;
struct rcu_head rcu;
pid_t pid;
@@ -149,7 +149,7 @@ static void kfd_smi_ev_client_free(struct rcu_head *p)
static int kfd_smi_ev_release(struct inode *inode, struct file *filep)
{
struct kfd_smi_client *client = filep->private_data;
- struct kfd_dev *dev = client->dev;
+ struct kfd_node *dev = client->dev;
spin_lock(&dev->smi_lock);
list_del_rcu(&client->list);
@@ -171,7 +171,7 @@ static bool kfd_smi_ev_enabled(pid_t pid, struct kfd_smi_client *client,
return events & KFD_SMI_EVENT_MASK_FROM_INDEX(event);
}
-static void add_event_to_kfifo(pid_t pid, struct kfd_dev *dev,
+static void add_event_to_kfifo(pid_t pid, struct kfd_node *dev,
unsigned int smi_event, char *event_msg, int len)
{
struct kfd_smi_client *client;
@@ -196,7 +196,7 @@ static void add_event_to_kfifo(pid_t pid, struct kfd_dev *dev,
}
__printf(4, 5)
-static void kfd_smi_event_add(pid_t pid, struct kfd_dev *dev,
+static void kfd_smi_event_add(pid_t pid, struct kfd_node *dev,
unsigned int event, char *fmt, ...)
{
char fifo_in[KFD_SMI_EVENT_MSG_SIZE];
@@ -215,7 +215,7 @@ static void kfd_smi_event_add(pid_t pid, struct kfd_dev *dev,
add_event_to_kfifo(pid, dev, event, fifo_in, len);
}
-void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset)
+void kfd_smi_event_update_gpu_reset(struct kfd_node *dev, bool post_reset)
{
unsigned int event;
@@ -228,7 +228,7 @@ void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset)
kfd_smi_event_add(0, dev, event, "%x\n", dev->reset_seq_num);
}
-void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev,
+void kfd_smi_event_update_thermal_throttling(struct kfd_node *dev,
uint64_t throttle_bitmask)
{
kfd_smi_event_add(0, dev, KFD_SMI_EVENT_THERMAL_THROTTLE, "%llx:%llx\n",
@@ -236,7 +236,7 @@ void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev,
amdgpu_dpm_get_thermal_throttling_counter(dev->adev));
}
-void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid)
+void kfd_smi_event_update_vmfault(struct kfd_node *dev, uint16_t pasid)
{
struct amdgpu_task_info task_info;
@@ -250,58 +250,58 @@ void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid)
task_info.pid, task_info.task_name);
}
-void kfd_smi_event_page_fault_start(struct kfd_dev *dev, pid_t pid,
+void kfd_smi_event_page_fault_start(struct kfd_node *node, pid_t pid,
unsigned long address, bool write_fault,
ktime_t ts)
{
- kfd_smi_event_add(pid, dev, KFD_SMI_EVENT_PAGE_FAULT_START,
+ kfd_smi_event_add(pid, node, KFD_SMI_EVENT_PAGE_FAULT_START,
"%lld -%d @%lx(%x) %c\n", ktime_to_ns(ts), pid,
- address, dev->id, write_fault ? 'W' : 'R');
+ address, node->id, write_fault ? 'W' : 'R');
}
-void kfd_smi_event_page_fault_end(struct kfd_dev *dev, pid_t pid,
+void kfd_smi_event_page_fault_end(struct kfd_node *node, pid_t pid,
unsigned long address, bool migration)
{
- kfd_smi_event_add(pid, dev, KFD_SMI_EVENT_PAGE_FAULT_END,
+ kfd_smi_event_add(pid, node, KFD_SMI_EVENT_PAGE_FAULT_END,
"%lld -%d @%lx(%x) %c\n", ktime_get_boottime_ns(),
- pid, address, dev->id, migration ? 'M' : 'U');
+ pid, address, node->id, migration ? 'M' : 'U');
}
-void kfd_smi_event_migration_start(struct kfd_dev *dev, pid_t pid,
+void kfd_smi_event_migration_start(struct kfd_node *node, pid_t pid,
unsigned long start, unsigned long end,
uint32_t from, uint32_t to,
uint32_t prefetch_loc, uint32_t preferred_loc,
uint32_t trigger)
{
- kfd_smi_event_add(pid, dev, KFD_SMI_EVENT_MIGRATE_START,
+ kfd_smi_event_add(pid, node, KFD_SMI_EVENT_MIGRATE_START,
"%lld -%d @%lx(%lx) %x->%x %x:%x %d\n",
ktime_get_boottime_ns(), pid, start, end - start,
from, to, prefetch_loc, preferred_loc, trigger);
}
-void kfd_smi_event_migration_end(struct kfd_dev *dev, pid_t pid,
+void kfd_smi_event_migration_end(struct kfd_node *node, pid_t pid,
unsigned long start, unsigned long end,
uint32_t from, uint32_t to, uint32_t trigger)
{
- kfd_smi_event_add(pid, dev, KFD_SMI_EVENT_MIGRATE_END,
+ kfd_smi_event_add(pid, node, KFD_SMI_EVENT_MIGRATE_END,
"%lld -%d @%lx(%lx) %x->%x %d\n",
ktime_get_boottime_ns(), pid, start, end - start,
from, to, trigger);
}
-void kfd_smi_event_queue_eviction(struct kfd_dev *dev, pid_t pid,
+void kfd_smi_event_queue_eviction(struct kfd_node *node, pid_t pid,
uint32_t trigger)
{
- kfd_smi_event_add(pid, dev, KFD_SMI_EVENT_QUEUE_EVICTION,
+ kfd_smi_event_add(pid, node, KFD_SMI_EVENT_QUEUE_EVICTION,
"%lld -%d %x %d\n", ktime_get_boottime_ns(), pid,
- dev->id, trigger);
+ node->id, trigger);
}
-void kfd_smi_event_queue_restore(struct kfd_dev *dev, pid_t pid)
+void kfd_smi_event_queue_restore(struct kfd_node *node, pid_t pid)
{
- kfd_smi_event_add(pid, dev, KFD_SMI_EVENT_QUEUE_RESTORE,
+ kfd_smi_event_add(pid, node, KFD_SMI_EVENT_QUEUE_RESTORE,
"%lld -%d %x\n", ktime_get_boottime_ns(), pid,
- dev->id);
+ node->id);
}
void kfd_smi_event_queue_restore_rescheduled(struct mm_struct *mm)
@@ -324,16 +324,16 @@ void kfd_smi_event_queue_restore_rescheduled(struct mm_struct *mm)
kfd_unref_process(p);
}
-void kfd_smi_event_unmap_from_gpu(struct kfd_dev *dev, pid_t pid,
+void kfd_smi_event_unmap_from_gpu(struct kfd_node *node, pid_t pid,
unsigned long address, unsigned long last,
uint32_t trigger)
{
- kfd_smi_event_add(pid, dev, KFD_SMI_EVENT_UNMAP_FROM_GPU,
+ kfd_smi_event_add(pid, node, KFD_SMI_EVENT_UNMAP_FROM_GPU,
"%lld -%d @%lx(%lx) %x %d\n", ktime_get_boottime_ns(),
- pid, address, last - address + 1, dev->id, trigger);
+ pid, address, last - address + 1, node->id, trigger);
}
-int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd)
+int kfd_smi_event_open(struct kfd_node *dev, uint32_t *fd)
{
struct kfd_smi_client *client;
int ret;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h
index 76fe4e0ec2d2..fa95c2dfd587 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h
@@ -24,29 +24,29 @@
#ifndef KFD_SMI_EVENTS_H_INCLUDED
#define KFD_SMI_EVENTS_H_INCLUDED
-int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd);
-void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid);
-void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev,
+int kfd_smi_event_open(struct kfd_node *dev, uint32_t *fd);
+void kfd_smi_event_update_vmfault(struct kfd_node *dev, uint16_t pasid);
+void kfd_smi_event_update_thermal_throttling(struct kfd_node *dev,
uint64_t throttle_bitmask);
-void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset);
-void kfd_smi_event_page_fault_start(struct kfd_dev *dev, pid_t pid,
+void kfd_smi_event_update_gpu_reset(struct kfd_node *dev, bool post_reset);
+void kfd_smi_event_page_fault_start(struct kfd_node *node, pid_t pid,
unsigned long address, bool write_fault,
ktime_t ts);
-void kfd_smi_event_page_fault_end(struct kfd_dev *dev, pid_t pid,
+void kfd_smi_event_page_fault_end(struct kfd_node *node, pid_t pid,
unsigned long address, bool migration);
-void kfd_smi_event_migration_start(struct kfd_dev *dev, pid_t pid,
+void kfd_smi_event_migration_start(struct kfd_node *node, pid_t pid,
unsigned long start, unsigned long end,
uint32_t from, uint32_t to,
uint32_t prefetch_loc, uint32_t preferred_loc,
uint32_t trigger);
-void kfd_smi_event_migration_end(struct kfd_dev *dev, pid_t pid,
+void kfd_smi_event_migration_end(struct kfd_node *node, pid_t pid,
unsigned long start, unsigned long end,
uint32_t from, uint32_t to, uint32_t trigger);
-void kfd_smi_event_queue_eviction(struct kfd_dev *dev, pid_t pid,
+void kfd_smi_event_queue_eviction(struct kfd_node *node, pid_t pid,
uint32_t trigger);
-void kfd_smi_event_queue_restore(struct kfd_dev *dev, pid_t pid);
+void kfd_smi_event_queue_restore(struct kfd_node *node, pid_t pid);
void kfd_smi_event_queue_restore_rescheduled(struct mm_struct *mm);
-void kfd_smi_event_unmap_from_gpu(struct kfd_dev *dev, pid_t pid,
+void kfd_smi_event_unmap_from_gpu(struct kfd_node *node, pid_t pid,
unsigned long address, unsigned long last,
uint32_t trigger);
#endif
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 96a138a39515..5ff1a5a89d96 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -170,12 +170,11 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
page = hmm_pfn_to_page(hmm_pfns[i]);
if (is_zone_device_page(page)) {
- struct amdgpu_device *bo_adev =
- amdgpu_ttm_adev(prange->svm_bo->bo->tbo.bdev);
+ struct amdgpu_device *bo_adev = prange->svm_bo->node->adev;
addr[i] = (hmm_pfns[i] << PAGE_SHIFT) +
bo_adev->vm_manager.vram_base_offset -
- bo_adev->kfd.dev->pgmap.range.start;
+ bo_adev->kfd.pgmap.range.start;
addr[i] |= SVM_RANGE_VRAM_DOMAIN;
pr_debug_ratelimited("vram address: 0x%llx\n", addr[i]);
continue;
@@ -281,7 +280,7 @@ static void svm_range_free(struct svm_range *prange, bool update_mem_usage)
if (update_mem_usage && !p->xnack_enabled) {
pr_debug("unreserve prange 0x%p size: 0x%llx\n", prange, size);
amdgpu_amdkfd_unreserve_mem_limit(NULL, size,
- KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
+ KFD_IOC_ALLOC_MEM_FLAGS_USERPTR, 0);
}
mutex_destroy(&prange->lock);
mutex_destroy(&prange->migrate_mutex);
@@ -314,7 +313,7 @@ svm_range *svm_range_new(struct svm_range_list *svms, uint64_t start,
p = container_of(svms, struct kfd_process, svms);
if (!p->xnack_enabled && update_mem_usage &&
amdgpu_amdkfd_reserve_mem_limit(NULL, size << PAGE_SHIFT,
- KFD_IOC_ALLOC_MEM_FLAGS_USERPTR)) {
+ KFD_IOC_ALLOC_MEM_FLAGS_USERPTR, 0)) {
pr_info("SVM mapping failed, exceeds resident system memory limit\n");
kfree(prange);
return NULL;
@@ -424,10 +423,8 @@ static void svm_range_bo_unref(struct svm_range_bo *svm_bo)
}
static bool
-svm_range_validate_svm_bo(struct amdgpu_device *adev, struct svm_range *prange)
+svm_range_validate_svm_bo(struct kfd_node *node, struct svm_range *prange)
{
- struct amdgpu_device *bo_adev;
-
mutex_lock(&prange->lock);
if (!prange->svm_bo) {
mutex_unlock(&prange->lock);
@@ -440,12 +437,11 @@ svm_range_validate_svm_bo(struct amdgpu_device *adev, struct svm_range *prange)
}
if (svm_bo_ref_unless_zero(prange->svm_bo)) {
/*
- * Migrate from GPU to GPU, remove range from source bo_adev
- * svm_bo range list, and return false to allocate svm_bo from
- * destination adev.
+ * Migrate from GPU to GPU, remove range from source svm_bo->node
+ * range list, and return false to allocate svm_bo from destination
+ * node.
*/
- bo_adev = amdgpu_ttm_adev(prange->svm_bo->bo->tbo.bdev);
- if (bo_adev != adev) {
+ if (prange->svm_bo->node != node) {
mutex_unlock(&prange->lock);
spin_lock(&prange->svm_bo->list_lock);
@@ -513,7 +509,7 @@ static struct svm_range_bo *svm_range_bo_new(void)
}
int
-svm_range_vram_node_new(struct amdgpu_device *adev, struct svm_range *prange,
+svm_range_vram_node_new(struct kfd_node *node, struct svm_range *prange,
bool clear)
{
struct amdgpu_bo_param bp;
@@ -528,7 +524,7 @@ svm_range_vram_node_new(struct amdgpu_device *adev, struct svm_range *prange,
pr_debug("pasid: %x svms 0x%p [0x%lx 0x%lx]\n", p->pasid, prange->svms,
prange->start, prange->last);
- if (svm_range_validate_svm_bo(adev, prange))
+ if (svm_range_validate_svm_bo(node, prange))
return 0;
svm_bo = svm_range_bo_new();
@@ -542,6 +538,7 @@ svm_range_vram_node_new(struct amdgpu_device *adev, struct svm_range *prange,
kfree(svm_bo);
return -ESRCH;
}
+ svm_bo->node = node;
svm_bo->eviction_fence =
amdgpu_amdkfd_fence_create(dma_fence_context_alloc(1),
mm,
@@ -558,13 +555,20 @@ svm_range_vram_node_new(struct amdgpu_device *adev, struct svm_range *prange,
bp.flags |= AMDGPU_GEM_CREATE_DISCARDABLE;
bp.type = ttm_bo_type_device;
bp.resv = NULL;
+ if (node->xcp)
+ bp.xcp_id_plus1 = node->xcp->id + 1;
- r = amdgpu_bo_create_user(adev, &bp, &ubo);
+ r = amdgpu_bo_create_user(node->adev, &bp, &ubo);
if (r) {
pr_debug("failed %d to create bo\n", r);
goto create_bo_failed;
}
bo = &ubo->bo;
+
+ pr_debug("alloc bo at offset 0x%lx size 0x%lx on partition %d\n",
+ bo->tbo.resource->start << PAGE_SHIFT, bp.size,
+ bp.xcp_id_plus1 - 1);
+
r = amdgpu_bo_reserve(bo, true);
if (r) {
pr_debug("failed %d to reserve bo\n", r);
@@ -617,45 +621,30 @@ void svm_range_vram_node_free(struct svm_range *prange)
prange->ttm_res = NULL;
}
-struct amdgpu_device *
-svm_range_get_adev_by_id(struct svm_range *prange, uint32_t gpu_id)
+struct kfd_node *
+svm_range_get_node_by_id(struct svm_range *prange, uint32_t gpu_id)
{
- struct kfd_process_device *pdd;
struct kfd_process *p;
- int32_t gpu_idx;
+ struct kfd_process_device *pdd;
p = container_of(prange->svms, struct kfd_process, svms);
-
- gpu_idx = kfd_process_gpuidx_from_gpuid(p, gpu_id);
- if (gpu_idx < 0) {
- pr_debug("failed to get device by id 0x%x\n", gpu_id);
- return NULL;
- }
- pdd = kfd_process_device_from_gpuidx(p, gpu_idx);
+ pdd = kfd_process_device_data_by_id(p, gpu_id);
if (!pdd) {
- pr_debug("failed to get device by idx 0x%x\n", gpu_idx);
+ pr_debug("failed to get kfd process device by id 0x%x\n", gpu_id);
return NULL;
}
- return pdd->dev->adev;
+ return pdd->dev;
}
struct kfd_process_device *
-svm_range_get_pdd_by_adev(struct svm_range *prange, struct amdgpu_device *adev)
+svm_range_get_pdd_by_node(struct svm_range *prange, struct kfd_node *node)
{
struct kfd_process *p;
- int32_t gpu_idx, gpuid;
- int r;
p = container_of(prange->svms, struct kfd_process, svms);
- r = kfd_process_gpuid_from_adev(p, adev, &gpuid, &gpu_idx);
- if (r) {
- pr_debug("failed to get device id by adev %p\n", adev);
- return NULL;
- }
-
- return kfd_process_device_from_gpuidx(p, gpu_idx);
+ return kfd_get_process_device_data(node, p);
}
static int svm_range_bo_validate(void *param, struct amdgpu_bo *bo)
@@ -735,7 +724,9 @@ svm_range_apply_attrs(struct kfd_process *p, struct svm_range *prange,
case KFD_IOCTL_SVM_ATTR_ACCESS:
case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE:
case KFD_IOCTL_SVM_ATTR_NO_ACCESS:
- *update_mapping = true;
+ if (!p->xnack_enabled)
+ *update_mapping = true;
+
gpuidx = kfd_process_gpuidx_from_gpuid(p,
attrs[i].value);
if (attrs[i].type == KFD_IOCTL_SVM_ATTR_NO_ACCESS) {
@@ -818,7 +809,7 @@ svm_range_is_same_attrs(struct kfd_process *p, struct svm_range *prange,
}
}
- return true;
+ return !prange->is_error_flag;
}
/**
@@ -1146,31 +1137,39 @@ svm_range_split_by_granularity(struct kfd_process *p, struct mm_struct *mm,
}
return 0;
}
+static bool
+svm_nodes_in_same_hive(struct kfd_node *node_a, struct kfd_node *node_b)
+{
+ return (node_a->adev == node_b->adev ||
+ amdgpu_xgmi_same_hive(node_a->adev, node_b->adev));
+}
static uint64_t
-svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange,
- int domain)
+svm_range_get_pte_flags(struct kfd_node *node,
+ struct svm_range *prange, int domain)
{
- struct amdgpu_device *bo_adev;
+ struct kfd_node *bo_node;
uint32_t flags = prange->flags;
uint32_t mapping_flags = 0;
uint64_t pte_flags;
bool snoop = (domain != SVM_RANGE_VRAM_DOMAIN);
bool coherent = flags & KFD_IOCTL_SVM_FLAG_COHERENT;
+ bool uncached = false; /*flags & KFD_IOCTL_SVM_FLAG_UNCACHED;*/
+ unsigned int mtype_local;
if (domain == SVM_RANGE_VRAM_DOMAIN)
- bo_adev = amdgpu_ttm_adev(prange->svm_bo->bo->tbo.bdev);
+ bo_node = prange->svm_bo->node;
- switch (KFD_GC_VERSION(adev->kfd.dev)) {
+ switch (node->adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 4, 1):
if (domain == SVM_RANGE_VRAM_DOMAIN) {
- if (bo_adev == adev) {
+ if (bo_node == node) {
mapping_flags |= coherent ?
AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
} else {
mapping_flags |= coherent ?
AMDGPU_VM_MTYPE_UC : AMDGPU_VM_MTYPE_NC;
- if (amdgpu_xgmi_same_hive(adev, bo_adev))
+ if (svm_nodes_in_same_hive(node, bo_node))
snoop = true;
}
} else {
@@ -1180,15 +1179,15 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange,
break;
case IP_VERSION(9, 4, 2):
if (domain == SVM_RANGE_VRAM_DOMAIN) {
- if (bo_adev == adev) {
+ if (bo_node == node) {
mapping_flags |= coherent ?
AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
- if (adev->gmc.xgmi.connected_to_cpu)
+ if (node->adev->gmc.xgmi.connected_to_cpu)
snoop = true;
} else {
mapping_flags |= coherent ?
AMDGPU_VM_MTYPE_UC : AMDGPU_VM_MTYPE_NC;
- if (amdgpu_xgmi_same_hive(adev, bo_adev))
+ if (svm_nodes_in_same_hive(node, bo_node))
snoop = true;
}
} else {
@@ -1196,6 +1195,37 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange,
AMDGPU_VM_MTYPE_UC : AMDGPU_VM_MTYPE_NC;
}
break;
+ case IP_VERSION(9, 4, 3):
+ mtype_local = amdgpu_mtype_local == 1 ? AMDGPU_VM_MTYPE_NC :
+ (amdgpu_mtype_local == 2 ? AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW);
+ snoop = true;
+ if (uncached) {
+ mapping_flags |= AMDGPU_VM_MTYPE_UC;
+ } else if (domain == SVM_RANGE_VRAM_DOMAIN) {
+ /* local HBM region close to partition */
+ if (bo_node->adev == node->adev &&
+ (!bo_node->xcp || !node->xcp || bo_node->xcp->mem_id == node->xcp->mem_id))
+ mapping_flags |= mtype_local;
+ /* local HBM region far from partition or remote XGMI GPU */
+ else if (svm_nodes_in_same_hive(bo_node, node))
+ mapping_flags |= AMDGPU_VM_MTYPE_NC;
+ /* PCIe P2P */
+ else
+ mapping_flags |= AMDGPU_VM_MTYPE_UC;
+ /* system memory accessed by the APU */
+ } else if (node->adev->flags & AMD_IS_APU) {
+ /* On NUMA systems, locality is determined per-page
+ * in amdgpu_gmc_override_vm_pte_flags
+ */
+ if (num_possible_nodes() <= 1)
+ mapping_flags |= mtype_local;
+ else
+ mapping_flags |= AMDGPU_VM_MTYPE_NC;
+ /* system memory accessed by the dGPU */
+ } else {
+ mapping_flags |= AMDGPU_VM_MTYPE_UC;
+ }
+ break;
default:
mapping_flags |= coherent ?
AMDGPU_VM_MTYPE_UC : AMDGPU_VM_MTYPE_NC;
@@ -1212,7 +1242,7 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange,
pte_flags |= (domain == SVM_RANGE_VRAM_DOMAIN) ? 0 : AMDGPU_PTE_SYSTEM;
pte_flags |= snoop ? AMDGPU_PTE_SNOOPED : 0;
- pte_flags |= amdgpu_gem_va_map_flags(adev, mapping_flags);
+ pte_flags |= amdgpu_gem_va_map_flags(node->adev, mapping_flags);
return pte_flags;
}
@@ -1319,7 +1349,7 @@ svm_range_map_to_gpu(struct kfd_process_device *pdd, struct svm_range *prange,
pr_debug("Mapping range [0x%lx 0x%llx] on domain: %s\n",
last_start, prange->start + i, last_domain ? "GPU" : "CPU");
- pte_flags = svm_range_get_pte_flags(adev, prange, last_domain);
+ pte_flags = svm_range_get_pte_flags(pdd->dev, prange, last_domain);
if (readonly)
pte_flags &= ~AMDGPU_PTE_WRITEABLE;
@@ -1328,6 +1358,10 @@ svm_range_map_to_gpu(struct kfd_process_device *pdd, struct svm_range *prange,
(last_domain == SVM_RANGE_VRAM_DOMAIN) ? 1 : 0,
pte_flags);
+ /* For dGPU mode, we use same vm_manager to allocate VRAM for
+ * different memory partition based on fpfn/lpfn, we should use
+ * same vm_manager.vram_base_offset regardless memory partition.
+ */
r = amdgpu_vm_update_range(adev, vm, false, false, flush_tlb, NULL,
last_start, prange->start + i,
pte_flags,
@@ -1365,16 +1399,14 @@ svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset,
unsigned long *bitmap, bool wait, bool flush_tlb)
{
struct kfd_process_device *pdd;
- struct amdgpu_device *bo_adev;
+ struct amdgpu_device *bo_adev = NULL;
struct kfd_process *p;
struct dma_fence *fence = NULL;
uint32_t gpuidx;
int r = 0;
if (prange->svm_bo && prange->ttm_res)
- bo_adev = amdgpu_ttm_adev(prange->svm_bo->bo->tbo.bdev);
- else
- bo_adev = NULL;
+ bo_adev = prange->svm_bo->node->adev;
p = container_of(prange->svms, struct kfd_process, svms);
for_each_set_bit(gpuidx, bitmap, MAX_GPU_INSTANCE) {
@@ -1522,48 +1554,54 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
struct svm_range *prange, int32_t gpuidx,
bool intr, bool wait, bool flush_tlb)
{
- struct svm_validate_context ctx;
+ struct svm_validate_context *ctx;
unsigned long start, end, addr;
struct kfd_process *p;
void *owner;
int32_t idx;
int r = 0;
- ctx.process = container_of(prange->svms, struct kfd_process, svms);
- ctx.prange = prange;
- ctx.intr = intr;
+ ctx = kzalloc(sizeof(struct svm_validate_context), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ ctx->process = container_of(prange->svms, struct kfd_process, svms);
+ ctx->prange = prange;
+ ctx->intr = intr;
if (gpuidx < MAX_GPU_INSTANCE) {
- bitmap_zero(ctx.bitmap, MAX_GPU_INSTANCE);
- bitmap_set(ctx.bitmap, gpuidx, 1);
- } else if (ctx.process->xnack_enabled) {
- bitmap_copy(ctx.bitmap, prange->bitmap_aip, MAX_GPU_INSTANCE);
+ bitmap_zero(ctx->bitmap, MAX_GPU_INSTANCE);
+ bitmap_set(ctx->bitmap, gpuidx, 1);
+ } else if (ctx->process->xnack_enabled) {
+ bitmap_copy(ctx->bitmap, prange->bitmap_aip, MAX_GPU_INSTANCE);
/* If prefetch range to GPU, or GPU retry fault migrate range to
* GPU, which has ACCESS attribute to the range, create mapping
* on that GPU.
*/
if (prange->actual_loc) {
- gpuidx = kfd_process_gpuidx_from_gpuid(ctx.process,
+ gpuidx = kfd_process_gpuidx_from_gpuid(ctx->process,
prange->actual_loc);
if (gpuidx < 0) {
WARN_ONCE(1, "failed get device by id 0x%x\n",
prange->actual_loc);
- return -EINVAL;
+ r = -EINVAL;
+ goto free_ctx;
}
if (test_bit(gpuidx, prange->bitmap_access))
- bitmap_set(ctx.bitmap, gpuidx, 1);
+ bitmap_set(ctx->bitmap, gpuidx, 1);
}
} else {
- bitmap_or(ctx.bitmap, prange->bitmap_access,
+ bitmap_or(ctx->bitmap, prange->bitmap_access,
prange->bitmap_aip, MAX_GPU_INSTANCE);
}
- if (bitmap_empty(ctx.bitmap, MAX_GPU_INSTANCE)) {
- if (!prange->mapped_to_gpu)
- return 0;
+ if (bitmap_empty(ctx->bitmap, MAX_GPU_INSTANCE)) {
+ if (!prange->mapped_to_gpu) {
+ r = 0;
+ goto free_ctx;
+ }
- bitmap_copy(ctx.bitmap, prange->bitmap_access, MAX_GPU_INSTANCE);
+ bitmap_copy(ctx->bitmap, prange->bitmap_access, MAX_GPU_INSTANCE);
}
if (prange->actual_loc && !prange->ttm_res) {
@@ -1571,15 +1609,16 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
* svm_migrate_ram_to_vram after allocating a BO.
*/
WARN_ONCE(1, "VRAM BO missing during validation\n");
- return -EINVAL;
+ r = -EINVAL;
+ goto free_ctx;
}
- svm_range_reserve_bos(&ctx);
+ svm_range_reserve_bos(ctx);
p = container_of(prange->svms, struct kfd_process, svms);
- owner = kfd_svm_page_owner(p, find_first_bit(ctx.bitmap,
+ owner = kfd_svm_page_owner(p, find_first_bit(ctx->bitmap,
MAX_GPU_INSTANCE));
- for_each_set_bit(idx, ctx.bitmap, MAX_GPU_INSTANCE) {
+ for_each_set_bit(idx, ctx->bitmap, MAX_GPU_INSTANCE) {
if (kfd_svm_page_owner(p, idx) != owner) {
owner = NULL;
break;
@@ -1616,7 +1655,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
}
offset = (addr - start) >> PAGE_SHIFT;
- r = svm_range_dma_map(prange, ctx.bitmap, offset, npages,
+ r = svm_range_dma_map(prange, ctx->bitmap, offset, npages,
hmm_range->hmm_pfns);
if (r) {
pr_debug("failed %d to dma map range\n", r);
@@ -1636,7 +1675,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
}
r = svm_range_map_to_gpus(prange, offset, npages, readonly,
- ctx.bitmap, wait, flush_tlb);
+ ctx->bitmap, wait, flush_tlb);
unlock_out:
svm_range_unlock(prange);
@@ -1650,11 +1689,15 @@ unlock_out:
}
unreserve_out:
- svm_range_unreserve_bos(&ctx);
+ svm_range_unreserve_bos(ctx);
+ prange->is_error_flag = !!r;
if (!r)
prange->validate_timestamp = ktime_get_boottime();
+free_ctx:
+ kfree(ctx);
+
return r;
}
@@ -1783,6 +1826,7 @@ out_reschedule:
* @mm: current process mm_struct
* @start: starting process queue number
* @last: last process queue number
+ * @event: mmu notifier event when range is evicted or migrated
*
* Stop all queues of the process to ensure GPU doesn't access the memory, then
* return to let CPU evict the buffer and proceed CPU pagetable update.
@@ -1906,14 +1950,23 @@ void svm_range_set_max_pages(struct amdgpu_device *adev)
{
uint64_t max_pages;
uint64_t pages, _pages;
+ uint64_t min_pages = 0;
+ int i, id;
+
+ for (i = 0; i < adev->kfd.dev->num_nodes; i++) {
+ if (adev->kfd.dev->nodes[i]->xcp)
+ id = adev->kfd.dev->nodes[i]->xcp->id;
+ else
+ id = -1;
+ pages = KFD_XCP_MEMORY_SIZE(adev, id) >> 17;
+ pages = clamp(pages, 1ULL << 9, 1ULL << 18);
+ pages = rounddown_pow_of_two(pages);
+ min_pages = min_not_zero(min_pages, pages);
+ }
- /* 1/32 VRAM size in pages */
- pages = adev->gmc.real_vram_size >> 17;
- pages = clamp(pages, 1ULL << 9, 1ULL << 18);
- pages = rounddown_pow_of_two(pages);
do {
max_pages = READ_ONCE(max_svm_range_pages);
- _pages = min_not_zero(max_pages, pages);
+ _pages = min_not_zero(max_pages, min_pages);
} while (cmpxchg(&max_svm_range_pages, max_pages, _pages) != max_pages);
}
@@ -2507,29 +2560,31 @@ svm_range_from_addr(struct svm_range_list *svms, unsigned long addr,
*/
static int32_t
svm_range_best_restore_location(struct svm_range *prange,
- struct amdgpu_device *adev,
+ struct kfd_node *node,
int32_t *gpuidx)
{
- struct amdgpu_device *bo_adev, *preferred_adev;
+ struct kfd_node *bo_node, *preferred_node;
struct kfd_process *p;
uint32_t gpuid;
int r;
p = container_of(prange->svms, struct kfd_process, svms);
- r = kfd_process_gpuid_from_adev(p, adev, &gpuid, gpuidx);
+ r = kfd_process_gpuid_from_node(p, node, &gpuid, gpuidx);
if (r < 0) {
pr_debug("failed to get gpuid from kgd\n");
return -1;
}
+ if (node->adev->gmc.is_app_apu)
+ return 0;
+
if (prange->preferred_loc == gpuid ||
prange->preferred_loc == KFD_IOCTL_SVM_LOCATION_SYSMEM) {
return prange->preferred_loc;
} else if (prange->preferred_loc != KFD_IOCTL_SVM_LOCATION_UNDEFINED) {
- preferred_adev = svm_range_get_adev_by_id(prange,
- prange->preferred_loc);
- if (amdgpu_xgmi_same_hive(adev, preferred_adev))
+ preferred_node = svm_range_get_node_by_id(prange, prange->preferred_loc);
+ if (preferred_node && svm_nodes_in_same_hive(node, preferred_node))
return prange->preferred_loc;
/* fall through */
}
@@ -2541,8 +2596,8 @@ svm_range_best_restore_location(struct svm_range *prange,
if (!prange->actual_loc)
return 0;
- bo_adev = svm_range_get_adev_by_id(prange, prange->actual_loc);
- if (amdgpu_xgmi_same_hive(adev, bo_adev))
+ bo_node = svm_range_get_node_by_id(prange, prange->actual_loc);
+ if (bo_node && svm_nodes_in_same_hive(node, bo_node))
return prange->actual_loc;
else
return 0;
@@ -2659,7 +2714,7 @@ svm_range_check_vm_userptr(struct kfd_process *p, uint64_t start, uint64_t last,
}
static struct
-svm_range *svm_range_create_unregistered_range(struct amdgpu_device *adev,
+svm_range *svm_range_create_unregistered_range(struct kfd_node *node,
struct kfd_process *p,
struct mm_struct *mm,
int64_t addr)
@@ -2694,7 +2749,7 @@ svm_range *svm_range_create_unregistered_range(struct amdgpu_device *adev,
pr_debug("Failed to create prange in address [0x%llx]\n", addr);
return NULL;
}
- if (kfd_process_gpuid_from_adev(p, adev, &gpuid, &gpuidx)) {
+ if (kfd_process_gpuid_from_node(p, node, &gpuid, &gpuidx)) {
pr_debug("failed to get gpuid from kgd\n");
svm_range_free(prange, true);
return NULL;
@@ -2748,7 +2803,7 @@ static bool svm_range_skip_recover(struct svm_range *prange)
}
static void
-svm_range_count_fault(struct amdgpu_device *adev, struct kfd_process *p,
+svm_range_count_fault(struct kfd_node *node, struct kfd_process *p,
int32_t gpuidx)
{
struct kfd_process_device *pdd;
@@ -2761,7 +2816,7 @@ svm_range_count_fault(struct amdgpu_device *adev, struct kfd_process *p,
uint32_t gpuid;
int r;
- r = kfd_process_gpuid_from_adev(p, adev, &gpuid, &gpuidx);
+ r = kfd_process_gpuid_from_node(p, node, &gpuid, &gpuidx);
if (r < 0)
return;
}
@@ -2789,6 +2844,7 @@ svm_fault_allowed(struct vm_area_struct *vma, bool write_fault)
int
svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
+ uint32_t vmid, uint32_t node_id,
uint64_t addr, bool write_fault)
{
struct mm_struct *mm = NULL;
@@ -2796,6 +2852,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
struct svm_range *prange;
struct kfd_process *p;
ktime_t timestamp = ktime_get_boottime();
+ struct kfd_node *node;
int32_t best_loc;
int32_t gpuidx = MAX_GPU_INSTANCE;
bool write_locked = false;
@@ -2803,7 +2860,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
bool migration = false;
int r = 0;
- if (!KFD_IS_SVM_API_SUPPORTED(adev->kfd.dev)) {
+ if (!KFD_IS_SVM_API_SUPPORTED(adev)) {
pr_debug("device does not support SVM\n");
return -EFAULT;
}
@@ -2839,6 +2896,13 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
goto out;
}
+ node = kfd_node_by_irq_ids(adev, node_id, vmid);
+ if (!node) {
+ pr_debug("kfd node does not exist node_id: %d, vmid: %d\n", node_id,
+ vmid);
+ r = -EFAULT;
+ goto out;
+ }
mmap_read_lock(mm);
retry_write_locked:
mutex_lock(&svms->lock);
@@ -2857,7 +2921,7 @@ retry_write_locked:
write_locked = true;
goto retry_write_locked;
}
- prange = svm_range_create_unregistered_range(adev, p, mm, addr);
+ prange = svm_range_create_unregistered_range(node, p, mm, addr);
if (!prange) {
pr_debug("failed to create unregistered range svms 0x%p address [0x%llx]\n",
svms, addr);
@@ -2872,7 +2936,7 @@ retry_write_locked:
mutex_lock(&prange->migrate_mutex);
if (svm_range_skip_recover(prange)) {
- amdgpu_gmc_filter_faults_remove(adev, addr, pasid);
+ amdgpu_gmc_filter_faults_remove(node->adev, addr, pasid);
r = 0;
goto out_unlock_range;
}
@@ -2903,7 +2967,7 @@ retry_write_locked:
goto out_unlock_range;
}
- best_loc = svm_range_best_restore_location(prange, adev, &gpuidx);
+ best_loc = svm_range_best_restore_location(prange, node, &gpuidx);
if (best_loc == -1) {
pr_debug("svms %p failed get best restore loc [0x%lx 0x%lx]\n",
svms, prange->start, prange->last);
@@ -2915,7 +2979,7 @@ retry_write_locked:
svms, prange->start, prange->last, best_loc,
prange->actual_loc);
- kfd_smi_event_page_fault_start(adev->kfd.dev, p->lead_thread->pid, addr,
+ kfd_smi_event_page_fault_start(node, p->lead_thread->pid, addr,
write_fault, timestamp);
if (prange->actual_loc != best_loc) {
@@ -2953,7 +3017,7 @@ retry_write_locked:
pr_debug("failed %d to map svms 0x%p [0x%lx 0x%lx] to gpus\n",
r, svms, prange->start, prange->last);
- kfd_smi_event_page_fault_end(adev->kfd.dev, p->lead_thread->pid, addr,
+ kfd_smi_event_page_fault_end(node, p->lead_thread->pid, addr,
migration);
out_unlock_range:
@@ -2962,7 +3026,7 @@ out_unlock_svms:
mutex_unlock(&svms->lock);
mmap_read_unlock(mm);
- svm_range_count_fault(adev, p, gpuidx);
+ svm_range_count_fault(node, p, gpuidx);
mmput(mm);
out:
@@ -2970,7 +3034,7 @@ out:
if (r == -EAGAIN) {
pr_debug("recover vm fault later\n");
- amdgpu_gmc_filter_faults_remove(adev, addr, pasid);
+ amdgpu_gmc_filter_faults_remove(node->adev, addr, pasid);
r = 0;
}
return r;
@@ -2994,10 +3058,10 @@ svm_range_switch_xnack_reserve_mem(struct kfd_process *p, bool xnack_enabled)
size = (pchild->last - pchild->start + 1) << PAGE_SHIFT;
if (xnack_enabled) {
amdgpu_amdkfd_unreserve_mem_limit(NULL, size,
- KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
+ KFD_IOC_ALLOC_MEM_FLAGS_USERPTR, 0);
} else {
r = amdgpu_amdkfd_reserve_mem_limit(NULL, size,
- KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
+ KFD_IOC_ALLOC_MEM_FLAGS_USERPTR, 0);
if (r)
goto out_unlock;
reserved_size += size;
@@ -3007,10 +3071,10 @@ svm_range_switch_xnack_reserve_mem(struct kfd_process *p, bool xnack_enabled)
size = (prange->last - prange->start + 1) << PAGE_SHIFT;
if (xnack_enabled) {
amdgpu_amdkfd_unreserve_mem_limit(NULL, size,
- KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
+ KFD_IOC_ALLOC_MEM_FLAGS_USERPTR, 0);
} else {
r = amdgpu_amdkfd_reserve_mem_limit(NULL, size,
- KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
+ KFD_IOC_ALLOC_MEM_FLAGS_USERPTR, 0);
if (r)
goto out_unlock;
reserved_size += size;
@@ -3023,7 +3087,7 @@ out_unlock:
if (r)
amdgpu_amdkfd_unreserve_mem_limit(NULL, reserved_size,
- KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
+ KFD_IOC_ALLOC_MEM_FLAGS_USERPTR, 0);
else
/* Change xnack mode must be inside svms lock, to avoid race with
* svm_range_deferred_list_work unreserve memory in parallel.
@@ -3081,7 +3145,7 @@ int svm_range_list_init(struct kfd_process *p)
spin_lock_init(&svms->deferred_list_lock);
for (i = 0; i < p->n_pdds; i++)
- if (KFD_IS_SVM_API_SUPPORTED(p->pdds[i]->dev))
+ if (KFD_IS_SVM_API_SUPPORTED(p->pdds[i]->dev->adev))
bitmap_set(svms->bitmap_supported, i, 1);
return 0;
@@ -3212,7 +3276,7 @@ svm_range_best_prefetch_location(struct svm_range *prange)
DECLARE_BITMAP(bitmap, MAX_GPU_INSTANCE);
uint32_t best_loc = prange->prefetch_loc;
struct kfd_process_device *pdd;
- struct amdgpu_device *bo_adev;
+ struct kfd_node *bo_node;
struct kfd_process *p;
uint32_t gpuidx;
@@ -3221,9 +3285,14 @@ svm_range_best_prefetch_location(struct svm_range *prange)
if (!best_loc || best_loc == KFD_IOCTL_SVM_LOCATION_UNDEFINED)
goto out;
- bo_adev = svm_range_get_adev_by_id(prange, best_loc);
- if (!bo_adev) {
- WARN_ONCE(1, "failed to get device by id 0x%x\n", best_loc);
+ bo_node = svm_range_get_node_by_id(prange, best_loc);
+ if (!bo_node) {
+ WARN_ONCE(1, "failed to get valid kfd node at id%x\n", best_loc);
+ best_loc = 0;
+ goto out;
+ }
+
+ if (bo_node->adev->gmc.is_app_apu) {
best_loc = 0;
goto out;
}
@@ -3241,10 +3310,10 @@ svm_range_best_prefetch_location(struct svm_range *prange)
continue;
}
- if (pdd->dev->adev == bo_adev)
+ if (pdd->dev->adev == bo_node->adev)
continue;
- if (!amdgpu_xgmi_same_hive(pdd->dev->adev, bo_adev)) {
+ if (!svm_nodes_in_same_hive(pdd->dev, bo_node)) {
best_loc = 0;
break;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index 7a33b93f9df6..21b14510882b 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -48,6 +48,7 @@ struct svm_range_bo {
struct work_struct eviction_work;
uint32_t evicting;
struct work_struct release_work;
+ struct kfd_node *node;
};
enum svm_work_list_ops {
@@ -133,6 +134,7 @@ struct svm_range {
DECLARE_BITMAP(bitmap_aip, MAX_GPU_INSTANCE);
bool validated_once;
bool mapped_to_gpu;
+ bool is_error_flag;
};
static inline void svm_range_lock(struct svm_range *prange)
@@ -163,16 +165,17 @@ int svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start,
struct svm_range *svm_range_from_addr(struct svm_range_list *svms,
unsigned long addr,
struct svm_range **parent);
-struct amdgpu_device *svm_range_get_adev_by_id(struct svm_range *prange,
- uint32_t id);
-int svm_range_vram_node_new(struct amdgpu_device *adev,
- struct svm_range *prange, bool clear);
+struct kfd_node *svm_range_get_node_by_id(struct svm_range *prange,
+ uint32_t gpu_id);
+int svm_range_vram_node_new(struct kfd_node *node, struct svm_range *prange,
+ bool clear);
void svm_range_vram_node_free(struct svm_range *prange);
int svm_range_split_by_granularity(struct kfd_process *p, struct mm_struct *mm,
unsigned long addr, struct svm_range *parent,
struct svm_range *prange);
-int svm_range_restore_pages(struct amdgpu_device *adev,
- unsigned int pasid, uint64_t addr, bool write_fault);
+int svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
+ uint32_t vmid, uint32_t node_id, uint64_t addr,
+ bool write_fault);
int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence);
void svm_range_add_list_work(struct svm_range_list *svms,
struct svm_range *prange, struct mm_struct *mm,
@@ -192,13 +195,14 @@ int kfd_criu_restore_svm(struct kfd_process *p,
uint64_t max_priv_data_size);
int kfd_criu_resume_svm(struct kfd_process *p);
struct kfd_process_device *
-svm_range_get_pdd_by_adev(struct svm_range *prange, struct amdgpu_device *adev);
+svm_range_get_pdd_by_node(struct svm_range *prange, struct kfd_node *node);
void svm_range_list_lock_and_flush_work(struct svm_range_list *svms, struct mm_struct *mm);
/* SVM API and HMM page migration work together, device memory type
* is initialized to not 0 when page migration register device memory.
*/
-#define KFD_IS_SVM_API_SUPPORTED(dev) ((dev)->pgmap.type != 0)
+#define KFD_IS_SVM_API_SUPPORTED(adev) ((adev)->kfd.pgmap.type != 0 ||\
+ (adev)->gmc.is_app_apu)
void svm_range_bo_unref_async(struct svm_range_bo *svm_bo);
@@ -219,8 +223,9 @@ static inline void svm_range_list_fini(struct kfd_process *p)
}
static inline int svm_range_restore_pages(struct amdgpu_device *adev,
- unsigned int pasid, uint64_t addr,
- bool write_fault)
+ unsigned int pasid,
+ uint32_t client_id, uint32_t node_id,
+ uint64_t addr, bool write_fault)
{
return -EFAULT;
}
@@ -261,6 +266,10 @@ static inline int kfd_criu_resume_svm(struct kfd_process *p)
return 0;
}
+static inline void svm_range_set_max_pages(struct amdgpu_device *adev)
+{
+}
+
#define KFD_IS_SVM_API_SUPPORTED(dev) false
#endif /* IS_ENABLED(CONFIG_HSA_AMD_SVM) */
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 8e4124dcb6e4..90b86a6ac7bd 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -96,7 +96,7 @@ struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id)
return ret;
}
-struct kfd_dev *kfd_device_by_id(uint32_t gpu_id)
+struct kfd_node *kfd_device_by_id(uint32_t gpu_id)
{
struct kfd_topology_device *top_dev;
@@ -107,10 +107,10 @@ struct kfd_dev *kfd_device_by_id(uint32_t gpu_id)
return top_dev->gpu;
}
-struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev)
+struct kfd_node *kfd_device_by_pci_dev(const struct pci_dev *pdev)
{
struct kfd_topology_device *top_dev;
- struct kfd_dev *device = NULL;
+ struct kfd_node *device = NULL;
down_read(&topology_lock);
@@ -125,24 +125,6 @@ struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev)
return device;
}
-struct kfd_dev *kfd_device_by_adev(const struct amdgpu_device *adev)
-{
- struct kfd_topology_device *top_dev;
- struct kfd_dev *device = NULL;
-
- down_read(&topology_lock);
-
- list_for_each_entry(top_dev, &topology_device_list, list)
- if (top_dev->gpu && top_dev->gpu->adev == adev) {
- device = top_dev->gpu;
- break;
- }
-
- up_read(&topology_lock);
-
- return device;
-}
-
/* Called with write topology_lock acquired */
static void kfd_release_topology_device(struct kfd_topology_device *dev)
{
@@ -468,7 +450,8 @@ 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 : 0);
+ dev->gpu ? (dev->node_props.simd_count *
+ NUM_XCC(dev->gpu->xcc_mask)) : 0);
sysfs_show_32bit_prop(buffer, offs, "mem_banks_count",
dev->node_props.mem_banks_count);
sysfs_show_32bit_prop(buffer, offs, "caches_count",
@@ -492,7 +475,8 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
sysfs_show_32bit_prop(buffer, offs, "wave_front_size",
dev->node_props.wave_front_size);
sysfs_show_32bit_prop(buffer, offs, "array_count",
- dev->node_props.array_count);
+ dev->gpu ? (dev->node_props.array_count *
+ NUM_XCC(dev->gpu->xcc_mask)) : 0);
sysfs_show_32bit_prop(buffer, offs, "simd_arrays_per_engine",
dev->node_props.simd_arrays_per_engine);
sysfs_show_32bit_prop(buffer, offs, "cu_per_simd_array",
@@ -526,7 +510,7 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
if (dev->gpu) {
log_max_watch_addr =
- __ilog2_u32(dev->gpu->device_info.num_of_watch_points);
+ __ilog2_u32(dev->gpu->kfd->device_info.num_of_watch_points);
if (log_max_watch_addr) {
dev->node_props.capability |=
@@ -548,14 +532,17 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
sysfs_show_64bit_prop(buffer, offs, "local_mem_size", 0ULL);
sysfs_show_32bit_prop(buffer, offs, "fw_version",
- dev->gpu->mec_fw_version);
+ dev->gpu->kfd->mec_fw_version);
sysfs_show_32bit_prop(buffer, offs, "capability",
dev->node_props.capability);
+ sysfs_show_64bit_prop(buffer, offs, "debug_prop",
+ dev->node_props.debug_prop);
sysfs_show_32bit_prop(buffer, offs, "sdma_fw_version",
- dev->gpu->sdma_fw_version);
+ dev->gpu->kfd->sdma_fw_version);
sysfs_show_64bit_prop(buffer, offs, "unique_id",
dev->gpu->adev->unique_id);
-
+ sysfs_show_32bit_prop(buffer, offs, "num_xcc",
+ NUM_XCC(dev->gpu->xcc_mask));
}
return sysfs_show_32bit_prop(buffer, offs, "max_engine_clk_ccompute",
@@ -1157,10 +1144,10 @@ void kfd_topology_shutdown(void)
up_write(&topology_lock);
}
-static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu)
+static uint32_t kfd_generate_gpu_id(struct kfd_node *gpu)
{
uint32_t hashout;
- uint32_t buf[7];
+ uint32_t buf[8];
uint64_t local_mem_size;
int i;
@@ -1177,8 +1164,9 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu)
buf[4] = gpu->adev->pdev->bus->number;
buf[5] = lower_32_bits(local_mem_size);
buf[6] = upper_32_bits(local_mem_size);
+ buf[7] = (ffs(gpu->xcc_mask) - 1) | (NUM_XCC(gpu->xcc_mask) << 16);
- for (i = 0, hashout = 0; i < 7; i++)
+ for (i = 0, hashout = 0; i < 8; i++)
hashout ^= hash_32(buf[i], KFD_GPU_ID_HASH_WIDTH);
return hashout;
@@ -1188,7 +1176,7 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu)
* list then return NULL. This means a new topology device has to
* be created for this GPU.
*/
-static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
+static struct kfd_topology_device *kfd_assign_gpu(struct kfd_node *gpu)
{
struct kfd_topology_device *dev;
struct kfd_topology_device *out_dev = NULL;
@@ -1201,7 +1189,7 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
/* Discrete GPUs need their own topology device list
* entries. Don't assign them to CPU/APU nodes.
*/
- if (!gpu->use_iommu_v2 &&
+ if (!gpu->kfd->use_iommu_v2 &&
dev->node_props.cpu_cores_count)
continue;
@@ -1248,7 +1236,8 @@ static void kfd_fill_mem_clk_max_info(struct kfd_topology_device *dev)
* for APUs - If CRAT from ACPI reports more than one bank, then
* all the banks will report the same mem_clk_max information
*/
- amdgpu_amdkfd_get_local_mem_info(dev->gpu->adev, &local_mem_info);
+ amdgpu_amdkfd_get_local_mem_info(dev->gpu->adev, &local_mem_info,
+ dev->gpu->xcp);
list_for_each_entry(mem, &dev->mem_props, list)
mem->mem_clk_max = local_mem_info.mem_clk_max;
@@ -1275,7 +1264,7 @@ static void kfd_set_iolink_no_atomics(struct kfd_topology_device *dev,
CRAT_IOLINK_FLAGS_NO_ATOMICS_64_BIT;
/* set gpu (dev) flags. */
} else {
- if (!dev->gpu->pci_atomic_requested ||
+ if (!dev->gpu->kfd->pci_atomic_requested ||
dev->gpu->adev->asic_type == CHIP_HAWAII)
link->flags |= CRAT_IOLINK_FLAGS_NO_ATOMICS_32_BIT |
CRAT_IOLINK_FLAGS_NO_ATOMICS_64_BIT;
@@ -1323,10 +1312,16 @@ static void kfd_fill_iolink_non_crat_info(struct kfd_topology_device *dev)
continue;
/* Include the CPU peer in GPU hive if connected over xGMI. */
- if (!peer_dev->gpu && !peer_dev->node_props.hive_id &&
- dev->node_props.hive_id &&
- dev->gpu->adev->gmc.xgmi.connected_to_cpu)
+ if (!peer_dev->gpu &&
+ link->iolink_type == CRAT_IOLINK_TYPE_XGMI) {
+ /*
+ * If the GPU is not part of a GPU hive, use its pci
+ * device location as the hive ID to bind with the CPU.
+ */
+ if (!dev->node_props.hive_id)
+ dev->node_props.hive_id = pci_dev_id(dev->gpu->adev->pdev);
peer_dev->node_props.hive_id = dev->node_props.hive_id;
+ }
list_for_each_entry(inbound_link, &peer_dev->io_link_props,
list) {
@@ -1569,8 +1564,8 @@ static int kfd_dev_create_p2p_links(void)
if (dev == new_dev)
break;
if (!dev->gpu || !dev->gpu->adev ||
- (dev->gpu->hive_id &&
- dev->gpu->hive_id == new_dev->gpu->hive_id))
+ (dev->gpu->kfd->hive_id &&
+ dev->gpu->kfd->hive_id == new_dev->gpu->kfd->hive_id))
goto next;
/* check if node(s) is/are peer accessible in one direction or bi-direction */
@@ -1590,7 +1585,6 @@ out:
return ret;
}
-
/* Helper function. See kfd_fill_gpu_cache_info for parameter description */
static int fill_in_l1_pcache(struct kfd_cache_properties **props_ext,
struct kfd_gpu_cache_info *pcache_info,
@@ -1723,7 +1717,7 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
/* kfd_fill_cache_non_crat_info - Fill GPU cache info using kfd_gpu_cache_info
* tables
*/
-static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct kfd_dev *kdev)
+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;
@@ -1805,7 +1799,7 @@ static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct
pr_debug("Added [%d] GPU cache entries\n", num_of_entries);
}
-static int kfd_topology_add_device_locked(struct kfd_dev *gpu, uint32_t gpu_id,
+static int kfd_topology_add_device_locked(struct kfd_node *gpu, uint32_t gpu_id,
struct kfd_topology_device **dev)
{
int proximity_domain = ++topology_crat_proximity_domain;
@@ -1865,7 +1859,103 @@ err:
return res;
}
-int kfd_topology_add_device(struct kfd_dev *gpu)
+static void kfd_topology_set_dbg_firmware_support(struct kfd_topology_device *dev)
+{
+ bool firmware_supported = true;
+
+ if (KFD_GC_VERSION(dev->gpu) >= IP_VERSION(11, 0, 0) &&
+ KFD_GC_VERSION(dev->gpu) < IP_VERSION(12, 0, 0)) {
+ uint32_t mes_api_rev = (dev->gpu->adev->mes.sched_version &
+ AMDGPU_MES_API_VERSION_MASK) >>
+ AMDGPU_MES_API_VERSION_SHIFT;
+ uint32_t mes_rev = dev->gpu->adev->mes.sched_version &
+ AMDGPU_MES_VERSION_MASK;
+
+ firmware_supported = (mes_api_rev >= 14) && (mes_rev >= 64);
+ goto out;
+ }
+
+ /*
+ * Note: Any unlisted devices here are assumed to support exception handling.
+ * Add additional checks here as needed.
+ */
+ switch (KFD_GC_VERSION(dev->gpu)) {
+ case IP_VERSION(9, 0, 1):
+ firmware_supported = dev->gpu->kfd->mec_fw_version >= 459 + 32768;
+ break;
+ case IP_VERSION(9, 1, 0):
+ case IP_VERSION(9, 2, 1):
+ case IP_VERSION(9, 2, 2):
+ case IP_VERSION(9, 3, 0):
+ case IP_VERSION(9, 4, 0):
+ firmware_supported = dev->gpu->kfd->mec_fw_version >= 459;
+ break;
+ case IP_VERSION(9, 4, 1):
+ firmware_supported = dev->gpu->kfd->mec_fw_version >= 60;
+ break;
+ case IP_VERSION(9, 4, 2):
+ firmware_supported = dev->gpu->kfd->mec_fw_version >= 51;
+ break;
+ case IP_VERSION(10, 1, 10):
+ case IP_VERSION(10, 1, 2):
+ case IP_VERSION(10, 1, 1):
+ firmware_supported = dev->gpu->kfd->mec_fw_version >= 144;
+ break;
+ case IP_VERSION(10, 3, 0):
+ case IP_VERSION(10, 3, 2):
+ case IP_VERSION(10, 3, 1):
+ case IP_VERSION(10, 3, 4):
+ case IP_VERSION(10, 3, 5):
+ firmware_supported = dev->gpu->kfd->mec_fw_version >= 89;
+ break;
+ case IP_VERSION(10, 1, 3):
+ case IP_VERSION(10, 3, 3):
+ firmware_supported = false;
+ break;
+ default:
+ break;
+ }
+
+out:
+ if (firmware_supported)
+ dev->node_props.capability |= HSA_CAP_TRAP_DEBUG_FIRMWARE_SUPPORTED;
+}
+
+static void kfd_topology_set_capabilities(struct kfd_topology_device *dev)
+{
+ dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_2_0 <<
+ HSA_CAP_DOORBELL_TYPE_TOTALBITS_SHIFT) &
+ HSA_CAP_DOORBELL_TYPE_TOTALBITS_MASK);
+
+ dev->node_props.capability |= HSA_CAP_TRAP_DEBUG_SUPPORT |
+ HSA_CAP_TRAP_DEBUG_WAVE_LAUNCH_TRAP_OVERRIDE_SUPPORTED |
+ HSA_CAP_TRAP_DEBUG_WAVE_LAUNCH_MODE_SUPPORTED;
+
+ if (KFD_GC_VERSION(dev->gpu) < IP_VERSION(10, 0, 0)) {
+ dev->node_props.debug_prop |= HSA_DBG_WATCH_ADDR_MASK_LO_BIT_GFX9 |
+ HSA_DBG_WATCH_ADDR_MASK_HI_BIT;
+
+ if (KFD_GC_VERSION(dev->gpu) < IP_VERSION(9, 4, 2))
+ dev->node_props.debug_prop |=
+ HSA_DBG_DISPATCH_INFO_ALWAYS_VALID;
+ else
+ dev->node_props.capability |=
+ HSA_CAP_TRAP_DEBUG_PRECISE_MEMORY_OPERATIONS_SUPPORTED;
+ } else {
+ dev->node_props.debug_prop |= HSA_DBG_WATCH_ADDR_MASK_LO_BIT_GFX10 |
+ HSA_DBG_WATCH_ADDR_MASK_HI_BIT;
+
+ if (KFD_GC_VERSION(dev->gpu) < IP_VERSION(11, 0, 0))
+ dev->node_props.debug_prop |= HSA_DBG_DISPATCH_INFO_ALWAYS_VALID;
+ else
+ dev->node_props.capability |=
+ HSA_CAP_TRAP_DEBUG_PRECISE_MEMORY_OPERATIONS_SUPPORTED;
+ }
+
+ kfd_topology_set_dbg_firmware_support(dev);
+}
+
+int kfd_topology_add_device(struct kfd_node *gpu)
{
uint32_t gpu_id;
struct kfd_topology_device *dev;
@@ -1916,28 +2006,37 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
dev->node_props.simd_arrays_per_engine =
cu_info.num_shader_arrays_per_engine;
- dev->node_props.gfx_target_version = gpu->device_info.gfx_target_version;
+ dev->node_props.gfx_target_version =
+ gpu->kfd->device_info.gfx_target_version;
dev->node_props.vendor_id = gpu->adev->pdev->vendor;
dev->node_props.device_id = gpu->adev->pdev->device;
dev->node_props.capability |=
((dev->gpu->adev->rev_id << HSA_CAP_ASIC_REVISION_SHIFT) &
HSA_CAP_ASIC_REVISION_MASK);
+
dev->node_props.location_id = pci_dev_id(gpu->adev->pdev);
+ if (KFD_GC_VERSION(dev->gpu->kfd) == IP_VERSION(9, 4, 3))
+ dev->node_props.location_id |= dev->gpu->node_id;
+
dev->node_props.domain = pci_domain_nr(gpu->adev->pdev->bus);
dev->node_props.max_engine_clk_fcompute =
amdgpu_amdkfd_get_max_engine_clock_in_mhz(dev->gpu->adev);
dev->node_props.max_engine_clk_ccompute =
cpufreq_quick_get_max(0) / 1000;
- dev->node_props.drm_render_minor =
- gpu->shared_resources.drm_render_minor;
- dev->node_props.hive_id = gpu->hive_id;
+ if (gpu->xcp)
+ dev->node_props.drm_render_minor = gpu->xcp->ddev->render->index;
+ else
+ dev->node_props.drm_render_minor =
+ gpu->kfd->shared_resources.drm_render_minor;
+
+ dev->node_props.hive_id = gpu->kfd->hive_id;
dev->node_props.num_sdma_engines = kfd_get_num_sdma_engines(gpu);
dev->node_props.num_sdma_xgmi_engines =
kfd_get_num_xgmi_sdma_engines(gpu);
dev->node_props.num_sdma_queues_per_engine =
- gpu->device_info.num_sdma_queues_per_engine -
- gpu->device_info.num_reserved_sdma_queues_per_engine;
+ gpu->kfd->device_info.num_sdma_queues_per_engine -
+ gpu->kfd->device_info.num_reserved_sdma_queues_per_engine;
dev->node_props.num_gws = (dev->gpu->gws &&
dev->gpu->dqm->sched_policy != KFD_SCHED_POLICY_NO_HWS) ?
dev->gpu->adev->gds.gws_size : 0;
@@ -1966,20 +2065,18 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
HSA_CAP_DOORBELL_TYPE_TOTALBITS_MASK);
break;
default:
- if (KFD_GC_VERSION(dev->gpu) >= IP_VERSION(9, 0, 1))
- dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_2_0 <<
- HSA_CAP_DOORBELL_TYPE_TOTALBITS_SHIFT) &
- HSA_CAP_DOORBELL_TYPE_TOTALBITS_MASK);
- else
+ if (KFD_GC_VERSION(dev->gpu) < IP_VERSION(9, 0, 1))
WARN(1, "Unexpected ASIC family %u",
dev->gpu->adev->asic_type);
+ else
+ kfd_topology_set_capabilities(dev);
}
/*
* Overwrite ATS capability according to needs_iommu_device to fix
* potential missing corresponding bit in CRAT of BIOS.
*/
- if (dev->gpu->use_iommu_v2)
+ if (dev->gpu->kfd->use_iommu_v2)
dev->node_props.capability |= HSA_CAP_ATS_PRESENT;
else
dev->node_props.capability &= ~HSA_CAP_ATS_PRESENT;
@@ -2007,7 +2104,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
dev->node_props.capability |= (dev->gpu->adev->ras_enabled != 0) ?
HSA_CAP_RASEVENTNOTIFY : 0;
- if (KFD_IS_SVM_API_SUPPORTED(dev->gpu->adev->kfd.dev))
+ if (KFD_IS_SVM_API_SUPPORTED(dev->gpu->adev))
dev->node_props.capability |= HSA_CAP_SVMAPI_SUPPORTED;
kfd_debug_print_topology();
@@ -2079,7 +2176,7 @@ static void kfd_topology_update_io_links(int proximity_domain)
}
}
-int kfd_topology_remove_device(struct kfd_dev *gpu)
+int kfd_topology_remove_device(struct kfd_node *gpu)
{
struct kfd_topology_device *dev, *tmp;
uint32_t gpu_id;
@@ -2119,7 +2216,7 @@ int kfd_topology_remove_device(struct kfd_dev *gpu)
* Return - 0: On success (@kdev will be NULL for non GPU nodes)
* -1: If end of list
*/
-int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev)
+int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_node **kdev)
{
struct kfd_topology_device *top_dev;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
index fca30d00a9bb..cba2cd5ed9d1 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
@@ -31,6 +31,11 @@
#define KFD_TOPOLOGY_PUBLIC_NAME_SIZE 32
+#define HSA_DBG_WATCH_ADDR_MASK_LO_BIT_GFX9 6
+#define HSA_DBG_WATCH_ADDR_MASK_LO_BIT_GFX10 7
+#define HSA_DBG_WATCH_ADDR_MASK_HI_BIT \
+ (29 << HSA_DBG_WATCH_ADDR_MASK_HI_BIT_SHIFT)
+
struct kfd_node_properties {
uint64_t hive_id;
uint32_t cpu_cores_count;
@@ -42,6 +47,7 @@ struct kfd_node_properties {
uint32_t cpu_core_id_base;
uint32_t simd_id_base;
uint32_t capability;
+ uint64_t debug_prop;
uint32_t max_waves_per_simd;
uint32_t lds_size_in_kb;
uint32_t gds_size_in_kb;
@@ -75,7 +81,7 @@ struct kfd_mem_properties {
uint32_t flags;
uint32_t width;
uint32_t mem_clk_max;
- struct kfd_dev *gpu;
+ struct kfd_node *gpu;
struct kobject *kobj;
struct attribute attr;
};
@@ -93,7 +99,7 @@ struct kfd_cache_properties {
uint32_t cache_latency;
uint32_t cache_type;
uint8_t sibling_map[CACHE_SIBLINGMAP_SIZE];
- struct kfd_dev *gpu;
+ struct kfd_node *gpu;
struct kobject *kobj;
struct attribute attr;
uint32_t sibling_map_size;
@@ -113,7 +119,7 @@ struct kfd_iolink_properties {
uint32_t max_bandwidth;
uint32_t rec_transfer_size;
uint32_t flags;
- struct kfd_dev *gpu;
+ struct kfd_node *gpu;
struct kobject *kobj;
struct attribute attr;
};
@@ -135,7 +141,7 @@ struct kfd_topology_device {
struct list_head io_link_props;
struct list_head p2p_link_props;
struct list_head perf_props;
- struct kfd_dev *gpu;
+ struct kfd_node *gpu;
struct kobject *kobj_node;
struct kobject *kobj_mem;
struct kobject *kobj_cache;
diff --git a/drivers/gpu/drm/amd/amdxcp/Makefile b/drivers/gpu/drm/amd/amdxcp/Makefile
new file mode 100644
index 000000000000..870501a4bb8c
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdxcp/Makefile
@@ -0,0 +1,25 @@
+#
+# Copyright 2023 Advanced Micro Devices, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+amdxcp-y := amdgpu_xcp_drv.o
+
+obj-$(CONFIG_DRM_AMDGPU) += amdxcp.o
diff --git a/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c b/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c
new file mode 100644
index 000000000000..353597fc908d
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_drv.h>
+
+#include "amdgpu_xcp_drv.h"
+
+#define MAX_XCP_PLATFORM_DEVICE 64
+
+struct xcp_device {
+ struct drm_device drm;
+ struct platform_device *pdev;
+};
+
+static const struct drm_driver amdgpu_xcp_driver = {
+ .driver_features = DRIVER_GEM | DRIVER_RENDER,
+ .name = "amdgpu_xcp_drv",
+ .major = 1,
+ .minor = 0,
+};
+
+static int pdev_num;
+static struct xcp_device *xcp_dev[MAX_XCP_PLATFORM_DEVICE];
+
+int amdgpu_xcp_drm_dev_alloc(struct drm_device **ddev)
+{
+ struct platform_device *pdev;
+ struct xcp_device *pxcp_dev;
+ int ret;
+
+ if (pdev_num >= MAX_XCP_PLATFORM_DEVICE)
+ return -ENODEV;
+
+ pdev = platform_device_register_simple("amdgpu_xcp", pdev_num, NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
+ ret = -ENOMEM;
+ goto out_unregister;
+ }
+
+ pxcp_dev = devm_drm_dev_alloc(&pdev->dev, &amdgpu_xcp_driver, struct xcp_device, drm);
+ if (IS_ERR(pxcp_dev)) {
+ ret = PTR_ERR(pxcp_dev);
+ goto out_devres;
+ }
+
+ xcp_dev[pdev_num] = pxcp_dev;
+ xcp_dev[pdev_num]->pdev = pdev;
+ *ddev = &pxcp_dev->drm;
+ pdev_num++;
+
+ return 0;
+
+out_devres:
+ devres_release_group(&pdev->dev, NULL);
+out_unregister:
+ platform_device_unregister(pdev);
+
+ return ret;
+}
+EXPORT_SYMBOL(amdgpu_xcp_drm_dev_alloc);
+
+void amdgpu_xcp_drv_release(void)
+{
+ for (--pdev_num; pdev_num >= 0; --pdev_num) {
+ devres_release_group(&xcp_dev[pdev_num]->pdev->dev, NULL);
+ platform_device_unregister(xcp_dev[pdev_num]->pdev);
+ xcp_dev[pdev_num]->pdev = NULL;
+ xcp_dev[pdev_num] = NULL;
+ }
+ pdev_num = 0;
+}
+EXPORT_SYMBOL(amdgpu_xcp_drv_release);
+
+static void __exit amdgpu_xcp_drv_exit(void)
+{
+ amdgpu_xcp_drv_release();
+}
+
+module_exit(amdgpu_xcp_drv_exit);
+
+MODULE_AUTHOR("AMD linux driver team");
+MODULE_DESCRIPTION("AMD XCP PLATFORM DEVICES");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.h b/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.h
new file mode 100644
index 000000000000..c1c4b679bf95
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdxcp/amdgpu_xcp_drv.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _AMDGPU_XCP_DRV_H_
+#define _AMDGPU_XCP_DRV_H_
+
+int amdgpu_xcp_drm_dev_alloc(struct drm_device **ddev);
+void amdgpu_xcp_drv_release(void);
+#endif /* _AMDGPU_XCP_DRV_H_ */
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig
index 2d8e55e29637..bf0a655d009e 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -8,7 +8,7 @@ config DRM_AMD_DC
depends on BROKEN || !CC_IS_CLANG || X86_64 || SPARC64 || ARM64
select SND_HDA_COMPONENT if SND_HDA_CORE
# !CC_IS_CLANG: https://github.com/ClangBuiltLinux/linux/issues/1752
- select DRM_AMD_DC_FP if (X86 || (PPC64 && ALTIVEC) || (ARM64 && KERNEL_MODE_NEON && !CC_IS_CLANG))
+ select DRM_AMD_DC_FP if (X86 || LOONGARCH || (PPC64 && ALTIVEC) || (ARM64 && KERNEL_MODE_NEON && !CC_IS_CLANG))
help
Choose this option if you want to use the new display engine
support for AMDGPU. This adds required support for Vega and
@@ -42,16 +42,13 @@ config DEBUG_KERNEL_DC
Choose this option if you want to hit kdgb_break in assert.
config DRM_AMD_SECURE_DISPLAY
- bool "Enable secure display support"
- depends on DEBUG_FS
- depends on DRM_AMD_DC_FP
- help
- Choose this option if you want to
- support secure display
-
- This option enables the calculation
- of crc of specific region via debugfs.
- Cooperate with specific DMCU FW.
+ bool "Enable secure display support"
+ depends on DEBUG_FS
+ depends on DRM_AMD_DC_FP
+ help
+ Choose this option if you want to support secure display
+ This option enables the calculation of crc of specific region via
+ debugfs. Cooperate with specific DMCU FW.
endmenu
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 7acd73e5004f..514f6785a020 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -365,6 +365,14 @@ static inline void reverse_planes_order(struct dc_surface_update *array_of_surfa
* adjustments and preparation before calling it. This function is a wrapper
* for the dc_update_planes_and_stream that does any required configuration
* before passing control to DC.
+ *
+ * @dc: Display Core control structure
+ * @update_type: specify whether it is FULL/MEDIUM/FAST update
+ * @planes_count: planes count to update
+ * @stream: stream state
+ * @stream_update: stream update
+ * @array_of_surface_update: dc surface update pointer
+ *
*/
static inline bool update_planes_and_stream_adapter(struct dc *dc,
int update_type,
@@ -1646,11 +1654,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
if (amdgpu_dc_feature_mask & DC_DISABLE_LTTPR_DP2_0)
init_data.flags.allow_lttpr_non_transparent_mode.bits.DP2_0 = true;
- /* Disable SubVP + DRR config by default */
- init_data.flags.disable_subvp_drr = true;
- if (amdgpu_dc_feature_mask & DC_ENABLE_SUBVP_DRR)
- init_data.flags.disable_subvp_drr = false;
-
init_data.flags.seamless_boot_edp_requested = false;
if (check_seamless_boot_capability(adev)) {
@@ -1672,9 +1675,11 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
adev->dm.dc = dc_create(&init_data);
if (adev->dm.dc) {
- DRM_INFO("Display Core initialized with v%s!\n", DC_VER);
+ DRM_INFO("Display Core v%s initialized on %s\n", DC_VER,
+ dce_version_to_string(adev->dm.dc->ctx->dce_version));
} else {
- DRM_INFO("Display Core failed to initialize with v%s!\n", DC_VER);
+ DRM_INFO("Display Core v%s failed to initialize on %s\n", DC_VER,
+ dce_version_to_string(adev->dm.dc->ctx->dce_version));
goto error;
}
@@ -1776,12 +1781,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
dc_init_callbacks(adev->dm.dc, &init_params);
}
-#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
- adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev);
- if (!adev->dm.secure_display_ctxs) {
- DRM_ERROR("amdgpu: failed to initialize secure_display_ctxs.\n");
- }
-#endif
if (dc_is_dmub_outbox_supported(adev->dm.dc)) {
init_completion(&adev->dm.dmub_aux_transfer_done);
adev->dm.dmub_notify = kzalloc(sizeof(struct dmub_notification), GFP_KERNEL);
@@ -1840,6 +1839,11 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
goto error;
}
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+ adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev);
+ if (!adev->dm.secure_display_ctxs)
+ DRM_ERROR("amdgpu: failed to initialize secure display contexts.\n");
+#endif
DRM_DEBUG_DRIVER("KMS initialized.\n");
@@ -3263,6 +3267,7 @@ static void dm_handle_mst_sideband_msg(struct amdgpu_dm_connector *aconnector)
while (dret == dpcd_bytes_to_read &&
process_count < max_process_count) {
+ u8 ack[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = {};
u8 retry;
dret = 0;
@@ -3271,28 +3276,29 @@ static void dm_handle_mst_sideband_msg(struct amdgpu_dm_connector *aconnector)
DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
/* handle HPD short pulse irq */
if (aconnector->mst_mgr.mst_state)
- drm_dp_mst_hpd_irq(
- &aconnector->mst_mgr,
- esi,
- &new_irq_handled);
+ drm_dp_mst_hpd_irq_handle_event(&aconnector->mst_mgr,
+ esi,
+ ack,
+ &new_irq_handled);
if (new_irq_handled) {
/* ACK at DPCD to notify down stream */
- const int ack_dpcd_bytes_to_write =
- dpcd_bytes_to_read - 1;
-
for (retry = 0; retry < 3; retry++) {
- u8 wret;
-
- wret = drm_dp_dpcd_write(
- &aconnector->dm_dp_aux.aux,
- dpcd_addr + 1,
- &esi[1],
- ack_dpcd_bytes_to_write);
- if (wret == ack_dpcd_bytes_to_write)
+ ssize_t wret;
+
+ wret = drm_dp_dpcd_writeb(&aconnector->dm_dp_aux.aux,
+ dpcd_addr + 1,
+ ack[1]);
+ if (wret == 1)
break;
}
+ if (retry == 3) {
+ DRM_ERROR("Failed to ack MST event.\n");
+ return;
+ }
+
+ drm_dp_mst_hpd_irq_send_new_request(&aconnector->mst_mgr);
/* check if there is new irq to be handled */
dret = drm_dp_dpcd_read(
&aconnector->dm_dp_aux.aux,
@@ -5331,21 +5337,44 @@ get_aspect_ratio(const struct drm_display_mode *mode_in)
}
static enum dc_color_space
-get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing)
+get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing,
+ const struct drm_connector_state *connector_state)
{
enum dc_color_space color_space = COLOR_SPACE_SRGB;
- switch (dc_crtc_timing->pixel_encoding) {
- case PIXEL_ENCODING_YCBCR422:
- case PIXEL_ENCODING_YCBCR444:
- case PIXEL_ENCODING_YCBCR420:
- {
+ switch (connector_state->colorspace) {
+ case DRM_MODE_COLORIMETRY_BT601_YCC:
+ if (dc_crtc_timing->flags.Y_ONLY)
+ color_space = COLOR_SPACE_YCBCR601_LIMITED;
+ else
+ color_space = COLOR_SPACE_YCBCR601;
+ break;
+ case DRM_MODE_COLORIMETRY_BT709_YCC:
+ if (dc_crtc_timing->flags.Y_ONLY)
+ color_space = COLOR_SPACE_YCBCR709_LIMITED;
+ else
+ color_space = COLOR_SPACE_YCBCR709;
+ break;
+ case DRM_MODE_COLORIMETRY_OPRGB:
+ color_space = COLOR_SPACE_ADOBERGB;
+ break;
+ case DRM_MODE_COLORIMETRY_BT2020_RGB:
+ case DRM_MODE_COLORIMETRY_BT2020_YCC:
+ if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
+ color_space = COLOR_SPACE_2020_RGB_FULLRANGE;
+ else
+ color_space = COLOR_SPACE_2020_YCBCR;
+ break;
+ case DRM_MODE_COLORIMETRY_DEFAULT: // ITU601
+ default:
+ if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) {
+ color_space = COLOR_SPACE_SRGB;
/*
* 27030khz is the separation point between HDTV and SDTV
* according to HDMI spec, we use YCbCr709 and YCbCr601
* respectively
*/
- if (dc_crtc_timing->pix_clk_100hz > 270300) {
+ } else if (dc_crtc_timing->pix_clk_100hz > 270300) {
if (dc_crtc_timing->flags.Y_ONLY)
color_space =
COLOR_SPACE_YCBCR709_LIMITED;
@@ -5358,15 +5387,6 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing)
else
color_space = COLOR_SPACE_YCBCR601;
}
-
- }
- break;
- case PIXEL_ENCODING_RGB:
- color_space = COLOR_SPACE_SRGB;
- break;
-
- default:
- WARN_ON(1);
break;
}
@@ -5505,7 +5525,7 @@ static void fill_stream_properties_from_drm_display_mode(
}
}
- stream->output_color_space = get_output_color_space(timing_out);
+ stream->output_color_space = get_output_color_space(timing_out, connector_state);
}
static void fill_audio_info(struct audio_info *audio_info,
@@ -5947,15 +5967,14 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
{
struct drm_display_mode *preferred_mode = NULL;
struct drm_connector *drm_connector;
- const struct drm_connector_state *con_state =
- dm_state ? &dm_state->base : NULL;
+ const struct drm_connector_state *con_state = &dm_state->base;
struct dc_stream_state *stream = NULL;
struct drm_display_mode mode;
struct drm_display_mode saved_mode;
struct drm_display_mode *freesync_mode = NULL;
bool native_mode_found = false;
bool recalculate_timing = false;
- bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false;
+ bool scale = dm_state->scaling != RMX_OFF;
int mode_refresh;
int preferred_refresh = 0;
enum color_transfer_func tf = TRANSFER_FUNC_UNKNOWN;
@@ -6018,8 +6037,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
*/
DRM_DEBUG_DRIVER("No preferred mode found\n");
} else {
- recalculate_timing = amdgpu_freesync_vid_mode &&
- is_freesync_video_mode(&mode, aconnector);
+ recalculate_timing = is_freesync_video_mode(&mode, aconnector);
if (recalculate_timing) {
freesync_mode = get_highest_refresh_rate_mode(aconnector, false);
drm_mode_copy(&saved_mode, &mode);
@@ -6034,7 +6052,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
if (recalculate_timing)
drm_mode_set_crtcinfo(&saved_mode, 0);
- else if (!dm_state)
+ else
drm_mode_set_crtcinfo(&mode, 0);
/*
@@ -6347,6 +6365,31 @@ amdgpu_dm_connector_late_register(struct drm_connector *connector)
return 0;
}
+static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector)
+{
+ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+ struct dc_link *dc_link = aconnector->dc_link;
+ struct dc_sink *dc_em_sink = aconnector->dc_em_sink;
+ struct edid *edid;
+
+ if (!connector->edid_override)
+ return;
+
+ drm_edid_override_connector_update(&aconnector->base);
+ edid = aconnector->base.edid_blob_ptr->data;
+ aconnector->edid = edid;
+
+ /* Update emulated (virtual) sink's EDID */
+ if (dc_em_sink && dc_link) {
+ memset(&dc_em_sink->edid_caps, 0, sizeof(struct dc_edid_caps));
+ memmove(dc_em_sink->dc_edid.raw_edid, edid, (edid->extensions + 1) * EDID_LENGTH);
+ dm_helpers_parse_edid_caps(
+ dc_link,
+ &dc_em_sink->dc_edid,
+ &dc_em_sink->edid_caps);
+ }
+}
+
static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
.reset = amdgpu_dm_connector_funcs_reset,
.detect = amdgpu_dm_connector_detect,
@@ -6357,7 +6400,8 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
.atomic_set_property = amdgpu_dm_connector_atomic_set_property,
.atomic_get_property = amdgpu_dm_connector_atomic_get_property,
.late_register = amdgpu_dm_connector_late_register,
- .early_unregister = amdgpu_dm_connector_unregister
+ .early_unregister = amdgpu_dm_connector_unregister,
+ .force = amdgpu_dm_connector_funcs_force
};
static int get_modes(struct drm_connector *connector)
@@ -6374,11 +6418,19 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
struct edid *edid;
if (!aconnector->base.edid_blob_ptr) {
- DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n",
- aconnector->base.name);
+ /* if connector->edid_override valid, pass
+ * it to edid_override to edid_blob_ptr
+ */
- aconnector->base.force = DRM_FORCE_OFF;
- return;
+ drm_edid_override_connector_update(&aconnector->base);
+
+ if (!aconnector->base.edid_blob_ptr) {
+ DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n",
+ aconnector->base.name);
+
+ aconnector->base.force = DRM_FORCE_OFF;
+ return;
+ }
}
edid = (struct edid *) aconnector->base.edid_blob_ptr->data;
@@ -6563,7 +6615,9 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec
goto fail;
}
- stream = create_validate_stream_for_sink(aconnector, mode, NULL, NULL);
+ stream = create_validate_stream_for_sink(aconnector, mode,
+ to_dm_connector_state(connector->state),
+ NULL);
if (stream) {
dc_stream_release(stream);
result = MODE_OK;
@@ -6657,6 +6711,14 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
if (!crtc)
return 0;
+ if (new_con_state->colorspace != old_con_state->colorspace) {
+ new_crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(new_crtc_state))
+ return PTR_ERR(new_crtc_state);
+
+ new_crtc_state->mode_changed = true;
+ }
+
if (!drm_connector_atomic_hdr_metadata_equal(old_con_state, new_con_state)) {
struct dc_info_packet hdr_infopacket;
@@ -6679,7 +6741,7 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
* set is permissible, however. So only force a
* modeset if we're entering or exiting HDR.
*/
- new_crtc_state->mode_changed =
+ new_crtc_state->mode_changed = new_crtc_state->mode_changed ||
!old_con_state->hdr_output_metadata ||
!new_con_state->hdr_output_metadata;
}
@@ -7168,7 +7230,7 @@ static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connect
struct amdgpu_dm_connector *amdgpu_dm_connector =
to_amdgpu_dm_connector(connector);
- if (!(amdgpu_freesync_vid_mode && edid))
+ if (!edid)
return;
if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
@@ -7210,6 +7272,12 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
return amdgpu_dm_connector->num_modes;
}
+static const u32 supported_colorspaces =
+ BIT(DRM_MODE_COLORIMETRY_BT709_YCC) |
+ BIT(DRM_MODE_COLORIMETRY_OPRGB) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_RGB) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_YCC);
+
void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
struct amdgpu_dm_connector *aconnector,
int connector_type,
@@ -7290,6 +7358,15 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
adev->mode_info.abm_level_property, 0);
}
+ if (connector_type == DRM_MODE_CONNECTOR_HDMIA) {
+ if (!drm_mode_create_hdmi_colorspace_property(&aconnector->base, supported_colorspaces))
+ drm_connector_attach_colorspace_property(&aconnector->base);
+ } else if (connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+ connector_type == DRM_MODE_CONNECTOR_eDP) {
+ if (!drm_mode_create_dp_colorspace_property(&aconnector->base, supported_colorspaces))
+ drm_connector_attach_colorspace_property(&aconnector->base);
+ }
+
if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector_type == DRM_MODE_CONNECTOR_eDP) {
@@ -8884,10 +8961,17 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_helper_cleanup_planes(dev, state);
- /* return the stolen vga memory back to VRAM */
- if (!adev->mman.keep_stolen_vga_memory)
- amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL);
- amdgpu_bo_free_kernel(&adev->mman.stolen_extended_memory, NULL, NULL);
+ /* Don't free the memory if we are hitting this as part of suspend.
+ * This way we don't free any memory during suspend; see
+ * amdgpu_bo_free_kernel(). The memory will be freed in the first
+ * non-suspend modeset or when the driver is torn down.
+ */
+ if (!adev->in_suspend) {
+ /* return the stolen vga memory back to VRAM */
+ if (!adev->mman.keep_stolen_vga_memory)
+ amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL);
+ amdgpu_bo_free_kernel(&adev->mman.stolen_extended_memory, NULL, NULL);
+ }
/*
* Finally, drop a runtime PM reference for each newly disabled CRTC,
@@ -9221,8 +9305,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
* TODO: Refactor this function to allow this check to work
* in all conditions.
*/
- if (amdgpu_freesync_vid_mode &&
- dm_new_crtc_state->stream &&
+ if (dm_new_crtc_state->stream &&
is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state))
goto skip_modeset;
@@ -9264,7 +9347,9 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
}
/* Now check if we should set freesync video mode */
- if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream &&
+ if (dm_new_crtc_state->stream &&
+ dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) &&
+ dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream) &&
is_timing_unchanged_for_freesync(new_crtc_state,
old_crtc_state)) {
new_crtc_state->mode_changed = false;
@@ -9276,7 +9361,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
set_freesync_fixed_config(dm_new_crtc_state);
goto skip_modeset;
- } else if (amdgpu_freesync_vid_mode && aconnector &&
+ } else if (aconnector &&
is_freesync_video_mode(&new_crtc_state->mode,
aconnector)) {
struct drm_display_mode *high_mode;
@@ -10336,7 +10421,7 @@ static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
input->cea_total_length = total_length;
memcpy(input->payload, data, length);
- res = dc_dmub_srv_cmd_with_reply_data(dm->dc->ctx->dmub_srv, &cmd);
+ res = dm_execute_dmub_cmd(dm->dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY);
if (!res) {
DRM_ERROR("EDID CEA parser failed\n");
return false;
@@ -10786,3 +10871,13 @@ bool check_seamless_boot_capability(struct amdgpu_device *adev)
return false;
}
+
+bool dm_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
+{
+ return dc_dmub_srv_cmd_run(ctx->dmub_srv, cmd, wait_type);
+}
+
+bool dm_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
+{
+ return dc_dmub_srv_cmd_run_list(ctx->dmub_srv, count, cmd, wait_type);
+}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 2e2413fd73a4..4561f55afa99 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -661,10 +661,6 @@ struct amdgpu_dm_connector {
struct mutex hpd_lock;
bool fake_enable;
-#ifdef CONFIG_DEBUG_FS
- uint32_t debugfs_dpcd_address;
- uint32_t debugfs_dpcd_size;
-#endif
bool force_yuv420_output;
struct dsc_preferred_settings dsc_settings;
union dp_downstream_port_present mst_downstream_port_present;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index 27711743c22c..0802f8e8fac5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -83,12 +83,15 @@ const char *const *amdgpu_dm_crtc_get_crc_sources(struct drm_crtc *crtc,
}
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
-static void amdgpu_dm_set_crc_window_default(struct drm_crtc *crtc)
+static void amdgpu_dm_set_crc_window_default(struct drm_crtc *crtc, struct dc_stream_state *stream)
{
struct drm_device *drm_dev = crtc->dev;
+ struct amdgpu_display_manager *dm = &drm_to_adev(drm_dev)->dm;
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+ bool was_activated;
spin_lock_irq(&drm_dev->event_lock);
+ was_activated = acrtc->dm_irq_params.window_param.activated;
acrtc->dm_irq_params.window_param.x_start = 0;
acrtc->dm_irq_params.window_param.y_start = 0;
acrtc->dm_irq_params.window_param.x_end = 0;
@@ -97,6 +100,14 @@ static void amdgpu_dm_set_crc_window_default(struct drm_crtc *crtc)
acrtc->dm_irq_params.window_param.update_win = false;
acrtc->dm_irq_params.window_param.skip_frame_cnt = 0;
spin_unlock_irq(&drm_dev->event_lock);
+
+ /* Disable secure_display if it was enabled */
+ if (was_activated) {
+ /* stop ROI update on this crtc */
+ flush_work(&dm->secure_display_ctxs[crtc->index].notify_ta_work);
+ flush_work(&dm->secure_display_ctxs[crtc->index].forward_roi_work);
+ dc_stream_forward_crc_window(stream, NULL, true);
+ }
}
static void amdgpu_dm_crtc_notify_ta_to_read(struct work_struct *work)
@@ -204,9 +215,6 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
struct dm_crtc_state *dm_crtc_state,
enum amdgpu_dm_pipe_crc_source source)
{
-#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
- int i;
-#endif
struct amdgpu_device *adev = drm_to_adev(crtc->dev);
struct dc_stream_state *stream_state = dm_crtc_state->stream;
bool enable = amdgpu_dm_is_valid_crc_source(source);
@@ -220,19 +228,6 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
/* Enable or disable CRTC CRC generation */
if (dm_is_crc_source_crtc(source) || source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE) {
-#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
- /* Disable secure_display if it was enabled */
- if (!enable) {
- for (i = 0; i < adev->mode_info.num_crtc; i++) {
- if (adev->dm.secure_display_ctxs[i].crtc == crtc) {
- /* stop ROI update on this crtc */
- flush_work(&adev->dm.secure_display_ctxs[i].notify_ta_work);
- flush_work(&adev->dm.secure_display_ctxs[i].forward_roi_work);
- dc_stream_forward_crc_window(stream_state, NULL, true);
- }
- }
- }
-#endif
if (!dc_stream_configure_crc(stream_state->ctx->dc,
stream_state, NULL, enable, enable)) {
ret = -EINVAL;
@@ -363,7 +358,7 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
/* Reset secure_display when we change crc source from debugfs */
- amdgpu_dm_set_crc_window_default(crtc);
+ amdgpu_dm_set_crc_window_default(crtc, crtc_state->stream);
#endif
if (amdgpu_dm_crtc_configure_crc_source(crtc, crtc_state, source)) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
index 935adca6f048..748e80ef40d0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
@@ -100,7 +100,7 @@ struct secure_display_context *amdgpu_dm_crtc_secure_display_create_contexts(
#else
#define amdgpu_dm_crc_window_is_activated(x)
#define amdgpu_dm_crtc_handle_crc_window_irq(x)
-#define amdgpu_dm_crtc_secure_display_create_contexts()
+#define amdgpu_dm_crtc_secure_display_create_contexts(x)
#endif
#endif /* AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_ */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 827fcb4fb3b3..5ea3284b2b77 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -907,6 +907,61 @@ unlock:
DEFINE_SHOW_ATTRIBUTE(amdgpu_current_bpc);
/*
+ * Returns the current colorspace for the crtc.
+ * Example usage: cat /sys/kernel/debug/dri/0/crtc-0/amdgpu_current_colorspace
+ */
+static int amdgpu_current_colorspace_show(struct seq_file *m, void *data)
+{
+ struct drm_crtc *crtc = m->private;
+ struct drm_device *dev = crtc->dev;
+ struct dm_crtc_state *dm_crtc_state = NULL;
+ int res = -ENODEV;
+
+ mutex_lock(&dev->mode_config.mutex);
+ drm_modeset_lock(&crtc->mutex, NULL);
+ if (crtc->state == NULL)
+ goto unlock;
+
+ dm_crtc_state = to_dm_crtc_state(crtc->state);
+ if (dm_crtc_state->stream == NULL)
+ goto unlock;
+
+ switch (dm_crtc_state->stream->output_color_space) {
+ case COLOR_SPACE_SRGB:
+ seq_printf(m, "sRGB");
+ break;
+ case COLOR_SPACE_YCBCR601:
+ case COLOR_SPACE_YCBCR601_LIMITED:
+ seq_printf(m, "BT601_YCC");
+ break;
+ case COLOR_SPACE_YCBCR709:
+ case COLOR_SPACE_YCBCR709_LIMITED:
+ seq_printf(m, "BT709_YCC");
+ break;
+ case COLOR_SPACE_ADOBERGB:
+ seq_printf(m, "opRGB");
+ break;
+ case COLOR_SPACE_2020_RGB_FULLRANGE:
+ seq_printf(m, "BT2020_RGB");
+ break;
+ case COLOR_SPACE_2020_YCBCR:
+ seq_printf(m, "BT2020_YCC");
+ break;
+ default:
+ goto unlock;
+ }
+ res = 0;
+
+unlock:
+ drm_modeset_unlock(&crtc->mutex);
+ mutex_unlock(&dev->mode_config.mutex);
+
+ return res;
+}
+DEFINE_SHOW_ATTRIBUTE(amdgpu_current_colorspace);
+
+
+/*
* Example usage:
* Disable dsc passthrough, i.e.,: have dsc decoding at converver, not external RX
* echo 1 /sys/kernel/debug/dri/0/DP-1/dsc_disable_passthrough
@@ -1039,88 +1094,6 @@ static ssize_t dp_sdp_message_debugfs_write(struct file *f, const char __user *b
return write_size;
}
-static ssize_t dp_dpcd_address_write(struct file *f, const char __user *buf,
- size_t size, loff_t *pos)
-{
- int r;
- struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
-
- if (size < sizeof(connector->debugfs_dpcd_address))
- return -EINVAL;
-
- r = copy_from_user(&connector->debugfs_dpcd_address,
- buf, sizeof(connector->debugfs_dpcd_address));
-
- return size - r;
-}
-
-static ssize_t dp_dpcd_size_write(struct file *f, const char __user *buf,
- size_t size, loff_t *pos)
-{
- int r;
- struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
-
- if (size < sizeof(connector->debugfs_dpcd_size))
- return -EINVAL;
-
- r = copy_from_user(&connector->debugfs_dpcd_size,
- buf, sizeof(connector->debugfs_dpcd_size));
-
- if (connector->debugfs_dpcd_size > 256)
- connector->debugfs_dpcd_size = 0;
-
- return size - r;
-}
-
-static ssize_t dp_dpcd_data_write(struct file *f, const char __user *buf,
- size_t size, loff_t *pos)
-{
- int r;
- char *data;
- struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
- struct dc_link *link = connector->dc_link;
- uint32_t write_size = connector->debugfs_dpcd_size;
-
- if (!write_size || size < write_size)
- return -EINVAL;
-
- data = kzalloc(write_size, GFP_KERNEL);
- if (!data)
- return 0;
-
- r = copy_from_user(data, buf, write_size);
-
- dm_helpers_dp_write_dpcd(link->ctx, link,
- connector->debugfs_dpcd_address, data, write_size - r);
- kfree(data);
- return write_size - r;
-}
-
-static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf,
- size_t size, loff_t *pos)
-{
- int r;
- char *data;
- struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
- struct dc_link *link = connector->dc_link;
- uint32_t read_size = connector->debugfs_dpcd_size;
-
- if (!read_size || size < read_size)
- return 0;
-
- data = kzalloc(read_size, GFP_KERNEL);
- if (!data)
- return 0;
-
- dm_helpers_dp_read_dpcd(link->ctx, link,
- connector->debugfs_dpcd_address, data, read_size);
-
- r = copy_to_user(buf, data, read_size);
-
- kfree(data);
- return read_size - r;
-}
-
/* function: Read link's DSC & FEC capabilities
*
*
@@ -2682,25 +2655,6 @@ static const struct file_operations sdp_message_fops = {
.llseek = default_llseek
};
-static const struct file_operations dp_dpcd_address_debugfs_fops = {
- .owner = THIS_MODULE,
- .write = dp_dpcd_address_write,
- .llseek = default_llseek
-};
-
-static const struct file_operations dp_dpcd_size_debugfs_fops = {
- .owner = THIS_MODULE,
- .write = dp_dpcd_size_write,
- .llseek = default_llseek
-};
-
-static const struct file_operations dp_dpcd_data_debugfs_fops = {
- .owner = THIS_MODULE,
- .read = dp_dpcd_data_read,
- .write = dp_dpcd_data_write,
- .llseek = default_llseek
-};
-
static const struct file_operations dp_max_bpc_debugfs_fops = {
.owner = THIS_MODULE,
.read = dp_max_bpc_read,
@@ -2724,9 +2678,6 @@ static const struct {
{"test_pattern", &dp_phy_test_pattern_fops},
{"hdcp_sink_capability", &hdcp_sink_capability_fops},
{"sdp_message", &sdp_message_fops},
- {"aux_dpcd_address", &dp_dpcd_address_debugfs_fops},
- {"aux_dpcd_size", &dp_dpcd_size_debugfs_fops},
- {"aux_dpcd_data", &dp_dpcd_data_debugfs_fops},
{"dsc_clock_en", &dp_dsc_clock_en_debugfs_fops},
{"dsc_slice_width", &dp_dsc_slice_width_debugfs_fops},
{"dsc_slice_height", &dp_dsc_slice_height_debugfs_fops},
@@ -2809,6 +2760,32 @@ static int psr_read_residency(void *data, u64 *val)
return 0;
}
+/* read allow_edp_hotplug_detection */
+static int allow_edp_hotplug_detection_get(void *data, u64 *val)
+{
+ struct amdgpu_dm_connector *aconnector = data;
+ struct drm_connector *connector = &aconnector->base;
+ struct drm_device *dev = connector->dev;
+ struct amdgpu_device *adev = drm_to_adev(dev);
+
+ *val = adev->dm.dc->config.allow_edp_hotplug_detection;
+
+ return 0;
+}
+
+/* set allow_edp_hotplug_detection */
+static int allow_edp_hotplug_detection_set(void *data, u64 val)
+{
+ struct amdgpu_dm_connector *aconnector = data;
+ struct drm_connector *connector = &aconnector->base;
+ struct drm_device *dev = connector->dev;
+ struct amdgpu_device *adev = drm_to_adev(dev);
+
+ adev->dm.dc->config.allow_edp_hotplug_detection = (uint32_t) val;
+
+ return 0;
+}
+
/*
* Set dmcub trace event IRQ enable or disable.
* Usage to enable dmcub trace event IRQ: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dmcub_trace_event_en
@@ -2847,6 +2824,10 @@ DEFINE_DEBUGFS_ATTRIBUTE(psr_fops, psr_get, NULL, "%llu\n");
DEFINE_DEBUGFS_ATTRIBUTE(psr_residency_fops, psr_read_residency, NULL,
"%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(allow_edp_hotplug_detection_fops,
+ allow_edp_hotplug_detection_get,
+ allow_edp_hotplug_detection_set, "%llu\n");
+
DEFINE_SHOW_ATTRIBUTE(current_backlight);
DEFINE_SHOW_ATTRIBUTE(target_backlight);
@@ -3017,6 +2998,8 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector)
&target_backlight_fops);
debugfs_create_file("ilr_setting", 0644, dir, connector,
&edp_ilr_debugfs_fops);
+ debugfs_create_file("allow_edp_hotplug_detection", 0644, dir, connector,
+ &allow_edp_hotplug_detection_fops);
}
for (i = 0; i < ARRAY_SIZE(connector_debugfs_entries); i++) {
@@ -3025,9 +3008,6 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector)
connector_debugfs_entries[i].fops);
}
- connector->debugfs_dpcd_address = 0;
- connector->debugfs_dpcd_size = 0;
-
if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA) {
for (i = 0; i < ARRAY_SIZE(hdmi_debugfs_entries); i++) {
debugfs_create_file(hdmi_debugfs_entries[i].name,
@@ -3246,6 +3226,8 @@ void crtc_debugfs_init(struct drm_crtc *crtc)
#endif
debugfs_create_file("amdgpu_current_bpc", 0644, crtc->debugfs_entry,
crtc, &amdgpu_current_bpc_fops);
+ debugfs_create_file("amdgpu_current_colorspace", 0644, crtc->debugfs_entry,
+ crtc, &amdgpu_current_colorspace_fops);
}
/*
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index c6ce2b7123b7..cd20cfc04996 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -44,9 +44,6 @@
#include "dm_helpers.h"
#include "ddc_service_types.h"
-/* MST Dock */
-static const uint8_t SYNAPTICS_DEVICE_ID[] = "SYNA";
-
/* dm_helpers_parse_edid_caps
*
* Parse edid caps
@@ -702,6 +699,9 @@ static void apply_synaptics_fifo_reset_wa(struct drm_dp_aux *aux)
DC_LOG_DC("Done apply_synaptics_fifo_reset_wa\n");
}
+/* MST Dock */
+static const uint8_t SYNAPTICS_DEVICE_ID[] = "SYNA";
+
static uint8_t write_dsc_enable_synaptics_non_virtual_dpcd_mst(
struct drm_dp_aux *aux,
const struct dc_stream_state *stream,
@@ -885,10 +885,34 @@ enum dc_edid_status dm_helpers_read_local_edid(
DRM_ERROR("EDID err: %d, on connector: %s",
edid_status,
aconnector->base.name);
+ if (link->aux_mode) {
+ union test_request test_request = {0};
+ union test_response test_response = {0};
- /* DP Compliance Test 4.2.2.3 */
- if (link->aux_mode)
- drm_dp_send_real_edid_checksum(&aconnector->dm_dp_aux.aux, sink->dc_edid.raw_edid[sink->dc_edid.length-1]);
+ dm_helpers_dp_read_dpcd(ctx,
+ link,
+ DP_TEST_REQUEST,
+ &test_request.raw,
+ sizeof(union test_request));
+
+ if (!test_request.bits.EDID_READ)
+ return edid_status;
+
+ test_response.bits.EDID_CHECKSUM_WRITE = 1;
+
+ dm_helpers_dp_write_dpcd(ctx,
+ link,
+ DP_TEST_EDID_CHECKSUM,
+ &sink->dc_edid.raw_edid[sink->dc_edid.length-1],
+ 1);
+
+ dm_helpers_dp_write_dpcd(ctx,
+ link,
+ DP_TEST_RESPONSE,
+ &test_response.raw,
+ sizeof(test_response));
+
+ }
return edid_status;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 810ab682f424..46d0a8f57e55 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -45,8 +45,7 @@
#endif
#include "dc/dcn20/dcn20_resource.h"
-bool is_timing_changed(struct dc_stream_state *cur_stream,
- struct dc_stream_state *new_stream);
+
#define PEAK_FACTOR_X1000 1006
static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
@@ -1422,7 +1421,7 @@ int pre_validate_dsc(struct drm_atomic_state *state,
struct dc_stream_state *stream = dm_state->context->streams[i];
if (local_dc_state->streams[i] &&
- is_timing_changed(stream, local_dc_state->streams[i])) {
+ dc_is_timing_changed(stream, local_dc_state->streams[i])) {
DRM_INFO_ONCE("crtc[%d] needs mode_changed\n", i);
} else {
int ind = find_crtc_index_in_state_by_stream(state, stream);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
index c42aa947c969..172aa10a8800 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
@@ -33,6 +33,8 @@
#include <asm/cputable.h>
#elif defined(CONFIG_ARM64)
#include <asm/neon.h>
+#elif defined(CONFIG_LOONGARCH)
+#include <asm/fpu.h>
#endif
/**
@@ -88,7 +90,7 @@ void dc_fpu_begin(const char *function_name, const int line)
*pcpu += 1;
if (*pcpu == 1) {
-#if defined(CONFIG_X86)
+#if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
migrate_disable();
kernel_fpu_begin();
#elif defined(CONFIG_PPC64)
@@ -128,7 +130,7 @@ void dc_fpu_end(const char *function_name, const int line)
pcpu = get_cpu_ptr(&fpu_recursion_depth);
*pcpu -= 1;
if (*pcpu <= 0) {
-#if defined(CONFIG_X86)
+#if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
kernel_fpu_end();
migrate_enable();
#elif defined(CONFIG_PPC64)
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
index 1ef9e4053bb7..90a02d7bd3da 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
@@ -123,9 +123,7 @@ static void encoder_control_dmcub(
sizeof(cmd.digx_encoder_control.header);
cmd.digx_encoder_control.encoder_control.dig.stream_param = *dig;
- dc_dmub_srv_cmd_queue(dmcub, &cmd);
- dc_dmub_srv_cmd_execute(dmcub);
- dc_dmub_srv_wait_idle(dmcub);
+ dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static enum bp_result encoder_control_digx_v1_5(
@@ -261,9 +259,7 @@ static void transmitter_control_dmcub(
sizeof(cmd.dig1_transmitter_control.header);
cmd.dig1_transmitter_control.transmitter_control.dig = *dig;
- dc_dmub_srv_cmd_queue(dmcub, &cmd);
- dc_dmub_srv_cmd_execute(dmcub);
- dc_dmub_srv_wait_idle(dmcub);
+ dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static enum bp_result transmitter_control_v1_6(
@@ -325,9 +321,7 @@ static void transmitter_control_dmcub_v1_7(
sizeof(cmd.dig1_transmitter_control.header);
cmd.dig1_transmitter_control.transmitter_control.dig_v1_7 = *dig;
- dc_dmub_srv_cmd_queue(dmcub, &cmd);
- dc_dmub_srv_cmd_execute(dmcub);
- dc_dmub_srv_wait_idle(dmcub);
+ dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static enum bp_result transmitter_control_v1_7(
@@ -435,9 +429,7 @@ static void set_pixel_clock_dmcub(
sizeof(cmd.set_pixel_clock.header);
cmd.set_pixel_clock.pixel_clock.clk = *clk;
- dc_dmub_srv_cmd_queue(dmcub, &cmd);
- dc_dmub_srv_cmd_execute(dmcub);
- dc_dmub_srv_wait_idle(dmcub);
+ dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static enum bp_result set_pixel_clock_v7(
@@ -804,9 +796,7 @@ static void enable_disp_power_gating_dmcub(
sizeof(cmd.enable_disp_power_gating.header);
cmd.enable_disp_power_gating.power_gating.pwr = *pwr;
- dc_dmub_srv_cmd_queue(dmcub, &cmd);
- dc_dmub_srv_cmd_execute(dmcub);
- dc_dmub_srv_wait_idle(dmcub);
+ dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static enum bp_result enable_disp_power_gating_v2_1(
@@ -1016,10 +1006,7 @@ static void enable_lvtma_control_dmcub(
panel_instance;
cmd.lvtma_control.data.bypass_panel_control_wait =
bypass_panel_control_wait;
- dc_dmub_srv_cmd_queue(dmcub, &cmd);
- dc_dmub_srv_cmd_execute(dmcub);
- dc_dmub_srv_wait_idle(dmcub);
-
+ dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static enum bp_result enable_lvtma_control(
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c
index 934e6423dc1a..1f36ad8a7de4 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c
@@ -111,12 +111,10 @@ int dce112_set_clock(struct clk_mgr *clk_mgr_base, int requested_clk_khz)
bp->funcs->set_dce_clock(bp, &dce_clk_params);
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
- if (clk_mgr_dce->dfs_bypass_disp_clk != actual_clock)
- dmcu->funcs->set_psr_wait_loop(dmcu,
- actual_clock / 1000 / 7);
- }
+ if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
+ if (clk_mgr_dce->dfs_bypass_disp_clk != actual_clock)
+ dmcu->funcs->set_psr_wait_loop(dmcu,
+ actual_clock / 1000 / 7);
}
clk_mgr_dce->dfs_bypass_disp_clk = actual_clock;
@@ -153,12 +151,10 @@ int dce112_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_clk_khz)
clk_mgr->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL;
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
- if (clk_mgr->dfs_bypass_disp_clk != actual_clock)
- dmcu->funcs->set_psr_wait_loop(dmcu,
- actual_clock / 1000 / 7);
- }
+ if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
+ if (clk_mgr->dfs_bypass_disp_clk != actual_clock)
+ dmcu->funcs->set_psr_wait_loop(dmcu,
+ actual_clock / 1000 / 7);
}
clk_mgr->dfs_bypass_disp_clk = actual_clock;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c
index 450eaead4f20..89b79dd39628 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c
@@ -135,12 +135,10 @@ int rv1_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_di
VBIOSSMC_MSG_SetDispclkFreq,
khz_to_mhz_ceil(requested_dispclk_khz));
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
- if (clk_mgr->dfs_bypass_disp_clk != actual_dispclk_set_mhz)
- dmcu->funcs->set_psr_wait_loop(dmcu,
- actual_dispclk_set_mhz / 7);
- }
+ if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
+ if (clk_mgr->dfs_bypass_disp_clk != actual_dispclk_set_mhz)
+ dmcu->funcs->set_psr_wait_loop(dmcu,
+ actual_dispclk_set_mhz / 7);
}
return actual_dispclk_set_mhz * 1000;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
index 650f3b4b562e..c435f7632e8e 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
@@ -531,6 +531,11 @@ void dcn20_clk_mgr_construct(
struct pp_smu_funcs *pp_smu,
struct dccg *dccg)
{
+ int dprefclk_did;
+ int target_div;
+ uint32_t pll_req_reg;
+ struct fixed31_32 pll_req;
+
clk_mgr->base.ctx = ctx;
clk_mgr->pp_smu = pp_smu;
clk_mgr->base.funcs = &dcn2_funcs;
@@ -547,42 +552,34 @@ void dcn20_clk_mgr_construct(
clk_mgr->base.dprefclk_khz = 700000; // 700 MHz planned if VCO is 3.85 GHz, will be retrieved
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
- dcn2_funcs.update_clocks = dcn2_update_clocks_fpga;
- clk_mgr->base.dentist_vco_freq_khz = 3850000;
+ /* DFS Slice 2 should be used for DPREFCLK */
+ dprefclk_did = REG_READ(CLK3_CLK2_DFS_CNTL);
+ /* Convert DPREFCLK DFS Slice DID to actual divider */
+ target_div = dentist_get_divider_from_did(dprefclk_did);
+ /* get FbMult value */
+ pll_req_reg = REG_READ(CLK3_CLK_PLL_REQ);
- } else {
- /* DFS Slice 2 should be used for DPREFCLK */
- int dprefclk_did = REG_READ(CLK3_CLK2_DFS_CNTL);
- /* Convert DPREFCLK DFS Slice DID to actual divider*/
- int target_div = dentist_get_divider_from_did(dprefclk_did);
-
- /* get FbMult value */
- uint32_t pll_req_reg = REG_READ(CLK3_CLK_PLL_REQ);
- struct fixed31_32 pll_req;
-
- /* set up a fixed-point number
- * this works because the int part is on the right edge of the register
- * and the frac part is on the left edge
- */
+ /* set up a fixed-point number
+ * this works because the int part is on the right edge of the register
+ * and the frac part is on the left edge
+ */
- pll_req = dc_fixpt_from_int(pll_req_reg & clk_mgr->clk_mgr_mask->FbMult_int);
- pll_req.value |= pll_req_reg & clk_mgr->clk_mgr_mask->FbMult_frac;
+ pll_req = dc_fixpt_from_int(pll_req_reg & clk_mgr->clk_mgr_mask->FbMult_int);
+ pll_req.value |= pll_req_reg & clk_mgr->clk_mgr_mask->FbMult_frac;
- /* multiply by REFCLK period */
- pll_req = dc_fixpt_mul_int(pll_req, 100000);
+ /* multiply by REFCLK period */
+ pll_req = dc_fixpt_mul_int(pll_req, 100000);
- /* integer part is now VCO frequency in kHz */
- clk_mgr->base.dentist_vco_freq_khz = dc_fixpt_floor(pll_req);
+ /* integer part is now VCO frequency in kHz */
+ clk_mgr->base.dentist_vco_freq_khz = dc_fixpt_floor(pll_req);
- /* in case we don't get a value from the register, use default */
- if (clk_mgr->base.dentist_vco_freq_khz == 0)
- clk_mgr->base.dentist_vco_freq_khz = 3850000;
+ /* in case we don't get a value from the register, use default */
+ if (clk_mgr->base.dentist_vco_freq_khz == 0)
+ clk_mgr->base.dentist_vco_freq_khz = 3850000;
- /* Calculate the DPREFCLK in kHz.*/
- clk_mgr->base.dprefclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR
- * clk_mgr->base.dentist_vco_freq_khz) / target_div;
- }
+ /* Calculate the DPREFCLK in kHz.*/
+ clk_mgr->base.dprefclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR
+ * clk_mgr->base.dentist_vco_freq_khz) / target_div;
//Integrated_info table does not exist on dGPU projects so should not be referenced
//anywhere in code for dGPUs.
//Also there is no plan for now that DFS BYPASS will be used on NV10/12/14.
@@ -590,4 +587,3 @@ void dcn20_clk_mgr_construct(
dce_clock_read_ss_info(clk_mgr);
}
-
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c
index 811720749faf..694fe4271b4d 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c
@@ -190,23 +190,17 @@ void dcn201_clk_mgr_construct(struct dc_context *ctx,
clk_mgr->dprefclk_ss_divider = 1000;
clk_mgr->ss_on_dprefclk = false;
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
- dcn201_funcs.update_clocks = dcn2_update_clocks_fpga;
- clk_mgr->base.dprefclk_khz = 600000;
- clk_mgr->base.dentist_vco_freq_khz = 3000000;
- } else {
- clk_mgr->base.dprefclk_khz = REG_READ(CLK4_CLK2_CURRENT_CNT);
- clk_mgr->base.dprefclk_khz *= 100;
+ clk_mgr->base.dprefclk_khz = REG_READ(CLK4_CLK2_CURRENT_CNT);
+ clk_mgr->base.dprefclk_khz *= 100;
- if (clk_mgr->base.dprefclk_khz == 0)
- clk_mgr->base.dprefclk_khz = 600000;
+ if (clk_mgr->base.dprefclk_khz == 0)
+ clk_mgr->base.dprefclk_khz = 600000;
- REG_GET(CLK4_CLK_PLL_REQ, FbMult_int, &clk_mgr->base.dentist_vco_freq_khz);
- clk_mgr->base.dentist_vco_freq_khz *= 100000;
+ REG_GET(CLK4_CLK_PLL_REQ, FbMult_int, &clk_mgr->base.dentist_vco_freq_khz);
+ clk_mgr->base.dentist_vco_freq_khz *= 100000;
- if (clk_mgr->base.dentist_vco_freq_khz == 0)
- clk_mgr->base.dentist_vco_freq_khz = 3000000;
- }
+ if (clk_mgr->base.dentist_vco_freq_khz == 0)
+ clk_mgr->base.dentist_vco_freq_khz = 3000000;
if (!debug->disable_dfs_bypass && bp->integrated_info)
if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
index bd9fd0b54f46..0c6a4ab72b1d 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
@@ -705,6 +705,7 @@ void rn_clk_mgr_construct(
struct dpm_clocks clock_table = { 0 };
enum pp_smu_status status = 0;
int is_green_sardine = 0;
+ struct clk_log_info log_info = {0};
#if defined(CONFIG_DRM_AMD_DC_FP)
is_green_sardine = ASICREV_IS_GREEN_SARDINE(ctx->asic_id.hw_internal_rev);
@@ -725,48 +726,41 @@ void rn_clk_mgr_construct(
clk_mgr->smu_ver = rn_vbios_smu_get_smu_version(clk_mgr);
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
- dcn21_funcs.update_clocks = dcn2_update_clocks_fpga;
+ clk_mgr->periodic_retraining_disabled = rn_vbios_smu_is_periodic_retraining_disabled(clk_mgr);
+
+ /* SMU Version 55.51.0 and up no longer have an issue
+ * that needs to limit minimum dispclk */
+ if (clk_mgr->smu_ver >= SMU_VER_55_51_0)
+ debug->min_disp_clk_khz = 0;
+
+ /* TODO: Check we get what we expect during bringup */
+ clk_mgr->base.dentist_vco_freq_khz = get_vco_frequency_from_reg(clk_mgr);
+
+ /* in case we don't get a value from the register, use default */
+ if (clk_mgr->base.dentist_vco_freq_khz == 0)
clk_mgr->base.dentist_vco_freq_khz = 3600000;
- } else {
- struct clk_log_info log_info = {0};
-
- clk_mgr->periodic_retraining_disabled = rn_vbios_smu_is_periodic_retraining_disabled(clk_mgr);
-
- /* SMU Version 55.51.0 and up no longer have an issue
- * that needs to limit minimum dispclk */
- if (clk_mgr->smu_ver >= SMU_VER_55_51_0)
- debug->min_disp_clk_khz = 0;
-
- /* TODO: Check we get what we expect during bringup */
- clk_mgr->base.dentist_vco_freq_khz = get_vco_frequency_from_reg(clk_mgr);
-
- /* in case we don't get a value from the register, use default */
- if (clk_mgr->base.dentist_vco_freq_khz == 0)
- clk_mgr->base.dentist_vco_freq_khz = 3600000;
-
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) {
- if (clk_mgr->periodic_retraining_disabled) {
- rn_bw_params.wm_table = lpddr4_wm_table_with_disabled_ppt;
- } else {
- if (is_green_sardine)
- rn_bw_params.wm_table = lpddr4_wm_table_gs;
- else
- rn_bw_params.wm_table = lpddr4_wm_table_rn;
- }
+
+ if (ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) {
+ if (clk_mgr->periodic_retraining_disabled) {
+ rn_bw_params.wm_table = lpddr4_wm_table_with_disabled_ppt;
} else {
if (is_green_sardine)
- rn_bw_params.wm_table = ddr4_wm_table_gs;
- else {
- if (ctx->dc->config.is_single_rank_dimm)
- rn_bw_params.wm_table = ddr4_1R_wm_table_rn;
- else
- rn_bw_params.wm_table = ddr4_wm_table_rn;
- }
+ rn_bw_params.wm_table = lpddr4_wm_table_gs;
+ else
+ rn_bw_params.wm_table = lpddr4_wm_table_rn;
+ }
+ } else {
+ if (is_green_sardine)
+ rn_bw_params.wm_table = ddr4_wm_table_gs;
+ else {
+ if (ctx->dc->config.is_single_rank_dimm)
+ rn_bw_params.wm_table = ddr4_1R_wm_table_rn;
+ else
+ rn_bw_params.wm_table = ddr4_wm_table_rn;
}
- /* Saved clocks configured at boot for debug purposes */
- rn_dump_clk_registers(&clk_mgr->base.boot_snapshot, &clk_mgr->base, &log_info);
}
+ /* Saved clocks configured at boot for debug purposes */
+ rn_dump_clk_registers(&clk_mgr->base.boot_snapshot, &clk_mgr->base, &log_info);
clk_mgr->base.dprefclk_khz = 600000;
dce_clock_read_ss_info(clk_mgr);
@@ -786,9 +780,8 @@ void rn_clk_mgr_construct(
}
}
- if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && clk_mgr->smu_ver >= 0x00371500) {
- /* enable powerfeatures when displaycount goes to 0 */
+ /* enable powerfeatures when displaycount goes to 0 */
+ if (clk_mgr->smu_ver >= 0x00371500)
rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(clk_mgr, !debug->disable_48mhz_pwrdwn);
- }
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c
index 27fbe906682f..8c9d45e5b13b 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c
@@ -147,17 +147,14 @@ int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dis
VBIOSSMC_MSG_SetDispclkFreq,
khz_to_mhz_ceil(requested_dispclk_khz));
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
- if (clk_mgr->dfs_bypass_disp_clk != actual_dispclk_set_mhz)
- dmcu->funcs->set_psr_wait_loop(dmcu,
- actual_dispclk_set_mhz / 7);
- }
+ if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
+ if (clk_mgr->dfs_bypass_disp_clk != actual_dispclk_set_mhz)
+ dmcu->funcs->set_psr_wait_loop(dmcu,
+ actual_dispclk_set_mhz / 7);
}
// pmfw always set clock more than or equal requested clock
- if (!IS_DIAG_DC(dc->ctx->dce_environment))
- ASSERT(actual_dispclk_set_mhz >= khz_to_mhz_ceil(requested_dispclk_khz));
+ ASSERT(actual_dispclk_set_mhz >= khz_to_mhz_ceil(requested_dispclk_khz));
return actual_dispclk_set_mhz * 1000;
}
@@ -221,15 +218,13 @@ void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phy
int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
{
int actual_dppclk_set_mhz = -1;
- struct dc *dc = clk_mgr->base.ctx->dc;
actual_dppclk_set_mhz = rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDppclkFreq,
khz_to_mhz_ceil(requested_dpp_khz));
- if (!IS_DIAG_DC(dc->ctx->dce_environment))
- ASSERT(actual_dppclk_set_mhz >= khz_to_mhz_ceil(requested_dpp_khz));
+ ASSERT(actual_dppclk_set_mhz >= khz_to_mhz_ceil(requested_dpp_khz));
return actual_dppclk_set_mhz * 1000;
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
index 694a9d3d92ae..3271c8c7905d 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
@@ -206,7 +206,6 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base,
bool force_reset = false;
bool update_uclk = false;
bool p_state_change_support;
- int total_plane_count;
if (dc->work_arounds.skip_clock_update || !clk_mgr->smu_present)
return;
@@ -247,8 +246,7 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base,
clk_mgr_base->clks.socclk_khz = new_clocks->socclk_khz;
clk_mgr_base->clks.prev_p_state_change_support = clk_mgr_base->clks.p_state_change_support;
- total_plane_count = clk_mgr_helper_get_active_plane_cnt(dc, context);
- p_state_change_support = new_clocks->p_state_change_support || (total_plane_count == 0);
+ p_state_change_support = new_clocks->p_state_change_support;
// invalidate the current P-State forced min in certain dc_mode_softmax situations
if (dc->clk_mgr->dc_mode_softmax_enabled && safe_to_lower && !p_state_change_support) {
@@ -523,6 +521,8 @@ void dcn3_clk_mgr_construct(
struct pp_smu_funcs *pp_smu,
struct dccg *dccg)
{
+ struct clk_state_registers_and_bypass s = { 0 };
+
clk_mgr->base.ctx = ctx;
clk_mgr->base.funcs = &dcn3_funcs;
clk_mgr->regs = &clk_mgr_regs;
@@ -539,27 +539,19 @@ void dcn3_clk_mgr_construct(
clk_mgr->base.dprefclk_khz = 730000; // 700 MHz planned if VCO is 3.85 GHz, will be retrieved
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
- clk_mgr->base.funcs = &dcn3_fpga_funcs;
- clk_mgr->base.dentist_vco_freq_khz = 3650000;
-
- } else {
- struct clk_state_registers_and_bypass s = { 0 };
+ /* integer part is now VCO frequency in kHz */
+ clk_mgr->base.dentist_vco_freq_khz = dcn30_get_vco_frequency_from_reg(clk_mgr);
- /* integer part is now VCO frequency in kHz */
- clk_mgr->base.dentist_vco_freq_khz = dcn30_get_vco_frequency_from_reg(clk_mgr);
-
- /* in case we don't get a value from the register, use default */
- if (clk_mgr->base.dentist_vco_freq_khz == 0)
- clk_mgr->base.dentist_vco_freq_khz = 3650000;
- /* Convert dprefclk units from MHz to KHz */
- /* Value already divided by 10, some resolution lost */
+ /* in case we don't get a value from the register, use default */
+ if (clk_mgr->base.dentist_vco_freq_khz == 0)
+ clk_mgr->base.dentist_vco_freq_khz = 3650000;
+ /* Convert dprefclk units from MHz to KHz */
+ /* Value already divided by 10, some resolution lost */
- /*TODO: uncomment assert once dcn3_dump_clk_registers is implemented */
- //ASSERT(s.dprefclk != 0);
- if (s.dprefclk != 0)
- clk_mgr->base.dprefclk_khz = s.dprefclk * 1000;
- }
+ /*TODO: uncomment assert once dcn3_dump_clk_registers is implemented */
+ //ASSERT(s.dprefclk != 0);
+ if (s.dprefclk != 0)
+ clk_mgr->base.dprefclk_khz = s.dprefclk * 1000;
clk_mgr->dfs_bypass_enabled = false;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c
index 1fbf1c105dc1..bdbf18306698 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c
@@ -312,6 +312,9 @@ void dcn30_smu_set_display_refresh_from_mall(struct clk_mgr_internal *clk_mgr, b
/* bits 8:7 for cache timer scale, bits 6:1 for cache timer delay, bit 0 = 1 for enable, = 0 for disable */
uint32_t param = (cache_timer_scale << 7) | (cache_timer_delay << 1) | (enable ? 1 : 0);
+ smu_print("SMU Set display refresh from mall: enable = %d, cache_timer_delay = %d, cache_timer_scale = %d\n",
+ enable, cache_timer_delay, cache_timer_scale);
+
dcn30_smu_send_msg_with_param(clk_mgr,
DALSMC_MSG_SetDisplayRefreshFromMall, param, NULL);
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
index 01383aac6b41..a5489fe6875f 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
@@ -117,7 +117,7 @@ static void vg_update_clocks(struct clk_mgr *clk_mgr_base,
display_count = vg_get_active_display_cnt_wa(dc, context);
/* if we can go lower, go lower */
- if (display_count == 0 && !IS_DIAG_DC(dc->ctx->dce_environment)) {
+ if (display_count == 0) {
union display_idle_optimization_u idle_info = { 0 };
idle_info.idle_info.df_request_disabled = 1;
@@ -151,10 +151,8 @@ static void vg_update_clocks(struct clk_mgr *clk_mgr_base,
}
// workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
- if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
- if (new_clocks->dppclk_khz < 100000)
- new_clocks->dppclk_khz = 100000;
- }
+ if (new_clocks->dppclk_khz < 100000)
+ new_clocks->dppclk_khz = 100000;
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
@@ -664,6 +662,7 @@ void vg_clk_mgr_construct(
struct dccg *dccg)
{
struct smu_dpm_clks smu_dpm_clks = { 0 };
+ struct clk_log_info log_info = {0};
clk_mgr->base.base.ctx = ctx;
clk_mgr->base.base.funcs = &vg_funcs;
@@ -703,32 +702,25 @@ void vg_clk_mgr_construct(
ASSERT(smu_dpm_clks.dpm_clks);
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
- vg_funcs.update_clocks = dcn2_update_clocks_fpga;
- clk_mgr->base.base.dentist_vco_freq_khz = 3600000;
- } else {
- struct clk_log_info log_info = {0};
+ clk_mgr->base.smu_ver = dcn301_smu_get_smu_version(&clk_mgr->base);
- clk_mgr->base.smu_ver = dcn301_smu_get_smu_version(&clk_mgr->base);
+ if (clk_mgr->base.smu_ver)
+ clk_mgr->base.smu_present = true;
- if (clk_mgr->base.smu_ver)
- clk_mgr->base.smu_present = true;
+ /* TODO: Check we get what we expect during bringup */
+ clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
- /* TODO: Check we get what we expect during bringup */
- clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
-
- /* in case we don't get a value from the register, use default */
- if (clk_mgr->base.base.dentist_vco_freq_khz == 0)
- clk_mgr->base.base.dentist_vco_freq_khz = 3600000;
+ /* in case we don't get a value from the register, use default */
+ if (clk_mgr->base.base.dentist_vco_freq_khz == 0)
+ clk_mgr->base.base.dentist_vco_freq_khz = 3600000;
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
- vg_bw_params.wm_table = lpddr5_wm_table;
- } else {
- vg_bw_params.wm_table = ddr4_wm_table;
- }
- /* Saved clocks configured at boot for debug purposes */
- vg_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info);
+ if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ vg_bw_params.wm_table = lpddr5_wm_table;
+ } else {
+ vg_bw_params.wm_table = ddr4_wm_table;
}
+ /* Saved clocks configured at boot for debug purposes */
+ vg_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info);
clk_mgr->base.base.dprefclk_khz = 600000;
dce_clock_read_ss_info(&clk_mgr->base);
@@ -746,12 +738,6 @@ void vg_clk_mgr_construct(
if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0)
dm_helpers_free_gpu_mem(clk_mgr->base.base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER,
smu_dpm_clks.dpm_clks);
-/*
- if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && clk_mgr->base.smu_ver) {
- enable powerfeatures when displaycount goes to 0
- dcn301_smu_enable_phy_refclk_pwrdwn(clk_mgr, !debug->disable_48mhz_pwrdwn);
- }
-*/
}
void vg_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
index f9e2e0c3095e..7ccd96959256 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
@@ -205,10 +205,8 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
}
// workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
- if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
- if (new_clocks->dppclk_khz < 100000)
- new_clocks->dppclk_khz = 100000;
- }
+ if (new_clocks->dppclk_khz < 100000)
+ new_clocks->dppclk_khz = 100000;
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
@@ -250,9 +248,7 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz;
cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz;
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr)
@@ -674,6 +670,7 @@ void dcn31_clk_mgr_construct(
struct dccg *dccg)
{
struct dcn31_smu_dpm_clks smu_dpm_clks = { 0 };
+ struct clk_log_info log_info = {0};
clk_mgr->base.base.ctx = ctx;
clk_mgr->base.base.funcs = &dcn31_funcs;
@@ -713,29 +710,22 @@ void dcn31_clk_mgr_construct(
ASSERT(smu_dpm_clks.dpm_clks);
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
- clk_mgr->base.base.funcs = &dcn3_fpga_funcs;
- } else {
- struct clk_log_info log_info = {0};
-
- clk_mgr->base.smu_ver = dcn31_smu_get_smu_version(&clk_mgr->base);
+ clk_mgr->base.smu_ver = dcn31_smu_get_smu_version(&clk_mgr->base);
- if (clk_mgr->base.smu_ver)
- clk_mgr->base.smu_present = true;
+ if (clk_mgr->base.smu_ver)
+ clk_mgr->base.smu_present = true;
- /* TODO: Check we get what we expect during bringup */
- clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
-
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
- dcn31_bw_params.wm_table = lpddr5_wm_table;
- } else {
- dcn31_bw_params.wm_table = ddr5_wm_table;
- }
- /* Saved clocks configured at boot for debug purposes */
- dcn31_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
- &clk_mgr->base.base, &log_info);
+ /* TODO: Check we get what we expect during bringup */
+ clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
+ if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ dcn31_bw_params.wm_table = lpddr5_wm_table;
+ } else {
+ dcn31_bw_params.wm_table = ddr5_wm_table;
}
+ /* Saved clocks configured at boot for debug purposes */
+ dcn31_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
+ &clk_mgr->base.base, &log_info);
clk_mgr->base.base.dprefclk_khz = 600000;
clk_mgr->base.base.clks.ref_dtbclk_khz = 600000;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c
index 0827c7df2855..32279c5db724 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c
@@ -130,7 +130,7 @@ static int dcn31_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr,
if (result == VBIOSSMC_Result_Failed) {
if (msg_id == VBIOSSMC_MSG_TransferTableDram2Smu &&
param == TABLE_WATERMARKS)
- DC_LOG_WARNING("Watermarks table not configured properly by SMU");
+ DC_LOG_DEBUG("Watermarks table not configured properly by SMU");
else
ASSERT(0);
REG_WRITE(MP1_SMN_C2PMSG_91, VBIOSSMC_Result_OK);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
index 5cb44f838bde..2f7c8996b19d 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
@@ -241,10 +241,8 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
}
// workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
- if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
- if (new_clocks->dppclk_khz < 100000)
- new_clocks->dppclk_khz = 100000;
- }
+ if (new_clocks->dppclk_khz < 100000)
+ new_clocks->dppclk_khz = 100000;
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
@@ -286,9 +284,7 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz;
cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz;
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr)
@@ -405,32 +401,32 @@ static struct wm_table lpddr5_wm_table = {
.wm_inst = WM_A,
.wm_type = WM_TYPE_PSTATE_CHG,
.pstate_latency_us = 11.65333,
- .sr_exit_time_us = 16.5,
- .sr_enter_plus_exit_time_us = 18.5,
+ .sr_exit_time_us = 30.0,
+ .sr_enter_plus_exit_time_us = 32.0,
.valid = true,
},
{
.wm_inst = WM_B,
.wm_type = WM_TYPE_PSTATE_CHG,
.pstate_latency_us = 11.65333,
- .sr_exit_time_us = 16.5,
- .sr_enter_plus_exit_time_us = 18.5,
+ .sr_exit_time_us = 30.0,
+ .sr_enter_plus_exit_time_us = 32.0,
.valid = true,
},
{
.wm_inst = WM_C,
.wm_type = WM_TYPE_PSTATE_CHG,
.pstate_latency_us = 11.65333,
- .sr_exit_time_us = 16.5,
- .sr_enter_plus_exit_time_us = 18.5,
+ .sr_exit_time_us = 30.0,
+ .sr_enter_plus_exit_time_us = 32.0,
.valid = true,
},
{
.wm_inst = WM_D,
.wm_type = WM_TYPE_PSTATE_CHG,
.pstate_latency_us = 11.65333,
- .sr_exit_time_us = 16.5,
- .sr_enter_plus_exit_time_us = 18.5,
+ .sr_exit_time_us = 30.0,
+ .sr_enter_plus_exit_time_us = 32.0,
.valid = true,
},
}
@@ -726,6 +722,7 @@ void dcn314_clk_mgr_construct(
struct dccg *dccg)
{
struct dcn314_smu_dpm_clks smu_dpm_clks = { 0 };
+ struct clk_log_info log_info = {0};
clk_mgr->base.base.ctx = ctx;
clk_mgr->base.base.funcs = &dcn314_funcs;
@@ -765,29 +762,22 @@ void dcn314_clk_mgr_construct(
ASSERT(smu_dpm_clks.dpm_clks);
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
- clk_mgr->base.base.funcs = &dcn3_fpga_funcs;
- } else {
- struct clk_log_info log_info = {0};
-
- clk_mgr->base.smu_ver = dcn314_smu_get_smu_version(&clk_mgr->base);
+ clk_mgr->base.smu_ver = dcn314_smu_get_smu_version(&clk_mgr->base);
- if (clk_mgr->base.smu_ver)
- clk_mgr->base.smu_present = true;
+ if (clk_mgr->base.smu_ver)
+ clk_mgr->base.smu_present = true;
- /* TODO: Check we get what we expect during bringup */
- clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
+ /* TODO: Check we get what we expect during bringup */
+ clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
- dcn314_bw_params.wm_table = lpddr5_wm_table;
- else
- dcn314_bw_params.wm_table = ddr5_wm_table;
+ if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
+ dcn314_bw_params.wm_table = lpddr5_wm_table;
+ else
+ dcn314_bw_params.wm_table = ddr5_wm_table;
- /* Saved clocks configured at boot for debug purposes */
- dcn314_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
- &clk_mgr->base.base, &log_info);
-
- }
+ /* Saved clocks configured at boot for debug purposes */
+ dcn314_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
+ &clk_mgr->base.base, &log_info);
clk_mgr->base.base.dprefclk_khz = 600000;
clk_mgr->base.base.clks.ref_dtbclk_khz = 600000;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.c
index 0765334f0825..07baa10a8647 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.c
@@ -145,7 +145,7 @@ static int dcn314_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr,
if (result == VBIOSSMC_Result_Failed) {
if (msg_id == VBIOSSMC_MSG_TransferTableDram2Smu &&
param == TABLE_WATERMARKS)
- DC_LOG_WARNING("Watermarks table not configured properly by SMU");
+ DC_LOG_DEBUG("Watermarks table not configured properly by SMU");
else if (msg_id == VBIOSSMC_MSG_SetHardMinDcfclkByFreq ||
msg_id == VBIOSSMC_MSG_SetMinDeepSleepDcfclk)
DC_LOG_WARNING("DCFCLK_DPM is not enabled by BIOS");
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
index b737cbc468f5..b2c4f97afc8b 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
@@ -184,12 +184,10 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
}
// workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
- if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
- if (new_clocks->dppclk_khz < MIN_DPP_DISP_CLK)
- new_clocks->dppclk_khz = MIN_DPP_DISP_CLK;
- if (new_clocks->dispclk_khz < MIN_DPP_DISP_CLK)
- new_clocks->dispclk_khz = MIN_DPP_DISP_CLK;
- }
+ if (new_clocks->dppclk_khz < MIN_DPP_DISP_CLK)
+ new_clocks->dppclk_khz = MIN_DPP_DISP_CLK;
+ if (new_clocks->dispclk_khz < MIN_DPP_DISP_CLK)
+ new_clocks->dispclk_khz = MIN_DPP_DISP_CLK;
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
@@ -234,9 +232,7 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz;
cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz;
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
@@ -602,6 +598,7 @@ void dcn315_clk_mgr_construct(
struct dccg *dccg)
{
struct dcn315_smu_dpm_clks smu_dpm_clks = { 0 };
+ struct clk_log_info log_info = {0};
clk_mgr->base.base.ctx = ctx;
clk_mgr->base.base.funcs = &dcn315_funcs;
@@ -641,26 +638,19 @@ void dcn315_clk_mgr_construct(
ASSERT(smu_dpm_clks.dpm_clks);
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
- clk_mgr->base.base.funcs = &dcn3_fpga_funcs;
- } else {
- struct clk_log_info log_info = {0};
-
- clk_mgr->base.smu_ver = dcn315_smu_get_smu_version(&clk_mgr->base);
+ clk_mgr->base.smu_ver = dcn315_smu_get_smu_version(&clk_mgr->base);
- if (clk_mgr->base.smu_ver > 0)
- clk_mgr->base.smu_present = true;
-
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
- dcn315_bw_params.wm_table = lpddr5_wm_table;
- } else {
- dcn315_bw_params.wm_table = ddr5_wm_table;
- }
- /* Saved clocks configured at boot for debug purposes */
- dcn315_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
- &clk_mgr->base.base, &log_info);
+ if (clk_mgr->base.smu_ver > 0)
+ clk_mgr->base.smu_present = true;
+ if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ dcn315_bw_params.wm_table = lpddr5_wm_table;
+ } else {
+ dcn315_bw_params.wm_table = ddr5_wm_table;
}
+ /* Saved clocks configured at boot for debug purposes */
+ dcn315_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
+ &clk_mgr->base.base, &log_info);
clk_mgr->base.base.dprefclk_khz = 600000;
clk_mgr->base.base.dprefclk_khz = dcn315_smu_get_dpref_clk(&clk_mgr->base);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
index 93db4dbee713..d7de756301cf 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
@@ -207,12 +207,10 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base,
}
// workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
- if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
- if (new_clocks->dppclk_khz < 100000)
- new_clocks->dppclk_khz = 100000;
- if (new_clocks->dispclk_khz < 100000)
- new_clocks->dispclk_khz = 100000;
- }
+ if (new_clocks->dppclk_khz < 100000)
+ new_clocks->dppclk_khz = 100000;
+ if (new_clocks->dispclk_khz < 100000)
+ new_clocks->dispclk_khz = 100000;
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
@@ -254,9 +252,7 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base,
cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz;
cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz;
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static void dcn316_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
@@ -618,6 +614,7 @@ void dcn316_clk_mgr_construct(
struct dccg *dccg)
{
struct dcn316_smu_dpm_clks smu_dpm_clks = { 0 };
+ struct clk_log_info log_info = {0};
clk_mgr->base.base.ctx = ctx;
clk_mgr->base.base.funcs = &dcn316_funcs;
@@ -657,35 +654,27 @@ void dcn316_clk_mgr_construct(
ASSERT(smu_dpm_clks.dpm_clks);
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
- clk_mgr->base.base.funcs = &dcn3_fpga_funcs;
- clk_mgr->base.base.dentist_vco_freq_khz = 2500000;
- } else {
- struct clk_log_info log_info = {0};
-
- clk_mgr->base.smu_ver = dcn316_smu_get_smu_version(&clk_mgr->base);
+ clk_mgr->base.smu_ver = dcn316_smu_get_smu_version(&clk_mgr->base);
- if (clk_mgr->base.smu_ver > 0)
- clk_mgr->base.smu_present = true;
+ if (clk_mgr->base.smu_ver > 0)
+ clk_mgr->base.smu_present = true;
- // Skip this for now as it did not work on DCN315, renable during bring up
- clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
+ // Skip this for now as it did not work on DCN315, renable during bring up
+ clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
- /* in case we don't get a value from the register, use default */
- if (clk_mgr->base.base.dentist_vco_freq_khz == 0)
- clk_mgr->base.base.dentist_vco_freq_khz = 2500000; /* 2400MHz */
+ /* in case we don't get a value from the register, use default */
+ if (clk_mgr->base.base.dentist_vco_freq_khz == 0)
+ clk_mgr->base.base.dentist_vco_freq_khz = 2500000; /* 2400MHz */
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
- dcn316_bw_params.wm_table = lpddr5_wm_table;
- } else {
- dcn316_bw_params.wm_table = ddr4_wm_table;
- }
- /* Saved clocks configured at boot for debug purposes */
- dcn316_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
- &clk_mgr->base.base, &log_info);
-
+ if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ dcn316_bw_params.wm_table = lpddr5_wm_table;
+ } else {
+ dcn316_bw_params.wm_table = ddr4_wm_table;
}
+ /* Saved clocks configured at boot for debug purposes */
+ dcn316_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
+ &clk_mgr->base.base, &log_info);
clk_mgr->base.base.dprefclk_khz = 600000;
clk_mgr->base.base.dprefclk_khz = dcn316_smu_get_dpref_clk(&clk_mgr->base);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
index 8d9444db092a..6a811755e2e6 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
@@ -182,23 +182,32 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
dcn32_init_single_clock(clk_mgr, PPCLK_DCFCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
&num_entries_per_clk->num_dcfclk_levels);
+ clk_mgr_base->bw_params->dc_mode_limit.dcfclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DCFCLK);
/* SOCCLK */
dcn32_init_single_clock(clk_mgr, PPCLK_SOCCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz,
&num_entries_per_clk->num_socclk_levels);
+ clk_mgr_base->bw_params->dc_mode_limit.socclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_SOCCLK);
/* DTBCLK */
- if (!clk_mgr->base.ctx->dc->debug.disable_dtb_ref_clk_switch)
+ if (!clk_mgr->base.ctx->dc->debug.disable_dtb_ref_clk_switch) {
dcn32_init_single_clock(clk_mgr, PPCLK_DTBCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz,
&num_entries_per_clk->num_dtbclk_levels);
+ clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz =
+ dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DTBCLK);
+ }
/* DISPCLK */
dcn32_init_single_clock(clk_mgr, PPCLK_DISPCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
&num_entries_per_clk->num_dispclk_levels);
num_levels = num_entries_per_clk->num_dispclk_levels;
+ clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DISPCLK);
+ //HW recommends limit of 1950 MHz in display clock for all DCN3.2.x
+ if (clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz > 1950)
+ clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz = 1950;
if (num_entries_per_clk->num_dcfclk_levels &&
num_entries_per_clk->num_dtbclk_levels &&
@@ -233,6 +242,32 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
DC_FP_END();
}
+static void dcn32_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
+ struct dc_state *context,
+ int ref_dtbclk_khz)
+{
+ struct dccg *dccg = clk_mgr->dccg;
+ uint32_t tg_mask = 0;
+ int i;
+
+ for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+ struct dtbclk_dto_params dto_params = {0};
+
+ /* use mask to program DTO once per tg */
+ if (pipe_ctx->stream_res.tg &&
+ !(tg_mask & (1 << pipe_ctx->stream_res.tg->inst))) {
+ tg_mask |= (1 << pipe_ctx->stream_res.tg->inst);
+
+ dto_params.otg_inst = pipe_ctx->stream_res.tg->inst;
+ dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
+
+ dccg->funcs->set_dtbclk_dto(clk_mgr->dccg, &dto_params);
+ //dccg->funcs->set_audio_dtbclk_dto(clk_mgr->dccg, &dto_params);
+ }
+ }
+}
+
/* Since DPPCLK request to PMFW needs to be exact (due to DPP DTO programming),
* update DPPCLK to be the exact frequency that will be set after the DPPCLK
* divider is updated. This will prevent rounding issues that could cause DPP
@@ -433,10 +468,6 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
bool update_uclk = false, update_fclk = false;
bool p_state_change_support;
bool fclk_p_state_change_support;
- int total_plane_count;
-
- if (dc->work_arounds.skip_clock_update)
- return;
if (clk_mgr_base->clks.dispclk_khz == 0 ||
(dc->debug.force_clock_mode & 0x1)) {
@@ -462,10 +493,10 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
clk_mgr_base->clks.fclk_prev_p_state_change_support = clk_mgr_base->clks.fclk_p_state_change_support;
- total_plane_count = clk_mgr_helper_get_active_plane_cnt(dc, context);
- fclk_p_state_change_support = new_clocks->fclk_p_state_change_support || (total_plane_count == 0);
+ fclk_p_state_change_support = new_clocks->fclk_p_state_change_support;
- if (should_update_pstate_support(safe_to_lower, fclk_p_state_change_support, clk_mgr_base->clks.fclk_p_state_change_support)) {
+ if (should_update_pstate_support(safe_to_lower, fclk_p_state_change_support, clk_mgr_base->clks.fclk_p_state_change_support) &&
+ !dc->work_arounds.clock_update_disable_mask.fclk) {
clk_mgr_base->clks.fclk_p_state_change_support = fclk_p_state_change_support;
/* To enable FCLK P-state switching, send FCLK_PSTATE_SUPPORTED message to PMFW */
@@ -479,12 +510,14 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
new_clocks->dcfclk_khz = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ?
new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000);
- if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
+ if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz) &&
+ !dc->work_arounds.clock_update_disable_mask.dcfclk) {
clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DCFCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_khz));
}
- if (should_set_clock(safe_to_lower, new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
+ if (should_set_clock(safe_to_lower, new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz) &&
+ !dc->work_arounds.clock_update_disable_mask.dcfclk_ds) {
clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
dcn30_smu_set_min_deep_sleep_dcef_clk(clk_mgr, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_deep_sleep_khz));
}
@@ -502,9 +535,9 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
dcn32_smu_send_cab_for_uclk_message(clk_mgr, clk_mgr_base->clks.num_ways);
}
-
- p_state_change_support = new_clocks->p_state_change_support || (total_plane_count == 0);
- if (should_update_pstate_support(safe_to_lower, p_state_change_support, clk_mgr_base->clks.p_state_change_support)) {
+ p_state_change_support = new_clocks->p_state_change_support;
+ if (should_update_pstate_support(safe_to_lower, p_state_change_support, clk_mgr_base->clks.p_state_change_support) &&
+ !dc->work_arounds.clock_update_disable_mask.uclk) {
clk_mgr_base->clks.p_state_change_support = p_state_change_support;
/* to disable P-State switching, set UCLK min = max */
@@ -518,20 +551,23 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
update_fclk = true;
}
- if (clk_mgr_base->ctx->dce_version != DCN_VERSION_3_21 && !clk_mgr_base->clks.fclk_p_state_change_support && update_fclk) {
+ if (clk_mgr_base->ctx->dce_version != DCN_VERSION_3_21 && !clk_mgr_base->clks.fclk_p_state_change_support && update_fclk &&
+ !dc->work_arounds.clock_update_disable_mask.fclk) {
/* Handle code for sending a message to PMFW that FCLK P-state change is not supported */
dcn32_smu_send_fclk_pstate_message(clk_mgr, FCLK_PSTATE_NOTSUPPORTED);
}
/* Always update saved value, even if new value not set due to P-State switching unsupported */
- if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr_base->clks.dramclk_khz)) {
+ if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr_base->clks.dramclk_khz) &&
+ !dc->work_arounds.clock_update_disable_mask.uclk) {
clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz;
update_uclk = true;
}
/* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */
if (clk_mgr_base->clks.p_state_change_support &&
- (update_uclk || !clk_mgr_base->clks.prev_p_state_change_support))
+ (update_uclk || !clk_mgr_base->clks.prev_p_state_change_support) &&
+ !dc->work_arounds.clock_update_disable_mask.uclk)
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
if (clk_mgr_base->clks.num_ways != new_clocks->num_ways &&
@@ -570,6 +606,7 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
/* DCCG requires KHz precision for DTBCLK */
clk_mgr_base->clks.ref_dtbclk_khz =
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DTBCLK, khz_to_mhz_ceil(new_clocks->ref_dtbclk_khz));
+ dcn32_update_clocks_update_dtb_dto(clk_mgr, context, clk_mgr_base->clks.ref_dtbclk_khz);
}
if (dc->config.forced_clocks == false || (force_reset && safe_to_lower)) {
@@ -789,6 +826,7 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
dcn32_init_single_clock(clk_mgr, PPCLK_UCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz,
&num_entries_per_clk->num_memclk_levels);
+ clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_UCLK);
/* memclk must have at least one level */
num_entries_per_clk->num_memclk_levels = num_entries_per_clk->num_memclk_levels ? num_entries_per_clk->num_memclk_levels : 1;
@@ -796,6 +834,7 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
dcn32_init_single_clock(clk_mgr, PPCLK_FCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz,
&num_entries_per_clk->num_fclk_levels);
+ clk_mgr_base->bw_params->dc_mode_limit.fclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_FCLK);
if (num_entries_per_clk->num_memclk_levels >= num_entries_per_clk->num_fclk_levels) {
num_levels = num_entries_per_clk->num_memclk_levels;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 7cde67b7f0c3..dd3a9d06c6e2 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -515,8 +515,7 @@ dc_stream_forward_dmub_crc_window(struct dc_dmub_srv *dmub_srv,
cmd.secure_display.roi_info.y_end = rect->y + rect->height;
}
- dc_dmub_srv_cmd_queue(dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dmub_srv);
+ dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
}
static inline void
@@ -858,7 +857,6 @@ static bool dc_construct_ctx(struct dc *dc,
const struct dc_init_data *init_params)
{
struct dc_context *dc_ctx;
- enum dce_version dc_version = DCE_VERSION_UNKNOWN;
dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL);
if (!dc_ctx)
@@ -876,8 +874,7 @@ static bool dc_construct_ctx(struct dc *dc,
/* Create logger */
- dc_version = resource_parse_asic_id(init_params->asic_id);
- dc_ctx->dce_version = dc_version;
+ dc_ctx->dce_version = resource_parse_asic_id(init_params->asic_id);
dc_ctx->perf_trace = dc_perf_trace_create();
if (!dc_ctx->perf_trace) {
@@ -1120,6 +1117,33 @@ static void phantom_pipe_blank(
hws->funcs.wait_for_blank_complete(opp);
}
+static void dc_update_viusal_confirm_color(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
+{
+ if (dc->ctx->dce_version >= DCN_VERSION_1_0) {
+ memset(&pipe_ctx->visual_confirm_color, 0, sizeof(struct tg_color));
+
+ if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR)
+ get_hdr_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
+ get_surface_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SWIZZLE)
+ get_surface_tile_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ else {
+ if (dc->ctx->dce_version < DCN_VERSION_2_0)
+ color_space_to_black_color(
+ dc, pipe_ctx->stream->output_color_space, &(pipe_ctx->visual_confirm_color));
+ }
+ if (dc->ctx->dce_version >= DCN_VERSION_2_0) {
+ if (dc->debug.visual_confirm == VISUAL_CONFIRM_MPCTREE)
+ get_mpctree_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP)
+ get_subvp_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ else if (dc->debug.visual_confirm == VISUAL_CONFIRM_MCLK_SWITCH)
+ get_mclk_switch_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ }
+ }
+}
+
static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
{
int i, j;
@@ -1190,6 +1214,9 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
dc_rem_all_planes_for_stream(dc, old_stream, dangling_context);
disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
+ if (pipe->stream && pipe->plane_state)
+ dc_update_viusal_confirm_color(dc, context, pipe);
+
if (dc->hwss.apply_ctx_for_surface) {
apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, true);
dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context);
@@ -2504,9 +2531,6 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
enum surface_update_type overall_type = UPDATE_TYPE_FAST;
union surface_update_flags *update_flags = &u->surface->update_flags;
- if (u->flip_addr)
- update_flags->bits.addr_update = 1;
-
if (!is_surface_in_context(context, u->surface) || u->surface->force_full_update) {
update_flags->raw = 0xFFFFFFFF;
return UPDATE_TYPE_FULL;
@@ -2565,15 +2589,19 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
elevate_update_type(&overall_type, type);
}
- if (update_flags->bits.input_csc_change
- || update_flags->bits.coeff_reduction_change
- || update_flags->bits.lut_3d
- || update_flags->bits.gamma_change
- || update_flags->bits.gamut_remap_change) {
+ if (update_flags->bits.lut_3d) {
type = UPDATE_TYPE_FULL;
elevate_update_type(&overall_type, type);
}
+ if (dc->debug.enable_legacy_fast_update &&
+ (update_flags->bits.gamma_change ||
+ update_flags->bits.gamut_remap_change ||
+ update_flags->bits.input_csc_change ||
+ update_flags->bits.coeff_reduction_change)) {
+ type = UPDATE_TYPE_FULL;
+ elevate_update_type(&overall_type, type);
+ }
return overall_type;
}
@@ -2606,7 +2634,7 @@ static enum surface_update_type check_update_surfaces_for_stream(
stream_update->integer_scaling_update)
su_flags->bits.scaling = 1;
- if (stream_update->out_transfer_func)
+ if (dc->debug.enable_legacy_fast_update && stream_update->out_transfer_func)
su_flags->bits.out_tf = 1;
if (stream_update->abm_level)
@@ -2626,14 +2654,23 @@ static enum surface_update_type check_update_surfaces_for_stream(
if (stream_update->mst_bw_update)
su_flags->bits.mst_bw = 1;
- if (stream_update->crtc_timing_adjust && dc_extended_blank_supported(dc))
- su_flags->bits.crtc_timing_adjust = 1;
+
+ if (stream_update->stream && stream_update->stream->freesync_on_desktop &&
+ (stream_update->vrr_infopacket || stream_update->allow_freesync ||
+ stream_update->vrr_active_variable || stream_update->vrr_active_fixed))
+ su_flags->bits.fams_changed = 1;
if (su_flags->raw != 0)
overall_type = UPDATE_TYPE_FULL;
if (stream_update->output_csc_transform || stream_update->output_color_space)
su_flags->bits.out_csc = 1;
+
+ /* Output transfer function changes do not require bandwidth recalculation,
+ * so don't trigger a full update
+ */
+ if (!dc->debug.enable_legacy_fast_update && stream_update->out_transfer_func)
+ su_flags->bits.out_tf = 1;
}
for (i = 0 ; i < surface_count; i++) {
@@ -2986,6 +3023,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
if (update->vrr_active_variable)
stream->vrr_active_variable = *update->vrr_active_variable;
+ if (update->vrr_active_fixed)
+ stream->vrr_active_fixed = *update->vrr_active_fixed;
+
if (update->crtc_timing_adjust)
stream->adjust = *update->crtc_timing_adjust;
@@ -3290,6 +3330,13 @@ static void commit_planes_do_stream_update(struct dc *dc,
dc->hwss.prepare_bandwidth(dc, dc->current_state);
dc->link_srv->set_dpms_on(dc->current_state, pipe_ctx);
}
+ } else if (pipe_ctx->stream->link->wa_flags.blank_stream_on_ocs_change && stream_update->output_color_space
+ && !stream->dpms_off && dc_is_dp_signal(pipe_ctx->stream->signal)) {
+ /*
+ * Workaround for firmware issue in some receivers where they don't pick up
+ * correct output color space unless DP link is disabled/re-enabled
+ */
+ dc->link_srv->set_dpms_on(dc->current_state, pipe_ctx);
}
if (stream_update->abm_level && pipe_ctx->stream_res.abm) {
@@ -3330,7 +3377,6 @@ void dc_dmub_update_dirty_rect(struct dc *dc,
struct dc_state *context)
{
union dmub_rb_cmd cmd;
- struct dc_context *dc_ctx = dc->ctx;
struct dmub_cmd_update_dirty_rect_data *update_dirty_rect;
unsigned int i, j;
unsigned int panel_inst = 0;
@@ -3371,12 +3417,168 @@ void dc_dmub_update_dirty_rect(struct dc *dc,
update_dirty_rect->panel_inst = panel_inst;
update_dirty_rect->pipe_idx = j;
- dc_dmub_srv_cmd_queue(dc_ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc_ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
+ }
+ }
+}
+
+static void build_dmub_update_dirty_rect(
+ struct dc *dc,
+ int surface_count,
+ struct dc_stream_state *stream,
+ struct dc_surface_update *srf_updates,
+ struct dc_state *context,
+ struct dc_dmub_cmd dc_dmub_cmd[],
+ unsigned int *dmub_cmd_count)
+{
+ union dmub_rb_cmd cmd;
+ struct dmub_cmd_update_dirty_rect_data *update_dirty_rect;
+ unsigned int i, j;
+ unsigned int panel_inst = 0;
+
+ if (!dc_dmub_should_send_dirty_rect_cmd(dc, stream))
+ return;
+
+ if (!dc_get_edp_link_panel_inst(dc, stream->link, &panel_inst))
+ return;
+
+ memset(&cmd, 0x0, sizeof(cmd));
+ cmd.update_dirty_rect.header.type = DMUB_CMD__UPDATE_DIRTY_RECT;
+ cmd.update_dirty_rect.header.sub_type = 0;
+ cmd.update_dirty_rect.header.payload_bytes =
+ sizeof(cmd.update_dirty_rect) -
+ sizeof(cmd.update_dirty_rect.header);
+ update_dirty_rect = &cmd.update_dirty_rect.update_dirty_rect_data;
+ for (i = 0; i < surface_count; i++) {
+ struct dc_plane_state *plane_state = srf_updates[i].surface;
+ const struct dc_flip_addrs *flip_addr = srf_updates[i].flip_addr;
+
+ if (!srf_updates[i].surface || !flip_addr)
+ continue;
+ /* Do not send in immediate flip mode */
+ if (srf_updates[i].surface->flip_immediate)
+ continue;
+ update_dirty_rect->cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
+ update_dirty_rect->dirty_rect_count = flip_addr->dirty_rect_count;
+ memcpy(update_dirty_rect->src_dirty_rects, flip_addr->dirty_rects,
+ sizeof(flip_addr->dirty_rects));
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+
+ if (pipe_ctx->stream != stream)
+ continue;
+ if (pipe_ctx->plane_state != plane_state)
+ continue;
+ update_dirty_rect->panel_inst = panel_inst;
+ update_dirty_rect->pipe_idx = j;
+ dc_dmub_cmd[*dmub_cmd_count].dmub_cmd = cmd;
+ dc_dmub_cmd[*dmub_cmd_count].wait_type = DM_DMUB_WAIT_TYPE_NO_WAIT;
+ (*dmub_cmd_count)++;
}
}
}
+
+/**
+ * build_dmub_cmd_list() - Build an array of DMCUB commands to be sent to DMCUB
+ *
+ * @dc: Current DC state
+ * @srf_updates: Array of surface updates
+ * @surface_count: Number of surfaces that have an updated
+ * @stream: Corresponding stream to be updated in the current flip
+ * @context: New DC state to be programmed
+ *
+ * @dc_dmub_cmd: Array of DMCUB commands to be sent to DMCUB
+ * @dmub_cmd_count: Count indicating the number of DMCUB commands in dc_dmub_cmd array
+ *
+ * This function builds an array of DMCUB commands to be sent to DMCUB. This function is required
+ * to build an array of commands and have them sent while the OTG lock is acquired.
+ *
+ * Return: void
+ */
+static void build_dmub_cmd_list(struct dc *dc,
+ struct dc_surface_update *srf_updates,
+ int surface_count,
+ struct dc_stream_state *stream,
+ struct dc_state *context,
+ struct dc_dmub_cmd dc_dmub_cmd[],
+ unsigned int *dmub_cmd_count)
+{
+ // Initialize cmd count to 0
+ *dmub_cmd_count = 0;
+ build_dmub_update_dirty_rect(dc, surface_count, stream, srf_updates, context, dc_dmub_cmd, dmub_cmd_count);
+}
+
+static void commit_planes_for_stream_fast(struct dc *dc,
+ struct dc_surface_update *srf_updates,
+ int surface_count,
+ struct dc_stream_state *stream,
+ struct dc_stream_update *stream_update,
+ enum surface_update_type update_type,
+ struct dc_state *context)
+{
+ int i, j;
+ struct pipe_ctx *top_pipe_to_program = NULL;
+ dc_z10_restore(dc);
+
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+
+ if (!pipe_ctx->top_pipe &&
+ !pipe_ctx->prev_odm_pipe &&
+ pipe_ctx->stream &&
+ pipe_ctx->stream == stream) {
+ top_pipe_to_program = pipe_ctx;
+ }
+ }
+
+ if (dc->debug.visual_confirm) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (pipe->stream && pipe->plane_state)
+ dc_update_viusal_confirm_color(dc, context, pipe);
+ }
+ }
+
+ for (i = 0; i < surface_count; i++) {
+ struct dc_plane_state *plane_state = srf_updates[i].surface;
+ /*set logical flag for lock/unlock use*/
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+
+ if (!pipe_ctx->plane_state)
+ continue;
+ if (should_update_pipe_for_plane(context, pipe_ctx, plane_state))
+ continue;
+ pipe_ctx->plane_state->triplebuffer_flips = false;
+ if (update_type == UPDATE_TYPE_FAST &&
+ dc->hwss.program_triplebuffer &&
+ !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) {
+ /*triple buffer for VUpdate only*/
+ pipe_ctx->plane_state->triplebuffer_flips = true;
+ }
+ }
+ }
+
+ build_dmub_cmd_list(dc,
+ srf_updates,
+ surface_count,
+ stream,
+ context,
+ context->dc_dmub_cmd,
+ &(context->dmub_cmd_count));
+ hwss_build_fast_sequence(dc,
+ context->dc_dmub_cmd,
+ context->dmub_cmd_count,
+ context->block_sequence,
+ &(context->block_sequence_steps),
+ top_pipe_to_program);
+ hwss_execute_sequence(dc,
+ context->block_sequence,
+ context->block_sequence_steps);
+}
+
static void commit_planes_for_stream(struct dc *dc,
struct dc_surface_update *srf_updates,
int surface_count,
@@ -3414,21 +3616,6 @@ static void commit_planes_for_stream(struct dc *dc,
}
}
- if (get_seamless_boot_stream_count(context) > 0 && surface_count > 0) {
- /* Optimize seamless boot flag keeps clocks and watermarks high until
- * first flip. After first flip, optimization is required to lower
- * bandwidth. Important to note that it is expected UEFI will
- * only light up a single display on POST, therefore we only expect
- * one stream with seamless boot flag set.
- */
- if (stream->apply_seamless_boot_optimization) {
- stream->apply_seamless_boot_optimization = false;
-
- if (get_seamless_boot_stream_count(context) == 0)
- dc->optimized_required = true;
- }
- }
-
if (update_type == UPDATE_TYPE_FULL) {
dc_allow_idle_optimizations(dc, false);
@@ -3470,6 +3657,14 @@ static void commit_planes_for_stream(struct dc *dc,
}
}
+ if (dc->debug.visual_confirm)
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (pipe->stream && pipe->plane_state)
+ dc_update_viusal_confirm_color(dc, context, pipe);
+ }
+
if (stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) {
struct pipe_ctx *mpcc_pipe;
struct pipe_ctx *odm_pipe;
@@ -3553,43 +3748,40 @@ static void commit_planes_for_stream(struct dc *dc,
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
- if (dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP &&
+ if ((dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP ||
+ dc->debug.visual_confirm == VISUAL_CONFIRM_MCLK_SWITCH) &&
pipe_ctx->stream && pipe_ctx->plane_state) {
- /* Only update visual confirm for SUBVP here.
+ /* Only update visual confirm for SUBVP and Mclk switching here.
* The bar appears on all pipes, so we need to update the bar on all displays,
* so the information doesn't get stale.
*/
- struct mpcc_blnd_cfg blnd_cfg = { 0 };
-
- dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color,
+ dc->hwss.update_visual_confirm_color(dc, pipe_ctx,
pipe_ctx->plane_res.hubp->inst);
}
}
}
- if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
- for (i = 0; i < surface_count; i++) {
- struct dc_plane_state *plane_state = srf_updates[i].surface;
- /*set logical flag for lock/unlock use*/
- for (j = 0; j < dc->res_pool->pipe_count; j++) {
- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
- if (!pipe_ctx->plane_state)
- continue;
- if (should_update_pipe_for_plane(context, pipe_ctx, plane_state))
- continue;
- pipe_ctx->plane_state->triplebuffer_flips = false;
- if (update_type == UPDATE_TYPE_FAST &&
- dc->hwss.program_triplebuffer != NULL &&
- !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) {
- /*triple buffer for VUpdate only*/
- pipe_ctx->plane_state->triplebuffer_flips = true;
- }
- }
- if (update_type == UPDATE_TYPE_FULL) {
- /* force vsync flip when reconfiguring pipes to prevent underflow */
- plane_state->flip_immediate = false;
+ for (i = 0; i < surface_count; i++) {
+ struct dc_plane_state *plane_state = srf_updates[i].surface;
+ /*set logical flag for lock/unlock use*/
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+ if (!pipe_ctx->plane_state)
+ continue;
+ if (should_update_pipe_for_plane(context, pipe_ctx, plane_state))
+ continue;
+ pipe_ctx->plane_state->triplebuffer_flips = false;
+ if (update_type == UPDATE_TYPE_FAST &&
+ dc->hwss.program_triplebuffer != NULL &&
+ !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) {
+ /*triple buffer for VUpdate only*/
+ pipe_ctx->plane_state->triplebuffer_flips = true;
}
}
+ if (update_type == UPDATE_TYPE_FULL) {
+ /* force vsync flip when reconfiguring pipes to prevent underflow */
+ plane_state->flip_immediate = false;
+ }
}
// Update Type FULL, Surface updates
@@ -4006,6 +4198,41 @@ static bool commit_minimal_transition_state(struct dc *dc,
return true;
}
+/**
+ * update_seamless_boot_flags() - Helper function for updating seamless boot flags
+ *
+ * @dc: Current DC state
+ * @context: New DC state to be programmed
+ * @surface_count: Number of surfaces that have an updated
+ * @stream: Corresponding stream to be updated in the current flip
+ *
+ * Updating seamless boot flags do not need to be part of the commit sequence. This
+ * helper function will update the seamless boot flags on each flip (if required)
+ * outside of the HW commit sequence (fast or slow).
+ *
+ * Return: void
+ */
+static void update_seamless_boot_flags(struct dc *dc,
+ struct dc_state *context,
+ int surface_count,
+ struct dc_stream_state *stream)
+{
+ if (get_seamless_boot_stream_count(context) > 0 && surface_count > 0) {
+ /* Optimize seamless boot flag keeps clocks and watermarks high until
+ * first flip. After first flip, optimization is required to lower
+ * bandwidth. Important to note that it is expected UEFI will
+ * only light up a single display on POST, therefore we only expect
+ * one stream with seamless boot flag set.
+ */
+ if (stream->apply_seamless_boot_optimization) {
+ stream->apply_seamless_boot_optimization = false;
+
+ if (get_seamless_boot_stream_count(context) == 0)
+ dc->optimized_required = true;
+ }
+ }
+}
+
bool dc_update_planes_and_stream(struct dc *dc,
struct dc_surface_update *srf_updates, int surface_count,
struct dc_stream_state *stream,
@@ -4072,14 +4299,25 @@ bool dc_update_planes_and_stream(struct dc *dc,
update_type = UPDATE_TYPE_FULL;
}
- commit_planes_for_stream(
- dc,
- srf_updates,
- surface_count,
- stream,
- stream_update,
- update_type,
- context);
+ update_seamless_boot_flags(dc, context, surface_count, stream);
+ if (!dc->debug.enable_legacy_fast_update && update_type == UPDATE_TYPE_FAST) {
+ commit_planes_for_stream_fast(dc,
+ srf_updates,
+ surface_count,
+ stream,
+ stream_update,
+ update_type,
+ context);
+ } else {
+ commit_planes_for_stream(
+ dc,
+ srf_updates,
+ surface_count,
+ stream,
+ stream_update,
+ update_type,
+ context);
+ }
if (dc->current_state != context) {
@@ -4204,7 +4442,17 @@ void dc_commit_updates_for_stream(struct dc *dc,
TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES);
- commit_planes_for_stream(
+ update_seamless_boot_flags(dc, context, surface_count, stream);
+ if (!dc->debug.enable_legacy_fast_update && update_type == UPDATE_TYPE_FAST) {
+ commit_planes_for_stream_fast(dc,
+ srf_updates,
+ surface_count,
+ stream,
+ stream_update,
+ update_type,
+ context);
+ } else {
+ commit_planes_for_stream(
dc,
srf_updates,
surface_count,
@@ -4212,6 +4460,7 @@ void dc_commit_updates_for_stream(struct dc *dc,
stream_update,
update_type,
context);
+ }
/*update current_State*/
if (dc->current_state != context) {
@@ -4298,9 +4547,6 @@ void dc_set_power_state(
dc_z10_restore(dc);
- if (dc->ctx->dmub_srv)
- dc_dmub_srv_wait_phy_init(dc->ctx->dmub_srv);
-
dc->hwss.init_hw(dc);
if (dc->hwss.init_sys_ctx != NULL &&
@@ -4640,7 +4886,6 @@ bool dc_process_dmub_aux_transfer_async(struct dc *dc,
{
uint8_t action;
union dmub_rb_cmd cmd = {0};
- struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
ASSERT(payload->length <= 16);
@@ -4688,9 +4933,7 @@ bool dc_process_dmub_aux_transfer_async(struct dc *dc,
);
}
- dc_dmub_srv_cmd_queue(dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dmub_srv);
- dc_dmub_srv_wait_idle(dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
@@ -4734,7 +4977,6 @@ bool dc_process_dmub_set_config_async(struct dc *dc,
struct dmub_notification *notify)
{
union dmub_rb_cmd cmd = {0};
- struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
bool is_cmd_complete = true;
/* prepare SET_CONFIG command */
@@ -4745,7 +4987,7 @@ bool dc_process_dmub_set_config_async(struct dc *dc,
cmd.set_config_access.set_config_control.cmd_pkt.msg_type = payload->msg_type;
cmd.set_config_access.set_config_control.cmd_pkt.msg_data = payload->msg_data;
- if (!dc_dmub_srv_cmd_with_reply_data(dmub_srv, &cmd)) {
+ if (!dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
/* command is not processed by dmub */
notify->sc_status = SET_CONFIG_UNKNOWN_ERROR;
return is_cmd_complete;
@@ -4780,7 +5022,6 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
uint8_t *mst_slots_in_use)
{
union dmub_rb_cmd cmd = {0};
- struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
/* prepare MST_ALLOC_SLOTS command */
cmd.set_mst_alloc_slots.header.type = DMUB_CMD__DPIA;
@@ -4789,7 +5030,7 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
cmd.set_mst_alloc_slots.mst_slots_control.instance = dc->links[link_index]->ddc_hw_inst;
cmd.set_mst_alloc_slots.mst_slots_control.mst_alloc_slots = mst_alloc_slots;
- if (!dc_dmub_srv_cmd_with_reply_data(dmub_srv, &cmd))
+ if (!dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
/* command is not processed by dmub */
return DC_ERROR_UNEXPECTED;
@@ -4823,19 +5064,28 @@ void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc,
uint32_t hpd_int_enable)
{
union dmub_rb_cmd cmd = {0};
- struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
cmd.dpia_hpd_int_enable.header.type = DMUB_CMD__DPIA_HPD_INT_ENABLE;
cmd.dpia_hpd_int_enable.enable = hpd_int_enable;
- dc_dmub_srv_cmd_queue(dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dmub_srv);
- dc_dmub_srv_wait_idle(dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
DC_LOG_DEBUG("%s: hpd_int_enable(%d)\n", __func__, hpd_int_enable);
}
/**
+ * dc_print_dmub_diagnostic_data - Print DMUB diagnostic data for debugging
+ *
+ * @dc: [in] dc structure
+ *
+ *
+ */
+void dc_print_dmub_diagnostic_data(const struct dc *dc)
+{
+ dc_dmub_srv_log_diagnostic_data(dc->ctx->dmub_srv);
+}
+
+/**
* dc_disable_accelerated_mode - disable accelerated mode
* @dc: dc structure
*/
@@ -4894,21 +5144,3 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo
if (pipe->stream_res.abm && pipe->stream_res.abm->funcs->set_abm_pause)
pipe->stream_res.abm->funcs->set_abm_pause(pipe->stream_res.abm, !enable, i, pipe->stream_res.tg->inst);
}
-
-/**
- * dc_extended_blank_supported - Decide whether extended blank is supported
- *
- * @dc: [in] Current DC state
- *
- * Extended blank is a freesync optimization feature to be enabled in the
- * future. During the extra vblank period gained from freesync, we have the
- * ability to enter z9/z10.
- *
- * Return:
- * Indicate whether extended blank is supported (%true or %false)
- */
-bool dc_extended_blank_supported(struct dc *dc)
-{
- return dc->debug.extended_blank_optimization && !dc->debug.disable_z10
- && dc->caps.zstate_support && dc->caps.is_apu;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 2acbf692193f..d7d00fefaab9 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -27,6 +27,8 @@
#include "core_types.h"
#include "timing_generator.h"
#include "hw_sequencer.h"
+#include "hw_sequencer_private.h"
+#include "basics/dc_common.h"
#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
@@ -421,6 +423,7 @@ void get_hdr_visual_confirm_color(
void get_subvp_visual_confirm_color(
struct dc *dc,
+ struct dc_state *context,
struct pipe_ctx *pipe_ctx,
struct tg_color *color)
{
@@ -428,15 +431,17 @@ void get_subvp_visual_confirm_color(
bool enable_subvp = false;
int i;
- if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx)
+ if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !context)
return;
for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
if (pipe->stream && pipe->stream->mall_stream_config.paired_stream &&
pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
/* SubVP enable - red */
+ color->color_g_y = 0;
+ color->color_b_cb = 0;
color->color_r_cr = color_value;
enable_subvp = true;
@@ -448,12 +453,374 @@ void get_subvp_visual_confirm_color(
if (enable_subvp && pipe_ctx->stream->mall_stream_config.type == SUBVP_NONE) {
color->color_r_cr = 0;
- if (pipe_ctx->stream->ignore_msa_timing_param == 1)
+ if (pipe_ctx->stream->allow_freesync == 1) {
/* SubVP enable and DRR on - green */
+ color->color_b_cb = 0;
color->color_g_y = color_value;
- else
+ } else {
/* SubVP enable and No DRR - blue */
+ color->color_g_y = 0;
color->color_b_cb = color_value;
+ }
+ }
+}
+
+void hwss_build_fast_sequence(struct dc *dc,
+ struct dc_dmub_cmd *dc_dmub_cmd,
+ unsigned int dmub_cmd_count,
+ struct block_sequence block_sequence[],
+ int *num_steps,
+ struct pipe_ctx *pipe_ctx)
+{
+ struct dc_plane_state *plane = pipe_ctx->plane_state;
+ struct dc_stream_state *stream = pipe_ctx->stream;
+ struct dce_hwseq *hws = dc->hwseq;
+ struct pipe_ctx *current_pipe = NULL;
+ struct pipe_ctx *current_mpc_pipe = NULL;
+ unsigned int i = 0;
+
+ *num_steps = 0; // Initialize to 0
+
+ if (!plane || !stream)
+ return;
+
+ if (dc->hwss.subvp_pipe_control_lock_fast) {
+ block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
+ block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = true;
+ block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.pipe_ctx = pipe_ctx;
+ block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST;
+ (*num_steps)++;
+ }
+ if (dc->hwss.pipe_control_lock) {
+ block_sequence[*num_steps].params.pipe_control_lock_params.dc = dc;
+ block_sequence[*num_steps].params.pipe_control_lock_params.lock = true;
+ block_sequence[*num_steps].params.pipe_control_lock_params.pipe_ctx = pipe_ctx;
+ block_sequence[*num_steps].func = OPTC_PIPE_CONTROL_LOCK;
+ (*num_steps)++;
+ }
+
+ for (i = 0; i < dmub_cmd_count; i++) {
+ block_sequence[*num_steps].params.send_dmcub_cmd_params.ctx = dc->ctx;
+ block_sequence[*num_steps].params.send_dmcub_cmd_params.cmd = &(dc_dmub_cmd[i].dmub_cmd);
+ block_sequence[*num_steps].params.send_dmcub_cmd_params.wait_type = dc_dmub_cmd[i].wait_type;
+ block_sequence[*num_steps].func = DMUB_SEND_DMCUB_CMD;
+ (*num_steps)++;
+ }
+
+ current_pipe = pipe_ctx;
+ while (current_pipe) {
+ current_mpc_pipe = current_pipe;
+ while (current_mpc_pipe) {
+ if (dc->hwss.set_flip_control_gsl && current_mpc_pipe->plane_state && current_mpc_pipe->plane_state->update_flags.raw) {
+ block_sequence[*num_steps].params.set_flip_control_gsl_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].params.set_flip_control_gsl_params.flip_immediate = current_mpc_pipe->plane_state->flip_immediate;
+ block_sequence[*num_steps].func = HUBP_SET_FLIP_CONTROL_GSL;
+ (*num_steps)++;
+ }
+ if (dc->hwss.program_triplebuffer && dc->debug.enable_tri_buf && current_mpc_pipe->plane_state->update_flags.raw) {
+ block_sequence[*num_steps].params.program_triplebuffer_params.dc = dc;
+ block_sequence[*num_steps].params.program_triplebuffer_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].params.program_triplebuffer_params.enableTripleBuffer = current_mpc_pipe->plane_state->triplebuffer_flips;
+ block_sequence[*num_steps].func = HUBP_PROGRAM_TRIPLEBUFFER;
+ (*num_steps)++;
+ }
+ if (dc->hwss.update_plane_addr && current_mpc_pipe->plane_state->update_flags.bits.addr_update) {
+ block_sequence[*num_steps].params.update_plane_addr_params.dc = dc;
+ block_sequence[*num_steps].params.update_plane_addr_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].func = HUBP_UPDATE_PLANE_ADDR;
+ (*num_steps)++;
+ }
+
+ if (hws->funcs.set_input_transfer_func && current_mpc_pipe->plane_state->update_flags.bits.gamma_change) {
+ block_sequence[*num_steps].params.set_input_transfer_func_params.dc = dc;
+ block_sequence[*num_steps].params.set_input_transfer_func_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].params.set_input_transfer_func_params.plane_state = current_mpc_pipe->plane_state;
+ block_sequence[*num_steps].func = DPP_SET_INPUT_TRANSFER_FUNC;
+ (*num_steps)++;
+ }
+
+ if (dc->hwss.program_gamut_remap && current_mpc_pipe->plane_state->update_flags.bits.gamut_remap_change) {
+ block_sequence[*num_steps].params.program_gamut_remap_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].func = DPP_PROGRAM_GAMUT_REMAP;
+ (*num_steps)++;
+ }
+ if (current_mpc_pipe->plane_state->update_flags.bits.input_csc_change) {
+ block_sequence[*num_steps].params.setup_dpp_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].func = DPP_SETUP_DPP;
+ (*num_steps)++;
+ }
+ if (current_mpc_pipe->plane_state->update_flags.bits.coeff_reduction_change) {
+ block_sequence[*num_steps].params.program_bias_and_scale_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].func = DPP_PROGRAM_BIAS_AND_SCALE;
+ (*num_steps)++;
+ }
+ if (hws->funcs.set_output_transfer_func && current_mpc_pipe->stream->update_flags.bits.out_tf) {
+ block_sequence[*num_steps].params.set_output_transfer_func_params.dc = dc;
+ block_sequence[*num_steps].params.set_output_transfer_func_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].params.set_output_transfer_func_params.stream = current_mpc_pipe->stream;
+ block_sequence[*num_steps].func = DPP_SET_OUTPUT_TRANSFER_FUNC;
+ (*num_steps)++;
+ }
+
+ if (current_mpc_pipe->stream->update_flags.bits.out_csc) {
+ block_sequence[*num_steps].params.power_on_mpc_mem_pwr_params.mpc = dc->res_pool->mpc;
+ block_sequence[*num_steps].params.power_on_mpc_mem_pwr_params.mpcc_id = current_mpc_pipe->plane_res.hubp->inst;
+ block_sequence[*num_steps].params.power_on_mpc_mem_pwr_params.power_on = true;
+ block_sequence[*num_steps].func = MPC_POWER_ON_MPC_MEM_PWR;
+ (*num_steps)++;
+
+ if (current_mpc_pipe->stream->csc_color_matrix.enable_adjustment == true) {
+ block_sequence[*num_steps].params.set_output_csc_params.mpc = dc->res_pool->mpc;
+ block_sequence[*num_steps].params.set_output_csc_params.opp_id = current_mpc_pipe->stream_res.opp->inst;
+ block_sequence[*num_steps].params.set_output_csc_params.regval = current_mpc_pipe->stream->csc_color_matrix.matrix;
+ block_sequence[*num_steps].params.set_output_csc_params.ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
+ block_sequence[*num_steps].func = MPC_SET_OUTPUT_CSC;
+ (*num_steps)++;
+ } else {
+ block_sequence[*num_steps].params.set_ocsc_default_params.mpc = dc->res_pool->mpc;
+ block_sequence[*num_steps].params.set_ocsc_default_params.opp_id = current_mpc_pipe->stream_res.opp->inst;
+ block_sequence[*num_steps].params.set_ocsc_default_params.color_space = current_mpc_pipe->stream->output_color_space;
+ block_sequence[*num_steps].params.set_ocsc_default_params.ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
+ block_sequence[*num_steps].func = MPC_SET_OCSC_DEFAULT;
+ (*num_steps)++;
+ }
+ }
+ current_mpc_pipe = current_mpc_pipe->bottom_pipe;
+ }
+ current_pipe = current_pipe->next_odm_pipe;
+ }
+
+ if (dc->hwss.pipe_control_lock) {
+ block_sequence[*num_steps].params.pipe_control_lock_params.dc = dc;
+ block_sequence[*num_steps].params.pipe_control_lock_params.lock = false;
+ block_sequence[*num_steps].params.pipe_control_lock_params.pipe_ctx = pipe_ctx;
+ block_sequence[*num_steps].func = OPTC_PIPE_CONTROL_LOCK;
+ (*num_steps)++;
+ }
+ if (dc->hwss.subvp_pipe_control_lock_fast) {
+ block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
+ block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = false;
+ block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.pipe_ctx = pipe_ctx;
+ block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST;
+ (*num_steps)++;
+ }
+
+ current_pipe = pipe_ctx;
+ while (current_pipe) {
+ current_mpc_pipe = current_pipe;
+
+ while (current_mpc_pipe) {
+ if (!current_mpc_pipe->bottom_pipe && !pipe_ctx->next_odm_pipe &&
+ current_mpc_pipe->stream && current_mpc_pipe->plane_state &&
+ current_mpc_pipe->plane_state->update_flags.bits.addr_update &&
+ !current_mpc_pipe->plane_state->skip_manual_trigger) {
+ block_sequence[*num_steps].params.program_manual_trigger_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].func = OPTC_PROGRAM_MANUAL_TRIGGER;
+ (*num_steps)++;
+ }
+ current_mpc_pipe = current_mpc_pipe->bottom_pipe;
+ }
+ current_pipe = current_pipe->next_odm_pipe;
+ }
+}
+
+void hwss_execute_sequence(struct dc *dc,
+ struct block_sequence block_sequence[],
+ int num_steps)
+{
+ unsigned int i;
+ union block_sequence_params *params;
+ struct dce_hwseq *hws = dc->hwseq;
+
+ for (i = 0; i < num_steps; i++) {
+ params = &(block_sequence[i].params);
+ switch (block_sequence[i].func) {
+
+ case DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST:
+ dc->hwss.subvp_pipe_control_lock_fast(params);
+ break;
+ case OPTC_PIPE_CONTROL_LOCK:
+ dc->hwss.pipe_control_lock(params->pipe_control_lock_params.dc,
+ params->pipe_control_lock_params.pipe_ctx,
+ params->pipe_control_lock_params.lock);
+ break;
+ case HUBP_SET_FLIP_CONTROL_GSL:
+ dc->hwss.set_flip_control_gsl(params->set_flip_control_gsl_params.pipe_ctx,
+ params->set_flip_control_gsl_params.flip_immediate);
+ break;
+ case HUBP_PROGRAM_TRIPLEBUFFER:
+ dc->hwss.program_triplebuffer(params->program_triplebuffer_params.dc,
+ params->program_triplebuffer_params.pipe_ctx,
+ params->program_triplebuffer_params.enableTripleBuffer);
+ break;
+ case HUBP_UPDATE_PLANE_ADDR:
+ dc->hwss.update_plane_addr(params->update_plane_addr_params.dc,
+ params->update_plane_addr_params.pipe_ctx);
+ break;
+ case DPP_SET_INPUT_TRANSFER_FUNC:
+ hws->funcs.set_input_transfer_func(params->set_input_transfer_func_params.dc,
+ params->set_input_transfer_func_params.pipe_ctx,
+ params->set_input_transfer_func_params.plane_state);
+ break;
+ case DPP_PROGRAM_GAMUT_REMAP:
+ dc->hwss.program_gamut_remap(params->program_gamut_remap_params.pipe_ctx);
+ break;
+ case DPP_SETUP_DPP:
+ hwss_setup_dpp(params);
+ break;
+ case DPP_PROGRAM_BIAS_AND_SCALE:
+ hwss_program_bias_and_scale(params);
+ break;
+ case OPTC_PROGRAM_MANUAL_TRIGGER:
+ hwss_program_manual_trigger(params);
+ break;
+ case DPP_SET_OUTPUT_TRANSFER_FUNC:
+ hws->funcs.set_output_transfer_func(params->set_output_transfer_func_params.dc,
+ params->set_output_transfer_func_params.pipe_ctx,
+ params->set_output_transfer_func_params.stream);
+ break;
+ case MPC_UPDATE_VISUAL_CONFIRM:
+ dc->hwss.update_visual_confirm_color(params->update_visual_confirm_params.dc,
+ params->update_visual_confirm_params.pipe_ctx,
+ params->update_visual_confirm_params.mpcc_id);
+ break;
+ case MPC_POWER_ON_MPC_MEM_PWR:
+ hwss_power_on_mpc_mem_pwr(params);
+ break;
+ case MPC_SET_OUTPUT_CSC:
+ hwss_set_output_csc(params);
+ break;
+ case MPC_SET_OCSC_DEFAULT:
+ hwss_set_ocsc_default(params);
+ break;
+ case DMUB_SEND_DMCUB_CMD:
+ hwss_send_dmcub_cmd(params);
+ break;
+ default:
+ ASSERT(false);
+ break;
+ }
+ }
+}
+
+void hwss_send_dmcub_cmd(union block_sequence_params *params)
+{
+ struct dc_context *ctx = params->send_dmcub_cmd_params.ctx;
+ union dmub_rb_cmd *cmd = params->send_dmcub_cmd_params.cmd;
+ enum dm_dmub_wait_type wait_type = params->send_dmcub_cmd_params.wait_type;
+
+ dm_execute_dmub_cmd(ctx, cmd, wait_type);
+}
+
+void hwss_program_manual_trigger(union block_sequence_params *params)
+{
+ struct pipe_ctx *pipe_ctx = params->program_manual_trigger_params.pipe_ctx;
+
+ if (pipe_ctx->stream_res.tg->funcs->program_manual_trigger)
+ pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg);
+}
+
+void hwss_setup_dpp(union block_sequence_params *params)
+{
+ struct pipe_ctx *pipe_ctx = params->setup_dpp_params.pipe_ctx;
+ struct dpp *dpp = pipe_ctx->plane_res.dpp;
+ struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+
+ if (dpp && dpp->funcs->dpp_setup) {
+ // program the input csc
+ dpp->funcs->dpp_setup(dpp,
+ plane_state->format,
+ EXPANSION_MODE_ZERO,
+ plane_state->input_csc_color_matrix,
+ plane_state->color_space,
+ NULL);
+ }
+}
+
+void hwss_program_bias_and_scale(union block_sequence_params *params)
+{
+ struct pipe_ctx *pipe_ctx = params->program_bias_and_scale_params.pipe_ctx;
+ struct dpp *dpp = pipe_ctx->plane_res.dpp;
+ struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+ struct dc_bias_and_scale bns_params = {0};
+
+ //TODO :for CNVC set scale and bias registers if necessary
+ build_prescale_params(&bns_params, plane_state);
+ if (dpp->funcs->dpp_program_bias_and_scale)
+ dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
+}
+
+void hwss_power_on_mpc_mem_pwr(union block_sequence_params *params)
+{
+ struct mpc *mpc = params->power_on_mpc_mem_pwr_params.mpc;
+ int mpcc_id = params->power_on_mpc_mem_pwr_params.mpcc_id;
+ bool power_on = params->power_on_mpc_mem_pwr_params.power_on;
+
+ if (mpc->funcs->power_on_mpc_mem_pwr)
+ mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, power_on);
+}
+
+void hwss_set_output_csc(union block_sequence_params *params)
+{
+ struct mpc *mpc = params->set_output_csc_params.mpc;
+ int opp_id = params->set_output_csc_params.opp_id;
+ const uint16_t *matrix = params->set_output_csc_params.regval;
+ enum mpc_output_csc_mode ocsc_mode = params->set_output_csc_params.ocsc_mode;
+
+ if (mpc->funcs->set_output_csc != NULL)
+ mpc->funcs->set_output_csc(mpc,
+ opp_id,
+ matrix,
+ ocsc_mode);
+}
+
+void hwss_set_ocsc_default(union block_sequence_params *params)
+{
+ struct mpc *mpc = params->set_ocsc_default_params.mpc;
+ int opp_id = params->set_ocsc_default_params.opp_id;
+ enum dc_color_space colorspace = params->set_ocsc_default_params.color_space;
+ enum mpc_output_csc_mode ocsc_mode = params->set_ocsc_default_params.ocsc_mode;
+
+ if (mpc->funcs->set_ocsc_default != NULL)
+ mpc->funcs->set_ocsc_default(mpc,
+ opp_id,
+ colorspace,
+ ocsc_mode);
+}
+
+void get_mclk_switch_visual_confirm_color(
+ struct dc *dc,
+ struct dc_state *context,
+ struct pipe_ctx *pipe_ctx,
+ struct tg_color *color)
+{
+ uint32_t color_value = MAX_TG_COLOR_VALUE;
+ struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
+
+ if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba || !context)
+ return;
+
+ if (vba->DRAMClockChangeSupport[vba->VoltageLevel][vba->maxMpcComb] !=
+ dm_dram_clock_change_unsupported) {
+ /* MCLK switching is supported */
+ if (!pipe_ctx->has_vactive_margin) {
+ /* In Vblank - yellow */
+ color->color_r_cr = color_value;
+ color->color_g_y = color_value;
+
+ if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
+ /* FPO + Vblank - cyan */
+ color->color_r_cr = 0;
+ color->color_g_y = color_value;
+ color->color_b_cb = color_value;
+ }
+ } else {
+ /* In Vactive - pink */
+ color->color_r_cr = color_value;
+ color->color_b_cb = color_value;
+ }
+ /* SubVP */
+ get_subvp_visual_confirm_color(dc, context, pipe_ctx, color);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index fe1551393b26..2f3d9a698486 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -69,6 +69,7 @@
#include "../dcn32/dcn32_resource.h"
#include "../dcn321/dcn321_resource.h"
+
#define DC_LOGGER_INIT(logger)
enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
@@ -1878,7 +1879,7 @@ bool dc_add_all_planes_for_stream(
return add_all_planes_for_stream(dc, stream, &set, 1, context);
}
-bool is_timing_changed(struct dc_stream_state *cur_stream,
+bool dc_is_timing_changed(struct dc_stream_state *cur_stream,
struct dc_stream_state *new_stream)
{
if (cur_stream == NULL)
@@ -1903,7 +1904,7 @@ static bool are_stream_backends_same(
if (stream_a == NULL || stream_b == NULL)
return false;
- if (is_timing_changed(stream_a, stream_b))
+ if (dc_is_timing_changed(stream_a, stream_b))
return false;
if (stream_a->signal != stream_b->signal)
@@ -3034,23 +3035,29 @@ static void set_avi_info_frame(
hdmi_info.bits.S0_S1 = scan_type;
/* C0, C1 : Colorimetry */
- if (color_space == COLOR_SPACE_YCBCR709 ||
- color_space == COLOR_SPACE_YCBCR709_LIMITED)
+ switch (color_space) {
+ case COLOR_SPACE_YCBCR709:
+ case COLOR_SPACE_YCBCR709_LIMITED:
hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709;
- else if (color_space == COLOR_SPACE_YCBCR601 ||
- color_space == COLOR_SPACE_YCBCR601_LIMITED)
+ break;
+ case COLOR_SPACE_YCBCR601:
+ case COLOR_SPACE_YCBCR601_LIMITED:
hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601;
- else {
- hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA;
- }
- if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
- color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
- color_space == COLOR_SPACE_2020_YCBCR) {
+ break;
+ case COLOR_SPACE_2020_RGB_FULLRANGE:
+ case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
+ case COLOR_SPACE_2020_YCBCR:
hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR;
hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED;
- } else if (color_space == COLOR_SPACE_ADOBERGB) {
+ break;
+ case COLOR_SPACE_ADOBERGB:
hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB;
hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED;
+ break;
+ case COLOR_SPACE_SRGB:
+ default:
+ hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA;
+ break;
}
if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR &&
@@ -3528,7 +3535,7 @@ bool pipe_need_reprogram(
if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc)
return true;
- if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
+ if (dc_is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
return true;
if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index 72b261ad9587..6e11d2b701f8 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -276,8 +276,8 @@ static void program_cursor_attributes(
}
dc->hwss.set_cursor_attribute(pipe_ctx);
-
- dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
+ if (dc->ctx->dmub_srv)
+ dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
if (dc->hwss.set_cursor_sdr_white_level)
dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
}
@@ -396,8 +396,8 @@ static void program_cursor_position(
}
dc->hwss.set_cursor_position(pipe_ctx);
-
- dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
+ if (dc->ctx->dmub_srv)
+ dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
}
if (pipe_to_program)
@@ -490,25 +490,6 @@ bool dc_stream_add_writeback(struct dc *dc,
struct dwbc *dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
dwb->otg_inst = stream_status->primary_otg_inst;
}
- if (IS_DIAG_DC(dc->ctx->dce_environment)) {
- if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
- dm_error("DC: update_bandwidth failed!\n");
- return false;
- }
-
- /* enable writeback */
- if (dc->hwss.enable_writeback) {
- struct dwbc *dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
-
- if (dwb->funcs->is_enabled(dwb)) {
- /* writeback pipe already enabled, only need to update */
- dc->hwss.update_writeback(dc, wb_info, dc->current_state);
- } else {
- /* Enable writeback pipe from scratch*/
- dc->hwss.enable_writeback(dc, wb_info, dc->current_state);
- }
- }
- }
return true;
}
@@ -553,17 +534,6 @@ bool dc_stream_remove_writeback(struct dc *dc,
}
stream->num_wb_info = j;
- if (IS_DIAG_DC(dc->ctx->dce_environment)) {
- /* recalculate and apply DML parameters */
- if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
- dm_error("DC: update_bandwidth failed!\n");
- return false;
- }
-
- /* disable writeback */
- if (dc->hwss.disable_writeback)
- dc->hwss.disable_writeback(dc, dwb_pipe_inst);
- }
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 30f0ba05a6e6..26d05e225088 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-14 Advanced Micro Devices, Inc.
+ * Copyright 2012-2023 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -45,7 +45,7 @@ struct aux_payload;
struct set_config_cmd_payload;
struct dmub_notification;
-#define DC_VER "3.2.230"
+#define DC_VER "3.2.239"
#define MAX_SURFACES 3
#define MAX_PLANES 6
@@ -60,7 +60,9 @@ struct dc_versions {
};
enum dp_protocol_version {
- DP_VERSION_1_4,
+ DP_VERSION_1_4 = 0,
+ DP_VERSION_2_1,
+ DP_VERSION_UNKNOWN,
};
enum dc_plane_type {
@@ -209,6 +211,8 @@ struct dc_color_caps {
struct dc_dmub_caps {
bool psr;
bool mclk_sw;
+ bool subvp_psr;
+ bool gecc_enable;
};
struct dc_caps {
@@ -262,6 +266,7 @@ struct dc_caps {
uint16_t subvp_pstate_allow_width_us;
uint16_t subvp_vertical_int_margin_us;
bool seamless_odm;
+ uint32_t max_v_total;
uint8_t subvp_drr_vblank_start_margin_us;
};
@@ -270,8 +275,13 @@ struct dc_bug_wa {
bool dedcn20_305_wa;
bool skip_clock_update;
bool lt_early_cr_pattern;
+ struct {
+ uint8_t uclk : 1;
+ uint8_t fclk : 1;
+ uint8_t dcfclk : 1;
+ uint8_t dcfclk_ds: 1;
+ } clock_update_disable_mask;
};
-
struct dc_dcc_surface_param {
struct dc_size surface_size;
enum surface_pixel_format format;
@@ -419,6 +429,7 @@ enum visual_confirm {
VISUAL_CONFIRM_FAMS = 7,
VISUAL_CONFIRM_SWIZZLE = 9,
VISUAL_CONFIRM_SUBVP = 14,
+ VISUAL_CONFIRM_MCLK_SWITCH = 16,
};
enum dc_psr_power_opts {
@@ -698,6 +709,8 @@ struct dc_virtual_addr_space_config {
struct dc_bounding_box_overrides {
int sr_exit_time_ns;
int sr_enter_plus_exit_time_ns;
+ int sr_exit_z8_time_ns;
+ int sr_enter_plus_exit_z8_time_ns;
int urgent_latency_ns;
int percent_of_ideal_drambw;
int dram_clock_change_latency_ns;
@@ -767,6 +780,8 @@ struct dc_debug_options {
int sr_enter_plus_exit_time_dpm0_ns;
int sr_exit_time_ns;
int sr_enter_plus_exit_time_ns;
+ int sr_exit_z8_time_ns;
+ int sr_enter_plus_exit_z8_time_ns;
int urgent_latency_ns;
uint32_t underflow_assert_delay_us;
int percent_of_ideal_drambw;
@@ -855,7 +870,6 @@ struct dc_debug_options {
bool force_usr_allow;
/* uses value at boot and disables switch */
bool disable_dtb_ref_clk_switch;
- uint32_t fixed_vs_aux_delay_config_wa;
bool extended_blank_optimization;
union aux_wake_wa_options aux_wake_wa;
uint32_t mst_start_top_delay;
@@ -879,6 +893,14 @@ struct dc_debug_options {
uint32_t fpo_vactive_margin_us;
bool disable_fpo_vactive;
bool disable_boot_optimizations;
+ bool override_odm_optimization;
+ bool minimize_dispclk_using_odm;
+ bool disable_subvp_high_refresh;
+ bool disable_dp_plus_plus_wa;
+ uint32_t fpo_vactive_min_active_margin_us;
+ uint32_t fpo_vactive_max_blank_us;
+ bool enable_legacy_fast_update;
+ bool disable_dc_mode_overwrite;
};
struct gpu_info_soc_bounding_box_v1_0;
@@ -1502,6 +1524,7 @@ struct dc_link {
/* Forced DPIA into TBT3 compatibility mode. */
bool dpia_forced_tbt3_mode;
bool dongle_mode_timing_override;
+ bool blank_stream_on_ocs_change;
} wa_flags;
struct link_mst_stream_allocation_table mst_stream_alloc_table;
@@ -2126,8 +2149,6 @@ struct dc_sink_init_data {
bool converter_disable_audio;
};
-bool dc_extended_blank_supported(struct dc *dc);
-
struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params);
/* Newer interfaces */
@@ -2220,10 +2241,15 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc,
uint32_t hpd_int_enable);
+void dc_print_dmub_diagnostic_data(const struct dc *dc);
+
/* DSC Interfaces */
#include "dc_dsc.h"
/* Disable acc mode Interfaces */
void dc_disable_accelerated_mode(struct dc *dc);
+bool dc_is_timing_changed(struct dc_stream_state *cur_stream,
+ struct dc_stream_state *new_stream);
+
#endif /* DC_INTERFACE_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
index a9b9490a532c..c52c40b16387 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -65,47 +65,6 @@ void dc_dmub_srv_destroy(struct dc_dmub_srv **dmub_srv)
}
}
-void dc_dmub_srv_cmd_queue(struct dc_dmub_srv *dc_dmub_srv,
- union dmub_rb_cmd *cmd)
-{
- struct dmub_srv *dmub = dc_dmub_srv->dmub;
- struct dc_context *dc_ctx = dc_dmub_srv->ctx;
- enum dmub_status status;
-
- status = dmub_srv_cmd_queue(dmub, cmd);
- if (status == DMUB_STATUS_OK)
- return;
-
- if (status != DMUB_STATUS_QUEUE_FULL)
- goto error;
-
- /* Execute and wait for queue to become empty again. */
- dc_dmub_srv_cmd_execute(dc_dmub_srv);
- dc_dmub_srv_wait_idle(dc_dmub_srv);
-
- /* Requeue the command. */
- status = dmub_srv_cmd_queue(dmub, cmd);
- if (status == DMUB_STATUS_OK)
- return;
-
-error:
- DC_ERROR("Error queuing DMUB command: status=%d\n", status);
- dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
-}
-
-void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv)
-{
- struct dmub_srv *dmub = dc_dmub_srv->dmub;
- struct dc_context *dc_ctx = dc_dmub_srv->ctx;
- enum dmub_status status;
-
- status = dmub_srv_cmd_execute(dmub);
- if (status != DMUB_STATUS_OK) {
- DC_ERROR("Error starting DMUB execution: status=%d\n", status);
- dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
- }
-}
-
void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv)
{
struct dmub_srv *dmub = dc_dmub_srv->dmub;
@@ -159,50 +118,89 @@ void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
}
}
-bool dc_dmub_srv_cmd_with_reply_data(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd)
+bool dc_dmub_srv_cmd_run(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
+{
+ return dc_dmub_srv_cmd_run_list(dc_dmub_srv, 1, cmd, wait_type);
+}
+
+bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int count, union dmub_rb_cmd *cmd_list, enum dm_dmub_wait_type wait_type)
{
+ struct dc_context *dc_ctx;
struct dmub_srv *dmub;
enum dmub_status status;
+ int i;
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
return false;
+ dc_ctx = dc_dmub_srv->ctx;
dmub = dc_dmub_srv->dmub;
- status = dmub_srv_cmd_with_reply_data(dmub, cmd);
+ for (i = 0 ; i < count; i++) {
+ // Queue command
+ status = dmub_srv_cmd_queue(dmub, &cmd_list[i]);
+
+ if (status == DMUB_STATUS_QUEUE_FULL) {
+ /* Execute and wait for queue to become empty again. */
+ dmub_srv_cmd_execute(dmub);
+ dmub_srv_wait_for_idle(dmub, 100000);
+
+ /* Requeue the command. */
+ status = dmub_srv_cmd_queue(dmub, &cmd_list[i]);
+ }
+
+ if (status != DMUB_STATUS_OK) {
+ DC_ERROR("Error queueing DMUB command: status=%d\n", status);
+ dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ return false;
+ }
+ }
+
+ status = dmub_srv_cmd_execute(dmub);
if (status != DMUB_STATUS_OK) {
- DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status);
+ DC_ERROR("Error starting DMUB execution: status=%d\n", status);
+ dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
return false;
}
+ // Wait for DMUB to process command
+ if (wait_type != DM_DMUB_WAIT_TYPE_NO_WAIT) {
+ status = dmub_srv_wait_for_idle(dmub, 100000);
+
+ if (status != DMUB_STATUS_OK) {
+ DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status);
+ dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ return false;
+ }
+
+ // Copy data back from ring buffer into command
+ if (wait_type == DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)
+ dmub_rb_get_return_data(&dmub->inbox1_rb, cmd_list);
+ }
+
return true;
}
-void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv)
+bool dc_dmub_srv_optimized_init_done(struct dc_dmub_srv *dc_dmub_srv)
{
- struct dmub_srv *dmub = dc_dmub_srv->dmub;
- struct dc_context *dc_ctx = dc_dmub_srv->ctx;
+ struct dmub_srv *dmub;
+ struct dc_context *dc_ctx;
+ union dmub_fw_boot_status boot_status;
enum dmub_status status;
- for (;;) {
- /* Wait up to a second for PHY init. */
- status = dmub_srv_wait_for_phy_init(dmub, 1000000);
- if (status == DMUB_STATUS_OK)
- /* Initialization OK */
- break;
-
- DC_ERROR("DMCUB PHY init failed: status=%d\n", status);
- ASSERT(0);
+ if (!dc_dmub_srv || !dc_dmub_srv->dmub)
+ return false;
- if (status != DMUB_STATUS_TIMEOUT)
- /*
- * Server likely initialized or we don't have
- * DMCUB HW support - this won't end.
- */
- break;
+ dmub = dc_dmub_srv->dmub;
+ dc_ctx = dc_dmub_srv->ctx;
- /* Continue spinning so we don't hang the ASIC. */
+ status = dmub_srv_get_fw_boot_status(dmub, &boot_status);
+ if (status != DMUB_STATUS_OK) {
+ DC_ERROR("Error querying DMUB boot status: error=%d\n", status);
+ return false;
}
+
+ return boot_status.bits.optimized_init_done;
}
bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv,
@@ -267,9 +265,7 @@ void dc_dmub_srv_drr_update_cmd(struct dc *dc, uint32_t tg_inst, uint32_t vtotal
cmd.drr_update.header.payload_bytes = sizeof(cmd.drr_update) - sizeof(cmd.drr_update.header);
// Send the command to the DMCUB.
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
void dc_dmub_srv_set_drr_manual_trigger_cmd(struct dc *dc, uint32_t tg_inst)
@@ -283,9 +279,7 @@ void dc_dmub_srv_set_drr_manual_trigger_cmd(struct dc *dc, uint32_t tg_inst)
cmd.drr_update.header.payload_bytes = sizeof(cmd.drr_update) - sizeof(cmd.drr_update.header);
// Send the command to the DMCUB.
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static uint8_t dc_dmub_srv_get_pipes_for_stream(struct dc *dc, struct dc_stream_state *stream)
@@ -378,21 +372,14 @@ bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, stru
sizeof(cmd.fw_assisted_mclk_switch) - sizeof(cmd.fw_assisted_mclk_switch.header);
// Send the command to the DMCUB.
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
-void dc_dmub_srv_query_caps_cmd(struct dmub_srv *dmub)
+void dc_dmub_srv_query_caps_cmd(struct dc_dmub_srv *dc_dmub_srv)
{
union dmub_rb_cmd cmd = { 0 };
- enum dmub_status status;
-
- if (!dmub) {
- return;
- }
memset(&cmd, 0, sizeof(cmd));
@@ -402,15 +389,10 @@ void dc_dmub_srv_query_caps_cmd(struct dmub_srv *dmub)
cmd.query_feature_caps.header.ret_status = 1;
cmd.query_feature_caps.header.payload_bytes = sizeof(struct dmub_cmd_query_feature_caps_data);
- /* Send command to fw */
- status = dmub_srv_cmd_with_reply_data(dmub, &cmd);
-
- ASSERT(status == DMUB_STATUS_OK);
-
/* If command was processed, copy feature caps to dmub srv */
- if (status == DMUB_STATUS_OK &&
+ if (dm_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) &&
cmd.query_feature_caps.header.ret_status == 0) {
- memcpy(&dmub->feature_caps,
+ memcpy(&dc_dmub_srv->dmub->feature_caps,
&cmd.query_feature_caps.query_feature_caps_data,
sizeof(struct dmub_feature_caps));
}
@@ -419,7 +401,6 @@ void dc_dmub_srv_query_caps_cmd(struct dmub_srv *dmub)
void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
union dmub_rb_cmd cmd = { 0 };
- enum dmub_status status;
unsigned int panel_inst = 0;
dc_get_edp_link_panel_inst(dc, pipe_ctx->stream->link, &panel_inst);
@@ -433,13 +414,8 @@ void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pi
cmd.visual_confirm_color.header.payload_bytes = sizeof(struct dmub_cmd_visual_confirm_color_data);
cmd.visual_confirm_color.visual_confirm_color_data.visual_confirm_color.panel_inst = panel_inst;
- // Send command to fw
- status = dmub_srv_cmd_with_reply_data(dc->ctx->dmub_srv->dmub, &cmd);
-
- ASSERT(status == DMUB_STATUS_OK);
-
// If command was processed, copy feature caps to dmub srv
- if (status == DMUB_STATUS_OK &&
+ if (dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) &&
cmd.visual_confirm_color.header.ret_status == 0) {
memcpy(&dc->ctx->dmub_srv->dmub->visual_confirm_color,
&cmd.visual_confirm_color.visual_confirm_color_data,
@@ -797,9 +773,8 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
cmd.fw_assisted_mclk_switch_v2.config_data.watermark_a_cache = wm_val_refclk < 0xFFFF ? wm_val_refclk : 0xFFFF;
}
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *diag_data)
@@ -823,74 +798,40 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
return;
}
- DC_LOG_DEBUG(
- "DMCUB STATE\n"
- " dmcub_version : %08x\n"
- " scratch [0] : %08x\n"
- " scratch [1] : %08x\n"
- " scratch [2] : %08x\n"
- " scratch [3] : %08x\n"
- " scratch [4] : %08x\n"
- " scratch [5] : %08x\n"
- " scratch [6] : %08x\n"
- " scratch [7] : %08x\n"
- " scratch [8] : %08x\n"
- " scratch [9] : %08x\n"
- " scratch [10] : %08x\n"
- " scratch [11] : %08x\n"
- " scratch [12] : %08x\n"
- " scratch [13] : %08x\n"
- " scratch [14] : %08x\n"
- " scratch [15] : %08x\n"
- " pc : %08x\n"
- " unk_fault_addr : %08x\n"
- " inst_fault_addr : %08x\n"
- " data_fault_addr : %08x\n"
- " inbox1_rptr : %08x\n"
- " inbox1_wptr : %08x\n"
- " inbox1_size : %08x\n"
- " inbox0_rptr : %08x\n"
- " inbox0_wptr : %08x\n"
- " inbox0_size : %08x\n"
- " is_enabled : %d\n"
- " is_soft_reset : %d\n"
- " is_secure_reset : %d\n"
- " is_traceport_en : %d\n"
- " is_cw0_en : %d\n"
- " is_cw6_en : %d\n",
- diag_data.dmcub_version,
- diag_data.scratch[0],
- diag_data.scratch[1],
- diag_data.scratch[2],
- diag_data.scratch[3],
- diag_data.scratch[4],
- diag_data.scratch[5],
- diag_data.scratch[6],
- diag_data.scratch[7],
- diag_data.scratch[8],
- diag_data.scratch[9],
- diag_data.scratch[10],
- diag_data.scratch[11],
- diag_data.scratch[12],
- diag_data.scratch[13],
- diag_data.scratch[14],
- diag_data.scratch[15],
- diag_data.pc,
- diag_data.undefined_address_fault_addr,
- diag_data.inst_fetch_fault_addr,
- diag_data.data_write_fault_addr,
- diag_data.inbox1_rptr,
- diag_data.inbox1_wptr,
- diag_data.inbox1_size,
- diag_data.inbox0_rptr,
- diag_data.inbox0_wptr,
- diag_data.inbox0_size,
- diag_data.is_dmcub_enabled,
- diag_data.is_dmcub_soft_reset,
- diag_data.is_dmcub_secure_reset,
- diag_data.is_traceport_en,
- diag_data.is_cw0_enabled,
- diag_data.is_cw6_enabled);
+ DC_LOG_DEBUG("DMCUB STATE:");
+ DC_LOG_DEBUG(" dmcub_version : %08x", diag_data.dmcub_version);
+ DC_LOG_DEBUG(" scratch [0] : %08x", diag_data.scratch[0]);
+ DC_LOG_DEBUG(" scratch [1] : %08x", diag_data.scratch[1]);
+ DC_LOG_DEBUG(" scratch [2] : %08x", diag_data.scratch[2]);
+ DC_LOG_DEBUG(" scratch [3] : %08x", diag_data.scratch[3]);
+ DC_LOG_DEBUG(" scratch [4] : %08x", diag_data.scratch[4]);
+ DC_LOG_DEBUG(" scratch [5] : %08x", diag_data.scratch[5]);
+ DC_LOG_DEBUG(" scratch [6] : %08x", diag_data.scratch[6]);
+ DC_LOG_DEBUG(" scratch [7] : %08x", diag_data.scratch[7]);
+ DC_LOG_DEBUG(" scratch [8] : %08x", diag_data.scratch[8]);
+ DC_LOG_DEBUG(" scratch [9] : %08x", diag_data.scratch[9]);
+ DC_LOG_DEBUG(" scratch [10] : %08x", diag_data.scratch[10]);
+ DC_LOG_DEBUG(" scratch [11] : %08x", diag_data.scratch[11]);
+ DC_LOG_DEBUG(" scratch [12] : %08x", diag_data.scratch[12]);
+ DC_LOG_DEBUG(" scratch [13] : %08x", diag_data.scratch[13]);
+ DC_LOG_DEBUG(" scratch [14] : %08x", diag_data.scratch[14]);
+ DC_LOG_DEBUG(" scratch [15] : %08x", diag_data.scratch[15]);
+ DC_LOG_DEBUG(" pc : %08x", diag_data.pc);
+ DC_LOG_DEBUG(" unk_fault_addr : %08x", diag_data.undefined_address_fault_addr);
+ DC_LOG_DEBUG(" inst_fault_addr : %08x", diag_data.inst_fetch_fault_addr);
+ DC_LOG_DEBUG(" data_fault_addr : %08x", diag_data.data_write_fault_addr);
+ DC_LOG_DEBUG(" inbox1_rptr : %08x", diag_data.inbox1_rptr);
+ DC_LOG_DEBUG(" inbox1_wptr : %08x", diag_data.inbox1_wptr);
+ DC_LOG_DEBUG(" inbox1_size : %08x", diag_data.inbox1_size);
+ DC_LOG_DEBUG(" inbox0_rptr : %08x", diag_data.inbox0_rptr);
+ DC_LOG_DEBUG(" inbox0_wptr : %08x", diag_data.inbox0_wptr);
+ DC_LOG_DEBUG(" inbox0_size : %08x", diag_data.inbox0_size);
+ DC_LOG_DEBUG(" is_enabled : %d", diag_data.is_dmcub_enabled);
+ DC_LOG_DEBUG(" is_soft_reset : %d", diag_data.is_dmcub_soft_reset);
+ DC_LOG_DEBUG(" is_secure_reset : %d", diag_data.is_dmcub_secure_reset);
+ DC_LOG_DEBUG(" is_traceport_en : %d", diag_data.is_traceport_en);
+ DC_LOG_DEBUG(" is_cw0_en : %d", diag_data.is_cw0_enabled);
+ DC_LOG_DEBUG(" is_cw6_en : %d", diag_data.is_cw6_enabled);
}
static bool dc_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
@@ -982,14 +923,6 @@ static void dc_build_cursor_update_payload0(
payload->panel_inst = panel_inst;
}
-static void dc_send_cmd_to_dmu(struct dc_dmub_srv *dmub_srv,
- union dmub_rb_cmd *cmd)
-{
- dc_dmub_srv_cmd_queue(dmub_srv, cmd);
- dc_dmub_srv_cmd_execute(dmub_srv);
- dc_dmub_srv_wait_idle(dmub_srv);
-}
-
static void dc_build_cursor_position_update_payload0(
struct dmub_cmd_update_cursor_payload0 *pl, const uint8_t p_idx,
const struct hubp *hubp, const struct dpp *dpp)
@@ -1032,9 +965,11 @@ static void dc_build_cursor_attribute_update_payload1(
void dc_send_update_cursor_info_to_dmu(
struct pipe_ctx *pCtx, uint8_t pipe_idx)
{
- union dmub_rb_cmd cmd = { 0 };
- union dmub_cmd_update_cursor_info_data *update_cursor_info =
- &cmd.update_cursor_info.update_cursor_info_data;
+ union dmub_rb_cmd cmd[2];
+ union dmub_cmd_update_cursor_info_data *update_cursor_info_0 =
+ &cmd[0].update_cursor_info.update_cursor_info_data;
+
+ memset(cmd, 0, sizeof(cmd));
if (!dc_dmub_should_update_cursor_data(pCtx))
return;
@@ -1051,31 +986,28 @@ void dc_send_update_cursor_info_to_dmu(
{
/* Build Payload#0 Header */
- cmd.update_cursor_info.header.type = DMUB_CMD__UPDATE_CURSOR_INFO;
- cmd.update_cursor_info.header.payload_bytes =
- sizeof(cmd.update_cursor_info.update_cursor_info_data);
- cmd.update_cursor_info.header.multi_cmd_pending = 1; /* To combine multi dmu cmd, 1st cmd */
+ cmd[0].update_cursor_info.header.type = DMUB_CMD__UPDATE_CURSOR_INFO;
+ cmd[0].update_cursor_info.header.payload_bytes =
+ sizeof(cmd[0].update_cursor_info.update_cursor_info_data);
+ cmd[0].update_cursor_info.header.multi_cmd_pending = 1; //To combine multi dmu cmd, 1st cmd
/* Prepare Payload */
- dc_build_cursor_update_payload0(pCtx, pipe_idx, &update_cursor_info->payload0);
+ dc_build_cursor_update_payload0(pCtx, pipe_idx, &update_cursor_info_0->payload0);
- dc_build_cursor_position_update_payload0(&update_cursor_info->payload0, pipe_idx,
+ dc_build_cursor_position_update_payload0(&update_cursor_info_0->payload0, pipe_idx,
pCtx->plane_res.hubp, pCtx->plane_res.dpp);
- /* Send update_curosr_info to queue */
- dc_dmub_srv_cmd_queue(pCtx->stream->ctx->dmub_srv, &cmd);
- }
+ }
{
/* Build Payload#1 Header */
- memset(update_cursor_info, 0, sizeof(union dmub_cmd_update_cursor_info_data));
- cmd.update_cursor_info.header.type = DMUB_CMD__UPDATE_CURSOR_INFO;
- cmd.update_cursor_info.header.payload_bytes = sizeof(struct cursor_attributes_cfg);
- cmd.update_cursor_info.header.multi_cmd_pending = 0; /* Indicate it's the last command. */
+ cmd[1].update_cursor_info.header.type = DMUB_CMD__UPDATE_CURSOR_INFO;
+ cmd[1].update_cursor_info.header.payload_bytes = sizeof(struct cursor_attributes_cfg);
+ cmd[1].update_cursor_info.header.multi_cmd_pending = 0; //Indicate it's the last command.
dc_build_cursor_attribute_update_payload1(
- &cmd.update_cursor_info.update_cursor_info_data.payload1.attribute_cfg,
+ &cmd[1].update_cursor_info.update_cursor_info_data.payload1.attribute_cfg,
pipe_idx, pCtx->plane_res.hubp, pCtx->plane_res.dpp);
/* Combine 2nd cmds update_curosr_info to DMU */
- dc_send_cmd_to_dmu(pCtx->stream->ctx->dmub_srv, &cmd);
+ dm_execute_dmub_cmd_list(pCtx->stream->ctx, 2, cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
index d34f5563df2e..a5196a9292b3 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
@@ -26,7 +26,7 @@
#ifndef _DMUB_DC_SRV_H_
#define _DMUB_DC_SRV_H_
-#include "os_types.h"
+#include "dm_services_types.h"
#include "dmub/dmub_srv.h"
struct dmub_srv;
@@ -52,16 +52,13 @@ struct dc_dmub_srv {
void *dm;
};
-void dc_dmub_srv_cmd_queue(struct dc_dmub_srv *dc_dmub_srv,
- union dmub_rb_cmd *cmd);
-
-void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv);
-
void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv);
-void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv);
+bool dc_dmub_srv_optimized_init_done(struct dc_dmub_srv *dc_dmub_srv);
+
+bool dc_dmub_srv_cmd_run(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type);
-bool dc_dmub_srv_cmd_with_reply_data(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd);
+bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int count, union dmub_rb_cmd *cmd_list, enum dm_dmub_wait_type wait_type);
bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv,
unsigned int stream_mask);
@@ -77,7 +74,7 @@ void dc_dmub_srv_drr_update_cmd(struct dc *dc, uint32_t tg_inst, uint32_t vtotal
void dc_dmub_srv_set_drr_manual_trigger_cmd(struct dc *dc, uint32_t tg_inst);
bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool enable_pstate, struct dc_state *context);
-void dc_dmub_srv_query_caps_cmd(struct dmub_srv *dmub);
+void dc_dmub_srv_query_caps_cmd(struct dc_dmub_srv *dc_dmub_srv);
void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pipe_ctx);
void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dmub_srv);
void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dmub_srv);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
index 49aab1924665..55139d7bf422 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
@@ -61,7 +61,7 @@ enum dc_link_rate {
*/
LINK_RATE_UHBR10 = 1000, // UHBR10 - 10.0 Gbps/Lane
LINK_RATE_UHBR13_5 = 1350, // UHBR13.5 - 13.5 Gbps/Lane
- LINK_RATE_UHBR20 = 2000, // UHBR10 - 20.0 Gbps/Lane
+ LINK_RATE_UHBR20 = 2000, // UHBR20 - 20.0 Gbps/Lane
};
enum dc_link_spread {
@@ -566,6 +566,12 @@ struct dpcd_amd_device_id {
uint8_t dal_version_byte2;
};
+struct target_luminance_value {
+ uint8_t byte0;
+ uint8_t byte1;
+ uint8_t byte2;
+};
+
struct dpcd_source_backlight_set {
struct {
uint8_t byte0;
@@ -1225,6 +1231,7 @@ struct dpcd_caps {
union dp_main_line_channel_coding_cap channel_coding_cap;
union dp_sink_video_fallback_formats fallback_formats;
union dp_fec_capability1 fec_cap1;
+ bool panel_luminance_control;
union dp_cable_id cable_id;
uint8_t edp_rev;
union edp_alpm_caps alpm_caps;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dsc.h b/drivers/gpu/drm/amd/display/dc/dc_dsc.h
index 0e92a322c2ed..9491b76d61f5 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dsc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dsc.h
@@ -58,6 +58,7 @@ struct dc_dsc_config_options {
uint32_t dsc_min_slice_height_override;
uint32_t max_target_bpp_limit_override_x16;
uint32_t slice_height_granularity;
+ uint32_t dsc_force_odm_hslice_override;
};
bool dc_dsc_parse_dsc_dpcd(const struct dc *dc,
diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c
index f43cce16bb6c..3907eeff560c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c
@@ -41,19 +41,13 @@ static inline void submit_dmub_read_modify_write(
const struct dc_context *ctx)
{
struct dmub_rb_cmd_read_modify_write *cmd_buf = &offload->cmd_data.read_modify_write;
- bool gather = false;
offload->should_burst_write =
(offload->same_addr_count == (DMUB_READ_MODIFY_WRITE_SEQ__MAX - 1));
cmd_buf->header.payload_bytes =
sizeof(struct dmub_cmd_read_modify_write_sequence) * offload->reg_seq_count;
- gather = ctx->dmub_srv->reg_helper_offload.gather_in_progress;
- ctx->dmub_srv->reg_helper_offload.gather_in_progress = false;
-
- dc_dmub_srv_cmd_queue(ctx->dmub_srv, &offload->cmd_data);
-
- ctx->dmub_srv->reg_helper_offload.gather_in_progress = gather;
+ dm_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT);
memset(cmd_buf, 0, sizeof(*cmd_buf));
@@ -66,17 +60,11 @@ static inline void submit_dmub_burst_write(
const struct dc_context *ctx)
{
struct dmub_rb_cmd_burst_write *cmd_buf = &offload->cmd_data.burst_write;
- bool gather = false;
cmd_buf->header.payload_bytes =
sizeof(uint32_t) * offload->reg_seq_count;
- gather = ctx->dmub_srv->reg_helper_offload.gather_in_progress;
- ctx->dmub_srv->reg_helper_offload.gather_in_progress = false;
-
- dc_dmub_srv_cmd_queue(ctx->dmub_srv, &offload->cmd_data);
-
- ctx->dmub_srv->reg_helper_offload.gather_in_progress = gather;
+ dm_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT);
memset(cmd_buf, 0, sizeof(*cmd_buf));
@@ -88,17 +76,11 @@ static inline void submit_dmub_reg_wait(
const struct dc_context *ctx)
{
struct dmub_rb_cmd_reg_wait *cmd_buf = &offload->cmd_data.reg_wait;
- bool gather = false;
-
- gather = ctx->dmub_srv->reg_helper_offload.gather_in_progress;
- ctx->dmub_srv->reg_helper_offload.gather_in_progress = false;
- dc_dmub_srv_cmd_queue(ctx->dmub_srv, &offload->cmd_data);
+ dm_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT);
memset(cmd_buf, 0, sizeof(*cmd_buf));
offload->reg_seq_count = 0;
-
- ctx->dmub_srv->reg_helper_offload.gather_in_progress = gather;
}
struct dc_reg_value_masks {
@@ -151,7 +133,6 @@ static void dmub_flush_buffer_execute(
const struct dc_context *ctx)
{
submit_dmub_read_modify_write(offload, ctx);
- dc_dmub_srv_cmd_execute(ctx->dmub_srv);
}
static void dmub_flush_burst_write_buffer_execute(
@@ -159,7 +140,6 @@ static void dmub_flush_burst_write_buffer_execute(
const struct dc_context *ctx)
{
submit_dmub_burst_write(offload, ctx);
- dc_dmub_srv_cmd_execute(ctx->dmub_srv);
}
static bool dmub_reg_value_burst_set_pack(const struct dc_context *ctx, uint32_t addr,
@@ -484,8 +464,7 @@ void generic_reg_wait(const struct dc_context *ctx,
field_value = get_reg_field_value_ex(reg_val, mask, shift);
if (field_value == condition_value) {
- if (i * delay_between_poll_us > 1000 &&
- !IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
+ if (i * delay_between_poll_us > 1000)
DC_LOG_DC("REG_WAIT taking a while: %dms in %s line:%d\n",
delay_between_poll_us * i / 1000,
func_name, line);
@@ -497,8 +476,7 @@ void generic_reg_wait(const struct dc_context *ctx,
delay_between_poll_us, time_out_num_tries,
func_name, line);
- if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
- BREAK_TO_DEBUGGER();
+ BREAK_TO_DEBUGGER();
}
void generic_write_indirect_reg(const struct dc_context *ctx,
@@ -691,8 +669,6 @@ void reg_sequence_start_execute(const struct dc_context *ctx)
default:
return;
}
-
- dc_dmub_srv_cmd_execute(ctx->dmub_srv);
}
}
@@ -712,3 +688,59 @@ void reg_sequence_wait_done(const struct dc_context *ctx)
dc_dmub_srv_wait_idle(ctx->dmub_srv);
}
}
+
+char *dce_version_to_string(const int version)
+{
+ switch (version) {
+ case DCE_VERSION_8_0:
+ return "DCE 8.0";
+ case DCE_VERSION_8_1:
+ return "DCE 8.1";
+ case DCE_VERSION_8_3:
+ return "DCE 8.3";
+ case DCE_VERSION_10_0:
+ return "DCE 10.0";
+ case DCE_VERSION_11_0:
+ return "DCE 11.0";
+ case DCE_VERSION_11_2:
+ return "DCE 11.2";
+ case DCE_VERSION_11_22:
+ return "DCE 11.22";
+ case DCE_VERSION_12_0:
+ return "DCE 12.0";
+ case DCE_VERSION_12_1:
+ return "DCE 12.1";
+ case DCN_VERSION_1_0:
+ return "DCN 1.0";
+ case DCN_VERSION_1_01:
+ return "DCN 1.0.1";
+ case DCN_VERSION_2_0:
+ return "DCN 2.0";
+ case DCN_VERSION_2_1:
+ return "DCN 2.1";
+ case DCN_VERSION_2_01:
+ return "DCN 2.0.1";
+ case DCN_VERSION_3_0:
+ return "DCN 3.0";
+ case DCN_VERSION_3_01:
+ return "DCN 3.0.1";
+ case DCN_VERSION_3_02:
+ return "DCN 3.0.2";
+ case DCN_VERSION_3_03:
+ return "DCN 3.0.3";
+ case DCN_VERSION_3_1:
+ return "DCN 3.1";
+ case DCN_VERSION_3_14:
+ return "DCN 3.1.4";
+ case DCN_VERSION_3_15:
+ return "DCN 3.1.5";
+ case DCN_VERSION_3_16:
+ return "DCN 3.1.6";
+ case DCN_VERSION_3_2:
+ return "DCN 3.2";
+ case DCN_VERSION_3_21:
+ return "DCN 3.2.1";
+ default:
+ return "Unknown";
+ }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 25284006019c..3697ea1d14c1 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -131,6 +131,7 @@ union stream_update_flags {
uint32_t dsc_changed : 1;
uint32_t mst_bw : 1;
uint32_t crtc_timing_adjust : 1;
+ uint32_t fams_changed : 1;
} bits;
uint32_t raw;
@@ -171,6 +172,10 @@ struct mall_temp_config {
bool is_phantom_plane[MAX_PIPES];
};
+struct dc_stream_debug_options {
+ char force_odm_combine_segments;
+};
+
struct dc_stream_state {
// sink is deprecated, new code should not reference
// this pointer
@@ -181,6 +186,7 @@ struct dc_stream_state {
* a stream via the volatile dc_state rather than the static dc_link.
*/
struct link_encoder *link_enc;
+ struct dc_stream_debug_options debug;
struct dc_panel_patch sink_patches;
union display_content_support content_support;
struct dc_crtc_timing timing;
@@ -227,6 +233,7 @@ struct dc_stream_state {
*/
bool vrr_active_variable;
bool freesync_on_desktop;
+ bool vrr_active_fixed;
bool converter_disable_audio;
uint8_t qs_bit;
@@ -295,6 +302,7 @@ struct dc_stream_state {
bool vblank_synchronized;
bool fpo_in_use;
struct mall_stream_config mall_stream_config;
+ bool skip_edp_power_down;
};
#define ABM_LEVEL_IMMEDIATE_DISABLE 255
@@ -320,6 +328,7 @@ struct dc_stream_update {
bool integer_scaling_update;
bool *allow_freesync;
bool *vrr_active_variable;
+ bool *vrr_active_fixed;
struct colorspace_transform *gamut_remap;
enum dc_color_space *output_color_space;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 45ab48fe5d00..0ce7728a5a4b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -69,13 +69,6 @@ enum dce_environment {
DCE_ENV_VIRTUAL_HW
};
-/* Note: use these macro definitions instead of direct comparison! */
-#define IS_FPGA_MAXIMUS_DC(dce_environment) \
- (dce_environment == DCE_ENV_FPGA_MAXIMUS)
-
-#define IS_DIAG_DC(dce_environment) \
- (IS_FPGA_MAXIMUS_DC(dce_environment) || (dce_environment == DCE_ENV_DIAG))
-
struct dc_perf_trace {
unsigned long read_count;
unsigned long write_count;
@@ -83,7 +76,7 @@ struct dc_perf_trace {
unsigned long last_entry_write;
};
-#define MAX_SURFACE_NUM 4
+#define MAX_SURFACE_NUM 6
#define NUM_PIXEL_FORMATS 10
enum tiling_mode {
@@ -196,6 +189,7 @@ struct dc_panel_patch {
unsigned int disable_fams;
unsigned int skip_avmute;
unsigned int mst_start_top_delay;
+ unsigned int delay_disable_aux_intercept_ms;
};
struct dc_edid_caps {
@@ -603,6 +597,7 @@ enum dc_psr_state {
PSR_STATE4b_FULL_FRAME,
PSR_STATE4c_FULL_FRAME,
PSR_STATE4_FULL_FRAME_POWERUP,
+ PSR_STATE4_FULL_FRAME_HW_LOCK,
PSR_STATE5,
PSR_STATE5a,
PSR_STATE5b,
diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile
index 0d7db132a20f..01490c9ba958 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile
@@ -29,7 +29,7 @@
DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \
dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \
dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o dce_aux.o \
-dce_i2c.o dce_i2c_hw.o dce_i2c_sw.o dmub_psr.o dmub_abm.o dce_panel_cntl.o \
+dce_i2c.o dce_i2c_hw.o dce_i2c_sw.o dmub_psr.o dmub_abm.o dmub_abm_lcd.o dce_panel_cntl.o \
dmub_hw_lock_mgr.o dmub_outbox.o
AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE))
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index 462c7a3ec3cc..ed8936405dfa 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -920,25 +920,6 @@ static bool dce112_program_pix_clk(
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
struct bp_pixel_clock_parameters bp_pc_params = {0};
- if (IS_FPGA_MAXIMUS_DC(clock_source->ctx->dce_environment)) {
- unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
- unsigned dp_dto_ref_100hz = 7000000;
- unsigned clock_100hz = pll_settings->actual_pix_clk_100hz;
-
- /* Set DTO values: phase = target clock, modulo = reference clock */
- REG_WRITE(PHASE[inst], clock_100hz);
- REG_WRITE(MODULO[inst], dp_dto_ref_100hz);
-
- /* Enable DTO */
- if (clk_src->cs_mask->PIPE0_DTO_SRC_SEL)
- REG_UPDATE_2(PIXEL_RATE_CNTL[inst],
- DP_DTO0_ENABLE, 1,
- PIPE0_DTO_SRC_SEL, 1);
- else
- REG_UPDATE(PIXEL_RATE_CNTL[inst],
- DP_DTO0_ENABLE, 1);
- return true;
- }
/* First disable SS
* ATOMBIOS will enable by default SS on PLL for DP,
* do not disable it here
@@ -1015,25 +996,6 @@ static bool dcn31_program_pix_clk(
REG_UPDATE(PIXEL_RATE_CNTL[inst],
DP_DTO0_ENABLE, 1);
} else {
- if (IS_FPGA_MAXIMUS_DC(clock_source->ctx->dce_environment)) {
- unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
- unsigned dp_dto_ref_100hz = 7000000;
- unsigned clock_100hz = pll_settings->actual_pix_clk_100hz;
-
- /* Set DTO values: phase = target clock, modulo = reference clock */
- REG_WRITE(PHASE[inst], clock_100hz);
- REG_WRITE(MODULO[inst], dp_dto_ref_100hz);
-
- /* Enable DTO */
- if (clk_src->cs_mask->PIPE0_DTO_SRC_SEL)
- REG_UPDATE_2(PIXEL_RATE_CNTL[inst],
- DP_DTO0_ENABLE, 1,
- PIPE0_DTO_SRC_SEL, 1);
- else
- REG_UPDATE(PIXEL_RATE_CNTL[inst],
- DP_DTO0_ENABLE, 1);
- return true;
- }
if (clk_src->cs_mask->PIPE0_DTO_SRC_SEL)
REG_UPDATE(PIXEL_RATE_CNTL[inst],
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
index e74266cc0098..63009db8b5a7 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
@@ -1093,11 +1093,9 @@ static void dcn21_dmcu_construct(
dce_dmcu_construct(dmcu_dce, ctx, regs, dmcu_shift, dmcu_mask);
- if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
- psp_version = dm_read_reg(ctx, mmMP0_SMN_C2PMSG_58);
- dmcu_dce->base.auto_load_dmcu = ((psp_version & 0x00FF00FF) > 0x00110029);
- dmcu_dce->base.psp_version = psp_version;
- }
+ psp_version = dm_read_reg(ctx, mmMP0_SMN_C2PMSG_58);
+ dmcu_dce->base.auto_load_dmcu = ((psp_version & 0x00FF00FF) > 0x00110029);
+ dmcu_dce->base.psp_version = psp_version;
}
struct dmcu *dce_dmcu_create(
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
index 9fc48208c2e4..2fb9572ce25d 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
@@ -24,212 +24,139 @@
*/
#include "dmub_abm.h"
-#include "dce_abm.h"
+#include "dmub_abm_lcd.h"
#include "dc.h"
-#include "dc_dmub_srv.h"
-#include "dmub/dmub_srv.h"
#include "core_types.h"
-#include "dm_services.h"
-#include "reg_helper.h"
-#include "fixed31_32.h"
-
-#include "atom.h"
#define TO_DMUB_ABM(abm)\
container_of(abm, struct dce_abm, base)
-#define REG(reg) \
- (dce_abm->regs->reg)
-
-#undef FN
-#define FN(reg_name, field_name) \
- dce_abm->abm_shift->field_name, dce_abm->abm_mask->field_name
-
-#define CTX \
- dce_abm->base.ctx
-
-#define DISABLE_ABM_IMMEDIATELY 255
-
-
+#define ABM_FEATURE_NO_SUPPORT 0
+#define ABM_LCD_SUPPORT 1
-static void dmub_abm_enable_fractional_pwm(struct dc_context *dc)
+static unsigned int abm_feature_support(struct abm *abm, unsigned int panel_inst)
{
- union dmub_rb_cmd cmd;
- uint32_t fractional_pwm = (dc->dc->config.disable_fractional_pwm == false) ? 1 : 0;
- uint32_t edp_id_count = dc->dc_edp_id_count;
+ struct dc_context *dc = abm->ctx;
+ struct dc_link *edp_links[MAX_NUM_EDP];
int i;
- uint8_t panel_mask = 0;
-
- for (i = 0; i < edp_id_count; i++)
- panel_mask |= 0x01 << i;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.abm_set_pwm_frac.header.type = DMUB_CMD__ABM;
- cmd.abm_set_pwm_frac.header.sub_type = DMUB_CMD__ABM_SET_PWM_FRAC;
- cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.fractional_pwm = fractional_pwm;
- cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
- cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.panel_mask = panel_mask;
- cmd.abm_set_pwm_frac.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pwm_frac_data);
-
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
-}
-
-static void dmub_abm_init(struct abm *abm, uint32_t backlight)
-{
- struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
-
- REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x3);
- REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x1);
- REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x3);
- REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x1);
- REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x1);
-
- REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0,
- ABM1_HG_NUM_OF_BINS_SEL, 0,
- ABM1_HG_VMAX_SEL, 1,
- ABM1_HG_BIN_BITWIDTH_SIZE_SEL, 0);
-
- REG_SET_3(DC_ABM1_IPCSC_COEFF_SEL, 0,
- ABM1_IPCSC_COEFF_SEL_R, 2,
- ABM1_IPCSC_COEFF_SEL_G, 4,
- ABM1_IPCSC_COEFF_SEL_B, 2);
-
- REG_UPDATE(BL1_PWM_CURRENT_ABM_LEVEL,
- BL1_PWM_CURRENT_ABM_LEVEL, backlight);
-
- REG_UPDATE(BL1_PWM_TARGET_ABM_LEVEL,
- BL1_PWM_TARGET_ABM_LEVEL, backlight);
+ int edp_num;
+ unsigned int ret = ABM_FEATURE_NO_SUPPORT;
- REG_UPDATE(BL1_PWM_USER_LEVEL,
- BL1_PWM_USER_LEVEL, backlight);
+ dc_get_edp_links(dc->dc, edp_links, &edp_num);
- REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES,
- ABM1_LS_MIN_PIXEL_VALUE_THRES, 0,
- ABM1_LS_MAX_PIXEL_VALUE_THRES, 1000);
+ for (i = 0; i < edp_num; i++) {
+ if (panel_inst == i)
+ break;
+ }
- REG_SET_3(DC_ABM1_HGLS_REG_READ_PROGRESS, 0,
- ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, 1,
- ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, 1,
- ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1);
+ if (i < edp_num) {
+ ret = ABM_LCD_SUPPORT;
+ }
- dmub_abm_enable_fractional_pwm(abm->ctx);
+ return ret;
}
-static unsigned int dmub_abm_get_current_backlight(struct abm *abm)
+static void dmub_abm_init_ex(struct abm *abm, uint32_t backlight)
{
- struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
- unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL);
-
- /* return backlight in hardware format which is unsigned 17 bits, with
- * 1 bit integer and 16 bit fractional
- */
- return backlight;
+ dmub_abm_init(abm, backlight);
}
-static unsigned int dmub_abm_get_target_backlight(struct abm *abm)
+static unsigned int dmub_abm_get_current_backlight_ex(struct abm *abm)
{
- struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
- unsigned int backlight = REG_READ(BL1_PWM_TARGET_ABM_LEVEL);
+ return dmub_abm_get_current_backlight(abm);
+}
- /* return backlight in hardware format which is unsigned 17 bits, with
- * 1 bit integer and 16 bit fractional
- */
- return backlight;
+static unsigned int dmub_abm_get_target_backlight_ex(struct abm *abm)
+{
+ return dmub_abm_get_target_backlight(abm);
}
-static bool dmub_abm_set_level(struct abm *abm, uint32_t level)
+static bool dmub_abm_set_level_ex(struct abm *abm, uint32_t level)
{
- union dmub_rb_cmd cmd;
- struct dc_context *dc = abm->ctx;
- struct dc_link *edp_links[MAX_NUM_EDP];
- int i;
- int edp_num;
- uint8_t panel_mask = 0;
+ bool ret = false;
+ unsigned int feature_support, i;
+ uint8_t panel_mask0 = 0;
- dc_get_edp_links(dc->dc, edp_links, &edp_num);
+ for (i = 0; i < MAX_NUM_EDP; i++) {
+ feature_support = abm_feature_support(abm, i);
- for (i = 0; i < edp_num; i++) {
- if (edp_links[i]->link_status.link_active)
- panel_mask |= (0x01 << i);
+ if (feature_support == ABM_LCD_SUPPORT)
+ panel_mask0 |= (0x01 << i);
}
- memset(&cmd, 0, sizeof(cmd));
- cmd.abm_set_level.header.type = DMUB_CMD__ABM;
- cmd.abm_set_level.header.sub_type = DMUB_CMD__ABM_SET_LEVEL;
- cmd.abm_set_level.abm_set_level_data.level = level;
- cmd.abm_set_level.abm_set_level_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
- cmd.abm_set_level.abm_set_level_data.panel_mask = panel_mask;
- cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_level_data);
+ if (panel_mask0)
+ ret = dmub_abm_set_level(abm, level, panel_mask0);
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
-
- return true;
+ return ret;
}
-static bool dmub_abm_init_config(struct abm *abm,
+static bool dmub_abm_init_config_ex(struct abm *abm,
const char *src,
unsigned int bytes,
unsigned int inst)
{
- union dmub_rb_cmd cmd;
- struct dc_context *dc = abm->ctx;
- uint8_t panel_mask = 0x01 << inst;
+ unsigned int feature_support;
+
+ feature_support = abm_feature_support(abm, inst);
+
+ if (feature_support == ABM_LCD_SUPPORT)
+ dmub_abm_init_config(abm, src, bytes, inst);
+
+ return true;
+}
- // TODO: Optimize by only reading back final 4 bytes
- dmub_flush_buffer_mem(&dc->dmub_srv->dmub->scratch_mem_fb);
+static bool dmub_abm_set_pause_ex(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst)
+{
+ bool ret = false;
+ unsigned int feature_support;
- // Copy iramtable into cw7
- memcpy(dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, (void *)src, bytes);
+ feature_support = abm_feature_support(abm, panel_inst);
- memset(&cmd, 0, sizeof(cmd));
- // Fw will copy from cw7 to fw_state
- cmd.abm_init_config.header.type = DMUB_CMD__ABM;
- cmd.abm_init_config.header.sub_type = DMUB_CMD__ABM_INIT_CONFIG;
- cmd.abm_init_config.abm_init_config_data.src.quad_part = dc->dmub_srv->dmub->scratch_mem_fb.gpu_addr;
- cmd.abm_init_config.abm_init_config_data.bytes = bytes;
- cmd.abm_init_config.abm_init_config_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
- cmd.abm_init_config.abm_init_config_data.panel_mask = panel_mask;
+ if (feature_support == ABM_LCD_SUPPORT)
+ ret = dmub_abm_set_pause(abm, pause, panel_inst, stream_inst);
- cmd.abm_init_config.header.payload_bytes = sizeof(struct dmub_cmd_abm_init_config_data);
+ return ret;
+}
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
+static bool dmub_abm_set_pipe_ex(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst)
+{
+ bool ret = false;
+ unsigned int feature_support;
- return true;
+ feature_support = abm_feature_support(abm, panel_inst);
+
+ if (feature_support == ABM_LCD_SUPPORT)
+ ret = dmub_abm_set_pipe(abm, otg_inst, option, panel_inst);
+
+ return ret;
}
-static bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst)
+static bool dmub_abm_set_backlight_level_pwm_ex(struct abm *abm,
+ unsigned int backlight_pwm_u16_16,
+ unsigned int frame_ramp,
+ unsigned int controller_id,
+ unsigned int panel_inst)
{
- union dmub_rb_cmd cmd;
- struct dc_context *dc = abm->ctx;
- uint8_t panel_mask = 0x01 << panel_inst;
+ bool ret = false;
+ unsigned int feature_support;
- memset(&cmd, 0, sizeof(cmd));
- cmd.abm_pause.header.type = DMUB_CMD__ABM;
- cmd.abm_pause.header.sub_type = DMUB_CMD__ABM_PAUSE;
- cmd.abm_pause.abm_pause_data.enable = pause;
- cmd.abm_pause.abm_pause_data.panel_mask = panel_mask;
- cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_pause_data);
+ feature_support = abm_feature_support(abm, panel_inst);
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
+ if (feature_support == ABM_LCD_SUPPORT)
+ ret = dmub_abm_set_backlight_level(abm, backlight_pwm_u16_16, frame_ramp, panel_inst);
- return true;
+ return ret;
}
static const struct abm_funcs abm_funcs = {
- .abm_init = dmub_abm_init,
- .set_abm_level = dmub_abm_set_level,
- .get_current_backlight = dmub_abm_get_current_backlight,
- .get_target_backlight = dmub_abm_get_target_backlight,
- .init_abm_config = dmub_abm_init_config,
- .set_abm_pause = dmub_abm_set_pause,
+ .abm_init = dmub_abm_init_ex,
+ .set_abm_level = dmub_abm_set_level_ex,
+ .get_current_backlight = dmub_abm_get_current_backlight_ex,
+ .get_target_backlight = dmub_abm_get_target_backlight_ex,
+ .init_abm_config = dmub_abm_init_config_ex,
+ .set_abm_pause = dmub_abm_set_pause_ex,
+ .set_pipe_ex = dmub_abm_set_pipe_ex,
+ .set_backlight_level_pwm = dmub_abm_set_backlight_level_pwm_ex,
};
static void dmub_abm_construct(
@@ -256,16 +183,19 @@ struct abm *dmub_abm_create(
const struct dce_abm_shift *abm_shift,
const struct dce_abm_mask *abm_mask)
{
- struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL);
+ if (ctx->dc->caps.dmcub_support) {
+ struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL);
- if (abm_dce == NULL) {
- BREAK_TO_DEBUGGER();
- return NULL;
- }
+ if (abm_dce == NULL) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
- dmub_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask);
+ dmub_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask);
- return &abm_dce->base;
+ return &abm_dce->base;
+ }
+ return NULL;
}
void dmub_abm_destroy(struct abm **abm)
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c
new file mode 100644
index 000000000000..39da73eba86e
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2019 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dmub_abm.h"
+#include "dmub_abm_lcd.h"
+#include "dce_abm.h"
+#include "dc.h"
+#include "dc_dmub_srv.h"
+#include "dmub/dmub_srv.h"
+#include "core_types.h"
+#include "dm_services.h"
+#include "reg_helper.h"
+#include "fixed31_32.h"
+
+#ifdef _WIN32
+#include "atombios.h"
+#else
+#include "atom.h"
+#endif
+
+#define TO_DMUB_ABM(abm)\
+ container_of(abm, struct dce_abm, base)
+
+#define REG(reg) \
+ (dce_abm->regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+ dce_abm->abm_shift->field_name, dce_abm->abm_mask->field_name
+
+#define CTX \
+ dce_abm->base.ctx
+
+#define DISABLE_ABM_IMMEDIATELY 255
+
+
+
+static void dmub_abm_enable_fractional_pwm(struct dc_context *dc)
+{
+ union dmub_rb_cmd cmd;
+ uint32_t fractional_pwm = (dc->dc->config.disable_fractional_pwm == false) ? 1 : 0;
+ uint32_t edp_id_count = dc->dc_edp_id_count;
+ int i;
+ uint8_t panel_mask = 0;
+
+ for (i = 0; i < edp_id_count; i++)
+ panel_mask |= 0x01 << i;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.abm_set_pwm_frac.header.type = DMUB_CMD__ABM;
+ cmd.abm_set_pwm_frac.header.sub_type = DMUB_CMD__ABM_SET_PWM_FRAC;
+ cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.fractional_pwm = fractional_pwm;
+ cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
+ cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.panel_mask = panel_mask;
+ cmd.abm_set_pwm_frac.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pwm_frac_data);
+
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+}
+
+void dmub_abm_init(struct abm *abm, uint32_t backlight)
+{
+ struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
+
+ REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x3);
+ REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x1);
+ REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x3);
+ REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x1);
+ REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x1);
+
+ REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0,
+ ABM1_HG_NUM_OF_BINS_SEL, 0,
+ ABM1_HG_VMAX_SEL, 1,
+ ABM1_HG_BIN_BITWIDTH_SIZE_SEL, 0);
+
+ REG_SET_3(DC_ABM1_IPCSC_COEFF_SEL, 0,
+ ABM1_IPCSC_COEFF_SEL_R, 2,
+ ABM1_IPCSC_COEFF_SEL_G, 4,
+ ABM1_IPCSC_COEFF_SEL_B, 2);
+
+ REG_UPDATE(BL1_PWM_CURRENT_ABM_LEVEL,
+ BL1_PWM_CURRENT_ABM_LEVEL, backlight);
+
+ REG_UPDATE(BL1_PWM_TARGET_ABM_LEVEL,
+ BL1_PWM_TARGET_ABM_LEVEL, backlight);
+
+ REG_UPDATE(BL1_PWM_USER_LEVEL,
+ BL1_PWM_USER_LEVEL, backlight);
+
+ REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES,
+ ABM1_LS_MIN_PIXEL_VALUE_THRES, 0,
+ ABM1_LS_MAX_PIXEL_VALUE_THRES, 1000);
+
+ REG_SET_3(DC_ABM1_HGLS_REG_READ_PROGRESS, 0,
+ ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, 1,
+ ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, 1,
+ ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1);
+
+ dmub_abm_enable_fractional_pwm(abm->ctx);
+}
+
+unsigned int dmub_abm_get_current_backlight(struct abm *abm)
+{
+ struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
+ unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL);
+
+ /* return backlight in hardware format which is unsigned 17 bits, with
+ * 1 bit integer and 16 bit fractional
+ */
+ return backlight;
+}
+
+unsigned int dmub_abm_get_target_backlight(struct abm *abm)
+{
+ struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
+ unsigned int backlight = REG_READ(BL1_PWM_TARGET_ABM_LEVEL);
+
+ /* return backlight in hardware format which is unsigned 17 bits, with
+ * 1 bit integer and 16 bit fractional
+ */
+ return backlight;
+}
+
+bool dmub_abm_set_level(struct abm *abm, uint32_t level, uint8_t panel_mask)
+{
+ union dmub_rb_cmd cmd;
+ struct dc_context *dc = abm->ctx;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.abm_set_level.header.type = DMUB_CMD__ABM;
+ cmd.abm_set_level.header.sub_type = DMUB_CMD__ABM_SET_LEVEL;
+ cmd.abm_set_level.abm_set_level_data.level = level;
+ cmd.abm_set_level.abm_set_level_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
+ cmd.abm_set_level.abm_set_level_data.panel_mask = panel_mask;
+ cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_level_data);
+
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+
+ return true;
+}
+
+void dmub_abm_init_config(struct abm *abm,
+ const char *src,
+ unsigned int bytes,
+ unsigned int inst)
+{
+ union dmub_rb_cmd cmd;
+ struct dc_context *dc = abm->ctx;
+ uint8_t panel_mask = 0x01 << inst;
+
+ // TODO: Optimize by only reading back final 4 bytes
+ dmub_flush_buffer_mem(&dc->dmub_srv->dmub->scratch_mem_fb);
+
+ // Copy iramtable into cw7
+ memcpy(dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, (void *)src, bytes);
+
+ memset(&cmd, 0, sizeof(cmd));
+ // Fw will copy from cw7 to fw_state
+ cmd.abm_init_config.header.type = DMUB_CMD__ABM;
+ cmd.abm_init_config.header.sub_type = DMUB_CMD__ABM_INIT_CONFIG;
+ cmd.abm_init_config.abm_init_config_data.src.quad_part = dc->dmub_srv->dmub->scratch_mem_fb.gpu_addr;
+ cmd.abm_init_config.abm_init_config_data.bytes = bytes;
+ cmd.abm_init_config.abm_init_config_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
+ cmd.abm_init_config.abm_init_config_data.panel_mask = panel_mask;
+
+ cmd.abm_init_config.header.payload_bytes = sizeof(struct dmub_cmd_abm_init_config_data);
+
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+
+}
+
+bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst)
+{
+ union dmub_rb_cmd cmd;
+ struct dc_context *dc = abm->ctx;
+ uint8_t panel_mask = 0x01 << panel_inst;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.abm_pause.header.type = DMUB_CMD__ABM;
+ cmd.abm_pause.header.sub_type = DMUB_CMD__ABM_PAUSE;
+ cmd.abm_pause.abm_pause_data.enable = pause;
+ cmd.abm_pause.abm_pause_data.panel_mask = panel_mask;
+ cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_pause_data);
+
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+
+ return true;
+}
+
+bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst)
+{
+ union dmub_rb_cmd cmd;
+ struct dc_context *dc = abm->ctx;
+ uint32_t ramping_boundary = 0xFFFF;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.abm_set_pipe.header.type = DMUB_CMD__ABM;
+ cmd.abm_set_pipe.header.sub_type = DMUB_CMD__ABM_SET_PIPE;
+ cmd.abm_set_pipe.abm_set_pipe_data.otg_inst = otg_inst;
+ cmd.abm_set_pipe.abm_set_pipe_data.set_pipe_option = option;
+ cmd.abm_set_pipe.abm_set_pipe_data.panel_inst = panel_inst;
+ cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary;
+ cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data);
+
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+
+ return true;
+}
+
+bool dmub_abm_set_backlight_level(struct abm *abm,
+ unsigned int backlight_pwm_u16_16,
+ unsigned int frame_ramp,
+ unsigned int panel_inst)
+{
+ union dmub_rb_cmd cmd;
+ struct dc_context *dc = abm->ctx;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.abm_set_backlight.header.type = DMUB_CMD__ABM;
+ cmd.abm_set_backlight.header.sub_type = DMUB_CMD__ABM_SET_BACKLIGHT;
+ cmd.abm_set_backlight.abm_set_backlight_data.frame_ramp = frame_ramp;
+ cmd.abm_set_backlight.abm_set_backlight_data.backlight_user_level = backlight_pwm_u16_16;
+ cmd.abm_set_backlight.abm_set_backlight_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
+ cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_inst);
+ cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data);
+
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+
+ return true;
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.h
new file mode 100644
index 000000000000..00b4e268768e
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DMUB_ABM_LCD_H__
+#define __DMUB_ABM_LCD_H__
+
+#include "abm.h"
+
+void dmub_abm_init(struct abm *abm, uint32_t backlight);
+bool dmub_abm_set_level(struct abm *abm, uint32_t level, uint8_t panel_mask);
+unsigned int dmub_abm_get_current_backlight(struct abm *abm);
+unsigned int dmub_abm_get_target_backlight(struct abm *abm);
+void dmub_abm_init_config(struct abm *abm,
+ const char *src,
+ unsigned int bytes,
+ unsigned int inst);
+
+bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst);
+bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst);
+bool dmub_abm_set_backlight_level(struct abm *abm,
+ unsigned int backlight_pwm_u16_16,
+ unsigned int frame_ramp,
+ unsigned int panel_inst);
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
index 3f32e9c3fbaf..2aa0e01a6891 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
@@ -47,9 +47,7 @@ void dmub_hw_lock_mgr_cmd(struct dc_dmub_srv *dmub_srv,
if (!lock)
cmd.lock_hw.lock_hw_data.should_release = 1;
- dc_dmub_srv_cmd_queue(dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dmub_srv);
- dc_dmub_srv_wait_idle(dmub_srv);
+ dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c
index fff1d07d865d..d8009b2dc56a 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c
@@ -48,7 +48,5 @@ void dmub_enable_outbox_notification(struct dc_dmub_srv *dmub_srv)
sizeof(cmd.outbox1_enable.header);
cmd.outbox1_enable.enable = true;
- dc_dmub_srv_cmd_queue(dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dmub_srv);
- dc_dmub_srv_wait_idle(dmub_srv);
+ dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
index 9705d8f88382..0f24b6fbd220 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
@@ -87,6 +87,8 @@ static enum dc_psr_state convert_psr_state(uint32_t raw_state)
state = PSR_STATE4c_FULL_FRAME;
else if (raw_state == 0x4E)
state = PSR_STATE4_FULL_FRAME_POWERUP;
+ else if (raw_state == 0x4F)
+ state = PSR_STATE4_FULL_FRAME_HW_LOCK;
else if (raw_state == 0x60)
state = PSR_STATE_HWLOCK_MGR;
else if (raw_state == 0x61)
@@ -168,9 +170,7 @@ static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *
cmd.psr_set_version.psr_set_version_data.panel_inst = panel_inst;
cmd.psr_set_version.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data);
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
@@ -198,9 +198,7 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait, uint8
cmd.psr_enable.header.payload_bytes = 0; // Send header only
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
+ dm_execute_dmub_cmd(dc->dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
/* Below loops 1000 x 500us = 500 ms.
* Exit PSR may need to wait 1-2 frames to power up. Timeout after at
@@ -248,9 +246,7 @@ static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_
cmd.psr_set_level.psr_set_level_data.psr_level = psr_level;
cmd.psr_set_level.psr_set_level_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
cmd.psr_set_level.psr_set_level_data.panel_inst = panel_inst;
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
@@ -269,9 +265,7 @@ static void dmub_psr_set_sink_vtotal_in_psr_active(struct dmub_psr *dmub,
cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_idle = psr_vtotal_idle;
cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_su = psr_vtotal_su;
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
@@ -290,9 +284,7 @@ static void dmub_psr_set_power_opt(struct dmub_psr *dmub, unsigned int power_opt
cmd.psr_set_power_opt.psr_set_power_opt_data.power_opt = power_opt;
cmd.psr_set_power_opt.psr_set_power_opt_data.panel_inst = panel_inst;
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
@@ -422,9 +414,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
copy_settings_data->relock_delay_frame_cnt = 2;
copy_settings_data->dsc_slice_height = psr_context->dsc_slice_height;
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
@@ -445,9 +435,7 @@ static void dmub_psr_force_static(struct dmub_psr *dmub, uint8_t panel_inst)
cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC;
cmd.psr_enable.header.payload_bytes = 0;
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
index 54805802cbd5..42e9b6a529f6 100644
--- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
@@ -401,6 +401,10 @@ static const struct dc_plane_cap plane_cap = {
}
};
+static const struct dc_debug_options debug_defaults = {
+ .enable_legacy_fast_update = true,
+};
+
#define CTX ctx
#define REG(reg) mm ## reg
@@ -1071,6 +1075,7 @@ static bool dce100_resource_construct(
dc->caps.dual_link_dvi = true;
dc->caps.disable_dp_clk_share = true;
dc->caps.extended_aux_timeout_support = false;
+ dc->debug = debug_defaults;
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.timing_generators[i] =
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 8d2460d06bce..6c9ca43d1040 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -209,9 +209,6 @@ static bool dce110_enable_display_power_gating(
struct dc_context *ctx = dc->ctx;
unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
- return true;
-
if (power_gating == PIPE_GATING_CONTROL_INIT)
cntl = ASIC_PIPE_INIT;
else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
@@ -1219,7 +1216,8 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
struct dce_hwseq *hws = link->dc->hwseq;
if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
- hws->funcs.edp_backlight_control(link, false);
+ if (!stream->skip_edp_power_down)
+ hws->funcs.edp_backlight_control(link, false);
link->dc->hwss.set_abm_immediate_disable(pipe_ctx);
}
@@ -2291,6 +2289,11 @@ enum dc_status dce110_apply_ctx_to_hw(
if (DC_OK != status)
return status;
+
+#ifdef CONFIG_DRM_AMD_DC_FP
+ if (hws->funcs.resync_fifo_dccg_dio)
+ hws->funcs.resync_fifo_dccg_dio(hws, dc, context);
+#endif
}
if (dc->fbc_compressor)
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
index a4a45a6ce61e..46eca5a21e1c 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
@@ -424,6 +424,10 @@ static const struct dc_plane_cap plane_cap = {
64
};
+static const struct dc_debug_options debug_defaults = {
+ .enable_legacy_fast_update = true,
+};
+
static const struct dc_plane_cap underlay_plane_cap = {
.type = DC_PLANE_TYPE_DCE_UNDERLAY,
.per_pixel_alpha = 1,
@@ -1368,6 +1372,7 @@ static bool dce110_resource_construct(
dc->caps.min_horizontal_blanking_period = 80;
dc->caps.is_apu = true;
dc->caps.extended_aux_timeout_support = false;
+ dc->debug = debug_defaults;
/*************************************************
* Create resources *
diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c
index 19873ee1f78d..690caaaff019 100644
--- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c
@@ -120,9 +120,6 @@ static bool dce112_enable_display_power_gating(
enum bp_pipe_control_action cntl;
struct dc_context *ctx = dc->ctx;
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
- return true;
-
if (power_gating == PIPE_GATING_CONTROL_INIT)
cntl = ASIC_PIPE_INIT;
else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
index e179e80667d1..808855886183 100644
--- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
@@ -429,6 +429,10 @@ static const struct dc_plane_cap plane_cap = {
64
};
+static const struct dc_debug_options debug_defaults = {
+ .enable_legacy_fast_update = true,
+};
+
#define CTX ctx
#define REG(reg) mm ## reg
@@ -1239,6 +1243,7 @@ static bool dce112_resource_construct(
dc->caps.min_horizontal_blanking_period = 80;
dc->caps.dual_link_dvi = true;
dc->caps.extended_aux_timeout_support = false;
+ dc->debug = debug_defaults;
/*************************************************
* Create resources *
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c
index d4afe6c824d2..45e08c4d5861 100644
--- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c
@@ -159,9 +159,6 @@ static bool dce120_enable_display_power_gating(
enum bp_pipe_control_action cntl;
struct dc_context *ctx = dc->ctx;
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
- return true;
-
if (power_gating == PIPE_GATING_CONTROL_INIT)
cntl = ASIC_PIPE_INIT;
else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c
index af631085e88c..18c5a86d2d61 100644
--- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c
@@ -526,6 +526,7 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults = {
.disable_clock_gate = true,
+ .enable_legacy_fast_update = true,
};
static struct clock_source *dce120_clock_source_create(
diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
index 5825e6f412bd..3935fd455f0f 100644
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
@@ -418,6 +418,10 @@ static const struct dc_plane_cap plane_cap = {
}
};
+static const struct dc_debug_options debug_defaults = {
+ .enable_legacy_fast_update = true,
+};
+
static const struct dce_dmcu_registers dmcu_regs = {
DMCU_DCE80_REG_LIST()
};
@@ -969,6 +973,7 @@ static bool dce80_construct(
dc->caps.min_horizontal_blanking_period = 80;
dc->caps.dual_link_dvi = true;
dc->caps.extended_aux_timeout_support = false;
+ dc->debug = debug_defaults;
/*************************************************
* Create resources *
@@ -1369,6 +1374,7 @@ static bool dce83_construct(
dc->caps.max_cursor_size = 128;
dc->caps.min_horizontal_blanking_period = 80;
dc->caps.is_apu = true;
+ dc->debug = debug_defaults;
/*************************************************
* Create resources *
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
index 0b17c2993ca5..09784222cc03 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
@@ -690,6 +690,8 @@ struct dcn_hubp_state {
uint32_t primary_surface_addr_hi;
uint32_t primary_meta_addr_lo;
uint32_t primary_meta_addr_hi;
+ uint32_t uclk_pstate_force;
+ uint32_t hubp_cntl;
};
struct dcn10_hubp {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index 1c3b6f25a782..20a1582be0b1 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -1012,31 +1012,29 @@ static void dcn10_reset_back_end_for_pipe(
return;
}
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- link = pipe_ctx->stream->link;
- /* DPMS may already disable or */
- /* dpms_off status is incorrect due to fastboot
- * feature. When system resume from S4 with second
- * screen only, the dpms_off would be true but
- * VBIOS lit up eDP, so check link status too.
- */
- if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
- dc->link_srv->set_dpms_off(pipe_ctx);
- else if (pipe_ctx->stream_res.audio)
- dc->hwss.disable_audio_stream(pipe_ctx);
-
- if (pipe_ctx->stream_res.audio) {
- /*disable az_endpoint*/
- pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
-
- /*free audio*/
- if (dc->caps.dynamic_audio == true) {
- /*we have to dynamic arbitrate the audio endpoints*/
- /*we free the resource, need reset is_audio_acquired*/
- update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
- pipe_ctx->stream_res.audio, false);
- pipe_ctx->stream_res.audio = NULL;
- }
+ link = pipe_ctx->stream->link;
+ /* DPMS may already disable or */
+ /* dpms_off status is incorrect due to fastboot
+ * feature. When system resume from S4 with second
+ * screen only, the dpms_off would be true but
+ * VBIOS lit up eDP, so check link status too.
+ */
+ if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
+ dc->link_srv->set_dpms_off(pipe_ctx);
+ else if (pipe_ctx->stream_res.audio)
+ dc->hwss.disable_audio_stream(pipe_ctx);
+
+ if (pipe_ctx->stream_res.audio) {
+ /*disable az_endpoint*/
+ pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
+
+ /*free audio*/
+ if (dc->caps.dynamic_audio == true) {
+ /*we have to dynamic arbitrate the audio endpoints*/
+ /*we free the resource, need reset is_audio_acquired*/
+ update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
+ pipe_ctx->stream_res.audio, false);
+ pipe_ctx->stream_res.audio = NULL;
}
}
@@ -1499,54 +1497,32 @@ void dcn10_init_hw(struct dc *dc)
if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->dccg_init)
dc->res_pool->dccg->funcs->dccg_init(res_pool->dccg);
- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
-
- REG_WRITE(REFCLK_CNTL, 0);
- REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
- REG_WRITE(DIO_MEM_PWR_CTRL, 0);
-
- if (!dc->debug.disable_clock_gate) {
- /* enable all DCN clock gating */
- REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
-
- REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
-
- REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
- }
-
- //Enable ability to power gate / don't force power on permanently
- if (hws->funcs.enable_power_gating_plane)
- hws->funcs.enable_power_gating_plane(hws, true);
-
- return;
- }
-
if (!dcb->funcs->is_accelerated_mode(dcb))
hws->funcs.disable_vga(dc->hwseq);
- hws->funcs.bios_golden_init(dc);
+ if (!dc_dmub_srv_optimized_init_done(dc->ctx->dmub_srv))
+ hws->funcs.bios_golden_init(dc);
+
if (dc->ctx->dc_bios->fw_info_valid) {
res_pool->ref_clocks.xtalin_clock_inKhz =
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- if (res_pool->dccg && res_pool->hubbub) {
+ if (res_pool->dccg && res_pool->hubbub) {
- (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
- dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
- &res_pool->ref_clocks.dccg_ref_clock_inKhz);
+ (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
+ dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
+ &res_pool->ref_clocks.dccg_ref_clock_inKhz);
- (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
- res_pool->ref_clocks.dccg_ref_clock_inKhz,
- &res_pool->ref_clocks.dchub_ref_clock_inKhz);
- } else {
- // Not all ASICs have DCCG sw component
- res_pool->ref_clocks.dccg_ref_clock_inKhz =
- res_pool->ref_clocks.xtalin_clock_inKhz;
- res_pool->ref_clocks.dchub_ref_clock_inKhz =
- res_pool->ref_clocks.xtalin_clock_inKhz;
- }
+ (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
+ res_pool->ref_clocks.dccg_ref_clock_inKhz,
+ &res_pool->ref_clocks.dchub_ref_clock_inKhz);
+ } else {
+ // Not all ASICs have DCCG sw component
+ res_pool->ref_clocks.dccg_ref_clock_inKhz =
+ res_pool->ref_clocks.xtalin_clock_inKhz;
+ res_pool->ref_clocks.dchub_ref_clock_inKhz =
+ res_pool->ref_clocks.xtalin_clock_inKhz;
}
} else
ASSERT_CRITICAL(false);
@@ -1923,6 +1899,11 @@ void dcn10_pipe_control_lock(
*
* TODO: Optimize cursor programming to be once per frame before VUPDATE
* to avoid the need for this workaround.
+ *
+ * @dc: Current DC state
+ * @pipe_ctx: Pipe_ctx pointer for delayed cursor update
+ *
+ * Return: void
*/
static void delay_cursor_until_vupdate(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
@@ -2600,23 +2581,15 @@ static void dcn10_update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state
dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
}
-void dcn10_update_visual_confirm_color(struct dc *dc, struct pipe_ctx *pipe_ctx, struct tg_color *color, int mpcc_id)
+void dcn10_update_visual_confirm_color(struct dc *dc,
+ struct pipe_ctx *pipe_ctx,
+ int mpcc_id)
{
struct mpc *mpc = dc->res_pool->mpc;
- if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR)
- get_hdr_visual_confirm_color(pipe_ctx, color);
- else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
- get_surface_visual_confirm_color(pipe_ctx, color);
- else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SWIZZLE)
- get_surface_tile_visual_confirm_color(pipe_ctx, color);
- else
- color_space_to_black_color(
- dc, pipe_ctx->stream->output_color_space, color);
-
if (mpc->funcs->set_bg_color) {
- memcpy(&pipe_ctx->plane_state->visual_confirm_color, color, sizeof(struct tg_color));
- mpc->funcs->set_bg_color(mpc, color, mpcc_id);
+ memcpy(&pipe_ctx->plane_state->visual_confirm_color, &(pipe_ctx->visual_confirm_color), sizeof(struct tg_color));
+ mpc->funcs->set_bg_color(mpc, &(pipe_ctx->visual_confirm_color), mpcc_id);
}
}
@@ -2669,7 +2642,7 @@ void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
/* If there is no full update, don't need to touch MPC tree*/
if (!pipe_ctx->plane_state->update_flags.bits.full_update) {
mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
- dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
+ dc->hwss.update_visual_confirm_color(dc, pipe_ctx, mpcc_id);
return;
}
@@ -2691,7 +2664,7 @@ void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
NULL,
hubp->inst,
mpcc_id);
- dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
+ dc->hwss.update_visual_confirm_color(dc, pipe_ctx, mpcc_id);
ASSERT(new_mpcc != NULL);
hubp->opp_id = pipe_ctx->stream_res.opp->inst;
@@ -3076,15 +3049,13 @@ void dcn10_prepare_bandwidth(
if (dc->debug.sanity_checks)
hws->funcs.verify_allow_pstate_change_high(dc);
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- if (context->stream_count == 0)
- context->bw_ctx.bw.dcn.clk.phyclk_khz = 0;
+ if (context->stream_count == 0)
+ context->bw_ctx.bw.dcn.clk.phyclk_khz = 0;
- dc->clk_mgr->funcs->update_clocks(
- dc->clk_mgr,
- context,
- false);
- }
+ dc->clk_mgr->funcs->update_clocks(
+ dc->clk_mgr,
+ context,
+ false);
dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub,
&context->bw_ctx.bw.dcn.watermarks,
@@ -3116,15 +3087,13 @@ void dcn10_optimize_bandwidth(
if (dc->debug.sanity_checks)
hws->funcs.verify_allow_pstate_change_high(dc);
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- if (context->stream_count == 0)
- context->bw_ctx.bw.dcn.clk.phyclk_khz = 0;
+ if (context->stream_count == 0)
+ context->bw_ctx.bw.dcn.clk.phyclk_khz = 0;
- dc->clk_mgr->funcs->update_clocks(
- dc->clk_mgr,
- context,
- true);
- }
+ dc->clk_mgr->funcs->update_clocks(
+ dc->clk_mgr,
+ context,
+ true);
hubbub->funcs->program_watermarks(hubbub,
&context->bw_ctx.bw.dcn.watermarks,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
index 0ef7bf7ddb75..ef6d56da417c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
@@ -202,7 +202,6 @@ void dcn10_get_dcc_en_bits(struct dc *dc, int *dcc_en_bits);
void dcn10_update_visual_confirm_color(
struct dc *dc,
struct pipe_ctx *pipe_ctx,
- struct tg_color *color,
int mpcc_id);
#endif /* __DC_HWSS_DCN10_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
index a0f8e31d2adc..46a2ebcabd1a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
@@ -45,7 +45,8 @@
#include "dcn10_cm_common.h"
#include "clk_mgr.h"
-unsigned int snprintf_count(char *pBuf, unsigned int bufSize, char *fmt, ...)
+__printf(3, 4)
+unsigned int snprintf_count(char *pbuf, unsigned int bufsize, char *fmt, ...)
{
int ret_vsnprintf;
unsigned int chars_printed;
@@ -53,15 +54,15 @@ unsigned int snprintf_count(char *pBuf, unsigned int bufSize, char *fmt, ...)
va_list args;
va_start(args, fmt);
- ret_vsnprintf = vsnprintf(pBuf, bufSize, fmt, args);
+ ret_vsnprintf = vsnprintf(pbuf, bufsize, fmt, args);
va_end(args);
if (ret_vsnprintf > 0) {
- if (ret_vsnprintf < bufSize)
+ if (ret_vsnprintf < bufsize)
chars_printed = ret_vsnprintf;
else
- chars_printed = bufSize - 1;
+ chars_printed = bufsize - 1;
} else
chars_printed = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c
index 41cec7acf51f..0dec57679269 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c
@@ -37,14 +37,14 @@
#define CTX \
oppn10->base.ctx
-
-/************* FORMATTER ************/
-
/**
- * set_truncation
+ * opp1_set_truncation():
* 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
* 2) enable truncation
* 3) HW remove 12bit FMT support for DCE11 power saving reason.
+ *
+ * @oppn10: output_pixel_processor struct instance for dcn10.
+ * @params: pointer to bit_depth_reduction_params.
*/
static void opp1_set_truncation(
struct dcn10_opp *oppn10,
@@ -149,11 +149,12 @@ void opp1_program_bit_depth_reduction(
}
/**
- * set_pixel_encoding
- *
- * Set Pixel Encoding
+ * opp1_set_pixel_encoding():
* 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
* 1: YCbCr 4:2:2
+ *
+ * @oppn10: output_pixel_processor struct instance for dcn10.
+ * @params: pointer to clamping_and_pixel_encoding_params.
*/
static void opp1_set_pixel_encoding(
struct dcn10_opp *oppn10,
@@ -180,13 +181,16 @@ static void opp1_set_pixel_encoding(
}
/**
- * Set Clamping
+ * opp1_set_clamping():
* 1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
* 1 for 8 bpc
* 2 for 10 bpc
* 3 for 12 bpc
* 7 for programable
* 2) Enable clamp if Limited range requested
+ *
+ * @oppn10: output_pixel_processor struct instance for dcn10.
+ * @params: pointer to clamping_and_pixel_encoding_params.
*/
static void opp1_set_clamping(
struct dcn10_opp *oppn10,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
index c9e53dc49c92..0e8f4f36c87c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
@@ -42,11 +42,13 @@
#define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100
/**
-* apply_front_porch_workaround TODO FPGA still need?
-*
-* This is a workaround for a bug that has existed since R5xx and has not been
-* fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive.
-*/
+ * apply_front_porch_workaround() - This is a workaround for a bug that has
+ * existed since R5xx and has not been fixed
+ * keep Front porch at minimum 2 for Interlaced
+ * mode or 1 for progressive.
+ *
+ * @timing: Timing parameters used to configure DCN blocks.
+ */
static void apply_front_porch_workaround(struct dc_crtc_timing *timing)
{
if (timing->flags.INTERLACE == 1) {
@@ -133,9 +135,20 @@ void optc1_setup_vertical_interrupt2(
}
/**
- * program_timing_generator used by mode timing set
- * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition.
- * Including SYNC. Call BIOS command table to program Timings.
+ * optc1_program_timing() - used by mode timing set Program
+ * CRTC Timing Registers - OTG_H_*,
+ * OTG_V_*, Pixel repetition.
+ * Including SYNC. Call BIOS command table to program Timings.
+ *
+ * @optc: timing_generator instance.
+ * @dc_crtc_timing: Timing parameters used to configure DCN blocks.
+ * @vready_offset: Vready's starting position.
+ * @vstartup_start: Vstartup period.
+ * @vupdate_offset: Vupdate starting position.
+ * @vupdate_width: Vupdate duration.
+ * @signal: DC signal types.
+ * @use_vbios: to program timings from BIOS command table.
+ *
*/
void optc1_program_timing(
struct timing_generator *optc,
@@ -385,6 +398,9 @@ void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enab
* Sets double buffer point for V_TOTAL, H_TOTAL, VTOTAL_MIN,
* VTOTAL_MAX, VTOTAL_MIN_SEL and VTOTAL_MAX_SEL registers.
*
+ * @optc: timing_generator instance.
+ * @enable: Enable DRR double buffering control if true, disable otherwise.
+ *
* Options: any time, start of frame, dp start of frame (range timing)
*/
void optc1_set_timing_double_buffer(struct timing_generator *optc, bool enable)
@@ -397,8 +413,9 @@ void optc1_set_timing_double_buffer(struct timing_generator *optc, bool enable)
}
/**
- * unblank_crtc
- * Call ASIC Control Object to UnBlank CRTC.
+ * optc1_unblank_crtc() - Call ASIC Control Object to UnBlank CRTC.
+ *
+ * @optc: timing_generator instance.
*/
static void optc1_unblank_crtc(struct timing_generator *optc)
{
@@ -419,8 +436,9 @@ static void optc1_unblank_crtc(struct timing_generator *optc)
}
/**
- * blank_crtc
- * Call ASIC Control Object to Blank CRTC.
+ * optc1_blank_crtc() - Call ASIC Control Object to Blank CRTC.
+ *
+ * @optc: timing_generator instance.
*/
static void optc1_blank_crtc(struct timing_generator *optc)
@@ -493,8 +511,9 @@ void optc1_enable_optc_clock(struct timing_generator *optc, bool enable)
}
/**
- * Enable CRTC
- * Enable CRTC - call ASIC Control Object to enable Timing generator.
+ * optc1_enable_crtc() - Enable CRTC - call ASIC Control Object to enable Timing generator.
+ *
+ * @optc: timing_generator instance.
*/
static bool optc1_enable_crtc(struct timing_generator *optc)
{
@@ -653,11 +672,9 @@ void optc1_lock(struct timing_generator *optc)
REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
OTG_MASTER_UPDATE_LOCK, 1);
- /* Should be fast, status does not update on maximus */
- if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
- REG_WAIT(OTG_MASTER_UPDATE_LOCK,
- UPDATE_LOCK_STATUS, 1,
- 1, 10);
+ REG_WAIT(OTG_MASTER_UPDATE_LOCK,
+ UPDATE_LOCK_STATUS, 1,
+ 1, 10);
TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
}
@@ -892,15 +909,11 @@ static void optc1_program_manual_trigger(struct timing_generator *optc)
MANUAL_FLOW_CONTROL, 0);
}
-
/**
- *****************************************************************************
- * Function: set_drr
+ * optc1_set_drr() - Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*.
*
- * @brief
- * Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*.
- *
- *****************************************************************************
+ * @optc: timing_generator instance.
+ * @params: parameters used for Dynamic Refresh Rate.
*/
void optc1_set_drr(
struct timing_generator *optc,
@@ -932,19 +945,10 @@ void optc1_set_drr(
OTG_FORCE_LOCK_ON_EVENT, 0,
OTG_SET_V_TOTAL_MIN_MASK_EN, 0,
OTG_SET_V_TOTAL_MIN_MASK, 0);
-
- // Setup manual flow control for EOF via TRIG_A
- optc->funcs->setup_manual_trigger(optc);
-
- } else {
- REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
- OTG_SET_V_TOTAL_MIN_MASK, 0,
- OTG_V_TOTAL_MIN_SEL, 0,
- OTG_V_TOTAL_MAX_SEL, 0,
- OTG_FORCE_LOCK_ON_EVENT, 0);
-
- optc->funcs->set_vtotal_min_max(optc, 0, 0);
}
+
+ // Setup manual flow control for EOF via TRIG_A
+ optc->funcs->setup_manual_trigger(optc);
}
void optc1_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
index 21ec1ba5ed75..4b02f8443534 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
@@ -553,6 +553,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.recovery_enabled = false, /*enable this by default after testing.*/
.max_downscale_src_width = 3840,
.underflow_assert_delay_us = 0xFFFFFFFF,
+ .enable_legacy_fast_update = true,
};
static const struct dc_debug_options debug_defaults_diags = {
@@ -886,13 +887,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn10_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hwseq = dcn10_hwseq_create,
-};
-
static void dcn10_clock_source_destroy(struct clock_source **clk_src)
{
kfree(TO_DCE110_CLK_SRC(*clk_src));
@@ -1651,9 +1645,8 @@ static bool dcn10_resource_construct(
}
if (!resource_construct(num_virtual_links, dc, &pool->base,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
- goto fail;
+ &res_create_funcs))
+ goto fail;
dcn10_hw_sequencer_construct(dc);
dc->caps.max_planes = pool->base.pipe_count;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h
index 7bdc146f7cb5..c8602bcfa393 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h
@@ -208,7 +208,9 @@
#define DCCG314_REG_FIELD_LIST(type) \
type DSCCLK3_DTO_PHASE;\
type DSCCLK3_DTO_MODULO;\
- type DSCCLK3_DTO_ENABLE;
+ type DSCCLK3_DTO_ENABLE;\
+ type DENTIST_DISPCLK_RDIVIDER;\
+ type DENTIST_DISPCLK_WDIVIDER;
#define DCCG32_REG_FIELD_LIST(type) \
type DPSTREAMCLK0_EN;\
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
index 5bd698cd6d20..5eebe7f03ddc 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
@@ -30,22 +30,13 @@
#include "dsc/dscc_types.h"
#include "dsc/rc_calc.h"
-static void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_config *pps);
-static bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_values *dsc_reg_vals,
- struct dsc_optc_config *dsc_optc_cfg);
-static void dsc_init_reg_values(struct dsc_reg_values *reg_vals);
-static void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params);
static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals);
-static enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_pixel_encoding dc_pix_enc, bool is_ycbcr422_simple);
-static enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_color_depth);
/* Object I/F functions */
-static void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz);
static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s);
static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg);
static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
struct dsc_optc_config *dsc_optc_cfg);
-static bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, uint8_t *dsc_packed_pps);
static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe);
static void dsc2_disable(struct display_stream_compressor *dsc);
static void dsc2_disconnect(struct display_stream_compressor *dsc);
@@ -108,7 +99,7 @@ void dsc2_construct(struct dcn20_dsc *dsc,
/* This returns the capabilities for a single DSC encoder engine. Number of slices and total throughput
* can be doubled, tripled etc. by using additional DSC engines.
*/
-static void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz)
+void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz)
{
dsc_enc_caps->dsc_version = 0x21; /* v1.2 - DP spec defined it in reverse order and we kept it */
@@ -184,7 +175,7 @@ static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const st
}
-static void dsc_config_log(struct display_stream_compressor *dsc, const struct dsc_config *config)
+void dsc_config_log(struct display_stream_compressor *dsc, const struct dsc_config *config)
{
DC_LOG_DSC("\tnum_slices_h %d", config->dc_dsc_cfg.num_slices_h);
DC_LOG_DSC("\tnum_slices_v %d", config->dc_dsc_cfg.num_slices_v);
@@ -211,7 +202,7 @@ static void dsc2_set_config(struct display_stream_compressor *dsc, const struct
}
-static bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, uint8_t *dsc_packed_pps)
+bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, uint8_t *dsc_packed_pps)
{
bool is_config_ok;
struct dsc_reg_values dsc_reg_vals;
@@ -291,7 +282,7 @@ static void dsc2_disconnect(struct display_stream_compressor *dsc)
}
/* This module's internal functions */
-static void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_config *pps)
+void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_config *pps)
{
int i;
int bits_per_pixel = pps->bits_per_pixel;
@@ -345,7 +336,7 @@ static void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_co
}
}
-static void dsc_override_rc_params(struct rc_params *rc, const struct dc_dsc_rc_params_override *override)
+void dsc_override_rc_params(struct rc_params *rc, const struct dc_dsc_rc_params_override *override)
{
uint8_t i;
@@ -372,7 +363,7 @@ static void dsc_override_rc_params(struct rc_params *rc, const struct dc_dsc_rc_
rc->flatness_det_thresh = override->flatness_det_thresh;
}
-static bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_values *dsc_reg_vals,
+bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_values *dsc_reg_vals,
struct dsc_optc_config *dsc_optc_cfg)
{
struct dsc_parameters dsc_params;
@@ -463,7 +454,7 @@ static bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_
}
-static enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_pixel_encoding dc_pix_enc, bool is_ycbcr422_simple)
+enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_pixel_encoding dc_pix_enc, bool is_ycbcr422_simple)
{
enum dsc_pixel_format dsc_pix_fmt = DSC_PIXFMT_UNKNOWN;
@@ -495,7 +486,7 @@ static enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_p
}
-static enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_color_depth dc_color_depth)
+enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_color_depth dc_color_depth)
{
enum dsc_bits_per_comp bpc = DSC_BPC_UNKNOWN;
@@ -518,7 +509,7 @@ static enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_co
}
-static void dsc_init_reg_values(struct dsc_reg_values *reg_vals)
+void dsc_init_reg_values(struct dsc_reg_values *reg_vals)
{
int i;
@@ -574,7 +565,7 @@ static void dsc_init_reg_values(struct dsc_reg_values *reg_vals)
* This is required because dscc_compute_dsc_parameters returns a modified PPS, which in turn
* affects non-PPS register values.
*/
-static void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params)
+void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params)
{
int i;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h
index 7ce64a3c1b02..ba869387c3c5 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h
@@ -549,6 +549,27 @@ struct dcn20_dsc {
int max_image_width;
};
+void dsc_config_log(struct display_stream_compressor *dsc,
+ const struct dsc_config *config);
+
+void dsc_log_pps(struct display_stream_compressor *dsc,
+ struct drm_dsc_config *pps);
+
+void dsc_override_rc_params(struct rc_params *rc,
+ const struct dc_dsc_rc_params_override *override);
+
+bool dsc_prepare_config(const struct dsc_config *dsc_cfg,
+ struct dsc_reg_values *dsc_reg_vals,
+ struct dsc_optc_config *dsc_optc_cfg);
+
+enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_pixel_encoding dc_pix_enc,
+ bool is_ycbcr422_simple);
+
+enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_color_depth dc_color_depth);
+
+void dsc_init_reg_values(struct dsc_reg_values *reg_vals);
+
+void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params);
void dsc2_construct(struct dcn20_dsc *dsc,
struct dc_context *ctx,
@@ -557,5 +578,12 @@ void dsc2_construct(struct dcn20_dsc *dsc,
const struct dcn20_dsc_shift *dsc_shift,
const struct dcn20_dsc_mask *dsc_mask);
+void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps,
+ int pixel_clock_100Hz);
+
+bool dsc2_get_packed_pps(struct display_stream_compressor *dsc,
+ const struct dsc_config *dsc_cfg,
+ uint8_t *dsc_packed_pps);
+
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
index 24bd93219936..6eebcb22e317 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
@@ -623,6 +623,17 @@ void hubbub2_read_state(struct hubbub *hubbub, struct dcn_hubbub_state *hubbub_s
REG_GET(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, &hubbub_state->vm_error_vmid);
REG_GET(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, &hubbub_state->vm_error_pipe);
}
+
+ if (REG(DCHUBBUB_TEST_DEBUG_INDEX) && REG(DCHUBBUB_TEST_DEBUG_DATA)) {
+ REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, 0x6);
+ hubbub_state->test_debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA);
+ }
+
+ if (REG(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL))
+ hubbub_state->watermark_change_cntl = REG_READ(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL);
+
+ if (REG(DCHUBBUB_ARB_DRAM_STATE_CNTL))
+ hubbub_state->dram_state_cntl = REG_READ(DCHUBBUB_ARB_DRAM_STATE_CNTL);
}
static const struct hubbub_funcs hubbub2_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index 5403e9399a46..eaf9e9ccad2a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -313,6 +313,10 @@ void dcn20_init_blank(
}
opp = dc->res_pool->opps[opp_id_src0];
+ /* don't override the blank pattern if already enabled with the correct one. */
+ if (opp->funcs->dpg_is_blanked && opp->funcs->dpg_is_blanked(opp))
+ return;
+
if (num_opps == 2) {
otg_active_width = otg_active_width / 2;
@@ -1357,6 +1361,7 @@ static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx
new_pipe->update_flags.bits.dppclk = 1;
new_pipe->update_flags.bits.hubp_interdependent = 1;
new_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
+ new_pipe->update_flags.bits.unbounded_req = 1;
new_pipe->update_flags.bits.gamut_remap = 1;
new_pipe->update_flags.bits.scaler = 1;
new_pipe->update_flags.bits.viewport = 1;
@@ -1500,6 +1505,9 @@ static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx
memcmp(&old_pipe->rq_regs, &new_pipe->rq_regs, sizeof(old_pipe->rq_regs)))
new_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
}
+
+ if (old_pipe->unbounded_req != new_pipe->unbounded_req)
+ new_pipe->update_flags.bits.unbounded_req = 1;
}
static void dcn20_update_dchubp_dpp(
@@ -1533,10 +1541,11 @@ static void dcn20_update_dchubp_dpp(
&pipe_ctx->ttu_regs,
&pipe_ctx->rq_regs,
&pipe_ctx->pipe_dlg_param);
-
- if (hubp->funcs->set_unbounded_requesting)
- hubp->funcs->set_unbounded_requesting(hubp, pipe_ctx->unbounded_req);
}
+
+ if (pipe_ctx->update_flags.bits.unbounded_req && hubp->funcs->set_unbounded_requesting)
+ hubp->funcs->set_unbounded_requesting(hubp, pipe_ctx->unbounded_req);
+
if (pipe_ctx->update_flags.bits.hubp_interdependent)
hubp->funcs->hubp_setup_interdependent(
hubp,
@@ -2117,7 +2126,7 @@ void dcn20_optimize_bandwidth(
dc->clk_mgr,
context,
true);
- if (dc_extended_blank_supported(dc) && context->bw_ctx.bw.dcn.clk.zstate_support == DCN_ZSTATE_SUPPORT_ALLOW) {
+ if (context->bw_ctx.bw.dcn.clk.zstate_support == DCN_ZSTATE_SUPPORT_ALLOW) {
for (i = 0; i < dc->res_pool->pipe_count; ++i) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
@@ -2125,7 +2134,7 @@ void dcn20_optimize_bandwidth(
&& pipe_ctx->stream->adjust.v_total_min == pipe_ctx->stream->adjust.v_total_max
&& pipe_ctx->stream->adjust.v_total_max > pipe_ctx->stream->timing.v_total)
pipe_ctx->plane_res.hubp->funcs->program_extended_blank(pipe_ctx->plane_res.hubp,
- pipe_ctx->dlg_regs.optimized_min_dst_y_next_start);
+ pipe_ctx->dlg_regs.min_dst_y_next_start);
}
}
}
@@ -2462,36 +2471,31 @@ static void dcn20_reset_back_end_for_pipe(
return;
}
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- /* DPMS may already disable or */
- /* dpms_off status is incorrect due to fastboot
- * feature. When system resume from S4 with second
- * screen only, the dpms_off would be true but
- * VBIOS lit up eDP, so check link status too.
- */
- if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
- dc->link_srv->set_dpms_off(pipe_ctx);
- else if (pipe_ctx->stream_res.audio)
- dc->hwss.disable_audio_stream(pipe_ctx);
-
- /* free acquired resources */
- if (pipe_ctx->stream_res.audio) {
- /*disable az_endpoint*/
- pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
-
- /*free audio*/
- if (dc->caps.dynamic_audio == true) {
- /*we have to dynamic arbitrate the audio endpoints*/
- /*we free the resource, need reset is_audio_acquired*/
- update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
- pipe_ctx->stream_res.audio, false);
- pipe_ctx->stream_res.audio = NULL;
- }
+ /* DPMS may already disable or */
+ /* dpms_off status is incorrect due to fastboot
+ * feature. When system resume from S4 with second
+ * screen only, the dpms_off would be true but
+ * VBIOS lit up eDP, so check link status too.
+ */
+ if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
+ dc->link_srv->set_dpms_off(pipe_ctx);
+ else if (pipe_ctx->stream_res.audio)
+ dc->hwss.disable_audio_stream(pipe_ctx);
+
+ /* free acquired resources */
+ if (pipe_ctx->stream_res.audio) {
+ /*disable az_endpoint*/
+ pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
+
+ /*free audio*/
+ if (dc->caps.dynamic_audio == true) {
+ /*we have to dynamic arbitrate the audio endpoints*/
+ /*we free the resource, need reset is_audio_acquired*/
+ update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
+ pipe_ctx->stream_res.audio, false);
+ pipe_ctx->stream_res.audio = NULL;
}
}
- else if (pipe_ctx->stream_res.dsc) {
- dc->link_srv->set_dsc_enable(pipe_ctx, false);
- }
/* by upper caller loop, parent pipe: pipe0, will be reset last.
* back end share by all pipes and will be disable only when disable
@@ -2567,28 +2571,6 @@ void dcn20_reset_hw_ctx_wrap(
}
}
-void dcn20_update_visual_confirm_color(struct dc *dc, struct pipe_ctx *pipe_ctx, struct tg_color *color, int mpcc_id)
-{
- struct mpc *mpc = dc->res_pool->mpc;
-
- // input to MPCC is always RGB, by default leave black_color at 0
- if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR)
- get_hdr_visual_confirm_color(pipe_ctx, color);
- else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
- get_surface_visual_confirm_color(pipe_ctx, color);
- else if (dc->debug.visual_confirm == VISUAL_CONFIRM_MPCTREE)
- get_mpctree_visual_confirm_color(pipe_ctx, color);
- else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SWIZZLE)
- get_surface_tile_visual_confirm_color(pipe_ctx, color);
- else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP)
- get_subvp_visual_confirm_color(dc, pipe_ctx, color);
-
- if (mpc->funcs->set_bg_color) {
- memcpy(&pipe_ctx->plane_state->visual_confirm_color, color, sizeof(struct tg_color));
- mpc->funcs->set_bg_color(mpc, color, mpcc_id);
- }
-}
-
void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
struct hubp *hubp = pipe_ctx->plane_res.hubp;
@@ -2644,7 +2626,7 @@ void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
if (!pipe_ctx->plane_state->update_flags.bits.full_update &&
!pipe_ctx->update_flags.bits.mpcc) {
mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
- dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
+ dc->hwss.update_visual_confirm_color(dc, pipe_ctx, mpcc_id);
return;
}
@@ -2666,7 +2648,7 @@ void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
NULL,
hubp->inst,
mpcc_id);
- dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
+ dc->hwss.update_visual_confirm_color(dc, pipe_ctx, mpcc_id);
ASSERT(new_mpcc != NULL);
hubp->opp_id = pipe_ctx->stream_res.opp->inst;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h
index 33a36c02b2f8..01901b08644c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h
@@ -150,10 +150,5 @@ void dcn20_set_disp_pattern_generator(const struct dc *dc,
const struct tg_color *solid_color,
int width, int height, int offset);
-void dcn20_update_visual_confirm_color(struct dc *dc,
- struct pipe_ctx *pipe_ctx,
- struct tg_color *color,
- int mpcc_id);
-
#endif /* __DC_HWSS_DCN20_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
index 7c5817c426fa..e4b44e691ce6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
@@ -102,7 +102,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = {
.disable_link_output = dce110_disable_link_output,
.set_disp_pattern_generator = dcn20_set_disp_pattern_generator,
.get_dcc_en_bits = dcn10_get_dcc_en_bits,
- .update_visual_confirm_color = dcn20_update_visual_confirm_color
+ .update_visual_confirm_color = dcn10_update_visual_confirm_color,
};
static const struct hwseq_private_funcs dcn20_private_funcs = {
@@ -145,8 +145,4 @@ void dcn20_hw_sequencer_construct(struct dc *dc)
dc->hwss = dcn20_funcs;
dc->hwseq->funcs = dcn20_private_funcs;
- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- dc->hwss.init_hw = dcn20_fpga_init_hw;
- dc->hwseq->funcs.init_pipes = NULL;
- }
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
index a08c335b7383..58bdbd859bf9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
@@ -38,8 +38,12 @@
optc1->tg_shift->field_name, optc1->tg_mask->field_name
/**
- * Enable CRTC
- * Enable CRTC - call ASIC Control Object to enable Timing generator.
+ * optc2_enable_crtc() - Enable CRTC - call ASIC Control Object to enable Timing generator.
+ *
+ * @optc: timing_generator instance.
+ *
+ * Return: If CRTC is enabled, return true.
+ *
*/
bool optc2_enable_crtc(struct timing_generator *optc)
{
@@ -73,15 +77,18 @@ bool optc2_enable_crtc(struct timing_generator *optc)
}
/**
- *For the below, I'm not sure how your GSL parameters are stored in your env,
- * so I will assume a gsl_params struct for now
+ * optc2_set_gsl() - Assign OTG to GSL groups,
+ * set one of the OTGs to be master & rest are slaves
+ *
+ * @optc: timing_generator instance.
+ * @params: pointer to gsl_params
*/
void optc2_set_gsl(struct timing_generator *optc,
const struct gsl_params *params)
{
struct optc *optc1 = DCN10TG_FROM_TG(optc);
-/**
+/*
* There are (MAX_OPTC+1)/2 gsl groups available for use.
* In each group (assign an OTG to a group by setting OTG_GSLX_EN = 1,
* set one of the OTGs to be the master (OTG_GSL_MASTER_EN = 1) and the rest are slaves.
@@ -391,10 +398,9 @@ void optc2_triplebuffer_lock(struct timing_generator *optc)
REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
OTG_MASTER_UPDATE_LOCK, 1);
- if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
- REG_WAIT(OTG_MASTER_UPDATE_LOCK,
- UPDATE_LOCK_STATUS, 1,
- 1, 10);
+ REG_WAIT(OTG_MASTER_UPDATE_LOCK,
+ UPDATE_LOCK_STATUS, 1,
+ 1, 10);
}
void optc2_triplebuffer_unlock(struct timing_generator *optc)
@@ -456,6 +462,16 @@ void optc2_setup_manual_trigger(struct timing_generator *optc)
{
struct optc *optc1 = DCN10TG_FROM_TG(optc);
+ /* Set the min/max selectors unconditionally so that
+ * DMCUB fw may change OTG timings when necessary
+ * TODO: Remove the w/a after fixing the issue in DMCUB firmware
+ */
+ REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
+ OTG_V_TOTAL_MIN_SEL, 1,
+ OTG_V_TOTAL_MAX_SEL, 1,
+ OTG_FORCE_LOCK_ON_EVENT, 0,
+ OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */
+
REG_SET_8(OTG_TRIGA_CNTL, 0,
OTG_TRIGA_SOURCE_SELECT, 21,
OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
index 1d8c5805ef20..4cc8de2627ce 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -722,22 +722,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.scl_reset_length10 = true,
.sanity_checks = false,
.underflow_assert_delay_us = 0xFFFFFFFF,
-};
-
-static const struct dc_debug_options debug_defaults_diags = {
- .disable_dmcu = false,
- .force_abm_enable = false,
- .timing_trace = true,
- .clock_trace = true,
- .disable_dpp_power_gate = true,
- .disable_hubp_power_gate = true,
- .disable_clock_gate = true,
- .disable_pplib_clock_request = true,
- .disable_pplib_wm_range = true,
- .disable_stutter = true,
- .scl_reset_length10 = true,
- .underflow_assert_delay_us = 0xFFFFFFFF,
- .enable_tri_buf = true,
+ .enable_legacy_fast_update = true,
};
void dcn20_dpp_destroy(struct dpp **dpp)
@@ -1066,13 +1051,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn20_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hwseq = dcn20_hwseq_create,
-};
-
static void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu);
void dcn20_clock_source_destroy(struct clock_source **clk_src)
@@ -2488,15 +2466,9 @@ static bool dcn20_resource_construct(
dc->caps.dp_hdmi21_pcon_support = true;
- if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) {
+ if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
- } else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
- pool->base.pipe_count = 4;
- pool->base.mpcc_count = pool->base.pipe_count;
- dc->debug = debug_defaults_diags;
- } else {
- dc->debug = debug_defaults_diags;
- }
+
//dcn2.0x
dc->work_arounds.dedcn20_305_wa = true;
@@ -2734,9 +2706,8 @@ static bool dcn20_resource_construct(
}
if (!resource_construct(num_virtual_links, dc, &pool->base,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
- goto create_fail;
+ &res_create_funcs))
+ goto create_fail;
dcn20_hw_sequencer_construct(dc);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c
index 1aeb04fbd89d..9e027db6d752 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c
@@ -231,52 +231,39 @@ void dcn201_init_hw(struct dc *dc)
if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
- REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
-
- hws->funcs.dccg_init(hws);
-
- REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
- REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
- REG_WRITE(REFCLK_CNTL, 0);
- } else {
- hws->funcs.bios_golden_init(dc);
-
- if (dc->ctx->dc_bios->fw_info_valid) {
- res_pool->ref_clocks.xtalin_clock_inKhz =
- dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
-
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- if (res_pool->dccg && res_pool->hubbub) {
- (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
- dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
- &res_pool->ref_clocks.dccg_ref_clock_inKhz);
-
- (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
- res_pool->ref_clocks.dccg_ref_clock_inKhz,
- &res_pool->ref_clocks.dchub_ref_clock_inKhz);
- } else {
- res_pool->ref_clocks.dccg_ref_clock_inKhz =
- res_pool->ref_clocks.xtalin_clock_inKhz;
- res_pool->ref_clocks.dchub_ref_clock_inKhz =
- res_pool->ref_clocks.xtalin_clock_inKhz;
- }
- }
- } else
- ASSERT_CRITICAL(false);
- for (i = 0; i < dc->link_count; i++) {
- /* Power up AND update implementation according to the
- * required signal (which may be different from the
- * default signal on connector).
- */
- struct dc_link *link = dc->links[i];
-
- link->link_enc->funcs->hw_init(link->link_enc);
+ hws->funcs.bios_golden_init(dc);
+
+ if (dc->ctx->dc_bios->fw_info_valid) {
+ res_pool->ref_clocks.xtalin_clock_inKhz =
+ dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
+
+ if (res_pool->dccg && res_pool->hubbub) {
+ (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
+ dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
+ &res_pool->ref_clocks.dccg_ref_clock_inKhz);
+
+ (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
+ res_pool->ref_clocks.dccg_ref_clock_inKhz,
+ &res_pool->ref_clocks.dchub_ref_clock_inKhz);
+ } else {
+ res_pool->ref_clocks.dccg_ref_clock_inKhz =
+ res_pool->ref_clocks.xtalin_clock_inKhz;
+ res_pool->ref_clocks.dchub_ref_clock_inKhz =
+ res_pool->ref_clocks.xtalin_clock_inKhz;
}
- if (hws->fb_offset.quad_part == 0)
- read_mmhub_vm_setup(hws);
+ } else
+ ASSERT_CRITICAL(false);
+ for (i = 0; i < dc->link_count; i++) {
+ /* Power up AND update implementation according to the
+ * required signal (which may be different from the
+ * default signal on connector).
+ */
+ struct dc_link *link = dc->links[i];
+
+ link->link_enc->funcs->hw_init(link->link_enc);
}
+ if (hws->fb_offset.quad_part == 0)
+ read_mmhub_vm_setup(hws);
/* Blank pixel data with OPP DPG */
for (i = 0; i < res_pool->timing_generator_count; i++) {
@@ -362,10 +349,6 @@ void dcn201_init_hw(struct dc *dc)
tg->funcs->tg_init(tg);
}
- /* end of FPGA. Below if real ASIC */
- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
- return;
-
for (i = 0; i < res_pool->audio_count; i++) {
struct audio *audio = res_pool->audios[i];
@@ -496,7 +479,7 @@ void dcn201_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
/* If there is no full update, don't need to touch MPC tree*/
if (!pipe_ctx->plane_state->update_flags.bits.full_update) {
- dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
+ dc->hwss.update_visual_confirm_color(dc, pipe_ctx, mpcc_id);
mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
return;
}
@@ -521,7 +504,7 @@ void dcn201_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
dc->res_pool->mpc, mpcc_id);
/* Call MPC to insert new plane */
- dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
+ dc->hwss.update_visual_confirm_color(dc, pipe_ctx, mpcc_id);
new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
mpc_tree_params,
&blnd_cfg,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c
index 9c16633e473a..92dd4cddbab8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c
@@ -91,7 +91,7 @@ static const struct hw_sequencer_funcs dcn201_funcs = {
.enable_dp_link_output = dce110_enable_dp_link_output,
.disable_link_output = dce110_disable_link_output,
.set_disp_pattern_generator = dcn20_set_disp_pattern_generator,
- .update_visual_confirm_color = dcn20_update_visual_confirm_color,
+ .update_visual_confirm_color = dcn10_update_visual_confirm_color,
};
static const struct hwseq_private_funcs dcn201_private_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.c
index 730875dfd8b4..70fcbec03fb6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.c
@@ -55,10 +55,9 @@ static void optc201_triplebuffer_lock(struct timing_generator *optc)
REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
OTG_MASTER_UPDATE_LOCK, 1);
- if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
- REG_WAIT(OTG_MASTER_UPDATE_LOCK,
- UPDATE_LOCK_STATUS, 1,
- 1, 10);
+ REG_WAIT(OTG_MASTER_UPDATE_LOCK,
+ UPDATE_LOCK_STATUS, 1,
+ 1, 10);
}
static void optc201_triplebuffer_unlock(struct timing_generator *optc)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c
index 6ea70da28aaa..fdba8a9f5c30 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c
@@ -613,6 +613,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.sanity_checks = false,
.underflow_assert_delay_us = 0xFFFFFFFF,
.enable_tri_buf = false,
+ .enable_legacy_fast_update = true,
};
static void dcn201_dpp_destroy(struct dpp **dpp)
@@ -896,13 +897,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn201_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hwseq = dcn201_hwseq_create,
-};
-
static void dcn201_clock_source_destroy(struct clock_source **clk_src)
{
kfree(TO_DCE110_CLK_SRC(*clk_src));
@@ -1272,9 +1266,8 @@ static bool dcn201_resource_construct(
}
if (!resource_construct(num_virtual_links, dc, &pool->base,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
- goto create_fail;
+ &res_create_funcs))
+ goto create_fail;
dcn201_hw_sequencer_construct(dc);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
index 58e459c7e7d3..f976fac8dc3f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
@@ -667,7 +667,6 @@ static void program_surface_flip_and_addr(struct hubp *hubp, struct surface_flip
static void dmcub_PLAT_54186_wa(struct hubp *hubp,
struct surface_flip_registers *flip_regs)
{
- struct dc_dmub_srv *dmcub = hubp->ctx->dmub_srv;
struct dcn21_hubp *hubp21 = TO_DCN21_HUBP(hubp);
union dmub_rb_cmd cmd;
@@ -690,11 +689,7 @@ static void dmcub_PLAT_54186_wa(struct hubp *hubp,
cmd.PLAT_54186_wa.flip.flip_params.vmid = flip_regs->vmid;
PERF_TRACE(); // TODO: remove after performance is stable.
- dc_dmub_srv_cmd_queue(dmcub, &cmd);
- PERF_TRACE(); // TODO: remove after performance is stable.
- dc_dmub_srv_cmd_execute(dmcub);
- PERF_TRACE(); // TODO: remove after performance is stable.
- dc_dmub_srv_wait_idle(dmcub);
+ dm_execute_dmub_cmd(hubp->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
PERF_TRACE(); // TODO: remove after performance is stable.
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c
index 2a182c2f57d6..43463d08f21b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c
@@ -152,13 +152,28 @@ static bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, uint32_t optio
cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary;
cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data);
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
+static void dmub_abm_set_backlight(struct dc_context *dc, uint32_t backlight_pwm_u16_16,
+ uint32_t frame_ramp, uint32_t panel_inst)
+{
+ union dmub_rb_cmd cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.abm_set_backlight.header.type = DMUB_CMD__ABM;
+ cmd.abm_set_backlight.header.sub_type = DMUB_CMD__ABM_SET_BACKLIGHT;
+ cmd.abm_set_backlight.abm_set_backlight_data.frame_ramp = frame_ramp;
+ cmd.abm_set_backlight.abm_set_backlight_data.backlight_user_level = backlight_pwm_u16_16;
+ cmd.abm_set_backlight.abm_set_backlight_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
+ cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_inst);
+ cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data);
+
+ dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+}
+
void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx)
{
struct abm *abm = pipe_ctx->stream_res.abm;
@@ -173,8 +188,12 @@ void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx)
}
if (abm && panel_cntl) {
- dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_IMMEDIATELY_DISABLE,
- panel_cntl->inst);
+ if (abm->funcs && abm->funcs->set_pipe_ex) {
+ abm->funcs->set_pipe_ex(abm, otg_inst, SET_ABM_PIPE_IMMEDIATELY_DISABLE,
+ panel_cntl->inst);
+ } else {
+ dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_IMMEDIATELY_DISABLE, panel_cntl->inst);
+ }
panel_cntl->funcs->store_backlight_level(panel_cntl);
}
}
@@ -191,18 +210,21 @@ void dcn21_set_pipe(struct pipe_ctx *pipe_ctx)
return;
}
- if (abm && panel_cntl)
- dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_NORMAL, panel_cntl->inst);
+ if (abm && panel_cntl) {
+ if (abm->funcs && abm->funcs->set_pipe_ex) {
+ abm->funcs->set_pipe_ex(abm, otg_inst, SET_ABM_PIPE_NORMAL, panel_cntl->inst);
+ } else {
+ dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_NORMAL, panel_cntl->inst);
+ }
+ }
}
bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx,
uint32_t backlight_pwm_u16_16,
uint32_t frame_ramp)
{
- union dmub_rb_cmd cmd;
struct dc_context *dc = pipe_ctx->stream->ctx;
struct abm *abm = pipe_ctx->stream_res.abm;
- uint32_t otg_inst = pipe_ctx->stream_res.tg->inst;
struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
if (dc->dc->res_pool->dmcu) {
@@ -210,21 +232,23 @@ bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx,
return true;
}
- if (abm && panel_cntl)
- dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_NORMAL, panel_cntl->inst);
+ if (abm != NULL) {
+ uint32_t otg_inst = pipe_ctx->stream_res.tg->inst;
- memset(&cmd, 0, sizeof(cmd));
- cmd.abm_set_backlight.header.type = DMUB_CMD__ABM;
- cmd.abm_set_backlight.header.sub_type = DMUB_CMD__ABM_SET_BACKLIGHT;
- cmd.abm_set_backlight.abm_set_backlight_data.frame_ramp = frame_ramp;
- cmd.abm_set_backlight.abm_set_backlight_data.backlight_user_level = backlight_pwm_u16_16;
- cmd.abm_set_backlight.abm_set_backlight_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
- cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_cntl->inst);
- cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data);
+ if (abm && panel_cntl) {
+ if (abm->funcs && abm->funcs->set_pipe_ex) {
+ abm->funcs->set_pipe_ex(abm, otg_inst, SET_ABM_PIPE_NORMAL, panel_cntl->inst);
+ } else {
+ dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_NORMAL, panel_cntl->inst);
+ }
+ }
+ }
- dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->dmub_srv);
- dc_dmub_srv_wait_idle(dc->dmub_srv);
+ if (abm && abm->funcs && abm->funcs->set_backlight_level_pwm)
+ abm->funcs->set_backlight_level_pwm(abm, backlight_pwm_u16_16,
+ frame_ramp, 0, panel_cntl->inst);
+ else
+ dmub_abm_set_backlight(dc, backlight_pwm_u16_16, frame_ramp, panel_cntl->inst);
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c
index fe1a8e2e08ef..f024157bd6eb 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c
@@ -106,7 +106,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = {
.is_abm_supported = dcn21_is_abm_supported,
.set_disp_pattern_generator = dcn20_set_disp_pattern_generator,
.get_dcc_en_bits = dcn10_get_dcc_en_bits,
- .update_visual_confirm_color = dcn20_update_visual_confirm_color,
+ .update_visual_confirm_color = dcn10_update_visual_confirm_color,
};
static const struct hwseq_private_funcs dcn21_private_funcs = {
@@ -151,8 +151,4 @@ void dcn21_hw_sequencer_construct(struct dc *dc)
dc->hwss = dcn21_funcs;
dc->hwseq->funcs = dcn21_private_funcs;
- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- dc->hwss.init_hw = dcn20_fpga_init_hw;
- dc->hwseq->funcs.init_pipes = NULL;
- }
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
index 19aaa557b2db..d693ea42d033 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
@@ -653,22 +653,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.usbc_combo_phy_reset_wa = true,
.dmub_command_table = true,
.use_max_lb = true,
-};
-
-static const struct dc_debug_options debug_defaults_diags = {
- .disable_dmcu = false,
- .force_abm_enable = false,
- .timing_trace = true,
- .clock_trace = true,
- .disable_dpp_power_gate = true,
- .disable_hubp_power_gate = true,
- .disable_clock_gate = true,
- .disable_pplib_clock_request = true,
- .disable_pplib_wm_range = true,
- .disable_stutter = true,
- .disable_48mhz_pwrdwn = true,
- .enable_tri_buf = true,
- .use_max_lb = true
+ .enable_legacy_fast_update = true,
};
static const struct dc_panel_config panel_config_defaults = {
@@ -1219,13 +1204,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn21_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hwseq = dcn21_hwseq_create,
-};
-
static const struct encoder_feature_support link_enc_feature = {
.max_hdmi_deep_color = COLOR_DEPTH_121212,
.max_hdmi_pixel_clock = 600000,
@@ -1503,11 +1481,6 @@ static bool dcn21_resource_construct(
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
- else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
- pool->base.pipe_count = 4;
- dc->debug = debug_defaults_diags;
- } else
- dc->debug = debug_defaults_diags;
// Init the vm_helper
if (dc->vm_helper)
@@ -1721,9 +1694,8 @@ static bool dcn21_resource_construct(
}
if (!resource_construct(num_virtual_links, dc, &pool->base,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
- goto create_fail;
+ &res_create_funcs))
+ goto create_fail;
dcn21_hw_sequencer_construct(dc);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
index b7c2ae9ddfda..4a3e9e47b6b6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
@@ -1,16 +1,16 @@
-#
+#
# Copyright 2020 Advanced Micro Devices, Inc.
-#
+#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -18,17 +18,31 @@
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
-#
+#
# Authors: AMD
-#
-#
+#
+#
+
+DCN30 := \
+ dcn30_init.o \
+ dcn30_hubbub.o \
+ dcn30_hubp.o \
+ dcn30_dpp.o \
+ dcn30_optc.o \
+ dcn30_dccg.o \
+ dcn30_hwseq.o \
+ dcn30_mpc.o dcn30_vpg.o \
+ dcn30_afmt.o \
+ dcn30_dio_stream_encoder.o \
+ dcn30_dwb.o \
+ dcn30_dpp_cm.o \
+ dcn30_dwb_cm.o \
+ dcn30_cm_common.o \
+ dcn30_mmhubbub.o \
+ dcn30_resource.o \
+ dcn30_dio_link_encoder.o
-DCN30 = dcn30_init.o dcn30_hubbub.o dcn30_hubp.o dcn30_dpp.o dcn30_optc.o \
- dcn30_dccg.o dcn30_hwseq.o dcn30_mpc.o dcn30_vpg.o \
- dcn30_afmt.o dcn30_dio_stream_encoder.o dcn30_dwb.o \
- dcn30_dpp_cm.o dcn30_dwb_cm.o dcn30_cm_common.o dcn30_mmhubbub.o \
- dcn30_dio_link_encoder.o dcn30_resource.o
AMD_DAL_DCN30 = $(addprefix $(AMDDALPATH)/dc/dcn30/,$(DCN30))
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
index 9d08127d209b..005dbe099a7a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
@@ -436,6 +436,21 @@ void enc3_stream_encoder_update_dp_info_packets(
&info_frame->vsc,
true);
}
+ /* TODO: VSC SDP at packetIndex 1 should be retricted only if PSR-SU on.
+ * There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU.
+ * In addition, currently the driver check the valid bit then update and
+ * send the corresponding Infopacket. For PSR-SU, the SDP only be sent
+ * while entering PSR-SU mode. So we need another parameter(e.g. send)
+ * in dc_info_packet to indicate which infopacket should be enabled by
+ * default here.
+ */
+ if (info_frame->vsc.valid) {
+ enc->vpg->funcs->update_generic_info_packet(
+ enc->vpg,
+ 1, /* packetIndex */
+ &info_frame->vsc,
+ true);
+ }
/* TODO: VSC SDP at packetIndex 1 should be restricted only if PSR-SU on.
* There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU.
* In addition, currently the driver check the valid bit then update and
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c
index e46bbe7ddcc9..2861d974fcf6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c
@@ -449,6 +449,12 @@ void hubp3_read_state(struct hubp *hubp)
SWATH_HEIGHT_C, &rq_regs->rq_regs_c.swath_height,
PTE_ROW_HEIGHT_LINEAR_C, &rq_regs->rq_regs_c.pte_row_height_linear);
+ if (REG(UCLK_PSTATE_FORCE))
+ s->uclk_pstate_force = REG_READ(UCLK_PSTATE_FORCE);
+
+ if (REG(DCHUBP_CNTL))
+ s->hubp_cntl = REG_READ(DCHUBP_CNTL);
+
}
void hubp3_setup(
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
index 32121db2851e..b9753867d97b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
@@ -330,10 +330,6 @@ void dcn30_enable_writeback(
DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\
__func__, wb_info->dwb_pipe_inst,\
wb_info->mpcc_inst);
- if (IS_DIAG_DC(dc->ctx->dce_environment)) {
- /*till diags switch to warmup interface*/
- dcn30_mmhubbub_warmup(dc, 1, wb_info);
- }
/* Update writeback pipe */
dcn30_set_writeback(dc, wb_info, context);
@@ -447,28 +443,6 @@ void dcn30_init_hw(struct dc *dc)
if (res_pool->dccg->funcs->dccg_init)
res_pool->dccg->funcs->dccg_init(res_pool->dccg);
- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
-
- REG_WRITE(REFCLK_CNTL, 0);
- REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
- REG_WRITE(DIO_MEM_PWR_CTRL, 0);
-
- if (!dc->debug.disable_clock_gate) {
- /* enable all DCN clock gating */
- REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
-
- REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
-
- REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
- }
-
- //Enable ability to power gate / don't force power on permanently
- if (hws->funcs.enable_power_gating_plane)
- hws->funcs.enable_power_gating_plane(hws, true);
-
- return;
- }
-
if (!dcb->funcs->is_accelerated_mode(dcb)) {
hws->funcs.bios_golden_init(dc);
hws->funcs.disable_vga(dc->hwseq);
@@ -491,23 +465,21 @@ void dcn30_init_hw(struct dc *dc)
res_pool->ref_clocks.xtalin_clock_inKhz =
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- if (res_pool->dccg && res_pool->hubbub) {
+ if (res_pool->dccg && res_pool->hubbub) {
- (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
- dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
- &res_pool->ref_clocks.dccg_ref_clock_inKhz);
+ (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
+ dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
+ &res_pool->ref_clocks.dccg_ref_clock_inKhz);
- (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
- res_pool->ref_clocks.dccg_ref_clock_inKhz,
- &res_pool->ref_clocks.dchub_ref_clock_inKhz);
- } else {
- // Not all ASICs have DCCG sw component
- res_pool->ref_clocks.dccg_ref_clock_inKhz =
- res_pool->ref_clocks.xtalin_clock_inKhz;
- res_pool->ref_clocks.dchub_ref_clock_inKhz =
- res_pool->ref_clocks.xtalin_clock_inKhz;
- }
+ (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
+ res_pool->ref_clocks.dccg_ref_clock_inKhz,
+ &res_pool->ref_clocks.dchub_ref_clock_inKhz);
+ } else {
+ // Not all ASICs have DCCG sw component
+ res_pool->ref_clocks.dccg_ref_clock_inKhz =
+ res_pool->ref_clocks.xtalin_clock_inKhz;
+ res_pool->ref_clocks.dchub_ref_clock_inKhz =
+ res_pool->ref_clocks.xtalin_clock_inKhz;
}
} else
ASSERT_CRITICAL(false);
@@ -632,7 +604,7 @@ void dcn30_init_hw(struct dc *dc)
dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
// Get DMCUB capabilities
- dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv->dmub);
+ dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv);
dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch;
}
@@ -736,8 +708,7 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_NO_DF_REQ;
cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header);
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
return true;
}
@@ -859,9 +830,7 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
cmd.mall.cursor_height = cursor_attr.height;
cmd.mall.cursor_pitch = cursor_attr.pitch;
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
/* Use copied cursor, and it's okay to not switch back */
cursor_attr.address.quad_part = cmd.mall.cursor_copy_dst.quad_part;
@@ -877,8 +846,7 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
cmd.mall.tmr_scale = tmr_scale;
cmd.mall.debug_bits = dc->debug.mall_error_as_fatal;
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
return true;
}
@@ -895,9 +863,7 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
cmd.mall.header.payload_bytes =
sizeof(cmd.mall) - sizeof(cmd.mall.header);
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c
index 3216d10c58ba..3d19acaa12f3 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c
@@ -106,7 +106,7 @@ static const struct hw_sequencer_funcs dcn30_funcs = {
.disable_link_output = dce110_disable_link_output,
.set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
.get_dcc_en_bits = dcn10_get_dcc_en_bits,
- .update_visual_confirm_color = dcn20_update_visual_confirm_color,
+ .update_visual_confirm_color = dcn10_update_visual_confirm_color,
.is_abm_supported = dcn21_is_abm_supported
};
@@ -151,8 +151,4 @@ void dcn30_hw_sequencer_construct(struct dc *dc)
dc->hwss = dcn30_funcs;
dc->hwseq->funcs = dcn30_private_funcs;
- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- dc->hwss.init_hw = dcn20_fpga_init_hw;
- dc->hwseq->funcs.init_pipes = NULL;
- }
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
index c95f000b63b2..dfb8f62765f2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
@@ -55,10 +55,9 @@ void optc3_triplebuffer_lock(struct timing_generator *optc)
REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
OTG_MASTER_UPDATE_LOCK, 1);
- if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
- REG_WAIT(OTG_MASTER_UPDATE_LOCK,
- UPDATE_LOCK_STATUS, 1,
- 1, 10);
+ REG_WAIT(OTG_MASTER_UPDATE_LOCK,
+ UPDATE_LOCK_STATUS, 1,
+ 1, 10);
TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
}
@@ -280,6 +279,9 @@ static void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, in
* Sets double buffer point for V_TOTAL, H_TOTAL, VTOTAL_MIN,
* VTOTAL_MAX, VTOTAL_MIN_SEL and VTOTAL_MAX_SEL registers.
*
+ * @optc: timing_generator instance.
+ * @enable: Enable DRR double buffering control if true, disable otherwise.
+ *
* Options: any time, start of frame, dp start of frame (range timing)
*/
static void optc3_set_timing_double_buffer(struct timing_generator *optc, bool enable)
@@ -301,7 +303,12 @@ static void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *o
void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max)
{
- optc1_set_vtotal_min_max(optc, vtotal_min, vtotal_max);
+ struct dc *dc = optc->ctx->dc;
+
+ if (dc->caps.dmub_caps.mclk_sw && !dc->debug.disable_fams)
+ dc_dmub_srv_drr_update_cmd(dc, optc->inst, vtotal_min, vtotal_max);
+ else
+ optc1_set_vtotal_min_max(optc, vtotal_min, vtotal_max);
}
void optc3_tg_init(struct timing_generator *optc)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
index 67a34cda3774..1a0284a068b2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
@@ -728,24 +728,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.exit_idle_opt_for_cursor_updates = true
};
-static const struct dc_debug_options debug_defaults_diags = {
- .disable_dmcu = true, //No dmcu on DCN30
- .force_abm_enable = false,
- .timing_trace = true,
- .clock_trace = true,
- .disable_dpp_power_gate = true,
- .disable_hubp_power_gate = true,
- .disable_clock_gate = true,
- .disable_pplib_clock_request = true,
- .disable_pplib_wm_range = true,
- .disable_stutter = false,
- .scl_reset_length10 = true,
- .dwb_fi_phase = -1, // -1 = disable
- .dmub_command_table = true,
- .enable_tri_buf = true,
- .use_max_lb = true
-};
-
static const struct dc_panel_config panel_config_defaults = {
.psr = {
.disable_psr = false,
@@ -1076,13 +1058,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn30_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hwseq = dcn30_hwseq_create,
-};
-
static void dcn30_resource_destruct(struct dcn30_resource_pool *pool)
{
unsigned int i;
@@ -2353,6 +2328,7 @@ static bool dcn30_resource_construct(
dc->caps.color.mpc.ocsc = 1;
dc->caps.dp_hdmi21_pcon_support = true;
+ dc->caps.max_v_total = (1 << 15) - 1;
/* read VBIOS LTTPR caps */
{
@@ -2376,10 +2352,7 @@ static bool dcn30_resource_construct(
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
- else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
- dc->debug = debug_defaults_diags;
- } else
- dc->debug = debug_defaults_diags;
+
// Init the vm_helper
if (dc->vm_helper)
vm_helper_init(dc->vm_helper, 16);
@@ -2577,8 +2550,7 @@ static bool dcn30_resource_construct(
/* Audio, Stream Encoders including DIG and virtual, MPC 3D LUTs */
if (!resource_construct(num_virtual_links, dc, &pool->base,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
+ &res_create_funcs))
goto create_fail;
/* HW Sequencer and Plane caps */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c
index 6192851c59ed..257df8660b4c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c
@@ -107,7 +107,7 @@ static const struct hw_sequencer_funcs dcn301_funcs = {
.get_dcc_en_bits = dcn10_get_dcc_en_bits,
.optimize_pwr_state = dcn21_optimize_pwr_state,
.exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state,
- .update_visual_confirm_color = dcn20_update_visual_confirm_color,
+ .update_visual_confirm_color = dcn10_update_visual_confirm_color,
};
static const struct hwseq_private_funcs dcn301_private_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
index 5ac2a272c380..3485fbb1093e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
@@ -702,23 +702,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.exit_idle_opt_for_cursor_updates = true
};
-static const struct dc_debug_options debug_defaults_diags = {
- .disable_dmcu = true,
- .force_abm_enable = false,
- .timing_trace = true,
- .clock_trace = true,
- .disable_dpp_power_gate = false,
- .disable_hubp_power_gate = false,
- .disable_clock_gate = true,
- .disable_pplib_clock_request = true,
- .disable_pplib_wm_range = true,
- .disable_stutter = true,
- .scl_reset_length10 = true,
- .dwb_fi_phase = -1, // -1 = disable
- .dmub_command_table = true,
- .use_max_lb = false,
-};
-
static void dcn301_dpp_destroy(struct dpp **dpp)
{
kfree(TO_DCN20_DPP(*dpp));
@@ -1047,13 +1030,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn301_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hwseq = dcn301_hwseq_create,
-};
-
static void dcn301_destruct(struct dcn301_resource_pool *pool)
{
unsigned int i;
@@ -1513,10 +1489,7 @@ static bool dcn301_resource_construct(
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
- else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
- dc->debug = debug_defaults_diags;
- } else
- dc->debug = debug_defaults_diags;
+
// Init the vm_helper
if (dc->vm_helper)
vm_helper_init(dc->vm_helper, 16);
@@ -1710,9 +1683,8 @@ static bool dcn301_resource_construct(
/* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */
if (!resource_construct(num_virtual_links, dc, &pool->base,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
- goto create_fail;
+ &res_create_funcs))
+ goto create_fail;
/* HW Sequencer and Plane caps */
dcn301_hw_sequencer_construct(dc);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
index 9f93c43115ba..7dc065ea247a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
@@ -98,24 +98,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.exit_idle_opt_for_cursor_updates = true
};
-static const struct dc_debug_options debug_defaults_diags = {
- .disable_dmcu = true,
- .force_abm_enable = false,
- .timing_trace = true,
- .clock_trace = true,
- .disable_dpp_power_gate = true,
- .disable_hubp_power_gate = true,
- .disable_clock_gate = true,
- .disable_pplib_clock_request = true,
- .disable_pplib_wm_range = true,
- .disable_stutter = false,
- .scl_reset_length10 = true,
- .dwb_fi_phase = -1, // -1 = disable
- .dmub_command_table = true,
- .enable_tri_buf = true,
- .use_max_lb = true
-};
-
static const struct dc_panel_config panel_config_defaults = {
.psr = {
.disable_psr = false,
@@ -954,13 +936,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn302_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hwseq = dcn302_hwseq_create,
-};
-
static bool is_soc_bounding_box_valid(struct dc *dc)
{
uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev;
@@ -1252,6 +1227,7 @@ static bool dcn302_resource_construct(
dc->caps.force_dp_tps4_for_cp2520 = true;
dc->caps.extended_aux_timeout_support = true;
dc->caps.dmcub_support = true;
+ dc->caps.max_v_total = (1 << 15) - 1;
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
@@ -1309,8 +1285,6 @@ static bool dcn302_resource_construct(
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
- else
- dc->debug = debug_defaults_diags;
// Init the vm_helper
if (dc->vm_helper)
@@ -1489,8 +1463,7 @@ static bool dcn302_resource_construct(
/* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */
if (!resource_construct(num_virtual_links, dc, pool,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
+ &res_create_funcs))
goto create_fail;
/* HW Sequencer and Plane caps */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
index 7f72ef882ca4..6d9761395288 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
@@ -81,23 +81,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.disable_idle_power_optimizations = false,
};
-static const struct dc_debug_options debug_defaults_diags = {
- .disable_dmcu = true,
- .force_abm_enable = false,
- .timing_trace = true,
- .clock_trace = true,
- .disable_dpp_power_gate = true,
- .disable_hubp_power_gate = true,
- .disable_clock_gate = true,
- .disable_pplib_clock_request = true,
- .disable_pplib_wm_range = true,
- .disable_stutter = false,
- .scl_reset_length10 = true,
- .dwb_fi_phase = -1, // -1 = disable
- .dmub_command_table = true,
- .enable_tri_buf = true,
-};
-
static const struct dc_panel_config panel_config_defaults = {
.psr = {
.disable_psr = false,
@@ -881,13 +864,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn303_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hwseq = dcn303_hwseq_create,
-};
-
static bool is_soc_bounding_box_valid(struct dc *dc)
{
uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev;
@@ -1176,6 +1152,7 @@ static bool dcn303_resource_construct(
dc->caps.force_dp_tps4_for_cp2520 = true;
dc->caps.extended_aux_timeout_support = true;
dc->caps.dmcub_support = true;
+ dc->caps.max_v_total = (1 << 15) - 1;
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
@@ -1232,8 +1209,6 @@ static bool dcn303_resource_construct(
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
- else
- dc->debug = debug_defaults_diags;
// Init the vm_helper
if (dc->vm_helper)
@@ -1400,8 +1375,7 @@ static bool dcn303_resource_construct(
/* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */
if (!resource_construct(num_virtual_links, dc, pool,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
+ &res_create_funcs))
goto create_fail;
/* HW Sequencer and Plane caps */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c
index 4c2fdfea162f..65c1d754e2d6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c
@@ -47,6 +47,14 @@ void dccg31_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+ if (dccg->dpp_clock_gated[dpp_inst]) {
+ /*
+ * Do not update the DPPCLK DTO if the clock is stopped.
+ * It is treated the same as if the pipe itself were in PG.
+ */
+ return;
+ }
+
if (dccg->ref_dppclk && req_dppclk) {
int ref_dppclk = dccg->ref_dppclk;
int modulo, phase;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c
index 745a5d187a98..bd62502380d8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c
@@ -117,7 +117,6 @@ static bool query_dp_alt_from_dmub(struct link_encoder *enc,
union dmub_rb_cmd *cmd)
{
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
- struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv;
memset(cmd, 0, sizeof(*cmd));
cmd->query_dp_alt.header.type = DMUB_CMD__VBIOS;
@@ -126,7 +125,7 @@ static bool query_dp_alt_from_dmub(struct link_encoder *enc,
cmd->query_dp_alt.header.payload_bytes = sizeof(cmd->query_dp_alt.data);
cmd->query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter);
- if (!dc_dmub_srv_cmd_with_reply_data(dc_dmub_srv, cmd))
+ if (!dm_execute_dmub_cmd(enc->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
return false;
return true;
@@ -425,7 +424,6 @@ static bool link_dpia_control(struct dc_context *dc_ctx,
struct dmub_cmd_dig_dpia_control_data *dpia_control)
{
union dmub_rb_cmd cmd;
- struct dc_dmub_srv *dmub = dc_ctx->dmub_srv;
memset(&cmd, 0, sizeof(cmd));
@@ -438,9 +436,7 @@ static bool link_dpia_control(struct dc_context *dc_ctx,
cmd.dig1_dpia_control.dpia_control = *dpia_control;
- dc_dmub_srv_cmd_queue(dmub, &cmd);
- dc_dmub_srv_cmd_execute(dmub);
- dc_dmub_srv_wait_idle(dmub);
+ dm_execute_dmub_cmd(dc_ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
index 7e7cd5b64e6a..7445ed27852a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c
@@ -103,6 +103,7 @@ static void dcn31_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigne
default:
break;
}
+ DC_LOG_DEBUG("Set DET%d to %d segments\n", hubp_inst, det_size_segments);
/* Should never be hit, if it is we have an erroneous hw config*/
ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
+ hubbub2->det3_size + hubbub2->compbuf_size_segments <= hubbub2->crb_size_segs);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
index 62ce36c75c4d..2a7f47642a44 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
@@ -117,28 +117,6 @@ void dcn31_init_hw(struct dc *dc)
if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
-
- REG_WRITE(REFCLK_CNTL, 0);
- REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
- REG_WRITE(DIO_MEM_PWR_CTRL, 0);
-
- if (!dc->debug.disable_clock_gate) {
- /* enable all DCN clock gating */
- REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
-
- REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
-
- REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
- }
-
- //Enable ability to power gate / don't force power on permanently
- if (hws->funcs.enable_power_gating_plane)
- hws->funcs.enable_power_gating_plane(hws, true);
-
- return;
- }
-
if (!dcb->funcs->is_accelerated_mode(dcb)) {
hws->funcs.bios_golden_init(dc);
if (hws->funcs.disable_vga)
@@ -154,23 +132,21 @@ void dcn31_init_hw(struct dc *dc)
res_pool->ref_clocks.xtalin_clock_inKhz =
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- if (res_pool->dccg && res_pool->hubbub) {
-
- (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
- dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
- &res_pool->ref_clocks.dccg_ref_clock_inKhz);
-
- (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
- res_pool->ref_clocks.dccg_ref_clock_inKhz,
- &res_pool->ref_clocks.dchub_ref_clock_inKhz);
- } else {
- // Not all ASICs have DCCG sw component
- res_pool->ref_clocks.dccg_ref_clock_inKhz =
- res_pool->ref_clocks.xtalin_clock_inKhz;
- res_pool->ref_clocks.dchub_ref_clock_inKhz =
- res_pool->ref_clocks.xtalin_clock_inKhz;
- }
+ if (res_pool->dccg && res_pool->hubbub) {
+
+ (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
+ dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
+ &res_pool->ref_clocks.dccg_ref_clock_inKhz);
+
+ (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
+ res_pool->ref_clocks.dccg_ref_clock_inKhz,
+ &res_pool->ref_clocks.dchub_ref_clock_inKhz);
+ } else {
+ // Not all ASICs have DCCG sw component
+ res_pool->ref_clocks.dccg_ref_clock_inKhz =
+ res_pool->ref_clocks.xtalin_clock_inKhz;
+ res_pool->ref_clocks.dchub_ref_clock_inKhz =
+ res_pool->ref_clocks.xtalin_clock_inKhz;
}
} else
ASSERT_CRITICAL(false);
@@ -197,10 +173,6 @@ void dcn31_init_hw(struct dc *dc)
}
}
- /* Enables outbox notifications for usb4 dpia */
- if (dc->res_pool->usb4_dpia_count)
- dmub_enable_outbox_notification(dc->ctx->dmub_srv);
-
/* we want to turn off all dp displays before doing detection */
dc->link_srv->blank_all_dp_displays(dc);
@@ -297,8 +269,9 @@ void dcn31_init_hw(struct dc *dc)
#endif
// Get DMCUB capabilities
- dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv->dmub);
+ dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv);
dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
+ dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch;
}
void dcn31_dsc_pg_control(
@@ -442,9 +415,7 @@ void dcn31_z10_save_init(struct dc *dc)
cmd.dcn_restore.header.type = DMUB_CMD__IDLE_OPT;
cmd.dcn_restore.header.sub_type = DMUB_CMD__IDLE_OPT_DCN_SAVE_INIT;
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
void dcn31_z10_restore(const struct dc *dc)
@@ -462,9 +433,7 @@ void dcn31_z10_restore(const struct dc *dc)
cmd.dcn_restore.header.type = DMUB_CMD__IDLE_OPT;
cmd.dcn_restore.header.sub_type = DMUB_CMD__IDLE_OPT_DCN_RESTORE;
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
@@ -560,35 +529,31 @@ static void dcn31_reset_back_end_for_pipe(
pipe_ctx->stream_res.tg->funcs->set_drr(
pipe_ctx->stream_res.tg, NULL);
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- link = pipe_ctx->stream->link;
- /* DPMS may already disable or */
- /* dpms_off status is incorrect due to fastboot
- * feature. When system resume from S4 with second
- * screen only, the dpms_off would be true but
- * VBIOS lit up eDP, so check link status too.
- */
- if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
- dc->link_srv->set_dpms_off(pipe_ctx);
- else if (pipe_ctx->stream_res.audio)
- dc->hwss.disable_audio_stream(pipe_ctx);
-
- /* free acquired resources */
- if (pipe_ctx->stream_res.audio) {
- /*disable az_endpoint*/
- pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
-
- /*free audio*/
- if (dc->caps.dynamic_audio == true) {
- /*we have to dynamic arbitrate the audio endpoints*/
- /*we free the resource, need reset is_audio_acquired*/
- update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
- pipe_ctx->stream_res.audio, false);
- pipe_ctx->stream_res.audio = NULL;
- }
+ link = pipe_ctx->stream->link;
+ /* DPMS may already disable or */
+ /* dpms_off status is incorrect due to fastboot
+ * feature. When system resume from S4 with second
+ * screen only, the dpms_off would be true but
+ * VBIOS lit up eDP, so check link status too.
+ */
+ if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
+ dc->link_srv->set_dpms_off(pipe_ctx);
+ else if (pipe_ctx->stream_res.audio)
+ dc->hwss.disable_audio_stream(pipe_ctx);
+
+ /* free acquired resources */
+ if (pipe_ctx->stream_res.audio) {
+ /*disable az_endpoint*/
+ pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
+
+ /*free audio*/
+ if (dc->caps.dynamic_audio == true) {
+ /*we have to dynamic arbitrate the audio endpoints*/
+ /*we free the resource, need reset is_audio_acquired*/
+ update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
+ pipe_ctx->stream_res.audio, false);
+ pipe_ctx->stream_res.audio = NULL;
}
- } else if (pipe_ctx->stream_res.dsc) {
- dc->link_srv->set_dsc_enable(pipe_ctx, false);
}
pipe_ctx->stream = NULL;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
index 3a32810bbe38..fc25cc300a17 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
@@ -58,6 +58,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = {
.enable_audio_stream = dce110_enable_audio_stream,
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane,
+ .disable_pixel_data = dcn20_disable_pixel_data,
.pipe_control_lock = dcn20_pipe_control_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.cursor_lock = dcn10_cursor_lock,
@@ -109,7 +110,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = {
.set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
.optimize_pwr_state = dcn21_optimize_pwr_state,
.exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state,
- .update_visual_confirm_color = dcn20_update_visual_confirm_color,
+ .update_visual_confirm_color = dcn10_update_visual_confirm_color,
};
static const struct hwseq_private_funcs dcn31_private_funcs = {
@@ -153,8 +154,4 @@ void dcn31_hw_sequencer_construct(struct dc *dc)
dc->hwss = dcn31_funcs;
dc->hwseq->funcs = dcn31_private_funcs;
- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- dc->hwss.init_hw = dcn20_fpga_init_hw;
- dc->hwseq->funcs.init_pipes = NULL;
- }
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c
index 11ea9d13e312..217acd4e292a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c
@@ -52,7 +52,7 @@ static bool dcn31_query_backlight_info(struct panel_cntl *panel_cntl, union dmub
cmd->panel_cntl.header.payload_bytes = sizeof(cmd->panel_cntl.data);
cmd->panel_cntl.data.inst = dcn31_panel_cntl->base.inst;
- return dc_dmub_srv_cmd_with_reply_data(dc_dmub_srv, cmd);
+ return dm_execute_dmub_cmd(dc_dmub_srv->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY);
}
static uint32_t dcn31_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_cntl)
@@ -85,7 +85,7 @@ static uint32_t dcn31_panel_cntl_hw_init(struct panel_cntl *panel_cntl)
panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV;
cmd.panel_cntl.data.bl_pwm_ref_div2 =
panel_cntl->stored_backlight_registers.PANEL_PWRSEQ_REF_DIV2;
- if (!dc_dmub_srv_cmd_with_reply_data(dc_dmub_srv, &cmd))
+ if (!dm_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
return 0;
panel_cntl->stored_backlight_registers.BL_PWM_CNTL = cmd.panel_cntl.data.bl_pwm_cntl;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
index ff8cd5076434..fc33b5fcabe1 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
@@ -887,28 +887,11 @@ static const struct dc_debug_options debug_defaults_drv = {
}
},
.disable_z10 = true,
+ .enable_legacy_fast_update = true,
.enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/
.dml_hostvm_override = DML_HOSTVM_OVERRIDE_FALSE,
};
-static const struct dc_debug_options debug_defaults_diags = {
- .disable_dmcu = true,
- .force_abm_enable = false,
- .timing_trace = true,
- .clock_trace = true,
- .disable_dpp_power_gate = true,
- .disable_hubp_power_gate = true,
- .disable_clock_gate = true,
- .disable_pplib_clock_request = true,
- .disable_pplib_wm_range = true,
- .disable_stutter = false,
- .scl_reset_length10 = true,
- .dwb_fi_phase = -1, // -1 = disable
- .dmub_command_table = true,
- .enable_tri_buf = true,
- .use_max_lb = true
-};
-
static const struct dc_panel_config panel_config_defaults = {
.psr = {
.disable_psr = false,
@@ -1341,13 +1324,6 @@ static struct dce_hwseq *dcn31_hwseq_create(
hws->regs = &hwseq_reg;
hws->shifts = &hwseq_shift;
hws->masks = &hwseq_mask;
- /* DCN3.1 FPGA Workaround
- * Need to enable HPO DP Stream Encoder before setting OTG master enable.
- * To do so, move calling function enable_stream_timing to only be done AFTER calling
- * function core_link_enable_stream
- */
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
- hws->wa.dp_hpo_and_otg_sequence = true;
}
return hws;
}
@@ -1360,15 +1336,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn31_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create,
- .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create,
- .create_hwseq = dcn31_hwseq_create,
-};
-
static void dcn31_resource_destruct(struct dcn31_resource_pool *pool)
{
unsigned int i;
@@ -1988,10 +1955,7 @@ static bool dcn31_resource_construct(
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
- else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
- dc->debug = debug_defaults_diags;
- } else
- dc->debug = debug_defaults_diags;
+
// Init the vm_helper
if (dc->vm_helper)
vm_helper_init(dc->vm_helper, 16);
@@ -2195,9 +2159,8 @@ static bool dcn31_resource_construct(
/* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */
if (!resource_construct(num_virtual_links, dc, &pool->base,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
- goto create_fail;
+ &res_create_funcs))
+ goto create_fail;
/* HW Sequencer and Plane caps */
dcn31_hw_sequencer_construct(dc);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
index de7bfba2c179..cf23d7bc560a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
@@ -45,6 +45,16 @@
#define DC_LOGGER \
dccg->ctx->logger
+static void dccg314_trigger_dio_fifo_resync(
+ struct dccg *dccg)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+ uint32_t dispclk_rdivider_value = 0;
+
+ REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, &dispclk_rdivider_value);
+ REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value);
+}
+
static void dccg314_get_pixel_rate_div(
struct dccg *dccg,
uint32_t otg_inst,
@@ -322,6 +332,9 @@ static void dccg314_dpp_root_clock_control(
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+ if (dccg->dpp_clock_gated[dpp_inst] == clock_on)
+ return;
+
if (clock_on) {
/* turn off the DTO and leave phase/modulo at max */
REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_ENABLE[dpp_inst], 0);
@@ -335,6 +348,8 @@ static void dccg314_dpp_root_clock_control(
DPPCLK0_DTO_PHASE, 0,
DPPCLK0_DTO_MODULO, 1);
}
+
+ dccg->dpp_clock_gated[dpp_inst] = !clock_on;
}
static const struct dccg_funcs dccg314_funcs = {
@@ -357,6 +372,7 @@ static const struct dccg_funcs dccg314_funcs = {
.disable_dsc = dccg31_disable_dscclk,
.enable_dsc = dccg31_enable_dscclk,
.set_pixel_rate_div = dccg314_set_pixel_rate_div,
+ .trigger_dio_fifo_resync = dccg314_trigger_dio_fifo_resync,
.set_valid_pixel_rate = dccg314_set_valid_pixel_rate,
};
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h
index 90687a9e8fdd..8e07d3151f91 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h
@@ -192,7 +192,10 @@
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_GATE_DISABLE, mask_sh),\
- DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_GATE_DISABLE, mask_sh)
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_GATE_DISABLE, mask_sh),\
+ DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_MODULO, mask_sh),\
+ DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, mask_sh),\
+ DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh)
struct dccg *dccg314_create(
struct dc_context *ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
index cc3fe9cac5b5..7a43f8868500 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
@@ -337,14 +337,13 @@ void dcn314_enable_power_gating_plane(struct dce_hwseq *hws, bool enable)
REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
}
-unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div)
+void dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div)
{
struct dc_stream_state *stream = pipe_ctx->stream;
- unsigned int odm_combine_factor = 0;
bool two_pix_per_container = false;
two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing);
- odm_combine_factor = get_odm_config(pipe_ctx, NULL);
+ get_odm_config(pipe_ctx, NULL);
if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) {
*k1_div = PIXEL_RATE_DIV_BY_1;
@@ -362,15 +361,11 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig
} else {
*k1_div = PIXEL_RATE_DIV_BY_1;
*k2_div = PIXEL_RATE_DIV_BY_4;
- if (odm_combine_factor == 2)
- *k2_div = PIXEL_RATE_DIV_BY_2;
}
}
if ((*k1_div == PIXEL_RATE_DIV_NA) && (*k2_div == PIXEL_RATE_DIV_NA))
ASSERT(false);
-
- return odm_combine_factor;
}
void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
@@ -390,6 +385,35 @@ void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
pix_per_cycle);
}
+void dcn314_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context)
+{
+ unsigned int i;
+ struct pipe_ctx *pipe = NULL;
+ bool otg_disabled[MAX_PIPES] = {false};
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (pipe->top_pipe || pipe->prev_odm_pipe)
+ continue;
+
+ if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal))) {
+ pipe->stream_res.tg->funcs->disable_crtc(pipe->stream_res.tg);
+ reset_sync_context_for_pipe(dc, context, i);
+ otg_disabled[i] = true;
+ }
+ }
+
+ hws->ctx->dc->res_pool->dccg->funcs->trigger_dio_fifo_resync(hws->ctx->dc->res_pool->dccg);
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (otg_disabled[i])
+ pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
+ }
+}
+
void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on)
{
if (!hws->ctx->dc->debug.root_clock_optimization.bits.dpp)
@@ -417,9 +441,7 @@ void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool
cmd.domain_control.data.inst = hubp_inst;
cmd.domain_control.data.power_gate = !power_on;
- dc_dmub_srv_cmd_queue(ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(ctx->dmub_srv);
- dc_dmub_srv_wait_idle(ctx->dmub_srv);
+ dm_execute_dmub_cmd(ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
PERF_TRACE();
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h
index 6d0b62503caa..96035c75e0df 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h
@@ -37,10 +37,12 @@ void dcn314_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool po
void dcn314_enable_power_gating_plane(struct dce_hwseq *hws, bool enable);
-unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div);
+void dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div);
void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx);
+void dcn314_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context);
+
void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on);
void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
index a588f46b166f..86d6a514dec0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
@@ -60,6 +60,7 @@ static const struct hw_sequencer_funcs dcn314_funcs = {
.enable_audio_stream = dce110_enable_audio_stream,
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane,
+ .disable_pixel_data = dcn20_disable_pixel_data,
.pipe_control_lock = dcn20_pipe_control_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.cursor_lock = dcn10_cursor_lock,
@@ -111,7 +112,7 @@ static const struct hw_sequencer_funcs dcn314_funcs = {
.set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
.optimize_pwr_state = dcn21_optimize_pwr_state,
.exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state,
- .update_visual_confirm_color = dcn20_update_visual_confirm_color,
+ .update_visual_confirm_color = dcn10_update_visual_confirm_color,
};
static const struct hwseq_private_funcs dcn314_private_funcs = {
@@ -151,6 +152,7 @@ static const struct hwseq_private_funcs dcn314_private_funcs = {
.setup_hpo_hw_control = dcn31_setup_hpo_hw_control,
.calculate_dccg_k1_k2_values = dcn314_calculate_dccg_k1_k2_values,
.set_pixels_per_cycle = dcn314_set_pixels_per_cycle,
+ .resync_fifo_dccg_dio = dcn314_resync_fifo_dccg_dio,
};
void dcn314_hw_sequencer_construct(struct dc *dc)
@@ -158,8 +160,4 @@ void dcn314_hw_sequencer_construct(struct dc *dc)
dc->hwss = dcn314_funcs;
dc->hwseq->funcs = dcn314_private_funcs;
- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- dc->hwss.init_hw = dcn20_fpga_init_hw;
- dc->hwseq->funcs.init_pipes = NULL;
- }
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
index abeeede38fb3..a840b008d660 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
@@ -117,23 +117,6 @@
#define regBIF_BX2_BIOS_SCRATCH_6 0x003e
#define regBIF_BX2_BIOS_SCRATCH_6_BASE_IDX 1
-struct IP_BASE_INSTANCE {
- unsigned int segment[MAX_SEGMENT];
-};
-
-struct IP_BASE {
- struct IP_BASE_INSTANCE instance[MAX_INSTANCE];
-};
-
-static const struct IP_BASE DCN_BASE = { { { { 0x00000012, 0x000000C0, 0x000034C0, 0x00009000, 0x02403C00, 0, 0, 0 } },
- { { 0, 0, 0, 0, 0, 0, 0, 0 } },
- { { 0, 0, 0, 0, 0, 0, 0, 0 } },
- { { 0, 0, 0, 0, 0, 0, 0, 0 } },
- { { 0, 0, 0, 0, 0, 0, 0, 0 } },
- { { 0, 0, 0, 0, 0, 0, 0, 0 } },
- { { 0, 0, 0, 0, 0, 0, 0, 0 } } } };
-
-
#define DC_LOGGER_INIT(logger)
enum dcn31_clk_src_array_id {
@@ -891,8 +874,8 @@ static const struct dc_debug_options debug_defaults_drv = {
.force_abm_enable = false,
.timing_trace = false,
.clock_trace = true,
- .disable_dpp_power_gate = true,
- .disable_hubp_power_gate = true,
+ .disable_dpp_power_gate = false,
+ .disable_hubp_power_gate = false,
.disable_pplib_clock_request = false,
.pipe_split_policy = MPC_SPLIT_DYNAMIC,
.force_single_disp_pipe_split = false,
@@ -921,6 +904,22 @@ static const struct dc_debug_options debug_defaults_drv = {
.afmt = true,
}
},
+
+ .root_clock_optimization = {
+ .bits = {
+ .dpp = true,
+ .dsc = false,
+ .hdmistream = false,
+ .hdmichar = false,
+ .dpstream = false,
+ .symclk32_se = false,
+ .symclk32_le = false,
+ .symclk_fe = false,
+ .physymclk = false,
+ .dpiasymclk = false,
+ }
+ },
+
.seamless_boot_odm_combine = true
};
@@ -1375,13 +1374,6 @@ static struct dce_hwseq *dcn314_hwseq_create(
hws->regs = &hwseq_reg;
hws->shifts = &hwseq_shift;
hws->masks = &hwseq_mask;
- /* DCN3.1 FPGA Workaround
- * Need to enable HPO DP Stream Encoder before setting OTG master enable.
- * To do so, move calling function enable_stream_timing to only be done AFTER calling
- * function core_link_enable_stream
- */
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
- hws->wa.dp_hpo_and_otg_sequence = true;
}
return hws;
}
@@ -1394,15 +1386,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn314_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create,
- .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create,
- .create_hwseq = dcn314_hwseq_create,
-};
-
static void dcn314_resource_destruct(struct dcn314_resource_pool *pool)
{
unsigned int i;
@@ -1900,6 +1883,13 @@ static bool dcn314_resource_construct(
/* Use pipe context based otg sync logic */
dc->config.use_pipe_ctx_sync_logic = true;
+ /* Disable pipe power gating when unsupported */
+ if (ctx->asic_id.hw_internal_rev == 0x01 ||
+ ctx->asic_id.hw_internal_rev == 0x80) {
+ dc->debug.disable_dpp_power_gate = true;
+ dc->debug.disable_hubp_power_gate = true;
+ }
+
/* read VBIOS LTTPR caps */
{
if (ctx->dc_bios->funcs->get_lttpr_caps) {
@@ -2101,8 +2091,7 @@ static bool dcn314_resource_construct(
/* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */
if (!resource_construct(num_virtual_links, dc, &pool->base,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
+ &res_create_funcs))
goto create_fail;
/* HW Sequencer and Plane caps */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
index 41c972c8eb19..f1153941907e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
@@ -136,6 +136,9 @@
#define DCN3_15_MAX_DET_SIZE 384
#define DCN3_15_CRB_SEGMENT_SIZE_KB 64
+#define DCN3_15_MAX_DET_SEGS (DCN3_15_MAX_DET_SIZE / DCN3_15_CRB_SEGMENT_SIZE_KB)
+/* Minimum 2 extra segments need to be in compbuf and claimable to guarantee seamless mpo transitions */
+#define MIN_RESERVED_DET_SEGS 2
enum dcn31_clk_src_array_id {
DCN31_CLK_SRC_PLL0,
@@ -884,27 +887,10 @@ static const struct dc_debug_options debug_defaults_drv = {
.afmt = true,
}
},
+ .enable_legacy_fast_update = true,
.psr_power_use_phy_fsm = 0,
};
-static const struct dc_debug_options debug_defaults_diags = {
- .disable_dmcu = true,
- .force_abm_enable = false,
- .timing_trace = true,
- .clock_trace = true,
- .disable_dpp_power_gate = true,
- .disable_hubp_power_gate = true,
- .disable_clock_gate = true,
- .disable_pplib_clock_request = true,
- .disable_pplib_wm_range = true,
- .disable_stutter = false,
- .scl_reset_length10 = true,
- .dwb_fi_phase = -1, // -1 = disable
- .dmub_command_table = true,
- .enable_tri_buf = true,
- .use_max_lb = true
-};
-
static const struct dc_panel_config panel_config_defaults = {
.psr = {
.disable_psr = false,
@@ -1339,13 +1325,6 @@ static struct dce_hwseq *dcn31_hwseq_create(
hws->regs = &hwseq_reg;
hws->shifts = &hwseq_shift;
hws->masks = &hwseq_mask;
- /* DCN3.1 FPGA Workaround
- * Need to enable HPO DP Stream Encoder before setting OTG master enable.
- * To do so, move calling function enable_stream_timing to only be done AFTER calling
- * function core_link_enable_stream
- */
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
- hws->wa.dp_hpo_and_otg_sequence = true;
}
return hws;
}
@@ -1358,15 +1337,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn31_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create,
- .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create,
- .create_hwseq = dcn31_hwseq_create,
-};
-
static void dcn315_resource_destruct(struct dcn315_resource_pool *pool)
{
unsigned int i;
@@ -1636,21 +1606,69 @@ static bool is_dual_plane(enum surface_pixel_format format)
return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA;
}
+static int source_format_to_bpp (enum source_format_class SourcePixelFormat)
+{
+ if (SourcePixelFormat == dm_444_64)
+ return 8;
+ else if (SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16)
+ return 2;
+ else if (SourcePixelFormat == dm_444_8)
+ return 1;
+ else if (SourcePixelFormat == dm_rgbe_alpha)
+ return 5;
+ else if (SourcePixelFormat == dm_420_8)
+ return 3;
+ else if (SourcePixelFormat == dm_420_12)
+ return 6;
+ else
+ return 4;
+}
+
+static bool allow_pixel_rate_crb(struct dc *dc, struct dc_state *context)
+{
+ int i;
+ struct resource_context *res_ctx = &context->res_ctx;
+
+ /*Don't apply for single stream*/
+ if (context->stream_count < 2)
+ return false;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (!res_ctx->pipe_ctx[i].stream)
+ continue;
+
+ /*Don't apply if scaling*/
+ if (res_ctx->pipe_ctx[i].stream->src.width != res_ctx->pipe_ctx[i].stream->dst.width ||
+ res_ctx->pipe_ctx[i].stream->src.height != res_ctx->pipe_ctx[i].stream->dst.height ||
+ (res_ctx->pipe_ctx[i].plane_state && (res_ctx->pipe_ctx[i].plane_state->src_rect.width
+ != res_ctx->pipe_ctx[i].plane_state->dst_rect.width ||
+ res_ctx->pipe_ctx[i].plane_state->src_rect.height
+ != res_ctx->pipe_ctx[i].plane_state->dst_rect.height)))
+ return false;
+ /*Don't apply if MPO to avoid transition issues*/
+ if (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state != res_ctx->pipe_ctx[i].plane_state)
+ return false;
+ }
+ return true;
+}
+
static int dcn315_populate_dml_pipes_from_context(
struct dc *dc, struct dc_state *context,
display_e2e_pipe_params_st *pipes,
bool fast_validate)
{
- int i, pipe_cnt;
+ int i, pipe_cnt, crb_idx, crb_pipes;
struct resource_context *res_ctx = &context->res_ctx;
struct pipe_ctx *pipe;
const int max_usable_det = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - DCN3_15_MIN_COMPBUF_SIZE_KB;
+ int remaining_det_segs = max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB;
+ bool pixel_rate_crb = allow_pixel_rate_crb(dc, context);
DC_FP_START();
dcn31x_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
DC_FP_END();
- for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
+ for (i = 0, pipe_cnt = 0, crb_pipes = 0; i < dc->res_pool->pipe_count; i++) {
struct dc_crtc_timing *timing;
if (!res_ctx->pipe_ctx[i].stream)
@@ -1671,6 +1689,28 @@ static int dcn315_populate_dml_pipes_from_context(
pipes[pipe_cnt].dout.dsc_input_bpc = 0;
DC_FP_START();
dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt);
+ if (pixel_rate_crb && !pipe->top_pipe && !pipe->prev_odm_pipe) {
+ int bpp = source_format_to_bpp(pipes[pipe_cnt].pipe.src.source_format);
+ /* Ceil to crb segment size */
+ int approx_det_segs_required_for_pstate = dcn_get_approx_det_segs_required_for_pstate(
+ &context->bw_ctx.dml.soc, timing->pix_clk_100hz, bpp, DCN3_15_CRB_SEGMENT_SIZE_KB);
+
+ if (approx_det_segs_required_for_pstate <= 2 * DCN3_15_MAX_DET_SEGS) {
+ bool split_required = approx_det_segs_required_for_pstate > DCN3_15_MAX_DET_SEGS;
+ split_required = split_required || timing->pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc);
+ split_required = split_required || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120);
+
+ /* Minimum 2 segments to allow mpc/odm combine if its used later */
+ if (approx_det_segs_required_for_pstate < 2)
+ approx_det_segs_required_for_pstate = 2;
+ if (split_required)
+ approx_det_segs_required_for_pstate += approx_det_segs_required_for_pstate % 2;
+ pipes[pipe_cnt].pipe.src.det_size_override = approx_det_segs_required_for_pstate;
+ remaining_det_segs -= approx_det_segs_required_for_pstate;
+ } else
+ remaining_det_segs = -1;
+ crb_pipes++;
+ }
DC_FP_END();
if (pipes[pipe_cnt].dout.dsc_enable) {
@@ -1689,16 +1729,55 @@ static int dcn315_populate_dml_pipes_from_context(
break;
}
}
-
pipe_cnt++;
}
+ /* Spread remaining unreserved crb evenly among all pipes*/
+ if (pixel_rate_crb) {
+ for (i = 0, pipe_cnt = 0, crb_idx = 0; i < dc->res_pool->pipe_count; i++) {
+ pipe = &res_ctx->pipe_ctx[i];
+ if (!pipe->stream)
+ continue;
+
+ /* Do not use asymetric crb if not enough for pstate support */
+ if (remaining_det_segs < 0) {
+ pipes[pipe_cnt].pipe.src.det_size_override = 0;
+ pipe_cnt++;
+ continue;
+ }
+
+ if (!pipe->top_pipe && !pipe->prev_odm_pipe) {
+ bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc)
+ || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120);
+
+ if (remaining_det_segs > MIN_RESERVED_DET_SEGS)
+ pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes +
+ (crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0);
+ if (pipes[pipe_cnt].pipe.src.det_size_override > 2 * DCN3_15_MAX_DET_SEGS) {
+ /* Clamp to 2 pipe split max det segments */
+ remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override - 2 * (DCN3_15_MAX_DET_SEGS);
+ pipes[pipe_cnt].pipe.src.det_size_override = 2 * DCN3_15_MAX_DET_SEGS;
+ }
+ if (pipes[pipe_cnt].pipe.src.det_size_override > DCN3_15_MAX_DET_SEGS || split_required) {
+ /* If we are splitting we must have an even number of segments */
+ remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override % 2;
+ pipes[pipe_cnt].pipe.src.det_size_override -= pipes[pipe_cnt].pipe.src.det_size_override % 2;
+ }
+ /* Convert segments into size for DML use */
+ pipes[pipe_cnt].pipe.src.det_size_override *= DCN3_15_CRB_SEGMENT_SIZE_KB;
+
+ crb_idx++;
+ }
+ pipe_cnt++;
+ }
+ }
+
if (pipe_cnt)
context->bw_ctx.dml.ip.det_buffer_size_kbytes =
(max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB / pipe_cnt) * DCN3_15_CRB_SEGMENT_SIZE_KB;
if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_15_MAX_DET_SIZE)
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_15_MAX_DET_SIZE;
- ASSERT(context->bw_ctx.dml.ip.det_buffer_size_kbytes >= DCN3_15_DEFAULT_DET_SIZE);
+
dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
if (is_dual_plane(pipe->plane_state->format)
@@ -1845,10 +1924,7 @@ static bool dcn315_resource_construct(
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
- else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
- dc->debug = debug_defaults_diags;
- } else
- dc->debug = debug_defaults_diags;
+
// Init the vm_helper
if (dc->vm_helper)
vm_helper_init(dc->vm_helper, 16);
@@ -2029,9 +2105,8 @@ static bool dcn315_resource_construct(
/* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */
if (!resource_construct(num_virtual_links, dc, &pool->base,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
- goto create_fail;
+ &res_create_funcs))
+ goto create_fail;
/* HW Sequencer and Plane caps */
dcn31_hw_sequencer_construct(dc);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c
index 9ead347a33e9..707cf28bbceb 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c
@@ -884,24 +884,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.afmt = true,
}
},
-};
-
-static const struct dc_debug_options debug_defaults_diags = {
- .disable_dmcu = true,
- .force_abm_enable = false,
- .timing_trace = true,
- .clock_trace = true,
- .disable_dpp_power_gate = true,
- .disable_hubp_power_gate = true,
- .disable_clock_gate = true,
- .disable_pplib_clock_request = true,
- .disable_pplib_wm_range = true,
- .disable_stutter = false,
- .scl_reset_length10 = true,
- .dwb_fi_phase = -1, // -1 = disable
- .dmub_command_table = true,
- .enable_tri_buf = true,
- .use_max_lb = true
+ .enable_legacy_fast_update = true,
};
static const struct dc_panel_config panel_config_defaults = {
@@ -1340,13 +1323,6 @@ static struct dce_hwseq *dcn31_hwseq_create(
hws->regs = &hwseq_reg;
hws->shifts = &hwseq_shift;
hws->masks = &hwseq_mask;
- /* DCN3.1 FPGA Workaround
- * Need to enable HPO DP Stream Encoder before setting OTG master enable.
- * To do so, move calling function enable_stream_timing to only be done AFTER calling
- * function core_link_enable_stream
- */
- if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
- hws->wa.dp_hpo_and_otg_sequence = true;
}
return hws;
}
@@ -1359,15 +1335,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn31_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create,
- .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create,
- .create_hwseq = dcn31_hwseq_create,
-};
-
static void dcn316_resource_destruct(struct dcn316_resource_pool *pool)
{
unsigned int i;
@@ -1844,10 +1811,7 @@ static bool dcn316_resource_construct(
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
- else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
- dc->debug = debug_defaults_diags;
- } else
- dc->debug = debug_defaults_diags;
+
// Init the vm_helper
if (dc->vm_helper)
vm_helper_init(dc->vm_helper, 16);
@@ -2028,9 +1992,8 @@ static bool dcn316_resource_construct(
/* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */
if (!resource_construct(num_virtual_links, dc, &pool->base,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
- goto create_fail;
+ &res_create_funcs))
+ goto create_fail;
/* HW Sequencer and Plane caps */
dcn31_hw_sequencer_construct(dc);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
index ffbb739d85b6..11e28e056cf7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
@@ -42,18 +42,14 @@
#define DC_LOGGER \
dccg->ctx->logger
-/* This function is a workaround for writing to OTG_PIXEL_RATE_DIV
- * without the probability of causing a DIG FIFO error.
- */
-static void dccg32_wait_for_dentist_change_done(
+static void dccg32_trigger_dio_fifo_resync(
struct dccg *dccg)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+ uint32_t dispclk_rdivider_value = 0;
- uint32_t dentist_dispclk_value = REG_READ(DENTIST_DISPCLK_CNTL);
-
- REG_WRITE(DENTIST_DISPCLK_CNTL, dentist_dispclk_value);
- REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 2000);
+ REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, &dispclk_rdivider_value);
+ REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value);
}
static void dccg32_get_pixel_rate_div(
@@ -124,29 +120,21 @@ static void dccg32_set_pixel_rate_div(
REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
OTG0_PIXEL_RATE_DIVK1, k1,
OTG0_PIXEL_RATE_DIVK2, k2);
-
- dccg32_wait_for_dentist_change_done(dccg);
break;
case 1:
REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
OTG1_PIXEL_RATE_DIVK1, k1,
OTG1_PIXEL_RATE_DIVK2, k2);
-
- dccg32_wait_for_dentist_change_done(dccg);
break;
case 2:
REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
OTG2_PIXEL_RATE_DIVK1, k1,
OTG2_PIXEL_RATE_DIVK2, k2);
-
- dccg32_wait_for_dentist_change_done(dccg);
break;
case 3:
REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
OTG3_PIXEL_RATE_DIVK1, k1,
OTG3_PIXEL_RATE_DIVK2, k2);
-
- dccg32_wait_for_dentist_change_done(dccg);
break;
default:
BREAK_TO_DEBUGGER();
@@ -352,6 +340,7 @@ static const struct dccg_funcs dccg32_funcs = {
.otg_add_pixel = dccg32_otg_add_pixel,
.otg_drop_pixel = dccg32_otg_drop_pixel,
.set_pixel_rate_div = dccg32_set_pixel_rate_div,
+ .trigger_dio_fifo_resync = dccg32_trigger_dio_fifo_resync,
};
struct dccg *dccg32_create(
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.h
index 8071ab98d708..cf5508718122 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.h
@@ -112,8 +112,9 @@
DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_EN, mask_sh),\
DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\
DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\
- DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh)
-
+ DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh),\
+ DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, mask_sh),\
+ DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh)
struct dccg *dccg32_create(
struct dc_context *ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c
index eb08ccc38e79..a18b9c0c5709 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c
@@ -42,8 +42,8 @@
hubbub2->shifts->field_name, hubbub2->masks->field_name
/**
- * @DCN32_CRB_SEGMENT_SIZE_KB: Maximum Configurable Return Buffer size for
- * DCN32
+ * DCN32_CRB_SEGMENT_SIZE_KB: Maximum Configurable Return Buffer size for
+ * DCN32
*/
#define DCN32_CRB_SEGMENT_SIZE_KB 64
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
index 1f5ee5cde6e1..c586468872e2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
@@ -274,8 +274,7 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable)
cmd.cab.header.sub_type = DMUB_CMD__CAB_NO_DCN_REQ;
cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header);
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
return true;
}
@@ -309,8 +308,7 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable)
cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header);
cmd.cab.cab_alloc_ways = ways;
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
return true;
}
@@ -326,9 +324,7 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable)
cmd.cab.header.payload_bytes =
sizeof(cmd.cab) - sizeof(cmd.cab.header);
- dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
- dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
@@ -413,6 +409,30 @@ void dcn32_subvp_pipe_control_lock(struct dc *dc,
}
}
+void dcn32_subvp_pipe_control_lock_fast(union block_sequence_params *params)
+{
+ struct dc *dc = params->subvp_pipe_control_lock_fast_params.dc;
+ bool lock = params->subvp_pipe_control_lock_fast_params.lock;
+ struct pipe_ctx *pipe_ctx = params->subvp_pipe_control_lock_fast_params.pipe_ctx;
+ bool subvp_immediate_flip = false;
+
+ if (pipe_ctx && pipe_ctx->stream && pipe_ctx->plane_state) {
+ if (pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN &&
+ pipe_ctx->plane_state->flip_immediate)
+ subvp_immediate_flip = true;
+ }
+
+ // Don't need to lock for DRR VSYNC flips -- FW will wait for DRR pending update cleared.
+ if (subvp_immediate_flip) {
+ union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
+
+ hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
+ hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
+ hw_lock_cmd.bits.lock = lock;
+ hw_lock_cmd.bits.should_release = !lock;
+ dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
+ }
+}
bool dcn32_set_mpc_shaper_3dlut(
struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream)
@@ -587,8 +607,8 @@ void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context)
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
struct hubp *hubp = pipe->plane_res.hubp;
- if (!pipe->stream || (pipe->stream && !(pipe->stream->mall_stream_config.type == SUBVP_MAIN ||
- pipe->stream->fpo_in_use))) {
+ if (!pipe->stream || !(pipe->stream->mall_stream_config.type == SUBVP_MAIN ||
+ pipe->stream->fpo_in_use)) {
if (hubp && hubp->funcs->hubp_update_force_pstate_disallow)
hubp->funcs->hubp_update_force_pstate_disallow(hubp, false);
}
@@ -596,7 +616,7 @@ void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context)
/* Today only FPO uses cursor P-State force. Only clear cursor P-State force
* if it's not FPO.
*/
- if (!pipe->stream || (pipe->stream && !pipe->stream->fpo_in_use)) {
+ if (!pipe->stream || !pipe->stream->fpo_in_use) {
if (hubp && hubp->funcs->hubp_update_force_cursor_pstate_disallow)
hubp->funcs->hubp_update_force_cursor_pstate_disallow(hubp, false);
}
@@ -721,6 +741,9 @@ static void dcn32_initialize_min_clocks(struct dc *dc)
clocks->socclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].socclk_mhz * 1000;
clocks->dramclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].memclk_mhz * 1000;
clocks->dppclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dppclk_mhz * 1000;
+ clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000;
+ clocks->fclk_p_state_change_support = true;
+ clocks->p_state_change_support = true;
if (dc->debug.disable_boot_optimizations) {
clocks->dispclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz * 1000;
} else {
@@ -730,9 +753,6 @@ static void dcn32_initialize_min_clocks(struct dc *dc)
* freq to ensure that the timing is valid and unchanged.
*/
clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr);
- clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000;
- clocks->fclk_p_state_change_support = true;
- clocks->p_state_change_support = true;
}
dc->clk_mgr->funcs->update_clocks(
@@ -946,8 +966,10 @@ void dcn32_init_hw(struct dc *dc)
// Get DMCUB capabilities
if (dc->ctx->dmub_srv) {
- dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv->dmub);
+ dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv);
dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
+ dc->caps.dmub_caps.subvp_psr = dc->ctx->dmub_srv->dmub->feature_caps.subvp_psr_support;
+ dc->caps.dmub_caps.gecc_enable = dc->ctx->dmub_srv->dmub->feature_caps.gecc_enable;
dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch;
}
}
@@ -1119,10 +1141,9 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
}
}
-unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div)
+void dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div)
{
struct dc_stream_state *stream = pipe_ctx->stream;
- unsigned int odm_combine_factor = 0;
bool two_pix_per_container = false;
// For phantom pipes, use the same programming as the main pipes
@@ -1130,7 +1151,6 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
stream = pipe_ctx->stream->mall_stream_config.paired_stream;
}
two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing);
- odm_combine_factor = get_odm_config(pipe_ctx, NULL);
if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) {
*k1_div = PIXEL_RATE_DIV_BY_1;
@@ -1148,15 +1168,13 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
} else {
*k1_div = PIXEL_RATE_DIV_BY_1;
*k2_div = PIXEL_RATE_DIV_BY_4;
- if ((odm_combine_factor == 2) || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx))
+ if (dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx))
*k2_div = PIXEL_RATE_DIV_BY_2;
}
}
if ((*k1_div == PIXEL_RATE_DIV_NA) && (*k2_div == PIXEL_RATE_DIV_NA))
ASSERT(false);
-
- return odm_combine_factor;
}
void dcn32_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
@@ -1177,6 +1195,36 @@ void dcn32_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
pix_per_cycle);
}
+void dcn32_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context)
+{
+ unsigned int i;
+ struct pipe_ctx *pipe = NULL;
+ bool otg_disabled[MAX_PIPES] = {false};
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (pipe->top_pipe || pipe->prev_odm_pipe)
+ continue;
+
+ if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal))
+ && pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) {
+ pipe->stream_res.tg->funcs->disable_crtc(pipe->stream_res.tg);
+ reset_sync_context_for_pipe(dc, context, i);
+ otg_disabled[i] = true;
+ }
+ }
+
+ hws->ctx->dc->res_pool->dccg->funcs->trigger_dio_fifo_resync(hws->ctx->dc->res_pool->dccg);
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (otg_disabled[i])
+ pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
+ }
+}
+
void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
struct dc_link_settings *link_settings)
{
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h
index 6694c1d14aa3..bf9bffabe0c0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h
@@ -71,10 +71,12 @@ void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context);
void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx);
-unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div);
+void dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div);
void dcn32_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx);
+void dcn32_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context);
+
void dcn32_subvp_pipe_control_lock(struct dc *dc,
struct dc_state *context,
bool lock,
@@ -82,6 +84,8 @@ void dcn32_subvp_pipe_control_lock(struct dc *dc,
struct pipe_ctx *top_pipe_to_program,
bool subvp_prev_use);
+void dcn32_subvp_pipe_control_lock_fast(union block_sequence_params *params);
+
void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
struct dc_link_settings *link_settings);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
index 8085f2acb1a9..c2490e16a66a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
@@ -109,7 +109,8 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
.commit_subvp_config = dcn32_commit_subvp_config,
.enable_phantom_streams = dcn32_enable_phantom_streams,
.subvp_pipe_control_lock = dcn32_subvp_pipe_control_lock,
- .update_visual_confirm_color = dcn20_update_visual_confirm_color,
+ .update_visual_confirm_color = dcn10_update_visual_confirm_color,
+ .subvp_pipe_control_lock_fast = dcn32_subvp_pipe_control_lock_fast,
.update_phantom_vp_position = dcn32_update_phantom_vp_position,
.update_dsc_pg = dcn32_update_dsc_pg,
.apply_update_flags_for_phantom = dcn32_apply_update_flags_for_phantom,
@@ -153,6 +154,7 @@ static const struct hwseq_private_funcs dcn32_private_funcs = {
.update_mall_sel = dcn32_update_mall_sel,
.calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
.set_pixels_per_cycle = dcn32_set_pixels_per_cycle,
+ .resync_fifo_dccg_dio = dcn32_resync_fifo_dccg_dio,
.is_dp_dig_pixel_rate_div_policy = dcn32_is_dp_dig_pixel_rate_div_policy,
};
@@ -161,8 +163,4 @@ void dcn32_hw_sequencer_init_functions(struct dc *dc)
dc->hwss = dcn32_funcs;
dc->hwseq->funcs = dcn32_private_funcs;
- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- dc->hwss.init_hw = dcn20_fpga_init_hw;
- dc->hwseq->funcs.init_pipes = NULL;
- }
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
index 2ee798965bc2..8abb94f60078 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
@@ -98,7 +98,7 @@ static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, i
optc1->opp_count = opp_cnt;
}
-static void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode)
+void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode)
{
struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -106,8 +106,11 @@ static void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, b
OTG_H_TIMING_DIV_MODE_MANUAL, manual_mode ? 1 : 0);
}
/**
- * Enable CRTC
- * Enable CRTC - call ASIC Control Object to enable Timing generator.
+ * optc32_enable_crtc() - Enable CRTC - call ASIC Control Object to enable Timing generator.
+ *
+ * @optc: timing_generator instance.
+ *
+ * Return: If CRTC is enabled, return true.
*/
static bool optc32_enable_crtc(struct timing_generator *optc)
{
@@ -245,16 +248,9 @@ static void optc32_set_drr(
}
optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1);
- optc32_setup_manual_trigger(optc);
- } else {
- REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
- OTG_SET_V_TOTAL_MIN_MASK, 0,
- OTG_V_TOTAL_MIN_SEL, 0,
- OTG_V_TOTAL_MAX_SEL, 0,
- OTG_FORCE_LOCK_ON_EVENT, 0);
-
- optc->funcs->set_vtotal_min_max(optc, 0, 0);
}
+
+ optc32_setup_manual_trigger(optc);
}
static struct timing_generator_funcs dcn32_tg_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h
index b92ba8c75694..abf0121a1006 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h
@@ -179,5 +179,6 @@
SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh)
void dcn32_timing_generator_init(struct optc *optc1);
+void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode);
#endif /* __DC_OPTC_DCN32_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
index 22dd1ebea618..19f134caa8ad 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
@@ -726,28 +726,12 @@ static const struct dc_debug_options debug_defaults_drv = {
.override_dispclk_programming = true,
.disable_fpo_optimizations = false,
.fpo_vactive_margin_us = 2000, // 2000us
- .disable_fpo_vactive = true,
+ .disable_fpo_vactive = false,
.disable_boot_optimizations = false,
-};
-
-static const struct dc_debug_options debug_defaults_diags = {
- .disable_dmcu = true,
- .force_abm_enable = false,
- .timing_trace = true,
- .clock_trace = true,
- .disable_dpp_power_gate = true,
- .disable_hubp_power_gate = true,
- .disable_dsc_power_gate = true,
- .disable_clock_gate = true,
- .disable_pplib_clock_request = true,
- .disable_pplib_wm_range = true,
- .disable_stutter = false,
- .scl_reset_length10 = true,
- .dwb_fi_phase = -1, // -1 = disable
- .dmub_command_table = true,
- .enable_tri_buf = true,
- .use_max_lb = true,
- .force_disable_subvp = true
+ .disable_subvp_high_refresh = false,
+ .disable_dp_plus_plus_wa = true,
+ .fpo_vactive_min_active_margin_us = 200,
+ .fpo_vactive_max_blank_us = 1000,
};
static struct dce_aux *dcn32_aux_engine_create(
@@ -1353,15 +1337,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn32_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hpo_dp_stream_encoder = dcn32_hpo_dp_stream_encoder_create,
- .create_hpo_dp_link_encoder = dcn32_hpo_dp_link_encoder_create,
- .create_hwseq = dcn32_hwseq_create,
-};
-
static void dcn32_resource_destruct(struct dcn32_resource_pool *pool)
{
unsigned int i;
@@ -1888,6 +1863,8 @@ bool dcn32_validate_bandwidth(struct dc *dc,
dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);
+ dcn32_override_min_req_memclk(dc, context);
+
BW_VAL_TRACE_END_WATERMARKS();
goto validate_out;
@@ -2198,6 +2175,7 @@ static bool dcn32_resource_construct(
dc->caps.extended_aux_timeout_support = true;
dc->caps.dmcub_support = true;
dc->caps.seamless_odm = true;
+ dc->caps.max_v_total = (1 << 15) - 1;
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
@@ -2254,10 +2232,7 @@ static bool dcn32_resource_construct(
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
- else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
- dc->debug = debug_defaults_diags;
- } else
- dc->debug = debug_defaults_diags;
+
// Init the vm_helper
if (dc->vm_helper)
vm_helper_init(dc->vm_helper, 16);
@@ -2313,8 +2288,7 @@ static bool dcn32_resource_construct(
}
/* DML */
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
- dml_init_instance(&dc->dml, &dcn3_2_soc, &dcn3_2_ip, DML_PROJECT_DCN32);
+ dml_init_instance(&dc->dml, &dcn3_2_soc, &dcn3_2_ip, DML_PROJECT_DCN32);
/* IRQ Service */
init_data.ctx = dc->ctx;
@@ -2451,9 +2425,8 @@ static bool dcn32_resource_construct(
/* Audio, HWSeq, Stream Encoders including HPO and virtual, MPC 3D LUTs */
if (!resource_construct(num_virtual_links, dc, &pool->base,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
- goto create_fail;
+ &res_create_funcs))
+ goto create_fail;
/* HW Sequencer init functions and Plane caps */
dcn32_hw_sequencer_init_functions(dc);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
index 3937dbc1e552..81e443170829 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
@@ -37,9 +37,10 @@
#define DCN3_2_MBLK_WIDTH 128
#define DCN3_2_MBLK_HEIGHT_4BPE 128
#define DCN3_2_MBLK_HEIGHT_8BPE 64
-#define DCN3_2_VMIN_DISPCLK_HZ 717000000
#define DCN3_2_DCFCLK_DS_INIT_KHZ 10000 // Choose 10Mhz for init DCFCLK DS freq
-#define DCN3_2_MIN_ACTIVE_SWITCH_MARGIN_FPO_US 100 // Only allow FPO + Vactive if active margin >= 100
+#define SUBVP_HIGH_REFRESH_LIST_LEN 3
+#define DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ 1800
+#define DCN3_2_VMIN_DISPCLK_HZ 717000000
#define TO_DCN32_RES_POOL(pool)\
container_of(pool, struct dcn32_resource_pool, base)
@@ -47,6 +48,15 @@
extern struct _vcs_dpi_ip_params_st dcn3_2_ip;
extern struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc;
+struct subvp_high_refresh_list {
+ int min_refresh;
+ int max_refresh;
+ struct resolution {
+ int width;
+ int height;
+ } res[SUBVP_HIGH_REFRESH_LIST_LEN];
+};
+
struct dcn32_resource_pool {
struct resource_pool base;
};
@@ -151,10 +161,18 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre
bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe);
+bool dcn32_allow_subvp_high_refresh_rate(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe);
+
unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans);
double dcn32_determine_max_vratio_prefetch(struct dc *dc, struct dc_state *context);
+bool dcn32_check_native_scaling_for_res(struct pipe_ctx *pipe, unsigned int width, unsigned int height);
+
+bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context);
+
+bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int vlevel);
+
/* definitions for run time init of reg offsets */
/* CLK SRC */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
index eeca16faf31a..a9c41ef0751f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
@@ -94,18 +94,15 @@ uint32_t dcn32_helper_calculate_mall_bytes_for_cursor(
}
/**
- * ********************************************************************************************
- * dcn32_helper_calculate_num_ways_for_subvp: Calculate number of ways needed for SubVP
+ * dcn32_helper_calculate_num_ways_for_subvp(): Calculate number of ways needed for SubVP
*
* Gets total allocation required for the phantom viewport calculated by DML in bytes and
* converts to number of cache ways.
*
- * @param [in] dc: current dc state
- * @param [in] context: new dc state
+ * @dc: current dc state
+ * @context: new dc state
*
- * @return: number of ways required for SubVP
- *
- * ********************************************************************************************
+ * Return: number of ways required for SubVP
*/
uint32_t dcn32_helper_calculate_num_ways_for_subvp(
struct dc *dc,
@@ -258,11 +255,8 @@ bool dcn32_is_psr_capable(struct pipe_ctx *pipe)
return psr_capable;
}
-#define DCN3_2_NEW_DET_OVERRIDE_MIN_MULTIPLIER 7
-
/**
- * *******************************************************************************************
- * dcn32_determine_det_override: Determine DET allocation for each pipe
+ * dcn32_determine_det_override(): Determine DET allocation for each pipe
*
* This function determines how much DET to allocate for each pipe. The total number of
* DET segments will be split equally among each of the streams, and after that the DET
@@ -271,6 +265,7 @@ bool dcn32_is_psr_capable(struct pipe_ctx *pipe)
* If there is a plane that's driven by more than 1 pipe (i.e. pipe split), then the
* number of DET for that given plane will be split among the pipes driving that plane.
*
+ *
* High level algorithm:
* 1. Split total DET among number of streams
* 2. For each stream, split DET among the planes
@@ -278,25 +273,11 @@ bool dcn32_is_psr_capable(struct pipe_ctx *pipe)
* among those pipes.
* 4. Assign the DET override to the DML pipes.
*
- * Special cases:
- *
- * For two displays that have a large difference in pixel rate, we may experience
- * underflow on the larger display when we divide the DET equally. For this, we
- * will implement a modified algorithm to assign more DET to larger display.
- *
- * 1. Calculate difference in pixel rates ( multiplier ) between two displays
- * 2. If the multiplier exceeds DCN3_2_NEW_DET_OVERRIDE_MIN_MULTIPLIER, then
- * implement the modified DET override algorithm.
- * 3. Assign smaller DET size for lower pixel display and higher DET size for
- * higher pixel display
+ * @dc: Current DC state
+ * @context: New DC state to be programmed
+ * @pipes: Array of DML pipes
*
- * @param [in]: dc: Current DC state
- * @param [in]: context: New DC state to be programmed
- * @param [in]: pipes: Array of DML pipes
- *
- * @return: void
- *
- * *******************************************************************************************
+ * Return: void
*/
void dcn32_determine_det_override(struct dc *dc,
struct dc_state *context,
@@ -309,31 +290,10 @@ void dcn32_determine_det_override(struct dc *dc,
struct dc_plane_state *current_plane = NULL;
uint8_t stream_count = 0;
- int phy_pix_clk_mult, lower_mode_stream_index;
- int phy_pix_clk[MAX_PIPES] = {0};
- bool use_new_det_override_algorithm = false;
-
for (i = 0; i < context->stream_count; i++) {
/* Don't count SubVP streams for DET allocation */
- if (context->streams[i]->mall_stream_config.type != SUBVP_PHANTOM) {
- phy_pix_clk[i] = context->streams[i]->phy_pix_clk;
+ if (context->streams[i]->mall_stream_config.type != SUBVP_PHANTOM)
stream_count++;
- }
- }
-
- /* Check for special case with two displays, one with much higher pixel rate */
- if (stream_count == 2) {
- ASSERT((phy_pix_clk[0] > 0) && (phy_pix_clk[1] > 0));
- if (phy_pix_clk[0] < phy_pix_clk[1]) {
- lower_mode_stream_index = 0;
- phy_pix_clk_mult = phy_pix_clk[1] / phy_pix_clk[0];
- } else {
- lower_mode_stream_index = 1;
- phy_pix_clk_mult = phy_pix_clk[0] / phy_pix_clk[1];
- }
-
- if (phy_pix_clk_mult >= DCN3_2_NEW_DET_OVERRIDE_MIN_MULTIPLIER)
- use_new_det_override_algorithm = true;
}
if (stream_count > 0) {
@@ -342,13 +302,6 @@ void dcn32_determine_det_override(struct dc *dc,
if (context->streams[i]->mall_stream_config.type == SUBVP_PHANTOM)
continue;
- if (use_new_det_override_algorithm) {
- if (i == lower_mode_stream_index)
- stream_segments = 4;
- else
- stream_segments = 14;
- }
-
if (context->stream_status[i].plane_count > 0)
plane_segments = stream_segments / context->stream_status[i].plane_count;
else
@@ -432,8 +385,7 @@ void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
}
/**
- * *******************************************************************************************
- * dcn32_save_mall_state: Save MALL (SubVP) state for fast validation cases
+ * dcn32_save_mall_state(): Save MALL (SubVP) state for fast validation cases
*
* This function saves the MALL (SubVP) case for fast validation cases. For fast validation,
* there are situations where a shallow copy of the dc->current_state is created for the
@@ -446,13 +398,11 @@ void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
* NOTE: This function ONLY works if the streams are not moved to a different pipe in the
* validation. We don't expect this to happen in fast_validation=1 cases.
*
- * @param [in]: dc: Current DC state
- * @param [in]: context: New DC state to be programmed
- * @param [out]: temp_config: struct used to cache the existing MALL state
- *
- * @return: void
+ * @dc: Current DC state
+ * @context: New DC state to be programmed
+ * @temp_config: struct used to cache the existing MALL state
*
- * *******************************************************************************************
+ * Return: void
*/
void dcn32_save_mall_state(struct dc *dc,
struct dc_state *context,
@@ -472,18 +422,15 @@ void dcn32_save_mall_state(struct dc *dc,
}
/**
- * *******************************************************************************************
- * dcn32_restore_mall_state: Restore MALL (SubVP) state for fast validation cases
+ * dcn32_restore_mall_state(): Restore MALL (SubVP) state for fast validation cases
*
* Restore the MALL state based on the previously saved state from dcn32_save_mall_state
*
- * @param [in]: dc: Current DC state
- * @param [in/out]: context: New DC state to be programmed, restore MALL state into here
- * @param [in]: temp_config: struct that has the cached MALL state
+ * @dc: Current DC state
+ * @context: New DC state to be programmed, restore MALL state into here
+ * @temp_config: struct that has the cached MALL state
*
- * @return: void
- *
- * *******************************************************************************************
+ * Return: void
*/
void dcn32_restore_mall_state(struct dc *dc,
struct dc_state *context,
@@ -588,10 +535,11 @@ static int get_refresh_rate(struct dc_stream_state *fpo_candidate_stream)
}
/**
- * dcn32_can_support_mclk_switch_using_fw_based_vblank_stretch - Determines if config can support FPO
+ * dcn32_can_support_mclk_switch_using_fw_based_vblank_stretch() - Determines if config can
+ * support FPO
*
- * @param [in]: dc - current dc state
- * @param [in]: context - new dc state
+ * @dc: current dc state
+ * @context: new dc state
*
* Return: Pointer to FPO stream candidate if config can support FPO, otherwise NULL
*/
@@ -626,7 +574,7 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre
DC_FP_END();
DC_FP_START();
- is_fpo_vactive = dcn32_find_vactive_pipe(dc, context, DCN3_2_MIN_ACTIVE_SWITCH_MARGIN_FPO_US);
+ is_fpo_vactive = dcn32_find_vactive_pipe(dc, context, dc->debug.fpo_vactive_min_active_margin_us);
DC_FP_END();
if (!is_fpo_vactive || dc->debug.disable_fpo_vactive)
return NULL;
@@ -656,3 +604,120 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre
return fpo_candidate_stream;
}
+
+bool dcn32_check_native_scaling_for_res(struct pipe_ctx *pipe, unsigned int width, unsigned int height)
+{
+ bool is_native_scaling = false;
+
+ if (pipe->stream->timing.h_addressable == width &&
+ pipe->stream->timing.v_addressable == height &&
+ pipe->plane_state->src_rect.width == width &&
+ pipe->plane_state->src_rect.height == height &&
+ pipe->plane_state->dst_rect.width == width &&
+ pipe->plane_state->dst_rect.height == height)
+ is_native_scaling = true;
+
+ return is_native_scaling;
+}
+
+/**
+ * dcn32_subvp_drr_admissable() - Determine if SubVP + DRR config is admissible
+ *
+ * @dc: Current DC state
+ * @context: New DC state to be programmed
+ *
+ * SubVP + DRR is admissible under the following conditions:
+ * - Config must have 2 displays (i.e., 2 non-phantom master pipes)
+ * - One display is SubVP
+ * - Other display must have Freesync enabled
+ * - The potential DRR display must not be PSR capable
+ *
+ * Return: True if admissible, false otherwise
+ */
+bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context)
+{
+ bool result = false;
+ uint32_t i;
+ uint8_t subvp_count = 0;
+ uint8_t non_subvp_pipes = 0;
+ bool drr_pipe_found = false;
+ bool drr_psr_capable = false;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (!pipe->stream)
+ continue;
+
+ if (pipe->plane_state && !pipe->top_pipe) {
+ if (pipe->stream->mall_stream_config.type == SUBVP_MAIN)
+ subvp_count++;
+ if (pipe->stream->mall_stream_config.type == SUBVP_NONE) {
+ non_subvp_pipes++;
+ drr_psr_capable = (drr_psr_capable || dcn32_is_psr_capable(pipe));
+ if (pipe->stream->ignore_msa_timing_param &&
+ (pipe->stream->allow_freesync || pipe->stream->vrr_active_variable)) {
+ drr_pipe_found = true;
+ }
+ }
+ }
+ }
+
+ if (subvp_count == 1 && non_subvp_pipes == 1 && drr_pipe_found && !drr_psr_capable)
+ result = true;
+
+ return result;
+}
+
+/**
+ * dcn32_subvp_vblank_admissable() - Determine if SubVP + Vblank config is admissible
+ *
+ * @dc: Current DC state
+ * @context: New DC state to be programmed
+ * @vlevel: Voltage level calculated by DML
+ *
+ * SubVP + Vblank is admissible under the following conditions:
+ * - Config must have 2 displays (i.e., 2 non-phantom master pipes)
+ * - One display is SubVP
+ * - Other display must not have Freesync capability
+ * - DML must have output DRAM clock change support as SubVP + Vblank
+ * - The potential vblank display must not be PSR capable
+ *
+ * Return: True if admissible, false otherwise
+ */
+bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int vlevel)
+{
+ bool result = false;
+ uint32_t i;
+ uint8_t subvp_count = 0;
+ uint8_t non_subvp_pipes = 0;
+ bool drr_pipe_found = false;
+ struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
+ bool vblank_psr_capable = false;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (!pipe->stream)
+ continue;
+
+ if (pipe->plane_state && !pipe->top_pipe) {
+ if (pipe->stream->mall_stream_config.type == SUBVP_MAIN)
+ subvp_count++;
+ if (pipe->stream->mall_stream_config.type == SUBVP_NONE) {
+ non_subvp_pipes++;
+ vblank_psr_capable = (vblank_psr_capable || dcn32_is_psr_capable(pipe));
+ if (pipe->stream->ignore_msa_timing_param &&
+ (pipe->stream->allow_freesync || pipe->stream->vrr_active_variable)) {
+ drr_pipe_found = true;
+ }
+ }
+ }
+ }
+
+ if (subvp_count == 1 && non_subvp_pipes == 1 && !drr_pipe_found && !vblank_psr_capable &&
+ vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_vblank_w_mall_sub_vp)
+ result = true;
+
+ return result;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
index a60ddb343d13..ea204742ad35 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
@@ -725,31 +725,13 @@ static const struct dc_debug_options debug_defaults_drv = {
.override_dispclk_programming = true,
.disable_fpo_optimizations = false,
.fpo_vactive_margin_us = 2000, // 2000us
- .disable_fpo_vactive = true,
+ .disable_fpo_vactive = false,
.disable_boot_optimizations = false,
+ .disable_subvp_high_refresh = false,
+ .fpo_vactive_min_active_margin_us = 200,
+ .fpo_vactive_max_blank_us = 1000,
};
-static const struct dc_debug_options debug_defaults_diags = {
- .disable_dmcu = true,
- .force_abm_enable = false,
- .timing_trace = true,
- .clock_trace = true,
- .disable_dpp_power_gate = true,
- .disable_hubp_power_gate = true,
- .disable_dsc_power_gate = true,
- .disable_clock_gate = true,
- .disable_pplib_clock_request = true,
- .disable_pplib_wm_range = true,
- .disable_stutter = false,
- .scl_reset_length10 = true,
- .dwb_fi_phase = -1, // -1 = disable
- .dmub_command_table = true,
- .enable_tri_buf = true,
- .use_max_lb = true,
- .force_disable_subvp = true,
-};
-
-
static struct dce_aux *dcn321_aux_engine_create(
struct dc_context *ctx,
uint32_t inst)
@@ -1340,15 +1322,6 @@ static const struct resource_create_funcs res_create_funcs = {
.create_hwseq = dcn321_hwseq_create,
};
-static const struct resource_create_funcs res_create_maximus_funcs = {
- .read_dce_straps = NULL,
- .create_audio = NULL,
- .create_stream_encoder = NULL,
- .create_hpo_dp_stream_encoder = dcn321_hpo_dp_stream_encoder_create,
- .create_hpo_dp_link_encoder = dcn321_hpo_dp_link_encoder_create,
- .create_hwseq = dcn321_hwseq_create,
-};
-
static void dcn321_resource_destruct(struct dcn321_resource_pool *pool)
{
unsigned int i;
@@ -1735,9 +1708,9 @@ static bool dcn321_resource_construct(
dc->caps.subvp_pstate_allow_width_us = 20;
dc->caps.subvp_vertical_int_margin_us = 30;
dc->caps.subvp_drr_vblank_start_margin_us = 100; // 100us margin
- dc->caps.max_slave_planes = 1;
- dc->caps.max_slave_yuv_planes = 1;
- dc->caps.max_slave_rgb_planes = 1;
+ dc->caps.max_slave_planes = 2;
+ dc->caps.max_slave_yuv_planes = 2;
+ dc->caps.max_slave_rgb_planes = 2;
dc->caps.post_blend_color_processing = true;
dc->caps.force_dp_tps4_for_cp2520 = true;
dc->caps.dp_hpo = true;
@@ -1745,6 +1718,7 @@ static bool dcn321_resource_construct(
dc->caps.edp_dsc_support = true;
dc->caps.extended_aux_timeout_support = true;
dc->caps.dmcub_support = true;
+ dc->caps.max_v_total = (1 << 15) - 1;
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
@@ -1798,10 +1772,7 @@ static bool dcn321_resource_construct(
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
- else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
- dc->debug = debug_defaults_diags;
- } else
- dc->debug = debug_defaults_diags;
+
// Init the vm_helper
if (dc->vm_helper)
vm_helper_init(dc->vm_helper, 16);
@@ -1857,8 +1828,7 @@ static bool dcn321_resource_construct(
}
/* DML */
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
- dml_init_instance(&dc->dml, &dcn3_21_soc, &dcn3_21_ip, DML_PROJECT_DCN32);
+ dml_init_instance(&dc->dml, &dcn3_21_soc, &dcn3_21_ip, DML_PROJECT_DCN32);
/* IRQ Service */
init_data.ctx = dc->ctx;
@@ -1990,9 +1960,8 @@ static bool dcn321_resource_construct(
/* Audio, HWSeq, Stream Encoders including HPO and virtual, MPC 3D LUTs */
if (!resource_construct(num_virtual_links, dc, &pool->base,
- (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
- &res_create_funcs : &res_create_maximus_funcs)))
- goto create_fail;
+ &res_create_funcs))
+ goto create_fail;
/* HW Sequencer init functions and Plane caps */
dcn32_hw_sequencer_init_functions(dc);
diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h
index 9a3f2a44f882..d0eed3b4771e 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services.h
@@ -40,6 +40,7 @@
struct dmub_srv;
struct dc_dmub_srv;
+union dmub_rb_cmd;
irq_handler_idx dm_register_interrupt(
struct dc_context *ctx,
@@ -274,6 +275,12 @@ void dm_perf_trace_timestamp(const char *func_name, unsigned int line, struct dc
#define PERF_TRACE_CTX(__CTX) dm_perf_trace_timestamp(__func__, __LINE__, __CTX)
/*
+ * DMUB Interfaces
+ */
+bool dm_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type);
+bool dm_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type);
+
+/*
* Debug and verification hooks
*/
@@ -285,4 +292,6 @@ void dm_dtn_log_append_v(struct dc_context *ctx,
void dm_dtn_log_end(struct dc_context *ctx,
struct dc_log_buffer_ctx *log_ctx);
+char *dce_version_to_string(const int version);
+
#endif /* __DM_SERVICES_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
index b52ba6ffabe1..facf269c4326 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
@@ -269,4 +269,10 @@ struct dtn_min_clk_info {
uint32_t min_memory_clock_khz;
};
+enum dm_dmub_wait_type {
+ DM_DMUB_WAIT_TYPE_NO_WAIT,
+ DM_DMUB_WAIT_TYPE_WAIT,
+ DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY,
+};
+
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile
index 01db035589c5..77cf5545c94c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile
@@ -38,6 +38,11 @@ ifdef CONFIG_ARM64
dml_rcflags := -mgeneral-regs-only
endif
+ifdef CONFIG_LOONGARCH
+dml_ccflags := -mfpu=64
+dml_rcflags := -msoft-float
+endif
+
ifdef CONFIG_CC_IS_GCC
ifneq ($(call gcc-min-version, 70100),y)
IS_OLD_GCC = 1
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
index f1c1a4b5fcac..8ae5ddbd1b27 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
@@ -948,10 +948,10 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc
{
int plane_count;
int i;
- unsigned int optimized_min_dst_y_next_start_us;
+ unsigned int min_dst_y_next_start_us;
plane_count = 0;
- optimized_min_dst_y_next_start_us = 0;
+ min_dst_y_next_start_us = 0;
for (i = 0; i < dc->res_pool->pipe_count; i++) {
if (context->res_ctx.pipe_ctx[i].plane_state)
plane_count++;
@@ -973,19 +973,18 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc
else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) {
struct dc_link *link = context->streams[0]->sink->link;
struct dc_stream_status *stream_status = &context->stream_status[0];
+ struct dc_stream_state *current_stream = context->streams[0];
int minmum_z8_residency = dc->debug.minimum_z8_residency_time > 0 ? dc->debug.minimum_z8_residency_time : 1000;
bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z8_residency;
bool is_pwrseq0 = link->link_index == 0;
+ bool isFreesyncVideo;
- if (dc_extended_blank_supported(dc)) {
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- if (context->res_ctx.pipe_ctx[i].stream == context->streams[0]
- && context->res_ctx.pipe_ctx[i].stream->adjust.v_total_min == context->res_ctx.pipe_ctx[i].stream->adjust.v_total_max
- && context->res_ctx.pipe_ctx[i].stream->adjust.v_total_min > context->res_ctx.pipe_ctx[i].stream->timing.v_total) {
- optimized_min_dst_y_next_start_us =
- context->res_ctx.pipe_ctx[i].dlg_regs.optimized_min_dst_y_next_start_us;
- break;
- }
+ isFreesyncVideo = current_stream->adjust.v_total_min == current_stream->adjust.v_total_max;
+ isFreesyncVideo = isFreesyncVideo && current_stream->timing.v_total < current_stream->adjust.v_total_min;
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (context->res_ctx.pipe_ctx[i].stream == current_stream && isFreesyncVideo) {
+ min_dst_y_next_start_us = context->res_ctx.pipe_ctx[i].dlg_regs.min_dst_y_next_start_us;
+ break;
}
}
@@ -993,7 +992,7 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc
if (stream_status->plane_count > 1)
return DCN_ZSTATE_SUPPORT_DISALLOW;
- if (is_pwrseq0 && (context->bw_ctx.dml.vba.StutterPeriod > 5000.0 || optimized_min_dst_y_next_start_us > 5000))
+ if (is_pwrseq0 && (context->bw_ctx.dml.vba.StutterPeriod > 5000.0 || min_dst_y_next_start_us > 5000))
return DCN_ZSTATE_SUPPORT_ALLOW;
else if (is_pwrseq0 && link->psr_settings.psr_version == DC_PSR_VERSION_1 && !link->panel_config.psr.disable_psr)
return allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY : DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY;
@@ -1043,7 +1042,7 @@ void dcn20_calculate_dlg_params(struct dc *dc,
int pipe_cnt,
int vlevel)
{
- int i, pipe_idx;
+ int i, pipe_idx, active_hubp_count = 0;
dc_assert_fp_enabled();
@@ -1079,6 +1078,8 @@ void dcn20_calculate_dlg_params(struct dc *dc,
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
if (!context->res_ctx.pipe_ctx[i].stream)
continue;
+ if (context->res_ctx.pipe_ctx[i].plane_state)
+ active_hubp_count++;
pipes[pipe_idx].pipe.dest.vstartup_start = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
pipes[pipe_idx].pipe.dest.vupdate_offset = get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
@@ -1098,13 +1099,13 @@ void dcn20_calculate_dlg_params(struct dc *dc,
context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz =
pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest;
- if (context->res_ctx.pipe_ctx[i].stream->adaptive_sync_infopacket.valid)
- dcn20_adjust_freesync_v_startup(
- &context->res_ctx.pipe_ctx[i].stream->timing,
- &context->res_ctx.pipe_ctx[i].pipe_dlg_param.vstartup_start);
pipe_idx++;
}
+ /* If DCN isn't making memory requests we can allow pstate change */
+ if (!active_hubp_count) {
+ context->bw_ctx.bw.dcn.clk.p_state_change_support = true;
+ }
/*save a original dppclock copy*/
context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
@@ -1885,6 +1886,17 @@ void dcn20_patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st
dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
}
+ if ((int)(bb->sr_exit_z8_time_us * 1000)
+ != dc->bb_overrides.sr_exit_z8_time_ns
+ && dc->bb_overrides.sr_exit_z8_time_ns) {
+ bb->sr_exit_z8_time_us = dc->bb_overrides.sr_exit_z8_time_ns / 1000.0;
+ }
+
+ if ((int)(bb->sr_enter_plus_exit_z8_time_us * 1000)
+ != dc->bb_overrides.sr_enter_plus_exit_z8_time_ns
+ && dc->bb_overrides.sr_enter_plus_exit_z8_time_ns) {
+ bb->sr_enter_plus_exit_z8_time_us = dc->bb_overrides.sr_enter_plus_exit_z8_time_ns / 1000.0;
+ }
if ((int)(bb->urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns
&& dc->bb_overrides.urgent_latency_ns) {
bb->urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
@@ -1915,6 +1927,7 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co
int vlevel = 0;
int pipe_split_from[MAX_PIPES];
int pipe_cnt = 0;
+ int i = 0;
display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC);
DC_LOGGER_INIT(dc->ctx->logger);
@@ -1938,6 +1951,15 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co
dcn20_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate);
dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (!context->res_ctx.pipe_ctx[i].stream)
+ continue;
+ if (context->res_ctx.pipe_ctx[i].stream->adaptive_sync_infopacket.valid)
+ dcn20_adjust_freesync_v_startup(
+ &context->res_ctx.pipe_ctx[i].stream->timing,
+ &context->res_ctx.pipe_ctx[i].pipe_dlg_param.vstartup_start);
+ }
+
BW_VAL_TRACE_END_WATERMARKS();
goto validate_out;
@@ -2210,6 +2232,7 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc,
int vlevel = 0;
int pipe_split_from[MAX_PIPES];
int pipe_cnt = 0;
+ int i = 0;
display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC);
DC_LOGGER_INIT(dc->ctx->logger);
@@ -2238,6 +2261,15 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc,
dcn21_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate);
dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (!context->res_ctx.pipe_ctx[i].stream)
+ continue;
+ if (context->res_ctx.pipe_ctx[i].stream->adaptive_sync_infopacket.valid)
+ dcn20_adjust_freesync_v_startup(
+ &context->res_ctx.pipe_ctx[i].stream->timing,
+ &context->res_ctx.pipe_ctx[i].pipe_dlg_param.vstartup_start);
+ }
+
BW_VAL_TRACE_END_WATERMARKS();
goto validate_out;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
index b7c2844d0cbe..f294f2f8c75b 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
@@ -810,7 +810,7 @@ static bool CalculatePrefetchSchedule(
*swath_width_chroma_ub = dml_ceil(SwathWidthY / 2 - 1, myPipe->BlockWidth256BytesC) + myPipe->BlockWidth256BytesC;
} else {
*swath_width_luma_ub = dml_ceil(SwathWidthY - 1, myPipe->BlockHeight256BytesY) + myPipe->BlockHeight256BytesY;
- if (myPipe->BlockWidth256BytesC > 0)
+ if (myPipe->BlockHeight256BytesC > 0)
*swath_width_chroma_ub = dml_ceil(SwathWidthY / 2 - 1, myPipe->BlockHeight256BytesC) + myPipe->BlockHeight256BytesC;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
index a352c703e258..ccb4ad78f667 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
@@ -674,10 +674,19 @@ void dcn30_fpu_update_bw_bounding_box(struct dc *dc,
}
/**
- * Finds dummy_latency_index when MCLK switching using firmware based
- * vblank stretch is enabled. This function will iterate through the
- * table of dummy pstate latencies until the lowest value that allows
+ * dcn30_find_dummy_latency_index_for_fw_based_mclk_switch() - Finds
+ * dummy_latency_index when MCLK switching using firmware based vblank stretch
+ * is enabled. This function will iterate through the table of dummy pstate
+ * latencies until the lowest value that allows
* dm_allow_self_refresh_and_mclk_switch to happen is found
+ *
+ * @dc: Current DC state
+ * @context: new dc state
+ * @pipes: DML pipe params
+ * @pipe_cnt: number of DML pipes
+ * @vlevel: Voltage level calculated by DML
+ *
+ * Return: lowest dummy_latency_index value
*/
int dcn30_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc,
struct dc_state *context,
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
index 7d0626e42ea6..9af1a43c042b 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
@@ -4939,8 +4939,8 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
}
v->TotImmediateFlipBytes = 0.0;
for (k = 0; k <= v->NumberOfActivePlanes - 1; k++) {
- v->TotImmediateFlipBytes = v->TotImmediateFlipBytes + v->NoOfDPP[i][j][k] * v->PDEAndMetaPTEBytesPerFrame[i][j][k]
- + v->MetaRowBytes[i][j][k] + v->DPTEBytesPerRow[i][j][k];
+ v->TotImmediateFlipBytes = v->TotImmediateFlipBytes + v->NoOfDPP[i][j][k] * (v->PDEAndMetaPTEBytesPerFrame[i][j][k]
+ + v->MetaRowBytes[i][j][k] + v->DPTEBytesPerRow[i][j][k]);
}
for (k = 0; k <= v->NumberOfActivePlanes - 1; k++) {
@@ -5130,7 +5130,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
ViewportExceedsSurface = true;
if (v->SourcePixelFormat[k] != dm_444_64 && v->SourcePixelFormat[k] != dm_444_32 && v->SourcePixelFormat[k] != dm_444_16
- && v->SourcePixelFormat[k] != dm_444_8 && v->SourcePixelFormat[k] != dm_rgbe) {
+ && v->SourcePixelFormat[k] != dm_444_16 && v->SourcePixelFormat[k] != dm_444_8 && v->SourcePixelFormat[k] != dm_rgbe) {
if (v->ViewportWidthChroma[k] > v->SurfaceWidthC[k] || v->ViewportHeightChroma[k] > v->SurfaceHeightC[k]) {
ViewportExceedsSurface = true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
index cd3cfcb2a2b0..0497a5d74a62 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
@@ -980,7 +980,7 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
unsigned int vstartup_start = 0;
unsigned int dst_x_after_scaler = 0;
- unsigned int dst_y_after_scaler = 0;
+ int dst_y_after_scaler = 0;
double line_wait = 0;
double dst_y_prefetch = 0;
double dst_y_per_vm_vblank = 0;
@@ -1171,6 +1171,8 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
dst_x_after_scaler = get_dst_x_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx);
dst_y_after_scaler = get_dst_y_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx);
+ if (dst_y_after_scaler < 0)
+ dst_y_after_scaler = 0;
// do some adjustment on the dst_after scaler to account for odm combine mode
dml_print("DML_DLG: %s: input dst_x_after_scaler = %d\n",
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
index 422f17aefd4a..6ce90678b33c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
@@ -333,45 +333,43 @@ void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
memcpy(s, dcn3_01_soc.clock_limits, sizeof(dcn3_01_soc.clock_limits));
/* Default clock levels are used for diags, which may lead to overclocking. */
- if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
- dcn3_01_ip.max_num_otg = pool->base.res_cap->num_timing_generator;
- dcn3_01_ip.max_num_dpp = pool->base.pipe_count;
- dcn3_01_soc.num_chans = bw_params->num_channels;
-
- ASSERT(clk_table->num_entries);
- for (i = 0; i < clk_table->num_entries; i++) {
- /* loop backwards*/
- for (closest_clk_lvl = 0, j = dcn3_01_soc.num_states - 1; j >= 0; j--) {
- if ((unsigned int) dcn3_01_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
- closest_clk_lvl = j;
- break;
- }
+ dcn3_01_ip.max_num_otg = pool->base.res_cap->num_timing_generator;
+ dcn3_01_ip.max_num_dpp = pool->base.pipe_count;
+ dcn3_01_soc.num_chans = bw_params->num_channels;
+
+ ASSERT(clk_table->num_entries);
+ for (i = 0; i < clk_table->num_entries; i++) {
+ /* loop backwards*/
+ for (closest_clk_lvl = 0, j = dcn3_01_soc.num_states - 1; j >= 0; j--) {
+ if ((unsigned int) dcn3_01_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
+ closest_clk_lvl = j;
+ break;
}
-
- s[i].state = i;
- s[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
- s[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
- s[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
- s[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2;
-
- s[i].dispclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
- s[i].dppclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
- s[i].dram_bw_per_chan_gbps =
- dcn3_01_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
- s[i].dscclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
- s[i].dtbclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
- s[i].phyclk_d18_mhz =
- dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
- s[i].phyclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
}
- if (clk_table->num_entries) {
- dcn3_01_soc.num_states = clk_table->num_entries;
- /* duplicate last level */
- s[dcn3_01_soc.num_states] =
- dcn3_01_soc.clock_limits[dcn3_01_soc.num_states - 1];
- s[dcn3_01_soc.num_states].state = dcn3_01_soc.num_states;
- }
+ s[i].state = i;
+ s[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
+ s[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
+ s[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
+ s[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2;
+
+ s[i].dispclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
+ s[i].dppclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
+ s[i].dram_bw_per_chan_gbps =
+ dcn3_01_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
+ s[i].dscclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
+ s[i].dtbclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
+ s[i].phyclk_d18_mhz =
+ dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
+ s[i].phyclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
+ }
+
+ if (clk_table->num_entries) {
+ dcn3_01_soc.num_states = clk_table->num_entries;
+ /* duplicate last level */
+ s[dcn3_01_soc.num_states] =
+ dcn3_01_soc.clock_limits[dcn3_01_soc.num_states - 1];
+ s[dcn3_01_soc.num_states].state = dcn3_01_soc.num_states;
}
memcpy(dcn3_01_soc.clock_limits, s, sizeof(dcn3_01_soc.clock_limits));
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
index 59836570603a..deb6d162a2d5 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
@@ -483,7 +483,7 @@ void dcn31_calculate_wm_and_dlg_fp(
int pipe_cnt,
int vlevel)
{
- int i, pipe_idx, active_hubp_count = 0;
+ int i, pipe_idx, total_det = 0, active_hubp_count = 0;
double dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
dc_assert_fp_enabled();
@@ -563,6 +563,18 @@ void dcn31_calculate_wm_and_dlg_fp(
if (context->res_ctx.pipe_ctx[i].stream)
context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = 0;
}
+ for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
+ if (!context->res_ctx.pipe_ctx[i].stream)
+ continue;
+
+ context->res_ctx.pipe_ctx[i].det_buffer_size_kb =
+ get_det_buffer_size_kbytes(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
+ if (context->res_ctx.pipe_ctx[i].det_buffer_size_kb > 384)
+ context->res_ctx.pipe_ctx[i].det_buffer_size_kb /= 2;
+ total_det += context->res_ctx.pipe_ctx[i].det_buffer_size_kb;
+ pipe_idx++;
+ }
+ context->bw_ctx.bw.dcn.compbuf_size_kb = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - total_det;
}
void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
@@ -570,6 +582,7 @@ void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
struct _vcs_dpi_voltage_scaling_st *s = dc->scratch.update_bw_bounding_box.clock_limits;
struct clk_limit_table *clk_table = &bw_params->clk_table;
unsigned int i, closest_clk_lvl;
+ int max_dispclk_mhz = 0, max_dppclk_mhz = 0;
int j;
dc_assert_fp_enabled();
@@ -577,59 +590,55 @@ void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
memcpy(s, dcn3_1_soc.clock_limits, sizeof(dcn3_1_soc.clock_limits));
// Default clock levels are used for diags, which may lead to overclocking.
- if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
- int max_dispclk_mhz = 0, max_dppclk_mhz = 0;
+ dcn3_1_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator;
+ dcn3_1_ip.max_num_dpp = dc->res_pool->pipe_count;
+ dcn3_1_soc.num_chans = bw_params->num_channels;
- dcn3_1_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator;
- dcn3_1_ip.max_num_dpp = dc->res_pool->pipe_count;
- dcn3_1_soc.num_chans = bw_params->num_channels;
+ ASSERT(clk_table->num_entries);
- ASSERT(clk_table->num_entries);
+ /* Prepass to find max clocks independent of voltage level. */
+ for (i = 0; i < clk_table->num_entries; ++i) {
+ if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz)
+ max_dispclk_mhz = clk_table->entries[i].dispclk_mhz;
+ if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz)
+ max_dppclk_mhz = clk_table->entries[i].dppclk_mhz;
+ }
- /* Prepass to find max clocks independent of voltage level. */
- for (i = 0; i < clk_table->num_entries; ++i) {
- if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz)
- max_dispclk_mhz = clk_table->entries[i].dispclk_mhz;
- if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz)
- max_dppclk_mhz = clk_table->entries[i].dppclk_mhz;
+ for (i = 0; i < clk_table->num_entries; i++) {
+ /* loop backwards*/
+ for (closest_clk_lvl = 0, j = dcn3_1_soc.num_states - 1; j >= 0; j--) {
+ if ((unsigned int) dcn3_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
+ closest_clk_lvl = j;
+ break;
+ }
}
- for (i = 0; i < clk_table->num_entries; i++) {
- /* loop backwards*/
- for (closest_clk_lvl = 0, j = dcn3_1_soc.num_states - 1; j >= 0; j--) {
- if ((unsigned int) dcn3_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
- closest_clk_lvl = j;
- break;
- }
- }
+ s[i].state = i;
- s[i].state = i;
-
- /* Clocks dependent on voltage level. */
- s[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
- s[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
- s[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
- s[i].dram_speed_mts = clk_table->entries[i].memclk_mhz *
- 2 * clk_table->entries[i].wck_ratio;
-
- /* Clocks independent of voltage level. */
- s[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz :
- dcn3_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
-
- s[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz :
- dcn3_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
-
- s[i].dram_bw_per_chan_gbps =
- dcn3_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
- s[i].dscclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
- s[i].dtbclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
- s[i].phyclk_d18_mhz =
- dcn3_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
- s[i].phyclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
- }
- if (clk_table->num_entries) {
- dcn3_1_soc.num_states = clk_table->num_entries;
- }
+ /* Clocks dependent on voltage level. */
+ s[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
+ s[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
+ s[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
+ s[i].dram_speed_mts = clk_table->entries[i].memclk_mhz *
+ 2 * clk_table->entries[i].wck_ratio;
+
+ /* Clocks independent of voltage level. */
+ s[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz :
+ dcn3_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
+
+ s[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz :
+ dcn3_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
+
+ s[i].dram_bw_per_chan_gbps =
+ dcn3_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
+ s[i].dscclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
+ s[i].dtbclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
+ s[i].phyclk_d18_mhz =
+ dcn3_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
+ s[i].phyclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
+ }
+ if (clk_table->num_entries) {
+ dcn3_1_soc.num_states = clk_table->num_entries;
}
memcpy(dcn3_1_soc.clock_limits, s, sizeof(dcn3_1_soc.clock_limits));
@@ -643,10 +652,7 @@ void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
dcn3_1_soc.dram_clock_change_latency_us = dc->debug.dram_clock_change_latency_ns / 1000;
}
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
- dml_init_instance(&dc->dml, &dcn3_1_soc, &dcn3_1_ip, DML_PROJECT_DCN31);
- else
- dml_init_instance(&dc->dml, &dcn3_1_soc, &dcn3_1_ip, DML_PROJECT_DCN31_FPGA);
+ dml_init_instance(&dc->dml, &dcn3_1_soc, &dcn3_1_ip, DML_PROJECT_DCN31);
}
void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
@@ -707,10 +713,7 @@ void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
dcn3_15_soc.dram_clock_change_latency_us = dc->debug.dram_clock_change_latency_ns / 1000;
}
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
- dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN315);
- else
- dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN31_FPGA);
+ dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN315);
}
void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
@@ -726,71 +729,68 @@ void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
memcpy(s, dcn3_16_soc.clock_limits, sizeof(dcn3_16_soc.clock_limits));
// Default clock levels are used for diags, which may lead to overclocking.
- if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
+ dcn3_16_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator;
+ dcn3_16_ip.max_num_dpp = dc->res_pool->pipe_count;
+ dcn3_16_soc.num_chans = bw_params->num_channels;
- dcn3_16_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator;
- dcn3_16_ip.max_num_dpp = dc->res_pool->pipe_count;
- dcn3_16_soc.num_chans = bw_params->num_channels;
-
- ASSERT(clk_table->num_entries);
+ ASSERT(clk_table->num_entries);
- /* Prepass to find max clocks independent of voltage level. */
- for (i = 0; i < clk_table->num_entries; ++i) {
- if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz)
- max_dispclk_mhz = clk_table->entries[i].dispclk_mhz;
- if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz)
- max_dppclk_mhz = clk_table->entries[i].dppclk_mhz;
- }
+ /* Prepass to find max clocks independent of voltage level. */
+ for (i = 0; i < clk_table->num_entries; ++i) {
+ if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz)
+ max_dispclk_mhz = clk_table->entries[i].dispclk_mhz;
+ if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz)
+ max_dppclk_mhz = clk_table->entries[i].dppclk_mhz;
+ }
- for (i = 0; i < clk_table->num_entries; i++) {
- /* loop backwards*/
- for (closest_clk_lvl = 0, j = dcn3_16_soc.num_states - 1; j >= 0; j--) {
- if ((unsigned int) dcn3_16_soc.clock_limits[j].dcfclk_mhz <=
- clk_table->entries[i].dcfclk_mhz) {
- closest_clk_lvl = j;
- break;
- }
- }
- // Ported from DCN315
- if (clk_table->num_entries == 1) {
- /*smu gives one DPM level, let's take the highest one*/
- closest_clk_lvl = dcn3_16_soc.num_states - 1;
+ for (i = 0; i < clk_table->num_entries; i++) {
+ /* loop backwards*/
+ for (closest_clk_lvl = 0, j = dcn3_16_soc.num_states - 1; j >= 0; j--) {
+ if ((unsigned int) dcn3_16_soc.clock_limits[j].dcfclk_mhz <=
+ clk_table->entries[i].dcfclk_mhz) {
+ closest_clk_lvl = j;
+ break;
}
+ }
+ // Ported from DCN315
+ if (clk_table->num_entries == 1) {
+ /*smu gives one DPM level, let's take the highest one*/
+ closest_clk_lvl = dcn3_16_soc.num_states - 1;
+ }
- s[i].state = i;
+ s[i].state = i;
- /* Clocks dependent on voltage level. */
- s[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
- if (clk_table->num_entries == 1 &&
- s[i].dcfclk_mhz <
- dcn3_16_soc.clock_limits[closest_clk_lvl].dcfclk_mhz) {
- /*SMU fix not released yet*/
- s[i].dcfclk_mhz =
- dcn3_16_soc.clock_limits[closest_clk_lvl].dcfclk_mhz;
- }
- s[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
- s[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
- s[i].dram_speed_mts = clk_table->entries[i].memclk_mhz *
- 2 * clk_table->entries[i].wck_ratio;
-
- /* Clocks independent of voltage level. */
- s[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz :
- dcn3_16_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
-
- s[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz :
- dcn3_16_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
-
- s[i].dram_bw_per_chan_gbps =
- dcn3_16_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
- s[i].dscclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
- s[i].dtbclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
- s[i].phyclk_d18_mhz =
- dcn3_16_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
- s[i].phyclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
- }
- if (clk_table->num_entries) {
- dcn3_16_soc.num_states = clk_table->num_entries;
+ /* Clocks dependent on voltage level. */
+ s[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
+ if (clk_table->num_entries == 1 &&
+ s[i].dcfclk_mhz <
+ dcn3_16_soc.clock_limits[closest_clk_lvl].dcfclk_mhz) {
+ /*SMU fix not released yet*/
+ s[i].dcfclk_mhz =
+ dcn3_16_soc.clock_limits[closest_clk_lvl].dcfclk_mhz;
}
+ s[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
+ s[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
+ s[i].dram_speed_mts = clk_table->entries[i].memclk_mhz *
+ 2 * clk_table->entries[i].wck_ratio;
+
+ /* Clocks independent of voltage level. */
+ s[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz :
+ dcn3_16_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
+
+ s[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz :
+ dcn3_16_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
+
+ s[i].dram_bw_per_chan_gbps =
+ dcn3_16_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
+ s[i].dscclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
+ s[i].dtbclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
+ s[i].phyclk_d18_mhz =
+ dcn3_16_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
+ s[i].phyclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
+ }
+ if (clk_table->num_entries) {
+ dcn3_16_soc.num_states = clk_table->num_entries;
}
memcpy(dcn3_16_soc.clock_limits, s, sizeof(dcn3_16_soc.clock_limits));
@@ -805,13 +805,21 @@ void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
dcn3_16_soc.dram_clock_change_latency_us = dc->debug.dram_clock_change_latency_ns / 1000;
}
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
- dml_init_instance(&dc->dml, &dcn3_16_soc, &dcn3_16_ip, DML_PROJECT_DCN31);
- else
- dml_init_instance(&dc->dml, &dcn3_16_soc, &dcn3_16_ip, DML_PROJECT_DCN31_FPGA);
+ dml_init_instance(&dc->dml, &dcn3_16_soc, &dcn3_16_ip, DML_PROJECT_DCN31);
}
int dcn_get_max_non_odm_pix_rate_100hz(struct _vcs_dpi_soc_bounding_box_st *soc)
{
return soc->clock_limits[0].dispclk_mhz * 10000.0 / (1.0 + soc->dcn_downspread_percent / 100.0);
}
+
+int dcn_get_approx_det_segs_required_for_pstate(
+ struct _vcs_dpi_soc_bounding_box_st *soc,
+ int pix_clk_100hz, int bpp, int seg_size_kb)
+{
+ /* Roughly calculate required crb to hide latency. In practice there is slightly
+ * more buffer available for latency hiding
+ */
+ return (int)(soc->dram_clock_change_latency_us * pix_clk_100hz * bpp
+ / 10240000 + seg_size_kb - 1) / seg_size_kb;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h
index 687d3522cc33..8f9c8faed260 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h
@@ -47,6 +47,9 @@ void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params);
void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params);
int dcn_get_max_non_odm_pix_rate_100hz(struct _vcs_dpi_soc_bounding_box_st *soc);
+int dcn_get_approx_det_segs_required_for_pstate(
+ struct _vcs_dpi_soc_bounding_box_st *soc,
+ int pix_clk_100hz, int bpp, int seg_size_kb);
int dcn31x_populate_dml_pipes_from_context(struct dc *dc,
struct dc_state *context,
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
index bd674dc30df3..43016c462251 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
@@ -532,7 +532,8 @@ static void CalculateStutterEfficiency(
static void CalculateSwathAndDETConfiguration(
bool ForceSingleDPP,
int NumberOfActivePlanes,
- unsigned int DETBufferSizeInKByte,
+ bool DETSharedByAllDPP,
+ unsigned int DETBufferSizeInKByte[],
double MaximumSwathWidthLuma[],
double MaximumSwathWidthChroma[],
enum scan_direction_class SourceScan[],
@@ -3118,7 +3119,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
v->SurfaceWidthC[k],
v->SurfaceHeightY[k],
v->SurfaceHeightC[k],
- v->DETBufferSizeInKByte[0] * 1024,
+ v->DETBufferSizeInKByte[k] * 1024,
v->BlockHeight256BytesY[k],
v->BlockHeight256BytesC[k],
v->SurfaceTiling[k],
@@ -3313,7 +3314,8 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib)
CalculateSwathAndDETConfiguration(
false,
v->NumberOfActivePlanes,
- v->DETBufferSizeInKByte[0],
+ mode_lib->project == DML_PROJECT_DCN315 && v->DETSizeOverride[0],
+ v->DETBufferSizeInKByte,
dummy1,
dummy2,
v->SourceScan,
@@ -3779,14 +3781,16 @@ static noinline void CalculatePrefetchSchedulePerPlane(
&v->VReadyOffsetPix[k]);
}
-static void PatchDETBufferSizeInKByte(unsigned int NumberOfActivePlanes, int NoOfDPPThisState[], unsigned int config_return_buffer_size_in_kbytes, unsigned int *DETBufferSizeInKByte)
+static void PatchDETBufferSizeInKByte(unsigned int NumberOfActivePlanes, int NoOfDPPThisState[], unsigned int config_return_buffer_size_in_kbytes, unsigned int DETBufferSizeInKByte[])
{
int i, total_pipes = 0;
for (i = 0; i < NumberOfActivePlanes; i++)
total_pipes += NoOfDPPThisState[i];
- *DETBufferSizeInKByte = ((config_return_buffer_size_in_kbytes - DCN3_15_MIN_COMPBUF_SIZE_KB) / 64 / total_pipes) * 64;
- if (*DETBufferSizeInKByte > DCN3_15_MAX_DET_SIZE)
- *DETBufferSizeInKByte = DCN3_15_MAX_DET_SIZE;
+ DETBufferSizeInKByte[0] = ((config_return_buffer_size_in_kbytes - DCN3_15_MIN_COMPBUF_SIZE_KB) / 64 / total_pipes) * 64;
+ if (DETBufferSizeInKByte[0] > DCN3_15_MAX_DET_SIZE)
+ DETBufferSizeInKByte[0] = DCN3_15_MAX_DET_SIZE;
+ for (i = 1; i < NumberOfActivePlanes; i++)
+ DETBufferSizeInKByte[i] = DETBufferSizeInKByte[0];
}
@@ -4026,7 +4030,8 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
CalculateSwathAndDETConfiguration(
true,
v->NumberOfActivePlanes,
- v->DETBufferSizeInKByte[0],
+ mode_lib->project == DML_PROJECT_DCN315 && v->DETSizeOverride[0],
+ v->DETBufferSizeInKByte,
v->MaximumSwathWidthLuma,
v->MaximumSwathWidthChroma,
v->SourceScan,
@@ -4166,6 +4171,10 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
|| (v->PlaneRequiredDISPCLK > v->MaxDispclkRoundedDownToDFSGranularity)) {
v->DISPCLK_DPPCLK_Support[i][j] = false;
}
+ if (mode_lib->project == DML_PROJECT_DCN315 && v->DETSizeOverride[k] > DCN3_15_MAX_DET_SIZE && v->NoOfDPP[i][j][k] < 2) {
+ v->MPCCombine[i][j][k] = true;
+ v->NoOfDPP[i][j][k] = 2;
+ }
}
v->TotalNumberOfActiveDPP[i][j] = 0;
v->TotalNumberOfSingleDPPPlanes[i][j] = 0;
@@ -4642,12 +4651,13 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
v->ODMCombineEnableThisState[k] = v->ODMCombineEnablePerState[i][k];
}
- if (v->NumberOfActivePlanes > 1 && mode_lib->project == DML_PROJECT_DCN315)
- PatchDETBufferSizeInKByte(v->NumberOfActivePlanes, v->NoOfDPPThisState, v->ip.config_return_buffer_size_in_kbytes, &v->DETBufferSizeInKByte[0]);
+ if (v->NumberOfActivePlanes > 1 && mode_lib->project == DML_PROJECT_DCN315 && !v->DETSizeOverride[0])
+ PatchDETBufferSizeInKByte(v->NumberOfActivePlanes, v->NoOfDPPThisState, v->ip.config_return_buffer_size_in_kbytes, v->DETBufferSizeInKByte);
CalculateSwathAndDETConfiguration(
false,
v->NumberOfActivePlanes,
- v->DETBufferSizeInKByte[0],
+ mode_lib->project == DML_PROJECT_DCN315 && v->DETSizeOverride[0],
+ v->DETBufferSizeInKByte,
v->MaximumSwathWidthLuma,
v->MaximumSwathWidthChroma,
v->SourceScan,
@@ -5274,8 +5284,8 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
v->TotImmediateFlipBytes = 0.0;
for (k = 0; k < v->NumberOfActivePlanes; k++) {
v->TotImmediateFlipBytes = v->TotImmediateFlipBytes
- + v->NoOfDPP[i][j][k] * v->PDEAndMetaPTEBytesPerFrame[i][j][k] + v->MetaRowBytes[i][j][k]
- + v->DPTEBytesPerRow[i][j][k];
+ + v->NoOfDPP[i][j][k] * (v->PDEAndMetaPTEBytesPerFrame[i][j][k] + v->MetaRowBytes[i][j][k]
+ + v->DPTEBytesPerRow[i][j][k]);
}
for (k = 0; k < v->NumberOfActivePlanes; k++) {
@@ -6611,7 +6621,8 @@ static void CalculateStutterEfficiency(
static void CalculateSwathAndDETConfiguration(
bool ForceSingleDPP,
int NumberOfActivePlanes,
- unsigned int DETBufferSizeInKByte,
+ bool DETSharedByAllDPP,
+ unsigned int DETBufferSizeInKByteA[],
double MaximumSwathWidthLuma[],
double MaximumSwathWidthChroma[],
enum scan_direction_class SourceScan[],
@@ -6695,6 +6706,10 @@ static void CalculateSwathAndDETConfiguration(
*ViewportSizeSupport = true;
for (k = 0; k < NumberOfActivePlanes; ++k) {
+ unsigned int DETBufferSizeInKByte = DETBufferSizeInKByteA[k];
+
+ if (DETSharedByAllDPP && DPPPerPlane[k])
+ DETBufferSizeInKByte /= DPPPerPlane[k];
if ((SourcePixelFormat[k] == dm_444_64 || SourcePixelFormat[k] == dm_444_32 || SourcePixelFormat[k] == dm_444_16 || SourcePixelFormat[k] == dm_mono_16
|| SourcePixelFormat[k] == dm_mono_8 || SourcePixelFormat[k] == dm_rgbe)) {
if (SurfaceTiling[k] == dm_sw_linear
@@ -7017,7 +7032,7 @@ static double CalculateUrgentLatency(
return ret;
}
-static void UseMinimumDCFCLK(
+static noinline_for_stack void UseMinimumDCFCLK(
struct display_mode_lib *mode_lib,
int MaxPrefetchMode,
int ReorderingBytes)
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c
index 2244e4fb8c96..4113ce79c4af 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c
@@ -987,8 +987,7 @@ static void dml_rq_dlg_get_dlg_params(
dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start;
disp_dlg_regs->min_dst_y_next_start = (unsigned int) (((double) dlg_vblank_start) * dml_pow(2, 2));
- disp_dlg_regs->optimized_min_dst_y_next_start_us = 0;
- disp_dlg_regs->optimized_min_dst_y_next_start = disp_dlg_regs->min_dst_y_next_start;
+ disp_dlg_regs->min_dst_y_next_start_us = 0;
ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int)dml_pow(2, 18));
dml_print("DML_DLG: %s: min_ttu_vblank (us) = %3.2f\n", __func__, min_ttu_vblank);
@@ -1433,14 +1432,6 @@ static void dml_rq_dlg_get_dlg_params(
dml_print("DML_DLG: %s: disp_dlg_regs->dst_y_per_vm_flip = 0x%x\n", __func__, disp_dlg_regs->dst_y_per_vm_flip);
dml_print("DML_DLG: %s: disp_dlg_regs->dst_y_per_row_flip = 0x%x\n", __func__, disp_dlg_regs->dst_y_per_row_flip);
- // hack for FPGA
- if (mode_lib->project == DML_PROJECT_DCN31_FPGA) {
- if (disp_dlg_regs->vratio_prefetch >= (unsigned int) dml_pow(2, 22)) {
- disp_dlg_regs->vratio_prefetch = (unsigned int) dml_pow(2, 22) - 1;
- dml_print("vratio_prefetch exceed the max value, the register field is [21:0]\n");
- }
- }
-
disp_dlg_regs->refcyc_per_pte_group_vblank_l = (unsigned int) (dst_y_per_row_vblank * (double) htotal * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l);
ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int)dml_pow(2, 13));
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
index 9e54e3d0eb78..c9afddd11589 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
@@ -33,7 +33,7 @@
#include "dml/display_mode_vba.h"
struct _vcs_dpi_ip_params_st dcn3_14_ip = {
- .VBlankNomDefaultUS = 668,
+ .VBlankNomDefaultUS = 800,
.gpuvm_enable = 1,
.gpuvm_max_page_table_levels = 1,
.hostvm_enable = 1,
@@ -190,8 +190,7 @@ void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
dc_assert_fp_enabled();
// Default clock levels are used for diags, which may lead to overclocking.
- if (!IS_DIAG_DC(dc->ctx->dce_environment) && dc->config.use_default_clock_table == false) {
-
+ if (dc->config.use_default_clock_table == false) {
dcn3_14_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator;
dcn3_14_ip.max_num_dpp = dc->res_pool->pipe_count;
@@ -266,11 +265,7 @@ void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
}
dcn20_patch_bounding_box(dc, &dcn3_14_soc);
-
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
- dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN314);
- else
- dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN31_FPGA);
+ dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN314);
}
static bool is_dual_plane(enum surface_pixel_format format)
@@ -286,6 +281,7 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c
struct resource_context *res_ctx = &context->res_ctx;
struct pipe_ctx *pipe;
bool upscaled = false;
+ const unsigned int max_allowed_vblank_nom = 1023;
dc_assert_fp_enabled();
@@ -299,9 +295,11 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c
pipe = &res_ctx->pipe_ctx[i];
timing = &pipe->stream->timing;
- if (dc_extended_blank_supported(dc) && pipe->stream->adjust.v_total_max == pipe->stream->adjust.v_total_min
- && pipe->stream->adjust.v_total_min > timing->v_total)
- pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min;
+ pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min;
+ pipes[pipe_cnt].pipe.dest.vblank_nom = timing->v_total - pipes[pipe_cnt].pipe.dest.vactive;
+ pipes[pipe_cnt].pipe.dest.vblank_nom = min(pipes[pipe_cnt].pipe.dest.vblank_nom, dcn3_14_ip.VBlankNomDefaultUS);
+ pipes[pipe_cnt].pipe.dest.vblank_nom = max(pipes[pipe_cnt].pipe.dest.vblank_nom, timing->v_sync_width);
+ pipes[pipe_cnt].pipe.dest.vblank_nom = min(pipes[pipe_cnt].pipe.dest.vblank_nom, max_allowed_vblank_nom);
if (pipe->plane_state &&
(pipe->plane_state->src_rect.height < pipe->plane_state->dst_rect.height ||
@@ -323,8 +321,6 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c
pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0;
pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_chroma = 0;
pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch;
- pipes[pipe_cnt].pipe.dest.vblank_nom =
- dcn3_14_ip.VBlankNomDefaultUS / (timing->h_total / (timing->pix_clk_100hz / 10000.0));
pipes[pipe_cnt].pipe.src.dcc_rate = 3;
pipes[pipe_cnt].dout.dsc_input_bpc = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
index 7eb2173b7691..9010c47476e9 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
@@ -5371,8 +5371,8 @@ void dml314_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_
v->TotImmediateFlipBytes = 0.0;
for (k = 0; k < v->NumberOfActivePlanes; k++) {
v->TotImmediateFlipBytes = v->TotImmediateFlipBytes
- + v->NoOfDPP[i][j][k] * v->PDEAndMetaPTEBytesPerFrame[i][j][k] + v->MetaRowBytes[i][j][k]
- + v->DPTEBytesPerRow[i][j][k];
+ + v->NoOfDPP[i][j][k] * (v->PDEAndMetaPTEBytesPerFrame[i][j][k] + v->MetaRowBytes[i][j][k]
+ + v->DPTEBytesPerRow[i][j][k]);
}
for (k = 0; k < v->NumberOfActivePlanes; k++) {
@@ -5557,6 +5557,65 @@ void dml314_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_
}
}
}
+ for (i = v->soc.num_states; i >= 0; i--) {
+ for (j = 0; j < 2; j++) {
+ enum dm_validation_status status = DML_VALIDATION_OK;
+
+ if (!v->ScaleRatioAndTapsSupport) {
+ status = DML_FAIL_SCALE_RATIO_TAP;
+ } else if (!v->SourceFormatPixelAndScanSupport) {
+ status = DML_FAIL_SOURCE_PIXEL_FORMAT;
+ } else if (!v->ViewportSizeSupport[i][j]) {
+ status = DML_FAIL_VIEWPORT_SIZE;
+ } else if (P2IWith420) {
+ status = DML_FAIL_P2I_WITH_420;
+ } else if (DSCOnlyIfNecessaryWithBPP) {
+ status = DML_FAIL_DSC_ONLY_IF_NECESSARY_WITH_BPP;
+ } else if (DSC422NativeNotSupported) {
+ status = DML_FAIL_NOT_DSC422_NATIVE;
+ } else if (!v->ODMCombine4To1SupportCheckOK[i]) {
+ status = DML_FAIL_ODM_COMBINE4TO1;
+ } else if (v->NotEnoughDSCUnits[i]) {
+ status = DML_FAIL_NOT_ENOUGH_DSC;
+ } else if (!v->ROBSupport[i][j]) {
+ status = DML_FAIL_REORDERING_BUFFER;
+ } else if (!v->DISPCLK_DPPCLK_Support[i][j]) {
+ status = DML_FAIL_DISPCLK_DPPCLK;
+ } else if (!v->TotalAvailablePipesSupport[i][j]) {
+ status = DML_FAIL_TOTAL_AVAILABLE_PIPES;
+ } else if (!EnoughWritebackUnits) {
+ status = DML_FAIL_ENOUGH_WRITEBACK_UNITS;
+ } else if (!v->WritebackLatencySupport) {
+ status = DML_FAIL_WRITEBACK_LATENCY;
+ } else if (!v->WritebackScaleRatioAndTapsSupport) {
+ status = DML_FAIL_WRITEBACK_SCALE_RATIO_TAP;
+ } else if (!v->CursorSupport) {
+ status = DML_FAIL_CURSOR_SUPPORT;
+ } else if (!v->PitchSupport) {
+ status = DML_FAIL_PITCH_SUPPORT;
+ } else if (ViewportExceedsSurface) {
+ status = DML_FAIL_VIEWPORT_EXCEEDS_SURFACE;
+ } else if (!v->PrefetchSupported[i][j]) {
+ status = DML_FAIL_PREFETCH_SUPPORT;
+ } else if (!v->DynamicMetadataSupported[i][j]) {
+ status = DML_FAIL_DYNAMIC_METADATA;
+ } else if (!v->TotalVerticalActiveBandwidthSupport[i][j]) {
+ status = DML_FAIL_TOTAL_V_ACTIVE_BW;
+ } else if (!v->VRatioInPrefetchSupported[i][j]) {
+ status = DML_FAIL_V_RATIO_PREFETCH;
+ } else if (!v->PTEBufferSizeNotExceeded[i][j]) {
+ status = DML_FAIL_PTE_BUFFER_SIZE;
+ } else if (v->NonsupportedDSCInputBPC) {
+ status = DML_FAIL_DSC_INPUT_BPC;
+ } else if ((v->HostVMEnable
+ && !v->ImmediateFlipSupportedForState[i][j])) {
+ status = DML_FAIL_HOST_VM_IMMEDIATE_FLIP;
+ } else if (FMTBufferExceeded) {
+ status = DML_FAIL_FMT_BUFFER_EXCEEDED;
+ }
+ mode_lib->vba.ValidationStatus[i] = status;
+ }
+ }
{
unsigned int MaximumMPCCombine = 0;
@@ -7061,7 +7120,7 @@ static double CalculateUrgentLatency(
return ret;
}
-static void UseMinimumDCFCLK(
+static noinline_for_stack void UseMinimumDCFCLK(
struct display_mode_lib *mode_lib,
int MaxPrefetchMode,
int ReorderingBytes)
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c
index ea4eb66066c4..b3e8dc08030c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c
@@ -951,7 +951,6 @@ static void dml_rq_dlg_get_dlg_params(
{
const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src;
const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest;
- const display_output_params_st *dout = &e2e_pipe_param[pipe_idx].dout;
const display_clocks_and_cfg_st *clks = &e2e_pipe_param[pipe_idx].clks_cfg;
const scaler_ratio_depth_st *scl = &e2e_pipe_param[pipe_idx].pipe.scale_ratio_depth;
const scaler_taps_st *taps = &e2e_pipe_param[pipe_idx].pipe.scale_taps;
@@ -1000,8 +999,6 @@ static void dml_rq_dlg_get_dlg_params(
unsigned int vupdate_width;
unsigned int vready_offset;
- unsigned int dispclk_delay_subtotal;
-
unsigned int vstartup_start;
unsigned int dst_x_after_scaler;
unsigned int dst_y_after_scaler;
@@ -1051,7 +1048,6 @@ static void dml_rq_dlg_get_dlg_params(
float vba__refcyc_per_req_delivery_pre_l = get_refcyc_per_req_delivery_pre_l_in_us(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz; // From VBA
float vba__refcyc_per_req_delivery_l = get_refcyc_per_req_delivery_l_in_us(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz; // From VBA
- int blank_lines = 0;
memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs));
memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs));
@@ -1075,17 +1071,10 @@ static void dml_rq_dlg_get_dlg_params(
min_ttu_vblank = get_min_ttu_vblank_in_us(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); // From VBA
dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start;
- disp_dlg_regs->optimized_min_dst_y_next_start = disp_dlg_regs->min_dst_y_next_start;
- disp_dlg_regs->optimized_min_dst_y_next_start_us = 0;
- disp_dlg_regs->min_dst_y_next_start = (unsigned int) (((double) dlg_vblank_start) * dml_pow(2, 2));
- blank_lines = (dst->vblank_end + dst->vtotal_min - dst->vblank_start - dst->vstartup_start - 1);
- if (blank_lines < 0)
- blank_lines = 0;
- if (blank_lines != 0) {
- disp_dlg_regs->optimized_min_dst_y_next_start = vba__min_dst_y_next_start;
- disp_dlg_regs->optimized_min_dst_y_next_start_us = (disp_dlg_regs->optimized_min_dst_y_next_start * dst->hactive) / (unsigned int) dst->pixel_rate_mhz;
- disp_dlg_regs->min_dst_y_next_start = disp_dlg_regs->optimized_min_dst_y_next_start;
- }
+ disp_dlg_regs->min_dst_y_next_start_us =
+ (vba__min_dst_y_next_start * dst->hactive) / (unsigned int) dst->pixel_rate_mhz;
+ disp_dlg_regs->min_dst_y_next_start = vba__min_dst_y_next_start * dml_pow(2, 2);
+
ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int)dml_pow(2, 18));
dml_print("DML_DLG: %s: min_ttu_vblank (us) = %3.2f\n", __func__, min_ttu_vblank);
@@ -1127,13 +1116,6 @@ static void dml_rq_dlg_get_dlg_params(
vupdate_offset = dst->vupdate_offset;
vupdate_width = dst->vupdate_width;
vready_offset = dst->vready_offset;
- dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal;
-
- if (dout->dsc_enable) {
- double dsc_delay = get_dsc_delay(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); // FROM VBA
-
- dispclk_delay_subtotal += dsc_delay;
- }
vstartup_start = dst->vstartup_start;
if (interlaced) {
@@ -1538,14 +1520,6 @@ static void dml_rq_dlg_get_dlg_params(
dml_print("DML_DLG: %s: disp_dlg_regs->dst_y_per_vm_flip = 0x%x\n", __func__, disp_dlg_regs->dst_y_per_vm_flip);
dml_print("DML_DLG: %s: disp_dlg_regs->dst_y_per_row_flip = 0x%x\n", __func__, disp_dlg_regs->dst_y_per_row_flip);
- // hack for FPGA
- if (mode_lib->project == DML_PROJECT_DCN31_FPGA) {
- if (disp_dlg_regs->vratio_prefetch >= (unsigned int) dml_pow(2, 22)) {
- disp_dlg_regs->vratio_prefetch = (unsigned int) dml_pow(2, 22) - 1;
- dml_print("vratio_prefetch exceed the max value, the register field is [21:0]\n");
- }
- }
-
disp_dlg_regs->refcyc_per_pte_group_vblank_l = (unsigned int) (dst_y_per_row_vblank * (double) htotal * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l);
ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int)dml_pow(2, 13));
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
index 0c4c3208def1..e2bb2b9971f3 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
@@ -35,6 +35,15 @@
#define DC_LOGGER_INIT(logger)
+static const struct subvp_high_refresh_list subvp_high_refresh_list = {
+ .min_refresh = 120,
+ .max_refresh = 165,
+ .res = {
+ {.width = 3840, .height = 2160, },
+ {.width = 3440, .height = 1440, },
+ {.width = 2560, .height = 1440, }},
+};
+
struct _vcs_dpi_ip_params_st dcn3_2_ip = {
.gpuvm_enable = 0,
.gpuvm_max_page_table_levels = 4,
@@ -670,7 +679,6 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
unsigned int max_frame_time = 0;
bool valid_assignment_found = false;
unsigned int free_pipes = dcn32_get_num_free_pipes(dc, context);
- bool current_assignment_freesync = false;
struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
@@ -692,8 +700,12 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
* to combine this with SubVP can cause issues with the scheduling).
* - Not TMZ surface
*/
- if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) && !dcn32_is_psr_capable(pipe) &&
- pipe->stream->mall_stream_config.type == SUBVP_NONE && refresh_rate < 120 && !pipe->plane_state->address.tmz_surface &&
+ if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) &&
+ !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) &&
+ (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) &&
+ pipe->stream->mall_stream_config.type == SUBVP_NONE &&
+ (refresh_rate < 120 || dcn32_allow_subvp_high_refresh_rate(dc, context, pipe)) &&
+ !pipe->plane_state->address.tmz_surface &&
(vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0 ||
(vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] > 0 &&
dcn32_allow_subvp_with_active_margin(pipe)))) {
@@ -707,19 +719,10 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
struct dc_stream_state *stream = pipe->stream;
unsigned int frame_us = (stream->timing.v_total * stream->timing.h_total /
(double)(stream->timing.pix_clk_100hz * 100)) * 1000000;
- if (frame_us > max_frame_time && !stream->ignore_msa_timing_param) {
+ if (frame_us > max_frame_time) {
*index = i;
max_frame_time = frame_us;
valid_assignment_found = true;
- current_assignment_freesync = false;
- /* For the 2-Freesync display case, still choose the one with the
- * longest frame time
- */
- } else if (stream->ignore_msa_timing_param && (!valid_assignment_found ||
- (current_assignment_freesync && frame_us > max_frame_time))) {
- *index = i;
- valid_assignment_found = true;
- current_assignment_freesync = true;
}
}
}
@@ -851,10 +854,9 @@ static bool subvp_subvp_schedulable(struct dc *dc, struct dc_state *context)
}
/**
- * subvp_drr_schedulable - Determine if SubVP + DRR config is schedulable
+ * subvp_drr_schedulable() - Determine if SubVP + DRR config is schedulable
* @dc: current dc state
* @context: new dc state
- * @drr_pipe: DRR pipe_ctx for the SubVP + DRR config
*
* High level algorithm:
* 1. Get timing for SubVP pipe, phantom pipe, and DRR pipe
@@ -865,11 +867,12 @@ static bool subvp_subvp_schedulable(struct dc *dc, struct dc_state *context)
*
* Return: True if the SubVP + DRR config is schedulable, false otherwise
*/
-static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context, struct pipe_ctx *drr_pipe)
+static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context)
{
bool schedulable = false;
uint32_t i;
struct pipe_ctx *pipe = NULL;
+ struct pipe_ctx *drr_pipe = NULL;
struct dc_crtc_timing *main_timing = NULL;
struct dc_crtc_timing *phantom_timing = NULL;
struct dc_crtc_timing *drr_timing = NULL;
@@ -880,10 +883,6 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context, struc
int16_t stretched_drr_us = 0;
int16_t drr_stretched_vblank_us = 0;
int16_t max_vblank_mallregion = 0;
- const struct dc_config *config = &dc->config;
-
- if (config->disable_subvp_drr)
- return false;
// Find SubVP pipe
for (i = 0; i < dc->res_pool->pipe_count; i++) {
@@ -899,6 +898,19 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context, struc
break;
}
+ // Find the DRR pipe
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ drr_pipe = &context->res_ctx.pipe_ctx[i];
+
+ // We check for master pipe only
+ if (!drr_pipe->stream || !drr_pipe->plane_state || drr_pipe->top_pipe || drr_pipe->prev_odm_pipe)
+ continue;
+
+ if (drr_pipe->stream->mall_stream_config.type == SUBVP_NONE && drr_pipe->stream->ignore_msa_timing_param &&
+ (drr_pipe->stream->allow_freesync || drr_pipe->stream->vrr_active_variable))
+ break;
+ }
+
main_timing = &pipe->stream->timing;
phantom_timing = &pipe->stream->mall_stream_config.paired_stream->timing;
drr_timing = &drr_pipe->stream->timing;
@@ -984,13 +996,7 @@ static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context)
if (!subvp_pipe && pipe->stream->mall_stream_config.type == SUBVP_MAIN)
subvp_pipe = pipe;
}
- // Use ignore_msa_timing_param and VRR active, or Freesync flag to identify as DRR On
- if (found && context->res_ctx.pipe_ctx[vblank_index].stream->ignore_msa_timing_param &&
- (context->res_ctx.pipe_ctx[vblank_index].stream->allow_freesync ||
- context->res_ctx.pipe_ctx[vblank_index].stream->vrr_active_variable)) {
- // SUBVP + DRR case -- only allowed if run through DRR validation path
- schedulable = false;
- } else if (found) {
+ if (found) {
main_timing = &subvp_pipe->stream->timing;
phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing;
vblank_timing = &context->res_ctx.pipe_ctx[vblank_index].stream->timing;
@@ -1020,6 +1026,53 @@ static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context)
}
/**
+ * subvp_subvp_admissable() - Determine if subvp + subvp config is admissible
+ *
+ * @dc: Current DC state
+ * @context: New DC state to be programmed
+ *
+ * SubVP + SubVP is admissible under the following conditions:
+ * - All SubVP pipes are < 120Hz OR
+ * - All SubVP pipes are >= 120hz
+ *
+ * Return: True if admissible, false otherwise
+ */
+static bool subvp_subvp_admissable(struct dc *dc,
+ struct dc_state *context)
+{
+ bool result = false;
+ uint32_t i;
+ uint8_t subvp_count = 0;
+ uint32_t min_refresh = subvp_high_refresh_list.min_refresh, max_refresh = 0;
+ uint32_t refresh_rate = 0;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (!pipe->stream)
+ continue;
+
+ if (pipe->plane_state && !pipe->top_pipe &&
+ pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
+ refresh_rate = (pipe->stream->timing.pix_clk_100hz * 100 +
+ pipe->stream->timing.v_total * pipe->stream->timing.h_total - 1)
+ / (double)(pipe->stream->timing.v_total * pipe->stream->timing.h_total);
+ if (refresh_rate < min_refresh)
+ min_refresh = refresh_rate;
+ if (refresh_rate > max_refresh)
+ max_refresh = refresh_rate;
+ subvp_count++;
+ }
+ }
+
+ if (subvp_count == 2 && ((min_refresh < 120 && max_refresh < 120) ||
+ (min_refresh >= 120 && max_refresh >= 120)))
+ result = true;
+
+ return result;
+}
+
+/**
* subvp_validate_static_schedulability - Check which SubVP case is calculated
* and handle static analysis based on the case.
* @dc: current dc state
@@ -1037,11 +1090,12 @@ static bool subvp_validate_static_schedulability(struct dc *dc,
struct dc_state *context,
int vlevel)
{
- bool schedulable = true; // true by default for single display case
+ bool schedulable = false;
struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
uint32_t i, pipe_idx;
uint8_t subvp_count = 0;
uint8_t vactive_count = 0;
+ uint8_t non_subvp_pipes = 0;
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
@@ -1049,14 +1103,18 @@ static bool subvp_validate_static_schedulability(struct dc *dc,
if (!pipe->stream)
continue;
- if (pipe->plane_state && !pipe->top_pipe &&
- pipe->stream->mall_stream_config.type == SUBVP_MAIN)
- subvp_count++;
+ if (pipe->plane_state && !pipe->top_pipe) {
+ if (pipe->stream->mall_stream_config.type == SUBVP_MAIN)
+ subvp_count++;
+ if (pipe->stream->mall_stream_config.type == SUBVP_NONE) {
+ non_subvp_pipes++;
+ }
+ }
// Count how many planes that aren't SubVP/phantom are capable of VACTIVE
// switching (SubVP + VACTIVE unsupported). In situations where we force
// SubVP for a VACTIVE plane, we don't want to increment the vactive_count.
- if (vba->ActiveDRAMClockChangeLatencyMargin[vba->pipe_plane[pipe_idx]] > 0 &&
+ if (vba->ActiveDRAMClockChangeLatencyMarginPerState[vlevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] > 0 &&
pipe->stream->mall_stream_config.type == SUBVP_NONE) {
vactive_count++;
}
@@ -1065,13 +1123,14 @@ static bool subvp_validate_static_schedulability(struct dc *dc,
if (subvp_count == 2) {
// Static schedulability check for SubVP + SubVP case
- schedulable = subvp_subvp_schedulable(dc, context);
- } else if (vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_vblank_w_mall_sub_vp) {
- // Static schedulability check for SubVP + VBLANK case. Also handle the case where
- // DML outputs SubVP + VBLANK + VACTIVE (DML will report as SubVP + VBLANK)
- if (vactive_count > 0)
- schedulable = false;
- else
+ schedulable = subvp_subvp_admissable(dc, context) && subvp_subvp_schedulable(dc, context);
+ } else if (subvp_count == 1 && non_subvp_pipes == 0) {
+ // Single SubVP configs will be supported by default as long as it's suppported by DML
+ schedulable = true;
+ } else if (subvp_count == 1 && non_subvp_pipes == 1) {
+ if (dcn32_subvp_drr_admissable(dc, context))
+ schedulable = subvp_drr_schedulable(dc, context);
+ else if (dcn32_subvp_vblank_admissable(dc, context, vlevel))
schedulable = subvp_vblank_schedulable(dc, context);
} else if (vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_vactive_w_mall_sub_vp &&
vactive_count > 0) {
@@ -1095,10 +1154,6 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
unsigned int dc_pipe_idx = 0;
int i = 0;
bool found_supported_config = false;
- struct pipe_ctx *pipe = NULL;
- uint32_t non_subvp_pipes = 0;
- bool drr_pipe_found = false;
- uint32_t drr_pipe_index = 0;
dc_assert_fp_enabled();
@@ -1129,7 +1184,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
* 4. Display configuration passes validation
* 5. (Config doesn't support MCLK in VACTIVE/VBLANK || dc->debug.force_subvp_mclk_switch)
*/
- if (!dc->debug.force_disable_subvp && dcn32_all_pipes_have_stream_and_plane(dc, context) &&
+ if (!dc->debug.force_disable_subvp && !dc->caps.dmub_caps.gecc_enable && dcn32_all_pipes_have_stream_and_plane(dc, context) &&
!dcn32_mpo_in_use(context) && !dcn32_any_surfaces_rotated(dc, context) &&
(*vlevel == context->bw_ctx.dml.soc.num_states ||
vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported ||
@@ -1188,31 +1243,12 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
}
}
- if (*vlevel < context->bw_ctx.dml.soc.num_states &&
- vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] != dm_dram_clock_change_unsupported
- && subvp_validate_static_schedulability(dc, context, *vlevel)) {
+ if (*vlevel < context->bw_ctx.dml.soc.num_states
+ && subvp_validate_static_schedulability(dc, context, *vlevel))
found_supported_config = true;
- } else if (*vlevel < context->bw_ctx.dml.soc.num_states) {
- /* Case where 1 SubVP is added, and DML reports MCLK unsupported or DRR is allowed.
- * This handles the case for SubVP + DRR, where the DRR display does not support MCLK
- * switch at it's native refresh rate / timing, or DRR is allowed for the non-subvp
- * display.
- */
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- pipe = &context->res_ctx.pipe_ctx[i];
- if (pipe->stream && pipe->plane_state && !pipe->top_pipe &&
- pipe->stream->mall_stream_config.type == SUBVP_NONE) {
- non_subvp_pipes++;
- // Use ignore_msa_timing_param flag to identify as DRR
- if (pipe->stream->ignore_msa_timing_param && pipe->stream->allow_freesync) {
- drr_pipe_found = true;
- drr_pipe_index = i;
- }
- }
- }
- // If there is only 1 remaining non SubVP pipe that is DRR, check static
- // schedulability for SubVP + DRR.
- if (non_subvp_pipes == 1 && drr_pipe_found) {
+ if (found_supported_config) {
+ // For SubVP + DRR cases, we can force the lowest vlevel that supports the mode
+ if (dcn32_subvp_drr_admissable(dc, context) && subvp_drr_schedulable(dc, context)) {
/* find lowest vlevel that supports the config */
for (i = *vlevel; i >= 0; i--) {
if (vba->ModeSupport[i][vba->maxMpcComb]) {
@@ -1221,9 +1257,6 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
break;
}
}
-
- found_supported_config = subvp_drr_schedulable(dc, context,
- &context->res_ctx.pipe_ctx[drr_pipe_index]);
}
}
}
@@ -1315,6 +1348,7 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
int i, pipe_idx, active_hubp_count = 0;
bool usr_retraining_support = false;
bool unbounded_req_enabled = false;
+ struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
dc_assert_fp_enabled();
@@ -1396,6 +1430,11 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
context->res_ctx.pipe_ctx[i].surface_size_in_mall_bytes = get_surface_size_in_mall(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
+ if (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] > 0)
+ context->res_ctx.pipe_ctx[i].has_vactive_margin = true;
+ else
+ context->res_ctx.pipe_ctx[i].has_vactive_margin = false;
+
/* MALL Allocation Sizes */
/* count from active, top pipes per plane only */
if (context->res_ctx.pipe_ctx[i].stream && context->res_ctx.pipe_ctx[i].plane_state &&
@@ -1432,6 +1471,7 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
context->bw_ctx.bw.dcn.clk.dramclk_khz = 0;
context->bw_ctx.bw.dcn.clk.fclk_khz = 0;
context->bw_ctx.bw.dcn.clk.p_state_change_support = true;
+ context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = true;
}
/*save a original dppclock copy*/
context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
@@ -2005,6 +2045,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb;
dcfclk_from_fw_based_mclk_switching = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
pstate_en = true;
+ context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] = dm_dram_clock_change_vblank;
} else {
/* Restore FCLK latency and re-run validation to go back to original validation
* output if we find that enabling FPO does not give us any benefit (i.e. lower
@@ -2062,6 +2103,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
* sr_enter_exit/sr_exit should be lower than used for DRAM (TBD after bringup or later, use as decided in Clk Mgr)
*/
+ /*
if (dcn3_2_soc.num_states > 2) {
vlevel_temp = 0;
dcfclk = dc->clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz;
@@ -2088,6 +2130,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
context->bw_ctx.bw.dcn.watermarks.d.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.fclk_pstate_change_ns = get_fclk_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.d.usr_retraining_ns = get_usr_retraining_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+ */
/* Set C, for Dummy P-State:
* All clocks min.
@@ -2189,6 +2232,9 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
context->bw_ctx.bw.dcn.watermarks.a.usr_retraining_ns = get_usr_retraining_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
}
+ /* Make set D = set A since we do not optimized watermarks for MALL */
+ context->bw_ctx.bw.dcn.watermarks.d = context->bw_ctx.bw.dcn.watermarks.a;
+
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
if (!context->res_ctx.pipe_ctx[i].stream)
continue;
@@ -2303,14 +2349,48 @@ void dcn32_patch_dpm_table(struct clk_bw_params *bw_params)
bw_params->clk_table.entries[0].memclk_mhz = dcn3_2_soc.clock_limits[0].dram_speed_mts / 16;
}
-static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
+/*
+ * override_max_clk_values - Overwrite the max clock frequencies with the max DC mode timings
+ * Input:
+ * max_clk_limit - struct containing the desired clock timings
+ * Output:
+ * curr_clk_limit - struct containing the timings that need to be overwritten
+ * Return: 0 upon success, non-zero for failure
+ */
+static int override_max_clk_values(struct clk_limit_table_entry *max_clk_limit,
+ struct clk_limit_table_entry *curr_clk_limit)
+{
+ if (NULL == max_clk_limit || NULL == curr_clk_limit)
+ return -1; //invalid parameters
+
+ //only overwrite if desired max clock frequency is initialized
+ if (max_clk_limit->dcfclk_mhz != 0)
+ curr_clk_limit->dcfclk_mhz = max_clk_limit->dcfclk_mhz;
+
+ if (max_clk_limit->fclk_mhz != 0)
+ curr_clk_limit->fclk_mhz = max_clk_limit->fclk_mhz;
+
+ if (max_clk_limit->memclk_mhz != 0)
+ curr_clk_limit->memclk_mhz = max_clk_limit->memclk_mhz;
+
+ if (max_clk_limit->socclk_mhz != 0)
+ curr_clk_limit->socclk_mhz = max_clk_limit->socclk_mhz;
+
+ if (max_clk_limit->dtbclk_mhz != 0)
+ curr_clk_limit->dtbclk_mhz = max_clk_limit->dtbclk_mhz;
+
+ if (max_clk_limit->dispclk_mhz != 0)
+ curr_clk_limit->dispclk_mhz = max_clk_limit->dispclk_mhz;
+
+ return 0;
+}
+
+static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk_bw_params *bw_params,
struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries)
{
int i, j;
struct _vcs_dpi_voltage_scaling_st entry = {0};
-
- unsigned int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0,
- max_phyclk_mhz = 0, max_dtbclk_mhz = 0, max_fclk_mhz = 0, max_uclk_mhz = 0;
+ struct clk_limit_table_entry max_clk_data = {0};
unsigned int min_dcfclk_mhz = 199, min_fclk_mhz = 299;
@@ -2321,51 +2401,76 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
unsigned int num_fclk_dpms = 0;
unsigned int num_dcfclk_dpms = 0;
- for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
- if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
- max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
- if (bw_params->clk_table.entries[i].fclk_mhz > max_fclk_mhz)
- max_fclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
- if (bw_params->clk_table.entries[i].memclk_mhz > max_uclk_mhz)
- max_uclk_mhz = bw_params->clk_table.entries[i].memclk_mhz;
- if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz)
- max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
- if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
- max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
- if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
- max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
- if (bw_params->clk_table.entries[i].dtbclk_mhz > max_dtbclk_mhz)
- max_dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
+ unsigned int num_dc_uclk_dpms = 0;
+ unsigned int num_dc_fclk_dpms = 0;
+ unsigned int num_dc_dcfclk_dpms = 0;
- if (bw_params->clk_table.entries[i].memclk_mhz > 0)
+ for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
+ if (bw_params->clk_table.entries[i].dcfclk_mhz > max_clk_data.dcfclk_mhz)
+ max_clk_data.dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
+ if (bw_params->clk_table.entries[i].fclk_mhz > max_clk_data.fclk_mhz)
+ max_clk_data.fclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
+ if (bw_params->clk_table.entries[i].memclk_mhz > max_clk_data.memclk_mhz)
+ max_clk_data.memclk_mhz = bw_params->clk_table.entries[i].memclk_mhz;
+ if (bw_params->clk_table.entries[i].dispclk_mhz > max_clk_data.dispclk_mhz)
+ max_clk_data.dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
+ if (bw_params->clk_table.entries[i].dppclk_mhz > max_clk_data.dppclk_mhz)
+ max_clk_data.dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
+ if (bw_params->clk_table.entries[i].phyclk_mhz > max_clk_data.phyclk_mhz)
+ max_clk_data.phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
+ if (bw_params->clk_table.entries[i].dtbclk_mhz > max_clk_data.dtbclk_mhz)
+ max_clk_data.dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
+
+ if (bw_params->clk_table.entries[i].memclk_mhz > 0) {
num_uclk_dpms++;
- if (bw_params->clk_table.entries[i].fclk_mhz > 0)
+ if (bw_params->clk_table.entries[i].memclk_mhz <= bw_params->dc_mode_limit.memclk_mhz)
+ num_dc_uclk_dpms++;
+ }
+ if (bw_params->clk_table.entries[i].fclk_mhz > 0) {
num_fclk_dpms++;
- if (bw_params->clk_table.entries[i].dcfclk_mhz > 0)
+ if (bw_params->clk_table.entries[i].fclk_mhz <= bw_params->dc_mode_limit.fclk_mhz)
+ num_dc_fclk_dpms++;
+ }
+ if (bw_params->clk_table.entries[i].dcfclk_mhz > 0) {
num_dcfclk_dpms++;
+ if (bw_params->clk_table.entries[i].dcfclk_mhz <= bw_params->dc_mode_limit.dcfclk_mhz)
+ num_dc_dcfclk_dpms++;
+ }
+ }
+
+ if (!disable_dc_mode_overwrite) {
+ //Overwrite max frequencies with max DC mode frequencies for DC mode systems
+ override_max_clk_values(&bw_params->dc_mode_limit, &max_clk_data);
+ num_uclk_dpms = num_dc_uclk_dpms;
+ num_fclk_dpms = num_dc_fclk_dpms;
+ num_dcfclk_dpms = num_dc_dcfclk_dpms;
+ bw_params->clk_table.num_entries_per_clk.num_memclk_levels = num_uclk_dpms;
+ bw_params->clk_table.num_entries_per_clk.num_fclk_levels = num_fclk_dpms;
}
if (num_dcfclk_dpms > 0 && bw_params->clk_table.entries[0].fclk_mhz > min_fclk_mhz)
min_fclk_mhz = bw_params->clk_table.entries[0].fclk_mhz;
- if (!max_dcfclk_mhz || !max_dispclk_mhz || !max_dtbclk_mhz)
+ if (!max_clk_data.dcfclk_mhz || !max_clk_data.dispclk_mhz || !max_clk_data.dtbclk_mhz)
return -1;
- if (max_dppclk_mhz == 0)
- max_dppclk_mhz = max_dispclk_mhz;
+ if (max_clk_data.dppclk_mhz == 0)
+ max_clk_data.dppclk_mhz = max_clk_data.dispclk_mhz;
- if (max_fclk_mhz == 0)
- max_fclk_mhz = max_dcfclk_mhz * dcn3_2_soc.pct_ideal_sdp_bw_after_urgent / dcn3_2_soc.pct_ideal_fabric_bw_after_urgent;
+ if (max_clk_data.fclk_mhz == 0)
+ max_clk_data.fclk_mhz = max_clk_data.dcfclk_mhz *
+ dcn3_2_soc.pct_ideal_sdp_bw_after_urgent /
+ dcn3_2_soc.pct_ideal_fabric_bw_after_urgent;
- if (max_phyclk_mhz == 0)
- max_phyclk_mhz = dcn3_2_soc.clock_limits[0].phyclk_mhz;
+ if (max_clk_data.phyclk_mhz == 0)
+ max_clk_data.phyclk_mhz = dcn3_2_soc.clock_limits[0].phyclk_mhz;
*num_entries = 0;
- entry.dispclk_mhz = max_dispclk_mhz;
- entry.dscclk_mhz = max_dispclk_mhz / 3;
- entry.dppclk_mhz = max_dppclk_mhz;
- entry.dtbclk_mhz = max_dtbclk_mhz;
- entry.phyclk_mhz = max_phyclk_mhz;
+ entry.dispclk_mhz = max_clk_data.dispclk_mhz;
+ entry.dscclk_mhz = max_clk_data.dispclk_mhz / 3;
+ entry.dppclk_mhz = max_clk_data.dppclk_mhz;
+ entry.dtbclk_mhz = max_clk_data.dtbclk_mhz;
+ entry.phyclk_mhz = max_clk_data.phyclk_mhz;
entry.phyclk_d18_mhz = dcn3_2_soc.clock_limits[0].phyclk_d18_mhz;
entry.phyclk_d32_mhz = dcn3_2_soc.clock_limits[0].phyclk_d32_mhz;
@@ -2379,7 +2484,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
}
// Insert the max DCFCLK
- entry.dcfclk_mhz = max_dcfclk_mhz;
+ entry.dcfclk_mhz = max_clk_data.dcfclk_mhz;
entry.fabricclk_mhz = 0;
entry.dram_speed_mts = 0;
@@ -2407,7 +2512,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
// If FCLK fine grained, only insert max
else {
entry.dcfclk_mhz = 0;
- entry.fabricclk_mhz = max_fclk_mhz;
+ entry.fabricclk_mhz = max_clk_data.fclk_mhz;
entry.dram_speed_mts = 0;
insert_entry_into_table_sorted(table, num_entries, &entry);
@@ -2419,9 +2524,9 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
// Remove states that require higher clocks than are supported
for (i = *num_entries - 1; i >= 0 ; i--) {
- if (table[i].dcfclk_mhz > max_dcfclk_mhz ||
- table[i].fabricclk_mhz > max_fclk_mhz ||
- table[i].dram_speed_mts > max_uclk_mhz * 16)
+ if (table[i].dcfclk_mhz > max_clk_data.dcfclk_mhz ||
+ table[i].fabricclk_mhz > max_clk_data.fclk_mhz ||
+ table[i].dram_speed_mts > max_clk_data.memclk_mhz * 16)
remove_entry_from_table_at_index(table, num_entries, i);
}
@@ -2508,80 +2613,78 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
{
dc_assert_fp_enabled();
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- /* Overrides from dc->config options */
- dcn3_2_ip.clamp_min_dcfclk = dc->config.clamp_min_dcfclk;
+ /* Overrides from dc->config options */
+ dcn3_2_ip.clamp_min_dcfclk = dc->config.clamp_min_dcfclk;
- /* Override from passed dc->bb_overrides if available*/
- if ((int)(dcn3_2_soc.sr_exit_time_us * 1000) != dc->bb_overrides.sr_exit_time_ns
- && dc->bb_overrides.sr_exit_time_ns) {
- dcn3_2_soc.sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
- }
-
- if ((int)(dcn3_2_soc.sr_enter_plus_exit_time_us * 1000)
- != dc->bb_overrides.sr_enter_plus_exit_time_ns
- && dc->bb_overrides.sr_enter_plus_exit_time_ns) {
- dcn3_2_soc.sr_enter_plus_exit_time_us =
- dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
- }
+ /* Override from passed dc->bb_overrides if available*/
+ if ((int)(dcn3_2_soc.sr_exit_time_us * 1000) != dc->bb_overrides.sr_exit_time_ns
+ && dc->bb_overrides.sr_exit_time_ns) {
+ dcn3_2_soc.sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
+ }
- if ((int)(dcn3_2_soc.urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns
- && dc->bb_overrides.urgent_latency_ns) {
- dcn3_2_soc.urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
- dcn3_2_soc.urgent_latency_pixel_data_only_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
- }
+ if ((int)(dcn3_2_soc.sr_enter_plus_exit_time_us * 1000)
+ != dc->bb_overrides.sr_enter_plus_exit_time_ns
+ && dc->bb_overrides.sr_enter_plus_exit_time_ns) {
+ dcn3_2_soc.sr_enter_plus_exit_time_us =
+ dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
+ }
- if ((int)(dcn3_2_soc.dram_clock_change_latency_us * 1000)
- != dc->bb_overrides.dram_clock_change_latency_ns
- && dc->bb_overrides.dram_clock_change_latency_ns) {
- dcn3_2_soc.dram_clock_change_latency_us =
- dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
- }
+ if ((int)(dcn3_2_soc.urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns
+ && dc->bb_overrides.urgent_latency_ns) {
+ dcn3_2_soc.urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
+ dcn3_2_soc.urgent_latency_pixel_data_only_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
+ }
- if ((int)(dcn3_2_soc.fclk_change_latency_us * 1000)
- != dc->bb_overrides.fclk_clock_change_latency_ns
- && dc->bb_overrides.fclk_clock_change_latency_ns) {
- dcn3_2_soc.fclk_change_latency_us =
- dc->bb_overrides.fclk_clock_change_latency_ns / 1000;
- }
+ if ((int)(dcn3_2_soc.dram_clock_change_latency_us * 1000)
+ != dc->bb_overrides.dram_clock_change_latency_ns
+ && dc->bb_overrides.dram_clock_change_latency_ns) {
+ dcn3_2_soc.dram_clock_change_latency_us =
+ dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
+ }
- if ((int)(dcn3_2_soc.dummy_pstate_latency_us * 1000)
- != dc->bb_overrides.dummy_clock_change_latency_ns
- && dc->bb_overrides.dummy_clock_change_latency_ns) {
- dcn3_2_soc.dummy_pstate_latency_us =
- dc->bb_overrides.dummy_clock_change_latency_ns / 1000.0;
- }
+ if ((int)(dcn3_2_soc.fclk_change_latency_us * 1000)
+ != dc->bb_overrides.fclk_clock_change_latency_ns
+ && dc->bb_overrides.fclk_clock_change_latency_ns) {
+ dcn3_2_soc.fclk_change_latency_us =
+ dc->bb_overrides.fclk_clock_change_latency_ns / 1000;
+ }
- /* Override from VBIOS if VBIOS bb_info available */
- if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
- struct bp_soc_bb_info bb_info = {0};
+ if ((int)(dcn3_2_soc.dummy_pstate_latency_us * 1000)
+ != dc->bb_overrides.dummy_clock_change_latency_ns
+ && dc->bb_overrides.dummy_clock_change_latency_ns) {
+ dcn3_2_soc.dummy_pstate_latency_us =
+ dc->bb_overrides.dummy_clock_change_latency_ns / 1000.0;
+ }
- if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
- if (bb_info.dram_clock_change_latency_100ns > 0)
- dcn3_2_soc.dram_clock_change_latency_us =
- bb_info.dram_clock_change_latency_100ns * 10;
+ /* Override from VBIOS if VBIOS bb_info available */
+ if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
+ struct bp_soc_bb_info bb_info = {0};
- if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
- dcn3_2_soc.sr_enter_plus_exit_time_us =
- bb_info.dram_sr_enter_exit_latency_100ns * 10;
+ if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
+ if (bb_info.dram_clock_change_latency_100ns > 0)
+ dcn3_2_soc.dram_clock_change_latency_us =
+ bb_info.dram_clock_change_latency_100ns * 10;
- if (bb_info.dram_sr_exit_latency_100ns > 0)
- dcn3_2_soc.sr_exit_time_us =
- bb_info.dram_sr_exit_latency_100ns * 10;
- }
- }
+ if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
+ dcn3_2_soc.sr_enter_plus_exit_time_us =
+ bb_info.dram_sr_enter_exit_latency_100ns * 10;
- /* Override from VBIOS for num_chan */
- if (dc->ctx->dc_bios->vram_info.num_chans) {
- dcn3_2_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans;
- dcn3_2_soc.mall_allocated_for_dcn_mbytes = (double)(dcn32_calc_num_avail_chans_for_mall(dc,
- dc->ctx->dc_bios->vram_info.num_chans) * dc->caps.mall_size_per_mem_channel);
+ if (bb_info.dram_sr_exit_latency_100ns > 0)
+ dcn3_2_soc.sr_exit_time_us =
+ bb_info.dram_sr_exit_latency_100ns * 10;
}
+ }
- if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
- dcn3_2_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
+ /* Override from VBIOS for num_chan */
+ if (dc->ctx->dc_bios->vram_info.num_chans) {
+ dcn3_2_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans;
+ dcn3_2_soc.mall_allocated_for_dcn_mbytes = (double)(dcn32_calc_num_avail_chans_for_mall(dc,
+ dc->ctx->dc_bios->vram_info.num_chans) * dc->caps.mall_size_per_mem_channel);
}
+ if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
+ dcn3_2_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
+
/* DML DSC delay factor workaround */
dcn3_2_ip.dsc_delay_factor_wa = dc->debug.dsc_delay_factor_wa_x1000 / 1000.0;
@@ -2592,7 +2695,7 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
/* Overrides Clock levelsfrom CLK Mgr table entries as reported by PM FW */
- if ((!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) && (bw_params->clk_table.entries[0].memclk_mhz)) {
+ if (bw_params->clk_table.entries[0].memclk_mhz) {
if (dc->debug.use_legacy_soc_bb_mechanism) {
unsigned int i = 0, j = 0, num_states = 0;
@@ -2736,7 +2839,8 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
dcn3_2_soc.clock_limits[i].phyclk_d32_mhz = dcn3_2_soc.clock_limits[0].phyclk_d32_mhz;
}
} else {
- build_synthetic_soc_states(bw_params, dcn3_2_soc.clock_limits, &dcn3_2_soc.num_states);
+ build_synthetic_soc_states(dc->debug.disable_dc_mode_overwrite, bw_params,
+ dcn3_2_soc.clock_limits, &dcn3_2_soc.num_states);
}
/* Re-init DML with updated bb */
@@ -2783,15 +2887,76 @@ bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe)
}
/**
- * *******************************************************************************************
- * dcn32_determine_max_vratio_prefetch: Determine max Vratio for prefetch by driver policy
+ * dcn32_allow_subvp_high_refresh_rate: Determine if the high refresh rate config will allow subvp
*
- * @param [in]: dc: Current DC state
- * @param [in]: context: New DC state to be programmed
+ * @dc: Current DC state
+ * @context: New DC state to be programmed
+ * @pipe: Pipe to be considered for use in subvp
*
- * @return: Max vratio for prefetch
+ * On high refresh rate display configs, we will allow subvp under the following conditions:
+ * 1. Resolution is 3840x2160, 3440x1440, or 2560x1440
+ * 2. Refresh rate is between 120hz - 165hz
+ * 3. No scaling
+ * 4. Freesync is inactive
+ * 5. For single display cases, freesync must be disabled
*
- * *******************************************************************************************
+ * Return: True if pipe can be used for subvp, false otherwise
+ */
+bool dcn32_allow_subvp_high_refresh_rate(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe)
+{
+ bool allow = false;
+ uint32_t refresh_rate = 0;
+ uint32_t subvp_min_refresh = subvp_high_refresh_list.min_refresh;
+ uint32_t subvp_max_refresh = subvp_high_refresh_list.max_refresh;
+ uint32_t min_refresh = subvp_max_refresh;
+ uint32_t i;
+
+ /* Only allow SubVP on high refresh displays if all connected displays
+ * are considered "high refresh" (i.e. >= 120hz). We do not want to
+ * allow combinations such as 120hz (SubVP) + 60hz (SubVP).
+ */
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+ if (!pipe_ctx->stream)
+ continue;
+ refresh_rate = (pipe_ctx->stream->timing.pix_clk_100hz * 100 +
+ pipe_ctx->stream->timing.v_total * pipe_ctx->stream->timing.h_total - 1)
+ / (double)(pipe_ctx->stream->timing.v_total * pipe_ctx->stream->timing.h_total);
+
+ if (refresh_rate < min_refresh)
+ min_refresh = refresh_rate;
+ }
+
+ if (!dc->debug.disable_subvp_high_refresh && min_refresh >= subvp_min_refresh && pipe->stream &&
+ pipe->plane_state && !(pipe->stream->vrr_active_variable || pipe->stream->vrr_active_fixed)) {
+ refresh_rate = (pipe->stream->timing.pix_clk_100hz * 100 +
+ pipe->stream->timing.v_total * pipe->stream->timing.h_total - 1)
+ / (double)(pipe->stream->timing.v_total * pipe->stream->timing.h_total);
+ if (refresh_rate >= subvp_min_refresh && refresh_rate <= subvp_max_refresh) {
+ for (i = 0; i < SUBVP_HIGH_REFRESH_LIST_LEN; i++) {
+ uint32_t width = subvp_high_refresh_list.res[i].width;
+ uint32_t height = subvp_high_refresh_list.res[i].height;
+
+ if (dcn32_check_native_scaling_for_res(pipe, width, height)) {
+ if ((context->stream_count == 1 && !pipe->stream->allow_freesync) || context->stream_count > 1) {
+ allow = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return allow;
+}
+
+/**
+ * dcn32_determine_max_vratio_prefetch: Determine max Vratio for prefetch by driver policy
+ *
+ * @dc: Current DC state
+ * @context: New DC state to be programmed
+ *
+ * Return: Max vratio for prefetch
*/
double dcn32_determine_max_vratio_prefetch(struct dc *dc, struct dc_state *context)
{
@@ -2821,9 +2986,9 @@ double dcn32_determine_max_vratio_prefetch(struct dc *dc, struct dc_state *conte
* ActiveMargin <= 0 to be the FPO stream candidate if found.
*
*
- * @param [in]: dc - current dc state
- * @param [in]: context - new dc state
- * @param [out]: fpo_candidate_stream - pointer to FPO stream candidate if one is found
+ * @dc: current dc state
+ * @context: new dc state
+ * @fpo_candidate_stream: pointer to FPO stream candidate if one is found
*
* Return: void
*/
@@ -2849,10 +3014,9 @@ void dcn32_assign_fpo_vactive_candidate(struct dc *dc, const struct dc_state *co
/**
* dcn32_find_vactive_pipe - Determines if the config has a pipe that can switch in VACTIVE
*
- * @param [in]: dc - current dc state
- * @param [in]: context - new dc state
- * @param [in]: vactive_margin_req_us - The vactive marign required for a vactive pipe to be
- * considered "found"
+ * @dc: current dc state
+ * @context: new dc state
+ * @vactive_margin_req_us: The vactive marign required for a vactive pipe to be considered "found"
*
* Return: True if VACTIVE display is found, false otherwise
*/
@@ -2861,6 +3025,7 @@ bool dcn32_find_vactive_pipe(struct dc *dc, const struct dc_state *context, uint
unsigned int i, pipe_idx;
const struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
bool vactive_found = false;
+ unsigned int blank_us = 0;
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
const struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
@@ -2868,7 +3033,10 @@ bool dcn32_find_vactive_pipe(struct dc *dc, const struct dc_state *context, uint
if (!pipe->stream)
continue;
- if (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] >= vactive_margin_req_us) {
+ blank_us = ((pipe->stream->timing.v_total - pipe->stream->timing.v_addressable) * pipe->stream->timing.h_total /
+ (double)(pipe->stream->timing.pix_clk_100hz * 100)) * 1000000;
+ if (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] >= vactive_margin_req_us &&
+ !(pipe->stream->vrr_active_variable || pipe->stream->vrr_active_fixed) && blank_us < dc->debug.fpo_vactive_max_blank_us) {
vactive_found = true;
break;
}
@@ -2882,3 +3050,18 @@ void dcn32_set_clock_limits(const struct _vcs_dpi_soc_bounding_box_st *soc_bb)
dc_assert_fp_enabled();
dcn3_2_soc.clock_limits[0].dcfclk_mhz = 1200.0;
}
+
+void dcn32_override_min_req_memclk(struct dc *dc, struct dc_state *context)
+{
+ // WA: restrict FPO and SubVP to use first non-strobe mode (DCN32 BW issue)
+ if ((context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || dcn32_subvp_in_use(dc, context)) &&
+ dc->dml.soc.num_chans <= 8) {
+ int num_mclk_levels = dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels;
+
+ if (context->bw_ctx.dml.vba.DRAMSpeed <= dc->clk_mgr->bw_params->clk_table.entries[0].memclk_mhz * 16 &&
+ num_mclk_levels > 1) {
+ context->bw_ctx.dml.vba.DRAMSpeed = dc->clk_mgr->bw_params->clk_table.entries[1].memclk_mhz * 16;
+ context->bw_ctx.bw.dcn.clk.dramclk_khz = context->bw_ctx.dml.vba.DRAMSpeed * 1000 / 16;
+ }
+ }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
index dcf512cd3072..a4206b71d650 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
@@ -80,6 +80,8 @@ void dcn32_assign_fpo_vactive_candidate(struct dc *dc, const struct dc_state *co
bool dcn32_find_vactive_pipe(struct dc *dc, const struct dc_state *context, uint32_t vactive_margin_req);
+void dcn32_override_min_req_memclk(struct dc *dc, struct dc_state *context);
+
void dcn32_set_clock_limits(const struct _vcs_dpi_soc_bounding_box_st *soc_bb);
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
index d75248b6cae9..cbdfb762c10c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
@@ -811,7 +811,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
v->SwathHeightC[k],
TWait,
(v->DRAMSpeedPerState[mode_lib->vba.VoltageLevel] <= MEM_STROBE_FREQ_MHZ ||
- v->DCFCLKPerState[mode_lib->vba.VoltageLevel] <= MIN_DCFCLK_FREQ_MHZ) ?
+ v->DCFCLKPerState[mode_lib->vba.VoltageLevel] <= DCFCLK_FREQ_EXTRA_PREFETCH_REQ_MHZ) ?
mode_lib->vba.ip.min_prefetch_in_strobe_us : 0,
/* Output */
&v->DSTXAfterScaler[k],
@@ -2323,10 +2323,14 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
mode_lib->vba.LinkCapacitySupport[i] = true;
for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) {
if (mode_lib->vba.BlendingAndTiming[k] == k
- && (mode_lib->vba.Output[k] == dm_dp || mode_lib->vba.Output[k] == dm_dp2p0
- || mode_lib->vba.Output[k] == dm_edp
- || mode_lib->vba.Output[k] == dm_hdmi)
- && mode_lib->vba.OutputBppPerState[i][k] == 0) {
+ && (mode_lib->vba.Output[k] == dm_dp || mode_lib->vba.Output[k] == dm_dp2p0
+ || mode_lib->vba.Output[k] == dm_edp
+ || mode_lib->vba.Output[k] == dm_hdmi)
+ && mode_lib->vba.OutputBppPerState[i][k] == 0 &&
+ (mode_lib->vba.UsesMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe)) {
+ /* Phantom pipes don't consider DSC in DML, so it could fail link check.
+ * However, we don't care about the link for phantom pipes.
+ */
mode_lib->vba.LinkCapacitySupport[i] = false;
}
}
@@ -3311,7 +3315,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
v->swath_width_chroma_ub_this_state[k],
v->SwathHeightYThisState[k],
v->SwathHeightCThisState[k], v->TWait,
- (v->DRAMSpeedPerState[i] <= MEM_STROBE_FREQ_MHZ || v->DCFCLKState[i][j] <= MIN_DCFCLK_FREQ_MHZ) ?
+ (v->DRAMSpeedPerState[i] <= MEM_STROBE_FREQ_MHZ || v->DCFCLKState[i][j] <= DCFCLK_FREQ_EXTRA_PREFETCH_REQ_MHZ) ?
mode_lib->vba.ip.min_prefetch_in_strobe_us : 0,
/* Output */
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h
index d98e36a9a09c..c4745d63039b 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.h
@@ -53,7 +53,7 @@
#define BPP_BLENDED_PIPE 0xffffffff
#define MEM_STROBE_FREQ_MHZ 1600
-#define MIN_DCFCLK_FREQ_MHZ 200
+#define DCFCLK_FREQ_EXTRA_PREFETCH_REQ_MHZ 300
#define MEM_STROBE_MAX_DELIVERY_TIME_US 60.0
struct display_mode_lib;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
index 61cc4904ade4..a50e7f4dce42 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
@@ -1595,7 +1595,6 @@ double dml32_TruncToValidBPP(
unsigned int NonDSCBPP0;
unsigned int NonDSCBPP1;
unsigned int NonDSCBPP2;
- unsigned int NonDSCBPP3;
if (Format == dm_420) {
NonDSCBPP0 = 12;
@@ -1604,10 +1603,9 @@ double dml32_TruncToValidBPP(
MinDSCBPP = 6;
MaxDSCBPP = 1.5 * DSCInputBitPerComponent - 1 / 16;
} else if (Format == dm_444) {
- NonDSCBPP0 = 18;
- NonDSCBPP1 = 24;
- NonDSCBPP2 = 30;
- NonDSCBPP3 = 36;
+ NonDSCBPP0 = 24;
+ NonDSCBPP1 = 30;
+ NonDSCBPP2 = 36;
MinDSCBPP = 8;
MaxDSCBPP = 3 * DSCInputBitPerComponent - 1.0 / 16;
} else {
@@ -1661,9 +1659,7 @@ double dml32_TruncToValidBPP(
else
return dml_floor(16.0 * MaxLinkBPP, 1.0) / 16.0;
} else {
- if (MaxLinkBPP >= NonDSCBPP3)
- return NonDSCBPP3;
- else if (MaxLinkBPP >= NonDSCBPP2)
+ if (MaxLinkBPP >= NonDSCBPP2)
return NonDSCBPP2;
else if (MaxLinkBPP >= NonDSCBPP1)
return NonDSCBPP1;
@@ -1674,7 +1670,7 @@ double dml32_TruncToValidBPP(
}
} else {
if (!((DSCEnable == false && (DesiredBPP == NonDSCBPP2 || DesiredBPP == NonDSCBPP1 ||
- DesiredBPP == NonDSCBPP0 || DesiredBPP == NonDSCBPP3)) ||
+ DesiredBPP <= NonDSCBPP0)) ||
(DSCEnable && DesiredBPP >= MinDSCBPP && DesiredBPP <= MaxDSCBPP)))
return BPP_INVALID;
else
@@ -4342,7 +4338,7 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
+ v->WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
}
if (v->USRRetrainingRequiredFinal)
- v->Watermark.WritebackUrgentWatermark = v->Watermark.WritebackUrgentWatermark
+ v->Watermark.WritebackDRAMClockChangeWatermark = v->Watermark.WritebackDRAMClockChangeWatermark
+ mmSOCParameters.USRRetrainingLatency;
if (TotalActiveWriteback <= 1) {
@@ -4660,6 +4656,10 @@ void dml32_CalculateMinAndMaxPrefetchMode(
} else if (AllowForPStateChangeOrStutterInVBlankFinal == dm_prefetch_support_uclk_fclk_and_stutter) {
*MinPrefetchMode = 0;
*MaxPrefetchMode = 0;
+ } else if (AllowForPStateChangeOrStutterInVBlankFinal ==
+ dm_prefetch_support_uclk_fclk_and_stutter_if_possible) {
+ *MinPrefetchMode = 0;
+ *MaxPrefetchMode = 3;
} else {
*MinPrefetchMode = 0;
*MaxPrefetchMode = 3;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c
index 395ae8761980..9ba6cb67655f 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c
@@ -116,7 +116,7 @@ void dml32_rq_dlg_get_rq_reg(display_rq_regs_st *rq_regs,
else
rq_regs->rq_regs_l.min_meta_chunk_size = dml_log2(min_meta_chunk_bytes) - 6 + 1;
- if (min_meta_chunk_bytes == 0)
+ if (p1_min_meta_chunk_bytes == 0)
rq_regs->rq_regs_c.min_meta_chunk_size = 0;
else
rq_regs->rq_regs_c.min_meta_chunk_size = dml_log2(p1_min_meta_chunk_bytes) - 6 + 1;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
index 342a1bcb4927..f0683fd9d3f0 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
@@ -252,14 +252,48 @@ static void remove_entry_from_table_at_index(struct _vcs_dpi_voltage_scaling_st
memset(&table[--(*num_entries)], 0, sizeof(struct _vcs_dpi_voltage_scaling_st));
}
-static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
+/*
+ * override_max_clk_values - Overwrite the max clock frequencies with the max DC mode timings
+ * Input:
+ * max_clk_limit - struct containing the desired clock timings
+ * Output:
+ * curr_clk_limit - struct containing the timings that need to be overwritten
+ * Return: 0 upon success, non-zero for failure
+ */
+static int override_max_clk_values(struct clk_limit_table_entry *max_clk_limit,
+ struct clk_limit_table_entry *curr_clk_limit)
+{
+ if (NULL == max_clk_limit || NULL == curr_clk_limit)
+ return -1; //invalid parameters
+
+ //only overwrite if desired max clock frequency is initialized
+ if (max_clk_limit->dcfclk_mhz != 0)
+ curr_clk_limit->dcfclk_mhz = max_clk_limit->dcfclk_mhz;
+
+ if (max_clk_limit->fclk_mhz != 0)
+ curr_clk_limit->fclk_mhz = max_clk_limit->fclk_mhz;
+
+ if (max_clk_limit->memclk_mhz != 0)
+ curr_clk_limit->memclk_mhz = max_clk_limit->memclk_mhz;
+
+ if (max_clk_limit->socclk_mhz != 0)
+ curr_clk_limit->socclk_mhz = max_clk_limit->socclk_mhz;
+
+ if (max_clk_limit->dtbclk_mhz != 0)
+ curr_clk_limit->dtbclk_mhz = max_clk_limit->dtbclk_mhz;
+
+ if (max_clk_limit->dispclk_mhz != 0)
+ curr_clk_limit->dispclk_mhz = max_clk_limit->dispclk_mhz;
+
+ return 0;
+}
+
+static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk_bw_params *bw_params,
struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries)
{
int i, j;
struct _vcs_dpi_voltage_scaling_st entry = {0};
-
- unsigned int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0,
- max_phyclk_mhz = 0, max_dtbclk_mhz = 0, max_fclk_mhz = 0, max_uclk_mhz = 0;
+ struct clk_limit_table_entry max_clk_data = {0};
unsigned int min_dcfclk_mhz = 199, min_fclk_mhz = 299;
@@ -270,53 +304,78 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
unsigned int num_fclk_dpms = 0;
unsigned int num_dcfclk_dpms = 0;
+ unsigned int num_dc_uclk_dpms = 0;
+ unsigned int num_dc_fclk_dpms = 0;
+ unsigned int num_dc_dcfclk_dpms = 0;
+
for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
- if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
- max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
- if (bw_params->clk_table.entries[i].fclk_mhz > max_fclk_mhz)
- max_fclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
- if (bw_params->clk_table.entries[i].memclk_mhz > max_uclk_mhz)
- max_uclk_mhz = bw_params->clk_table.entries[i].memclk_mhz;
- if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz)
- max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
- if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
- max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
- if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
- max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
- if (bw_params->clk_table.entries[i].dtbclk_mhz > max_dtbclk_mhz)
- max_dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
-
- if (bw_params->clk_table.entries[i].memclk_mhz > 0)
+ if (bw_params->clk_table.entries[i].dcfclk_mhz > max_clk_data.dcfclk_mhz)
+ max_clk_data.dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
+ if (bw_params->clk_table.entries[i].fclk_mhz > max_clk_data.fclk_mhz)
+ max_clk_data.fclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
+ if (bw_params->clk_table.entries[i].memclk_mhz > max_clk_data.memclk_mhz)
+ max_clk_data.memclk_mhz = bw_params->clk_table.entries[i].memclk_mhz;
+ if (bw_params->clk_table.entries[i].dispclk_mhz > max_clk_data.dispclk_mhz)
+ max_clk_data.dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
+ if (bw_params->clk_table.entries[i].dppclk_mhz > max_clk_data.dppclk_mhz)
+ max_clk_data.dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
+ if (bw_params->clk_table.entries[i].phyclk_mhz > max_clk_data.phyclk_mhz)
+ max_clk_data.phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
+ if (bw_params->clk_table.entries[i].dtbclk_mhz > max_clk_data.dtbclk_mhz)
+ max_clk_data.dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
+
+ if (bw_params->clk_table.entries[i].memclk_mhz > 0) {
num_uclk_dpms++;
- if (bw_params->clk_table.entries[i].fclk_mhz > 0)
+ if (bw_params->clk_table.entries[i].memclk_mhz <= bw_params->dc_mode_limit.memclk_mhz)
+ num_dc_uclk_dpms++;
+ }
+ if (bw_params->clk_table.entries[i].fclk_mhz > 0) {
num_fclk_dpms++;
- if (bw_params->clk_table.entries[i].dcfclk_mhz > 0)
+ if (bw_params->clk_table.entries[i].fclk_mhz <= bw_params->dc_mode_limit.fclk_mhz)
+ num_dc_fclk_dpms++;
+ }
+ if (bw_params->clk_table.entries[i].dcfclk_mhz > 0) {
num_dcfclk_dpms++;
+ if (bw_params->clk_table.entries[i].dcfclk_mhz <= bw_params->dc_mode_limit.dcfclk_mhz)
+ num_dc_dcfclk_dpms++;
+ }
+ }
+
+ if (!disable_dc_mode_overwrite) {
+ //Overwrite max frequencies with max DC mode frequencies for DC mode systems
+ override_max_clk_values(&bw_params->dc_mode_limit, &max_clk_data);
+ num_uclk_dpms = num_dc_uclk_dpms;
+ num_fclk_dpms = num_dc_fclk_dpms;
+ num_dcfclk_dpms = num_dc_dcfclk_dpms;
+ bw_params->clk_table.num_entries_per_clk.num_memclk_levels = num_uclk_dpms;
+ bw_params->clk_table.num_entries_per_clk.num_fclk_levels = num_fclk_dpms;
}
if (num_dcfclk_dpms > 0 && bw_params->clk_table.entries[0].fclk_mhz > min_fclk_mhz)
min_fclk_mhz = bw_params->clk_table.entries[0].fclk_mhz;
- if (!max_dcfclk_mhz || !max_dispclk_mhz || !max_dtbclk_mhz)
+ if (!max_clk_data.dcfclk_mhz || !max_clk_data.dispclk_mhz || !max_clk_data.dtbclk_mhz)
return -1;
- if (max_dppclk_mhz == 0)
- max_dppclk_mhz = max_dispclk_mhz;
+ if (max_clk_data.dppclk_mhz == 0)
+ max_clk_data.dppclk_mhz = max_clk_data.dispclk_mhz;
- if (max_fclk_mhz == 0)
- max_fclk_mhz = max_dcfclk_mhz * dcn3_21_soc.pct_ideal_sdp_bw_after_urgent / dcn3_21_soc.pct_ideal_fabric_bw_after_urgent;
+ if (max_clk_data.fclk_mhz == 0)
+ max_clk_data.fclk_mhz = max_clk_data.dcfclk_mhz *
+ dcn3_2_soc.pct_ideal_sdp_bw_after_urgent /
+ dcn3_2_soc.pct_ideal_fabric_bw_after_urgent;
- if (max_phyclk_mhz == 0)
- max_phyclk_mhz = dcn3_21_soc.clock_limits[0].phyclk_mhz;
+ if (max_clk_data.phyclk_mhz == 0)
+ max_clk_data.phyclk_mhz = dcn3_2_soc.clock_limits[0].phyclk_mhz;
*num_entries = 0;
- entry.dispclk_mhz = max_dispclk_mhz;
- entry.dscclk_mhz = max_dispclk_mhz / 3;
- entry.dppclk_mhz = max_dppclk_mhz;
- entry.dtbclk_mhz = max_dtbclk_mhz;
- entry.phyclk_mhz = max_phyclk_mhz;
- entry.phyclk_d18_mhz = dcn3_21_soc.clock_limits[0].phyclk_d18_mhz;
- entry.phyclk_d32_mhz = dcn3_21_soc.clock_limits[0].phyclk_d32_mhz;
+ entry.dispclk_mhz = max_clk_data.dispclk_mhz;
+ entry.dscclk_mhz = max_clk_data.dispclk_mhz / 3;
+ entry.dppclk_mhz = max_clk_data.dppclk_mhz;
+ entry.dtbclk_mhz = max_clk_data.dtbclk_mhz;
+ entry.phyclk_mhz = max_clk_data.phyclk_mhz;
+ entry.phyclk_d18_mhz = dcn3_2_soc.clock_limits[0].phyclk_d18_mhz;
+ entry.phyclk_d32_mhz = dcn3_2_soc.clock_limits[0].phyclk_d32_mhz;
// Insert all the DCFCLK STAs
for (i = 0; i < num_dcfclk_stas; i++) {
@@ -328,7 +387,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
}
// Insert the max DCFCLK
- entry.dcfclk_mhz = max_dcfclk_mhz;
+ entry.dcfclk_mhz = max_clk_data.dcfclk_mhz;
entry.fabricclk_mhz = 0;
entry.dram_speed_mts = 0;
@@ -356,7 +415,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
// If FCLK fine grained, only insert max
else {
entry.dcfclk_mhz = 0;
- entry.fabricclk_mhz = max_fclk_mhz;
+ entry.fabricclk_mhz = max_clk_data.fclk_mhz;
entry.dram_speed_mts = 0;
dcn321_insert_entry_into_table_sorted(table, num_entries, &entry);
@@ -368,9 +427,9 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
// Remove states that require higher clocks than are supported
for (i = *num_entries - 1; i >= 0 ; i--) {
- if (table[i].dcfclk_mhz > max_dcfclk_mhz ||
- table[i].fabricclk_mhz > max_fclk_mhz ||
- table[i].dram_speed_mts > max_uclk_mhz * 16)
+ if (table[i].dcfclk_mhz > max_clk_data.dcfclk_mhz ||
+ table[i].fabricclk_mhz > max_clk_data.fclk_mhz ||
+ table[i].dram_speed_mts > max_clk_data.memclk_mhz * 16)
remove_entry_from_table_at_index(table, num_entries, i);
}
@@ -471,80 +530,78 @@ static void dcn321_get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts,
void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params)
{
dc_assert_fp_enabled();
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- /* Overrides from dc->config options */
- dcn3_21_ip.clamp_min_dcfclk = dc->config.clamp_min_dcfclk;
-
- /* Override from passed dc->bb_overrides if available*/
- if ((int)(dcn3_21_soc.sr_exit_time_us * 1000) != dc->bb_overrides.sr_exit_time_ns
- && dc->bb_overrides.sr_exit_time_ns) {
- dcn3_21_soc.sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
- }
+ /* Overrides from dc->config options */
+ dcn3_21_ip.clamp_min_dcfclk = dc->config.clamp_min_dcfclk;
- if ((int)(dcn3_21_soc.sr_enter_plus_exit_time_us * 1000)
- != dc->bb_overrides.sr_enter_plus_exit_time_ns
- && dc->bb_overrides.sr_enter_plus_exit_time_ns) {
- dcn3_21_soc.sr_enter_plus_exit_time_us =
- dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
- }
+ /* Override from passed dc->bb_overrides if available*/
+ if ((int)(dcn3_21_soc.sr_exit_time_us * 1000) != dc->bb_overrides.sr_exit_time_ns
+ && dc->bb_overrides.sr_exit_time_ns) {
+ dcn3_21_soc.sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
+ }
- if ((int)(dcn3_21_soc.urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns
- && dc->bb_overrides.urgent_latency_ns) {
- dcn3_21_soc.urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
- dcn3_21_soc.urgent_latency_pixel_data_only_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
- }
+ if ((int)(dcn3_21_soc.sr_enter_plus_exit_time_us * 1000)
+ != dc->bb_overrides.sr_enter_plus_exit_time_ns
+ && dc->bb_overrides.sr_enter_plus_exit_time_ns) {
+ dcn3_21_soc.sr_enter_plus_exit_time_us =
+ dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
+ }
- if ((int)(dcn3_21_soc.dram_clock_change_latency_us * 1000)
- != dc->bb_overrides.dram_clock_change_latency_ns
- && dc->bb_overrides.dram_clock_change_latency_ns) {
- dcn3_21_soc.dram_clock_change_latency_us =
- dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
- }
+ if ((int)(dcn3_21_soc.urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns
+ && dc->bb_overrides.urgent_latency_ns) {
+ dcn3_21_soc.urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
+ dcn3_21_soc.urgent_latency_pixel_data_only_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
+ }
- if ((int)(dcn3_21_soc.fclk_change_latency_us * 1000)
- != dc->bb_overrides.fclk_clock_change_latency_ns
- && dc->bb_overrides.fclk_clock_change_latency_ns) {
- dcn3_21_soc.fclk_change_latency_us =
- dc->bb_overrides.fclk_clock_change_latency_ns / 1000;
- }
+ if ((int)(dcn3_21_soc.dram_clock_change_latency_us * 1000)
+ != dc->bb_overrides.dram_clock_change_latency_ns
+ && dc->bb_overrides.dram_clock_change_latency_ns) {
+ dcn3_21_soc.dram_clock_change_latency_us =
+ dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
+ }
- if ((int)(dcn3_21_soc.dummy_pstate_latency_us * 1000)
- != dc->bb_overrides.dummy_clock_change_latency_ns
- && dc->bb_overrides.dummy_clock_change_latency_ns) {
- dcn3_21_soc.dummy_pstate_latency_us =
- dc->bb_overrides.dummy_clock_change_latency_ns / 1000.0;
- }
+ if ((int)(dcn3_21_soc.fclk_change_latency_us * 1000)
+ != dc->bb_overrides.fclk_clock_change_latency_ns
+ && dc->bb_overrides.fclk_clock_change_latency_ns) {
+ dcn3_21_soc.fclk_change_latency_us =
+ dc->bb_overrides.fclk_clock_change_latency_ns / 1000;
+ }
- /* Override from VBIOS if VBIOS bb_info available */
- if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
- struct bp_soc_bb_info bb_info = {0};
+ if ((int)(dcn3_21_soc.dummy_pstate_latency_us * 1000)
+ != dc->bb_overrides.dummy_clock_change_latency_ns
+ && dc->bb_overrides.dummy_clock_change_latency_ns) {
+ dcn3_21_soc.dummy_pstate_latency_us =
+ dc->bb_overrides.dummy_clock_change_latency_ns / 1000.0;
+ }
- if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
- if (bb_info.dram_clock_change_latency_100ns > 0)
- dcn3_21_soc.dram_clock_change_latency_us =
- bb_info.dram_clock_change_latency_100ns * 10;
+ /* Override from VBIOS if VBIOS bb_info available */
+ if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
+ struct bp_soc_bb_info bb_info = {0};
- if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
- dcn3_21_soc.sr_enter_plus_exit_time_us =
- bb_info.dram_sr_enter_exit_latency_100ns * 10;
+ if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
+ if (bb_info.dram_clock_change_latency_100ns > 0)
+ dcn3_21_soc.dram_clock_change_latency_us =
+ bb_info.dram_clock_change_latency_100ns * 10;
- if (bb_info.dram_sr_exit_latency_100ns > 0)
- dcn3_21_soc.sr_exit_time_us =
- bb_info.dram_sr_exit_latency_100ns * 10;
- }
- }
+ if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
+ dcn3_21_soc.sr_enter_plus_exit_time_us =
+ bb_info.dram_sr_enter_exit_latency_100ns * 10;
- /* Override from VBIOS for num_chan */
- if (dc->ctx->dc_bios->vram_info.num_chans) {
- dcn3_21_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans;
- dcn3_21_soc.mall_allocated_for_dcn_mbytes = (double)(dcn32_calc_num_avail_chans_for_mall(dc,
- dc->ctx->dc_bios->vram_info.num_chans) * dc->caps.mall_size_per_mem_channel);
+ if (bb_info.dram_sr_exit_latency_100ns > 0)
+ dcn3_21_soc.sr_exit_time_us =
+ bb_info.dram_sr_exit_latency_100ns * 10;
}
+ }
- if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
- dcn3_21_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
+ /* Override from VBIOS for num_chan */
+ if (dc->ctx->dc_bios->vram_info.num_chans) {
+ dcn3_21_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans;
+ dcn3_21_soc.mall_allocated_for_dcn_mbytes = (double)(dcn32_calc_num_avail_chans_for_mall(dc,
+ dc->ctx->dc_bios->vram_info.num_chans) * dc->caps.mall_size_per_mem_channel);
}
+ if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
+ dcn3_21_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
+
/* DML DSC delay factor workaround */
dcn3_21_ip.dsc_delay_factor_wa = dc->debug.dsc_delay_factor_wa_x1000 / 1000.0;
@@ -555,150 +612,149 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
/* Overrides Clock levelsfrom CLK Mgr table entries as reported by PM FW */
- if ((!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) && (bw_params->clk_table.entries[0].memclk_mhz)) {
- if (dc->debug.use_legacy_soc_bb_mechanism) {
- unsigned int i = 0, j = 0, num_states = 0;
-
- unsigned int dcfclk_mhz[DC__VOLTAGE_STATES] = {0};
- unsigned int dram_speed_mts[DC__VOLTAGE_STATES] = {0};
- unsigned int optimal_uclk_for_dcfclk_sta_targets[DC__VOLTAGE_STATES] = {0};
- unsigned int optimal_dcfclk_for_uclk[DC__VOLTAGE_STATES] = {0};
-
- unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {615, 906, 1324, 1564};
- unsigned int num_dcfclk_sta_targets = 4, num_uclk_states = 0;
- unsigned int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0, max_phyclk_mhz = 0;
-
- for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
- if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
- max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
- if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz)
- max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
- if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
- max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
- if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
- max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
- }
- if (!max_dcfclk_mhz)
- max_dcfclk_mhz = dcn3_21_soc.clock_limits[0].dcfclk_mhz;
- if (!max_dispclk_mhz)
- max_dispclk_mhz = dcn3_21_soc.clock_limits[0].dispclk_mhz;
- if (!max_dppclk_mhz)
- max_dppclk_mhz = dcn3_21_soc.clock_limits[0].dppclk_mhz;
- if (!max_phyclk_mhz)
- max_phyclk_mhz = dcn3_21_soc.clock_limits[0].phyclk_mhz;
-
- if (max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
- // If max DCFCLK is greater than the max DCFCLK STA target, insert into the DCFCLK STA target array
- dcfclk_sta_targets[num_dcfclk_sta_targets] = max_dcfclk_mhz;
- num_dcfclk_sta_targets++;
- } else if (max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
- // If max DCFCLK is less than the max DCFCLK STA target, cap values and remove duplicates
- for (i = 0; i < num_dcfclk_sta_targets; i++) {
- if (dcfclk_sta_targets[i] > max_dcfclk_mhz) {
- dcfclk_sta_targets[i] = max_dcfclk_mhz;
- break;
- }
+ if (dc->debug.use_legacy_soc_bb_mechanism) {
+ unsigned int i = 0, j = 0, num_states = 0;
+
+ unsigned int dcfclk_mhz[DC__VOLTAGE_STATES] = {0};
+ unsigned int dram_speed_mts[DC__VOLTAGE_STATES] = {0};
+ unsigned int optimal_uclk_for_dcfclk_sta_targets[DC__VOLTAGE_STATES] = {0};
+ unsigned int optimal_dcfclk_for_uclk[DC__VOLTAGE_STATES] = {0};
+
+ unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {615, 906, 1324, 1564};
+ unsigned int num_dcfclk_sta_targets = 4, num_uclk_states = 0;
+ unsigned int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0, max_phyclk_mhz = 0;
+
+ for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
+ if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
+ max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
+ if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz)
+ max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
+ if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
+ max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
+ if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
+ max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
+ }
+ if (!max_dcfclk_mhz)
+ max_dcfclk_mhz = dcn3_21_soc.clock_limits[0].dcfclk_mhz;
+ if (!max_dispclk_mhz)
+ max_dispclk_mhz = dcn3_21_soc.clock_limits[0].dispclk_mhz;
+ if (!max_dppclk_mhz)
+ max_dppclk_mhz = dcn3_21_soc.clock_limits[0].dppclk_mhz;
+ if (!max_phyclk_mhz)
+ max_phyclk_mhz = dcn3_21_soc.clock_limits[0].phyclk_mhz;
+
+ if (max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
+ // If max DCFCLK is greater than the max DCFCLK STA target, insert into the DCFCLK STA target array
+ dcfclk_sta_targets[num_dcfclk_sta_targets] = max_dcfclk_mhz;
+ num_dcfclk_sta_targets++;
+ } else if (max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
+ // If max DCFCLK is less than the max DCFCLK STA target, cap values and remove duplicates
+ for (i = 0; i < num_dcfclk_sta_targets; i++) {
+ if (dcfclk_sta_targets[i] > max_dcfclk_mhz) {
+ dcfclk_sta_targets[i] = max_dcfclk_mhz;
+ break;
}
- // Update size of array since we "removed" duplicates
- num_dcfclk_sta_targets = i + 1;
}
+ // Update size of array since we "removed" duplicates
+ num_dcfclk_sta_targets = i + 1;
+ }
- num_uclk_states = bw_params->clk_table.num_entries;
+ num_uclk_states = bw_params->clk_table.num_entries;
- // Calculate optimal dcfclk for each uclk
- for (i = 0; i < num_uclk_states; i++) {
- dcn321_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16,
- &optimal_dcfclk_for_uclk[i], NULL);
- if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz) {
- optimal_dcfclk_for_uclk[i] = bw_params->clk_table.entries[0].dcfclk_mhz;
- }
+ // Calculate optimal dcfclk for each uclk
+ for (i = 0; i < num_uclk_states; i++) {
+ dcn321_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16,
+ &optimal_dcfclk_for_uclk[i], NULL);
+ if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz) {
+ optimal_dcfclk_for_uclk[i] = bw_params->clk_table.entries[0].dcfclk_mhz;
}
+ }
- // Calculate optimal uclk for each dcfclk sta target
- for (i = 0; i < num_dcfclk_sta_targets; i++) {
- for (j = 0; j < num_uclk_states; j++) {
- if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) {
- optimal_uclk_for_dcfclk_sta_targets[i] =
- bw_params->clk_table.entries[j].memclk_mhz * 16;
- break;
- }
+ // Calculate optimal uclk for each dcfclk sta target
+ for (i = 0; i < num_dcfclk_sta_targets; i++) {
+ for (j = 0; j < num_uclk_states; j++) {
+ if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) {
+ optimal_uclk_for_dcfclk_sta_targets[i] =
+ bw_params->clk_table.entries[j].memclk_mhz * 16;
+ break;
}
}
+ }
- i = 0;
- j = 0;
- // create the final dcfclk and uclk table
- while (i < num_dcfclk_sta_targets && j < num_uclk_states && num_states < DC__VOLTAGE_STATES) {
- if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j] && i < num_dcfclk_sta_targets) {
- dcfclk_mhz[num_states] = dcfclk_sta_targets[i];
- dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];
+ i = 0;
+ j = 0;
+ // create the final dcfclk and uclk table
+ while (i < num_dcfclk_sta_targets && j < num_uclk_states && num_states < DC__VOLTAGE_STATES) {
+ if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j] && i < num_dcfclk_sta_targets) {
+ dcfclk_mhz[num_states] = dcfclk_sta_targets[i];
+ dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];
+ } else {
+ if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) {
+ dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];
+ dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;
} else {
- if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) {
- dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];
- dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;
- } else {
- j = num_uclk_states;
- }
+ j = num_uclk_states;
}
}
+ }
- while (i < num_dcfclk_sta_targets && num_states < DC__VOLTAGE_STATES) {
- dcfclk_mhz[num_states] = dcfclk_sta_targets[i];
- dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];
- }
+ while (i < num_dcfclk_sta_targets && num_states < DC__VOLTAGE_STATES) {
+ dcfclk_mhz[num_states] = dcfclk_sta_targets[i];
+ dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];
+ }
- while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES &&
- optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) {
- dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];
- dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;
- }
+ while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES &&
+ optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) {
+ dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];
+ dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;
+ }
- dcn3_21_soc.num_states = num_states;
- for (i = 0; i < dcn3_21_soc.num_states; i++) {
- dcn3_21_soc.clock_limits[i].state = i;
- dcn3_21_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i];
- dcn3_21_soc.clock_limits[i].fabricclk_mhz = dcfclk_mhz[i];
-
- /* Fill all states with max values of all these clocks */
- dcn3_21_soc.clock_limits[i].dispclk_mhz = max_dispclk_mhz;
- dcn3_21_soc.clock_limits[i].dppclk_mhz = max_dppclk_mhz;
- dcn3_21_soc.clock_limits[i].phyclk_mhz = max_phyclk_mhz;
- dcn3_21_soc.clock_limits[i].dscclk_mhz = max_dispclk_mhz / 3;
-
- /* Populate from bw_params for DTBCLK, SOCCLK */
- if (i > 0) {
- if (!bw_params->clk_table.entries[i].dtbclk_mhz) {
- dcn3_21_soc.clock_limits[i].dtbclk_mhz = dcn3_21_soc.clock_limits[i-1].dtbclk_mhz;
- } else {
- dcn3_21_soc.clock_limits[i].dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
- }
- } else if (bw_params->clk_table.entries[i].dtbclk_mhz) {
+ dcn3_21_soc.num_states = num_states;
+ for (i = 0; i < dcn3_21_soc.num_states; i++) {
+ dcn3_21_soc.clock_limits[i].state = i;
+ dcn3_21_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i];
+ dcn3_21_soc.clock_limits[i].fabricclk_mhz = dcfclk_mhz[i];
+
+ /* Fill all states with max values of all these clocks */
+ dcn3_21_soc.clock_limits[i].dispclk_mhz = max_dispclk_mhz;
+ dcn3_21_soc.clock_limits[i].dppclk_mhz = max_dppclk_mhz;
+ dcn3_21_soc.clock_limits[i].phyclk_mhz = max_phyclk_mhz;
+ dcn3_21_soc.clock_limits[i].dscclk_mhz = max_dispclk_mhz / 3;
+
+ /* Populate from bw_params for DTBCLK, SOCCLK */
+ if (i > 0) {
+ if (!bw_params->clk_table.entries[i].dtbclk_mhz) {
+ dcn3_21_soc.clock_limits[i].dtbclk_mhz = dcn3_21_soc.clock_limits[i-1].dtbclk_mhz;
+ } else {
dcn3_21_soc.clock_limits[i].dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
}
+ } else if (bw_params->clk_table.entries[i].dtbclk_mhz) {
+ dcn3_21_soc.clock_limits[i].dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
+ }
- if (!bw_params->clk_table.entries[i].socclk_mhz && i > 0)
- dcn3_21_soc.clock_limits[i].socclk_mhz = dcn3_21_soc.clock_limits[i-1].socclk_mhz;
- else
- dcn3_21_soc.clock_limits[i].socclk_mhz = bw_params->clk_table.entries[i].socclk_mhz;
+ if (!bw_params->clk_table.entries[i].socclk_mhz && i > 0)
+ dcn3_21_soc.clock_limits[i].socclk_mhz = dcn3_21_soc.clock_limits[i-1].socclk_mhz;
+ else
+ dcn3_21_soc.clock_limits[i].socclk_mhz = bw_params->clk_table.entries[i].socclk_mhz;
- if (!dram_speed_mts[i] && i > 0)
- dcn3_21_soc.clock_limits[i].dram_speed_mts = dcn3_21_soc.clock_limits[i-1].dram_speed_mts;
- else
- dcn3_21_soc.clock_limits[i].dram_speed_mts = dram_speed_mts[i];
+ if (!dram_speed_mts[i] && i > 0)
+ dcn3_21_soc.clock_limits[i].dram_speed_mts = dcn3_21_soc.clock_limits[i-1].dram_speed_mts;
+ else
+ dcn3_21_soc.clock_limits[i].dram_speed_mts = dram_speed_mts[i];
- /* These clocks cannot come from bw_params, always fill from dcn3_21_soc[0] */
- /* PHYCLK_D18, PHYCLK_D32 */
- dcn3_21_soc.clock_limits[i].phyclk_d18_mhz = dcn3_21_soc.clock_limits[0].phyclk_d18_mhz;
- dcn3_21_soc.clock_limits[i].phyclk_d32_mhz = dcn3_21_soc.clock_limits[0].phyclk_d32_mhz;
- }
- } else {
- build_synthetic_soc_states(bw_params, dcn3_21_soc.clock_limits, &dcn3_21_soc.num_states);
+ /* These clocks cannot come from bw_params, always fill from dcn3_21_soc[0] */
+ /* PHYCLK_D18, PHYCLK_D32 */
+ dcn3_21_soc.clock_limits[i].phyclk_d18_mhz = dcn3_21_soc.clock_limits[0].phyclk_d18_mhz;
+ dcn3_21_soc.clock_limits[i].phyclk_d32_mhz = dcn3_21_soc.clock_limits[0].phyclk_d32_mhz;
}
-
- /* Re-init DML with updated bb */
- dml_init_instance(&dc->dml, &dcn3_21_soc, &dcn3_21_ip, DML_PROJECT_DCN32);
- if (dc->current_state)
- dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_21_soc, &dcn3_21_ip, DML_PROJECT_DCN32);
+ } else {
+ build_synthetic_soc_states(dc->debug.disable_dc_mode_overwrite, bw_params,
+ dcn3_21_soc.clock_limits, &dcn3_21_soc.num_states);
}
+
+ /* Re-init DML with updated bb */
+ dml_init_instance(&dc->dml, &dcn3_21_soc, &dcn3_21_ip, DML_PROJECT_DCN32);
+ if (dc->current_state)
+ dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_21_soc, &dcn3_21_ip, DML_PROJECT_DCN32);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h
index 0bffae95f3a2..d5831a34f5a1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h
@@ -190,6 +190,14 @@ enum dm_validation_status {
DML_FAIL_DSC_INPUT_BPC,
DML_FAIL_PREFETCH_SUPPORT,
DML_FAIL_V_RATIO_PREFETCH,
+ DML_FAIL_P2I_WITH_420,
+ DML_FAIL_DSC_ONLY_IF_NECESSARY_WITH_BPP,
+ DML_FAIL_NOT_DSC422_NATIVE,
+ DML_FAIL_ODM_COMBINE4TO1,
+ DML_FAIL_ENOUGH_WRITEBACK_UNITS,
+ DML_FAIL_VIEWPORT_EXCEEDS_SURFACE,
+ DML_FAIL_DYNAMIC_METADATA,
+ DML_FAIL_FMT_BUFFER_EXCEEDED,
};
enum writeback_config {
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c
index bdf3ac6cadd5..da0cfbb071e6 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c
@@ -113,7 +113,6 @@ void dml_init_instance(struct display_mode_lib *lib,
lib->funcs = dml30_funcs;
break;
case DML_PROJECT_DCN31:
- case DML_PROJECT_DCN31_FPGA:
case DML_PROJECT_DCN315:
lib->funcs = dml31_funcs;
break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h
index a9d49ef58fb5..5edf69fa40d1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h
@@ -41,7 +41,6 @@ enum dml_project {
DML_PROJECT_DCN30,
DML_PROJECT_DCN31,
DML_PROJECT_DCN315,
- DML_PROJECT_DCN31_FPGA,
DML_PROJECT_DCN314,
DML_PROJECT_DCN32,
};
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
index 3c077164f362..ff0246a9458f 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
@@ -619,8 +619,7 @@ struct _vcs_dpi_display_dlg_regs_st {
unsigned int refcyc_h_blank_end;
unsigned int dlg_vblank_end;
unsigned int min_dst_y_next_start;
- unsigned int optimized_min_dst_y_next_start;
- unsigned int optimized_min_dst_y_next_start_us;
+ unsigned int min_dst_y_next_start_us;
unsigned int refcyc_per_htotal;
unsigned int refcyc_x_after_scaler;
unsigned int dst_y_after_scaler;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c
index f9653f511baa..9a3ded311195 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c
@@ -571,6 +571,10 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
mode_lib->vba.OutputLinkDPRate[mode_lib->vba.NumberOfActivePlanes] = dout->dp_rate;
mode_lib->vba.ODMUse[mode_lib->vba.NumberOfActivePlanes] = dst->odm_combine_policy;
mode_lib->vba.DETSizeOverride[mode_lib->vba.NumberOfActivePlanes] = src->det_size_override;
+ if (src->det_size_override)
+ mode_lib->vba.DETBufferSizeInKByte[mode_lib->vba.NumberOfActivePlanes] = src->det_size_override;
+ else
+ mode_lib->vba.DETBufferSizeInKByte[mode_lib->vba.NumberOfActivePlanes] = ip->det_buffer_size_kbytes;
//TODO: Need to assign correct values to dp_multistream vars
mode_lib->vba.OutputMultistreamEn[mode_lib->vba.NumberOfActiveSurfaces] = dout->dp_multistream_en;
mode_lib->vba.OutputMultistreamId[mode_lib->vba.NumberOfActiveSurfaces] = dout->dp_multistream_id;
@@ -785,6 +789,8 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
mode_lib->vba.pipe_plane[k] =
mode_lib->vba.NumberOfActivePlanes;
mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes]++;
+ if (src_k->det_size_override)
+ mode_lib->vba.DETBufferSizeInKByte[mode_lib->vba.NumberOfActivePlanes] = src_k->det_size_override;
if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes]
== dm_horz) {
mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] +=
@@ -927,18 +933,16 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
}
/**
- * ********************************************************************************************
* cache_debug_params: Cache any params that needed to be maintained from the initial validation
* for debug purposes.
*
* The DML getters can modify some of the VBA params that we are interested in (for example when
* calculating with dummy p-state latency), so cache any params here that we want for debugging
*
- * @param [in] mode_lib: mode_lib input/output of validate call
+ * @mode_lib: mode_lib input/output of validate call
*
- * @return: void
+ * Return: void
*
- * ********************************************************************************************
*/
static void cache_debug_params(struct display_mode_lib *mode_lib)
{
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
index 2bdc47615543..58dd62cce4bb 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
@@ -645,8 +645,6 @@ static int get_available_dsc_slices(union dsc_enc_slice_caps slice_caps, int *av
{
int idx = 0;
- memset(available_slices, -1, MIN_AVAILABLE_SLICES_SIZE);
-
if (slice_caps.bits.NUM_SLICES_1)
available_slices[idx++] = 1;
@@ -700,7 +698,7 @@ static int inc_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices)
}
}
- if (new_num_slices == num_slices) // No biger number of slices found
+ if (new_num_slices == num_slices) // No bigger number of slices found
new_num_slices++;
return new_num_slices;
@@ -952,6 +950,13 @@ static bool setup_dsc_config(
else
is_dsc_possible = false;
}
+ // When we force 2:1 ODM, we can't have 1 slice to divide amongst 2 separate DSC instances
+ // need to enforce at minimum 2 horizontal slices
+ if (options->dsc_force_odm_hslice_override) {
+ num_slices_h = fit_num_slices_up(dsc_common_caps.slice_caps, 2);
+ if (num_slices_h == 0)
+ is_dsc_possible = false;
+ }
if (!is_dsc_possible)
goto done;
@@ -1163,6 +1168,7 @@ void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable)
void dc_dsc_get_default_config_option(const struct dc *dc, struct dc_dsc_config_options *options)
{
options->dsc_min_slice_height_override = dc->debug.dsc_min_slice_height_override;
+ options->dsc_force_odm_hslice_override = dc->debug.force_odm_combine;
options->max_target_bpp_limit_override_x16 = 0;
options->slice_height_granularity = 1;
}
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index 2eb597a24425..034610b74a37 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -37,6 +37,7 @@
#include "dwb.h"
#include "mcif_wb.h"
#include "panel_cntl.h"
+#include "dmub/inc/dmub_cmd.h"
#define MAX_CLOCK_SOURCES 7
#define MAX_SVP_PHANTOM_STREAMS 2
@@ -374,6 +375,7 @@ union pipe_update_flags {
uint32_t viewport : 1;
uint32_t plane_changed : 1;
uint32_t det_size : 1;
+ uint32_t unbounded_req : 1;
} bits;
uint32_t raw;
};
@@ -426,6 +428,8 @@ struct pipe_ctx {
struct dwbc *dwbc;
struct mcif_wb *mcif_wb;
union pipe_update_flags update_flags;
+ struct tg_color visual_confirm_color;
+ bool has_vactive_margin;
};
/* Data used for dynamic link encoder assignment.
@@ -496,6 +500,11 @@ struct bw_context {
struct display_mode_lib dml;
};
+struct dc_dmub_cmd {
+ union dmub_rb_cmd dmub_cmd;
+ enum dm_dmub_wait_type wait_type;
+};
+
/**
* struct dc_state - The full description of a state requested by users
*/
@@ -544,6 +553,11 @@ struct dc_state {
*/
struct bw_context bw_ctx;
+ struct block_sequence block_sequence[50];
+ unsigned int block_sequence_steps;
+ struct dc_dmub_cmd dc_dmub_cmd[10];
+ unsigned int dmub_cmd_count;
+
/**
* @refcount: refcount reference
*
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h
index ecb4191b6e64..d2190a3320f6 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h
@@ -55,6 +55,10 @@ struct abm_funcs {
unsigned int bytes,
unsigned int inst);
bool (*set_abm_pause)(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int otg_inst);
+ bool (*set_pipe_ex)(struct abm *abm,
+ unsigned int otg_inst,
+ unsigned int option,
+ unsigned int panel_inst);
};
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
index bef843cc32a1..6faf40fa5c69 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
@@ -233,6 +233,7 @@ struct clk_bw_params {
struct clk_limit_table clk_table;
struct wm_table wm_table;
struct dummy_pstate_entry dummy_pstate_table[4];
+ struct clk_limit_table_entry dc_mode_limit;
};
/* Public interfaces */
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
index ad6acd1b34e1..8dc804bbe98b 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
@@ -68,6 +68,7 @@ struct dccg {
const struct dccg_funcs *funcs;
int pipe_dppclk_khz[MAX_PIPES];
int ref_dppclk;
+ bool dpp_clock_gated[MAX_PIPES];
//int dtbclk_khz[MAX_PIPES];/* TODO needs to be removed */
//int audio_dtbclk_khz;/* TODO needs to be removed */
//int ref_dtbclk_khz;/* TODO needs to be removed */
@@ -159,6 +160,9 @@ struct dccg_funcs {
int otg_inst,
int pixclk_khz);
+ void (*trigger_dio_fifo_resync)(
+ struct dccg *dccg);
+
void (*dpp_root_clock_control)(
struct dccg *dccg,
unsigned int dpp_inst,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
index beb26dc8a07f..aaa293613846 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -111,6 +111,9 @@ struct dcn_hubbub_state {
uint32_t vm_error_vmid;
uint32_t vm_error_pipe;
uint32_t vm_error_mode;
+ uint32_t test_debug_data;
+ uint32_t watermark_change_cntl;
+ uint32_t dram_state_cntl;
};
struct hubbub_funcs {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
index 88ac723d10aa..02ff99f7bec2 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -44,6 +44,138 @@ struct dc_virtual_addr_space_config;
struct dpp;
struct dce_hwseq;
struct link_resource;
+struct dc_dmub_cmd;
+
+struct subvp_pipe_control_lock_fast_params {
+ struct dc *dc;
+ bool lock;
+ struct pipe_ctx *pipe_ctx;
+};
+
+struct pipe_control_lock_params {
+ struct dc *dc;
+ struct pipe_ctx *pipe_ctx;
+ bool lock;
+};
+
+struct set_flip_control_gsl_params {
+ struct pipe_ctx *pipe_ctx;
+ bool flip_immediate;
+};
+
+struct program_triplebuffer_params {
+ const struct dc *dc;
+ struct pipe_ctx *pipe_ctx;
+ bool enableTripleBuffer;
+};
+
+struct update_plane_addr_params {
+ struct dc *dc;
+ struct pipe_ctx *pipe_ctx;
+};
+
+struct set_input_transfer_func_params {
+ struct dc *dc;
+ struct pipe_ctx *pipe_ctx;
+ struct dc_plane_state *plane_state;
+};
+
+struct program_gamut_remap_params {
+ struct pipe_ctx *pipe_ctx;
+};
+
+struct program_manual_trigger_params {
+ struct pipe_ctx *pipe_ctx;
+};
+
+struct send_dmcub_cmd_params {
+ struct dc_context *ctx;
+ union dmub_rb_cmd *cmd;
+ enum dm_dmub_wait_type wait_type;
+};
+
+struct setup_dpp_params {
+ struct pipe_ctx *pipe_ctx;
+};
+
+struct program_bias_and_scale_params {
+ struct pipe_ctx *pipe_ctx;
+};
+
+struct set_output_transfer_func_params {
+ struct dc *dc;
+ struct pipe_ctx *pipe_ctx;
+ const struct dc_stream_state *stream;
+};
+
+struct update_visual_confirm_params {
+ struct dc *dc;
+ struct pipe_ctx *pipe_ctx;
+ int mpcc_id;
+};
+
+struct power_on_mpc_mem_pwr_params {
+ struct mpc *mpc;
+ int mpcc_id;
+ bool power_on;
+};
+
+struct set_output_csc_params {
+ struct mpc *mpc;
+ int opp_id;
+ const uint16_t *regval;
+ enum mpc_output_csc_mode ocsc_mode;
+};
+
+struct set_ocsc_default_params {
+ struct mpc *mpc;
+ int opp_id;
+ enum dc_color_space color_space;
+ enum mpc_output_csc_mode ocsc_mode;
+};
+
+union block_sequence_params {
+ struct update_plane_addr_params update_plane_addr_params;
+ struct subvp_pipe_control_lock_fast_params subvp_pipe_control_lock_fast_params;
+ struct pipe_control_lock_params pipe_control_lock_params;
+ struct set_flip_control_gsl_params set_flip_control_gsl_params;
+ struct program_triplebuffer_params program_triplebuffer_params;
+ struct set_input_transfer_func_params set_input_transfer_func_params;
+ struct program_gamut_remap_params program_gamut_remap_params;
+ struct program_manual_trigger_params program_manual_trigger_params;
+ struct send_dmcub_cmd_params send_dmcub_cmd_params;
+ struct setup_dpp_params setup_dpp_params;
+ struct program_bias_and_scale_params program_bias_and_scale_params;
+ struct set_output_transfer_func_params set_output_transfer_func_params;
+ struct update_visual_confirm_params update_visual_confirm_params;
+ struct power_on_mpc_mem_pwr_params power_on_mpc_mem_pwr_params;
+ struct set_output_csc_params set_output_csc_params;
+ struct set_ocsc_default_params set_ocsc_default_params;
+};
+
+enum block_sequence_func {
+ DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST = 0,
+ OPTC_PIPE_CONTROL_LOCK,
+ HUBP_SET_FLIP_CONTROL_GSL,
+ HUBP_PROGRAM_TRIPLEBUFFER,
+ HUBP_UPDATE_PLANE_ADDR,
+ DPP_SET_INPUT_TRANSFER_FUNC,
+ DPP_PROGRAM_GAMUT_REMAP,
+ OPTC_PROGRAM_MANUAL_TRIGGER,
+ DMUB_SEND_DMCUB_CMD,
+ DPP_SETUP_DPP,
+ DPP_PROGRAM_BIAS_AND_SCALE,
+ DPP_SET_OUTPUT_TRANSFER_FUNC,
+ MPC_UPDATE_VISUAL_CONFIRM,
+ MPC_POWER_ON_MPC_MEM_PWR,
+ MPC_SET_OUTPUT_CSC,
+ MPC_SET_OCSC_DEFAULT,
+};
+
+struct block_sequence {
+ union block_sequence_params params;
+ enum block_sequence_func func;
+};
struct hw_sequencer_funcs {
void (*hardware_release)(struct dc *dc);
@@ -252,12 +384,12 @@ struct hw_sequencer_funcs {
const struct tg_color *solid_color,
int width, int height, int offset);
+ void (*subvp_pipe_control_lock_fast)(union block_sequence_params *params);
void (*z10_restore)(const struct dc *dc);
void (*z10_save_init)(struct dc *dc);
void (*update_visual_confirm_color)(struct dc *dc,
struct pipe_ctx *pipe_ctx,
- struct tg_color *color,
int mpcc_id);
void (*update_phantom_vp_position)(struct dc *dc,
@@ -294,6 +426,7 @@ void get_surface_visual_confirm_color(
void get_subvp_visual_confirm_color(
struct dc *dc,
+ struct dc_state *context,
struct pipe_ctx *pipe_ctx,
struct tg_color *color);
@@ -306,4 +439,36 @@ void get_mpctree_visual_confirm_color(
void get_surface_tile_visual_confirm_color(
struct pipe_ctx *pipe_ctx,
struct tg_color *color);
+
+void get_mclk_switch_visual_confirm_color(
+ struct dc *dc,
+ struct dc_state *context,
+ struct pipe_ctx *pipe_ctx,
+ struct tg_color *color);
+
+void hwss_execute_sequence(struct dc *dc,
+ struct block_sequence block_sequence[],
+ int num_steps);
+
+void hwss_build_fast_sequence(struct dc *dc,
+ struct dc_dmub_cmd *dc_dmub_cmd,
+ unsigned int dmub_cmd_count,
+ struct block_sequence block_sequence[],
+ int *num_steps,
+ struct pipe_ctx *pipe_ctx);
+
+void hwss_send_dmcub_cmd(union block_sequence_params *params);
+
+void hwss_program_manual_trigger(union block_sequence_params *params);
+
+void hwss_setup_dpp(union block_sequence_params *params);
+
+void hwss_program_bias_and_scale(union block_sequence_params *params);
+
+void hwss_power_on_mpc_mem_pwr(union block_sequence_params *params);
+
+void hwss_set_output_csc(union block_sequence_params *params);
+
+void hwss_set_ocsc_default(union block_sequence_params *params);
+
#endif /* __DC_HW_SEQUENCER_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
index 4513544559be..a151865a3a20 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
@@ -156,10 +156,12 @@ struct hwseq_private_funcs {
void (*program_mall_pipe_config)(struct dc *dc, struct dc_state *context);
void (*update_force_pstate)(struct dc *dc, struct dc_state *context);
void (*update_mall_sel)(struct dc *dc, struct dc_state *context);
- unsigned int (*calculate_dccg_k1_k2_values)(struct pipe_ctx *pipe_ctx,
+ void (*calculate_dccg_k1_k2_values)(struct pipe_ctx *pipe_ctx,
unsigned int *k1_div,
unsigned int *k2_div);
void (*set_pixels_per_cycle)(struct pipe_ctx *pipe_ctx);
+ void (*resync_fifo_dccg_dio)(struct dce_hwseq *hws, struct dc *dc,
+ struct dc_state *context);
bool (*is_dp_dig_pixel_rate_div_policy)(struct pipe_ctx *pipe_ctx);
#endif
};
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
index edd7d026a762..586fe25c1702 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
@@ -28,24 +28,6 @@
#include "dccg.h"
#include "clk_mgr.h"
-static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link)
-{
- switch (link->link_enc->transmitter) {
- case TRANSMITTER_UNIPHY_A:
- return PHYD32CLKA;
- case TRANSMITTER_UNIPHY_B:
- return PHYD32CLKB;
- case TRANSMITTER_UNIPHY_C:
- return PHYD32CLKC;
- case TRANSMITTER_UNIPHY_D:
- return PHYD32CLKD;
- case TRANSMITTER_UNIPHY_E:
- return PHYD32CLKE;
- default:
- return PHYD32CLKA;
- }
-}
-
static void set_hpo_dp_throttled_vcp_size(struct pipe_ctx *pipe_ctx,
struct fixed31_32 throttled_vcp_size)
{
@@ -120,81 +102,26 @@ static void setup_hpo_dp_stream_attribute(struct pipe_ctx *pipe_ctx)
DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR);
}
-static void enable_hpo_dp_fpga_link_output(struct dc_link *link,
- const struct link_resource *link_res,
- enum signal_type signal,
- enum clock_source_id clock_source,
- const struct dc_link_settings *link_settings)
-{
- const struct dc *dc = link->dc;
- enum phyd32clk_clock_source phyd32clk = get_phyd32clk_src(link);
- int phyd32clk_freq_khz = link_settings->link_rate == LINK_RATE_UHBR10 ? 312500 :
- link_settings->link_rate == LINK_RATE_UHBR13_5 ? 412875 :
- link_settings->link_rate == LINK_RATE_UHBR20 ? 625000 : 0;
-
- dm_set_phyd32clk(dc->ctx, phyd32clk_freq_khz);
- dc->res_pool->dccg->funcs->set_physymclk(
- dc->res_pool->dccg,
- link->link_enc_hw_inst,
- PHYSYMCLK_FORCE_SRC_PHYD32CLK,
- true);
- dc->res_pool->dccg->funcs->enable_symclk32_le(
- dc->res_pool->dccg,
- link_res->hpo_dp_link_enc->inst,
- phyd32clk);
- link_res->hpo_dp_link_enc->funcs->link_enable(
- link_res->hpo_dp_link_enc,
- link_settings->lane_count);
-
-}
-
static void enable_hpo_dp_link_output(struct dc_link *link,
const struct link_resource *link_res,
enum signal_type signal,
enum clock_source_id clock_source,
const struct dc_link_settings *link_settings)
{
- if (IS_FPGA_MAXIMUS_DC(link->dc->ctx->dce_environment))
- enable_hpo_dp_fpga_link_output(link, link_res, signal,
- clock_source, link_settings);
- else
- link_res->hpo_dp_link_enc->funcs->enable_link_phy(
- link_res->hpo_dp_link_enc,
- link_settings,
- link->link_enc->transmitter,
- link->link_enc->hpd_source);
-}
-
-
-static void disable_hpo_dp_fpga_link_output(struct dc_link *link,
- const struct link_resource *link_res,
- enum signal_type signal)
-{
- const struct dc *dc = link->dc;
-
- link_res->hpo_dp_link_enc->funcs->link_disable(link_res->hpo_dp_link_enc);
- dc->res_pool->dccg->funcs->disable_symclk32_le(
- dc->res_pool->dccg,
- link_res->hpo_dp_link_enc->inst);
- dc->res_pool->dccg->funcs->set_physymclk(
- dc->res_pool->dccg,
- link->link_enc_hw_inst,
- PHYSYMCLK_FORCE_SRC_SYMCLK,
- false);
- dm_set_phyd32clk(dc->ctx, 0);
+ link_res->hpo_dp_link_enc->funcs->enable_link_phy(
+ link_res->hpo_dp_link_enc,
+ link_settings,
+ link->link_enc->transmitter,
+ link->link_enc->hpd_source);
}
static void disable_hpo_dp_link_output(struct dc_link *link,
const struct link_resource *link_res,
enum signal_type signal)
{
- if (IS_FPGA_MAXIMUS_DC(link->dc->ctx->dce_environment)) {
- disable_hpo_dp_fpga_link_output(link, link_res, signal);
- } else {
link_res->hpo_dp_link_enc->funcs->link_disable(link_res->hpo_dp_link_enc);
link_res->hpo_dp_link_enc->funcs->disable_link_phy(
link_res->hpo_dp_link_enc, signal);
- }
}
static void set_hpo_dp_link_test_pattern(struct dc_link *link,
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
index d471d58aba92..8041b8369e45 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -593,6 +593,10 @@ static bool detect_dp(struct dc_link *link,
/* DP SST branch */
link->type = dc_connection_sst_branch;
} else {
+ if (link->dc->debug.disable_dp_plus_plus_wa &&
+ link->link_enc->features.flags.bits.IS_UHBR20_CAPABLE)
+ return false;
+
/* DP passive dongles */
sink_caps->signal = dp_passive_dongle_detection(link->ddc,
sink_caps,
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index 2267fb097830..1a7b93e41e35 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -765,7 +765,7 @@ static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
struct dc_stream_state *stream = pipe_ctx->stream;
bool result = false;
- if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
+ if (dc_is_virtual_signal(stream->signal))
result = true;
else
result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable);
@@ -778,7 +778,6 @@ static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
{
struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
- struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dc_stream_state *stream = pipe_ctx->stream;
struct pipe_ctx *odm_pipe;
int opp_cnt = 1;
@@ -816,8 +815,7 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
/* Enable DSC in encoder */
- if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)
- && !dp_is_128b_132b_signal(pipe_ctx)) {
+ if (dc_is_dp_signal(stream->signal) && !dp_is_128b_132b_signal(pipe_ctx)) {
DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
dsc_optc_config_log(dsc, &dsc_optc_cfg);
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
@@ -849,7 +847,7 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
false,
NULL,
true);
- else if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
+ else {
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
pipe_ctx->stream_res.stream_enc,
OPTC_DSC_DISABLED, 0, 0);
@@ -2209,9 +2207,8 @@ static enum dc_status enable_link(
* link settings. Need to call disable first before enabling at
* new link settings.
*/
- if (link->link_status.link_active) {
+ if (link->link_status.link_active && !stream->skip_edp_power_down)
disable_link(link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
- }
switch (pipe_ctx->stream->signal) {
case SIGNAL_TYPE_DISPLAY_PORT:
@@ -2271,8 +2268,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
}
}
- if (!IS_DIAG_DC(dc->ctx->dce_environment) &&
- dc_is_virtual_signal(pipe_ctx->stream->signal))
+ if (dc_is_virtual_signal(pipe_ctx->stream->signal))
return;
if (!pipe_ctx->stream->sink->edid_caps.panel_patch.skip_avmute) {
@@ -2330,7 +2326,9 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
dc->hwss.disable_stream(pipe_ctx);
} else {
dc->hwss.disable_stream(pipe_ctx);
- disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
+ if (!pipe_ctx->stream->skip_edp_power_down) {
+ disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
+ }
}
if (pipe_ctx->stream->timing.flags.DSC) {
@@ -2358,6 +2356,8 @@ void link_set_dpms_on(
enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO;
struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg;
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
+ bool apply_edp_fast_boot_optimization =
+ pipe_ctx->stream->apply_edp_fast_boot_optimization;
ASSERT(is_master_pipe_for_link(link, pipe_ctx));
@@ -2375,8 +2375,7 @@ void link_set_dpms_on(
}
}
- if (!IS_DIAG_DC(dc->ctx->dce_environment) &&
- dc_is_virtual_signal(pipe_ctx->stream->signal))
+ if (dc_is_virtual_signal(pipe_ctx->stream->signal))
return;
link_enc = link_enc_cfg_get_link_enc(link);
@@ -2402,138 +2401,126 @@ void link_set_dpms_on(
link_hwss->setup_stream_attribute(pipe_ctx);
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- bool apply_edp_fast_boot_optimization =
- pipe_ctx->stream->apply_edp_fast_boot_optimization;
-
- pipe_ctx->stream->apply_edp_fast_boot_optimization = false;
+ pipe_ctx->stream->apply_edp_fast_boot_optimization = false;
- // Enable VPG before building infoframe
- if (vpg && vpg->funcs->vpg_poweron)
- vpg->funcs->vpg_poweron(vpg);
+ // Enable VPG before building infoframe
+ if (vpg && vpg->funcs->vpg_poweron)
+ vpg->funcs->vpg_poweron(vpg);
- resource_build_info_frame(pipe_ctx);
- dc->hwss.update_info_frame(pipe_ctx);
+ resource_build_info_frame(pipe_ctx);
+ dc->hwss.update_info_frame(pipe_ctx);
- if (dc_is_dp_signal(pipe_ctx->stream->signal))
- dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);
-
- /* Do not touch link on seamless boot optimization. */
- if (pipe_ctx->stream->apply_seamless_boot_optimization) {
- pipe_ctx->stream->dpms_off = false;
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);
- /* Still enable stream features & audio on seamless boot for DP external displays */
- if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) {
- enable_stream_features(pipe_ctx);
- dc->hwss.enable_audio_stream(pipe_ctx);
- }
+ /* Do not touch link on seamless boot optimization. */
+ if (pipe_ctx->stream->apply_seamless_boot_optimization) {
+ pipe_ctx->stream->dpms_off = false;
- update_psp_stream_config(pipe_ctx, false);
- return;
- }
-
- /* eDP lit up by bios already, no need to enable again. */
- if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP &&
- apply_edp_fast_boot_optimization &&
- !pipe_ctx->stream->timing.flags.DSC &&
- !pipe_ctx->next_odm_pipe) {
- pipe_ctx->stream->dpms_off = false;
- update_psp_stream_config(pipe_ctx, false);
- return;
+ /* Still enable stream features & audio on seamless boot for DP external displays */
+ if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) {
+ enable_stream_features(pipe_ctx);
+ dc->hwss.enable_audio_stream(pipe_ctx);
}
- if (pipe_ctx->stream->dpms_off)
- return;
+ update_psp_stream_config(pipe_ctx, false);
+ return;
+ }
- /* Have to setup DSC before DIG FE and BE are connected (which happens before the
- * link training). This is to make sure the bandwidth sent to DIG BE won't be
- * bigger than what the link and/or DIG BE can handle. VBID[6]/CompressedStream_flag
- * will be automatically set at a later time when the video is enabled
- * (DP_VID_STREAM_EN = 1).
- */
- if (pipe_ctx->stream->timing.flags.DSC) {
- if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
- dc_is_virtual_signal(pipe_ctx->stream->signal))
- link_set_dsc_enable(pipe_ctx, true);
+ /* eDP lit up by bios already, no need to enable again. */
+ if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP &&
+ apply_edp_fast_boot_optimization &&
+ !pipe_ctx->stream->timing.flags.DSC &&
+ !pipe_ctx->next_odm_pipe) {
+ pipe_ctx->stream->dpms_off = false;
+ update_psp_stream_config(pipe_ctx, false);
+ return;
+ }
- }
+ if (pipe_ctx->stream->dpms_off)
+ return;
- status = enable_link(state, pipe_ctx);
+ /* Have to setup DSC before DIG FE and BE are connected (which happens before the
+ * link training). This is to make sure the bandwidth sent to DIG BE won't be
+ * bigger than what the link and/or DIG BE can handle. VBID[6]/CompressedStream_flag
+ * will be automatically set at a later time when the video is enabled
+ * (DP_VID_STREAM_EN = 1).
+ */
+ if (pipe_ctx->stream->timing.flags.DSC) {
+ if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
+ dc_is_virtual_signal(pipe_ctx->stream->signal))
+ link_set_dsc_enable(pipe_ctx, true);
- if (status != DC_OK) {
- DC_LOG_WARNING("enabling link %u failed: %d\n",
- pipe_ctx->stream->link->link_index,
- status);
+ }
- /* Abort stream enable *unless* the failure was due to
- * DP link training - some DP monitors will recover and
- * show the stream anyway. But MST displays can't proceed
- * without link training.
- */
- if (status != DC_FAIL_DP_LINK_TRAINING ||
- pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
- if (false == stream->link->link_status.link_active)
- disable_link(stream->link, &pipe_ctx->link_res,
- pipe_ctx->stream->signal);
- BREAK_TO_DEBUGGER();
- return;
- }
- }
+ status = enable_link(state, pipe_ctx);
- /* turn off otg test pattern if enable */
- if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
- pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
- CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
- COLOR_DEPTH_UNDEFINED);
+ if (status != DC_OK) {
+ DC_LOG_WARNING("enabling link %u failed: %d\n",
+ pipe_ctx->stream->link->link_index,
+ status);
- /* This second call is needed to reconfigure the DIG
- * as a workaround for the incorrect value being applied
- * from transmitter control.
+ /* Abort stream enable *unless* the failure was due to
+ * DP link training - some DP monitors will recover and
+ * show the stream anyway. But MST displays can't proceed
+ * without link training.
*/
- if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) ||
- dp_is_128b_132b_signal(pipe_ctx))) {
- if (link_enc)
- link_enc->funcs->setup(
- link_enc,
+ if (status != DC_FAIL_DP_LINK_TRAINING ||
+ pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+ if (false == stream->link->link_status.link_active)
+ disable_link(stream->link, &pipe_ctx->link_res,
pipe_ctx->stream->signal);
- }
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+ }
- dc->hwss.enable_stream(pipe_ctx);
+ /* turn off otg test pattern if enable */
+ if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
+ pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
+ CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
+ COLOR_DEPTH_UNDEFINED);
- /* Set DPS PPS SDP (AKA "info frames") */
- if (pipe_ctx->stream->timing.flags.DSC) {
- if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
- dc_is_virtual_signal(pipe_ctx->stream->signal)) {
- dp_set_dsc_on_rx(pipe_ctx, true);
- link_set_dsc_pps_packet(pipe_ctx, true, true);
- }
+ /* This second call is needed to reconfigure the DIG
+ * as a workaround for the incorrect value being applied
+ * from transmitter control.
+ */
+ if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) ||
+ dp_is_128b_132b_signal(pipe_ctx))) {
+ if (link_enc)
+ link_enc->funcs->setup(
+ link_enc,
+ pipe_ctx->stream->signal);
}
- if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
- allocate_mst_payload(pipe_ctx);
- else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
- dp_is_128b_132b_signal(pipe_ctx))
- update_sst_payload(pipe_ctx, true);
+ dc->hwss.enable_stream(pipe_ctx);
+
+ /* Set DPS PPS SDP (AKA "info frames") */
+ if (pipe_ctx->stream->timing.flags.DSC) {
+ if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
+ dc_is_virtual_signal(pipe_ctx->stream->signal)) {
+ dp_set_dsc_on_rx(pipe_ctx, true);
+ link_set_dsc_pps_packet(pipe_ctx, true, true);
+ }
+ }
- dc->hwss.unblank_stream(pipe_ctx,
- &pipe_ctx->stream->link->cur_link_settings);
+ if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+ allocate_mst_payload(pipe_ctx);
+ else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
+ dp_is_128b_132b_signal(pipe_ctx))
+ update_sst_payload(pipe_ctx, true);
- if (stream->sink_patches.delay_ignore_msa > 0)
- msleep(stream->sink_patches.delay_ignore_msa);
+ dc->hwss.unblank_stream(pipe_ctx,
+ &pipe_ctx->stream->link->cur_link_settings);
- if (dc_is_dp_signal(pipe_ctx->stream->signal))
- enable_stream_features(pipe_ctx);
- update_psp_stream_config(pipe_ctx, false);
+ if (stream->sink_patches.delay_ignore_msa > 0)
+ msleep(stream->sink_patches.delay_ignore_msa);
- dc->hwss.enable_audio_stream(pipe_ctx);
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ enable_stream_features(pipe_ctx);
+ update_psp_stream_config(pipe_ctx, false);
- } else { // if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
- if (dp_is_128b_132b_signal(pipe_ctx))
- dp_fpga_hpo_enable_link_and_stream(state, pipe_ctx);
- if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
- dc_is_virtual_signal(pipe_ctx->stream->signal))
- link_set_dsc_enable(pipe_ctx, true);
- }
+ dc->hwss.enable_audio_stream(pipe_ctx);
if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
set_avmute(pipe_ctx, false);
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
index 1515c817f03b..ac1c3e2e7c1d 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
@@ -563,11 +563,9 @@ static bool construct_phy(struct dc_link *link,
goto create_fail;
}
- /* TODO: #DAL3 Implement id to str function.*/
- LINK_INFO("Connector[%d] description:"
- "signal %d\n",
+ LINK_INFO("Connector[%d] description: signal: %s\n",
init_params->connector_index,
- link->connector_signal);
+ signal_type_to_string(link->connector_signal));
ddc_service_init_data.ctx = link->ctx;
ddc_service_init_data.id = link->link_id;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
index ba98013fecd0..3a5e80b57711 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
@@ -326,8 +326,7 @@ bool dp_is_fec_supported(const struct dc_link *link)
return (dc_is_dp_signal(link->connector_signal) && link_enc &&
link_enc->features.fec_supported &&
- link->dpcd_caps.fec_cap.bits.FEC_CAPABLE &&
- !IS_FPGA_MAXIMUS_DC(link->ctx->dce_environment));
+ link->dpcd_caps.fec_cap.bits.FEC_CAPABLE);
}
bool dp_should_enable_fec(const struct dc_link *link)
@@ -1043,9 +1042,7 @@ static enum dc_status wake_up_aux_channel(struct dc_link *link)
DP_SET_POWER,
&dpcd_power_state,
sizeof(dpcd_power_state));
- if (status < 0)
- DC_LOG_DC("%s: Failed to power up sink: %s\n", __func__,
- dpcd_power_state == DP_SET_POWER_D0 ? "D0" : "D3");
+ DC_LOG_DC("%s: Failed to power up sink\n", __func__);
return DC_ERROR_UNEXPECTED;
}
@@ -1396,7 +1393,7 @@ static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id)
cmd.cable_id.header.payload_bytes = sizeof(cmd.cable_id.data);
cmd.cable_id.data.input.phy_inst = resource_transmitter_to_phy_idx(
link->dc, link->link_enc->transmitter);
- if (dc_dmub_srv_cmd_with_reply_data(link->ctx->dmub_srv, &cmd) &&
+ if (dm_execute_dmub_cmd(link->dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) &&
cmd.cable_id.header.ret_status == 1) {
cable_id->raw = cmd.cable_id.data.output_raw;
DC_LOG_DC("usbc_cable_id = %d.\n", cable_id->raw);
@@ -1452,7 +1449,8 @@ bool read_is_mst_supported(struct dc_link *link)
*/
static bool dpcd_read_sink_ext_caps(struct dc_link *link)
{
- uint8_t dpcd_data;
+ uint8_t dpcd_data = 0;
+ uint8_t edp_general_cap2 = 0;
if (!link)
return false;
@@ -1461,6 +1459,12 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link)
return false;
link->dpcd_sink_ext_caps.raw = dpcd_data;
+
+ if (core_link_read_dpcd(link, DP_EDP_GENERAL_CAP_2, &edp_general_cap2, 1) != DC_OK)
+ return false;
+
+ link->dpcd_caps.panel_luminance_control = (edp_general_cap2 & DP_EDP_PANEL_LUMINANCE_CONTROL_CAPABLE) != 0;
+
return true;
}
@@ -1554,6 +1558,9 @@ static bool retrieve_link_cap(struct dc_link *link)
int i;
struct dp_sink_hw_fw_revision dp_hw_fw_revision;
const uint32_t post_oui_delay = 30; // 30ms
+ bool is_fec_supported = false;
+ bool is_dsc_basic_supported = false;
+ bool is_dsc_passthrough_supported = false;
memset(dpcd_data, '\0', sizeof(dpcd_data));
memset(&down_strm_port_count,
@@ -1696,6 +1703,7 @@ static bool retrieve_link_cap(struct dc_link *link)
/* TODO - decouple raw mst capability from policy decision */
link->dpcd_caps.is_mst_capable = read_is_mst_supported(link);
+ DC_LOG_DC("%s: MST_Support: %s\n", __func__, str_yes_no(link->dpcd_caps.is_mst_capable));
get_active_converter_info(ds_port.byte, link);
@@ -1803,6 +1811,17 @@ static bool retrieve_link_cap(struct dc_link *link)
DP_DSC_SUPPORT,
link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw));
+ if (status == DC_OK) {
+ is_fec_supported = link->dpcd_caps.fec_cap.bits.FEC_CAPABLE;
+ is_dsc_basic_supported = link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT;
+ is_dsc_passthrough_supported = link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT;
+ DC_LOG_DC("%s: FEC_Sink_Support: %s\n", __func__,
+ str_yes_no(is_fec_supported));
+ DC_LOG_DC("%s: DSC_Basic_Sink_Support: %s\n", __func__,
+ str_yes_no(is_dsc_basic_supported));
+ DC_LOG_DC("%s: DSC_Passthrough_Sink_Support: %s\n", __func__,
+ str_yes_no(is_dsc_passthrough_supported));
+ }
if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
status = core_link_read_dpcd(
link,
@@ -1931,6 +1950,9 @@ void detect_edp_sink_caps(struct dc_link *link)
link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 +
supported_link_rates[entry]) * 200;
+ DC_LOG_DC("%s: eDP v1.4 supported sink rates: [%d] %d kHz\n", __func__,
+ entry / 2, link_rate_in_khz);
+
if (link_rate_in_khz != 0) {
link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz);
link->dpcd_caps.edp_supported_link_rates[link->dpcd_caps.edp_supported_link_rates_count] = link_rate;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c
index 4626fabc0a96..0bb749133909 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c
@@ -90,7 +90,7 @@ bool dpia_query_hpd_status(struct dc_link *link)
cmd.query_hpd.data.ch_type = AUX_CHANNEL_DPIA;
/* Return HPD status reported by DMUB if query successfully executed. */
- if (dc_dmub_srv_cmd_with_reply_data(dmub_srv, &cmd) && cmd.query_hpd.data.status == AUX_RET_SUCCESS)
+ if (dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && cmd.query_hpd.data.status == AUX_RET_SUCCESS)
is_hpd_high = cmd.query_hpd.data.result;
DC_LOG_DEBUG("%s: link(%d) dpia(%d) cmd_status(%d) result(%d)\n",
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
index 579fa222810d..e011df4bdaf2 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
@@ -1653,10 +1653,19 @@ bool perform_link_training_with_retries(
break;
}
- DC_LOG_WARNING("%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) @ spread = %x : fail reason:(%d)\n",
- __func__, link->link_index, (unsigned int)j + 1, attempts,
- cur_link_settings.link_rate, cur_link_settings.lane_count,
- cur_link_settings.link_spread, status);
+ if (j == (attempts - 1)) {
+ DC_LOG_WARNING(
+ "%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) @ spread = %x : fail reason:(%d)\n",
+ __func__, link->link_index, (unsigned int)j + 1, attempts,
+ cur_link_settings.link_rate, cur_link_settings.lane_count,
+ cur_link_settings.link_spread, status);
+ } else {
+ DC_LOG_HW_LINK_TRAINING(
+ "%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) @ spread = %x : fail reason:(%d)\n",
+ __func__, link->link_index, (unsigned int)j + 1, attempts,
+ cur_link_settings.link_rate, cur_link_settings.lane_count,
+ cur_link_settings.link_spread, status);
+ }
dp_disable_link_phy(link, &pipe_ctx->link_res, signal);
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c
index 23d380f09a21..db87cfe37b5c 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c
@@ -211,11 +211,17 @@ enum link_training_result dp_perform_128b_132b_link_training(
dpcd_set_link_settings(link, lt_settings);
- if (result == LINK_TRAINING_SUCCESS)
+ if (result == LINK_TRAINING_SUCCESS) {
result = dp_perform_128b_132b_channel_eq_done_sequence(link, link_res, lt_settings);
+ if (result == LINK_TRAINING_SUCCESS)
+ DC_LOG_HW_LINK_TRAINING("%s: Channel EQ done.\n", __func__);
+ }
- if (result == LINK_TRAINING_SUCCESS)
+ if (result == LINK_TRAINING_SUCCESS) {
result = dp_perform_128b_132b_cds_done_sequence(link, link_res, lt_settings);
+ if (result == LINK_TRAINING_SUCCESS)
+ DC_LOG_HW_LINK_TRAINING("%s: CDS done.\n", __func__);
+ }
return result;
}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c
index 3889ebb2256b..2b4c15b0b407 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c
@@ -388,6 +388,8 @@ enum link_training_result dp_perform_8b_10b_link_training(
link_res,
lt_settings,
repeater_id);
+ if (status == LINK_TRAINING_SUCCESS)
+ DC_LOG_HW_LINK_TRAINING("%s: Channel EQ done.\n", __func__);
repeater_training_done(link, repeater_id);
@@ -409,6 +411,8 @@ enum link_training_result dp_perform_8b_10b_link_training(
link_res,
lt_settings,
DPRX);
+ if (status == LINK_TRAINING_SUCCESS)
+ DC_LOG_HW_LINK_TRAINING("%s: Channel EQ done.\n", __func__);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c
index 5731c4b61f9f..15faaf645b14 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c
@@ -233,7 +233,7 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
const uint8_t vendor_lttpr_write_data_intercept_en[4] = {0x1, 0x55, 0x63, 0x0};
const uint8_t vendor_lttpr_write_data_intercept_dis[4] = {0x1, 0x55, 0x63, 0x68};
- uint32_t pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa;
+ uint32_t pre_disable_intercept_delay_ms = 0;
uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
uint32_t vendor_lttpr_write_address = 0xF004F;
@@ -244,6 +244,10 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
uint8_t toggle_rate;
uint8_t rate;
+ if (link->local_sink)
+ pre_disable_intercept_delay_ms =
+ link->local_sink->edid_caps.panel_patch.delay_disable_aux_intercept_ms;
+
/* Only 8b/10b is supported */
ASSERT(link_dp_get_encoding_format(&lt_settings->link_settings) ==
DP_8b_10b_ENCODING);
@@ -259,7 +263,7 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
/* Certain display and cable configuration require extra delay */
if (offset > 2)
- pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa * 2;
+ pre_disable_intercept_delay_ms = pre_disable_intercept_delay_ms * 2;
}
/* Vendor specific: Reset lane settings */
@@ -380,7 +384,8 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
0);
/* Vendor specific: Disable intercept */
for (i = 0; i < max_vendor_dpcd_retries; i++) {
- msleep(pre_disable_intercept_delay_ms);
+ if (pre_disable_intercept_delay_ms != 0)
+ msleep(pre_disable_intercept_delay_ms);
dpcd_status = core_link_write_dpcd(
link,
vendor_lttpr_write_address,
@@ -591,10 +596,9 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
const uint8_t vendor_lttpr_write_data_adicora_eq1[4] = {0x1, 0x55, 0x63, 0x2E};
const uint8_t vendor_lttpr_write_data_adicora_eq2[4] = {0x1, 0x55, 0x63, 0x01};
const uint8_t vendor_lttpr_write_data_adicora_eq3[4] = {0x1, 0x55, 0x63, 0x68};
- uint32_t pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa;
uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
-
+ uint32_t pre_disable_intercept_delay_ms = 0;
uint32_t vendor_lttpr_write_address = 0xF004F;
enum link_training_result status = LINK_TRAINING_SUCCESS;
uint8_t lane = 0;
@@ -603,6 +607,10 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
uint8_t toggle_rate;
uint8_t rate;
+ if (link->local_sink)
+ pre_disable_intercept_delay_ms =
+ link->local_sink->edid_caps.panel_patch.delay_disable_aux_intercept_ms;
+
/* Only 8b/10b is supported */
ASSERT(link_dp_get_encoding_format(&lt_settings->link_settings) ==
DP_8b_10b_ENCODING);
@@ -618,7 +626,7 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
/* Certain display and cable configuration require extra delay */
if (offset > 2)
- pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa * 2;
+ pre_disable_intercept_delay_ms = pre_disable_intercept_delay_ms * 2;
}
/* Vendor specific: Reset lane settings */
@@ -739,7 +747,8 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
0);
/* Vendor specific: Disable intercept */
for (i = 0; i < max_vendor_dpcd_retries; i++) {
- msleep(pre_disable_intercept_delay_ms);
+ if (pre_disable_intercept_delay_ms != 0)
+ msleep(pre_disable_intercept_delay_ms);
dpcd_status = core_link_write_dpcd(
link,
vendor_lttpr_write_address,
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
index 8d1df863659c..2039a345f23a 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
@@ -165,14 +165,35 @@ bool edp_set_backlight_level_nits(struct dc_link *link,
*(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms;
- if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
+ if (!link->dpcd_caps.panel_luminance_control) {
+ if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
(uint8_t *)(&dpcd_backlight_set),
sizeof(dpcd_backlight_set)) != DC_OK)
- return false;
+ return false;
- if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL,
+ if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL,
&backlight_control, 1) != DC_OK)
- return false;
+ return false;
+ } else {
+ const uint8_t backlight_enable = DP_EDP_PANEL_LUMINANCE_CONTROL_ENABLE;
+ struct target_luminance_value *target_luminance = NULL;
+
+ //if target luminance value is greater than 24 bits, clip the value to 24 bits
+ if (backlight_millinits > 0xFFFFFF)
+ backlight_millinits = 0xFFFFFF;
+
+ target_luminance = (struct target_luminance_value *)&backlight_millinits;
+
+ if (core_link_write_dpcd(link, DP_EDP_BACKLIGHT_MODE_SET_REGISTER,
+ &backlight_enable,
+ sizeof(backlight_enable)) != DC_OK)
+ return false;
+
+ if (core_link_write_dpcd(link, DP_EDP_PANEL_TARGET_LUMINANCE_VALUE,
+ (uint8_t *)(target_luminance),
+ sizeof(struct target_luminance_value)) != DC_OK)
+ return false;
+ }
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
index ba1715e2d25a..7c9a2b34bd05 100644
--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
@@ -271,7 +271,7 @@ struct dmub_srv_hw_params {
*/
struct dmub_diagnostic_data {
uint32_t dmcub_version;
- uint32_t scratch[16];
+ uint32_t scratch[17];
uint32_t pc;
uint32_t undefined_address_fault_addr;
uint32_t inst_fetch_fault_addr;
@@ -282,6 +282,7 @@ struct dmub_diagnostic_data {
uint32_t inbox0_rptr;
uint32_t inbox0_wptr;
uint32_t inbox0_size;
+ uint32_t gpint_datain0;
uint8_t is_dmcub_enabled : 1;
uint8_t is_dmcub_soft_reset : 1;
uint8_t is_dmcub_secure_reset : 1;
@@ -340,6 +341,8 @@ struct dmub_srv_hw_funcs {
void (*setup_mailbox)(struct dmub_srv *dmub,
const struct dmub_region *inbox1);
+ uint32_t (*get_inbox1_wptr)(struct dmub_srv *dmub);
+
uint32_t (*get_inbox1_rptr)(struct dmub_srv *dmub);
void (*set_inbox1_wptr)(struct dmub_srv *dmub, uint32_t wptr_offset);
@@ -366,7 +369,6 @@ struct dmub_srv_hw_funcs {
bool (*is_hw_init)(struct dmub_srv *dmub);
- bool (*is_phy_init)(struct dmub_srv *dmub);
void (*enable_dmub_boot_options)(struct dmub_srv *dmub,
const struct dmub_srv_hw_params *params);
@@ -602,6 +604,18 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub);
/**
+ * dmub_srv_sync_inbox1() - sync sw state with hw state
+ * @dmub: the dmub service
+ *
+ * Sync sw state with hw state when resume from S0i3
+ *
+ * Return:
+ * DMUB_STATUS_OK - success
+ * DMUB_STATUS_INVALID - unspecified error
+ */
+enum dmub_status dmub_srv_sync_inbox1(struct dmub_srv *dmub);
+
+/**
* dmub_srv_cmd_queue() - queues a command to the DMUB
* @dmub: the dmub service
* @cmd: the command to queue
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
index 598fa1de54ce..af1f50742371 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -257,7 +257,9 @@ struct dmub_feature_caps {
*/
uint8_t psr;
uint8_t fw_assisted_mclk_switch;
- uint8_t reserved[6];
+ uint8_t reserved[4];
+ uint8_t subvp_psr_support;
+ uint8_t gecc_enable;
};
struct dmub_visual_confirm_color {
@@ -360,7 +362,7 @@ union dmub_fw_boot_status {
uint32_t optimized_init_done : 1; /**< 1 if optimized init done */
uint32_t restore_required : 1; /**< 1 if driver should call restore */
uint32_t defer_load : 1; /**< 1 if VBIOS data is deferred programmed */
- uint32_t reserved : 1;
+ uint32_t fams_enabled : 1; /**< 1 if VBIOS data is deferred programmed */
uint32_t detection_required: 1; /**< if detection need to be triggered by driver */
uint32_t hw_power_init_done: 1; /**< 1 if hw power init is completed */
} bits; /**< status bits */
@@ -376,6 +378,7 @@ enum dmub_fw_boot_status_bit {
DMUB_FW_BOOT_STATUS_BIT_OPTIMIZED_INIT_DONE = (1 << 2), /**< 1 if init done */
DMUB_FW_BOOT_STATUS_BIT_RESTORE_REQUIRED = (1 << 3), /**< 1 if driver should call restore */
DMUB_FW_BOOT_STATUS_BIT_DEFERRED_LOADED = (1 << 4), /**< 1 if VBIOS data is deferred programmed */
+ DMUB_FW_BOOT_STATUS_BIT_FAMS_ENABLED = (1 << 5), /**< 1 if FAMS is enabled*/
DMUB_FW_BOOT_STATUS_BIT_DETECTION_REQUIRED = (1 << 6), /**< 1 if detection need to be triggered by driver*/
DMUB_FW_BOOT_STATUS_BIT_HW_POWER_INIT_DONE = (1 << 7), /**< 1 if hw power init is completed */
};
@@ -395,6 +398,12 @@ enum dmub_lvtma_status_bit {
DMUB_LVTMA_STATUS_BIT_EDP_ON = (1 << 1),
};
+enum dmub_ips_disable_type {
+ DMUB_IPS_DISABLE_IPS1 = 1,
+ DMUB_IPS_DISABLE_IPS2 = 2,
+ DMUB_IPS_DISABLE_IPS2_Z10 = 3,
+};
+
/**
* union dmub_fw_boot_options - Boot option definitions for SCRATCH14
*/
@@ -419,7 +428,10 @@ union dmub_fw_boot_options {
uint32_t dpia_hpd_int_enable_supported: 1; /* 1 if dpia hpd int enable supported */
uint32_t usb4_dpia_bw_alloc_supported: 1; /* 1 if USB4 dpia BW allocation supported */
uint32_t disable_clk_ds: 1; /* 1 if disallow dispclk_ds and dppclk_ds*/
- uint32_t reserved : 14; /**< reserved */
+ uint32_t disable_timeout_recovery : 1; /* 1 if timeout recovery should be disabled */
+ uint32_t ips_pg_disable: 1; /* 1 to disable ONO domains power gating*/
+ uint32_t ips_disable: 2; /* options to disable ips support*/
+ uint32_t reserved : 10; /**< reserved */
} bits; /**< boot bits */
uint32_t all; /**< 32-bit access to bits */
};
@@ -988,16 +1000,25 @@ struct dmub_rb_cmd_mall {
};
/**
- * enum dmub_cmd_cab_type - TODO:
+ * enum dmub_cmd_cab_type - CAB command data.
*/
enum dmub_cmd_cab_type {
+ /**
+ * No idle optimizations (i.e. no CAB)
+ */
DMUB_CMD__CAB_NO_IDLE_OPTIMIZATION = 0,
+ /**
+ * No DCN requests for memory
+ */
DMUB_CMD__CAB_NO_DCN_REQ = 1,
+ /**
+ * Fit surfaces in CAB (i.e. CAB enable)
+ */
DMUB_CMD__CAB_DCN_SS_FIT_IN_CAB = 2,
};
/**
- * struct dmub_rb_cmd_cab_for_ss - TODO:
+ * struct dmub_rb_cmd_cab - CAB command data.
*/
struct dmub_rb_cmd_cab_for_ss {
struct dmub_cmd_header header;
@@ -1005,6 +1026,9 @@ struct dmub_rb_cmd_cab_for_ss {
uint8_t debug_bits; /* debug bits */
};
+/**
+ * Enum for indicating which MCLK switch mode per pipe
+ */
enum mclk_switch_mode {
NONE = 0,
FPO = 1,
@@ -1125,8 +1149,6 @@ struct dmub_rb_cmd_idle_opt_dcn_restore {
*/
struct dmub_dcn_notify_idle_cntl_data {
uint8_t driver_idle;
- uint8_t d3_entry;
- uint8_t trigger;
uint8_t pad[1];
};
@@ -3550,6 +3572,10 @@ union dmub_rb_cmd {
* Definition of a DMUB_CMD__DPIA_HPD_INT_ENABLE command.
*/
struct dmub_rb_cmd_dpia_hpd_int_enable dpia_hpd_int_enable;
+ /**
+ * Definition of a DMUB_CMD__IDLE_OPT_DCN_NOTIFY_IDLE command.
+ */
+ struct dmub_rb_cmd_idle_opt_dcn_notify_idle idle_opt_notify_idle;
};
/**
diff --git a/drivers/gpu/drm/amd/display/dmub/src/Makefile b/drivers/gpu/drm/amd/display/dmub/src/Makefile
index 0589ad4778ee..caf095aca8f3 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/Makefile
+++ b/drivers/gpu/drm/amd/display/dmub/src/Makefile
@@ -22,7 +22,7 @@
DMUB = dmub_srv.o dmub_srv_stat.o dmub_reg.o dmub_dcn20.o dmub_dcn21.o
DMUB += dmub_dcn30.o dmub_dcn301.o dmub_dcn302.o dmub_dcn303.o
-DMUB += dmub_dcn31.o dmub_dcn315.o dmub_dcn316.o
+DMUB += dmub_dcn31.o dmub_dcn314.o dmub_dcn315.o dmub_dcn316.o
DMUB += dmub_dcn32.o
AMD_DAL_DMUB = $(addprefix $(AMDDALPATH)/dmub/src/,$(DMUB))
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
index a6540e27044d..98dad0d47e72 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
@@ -282,6 +282,11 @@ void dmub_dcn20_setup_mailbox(struct dmub_srv *dmub,
REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
}
+uint32_t dmub_dcn20_get_inbox1_wptr(struct dmub_srv *dmub)
+{
+ return REG_READ(DMCUB_INBOX1_WPTR);
+}
+
uint32_t dmub_dcn20_get_inbox1_rptr(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_INBOX1_RPTR);
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
index c2e5831ac52c..1df128e57ed3 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
@@ -202,6 +202,8 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
void dmub_dcn20_setup_mailbox(struct dmub_srv *dmub,
const struct dmub_region *inbox1);
+uint32_t dmub_dcn20_get_inbox1_wptr(struct dmub_srv *dmub);
+
uint32_t dmub_dcn20_get_inbox1_rptr(struct dmub_srv *dmub);
void dmub_dcn20_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset);
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c
index 51bb9bceb1b1..2d212bc974cc 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c
@@ -54,9 +54,3 @@ const struct dmub_srv_common_regs dmub_srv_dcn21_regs = {
#undef DMUB_SF
};
-/* Shared functions. */
-
-bool dmub_dcn21_is_phy_init(struct dmub_srv *dmub)
-{
- return REG_READ(DMCUB_SCRATCH10) == 0;
-}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h
index 6fd5b0cd4ef3..8c4033ae4007 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h
@@ -32,8 +32,4 @@
extern const struct dmub_srv_common_regs dmub_srv_dcn21_regs;
-/* Hardware functions. */
-
-bool dmub_dcn21_is_phy_init(struct dmub_srv *dmub);
-
#endif /* _DMUB_DCN21_H_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
index c90b9ee42e12..ebf7aeec4029 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
@@ -242,6 +242,11 @@ void dmub_dcn31_setup_mailbox(struct dmub_srv *dmub,
REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
}
+uint32_t dmub_dcn31_get_inbox1_wptr(struct dmub_srv *dmub)
+{
+ return REG_READ(DMCUB_INBOX1_WPTR);
+}
+
uint32_t dmub_dcn31_get_inbox1_rptr(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_INBOX1_RPTR);
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
index f6db6f89d45d..7d5c10ee539b 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
@@ -204,6 +204,8 @@ void dmub_dcn31_setup_windows(struct dmub_srv *dmub,
void dmub_dcn31_setup_mailbox(struct dmub_srv *dmub,
const struct dmub_region *inbox1);
+uint32_t dmub_dcn31_get_inbox1_wptr(struct dmub_srv *dmub);
+
uint32_t dmub_dcn31_get_inbox1_rptr(struct dmub_srv *dmub);
void dmub_dcn31_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset);
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c
new file mode 100644
index 000000000000..48a06dbd9be7
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "../dmub_srv.h"
+#include "dmub_reg.h"
+#include "dmub_dcn314.h"
+
+#include "dcn/dcn_3_1_4_offset.h"
+#include "dcn/dcn_3_1_4_sh_mask.h"
+
+#define DCN_BASE__INST0_SEG0 0x00000012
+#define DCN_BASE__INST0_SEG1 0x000000C0
+#define DCN_BASE__INST0_SEG2 0x000034C0
+#define DCN_BASE__INST0_SEG3 0x00009000
+#define DCN_BASE__INST0_SEG4 0x02403C00
+#define DCN_BASE__INST0_SEG5 0
+
+#define BASE_INNER(seg) DCN_BASE__INST0_SEG##seg
+#define CTX dmub
+#define REGS dmub->regs_dcn31
+#define REG_OFFSET_EXP(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name)
+
+/* Registers. */
+
+const struct dmub_srv_dcn31_regs dmub_srv_dcn314_regs = {
+#define DMUB_SR(reg) REG_OFFSET_EXP(reg),
+ {
+ DMUB_DCN31_REGS()
+ DMCUB_INTERNAL_REGS()
+ },
+#undef DMUB_SR
+
+#define DMUB_SF(reg, field) FD_MASK(reg, field),
+ { DMUB_DCN31_FIELDS() },
+#undef DMUB_SF
+
+#define DMUB_SF(reg, field) FD_SHIFT(reg, field),
+ { DMUB_DCN31_FIELDS() },
+#undef DMUB_SF
+};
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h
new file mode 100644
index 000000000000..674267a2940e
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef _DMUB_DCN314_H_
+#define _DMUB_DCN314_H_
+
+#include "dmub_dcn31.h"
+
+extern const struct dmub_srv_dcn31_regs dmub_srv_dcn314_regs;
+
+#endif /* _DMUB_DCN314_H_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
index 9c20516be066..bf5994e292d9 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
@@ -116,10 +116,6 @@ void dmub_dcn32_reset(struct dmub_srv *dmub)
break;
}
- /* Clear the GPINT command manually so we don't reset again. */
- cmd.all = 0;
- dmub->hw_funcs.set_gpint(dmub, cmd);
-
/* Force reset in case we timed out, DMCUB is likely hung. */
}
@@ -133,6 +129,10 @@ void dmub_dcn32_reset(struct dmub_srv *dmub)
REG_WRITE(DMCUB_OUTBOX0_RPTR, 0);
REG_WRITE(DMCUB_OUTBOX0_WPTR, 0);
REG_WRITE(DMCUB_SCRATCH0, 0);
+
+ /* Clear the GPINT command manually so we don't reset again. */
+ cmd.all = 0;
+ dmub->hw_funcs.set_gpint(dmub, cmd);
}
void dmub_dcn32_reset_release(struct dmub_srv *dmub)
@@ -266,6 +266,11 @@ void dmub_dcn32_setup_mailbox(struct dmub_srv *dmub,
REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
}
+uint32_t dmub_dcn32_get_inbox1_wptr(struct dmub_srv *dmub)
+{
+ return REG_READ(DMCUB_INBOX1_WPTR);
+}
+
uint32_t dmub_dcn32_get_inbox1_rptr(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_INBOX1_RPTR);
@@ -434,6 +439,7 @@ void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti
diag_data->scratch[13] = REG_READ(DMCUB_SCRATCH13);
diag_data->scratch[14] = REG_READ(DMCUB_SCRATCH14);
diag_data->scratch[15] = REG_READ(DMCUB_SCRATCH15);
+ diag_data->scratch[16] = REG_READ(DMCUB_SCRATCH16);
diag_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR);
diag_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR);
@@ -464,6 +470,8 @@ void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
diag_data->is_cw6_enabled = is_cw6_enabled;
+
+ diag_data->gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0);
}
void dmub_dcn32_configure_dmub_in_system_memory(struct dmub_srv *dmub)
{
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h
index 7d1a6eb4d665..d58a1e4b9f1c 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h
@@ -107,6 +107,7 @@ struct dmub_srv;
DMUB_SR(DMCUB_SCRATCH15) \
DMUB_SR(DMCUB_SCRATCH16) \
DMUB_SR(DMCUB_SCRATCH17) \
+ DMUB_SR(DMCUB_GPINT_DATAIN0) \
DMUB_SR(DMCUB_GPINT_DATAIN1) \
DMUB_SR(DMCUB_GPINT_DATAOUT) \
DMUB_SR(CC_DC_PIPE_DIS) \
@@ -206,6 +207,8 @@ void dmub_dcn32_setup_windows(struct dmub_srv *dmub,
void dmub_dcn32_setup_mailbox(struct dmub_srv *dmub,
const struct dmub_region *inbox1);
+uint32_t dmub_dcn32_get_inbox1_wptr(struct dmub_srv *dmub);
+
uint32_t dmub_dcn32_get_inbox1_rptr(struct dmub_srv *dmub);
void dmub_dcn32_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset);
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
index 92c18bfb98b3..9e9a6a44a7ac 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
@@ -32,6 +32,7 @@
#include "dmub_dcn302.h"
#include "dmub_dcn303.h"
#include "dmub_dcn31.h"
+#include "dmub_dcn314.h"
#include "dmub_dcn315.h"
#include "dmub_dcn316.h"
#include "dmub_dcn32.h"
@@ -166,6 +167,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
funcs->backdoor_load = dmub_dcn20_backdoor_load;
funcs->setup_windows = dmub_dcn20_setup_windows;
funcs->setup_mailbox = dmub_dcn20_setup_mailbox;
+ funcs->get_inbox1_wptr = dmub_dcn20_get_inbox1_wptr;
funcs->get_inbox1_rptr = dmub_dcn20_get_inbox1_rptr;
funcs->set_inbox1_wptr = dmub_dcn20_set_inbox1_wptr;
funcs->is_supported = dmub_dcn20_is_supported;
@@ -190,11 +192,9 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
funcs->get_diagnostic_data = dmub_dcn20_get_diagnostic_data;
- if (asic == DMUB_ASIC_DCN21) {
+ if (asic == DMUB_ASIC_DCN21)
dmub->regs = &dmub_srv_dcn21_regs;
- funcs->is_phy_init = dmub_dcn21_is_phy_init;
- }
if (asic == DMUB_ASIC_DCN30) {
dmub->regs = &dmub_srv_dcn30_regs;
@@ -226,7 +226,9 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
case DMUB_ASIC_DCN314:
case DMUB_ASIC_DCN315:
case DMUB_ASIC_DCN316:
- if (asic == DMUB_ASIC_DCN315)
+ if (asic == DMUB_ASIC_DCN314)
+ dmub->regs_dcn31 = &dmub_srv_dcn314_regs;
+ else if (asic == DMUB_ASIC_DCN315)
dmub->regs_dcn31 = &dmub_srv_dcn315_regs;
else if (asic == DMUB_ASIC_DCN316)
dmub->regs_dcn31 = &dmub_srv_dcn316_regs;
@@ -237,6 +239,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
funcs->backdoor_load = dmub_dcn31_backdoor_load;
funcs->setup_windows = dmub_dcn31_setup_windows;
funcs->setup_mailbox = dmub_dcn31_setup_mailbox;
+ funcs->get_inbox1_wptr = dmub_dcn31_get_inbox1_wptr;
funcs->get_inbox1_rptr = dmub_dcn31_get_inbox1_rptr;
funcs->set_inbox1_wptr = dmub_dcn31_set_inbox1_wptr;
funcs->setup_out_mailbox = dmub_dcn31_setup_out_mailbox;
@@ -275,6 +278,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
funcs->backdoor_load_zfb_mode = dmub_dcn32_backdoor_load_zfb_mode;
funcs->setup_windows = dmub_dcn32_setup_windows;
funcs->setup_mailbox = dmub_dcn32_setup_mailbox;
+ funcs->get_inbox1_wptr = dmub_dcn32_get_inbox1_wptr;
funcs->get_inbox1_rptr = dmub_dcn32_get_inbox1_rptr;
funcs->set_inbox1_wptr = dmub_dcn32_set_inbox1_wptr;
funcs->setup_out_mailbox = dmub_dcn32_setup_out_mailbox;
@@ -644,6 +648,20 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
return DMUB_STATUS_OK;
}
+enum dmub_status dmub_srv_sync_inbox1(struct dmub_srv *dmub)
+{
+ if (!dmub->sw_init)
+ return DMUB_STATUS_INVALID;
+
+ if (dmub->hw_funcs.get_inbox1_rptr && dmub->hw_funcs.get_inbox1_wptr) {
+ dmub->inbox1_rb.rptr = dmub->hw_funcs.get_inbox1_rptr(dmub);
+ dmub->inbox1_rb.wrpt = dmub->hw_funcs.get_inbox1_wptr(dmub);
+ dmub->inbox1_last_wptr = dmub->inbox1_rb.wrpt;
+ }
+
+ return DMUB_STATUS_OK;
+}
+
enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub)
{
if (!dmub->sw_init)
@@ -721,27 +739,6 @@ enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub,
return DMUB_STATUS_TIMEOUT;
}
-enum dmub_status dmub_srv_wait_for_phy_init(struct dmub_srv *dmub,
- uint32_t timeout_us)
-{
- uint32_t i = 0;
-
- if (!dmub->hw_init)
- return DMUB_STATUS_INVALID;
-
- if (!dmub->hw_funcs.is_phy_init)
- return DMUB_STATUS_OK;
-
- for (i = 0; i <= timeout_us; i += 10) {
- if (dmub->hw_funcs.is_phy_init(dmub))
- return DMUB_STATUS_OK;
-
- udelay(10);
- }
-
- return DMUB_STATUS_TIMEOUT;
-}
-
enum dmub_status dmub_srv_wait_for_idle(struct dmub_srv *dmub,
uint32_t timeout_us)
{
diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h
index ece97ae0e826..d4cf7ead1d87 100644
--- a/drivers/gpu/drm/amd/display/include/fixed31_32.h
+++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h
@@ -525,7 +525,7 @@ static inline struct fixed31_32 dc_fixpt_truncate(struct fixed31_32 arg, unsigne
if (negative)
arg.value = -arg.value;
- arg.value &= (~0LL) << (FIXED31_32_BITS_PER_FRACTIONAL_PART - frac_bits);
+ arg.value &= (~0ULL) << (FIXED31_32_BITS_PER_FRACTIONAL_PART - frac_bits);
if (negative)
arg.value = -arg.value;
return arg;
diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h
index 23a308c3eccb..325c5ba4c82a 100644
--- a/drivers/gpu/drm/amd/display/include/signal_types.h
+++ b/drivers/gpu/drm/amd/display/include/signal_types.h
@@ -44,6 +44,34 @@ enum signal_type {
SIGNAL_TYPE_VIRTUAL = (1 << 9), /* Virtual Display */
};
+static inline const char *signal_type_to_string(const int type)
+{
+ switch (type) {
+ case SIGNAL_TYPE_NONE:
+ return "No signal";
+ case SIGNAL_TYPE_DVI_SINGLE_LINK:
+ return "DVI: Single Link";
+ case SIGNAL_TYPE_DVI_DUAL_LINK:
+ return "DVI: Dual Link";
+ case SIGNAL_TYPE_HDMI_TYPE_A:
+ return "HDMI: TYPE A";
+ case SIGNAL_TYPE_LVDS:
+ return "LVDS";
+ case SIGNAL_TYPE_RGB:
+ return "RGB";
+ case SIGNAL_TYPE_DISPLAY_PORT:
+ return "Display Port";
+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
+ return "Display Port: MST";
+ case SIGNAL_TYPE_EDP:
+ return "Embedded Display Port";
+ case SIGNAL_TYPE_VIRTUAL:
+ return "Virtual";
+ default:
+ return "Unknown";
+ }
+}
+
/* help functions for signal types manipulation */
static inline bool dc_is_hdmi_tmds_signal(enum signal_type signal)
{
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index 5c41a4751db4..dbd60811f95d 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Advanced Micro Devices, Inc.
+ * Copyright 2016-2023 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -989,6 +989,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
unsigned int refresh_range = 0;
unsigned long long min_refresh_in_uhz = 0;
unsigned long long max_refresh_in_uhz = 0;
+ unsigned long long min_hardware_refresh_in_uhz = 0;
if (mod_freesync == NULL)
return;
@@ -999,7 +1000,13 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
nominal_field_rate_in_uhz =
mod_freesync_calc_nominal_field_rate(stream);
- min_refresh_in_uhz = in_config->min_refresh_in_uhz;
+ if (stream->ctx->dc->caps.max_v_total != 0 && stream->timing.h_total != 0) {
+ min_hardware_refresh_in_uhz = div64_u64((stream->timing.pix_clk_100hz * 100000000ULL),
+ (stream->timing.h_total * stream->ctx->dc->caps.max_v_total));
+ }
+ /* Limit minimum refresh rate to what can be supported by hardware */
+ min_refresh_in_uhz = min_hardware_refresh_in_uhz > in_config->min_refresh_in_uhz ?
+ min_hardware_refresh_in_uhz : in_config->min_refresh_in_uhz;
max_refresh_in_uhz = in_config->max_refresh_in_uhz;
/* Full range may be larger than current video timing, so cap at nominal */
@@ -1137,10 +1144,6 @@ void mod_freesync_handle_preflip(struct mod_freesync *mod_freesync,
if (in_out_vrr->supported &&
in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE) {
- unsigned int oldest_index = plane->time.index + 1;
-
- if (oldest_index >= DC_PLANE_UPDATE_TIMES_MAX)
- oldest_index = 0;
last_render_time_in_us = curr_time_stamp_in_us -
plane->time.prev_update_time_in_us;
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
index 51e76bce92ea..30349881a283 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
@@ -116,6 +116,27 @@ static const struct abm_parameters * const abm_settings[] = {
abm_settings_config2,
};
+static const struct dm_bl_data_point custom_backlight_curve0[] = {
+ {2, 14}, {4, 16}, {6, 18}, {8, 21}, {10, 23}, {12, 26}, {14, 29}, {16, 32}, {18, 35},
+ {20, 38}, {22, 41}, {24, 44}, {26, 48}, {28, 52}, {30, 55}, {32, 59}, {34, 62},
+ {36, 67}, {38, 71}, {40, 75}, {42, 80}, {44, 84}, {46, 88}, {48, 93}, {50, 98},
+ {52, 103}, {54, 108}, {56, 113}, {58, 118}, {60, 123}, {62, 129}, {64, 135}, {66, 140},
+ {68, 146}, {70, 152}, {72, 158}, {74, 164}, {76, 171}, {78, 177}, {80, 183}, {82, 190},
+ {84, 197}, {86, 204}, {88, 211}, {90, 218}, {92, 225}, {94, 232}, {96, 240}, {98, 247}};
+
+struct custom_backlight_profile {
+ uint8_t ac_level_percentage;
+ uint8_t dc_level_percentage;
+ uint8_t min_input_signal;
+ uint8_t max_input_signal;
+ uint8_t num_data_points;
+ const struct dm_bl_data_point *data_points;
+};
+
+static const struct custom_backlight_profile custom_backlight_profiles[] = {
+ {100, 32, 12, 255, ARRAY_SIZE(custom_backlight_curve0), custom_backlight_curve0},
+};
+
#define NUM_AMBI_LEVEL 5
#define NUM_AGGR_LEVEL 4
#define NUM_POWER_FN_SEGS 8
@@ -944,3 +965,25 @@ bool psr_su_set_dsc_slice_height(struct dc *dc, struct dc_link *link,
return true;
}
+
+bool fill_custom_backlight_caps(unsigned int config_no, struct dm_acpi_atif_backlight_caps *caps)
+{
+ unsigned int data_points_size;
+
+ if (config_no >= ARRAY_SIZE(custom_backlight_profiles))
+ return false;
+
+ data_points_size = custom_backlight_profiles[config_no].num_data_points
+ * sizeof(custom_backlight_profiles[config_no].data_points[0]);
+
+ caps->size = sizeof(struct dm_acpi_atif_backlight_caps) - sizeof(caps->data_points) + data_points_size;
+ caps->flags = 0;
+ caps->error_code = 0;
+ caps->ac_level_percentage = custom_backlight_profiles[config_no].ac_level_percentage;
+ caps->dc_level_percentage = custom_backlight_profiles[config_no].dc_level_percentage;
+ caps->min_input_signal = custom_backlight_profiles[config_no].min_input_signal;
+ caps->max_input_signal = custom_backlight_profiles[config_no].max_input_signal;
+ caps->num_data_points = custom_backlight_profiles[config_no].num_data_points;
+ memcpy(caps->data_points, custom_backlight_profiles[config_no].data_points, data_points_size);
+ return true;
+}
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
index 1d3079e56799..ffc924c9991b 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
@@ -62,4 +62,7 @@ bool mod_power_only_edp(const struct dc_state *context,
bool psr_su_set_dsc_slice_height(struct dc *dc, struct dc_link *link,
struct dc_stream_state *stream,
struct psr_config *config);
+
+bool fill_custom_backlight_caps(unsigned int config_no,
+ struct dm_acpi_atif_backlight_caps *caps);
#endif /* MODULES_POWER_POWER_HELPERS_H_ */
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h
index e4a22c68517d..f175e65b853a 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -240,7 +240,6 @@ enum DC_FEATURE_MASK {
DC_DISABLE_LTTPR_DP2_0 = (1 << 6), //0x40, disabled by default
DC_PSR_ALLOW_SMU_OPT = (1 << 7), //0x80, disabled by default
DC_PSR_ALLOW_MULTI_DISP_OPT = (1 << 8), //0x100, disabled by default
- DC_ENABLE_SUBVP_DRR = (1 << 9), // 0x200, disabled by default
};
enum DC_DEBUG_MASK {
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_offset.h
index 79c41004c0b6..4908044f7409 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_offset.h
@@ -5194,6 +5194,20 @@
#define mmSPI_WCL_PIPE_PERCENT_CS6_BASE_IDX 0
#define mmSPI_WCL_PIPE_PERCENT_CS7 0x1f70
#define mmSPI_WCL_PIPE_PERCENT_CS7_BASE_IDX 0
+#define mmSPI_GDBG_WAVE_CNTL 0x1f71
+#define mmSPI_GDBG_WAVE_CNTL_BASE_IDX 0
+#define mmSPI_GDBG_TRAP_CONFIG 0x1f72
+#define mmSPI_GDBG_TRAP_CONFIG_BASE_IDX 0
+#define mmSPI_GDBG_TRAP_MASK 0x1f73
+#define mmSPI_GDBG_TRAP_MASK_BASE_IDX 0
+#define mmSPI_GDBG_WAVE_CNTL2 0x1f74
+#define mmSPI_GDBG_WAVE_CNTL2_BASE_IDX 0
+#define mmSPI_GDBG_WAVE_CNTL3 0x1f75
+#define mmSPI_GDBG_WAVE_CNTL3_BASE_IDX 0
+#define mmSPI_GDBG_TRAP_DATA0 0x1f78
+#define mmSPI_GDBG_TRAP_DATA0_BASE_IDX 0
+#define mmSPI_GDBG_TRAP_DATA1 0x1f79
+#define mmSPI_GDBG_TRAP_DATA1_BASE_IDX 0
#define mmSPI_COMPUTE_QUEUE_RESET 0x1f7b
#define mmSPI_COMPUTE_QUEUE_RESET_BASE_IDX 0
#define mmSPI_RESOURCE_RESERVE_CU_0 0x1f7c
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_sh_mask.h
index 52043e143067..9b7d219e7954 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_sh_mask.h
@@ -19700,6 +19700,75 @@
//SPI_WCL_PIPE_PERCENT_CS7
#define SPI_WCL_PIPE_PERCENT_CS7__VALUE__SHIFT 0x0
#define SPI_WCL_PIPE_PERCENT_CS7__VALUE_MASK 0x7FL
+//SPI_GDBG_WAVE_CNTL
+#define SPI_GDBG_WAVE_CNTL__STALL_RA__SHIFT 0x0
+#define SPI_GDBG_WAVE_CNTL__STALL_VMID__SHIFT 0x1
+#define SPI_GDBG_WAVE_CNTL__STALL_RA_MASK 0x00000001L
+#define SPI_GDBG_WAVE_CNTL__STALL_VMID_MASK 0x0001FFFEL
+//SPI_GDBG_TRAP_CONFIG
+#define SPI_GDBG_TRAP_CONFIG__ME_SEL__SHIFT 0x0
+#define SPI_GDBG_TRAP_CONFIG__PIPE_SEL__SHIFT 0x2
+#define SPI_GDBG_TRAP_CONFIG__QUEUE_SEL__SHIFT 0x4
+#define SPI_GDBG_TRAP_CONFIG__ME_MATCH__SHIFT 0x7
+#define SPI_GDBG_TRAP_CONFIG__PIPE_MATCH__SHIFT 0x8
+#define SPI_GDBG_TRAP_CONFIG__QUEUE_MATCH__SHIFT 0x9
+#define SPI_GDBG_TRAP_CONFIG__TRAP_EN__SHIFT 0xf
+#define SPI_GDBG_TRAP_CONFIG__VMID_SEL__SHIFT 0x10
+#define SPI_GDBG_TRAP_CONFIG__ME_SEL_MASK 0x00000003L
+#define SPI_GDBG_TRAP_CONFIG__PIPE_SEL_MASK 0x0000000CL
+#define SPI_GDBG_TRAP_CONFIG__QUEUE_SEL_MASK 0x00000070L
+#define SPI_GDBG_TRAP_CONFIG__ME_MATCH_MASK 0x00000080L
+#define SPI_GDBG_TRAP_CONFIG__PIPE_MATCH_MASK 0x00000100L
+#define SPI_GDBG_TRAP_CONFIG__QUEUE_MATCH_MASK 0x00000200L
+#define SPI_GDBG_TRAP_CONFIG__TRAP_EN_MASK 0x00008000L
+#define SPI_GDBG_TRAP_CONFIG__VMID_SEL_MASK 0xFFFF0000L
+//SPI_GDBG_TRAP_MASK
+#define SPI_GDBG_TRAP_MASK__EXCP_EN__SHIFT 0x0
+#define SPI_GDBG_TRAP_MASK__REPLACE__SHIFT 0x9
+#define SPI_GDBG_TRAP_MASK__EXCP_EN_MASK 0x01FFL
+#define SPI_GDBG_TRAP_MASK__REPLACE_MASK 0x0200L
+//SPI_GDBG_WAVE_CNTL2
+#define SPI_GDBG_WAVE_CNTL2__VMID_MASK__SHIFT 0x0
+#define SPI_GDBG_WAVE_CNTL2__MODE__SHIFT 0x10
+#define SPI_GDBG_WAVE_CNTL2__VMID_MASK_MASK 0x0000FFFFL
+#define SPI_GDBG_WAVE_CNTL2__MODE_MASK 0x00030000L
+//SPI_GDBG_WAVE_CNTL3
+#define SPI_GDBG_WAVE_CNTL3__STALL_PS__SHIFT 0x0
+#define SPI_GDBG_WAVE_CNTL3__STALL_VS__SHIFT 0x1
+#define SPI_GDBG_WAVE_CNTL3__STALL_GS__SHIFT 0x2
+#define SPI_GDBG_WAVE_CNTL3__STALL_HS__SHIFT 0x3
+#define SPI_GDBG_WAVE_CNTL3__STALL_CSG__SHIFT 0x4
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS0__SHIFT 0x5
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS1__SHIFT 0x6
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS2__SHIFT 0x7
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS3__SHIFT 0x8
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS4__SHIFT 0x9
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS5__SHIFT 0xa
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS6__SHIFT 0xb
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS7__SHIFT 0xc
+#define SPI_GDBG_WAVE_CNTL3__STALL_DURATION__SHIFT 0xd
+#define SPI_GDBG_WAVE_CNTL3__STALL_MULT__SHIFT 0x1c
+#define SPI_GDBG_WAVE_CNTL3__STALL_PS_MASK 0x00000001L
+#define SPI_GDBG_WAVE_CNTL3__STALL_VS_MASK 0x00000002L
+#define SPI_GDBG_WAVE_CNTL3__STALL_GS_MASK 0x00000004L
+#define SPI_GDBG_WAVE_CNTL3__STALL_HS_MASK 0x00000008L
+#define SPI_GDBG_WAVE_CNTL3__STALL_CSG_MASK 0x00000010L
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS0_MASK 0x00000020L
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS1_MASK 0x00000040L
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS2_MASK 0x00000080L
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS3_MASK 0x00000100L
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS4_MASK 0x00000200L
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS5_MASK 0x00000400L
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS6_MASK 0x00000800L
+#define SPI_GDBG_WAVE_CNTL3__STALL_CS7_MASK 0x00001000L
+#define SPI_GDBG_WAVE_CNTL3__STALL_DURATION_MASK 0x0FFFE000L
+#define SPI_GDBG_WAVE_CNTL3__STALL_MULT_MASK 0x10000000L
+//SPI_GDBG_TRAP_DATA0
+#define SPI_GDBG_TRAP_DATA0__DATA__SHIFT 0x0
+#define SPI_GDBG_TRAP_DATA0__DATA_MASK 0xFFFFFFFFL
+//SPI_GDBG_TRAP_DATA1
+#define SPI_GDBG_TRAP_DATA1__DATA__SHIFT 0x0
+#define SPI_GDBG_TRAP_DATA1__DATA_MASK 0xFFFFFFFFL
//SPI_COMPUTE_QUEUE_RESET
#define SPI_COMPUTE_QUEUE_RESET__RESET__SHIFT 0x0
#define SPI_COMPUTE_QUEUE_RESET__RESET_MASK 0x01L
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h
index a734abaa91a5..5e15ac14b63c 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h
@@ -26,6 +26,8 @@
#define mmSQ_DEBUG_STS_GLOBAL_BASE_IDX 0
#define mmSQ_DEBUG_STS_GLOBAL2 0x10B0
#define mmSQ_DEBUG_STS_GLOBAL2_BASE_IDX 0
+#define mmSQ_DEBUG 0x10B1
+#define mmSQ_DEBUG_BASE_IDX 0
// addressBlock: gc_sdma0_sdma0dec
// base address: 0x4980
@@ -4853,10 +4855,18 @@
#define mmSPI_WCL_PIPE_PERCENT_CS3_BASE_IDX 0
#define mmSPI_GDBG_WAVE_CNTL 0x1f71
#define mmSPI_GDBG_WAVE_CNTL_BASE_IDX 0
+#define mmSPI_GDBG_TRAP_CONFIG 0x1f72
+#define mmSPI_GDBG_TRAP_CONFIG_BASE_IDX 0
#define mmSPI_GDBG_TRAP_MASK 0x1f73
#define mmSPI_GDBG_TRAP_MASK_BASE_IDX 0
#define mmSPI_GDBG_WAVE_CNTL2 0x1f74
#define mmSPI_GDBG_WAVE_CNTL2_BASE_IDX 0
+#define mmSPI_GDBG_WAVE_CNTL3 0x1f75
+#define mmSPI_GDBG_WAVE_CNTL3_BASE_IDX 0
+#define mmSPI_GDBG_TRAP_DATA0 0x1f78
+#define mmSPI_GDBG_TRAP_DATA0_BASE_IDX 0
+#define mmSPI_GDBG_TRAP_DATA1 0x1f79
+#define mmSPI_GDBG_TRAP_DATA1_BASE_IDX 0
#define mmSPI_COMPUTE_QUEUE_RESET 0x1f7b
#define mmSPI_COMPUTE_QUEUE_RESET_BASE_IDX 0
#define mmSPI_RESOURCE_RESERVE_CU_0 0x1f7c
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h
index d7a17bae2584..e4ecd6c2d20e 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h
@@ -47907,6 +47907,10 @@
// addressBlock: sqind
+//SQ_DEBUG
+#define SQ_DEBUG__SINGLE_MEMOP_MASK 0x00000001L
+#define SQ_DEBUG__SINGLE_MEMOP__SHIFT 0x00000000
+
//SQ_DEBUG_STS_GLOBAL
#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX0_MASK 0x000000ffL
#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX0__SHIFT 0x00000000
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_0_0_sh_mask.h
index 4f08f90856fc..3088a4a13cb5 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_0_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_0_0_sh_mask.h
@@ -17216,11 +17216,15 @@
#define SPI_GDBG_PER_VMID_CNTL__TRAP_EN__SHIFT 0x3
#define SPI_GDBG_PER_VMID_CNTL__EXCP_EN__SHIFT 0x4
#define SPI_GDBG_PER_VMID_CNTL__EXCP_REPLACE__SHIFT 0xd
+#define SPI_GDBG_PER_VMID_CNTL__TRAP_ON_START__SHIFT 0xe
+#define SPI_GDBG_PER_VMID_CNTL__TRAP_ON_END__SHIFT 0xf
#define SPI_GDBG_PER_VMID_CNTL__STALL_VMID_MASK 0x00000001L
#define SPI_GDBG_PER_VMID_CNTL__LAUNCH_MODE_MASK 0x00000006L
#define SPI_GDBG_PER_VMID_CNTL__TRAP_EN_MASK 0x00000008L
#define SPI_GDBG_PER_VMID_CNTL__EXCP_EN_MASK 0x00001FF0L
#define SPI_GDBG_PER_VMID_CNTL__EXCP_REPLACE_MASK 0x00002000L
+#define SPI_GDBG_PER_VMID_CNTL__TRAP_ON_START_MASK 0x00004000L
+#define SPI_GDBG_PER_VMID_CNTL__TRAP_ON_END_MASK 0x00008000L
//SPI_COMPUTE_QUEUE_RESET
#define SPI_COMPUTE_QUEUE_RESET__RESET__SHIFT 0x0
#define SPI_COMPUTE_QUEUE_RESET__RESET_MASK 0x01L
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_offset.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_offset.h
index 3100de8b3881..393963502b7a 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_offset.h
@@ -705,6 +705,46 @@
#define regSQC_ICACHE_UTCL1_STATUS_BASE_IDX 0
#define regSQC_DCACHE_UTCL1_STATUS 0x03d8
#define regSQC_DCACHE_UTCL1_STATUS_BASE_IDX 0
+#define regSQC_UE_EDC_LO 0x03d9
+#define regSQC_UE_EDC_LO_BASE_IDX 0
+#define regSQC_UE_EDC_HI 0x03da
+#define regSQC_UE_EDC_HI_BASE_IDX 0
+#define regSQC_CE_EDC_LO 0x03db
+#define regSQC_CE_EDC_LO_BASE_IDX 0
+#define regSQC_CE_EDC_HI 0x03dc
+#define regSQC_CE_EDC_HI_BASE_IDX 0
+#define regSQ_UE_ERR_STATUS_LO 0x03dd
+#define regSQ_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regSQ_UE_ERR_STATUS_HI 0x03de
+#define regSQ_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regSQ_CE_ERR_STATUS_LO 0x03df
+#define regSQ_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regSQ_CE_ERR_STATUS_HI 0x03e0
+#define regSQ_CE_ERR_STATUS_HI_BASE_IDX 0
+#define regLDS_UE_ERR_STATUS_LO 0x03e1
+#define regLDS_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regLDS_UE_ERR_STATUS_HI 0x03e2
+#define regLDS_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regLDS_CE_ERR_STATUS_LO 0x03e3
+#define regLDS_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regLDS_CE_ERR_STATUS_HI 0x03e4
+#define regLDS_CE_ERR_STATUS_HI_BASE_IDX 0
+#define regSP0_UE_ERR_STATUS_LO 0x03e5
+#define regSP0_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regSP0_UE_ERR_STATUS_HI 0x03e6
+#define regSP0_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regSP0_CE_ERR_STATUS_LO 0x03e7
+#define regSP0_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regSP0_CE_ERR_STATUS_HI 0x03e8
+#define regSP0_CE_ERR_STATUS_HI_BASE_IDX 0
+#define regSP1_UE_ERR_STATUS_LO 0x03e9
+#define regSP1_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regSP1_UE_ERR_STATUS_HI 0x03ea
+#define regSP1_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regSP1_CE_ERR_STATUS_LO 0x03eb
+#define regSP1_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regSP1_CE_ERR_STATUS_HI 0x03ec
+#define regSP1_CE_ERR_STATUS_HI_BASE_IDX 0
// addressBlock: xcd0_gc_shsdec
@@ -727,6 +767,14 @@
#define regSPI_DSM_CNTL2_BASE_IDX 0
#define regSPI_EDC_CNT 0x0445
#define regSPI_EDC_CNT_BASE_IDX 0
+#define regSPI_UE_ERR_STATUS_LO 0x0446
+#define regSPI_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regSPI_UE_ERR_STATUS_HI 0x0447
+#define regSPI_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regSPI_CE_ERR_STATUS_LO 0x0448
+#define regSPI_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regSPI_CE_ERR_STATUS_HI 0x0449
+#define regSPI_CE_ERR_STATUS_HI_BASE_IDX 0
#define regSPI_DEBUG_BUSY 0x0450
#define regSPI_DEBUG_BUSY_BASE_IDX 0
#define regSPI_CONFIG_PS_CU_EN 0x0452
@@ -871,6 +919,14 @@
#define regTD_STATUS_BASE_IDX 0
#define regTD_POWER_CNTL 0x052a
#define regTD_POWER_CNTL_BASE_IDX 0
+#define regTD_UE_EDC_LO 0x052b
+#define regTD_UE_EDC_LO_BASE_IDX 0
+#define regTD_UE_EDC_HI 0x052c
+#define regTD_UE_EDC_HI_BASE_IDX 0
+#define regTD_CE_EDC_LO 0x052d
+#define regTD_CE_EDC_LO_BASE_IDX 0
+#define regTD_CE_EDC_HI 0x052e
+#define regTD_CE_EDC_HI_BASE_IDX 0
#define regTD_DSM_CNTL 0x052f
#define regTD_DSM_CNTL_BASE_IDX 0
#define regTD_DSM_CNTL2 0x0530
@@ -893,6 +949,14 @@
#define regTA_DSM_CNTL_BASE_IDX 0
#define regTA_DSM_CNTL2 0x0585
#define regTA_DSM_CNTL2_BASE_IDX 0
+#define regTA_UE_EDC_LO 0x0587
+#define regTA_UE_EDC_LO_BASE_IDX 0
+#define regTA_UE_EDC_HI 0x0588
+#define regTA_UE_EDC_HI_BASE_IDX 0
+#define regTA_CE_EDC_LO 0x0589
+#define regTA_CE_EDC_LO_BASE_IDX 0
+#define regTA_CE_EDC_HI 0x058a
+#define regTA_CE_EDC_HI_BASE_IDX 0
// addressBlock: xcd0_gc_gdsdec
@@ -923,6 +987,14 @@
#define regGDS_DSM_CNTL2_BASE_IDX 0
#define regGDS_WD_GDS_CSB 0x05ce
#define regGDS_WD_GDS_CSB_BASE_IDX 0
+#define regGDS_UE_ERR_STATUS_LO 0x05cf
+#define regGDS_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regGDS_UE_ERR_STATUS_HI 0x05d0
+#define regGDS_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regGDS_CE_ERR_STATUS_LO 0x05d1
+#define regGDS_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regGDS_CE_ERR_STATUS_HI 0x05d2
+#define regGDS_CE_ERR_STATUS_HI_BASE_IDX 0
// addressBlock: xcd0_gc_rbdec
@@ -1243,6 +1315,10 @@
#define regGCEA_MAM_CTRL_BASE_IDX 0
#define regGCEA_MAM_CTRL2 0x0702
#define regGCEA_MAM_CTRL2_BASE_IDX 0
+#define regGCEA_UE_ERR_STATUS_LO 0x0706
+#define regGCEA_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regGCEA_UE_ERR_STATUS_HI 0x0707
+#define regGCEA_UE_ERR_STATUS_HI_BASE_IDX 0
#define regGCEA_DSM_CNTL 0x0708
#define regGCEA_DSM_CNTL_BASE_IDX 0
#define regGCEA_DSM_CNTLA 0x0709
@@ -1277,6 +1353,10 @@
#define regGCEA_SDP_BACKDOOR_DATACREDITS1_BASE_IDX 0
#define regGCEA_SDP_BACKDOOR_MISCCREDITS 0x0719
#define regGCEA_SDP_BACKDOOR_MISCCREDITS_BASE_IDX 0
+#define regGCEA_CE_ERR_STATUS_LO 0x071b
+#define regGCEA_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regGCEA_CE_ERR_STATUS_HI 0x071d
+#define regGCEA_CE_ERR_STATUS_HI_BASE_IDX 0
#define regGCEA_SDP_ENABLE 0x071f
#define regGCEA_SDP_ENABLE_BASE_IDX 0
@@ -1389,6 +1469,14 @@
#define regATC_L2_CNTL4_BASE_IDX 0
#define regATC_L2_MM_GROUP_RT_CLASSES 0x0816
#define regATC_L2_MM_GROUP_RT_CLASSES_BASE_IDX 0
+#define regATC_L2_UE_ERR_STATUS_LO 0x081a
+#define regATC_L2_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regATC_L2_UE_ERR_STATUS_HI 0x081b
+#define regATC_L2_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regATC_L2_CE_ERR_STATUS_LO 0x081c
+#define regATC_L2_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regATC_L2_CE_ERR_STATUS_HI 0x081d
+#define regATC_L2_CE_ERR_STATUS_HI_BASE_IDX 0
// addressBlock: xcd0_gc_utcl2_vml2pfdec
@@ -1475,6 +1563,30 @@
#define regUTCL2_EDC_MODE_BASE_IDX 0
#define regUTCL2_EDC_CONFIG 0x084c
#define regUTCL2_EDC_CONFIG_BASE_IDX 0
+#define regVML2_UE_ERR_STATUS_LO 0x084d
+#define regVML2_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regVML2_WALKER_UE_ERR_STATUS_LO 0x084e
+#define regVML2_WALKER_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regUTCL2_UE_ERR_STATUS_LO 0x084f
+#define regUTCL2_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regVML2_UE_ERR_STATUS_HI 0x0850
+#define regVML2_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regVML2_WALKER_UE_ERR_STATUS_HI 0x0851
+#define regVML2_WALKER_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regUTCL2_UE_ERR_STATUS_HI 0x0852
+#define regUTCL2_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regVML2_CE_ERR_STATUS_LO 0x0853
+#define regVML2_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regVML2_WALKER_CE_ERR_STATUS_LO 0x0854
+#define regVML2_WALKER_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regUTCL2_CE_ERR_STATUS_LO 0x0855
+#define regUTCL2_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regVML2_CE_ERR_STATUS_HI 0x0856
+#define regVML2_CE_ERR_STATUS_HI_BASE_IDX 0
+#define regVML2_WALKER_CE_ERR_STATUS_HI 0x0857
+#define regVML2_WALKER_CE_ERR_STATUS_HI_BASE_IDX 0
+#define regUTCL2_CE_ERR_STATUS_HI 0x0858
+#define regUTCL2_CE_ERR_STATUS_HI_BASE_IDX 0
// addressBlock: xcd0_gc_utcl2_vml2vcdec
@@ -2011,6 +2123,22 @@
#define regTC_CFG_L1_VOLATILE_BASE_IDX 0
#define regTC_CFG_L2_VOLATILE 0x0b23
#define regTC_CFG_L2_VOLATILE_BASE_IDX 0
+#define regTCP_UE_EDC_HI_REG 0x0b54
+#define regTCP_UE_EDC_HI_REG_BASE_IDX 0
+#define regTCP_UE_EDC_LO_REG 0x0b55
+#define regTCP_UE_EDC_LO_REG_BASE_IDX 0
+#define regTCP_CE_EDC_HI_REG 0x0b56
+#define regTCP_CE_EDC_HI_REG_BASE_IDX 0
+#define regTCP_CE_EDC_LO_REG 0x0b57
+#define regTCP_CE_EDC_LO_REG_BASE_IDX 0
+#define regTCI_UE_EDC_HI_REG 0x0b58
+#define regTCI_UE_EDC_HI_REG_BASE_IDX 0
+#define regTCI_UE_EDC_LO_REG 0x0b59
+#define regTCI_UE_EDC_LO_REG_BASE_IDX 0
+#define regTCI_CE_EDC_HI_REG 0x0b5a
+#define regTCI_CE_EDC_HI_REG_BASE_IDX 0
+#define regTCI_CE_EDC_LO_REG 0x0b5b
+#define regTCI_CE_EDC_LO_REG_BASE_IDX 0
#define regTCI_MISC 0x0b5c
#define regTCI_MISC_BASE_IDX 0
#define regTCI_CNTL_3 0x0b5d
@@ -2061,6 +2189,26 @@
#define regTCX_DSM_CNTL_BASE_IDX 0
#define regTCX_DSM_CNTL2 0x0bc8
#define regTCX_DSM_CNTL2_BASE_IDX 0
+#define regTCA_UE_ERR_STATUS_LO 0x0bc9
+#define regTCA_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regTCA_UE_ERR_STATUS_HI 0x0bca
+#define regTCA_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regTCX_UE_ERR_STATUS_LO 0x0bcb
+#define regTCX_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regTCX_UE_ERR_STATUS_HI 0x0bcc
+#define regTCX_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regTCX_CE_ERR_STATUS_LO 0x0bcd
+#define regTCX_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regTCX_CE_ERR_STATUS_HI 0x0bce
+#define regTCX_CE_ERR_STATUS_HI_BASE_IDX 0
+#define regTCC_UE_ERR_STATUS_LO 0x0bcf
+#define regTCC_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regTCC_UE_ERR_STATUS_HI 0x0bd0
+#define regTCC_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regTCC_CE_ERR_STATUS_LO 0x0bd1
+#define regTCC_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regTCC_CE_ERR_STATUS_HI 0x0bd2
+#define regTCC_CE_ERR_STATUS_HI_BASE_IDX 0
// addressBlock: xcd0_gc_shdec
@@ -2905,6 +3053,30 @@
#define regCP_MEC2_F32_INT_DIS_BASE_IDX 0
#define regCP_VMID_STATUS 0x10bf
#define regCP_VMID_STATUS_BASE_IDX 0
+#define regCPC_UE_ERR_STATUS_LO 0x10e0
+#define regCPC_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regCPC_UE_ERR_STATUS_HI 0x10e1
+#define regCPC_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regCPC_CE_ERR_STATUS_LO 0x10e2
+#define regCPC_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regCPC_CE_ERR_STATUS_HI 0x10e3
+#define regCPC_CE_ERR_STATUS_HI_BASE_IDX 0
+#define regCPF_UE_ERR_STATUS_LO 0x10e4
+#define regCPF_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regCPF_UE_ERR_STATUS_HI 0x10e5
+#define regCPF_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regCPF_CE_ERR_STATUS_LO 0x10e6
+#define regCPF_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regCPF_CE_ERR_STATUS_HI 0x10e7
+#define regCPF_CE_ERR_STATUS_HI_BASE_IDX 0
+#define regCPG_UE_ERR_STATUS_LO 0x10e8
+#define regCPG_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regCPG_UE_ERR_STATUS_HI 0x10e9
+#define regCPG_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regCPG_CE_ERR_STATUS_LO 0x10ea
+#define regCPG_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regCPG_CE_ERR_STATUS_HI 0x10eb
+#define regCPG_CE_ERR_STATUS_HI_BASE_IDX 0
// addressBlock: xcd0_gc_cppdec2
@@ -5364,6 +5536,18 @@
#define regSPI_WAVE_LIMIT_CNTL 0x2443
#define regSPI_WAVE_LIMIT_CNTL_BASE_IDX 1
+// addressBlock: xcd0_gc_gccanedec
+// base address: 0x33d00
+#define regGC_CANE_ERR_STATUS 0x2f4d
+#define regGC_CANE_ERR_STATUS_BASE_IDX 1
+#define regGC_CANE_UE_ERR_STATUS_LO 0x2f4e
+#define regGC_CANE_UE_ERR_STATUS_LO_BASE_IDX 1
+#define regGC_CANE_UE_ERR_STATUS_HI 0x2f4f
+#define regGC_CANE_UE_ERR_STATUS_HI_BASE_IDX 1
+#define regGC_CANE_CE_ERR_STATUS_LO 0x2f50
+#define regGC_CANE_CE_ERR_STATUS_LO_BASE_IDX 1
+#define regGC_CANE_CE_ERR_STATUS_HI 0x2f51
+#define regGC_CANE_CE_ERR_STATUS_HI_BASE_IDX 1
// addressBlock: xcd0_gc_perfddec
// base address: 0x34000
@@ -6583,6 +6767,10 @@
#define regRLC_CAPTURE_GPU_CLOCK_COUNT_2_BASE_IDX 1
#define regRLC_CPG_STAT_INVAL 0x4d09
#define regRLC_CPG_STAT_INVAL_BASE_IDX 1
+#define regRLC_UE_ERR_STATUS_LOW 0x4d40
+#define regRLC_UE_ERR_STATUS_LOW_BASE_IDX 1
+#define regRLC_UE_ERR_STATUS_HIGH 0x4d41
+#define regRLC_UE_ERR_STATUS_HIGH_BASE_IDX 1
#define regRLC_DSM_CNTL 0x4d42
#define regRLC_DSM_CNTL_BASE_IDX 1
#define regRLC_DSM_CNTLA 0x4d43
@@ -6591,6 +6779,10 @@
#define regRLC_DSM_CNTL2_BASE_IDX 1
#define regRLC_DSM_CNTL2A 0x4d45
#define regRLC_DSM_CNTL2A_BASE_IDX 1
+#define regRLC_CE_ERR_STATUS_LOW 0x4d49
+#define regRLC_CE_ERR_STATUS_LOW_BASE_IDX 1
+#define regRLC_CE_ERR_STATUS_HIGH 0x4d4a
+#define regRLC_CE_ERR_STATUS_HIGH_BASE_IDX 1
#define regRLC_RLCV_SPARE_INT 0x4f30
#define regRLC_RLCV_SPARE_INT_BASE_IDX 1
#define regRLC_SMU_CLK_REQ 0x4f97
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_sh_mask.h
index 84a75b58347f..2bd9f3f1026f 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_3_sh_mask.h
@@ -4129,6 +4129,240 @@
#define SQC_DCACHE_UTCL1_STATUS__FAULT_DETECTED_MASK 0x00000001L
#define SQC_DCACHE_UTCL1_STATUS__RETRY_DETECTED_MASK 0x00000002L
#define SQC_DCACHE_UTCL1_STATUS__PRT_DETECTED_MASK 0x00000004L
+//SQC_UE_EDC_LO
+#define SQC_UE_EDC_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define SQC_UE_EDC_LO__ADDRESS_INFO_VALID_FLAG__SHIFT 0x1
+#define SQC_UE_EDC_LO__ADDRESS__SHIFT 0x2
+#define SQC_UE_EDC_LO__MEM_ID__SHIFT 0x18
+#define SQC_UE_EDC_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define SQC_UE_EDC_LO__ADDRESS_INFO_VALID_FLAG_MASK 0x00000002L
+#define SQC_UE_EDC_LO__ADDRESS_MASK 0x00FFFFFCL
+#define SQC_UE_EDC_LO__MEM_ID_MASK 0xFF000000L
+//SQC_UE_EDC_HI
+#define SQC_UE_EDC_HI__ECC__SHIFT 0x0
+#define SQC_UE_EDC_HI__PARITY__SHIFT 0x1
+#define SQC_UE_EDC_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define SQC_UE_EDC_HI__ERR_INFO__SHIFT 0x3
+#define SQC_UE_EDC_HI__UE_CNT__SHIFT 0x17
+#define SQC_UE_EDC_HI__FED_CNT__SHIFT 0x1a
+#define SQC_UE_EDC_HI__ECC_MASK 0x00000001L
+#define SQC_UE_EDC_HI__PARITY_MASK 0x00000002L
+#define SQC_UE_EDC_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define SQC_UE_EDC_HI__ERR_INFO_MASK 0x007FFFF8L
+#define SQC_UE_EDC_HI__UE_CNT_MASK 0x03800000L
+#define SQC_UE_EDC_HI__FED_CNT_MASK 0x1C000000L
+//SQC_CE_EDC_LO
+#define SQC_CE_EDC_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define SQC_CE_EDC_LO__ADDRESS_INFO_VALID_FLAG__SHIFT 0x1
+#define SQC_CE_EDC_LO__ADDRESS__SHIFT 0x2
+#define SQC_CE_EDC_LO__MEM_ID__SHIFT 0x18
+#define SQC_CE_EDC_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define SQC_CE_EDC_LO__ADDRESS_INFO_VALID_FLAG_MASK 0x00000002L
+#define SQC_CE_EDC_LO__ADDRESS_MASK 0x00FFFFFCL
+#define SQC_CE_EDC_LO__MEM_ID_MASK 0xFF000000L
+//SQC_CE_EDC_HI
+#define SQC_CE_EDC_HI__ECC__SHIFT 0x0
+#define SQC_CE_EDC_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define SQC_CE_EDC_HI__ERR_INFO__SHIFT 0x3
+#define SQC_CE_EDC_HI__CE_CNT__SHIFT 0x17
+#define SQC_CE_EDC_HI__POSION__SHIFT 0x1a
+#define SQC_CE_EDC_HI__ECC_MASK 0x00000001L
+#define SQC_CE_EDC_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define SQC_CE_EDC_HI__ERR_INFO_MASK 0x007FFFF8L
+#define SQC_CE_EDC_HI__CE_CNT_MASK 0x03800000L
+#define SQC_CE_EDC_HI__POSION_MASK 0x04000000L
+//SQ_UE_ERR_STATUS_LO
+#define SQ_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define SQ_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define SQ_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define SQ_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define SQ_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define SQ_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define SQ_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define SQ_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//SQ_UE_ERR_STATUS_HI
+#define SQ_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define SQ_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define SQ_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define SQ_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define SQ_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define SQ_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define SQ_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define SQ_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define SQ_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define SQ_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define SQ_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define SQ_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define SQ_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define SQ_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
+//SQ_CE_ERR_STATUS_LO
+#define SQ_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define SQ_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define SQ_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define SQ_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define SQ_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define SQ_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define SQ_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define SQ_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//SQ_CE_ERR_STATUS_HI
+#define SQ_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define SQ_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define SQ_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define SQ_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define SQ_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define SQ_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define SQ_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define SQ_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define SQ_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define SQ_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define SQ_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define SQ_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define SQ_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define SQ_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
+//LDS_UE_ERR_STATUS_LO
+#define LDS_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define LDS_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define LDS_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define LDS_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define LDS_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define LDS_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define LDS_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define LDS_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//LDS_UE_ERR_STATUS_HI
+#define LDS_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define LDS_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define LDS_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define LDS_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define LDS_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define LDS_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define LDS_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define LDS_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define LDS_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define LDS_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define LDS_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define LDS_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define LDS_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define LDS_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
+//LDS_CE_ERR_STATUS_LO
+#define LDS_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define LDS_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define LDS_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define LDS_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define LDS_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define LDS_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define LDS_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define LDS_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//LDS_CE_ERR_STATUS_HI
+#define LDS_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define LDS_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define LDS_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define LDS_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define LDS_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define LDS_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define LDS_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define LDS_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define LDS_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define LDS_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define LDS_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define LDS_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define LDS_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define LDS_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
+//SP0_UE_ERR_STATUS_LO
+#define SP0_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define SP0_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define SP0_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define SP0_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define SP0_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define SP0_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define SP0_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define SP0_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//SP0_UE_ERR_STATUS_HI
+#define SP0_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define SP0_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define SP0_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define SP0_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define SP0_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define SP0_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define SP0_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define SP0_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define SP0_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define SP0_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define SP0_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define SP0_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define SP0_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define SP0_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
+//SP0_CE_ERR_STATUS_LO
+#define SP0_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define SP0_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define SP0_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define SP0_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define SP0_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define SP0_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define SP0_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define SP0_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//SP0_CE_ERR_STATUS_HI
+#define SP0_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define SP0_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define SP0_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define SP0_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define SP0_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define SP0_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define SP0_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define SP0_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define SP0_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define SP0_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define SP0_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define SP0_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define SP0_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define SP0_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
+//SP1_UE_ERR_STATUS_LO
+#define SP1_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define SP1_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define SP1_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define SP1_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define SP1_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define SP1_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define SP1_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define SP1_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//SP1_UE_ERR_STATUS_HI
+#define SP1_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define SP1_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define SP1_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define SP1_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define SP1_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define SP1_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define SP1_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define SP1_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define SP1_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define SP1_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define SP1_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define SP1_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define SP1_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define SP1_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
+//SP1_CE_ERR_STATUS_LO
+#define SP1_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define SP1_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define SP1_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define SP1_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define SP1_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define SP1_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define SP1_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define SP1_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//SP1_CE_ERR_STATUS_HI
+#define SP1_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define SP1_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define SP1_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define SP1_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define SP1_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define SP1_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define SP1_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define SP1_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define SP1_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define SP1_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define SP1_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define SP1_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define SP1_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define SP1_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
// addressBlock: xcd0_gc_shsdec
@@ -4235,6 +4469,54 @@
#define SPI_EDC_CNT__SPI_LIFE_CNT_SEC_COUNT_MASK 0x00030000L
#define SPI_EDC_CNT__SPI_LIFE_CNT_DED_COUNT_MASK 0x000C0000L
#define SPI_EDC_CNT__UNUSED_MASK 0xFFF00000L
+//SPI_UE_ERR_STATUS_LO
+#define SPI_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define SPI_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define SPI_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define SPI_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define SPI_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define SPI_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define SPI_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define SPI_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//SPI_UE_ERR_STATUS_HI
+#define SPI_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define SPI_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define SPI_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define SPI_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define SPI_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define SPI_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define SPI_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define SPI_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define SPI_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define SPI_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define SPI_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define SPI_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define SPI_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define SPI_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
+//SPI_CE_ERR_STATUS_LO
+#define SPI_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define SPI_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define SPI_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define SPI_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define SPI_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define SPI_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define SPI_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define SPI_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//SPI_CE_ERR_STATUS_HI
+#define SPI_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define SPI_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define SPI_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define SPI_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define SPI_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define SPI_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define SPI_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define SPI_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define SPI_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define SPI_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define SPI_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define SPI_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define SPI_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define SPI_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
//SPI_DEBUG_BUSY
#define SPI_DEBUG_BUSY__HS_BUSY__SHIFT 0x0
#define SPI_DEBUG_BUSY__GS_BUSY__SHIFT 0x1
@@ -4622,6 +4904,48 @@
#define TD_POWER_CNTL__MGCG_OUTPUTSTAGE_MASK 0x00000002L
#define TD_POWER_CNTL__MID0_THREAD_DATA_MASK 0x00000004L
#define TD_POWER_CNTL__MID2_ACCUM_DATA_MASK 0x00000008L
+//TD_UE_EDC_LO
+#define TD_UE_EDC_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define TD_UE_EDC_LO__ADDRESS_INFO_VALID_FLAG__SHIFT 0x1
+#define TD_UE_EDC_LO__ADDRESS__SHIFT 0x2
+#define TD_UE_EDC_LO__MEM_ID__SHIFT 0x18
+#define TD_UE_EDC_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define TD_UE_EDC_LO__ADDRESS_INFO_VALID_FLAG_MASK 0x00000002L
+#define TD_UE_EDC_LO__ADDRESS_MASK 0x00FFFFFCL
+#define TD_UE_EDC_LO__MEM_ID_MASK 0xFF000000L
+//TD_UE_EDC_HI
+#define TD_UE_EDC_HI__ECC__SHIFT 0x0
+#define TD_UE_EDC_HI__PARITY__SHIFT 0x1
+#define TD_UE_EDC_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define TD_UE_EDC_HI__ERR_INFO__SHIFT 0x3
+#define TD_UE_EDC_HI__UE_CNT__SHIFT 0x17
+#define TD_UE_EDC_HI__FED_CNT__SHIFT 0x1a
+#define TD_UE_EDC_HI__ECC_MASK 0x00000001L
+#define TD_UE_EDC_HI__PARITY_MASK 0x00000002L
+#define TD_UE_EDC_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TD_UE_EDC_HI__ERR_INFO_MASK 0x007FFFF8L
+#define TD_UE_EDC_HI__UE_CNT_MASK 0x03800000L
+#define TD_UE_EDC_HI__FED_CNT_MASK 0x1C000000L
+//TD_CE_EDC_LO
+#define TD_CE_EDC_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define TD_CE_EDC_LO__ADDRESS_INFO_VALID_FLAG__SHIFT 0x1
+#define TD_CE_EDC_LO__ADDRESS__SHIFT 0x2
+#define TD_CE_EDC_LO__MEM_ID__SHIFT 0x18
+#define TD_CE_EDC_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define TD_CE_EDC_LO__ADDRESS_INFO_VALID_FLAG_MASK 0x00000002L
+#define TD_CE_EDC_LO__ADDRESS_MASK 0x00FFFFFCL
+#define TD_CE_EDC_LO__MEM_ID_MASK 0xFF000000L
+//TD_CE_EDC_HI
+#define TD_CE_EDC_HI__ECC__SHIFT 0x0
+#define TD_CE_EDC_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define TD_CE_EDC_HI__ERR_INFO__SHIFT 0x3
+#define TD_CE_EDC_HI__CE_CNT__SHIFT 0x17
+#define TD_CE_EDC_HI__POISON__SHIFT 0x1a
+#define TD_CE_EDC_HI__ECC_MASK 0x00000001L
+#define TD_CE_EDC_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TD_CE_EDC_HI__ERR_INFO_MASK 0x007FFFF8L
+#define TD_CE_EDC_HI__CE_CNT_MASK 0x03800000L
+#define TD_CE_EDC_HI__POISON_MASK 0x04000000L
//TD_DSM_CNTL
#define TD_DSM_CNTL__TD_SS_FIFO_LO_DSM_IRRITATOR_DATA__SHIFT 0x0
#define TD_DSM_CNTL__TD_SS_FIFO_LO_ENABLE_SINGLE_WRITE__SHIFT 0x2
@@ -4771,6 +5095,48 @@
#define TA_DSM_CNTL2__TA_FS_AFIFO_HI_ENABLE_ERROR_INJECT_MASK 0x000C0000L
#define TA_DSM_CNTL2__TA_FS_AFIFO_HI_SELECT_INJECT_DELAY_MASK 0x00100000L
#define TA_DSM_CNTL2__TA_INJECT_DELAY_MASK 0xFC000000L
+//TA_UE_EDC_LO
+#define TA_UE_EDC_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define TA_UE_EDC_LO__ADDRESS_INFO_VALID_FLAG__SHIFT 0x1
+#define TA_UE_EDC_LO__ADDRESS__SHIFT 0x2
+#define TA_UE_EDC_LO__MEM_ID__SHIFT 0x18
+#define TA_UE_EDC_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define TA_UE_EDC_LO__ADDRESS_INFO_VALID_FLAG_MASK 0x00000002L
+#define TA_UE_EDC_LO__ADDRESS_MASK 0x00FFFFFCL
+#define TA_UE_EDC_LO__MEM_ID_MASK 0xFF000000L
+//TA_UE_EDC_HI
+#define TA_UE_EDC_HI__ECC__SHIFT 0x0
+#define TA_UE_EDC_HI__PARITY__SHIFT 0x1
+#define TA_UE_EDC_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define TA_UE_EDC_HI__ERR_INFO__SHIFT 0x3
+#define TA_UE_EDC_HI__UE_CNT__SHIFT 0x17
+#define TA_UE_EDC_HI__FED_CNT__SHIFT 0x1a
+#define TA_UE_EDC_HI__ECC_MASK 0x00000001L
+#define TA_UE_EDC_HI__PARITY_MASK 0x00000002L
+#define TA_UE_EDC_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TA_UE_EDC_HI__ERR_INFO_MASK 0x007FFFF8L
+#define TA_UE_EDC_HI__UE_CNT_MASK 0x03800000L
+#define TA_UE_EDC_HI__FED_CNT_MASK 0x1C000000L
+//TA_CE_EDC_LO
+#define TA_CE_EDC_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define TA_CE_EDC_LO__ADDRESS_INFO_VALID_FLAG__SHIFT 0x1
+#define TA_CE_EDC_LO__ADDRESS__SHIFT 0x2
+#define TA_CE_EDC_LO__MEM_ID__SHIFT 0x18
+#define TA_CE_EDC_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define TA_CE_EDC_LO__ADDRESS_INFO_VALID_FLAG_MASK 0x00000002L
+#define TA_CE_EDC_LO__ADDRESS_MASK 0x00FFFFFCL
+#define TA_CE_EDC_LO__MEM_ID_MASK 0xFF000000L
+//TA_CE_EDC_HI
+#define TA_CE_EDC_HI__ECC__SHIFT 0x0
+#define TA_CE_EDC_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define TA_CE_EDC_HI__ERR_INFO__SHIFT 0x3
+#define TA_CE_EDC_HI__CE_CNT__SHIFT 0x17
+#define TA_CE_EDC_HI__POISON__SHIFT 0x1a
+#define TA_CE_EDC_HI__ECC_MASK 0x00000001L
+#define TA_CE_EDC_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TA_CE_EDC_HI__ERR_INFO_MASK 0x007FFFF8L
+#define TA_CE_EDC_HI__CE_CNT_MASK 0x03800000L
+#define TA_CE_EDC_HI__POISON_MASK 0x04000000L
// addressBlock: xcd0_gc_gdsdec
@@ -5015,6 +5381,54 @@
#define GDS_WD_GDS_CSB__UNUSED__SHIFT 0xd
#define GDS_WD_GDS_CSB__COUNTER_MASK 0x00001FFFL
#define GDS_WD_GDS_CSB__UNUSED_MASK 0xFFFFE000L
+//GDS_UE_ERR_STATUS_LO
+#define GDS_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define GDS_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define GDS_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define GDS_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define GDS_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define GDS_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define GDS_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define GDS_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//GDS_UE_ERR_STATUS_HI
+#define GDS_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define GDS_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define GDS_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define GDS_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define GDS_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define GDS_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define GDS_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define GDS_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define GDS_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define GDS_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define GDS_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define GDS_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define GDS_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define GDS_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
+//GDS_CE_ERR_STATUS_LO
+#define GDS_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define GDS_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define GDS_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define GDS_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define GDS_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define GDS_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define GDS_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define GDS_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//GDS_CE_ERR_STATUS_HI
+#define GDS_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define GDS_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define GDS_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define GDS_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define GDS_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define GDS_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define GDS_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define GDS_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define GDS_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define GDS_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define GDS_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define GDS_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define GDS_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define GDS_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
// addressBlock: xcd0_gc_rbdec
@@ -7370,6 +7784,30 @@
#define GCEA_MAM_CTRL2__ARAM_FLUSH_NOALLOC_MASK 0x00000040L
#define GCEA_MAM_CTRL2__RESERVED_FIELD_MASK 0x00FFFF80L
#define GCEA_MAM_CTRL2__ADDR_HI_MASK 0xFF000000L
+//GCEA_UE_ERR_STATUS_LO
+#define GCEA_UE_ERR_STATUS_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define GCEA_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define GCEA_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define GCEA_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define GCEA_UE_ERR_STATUS_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define GCEA_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define GCEA_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define GCEA_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//GCEA_UE_ERR_STATUS_HI
+#define GCEA_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define GCEA_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define GCEA_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define GCEA_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define GCEA_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define GCEA_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define GCEA_UE_ERR_STATUS_HI__RESERVED_FIELD__SHIFT 0x1d
+#define GCEA_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define GCEA_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define GCEA_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define GCEA_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define GCEA_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define GCEA_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define GCEA_UE_ERR_STATUS_HI__RESERVED_FIELD_MASK 0xE0000000L
//GCEA_DSM_CNTL
#define GCEA_DSM_CNTL__DRAMRD_CMDMEM_DSM_IRRITATOR_DATA__SHIFT 0x0
#define GCEA_DSM_CNTL__DRAMRD_CMDMEM_ENABLE_SINGLE_WRITE__SHIFT 0x2
@@ -7745,6 +8183,30 @@
#define GCEA_SDP_BACKDOOR_MISCCREDITS__WRRSP_CREDITS_RELEASED_MASK 0x0000FF00L
#define GCEA_SDP_BACKDOOR_MISCCREDITS__PRB_REQ_CREDITS_RELEASED_MASK 0x007F0000L
#define GCEA_SDP_BACKDOOR_MISCCREDITS__PRB_RSP_CREDITS_RECEIVED_MASK 0x3F800000L
+//GCEA_CE_ERR_STATUS_LO
+#define GCEA_CE_ERR_STATUS_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define GCEA_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define GCEA_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define GCEA_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define GCEA_CE_ERR_STATUS_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define GCEA_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define GCEA_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define GCEA_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//GCEA_CE_ERR_STATUS_HI
+#define GCEA_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define GCEA_CE_ERR_STATUS_HI__RESERVED_FIELD0__SHIFT 0x1
+#define GCEA_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define GCEA_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define GCEA_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define GCEA_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define GCEA_CE_ERR_STATUS_HI__RESERVED_FIELD1__SHIFT 0x1b
+#define GCEA_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define GCEA_CE_ERR_STATUS_HI__RESERVED_FIELD0_MASK 0x00000002L
+#define GCEA_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define GCEA_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define GCEA_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define GCEA_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define GCEA_CE_ERR_STATUS_HI__RESERVED_FIELD1_MASK 0xF8000000L
//GCEA_SDP_ENABLE
#define GCEA_SDP_ENABLE__ENABLE__SHIFT 0x0
#define GCEA_SDP_ENABLE__ENABLE_MASK 0x00000001L
@@ -8440,6 +8902,54 @@
//ATC_L2_MM_GROUP_RT_CLASSES
#define ATC_L2_MM_GROUP_RT_CLASSES__GROUP_RT_CLASS__SHIFT 0x0
#define ATC_L2_MM_GROUP_RT_CLASSES__GROUP_RT_CLASS_MASK 0xFFFFFFFFL
+//ATC_L2_UE_ERR_STATUS_LO
+#define ATC_L2_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define ATC_L2_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define ATC_L2_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define ATC_L2_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define ATC_L2_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define ATC_L2_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define ATC_L2_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define ATC_L2_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//ATC_L2_UE_ERR_STATUS_HI
+#define ATC_L2_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define ATC_L2_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define ATC_L2_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define ATC_L2_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define ATC_L2_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define ATC_L2_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define ATC_L2_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define ATC_L2_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define ATC_L2_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define ATC_L2_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define ATC_L2_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define ATC_L2_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define ATC_L2_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define ATC_L2_UE_ERR_STATUS_HI__RESERVED_MASK 0x60000000L
+//ATC_L2_CE_ERR_STATUS_LO
+#define ATC_L2_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define ATC_L2_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define ATC_L2_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define ATC_L2_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define ATC_L2_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define ATC_L2_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define ATC_L2_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define ATC_L2_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//ATC_L2_CE_ERR_STATUS_HI
+#define ATC_L2_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define ATC_L2_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define ATC_L2_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define ATC_L2_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define ATC_L2_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define ATC_L2_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define ATC_L2_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define ATC_L2_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define ATC_L2_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define ATC_L2_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define ATC_L2_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define ATC_L2_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define ATC_L2_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define ATC_L2_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
// addressBlock: xcd0_gc_utcl2_vml2pfdec
@@ -8888,6 +9398,150 @@
#define UTCL2_EDC_CONFIG__DIS_EDC__SHIFT 0x1
#define UTCL2_EDC_CONFIG__WRITE_DIS_MASK 0x00000001L
#define UTCL2_EDC_CONFIG__DIS_EDC_MASK 0x00000002L
+//VML2_UE_ERR_STATUS_LO
+#define VML2_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define VML2_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define VML2_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define VML2_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define VML2_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define VML2_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define VML2_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define VML2_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//VML2_WALKER_UE_ERR_STATUS_LO
+#define VML2_WALKER_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define VML2_WALKER_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define VML2_WALKER_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define VML2_WALKER_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define VML2_WALKER_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define VML2_WALKER_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define VML2_WALKER_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define VML2_WALKER_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//UTCL2_UE_ERR_STATUS_LO
+#define UTCL2_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define UTCL2_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define UTCL2_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define UTCL2_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define UTCL2_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define UTCL2_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define UTCL2_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define UTCL2_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//VML2_UE_ERR_STATUS_HI
+#define VML2_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define VML2_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define VML2_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define VML2_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define VML2_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define VML2_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define VML2_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define VML2_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define VML2_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define VML2_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define VML2_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define VML2_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define VML2_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define VML2_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
+//VML2_WALKER_UE_ERR_STATUS_HI
+#define VML2_WALKER_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define VML2_WALKER_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define VML2_WALKER_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define VML2_WALKER_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define VML2_WALKER_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define VML2_WALKER_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define VML2_WALKER_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define VML2_WALKER_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define VML2_WALKER_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define VML2_WALKER_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define VML2_WALKER_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define VML2_WALKER_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define VML2_WALKER_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define VML2_WALKER_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
+//UTCL2_UE_ERR_STATUS_HI
+#define UTCL2_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define UTCL2_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define UTCL2_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define UTCL2_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define UTCL2_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define UTCL2_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define UTCL2_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define UTCL2_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define UTCL2_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define UTCL2_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define UTCL2_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define UTCL2_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define UTCL2_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define UTCL2_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
+//VML2_CE_ERR_STATUS_LO
+#define VML2_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define VML2_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define VML2_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define VML2_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define VML2_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define VML2_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define VML2_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define VML2_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//VML2_WALKER_CE_ERR_STATUS_LO
+#define VML2_WALKER_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define VML2_WALKER_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define VML2_WALKER_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define VML2_WALKER_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define VML2_WALKER_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define VML2_WALKER_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define VML2_WALKER_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define VML2_WALKER_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//UTCL2_CE_ERR_STATUS_LO
+#define UTCL2_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define UTCL2_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define UTCL2_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define UTCL2_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define UTCL2_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define UTCL2_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define UTCL2_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define UTCL2_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//VML2_CE_ERR_STATUS_HI
+#define VML2_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define VML2_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define VML2_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define VML2_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define VML2_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define VML2_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define VML2_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define VML2_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define VML2_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define VML2_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define VML2_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define VML2_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define VML2_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define VML2_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
+//VML2_WALKER_CE_ERR_STATUS_HI
+#define VML2_WALKER_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define VML2_WALKER_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define VML2_WALKER_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define VML2_WALKER_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define VML2_WALKER_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define VML2_WALKER_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define VML2_WALKER_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define VML2_WALKER_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define VML2_WALKER_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define VML2_WALKER_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define VML2_WALKER_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define VML2_WALKER_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define VML2_WALKER_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define VML2_WALKER_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
+//UTCL2_CE_ERR_STATUS_HI
+#define UTCL2_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define UTCL2_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define UTCL2_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define UTCL2_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define UTCL2_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define UTCL2_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define UTCL2_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define UTCL2_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define UTCL2_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define UTCL2_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define UTCL2_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define UTCL2_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define UTCL2_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define UTCL2_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
// addressBlock: xcd0_gc_utcl2_vml2vcdec
@@ -11139,6 +11793,98 @@
//TC_CFG_L2_VOLATILE
#define TC_CFG_L2_VOLATILE__VOL__SHIFT 0x0
#define TC_CFG_L2_VOLATILE__VOL_MASK 0x0000000FL
+//TCP_UE_EDC_HI_REG
+#define TCP_UE_EDC_HI_REG__ECC__SHIFT 0x0
+#define TCP_UE_EDC_HI_REG__PARITY__SHIFT 0x1
+#define TCP_UE_EDC_HI_REG__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define TCP_UE_EDC_HI_REG__ERR_INFO__SHIFT 0x3
+#define TCP_UE_EDC_HI_REG__UE_CNT__SHIFT 0x17
+#define TCP_UE_EDC_HI_REG__FED_CNT__SHIFT 0x1a
+#define TCP_UE_EDC_HI_REG__RESERVED__SHIFT 0x1d
+#define TCP_UE_EDC_HI_REG__ECC_MASK 0x00000001L
+#define TCP_UE_EDC_HI_REG__PARITY_MASK 0x00000002L
+#define TCP_UE_EDC_HI_REG__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TCP_UE_EDC_HI_REG__ERR_INFO_MASK 0x007FFFF8L
+#define TCP_UE_EDC_HI_REG__UE_CNT_MASK 0x03800000L
+#define TCP_UE_EDC_HI_REG__FED_CNT_MASK 0x1C000000L
+#define TCP_UE_EDC_HI_REG__RESERVED_MASK 0xE0000000L
+//TCP_UE_EDC_LO_REG
+#define TCP_UE_EDC_LO_REG__STATUS_VALID_FLAG__SHIFT 0x0
+#define TCP_UE_EDC_LO_REG__ADDRESS_INFO_VALID_FLAG__SHIFT 0x1
+#define TCP_UE_EDC_LO_REG__ADDRESS__SHIFT 0x2
+#define TCP_UE_EDC_LO_REG__MEM_ID__SHIFT 0x18
+#define TCP_UE_EDC_LO_REG__STATUS_VALID_FLAG_MASK 0x00000001L
+#define TCP_UE_EDC_LO_REG__ADDRESS_INFO_VALID_FLAG_MASK 0x00000002L
+#define TCP_UE_EDC_LO_REG__ADDRESS_MASK 0x00FFFFFCL
+#define TCP_UE_EDC_LO_REG__MEM_ID_MASK 0xFF000000L
+//TCP_CE_EDC_HI_REG
+#define TCP_CE_EDC_HI_REG__ECC__SHIFT 0x0
+#define TCP_CE_EDC_HI_REG__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define TCP_CE_EDC_HI_REG__ERR_INFO__SHIFT 0x3
+#define TCP_CE_EDC_HI_REG__CE_CNT__SHIFT 0x17
+#define TCP_CE_EDC_HI_REG__POISON__SHIFT 0x1a
+#define TCP_CE_EDC_HI_REG__RESERVED__SHIFT 0x1b
+#define TCP_CE_EDC_HI_REG__ECC_MASK 0x00000001L
+#define TCP_CE_EDC_HI_REG__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TCP_CE_EDC_HI_REG__ERR_INFO_MASK 0x007FFFF8L
+#define TCP_CE_EDC_HI_REG__CE_CNT_MASK 0x03800000L
+#define TCP_CE_EDC_HI_REG__POISON_MASK 0x04000000L
+#define TCP_CE_EDC_HI_REG__RESERVED_MASK 0xF8000000L
+//TCP_CE_EDC_LO_REG
+#define TCP_CE_EDC_LO_REG__STATUS_VALID_FLAG__SHIFT 0x0
+#define TCP_CE_EDC_LO_REG__ADDRESS_INFO_VALID_FLAG__SHIFT 0x1
+#define TCP_CE_EDC_LO_REG__ADDRESS__SHIFT 0x2
+#define TCP_CE_EDC_LO_REG__MEM_ID__SHIFT 0x18
+#define TCP_CE_EDC_LO_REG__STATUS_VALID_FLAG_MASK 0x00000001L
+#define TCP_CE_EDC_LO_REG__ADDRESS_INFO_VALID_FLAG_MASK 0x00000002L
+#define TCP_CE_EDC_LO_REG__ADDRESS_MASK 0x00FFFFFCL
+#define TCP_CE_EDC_LO_REG__MEM_ID_MASK 0xFF000000L
+//TCI_UE_EDC_HI_REG
+#define TCI_UE_EDC_HI_REG__ECC__SHIFT 0x0
+#define TCI_UE_EDC_HI_REG__PARITY__SHIFT 0x1
+#define TCI_UE_EDC_HI_REG__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define TCI_UE_EDC_HI_REG__ERR_INFO__SHIFT 0x3
+#define TCI_UE_EDC_HI_REG__UE_CNT__SHIFT 0x17
+#define TCI_UE_EDC_HI_REG__FED_CNT__SHIFT 0x1a
+#define TCI_UE_EDC_HI_REG__RESERVED__SHIFT 0x1d
+#define TCI_UE_EDC_HI_REG__ECC_MASK 0x00000001L
+#define TCI_UE_EDC_HI_REG__PARITY_MASK 0x00000002L
+#define TCI_UE_EDC_HI_REG__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TCI_UE_EDC_HI_REG__ERR_INFO_MASK 0x007FFFF8L
+#define TCI_UE_EDC_HI_REG__UE_CNT_MASK 0x03800000L
+#define TCI_UE_EDC_HI_REG__FED_CNT_MASK 0x1C000000L
+#define TCI_UE_EDC_HI_REG__RESERVED_MASK 0xE0000000L
+//TCI_UE_EDC_LO_REG
+#define TCI_UE_EDC_LO_REG__STATUS_VALID_FLAG__SHIFT 0x0
+#define TCI_UE_EDC_LO_REG__ADDRESS_INFO_VALID_FLAG__SHIFT 0x1
+#define TCI_UE_EDC_LO_REG__ADDRESS__SHIFT 0x2
+#define TCI_UE_EDC_LO_REG__MEM_ID__SHIFT 0x18
+#define TCI_UE_EDC_LO_REG__STATUS_VALID_FLAG_MASK 0x00000001L
+#define TCI_UE_EDC_LO_REG__ADDRESS_INFO_VALID_FLAG_MASK 0x00000002L
+#define TCI_UE_EDC_LO_REG__ADDRESS_MASK 0x00FFFFFCL
+#define TCI_UE_EDC_LO_REG__MEM_ID_MASK 0xFF000000L
+//TCI_CE_EDC_HI_REG
+#define TCI_CE_EDC_HI_REG__ECC__SHIFT 0x0
+#define TCI_CE_EDC_HI_REG__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define TCI_CE_EDC_HI_REG__ERR_INFO__SHIFT 0x3
+#define TCI_CE_EDC_HI_REG__CE_CNT__SHIFT 0x17
+#define TCI_CE_EDC_HI_REG__POISON__SHIFT 0x1a
+#define TCI_CE_EDC_HI_REG__RESERVED__SHIFT 0x1b
+#define TCI_CE_EDC_HI_REG__ECC_MASK 0x00000001L
+#define TCI_CE_EDC_HI_REG__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TCI_CE_EDC_HI_REG__ERR_INFO_MASK 0x007FFFF8L
+#define TCI_CE_EDC_HI_REG__CE_CNT_MASK 0x03800000L
+#define TCI_CE_EDC_HI_REG__POISON_MASK 0x04000000L
+#define TCI_CE_EDC_HI_REG__RESERVED_MASK 0xF8000000L
+//TCI_CE_EDC_LO_REG
+#define TCI_CE_EDC_LO_REG__STATUS_VALID_FLAG__SHIFT 0x0
+#define TCI_CE_EDC_LO_REG__ADDRESS_INFO_VALID_FLAG__SHIFT 0x1
+#define TCI_CE_EDC_LO_REG__ADDRESS__SHIFT 0x2
+#define TCI_CE_EDC_LO_REG__MEM_ID__SHIFT 0x18
+#define TCI_CE_EDC_LO_REG__STATUS_VALID_FLAG_MASK 0x00000001L
+#define TCI_CE_EDC_LO_REG__ADDRESS_INFO_VALID_FLAG_MASK 0x00000002L
+#define TCI_CE_EDC_LO_REG__ADDRESS_MASK 0x00FFFFFCL
+#define TCI_CE_EDC_LO_REG__MEM_ID_MASK 0xFF000000L
//TCI_MISC
#define TCI_MISC__FGCG_REPEATER_DISABLE__SHIFT 0x0
#define TCI_MISC__LEGACY_MGCG_DISABLE__SHIFT 0x1
@@ -11560,6 +12306,112 @@
#define TCX_DSM_CNTL2__SED_ENABLE_ERROR_INJECT_MASK 0x00000003L
#define TCX_DSM_CNTL2__SED_SELECT_INJECT_DELAY_MASK 0x00000004L
#define TCX_DSM_CNTL2__INJECT_DELAY_MASK 0xFC000000L
+//TCA_UE_ERR_STATUS_LO
+#define TCA_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define TCA_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define TCA_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define TCA_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define TCA_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define TCA_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define TCA_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define TCA_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//TCA_UE_ERR_STATUS_HI
+#define TCA_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define TCA_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define TCA_UE_ERR_STATUS_HI__ERROR_INFO_VALID_FLAG__SHIFT 0x2
+#define TCA_UE_ERR_STATUS_HI__ERROR_INFO__SHIFT 0x3
+#define TCA_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define TCA_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define TCA_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define TCA_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define TCA_UE_ERR_STATUS_HI__ERROR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TCA_UE_ERR_STATUS_HI__ERROR_INFO_MASK 0x007FFFF8L
+#define TCA_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define TCA_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+//TCX_UE_ERR_STATUS_LO
+#define TCX_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define TCX_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define TCX_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define TCX_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define TCX_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define TCX_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define TCX_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define TCX_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//TCX_UE_ERR_STATUS_HI
+#define TCX_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define TCX_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define TCX_UE_ERR_STATUS_HI__ERROR_INFO_VALID_FLAG__SHIFT 0x2
+#define TCX_UE_ERR_STATUS_HI__ERROR_INFO__SHIFT 0x3
+#define TCX_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define TCX_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define TCX_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define TCX_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define TCX_UE_ERR_STATUS_HI__ERROR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TCX_UE_ERR_STATUS_HI__ERROR_INFO_MASK 0x007FFFF8L
+#define TCX_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define TCX_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+//TCX_CE_ERR_STATUS_LO
+#define TCX_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define TCX_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define TCX_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define TCX_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define TCX_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define TCX_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define TCX_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define TCX_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//TCX_CE_ERR_STATUS_HI
+#define TCX_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define TCX_CE_ERR_STATUS_HI__ERROR_INFO_VALID_FLAG__SHIFT 0x2
+#define TCX_CE_ERR_STATUS_HI__ERROR_INFO__SHIFT 0x3
+#define TCX_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define TCX_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define TCX_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define TCX_CE_ERR_STATUS_HI__ERROR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TCX_CE_ERR_STATUS_HI__ERROR_INFO_MASK 0x007FFFF8L
+#define TCX_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define TCX_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+//TCC_UE_ERR_STATUS_LO
+#define TCC_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define TCC_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define TCC_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define TCC_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define TCC_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define TCC_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define TCC_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define TCC_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//TCC_UE_ERR_STATUS_HI
+#define TCC_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define TCC_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define TCC_UE_ERR_STATUS_HI__ERROR_INFO_VALID_FLAG__SHIFT 0x2
+#define TCC_UE_ERR_STATUS_HI__ERROR_INFO__SHIFT 0x3
+#define TCC_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define TCC_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define TCC_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define TCC_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define TCC_UE_ERR_STATUS_HI__ERROR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TCC_UE_ERR_STATUS_HI__ERROR_INFO_MASK 0x007FFFF8L
+#define TCC_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define TCC_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+//TCC_CE_ERR_STATUS_LO
+#define TCC_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define TCC_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define TCC_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define TCC_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define TCC_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define TCC_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define TCC_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define TCC_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//TCC_CE_ERR_STATUS_HI
+#define TCC_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define TCC_CE_ERR_STATUS_HI__ERROR_INFO_VALID_FLAG__SHIFT 0x2
+#define TCC_CE_ERR_STATUS_HI__ERROR_INFO__SHIFT 0x3
+#define TCC_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define TCC_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define TCC_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define TCC_CE_ERR_STATUS_HI__ERROR_INFO_VALID_FLAG_MASK 0x00000004L
+#define TCC_CE_ERR_STATUS_HI__ERROR_INFO_MASK 0x007FFFF8L
+#define TCC_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define TCC_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
// addressBlock: xcd0_gc_shdec
@@ -14384,6 +15236,150 @@
#define CP_VMID_STATUS__PREEMPT_CE_STATUS__SHIFT 0x10
#define CP_VMID_STATUS__PREEMPT_DE_STATUS_MASK 0x0000FFFFL
#define CP_VMID_STATUS__PREEMPT_CE_STATUS_MASK 0xFFFF0000L
+//CPC_UE_ERR_STATUS_LO
+#define CPC_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define CPC_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define CPC_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define CPC_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define CPC_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define CPC_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define CPC_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define CPC_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//CPC_UE_ERR_STATUS_HI
+#define CPC_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define CPC_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define CPC_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define CPC_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define CPC_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define CPC_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define CPC_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define CPC_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define CPC_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define CPC_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define CPC_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define CPC_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define CPC_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define CPC_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
+//CPC_CE_ERR_STATUS_LO
+#define CPC_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define CPC_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define CPC_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define CPC_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define CPC_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define CPC_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define CPC_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define CPC_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//CPC_CE_ERR_STATUS_HI
+#define CPC_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define CPC_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define CPC_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define CPC_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define CPC_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define CPC_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define CPC_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define CPC_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define CPC_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define CPC_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define CPC_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define CPC_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define CPC_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define CPC_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
+//CPF_UE_ERR_STATUS_LO
+#define CPF_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define CPF_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define CPF_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define CPF_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define CPF_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define CPF_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define CPF_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define CPF_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//CPF_UE_ERR_STATUS_HI
+#define CPF_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define CPF_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define CPF_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define CPF_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define CPF_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define CPF_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define CPF_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define CPF_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define CPF_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define CPF_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define CPF_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define CPF_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define CPF_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define CPF_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
+//CPF_CE_ERR_STATUS_LO
+#define CPF_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define CPF_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define CPF_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define CPF_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define CPF_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define CPF_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define CPF_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define CPF_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//CPF_CE_ERR_STATUS_HI
+#define CPF_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define CPF_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define CPF_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define CPF_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define CPF_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define CPF_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define CPF_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define CPF_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define CPF_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define CPF_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define CPF_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define CPF_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define CPF_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define CPF_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
+//CPG_UE_ERR_STATUS_LO
+#define CPG_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define CPG_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define CPG_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define CPG_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define CPG_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define CPG_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define CPG_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define CPG_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//CPG_UE_ERR_STATUS_HI
+#define CPG_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define CPG_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define CPG_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define CPG_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define CPG_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define CPG_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define CPG_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define CPG_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define CPG_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define CPG_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define CPG_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define CPG_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define CPG_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define CPG_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
+//CPG_CE_ERR_STATUS_LO
+#define CPG_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define CPG_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define CPG_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define CPG_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define CPG_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define CPG_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define CPG_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define CPG_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//CPG_CE_ERR_STATUS_HI
+#define CPG_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define CPG_CE_ERR_STATUS_HI__OTHER__SHIFT 0x1
+#define CPG_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define CPG_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define CPG_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define CPG_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define CPG_CE_ERR_STATUS_HI__RESERVED__SHIFT 0x1b
+#define CPG_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define CPG_CE_ERR_STATUS_HI__OTHER_MASK 0x00000002L
+#define CPG_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define CPG_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define CPG_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define CPG_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define CPG_CE_ERR_STATUS_HI__RESERVED_MASK 0xF8000000L
// addressBlock: xcd0_gc_cppdec2
@@ -22764,6 +23760,74 @@
#define SPI_WAVE_LIMIT_CNTL__GS_WAVE_GRAN_MASK 0x00000030L
#define SPI_WAVE_LIMIT_CNTL__HS_WAVE_GRAN_MASK 0x000000C0L
+// addressBlock: xcd0_gc_gccanedec
+//GC_CANE_ERR_STATUS
+#define GC_CANE_ERR_STATUS__SDPM_RDRSP_STATUS__SHIFT 0x0
+#define GC_CANE_ERR_STATUS__SDPM_WRRSP_STATUS__SHIFT 0x4
+#define GC_CANE_ERR_STATUS__SDPM_RDRSP_DATASTATUS__SHIFT 0x8
+#define GC_CANE_ERR_STATUS__SDPM_RDRSP_DATAPARITY_ERROR__SHIFT 0xa
+#define GC_CANE_ERR_STATUS__SDPS_DAT_ERROR__SHIFT 0xb
+#define GC_CANE_ERR_STATUS__SDPS_DAT_PARITY_ERROR__SHIFT 0xc
+#define GC_CANE_ERR_STATUS__CLEAR_ERROR_STATUS__SHIFT 0xd
+#define GC_CANE_ERR_STATUS__BUSY_ON_ERROR__SHIFT 0xe
+#define GC_CANE_ERR_STATUS__BUSY_ON_UER_ERROR__SHIFT 0xf
+#define GC_CANE_ERR_STATUS__FUE_FLAG__SHIFT 0x10
+#define GC_CANE_ERR_STATUS__INTERRUPT_ON_FATAL__SHIFT 0x11
+#define GC_CANE_ERR_STATUS__LEVEL_INTERRUPT__SHIFT 0x12
+#define GC_CANE_ERR_STATUS__SDPM_RDRSP_STATUS_MASK 0x0000000FL
+#define GC_CANE_ERR_STATUS__SDPM_WRRSP_STATUS_MASK 0x000000F0L
+#define GC_CANE_ERR_STATUS__SDPM_RDRSP_DATASTATUS_MASK 0x00000300L
+#define GC_CANE_ERR_STATUS__SDPM_RDRSP_DATAPARITY_ERROR_MASK 0x00000400L
+#define GC_CANE_ERR_STATUS__SDPS_DAT_ERROR_MASK 0x00000800L
+#define GC_CANE_ERR_STATUS__SDPS_DAT_PARITY_ERROR_MASK 0x00001000L
+#define GC_CANE_ERR_STATUS__CLEAR_ERROR_STATUS_MASK 0x00002000L
+#define GC_CANE_ERR_STATUS__BUSY_ON_ERROR_MASK 0x00004000L
+#define GC_CANE_ERR_STATUS__BUSY_ON_UER_ERROR_MASK 0x00008000L
+#define GC_CANE_ERR_STATUS__FUE_FLAG_MASK 0x00010000L
+#define GC_CANE_ERR_STATUS__INTERRUPT_ON_FATAL_MASK 0x00020000L
+#define GC_CANE_ERR_STATUS__LEVEL_INTERRUPT_MASK 0x00040000L
+//GC_CANE_UE_ERR_STATUS_LO
+#define GC_CANE_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define GC_CANE_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define GC_CANE_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define GC_CANE_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define GC_CANE_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define GC_CANE_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define GC_CANE_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define GC_CANE_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//GC_CANE_UE_ERR_STATUS_HI
+#define GC_CANE_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define GC_CANE_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define GC_CANE_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define GC_CANE_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define GC_CANE_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define GC_CANE_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define GC_CANE_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define GC_CANE_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define GC_CANE_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define GC_CANE_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define GC_CANE_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define GC_CANE_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+//GC_CANE_CE_ERR_STATUS_LO
+#define GC_CANE_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define GC_CANE_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define GC_CANE_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define GC_CANE_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define GC_CANE_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define GC_CANE_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define GC_CANE_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define GC_CANE_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//GC_CANE_CE_ERR_STATUS_HI
+#define GC_CANE_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define GC_CANE_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define GC_CANE_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define GC_CANE_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define GC_CANE_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define GC_CANE_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define GC_CANE_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define GC_CANE_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define GC_CANE_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define GC_CANE_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
// addressBlock: xcd0_gc_perfddec
//CPG_PERFCOUNTER1_LO
@@ -26471,6 +27535,30 @@
//RLC_CPG_STAT_INVAL
#define RLC_CPG_STAT_INVAL__CPG_stat_inval__SHIFT 0x0
#define RLC_CPG_STAT_INVAL__CPG_stat_inval_MASK 0x00000001L
+//RLC_UE_ERR_STATUS_LOW
+#define RLC_UE_ERR_STATUS_LOW__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define RLC_UE_ERR_STATUS_LOW__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define RLC_UE_ERR_STATUS_LOW__ADDRESS__SHIFT 0x2
+#define RLC_UE_ERR_STATUS_LOW__MEMORY_ID__SHIFT 0x18
+#define RLC_UE_ERR_STATUS_LOW__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define RLC_UE_ERR_STATUS_LOW__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define RLC_UE_ERR_STATUS_LOW__ADDRESS_MASK 0x00FFFFFCL
+#define RLC_UE_ERR_STATUS_LOW__MEMORY_ID_MASK 0xFF000000L
+//RLC_UE_ERR_STATUS_HIGH
+#define RLC_UE_ERR_STATUS_HIGH__ECC__SHIFT 0x0
+#define RLC_UE_ERR_STATUS_HIGH__PARITY__SHIFT 0x1
+#define RLC_UE_ERR_STATUS_HIGH__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define RLC_UE_ERR_STATUS_HIGH__ERR_INFO__SHIFT 0x3
+#define RLC_UE_ERR_STATUS_HIGH__UE_CNT__SHIFT 0x17
+#define RLC_UE_ERR_STATUS_HIGH__FED_CNT__SHIFT 0x1a
+#define RLC_UE_ERR_STATUS_HIGH__RESERVED__SHIFT 0x1d
+#define RLC_UE_ERR_STATUS_HIGH__ECC_MASK 0x00000001L
+#define RLC_UE_ERR_STATUS_HIGH__PARITY_MASK 0x00000002L
+#define RLC_UE_ERR_STATUS_HIGH__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define RLC_UE_ERR_STATUS_HIGH__ERR_INFO_MASK 0x007FFFF8L
+#define RLC_UE_ERR_STATUS_HIGH__UE_CNT_MASK 0x03800000L
+#define RLC_UE_ERR_STATUS_HIGH__FED_CNT_MASK 0x1C000000L
+#define RLC_UE_ERR_STATUS_HIGH__RESERVED_MASK 0xE0000000L
//RLC_DSM_CNTL
#define RLC_DSM_CNTL__RLCG_INSTR_RAM_IRRITATOR_DATA_SEL__SHIFT 0x0
#define RLC_DSM_CNTL__RLCG_INSTR_RAM_IRRITATOR_SINGLE_WRITE__SHIFT 0x2
@@ -26573,6 +27661,30 @@
#define RLC_DSM_CNTL2A__RLC_SPM_SE2_SCRATCH_RAM_SELECT_INJECT_DELAY_MASK 0x00000100L
#define RLC_DSM_CNTL2A__RLC_SPM_SE3_SCRATCH_RAM_ENABLE_ERROR_INJECT_MASK 0x00000600L
#define RLC_DSM_CNTL2A__RLC_SPM_SE3_SCRATCH_RAM_SELECT_INJECT_DELAY_MASK 0x00000800L
+//RLC_CE_ERR_STATUS_LOW
+#define RLC_CE_ERR_STATUS_LOW__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define RLC_CE_ERR_STATUS_LOW__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define RLC_CE_ERR_STATUS_LOW__ADDRESS__SHIFT 0x2
+#define RLC_CE_ERR_STATUS_LOW__MEMORY_ID__SHIFT 0x18
+#define RLC_CE_ERR_STATUS_LOW__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define RLC_CE_ERR_STATUS_LOW__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define RLC_CE_ERR_STATUS_LOW__ADDRESS_MASK 0x00FFFFFCL
+#define RLC_CE_ERR_STATUS_LOW__MEMORY_ID_MASK 0xFF000000L
+//RLC_CE_ERR_STATUS_HIGH
+#define RLC_CE_ERR_STATUS_HIGH__ECC__SHIFT 0x0
+#define RLC_CE_ERR_STATUS_HIGH__OTHER__SHIFT 0x1
+#define RLC_CE_ERR_STATUS_HIGH__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define RLC_CE_ERR_STATUS_HIGH__ERR_INFO__SHIFT 0x3
+#define RLC_CE_ERR_STATUS_HIGH__CE_CNT__SHIFT 0x17
+#define RLC_CE_ERR_STATUS_HIGH__POISON__SHIFT 0x1a
+#define RLC_CE_ERR_STATUS_HIGH__RESERVED__SHIFT 0x1b
+#define RLC_CE_ERR_STATUS_HIGH__ECC_MASK 0x00000001L
+#define RLC_CE_ERR_STATUS_HIGH__OTHER_MASK 0x00000002L
+#define RLC_CE_ERR_STATUS_HIGH__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define RLC_CE_ERR_STATUS_HIGH__ERR_INFO_MASK 0x007FFFF8L
+#define RLC_CE_ERR_STATUS_HIGH__CE_CNT_MASK 0x03800000L
+#define RLC_CE_ERR_STATUS_HIGH__POISON_MASK 0x04000000L
+#define RLC_CE_ERR_STATUS_HIGH__RESERVED_MASK 0xF8000000L
//RLC_RLCV_SPARE_INT
#define RLC_RLCV_SPARE_INT__INTERRUPT__SHIFT 0x0
#define RLC_RLCV_SPARE_INT__RESERVED__SHIFT 0x1
diff --git a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_1_8_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_1_8_0_offset.h
index 8bcc81f2dfc0..879ee9de3ff3 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_1_8_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_1_8_0_offset.h
@@ -1491,6 +1491,10 @@
#define regMMEA0_PERFCOUNTER1_CFG_BASE_IDX 0
#define regMMEA0_PERFCOUNTER_RSLT_CNTL 0x0400
#define regMMEA0_PERFCOUNTER_RSLT_CNTL_BASE_IDX 0
+#define regMMEA0_UE_ERR_STATUS_LO 0x0406
+#define regMMEA0_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regMMEA0_UE_ERR_STATUS_HI 0x0407
+#define regMMEA0_UE_ERR_STATUS_HI_BASE_IDX 0
#define regMMEA0_DSM_CNTL 0x0408
#define regMMEA0_DSM_CNTL_BASE_IDX 0
#define regMMEA0_DSM_CNTLA 0x0409
@@ -1511,8 +1515,12 @@
#define regMMEA0_ERR_STATUS_BASE_IDX 0
#define regMMEA0_MISC2 0x0412
#define regMMEA0_MISC2_BASE_IDX 0
+#define regMMEA0_CE_ERR_STATUS_LO 0x0414
+#define regMMEA0_CE_ERR_STATUS_LO_BASE_IDX 0
#define regMMEA0_MISC_AON 0x0415
#define regMMEA0_MISC_AON_BASE_IDX 0
+#define regMMEA0_CE_ERR_STATUS_HI 0x0416
+#define regMMEA0_CE_ERR_STATUS_HI_BASE_IDX 0
// addressBlock: aid_mmhub_ea_mmeadec1
@@ -1709,6 +1717,10 @@
#define regMMEA1_PERFCOUNTER1_CFG_BASE_IDX 0
#define regMMEA1_PERFCOUNTER_RSLT_CNTL 0x0540
#define regMMEA1_PERFCOUNTER_RSLT_CNTL_BASE_IDX 0
+#define regMMEA1_UE_ERR_STATUS_LO 0x0546
+#define regMMEA1_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regMMEA1_UE_ERR_STATUS_HI 0x0547
+#define regMMEA1_UE_ERR_STATUS_HI_BASE_IDX 0
#define regMMEA1_DSM_CNTL 0x0548
#define regMMEA1_DSM_CNTL_BASE_IDX 0
#define regMMEA1_DSM_CNTLA 0x0549
@@ -1729,8 +1741,12 @@
#define regMMEA1_ERR_STATUS_BASE_IDX 0
#define regMMEA1_MISC2 0x0552
#define regMMEA1_MISC2_BASE_IDX 0
+#define regMMEA1_CE_ERR_STATUS_LO 0x0554
+#define regMMEA1_CE_ERR_STATUS_LO_BASE_IDX 0
#define regMMEA1_MISC_AON 0x0555
#define regMMEA1_MISC_AON_BASE_IDX 0
+#define regMMEA1_CE_ERR_STATUS_HI 0x0556
+#define regMMEA1_CE_ERR_STATUS_HI_BASE_IDX 0
// addressBlock: aid_mmhub_ea_mmeadec2
@@ -1927,6 +1943,10 @@
#define regMMEA2_PERFCOUNTER1_CFG_BASE_IDX 0
#define regMMEA2_PERFCOUNTER_RSLT_CNTL 0x0680
#define regMMEA2_PERFCOUNTER_RSLT_CNTL_BASE_IDX 0
+#define regMMEA2_UE_ERR_STATUS_LO 0x0686
+#define regMMEA2_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regMMEA2_UE_ERR_STATUS_HI 0x0687
+#define regMMEA2_UE_ERR_STATUS_HI_BASE_IDX 0
#define regMMEA2_DSM_CNTL 0x0688
#define regMMEA2_DSM_CNTL_BASE_IDX 0
#define regMMEA2_DSM_CNTLA 0x0689
@@ -1947,8 +1967,12 @@
#define regMMEA2_ERR_STATUS_BASE_IDX 0
#define regMMEA2_MISC2 0x0692
#define regMMEA2_MISC2_BASE_IDX 0
+#define regMMEA2_CE_ERR_STATUS_LO 0x0694
+#define regMMEA2_CE_ERR_STATUS_LO_BASE_IDX 0
#define regMMEA2_MISC_AON 0x0695
#define regMMEA2_MISC_AON_BASE_IDX 0
+#define regMMEA2_CE_ERR_STATUS_HI 0x0696
+#define regMMEA2_CE_ERR_STATUS_HI_BASE_IDX 0
// addressBlock: aid_mmhub_ea_mmeadec3
@@ -2145,6 +2169,10 @@
#define regMMEA3_PERFCOUNTER1_CFG_BASE_IDX 0
#define regMMEA3_PERFCOUNTER_RSLT_CNTL 0x07c0
#define regMMEA3_PERFCOUNTER_RSLT_CNTL_BASE_IDX 0
+#define regMMEA3_UE_ERR_STATUS_LO 0x07c6
+#define regMMEA3_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regMMEA3_UE_ERR_STATUS_HI 0x07c7
+#define regMMEA3_UE_ERR_STATUS_HI_BASE_IDX 0
#define regMMEA3_DSM_CNTL 0x07c8
#define regMMEA3_DSM_CNTL_BASE_IDX 0
#define regMMEA3_DSM_CNTLA 0x07c9
@@ -2165,9 +2193,12 @@
#define regMMEA3_ERR_STATUS_BASE_IDX 0
#define regMMEA3_MISC2 0x07d2
#define regMMEA3_MISC2_BASE_IDX 0
+#define regMMEA3_CE_ERR_STATUS_LO 0x07d4
+#define regMMEA3_CE_ERR_STATUS_LO_BASE_IDX 0
#define regMMEA3_MISC_AON 0x07d5
#define regMMEA3_MISC_AON_BASE_IDX 0
-
+#define regMMEA3_CE_ERR_STATUS_HI 0x07d6
+#define regMMEA3_CE_ERR_STATUS_HI_BASE_IDX 0
// addressBlock: aid_mmhub_ea_mmeadec4
// base address: 0x62000
@@ -2363,6 +2394,10 @@
#define regMMEA4_PERFCOUNTER1_CFG_BASE_IDX 0
#define regMMEA4_PERFCOUNTER_RSLT_CNTL 0x0900
#define regMMEA4_PERFCOUNTER_RSLT_CNTL_BASE_IDX 0
+#define regMMEA4_UE_ERR_STATUS_LO 0x0906
+#define regMMEA4_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regMMEA4_UE_ERR_STATUS_HI 0x0907
+#define regMMEA4_UE_ERR_STATUS_HI_BASE_IDX 0
#define regMMEA4_DSM_CNTL 0x0908
#define regMMEA4_DSM_CNTL_BASE_IDX 0
#define regMMEA4_DSM_CNTLA 0x0909
@@ -2383,9 +2418,12 @@
#define regMMEA4_ERR_STATUS_BASE_IDX 0
#define regMMEA4_MISC2 0x0912
#define regMMEA4_MISC2_BASE_IDX 0
+#define regMMEA4_CE_ERR_STATUS_LO 0x0914
+#define regMMEA4_CE_ERR_STATUS_LO_BASE_IDX 0
#define regMMEA4_MISC_AON 0x0915
#define regMMEA4_MISC_AON_BASE_IDX 0
-
+#define regMMEA4_CE_ERR_STATUS_HI 0x0916
+#define regMMEA4_CE_ERR_STATUS_HI_BASE_IDX 0
// addressBlock: aid_mmhub_pctldec0
// base address: 0x62a00
@@ -3310,5 +3348,19 @@
#define regL2TLB_PERFCOUNTER_HI 0x0d2d
#define regL2TLB_PERFCOUNTER_HI_BASE_IDX 0
+// addressBlock: aid_mmhub_mm_cane_mmcanedec
+// base address: 0x635f0
+#define regMM_CANE_ICG_CTRL 0x0d8a
+#define regMM_CANE_ICG_CTRL_BASE_IDX 0
+#define regMM_CANE_ERR_STATUS 0x0d8c
+#define regMM_CANE_ERR_STATUS_BASE_IDX 0
+#define regMM_CANE_UE_ERR_STATUS_LO 0x0d8d
+#define regMM_CANE_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regMM_CANE_UE_ERR_STATUS_HI 0x0d8e
+#define regMM_CANE_UE_ERR_STATUS_HI_BASE_IDX 0
+#define regMM_CANE_CE_ERR_STATUS_LO 0x0d8f
+#define regMM_CANE_CE_ERR_STATUS_LO_BASE_IDX 0
+#define regMM_CANE_CE_ERR_STATUS_HI 0x0d90
+#define regMM_CANE_CE_ERR_STATUS_HI_BASE_IDX 0
#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_1_8_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_1_8_0_sh_mask.h
index af41468ce69f..088c1f02aa43 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_1_8_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_1_8_0_sh_mask.h
@@ -10470,6 +10470,30 @@
#define MMEA0_PERFCOUNTER_RSLT_CNTL__ENABLE_ANY_MASK 0x01000000L
#define MMEA0_PERFCOUNTER_RSLT_CNTL__CLEAR_ALL_MASK 0x02000000L
#define MMEA0_PERFCOUNTER_RSLT_CNTL__STOP_ALL_ON_SATURATE_MASK 0x04000000L
+//MMEA0_UE_ERR_STATUS_LO
+#define MMEA0_UE_ERR_STATUS_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define MMEA0_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define MMEA0_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define MMEA0_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define MMEA0_UE_ERR_STATUS_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define MMEA0_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define MMEA0_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define MMEA0_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//MMEA0_UE_ERR_STATUS_HI
+#define MMEA0_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define MMEA0_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define MMEA0_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define MMEA0_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define MMEA0_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define MMEA0_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define MMEA0_UE_ERR_STATUS_HI__RESERVED_FIELD__SHIFT 0x1d
+#define MMEA0_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define MMEA0_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define MMEA0_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define MMEA0_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define MMEA0_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define MMEA0_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define MMEA0_UE_ERR_STATUS_HI__RESERVED_FIELD_MASK 0xE0000000L
//MMEA0_DSM_CNTL
#define MMEA0_DSM_CNTL__DRAMRD_CMDMEM_DSM_IRRITATOR_DATA__SHIFT 0x0
#define MMEA0_DSM_CNTL__DRAMRD_CMDMEM_ENABLE_SINGLE_WRITE__SHIFT 0x2
@@ -10718,12 +10742,35 @@
#define MMEA0_MISC2__DRAM_WR_THROTTLE_MASK 0x00020000L
#define MMEA0_MISC2__GMI_RD_THROTTLE_MASK 0x00040000L
#define MMEA0_MISC2__GMI_WR_THROTTLE_MASK 0x00080000L
+//MMEA0_CE_ERR_STATUS_LO
+#define MMEA0_CE_ERR_STATUS_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define MMEA0_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define MMEA0_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define MMEA0_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define MMEA0_CE_ERR_STATUS_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define MMEA0_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define MMEA0_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define MMEA0_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
//MMEA0_MISC_AON
#define MMEA0_MISC_AON__LINKMGR_PARTACK_HYSTERESIS__SHIFT 0x0
#define MMEA0_MISC_AON__LINKMGR_PARTACK_DEASSERT_MODE__SHIFT 0x2
#define MMEA0_MISC_AON__LINKMGR_PARTACK_HYSTERESIS_MASK 0x00000003L
#define MMEA0_MISC_AON__LINKMGR_PARTACK_DEASSERT_MODE_MASK 0x00000004L
-
+//MMEA0_CE_ERR_STATUS_HI
+#define MMEA0_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define MMEA0_CE_ERR_STATUS_HI__RESERVED_FIELD0__SHIFT 0x1
+#define MMEA0_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define MMEA0_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define MMEA0_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define MMEA0_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define MMEA0_CE_ERR_STATUS_HI__RESERVED_FIELD1__SHIFT 0x1b
+#define MMEA0_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define MMEA0_CE_ERR_STATUS_HI__RESERVED_FIELD0_MASK 0x00000002L
+#define MMEA0_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define MMEA0_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define MMEA0_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define MMEA0_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define MMEA0_CE_ERR_STATUS_HI__RESERVED_FIELD1_MASK 0xF8000000L
// addressBlock: aid_mmhub_ea_mmeadec1
//MMEA1_DRAM_RD_CLI2GRP_MAP0
@@ -12418,6 +12465,30 @@
#define MMEA1_PERFCOUNTER_RSLT_CNTL__ENABLE_ANY_MASK 0x01000000L
#define MMEA1_PERFCOUNTER_RSLT_CNTL__CLEAR_ALL_MASK 0x02000000L
#define MMEA1_PERFCOUNTER_RSLT_CNTL__STOP_ALL_ON_SATURATE_MASK 0x04000000L
+//MMEA1_UE_ERR_STATUS_LO
+#define MMEA1_UE_ERR_STATUS_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define MMEA1_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define MMEA1_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define MMEA1_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define MMEA1_UE_ERR_STATUS_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define MMEA1_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define MMEA1_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define MMEA1_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//MMEA1_UE_ERR_STATUS_HI
+#define MMEA1_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define MMEA1_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define MMEA1_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define MMEA1_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define MMEA1_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define MMEA1_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define MMEA1_UE_ERR_STATUS_HI__RESERVED_FIELD__SHIFT 0x1d
+#define MMEA1_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define MMEA1_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define MMEA1_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define MMEA1_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define MMEA1_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define MMEA1_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define MMEA1_UE_ERR_STATUS_HI__RESERVED_FIELD_MASK 0xE0000000L
//MMEA1_DSM_CNTL
#define MMEA1_DSM_CNTL__DRAMRD_CMDMEM_DSM_IRRITATOR_DATA__SHIFT 0x0
#define MMEA1_DSM_CNTL__DRAMRD_CMDMEM_ENABLE_SINGLE_WRITE__SHIFT 0x2
@@ -12666,12 +12737,35 @@
#define MMEA1_MISC2__DRAM_WR_THROTTLE_MASK 0x00020000L
#define MMEA1_MISC2__GMI_RD_THROTTLE_MASK 0x00040000L
#define MMEA1_MISC2__GMI_WR_THROTTLE_MASK 0x00080000L
+//MMEA1_CE_ERR_STATUS_LO
+#define MMEA1_CE_ERR_STATUS_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define MMEA1_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define MMEA1_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define MMEA1_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define MMEA1_CE_ERR_STATUS_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define MMEA1_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define MMEA1_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define MMEA1_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
//MMEA1_MISC_AON
#define MMEA1_MISC_AON__LINKMGR_PARTACK_HYSTERESIS__SHIFT 0x0
#define MMEA1_MISC_AON__LINKMGR_PARTACK_DEASSERT_MODE__SHIFT 0x2
#define MMEA1_MISC_AON__LINKMGR_PARTACK_HYSTERESIS_MASK 0x00000003L
#define MMEA1_MISC_AON__LINKMGR_PARTACK_DEASSERT_MODE_MASK 0x00000004L
-
+//MMEA1_CE_ERR_STATUS_HI
+#define MMEA1_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define MMEA1_CE_ERR_STATUS_HI__RESERVED_FIELD0__SHIFT 0x1
+#define MMEA1_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define MMEA1_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define MMEA1_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define MMEA1_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define MMEA1_CE_ERR_STATUS_HI__RESERVED_FIELD1__SHIFT 0x1b
+#define MMEA1_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define MMEA1_CE_ERR_STATUS_HI__RESERVED_FIELD0_MASK 0x00000002L
+#define MMEA1_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define MMEA1_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define MMEA1_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define MMEA1_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define MMEA1_CE_ERR_STATUS_HI__RESERVED_FIELD1_MASK 0xF8000000L
// addressBlock: aid_mmhub_ea_mmeadec2
//MMEA2_DRAM_RD_CLI2GRP_MAP0
@@ -14366,6 +14460,30 @@
#define MMEA2_PERFCOUNTER_RSLT_CNTL__ENABLE_ANY_MASK 0x01000000L
#define MMEA2_PERFCOUNTER_RSLT_CNTL__CLEAR_ALL_MASK 0x02000000L
#define MMEA2_PERFCOUNTER_RSLT_CNTL__STOP_ALL_ON_SATURATE_MASK 0x04000000L
+//MMEA2_UE_ERR_STATUS_LO
+#define MMEA2_UE_ERR_STATUS_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define MMEA2_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define MMEA2_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define MMEA2_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define MMEA2_UE_ERR_STATUS_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define MMEA2_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define MMEA2_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define MMEA2_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//MMEA2_UE_ERR_STATUS_HI
+#define MMEA2_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define MMEA2_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define MMEA2_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define MMEA2_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define MMEA2_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define MMEA2_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define MMEA2_UE_ERR_STATUS_HI__RESERVED_FIELD__SHIFT 0x1d
+#define MMEA2_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define MMEA2_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define MMEA2_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define MMEA2_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define MMEA2_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define MMEA2_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define MMEA2_UE_ERR_STATUS_HI__RESERVED_FIELD_MASK 0xE0000000L
//MMEA2_DSM_CNTL
#define MMEA2_DSM_CNTL__DRAMRD_CMDMEM_DSM_IRRITATOR_DATA__SHIFT 0x0
#define MMEA2_DSM_CNTL__DRAMRD_CMDMEM_ENABLE_SINGLE_WRITE__SHIFT 0x2
@@ -14614,12 +14732,35 @@
#define MMEA2_MISC2__DRAM_WR_THROTTLE_MASK 0x00020000L
#define MMEA2_MISC2__GMI_RD_THROTTLE_MASK 0x00040000L
#define MMEA2_MISC2__GMI_WR_THROTTLE_MASK 0x00080000L
+//MMEA2_CE_ERR_STATUS_LO
+#define MMEA2_CE_ERR_STATUS_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define MMEA2_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define MMEA2_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define MMEA2_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define MMEA2_CE_ERR_STATUS_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define MMEA2_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define MMEA2_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define MMEA2_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
//MMEA2_MISC_AON
#define MMEA2_MISC_AON__LINKMGR_PARTACK_HYSTERESIS__SHIFT 0x0
#define MMEA2_MISC_AON__LINKMGR_PARTACK_DEASSERT_MODE__SHIFT 0x2
#define MMEA2_MISC_AON__LINKMGR_PARTACK_HYSTERESIS_MASK 0x00000003L
#define MMEA2_MISC_AON__LINKMGR_PARTACK_DEASSERT_MODE_MASK 0x00000004L
-
+//MMEA2_CE_ERR_STATUS_HI
+#define MMEA2_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define MMEA2_CE_ERR_STATUS_HI__RESERVED_FIELD0__SHIFT 0x1
+#define MMEA2_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define MMEA2_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define MMEA2_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define MMEA2_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define MMEA2_CE_ERR_STATUS_HI__RESERVED_FIELD1__SHIFT 0x1b
+#define MMEA2_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define MMEA2_CE_ERR_STATUS_HI__RESERVED_FIELD0_MASK 0x00000002L
+#define MMEA2_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define MMEA2_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define MMEA2_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define MMEA2_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define MMEA2_CE_ERR_STATUS_HI__RESERVED_FIELD1_MASK 0xF8000000L
// addressBlock: aid_mmhub_ea_mmeadec3
//MMEA3_DRAM_RD_CLI2GRP_MAP0
@@ -16314,6 +16455,30 @@
#define MMEA3_PERFCOUNTER_RSLT_CNTL__ENABLE_ANY_MASK 0x01000000L
#define MMEA3_PERFCOUNTER_RSLT_CNTL__CLEAR_ALL_MASK 0x02000000L
#define MMEA3_PERFCOUNTER_RSLT_CNTL__STOP_ALL_ON_SATURATE_MASK 0x04000000L
+//MMEA3_UE_ERR_STATUS_LO
+#define MMEA3_UE_ERR_STATUS_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define MMEA3_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define MMEA3_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define MMEA3_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define MMEA3_UE_ERR_STATUS_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define MMEA3_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define MMEA3_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define MMEA3_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//MMEA3_UE_ERR_STATUS_HI
+#define MMEA3_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define MMEA3_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define MMEA3_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define MMEA3_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define MMEA3_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define MMEA3_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define MMEA3_UE_ERR_STATUS_HI__RESERVED_FIELD__SHIFT 0x1d
+#define MMEA3_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define MMEA3_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define MMEA3_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define MMEA3_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define MMEA3_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define MMEA3_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define MMEA3_UE_ERR_STATUS_HI__RESERVED_FIELD_MASK 0xE0000000L
//MMEA3_DSM_CNTL
#define MMEA3_DSM_CNTL__DRAMRD_CMDMEM_DSM_IRRITATOR_DATA__SHIFT 0x0
#define MMEA3_DSM_CNTL__DRAMRD_CMDMEM_ENABLE_SINGLE_WRITE__SHIFT 0x2
@@ -16562,12 +16727,35 @@
#define MMEA3_MISC2__DRAM_WR_THROTTLE_MASK 0x00020000L
#define MMEA3_MISC2__GMI_RD_THROTTLE_MASK 0x00040000L
#define MMEA3_MISC2__GMI_WR_THROTTLE_MASK 0x00080000L
+//MMEA3_CE_ERR_STATUS_LO
+#define MMEA3_CE_ERR_STATUS_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define MMEA3_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define MMEA3_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define MMEA3_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define MMEA3_CE_ERR_STATUS_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define MMEA3_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define MMEA3_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define MMEA3_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
//MMEA3_MISC_AON
#define MMEA3_MISC_AON__LINKMGR_PARTACK_HYSTERESIS__SHIFT 0x0
#define MMEA3_MISC_AON__LINKMGR_PARTACK_DEASSERT_MODE__SHIFT 0x2
#define MMEA3_MISC_AON__LINKMGR_PARTACK_HYSTERESIS_MASK 0x00000003L
#define MMEA3_MISC_AON__LINKMGR_PARTACK_DEASSERT_MODE_MASK 0x00000004L
-
+//MMEA3_CE_ERR_STATUS_HI
+#define MMEA3_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define MMEA3_CE_ERR_STATUS_HI__RESERVED_FIELD0__SHIFT 0x1
+#define MMEA3_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define MMEA3_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define MMEA3_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define MMEA3_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define MMEA3_CE_ERR_STATUS_HI__RESERVED_FIELD1__SHIFT 0x1b
+#define MMEA3_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define MMEA3_CE_ERR_STATUS_HI__RESERVED_FIELD0_MASK 0x00000002L
+#define MMEA3_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define MMEA3_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define MMEA3_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define MMEA3_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define MMEA3_CE_ERR_STATUS_HI__RESERVED_FIELD1_MASK 0xF8000000L
// addressBlock: aid_mmhub_ea_mmeadec4
//MMEA4_DRAM_RD_CLI2GRP_MAP0
@@ -18262,6 +18450,30 @@
#define MMEA4_PERFCOUNTER_RSLT_CNTL__ENABLE_ANY_MASK 0x01000000L
#define MMEA4_PERFCOUNTER_RSLT_CNTL__CLEAR_ALL_MASK 0x02000000L
#define MMEA4_PERFCOUNTER_RSLT_CNTL__STOP_ALL_ON_SATURATE_MASK 0x04000000L
+//MMEA4_UE_ERR_STATUS_LO
+#define MMEA4_UE_ERR_STATUS_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define MMEA4_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define MMEA4_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define MMEA4_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define MMEA4_UE_ERR_STATUS_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define MMEA4_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define MMEA4_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define MMEA4_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//MMEA4_UE_ERR_STATUS_HI
+#define MMEA4_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define MMEA4_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define MMEA4_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define MMEA4_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define MMEA4_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define MMEA4_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define MMEA4_UE_ERR_STATUS_HI__RESERVED_FIELD__SHIFT 0x1d
+#define MMEA4_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define MMEA4_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define MMEA4_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define MMEA4_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define MMEA4_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define MMEA4_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define MMEA4_UE_ERR_STATUS_HI__RESERVED_FIELD_MASK 0xE0000000L
//MMEA4_DSM_CNTL
#define MMEA4_DSM_CNTL__DRAMRD_CMDMEM_DSM_IRRITATOR_DATA__SHIFT 0x0
#define MMEA4_DSM_CNTL__DRAMRD_CMDMEM_ENABLE_SINGLE_WRITE__SHIFT 0x2
@@ -18510,12 +18722,35 @@
#define MMEA4_MISC2__DRAM_WR_THROTTLE_MASK 0x00020000L
#define MMEA4_MISC2__GMI_RD_THROTTLE_MASK 0x00040000L
#define MMEA4_MISC2__GMI_WR_THROTTLE_MASK 0x00080000L
+//MMEA4_CE_ERR_STATUS_LO
+#define MMEA4_CE_ERR_STATUS_LO__STATUS_VALID_FLAG__SHIFT 0x0
+#define MMEA4_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define MMEA4_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define MMEA4_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define MMEA4_CE_ERR_STATUS_LO__STATUS_VALID_FLAG_MASK 0x00000001L
+#define MMEA4_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define MMEA4_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define MMEA4_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
//MMEA4_MISC_AON
#define MMEA4_MISC_AON__LINKMGR_PARTACK_HYSTERESIS__SHIFT 0x0
#define MMEA4_MISC_AON__LINKMGR_PARTACK_DEASSERT_MODE__SHIFT 0x2
#define MMEA4_MISC_AON__LINKMGR_PARTACK_HYSTERESIS_MASK 0x00000003L
#define MMEA4_MISC_AON__LINKMGR_PARTACK_DEASSERT_MODE_MASK 0x00000004L
-
+//MMEA4_CE_ERR_STATUS_HI
+#define MMEA4_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define MMEA4_CE_ERR_STATUS_HI__RESERVED_FIELD0__SHIFT 0x1
+#define MMEA4_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define MMEA4_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define MMEA4_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define MMEA4_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define MMEA4_CE_ERR_STATUS_HI__RESERVED_FIELD1__SHIFT 0x1b
+#define MMEA4_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define MMEA4_CE_ERR_STATUS_HI__RESERVED_FIELD0_MASK 0x00000002L
+#define MMEA4_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define MMEA4_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define MMEA4_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define MMEA4_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
+#define MMEA4_CE_ERR_STATUS_HI__RESERVED_FIELD1_MASK 0xF8000000L
// addressBlock: aid_mmhub_pctldec0
//PCTL0_CTRL
@@ -22311,5 +22546,83 @@
#define L2TLB_PERFCOUNTER_HI__COUNTER_HI_MASK 0x0000FFFFL
#define L2TLB_PERFCOUNTER_HI__COMPARE_VALUE_MASK 0xFFFF0000L
-
+// addressBlock: aid_mmhub_mm_cane_mmcanedec
+//MM_CANE_ICG_CTRL
+#define MM_CANE_ICG_CTRL__SOFT_OVERRIDE_IREQ0__SHIFT 0x0
+#define MM_CANE_ICG_CTRL__SOFT_OVERRIDE_ATRET__SHIFT 0x1
+#define MM_CANE_ICG_CTRL__SOFT_OVERRIDE_OREQ__SHIFT 0x2
+#define MM_CANE_ICG_CTRL__SOFT_OVERRIDE_REGISTER__SHIFT 0x3
+#define MM_CANE_ICG_CTRL__SOFT_OVERRIDE_SDPM_RETURN__SHIFT 0x4
+#define MM_CANE_ICG_CTRL__SOFT_OVERRIDE_IREQ0_MASK 0x00000001L
+#define MM_CANE_ICG_CTRL__SOFT_OVERRIDE_ATRET_MASK 0x00000002L
+#define MM_CANE_ICG_CTRL__SOFT_OVERRIDE_OREQ_MASK 0x00000004L
+#define MM_CANE_ICG_CTRL__SOFT_OVERRIDE_REGISTER_MASK 0x00000008L
+#define MM_CANE_ICG_CTRL__SOFT_OVERRIDE_SDPM_RETURN_MASK 0x00000010L
+//MM_CANE_ERR_STATUS
+#define MM_CANE_ERR_STATUS__SDPM_RDRSP_STATUS__SHIFT 0x0
+#define MM_CANE_ERR_STATUS__SDPM_WRRSP_STATUS__SHIFT 0x4
+#define MM_CANE_ERR_STATUS__SDPM_RDRSP_DATASTATUS__SHIFT 0x8
+#define MM_CANE_ERR_STATUS__SDPM_RDRSP_DATAPARITY_ERROR__SHIFT 0xa
+#define MM_CANE_ERR_STATUS__SDPS_DAT_ERROR__SHIFT 0xb
+#define MM_CANE_ERR_STATUS__SDPS_DAT_PARITY_ERROR__SHIFT 0xc
+#define MM_CANE_ERR_STATUS__CLEAR_ERROR_STATUS__SHIFT 0xd
+#define MM_CANE_ERR_STATUS__BUSY_ON_ERROR__SHIFT 0xe
+#define MM_CANE_ERR_STATUS__BUSY_ON_UER_ERROR__SHIFT 0xf
+#define MM_CANE_ERR_STATUS__FUE_FLAG__SHIFT 0x10
+#define MM_CANE_ERR_STATUS__INTERRUPT_ON_FATAL__SHIFT 0x11
+#define MM_CANE_ERR_STATUS__LEVEL_INTERRUPT__SHIFT 0x12
+#define MM_CANE_ERR_STATUS__SDPM_RDRSP_STATUS_MASK 0x0000000FL
+#define MM_CANE_ERR_STATUS__SDPM_WRRSP_STATUS_MASK 0x000000F0L
+#define MM_CANE_ERR_STATUS__SDPM_RDRSP_DATASTATUS_MASK 0x00000300L
+#define MM_CANE_ERR_STATUS__SDPM_RDRSP_DATAPARITY_ERROR_MASK 0x00000400L
+#define MM_CANE_ERR_STATUS__SDPS_DAT_ERROR_MASK 0x00000800L
+#define MM_CANE_ERR_STATUS__SDPS_DAT_PARITY_ERROR_MASK 0x00001000L
+#define MM_CANE_ERR_STATUS__CLEAR_ERROR_STATUS_MASK 0x00002000L
+#define MM_CANE_ERR_STATUS__BUSY_ON_ERROR_MASK 0x00004000L
+#define MM_CANE_ERR_STATUS__BUSY_ON_UER_ERROR_MASK 0x00008000L
+#define MM_CANE_ERR_STATUS__FUE_FLAG_MASK 0x00010000L
+#define MM_CANE_ERR_STATUS__INTERRUPT_ON_FATAL_MASK 0x00020000L
+#define MM_CANE_ERR_STATUS__LEVEL_INTERRUPT_MASK 0x00040000L
+//MM_CANE_UE_ERR_STATUS_LO
+#define MM_CANE_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define MM_CANE_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define MM_CANE_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define MM_CANE_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define MM_CANE_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define MM_CANE_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define MM_CANE_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define MM_CANE_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//MM_CANE_UE_ERR_STATUS_HI
+#define MM_CANE_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define MM_CANE_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define MM_CANE_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define MM_CANE_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define MM_CANE_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define MM_CANE_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define MM_CANE_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define MM_CANE_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define MM_CANE_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define MM_CANE_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define MM_CANE_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define MM_CANE_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+//MM_CANE_CE_ERR_STATUS_LO
+#define MM_CANE_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define MM_CANE_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define MM_CANE_CE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define MM_CANE_CE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define MM_CANE_CE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define MM_CANE_CE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define MM_CANE_CE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define MM_CANE_CE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//MM_CANE_CE_ERR_STATUS_HI
+#define MM_CANE_CE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define MM_CANE_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define MM_CANE_CE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define MM_CANE_CE_ERR_STATUS_HI__CE_CNT__SHIFT 0x17
+#define MM_CANE_CE_ERR_STATUS_HI__POISON__SHIFT 0x1a
+#define MM_CANE_CE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define MM_CANE_CE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define MM_CANE_CE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define MM_CANE_CE_ERR_STATUS_HI__CE_CNT_MASK 0x03800000L
+#define MM_CANE_CE_ERR_STATUS_HI__POISON_MASK 0x04000000L
#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_9_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_9_0_offset.h
index 033f2796c1e3..c8a15c8f4822 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_9_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_9_0_offset.h
@@ -6201,6 +6201,8 @@
#define regNBIF_SHUB_TODET_SYNCFLOOD_CTRL2_BASE_IDX 8
#define regBIFC_BME_ERR_LOG_HB 0xe8ab
#define regBIFC_BME_ERR_LOG_HB_BASE_IDX 8
+#define regBIFC_GFX_INT_MONITOR_MASK 0xe8ad
+#define regBIFC_GFX_INT_MONITOR_MASK_BASE_IDX 8
#define regBIFC_HRP_SDP_WRRSP_POOLCRED_ALLOC 0xe8c0
#define regBIFC_HRP_SDP_WRRSP_POOLCRED_ALLOC_BASE_IDX 8
#define regBIFC_HRP_SDP_RDRSP_POOLCRED_ALLOC 0xe8c1
diff --git a/drivers/gpu/drm/amd/include/asic_reg/sdma/sdma_4_4_2_offset.h b/drivers/gpu/drm/amd/include/asic_reg/sdma/sdma_4_4_2_offset.h
index 31bef0776ded..ead81aeffd67 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/sdma/sdma_4_4_2_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/sdma/sdma_4_4_2_offset.h
@@ -211,6 +211,10 @@
#define regSDMA_RAS_STATUS_BASE_IDX 0
#define regSDMA_CLK_STATUS 0x0068
#define regSDMA_CLK_STATUS_BASE_IDX 0
+#define regSDMA_UE_ERR_STATUS_LO 0x0069
+#define regSDMA_UE_ERR_STATUS_LO_BASE_IDX 0
+#define regSDMA_UE_ERR_STATUS_HI 0x006a
+#define regSDMA_UE_ERR_STATUS_HI_BASE_IDX 0
#define regSDMA_POWER_CNTL 0x006b
#define regSDMA_POWER_CNTL_BASE_IDX 0
#define regSDMA_CLK_CTRL 0x006c
diff --git a/drivers/gpu/drm/amd/include/asic_reg/sdma/sdma_4_4_2_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/sdma/sdma_4_4_2_sh_mask.h
index e46cb3339355..290953bdf1d6 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/sdma/sdma_4_4_2_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/sdma/sdma_4_4_2_sh_mask.h
@@ -1171,6 +1171,30 @@
#define SDMA_CLK_STATUS__F32_CLK_MASK 0x00000008L
#define SDMA_CLK_STATUS__CE_CLK_MASK 0x00000010L
#define SDMA_CLK_STATUS__PERF_CLK_MASK 0x00000020L
+//SDMA_UE_ERR_STATUS_LO
+#define SDMA_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG__SHIFT 0x0
+#define SDMA_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG__SHIFT 0x1
+#define SDMA_UE_ERR_STATUS_LO__ADDRESS__SHIFT 0x2
+#define SDMA_UE_ERR_STATUS_LO__MEMORY_ID__SHIFT 0x18
+#define SDMA_UE_ERR_STATUS_LO__ERR_STATUS_VALID_FLAG_MASK 0x00000001L
+#define SDMA_UE_ERR_STATUS_LO__ADDRESS_VALID_FLAG_MASK 0x00000002L
+#define SDMA_UE_ERR_STATUS_LO__ADDRESS_MASK 0x00FFFFFCL
+#define SDMA_UE_ERR_STATUS_LO__MEMORY_ID_MASK 0xFF000000L
+//SDMA_UE_ERR_STATUS_HI
+#define SDMA_UE_ERR_STATUS_HI__ECC__SHIFT 0x0
+#define SDMA_UE_ERR_STATUS_HI__PARITY__SHIFT 0x1
+#define SDMA_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG__SHIFT 0x2
+#define SDMA_UE_ERR_STATUS_HI__ERR_INFO__SHIFT 0x3
+#define SDMA_UE_ERR_STATUS_HI__UE_CNT__SHIFT 0x17
+#define SDMA_UE_ERR_STATUS_HI__FED_CNT__SHIFT 0x1a
+#define SDMA_UE_ERR_STATUS_HI__RESERVED__SHIFT 0x1d
+#define SDMA_UE_ERR_STATUS_HI__ECC_MASK 0x00000001L
+#define SDMA_UE_ERR_STATUS_HI__PARITY_MASK 0x00000002L
+#define SDMA_UE_ERR_STATUS_HI__ERR_INFO_VALID_FLAG_MASK 0x00000004L
+#define SDMA_UE_ERR_STATUS_HI__ERR_INFO_MASK 0x007FFFF8L
+#define SDMA_UE_ERR_STATUS_HI__UE_CNT_MASK 0x03800000L
+#define SDMA_UE_ERR_STATUS_HI__FED_CNT_MASK 0x1C000000L
+#define SDMA_UE_ERR_STATUS_HI__RESERVED_MASK 0xE0000000L
//SDMA_POWER_CNTL
#define SDMA_POWER_CNTL__PG_CNTL_ENABLE__SHIFT 0x0
#define SDMA_POWER_CNTL__EXT_PG_POWER_ON_REQ__SHIFT 0x1
diff --git a/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_13_0_3_offset.h b/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_13_0_3_offset.h
new file mode 100644
index 000000000000..b62b489402c5
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_13_0_3_offset.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef _smuio_13_0_3_OFFSET_HEADER
+#define _smuio_13_0_3_OFFSET_HEADER
+
+
+
+// addressBlock: aid_smuio_smuio_reset_SmuSmuioDec
+// base address: 0x5a300
+#define regSMUIO_MP_RESET_INTR 0x00c1
+#define regSMUIO_MP_RESET_INTR_BASE_IDX 1
+#define regSMUIO_SOC_HALT 0x00c2
+#define regSMUIO_SOC_HALT_BASE_IDX 1
+
+
+// addressBlock: aid_smuio_smuio_tsc_SmuSmuioDec
+// base address: 0x5a8a0
+#define regPWROK_REFCLK_GAP_CYCLES 0x0028
+#define regPWROK_REFCLK_GAP_CYCLES_BASE_IDX 2
+#define regGOLDEN_TSC_INCREMENT_UPPER 0x002b
+#define regGOLDEN_TSC_INCREMENT_UPPER_BASE_IDX 2
+#define regGOLDEN_TSC_INCREMENT_LOWER 0x002c
+#define regGOLDEN_TSC_INCREMENT_LOWER_BASE_IDX 2
+#define regGOLDEN_TSC_COUNT_UPPER 0x002d
+#define regGOLDEN_TSC_COUNT_UPPER_BASE_IDX 2
+#define regGOLDEN_TSC_COUNT_LOWER 0x002e
+#define regGOLDEN_TSC_COUNT_LOWER_BASE_IDX 2
+#define regSOC_GOLDEN_TSC_SHADOW_UPPER 0x002f
+#define regSOC_GOLDEN_TSC_SHADOW_UPPER_BASE_IDX 2
+#define regSOC_GOLDEN_TSC_SHADOW_LOWER 0x0030
+#define regSOC_GOLDEN_TSC_SHADOW_LOWER_BASE_IDX 2
+#define regSOC_GAP_PWROK 0x0031
+#define regSOC_GAP_PWROK_BASE_IDX 2
+
+
+// addressBlock: aid_smuio_smuio_swtimer_SmuSmuioDec
+// base address: 0x5ac70
+#define regPWR_VIRT_RESET_REQ 0x011c
+#define regPWR_VIRT_RESET_REQ_BASE_IDX 2
+#define regPWR_DISP_TIMER_CONTROL 0x011d
+#define regPWR_DISP_TIMER_CONTROL_BASE_IDX 2
+#define regPWR_DISP_TIMER_DEBUG 0x011e
+#define regPWR_DISP_TIMER_DEBUG_BASE_IDX 2
+#define regPWR_DISP_TIMER2_CONTROL 0x011f
+#define regPWR_DISP_TIMER2_CONTROL_BASE_IDX 2
+#define regPWR_DISP_TIMER2_DEBUG 0x0120
+#define regPWR_DISP_TIMER2_DEBUG_BASE_IDX 2
+#define regPWR_DISP_TIMER_GLOBAL_CONTROL 0x0121
+#define regPWR_DISP_TIMER_GLOBAL_CONTROL_BASE_IDX 2
+#define regPWR_IH_CONTROL 0x0122
+#define regPWR_IH_CONTROL_BASE_IDX 2
+
+
+// addressBlock: aid_smuio_smuio_misc_SmuSmuioDec
+// base address: 0x5a000
+#define regSMUIO_MCM_CONFIG 0x0023
+#define regSMUIO_MCM_CONFIG_BASE_IDX 1
+#define regIP_DISCOVERY_VERSION 0x0000
+#define regIP_DISCOVERY_VERSION_BASE_IDX 2
+#define regSCRATCH_REGISTER0 0x01bd
+#define regSCRATCH_REGISTER0_BASE_IDX 2
+#define regSCRATCH_REGISTER1 0x01be
+#define regSCRATCH_REGISTER1_BASE_IDX 2
+#define regSCRATCH_REGISTER2 0x01bf
+#define regSCRATCH_REGISTER2_BASE_IDX 2
+#define regSCRATCH_REGISTER3 0x01c0
+#define regSCRATCH_REGISTER3_BASE_IDX 2
+#define regSCRATCH_REGISTER4 0x01c1
+#define regSCRATCH_REGISTER4_BASE_IDX 2
+#define regSCRATCH_REGISTER5 0x01c2
+#define regSCRATCH_REGISTER5_BASE_IDX 2
+#define regSCRATCH_REGISTER6 0x01c3
+#define regSCRATCH_REGISTER6_BASE_IDX 2
+#define regSCRATCH_REGISTER7 0x01c4
+#define regSCRATCH_REGISTER7_BASE_IDX 2
+
+
+// addressBlock: aid_smuio_smuio_gpio_SmuSmuioDec
+// base address: 0x5a500
+#define regSMU_GPIOPAD_SW_INT_STAT 0x0140
+#define regSMU_GPIOPAD_SW_INT_STAT_BASE_IDX 1
+#define regSMU_GPIOPAD_MASK 0x0141
+#define regSMU_GPIOPAD_MASK_BASE_IDX 1
+#define regSMU_GPIOPAD_A 0x0142
+#define regSMU_GPIOPAD_A_BASE_IDX 1
+#define regSMU_GPIOPAD_TXIMPSEL 0x0143
+#define regSMU_GPIOPAD_TXIMPSEL_BASE_IDX 1
+#define regSMU_GPIOPAD_EN 0x0144
+#define regSMU_GPIOPAD_EN_BASE_IDX 1
+#define regSMU_GPIOPAD_Y 0x0145
+#define regSMU_GPIOPAD_Y_BASE_IDX 1
+#define regSMU_GPIOPAD_RXEN 0x0146
+#define regSMU_GPIOPAD_RXEN_BASE_IDX 1
+#define regSMU_GPIOPAD_RCVR_SEL0 0x0147
+#define regSMU_GPIOPAD_RCVR_SEL0_BASE_IDX 1
+#define regSMU_GPIOPAD_RCVR_SEL1 0x0148
+#define regSMU_GPIOPAD_RCVR_SEL1_BASE_IDX 1
+#define regSMU_GPIOPAD_PU_EN 0x0149
+#define regSMU_GPIOPAD_PU_EN_BASE_IDX 1
+#define regSMU_GPIOPAD_PD_EN 0x014a
+#define regSMU_GPIOPAD_PD_EN_BASE_IDX 1
+#define regSMU_GPIOPAD_PINSTRAPS 0x014b
+#define regSMU_GPIOPAD_PINSTRAPS_BASE_IDX 1
+#define regDFT_PINSTRAPS 0x014c
+#define regDFT_PINSTRAPS_BASE_IDX 1
+#define regSMU_GPIOPAD_INT_STAT_EN 0x014d
+#define regSMU_GPIOPAD_INT_STAT_EN_BASE_IDX 1
+#define regSMU_GPIOPAD_INT_STAT 0x014e
+#define regSMU_GPIOPAD_INT_STAT_BASE_IDX 1
+#define regSMU_GPIOPAD_INT_STAT_AK 0x014f
+#define regSMU_GPIOPAD_INT_STAT_AK_BASE_IDX 1
+#define regSMU_GPIOPAD_INT_EN 0x0150
+#define regSMU_GPIOPAD_INT_EN_BASE_IDX 1
+#define regSMU_GPIOPAD_INT_TYPE 0x0151
+#define regSMU_GPIOPAD_INT_TYPE_BASE_IDX 1
+#define regSMU_GPIOPAD_INT_POLARITY 0x0152
+#define regSMU_GPIOPAD_INT_POLARITY_BASE_IDX 1
+#define regSMUIO_PCC_GPIO_SELECT 0x0155
+#define regSMUIO_PCC_GPIO_SELECT_BASE_IDX 1
+#define regSMU_GPIOPAD_S0 0x0156
+#define regSMU_GPIOPAD_S0_BASE_IDX 1
+#define regSMU_GPIOPAD_S1 0x0157
+#define regSMU_GPIOPAD_S1_BASE_IDX 1
+#define regSMU_GPIOPAD_SCHMEN 0x0158
+#define regSMU_GPIOPAD_SCHMEN_BASE_IDX 1
+#define regSMU_GPIOPAD_SCL_EN 0x0159
+#define regSMU_GPIOPAD_SCL_EN_BASE_IDX 1
+#define regSMU_GPIOPAD_SDA_EN 0x015a
+#define regSMU_GPIOPAD_SDA_EN_BASE_IDX 1
+#define regSMUIO_GPIO_INT0_SELECT 0x015b
+#define regSMUIO_GPIO_INT0_SELECT_BASE_IDX 1
+#define regSMUIO_GPIO_INT1_SELECT 0x015c
+#define regSMUIO_GPIO_INT1_SELECT_BASE_IDX 1
+#define regSMUIO_GPIO_INT2_SELECT 0x015d
+#define regSMUIO_GPIO_INT2_SELECT_BASE_IDX 1
+#define regSMUIO_GPIO_INT3_SELECT 0x015e
+#define regSMUIO_GPIO_INT3_SELECT_BASE_IDX 1
+#define regSMU_GPIOPAD_MP_INT0_STAT 0x015f
+#define regSMU_GPIOPAD_MP_INT0_STAT_BASE_IDX 1
+#define regSMU_GPIOPAD_MP_INT1_STAT 0x0160
+#define regSMU_GPIOPAD_MP_INT1_STAT_BASE_IDX 1
+#define regSMU_GPIOPAD_MP_INT2_STAT 0x0161
+#define regSMU_GPIOPAD_MP_INT2_STAT_BASE_IDX 1
+#define regSMU_GPIOPAD_MP_INT3_STAT 0x0162
+#define regSMU_GPIOPAD_MP_INT3_STAT_BASE_IDX 1
+#define regSMIO_INDEX 0x0163
+#define regSMIO_INDEX_BASE_IDX 1
+#define regS0_VID_SMIO_CNTL 0x0164
+#define regS0_VID_SMIO_CNTL_BASE_IDX 1
+#define regS1_VID_SMIO_CNTL 0x0165
+#define regS1_VID_SMIO_CNTL_BASE_IDX 1
+#define regOPEN_DRAIN_SELECT 0x0166
+#define regOPEN_DRAIN_SELECT_BASE_IDX 1
+#define regSMIO_ENABLE 0x0167
+#define regSMIO_ENABLE_BASE_IDX 1
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_13_0_3_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_13_0_3_sh_mask.h
new file mode 100644
index 000000000000..be896f3089fe
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_13_0_3_sh_mask.h
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef _smuio_13_0_3_SH_MASK_HEADER
+#define _smuio_13_0_3_SH_MASK_HEADER
+
+
+// addressBlock: aid_smuio_smuio_reset_SmuSmuioDec
+//SMUIO_MP_RESET_INTR
+#define SMUIO_MP_RESET_INTR__SMUIO_MP_RESET_INTR__SHIFT 0x0
+#define SMUIO_MP_RESET_INTR__SMUIO_MP_RESET_INTR_MASK 0x00000001L
+//SMUIO_SOC_HALT
+#define SMUIO_SOC_HALT__WDT_FORCE_PWROK_EN__SHIFT 0x2
+#define SMUIO_SOC_HALT__WDT_FORCE_RESETn_EN__SHIFT 0x3
+#define SMUIO_SOC_HALT__WDT_FORCE_PWROK_EN_MASK 0x00000004L
+#define SMUIO_SOC_HALT__WDT_FORCE_RESETn_EN_MASK 0x00000008L
+
+
+// addressBlock: aid_smuio_smuio_tsc_SmuSmuioDec
+//PWROK_REFCLK_GAP_CYCLES
+#define PWROK_REFCLK_GAP_CYCLES__Pwrok_PreAssertion_clkgap_cycles__SHIFT 0x0
+#define PWROK_REFCLK_GAP_CYCLES__Pwrok_PostAssertion_clkgap_cycles__SHIFT 0x8
+#define PWROK_REFCLK_GAP_CYCLES__Pwrok_PreAssertion_clkgap_cycles_MASK 0x000000FFL
+#define PWROK_REFCLK_GAP_CYCLES__Pwrok_PostAssertion_clkgap_cycles_MASK 0x0000FF00L
+//GOLDEN_TSC_INCREMENT_UPPER
+#define GOLDEN_TSC_INCREMENT_UPPER__GoldenTscIncrementUpper__SHIFT 0x0
+#define GOLDEN_TSC_INCREMENT_UPPER__GoldenTscIncrementUpper_MASK 0x00FFFFFFL
+//GOLDEN_TSC_INCREMENT_LOWER
+#define GOLDEN_TSC_INCREMENT_LOWER__GoldenTscIncrementLower__SHIFT 0x0
+#define GOLDEN_TSC_INCREMENT_LOWER__GoldenTscIncrementLower_MASK 0xFFFFFFFFL
+//GOLDEN_TSC_COUNT_UPPER
+#define GOLDEN_TSC_COUNT_UPPER__GoldenTscCountUpper__SHIFT 0x0
+#define GOLDEN_TSC_COUNT_UPPER__GoldenTscCountUpper_MASK 0x00FFFFFFL
+//GOLDEN_TSC_COUNT_LOWER
+#define GOLDEN_TSC_COUNT_LOWER__GoldenTscCountLower__SHIFT 0x0
+#define GOLDEN_TSC_COUNT_LOWER__GoldenTscCountLower_MASK 0xFFFFFFFFL
+//SOC_GOLDEN_TSC_SHADOW_UPPER
+#define SOC_GOLDEN_TSC_SHADOW_UPPER__SocGoldenTscShadowUpper__SHIFT 0x0
+#define SOC_GOLDEN_TSC_SHADOW_UPPER__SocGoldenTscShadowUpper_MASK 0x00FFFFFFL
+//SOC_GOLDEN_TSC_SHADOW_LOWER
+#define SOC_GOLDEN_TSC_SHADOW_LOWER__SocGoldenTscShadowLower__SHIFT 0x0
+#define SOC_GOLDEN_TSC_SHADOW_LOWER__SocGoldenTscShadowLower_MASK 0xFFFFFFFFL
+//SOC_GAP_PWROK
+#define SOC_GAP_PWROK__soc_gap_pwrok__SHIFT 0x0
+#define SOC_GAP_PWROK__soc_gap_pwrok_MASK 0x00000001L
+
+
+// addressBlock: aid_smuio_smuio_swtimer_SmuSmuioDec
+//PWR_VIRT_RESET_REQ
+#define PWR_VIRT_RESET_REQ__VF_FLR__SHIFT 0x0
+#define PWR_VIRT_RESET_REQ__PF_FLR__SHIFT 0x1f
+#define PWR_VIRT_RESET_REQ__VF_FLR_MASK 0x7FFFFFFFL
+#define PWR_VIRT_RESET_REQ__PF_FLR_MASK 0x80000000L
+//PWR_DISP_TIMER_CONTROL
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_COUNT__SHIFT 0x0
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_ENABLE__SHIFT 0x19
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_DISABLE__SHIFT 0x1a
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_MASK__SHIFT 0x1b
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_STAT_AK__SHIFT 0x1c
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_TYPE__SHIFT 0x1d
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_MODE__SHIFT 0x1e
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_COUNT_MASK 0x01FFFFFFL
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_ENABLE_MASK 0x02000000L
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_DISABLE_MASK 0x04000000L
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_MASK_MASK 0x08000000L
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_STAT_AK_MASK 0x10000000L
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_TYPE_MASK 0x20000000L
+#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_MODE_MASK 0x40000000L
+//PWR_DISP_TIMER_DEBUG
+#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_INT_RUNNING__SHIFT 0x0
+#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_INT_STAT__SHIFT 0x1
+#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_INT__SHIFT 0x2
+#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_RUN_VAL__SHIFT 0x7
+#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_INT_RUNNING_MASK 0x00000001L
+#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_INT_STAT_MASK 0x00000002L
+#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_INT_MASK 0x00000004L
+#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_RUN_VAL_MASK 0xFFFFFF80L
+//PWR_DISP_TIMER2_CONTROL
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_COUNT__SHIFT 0x0
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_ENABLE__SHIFT 0x19
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_DISABLE__SHIFT 0x1a
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_MASK__SHIFT 0x1b
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_STAT_AK__SHIFT 0x1c
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_TYPE__SHIFT 0x1d
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_MODE__SHIFT 0x1e
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_COUNT_MASK 0x01FFFFFFL
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_ENABLE_MASK 0x02000000L
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_DISABLE_MASK 0x04000000L
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_MASK_MASK 0x08000000L
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_STAT_AK_MASK 0x10000000L
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_TYPE_MASK 0x20000000L
+#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_MODE_MASK 0x40000000L
+//PWR_DISP_TIMER2_DEBUG
+#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_INT_RUNNING__SHIFT 0x0
+#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_INT_STAT__SHIFT 0x1
+#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_INT__SHIFT 0x2
+#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_RUN_VAL__SHIFT 0x7
+#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_INT_RUNNING_MASK 0x00000001L
+#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_INT_STAT_MASK 0x00000002L
+#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_INT_MASK 0x00000004L
+#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_RUN_VAL_MASK 0xFFFFFF80L
+//PWR_DISP_TIMER_GLOBAL_CONTROL
+#define PWR_DISP_TIMER_GLOBAL_CONTROL__DISP_TIMER_PULSE_WIDTH__SHIFT 0x0
+#define PWR_DISP_TIMER_GLOBAL_CONTROL__DISP_TIMER_PULSE_EN__SHIFT 0xa
+#define PWR_DISP_TIMER_GLOBAL_CONTROL__DISP_TIMER_PULSE_WIDTH_MASK 0x000003FFL
+#define PWR_DISP_TIMER_GLOBAL_CONTROL__DISP_TIMER_PULSE_EN_MASK 0x00000400L
+//PWR_IH_CONTROL
+#define PWR_IH_CONTROL__MAX_CREDIT__SHIFT 0x0
+#define PWR_IH_CONTROL__DISP_TIMER_TRIGGER_MASK__SHIFT 0x5
+#define PWR_IH_CONTROL__DISP_TIMER2_TRIGGER_MASK__SHIFT 0x6
+#define PWR_IH_CONTROL__PWR_IH_CLK_GATE_EN__SHIFT 0x1f
+#define PWR_IH_CONTROL__MAX_CREDIT_MASK 0x0000001FL
+#define PWR_IH_CONTROL__DISP_TIMER_TRIGGER_MASK_MASK 0x00000020L
+#define PWR_IH_CONTROL__DISP_TIMER2_TRIGGER_MASK_MASK 0x00000040L
+#define PWR_IH_CONTROL__PWR_IH_CLK_GATE_EN_MASK 0x80000000L
+
+
+// addressBlock: aid_smuio_smuio_misc_SmuSmuioDec
+//SMUIO_MCM_CONFIG
+#define SMUIO_MCM_CONFIG__DIE_ID__SHIFT 0x0
+#define SMUIO_MCM_CONFIG__PKG_TYPE__SHIFT 0x2
+#define SMUIO_MCM_CONFIG__SOCKET_ID__SHIFT 0x8
+#define SMUIO_MCM_CONFIG__PKG_SUBTYPE__SHIFT 0xc
+#define SMUIO_MCM_CONFIG__CONSOLE_K__SHIFT 0x10
+#define SMUIO_MCM_CONFIG__CONSOLE_A__SHIFT 0x11
+#define SMUIO_MCM_CONFIG__TOPOLOGY_ID__SHIFT 0x12
+#define SMUIO_MCM_CONFIG__DIE_ID_MASK 0x00000003L
+#define SMUIO_MCM_CONFIG__PKG_TYPE_MASK 0x0000003CL
+#define SMUIO_MCM_CONFIG__SOCKET_ID_MASK 0x00000F00L
+#define SMUIO_MCM_CONFIG__PKG_SUBTYPE_MASK 0x00001000L
+#define SMUIO_MCM_CONFIG__CONSOLE_K_MASK 0x00010000L
+#define SMUIO_MCM_CONFIG__CONSOLE_A_MASK 0x00020000L
+#define SMUIO_MCM_CONFIG__TOPOLOGY_ID_MASK 0x007C0000L
+//IP_DISCOVERY_VERSION
+#define IP_DISCOVERY_VERSION__IP_DISCOVERY_VERSION__SHIFT 0x0
+#define IP_DISCOVERY_VERSION__IP_DISCOVERY_VERSION_MASK 0xFFFFFFFFL
+//SCRATCH_REGISTER0
+#define SCRATCH_REGISTER0__ScratchPad0__SHIFT 0x0
+#define SCRATCH_REGISTER0__ScratchPad0_MASK 0xFFFFFFFFL
+//SCRATCH_REGISTER1
+#define SCRATCH_REGISTER1__ScratchPad1__SHIFT 0x0
+#define SCRATCH_REGISTER1__ScratchPad1_MASK 0xFFFFFFFFL
+//SCRATCH_REGISTER2
+#define SCRATCH_REGISTER2__ScratchPad2__SHIFT 0x0
+#define SCRATCH_REGISTER2__ScratchPad2_MASK 0xFFFFFFFFL
+//SCRATCH_REGISTER3
+#define SCRATCH_REGISTER3__ScratchPad3__SHIFT 0x0
+#define SCRATCH_REGISTER3__ScratchPad3_MASK 0xFFFFFFFFL
+//SCRATCH_REGISTER4
+#define SCRATCH_REGISTER4__ScratchPad4__SHIFT 0x0
+#define SCRATCH_REGISTER4__ScratchPad4_MASK 0xFFFFFFFFL
+//SCRATCH_REGISTER5
+#define SCRATCH_REGISTER5__ScratchPad5__SHIFT 0x0
+#define SCRATCH_REGISTER5__ScratchPad5_MASK 0xFFFFFFFFL
+//SCRATCH_REGISTER6
+#define SCRATCH_REGISTER6__ScratchPad6__SHIFT 0x0
+#define SCRATCH_REGISTER6__ScratchPad6_MASK 0xFFFFFFFFL
+//SCRATCH_REGISTER7
+#define SCRATCH_REGISTER7__ScratchPad7__SHIFT 0x0
+#define SCRATCH_REGISTER7__ScratchPad7_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_smuio_smuio_gpio_SmuSmuioDec
+//SMU_GPIOPAD_SW_INT_STAT
+#define SMU_GPIOPAD_SW_INT_STAT__SW_INT_STAT__SHIFT 0x0
+#define SMU_GPIOPAD_SW_INT_STAT__SW_INT_STAT_MASK 0x00000001L
+//SMU_GPIOPAD_MASK
+#define SMU_GPIOPAD_MASK__GPIO_MASK__SHIFT 0x0
+#define SMU_GPIOPAD_MASK__GPIO_MASK_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_A
+#define SMU_GPIOPAD_A__GPIO_A__SHIFT 0x0
+#define SMU_GPIOPAD_A__GPIO_A_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_TXIMPSEL
+#define SMU_GPIOPAD_TXIMPSEL__GPIO_TXIMPSEL__SHIFT 0x0
+#define SMU_GPIOPAD_TXIMPSEL__GPIO_TXIMPSEL_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_EN
+#define SMU_GPIOPAD_EN__GPIO_EN__SHIFT 0x0
+#define SMU_GPIOPAD_EN__GPIO_EN_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_Y
+#define SMU_GPIOPAD_Y__GPIO_Y__SHIFT 0x0
+#define SMU_GPIOPAD_Y__GPIO_Y_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_RXEN
+#define SMU_GPIOPAD_RXEN__GPIO_RXEN__SHIFT 0x0
+#define SMU_GPIOPAD_RXEN__GPIO_RXEN_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_RCVR_SEL0
+#define SMU_GPIOPAD_RCVR_SEL0__GPIO_RCVR_SEL0__SHIFT 0x0
+#define SMU_GPIOPAD_RCVR_SEL0__GPIO_RCVR_SEL0_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_RCVR_SEL1
+#define SMU_GPIOPAD_RCVR_SEL1__GPIO_RCVR_SEL1__SHIFT 0x0
+#define SMU_GPIOPAD_RCVR_SEL1__GPIO_RCVR_SEL1_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_PU_EN
+#define SMU_GPIOPAD_PU_EN__GPIO_PU_EN__SHIFT 0x0
+#define SMU_GPIOPAD_PU_EN__GPIO_PU_EN_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_PD_EN
+#define SMU_GPIOPAD_PD_EN__GPIO_PD_EN__SHIFT 0x0
+#define SMU_GPIOPAD_PD_EN__GPIO_PD_EN_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_PINSTRAPS
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_0__SHIFT 0x0
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_1__SHIFT 0x1
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_2__SHIFT 0x2
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_3__SHIFT 0x3
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_4__SHIFT 0x4
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_5__SHIFT 0x5
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_6__SHIFT 0x6
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_7__SHIFT 0x7
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_8__SHIFT 0x8
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_9__SHIFT 0x9
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_10__SHIFT 0xa
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_11__SHIFT 0xb
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_12__SHIFT 0xc
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_13__SHIFT 0xd
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_14__SHIFT 0xe
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_15__SHIFT 0xf
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_16__SHIFT 0x10
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_17__SHIFT 0x11
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_18__SHIFT 0x12
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_19__SHIFT 0x13
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_20__SHIFT 0x14
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_21__SHIFT 0x15
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_22__SHIFT 0x16
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_23__SHIFT 0x17
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_24__SHIFT 0x18
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_25__SHIFT 0x19
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_26__SHIFT 0x1a
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_27__SHIFT 0x1b
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_28__SHIFT 0x1c
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_29__SHIFT 0x1d
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_30__SHIFT 0x1e
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_0_MASK 0x00000001L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_1_MASK 0x00000002L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_2_MASK 0x00000004L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_3_MASK 0x00000008L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_4_MASK 0x00000010L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_5_MASK 0x00000020L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_6_MASK 0x00000040L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_7_MASK 0x00000080L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_8_MASK 0x00000100L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_9_MASK 0x00000200L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_10_MASK 0x00000400L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_11_MASK 0x00000800L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_12_MASK 0x00001000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_13_MASK 0x00002000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_14_MASK 0x00004000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_15_MASK 0x00008000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_16_MASK 0x00010000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_17_MASK 0x00020000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_18_MASK 0x00040000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_19_MASK 0x00080000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_20_MASK 0x00100000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_21_MASK 0x00200000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_22_MASK 0x00400000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_23_MASK 0x00800000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_24_MASK 0x01000000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_25_MASK 0x02000000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_26_MASK 0x04000000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_27_MASK 0x08000000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_28_MASK 0x10000000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_29_MASK 0x20000000L
+#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_30_MASK 0x40000000L
+//DFT_PINSTRAPS
+#define DFT_PINSTRAPS__DFT_PINSTRAPS__SHIFT 0x0
+#define DFT_PINSTRAPS__DFT_PINSTRAPS_MASK 0x000003FFL
+//SMU_GPIOPAD_INT_STAT_EN
+#define SMU_GPIOPAD_INT_STAT_EN__GPIO_INT_STAT_EN__SHIFT 0x0
+#define SMU_GPIOPAD_INT_STAT_EN__SW_INITIATED_INT_STAT_EN__SHIFT 0x1f
+#define SMU_GPIOPAD_INT_STAT_EN__GPIO_INT_STAT_EN_MASK 0x1FFFFFFFL
+#define SMU_GPIOPAD_INT_STAT_EN__SW_INITIATED_INT_STAT_EN_MASK 0x80000000L
+//SMU_GPIOPAD_INT_STAT
+#define SMU_GPIOPAD_INT_STAT__GPIO_INT_STAT__SHIFT 0x0
+#define SMU_GPIOPAD_INT_STAT__SW_INITIATED_INT_STAT__SHIFT 0x1f
+#define SMU_GPIOPAD_INT_STAT__GPIO_INT_STAT_MASK 0x1FFFFFFFL
+#define SMU_GPIOPAD_INT_STAT__SW_INITIATED_INT_STAT_MASK 0x80000000L
+//SMU_GPIOPAD_INT_STAT_AK
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_0__SHIFT 0x0
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_1__SHIFT 0x1
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_2__SHIFT 0x2
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_3__SHIFT 0x3
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_4__SHIFT 0x4
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_5__SHIFT 0x5
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_6__SHIFT 0x6
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_7__SHIFT 0x7
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_8__SHIFT 0x8
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_9__SHIFT 0x9
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_10__SHIFT 0xa
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_11__SHIFT 0xb
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_12__SHIFT 0xc
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_13__SHIFT 0xd
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_14__SHIFT 0xe
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_15__SHIFT 0xf
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_16__SHIFT 0x10
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_17__SHIFT 0x11
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_18__SHIFT 0x12
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_19__SHIFT 0x13
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_20__SHIFT 0x14
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_21__SHIFT 0x15
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_22__SHIFT 0x16
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_23__SHIFT 0x17
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_24__SHIFT 0x18
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_25__SHIFT 0x19
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_26__SHIFT 0x1a
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_27__SHIFT 0x1b
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_28__SHIFT 0x1c
+#define SMU_GPIOPAD_INT_STAT_AK__SW_INITIATED_INT_STAT_AK__SHIFT 0x1f
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_0_MASK 0x00000001L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_1_MASK 0x00000002L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_2_MASK 0x00000004L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_3_MASK 0x00000008L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_4_MASK 0x00000010L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_5_MASK 0x00000020L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_6_MASK 0x00000040L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_7_MASK 0x00000080L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_8_MASK 0x00000100L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_9_MASK 0x00000200L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_10_MASK 0x00000400L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_11_MASK 0x00000800L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_12_MASK 0x00001000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_13_MASK 0x00002000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_14_MASK 0x00004000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_15_MASK 0x00008000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_16_MASK 0x00010000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_17_MASK 0x00020000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_18_MASK 0x00040000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_19_MASK 0x00080000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_20_MASK 0x00100000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_21_MASK 0x00200000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_22_MASK 0x00400000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_23_MASK 0x00800000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_24_MASK 0x01000000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_25_MASK 0x02000000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_26_MASK 0x04000000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_27_MASK 0x08000000L
+#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_28_MASK 0x10000000L
+#define SMU_GPIOPAD_INT_STAT_AK__SW_INITIATED_INT_STAT_AK_MASK 0x80000000L
+//SMU_GPIOPAD_INT_EN
+#define SMU_GPIOPAD_INT_EN__GPIO_INT_EN__SHIFT 0x0
+#define SMU_GPIOPAD_INT_EN__SW_INITIATED_INT_EN__SHIFT 0x1f
+#define SMU_GPIOPAD_INT_EN__GPIO_INT_EN_MASK 0x1FFFFFFFL
+#define SMU_GPIOPAD_INT_EN__SW_INITIATED_INT_EN_MASK 0x80000000L
+//SMU_GPIOPAD_INT_TYPE
+#define SMU_GPIOPAD_INT_TYPE__GPIO_INT_TYPE__SHIFT 0x0
+#define SMU_GPIOPAD_INT_TYPE__SW_INITIATED_INT_TYPE__SHIFT 0x1f
+#define SMU_GPIOPAD_INT_TYPE__GPIO_INT_TYPE_MASK 0x1FFFFFFFL
+#define SMU_GPIOPAD_INT_TYPE__SW_INITIATED_INT_TYPE_MASK 0x80000000L
+//SMU_GPIOPAD_INT_POLARITY
+#define SMU_GPIOPAD_INT_POLARITY__GPIO_INT_POLARITY__SHIFT 0x0
+#define SMU_GPIOPAD_INT_POLARITY__SW_INITIATED_INT_POLARITY__SHIFT 0x1f
+#define SMU_GPIOPAD_INT_POLARITY__GPIO_INT_POLARITY_MASK 0x1FFFFFFFL
+#define SMU_GPIOPAD_INT_POLARITY__SW_INITIATED_INT_POLARITY_MASK 0x80000000L
+//SMUIO_PCC_GPIO_SELECT
+#define SMUIO_PCC_GPIO_SELECT__GPIO__SHIFT 0x0
+#define SMUIO_PCC_GPIO_SELECT__GPIO_MASK 0xFFFFFFFFL
+//SMU_GPIOPAD_S0
+#define SMU_GPIOPAD_S0__GPIO_S0__SHIFT 0x0
+#define SMU_GPIOPAD_S0__GPIO_S0_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_S1
+#define SMU_GPIOPAD_S1__GPIO_S1__SHIFT 0x0
+#define SMU_GPIOPAD_S1__GPIO_S1_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_SCHMEN
+#define SMU_GPIOPAD_SCHMEN__GPIO_SCHMEN__SHIFT 0x0
+#define SMU_GPIOPAD_SCHMEN__GPIO_SCHMEN_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_SCL_EN
+#define SMU_GPIOPAD_SCL_EN__GPIO_SCL_EN__SHIFT 0x0
+#define SMU_GPIOPAD_SCL_EN__GPIO_SCL_EN_MASK 0x7FFFFFFFL
+//SMU_GPIOPAD_SDA_EN
+#define SMU_GPIOPAD_SDA_EN__GPIO_SDA_EN__SHIFT 0x0
+#define SMU_GPIOPAD_SDA_EN__GPIO_SDA_EN_MASK 0x7FFFFFFFL
+//SMUIO_GPIO_INT0_SELECT
+#define SMUIO_GPIO_INT0_SELECT__GPIO_INT0_SELECT__SHIFT 0x0
+#define SMUIO_GPIO_INT0_SELECT__GPIO_INT0_SELECT_MASK 0xFFFFFFFFL
+//SMUIO_GPIO_INT1_SELECT
+#define SMUIO_GPIO_INT1_SELECT__GPIO_INT1_SELECT__SHIFT 0x0
+#define SMUIO_GPIO_INT1_SELECT__GPIO_INT1_SELECT_MASK 0xFFFFFFFFL
+//SMUIO_GPIO_INT2_SELECT
+#define SMUIO_GPIO_INT2_SELECT__GPIO_INT2_SELECT__SHIFT 0x0
+#define SMUIO_GPIO_INT2_SELECT__GPIO_INT2_SELECT_MASK 0xFFFFFFFFL
+//SMUIO_GPIO_INT3_SELECT
+#define SMUIO_GPIO_INT3_SELECT__GPIO_INT3_SELECT__SHIFT 0x0
+#define SMUIO_GPIO_INT3_SELECT__GPIO_INT3_SELECT_MASK 0xFFFFFFFFL
+//SMU_GPIOPAD_MP_INT0_STAT
+#define SMU_GPIOPAD_MP_INT0_STAT__GPIO_MP_INT0_STAT__SHIFT 0x0
+#define SMU_GPIOPAD_MP_INT0_STAT__GPIO_MP_INT0_STAT_MASK 0x1FFFFFFFL
+//SMU_GPIOPAD_MP_INT1_STAT
+#define SMU_GPIOPAD_MP_INT1_STAT__GPIO_MP_INT1_STAT__SHIFT 0x0
+#define SMU_GPIOPAD_MP_INT1_STAT__GPIO_MP_INT1_STAT_MASK 0x1FFFFFFFL
+//SMU_GPIOPAD_MP_INT2_STAT
+#define SMU_GPIOPAD_MP_INT2_STAT__GPIO_MP_INT2_STAT__SHIFT 0x0
+#define SMU_GPIOPAD_MP_INT2_STAT__GPIO_MP_INT2_STAT_MASK 0x1FFFFFFFL
+//SMU_GPIOPAD_MP_INT3_STAT
+#define SMU_GPIOPAD_MP_INT3_STAT__GPIO_MP_INT3_STAT__SHIFT 0x0
+#define SMU_GPIOPAD_MP_INT3_STAT__GPIO_MP_INT3_STAT_MASK 0x1FFFFFFFL
+//SMIO_INDEX
+#define SMIO_INDEX__SW_SMIO_INDEX__SHIFT 0x0
+#define SMIO_INDEX__SW_SMIO_INDEX_MASK 0x00000001L
+//S0_VID_SMIO_CNTL
+#define S0_VID_SMIO_CNTL__S0_SMIO_VALUES__SHIFT 0x0
+#define S0_VID_SMIO_CNTL__S0_SMIO_VALUES_MASK 0xFFFFFFFFL
+//S1_VID_SMIO_CNTL
+#define S1_VID_SMIO_CNTL__S1_SMIO_VALUES__SHIFT 0x0
+#define S1_VID_SMIO_CNTL__S1_SMIO_VALUES_MASK 0xFFFFFFFFL
+//OPEN_DRAIN_SELECT
+#define OPEN_DRAIN_SELECT__OPEN_DRAIN_SELECT__SHIFT 0x0
+#define OPEN_DRAIN_SELECT__RESERVED__SHIFT 0x1f
+#define OPEN_DRAIN_SELECT__OPEN_DRAIN_SELECT_MASK 0x7FFFFFFFL
+#define OPEN_DRAIN_SELECT__RESERVED_MASK 0x80000000L
+//SMIO_ENABLE
+#define SMIO_ENABLE__SMIO_ENABLE__SHIFT 0x0
+#define SMIO_ENABLE__SMIO_ENABLE_MASK 0xFFFFFFFFL
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_4_0_3_offset.h b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_4_0_3_offset.h
new file mode 100644
index 000000000000..e9742d10de1c
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_4_0_3_offset.h
@@ -0,0 +1,2332 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef _vcn_4_0_3_OFFSET_HEADER
+#define _vcn_4_0_3_OFFSET_HEADER
+
+
+
+// addressBlock: aid_uvd0_uvddec
+// base address: 0x1fb00
+#define regUVD_TOP_CTRL 0x00c0
+#define regUVD_TOP_CTRL_BASE_IDX 1
+#define regUVD_CGC_GATE 0x00c1
+#define regUVD_CGC_GATE_BASE_IDX 1
+#define regUVD_CGC_CTRL 0x00c2
+#define regUVD_CGC_CTRL_BASE_IDX 1
+#define regAVM_SUVD_CGC_GATE 0x00c4
+#define regAVM_SUVD_CGC_GATE_BASE_IDX 1
+#define regCDEFE_SUVD_CGC_GATE 0x00c4
+#define regCDEFE_SUVD_CGC_GATE_BASE_IDX 1
+#define regEFC_SUVD_CGC_GATE 0x00c4
+#define regEFC_SUVD_CGC_GATE_BASE_IDX 1
+#define regENT_SUVD_CGC_GATE 0x00c4
+#define regENT_SUVD_CGC_GATE_BASE_IDX 1
+#define regIME_SUVD_CGC_GATE 0x00c4
+#define regIME_SUVD_CGC_GATE_BASE_IDX 1
+#define regPPU_SUVD_CGC_GATE 0x00c4
+#define regPPU_SUVD_CGC_GATE_BASE_IDX 1
+#define regSAOE_SUVD_CGC_GATE 0x00c4
+#define regSAOE_SUVD_CGC_GATE_BASE_IDX 1
+#define regSCM_SUVD_CGC_GATE 0x00c4
+#define regSCM_SUVD_CGC_GATE_BASE_IDX 1
+#define regSDB_SUVD_CGC_GATE 0x00c4
+#define regSDB_SUVD_CGC_GATE_BASE_IDX 1
+#define regSIT0_NXT_SUVD_CGC_GATE 0x00c4
+#define regSIT0_NXT_SUVD_CGC_GATE_BASE_IDX 1
+#define regSIT1_NXT_SUVD_CGC_GATE 0x00c4
+#define regSIT1_NXT_SUVD_CGC_GATE_BASE_IDX 1
+#define regSIT2_NXT_SUVD_CGC_GATE 0x00c4
+#define regSIT2_NXT_SUVD_CGC_GATE_BASE_IDX 1
+#define regSIT_SUVD_CGC_GATE 0x00c4
+#define regSIT_SUVD_CGC_GATE_BASE_IDX 1
+#define regSMPA_SUVD_CGC_GATE 0x00c4
+#define regSMPA_SUVD_CGC_GATE_BASE_IDX 1
+#define regSMP_SUVD_CGC_GATE 0x00c4
+#define regSMP_SUVD_CGC_GATE_BASE_IDX 1
+#define regSRE_SUVD_CGC_GATE 0x00c4
+#define regSRE_SUVD_CGC_GATE_BASE_IDX 1
+#define regUVD_MPBE0_SUVD_CGC_GATE 0x00c4
+#define regUVD_MPBE0_SUVD_CGC_GATE_BASE_IDX 1
+#define regUVD_MPBE1_SUVD_CGC_GATE 0x00c4
+#define regUVD_MPBE1_SUVD_CGC_GATE_BASE_IDX 1
+#define regUVD_SUVD_CGC_GATE 0x00c4
+#define regUVD_SUVD_CGC_GATE_BASE_IDX 1
+#define regAVM_SUVD_CGC_GATE2 0x00c5
+#define regAVM_SUVD_CGC_GATE2_BASE_IDX 1
+#define regCDEFE_SUVD_CGC_GATE2 0x00c5
+#define regCDEFE_SUVD_CGC_GATE2_BASE_IDX 1
+#define regDBR_SUVD_CGC_GATE2 0x00c5
+#define regDBR_SUVD_CGC_GATE2_BASE_IDX 1
+#define regENT_SUVD_CGC_GATE2 0x00c5
+#define regENT_SUVD_CGC_GATE2_BASE_IDX 1
+#define regIME_SUVD_CGC_GATE2 0x00c5
+#define regIME_SUVD_CGC_GATE2_BASE_IDX 1
+#define regMPC1_SUVD_CGC_GATE2 0x00c5
+#define regMPC1_SUVD_CGC_GATE2_BASE_IDX 1
+#define regSAOE_SUVD_CGC_GATE2 0x00c5
+#define regSAOE_SUVD_CGC_GATE2_BASE_IDX 1
+#define regSDB_SUVD_CGC_GATE2 0x00c5
+#define regSDB_SUVD_CGC_GATE2_BASE_IDX 1
+#define regSIT0_NXT_SUVD_CGC_GATE2 0x00c5
+#define regSIT0_NXT_SUVD_CGC_GATE2_BASE_IDX 1
+#define regSIT1_NXT_SUVD_CGC_GATE2 0x00c5
+#define regSIT1_NXT_SUVD_CGC_GATE2_BASE_IDX 1
+#define regSIT2_NXT_SUVD_CGC_GATE2 0x00c5
+#define regSIT2_NXT_SUVD_CGC_GATE2_BASE_IDX 1
+#define regSIT_SUVD_CGC_GATE2 0x00c5
+#define regSIT_SUVD_CGC_GATE2_BASE_IDX 1
+#define regSMPA_SUVD_CGC_GATE2 0x00c5
+#define regSMPA_SUVD_CGC_GATE2_BASE_IDX 1
+#define regSMP_SUVD_CGC_GATE2 0x00c5
+#define regSMP_SUVD_CGC_GATE2_BASE_IDX 1
+#define regSRE_SUVD_CGC_GATE2 0x00c5
+#define regSRE_SUVD_CGC_GATE2_BASE_IDX 1
+#define regUVD_MPBE0_SUVD_CGC_GATE2 0x00c5
+#define regUVD_MPBE0_SUVD_CGC_GATE2_BASE_IDX 1
+#define regUVD_MPBE1_SUVD_CGC_GATE2 0x00c5
+#define regUVD_MPBE1_SUVD_CGC_GATE2_BASE_IDX 1
+#define regUVD_SUVD_CGC_GATE2 0x00c5
+#define regUVD_SUVD_CGC_GATE2_BASE_IDX 1
+#define regAVM_SUVD_CGC_CTRL 0x00c6
+#define regAVM_SUVD_CGC_CTRL_BASE_IDX 1
+#define regCDEFE_SUVD_CGC_CTRL 0x00c6
+#define regCDEFE_SUVD_CGC_CTRL_BASE_IDX 1
+#define regDBR_SUVD_CGC_CTRL 0x00c6
+#define regDBR_SUVD_CGC_CTRL_BASE_IDX 1
+#define regEFC_SUVD_CGC_CTRL 0x00c6
+#define regEFC_SUVD_CGC_CTRL_BASE_IDX 1
+#define regENT_SUVD_CGC_CTRL 0x00c6
+#define regENT_SUVD_CGC_CTRL_BASE_IDX 1
+#define regIME_SUVD_CGC_CTRL 0x00c6
+#define regIME_SUVD_CGC_CTRL_BASE_IDX 1
+#define regMPC1_SUVD_CGC_CTRL 0x00c6
+#define regMPC1_SUVD_CGC_CTRL_BASE_IDX 1
+#define regPPU_SUVD_CGC_CTRL 0x00c6
+#define regPPU_SUVD_CGC_CTRL_BASE_IDX 1
+#define regSAOE_SUVD_CGC_CTRL 0x00c6
+#define regSAOE_SUVD_CGC_CTRL_BASE_IDX 1
+#define regSCM_SUVD_CGC_CTRL 0x00c6
+#define regSCM_SUVD_CGC_CTRL_BASE_IDX 1
+#define regSDB_SUVD_CGC_CTRL 0x00c6
+#define regSDB_SUVD_CGC_CTRL_BASE_IDX 1
+#define regSIT0_NXT_SUVD_CGC_CTRL 0x00c6
+#define regSIT0_NXT_SUVD_CGC_CTRL_BASE_IDX 1
+#define regSIT1_NXT_SUVD_CGC_CTRL 0x00c6
+#define regSIT1_NXT_SUVD_CGC_CTRL_BASE_IDX 1
+#define regSIT2_NXT_SUVD_CGC_CTRL 0x00c6
+#define regSIT2_NXT_SUVD_CGC_CTRL_BASE_IDX 1
+#define regSIT_SUVD_CGC_CTRL 0x00c6
+#define regSIT_SUVD_CGC_CTRL_BASE_IDX 1
+#define regSMPA_SUVD_CGC_CTRL 0x00c6
+#define regSMPA_SUVD_CGC_CTRL_BASE_IDX 1
+#define regSMP_SUVD_CGC_CTRL 0x00c6
+#define regSMP_SUVD_CGC_CTRL_BASE_IDX 1
+#define regSRE_SUVD_CGC_CTRL 0x00c6
+#define regSRE_SUVD_CGC_CTRL_BASE_IDX 1
+#define regUVD_MPBE0_SUVD_CGC_CTRL 0x00c6
+#define regUVD_MPBE0_SUVD_CGC_CTRL_BASE_IDX 1
+#define regUVD_MPBE1_SUVD_CGC_CTRL 0x00c6
+#define regUVD_MPBE1_SUVD_CGC_CTRL_BASE_IDX 1
+#define regUVD_SUVD_CGC_CTRL 0x00c6
+#define regUVD_SUVD_CGC_CTRL_BASE_IDX 1
+#define regUVD_CGC_CTRL3 0x00ca
+#define regUVD_CGC_CTRL3_BASE_IDX 1
+#define regUVD_GPCOM_VCPU_DATA0 0x00d0
+#define regUVD_GPCOM_VCPU_DATA0_BASE_IDX 1
+#define regUVD_GPCOM_VCPU_DATA1 0x00d1
+#define regUVD_GPCOM_VCPU_DATA1_BASE_IDX 1
+#define regUVD_GPCOM_SYS_CMD 0x00d2
+#define regUVD_GPCOM_SYS_CMD_BASE_IDX 1
+#define regUVD_GPCOM_SYS_DATA0 0x00d3
+#define regUVD_GPCOM_SYS_DATA0_BASE_IDX 1
+#define regUVD_GPCOM_SYS_DATA1 0x00d4
+#define regUVD_GPCOM_SYS_DATA1_BASE_IDX 1
+#define regUVD_VCPU_INT_EN 0x00d5
+#define regUVD_VCPU_INT_EN_BASE_IDX 1
+#define regUVD_VCPU_INT_STATUS 0x00d6
+#define regUVD_VCPU_INT_STATUS_BASE_IDX 1
+#define regUVD_VCPU_INT_ACK 0x00d7
+#define regUVD_VCPU_INT_ACK_BASE_IDX 1
+#define regUVD_VCPU_INT_ROUTE 0x00d8
+#define regUVD_VCPU_INT_ROUTE_BASE_IDX 1
+#define regUVD_DRV_FW_MSG 0x00d9
+#define regUVD_DRV_FW_MSG_BASE_IDX 1
+#define regUVD_FW_DRV_MSG_ACK 0x00da
+#define regUVD_FW_DRV_MSG_ACK_BASE_IDX 1
+#define regUVD_SUVD_INT_EN 0x00db
+#define regUVD_SUVD_INT_EN_BASE_IDX 1
+#define regUVD_SUVD_INT_STATUS 0x00dc
+#define regUVD_SUVD_INT_STATUS_BASE_IDX 1
+#define regUVD_SUVD_INT_ACK 0x00dd
+#define regUVD_SUVD_INT_ACK_BASE_IDX 1
+#define regUVD_ENC_VCPU_INT_EN 0x00de
+#define regUVD_ENC_VCPU_INT_EN_BASE_IDX 1
+#define regUVD_ENC_VCPU_INT_STATUS 0x00df
+#define regUVD_ENC_VCPU_INT_STATUS_BASE_IDX 1
+#define regUVD_ENC_VCPU_INT_ACK 0x00e0
+#define regUVD_ENC_VCPU_INT_ACK_BASE_IDX 1
+#define regUVD_MASTINT_EN 0x00e1
+#define regUVD_MASTINT_EN_BASE_IDX 1
+#define regUVD_SYS_INT_EN 0x00e2
+#define regUVD_SYS_INT_EN_BASE_IDX 1
+#define regUVD_SYS_INT_STATUS 0x00e3
+#define regUVD_SYS_INT_STATUS_BASE_IDX 1
+#define regUVD_SYS_INT_ACK 0x00e4
+#define regUVD_SYS_INT_ACK_BASE_IDX 1
+#define regUVD_JOB_DONE 0x00e5
+#define regUVD_JOB_DONE_BASE_IDX 1
+#define regUVD_CBUF_ID 0x00e6
+#define regUVD_CBUF_ID_BASE_IDX 1
+#define regUVD_CONTEXT_ID 0x00e7
+#define regUVD_CONTEXT_ID_BASE_IDX 1
+#define regUVD_CONTEXT_ID2 0x00e8
+#define regUVD_CONTEXT_ID2_BASE_IDX 1
+#define regUVD_NO_OP 0x00e9
+#define regUVD_NO_OP_BASE_IDX 1
+#define regUVD_RB_BASE_LO 0x00ea
+#define regUVD_RB_BASE_LO_BASE_IDX 1
+#define regUVD_RB_BASE_HI 0x00eb
+#define regUVD_RB_BASE_HI_BASE_IDX 1
+#define regUVD_RB_SIZE 0x00ec
+#define regUVD_RB_SIZE_BASE_IDX 1
+#define regUVD_RB_BASE_LO2 0x00ef
+#define regUVD_RB_BASE_LO2_BASE_IDX 1
+#define regUVD_RB_BASE_HI2 0x00f0
+#define regUVD_RB_BASE_HI2_BASE_IDX 1
+#define regUVD_RB_SIZE2 0x00f1
+#define regUVD_RB_SIZE2_BASE_IDX 1
+#define regUVD_RB_BASE_LO3 0x00f4
+#define regUVD_RB_BASE_LO3_BASE_IDX 1
+#define regUVD_RB_BASE_HI3 0x00f5
+#define regUVD_RB_BASE_HI3_BASE_IDX 1
+#define regUVD_RB_SIZE3 0x00f6
+#define regUVD_RB_SIZE3_BASE_IDX 1
+#define regUVD_RB_BASE_LO4 0x00f9
+#define regUVD_RB_BASE_LO4_BASE_IDX 1
+#define regUVD_RB_BASE_HI4 0x00fa
+#define regUVD_RB_BASE_HI4_BASE_IDX 1
+#define regUVD_RB_SIZE4 0x00fb
+#define regUVD_RB_SIZE4_BASE_IDX 1
+#define regUVD_OUT_RB_BASE_LO 0x00fe
+#define regUVD_OUT_RB_BASE_LO_BASE_IDX 1
+#define regUVD_OUT_RB_BASE_HI 0x00ff
+#define regUVD_OUT_RB_BASE_HI_BASE_IDX 1
+#define regUVD_OUT_RB_SIZE 0x0100
+#define regUVD_OUT_RB_SIZE_BASE_IDX 1
+#define regUVD_IOV_ACTIVE_FCN_ID 0x0103
+#define regUVD_IOV_ACTIVE_FCN_ID_BASE_IDX 1
+#define regUVD_IOV_MAILBOX 0x0104
+#define regUVD_IOV_MAILBOX_BASE_IDX 1
+#define regUVD_IOV_MAILBOX_RESP 0x0105
+#define regUVD_IOV_MAILBOX_RESP_BASE_IDX 1
+#define regUVD_RB_ARB_CTRL 0x0106
+#define regUVD_RB_ARB_CTRL_BASE_IDX 1
+#define regUVD_CTX_INDEX 0x0107
+#define regUVD_CTX_INDEX_BASE_IDX 1
+#define regUVD_CTX_DATA 0x0108
+#define regUVD_CTX_DATA_BASE_IDX 1
+#define regUVD_CXW_WR 0x0109
+#define regUVD_CXW_WR_BASE_IDX 1
+#define regUVD_CXW_WR_INT_ID 0x010a
+#define regUVD_CXW_WR_INT_ID_BASE_IDX 1
+#define regUVD_CXW_WR_INT_CTX_ID 0x010b
+#define regUVD_CXW_WR_INT_CTX_ID_BASE_IDX 1
+#define regUVD_CXW_INT_ID 0x010c
+#define regUVD_CXW_INT_ID_BASE_IDX 1
+#define regUVD_MPEG2_ERROR 0x010d
+#define regUVD_MPEG2_ERROR_BASE_IDX 1
+#define regUVD_YBASE 0x0110
+#define regUVD_YBASE_BASE_IDX 1
+#define regUVD_UVBASE 0x0111
+#define regUVD_UVBASE_BASE_IDX 1
+#define regUVD_PITCH 0x0112
+#define regUVD_PITCH_BASE_IDX 1
+#define regUVD_WIDTH 0x0113
+#define regUVD_WIDTH_BASE_IDX 1
+#define regUVD_HEIGHT 0x0114
+#define regUVD_HEIGHT_BASE_IDX 1
+#define regUVD_PICCOUNT 0x0115
+#define regUVD_PICCOUNT_BASE_IDX 1
+#define regUVD_MPRD_INITIAL_XY 0x0116
+#define regUVD_MPRD_INITIAL_XY_BASE_IDX 1
+#define regUVD_MPEG2_CTRL 0x0117
+#define regUVD_MPEG2_CTRL_BASE_IDX 1
+#define regUVD_MB_CTL_BUF_BASE 0x0118
+#define regUVD_MB_CTL_BUF_BASE_BASE_IDX 1
+#define regUVD_PIC_CTL_BUF_BASE 0x0119
+#define regUVD_PIC_CTL_BUF_BASE_BASE_IDX 1
+#define regUVD_DXVA_BUF_SIZE 0x011a
+#define regUVD_DXVA_BUF_SIZE_BASE_IDX 1
+#define regUVD_SCRATCH_NP 0x011b
+#define regUVD_SCRATCH_NP_BASE_IDX 1
+#define regUVD_CLK_SWT_HANDSHAKE 0x011c
+#define regUVD_CLK_SWT_HANDSHAKE_BASE_IDX 1
+#define regUVD_GP_SCRATCH0 0x011e
+#define regUVD_GP_SCRATCH0_BASE_IDX 1
+#define regUVD_GP_SCRATCH1 0x011f
+#define regUVD_GP_SCRATCH1_BASE_IDX 1
+#define regUVD_GP_SCRATCH2 0x0120
+#define regUVD_GP_SCRATCH2_BASE_IDX 1
+#define regUVD_GP_SCRATCH3 0x0121
+#define regUVD_GP_SCRATCH3_BASE_IDX 1
+#define regUVD_GP_SCRATCH4 0x0122
+#define regUVD_GP_SCRATCH4_BASE_IDX 1
+#define regUVD_GP_SCRATCH5 0x0123
+#define regUVD_GP_SCRATCH5_BASE_IDX 1
+#define regUVD_GP_SCRATCH6 0x0124
+#define regUVD_GP_SCRATCH6_BASE_IDX 1
+#define regUVD_GP_SCRATCH7 0x0125
+#define regUVD_GP_SCRATCH7_BASE_IDX 1
+#define regUVD_GP_SCRATCH8 0x0126
+#define regUVD_GP_SCRATCH8_BASE_IDX 1
+#define regUVD_GP_SCRATCH9 0x0127
+#define regUVD_GP_SCRATCH9_BASE_IDX 1
+#define regUVD_GP_SCRATCH10 0x0128
+#define regUVD_GP_SCRATCH10_BASE_IDX 1
+#define regUVD_GP_SCRATCH11 0x0129
+#define regUVD_GP_SCRATCH11_BASE_IDX 1
+#define regUVD_GP_SCRATCH12 0x012a
+#define regUVD_GP_SCRATCH12_BASE_IDX 1
+#define regUVD_GP_SCRATCH13 0x012b
+#define regUVD_GP_SCRATCH13_BASE_IDX 1
+#define regUVD_GP_SCRATCH14 0x012c
+#define regUVD_GP_SCRATCH14_BASE_IDX 1
+#define regUVD_GP_SCRATCH15 0x012d
+#define regUVD_GP_SCRATCH15_BASE_IDX 1
+#define regUVD_GP_SCRATCH16 0x012e
+#define regUVD_GP_SCRATCH16_BASE_IDX 1
+#define regUVD_GP_SCRATCH17 0x012f
+#define regUVD_GP_SCRATCH17_BASE_IDX 1
+#define regUVD_GP_SCRATCH18 0x0130
+#define regUVD_GP_SCRATCH18_BASE_IDX 1
+#define regUVD_GP_SCRATCH19 0x0131
+#define regUVD_GP_SCRATCH19_BASE_IDX 1
+#define regUVD_GP_SCRATCH20 0x0132
+#define regUVD_GP_SCRATCH20_BASE_IDX 1
+#define regUVD_GP_SCRATCH21 0x0133
+#define regUVD_GP_SCRATCH21_BASE_IDX 1
+#define regUVD_GP_SCRATCH22 0x0134
+#define regUVD_GP_SCRATCH22_BASE_IDX 1
+#define regUVD_GP_SCRATCH23 0x0135
+#define regUVD_GP_SCRATCH23_BASE_IDX 1
+#define regUVD_AUDIO_RB_BASE_LO 0x0136
+#define regUVD_AUDIO_RB_BASE_LO_BASE_IDX 1
+#define regUVD_AUDIO_RB_BASE_HI 0x0137
+#define regUVD_AUDIO_RB_BASE_HI_BASE_IDX 1
+#define regUVD_AUDIO_RB_SIZE 0x0138
+#define regUVD_AUDIO_RB_SIZE_BASE_IDX 1
+#define regUVD_VCPU_INT_STATUS2 0x013b
+#define regUVD_VCPU_INT_STATUS2_BASE_IDX 1
+#define regUVD_VCPU_INT_ACK2 0x013c
+#define regUVD_VCPU_INT_ACK2_BASE_IDX 1
+#define regUVD_VCPU_INT_EN2 0x013d
+#define regUVD_VCPU_INT_EN2_BASE_IDX 1
+#define regUVD_SUVD_CGC_STATUS2 0x013e
+#define regUVD_SUVD_CGC_STATUS2_BASE_IDX 1
+#define regUVD_SUVD_INT_STATUS2 0x0140
+#define regUVD_SUVD_INT_STATUS2_BASE_IDX 1
+#define regUVD_SUVD_INT_EN2 0x0141
+#define regUVD_SUVD_INT_EN2_BASE_IDX 1
+#define regUVD_SUVD_INT_ACK2 0x0142
+#define regUVD_SUVD_INT_ACK2_BASE_IDX 1
+#define regUVD_STATUS 0x0143
+#define regUVD_STATUS_BASE_IDX 1
+#define regUVD_ENC_PIPE_BUSY 0x0144
+#define regUVD_ENC_PIPE_BUSY_BASE_IDX 1
+#define regUVD_FW_POWER_STATUS 0x0145
+#define regUVD_FW_POWER_STATUS_BASE_IDX 1
+#define regUVD_CNTL 0x0146
+#define regUVD_CNTL_BASE_IDX 1
+#define regUVD_SOFT_RESET 0x0147
+#define regUVD_SOFT_RESET_BASE_IDX 1
+#define regUVD_SOFT_RESET2 0x0148
+#define regUVD_SOFT_RESET2_BASE_IDX 1
+#define regUVD_MMSCH_SOFT_RESET 0x0149
+#define regUVD_MMSCH_SOFT_RESET_BASE_IDX 1
+#define regUVD_WIG_CTRL 0x014a
+#define regUVD_WIG_CTRL_BASE_IDX 1
+#define regUVD_CGC_STATUS 0x014c
+#define regUVD_CGC_STATUS_BASE_IDX 1
+#define regUVD_CGC_UDEC_STATUS 0x014e
+#define regUVD_CGC_UDEC_STATUS_BASE_IDX 1
+#define regUVD_SUVD_CGC_STATUS 0x0150
+#define regUVD_SUVD_CGC_STATUS_BASE_IDX 1
+#define regUVD_GPCOM_VCPU_CMD 0x0152
+#define regUVD_GPCOM_VCPU_CMD_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_ecpudec
+// base address: 0x1fe00
+#define regUVD_VCPU_CACHE_OFFSET0 0x0180
+#define regUVD_VCPU_CACHE_OFFSET0_BASE_IDX 1
+#define regUVD_VCPU_CACHE_SIZE0 0x0181
+#define regUVD_VCPU_CACHE_SIZE0_BASE_IDX 1
+#define regUVD_VCPU_CACHE_OFFSET1 0x0182
+#define regUVD_VCPU_CACHE_OFFSET1_BASE_IDX 1
+#define regUVD_VCPU_CACHE_SIZE1 0x0183
+#define regUVD_VCPU_CACHE_SIZE1_BASE_IDX 1
+#define regUVD_VCPU_CACHE_OFFSET2 0x0184
+#define regUVD_VCPU_CACHE_OFFSET2_BASE_IDX 1
+#define regUVD_VCPU_CACHE_SIZE2 0x0185
+#define regUVD_VCPU_CACHE_SIZE2_BASE_IDX 1
+#define regUVD_VCPU_CACHE_OFFSET3 0x0186
+#define regUVD_VCPU_CACHE_OFFSET3_BASE_IDX 1
+#define regUVD_VCPU_CACHE_SIZE3 0x0187
+#define regUVD_VCPU_CACHE_SIZE3_BASE_IDX 1
+#define regUVD_VCPU_CACHE_OFFSET4 0x0188
+#define regUVD_VCPU_CACHE_OFFSET4_BASE_IDX 1
+#define regUVD_VCPU_CACHE_SIZE4 0x0189
+#define regUVD_VCPU_CACHE_SIZE4_BASE_IDX 1
+#define regUVD_VCPU_CACHE_OFFSET5 0x018a
+#define regUVD_VCPU_CACHE_OFFSET5_BASE_IDX 1
+#define regUVD_VCPU_CACHE_SIZE5 0x018b
+#define regUVD_VCPU_CACHE_SIZE5_BASE_IDX 1
+#define regUVD_VCPU_CACHE_OFFSET6 0x018c
+#define regUVD_VCPU_CACHE_OFFSET6_BASE_IDX 1
+#define regUVD_VCPU_CACHE_SIZE6 0x018d
+#define regUVD_VCPU_CACHE_SIZE6_BASE_IDX 1
+#define regUVD_VCPU_CACHE_OFFSET7 0x018e
+#define regUVD_VCPU_CACHE_OFFSET7_BASE_IDX 1
+#define regUVD_VCPU_CACHE_SIZE7 0x018f
+#define regUVD_VCPU_CACHE_SIZE7_BASE_IDX 1
+#define regUVD_VCPU_CACHE_OFFSET8 0x0190
+#define regUVD_VCPU_CACHE_OFFSET8_BASE_IDX 1
+#define regUVD_VCPU_CACHE_SIZE8 0x0191
+#define regUVD_VCPU_CACHE_SIZE8_BASE_IDX 1
+#define regUVD_VCPU_NONCACHE_OFFSET0 0x0192
+#define regUVD_VCPU_NONCACHE_OFFSET0_BASE_IDX 1
+#define regUVD_VCPU_NONCACHE_SIZE0 0x0193
+#define regUVD_VCPU_NONCACHE_SIZE0_BASE_IDX 1
+#define regUVD_VCPU_NONCACHE_OFFSET1 0x0194
+#define regUVD_VCPU_NONCACHE_OFFSET1_BASE_IDX 1
+#define regUVD_VCPU_NONCACHE_SIZE1 0x0195
+#define regUVD_VCPU_NONCACHE_SIZE1_BASE_IDX 1
+#define regUVD_VCPU_CNTL 0x0196
+#define regUVD_VCPU_CNTL_BASE_IDX 1
+#define regUVD_VCPU_PRID 0x0197
+#define regUVD_VCPU_PRID_BASE_IDX 1
+#define regUVD_VCPU_TRCE 0x0198
+#define regUVD_VCPU_TRCE_BASE_IDX 1
+#define regUVD_VCPU_TRCE_RD 0x0199
+#define regUVD_VCPU_TRCE_RD_BASE_IDX 1
+#define regUVD_VCPU_IND_INDEX 0x019b
+#define regUVD_VCPU_IND_INDEX_BASE_IDX 1
+#define regUVD_VCPU_IND_DATA 0x019c
+#define regUVD_VCPU_IND_DATA_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_uvd_mpcdec
+// base address: 0x1ff30
+#define regUVD_MP_SWAP_CNTL 0x01cc
+#define regUVD_MP_SWAP_CNTL_BASE_IDX 1
+#define regUVD_MP_SWAP_CNTL2 0x01cd
+#define regUVD_MP_SWAP_CNTL2_BASE_IDX 1
+#define regUVD_MPC_LUMA_SRCH 0x01ce
+#define regUVD_MPC_LUMA_SRCH_BASE_IDX 1
+#define regUVD_MPC_LUMA_HIT 0x01cf
+#define regUVD_MPC_LUMA_HIT_BASE_IDX 1
+#define regUVD_MPC_LUMA_HITPEND 0x01d0
+#define regUVD_MPC_LUMA_HITPEND_BASE_IDX 1
+#define regUVD_MPC_CHROMA_SRCH 0x01d1
+#define regUVD_MPC_CHROMA_SRCH_BASE_IDX 1
+#define regUVD_MPC_CHROMA_HIT 0x01d2
+#define regUVD_MPC_CHROMA_HIT_BASE_IDX 1
+#define regUVD_MPC_CHROMA_HITPEND 0x01d3
+#define regUVD_MPC_CHROMA_HITPEND_BASE_IDX 1
+#define regUVD_MPC_CNTL 0x01d4
+#define regUVD_MPC_CNTL_BASE_IDX 1
+#define regUVD_MPC_PITCH 0x01d5
+#define regUVD_MPC_PITCH_BASE_IDX 1
+#define regUVD_MPC_SET_MUXA0 0x01d6
+#define regUVD_MPC_SET_MUXA0_BASE_IDX 1
+#define regUVD_MPC_SET_MUXA1 0x01d7
+#define regUVD_MPC_SET_MUXA1_BASE_IDX 1
+#define regUVD_MPC_SET_MUXB0 0x01d8
+#define regUVD_MPC_SET_MUXB0_BASE_IDX 1
+#define regUVD_MPC_SET_MUXB1 0x01d9
+#define regUVD_MPC_SET_MUXB1_BASE_IDX 1
+#define regUVD_MPC_SET_MUX 0x01da
+#define regUVD_MPC_SET_MUX_BASE_IDX 1
+#define regUVD_MPC_SET_ALU 0x01db
+#define regUVD_MPC_SET_ALU_BASE_IDX 1
+#define regUVD_MPC_PERF0 0x01dc
+#define regUVD_MPC_PERF0_BASE_IDX 1
+#define regUVD_MPC_PERF1 0x01dd
+#define regUVD_MPC_PERF1_BASE_IDX 1
+#define regUVD_MPC_IND_INDEX 0x01de
+#define regUVD_MPC_IND_INDEX_BASE_IDX 1
+#define regUVD_MPC_IND_DATA 0x01df
+#define regUVD_MPC_IND_DATA_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_uvd_rbcdec
+// base address: 0x1ff90
+#define regUVD_RBC_IB_SIZE 0x01e4
+#define regUVD_RBC_IB_SIZE_BASE_IDX 1
+#define regUVD_RBC_IB_SIZE_UPDATE 0x01e5
+#define regUVD_RBC_IB_SIZE_UPDATE_BASE_IDX 1
+#define regUVD_RBC_RB_CNTL 0x01e6
+#define regUVD_RBC_RB_CNTL_BASE_IDX 1
+#define regUVD_RBC_RB_RPTR_ADDR 0x01e7
+#define regUVD_RBC_RB_RPTR_ADDR_BASE_IDX 1
+#define regUVD_RBC_VCPU_ACCESS 0x01ea
+#define regUVD_RBC_VCPU_ACCESS_BASE_IDX 1
+#define regUVD_FW_SEMAPHORE_CNTL 0x01eb
+#define regUVD_FW_SEMAPHORE_CNTL_BASE_IDX 1
+#define regUVD_RBC_READ_REQ_URGENT_CNTL 0x01ed
+#define regUVD_RBC_READ_REQ_URGENT_CNTL_BASE_IDX 1
+#define regUVD_RBC_RB_WPTR_CNTL 0x01ee
+#define regUVD_RBC_RB_WPTR_CNTL_BASE_IDX 1
+#define regUVD_RBC_WPTR_STATUS 0x01ef
+#define regUVD_RBC_WPTR_STATUS_BASE_IDX 1
+#define regUVD_RBC_WPTR_POLL_CNTL 0x01f0
+#define regUVD_RBC_WPTR_POLL_CNTL_BASE_IDX 1
+#define regUVD_RBC_WPTR_POLL_ADDR 0x01f1
+#define regUVD_RBC_WPTR_POLL_ADDR_BASE_IDX 1
+#define regUVD_SEMA_CMD 0x01f2
+#define regUVD_SEMA_CMD_BASE_IDX 1
+#define regUVD_SEMA_ADDR_LOW 0x01f3
+#define regUVD_SEMA_ADDR_LOW_BASE_IDX 1
+#define regUVD_SEMA_ADDR_HIGH 0x01f4
+#define regUVD_SEMA_ADDR_HIGH_BASE_IDX 1
+#define regUVD_ENGINE_CNTL 0x01f5
+#define regUVD_ENGINE_CNTL_BASE_IDX 1
+#define regUVD_SEMA_TIMEOUT_STATUS 0x01f6
+#define regUVD_SEMA_TIMEOUT_STATUS_BASE_IDX 1
+#define regUVD_SEMA_CNTL 0x01f7
+#define regUVD_SEMA_CNTL_BASE_IDX 1
+#define regUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL 0x01f8
+#define regUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL_BASE_IDX 1
+#define regUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL 0x01f9
+#define regUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL_BASE_IDX 1
+#define regUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL 0x01fa
+#define regUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL_BASE_IDX 1
+#define regUVD_JOB_START 0x01fb
+#define regUVD_JOB_START_BASE_IDX 1
+#define regUVD_RBC_BUF_STATUS 0x01fc
+#define regUVD_RBC_BUF_STATUS_BASE_IDX 1
+#define regUVD_RBC_SWAP_CNTL 0x01fd
+#define regUVD_RBC_SWAP_CNTL_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_lmi_adpdec
+// base address: 0x20090
+#define regUVD_LMI_RE_64BIT_BAR_LOW 0x0224
+#define regUVD_LMI_RE_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_RE_64BIT_BAR_HIGH 0x0225
+#define regUVD_LMI_RE_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_IT_64BIT_BAR_LOW 0x0226
+#define regUVD_LMI_IT_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_IT_64BIT_BAR_HIGH 0x0227
+#define regUVD_LMI_IT_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MP_64BIT_BAR_LOW 0x0228
+#define regUVD_LMI_MP_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MP_64BIT_BAR_HIGH 0x0229
+#define regUVD_LMI_MP_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_CM_64BIT_BAR_LOW 0x022a
+#define regUVD_LMI_CM_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_CM_64BIT_BAR_HIGH 0x022b
+#define regUVD_LMI_CM_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_DB_64BIT_BAR_LOW 0x022c
+#define regUVD_LMI_DB_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_DB_64BIT_BAR_HIGH 0x022d
+#define regUVD_LMI_DB_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_DBW_64BIT_BAR_LOW 0x022e
+#define regUVD_LMI_DBW_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_DBW_64BIT_BAR_HIGH 0x022f
+#define regUVD_LMI_DBW_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_IDCT_64BIT_BAR_LOW 0x0230
+#define regUVD_LMI_IDCT_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_IDCT_64BIT_BAR_HIGH 0x0231
+#define regUVD_LMI_IDCT_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MPRD_S0_64BIT_BAR_LOW 0x0232
+#define regUVD_LMI_MPRD_S0_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MPRD_S0_64BIT_BAR_HIGH 0x0233
+#define regUVD_LMI_MPRD_S0_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MPRD_S1_64BIT_BAR_LOW 0x0234
+#define regUVD_LMI_MPRD_S1_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MPRD_S1_64BIT_BAR_HIGH 0x0235
+#define regUVD_LMI_MPRD_S1_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MPRD_DBW_64BIT_BAR_LOW 0x0236
+#define regUVD_LMI_MPRD_DBW_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MPRD_DBW_64BIT_BAR_HIGH 0x0237
+#define regUVD_LMI_MPRD_DBW_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MPC_64BIT_BAR_LOW 0x0238
+#define regUVD_LMI_MPC_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MPC_64BIT_BAR_HIGH 0x0239
+#define regUVD_LMI_MPC_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_RBC_RB_64BIT_BAR_LOW 0x023a
+#define regUVD_LMI_RBC_RB_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_RBC_RB_64BIT_BAR_HIGH 0x023b
+#define regUVD_LMI_RBC_RB_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_RBC_IB_64BIT_BAR_LOW 0x023c
+#define regUVD_LMI_RBC_IB_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_RBC_IB_64BIT_BAR_HIGH 0x023d
+#define regUVD_LMI_RBC_IB_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_LBSI_64BIT_BAR_LOW 0x023e
+#define regUVD_LMI_LBSI_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_LBSI_64BIT_BAR_HIGH 0x023f
+#define regUVD_LMI_LBSI_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW 0x0240
+#define regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH 0x0241
+#define regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_VCPU_NC1_64BIT_BAR_LOW 0x0242
+#define regUVD_LMI_VCPU_NC1_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_VCPU_NC1_64BIT_BAR_HIGH 0x0243
+#define regUVD_LMI_VCPU_NC1_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW 0x0244
+#define regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH 0x0245
+#define regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_CENC_64BIT_BAR_LOW 0x0246
+#define regUVD_LMI_CENC_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_CENC_64BIT_BAR_HIGH 0x0247
+#define regUVD_LMI_CENC_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_SRE_64BIT_BAR_LOW 0x0248
+#define regUVD_LMI_SRE_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_SRE_64BIT_BAR_HIGH 0x0249
+#define regUVD_LMI_SRE_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_GPGPU_64BIT_BAR_LOW 0x024a
+#define regUVD_LMI_MIF_GPGPU_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_GPGPU_64BIT_BAR_HIGH 0x024b
+#define regUVD_LMI_MIF_GPGPU_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_CURR_LUMA_64BIT_BAR_LOW 0x024c
+#define regUVD_LMI_MIF_CURR_LUMA_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_CURR_LUMA_64BIT_BAR_HIGH 0x024d
+#define regUVD_LMI_MIF_CURR_LUMA_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_CURR_CHROMA_64BIT_BAR_LOW 0x024e
+#define regUVD_LMI_MIF_CURR_CHROMA_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_CURR_CHROMA_64BIT_BAR_HIGH 0x024f
+#define regUVD_LMI_MIF_CURR_CHROMA_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_REF_64BIT_BAR_LOW 0x0250
+#define regUVD_LMI_MIF_REF_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_REF_64BIT_BAR_HIGH 0x0251
+#define regUVD_LMI_MIF_REF_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_DBW_64BIT_BAR_LOW 0x0252
+#define regUVD_LMI_MIF_DBW_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_DBW_64BIT_BAR_HIGH 0x0253
+#define regUVD_LMI_MIF_DBW_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_CM_COLOC_64BIT_BAR_LOW 0x0254
+#define regUVD_LMI_MIF_CM_COLOC_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_CM_COLOC_64BIT_BAR_HIGH 0x0255
+#define regUVD_LMI_MIF_CM_COLOC_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_BSP0_64BIT_BAR_LOW 0x0256
+#define regUVD_LMI_MIF_BSP0_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_BSP0_64BIT_BAR_HIGH 0x0257
+#define regUVD_LMI_MIF_BSP0_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_BSP1_64BIT_BAR_LOW 0x0258
+#define regUVD_LMI_MIF_BSP1_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_BSP1_64BIT_BAR_HIGH 0x0259
+#define regUVD_LMI_MIF_BSP1_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_BSP2_64BIT_BAR_LOW 0x025a
+#define regUVD_LMI_MIF_BSP2_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_BSP2_64BIT_BAR_HIGH 0x025b
+#define regUVD_LMI_MIF_BSP2_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_BSP3_64BIT_BAR_LOW 0x025c
+#define regUVD_LMI_MIF_BSP3_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_BSP3_64BIT_BAR_HIGH 0x025d
+#define regUVD_LMI_MIF_BSP3_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_BSD0_64BIT_BAR_LOW 0x025e
+#define regUVD_LMI_MIF_BSD0_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_BSD0_64BIT_BAR_HIGH 0x025f
+#define regUVD_LMI_MIF_BSD0_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_BSD1_64BIT_BAR_LOW 0x0260
+#define regUVD_LMI_MIF_BSD1_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_BSD1_64BIT_BAR_HIGH 0x0261
+#define regUVD_LMI_MIF_BSD1_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_BSD2_64BIT_BAR_LOW 0x0262
+#define regUVD_LMI_MIF_BSD2_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_BSD2_64BIT_BAR_HIGH 0x0263
+#define regUVD_LMI_MIF_BSD2_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_BSD3_64BIT_BAR_LOW 0x0264
+#define regUVD_LMI_MIF_BSD3_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_BSD3_64BIT_BAR_HIGH 0x0265
+#define regUVD_LMI_MIF_BSD3_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_BSD4_64BIT_BAR_LOW 0x0266
+#define regUVD_LMI_MIF_BSD4_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_BSD4_64BIT_BAR_HIGH 0x0267
+#define regUVD_LMI_MIF_BSD4_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW 0x0270
+#define regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH 0x0271
+#define regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE8_64BIT_BAR_LOW 0x0272
+#define regUVD_LMI_VCPU_CACHE8_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE8_64BIT_BAR_HIGH 0x0273
+#define regUVD_LMI_VCPU_CACHE8_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW 0x0274
+#define regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH 0x0275
+#define regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE3_64BIT_BAR_LOW 0x0276
+#define regUVD_LMI_VCPU_CACHE3_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE3_64BIT_BAR_HIGH 0x0277
+#define regUVD_LMI_VCPU_CACHE3_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE4_64BIT_BAR_LOW 0x0278
+#define regUVD_LMI_VCPU_CACHE4_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE4_64BIT_BAR_HIGH 0x0279
+#define regUVD_LMI_VCPU_CACHE4_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE5_64BIT_BAR_LOW 0x027a
+#define regUVD_LMI_VCPU_CACHE5_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE5_64BIT_BAR_HIGH 0x027b
+#define regUVD_LMI_VCPU_CACHE5_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE6_64BIT_BAR_LOW 0x027c
+#define regUVD_LMI_VCPU_CACHE6_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE6_64BIT_BAR_HIGH 0x027d
+#define regUVD_LMI_VCPU_CACHE6_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE7_64BIT_BAR_LOW 0x027e
+#define regUVD_LMI_VCPU_CACHE7_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE7_64BIT_BAR_HIGH 0x027f
+#define regUVD_LMI_VCPU_CACHE7_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_SCLR_64BIT_BAR_LOW 0x0280
+#define regUVD_LMI_MIF_SCLR_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_SCLR_64BIT_BAR_HIGH 0x0281
+#define regUVD_LMI_MIF_SCLR_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_SCLR2_64BIT_BAR_LOW 0x0282
+#define regUVD_LMI_MIF_SCLR2_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_SCLR2_64BIT_BAR_HIGH 0x0283
+#define regUVD_LMI_MIF_SCLR2_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_SPH_64BIT_BAR_HIGH 0x0284
+#define regUVD_LMI_SPH_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_IMAGEPASTE_LUMA_64BIT_BAR_LOW 0x0298
+#define regUVD_LMI_MIF_IMAGEPASTE_LUMA_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_IMAGEPASTE_LUMA_64BIT_BAR_HIGH 0x0299
+#define regUVD_LMI_MIF_IMAGEPASTE_LUMA_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_IMAGEPASTE_CHROMA_64BIT_BAR_LOW 0x029a
+#define regUVD_LMI_MIF_IMAGEPASTE_CHROMA_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_IMAGEPASTE_CHROMA_64BIT_BAR_HIGH 0x029b
+#define regUVD_LMI_MIF_IMAGEPASTE_CHROMA_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_PRIVACY_LUMA_64BIT_BAR_LOW 0x029c
+#define regUVD_LMI_MIF_PRIVACY_LUMA_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_PRIVACY_LUMA_64BIT_BAR_HIGH 0x029d
+#define regUVD_LMI_MIF_PRIVACY_LUMA_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MIF_PRIVACY_CHROMA_64BIT_BAR_LOW 0x029e
+#define regUVD_LMI_MIF_PRIVACY_CHROMA_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_PRIVACY_CHROMA_64BIT_BAR_HIGH 0x029f
+#define regUVD_LMI_MIF_PRIVACY_CHROMA_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_ADP_ATOMIC_CONFIG 0x02a1
+#define regUVD_ADP_ATOMIC_CONFIG_BASE_IDX 1
+#define regUVD_LMI_ARB_CTRL2 0x02a2
+#define regUVD_LMI_ARB_CTRL2_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE_VMIDS_MULTI 0x02a7
+#define regUVD_LMI_VCPU_CACHE_VMIDS_MULTI_BASE_IDX 1
+#define regUVD_LMI_VCPU_NC_VMIDS_MULTI 0x02a8
+#define regUVD_LMI_VCPU_NC_VMIDS_MULTI_BASE_IDX 1
+#define regUVD_LMI_LAT_CTRL 0x02a9
+#define regUVD_LMI_LAT_CTRL_BASE_IDX 1
+#define regUVD_LMI_LAT_CNTR 0x02aa
+#define regUVD_LMI_LAT_CNTR_BASE_IDX 1
+#define regUVD_LMI_AVG_LAT_CNTR 0x02ab
+#define regUVD_LMI_AVG_LAT_CNTR_BASE_IDX 1
+#define regUVD_LMI_SPH 0x02ac
+#define regUVD_LMI_SPH_BASE_IDX 1
+#define regUVD_LMI_VCPU_CACHE_VMID 0x02ad
+#define regUVD_LMI_VCPU_CACHE_VMID_BASE_IDX 1
+#define regUVD_LMI_CTRL2 0x02ae
+#define regUVD_LMI_CTRL2_BASE_IDX 1
+#define regUVD_LMI_URGENT_CTRL 0x02af
+#define regUVD_LMI_URGENT_CTRL_BASE_IDX 1
+#define regUVD_LMI_CTRL 0x02b0
+#define regUVD_LMI_CTRL_BASE_IDX 1
+#define regUVD_LMI_STATUS 0x02b1
+#define regUVD_LMI_STATUS_BASE_IDX 1
+#define regUVD_LMI_PERFMON_CTRL 0x02b4
+#define regUVD_LMI_PERFMON_CTRL_BASE_IDX 1
+#define regUVD_LMI_PERFMON_COUNT_LO 0x02b5
+#define regUVD_LMI_PERFMON_COUNT_LO_BASE_IDX 1
+#define regUVD_LMI_PERFMON_COUNT_HI 0x02b6
+#define regUVD_LMI_PERFMON_COUNT_HI_BASE_IDX 1
+#define regUVD_LMI_ADP_SWAP_CNTL 0x02b7
+#define regUVD_LMI_ADP_SWAP_CNTL_BASE_IDX 1
+#define regUVD_LMI_RBC_RB_VMID 0x02b8
+#define regUVD_LMI_RBC_RB_VMID_BASE_IDX 1
+#define regUVD_LMI_RBC_IB_VMID 0x02b9
+#define regUVD_LMI_RBC_IB_VMID_BASE_IDX 1
+#define regUVD_LMI_MC_CREDITS 0x02ba
+#define regUVD_LMI_MC_CREDITS_BASE_IDX 1
+#define regUVD_LMI_ADP_IND_INDEX 0x02be
+#define regUVD_LMI_ADP_IND_INDEX_BASE_IDX 1
+#define regUVD_LMI_ADP_IND_DATA 0x02bf
+#define regUVD_LMI_ADP_IND_DATA_BASE_IDX 1
+#define regUVD_LMI_ADP_PF_EN 0x02c0
+#define regUVD_LMI_ADP_PF_EN_BASE_IDX 1
+#define regUVD_LMI_PREF_CTRL 0x02c2
+#define regUVD_LMI_PREF_CTRL_BASE_IDX 1
+#define regUVD_LMI_MIF_REF_LUMA_64BIT_BAR_LOW 0x02dd
+#define regUVD_LMI_MIF_REF_LUMA_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MIF_REF_LUMA_64BIT_BAR_HIGH 0x02de
+#define regUVD_LMI_MIF_REF_LUMA_64BIT_BAR_HIGH_BASE_IDX 1
+#define regVCN_RAS_CNTL 0x02df
+#define regVCN_RAS_CNTL_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_uvd_jpeg0_jpegnpdec
+// base address: 0x20f00
+#define regUVD_JPEG_CNTL 0x05c0
+#define regUVD_JPEG_CNTL_BASE_IDX 1
+#define regUVD_JPEG_RB_BASE 0x05c1
+#define regUVD_JPEG_RB_BASE_BASE_IDX 1
+#define regUVD_JPEG_RB_WPTR 0x05c2
+#define regUVD_JPEG_RB_WPTR_BASE_IDX 1
+#define regUVD_JPEG_RB_RPTR 0x05c3
+#define regUVD_JPEG_RB_RPTR_BASE_IDX 1
+#define regUVD_JPEG_RB_SIZE 0x05c4
+#define regUVD_JPEG_RB_SIZE_BASE_IDX 1
+#define regUVD_JPEG_DEC_CNT 0x05c5
+#define regUVD_JPEG_DEC_CNT_BASE_IDX 1
+#define regUVD_JPEG_SPS_INFO 0x05c6
+#define regUVD_JPEG_SPS_INFO_BASE_IDX 1
+#define regUVD_JPEG_SPS1_INFO 0x05c7
+#define regUVD_JPEG_SPS1_INFO_BASE_IDX 1
+#define regUVD_JPEG_RE_TIMER 0x05c8
+#define regUVD_JPEG_RE_TIMER_BASE_IDX 1
+#define regUVD_JPEG_DEC_SCRATCH0 0x05c9
+#define regUVD_JPEG_DEC_SCRATCH0_BASE_IDX 1
+#define regUVD_JPEG_INT_EN 0x05ca
+#define regUVD_JPEG_INT_EN_BASE_IDX 1
+#define regUVD_JPEG_INT_STAT 0x05cb
+#define regUVD_JPEG_INT_STAT_BASE_IDX 1
+#define regUVD_JPEG_TIER_CNTL0 0x05cc
+#define regUVD_JPEG_TIER_CNTL0_BASE_IDX 1
+#define regUVD_JPEG_TIER_CNTL1 0x05cd
+#define regUVD_JPEG_TIER_CNTL1_BASE_IDX 1
+#define regUVD_JPEG_TIER_CNTL2 0x05ce
+#define regUVD_JPEG_TIER_CNTL2_BASE_IDX 1
+#define regUVD_JPEG_TIER_STATUS 0x05cf
+#define regUVD_JPEG_TIER_STATUS_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_uvd_jpeg_sclk0_jpegnpsclkdec
+// base address: 0x21000
+#define regUVD_JPEG_OUTBUF_CNTL 0x0600
+#define regUVD_JPEG_OUTBUF_CNTL_BASE_IDX 1
+#define regUVD_JPEG_OUTBUF_WPTR 0x0601
+#define regUVD_JPEG_OUTBUF_WPTR_BASE_IDX 1
+#define regUVD_JPEG_OUTBUF_RPTR 0x0602
+#define regUVD_JPEG_OUTBUF_RPTR_BASE_IDX 1
+#define regUVD_JPEG_PITCH 0x0603
+#define regUVD_JPEG_PITCH_BASE_IDX 1
+#define regUVD_JPEG_UV_PITCH 0x0604
+#define regUVD_JPEG_UV_PITCH_BASE_IDX 1
+#define regJPEG_DEC_Y_GFX8_TILING_SURFACE 0x0605
+#define regJPEG_DEC_Y_GFX8_TILING_SURFACE_BASE_IDX 1
+#define regJPEG_DEC_UV_GFX8_TILING_SURFACE 0x0606
+#define regJPEG_DEC_UV_GFX8_TILING_SURFACE_BASE_IDX 1
+#define regJPEG_DEC_GFX8_ADDR_CONFIG 0x0607
+#define regJPEG_DEC_GFX8_ADDR_CONFIG_BASE_IDX 1
+#define regJPEG_DEC_Y_GFX10_TILING_SURFACE 0x0608
+#define regJPEG_DEC_Y_GFX10_TILING_SURFACE_BASE_IDX 1
+#define regJPEG_DEC_UV_GFX10_TILING_SURFACE 0x0609
+#define regJPEG_DEC_UV_GFX10_TILING_SURFACE_BASE_IDX 1
+#define regJPEG_DEC_GFX10_ADDR_CONFIG 0x060a
+#define regJPEG_DEC_GFX10_ADDR_CONFIG_BASE_IDX 1
+#define regJPEG_DEC_ADDR_MODE 0x060b
+#define regJPEG_DEC_ADDR_MODE_BASE_IDX 1
+#define regUVD_JPEG_OUTPUT_XY 0x060c
+#define regUVD_JPEG_OUTPUT_XY_BASE_IDX 1
+#define regUVD_JPEG_GPCOM_CMD 0x060d
+#define regUVD_JPEG_GPCOM_CMD_BASE_IDX 1
+#define regUVD_JPEG_GPCOM_DATA0 0x060e
+#define regUVD_JPEG_GPCOM_DATA0_BASE_IDX 1
+#define regUVD_JPEG_GPCOM_DATA1 0x060f
+#define regUVD_JPEG_GPCOM_DATA1_BASE_IDX 1
+#define regUVD_JPEG_SCRATCH1 0x0610
+#define regUVD_JPEG_SCRATCH1_BASE_IDX 1
+#define regUVD_JPEG_DEC_SOFT_RST 0x0611
+#define regUVD_JPEG_DEC_SOFT_RST_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_uvd_jrbc0_uvd_jrbc_dec
+// base address: 0x21100
+#define regUVD_JRBC0_UVD_JRBC_RB_WPTR 0x0640
+#define regUVD_JRBC0_UVD_JRBC_RB_WPTR_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_RB_CNTL 0x0641
+#define regUVD_JRBC0_UVD_JRBC_RB_CNTL_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_IB_SIZE 0x0642
+#define regUVD_JRBC0_UVD_JRBC_IB_SIZE_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_URGENT_CNTL 0x0643
+#define regUVD_JRBC0_UVD_JRBC_URGENT_CNTL_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_RB_REF_DATA 0x0644
+#define regUVD_JRBC0_UVD_JRBC_RB_REF_DATA_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_RB_COND_RD_TIMER 0x0645
+#define regUVD_JRBC0_UVD_JRBC_RB_COND_RD_TIMER_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_SOFT_RESET 0x0648
+#define regUVD_JRBC0_UVD_JRBC_SOFT_RESET_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_STATUS 0x0649
+#define regUVD_JRBC0_UVD_JRBC_STATUS_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_RB_RPTR 0x064a
+#define regUVD_JRBC0_UVD_JRBC_RB_RPTR_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_RB_BUF_STATUS 0x064b
+#define regUVD_JRBC0_UVD_JRBC_RB_BUF_STATUS_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_IB_BUF_STATUS 0x064c
+#define regUVD_JRBC0_UVD_JRBC_IB_BUF_STATUS_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_IB_SIZE_UPDATE 0x064d
+#define regUVD_JRBC0_UVD_JRBC_IB_SIZE_UPDATE_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_IB_COND_RD_TIMER 0x064e
+#define regUVD_JRBC0_UVD_JRBC_IB_COND_RD_TIMER_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_IB_REF_DATA 0x064f
+#define regUVD_JRBC0_UVD_JRBC_IB_REF_DATA_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JPEG_PREEMPT_CMD 0x0650
+#define regUVD_JRBC0_UVD_JPEG_PREEMPT_CMD_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JPEG_PREEMPT_FENCE_DATA0 0x0651
+#define regUVD_JRBC0_UVD_JPEG_PREEMPT_FENCE_DATA0_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JPEG_PREEMPT_FENCE_DATA1 0x0652
+#define regUVD_JRBC0_UVD_JPEG_PREEMPT_FENCE_DATA1_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_RB_SIZE 0x0653
+#define regUVD_JRBC0_UVD_JRBC_RB_SIZE_BASE_IDX 1
+#define regUVD_JRBC0_UVD_JRBC_SCRATCH0 0x0654
+#define regUVD_JRBC0_UVD_JRBC_SCRATCH0_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_uvd_jmi0_uvd_jmi_dec
+// base address: 0x21180
+#define regUVD_JMI0_UVD_JPEG_DEC_PF_CTRL 0x0660
+#define regUVD_JMI0_UVD_JPEG_DEC_PF_CTRL_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JRBC_CTRL 0x0661
+#define regUVD_JMI0_UVD_LMI_JRBC_CTRL_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JPEG_CTRL 0x0662
+#define regUVD_JMI0_UVD_LMI_JPEG_CTRL_BASE_IDX 1
+#define regUVD_JMI0_JPEG_LMI_DROP 0x0663
+#define regUVD_JMI0_JPEG_LMI_DROP_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JRBC_IB_VMID 0x0664
+#define regUVD_JMI0_UVD_LMI_JRBC_IB_VMID_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JRBC_RB_VMID 0x0665
+#define regUVD_JMI0_UVD_LMI_JRBC_RB_VMID_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JPEG_VMID 0x0666
+#define regUVD_JMI0_UVD_LMI_JPEG_VMID_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW 0x0667
+#define regUVD_JMI0_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH 0x0668
+#define regUVD_JMI0_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JRBC_RB_64BIT_BAR_LOW 0x0669
+#define regUVD_JMI0_UVD_LMI_JRBC_RB_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH 0x066a
+#define regUVD_JMI0_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW 0x066b
+#define regUVD_JMI0_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH 0x066c
+#define regUVD_JMI0_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JPEG_PREEMPT_VMID 0x066d
+#define regUVD_JMI0_UVD_LMI_JPEG_PREEMPT_VMID_BASE_IDX 1
+#define regUVD_JMI0_UVD_JMI_DEC_SWAP_CNTL 0x066e
+#define regUVD_JMI0_UVD_JMI_DEC_SWAP_CNTL_BASE_IDX 1
+#define regUVD_JMI0_UVD_JMI_ATOMIC_CNTL 0x066f
+#define regUVD_JMI0_UVD_JMI_ATOMIC_CNTL_BASE_IDX 1
+#define regUVD_JMI0_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW 0x0670
+#define regUVD_JMI0_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_JMI0_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH 0x0671
+#define regUVD_JMI0_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JPEG_READ_64BIT_BAR_LOW 0x0672
+#define regUVD_JMI0_UVD_LMI_JPEG_READ_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH 0x0673
+#define regUVD_JMI0_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW 0x0674
+#define regUVD_JMI0_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH 0x0675
+#define regUVD_JMI0_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JRBC_IB_64BIT_BAR_LOW 0x0676
+#define regUVD_JMI0_UVD_LMI_JRBC_IB_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH 0x0677
+#define regUVD_JMI0_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW 0x0678
+#define regUVD_JMI0_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_JMI0_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH 0x0679
+#define regUVD_JMI0_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_JMI0_UVD_JMI_ATOMIC_CNTL2 0x067d
+#define regUVD_JMI0_UVD_JMI_ATOMIC_CNTL2_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_uvd_jmi_common_dec
+// base address: 0x21300
+#define regUVD_JADP_MCIF_URGENT_CTRL 0x06c1
+#define regUVD_JADP_MCIF_URGENT_CTRL_BASE_IDX 1
+#define regUVD_JMI_URGENT_CTRL 0x06c2
+#define regUVD_JMI_URGENT_CTRL_BASE_IDX 1
+#define regUVD_JMI_CTRL 0x06c3
+#define regUVD_JMI_CTRL_BASE_IDX 1
+#define regJPEG_MEMCHECK_CLAMPING_CNTL 0x06c4
+#define regJPEG_MEMCHECK_CLAMPING_CNTL_BASE_IDX 1
+#define regJPEG_MEMCHECK_SAFE_ADDR 0x06c5
+#define regJPEG_MEMCHECK_SAFE_ADDR_BASE_IDX 1
+#define regJPEG_MEMCHECK_SAFE_ADDR_64BIT 0x06c6
+#define regJPEG_MEMCHECK_SAFE_ADDR_64BIT_BASE_IDX 1
+#define regUVD_JMI_LAT_CTRL 0x06c7
+#define regUVD_JMI_LAT_CTRL_BASE_IDX 1
+#define regUVD_JMI_LAT_CNTR 0x06c8
+#define regUVD_JMI_LAT_CNTR_BASE_IDX 1
+#define regUVD_JMI_AVG_LAT_CNTR 0x06c9
+#define regUVD_JMI_AVG_LAT_CNTR_BASE_IDX 1
+#define regUVD_JMI_PERFMON_CTRL 0x06ca
+#define regUVD_JMI_PERFMON_CTRL_BASE_IDX 1
+#define regUVD_JMI_PERFMON_COUNT_LO 0x06cb
+#define regUVD_JMI_PERFMON_COUNT_LO_BASE_IDX 1
+#define regUVD_JMI_PERFMON_COUNT_HI 0x06cc
+#define regUVD_JMI_PERFMON_COUNT_HI_BASE_IDX 1
+#define regUVD_JMI_CLEAN_STATUS 0x06cd
+#define regUVD_JMI_CLEAN_STATUS_BASE_IDX 1
+#define regUVD_JMI_CNTL 0x06ce
+#define regUVD_JMI_CNTL_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_uvd_jpeg_common_dec
+// base address: 0x21400
+#define regJPEG_SOFT_RESET_STATUS 0x0700
+#define regJPEG_SOFT_RESET_STATUS_BASE_IDX 1
+#define regJPEG_SYS_INT_EN 0x0701
+#define regJPEG_SYS_INT_EN_BASE_IDX 1
+#define regJPEG_SYS_INT_EN1 0x0702
+#define regJPEG_SYS_INT_EN1_BASE_IDX 1
+#define regJPEG_SYS_INT_STATUS 0x0703
+#define regJPEG_SYS_INT_STATUS_BASE_IDX 1
+#define regJPEG_SYS_INT_STATUS1 0x0704
+#define regJPEG_SYS_INT_STATUS1_BASE_IDX 1
+#define regJPEG_SYS_INT_ACK 0x0705
+#define regJPEG_SYS_INT_ACK_BASE_IDX 1
+#define regJPEG_SYS_INT_ACK1 0x0706
+#define regJPEG_SYS_INT_ACK1_BASE_IDX 1
+#define regJPEG_MEMCHECK_SYS_INT_EN 0x0707
+#define regJPEG_MEMCHECK_SYS_INT_EN_BASE_IDX 1
+#define regJPEG_MEMCHECK_SYS_INT_EN1 0x0708
+#define regJPEG_MEMCHECK_SYS_INT_EN1_BASE_IDX 1
+#define regJPEG_MEMCHECK_SYS_INT_STAT 0x0709
+#define regJPEG_MEMCHECK_SYS_INT_STAT_BASE_IDX 1
+#define regJPEG_MEMCHECK_SYS_INT_STAT1 0x070a
+#define regJPEG_MEMCHECK_SYS_INT_STAT1_BASE_IDX 1
+#define regJPEG_MEMCHECK_SYS_INT_STAT2 0x070b
+#define regJPEG_MEMCHECK_SYS_INT_STAT2_BASE_IDX 1
+#define regJPEG_MEMCHECK_SYS_INT_ACK 0x070c
+#define regJPEG_MEMCHECK_SYS_INT_ACK_BASE_IDX 1
+#define regJPEG_MEMCHECK_SYS_INT_ACK1 0x070d
+#define regJPEG_MEMCHECK_SYS_INT_ACK1_BASE_IDX 1
+#define regJPEG_MEMCHECK_SYS_INT_ACK2 0x070e
+#define regJPEG_MEMCHECK_SYS_INT_ACK2_BASE_IDX 1
+#define regJPEG_MASTINT_EN 0x0710
+#define regJPEG_MASTINT_EN_BASE_IDX 1
+#define regJPEG_IH_CTRL 0x0711
+#define regJPEG_IH_CTRL_BASE_IDX 1
+#define regJRBBM_ARB_CTRL 0x0713
+#define regJRBBM_ARB_CTRL_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_uvd_jpeg_common_sclk_dec
+// base address: 0x21480
+#define regJPEG_CGC_GATE 0x0720
+#define regJPEG_CGC_GATE_BASE_IDX 1
+#define regJPEG_CGC_CTRL 0x0721
+#define regJPEG_CGC_CTRL_BASE_IDX 1
+#define regJPEG_CGC_STATUS 0x0722
+#define regJPEG_CGC_STATUS_BASE_IDX 1
+#define regJPEG_COMN_CGC_MEM_CTRL 0x0723
+#define regJPEG_COMN_CGC_MEM_CTRL_BASE_IDX 1
+#define regJPEG_DEC_CGC_MEM_CTRL 0x0724
+#define regJPEG_DEC_CGC_MEM_CTRL_BASE_IDX 1
+#define regJPEG_ENC_CGC_MEM_CTRL 0x0726
+#define regJPEG_ENC_CGC_MEM_CTRL_BASE_IDX 1
+#define regJPEG_PERF_BANK_CONF 0x0727
+#define regJPEG_PERF_BANK_CONF_BASE_IDX 1
+#define regJPEG_PERF_BANK_EVENT_SEL 0x0728
+#define regJPEG_PERF_BANK_EVENT_SEL_BASE_IDX 1
+#define regJPEG_PERF_BANK_COUNT0 0x0729
+#define regJPEG_PERF_BANK_COUNT0_BASE_IDX 1
+#define regJPEG_PERF_BANK_COUNT1 0x072a
+#define regJPEG_PERF_BANK_COUNT1_BASE_IDX 1
+#define regJPEG_PERF_BANK_COUNT2 0x072b
+#define regJPEG_PERF_BANK_COUNT2_BASE_IDX 1
+#define regJPEG_PERF_BANK_COUNT3 0x072c
+#define regJPEG_PERF_BANK_COUNT3_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_uvd_pg_dec
+// base address: 0x1f800
+#define regUVD_PGFSM_CONFIG 0x0000
+#define regUVD_PGFSM_CONFIG_BASE_IDX 1
+#define regUVD_PGFSM_STATUS 0x0001
+#define regUVD_PGFSM_STATUS_BASE_IDX 1
+#define regUVD_POWER_STATUS 0x0002
+#define regUVD_POWER_STATUS_BASE_IDX 1
+#define regUVD_JPEG_POWER_STATUS 0x0003
+#define regUVD_JPEG_POWER_STATUS_BASE_IDX 1
+#define regUVD_MC_DJPEG_RD_SPACE 0x0006
+#define regUVD_MC_DJPEG_RD_SPACE_BASE_IDX 1
+#define regUVD_MC_DJPEG_WR_SPACE 0x0007
+#define regUVD_MC_DJPEG_WR_SPACE_BASE_IDX 1
+#define regUVD_MC_EJPEG_RD_SPACE 0x0008
+#define regUVD_MC_EJPEG_RD_SPACE_BASE_IDX 1
+#define regUVD_MC_EJPEG_WR_SPACE 0x0009
+#define regUVD_MC_EJPEG_WR_SPACE_BASE_IDX 1
+#define regUVD_PG_IND_INDEX 0x000c
+#define regUVD_PG_IND_INDEX_BASE_IDX 1
+#define regUVD_PG_IND_DATA 0x000e
+#define regUVD_PG_IND_DATA_BASE_IDX 1
+#define regCC_UVD_HARVESTING 0x000f
+#define regCC_UVD_HARVESTING_BASE_IDX 1
+#define regUVD_DPG_LMA_CTL 0x0011
+#define regUVD_DPG_LMA_CTL_BASE_IDX 1
+#define regUVD_DPG_LMA_DATA 0x0012
+#define regUVD_DPG_LMA_DATA_BASE_IDX 1
+#define regUVD_DPG_LMA_MASK 0x0013
+#define regUVD_DPG_LMA_MASK_BASE_IDX 1
+#define regUVD_DPG_PAUSE 0x0014
+#define regUVD_DPG_PAUSE_BASE_IDX 1
+#define regUVD_SCRATCH1 0x0015
+#define regUVD_SCRATCH1_BASE_IDX 1
+#define regUVD_SCRATCH2 0x0016
+#define regUVD_SCRATCH2_BASE_IDX 1
+#define regUVD_SCRATCH3 0x0017
+#define regUVD_SCRATCH3_BASE_IDX 1
+#define regUVD_SCRATCH4 0x0018
+#define regUVD_SCRATCH4_BASE_IDX 1
+#define regUVD_SCRATCH5 0x0019
+#define regUVD_SCRATCH5_BASE_IDX 1
+#define regUVD_SCRATCH6 0x001a
+#define regUVD_SCRATCH6_BASE_IDX 1
+#define regUVD_SCRATCH7 0x001b
+#define regUVD_SCRATCH7_BASE_IDX 1
+#define regUVD_SCRATCH8 0x001c
+#define regUVD_SCRATCH8_BASE_IDX 1
+#define regUVD_SCRATCH9 0x001d
+#define regUVD_SCRATCH9_BASE_IDX 1
+#define regUVD_SCRATCH10 0x001e
+#define regUVD_SCRATCH10_BASE_IDX 1
+#define regUVD_SCRATCH11 0x001f
+#define regUVD_SCRATCH11_BASE_IDX 1
+#define regUVD_SCRATCH12 0x0020
+#define regUVD_SCRATCH12_BASE_IDX 1
+#define regUVD_SCRATCH13 0x0021
+#define regUVD_SCRATCH13_BASE_IDX 1
+#define regUVD_SCRATCH14 0x0022
+#define regUVD_SCRATCH14_BASE_IDX 1
+#define regUVD_FREE_COUNTER_REG 0x0023
+#define regUVD_FREE_COUNTER_REG_BASE_IDX 1
+#define regUVD_DPG_LMI_VCPU_CACHE_64BIT_BAR_LOW 0x0024
+#define regUVD_DPG_LMI_VCPU_CACHE_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_DPG_LMI_VCPU_CACHE_64BIT_BAR_HIGH 0x0025
+#define regUVD_DPG_LMI_VCPU_CACHE_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_DPG_VCPU_CACHE_OFFSET0 0x0026
+#define regUVD_DPG_VCPU_CACHE_OFFSET0_BASE_IDX 1
+#define regUVD_DPG_LMI_VCPU_CACHE_VMID 0x0027
+#define regUVD_DPG_LMI_VCPU_CACHE_VMID_BASE_IDX 1
+#define regUVD_REG_FILTER_EN 0x0028
+#define regUVD_REG_FILTER_EN_BASE_IDX 1
+#define regUVD_SECURITY_REG_VIO_REPORT 0x0029
+#define regUVD_SECURITY_REG_VIO_REPORT_BASE_IDX 1
+#define regUVD_FW_VERSION 0x002a
+#define regUVD_FW_VERSION_BASE_IDX 1
+#define regUVD_PF_STATUS 0x002c
+#define regUVD_PF_STATUS_BASE_IDX 1
+#define regUVD_DPG_CLK_EN_VCPU_REPORT 0x002e
+#define regUVD_DPG_CLK_EN_VCPU_REPORT_BASE_IDX 1
+#define regCC_UVD_VCPU_ERR_DETECT_BOT_LO 0x002f
+#define regCC_UVD_VCPU_ERR_DETECT_BOT_LO_BASE_IDX 1
+#define regCC_UVD_VCPU_ERR_DETECT_BOT_HI 0x0030
+#define regCC_UVD_VCPU_ERR_DETECT_BOT_HI_BASE_IDX 1
+#define regCC_UVD_VCPU_ERR_DETECT_TOP_LO 0x0031
+#define regCC_UVD_VCPU_ERR_DETECT_TOP_LO_BASE_IDX 1
+#define regCC_UVD_VCPU_ERR_DETECT_TOP_HI 0x0032
+#define regCC_UVD_VCPU_ERR_DETECT_TOP_HI_BASE_IDX 1
+#define regCC_UVD_VCPU_ERR 0x0033
+#define regCC_UVD_VCPU_ERR_BASE_IDX 1
+#define regCC_UVD_VCPU_ERR_INST_ADDR_LO 0x0034
+#define regCC_UVD_VCPU_ERR_INST_ADDR_LO_BASE_IDX 1
+#define regCC_UVD_VCPU_ERR_INST_ADDR_HI 0x0035
+#define regCC_UVD_VCPU_ERR_INST_ADDR_HI_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC_SPACE 0x003d
+#define regUVD_LMI_MMSCH_NC_SPACE_BASE_IDX 1
+#define regUVD_LMI_ATOMIC_SPACE 0x003e
+#define regUVD_LMI_ATOMIC_SPACE_BASE_IDX 1
+#define regUVD_GFX8_ADDR_CONFIG 0x0041
+#define regUVD_GFX8_ADDR_CONFIG_BASE_IDX 1
+#define regUVD_GFX10_ADDR_CONFIG 0x0042
+#define regUVD_GFX10_ADDR_CONFIG_BASE_IDX 1
+#define regUVD_GPCNT2_CNTL 0x0043
+#define regUVD_GPCNT2_CNTL_BASE_IDX 1
+#define regUVD_GPCNT2_TARGET_LOWER 0x0044
+#define regUVD_GPCNT2_TARGET_LOWER_BASE_IDX 1
+#define regUVD_GPCNT2_STATUS_LOWER 0x0045
+#define regUVD_GPCNT2_STATUS_LOWER_BASE_IDX 1
+#define regUVD_GPCNT2_TARGET_UPPER 0x0046
+#define regUVD_GPCNT2_TARGET_UPPER_BASE_IDX 1
+#define regUVD_GPCNT2_STATUS_UPPER 0x0047
+#define regUVD_GPCNT2_STATUS_UPPER_BASE_IDX 1
+#define regUVD_GPCNT3_CNTL 0x0048
+#define regUVD_GPCNT3_CNTL_BASE_IDX 1
+#define regUVD_GPCNT3_TARGET_LOWER 0x0049
+#define regUVD_GPCNT3_TARGET_LOWER_BASE_IDX 1
+#define regUVD_GPCNT3_STATUS_LOWER 0x004a
+#define regUVD_GPCNT3_STATUS_LOWER_BASE_IDX 1
+#define regUVD_GPCNT3_TARGET_UPPER 0x004b
+#define regUVD_GPCNT3_TARGET_UPPER_BASE_IDX 1
+#define regUVD_GPCNT3_STATUS_UPPER 0x004c
+#define regUVD_GPCNT3_STATUS_UPPER_BASE_IDX 1
+#define regUVD_VCLK_DS_CNTL 0x004d
+#define regUVD_VCLK_DS_CNTL_BASE_IDX 1
+#define regUVD_DCLK_DS_CNTL 0x004e
+#define regUVD_DCLK_DS_CNTL_BASE_IDX 1
+#define regUVD_TSC_LOWER 0x004f
+#define regUVD_TSC_LOWER_BASE_IDX 1
+#define regUVD_TSC_UPPER 0x0050
+#define regUVD_TSC_UPPER_BASE_IDX 1
+#define regVCN_FEATURES 0x0051
+#define regVCN_FEATURES_BASE_IDX 1
+#define regUVD_GPUIOV_STATUS 0x0055
+#define regUVD_GPUIOV_STATUS_BASE_IDX 1
+#define regUVD_RAS_VCPU_VCODEC_STATUS 0x0057
+#define regUVD_RAS_VCPU_VCODEC_STATUS_BASE_IDX 1
+#define regUVD_RAS_MMSCH_FATAL_ERROR 0x0058
+#define regUVD_RAS_MMSCH_FATAL_ERROR_BASE_IDX 1
+#define regUVD_RAS_JPEG0_STATUS 0x0059
+#define regUVD_RAS_JPEG0_STATUS_BASE_IDX 1
+#define regUVD_RAS_JPEG1_STATUS 0x005a
+#define regUVD_RAS_JPEG1_STATUS_BASE_IDX 1
+#define regUVD_RAS_CNTL_PMI_ARB 0x005b
+#define regUVD_RAS_CNTL_PMI_ARB_BASE_IDX 1
+#define regUVD_SCRATCH15 0x005c
+#define regUVD_SCRATCH15_BASE_IDX 1
+#define regVCN_JPEG_DB_CTRL1 0x005d
+#define regVCN_JPEG_DB_CTRL1_BASE_IDX 1
+#define regVCN_JPEG_DB_CTRL2 0x005e
+#define regVCN_JPEG_DB_CTRL2_BASE_IDX 1
+#define regVCN_JPEG_DB_CTRL3 0x005f
+#define regVCN_JPEG_DB_CTRL3_BASE_IDX 1
+#define regVCN_JPEG_DB_CTRL4 0x0060
+#define regVCN_JPEG_DB_CTRL4_BASE_IDX 1
+#define regVCN_JPEG_DB_CTRL5 0x0061
+#define regVCN_JPEG_DB_CTRL5_BASE_IDX 1
+#define regVCN_JPEG_DB_CTRL6 0x0062
+#define regVCN_JPEG_DB_CTRL6_BASE_IDX 1
+#define regVCN_JPEG_DB_CTRL7 0x0063
+#define regVCN_JPEG_DB_CTRL7_BASE_IDX 1
+#define regUVD_SCRATCH32 0x006d
+#define regUVD_SCRATCH32_BASE_IDX 1
+#define regUVD_VERSION 0x006e
+#define regUVD_VERSION_BASE_IDX 1
+#define regVCN_RB_DB_CTRL 0x0070
+#define regVCN_RB_DB_CTRL_BASE_IDX 1
+#define regVCN_JPEG_DB_CTRL 0x0071
+#define regVCN_JPEG_DB_CTRL_BASE_IDX 1
+#define regVCN_RB1_DB_CTRL 0x0072
+#define regVCN_RB1_DB_CTRL_BASE_IDX 1
+#define regVCN_RB2_DB_CTRL 0x0073
+#define regVCN_RB2_DB_CTRL_BASE_IDX 1
+#define regVCN_RB3_DB_CTRL 0x0074
+#define regVCN_RB3_DB_CTRL_BASE_IDX 1
+#define regVCN_RB4_DB_CTRL 0x0075
+#define regVCN_RB4_DB_CTRL_BASE_IDX 1
+#define regVCN_RB_ENABLE 0x0085
+#define regVCN_RB_ENABLE_BASE_IDX 1
+#define regVCN_RB_WPTR_CTRL 0x0086
+#define regVCN_RB_WPTR_CTRL_BASE_IDX 1
+#define regUVD_RB_RPTR 0x00ac
+#define regUVD_RB_RPTR_BASE_IDX 1
+#define regUVD_RB_WPTR 0x00ad
+#define regUVD_RB_WPTR_BASE_IDX 1
+#define regUVD_RB_RPTR2 0x00ae
+#define regUVD_RB_RPTR2_BASE_IDX 1
+#define regUVD_RB_WPTR2 0x00af
+#define regUVD_RB_WPTR2_BASE_IDX 1
+#define regUVD_RB_RPTR3 0x00b0
+#define regUVD_RB_RPTR3_BASE_IDX 1
+#define regUVD_RB_WPTR3 0x00b1
+#define regUVD_RB_WPTR3_BASE_IDX 1
+#define regUVD_RB_RPTR4 0x00b2
+#define regUVD_RB_RPTR4_BASE_IDX 1
+#define regUVD_RB_WPTR4 0x00b3
+#define regUVD_RB_WPTR4_BASE_IDX 1
+#define regUVD_OUT_RB_RPTR 0x00b4
+#define regUVD_OUT_RB_RPTR_BASE_IDX 1
+#define regUVD_OUT_RB_WPTR 0x00b5
+#define regUVD_OUT_RB_WPTR_BASE_IDX 1
+#define regUVD_AUDIO_RB_RPTR 0x00b6
+#define regUVD_AUDIO_RB_RPTR_BASE_IDX 1
+#define regUVD_AUDIO_RB_WPTR 0x00b7
+#define regUVD_AUDIO_RB_WPTR_BASE_IDX 1
+#define regUVD_RBC_RB_RPTR 0x00b8
+#define regUVD_RBC_RB_RPTR_BASE_IDX 1
+#define regUVD_RBC_RB_WPTR 0x00b9
+#define regUVD_RBC_RB_WPTR_BASE_IDX 1
+#define regUVD_DPG_LMA_CTL2 0x00bb
+#define regUVD_DPG_LMA_CTL2_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_mmsch_dec
+// base address: 0x20d00
+#define regMMSCH_UCODE_ADDR 0x0540
+#define regMMSCH_UCODE_ADDR_BASE_IDX 1
+#define regMMSCH_UCODE_DATA 0x0541
+#define regMMSCH_UCODE_DATA_BASE_IDX 1
+#define regMMSCH_SRAM_ADDR 0x0542
+#define regMMSCH_SRAM_ADDR_BASE_IDX 1
+#define regMMSCH_SRAM_DATA 0x0543
+#define regMMSCH_SRAM_DATA_BASE_IDX 1
+#define regMMSCH_VF_SRAM_OFFSET 0x0544
+#define regMMSCH_VF_SRAM_OFFSET_BASE_IDX 1
+#define regMMSCH_DB_SRAM_OFFSET 0x0545
+#define regMMSCH_DB_SRAM_OFFSET_BASE_IDX 1
+#define regMMSCH_CTX_SRAM_OFFSET 0x0546
+#define regMMSCH_CTX_SRAM_OFFSET_BASE_IDX 1
+#define regMMSCH_CTL 0x0547
+#define regMMSCH_CTL_BASE_IDX 1
+#define regMMSCH_INTR 0x0548
+#define regMMSCH_INTR_BASE_IDX 1
+#define regMMSCH_INTR_ACK 0x0549
+#define regMMSCH_INTR_ACK_BASE_IDX 1
+#define regMMSCH_INTR_STATUS 0x054a
+#define regMMSCH_INTR_STATUS_BASE_IDX 1
+#define regMMSCH_VF_VMID 0x054b
+#define regMMSCH_VF_VMID_BASE_IDX 1
+#define regMMSCH_VF_CTX_ADDR_LO 0x054c
+#define regMMSCH_VF_CTX_ADDR_LO_BASE_IDX 1
+#define regMMSCH_VF_CTX_ADDR_HI 0x054d
+#define regMMSCH_VF_CTX_ADDR_HI_BASE_IDX 1
+#define regMMSCH_VF_CTX_SIZE 0x054e
+#define regMMSCH_VF_CTX_SIZE_BASE_IDX 1
+#define regMMSCH_VF_GPCOM_ADDR_LO 0x054f
+#define regMMSCH_VF_GPCOM_ADDR_LO_BASE_IDX 1
+#define regMMSCH_VF_GPCOM_ADDR_HI 0x0550
+#define regMMSCH_VF_GPCOM_ADDR_HI_BASE_IDX 1
+#define regMMSCH_VF_GPCOM_SIZE 0x0551
+#define regMMSCH_VF_GPCOM_SIZE_BASE_IDX 1
+#define regMMSCH_VF_MAILBOX_HOST 0x0552
+#define regMMSCH_VF_MAILBOX_HOST_BASE_IDX 1
+#define regMMSCH_VF_MAILBOX_RESP 0x0553
+#define regMMSCH_VF_MAILBOX_RESP_BASE_IDX 1
+#define regMMSCH_VF_MAILBOX_0 0x0554
+#define regMMSCH_VF_MAILBOX_0_BASE_IDX 1
+#define regMMSCH_VF_MAILBOX_0_RESP 0x0555
+#define regMMSCH_VF_MAILBOX_0_RESP_BASE_IDX 1
+#define regMMSCH_VF_MAILBOX_1 0x0556
+#define regMMSCH_VF_MAILBOX_1_BASE_IDX 1
+#define regMMSCH_VF_MAILBOX_1_RESP 0x0557
+#define regMMSCH_VF_MAILBOX_1_RESP_BASE_IDX 1
+#define regMMSCH_CNTL 0x055c
+#define regMMSCH_CNTL_BASE_IDX 1
+#define regMMSCH_NONCACHE_OFFSET0 0x055d
+#define regMMSCH_NONCACHE_OFFSET0_BASE_IDX 1
+#define regMMSCH_NONCACHE_SIZE0 0x055e
+#define regMMSCH_NONCACHE_SIZE0_BASE_IDX 1
+#define regMMSCH_NONCACHE_OFFSET1 0x055f
+#define regMMSCH_NONCACHE_OFFSET1_BASE_IDX 1
+#define regMMSCH_NONCACHE_SIZE1 0x0560
+#define regMMSCH_NONCACHE_SIZE1_BASE_IDX 1
+#define regMMSCH_PROC_STATE1 0x0566
+#define regMMSCH_PROC_STATE1_BASE_IDX 1
+#define regMMSCH_LAST_MC_ADDR 0x0567
+#define regMMSCH_LAST_MC_ADDR_BASE_IDX 1
+#define regMMSCH_LAST_MEM_ACCESS_HI 0x0568
+#define regMMSCH_LAST_MEM_ACCESS_HI_BASE_IDX 1
+#define regMMSCH_LAST_MEM_ACCESS_LO 0x0569
+#define regMMSCH_LAST_MEM_ACCESS_LO_BASE_IDX 1
+#define regMMSCH_IOV_ACTIVE_FCN_ID 0x056a
+#define regMMSCH_IOV_ACTIVE_FCN_ID_BASE_IDX 1
+#define regMMSCH_SCRATCH_0 0x056b
+#define regMMSCH_SCRATCH_0_BASE_IDX 1
+#define regMMSCH_SCRATCH_1 0x056c
+#define regMMSCH_SCRATCH_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_SCH_BLOCK_0 0x056d
+#define regMMSCH_GPUIOV_SCH_BLOCK_0_BASE_IDX 1
+#define regMMSCH_GPUIOV_CMD_CONTROL_0 0x056e
+#define regMMSCH_GPUIOV_CMD_CONTROL_0_BASE_IDX 1
+#define regMMSCH_GPUIOV_CMD_STATUS_0 0x056f
+#define regMMSCH_GPUIOV_CMD_STATUS_0_BASE_IDX 1
+#define regMMSCH_GPUIOV_VM_BUSY_STATUS_0 0x0570
+#define regMMSCH_GPUIOV_VM_BUSY_STATUS_0_BASE_IDX 1
+#define regMMSCH_GPUIOV_ACTIVE_FCNS_0 0x0571
+#define regMMSCH_GPUIOV_ACTIVE_FCNS_0_BASE_IDX 1
+#define regMMSCH_GPUIOV_ACTIVE_FCN_ID_0 0x0572
+#define regMMSCH_GPUIOV_ACTIVE_FCN_ID_0_BASE_IDX 1
+#define regMMSCH_GPUIOV_DW6_0 0x0573
+#define regMMSCH_GPUIOV_DW6_0_BASE_IDX 1
+#define regMMSCH_GPUIOV_DW7_0 0x0574
+#define regMMSCH_GPUIOV_DW7_0_BASE_IDX 1
+#define regMMSCH_GPUIOV_DW8_0 0x0575
+#define regMMSCH_GPUIOV_DW8_0_BASE_IDX 1
+#define regMMSCH_GPUIOV_SCH_BLOCK_1 0x0576
+#define regMMSCH_GPUIOV_SCH_BLOCK_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_CMD_CONTROL_1 0x0577
+#define regMMSCH_GPUIOV_CMD_CONTROL_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_CMD_STATUS_1 0x0578
+#define regMMSCH_GPUIOV_CMD_STATUS_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_VM_BUSY_STATUS_1 0x0579
+#define regMMSCH_GPUIOV_VM_BUSY_STATUS_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_ACTIVE_FCNS_1 0x057a
+#define regMMSCH_GPUIOV_ACTIVE_FCNS_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_ACTIVE_FCN_ID_1 0x057b
+#define regMMSCH_GPUIOV_ACTIVE_FCN_ID_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_DW6_1 0x057c
+#define regMMSCH_GPUIOV_DW6_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_DW7_1 0x057d
+#define regMMSCH_GPUIOV_DW7_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_DW8_1 0x057e
+#define regMMSCH_GPUIOV_DW8_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_CNTXT 0x057f
+#define regMMSCH_GPUIOV_CNTXT_BASE_IDX 1
+#define regMMSCH_SCRATCH_2 0x0580
+#define regMMSCH_SCRATCH_2_BASE_IDX 1
+#define regMMSCH_SCRATCH_3 0x0581
+#define regMMSCH_SCRATCH_3_BASE_IDX 1
+#define regMMSCH_SCRATCH_4 0x0582
+#define regMMSCH_SCRATCH_4_BASE_IDX 1
+#define regMMSCH_SCRATCH_5 0x0583
+#define regMMSCH_SCRATCH_5_BASE_IDX 1
+#define regMMSCH_SCRATCH_6 0x0584
+#define regMMSCH_SCRATCH_6_BASE_IDX 1
+#define regMMSCH_SCRATCH_7 0x0585
+#define regMMSCH_SCRATCH_7_BASE_IDX 1
+#define regMMSCH_VFID_FIFO_HEAD_0 0x0586
+#define regMMSCH_VFID_FIFO_HEAD_0_BASE_IDX 1
+#define regMMSCH_VFID_FIFO_TAIL_0 0x0587
+#define regMMSCH_VFID_FIFO_TAIL_0_BASE_IDX 1
+#define regMMSCH_VFID_FIFO_HEAD_1 0x0588
+#define regMMSCH_VFID_FIFO_HEAD_1_BASE_IDX 1
+#define regMMSCH_VFID_FIFO_TAIL_1 0x0589
+#define regMMSCH_VFID_FIFO_TAIL_1_BASE_IDX 1
+#define regMMSCH_NACK_STATUS 0x058a
+#define regMMSCH_NACK_STATUS_BASE_IDX 1
+#define regMMSCH_VF_MAILBOX0_DATA 0x058b
+#define regMMSCH_VF_MAILBOX0_DATA_BASE_IDX 1
+#define regMMSCH_VF_MAILBOX1_DATA 0x058c
+#define regMMSCH_VF_MAILBOX1_DATA_BASE_IDX 1
+#define regMMSCH_GPUIOV_SCH_BLOCK_IP_0 0x058d
+#define regMMSCH_GPUIOV_SCH_BLOCK_IP_0_BASE_IDX 1
+#define regMMSCH_GPUIOV_CMD_STATUS_IP_0 0x058e
+#define regMMSCH_GPUIOV_CMD_STATUS_IP_0_BASE_IDX 1
+#define regMMSCH_GPUIOV_ACTIVE_FCN_ID_IP_0 0x058f
+#define regMMSCH_GPUIOV_ACTIVE_FCN_ID_IP_0_BASE_IDX 1
+#define regMMSCH_GPUIOV_SCH_BLOCK_IP_1 0x0590
+#define regMMSCH_GPUIOV_SCH_BLOCK_IP_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_CMD_STATUS_IP_1 0x0591
+#define regMMSCH_GPUIOV_CMD_STATUS_IP_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_ACTIVE_FCN_ID_IP_1 0x0592
+#define regMMSCH_GPUIOV_ACTIVE_FCN_ID_IP_1_BASE_IDX 1
+#define regMMSCH_GPUIOV_CNTXT_IP 0x0593
+#define regMMSCH_GPUIOV_CNTXT_IP_BASE_IDX 1
+#define regMMSCH_GPUIOV_SCH_BLOCK_2 0x0594
+#define regMMSCH_GPUIOV_SCH_BLOCK_2_BASE_IDX 1
+#define regMMSCH_GPUIOV_CMD_CONTROL_2 0x0595
+#define regMMSCH_GPUIOV_CMD_CONTROL_2_BASE_IDX 1
+#define regMMSCH_GPUIOV_CMD_STATUS_2 0x0596
+#define regMMSCH_GPUIOV_CMD_STATUS_2_BASE_IDX 1
+#define regMMSCH_GPUIOV_VM_BUSY_STATUS_2 0x0597
+#define regMMSCH_GPUIOV_VM_BUSY_STATUS_2_BASE_IDX 1
+#define regMMSCH_GPUIOV_ACTIVE_FCNS_2 0x0598
+#define regMMSCH_GPUIOV_ACTIVE_FCNS_2_BASE_IDX 1
+#define regMMSCH_GPUIOV_ACTIVE_FCN_ID_2 0x0599
+#define regMMSCH_GPUIOV_ACTIVE_FCN_ID_2_BASE_IDX 1
+#define regMMSCH_GPUIOV_DW6_2 0x059a
+#define regMMSCH_GPUIOV_DW6_2_BASE_IDX 1
+#define regMMSCH_GPUIOV_DW7_2 0x059b
+#define regMMSCH_GPUIOV_DW7_2_BASE_IDX 1
+#define regMMSCH_GPUIOV_DW8_2 0x059c
+#define regMMSCH_GPUIOV_DW8_2_BASE_IDX 1
+#define regMMSCH_GPUIOV_SCH_BLOCK_IP_2 0x059d
+#define regMMSCH_GPUIOV_SCH_BLOCK_IP_2_BASE_IDX 1
+#define regMMSCH_GPUIOV_CMD_STATUS_IP_2 0x059e
+#define regMMSCH_GPUIOV_CMD_STATUS_IP_2_BASE_IDX 1
+#define regMMSCH_GPUIOV_ACTIVE_FCN_ID_IP_2 0x059f
+#define regMMSCH_GPUIOV_ACTIVE_FCN_ID_IP_2_BASE_IDX 1
+#define regMMSCH_VFID_FIFO_HEAD_2 0x05a0
+#define regMMSCH_VFID_FIFO_HEAD_2_BASE_IDX 1
+#define regMMSCH_VFID_FIFO_TAIL_2 0x05a1
+#define regMMSCH_VFID_FIFO_TAIL_2_BASE_IDX 1
+#define regMMSCH_VM_BUSY_STATUS_0 0x05a2
+#define regMMSCH_VM_BUSY_STATUS_0_BASE_IDX 1
+#define regMMSCH_VM_BUSY_STATUS_1 0x05a3
+#define regMMSCH_VM_BUSY_STATUS_1_BASE_IDX 1
+#define regMMSCH_VM_BUSY_STATUS_2 0x05a4
+#define regMMSCH_VM_BUSY_STATUS_2_BASE_IDX 1
+
+
+// addressBlock: aid_uvd0_slmi_adpdec
+// base address: 0x21c00
+#define regUVD_LMI_MMSCH_NC0_64BIT_BAR_LOW 0x0900
+#define regUVD_LMI_MMSCH_NC0_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC0_64BIT_BAR_HIGH 0x0901
+#define regUVD_LMI_MMSCH_NC0_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC1_64BIT_BAR_LOW 0x0902
+#define regUVD_LMI_MMSCH_NC1_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC1_64BIT_BAR_HIGH 0x0903
+#define regUVD_LMI_MMSCH_NC1_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC2_64BIT_BAR_LOW 0x0904
+#define regUVD_LMI_MMSCH_NC2_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC2_64BIT_BAR_HIGH 0x0905
+#define regUVD_LMI_MMSCH_NC2_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC3_64BIT_BAR_LOW 0x0906
+#define regUVD_LMI_MMSCH_NC3_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC3_64BIT_BAR_HIGH 0x0907
+#define regUVD_LMI_MMSCH_NC3_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC4_64BIT_BAR_LOW 0x0908
+#define regUVD_LMI_MMSCH_NC4_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC4_64BIT_BAR_HIGH 0x0909
+#define regUVD_LMI_MMSCH_NC4_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC5_64BIT_BAR_LOW 0x090a
+#define regUVD_LMI_MMSCH_NC5_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC5_64BIT_BAR_HIGH 0x090b
+#define regUVD_LMI_MMSCH_NC5_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC6_64BIT_BAR_LOW 0x090c
+#define regUVD_LMI_MMSCH_NC6_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC6_64BIT_BAR_HIGH 0x090d
+#define regUVD_LMI_MMSCH_NC6_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC7_64BIT_BAR_LOW 0x090e
+#define regUVD_LMI_MMSCH_NC7_64BIT_BAR_LOW_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC7_64BIT_BAR_HIGH 0x090f
+#define regUVD_LMI_MMSCH_NC7_64BIT_BAR_HIGH_BASE_IDX 1
+#define regUVD_LMI_MMSCH_NC_VMID 0x0910
+#define regUVD_LMI_MMSCH_NC_VMID_BASE_IDX 1
+#define regUVD_LMI_MMSCH_CTRL 0x0911
+#define regUVD_LMI_MMSCH_CTRL_BASE_IDX 1
+#define regUVD_MMSCH_LMI_STATUS 0x0912
+#define regUVD_MMSCH_LMI_STATUS_BASE_IDX 1
+#define regVCN_RAS_CNTL_MMSCH 0x0914
+#define regVCN_RAS_CNTL_MMSCH_BASE_IDX 1
+
+// addressBlock: aid_uvd0_vcn_edcc_dec
+// base address: 0x21d20
+#define regVCN_UE_ERR_STATUS_LO_VIDD 0x094c
+#define regVCN_UE_ERR_STATUS_LO_VIDD_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_VIDD 0x094d
+#define regVCN_UE_ERR_STATUS_HI_VIDD_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_VIDV 0x094e
+#define regVCN_UE_ERR_STATUS_LO_VIDV_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_VIDV 0x094f
+#define regVCN_UE_ERR_STATUS_HI_VIDV_BASE_IDX 1
+#define regVCN_CE_ERR_STATUS_LO_MMSCHD 0x0950
+#define regVCN_CE_ERR_STATUS_LO_MMSCHD_BASE_IDX 1
+#define regVCN_CE_ERR_STATUS_HI_MMSCHD 0x0951
+#define regVCN_CE_ERR_STATUS_HI_MMSCHD_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG0S 0x0952
+#define regVCN_UE_ERR_STATUS_LO_JPEG0S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG0S 0x0953
+#define regVCN_UE_ERR_STATUS_HI_JPEG0S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG0D 0x0954
+#define regVCN_UE_ERR_STATUS_LO_JPEG0D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG0D 0x0955
+#define regVCN_UE_ERR_STATUS_HI_JPEG0D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG1S 0x0956
+#define regVCN_UE_ERR_STATUS_LO_JPEG1S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG1S 0x0957
+#define regVCN_UE_ERR_STATUS_HI_JPEG1S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG1D 0x0958
+#define regVCN_UE_ERR_STATUS_LO_JPEG1D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG1D 0x0959
+#define regVCN_UE_ERR_STATUS_HI_JPEG1D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG2S 0x095a
+#define regVCN_UE_ERR_STATUS_LO_JPEG2S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG2S 0x095b
+#define regVCN_UE_ERR_STATUS_HI_JPEG2S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG2D 0x095c
+#define regVCN_UE_ERR_STATUS_LO_JPEG2D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG2D 0x095d
+#define regVCN_UE_ERR_STATUS_HI_JPEG2D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG3S 0x095e
+#define regVCN_UE_ERR_STATUS_LO_JPEG3S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG3S 0x095f
+#define regVCN_UE_ERR_STATUS_HI_JPEG3S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG3D 0x0960
+#define regVCN_UE_ERR_STATUS_LO_JPEG3D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG3D 0x0961
+#define regVCN_UE_ERR_STATUS_HI_JPEG3D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG4S 0x0962
+#define regVCN_UE_ERR_STATUS_LO_JPEG4S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG4S 0x0963
+#define regVCN_UE_ERR_STATUS_HI_JPEG4S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG4D 0x0964
+#define regVCN_UE_ERR_STATUS_LO_JPEG4D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG4D 0x0965
+#define regVCN_UE_ERR_STATUS_HI_JPEG4D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG5S 0x0966
+#define regVCN_UE_ERR_STATUS_LO_JPEG5S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG5S 0x0967
+#define regVCN_UE_ERR_STATUS_HI_JPEG5S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG5D 0x0968
+#define regVCN_UE_ERR_STATUS_LO_JPEG5D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG5D 0x0969
+#define regVCN_UE_ERR_STATUS_HI_JPEG5D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG6S 0x096a
+#define regVCN_UE_ERR_STATUS_LO_JPEG6S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG6S 0x096b
+#define regVCN_UE_ERR_STATUS_HI_JPEG6S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG6D 0x096c
+#define regVCN_UE_ERR_STATUS_LO_JPEG6D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG6D 0x096d
+#define regVCN_UE_ERR_STATUS_HI_JPEG6D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG7S 0x096e
+#define regVCN_UE_ERR_STATUS_LO_JPEG7S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG7S 0x096f
+#define regVCN_UE_ERR_STATUS_HI_JPEG7S_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_LO_JPEG7D 0x0970
+#define regVCN_UE_ERR_STATUS_LO_JPEG7D_BASE_IDX 1
+#define regVCN_UE_ERR_STATUS_HI_JPEG7D 0x0971
+#define regVCN_UE_ERR_STATUS_HI_JPEG7D_BASE_IDX 1
+
+// addressBlock: aid_uvd0_uvd_jrbc1_uvd_jrbc_dec
+// base address: 0x1e000
+#define regUVD_JRBC1_UVD_JRBC_RB_WPTR 0x0000
+#define regUVD_JRBC1_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_RB_CNTL 0x0001
+#define regUVD_JRBC1_UVD_JRBC_RB_CNTL_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_IB_SIZE 0x0002
+#define regUVD_JRBC1_UVD_JRBC_IB_SIZE_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_URGENT_CNTL 0x0003
+#define regUVD_JRBC1_UVD_JRBC_URGENT_CNTL_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_RB_REF_DATA 0x0004
+#define regUVD_JRBC1_UVD_JRBC_RB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_RB_COND_RD_TIMER 0x0005
+#define regUVD_JRBC1_UVD_JRBC_RB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_SOFT_RESET 0x0008
+#define regUVD_JRBC1_UVD_JRBC_SOFT_RESET_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_STATUS 0x0009
+#define regUVD_JRBC1_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_RB_RPTR 0x000a
+#define regUVD_JRBC1_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_RB_BUF_STATUS 0x000b
+#define regUVD_JRBC1_UVD_JRBC_RB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_IB_BUF_STATUS 0x000c
+#define regUVD_JRBC1_UVD_JRBC_IB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_IB_SIZE_UPDATE 0x000d
+#define regUVD_JRBC1_UVD_JRBC_IB_SIZE_UPDATE_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_IB_COND_RD_TIMER 0x000e
+#define regUVD_JRBC1_UVD_JRBC_IB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_IB_REF_DATA 0x000f
+#define regUVD_JRBC1_UVD_JRBC_IB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JPEG_PREEMPT_CMD 0x0010
+#define regUVD_JRBC1_UVD_JPEG_PREEMPT_CMD_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JPEG_PREEMPT_FENCE_DATA0 0x0011
+#define regUVD_JRBC1_UVD_JPEG_PREEMPT_FENCE_DATA0_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JPEG_PREEMPT_FENCE_DATA1 0x0012
+#define regUVD_JRBC1_UVD_JPEG_PREEMPT_FENCE_DATA1_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_RB_SIZE 0x0013
+#define regUVD_JRBC1_UVD_JRBC_RB_SIZE_BASE_IDX 0
+#define regUVD_JRBC1_UVD_JRBC_SCRATCH0 0x0014
+#define regUVD_JRBC1_UVD_JRBC_SCRATCH0_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jrbc2_uvd_jrbc_dec
+// base address: 0x1e100
+#define regUVD_JRBC2_UVD_JRBC_RB_WPTR 0x0040
+#define regUVD_JRBC2_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_RB_CNTL 0x0041
+#define regUVD_JRBC2_UVD_JRBC_RB_CNTL_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_IB_SIZE 0x0042
+#define regUVD_JRBC2_UVD_JRBC_IB_SIZE_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_URGENT_CNTL 0x0043
+#define regUVD_JRBC2_UVD_JRBC_URGENT_CNTL_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_RB_REF_DATA 0x0044
+#define regUVD_JRBC2_UVD_JRBC_RB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_RB_COND_RD_TIMER 0x0045
+#define regUVD_JRBC2_UVD_JRBC_RB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_SOFT_RESET 0x0048
+#define regUVD_JRBC2_UVD_JRBC_SOFT_RESET_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_STATUS 0x0049
+#define regUVD_JRBC2_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_RB_RPTR 0x004a
+#define regUVD_JRBC2_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_RB_BUF_STATUS 0x004b
+#define regUVD_JRBC2_UVD_JRBC_RB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_IB_BUF_STATUS 0x004c
+#define regUVD_JRBC2_UVD_JRBC_IB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_IB_SIZE_UPDATE 0x004d
+#define regUVD_JRBC2_UVD_JRBC_IB_SIZE_UPDATE_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_IB_COND_RD_TIMER 0x004e
+#define regUVD_JRBC2_UVD_JRBC_IB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_IB_REF_DATA 0x004f
+#define regUVD_JRBC2_UVD_JRBC_IB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JPEG_PREEMPT_CMD 0x0050
+#define regUVD_JRBC2_UVD_JPEG_PREEMPT_CMD_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JPEG_PREEMPT_FENCE_DATA0 0x0051
+#define regUVD_JRBC2_UVD_JPEG_PREEMPT_FENCE_DATA0_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JPEG_PREEMPT_FENCE_DATA1 0x0052
+#define regUVD_JRBC2_UVD_JPEG_PREEMPT_FENCE_DATA1_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_RB_SIZE 0x0053
+#define regUVD_JRBC2_UVD_JRBC_RB_SIZE_BASE_IDX 0
+#define regUVD_JRBC2_UVD_JRBC_SCRATCH0 0x0054
+#define regUVD_JRBC2_UVD_JRBC_SCRATCH0_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jrbc3_uvd_jrbc_dec
+// base address: 0x1e200
+#define regUVD_JRBC3_UVD_JRBC_RB_WPTR 0x0080
+#define regUVD_JRBC3_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_RB_CNTL 0x0081
+#define regUVD_JRBC3_UVD_JRBC_RB_CNTL_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_IB_SIZE 0x0082
+#define regUVD_JRBC3_UVD_JRBC_IB_SIZE_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_URGENT_CNTL 0x0083
+#define regUVD_JRBC3_UVD_JRBC_URGENT_CNTL_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_RB_REF_DATA 0x0084
+#define regUVD_JRBC3_UVD_JRBC_RB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_RB_COND_RD_TIMER 0x0085
+#define regUVD_JRBC3_UVD_JRBC_RB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_SOFT_RESET 0x0088
+#define regUVD_JRBC3_UVD_JRBC_SOFT_RESET_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_STATUS 0x0089
+#define regUVD_JRBC3_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_RB_RPTR 0x008a
+#define regUVD_JRBC3_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_RB_BUF_STATUS 0x008b
+#define regUVD_JRBC3_UVD_JRBC_RB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_IB_BUF_STATUS 0x008c
+#define regUVD_JRBC3_UVD_JRBC_IB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_IB_SIZE_UPDATE 0x008d
+#define regUVD_JRBC3_UVD_JRBC_IB_SIZE_UPDATE_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_IB_COND_RD_TIMER 0x008e
+#define regUVD_JRBC3_UVD_JRBC_IB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_IB_REF_DATA 0x008f
+#define regUVD_JRBC3_UVD_JRBC_IB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JPEG_PREEMPT_CMD 0x0090
+#define regUVD_JRBC3_UVD_JPEG_PREEMPT_CMD_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JPEG_PREEMPT_FENCE_DATA0 0x0091
+#define regUVD_JRBC3_UVD_JPEG_PREEMPT_FENCE_DATA0_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JPEG_PREEMPT_FENCE_DATA1 0x0092
+#define regUVD_JRBC3_UVD_JPEG_PREEMPT_FENCE_DATA1_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_RB_SIZE 0x0093
+#define regUVD_JRBC3_UVD_JRBC_RB_SIZE_BASE_IDX 0
+#define regUVD_JRBC3_UVD_JRBC_SCRATCH0 0x0094
+#define regUVD_JRBC3_UVD_JRBC_SCRATCH0_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jrbc4_uvd_jrbc_dec
+// base address: 0x1e300
+#define regUVD_JRBC4_UVD_JRBC_RB_WPTR 0x00c0
+#define regUVD_JRBC4_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_RB_CNTL 0x00c1
+#define regUVD_JRBC4_UVD_JRBC_RB_CNTL_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_IB_SIZE 0x00c2
+#define regUVD_JRBC4_UVD_JRBC_IB_SIZE_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_URGENT_CNTL 0x00c3
+#define regUVD_JRBC4_UVD_JRBC_URGENT_CNTL_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_RB_REF_DATA 0x00c4
+#define regUVD_JRBC4_UVD_JRBC_RB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_RB_COND_RD_TIMER 0x00c5
+#define regUVD_JRBC4_UVD_JRBC_RB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_SOFT_RESET 0x00c8
+#define regUVD_JRBC4_UVD_JRBC_SOFT_RESET_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_STATUS 0x00c9
+#define regUVD_JRBC4_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_RB_RPTR 0x00ca
+#define regUVD_JRBC4_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_RB_BUF_STATUS 0x00cb
+#define regUVD_JRBC4_UVD_JRBC_RB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_IB_BUF_STATUS 0x00cc
+#define regUVD_JRBC4_UVD_JRBC_IB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_IB_SIZE_UPDATE 0x00cd
+#define regUVD_JRBC4_UVD_JRBC_IB_SIZE_UPDATE_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_IB_COND_RD_TIMER 0x00ce
+#define regUVD_JRBC4_UVD_JRBC_IB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_IB_REF_DATA 0x00cf
+#define regUVD_JRBC4_UVD_JRBC_IB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JPEG_PREEMPT_CMD 0x00d0
+#define regUVD_JRBC4_UVD_JPEG_PREEMPT_CMD_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JPEG_PREEMPT_FENCE_DATA0 0x00d1
+#define regUVD_JRBC4_UVD_JPEG_PREEMPT_FENCE_DATA0_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JPEG_PREEMPT_FENCE_DATA1 0x00d2
+#define regUVD_JRBC4_UVD_JPEG_PREEMPT_FENCE_DATA1_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_RB_SIZE 0x00d3
+#define regUVD_JRBC4_UVD_JRBC_RB_SIZE_BASE_IDX 0
+#define regUVD_JRBC4_UVD_JRBC_SCRATCH0 0x00d4
+#define regUVD_JRBC4_UVD_JRBC_SCRATCH0_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jrbc5_uvd_jrbc_dec
+// base address: 0x1e400
+#define regUVD_JRBC5_UVD_JRBC_RB_WPTR 0x0100
+#define regUVD_JRBC5_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_RB_CNTL 0x0101
+#define regUVD_JRBC5_UVD_JRBC_RB_CNTL_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_IB_SIZE 0x0102
+#define regUVD_JRBC5_UVD_JRBC_IB_SIZE_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_URGENT_CNTL 0x0103
+#define regUVD_JRBC5_UVD_JRBC_URGENT_CNTL_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_RB_REF_DATA 0x0104
+#define regUVD_JRBC5_UVD_JRBC_RB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_RB_COND_RD_TIMER 0x0105
+#define regUVD_JRBC5_UVD_JRBC_RB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_SOFT_RESET 0x0108
+#define regUVD_JRBC5_UVD_JRBC_SOFT_RESET_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_STATUS 0x0109
+#define regUVD_JRBC5_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_RB_RPTR 0x010a
+#define regUVD_JRBC5_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_RB_BUF_STATUS 0x010b
+#define regUVD_JRBC5_UVD_JRBC_RB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_IB_BUF_STATUS 0x010c
+#define regUVD_JRBC5_UVD_JRBC_IB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_IB_SIZE_UPDATE 0x010d
+#define regUVD_JRBC5_UVD_JRBC_IB_SIZE_UPDATE_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_IB_COND_RD_TIMER 0x010e
+#define regUVD_JRBC5_UVD_JRBC_IB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_IB_REF_DATA 0x010f
+#define regUVD_JRBC5_UVD_JRBC_IB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JPEG_PREEMPT_CMD 0x0110
+#define regUVD_JRBC5_UVD_JPEG_PREEMPT_CMD_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JPEG_PREEMPT_FENCE_DATA0 0x0111
+#define regUVD_JRBC5_UVD_JPEG_PREEMPT_FENCE_DATA0_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JPEG_PREEMPT_FENCE_DATA1 0x0112
+#define regUVD_JRBC5_UVD_JPEG_PREEMPT_FENCE_DATA1_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_RB_SIZE 0x0113
+#define regUVD_JRBC5_UVD_JRBC_RB_SIZE_BASE_IDX 0
+#define regUVD_JRBC5_UVD_JRBC_SCRATCH0 0x0114
+#define regUVD_JRBC5_UVD_JRBC_SCRATCH0_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jrbc6_uvd_jrbc_dec
+// base address: 0x1e500
+#define regUVD_JRBC6_UVD_JRBC_RB_WPTR 0x0140
+#define regUVD_JRBC6_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_RB_CNTL 0x0141
+#define regUVD_JRBC6_UVD_JRBC_RB_CNTL_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_IB_SIZE 0x0142
+#define regUVD_JRBC6_UVD_JRBC_IB_SIZE_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_URGENT_CNTL 0x0143
+#define regUVD_JRBC6_UVD_JRBC_URGENT_CNTL_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_RB_REF_DATA 0x0144
+#define regUVD_JRBC6_UVD_JRBC_RB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_RB_COND_RD_TIMER 0x0145
+#define regUVD_JRBC6_UVD_JRBC_RB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_SOFT_RESET 0x0148
+#define regUVD_JRBC6_UVD_JRBC_SOFT_RESET_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_STATUS 0x0149
+#define regUVD_JRBC6_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_RB_RPTR 0x014a
+#define regUVD_JRBC6_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_RB_BUF_STATUS 0x014b
+#define regUVD_JRBC6_UVD_JRBC_RB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_IB_BUF_STATUS 0x014c
+#define regUVD_JRBC6_UVD_JRBC_IB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_IB_SIZE_UPDATE 0x014d
+#define regUVD_JRBC6_UVD_JRBC_IB_SIZE_UPDATE_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_IB_COND_RD_TIMER 0x014e
+#define regUVD_JRBC6_UVD_JRBC_IB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_IB_REF_DATA 0x014f
+#define regUVD_JRBC6_UVD_JRBC_IB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JPEG_PREEMPT_CMD 0x0150
+#define regUVD_JRBC6_UVD_JPEG_PREEMPT_CMD_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JPEG_PREEMPT_FENCE_DATA0 0x0151
+#define regUVD_JRBC6_UVD_JPEG_PREEMPT_FENCE_DATA0_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JPEG_PREEMPT_FENCE_DATA1 0x0152
+#define regUVD_JRBC6_UVD_JPEG_PREEMPT_FENCE_DATA1_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_RB_SIZE 0x0153
+#define regUVD_JRBC6_UVD_JRBC_RB_SIZE_BASE_IDX 0
+#define regUVD_JRBC6_UVD_JRBC_SCRATCH0 0x0154
+#define regUVD_JRBC6_UVD_JRBC_SCRATCH0_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jrbc7_uvd_jrbc_dec
+// base address: 0x1e600
+#define regUVD_JRBC7_UVD_JRBC_RB_WPTR 0x0180
+#define regUVD_JRBC7_UVD_JRBC_RB_WPTR_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_RB_CNTL 0x0181
+#define regUVD_JRBC7_UVD_JRBC_RB_CNTL_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_IB_SIZE 0x0182
+#define regUVD_JRBC7_UVD_JRBC_IB_SIZE_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_URGENT_CNTL 0x0183
+#define regUVD_JRBC7_UVD_JRBC_URGENT_CNTL_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_RB_REF_DATA 0x0184
+#define regUVD_JRBC7_UVD_JRBC_RB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_RB_COND_RD_TIMER 0x0185
+#define regUVD_JRBC7_UVD_JRBC_RB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_SOFT_RESET 0x0188
+#define regUVD_JRBC7_UVD_JRBC_SOFT_RESET_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_STATUS 0x0189
+#define regUVD_JRBC7_UVD_JRBC_STATUS_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_RB_RPTR 0x018a
+#define regUVD_JRBC7_UVD_JRBC_RB_RPTR_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_RB_BUF_STATUS 0x018b
+#define regUVD_JRBC7_UVD_JRBC_RB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_IB_BUF_STATUS 0x018c
+#define regUVD_JRBC7_UVD_JRBC_IB_BUF_STATUS_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_IB_SIZE_UPDATE 0x018d
+#define regUVD_JRBC7_UVD_JRBC_IB_SIZE_UPDATE_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_IB_COND_RD_TIMER 0x018e
+#define regUVD_JRBC7_UVD_JRBC_IB_COND_RD_TIMER_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_IB_REF_DATA 0x018f
+#define regUVD_JRBC7_UVD_JRBC_IB_REF_DATA_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JPEG_PREEMPT_CMD 0x0190
+#define regUVD_JRBC7_UVD_JPEG_PREEMPT_CMD_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JPEG_PREEMPT_FENCE_DATA0 0x0191
+#define regUVD_JRBC7_UVD_JPEG_PREEMPT_FENCE_DATA0_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JPEG_PREEMPT_FENCE_DATA1 0x0192
+#define regUVD_JRBC7_UVD_JPEG_PREEMPT_FENCE_DATA1_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_RB_SIZE 0x0193
+#define regUVD_JRBC7_UVD_JRBC_RB_SIZE_BASE_IDX 0
+#define regUVD_JRBC7_UVD_JRBC_SCRATCH0 0x0194
+#define regUVD_JRBC7_UVD_JRBC_SCRATCH0_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jmi1_uvd_jmi_dec
+// base address: 0x1e080
+#define regUVD_JMI1_UVD_JPEG_DEC_PF_CTRL 0x0020
+#define regUVD_JMI1_UVD_JPEG_DEC_PF_CTRL_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JRBC_CTRL 0x0021
+#define regUVD_JMI1_UVD_LMI_JRBC_CTRL_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JPEG_CTRL 0x0022
+#define regUVD_JMI1_UVD_LMI_JPEG_CTRL_BASE_IDX 0
+#define regUVD_JMI1_JPEG_LMI_DROP 0x0023
+#define regUVD_JMI1_JPEG_LMI_DROP_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JRBC_IB_VMID 0x0024
+#define regUVD_JMI1_UVD_LMI_JRBC_IB_VMID_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JRBC_RB_VMID 0x0025
+#define regUVD_JMI1_UVD_LMI_JRBC_RB_VMID_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JPEG_VMID 0x0026
+#define regUVD_JMI1_UVD_LMI_JPEG_VMID_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW 0x0027
+#define regUVD_JMI1_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH 0x0028
+#define regUVD_JMI1_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JRBC_RB_64BIT_BAR_LOW 0x0029
+#define regUVD_JMI1_UVD_LMI_JRBC_RB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH 0x002a
+#define regUVD_JMI1_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW 0x002b
+#define regUVD_JMI1_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH 0x002c
+#define regUVD_JMI1_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JPEG_PREEMPT_VMID 0x002d
+#define regUVD_JMI1_UVD_LMI_JPEG_PREEMPT_VMID_BASE_IDX 0
+#define regUVD_JMI1_UVD_JMI_DEC_SWAP_CNTL 0x002e
+#define regUVD_JMI1_UVD_JMI_DEC_SWAP_CNTL_BASE_IDX 0
+#define regUVD_JMI1_UVD_JMI_ATOMIC_CNTL 0x002f
+#define regUVD_JMI1_UVD_JMI_ATOMIC_CNTL_BASE_IDX 0
+#define regUVD_JMI1_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW 0x0030
+#define regUVD_JMI1_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI1_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH 0x0031
+#define regUVD_JMI1_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JPEG_READ_64BIT_BAR_LOW 0x0032
+#define regUVD_JMI1_UVD_LMI_JPEG_READ_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH 0x0033
+#define regUVD_JMI1_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW 0x0034
+#define regUVD_JMI1_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH 0x0035
+#define regUVD_JMI1_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JRBC_IB_64BIT_BAR_LOW 0x0036
+#define regUVD_JMI1_UVD_LMI_JRBC_IB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH 0x0037
+#define regUVD_JMI1_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW 0x0038
+#define regUVD_JMI1_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI1_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH 0x0039
+#define regUVD_JMI1_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI1_UVD_JMI_ATOMIC_CNTL2 0x003d
+#define regUVD_JMI1_UVD_JMI_ATOMIC_CNTL2_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jmi2_uvd_jmi_dec
+// base address: 0x1e180
+#define regUVD_JMI2_UVD_JPEG_DEC_PF_CTRL 0x0060
+#define regUVD_JMI2_UVD_JPEG_DEC_PF_CTRL_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JRBC_CTRL 0x0061
+#define regUVD_JMI2_UVD_LMI_JRBC_CTRL_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JPEG_CTRL 0x0062
+#define regUVD_JMI2_UVD_LMI_JPEG_CTRL_BASE_IDX 0
+#define regUVD_JMI2_JPEG_LMI_DROP 0x0063
+#define regUVD_JMI2_JPEG_LMI_DROP_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JRBC_IB_VMID 0x0064
+#define regUVD_JMI2_UVD_LMI_JRBC_IB_VMID_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JRBC_RB_VMID 0x0065
+#define regUVD_JMI2_UVD_LMI_JRBC_RB_VMID_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JPEG_VMID 0x0066
+#define regUVD_JMI2_UVD_LMI_JPEG_VMID_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW 0x0067
+#define regUVD_JMI2_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH 0x0068
+#define regUVD_JMI2_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JRBC_RB_64BIT_BAR_LOW 0x0069
+#define regUVD_JMI2_UVD_LMI_JRBC_RB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH 0x006a
+#define regUVD_JMI2_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW 0x006b
+#define regUVD_JMI2_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH 0x006c
+#define regUVD_JMI2_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JPEG_PREEMPT_VMID 0x006d
+#define regUVD_JMI2_UVD_LMI_JPEG_PREEMPT_VMID_BASE_IDX 0
+#define regUVD_JMI2_UVD_JMI_DEC_SWAP_CNTL 0x006e
+#define regUVD_JMI2_UVD_JMI_DEC_SWAP_CNTL_BASE_IDX 0
+#define regUVD_JMI2_UVD_JMI_ATOMIC_CNTL 0x006f
+#define regUVD_JMI2_UVD_JMI_ATOMIC_CNTL_BASE_IDX 0
+#define regUVD_JMI2_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW 0x0070
+#define regUVD_JMI2_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI2_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH 0x0071
+#define regUVD_JMI2_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JPEG_READ_64BIT_BAR_LOW 0x0072
+#define regUVD_JMI2_UVD_LMI_JPEG_READ_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH 0x0073
+#define regUVD_JMI2_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW 0x0074
+#define regUVD_JMI2_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH 0x0075
+#define regUVD_JMI2_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JRBC_IB_64BIT_BAR_LOW 0x0076
+#define regUVD_JMI2_UVD_LMI_JRBC_IB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH 0x0077
+#define regUVD_JMI2_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW 0x0078
+#define regUVD_JMI2_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI2_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH 0x0079
+#define regUVD_JMI2_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI2_UVD_JMI_ATOMIC_CNTL2 0x007d
+#define regUVD_JMI2_UVD_JMI_ATOMIC_CNTL2_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jmi3_uvd_jmi_dec
+// base address: 0x1e280
+#define regUVD_JMI3_UVD_JPEG_DEC_PF_CTRL 0x00a0
+#define regUVD_JMI3_UVD_JPEG_DEC_PF_CTRL_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JRBC_CTRL 0x00a1
+#define regUVD_JMI3_UVD_LMI_JRBC_CTRL_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JPEG_CTRL 0x00a2
+#define regUVD_JMI3_UVD_LMI_JPEG_CTRL_BASE_IDX 0
+#define regUVD_JMI3_JPEG_LMI_DROP 0x00a3
+#define regUVD_JMI3_JPEG_LMI_DROP_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JRBC_IB_VMID 0x00a4
+#define regUVD_JMI3_UVD_LMI_JRBC_IB_VMID_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JRBC_RB_VMID 0x00a5
+#define regUVD_JMI3_UVD_LMI_JRBC_RB_VMID_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JPEG_VMID 0x00a6
+#define regUVD_JMI3_UVD_LMI_JPEG_VMID_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW 0x00a7
+#define regUVD_JMI3_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH 0x00a8
+#define regUVD_JMI3_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JRBC_RB_64BIT_BAR_LOW 0x00a9
+#define regUVD_JMI3_UVD_LMI_JRBC_RB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH 0x00aa
+#define regUVD_JMI3_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW 0x00ab
+#define regUVD_JMI3_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH 0x00ac
+#define regUVD_JMI3_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JPEG_PREEMPT_VMID 0x00ad
+#define regUVD_JMI3_UVD_LMI_JPEG_PREEMPT_VMID_BASE_IDX 0
+#define regUVD_JMI3_UVD_JMI_DEC_SWAP_CNTL 0x00ae
+#define regUVD_JMI3_UVD_JMI_DEC_SWAP_CNTL_BASE_IDX 0
+#define regUVD_JMI3_UVD_JMI_ATOMIC_CNTL 0x00af
+#define regUVD_JMI3_UVD_JMI_ATOMIC_CNTL_BASE_IDX 0
+#define regUVD_JMI3_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW 0x00b0
+#define regUVD_JMI3_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI3_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH 0x00b1
+#define regUVD_JMI3_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JPEG_READ_64BIT_BAR_LOW 0x00b2
+#define regUVD_JMI3_UVD_LMI_JPEG_READ_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH 0x00b3
+#define regUVD_JMI3_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW 0x00b4
+#define regUVD_JMI3_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH 0x00b5
+#define regUVD_JMI3_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JRBC_IB_64BIT_BAR_LOW 0x00b6
+#define regUVD_JMI3_UVD_LMI_JRBC_IB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH 0x00b7
+#define regUVD_JMI3_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW 0x00b8
+#define regUVD_JMI3_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI3_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH 0x00b9
+#define regUVD_JMI3_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI3_UVD_JMI_ATOMIC_CNTL2 0x00bd
+#define regUVD_JMI3_UVD_JMI_ATOMIC_CNTL2_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jmi4_uvd_jmi_dec
+// base address: 0x1e380
+#define regUVD_JMI4_UVD_JPEG_DEC_PF_CTRL 0x00e0
+#define regUVD_JMI4_UVD_JPEG_DEC_PF_CTRL_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JRBC_CTRL 0x00e1
+#define regUVD_JMI4_UVD_LMI_JRBC_CTRL_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JPEG_CTRL 0x00e2
+#define regUVD_JMI4_UVD_LMI_JPEG_CTRL_BASE_IDX 0
+#define regUVD_JMI4_JPEG_LMI_DROP 0x00e3
+#define regUVD_JMI4_JPEG_LMI_DROP_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JRBC_IB_VMID 0x00e4
+#define regUVD_JMI4_UVD_LMI_JRBC_IB_VMID_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JRBC_RB_VMID 0x00e5
+#define regUVD_JMI4_UVD_LMI_JRBC_RB_VMID_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JPEG_VMID 0x00e6
+#define regUVD_JMI4_UVD_LMI_JPEG_VMID_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW 0x00e7
+#define regUVD_JMI4_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH 0x00e8
+#define regUVD_JMI4_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JRBC_RB_64BIT_BAR_LOW 0x00e9
+#define regUVD_JMI4_UVD_LMI_JRBC_RB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH 0x00ea
+#define regUVD_JMI4_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW 0x00eb
+#define regUVD_JMI4_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH 0x00ec
+#define regUVD_JMI4_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JPEG_PREEMPT_VMID 0x00ed
+#define regUVD_JMI4_UVD_LMI_JPEG_PREEMPT_VMID_BASE_IDX 0
+#define regUVD_JMI4_UVD_JMI_DEC_SWAP_CNTL 0x00ee
+#define regUVD_JMI4_UVD_JMI_DEC_SWAP_CNTL_BASE_IDX 0
+#define regUVD_JMI4_UVD_JMI_ATOMIC_CNTL 0x00ef
+#define regUVD_JMI4_UVD_JMI_ATOMIC_CNTL_BASE_IDX 0
+#define regUVD_JMI4_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW 0x00f0
+#define regUVD_JMI4_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI4_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH 0x00f1
+#define regUVD_JMI4_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JPEG_READ_64BIT_BAR_LOW 0x00f2
+#define regUVD_JMI4_UVD_LMI_JPEG_READ_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH 0x00f3
+#define regUVD_JMI4_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW 0x00f4
+#define regUVD_JMI4_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH 0x00f5
+#define regUVD_JMI4_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JRBC_IB_64BIT_BAR_LOW 0x00f6
+#define regUVD_JMI4_UVD_LMI_JRBC_IB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH 0x00f7
+#define regUVD_JMI4_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW 0x00f8
+#define regUVD_JMI4_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI4_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH 0x00f9
+#define regUVD_JMI4_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI4_UVD_JMI_ATOMIC_CNTL2 0x00fd
+#define regUVD_JMI4_UVD_JMI_ATOMIC_CNTL2_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jmi5_uvd_jmi_dec
+// base address: 0x1e480
+#define regUVD_JMI5_UVD_JPEG_DEC_PF_CTRL 0x0120
+#define regUVD_JMI5_UVD_JPEG_DEC_PF_CTRL_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JRBC_CTRL 0x0121
+#define regUVD_JMI5_UVD_LMI_JRBC_CTRL_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JPEG_CTRL 0x0122
+#define regUVD_JMI5_UVD_LMI_JPEG_CTRL_BASE_IDX 0
+#define regUVD_JMI5_JPEG_LMI_DROP 0x0123
+#define regUVD_JMI5_JPEG_LMI_DROP_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JRBC_IB_VMID 0x0124
+#define regUVD_JMI5_UVD_LMI_JRBC_IB_VMID_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JRBC_RB_VMID 0x0125
+#define regUVD_JMI5_UVD_LMI_JRBC_RB_VMID_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JPEG_VMID 0x0126
+#define regUVD_JMI5_UVD_LMI_JPEG_VMID_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW 0x0127
+#define regUVD_JMI5_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH 0x0128
+#define regUVD_JMI5_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JRBC_RB_64BIT_BAR_LOW 0x0129
+#define regUVD_JMI5_UVD_LMI_JRBC_RB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH 0x012a
+#define regUVD_JMI5_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW 0x012b
+#define regUVD_JMI5_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH 0x012c
+#define regUVD_JMI5_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JPEG_PREEMPT_VMID 0x012d
+#define regUVD_JMI5_UVD_LMI_JPEG_PREEMPT_VMID_BASE_IDX 0
+#define regUVD_JMI5_UVD_JMI_DEC_SWAP_CNTL 0x012e
+#define regUVD_JMI5_UVD_JMI_DEC_SWAP_CNTL_BASE_IDX 0
+#define regUVD_JMI5_UVD_JMI_ATOMIC_CNTL 0x012f
+#define regUVD_JMI5_UVD_JMI_ATOMIC_CNTL_BASE_IDX 0
+#define regUVD_JMI5_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW 0x0130
+#define regUVD_JMI5_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI5_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH 0x0131
+#define regUVD_JMI5_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JPEG_READ_64BIT_BAR_LOW 0x0132
+#define regUVD_JMI5_UVD_LMI_JPEG_READ_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH 0x0133
+#define regUVD_JMI5_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW 0x0134
+#define regUVD_JMI5_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH 0x0135
+#define regUVD_JMI5_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JRBC_IB_64BIT_BAR_LOW 0x0136
+#define regUVD_JMI5_UVD_LMI_JRBC_IB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH 0x0137
+#define regUVD_JMI5_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW 0x0138
+#define regUVD_JMI5_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI5_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH 0x0139
+#define regUVD_JMI5_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI5_UVD_JMI_ATOMIC_CNTL2 0x013d
+#define regUVD_JMI5_UVD_JMI_ATOMIC_CNTL2_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jmi6_uvd_jmi_dec
+// base address: 0x1e580
+#define regUVD_JMI6_UVD_JPEG_DEC_PF_CTRL 0x0160
+#define regUVD_JMI6_UVD_JPEG_DEC_PF_CTRL_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JRBC_CTRL 0x0161
+#define regUVD_JMI6_UVD_LMI_JRBC_CTRL_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JPEG_CTRL 0x0162
+#define regUVD_JMI6_UVD_LMI_JPEG_CTRL_BASE_IDX 0
+#define regUVD_JMI6_JPEG_LMI_DROP 0x0163
+#define regUVD_JMI6_JPEG_LMI_DROP_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JRBC_IB_VMID 0x0164
+#define regUVD_JMI6_UVD_LMI_JRBC_IB_VMID_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JRBC_RB_VMID 0x0165
+#define regUVD_JMI6_UVD_LMI_JRBC_RB_VMID_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JPEG_VMID 0x0166
+#define regUVD_JMI6_UVD_LMI_JPEG_VMID_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW 0x0167
+#define regUVD_JMI6_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH 0x0168
+#define regUVD_JMI6_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JRBC_RB_64BIT_BAR_LOW 0x0169
+#define regUVD_JMI6_UVD_LMI_JRBC_RB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH 0x016a
+#define regUVD_JMI6_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW 0x016b
+#define regUVD_JMI6_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH 0x016c
+#define regUVD_JMI6_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JPEG_PREEMPT_VMID 0x016d
+#define regUVD_JMI6_UVD_LMI_JPEG_PREEMPT_VMID_BASE_IDX 0
+#define regUVD_JMI6_UVD_JMI_DEC_SWAP_CNTL 0x016e
+#define regUVD_JMI6_UVD_JMI_DEC_SWAP_CNTL_BASE_IDX 0
+#define regUVD_JMI6_UVD_JMI_ATOMIC_CNTL 0x016f
+#define regUVD_JMI6_UVD_JMI_ATOMIC_CNTL_BASE_IDX 0
+#define regUVD_JMI6_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW 0x0170
+#define regUVD_JMI6_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI6_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH 0x0171
+#define regUVD_JMI6_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JPEG_READ_64BIT_BAR_LOW 0x0172
+#define regUVD_JMI6_UVD_LMI_JPEG_READ_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH 0x0173
+#define regUVD_JMI6_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW 0x0174
+#define regUVD_JMI6_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH 0x0175
+#define regUVD_JMI6_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JRBC_IB_64BIT_BAR_LOW 0x0176
+#define regUVD_JMI6_UVD_LMI_JRBC_IB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH 0x0177
+#define regUVD_JMI6_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW 0x0178
+#define regUVD_JMI6_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI6_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH 0x0179
+#define regUVD_JMI6_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI6_UVD_JMI_ATOMIC_CNTL2 0x017d
+#define regUVD_JMI6_UVD_JMI_ATOMIC_CNTL2_BASE_IDX 0
+
+
+// addressBlock: aid_uvd0_uvd_jmi7_uvd_jmi_dec
+// base address: 0x1e680
+#define regUVD_JMI7_UVD_JPEG_DEC_PF_CTRL 0x01a0
+#define regUVD_JMI7_UVD_JPEG_DEC_PF_CTRL_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JRBC_CTRL 0x01a1
+#define regUVD_JMI7_UVD_LMI_JRBC_CTRL_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JPEG_CTRL 0x01a2
+#define regUVD_JMI7_UVD_LMI_JPEG_CTRL_BASE_IDX 0
+#define regUVD_JMI7_JPEG_LMI_DROP 0x01a3
+#define regUVD_JMI7_JPEG_LMI_DROP_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JRBC_IB_VMID 0x01a4
+#define regUVD_JMI7_UVD_LMI_JRBC_IB_VMID_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JRBC_RB_VMID 0x01a5
+#define regUVD_JMI7_UVD_LMI_JRBC_RB_VMID_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JPEG_VMID 0x01a6
+#define regUVD_JMI7_UVD_LMI_JPEG_VMID_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW 0x01a7
+#define regUVD_JMI7_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH 0x01a8
+#define regUVD_JMI7_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JRBC_RB_64BIT_BAR_LOW 0x01a9
+#define regUVD_JMI7_UVD_LMI_JRBC_RB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH 0x01aa
+#define regUVD_JMI7_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW 0x01ab
+#define regUVD_JMI7_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH 0x01ac
+#define regUVD_JMI7_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JPEG_PREEMPT_VMID 0x01ad
+#define regUVD_JMI7_UVD_LMI_JPEG_PREEMPT_VMID_BASE_IDX 0
+#define regUVD_JMI7_UVD_JMI_DEC_SWAP_CNTL 0x01ae
+#define regUVD_JMI7_UVD_JMI_DEC_SWAP_CNTL_BASE_IDX 0
+#define regUVD_JMI7_UVD_JMI_ATOMIC_CNTL 0x01af
+#define regUVD_JMI7_UVD_JMI_ATOMIC_CNTL_BASE_IDX 0
+#define regUVD_JMI7_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW 0x01b0
+#define regUVD_JMI7_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI7_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH 0x01b1
+#define regUVD_JMI7_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JPEG_READ_64BIT_BAR_LOW 0x01b2
+#define regUVD_JMI7_UVD_LMI_JPEG_READ_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH 0x01b3
+#define regUVD_JMI7_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW 0x01b4
+#define regUVD_JMI7_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH 0x01b5
+#define regUVD_JMI7_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JRBC_IB_64BIT_BAR_LOW 0x01b6
+#define regUVD_JMI7_UVD_LMI_JRBC_IB_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH 0x01b7
+#define regUVD_JMI7_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW 0x01b8
+#define regUVD_JMI7_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW_BASE_IDX 0
+#define regUVD_JMI7_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH 0x01b9
+#define regUVD_JMI7_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH_BASE_IDX 0
+#define regUVD_JMI7_UVD_JMI_ATOMIC_CNTL2 0x01bd
+#define regUVD_JMI7_UVD_JMI_ATOMIC_CNTL2_BASE_IDX 0
+
+
+// addressBlock: uvdctxind
+// base address: 0x0
+#define ixUVD_CGC_MEM_CTRL 0x0000
+#define ixUVD_CGC_CTRL2 0x0001
+#define ixUVD_CGC_MEM_DS_CTRL 0x0002
+#define ixUVD_CGC_MEM_SD_CTRL 0x0003
+#define ixUVD_SW_SCRATCH_00 0x0004
+#define ixUVD_SW_SCRATCH_01 0x0005
+#define ixUVD_SW_SCRATCH_02 0x0006
+#define ixUVD_SW_SCRATCH_03 0x0007
+#define ixUVD_SW_SCRATCH_04 0x0008
+#define ixUVD_SW_SCRATCH_05 0x0009
+#define ixUVD_SW_SCRATCH_06 0x000a
+#define ixUVD_SW_SCRATCH_07 0x000b
+#define ixUVD_SW_SCRATCH_08 0x000c
+#define ixUVD_SW_SCRATCH_09 0x000d
+#define ixUVD_SW_SCRATCH_10 0x000e
+#define ixUVD_SW_SCRATCH_11 0x000f
+#define ixUVD_SW_SCRATCH_12 0x0010
+#define ixUVD_SW_SCRATCH_13 0x0011
+#define ixUVD_SW_SCRATCH_14 0x0012
+#define ixUVD_SW_SCRATCH_15 0x0013
+#define ixUVD_IH_SEM_CTRL 0x001e
+
+
+// addressBlock: lmi_adp_indirect
+// base address: 0x0
+#define ixUVD_LMI_CRC0 0x0000
+#define ixUVD_LMI_CRC1 0x0001
+#define ixUVD_LMI_CRC2 0x0002
+#define ixUVD_LMI_CRC3 0x0003
+#define ixUVD_LMI_CRC10 0x000a
+#define ixUVD_LMI_CRC11 0x000b
+#define ixUVD_LMI_CRC12 0x000c
+#define ixUVD_LMI_CRC13 0x000d
+#define ixUVD_LMI_CRC14 0x000e
+#define ixUVD_LMI_CRC15 0x000f
+#define ixUVD_LMI_SWAP_CNTL2 0x0029
+#define ixUVD_MEMCHECK_SYS_INT_EN 0x0134
+#define ixUVD_MEMCHECK_SYS_INT_STAT 0x0135
+#define ixUVD_MEMCHECK_SYS_INT_ACK 0x0136
+#define ixUVD_MEMCHECK_VCPU_INT_EN 0x0137
+#define ixUVD_MEMCHECK_VCPU_INT_STAT 0x0138
+#define ixUVD_MEMCHECK_VCPU_INT_ACK 0x0139
+#define ixUVD_MEMCHECK2_SYS_INT_STAT 0x0140
+#define ixUVD_MEMCHECK2_SYS_INT_ACK 0x0141
+#define ixUVD_MEMCHECK2_VCPU_INT_STAT 0x0142
+#define ixUVD_MEMCHECK2_VCPU_INT_ACK 0x0143
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_4_0_3_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_4_0_3_sh_mask.h
new file mode 100644
index 000000000000..5bd8111bf04a
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_4_0_3_sh_mask.h
@@ -0,0 +1,10919 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef _vcn_4_0_3_SH_MASK_HEADER
+#define _vcn_4_0_3_SH_MASK_HEADER
+
+
+// addressBlock: aid_uvd0_uvddec
+//UVD_TOP_CTRL
+#define UVD_TOP_CTRL__STANDARD__SHIFT 0x0
+#define UVD_TOP_CTRL__STD_VERSION__SHIFT 0x4
+#define UVD_TOP_CTRL__STANDARD_MASK 0x0000000FL
+#define UVD_TOP_CTRL__STD_VERSION_MASK 0x00000010L
+//UVD_CGC_GATE
+#define UVD_CGC_GATE__SYS__SHIFT 0x0
+#define UVD_CGC_GATE__UDEC__SHIFT 0x1
+#define UVD_CGC_GATE__MPEG2__SHIFT 0x2
+#define UVD_CGC_GATE__REGS__SHIFT 0x3
+#define UVD_CGC_GATE__RBC__SHIFT 0x4
+#define UVD_CGC_GATE__LMI_MC__SHIFT 0x5
+#define UVD_CGC_GATE__LMI_UMC__SHIFT 0x6
+#define UVD_CGC_GATE__IDCT__SHIFT 0x7
+#define UVD_CGC_GATE__MPRD__SHIFT 0x8
+#define UVD_CGC_GATE__MPC__SHIFT 0x9
+#define UVD_CGC_GATE__LBSI__SHIFT 0xa
+#define UVD_CGC_GATE__LRBBM__SHIFT 0xb
+#define UVD_CGC_GATE__UDEC_RE__SHIFT 0xc
+#define UVD_CGC_GATE__UDEC_CM__SHIFT 0xd
+#define UVD_CGC_GATE__UDEC_IT__SHIFT 0xe
+#define UVD_CGC_GATE__UDEC_DB__SHIFT 0xf
+#define UVD_CGC_GATE__UDEC_MP__SHIFT 0x10
+#define UVD_CGC_GATE__WCB__SHIFT 0x11
+#define UVD_CGC_GATE__VCPU__SHIFT 0x12
+#define UVD_CGC_GATE__MMSCH__SHIFT 0x14
+#define UVD_CGC_GATE__LCM0__SHIFT 0x15
+#define UVD_CGC_GATE__LCM1__SHIFT 0x16
+#define UVD_CGC_GATE__MIF__SHIFT 0x17
+#define UVD_CGC_GATE__VREG__SHIFT 0x18
+#define UVD_CGC_GATE__PE__SHIFT 0x19
+#define UVD_CGC_GATE__PPU__SHIFT 0x1a
+#define UVD_CGC_GATE__SYS_MASK 0x00000001L
+#define UVD_CGC_GATE__UDEC_MASK 0x00000002L
+#define UVD_CGC_GATE__MPEG2_MASK 0x00000004L
+#define UVD_CGC_GATE__REGS_MASK 0x00000008L
+#define UVD_CGC_GATE__RBC_MASK 0x00000010L
+#define UVD_CGC_GATE__LMI_MC_MASK 0x00000020L
+#define UVD_CGC_GATE__LMI_UMC_MASK 0x00000040L
+#define UVD_CGC_GATE__IDCT_MASK 0x00000080L
+#define UVD_CGC_GATE__MPRD_MASK 0x00000100L
+#define UVD_CGC_GATE__MPC_MASK 0x00000200L
+#define UVD_CGC_GATE__LBSI_MASK 0x00000400L
+#define UVD_CGC_GATE__LRBBM_MASK 0x00000800L
+#define UVD_CGC_GATE__UDEC_RE_MASK 0x00001000L
+#define UVD_CGC_GATE__UDEC_CM_MASK 0x00002000L
+#define UVD_CGC_GATE__UDEC_IT_MASK 0x00004000L
+#define UVD_CGC_GATE__UDEC_DB_MASK 0x00008000L
+#define UVD_CGC_GATE__UDEC_MP_MASK 0x00010000L
+#define UVD_CGC_GATE__WCB_MASK 0x00020000L
+#define UVD_CGC_GATE__VCPU_MASK 0x00040000L
+#define UVD_CGC_GATE__MMSCH_MASK 0x00100000L
+#define UVD_CGC_GATE__LCM0_MASK 0x00200000L
+#define UVD_CGC_GATE__LCM1_MASK 0x00400000L
+#define UVD_CGC_GATE__MIF_MASK 0x00800000L
+#define UVD_CGC_GATE__VREG_MASK 0x01000000L
+#define UVD_CGC_GATE__PE_MASK 0x02000000L
+#define UVD_CGC_GATE__PPU_MASK 0x04000000L
+//UVD_CGC_CTRL
+#define UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT 0x0
+#define UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT 0x2
+#define UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT 0x6
+#define UVD_CGC_CTRL__UDEC_RE_MODE__SHIFT 0xb
+#define UVD_CGC_CTRL__UDEC_CM_MODE__SHIFT 0xc
+#define UVD_CGC_CTRL__UDEC_IT_MODE__SHIFT 0xd
+#define UVD_CGC_CTRL__UDEC_DB_MODE__SHIFT 0xe
+#define UVD_CGC_CTRL__UDEC_MP_MODE__SHIFT 0xf
+#define UVD_CGC_CTRL__SYS_MODE__SHIFT 0x10
+#define UVD_CGC_CTRL__UDEC_MODE__SHIFT 0x11
+#define UVD_CGC_CTRL__MPEG2_MODE__SHIFT 0x12
+#define UVD_CGC_CTRL__REGS_MODE__SHIFT 0x13
+#define UVD_CGC_CTRL__RBC_MODE__SHIFT 0x14
+#define UVD_CGC_CTRL__LMI_MC_MODE__SHIFT 0x15
+#define UVD_CGC_CTRL__LMI_UMC_MODE__SHIFT 0x16
+#define UVD_CGC_CTRL__IDCT_MODE__SHIFT 0x17
+#define UVD_CGC_CTRL__MPRD_MODE__SHIFT 0x18
+#define UVD_CGC_CTRL__MPC_MODE__SHIFT 0x19
+#define UVD_CGC_CTRL__LBSI_MODE__SHIFT 0x1a
+#define UVD_CGC_CTRL__LRBBM_MODE__SHIFT 0x1b
+#define UVD_CGC_CTRL__WCB_MODE__SHIFT 0x1c
+#define UVD_CGC_CTRL__VCPU_MODE__SHIFT 0x1d
+#define UVD_CGC_CTRL__MMSCH_MODE__SHIFT 0x1f
+#define UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK 0x00000001L
+#define UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK 0x0000003CL
+#define UVD_CGC_CTRL__CLK_OFF_DELAY_MASK 0x000007C0L
+#define UVD_CGC_CTRL__UDEC_RE_MODE_MASK 0x00000800L
+#define UVD_CGC_CTRL__UDEC_CM_MODE_MASK 0x00001000L
+#define UVD_CGC_CTRL__UDEC_IT_MODE_MASK 0x00002000L
+#define UVD_CGC_CTRL__UDEC_DB_MODE_MASK 0x00004000L
+#define UVD_CGC_CTRL__UDEC_MP_MODE_MASK 0x00008000L
+#define UVD_CGC_CTRL__SYS_MODE_MASK 0x00010000L
+#define UVD_CGC_CTRL__UDEC_MODE_MASK 0x00020000L
+#define UVD_CGC_CTRL__MPEG2_MODE_MASK 0x00040000L
+#define UVD_CGC_CTRL__REGS_MODE_MASK 0x00080000L
+#define UVD_CGC_CTRL__RBC_MODE_MASK 0x00100000L
+#define UVD_CGC_CTRL__LMI_MC_MODE_MASK 0x00200000L
+#define UVD_CGC_CTRL__LMI_UMC_MODE_MASK 0x00400000L
+#define UVD_CGC_CTRL__IDCT_MODE_MASK 0x00800000L
+#define UVD_CGC_CTRL__MPRD_MODE_MASK 0x01000000L
+#define UVD_CGC_CTRL__MPC_MODE_MASK 0x02000000L
+#define UVD_CGC_CTRL__LBSI_MODE_MASK 0x04000000L
+#define UVD_CGC_CTRL__LRBBM_MODE_MASK 0x08000000L
+#define UVD_CGC_CTRL__WCB_MODE_MASK 0x10000000L
+#define UVD_CGC_CTRL__VCPU_MODE_MASK 0x20000000L
+#define UVD_CGC_CTRL__MMSCH_MODE_MASK 0x80000000L
+//AVM_SUVD_CGC_GATE
+#define AVM_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define AVM_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define AVM_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define AVM_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define AVM_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define AVM_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define AVM_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define AVM_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define AVM_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define AVM_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define AVM_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define AVM_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define AVM_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define AVM_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define AVM_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define AVM_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define AVM_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define AVM_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define AVM_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define AVM_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define AVM_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define AVM_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define AVM_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define AVM_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define AVM_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define AVM_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define AVM_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define AVM_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define AVM_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define AVM_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define AVM_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define AVM_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define AVM_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define AVM_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define AVM_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define AVM_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define AVM_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define AVM_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define AVM_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define AVM_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define AVM_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define AVM_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define AVM_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define AVM_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define AVM_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define AVM_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define AVM_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define AVM_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define AVM_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define AVM_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define AVM_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define AVM_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define AVM_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define AVM_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define AVM_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define AVM_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define AVM_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define AVM_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define AVM_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define AVM_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define AVM_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define AVM_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define AVM_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define AVM_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//CDEFE_SUVD_CGC_GATE
+#define CDEFE_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define CDEFE_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define CDEFE_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define CDEFE_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define CDEFE_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define CDEFE_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define CDEFE_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define CDEFE_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define CDEFE_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define CDEFE_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define CDEFE_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define CDEFE_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define CDEFE_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define CDEFE_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define CDEFE_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define CDEFE_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define CDEFE_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define CDEFE_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define CDEFE_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define CDEFE_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define CDEFE_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define CDEFE_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define CDEFE_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define CDEFE_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define CDEFE_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define CDEFE_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define CDEFE_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define CDEFE_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define CDEFE_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define CDEFE_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define CDEFE_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define CDEFE_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define CDEFE_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define CDEFE_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define CDEFE_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define CDEFE_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define CDEFE_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define CDEFE_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define CDEFE_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define CDEFE_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define CDEFE_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define CDEFE_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define CDEFE_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define CDEFE_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define CDEFE_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define CDEFE_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define CDEFE_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define CDEFE_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define CDEFE_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define CDEFE_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define CDEFE_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define CDEFE_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define CDEFE_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define CDEFE_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define CDEFE_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define CDEFE_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define CDEFE_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define CDEFE_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define CDEFE_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define CDEFE_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define CDEFE_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define CDEFE_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define CDEFE_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define CDEFE_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//EFC_SUVD_CGC_GATE
+#define EFC_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define EFC_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define EFC_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define EFC_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define EFC_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define EFC_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define EFC_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define EFC_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define EFC_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define EFC_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define EFC_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define EFC_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define EFC_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define EFC_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define EFC_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define EFC_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define EFC_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define EFC_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define EFC_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define EFC_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define EFC_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define EFC_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define EFC_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define EFC_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define EFC_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define EFC_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define EFC_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define EFC_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define EFC_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define EFC_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define EFC_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define EFC_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define EFC_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define EFC_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define EFC_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define EFC_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define EFC_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define EFC_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define EFC_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define EFC_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define EFC_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define EFC_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define EFC_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define EFC_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define EFC_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define EFC_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define EFC_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define EFC_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define EFC_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define EFC_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define EFC_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define EFC_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define EFC_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define EFC_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define EFC_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define EFC_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define EFC_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define EFC_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define EFC_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define EFC_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define EFC_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define EFC_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define EFC_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define EFC_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//ENT_SUVD_CGC_GATE
+#define ENT_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define ENT_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define ENT_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define ENT_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define ENT_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define ENT_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define ENT_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define ENT_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define ENT_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define ENT_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define ENT_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define ENT_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define ENT_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define ENT_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define ENT_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define ENT_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define ENT_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define ENT_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define ENT_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define ENT_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define ENT_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define ENT_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define ENT_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define ENT_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define ENT_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define ENT_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define ENT_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define ENT_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define ENT_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define ENT_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define ENT_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define ENT_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define ENT_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define ENT_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define ENT_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define ENT_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define ENT_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define ENT_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define ENT_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define ENT_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define ENT_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define ENT_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define ENT_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define ENT_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define ENT_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define ENT_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define ENT_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define ENT_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define ENT_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define ENT_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define ENT_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define ENT_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define ENT_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define ENT_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define ENT_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define ENT_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define ENT_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define ENT_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define ENT_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define ENT_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define ENT_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define ENT_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define ENT_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define ENT_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//IME_SUVD_CGC_GATE
+#define IME_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define IME_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define IME_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define IME_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define IME_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define IME_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define IME_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define IME_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define IME_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define IME_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define IME_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define IME_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define IME_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define IME_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define IME_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define IME_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define IME_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define IME_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define IME_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define IME_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define IME_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define IME_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define IME_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define IME_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define IME_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define IME_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define IME_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define IME_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define IME_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define IME_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define IME_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define IME_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define IME_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define IME_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define IME_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define IME_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define IME_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define IME_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define IME_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define IME_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define IME_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define IME_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define IME_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define IME_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define IME_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define IME_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define IME_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define IME_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define IME_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define IME_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define IME_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define IME_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define IME_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define IME_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define IME_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define IME_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define IME_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define IME_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define IME_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define IME_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define IME_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define IME_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define IME_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define IME_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//PPU_SUVD_CGC_GATE
+#define PPU_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define PPU_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define PPU_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define PPU_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define PPU_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define PPU_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define PPU_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define PPU_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define PPU_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define PPU_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define PPU_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define PPU_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define PPU_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define PPU_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define PPU_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define PPU_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define PPU_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define PPU_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define PPU_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define PPU_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define PPU_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define PPU_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define PPU_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define PPU_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define PPU_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define PPU_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define PPU_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define PPU_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define PPU_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define PPU_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define PPU_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define PPU_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define PPU_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define PPU_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define PPU_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define PPU_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define PPU_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define PPU_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define PPU_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define PPU_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define PPU_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define PPU_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define PPU_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define PPU_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define PPU_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define PPU_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define PPU_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define PPU_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define PPU_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define PPU_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define PPU_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define PPU_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define PPU_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define PPU_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define PPU_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define PPU_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define PPU_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define PPU_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define PPU_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define PPU_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define PPU_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define PPU_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define PPU_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define PPU_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//SAOE_SUVD_CGC_GATE
+#define SAOE_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define SAOE_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define SAOE_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define SAOE_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define SAOE_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define SAOE_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define SAOE_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define SAOE_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define SAOE_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define SAOE_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define SAOE_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define SAOE_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define SAOE_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define SAOE_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define SAOE_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define SAOE_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define SAOE_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define SAOE_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define SAOE_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define SAOE_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define SAOE_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define SAOE_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define SAOE_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define SAOE_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define SAOE_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define SAOE_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define SAOE_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define SAOE_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define SAOE_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define SAOE_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define SAOE_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define SAOE_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define SAOE_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define SAOE_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define SAOE_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define SAOE_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define SAOE_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define SAOE_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define SAOE_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define SAOE_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define SAOE_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define SAOE_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define SAOE_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define SAOE_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define SAOE_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define SAOE_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define SAOE_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define SAOE_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define SAOE_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define SAOE_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define SAOE_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define SAOE_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define SAOE_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define SAOE_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define SAOE_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define SAOE_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define SAOE_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define SAOE_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define SAOE_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define SAOE_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define SAOE_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define SAOE_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define SAOE_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define SAOE_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//SCM_SUVD_CGC_GATE
+#define SCM_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define SCM_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define SCM_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define SCM_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define SCM_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define SCM_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define SCM_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define SCM_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define SCM_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define SCM_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define SCM_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define SCM_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define SCM_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define SCM_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define SCM_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define SCM_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define SCM_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define SCM_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define SCM_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define SCM_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define SCM_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define SCM_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define SCM_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define SCM_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define SCM_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define SCM_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define SCM_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define SCM_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define SCM_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define SCM_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define SCM_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define SCM_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define SCM_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define SCM_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define SCM_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define SCM_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define SCM_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define SCM_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define SCM_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define SCM_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define SCM_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define SCM_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define SCM_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define SCM_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define SCM_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define SCM_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define SCM_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define SCM_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define SCM_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define SCM_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define SCM_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define SCM_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define SCM_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define SCM_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define SCM_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define SCM_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define SCM_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define SCM_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define SCM_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define SCM_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define SCM_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define SCM_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define SCM_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define SCM_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//SDB_SUVD_CGC_GATE
+#define SDB_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define SDB_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define SDB_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define SDB_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define SDB_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define SDB_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define SDB_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define SDB_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define SDB_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define SDB_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define SDB_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define SDB_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define SDB_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define SDB_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define SDB_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define SDB_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define SDB_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define SDB_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define SDB_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define SDB_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define SDB_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define SDB_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define SDB_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define SDB_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define SDB_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define SDB_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define SDB_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define SDB_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define SDB_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define SDB_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define SDB_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define SDB_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define SDB_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define SDB_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define SDB_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define SDB_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define SDB_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define SDB_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define SDB_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define SDB_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define SDB_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define SDB_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define SDB_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define SDB_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define SDB_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define SDB_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define SDB_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define SDB_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define SDB_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define SDB_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define SDB_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define SDB_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define SDB_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define SDB_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define SDB_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define SDB_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define SDB_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define SDB_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define SDB_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define SDB_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define SDB_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define SDB_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define SDB_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define SDB_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//SIT0_NXT_SUVD_CGC_GATE
+#define SIT0_NXT_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define SIT0_NXT_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define SIT0_NXT_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define SIT0_NXT_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define SIT0_NXT_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define SIT0_NXT_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define SIT0_NXT_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define SIT0_NXT_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define SIT0_NXT_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define SIT0_NXT_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define SIT0_NXT_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define SIT0_NXT_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define SIT0_NXT_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define SIT0_NXT_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define SIT0_NXT_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define SIT0_NXT_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define SIT0_NXT_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define SIT0_NXT_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define SIT0_NXT_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define SIT0_NXT_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define SIT0_NXT_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define SIT0_NXT_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define SIT0_NXT_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define SIT0_NXT_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define SIT0_NXT_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define SIT0_NXT_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define SIT0_NXT_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define SIT0_NXT_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define SIT0_NXT_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define SIT0_NXT_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define SIT0_NXT_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define SIT0_NXT_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define SIT0_NXT_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define SIT0_NXT_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define SIT0_NXT_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define SIT0_NXT_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define SIT0_NXT_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define SIT0_NXT_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define SIT0_NXT_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define SIT0_NXT_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define SIT0_NXT_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define SIT0_NXT_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define SIT0_NXT_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define SIT0_NXT_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define SIT0_NXT_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define SIT0_NXT_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define SIT0_NXT_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define SIT0_NXT_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define SIT0_NXT_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define SIT0_NXT_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define SIT0_NXT_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define SIT0_NXT_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define SIT0_NXT_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define SIT0_NXT_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define SIT0_NXT_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define SIT0_NXT_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define SIT0_NXT_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define SIT0_NXT_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define SIT0_NXT_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define SIT0_NXT_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define SIT0_NXT_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define SIT0_NXT_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define SIT0_NXT_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define SIT0_NXT_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//SIT1_NXT_SUVD_CGC_GATE
+#define SIT1_NXT_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define SIT1_NXT_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define SIT1_NXT_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define SIT1_NXT_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define SIT1_NXT_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define SIT1_NXT_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define SIT1_NXT_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define SIT1_NXT_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define SIT1_NXT_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define SIT1_NXT_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define SIT1_NXT_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define SIT1_NXT_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define SIT1_NXT_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define SIT1_NXT_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define SIT1_NXT_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define SIT1_NXT_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define SIT1_NXT_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define SIT1_NXT_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define SIT1_NXT_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define SIT1_NXT_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define SIT1_NXT_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define SIT1_NXT_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define SIT1_NXT_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define SIT1_NXT_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define SIT1_NXT_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define SIT1_NXT_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define SIT1_NXT_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define SIT1_NXT_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define SIT1_NXT_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define SIT1_NXT_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define SIT1_NXT_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define SIT1_NXT_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define SIT1_NXT_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define SIT1_NXT_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define SIT1_NXT_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define SIT1_NXT_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define SIT1_NXT_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define SIT1_NXT_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define SIT1_NXT_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define SIT1_NXT_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define SIT1_NXT_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define SIT1_NXT_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define SIT1_NXT_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define SIT1_NXT_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define SIT1_NXT_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define SIT1_NXT_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define SIT1_NXT_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define SIT1_NXT_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define SIT1_NXT_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define SIT1_NXT_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define SIT1_NXT_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define SIT1_NXT_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define SIT1_NXT_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define SIT1_NXT_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define SIT1_NXT_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define SIT1_NXT_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define SIT1_NXT_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define SIT1_NXT_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define SIT1_NXT_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define SIT1_NXT_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define SIT1_NXT_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define SIT1_NXT_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define SIT1_NXT_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define SIT1_NXT_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//SIT2_NXT_SUVD_CGC_GATE
+#define SIT2_NXT_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define SIT2_NXT_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define SIT2_NXT_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define SIT2_NXT_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define SIT2_NXT_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define SIT2_NXT_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define SIT2_NXT_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define SIT2_NXT_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define SIT2_NXT_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define SIT2_NXT_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define SIT2_NXT_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define SIT2_NXT_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define SIT2_NXT_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define SIT2_NXT_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define SIT2_NXT_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define SIT2_NXT_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define SIT2_NXT_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define SIT2_NXT_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define SIT2_NXT_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define SIT2_NXT_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define SIT2_NXT_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define SIT2_NXT_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define SIT2_NXT_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define SIT2_NXT_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define SIT2_NXT_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define SIT2_NXT_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define SIT2_NXT_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define SIT2_NXT_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define SIT2_NXT_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define SIT2_NXT_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define SIT2_NXT_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define SIT2_NXT_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define SIT2_NXT_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define SIT2_NXT_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define SIT2_NXT_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define SIT2_NXT_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define SIT2_NXT_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define SIT2_NXT_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define SIT2_NXT_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define SIT2_NXT_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define SIT2_NXT_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define SIT2_NXT_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define SIT2_NXT_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define SIT2_NXT_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define SIT2_NXT_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define SIT2_NXT_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define SIT2_NXT_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define SIT2_NXT_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define SIT2_NXT_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define SIT2_NXT_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define SIT2_NXT_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define SIT2_NXT_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define SIT2_NXT_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define SIT2_NXT_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define SIT2_NXT_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define SIT2_NXT_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define SIT2_NXT_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define SIT2_NXT_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define SIT2_NXT_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define SIT2_NXT_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define SIT2_NXT_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define SIT2_NXT_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define SIT2_NXT_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define SIT2_NXT_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//SIT_SUVD_CGC_GATE
+#define SIT_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define SIT_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define SIT_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define SIT_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define SIT_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define SIT_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define SIT_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define SIT_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define SIT_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define SIT_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define SIT_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define SIT_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define SIT_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define SIT_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define SIT_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define SIT_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define SIT_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define SIT_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define SIT_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define SIT_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define SIT_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define SIT_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define SIT_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define SIT_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define SIT_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define SIT_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define SIT_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define SIT_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define SIT_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define SIT_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define SIT_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define SIT_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define SIT_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define SIT_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define SIT_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define SIT_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define SIT_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define SIT_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define SIT_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define SIT_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define SIT_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define SIT_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define SIT_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define SIT_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define SIT_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define SIT_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define SIT_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define SIT_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define SIT_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define SIT_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define SIT_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define SIT_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define SIT_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define SIT_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define SIT_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define SIT_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define SIT_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define SIT_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define SIT_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define SIT_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define SIT_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define SIT_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define SIT_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define SIT_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//SMPA_SUVD_CGC_GATE
+#define SMPA_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define SMPA_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define SMPA_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define SMPA_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define SMPA_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define SMPA_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define SMPA_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define SMPA_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define SMPA_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define SMPA_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define SMPA_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define SMPA_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define SMPA_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define SMPA_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define SMPA_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define SMPA_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define SMPA_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define SMPA_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define SMPA_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define SMPA_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define SMPA_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define SMPA_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define SMPA_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define SMPA_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define SMPA_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define SMPA_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define SMPA_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define SMPA_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define SMPA_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define SMPA_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define SMPA_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define SMPA_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define SMPA_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define SMPA_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define SMPA_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define SMPA_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define SMPA_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define SMPA_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define SMPA_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define SMPA_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define SMPA_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define SMPA_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define SMPA_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define SMPA_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define SMPA_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define SMPA_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define SMPA_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define SMPA_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define SMPA_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define SMPA_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define SMPA_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define SMPA_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define SMPA_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define SMPA_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define SMPA_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define SMPA_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define SMPA_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define SMPA_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define SMPA_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define SMPA_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define SMPA_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define SMPA_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define SMPA_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define SMPA_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//SMP_SUVD_CGC_GATE
+#define SMP_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define SMP_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define SMP_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define SMP_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define SMP_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define SMP_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define SMP_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define SMP_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define SMP_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define SMP_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define SMP_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define SMP_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define SMP_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define SMP_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define SMP_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define SMP_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define SMP_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define SMP_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define SMP_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define SMP_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define SMP_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define SMP_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define SMP_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define SMP_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define SMP_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define SMP_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define SMP_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define SMP_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define SMP_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define SMP_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define SMP_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define SMP_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define SMP_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define SMP_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define SMP_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define SMP_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define SMP_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define SMP_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define SMP_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define SMP_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define SMP_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define SMP_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define SMP_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define SMP_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define SMP_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define SMP_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define SMP_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define SMP_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define SMP_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define SMP_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define SMP_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define SMP_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define SMP_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define SMP_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define SMP_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define SMP_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define SMP_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define SMP_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define SMP_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define SMP_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define SMP_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define SMP_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define SMP_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define SMP_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//SRE_SUVD_CGC_GATE
+#define SRE_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define SRE_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define SRE_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define SRE_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define SRE_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define SRE_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define SRE_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define SRE_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define SRE_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define SRE_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define SRE_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define SRE_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define SRE_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define SRE_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define SRE_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define SRE_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define SRE_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define SRE_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define SRE_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define SRE_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define SRE_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define SRE_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define SRE_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define SRE_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define SRE_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define SRE_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define SRE_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define SRE_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define SRE_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define SRE_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define SRE_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define SRE_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define SRE_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define SRE_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define SRE_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define SRE_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define SRE_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define SRE_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define SRE_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define SRE_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define SRE_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define SRE_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define SRE_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define SRE_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define SRE_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define SRE_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define SRE_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define SRE_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define SRE_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define SRE_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define SRE_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define SRE_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define SRE_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define SRE_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define SRE_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define SRE_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define SRE_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define SRE_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define SRE_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define SRE_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define SRE_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define SRE_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define SRE_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define SRE_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//UVD_MPBE0_SUVD_CGC_GATE
+#define UVD_MPBE0_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define UVD_MPBE0_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define UVD_MPBE0_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define UVD_MPBE0_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define UVD_MPBE0_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define UVD_MPBE0_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define UVD_MPBE0_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define UVD_MPBE0_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define UVD_MPBE0_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define UVD_MPBE0_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define UVD_MPBE0_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define UVD_MPBE0_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define UVD_MPBE0_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define UVD_MPBE0_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define UVD_MPBE0_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define UVD_MPBE0_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define UVD_MPBE0_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define UVD_MPBE0_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define UVD_MPBE0_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define UVD_MPBE0_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define UVD_MPBE0_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define UVD_MPBE0_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define UVD_MPBE0_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define UVD_MPBE0_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define UVD_MPBE0_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define UVD_MPBE0_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define UVD_MPBE0_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define UVD_MPBE0_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define UVD_MPBE0_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define UVD_MPBE0_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define UVD_MPBE0_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define UVD_MPBE0_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define UVD_MPBE0_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define UVD_MPBE0_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define UVD_MPBE0_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define UVD_MPBE0_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define UVD_MPBE0_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define UVD_MPBE0_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define UVD_MPBE0_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define UVD_MPBE0_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define UVD_MPBE0_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define UVD_MPBE0_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define UVD_MPBE0_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define UVD_MPBE0_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define UVD_MPBE0_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define UVD_MPBE0_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define UVD_MPBE0_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define UVD_MPBE0_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define UVD_MPBE0_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define UVD_MPBE0_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define UVD_MPBE0_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define UVD_MPBE0_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define UVD_MPBE0_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define UVD_MPBE0_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define UVD_MPBE0_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define UVD_MPBE0_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define UVD_MPBE0_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define UVD_MPBE0_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define UVD_MPBE0_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define UVD_MPBE0_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define UVD_MPBE0_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define UVD_MPBE0_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define UVD_MPBE0_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define UVD_MPBE0_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//UVD_MPBE1_SUVD_CGC_GATE
+#define UVD_MPBE1_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define UVD_MPBE1_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define UVD_MPBE1_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define UVD_MPBE1_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define UVD_MPBE1_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define UVD_MPBE1_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define UVD_MPBE1_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define UVD_MPBE1_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define UVD_MPBE1_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define UVD_MPBE1_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define UVD_MPBE1_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define UVD_MPBE1_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define UVD_MPBE1_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define UVD_MPBE1_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define UVD_MPBE1_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define UVD_MPBE1_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define UVD_MPBE1_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define UVD_MPBE1_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define UVD_MPBE1_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define UVD_MPBE1_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define UVD_MPBE1_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define UVD_MPBE1_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define UVD_MPBE1_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define UVD_MPBE1_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define UVD_MPBE1_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define UVD_MPBE1_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define UVD_MPBE1_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define UVD_MPBE1_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define UVD_MPBE1_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define UVD_MPBE1_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define UVD_MPBE1_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define UVD_MPBE1_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define UVD_MPBE1_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define UVD_MPBE1_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define UVD_MPBE1_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define UVD_MPBE1_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define UVD_MPBE1_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define UVD_MPBE1_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define UVD_MPBE1_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define UVD_MPBE1_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define UVD_MPBE1_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define UVD_MPBE1_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define UVD_MPBE1_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define UVD_MPBE1_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define UVD_MPBE1_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define UVD_MPBE1_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define UVD_MPBE1_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define UVD_MPBE1_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define UVD_MPBE1_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define UVD_MPBE1_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define UVD_MPBE1_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define UVD_MPBE1_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define UVD_MPBE1_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define UVD_MPBE1_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define UVD_MPBE1_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define UVD_MPBE1_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define UVD_MPBE1_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define UVD_MPBE1_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define UVD_MPBE1_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define UVD_MPBE1_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define UVD_MPBE1_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define UVD_MPBE1_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define UVD_MPBE1_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define UVD_MPBE1_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//UVD_SUVD_CGC_GATE
+#define UVD_SUVD_CGC_GATE__SRE__SHIFT 0x0
+#define UVD_SUVD_CGC_GATE__SIT__SHIFT 0x1
+#define UVD_SUVD_CGC_GATE__SMP__SHIFT 0x2
+#define UVD_SUVD_CGC_GATE__SCM__SHIFT 0x3
+#define UVD_SUVD_CGC_GATE__SDB__SHIFT 0x4
+#define UVD_SUVD_CGC_GATE__SRE_H264__SHIFT 0x5
+#define UVD_SUVD_CGC_GATE__SRE_HEVC__SHIFT 0x6
+#define UVD_SUVD_CGC_GATE__SIT_H264__SHIFT 0x7
+#define UVD_SUVD_CGC_GATE__SIT_HEVC__SHIFT 0x8
+#define UVD_SUVD_CGC_GATE__SCM_H264__SHIFT 0x9
+#define UVD_SUVD_CGC_GATE__SCM_HEVC__SHIFT 0xa
+#define UVD_SUVD_CGC_GATE__SDB_H264__SHIFT 0xb
+#define UVD_SUVD_CGC_GATE__SDB_HEVC__SHIFT 0xc
+#define UVD_SUVD_CGC_GATE__SCLR__SHIFT 0xd
+#define UVD_SUVD_CGC_GATE__UVD_SC__SHIFT 0xe
+#define UVD_SUVD_CGC_GATE__ENT__SHIFT 0xf
+#define UVD_SUVD_CGC_GATE__IME__SHIFT 0x10
+#define UVD_SUVD_CGC_GATE__SIT_HEVC_DEC__SHIFT 0x11
+#define UVD_SUVD_CGC_GATE__SIT_HEVC_ENC__SHIFT 0x12
+#define UVD_SUVD_CGC_GATE__SITE__SHIFT 0x13
+#define UVD_SUVD_CGC_GATE__SRE_VP9__SHIFT 0x14
+#define UVD_SUVD_CGC_GATE__SCM_VP9__SHIFT 0x15
+#define UVD_SUVD_CGC_GATE__SIT_VP9_DEC__SHIFT 0x16
+#define UVD_SUVD_CGC_GATE__SDB_VP9__SHIFT 0x17
+#define UVD_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18
+#define UVD_SUVD_CGC_GATE__EFC__SHIFT 0x19
+#define UVD_SUVD_CGC_GATE__SAOE__SHIFT 0x1a
+#define UVD_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b
+#define UVD_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c
+#define UVD_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d
+#define UVD_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e
+#define UVD_SUVD_CGC_GATE__SMPA__SHIFT 0x1f
+#define UVD_SUVD_CGC_GATE__SRE_MASK 0x00000001L
+#define UVD_SUVD_CGC_GATE__SIT_MASK 0x00000002L
+#define UVD_SUVD_CGC_GATE__SMP_MASK 0x00000004L
+#define UVD_SUVD_CGC_GATE__SCM_MASK 0x00000008L
+#define UVD_SUVD_CGC_GATE__SDB_MASK 0x00000010L
+#define UVD_SUVD_CGC_GATE__SRE_H264_MASK 0x00000020L
+#define UVD_SUVD_CGC_GATE__SRE_HEVC_MASK 0x00000040L
+#define UVD_SUVD_CGC_GATE__SIT_H264_MASK 0x00000080L
+#define UVD_SUVD_CGC_GATE__SIT_HEVC_MASK 0x00000100L
+#define UVD_SUVD_CGC_GATE__SCM_H264_MASK 0x00000200L
+#define UVD_SUVD_CGC_GATE__SCM_HEVC_MASK 0x00000400L
+#define UVD_SUVD_CGC_GATE__SDB_H264_MASK 0x00000800L
+#define UVD_SUVD_CGC_GATE__SDB_HEVC_MASK 0x00001000L
+#define UVD_SUVD_CGC_GATE__SCLR_MASK 0x00002000L
+#define UVD_SUVD_CGC_GATE__UVD_SC_MASK 0x00004000L
+#define UVD_SUVD_CGC_GATE__ENT_MASK 0x00008000L
+#define UVD_SUVD_CGC_GATE__IME_MASK 0x00010000L
+#define UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 0x00020000L
+#define UVD_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 0x00040000L
+#define UVD_SUVD_CGC_GATE__SITE_MASK 0x00080000L
+#define UVD_SUVD_CGC_GATE__SRE_VP9_MASK 0x00100000L
+#define UVD_SUVD_CGC_GATE__SCM_VP9_MASK 0x00200000L
+#define UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 0x00400000L
+#define UVD_SUVD_CGC_GATE__SDB_VP9_MASK 0x00800000L
+#define UVD_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L
+#define UVD_SUVD_CGC_GATE__EFC_MASK 0x02000000L
+#define UVD_SUVD_CGC_GATE__SAOE_MASK 0x04000000L
+#define UVD_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L
+#define UVD_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L
+#define UVD_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L
+#define UVD_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L
+#define UVD_SUVD_CGC_GATE__SMPA_MASK 0x80000000L
+//AVM_SUVD_CGC_GATE2
+#define AVM_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define AVM_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define AVM_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define AVM_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define AVM_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define AVM_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define AVM_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define AVM_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define AVM_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define AVM_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define AVM_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define AVM_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define AVM_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define AVM_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define AVM_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define AVM_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define AVM_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define AVM_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define AVM_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define AVM_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define AVM_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define AVM_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define AVM_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define AVM_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//CDEFE_SUVD_CGC_GATE2
+#define CDEFE_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define CDEFE_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define CDEFE_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define CDEFE_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define CDEFE_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define CDEFE_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define CDEFE_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define CDEFE_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define CDEFE_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define CDEFE_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define CDEFE_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define CDEFE_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define CDEFE_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define CDEFE_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define CDEFE_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define CDEFE_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define CDEFE_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define CDEFE_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define CDEFE_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define CDEFE_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define CDEFE_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define CDEFE_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define CDEFE_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define CDEFE_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//DBR_SUVD_CGC_GATE2
+#define DBR_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define DBR_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define DBR_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define DBR_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define DBR_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define DBR_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define DBR_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define DBR_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define DBR_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define DBR_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define DBR_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define DBR_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define DBR_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define DBR_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define DBR_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define DBR_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define DBR_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define DBR_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define DBR_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define DBR_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define DBR_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define DBR_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define DBR_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define DBR_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//ENT_SUVD_CGC_GATE2
+#define ENT_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define ENT_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define ENT_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define ENT_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define ENT_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define ENT_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define ENT_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define ENT_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define ENT_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define ENT_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define ENT_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define ENT_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define ENT_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define ENT_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define ENT_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define ENT_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define ENT_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define ENT_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define ENT_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define ENT_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define ENT_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define ENT_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define ENT_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define ENT_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//IME_SUVD_CGC_GATE2
+#define IME_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define IME_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define IME_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define IME_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define IME_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define IME_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define IME_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define IME_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define IME_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define IME_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define IME_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define IME_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define IME_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define IME_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define IME_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define IME_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define IME_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define IME_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define IME_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define IME_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define IME_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define IME_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define IME_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define IME_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//MPC1_SUVD_CGC_GATE2
+#define MPC1_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define MPC1_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define MPC1_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define MPC1_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define MPC1_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define MPC1_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define MPC1_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define MPC1_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define MPC1_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define MPC1_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define MPC1_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define MPC1_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define MPC1_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define MPC1_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define MPC1_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define MPC1_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define MPC1_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define MPC1_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define MPC1_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define MPC1_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define MPC1_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define MPC1_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define MPC1_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define MPC1_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//SAOE_SUVD_CGC_GATE2
+#define SAOE_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define SAOE_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define SAOE_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define SAOE_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define SAOE_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define SAOE_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define SAOE_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define SAOE_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define SAOE_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define SAOE_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define SAOE_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define SAOE_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define SAOE_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define SAOE_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define SAOE_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define SAOE_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define SAOE_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define SAOE_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define SAOE_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define SAOE_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define SAOE_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define SAOE_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define SAOE_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define SAOE_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//SDB_SUVD_CGC_GATE2
+#define SDB_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define SDB_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define SDB_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define SDB_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define SDB_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define SDB_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define SDB_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define SDB_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define SDB_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define SDB_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define SDB_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define SDB_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define SDB_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define SDB_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define SDB_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define SDB_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define SDB_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define SDB_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define SDB_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define SDB_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define SDB_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define SDB_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define SDB_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define SDB_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//SIT0_NXT_SUVD_CGC_GATE2
+#define SIT0_NXT_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define SIT0_NXT_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define SIT0_NXT_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define SIT0_NXT_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define SIT0_NXT_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define SIT0_NXT_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define SIT0_NXT_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define SIT0_NXT_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define SIT0_NXT_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define SIT0_NXT_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define SIT0_NXT_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define SIT0_NXT_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define SIT0_NXT_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define SIT0_NXT_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define SIT0_NXT_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define SIT0_NXT_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define SIT0_NXT_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define SIT0_NXT_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define SIT0_NXT_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define SIT0_NXT_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define SIT0_NXT_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define SIT0_NXT_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define SIT0_NXT_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define SIT0_NXT_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//SIT1_NXT_SUVD_CGC_GATE2
+#define SIT1_NXT_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define SIT1_NXT_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define SIT1_NXT_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define SIT1_NXT_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define SIT1_NXT_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define SIT1_NXT_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define SIT1_NXT_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define SIT1_NXT_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define SIT1_NXT_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define SIT1_NXT_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define SIT1_NXT_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define SIT1_NXT_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define SIT1_NXT_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define SIT1_NXT_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define SIT1_NXT_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define SIT1_NXT_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define SIT1_NXT_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define SIT1_NXT_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define SIT1_NXT_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define SIT1_NXT_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define SIT1_NXT_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define SIT1_NXT_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define SIT1_NXT_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define SIT1_NXT_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//SIT2_NXT_SUVD_CGC_GATE2
+#define SIT2_NXT_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define SIT2_NXT_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define SIT2_NXT_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define SIT2_NXT_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define SIT2_NXT_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define SIT2_NXT_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define SIT2_NXT_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define SIT2_NXT_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define SIT2_NXT_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define SIT2_NXT_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define SIT2_NXT_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define SIT2_NXT_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define SIT2_NXT_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define SIT2_NXT_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define SIT2_NXT_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define SIT2_NXT_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define SIT2_NXT_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define SIT2_NXT_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define SIT2_NXT_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define SIT2_NXT_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define SIT2_NXT_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define SIT2_NXT_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define SIT2_NXT_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define SIT2_NXT_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//SIT_SUVD_CGC_GATE2
+#define SIT_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define SIT_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define SIT_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define SIT_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define SIT_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define SIT_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define SIT_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define SIT_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define SIT_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define SIT_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define SIT_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define SIT_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define SIT_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define SIT_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define SIT_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define SIT_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define SIT_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define SIT_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define SIT_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define SIT_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define SIT_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define SIT_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define SIT_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define SIT_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//SMPA_SUVD_CGC_GATE2
+#define SMPA_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define SMPA_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define SMPA_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define SMPA_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define SMPA_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define SMPA_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define SMPA_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define SMPA_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define SMPA_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define SMPA_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define SMPA_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define SMPA_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define SMPA_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define SMPA_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define SMPA_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define SMPA_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define SMPA_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define SMPA_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define SMPA_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define SMPA_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define SMPA_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define SMPA_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define SMPA_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define SMPA_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//SMP_SUVD_CGC_GATE2
+#define SMP_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define SMP_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define SMP_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define SMP_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define SMP_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define SMP_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define SMP_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define SMP_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define SMP_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define SMP_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define SMP_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define SMP_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define SMP_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define SMP_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define SMP_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define SMP_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define SMP_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define SMP_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define SMP_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define SMP_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define SMP_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define SMP_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define SMP_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define SMP_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//SRE_SUVD_CGC_GATE2
+#define SRE_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define SRE_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define SRE_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define SRE_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define SRE_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define SRE_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define SRE_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define SRE_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define SRE_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define SRE_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define SRE_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define SRE_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define SRE_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define SRE_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define SRE_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define SRE_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define SRE_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define SRE_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define SRE_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define SRE_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define SRE_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define SRE_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define SRE_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define SRE_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//UVD_MPBE0_SUVD_CGC_GATE2
+#define UVD_MPBE0_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define UVD_MPBE0_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define UVD_MPBE0_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define UVD_MPBE0_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define UVD_MPBE0_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define UVD_MPBE0_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define UVD_MPBE0_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define UVD_MPBE0_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define UVD_MPBE0_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define UVD_MPBE0_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define UVD_MPBE0_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define UVD_MPBE0_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define UVD_MPBE0_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define UVD_MPBE0_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+//UVD_MPBE1_SUVD_CGC_GATE2
+#define UVD_MPBE1_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define UVD_MPBE1_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define UVD_MPBE1_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define UVD_MPBE1_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define UVD_MPBE1_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define UVD_MPBE1_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define UVD_MPBE1_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define UVD_MPBE1_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define UVD_MPBE1_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define UVD_MPBE1_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define UVD_MPBE1_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define UVD_MPBE1_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define UVD_MPBE1_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define UVD_MPBE1_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+//UVD_SUVD_CGC_GATE2
+#define UVD_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0
+#define UVD_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1
+#define UVD_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2
+#define UVD_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3
+#define UVD_SUVD_CGC_GATE2__MPC1__SHIFT 0x4
+#define UVD_SUVD_CGC_GATE2__SRE_AV1_ENC__SHIFT 0x5
+#define UVD_SUVD_CGC_GATE2__CDEFE__SHIFT 0x6
+#define UVD_SUVD_CGC_GATE2__AVM_0__SHIFT 0x7
+#define UVD_SUVD_CGC_GATE2__AVM_1__SHIFT 0x8
+#define UVD_SUVD_CGC_GATE2__SIT_NXT_CMN__SHIFT 0x9
+#define UVD_SUVD_CGC_GATE2__SIT_NXT_DEC__SHIFT 0xa
+#define UVD_SUVD_CGC_GATE2__SIT_NXT_ENC__SHIFT 0xb
+#define UVD_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L
+#define UVD_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L
+#define UVD_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L
+#define UVD_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L
+#define UVD_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L
+#define UVD_SUVD_CGC_GATE2__SRE_AV1_ENC_MASK 0x00000020L
+#define UVD_SUVD_CGC_GATE2__CDEFE_MASK 0x00000040L
+#define UVD_SUVD_CGC_GATE2__AVM_0_MASK 0x00000080L
+#define UVD_SUVD_CGC_GATE2__AVM_1_MASK 0x00000100L
+#define UVD_SUVD_CGC_GATE2__SIT_NXT_CMN_MASK 0x00000200L
+#define UVD_SUVD_CGC_GATE2__SIT_NXT_DEC_MASK 0x00000400L
+#define UVD_SUVD_CGC_GATE2__SIT_NXT_ENC_MASK 0x00000800L
+//AVM_SUVD_CGC_CTRL
+#define AVM_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define AVM_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define AVM_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define AVM_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define AVM_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define AVM_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define AVM_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define AVM_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define AVM_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define AVM_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define AVM_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define AVM_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define AVM_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define AVM_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define AVM_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define AVM_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define AVM_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define AVM_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define AVM_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define AVM_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define AVM_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define AVM_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define AVM_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define AVM_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define AVM_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define AVM_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define AVM_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define AVM_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define AVM_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define AVM_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define AVM_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define AVM_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define AVM_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define AVM_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define AVM_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define AVM_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define AVM_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define AVM_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define AVM_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define AVM_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define AVM_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define AVM_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define AVM_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define AVM_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define AVM_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define AVM_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define AVM_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define AVM_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define AVM_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define AVM_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define AVM_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define AVM_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//CDEFE_SUVD_CGC_CTRL
+#define CDEFE_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define CDEFE_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define CDEFE_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define CDEFE_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define CDEFE_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define CDEFE_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define CDEFE_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define CDEFE_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define CDEFE_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define CDEFE_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define CDEFE_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define CDEFE_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define CDEFE_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define CDEFE_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define CDEFE_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define CDEFE_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define CDEFE_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define CDEFE_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define CDEFE_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define CDEFE_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define CDEFE_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define CDEFE_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define CDEFE_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define CDEFE_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define CDEFE_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define CDEFE_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define CDEFE_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define CDEFE_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define CDEFE_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define CDEFE_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define CDEFE_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define CDEFE_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define CDEFE_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define CDEFE_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define CDEFE_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define CDEFE_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define CDEFE_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define CDEFE_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define CDEFE_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define CDEFE_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define CDEFE_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define CDEFE_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define CDEFE_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define CDEFE_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define CDEFE_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define CDEFE_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define CDEFE_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define CDEFE_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define CDEFE_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define CDEFE_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define CDEFE_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define CDEFE_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//DBR_SUVD_CGC_CTRL
+#define DBR_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define DBR_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define DBR_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define DBR_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define DBR_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define DBR_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define DBR_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define DBR_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define DBR_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define DBR_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define DBR_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define DBR_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define DBR_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define DBR_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define DBR_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define DBR_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define DBR_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define DBR_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define DBR_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define DBR_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define DBR_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define DBR_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define DBR_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define DBR_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define DBR_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define DBR_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define DBR_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define DBR_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define DBR_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define DBR_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define DBR_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define DBR_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define DBR_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define DBR_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define DBR_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define DBR_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define DBR_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define DBR_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define DBR_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define DBR_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define DBR_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define DBR_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define DBR_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define DBR_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define DBR_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define DBR_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define DBR_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define DBR_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define DBR_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define DBR_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define DBR_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define DBR_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//EFC_SUVD_CGC_CTRL
+#define EFC_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define EFC_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define EFC_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define EFC_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define EFC_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define EFC_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define EFC_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define EFC_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define EFC_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define EFC_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define EFC_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define EFC_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define EFC_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define EFC_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define EFC_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define EFC_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define EFC_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define EFC_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define EFC_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define EFC_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define EFC_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define EFC_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define EFC_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define EFC_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define EFC_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define EFC_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define EFC_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define EFC_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define EFC_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define EFC_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define EFC_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define EFC_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define EFC_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define EFC_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define EFC_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define EFC_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define EFC_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define EFC_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define EFC_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define EFC_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define EFC_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define EFC_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define EFC_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define EFC_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define EFC_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define EFC_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define EFC_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define EFC_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define EFC_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define EFC_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define EFC_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define EFC_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//ENT_SUVD_CGC_CTRL
+#define ENT_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define ENT_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define ENT_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define ENT_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define ENT_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define ENT_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define ENT_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define ENT_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define ENT_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define ENT_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define ENT_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define ENT_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define ENT_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define ENT_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define ENT_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define ENT_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define ENT_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define ENT_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define ENT_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define ENT_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define ENT_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define ENT_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define ENT_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define ENT_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define ENT_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define ENT_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define ENT_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define ENT_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define ENT_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define ENT_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define ENT_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define ENT_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define ENT_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define ENT_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define ENT_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define ENT_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define ENT_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define ENT_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define ENT_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define ENT_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define ENT_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define ENT_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define ENT_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define ENT_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define ENT_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define ENT_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define ENT_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define ENT_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define ENT_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define ENT_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define ENT_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define ENT_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//IME_SUVD_CGC_CTRL
+#define IME_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define IME_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define IME_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define IME_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define IME_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define IME_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define IME_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define IME_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define IME_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define IME_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define IME_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define IME_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define IME_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define IME_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define IME_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define IME_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define IME_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define IME_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define IME_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define IME_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define IME_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define IME_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define IME_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define IME_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define IME_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define IME_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define IME_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define IME_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define IME_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define IME_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define IME_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define IME_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define IME_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define IME_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define IME_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define IME_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define IME_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define IME_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define IME_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define IME_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define IME_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define IME_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define IME_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define IME_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define IME_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define IME_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define IME_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define IME_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define IME_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define IME_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define IME_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define IME_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//MPC1_SUVD_CGC_CTRL
+#define MPC1_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define MPC1_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define MPC1_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define MPC1_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define MPC1_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define MPC1_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define MPC1_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define MPC1_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define MPC1_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define MPC1_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define MPC1_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define MPC1_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define MPC1_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define MPC1_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define MPC1_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define MPC1_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define MPC1_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define MPC1_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define MPC1_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define MPC1_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define MPC1_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define MPC1_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define MPC1_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define MPC1_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define MPC1_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define MPC1_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define MPC1_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define MPC1_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define MPC1_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define MPC1_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define MPC1_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define MPC1_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define MPC1_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define MPC1_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define MPC1_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define MPC1_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define MPC1_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define MPC1_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define MPC1_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define MPC1_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define MPC1_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define MPC1_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define MPC1_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define MPC1_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define MPC1_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define MPC1_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define MPC1_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define MPC1_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define MPC1_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define MPC1_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define MPC1_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define MPC1_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//PPU_SUVD_CGC_CTRL
+#define PPU_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define PPU_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define PPU_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define PPU_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define PPU_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define PPU_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define PPU_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define PPU_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define PPU_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define PPU_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define PPU_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define PPU_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define PPU_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define PPU_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define PPU_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define PPU_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define PPU_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define PPU_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define PPU_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define PPU_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define PPU_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define PPU_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define PPU_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define PPU_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define PPU_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define PPU_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define PPU_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define PPU_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define PPU_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define PPU_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define PPU_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define PPU_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define PPU_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define PPU_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define PPU_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define PPU_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define PPU_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define PPU_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define PPU_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define PPU_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define PPU_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define PPU_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define PPU_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define PPU_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define PPU_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define PPU_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define PPU_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define PPU_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define PPU_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define PPU_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define PPU_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define PPU_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//SAOE_SUVD_CGC_CTRL
+#define SAOE_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define SAOE_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define SAOE_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define SAOE_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define SAOE_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define SAOE_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define SAOE_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define SAOE_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define SAOE_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define SAOE_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define SAOE_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define SAOE_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define SAOE_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define SAOE_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define SAOE_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define SAOE_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define SAOE_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define SAOE_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define SAOE_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define SAOE_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define SAOE_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define SAOE_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define SAOE_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define SAOE_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define SAOE_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define SAOE_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define SAOE_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define SAOE_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define SAOE_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define SAOE_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define SAOE_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define SAOE_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define SAOE_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define SAOE_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define SAOE_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define SAOE_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define SAOE_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define SAOE_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define SAOE_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define SAOE_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define SAOE_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define SAOE_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define SAOE_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define SAOE_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define SAOE_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define SAOE_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define SAOE_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define SAOE_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define SAOE_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define SAOE_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define SAOE_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define SAOE_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//SCM_SUVD_CGC_CTRL
+#define SCM_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define SCM_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define SCM_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define SCM_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define SCM_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define SCM_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define SCM_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define SCM_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define SCM_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define SCM_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define SCM_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define SCM_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define SCM_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define SCM_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define SCM_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define SCM_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define SCM_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define SCM_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define SCM_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define SCM_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define SCM_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define SCM_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define SCM_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define SCM_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define SCM_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define SCM_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define SCM_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define SCM_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define SCM_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define SCM_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define SCM_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define SCM_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define SCM_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define SCM_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define SCM_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define SCM_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define SCM_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define SCM_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define SCM_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define SCM_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define SCM_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define SCM_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define SCM_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define SCM_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define SCM_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define SCM_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define SCM_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define SCM_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define SCM_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define SCM_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define SCM_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define SCM_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//SDB_SUVD_CGC_CTRL
+#define SDB_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define SDB_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define SDB_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define SDB_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define SDB_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define SDB_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define SDB_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define SDB_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define SDB_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define SDB_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define SDB_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define SDB_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define SDB_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define SDB_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define SDB_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define SDB_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define SDB_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define SDB_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define SDB_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define SDB_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define SDB_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define SDB_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define SDB_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define SDB_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define SDB_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define SDB_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define SDB_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define SDB_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define SDB_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define SDB_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define SDB_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define SDB_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define SDB_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define SDB_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define SDB_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define SDB_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define SDB_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define SDB_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define SDB_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define SDB_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define SDB_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define SDB_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define SDB_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define SDB_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define SDB_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define SDB_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define SDB_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define SDB_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define SDB_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define SDB_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define SDB_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define SDB_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//SIT0_NXT_SUVD_CGC_CTRL
+#define SIT0_NXT_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define SIT0_NXT_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define SIT0_NXT_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define SIT0_NXT_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define SIT0_NXT_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define SIT0_NXT_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define SIT0_NXT_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define SIT0_NXT_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define SIT0_NXT_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define SIT0_NXT_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define SIT0_NXT_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define SIT0_NXT_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define SIT0_NXT_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define SIT0_NXT_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define SIT0_NXT_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define SIT0_NXT_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define SIT0_NXT_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define SIT0_NXT_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define SIT0_NXT_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define SIT0_NXT_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define SIT0_NXT_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define SIT0_NXT_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define SIT0_NXT_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define SIT0_NXT_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define SIT0_NXT_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define SIT0_NXT_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define SIT0_NXT_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define SIT0_NXT_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define SIT0_NXT_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define SIT0_NXT_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define SIT0_NXT_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define SIT0_NXT_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define SIT0_NXT_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define SIT0_NXT_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define SIT0_NXT_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define SIT0_NXT_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define SIT0_NXT_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define SIT0_NXT_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define SIT0_NXT_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define SIT0_NXT_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define SIT0_NXT_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define SIT0_NXT_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define SIT0_NXT_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define SIT0_NXT_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define SIT0_NXT_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define SIT0_NXT_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define SIT0_NXT_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define SIT0_NXT_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define SIT0_NXT_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define SIT0_NXT_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define SIT0_NXT_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define SIT0_NXT_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//SIT1_NXT_SUVD_CGC_CTRL
+#define SIT1_NXT_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define SIT1_NXT_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define SIT1_NXT_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define SIT1_NXT_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define SIT1_NXT_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define SIT1_NXT_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define SIT1_NXT_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define SIT1_NXT_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define SIT1_NXT_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define SIT1_NXT_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define SIT1_NXT_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define SIT1_NXT_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define SIT1_NXT_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define SIT1_NXT_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define SIT1_NXT_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define SIT1_NXT_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define SIT1_NXT_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define SIT1_NXT_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define SIT1_NXT_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define SIT1_NXT_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define SIT1_NXT_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define SIT1_NXT_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define SIT1_NXT_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define SIT1_NXT_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define SIT1_NXT_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define SIT1_NXT_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define SIT1_NXT_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define SIT1_NXT_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define SIT1_NXT_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define SIT1_NXT_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define SIT1_NXT_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define SIT1_NXT_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define SIT1_NXT_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define SIT1_NXT_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define SIT1_NXT_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define SIT1_NXT_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define SIT1_NXT_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define SIT1_NXT_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define SIT1_NXT_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define SIT1_NXT_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define SIT1_NXT_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define SIT1_NXT_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define SIT1_NXT_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define SIT1_NXT_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define SIT1_NXT_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define SIT1_NXT_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define SIT1_NXT_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define SIT1_NXT_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define SIT1_NXT_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define SIT1_NXT_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define SIT1_NXT_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define SIT1_NXT_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//SIT2_NXT_SUVD_CGC_CTRL
+#define SIT2_NXT_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define SIT2_NXT_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define SIT2_NXT_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define SIT2_NXT_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define SIT2_NXT_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define SIT2_NXT_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define SIT2_NXT_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define SIT2_NXT_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define SIT2_NXT_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define SIT2_NXT_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define SIT2_NXT_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define SIT2_NXT_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define SIT2_NXT_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define SIT2_NXT_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define SIT2_NXT_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define SIT2_NXT_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define SIT2_NXT_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define SIT2_NXT_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define SIT2_NXT_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define SIT2_NXT_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define SIT2_NXT_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define SIT2_NXT_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define SIT2_NXT_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define SIT2_NXT_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define SIT2_NXT_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define SIT2_NXT_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define SIT2_NXT_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define SIT2_NXT_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define SIT2_NXT_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define SIT2_NXT_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define SIT2_NXT_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define SIT2_NXT_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define SIT2_NXT_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define SIT2_NXT_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define SIT2_NXT_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define SIT2_NXT_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define SIT2_NXT_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define SIT2_NXT_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define SIT2_NXT_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define SIT2_NXT_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define SIT2_NXT_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define SIT2_NXT_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define SIT2_NXT_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define SIT2_NXT_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define SIT2_NXT_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define SIT2_NXT_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define SIT2_NXT_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define SIT2_NXT_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define SIT2_NXT_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define SIT2_NXT_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define SIT2_NXT_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define SIT2_NXT_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//SIT_SUVD_CGC_CTRL
+#define SIT_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define SIT_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define SIT_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define SIT_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define SIT_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define SIT_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define SIT_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define SIT_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define SIT_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define SIT_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define SIT_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define SIT_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define SIT_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define SIT_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define SIT_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define SIT_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define SIT_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define SIT_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define SIT_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define SIT_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define SIT_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define SIT_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define SIT_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define SIT_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define SIT_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define SIT_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define SIT_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define SIT_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define SIT_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define SIT_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define SIT_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define SIT_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define SIT_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define SIT_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define SIT_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define SIT_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define SIT_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define SIT_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define SIT_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define SIT_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define SIT_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define SIT_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define SIT_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define SIT_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define SIT_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define SIT_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define SIT_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define SIT_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define SIT_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define SIT_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define SIT_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define SIT_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//SMPA_SUVD_CGC_CTRL
+#define SMPA_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define SMPA_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define SMPA_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define SMPA_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define SMPA_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define SMPA_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define SMPA_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define SMPA_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define SMPA_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define SMPA_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define SMPA_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define SMPA_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define SMPA_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define SMPA_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define SMPA_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define SMPA_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define SMPA_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define SMPA_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define SMPA_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define SMPA_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define SMPA_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define SMPA_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define SMPA_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define SMPA_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define SMPA_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define SMPA_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define SMPA_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define SMPA_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define SMPA_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define SMPA_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define SMPA_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define SMPA_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define SMPA_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define SMPA_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define SMPA_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define SMPA_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define SMPA_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define SMPA_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define SMPA_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define SMPA_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define SMPA_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define SMPA_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define SMPA_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define SMPA_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define SMPA_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define SMPA_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define SMPA_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define SMPA_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define SMPA_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define SMPA_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define SMPA_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define SMPA_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//SMP_SUVD_CGC_CTRL
+#define SMP_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define SMP_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define SMP_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define SMP_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define SMP_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define SMP_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define SMP_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define SMP_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define SMP_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define SMP_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define SMP_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define SMP_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define SMP_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define SMP_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define SMP_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define SMP_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define SMP_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define SMP_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define SMP_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define SMP_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define SMP_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define SMP_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define SMP_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define SMP_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define SMP_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define SMP_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define SMP_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define SMP_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define SMP_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define SMP_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define SMP_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define SMP_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define SMP_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define SMP_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define SMP_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define SMP_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define SMP_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define SMP_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define SMP_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define SMP_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define SMP_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define SMP_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define SMP_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define SMP_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define SMP_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define SMP_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define SMP_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define SMP_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define SMP_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define SMP_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define SMP_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define SMP_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//SRE_SUVD_CGC_CTRL
+#define SRE_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define SRE_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define SRE_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define SRE_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define SRE_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define SRE_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define SRE_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define SRE_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define SRE_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define SRE_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define SRE_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define SRE_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define SRE_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define SRE_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define SRE_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define SRE_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define SRE_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define SRE_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define SRE_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define SRE_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define SRE_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define SRE_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define SRE_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define SRE_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define SRE_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define SRE_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define SRE_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define SRE_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define SRE_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define SRE_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define SRE_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define SRE_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define SRE_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define SRE_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define SRE_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define SRE_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define SRE_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define SRE_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define SRE_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define SRE_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define SRE_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define SRE_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define SRE_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define SRE_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define SRE_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define SRE_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define SRE_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define SRE_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define SRE_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define SRE_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define SRE_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define SRE_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//UVD_MPBE0_SUVD_CGC_CTRL
+#define UVD_MPBE0_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define UVD_MPBE0_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define UVD_MPBE0_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define UVD_MPBE0_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define UVD_MPBE0_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define UVD_MPBE0_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define UVD_MPBE0_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define UVD_MPBE0_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define UVD_MPBE0_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define UVD_MPBE0_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define UVD_MPBE0_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define UVD_MPBE0_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define UVD_MPBE0_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define UVD_MPBE0_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define UVD_MPBE0_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define UVD_MPBE0_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define UVD_MPBE0_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define UVD_MPBE0_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define UVD_MPBE0_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define UVD_MPBE0_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define UVD_MPBE0_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define UVD_MPBE0_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define UVD_MPBE0_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define UVD_MPBE0_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define UVD_MPBE0_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define UVD_MPBE0_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define UVD_MPBE0_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define UVD_MPBE0_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define UVD_MPBE0_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define UVD_MPBE0_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define UVD_MPBE0_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define UVD_MPBE0_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define UVD_MPBE0_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define UVD_MPBE0_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define UVD_MPBE0_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define UVD_MPBE0_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define UVD_MPBE0_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define UVD_MPBE0_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define UVD_MPBE0_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define UVD_MPBE0_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define UVD_MPBE0_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define UVD_MPBE0_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//UVD_MPBE1_SUVD_CGC_CTRL
+#define UVD_MPBE1_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define UVD_MPBE1_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define UVD_MPBE1_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define UVD_MPBE1_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define UVD_MPBE1_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define UVD_MPBE1_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define UVD_MPBE1_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define UVD_MPBE1_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define UVD_MPBE1_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define UVD_MPBE1_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define UVD_MPBE1_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define UVD_MPBE1_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define UVD_MPBE1_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define UVD_MPBE1_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define UVD_MPBE1_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define UVD_MPBE1_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define UVD_MPBE1_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define UVD_MPBE1_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define UVD_MPBE1_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define UVD_MPBE1_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define UVD_MPBE1_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define UVD_MPBE1_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define UVD_MPBE1_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define UVD_MPBE1_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define UVD_MPBE1_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define UVD_MPBE1_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define UVD_MPBE1_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define UVD_MPBE1_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define UVD_MPBE1_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define UVD_MPBE1_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define UVD_MPBE1_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define UVD_MPBE1_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define UVD_MPBE1_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define UVD_MPBE1_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define UVD_MPBE1_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define UVD_MPBE1_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define UVD_MPBE1_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define UVD_MPBE1_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define UVD_MPBE1_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define UVD_MPBE1_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define UVD_MPBE1_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define UVD_MPBE1_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//UVD_SUVD_CGC_CTRL
+#define UVD_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0
+#define UVD_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1
+#define UVD_SUVD_CGC_CTRL__SMP_MODE__SHIFT 0x2
+#define UVD_SUVD_CGC_CTRL__SCM_MODE__SHIFT 0x3
+#define UVD_SUVD_CGC_CTRL__SDB_MODE__SHIFT 0x4
+#define UVD_SUVD_CGC_CTRL__SCLR_MODE__SHIFT 0x5
+#define UVD_SUVD_CGC_CTRL__UVD_SC_MODE__SHIFT 0x6
+#define UVD_SUVD_CGC_CTRL__ENT_MODE__SHIFT 0x7
+#define UVD_SUVD_CGC_CTRL__IME_MODE__SHIFT 0x8
+#define UVD_SUVD_CGC_CTRL__SITE_MODE__SHIFT 0x9
+#define UVD_SUVD_CGC_CTRL__EFC_MODE__SHIFT 0xa
+#define UVD_SUVD_CGC_CTRL__SAOE_MODE__SHIFT 0xb
+#define UVD_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc
+#define UVD_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd
+#define UVD_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe
+#define UVD_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf
+#define UVD_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10
+#define UVD_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11
+#define UVD_SUVD_CGC_CTRL__AVM_0_MODE__SHIFT 0x12
+#define UVD_SUVD_CGC_CTRL__AVM_1_MODE__SHIFT 0x13
+#define UVD_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE__SHIFT 0x14
+#define UVD_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE__SHIFT 0x15
+#define UVD_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE__SHIFT 0x16
+#define UVD_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c
+#define UVD_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d
+#define UVD_SUVD_CGC_CTRL__CDEFE_MODE__SHIFT 0x1e
+#define UVD_SUVD_CGC_CTRL__SRE_MODE_MASK 0x00000001L
+#define UVD_SUVD_CGC_CTRL__SIT_MODE_MASK 0x00000002L
+#define UVD_SUVD_CGC_CTRL__SMP_MODE_MASK 0x00000004L
+#define UVD_SUVD_CGC_CTRL__SCM_MODE_MASK 0x00000008L
+#define UVD_SUVD_CGC_CTRL__SDB_MODE_MASK 0x00000010L
+#define UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK 0x00000020L
+#define UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 0x00000040L
+#define UVD_SUVD_CGC_CTRL__ENT_MODE_MASK 0x00000080L
+#define UVD_SUVD_CGC_CTRL__IME_MODE_MASK 0x00000100L
+#define UVD_SUVD_CGC_CTRL__SITE_MODE_MASK 0x00000200L
+#define UVD_SUVD_CGC_CTRL__EFC_MODE_MASK 0x00000400L
+#define UVD_SUVD_CGC_CTRL__SAOE_MODE_MASK 0x00000800L
+#define UVD_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L
+#define UVD_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L
+#define UVD_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L
+#define UVD_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L
+#define UVD_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L
+#define UVD_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L
+#define UVD_SUVD_CGC_CTRL__AVM_0_MODE_MASK 0x00040000L
+#define UVD_SUVD_CGC_CTRL__AVM_1_MODE_MASK 0x00080000L
+#define UVD_SUVD_CGC_CTRL__SIT_NXT_CMN_MODE_MASK 0x00100000L
+#define UVD_SUVD_CGC_CTRL__SIT_NXT_DEC_MODE_MASK 0x00200000L
+#define UVD_SUVD_CGC_CTRL__SIT_NXT_ENC_MODE_MASK 0x00400000L
+#define UVD_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L
+#define UVD_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L
+#define UVD_SUVD_CGC_CTRL__CDEFE_MODE_MASK 0x40000000L
+//UVD_CGC_CTRL3
+#define UVD_CGC_CTRL3__CGC_CLK_OFF_DELAY__SHIFT 0x0
+#define UVD_CGC_CTRL3__LCM0_MODE__SHIFT 0xb
+#define UVD_CGC_CTRL3__LCM1_MODE__SHIFT 0xc
+#define UVD_CGC_CTRL3__MIF_MODE__SHIFT 0xd
+#define UVD_CGC_CTRL3__VREG_MODE__SHIFT 0xe
+#define UVD_CGC_CTRL3__PE_MODE__SHIFT 0xf
+#define UVD_CGC_CTRL3__PPU_MODE__SHIFT 0x10
+#define UVD_CGC_CTRL3__CGC_CLK_OFF_DELAY_MASK 0x000000FFL
+#define UVD_CGC_CTRL3__LCM0_MODE_MASK 0x00000800L
+#define UVD_CGC_CTRL3__LCM1_MODE_MASK 0x00001000L
+#define UVD_CGC_CTRL3__MIF_MODE_MASK 0x00002000L
+#define UVD_CGC_CTRL3__VREG_MODE_MASK 0x00004000L
+#define UVD_CGC_CTRL3__PE_MODE_MASK 0x00008000L
+#define UVD_CGC_CTRL3__PPU_MODE_MASK 0x00010000L
+//UVD_GPCOM_VCPU_DATA0
+#define UVD_GPCOM_VCPU_DATA0__DATA0__SHIFT 0x0
+#define UVD_GPCOM_VCPU_DATA0__DATA0_MASK 0xFFFFFFFFL
+//UVD_GPCOM_VCPU_DATA1
+#define UVD_GPCOM_VCPU_DATA1__DATA1__SHIFT 0x0
+#define UVD_GPCOM_VCPU_DATA1__DATA1_MASK 0xFFFFFFFFL
+//UVD_GPCOM_SYS_CMD
+#define UVD_GPCOM_SYS_CMD__CMD_SEND__SHIFT 0x0
+#define UVD_GPCOM_SYS_CMD__CMD__SHIFT 0x1
+#define UVD_GPCOM_SYS_CMD__CMD_SOURCE__SHIFT 0x1f
+#define UVD_GPCOM_SYS_CMD__CMD_SEND_MASK 0x00000001L
+#define UVD_GPCOM_SYS_CMD__CMD_MASK 0x7FFFFFFEL
+#define UVD_GPCOM_SYS_CMD__CMD_SOURCE_MASK 0x80000000L
+//UVD_GPCOM_SYS_DATA0
+#define UVD_GPCOM_SYS_DATA0__DATA0__SHIFT 0x0
+#define UVD_GPCOM_SYS_DATA0__DATA0_MASK 0xFFFFFFFFL
+//UVD_GPCOM_SYS_DATA1
+#define UVD_GPCOM_SYS_DATA1__DATA1__SHIFT 0x0
+#define UVD_GPCOM_SYS_DATA1__DATA1_MASK 0xFFFFFFFFL
+//UVD_VCPU_INT_EN
+#define UVD_VCPU_INT_EN__PIF_ADDR_ERR_EN__SHIFT 0x0
+#define UVD_VCPU_INT_EN__SEMA_WAIT_FAULT_TIMEOUT_EN__SHIFT 0x1
+#define UVD_VCPU_INT_EN__SEMA_SIGNAL_INCOMPLETE_TIMEOUT_EN__SHIFT 0x2
+#define UVD_VCPU_INT_EN__NJ_PF_RPT_EN__SHIFT 0x3
+#define UVD_VCPU_INT_EN__SW_RB1_INT_EN__SHIFT 0x4
+#define UVD_VCPU_INT_EN__SW_RB2_INT_EN__SHIFT 0x5
+#define UVD_VCPU_INT_EN__RBC_REG_PRIV_FAULT_EN__SHIFT 0x6
+#define UVD_VCPU_INT_EN__SW_RB3_INT_EN__SHIFT 0x7
+#define UVD_VCPU_INT_EN__SW_RB4_INT_EN__SHIFT 0x9
+#define UVD_VCPU_INT_EN__SW_RB5_INT_EN__SHIFT 0xa
+#define UVD_VCPU_INT_EN__LBSI_EN__SHIFT 0xb
+#define UVD_VCPU_INT_EN__UDEC_EN__SHIFT 0xc
+#define UVD_VCPU_INT_EN__LMI_AXI_UNSUPPORTED_LEN_EN__SHIFT 0xd
+#define UVD_VCPU_INT_EN__LMI_AXI_UNSUPPORTED_ADR_ALIGN_EN__SHIFT 0xe
+#define UVD_VCPU_INT_EN__SUVD_EN__SHIFT 0xf
+#define UVD_VCPU_INT_EN__RPTR_WR_EN__SHIFT 0x10
+#define UVD_VCPU_INT_EN__JOB_START_EN__SHIFT 0x11
+#define UVD_VCPU_INT_EN__NJ_PF_EN__SHIFT 0x12
+#define UVD_VCPU_INT_EN__SEMA_WAIT_FAIL_SIG_EN__SHIFT 0x17
+#define UVD_VCPU_INT_EN__IDCT_EN__SHIFT 0x18
+#define UVD_VCPU_INT_EN__MPRD_EN__SHIFT 0x19
+#define UVD_VCPU_INT_EN__AVM_INT_EN__SHIFT 0x1a
+#define UVD_VCPU_INT_EN__CLK_SWT_EN__SHIFT 0x1b
+#define UVD_VCPU_INT_EN__MIF_HWINT_EN__SHIFT 0x1c
+#define UVD_VCPU_INT_EN__MPRD_ERR_EN__SHIFT 0x1d
+#define UVD_VCPU_INT_EN__DRV_FW_REQ_EN__SHIFT 0x1e
+#define UVD_VCPU_INT_EN__DRV_FW_ACK_EN__SHIFT 0x1f
+#define UVD_VCPU_INT_EN__PIF_ADDR_ERR_EN_MASK 0x00000001L
+#define UVD_VCPU_INT_EN__SEMA_WAIT_FAULT_TIMEOUT_EN_MASK 0x00000002L
+#define UVD_VCPU_INT_EN__SEMA_SIGNAL_INCOMPLETE_TIMEOUT_EN_MASK 0x00000004L
+#define UVD_VCPU_INT_EN__NJ_PF_RPT_EN_MASK 0x00000008L
+#define UVD_VCPU_INT_EN__SW_RB1_INT_EN_MASK 0x00000010L
+#define UVD_VCPU_INT_EN__SW_RB2_INT_EN_MASK 0x00000020L
+#define UVD_VCPU_INT_EN__RBC_REG_PRIV_FAULT_EN_MASK 0x00000040L
+#define UVD_VCPU_INT_EN__SW_RB3_INT_EN_MASK 0x00000080L
+#define UVD_VCPU_INT_EN__SW_RB4_INT_EN_MASK 0x00000200L
+#define UVD_VCPU_INT_EN__SW_RB5_INT_EN_MASK 0x00000400L
+#define UVD_VCPU_INT_EN__LBSI_EN_MASK 0x00000800L
+#define UVD_VCPU_INT_EN__UDEC_EN_MASK 0x00001000L
+#define UVD_VCPU_INT_EN__LMI_AXI_UNSUPPORTED_LEN_EN_MASK 0x00002000L
+#define UVD_VCPU_INT_EN__LMI_AXI_UNSUPPORTED_ADR_ALIGN_EN_MASK 0x00004000L
+#define UVD_VCPU_INT_EN__SUVD_EN_MASK 0x00008000L
+#define UVD_VCPU_INT_EN__RPTR_WR_EN_MASK 0x00010000L
+#define UVD_VCPU_INT_EN__JOB_START_EN_MASK 0x00020000L
+#define UVD_VCPU_INT_EN__NJ_PF_EN_MASK 0x00040000L
+#define UVD_VCPU_INT_EN__SEMA_WAIT_FAIL_SIG_EN_MASK 0x00800000L
+#define UVD_VCPU_INT_EN__IDCT_EN_MASK 0x01000000L
+#define UVD_VCPU_INT_EN__MPRD_EN_MASK 0x02000000L
+#define UVD_VCPU_INT_EN__AVM_INT_EN_MASK 0x04000000L
+#define UVD_VCPU_INT_EN__CLK_SWT_EN_MASK 0x08000000L
+#define UVD_VCPU_INT_EN__MIF_HWINT_EN_MASK 0x10000000L
+#define UVD_VCPU_INT_EN__MPRD_ERR_EN_MASK 0x20000000L
+#define UVD_VCPU_INT_EN__DRV_FW_REQ_EN_MASK 0x40000000L
+#define UVD_VCPU_INT_EN__DRV_FW_ACK_EN_MASK 0x80000000L
+//UVD_VCPU_INT_STATUS
+#define UVD_VCPU_INT_STATUS__PIF_ADDR_ERR_INT__SHIFT 0x0
+#define UVD_VCPU_INT_STATUS__SEMA_WAIT_FAULT_TIMEOUT_INT__SHIFT 0x1
+#define UVD_VCPU_INT_STATUS__SEMA_SIGNAL_INCOMPLETE_TIMEOUT_INT__SHIFT 0x2
+#define UVD_VCPU_INT_STATUS__NJ_PF_RPT_INT__SHIFT 0x3
+#define UVD_VCPU_INT_STATUS__SW_RB1_INT__SHIFT 0x4
+#define UVD_VCPU_INT_STATUS__SW_RB2_INT__SHIFT 0x5
+#define UVD_VCPU_INT_STATUS__RBC_REG_PRIV_FAULT_INT__SHIFT 0x6
+#define UVD_VCPU_INT_STATUS__SW_RB3_INT__SHIFT 0x7
+#define UVD_VCPU_INT_STATUS__SW_RB4_INT__SHIFT 0x9
+#define UVD_VCPU_INT_STATUS__SW_RB5_INT__SHIFT 0xa
+#define UVD_VCPU_INT_STATUS__LBSI_INT__SHIFT 0xb
+#define UVD_VCPU_INT_STATUS__UDEC_INT__SHIFT 0xc
+#define UVD_VCPU_INT_STATUS__LMI_AXI_UNSUPPORTED_LEN_INT__SHIFT 0xd
+#define UVD_VCPU_INT_STATUS__LMI_AXI_UNSUPPORTED_ADR_ALIGN_INT__SHIFT 0xe
+#define UVD_VCPU_INT_STATUS__SUVD_INT__SHIFT 0xf
+#define UVD_VCPU_INT_STATUS__RPTR_WR_INT__SHIFT 0x10
+#define UVD_VCPU_INT_STATUS__JOB_START_INT__SHIFT 0x11
+#define UVD_VCPU_INT_STATUS__NJ_PF_INT__SHIFT 0x12
+#define UVD_VCPU_INT_STATUS__GPCOM_INT__SHIFT 0x14
+#define UVD_VCPU_INT_STATUS__SEMA_WAIT_FAIL_SIG_INT__SHIFT 0x17
+#define UVD_VCPU_INT_STATUS__IDCT_INT__SHIFT 0x18
+#define UVD_VCPU_INT_STATUS__MPRD_INT__SHIFT 0x19
+#define UVD_VCPU_INT_STATUS__AVM_INT__SHIFT 0x1a
+#define UVD_VCPU_INT_STATUS__CLK_SWT_INT__SHIFT 0x1b
+#define UVD_VCPU_INT_STATUS__MIF_HWINT__SHIFT 0x1c
+#define UVD_VCPU_INT_STATUS__MPRD_ERR_INT__SHIFT 0x1d
+#define UVD_VCPU_INT_STATUS__DRV_FW_REQ_INT__SHIFT 0x1e
+#define UVD_VCPU_INT_STATUS__DRV_FW_ACK_INT__SHIFT 0x1f
+#define UVD_VCPU_INT_STATUS__PIF_ADDR_ERR_INT_MASK 0x00000001L
+#define UVD_VCPU_INT_STATUS__SEMA_WAIT_FAULT_TIMEOUT_INT_MASK 0x00000002L
+#define UVD_VCPU_INT_STATUS__SEMA_SIGNAL_INCOMPLETE_TIMEOUT_INT_MASK 0x00000004L
+#define UVD_VCPU_INT_STATUS__NJ_PF_RPT_INT_MASK 0x00000008L
+#define UVD_VCPU_INT_STATUS__SW_RB1_INT_MASK 0x00000010L
+#define UVD_VCPU_INT_STATUS__SW_RB2_INT_MASK 0x00000020L
+#define UVD_VCPU_INT_STATUS__RBC_REG_PRIV_FAULT_INT_MASK 0x00000040L
+#define UVD_VCPU_INT_STATUS__SW_RB3_INT_MASK 0x00000080L
+#define UVD_VCPU_INT_STATUS__SW_RB4_INT_MASK 0x00000200L
+#define UVD_VCPU_INT_STATUS__SW_RB5_INT_MASK 0x00000400L
+#define UVD_VCPU_INT_STATUS__LBSI_INT_MASK 0x00000800L
+#define UVD_VCPU_INT_STATUS__UDEC_INT_MASK 0x00001000L
+#define UVD_VCPU_INT_STATUS__LMI_AXI_UNSUPPORTED_LEN_INT_MASK 0x00002000L
+#define UVD_VCPU_INT_STATUS__LMI_AXI_UNSUPPORTED_ADR_ALIGN_INT_MASK 0x00004000L
+#define UVD_VCPU_INT_STATUS__SUVD_INT_MASK 0x00008000L
+#define UVD_VCPU_INT_STATUS__RPTR_WR_INT_MASK 0x00010000L
+#define UVD_VCPU_INT_STATUS__JOB_START_INT_MASK 0x00020000L
+#define UVD_VCPU_INT_STATUS__NJ_PF_INT_MASK 0x00040000L
+#define UVD_VCPU_INT_STATUS__GPCOM_INT_MASK 0x00100000L
+#define UVD_VCPU_INT_STATUS__SEMA_WAIT_FAIL_SIG_INT_MASK 0x00800000L
+#define UVD_VCPU_INT_STATUS__IDCT_INT_MASK 0x01000000L
+#define UVD_VCPU_INT_STATUS__MPRD_INT_MASK 0x02000000L
+#define UVD_VCPU_INT_STATUS__AVM_INT_MASK 0x04000000L
+#define UVD_VCPU_INT_STATUS__CLK_SWT_INT_MASK 0x08000000L
+#define UVD_VCPU_INT_STATUS__MIF_HWINT_MASK 0x10000000L
+#define UVD_VCPU_INT_STATUS__MPRD_ERR_INT_MASK 0x20000000L
+#define UVD_VCPU_INT_STATUS__DRV_FW_REQ_INT_MASK 0x40000000L
+#define UVD_VCPU_INT_STATUS__DRV_FW_ACK_INT_MASK 0x80000000L
+//UVD_VCPU_INT_ACK
+#define UVD_VCPU_INT_ACK__PIF_ADDR_ERR_ACK__SHIFT 0x0
+#define UVD_VCPU_INT_ACK__SEMA_WAIT_FAULT_TIMEOUT_ACK__SHIFT 0x1
+#define UVD_VCPU_INT_ACK__SEMA_SIGNAL_INCOMPLETE_TIMEOUT_ACK__SHIFT 0x2
+#define UVD_VCPU_INT_ACK__NJ_PF_RPT_ACK__SHIFT 0x3
+#define UVD_VCPU_INT_ACK__SW_RB1_INT_ACK__SHIFT 0x4
+#define UVD_VCPU_INT_ACK__SW_RB2_INT_ACK__SHIFT 0x5
+#define UVD_VCPU_INT_ACK__RBC_REG_PRIV_FAULT_ACK__SHIFT 0x6
+#define UVD_VCPU_INT_ACK__SW_RB3_INT_ACK__SHIFT 0x7
+#define UVD_VCPU_INT_ACK__SW_RB4_INT_ACK__SHIFT 0x9
+#define UVD_VCPU_INT_ACK__SW_RB5_INT_ACK__SHIFT 0xa
+#define UVD_VCPU_INT_ACK__LBSI_ACK__SHIFT 0xb
+#define UVD_VCPU_INT_ACK__UDEC_ACK__SHIFT 0xc
+#define UVD_VCPU_INT_ACK__LMI_AXI_UNSUPPORTED_LEN_ACK__SHIFT 0xd
+#define UVD_VCPU_INT_ACK__LMI_AXI_UNSUPPORTED_ADR_ALIGN_ACK__SHIFT 0xe
+#define UVD_VCPU_INT_ACK__SUVD_ACK__SHIFT 0xf
+#define UVD_VCPU_INT_ACK__RPTR_WR_ACK__SHIFT 0x10
+#define UVD_VCPU_INT_ACK__JOB_START_ACK__SHIFT 0x11
+#define UVD_VCPU_INT_ACK__NJ_PF_ACK__SHIFT 0x12
+#define UVD_VCPU_INT_ACK__SEMA_WAIT_FAIL_SIG_ACK__SHIFT 0x17
+#define UVD_VCPU_INT_ACK__IDCT_ACK__SHIFT 0x18
+#define UVD_VCPU_INT_ACK__MPRD_ACK__SHIFT 0x19
+#define UVD_VCPU_INT_ACK__AVM_INT_ACK__SHIFT 0x1a
+#define UVD_VCPU_INT_ACK__CLK_SWT_ACK__SHIFT 0x1b
+#define UVD_VCPU_INT_ACK__MIF_HWINT_ACK__SHIFT 0x1c
+#define UVD_VCPU_INT_ACK__MPRD_ERR_ACK__SHIFT 0x1d
+#define UVD_VCPU_INT_ACK__DRV_FW_REQ_ACK__SHIFT 0x1e
+#define UVD_VCPU_INT_ACK__DRV_FW_ACK_ACK__SHIFT 0x1f
+#define UVD_VCPU_INT_ACK__PIF_ADDR_ERR_ACK_MASK 0x00000001L
+#define UVD_VCPU_INT_ACK__SEMA_WAIT_FAULT_TIMEOUT_ACK_MASK 0x00000002L
+#define UVD_VCPU_INT_ACK__SEMA_SIGNAL_INCOMPLETE_TIMEOUT_ACK_MASK 0x00000004L
+#define UVD_VCPU_INT_ACK__NJ_PF_RPT_ACK_MASK 0x00000008L
+#define UVD_VCPU_INT_ACK__SW_RB1_INT_ACK_MASK 0x00000010L
+#define UVD_VCPU_INT_ACK__SW_RB2_INT_ACK_MASK 0x00000020L
+#define UVD_VCPU_INT_ACK__RBC_REG_PRIV_FAULT_ACK_MASK 0x00000040L
+#define UVD_VCPU_INT_ACK__SW_RB3_INT_ACK_MASK 0x00000080L
+#define UVD_VCPU_INT_ACK__SW_RB4_INT_ACK_MASK 0x00000200L
+#define UVD_VCPU_INT_ACK__SW_RB5_INT_ACK_MASK 0x00000400L
+#define UVD_VCPU_INT_ACK__LBSI_ACK_MASK 0x00000800L
+#define UVD_VCPU_INT_ACK__UDEC_ACK_MASK 0x00001000L
+#define UVD_VCPU_INT_ACK__LMI_AXI_UNSUPPORTED_LEN_ACK_MASK 0x00002000L
+#define UVD_VCPU_INT_ACK__LMI_AXI_UNSUPPORTED_ADR_ALIGN_ACK_MASK 0x00004000L
+#define UVD_VCPU_INT_ACK__SUVD_ACK_MASK 0x00008000L
+#define UVD_VCPU_INT_ACK__RPTR_WR_ACK_MASK 0x00010000L
+#define UVD_VCPU_INT_ACK__JOB_START_ACK_MASK 0x00020000L
+#define UVD_VCPU_INT_ACK__NJ_PF_ACK_MASK 0x00040000L
+#define UVD_VCPU_INT_ACK__SEMA_WAIT_FAIL_SIG_ACK_MASK 0x00800000L
+#define UVD_VCPU_INT_ACK__IDCT_ACK_MASK 0x01000000L
+#define UVD_VCPU_INT_ACK__MPRD_ACK_MASK 0x02000000L
+#define UVD_VCPU_INT_ACK__AVM_INT_ACK_MASK 0x04000000L
+#define UVD_VCPU_INT_ACK__CLK_SWT_ACK_MASK 0x08000000L
+#define UVD_VCPU_INT_ACK__MIF_HWINT_ACK_MASK 0x10000000L
+#define UVD_VCPU_INT_ACK__MPRD_ERR_ACK_MASK 0x20000000L
+#define UVD_VCPU_INT_ACK__DRV_FW_REQ_ACK_MASK 0x40000000L
+#define UVD_VCPU_INT_ACK__DRV_FW_ACK_ACK_MASK 0x80000000L
+//UVD_VCPU_INT_ROUTE
+#define UVD_VCPU_INT_ROUTE__DRV_FW_MSG__SHIFT 0x0
+#define UVD_VCPU_INT_ROUTE__FW_DRV_MSG_ACK__SHIFT 0x1
+#define UVD_VCPU_INT_ROUTE__VCPU_GPCOM__SHIFT 0x2
+#define UVD_VCPU_INT_ROUTE__DRV_FW_MSG_MASK 0x00000001L
+#define UVD_VCPU_INT_ROUTE__FW_DRV_MSG_ACK_MASK 0x00000002L
+#define UVD_VCPU_INT_ROUTE__VCPU_GPCOM_MASK 0x00000004L
+//UVD_DRV_FW_MSG
+#define UVD_DRV_FW_MSG__MSG__SHIFT 0x0
+#define UVD_DRV_FW_MSG__MSG_MASK 0xFFFFFFFFL
+//UVD_FW_DRV_MSG_ACK
+#define UVD_FW_DRV_MSG_ACK__ACK__SHIFT 0x0
+#define UVD_FW_DRV_MSG_ACK__ACK_MASK 0x00000001L
+//UVD_SUVD_INT_EN
+#define UVD_SUVD_INT_EN__SRE_FUNC_INT_EN__SHIFT 0x0
+#define UVD_SUVD_INT_EN__SRE_ERR_INT_EN__SHIFT 0x5
+#define UVD_SUVD_INT_EN__SIT_FUNC_INT_EN__SHIFT 0x6
+#define UVD_SUVD_INT_EN__SIT_ERR_INT_EN__SHIFT 0xb
+#define UVD_SUVD_INT_EN__SMP_FUNC_INT_EN__SHIFT 0xc
+#define UVD_SUVD_INT_EN__SMP_ERR_INT_EN__SHIFT 0x11
+#define UVD_SUVD_INT_EN__SCM_FUNC_INT_EN__SHIFT 0x12
+#define UVD_SUVD_INT_EN__SCM_ERR_INT_EN__SHIFT 0x17
+#define UVD_SUVD_INT_EN__SDB_FUNC_INT_EN__SHIFT 0x18
+#define UVD_SUVD_INT_EN__SDB_ERR_INT_EN__SHIFT 0x1d
+#define UVD_SUVD_INT_EN__FBC_ERR_INT_EN__SHIFT 0x1e
+#define UVD_SUVD_INT_EN__SRE_FUNC_INT_EN_MASK 0x0000001FL
+#define UVD_SUVD_INT_EN__SRE_ERR_INT_EN_MASK 0x00000020L
+#define UVD_SUVD_INT_EN__SIT_FUNC_INT_EN_MASK 0x000007C0L
+#define UVD_SUVD_INT_EN__SIT_ERR_INT_EN_MASK 0x00000800L
+#define UVD_SUVD_INT_EN__SMP_FUNC_INT_EN_MASK 0x0001F000L
+#define UVD_SUVD_INT_EN__SMP_ERR_INT_EN_MASK 0x00020000L
+#define UVD_SUVD_INT_EN__SCM_FUNC_INT_EN_MASK 0x007C0000L
+#define UVD_SUVD_INT_EN__SCM_ERR_INT_EN_MASK 0x00800000L
+#define UVD_SUVD_INT_EN__SDB_FUNC_INT_EN_MASK 0x1F000000L
+#define UVD_SUVD_INT_EN__SDB_ERR_INT_EN_MASK 0x20000000L
+#define UVD_SUVD_INT_EN__FBC_ERR_INT_EN_MASK 0x40000000L
+//UVD_SUVD_INT_STATUS
+#define UVD_SUVD_INT_STATUS__SRE_FUNC_INT__SHIFT 0x0
+#define UVD_SUVD_INT_STATUS__SRE_ERR_INT__SHIFT 0x5
+#define UVD_SUVD_INT_STATUS__SIT_FUNC_INT__SHIFT 0x6
+#define UVD_SUVD_INT_STATUS__SIT_ERR_INT__SHIFT 0xb
+#define UVD_SUVD_INT_STATUS__SMP_FUNC_INT__SHIFT 0xc
+#define UVD_SUVD_INT_STATUS__SMP_ERR_INT__SHIFT 0x11
+#define UVD_SUVD_INT_STATUS__SCM_FUNC_INT__SHIFT 0x12
+#define UVD_SUVD_INT_STATUS__SCM_ERR_INT__SHIFT 0x17
+#define UVD_SUVD_INT_STATUS__SDB_FUNC_INT__SHIFT 0x18
+#define UVD_SUVD_INT_STATUS__SDB_ERR_INT__SHIFT 0x1d
+#define UVD_SUVD_INT_STATUS__FBC_ERR_INT__SHIFT 0x1e
+#define UVD_SUVD_INT_STATUS__SRE_FUNC_INT_MASK 0x0000001FL
+#define UVD_SUVD_INT_STATUS__SRE_ERR_INT_MASK 0x00000020L
+#define UVD_SUVD_INT_STATUS__SIT_FUNC_INT_MASK 0x000007C0L
+#define UVD_SUVD_INT_STATUS__SIT_ERR_INT_MASK 0x00000800L
+#define UVD_SUVD_INT_STATUS__SMP_FUNC_INT_MASK 0x0001F000L
+#define UVD_SUVD_INT_STATUS__SMP_ERR_INT_MASK 0x00020000L
+#define UVD_SUVD_INT_STATUS__SCM_FUNC_INT_MASK 0x007C0000L
+#define UVD_SUVD_INT_STATUS__SCM_ERR_INT_MASK 0x00800000L
+#define UVD_SUVD_INT_STATUS__SDB_FUNC_INT_MASK 0x1F000000L
+#define UVD_SUVD_INT_STATUS__SDB_ERR_INT_MASK 0x20000000L
+#define UVD_SUVD_INT_STATUS__FBC_ERR_INT_MASK 0x40000000L
+//UVD_SUVD_INT_ACK
+#define UVD_SUVD_INT_ACK__SRE_FUNC_INT_ACK__SHIFT 0x0
+#define UVD_SUVD_INT_ACK__SRE_ERR_INT_ACK__SHIFT 0x5
+#define UVD_SUVD_INT_ACK__SIT_FUNC_INT_ACK__SHIFT 0x6
+#define UVD_SUVD_INT_ACK__SIT_ERR_INT_ACK__SHIFT 0xb
+#define UVD_SUVD_INT_ACK__SMP_FUNC_INT_ACK__SHIFT 0xc
+#define UVD_SUVD_INT_ACK__SMP_ERR_INT_ACK__SHIFT 0x11
+#define UVD_SUVD_INT_ACK__SCM_FUNC_INT_ACK__SHIFT 0x12
+#define UVD_SUVD_INT_ACK__SCM_ERR_INT_ACK__SHIFT 0x17
+#define UVD_SUVD_INT_ACK__SDB_FUNC_INT_ACK__SHIFT 0x18
+#define UVD_SUVD_INT_ACK__SDB_ERR_INT_ACK__SHIFT 0x1d
+#define UVD_SUVD_INT_ACK__FBC_ERR_INT_ACK__SHIFT 0x1e
+#define UVD_SUVD_INT_ACK__SRE_FUNC_INT_ACK_MASK 0x0000001FL
+#define UVD_SUVD_INT_ACK__SRE_ERR_INT_ACK_MASK 0x00000020L
+#define UVD_SUVD_INT_ACK__SIT_FUNC_INT_ACK_MASK 0x000007C0L
+#define UVD_SUVD_INT_ACK__SIT_ERR_INT_ACK_MASK 0x00000800L
+#define UVD_SUVD_INT_ACK__SMP_FUNC_INT_ACK_MASK 0x0001F000L
+#define UVD_SUVD_INT_ACK__SMP_ERR_INT_ACK_MASK 0x00020000L
+#define UVD_SUVD_INT_ACK__SCM_FUNC_INT_ACK_MASK 0x007C0000L
+#define UVD_SUVD_INT_ACK__SCM_ERR_INT_ACK_MASK 0x00800000L
+#define UVD_SUVD_INT_ACK__SDB_FUNC_INT_ACK_MASK 0x1F000000L
+#define UVD_SUVD_INT_ACK__SDB_ERR_INT_ACK_MASK 0x20000000L
+#define UVD_SUVD_INT_ACK__FBC_ERR_INT_ACK_MASK 0x40000000L
+//UVD_ENC_VCPU_INT_EN
+#define UVD_ENC_VCPU_INT_EN__DCE_UVD_SCAN_IN_BUFMGR_EN__SHIFT 0x0
+#define UVD_ENC_VCPU_INT_EN__DCE_UVD_SCAN_IN_BUFMGR2_EN__SHIFT 0x1
+#define UVD_ENC_VCPU_INT_EN__DCE_UVD_SCAN_IN_BUFMGR3_EN__SHIFT 0x2
+#define UVD_ENC_VCPU_INT_EN__DCE_UVD_SCAN_IN_BUFMGR_EN_MASK 0x00000001L
+#define UVD_ENC_VCPU_INT_EN__DCE_UVD_SCAN_IN_BUFMGR2_EN_MASK 0x00000002L
+#define UVD_ENC_VCPU_INT_EN__DCE_UVD_SCAN_IN_BUFMGR3_EN_MASK 0x00000004L
+//UVD_ENC_VCPU_INT_STATUS
+#define UVD_ENC_VCPU_INT_STATUS__DCE_UVD_SCAN_IN_BUFMGR_INT__SHIFT 0x0
+#define UVD_ENC_VCPU_INT_STATUS__DCE_UVD_SCAN_IN_BUFMGR2_INT__SHIFT 0x1
+#define UVD_ENC_VCPU_INT_STATUS__DCE_UVD_SCAN_IN_BUFMGR3_INT__SHIFT 0x2
+#define UVD_ENC_VCPU_INT_STATUS__DCE_UVD_SCAN_IN_BUFMGR_INT_MASK 0x00000001L
+#define UVD_ENC_VCPU_INT_STATUS__DCE_UVD_SCAN_IN_BUFMGR2_INT_MASK 0x00000002L
+#define UVD_ENC_VCPU_INT_STATUS__DCE_UVD_SCAN_IN_BUFMGR3_INT_MASK 0x00000004L
+//UVD_ENC_VCPU_INT_ACK
+#define UVD_ENC_VCPU_INT_ACK__DCE_UVD_SCAN_IN_BUFMGR_ACK__SHIFT 0x0
+#define UVD_ENC_VCPU_INT_ACK__DCE_UVD_SCAN_IN_BUFMGR2_ACK__SHIFT 0x1
+#define UVD_ENC_VCPU_INT_ACK__DCE_UVD_SCAN_IN_BUFMGR3_ACK__SHIFT 0x2
+#define UVD_ENC_VCPU_INT_ACK__DCE_UVD_SCAN_IN_BUFMGR_ACK_MASK 0x00000001L
+#define UVD_ENC_VCPU_INT_ACK__DCE_UVD_SCAN_IN_BUFMGR2_ACK_MASK 0x00000002L
+#define UVD_ENC_VCPU_INT_ACK__DCE_UVD_SCAN_IN_BUFMGR3_ACK_MASK 0x00000004L
+//UVD_MASTINT_EN
+#define UVD_MASTINT_EN__OVERRUN_RST__SHIFT 0x0
+#define UVD_MASTINT_EN__VCPU_EN__SHIFT 0x1
+#define UVD_MASTINT_EN__SYS_EN__SHIFT 0x2
+#define UVD_MASTINT_EN__INT_OVERRUN__SHIFT 0x4
+#define UVD_MASTINT_EN__OVERRUN_RST_MASK 0x00000001L
+#define UVD_MASTINT_EN__VCPU_EN_MASK 0x00000002L
+#define UVD_MASTINT_EN__SYS_EN_MASK 0x00000004L
+#define UVD_MASTINT_EN__INT_OVERRUN_MASK 0x00FFFFF0L
+//UVD_SYS_INT_EN
+#define UVD_SYS_INT_EN__PIF_ADDR_ERR_EN__SHIFT 0x0
+#define UVD_SYS_INT_EN__SEMA_WAIT_FAULT_TIMEOUT_EN__SHIFT 0x1
+#define UVD_SYS_INT_EN__SEMA_SIGNAL_INCOMPLETE_TIMEOUT_EN__SHIFT 0x2
+#define UVD_SYS_INT_EN__CXW_WR_EN__SHIFT 0x3
+#define UVD_SYS_INT_EN__RBC_REG_PRIV_FAULT_EN__SHIFT 0x6
+#define UVD_SYS_INT_EN__LBSI_EN__SHIFT 0xb
+#define UVD_SYS_INT_EN__UDEC_EN__SHIFT 0xc
+#define UVD_SYS_INT_EN__LMI_AXI_UNSUPPORTED_LEN_EN__SHIFT 0xd
+#define UVD_SYS_INT_EN__LMI_AXI_UNSUPPORTED_ADR_ALIGN_EN__SHIFT 0xe
+#define UVD_SYS_INT_EN__SUVD_EN__SHIFT 0xf
+#define UVD_SYS_INT_EN__JOB_DONE_EN__SHIFT 0x10
+#define UVD_SYS_INT_EN__SEMA_WAIT_FAIL_SIG_EN__SHIFT 0x17
+#define UVD_SYS_INT_EN__IDCT_EN__SHIFT 0x18
+#define UVD_SYS_INT_EN__MPRD_EN__SHIFT 0x19
+#define UVD_SYS_INT_EN__RASCNTL_VCPU_VCODEC_EN__SHIFT 0x1a
+#define UVD_SYS_INT_EN__CLK_SWT_EN__SHIFT 0x1b
+#define UVD_SYS_INT_EN__MIF_HWINT_EN__SHIFT 0x1c
+#define UVD_SYS_INT_EN__MPRD_ERR_EN__SHIFT 0x1d
+#define UVD_SYS_INT_EN__AVM_INT_EN__SHIFT 0x1f
+#define UVD_SYS_INT_EN__PIF_ADDR_ERR_EN_MASK 0x00000001L
+#define UVD_SYS_INT_EN__SEMA_WAIT_FAULT_TIMEOUT_EN_MASK 0x00000002L
+#define UVD_SYS_INT_EN__SEMA_SIGNAL_INCOMPLETE_TIMEOUT_EN_MASK 0x00000004L
+#define UVD_SYS_INT_EN__CXW_WR_EN_MASK 0x00000008L
+#define UVD_SYS_INT_EN__RBC_REG_PRIV_FAULT_EN_MASK 0x00000040L
+#define UVD_SYS_INT_EN__LBSI_EN_MASK 0x00000800L
+#define UVD_SYS_INT_EN__UDEC_EN_MASK 0x00001000L
+#define UVD_SYS_INT_EN__LMI_AXI_UNSUPPORTED_LEN_EN_MASK 0x00002000L
+#define UVD_SYS_INT_EN__LMI_AXI_UNSUPPORTED_ADR_ALIGN_EN_MASK 0x00004000L
+#define UVD_SYS_INT_EN__SUVD_EN_MASK 0x00008000L
+#define UVD_SYS_INT_EN__JOB_DONE_EN_MASK 0x00010000L
+#define UVD_SYS_INT_EN__SEMA_WAIT_FAIL_SIG_EN_MASK 0x00800000L
+#define UVD_SYS_INT_EN__IDCT_EN_MASK 0x01000000L
+#define UVD_SYS_INT_EN__MPRD_EN_MASK 0x02000000L
+#define UVD_SYS_INT_EN__RASCNTL_VCPU_VCODEC_EN_MASK 0x04000000L
+#define UVD_SYS_INT_EN__CLK_SWT_EN_MASK 0x08000000L
+#define UVD_SYS_INT_EN__MIF_HWINT_EN_MASK 0x10000000L
+#define UVD_SYS_INT_EN__MPRD_ERR_EN_MASK 0x20000000L
+#define UVD_SYS_INT_EN__AVM_INT_EN_MASK 0x80000000L
+//UVD_SYS_INT_STATUS
+#define UVD_SYS_INT_STATUS__PIF_ADDR_ERR_INT__SHIFT 0x0
+#define UVD_SYS_INT_STATUS__SEMA_WAIT_FAULT_TIMEOUT_INT__SHIFT 0x1
+#define UVD_SYS_INT_STATUS__SEMA_SIGNAL_INCOMPLETE_TIMEOUT_INT__SHIFT 0x2
+#define UVD_SYS_INT_STATUS__CXW_WR_INT__SHIFT 0x3
+#define UVD_SYS_INT_STATUS__RBC_REG_PRIV_FAULT_INT__SHIFT 0x6
+#define UVD_SYS_INT_STATUS__LBSI_INT__SHIFT 0xb
+#define UVD_SYS_INT_STATUS__UDEC_INT__SHIFT 0xc
+#define UVD_SYS_INT_STATUS__LMI_AXI_UNSUPPORTED_LEN_INT__SHIFT 0xd
+#define UVD_SYS_INT_STATUS__LMI_AXI_UNSUPPORTED_ADR_ALIGN_INT__SHIFT 0xe
+#define UVD_SYS_INT_STATUS__SUVD_INT__SHIFT 0xf
+#define UVD_SYS_INT_STATUS__JOB_DONE_INT__SHIFT 0x10
+#define UVD_SYS_INT_STATUS__GPCOM_INT__SHIFT 0x12
+#define UVD_SYS_INT_STATUS__SEMA_WAIT_FAIL_SIG_INT__SHIFT 0x17
+#define UVD_SYS_INT_STATUS__IDCT_INT__SHIFT 0x18
+#define UVD_SYS_INT_STATUS__MPRD_INT__SHIFT 0x19
+#define UVD_SYS_INT_STATUS__CLK_SWT_INT__SHIFT 0x1b
+#define UVD_SYS_INT_STATUS__MIF_HWINT__SHIFT 0x1c
+#define UVD_SYS_INT_STATUS__MPRD_ERR_INT__SHIFT 0x1d
+#define UVD_SYS_INT_STATUS__RASCNTL_VCPU_VCODEC_INT__SHIFT 0x1e
+#define UVD_SYS_INT_STATUS__AVM_INT__SHIFT 0x1f
+#define UVD_SYS_INT_STATUS__PIF_ADDR_ERR_INT_MASK 0x00000001L
+#define UVD_SYS_INT_STATUS__SEMA_WAIT_FAULT_TIMEOUT_INT_MASK 0x00000002L
+#define UVD_SYS_INT_STATUS__SEMA_SIGNAL_INCOMPLETE_TIMEOUT_INT_MASK 0x00000004L
+#define UVD_SYS_INT_STATUS__CXW_WR_INT_MASK 0x00000008L
+#define UVD_SYS_INT_STATUS__RBC_REG_PRIV_FAULT_INT_MASK 0x00000040L
+#define UVD_SYS_INT_STATUS__LBSI_INT_MASK 0x00000800L
+#define UVD_SYS_INT_STATUS__UDEC_INT_MASK 0x00001000L
+#define UVD_SYS_INT_STATUS__LMI_AXI_UNSUPPORTED_LEN_INT_MASK 0x00002000L
+#define UVD_SYS_INT_STATUS__LMI_AXI_UNSUPPORTED_ADR_ALIGN_INT_MASK 0x00004000L
+#define UVD_SYS_INT_STATUS__SUVD_INT_MASK 0x00008000L
+#define UVD_SYS_INT_STATUS__JOB_DONE_INT_MASK 0x00010000L
+#define UVD_SYS_INT_STATUS__GPCOM_INT_MASK 0x00040000L
+#define UVD_SYS_INT_STATUS__SEMA_WAIT_FAIL_SIG_INT_MASK 0x00800000L
+#define UVD_SYS_INT_STATUS__IDCT_INT_MASK 0x01000000L
+#define UVD_SYS_INT_STATUS__MPRD_INT_MASK 0x02000000L
+#define UVD_SYS_INT_STATUS__CLK_SWT_INT_MASK 0x08000000L
+#define UVD_SYS_INT_STATUS__MIF_HWINT_MASK 0x10000000L
+#define UVD_SYS_INT_STATUS__MPRD_ERR_INT_MASK 0x20000000L
+#define UVD_SYS_INT_STATUS__RASCNTL_VCPU_VCODEC_INT_MASK 0x40000000L
+#define UVD_SYS_INT_STATUS__AVM_INT_MASK 0x80000000L
+//UVD_SYS_INT_ACK
+#define UVD_SYS_INT_ACK__PIF_ADDR_ERR_ACK__SHIFT 0x0
+#define UVD_SYS_INT_ACK__SEMA_WAIT_FAULT_TIMEOUT_ACK__SHIFT 0x1
+#define UVD_SYS_INT_ACK__SEMA_SIGNAL_INCOMPLETE_TIMEOUT_ACK__SHIFT 0x2
+#define UVD_SYS_INT_ACK__CXW_WR_ACK__SHIFT 0x3
+#define UVD_SYS_INT_ACK__RBC_REG_PRIV_FAULT_ACK__SHIFT 0x6
+#define UVD_SYS_INT_ACK__LBSI_ACK__SHIFT 0xb
+#define UVD_SYS_INT_ACK__UDEC_ACK__SHIFT 0xc
+#define UVD_SYS_INT_ACK__LMI_AXI_UNSUPPORTED_LEN_ACK__SHIFT 0xd
+#define UVD_SYS_INT_ACK__LMI_AXI_UNSUPPORTED_ADR_ALIGN_ACK__SHIFT 0xe
+#define UVD_SYS_INT_ACK__SUVD_ACK__SHIFT 0xf
+#define UVD_SYS_INT_ACK__JOB_DONE_ACK__SHIFT 0x10
+#define UVD_SYS_INT_ACK__SEMA_WAIT_FAIL_SIG_ACK__SHIFT 0x17
+#define UVD_SYS_INT_ACK__IDCT_ACK__SHIFT 0x18
+#define UVD_SYS_INT_ACK__MPRD_ACK__SHIFT 0x19
+#define UVD_SYS_INT_ACK__CLK_SWT_ACK__SHIFT 0x1b
+#define UVD_SYS_INT_ACK__MIF_HWINT_ACK__SHIFT 0x1c
+#define UVD_SYS_INT_ACK__MPRD_ERR_ACK__SHIFT 0x1d
+#define UVD_SYS_INT_ACK__RASCNTL_VCPU_VCODEC_ACK__SHIFT 0x1e
+#define UVD_SYS_INT_ACK__AVM_INT_ACK__SHIFT 0x1f
+#define UVD_SYS_INT_ACK__PIF_ADDR_ERR_ACK_MASK 0x00000001L
+#define UVD_SYS_INT_ACK__SEMA_WAIT_FAULT_TIMEOUT_ACK_MASK 0x00000002L
+#define UVD_SYS_INT_ACK__SEMA_SIGNAL_INCOMPLETE_TIMEOUT_ACK_MASK 0x00000004L
+#define UVD_SYS_INT_ACK__CXW_WR_ACK_MASK 0x00000008L
+#define UVD_SYS_INT_ACK__RBC_REG_PRIV_FAULT_ACK_MASK 0x00000040L
+#define UVD_SYS_INT_ACK__LBSI_ACK_MASK 0x00000800L
+#define UVD_SYS_INT_ACK__UDEC_ACK_MASK 0x00001000L
+#define UVD_SYS_INT_ACK__LMI_AXI_UNSUPPORTED_LEN_ACK_MASK 0x00002000L
+#define UVD_SYS_INT_ACK__LMI_AXI_UNSUPPORTED_ADR_ALIGN_ACK_MASK 0x00004000L
+#define UVD_SYS_INT_ACK__SUVD_ACK_MASK 0x00008000L
+#define UVD_SYS_INT_ACK__JOB_DONE_ACK_MASK 0x00010000L
+#define UVD_SYS_INT_ACK__SEMA_WAIT_FAIL_SIG_ACK_MASK 0x00800000L
+#define UVD_SYS_INT_ACK__IDCT_ACK_MASK 0x01000000L
+#define UVD_SYS_INT_ACK__MPRD_ACK_MASK 0x02000000L
+#define UVD_SYS_INT_ACK__CLK_SWT_ACK_MASK 0x08000000L
+#define UVD_SYS_INT_ACK__MIF_HWINT_ACK_MASK 0x10000000L
+#define UVD_SYS_INT_ACK__MPRD_ERR_ACK_MASK 0x20000000L
+#define UVD_SYS_INT_ACK__RASCNTL_VCPU_VCODEC_ACK_MASK 0x40000000L
+#define UVD_SYS_INT_ACK__AVM_INT_ACK_MASK 0x80000000L
+//UVD_JOB_DONE
+#define UVD_JOB_DONE__JOB_DONE__SHIFT 0x0
+#define UVD_JOB_DONE__JOB_DONE_MASK 0x00000003L
+//UVD_CBUF_ID
+#define UVD_CBUF_ID__CBUF_ID__SHIFT 0x0
+#define UVD_CBUF_ID__CBUF_ID_MASK 0xFFFFFFFFL
+//UVD_CONTEXT_ID
+#define UVD_CONTEXT_ID__CONTEXT_ID__SHIFT 0x0
+#define UVD_CONTEXT_ID__CONTEXT_ID_MASK 0xFFFFFFFFL
+//UVD_CONTEXT_ID2
+#define UVD_CONTEXT_ID2__CONTEXT_ID2__SHIFT 0x0
+#define UVD_CONTEXT_ID2__CONTEXT_ID2_MASK 0xFFFFFFFFL
+//UVD_NO_OP
+#define UVD_NO_OP__NO_OP__SHIFT 0x0
+#define UVD_NO_OP__NO_OP_MASK 0xFFFFFFFFL
+//UVD_RB_BASE_LO
+#define UVD_RB_BASE_LO__RB_BASE_LO__SHIFT 0x6
+#define UVD_RB_BASE_LO__RB_BASE_LO_MASK 0xFFFFFFC0L
+//UVD_RB_BASE_HI
+#define UVD_RB_BASE_HI__RB_BASE_HI__SHIFT 0x0
+#define UVD_RB_BASE_HI__RB_BASE_HI_MASK 0xFFFFFFFFL
+//UVD_RB_SIZE
+#define UVD_RB_SIZE__RB_SIZE__SHIFT 0x4
+#define UVD_RB_SIZE__RB_SIZE_MASK 0x007FFFF0L
+//UVD_RB_BASE_LO2
+#define UVD_RB_BASE_LO2__RB_BASE_LO__SHIFT 0x6
+#define UVD_RB_BASE_LO2__RB_BASE_LO_MASK 0xFFFFFFC0L
+//UVD_RB_BASE_HI2
+#define UVD_RB_BASE_HI2__RB_BASE_HI__SHIFT 0x0
+#define UVD_RB_BASE_HI2__RB_BASE_HI_MASK 0xFFFFFFFFL
+//UVD_RB_SIZE2
+#define UVD_RB_SIZE2__RB_SIZE__SHIFT 0x4
+#define UVD_RB_SIZE2__RB_SIZE_MASK 0x007FFFF0L
+//UVD_RB_BASE_LO3
+#define UVD_RB_BASE_LO3__RB_BASE_LO__SHIFT 0x6
+#define UVD_RB_BASE_LO3__RB_BASE_LO_MASK 0xFFFFFFC0L
+//UVD_RB_BASE_HI3
+#define UVD_RB_BASE_HI3__RB_BASE_HI__SHIFT 0x0
+#define UVD_RB_BASE_HI3__RB_BASE_HI_MASK 0xFFFFFFFFL
+//UVD_RB_SIZE3
+#define UVD_RB_SIZE3__RB_SIZE__SHIFT 0x4
+#define UVD_RB_SIZE3__RB_SIZE_MASK 0x007FFFF0L
+//UVD_RB_BASE_LO4
+#define UVD_RB_BASE_LO4__RB_BASE_LO__SHIFT 0x6
+#define UVD_RB_BASE_LO4__RB_BASE_LO_MASK 0xFFFFFFC0L
+//UVD_RB_BASE_HI4
+#define UVD_RB_BASE_HI4__RB_BASE_HI__SHIFT 0x0
+#define UVD_RB_BASE_HI4__RB_BASE_HI_MASK 0xFFFFFFFFL
+//UVD_RB_SIZE4
+#define UVD_RB_SIZE4__RB_SIZE__SHIFT 0x4
+#define UVD_RB_SIZE4__RB_SIZE_MASK 0x007FFFF0L
+//UVD_OUT_RB_BASE_LO
+#define UVD_OUT_RB_BASE_LO__RB_BASE_LO__SHIFT 0x6
+#define UVD_OUT_RB_BASE_LO__RB_BASE_LO_MASK 0xFFFFFFC0L
+//UVD_OUT_RB_BASE_HI
+#define UVD_OUT_RB_BASE_HI__RB_BASE_HI__SHIFT 0x0
+#define UVD_OUT_RB_BASE_HI__RB_BASE_HI_MASK 0xFFFFFFFFL
+//UVD_OUT_RB_SIZE
+#define UVD_OUT_RB_SIZE__RB_SIZE__SHIFT 0x4
+#define UVD_OUT_RB_SIZE__RB_SIZE_MASK 0x007FFFF0L
+//UVD_IOV_ACTIVE_FCN_ID
+#define UVD_IOV_ACTIVE_FCN_ID__VF_ID__SHIFT 0x0
+#define UVD_IOV_ACTIVE_FCN_ID__PF_VF__SHIFT 0x1f
+#define UVD_IOV_ACTIVE_FCN_ID__VF_ID_MASK 0x0000003FL
+#define UVD_IOV_ACTIVE_FCN_ID__PF_VF_MASK 0x80000000L
+//UVD_IOV_MAILBOX
+#define UVD_IOV_MAILBOX__MAILBOX__SHIFT 0x0
+#define UVD_IOV_MAILBOX__MAILBOX_MASK 0xFFFFFFFFL
+//UVD_IOV_MAILBOX_RESP
+#define UVD_IOV_MAILBOX_RESP__RESP__SHIFT 0x0
+#define UVD_IOV_MAILBOX_RESP__RESP_MASK 0xFFFFFFFFL
+//UVD_RB_ARB_CTRL
+#define UVD_RB_ARB_CTRL__SRBM_DROP__SHIFT 0x0
+#define UVD_RB_ARB_CTRL__SRBM_DIS__SHIFT 0x1
+#define UVD_RB_ARB_CTRL__VCPU_DROP__SHIFT 0x2
+#define UVD_RB_ARB_CTRL__VCPU_DIS__SHIFT 0x3
+#define UVD_RB_ARB_CTRL__RBC_DROP__SHIFT 0x4
+#define UVD_RB_ARB_CTRL__RBC_DIS__SHIFT 0x5
+#define UVD_RB_ARB_CTRL__FWOFLD_DROP__SHIFT 0x6
+#define UVD_RB_ARB_CTRL__FWOFLD_DIS__SHIFT 0x7
+#define UVD_RB_ARB_CTRL__FAST_PATH_EN__SHIFT 0x8
+#define UVD_RB_ARB_CTRL__UVD_RB_DBG_EN__SHIFT 0x9
+#define UVD_RB_ARB_CTRL__SRBM_DROP_MASK 0x00000001L
+#define UVD_RB_ARB_CTRL__SRBM_DIS_MASK 0x00000002L
+#define UVD_RB_ARB_CTRL__VCPU_DROP_MASK 0x00000004L
+#define UVD_RB_ARB_CTRL__VCPU_DIS_MASK 0x00000008L
+#define UVD_RB_ARB_CTRL__RBC_DROP_MASK 0x00000010L
+#define UVD_RB_ARB_CTRL__RBC_DIS_MASK 0x00000020L
+#define UVD_RB_ARB_CTRL__FWOFLD_DROP_MASK 0x00000040L
+#define UVD_RB_ARB_CTRL__FWOFLD_DIS_MASK 0x00000080L
+#define UVD_RB_ARB_CTRL__FAST_PATH_EN_MASK 0x00000100L
+#define UVD_RB_ARB_CTRL__UVD_RB_DBG_EN_MASK 0x00000200L
+//UVD_CTX_INDEX
+#define UVD_CTX_INDEX__INDEX__SHIFT 0x0
+#define UVD_CTX_INDEX__INDEX_MASK 0x000001FFL
+//UVD_CTX_DATA
+#define UVD_CTX_DATA__DATA__SHIFT 0x0
+#define UVD_CTX_DATA__DATA_MASK 0xFFFFFFFFL
+//UVD_CXW_WR
+#define UVD_CXW_WR__DAT__SHIFT 0x0
+#define UVD_CXW_WR__STAT__SHIFT 0x1f
+#define UVD_CXW_WR__DAT_MASK 0x0FFFFFFFL
+#define UVD_CXW_WR__STAT_MASK 0x80000000L
+//UVD_CXW_WR_INT_ID
+#define UVD_CXW_WR_INT_ID__ID__SHIFT 0x0
+#define UVD_CXW_WR_INT_ID__ID_MASK 0x000000FFL
+//UVD_CXW_WR_INT_CTX_ID
+#define UVD_CXW_WR_INT_CTX_ID__ID__SHIFT 0x0
+#define UVD_CXW_WR_INT_CTX_ID__ID_MASK 0x0FFFFFFFL
+//UVD_CXW_INT_ID
+#define UVD_CXW_INT_ID__ID__SHIFT 0x0
+#define UVD_CXW_INT_ID__ID_MASK 0x000000FFL
+//UVD_MPEG2_ERROR
+#define UVD_MPEG2_ERROR__STATUS__SHIFT 0x0
+#define UVD_MPEG2_ERROR__STATUS_MASK 0xFFFFFFFFL
+//UVD_YBASE
+#define UVD_YBASE__DUM__SHIFT 0x0
+#define UVD_YBASE__DUM_MASK 0xFFFFFFFFL
+//UVD_UVBASE
+#define UVD_UVBASE__DUM__SHIFT 0x0
+#define UVD_UVBASE__DUM_MASK 0xFFFFFFFFL
+//UVD_PITCH
+#define UVD_PITCH__DUM__SHIFT 0x0
+#define UVD_PITCH__DUM_MASK 0xFFFFFFFFL
+//UVD_WIDTH
+#define UVD_WIDTH__DUM__SHIFT 0x0
+#define UVD_WIDTH__DUM_MASK 0xFFFFFFFFL
+//UVD_HEIGHT
+#define UVD_HEIGHT__DUM__SHIFT 0x0
+#define UVD_HEIGHT__DUM_MASK 0xFFFFFFFFL
+//UVD_PICCOUNT
+#define UVD_PICCOUNT__DUM__SHIFT 0x0
+#define UVD_PICCOUNT__DUM_MASK 0xFFFFFFFFL
+//UVD_MPRD_INITIAL_XY
+#define UVD_MPRD_INITIAL_XY__MPRD_SCREEN_X__SHIFT 0x0
+#define UVD_MPRD_INITIAL_XY__MPRD_SCREEN_Y__SHIFT 0x10
+#define UVD_MPRD_INITIAL_XY__MPRD_SCREEN_X_MASK 0x00000FFFL
+#define UVD_MPRD_INITIAL_XY__MPRD_SCREEN_Y_MASK 0x0FFF0000L
+//UVD_MPEG2_CTRL
+#define UVD_MPEG2_CTRL__EN__SHIFT 0x0
+#define UVD_MPEG2_CTRL__TRICK_MODE__SHIFT 0x1
+#define UVD_MPEG2_CTRL__NUM_MB_PER_JOB__SHIFT 0x10
+#define UVD_MPEG2_CTRL__EN_MASK 0x00000001L
+#define UVD_MPEG2_CTRL__TRICK_MODE_MASK 0x00000002L
+#define UVD_MPEG2_CTRL__NUM_MB_PER_JOB_MASK 0xFFFF0000L
+//UVD_MB_CTL_BUF_BASE
+#define UVD_MB_CTL_BUF_BASE__BASE__SHIFT 0x0
+#define UVD_MB_CTL_BUF_BASE__BASE_MASK 0xFFFFFFFFL
+//UVD_PIC_CTL_BUF_BASE
+#define UVD_PIC_CTL_BUF_BASE__BASE__SHIFT 0x0
+#define UVD_PIC_CTL_BUF_BASE__BASE_MASK 0xFFFFFFFFL
+//UVD_DXVA_BUF_SIZE
+#define UVD_DXVA_BUF_SIZE__PIC_SIZE__SHIFT 0x0
+#define UVD_DXVA_BUF_SIZE__MB_SIZE__SHIFT 0x10
+#define UVD_DXVA_BUF_SIZE__PIC_SIZE_MASK 0x0000FFFFL
+#define UVD_DXVA_BUF_SIZE__MB_SIZE_MASK 0xFFFF0000L
+//UVD_SCRATCH_NP
+#define UVD_SCRATCH_NP__DATA__SHIFT 0x0
+#define UVD_SCRATCH_NP__DATA_MASK 0xFFFFFFFFL
+//UVD_CLK_SWT_HANDSHAKE
+#define UVD_CLK_SWT_HANDSHAKE__CLK_SWT_TYPE__SHIFT 0x0
+#define UVD_CLK_SWT_HANDSHAKE__CLK_DOMAIN_SWT__SHIFT 0x8
+#define UVD_CLK_SWT_HANDSHAKE__CLK_SWT_TYPE_MASK 0x00000003L
+#define UVD_CLK_SWT_HANDSHAKE__CLK_DOMAIN_SWT_MASK 0x00000300L
+//UVD_GP_SCRATCH0
+#define UVD_GP_SCRATCH0__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH0__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH1
+#define UVD_GP_SCRATCH1__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH1__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH2
+#define UVD_GP_SCRATCH2__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH2__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH3
+#define UVD_GP_SCRATCH3__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH3__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH4
+#define UVD_GP_SCRATCH4__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH4__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH5
+#define UVD_GP_SCRATCH5__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH5__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH6
+#define UVD_GP_SCRATCH6__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH6__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH7
+#define UVD_GP_SCRATCH7__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH7__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH8
+#define UVD_GP_SCRATCH8__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH8__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH9
+#define UVD_GP_SCRATCH9__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH9__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH10
+#define UVD_GP_SCRATCH10__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH10__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH11
+#define UVD_GP_SCRATCH11__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH11__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH12
+#define UVD_GP_SCRATCH12__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH12__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH13
+#define UVD_GP_SCRATCH13__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH13__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH14
+#define UVD_GP_SCRATCH14__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH14__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH15
+#define UVD_GP_SCRATCH15__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH15__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH16
+#define UVD_GP_SCRATCH16__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH16__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH17
+#define UVD_GP_SCRATCH17__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH17__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH18
+#define UVD_GP_SCRATCH18__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH18__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH19
+#define UVD_GP_SCRATCH19__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH19__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH20
+#define UVD_GP_SCRATCH20__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH20__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH21
+#define UVD_GP_SCRATCH21__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH21__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH22
+#define UVD_GP_SCRATCH22__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH22__DATA_MASK 0xFFFFFFFFL
+//UVD_GP_SCRATCH23
+#define UVD_GP_SCRATCH23__DATA__SHIFT 0x0
+#define UVD_GP_SCRATCH23__DATA_MASK 0xFFFFFFFFL
+//UVD_AUDIO_RB_BASE_LO
+#define UVD_AUDIO_RB_BASE_LO__RB_BASE_LO__SHIFT 0x6
+#define UVD_AUDIO_RB_BASE_LO__RB_BASE_LO_MASK 0xFFFFFFC0L
+//UVD_AUDIO_RB_BASE_HI
+#define UVD_AUDIO_RB_BASE_HI__RB_BASE_HI__SHIFT 0x0
+#define UVD_AUDIO_RB_BASE_HI__RB_BASE_HI_MASK 0xFFFFFFFFL
+//UVD_AUDIO_RB_SIZE
+#define UVD_AUDIO_RB_SIZE__RB_SIZE__SHIFT 0x4
+#define UVD_AUDIO_RB_SIZE__RB_SIZE_MASK 0x007FFFF0L
+//UVD_VCPU_INT_STATUS2
+#define UVD_VCPU_INT_STATUS2__SW_RB6_INT__SHIFT 0x0
+#define UVD_VCPU_INT_STATUS2__RASCNTL_VCPU_VCODEC_INT__SHIFT 0x15
+#define UVD_VCPU_INT_STATUS2__SW_RB6_INT_MASK 0x00000001L
+#define UVD_VCPU_INT_STATUS2__RASCNTL_VCPU_VCODEC_INT_MASK 0x00200000L
+//UVD_VCPU_INT_ACK2
+#define UVD_VCPU_INT_ACK2__SW_RB6_INT_ACK__SHIFT 0x0
+#define UVD_VCPU_INT_ACK2__RASCNTL_VCPU_VCODEC_ACK__SHIFT 0x16
+#define UVD_VCPU_INT_ACK2__SW_RB6_INT_ACK_MASK 0x00000001L
+#define UVD_VCPU_INT_ACK2__RASCNTL_VCPU_VCODEC_ACK_MASK 0x00400000L
+//UVD_VCPU_INT_EN2
+#define UVD_VCPU_INT_EN2__SW_RB6_INT_EN__SHIFT 0x0
+#define UVD_VCPU_INT_EN2__RASCNTL_VCPU_VCODEC_EN__SHIFT 0x1
+#define UVD_VCPU_INT_EN2__SW_RB6_INT_EN_MASK 0x00000001L
+#define UVD_VCPU_INT_EN2__RASCNTL_VCPU_VCODEC_EN_MASK 0x00000002L
+//UVD_SUVD_CGC_STATUS2
+#define UVD_SUVD_CGC_STATUS2__SMPA_VCLK__SHIFT 0x0
+#define UVD_SUVD_CGC_STATUS2__SMPA_DCLK__SHIFT 0x1
+#define UVD_SUVD_CGC_STATUS2__MPBE1_DCLK__SHIFT 0x3
+#define UVD_SUVD_CGC_STATUS2__SIT_AV1_DCLK__SHIFT 0x4
+#define UVD_SUVD_CGC_STATUS2__SDB_AV1_DCLK__SHIFT 0x5
+#define UVD_SUVD_CGC_STATUS2__MPC1_DCLK__SHIFT 0x6
+#define UVD_SUVD_CGC_STATUS2__MPC1_SCLK__SHIFT 0x7
+#define UVD_SUVD_CGC_STATUS2__MPC1_VCLK__SHIFT 0x8
+#define UVD_SUVD_CGC_STATUS2__SRE_AV1_ENC_DCLK__SHIFT 0x9
+#define UVD_SUVD_CGC_STATUS2__CDEFE_DCLK__SHIFT 0xa
+#define UVD_SUVD_CGC_STATUS2__SIT0_DCLK__SHIFT 0xb
+#define UVD_SUVD_CGC_STATUS2__SIT1_DCLK__SHIFT 0xc
+#define UVD_SUVD_CGC_STATUS2__SIT2_DCLK__SHIFT 0xd
+#define UVD_SUVD_CGC_STATUS2__FBC_PCLK__SHIFT 0x1c
+#define UVD_SUVD_CGC_STATUS2__FBC_CCLK__SHIFT 0x1d
+#define UVD_SUVD_CGC_STATUS2__SMPA_VCLK_MASK 0x00000001L
+#define UVD_SUVD_CGC_STATUS2__SMPA_DCLK_MASK 0x00000002L
+#define UVD_SUVD_CGC_STATUS2__MPBE1_DCLK_MASK 0x00000008L
+#define UVD_SUVD_CGC_STATUS2__SIT_AV1_DCLK_MASK 0x00000010L
+#define UVD_SUVD_CGC_STATUS2__SDB_AV1_DCLK_MASK 0x00000020L
+#define UVD_SUVD_CGC_STATUS2__MPC1_DCLK_MASK 0x00000040L
+#define UVD_SUVD_CGC_STATUS2__MPC1_SCLK_MASK 0x00000080L
+#define UVD_SUVD_CGC_STATUS2__MPC1_VCLK_MASK 0x00000100L
+#define UVD_SUVD_CGC_STATUS2__SRE_AV1_ENC_DCLK_MASK 0x00000200L
+#define UVD_SUVD_CGC_STATUS2__CDEFE_DCLK_MASK 0x00000400L
+#define UVD_SUVD_CGC_STATUS2__SIT0_DCLK_MASK 0x00000800L
+#define UVD_SUVD_CGC_STATUS2__SIT1_DCLK_MASK 0x00001000L
+#define UVD_SUVD_CGC_STATUS2__SIT2_DCLK_MASK 0x00002000L
+#define UVD_SUVD_CGC_STATUS2__FBC_PCLK_MASK 0x10000000L
+#define UVD_SUVD_CGC_STATUS2__FBC_CCLK_MASK 0x20000000L
+//UVD_SUVD_INT_STATUS2
+#define UVD_SUVD_INT_STATUS2__SMPA_FUNC_INT__SHIFT 0x0
+#define UVD_SUVD_INT_STATUS2__SMPA_ERR_INT__SHIFT 0x5
+#define UVD_SUVD_INT_STATUS2__SDB_AV1_FUNC_INT__SHIFT 0x6
+#define UVD_SUVD_INT_STATUS2__SDB_AV1_ERR_INT__SHIFT 0xb
+#define UVD_SUVD_INT_STATUS2__SMPA_FUNC_INT_MASK 0x0000001FL
+#define UVD_SUVD_INT_STATUS2__SMPA_ERR_INT_MASK 0x00000020L
+#define UVD_SUVD_INT_STATUS2__SDB_AV1_FUNC_INT_MASK 0x000007C0L
+#define UVD_SUVD_INT_STATUS2__SDB_AV1_ERR_INT_MASK 0x00000800L
+//UVD_SUVD_INT_EN2
+#define UVD_SUVD_INT_EN2__SMPA_FUNC_INT_EN__SHIFT 0x0
+#define UVD_SUVD_INT_EN2__SMPA_ERR_INT_EN__SHIFT 0x5
+#define UVD_SUVD_INT_EN2__SDB_AV1_FUNC_INT_EN__SHIFT 0x6
+#define UVD_SUVD_INT_EN2__SDB_AV1_ERR_INT_EN__SHIFT 0xb
+#define UVD_SUVD_INT_EN2__SMPA_FUNC_INT_EN_MASK 0x0000001FL
+#define UVD_SUVD_INT_EN2__SMPA_ERR_INT_EN_MASK 0x00000020L
+#define UVD_SUVD_INT_EN2__SDB_AV1_FUNC_INT_EN_MASK 0x000007C0L
+#define UVD_SUVD_INT_EN2__SDB_AV1_ERR_INT_EN_MASK 0x00000800L
+//UVD_SUVD_INT_ACK2
+#define UVD_SUVD_INT_ACK2__SMPA_FUNC_INT_ACK__SHIFT 0x0
+#define UVD_SUVD_INT_ACK2__SMPA_ERR_INT_ACK__SHIFT 0x5
+#define UVD_SUVD_INT_ACK2__SDB_AV1_FUNC_INT_ACK__SHIFT 0x6
+#define UVD_SUVD_INT_ACK2__SDB_AV1_ERR_INT_ACK__SHIFT 0xb
+#define UVD_SUVD_INT_ACK2__SMPA_FUNC_INT_ACK_MASK 0x0000001FL
+#define UVD_SUVD_INT_ACK2__SMPA_ERR_INT_ACK_MASK 0x00000020L
+#define UVD_SUVD_INT_ACK2__SDB_AV1_FUNC_INT_ACK_MASK 0x000007C0L
+#define UVD_SUVD_INT_ACK2__SDB_AV1_ERR_INT_ACK_MASK 0x00000800L
+//UVD_STATUS
+#define UVD_STATUS__RBC_BUSY__SHIFT 0x0
+#define UVD_STATUS__VCPU_REPORT__SHIFT 0x1
+#define UVD_STATUS__FILL_0__SHIFT 0x8
+#define UVD_STATUS__RBC_ACCESS_GPCOM__SHIFT 0x10
+#define UVD_STATUS__DRM_BUSY__SHIFT 0x11
+#define UVD_STATUS__FILL_1__SHIFT 0x12
+#define UVD_STATUS__SYS_GPCOM_REQ__SHIFT 0x1f
+#define UVD_STATUS__RBC_BUSY_MASK 0x00000001L
+#define UVD_STATUS__VCPU_REPORT_MASK 0x000000FEL
+#define UVD_STATUS__FILL_0_MASK 0x0000FF00L
+#define UVD_STATUS__RBC_ACCESS_GPCOM_MASK 0x00010000L
+#define UVD_STATUS__DRM_BUSY_MASK 0x00020000L
+#define UVD_STATUS__FILL_1_MASK 0x7FFC0000L
+#define UVD_STATUS__SYS_GPCOM_REQ_MASK 0x80000000L
+//UVD_ENC_PIPE_BUSY
+#define UVD_ENC_PIPE_BUSY__IME_BUSY__SHIFT 0x0
+#define UVD_ENC_PIPE_BUSY__SMP_BUSY__SHIFT 0x1
+#define UVD_ENC_PIPE_BUSY__SIT_BUSY__SHIFT 0x2
+#define UVD_ENC_PIPE_BUSY__SDB_BUSY__SHIFT 0x3
+#define UVD_ENC_PIPE_BUSY__ENT_BUSY__SHIFT 0x4
+#define UVD_ENC_PIPE_BUSY__ENT_HEADER_BUSY__SHIFT 0x5
+#define UVD_ENC_PIPE_BUSY__LCM_BUSY__SHIFT 0x6
+#define UVD_ENC_PIPE_BUSY__MDM_RD_CUR_BUSY__SHIFT 0x7
+#define UVD_ENC_PIPE_BUSY__MDM_RD_REF_BUSY__SHIFT 0x8
+#define UVD_ENC_PIPE_BUSY__MDM_RD_GEN_BUSY__SHIFT 0x9
+#define UVD_ENC_PIPE_BUSY__MDM_WR_RECON_BUSY__SHIFT 0xa
+#define UVD_ENC_PIPE_BUSY__MDM_WR_GEN_BUSY__SHIFT 0xb
+#define UVD_ENC_PIPE_BUSY__EFC_BUSY__SHIFT 0xc
+#define UVD_ENC_PIPE_BUSY__MDM_PPU_BUSY__SHIFT 0xd
+#define UVD_ENC_PIPE_BUSY__MIF_AUTODMA_BUSY__SHIFT 0xe
+#define UVD_ENC_PIPE_BUSY__CDEFE_BUSY__SHIFT 0xf
+#define UVD_ENC_PIPE_BUSY__MIF_RD_CUR_BUSY__SHIFT 0x10
+#define UVD_ENC_PIPE_BUSY__MIF_RD_REF0_BUSY__SHIFT 0x11
+#define UVD_ENC_PIPE_BUSY__MIF_WR_GEN0_BUSY__SHIFT 0x12
+#define UVD_ENC_PIPE_BUSY__MIF_RD_GEN0_BUSY__SHIFT 0x13
+#define UVD_ENC_PIPE_BUSY__MIF_WR_GEN1_BUSY__SHIFT 0x14
+#define UVD_ENC_PIPE_BUSY__MIF_RD_GEN1_BUSY__SHIFT 0x15
+#define UVD_ENC_PIPE_BUSY__MIF_WR_BSP0_BUSY__SHIFT 0x16
+#define UVD_ENC_PIPE_BUSY__MIF_WR_BSP1_BUSY__SHIFT 0x17
+#define UVD_ENC_PIPE_BUSY__MIF_RD_BSD0_BUSY__SHIFT 0x18
+#define UVD_ENC_PIPE_BUSY__MIF_RD_BSD1_BUSY__SHIFT 0x19
+#define UVD_ENC_PIPE_BUSY__MIF_RD_BSD2_BUSY__SHIFT 0x1a
+#define UVD_ENC_PIPE_BUSY__MIF_RD_BSD3_BUSY__SHIFT 0x1b
+#define UVD_ENC_PIPE_BUSY__MIF_RD_BSD4_BUSY__SHIFT 0x1c
+#define UVD_ENC_PIPE_BUSY__MIF_WR_BSP2_BUSY__SHIFT 0x1d
+#define UVD_ENC_PIPE_BUSY__MIF_WR_BSP3_BUSY__SHIFT 0x1e
+#define UVD_ENC_PIPE_BUSY__SAOE_BUSY__SHIFT 0x1f
+#define UVD_ENC_PIPE_BUSY__IME_BUSY_MASK 0x00000001L
+#define UVD_ENC_PIPE_BUSY__SMP_BUSY_MASK 0x00000002L
+#define UVD_ENC_PIPE_BUSY__SIT_BUSY_MASK 0x00000004L
+#define UVD_ENC_PIPE_BUSY__SDB_BUSY_MASK 0x00000008L
+#define UVD_ENC_PIPE_BUSY__ENT_BUSY_MASK 0x00000010L
+#define UVD_ENC_PIPE_BUSY__ENT_HEADER_BUSY_MASK 0x00000020L
+#define UVD_ENC_PIPE_BUSY__LCM_BUSY_MASK 0x00000040L
+#define UVD_ENC_PIPE_BUSY__MDM_RD_CUR_BUSY_MASK 0x00000080L
+#define UVD_ENC_PIPE_BUSY__MDM_RD_REF_BUSY_MASK 0x00000100L
+#define UVD_ENC_PIPE_BUSY__MDM_RD_GEN_BUSY_MASK 0x00000200L
+#define UVD_ENC_PIPE_BUSY__MDM_WR_RECON_BUSY_MASK 0x00000400L
+#define UVD_ENC_PIPE_BUSY__MDM_WR_GEN_BUSY_MASK 0x00000800L
+#define UVD_ENC_PIPE_BUSY__EFC_BUSY_MASK 0x00001000L
+#define UVD_ENC_PIPE_BUSY__MDM_PPU_BUSY_MASK 0x00002000L
+#define UVD_ENC_PIPE_BUSY__MIF_AUTODMA_BUSY_MASK 0x00004000L
+#define UVD_ENC_PIPE_BUSY__CDEFE_BUSY_MASK 0x00008000L
+#define UVD_ENC_PIPE_BUSY__MIF_RD_CUR_BUSY_MASK 0x00010000L
+#define UVD_ENC_PIPE_BUSY__MIF_RD_REF0_BUSY_MASK 0x00020000L
+#define UVD_ENC_PIPE_BUSY__MIF_WR_GEN0_BUSY_MASK 0x00040000L
+#define UVD_ENC_PIPE_BUSY__MIF_RD_GEN0_BUSY_MASK 0x00080000L
+#define UVD_ENC_PIPE_BUSY__MIF_WR_GEN1_BUSY_MASK 0x00100000L
+#define UVD_ENC_PIPE_BUSY__MIF_RD_GEN1_BUSY_MASK 0x00200000L
+#define UVD_ENC_PIPE_BUSY__MIF_WR_BSP0_BUSY_MASK 0x00400000L
+#define UVD_ENC_PIPE_BUSY__MIF_WR_BSP1_BUSY_MASK 0x00800000L
+#define UVD_ENC_PIPE_BUSY__MIF_RD_BSD0_BUSY_MASK 0x01000000L
+#define UVD_ENC_PIPE_BUSY__MIF_RD_BSD1_BUSY_MASK 0x02000000L
+#define UVD_ENC_PIPE_BUSY__MIF_RD_BSD2_BUSY_MASK 0x04000000L
+#define UVD_ENC_PIPE_BUSY__MIF_RD_BSD3_BUSY_MASK 0x08000000L
+#define UVD_ENC_PIPE_BUSY__MIF_RD_BSD4_BUSY_MASK 0x10000000L
+#define UVD_ENC_PIPE_BUSY__MIF_WR_BSP2_BUSY_MASK 0x20000000L
+#define UVD_ENC_PIPE_BUSY__MIF_WR_BSP3_BUSY_MASK 0x40000000L
+#define UVD_ENC_PIPE_BUSY__SAOE_BUSY_MASK 0x80000000L
+//UVD_FW_POWER_STATUS
+#define UVD_FW_POWER_STATUS__UVDF_PWR_OFF__SHIFT 0x0
+#define UVD_FW_POWER_STATUS__UVDTC_PWR_OFF__SHIFT 0x1
+#define UVD_FW_POWER_STATUS__UVDB_PWR_OFF__SHIFT 0x2
+#define UVD_FW_POWER_STATUS__UVDTA_PWR_OFF__SHIFT 0x3
+#define UVD_FW_POWER_STATUS__UVDTD_PWR_OFF__SHIFT 0x4
+#define UVD_FW_POWER_STATUS__UVDTE_PWR_OFF__SHIFT 0x5
+#define UVD_FW_POWER_STATUS__UVDE_PWR_OFF__SHIFT 0x6
+#define UVD_FW_POWER_STATUS__UVDAB_PWR_OFF__SHIFT 0x7
+#define UVD_FW_POWER_STATUS__UVDTB_PWR_OFF__SHIFT 0x8
+#define UVD_FW_POWER_STATUS__UVDNA_PWR_OFF__SHIFT 0x9
+#define UVD_FW_POWER_STATUS__UVDNB_PWR_OFF__SHIFT 0xa
+#define UVD_FW_POWER_STATUS__UVDF_PWR_OFF_MASK 0x00000001L
+#define UVD_FW_POWER_STATUS__UVDTC_PWR_OFF_MASK 0x00000002L
+#define UVD_FW_POWER_STATUS__UVDB_PWR_OFF_MASK 0x00000004L
+#define UVD_FW_POWER_STATUS__UVDTA_PWR_OFF_MASK 0x00000008L
+#define UVD_FW_POWER_STATUS__UVDTD_PWR_OFF_MASK 0x00000010L
+#define UVD_FW_POWER_STATUS__UVDTE_PWR_OFF_MASK 0x00000020L
+#define UVD_FW_POWER_STATUS__UVDE_PWR_OFF_MASK 0x00000040L
+#define UVD_FW_POWER_STATUS__UVDAB_PWR_OFF_MASK 0x00000080L
+#define UVD_FW_POWER_STATUS__UVDTB_PWR_OFF_MASK 0x00000100L
+#define UVD_FW_POWER_STATUS__UVDNA_PWR_OFF_MASK 0x00000200L
+#define UVD_FW_POWER_STATUS__UVDNB_PWR_OFF_MASK 0x00000400L
+//UVD_CNTL
+#define UVD_CNTL__MIF_WR_LOW_THRESHOLD_BP__SHIFT 0x11
+#define UVD_CNTL__SUVD_EN__SHIFT 0x13
+#define UVD_CNTL__CABAC_MB_ACC__SHIFT 0x1c
+#define UVD_CNTL__LRBBM_SAFE_SYNC_DIS__SHIFT 0x1f
+#define UVD_CNTL__MIF_WR_LOW_THRESHOLD_BP_MASK 0x00020000L
+#define UVD_CNTL__SUVD_EN_MASK 0x00080000L
+#define UVD_CNTL__CABAC_MB_ACC_MASK 0x10000000L
+#define UVD_CNTL__LRBBM_SAFE_SYNC_DIS_MASK 0x80000000L
+//UVD_SOFT_RESET
+#define UVD_SOFT_RESET__RBC_SOFT_RESET__SHIFT 0x0
+#define UVD_SOFT_RESET__LBSI_SOFT_RESET__SHIFT 0x1
+#define UVD_SOFT_RESET__LMI_SOFT_RESET__SHIFT 0x2
+#define UVD_SOFT_RESET__VCPU_SOFT_RESET__SHIFT 0x3
+#define UVD_SOFT_RESET__UDEC_SOFT_RESET__SHIFT 0x4
+#define UVD_SOFT_RESET__CXW_SOFT_RESET__SHIFT 0x6
+#define UVD_SOFT_RESET__TAP_SOFT_RESET__SHIFT 0x7
+#define UVD_SOFT_RESET__MPC_SOFT_RESET__SHIFT 0x8
+#define UVD_SOFT_RESET__EFC_SOFT_RESET__SHIFT 0x9
+#define UVD_SOFT_RESET__IH_SOFT_RESET__SHIFT 0xa
+#define UVD_SOFT_RESET__MPRD_SOFT_RESET__SHIFT 0xb
+#define UVD_SOFT_RESET__IDCT_SOFT_RESET__SHIFT 0xc
+#define UVD_SOFT_RESET__LMI_UMC_SOFT_RESET__SHIFT 0xd
+#define UVD_SOFT_RESET__SPH_SOFT_RESET__SHIFT 0xe
+#define UVD_SOFT_RESET__MIF_SOFT_RESET__SHIFT 0xf
+#define UVD_SOFT_RESET__LCM_SOFT_RESET__SHIFT 0x10
+#define UVD_SOFT_RESET__SUVD_SOFT_RESET__SHIFT 0x11
+#define UVD_SOFT_RESET__LBSI_VCLK_RESET_STATUS__SHIFT 0x12
+#define UVD_SOFT_RESET__VCPU_VCLK_RESET_STATUS__SHIFT 0x13
+#define UVD_SOFT_RESET__UDEC_VCLK_RESET_STATUS__SHIFT 0x14
+#define UVD_SOFT_RESET__UDEC_DCLK_RESET_STATUS__SHIFT 0x15
+#define UVD_SOFT_RESET__MPC_DCLK_RESET_STATUS__SHIFT 0x16
+#define UVD_SOFT_RESET__MPRD_VCLK_RESET_STATUS__SHIFT 0x17
+#define UVD_SOFT_RESET__MPRD_DCLK_RESET_STATUS__SHIFT 0x18
+#define UVD_SOFT_RESET__IDCT_VCLK_RESET_STATUS__SHIFT 0x19
+#define UVD_SOFT_RESET__MIF_DCLK_RESET_STATUS__SHIFT 0x1a
+#define UVD_SOFT_RESET__LCM_DCLK_RESET_STATUS__SHIFT 0x1b
+#define UVD_SOFT_RESET__SUVD_VCLK_RESET_STATUS__SHIFT 0x1c
+#define UVD_SOFT_RESET__SUVD_DCLK_RESET_STATUS__SHIFT 0x1d
+#define UVD_SOFT_RESET__RE_DCLK_RESET_STATUS__SHIFT 0x1e
+#define UVD_SOFT_RESET__SRE_DCLK_RESET_STATUS__SHIFT 0x1f
+#define UVD_SOFT_RESET__RBC_SOFT_RESET_MASK 0x00000001L
+#define UVD_SOFT_RESET__LBSI_SOFT_RESET_MASK 0x00000002L
+#define UVD_SOFT_RESET__LMI_SOFT_RESET_MASK 0x00000004L
+#define UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK 0x00000008L
+#define UVD_SOFT_RESET__UDEC_SOFT_RESET_MASK 0x00000010L
+#define UVD_SOFT_RESET__CXW_SOFT_RESET_MASK 0x00000040L
+#define UVD_SOFT_RESET__TAP_SOFT_RESET_MASK 0x00000080L
+#define UVD_SOFT_RESET__MPC_SOFT_RESET_MASK 0x00000100L
+#define UVD_SOFT_RESET__EFC_SOFT_RESET_MASK 0x00000200L
+#define UVD_SOFT_RESET__IH_SOFT_RESET_MASK 0x00000400L
+#define UVD_SOFT_RESET__MPRD_SOFT_RESET_MASK 0x00000800L
+#define UVD_SOFT_RESET__IDCT_SOFT_RESET_MASK 0x00001000L
+#define UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK 0x00002000L
+#define UVD_SOFT_RESET__SPH_SOFT_RESET_MASK 0x00004000L
+#define UVD_SOFT_RESET__MIF_SOFT_RESET_MASK 0x00008000L
+#define UVD_SOFT_RESET__LCM_SOFT_RESET_MASK 0x00010000L
+#define UVD_SOFT_RESET__SUVD_SOFT_RESET_MASK 0x00020000L
+#define UVD_SOFT_RESET__LBSI_VCLK_RESET_STATUS_MASK 0x00040000L
+#define UVD_SOFT_RESET__VCPU_VCLK_RESET_STATUS_MASK 0x00080000L
+#define UVD_SOFT_RESET__UDEC_VCLK_RESET_STATUS_MASK 0x00100000L
+#define UVD_SOFT_RESET__UDEC_DCLK_RESET_STATUS_MASK 0x00200000L
+#define UVD_SOFT_RESET__MPC_DCLK_RESET_STATUS_MASK 0x00400000L
+#define UVD_SOFT_RESET__MPRD_VCLK_RESET_STATUS_MASK 0x00800000L
+#define UVD_SOFT_RESET__MPRD_DCLK_RESET_STATUS_MASK 0x01000000L
+#define UVD_SOFT_RESET__IDCT_VCLK_RESET_STATUS_MASK 0x02000000L
+#define UVD_SOFT_RESET__MIF_DCLK_RESET_STATUS_MASK 0x04000000L
+#define UVD_SOFT_RESET__LCM_DCLK_RESET_STATUS_MASK 0x08000000L
+#define UVD_SOFT_RESET__SUVD_VCLK_RESET_STATUS_MASK 0x10000000L
+#define UVD_SOFT_RESET__SUVD_DCLK_RESET_STATUS_MASK 0x20000000L
+#define UVD_SOFT_RESET__RE_DCLK_RESET_STATUS_MASK 0x40000000L
+#define UVD_SOFT_RESET__SRE_DCLK_RESET_STATUS_MASK 0x80000000L
+//UVD_SOFT_RESET2
+#define UVD_SOFT_RESET2__ATOMIC_SOFT_RESET__SHIFT 0x0
+#define UVD_SOFT_RESET2__PPU_SOFT_RESET__SHIFT 0x1
+#define UVD_SOFT_RESET2__MMSCH_VCLK_RESET_STATUS__SHIFT 0x10
+#define UVD_SOFT_RESET2__MMSCH_SCLK_RESET_STATUS__SHIFT 0x11
+#define UVD_SOFT_RESET2__ATOMIC_SOFT_RESET_MASK 0x00000001L
+#define UVD_SOFT_RESET2__PPU_SOFT_RESET_MASK 0x00000002L
+#define UVD_SOFT_RESET2__MMSCH_VCLK_RESET_STATUS_MASK 0x00010000L
+#define UVD_SOFT_RESET2__MMSCH_SCLK_RESET_STATUS_MASK 0x00020000L
+//UVD_MMSCH_SOFT_RESET
+#define UVD_MMSCH_SOFT_RESET__MMSCH_RESET__SHIFT 0x0
+#define UVD_MMSCH_SOFT_RESET__TAP_SOFT_RESET__SHIFT 0x1
+#define UVD_MMSCH_SOFT_RESET__MMSCH_LOCK__SHIFT 0x1f
+#define UVD_MMSCH_SOFT_RESET__MMSCH_RESET_MASK 0x00000001L
+#define UVD_MMSCH_SOFT_RESET__TAP_SOFT_RESET_MASK 0x00000002L
+#define UVD_MMSCH_SOFT_RESET__MMSCH_LOCK_MASK 0x80000000L
+//UVD_WIG_CTRL
+#define UVD_WIG_CTRL__AVM_SOFT_RESET__SHIFT 0x0
+#define UVD_WIG_CTRL__ACAP_SOFT_RESET__SHIFT 0x1
+#define UVD_WIG_CTRL__WIG_SOFT_RESET__SHIFT 0x2
+#define UVD_WIG_CTRL__WIG_REGCLK_FORCE_ON__SHIFT 0x3
+#define UVD_WIG_CTRL__AVM_REGCLK_FORCE_ON__SHIFT 0x4
+#define UVD_WIG_CTRL__AVM_SOFT_RESET_MASK 0x00000001L
+#define UVD_WIG_CTRL__ACAP_SOFT_RESET_MASK 0x00000002L
+#define UVD_WIG_CTRL__WIG_SOFT_RESET_MASK 0x00000004L
+#define UVD_WIG_CTRL__WIG_REGCLK_FORCE_ON_MASK 0x00000008L
+#define UVD_WIG_CTRL__AVM_REGCLK_FORCE_ON_MASK 0x00000010L
+//UVD_CGC_STATUS
+#define UVD_CGC_STATUS__SYS_SCLK__SHIFT 0x0
+#define UVD_CGC_STATUS__SYS_DCLK__SHIFT 0x1
+#define UVD_CGC_STATUS__SYS_VCLK__SHIFT 0x2
+#define UVD_CGC_STATUS__UDEC_SCLK__SHIFT 0x3
+#define UVD_CGC_STATUS__UDEC_DCLK__SHIFT 0x4
+#define UVD_CGC_STATUS__UDEC_VCLK__SHIFT 0x5
+#define UVD_CGC_STATUS__MPEG2_SCLK__SHIFT 0x6
+#define UVD_CGC_STATUS__MPEG2_DCLK__SHIFT 0x7
+#define UVD_CGC_STATUS__MPEG2_VCLK__SHIFT 0x8
+#define UVD_CGC_STATUS__REGS_SCLK__SHIFT 0x9
+#define UVD_CGC_STATUS__REGS_VCLK__SHIFT 0xa
+#define UVD_CGC_STATUS__RBC_SCLK__SHIFT 0xb
+#define UVD_CGC_STATUS__LMI_MC_SCLK__SHIFT 0xc
+#define UVD_CGC_STATUS__LMI_UMC_SCLK__SHIFT 0xd
+#define UVD_CGC_STATUS__IDCT_SCLK__SHIFT 0xe
+#define UVD_CGC_STATUS__IDCT_VCLK__SHIFT 0xf
+#define UVD_CGC_STATUS__MPRD_SCLK__SHIFT 0x10
+#define UVD_CGC_STATUS__MPRD_DCLK__SHIFT 0x11
+#define UVD_CGC_STATUS__MPRD_VCLK__SHIFT 0x12
+#define UVD_CGC_STATUS__MPC_SCLK__SHIFT 0x13
+#define UVD_CGC_STATUS__MPC_DCLK__SHIFT 0x14
+#define UVD_CGC_STATUS__LBSI_SCLK__SHIFT 0x15
+#define UVD_CGC_STATUS__LBSI_VCLK__SHIFT 0x16
+#define UVD_CGC_STATUS__LRBBM_SCLK__SHIFT 0x17
+#define UVD_CGC_STATUS__WCB_SCLK__SHIFT 0x18
+#define UVD_CGC_STATUS__VCPU_SCLK__SHIFT 0x19
+#define UVD_CGC_STATUS__VCPU_VCLK__SHIFT 0x1a
+#define UVD_CGC_STATUS__MMSCH_SCLK__SHIFT 0x1b
+#define UVD_CGC_STATUS__MMSCH_VCLK__SHIFT 0x1c
+#define UVD_CGC_STATUS__ALL_ENC_ACTIVE__SHIFT 0x1d
+#define UVD_CGC_STATUS__LRBBM_DCLK__SHIFT 0x1e
+#define UVD_CGC_STATUS__ALL_DEC_ACTIVE__SHIFT 0x1f
+#define UVD_CGC_STATUS__SYS_SCLK_MASK 0x00000001L
+#define UVD_CGC_STATUS__SYS_DCLK_MASK 0x00000002L
+#define UVD_CGC_STATUS__SYS_VCLK_MASK 0x00000004L
+#define UVD_CGC_STATUS__UDEC_SCLK_MASK 0x00000008L
+#define UVD_CGC_STATUS__UDEC_DCLK_MASK 0x00000010L
+#define UVD_CGC_STATUS__UDEC_VCLK_MASK 0x00000020L
+#define UVD_CGC_STATUS__MPEG2_SCLK_MASK 0x00000040L
+#define UVD_CGC_STATUS__MPEG2_DCLK_MASK 0x00000080L
+#define UVD_CGC_STATUS__MPEG2_VCLK_MASK 0x00000100L
+#define UVD_CGC_STATUS__REGS_SCLK_MASK 0x00000200L
+#define UVD_CGC_STATUS__REGS_VCLK_MASK 0x00000400L
+#define UVD_CGC_STATUS__RBC_SCLK_MASK 0x00000800L
+#define UVD_CGC_STATUS__LMI_MC_SCLK_MASK 0x00001000L
+#define UVD_CGC_STATUS__LMI_UMC_SCLK_MASK 0x00002000L
+#define UVD_CGC_STATUS__IDCT_SCLK_MASK 0x00004000L
+#define UVD_CGC_STATUS__IDCT_VCLK_MASK 0x00008000L
+#define UVD_CGC_STATUS__MPRD_SCLK_MASK 0x00010000L
+#define UVD_CGC_STATUS__MPRD_DCLK_MASK 0x00020000L
+#define UVD_CGC_STATUS__MPRD_VCLK_MASK 0x00040000L
+#define UVD_CGC_STATUS__MPC_SCLK_MASK 0x00080000L
+#define UVD_CGC_STATUS__MPC_DCLK_MASK 0x00100000L
+#define UVD_CGC_STATUS__LBSI_SCLK_MASK 0x00200000L
+#define UVD_CGC_STATUS__LBSI_VCLK_MASK 0x00400000L
+#define UVD_CGC_STATUS__LRBBM_SCLK_MASK 0x00800000L
+#define UVD_CGC_STATUS__WCB_SCLK_MASK 0x01000000L
+#define UVD_CGC_STATUS__VCPU_SCLK_MASK 0x02000000L
+#define UVD_CGC_STATUS__VCPU_VCLK_MASK 0x04000000L
+#define UVD_CGC_STATUS__MMSCH_SCLK_MASK 0x08000000L
+#define UVD_CGC_STATUS__MMSCH_VCLK_MASK 0x10000000L
+#define UVD_CGC_STATUS__ALL_ENC_ACTIVE_MASK 0x20000000L
+#define UVD_CGC_STATUS__LRBBM_DCLK_MASK 0x40000000L
+#define UVD_CGC_STATUS__ALL_DEC_ACTIVE_MASK 0x80000000L
+//UVD_CGC_UDEC_STATUS
+#define UVD_CGC_UDEC_STATUS__RE_SCLK__SHIFT 0x0
+#define UVD_CGC_UDEC_STATUS__RE_DCLK__SHIFT 0x1
+#define UVD_CGC_UDEC_STATUS__RE_VCLK__SHIFT 0x2
+#define UVD_CGC_UDEC_STATUS__CM_SCLK__SHIFT 0x3
+#define UVD_CGC_UDEC_STATUS__CM_DCLK__SHIFT 0x4
+#define UVD_CGC_UDEC_STATUS__CM_VCLK__SHIFT 0x5
+#define UVD_CGC_UDEC_STATUS__IT_SCLK__SHIFT 0x6
+#define UVD_CGC_UDEC_STATUS__IT_DCLK__SHIFT 0x7
+#define UVD_CGC_UDEC_STATUS__IT_VCLK__SHIFT 0x8
+#define UVD_CGC_UDEC_STATUS__DB_SCLK__SHIFT 0x9
+#define UVD_CGC_UDEC_STATUS__DB_DCLK__SHIFT 0xa
+#define UVD_CGC_UDEC_STATUS__DB_VCLK__SHIFT 0xb
+#define UVD_CGC_UDEC_STATUS__MP_SCLK__SHIFT 0xc
+#define UVD_CGC_UDEC_STATUS__MP_DCLK__SHIFT 0xd
+#define UVD_CGC_UDEC_STATUS__MP_VCLK__SHIFT 0xe
+#define UVD_CGC_UDEC_STATUS__RE_SCLK_MASK 0x00000001L
+#define UVD_CGC_UDEC_STATUS__RE_DCLK_MASK 0x00000002L
+#define UVD_CGC_UDEC_STATUS__RE_VCLK_MASK 0x00000004L
+#define UVD_CGC_UDEC_STATUS__CM_SCLK_MASK 0x00000008L
+#define UVD_CGC_UDEC_STATUS__CM_DCLK_MASK 0x00000010L
+#define UVD_CGC_UDEC_STATUS__CM_VCLK_MASK 0x00000020L
+#define UVD_CGC_UDEC_STATUS__IT_SCLK_MASK 0x00000040L
+#define UVD_CGC_UDEC_STATUS__IT_DCLK_MASK 0x00000080L
+#define UVD_CGC_UDEC_STATUS__IT_VCLK_MASK 0x00000100L
+#define UVD_CGC_UDEC_STATUS__DB_SCLK_MASK 0x00000200L
+#define UVD_CGC_UDEC_STATUS__DB_DCLK_MASK 0x00000400L
+#define UVD_CGC_UDEC_STATUS__DB_VCLK_MASK 0x00000800L
+#define UVD_CGC_UDEC_STATUS__MP_SCLK_MASK 0x00001000L
+#define UVD_CGC_UDEC_STATUS__MP_DCLK_MASK 0x00002000L
+#define UVD_CGC_UDEC_STATUS__MP_VCLK_MASK 0x00004000L
+//UVD_SUVD_CGC_STATUS
+#define UVD_SUVD_CGC_STATUS__SRE_VCLK__SHIFT 0x0
+#define UVD_SUVD_CGC_STATUS__SRE_DCLK__SHIFT 0x1
+#define UVD_SUVD_CGC_STATUS__SIT_DCLK__SHIFT 0x2
+#define UVD_SUVD_CGC_STATUS__SMP_DCLK__SHIFT 0x3
+#define UVD_SUVD_CGC_STATUS__SCM_DCLK__SHIFT 0x4
+#define UVD_SUVD_CGC_STATUS__SDB_DCLK__SHIFT 0x5
+#define UVD_SUVD_CGC_STATUS__SRE_H264_VCLK__SHIFT 0x6
+#define UVD_SUVD_CGC_STATUS__SRE_HEVC_VCLK__SHIFT 0x7
+#define UVD_SUVD_CGC_STATUS__SIT_H264_DCLK__SHIFT 0x8
+#define UVD_SUVD_CGC_STATUS__SIT_HEVC_DCLK__SHIFT 0x9
+#define UVD_SUVD_CGC_STATUS__SCM_H264_DCLK__SHIFT 0xa
+#define UVD_SUVD_CGC_STATUS__SCM_HEVC_DCLK__SHIFT 0xb
+#define UVD_SUVD_CGC_STATUS__SDB_H264_DCLK__SHIFT 0xc
+#define UVD_SUVD_CGC_STATUS__SDB_HEVC_DCLK__SHIFT 0xd
+#define UVD_SUVD_CGC_STATUS__SCLR_DCLK__SHIFT 0xe
+#define UVD_SUVD_CGC_STATUS__UVD_SC__SHIFT 0xf
+#define UVD_SUVD_CGC_STATUS__ENT_DCLK__SHIFT 0x10
+#define UVD_SUVD_CGC_STATUS__IME_DCLK__SHIFT 0x11
+#define UVD_SUVD_CGC_STATUS__SIT_HEVC_DEC_DCLK__SHIFT 0x12
+#define UVD_SUVD_CGC_STATUS__SIT_HEVC_ENC_DCLK__SHIFT 0x13
+#define UVD_SUVD_CGC_STATUS__SITE_DCLK__SHIFT 0x14
+#define UVD_SUVD_CGC_STATUS__SITE_HEVC_DCLK__SHIFT 0x15
+#define UVD_SUVD_CGC_STATUS__SITE_HEVC_ENC_DCLK__SHIFT 0x16
+#define UVD_SUVD_CGC_STATUS__SRE_VP9_VCLK__SHIFT 0x17
+#define UVD_SUVD_CGC_STATUS__SCM_VP9_VCLK__SHIFT 0x18
+#define UVD_SUVD_CGC_STATUS__SIT_VP9_DEC_DCLK__SHIFT 0x19
+#define UVD_SUVD_CGC_STATUS__SDB_VP9_DCLK__SHIFT 0x1a
+#define UVD_SUVD_CGC_STATUS__IME_HEVC_DCLK__SHIFT 0x1b
+#define UVD_SUVD_CGC_STATUS__EFC_DCLK__SHIFT 0x1c
+#define UVD_SUVD_CGC_STATUS__SAOE_DCLK__SHIFT 0x1d
+#define UVD_SUVD_CGC_STATUS__SRE_AV1_VCLK__SHIFT 0x1e
+#define UVD_SUVD_CGC_STATUS__SCM_AV1_DCLK__SHIFT 0x1f
+#define UVD_SUVD_CGC_STATUS__SRE_VCLK_MASK 0x00000001L
+#define UVD_SUVD_CGC_STATUS__SRE_DCLK_MASK 0x00000002L
+#define UVD_SUVD_CGC_STATUS__SIT_DCLK_MASK 0x00000004L
+#define UVD_SUVD_CGC_STATUS__SMP_DCLK_MASK 0x00000008L
+#define UVD_SUVD_CGC_STATUS__SCM_DCLK_MASK 0x00000010L
+#define UVD_SUVD_CGC_STATUS__SDB_DCLK_MASK 0x00000020L
+#define UVD_SUVD_CGC_STATUS__SRE_H264_VCLK_MASK 0x00000040L
+#define UVD_SUVD_CGC_STATUS__SRE_HEVC_VCLK_MASK 0x00000080L
+#define UVD_SUVD_CGC_STATUS__SIT_H264_DCLK_MASK 0x00000100L
+#define UVD_SUVD_CGC_STATUS__SIT_HEVC_DCLK_MASK 0x00000200L
+#define UVD_SUVD_CGC_STATUS__SCM_H264_DCLK_MASK 0x00000400L
+#define UVD_SUVD_CGC_STATUS__SCM_HEVC_DCLK_MASK 0x00000800L
+#define UVD_SUVD_CGC_STATUS__SDB_H264_DCLK_MASK 0x00001000L
+#define UVD_SUVD_CGC_STATUS__SDB_HEVC_DCLK_MASK 0x00002000L
+#define UVD_SUVD_CGC_STATUS__SCLR_DCLK_MASK 0x00004000L
+#define UVD_SUVD_CGC_STATUS__UVD_SC_MASK 0x00008000L
+#define UVD_SUVD_CGC_STATUS__ENT_DCLK_MASK 0x00010000L
+#define UVD_SUVD_CGC_STATUS__IME_DCLK_MASK 0x00020000L
+#define UVD_SUVD_CGC_STATUS__SIT_HEVC_DEC_DCLK_MASK 0x00040000L
+#define UVD_SUVD_CGC_STATUS__SIT_HEVC_ENC_DCLK_MASK 0x00080000L
+#define UVD_SUVD_CGC_STATUS__SITE_DCLK_MASK 0x00100000L
+#define UVD_SUVD_CGC_STATUS__SITE_HEVC_DCLK_MASK 0x00200000L
+#define UVD_SUVD_CGC_STATUS__SITE_HEVC_ENC_DCLK_MASK 0x00400000L
+#define UVD_SUVD_CGC_STATUS__SRE_VP9_VCLK_MASK 0x00800000L
+#define UVD_SUVD_CGC_STATUS__SCM_VP9_VCLK_MASK 0x01000000L
+#define UVD_SUVD_CGC_STATUS__SIT_VP9_DEC_DCLK_MASK 0x02000000L
+#define UVD_SUVD_CGC_STATUS__SDB_VP9_DCLK_MASK 0x04000000L
+#define UVD_SUVD_CGC_STATUS__IME_HEVC_DCLK_MASK 0x08000000L
+#define UVD_SUVD_CGC_STATUS__EFC_DCLK_MASK 0x10000000L
+#define UVD_SUVD_CGC_STATUS__SAOE_DCLK_MASK 0x20000000L
+#define UVD_SUVD_CGC_STATUS__SRE_AV1_VCLK_MASK 0x40000000L
+#define UVD_SUVD_CGC_STATUS__SCM_AV1_DCLK_MASK 0x80000000L
+//UVD_GPCOM_VCPU_CMD
+#define UVD_GPCOM_VCPU_CMD__CMD_SEND__SHIFT 0x0
+#define UVD_GPCOM_VCPU_CMD__CMD__SHIFT 0x1
+#define UVD_GPCOM_VCPU_CMD__CMD_SOURCE__SHIFT 0x1f
+#define UVD_GPCOM_VCPU_CMD__CMD_SEND_MASK 0x00000001L
+#define UVD_GPCOM_VCPU_CMD__CMD_MASK 0x7FFFFFFEL
+#define UVD_GPCOM_VCPU_CMD__CMD_SOURCE_MASK 0x80000000L
+
+
+// addressBlock: aid_uvd0_ecpudec
+//UVD_VCPU_CACHE_OFFSET0
+#define UVD_VCPU_CACHE_OFFSET0__CACHE_OFFSET0__SHIFT 0x0
+#define UVD_VCPU_CACHE_OFFSET0__CACHE_OFFSET0_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_SIZE0
+#define UVD_VCPU_CACHE_SIZE0__CACHE_SIZE0__SHIFT 0x0
+#define UVD_VCPU_CACHE_SIZE0__CACHE_SIZE0_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_OFFSET1
+#define UVD_VCPU_CACHE_OFFSET1__CACHE_OFFSET1__SHIFT 0x0
+#define UVD_VCPU_CACHE_OFFSET1__CACHE_OFFSET1_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_SIZE1
+#define UVD_VCPU_CACHE_SIZE1__CACHE_SIZE1__SHIFT 0x0
+#define UVD_VCPU_CACHE_SIZE1__CACHE_SIZE1_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_OFFSET2
+#define UVD_VCPU_CACHE_OFFSET2__CACHE_OFFSET2__SHIFT 0x0
+#define UVD_VCPU_CACHE_OFFSET2__CACHE_OFFSET2_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_SIZE2
+#define UVD_VCPU_CACHE_SIZE2__CACHE_SIZE2__SHIFT 0x0
+#define UVD_VCPU_CACHE_SIZE2__CACHE_SIZE2_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_OFFSET3
+#define UVD_VCPU_CACHE_OFFSET3__CACHE_OFFSET3__SHIFT 0x0
+#define UVD_VCPU_CACHE_OFFSET3__CACHE_OFFSET3_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_SIZE3
+#define UVD_VCPU_CACHE_SIZE3__CACHE_SIZE3__SHIFT 0x0
+#define UVD_VCPU_CACHE_SIZE3__CACHE_SIZE3_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_OFFSET4
+#define UVD_VCPU_CACHE_OFFSET4__CACHE_OFFSET4__SHIFT 0x0
+#define UVD_VCPU_CACHE_OFFSET4__CACHE_OFFSET4_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_SIZE4
+#define UVD_VCPU_CACHE_SIZE4__CACHE_SIZE4__SHIFT 0x0
+#define UVD_VCPU_CACHE_SIZE4__CACHE_SIZE4_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_OFFSET5
+#define UVD_VCPU_CACHE_OFFSET5__CACHE_OFFSET5__SHIFT 0x0
+#define UVD_VCPU_CACHE_OFFSET5__CACHE_OFFSET5_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_SIZE5
+#define UVD_VCPU_CACHE_SIZE5__CACHE_SIZE5__SHIFT 0x0
+#define UVD_VCPU_CACHE_SIZE5__CACHE_SIZE5_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_OFFSET6
+#define UVD_VCPU_CACHE_OFFSET6__CACHE_OFFSET6__SHIFT 0x0
+#define UVD_VCPU_CACHE_OFFSET6__CACHE_OFFSET6_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_SIZE6
+#define UVD_VCPU_CACHE_SIZE6__CACHE_SIZE6__SHIFT 0x0
+#define UVD_VCPU_CACHE_SIZE6__CACHE_SIZE6_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_OFFSET7
+#define UVD_VCPU_CACHE_OFFSET7__CACHE_OFFSET7__SHIFT 0x0
+#define UVD_VCPU_CACHE_OFFSET7__CACHE_OFFSET7_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_SIZE7
+#define UVD_VCPU_CACHE_SIZE7__CACHE_SIZE7__SHIFT 0x0
+#define UVD_VCPU_CACHE_SIZE7__CACHE_SIZE7_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_OFFSET8
+#define UVD_VCPU_CACHE_OFFSET8__CACHE_OFFSET8__SHIFT 0x0
+#define UVD_VCPU_CACHE_OFFSET8__CACHE_OFFSET8_MASK 0x001FFFFFL
+//UVD_VCPU_CACHE_SIZE8
+#define UVD_VCPU_CACHE_SIZE8__CACHE_SIZE8__SHIFT 0x0
+#define UVD_VCPU_CACHE_SIZE8__CACHE_SIZE8_MASK 0x001FFFFFL
+//UVD_VCPU_NONCACHE_OFFSET0
+#define UVD_VCPU_NONCACHE_OFFSET0__NONCACHE_OFFSET0__SHIFT 0x0
+#define UVD_VCPU_NONCACHE_OFFSET0__NONCACHE_OFFSET0_MASK 0x01FFFFFFL
+//UVD_VCPU_NONCACHE_SIZE0
+#define UVD_VCPU_NONCACHE_SIZE0__NONCACHE_SIZE0__SHIFT 0x0
+#define UVD_VCPU_NONCACHE_SIZE0__NONCACHE_SIZE0_MASK 0x001FFFFFL
+//UVD_VCPU_NONCACHE_OFFSET1
+#define UVD_VCPU_NONCACHE_OFFSET1__NONCACHE_OFFSET1__SHIFT 0x0
+#define UVD_VCPU_NONCACHE_OFFSET1__NONCACHE_OFFSET1_MASK 0x01FFFFFFL
+//UVD_VCPU_NONCACHE_SIZE1
+#define UVD_VCPU_NONCACHE_SIZE1__NONCACHE_SIZE1__SHIFT 0x0
+#define UVD_VCPU_NONCACHE_SIZE1__NONCACHE_SIZE1_MASK 0x001FFFFFL
+//UVD_VCPU_CNTL
+#define UVD_VCPU_CNTL__IRQ_ERR__SHIFT 0x0
+#define UVD_VCPU_CNTL__AXI_MAX_BRST_SIZE_IS_4__SHIFT 0x4
+#define UVD_VCPU_CNTL__PMB_ED_ENABLE__SHIFT 0x5
+#define UVD_VCPU_CNTL__PMB_SOFT_RESET__SHIFT 0x6
+#define UVD_VCPU_CNTL__RBBM_SOFT_RESET__SHIFT 0x7
+#define UVD_VCPU_CNTL__ABORT_REQ__SHIFT 0x8
+#define UVD_VCPU_CNTL__CLK_EN__SHIFT 0x9
+#define UVD_VCPU_CNTL__TRCE_EN__SHIFT 0xa
+#define UVD_VCPU_CNTL__TRCE_MUX__SHIFT 0xb
+#define UVD_VCPU_CNTL__DBG_MUX__SHIFT 0xd
+#define UVD_VCPU_CNTL__JTAG_EN__SHIFT 0x10
+#define UVD_VCPU_CNTL__TIMEOUT_DIS__SHIFT 0x12
+#define UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT 0x14
+#define UVD_VCPU_CNTL__BLK_RST__SHIFT 0x1c
+#define UVD_VCPU_CNTL__RUNSTALL__SHIFT 0x1d
+#define UVD_VCPU_CNTL__SRE_CMDIF_DRST__SHIFT 0x1e
+#define UVD_VCPU_CNTL__SRE_CMDIF_VRST__SHIFT 0x1f
+#define UVD_VCPU_CNTL__IRQ_ERR_MASK 0x0000000FL
+#define UVD_VCPU_CNTL__AXI_MAX_BRST_SIZE_IS_4_MASK 0x00000010L
+#define UVD_VCPU_CNTL__PMB_ED_ENABLE_MASK 0x00000020L
+#define UVD_VCPU_CNTL__PMB_SOFT_RESET_MASK 0x00000040L
+#define UVD_VCPU_CNTL__RBBM_SOFT_RESET_MASK 0x00000080L
+#define UVD_VCPU_CNTL__ABORT_REQ_MASK 0x00000100L
+#define UVD_VCPU_CNTL__CLK_EN_MASK 0x00000200L
+#define UVD_VCPU_CNTL__TRCE_EN_MASK 0x00000400L
+#define UVD_VCPU_CNTL__TRCE_MUX_MASK 0x00001800L
+#define UVD_VCPU_CNTL__DBG_MUX_MASK 0x0000E000L
+#define UVD_VCPU_CNTL__JTAG_EN_MASK 0x00010000L
+#define UVD_VCPU_CNTL__TIMEOUT_DIS_MASK 0x00040000L
+#define UVD_VCPU_CNTL__PRB_TIMEOUT_VAL_MASK 0x0FF00000L
+#define UVD_VCPU_CNTL__BLK_RST_MASK 0x10000000L
+#define UVD_VCPU_CNTL__RUNSTALL_MASK 0x20000000L
+#define UVD_VCPU_CNTL__SRE_CMDIF_DRST_MASK 0x40000000L
+#define UVD_VCPU_CNTL__SRE_CMDIF_VRST_MASK 0x80000000L
+//UVD_VCPU_PRID
+#define UVD_VCPU_PRID__PRID__SHIFT 0x0
+#define UVD_VCPU_PRID__PRID_MASK 0x0000FFFFL
+//UVD_VCPU_TRCE
+#define UVD_VCPU_TRCE__PC__SHIFT 0x0
+#define UVD_VCPU_TRCE__PC_MASK 0x0FFFFFFFL
+//UVD_VCPU_TRCE_RD
+#define UVD_VCPU_TRCE_RD__DATA__SHIFT 0x0
+#define UVD_VCPU_TRCE_RD__DATA_MASK 0xFFFFFFFFL
+//UVD_VCPU_IND_INDEX
+#define UVD_VCPU_IND_INDEX__INDEX__SHIFT 0x0
+#define UVD_VCPU_IND_INDEX__INDEX_MASK 0x000001FFL
+//UVD_VCPU_IND_DATA
+#define UVD_VCPU_IND_DATA__DATA__SHIFT 0x0
+#define UVD_VCPU_IND_DATA__DATA_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_uvd0_uvd_mpcdec
+//UVD_MP_SWAP_CNTL
+#define UVD_MP_SWAP_CNTL__MP_REF0_MC_SWAP__SHIFT 0x0
+#define UVD_MP_SWAP_CNTL__MP_REF1_MC_SWAP__SHIFT 0x2
+#define UVD_MP_SWAP_CNTL__MP_REF2_MC_SWAP__SHIFT 0x4
+#define UVD_MP_SWAP_CNTL__MP_REF3_MC_SWAP__SHIFT 0x6
+#define UVD_MP_SWAP_CNTL__MP_REF4_MC_SWAP__SHIFT 0x8
+#define UVD_MP_SWAP_CNTL__MP_REF5_MC_SWAP__SHIFT 0xa
+#define UVD_MP_SWAP_CNTL__MP_REF6_MC_SWAP__SHIFT 0xc
+#define UVD_MP_SWAP_CNTL__MP_REF7_MC_SWAP__SHIFT 0xe
+#define UVD_MP_SWAP_CNTL__MP_REF8_MC_SWAP__SHIFT 0x10
+#define UVD_MP_SWAP_CNTL__MP_REF9_MC_SWAP__SHIFT 0x12
+#define UVD_MP_SWAP_CNTL__MP_REF10_MC_SWAP__SHIFT 0x14
+#define UVD_MP_SWAP_CNTL__MP_REF11_MC_SWAP__SHIFT 0x16
+#define UVD_MP_SWAP_CNTL__MP_REF12_MC_SWAP__SHIFT 0x18
+#define UVD_MP_SWAP_CNTL__MP_REF13_MC_SWAP__SHIFT 0x1a
+#define UVD_MP_SWAP_CNTL__MP_REF14_MC_SWAP__SHIFT 0x1c
+#define UVD_MP_SWAP_CNTL__MP_REF15_MC_SWAP__SHIFT 0x1e
+#define UVD_MP_SWAP_CNTL__MP_REF0_MC_SWAP_MASK 0x00000003L
+#define UVD_MP_SWAP_CNTL__MP_REF1_MC_SWAP_MASK 0x0000000CL
+#define UVD_MP_SWAP_CNTL__MP_REF2_MC_SWAP_MASK 0x00000030L
+#define UVD_MP_SWAP_CNTL__MP_REF3_MC_SWAP_MASK 0x000000C0L
+#define UVD_MP_SWAP_CNTL__MP_REF4_MC_SWAP_MASK 0x00000300L
+#define UVD_MP_SWAP_CNTL__MP_REF5_MC_SWAP_MASK 0x00000C00L
+#define UVD_MP_SWAP_CNTL__MP_REF6_MC_SWAP_MASK 0x00003000L
+#define UVD_MP_SWAP_CNTL__MP_REF7_MC_SWAP_MASK 0x0000C000L
+#define UVD_MP_SWAP_CNTL__MP_REF8_MC_SWAP_MASK 0x00030000L
+#define UVD_MP_SWAP_CNTL__MP_REF9_MC_SWAP_MASK 0x000C0000L
+#define UVD_MP_SWAP_CNTL__MP_REF10_MC_SWAP_MASK 0x00300000L
+#define UVD_MP_SWAP_CNTL__MP_REF11_MC_SWAP_MASK 0x00C00000L
+#define UVD_MP_SWAP_CNTL__MP_REF12_MC_SWAP_MASK 0x03000000L
+#define UVD_MP_SWAP_CNTL__MP_REF13_MC_SWAP_MASK 0x0C000000L
+#define UVD_MP_SWAP_CNTL__MP_REF14_MC_SWAP_MASK 0x30000000L
+#define UVD_MP_SWAP_CNTL__MP_REF15_MC_SWAP_MASK 0xC0000000L
+//UVD_MP_SWAP_CNTL2
+#define UVD_MP_SWAP_CNTL2__MP_REF16_MC_SWAP__SHIFT 0x0
+#define UVD_MP_SWAP_CNTL2__MP_REF16_MC_SWAP_MASK 0x00000003L
+//UVD_MPC_LUMA_SRCH
+#define UVD_MPC_LUMA_SRCH__CNTR__SHIFT 0x0
+#define UVD_MPC_LUMA_SRCH__CNTR_MASK 0xFFFFFFFFL
+//UVD_MPC_LUMA_HIT
+#define UVD_MPC_LUMA_HIT__CNTR__SHIFT 0x0
+#define UVD_MPC_LUMA_HIT__CNTR_MASK 0xFFFFFFFFL
+//UVD_MPC_LUMA_HITPEND
+#define UVD_MPC_LUMA_HITPEND__CNTR__SHIFT 0x0
+#define UVD_MPC_LUMA_HITPEND__CNTR_MASK 0xFFFFFFFFL
+//UVD_MPC_CHROMA_SRCH
+#define UVD_MPC_CHROMA_SRCH__CNTR__SHIFT 0x0
+#define UVD_MPC_CHROMA_SRCH__CNTR_MASK 0xFFFFFFFFL
+//UVD_MPC_CHROMA_HIT
+#define UVD_MPC_CHROMA_HIT__CNTR__SHIFT 0x0
+#define UVD_MPC_CHROMA_HIT__CNTR_MASK 0xFFFFFFFFL
+//UVD_MPC_CHROMA_HITPEND
+#define UVD_MPC_CHROMA_HITPEND__CNTR__SHIFT 0x0
+#define UVD_MPC_CHROMA_HITPEND__CNTR_MASK 0xFFFFFFFFL
+//UVD_MPC_CNTL
+#define UVD_MPC_CNTL__BLK_RST__SHIFT 0x0
+#define UVD_MPC_CNTL__REG_MPC1_PERF_SELECT__SHIFT 0x1
+#define UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT 0x3
+#define UVD_MPC_CNTL__PERF_RST__SHIFT 0x6
+#define UVD_MPC_CNTL__REG_MPC_CNTL_BACKWARD_COMPATIBILITY__SHIFT 0x7
+#define UVD_MPC_CNTL__DBG_MUX__SHIFT 0x8
+#define UVD_MPC_CNTL__AVE_WEIGHT__SHIFT 0x10
+#define UVD_MPC_CNTL__URGENT_EN__SHIFT 0x12
+#define UVD_MPC_CNTL__SMPAT_REQ_SPEED_UP__SHIFT 0x13
+#define UVD_MPC_CNTL__TEST_MODE_EN__SHIFT 0x14
+#define UVD_MPC_CNTL__BLK_RST_MASK 0x00000001L
+#define UVD_MPC_CNTL__REG_MPC1_PERF_SELECT_MASK 0x00000002L
+#define UVD_MPC_CNTL__REPLACEMENT_MODE_MASK 0x00000038L
+#define UVD_MPC_CNTL__PERF_RST_MASK 0x00000040L
+#define UVD_MPC_CNTL__REG_MPC_CNTL_BACKWARD_COMPATIBILITY_MASK 0x00000080L
+#define UVD_MPC_CNTL__DBG_MUX_MASK 0x00000F00L
+#define UVD_MPC_CNTL__AVE_WEIGHT_MASK 0x00030000L
+#define UVD_MPC_CNTL__URGENT_EN_MASK 0x00040000L
+#define UVD_MPC_CNTL__SMPAT_REQ_SPEED_UP_MASK 0x00080000L
+#define UVD_MPC_CNTL__TEST_MODE_EN_MASK 0x00300000L
+//UVD_MPC_PITCH
+#define UVD_MPC_PITCH__LUMA_PITCH__SHIFT 0x0
+#define UVD_MPC_PITCH__LUMA_PITCH_MASK 0x000007FFL
+//UVD_MPC_SET_MUXA0
+#define UVD_MPC_SET_MUXA0__VARA_0__SHIFT 0x0
+#define UVD_MPC_SET_MUXA0__VARA_1__SHIFT 0x6
+#define UVD_MPC_SET_MUXA0__VARA_2__SHIFT 0xc
+#define UVD_MPC_SET_MUXA0__VARA_3__SHIFT 0x12
+#define UVD_MPC_SET_MUXA0__VARA_4__SHIFT 0x18
+#define UVD_MPC_SET_MUXA0__VARA_0_MASK 0x0000003FL
+#define UVD_MPC_SET_MUXA0__VARA_1_MASK 0x00000FC0L
+#define UVD_MPC_SET_MUXA0__VARA_2_MASK 0x0003F000L
+#define UVD_MPC_SET_MUXA0__VARA_3_MASK 0x00FC0000L
+#define UVD_MPC_SET_MUXA0__VARA_4_MASK 0x3F000000L
+//UVD_MPC_SET_MUXA1
+#define UVD_MPC_SET_MUXA1__VARA_5__SHIFT 0x0
+#define UVD_MPC_SET_MUXA1__VARA_6__SHIFT 0x6
+#define UVD_MPC_SET_MUXA1__VARA_7__SHIFT 0xc
+#define UVD_MPC_SET_MUXA1__VARA_5_MASK 0x0000003FL
+#define UVD_MPC_SET_MUXA1__VARA_6_MASK 0x00000FC0L
+#define UVD_MPC_SET_MUXA1__VARA_7_MASK 0x0003F000L
+//UVD_MPC_SET_MUXB0
+#define UVD_MPC_SET_MUXB0__VARB_0__SHIFT 0x0
+#define UVD_MPC_SET_MUXB0__VARB_1__SHIFT 0x6
+#define UVD_MPC_SET_MUXB0__VARB_2__SHIFT 0xc
+#define UVD_MPC_SET_MUXB0__VARB_3__SHIFT 0x12
+#define UVD_MPC_SET_MUXB0__VARB_4__SHIFT 0x18
+#define UVD_MPC_SET_MUXB0__VARB_0_MASK 0x0000003FL
+#define UVD_MPC_SET_MUXB0__VARB_1_MASK 0x00000FC0L
+#define UVD_MPC_SET_MUXB0__VARB_2_MASK 0x0003F000L
+#define UVD_MPC_SET_MUXB0__VARB_3_MASK 0x00FC0000L
+#define UVD_MPC_SET_MUXB0__VARB_4_MASK 0x3F000000L
+//UVD_MPC_SET_MUXB1
+#define UVD_MPC_SET_MUXB1__VARB_5__SHIFT 0x0
+#define UVD_MPC_SET_MUXB1__VARB_6__SHIFT 0x6
+#define UVD_MPC_SET_MUXB1__VARB_7__SHIFT 0xc
+#define UVD_MPC_SET_MUXB1__VARB_5_MASK 0x0000003FL
+#define UVD_MPC_SET_MUXB1__VARB_6_MASK 0x00000FC0L
+#define UVD_MPC_SET_MUXB1__VARB_7_MASK 0x0003F000L
+//UVD_MPC_SET_MUX
+#define UVD_MPC_SET_MUX__SET_0__SHIFT 0x0
+#define UVD_MPC_SET_MUX__SET_1__SHIFT 0x3
+#define UVD_MPC_SET_MUX__SET_2__SHIFT 0x6
+#define UVD_MPC_SET_MUX__SET_0_MASK 0x00000007L
+#define UVD_MPC_SET_MUX__SET_1_MASK 0x00000038L
+#define UVD_MPC_SET_MUX__SET_2_MASK 0x000001C0L
+//UVD_MPC_SET_ALU
+#define UVD_MPC_SET_ALU__FUNCT__SHIFT 0x0
+#define UVD_MPC_SET_ALU__OPERAND__SHIFT 0x4
+#define UVD_MPC_SET_ALU__FUNCT_MASK 0x00000007L
+#define UVD_MPC_SET_ALU__OPERAND_MASK 0x00000FF0L
+//UVD_MPC_PERF0
+#define UVD_MPC_PERF0__MAX_LAT__SHIFT 0x0
+#define UVD_MPC_PERF0__MAX_LAT_MASK 0x000003FFL
+//UVD_MPC_PERF1
+#define UVD_MPC_PERF1__AVE_LAT__SHIFT 0x0
+#define UVD_MPC_PERF1__AVE_LAT_MASK 0x000003FFL
+//UVD_MPC_IND_INDEX
+#define UVD_MPC_IND_INDEX__INDEX__SHIFT 0x0
+#define UVD_MPC_IND_INDEX__INDEX_MASK 0x000001FFL
+//UVD_MPC_IND_DATA
+#define UVD_MPC_IND_DATA__DATA__SHIFT 0x0
+#define UVD_MPC_IND_DATA__DATA_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_uvd0_uvd_rbcdec
+//UVD_RBC_IB_SIZE
+#define UVD_RBC_IB_SIZE__IB_SIZE__SHIFT 0x4
+#define UVD_RBC_IB_SIZE__IB_SIZE_MASK 0x007FFFF0L
+//UVD_RBC_IB_SIZE_UPDATE
+#define UVD_RBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE__SHIFT 0x4
+#define UVD_RBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE_MASK 0x007FFFF0L
+//UVD_RBC_RB_CNTL
+#define UVD_RBC_RB_CNTL__RB_BUFSZ__SHIFT 0x0
+#define UVD_RBC_RB_CNTL__RB_BLKSZ__SHIFT 0x8
+#define UVD_RBC_RB_CNTL__RB_NO_FETCH__SHIFT 0x10
+#define UVD_RBC_RB_CNTL__RB_WPTR_POLL_EN__SHIFT 0x14
+#define UVD_RBC_RB_CNTL__RB_NO_UPDATE__SHIFT 0x18
+#define UVD_RBC_RB_CNTL__RB_RPTR_WR_EN__SHIFT 0x1c
+#define UVD_RBC_RB_CNTL__BLK_RST__SHIFT 0x1d
+#define UVD_RBC_RB_CNTL__RB_BUFSZ_MASK 0x0000001FL
+#define UVD_RBC_RB_CNTL__RB_BLKSZ_MASK 0x00001F00L
+#define UVD_RBC_RB_CNTL__RB_NO_FETCH_MASK 0x00010000L
+#define UVD_RBC_RB_CNTL__RB_WPTR_POLL_EN_MASK 0x00100000L
+#define UVD_RBC_RB_CNTL__RB_NO_UPDATE_MASK 0x01000000L
+#define UVD_RBC_RB_CNTL__RB_RPTR_WR_EN_MASK 0x10000000L
+#define UVD_RBC_RB_CNTL__BLK_RST_MASK 0x20000000L
+//UVD_RBC_RB_RPTR_ADDR
+#define UVD_RBC_RB_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x0
+#define UVD_RBC_RB_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xFFFFFFFFL
+//UVD_RBC_VCPU_ACCESS
+#define UVD_RBC_VCPU_ACCESS__ENABLE_RBC__SHIFT 0x0
+#define UVD_RBC_VCPU_ACCESS__ENABLE_RBC_MASK 0x00000001L
+//UVD_FW_SEMAPHORE_CNTL
+#define UVD_FW_SEMAPHORE_CNTL__START__SHIFT 0x0
+#define UVD_FW_SEMAPHORE_CNTL__BUSY__SHIFT 0x8
+#define UVD_FW_SEMAPHORE_CNTL__PASS__SHIFT 0x9
+#define UVD_FW_SEMAPHORE_CNTL__START_MASK 0x00000001L
+#define UVD_FW_SEMAPHORE_CNTL__BUSY_MASK 0x00000100L
+#define UVD_FW_SEMAPHORE_CNTL__PASS_MASK 0x00000200L
+//UVD_RBC_READ_REQ_URGENT_CNTL
+#define UVD_RBC_READ_REQ_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK__SHIFT 0x0
+#define UVD_RBC_READ_REQ_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK_MASK 0x00000003L
+//UVD_RBC_RB_WPTR_CNTL
+#define UVD_RBC_RB_WPTR_CNTL__RB_PRE_WRITE_TIMER__SHIFT 0x0
+#define UVD_RBC_RB_WPTR_CNTL__RB_PRE_WRITE_TIMER_MASK 0x00007FFFL
+//UVD_RBC_WPTR_STATUS
+#define UVD_RBC_WPTR_STATUS__RB_WPTR_IN_USE__SHIFT 0x4
+#define UVD_RBC_WPTR_STATUS__RB_WPTR_IN_USE_MASK 0x007FFFF0L
+//UVD_RBC_WPTR_POLL_CNTL
+#define UVD_RBC_WPTR_POLL_CNTL__POLL_FREQ__SHIFT 0x0
+#define UVD_RBC_WPTR_POLL_CNTL__IDLE_POLL_COUNT__SHIFT 0x10
+#define UVD_RBC_WPTR_POLL_CNTL__POLL_FREQ_MASK 0x0000FFFFL
+#define UVD_RBC_WPTR_POLL_CNTL__IDLE_POLL_COUNT_MASK 0xFFFF0000L
+//UVD_RBC_WPTR_POLL_ADDR
+#define UVD_RBC_WPTR_POLL_ADDR__POLL_ADDR__SHIFT 0x2
+#define UVD_RBC_WPTR_POLL_ADDR__POLL_ADDR_MASK 0xFFFFFFFCL
+//UVD_SEMA_CMD
+#define UVD_SEMA_CMD__REQ_CMD__SHIFT 0x0
+#define UVD_SEMA_CMD__WR_PHASE__SHIFT 0x4
+#define UVD_SEMA_CMD__MODE__SHIFT 0x6
+#define UVD_SEMA_CMD__VMID_EN__SHIFT 0x7
+#define UVD_SEMA_CMD__VMID__SHIFT 0x8
+#define UVD_SEMA_CMD__REQ_CMD_MASK 0x0000000FL
+#define UVD_SEMA_CMD__WR_PHASE_MASK 0x00000030L
+#define UVD_SEMA_CMD__MODE_MASK 0x00000040L
+#define UVD_SEMA_CMD__VMID_EN_MASK 0x00000080L
+#define UVD_SEMA_CMD__VMID_MASK 0x00000F00L
+//UVD_SEMA_ADDR_LOW
+#define UVD_SEMA_ADDR_LOW__ADDR_26_3__SHIFT 0x0
+#define UVD_SEMA_ADDR_LOW__ADDR_26_3_MASK 0x00FFFFFFL
+//UVD_SEMA_ADDR_HIGH
+#define UVD_SEMA_ADDR_HIGH__ADDR_47_27__SHIFT 0x0
+#define UVD_SEMA_ADDR_HIGH__ADDR_47_27_MASK 0x001FFFFFL
+//UVD_ENGINE_CNTL
+#define UVD_ENGINE_CNTL__ENGINE_START__SHIFT 0x0
+#define UVD_ENGINE_CNTL__ENGINE_START_MODE__SHIFT 0x1
+#define UVD_ENGINE_CNTL__NJ_PF_HANDLE_DISABLE__SHIFT 0x2
+#define UVD_ENGINE_CNTL__ENGINE_START_MASK 0x00000001L
+#define UVD_ENGINE_CNTL__ENGINE_START_MODE_MASK 0x00000002L
+#define UVD_ENGINE_CNTL__NJ_PF_HANDLE_DISABLE_MASK 0x00000004L
+//UVD_SEMA_TIMEOUT_STATUS
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_WAIT_INCOMPLETE_TIMEOUT_STAT__SHIFT 0x0
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_WAIT_FAULT_TIMEOUT_STAT__SHIFT 0x1
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_SIGNAL_INCOMPLETE_TIMEOUT_STAT__SHIFT 0x2
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_TIMEOUT_CLEAR__SHIFT 0x3
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_WAIT_INCOMPLETE_TIMEOUT_STAT_MASK 0x00000001L
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_WAIT_FAULT_TIMEOUT_STAT_MASK 0x00000002L
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_SIGNAL_INCOMPLETE_TIMEOUT_STAT_MASK 0x00000004L
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_TIMEOUT_CLEAR_MASK 0x00000008L
+//UVD_SEMA_CNTL
+#define UVD_SEMA_CNTL__SEMAPHORE_EN__SHIFT 0x0
+#define UVD_SEMA_CNTL__ADVANCED_MODE_DIS__SHIFT 0x1
+#define UVD_SEMA_CNTL__SEMAPHORE_EN_MASK 0x00000001L
+#define UVD_SEMA_CNTL__ADVANCED_MODE_DIS_MASK 0x00000002L
+//UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SIGNAL_INCOMPLETE_EN__SHIFT 0x0
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SIGNAL_INCOMPLETE_COUNT__SHIFT 0x1
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__RESEND_TIMER__SHIFT 0x18
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SIGNAL_INCOMPLETE_EN_MASK 0x00000001L
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SIGNAL_INCOMPLETE_COUNT_MASK 0x001FFFFEL
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__RESEND_TIMER_MASK 0x07000000L
+//UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__WAIT_FAULT_EN__SHIFT 0x0
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__WAIT_FAULT_COUNT__SHIFT 0x1
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__RESEND_TIMER__SHIFT 0x18
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__WAIT_FAULT_EN_MASK 0x00000001L
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__WAIT_FAULT_COUNT_MASK 0x001FFFFEL
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__RESEND_TIMER_MASK 0x07000000L
+//UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__WAIT_INCOMPLETE_EN__SHIFT 0x0
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__WAIT_INCOMPLETE_COUNT__SHIFT 0x1
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__RESEND_TIMER__SHIFT 0x18
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__WAIT_INCOMPLETE_EN_MASK 0x00000001L
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__WAIT_INCOMPLETE_COUNT_MASK 0x001FFFFEL
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__RESEND_TIMER_MASK 0x07000000L
+//UVD_JOB_START
+#define UVD_JOB_START__JOB_START__SHIFT 0x0
+#define UVD_JOB_START__JOB_START_MASK 0x00000001L
+//UVD_RBC_BUF_STATUS
+#define UVD_RBC_BUF_STATUS__RB_BUF_VALID__SHIFT 0x0
+#define UVD_RBC_BUF_STATUS__IB_BUF_VALID__SHIFT 0x8
+#define UVD_RBC_BUF_STATUS__RB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_RBC_BUF_STATUS__IB_BUF_RD_ADDR__SHIFT 0x13
+#define UVD_RBC_BUF_STATUS__RB_BUF_WR_ADDR__SHIFT 0x16
+#define UVD_RBC_BUF_STATUS__IB_BUF_WR_ADDR__SHIFT 0x19
+#define UVD_RBC_BUF_STATUS__RB_BUF_VALID_MASK 0x000000FFL
+#define UVD_RBC_BUF_STATUS__IB_BUF_VALID_MASK 0x0000FF00L
+#define UVD_RBC_BUF_STATUS__RB_BUF_RD_ADDR_MASK 0x00070000L
+#define UVD_RBC_BUF_STATUS__IB_BUF_RD_ADDR_MASK 0x00380000L
+#define UVD_RBC_BUF_STATUS__RB_BUF_WR_ADDR_MASK 0x01C00000L
+#define UVD_RBC_BUF_STATUS__IB_BUF_WR_ADDR_MASK 0x0E000000L
+//UVD_RBC_SWAP_CNTL
+#define UVD_RBC_SWAP_CNTL__RB_MC_SWAP__SHIFT 0x0
+#define UVD_RBC_SWAP_CNTL__IB_MC_SWAP__SHIFT 0x2
+#define UVD_RBC_SWAP_CNTL__RB_RPTR_MC_SWAP__SHIFT 0x4
+#define UVD_RBC_SWAP_CNTL__RB_WR_MC_SWAP__SHIFT 0x1a
+#define UVD_RBC_SWAP_CNTL__RB_MC_SWAP_MASK 0x00000003L
+#define UVD_RBC_SWAP_CNTL__IB_MC_SWAP_MASK 0x0000000CL
+#define UVD_RBC_SWAP_CNTL__RB_RPTR_MC_SWAP_MASK 0x00000030L
+#define UVD_RBC_SWAP_CNTL__RB_WR_MC_SWAP_MASK 0x0C000000L
+
+
+// addressBlock: aid_uvd0_lmi_adpdec
+//UVD_LMI_RE_64BIT_BAR_LOW
+#define UVD_LMI_RE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_RE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_RE_64BIT_BAR_HIGH
+#define UVD_LMI_RE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_RE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_IT_64BIT_BAR_LOW
+#define UVD_LMI_IT_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_IT_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_IT_64BIT_BAR_HIGH
+#define UVD_LMI_IT_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_IT_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MP_64BIT_BAR_LOW
+#define UVD_LMI_MP_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MP_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MP_64BIT_BAR_HIGH
+#define UVD_LMI_MP_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MP_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_CM_64BIT_BAR_LOW
+#define UVD_LMI_CM_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_CM_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_CM_64BIT_BAR_HIGH
+#define UVD_LMI_CM_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_CM_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_DB_64BIT_BAR_LOW
+#define UVD_LMI_DB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_DB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_DB_64BIT_BAR_HIGH
+#define UVD_LMI_DB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_DB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_DBW_64BIT_BAR_LOW
+#define UVD_LMI_DBW_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_DBW_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_DBW_64BIT_BAR_HIGH
+#define UVD_LMI_DBW_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_DBW_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_IDCT_64BIT_BAR_LOW
+#define UVD_LMI_IDCT_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_IDCT_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_IDCT_64BIT_BAR_HIGH
+#define UVD_LMI_IDCT_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_IDCT_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MPRD_S0_64BIT_BAR_LOW
+#define UVD_LMI_MPRD_S0_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MPRD_S0_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MPRD_S0_64BIT_BAR_HIGH
+#define UVD_LMI_MPRD_S0_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MPRD_S0_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MPRD_S1_64BIT_BAR_LOW
+#define UVD_LMI_MPRD_S1_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MPRD_S1_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MPRD_S1_64BIT_BAR_HIGH
+#define UVD_LMI_MPRD_S1_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MPRD_S1_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MPRD_DBW_64BIT_BAR_LOW
+#define UVD_LMI_MPRD_DBW_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MPRD_DBW_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MPRD_DBW_64BIT_BAR_HIGH
+#define UVD_LMI_MPRD_DBW_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MPRD_DBW_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MPC_64BIT_BAR_LOW
+#define UVD_LMI_MPC_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MPC_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MPC_64BIT_BAR_HIGH
+#define UVD_LMI_MPC_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MPC_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_RBC_RB_64BIT_BAR_LOW
+#define UVD_LMI_RBC_RB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_RBC_RB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_RBC_RB_64BIT_BAR_HIGH
+#define UVD_LMI_RBC_RB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_RBC_RB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_RBC_IB_64BIT_BAR_LOW
+#define UVD_LMI_RBC_IB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_RBC_IB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_RBC_IB_64BIT_BAR_HIGH
+#define UVD_LMI_RBC_IB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_RBC_IB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_LBSI_64BIT_BAR_LOW
+#define UVD_LMI_LBSI_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_LBSI_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_LBSI_64BIT_BAR_HIGH
+#define UVD_LMI_LBSI_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_LBSI_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_NC0_64BIT_BAR_LOW
+#define UVD_LMI_VCPU_NC0_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_VCPU_NC0_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_NC0_64BIT_BAR_HIGH
+#define UVD_LMI_VCPU_NC0_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_VCPU_NC0_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_NC1_64BIT_BAR_LOW
+#define UVD_LMI_VCPU_NC1_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_VCPU_NC1_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_NC1_64BIT_BAR_HIGH
+#define UVD_LMI_VCPU_NC1_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_VCPU_NC1_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE_64BIT_BAR_LOW
+#define UVD_LMI_VCPU_CACHE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH
+#define UVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_CENC_64BIT_BAR_LOW
+#define UVD_LMI_CENC_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_CENC_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_CENC_64BIT_BAR_HIGH
+#define UVD_LMI_CENC_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_CENC_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_SRE_64BIT_BAR_LOW
+#define UVD_LMI_SRE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_SRE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_SRE_64BIT_BAR_HIGH
+#define UVD_LMI_SRE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_SRE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_GPGPU_64BIT_BAR_LOW
+#define UVD_LMI_MIF_GPGPU_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_GPGPU_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_GPGPU_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_GPGPU_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_GPGPU_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_CURR_LUMA_64BIT_BAR_LOW
+#define UVD_LMI_MIF_CURR_LUMA_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_CURR_LUMA_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_CURR_LUMA_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_CURR_LUMA_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_CURR_LUMA_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_CURR_CHROMA_64BIT_BAR_LOW
+#define UVD_LMI_MIF_CURR_CHROMA_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_CURR_CHROMA_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_CURR_CHROMA_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_CURR_CHROMA_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_CURR_CHROMA_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_REF_64BIT_BAR_LOW
+#define UVD_LMI_MIF_REF_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_REF_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_REF_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_REF_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_REF_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_DBW_64BIT_BAR_LOW
+#define UVD_LMI_MIF_DBW_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_DBW_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_DBW_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_DBW_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_DBW_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_CM_COLOC_64BIT_BAR_LOW
+#define UVD_LMI_MIF_CM_COLOC_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_CM_COLOC_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_CM_COLOC_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_CM_COLOC_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_CM_COLOC_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSP0_64BIT_BAR_LOW
+#define UVD_LMI_MIF_BSP0_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_BSP0_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSP0_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_BSP0_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_BSP0_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSP1_64BIT_BAR_LOW
+#define UVD_LMI_MIF_BSP1_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_BSP1_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSP1_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_BSP1_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_BSP1_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSP2_64BIT_BAR_LOW
+#define UVD_LMI_MIF_BSP2_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_BSP2_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSP2_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_BSP2_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_BSP2_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSP3_64BIT_BAR_LOW
+#define UVD_LMI_MIF_BSP3_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_BSP3_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSP3_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_BSP3_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_BSP3_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSD0_64BIT_BAR_LOW
+#define UVD_LMI_MIF_BSD0_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_BSD0_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSD0_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_BSD0_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_BSD0_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSD1_64BIT_BAR_LOW
+#define UVD_LMI_MIF_BSD1_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_BSD1_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSD1_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_BSD1_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_BSD1_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSD2_64BIT_BAR_LOW
+#define UVD_LMI_MIF_BSD2_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_BSD2_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSD2_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_BSD2_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_BSD2_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSD3_64BIT_BAR_LOW
+#define UVD_LMI_MIF_BSD3_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_BSD3_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSD3_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_BSD3_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_BSD3_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSD4_64BIT_BAR_LOW
+#define UVD_LMI_MIF_BSD4_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_BSD4_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_BSD4_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_BSD4_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_BSD4_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW
+#define UVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH
+#define UVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE8_64BIT_BAR_LOW
+#define UVD_LMI_VCPU_CACHE8_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE8_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE8_64BIT_BAR_HIGH
+#define UVD_LMI_VCPU_CACHE8_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE8_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW
+#define UVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH
+#define UVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE3_64BIT_BAR_LOW
+#define UVD_LMI_VCPU_CACHE3_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE3_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE3_64BIT_BAR_HIGH
+#define UVD_LMI_VCPU_CACHE3_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE3_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE4_64BIT_BAR_LOW
+#define UVD_LMI_VCPU_CACHE4_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE4_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE4_64BIT_BAR_HIGH
+#define UVD_LMI_VCPU_CACHE4_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE4_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE5_64BIT_BAR_LOW
+#define UVD_LMI_VCPU_CACHE5_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE5_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE5_64BIT_BAR_HIGH
+#define UVD_LMI_VCPU_CACHE5_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE5_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE6_64BIT_BAR_LOW
+#define UVD_LMI_VCPU_CACHE6_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE6_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE6_64BIT_BAR_HIGH
+#define UVD_LMI_VCPU_CACHE6_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE6_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE7_64BIT_BAR_LOW
+#define UVD_LMI_VCPU_CACHE7_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE7_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_VCPU_CACHE7_64BIT_BAR_HIGH
+#define UVD_LMI_VCPU_CACHE7_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE7_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_SCLR_64BIT_BAR_LOW
+#define UVD_LMI_MIF_SCLR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_SCLR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_SCLR_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_SCLR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_SCLR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_SCLR2_64BIT_BAR_LOW
+#define UVD_LMI_MIF_SCLR2_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_SCLR2_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_SCLR2_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_SCLR2_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_SCLR2_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_SPH_64BIT_BAR_HIGH
+#define UVD_LMI_SPH_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_SPH_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_IMAGEPASTE_LUMA_64BIT_BAR_LOW
+#define UVD_LMI_MIF_IMAGEPASTE_LUMA_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_IMAGEPASTE_LUMA_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_IMAGEPASTE_LUMA_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_IMAGEPASTE_LUMA_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_IMAGEPASTE_LUMA_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_IMAGEPASTE_CHROMA_64BIT_BAR_LOW
+#define UVD_LMI_MIF_IMAGEPASTE_CHROMA_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_IMAGEPASTE_CHROMA_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_IMAGEPASTE_CHROMA_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_IMAGEPASTE_CHROMA_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_IMAGEPASTE_CHROMA_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_PRIVACY_LUMA_64BIT_BAR_LOW
+#define UVD_LMI_MIF_PRIVACY_LUMA_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_PRIVACY_LUMA_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_PRIVACY_LUMA_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_PRIVACY_LUMA_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_PRIVACY_LUMA_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_PRIVACY_CHROMA_64BIT_BAR_LOW
+#define UVD_LMI_MIF_PRIVACY_CHROMA_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_PRIVACY_CHROMA_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_PRIVACY_CHROMA_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_PRIVACY_CHROMA_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_PRIVACY_CHROMA_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_ADP_ATOMIC_CONFIG
+#define UVD_ADP_ATOMIC_CONFIG__ATOMIC_USER0_WR_CACHE__SHIFT 0x0
+#define UVD_ADP_ATOMIC_CONFIG__ATOMIC_USER1_WR_CACHE__SHIFT 0x4
+#define UVD_ADP_ATOMIC_CONFIG__ATOMIC_USER2_WR_CACHE__SHIFT 0x8
+#define UVD_ADP_ATOMIC_CONFIG__ATOMIC_USER3_WR_CACHE__SHIFT 0xc
+#define UVD_ADP_ATOMIC_CONFIG__ATOMIC_RD_URG__SHIFT 0x10
+#define UVD_ADP_ATOMIC_CONFIG__ATOMIC_USER0_WR_CACHE_MASK 0x0000000FL
+#define UVD_ADP_ATOMIC_CONFIG__ATOMIC_USER1_WR_CACHE_MASK 0x000000F0L
+#define UVD_ADP_ATOMIC_CONFIG__ATOMIC_USER2_WR_CACHE_MASK 0x00000F00L
+#define UVD_ADP_ATOMIC_CONFIG__ATOMIC_USER3_WR_CACHE_MASK 0x0000F000L
+#define UVD_ADP_ATOMIC_CONFIG__ATOMIC_RD_URG_MASK 0x000F0000L
+//UVD_LMI_ARB_CTRL2
+#define UVD_LMI_ARB_CTRL2__CENC_RD_WAIT_EN__SHIFT 0x0
+#define UVD_LMI_ARB_CTRL2__ATOMIC_WR_WAIT_EN__SHIFT 0x1
+#define UVD_LMI_ARB_CTRL2__CENC_RD_MAX_BURST__SHIFT 0x2
+#define UVD_LMI_ARB_CTRL2__ATOMIC_WR_MAX_BURST__SHIFT 0x6
+#define UVD_LMI_ARB_CTRL2__MIF_RD_REQ_RET_MAX__SHIFT 0xa
+#define UVD_LMI_ARB_CTRL2__MIF_WR_REQ_RET_MAX__SHIFT 0x14
+#define UVD_LMI_ARB_CTRL2__CENC_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_LMI_ARB_CTRL2__ATOMIC_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_LMI_ARB_CTRL2__CENC_RD_MAX_BURST_MASK 0x0000003CL
+#define UVD_LMI_ARB_CTRL2__ATOMIC_WR_MAX_BURST_MASK 0x000003C0L
+#define UVD_LMI_ARB_CTRL2__MIF_RD_REQ_RET_MAX_MASK 0x000FFC00L
+#define UVD_LMI_ARB_CTRL2__MIF_WR_REQ_RET_MAX_MASK 0xFFF00000L
+//UVD_LMI_VCPU_CACHE_VMIDS_MULTI
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE1_VMID__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE2_VMID__SHIFT 0x4
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE3_VMID__SHIFT 0x8
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE4_VMID__SHIFT 0xc
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE5_VMID__SHIFT 0x10
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE6_VMID__SHIFT 0x14
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE7_VMID__SHIFT 0x18
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE8_VMID__SHIFT 0x1c
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE1_VMID_MASK 0x0000000FL
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE2_VMID_MASK 0x000000F0L
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE3_VMID_MASK 0x00000F00L
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE4_VMID_MASK 0x0000F000L
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE5_VMID_MASK 0x000F0000L
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE6_VMID_MASK 0x00F00000L
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE7_VMID_MASK 0x0F000000L
+#define UVD_LMI_VCPU_CACHE_VMIDS_MULTI__VCPU_CACHE8_VMID_MASK 0xF0000000L
+//UVD_LMI_VCPU_NC_VMIDS_MULTI
+#define UVD_LMI_VCPU_NC_VMIDS_MULTI__VCPU_NC2_VMID__SHIFT 0x4
+#define UVD_LMI_VCPU_NC_VMIDS_MULTI__VCPU_NC3_VMID__SHIFT 0x8
+#define UVD_LMI_VCPU_NC_VMIDS_MULTI__VCPU_NC4_VMID__SHIFT 0xc
+#define UVD_LMI_VCPU_NC_VMIDS_MULTI__VCPU_NC5_VMID__SHIFT 0x10
+#define UVD_LMI_VCPU_NC_VMIDS_MULTI__VCPU_NC6_VMID__SHIFT 0x14
+#define UVD_LMI_VCPU_NC_VMIDS_MULTI__VCPU_NC7_VMID__SHIFT 0x18
+#define UVD_LMI_VCPU_NC_VMIDS_MULTI__VCPU_NC2_VMID_MASK 0x000000F0L
+#define UVD_LMI_VCPU_NC_VMIDS_MULTI__VCPU_NC3_VMID_MASK 0x00000F00L
+#define UVD_LMI_VCPU_NC_VMIDS_MULTI__VCPU_NC4_VMID_MASK 0x0000F000L
+#define UVD_LMI_VCPU_NC_VMIDS_MULTI__VCPU_NC5_VMID_MASK 0x000F0000L
+#define UVD_LMI_VCPU_NC_VMIDS_MULTI__VCPU_NC6_VMID_MASK 0x00F00000L
+#define UVD_LMI_VCPU_NC_VMIDS_MULTI__VCPU_NC7_VMID_MASK 0x0F000000L
+//UVD_LMI_LAT_CTRL
+#define UVD_LMI_LAT_CTRL__SCALE__SHIFT 0x0
+#define UVD_LMI_LAT_CTRL__MAX_START__SHIFT 0x8
+#define UVD_LMI_LAT_CTRL__MIN_START__SHIFT 0x9
+#define UVD_LMI_LAT_CTRL__AVG_START__SHIFT 0xa
+#define UVD_LMI_LAT_CTRL__PERFMON_SYNC__SHIFT 0xb
+#define UVD_LMI_LAT_CTRL__SKIP__SHIFT 0x10
+#define UVD_LMI_LAT_CTRL__SCALE_MASK 0x000000FFL
+#define UVD_LMI_LAT_CTRL__MAX_START_MASK 0x00000100L
+#define UVD_LMI_LAT_CTRL__MIN_START_MASK 0x00000200L
+#define UVD_LMI_LAT_CTRL__AVG_START_MASK 0x00000400L
+#define UVD_LMI_LAT_CTRL__PERFMON_SYNC_MASK 0x00000800L
+#define UVD_LMI_LAT_CTRL__SKIP_MASK 0x000F0000L
+//UVD_LMI_LAT_CNTR
+#define UVD_LMI_LAT_CNTR__MAX_LAT__SHIFT 0x0
+#define UVD_LMI_LAT_CNTR__MIN_LAT__SHIFT 0x8
+#define UVD_LMI_LAT_CNTR__MAX_LAT_MASK 0x000000FFL
+#define UVD_LMI_LAT_CNTR__MIN_LAT_MASK 0x0000FF00L
+//UVD_LMI_AVG_LAT_CNTR
+#define UVD_LMI_AVG_LAT_CNTR__ENV_LOW__SHIFT 0x0
+#define UVD_LMI_AVG_LAT_CNTR__ENV_HIGH__SHIFT 0x8
+#define UVD_LMI_AVG_LAT_CNTR__ENV_HIT__SHIFT 0x10
+#define UVD_LMI_AVG_LAT_CNTR__ENV_LOW_MASK 0x000000FFL
+#define UVD_LMI_AVG_LAT_CNTR__ENV_HIGH_MASK 0x0000FF00L
+#define UVD_LMI_AVG_LAT_CNTR__ENV_HIT_MASK 0xFFFF0000L
+//UVD_LMI_SPH
+#define UVD_LMI_SPH__ADDR__SHIFT 0x0
+#define UVD_LMI_SPH__STS__SHIFT 0x1c
+#define UVD_LMI_SPH__STS_VALID__SHIFT 0x1e
+#define UVD_LMI_SPH__STS_OVERFLOW__SHIFT 0x1f
+#define UVD_LMI_SPH__ADDR_MASK 0x0FFFFFFFL
+#define UVD_LMI_SPH__STS_MASK 0x30000000L
+#define UVD_LMI_SPH__STS_VALID_MASK 0x40000000L
+#define UVD_LMI_SPH__STS_OVERFLOW_MASK 0x80000000L
+//UVD_LMI_VCPU_CACHE_VMID
+#define UVD_LMI_VCPU_CACHE_VMID__VCPU_CACHE_VMID__SHIFT 0x0
+#define UVD_LMI_VCPU_CACHE_VMID__VCPU_CACHE_VMID_MASK 0x0000000FL
+//UVD_LMI_CTRL2
+#define UVD_LMI_CTRL2__SPH_DIS__SHIFT 0x0
+#define UVD_LMI_CTRL2__STALL_ARB__SHIFT 0x1
+#define UVD_LMI_CTRL2__ASSERT_UMC_URGENT__SHIFT 0x2
+#define UVD_LMI_CTRL2__MASK_UMC_URGENT__SHIFT 0x3
+#define UVD_LMI_CTRL2__CRC1_RESET__SHIFT 0x4
+#define UVD_LMI_CTRL2__DRCITF_BUBBLE_FIX_DIS__SHIFT 0x7
+#define UVD_LMI_CTRL2__STALL_ARB_UMC__SHIFT 0x8
+#define UVD_LMI_CTRL2__MC_READ_ID_SEL__SHIFT 0x9
+#define UVD_LMI_CTRL2__MC_WRITE_ID_SEL__SHIFT 0xb
+#define UVD_LMI_CTRL2__VCPU_NC0_EXT_EN__SHIFT 0xd
+#define UVD_LMI_CTRL2__VCPU_NC1_EXT_EN__SHIFT 0xe
+#define UVD_LMI_CTRL2__SPU_EXTRA_CID_EN__SHIFT 0xf
+#define UVD_LMI_CTRL2__RE_OFFLOAD_EN__SHIFT 0x10
+#define UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM__SHIFT 0x11
+#define UVD_LMI_CTRL2__CLEAR_NJ_PF_BP__SHIFT 0x19
+#define UVD_LMI_CTRL2__NJ_MIF_GATING__SHIFT 0x1a
+#define UVD_LMI_CTRL2__CRC1_SEL__SHIFT 0x1b
+#define UVD_LMI_CTRL2__SPH_DIS_MASK 0x00000001L
+#define UVD_LMI_CTRL2__STALL_ARB_MASK 0x00000002L
+#define UVD_LMI_CTRL2__ASSERT_UMC_URGENT_MASK 0x00000004L
+#define UVD_LMI_CTRL2__MASK_UMC_URGENT_MASK 0x00000008L
+#define UVD_LMI_CTRL2__CRC1_RESET_MASK 0x00000010L
+#define UVD_LMI_CTRL2__DRCITF_BUBBLE_FIX_DIS_MASK 0x00000080L
+#define UVD_LMI_CTRL2__STALL_ARB_UMC_MASK 0x00000100L
+#define UVD_LMI_CTRL2__MC_READ_ID_SEL_MASK 0x00000600L
+#define UVD_LMI_CTRL2__MC_WRITE_ID_SEL_MASK 0x00001800L
+#define UVD_LMI_CTRL2__VCPU_NC0_EXT_EN_MASK 0x00002000L
+#define UVD_LMI_CTRL2__VCPU_NC1_EXT_EN_MASK 0x00004000L
+#define UVD_LMI_CTRL2__SPU_EXTRA_CID_EN_MASK 0x00008000L
+#define UVD_LMI_CTRL2__RE_OFFLOAD_EN_MASK 0x00010000L
+#define UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM_MASK 0x01FE0000L
+#define UVD_LMI_CTRL2__CLEAR_NJ_PF_BP_MASK 0x02000000L
+#define UVD_LMI_CTRL2__NJ_MIF_GATING_MASK 0x04000000L
+#define UVD_LMI_CTRL2__CRC1_SEL_MASK 0xF8000000L
+//UVD_LMI_URGENT_CTRL
+#define UVD_LMI_URGENT_CTRL__ENABLE_MC_RD_URGENT_STALL__SHIFT 0x0
+#define UVD_LMI_URGENT_CTRL__ASSERT_MC_RD_STALL__SHIFT 0x1
+#define UVD_LMI_URGENT_CTRL__ASSERT_MC_RD_URGENT__SHIFT 0x2
+#define UVD_LMI_URGENT_CTRL__ENABLE_MC_WR_URGENT_STALL__SHIFT 0x8
+#define UVD_LMI_URGENT_CTRL__ASSERT_MC_WR_STALL__SHIFT 0x9
+#define UVD_LMI_URGENT_CTRL__ASSERT_MC_WR_URGENT__SHIFT 0xa
+#define UVD_LMI_URGENT_CTRL__ENABLE_UMC_RD_URGENT_STALL__SHIFT 0x10
+#define UVD_LMI_URGENT_CTRL__ASSERT_UMC_RD_STALL__SHIFT 0x11
+#define UVD_LMI_URGENT_CTRL__ASSERT_UMC_RD_URGENT__SHIFT 0x12
+#define UVD_LMI_URGENT_CTRL__ENABLE_UMC_WR_URGENT_STALL__SHIFT 0x18
+#define UVD_LMI_URGENT_CTRL__ASSERT_UMC_WR_STALL__SHIFT 0x19
+#define UVD_LMI_URGENT_CTRL__ASSERT_UMC_WR_URGENT__SHIFT 0x1a
+#define UVD_LMI_URGENT_CTRL__ENABLE_MC_RD_URGENT_STALL_MASK 0x00000001L
+#define UVD_LMI_URGENT_CTRL__ASSERT_MC_RD_STALL_MASK 0x00000002L
+#define UVD_LMI_URGENT_CTRL__ASSERT_MC_RD_URGENT_MASK 0x0000003CL
+#define UVD_LMI_URGENT_CTRL__ENABLE_MC_WR_URGENT_STALL_MASK 0x00000100L
+#define UVD_LMI_URGENT_CTRL__ASSERT_MC_WR_STALL_MASK 0x00000200L
+#define UVD_LMI_URGENT_CTRL__ASSERT_MC_WR_URGENT_MASK 0x00003C00L
+#define UVD_LMI_URGENT_CTRL__ENABLE_UMC_RD_URGENT_STALL_MASK 0x00010000L
+#define UVD_LMI_URGENT_CTRL__ASSERT_UMC_RD_STALL_MASK 0x00020000L
+#define UVD_LMI_URGENT_CTRL__ASSERT_UMC_RD_URGENT_MASK 0x003C0000L
+#define UVD_LMI_URGENT_CTRL__ENABLE_UMC_WR_URGENT_STALL_MASK 0x01000000L
+#define UVD_LMI_URGENT_CTRL__ASSERT_UMC_WR_STALL_MASK 0x02000000L
+#define UVD_LMI_URGENT_CTRL__ASSERT_UMC_WR_URGENT_MASK 0x3C000000L
+//UVD_LMI_CTRL
+#define UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT 0x0
+#define UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN__SHIFT 0x8
+#define UVD_LMI_CTRL__REQ_MODE__SHIFT 0x9
+#define UVD_LMI_CTRL__ASSERT_MC_URGENT__SHIFT 0xb
+#define UVD_LMI_CTRL__MASK_MC_URGENT__SHIFT 0xc
+#define UVD_LMI_CTRL__DATA_COHERENCY_EN__SHIFT 0xd
+#define UVD_LMI_CTRL__CRC_RESET__SHIFT 0xe
+#define UVD_LMI_CTRL__CRC_SEL__SHIFT 0xf
+#define UVD_LMI_CTRL__DISABLE_ON_FWV_FAIL__SHIFT 0x14
+#define UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN__SHIFT 0x15
+#define UVD_LMI_CTRL__CM_DATA_COHERENCY_EN__SHIFT 0x16
+#define UVD_LMI_CTRL__DB_DB_DATA_COHERENCY_EN__SHIFT 0x17
+#define UVD_LMI_CTRL__DB_IT_DATA_COHERENCY_EN__SHIFT 0x18
+#define UVD_LMI_CTRL__IT_IT_DATA_COHERENCY_EN__SHIFT 0x19
+#define UVD_LMI_CTRL__MIF_MIF_DATA_COHERENCY_EN__SHIFT 0x1a
+#define UVD_LMI_CTRL__MIF_LESS_OUTSTANDING_RD_REQ__SHIFT 0x1b
+#define UVD_LMI_CTRL__MC_BLK_RST__SHIFT 0x1c
+#define UVD_LMI_CTRL__UMC_BLK_RST__SHIFT 0x1d
+#define UVD_LMI_CTRL__RFU__SHIFT 0x1e
+#define UVD_LMI_CTRL__WRITE_CLEAN_TIMER_MASK 0x000000FFL
+#define UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK 0x00000100L
+#define UVD_LMI_CTRL__REQ_MODE_MASK 0x00000200L
+#define UVD_LMI_CTRL__ASSERT_MC_URGENT_MASK 0x00000800L
+#define UVD_LMI_CTRL__MASK_MC_URGENT_MASK 0x00001000L
+#define UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK 0x00002000L
+#define UVD_LMI_CTRL__CRC_RESET_MASK 0x00004000L
+#define UVD_LMI_CTRL__CRC_SEL_MASK 0x000F8000L
+#define UVD_LMI_CTRL__DISABLE_ON_FWV_FAIL_MASK 0x00100000L
+#define UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK 0x00200000L
+#define UVD_LMI_CTRL__CM_DATA_COHERENCY_EN_MASK 0x00400000L
+#define UVD_LMI_CTRL__DB_DB_DATA_COHERENCY_EN_MASK 0x00800000L
+#define UVD_LMI_CTRL__DB_IT_DATA_COHERENCY_EN_MASK 0x01000000L
+#define UVD_LMI_CTRL__IT_IT_DATA_COHERENCY_EN_MASK 0x02000000L
+#define UVD_LMI_CTRL__MIF_MIF_DATA_COHERENCY_EN_MASK 0x04000000L
+#define UVD_LMI_CTRL__MIF_LESS_OUTSTANDING_RD_REQ_MASK 0x08000000L
+#define UVD_LMI_CTRL__MC_BLK_RST_MASK 0x10000000L
+#define UVD_LMI_CTRL__UMC_BLK_RST_MASK 0x20000000L
+#define UVD_LMI_CTRL__RFU_MASK 0xC0000000L
+//UVD_LMI_STATUS
+#define UVD_LMI_STATUS__READ_CLEAN__SHIFT 0x0
+#define UVD_LMI_STATUS__WRITE_CLEAN__SHIFT 0x1
+#define UVD_LMI_STATUS__WRITE_CLEAN_RAW__SHIFT 0x2
+#define UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN__SHIFT 0x3
+#define UVD_LMI_STATUS__UMC_READ_CLEAN__SHIFT 0x4
+#define UVD_LMI_STATUS__UMC_WRITE_CLEAN__SHIFT 0x5
+#define UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW__SHIFT 0x6
+#define UVD_LMI_STATUS__PENDING_UVD_MC_WRITE__SHIFT 0x7
+#define UVD_LMI_STATUS__READ_CLEAN_RAW__SHIFT 0x8
+#define UVD_LMI_STATUS__UMC_READ_CLEAN_RAW__SHIFT 0x9
+#define UVD_LMI_STATUS__UMC_UVD_IDLE__SHIFT 0xa
+#define UVD_LMI_STATUS__UMC_AVP_IDLE__SHIFT 0xb
+#define UVD_LMI_STATUS__ADP_MC_READ_CLEAN__SHIFT 0xc
+#define UVD_LMI_STATUS__ADP_UMC_READ_CLEAN__SHIFT 0xd
+#define UVD_LMI_STATUS__BSP0_WRITE_CLEAN__SHIFT 0x12
+#define UVD_LMI_STATUS__BSP1_WRITE_CLEAN__SHIFT 0x13
+#define UVD_LMI_STATUS__BSP2_WRITE_CLEAN__SHIFT 0x14
+#define UVD_LMI_STATUS__BSP3_WRITE_CLEAN__SHIFT 0x15
+#define UVD_LMI_STATUS__CENC_READ_CLEAN__SHIFT 0x16
+#define UVD_LMI_STATUS__READ_CLEAN_MASK 0x00000001L
+#define UVD_LMI_STATUS__WRITE_CLEAN_MASK 0x00000002L
+#define UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK 0x00000004L
+#define UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK 0x00000008L
+#define UVD_LMI_STATUS__UMC_READ_CLEAN_MASK 0x00000010L
+#define UVD_LMI_STATUS__UMC_WRITE_CLEAN_MASK 0x00000020L
+#define UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK 0x00000040L
+#define UVD_LMI_STATUS__PENDING_UVD_MC_WRITE_MASK 0x00000080L
+#define UVD_LMI_STATUS__READ_CLEAN_RAW_MASK 0x00000100L
+#define UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK 0x00000200L
+#define UVD_LMI_STATUS__UMC_UVD_IDLE_MASK 0x00000400L
+#define UVD_LMI_STATUS__UMC_AVP_IDLE_MASK 0x00000800L
+#define UVD_LMI_STATUS__ADP_MC_READ_CLEAN_MASK 0x00001000L
+#define UVD_LMI_STATUS__ADP_UMC_READ_CLEAN_MASK 0x00002000L
+#define UVD_LMI_STATUS__BSP0_WRITE_CLEAN_MASK 0x00040000L
+#define UVD_LMI_STATUS__BSP1_WRITE_CLEAN_MASK 0x00080000L
+#define UVD_LMI_STATUS__BSP2_WRITE_CLEAN_MASK 0x00100000L
+#define UVD_LMI_STATUS__BSP3_WRITE_CLEAN_MASK 0x00200000L
+#define UVD_LMI_STATUS__CENC_READ_CLEAN_MASK 0x00400000L
+//UVD_LMI_PERFMON_CTRL
+#define UVD_LMI_PERFMON_CTRL__PERFMON_STATE__SHIFT 0x0
+#define UVD_LMI_PERFMON_CTRL__PERFMON_SEL__SHIFT 0x8
+#define UVD_LMI_PERFMON_CTRL__PERFMON_STATE_MASK 0x00000003L
+#define UVD_LMI_PERFMON_CTRL__PERFMON_SEL_MASK 0x00001F00L
+//UVD_LMI_PERFMON_COUNT_LO
+#define UVD_LMI_PERFMON_COUNT_LO__PERFMON_COUNT__SHIFT 0x0
+#define UVD_LMI_PERFMON_COUNT_LO__PERFMON_COUNT_MASK 0xFFFFFFFFL
+//UVD_LMI_PERFMON_COUNT_HI
+#define UVD_LMI_PERFMON_COUNT_HI__PERFMON_COUNT__SHIFT 0x0
+#define UVD_LMI_PERFMON_COUNT_HI__PERFMON_COUNT_MASK 0x0000FFFFL
+//UVD_LMI_ADP_SWAP_CNTL
+#define UVD_LMI_ADP_SWAP_CNTL__VCPU_R_MC_SWAP__SHIFT 0x6
+#define UVD_LMI_ADP_SWAP_CNTL__VCPU_W_MC_SWAP__SHIFT 0x8
+#define UVD_LMI_ADP_SWAP_CNTL__CM_MC_SWAP__SHIFT 0xa
+#define UVD_LMI_ADP_SWAP_CNTL__IT_MC_SWAP__SHIFT 0xc
+#define UVD_LMI_ADP_SWAP_CNTL__DB_R_MC_SWAP__SHIFT 0xe
+#define UVD_LMI_ADP_SWAP_CNTL__DB_W_MC_SWAP__SHIFT 0x10
+#define UVD_LMI_ADP_SWAP_CNTL__CSM_MC_SWAP__SHIFT 0x12
+#define UVD_LMI_ADP_SWAP_CNTL__PREF_MC_SWAP__SHIFT 0x14
+#define UVD_LMI_ADP_SWAP_CNTL__DBW_MC_SWAP__SHIFT 0x18
+#define UVD_LMI_ADP_SWAP_CNTL__RE_MC_SWAP__SHIFT 0x1c
+#define UVD_LMI_ADP_SWAP_CNTL__MP_MC_SWAP__SHIFT 0x1e
+#define UVD_LMI_ADP_SWAP_CNTL__VCPU_R_MC_SWAP_MASK 0x000000C0L
+#define UVD_LMI_ADP_SWAP_CNTL__VCPU_W_MC_SWAP_MASK 0x00000300L
+#define UVD_LMI_ADP_SWAP_CNTL__CM_MC_SWAP_MASK 0x00000C00L
+#define UVD_LMI_ADP_SWAP_CNTL__IT_MC_SWAP_MASK 0x00003000L
+#define UVD_LMI_ADP_SWAP_CNTL__DB_R_MC_SWAP_MASK 0x0000C000L
+#define UVD_LMI_ADP_SWAP_CNTL__DB_W_MC_SWAP_MASK 0x00030000L
+#define UVD_LMI_ADP_SWAP_CNTL__CSM_MC_SWAP_MASK 0x000C0000L
+#define UVD_LMI_ADP_SWAP_CNTL__PREF_MC_SWAP_MASK 0x00300000L
+#define UVD_LMI_ADP_SWAP_CNTL__DBW_MC_SWAP_MASK 0x03000000L
+#define UVD_LMI_ADP_SWAP_CNTL__RE_MC_SWAP_MASK 0x30000000L
+#define UVD_LMI_ADP_SWAP_CNTL__MP_MC_SWAP_MASK 0xC0000000L
+//UVD_LMI_RBC_RB_VMID
+#define UVD_LMI_RBC_RB_VMID__RB_VMID__SHIFT 0x0
+#define UVD_LMI_RBC_RB_VMID__RB_VMID_MASK 0x0000000FL
+//UVD_LMI_RBC_IB_VMID
+#define UVD_LMI_RBC_IB_VMID__IB_VMID__SHIFT 0x0
+#define UVD_LMI_RBC_IB_VMID__IB_VMID_MASK 0x0000000FL
+//UVD_LMI_MC_CREDITS
+#define UVD_LMI_MC_CREDITS__UVD_RD_CREDITS__SHIFT 0x0
+#define UVD_LMI_MC_CREDITS__UVD_WR_CREDITS__SHIFT 0x8
+#define UVD_LMI_MC_CREDITS__UMC_RD_CREDITS__SHIFT 0x10
+#define UVD_LMI_MC_CREDITS__UMC_WR_CREDITS__SHIFT 0x18
+#define UVD_LMI_MC_CREDITS__UVD_RD_CREDITS_MASK 0x0000003FL
+#define UVD_LMI_MC_CREDITS__UVD_WR_CREDITS_MASK 0x00003F00L
+#define UVD_LMI_MC_CREDITS__UMC_RD_CREDITS_MASK 0x003F0000L
+#define UVD_LMI_MC_CREDITS__UMC_WR_CREDITS_MASK 0x3F000000L
+//UVD_LMI_ADP_IND_INDEX
+#define UVD_LMI_ADP_IND_INDEX__INDEX__SHIFT 0x0
+#define UVD_LMI_ADP_IND_INDEX__INDEX_MASK 0x00001FFFL
+//UVD_LMI_ADP_IND_DATA
+#define UVD_LMI_ADP_IND_DATA__DATA__SHIFT 0x0
+#define UVD_LMI_ADP_IND_DATA__DATA_MASK 0xFFFFFFFFL
+//UVD_LMI_ADP_PF_EN
+#define UVD_LMI_ADP_PF_EN__VCPU_CACHE0_PF_EN__SHIFT 0x0
+#define UVD_LMI_ADP_PF_EN__VCPU_CACHE1_PF_EN__SHIFT 0x1
+#define UVD_LMI_ADP_PF_EN__VCPU_CACHE2_PF_EN__SHIFT 0x2
+#define UVD_LMI_ADP_PF_EN__VCPU_CACHE0_PF_EN_MASK 0x00000001L
+#define UVD_LMI_ADP_PF_EN__VCPU_CACHE1_PF_EN_MASK 0x00000002L
+#define UVD_LMI_ADP_PF_EN__VCPU_CACHE2_PF_EN_MASK 0x00000004L
+//UVD_LMI_PREF_CTRL
+#define UVD_LMI_PREF_CTRL__PREF_RST__SHIFT 0x0
+#define UVD_LMI_PREF_CTRL__PREF_BUSY_STATUS__SHIFT 0x1
+#define UVD_LMI_PREF_CTRL__PREF_WSTRB__SHIFT 0x2
+#define UVD_LMI_PREF_CTRL__PREF_WRITE_SIZE__SHIFT 0x3
+#define UVD_LMI_PREF_CTRL__PREF_STEP_SIZE__SHIFT 0x4
+#define UVD_LMI_PREF_CTRL__PREF_SIZE__SHIFT 0x13
+#define UVD_LMI_PREF_CTRL__PREF_RST_MASK 0x00000001L
+#define UVD_LMI_PREF_CTRL__PREF_BUSY_STATUS_MASK 0x00000002L
+#define UVD_LMI_PREF_CTRL__PREF_WSTRB_MASK 0x00000004L
+#define UVD_LMI_PREF_CTRL__PREF_WRITE_SIZE_MASK 0x00000008L
+#define UVD_LMI_PREF_CTRL__PREF_STEP_SIZE_MASK 0x00000070L
+#define UVD_LMI_PREF_CTRL__PREF_SIZE_MASK 0xFFF80000L
+//UVD_LMI_MIF_REF_LUMA_64BIT_BAR_LOW
+#define UVD_LMI_MIF_REF_LUMA_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MIF_REF_LUMA_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MIF_REF_LUMA_64BIT_BAR_HIGH
+#define UVD_LMI_MIF_REF_LUMA_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MIF_REF_LUMA_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//VCN_RAS_CNTL
+#define VCN_RAS_CNTL__VCPU_VCODEC_IH_EN__SHIFT 0x0
+#define VCN_RAS_CNTL__VCPU_VCODEC_PMI_EN__SHIFT 0x4
+#define VCN_RAS_CNTL__VCPU_VCODEC_REARM__SHIFT 0x8
+#define VCN_RAS_CNTL__VCPU_VCODEC_STALL_EN__SHIFT 0xc
+#define VCN_RAS_CNTL__VCPU_VCODEC_READY__SHIFT 0x10
+#define VCN_RAS_CNTL__VCPU_VCODEC_IH_EN_MASK 0x00000001L
+#define VCN_RAS_CNTL__VCPU_VCODEC_PMI_EN_MASK 0x00000010L
+#define VCN_RAS_CNTL__VCPU_VCODEC_REARM_MASK 0x00000100L
+#define VCN_RAS_CNTL__VCPU_VCODEC_STALL_EN_MASK 0x00001000L
+#define VCN_RAS_CNTL__VCPU_VCODEC_READY_MASK 0x00010000L
+
+
+// addressBlock: aid_uvd0_uvd_jpeg0_jpegnpdec
+//UVD_JPEG_CNTL
+#define UVD_JPEG_CNTL__REQUEST_EN__SHIFT 0x1
+#define UVD_JPEG_CNTL__ERR_RST_EN__SHIFT 0x2
+#define UVD_JPEG_CNTL__DBG_MUX_SEL__SHIFT 0x8
+#define UVD_JPEG_CNTL__FORMAT_CONV_EN__SHIFT 0x10
+#define UVD_JPEG_CNTL__VUP_MODE__SHIFT 0x11
+#define UVD_JPEG_CNTL__FC_TIMEOUT_EN__SHIFT 0x12
+#define UVD_JPEG_CNTL__ROI_CROP_EN__SHIFT 0x18
+#define UVD_JPEG_CNTL__ROI_CROP_EARLY_DECODE_STOP_DIS__SHIFT 0x19
+#define UVD_JPEG_CNTL__REQUEST_EN_MASK 0x00000002L
+#define UVD_JPEG_CNTL__ERR_RST_EN_MASK 0x00000004L
+#define UVD_JPEG_CNTL__DBG_MUX_SEL_MASK 0x00007F00L
+#define UVD_JPEG_CNTL__FORMAT_CONV_EN_MASK 0x00010000L
+#define UVD_JPEG_CNTL__VUP_MODE_MASK 0x00020000L
+#define UVD_JPEG_CNTL__FC_TIMEOUT_EN_MASK 0x00040000L
+#define UVD_JPEG_CNTL__ROI_CROP_EN_MASK 0x01000000L
+#define UVD_JPEG_CNTL__ROI_CROP_EARLY_DECODE_STOP_DIS_MASK 0x02000000L
+//UVD_JPEG_RB_BASE
+#define UVD_JPEG_RB_BASE__RB_BYTE_OFF__SHIFT 0x0
+#define UVD_JPEG_RB_BASE__RB_BASE__SHIFT 0x6
+#define UVD_JPEG_RB_BASE__RB_BYTE_OFF_MASK 0x0000003FL
+#define UVD_JPEG_RB_BASE__RB_BASE_MASK 0xFFFFFFC0L
+//UVD_JPEG_RB_WPTR
+#define UVD_JPEG_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_JPEG_RB_WPTR__RB_WPTR_MASK 0x3FFFFFF0L
+//UVD_JPEG_RB_RPTR
+#define UVD_JPEG_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_JPEG_RB_RPTR__RB_RPTR_MASK 0x3FFFFFF0L
+//UVD_JPEG_RB_SIZE
+#define UVD_JPEG_RB_SIZE__RB_SIZE__SHIFT 0x4
+#define UVD_JPEG_RB_SIZE__RB_SIZE_MASK 0x3FFFFFF0L
+//UVD_JPEG_DEC_CNT
+#define UVD_JPEG_DEC_CNT__DECODE_COUNT__SHIFT 0x0
+#define UVD_JPEG_DEC_CNT__DECODE_COUNT_MASK 0xFFFFFFFFL
+//UVD_JPEG_SPS_INFO
+#define UVD_JPEG_SPS_INFO__PIC_WIDTH__SHIFT 0x0
+#define UVD_JPEG_SPS_INFO__PIC_HEIGHT__SHIFT 0x10
+#define UVD_JPEG_SPS_INFO__PIC_WIDTH_MASK 0x0000FFFFL
+#define UVD_JPEG_SPS_INFO__PIC_HEIGHT_MASK 0xFFFF0000L
+//UVD_JPEG_SPS1_INFO
+#define UVD_JPEG_SPS1_INFO__CHROMA_FORMAT_IDC__SHIFT 0x0
+#define UVD_JPEG_SPS1_INFO__YUV422_SUBFORMAT__SHIFT 0x3
+#define UVD_JPEG_SPS1_INFO__OUT_FMT_422__SHIFT 0x4
+#define UVD_JPEG_SPS1_INFO__CHROMA_FORMAT_IDC_MASK 0x00000007L
+#define UVD_JPEG_SPS1_INFO__YUV422_SUBFORMAT_MASK 0x00000008L
+#define UVD_JPEG_SPS1_INFO__OUT_FMT_422_MASK 0x00000010L
+//UVD_JPEG_RE_TIMER
+#define UVD_JPEG_RE_TIMER__TIMER_OUT__SHIFT 0x0
+#define UVD_JPEG_RE_TIMER__TIMER_OUT_EN__SHIFT 0x10
+#define UVD_JPEG_RE_TIMER__TIMER_OUT_MASK 0x000000FFL
+#define UVD_JPEG_RE_TIMER__TIMER_OUT_EN_MASK 0x00010000L
+//UVD_JPEG_DEC_SCRATCH0
+#define UVD_JPEG_DEC_SCRATCH0__SCRATCH0__SHIFT 0x0
+#define UVD_JPEG_DEC_SCRATCH0__SCRATCH0_MASK 0xFFFFFFFFL
+//UVD_JPEG_INT_EN
+#define UVD_JPEG_INT_EN__OUTBUF_WPTR_INC_EN__SHIFT 0x0
+#define UVD_JPEG_INT_EN__JOB_AVAIL_EN__SHIFT 0x1
+#define UVD_JPEG_INT_EN__FENCE_VAL_EN__SHIFT 0x2
+#define UVD_JPEG_INT_EN__FIFO_OVERFLOW_ERR_EN__SHIFT 0x6
+#define UVD_JPEG_INT_EN__BLK_CNT_OUT_OF_SYNC_ERR_EN__SHIFT 0x7
+#define UVD_JPEG_INT_EN__EOI_ERR_EN__SHIFT 0x8
+#define UVD_JPEG_INT_EN__HFM_ERR_EN__SHIFT 0x9
+#define UVD_JPEG_INT_EN__RST_ERR_EN__SHIFT 0xa
+#define UVD_JPEG_INT_EN__ECS_MK_ERR_EN__SHIFT 0xb
+#define UVD_JPEG_INT_EN__TIMEOUT_ERR_EN__SHIFT 0xc
+#define UVD_JPEG_INT_EN__MARKER_ERR_EN__SHIFT 0xd
+#define UVD_JPEG_INT_EN__FMT_ERR_EN__SHIFT 0xe
+#define UVD_JPEG_INT_EN__PROFILE_ERR_EN__SHIFT 0xf
+#define UVD_JPEG_INT_EN__FC_TIMEOUT_ERR_EN__SHIFT 0x10
+#define UVD_JPEG_INT_EN__FC_FMT_ERR_EN__SHIFT 0x11
+#define UVD_JPEG_INT_EN__FC_SRC_ERR_EN__SHIFT 0x12
+#define UVD_JPEG_INT_EN__CROP_SIZE_ERR_EN__SHIFT 0x13
+#define UVD_JPEG_INT_EN__OUTBUF_WPTR_INC_EN_MASK 0x00000001L
+#define UVD_JPEG_INT_EN__JOB_AVAIL_EN_MASK 0x00000002L
+#define UVD_JPEG_INT_EN__FENCE_VAL_EN_MASK 0x00000004L
+#define UVD_JPEG_INT_EN__FIFO_OVERFLOW_ERR_EN_MASK 0x00000040L
+#define UVD_JPEG_INT_EN__BLK_CNT_OUT_OF_SYNC_ERR_EN_MASK 0x00000080L
+#define UVD_JPEG_INT_EN__EOI_ERR_EN_MASK 0x00000100L
+#define UVD_JPEG_INT_EN__HFM_ERR_EN_MASK 0x00000200L
+#define UVD_JPEG_INT_EN__RST_ERR_EN_MASK 0x00000400L
+#define UVD_JPEG_INT_EN__ECS_MK_ERR_EN_MASK 0x00000800L
+#define UVD_JPEG_INT_EN__TIMEOUT_ERR_EN_MASK 0x00001000L
+#define UVD_JPEG_INT_EN__MARKER_ERR_EN_MASK 0x00002000L
+#define UVD_JPEG_INT_EN__FMT_ERR_EN_MASK 0x00004000L
+#define UVD_JPEG_INT_EN__PROFILE_ERR_EN_MASK 0x00008000L
+#define UVD_JPEG_INT_EN__FC_TIMEOUT_ERR_EN_MASK 0x00010000L
+#define UVD_JPEG_INT_EN__FC_FMT_ERR_EN_MASK 0x00020000L
+#define UVD_JPEG_INT_EN__FC_SRC_ERR_EN_MASK 0x00040000L
+#define UVD_JPEG_INT_EN__CROP_SIZE_ERR_EN_MASK 0x00080000L
+//UVD_JPEG_INT_STAT
+#define UVD_JPEG_INT_STAT__OUTBUF_WPTR_INC_INT__SHIFT 0x0
+#define UVD_JPEG_INT_STAT__JOB_AVAIL_INT__SHIFT 0x1
+#define UVD_JPEG_INT_STAT__FENCE_VAL_INT__SHIFT 0x2
+#define UVD_JPEG_INT_STAT__FIFO_OVERFLOW_ERR_INT__SHIFT 0x6
+#define UVD_JPEG_INT_STAT__BLK_CNT_OUT_OF_SYNC_ERR_INT__SHIFT 0x7
+#define UVD_JPEG_INT_STAT__EOI_ERR_INT__SHIFT 0x8
+#define UVD_JPEG_INT_STAT__HFM_ERR_INT__SHIFT 0x9
+#define UVD_JPEG_INT_STAT__RST_ERR_INT__SHIFT 0xa
+#define UVD_JPEG_INT_STAT__ECS_MK_ERR_INT__SHIFT 0xb
+#define UVD_JPEG_INT_STAT__TIMEOUT_ERR_INT__SHIFT 0xc
+#define UVD_JPEG_INT_STAT__MARKER_ERR_INT__SHIFT 0xd
+#define UVD_JPEG_INT_STAT__FMT_ERR_INT__SHIFT 0xe
+#define UVD_JPEG_INT_STAT__PROFILE_ERR_INT__SHIFT 0xf
+#define UVD_JPEG_INT_STAT__FC_TIMEOUT_ERR_INT__SHIFT 0x10
+#define UVD_JPEG_INT_STAT__FC_FMT_ERR_INT__SHIFT 0x11
+#define UVD_JPEG_INT_STAT__FC_SRC_ERR_INT__SHIFT 0x12
+#define UVD_JPEG_INT_STAT__CROP_SIZE_ERR_INT__SHIFT 0x13
+#define UVD_JPEG_INT_STAT__OUTBUF_WPTR_INC_INT_MASK 0x00000001L
+#define UVD_JPEG_INT_STAT__JOB_AVAIL_INT_MASK 0x00000002L
+#define UVD_JPEG_INT_STAT__FENCE_VAL_INT_MASK 0x00000004L
+#define UVD_JPEG_INT_STAT__FIFO_OVERFLOW_ERR_INT_MASK 0x00000040L
+#define UVD_JPEG_INT_STAT__BLK_CNT_OUT_OF_SYNC_ERR_INT_MASK 0x00000080L
+#define UVD_JPEG_INT_STAT__EOI_ERR_INT_MASK 0x00000100L
+#define UVD_JPEG_INT_STAT__HFM_ERR_INT_MASK 0x00000200L
+#define UVD_JPEG_INT_STAT__RST_ERR_INT_MASK 0x00000400L
+#define UVD_JPEG_INT_STAT__ECS_MK_ERR_INT_MASK 0x00000800L
+#define UVD_JPEG_INT_STAT__TIMEOUT_ERR_INT_MASK 0x00001000L
+#define UVD_JPEG_INT_STAT__MARKER_ERR_INT_MASK 0x00002000L
+#define UVD_JPEG_INT_STAT__FMT_ERR_INT_MASK 0x00004000L
+#define UVD_JPEG_INT_STAT__PROFILE_ERR_INT_MASK 0x00008000L
+#define UVD_JPEG_INT_STAT__FC_TIMEOUT_ERR_INT_MASK 0x00010000L
+#define UVD_JPEG_INT_STAT__FC_FMT_ERR_INT_MASK 0x00020000L
+#define UVD_JPEG_INT_STAT__FC_SRC_ERR_INT_MASK 0x00040000L
+#define UVD_JPEG_INT_STAT__CROP_SIZE_ERR_INT_MASK 0x00080000L
+//UVD_JPEG_TIER_CNTL0
+#define UVD_JPEG_TIER_CNTL0__TIER_SEL__SHIFT 0x0
+#define UVD_JPEG_TIER_CNTL0__Y_COMP_ID__SHIFT 0x2
+#define UVD_JPEG_TIER_CNTL0__U_COMP_ID__SHIFT 0x4
+#define UVD_JPEG_TIER_CNTL0__V_COMP_ID__SHIFT 0x6
+#define UVD_JPEG_TIER_CNTL0__Y_H_SAMP_FAC__SHIFT 0x8
+#define UVD_JPEG_TIER_CNTL0__Y_V_SAMP_FAC__SHIFT 0xb
+#define UVD_JPEG_TIER_CNTL0__U_H_SAMP_FAC__SHIFT 0xe
+#define UVD_JPEG_TIER_CNTL0__U_V_SAMP_FAC__SHIFT 0x11
+#define UVD_JPEG_TIER_CNTL0__V_H_SAMP_FAC__SHIFT 0x14
+#define UVD_JPEG_TIER_CNTL0__V_V_SAMP_FAC__SHIFT 0x17
+#define UVD_JPEG_TIER_CNTL0__Y_TQ__SHIFT 0x1a
+#define UVD_JPEG_TIER_CNTL0__U_TQ__SHIFT 0x1c
+#define UVD_JPEG_TIER_CNTL0__V_TQ__SHIFT 0x1e
+#define UVD_JPEG_TIER_CNTL0__TIER_SEL_MASK 0x00000003L
+#define UVD_JPEG_TIER_CNTL0__Y_COMP_ID_MASK 0x0000000CL
+#define UVD_JPEG_TIER_CNTL0__U_COMP_ID_MASK 0x00000030L
+#define UVD_JPEG_TIER_CNTL0__V_COMP_ID_MASK 0x000000C0L
+#define UVD_JPEG_TIER_CNTL0__Y_H_SAMP_FAC_MASK 0x00000700L
+#define UVD_JPEG_TIER_CNTL0__Y_V_SAMP_FAC_MASK 0x00003800L
+#define UVD_JPEG_TIER_CNTL0__U_H_SAMP_FAC_MASK 0x0001C000L
+#define UVD_JPEG_TIER_CNTL0__U_V_SAMP_FAC_MASK 0x000E0000L
+#define UVD_JPEG_TIER_CNTL0__V_H_SAMP_FAC_MASK 0x00700000L
+#define UVD_JPEG_TIER_CNTL0__V_V_SAMP_FAC_MASK 0x03800000L
+#define UVD_JPEG_TIER_CNTL0__Y_TQ_MASK 0x0C000000L
+#define UVD_JPEG_TIER_CNTL0__U_TQ_MASK 0x30000000L
+#define UVD_JPEG_TIER_CNTL0__V_TQ_MASK 0xC0000000L
+//UVD_JPEG_TIER_CNTL1
+#define UVD_JPEG_TIER_CNTL1__SRC_WIDTH__SHIFT 0x0
+#define UVD_JPEG_TIER_CNTL1__SRC_HEIGHT__SHIFT 0x10
+#define UVD_JPEG_TIER_CNTL1__SRC_WIDTH_MASK 0x0000FFFFL
+#define UVD_JPEG_TIER_CNTL1__SRC_HEIGHT_MASK 0xFFFF0000L
+//UVD_JPEG_TIER_CNTL2
+#define UVD_JPEG_TIER_CNTL2__TBL_ECS_SEL__SHIFT 0x0
+#define UVD_JPEG_TIER_CNTL2__TBL_TYPE__SHIFT 0x1
+#define UVD_JPEG_TIER_CNTL2__TQ__SHIFT 0x2
+#define UVD_JPEG_TIER_CNTL2__TH__SHIFT 0x4
+#define UVD_JPEG_TIER_CNTL2__TC__SHIFT 0x6
+#define UVD_JPEG_TIER_CNTL2__TD__SHIFT 0x7
+#define UVD_JPEG_TIER_CNTL2__TA__SHIFT 0xa
+#define UVD_JPEG_TIER_CNTL2__TIER2_HTBL_CNTLEN__SHIFT 0xe
+#define UVD_JPEG_TIER_CNTL2__DRI_VAL__SHIFT 0x10
+#define UVD_JPEG_TIER_CNTL2__TBL_ECS_SEL_MASK 0x00000001L
+#define UVD_JPEG_TIER_CNTL2__TBL_TYPE_MASK 0x00000002L
+#define UVD_JPEG_TIER_CNTL2__TQ_MASK 0x0000000CL
+#define UVD_JPEG_TIER_CNTL2__TH_MASK 0x00000030L
+#define UVD_JPEG_TIER_CNTL2__TC_MASK 0x00000040L
+#define UVD_JPEG_TIER_CNTL2__TD_MASK 0x00000380L
+#define UVD_JPEG_TIER_CNTL2__TA_MASK 0x00001C00L
+#define UVD_JPEG_TIER_CNTL2__TIER2_HTBL_CNTLEN_MASK 0x00004000L
+#define UVD_JPEG_TIER_CNTL2__DRI_VAL_MASK 0xFFFF0000L
+//UVD_JPEG_TIER_STATUS
+#define UVD_JPEG_TIER_STATUS__BSI_FETCH_DONE__SHIFT 0x0
+#define UVD_JPEG_TIER_STATUS__DECODE_DONE__SHIFT 0x1
+#define UVD_JPEG_TIER_STATUS__BSI_FETCH_DONE_MASK 0x00000001L
+#define UVD_JPEG_TIER_STATUS__DECODE_DONE_MASK 0x00000002L
+
+
+// addressBlock: aid_uvd0_uvd_jpeg_sclk0_jpegnpsclkdec
+//UVD_JPEG_OUTBUF_CNTL
+#define UVD_JPEG_OUTBUF_CNTL__OUTBUF_CNT__SHIFT 0x0
+#define UVD_JPEG_OUTBUF_CNTL__HGT_ALIGN__SHIFT 0x2
+#define UVD_JPEG_OUTBUF_CNTL__JPEG0_DECODE_DONE_FIX__SHIFT 0x6
+#define UVD_JPEG_OUTBUF_CNTL__JPEG0_WR_COMB_MAX_CNT__SHIFT 0x7
+#define UVD_JPEG_OUTBUF_CNTL__JPEG0_WR_COMB_TIMER__SHIFT 0x9
+#define UVD_JPEG_OUTBUF_CNTL__DIS_OBUF_AVAIL_CHECK__SHIFT 0x10
+#define UVD_JPEG_OUTBUF_CNTL__OUTBUF_CNT_MASK 0x00000003L
+#define UVD_JPEG_OUTBUF_CNTL__HGT_ALIGN_MASK 0x00000004L
+#define UVD_JPEG_OUTBUF_CNTL__JPEG0_DECODE_DONE_FIX_MASK 0x00000040L
+#define UVD_JPEG_OUTBUF_CNTL__JPEG0_WR_COMB_MAX_CNT_MASK 0x00000180L
+#define UVD_JPEG_OUTBUF_CNTL__JPEG0_WR_COMB_TIMER_MASK 0x00001E00L
+#define UVD_JPEG_OUTBUF_CNTL__DIS_OBUF_AVAIL_CHECK_MASK 0x00010000L
+//UVD_JPEG_OUTBUF_WPTR
+#define UVD_JPEG_OUTBUF_WPTR__OUTBUF_WPTR__SHIFT 0x0
+#define UVD_JPEG_OUTBUF_WPTR__OUTBUF_WPTR_MASK 0xFFFFFFFFL
+//UVD_JPEG_OUTBUF_RPTR
+#define UVD_JPEG_OUTBUF_RPTR__OUTBUF_RPTR__SHIFT 0x0
+#define UVD_JPEG_OUTBUF_RPTR__OUTBUF_RPTR_MASK 0xFFFFFFFFL
+//UVD_JPEG_PITCH
+#define UVD_JPEG_PITCH__PITCH__SHIFT 0x0
+#define UVD_JPEG_PITCH__PITCH_MASK 0xFFFFFFFFL
+//UVD_JPEG_UV_PITCH
+#define UVD_JPEG_UV_PITCH__UV_PITCH__SHIFT 0x0
+#define UVD_JPEG_UV_PITCH__UV_PITCH_MASK 0xFFFFFFFFL
+//JPEG_DEC_Y_GFX8_TILING_SURFACE
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__BANK_WIDTH__SHIFT 0x0
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__BANK_HEIGHT__SHIFT 0x2
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__MACRO_TILE_ASPECT__SHIFT 0x4
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__NUM_BANKS__SHIFT 0x6
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__PIPE_CONFIG__SHIFT 0x8
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__TILE_SPLIT__SHIFT 0xd
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__ARRAY_MODE__SHIFT 0x10
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__BANK_WIDTH_MASK 0x00000003L
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__BANK_HEIGHT_MASK 0x0000000CL
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__MACRO_TILE_ASPECT_MASK 0x00000030L
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__NUM_BANKS_MASK 0x000000C0L
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__PIPE_CONFIG_MASK 0x00001F00L
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__TILE_SPLIT_MASK 0x0000E000L
+#define JPEG_DEC_Y_GFX8_TILING_SURFACE__ARRAY_MODE_MASK 0x000F0000L
+//JPEG_DEC_UV_GFX8_TILING_SURFACE
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__BANK_WIDTH__SHIFT 0x0
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__BANK_HEIGHT__SHIFT 0x2
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__MACRO_TILE_ASPECT__SHIFT 0x4
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__NUM_BANKS__SHIFT 0x6
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__PIPE_CONFIG__SHIFT 0x8
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__TILE_SPLIT__SHIFT 0xd
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__ARRAY_MODE__SHIFT 0x10
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__BANK_WIDTH_MASK 0x00000003L
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__BANK_HEIGHT_MASK 0x0000000CL
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__MACRO_TILE_ASPECT_MASK 0x00000030L
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__NUM_BANKS_MASK 0x000000C0L
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__PIPE_CONFIG_MASK 0x00001F00L
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__TILE_SPLIT_MASK 0x0000E000L
+#define JPEG_DEC_UV_GFX8_TILING_SURFACE__ARRAY_MODE_MASK 0x000F0000L
+//JPEG_DEC_GFX8_ADDR_CONFIG
+#define JPEG_DEC_GFX8_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x4
+#define JPEG_DEC_GFX8_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+//JPEG_DEC_Y_GFX10_TILING_SURFACE
+#define JPEG_DEC_Y_GFX10_TILING_SURFACE__SWIZZLE_MODE__SHIFT 0x0
+#define JPEG_DEC_Y_GFX10_TILING_SURFACE__SWIZZLE_MODE_MASK 0x0000001FL
+//JPEG_DEC_UV_GFX10_TILING_SURFACE
+#define JPEG_DEC_UV_GFX10_TILING_SURFACE__SWIZZLE_MODE__SHIFT 0x0
+#define JPEG_DEC_UV_GFX10_TILING_SURFACE__SWIZZLE_MODE_MASK 0x0000001FL
+//JPEG_DEC_GFX10_ADDR_CONFIG
+#define JPEG_DEC_GFX10_ADDR_CONFIG__NUM_PIPES__SHIFT 0x0
+#define JPEG_DEC_GFX10_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x3
+#define JPEG_DEC_GFX10_ADDR_CONFIG__NUM_PKRS__SHIFT 0x8
+#define JPEG_DEC_GFX10_ADDR_CONFIG__NUM_BANKS__SHIFT 0xc
+#define JPEG_DEC_GFX10_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x13
+#define JPEG_DEC_GFX10_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define JPEG_DEC_GFX10_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000038L
+#define JPEG_DEC_GFX10_ADDR_CONFIG__NUM_PKRS_MASK 0x00000700L
+#define JPEG_DEC_GFX10_ADDR_CONFIG__NUM_BANKS_MASK 0x00007000L
+#define JPEG_DEC_GFX10_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00180000L
+//JPEG_DEC_ADDR_MODE
+#define JPEG_DEC_ADDR_MODE__ADDR_MODE_Y__SHIFT 0x0
+#define JPEG_DEC_ADDR_MODE__ADDR_MODE_UV__SHIFT 0x2
+#define JPEG_DEC_ADDR_MODE__ADDR_LIB_SEL__SHIFT 0xc
+#define JPEG_DEC_ADDR_MODE__ADDR_MODE_Y_MASK 0x00000003L
+#define JPEG_DEC_ADDR_MODE__ADDR_MODE_UV_MASK 0x0000000CL
+#define JPEG_DEC_ADDR_MODE__ADDR_LIB_SEL_MASK 0x00007000L
+//UVD_JPEG_OUTPUT_XY
+#define UVD_JPEG_OUTPUT_XY__OUTPUT_X__SHIFT 0x0
+#define UVD_JPEG_OUTPUT_XY__OUTPUT_Y__SHIFT 0x10
+#define UVD_JPEG_OUTPUT_XY__OUTPUT_X_MASK 0x00003FFFL
+#define UVD_JPEG_OUTPUT_XY__OUTPUT_Y_MASK 0x3FFF0000L
+//UVD_JPEG_GPCOM_CMD
+#define UVD_JPEG_GPCOM_CMD__CMD__SHIFT 0x1
+#define UVD_JPEG_GPCOM_CMD__CMD_MASK 0x0000000EL
+//UVD_JPEG_GPCOM_DATA0
+#define UVD_JPEG_GPCOM_DATA0__DATA0__SHIFT 0x0
+#define UVD_JPEG_GPCOM_DATA0__DATA0_MASK 0xFFFFFFFFL
+//UVD_JPEG_GPCOM_DATA1
+#define UVD_JPEG_GPCOM_DATA1__DATA1__SHIFT 0x0
+#define UVD_JPEG_GPCOM_DATA1__DATA1_MASK 0xFFFFFFFFL
+//UVD_JPEG_SCRATCH1
+#define UVD_JPEG_SCRATCH1__SCRATCH1__SHIFT 0x0
+#define UVD_JPEG_SCRATCH1__SCRATCH1_MASK 0xFFFFFFFFL
+//UVD_JPEG_DEC_SOFT_RST
+#define UVD_JPEG_DEC_SOFT_RST__SOFT_RESET__SHIFT 0x0
+#define UVD_JPEG_DEC_SOFT_RST__RESET_STATUS__SHIFT 0x10
+#define UVD_JPEG_DEC_SOFT_RST__SOFT_RESET_MASK 0x00000001L
+#define UVD_JPEG_DEC_SOFT_RST__RESET_STATUS_MASK 0x00010000L
+
+// addressBlock: aid_uvd0_vcn_edcc_dec
+//VCN_UE_ERR_STATUS_LO_VIDD
+#define VCN_UE_ERR_STATUS_LO_VIDD__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_VIDD__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_VIDD__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_VIDD__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_VIDD__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_VIDD__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_VIDD__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_VIDD__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_VIDD
+#define VCN_UE_ERR_STATUS_HI_VIDD__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_VIDD__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_VIDD__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_VIDD__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_VIDD__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_VIDD__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_VIDD__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_VIDD__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_VIDD__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_VIDD__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_VIDD__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_VIDD__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_VIDD__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_VIDD__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_VIDD__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_VIDD__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_VIDV
+#define VCN_UE_ERR_STATUS_LO_VIDV__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_VIDV__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_VIDV__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_VIDV__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_VIDV__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_VIDV__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_VIDV__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_VIDV__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_VIDV
+#define VCN_UE_ERR_STATUS_HI_VIDV__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_VIDV__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_VIDV__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_VIDV__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_VIDV__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_VIDV__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_VIDV__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_VIDV__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_VIDV__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_VIDV__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_VIDV__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_VIDV__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_VIDV__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_VIDV__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_VIDV__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_VIDV__Err_clr_MASK 0x80000000L
+//VCN_CE_ERR_STATUS_LO_MMSCHD
+#define VCN_CE_ERR_STATUS_LO_MMSCHD__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_CE_ERR_STATUS_LO_MMSCHD__Address_Valid_Flag__SHIFT 0x1
+#define VCN_CE_ERR_STATUS_LO_MMSCHD__Address__SHIFT 0x2
+#define VCN_CE_ERR_STATUS_LO_MMSCHD__Memory_id__SHIFT 0x18
+#define VCN_CE_ERR_STATUS_LO_MMSCHD__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_CE_ERR_STATUS_LO_MMSCHD__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_CE_ERR_STATUS_LO_MMSCHD__Address_MASK 0x00FFFFFCL
+#define VCN_CE_ERR_STATUS_LO_MMSCHD__Memory_id_MASK 0xFF000000L
+//VCN_CE_ERR_STATUS_HI_MMSCHD
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__ECC__SHIFT 0x0
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__Other__SHIFT 0x1
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__Err_Info__SHIFT 0x3
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__CE_Cnt__SHIFT 0x17
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__Poison__SHIFT 0x1c
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__RESERVED__SHIFT 0x1d
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__Err_clr__SHIFT 0x1f
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__ECC_MASK 0x00000001L
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__Other_MASK 0x00000002L
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__Err_Info_MASK 0x007FFFF8L
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__CE_Cnt_MASK 0x03800000L
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__Poison_MASK 0x10000000L
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__RESERVED_MASK 0x60000000L
+#define VCN_CE_ERR_STATUS_HI_MMSCHD__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG0S
+#define VCN_UE_ERR_STATUS_LO_JPEG0S__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG0S__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG0S__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG0S__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG0S__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG0S__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG0S__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG0S__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG0S
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG0S__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG0D
+#define VCN_UE_ERR_STATUS_LO_JPEG0D__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG0D__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG0D__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG0D__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG0D__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG0D__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG0D__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG0D__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG0D
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG0D__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG1S
+#define VCN_UE_ERR_STATUS_LO_JPEG1S__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG1S__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG1S__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG1S__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG1S__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG1S__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG1S__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG1S__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG1S
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG1S__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG1D
+#define VCN_UE_ERR_STATUS_LO_JPEG1D__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG1D__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG1D__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG1D__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG1D__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG1D__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG1D__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG1D__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG1D
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG1D__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG2S
+#define VCN_UE_ERR_STATUS_LO_JPEG2S__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG2S__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG2S__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG2S__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG2S__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG2S__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG2S__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG2S__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG2S
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG2S__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG2D
+#define VCN_UE_ERR_STATUS_LO_JPEG2D__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG2D__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG2D__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG2D__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG2D__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG2D__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG2D__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG2D__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG2D
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG2D__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG3S
+#define VCN_UE_ERR_STATUS_LO_JPEG3S__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG3S__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG3S__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG3S__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG3S__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG3S__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG3S__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG3S__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG3S
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG3S__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG3D
+#define VCN_UE_ERR_STATUS_LO_JPEG3D__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG3D__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG3D__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG3D__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG3D__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG3D__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG3D__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG3D__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG3D
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG3D__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG4S
+#define VCN_UE_ERR_STATUS_LO_JPEG4S__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG4S__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG4S__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG4S__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG4S__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG4S__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG4S__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG4S__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG4S
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG4S__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG4D
+#define VCN_UE_ERR_STATUS_LO_JPEG4D__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG4D__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG4D__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG4D__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG4D__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG4D__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG4D__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG4D__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG4D
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG4D__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG5S
+#define VCN_UE_ERR_STATUS_LO_JPEG5S__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG5S__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG5S__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG5S__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG5S__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG5S__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG5S__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG5S__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG5S
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG5S__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG5D
+#define VCN_UE_ERR_STATUS_LO_JPEG5D__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG5D__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG5D__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG5D__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG5D__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG5D__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG5D__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG5D__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG5D
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG5D__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG6S
+#define VCN_UE_ERR_STATUS_LO_JPEG6S__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG6S__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG6S__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG6S__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG6S__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG6S__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG6S__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG6S__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG6S
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG6S__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG6D
+#define VCN_UE_ERR_STATUS_LO_JPEG6D__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG6D__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG6D__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG6D__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG6D__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG6D__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG6D__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG6D__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG6D
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG6D__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG7S
+#define VCN_UE_ERR_STATUS_LO_JPEG7S__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG7S__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG7S__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG7S__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG7S__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG7S__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG7S__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG7S__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG7S
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG7S__Err_clr_MASK 0x80000000L
+//VCN_UE_ERR_STATUS_LO_JPEG7D
+#define VCN_UE_ERR_STATUS_LO_JPEG7D__Err_Status_Valid_Flag__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_LO_JPEG7D__Address_Valid_Flag__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_LO_JPEG7D__Address__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_LO_JPEG7D__Memory_id__SHIFT 0x18
+#define VCN_UE_ERR_STATUS_LO_JPEG7D__Err_Status_Valid_Flag_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_LO_JPEG7D__Address_Valid_Flag_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_LO_JPEG7D__Address_MASK 0x00FFFFFCL
+#define VCN_UE_ERR_STATUS_LO_JPEG7D__Memory_id_MASK 0xFF000000L
+//VCN_UE_ERR_STATUS_HI_JPEG7D
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__ECC__SHIFT 0x0
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__Parity__SHIFT 0x1
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__Err_Info_Valid_Flag__SHIFT 0x2
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__Err_Info__SHIFT 0x3
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__UE_Cnt__SHIFT 0x17
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__FED_Cnt__SHIFT 0x1a
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__RESERVED__SHIFT 0x1d
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__Err_clr__SHIFT 0x1f
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__ECC_MASK 0x00000001L
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__Parity_MASK 0x00000002L
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__Err_Info_Valid_Flag_MASK 0x00000004L
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__Err_Info_MASK 0x007FFFF8L
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__UE_Cnt_MASK 0x03800000L
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__FED_Cnt_MASK 0x1C000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__RESERVED_MASK 0x60000000L
+#define VCN_UE_ERR_STATUS_HI_JPEG7D__Err_clr_MASK 0x80000000L
+
+// addressBlock: aid_uvd0_uvd_jrbc0_uvd_jrbc_dec
+//UVD_JRBC0_UVD_JRBC_RB_WPTR
+#define UVD_JRBC0_UVD_JRBC_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_JRBC0_UVD_JRBC_RB_WPTR__RB_WPTR_MASK 0x007FFFF0L
+//UVD_JRBC0_UVD_JRBC_RB_CNTL
+#define UVD_JRBC0_UVD_JRBC_RB_CNTL__RB_NO_FETCH__SHIFT 0x0
+#define UVD_JRBC0_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN__SHIFT 0x1
+#define UVD_JRBC0_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER__SHIFT 0x4
+#define UVD_JRBC0_UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK 0x00000001L
+#define UVD_JRBC0_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK 0x00000002L
+#define UVD_JRBC0_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER_MASK 0x0007FFF0L
+//UVD_JRBC0_UVD_JRBC_IB_SIZE
+#define UVD_JRBC0_UVD_JRBC_IB_SIZE__IB_SIZE__SHIFT 0x4
+#define UVD_JRBC0_UVD_JRBC_IB_SIZE__IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC0_UVD_JRBC_URGENT_CNTL
+#define UVD_JRBC0_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK__SHIFT 0x0
+#define UVD_JRBC0_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK_MASK 0x00000003L
+//UVD_JRBC0_UVD_JRBC_RB_REF_DATA
+#define UVD_JRBC0_UVD_JRBC_RB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC0_UVD_JRBC_RB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC0_UVD_JRBC_RB_COND_RD_TIMER
+#define UVD_JRBC0_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC0_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC0_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC0_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC0_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC0_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC0_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC0_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC0_UVD_JRBC_SOFT_RESET
+#define UVD_JRBC0_UVD_JRBC_SOFT_RESET__RESET__SHIFT 0x0
+#define UVD_JRBC0_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS__SHIFT 0x11
+#define UVD_JRBC0_UVD_JRBC_SOFT_RESET__RESET_MASK 0x00000001L
+#define UVD_JRBC0_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS_MASK 0x00020000L
+//UVD_JRBC0_UVD_JRBC_STATUS
+#define UVD_JRBC0_UVD_JRBC_STATUS__RB_JOB_DONE__SHIFT 0x0
+#define UVD_JRBC0_UVD_JRBC_STATUS__IB_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC0_UVD_JRBC_STATUS__RB_ILLEGAL_CMD__SHIFT 0x2
+#define UVD_JRBC0_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT__SHIFT 0x3
+#define UVD_JRBC0_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT__SHIFT 0x4
+#define UVD_JRBC0_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT__SHIFT 0x5
+#define UVD_JRBC0_UVD_JRBC_STATUS__IB_ILLEGAL_CMD__SHIFT 0x6
+#define UVD_JRBC0_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT__SHIFT 0x7
+#define UVD_JRBC0_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT__SHIFT 0x8
+#define UVD_JRBC0_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT__SHIFT 0x9
+#define UVD_JRBC0_UVD_JRBC_STATUS__RB_TRAP_STATUS__SHIFT 0xa
+#define UVD_JRBC0_UVD_JRBC_STATUS__PREEMPT_STATUS__SHIFT 0xb
+#define UVD_JRBC0_UVD_JRBC_STATUS__IB_TRAP_STATUS__SHIFT 0xc
+#define UVD_JRBC0_UVD_JRBC_STATUS__INT_EN__SHIFT 0x10
+#define UVD_JRBC0_UVD_JRBC_STATUS__INT_ACK__SHIFT 0x11
+#define UVD_JRBC0_UVD_JRBC_STATUS__RB_JOB_DONE_MASK 0x00000001L
+#define UVD_JRBC0_UVD_JRBC_STATUS__IB_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC0_UVD_JRBC_STATUS__RB_ILLEGAL_CMD_MASK 0x00000004L
+#define UVD_JRBC0_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT_MASK 0x00000008L
+#define UVD_JRBC0_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT_MASK 0x00000010L
+#define UVD_JRBC0_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT_MASK 0x00000020L
+#define UVD_JRBC0_UVD_JRBC_STATUS__IB_ILLEGAL_CMD_MASK 0x00000040L
+#define UVD_JRBC0_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT_MASK 0x00000080L
+#define UVD_JRBC0_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT_MASK 0x00000100L
+#define UVD_JRBC0_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT_MASK 0x00000200L
+#define UVD_JRBC0_UVD_JRBC_STATUS__RB_TRAP_STATUS_MASK 0x00000400L
+#define UVD_JRBC0_UVD_JRBC_STATUS__PREEMPT_STATUS_MASK 0x00000800L
+#define UVD_JRBC0_UVD_JRBC_STATUS__IB_TRAP_STATUS_MASK 0x00001000L
+#define UVD_JRBC0_UVD_JRBC_STATUS__INT_EN_MASK 0x00010000L
+#define UVD_JRBC0_UVD_JRBC_STATUS__INT_ACK_MASK 0x00020000L
+//UVD_JRBC0_UVD_JRBC_RB_RPTR
+#define UVD_JRBC0_UVD_JRBC_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_JRBC0_UVD_JRBC_RB_RPTR__RB_RPTR_MASK 0x007FFFF0L
+//UVD_JRBC0_UVD_JRBC_RB_BUF_STATUS
+#define UVD_JRBC0_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC0_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC0_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC0_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC0_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC0_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC0_UVD_JRBC_IB_BUF_STATUS
+#define UVD_JRBC0_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC0_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC0_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC0_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC0_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC0_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC0_UVD_JRBC_IB_SIZE_UPDATE
+#define UVD_JRBC0_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE__SHIFT 0x4
+#define UVD_JRBC0_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC0_UVD_JRBC_IB_COND_RD_TIMER
+#define UVD_JRBC0_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC0_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC0_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC0_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC0_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC0_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC0_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC0_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC0_UVD_JRBC_IB_REF_DATA
+#define UVD_JRBC0_UVD_JRBC_IB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC0_UVD_JRBC_IB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC0_UVD_JPEG_PREEMPT_CMD
+#define UVD_JRBC0_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN__SHIFT 0x0
+#define UVD_JRBC0_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC0_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD__SHIFT 0x2
+#define UVD_JRBC0_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN_MASK 0x00000001L
+#define UVD_JRBC0_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC0_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD_MASK 0x00000004L
+//UVD_JRBC0_UVD_JPEG_PREEMPT_FENCE_DATA0
+#define UVD_JRBC0_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0__SHIFT 0x0
+#define UVD_JRBC0_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0_MASK 0xFFFFFFFFL
+//UVD_JRBC0_UVD_JPEG_PREEMPT_FENCE_DATA1
+#define UVD_JRBC0_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1__SHIFT 0x0
+#define UVD_JRBC0_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1_MASK 0xFFFFFFFFL
+//UVD_JRBC0_UVD_JRBC_RB_SIZE
+#define UVD_JRBC0_UVD_JRBC_RB_SIZE__RB_SIZE__SHIFT 0x4
+#define UVD_JRBC0_UVD_JRBC_RB_SIZE__RB_SIZE_MASK 0x00FFFFF0L
+//UVD_JRBC0_UVD_JRBC_SCRATCH0
+#define UVD_JRBC0_UVD_JRBC_SCRATCH0__SCRATCH0__SHIFT 0x0
+#define UVD_JRBC0_UVD_JRBC_SCRATCH0__SCRATCH0_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_uvd0_uvd_jmi0_uvd_jmi_dec
+//UVD_JMI0_UVD_JPEG_DEC_PF_CTRL
+#define UVD_JMI0_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS__SHIFT 0x0
+#define UVD_JMI0_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING__SHIFT 0x1
+#define UVD_JMI0_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS_MASK 0x00000001L
+#define UVD_JMI0_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING_MASK 0x00000002L
+//UVD_JMI0_UVD_LMI_JRBC_CTRL
+#define UVD_JMI0_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI0_UVD_LMI_JRBC_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI0_UVD_LMI_JRBC_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI0_UVD_LMI_JRBC_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI0_UVD_LMI_JRBC_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI0_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI0_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI0_UVD_LMI_JRBC_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI0_UVD_LMI_JRBC_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI0_UVD_LMI_JRBC_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI0_UVD_LMI_JRBC_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI0_UVD_LMI_JPEG_CTRL
+#define UVD_JMI0_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI0_UVD_LMI_JPEG_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI0_UVD_LMI_JPEG_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI0_UVD_LMI_JPEG_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI0_UVD_LMI_JPEG_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI0_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI0_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI0_UVD_LMI_JPEG_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI0_UVD_LMI_JPEG_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI0_UVD_LMI_JPEG_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI0_UVD_LMI_JPEG_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI0_JPEG_LMI_DROP
+#define UVD_JMI0_JPEG_LMI_DROP__JPEG_WR_DROP__SHIFT 0x0
+#define UVD_JMI0_JPEG_LMI_DROP__JRBC_WR_DROP__SHIFT 0x1
+#define UVD_JMI0_JPEG_LMI_DROP__JPEG_RD_DROP__SHIFT 0x2
+#define UVD_JMI0_JPEG_LMI_DROP__JRBC_RD_DROP__SHIFT 0x3
+#define UVD_JMI0_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP__SHIFT 0x4
+#define UVD_JMI0_JPEG_LMI_DROP__JPEG_WR_DROP_MASK 0x00000001L
+#define UVD_JMI0_JPEG_LMI_DROP__JRBC_WR_DROP_MASK 0x00000002L
+#define UVD_JMI0_JPEG_LMI_DROP__JPEG_RD_DROP_MASK 0x00000004L
+#define UVD_JMI0_JPEG_LMI_DROP__JRBC_RD_DROP_MASK 0x00000008L
+#define UVD_JMI0_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP_MASK 0x00000010L
+//UVD_JMI0_UVD_LMI_JRBC_IB_VMID
+#define UVD_JMI0_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID__SHIFT 0x4
+#define UVD_JMI0_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI0_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI0_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI0_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI0_UVD_LMI_JRBC_RB_VMID
+#define UVD_JMI0_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID__SHIFT 0x4
+#define UVD_JMI0_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI0_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI0_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI0_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI0_UVD_LMI_JPEG_VMID
+#define UVD_JMI0_UVD_LMI_JPEG_VMID__JPEG_RD_VMID__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JPEG_VMID__JPEG_WR_VMID__SHIFT 0x4
+#define UVD_JMI0_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID__SHIFT 0x8
+#define UVD_JMI0_UVD_LMI_JPEG_VMID__JPEG_RD_VMID_MASK 0x0000000FL
+#define UVD_JMI0_UVD_LMI_JPEG_VMID__JPEG_WR_VMID_MASK 0x000000F0L
+#define UVD_JMI0_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID_MASK 0x00000F00L
+//UVD_JMI0_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW
+#define UVD_JMI0_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH
+#define UVD_JMI0_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JRBC_RB_64BIT_BAR_LOW
+#define UVD_JMI0_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH
+#define UVD_JMI0_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI0_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI0_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JPEG_PREEMPT_VMID
+#define UVD_JMI0_UVD_LMI_JPEG_PREEMPT_VMID__VMID__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JPEG_PREEMPT_VMID__VMID_MASK 0x0000000FL
+//UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP__SHIFT 0x0
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP__SHIFT 0x2
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP__SHIFT 0x4
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP__SHIFT 0x6
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP__SHIFT 0x8
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP__SHIFT 0xa
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP__SHIFT 0xc
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP__SHIFT 0xe
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP__SHIFT 0x10
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP_MASK 0x00000003L
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP_MASK 0x0000000CL
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP_MASK 0x00000030L
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP_MASK 0x000000C0L
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP_MASK 0x00000300L
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP_MASK 0x00000C00L
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP_MASK 0x00003000L
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP_MASK 0x0000C000L
+#define UVD_JMI0_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP_MASK 0x00030000L
+//UVD_JMI0_UVD_JMI_ATOMIC_CNTL
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en__SHIFT 0x0
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL__atomic_max_burst__SHIFT 0x1
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop__SHIFT 0x5
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en__SHIFT 0x6
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG__SHIFT 0x7
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE__SHIFT 0xb
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en_MASK 0x00000001L
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL__atomic_max_burst_MASK 0x0000001EL
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop_MASK 0x00000020L
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en_MASK 0x00000040L
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG_MASK 0x00000780L
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE_MASK 0x00000800L
+//UVD_JMI0_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW
+#define UVD_JMI0_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI0_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI0_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI0_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JPEG_READ_64BIT_BAR_LOW
+#define UVD_JMI0_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH
+#define UVD_JMI0_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW
+#define UVD_JMI0_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI0_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JRBC_IB_64BIT_BAR_LOW
+#define UVD_JMI0_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH
+#define UVD_JMI0_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI0_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI0_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI0_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI0_UVD_JMI_ATOMIC_CNTL2
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap__SHIFT 0x10
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP__SHIFT 0x18
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap_MASK 0x00FF0000L
+#define UVD_JMI0_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP_MASK 0xFF000000L
+
+
+// addressBlock: aid_uvd0_uvd_jmi_common_dec
+//UVD_JADP_MCIF_URGENT_CTRL
+#define UVD_JADP_MCIF_URGENT_CTRL__WR_WATERMARK__SHIFT 0x0
+#define UVD_JADP_MCIF_URGENT_CTRL__RD_WATERMARK__SHIFT 0x6
+#define UVD_JADP_MCIF_URGENT_CTRL__WR_RD_URGENT_TIMER__SHIFT 0xb
+#define UVD_JADP_MCIF_URGENT_CTRL__WR_URGENT_PROG_STEP__SHIFT 0x11
+#define UVD_JADP_MCIF_URGENT_CTRL__RD_URGENT_PROG_STEP__SHIFT 0x15
+#define UVD_JADP_MCIF_URGENT_CTRL__WR_QOS_EN__SHIFT 0x19
+#define UVD_JADP_MCIF_URGENT_CTRL__RD_QOS_EN__SHIFT 0x1a
+#define UVD_JADP_MCIF_URGENT_CTRL__WR_WATERMARK_MASK 0x0000003FL
+#define UVD_JADP_MCIF_URGENT_CTRL__RD_WATERMARK_MASK 0x000007C0L
+#define UVD_JADP_MCIF_URGENT_CTRL__WR_RD_URGENT_TIMER_MASK 0x0001F800L
+#define UVD_JADP_MCIF_URGENT_CTRL__WR_URGENT_PROG_STEP_MASK 0x001E0000L
+#define UVD_JADP_MCIF_URGENT_CTRL__RD_URGENT_PROG_STEP_MASK 0x01E00000L
+#define UVD_JADP_MCIF_URGENT_CTRL__WR_QOS_EN_MASK 0x02000000L
+#define UVD_JADP_MCIF_URGENT_CTRL__RD_QOS_EN_MASK 0x04000000L
+//UVD_JMI_URGENT_CTRL
+#define UVD_JMI_URGENT_CTRL__ENABLE_MC_RD_URGENT_STALL__SHIFT 0x0
+#define UVD_JMI_URGENT_CTRL__ASSERT_MC_RD_URGENT__SHIFT 0x4
+#define UVD_JMI_URGENT_CTRL__ENABLE_MC_WR_URGENT_STALL__SHIFT 0x10
+#define UVD_JMI_URGENT_CTRL__ASSERT_MC_WR_URGENT__SHIFT 0x14
+#define UVD_JMI_URGENT_CTRL__ENABLE_MC_RD_URGENT_STALL_MASK 0x00000001L
+#define UVD_JMI_URGENT_CTRL__ASSERT_MC_RD_URGENT_MASK 0x000000F0L
+#define UVD_JMI_URGENT_CTRL__ENABLE_MC_WR_URGENT_STALL_MASK 0x00010000L
+#define UVD_JMI_URGENT_CTRL__ASSERT_MC_WR_URGENT_MASK 0x00F00000L
+//UVD_JMI_CTRL
+#define UVD_JMI_CTRL__STALL_MC_ARB__SHIFT 0x0
+#define UVD_JMI_CTRL__MASK_MC_URGENT__SHIFT 0x1
+#define UVD_JMI_CTRL__ASSERT_MC_URGENT__SHIFT 0x2
+#define UVD_JMI_CTRL__MC_RD_ARB_WAIT_TIMER__SHIFT 0x8
+#define UVD_JMI_CTRL__MC_WR_ARB_WAIT_TIMER__SHIFT 0x10
+#define UVD_JMI_CTRL__STALL_MC_ARB_MASK 0x00000001L
+#define UVD_JMI_CTRL__MASK_MC_URGENT_MASK 0x00000002L
+#define UVD_JMI_CTRL__ASSERT_MC_URGENT_MASK 0x00000004L
+#define UVD_JMI_CTRL__MC_RD_ARB_WAIT_TIMER_MASK 0x0000FF00L
+#define UVD_JMI_CTRL__MC_WR_ARB_WAIT_TIMER_MASK 0x00FF0000L
+//JPEG_MEMCHECK_CLAMPING_CNTL
+#define JPEG_MEMCHECK_CLAMPING_CNTL__CLAMP_TO_SAFE_ADDR_EN__SHIFT 0x0
+#define JPEG_MEMCHECK_CLAMPING_CNTL__CLAMP_TO_SAFE_ADDR_EN_MASK 0x00000001L
+//JPEG_MEMCHECK_SAFE_ADDR
+#define JPEG_MEMCHECK_SAFE_ADDR__MEMCHECK_SAFE_ADDR__SHIFT 0x0
+#define JPEG_MEMCHECK_SAFE_ADDR__MEMCHECK_SAFE_ADDR_MASK 0xFFFFFFFFL
+//JPEG_MEMCHECK_SAFE_ADDR_64BIT
+#define JPEG_MEMCHECK_SAFE_ADDR_64BIT__MEMCHECK_SAFE_ADDR_64BIT__SHIFT 0x0
+#define JPEG_MEMCHECK_SAFE_ADDR_64BIT__MEMCHECK_SAFE_ADDR_64BIT_MASK 0xFFFFFFFFL
+//UVD_JMI_LAT_CTRL
+#define UVD_JMI_LAT_CTRL__SCALE__SHIFT 0x0
+#define UVD_JMI_LAT_CTRL__MAX_START__SHIFT 0x8
+#define UVD_JMI_LAT_CTRL__MIN_START__SHIFT 0x9
+#define UVD_JMI_LAT_CTRL__AVG_START__SHIFT 0xa
+#define UVD_JMI_LAT_CTRL__PERFMON_SYNC__SHIFT 0xb
+#define UVD_JMI_LAT_CTRL__SKIP__SHIFT 0x10
+#define UVD_JMI_LAT_CTRL__SCALE_MASK 0x000000FFL
+#define UVD_JMI_LAT_CTRL__MAX_START_MASK 0x00000100L
+#define UVD_JMI_LAT_CTRL__MIN_START_MASK 0x00000200L
+#define UVD_JMI_LAT_CTRL__AVG_START_MASK 0x00000400L
+#define UVD_JMI_LAT_CTRL__PERFMON_SYNC_MASK 0x00000800L
+#define UVD_JMI_LAT_CTRL__SKIP_MASK 0x000F0000L
+//UVD_JMI_LAT_CNTR
+#define UVD_JMI_LAT_CNTR__MAX_LAT__SHIFT 0x0
+#define UVD_JMI_LAT_CNTR__MIN_LAT__SHIFT 0x8
+#define UVD_JMI_LAT_CNTR__MAX_LAT_MASK 0x000000FFL
+#define UVD_JMI_LAT_CNTR__MIN_LAT_MASK 0x0000FF00L
+//UVD_JMI_AVG_LAT_CNTR
+#define UVD_JMI_AVG_LAT_CNTR__ENV_LOW__SHIFT 0x0
+#define UVD_JMI_AVG_LAT_CNTR__ENV_HIGH__SHIFT 0x8
+#define UVD_JMI_AVG_LAT_CNTR__ENV_HIT__SHIFT 0x10
+#define UVD_JMI_AVG_LAT_CNTR__ENV_LOW_MASK 0x000000FFL
+#define UVD_JMI_AVG_LAT_CNTR__ENV_HIGH_MASK 0x0000FF00L
+#define UVD_JMI_AVG_LAT_CNTR__ENV_HIT_MASK 0xFFFF0000L
+//UVD_JMI_PERFMON_CTRL
+#define UVD_JMI_PERFMON_CTRL__PERFMON_STATE__SHIFT 0x0
+#define UVD_JMI_PERFMON_CTRL__PERFMON_SEL__SHIFT 0x8
+#define UVD_JMI_PERFMON_CTRL__PERFMON_STATE_MASK 0x00000003L
+#define UVD_JMI_PERFMON_CTRL__PERFMON_SEL_MASK 0x00001F00L
+//UVD_JMI_PERFMON_COUNT_LO
+#define UVD_JMI_PERFMON_COUNT_LO__PERFMON_COUNT__SHIFT 0x0
+#define UVD_JMI_PERFMON_COUNT_LO__PERFMON_COUNT_MASK 0xFFFFFFFFL
+//UVD_JMI_PERFMON_COUNT_HI
+#define UVD_JMI_PERFMON_COUNT_HI__PERFMON_COUNT__SHIFT 0x0
+#define UVD_JMI_PERFMON_COUNT_HI__PERFMON_COUNT_MASK 0x0000FFFFL
+//UVD_JMI_CLEAN_STATUS
+#define UVD_JMI_CLEAN_STATUS__LMI_READ_CLEAN__SHIFT 0x0
+#define UVD_JMI_CLEAN_STATUS__LMI_READ_CLEAN_RAW__SHIFT 0x1
+#define UVD_JMI_CLEAN_STATUS__LMI_WRITE_CLEAN__SHIFT 0x2
+#define UVD_JMI_CLEAN_STATUS__LMI_WRITE_CLEAN_RAW__SHIFT 0x3
+#define UVD_JMI_CLEAN_STATUS__MC_WRITE_PENDING__SHIFT 0x4
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE0_READ_CLEAN__SHIFT 0x8
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE1_READ_CLEAN__SHIFT 0x9
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE2_READ_CLEAN__SHIFT 0xa
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE3_READ_CLEAN__SHIFT 0xb
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE4_READ_CLEAN__SHIFT 0xc
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE5_READ_CLEAN__SHIFT 0xd
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE6_READ_CLEAN__SHIFT 0xe
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE7_READ_CLEAN__SHIFT 0xf
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE0_WRITE_CLEAN__SHIFT 0x10
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE1_WRITE_CLEAN__SHIFT 0x11
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE2_WRITE_CLEAN__SHIFT 0x12
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE3_WRITE_CLEAN__SHIFT 0x13
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE4_WRITE_CLEAN__SHIFT 0x14
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE5_WRITE_CLEAN__SHIFT 0x15
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE6_WRITE_CLEAN__SHIFT 0x16
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE7_WRITE_CLEAN__SHIFT 0x17
+#define UVD_JMI_CLEAN_STATUS__LMI_READ_CLEAN_MASK 0x00000001L
+#define UVD_JMI_CLEAN_STATUS__LMI_READ_CLEAN_RAW_MASK 0x00000002L
+#define UVD_JMI_CLEAN_STATUS__LMI_WRITE_CLEAN_MASK 0x00000004L
+#define UVD_JMI_CLEAN_STATUS__LMI_WRITE_CLEAN_RAW_MASK 0x00000008L
+#define UVD_JMI_CLEAN_STATUS__MC_WRITE_PENDING_MASK 0x00000010L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE0_READ_CLEAN_MASK 0x00000100L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE1_READ_CLEAN_MASK 0x00000200L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE2_READ_CLEAN_MASK 0x00000400L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE3_READ_CLEAN_MASK 0x00000800L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE4_READ_CLEAN_MASK 0x00001000L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE5_READ_CLEAN_MASK 0x00002000L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE6_READ_CLEAN_MASK 0x00004000L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE7_READ_CLEAN_MASK 0x00008000L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE0_WRITE_CLEAN_MASK 0x00010000L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE1_WRITE_CLEAN_MASK 0x00020000L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE2_WRITE_CLEAN_MASK 0x00040000L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE3_WRITE_CLEAN_MASK 0x00080000L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE4_WRITE_CLEAN_MASK 0x00100000L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE5_WRITE_CLEAN_MASK 0x00200000L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE6_WRITE_CLEAN_MASK 0x00400000L
+#define UVD_JMI_CLEAN_STATUS__DJPEG_CORE7_WRITE_CLEAN_MASK 0x00800000L
+//UVD_JMI_CNTL
+#define UVD_JMI_CNTL__SOFT_RESET__SHIFT 0x0
+#define UVD_JMI_CNTL__MC_RD_REQ_RET_MAX__SHIFT 0x8
+#define UVD_JMI_CNTL__SOFT_RESET_MASK 0x00000001L
+#define UVD_JMI_CNTL__MC_RD_REQ_RET_MAX_MASK 0x0003FF00L
+
+
+// addressBlock: aid_uvd0_uvd_jpeg_common_dec
+//JPEG_SOFT_RESET_STATUS
+#define JPEG_SOFT_RESET_STATUS__JPEG0_DEC_RESET_STATUS__SHIFT 0x0
+#define JPEG_SOFT_RESET_STATUS__JPEG1_DEC_RESET_STATUS__SHIFT 0x1
+#define JPEG_SOFT_RESET_STATUS__JPEG2_DEC_RESET_STATUS__SHIFT 0x2
+#define JPEG_SOFT_RESET_STATUS__JPEG3_DEC_RESET_STATUS__SHIFT 0x3
+#define JPEG_SOFT_RESET_STATUS__JPEG4_DEC_RESET_STATUS__SHIFT 0x4
+#define JPEG_SOFT_RESET_STATUS__JPEG5_DEC_RESET_STATUS__SHIFT 0x5
+#define JPEG_SOFT_RESET_STATUS__JPEG6_DEC_RESET_STATUS__SHIFT 0x6
+#define JPEG_SOFT_RESET_STATUS__JPEG7_DEC_RESET_STATUS__SHIFT 0x7
+#define JPEG_SOFT_RESET_STATUS__DJRBC0_RESET_STATUS__SHIFT 0x8
+#define JPEG_SOFT_RESET_STATUS__DJRBC1_RESET_STATUS__SHIFT 0x9
+#define JPEG_SOFT_RESET_STATUS__DJRBC2_RESET_STATUS__SHIFT 0xa
+#define JPEG_SOFT_RESET_STATUS__DJRBC3_RESET_STATUS__SHIFT 0xb
+#define JPEG_SOFT_RESET_STATUS__DJRBC4_RESET_STATUS__SHIFT 0xc
+#define JPEG_SOFT_RESET_STATUS__DJRBC5_RESET_STATUS__SHIFT 0xd
+#define JPEG_SOFT_RESET_STATUS__DJRBC6_RESET_STATUS__SHIFT 0xe
+#define JPEG_SOFT_RESET_STATUS__DJRBC7_RESET_STATUS__SHIFT 0xf
+#define JPEG_SOFT_RESET_STATUS__JPEG_ENC_RESET_STATUS__SHIFT 0x11
+#define JPEG_SOFT_RESET_STATUS__EJRBC_RESET_STATUS__SHIFT 0x12
+#define JPEG_SOFT_RESET_STATUS__JMCIF_RESET_STATUS__SHIFT 0x18
+#define JPEG_SOFT_RESET_STATUS__JPEG0_DEC_RESET_STATUS_MASK 0x00000001L
+#define JPEG_SOFT_RESET_STATUS__JPEG1_DEC_RESET_STATUS_MASK 0x00000002L
+#define JPEG_SOFT_RESET_STATUS__JPEG2_DEC_RESET_STATUS_MASK 0x00000004L
+#define JPEG_SOFT_RESET_STATUS__JPEG3_DEC_RESET_STATUS_MASK 0x00000008L
+#define JPEG_SOFT_RESET_STATUS__JPEG4_DEC_RESET_STATUS_MASK 0x00000010L
+#define JPEG_SOFT_RESET_STATUS__JPEG5_DEC_RESET_STATUS_MASK 0x00000020L
+#define JPEG_SOFT_RESET_STATUS__JPEG6_DEC_RESET_STATUS_MASK 0x00000040L
+#define JPEG_SOFT_RESET_STATUS__JPEG7_DEC_RESET_STATUS_MASK 0x00000080L
+#define JPEG_SOFT_RESET_STATUS__DJRBC0_RESET_STATUS_MASK 0x00000100L
+#define JPEG_SOFT_RESET_STATUS__DJRBC1_RESET_STATUS_MASK 0x00000200L
+#define JPEG_SOFT_RESET_STATUS__DJRBC2_RESET_STATUS_MASK 0x00000400L
+#define JPEG_SOFT_RESET_STATUS__DJRBC3_RESET_STATUS_MASK 0x00000800L
+#define JPEG_SOFT_RESET_STATUS__DJRBC4_RESET_STATUS_MASK 0x00001000L
+#define JPEG_SOFT_RESET_STATUS__DJRBC5_RESET_STATUS_MASK 0x00002000L
+#define JPEG_SOFT_RESET_STATUS__DJRBC6_RESET_STATUS_MASK 0x00004000L
+#define JPEG_SOFT_RESET_STATUS__DJRBC7_RESET_STATUS_MASK 0x00008000L
+#define JPEG_SOFT_RESET_STATUS__JPEG_ENC_RESET_STATUS_MASK 0x00020000L
+#define JPEG_SOFT_RESET_STATUS__EJRBC_RESET_STATUS_MASK 0x00040000L
+#define JPEG_SOFT_RESET_STATUS__JMCIF_RESET_STATUS_MASK 0x01000000L
+//JPEG_SYS_INT_EN
+#define JPEG_SYS_INT_EN__DJPEG0_CORE__SHIFT 0x0
+#define JPEG_SYS_INT_EN__DJPEG1_CORE__SHIFT 0x1
+#define JPEG_SYS_INT_EN__DJPEG2_CORE__SHIFT 0x2
+#define JPEG_SYS_INT_EN__DJPEG3_CORE__SHIFT 0x3
+#define JPEG_SYS_INT_EN__DJPEG4_CORE__SHIFT 0x4
+#define JPEG_SYS_INT_EN__DJPEG5_CORE__SHIFT 0x5
+#define JPEG_SYS_INT_EN__DJPEG6_CORE__SHIFT 0x6
+#define JPEG_SYS_INT_EN__DJPEG7_CORE__SHIFT 0x7
+#define JPEG_SYS_INT_EN__DJRBC0__SHIFT 0x8
+#define JPEG_SYS_INT_EN__DJRBC1__SHIFT 0x9
+#define JPEG_SYS_INT_EN__DJRBC2__SHIFT 0xa
+#define JPEG_SYS_INT_EN__DJRBC3__SHIFT 0xb
+#define JPEG_SYS_INT_EN__DJRBC4__SHIFT 0xc
+#define JPEG_SYS_INT_EN__DJRBC5__SHIFT 0xd
+#define JPEG_SYS_INT_EN__DJRBC6__SHIFT 0xe
+#define JPEG_SYS_INT_EN__DJRBC7__SHIFT 0xf
+#define JPEG_SYS_INT_EN__DJPEG0_PF_RPT__SHIFT 0x10
+#define JPEG_SYS_INT_EN__DJPEG1_PF_RPT__SHIFT 0x11
+#define JPEG_SYS_INT_EN__DJPEG2_PF_RPT__SHIFT 0x12
+#define JPEG_SYS_INT_EN__DJPEG3_PF_RPT__SHIFT 0x13
+#define JPEG_SYS_INT_EN__DJPEG4_PF_RPT__SHIFT 0x14
+#define JPEG_SYS_INT_EN__DJPEG5_PF_RPT__SHIFT 0x15
+#define JPEG_SYS_INT_EN__DJPEG6_PF_RPT__SHIFT 0x16
+#define JPEG_SYS_INT_EN__DJPEG7_PF_RPT__SHIFT 0x17
+#define JPEG_SYS_INT_EN__DJPEG0_RAS_CNTL__SHIFT 0x18
+#define JPEG_SYS_INT_EN__DJPEG1_RAS_CNTL__SHIFT 0x19
+#define JPEG_SYS_INT_EN__DJPEG0_CORE_MASK 0x00000001L
+#define JPEG_SYS_INT_EN__DJPEG1_CORE_MASK 0x00000002L
+#define JPEG_SYS_INT_EN__DJPEG2_CORE_MASK 0x00000004L
+#define JPEG_SYS_INT_EN__DJPEG3_CORE_MASK 0x00000008L
+#define JPEG_SYS_INT_EN__DJPEG4_CORE_MASK 0x00000010L
+#define JPEG_SYS_INT_EN__DJPEG5_CORE_MASK 0x00000020L
+#define JPEG_SYS_INT_EN__DJPEG6_CORE_MASK 0x00000040L
+#define JPEG_SYS_INT_EN__DJPEG7_CORE_MASK 0x00000080L
+#define JPEG_SYS_INT_EN__DJRBC0_MASK 0x00000100L
+#define JPEG_SYS_INT_EN__DJRBC1_MASK 0x00000200L
+#define JPEG_SYS_INT_EN__DJRBC2_MASK 0x00000400L
+#define JPEG_SYS_INT_EN__DJRBC3_MASK 0x00000800L
+#define JPEG_SYS_INT_EN__DJRBC4_MASK 0x00001000L
+#define JPEG_SYS_INT_EN__DJRBC5_MASK 0x00002000L
+#define JPEG_SYS_INT_EN__DJRBC6_MASK 0x00004000L
+#define JPEG_SYS_INT_EN__DJRBC7_MASK 0x00008000L
+#define JPEG_SYS_INT_EN__DJPEG0_PF_RPT_MASK 0x00010000L
+#define JPEG_SYS_INT_EN__DJPEG1_PF_RPT_MASK 0x00020000L
+#define JPEG_SYS_INT_EN__DJPEG2_PF_RPT_MASK 0x00040000L
+#define JPEG_SYS_INT_EN__DJPEG3_PF_RPT_MASK 0x00080000L
+#define JPEG_SYS_INT_EN__DJPEG4_PF_RPT_MASK 0x00100000L
+#define JPEG_SYS_INT_EN__DJPEG5_PF_RPT_MASK 0x00200000L
+#define JPEG_SYS_INT_EN__DJPEG6_PF_RPT_MASK 0x00400000L
+#define JPEG_SYS_INT_EN__DJPEG7_PF_RPT_MASK 0x00800000L
+#define JPEG_SYS_INT_EN__DJPEG0_RAS_CNTL_MASK 0x01000000L
+#define JPEG_SYS_INT_EN__DJPEG1_RAS_CNTL_MASK 0x02000000L
+//JPEG_SYS_INT_EN1
+#define JPEG_SYS_INT_EN1__EJPEG_PF_RPT__SHIFT 0x0
+#define JPEG_SYS_INT_EN1__EJPEG_CORE__SHIFT 0x1
+#define JPEG_SYS_INT_EN1__EJRBC__SHIFT 0x2
+#define JPEG_SYS_INT_EN1__EJPEG_RAS_CNTL__SHIFT 0x3
+#define JPEG_SYS_INT_EN1__EJPEG_PF_RPT_MASK 0x00000001L
+#define JPEG_SYS_INT_EN1__EJPEG_CORE_MASK 0x00000002L
+#define JPEG_SYS_INT_EN1__EJRBC_MASK 0x00000004L
+#define JPEG_SYS_INT_EN1__EJPEG_RAS_CNTL_MASK 0x00000008L
+//JPEG_SYS_INT_STATUS
+#define JPEG_SYS_INT_STATUS__DJPEG0_CORE__SHIFT 0x0
+#define JPEG_SYS_INT_STATUS__DJPEG1_CORE__SHIFT 0x1
+#define JPEG_SYS_INT_STATUS__DJPEG2_CORE__SHIFT 0x2
+#define JPEG_SYS_INT_STATUS__DJPEG3_CORE__SHIFT 0x3
+#define JPEG_SYS_INT_STATUS__DJPEG4_CORE__SHIFT 0x4
+#define JPEG_SYS_INT_STATUS__DJPEG5_CORE__SHIFT 0x5
+#define JPEG_SYS_INT_STATUS__DJPEG6_CORE__SHIFT 0x6
+#define JPEG_SYS_INT_STATUS__DJPEG7_CORE__SHIFT 0x7
+#define JPEG_SYS_INT_STATUS__DJRBC0__SHIFT 0x8
+#define JPEG_SYS_INT_STATUS__DJRBC1__SHIFT 0x9
+#define JPEG_SYS_INT_STATUS__DJRBC2__SHIFT 0xa
+#define JPEG_SYS_INT_STATUS__DJRBC3__SHIFT 0xb
+#define JPEG_SYS_INT_STATUS__DJRBC4__SHIFT 0xc
+#define JPEG_SYS_INT_STATUS__DJRBC5__SHIFT 0xd
+#define JPEG_SYS_INT_STATUS__DJRBC6__SHIFT 0xe
+#define JPEG_SYS_INT_STATUS__DJRBC7__SHIFT 0xf
+#define JPEG_SYS_INT_STATUS__DJPEG0_PF_RPT__SHIFT 0x10
+#define JPEG_SYS_INT_STATUS__DJPEG1_PF_RPT__SHIFT 0x11
+#define JPEG_SYS_INT_STATUS__DJPEG2_PF_RPT__SHIFT 0x12
+#define JPEG_SYS_INT_STATUS__DJPEG3_PF_RPT__SHIFT 0x13
+#define JPEG_SYS_INT_STATUS__DJPEG4_PF_RPT__SHIFT 0x14
+#define JPEG_SYS_INT_STATUS__DJPEG5_PF_RPT__SHIFT 0x15
+#define JPEG_SYS_INT_STATUS__DJPEG6_PF_RPT__SHIFT 0x16
+#define JPEG_SYS_INT_STATUS__DJPEG7_PF_RPT__SHIFT 0x17
+#define JPEG_SYS_INT_STATUS__DJPEG0_RAS_CNTL__SHIFT 0x18
+#define JPEG_SYS_INT_STATUS__DJPEG1_RAS_CNTL__SHIFT 0x19
+#define JPEG_SYS_INT_STATUS__DJPEG0_CORE_MASK 0x00000001L
+#define JPEG_SYS_INT_STATUS__DJPEG1_CORE_MASK 0x00000002L
+#define JPEG_SYS_INT_STATUS__DJPEG2_CORE_MASK 0x00000004L
+#define JPEG_SYS_INT_STATUS__DJPEG3_CORE_MASK 0x00000008L
+#define JPEG_SYS_INT_STATUS__DJPEG4_CORE_MASK 0x00000010L
+#define JPEG_SYS_INT_STATUS__DJPEG5_CORE_MASK 0x00000020L
+#define JPEG_SYS_INT_STATUS__DJPEG6_CORE_MASK 0x00000040L
+#define JPEG_SYS_INT_STATUS__DJPEG7_CORE_MASK 0x00000080L
+#define JPEG_SYS_INT_STATUS__DJRBC0_MASK 0x00000100L
+#define JPEG_SYS_INT_STATUS__DJRBC1_MASK 0x00000200L
+#define JPEG_SYS_INT_STATUS__DJRBC2_MASK 0x00000400L
+#define JPEG_SYS_INT_STATUS__DJRBC3_MASK 0x00000800L
+#define JPEG_SYS_INT_STATUS__DJRBC4_MASK 0x00001000L
+#define JPEG_SYS_INT_STATUS__DJRBC5_MASK 0x00002000L
+#define JPEG_SYS_INT_STATUS__DJRBC6_MASK 0x00004000L
+#define JPEG_SYS_INT_STATUS__DJRBC7_MASK 0x00008000L
+#define JPEG_SYS_INT_STATUS__DJPEG0_PF_RPT_MASK 0x00010000L
+#define JPEG_SYS_INT_STATUS__DJPEG1_PF_RPT_MASK 0x00020000L
+#define JPEG_SYS_INT_STATUS__DJPEG2_PF_RPT_MASK 0x00040000L
+#define JPEG_SYS_INT_STATUS__DJPEG3_PF_RPT_MASK 0x00080000L
+#define JPEG_SYS_INT_STATUS__DJPEG4_PF_RPT_MASK 0x00100000L
+#define JPEG_SYS_INT_STATUS__DJPEG5_PF_RPT_MASK 0x00200000L
+#define JPEG_SYS_INT_STATUS__DJPEG6_PF_RPT_MASK 0x00400000L
+#define JPEG_SYS_INT_STATUS__DJPEG7_PF_RPT_MASK 0x00800000L
+#define JPEG_SYS_INT_STATUS__DJPEG0_RAS_CNTL_MASK 0x01000000L
+#define JPEG_SYS_INT_STATUS__DJPEG1_RAS_CNTL_MASK 0x02000000L
+//JPEG_SYS_INT_STATUS1
+#define JPEG_SYS_INT_STATUS1__EJPEG_PF_RPT__SHIFT 0x0
+#define JPEG_SYS_INT_STATUS1__EJPEG_CORE__SHIFT 0x1
+#define JPEG_SYS_INT_STATUS1__EJRBC__SHIFT 0x2
+#define JPEG_SYS_INT_STATUS1__EJPEG_RAS_CNTL__SHIFT 0x3
+#define JPEG_SYS_INT_STATUS1__EJPEG_PF_RPT_MASK 0x00000001L
+#define JPEG_SYS_INT_STATUS1__EJPEG_CORE_MASK 0x00000002L
+#define JPEG_SYS_INT_STATUS1__EJRBC_MASK 0x00000004L
+#define JPEG_SYS_INT_STATUS1__EJPEG_RAS_CNTL_MASK 0x00000008L
+//JPEG_SYS_INT_ACK
+#define JPEG_SYS_INT_ACK__DJPEG0_CORE__SHIFT 0x0
+#define JPEG_SYS_INT_ACK__DJPEG1_CORE__SHIFT 0x1
+#define JPEG_SYS_INT_ACK__DJPEG2_CORE__SHIFT 0x2
+#define JPEG_SYS_INT_ACK__DJPEG3_CORE__SHIFT 0x3
+#define JPEG_SYS_INT_ACK__DJPEG4_CORE__SHIFT 0x4
+#define JPEG_SYS_INT_ACK__DJPEG5_CORE__SHIFT 0x5
+#define JPEG_SYS_INT_ACK__DJPEG6_CORE__SHIFT 0x6
+#define JPEG_SYS_INT_ACK__DJPEG7_CORE__SHIFT 0x7
+#define JPEG_SYS_INT_ACK__DJRBC0__SHIFT 0x8
+#define JPEG_SYS_INT_ACK__DJRBC1__SHIFT 0x9
+#define JPEG_SYS_INT_ACK__DJRBC2__SHIFT 0xa
+#define JPEG_SYS_INT_ACK__DJRBC3__SHIFT 0xb
+#define JPEG_SYS_INT_ACK__DJRBC4__SHIFT 0xc
+#define JPEG_SYS_INT_ACK__DJRBC5__SHIFT 0xd
+#define JPEG_SYS_INT_ACK__DJRBC6__SHIFT 0xe
+#define JPEG_SYS_INT_ACK__DJRBC7__SHIFT 0xf
+#define JPEG_SYS_INT_ACK__DJPEG0_PF_RPT__SHIFT 0x10
+#define JPEG_SYS_INT_ACK__DJPEG1_PF_RPT__SHIFT 0x11
+#define JPEG_SYS_INT_ACK__DJPEG2_PF_RPT__SHIFT 0x12
+#define JPEG_SYS_INT_ACK__DJPEG3_PF_RPT__SHIFT 0x13
+#define JPEG_SYS_INT_ACK__DJPEG4_PF_RPT__SHIFT 0x14
+#define JPEG_SYS_INT_ACK__DJPEG5_PF_RPT__SHIFT 0x15
+#define JPEG_SYS_INT_ACK__DJPEG6_PF_RPT__SHIFT 0x16
+#define JPEG_SYS_INT_ACK__DJPEG7_PF_RPT__SHIFT 0x17
+#define JPEG_SYS_INT_ACK__DJPEG0_RAS_CNTL__SHIFT 0x18
+#define JPEG_SYS_INT_ACK__DJPEG1_RAS_CNTL__SHIFT 0x19
+#define JPEG_SYS_INT_ACK__DJPEG0_CORE_MASK 0x00000001L
+#define JPEG_SYS_INT_ACK__DJPEG1_CORE_MASK 0x00000002L
+#define JPEG_SYS_INT_ACK__DJPEG2_CORE_MASK 0x00000004L
+#define JPEG_SYS_INT_ACK__DJPEG3_CORE_MASK 0x00000008L
+#define JPEG_SYS_INT_ACK__DJPEG4_CORE_MASK 0x00000010L
+#define JPEG_SYS_INT_ACK__DJPEG5_CORE_MASK 0x00000020L
+#define JPEG_SYS_INT_ACK__DJPEG6_CORE_MASK 0x00000040L
+#define JPEG_SYS_INT_ACK__DJPEG7_CORE_MASK 0x00000080L
+#define JPEG_SYS_INT_ACK__DJRBC0_MASK 0x00000100L
+#define JPEG_SYS_INT_ACK__DJRBC1_MASK 0x00000200L
+#define JPEG_SYS_INT_ACK__DJRBC2_MASK 0x00000400L
+#define JPEG_SYS_INT_ACK__DJRBC3_MASK 0x00000800L
+#define JPEG_SYS_INT_ACK__DJRBC4_MASK 0x00001000L
+#define JPEG_SYS_INT_ACK__DJRBC5_MASK 0x00002000L
+#define JPEG_SYS_INT_ACK__DJRBC6_MASK 0x00004000L
+#define JPEG_SYS_INT_ACK__DJRBC7_MASK 0x00008000L
+#define JPEG_SYS_INT_ACK__DJPEG0_PF_RPT_MASK 0x00010000L
+#define JPEG_SYS_INT_ACK__DJPEG1_PF_RPT_MASK 0x00020000L
+#define JPEG_SYS_INT_ACK__DJPEG2_PF_RPT_MASK 0x00040000L
+#define JPEG_SYS_INT_ACK__DJPEG3_PF_RPT_MASK 0x00080000L
+#define JPEG_SYS_INT_ACK__DJPEG4_PF_RPT_MASK 0x00100000L
+#define JPEG_SYS_INT_ACK__DJPEG5_PF_RPT_MASK 0x00200000L
+#define JPEG_SYS_INT_ACK__DJPEG6_PF_RPT_MASK 0x00400000L
+#define JPEG_SYS_INT_ACK__DJPEG7_PF_RPT_MASK 0x00800000L
+#define JPEG_SYS_INT_ACK__DJPEG0_RAS_CNTL_MASK 0x01000000L
+#define JPEG_SYS_INT_ACK__DJPEG1_RAS_CNTL_MASK 0x02000000L
+//JPEG_SYS_INT_ACK1
+#define JPEG_SYS_INT_ACK1__EJPEG_PF_RPT__SHIFT 0x0
+#define JPEG_SYS_INT_ACK1__EJPEG_CORE__SHIFT 0x1
+#define JPEG_SYS_INT_ACK1__EJRBC__SHIFT 0x2
+#define JPEG_SYS_INT_ACK1__EJPEG_RAS_CNTL__SHIFT 0x3
+#define JPEG_SYS_INT_ACK1__EJPEG_PF_RPT_MASK 0x00000001L
+#define JPEG_SYS_INT_ACK1__EJPEG_CORE_MASK 0x00000002L
+#define JPEG_SYS_INT_ACK1__EJRBC_MASK 0x00000004L
+#define JPEG_SYS_INT_ACK1__EJPEG_RAS_CNTL_MASK 0x00000008L
+//JPEG_MEMCHECK_SYS_INT_EN
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC0_RD_ERR_EN__SHIFT 0x0
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC1_RD_ERR_EN__SHIFT 0x1
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC2_RD_ERR_EN__SHIFT 0x2
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC3_RD_ERR_EN__SHIFT 0x3
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC4_RD_ERR_EN__SHIFT 0x4
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC5_RD_ERR_EN__SHIFT 0x5
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC6_RD_ERR_EN__SHIFT 0x6
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC7_RD_ERR_EN__SHIFT 0x7
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH0_RD_ERR_EN__SHIFT 0x8
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH1_RD_ERR_EN__SHIFT 0x9
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH2_RD_ERR_EN__SHIFT 0xa
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH3_RD_ERR_EN__SHIFT 0xb
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH4_RD_ERR_EN__SHIFT 0xc
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH5_RD_ERR_EN__SHIFT 0xd
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH6_RD_ERR_EN__SHIFT 0xe
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH7_RD_ERR_EN__SHIFT 0xf
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC0_WR_ERR_EN__SHIFT 0x10
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC1_WR_ERR_EN__SHIFT 0x11
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC2_WR_ERR_EN__SHIFT 0x12
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC3_WR_ERR_EN__SHIFT 0x13
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC4_WR_ERR_EN__SHIFT 0x14
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC5_WR_ERR_EN__SHIFT 0x15
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC6_WR_ERR_EN__SHIFT 0x16
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC7_WR_ERR_EN__SHIFT 0x17
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF0_WR_ERR_EN__SHIFT 0x18
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF1_WR_ERR_EN__SHIFT 0x19
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF2_WR_ERR_EN__SHIFT 0x1a
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF3_WR_ERR_EN__SHIFT 0x1b
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF4_WR_ERR_EN__SHIFT 0x1c
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF5_WR_ERR_EN__SHIFT 0x1d
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF6_WR_ERR_EN__SHIFT 0x1e
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF7_WR_ERR_EN__SHIFT 0x1f
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC0_RD_ERR_EN_MASK 0x00000001L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC1_RD_ERR_EN_MASK 0x00000002L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC2_RD_ERR_EN_MASK 0x00000004L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC3_RD_ERR_EN_MASK 0x00000008L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC4_RD_ERR_EN_MASK 0x00000010L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC5_RD_ERR_EN_MASK 0x00000020L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC6_RD_ERR_EN_MASK 0x00000040L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC7_RD_ERR_EN_MASK 0x00000080L
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH0_RD_ERR_EN_MASK 0x00000100L
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH1_RD_ERR_EN_MASK 0x00000200L
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH2_RD_ERR_EN_MASK 0x00000400L
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH3_RD_ERR_EN_MASK 0x00000800L
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH4_RD_ERR_EN_MASK 0x00001000L
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH5_RD_ERR_EN_MASK 0x00002000L
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH6_RD_ERR_EN_MASK 0x00004000L
+#define JPEG_MEMCHECK_SYS_INT_EN__BSFETCH7_RD_ERR_EN_MASK 0x00008000L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC0_WR_ERR_EN_MASK 0x00010000L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC1_WR_ERR_EN_MASK 0x00020000L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC2_WR_ERR_EN_MASK 0x00040000L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC3_WR_ERR_EN_MASK 0x00080000L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC4_WR_ERR_EN_MASK 0x00100000L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC5_WR_ERR_EN_MASK 0x00200000L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC6_WR_ERR_EN_MASK 0x00400000L
+#define JPEG_MEMCHECK_SYS_INT_EN__DJRBC7_WR_ERR_EN_MASK 0x00800000L
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF0_WR_ERR_EN_MASK 0x01000000L
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF1_WR_ERR_EN_MASK 0x02000000L
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF2_WR_ERR_EN_MASK 0x04000000L
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF3_WR_ERR_EN_MASK 0x08000000L
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF4_WR_ERR_EN_MASK 0x10000000L
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF5_WR_ERR_EN_MASK 0x20000000L
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF6_WR_ERR_EN_MASK 0x40000000L
+#define JPEG_MEMCHECK_SYS_INT_EN__OBUF7_WR_ERR_EN_MASK 0x80000000L
+//JPEG_MEMCHECK_SYS_INT_EN1
+#define JPEG_MEMCHECK_SYS_INT_EN1__EJRBC_RD_ERR_EN__SHIFT 0x0
+#define JPEG_MEMCHECK_SYS_INT_EN1__PELFETCH_RD_ERR_EN__SHIFT 0x1
+#define JPEG_MEMCHECK_SYS_INT_EN1__SCALAR_RD_ERR_EN__SHIFT 0x2
+#define JPEG_MEMCHECK_SYS_INT_EN1__EJRBC_WR_ERR_EN__SHIFT 0x3
+#define JPEG_MEMCHECK_SYS_INT_EN1__BS_WR_ERR_EN__SHIFT 0x4
+#define JPEG_MEMCHECK_SYS_INT_EN1__SCALAR_WR_ERR_EN__SHIFT 0x5
+#define JPEG_MEMCHECK_SYS_INT_EN1__EJRBC_RD_ERR_EN_MASK 0x00000001L
+#define JPEG_MEMCHECK_SYS_INT_EN1__PELFETCH_RD_ERR_EN_MASK 0x00000002L
+#define JPEG_MEMCHECK_SYS_INT_EN1__SCALAR_RD_ERR_EN_MASK 0x00000004L
+#define JPEG_MEMCHECK_SYS_INT_EN1__EJRBC_WR_ERR_EN_MASK 0x00000008L
+#define JPEG_MEMCHECK_SYS_INT_EN1__BS_WR_ERR_EN_MASK 0x00000010L
+#define JPEG_MEMCHECK_SYS_INT_EN1__SCALAR_WR_ERR_EN_MASK 0x00000020L
+//JPEG_MEMCHECK_SYS_INT_STAT
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH0_RD_HI_ERR__SHIFT 0x0
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH1_RD_HI_ERR__SHIFT 0x1
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH2_RD_HI_ERR__SHIFT 0x2
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH3_RD_HI_ERR__SHIFT 0x3
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH4_RD_HI_ERR__SHIFT 0x4
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH5_RD_HI_ERR__SHIFT 0x5
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH6_RD_HI_ERR__SHIFT 0x6
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH7_RD_HI_ERR__SHIFT 0x7
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH0_RD_LO_ERR__SHIFT 0x8
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH1_RD_LO_ERR__SHIFT 0x9
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH2_RD_LO_ERR__SHIFT 0xa
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH3_RD_LO_ERR__SHIFT 0xb
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH4_RD_LO_ERR__SHIFT 0xc
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH5_RD_LO_ERR__SHIFT 0xd
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH6_RD_LO_ERR__SHIFT 0xe
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH7_RD_LO_ERR__SHIFT 0xf
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF0_WR_HI_ERR__SHIFT 0x10
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF1_WR_HI_ERR__SHIFT 0x11
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF2_WR_HI_ERR__SHIFT 0x12
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF3_WR_HI_ERR__SHIFT 0x13
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF4_WR_HI_ERR__SHIFT 0x14
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF5_WR_HI_ERR__SHIFT 0x15
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF6_WR_HI_ERR__SHIFT 0x16
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF7_WR_HI_ERR__SHIFT 0x17
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF0_WR_LO_ERR__SHIFT 0x18
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF1_WR_LO_ERR__SHIFT 0x19
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF2_WR_LO_ERR__SHIFT 0x1a
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF3_WR_LO_ERR__SHIFT 0x1b
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF4_WR_LO_ERR__SHIFT 0x1c
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF5_WR_LO_ERR__SHIFT 0x1d
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF6_WR_LO_ERR__SHIFT 0x1e
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF7_WR_LO_ERR__SHIFT 0x1f
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH0_RD_HI_ERR_MASK 0x00000001L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH1_RD_HI_ERR_MASK 0x00000002L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH2_RD_HI_ERR_MASK 0x00000004L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH3_RD_HI_ERR_MASK 0x00000008L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH4_RD_HI_ERR_MASK 0x00000010L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH5_RD_HI_ERR_MASK 0x00000020L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH6_RD_HI_ERR_MASK 0x00000040L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH7_RD_HI_ERR_MASK 0x00000080L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH0_RD_LO_ERR_MASK 0x00000100L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH1_RD_LO_ERR_MASK 0x00000200L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH2_RD_LO_ERR_MASK 0x00000400L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH3_RD_LO_ERR_MASK 0x00000800L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH4_RD_LO_ERR_MASK 0x00001000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH5_RD_LO_ERR_MASK 0x00002000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH6_RD_LO_ERR_MASK 0x00004000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__BSFETCH7_RD_LO_ERR_MASK 0x00008000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF0_WR_HI_ERR_MASK 0x00010000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF1_WR_HI_ERR_MASK 0x00020000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF2_WR_HI_ERR_MASK 0x00040000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF3_WR_HI_ERR_MASK 0x00080000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF4_WR_HI_ERR_MASK 0x00100000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF5_WR_HI_ERR_MASK 0x00200000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF6_WR_HI_ERR_MASK 0x00400000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF7_WR_HI_ERR_MASK 0x00800000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF0_WR_LO_ERR_MASK 0x01000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF1_WR_LO_ERR_MASK 0x02000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF2_WR_LO_ERR_MASK 0x04000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF3_WR_LO_ERR_MASK 0x08000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF4_WR_LO_ERR_MASK 0x10000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF5_WR_LO_ERR_MASK 0x20000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF6_WR_LO_ERR_MASK 0x40000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT__OBUF7_WR_LO_ERR_MASK 0x80000000L
+//JPEG_MEMCHECK_SYS_INT_STAT1
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC0_RD_HI_ERR__SHIFT 0x0
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC1_RD_HI_ERR__SHIFT 0x1
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC2_RD_HI_ERR__SHIFT 0x2
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC3_RD_HI_ERR__SHIFT 0x3
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC4_RD_HI_ERR__SHIFT 0x4
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC5_RD_HI_ERR__SHIFT 0x5
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC6_RD_HI_ERR__SHIFT 0x6
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC7_RD_HI_ERR__SHIFT 0x7
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC0_RD_LO_ERR__SHIFT 0x8
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC1_RD_LO_ERR__SHIFT 0x9
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC2_RD_LO_ERR__SHIFT 0xa
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC3_RD_LO_ERR__SHIFT 0xb
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC4_RD_LO_ERR__SHIFT 0xc
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC5_RD_LO_ERR__SHIFT 0xd
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC6_RD_LO_ERR__SHIFT 0xe
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC7_RD_LO_ERR__SHIFT 0xf
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC0_WR_HI_ERR__SHIFT 0x10
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC1_WR_HI_ERR__SHIFT 0x11
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC2_WR_HI_ERR__SHIFT 0x12
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC3_WR_HI_ERR__SHIFT 0x13
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC4_WR_HI_ERR__SHIFT 0x14
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC5_WR_HI_ERR__SHIFT 0x15
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC6_WR_HI_ERR__SHIFT 0x16
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC7_WR_HI_ERR__SHIFT 0x17
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC0_WR_LO_ERR__SHIFT 0x18
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC1_WR_LO_ERR__SHIFT 0x19
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC2_WR_LO_ERR__SHIFT 0x1a
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC3_WR_LO_ERR__SHIFT 0x1b
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC4_WR_LO_ERR__SHIFT 0x1c
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC5_WR_LO_ERR__SHIFT 0x1d
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC6_WR_LO_ERR__SHIFT 0x1e
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC7_WR_LO_ERR__SHIFT 0x1f
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC0_RD_HI_ERR_MASK 0x00000001L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC1_RD_HI_ERR_MASK 0x00000002L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC2_RD_HI_ERR_MASK 0x00000004L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC3_RD_HI_ERR_MASK 0x00000008L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC4_RD_HI_ERR_MASK 0x00000010L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC5_RD_HI_ERR_MASK 0x00000020L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC6_RD_HI_ERR_MASK 0x00000040L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC7_RD_HI_ERR_MASK 0x00000080L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC0_RD_LO_ERR_MASK 0x00000100L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC1_RD_LO_ERR_MASK 0x00000200L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC2_RD_LO_ERR_MASK 0x00000400L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC3_RD_LO_ERR_MASK 0x00000800L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC4_RD_LO_ERR_MASK 0x00001000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC5_RD_LO_ERR_MASK 0x00002000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC6_RD_LO_ERR_MASK 0x00004000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC7_RD_LO_ERR_MASK 0x00008000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC0_WR_HI_ERR_MASK 0x00010000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC1_WR_HI_ERR_MASK 0x00020000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC2_WR_HI_ERR_MASK 0x00040000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC3_WR_HI_ERR_MASK 0x00080000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC4_WR_HI_ERR_MASK 0x00100000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC5_WR_HI_ERR_MASK 0x00200000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC6_WR_HI_ERR_MASK 0x00400000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC7_WR_HI_ERR_MASK 0x00800000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC0_WR_LO_ERR_MASK 0x01000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC1_WR_LO_ERR_MASK 0x02000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC2_WR_LO_ERR_MASK 0x04000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC3_WR_LO_ERR_MASK 0x08000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC4_WR_LO_ERR_MASK 0x10000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC5_WR_LO_ERR_MASK 0x20000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC6_WR_LO_ERR_MASK 0x40000000L
+#define JPEG_MEMCHECK_SYS_INT_STAT1__DJRBC7_WR_LO_ERR_MASK 0x80000000L
+//JPEG_MEMCHECK_SYS_INT_STAT2
+#define JPEG_MEMCHECK_SYS_INT_STAT2__EJRBC_RD_HI_ERR__SHIFT 0x0
+#define JPEG_MEMCHECK_SYS_INT_STAT2__EJRBC_RD_LO_ERR__SHIFT 0x1
+#define JPEG_MEMCHECK_SYS_INT_STAT2__PELFETCH_RD_HI_ERR__SHIFT 0x2
+#define JPEG_MEMCHECK_SYS_INT_STAT2__PELFETCH_RD_LO_ERR__SHIFT 0x3
+#define JPEG_MEMCHECK_SYS_INT_STAT2__SCALAR_RD_HI_ERR__SHIFT 0x4
+#define JPEG_MEMCHECK_SYS_INT_STAT2__SCALAR_RD_LO_ERR__SHIFT 0x5
+#define JPEG_MEMCHECK_SYS_INT_STAT2__EJRBC_WR_HI_ERR__SHIFT 0x6
+#define JPEG_MEMCHECK_SYS_INT_STAT2__EJRBC_WR_LO_ERR__SHIFT 0x7
+#define JPEG_MEMCHECK_SYS_INT_STAT2__BS_WR_HI_ERR__SHIFT 0x8
+#define JPEG_MEMCHECK_SYS_INT_STAT2__BS_WR_LO_ERR__SHIFT 0x9
+#define JPEG_MEMCHECK_SYS_INT_STAT2__SCALAR_WR_HI_ERR__SHIFT 0xa
+#define JPEG_MEMCHECK_SYS_INT_STAT2__SCALAR_WR_LO_ERR__SHIFT 0xb
+#define JPEG_MEMCHECK_SYS_INT_STAT2__EJRBC_RD_HI_ERR_MASK 0x00000001L
+#define JPEG_MEMCHECK_SYS_INT_STAT2__EJRBC_RD_LO_ERR_MASK 0x00000002L
+#define JPEG_MEMCHECK_SYS_INT_STAT2__PELFETCH_RD_HI_ERR_MASK 0x00000004L
+#define JPEG_MEMCHECK_SYS_INT_STAT2__PELFETCH_RD_LO_ERR_MASK 0x00000008L
+#define JPEG_MEMCHECK_SYS_INT_STAT2__SCALAR_RD_HI_ERR_MASK 0x00000010L
+#define JPEG_MEMCHECK_SYS_INT_STAT2__SCALAR_RD_LO_ERR_MASK 0x00000020L
+#define JPEG_MEMCHECK_SYS_INT_STAT2__EJRBC_WR_HI_ERR_MASK 0x00000040L
+#define JPEG_MEMCHECK_SYS_INT_STAT2__EJRBC_WR_LO_ERR_MASK 0x00000080L
+#define JPEG_MEMCHECK_SYS_INT_STAT2__BS_WR_HI_ERR_MASK 0x00000100L
+#define JPEG_MEMCHECK_SYS_INT_STAT2__BS_WR_LO_ERR_MASK 0x00000200L
+#define JPEG_MEMCHECK_SYS_INT_STAT2__SCALAR_WR_HI_ERR_MASK 0x00000400L
+#define JPEG_MEMCHECK_SYS_INT_STAT2__SCALAR_WR_LO_ERR_MASK 0x00000800L
+//JPEG_MEMCHECK_SYS_INT_ACK
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH0_RD_HI_ERR__SHIFT 0x0
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH1_RD_HI_ERR__SHIFT 0x1
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH2_RD_HI_ERR__SHIFT 0x2
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH3_RD_HI_ERR__SHIFT 0x3
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH4_RD_HI_ERR__SHIFT 0x4
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH5_RD_HI_ERR__SHIFT 0x5
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH6_RD_HI_ERR__SHIFT 0x6
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH7_RD_HI_ERR__SHIFT 0x7
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH0_RD_LO_ERR__SHIFT 0x8
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH1_RD_LO_ERR__SHIFT 0x9
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH2_RD_LO_ERR__SHIFT 0xa
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH3_RD_LO_ERR__SHIFT 0xb
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH4_RD_LO_ERR__SHIFT 0xc
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH5_RD_LO_ERR__SHIFT 0xd
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH6_RD_LO_ERR__SHIFT 0xe
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH7_RD_LO_ERR__SHIFT 0xf
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF0_WR_HI_ERR__SHIFT 0x10
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF1_WR_HI_ERR__SHIFT 0x11
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF2_WR_HI_ERR__SHIFT 0x12
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF3_WR_HI_ERR__SHIFT 0x13
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF4_WR_HI_ERR__SHIFT 0x14
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF5_WR_HI_ERR__SHIFT 0x15
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF6_WR_HI_ERR__SHIFT 0x16
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF7_WR_HI_ERR__SHIFT 0x17
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF0_WR_LO_ERR__SHIFT 0x18
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF1_WR_LO_ERR__SHIFT 0x19
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF2_WR_LO_ERR__SHIFT 0x1a
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF3_WR_LO_ERR__SHIFT 0x1b
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF4_WR_LO_ERR__SHIFT 0x1c
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF5_WR_LO_ERR__SHIFT 0x1d
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF6_WR_LO_ERR__SHIFT 0x1e
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF7_WR_LO_ERR__SHIFT 0x1f
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH0_RD_HI_ERR_MASK 0x00000001L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH1_RD_HI_ERR_MASK 0x00000002L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH2_RD_HI_ERR_MASK 0x00000004L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH3_RD_HI_ERR_MASK 0x00000008L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH4_RD_HI_ERR_MASK 0x00000010L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH5_RD_HI_ERR_MASK 0x00000020L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH6_RD_HI_ERR_MASK 0x00000040L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH7_RD_HI_ERR_MASK 0x00000080L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH0_RD_LO_ERR_MASK 0x00000100L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH1_RD_LO_ERR_MASK 0x00000200L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH2_RD_LO_ERR_MASK 0x00000400L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH3_RD_LO_ERR_MASK 0x00000800L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH4_RD_LO_ERR_MASK 0x00001000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH5_RD_LO_ERR_MASK 0x00002000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH6_RD_LO_ERR_MASK 0x00004000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__BSFETCH7_RD_LO_ERR_MASK 0x00008000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF0_WR_HI_ERR_MASK 0x00010000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF1_WR_HI_ERR_MASK 0x00020000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF2_WR_HI_ERR_MASK 0x00040000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF3_WR_HI_ERR_MASK 0x00080000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF4_WR_HI_ERR_MASK 0x00100000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF5_WR_HI_ERR_MASK 0x00200000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF6_WR_HI_ERR_MASK 0x00400000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF7_WR_HI_ERR_MASK 0x00800000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF0_WR_LO_ERR_MASK 0x01000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF1_WR_LO_ERR_MASK 0x02000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF2_WR_LO_ERR_MASK 0x04000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF3_WR_LO_ERR_MASK 0x08000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF4_WR_LO_ERR_MASK 0x10000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF5_WR_LO_ERR_MASK 0x20000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF6_WR_LO_ERR_MASK 0x40000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK__OBUF7_WR_LO_ERR_MASK 0x80000000L
+//JPEG_MEMCHECK_SYS_INT_ACK1
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC0_RD_HI_ERR__SHIFT 0x0
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC1_RD_HI_ERR__SHIFT 0x1
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC2_RD_HI_ERR__SHIFT 0x2
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC3_RD_HI_ERR__SHIFT 0x3
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC4_RD_HI_ERR__SHIFT 0x4
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC5_RD_HI_ERR__SHIFT 0x5
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC6_RD_HI_ERR__SHIFT 0x6
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC7_RD_HI_ERR__SHIFT 0x7
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC0_RD_LO_ERR__SHIFT 0x8
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC1_RD_LO_ERR__SHIFT 0x9
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC2_RD_LO_ERR__SHIFT 0xa
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC3_RD_LO_ERR__SHIFT 0xb
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC4_RD_LO_ERR__SHIFT 0xc
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC5_RD_LO_ERR__SHIFT 0xd
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC6_RD_LO_ERR__SHIFT 0xe
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC7_RD_LO_ERR__SHIFT 0xf
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC0_WR_HI_ERR__SHIFT 0x10
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC1_WR_HI_ERR__SHIFT 0x11
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC2_WR_HI_ERR__SHIFT 0x12
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC3_WR_HI_ERR__SHIFT 0x13
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC4_WR_HI_ERR__SHIFT 0x14
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC5_WR_HI_ERR__SHIFT 0x15
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC6_WR_HI_ERR__SHIFT 0x16
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC7_WR_HI_ERR__SHIFT 0x17
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC0_WR_LO_ERR__SHIFT 0x18
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC1_WR_LO_ERR__SHIFT 0x19
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC2_WR_LO_ERR__SHIFT 0x1a
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC3_WR_LO_ERR__SHIFT 0x1b
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC4_WR_LO_ERR__SHIFT 0x1c
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC5_WR_LO_ERR__SHIFT 0x1d
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC6_WR_LO_ERR__SHIFT 0x1e
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC7_WR_LO_ERR__SHIFT 0x1f
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC0_RD_HI_ERR_MASK 0x00000001L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC1_RD_HI_ERR_MASK 0x00000002L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC2_RD_HI_ERR_MASK 0x00000004L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC3_RD_HI_ERR_MASK 0x00000008L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC4_RD_HI_ERR_MASK 0x00000010L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC5_RD_HI_ERR_MASK 0x00000020L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC6_RD_HI_ERR_MASK 0x00000040L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC7_RD_HI_ERR_MASK 0x00000080L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC0_RD_LO_ERR_MASK 0x00000100L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC1_RD_LO_ERR_MASK 0x00000200L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC2_RD_LO_ERR_MASK 0x00000400L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC3_RD_LO_ERR_MASK 0x00000800L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC4_RD_LO_ERR_MASK 0x00001000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC5_RD_LO_ERR_MASK 0x00002000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC6_RD_LO_ERR_MASK 0x00004000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC7_RD_LO_ERR_MASK 0x00008000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC0_WR_HI_ERR_MASK 0x00010000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC1_WR_HI_ERR_MASK 0x00020000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC2_WR_HI_ERR_MASK 0x00040000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC3_WR_HI_ERR_MASK 0x00080000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC4_WR_HI_ERR_MASK 0x00100000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC5_WR_HI_ERR_MASK 0x00200000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC6_WR_HI_ERR_MASK 0x00400000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC7_WR_HI_ERR_MASK 0x00800000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC0_WR_LO_ERR_MASK 0x01000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC1_WR_LO_ERR_MASK 0x02000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC2_WR_LO_ERR_MASK 0x04000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC3_WR_LO_ERR_MASK 0x08000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC4_WR_LO_ERR_MASK 0x10000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC5_WR_LO_ERR_MASK 0x20000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC6_WR_LO_ERR_MASK 0x40000000L
+#define JPEG_MEMCHECK_SYS_INT_ACK1__DJRBC7_WR_LO_ERR_MASK 0x80000000L
+//JPEG_MEMCHECK_SYS_INT_ACK2
+#define JPEG_MEMCHECK_SYS_INT_ACK2__EJRBC_RD_HI_ERR__SHIFT 0x0
+#define JPEG_MEMCHECK_SYS_INT_ACK2__EJRBC_RD_LO_ERR__SHIFT 0x1
+#define JPEG_MEMCHECK_SYS_INT_ACK2__PELFETCH_RD_HI_ERR__SHIFT 0x2
+#define JPEG_MEMCHECK_SYS_INT_ACK2__PELFETCH_RD_LO_ERR__SHIFT 0x3
+#define JPEG_MEMCHECK_SYS_INT_ACK2__SCALAR_RD_HI_ERR__SHIFT 0x4
+#define JPEG_MEMCHECK_SYS_INT_ACK2__SCALAR_RD_LO_ERR__SHIFT 0x5
+#define JPEG_MEMCHECK_SYS_INT_ACK2__EJRBC_WR_HI_ERR__SHIFT 0x6
+#define JPEG_MEMCHECK_SYS_INT_ACK2__EJRBC_WR_LO_ERR__SHIFT 0x7
+#define JPEG_MEMCHECK_SYS_INT_ACK2__BS_WR_HI_ERR__SHIFT 0x8
+#define JPEG_MEMCHECK_SYS_INT_ACK2__BS_WR_LO_ERR__SHIFT 0x9
+#define JPEG_MEMCHECK_SYS_INT_ACK2__SCALAR_WR_HI_ERR__SHIFT 0xa
+#define JPEG_MEMCHECK_SYS_INT_ACK2__SCALAR_WR_LO_ERR__SHIFT 0xb
+#define JPEG_MEMCHECK_SYS_INT_ACK2__EJRBC_RD_HI_ERR_MASK 0x00000001L
+#define JPEG_MEMCHECK_SYS_INT_ACK2__EJRBC_RD_LO_ERR_MASK 0x00000002L
+#define JPEG_MEMCHECK_SYS_INT_ACK2__PELFETCH_RD_HI_ERR_MASK 0x00000004L
+#define JPEG_MEMCHECK_SYS_INT_ACK2__PELFETCH_RD_LO_ERR_MASK 0x00000008L
+#define JPEG_MEMCHECK_SYS_INT_ACK2__SCALAR_RD_HI_ERR_MASK 0x00000010L
+#define JPEG_MEMCHECK_SYS_INT_ACK2__SCALAR_RD_LO_ERR_MASK 0x00000020L
+#define JPEG_MEMCHECK_SYS_INT_ACK2__EJRBC_WR_HI_ERR_MASK 0x00000040L
+#define JPEG_MEMCHECK_SYS_INT_ACK2__EJRBC_WR_LO_ERR_MASK 0x00000080L
+#define JPEG_MEMCHECK_SYS_INT_ACK2__BS_WR_HI_ERR_MASK 0x00000100L
+#define JPEG_MEMCHECK_SYS_INT_ACK2__BS_WR_LO_ERR_MASK 0x00000200L
+#define JPEG_MEMCHECK_SYS_INT_ACK2__SCALAR_WR_HI_ERR_MASK 0x00000400L
+#define JPEG_MEMCHECK_SYS_INT_ACK2__SCALAR_WR_LO_ERR_MASK 0x00000800L
+//JPEG_MASTINT_EN
+#define JPEG_MASTINT_EN__OVERRUN_RST__SHIFT 0x0
+#define JPEG_MASTINT_EN__INT_OVERRUN__SHIFT 0x4
+#define JPEG_MASTINT_EN__OVERRUN_RST_MASK 0x00000001L
+#define JPEG_MASTINT_EN__INT_OVERRUN_MASK 0x007FFFF0L
+//JPEG_IH_CTRL
+#define JPEG_IH_CTRL__IH_SOFT_RESET__SHIFT 0x0
+#define JPEG_IH_CTRL__IH_STALL_EN__SHIFT 0x1
+#define JPEG_IH_CTRL__IH_STATUS_CLEAN__SHIFT 0x2
+#define JPEG_IH_CTRL__IH_VMID__SHIFT 0x3
+#define JPEG_IH_CTRL__IH_USER_DATA__SHIFT 0x7
+#define JPEG_IH_CTRL__IH_RINGID__SHIFT 0x13
+#define JPEG_IH_CTRL__IH_SOFT_RESET_MASK 0x00000001L
+#define JPEG_IH_CTRL__IH_STALL_EN_MASK 0x00000002L
+#define JPEG_IH_CTRL__IH_STATUS_CLEAN_MASK 0x00000004L
+#define JPEG_IH_CTRL__IH_VMID_MASK 0x00000078L
+#define JPEG_IH_CTRL__IH_USER_DATA_MASK 0x0007FF80L
+#define JPEG_IH_CTRL__IH_RINGID_MASK 0x07F80000L
+//JRBBM_ARB_CTRL
+#define JRBBM_ARB_CTRL__DJRBC0_DROP__SHIFT 0x0
+#define JRBBM_ARB_CTRL__DJRBC1_DROP__SHIFT 0x1
+#define JRBBM_ARB_CTRL__DJRBC2_DROP__SHIFT 0x2
+#define JRBBM_ARB_CTRL__DJRBC3_DROP__SHIFT 0x3
+#define JRBBM_ARB_CTRL__DJRBC4_DROP__SHIFT 0x4
+#define JRBBM_ARB_CTRL__DJRBC5_DROP__SHIFT 0x5
+#define JRBBM_ARB_CTRL__DJRBC6_DROP__SHIFT 0x6
+#define JRBBM_ARB_CTRL__DJRBC7_DROP__SHIFT 0x7
+#define JRBBM_ARB_CTRL__EJRBC_DROP__SHIFT 0x8
+#define JRBBM_ARB_CTRL__SRBM_DROP__SHIFT 0x9
+#define JRBBM_ARB_CTRL__DJRBC0_DROP_MASK 0x00000001L
+#define JRBBM_ARB_CTRL__DJRBC1_DROP_MASK 0x00000002L
+#define JRBBM_ARB_CTRL__DJRBC2_DROP_MASK 0x00000004L
+#define JRBBM_ARB_CTRL__DJRBC3_DROP_MASK 0x00000008L
+#define JRBBM_ARB_CTRL__DJRBC4_DROP_MASK 0x00000010L
+#define JRBBM_ARB_CTRL__DJRBC5_DROP_MASK 0x00000020L
+#define JRBBM_ARB_CTRL__DJRBC6_DROP_MASK 0x00000040L
+#define JRBBM_ARB_CTRL__DJRBC7_DROP_MASK 0x00000080L
+#define JRBBM_ARB_CTRL__EJRBC_DROP_MASK 0x00000100L
+#define JRBBM_ARB_CTRL__SRBM_DROP_MASK 0x00000200L
+
+
+// addressBlock: aid_uvd0_uvd_jpeg_common_sclk_dec
+//JPEG_CGC_GATE
+#define JPEG_CGC_GATE__JPEG0_DEC__SHIFT 0x0
+#define JPEG_CGC_GATE__JPEG1_DEC__SHIFT 0x1
+#define JPEG_CGC_GATE__JPEG2_DEC__SHIFT 0x2
+#define JPEG_CGC_GATE__JPEG3_DEC__SHIFT 0x3
+#define JPEG_CGC_GATE__JPEG4_DEC__SHIFT 0x4
+#define JPEG_CGC_GATE__JPEG5_DEC__SHIFT 0x5
+#define JPEG_CGC_GATE__JPEG6_DEC__SHIFT 0x6
+#define JPEG_CGC_GATE__JPEG7_DEC__SHIFT 0x7
+#define JPEG_CGC_GATE__JPEG_ENC__SHIFT 0x8
+#define JPEG_CGC_GATE__JMCIF__SHIFT 0x9
+#define JPEG_CGC_GATE__JRBBM__SHIFT 0xa
+#define JPEG_CGC_GATE__JPEG0_DEC_MASK 0x00000001L
+#define JPEG_CGC_GATE__JPEG1_DEC_MASK 0x00000002L
+#define JPEG_CGC_GATE__JPEG2_DEC_MASK 0x00000004L
+#define JPEG_CGC_GATE__JPEG3_DEC_MASK 0x00000008L
+#define JPEG_CGC_GATE__JPEG4_DEC_MASK 0x00000010L
+#define JPEG_CGC_GATE__JPEG5_DEC_MASK 0x00000020L
+#define JPEG_CGC_GATE__JPEG6_DEC_MASK 0x00000040L
+#define JPEG_CGC_GATE__JPEG7_DEC_MASK 0x00000080L
+#define JPEG_CGC_GATE__JPEG_ENC_MASK 0x00000100L
+#define JPEG_CGC_GATE__JMCIF_MASK 0x00000200L
+#define JPEG_CGC_GATE__JRBBM_MASK 0x00000400L
+//JPEG_CGC_CTRL
+#define JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT 0x0
+#define JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT 0x1
+#define JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT 0x5
+#define JPEG_CGC_CTRL__JPEG0_DEC_MODE__SHIFT 0x10
+#define JPEG_CGC_CTRL__JPEG1_DEC_MODE__SHIFT 0x11
+#define JPEG_CGC_CTRL__JPEG2_DEC_MODE__SHIFT 0x12
+#define JPEG_CGC_CTRL__JPEG3_DEC_MODE__SHIFT 0x13
+#define JPEG_CGC_CTRL__JPEG4_DEC_MODE__SHIFT 0x14
+#define JPEG_CGC_CTRL__JPEG5_DEC_MODE__SHIFT 0x15
+#define JPEG_CGC_CTRL__JPEG6_DEC_MODE__SHIFT 0x16
+#define JPEG_CGC_CTRL__JPEG7_DEC_MODE__SHIFT 0x17
+#define JPEG_CGC_CTRL__JPEG_ENC_MODE__SHIFT 0x18
+#define JPEG_CGC_CTRL__JMCIF_MODE__SHIFT 0x19
+#define JPEG_CGC_CTRL__JRBBM_MODE__SHIFT 0x1a
+#define JPEG_CGC_CTRL__DYN_CLOCK_MODE_MASK 0x00000001L
+#define JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK 0x0000001EL
+#define JPEG_CGC_CTRL__CLK_OFF_DELAY_MASK 0x00001FE0L
+#define JPEG_CGC_CTRL__JPEG0_DEC_MODE_MASK 0x00010000L
+#define JPEG_CGC_CTRL__JPEG1_DEC_MODE_MASK 0x00020000L
+#define JPEG_CGC_CTRL__JPEG2_DEC_MODE_MASK 0x00040000L
+#define JPEG_CGC_CTRL__JPEG3_DEC_MODE_MASK 0x00080000L
+#define JPEG_CGC_CTRL__JPEG4_DEC_MODE_MASK 0x00100000L
+#define JPEG_CGC_CTRL__JPEG5_DEC_MODE_MASK 0x00200000L
+#define JPEG_CGC_CTRL__JPEG6_DEC_MODE_MASK 0x00400000L
+#define JPEG_CGC_CTRL__JPEG7_DEC_MODE_MASK 0x00800000L
+#define JPEG_CGC_CTRL__JPEG_ENC_MODE_MASK 0x01000000L
+#define JPEG_CGC_CTRL__JMCIF_MODE_MASK 0x02000000L
+#define JPEG_CGC_CTRL__JRBBM_MODE_MASK 0x04000000L
+//JPEG_CGC_STATUS
+#define JPEG_CGC_STATUS__JPEG0_DEC_VCLK_ACTIVE__SHIFT 0x0
+#define JPEG_CGC_STATUS__JPEG0_DEC_SCLK_ACTIVE__SHIFT 0x1
+#define JPEG_CGC_STATUS__JPEG1_DEC_VCLK_ACTIVE__SHIFT 0x2
+#define JPEG_CGC_STATUS__JPEG1_DEC_SCLK_ACTIVE__SHIFT 0x3
+#define JPEG_CGC_STATUS__JPEG2_DEC_VCLK_ACTIVE__SHIFT 0x4
+#define JPEG_CGC_STATUS__JPEG2_DEC_SCLK_ACTIVE__SHIFT 0x5
+#define JPEG_CGC_STATUS__JPEG3_DEC_VCLK_ACTIVE__SHIFT 0x6
+#define JPEG_CGC_STATUS__JPEG3_DEC_SCLK_ACTIVE__SHIFT 0x7
+#define JPEG_CGC_STATUS__JPEG4_DEC_VCLK_ACTIVE__SHIFT 0x8
+#define JPEG_CGC_STATUS__JPEG4_DEC_SCLK_ACTIVE__SHIFT 0x9
+#define JPEG_CGC_STATUS__JPEG5_DEC_VCLK_ACTIVE__SHIFT 0xa
+#define JPEG_CGC_STATUS__JPEG5_DEC_SCLK_ACTIVE__SHIFT 0xb
+#define JPEG_CGC_STATUS__JPEG6_DEC_VCLK_ACTIVE__SHIFT 0xc
+#define JPEG_CGC_STATUS__JPEG6_DEC_SCLK_ACTIVE__SHIFT 0xd
+#define JPEG_CGC_STATUS__JPEG7_DEC_VCLK_ACTIVE__SHIFT 0xe
+#define JPEG_CGC_STATUS__JPEG7_DEC_SCLK_ACTIVE__SHIFT 0xf
+#define JPEG_CGC_STATUS__JPEG_ENC_VCLK_ACTIVE__SHIFT 0x10
+#define JPEG_CGC_STATUS__JPEG_ENC_SCLK_ACTIVE__SHIFT 0x11
+#define JPEG_CGC_STATUS__JMCIF_SCLK_ACTIVE__SHIFT 0x12
+#define JPEG_CGC_STATUS__JRBBM_VCLK_ACTIVE__SHIFT 0x13
+#define JPEG_CGC_STATUS__JRBBM_SCLK_ACTIVE__SHIFT 0x14
+#define JPEG_CGC_STATUS__JPEG0_DEC_VCLK_ACTIVE_MASK 0x00000001L
+#define JPEG_CGC_STATUS__JPEG0_DEC_SCLK_ACTIVE_MASK 0x00000002L
+#define JPEG_CGC_STATUS__JPEG1_DEC_VCLK_ACTIVE_MASK 0x00000004L
+#define JPEG_CGC_STATUS__JPEG1_DEC_SCLK_ACTIVE_MASK 0x00000008L
+#define JPEG_CGC_STATUS__JPEG2_DEC_VCLK_ACTIVE_MASK 0x00000010L
+#define JPEG_CGC_STATUS__JPEG2_DEC_SCLK_ACTIVE_MASK 0x00000020L
+#define JPEG_CGC_STATUS__JPEG3_DEC_VCLK_ACTIVE_MASK 0x00000040L
+#define JPEG_CGC_STATUS__JPEG3_DEC_SCLK_ACTIVE_MASK 0x00000080L
+#define JPEG_CGC_STATUS__JPEG4_DEC_VCLK_ACTIVE_MASK 0x00000100L
+#define JPEG_CGC_STATUS__JPEG4_DEC_SCLK_ACTIVE_MASK 0x00000200L
+#define JPEG_CGC_STATUS__JPEG5_DEC_VCLK_ACTIVE_MASK 0x00000400L
+#define JPEG_CGC_STATUS__JPEG5_DEC_SCLK_ACTIVE_MASK 0x00000800L
+#define JPEG_CGC_STATUS__JPEG6_DEC_VCLK_ACTIVE_MASK 0x00001000L
+#define JPEG_CGC_STATUS__JPEG6_DEC_SCLK_ACTIVE_MASK 0x00002000L
+#define JPEG_CGC_STATUS__JPEG7_DEC_VCLK_ACTIVE_MASK 0x00004000L
+#define JPEG_CGC_STATUS__JPEG7_DEC_SCLK_ACTIVE_MASK 0x00008000L
+#define JPEG_CGC_STATUS__JPEG_ENC_VCLK_ACTIVE_MASK 0x00010000L
+#define JPEG_CGC_STATUS__JPEG_ENC_SCLK_ACTIVE_MASK 0x00020000L
+#define JPEG_CGC_STATUS__JMCIF_SCLK_ACTIVE_MASK 0x00040000L
+#define JPEG_CGC_STATUS__JRBBM_VCLK_ACTIVE_MASK 0x00080000L
+#define JPEG_CGC_STATUS__JRBBM_SCLK_ACTIVE_MASK 0x00100000L
+//JPEG_COMN_CGC_MEM_CTRL
+#define JPEG_COMN_CGC_MEM_CTRL__JMCIF_LS_EN__SHIFT 0x0
+#define JPEG_COMN_CGC_MEM_CTRL__JMCIF_DS_EN__SHIFT 0x1
+#define JPEG_COMN_CGC_MEM_CTRL__JMCIF_SD_EN__SHIFT 0x2
+#define JPEG_COMN_CGC_MEM_CTRL__JMCIF_LS_SW_EN__SHIFT 0x3
+#define JPEG_COMN_CGC_MEM_CTRL__JMCIF_LS_EN_MASK 0x00000001L
+#define JPEG_COMN_CGC_MEM_CTRL__JMCIF_DS_EN_MASK 0x00000002L
+#define JPEG_COMN_CGC_MEM_CTRL__JMCIF_SD_EN_MASK 0x00000004L
+#define JPEG_COMN_CGC_MEM_CTRL__JMCIF_LS_SW_EN_MASK 0x00000008L
+//JPEG_DEC_CGC_MEM_CTRL
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG0_DEC_LS_EN__SHIFT 0x0
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG0_DEC_DS_EN__SHIFT 0x1
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG0_DEC_SD_EN__SHIFT 0x2
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG0_DEC_LS_SW_EN__SHIFT 0x3
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG1_DEC_LS_EN__SHIFT 0x4
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG1_DEC_DS_EN__SHIFT 0x5
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG1_DEC_SD_EN__SHIFT 0x6
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG1_DEC_LS_SW_EN__SHIFT 0x7
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG2_DEC_LS_EN__SHIFT 0x8
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG2_DEC_DS_EN__SHIFT 0x9
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG2_DEC_SD_EN__SHIFT 0xa
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG2_DEC_LS_SW_EN__SHIFT 0xb
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG3_DEC_LS_EN__SHIFT 0xc
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG3_DEC_DS_EN__SHIFT 0xd
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG3_DEC_SD_EN__SHIFT 0xe
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG3_DEC_LS_SW_EN__SHIFT 0xf
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG4_DEC_LS_EN__SHIFT 0x10
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG4_DEC_DS_EN__SHIFT 0x11
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG4_DEC_SD_EN__SHIFT 0x12
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG4_DEC_LS_SW_EN__SHIFT 0x13
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG5_DEC_LS_EN__SHIFT 0x14
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG5_DEC_DS_EN__SHIFT 0x15
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG5_DEC_SD_EN__SHIFT 0x16
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG5_DEC_LS_SW_EN__SHIFT 0x17
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG6_DEC_LS_EN__SHIFT 0x18
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG6_DEC_DS_EN__SHIFT 0x19
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG6_DEC_SD_EN__SHIFT 0x1a
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG6_DEC_LS_SW_EN__SHIFT 0x1b
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG7_DEC_LS_EN__SHIFT 0x1c
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG7_DEC_DS_EN__SHIFT 0x1d
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG7_DEC_SD_EN__SHIFT 0x1e
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG7_DEC_LS_SW_EN__SHIFT 0x1f
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG0_DEC_LS_EN_MASK 0x00000001L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG0_DEC_DS_EN_MASK 0x00000002L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG0_DEC_SD_EN_MASK 0x00000004L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG0_DEC_LS_SW_EN_MASK 0x00000008L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG1_DEC_LS_EN_MASK 0x00000010L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG1_DEC_DS_EN_MASK 0x00000020L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG1_DEC_SD_EN_MASK 0x00000040L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG1_DEC_LS_SW_EN_MASK 0x00000080L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG2_DEC_LS_EN_MASK 0x00000100L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG2_DEC_DS_EN_MASK 0x00000200L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG2_DEC_SD_EN_MASK 0x00000400L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG2_DEC_LS_SW_EN_MASK 0x00000800L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG3_DEC_LS_EN_MASK 0x00001000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG3_DEC_DS_EN_MASK 0x00002000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG3_DEC_SD_EN_MASK 0x00004000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG3_DEC_LS_SW_EN_MASK 0x00008000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG4_DEC_LS_EN_MASK 0x00010000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG4_DEC_DS_EN_MASK 0x00020000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG4_DEC_SD_EN_MASK 0x00040000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG4_DEC_LS_SW_EN_MASK 0x00080000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG5_DEC_LS_EN_MASK 0x00100000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG5_DEC_DS_EN_MASK 0x00200000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG5_DEC_SD_EN_MASK 0x00400000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG5_DEC_LS_SW_EN_MASK 0x00800000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG6_DEC_LS_EN_MASK 0x01000000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG6_DEC_DS_EN_MASK 0x02000000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG6_DEC_SD_EN_MASK 0x04000000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG6_DEC_LS_SW_EN_MASK 0x08000000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG7_DEC_LS_EN_MASK 0x10000000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG7_DEC_DS_EN_MASK 0x20000000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG7_DEC_SD_EN_MASK 0x40000000L
+#define JPEG_DEC_CGC_MEM_CTRL__JPEG7_DEC_LS_SW_EN_MASK 0x80000000L
+//JPEG_ENC_CGC_MEM_CTRL
+#define JPEG_ENC_CGC_MEM_CTRL__JPEG_ENC_LS_EN__SHIFT 0x0
+#define JPEG_ENC_CGC_MEM_CTRL__JPEG_ENC_DS_EN__SHIFT 0x1
+#define JPEG_ENC_CGC_MEM_CTRL__JPEG_ENC_SD_EN__SHIFT 0x2
+#define JPEG_ENC_CGC_MEM_CTRL__JPEG_ENC_LS_SW_EN__SHIFT 0x3
+#define JPEG_ENC_CGC_MEM_CTRL__JPEG_ENC_LS_EN_MASK 0x00000001L
+#define JPEG_ENC_CGC_MEM_CTRL__JPEG_ENC_DS_EN_MASK 0x00000002L
+#define JPEG_ENC_CGC_MEM_CTRL__JPEG_ENC_SD_EN_MASK 0x00000004L
+#define JPEG_ENC_CGC_MEM_CTRL__JPEG_ENC_LS_SW_EN_MASK 0x00000008L
+//JPEG_PERF_BANK_CONF
+#define JPEG_PERF_BANK_CONF__RESET__SHIFT 0x0
+#define JPEG_PERF_BANK_CONF__PEEK__SHIFT 0x8
+#define JPEG_PERF_BANK_CONF__CONCATENATE__SHIFT 0x10
+#define JPEG_PERF_BANK_CONF__CORE_SEL__SHIFT 0x15
+#define JPEG_PERF_BANK_CONF__RESET_MASK 0x0000000FL
+#define JPEG_PERF_BANK_CONF__PEEK_MASK 0x00000F00L
+#define JPEG_PERF_BANK_CONF__CONCATENATE_MASK 0x00030000L
+#define JPEG_PERF_BANK_CONF__CORE_SEL_MASK 0x00E00000L
+//JPEG_PERF_BANK_EVENT_SEL
+#define JPEG_PERF_BANK_EVENT_SEL__SEL0__SHIFT 0x0
+#define JPEG_PERF_BANK_EVENT_SEL__SEL1__SHIFT 0x8
+#define JPEG_PERF_BANK_EVENT_SEL__SEL2__SHIFT 0x10
+#define JPEG_PERF_BANK_EVENT_SEL__SEL3__SHIFT 0x18
+#define JPEG_PERF_BANK_EVENT_SEL__SEL0_MASK 0x000000FFL
+#define JPEG_PERF_BANK_EVENT_SEL__SEL1_MASK 0x0000FF00L
+#define JPEG_PERF_BANK_EVENT_SEL__SEL2_MASK 0x00FF0000L
+#define JPEG_PERF_BANK_EVENT_SEL__SEL3_MASK 0xFF000000L
+//JPEG_PERF_BANK_COUNT0
+#define JPEG_PERF_BANK_COUNT0__COUNT__SHIFT 0x0
+#define JPEG_PERF_BANK_COUNT0__COUNT_MASK 0xFFFFFFFFL
+//JPEG_PERF_BANK_COUNT1
+#define JPEG_PERF_BANK_COUNT1__COUNT__SHIFT 0x0
+#define JPEG_PERF_BANK_COUNT1__COUNT_MASK 0xFFFFFFFFL
+//JPEG_PERF_BANK_COUNT2
+#define JPEG_PERF_BANK_COUNT2__COUNT__SHIFT 0x0
+#define JPEG_PERF_BANK_COUNT2__COUNT_MASK 0xFFFFFFFFL
+//JPEG_PERF_BANK_COUNT3
+#define JPEG_PERF_BANK_COUNT3__COUNT__SHIFT 0x0
+#define JPEG_PERF_BANK_COUNT3__COUNT_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_uvd0_uvd_pg_dec
+//UVD_PGFSM_CONFIG
+#define UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT 0x0
+#define UVD_PGFSM_CONFIG__UVDS_PWR_CONFIG__SHIFT 0x2
+#define UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT 0x4
+#define UVD_PGFSM_CONFIG__UVDTC_PWR_CONFIG__SHIFT 0x6
+#define UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT 0x8
+#define UVD_PGFSM_CONFIG__UVDTA_PWR_CONFIG__SHIFT 0xa
+#define UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT 0xc
+#define UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT 0xe
+#define UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT 0x10
+#define UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT 0x12
+#define UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT 0x14
+#define UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT 0x16
+#define UVD_PGFSM_CONFIG__UVDTB_PWR_CONFIG__SHIFT 0x18
+#define UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT 0x1a
+#define UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT 0x1c
+#define UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG_MASK 0x00000003L
+#define UVD_PGFSM_CONFIG__UVDS_PWR_CONFIG_MASK 0x0000000CL
+#define UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG_MASK 0x00000030L
+#define UVD_PGFSM_CONFIG__UVDTC_PWR_CONFIG_MASK 0x000000C0L
+#define UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG_MASK 0x00000300L
+#define UVD_PGFSM_CONFIG__UVDTA_PWR_CONFIG_MASK 0x00000C00L
+#define UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG_MASK 0x00003000L
+#define UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG_MASK 0x0000C000L
+#define UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG_MASK 0x00030000L
+#define UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG_MASK 0x000C0000L
+#define UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG_MASK 0x00300000L
+#define UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG_MASK 0x00C00000L
+#define UVD_PGFSM_CONFIG__UVDTB_PWR_CONFIG_MASK 0x03000000L
+#define UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG_MASK 0x0C000000L
+#define UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG_MASK 0x30000000L
+//UVD_PGFSM_STATUS
+#define UVD_PGFSM_STATUS__UVDM_PWR_STATUS__SHIFT 0x0
+#define UVD_PGFSM_STATUS__UVDS_PWR_STATUS__SHIFT 0x2
+#define UVD_PGFSM_STATUS__UVDF_PWR_STATUS__SHIFT 0x4
+#define UVD_PGFSM_STATUS__UVDTC_PWR_STATUS__SHIFT 0x6
+#define UVD_PGFSM_STATUS__UVDB_PWR_STATUS__SHIFT 0x8
+#define UVD_PGFSM_STATUS__UVDTA_PWR_STATUS__SHIFT 0xa
+#define UVD_PGFSM_STATUS__UVDLM_PWR_STATUS__SHIFT 0xc
+#define UVD_PGFSM_STATUS__UVDTD_PWR_STATUS__SHIFT 0xe
+#define UVD_PGFSM_STATUS__UVDTE_PWR_STATUS__SHIFT 0x10
+#define UVD_PGFSM_STATUS__UVDE_PWR_STATUS__SHIFT 0x12
+#define UVD_PGFSM_STATUS__UVDAB_PWR_STATUS__SHIFT 0x14
+#define UVD_PGFSM_STATUS__UVDJ_PWR_STATUS__SHIFT 0x16
+#define UVD_PGFSM_STATUS__UVDTB_PWR_STATUS__SHIFT 0x18
+#define UVD_PGFSM_STATUS__UVDNA_PWR_STATUS__SHIFT 0x1a
+#define UVD_PGFSM_STATUS__UVDNB_PWR_STATUS__SHIFT 0x1c
+#define UVD_PGFSM_STATUS__UVDM_PWR_STATUS_MASK 0x00000003L
+#define UVD_PGFSM_STATUS__UVDS_PWR_STATUS_MASK 0x0000000CL
+#define UVD_PGFSM_STATUS__UVDF_PWR_STATUS_MASK 0x00000030L
+#define UVD_PGFSM_STATUS__UVDTC_PWR_STATUS_MASK 0x000000C0L
+#define UVD_PGFSM_STATUS__UVDB_PWR_STATUS_MASK 0x00000300L
+#define UVD_PGFSM_STATUS__UVDTA_PWR_STATUS_MASK 0x00000C00L
+#define UVD_PGFSM_STATUS__UVDLM_PWR_STATUS_MASK 0x00003000L
+#define UVD_PGFSM_STATUS__UVDTD_PWR_STATUS_MASK 0x0000C000L
+#define UVD_PGFSM_STATUS__UVDTE_PWR_STATUS_MASK 0x00030000L
+#define UVD_PGFSM_STATUS__UVDE_PWR_STATUS_MASK 0x000C0000L
+#define UVD_PGFSM_STATUS__UVDAB_PWR_STATUS_MASK 0x00300000L
+#define UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK 0x00C00000L
+#define UVD_PGFSM_STATUS__UVDTB_PWR_STATUS_MASK 0x03000000L
+#define UVD_PGFSM_STATUS__UVDNA_PWR_STATUS_MASK 0x0C000000L
+#define UVD_PGFSM_STATUS__UVDNB_PWR_STATUS_MASK 0x30000000L
+//UVD_POWER_STATUS
+#define UVD_POWER_STATUS__UVD_POWER_STATUS__SHIFT 0x0
+#define UVD_POWER_STATUS__UVD_PG_MODE__SHIFT 0x2
+#define UVD_POWER_STATUS__UVD_CG_MODE__SHIFT 0x4
+#define UVD_POWER_STATUS__UVD_PG_EN__SHIFT 0x8
+#define UVD_POWER_STATUS__RBC_SNOOP_DIS__SHIFT 0x9
+#define UVD_POWER_STATUS__SW_RB_SNOOP_DIS__SHIFT 0xb
+#define UVD_POWER_STATUS__STALL_DPG_POWER_UP__SHIFT 0x1f
+#define UVD_POWER_STATUS__UVD_POWER_STATUS_MASK 0x00000003L
+#define UVD_POWER_STATUS__UVD_PG_MODE_MASK 0x00000004L
+#define UVD_POWER_STATUS__UVD_CG_MODE_MASK 0x00000030L
+#define UVD_POWER_STATUS__UVD_PG_EN_MASK 0x00000100L
+#define UVD_POWER_STATUS__RBC_SNOOP_DIS_MASK 0x00000200L
+#define UVD_POWER_STATUS__SW_RB_SNOOP_DIS_MASK 0x00000800L
+#define UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK 0x80000000L
+//UVD_JPEG_POWER_STATUS
+#define UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS__SHIFT 0x0
+#define UVD_JPEG_POWER_STATUS__JPEG_PG_MODE__SHIFT 0x4
+#define UVD_JPEG_POWER_STATUS__JRBC_DEC_SNOOP_DIS__SHIFT 0x8
+#define UVD_JPEG_POWER_STATUS__JRBC_ENC_SNOOP_DIS__SHIFT 0x9
+#define UVD_JPEG_POWER_STATUS__STALL_JDPG_POWER_UP__SHIFT 0x1f
+#define UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK 0x00000001L
+#define UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK 0x00000010L
+#define UVD_JPEG_POWER_STATUS__JRBC_DEC_SNOOP_DIS_MASK 0x00000100L
+#define UVD_JPEG_POWER_STATUS__JRBC_ENC_SNOOP_DIS_MASK 0x00000200L
+#define UVD_JPEG_POWER_STATUS__STALL_JDPG_POWER_UP_MASK 0x80000000L
+//UVD_MC_DJPEG_RD_SPACE
+#define UVD_MC_DJPEG_RD_SPACE__DJPEG_RD_SPACE__SHIFT 0x0
+#define UVD_MC_DJPEG_RD_SPACE__DJPEG_RD_SPACE_MASK 0x0003FFFFL
+//UVD_MC_DJPEG_WR_SPACE
+#define UVD_MC_DJPEG_WR_SPACE__DJPEG_WR_SPACE__SHIFT 0x0
+#define UVD_MC_DJPEG_WR_SPACE__DJPEG_WR_SPACE_MASK 0x0003FFFFL
+//UVD_MC_EJPEG_RD_SPACE
+#define UVD_MC_EJPEG_RD_SPACE__EJPEG_RD_SPACE__SHIFT 0x0
+#define UVD_MC_EJPEG_RD_SPACE__EJPEG_RD_SPACE_MASK 0x0003FFFFL
+//UVD_MC_EJPEG_WR_SPACE
+#define UVD_MC_EJPEG_WR_SPACE__EJPEG_WR_SPACE__SHIFT 0x0
+#define UVD_MC_EJPEG_WR_SPACE__EJPEG_WR_SPACE_MASK 0x0003FFFFL
+//UVD_PG_IND_INDEX
+#define UVD_PG_IND_INDEX__INDEX__SHIFT 0x0
+#define UVD_PG_IND_INDEX__INDEX_MASK 0x0000003FL
+//UVD_PG_IND_DATA
+#define UVD_PG_IND_DATA__DATA__SHIFT 0x0
+#define UVD_PG_IND_DATA__DATA_MASK 0xFFFFFFFFL
+//CC_UVD_HARVESTING
+#define CC_UVD_HARVESTING__MMSCH_DISABLE__SHIFT 0x0
+#define CC_UVD_HARVESTING__UVD_DISABLE__SHIFT 0x1
+#define CC_UVD_HARVESTING__MMSCH_DISABLE_MASK 0x00000001L
+#define CC_UVD_HARVESTING__UVD_DISABLE_MASK 0x00000002L
+//UVD_DPG_LMA_CTL
+#define UVD_DPG_LMA_CTL__READ_WRITE__SHIFT 0x0
+#define UVD_DPG_LMA_CTL__MASK_EN__SHIFT 0x1
+#define UVD_DPG_LMA_CTL__ADDR_AUTO_INCREMENT__SHIFT 0x2
+#define UVD_DPG_LMA_CTL__SRAM_SEL__SHIFT 0x4
+#define UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT 0x10
+#define UVD_DPG_LMA_CTL__READ_WRITE_MASK 0x00000001L
+#define UVD_DPG_LMA_CTL__MASK_EN_MASK 0x00000002L
+#define UVD_DPG_LMA_CTL__ADDR_AUTO_INCREMENT_MASK 0x00000004L
+#define UVD_DPG_LMA_CTL__SRAM_SEL_MASK 0x00000010L
+#define UVD_DPG_LMA_CTL__READ_WRITE_ADDR_MASK 0xFFFF0000L
+//UVD_DPG_LMA_DATA
+#define UVD_DPG_LMA_DATA__LMA_DATA__SHIFT 0x0
+#define UVD_DPG_LMA_DATA__LMA_DATA_MASK 0xFFFFFFFFL
+//UVD_DPG_LMA_MASK
+#define UVD_DPG_LMA_MASK__LMA_MASK__SHIFT 0x0
+#define UVD_DPG_LMA_MASK__LMA_MASK_MASK 0xFFFFFFFFL
+//UVD_DPG_PAUSE
+#define UVD_DPG_PAUSE__JPEG_PAUSE_DPG_REQ__SHIFT 0x0
+#define UVD_DPG_PAUSE__JPEG_PAUSE_DPG_ACK__SHIFT 0x1
+#define UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ__SHIFT 0x2
+#define UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK__SHIFT 0x3
+#define UVD_DPG_PAUSE__JPEG_PAUSE_DPG_REQ_MASK 0x00000001L
+#define UVD_DPG_PAUSE__JPEG_PAUSE_DPG_ACK_MASK 0x00000002L
+#define UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK 0x00000004L
+#define UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK 0x00000008L
+//UVD_SCRATCH1
+#define UVD_SCRATCH1__SCRATCH1_DATA__SHIFT 0x0
+#define UVD_SCRATCH1__SCRATCH1_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH2
+#define UVD_SCRATCH2__SCRATCH2_DATA__SHIFT 0x0
+#define UVD_SCRATCH2__SCRATCH2_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH3
+#define UVD_SCRATCH3__SCRATCH3_DATA__SHIFT 0x0
+#define UVD_SCRATCH3__SCRATCH3_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH4
+#define UVD_SCRATCH4__SCRATCH4_DATA__SHIFT 0x0
+#define UVD_SCRATCH4__SCRATCH4_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH5
+#define UVD_SCRATCH5__SCRATCH5_DATA__SHIFT 0x0
+#define UVD_SCRATCH5__SCRATCH5_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH6
+#define UVD_SCRATCH6__SCRATCH6_DATA__SHIFT 0x0
+#define UVD_SCRATCH6__SCRATCH6_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH7
+#define UVD_SCRATCH7__SCRATCH7_DATA__SHIFT 0x0
+#define UVD_SCRATCH7__SCRATCH7_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH8
+#define UVD_SCRATCH8__SCRATCH8_DATA__SHIFT 0x0
+#define UVD_SCRATCH8__SCRATCH8_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH9
+#define UVD_SCRATCH9__SCRATCH9_DATA__SHIFT 0x0
+#define UVD_SCRATCH9__SCRATCH9_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH10
+#define UVD_SCRATCH10__SCRATCH10_DATA__SHIFT 0x0
+#define UVD_SCRATCH10__SCRATCH10_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH11
+#define UVD_SCRATCH11__SCRATCH11_DATA__SHIFT 0x0
+#define UVD_SCRATCH11__SCRATCH11_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH12
+#define UVD_SCRATCH12__SCRATCH12_DATA__SHIFT 0x0
+#define UVD_SCRATCH12__SCRATCH12_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH13
+#define UVD_SCRATCH13__SCRATCH13_DATA__SHIFT 0x0
+#define UVD_SCRATCH13__SCRATCH13_DATA_MASK 0xFFFFFFFFL
+//UVD_SCRATCH14
+#define UVD_SCRATCH14__SCRATCH14_DATA__SHIFT 0x0
+#define UVD_SCRATCH14__SCRATCH14_DATA_MASK 0xFFFFFFFFL
+//UVD_FREE_COUNTER_REG
+#define UVD_FREE_COUNTER_REG__FREE_COUNTER__SHIFT 0x0
+#define UVD_FREE_COUNTER_REG__FREE_COUNTER_MASK 0xFFFFFFFFL
+//UVD_DPG_LMI_VCPU_CACHE_64BIT_BAR_LOW
+#define UVD_DPG_LMI_VCPU_CACHE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_DPG_LMI_VCPU_CACHE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_DPG_LMI_VCPU_CACHE_64BIT_BAR_HIGH
+#define UVD_DPG_LMI_VCPU_CACHE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_DPG_LMI_VCPU_CACHE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_DPG_VCPU_CACHE_OFFSET0
+#define UVD_DPG_VCPU_CACHE_OFFSET0__CACHE_OFFSET0__SHIFT 0x0
+#define UVD_DPG_VCPU_CACHE_OFFSET0__CACHE_OFFSET0_MASK 0x01FFFFFFL
+//UVD_DPG_LMI_VCPU_CACHE_VMID
+#define UVD_DPG_LMI_VCPU_CACHE_VMID__VCPU_CACHE_VMID__SHIFT 0x0
+#define UVD_DPG_LMI_VCPU_CACHE_VMID__VCPU_CACHE_VMID_MASK 0x0000000FL
+//UVD_REG_FILTER_EN
+#define UVD_REG_FILTER_EN__UVD_REG_FILTER_EN__SHIFT 0x0
+#define UVD_REG_FILTER_EN__MMSCH_HI_PRIV__SHIFT 0x1
+#define UVD_REG_FILTER_EN__VIDEO_PRIV_EN__SHIFT 0x2
+#define UVD_REG_FILTER_EN__JPEG_PRIV_EN__SHIFT 0x3
+#define UVD_REG_FILTER_EN__UVD_REG_FILTER_EN_MASK 0x00000001L
+#define UVD_REG_FILTER_EN__MMSCH_HI_PRIV_MASK 0x00000002L
+#define UVD_REG_FILTER_EN__VIDEO_PRIV_EN_MASK 0x00000004L
+#define UVD_REG_FILTER_EN__JPEG_PRIV_EN_MASK 0x00000008L
+//UVD_SECURITY_REG_VIO_REPORT
+#define UVD_SECURITY_REG_VIO_REPORT__HOST_REG_VIO__SHIFT 0x0
+#define UVD_SECURITY_REG_VIO_REPORT__VCPU_REG_VIO__SHIFT 0x1
+#define UVD_SECURITY_REG_VIO_REPORT__VIDEO_REG_VIO__SHIFT 0x2
+#define UVD_SECURITY_REG_VIO_REPORT__DPG_REG_VIO__SHIFT 0x3
+#define UVD_SECURITY_REG_VIO_REPORT__JPEG_REG_VIO__SHIFT 0x4
+#define UVD_SECURITY_REG_VIO_REPORT__JDPG_REG_VIO__SHIFT 0x5
+#define UVD_SECURITY_REG_VIO_REPORT__HOST_REG_VIO_MASK 0x00000001L
+#define UVD_SECURITY_REG_VIO_REPORT__VCPU_REG_VIO_MASK 0x00000002L
+#define UVD_SECURITY_REG_VIO_REPORT__VIDEO_REG_VIO_MASK 0x00000004L
+#define UVD_SECURITY_REG_VIO_REPORT__DPG_REG_VIO_MASK 0x00000008L
+#define UVD_SECURITY_REG_VIO_REPORT__JPEG_REG_VIO_MASK 0x00000010L
+#define UVD_SECURITY_REG_VIO_REPORT__JDPG_REG_VIO_MASK 0x00000020L
+//UVD_FW_VERSION
+#define UVD_FW_VERSION__FW_VERSION__SHIFT 0x0
+#define UVD_FW_VERSION__FW_VERSION_MASK 0xFFFFFFFFL
+//UVD_PF_STATUS
+#define UVD_PF_STATUS__JPEG_PF_OCCURED__SHIFT 0x0
+#define UVD_PF_STATUS__NJ_PF_OCCURED__SHIFT 0x1
+#define UVD_PF_STATUS__ENCODER0_PF_OCCURED__SHIFT 0x2
+#define UVD_PF_STATUS__ENCODER1_PF_OCCURED__SHIFT 0x3
+#define UVD_PF_STATUS__ENCODER2_PF_OCCURED__SHIFT 0x4
+#define UVD_PF_STATUS__ENCODER3_PF_OCCURED__SHIFT 0x5
+#define UVD_PF_STATUS__ENCODER4_PF_OCCURED__SHIFT 0x6
+#define UVD_PF_STATUS__EJPEG_PF_OCCURED__SHIFT 0x7
+#define UVD_PF_STATUS__JPEG_PF_CLEAR__SHIFT 0x8
+#define UVD_PF_STATUS__NJ_PF_CLEAR__SHIFT 0x9
+#define UVD_PF_STATUS__ENCODER0_PF_CLEAR__SHIFT 0xa
+#define UVD_PF_STATUS__ENCODER1_PF_CLEAR__SHIFT 0xb
+#define UVD_PF_STATUS__ENCODER2_PF_CLEAR__SHIFT 0xc
+#define UVD_PF_STATUS__ENCODER3_PF_CLEAR__SHIFT 0xd
+#define UVD_PF_STATUS__ENCODER4_PF_CLEAR__SHIFT 0xe
+#define UVD_PF_STATUS__EJPEG_PF_CLEAR__SHIFT 0xf
+#define UVD_PF_STATUS__NJ_ATM_PF_OCCURED__SHIFT 0x10
+#define UVD_PF_STATUS__DJ_ATM_PF_OCCURED__SHIFT 0x11
+#define UVD_PF_STATUS__EJ_ATM_PF_OCCURED__SHIFT 0x12
+#define UVD_PF_STATUS__JPEG2_PF_OCCURED__SHIFT 0x13
+#define UVD_PF_STATUS__DJ2_ATM_PF_OCCURED__SHIFT 0x14
+#define UVD_PF_STATUS__JPEG2_PF_CLEAR__SHIFT 0x15
+#define UVD_PF_STATUS__ENCODER5_PF_OCCURED__SHIFT 0x16
+#define UVD_PF_STATUS__ENCODER5_PF_CLEAR__SHIFT 0x17
+#define UVD_PF_STATUS__JPEG_PF_OCCURED_MASK 0x00000001L
+#define UVD_PF_STATUS__NJ_PF_OCCURED_MASK 0x00000002L
+#define UVD_PF_STATUS__ENCODER0_PF_OCCURED_MASK 0x00000004L
+#define UVD_PF_STATUS__ENCODER1_PF_OCCURED_MASK 0x00000008L
+#define UVD_PF_STATUS__ENCODER2_PF_OCCURED_MASK 0x00000010L
+#define UVD_PF_STATUS__ENCODER3_PF_OCCURED_MASK 0x00000020L
+#define UVD_PF_STATUS__ENCODER4_PF_OCCURED_MASK 0x00000040L
+#define UVD_PF_STATUS__EJPEG_PF_OCCURED_MASK 0x00000080L
+#define UVD_PF_STATUS__JPEG_PF_CLEAR_MASK 0x00000100L
+#define UVD_PF_STATUS__NJ_PF_CLEAR_MASK 0x00000200L
+#define UVD_PF_STATUS__ENCODER0_PF_CLEAR_MASK 0x00000400L
+#define UVD_PF_STATUS__ENCODER1_PF_CLEAR_MASK 0x00000800L
+#define UVD_PF_STATUS__ENCODER2_PF_CLEAR_MASK 0x00001000L
+#define UVD_PF_STATUS__ENCODER3_PF_CLEAR_MASK 0x00002000L
+#define UVD_PF_STATUS__ENCODER4_PF_CLEAR_MASK 0x00004000L
+#define UVD_PF_STATUS__EJPEG_PF_CLEAR_MASK 0x00008000L
+#define UVD_PF_STATUS__NJ_ATM_PF_OCCURED_MASK 0x00010000L
+#define UVD_PF_STATUS__DJ_ATM_PF_OCCURED_MASK 0x00020000L
+#define UVD_PF_STATUS__EJ_ATM_PF_OCCURED_MASK 0x00040000L
+#define UVD_PF_STATUS__JPEG2_PF_OCCURED_MASK 0x00080000L
+#define UVD_PF_STATUS__DJ2_ATM_PF_OCCURED_MASK 0x00100000L
+#define UVD_PF_STATUS__JPEG2_PF_CLEAR_MASK 0x00200000L
+#define UVD_PF_STATUS__ENCODER5_PF_OCCURED_MASK 0x00400000L
+#define UVD_PF_STATUS__ENCODER5_PF_CLEAR_MASK 0x00800000L
+//UVD_DPG_CLK_EN_VCPU_REPORT
+#define UVD_DPG_CLK_EN_VCPU_REPORT__CLK_EN__SHIFT 0x0
+#define UVD_DPG_CLK_EN_VCPU_REPORT__VCPU_REPORT__SHIFT 0x1
+#define UVD_DPG_CLK_EN_VCPU_REPORT__CLK_EN_MASK 0x00000001L
+#define UVD_DPG_CLK_EN_VCPU_REPORT__VCPU_REPORT_MASK 0x000000FEL
+//CC_UVD_VCPU_ERR_DETECT_BOT_LO
+#define CC_UVD_VCPU_ERR_DETECT_BOT_LO__UVD_VCPU_ERR_DETECT_BOT_LO__SHIFT 0xc
+#define CC_UVD_VCPU_ERR_DETECT_BOT_LO__UVD_VCPU_ERR_DETECT_BOT_LO_MASK 0xFFFFF000L
+//CC_UVD_VCPU_ERR_DETECT_BOT_HI
+#define CC_UVD_VCPU_ERR_DETECT_BOT_HI__UVD_VCPU_ERR_DETECT_BOT_HI__SHIFT 0x0
+#define CC_UVD_VCPU_ERR_DETECT_BOT_HI__UVD_VCPU_ERR_DETECT_BOT_HI_MASK 0x0000FFFFL
+//CC_UVD_VCPU_ERR_DETECT_TOP_LO
+#define CC_UVD_VCPU_ERR_DETECT_TOP_LO__UVD_VCPU_ERR_DETECT_TOP_LO__SHIFT 0xc
+#define CC_UVD_VCPU_ERR_DETECT_TOP_LO__UVD_VCPU_ERR_DETECT_TOP_LO_MASK 0xFFFFF000L
+//CC_UVD_VCPU_ERR_DETECT_TOP_HI
+#define CC_UVD_VCPU_ERR_DETECT_TOP_HI__UVD_VCPU_ERR_DETECT_TOP_HI__SHIFT 0x0
+#define CC_UVD_VCPU_ERR_DETECT_TOP_HI__UVD_VCPU_ERR_DETECT_TOP_HI_MASK 0x0000FFFFL
+//CC_UVD_VCPU_ERR
+#define CC_UVD_VCPU_ERR__UVD_VCPU_ERR_STATUS__SHIFT 0x0
+#define CC_UVD_VCPU_ERR__UVD_VCPU_ERR_CLEAR__SHIFT 0x1
+#define CC_UVD_VCPU_ERR__UVD_VCPU_ERR_DETECT_EN__SHIFT 0x2
+#define CC_UVD_VCPU_ERR__UVD_TMZ_DBG_DIS__SHIFT 0x3
+#define CC_UVD_VCPU_ERR__RESET_ON_FAULT__SHIFT 0x4
+#define CC_UVD_VCPU_ERR__UVD_VCPU_ERR_STATUS_MASK 0x00000001L
+#define CC_UVD_VCPU_ERR__UVD_VCPU_ERR_CLEAR_MASK 0x00000002L
+#define CC_UVD_VCPU_ERR__UVD_VCPU_ERR_DETECT_EN_MASK 0x00000004L
+#define CC_UVD_VCPU_ERR__UVD_TMZ_DBG_DIS_MASK 0x00000008L
+#define CC_UVD_VCPU_ERR__RESET_ON_FAULT_MASK 0x00000010L
+//CC_UVD_VCPU_ERR_INST_ADDR_LO
+#define CC_UVD_VCPU_ERR_INST_ADDR_LO__UVD_VCPU_ERR_INST_ADDR_LO__SHIFT 0x0
+#define CC_UVD_VCPU_ERR_INST_ADDR_LO__UVD_VCPU_ERR_INST_ADDR_LO_MASK 0xFFFFFFFFL
+//CC_UVD_VCPU_ERR_INST_ADDR_HI
+#define CC_UVD_VCPU_ERR_INST_ADDR_HI__UVD_VCPU_ERR_INST_ADDR_HI__SHIFT 0x0
+#define CC_UVD_VCPU_ERR_INST_ADDR_HI__UVD_VCPU_ERR_INST_ADDR_HI_MASK 0x0000FFFFL
+//UVD_LMI_MMSCH_NC_SPACE
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC0_SPACE__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC1_SPACE__SHIFT 0x3
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC2_SPACE__SHIFT 0x6
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC3_SPACE__SHIFT 0x9
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC4_SPACE__SHIFT 0xc
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC5_SPACE__SHIFT 0xf
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC6_SPACE__SHIFT 0x12
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC7_SPACE__SHIFT 0x15
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC0_SPACE_MASK 0x00000007L
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC1_SPACE_MASK 0x00000038L
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC2_SPACE_MASK 0x000001C0L
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC3_SPACE_MASK 0x00000E00L
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC4_SPACE_MASK 0x00007000L
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC5_SPACE_MASK 0x00038000L
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC6_SPACE_MASK 0x001C0000L
+#define UVD_LMI_MMSCH_NC_SPACE__MMSCH_NC7_SPACE_MASK 0x00E00000L
+//UVD_LMI_ATOMIC_SPACE
+#define UVD_LMI_ATOMIC_SPACE__ATOMIC_USER0_SPACE__SHIFT 0x0
+#define UVD_LMI_ATOMIC_SPACE__ATOMIC_USER1_SPACE__SHIFT 0x3
+#define UVD_LMI_ATOMIC_SPACE__ATOMIC_USER2_SPACE__SHIFT 0x6
+#define UVD_LMI_ATOMIC_SPACE__ATOMIC_USER3_SPACE__SHIFT 0x9
+#define UVD_LMI_ATOMIC_SPACE__ATOMIC_USER0_SPACE_MASK 0x00000007L
+#define UVD_LMI_ATOMIC_SPACE__ATOMIC_USER1_SPACE_MASK 0x00000038L
+#define UVD_LMI_ATOMIC_SPACE__ATOMIC_USER2_SPACE_MASK 0x000001C0L
+#define UVD_LMI_ATOMIC_SPACE__ATOMIC_USER3_SPACE_MASK 0x00000E00L
+//UVD_GFX8_ADDR_CONFIG
+#define UVD_GFX8_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x4
+#define UVD_GFX8_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+//UVD_GFX10_ADDR_CONFIG
+#define UVD_GFX10_ADDR_CONFIG__NUM_PIPES__SHIFT 0x0
+#define UVD_GFX10_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x3
+#define UVD_GFX10_ADDR_CONFIG__MAX_COMPRESSED_FRAGS__SHIFT 0x6
+#define UVD_GFX10_ADDR_CONFIG__NUM_PKRS__SHIFT 0x8
+#define UVD_GFX10_ADDR_CONFIG__NUM_BANKS__SHIFT 0xc
+#define UVD_GFX10_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x13
+#define UVD_GFX10_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_GFX10_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000038L
+#define UVD_GFX10_ADDR_CONFIG__MAX_COMPRESSED_FRAGS_MASK 0x000000C0L
+#define UVD_GFX10_ADDR_CONFIG__NUM_PKRS_MASK 0x00000700L
+#define UVD_GFX10_ADDR_CONFIG__NUM_BANKS_MASK 0x00007000L
+#define UVD_GFX10_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00180000L
+//UVD_GPCNT2_CNTL
+#define UVD_GPCNT2_CNTL__CLR__SHIFT 0x0
+#define UVD_GPCNT2_CNTL__START__SHIFT 0x1
+#define UVD_GPCNT2_CNTL__COUNTUP__SHIFT 0x2
+#define UVD_GPCNT2_CNTL__CLR_MASK 0x00000001L
+#define UVD_GPCNT2_CNTL__START_MASK 0x00000002L
+#define UVD_GPCNT2_CNTL__COUNTUP_MASK 0x00000004L
+//UVD_GPCNT2_TARGET_LOWER
+#define UVD_GPCNT2_TARGET_LOWER__TARGET__SHIFT 0x0
+#define UVD_GPCNT2_TARGET_LOWER__TARGET_MASK 0xFFFFFFFFL
+//UVD_GPCNT2_STATUS_LOWER
+#define UVD_GPCNT2_STATUS_LOWER__COUNT__SHIFT 0x0
+#define UVD_GPCNT2_STATUS_LOWER__COUNT_MASK 0xFFFFFFFFL
+//UVD_GPCNT2_TARGET_UPPER
+#define UVD_GPCNT2_TARGET_UPPER__TARGET__SHIFT 0x0
+#define UVD_GPCNT2_TARGET_UPPER__TARGET_MASK 0x0000FFFFL
+//UVD_GPCNT2_STATUS_UPPER
+#define UVD_GPCNT2_STATUS_UPPER__COUNT__SHIFT 0x0
+#define UVD_GPCNT2_STATUS_UPPER__COUNT_MASK 0x0000FFFFL
+//UVD_GPCNT3_CNTL
+#define UVD_GPCNT3_CNTL__CLR__SHIFT 0x0
+#define UVD_GPCNT3_CNTL__START__SHIFT 0x1
+#define UVD_GPCNT3_CNTL__COUNTUP__SHIFT 0x2
+#define UVD_GPCNT3_CNTL__FREQ__SHIFT 0x3
+#define UVD_GPCNT3_CNTL__DIV__SHIFT 0xa
+#define UVD_GPCNT3_CNTL__CLR_MASK 0x00000001L
+#define UVD_GPCNT3_CNTL__START_MASK 0x00000002L
+#define UVD_GPCNT3_CNTL__COUNTUP_MASK 0x00000004L
+#define UVD_GPCNT3_CNTL__FREQ_MASK 0x000003F8L
+#define UVD_GPCNT3_CNTL__DIV_MASK 0x0001FC00L
+//UVD_GPCNT3_TARGET_LOWER
+#define UVD_GPCNT3_TARGET_LOWER__TARGET__SHIFT 0x0
+#define UVD_GPCNT3_TARGET_LOWER__TARGET_MASK 0xFFFFFFFFL
+//UVD_GPCNT3_STATUS_LOWER
+#define UVD_GPCNT3_STATUS_LOWER__COUNT__SHIFT 0x0
+#define UVD_GPCNT3_STATUS_LOWER__COUNT_MASK 0xFFFFFFFFL
+//UVD_GPCNT3_TARGET_UPPER
+#define UVD_GPCNT3_TARGET_UPPER__TARGET__SHIFT 0x0
+#define UVD_GPCNT3_TARGET_UPPER__TARGET_MASK 0x0000FFFFL
+//UVD_GPCNT3_STATUS_UPPER
+#define UVD_GPCNT3_STATUS_UPPER__COUNT__SHIFT 0x0
+#define UVD_GPCNT3_STATUS_UPPER__COUNT_MASK 0x0000FFFFL
+//UVD_VCLK_DS_CNTL
+#define UVD_VCLK_DS_CNTL__VCLK_DS_EN__SHIFT 0x0
+#define UVD_VCLK_DS_CNTL__VCLK_DS_STATUS__SHIFT 0x4
+#define UVD_VCLK_DS_CNTL__VCLK_DS_HYSTERESIS_CNT__SHIFT 0x10
+#define UVD_VCLK_DS_CNTL__VCLK_DS_EN_MASK 0x00000001L
+#define UVD_VCLK_DS_CNTL__VCLK_DS_STATUS_MASK 0x00000010L
+#define UVD_VCLK_DS_CNTL__VCLK_DS_HYSTERESIS_CNT_MASK 0xFFFF0000L
+//UVD_DCLK_DS_CNTL
+#define UVD_DCLK_DS_CNTL__DCLK_DS_EN__SHIFT 0x0
+#define UVD_DCLK_DS_CNTL__DCLK_DS_STATUS__SHIFT 0x4
+#define UVD_DCLK_DS_CNTL__DCLK_DS_HYSTERESIS_CNT__SHIFT 0x10
+#define UVD_DCLK_DS_CNTL__DCLK_DS_EN_MASK 0x00000001L
+#define UVD_DCLK_DS_CNTL__DCLK_DS_STATUS_MASK 0x00000010L
+#define UVD_DCLK_DS_CNTL__DCLK_DS_HYSTERESIS_CNT_MASK 0xFFFF0000L
+//UVD_TSC_LOWER
+#define UVD_TSC_LOWER__COUNT__SHIFT 0x0
+#define UVD_TSC_LOWER__COUNT_MASK 0xFFFFFFFFL
+//UVD_TSC_UPPER
+#define UVD_TSC_UPPER__COUNT__SHIFT 0x0
+#define UVD_TSC_UPPER__COUNT_MASK 0x00FFFFFFL
+//VCN_FEATURES
+#define VCN_FEATURES__HAS_VIDEO_DEC__SHIFT 0x0
+#define VCN_FEATURES__HAS_VIDEO_ENC__SHIFT 0x1
+#define VCN_FEATURES__HAS_MJPEG_DEC__SHIFT 0x2
+#define VCN_FEATURES__HAS_MJPEG_ENC__SHIFT 0x3
+#define VCN_FEATURES__HAS_VIDEO_VIRT__SHIFT 0x4
+#define VCN_FEATURES__HAS_H264_LEGACY_DEC__SHIFT 0x5
+#define VCN_FEATURES__HAS_UDEC_DEC__SHIFT 0x6
+#define VCN_FEATURES__HAS_MJPEG2_IDCT_DEC__SHIFT 0x7
+#define VCN_FEATURES__HAS_SCLR_DEC__SHIFT 0x8
+#define VCN_FEATURES__HAS_VP9_DEC__SHIFT 0x9
+#define VCN_FEATURES__HAS_AV1_DEC__SHIFT 0xa
+#define VCN_FEATURES__HAS_EFC_ENC__SHIFT 0xb
+#define VCN_FEATURES__HAS_EFC_HDR2SDR_ENC__SHIFT 0xc
+#define VCN_FEATURES__HAS_DUAL_MJPEG_DEC__SHIFT 0xd
+#define VCN_FEATURES__HAS_AV1_ENC__SHIFT 0xe
+#define VCN_FEATURES__INSTANCE_ID__SHIFT 0x1c
+#define VCN_FEATURES__HAS_VIDEO_DEC_MASK 0x00000001L
+#define VCN_FEATURES__HAS_VIDEO_ENC_MASK 0x00000002L
+#define VCN_FEATURES__HAS_MJPEG_DEC_MASK 0x00000004L
+#define VCN_FEATURES__HAS_MJPEG_ENC_MASK 0x00000008L
+#define VCN_FEATURES__HAS_VIDEO_VIRT_MASK 0x00000010L
+#define VCN_FEATURES__HAS_H264_LEGACY_DEC_MASK 0x00000020L
+#define VCN_FEATURES__HAS_UDEC_DEC_MASK 0x00000040L
+#define VCN_FEATURES__HAS_MJPEG2_IDCT_DEC_MASK 0x00000080L
+#define VCN_FEATURES__HAS_SCLR_DEC_MASK 0x00000100L
+#define VCN_FEATURES__HAS_VP9_DEC_MASK 0x00000200L
+#define VCN_FEATURES__HAS_AV1_DEC_MASK 0x00000400L
+#define VCN_FEATURES__HAS_EFC_ENC_MASK 0x00000800L
+#define VCN_FEATURES__HAS_EFC_HDR2SDR_ENC_MASK 0x00001000L
+#define VCN_FEATURES__HAS_DUAL_MJPEG_DEC_MASK 0x00002000L
+#define VCN_FEATURES__HAS_AV1_ENC_MASK 0x00004000L
+#define VCN_FEATURES__INSTANCE_ID_MASK 0xF0000000L
+//UVD_GPUIOV_STATUS
+#define UVD_GPUIOV_STATUS__UVD_GPUIOV_STATUS_VF_ENABLE__SHIFT 0x0
+#define UVD_GPUIOV_STATUS__UVD_GPUIOV_STATUS_VF_ENABLE_MASK 0x00000001L
+//UVD_RAS_VCPU_VCODEC_STATUS
+#define UVD_RAS_VCPU_VCODEC_STATUS__POISONED_VF__SHIFT 0x0
+#define UVD_RAS_VCPU_VCODEC_STATUS__POISONED_PF__SHIFT 0x1f
+#define UVD_RAS_VCPU_VCODEC_STATUS__POISONED_VF_MASK 0x7FFFFFFFL
+#define UVD_RAS_VCPU_VCODEC_STATUS__POISONED_PF_MASK 0x80000000L
+//UVD_RAS_MMSCH_FATAL_ERROR
+#define UVD_RAS_MMSCH_FATAL_ERROR__POISONED_VF__SHIFT 0x0
+#define UVD_RAS_MMSCH_FATAL_ERROR__POISONED_PF__SHIFT 0x1f
+#define UVD_RAS_MMSCH_FATAL_ERROR__POISONED_VF_MASK 0x7FFFFFFFL
+#define UVD_RAS_MMSCH_FATAL_ERROR__POISONED_PF_MASK 0x80000000L
+//UVD_RAS_JPEG0_STATUS
+#define UVD_RAS_JPEG0_STATUS__POISONED_VF__SHIFT 0x0
+#define UVD_RAS_JPEG0_STATUS__POISONED_PF__SHIFT 0x1f
+#define UVD_RAS_JPEG0_STATUS__POISONED_VF_MASK 0x7FFFFFFFL
+#define UVD_RAS_JPEG0_STATUS__POISONED_PF_MASK 0x80000000L
+//UVD_RAS_JPEG1_STATUS
+#define UVD_RAS_JPEG1_STATUS__POISONED_VF__SHIFT 0x0
+#define UVD_RAS_JPEG1_STATUS__POISONED_PF__SHIFT 0x1f
+#define UVD_RAS_JPEG1_STATUS__POISONED_VF_MASK 0x7FFFFFFFL
+#define UVD_RAS_JPEG1_STATUS__POISONED_PF_MASK 0x80000000L
+//UVD_RAS_CNTL_PMI_ARB
+#define UVD_RAS_CNTL_PMI_ARB__STAT_VCPU_VCODEC__SHIFT 0x0
+#define UVD_RAS_CNTL_PMI_ARB__ACK_VCPU_VCODEC__SHIFT 0x1
+#define UVD_RAS_CNTL_PMI_ARB__STAT_MMSCH__SHIFT 0x2
+#define UVD_RAS_CNTL_PMI_ARB__ACK_MMSCH__SHIFT 0x3
+#define UVD_RAS_CNTL_PMI_ARB__STAT_JPEG0__SHIFT 0x4
+#define UVD_RAS_CNTL_PMI_ARB__ACK_JPEG0__SHIFT 0x5
+#define UVD_RAS_CNTL_PMI_ARB__STAT_JPEG1__SHIFT 0x6
+#define UVD_RAS_CNTL_PMI_ARB__ACK_JPEG1__SHIFT 0x7
+#define UVD_RAS_CNTL_PMI_ARB__STAT_VCPU_VCODEC_MASK 0x00000001L
+#define UVD_RAS_CNTL_PMI_ARB__ACK_VCPU_VCODEC_MASK 0x00000002L
+#define UVD_RAS_CNTL_PMI_ARB__STAT_MMSCH_MASK 0x00000004L
+#define UVD_RAS_CNTL_PMI_ARB__ACK_MMSCH_MASK 0x00000008L
+#define UVD_RAS_CNTL_PMI_ARB__STAT_JPEG0_MASK 0x00000010L
+#define UVD_RAS_CNTL_PMI_ARB__ACK_JPEG0_MASK 0x00000020L
+#define UVD_RAS_CNTL_PMI_ARB__STAT_JPEG1_MASK 0x00000040L
+#define UVD_RAS_CNTL_PMI_ARB__ACK_JPEG1_MASK 0x00000080L
+//UVD_SCRATCH15
+#define UVD_SCRATCH15__SCRATCH15_DATA__SHIFT 0x0
+#define UVD_SCRATCH15__SCRATCH15_DATA_MASK 0xFFFFFFFFL
+//VCN_JPEG_DB_CTRL1
+#define VCN_JPEG_DB_CTRL1__OFFSET__SHIFT 0x2
+#define VCN_JPEG_DB_CTRL1__EN__SHIFT 0x1e
+#define VCN_JPEG_DB_CTRL1__HIT__SHIFT 0x1f
+#define VCN_JPEG_DB_CTRL1__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_JPEG_DB_CTRL1__EN_MASK 0x40000000L
+#define VCN_JPEG_DB_CTRL1__HIT_MASK 0x80000000L
+//VCN_JPEG_DB_CTRL2
+#define VCN_JPEG_DB_CTRL2__OFFSET__SHIFT 0x2
+#define VCN_JPEG_DB_CTRL2__EN__SHIFT 0x1e
+#define VCN_JPEG_DB_CTRL2__HIT__SHIFT 0x1f
+#define VCN_JPEG_DB_CTRL2__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_JPEG_DB_CTRL2__EN_MASK 0x40000000L
+#define VCN_JPEG_DB_CTRL2__HIT_MASK 0x80000000L
+//VCN_JPEG_DB_CTRL3
+#define VCN_JPEG_DB_CTRL3__OFFSET__SHIFT 0x2
+#define VCN_JPEG_DB_CTRL3__EN__SHIFT 0x1e
+#define VCN_JPEG_DB_CTRL3__HIT__SHIFT 0x1f
+#define VCN_JPEG_DB_CTRL3__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_JPEG_DB_CTRL3__EN_MASK 0x40000000L
+#define VCN_JPEG_DB_CTRL3__HIT_MASK 0x80000000L
+//VCN_JPEG_DB_CTRL4
+#define VCN_JPEG_DB_CTRL4__OFFSET__SHIFT 0x2
+#define VCN_JPEG_DB_CTRL4__EN__SHIFT 0x1e
+#define VCN_JPEG_DB_CTRL4__HIT__SHIFT 0x1f
+#define VCN_JPEG_DB_CTRL4__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_JPEG_DB_CTRL4__EN_MASK 0x40000000L
+#define VCN_JPEG_DB_CTRL4__HIT_MASK 0x80000000L
+//VCN_JPEG_DB_CTRL5
+#define VCN_JPEG_DB_CTRL5__OFFSET__SHIFT 0x2
+#define VCN_JPEG_DB_CTRL5__EN__SHIFT 0x1e
+#define VCN_JPEG_DB_CTRL5__HIT__SHIFT 0x1f
+#define VCN_JPEG_DB_CTRL5__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_JPEG_DB_CTRL5__EN_MASK 0x40000000L
+#define VCN_JPEG_DB_CTRL5__HIT_MASK 0x80000000L
+//VCN_JPEG_DB_CTRL6
+#define VCN_JPEG_DB_CTRL6__OFFSET__SHIFT 0x2
+#define VCN_JPEG_DB_CTRL6__EN__SHIFT 0x1e
+#define VCN_JPEG_DB_CTRL6__HIT__SHIFT 0x1f
+#define VCN_JPEG_DB_CTRL6__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_JPEG_DB_CTRL6__EN_MASK 0x40000000L
+#define VCN_JPEG_DB_CTRL6__HIT_MASK 0x80000000L
+//VCN_JPEG_DB_CTRL7
+#define VCN_JPEG_DB_CTRL7__OFFSET__SHIFT 0x2
+#define VCN_JPEG_DB_CTRL7__EN__SHIFT 0x1e
+#define VCN_JPEG_DB_CTRL7__HIT__SHIFT 0x1f
+#define VCN_JPEG_DB_CTRL7__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_JPEG_DB_CTRL7__EN_MASK 0x40000000L
+#define VCN_JPEG_DB_CTRL7__HIT_MASK 0x80000000L
+//UVD_SCRATCH32
+#define UVD_SCRATCH32__SCRATCH32_DATA__SHIFT 0x0
+#define UVD_SCRATCH32__SCRATCH32_DATA_MASK 0xFFFFFFFFL
+//UVD_VERSION
+#define UVD_VERSION__VARIANT_TYPE__SHIFT 0x0
+#define UVD_VERSION__MINOR_VERSION__SHIFT 0x8
+#define UVD_VERSION__MAJOR_VERSION__SHIFT 0x10
+#define UVD_VERSION__INSTANCE_ID__SHIFT 0x1c
+#define UVD_VERSION__VARIANT_TYPE_MASK 0x000000FFL
+#define UVD_VERSION__MINOR_VERSION_MASK 0x0000FF00L
+#define UVD_VERSION__MAJOR_VERSION_MASK 0x0FFF0000L
+#define UVD_VERSION__INSTANCE_ID_MASK 0xF0000000L
+//VCN_RB_DB_CTRL
+#define VCN_RB_DB_CTRL__OFFSET__SHIFT 0x2
+#define VCN_RB_DB_CTRL__EN__SHIFT 0x1e
+#define VCN_RB_DB_CTRL__HIT__SHIFT 0x1f
+#define VCN_RB_DB_CTRL__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_RB_DB_CTRL__EN_MASK 0x40000000L
+#define VCN_RB_DB_CTRL__HIT_MASK 0x80000000L
+//VCN_JPEG_DB_CTRL
+#define VCN_JPEG_DB_CTRL__OFFSET__SHIFT 0x2
+#define VCN_JPEG_DB_CTRL__EN__SHIFT 0x1e
+#define VCN_JPEG_DB_CTRL__HIT__SHIFT 0x1f
+#define VCN_JPEG_DB_CTRL__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_JPEG_DB_CTRL__EN_MASK 0x40000000L
+#define VCN_JPEG_DB_CTRL__HIT_MASK 0x80000000L
+//VCN_RB1_DB_CTRL
+#define VCN_RB1_DB_CTRL__OFFSET__SHIFT 0x2
+#define VCN_RB1_DB_CTRL__EN__SHIFT 0x1e
+#define VCN_RB1_DB_CTRL__HIT__SHIFT 0x1f
+#define VCN_RB1_DB_CTRL__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_RB1_DB_CTRL__EN_MASK 0x40000000L
+#define VCN_RB1_DB_CTRL__HIT_MASK 0x80000000L
+//VCN_RB2_DB_CTRL
+#define VCN_RB2_DB_CTRL__OFFSET__SHIFT 0x2
+#define VCN_RB2_DB_CTRL__EN__SHIFT 0x1e
+#define VCN_RB2_DB_CTRL__HIT__SHIFT 0x1f
+#define VCN_RB2_DB_CTRL__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_RB2_DB_CTRL__EN_MASK 0x40000000L
+#define VCN_RB2_DB_CTRL__HIT_MASK 0x80000000L
+//VCN_RB3_DB_CTRL
+#define VCN_RB3_DB_CTRL__OFFSET__SHIFT 0x2
+#define VCN_RB3_DB_CTRL__EN__SHIFT 0x1e
+#define VCN_RB3_DB_CTRL__HIT__SHIFT 0x1f
+#define VCN_RB3_DB_CTRL__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_RB3_DB_CTRL__EN_MASK 0x40000000L
+#define VCN_RB3_DB_CTRL__HIT_MASK 0x80000000L
+//VCN_RB4_DB_CTRL
+#define VCN_RB4_DB_CTRL__OFFSET__SHIFT 0x2
+#define VCN_RB4_DB_CTRL__EN__SHIFT 0x1e
+#define VCN_RB4_DB_CTRL__HIT__SHIFT 0x1f
+#define VCN_RB4_DB_CTRL__OFFSET_MASK 0x0FFFFFFCL
+#define VCN_RB4_DB_CTRL__EN_MASK 0x40000000L
+#define VCN_RB4_DB_CTRL__HIT_MASK 0x80000000L
+//VCN_RB_ENABLE
+#define VCN_RB_ENABLE__RB_EN__SHIFT 0x0
+#define VCN_RB_ENABLE__JPEG_RB_EN__SHIFT 0x1
+#define VCN_RB_ENABLE__RB1_EN__SHIFT 0x2
+#define VCN_RB_ENABLE__RB2_EN__SHIFT 0x3
+#define VCN_RB_ENABLE__RB3_EN__SHIFT 0x4
+#define VCN_RB_ENABLE__RB4_EN__SHIFT 0x5
+#define VCN_RB_ENABLE__UMSCH_RB_EN__SHIFT 0x6
+#define VCN_RB_ENABLE__EJPEG_RB_EN__SHIFT 0x7
+#define VCN_RB_ENABLE__AUDIO_RB_EN__SHIFT 0x8
+#define VCN_RB_ENABLE__RB_EN_MASK 0x00000001L
+#define VCN_RB_ENABLE__JPEG_RB_EN_MASK 0x00000002L
+#define VCN_RB_ENABLE__RB1_EN_MASK 0x00000004L
+#define VCN_RB_ENABLE__RB2_EN_MASK 0x00000008L
+#define VCN_RB_ENABLE__RB3_EN_MASK 0x00000010L
+#define VCN_RB_ENABLE__RB4_EN_MASK 0x00000020L
+#define VCN_RB_ENABLE__UMSCH_RB_EN_MASK 0x00000040L
+#define VCN_RB_ENABLE__EJPEG_RB_EN_MASK 0x00000080L
+#define VCN_RB_ENABLE__AUDIO_RB_EN_MASK 0x00000100L
+//VCN_RB_WPTR_CTRL
+#define VCN_RB_WPTR_CTRL__RB_CS_EN__SHIFT 0x0
+#define VCN_RB_WPTR_CTRL__JPEG_CS_EN__SHIFT 0x1
+#define VCN_RB_WPTR_CTRL__RB1_CS_EN__SHIFT 0x2
+#define VCN_RB_WPTR_CTRL__RB2_CS_EN__SHIFT 0x3
+#define VCN_RB_WPTR_CTRL__RB3_CS_EN__SHIFT 0x4
+#define VCN_RB_WPTR_CTRL__RB4_CS_EN__SHIFT 0x5
+#define VCN_RB_WPTR_CTRL__UMSCH_RB_CS_EN__SHIFT 0x6
+#define VCN_RB_WPTR_CTRL__EJPEG_RB_CS_EN__SHIFT 0x7
+#define VCN_RB_WPTR_CTRL__AUDIO_RB_CS_EN__SHIFT 0x8
+#define VCN_RB_WPTR_CTRL__RB_CS_EN_MASK 0x00000001L
+#define VCN_RB_WPTR_CTRL__JPEG_CS_EN_MASK 0x00000002L
+#define VCN_RB_WPTR_CTRL__RB1_CS_EN_MASK 0x00000004L
+#define VCN_RB_WPTR_CTRL__RB2_CS_EN_MASK 0x00000008L
+#define VCN_RB_WPTR_CTRL__RB3_CS_EN_MASK 0x00000010L
+#define VCN_RB_WPTR_CTRL__RB4_CS_EN_MASK 0x00000020L
+#define VCN_RB_WPTR_CTRL__UMSCH_RB_CS_EN_MASK 0x00000040L
+#define VCN_RB_WPTR_CTRL__EJPEG_RB_CS_EN_MASK 0x00000080L
+#define VCN_RB_WPTR_CTRL__AUDIO_RB_CS_EN_MASK 0x00000100L
+//UVD_RB_RPTR
+#define UVD_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_RB_RPTR__RB_RPTR_MASK 0x007FFFF0L
+//UVD_RB_WPTR
+#define UVD_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_RB_WPTR__RB_WPTR_MASK 0x007FFFF0L
+//UVD_RB_RPTR2
+#define UVD_RB_RPTR2__RB_RPTR__SHIFT 0x4
+#define UVD_RB_RPTR2__RB_RPTR_MASK 0x007FFFF0L
+//UVD_RB_WPTR2
+#define UVD_RB_WPTR2__RB_WPTR__SHIFT 0x4
+#define UVD_RB_WPTR2__RB_WPTR_MASK 0x007FFFF0L
+//UVD_RB_RPTR3
+#define UVD_RB_RPTR3__RB_RPTR__SHIFT 0x4
+#define UVD_RB_RPTR3__RB_RPTR_MASK 0x007FFFF0L
+//UVD_RB_WPTR3
+#define UVD_RB_WPTR3__RB_WPTR__SHIFT 0x4
+#define UVD_RB_WPTR3__RB_WPTR_MASK 0x007FFFF0L
+//UVD_RB_RPTR4
+#define UVD_RB_RPTR4__RB_RPTR__SHIFT 0x4
+#define UVD_RB_RPTR4__RB_RPTR_MASK 0x007FFFF0L
+//UVD_RB_WPTR4
+#define UVD_RB_WPTR4__RB_WPTR__SHIFT 0x4
+#define UVD_RB_WPTR4__RB_WPTR_MASK 0x007FFFF0L
+//UVD_OUT_RB_RPTR
+#define UVD_OUT_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_OUT_RB_RPTR__RB_RPTR_MASK 0x007FFFF0L
+//UVD_OUT_RB_WPTR
+#define UVD_OUT_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_OUT_RB_WPTR__RB_WPTR_MASK 0x007FFFF0L
+//UVD_AUDIO_RB_RPTR
+#define UVD_AUDIO_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_AUDIO_RB_RPTR__RB_RPTR_MASK 0x007FFFF0L
+//UVD_AUDIO_RB_WPTR
+#define UVD_AUDIO_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_AUDIO_RB_WPTR__RB_WPTR_MASK 0x007FFFF0L
+//UVD_RBC_RB_RPTR
+#define UVD_RBC_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_RBC_RB_RPTR__RB_RPTR_MASK 0x007FFFF0L
+//UVD_RBC_RB_WPTR
+#define UVD_RBC_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_RBC_RB_WPTR__RB_WPTR_MASK 0x007FFFF0L
+//UVD_DPG_LMA_CTL2
+#define UVD_DPG_LMA_CTL2__DIRECT_ACCESS_SRAM_SEL__SHIFT 0x0
+#define UVD_DPG_LMA_CTL2__FIFO_DIRECT_ACCESS_EN__SHIFT 0x1
+#define UVD_DPG_LMA_CTL2__VID_WRITE_PTR__SHIFT 0x2
+#define UVD_DPG_LMA_CTL2__JPEG_WRITE_PTR__SHIFT 0x9
+#define UVD_DPG_LMA_CTL2__DIRECT_ACCESS_SRAM_SEL_MASK 0x00000001L
+#define UVD_DPG_LMA_CTL2__FIFO_DIRECT_ACCESS_EN_MASK 0x00000002L
+#define UVD_DPG_LMA_CTL2__VID_WRITE_PTR_MASK 0x000001FCL
+#define UVD_DPG_LMA_CTL2__JPEG_WRITE_PTR_MASK 0x0000FE00L
+
+
+// addressBlock: aid_uvd0_mmsch_dec
+//MMSCH_UCODE_ADDR
+#define MMSCH_UCODE_ADDR__UCODE_ADDR__SHIFT 0x2
+#define MMSCH_UCODE_ADDR__UCODE_LOCK__SHIFT 0x1f
+#define MMSCH_UCODE_ADDR__UCODE_ADDR_MASK 0x00003FFCL
+#define MMSCH_UCODE_ADDR__UCODE_LOCK_MASK 0x80000000L
+//MMSCH_UCODE_DATA
+#define MMSCH_UCODE_DATA__UCODE_DATA__SHIFT 0x0
+#define MMSCH_UCODE_DATA__UCODE_DATA_MASK 0xFFFFFFFFL
+//MMSCH_SRAM_ADDR
+#define MMSCH_SRAM_ADDR__SRAM_ADDR__SHIFT 0x2
+#define MMSCH_SRAM_ADDR__SRAM_LOCK__SHIFT 0x1f
+#define MMSCH_SRAM_ADDR__SRAM_ADDR_MASK 0x00001FFCL
+#define MMSCH_SRAM_ADDR__SRAM_LOCK_MASK 0x80000000L
+//MMSCH_SRAM_DATA
+#define MMSCH_SRAM_DATA__SRAM_DATA__SHIFT 0x0
+#define MMSCH_SRAM_DATA__SRAM_DATA_MASK 0xFFFFFFFFL
+//MMSCH_VF_SRAM_OFFSET
+#define MMSCH_VF_SRAM_OFFSET__VF_SRAM_OFFSET__SHIFT 0x2
+#define MMSCH_VF_SRAM_OFFSET__VF_SRAM_NUM_DW_PER_VF__SHIFT 0x10
+#define MMSCH_VF_SRAM_OFFSET__VF_SRAM_OFFSET_MASK 0x00001FFCL
+#define MMSCH_VF_SRAM_OFFSET__VF_SRAM_NUM_DW_PER_VF_MASK 0x00FF0000L
+//MMSCH_DB_SRAM_OFFSET
+#define MMSCH_DB_SRAM_OFFSET__DB_SRAM_OFFSET__SHIFT 0x2
+#define MMSCH_DB_SRAM_OFFSET__DB_SRAM_NUM_ENG__SHIFT 0x10
+#define MMSCH_DB_SRAM_OFFSET__DB_SRAM_NUM_RING_PER_ENG__SHIFT 0x18
+#define MMSCH_DB_SRAM_OFFSET__DB_SRAM_OFFSET_MASK 0x00001FFCL
+#define MMSCH_DB_SRAM_OFFSET__DB_SRAM_NUM_ENG_MASK 0x00FF0000L
+#define MMSCH_DB_SRAM_OFFSET__DB_SRAM_NUM_RING_PER_ENG_MASK 0xFF000000L
+//MMSCH_CTX_SRAM_OFFSET
+#define MMSCH_CTX_SRAM_OFFSET__CTX_SRAM_OFFSET__SHIFT 0x2
+#define MMSCH_CTX_SRAM_OFFSET__CTX_SRAM_SIZE__SHIFT 0x10
+#define MMSCH_CTX_SRAM_OFFSET__CTX_SRAM_OFFSET_MASK 0x00001FFCL
+#define MMSCH_CTX_SRAM_OFFSET__CTX_SRAM_SIZE_MASK 0xFFFF0000L
+//MMSCH_CTL
+#define MMSCH_CTL__P_RUNSTALL__SHIFT 0x0
+#define MMSCH_CTL__P_RESET__SHIFT 0x1
+#define MMSCH_CTL__VFID_FIFO_EN__SHIFT 0x4
+#define MMSCH_CTL__P_LOCK__SHIFT 0x1f
+#define MMSCH_CTL__P_RUNSTALL_MASK 0x00000001L
+#define MMSCH_CTL__P_RESET_MASK 0x00000002L
+#define MMSCH_CTL__VFID_FIFO_EN_MASK 0x00000010L
+#define MMSCH_CTL__P_LOCK_MASK 0x80000000L
+//MMSCH_INTR
+#define MMSCH_INTR__INTR__SHIFT 0x0
+#define MMSCH_INTR__INTR_MASK 0x00001FFFL
+//MMSCH_INTR_ACK
+#define MMSCH_INTR_ACK__INTR__SHIFT 0x0
+#define MMSCH_INTR_ACK__INTR_MASK 0x00001FFFL
+//MMSCH_INTR_STATUS
+#define MMSCH_INTR_STATUS__INTR__SHIFT 0x0
+#define MMSCH_INTR_STATUS__INTR_MASK 0x00001FFFL
+//MMSCH_VF_VMID
+#define MMSCH_VF_VMID__VF_CTX_VMID__SHIFT 0x0
+#define MMSCH_VF_VMID__VF_GPCOM_VMID__SHIFT 0x5
+#define MMSCH_VF_VMID__VF_CTX_VMID_MASK 0x0000001FL
+#define MMSCH_VF_VMID__VF_GPCOM_VMID_MASK 0x000003E0L
+//MMSCH_VF_CTX_ADDR_LO
+#define MMSCH_VF_CTX_ADDR_LO__VF_CTX_ADDR_LO__SHIFT 0x6
+#define MMSCH_VF_CTX_ADDR_LO__VF_CTX_ADDR_LO_MASK 0xFFFFFFC0L
+//MMSCH_VF_CTX_ADDR_HI
+#define MMSCH_VF_CTX_ADDR_HI__VF_CTX_ADDR_HI__SHIFT 0x0
+#define MMSCH_VF_CTX_ADDR_HI__VF_CTX_ADDR_HI_MASK 0xFFFFFFFFL
+//MMSCH_VF_CTX_SIZE
+#define MMSCH_VF_CTX_SIZE__VF_CTX_SIZE__SHIFT 0x0
+#define MMSCH_VF_CTX_SIZE__VF_CTX_SIZE_MASK 0xFFFFFFFFL
+//MMSCH_VF_GPCOM_ADDR_LO
+#define MMSCH_VF_GPCOM_ADDR_LO__VF_GPCOM_ADDR_LO__SHIFT 0x6
+#define MMSCH_VF_GPCOM_ADDR_LO__VF_GPCOM_ADDR_LO_MASK 0xFFFFFFC0L
+//MMSCH_VF_GPCOM_ADDR_HI
+#define MMSCH_VF_GPCOM_ADDR_HI__VF_GPCOM_ADDR_HI__SHIFT 0x0
+#define MMSCH_VF_GPCOM_ADDR_HI__VF_GPCOM_ADDR_HI_MASK 0xFFFFFFFFL
+//MMSCH_VF_GPCOM_SIZE
+#define MMSCH_VF_GPCOM_SIZE__VF_GPCOM_SIZE__SHIFT 0x0
+#define MMSCH_VF_GPCOM_SIZE__VF_GPCOM_SIZE_MASK 0xFFFFFFFFL
+//MMSCH_VF_MAILBOX_HOST
+#define MMSCH_VF_MAILBOX_HOST__DATA__SHIFT 0x0
+#define MMSCH_VF_MAILBOX_HOST__DATA_MASK 0xFFFFFFFFL
+//MMSCH_VF_MAILBOX_RESP
+#define MMSCH_VF_MAILBOX_RESP__RESP__SHIFT 0x0
+#define MMSCH_VF_MAILBOX_RESP__RESP_MASK 0xFFFFFFFFL
+//MMSCH_VF_MAILBOX_0
+#define MMSCH_VF_MAILBOX_0__DATA__SHIFT 0x0
+#define MMSCH_VF_MAILBOX_0__DATA_MASK 0xFFFFFFFFL
+//MMSCH_VF_MAILBOX_0_RESP
+#define MMSCH_VF_MAILBOX_0_RESP__RESP__SHIFT 0x0
+#define MMSCH_VF_MAILBOX_0_RESP__RESP_MASK 0xFFFFFFFFL
+//MMSCH_VF_MAILBOX_1
+#define MMSCH_VF_MAILBOX_1__DATA__SHIFT 0x0
+#define MMSCH_VF_MAILBOX_1__DATA_MASK 0xFFFFFFFFL
+//MMSCH_VF_MAILBOX_1_RESP
+#define MMSCH_VF_MAILBOX_1_RESP__RESP__SHIFT 0x0
+#define MMSCH_VF_MAILBOX_1_RESP__RESP_MASK 0xFFFFFFFFL
+//MMSCH_CNTL
+#define MMSCH_CNTL__CLK_EN__SHIFT 0x0
+#define MMSCH_CNTL__ED_ENABLE__SHIFT 0x1
+#define MMSCH_CNTL__AXI_MAX_BRST_SIZE_IS_4__SHIFT 0x2
+#define MMSCH_CNTL__AXI_40BIT_PIF_ADDR_FIX_EN__SHIFT 0x3
+#define MMSCH_CNTL__PDEBUG_ENABLE__SHIFT 0x4
+#define MMSCH_CNTL__MMSCH_IRQ_ERR__SHIFT 0x5
+#define MMSCH_CNTL__MMSCH_NACK_INTR_EN__SHIFT 0x9
+#define MMSCH_CNTL__MMSCH_DB_BUSY_INTR_EN__SHIFT 0xa
+#define MMSCH_CNTL__PRB_TIMEOUT_VAL__SHIFT 0x14
+#define MMSCH_CNTL__TIMEOUT_DIS__SHIFT 0x1c
+#define MMSCH_CNTL__MMSCH_IDLE__SHIFT 0x1d
+#define MMSCH_CNTL__CLK_EN_MASK 0x00000001L
+#define MMSCH_CNTL__ED_ENABLE_MASK 0x00000002L
+#define MMSCH_CNTL__AXI_MAX_BRST_SIZE_IS_4_MASK 0x00000004L
+#define MMSCH_CNTL__AXI_40BIT_PIF_ADDR_FIX_EN_MASK 0x00000008L
+#define MMSCH_CNTL__PDEBUG_ENABLE_MASK 0x00000010L
+#define MMSCH_CNTL__MMSCH_IRQ_ERR_MASK 0x000001E0L
+#define MMSCH_CNTL__MMSCH_NACK_INTR_EN_MASK 0x00000200L
+#define MMSCH_CNTL__MMSCH_DB_BUSY_INTR_EN_MASK 0x00000400L
+#define MMSCH_CNTL__PRB_TIMEOUT_VAL_MASK 0x0FF00000L
+#define MMSCH_CNTL__TIMEOUT_DIS_MASK 0x10000000L
+#define MMSCH_CNTL__MMSCH_IDLE_MASK 0x20000000L
+//MMSCH_NONCACHE_OFFSET0
+#define MMSCH_NONCACHE_OFFSET0__OFFSET__SHIFT 0x0
+#define MMSCH_NONCACHE_OFFSET0__OFFSET_MASK 0x0FFFFFFFL
+//MMSCH_NONCACHE_SIZE0
+#define MMSCH_NONCACHE_SIZE0__SIZE__SHIFT 0x0
+#define MMSCH_NONCACHE_SIZE0__SIZE_MASK 0x00FFFFFFL
+//MMSCH_NONCACHE_OFFSET1
+#define MMSCH_NONCACHE_OFFSET1__OFFSET__SHIFT 0x0
+#define MMSCH_NONCACHE_OFFSET1__OFFSET_MASK 0x0FFFFFFFL
+//MMSCH_NONCACHE_SIZE1
+#define MMSCH_NONCACHE_SIZE1__SIZE__SHIFT 0x0
+#define MMSCH_NONCACHE_SIZE1__SIZE_MASK 0x00FFFFFFL
+//MMSCH_PROC_STATE1
+#define MMSCH_PROC_STATE1__PC__SHIFT 0x0
+#define MMSCH_PROC_STATE1__PC_MASK 0xFFFFFFFFL
+//MMSCH_LAST_MC_ADDR
+#define MMSCH_LAST_MC_ADDR__MC_ADDR__SHIFT 0x0
+#define MMSCH_LAST_MC_ADDR__RW__SHIFT 0x1f
+#define MMSCH_LAST_MC_ADDR__MC_ADDR_MASK 0x0FFFFFFFL
+#define MMSCH_LAST_MC_ADDR__RW_MASK 0x80000000L
+//MMSCH_LAST_MEM_ACCESS_HI
+#define MMSCH_LAST_MEM_ACCESS_HI__PROC_CMD__SHIFT 0x0
+#define MMSCH_LAST_MEM_ACCESS_HI__FIFO_RPTR__SHIFT 0x8
+#define MMSCH_LAST_MEM_ACCESS_HI__FIFO_WPTR__SHIFT 0xc
+#define MMSCH_LAST_MEM_ACCESS_HI__PROC_CMD_MASK 0x00000007L
+#define MMSCH_LAST_MEM_ACCESS_HI__FIFO_RPTR_MASK 0x00000700L
+#define MMSCH_LAST_MEM_ACCESS_HI__FIFO_WPTR_MASK 0x00007000L
+//MMSCH_LAST_MEM_ACCESS_LO
+#define MMSCH_LAST_MEM_ACCESS_LO__PROC_ADDR__SHIFT 0x0
+#define MMSCH_LAST_MEM_ACCESS_LO__PROC_ADDR_MASK 0xFFFFFFFFL
+//MMSCH_IOV_ACTIVE_FCN_ID
+#define MMSCH_IOV_ACTIVE_FCN_ID__ACTIVE_VF_ID__SHIFT 0x0
+#define MMSCH_IOV_ACTIVE_FCN_ID__ACTIVE_PF_VF__SHIFT 0x1f
+#define MMSCH_IOV_ACTIVE_FCN_ID__ACTIVE_VF_ID_MASK 0x0000001FL
+#define MMSCH_IOV_ACTIVE_FCN_ID__ACTIVE_PF_VF_MASK 0x80000000L
+//MMSCH_SCRATCH_0
+#define MMSCH_SCRATCH_0__SCRATCH_0__SHIFT 0x0
+#define MMSCH_SCRATCH_0__SCRATCH_0_MASK 0xFFFFFFFFL
+//MMSCH_SCRATCH_1
+#define MMSCH_SCRATCH_1__SCRATCH_1__SHIFT 0x0
+#define MMSCH_SCRATCH_1__SCRATCH_1_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_SCH_BLOCK_0
+#define MMSCH_GPUIOV_SCH_BLOCK_0__ID__SHIFT 0x0
+#define MMSCH_GPUIOV_SCH_BLOCK_0__VERSION__SHIFT 0x4
+#define MMSCH_GPUIOV_SCH_BLOCK_0__SIZE__SHIFT 0x8
+#define MMSCH_GPUIOV_SCH_BLOCK_0__ID_MASK 0x0000000FL
+#define MMSCH_GPUIOV_SCH_BLOCK_0__VERSION_MASK 0x000000F0L
+#define MMSCH_GPUIOV_SCH_BLOCK_0__SIZE_MASK 0x0000FF00L
+//MMSCH_GPUIOV_CMD_CONTROL_0
+#define MMSCH_GPUIOV_CMD_CONTROL_0__CMD_TYPE__SHIFT 0x0
+#define MMSCH_GPUIOV_CMD_CONTROL_0__CMD_EXECUTE__SHIFT 0x4
+#define MMSCH_GPUIOV_CMD_CONTROL_0__CMD_EXECUTE_INTR_EN__SHIFT 0x5
+#define MMSCH_GPUIOV_CMD_CONTROL_0__VM_BUSY_INTR_EN__SHIFT 0x6
+#define MMSCH_GPUIOV_CMD_CONTROL_0__FUNCTINO_ID__SHIFT 0x8
+#define MMSCH_GPUIOV_CMD_CONTROL_0__NEXT_FUNCTINO_ID__SHIFT 0x10
+#define MMSCH_GPUIOV_CMD_CONTROL_0__CMD_TYPE_MASK 0x0000000FL
+#define MMSCH_GPUIOV_CMD_CONTROL_0__CMD_EXECUTE_MASK 0x00000010L
+#define MMSCH_GPUIOV_CMD_CONTROL_0__CMD_EXECUTE_INTR_EN_MASK 0x00000020L
+#define MMSCH_GPUIOV_CMD_CONTROL_0__VM_BUSY_INTR_EN_MASK 0x00000040L
+#define MMSCH_GPUIOV_CMD_CONTROL_0__FUNCTINO_ID_MASK 0x0000FF00L
+#define MMSCH_GPUIOV_CMD_CONTROL_0__NEXT_FUNCTINO_ID_MASK 0x00FF0000L
+//MMSCH_GPUIOV_CMD_STATUS_0
+#define MMSCH_GPUIOV_CMD_STATUS_0__CMD_STATUS__SHIFT 0x0
+#define MMSCH_GPUIOV_CMD_STATUS_0__CMD_STATUS_MASK 0x0000000FL
+//MMSCH_GPUIOV_VM_BUSY_STATUS_0
+#define MMSCH_GPUIOV_VM_BUSY_STATUS_0__BUSY__SHIFT 0x0
+#define MMSCH_GPUIOV_VM_BUSY_STATUS_0__BUSY_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_ACTIVE_FCNS_0
+#define MMSCH_GPUIOV_ACTIVE_FCNS_0__ACTIVE_FCNS__SHIFT 0x0
+#define MMSCH_GPUIOV_ACTIVE_FCNS_0__ACTIVE_FCNS_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_ACTIVE_FCN_ID_0
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_0__ID__SHIFT 0x0
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_0__ID_STATUS__SHIFT 0x8
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_0__ID_MASK 0x000000FFL
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_0__ID_STATUS_MASK 0x00000F00L
+//MMSCH_GPUIOV_DW6_0
+#define MMSCH_GPUIOV_DW6_0__DATA__SHIFT 0x0
+#define MMSCH_GPUIOV_DW6_0__DATA_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_DW7_0
+#define MMSCH_GPUIOV_DW7_0__DATA__SHIFT 0x0
+#define MMSCH_GPUIOV_DW7_0__DATA_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_DW8_0
+#define MMSCH_GPUIOV_DW8_0__DATA__SHIFT 0x0
+#define MMSCH_GPUIOV_DW8_0__DATA_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_SCH_BLOCK_1
+#define MMSCH_GPUIOV_SCH_BLOCK_1__ID__SHIFT 0x0
+#define MMSCH_GPUIOV_SCH_BLOCK_1__VERSION__SHIFT 0x4
+#define MMSCH_GPUIOV_SCH_BLOCK_1__SIZE__SHIFT 0x8
+#define MMSCH_GPUIOV_SCH_BLOCK_1__ID_MASK 0x0000000FL
+#define MMSCH_GPUIOV_SCH_BLOCK_1__VERSION_MASK 0x000000F0L
+#define MMSCH_GPUIOV_SCH_BLOCK_1__SIZE_MASK 0x0000FF00L
+//MMSCH_GPUIOV_CMD_CONTROL_1
+#define MMSCH_GPUIOV_CMD_CONTROL_1__CMD_TYPE__SHIFT 0x0
+#define MMSCH_GPUIOV_CMD_CONTROL_1__CMD_EXECUTE__SHIFT 0x4
+#define MMSCH_GPUIOV_CMD_CONTROL_1__CMD_EXECUTE_INTR_EN__SHIFT 0x5
+#define MMSCH_GPUIOV_CMD_CONTROL_1__VM_BUSY_INTR_EN__SHIFT 0x6
+#define MMSCH_GPUIOV_CMD_CONTROL_1__FUNCTINO_ID__SHIFT 0x8
+#define MMSCH_GPUIOV_CMD_CONTROL_1__NEXT_FUNCTINO_ID__SHIFT 0x10
+#define MMSCH_GPUIOV_CMD_CONTROL_1__CMD_TYPE_MASK 0x0000000FL
+#define MMSCH_GPUIOV_CMD_CONTROL_1__CMD_EXECUTE_MASK 0x00000010L
+#define MMSCH_GPUIOV_CMD_CONTROL_1__CMD_EXECUTE_INTR_EN_MASK 0x00000020L
+#define MMSCH_GPUIOV_CMD_CONTROL_1__VM_BUSY_INTR_EN_MASK 0x00000040L
+#define MMSCH_GPUIOV_CMD_CONTROL_1__FUNCTINO_ID_MASK 0x0000FF00L
+#define MMSCH_GPUIOV_CMD_CONTROL_1__NEXT_FUNCTINO_ID_MASK 0x00FF0000L
+//MMSCH_GPUIOV_CMD_STATUS_1
+#define MMSCH_GPUIOV_CMD_STATUS_1__CMD_STATUS__SHIFT 0x0
+#define MMSCH_GPUIOV_CMD_STATUS_1__CMD_STATUS_MASK 0x0000000FL
+//MMSCH_GPUIOV_VM_BUSY_STATUS_1
+#define MMSCH_GPUIOV_VM_BUSY_STATUS_1__BUSY__SHIFT 0x0
+#define MMSCH_GPUIOV_VM_BUSY_STATUS_1__BUSY_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_ACTIVE_FCNS_1
+#define MMSCH_GPUIOV_ACTIVE_FCNS_1__ACTIVE_FCNS__SHIFT 0x0
+#define MMSCH_GPUIOV_ACTIVE_FCNS_1__ACTIVE_FCNS_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_ACTIVE_FCN_ID_1
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_1__ID__SHIFT 0x0
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_1__ID_STATUS__SHIFT 0x8
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_1__ID_MASK 0x000000FFL
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_1__ID_STATUS_MASK 0x00000F00L
+//MMSCH_GPUIOV_DW6_1
+#define MMSCH_GPUIOV_DW6_1__DATA__SHIFT 0x0
+#define MMSCH_GPUIOV_DW6_1__DATA_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_DW7_1
+#define MMSCH_GPUIOV_DW7_1__DATA__SHIFT 0x0
+#define MMSCH_GPUIOV_DW7_1__DATA_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_DW8_1
+#define MMSCH_GPUIOV_DW8_1__DATA__SHIFT 0x0
+#define MMSCH_GPUIOV_DW8_1__DATA_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_CNTXT
+#define MMSCH_GPUIOV_CNTXT__CNTXT_SIZE__SHIFT 0x0
+#define MMSCH_GPUIOV_CNTXT__CNTXT_LOCATION__SHIFT 0x7
+#define MMSCH_GPUIOV_CNTXT__CNTXT_OFFSET__SHIFT 0xa
+#define MMSCH_GPUIOV_CNTXT__CNTXT_SIZE_MASK 0x0000007FL
+#define MMSCH_GPUIOV_CNTXT__CNTXT_LOCATION_MASK 0x00000080L
+#define MMSCH_GPUIOV_CNTXT__CNTXT_OFFSET_MASK 0xFFFFFC00L
+//MMSCH_SCRATCH_2
+#define MMSCH_SCRATCH_2__SCRATCH_2__SHIFT 0x0
+#define MMSCH_SCRATCH_2__SCRATCH_2_MASK 0xFFFFFFFFL
+//MMSCH_SCRATCH_3
+#define MMSCH_SCRATCH_3__SCRATCH_3__SHIFT 0x0
+#define MMSCH_SCRATCH_3__SCRATCH_3_MASK 0xFFFFFFFFL
+//MMSCH_SCRATCH_4
+#define MMSCH_SCRATCH_4__SCRATCH_4__SHIFT 0x0
+#define MMSCH_SCRATCH_4__SCRATCH_4_MASK 0xFFFFFFFFL
+//MMSCH_SCRATCH_5
+#define MMSCH_SCRATCH_5__SCRATCH_5__SHIFT 0x0
+#define MMSCH_SCRATCH_5__SCRATCH_5_MASK 0xFFFFFFFFL
+//MMSCH_SCRATCH_6
+#define MMSCH_SCRATCH_6__SCRATCH_6__SHIFT 0x0
+#define MMSCH_SCRATCH_6__SCRATCH_6_MASK 0xFFFFFFFFL
+//MMSCH_SCRATCH_7
+#define MMSCH_SCRATCH_7__SCRATCH_7__SHIFT 0x0
+#define MMSCH_SCRATCH_7__SCRATCH_7_MASK 0xFFFFFFFFL
+//MMSCH_VFID_FIFO_HEAD_0
+#define MMSCH_VFID_FIFO_HEAD_0__HEAD__SHIFT 0x0
+#define MMSCH_VFID_FIFO_HEAD_0__HEAD_MASK 0x0000003FL
+//MMSCH_VFID_FIFO_TAIL_0
+#define MMSCH_VFID_FIFO_TAIL_0__TAIL__SHIFT 0x0
+#define MMSCH_VFID_FIFO_TAIL_0__TAIL_MASK 0x0000003FL
+//MMSCH_VFID_FIFO_HEAD_1
+#define MMSCH_VFID_FIFO_HEAD_1__HEAD__SHIFT 0x0
+#define MMSCH_VFID_FIFO_HEAD_1__HEAD_MASK 0x0000003FL
+//MMSCH_VFID_FIFO_TAIL_1
+#define MMSCH_VFID_FIFO_TAIL_1__TAIL__SHIFT 0x0
+#define MMSCH_VFID_FIFO_TAIL_1__TAIL_MASK 0x0000003FL
+//MMSCH_NACK_STATUS
+#define MMSCH_NACK_STATUS__WR_NACK_STATUS__SHIFT 0x0
+#define MMSCH_NACK_STATUS__RD_NACK_STATUS__SHIFT 0x2
+#define MMSCH_NACK_STATUS__WR_NACK_STATUS_MASK 0x00000003L
+#define MMSCH_NACK_STATUS__RD_NACK_STATUS_MASK 0x0000000CL
+//MMSCH_VF_MAILBOX0_DATA
+#define MMSCH_VF_MAILBOX0_DATA__DATA__SHIFT 0x0
+#define MMSCH_VF_MAILBOX0_DATA__DATA_MASK 0xFFFFFFFFL
+//MMSCH_VF_MAILBOX1_DATA
+#define MMSCH_VF_MAILBOX1_DATA__DATA__SHIFT 0x0
+#define MMSCH_VF_MAILBOX1_DATA__DATA_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_SCH_BLOCK_IP_0
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_0__ID__SHIFT 0x0
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_0__VERSION__SHIFT 0x4
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_0__SIZE__SHIFT 0x8
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_0__ID_MASK 0x0000000FL
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_0__VERSION_MASK 0x000000F0L
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_0__SIZE_MASK 0x0000FF00L
+//MMSCH_GPUIOV_CMD_STATUS_IP_0
+#define MMSCH_GPUIOV_CMD_STATUS_IP_0__CMD_STATUS__SHIFT 0x0
+#define MMSCH_GPUIOV_CMD_STATUS_IP_0__CMD_STATUS_MASK 0x0000000FL
+//MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_0
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_0__ID__SHIFT 0x0
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_0__ID_STATUS__SHIFT 0x8
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_0__ID_MASK 0x000000FFL
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_0__ID_STATUS_MASK 0x00000F00L
+//MMSCH_GPUIOV_SCH_BLOCK_IP_1
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_1__ID__SHIFT 0x0
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_1__VERSION__SHIFT 0x4
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_1__SIZE__SHIFT 0x8
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_1__ID_MASK 0x0000000FL
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_1__VERSION_MASK 0x000000F0L
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_1__SIZE_MASK 0x0000FF00L
+//MMSCH_GPUIOV_CMD_STATUS_IP_1
+#define MMSCH_GPUIOV_CMD_STATUS_IP_1__CMD_STATUS__SHIFT 0x0
+#define MMSCH_GPUIOV_CMD_STATUS_IP_1__CMD_STATUS_MASK 0x0000000FL
+//MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_1
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_1__ID__SHIFT 0x0
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_1__ID_STATUS__SHIFT 0x8
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_1__ID_MASK 0x000000FFL
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_1__ID_STATUS_MASK 0x00000F00L
+//MMSCH_GPUIOV_CNTXT_IP
+#define MMSCH_GPUIOV_CNTXT_IP__CNTXT_SIZE__SHIFT 0x0
+#define MMSCH_GPUIOV_CNTXT_IP__CNTXT_LOCATION__SHIFT 0x7
+#define MMSCH_GPUIOV_CNTXT_IP__CNTXT_SIZE_MASK 0x0000007FL
+#define MMSCH_GPUIOV_CNTXT_IP__CNTXT_LOCATION_MASK 0x00000080L
+//MMSCH_GPUIOV_SCH_BLOCK_2
+#define MMSCH_GPUIOV_SCH_BLOCK_2__ID__SHIFT 0x0
+#define MMSCH_GPUIOV_SCH_BLOCK_2__VERSION__SHIFT 0x4
+#define MMSCH_GPUIOV_SCH_BLOCK_2__SIZE__SHIFT 0x8
+#define MMSCH_GPUIOV_SCH_BLOCK_2__ID_MASK 0x0000000FL
+#define MMSCH_GPUIOV_SCH_BLOCK_2__VERSION_MASK 0x000000F0L
+#define MMSCH_GPUIOV_SCH_BLOCK_2__SIZE_MASK 0x0000FF00L
+//MMSCH_GPUIOV_CMD_CONTROL_2
+#define MMSCH_GPUIOV_CMD_CONTROL_2__CMD_TYPE__SHIFT 0x0
+#define MMSCH_GPUIOV_CMD_CONTROL_2__CMD_EXECUTE__SHIFT 0x4
+#define MMSCH_GPUIOV_CMD_CONTROL_2__CMD_EXECUTE_INTR_EN__SHIFT 0x5
+#define MMSCH_GPUIOV_CMD_CONTROL_2__VM_BUSY_INTR_EN__SHIFT 0x6
+#define MMSCH_GPUIOV_CMD_CONTROL_2__FUNCTINO_ID__SHIFT 0x8
+#define MMSCH_GPUIOV_CMD_CONTROL_2__NEXT_FUNCTINO_ID__SHIFT 0x10
+#define MMSCH_GPUIOV_CMD_CONTROL_2__CMD_TYPE_MASK 0x0000000FL
+#define MMSCH_GPUIOV_CMD_CONTROL_2__CMD_EXECUTE_MASK 0x00000010L
+#define MMSCH_GPUIOV_CMD_CONTROL_2__CMD_EXECUTE_INTR_EN_MASK 0x00000020L
+#define MMSCH_GPUIOV_CMD_CONTROL_2__VM_BUSY_INTR_EN_MASK 0x00000040L
+#define MMSCH_GPUIOV_CMD_CONTROL_2__FUNCTINO_ID_MASK 0x0000FF00L
+#define MMSCH_GPUIOV_CMD_CONTROL_2__NEXT_FUNCTINO_ID_MASK 0x00FF0000L
+//MMSCH_GPUIOV_CMD_STATUS_2
+#define MMSCH_GPUIOV_CMD_STATUS_2__CMD_STATUS__SHIFT 0x0
+#define MMSCH_GPUIOV_CMD_STATUS_2__CMD_STATUS_MASK 0x0000000FL
+//MMSCH_GPUIOV_VM_BUSY_STATUS_2
+#define MMSCH_GPUIOV_VM_BUSY_STATUS_2__BUSY__SHIFT 0x0
+#define MMSCH_GPUIOV_VM_BUSY_STATUS_2__BUSY_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_ACTIVE_FCNS_2
+#define MMSCH_GPUIOV_ACTIVE_FCNS_2__ACTIVE_FCNS__SHIFT 0x0
+#define MMSCH_GPUIOV_ACTIVE_FCNS_2__ACTIVE_FCNS_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_ACTIVE_FCN_ID_2
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_2__ID__SHIFT 0x0
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_2__ID_STATUS__SHIFT 0x8
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_2__ID_MASK 0x000000FFL
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_2__ID_STATUS_MASK 0x00000F00L
+//MMSCH_GPUIOV_DW6_2
+#define MMSCH_GPUIOV_DW6_2__DATA__SHIFT 0x0
+#define MMSCH_GPUIOV_DW6_2__DATA_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_DW7_2
+#define MMSCH_GPUIOV_DW7_2__DATA__SHIFT 0x0
+#define MMSCH_GPUIOV_DW7_2__DATA_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_DW8_2
+#define MMSCH_GPUIOV_DW8_2__DATA__SHIFT 0x0
+#define MMSCH_GPUIOV_DW8_2__DATA_MASK 0xFFFFFFFFL
+//MMSCH_GPUIOV_SCH_BLOCK_IP_2
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_2__ID__SHIFT 0x0
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_2__VERSION__SHIFT 0x4
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_2__SIZE__SHIFT 0x8
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_2__ID_MASK 0x0000000FL
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_2__VERSION_MASK 0x000000F0L
+#define MMSCH_GPUIOV_SCH_BLOCK_IP_2__SIZE_MASK 0x0000FF00L
+//MMSCH_GPUIOV_CMD_STATUS_IP_2
+#define MMSCH_GPUIOV_CMD_STATUS_IP_2__CMD_STATUS__SHIFT 0x0
+#define MMSCH_GPUIOV_CMD_STATUS_IP_2__CMD_STATUS_MASK 0x0000000FL
+//MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_2
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_2__ID__SHIFT 0x0
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_2__ID_STATUS__SHIFT 0x8
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_2__ID_MASK 0x000000FFL
+#define MMSCH_GPUIOV_ACTIVE_FCN_ID_IP_2__ID_STATUS_MASK 0x00000F00L
+//MMSCH_VFID_FIFO_HEAD_2
+#define MMSCH_VFID_FIFO_HEAD_2__HEAD__SHIFT 0x0
+#define MMSCH_VFID_FIFO_HEAD_2__HEAD_MASK 0x0000003FL
+//MMSCH_VFID_FIFO_TAIL_2
+#define MMSCH_VFID_FIFO_TAIL_2__TAIL__SHIFT 0x0
+#define MMSCH_VFID_FIFO_TAIL_2__TAIL_MASK 0x0000003FL
+//MMSCH_VM_BUSY_STATUS_0
+#define MMSCH_VM_BUSY_STATUS_0__BUSY__SHIFT 0x0
+#define MMSCH_VM_BUSY_STATUS_0__BUSY_MASK 0xFFFFFFFFL
+//MMSCH_VM_BUSY_STATUS_1
+#define MMSCH_VM_BUSY_STATUS_1__BUSY__SHIFT 0x0
+#define MMSCH_VM_BUSY_STATUS_1__BUSY_MASK 0xFFFFFFFFL
+//MMSCH_VM_BUSY_STATUS_2
+#define MMSCH_VM_BUSY_STATUS_2__BUSY__SHIFT 0x0
+#define MMSCH_VM_BUSY_STATUS_2__BUSY_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_uvd0_slmi_adpdec
+//UVD_LMI_MMSCH_NC0_64BIT_BAR_LOW
+#define UVD_LMI_MMSCH_NC0_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC0_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC0_64BIT_BAR_HIGH
+#define UVD_LMI_MMSCH_NC0_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC0_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC1_64BIT_BAR_LOW
+#define UVD_LMI_MMSCH_NC1_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC1_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC1_64BIT_BAR_HIGH
+#define UVD_LMI_MMSCH_NC1_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC1_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC2_64BIT_BAR_LOW
+#define UVD_LMI_MMSCH_NC2_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC2_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC2_64BIT_BAR_HIGH
+#define UVD_LMI_MMSCH_NC2_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC2_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC3_64BIT_BAR_LOW
+#define UVD_LMI_MMSCH_NC3_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC3_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC3_64BIT_BAR_HIGH
+#define UVD_LMI_MMSCH_NC3_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC3_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC4_64BIT_BAR_LOW
+#define UVD_LMI_MMSCH_NC4_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC4_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC4_64BIT_BAR_HIGH
+#define UVD_LMI_MMSCH_NC4_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC4_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC5_64BIT_BAR_LOW
+#define UVD_LMI_MMSCH_NC5_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC5_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC5_64BIT_BAR_HIGH
+#define UVD_LMI_MMSCH_NC5_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC5_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC6_64BIT_BAR_LOW
+#define UVD_LMI_MMSCH_NC6_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC6_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC6_64BIT_BAR_HIGH
+#define UVD_LMI_MMSCH_NC6_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC6_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC7_64BIT_BAR_LOW
+#define UVD_LMI_MMSCH_NC7_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC7_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC7_64BIT_BAR_HIGH
+#define UVD_LMI_MMSCH_NC7_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC7_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_LMI_MMSCH_NC_VMID
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC0_VMID__SHIFT 0x0
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC1_VMID__SHIFT 0x4
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC2_VMID__SHIFT 0x8
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC3_VMID__SHIFT 0xc
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC4_VMID__SHIFT 0x10
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC5_VMID__SHIFT 0x14
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC6_VMID__SHIFT 0x18
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC7_VMID__SHIFT 0x1c
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC0_VMID_MASK 0x0000000FL
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC1_VMID_MASK 0x000000F0L
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC2_VMID_MASK 0x00000F00L
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC3_VMID_MASK 0x0000F000L
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC4_VMID_MASK 0x000F0000L
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC5_VMID_MASK 0x00F00000L
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC6_VMID_MASK 0x0F000000L
+#define UVD_LMI_MMSCH_NC_VMID__MMSCH_NC7_VMID_MASK 0xF0000000L
+//UVD_LMI_MMSCH_CTRL
+#define UVD_LMI_MMSCH_CTRL__MMSCH_DATA_COHERENCY_EN__SHIFT 0x0
+#define UVD_LMI_MMSCH_CTRL__MMSCH_VM__SHIFT 0x1
+#define UVD_LMI_MMSCH_CTRL__PRIV_CLIENT_MMSCH__SHIFT 0x2
+#define UVD_LMI_MMSCH_CTRL__MMSCH_R_MC_SWAP__SHIFT 0x3
+#define UVD_LMI_MMSCH_CTRL__MMSCH_W_MC_SWAP__SHIFT 0x5
+#define UVD_LMI_MMSCH_CTRL__MMSCH_RD__SHIFT 0x7
+#define UVD_LMI_MMSCH_CTRL__MMSCH_WR__SHIFT 0x9
+#define UVD_LMI_MMSCH_CTRL__MMSCH_RD_DROP__SHIFT 0xb
+#define UVD_LMI_MMSCH_CTRL__MMSCH_WR_DROP__SHIFT 0xc
+#define UVD_LMI_MMSCH_CTRL__MMSCH_DATA_COHERENCY_EN_MASK 0x00000001L
+#define UVD_LMI_MMSCH_CTRL__MMSCH_VM_MASK 0x00000002L
+#define UVD_LMI_MMSCH_CTRL__PRIV_CLIENT_MMSCH_MASK 0x00000004L
+#define UVD_LMI_MMSCH_CTRL__MMSCH_R_MC_SWAP_MASK 0x00000018L
+#define UVD_LMI_MMSCH_CTRL__MMSCH_W_MC_SWAP_MASK 0x00000060L
+#define UVD_LMI_MMSCH_CTRL__MMSCH_RD_MASK 0x00000180L
+#define UVD_LMI_MMSCH_CTRL__MMSCH_WR_MASK 0x00000600L
+#define UVD_LMI_MMSCH_CTRL__MMSCH_RD_DROP_MASK 0x00000800L
+#define UVD_LMI_MMSCH_CTRL__MMSCH_WR_DROP_MASK 0x00001000L
+//UVD_MMSCH_LMI_STATUS
+#define UVD_MMSCH_LMI_STATUS__LMI_AXI_MMSCH_UNSUPPORTED_LEN_INT__SHIFT 0x0
+#define UVD_MMSCH_LMI_STATUS__LMI_AXI_MMSCH_UNSUPPORTED_ADR_ALIGN_INT__SHIFT 0x1
+#define UVD_MMSCH_LMI_STATUS__MMSCH_LMI_WRITE_CLEAN__SHIFT 0x2
+#define UVD_MMSCH_LMI_STATUS__AXI_MMSCH_ERR_LEN__SHIFT 0x4
+#define UVD_MMSCH_LMI_STATUS__AXI_MMSCH_ERR_ADDR_LSBS__SHIFT 0x8
+#define UVD_MMSCH_LMI_STATUS__AXI_MMSCH_ERR_AWRITE__SHIFT 0xc
+#define UVD_MMSCH_LMI_STATUS__MMSCH_RD_CLEAN__SHIFT 0xd
+#define UVD_MMSCH_LMI_STATUS__MMSCH_WR_CLEAN__SHIFT 0xe
+#define UVD_MMSCH_LMI_STATUS__LMI_AXI_MMSCH_UNSUPPORTED_LEN_INT_MASK 0x00000001L
+#define UVD_MMSCH_LMI_STATUS__LMI_AXI_MMSCH_UNSUPPORTED_ADR_ALIGN_INT_MASK 0x00000002L
+#define UVD_MMSCH_LMI_STATUS__MMSCH_LMI_WRITE_CLEAN_MASK 0x00000004L
+#define UVD_MMSCH_LMI_STATUS__AXI_MMSCH_ERR_LEN_MASK 0x000000F0L
+#define UVD_MMSCH_LMI_STATUS__AXI_MMSCH_ERR_ADDR_LSBS_MASK 0x00000700L
+#define UVD_MMSCH_LMI_STATUS__AXI_MMSCH_ERR_AWRITE_MASK 0x00001000L
+#define UVD_MMSCH_LMI_STATUS__MMSCH_RD_CLEAN_MASK 0x00002000L
+#define UVD_MMSCH_LMI_STATUS__MMSCH_WR_CLEAN_MASK 0x00004000L
+//VCN_RAS_CNTL_MMSCH
+#define VCN_RAS_CNTL_MMSCH__MMSCH_FATAL_ERROR_EN__SHIFT 0x1
+#define VCN_RAS_CNTL_MMSCH__MMSCH_PMI_EN__SHIFT 0x5
+#define VCN_RAS_CNTL_MMSCH__MMSCH_REARM__SHIFT 0x9
+#define VCN_RAS_CNTL_MMSCH__MMSCH_READY__SHIFT 0x11
+#define VCN_RAS_CNTL_MMSCH__MMSCH_FATAL_ERROR_EN_MASK 0x00000002L
+#define VCN_RAS_CNTL_MMSCH__MMSCH_PMI_EN_MASK 0x00000020L
+#define VCN_RAS_CNTL_MMSCH__MMSCH_REARM_MASK 0x00000200L
+#define VCN_RAS_CNTL_MMSCH__MMSCH_READY_MASK 0x00020000L
+
+
+// addressBlock: aid_uvd0_uvd_jrbc1_uvd_jrbc_dec
+//UVD_JRBC1_UVD_JRBC_RB_WPTR
+#define UVD_JRBC1_UVD_JRBC_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_JRBC1_UVD_JRBC_RB_WPTR__RB_WPTR_MASK 0x007FFFF0L
+//UVD_JRBC1_UVD_JRBC_RB_CNTL
+#define UVD_JRBC1_UVD_JRBC_RB_CNTL__RB_NO_FETCH__SHIFT 0x0
+#define UVD_JRBC1_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN__SHIFT 0x1
+#define UVD_JRBC1_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER__SHIFT 0x4
+#define UVD_JRBC1_UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK 0x00000001L
+#define UVD_JRBC1_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK 0x00000002L
+#define UVD_JRBC1_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER_MASK 0x0007FFF0L
+//UVD_JRBC1_UVD_JRBC_IB_SIZE
+#define UVD_JRBC1_UVD_JRBC_IB_SIZE__IB_SIZE__SHIFT 0x4
+#define UVD_JRBC1_UVD_JRBC_IB_SIZE__IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC1_UVD_JRBC_URGENT_CNTL
+#define UVD_JRBC1_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK__SHIFT 0x0
+#define UVD_JRBC1_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK_MASK 0x00000003L
+//UVD_JRBC1_UVD_JRBC_RB_REF_DATA
+#define UVD_JRBC1_UVD_JRBC_RB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC1_UVD_JRBC_RB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC1_UVD_JRBC_RB_COND_RD_TIMER
+#define UVD_JRBC1_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC1_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC1_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC1_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC1_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC1_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC1_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC1_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC1_UVD_JRBC_SOFT_RESET
+#define UVD_JRBC1_UVD_JRBC_SOFT_RESET__RESET__SHIFT 0x0
+#define UVD_JRBC1_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS__SHIFT 0x11
+#define UVD_JRBC1_UVD_JRBC_SOFT_RESET__RESET_MASK 0x00000001L
+#define UVD_JRBC1_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS_MASK 0x00020000L
+//UVD_JRBC1_UVD_JRBC_STATUS
+#define UVD_JRBC1_UVD_JRBC_STATUS__RB_JOB_DONE__SHIFT 0x0
+#define UVD_JRBC1_UVD_JRBC_STATUS__IB_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC1_UVD_JRBC_STATUS__RB_ILLEGAL_CMD__SHIFT 0x2
+#define UVD_JRBC1_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT__SHIFT 0x3
+#define UVD_JRBC1_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT__SHIFT 0x4
+#define UVD_JRBC1_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT__SHIFT 0x5
+#define UVD_JRBC1_UVD_JRBC_STATUS__IB_ILLEGAL_CMD__SHIFT 0x6
+#define UVD_JRBC1_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT__SHIFT 0x7
+#define UVD_JRBC1_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT__SHIFT 0x8
+#define UVD_JRBC1_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT__SHIFT 0x9
+#define UVD_JRBC1_UVD_JRBC_STATUS__RB_TRAP_STATUS__SHIFT 0xa
+#define UVD_JRBC1_UVD_JRBC_STATUS__PREEMPT_STATUS__SHIFT 0xb
+#define UVD_JRBC1_UVD_JRBC_STATUS__IB_TRAP_STATUS__SHIFT 0xc
+#define UVD_JRBC1_UVD_JRBC_STATUS__INT_EN__SHIFT 0x10
+#define UVD_JRBC1_UVD_JRBC_STATUS__INT_ACK__SHIFT 0x11
+#define UVD_JRBC1_UVD_JRBC_STATUS__RB_JOB_DONE_MASK 0x00000001L
+#define UVD_JRBC1_UVD_JRBC_STATUS__IB_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC1_UVD_JRBC_STATUS__RB_ILLEGAL_CMD_MASK 0x00000004L
+#define UVD_JRBC1_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT_MASK 0x00000008L
+#define UVD_JRBC1_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT_MASK 0x00000010L
+#define UVD_JRBC1_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT_MASK 0x00000020L
+#define UVD_JRBC1_UVD_JRBC_STATUS__IB_ILLEGAL_CMD_MASK 0x00000040L
+#define UVD_JRBC1_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT_MASK 0x00000080L
+#define UVD_JRBC1_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT_MASK 0x00000100L
+#define UVD_JRBC1_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT_MASK 0x00000200L
+#define UVD_JRBC1_UVD_JRBC_STATUS__RB_TRAP_STATUS_MASK 0x00000400L
+#define UVD_JRBC1_UVD_JRBC_STATUS__PREEMPT_STATUS_MASK 0x00000800L
+#define UVD_JRBC1_UVD_JRBC_STATUS__IB_TRAP_STATUS_MASK 0x00001000L
+#define UVD_JRBC1_UVD_JRBC_STATUS__INT_EN_MASK 0x00010000L
+#define UVD_JRBC1_UVD_JRBC_STATUS__INT_ACK_MASK 0x00020000L
+//UVD_JRBC1_UVD_JRBC_RB_RPTR
+#define UVD_JRBC1_UVD_JRBC_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_JRBC1_UVD_JRBC_RB_RPTR__RB_RPTR_MASK 0x007FFFF0L
+//UVD_JRBC1_UVD_JRBC_RB_BUF_STATUS
+#define UVD_JRBC1_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC1_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC1_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC1_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC1_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC1_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC1_UVD_JRBC_IB_BUF_STATUS
+#define UVD_JRBC1_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC1_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC1_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC1_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC1_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC1_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC1_UVD_JRBC_IB_SIZE_UPDATE
+#define UVD_JRBC1_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE__SHIFT 0x4
+#define UVD_JRBC1_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC1_UVD_JRBC_IB_COND_RD_TIMER
+#define UVD_JRBC1_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC1_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC1_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC1_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC1_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC1_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC1_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC1_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC1_UVD_JRBC_IB_REF_DATA
+#define UVD_JRBC1_UVD_JRBC_IB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC1_UVD_JRBC_IB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC1_UVD_JPEG_PREEMPT_CMD
+#define UVD_JRBC1_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN__SHIFT 0x0
+#define UVD_JRBC1_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC1_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD__SHIFT 0x2
+#define UVD_JRBC1_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN_MASK 0x00000001L
+#define UVD_JRBC1_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC1_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD_MASK 0x00000004L
+//UVD_JRBC1_UVD_JPEG_PREEMPT_FENCE_DATA0
+#define UVD_JRBC1_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0__SHIFT 0x0
+#define UVD_JRBC1_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0_MASK 0xFFFFFFFFL
+//UVD_JRBC1_UVD_JPEG_PREEMPT_FENCE_DATA1
+#define UVD_JRBC1_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1__SHIFT 0x0
+#define UVD_JRBC1_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1_MASK 0xFFFFFFFFL
+//UVD_JRBC1_UVD_JRBC_RB_SIZE
+#define UVD_JRBC1_UVD_JRBC_RB_SIZE__RB_SIZE__SHIFT 0x4
+#define UVD_JRBC1_UVD_JRBC_RB_SIZE__RB_SIZE_MASK 0x00FFFFF0L
+//UVD_JRBC1_UVD_JRBC_SCRATCH0
+#define UVD_JRBC1_UVD_JRBC_SCRATCH0__SCRATCH0__SHIFT 0x0
+#define UVD_JRBC1_UVD_JRBC_SCRATCH0__SCRATCH0_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_uvd0_uvd_jrbc2_uvd_jrbc_dec
+//UVD_JRBC2_UVD_JRBC_RB_WPTR
+#define UVD_JRBC2_UVD_JRBC_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_JRBC2_UVD_JRBC_RB_WPTR__RB_WPTR_MASK 0x007FFFF0L
+//UVD_JRBC2_UVD_JRBC_RB_CNTL
+#define UVD_JRBC2_UVD_JRBC_RB_CNTL__RB_NO_FETCH__SHIFT 0x0
+#define UVD_JRBC2_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN__SHIFT 0x1
+#define UVD_JRBC2_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER__SHIFT 0x4
+#define UVD_JRBC2_UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK 0x00000001L
+#define UVD_JRBC2_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK 0x00000002L
+#define UVD_JRBC2_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER_MASK 0x0007FFF0L
+//UVD_JRBC2_UVD_JRBC_IB_SIZE
+#define UVD_JRBC2_UVD_JRBC_IB_SIZE__IB_SIZE__SHIFT 0x4
+#define UVD_JRBC2_UVD_JRBC_IB_SIZE__IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC2_UVD_JRBC_URGENT_CNTL
+#define UVD_JRBC2_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK__SHIFT 0x0
+#define UVD_JRBC2_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK_MASK 0x00000003L
+//UVD_JRBC2_UVD_JRBC_RB_REF_DATA
+#define UVD_JRBC2_UVD_JRBC_RB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC2_UVD_JRBC_RB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC2_UVD_JRBC_RB_COND_RD_TIMER
+#define UVD_JRBC2_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC2_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC2_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC2_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC2_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC2_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC2_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC2_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC2_UVD_JRBC_SOFT_RESET
+#define UVD_JRBC2_UVD_JRBC_SOFT_RESET__RESET__SHIFT 0x0
+#define UVD_JRBC2_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS__SHIFT 0x11
+#define UVD_JRBC2_UVD_JRBC_SOFT_RESET__RESET_MASK 0x00000001L
+#define UVD_JRBC2_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS_MASK 0x00020000L
+//UVD_JRBC2_UVD_JRBC_STATUS
+#define UVD_JRBC2_UVD_JRBC_STATUS__RB_JOB_DONE__SHIFT 0x0
+#define UVD_JRBC2_UVD_JRBC_STATUS__IB_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC2_UVD_JRBC_STATUS__RB_ILLEGAL_CMD__SHIFT 0x2
+#define UVD_JRBC2_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT__SHIFT 0x3
+#define UVD_JRBC2_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT__SHIFT 0x4
+#define UVD_JRBC2_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT__SHIFT 0x5
+#define UVD_JRBC2_UVD_JRBC_STATUS__IB_ILLEGAL_CMD__SHIFT 0x6
+#define UVD_JRBC2_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT__SHIFT 0x7
+#define UVD_JRBC2_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT__SHIFT 0x8
+#define UVD_JRBC2_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT__SHIFT 0x9
+#define UVD_JRBC2_UVD_JRBC_STATUS__RB_TRAP_STATUS__SHIFT 0xa
+#define UVD_JRBC2_UVD_JRBC_STATUS__PREEMPT_STATUS__SHIFT 0xb
+#define UVD_JRBC2_UVD_JRBC_STATUS__IB_TRAP_STATUS__SHIFT 0xc
+#define UVD_JRBC2_UVD_JRBC_STATUS__INT_EN__SHIFT 0x10
+#define UVD_JRBC2_UVD_JRBC_STATUS__INT_ACK__SHIFT 0x11
+#define UVD_JRBC2_UVD_JRBC_STATUS__RB_JOB_DONE_MASK 0x00000001L
+#define UVD_JRBC2_UVD_JRBC_STATUS__IB_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC2_UVD_JRBC_STATUS__RB_ILLEGAL_CMD_MASK 0x00000004L
+#define UVD_JRBC2_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT_MASK 0x00000008L
+#define UVD_JRBC2_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT_MASK 0x00000010L
+#define UVD_JRBC2_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT_MASK 0x00000020L
+#define UVD_JRBC2_UVD_JRBC_STATUS__IB_ILLEGAL_CMD_MASK 0x00000040L
+#define UVD_JRBC2_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT_MASK 0x00000080L
+#define UVD_JRBC2_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT_MASK 0x00000100L
+#define UVD_JRBC2_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT_MASK 0x00000200L
+#define UVD_JRBC2_UVD_JRBC_STATUS__RB_TRAP_STATUS_MASK 0x00000400L
+#define UVD_JRBC2_UVD_JRBC_STATUS__PREEMPT_STATUS_MASK 0x00000800L
+#define UVD_JRBC2_UVD_JRBC_STATUS__IB_TRAP_STATUS_MASK 0x00001000L
+#define UVD_JRBC2_UVD_JRBC_STATUS__INT_EN_MASK 0x00010000L
+#define UVD_JRBC2_UVD_JRBC_STATUS__INT_ACK_MASK 0x00020000L
+//UVD_JRBC2_UVD_JRBC_RB_RPTR
+#define UVD_JRBC2_UVD_JRBC_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_JRBC2_UVD_JRBC_RB_RPTR__RB_RPTR_MASK 0x007FFFF0L
+//UVD_JRBC2_UVD_JRBC_RB_BUF_STATUS
+#define UVD_JRBC2_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC2_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC2_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC2_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC2_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC2_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC2_UVD_JRBC_IB_BUF_STATUS
+#define UVD_JRBC2_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC2_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC2_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC2_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC2_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC2_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC2_UVD_JRBC_IB_SIZE_UPDATE
+#define UVD_JRBC2_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE__SHIFT 0x4
+#define UVD_JRBC2_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC2_UVD_JRBC_IB_COND_RD_TIMER
+#define UVD_JRBC2_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC2_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC2_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC2_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC2_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC2_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC2_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC2_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC2_UVD_JRBC_IB_REF_DATA
+#define UVD_JRBC2_UVD_JRBC_IB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC2_UVD_JRBC_IB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC2_UVD_JPEG_PREEMPT_CMD
+#define UVD_JRBC2_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN__SHIFT 0x0
+#define UVD_JRBC2_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC2_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD__SHIFT 0x2
+#define UVD_JRBC2_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN_MASK 0x00000001L
+#define UVD_JRBC2_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC2_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD_MASK 0x00000004L
+//UVD_JRBC2_UVD_JPEG_PREEMPT_FENCE_DATA0
+#define UVD_JRBC2_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0__SHIFT 0x0
+#define UVD_JRBC2_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0_MASK 0xFFFFFFFFL
+//UVD_JRBC2_UVD_JPEG_PREEMPT_FENCE_DATA1
+#define UVD_JRBC2_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1__SHIFT 0x0
+#define UVD_JRBC2_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1_MASK 0xFFFFFFFFL
+//UVD_JRBC2_UVD_JRBC_RB_SIZE
+#define UVD_JRBC2_UVD_JRBC_RB_SIZE__RB_SIZE__SHIFT 0x4
+#define UVD_JRBC2_UVD_JRBC_RB_SIZE__RB_SIZE_MASK 0x00FFFFF0L
+//UVD_JRBC2_UVD_JRBC_SCRATCH0
+#define UVD_JRBC2_UVD_JRBC_SCRATCH0__SCRATCH0__SHIFT 0x0
+#define UVD_JRBC2_UVD_JRBC_SCRATCH0__SCRATCH0_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_uvd0_uvd_jrbc3_uvd_jrbc_dec
+//UVD_JRBC3_UVD_JRBC_RB_WPTR
+#define UVD_JRBC3_UVD_JRBC_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_JRBC3_UVD_JRBC_RB_WPTR__RB_WPTR_MASK 0x007FFFF0L
+//UVD_JRBC3_UVD_JRBC_RB_CNTL
+#define UVD_JRBC3_UVD_JRBC_RB_CNTL__RB_NO_FETCH__SHIFT 0x0
+#define UVD_JRBC3_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN__SHIFT 0x1
+#define UVD_JRBC3_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER__SHIFT 0x4
+#define UVD_JRBC3_UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK 0x00000001L
+#define UVD_JRBC3_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK 0x00000002L
+#define UVD_JRBC3_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER_MASK 0x0007FFF0L
+//UVD_JRBC3_UVD_JRBC_IB_SIZE
+#define UVD_JRBC3_UVD_JRBC_IB_SIZE__IB_SIZE__SHIFT 0x4
+#define UVD_JRBC3_UVD_JRBC_IB_SIZE__IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC3_UVD_JRBC_URGENT_CNTL
+#define UVD_JRBC3_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK__SHIFT 0x0
+#define UVD_JRBC3_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK_MASK 0x00000003L
+//UVD_JRBC3_UVD_JRBC_RB_REF_DATA
+#define UVD_JRBC3_UVD_JRBC_RB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC3_UVD_JRBC_RB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC3_UVD_JRBC_RB_COND_RD_TIMER
+#define UVD_JRBC3_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC3_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC3_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC3_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC3_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC3_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC3_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC3_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC3_UVD_JRBC_SOFT_RESET
+#define UVD_JRBC3_UVD_JRBC_SOFT_RESET__RESET__SHIFT 0x0
+#define UVD_JRBC3_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS__SHIFT 0x11
+#define UVD_JRBC3_UVD_JRBC_SOFT_RESET__RESET_MASK 0x00000001L
+#define UVD_JRBC3_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS_MASK 0x00020000L
+//UVD_JRBC3_UVD_JRBC_STATUS
+#define UVD_JRBC3_UVD_JRBC_STATUS__RB_JOB_DONE__SHIFT 0x0
+#define UVD_JRBC3_UVD_JRBC_STATUS__IB_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC3_UVD_JRBC_STATUS__RB_ILLEGAL_CMD__SHIFT 0x2
+#define UVD_JRBC3_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT__SHIFT 0x3
+#define UVD_JRBC3_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT__SHIFT 0x4
+#define UVD_JRBC3_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT__SHIFT 0x5
+#define UVD_JRBC3_UVD_JRBC_STATUS__IB_ILLEGAL_CMD__SHIFT 0x6
+#define UVD_JRBC3_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT__SHIFT 0x7
+#define UVD_JRBC3_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT__SHIFT 0x8
+#define UVD_JRBC3_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT__SHIFT 0x9
+#define UVD_JRBC3_UVD_JRBC_STATUS__RB_TRAP_STATUS__SHIFT 0xa
+#define UVD_JRBC3_UVD_JRBC_STATUS__PREEMPT_STATUS__SHIFT 0xb
+#define UVD_JRBC3_UVD_JRBC_STATUS__IB_TRAP_STATUS__SHIFT 0xc
+#define UVD_JRBC3_UVD_JRBC_STATUS__INT_EN__SHIFT 0x10
+#define UVD_JRBC3_UVD_JRBC_STATUS__INT_ACK__SHIFT 0x11
+#define UVD_JRBC3_UVD_JRBC_STATUS__RB_JOB_DONE_MASK 0x00000001L
+#define UVD_JRBC3_UVD_JRBC_STATUS__IB_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC3_UVD_JRBC_STATUS__RB_ILLEGAL_CMD_MASK 0x00000004L
+#define UVD_JRBC3_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT_MASK 0x00000008L
+#define UVD_JRBC3_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT_MASK 0x00000010L
+#define UVD_JRBC3_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT_MASK 0x00000020L
+#define UVD_JRBC3_UVD_JRBC_STATUS__IB_ILLEGAL_CMD_MASK 0x00000040L
+#define UVD_JRBC3_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT_MASK 0x00000080L
+#define UVD_JRBC3_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT_MASK 0x00000100L
+#define UVD_JRBC3_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT_MASK 0x00000200L
+#define UVD_JRBC3_UVD_JRBC_STATUS__RB_TRAP_STATUS_MASK 0x00000400L
+#define UVD_JRBC3_UVD_JRBC_STATUS__PREEMPT_STATUS_MASK 0x00000800L
+#define UVD_JRBC3_UVD_JRBC_STATUS__IB_TRAP_STATUS_MASK 0x00001000L
+#define UVD_JRBC3_UVD_JRBC_STATUS__INT_EN_MASK 0x00010000L
+#define UVD_JRBC3_UVD_JRBC_STATUS__INT_ACK_MASK 0x00020000L
+//UVD_JRBC3_UVD_JRBC_RB_RPTR
+#define UVD_JRBC3_UVD_JRBC_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_JRBC3_UVD_JRBC_RB_RPTR__RB_RPTR_MASK 0x007FFFF0L
+//UVD_JRBC3_UVD_JRBC_RB_BUF_STATUS
+#define UVD_JRBC3_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC3_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC3_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC3_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC3_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC3_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC3_UVD_JRBC_IB_BUF_STATUS
+#define UVD_JRBC3_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC3_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC3_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC3_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC3_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC3_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC3_UVD_JRBC_IB_SIZE_UPDATE
+#define UVD_JRBC3_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE__SHIFT 0x4
+#define UVD_JRBC3_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC3_UVD_JRBC_IB_COND_RD_TIMER
+#define UVD_JRBC3_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC3_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC3_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC3_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC3_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC3_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC3_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC3_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC3_UVD_JRBC_IB_REF_DATA
+#define UVD_JRBC3_UVD_JRBC_IB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC3_UVD_JRBC_IB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC3_UVD_JPEG_PREEMPT_CMD
+#define UVD_JRBC3_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN__SHIFT 0x0
+#define UVD_JRBC3_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC3_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD__SHIFT 0x2
+#define UVD_JRBC3_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN_MASK 0x00000001L
+#define UVD_JRBC3_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC3_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD_MASK 0x00000004L
+//UVD_JRBC3_UVD_JPEG_PREEMPT_FENCE_DATA0
+#define UVD_JRBC3_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0__SHIFT 0x0
+#define UVD_JRBC3_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0_MASK 0xFFFFFFFFL
+//UVD_JRBC3_UVD_JPEG_PREEMPT_FENCE_DATA1
+#define UVD_JRBC3_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1__SHIFT 0x0
+#define UVD_JRBC3_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1_MASK 0xFFFFFFFFL
+//UVD_JRBC3_UVD_JRBC_RB_SIZE
+#define UVD_JRBC3_UVD_JRBC_RB_SIZE__RB_SIZE__SHIFT 0x4
+#define UVD_JRBC3_UVD_JRBC_RB_SIZE__RB_SIZE_MASK 0x00FFFFF0L
+//UVD_JRBC3_UVD_JRBC_SCRATCH0
+#define UVD_JRBC3_UVD_JRBC_SCRATCH0__SCRATCH0__SHIFT 0x0
+#define UVD_JRBC3_UVD_JRBC_SCRATCH0__SCRATCH0_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_uvd0_uvd_jrbc4_uvd_jrbc_dec
+//UVD_JRBC4_UVD_JRBC_RB_WPTR
+#define UVD_JRBC4_UVD_JRBC_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_JRBC4_UVD_JRBC_RB_WPTR__RB_WPTR_MASK 0x007FFFF0L
+//UVD_JRBC4_UVD_JRBC_RB_CNTL
+#define UVD_JRBC4_UVD_JRBC_RB_CNTL__RB_NO_FETCH__SHIFT 0x0
+#define UVD_JRBC4_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN__SHIFT 0x1
+#define UVD_JRBC4_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER__SHIFT 0x4
+#define UVD_JRBC4_UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK 0x00000001L
+#define UVD_JRBC4_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK 0x00000002L
+#define UVD_JRBC4_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER_MASK 0x0007FFF0L
+//UVD_JRBC4_UVD_JRBC_IB_SIZE
+#define UVD_JRBC4_UVD_JRBC_IB_SIZE__IB_SIZE__SHIFT 0x4
+#define UVD_JRBC4_UVD_JRBC_IB_SIZE__IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC4_UVD_JRBC_URGENT_CNTL
+#define UVD_JRBC4_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK__SHIFT 0x0
+#define UVD_JRBC4_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK_MASK 0x00000003L
+//UVD_JRBC4_UVD_JRBC_RB_REF_DATA
+#define UVD_JRBC4_UVD_JRBC_RB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC4_UVD_JRBC_RB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC4_UVD_JRBC_RB_COND_RD_TIMER
+#define UVD_JRBC4_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC4_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC4_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC4_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC4_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC4_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC4_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC4_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC4_UVD_JRBC_SOFT_RESET
+#define UVD_JRBC4_UVD_JRBC_SOFT_RESET__RESET__SHIFT 0x0
+#define UVD_JRBC4_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS__SHIFT 0x11
+#define UVD_JRBC4_UVD_JRBC_SOFT_RESET__RESET_MASK 0x00000001L
+#define UVD_JRBC4_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS_MASK 0x00020000L
+//UVD_JRBC4_UVD_JRBC_STATUS
+#define UVD_JRBC4_UVD_JRBC_STATUS__RB_JOB_DONE__SHIFT 0x0
+#define UVD_JRBC4_UVD_JRBC_STATUS__IB_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC4_UVD_JRBC_STATUS__RB_ILLEGAL_CMD__SHIFT 0x2
+#define UVD_JRBC4_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT__SHIFT 0x3
+#define UVD_JRBC4_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT__SHIFT 0x4
+#define UVD_JRBC4_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT__SHIFT 0x5
+#define UVD_JRBC4_UVD_JRBC_STATUS__IB_ILLEGAL_CMD__SHIFT 0x6
+#define UVD_JRBC4_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT__SHIFT 0x7
+#define UVD_JRBC4_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT__SHIFT 0x8
+#define UVD_JRBC4_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT__SHIFT 0x9
+#define UVD_JRBC4_UVD_JRBC_STATUS__RB_TRAP_STATUS__SHIFT 0xa
+#define UVD_JRBC4_UVD_JRBC_STATUS__PREEMPT_STATUS__SHIFT 0xb
+#define UVD_JRBC4_UVD_JRBC_STATUS__IB_TRAP_STATUS__SHIFT 0xc
+#define UVD_JRBC4_UVD_JRBC_STATUS__INT_EN__SHIFT 0x10
+#define UVD_JRBC4_UVD_JRBC_STATUS__INT_ACK__SHIFT 0x11
+#define UVD_JRBC4_UVD_JRBC_STATUS__RB_JOB_DONE_MASK 0x00000001L
+#define UVD_JRBC4_UVD_JRBC_STATUS__IB_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC4_UVD_JRBC_STATUS__RB_ILLEGAL_CMD_MASK 0x00000004L
+#define UVD_JRBC4_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT_MASK 0x00000008L
+#define UVD_JRBC4_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT_MASK 0x00000010L
+#define UVD_JRBC4_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT_MASK 0x00000020L
+#define UVD_JRBC4_UVD_JRBC_STATUS__IB_ILLEGAL_CMD_MASK 0x00000040L
+#define UVD_JRBC4_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT_MASK 0x00000080L
+#define UVD_JRBC4_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT_MASK 0x00000100L
+#define UVD_JRBC4_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT_MASK 0x00000200L
+#define UVD_JRBC4_UVD_JRBC_STATUS__RB_TRAP_STATUS_MASK 0x00000400L
+#define UVD_JRBC4_UVD_JRBC_STATUS__PREEMPT_STATUS_MASK 0x00000800L
+#define UVD_JRBC4_UVD_JRBC_STATUS__IB_TRAP_STATUS_MASK 0x00001000L
+#define UVD_JRBC4_UVD_JRBC_STATUS__INT_EN_MASK 0x00010000L
+#define UVD_JRBC4_UVD_JRBC_STATUS__INT_ACK_MASK 0x00020000L
+//UVD_JRBC4_UVD_JRBC_RB_RPTR
+#define UVD_JRBC4_UVD_JRBC_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_JRBC4_UVD_JRBC_RB_RPTR__RB_RPTR_MASK 0x007FFFF0L
+//UVD_JRBC4_UVD_JRBC_RB_BUF_STATUS
+#define UVD_JRBC4_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC4_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC4_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC4_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC4_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC4_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC4_UVD_JRBC_IB_BUF_STATUS
+#define UVD_JRBC4_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC4_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC4_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC4_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC4_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC4_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC4_UVD_JRBC_IB_SIZE_UPDATE
+#define UVD_JRBC4_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE__SHIFT 0x4
+#define UVD_JRBC4_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC4_UVD_JRBC_IB_COND_RD_TIMER
+#define UVD_JRBC4_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC4_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC4_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC4_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC4_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC4_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC4_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC4_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC4_UVD_JRBC_IB_REF_DATA
+#define UVD_JRBC4_UVD_JRBC_IB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC4_UVD_JRBC_IB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC4_UVD_JPEG_PREEMPT_CMD
+#define UVD_JRBC4_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN__SHIFT 0x0
+#define UVD_JRBC4_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC4_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD__SHIFT 0x2
+#define UVD_JRBC4_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN_MASK 0x00000001L
+#define UVD_JRBC4_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC4_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD_MASK 0x00000004L
+//UVD_JRBC4_UVD_JPEG_PREEMPT_FENCE_DATA0
+#define UVD_JRBC4_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0__SHIFT 0x0
+#define UVD_JRBC4_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0_MASK 0xFFFFFFFFL
+//UVD_JRBC4_UVD_JPEG_PREEMPT_FENCE_DATA1
+#define UVD_JRBC4_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1__SHIFT 0x0
+#define UVD_JRBC4_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1_MASK 0xFFFFFFFFL
+//UVD_JRBC4_UVD_JRBC_RB_SIZE
+#define UVD_JRBC4_UVD_JRBC_RB_SIZE__RB_SIZE__SHIFT 0x4
+#define UVD_JRBC4_UVD_JRBC_RB_SIZE__RB_SIZE_MASK 0x00FFFFF0L
+//UVD_JRBC4_UVD_JRBC_SCRATCH0
+#define UVD_JRBC4_UVD_JRBC_SCRATCH0__SCRATCH0__SHIFT 0x0
+#define UVD_JRBC4_UVD_JRBC_SCRATCH0__SCRATCH0_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_uvd0_uvd_jrbc5_uvd_jrbc_dec
+//UVD_JRBC5_UVD_JRBC_RB_WPTR
+#define UVD_JRBC5_UVD_JRBC_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_JRBC5_UVD_JRBC_RB_WPTR__RB_WPTR_MASK 0x007FFFF0L
+//UVD_JRBC5_UVD_JRBC_RB_CNTL
+#define UVD_JRBC5_UVD_JRBC_RB_CNTL__RB_NO_FETCH__SHIFT 0x0
+#define UVD_JRBC5_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN__SHIFT 0x1
+#define UVD_JRBC5_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER__SHIFT 0x4
+#define UVD_JRBC5_UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK 0x00000001L
+#define UVD_JRBC5_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK 0x00000002L
+#define UVD_JRBC5_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER_MASK 0x0007FFF0L
+//UVD_JRBC5_UVD_JRBC_IB_SIZE
+#define UVD_JRBC5_UVD_JRBC_IB_SIZE__IB_SIZE__SHIFT 0x4
+#define UVD_JRBC5_UVD_JRBC_IB_SIZE__IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC5_UVD_JRBC_URGENT_CNTL
+#define UVD_JRBC5_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK__SHIFT 0x0
+#define UVD_JRBC5_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK_MASK 0x00000003L
+//UVD_JRBC5_UVD_JRBC_RB_REF_DATA
+#define UVD_JRBC5_UVD_JRBC_RB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC5_UVD_JRBC_RB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC5_UVD_JRBC_RB_COND_RD_TIMER
+#define UVD_JRBC5_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC5_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC5_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC5_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC5_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC5_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC5_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC5_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC5_UVD_JRBC_SOFT_RESET
+#define UVD_JRBC5_UVD_JRBC_SOFT_RESET__RESET__SHIFT 0x0
+#define UVD_JRBC5_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS__SHIFT 0x11
+#define UVD_JRBC5_UVD_JRBC_SOFT_RESET__RESET_MASK 0x00000001L
+#define UVD_JRBC5_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS_MASK 0x00020000L
+//UVD_JRBC5_UVD_JRBC_STATUS
+#define UVD_JRBC5_UVD_JRBC_STATUS__RB_JOB_DONE__SHIFT 0x0
+#define UVD_JRBC5_UVD_JRBC_STATUS__IB_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC5_UVD_JRBC_STATUS__RB_ILLEGAL_CMD__SHIFT 0x2
+#define UVD_JRBC5_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT__SHIFT 0x3
+#define UVD_JRBC5_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT__SHIFT 0x4
+#define UVD_JRBC5_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT__SHIFT 0x5
+#define UVD_JRBC5_UVD_JRBC_STATUS__IB_ILLEGAL_CMD__SHIFT 0x6
+#define UVD_JRBC5_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT__SHIFT 0x7
+#define UVD_JRBC5_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT__SHIFT 0x8
+#define UVD_JRBC5_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT__SHIFT 0x9
+#define UVD_JRBC5_UVD_JRBC_STATUS__RB_TRAP_STATUS__SHIFT 0xa
+#define UVD_JRBC5_UVD_JRBC_STATUS__PREEMPT_STATUS__SHIFT 0xb
+#define UVD_JRBC5_UVD_JRBC_STATUS__IB_TRAP_STATUS__SHIFT 0xc
+#define UVD_JRBC5_UVD_JRBC_STATUS__INT_EN__SHIFT 0x10
+#define UVD_JRBC5_UVD_JRBC_STATUS__INT_ACK__SHIFT 0x11
+#define UVD_JRBC5_UVD_JRBC_STATUS__RB_JOB_DONE_MASK 0x00000001L
+#define UVD_JRBC5_UVD_JRBC_STATUS__IB_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC5_UVD_JRBC_STATUS__RB_ILLEGAL_CMD_MASK 0x00000004L
+#define UVD_JRBC5_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT_MASK 0x00000008L
+#define UVD_JRBC5_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT_MASK 0x00000010L
+#define UVD_JRBC5_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT_MASK 0x00000020L
+#define UVD_JRBC5_UVD_JRBC_STATUS__IB_ILLEGAL_CMD_MASK 0x00000040L
+#define UVD_JRBC5_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT_MASK 0x00000080L
+#define UVD_JRBC5_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT_MASK 0x00000100L
+#define UVD_JRBC5_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT_MASK 0x00000200L
+#define UVD_JRBC5_UVD_JRBC_STATUS__RB_TRAP_STATUS_MASK 0x00000400L
+#define UVD_JRBC5_UVD_JRBC_STATUS__PREEMPT_STATUS_MASK 0x00000800L
+#define UVD_JRBC5_UVD_JRBC_STATUS__IB_TRAP_STATUS_MASK 0x00001000L
+#define UVD_JRBC5_UVD_JRBC_STATUS__INT_EN_MASK 0x00010000L
+#define UVD_JRBC5_UVD_JRBC_STATUS__INT_ACK_MASK 0x00020000L
+//UVD_JRBC5_UVD_JRBC_RB_RPTR
+#define UVD_JRBC5_UVD_JRBC_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_JRBC5_UVD_JRBC_RB_RPTR__RB_RPTR_MASK 0x007FFFF0L
+//UVD_JRBC5_UVD_JRBC_RB_BUF_STATUS
+#define UVD_JRBC5_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC5_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC5_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC5_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC5_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC5_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC5_UVD_JRBC_IB_BUF_STATUS
+#define UVD_JRBC5_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC5_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC5_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC5_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC5_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC5_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC5_UVD_JRBC_IB_SIZE_UPDATE
+#define UVD_JRBC5_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE__SHIFT 0x4
+#define UVD_JRBC5_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC5_UVD_JRBC_IB_COND_RD_TIMER
+#define UVD_JRBC5_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC5_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC5_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC5_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC5_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC5_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC5_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC5_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC5_UVD_JRBC_IB_REF_DATA
+#define UVD_JRBC5_UVD_JRBC_IB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC5_UVD_JRBC_IB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC5_UVD_JPEG_PREEMPT_CMD
+#define UVD_JRBC5_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN__SHIFT 0x0
+#define UVD_JRBC5_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC5_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD__SHIFT 0x2
+#define UVD_JRBC5_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN_MASK 0x00000001L
+#define UVD_JRBC5_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC5_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD_MASK 0x00000004L
+//UVD_JRBC5_UVD_JPEG_PREEMPT_FENCE_DATA0
+#define UVD_JRBC5_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0__SHIFT 0x0
+#define UVD_JRBC5_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0_MASK 0xFFFFFFFFL
+//UVD_JRBC5_UVD_JPEG_PREEMPT_FENCE_DATA1
+#define UVD_JRBC5_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1__SHIFT 0x0
+#define UVD_JRBC5_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1_MASK 0xFFFFFFFFL
+//UVD_JRBC5_UVD_JRBC_RB_SIZE
+#define UVD_JRBC5_UVD_JRBC_RB_SIZE__RB_SIZE__SHIFT 0x4
+#define UVD_JRBC5_UVD_JRBC_RB_SIZE__RB_SIZE_MASK 0x00FFFFF0L
+//UVD_JRBC5_UVD_JRBC_SCRATCH0
+#define UVD_JRBC5_UVD_JRBC_SCRATCH0__SCRATCH0__SHIFT 0x0
+#define UVD_JRBC5_UVD_JRBC_SCRATCH0__SCRATCH0_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_uvd0_uvd_jrbc6_uvd_jrbc_dec
+//UVD_JRBC6_UVD_JRBC_RB_WPTR
+#define UVD_JRBC6_UVD_JRBC_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_JRBC6_UVD_JRBC_RB_WPTR__RB_WPTR_MASK 0x007FFFF0L
+//UVD_JRBC6_UVD_JRBC_RB_CNTL
+#define UVD_JRBC6_UVD_JRBC_RB_CNTL__RB_NO_FETCH__SHIFT 0x0
+#define UVD_JRBC6_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN__SHIFT 0x1
+#define UVD_JRBC6_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER__SHIFT 0x4
+#define UVD_JRBC6_UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK 0x00000001L
+#define UVD_JRBC6_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK 0x00000002L
+#define UVD_JRBC6_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER_MASK 0x0007FFF0L
+//UVD_JRBC6_UVD_JRBC_IB_SIZE
+#define UVD_JRBC6_UVD_JRBC_IB_SIZE__IB_SIZE__SHIFT 0x4
+#define UVD_JRBC6_UVD_JRBC_IB_SIZE__IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC6_UVD_JRBC_URGENT_CNTL
+#define UVD_JRBC6_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK__SHIFT 0x0
+#define UVD_JRBC6_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK_MASK 0x00000003L
+//UVD_JRBC6_UVD_JRBC_RB_REF_DATA
+#define UVD_JRBC6_UVD_JRBC_RB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC6_UVD_JRBC_RB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC6_UVD_JRBC_RB_COND_RD_TIMER
+#define UVD_JRBC6_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC6_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC6_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC6_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC6_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC6_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC6_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC6_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC6_UVD_JRBC_SOFT_RESET
+#define UVD_JRBC6_UVD_JRBC_SOFT_RESET__RESET__SHIFT 0x0
+#define UVD_JRBC6_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS__SHIFT 0x11
+#define UVD_JRBC6_UVD_JRBC_SOFT_RESET__RESET_MASK 0x00000001L
+#define UVD_JRBC6_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS_MASK 0x00020000L
+//UVD_JRBC6_UVD_JRBC_STATUS
+#define UVD_JRBC6_UVD_JRBC_STATUS__RB_JOB_DONE__SHIFT 0x0
+#define UVD_JRBC6_UVD_JRBC_STATUS__IB_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC6_UVD_JRBC_STATUS__RB_ILLEGAL_CMD__SHIFT 0x2
+#define UVD_JRBC6_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT__SHIFT 0x3
+#define UVD_JRBC6_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT__SHIFT 0x4
+#define UVD_JRBC6_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT__SHIFT 0x5
+#define UVD_JRBC6_UVD_JRBC_STATUS__IB_ILLEGAL_CMD__SHIFT 0x6
+#define UVD_JRBC6_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT__SHIFT 0x7
+#define UVD_JRBC6_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT__SHIFT 0x8
+#define UVD_JRBC6_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT__SHIFT 0x9
+#define UVD_JRBC6_UVD_JRBC_STATUS__RB_TRAP_STATUS__SHIFT 0xa
+#define UVD_JRBC6_UVD_JRBC_STATUS__PREEMPT_STATUS__SHIFT 0xb
+#define UVD_JRBC6_UVD_JRBC_STATUS__IB_TRAP_STATUS__SHIFT 0xc
+#define UVD_JRBC6_UVD_JRBC_STATUS__INT_EN__SHIFT 0x10
+#define UVD_JRBC6_UVD_JRBC_STATUS__INT_ACK__SHIFT 0x11
+#define UVD_JRBC6_UVD_JRBC_STATUS__RB_JOB_DONE_MASK 0x00000001L
+#define UVD_JRBC6_UVD_JRBC_STATUS__IB_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC6_UVD_JRBC_STATUS__RB_ILLEGAL_CMD_MASK 0x00000004L
+#define UVD_JRBC6_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT_MASK 0x00000008L
+#define UVD_JRBC6_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT_MASK 0x00000010L
+#define UVD_JRBC6_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT_MASK 0x00000020L
+#define UVD_JRBC6_UVD_JRBC_STATUS__IB_ILLEGAL_CMD_MASK 0x00000040L
+#define UVD_JRBC6_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT_MASK 0x00000080L
+#define UVD_JRBC6_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT_MASK 0x00000100L
+#define UVD_JRBC6_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT_MASK 0x00000200L
+#define UVD_JRBC6_UVD_JRBC_STATUS__RB_TRAP_STATUS_MASK 0x00000400L
+#define UVD_JRBC6_UVD_JRBC_STATUS__PREEMPT_STATUS_MASK 0x00000800L
+#define UVD_JRBC6_UVD_JRBC_STATUS__IB_TRAP_STATUS_MASK 0x00001000L
+#define UVD_JRBC6_UVD_JRBC_STATUS__INT_EN_MASK 0x00010000L
+#define UVD_JRBC6_UVD_JRBC_STATUS__INT_ACK_MASK 0x00020000L
+//UVD_JRBC6_UVD_JRBC_RB_RPTR
+#define UVD_JRBC6_UVD_JRBC_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_JRBC6_UVD_JRBC_RB_RPTR__RB_RPTR_MASK 0x007FFFF0L
+//UVD_JRBC6_UVD_JRBC_RB_BUF_STATUS
+#define UVD_JRBC6_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC6_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC6_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC6_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC6_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC6_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC6_UVD_JRBC_IB_BUF_STATUS
+#define UVD_JRBC6_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC6_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC6_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC6_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC6_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC6_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC6_UVD_JRBC_IB_SIZE_UPDATE
+#define UVD_JRBC6_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE__SHIFT 0x4
+#define UVD_JRBC6_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC6_UVD_JRBC_IB_COND_RD_TIMER
+#define UVD_JRBC6_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC6_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC6_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC6_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC6_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC6_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC6_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC6_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC6_UVD_JRBC_IB_REF_DATA
+#define UVD_JRBC6_UVD_JRBC_IB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC6_UVD_JRBC_IB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC6_UVD_JPEG_PREEMPT_CMD
+#define UVD_JRBC6_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN__SHIFT 0x0
+#define UVD_JRBC6_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC6_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD__SHIFT 0x2
+#define UVD_JRBC6_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN_MASK 0x00000001L
+#define UVD_JRBC6_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC6_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD_MASK 0x00000004L
+//UVD_JRBC6_UVD_JPEG_PREEMPT_FENCE_DATA0
+#define UVD_JRBC6_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0__SHIFT 0x0
+#define UVD_JRBC6_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0_MASK 0xFFFFFFFFL
+//UVD_JRBC6_UVD_JPEG_PREEMPT_FENCE_DATA1
+#define UVD_JRBC6_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1__SHIFT 0x0
+#define UVD_JRBC6_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1_MASK 0xFFFFFFFFL
+//UVD_JRBC6_UVD_JRBC_RB_SIZE
+#define UVD_JRBC6_UVD_JRBC_RB_SIZE__RB_SIZE__SHIFT 0x4
+#define UVD_JRBC6_UVD_JRBC_RB_SIZE__RB_SIZE_MASK 0x00FFFFF0L
+//UVD_JRBC6_UVD_JRBC_SCRATCH0
+#define UVD_JRBC6_UVD_JRBC_SCRATCH0__SCRATCH0__SHIFT 0x0
+#define UVD_JRBC6_UVD_JRBC_SCRATCH0__SCRATCH0_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_uvd0_uvd_jrbc7_uvd_jrbc_dec
+//UVD_JRBC7_UVD_JRBC_RB_WPTR
+#define UVD_JRBC7_UVD_JRBC_RB_WPTR__RB_WPTR__SHIFT 0x4
+#define UVD_JRBC7_UVD_JRBC_RB_WPTR__RB_WPTR_MASK 0x007FFFF0L
+//UVD_JRBC7_UVD_JRBC_RB_CNTL
+#define UVD_JRBC7_UVD_JRBC_RB_CNTL__RB_NO_FETCH__SHIFT 0x0
+#define UVD_JRBC7_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN__SHIFT 0x1
+#define UVD_JRBC7_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER__SHIFT 0x4
+#define UVD_JRBC7_UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK 0x00000001L
+#define UVD_JRBC7_UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK 0x00000002L
+#define UVD_JRBC7_UVD_JRBC_RB_CNTL__RB_PRE_WRITE_TIMER_MASK 0x0007FFF0L
+//UVD_JRBC7_UVD_JRBC_IB_SIZE
+#define UVD_JRBC7_UVD_JRBC_IB_SIZE__IB_SIZE__SHIFT 0x4
+#define UVD_JRBC7_UVD_JRBC_IB_SIZE__IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC7_UVD_JRBC_URGENT_CNTL
+#define UVD_JRBC7_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK__SHIFT 0x0
+#define UVD_JRBC7_UVD_JRBC_URGENT_CNTL__CMD_READ_REQ_PRIORITY_MARK_MASK 0x00000003L
+//UVD_JRBC7_UVD_JRBC_RB_REF_DATA
+#define UVD_JRBC7_UVD_JRBC_RB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC7_UVD_JRBC_RB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC7_UVD_JRBC_RB_COND_RD_TIMER
+#define UVD_JRBC7_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC7_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC7_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC7_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC7_UVD_JRBC_RB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC7_UVD_JRBC_RB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC7_UVD_JRBC_RB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC7_UVD_JRBC_RB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC7_UVD_JRBC_SOFT_RESET
+#define UVD_JRBC7_UVD_JRBC_SOFT_RESET__RESET__SHIFT 0x0
+#define UVD_JRBC7_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS__SHIFT 0x11
+#define UVD_JRBC7_UVD_JRBC_SOFT_RESET__RESET_MASK 0x00000001L
+#define UVD_JRBC7_UVD_JRBC_SOFT_RESET__SCLK_RESET_STATUS_MASK 0x00020000L
+//UVD_JRBC7_UVD_JRBC_STATUS
+#define UVD_JRBC7_UVD_JRBC_STATUS__RB_JOB_DONE__SHIFT 0x0
+#define UVD_JRBC7_UVD_JRBC_STATUS__IB_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC7_UVD_JRBC_STATUS__RB_ILLEGAL_CMD__SHIFT 0x2
+#define UVD_JRBC7_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT__SHIFT 0x3
+#define UVD_JRBC7_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT__SHIFT 0x4
+#define UVD_JRBC7_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT__SHIFT 0x5
+#define UVD_JRBC7_UVD_JRBC_STATUS__IB_ILLEGAL_CMD__SHIFT 0x6
+#define UVD_JRBC7_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT__SHIFT 0x7
+#define UVD_JRBC7_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT__SHIFT 0x8
+#define UVD_JRBC7_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT__SHIFT 0x9
+#define UVD_JRBC7_UVD_JRBC_STATUS__RB_TRAP_STATUS__SHIFT 0xa
+#define UVD_JRBC7_UVD_JRBC_STATUS__PREEMPT_STATUS__SHIFT 0xb
+#define UVD_JRBC7_UVD_JRBC_STATUS__IB_TRAP_STATUS__SHIFT 0xc
+#define UVD_JRBC7_UVD_JRBC_STATUS__INT_EN__SHIFT 0x10
+#define UVD_JRBC7_UVD_JRBC_STATUS__INT_ACK__SHIFT 0x11
+#define UVD_JRBC7_UVD_JRBC_STATUS__RB_JOB_DONE_MASK 0x00000001L
+#define UVD_JRBC7_UVD_JRBC_STATUS__IB_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC7_UVD_JRBC_STATUS__RB_ILLEGAL_CMD_MASK 0x00000004L
+#define UVD_JRBC7_UVD_JRBC_STATUS__RB_COND_REG_RD_TIMEOUT_MASK 0x00000008L
+#define UVD_JRBC7_UVD_JRBC_STATUS__RB_MEM_WR_TIMEOUT_MASK 0x00000010L
+#define UVD_JRBC7_UVD_JRBC_STATUS__RB_MEM_RD_TIMEOUT_MASK 0x00000020L
+#define UVD_JRBC7_UVD_JRBC_STATUS__IB_ILLEGAL_CMD_MASK 0x00000040L
+#define UVD_JRBC7_UVD_JRBC_STATUS__IB_COND_REG_RD_TIMEOUT_MASK 0x00000080L
+#define UVD_JRBC7_UVD_JRBC_STATUS__IB_MEM_WR_TIMEOUT_MASK 0x00000100L
+#define UVD_JRBC7_UVD_JRBC_STATUS__IB_MEM_RD_TIMEOUT_MASK 0x00000200L
+#define UVD_JRBC7_UVD_JRBC_STATUS__RB_TRAP_STATUS_MASK 0x00000400L
+#define UVD_JRBC7_UVD_JRBC_STATUS__PREEMPT_STATUS_MASK 0x00000800L
+#define UVD_JRBC7_UVD_JRBC_STATUS__IB_TRAP_STATUS_MASK 0x00001000L
+#define UVD_JRBC7_UVD_JRBC_STATUS__INT_EN_MASK 0x00010000L
+#define UVD_JRBC7_UVD_JRBC_STATUS__INT_ACK_MASK 0x00020000L
+//UVD_JRBC7_UVD_JRBC_RB_RPTR
+#define UVD_JRBC7_UVD_JRBC_RB_RPTR__RB_RPTR__SHIFT 0x4
+#define UVD_JRBC7_UVD_JRBC_RB_RPTR__RB_RPTR_MASK 0x007FFFF0L
+//UVD_JRBC7_UVD_JRBC_RB_BUF_STATUS
+#define UVD_JRBC7_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC7_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC7_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC7_UVD_JRBC_RB_BUF_STATUS__RB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC7_UVD_JRBC_RB_BUF_STATUS__RB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC7_UVD_JRBC_RB_BUF_STATUS__RB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC7_UVD_JRBC_IB_BUF_STATUS
+#define UVD_JRBC7_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID__SHIFT 0x0
+#define UVD_JRBC7_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR__SHIFT 0x10
+#define UVD_JRBC7_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR__SHIFT 0x18
+#define UVD_JRBC7_UVD_JRBC_IB_BUF_STATUS__IB_BUF_VALID_MASK 0x0000FFFFL
+#define UVD_JRBC7_UVD_JRBC_IB_BUF_STATUS__IB_BUF_RD_ADDR_MASK 0x000F0000L
+#define UVD_JRBC7_UVD_JRBC_IB_BUF_STATUS__IB_BUF_WR_ADDR_MASK 0x03000000L
+//UVD_JRBC7_UVD_JRBC_IB_SIZE_UPDATE
+#define UVD_JRBC7_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE__SHIFT 0x4
+#define UVD_JRBC7_UVD_JRBC_IB_SIZE_UPDATE__REMAIN_IB_SIZE_MASK 0x007FFFF0L
+//UVD_JRBC7_UVD_JRBC_IB_COND_RD_TIMER
+#define UVD_JRBC7_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT__SHIFT 0x0
+#define UVD_JRBC7_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT__SHIFT 0x10
+#define UVD_JRBC7_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN__SHIFT 0x18
+#define UVD_JRBC7_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN__SHIFT 0x19
+#define UVD_JRBC7_UVD_JRBC_IB_COND_RD_TIMER__RETRY_TIMER_CNT_MASK 0x0000FFFFL
+#define UVD_JRBC7_UVD_JRBC_IB_COND_RD_TIMER__RETRY_INTERVAL_CNT_MASK 0x00FF0000L
+#define UVD_JRBC7_UVD_JRBC_IB_COND_RD_TIMER__CONTINUOUS_POLL_EN_MASK 0x01000000L
+#define UVD_JRBC7_UVD_JRBC_IB_COND_RD_TIMER__MEM_TIMEOUT_EN_MASK 0x02000000L
+//UVD_JRBC7_UVD_JRBC_IB_REF_DATA
+#define UVD_JRBC7_UVD_JRBC_IB_REF_DATA__REF_DATA__SHIFT 0x0
+#define UVD_JRBC7_UVD_JRBC_IB_REF_DATA__REF_DATA_MASK 0xFFFFFFFFL
+//UVD_JRBC7_UVD_JPEG_PREEMPT_CMD
+#define UVD_JRBC7_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN__SHIFT 0x0
+#define UVD_JRBC7_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE__SHIFT 0x1
+#define UVD_JRBC7_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD__SHIFT 0x2
+#define UVD_JRBC7_UVD_JPEG_PREEMPT_CMD__PREEMPT_EN_MASK 0x00000001L
+#define UVD_JRBC7_UVD_JPEG_PREEMPT_CMD__WAIT_JPEG_JOB_DONE_MASK 0x00000002L
+#define UVD_JRBC7_UVD_JPEG_PREEMPT_CMD__PREEMPT_FENCE_CMD_MASK 0x00000004L
+//UVD_JRBC7_UVD_JPEG_PREEMPT_FENCE_DATA0
+#define UVD_JRBC7_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0__SHIFT 0x0
+#define UVD_JRBC7_UVD_JPEG_PREEMPT_FENCE_DATA0__PREEMPT_FENCE_DATA0_MASK 0xFFFFFFFFL
+//UVD_JRBC7_UVD_JPEG_PREEMPT_FENCE_DATA1
+#define UVD_JRBC7_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1__SHIFT 0x0
+#define UVD_JRBC7_UVD_JPEG_PREEMPT_FENCE_DATA1__PREEMPT_FENCE_DATA1_MASK 0xFFFFFFFFL
+//UVD_JRBC7_UVD_JRBC_RB_SIZE
+#define UVD_JRBC7_UVD_JRBC_RB_SIZE__RB_SIZE__SHIFT 0x4
+#define UVD_JRBC7_UVD_JRBC_RB_SIZE__RB_SIZE_MASK 0x00FFFFF0L
+//UVD_JRBC7_UVD_JRBC_SCRATCH0
+#define UVD_JRBC7_UVD_JRBC_SCRATCH0__SCRATCH0__SHIFT 0x0
+#define UVD_JRBC7_UVD_JRBC_SCRATCH0__SCRATCH0_MASK 0xFFFFFFFFL
+
+
+// addressBlock: aid_uvd0_uvd_jmi1_uvd_jmi_dec
+//UVD_JMI1_UVD_JPEG_DEC_PF_CTRL
+#define UVD_JMI1_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS__SHIFT 0x0
+#define UVD_JMI1_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING__SHIFT 0x1
+#define UVD_JMI1_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS_MASK 0x00000001L
+#define UVD_JMI1_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING_MASK 0x00000002L
+//UVD_JMI1_UVD_LMI_JRBC_CTRL
+#define UVD_JMI1_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI1_UVD_LMI_JRBC_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI1_UVD_LMI_JRBC_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI1_UVD_LMI_JRBC_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI1_UVD_LMI_JRBC_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI1_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI1_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI1_UVD_LMI_JRBC_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI1_UVD_LMI_JRBC_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI1_UVD_LMI_JRBC_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI1_UVD_LMI_JRBC_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI1_UVD_LMI_JPEG_CTRL
+#define UVD_JMI1_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI1_UVD_LMI_JPEG_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI1_UVD_LMI_JPEG_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI1_UVD_LMI_JPEG_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI1_UVD_LMI_JPEG_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI1_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI1_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI1_UVD_LMI_JPEG_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI1_UVD_LMI_JPEG_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI1_UVD_LMI_JPEG_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI1_UVD_LMI_JPEG_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI1_JPEG_LMI_DROP
+#define UVD_JMI1_JPEG_LMI_DROP__JPEG_WR_DROP__SHIFT 0x0
+#define UVD_JMI1_JPEG_LMI_DROP__JRBC_WR_DROP__SHIFT 0x1
+#define UVD_JMI1_JPEG_LMI_DROP__JPEG_RD_DROP__SHIFT 0x2
+#define UVD_JMI1_JPEG_LMI_DROP__JRBC_RD_DROP__SHIFT 0x3
+#define UVD_JMI1_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP__SHIFT 0x4
+#define UVD_JMI1_JPEG_LMI_DROP__JPEG_WR_DROP_MASK 0x00000001L
+#define UVD_JMI1_JPEG_LMI_DROP__JRBC_WR_DROP_MASK 0x00000002L
+#define UVD_JMI1_JPEG_LMI_DROP__JPEG_RD_DROP_MASK 0x00000004L
+#define UVD_JMI1_JPEG_LMI_DROP__JRBC_RD_DROP_MASK 0x00000008L
+#define UVD_JMI1_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP_MASK 0x00000010L
+//UVD_JMI1_UVD_LMI_JRBC_IB_VMID
+#define UVD_JMI1_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID__SHIFT 0x4
+#define UVD_JMI1_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI1_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI1_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI1_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI1_UVD_LMI_JRBC_RB_VMID
+#define UVD_JMI1_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID__SHIFT 0x4
+#define UVD_JMI1_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI1_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI1_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI1_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI1_UVD_LMI_JPEG_VMID
+#define UVD_JMI1_UVD_LMI_JPEG_VMID__JPEG_RD_VMID__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JPEG_VMID__JPEG_WR_VMID__SHIFT 0x4
+#define UVD_JMI1_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID__SHIFT 0x8
+#define UVD_JMI1_UVD_LMI_JPEG_VMID__JPEG_RD_VMID_MASK 0x0000000FL
+#define UVD_JMI1_UVD_LMI_JPEG_VMID__JPEG_WR_VMID_MASK 0x000000F0L
+#define UVD_JMI1_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID_MASK 0x00000F00L
+//UVD_JMI1_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW
+#define UVD_JMI1_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH
+#define UVD_JMI1_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JRBC_RB_64BIT_BAR_LOW
+#define UVD_JMI1_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH
+#define UVD_JMI1_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI1_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI1_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JPEG_PREEMPT_VMID
+#define UVD_JMI1_UVD_LMI_JPEG_PREEMPT_VMID__VMID__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JPEG_PREEMPT_VMID__VMID_MASK 0x0000000FL
+//UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP__SHIFT 0x0
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP__SHIFT 0x2
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP__SHIFT 0x4
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP__SHIFT 0x6
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP__SHIFT 0x8
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP__SHIFT 0xa
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP__SHIFT 0xc
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP__SHIFT 0xe
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP__SHIFT 0x10
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP_MASK 0x00000003L
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP_MASK 0x0000000CL
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP_MASK 0x00000030L
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP_MASK 0x000000C0L
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP_MASK 0x00000300L
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP_MASK 0x00000C00L
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP_MASK 0x00003000L
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP_MASK 0x0000C000L
+#define UVD_JMI1_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP_MASK 0x00030000L
+//UVD_JMI1_UVD_JMI_ATOMIC_CNTL
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en__SHIFT 0x0
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL__atomic_max_burst__SHIFT 0x1
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop__SHIFT 0x5
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en__SHIFT 0x6
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG__SHIFT 0x7
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE__SHIFT 0xb
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en_MASK 0x00000001L
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL__atomic_max_burst_MASK 0x0000001EL
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop_MASK 0x00000020L
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en_MASK 0x00000040L
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG_MASK 0x00000780L
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE_MASK 0x00000800L
+//UVD_JMI1_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW
+#define UVD_JMI1_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI1_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI1_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI1_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JPEG_READ_64BIT_BAR_LOW
+#define UVD_JMI1_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH
+#define UVD_JMI1_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW
+#define UVD_JMI1_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI1_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JRBC_IB_64BIT_BAR_LOW
+#define UVD_JMI1_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH
+#define UVD_JMI1_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI1_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI1_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI1_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI1_UVD_JMI_ATOMIC_CNTL2
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap__SHIFT 0x10
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP__SHIFT 0x18
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap_MASK 0x00FF0000L
+#define UVD_JMI1_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP_MASK 0xFF000000L
+
+
+// addressBlock: aid_uvd0_uvd_jmi2_uvd_jmi_dec
+//UVD_JMI2_UVD_JPEG_DEC_PF_CTRL
+#define UVD_JMI2_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS__SHIFT 0x0
+#define UVD_JMI2_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING__SHIFT 0x1
+#define UVD_JMI2_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS_MASK 0x00000001L
+#define UVD_JMI2_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING_MASK 0x00000002L
+//UVD_JMI2_UVD_LMI_JRBC_CTRL
+#define UVD_JMI2_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI2_UVD_LMI_JRBC_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI2_UVD_LMI_JRBC_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI2_UVD_LMI_JRBC_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI2_UVD_LMI_JRBC_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI2_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI2_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI2_UVD_LMI_JRBC_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI2_UVD_LMI_JRBC_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI2_UVD_LMI_JRBC_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI2_UVD_LMI_JRBC_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI2_UVD_LMI_JPEG_CTRL
+#define UVD_JMI2_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI2_UVD_LMI_JPEG_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI2_UVD_LMI_JPEG_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI2_UVD_LMI_JPEG_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI2_UVD_LMI_JPEG_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI2_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI2_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI2_UVD_LMI_JPEG_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI2_UVD_LMI_JPEG_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI2_UVD_LMI_JPEG_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI2_UVD_LMI_JPEG_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI2_JPEG_LMI_DROP
+#define UVD_JMI2_JPEG_LMI_DROP__JPEG_WR_DROP__SHIFT 0x0
+#define UVD_JMI2_JPEG_LMI_DROP__JRBC_WR_DROP__SHIFT 0x1
+#define UVD_JMI2_JPEG_LMI_DROP__JPEG_RD_DROP__SHIFT 0x2
+#define UVD_JMI2_JPEG_LMI_DROP__JRBC_RD_DROP__SHIFT 0x3
+#define UVD_JMI2_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP__SHIFT 0x4
+#define UVD_JMI2_JPEG_LMI_DROP__JPEG_WR_DROP_MASK 0x00000001L
+#define UVD_JMI2_JPEG_LMI_DROP__JRBC_WR_DROP_MASK 0x00000002L
+#define UVD_JMI2_JPEG_LMI_DROP__JPEG_RD_DROP_MASK 0x00000004L
+#define UVD_JMI2_JPEG_LMI_DROP__JRBC_RD_DROP_MASK 0x00000008L
+#define UVD_JMI2_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP_MASK 0x00000010L
+//UVD_JMI2_UVD_LMI_JRBC_IB_VMID
+#define UVD_JMI2_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID__SHIFT 0x4
+#define UVD_JMI2_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI2_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI2_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI2_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI2_UVD_LMI_JRBC_RB_VMID
+#define UVD_JMI2_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID__SHIFT 0x4
+#define UVD_JMI2_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI2_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI2_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI2_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI2_UVD_LMI_JPEG_VMID
+#define UVD_JMI2_UVD_LMI_JPEG_VMID__JPEG_RD_VMID__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JPEG_VMID__JPEG_WR_VMID__SHIFT 0x4
+#define UVD_JMI2_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID__SHIFT 0x8
+#define UVD_JMI2_UVD_LMI_JPEG_VMID__JPEG_RD_VMID_MASK 0x0000000FL
+#define UVD_JMI2_UVD_LMI_JPEG_VMID__JPEG_WR_VMID_MASK 0x000000F0L
+#define UVD_JMI2_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID_MASK 0x00000F00L
+//UVD_JMI2_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW
+#define UVD_JMI2_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH
+#define UVD_JMI2_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JRBC_RB_64BIT_BAR_LOW
+#define UVD_JMI2_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH
+#define UVD_JMI2_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI2_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI2_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JPEG_PREEMPT_VMID
+#define UVD_JMI2_UVD_LMI_JPEG_PREEMPT_VMID__VMID__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JPEG_PREEMPT_VMID__VMID_MASK 0x0000000FL
+//UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP__SHIFT 0x0
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP__SHIFT 0x2
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP__SHIFT 0x4
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP__SHIFT 0x6
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP__SHIFT 0x8
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP__SHIFT 0xa
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP__SHIFT 0xc
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP__SHIFT 0xe
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP__SHIFT 0x10
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP_MASK 0x00000003L
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP_MASK 0x0000000CL
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP_MASK 0x00000030L
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP_MASK 0x000000C0L
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP_MASK 0x00000300L
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP_MASK 0x00000C00L
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP_MASK 0x00003000L
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP_MASK 0x0000C000L
+#define UVD_JMI2_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP_MASK 0x00030000L
+//UVD_JMI2_UVD_JMI_ATOMIC_CNTL
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en__SHIFT 0x0
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL__atomic_max_burst__SHIFT 0x1
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop__SHIFT 0x5
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en__SHIFT 0x6
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG__SHIFT 0x7
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE__SHIFT 0xb
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en_MASK 0x00000001L
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL__atomic_max_burst_MASK 0x0000001EL
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop_MASK 0x00000020L
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en_MASK 0x00000040L
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG_MASK 0x00000780L
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE_MASK 0x00000800L
+//UVD_JMI2_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW
+#define UVD_JMI2_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI2_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI2_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI2_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JPEG_READ_64BIT_BAR_LOW
+#define UVD_JMI2_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH
+#define UVD_JMI2_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW
+#define UVD_JMI2_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI2_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JRBC_IB_64BIT_BAR_LOW
+#define UVD_JMI2_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH
+#define UVD_JMI2_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI2_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI2_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI2_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI2_UVD_JMI_ATOMIC_CNTL2
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap__SHIFT 0x10
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP__SHIFT 0x18
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap_MASK 0x00FF0000L
+#define UVD_JMI2_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP_MASK 0xFF000000L
+
+
+// addressBlock: aid_uvd0_uvd_jmi3_uvd_jmi_dec
+//UVD_JMI3_UVD_JPEG_DEC_PF_CTRL
+#define UVD_JMI3_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS__SHIFT 0x0
+#define UVD_JMI3_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING__SHIFT 0x1
+#define UVD_JMI3_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS_MASK 0x00000001L
+#define UVD_JMI3_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING_MASK 0x00000002L
+//UVD_JMI3_UVD_LMI_JRBC_CTRL
+#define UVD_JMI3_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI3_UVD_LMI_JRBC_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI3_UVD_LMI_JRBC_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI3_UVD_LMI_JRBC_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI3_UVD_LMI_JRBC_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI3_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI3_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI3_UVD_LMI_JRBC_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI3_UVD_LMI_JRBC_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI3_UVD_LMI_JRBC_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI3_UVD_LMI_JRBC_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI3_UVD_LMI_JPEG_CTRL
+#define UVD_JMI3_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI3_UVD_LMI_JPEG_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI3_UVD_LMI_JPEG_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI3_UVD_LMI_JPEG_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI3_UVD_LMI_JPEG_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI3_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI3_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI3_UVD_LMI_JPEG_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI3_UVD_LMI_JPEG_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI3_UVD_LMI_JPEG_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI3_UVD_LMI_JPEG_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI3_JPEG_LMI_DROP
+#define UVD_JMI3_JPEG_LMI_DROP__JPEG_WR_DROP__SHIFT 0x0
+#define UVD_JMI3_JPEG_LMI_DROP__JRBC_WR_DROP__SHIFT 0x1
+#define UVD_JMI3_JPEG_LMI_DROP__JPEG_RD_DROP__SHIFT 0x2
+#define UVD_JMI3_JPEG_LMI_DROP__JRBC_RD_DROP__SHIFT 0x3
+#define UVD_JMI3_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP__SHIFT 0x4
+#define UVD_JMI3_JPEG_LMI_DROP__JPEG_WR_DROP_MASK 0x00000001L
+#define UVD_JMI3_JPEG_LMI_DROP__JRBC_WR_DROP_MASK 0x00000002L
+#define UVD_JMI3_JPEG_LMI_DROP__JPEG_RD_DROP_MASK 0x00000004L
+#define UVD_JMI3_JPEG_LMI_DROP__JRBC_RD_DROP_MASK 0x00000008L
+#define UVD_JMI3_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP_MASK 0x00000010L
+//UVD_JMI3_UVD_LMI_JRBC_IB_VMID
+#define UVD_JMI3_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID__SHIFT 0x4
+#define UVD_JMI3_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI3_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI3_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI3_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI3_UVD_LMI_JRBC_RB_VMID
+#define UVD_JMI3_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID__SHIFT 0x4
+#define UVD_JMI3_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI3_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI3_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI3_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI3_UVD_LMI_JPEG_VMID
+#define UVD_JMI3_UVD_LMI_JPEG_VMID__JPEG_RD_VMID__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JPEG_VMID__JPEG_WR_VMID__SHIFT 0x4
+#define UVD_JMI3_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID__SHIFT 0x8
+#define UVD_JMI3_UVD_LMI_JPEG_VMID__JPEG_RD_VMID_MASK 0x0000000FL
+#define UVD_JMI3_UVD_LMI_JPEG_VMID__JPEG_WR_VMID_MASK 0x000000F0L
+#define UVD_JMI3_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID_MASK 0x00000F00L
+//UVD_JMI3_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW
+#define UVD_JMI3_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH
+#define UVD_JMI3_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JRBC_RB_64BIT_BAR_LOW
+#define UVD_JMI3_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH
+#define UVD_JMI3_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI3_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI3_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JPEG_PREEMPT_VMID
+#define UVD_JMI3_UVD_LMI_JPEG_PREEMPT_VMID__VMID__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JPEG_PREEMPT_VMID__VMID_MASK 0x0000000FL
+//UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP__SHIFT 0x0
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP__SHIFT 0x2
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP__SHIFT 0x4
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP__SHIFT 0x6
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP__SHIFT 0x8
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP__SHIFT 0xa
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP__SHIFT 0xc
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP__SHIFT 0xe
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP__SHIFT 0x10
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP_MASK 0x00000003L
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP_MASK 0x0000000CL
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP_MASK 0x00000030L
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP_MASK 0x000000C0L
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP_MASK 0x00000300L
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP_MASK 0x00000C00L
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP_MASK 0x00003000L
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP_MASK 0x0000C000L
+#define UVD_JMI3_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP_MASK 0x00030000L
+//UVD_JMI3_UVD_JMI_ATOMIC_CNTL
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en__SHIFT 0x0
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL__atomic_max_burst__SHIFT 0x1
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop__SHIFT 0x5
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en__SHIFT 0x6
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG__SHIFT 0x7
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE__SHIFT 0xb
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en_MASK 0x00000001L
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL__atomic_max_burst_MASK 0x0000001EL
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop_MASK 0x00000020L
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en_MASK 0x00000040L
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG_MASK 0x00000780L
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE_MASK 0x00000800L
+//UVD_JMI3_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW
+#define UVD_JMI3_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI3_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI3_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI3_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JPEG_READ_64BIT_BAR_LOW
+#define UVD_JMI3_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH
+#define UVD_JMI3_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW
+#define UVD_JMI3_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI3_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JRBC_IB_64BIT_BAR_LOW
+#define UVD_JMI3_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH
+#define UVD_JMI3_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI3_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI3_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI3_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI3_UVD_JMI_ATOMIC_CNTL2
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap__SHIFT 0x10
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP__SHIFT 0x18
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap_MASK 0x00FF0000L
+#define UVD_JMI3_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP_MASK 0xFF000000L
+
+
+// addressBlock: aid_uvd0_uvd_jmi4_uvd_jmi_dec
+//UVD_JMI4_UVD_JPEG_DEC_PF_CTRL
+#define UVD_JMI4_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS__SHIFT 0x0
+#define UVD_JMI4_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING__SHIFT 0x1
+#define UVD_JMI4_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS_MASK 0x00000001L
+#define UVD_JMI4_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING_MASK 0x00000002L
+//UVD_JMI4_UVD_LMI_JRBC_CTRL
+#define UVD_JMI4_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI4_UVD_LMI_JRBC_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI4_UVD_LMI_JRBC_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI4_UVD_LMI_JRBC_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI4_UVD_LMI_JRBC_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI4_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI4_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI4_UVD_LMI_JRBC_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI4_UVD_LMI_JRBC_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI4_UVD_LMI_JRBC_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI4_UVD_LMI_JRBC_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI4_UVD_LMI_JPEG_CTRL
+#define UVD_JMI4_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI4_UVD_LMI_JPEG_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI4_UVD_LMI_JPEG_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI4_UVD_LMI_JPEG_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI4_UVD_LMI_JPEG_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI4_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI4_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI4_UVD_LMI_JPEG_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI4_UVD_LMI_JPEG_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI4_UVD_LMI_JPEG_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI4_UVD_LMI_JPEG_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI4_JPEG_LMI_DROP
+#define UVD_JMI4_JPEG_LMI_DROP__JPEG_WR_DROP__SHIFT 0x0
+#define UVD_JMI4_JPEG_LMI_DROP__JRBC_WR_DROP__SHIFT 0x1
+#define UVD_JMI4_JPEG_LMI_DROP__JPEG_RD_DROP__SHIFT 0x2
+#define UVD_JMI4_JPEG_LMI_DROP__JRBC_RD_DROP__SHIFT 0x3
+#define UVD_JMI4_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP__SHIFT 0x4
+#define UVD_JMI4_JPEG_LMI_DROP__JPEG_WR_DROP_MASK 0x00000001L
+#define UVD_JMI4_JPEG_LMI_DROP__JRBC_WR_DROP_MASK 0x00000002L
+#define UVD_JMI4_JPEG_LMI_DROP__JPEG_RD_DROP_MASK 0x00000004L
+#define UVD_JMI4_JPEG_LMI_DROP__JRBC_RD_DROP_MASK 0x00000008L
+#define UVD_JMI4_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP_MASK 0x00000010L
+//UVD_JMI4_UVD_LMI_JRBC_IB_VMID
+#define UVD_JMI4_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID__SHIFT 0x4
+#define UVD_JMI4_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI4_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI4_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI4_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI4_UVD_LMI_JRBC_RB_VMID
+#define UVD_JMI4_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID__SHIFT 0x4
+#define UVD_JMI4_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI4_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI4_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI4_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI4_UVD_LMI_JPEG_VMID
+#define UVD_JMI4_UVD_LMI_JPEG_VMID__JPEG_RD_VMID__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JPEG_VMID__JPEG_WR_VMID__SHIFT 0x4
+#define UVD_JMI4_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID__SHIFT 0x8
+#define UVD_JMI4_UVD_LMI_JPEG_VMID__JPEG_RD_VMID_MASK 0x0000000FL
+#define UVD_JMI4_UVD_LMI_JPEG_VMID__JPEG_WR_VMID_MASK 0x000000F0L
+#define UVD_JMI4_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID_MASK 0x00000F00L
+//UVD_JMI4_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW
+#define UVD_JMI4_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH
+#define UVD_JMI4_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JRBC_RB_64BIT_BAR_LOW
+#define UVD_JMI4_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH
+#define UVD_JMI4_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI4_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI4_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JPEG_PREEMPT_VMID
+#define UVD_JMI4_UVD_LMI_JPEG_PREEMPT_VMID__VMID__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JPEG_PREEMPT_VMID__VMID_MASK 0x0000000FL
+//UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP__SHIFT 0x0
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP__SHIFT 0x2
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP__SHIFT 0x4
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP__SHIFT 0x6
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP__SHIFT 0x8
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP__SHIFT 0xa
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP__SHIFT 0xc
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP__SHIFT 0xe
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP__SHIFT 0x10
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP_MASK 0x00000003L
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP_MASK 0x0000000CL
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP_MASK 0x00000030L
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP_MASK 0x000000C0L
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP_MASK 0x00000300L
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP_MASK 0x00000C00L
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP_MASK 0x00003000L
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP_MASK 0x0000C000L
+#define UVD_JMI4_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP_MASK 0x00030000L
+//UVD_JMI4_UVD_JMI_ATOMIC_CNTL
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en__SHIFT 0x0
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL__atomic_max_burst__SHIFT 0x1
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop__SHIFT 0x5
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en__SHIFT 0x6
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG__SHIFT 0x7
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE__SHIFT 0xb
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en_MASK 0x00000001L
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL__atomic_max_burst_MASK 0x0000001EL
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop_MASK 0x00000020L
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en_MASK 0x00000040L
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG_MASK 0x00000780L
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE_MASK 0x00000800L
+//UVD_JMI4_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW
+#define UVD_JMI4_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI4_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI4_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI4_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JPEG_READ_64BIT_BAR_LOW
+#define UVD_JMI4_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH
+#define UVD_JMI4_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW
+#define UVD_JMI4_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI4_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JRBC_IB_64BIT_BAR_LOW
+#define UVD_JMI4_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH
+#define UVD_JMI4_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI4_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI4_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI4_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI4_UVD_JMI_ATOMIC_CNTL2
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap__SHIFT 0x10
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP__SHIFT 0x18
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap_MASK 0x00FF0000L
+#define UVD_JMI4_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP_MASK 0xFF000000L
+
+
+// addressBlock: aid_uvd0_uvd_jmi5_uvd_jmi_dec
+//UVD_JMI5_UVD_JPEG_DEC_PF_CTRL
+#define UVD_JMI5_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS__SHIFT 0x0
+#define UVD_JMI5_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING__SHIFT 0x1
+#define UVD_JMI5_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS_MASK 0x00000001L
+#define UVD_JMI5_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING_MASK 0x00000002L
+//UVD_JMI5_UVD_LMI_JRBC_CTRL
+#define UVD_JMI5_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI5_UVD_LMI_JRBC_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI5_UVD_LMI_JRBC_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI5_UVD_LMI_JRBC_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI5_UVD_LMI_JRBC_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI5_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI5_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI5_UVD_LMI_JRBC_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI5_UVD_LMI_JRBC_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI5_UVD_LMI_JRBC_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI5_UVD_LMI_JRBC_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI5_UVD_LMI_JPEG_CTRL
+#define UVD_JMI5_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI5_UVD_LMI_JPEG_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI5_UVD_LMI_JPEG_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI5_UVD_LMI_JPEG_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI5_UVD_LMI_JPEG_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI5_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI5_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI5_UVD_LMI_JPEG_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI5_UVD_LMI_JPEG_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI5_UVD_LMI_JPEG_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI5_UVD_LMI_JPEG_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI5_JPEG_LMI_DROP
+#define UVD_JMI5_JPEG_LMI_DROP__JPEG_WR_DROP__SHIFT 0x0
+#define UVD_JMI5_JPEG_LMI_DROP__JRBC_WR_DROP__SHIFT 0x1
+#define UVD_JMI5_JPEG_LMI_DROP__JPEG_RD_DROP__SHIFT 0x2
+#define UVD_JMI5_JPEG_LMI_DROP__JRBC_RD_DROP__SHIFT 0x3
+#define UVD_JMI5_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP__SHIFT 0x4
+#define UVD_JMI5_JPEG_LMI_DROP__JPEG_WR_DROP_MASK 0x00000001L
+#define UVD_JMI5_JPEG_LMI_DROP__JRBC_WR_DROP_MASK 0x00000002L
+#define UVD_JMI5_JPEG_LMI_DROP__JPEG_RD_DROP_MASK 0x00000004L
+#define UVD_JMI5_JPEG_LMI_DROP__JRBC_RD_DROP_MASK 0x00000008L
+#define UVD_JMI5_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP_MASK 0x00000010L
+//UVD_JMI5_UVD_LMI_JRBC_IB_VMID
+#define UVD_JMI5_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID__SHIFT 0x4
+#define UVD_JMI5_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI5_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI5_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI5_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI5_UVD_LMI_JRBC_RB_VMID
+#define UVD_JMI5_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID__SHIFT 0x4
+#define UVD_JMI5_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI5_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI5_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI5_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI5_UVD_LMI_JPEG_VMID
+#define UVD_JMI5_UVD_LMI_JPEG_VMID__JPEG_RD_VMID__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JPEG_VMID__JPEG_WR_VMID__SHIFT 0x4
+#define UVD_JMI5_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID__SHIFT 0x8
+#define UVD_JMI5_UVD_LMI_JPEG_VMID__JPEG_RD_VMID_MASK 0x0000000FL
+#define UVD_JMI5_UVD_LMI_JPEG_VMID__JPEG_WR_VMID_MASK 0x000000F0L
+#define UVD_JMI5_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID_MASK 0x00000F00L
+//UVD_JMI5_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW
+#define UVD_JMI5_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH
+#define UVD_JMI5_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JRBC_RB_64BIT_BAR_LOW
+#define UVD_JMI5_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH
+#define UVD_JMI5_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI5_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI5_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JPEG_PREEMPT_VMID
+#define UVD_JMI5_UVD_LMI_JPEG_PREEMPT_VMID__VMID__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JPEG_PREEMPT_VMID__VMID_MASK 0x0000000FL
+//UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP__SHIFT 0x0
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP__SHIFT 0x2
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP__SHIFT 0x4
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP__SHIFT 0x6
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP__SHIFT 0x8
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP__SHIFT 0xa
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP__SHIFT 0xc
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP__SHIFT 0xe
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP__SHIFT 0x10
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP_MASK 0x00000003L
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP_MASK 0x0000000CL
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP_MASK 0x00000030L
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP_MASK 0x000000C0L
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP_MASK 0x00000300L
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP_MASK 0x00000C00L
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP_MASK 0x00003000L
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP_MASK 0x0000C000L
+#define UVD_JMI5_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP_MASK 0x00030000L
+//UVD_JMI5_UVD_JMI_ATOMIC_CNTL
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en__SHIFT 0x0
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL__atomic_max_burst__SHIFT 0x1
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop__SHIFT 0x5
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en__SHIFT 0x6
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG__SHIFT 0x7
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE__SHIFT 0xb
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en_MASK 0x00000001L
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL__atomic_max_burst_MASK 0x0000001EL
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop_MASK 0x00000020L
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en_MASK 0x00000040L
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG_MASK 0x00000780L
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE_MASK 0x00000800L
+//UVD_JMI5_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW
+#define UVD_JMI5_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI5_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI5_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI5_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JPEG_READ_64BIT_BAR_LOW
+#define UVD_JMI5_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH
+#define UVD_JMI5_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW
+#define UVD_JMI5_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI5_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JRBC_IB_64BIT_BAR_LOW
+#define UVD_JMI5_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH
+#define UVD_JMI5_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI5_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI5_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI5_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI5_UVD_JMI_ATOMIC_CNTL2
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap__SHIFT 0x10
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP__SHIFT 0x18
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap_MASK 0x00FF0000L
+#define UVD_JMI5_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP_MASK 0xFF000000L
+
+
+// addressBlock: aid_uvd0_uvd_jmi6_uvd_jmi_dec
+//UVD_JMI6_UVD_JPEG_DEC_PF_CTRL
+#define UVD_JMI6_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS__SHIFT 0x0
+#define UVD_JMI6_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING__SHIFT 0x1
+#define UVD_JMI6_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS_MASK 0x00000001L
+#define UVD_JMI6_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING_MASK 0x00000002L
+//UVD_JMI6_UVD_LMI_JRBC_CTRL
+#define UVD_JMI6_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI6_UVD_LMI_JRBC_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI6_UVD_LMI_JRBC_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI6_UVD_LMI_JRBC_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI6_UVD_LMI_JRBC_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI6_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI6_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI6_UVD_LMI_JRBC_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI6_UVD_LMI_JRBC_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI6_UVD_LMI_JRBC_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI6_UVD_LMI_JRBC_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI6_UVD_LMI_JPEG_CTRL
+#define UVD_JMI6_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI6_UVD_LMI_JPEG_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI6_UVD_LMI_JPEG_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI6_UVD_LMI_JPEG_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI6_UVD_LMI_JPEG_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI6_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI6_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI6_UVD_LMI_JPEG_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI6_UVD_LMI_JPEG_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI6_UVD_LMI_JPEG_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI6_UVD_LMI_JPEG_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI6_JPEG_LMI_DROP
+#define UVD_JMI6_JPEG_LMI_DROP__JPEG_WR_DROP__SHIFT 0x0
+#define UVD_JMI6_JPEG_LMI_DROP__JRBC_WR_DROP__SHIFT 0x1
+#define UVD_JMI6_JPEG_LMI_DROP__JPEG_RD_DROP__SHIFT 0x2
+#define UVD_JMI6_JPEG_LMI_DROP__JRBC_RD_DROP__SHIFT 0x3
+#define UVD_JMI6_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP__SHIFT 0x4
+#define UVD_JMI6_JPEG_LMI_DROP__JPEG_WR_DROP_MASK 0x00000001L
+#define UVD_JMI6_JPEG_LMI_DROP__JRBC_WR_DROP_MASK 0x00000002L
+#define UVD_JMI6_JPEG_LMI_DROP__JPEG_RD_DROP_MASK 0x00000004L
+#define UVD_JMI6_JPEG_LMI_DROP__JRBC_RD_DROP_MASK 0x00000008L
+#define UVD_JMI6_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP_MASK 0x00000010L
+//UVD_JMI6_UVD_LMI_JRBC_IB_VMID
+#define UVD_JMI6_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID__SHIFT 0x4
+#define UVD_JMI6_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI6_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI6_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI6_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI6_UVD_LMI_JRBC_RB_VMID
+#define UVD_JMI6_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID__SHIFT 0x4
+#define UVD_JMI6_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI6_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI6_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI6_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI6_UVD_LMI_JPEG_VMID
+#define UVD_JMI6_UVD_LMI_JPEG_VMID__JPEG_RD_VMID__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JPEG_VMID__JPEG_WR_VMID__SHIFT 0x4
+#define UVD_JMI6_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID__SHIFT 0x8
+#define UVD_JMI6_UVD_LMI_JPEG_VMID__JPEG_RD_VMID_MASK 0x0000000FL
+#define UVD_JMI6_UVD_LMI_JPEG_VMID__JPEG_WR_VMID_MASK 0x000000F0L
+#define UVD_JMI6_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID_MASK 0x00000F00L
+//UVD_JMI6_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW
+#define UVD_JMI6_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH
+#define UVD_JMI6_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JRBC_RB_64BIT_BAR_LOW
+#define UVD_JMI6_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH
+#define UVD_JMI6_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI6_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI6_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JPEG_PREEMPT_VMID
+#define UVD_JMI6_UVD_LMI_JPEG_PREEMPT_VMID__VMID__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JPEG_PREEMPT_VMID__VMID_MASK 0x0000000FL
+//UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP__SHIFT 0x0
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP__SHIFT 0x2
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP__SHIFT 0x4
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP__SHIFT 0x6
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP__SHIFT 0x8
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP__SHIFT 0xa
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP__SHIFT 0xc
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP__SHIFT 0xe
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP__SHIFT 0x10
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP_MASK 0x00000003L
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP_MASK 0x0000000CL
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP_MASK 0x00000030L
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP_MASK 0x000000C0L
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP_MASK 0x00000300L
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP_MASK 0x00000C00L
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP_MASK 0x00003000L
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP_MASK 0x0000C000L
+#define UVD_JMI6_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP_MASK 0x00030000L
+//UVD_JMI6_UVD_JMI_ATOMIC_CNTL
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en__SHIFT 0x0
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL__atomic_max_burst__SHIFT 0x1
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop__SHIFT 0x5
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en__SHIFT 0x6
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG__SHIFT 0x7
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE__SHIFT 0xb
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en_MASK 0x00000001L
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL__atomic_max_burst_MASK 0x0000001EL
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop_MASK 0x00000020L
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en_MASK 0x00000040L
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG_MASK 0x00000780L
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE_MASK 0x00000800L
+//UVD_JMI6_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW
+#define UVD_JMI6_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI6_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI6_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI6_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JPEG_READ_64BIT_BAR_LOW
+#define UVD_JMI6_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH
+#define UVD_JMI6_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW
+#define UVD_JMI6_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI6_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JRBC_IB_64BIT_BAR_LOW
+#define UVD_JMI6_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH
+#define UVD_JMI6_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI6_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI6_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI6_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI6_UVD_JMI_ATOMIC_CNTL2
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap__SHIFT 0x10
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP__SHIFT 0x18
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap_MASK 0x00FF0000L
+#define UVD_JMI6_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP_MASK 0xFF000000L
+
+
+// addressBlock: aid_uvd0_uvd_jmi7_uvd_jmi_dec
+//UVD_JMI7_UVD_JPEG_DEC_PF_CTRL
+#define UVD_JMI7_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS__SHIFT 0x0
+#define UVD_JMI7_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING__SHIFT 0x1
+#define UVD_JMI7_UVD_JPEG_DEC_PF_CTRL__DEC_PF_HANDLING_DIS_MASK 0x00000001L
+#define UVD_JMI7_UVD_JPEG_DEC_PF_CTRL__DEC_PF_SW_GATING_MASK 0x00000002L
+//UVD_JMI7_UVD_LMI_JRBC_CTRL
+#define UVD_JMI7_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI7_UVD_LMI_JRBC_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI7_UVD_LMI_JRBC_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI7_UVD_LMI_JRBC_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI7_UVD_LMI_JRBC_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI7_UVD_LMI_JRBC_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI7_UVD_LMI_JRBC_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI7_UVD_LMI_JRBC_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI7_UVD_LMI_JRBC_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI7_UVD_LMI_JRBC_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI7_UVD_LMI_JRBC_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI7_UVD_LMI_JPEG_CTRL
+#define UVD_JMI7_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN__SHIFT 0x1
+#define UVD_JMI7_UVD_LMI_JPEG_CTRL__RD_MAX_BURST__SHIFT 0x4
+#define UVD_JMI7_UVD_LMI_JPEG_CTRL__WR_MAX_BURST__SHIFT 0x8
+#define UVD_JMI7_UVD_LMI_JPEG_CTRL__RD_SWAP__SHIFT 0x14
+#define UVD_JMI7_UVD_LMI_JPEG_CTRL__WR_SWAP__SHIFT 0x16
+#define UVD_JMI7_UVD_LMI_JPEG_CTRL__ARB_RD_WAIT_EN_MASK 0x00000001L
+#define UVD_JMI7_UVD_LMI_JPEG_CTRL__ARB_WR_WAIT_EN_MASK 0x00000002L
+#define UVD_JMI7_UVD_LMI_JPEG_CTRL__RD_MAX_BURST_MASK 0x000000F0L
+#define UVD_JMI7_UVD_LMI_JPEG_CTRL__WR_MAX_BURST_MASK 0x00000F00L
+#define UVD_JMI7_UVD_LMI_JPEG_CTRL__RD_SWAP_MASK 0x00300000L
+#define UVD_JMI7_UVD_LMI_JPEG_CTRL__WR_SWAP_MASK 0x00C00000L
+//UVD_JMI7_JPEG_LMI_DROP
+#define UVD_JMI7_JPEG_LMI_DROP__JPEG_WR_DROP__SHIFT 0x0
+#define UVD_JMI7_JPEG_LMI_DROP__JRBC_WR_DROP__SHIFT 0x1
+#define UVD_JMI7_JPEG_LMI_DROP__JPEG_RD_DROP__SHIFT 0x2
+#define UVD_JMI7_JPEG_LMI_DROP__JRBC_RD_DROP__SHIFT 0x3
+#define UVD_JMI7_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP__SHIFT 0x4
+#define UVD_JMI7_JPEG_LMI_DROP__JPEG_WR_DROP_MASK 0x00000001L
+#define UVD_JMI7_JPEG_LMI_DROP__JRBC_WR_DROP_MASK 0x00000002L
+#define UVD_JMI7_JPEG_LMI_DROP__JPEG_RD_DROP_MASK 0x00000004L
+#define UVD_JMI7_JPEG_LMI_DROP__JRBC_RD_DROP_MASK 0x00000008L
+#define UVD_JMI7_JPEG_LMI_DROP__JPEG_ATOMIC_WR_DROP_MASK 0x00000010L
+//UVD_JMI7_UVD_LMI_JRBC_IB_VMID
+#define UVD_JMI7_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID__SHIFT 0x4
+#define UVD_JMI7_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI7_UVD_LMI_JRBC_IB_VMID__IB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI7_UVD_LMI_JRBC_IB_VMID__IB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI7_UVD_LMI_JRBC_IB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI7_UVD_LMI_JRBC_RB_VMID
+#define UVD_JMI7_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID__SHIFT 0x4
+#define UVD_JMI7_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID__SHIFT 0x8
+#define UVD_JMI7_UVD_LMI_JRBC_RB_VMID__RB_WR_VMID_MASK 0x0000000FL
+#define UVD_JMI7_UVD_LMI_JRBC_RB_VMID__RB_RD_VMID_MASK 0x000000F0L
+#define UVD_JMI7_UVD_LMI_JRBC_RB_VMID__MEM_RD_VMID_MASK 0x00000F00L
+//UVD_JMI7_UVD_LMI_JPEG_VMID
+#define UVD_JMI7_UVD_LMI_JPEG_VMID__JPEG_RD_VMID__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JPEG_VMID__JPEG_WR_VMID__SHIFT 0x4
+#define UVD_JMI7_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID__SHIFT 0x8
+#define UVD_JMI7_UVD_LMI_JPEG_VMID__JPEG_RD_VMID_MASK 0x0000000FL
+#define UVD_JMI7_UVD_LMI_JPEG_VMID__JPEG_WR_VMID_MASK 0x000000F0L
+#define UVD_JMI7_UVD_LMI_JPEG_VMID__ATOMIC_USER0_WR_VMID_MASK 0x00000F00L
+//UVD_JMI7_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW
+#define UVD_JMI7_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH
+#define UVD_JMI7_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JPEG_PREEMPT_FENCE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JRBC_RB_64BIT_BAR_LOW
+#define UVD_JMI7_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JRBC_RB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH
+#define UVD_JMI7_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JRBC_RB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI7_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI7_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JPEG_PREEMPT_VMID
+#define UVD_JMI7_UVD_LMI_JPEG_PREEMPT_VMID__VMID__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JPEG_PREEMPT_VMID__VMID_MASK 0x0000000FL
+//UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP__SHIFT 0x0
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP__SHIFT 0x2
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP__SHIFT 0x4
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP__SHIFT 0x6
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP__SHIFT 0x8
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP__SHIFT 0xa
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP__SHIFT 0xc
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP__SHIFT 0xe
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP__SHIFT 0x10
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__RB_MC_SWAP_MASK 0x00000003L
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__IB_MC_SWAP_MASK 0x0000000CL
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_WR_MC_SWAP_MASK 0x00000030L
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_WR_MC_SWAP_MASK 0x000000C0L
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__RB_MEM_RD_MC_SWAP_MASK 0x00000300L
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__IB_MEM_RD_MC_SWAP_MASK 0x00000C00L
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__PREEMPT_WR_MC_SWAP_MASK 0x00003000L
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__JPEG_RD_MC_SWAP_MASK 0x0000C000L
+#define UVD_JMI7_UVD_JMI_DEC_SWAP_CNTL__JPEG_WR_MC_SWAP_MASK 0x00030000L
+//UVD_JMI7_UVD_JMI_ATOMIC_CNTL
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en__SHIFT 0x0
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL__atomic_max_burst__SHIFT 0x1
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop__SHIFT 0x5
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en__SHIFT 0x6
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG__SHIFT 0x7
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE__SHIFT 0xb
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL__atomic_arb_wait_en_MASK 0x00000001L
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL__atomic_max_burst_MASK 0x0000001EL
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL__atomic_wr_drop_MASK 0x00000020L
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL__atomic_wr_clamping_en_MASK 0x00000040L
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL__ATOMIC_WR_URG_MASK 0x00000780L
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL__ATOMIC_SW_GATE_MASK 0x00000800L
+//UVD_JMI7_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW
+#define UVD_JMI7_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI7_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI7_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI7_UVD_JMI_ATOMIC_USER0_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JPEG_READ_64BIT_BAR_LOW
+#define UVD_JMI7_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JPEG_READ_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH
+#define UVD_JMI7_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JPEG_READ_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW
+#define UVD_JMI7_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JPEG_WRITE_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH
+#define UVD_JMI7_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JPEG_WRITE_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JRBC_IB_64BIT_BAR_LOW
+#define UVD_JMI7_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JRBC_IB_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH
+#define UVD_JMI7_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JRBC_IB_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW
+#define UVD_JMI7_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_LOW__BITS_31_0_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH
+#define UVD_JMI7_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32__SHIFT 0x0
+#define UVD_JMI7_UVD_LMI_JRBC_IB_MEM_WR_64BIT_BAR_HIGH__BITS_63_32_MASK 0xFFFFFFFFL
+//UVD_JMI7_UVD_JMI_ATOMIC_CNTL2
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap__SHIFT 0x10
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP__SHIFT 0x18
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL2__atomic_uvd_swap_MASK 0x00FF0000L
+#define UVD_JMI7_UVD_JMI_ATOMIC_CNTL2__ATOMIC_MC_SWAP_MASK 0xFF000000L
+
+
+// addressBlock: uvdctxind
+//UVD_CGC_MEM_CTRL
+#define UVD_CGC_MEM_CTRL__LMI_MC_LS_EN__SHIFT 0x0
+#define UVD_CGC_MEM_CTRL__MPC_LS_EN__SHIFT 0x1
+#define UVD_CGC_MEM_CTRL__MPRD_LS_EN__SHIFT 0x2
+#define UVD_CGC_MEM_CTRL__WCB_LS_EN__SHIFT 0x3
+#define UVD_CGC_MEM_CTRL__UDEC_RE_LS_EN__SHIFT 0x4
+#define UVD_CGC_MEM_CTRL__UDEC_CM_LS_EN__SHIFT 0x5
+#define UVD_CGC_MEM_CTRL__UDEC_IT_LS_EN__SHIFT 0x6
+#define UVD_CGC_MEM_CTRL__UDEC_DB_LS_EN__SHIFT 0x7
+#define UVD_CGC_MEM_CTRL__UDEC_MP_LS_EN__SHIFT 0x8
+#define UVD_CGC_MEM_CTRL__SYS_LS_EN__SHIFT 0x9
+#define UVD_CGC_MEM_CTRL__VCPU_LS_EN__SHIFT 0xa
+#define UVD_CGC_MEM_CTRL__MIF_LS_EN__SHIFT 0xc
+#define UVD_CGC_MEM_CTRL__LCM_LS_EN__SHIFT 0xd
+#define UVD_CGC_MEM_CTRL__MMSCH_LS_EN__SHIFT 0xe
+#define UVD_CGC_MEM_CTRL__MPC1_LS_EN__SHIFT 0xf
+#define UVD_CGC_MEM_CTRL__LS_SET_DELAY__SHIFT 0x10
+#define UVD_CGC_MEM_CTRL__LS_CLEAR_DELAY__SHIFT 0x14
+#define UVD_CGC_MEM_CTRL__LMI_MC_LS_EN_MASK 0x00000001L
+#define UVD_CGC_MEM_CTRL__MPC_LS_EN_MASK 0x00000002L
+#define UVD_CGC_MEM_CTRL__MPRD_LS_EN_MASK 0x00000004L
+#define UVD_CGC_MEM_CTRL__WCB_LS_EN_MASK 0x00000008L
+#define UVD_CGC_MEM_CTRL__UDEC_RE_LS_EN_MASK 0x00000010L
+#define UVD_CGC_MEM_CTRL__UDEC_CM_LS_EN_MASK 0x00000020L
+#define UVD_CGC_MEM_CTRL__UDEC_IT_LS_EN_MASK 0x00000040L
+#define UVD_CGC_MEM_CTRL__UDEC_DB_LS_EN_MASK 0x00000080L
+#define UVD_CGC_MEM_CTRL__UDEC_MP_LS_EN_MASK 0x00000100L
+#define UVD_CGC_MEM_CTRL__SYS_LS_EN_MASK 0x00000200L
+#define UVD_CGC_MEM_CTRL__VCPU_LS_EN_MASK 0x00000400L
+#define UVD_CGC_MEM_CTRL__MIF_LS_EN_MASK 0x00001000L
+#define UVD_CGC_MEM_CTRL__LCM_LS_EN_MASK 0x00002000L
+#define UVD_CGC_MEM_CTRL__MMSCH_LS_EN_MASK 0x00004000L
+#define UVD_CGC_MEM_CTRL__MPC1_LS_EN_MASK 0x00008000L
+#define UVD_CGC_MEM_CTRL__LS_SET_DELAY_MASK 0x000F0000L
+#define UVD_CGC_MEM_CTRL__LS_CLEAR_DELAY_MASK 0x00F00000L
+//UVD_CGC_CTRL2
+#define UVD_CGC_CTRL2__DYN_OCLK_RAMP_EN__SHIFT 0x0
+#define UVD_CGC_CTRL2__DYN_RCLK_RAMP_EN__SHIFT 0x1
+#define UVD_CGC_CTRL2__GATER_DIV_ID__SHIFT 0x2
+#define UVD_CGC_CTRL2__DYN_OCLK_RAMP_EN_MASK 0x00000001L
+#define UVD_CGC_CTRL2__DYN_RCLK_RAMP_EN_MASK 0x00000002L
+#define UVD_CGC_CTRL2__GATER_DIV_ID_MASK 0x0000001CL
+//UVD_CGC_MEM_DS_CTRL
+#define UVD_CGC_MEM_DS_CTRL__LMI_MC_DS_EN__SHIFT 0x0
+#define UVD_CGC_MEM_DS_CTRL__MPC_DS_EN__SHIFT 0x1
+#define UVD_CGC_MEM_DS_CTRL__MPRD_DS_EN__SHIFT 0x2
+#define UVD_CGC_MEM_DS_CTRL__WCB_DS_EN__SHIFT 0x3
+#define UVD_CGC_MEM_DS_CTRL__UDEC_RE_DS_EN__SHIFT 0x4
+#define UVD_CGC_MEM_DS_CTRL__UDEC_CM_DS_EN__SHIFT 0x5
+#define UVD_CGC_MEM_DS_CTRL__UDEC_IT_DS_EN__SHIFT 0x6
+#define UVD_CGC_MEM_DS_CTRL__UDEC_DB_DS_EN__SHIFT 0x7
+#define UVD_CGC_MEM_DS_CTRL__UDEC_MP_DS_EN__SHIFT 0x8
+#define UVD_CGC_MEM_DS_CTRL__SYS_DS_EN__SHIFT 0x9
+#define UVD_CGC_MEM_DS_CTRL__VCPU_DS_EN__SHIFT 0xa
+#define UVD_CGC_MEM_DS_CTRL__MIF_DS_EN__SHIFT 0xc
+#define UVD_CGC_MEM_DS_CTRL__LCM_DS_EN__SHIFT 0xd
+#define UVD_CGC_MEM_DS_CTRL__MMSCH_DS_EN__SHIFT 0xe
+#define UVD_CGC_MEM_DS_CTRL__MPC1_DS_EN__SHIFT 0xf
+#define UVD_CGC_MEM_DS_CTRL__LMI_MC_DS_EN_MASK 0x00000001L
+#define UVD_CGC_MEM_DS_CTRL__MPC_DS_EN_MASK 0x00000002L
+#define UVD_CGC_MEM_DS_CTRL__MPRD_DS_EN_MASK 0x00000004L
+#define UVD_CGC_MEM_DS_CTRL__WCB_DS_EN_MASK 0x00000008L
+#define UVD_CGC_MEM_DS_CTRL__UDEC_RE_DS_EN_MASK 0x00000010L
+#define UVD_CGC_MEM_DS_CTRL__UDEC_CM_DS_EN_MASK 0x00000020L
+#define UVD_CGC_MEM_DS_CTRL__UDEC_IT_DS_EN_MASK 0x00000040L
+#define UVD_CGC_MEM_DS_CTRL__UDEC_DB_DS_EN_MASK 0x00000080L
+#define UVD_CGC_MEM_DS_CTRL__UDEC_MP_DS_EN_MASK 0x00000100L
+#define UVD_CGC_MEM_DS_CTRL__SYS_DS_EN_MASK 0x00000200L
+#define UVD_CGC_MEM_DS_CTRL__VCPU_DS_EN_MASK 0x00000400L
+#define UVD_CGC_MEM_DS_CTRL__MIF_DS_EN_MASK 0x00001000L
+#define UVD_CGC_MEM_DS_CTRL__LCM_DS_EN_MASK 0x00002000L
+#define UVD_CGC_MEM_DS_CTRL__MMSCH_DS_EN_MASK 0x00004000L
+#define UVD_CGC_MEM_DS_CTRL__MPC1_DS_EN_MASK 0x00008000L
+//UVD_CGC_MEM_SD_CTRL
+#define UVD_CGC_MEM_SD_CTRL__LMI_MC_SD_EN__SHIFT 0x0
+#define UVD_CGC_MEM_SD_CTRL__MPC_SD_EN__SHIFT 0x1
+#define UVD_CGC_MEM_SD_CTRL__MPRD_SD_EN__SHIFT 0x2
+#define UVD_CGC_MEM_SD_CTRL__WCB_SD_EN__SHIFT 0x3
+#define UVD_CGC_MEM_SD_CTRL__UDEC_RE_SD_EN__SHIFT 0x4
+#define UVD_CGC_MEM_SD_CTRL__UDEC_CM_SD_EN__SHIFT 0x5
+#define UVD_CGC_MEM_SD_CTRL__UDEC_IT_SD_EN__SHIFT 0x6
+#define UVD_CGC_MEM_SD_CTRL__UDEC_DB_SD_EN__SHIFT 0x7
+#define UVD_CGC_MEM_SD_CTRL__UDEC_MP_SD_EN__SHIFT 0x8
+#define UVD_CGC_MEM_SD_CTRL__SYS_SD_EN__SHIFT 0x9
+#define UVD_CGC_MEM_SD_CTRL__VCPU_SD_EN__SHIFT 0xa
+#define UVD_CGC_MEM_SD_CTRL__MIF_SD_EN__SHIFT 0xc
+#define UVD_CGC_MEM_SD_CTRL__LCM_SD_EN__SHIFT 0xd
+#define UVD_CGC_MEM_SD_CTRL__MMSCH_SD_EN__SHIFT 0xe
+#define UVD_CGC_MEM_SD_CTRL__MPC1_SD_EN__SHIFT 0xf
+#define UVD_CGC_MEM_SD_CTRL__LMI_MC_SD_EN_MASK 0x00000001L
+#define UVD_CGC_MEM_SD_CTRL__MPC_SD_EN_MASK 0x00000002L
+#define UVD_CGC_MEM_SD_CTRL__MPRD_SD_EN_MASK 0x00000004L
+#define UVD_CGC_MEM_SD_CTRL__WCB_SD_EN_MASK 0x00000008L
+#define UVD_CGC_MEM_SD_CTRL__UDEC_RE_SD_EN_MASK 0x00000010L
+#define UVD_CGC_MEM_SD_CTRL__UDEC_CM_SD_EN_MASK 0x00000020L
+#define UVD_CGC_MEM_SD_CTRL__UDEC_IT_SD_EN_MASK 0x00000040L
+#define UVD_CGC_MEM_SD_CTRL__UDEC_DB_SD_EN_MASK 0x00000080L
+#define UVD_CGC_MEM_SD_CTRL__UDEC_MP_SD_EN_MASK 0x00000100L
+#define UVD_CGC_MEM_SD_CTRL__SYS_SD_EN_MASK 0x00000200L
+#define UVD_CGC_MEM_SD_CTRL__VCPU_SD_EN_MASK 0x00000400L
+#define UVD_CGC_MEM_SD_CTRL__MIF_SD_EN_MASK 0x00001000L
+#define UVD_CGC_MEM_SD_CTRL__LCM_SD_EN_MASK 0x00002000L
+#define UVD_CGC_MEM_SD_CTRL__MMSCH_SD_EN_MASK 0x00004000L
+#define UVD_CGC_MEM_SD_CTRL__MPC1_SD_EN_MASK 0x00008000L
+//UVD_SW_SCRATCH_00
+#define UVD_SW_SCRATCH_00__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_00__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_01
+#define UVD_SW_SCRATCH_01__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_01__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_02
+#define UVD_SW_SCRATCH_02__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_02__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_03
+#define UVD_SW_SCRATCH_03__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_03__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_04
+#define UVD_SW_SCRATCH_04__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_04__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_05
+#define UVD_SW_SCRATCH_05__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_05__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_06
+#define UVD_SW_SCRATCH_06__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_06__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_07
+#define UVD_SW_SCRATCH_07__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_07__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_08
+#define UVD_SW_SCRATCH_08__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_08__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_09
+#define UVD_SW_SCRATCH_09__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_09__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_10
+#define UVD_SW_SCRATCH_10__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_10__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_11
+#define UVD_SW_SCRATCH_11__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_11__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_12
+#define UVD_SW_SCRATCH_12__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_12__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_13
+#define UVD_SW_SCRATCH_13__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_13__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_14
+#define UVD_SW_SCRATCH_14__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_14__DATA_MASK 0xFFFFFFFFL
+//UVD_SW_SCRATCH_15
+#define UVD_SW_SCRATCH_15__DATA__SHIFT 0x0
+#define UVD_SW_SCRATCH_15__DATA_MASK 0xFFFFFFFFL
+//UVD_IH_SEM_CTRL
+#define UVD_IH_SEM_CTRL__IH_STALL_EN__SHIFT 0x0
+#define UVD_IH_SEM_CTRL__SEM_STALL_EN__SHIFT 0x1
+#define UVD_IH_SEM_CTRL__IH_STATUS_CLEAN__SHIFT 0x2
+#define UVD_IH_SEM_CTRL__SEM_STATUS_CLEAN__SHIFT 0x3
+#define UVD_IH_SEM_CTRL__IH_VMID__SHIFT 0x4
+#define UVD_IH_SEM_CTRL__IH_USER_DATA__SHIFT 0x8
+#define UVD_IH_SEM_CTRL__IH_RINGID__SHIFT 0x14
+#define UVD_IH_SEM_CTRL__IH_STALL_EN_MASK 0x00000001L
+#define UVD_IH_SEM_CTRL__SEM_STALL_EN_MASK 0x00000002L
+#define UVD_IH_SEM_CTRL__IH_STATUS_CLEAN_MASK 0x00000004L
+#define UVD_IH_SEM_CTRL__SEM_STATUS_CLEAN_MASK 0x00000008L
+#define UVD_IH_SEM_CTRL__IH_VMID_MASK 0x000000F0L
+#define UVD_IH_SEM_CTRL__IH_USER_DATA_MASK 0x000FFF00L
+#define UVD_IH_SEM_CTRL__IH_RINGID_MASK 0x0FF00000L
+
+
+// addressBlock: lmi_adp_indirect
+//UVD_LMI_CRC0
+#define UVD_LMI_CRC0__CRC32__SHIFT 0x0
+#define UVD_LMI_CRC0__CRC32_MASK 0xFFFFFFFFL
+//UVD_LMI_CRC1
+#define UVD_LMI_CRC1__CRC32__SHIFT 0x0
+#define UVD_LMI_CRC1__CRC32_MASK 0xFFFFFFFFL
+//UVD_LMI_CRC2
+#define UVD_LMI_CRC2__CRC32__SHIFT 0x0
+#define UVD_LMI_CRC2__CRC32_MASK 0xFFFFFFFFL
+//UVD_LMI_CRC3
+#define UVD_LMI_CRC3__CRC32__SHIFT 0x0
+#define UVD_LMI_CRC3__CRC32_MASK 0xFFFFFFFFL
+//UVD_LMI_CRC10
+#define UVD_LMI_CRC10__CRC32__SHIFT 0x0
+#define UVD_LMI_CRC10__CRC32_MASK 0xFFFFFFFFL
+//UVD_LMI_CRC11
+#define UVD_LMI_CRC11__CRC32__SHIFT 0x0
+#define UVD_LMI_CRC11__CRC32_MASK 0xFFFFFFFFL
+//UVD_LMI_CRC12
+#define UVD_LMI_CRC12__CRC32__SHIFT 0x0
+#define UVD_LMI_CRC12__CRC32_MASK 0xFFFFFFFFL
+//UVD_LMI_CRC13
+#define UVD_LMI_CRC13__CRC32__SHIFT 0x0
+#define UVD_LMI_CRC13__CRC32_MASK 0xFFFFFFFFL
+//UVD_LMI_CRC14
+#define UVD_LMI_CRC14__CRC32__SHIFT 0x0
+#define UVD_LMI_CRC14__CRC32_MASK 0xFFFFFFFFL
+//UVD_LMI_CRC15
+#define UVD_LMI_CRC15__CRC32__SHIFT 0x0
+#define UVD_LMI_CRC15__CRC32_MASK 0xFFFFFFFFL
+//UVD_LMI_SWAP_CNTL2
+#define UVD_LMI_SWAP_CNTL2__SCPU_R_MC_SWAP__SHIFT 0x0
+#define UVD_LMI_SWAP_CNTL2__SCPU_W_MC_SWAP__SHIFT 0x2
+#define UVD_LMI_SWAP_CNTL2__ATOMIC_MC_SWAP__SHIFT 0x4
+#define UVD_LMI_SWAP_CNTL2__CENC_MC_SWAP__SHIFT 0xc
+#define UVD_LMI_SWAP_CNTL2__FBC_KEY_MC_SWAP__SHIFT 0xe
+#define UVD_LMI_SWAP_CNTL2__SCPU_R_MC_SWAP_MASK 0x00000003L
+#define UVD_LMI_SWAP_CNTL2__SCPU_W_MC_SWAP_MASK 0x0000000CL
+#define UVD_LMI_SWAP_CNTL2__ATOMIC_MC_SWAP_MASK 0x00000FF0L
+#define UVD_LMI_SWAP_CNTL2__CENC_MC_SWAP_MASK 0x00003000L
+#define UVD_LMI_SWAP_CNTL2__FBC_KEY_MC_SWAP_MASK 0x0000C000L
+//UVD_MEMCHECK_SYS_INT_EN
+#define UVD_MEMCHECK_SYS_INT_EN__RE_ERR_EN__SHIFT 0x0
+#define UVD_MEMCHECK_SYS_INT_EN__IT_ERR_EN__SHIFT 0x1
+#define UVD_MEMCHECK_SYS_INT_EN__MP_ERR_EN__SHIFT 0x2
+#define UVD_MEMCHECK_SYS_INT_EN__DB_ERR_EN__SHIFT 0x3
+#define UVD_MEMCHECK_SYS_INT_EN__DBW_ERR_EN__SHIFT 0x4
+#define UVD_MEMCHECK_SYS_INT_EN__CM_ERR_EN__SHIFT 0x5
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_REF_ERR_EN__SHIFT 0x6
+#define UVD_MEMCHECK_SYS_INT_EN__VCPU_ERR_EN__SHIFT 0x7
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_DBW_ERR_EN__SHIFT 0x8
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_CM_COLOC_ERR_EN__SHIFT 0x9
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_BSP0_ERR_EN__SHIFT 0xa
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_BSP1_ERR_EN__SHIFT 0xb
+#define UVD_MEMCHECK_SYS_INT_EN__SRE_ERR_EN__SHIFT 0xc
+#define UVD_MEMCHECK_SYS_INT_EN__IT_RD_ERR_EN__SHIFT 0xf
+#define UVD_MEMCHECK_SYS_INT_EN__CM_RD_ERR_EN__SHIFT 0x10
+#define UVD_MEMCHECK_SYS_INT_EN__DB_RD_ERR_EN__SHIFT 0x11
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_RD_ERR_EN__SHIFT 0x12
+#define UVD_MEMCHECK_SYS_INT_EN__IDCT_RD_ERR_EN__SHIFT 0x13
+#define UVD_MEMCHECK_SYS_INT_EN__MPC_RD_ERR_EN__SHIFT 0x14
+#define UVD_MEMCHECK_SYS_INT_EN__LBSI_RD_ERR_EN__SHIFT 0x15
+#define UVD_MEMCHECK_SYS_INT_EN__RBC_RD_ERR_EN__SHIFT 0x18
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_BSP2_ERR_EN__SHIFT 0x1b
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_BSP3_ERR_EN__SHIFT 0x1c
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_SCLR_ERR_EN__SHIFT 0x1d
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_SCLR2_ERR_EN__SHIFT 0x1e
+#define UVD_MEMCHECK_SYS_INT_EN__PREF_ERR_EN__SHIFT 0x1f
+#define UVD_MEMCHECK_SYS_INT_EN__RE_ERR_EN_MASK 0x00000001L
+#define UVD_MEMCHECK_SYS_INT_EN__IT_ERR_EN_MASK 0x00000002L
+#define UVD_MEMCHECK_SYS_INT_EN__MP_ERR_EN_MASK 0x00000004L
+#define UVD_MEMCHECK_SYS_INT_EN__DB_ERR_EN_MASK 0x00000008L
+#define UVD_MEMCHECK_SYS_INT_EN__DBW_ERR_EN_MASK 0x00000010L
+#define UVD_MEMCHECK_SYS_INT_EN__CM_ERR_EN_MASK 0x00000020L
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_REF_ERR_EN_MASK 0x00000040L
+#define UVD_MEMCHECK_SYS_INT_EN__VCPU_ERR_EN_MASK 0x00000080L
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_DBW_ERR_EN_MASK 0x00000100L
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_CM_COLOC_ERR_EN_MASK 0x00000200L
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_BSP0_ERR_EN_MASK 0x00000400L
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_BSP1_ERR_EN_MASK 0x00000800L
+#define UVD_MEMCHECK_SYS_INT_EN__SRE_ERR_EN_MASK 0x00001000L
+#define UVD_MEMCHECK_SYS_INT_EN__IT_RD_ERR_EN_MASK 0x00008000L
+#define UVD_MEMCHECK_SYS_INT_EN__CM_RD_ERR_EN_MASK 0x00010000L
+#define UVD_MEMCHECK_SYS_INT_EN__DB_RD_ERR_EN_MASK 0x00020000L
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_RD_ERR_EN_MASK 0x00040000L
+#define UVD_MEMCHECK_SYS_INT_EN__IDCT_RD_ERR_EN_MASK 0x00080000L
+#define UVD_MEMCHECK_SYS_INT_EN__MPC_RD_ERR_EN_MASK 0x00100000L
+#define UVD_MEMCHECK_SYS_INT_EN__LBSI_RD_ERR_EN_MASK 0x00200000L
+#define UVD_MEMCHECK_SYS_INT_EN__RBC_RD_ERR_EN_MASK 0x01000000L
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_BSP2_ERR_EN_MASK 0x08000000L
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_BSP3_ERR_EN_MASK 0x10000000L
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_SCLR_ERR_EN_MASK 0x20000000L
+#define UVD_MEMCHECK_SYS_INT_EN__MIF_SCLR2_ERR_EN_MASK 0x40000000L
+#define UVD_MEMCHECK_SYS_INT_EN__PREF_ERR_EN_MASK 0x80000000L
+//UVD_MEMCHECK_SYS_INT_STAT
+#define UVD_MEMCHECK_SYS_INT_STAT__RE_LO_ERR__SHIFT 0x0
+#define UVD_MEMCHECK_SYS_INT_STAT__RE_HI_ERR__SHIFT 0x1
+#define UVD_MEMCHECK_SYS_INT_STAT__IT_LO_ERR__SHIFT 0x2
+#define UVD_MEMCHECK_SYS_INT_STAT__IT_HI_ERR__SHIFT 0x3
+#define UVD_MEMCHECK_SYS_INT_STAT__MP_LO_ERR__SHIFT 0x4
+#define UVD_MEMCHECK_SYS_INT_STAT__MP_HI_ERR__SHIFT 0x5
+#define UVD_MEMCHECK_SYS_INT_STAT__DB_LO_ERR__SHIFT 0x6
+#define UVD_MEMCHECK_SYS_INT_STAT__DB_HI_ERR__SHIFT 0x7
+#define UVD_MEMCHECK_SYS_INT_STAT__DBW_LO_ERR__SHIFT 0x8
+#define UVD_MEMCHECK_SYS_INT_STAT__DBW_HI_ERR__SHIFT 0x9
+#define UVD_MEMCHECK_SYS_INT_STAT__CM_LO_ERR__SHIFT 0xa
+#define UVD_MEMCHECK_SYS_INT_STAT__CM_HI_ERR__SHIFT 0xb
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_REF_LO_ERR__SHIFT 0xc
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_REF_HI_ERR__SHIFT 0xd
+#define UVD_MEMCHECK_SYS_INT_STAT__VCPU_LO_ERR__SHIFT 0xe
+#define UVD_MEMCHECK_SYS_INT_STAT__VCPU_HI_ERR__SHIFT 0xf
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_DBW_LO_ERR__SHIFT 0x10
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_DBW_HI_ERR__SHIFT 0x11
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_CM_COLOC_LO_ERR__SHIFT 0x12
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_CM_COLOC_HI_ERR__SHIFT 0x13
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_BSP0_LO_ERR__SHIFT 0x14
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_BSP0_HI_ERR__SHIFT 0x15
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_BSP1_LO_ERR__SHIFT 0x16
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_BSP1_HI_ERR__SHIFT 0x17
+#define UVD_MEMCHECK_SYS_INT_STAT__SRE_LO_ERR__SHIFT 0x18
+#define UVD_MEMCHECK_SYS_INT_STAT__SRE_HI_ERR__SHIFT 0x19
+#define UVD_MEMCHECK_SYS_INT_STAT__IT_RD_LO_ERR__SHIFT 0x1e
+#define UVD_MEMCHECK_SYS_INT_STAT__IT_RD_HI_ERR__SHIFT 0x1f
+#define UVD_MEMCHECK_SYS_INT_STAT__RE_LO_ERR_MASK 0x00000001L
+#define UVD_MEMCHECK_SYS_INT_STAT__RE_HI_ERR_MASK 0x00000002L
+#define UVD_MEMCHECK_SYS_INT_STAT__IT_LO_ERR_MASK 0x00000004L
+#define UVD_MEMCHECK_SYS_INT_STAT__IT_HI_ERR_MASK 0x00000008L
+#define UVD_MEMCHECK_SYS_INT_STAT__MP_LO_ERR_MASK 0x00000010L
+#define UVD_MEMCHECK_SYS_INT_STAT__MP_HI_ERR_MASK 0x00000020L
+#define UVD_MEMCHECK_SYS_INT_STAT__DB_LO_ERR_MASK 0x00000040L
+#define UVD_MEMCHECK_SYS_INT_STAT__DB_HI_ERR_MASK 0x00000080L
+#define UVD_MEMCHECK_SYS_INT_STAT__DBW_LO_ERR_MASK 0x00000100L
+#define UVD_MEMCHECK_SYS_INT_STAT__DBW_HI_ERR_MASK 0x00000200L
+#define UVD_MEMCHECK_SYS_INT_STAT__CM_LO_ERR_MASK 0x00000400L
+#define UVD_MEMCHECK_SYS_INT_STAT__CM_HI_ERR_MASK 0x00000800L
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_REF_LO_ERR_MASK 0x00001000L
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_REF_HI_ERR_MASK 0x00002000L
+#define UVD_MEMCHECK_SYS_INT_STAT__VCPU_LO_ERR_MASK 0x00004000L
+#define UVD_MEMCHECK_SYS_INT_STAT__VCPU_HI_ERR_MASK 0x00008000L
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_DBW_LO_ERR_MASK 0x00010000L
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_DBW_HI_ERR_MASK 0x00020000L
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_CM_COLOC_LO_ERR_MASK 0x00040000L
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_CM_COLOC_HI_ERR_MASK 0x00080000L
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_BSP0_LO_ERR_MASK 0x00100000L
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_BSP0_HI_ERR_MASK 0x00200000L
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_BSP1_LO_ERR_MASK 0x00400000L
+#define UVD_MEMCHECK_SYS_INT_STAT__MIF_BSP1_HI_ERR_MASK 0x00800000L
+#define UVD_MEMCHECK_SYS_INT_STAT__SRE_LO_ERR_MASK 0x01000000L
+#define UVD_MEMCHECK_SYS_INT_STAT__SRE_HI_ERR_MASK 0x02000000L
+#define UVD_MEMCHECK_SYS_INT_STAT__IT_RD_LO_ERR_MASK 0x40000000L
+#define UVD_MEMCHECK_SYS_INT_STAT__IT_RD_HI_ERR_MASK 0x80000000L
+//UVD_MEMCHECK_SYS_INT_ACK
+#define UVD_MEMCHECK_SYS_INT_ACK__RE_LO_ACK__SHIFT 0x0
+#define UVD_MEMCHECK_SYS_INT_ACK__RE_HI_ACK__SHIFT 0x1
+#define UVD_MEMCHECK_SYS_INT_ACK__IT_LO_ACK__SHIFT 0x2
+#define UVD_MEMCHECK_SYS_INT_ACK__IT_HI_ACK__SHIFT 0x3
+#define UVD_MEMCHECK_SYS_INT_ACK__MP_LO_ACK__SHIFT 0x4
+#define UVD_MEMCHECK_SYS_INT_ACK__MP_HI_ACK__SHIFT 0x5
+#define UVD_MEMCHECK_SYS_INT_ACK__DB_LO_ACK__SHIFT 0x6
+#define UVD_MEMCHECK_SYS_INT_ACK__DB_HI_ACK__SHIFT 0x7
+#define UVD_MEMCHECK_SYS_INT_ACK__DBW_LO_ACK__SHIFT 0x8
+#define UVD_MEMCHECK_SYS_INT_ACK__DBW_HI_ACK__SHIFT 0x9
+#define UVD_MEMCHECK_SYS_INT_ACK__CM_LO_ACK__SHIFT 0xa
+#define UVD_MEMCHECK_SYS_INT_ACK__CM_HI_ACK__SHIFT 0xb
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_REF_LO_ACK__SHIFT 0xc
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_REF_HI_ACK__SHIFT 0xd
+#define UVD_MEMCHECK_SYS_INT_ACK__VCPU_LO_ACK__SHIFT 0xe
+#define UVD_MEMCHECK_SYS_INT_ACK__VCPU_HI_ACK__SHIFT 0xf
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_DBW_LO_ACK__SHIFT 0x10
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_DBW_HI_ACK__SHIFT 0x11
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_CM_COLOC_LO_ACK__SHIFT 0x12
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_CM_COLOC_HI_ACK__SHIFT 0x13
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_BSP0_LO_ACK__SHIFT 0x14
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_BSP0_HI_ACK__SHIFT 0x15
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_BSP1_LO_ACK__SHIFT 0x16
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_BSP1_HI_ACK__SHIFT 0x17
+#define UVD_MEMCHECK_SYS_INT_ACK__SRE_LO_ACK__SHIFT 0x18
+#define UVD_MEMCHECK_SYS_INT_ACK__SRE_HI_ACK__SHIFT 0x19
+#define UVD_MEMCHECK_SYS_INT_ACK__IT_RD_LO_ACK__SHIFT 0x1e
+#define UVD_MEMCHECK_SYS_INT_ACK__IT_RD_HI_ACK__SHIFT 0x1f
+#define UVD_MEMCHECK_SYS_INT_ACK__RE_LO_ACK_MASK 0x00000001L
+#define UVD_MEMCHECK_SYS_INT_ACK__RE_HI_ACK_MASK 0x00000002L
+#define UVD_MEMCHECK_SYS_INT_ACK__IT_LO_ACK_MASK 0x00000004L
+#define UVD_MEMCHECK_SYS_INT_ACK__IT_HI_ACK_MASK 0x00000008L
+#define UVD_MEMCHECK_SYS_INT_ACK__MP_LO_ACK_MASK 0x00000010L
+#define UVD_MEMCHECK_SYS_INT_ACK__MP_HI_ACK_MASK 0x00000020L
+#define UVD_MEMCHECK_SYS_INT_ACK__DB_LO_ACK_MASK 0x00000040L
+#define UVD_MEMCHECK_SYS_INT_ACK__DB_HI_ACK_MASK 0x00000080L
+#define UVD_MEMCHECK_SYS_INT_ACK__DBW_LO_ACK_MASK 0x00000100L
+#define UVD_MEMCHECK_SYS_INT_ACK__DBW_HI_ACK_MASK 0x00000200L
+#define UVD_MEMCHECK_SYS_INT_ACK__CM_LO_ACK_MASK 0x00000400L
+#define UVD_MEMCHECK_SYS_INT_ACK__CM_HI_ACK_MASK 0x00000800L
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_REF_LO_ACK_MASK 0x00001000L
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_REF_HI_ACK_MASK 0x00002000L
+#define UVD_MEMCHECK_SYS_INT_ACK__VCPU_LO_ACK_MASK 0x00004000L
+#define UVD_MEMCHECK_SYS_INT_ACK__VCPU_HI_ACK_MASK 0x00008000L
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_DBW_LO_ACK_MASK 0x00010000L
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_DBW_HI_ACK_MASK 0x00020000L
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_CM_COLOC_LO_ACK_MASK 0x00040000L
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_CM_COLOC_HI_ACK_MASK 0x00080000L
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_BSP0_LO_ACK_MASK 0x00100000L
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_BSP0_HI_ACK_MASK 0x00200000L
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_BSP1_LO_ACK_MASK 0x00400000L
+#define UVD_MEMCHECK_SYS_INT_ACK__MIF_BSP1_HI_ACK_MASK 0x00800000L
+#define UVD_MEMCHECK_SYS_INT_ACK__SRE_LO_ACK_MASK 0x01000000L
+#define UVD_MEMCHECK_SYS_INT_ACK__SRE_HI_ACK_MASK 0x02000000L
+#define UVD_MEMCHECK_SYS_INT_ACK__IT_RD_LO_ACK_MASK 0x40000000L
+#define UVD_MEMCHECK_SYS_INT_ACK__IT_RD_HI_ACK_MASK 0x80000000L
+//UVD_MEMCHECK_VCPU_INT_EN
+#define UVD_MEMCHECK_VCPU_INT_EN__RE_ERR_EN__SHIFT 0x0
+#define UVD_MEMCHECK_VCPU_INT_EN__IT_ERR_EN__SHIFT 0x1
+#define UVD_MEMCHECK_VCPU_INT_EN__MP_ERR_EN__SHIFT 0x2
+#define UVD_MEMCHECK_VCPU_INT_EN__DB_ERR_EN__SHIFT 0x3
+#define UVD_MEMCHECK_VCPU_INT_EN__DBW_ERR_EN__SHIFT 0x4
+#define UVD_MEMCHECK_VCPU_INT_EN__CM_ERR_EN__SHIFT 0x5
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_REF_ERR_EN__SHIFT 0x6
+#define UVD_MEMCHECK_VCPU_INT_EN__VCPU_ERR_EN__SHIFT 0x7
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_DBW_ERR_EN__SHIFT 0x8
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_CM_COLOC_ERR_EN__SHIFT 0x9
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_BSP0_ERR_EN__SHIFT 0xa
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_BSP1_ERR_EN__SHIFT 0xb
+#define UVD_MEMCHECK_VCPU_INT_EN__SRE_ERR_EN__SHIFT 0xc
+#define UVD_MEMCHECK_VCPU_INT_EN__IT_RD_ERR_EN__SHIFT 0xf
+#define UVD_MEMCHECK_VCPU_INT_EN__CM_RD_ERR_EN__SHIFT 0x10
+#define UVD_MEMCHECK_VCPU_INT_EN__DB_RD_ERR_EN__SHIFT 0x11
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_RD_ERR_EN__SHIFT 0x12
+#define UVD_MEMCHECK_VCPU_INT_EN__IDCT_RD_ERR_EN__SHIFT 0x13
+#define UVD_MEMCHECK_VCPU_INT_EN__MPC_RD_ERR_EN__SHIFT 0x14
+#define UVD_MEMCHECK_VCPU_INT_EN__LBSI_RD_ERR_EN__SHIFT 0x15
+#define UVD_MEMCHECK_VCPU_INT_EN__RBC_RD_ERR_EN__SHIFT 0x18
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_BSP2_ERR_EN__SHIFT 0x19
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_BSP3_ERR_EN__SHIFT 0x1a
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_SCLR_ERR_EN__SHIFT 0x1b
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_SCLR2_ERR_EN__SHIFT 0x1c
+#define UVD_MEMCHECK_VCPU_INT_EN__PREF_ERR_EN__SHIFT 0x1d
+#define UVD_MEMCHECK_VCPU_INT_EN__RE_ERR_EN_MASK 0x00000001L
+#define UVD_MEMCHECK_VCPU_INT_EN__IT_ERR_EN_MASK 0x00000002L
+#define UVD_MEMCHECK_VCPU_INT_EN__MP_ERR_EN_MASK 0x00000004L
+#define UVD_MEMCHECK_VCPU_INT_EN__DB_ERR_EN_MASK 0x00000008L
+#define UVD_MEMCHECK_VCPU_INT_EN__DBW_ERR_EN_MASK 0x00000010L
+#define UVD_MEMCHECK_VCPU_INT_EN__CM_ERR_EN_MASK 0x00000020L
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_REF_ERR_EN_MASK 0x00000040L
+#define UVD_MEMCHECK_VCPU_INT_EN__VCPU_ERR_EN_MASK 0x00000080L
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_DBW_ERR_EN_MASK 0x00000100L
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_CM_COLOC_ERR_EN_MASK 0x00000200L
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_BSP0_ERR_EN_MASK 0x00000400L
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_BSP1_ERR_EN_MASK 0x00000800L
+#define UVD_MEMCHECK_VCPU_INT_EN__SRE_ERR_EN_MASK 0x00001000L
+#define UVD_MEMCHECK_VCPU_INT_EN__IT_RD_ERR_EN_MASK 0x00008000L
+#define UVD_MEMCHECK_VCPU_INT_EN__CM_RD_ERR_EN_MASK 0x00010000L
+#define UVD_MEMCHECK_VCPU_INT_EN__DB_RD_ERR_EN_MASK 0x00020000L
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_RD_ERR_EN_MASK 0x00040000L
+#define UVD_MEMCHECK_VCPU_INT_EN__IDCT_RD_ERR_EN_MASK 0x00080000L
+#define UVD_MEMCHECK_VCPU_INT_EN__MPC_RD_ERR_EN_MASK 0x00100000L
+#define UVD_MEMCHECK_VCPU_INT_EN__LBSI_RD_ERR_EN_MASK 0x00200000L
+#define UVD_MEMCHECK_VCPU_INT_EN__RBC_RD_ERR_EN_MASK 0x01000000L
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_BSP2_ERR_EN_MASK 0x02000000L
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_BSP3_ERR_EN_MASK 0x04000000L
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_SCLR_ERR_EN_MASK 0x08000000L
+#define UVD_MEMCHECK_VCPU_INT_EN__MIF_SCLR2_ERR_EN_MASK 0x10000000L
+#define UVD_MEMCHECK_VCPU_INT_EN__PREF_ERR_EN_MASK 0x20000000L
+//UVD_MEMCHECK_VCPU_INT_STAT
+#define UVD_MEMCHECK_VCPU_INT_STAT__RE_LO_ERR__SHIFT 0x0
+#define UVD_MEMCHECK_VCPU_INT_STAT__RE_HI_ERR__SHIFT 0x1
+#define UVD_MEMCHECK_VCPU_INT_STAT__IT_LO_ERR__SHIFT 0x2
+#define UVD_MEMCHECK_VCPU_INT_STAT__IT_HI_ERR__SHIFT 0x3
+#define UVD_MEMCHECK_VCPU_INT_STAT__MP_LO_ERR__SHIFT 0x4
+#define UVD_MEMCHECK_VCPU_INT_STAT__MP_HI_ERR__SHIFT 0x5
+#define UVD_MEMCHECK_VCPU_INT_STAT__DB_LO_ERR__SHIFT 0x6
+#define UVD_MEMCHECK_VCPU_INT_STAT__DB_HI_ERR__SHIFT 0x7
+#define UVD_MEMCHECK_VCPU_INT_STAT__DBW_LO_ERR__SHIFT 0x8
+#define UVD_MEMCHECK_VCPU_INT_STAT__DBW_HI_ERR__SHIFT 0x9
+#define UVD_MEMCHECK_VCPU_INT_STAT__CM_LO_ERR__SHIFT 0xa
+#define UVD_MEMCHECK_VCPU_INT_STAT__CM_HI_ERR__SHIFT 0xb
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_REF_LO_ERR__SHIFT 0xc
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_REF_HI_ERR__SHIFT 0xd
+#define UVD_MEMCHECK_VCPU_INT_STAT__VCPU_LO_ERR__SHIFT 0xe
+#define UVD_MEMCHECK_VCPU_INT_STAT__VCPU_HI_ERR__SHIFT 0xf
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_DBW_LO_ERR__SHIFT 0x10
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_DBW_HI_ERR__SHIFT 0x11
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_CM_COLOC_LO_ERR__SHIFT 0x12
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_CM_COLOC_HI_ERR__SHIFT 0x13
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_BSP0_LO_ERR__SHIFT 0x14
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_BSP0_HI_ERR__SHIFT 0x15
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_BSP1_LO_ERR__SHIFT 0x16
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_BSP1_HI_ERR__SHIFT 0x17
+#define UVD_MEMCHECK_VCPU_INT_STAT__SRE_LO_ERR__SHIFT 0x18
+#define UVD_MEMCHECK_VCPU_INT_STAT__SRE_HI_ERR__SHIFT 0x19
+#define UVD_MEMCHECK_VCPU_INT_STAT__IT_RD_LO_ERR__SHIFT 0x1e
+#define UVD_MEMCHECK_VCPU_INT_STAT__IT_RD_HI_ERR__SHIFT 0x1f
+#define UVD_MEMCHECK_VCPU_INT_STAT__RE_LO_ERR_MASK 0x00000001L
+#define UVD_MEMCHECK_VCPU_INT_STAT__RE_HI_ERR_MASK 0x00000002L
+#define UVD_MEMCHECK_VCPU_INT_STAT__IT_LO_ERR_MASK 0x00000004L
+#define UVD_MEMCHECK_VCPU_INT_STAT__IT_HI_ERR_MASK 0x00000008L
+#define UVD_MEMCHECK_VCPU_INT_STAT__MP_LO_ERR_MASK 0x00000010L
+#define UVD_MEMCHECK_VCPU_INT_STAT__MP_HI_ERR_MASK 0x00000020L
+#define UVD_MEMCHECK_VCPU_INT_STAT__DB_LO_ERR_MASK 0x00000040L
+#define UVD_MEMCHECK_VCPU_INT_STAT__DB_HI_ERR_MASK 0x00000080L
+#define UVD_MEMCHECK_VCPU_INT_STAT__DBW_LO_ERR_MASK 0x00000100L
+#define UVD_MEMCHECK_VCPU_INT_STAT__DBW_HI_ERR_MASK 0x00000200L
+#define UVD_MEMCHECK_VCPU_INT_STAT__CM_LO_ERR_MASK 0x00000400L
+#define UVD_MEMCHECK_VCPU_INT_STAT__CM_HI_ERR_MASK 0x00000800L
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_REF_LO_ERR_MASK 0x00001000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_REF_HI_ERR_MASK 0x00002000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__VCPU_LO_ERR_MASK 0x00004000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__VCPU_HI_ERR_MASK 0x00008000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_DBW_LO_ERR_MASK 0x00010000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_DBW_HI_ERR_MASK 0x00020000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_CM_COLOC_LO_ERR_MASK 0x00040000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_CM_COLOC_HI_ERR_MASK 0x00080000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_BSP0_LO_ERR_MASK 0x00100000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_BSP0_HI_ERR_MASK 0x00200000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_BSP1_LO_ERR_MASK 0x00400000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__MIF_BSP1_HI_ERR_MASK 0x00800000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__SRE_LO_ERR_MASK 0x01000000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__SRE_HI_ERR_MASK 0x02000000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__IT_RD_LO_ERR_MASK 0x40000000L
+#define UVD_MEMCHECK_VCPU_INT_STAT__IT_RD_HI_ERR_MASK 0x80000000L
+//UVD_MEMCHECK_VCPU_INT_ACK
+#define UVD_MEMCHECK_VCPU_INT_ACK__RE_LO_ACK__SHIFT 0x0
+#define UVD_MEMCHECK_VCPU_INT_ACK__RE_HI_ACK__SHIFT 0x1
+#define UVD_MEMCHECK_VCPU_INT_ACK__IT_LO_ACK__SHIFT 0x2
+#define UVD_MEMCHECK_VCPU_INT_ACK__IT_HI_ACK__SHIFT 0x3
+#define UVD_MEMCHECK_VCPU_INT_ACK__MP_LO_ACK__SHIFT 0x4
+#define UVD_MEMCHECK_VCPU_INT_ACK__MP_HI_ACK__SHIFT 0x5
+#define UVD_MEMCHECK_VCPU_INT_ACK__DB_LO_ACK__SHIFT 0x6
+#define UVD_MEMCHECK_VCPU_INT_ACK__DB_HI_ACK__SHIFT 0x7
+#define UVD_MEMCHECK_VCPU_INT_ACK__DBW_LO_ACK__SHIFT 0x8
+#define UVD_MEMCHECK_VCPU_INT_ACK__DBW_HI_ACK__SHIFT 0x9
+#define UVD_MEMCHECK_VCPU_INT_ACK__CM_LO_ACK__SHIFT 0xa
+#define UVD_MEMCHECK_VCPU_INT_ACK__CM_HI_ACK__SHIFT 0xb
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_REF_LO_ACK__SHIFT 0xc
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_REF_HI_ACK__SHIFT 0xd
+#define UVD_MEMCHECK_VCPU_INT_ACK__VCPU_LO_ACK__SHIFT 0xe
+#define UVD_MEMCHECK_VCPU_INT_ACK__VCPU_HI_ACK__SHIFT 0xf
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_DBW_LO_ACK__SHIFT 0x10
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_DBW_HI_ACK__SHIFT 0x11
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_CM_COLOC_LO_ACK__SHIFT 0x12
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_CM_COLOC_HI_ACK__SHIFT 0x13
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_BSP0_LO_ACK__SHIFT 0x14
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_BSP0_HI_ACK__SHIFT 0x15
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_BSP1_LO_ACK__SHIFT 0x16
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_BSP1_HI_ACK__SHIFT 0x17
+#define UVD_MEMCHECK_VCPU_INT_ACK__SRE_LO_ACK__SHIFT 0x18
+#define UVD_MEMCHECK_VCPU_INT_ACK__SRE_HI_ACK__SHIFT 0x19
+#define UVD_MEMCHECK_VCPU_INT_ACK__IT_RD_LO_ACK__SHIFT 0x1e
+#define UVD_MEMCHECK_VCPU_INT_ACK__IT_RD_HI_ACK__SHIFT 0x1f
+#define UVD_MEMCHECK_VCPU_INT_ACK__RE_LO_ACK_MASK 0x00000001L
+#define UVD_MEMCHECK_VCPU_INT_ACK__RE_HI_ACK_MASK 0x00000002L
+#define UVD_MEMCHECK_VCPU_INT_ACK__IT_LO_ACK_MASK 0x00000004L
+#define UVD_MEMCHECK_VCPU_INT_ACK__IT_HI_ACK_MASK 0x00000008L
+#define UVD_MEMCHECK_VCPU_INT_ACK__MP_LO_ACK_MASK 0x00000010L
+#define UVD_MEMCHECK_VCPU_INT_ACK__MP_HI_ACK_MASK 0x00000020L
+#define UVD_MEMCHECK_VCPU_INT_ACK__DB_LO_ACK_MASK 0x00000040L
+#define UVD_MEMCHECK_VCPU_INT_ACK__DB_HI_ACK_MASK 0x00000080L
+#define UVD_MEMCHECK_VCPU_INT_ACK__DBW_LO_ACK_MASK 0x00000100L
+#define UVD_MEMCHECK_VCPU_INT_ACK__DBW_HI_ACK_MASK 0x00000200L
+#define UVD_MEMCHECK_VCPU_INT_ACK__CM_LO_ACK_MASK 0x00000400L
+#define UVD_MEMCHECK_VCPU_INT_ACK__CM_HI_ACK_MASK 0x00000800L
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_REF_LO_ACK_MASK 0x00001000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_REF_HI_ACK_MASK 0x00002000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__VCPU_LO_ACK_MASK 0x00004000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__VCPU_HI_ACK_MASK 0x00008000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_DBW_LO_ACK_MASK 0x00010000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_DBW_HI_ACK_MASK 0x00020000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_CM_COLOC_LO_ACK_MASK 0x00040000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_CM_COLOC_HI_ACK_MASK 0x00080000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_BSP0_LO_ACK_MASK 0x00100000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_BSP0_HI_ACK_MASK 0x00200000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_BSP1_LO_ACK_MASK 0x00400000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__MIF_BSP1_HI_ACK_MASK 0x00800000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__SRE_LO_ACK_MASK 0x01000000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__SRE_HI_ACK_MASK 0x02000000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__IT_RD_LO_ACK_MASK 0x40000000L
+#define UVD_MEMCHECK_VCPU_INT_ACK__IT_RD_HI_ACK_MASK 0x80000000L
+//UVD_MEMCHECK2_SYS_INT_STAT
+#define UVD_MEMCHECK2_SYS_INT_STAT__CM_RD_LO_ERR__SHIFT 0x0
+#define UVD_MEMCHECK2_SYS_INT_STAT__CM_RD_HI_ERR__SHIFT 0x1
+#define UVD_MEMCHECK2_SYS_INT_STAT__DB_RD_LO_ERR__SHIFT 0x2
+#define UVD_MEMCHECK2_SYS_INT_STAT__DB_RD_HI_ERR__SHIFT 0x3
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_RD_LO_ERR__SHIFT 0x4
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_RD_HI_ERR__SHIFT 0x5
+#define UVD_MEMCHECK2_SYS_INT_STAT__IDCT_RD_LO_ERR__SHIFT 0x6
+#define UVD_MEMCHECK2_SYS_INT_STAT__IDCT_RD_HI_ERR__SHIFT 0x7
+#define UVD_MEMCHECK2_SYS_INT_STAT__MPC_RD_LO_ERR__SHIFT 0x8
+#define UVD_MEMCHECK2_SYS_INT_STAT__MPC_RD_HI_ERR__SHIFT 0x9
+#define UVD_MEMCHECK2_SYS_INT_STAT__LBSI_RD_LO_ERR__SHIFT 0xa
+#define UVD_MEMCHECK2_SYS_INT_STAT__LBSI_RD_HI_ERR__SHIFT 0xb
+#define UVD_MEMCHECK2_SYS_INT_STAT__RBC_RD_LO_ERR__SHIFT 0x10
+#define UVD_MEMCHECK2_SYS_INT_STAT__RBC_RD_HI_ERR__SHIFT 0x11
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_BSP2_LO_ERR__SHIFT 0x16
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_BSP2_HI_ERR__SHIFT 0x17
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_BSP3_LO_ERR__SHIFT 0x18
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_BSP3_HI_ERR__SHIFT 0x19
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_SCLR_LO_ERR__SHIFT 0x1a
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_SCLR_HI_ERR__SHIFT 0x1b
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_SCLR2_LO_ERR__SHIFT 0x1c
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_SCLR2_HI_ERR__SHIFT 0x1d
+#define UVD_MEMCHECK2_SYS_INT_STAT__PREF_LO_ERR__SHIFT 0x1e
+#define UVD_MEMCHECK2_SYS_INT_STAT__PREF_HI_ERR__SHIFT 0x1f
+#define UVD_MEMCHECK2_SYS_INT_STAT__CM_RD_LO_ERR_MASK 0x00000001L
+#define UVD_MEMCHECK2_SYS_INT_STAT__CM_RD_HI_ERR_MASK 0x00000002L
+#define UVD_MEMCHECK2_SYS_INT_STAT__DB_RD_LO_ERR_MASK 0x00000004L
+#define UVD_MEMCHECK2_SYS_INT_STAT__DB_RD_HI_ERR_MASK 0x00000008L
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_RD_LO_ERR_MASK 0x00000010L
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_RD_HI_ERR_MASK 0x00000020L
+#define UVD_MEMCHECK2_SYS_INT_STAT__IDCT_RD_LO_ERR_MASK 0x00000040L
+#define UVD_MEMCHECK2_SYS_INT_STAT__IDCT_RD_HI_ERR_MASK 0x00000080L
+#define UVD_MEMCHECK2_SYS_INT_STAT__MPC_RD_LO_ERR_MASK 0x00000100L
+#define UVD_MEMCHECK2_SYS_INT_STAT__MPC_RD_HI_ERR_MASK 0x00000200L
+#define UVD_MEMCHECK2_SYS_INT_STAT__LBSI_RD_LO_ERR_MASK 0x00000400L
+#define UVD_MEMCHECK2_SYS_INT_STAT__LBSI_RD_HI_ERR_MASK 0x00000800L
+#define UVD_MEMCHECK2_SYS_INT_STAT__RBC_RD_LO_ERR_MASK 0x00010000L
+#define UVD_MEMCHECK2_SYS_INT_STAT__RBC_RD_HI_ERR_MASK 0x00020000L
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_BSP2_LO_ERR_MASK 0x00400000L
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_BSP2_HI_ERR_MASK 0x00800000L
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_BSP3_LO_ERR_MASK 0x01000000L
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_BSP3_HI_ERR_MASK 0x02000000L
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_SCLR_LO_ERR_MASK 0x04000000L
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_SCLR_HI_ERR_MASK 0x08000000L
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_SCLR2_LO_ERR_MASK 0x10000000L
+#define UVD_MEMCHECK2_SYS_INT_STAT__MIF_SCLR2_HI_ERR_MASK 0x20000000L
+#define UVD_MEMCHECK2_SYS_INT_STAT__PREF_LO_ERR_MASK 0x40000000L
+#define UVD_MEMCHECK2_SYS_INT_STAT__PREF_HI_ERR_MASK 0x80000000L
+//UVD_MEMCHECK2_SYS_INT_ACK
+#define UVD_MEMCHECK2_SYS_INT_ACK__CM_RD_LO_ACK__SHIFT 0x0
+#define UVD_MEMCHECK2_SYS_INT_ACK__CM_RD_HI_ACK__SHIFT 0x1
+#define UVD_MEMCHECK2_SYS_INT_ACK__DB_RD_LO_ACK__SHIFT 0x2
+#define UVD_MEMCHECK2_SYS_INT_ACK__DB_RD_HI_ACK__SHIFT 0x3
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_RD_LO_ACK__SHIFT 0x4
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_RD_HI_ACK__SHIFT 0x5
+#define UVD_MEMCHECK2_SYS_INT_ACK__IDCT_RD_LO_ACK__SHIFT 0x6
+#define UVD_MEMCHECK2_SYS_INT_ACK__IDCT_RD_HI_ACK__SHIFT 0x7
+#define UVD_MEMCHECK2_SYS_INT_ACK__MPC_RD_LO_ACK__SHIFT 0x8
+#define UVD_MEMCHECK2_SYS_INT_ACK__MPC_RD_HI_ACK__SHIFT 0x9
+#define UVD_MEMCHECK2_SYS_INT_ACK__LBSI_RD_LO_ACK__SHIFT 0xa
+#define UVD_MEMCHECK2_SYS_INT_ACK__LBSI_RD_HI_ACK__SHIFT 0xb
+#define UVD_MEMCHECK2_SYS_INT_ACK__RBC_RD_LO_ACK__SHIFT 0x10
+#define UVD_MEMCHECK2_SYS_INT_ACK__RBC_RD_HI_ACK__SHIFT 0x11
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_BSP2_LO_ACK__SHIFT 0x16
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_BSP2_HI_ACK__SHIFT 0x17
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_BSP3_LO_ACK__SHIFT 0x18
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_BSP3_HI_ACK__SHIFT 0x19
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_SCLR_LO_ACK__SHIFT 0x1a
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_SCLR_HI_ACK__SHIFT 0x1b
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_SCLR2_LO_ACK__SHIFT 0x1c
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_SCLR2_HI_ACK__SHIFT 0x1d
+#define UVD_MEMCHECK2_SYS_INT_ACK__PREF_LO_ACK__SHIFT 0x1e
+#define UVD_MEMCHECK2_SYS_INT_ACK__PREF_HI_ACK__SHIFT 0x1f
+#define UVD_MEMCHECK2_SYS_INT_ACK__CM_RD_LO_ACK_MASK 0x00000001L
+#define UVD_MEMCHECK2_SYS_INT_ACK__CM_RD_HI_ACK_MASK 0x00000002L
+#define UVD_MEMCHECK2_SYS_INT_ACK__DB_RD_LO_ACK_MASK 0x00000004L
+#define UVD_MEMCHECK2_SYS_INT_ACK__DB_RD_HI_ACK_MASK 0x00000008L
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_RD_LO_ACK_MASK 0x00000010L
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_RD_HI_ACK_MASK 0x00000020L
+#define UVD_MEMCHECK2_SYS_INT_ACK__IDCT_RD_LO_ACK_MASK 0x00000040L
+#define UVD_MEMCHECK2_SYS_INT_ACK__IDCT_RD_HI_ACK_MASK 0x00000080L
+#define UVD_MEMCHECK2_SYS_INT_ACK__MPC_RD_LO_ACK_MASK 0x00000100L
+#define UVD_MEMCHECK2_SYS_INT_ACK__MPC_RD_HI_ACK_MASK 0x00000200L
+#define UVD_MEMCHECK2_SYS_INT_ACK__LBSI_RD_LO_ACK_MASK 0x00000400L
+#define UVD_MEMCHECK2_SYS_INT_ACK__LBSI_RD_HI_ACK_MASK 0x00000800L
+#define UVD_MEMCHECK2_SYS_INT_ACK__RBC_RD_LO_ACK_MASK 0x00010000L
+#define UVD_MEMCHECK2_SYS_INT_ACK__RBC_RD_HI_ACK_MASK 0x00020000L
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_BSP2_LO_ACK_MASK 0x00400000L
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_BSP2_HI_ACK_MASK 0x00800000L
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_BSP3_LO_ACK_MASK 0x01000000L
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_BSP3_HI_ACK_MASK 0x02000000L
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_SCLR_LO_ACK_MASK 0x04000000L
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_SCLR_HI_ACK_MASK 0x08000000L
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_SCLR2_LO_ACK_MASK 0x10000000L
+#define UVD_MEMCHECK2_SYS_INT_ACK__MIF_SCLR2_HI_ACK_MASK 0x20000000L
+#define UVD_MEMCHECK2_SYS_INT_ACK__PREF_LO_ACK_MASK 0x40000000L
+#define UVD_MEMCHECK2_SYS_INT_ACK__PREF_HI_ACK_MASK 0x80000000L
+//UVD_MEMCHECK2_VCPU_INT_STAT
+#define UVD_MEMCHECK2_VCPU_INT_STAT__CM_RD_LO_ERR__SHIFT 0x0
+#define UVD_MEMCHECK2_VCPU_INT_STAT__CM_RD_HI_ERR__SHIFT 0x1
+#define UVD_MEMCHECK2_VCPU_INT_STAT__DB_RD_LO_ERR__SHIFT 0x2
+#define UVD_MEMCHECK2_VCPU_INT_STAT__DB_RD_HI_ERR__SHIFT 0x3
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_RD_LO_ERR__SHIFT 0x4
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_RD_HI_ERR__SHIFT 0x5
+#define UVD_MEMCHECK2_VCPU_INT_STAT__IDCT_RD_LO_ERR__SHIFT 0x6
+#define UVD_MEMCHECK2_VCPU_INT_STAT__IDCT_RD_HI_ERR__SHIFT 0x7
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MPC_RD_LO_ERR__SHIFT 0x8
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MPC_RD_HI_ERR__SHIFT 0x9
+#define UVD_MEMCHECK2_VCPU_INT_STAT__LBSI_RD_LO_ERR__SHIFT 0xa
+#define UVD_MEMCHECK2_VCPU_INT_STAT__LBSI_RD_HI_ERR__SHIFT 0xb
+#define UVD_MEMCHECK2_VCPU_INT_STAT__RBC_RD_LO_ERR__SHIFT 0x10
+#define UVD_MEMCHECK2_VCPU_INT_STAT__RBC_RD_HI_ERR__SHIFT 0x11
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_BSP2_LO_ERR__SHIFT 0x12
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_BSP2_HI_ERR__SHIFT 0x13
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_BSP3_LO_ERR__SHIFT 0x14
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_BSP3_HI_ERR__SHIFT 0x15
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_SCLR_LO_ERR__SHIFT 0x16
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_SCLR_HI_ERR__SHIFT 0x17
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_SCLR2_LO_ERR__SHIFT 0x18
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_SCLR2_HI_ERR__SHIFT 0x19
+#define UVD_MEMCHECK2_VCPU_INT_STAT__PREF_LO_ERR__SHIFT 0x1a
+#define UVD_MEMCHECK2_VCPU_INT_STAT__PREF_HI_ERR__SHIFT 0x1b
+#define UVD_MEMCHECK2_VCPU_INT_STAT__CM_RD_LO_ERR_MASK 0x00000001L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__CM_RD_HI_ERR_MASK 0x00000002L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__DB_RD_LO_ERR_MASK 0x00000004L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__DB_RD_HI_ERR_MASK 0x00000008L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_RD_LO_ERR_MASK 0x00000010L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_RD_HI_ERR_MASK 0x00000020L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__IDCT_RD_LO_ERR_MASK 0x00000040L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__IDCT_RD_HI_ERR_MASK 0x00000080L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MPC_RD_LO_ERR_MASK 0x00000100L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MPC_RD_HI_ERR_MASK 0x00000200L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__LBSI_RD_LO_ERR_MASK 0x00000400L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__LBSI_RD_HI_ERR_MASK 0x00000800L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__RBC_RD_LO_ERR_MASK 0x00010000L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__RBC_RD_HI_ERR_MASK 0x00020000L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_BSP2_LO_ERR_MASK 0x00040000L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_BSP2_HI_ERR_MASK 0x00080000L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_BSP3_LO_ERR_MASK 0x00100000L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_BSP3_HI_ERR_MASK 0x00200000L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_SCLR_LO_ERR_MASK 0x00400000L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_SCLR_HI_ERR_MASK 0x00800000L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_SCLR2_LO_ERR_MASK 0x01000000L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__MIF_SCLR2_HI_ERR_MASK 0x02000000L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__PREF_LO_ERR_MASK 0x04000000L
+#define UVD_MEMCHECK2_VCPU_INT_STAT__PREF_HI_ERR_MASK 0x08000000L
+//UVD_MEMCHECK2_VCPU_INT_ACK
+#define UVD_MEMCHECK2_VCPU_INT_ACK__CM_RD_LO_ACK__SHIFT 0x0
+#define UVD_MEMCHECK2_VCPU_INT_ACK__CM_RD_HI_ACK__SHIFT 0x1
+#define UVD_MEMCHECK2_VCPU_INT_ACK__DB_RD_LO_ACK__SHIFT 0x2
+#define UVD_MEMCHECK2_VCPU_INT_ACK__DB_RD_HI_ACK__SHIFT 0x3
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_RD_LO_ACK__SHIFT 0x4
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_RD_HI_ACK__SHIFT 0x5
+#define UVD_MEMCHECK2_VCPU_INT_ACK__IDCT_RD_LO_ACK__SHIFT 0x6
+#define UVD_MEMCHECK2_VCPU_INT_ACK__IDCT_RD_HI_ACK__SHIFT 0x7
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MPC_RD_LO_ACK__SHIFT 0x8
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MPC_RD_HI_ACK__SHIFT 0x9
+#define UVD_MEMCHECK2_VCPU_INT_ACK__LBSI_RD_LO_ACK__SHIFT 0xa
+#define UVD_MEMCHECK2_VCPU_INT_ACK__LBSI_RD_HI_ACK__SHIFT 0xb
+#define UVD_MEMCHECK2_VCPU_INT_ACK__RBC_RD_LO_ACK__SHIFT 0x10
+#define UVD_MEMCHECK2_VCPU_INT_ACK__RBC_RD_HI_ACK__SHIFT 0x11
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_BSP2_LO_ACK__SHIFT 0x12
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_BSP2_HI_ACK__SHIFT 0x13
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_BSP3_LO_ACK__SHIFT 0x14
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_BSP3_HI_ACK__SHIFT 0x15
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_SCLR_LO_ACK__SHIFT 0x16
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_SCLR_HI_ACK__SHIFT 0x17
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_SCLR2_LO_ACK__SHIFT 0x18
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_SCLR2_HI_ACK__SHIFT 0x19
+#define UVD_MEMCHECK2_VCPU_INT_ACK__PREF_LO_ACK__SHIFT 0x1a
+#define UVD_MEMCHECK2_VCPU_INT_ACK__PREF_HI_ACK__SHIFT 0x1b
+#define UVD_MEMCHECK2_VCPU_INT_ACK__CM_RD_LO_ACK_MASK 0x00000001L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__CM_RD_HI_ACK_MASK 0x00000002L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__DB_RD_LO_ACK_MASK 0x00000004L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__DB_RD_HI_ACK_MASK 0x00000008L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_RD_LO_ACK_MASK 0x00000010L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_RD_HI_ACK_MASK 0x00000020L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__IDCT_RD_LO_ACK_MASK 0x00000040L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__IDCT_RD_HI_ACK_MASK 0x00000080L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MPC_RD_LO_ACK_MASK 0x00000100L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MPC_RD_HI_ACK_MASK 0x00000200L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__LBSI_RD_LO_ACK_MASK 0x00000400L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__LBSI_RD_HI_ACK_MASK 0x00000800L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__RBC_RD_LO_ACK_MASK 0x00010000L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__RBC_RD_HI_ACK_MASK 0x00020000L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_BSP2_LO_ACK_MASK 0x00040000L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_BSP2_HI_ACK_MASK 0x00080000L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_BSP3_LO_ACK_MASK 0x00100000L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_BSP3_HI_ACK_MASK 0x00200000L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_SCLR_LO_ACK_MASK 0x00400000L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_SCLR_HI_ACK_MASK 0x00800000L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_SCLR2_LO_ACK_MASK 0x01000000L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__MIF_SCLR2_HI_ACK_MASK 0x02000000L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__PREF_LO_ACK_MASK 0x04000000L
+#define UVD_MEMCHECK2_VCPU_INT_ACK__PREF_HI_ACK_MASK 0x08000000L
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h
index bbe1337a8cee..e68c1e280322 100644
--- a/drivers/gpu/drm/amd/include/atomfirmware.h
+++ b/drivers/gpu/drm/amd/include/atomfirmware.h
@@ -182,6 +182,7 @@ enum atom_dgpu_vram_type {
ATOM_DGPU_VRAM_TYPE_HBM2 = 0x60,
ATOM_DGPU_VRAM_TYPE_HBM2E = 0x61,
ATOM_DGPU_VRAM_TYPE_GDDR6 = 0x70,
+ ATOM_DGPU_VRAM_TYPE_HBM3 = 0x80,
};
enum atom_dp_vs_preemph_def{
diff --git a/drivers/gpu/drm/amd/include/discovery.h b/drivers/gpu/drm/amd/include/discovery.h
index f150404ffc68..f43e29722ef7 100644
--- a/drivers/gpu/drm/amd/include/discovery.h
+++ b/drivers/gpu/drm/amd/include/discovery.h
@@ -79,7 +79,14 @@ typedef struct ip_discovery_header
uint32_t id; /* Table ID */
uint16_t num_dies; /* Number of Dies */
die_info die_info[16]; /* list die information for up to 16 dies */
- uint16_t padding[1]; /* padding */
+ union {
+ uint16_t padding[1]; /* version <= 3 */
+ struct { /* version == 4 */
+ uint8_t base_addr_64_bit : 1; /* ip structures are using 64 bit base address */
+ uint8_t reserved : 7;
+ uint8_t reserved2;
+ };
+ };
} ip_discovery_header;
typedef struct ip
@@ -115,9 +122,29 @@ typedef struct ip_v3
uint8_t sub_revision : 4; /* HCID Sub-Revision */
uint8_t variant : 4; /* HW variant */
#endif
- uint32_t base_address[1]; /* Base Address list. Corresponds to the num_base_address field*/
+ uint32_t base_address[]; /* Base Address list. Corresponds to the num_base_address field*/
} ip_v3;
+typedef struct ip_v4 {
+ uint16_t hw_id; /* Hardware ID */
+ uint8_t instance_number; /* Instance number for the IP */
+ uint8_t num_base_address; /* Number of base addresses*/
+ uint8_t major; /* Hardware ID.major version */
+ uint8_t minor; /* Hardware ID.minor version */
+ uint8_t revision; /* Hardware ID.revision version */
+#if defined(LITTLEENDIAN_CPU)
+ uint8_t sub_revision : 4; /* HCID Sub-Revision */
+ uint8_t variant : 4; /* HW variant */
+#elif defined(BIGENDIAN_CPU)
+ uint8_t variant : 4; /* HW variant */
+ uint8_t sub_revision : 4; /* HCID Sub-Revision */
+#endif
+ union {
+ DECLARE_FLEX_ARRAY(uint32_t, base_address); /* 32-bit Base Address list. Corresponds to the num_base_address field*/
+ DECLARE_FLEX_ARRAY(uint64_t, base_address_64); /* 64-bit Base Address list. Corresponds to the num_base_address field*/
+ } __packed;
+} ip_v4;
+
typedef struct die_header
{
uint16_t die_id;
@@ -134,6 +161,7 @@ typedef struct ip_structure
{
ip *ip_list;
ip_v3 *ip_v3_list;
+ ip_v4 *ip_v4_list;
}; /* IP list. Variable size*/
} die;
} ip_structure;
diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
index 5cb3e8634739..d0df3381539f 100644
--- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
@@ -230,28 +230,30 @@ struct kfd2kgd_calls {
/* Register access functions */
void (*program_sh_mem_settings)(struct amdgpu_device *adev, uint32_t vmid,
uint32_t sh_mem_config, uint32_t sh_mem_ape1_base,
- uint32_t sh_mem_ape1_limit, uint32_t sh_mem_bases);
+ uint32_t sh_mem_ape1_limit, uint32_t sh_mem_bases,
+ uint32_t inst);
int (*set_pasid_vmid_mapping)(struct amdgpu_device *adev, u32 pasid,
- unsigned int vmid);
+ unsigned int vmid, uint32_t inst);
- int (*init_interrupts)(struct amdgpu_device *adev, uint32_t pipe_id);
+ int (*init_interrupts)(struct amdgpu_device *adev, uint32_t pipe_id,
+ uint32_t inst);
int (*hqd_load)(struct amdgpu_device *adev, void *mqd, uint32_t pipe_id,
uint32_t queue_id, uint32_t __user *wptr,
uint32_t wptr_shift, uint32_t wptr_mask,
- struct mm_struct *mm);
+ struct mm_struct *mm, uint32_t inst);
int (*hiq_mqd_load)(struct amdgpu_device *adev, void *mqd,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t doorbell_off);
+ uint32_t doorbell_off, uint32_t inst);
int (*hqd_sdma_load)(struct amdgpu_device *adev, void *mqd,
uint32_t __user *wptr, struct mm_struct *mm);
int (*hqd_dump)(struct amdgpu_device *adev,
uint32_t pipe_id, uint32_t queue_id,
- uint32_t (**dump)[2], uint32_t *n_regs);
+ uint32_t (**dump)[2], uint32_t *n_regs, uint32_t inst);
int (*hqd_sdma_dump)(struct amdgpu_device *adev,
uint32_t engine_id, uint32_t queue_id,
@@ -259,12 +261,12 @@ struct kfd2kgd_calls {
bool (*hqd_is_occupied)(struct amdgpu_device *adev,
uint64_t queue_address, uint32_t pipe_id,
- uint32_t queue_id);
+ uint32_t queue_id, uint32_t inst);
int (*hqd_destroy)(struct amdgpu_device *adev, void *mqd,
enum kfd_preempt_type reset_type,
unsigned int timeout, uint32_t pipe_id,
- uint32_t queue_id);
+ uint32_t queue_id, uint32_t inst);
bool (*hqd_sdma_is_occupied)(struct amdgpu_device *adev, void *mqd);
@@ -273,7 +275,7 @@ struct kfd2kgd_calls {
int (*wave_control_execute)(struct amdgpu_device *adev,
uint32_t gfx_index_val,
- uint32_t sq_cmd);
+ uint32_t sq_cmd, uint32_t inst);
bool (*get_atc_vmid_pasid_mapping_info)(struct amdgpu_device *adev,
uint8_t vmid,
uint16_t *p_pasid);
@@ -289,10 +291,45 @@ struct kfd2kgd_calls {
uint32_t vmid, uint64_t page_table_base);
uint32_t (*read_vmid_from_vmfault_reg)(struct amdgpu_device *adev);
+ uint32_t (*enable_debug_trap)(struct amdgpu_device *adev,
+ bool restore_dbg_registers,
+ uint32_t vmid);
+ uint32_t (*disable_debug_trap)(struct amdgpu_device *adev,
+ bool keep_trap_enabled,
+ uint32_t vmid);
+ int (*validate_trap_override_request)(struct amdgpu_device *adev,
+ uint32_t trap_override,
+ uint32_t *trap_mask_supported);
+ uint32_t (*set_wave_launch_trap_override)(struct amdgpu_device *adev,
+ uint32_t vmid,
+ uint32_t trap_override,
+ uint32_t trap_mask_bits,
+ uint32_t trap_mask_request,
+ uint32_t *trap_mask_prev,
+ uint32_t kfd_dbg_trap_cntl_prev);
+ uint32_t (*set_wave_launch_mode)(struct amdgpu_device *adev,
+ uint8_t wave_launch_mode,
+ uint32_t vmid);
+ uint32_t (*set_address_watch)(struct amdgpu_device *adev,
+ uint64_t watch_address,
+ uint32_t watch_address_mask,
+ uint32_t watch_id,
+ uint32_t watch_mode,
+ uint32_t debug_vmid);
+ uint32_t (*clear_address_watch)(struct amdgpu_device *adev,
+ uint32_t watch_id);
+ void (*get_iq_wait_times)(struct amdgpu_device *adev,
+ uint32_t *wait_times);
+ void (*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);
void (*get_cu_occupancy)(struct amdgpu_device *adev, int pasid,
- int *wave_cnt, int *max_waves_per_cu);
+ int *wave_cnt, int *max_waves_per_cu, uint32_t inst);
void (*program_trap_handler_settings)(struct amdgpu_device *adev,
- uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr);
+ uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr,
+ uint32_t inst);
};
#endif /* KGD_KFD_INTERFACE_H_INCLUDED */
diff --git a/drivers/gpu/drm/amd/include/mes_v11_api_def.h b/drivers/gpu/drm/amd/include/mes_v11_api_def.h
index dc694cb246d9..0997e999416a 100644
--- a/drivers/gpu/drm/amd/include/mes_v11_api_def.h
+++ b/drivers/gpu/drm/amd/include/mes_v11_api_def.h
@@ -274,7 +274,8 @@ union MESAPI__ADD_QUEUE {
uint32_t is_kfd_process : 1;
uint32_t trap_en : 1;
uint32_t is_aql_queue : 1;
- uint32_t reserved : 20;
+ uint32_t skip_process_ctx_clear : 1;
+ uint32_t reserved : 19;
};
struct MES_API_STATUS api_status;
uint64_t tma_addr;
@@ -523,6 +524,7 @@ enum MESAPI_MISC_OPCODE {
MESAPI_MISC__QUERY_STATUS,
MESAPI_MISC__READ_REG,
MESAPI_MISC__WAIT_REG_MEM,
+ MESAPI_MISC__SET_SHADER_DEBUGGER,
MESAPI_MISC__MAX,
};
@@ -561,6 +563,21 @@ struct QUERY_STATUS {
uint32_t context_id;
};
+struct SET_SHADER_DEBUGGER {
+ uint64_t process_context_addr;
+ union {
+ struct {
+ uint32_t single_memop : 1; /* SQ_DEBUG.single_memop */
+ uint32_t single_alu_op : 1; /* SQ_DEBUG.single_alu_op */
+ uint32_t reserved : 30;
+ };
+ uint32_t u32all;
+ } flags;
+ uint32_t spi_gdbg_per_vmid_cntl;
+ uint32_t tcp_watch_cntl[4]; /* TCP_WATCHx_CNTL */
+ uint32_t trap_en;
+};
+
union MESAPI__MISC {
struct {
union MES_API_HEADER header;
@@ -573,6 +590,9 @@ union MESAPI__MISC {
struct QUERY_STATUS query_status;
struct READ_REG read_reg;
struct WAIT_REG_MEM wait_reg_mem;
+ struct SET_SHADER_DEBUGGER set_shader_debugger;
+ enum MES_AMD_PRIORITY_LEVEL queue_sch_level;
+
uint32_t data[MISC_DATA_MAX_SIZE_IN_DWORDS];
};
};
diff --git a/drivers/gpu/drm/amd/include/v9_structs.h b/drivers/gpu/drm/amd/include/v9_structs.h
index a0c672889fe4..a2f81b9c38af 100644
--- a/drivers/gpu/drm/amd/include/v9_structs.h
+++ b/drivers/gpu/drm/amd/include/v9_structs.h
@@ -196,10 +196,20 @@ struct v9_mqd {
uint32_t compute_wave_restore_addr_lo;
uint32_t compute_wave_restore_addr_hi;
uint32_t compute_wave_restore_control;
- uint32_t compute_static_thread_mgmt_se4;
- uint32_t compute_static_thread_mgmt_se5;
- uint32_t compute_static_thread_mgmt_se6;
- uint32_t compute_static_thread_mgmt_se7;
+ union {
+ struct {
+ uint32_t compute_static_thread_mgmt_se4;
+ uint32_t compute_static_thread_mgmt_se5;
+ uint32_t compute_static_thread_mgmt_se6;
+ uint32_t compute_static_thread_mgmt_se7;
+ };
+ struct {
+ uint32_t compute_current_logic_xcc_id; // offset: 39 (0x27)
+ uint32_t compute_restart_cg_tg_id; // offset: 40 (0x28)
+ uint32_t compute_tg_chunk_size; // offset: 41 (0x29)
+ uint32_t compute_restore_tg_chunk_size; // offset: 42 (0x2A)
+ };
+ };
uint32_t reserved_43;
uint32_t reserved_44;
uint32_t reserved_45;
@@ -382,8 +392,16 @@ struct v9_mqd {
uint32_t iqtimer_pkt_dw29;
uint32_t iqtimer_pkt_dw30;
uint32_t iqtimer_pkt_dw31;
- uint32_t reserved_225;
- uint32_t reserved_226;
+ union {
+ struct {
+ uint32_t reserved_225;
+ uint32_t reserved_226;
+ };
+ struct {
+ uint32_t pm4_target_xcc_in_xcp; // offset: 225 (0xE1)
+ uint32_t cp_mqd_stride_size; // offset: 226 (0xE2)
+ };
+ };
uint32_t reserved_227;
uint32_t set_resources_header;
uint32_t set_resources_dw1;
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index f4f40459f22b..a57952b93e73 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -678,7 +678,12 @@ static ssize_t amdgpu_set_pp_table(struct device *dev,
* clock labeled OD_MCLK
*
* - three <frequency, voltage> points labeled OD_VDDC_CURVE.
- * They can be used to calibrate the sclk voltage curve.
+ * They can be used to calibrate the sclk voltage curve. This is
+ * available for Vega20 and NV1X.
+ *
+ * - voltage offset for the six anchor points of the v/f curve labeled
+ * OD_VDDC_CURVE. They can be used to calibrate the v/f curve. This
+ * is only availabe for some SMU13 ASICs.
*
* - voltage offset(in mV) applied on target voltage calculation.
* This is available for Sienna Cichlid, Navy Flounder and Dimgrey
@@ -719,12 +724,19 @@ static ssize_t amdgpu_set_pp_table(struct device *dev,
* E.g., "p 2 0 800" would set the minimum core clock on core
* 2 to 800Mhz.
*
- * For sclk voltage curve, enter the new values by writing a
- * string that contains "vc point clock voltage" to the file. The
- * points are indexed by 0, 1 and 2. E.g., "vc 0 300 600" will
- * update point1 with clock set as 300Mhz and voltage as
- * 600mV. "vc 2 1000 1000" will update point3 with clock set
- * as 1000Mhz and voltage 1000mV.
+ * For sclk voltage curve,
+ * - For NV1X, enter the new values by writing a string that
+ * contains "vc point clock voltage" to the file. The points
+ * are indexed by 0, 1 and 2. E.g., "vc 0 300 600" will update
+ * point1 with clock set as 300Mhz and voltage as 600mV. "vc 2
+ * 1000 1000" will update point3 with clock set as 1000Mhz and
+ * voltage 1000mV.
+ * - For SMU13 ASICs, enter the new values by writing a string that
+ * contains "vc anchor_point_index voltage_offset" to the file.
+ * There are total six anchor points defined on the v/f curve with
+ * index as 0 - 5.
+ * - "vc 0 10" will update the voltage offset for point1 as 10mv.
+ * - "vc 5 -10" will update the voltage offset for point6 as -10mv.
*
* To update the voltage offset applied for gfxclk/voltage calculation,
* enter the new value by writing a string that contains "vo offset".
@@ -3360,7 +3372,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
return 0;
/* Skip crit temp on APU */
- if ((adev->flags & AMD_IS_APU) && (adev->family >= AMDGPU_FAMILY_CZ) &&
+ if ((((adev->flags & AMD_IS_APU) && (adev->family >= AMDGPU_FAMILY_CZ)) ||
+ (gc_ver == IP_VERSION(9, 4, 3))) &&
(attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
return 0;
@@ -3393,9 +3406,10 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */
effective_mode &= ~S_IWUSR;
- /* In the case of APUs, this is only implemented on Vangogh */
+ /* not implemented yet for APUs other than GC 10.3.1 (vangogh) and 9.4.3 */
if (((adev->family == AMDGPU_FAMILY_SI) ||
- ((adev->flags & AMD_IS_APU) && (gc_ver != IP_VERSION(10, 3, 1)))) &&
+ ((adev->flags & AMD_IS_APU) && (gc_ver != IP_VERSION(10, 3, 1)) &&
+ (gc_ver != IP_VERSION(9, 4, 3)))) &&
(attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr ||
attr == &sensor_dev_attr_power1_cap.dev_attr.attr ||
@@ -3424,36 +3438,48 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
return 0;
if ((adev->family == AMDGPU_FAMILY_SI || /* not implemented yet */
- adev->family == AMDGPU_FAMILY_KV) && /* not implemented yet */
+ adev->family == AMDGPU_FAMILY_KV || /* not implemented yet */
+ (gc_ver == IP_VERSION(9, 4, 3))) &&
(attr == &sensor_dev_attr_in0_input.dev_attr.attr ||
attr == &sensor_dev_attr_in0_label.dev_attr.attr))
return 0;
- /* only APUs have vddnb */
- if (!(adev->flags & AMD_IS_APU) &&
+ /* only APUs other than gc 9,4,3 have vddnb */
+ if ((!(adev->flags & AMD_IS_APU) || (gc_ver == IP_VERSION(9, 4, 3))) &&
(attr == &sensor_dev_attr_in1_input.dev_attr.attr ||
attr == &sensor_dev_attr_in1_label.dev_attr.attr))
return 0;
- /* no mclk on APUs */
- if ((adev->flags & AMD_IS_APU) &&
+ /* no mclk on APUs other than gc 9,4,3*/
+ if (((adev->flags & AMD_IS_APU) && (gc_ver != IP_VERSION(9, 4, 3))) &&
(attr == &sensor_dev_attr_freq2_input.dev_attr.attr ||
attr == &sensor_dev_attr_freq2_label.dev_attr.attr))
return 0;
- /* only SOC15 dGPUs support hotspot and mem temperatures */
if (((adev->flags & AMD_IS_APU) || gc_ver < IP_VERSION(9, 0, 0)) &&
+ (gc_ver != IP_VERSION(9, 4, 3)) &&
+ (attr == &sensor_dev_attr_temp2_input.dev_attr.attr ||
+ attr == &sensor_dev_attr_temp2_label.dev_attr.attr ||
+ attr == &sensor_dev_attr_temp3_input.dev_attr.attr ||
+ attr == &sensor_dev_attr_temp3_label.dev_attr.attr))
+ return 0;
+
+ /* hotspot temperature for gc 9,4,3*/
+ if ((gc_ver == IP_VERSION(9, 4, 3)) &&
+ (attr == &sensor_dev_attr_temp1_input.dev_attr.attr ||
+ attr == &sensor_dev_attr_temp1_label.dev_attr.attr))
+ return 0;
+
+ /* only SOC15 dGPUs support hotspot and mem temperatures */
+ if (((adev->flags & AMD_IS_APU) || gc_ver < IP_VERSION(9, 0, 0) ||
+ (gc_ver == IP_VERSION(9, 4, 3))) &&
(attr == &sensor_dev_attr_temp2_crit.dev_attr.attr ||
attr == &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr ||
attr == &sensor_dev_attr_temp3_crit.dev_attr.attr ||
attr == &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr ||
attr == &sensor_dev_attr_temp1_emergency.dev_attr.attr ||
attr == &sensor_dev_attr_temp2_emergency.dev_attr.attr ||
- attr == &sensor_dev_attr_temp3_emergency.dev_attr.attr ||
- attr == &sensor_dev_attr_temp2_input.dev_attr.attr ||
- attr == &sensor_dev_attr_temp3_input.dev_attr.attr ||
- attr == &sensor_dev_attr_temp2_label.dev_attr.attr ||
- attr == &sensor_dev_attr_temp3_label.dev_attr.attr))
+ attr == &sensor_dev_attr_temp3_emergency.dev_attr.attr))
return 0;
/* only Vangogh has fast PPT limit and power labels */
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v13_0_0_pptable.h b/drivers/gpu/drm/amd/pm/inc/smu_v13_0_0_pptable.h
index 566a0da59e53..1dc7a065a6d4 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu_v13_0_0_pptable.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu_v13_0_0_pptable.h
@@ -38,13 +38,12 @@
#define SMU_13_0_0_PP_THERMALCONTROLLER_NONE 0
#define SMU_13_0_0_PP_THERMALCONTROLLER_NAVI21 28
-#define SMU_13_0_0_PP_OVERDRIVE_VERSION 0x81 // OverDrive 8 Table Version 0.2
+#define SMU_13_0_0_PP_OVERDRIVE_VERSION 0x83 // OverDrive 8 Table Version 0.2
#define SMU_13_0_0_PP_POWERSAVINGCLOCK_VERSION 0x01 // Power Saving Clock Table Version 1.00
enum SMU_13_0_0_ODFEATURE_CAP
{
SMU_13_0_0_ODCAP_GFXCLK_LIMITS = 0,
- SMU_13_0_0_ODCAP_GFXCLK_CURVE,
SMU_13_0_0_ODCAP_UCLK_LIMITS,
SMU_13_0_0_ODCAP_POWER_LIMIT,
SMU_13_0_0_ODCAP_FAN_ACOUSTIC_LIMIT,
@@ -59,13 +58,13 @@ enum SMU_13_0_0_ODFEATURE_CAP
SMU_13_0_0_ODCAP_FAN_CURVE,
SMU_13_0_0_ODCAP_AUTO_FAN_ACOUSTIC_LIMIT,
SMU_13_0_0_ODCAP_POWER_MODE,
+ SMU_13_0_0_ODCAP_PER_ZONE_GFX_VOLTAGE_OFFSET,
SMU_13_0_0_ODCAP_COUNT,
};
enum SMU_13_0_0_ODFEATURE_ID
{
SMU_13_0_0_ODFEATURE_GFXCLK_LIMITS = 1 << SMU_13_0_0_ODCAP_GFXCLK_LIMITS, //GFXCLK Limit feature
- SMU_13_0_0_ODFEATURE_GFXCLK_CURVE = 1 << SMU_13_0_0_ODCAP_GFXCLK_CURVE, //GFXCLK Curve feature
SMU_13_0_0_ODFEATURE_UCLK_LIMITS = 1 << SMU_13_0_0_ODCAP_UCLK_LIMITS, //UCLK Limit feature
SMU_13_0_0_ODFEATURE_POWER_LIMIT = 1 << SMU_13_0_0_ODCAP_POWER_LIMIT, //Power Limit feature
SMU_13_0_0_ODFEATURE_FAN_ACOUSTIC_LIMIT = 1 << SMU_13_0_0_ODCAP_FAN_ACOUSTIC_LIMIT, //Fan Acoustic RPM feature
@@ -80,6 +79,7 @@ enum SMU_13_0_0_ODFEATURE_ID
SMU_13_0_0_ODFEATURE_FAN_CURVE = 1 << SMU_13_0_0_ODCAP_FAN_CURVE, //Fan Curve feature
SMU_13_0_0_ODFEATURE_AUTO_FAN_ACOUSTIC_LIMIT = 1 << SMU_13_0_0_ODCAP_AUTO_FAN_ACOUSTIC_LIMIT, //Auto Fan Acoustic RPM feature
SMU_13_0_0_ODFEATURE_POWER_MODE = 1 << SMU_13_0_0_ODCAP_POWER_MODE, //Optimized GPU Power Mode feature
+ SMU_13_0_0_ODFEATURE_PER_ZONE_GFX_VOLTAGE_OFFSET = 1 << SMU_13_0_0_ODCAP_PER_ZONE_GFX_VOLTAGE_OFFSET, //Perzone voltage offset feature
SMU_13_0_0_ODFEATURE_COUNT = 16,
};
@@ -89,10 +89,6 @@ enum SMU_13_0_0_ODSETTING_ID
{
SMU_13_0_0_ODSETTING_GFXCLKFMAX = 0,
SMU_13_0_0_ODSETTING_GFXCLKFMIN,
- SMU_13_0_0_ODSETTING_CUSTOM_GFX_VF_CURVE_A,
- SMU_13_0_0_ODSETTING_CUSTOM_GFX_VF_CURVE_B,
- SMU_13_0_0_ODSETTING_CUSTOM_GFX_VF_CURVE_C,
- SMU_13_0_0_ODSETTING_CUSTOM_CURVE_VFT_FMIN,
SMU_13_0_0_ODSETTING_UCLKFMIN,
SMU_13_0_0_ODSETTING_UCLKFMAX,
SMU_13_0_0_ODSETTING_POWERPERCENTAGE,
@@ -117,6 +113,12 @@ enum SMU_13_0_0_ODSETTING_ID
SMU_13_0_0_ODSETTING_FAN_CURVE_SPEED_5,
SMU_13_0_0_ODSETTING_AUTO_FAN_ACOUSTIC_LIMIT,
SMU_13_0_0_ODSETTING_POWER_MODE,
+ SMU_13_0_0_ODSETTING_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_1,
+ SMU_13_0_0_ODSETTING_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_2,
+ SMU_13_0_0_ODSETTING_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_3,
+ SMU_13_0_0_ODSETTING_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_4,
+ SMU_13_0_0_ODSETTING_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_5,
+ SMU_13_0_0_ODSETTING_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_6,
SMU_13_0_0_ODSETTING_COUNT,
};
#define SMU_13_0_0_MAX_ODSETTING 64 //Maximum Number of ODSettings
diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c
index f5e08b60f66e..36c831b280ed 100644
--- a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c
+++ b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c
@@ -508,19 +508,19 @@ static int kv_enable_didt(struct amdgpu_device *adev, bool enable)
pi->caps_db_ramping ||
pi->caps_td_ramping ||
pi->caps_tcp_ramping) {
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
if (enable) {
ret = kv_program_pt_config_registers(adev, didt_config_kv);
if (ret) {
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return ret;
}
}
kv_do_enable_didt(adev, enable);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
return 0;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c
index 32a5a00fd8ae..21be23ec3c79 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c
@@ -973,7 +973,7 @@ int smu7_enable_didt_config(struct pp_hwmgr *hwmgr)
PP_CAP(PHM_PlatformCaps_TDRamping) ||
PP_CAP(PHM_PlatformCaps_TCPRamping)) {
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
mutex_lock(&adev->grbm_idx_mutex);
value = 0;
value2 = cgs_read_register(hwmgr->device, mmGRBM_GFX_INDEX);
@@ -1048,13 +1048,13 @@ int smu7_enable_didt_config(struct pp_hwmgr *hwmgr)
}
mutex_unlock(&adev->grbm_idx_mutex);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
return 0;
error:
mutex_unlock(&adev->grbm_idx_mutex);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return result;
}
@@ -1068,7 +1068,7 @@ int smu7_disable_didt_config(struct pp_hwmgr *hwmgr)
PP_CAP(PHM_PlatformCaps_TDRamping) ||
PP_CAP(PHM_PlatformCaps_TCPRamping)) {
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
result = smu7_enable_didt(hwmgr, false);
PP_ASSERT_WITH_CODE((result == 0),
@@ -1081,12 +1081,12 @@ int smu7_disable_didt_config(struct pp_hwmgr *hwmgr)
PP_ASSERT_WITH_CODE((0 == result),
"Failed to disable DPM DIDT.", goto error);
}
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
return 0;
error:
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return result;
}
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.c
index 9757d47dd6b8..309a9d3bc1b7 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.c
@@ -915,7 +915,7 @@ static int vega10_enable_cac_driving_se_didt_config(struct pp_hwmgr *hwmgr)
num_se = adev->gfx.config.max_shader_engines;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
mutex_lock(&adev->grbm_idx_mutex);
for (count = 0; count < num_se; count++) {
@@ -940,7 +940,7 @@ static int vega10_enable_cac_driving_se_didt_config(struct pp_hwmgr *hwmgr)
vega10_didt_set_mask(hwmgr, true);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return 0;
}
@@ -949,11 +949,11 @@ static int vega10_disable_cac_driving_se_didt_config(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
vega10_didt_set_mask(hwmgr, false);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return 0;
}
@@ -966,7 +966,7 @@ static int vega10_enable_psm_gc_didt_config(struct pp_hwmgr *hwmgr)
num_se = adev->gfx.config.max_shader_engines;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
mutex_lock(&adev->grbm_idx_mutex);
for (count = 0; count < num_se; count++) {
@@ -985,7 +985,7 @@ static int vega10_enable_psm_gc_didt_config(struct pp_hwmgr *hwmgr)
vega10_didt_set_mask(hwmgr, true);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
vega10_program_gc_didt_config_registers(hwmgr, GCDiDtDroopCtrlConfig_vega10);
if (PP_CAP(PHM_PlatformCaps_GCEDC))
@@ -1002,11 +1002,11 @@ static int vega10_disable_psm_gc_didt_config(struct pp_hwmgr *hwmgr)
struct amdgpu_device *adev = hwmgr->adev;
uint32_t data;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
vega10_didt_set_mask(hwmgr, false);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
if (PP_CAP(PHM_PlatformCaps_GCEDC)) {
data = 0x00000000;
@@ -1027,7 +1027,7 @@ static int vega10_enable_se_edc_config(struct pp_hwmgr *hwmgr)
num_se = adev->gfx.config.max_shader_engines;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
mutex_lock(&adev->grbm_idx_mutex);
for (count = 0; count < num_se; count++) {
@@ -1048,7 +1048,7 @@ static int vega10_enable_se_edc_config(struct pp_hwmgr *hwmgr)
vega10_didt_set_mask(hwmgr, true);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return 0;
}
@@ -1057,11 +1057,11 @@ static int vega10_disable_se_edc_config(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
vega10_didt_set_mask(hwmgr, false);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return 0;
}
@@ -1075,7 +1075,7 @@ static int vega10_enable_psm_gc_edc_config(struct pp_hwmgr *hwmgr)
num_se = adev->gfx.config.max_shader_engines;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMResetConfig_vega10);
@@ -1096,7 +1096,7 @@ static int vega10_enable_psm_gc_edc_config(struct pp_hwmgr *hwmgr)
vega10_didt_set_mask(hwmgr, true);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCDroopCtrlConfig_vega10);
@@ -1116,11 +1116,11 @@ static int vega10_disable_psm_gc_edc_config(struct pp_hwmgr *hwmgr)
struct amdgpu_device *adev = hwmgr->adev;
uint32_t data;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
vega10_didt_set_mask(hwmgr, false);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
if (PP_CAP(PHM_PlatformCaps_GCEDC)) {
data = 0x00000000;
@@ -1138,7 +1138,7 @@ static int vega10_enable_se_edc_force_stall_config(struct pp_hwmgr *hwmgr)
struct amdgpu_device *adev = hwmgr->adev;
int result;
- amdgpu_gfx_rlc_enter_safe_mode(adev);
+ amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
mutex_lock(&adev->grbm_idx_mutex);
WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, 0xE0000000);
@@ -1151,7 +1151,7 @@ static int vega10_enable_se_edc_force_stall_config(struct pp_hwmgr *hwmgr)
vega10_didt_set_mask(hwmgr, false);
- amdgpu_gfx_rlc_exit_safe_mode(adev);
+ amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return 0;
}
diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
index 5ce433e2c16a..f1580a26a850 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
@@ -359,7 +359,7 @@ struct pp_hwmgr_func {
int (*set_ppfeature_status)(struct pp_hwmgr *hwmgr, uint64_t ppfeature_masks);
int (*set_mp1_state)(struct pp_hwmgr *hwmgr, enum pp_mp1_state mp1_state);
int (*asic_reset)(struct pp_hwmgr *hwmgr, enum SMU_ASIC_RESET_MODE mode);
- int (*smu_i2c_bus_access)(struct pp_hwmgr *hwmgr, bool aquire);
+ int (*smu_i2c_bus_access)(struct pp_hwmgr *hwmgr, bool acquire);
int (*set_df_cstate)(struct pp_hwmgr *hwmgr, enum pp_df_cstate state);
int (*set_xgmi_pstate)(struct pp_hwmgr *hwmgr, uint32_t pstate);
int (*disable_power_features_for_compute_performance)(struct pp_hwmgr *hwmgr,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 2ddf5198e5c4..4dea79a0c5b5 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -822,11 +822,20 @@ static int smu_init_fb_allocations(struct smu_context *smu)
}
}
+ driver_table->domain = AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT;
/* VRAM allocation for driver table */
for (i = 0; i < SMU_TABLE_COUNT; i++) {
if (tables[i].size == 0)
continue;
+ /* If one of the tables has VRAM domain restriction, keep it in
+ * VRAM
+ */
+ if ((tables[i].domain &
+ (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT)) ==
+ AMDGPU_GEM_DOMAIN_VRAM)
+ driver_table->domain = AMDGPU_GEM_DOMAIN_VRAM;
+
if (i == SMU_TABLE_PMSTATUSLOG)
continue;
@@ -836,7 +845,6 @@ static int smu_init_fb_allocations(struct smu_context *smu)
driver_table->size = max_table_size;
driver_table->align = PAGE_SIZE;
- driver_table->domain = AMDGPU_GEM_DOMAIN_VRAM;
ret = amdgpu_bo_create_kernel(adev,
driver_table->size,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_aldebaran.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_aldebaran.h
index 90200f31ff52..cddf45eebee8 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_aldebaran.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_aldebaran.h
@@ -24,6 +24,8 @@
#ifndef SMU13_DRIVER_IF_ALDEBARAN_H
#define SMU13_DRIVER_IF_ALDEBARAN_H
+#define SMU13_DRIVER_IF_VERSION_ALDE 0x08
+
#define NUM_VCLK_DPM_LEVELS 8
#define NUM_DCLK_DPM_LEVELS 8
#define NUM_SOCCLK_DPM_LEVELS 8
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h
index b686fb68a6e7..9dd1ed5b8940 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h
@@ -24,8 +24,10 @@
#ifndef SMU13_DRIVER_IF_V13_0_0_H
#define SMU13_DRIVER_IF_V13_0_0_H
+#define SMU13_0_0_DRIVER_IF_VERSION 0x3D
+
//Increment this version if SkuTable_t or BoardTable_t change
-#define PPTABLE_VERSION 0x26
+#define PPTABLE_VERSION 0x2B
#define NUM_GFXCLK_DPM_LEVELS 16
#define NUM_SOCCLK_DPM_LEVELS 8
@@ -94,7 +96,7 @@
#define FEATURE_ATHUB_MMHUB_PG_BIT 48
#define FEATURE_SOC_PCC_BIT 49
#define FEATURE_EDC_PWRBRK_BIT 50
-#define FEATURE_SPARE_51_BIT 51
+#define FEATURE_BOMXCO_SVI3_PROG_BIT 51
#define FEATURE_SPARE_52_BIT 52
#define FEATURE_SPARE_53_BIT 53
#define FEATURE_SPARE_54_BIT 54
@@ -310,6 +312,7 @@ typedef enum {
I2C_CONTROLLER_PROTOCOL_VR_IR35217,
I2C_CONTROLLER_PROTOCOL_TMP_MAX31875,
I2C_CONTROLLER_PROTOCOL_INA3221,
+ I2C_CONTROLLER_PROTOCOL_TMP_MAX6604,
I2C_CONTROLLER_PROTOCOL_COUNT,
} I2cControllerProtocol_e;
@@ -568,6 +571,7 @@ typedef enum {
} POWER_SOURCE_e;
typedef enum {
+ MEM_VENDOR_PLACEHOLDER0,
MEM_VENDOR_SAMSUNG,
MEM_VENDOR_INFINEON,
MEM_VENDOR_ELPIDA,
@@ -577,7 +581,6 @@ typedef enum {
MEM_VENDOR_MOSEL,
MEM_VENDOR_WINBOND,
MEM_VENDOR_ESMT,
- MEM_VENDOR_PLACEHOLDER0,
MEM_VENDOR_PLACEHOLDER1,
MEM_VENDOR_PLACEHOLDER2,
MEM_VENDOR_PLACEHOLDER3,
@@ -665,7 +668,14 @@ typedef enum {
#define PP_NUM_RTAVFS_PWL_ZONES 5
-
+#define PP_OD_FEATURE_GFX_VF_CURVE_BIT 0
+#define PP_OD_FEATURE_PPT_BIT 2
+#define PP_OD_FEATURE_FAN_CURVE_BIT 3
+#define PP_OD_FEATURE_GFXCLK_BIT 7
+#define PP_OD_FEATURE_UCLK_BIT 8
+#define PP_OD_FEATURE_ZERO_FAN_BIT 9
+#define PP_OD_FEATURE_TEMPERATURE_BIT 10
+#define PP_OD_FEATURE_COUNT 13
// VBIOS or PPLIB configures telemetry slope and offset. Only slope expected to be set for SVI3
// Slope Q1.7, Offset Q1.2
@@ -687,10 +697,8 @@ typedef struct {
//Voltage control
int16_t VoltageOffsetPerZoneBoundary[PP_NUM_OD_VF_CURVE_POINTS];
- uint16_t VddGfxVmax; // in mV
- uint8_t IdlePwrSavingFeaturesCtrl;
- uint8_t RuntimePwrSavingFeaturesCtrl;
+ uint32_t Reserved;
//Frequency changes
int16_t GfxclkFmin; // MHz
@@ -727,10 +735,9 @@ typedef struct {
uint32_t FeatureCtrlMask;
int16_t VoltageOffsetPerZoneBoundary;
- uint16_t VddGfxVmax; // in mV
+ uint16_t Reserved1;
- uint8_t IdlePwrSavingFeaturesCtrl;
- uint8_t RuntimePwrSavingFeaturesCtrl;
+ uint16_t Reserved2;
int16_t GfxclkFmin; // MHz
int16_t GfxclkFmax; // MHz
@@ -806,6 +813,9 @@ typedef enum {
#define INVALID_BOARD_GPIO 0xFF
+#define MARKETING_BASE_CLOCKS 0
+#define MARKETING_GAME_CLOCKS 1
+#define MARKETING_BOOST_CLOCKS 2
typedef struct {
//PLL 0
@@ -1096,10 +1106,15 @@ typedef struct {
uint16_t DcsExitHysteresis; //The min amount of time power credit accumulator should have a value > 0 before SMU exits the DCS throttling phase.
uint16_t DcsTimeout; //This is the amount of time SMU FW waits for RLC to put GFX into GFXOFF before reverting to the fallback mechanism of throttling GFXCLK to Fmin.
+ uint8_t FoptEnabled;
+ uint8_t DcsSpare2[3];
+ uint32_t DcsFoptM; //Tuning paramters to shift Fopt calculation
+ uint32_t DcsFoptB; //Tuning paramters to shift Fopt calculation
- uint32_t DcsSpare[16];
+ uint32_t DcsSpare[11];
// UCLK section
+ uint16_t ShadowFreqTableUclk[NUM_UCLK_DPM_LEVELS]; // In MHz
uint8_t UseStrobeModeOptimizations; //Set to indicate that FW should use strobe mode optimizations
uint8_t PaddingMem[3];
@@ -1245,8 +1260,13 @@ typedef struct {
QuadraticInt_t qFeffCoeffBaseClock[POWER_SOURCE_COUNT];
QuadraticInt_t qFeffCoeffBoostClock[POWER_SOURCE_COUNT];
+ uint16_t TemperatureLimit_Hynix; // In degrees Celsius. Memory temperature limit associated with Hynix
+ uint16_t TemperatureLimit_Micron; // In degrees Celsius. Memory temperature limit associated with Micron
+ uint16_t TemperatureFwCtfLimit_Hynix;
+ uint16_t TemperatureFwCtfLimit_Micron;
+
// SECTION: Sku Reserved
- uint32_t Spare[43];
+ uint32_t Spare[41];
// Padding for MMHUB - do not modify this
uint32_t MmHubPadding[8];
@@ -1318,8 +1338,9 @@ typedef struct {
// UCLK Spread Spectrum
uint8_t UclkSpreadPercent[MEM_VENDOR_COUNT];
+ uint8_t GfxclkSpreadEnable;
+
// FCLK Spread Spectrum
- uint8_t FclkSpreadPadding;
uint8_t FclkSpreadPercent; // Q4.4
uint16_t FclkSpreadFreq; // kHz
@@ -1444,6 +1465,8 @@ typedef struct {
uint8_t ThrottlingPercentage[THROTTLER_COUNT];
+ uint8_t VmaxThrottlingPercentage;
+ uint8_t Padding1[3];
//metrics for D3hot entry/exit and driver ARM msgs
uint32_t D3HotEntryCountPerMode[D3HOT_SEQUENCE_COUNT];
@@ -1463,7 +1486,7 @@ typedef struct {
typedef struct {
SmuMetrics_t SmuMetrics;
- uint32_t Spare[30];
+ uint32_t Spare[29];
// Padding - ignore
uint32_t MmHubPadding[8]; // SMU internal use
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h
index 2162ecd1057d..fee9293b3f97 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h
@@ -27,7 +27,7 @@
// *** IMPORTANT ***
// SMU TEAM: Always increment the interface version if
// any structure is changed in this file
-#define PMFW_DRIVER_IF_VERSION 8
+#define SMU13_0_4_DRIVER_IF_VERSION 8
typedef struct {
int32_t value;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_5.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_5.h
index aa971412b434..7589faa0232d 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_5.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_5.h
@@ -23,7 +23,7 @@
#ifndef __SMU13_DRIVER_IF_V13_0_5_H__
#define __SMU13_DRIVER_IF_V13_0_5_H__
-#define PMFW_DRIVER_IF_VERSION 4
+#define SMU13_0_5_DRIVER_IF_VERSION 4
// Throttler Status Bitmask
#define THROTTLER_STATUS_BIT_SPL 0
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_6.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_6.h
index be596777cd2c..ca4a5e99ccd1 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_6.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_6.h
@@ -26,7 +26,7 @@
// *** IMPORTANT ***
// PMFW TEAM: Always increment the interface version if
// anything is changed in this file
-#define SMU13_0_6_DRIVER_IF_VERSION 0x08042022
+#define SMU13_0_6_DRIVER_IF_VERSION 0x08042024
//I2C Interface
#define NUM_I2C_CONTROLLERS 8
@@ -106,7 +106,7 @@ typedef enum {
} UCLK_DPM_MODE_e;
typedef struct {
- //0-26 SOC, 27-29 SOCIO
+ //0-23 SOC, 24-26 SOCIO, 27-29 SOC
uint16_t avgPsmCount[30];
uint16_t minPsmCount[30];
float avgPsmVoltage[30];
@@ -121,6 +121,17 @@ typedef struct {
float minPsmVoltage[30];
} AvfsDebugTableXcd_t;
+// Defines used for IH-based thermal interrupts to GFX driver - A/X only
+#define IH_INTERRUPT_ID_TO_DRIVER 0xFE
+#define IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING 0x7
+
+//thermal over-temp mask defines for IH interrupt to host
+#define THROTTLER_PROCHOT_BIT 0
+#define THROTTLER_PPT_BIT 1
+#define THROTTLER_THERMAL_SOCKET_BIT 2//AID, XCD, CCD throttling
+#define THROTTLER_THERMAL_VR_BIT 3//VRHOT
+#define THROTTLER_THERMAL_HBM_BIT 4
+
// These defines are used with the following messages:
// SMC_MSG_TransferTableDram2Smu
// SMC_MSG_TransferTableSmu2Dram
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h
index 4c46a0392451..62b7c0daff68 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h
@@ -25,7 +25,7 @@
// *** IMPORTANT ***
// PMFW TEAM: Always increment the interface version on any change to this file
-#define SMU13_DRIVER_IF_VERSION 0x35
+#define SMU13_0_7_DRIVER_IF_VERSION 0x35
//Increment this version if SkuTable_t or BoardTable_t change
#define PPTABLE_VERSION 0x27
@@ -683,18 +683,12 @@ typedef struct {
#define PP_OD_FEATURE_GFX_VF_CURVE_BIT 0
-#define PP_OD_FEATURE_VMAX_BIT 1
#define PP_OD_FEATURE_PPT_BIT 2
#define PP_OD_FEATURE_FAN_CURVE_BIT 3
-#define PP_OD_FEATURE_FREQ_DETER_BIT 4
-#define PP_OD_FEATURE_FULL_CTRL_BIT 5
-#define PP_OD_FEATURE_TDC_BIT 6
#define PP_OD_FEATURE_GFXCLK_BIT 7
#define PP_OD_FEATURE_UCLK_BIT 8
#define PP_OD_FEATURE_ZERO_FAN_BIT 9
#define PP_OD_FEATURE_TEMPERATURE_BIT 10
-#define PP_OD_FEATURE_POWER_FEATURE_CTRL_BIT 11
-#define PP_OD_FEATURE_ASIC_TDC_BIT 12
#define PP_OD_FEATURE_COUNT 13
typedef enum {
@@ -713,10 +707,8 @@ typedef struct {
//Voltage control
int16_t VoltageOffsetPerZoneBoundary[PP_NUM_OD_VF_CURVE_POINTS];
- uint16_t VddGfxVmax; // in mV
- uint8_t IdlePwrSavingFeaturesCtrl;
- uint8_t RuntimePwrSavingFeaturesCtrl;
+ uint32_t Reserved;
//Frequency changes
int16_t GfxclkFmin; // MHz
@@ -741,12 +733,7 @@ typedef struct {
uint8_t MaxOpTemp;
uint8_t Padding[4];
- uint16_t GfxVoltageFullCtrlMode;
- uint16_t GfxclkFullCtrlMode;
- uint16_t UclkFullCtrlMode;
- int16_t AsicTdc;
-
- uint32_t Spare[10];
+ uint32_t Spare[12];
uint32_t MmHubPadding[8]; // SMU internal use. Adding here instead of external as a workaround
} OverDriveTable_t;
@@ -759,10 +746,9 @@ typedef struct {
uint32_t FeatureCtrlMask;
int16_t VoltageOffsetPerZoneBoundary;
- uint16_t VddGfxVmax; // in mV
+ uint16_t Reserved1;
- uint8_t IdlePwrSavingFeaturesCtrl;
- uint8_t RuntimePwrSavingFeaturesCtrl;
+ uint16_t Reserved2;
int16_t GfxclkFmin; // MHz
int16_t GfxclkFmax; // MHz
@@ -785,12 +771,7 @@ typedef struct {
uint8_t MaxOpTemp;
uint8_t Padding[4];
- uint16_t GfxVoltageFullCtrlMode;
- uint16_t GfxclkFullCtrlMode;
- uint16_t UclkFullCtrlMode;
- int16_t AsicTdc;
-
- uint32_t Spare[10];
+ uint32_t Spare[12];
} OverDriveLimits_t;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_yellow_carp.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_yellow_carp.h
index 25540cb28208..7417634827ad 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_yellow_carp.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_yellow_carp.h
@@ -26,7 +26,7 @@
// *** IMPORTANT ***
// SMU TEAM: Always increment the interface version if
// any structure is changed in this file
-#define SMU13_DRIVER_IF_VERSION 4
+#define SMU13_YELLOW_CARP_DRIVER_IF_VERSION 4
typedef struct {
int32_t value;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h
index bdccbb4a6276..252aef190c5c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h
@@ -123,9 +123,9 @@ typedef enum {
VOLTAGE_GUARDBAND_COUNT
} GFX_GUARDBAND_e;
-#define SMU_METRICS_TABLE_VERSION 0x1
+#define SMU_METRICS_TABLE_VERSION 0x5
-typedef struct {
+typedef struct __attribute__((packed, aligned(4))) {
uint32_t AccumulationCounter;
//TEMPERATURE
@@ -198,11 +198,20 @@ typedef struct {
uint32_t SocketThmResidencyAcc;
uint32_t VrThmResidencyAcc;
uint32_t HbmThmResidencyAcc;
+ uint32_t spare;
+
+ // New Items at end to maintain driver compatibility
+ uint32_t GfxclkFrequency[8];
+
+ //PSNs
+ uint64_t PublicSerialNumber_AID[4];
+ uint64_t PublicSerialNumber_XCD[8];
+ uint64_t PublicSerialNumber_CCD[12];
} MetricsTable_t;
-#define SMU_VF_METRICS_TABLE_VERSION 0x1
+#define SMU_VF_METRICS_TABLE_VERSION 0x3
-typedef struct {
+typedef struct __attribute__((packed, aligned(4))) {
uint32_t AccumulationCounter;
uint32_t InstGfxclk_TargFreq;
uint64_t AccGfxclk_TargFreq;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_ppsmc.h
index b838e8db395a..ae4f44c4b877 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_ppsmc.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_ppsmc.h
@@ -82,7 +82,8 @@
#define PPSMC_MSG_SetSoftMaxGfxClk 0x31
#define PPSMC_MSG_GetMinGfxDpmFreq 0x32
#define PPSMC_MSG_GetMaxGfxDpmFreq 0x33
-#define PPSMC_Message_Count 0x34
+#define PPSMC_MSG_PrepareForDriverUnload 0x34
+#define PPSMC_Message_Count 0x35
//PPSMC Reset Types for driver msg argument
#define PPSMC_RESET_TYPE_DRIVER_MODE_1_RESET 0x1
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
index df3baaab0037..6a0ac0bbaace 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
@@ -25,17 +25,6 @@
#include "amdgpu_smu.h"
-#define SMU13_DRIVER_IF_VERSION_INV 0xFFFFFFFF
-#define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04
-#define SMU13_DRIVER_IF_VERSION_ALDE 0x08
-#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_0 0x37
-#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x08
-#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04
-#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10 0x32
-#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x37
-#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_10 0x1D
-#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_6 0x0
-
#define SMU13_MODE1_RESET_WAIT_TIME_IN_MS 500 //500ms
/* MP Apertures */
@@ -62,6 +51,8 @@
#define CTF_OFFSET_HOTSPOT 5
#define CTF_OFFSET_MEM 5
+#define SMU_13_VCLK_SHIFT 16
+
extern const int pmfw_decoded_link_speed[5];
extern const int pmfw_decoded_link_width[7];
@@ -130,6 +121,7 @@ struct smu_13_0_power_context {
uint32_t power_source;
uint8_t in_power_limit_boost_mode;
enum smu_13_0_power_state power_state;
+ atomic_t throttle_status;
};
#if defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h
index 478862ded0bd..eadbe0149cae 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h
@@ -38,13 +38,12 @@
#define SMU_13_0_7_PP_THERMALCONTROLLER_NONE 0
#define SMU_13_0_7_PP_THERMALCONTROLLER_NAVI21 28
-#define SMU_13_0_7_PP_OVERDRIVE_VERSION 0x81 // OverDrive 8 Table Version 0.2
+#define SMU_13_0_7_PP_OVERDRIVE_VERSION 0x83 // OverDrive 8 Table Version 0.2
#define SMU_13_0_7_PP_POWERSAVINGCLOCK_VERSION 0x01 // Power Saving Clock Table Version 1.00
enum SMU_13_0_7_ODFEATURE_CAP
{
SMU_13_0_7_ODCAP_GFXCLK_LIMITS = 0,
- SMU_13_0_7_ODCAP_GFXCLK_CURVE,
SMU_13_0_7_ODCAP_UCLK_LIMITS,
SMU_13_0_7_ODCAP_POWER_LIMIT,
SMU_13_0_7_ODCAP_FAN_ACOUSTIC_LIMIT,
@@ -59,13 +58,13 @@ enum SMU_13_0_7_ODFEATURE_CAP
SMU_13_0_7_ODCAP_FAN_CURVE,
SMU_13_0_7_ODCAP_AUTO_FAN_ACOUSTIC_LIMIT,
SMU_13_0_7_ODCAP_POWER_MODE,
+ SMU_13_0_7_ODCAP_PER_ZONE_GFX_VOLTAGE_OFFSET,
SMU_13_0_7_ODCAP_COUNT,
};
enum SMU_13_0_7_ODFEATURE_ID
{
SMU_13_0_7_ODFEATURE_GFXCLK_LIMITS = 1 << SMU_13_0_7_ODCAP_GFXCLK_LIMITS, //GFXCLK Limit feature
- SMU_13_0_7_ODFEATURE_GFXCLK_CURVE = 1 << SMU_13_0_7_ODCAP_GFXCLK_CURVE, //GFXCLK Curve feature
SMU_13_0_7_ODFEATURE_UCLK_LIMITS = 1 << SMU_13_0_7_ODCAP_UCLK_LIMITS, //UCLK Limit feature
SMU_13_0_7_ODFEATURE_POWER_LIMIT = 1 << SMU_13_0_7_ODCAP_POWER_LIMIT, //Power Limit feature
SMU_13_0_7_ODFEATURE_FAN_ACOUSTIC_LIMIT = 1 << SMU_13_0_7_ODCAP_FAN_ACOUSTIC_LIMIT, //Fan Acoustic RPM feature
@@ -80,6 +79,7 @@ enum SMU_13_0_7_ODFEATURE_ID
SMU_13_0_7_ODFEATURE_FAN_CURVE = 1 << SMU_13_0_7_ODCAP_FAN_CURVE, //Fan Curve feature
SMU_13_0_7_ODFEATURE_AUTO_FAN_ACOUSTIC_LIMIT = 1 << SMU_13_0_7_ODCAP_AUTO_FAN_ACOUSTIC_LIMIT, //Auto Fan Acoustic RPM feature
SMU_13_0_7_ODFEATURE_POWER_MODE = 1 << SMU_13_0_7_ODCAP_POWER_MODE, //Optimized GPU Power Mode feature
+ SMU_13_0_7_ODFEATURE_PER_ZONE_GFX_VOLTAGE_OFFSET = 1 << SMU_13_0_7_ODCAP_PER_ZONE_GFX_VOLTAGE_OFFSET, //Perzone voltage offset feature
SMU_13_0_7_ODFEATURE_COUNT = 16,
};
@@ -89,10 +89,6 @@ enum SMU_13_0_7_ODSETTING_ID
{
SMU_13_0_7_ODSETTING_GFXCLKFMAX = 0,
SMU_13_0_7_ODSETTING_GFXCLKFMIN,
- SMU_13_0_7_ODSETTING_CUSTOM_GFX_VF_CURVE_A,
- SMU_13_0_7_ODSETTING_CUSTOM_GFX_VF_CURVE_B,
- SMU_13_0_7_ODSETTING_CUSTOM_GFX_VF_CURVE_C,
- SMU_13_0_7_ODSETTING_CUSTOM_CURVE_VFT_FMIN,
SMU_13_0_7_ODSETTING_UCLKFMIN,
SMU_13_0_7_ODSETTING_UCLKFMAX,
SMU_13_0_7_ODSETTING_POWERPERCENTAGE,
@@ -117,6 +113,12 @@ enum SMU_13_0_7_ODSETTING_ID
SMU_13_0_7_ODSETTING_FAN_CURVE_SPEED_5,
SMU_13_0_7_ODSETTING_AUTO_FAN_ACOUSTIC_LIMIT,
SMU_13_0_7_ODSETTING_POWER_MODE,
+ SMU_13_0_7_ODSETTING_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_1,
+ SMU_13_0_7_ODSETTING_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_2,
+ SMU_13_0_7_ODSETTING_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_3,
+ SMU_13_0_7_ODSETTING_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_4,
+ SMU_13_0_7_ODSETTING_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_5,
+ SMU_13_0_7_ODSETTING_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_6,
SMU_13_0_7_ODSETTING_COUNT,
};
#define SMU_13_0_7_MAX_ODSETTING 64 //Maximum Number of ODSettings
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 85d53597eb07..f7ed3e655e39 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -431,7 +431,13 @@ static int sienna_cichlid_append_powerplay_table(struct smu_context *smu)
{
struct atom_smc_dpm_info_v4_9 *smc_dpm_table;
int index, ret;
- I2cControllerConfig_t *table_member;
+ PPTable_beige_goby_t *ppt_beige_goby;
+ PPTable_t *ppt;
+
+ if (smu->adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 13))
+ ppt_beige_goby = smu->smu_table.driver_pptable;
+ else
+ ppt = smu->smu_table.driver_pptable;
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
smc_dpm_info);
@@ -440,9 +446,13 @@ static int sienna_cichlid_append_powerplay_table(struct smu_context *smu)
(uint8_t **)&smc_dpm_table);
if (ret)
return ret;
- GET_PPTABLE_MEMBER(I2cControllers, &table_member);
- memcpy(table_member, smc_dpm_table->I2cControllers,
- sizeof(*smc_dpm_table) - sizeof(smc_dpm_table->table_header));
+
+ if (smu->adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 13))
+ smu_memcpy_trailing(ppt_beige_goby, I2cControllers, BoardReserved,
+ smc_dpm_table, I2cControllers);
+ else
+ smu_memcpy_trailing(ppt, I2cControllers, BoardReserved,
+ smc_dpm_table, I2cControllers);
return 0;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
index d30ec3005ea1..e80f122d8aec 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
@@ -2147,5 +2147,6 @@ void aldebaran_set_ppt_funcs(struct smu_context *smu)
smu->clock_map = aldebaran_clk_map;
smu->feature_map = aldebaran_feature_mask_map;
smu->table_map = aldebaran_table_map;
+ smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_ALDE;
smu_v13_0_set_smu_mailbox_registers(smu);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
index ca379181081c..e52c563f0dac 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
@@ -269,45 +269,10 @@ int smu_v13_0_check_fw_version(struct smu_context *smu)
smu_major = (smu_version >> 16) & 0xff;
smu_minor = (smu_version >> 8) & 0xff;
smu_debug = (smu_version >> 0) & 0xff;
- if (smu->is_apu)
+ if (smu->is_apu ||
+ adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 6))
adev->pm.fw_version = smu_version;
- switch (adev->ip_versions[MP1_HWIP][0]) {
- case IP_VERSION(13, 0, 2):
- smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_ALDE;
- break;
- case IP_VERSION(13, 0, 0):
- smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_0;
- break;
- case IP_VERSION(13, 0, 10):
- smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10;
- break;
- case IP_VERSION(13, 0, 7):
- smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_7;
- break;
- case IP_VERSION(13, 0, 1):
- case IP_VERSION(13, 0, 3):
- case IP_VERSION(13, 0, 8):
- smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_YELLOW_CARP;
- break;
- case IP_VERSION(13, 0, 4):
- case IP_VERSION(13, 0, 11):
- smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_4;
- break;
- case IP_VERSION(13, 0, 5):
- smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_5;
- break;
- case IP_VERSION(13, 0, 6):
- smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_6;
- adev->pm.fw_version = smu_version;
- break;
- default:
- dev_err(adev->dev, "smu unsupported IP version: 0x%x.\n",
- adev->ip_versions[MP1_HWIP][0]);
- smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_INV;
- break;
- }
-
/* only for dGPU w/ SMU13*/
if (adev->pm.fw)
dev_dbg(smu->adev->dev, "smu fw reported program %d, version = 0x%08x (%d.%d.%d)\n",
@@ -502,17 +467,26 @@ int smu_v13_0_init_smc_tables(struct smu_context *smu)
ret = -ENOMEM;
goto err3_out;
}
+
+ smu_table->user_overdrive_table =
+ kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL);
+ if (!smu_table->user_overdrive_table) {
+ ret = -ENOMEM;
+ goto err4_out;
+ }
}
smu_table->combo_pptable =
kzalloc(tables[SMU_TABLE_COMBO_PPTABLE].size, GFP_KERNEL);
if (!smu_table->combo_pptable) {
ret = -ENOMEM;
- goto err4_out;
+ goto err5_out;
}
return 0;
+err5_out:
+ kfree(smu_table->user_overdrive_table);
err4_out:
kfree(smu_table->boot_overdrive_table);
err3_out:
@@ -532,12 +506,14 @@ int smu_v13_0_fini_smc_tables(struct smu_context *smu)
kfree(smu_table->gpu_metrics_table);
kfree(smu_table->combo_pptable);
+ kfree(smu_table->user_overdrive_table);
kfree(smu_table->boot_overdrive_table);
kfree(smu_table->overdrive_table);
kfree(smu_table->max_sustainable_clocks);
kfree(smu_table->driver_pptable);
smu_table->gpu_metrics_table = NULL;
smu_table->combo_pptable = NULL;
+ smu_table->user_overdrive_table = NULL;
smu_table->boot_overdrive_table = NULL;
smu_table->overdrive_table = NULL;
smu_table->max_sustainable_clocks = NULL;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index 08577d1b84ec..a6083957ae51 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -46,7 +46,6 @@
#include "asic_reg/mp/mp_13_0_0_sh_mask.h"
#include "smu_cmn.h"
#include "amdgpu_ras.h"
-#include "umc_v8_10.h"
/*
* DO NOT use these for err/warn/info/debug messages.
@@ -237,6 +236,7 @@ static struct cmn2asic_mapping smu_v13_0_0_table_map[SMU_TABLE_COUNT] = {
[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
TAB_MAP(I2C_COMMANDS),
TAB_MAP(ECCINFO),
+ TAB_MAP(OVERDRIVE),
};
static struct cmn2asic_mapping smu_v13_0_0_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
@@ -331,6 +331,11 @@ static int smu_v13_0_0_check_powerplay_table(struct smu_context *smu)
struct smu_13_0_0_powerplay_table *powerplay_table =
table_context->power_play_table;
struct smu_baco_context *smu_baco = &smu->smu_baco;
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+ const OverDriveLimits_t * const overdrive_upperlimits =
+ &pptable->SkuTable.OverDriveLimitsBasicMax;
+ const OverDriveLimits_t * const overdrive_lowerlimits =
+ &pptable->SkuTable.OverDriveLimitsMin;
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC)
smu->dc_controlled_by_gpio = true;
@@ -342,6 +347,10 @@ static int smu_v13_0_0_check_powerplay_table(struct smu_context *smu)
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO)
smu_baco->maco_support = true;
+ if (!overdrive_lowerlimits->FeatureCtrlMask ||
+ !overdrive_upperlimits->FeatureCtrlMask)
+ smu->od_enabled = false;
+
table_context->thermal_controller_type =
powerplay_table->thermal_controller_type;
@@ -461,7 +470,7 @@ static int smu_v13_0_0_tables_init(struct smu_context *smu)
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
- SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
+ SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTableExternal_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE,
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
@@ -1022,17 +1031,119 @@ static int smu_v13_0_0_get_current_clk_freq_by_table(struct smu_context *smu,
value);
}
+static bool smu_v13_0_0_is_od_feature_supported(struct smu_context *smu,
+ int od_feature_bit)
+{
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+ const OverDriveLimits_t * const overdrive_upperlimits =
+ &pptable->SkuTable.OverDriveLimitsBasicMax;
+
+ return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
+}
+
+static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
+ int od_feature_bit,
+ bool lower_boundary,
+ int32_t *min,
+ int32_t *max)
+{
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+ const OverDriveLimits_t * const overdrive_upperlimits =
+ &pptable->SkuTable.OverDriveLimitsBasicMax;
+ const OverDriveLimits_t * const overdrive_lowerlimits =
+ &pptable->SkuTable.OverDriveLimitsMin;
+ int32_t od_min_setting, od_max_setting;
+
+ switch (od_feature_bit) {
+ case PP_OD_FEATURE_GFXCLK_BIT:
+ if (lower_boundary) {
+ od_min_setting = overdrive_lowerlimits->GfxclkFmin;
+ od_max_setting = overdrive_upperlimits->GfxclkFmin;
+ } else {
+ od_min_setting = overdrive_lowerlimits->GfxclkFmax;
+ od_max_setting = overdrive_upperlimits->GfxclkFmax;
+ }
+ break;
+ case PP_OD_FEATURE_UCLK_BIT:
+ if (lower_boundary) {
+ od_min_setting = overdrive_lowerlimits->UclkFmin;
+ od_max_setting = overdrive_upperlimits->UclkFmin;
+ } else {
+ od_min_setting = overdrive_lowerlimits->UclkFmax;
+ od_max_setting = overdrive_upperlimits->UclkFmax;
+ }
+ break;
+ case PP_OD_FEATURE_GFX_VF_CURVE_BIT:
+ od_min_setting = overdrive_lowerlimits->VoltageOffsetPerZoneBoundary;
+ od_max_setting = overdrive_upperlimits->VoltageOffsetPerZoneBoundary;
+ break;
+ default:
+ break;
+ }
+
+ if (min)
+ *min = od_min_setting;
+ if (max)
+ *max = od_max_setting;
+}
+
+static void smu_v13_0_0_dump_od_table(struct smu_context *smu,
+ OverDriveTableExternal_t *od_table)
+{
+ struct amdgpu_device *adev = smu->adev;
+
+ dev_dbg(adev->dev, "OD: Gfxclk: (%d, %d)\n", od_table->OverDriveTable.GfxclkFmin,
+ od_table->OverDriveTable.GfxclkFmax);
+ dev_dbg(adev->dev, "OD: Uclk: (%d, %d)\n", od_table->OverDriveTable.UclkFmin,
+ od_table->OverDriveTable.UclkFmax);
+}
+
+static int smu_v13_0_0_get_overdrive_table(struct smu_context *smu,
+ OverDriveTableExternal_t *od_table)
+{
+ int ret = 0;
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_OVERDRIVE,
+ 0,
+ (void *)od_table,
+ false);
+ if (ret)
+ dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
+
+ return ret;
+}
+
+static int smu_v13_0_0_upload_overdrive_table(struct smu_context *smu,
+ OverDriveTableExternal_t *od_table)
+{
+ int ret = 0;
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_OVERDRIVE,
+ 0,
+ (void *)od_table,
+ true);
+ if (ret)
+ dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
+
+ return ret;
+}
+
static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
enum smu_clk_type clk_type,
char *buf)
{
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+ OverDriveTableExternal_t *od_table =
+ (OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
struct smu_13_0_dpm_table *single_dpm_table;
struct smu_13_0_pcie_table *pcie_table;
const int link_width[] = {0, 1, 2, 4, 8, 12, 16};
uint32_t gen_speed, lane_width;
int i, curr_freq, size = 0;
+ int32_t min_value, max_value;
int ret = 0;
smu_cmn_get_sysfs_buf(&buf, &size);
@@ -1149,6 +1260,89 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
"*" : "");
break;
+ case SMU_OD_SCLK:
+ if (!smu_v13_0_0_is_od_feature_supported(smu,
+ PP_OD_FEATURE_GFXCLK_BIT))
+ break;
+
+ size += sysfs_emit_at(buf, size, "OD_SCLK:\n");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
+ od_table->OverDriveTable.GfxclkFmin,
+ od_table->OverDriveTable.GfxclkFmax);
+ break;
+
+ case SMU_OD_MCLK:
+ if (!smu_v13_0_0_is_od_feature_supported(smu,
+ PP_OD_FEATURE_UCLK_BIT))
+ break;
+
+ size += sysfs_emit_at(buf, size, "OD_MCLK:\n");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMHz\n",
+ od_table->OverDriveTable.UclkFmin,
+ od_table->OverDriveTable.UclkFmax);
+ break;
+
+ case SMU_OD_VDDC_CURVE:
+ if (!smu_v13_0_0_is_od_feature_supported(smu,
+ PP_OD_FEATURE_GFX_VF_CURVE_BIT))
+ break;
+
+ size += sysfs_emit_at(buf, size, "OD_VDDC_CURVE:\n");
+ for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
+ size += sysfs_emit_at(buf, size, "%d: %dmv\n",
+ i,
+ od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i]);
+ break;
+
+ case SMU_OD_RANGE:
+ if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) &&
+ !smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) &&
+ !smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT))
+ break;
+
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
+
+ if (smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) {
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_GFXCLK_BIT,
+ true,
+ &min_value,
+ NULL);
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_GFXCLK_BIT,
+ false,
+ NULL,
+ &max_value);
+ size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
+ min_value, max_value);
+ }
+
+ if (smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) {
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_UCLK_BIT,
+ true,
+ &min_value,
+ NULL);
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_UCLK_BIT,
+ false,
+ NULL,
+ &max_value);
+ size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n",
+ min_value, max_value);
+ }
+
+ if (smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) {
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_GFX_VF_CURVE_BIT,
+ true,
+ &min_value,
+ &max_value);
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE: %7dmv %10dmv\n",
+ min_value, max_value);
+ }
+ break;
+
default:
break;
}
@@ -1156,6 +1350,222 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
return size;
}
+static int smu_v13_0_0_od_edit_dpm_table(struct smu_context *smu,
+ enum PP_OD_DPM_TABLE_COMMAND type,
+ long input[],
+ uint32_t size)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ OverDriveTableExternal_t *od_table =
+ (OverDriveTableExternal_t *)table_context->overdrive_table;
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t offset_of_featurectrlmask;
+ int32_t minimum, maximum;
+ uint32_t feature_ctrlmask;
+ int i, ret = 0;
+
+ switch (type) {
+ case PP_OD_EDIT_SCLK_VDDC_TABLE:
+ if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) {
+ dev_warn(adev->dev, "GFXCLK_LIMITS setting not supported!\n");
+ return -ENOTSUPP;
+ }
+
+ for (i = 0; i < size; i += 2) {
+ if (i + 2 > size) {
+ dev_info(adev->dev, "invalid number of input parameters %d\n", size);
+ return -EINVAL;
+ }
+
+ switch (input[i]) {
+ case 0:
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_GFXCLK_BIT,
+ true,
+ &minimum,
+ &maximum);
+ if (input[i + 1] < minimum ||
+ input[i + 1] > maximum) {
+ dev_info(adev->dev, "GfxclkFmin (%ld) must be within [%u, %u]!\n",
+ input[i + 1], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.GfxclkFmin = input[i + 1];
+ od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT;
+ break;
+
+ case 1:
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_GFXCLK_BIT,
+ false,
+ &minimum,
+ &maximum);
+ if (input[i + 1] < minimum ||
+ input[i + 1] > maximum) {
+ dev_info(adev->dev, "GfxclkFmax (%ld) must be within [%u, %u]!\n",
+ input[i + 1], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.GfxclkFmax = input[i + 1];
+ od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT;
+ break;
+
+ default:
+ dev_info(adev->dev, "Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]);
+ dev_info(adev->dev, "Supported indices: [0:min,1:max]\n");
+ return -EINVAL;
+ }
+ }
+
+ if (od_table->OverDriveTable.GfxclkFmin > od_table->OverDriveTable.GfxclkFmax) {
+ dev_err(adev->dev,
+ "Invalid setting: GfxclkFmin(%u) is bigger than GfxclkFmax(%u)\n",
+ (uint32_t)od_table->OverDriveTable.GfxclkFmin,
+ (uint32_t)od_table->OverDriveTable.GfxclkFmax);
+ return -EINVAL;
+ }
+ break;
+
+ case PP_OD_EDIT_MCLK_VDDC_TABLE:
+ if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) {
+ dev_warn(adev->dev, "UCLK_LIMITS setting not supported!\n");
+ return -ENOTSUPP;
+ }
+
+ for (i = 0; i < size; i += 2) {
+ if (i + 2 > size) {
+ dev_info(adev->dev, "invalid number of input parameters %d\n", size);
+ return -EINVAL;
+ }
+
+ switch (input[i]) {
+ case 0:
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_UCLK_BIT,
+ true,
+ &minimum,
+ &maximum);
+ if (input[i + 1] < minimum ||
+ input[i + 1] > maximum) {
+ dev_info(adev->dev, "UclkFmin (%ld) must be within [%u, %u]!\n",
+ input[i + 1], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.UclkFmin = input[i + 1];
+ od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT;
+ break;
+
+ case 1:
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_UCLK_BIT,
+ false,
+ &minimum,
+ &maximum);
+ if (input[i + 1] < minimum ||
+ input[i + 1] > maximum) {
+ dev_info(adev->dev, "UclkFmax (%ld) must be within [%u, %u]!\n",
+ input[i + 1], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.UclkFmax = input[i + 1];
+ od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT;
+ break;
+
+ default:
+ dev_info(adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[i]);
+ dev_info(adev->dev, "Supported indices: [0:min,1:max]\n");
+ return -EINVAL;
+ }
+ }
+
+ if (od_table->OverDriveTable.UclkFmin > od_table->OverDriveTable.UclkFmax) {
+ dev_err(adev->dev,
+ "Invalid setting: UclkFmin(%u) is bigger than UclkFmax(%u)\n",
+ (uint32_t)od_table->OverDriveTable.UclkFmin,
+ (uint32_t)od_table->OverDriveTable.UclkFmax);
+ return -EINVAL;
+ }
+ break;
+
+ case PP_OD_EDIT_VDDC_CURVE:
+ if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) {
+ dev_warn(adev->dev, "VF curve setting not supported!\n");
+ return -ENOTSUPP;
+ }
+
+ if (input[0] >= PP_NUM_OD_VF_CURVE_POINTS ||
+ input[0] < 0)
+ return -EINVAL;
+
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_GFX_VF_CURVE_BIT,
+ true,
+ &minimum,
+ &maximum);
+ if (input[1] < minimum ||
+ input[1] > maximum) {
+ dev_info(adev->dev, "Voltage offset (%ld) must be within [%d, %d]!\n",
+ input[1], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[input[0]] = input[1];
+ od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFX_VF_CURVE_BIT;
+ break;
+
+ case PP_OD_RESTORE_DEFAULT_TABLE:
+ feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask;
+ memcpy(od_table,
+ table_context->boot_overdrive_table,
+ sizeof(OverDriveTableExternal_t));
+ od_table->OverDriveTable.FeatureCtrlMask = feature_ctrlmask;
+ fallthrough;
+
+ case PP_OD_COMMIT_DPM_TABLE:
+ /*
+ * The member below instructs PMFW the settings focused in
+ * this single operation.
+ * `uint32_t FeatureCtrlMask;`
+ * It does not contain actual informations about user's custom
+ * settings. Thus we do not cache it.
+ */
+ offset_of_featurectrlmask = offsetof(OverDriveTable_t, FeatureCtrlMask);
+ if (memcmp((u8 *)od_table + offset_of_featurectrlmask,
+ table_context->user_overdrive_table + offset_of_featurectrlmask,
+ sizeof(OverDriveTableExternal_t) - offset_of_featurectrlmask)) {
+ smu_v13_0_0_dump_od_table(smu, od_table);
+
+ ret = smu_v13_0_0_upload_overdrive_table(smu, od_table);
+ if (ret) {
+ dev_err(adev->dev, "Failed to upload overdrive table!\n");
+ return ret;
+ }
+
+ od_table->OverDriveTable.FeatureCtrlMask = 0;
+ memcpy(table_context->user_overdrive_table + offset_of_featurectrlmask,
+ (u8 *)od_table + offset_of_featurectrlmask,
+ sizeof(OverDriveTableExternal_t) - offset_of_featurectrlmask);
+
+ if (!memcmp(table_context->user_overdrive_table,
+ table_context->boot_overdrive_table,
+ sizeof(OverDriveTableExternal_t)))
+ smu->user_dpm_profile.user_od = false;
+ else
+ smu->user_dpm_profile.user_od = true;
+ }
+ break;
+
+ default:
+ return -ENOSYS;
+ }
+
+ return ret;
+}
+
static int smu_v13_0_0_force_clk_levels(struct smu_context *smu,
enum smu_clk_type clk_type,
uint32_t mask)
@@ -1384,6 +1794,78 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
return sizeof(struct gpu_metrics_v1_3);
}
+static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu)
+{
+ OverDriveTableExternal_t *od_table =
+ (OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
+ OverDriveTableExternal_t *boot_od_table =
+ (OverDriveTableExternal_t *)smu->smu_table.boot_overdrive_table;
+ OverDriveTableExternal_t *user_od_table =
+ (OverDriveTableExternal_t *)smu->smu_table.user_overdrive_table;
+ OverDriveTableExternal_t user_od_table_bak;
+ int ret = 0;
+ int i;
+
+ ret = smu_v13_0_0_get_overdrive_table(smu, boot_od_table);
+ if (ret)
+ return ret;
+
+ smu_v13_0_0_dump_od_table(smu, boot_od_table);
+
+ memcpy(od_table,
+ boot_od_table,
+ sizeof(OverDriveTableExternal_t));
+
+ /*
+ * For S3/S4/Runpm resume, we need to setup those overdrive tables again,
+ * but we have to preserve user defined values in "user_od_table".
+ */
+ if (!smu->adev->in_suspend) {
+ memcpy(user_od_table,
+ boot_od_table,
+ sizeof(OverDriveTableExternal_t));
+ smu->user_dpm_profile.user_od = false;
+ } else if (smu->user_dpm_profile.user_od) {
+ memcpy(&user_od_table_bak,
+ user_od_table,
+ sizeof(OverDriveTableExternal_t));
+ memcpy(user_od_table,
+ boot_od_table,
+ sizeof(OverDriveTableExternal_t));
+ user_od_table->OverDriveTable.GfxclkFmin =
+ user_od_table_bak.OverDriveTable.GfxclkFmin;
+ user_od_table->OverDriveTable.GfxclkFmax =
+ user_od_table_bak.OverDriveTable.GfxclkFmax;
+ user_od_table->OverDriveTable.UclkFmin =
+ user_od_table_bak.OverDriveTable.UclkFmin;
+ user_od_table->OverDriveTable.UclkFmax =
+ user_od_table_bak.OverDriveTable.UclkFmax;
+ for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
+ user_od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] =
+ user_od_table_bak.OverDriveTable.VoltageOffsetPerZoneBoundary[i];
+ }
+
+ return 0;
+}
+
+static int smu_v13_0_0_restore_user_od_settings(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ OverDriveTableExternal_t *od_table = table_context->overdrive_table;
+ OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table;
+ int res;
+
+ user_od_table->OverDriveTable.FeatureCtrlMask = 1U << PP_OD_FEATURE_GFXCLK_BIT |
+ 1U << PP_OD_FEATURE_UCLK_BIT |
+ 1U << PP_OD_FEATURE_GFX_VF_CURVE_BIT;
+ res = smu_v13_0_0_upload_overdrive_table(smu, user_od_table);
+ user_od_table->OverDriveTable.FeatureCtrlMask = 0;
+ if (res == 0)
+ memcpy(od_table, user_od_table, sizeof(OverDriveTableExternal_t));
+
+ return res;
+}
+
static int smu_v13_0_0_populate_umd_state_clk(struct smu_context *smu)
{
struct smu_13_0_dpm_context *dpm_context =
@@ -2126,7 +2608,7 @@ static ssize_t smu_v13_0_0_get_ecc_info(struct smu_context *smu,
ecc_table = (EccInfoTable_t *)smu_table->ecc_table;
- for (i = 0; i < UMC_V8_10_TOTAL_CHANNEL_NUM(adev); i++) {
+ for (i = 0; i < ARRAY_SIZE(ecc_table->EccInfo); i++) {
ecc_info_per_channel = &(eccinfo->ecc[i]);
ecc_info_per_channel->ce_count_lo_chip =
ecc_table->EccInfo[i].ce_count_lo_chip;
@@ -2179,6 +2661,9 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
.notify_memory_pool_location = smu_v13_0_notify_memory_pool_location,
.get_gpu_metrics = smu_v13_0_0_get_gpu_metrics,
.set_soft_freq_limited_range = smu_v13_0_set_soft_freq_limited_range,
+ .set_default_od_settings = smu_v13_0_0_set_default_od_settings,
+ .restore_user_od_settings = smu_v13_0_0_restore_user_od_settings,
+ .od_edit_dpm_table = smu_v13_0_0_od_edit_dpm_table,
.init_pptable_microcode = smu_v13_0_init_pptable_microcode,
.populate_umd_state_clk = smu_v13_0_0_populate_umd_state_clk,
.set_performance_level = smu_v13_0_set_performance_level,
@@ -2228,5 +2713,6 @@ void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu)
smu->table_map = smu_v13_0_0_table_map;
smu->pwr_src_map = smu_v13_0_0_pwr_src_map;
smu->workload_map = smu_v13_0_0_workload_map;
+ smu->smc_driver_if_version = SMU13_0_0_DRIVER_IF_VERSION;
smu_v13_0_0_set_smu_mailbox_registers(smu);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
index 6d9760eac16d..ef37dda9908f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
@@ -54,6 +54,10 @@
#define FEATURE_MASK(feature) (1ULL << feature)
+#define SMU_13_0_4_UMD_PSTATE_GFXCLK 938
+#define SMU_13_0_4_UMD_PSTATE_SOCCLK 938
+#define SMU_13_0_4_UMD_PSTATE_FCLK 1875
+
#define SMC_DPM_FEATURE ( \
FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \
FEATURE_MASK(FEATURE_VCN_DPM_BIT) | \
@@ -831,6 +835,8 @@ static int smu_v13_0_4_set_soft_freq_limited_range(struct smu_context *smu,
uint32_t max)
{
enum smu_message_type msg_set_min, msg_set_max;
+ uint32_t min_clk = min;
+ uint32_t max_clk = max;
int ret = 0;
if (!smu_v13_0_4_clk_dpm_is_enabled(smu, clk_type))
@@ -859,12 +865,17 @@ static int smu_v13_0_4_set_soft_freq_limited_range(struct smu_context *smu,
return -EINVAL;
}
- ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min, NULL);
+ if (clk_type == SMU_VCLK) {
+ min_clk = min << SMU_13_VCLK_SHIFT;
+ max_clk = max << SMU_13_VCLK_SHIFT;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min_clk, NULL);
if (ret)
return ret;
return smu_cmn_send_smc_msg_with_param(smu, msg_set_max,
- max, NULL);
+ max_clk, NULL);
}
static int smu_v13_0_4_force_clk_levels(struct smu_context *smu,
@@ -901,6 +912,50 @@ static int smu_v13_0_4_force_clk_levels(struct smu_context *smu,
return ret;
}
+static int smu_v13_0_4_get_dpm_profile_freq(struct smu_context *smu,
+ enum amd_dpm_forced_level level,
+ enum smu_clk_type clk_type,
+ uint32_t *min_clk,
+ uint32_t *max_clk)
+{
+ int ret = 0;
+ uint32_t clk_limit = 0;
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ clk_limit = SMU_13_0_4_UMD_PSTATE_GFXCLK;
+ if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &clk_limit);
+ else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK)
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SCLK, &clk_limit, NULL);
+ break;
+ case SMU_SOCCLK:
+ clk_limit = SMU_13_0_4_UMD_PSTATE_SOCCLK;
+ if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &clk_limit);
+ break;
+ case SMU_FCLK:
+ clk_limit = SMU_13_0_4_UMD_PSTATE_FCLK;
+ if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &clk_limit);
+ else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK)
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_FCLK, &clk_limit, NULL);
+ break;
+ case SMU_VCLK:
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &clk_limit);
+ break;
+ case SMU_DCLK:
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &clk_limit);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ *min_clk = *max_clk = clk_limit;
+ return ret;
+}
+
static int smu_v13_0_4_set_performance_level(struct smu_context *smu,
enum amd_dpm_forced_level level)
{
@@ -908,6 +963,8 @@ static int smu_v13_0_4_set_performance_level(struct smu_context *smu,
uint32_t sclk_min = 0, sclk_max = 0;
uint32_t fclk_min = 0, fclk_max = 0;
uint32_t socclk_min = 0, socclk_max = 0;
+ uint32_t vclk_min = 0, vclk_max = 0;
+ uint32_t dclk_min = 0, dclk_max = 0;
int ret = 0;
switch (level) {
@@ -915,28 +972,42 @@ static int smu_v13_0_4_set_performance_level(struct smu_context *smu,
smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max);
smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_max);
smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max);
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &vclk_max);
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &dclk_max);
sclk_min = sclk_max;
fclk_min = fclk_max;
socclk_min = socclk_max;
+ vclk_min = vclk_max;
+ dclk_min = dclk_max;
break;
case AMD_DPM_FORCED_LEVEL_LOW:
smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL);
smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, NULL);
smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL);
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, NULL);
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, NULL);
sclk_max = sclk_min;
fclk_max = fclk_min;
socclk_max = socclk_min;
+ vclk_max = vclk_min;
+ dclk_max = dclk_min;
break;
case AMD_DPM_FORCED_LEVEL_AUTO:
smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max);
smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, &fclk_max);
smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max);
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, &vclk_max);
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, &dclk_max);
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
- /* Temporarily do nothing since the optimal clocks haven't been provided yet */
+ smu_v13_0_4_get_dpm_profile_freq(smu, level, SMU_SCLK, &sclk_min, &sclk_max);
+ smu_v13_0_4_get_dpm_profile_freq(smu, level, SMU_FCLK, &fclk_min, &fclk_max);
+ smu_v13_0_4_get_dpm_profile_freq(smu, level, SMU_SOCCLK, &socclk_min, &socclk_max);
+ smu_v13_0_4_get_dpm_profile_freq(smu, level, SMU_VCLK, &vclk_min, &vclk_max);
+ smu_v13_0_4_get_dpm_profile_freq(smu, level, SMU_DCLK, &dclk_min, &dclk_max);
break;
case AMD_DPM_FORCED_LEVEL_MANUAL:
case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
@@ -976,6 +1047,23 @@ static int smu_v13_0_4_set_performance_level(struct smu_context *smu,
return ret;
}
+ if (vclk_min && vclk_max) {
+ ret = smu_v13_0_4_set_soft_freq_limited_range(smu,
+ SMU_VCLK,
+ vclk_min,
+ vclk_max);
+ if (ret)
+ return ret;
+ }
+
+ if (dclk_min && dclk_max) {
+ ret = smu_v13_0_4_set_soft_freq_limited_range(smu,
+ SMU_DCLK,
+ dclk_min,
+ dclk_max);
+ if (ret)
+ return ret;
+ }
return ret;
}
@@ -1044,6 +1132,7 @@ void smu_v13_0_4_set_ppt_funcs(struct smu_context *smu)
smu->message_map = smu_v13_0_4_message_map;
smu->feature_map = smu_v13_0_4_feature_mask_map;
smu->table_map = smu_v13_0_4_table_map;
+ smu->smc_driver_if_version = SMU13_0_4_DRIVER_IF_VERSION;
smu->is_apu = true;
if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 4))
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c
index 0081fa607e02..42f110602eb1 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c
@@ -831,6 +831,8 @@ static int smu_v13_0_5_set_soft_freq_limited_range(struct smu_context *smu,
uint32_t max)
{
enum smu_message_type msg_set_min, msg_set_max;
+ uint32_t min_clk = min;
+ uint32_t max_clk = max;
int ret = 0;
if (!smu_v13_0_5_clk_dpm_is_enabled(smu, clk_type))
@@ -851,11 +853,16 @@ static int smu_v13_0_5_set_soft_freq_limited_range(struct smu_context *smu,
return -EINVAL;
}
- ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min, NULL);
+ if (clk_type == SMU_VCLK) {
+ min_clk = min << SMU_13_VCLK_SHIFT;
+ max_clk = max << SMU_13_VCLK_SHIFT;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min_clk, NULL);
if (ret)
goto out;
- ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_max, max, NULL);
+ ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_max, max_clk, NULL);
if (ret)
goto out;
@@ -971,31 +978,79 @@ force_level_out:
return ret;
}
+static int smu_v13_0_5_get_dpm_profile_freq(struct smu_context *smu,
+ enum amd_dpm_forced_level level,
+ enum smu_clk_type clk_type,
+ uint32_t *min_clk,
+ uint32_t *max_clk)
+{
+ int ret = 0;
+ uint32_t clk_limit = 0;
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ clk_limit = SMU_13_0_5_UMD_PSTATE_GFXCLK;
+ if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
+ smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &clk_limit);
+ else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK)
+ smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_SCLK, &clk_limit, NULL);
+ break;
+ case SMU_VCLK:
+ smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &clk_limit);
+ break;
+ case SMU_DCLK:
+ smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &clk_limit);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ *min_clk = *max_clk = clk_limit;
+ return ret;
+}
+
static int smu_v13_0_5_set_performance_level(struct smu_context *smu,
enum amd_dpm_forced_level level)
{
struct amdgpu_device *adev = smu->adev;
uint32_t sclk_min = 0, sclk_max = 0;
+ uint32_t vclk_min = 0, vclk_max = 0;
+ uint32_t dclk_min = 0, dclk_max = 0;
int ret = 0;
switch (level) {
case AMD_DPM_FORCED_LEVEL_HIGH:
smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max);
+ smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &vclk_max);
+ smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &dclk_max);
sclk_min = sclk_max;
+ vclk_min = vclk_max;
+ dclk_min = dclk_max;
break;
case AMD_DPM_FORCED_LEVEL_LOW:
smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL);
+ smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, NULL);
+ smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, NULL);
sclk_max = sclk_min;
+ vclk_max = vclk_min;
+ dclk_max = dclk_min;
break;
case AMD_DPM_FORCED_LEVEL_AUTO:
smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max);
+ smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, &vclk_max);
+ smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, &dclk_max);
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
- case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
- /* Temporarily do nothing since the optimal clocks haven't been provided yet */
+ smu_v13_0_5_get_dpm_profile_freq(smu, level, SMU_SCLK, &sclk_min, &sclk_max);
+ smu_v13_0_5_get_dpm_profile_freq(smu, level, SMU_VCLK, &vclk_min, &vclk_max);
+ smu_v13_0_5_get_dpm_profile_freq(smu, level, SMU_DCLK, &dclk_min, &dclk_max);
break;
+ case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
+ dev_err(adev->dev, "The performance level profile_min_mclk is not supported.");
+ return -EOPNOTSUPP;
case AMD_DPM_FORCED_LEVEL_MANUAL:
case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
return 0;
@@ -1016,6 +1071,23 @@ static int smu_v13_0_5_set_performance_level(struct smu_context *smu,
smu->gfx_actual_soft_max_freq = sclk_max;
}
+ if (vclk_min && vclk_max) {
+ ret = smu_v13_0_5_set_soft_freq_limited_range(smu,
+ SMU_VCLK,
+ vclk_min,
+ vclk_max);
+ if (ret)
+ return ret;
+ }
+
+ if (dclk_min && dclk_max) {
+ ret = smu_v13_0_5_set_soft_freq_limited_range(smu,
+ SMU_DCLK,
+ dclk_min,
+ dclk_max);
+ if (ret)
+ return ret;
+ }
return ret;
}
@@ -1069,6 +1141,7 @@ void smu_v13_0_5_set_ppt_funcs(struct smu_context *smu)
smu->feature_map = smu_v13_0_5_feature_mask_map;
smu->table_map = smu_v13_0_5_table_map;
smu->is_apu = true;
+ smu->smc_driver_if_version = SMU13_0_5_DRIVER_IF_VERSION;
smu->param_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_C2PMSG_34);
smu->msg_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_C2PMSG_2);
smu->resp_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_C2PMSG_33);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.h
index 40bc0f8e6d61..263cd651855e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.h
@@ -24,6 +24,6 @@
#define __SMU_V13_0_5_PPT_H__
extern void smu_v13_0_5_set_ppt_funcs(struct smu_context *smu);
-#define SMU_13_0_5_UMD_PSTATE_GFXCLK 1100
+#define SMU_13_0_5_UMD_PSTATE_GFXCLK 700
#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
index ea8f3d6fb98b..a92ea4601ea4 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@ -80,7 +80,10 @@
/* possible frequency drift (1Mhz) */
#define EPSILON 1
-#define smnPCIE_ESM_CTRL 0x111003D0
+#define smnPCIE_ESM_CTRL 0x193D0
+#define smnPCIE_LC_LINK_WIDTH_CNTL 0x1ab40288
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK 0x00000070L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT 0x4
static const struct cmn2asic_msg_mapping smu_v13_0_6_message_map[SMU_MSG_MAX_COUNT] = {
MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0),
@@ -122,6 +125,7 @@ static const struct cmn2asic_msg_mapping smu_v13_0_6_message_map[SMU_MSG_MAX_COU
MSG_MAP(GetMaxGfxclkFrequency, PPSMC_MSG_GetMaxGfxDpmFreq, 0),
MSG_MAP(SetSoftMinGfxclk, PPSMC_MSG_SetSoftMinGfxClk, 0),
MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 0),
+ MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareForDriverUnload, 0),
};
static const struct cmn2asic_mapping smu_v13_0_6_clk_map[SMU_CLK_COUNT] = {
@@ -171,18 +175,12 @@ static const struct cmn2asic_mapping smu_v13_0_6_table_map[SMU_TABLE_COUNT] = {
TAB_MAP(I2C_COMMANDS),
};
-#define THROTTLER_PROCHOT_GFX_BIT 0
-#define THROTTLER_PPT_BIT 1
-#define THROTTLER_TEMP_SOC_BIT 2
-#define THROTTLER_TEMP_VR_GFX_BIT 3
-#define THROTTLER_TEMP_HBM_BIT 4
-
static const uint8_t smu_v13_0_6_throttler_map[] = {
[THROTTLER_PPT_BIT] = (SMU_THROTTLER_PPT0_BIT),
- [THROTTLER_TEMP_SOC_BIT] = (SMU_THROTTLER_TEMP_GPU_BIT),
- [THROTTLER_TEMP_HBM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT),
- [THROTTLER_TEMP_VR_GFX_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT),
- [THROTTLER_PROCHOT_GFX_BIT] = (SMU_THROTTLER_PROCHOT_GFX_BIT),
+ [THROTTLER_THERMAL_SOCKET_BIT] = (SMU_THROTTLER_TEMP_GPU_BIT),
+ [THROTTLER_THERMAL_HBM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT),
+ [THROTTLER_THERMAL_VR_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT),
+ [THROTTLER_PROCHOT_BIT] = (SMU_THROTTLER_PROCHOT_GFX_BIT),
};
struct PPTable_t {
@@ -197,10 +195,12 @@ struct PPTable_t {
uint32_t LclkFrequencyTable[4];
uint32_t MaxLclkDpmRange;
uint32_t MinLclkDpmRange;
+ uint64_t PublicSerialNumber_AID;
bool Init;
};
#define SMUQ10_TO_UINT(x) ((x) >> 10)
+#define SMUQ16_TO_UINT(x) ((x) >> 16)
struct smu_v13_0_6_dpm_map {
enum smu_clk_type clk_type;
@@ -220,10 +220,12 @@ static int smu_v13_0_6_tables_init(struct smu_context *smu)
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(MetricsTable_t),
- PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT);
SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
- PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT);
smu_table->metrics_table = kzalloc(sizeof(MetricsTable_t), GFP_KERNEL);
if (!smu_table->metrics_table)
@@ -355,6 +357,9 @@ static int smu_v13_0_6_setup_driver_pptable(struct smu_context *smu)
SMUQ10_TO_UINT(metrics->LclkFrequencyTable[i]);
}
+ /* use AID0 serial number by default */
+ pptable->PublicSerialNumber_AID = metrics->PublicSerialNumber_AID[0];
+
pptable->Init = true;
}
@@ -385,7 +390,7 @@ static int smu_v13_0_6_get_dpm_ultimate_freq(struct smu_context *smu,
break;
case SMU_SOCCLK:
if (pptable->Init)
- clock_limit = pptable->UclkFrequencyTable[0];
+ clock_limit = pptable->SocclkFrequencyTable[0];
break;
case SMU_FCLK:
if (pptable->Init)
@@ -638,16 +643,14 @@ static int smu_v13_0_6_freqs_in_same_level(int32_t frequency1,
return (abs(frequency1 - frequency2) <= EPSILON);
}
-static uint32_t smu_v13_0_6_get_throttler_status(struct smu_context *smu,
- MetricsTable_t *metrics)
+static uint32_t smu_v13_0_6_get_throttler_status(struct smu_context *smu)
{
+ struct smu_power_context *smu_power = &smu->smu_power;
+ struct smu_13_0_power_context *power_context = smu_power->power_context;
uint32_t throttler_status = 0;
- throttler_status |= metrics->ProchotResidencyAcc > 0 ? 1U << THROTTLER_PROCHOT_GFX_BIT : 0;
- throttler_status |= metrics->PptResidencyAcc > 0 ? 1U << THROTTLER_PPT_BIT : 0;
- throttler_status |= metrics->SocketThmResidencyAcc > 0 ? 1U << THROTTLER_TEMP_SOC_BIT : 0;
- throttler_status |= metrics->VrThmResidencyAcc > 0 ? 1U << THROTTLER_TEMP_VR_GFX_BIT : 0;
- throttler_status |= metrics->HbmThmResidencyAcc > 0 ? 1U << THROTTLER_TEMP_HBM_BIT : 0;
+ throttler_status = atomic_read(&power_context->throttle_status);
+ dev_dbg(smu->adev->dev, "SMU Throttler status: %u", throttler_status);
return throttler_status;
}
@@ -658,7 +661,10 @@ static int smu_v13_0_6_get_smu_metrics_data(struct smu_context *smu,
{
struct smu_table_context *smu_table = &smu->smu_table;
MetricsTable_t *metrics = (MetricsTable_t *)smu_table->metrics_table;
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t smu_version;
int ret = 0;
+ int xcc_id;
ret = smu_v13_0_6_get_metrics_table(smu, NULL, false);
if (ret)
@@ -668,7 +674,13 @@ static int smu_v13_0_6_get_smu_metrics_data(struct smu_context *smu,
switch (member) {
case METRICS_CURR_GFXCLK:
case METRICS_AVERAGE_GFXCLK:
- *value = 0;
+ smu_cmn_get_smc_version(smu, NULL, &smu_version);
+ if (smu_version >= 0x552F00) {
+ xcc_id = GET_INST(GC, 0);
+ *value = SMUQ10_TO_UINT(metrics->GfxclkFrequency[xcc_id]);
+ } else {
+ *value = 0;
+ }
break;
case METRICS_CURR_SOCCLK:
case METRICS_AVERAGE_SOCCLK:
@@ -708,9 +720,6 @@ static int smu_v13_0_6_get_smu_metrics_data(struct smu_context *smu,
case METRICS_TEMPERATURE_VRSOC:
*value = SMUQ10_TO_UINT(metrics->MaxVrTemperature);
break;
- case METRICS_THROTTLER_STATUS:
- *value = smu_v13_0_6_get_throttler_status(smu, metrics);
- break;
default:
*value = UINT_MAX;
break;
@@ -1246,21 +1255,6 @@ static int smu_v13_0_6_get_power_limit(struct smu_context *smu,
uint32_t power_limit = 0;
int ret;
- if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
- if (current_power_limit)
- *current_power_limit = 0;
- if (default_power_limit)
- *default_power_limit = 0;
- if (max_power_limit)
- *max_power_limit = 0;
-
- dev_warn(
- smu->adev->dev,
- "PPT feature is not enabled, power values can't be fetched.");
-
- return 0;
- }
-
ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetPptLimit, &power_limit);
if (ret) {
@@ -1287,16 +1281,147 @@ static int smu_v13_0_6_set_power_limit(struct smu_context *smu,
return smu_v13_0_set_power_limit(smu, limit_type, limit);
}
-static int smu_v13_0_6_system_features_control(struct smu_context *smu,
- bool enable)
+static int smu_v13_0_6_irq_process(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
{
- int ret;
+ struct smu_context *smu = adev->powerplay.pp_handle;
+ struct smu_power_context *smu_power = &smu->smu_power;
+ struct smu_13_0_power_context *power_context = smu_power->power_context;
+ uint32_t client_id = entry->client_id;
+ uint32_t ctxid = entry->src_data[0];
+ uint32_t src_id = entry->src_id;
+ uint32_t data;
+
+ if (client_id == SOC15_IH_CLIENTID_MP1) {
+ if (src_id == IH_INTERRUPT_ID_TO_DRIVER) {
+ /* ACK SMUToHost interrupt */
+ data = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL);
+ data = REG_SET_FIELD(data, MP1_SMN_IH_SW_INT_CTRL, INT_ACK, 1);
+ WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, data);
+ /*
+ * ctxid is used to distinguish different events for SMCToHost
+ * interrupt.
+ */
+ switch (ctxid) {
+ case IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING:
+ /*
+ * Increment the throttle interrupt counter
+ */
+ atomic64_inc(&smu->throttle_int_counter);
+
+ if (!atomic_read(&adev->throttling_logging_enabled))
+ return 0;
+
+ /* This uses the new method which fixes the
+ * incorrect throttling status reporting
+ * through metrics table. For older FWs,
+ * it will be ignored.
+ */
+ if (__ratelimit(&adev->throttling_logging_rs)) {
+ atomic_set(
+ &power_context->throttle_status,
+ entry->src_data[1]);
+ schedule_work(&smu->throttling_logging_work);
+ }
+
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int smu_v13_0_6_set_irq_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ unsigned tyep,
+ enum amdgpu_interrupt_state state)
+{
+ uint32_t val = 0;
+
+ switch (state) {
+ case AMDGPU_IRQ_STATE_DISABLE:
+ /* For MP1 SW irqs */
+ val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL);
+ val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 1);
+ WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, val);
- /* Nothing to be done for APU */
- if (smu->adev->flags & AMD_IS_APU)
+ break;
+ case AMDGPU_IRQ_STATE_ENABLE:
+ /* For MP1 SW irqs */
+ val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT);
+ val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, ID, 0xFE);
+ val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, VALID, 0);
+ WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT, val);
+
+ val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL);
+ val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 0);
+ WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, val);
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static const struct amdgpu_irq_src_funcs smu_v13_0_6_irq_funcs =
+{
+ .set = smu_v13_0_6_set_irq_state,
+ .process = smu_v13_0_6_irq_process,
+};
+
+static int smu_v13_0_6_register_irq_handler(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ struct amdgpu_irq_src *irq_src = &smu->irq_source;
+ int ret = 0;
+
+ if (amdgpu_sriov_vf(adev))
return 0;
- ret = smu_v13_0_system_features_control(smu, enable);
+ irq_src->num_types = 1;
+ irq_src->funcs = &smu_v13_0_6_irq_funcs;
+
+ ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_MP1,
+ IH_INTERRUPT_ID_TO_DRIVER,
+ irq_src);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static int smu_v13_0_6_notify_unload(struct smu_context *smu)
+{
+ uint32_t smu_version;
+
+ smu_cmn_get_smc_version(smu, NULL, &smu_version);
+ if (smu_version <= 0x553500)
+ return 0;
+
+ dev_dbg(smu->adev->dev, "Notify PMFW about driver unload");
+ /* Ignore return, just intimate FW that driver is not going to be there */
+ smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
+
+ return 0;
+}
+
+static int smu_v13_0_6_system_features_control(struct smu_context *smu,
+ bool enable)
+{
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+
+ if (enable) {
+ if (!(adev->flags & AMD_IS_APU))
+ ret = smu_v13_0_system_features_control(smu, enable);
+ } else {
+ /* Notify FW that the device is no longer driver managed */
+ smu_v13_0_6_notify_unload(smu);
+ }
return ret;
}
@@ -1737,19 +1862,11 @@ static void smu_v13_0_6_i2c_control_fini(struct smu_context *smu)
static void smu_v13_0_6_get_unique_id(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
- //SmuMetrics_t *metrics = smu->smu_table.metrics_table;
- uint32_t upper32 = 0, lower32 = 0;
- int ret;
-
- ret = smu_cmn_get_metrics_table(smu, NULL, false);
- if (ret)
- goto out;
-
- //upper32 = metrics->PublicSerialNumUpper32;
- //lower32 = metrics->PublicSerialNumLower32;
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct PPTable_t *pptable =
+ (struct PPTable_t *)smu_table->driver_pptable;
-out:
- adev->unique_id = ((uint64_t)upper32 << 32) | lower32;
+ adev->unique_id = pptable->PublicSerialNumber_AID;
if (adev->serial[0] == '\0')
sprintf(adev->serial, "%016llx", adev->unique_id);
}
@@ -1774,37 +1891,35 @@ static int smu_v13_0_6_allow_xgmi_power_down(struct smu_context *smu, bool en)
en ? 0 : 1, NULL);
}
-static const struct throttling_logging_label {
- uint32_t feature_mask;
- const char *label;
-} logging_label[] = {
- { (1U << THROTTLER_TEMP_HBM_BIT), "HBM" },
- { (1U << THROTTLER_TEMP_SOC_BIT), "SOC" },
- { (1U << THROTTLER_TEMP_VR_GFX_BIT), "VR limit" },
+static const char *const throttling_logging_label[] = {
+ [THROTTLER_PROCHOT_BIT] = "Prochot",
+ [THROTTLER_PPT_BIT] = "PPT",
+ [THROTTLER_THERMAL_SOCKET_BIT] = "SOC",
+ [THROTTLER_THERMAL_VR_BIT] = "VR",
+ [THROTTLER_THERMAL_HBM_BIT] = "HBM"
};
+
static void smu_v13_0_6_log_thermal_throttling_event(struct smu_context *smu)
{
- int ret;
int throttler_idx, throtting_events = 0, buf_idx = 0;
struct amdgpu_device *adev = smu->adev;
uint32_t throttler_status;
char log_buf[256];
- ret = smu_v13_0_6_get_smu_metrics_data(smu, METRICS_THROTTLER_STATUS,
- &throttler_status);
- if (ret)
+ throttler_status = smu_v13_0_6_get_throttler_status(smu);
+ if (!throttler_status)
return;
memset(log_buf, 0, sizeof(log_buf));
- for (throttler_idx = 0; throttler_idx < ARRAY_SIZE(logging_label);
+ for (throttler_idx = 0;
+ throttler_idx < ARRAY_SIZE(throttling_logging_label);
throttler_idx++) {
- if (throttler_status &
- logging_label[throttler_idx].feature_mask) {
+ if (throttler_status & (1U << throttler_idx)) {
throtting_events++;
- buf_idx += snprintf(log_buf + buf_idx,
- sizeof(log_buf) - buf_idx, "%s%s",
- throtting_events > 1 ? " and " : "",
- logging_label[throttler_idx].label);
+ buf_idx += snprintf(
+ log_buf + buf_idx, sizeof(log_buf) - buf_idx,
+ "%s%s", throtting_events > 1 ? " and " : "",
+ throttling_logging_label[throttler_idx]);
if (buf_idx >= sizeof(log_buf)) {
dev_err(adev->dev, "buffer overflow!\n");
log_buf[sizeof(log_buf) - 1] = '\0';
@@ -1813,16 +1928,24 @@ static void smu_v13_0_6_log_thermal_throttling_event(struct smu_context *smu)
}
}
- dev_warn(
- adev->dev,
- "WARN: GPU thermal throttling temperature reached, expect performance decrease. %s.\n",
- log_buf);
+ dev_warn(adev->dev,
+ "WARN: GPU is throttled, expect performance decrease. %s.\n",
+ log_buf);
kgd2kfd_smi_event_throttle(
smu->adev->kfd.dev,
smu_cmn_get_indep_throttler_status(throttler_status,
smu_v13_0_6_throttler_map));
}
+static int
+smu_v13_0_6_get_current_pcie_link_width_level(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+
+ return REG_GET_FIELD(RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL),
+ PCIE_LC_LINK_WIDTH_CNTL, LC_LINK_WIDTH_RD);
+}
+
static int smu_v13_0_6_get_current_pcie_link_speed(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
@@ -1841,8 +1964,12 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
struct smu_table_context *smu_table = &smu->smu_table;
struct gpu_metrics_v1_3 *gpu_metrics =
(struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0, inst0, xcc0;
MetricsTable_t *metrics;
- int i, ret = 0;
+
+ inst0 = adev->sdma.instance[0].aid_id;
+ xcc0 = GET_INST(GC, 0);
metrics = kzalloc(sizeof(MetricsTable_t), GFP_KERNEL);
ret = smu_v13_0_6_get_metrics_table(smu, metrics, true);
@@ -1851,51 +1978,59 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
- /* TODO: Decide on how to fill in zero value fields */
- gpu_metrics->temperature_edge = 0;
- gpu_metrics->temperature_hotspot = 0;
- gpu_metrics->temperature_mem = 0;
- gpu_metrics->temperature_vrgfx = 0;
- gpu_metrics->temperature_vrsoc = 0;
- gpu_metrics->temperature_vrmem = 0;
-
- gpu_metrics->average_gfx_activity = 0;
- gpu_metrics->average_umc_activity = 0;
- gpu_metrics->average_mm_activity = 0;
-
- gpu_metrics->average_socket_power = 0;
- gpu_metrics->energy_accumulator = 0;
-
- gpu_metrics->average_gfxclk_frequency = 0;
- gpu_metrics->average_socclk_frequency = 0;
- gpu_metrics->average_uclk_frequency = 0;
- gpu_metrics->average_vclk0_frequency = 0;
- gpu_metrics->average_dclk0_frequency = 0;
-
- gpu_metrics->current_gfxclk = 0;
- gpu_metrics->current_socclk = 0;
- gpu_metrics->current_uclk = 0;
- gpu_metrics->current_vclk0 = 0;
- gpu_metrics->current_dclk0 = 0;
-
+ gpu_metrics->temperature_hotspot =
+ SMUQ10_TO_UINT(metrics->MaxSocketTemperature);
+ /* Individual HBM stack temperature is not reported */
+ gpu_metrics->temperature_mem =
+ SMUQ10_TO_UINT(metrics->MaxHbmTemperature);
+ /* Reports max temperature of all voltage rails */
+ gpu_metrics->temperature_vrsoc =
+ SMUQ10_TO_UINT(metrics->MaxVrTemperature);
+
+ gpu_metrics->average_gfx_activity =
+ SMUQ10_TO_UINT(metrics->SocketGfxBusy);
+ gpu_metrics->average_umc_activity =
+ SMUQ10_TO_UINT(metrics->DramBandwidthUtilization);
+
+ gpu_metrics->average_socket_power =
+ SMUQ10_TO_UINT(metrics->SocketPower);
+ gpu_metrics->energy_accumulator =
+ SMUQ16_TO_UINT(metrics->SocketEnergyAcc);
+
+ gpu_metrics->current_gfxclk =
+ SMUQ10_TO_UINT(metrics->GfxclkFrequency[xcc0]);
+ gpu_metrics->current_socclk =
+ SMUQ10_TO_UINT(metrics->SocclkFrequency[inst0]);
+ gpu_metrics->current_uclk = SMUQ10_TO_UINT(metrics->UclkFrequency);
+ gpu_metrics->current_vclk0 =
+ SMUQ10_TO_UINT(metrics->VclkFrequency[inst0]);
+ gpu_metrics->current_dclk0 =
+ SMUQ10_TO_UINT(metrics->DclkFrequency[inst0]);
+
+ gpu_metrics->average_gfxclk_frequency = gpu_metrics->current_gfxclk;
+ gpu_metrics->average_socclk_frequency = gpu_metrics->current_socclk;
+ gpu_metrics->average_uclk_frequency = gpu_metrics->current_uclk;
+ gpu_metrics->average_vclk0_frequency = gpu_metrics->current_vclk0;
+ gpu_metrics->average_dclk0_frequency = gpu_metrics->current_dclk0;
+
+ /* Throttle status is not reported through metrics now */
gpu_metrics->throttle_status = 0;
- gpu_metrics->indep_throttle_status = smu_cmn_get_indep_throttler_status(
- gpu_metrics->throttle_status, smu_v13_0_6_throttler_map);
- gpu_metrics->current_fan_speed = 0;
-
- gpu_metrics->pcie_link_width = 0;
- gpu_metrics->pcie_link_speed = smu_v13_0_6_get_current_pcie_link_speed(smu);
+ if (!(adev->flags & AMD_IS_APU)) {
+ gpu_metrics->pcie_link_width =
+ smu_v13_0_6_get_current_pcie_link_width_level(smu);
+ gpu_metrics->pcie_link_speed =
+ smu_v13_0_6_get_current_pcie_link_speed(smu);
+ }
gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
- gpu_metrics->gfx_activity_acc = 0;
- gpu_metrics->mem_activity_acc = 0;
+ gpu_metrics->gfx_activity_acc =
+ SMUQ10_TO_UINT(metrics->SocketGfxBusyAcc);
+ gpu_metrics->mem_activity_acc =
+ SMUQ10_TO_UINT(metrics->DramBandwidthUtilizationAcc);
- for (i = 0; i < NUM_HBM_INSTANCES; i++)
- gpu_metrics->temperature_hbm[i] = 0;
-
- gpu_metrics->firmware_timestamp = 0;
+ gpu_metrics->firmware_timestamp = metrics->Timestamp;
*table = (void *)gpu_metrics;
kfree(metrics);
@@ -1905,27 +2040,27 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
static int smu_v13_0_6_mode2_reset(struct smu_context *smu)
{
- u32 smu_version;
int ret = 0, index;
struct amdgpu_device *adev = smu->adev;
int timeout = 10;
- smu_cmn_get_smc_version(smu, NULL, &smu_version);
-
index = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG,
SMU_MSG_GfxDeviceDriverReset);
mutex_lock(&smu->message_lock);
+
ret = smu_cmn_send_msg_without_waiting(smu, (uint16_t)index,
SMU_RESET_MODE_2);
+
/* This is similar to FLR, wait till max FLR timeout */
msleep(100);
+
dev_dbg(smu->adev->dev, "restore config space...\n");
/* Restore the config space saved during init */
amdgpu_device_load_pci_state(adev->pdev);
dev_dbg(smu->adev->dev, "wait for reset ack\n");
- while (ret == -ETIME && timeout) {
+ do {
ret = smu_cmn_wait_for_response(smu);
/* Wait a bit more time for getting ACK */
if (ret == -ETIME) {
@@ -1934,16 +2069,14 @@ static int smu_v13_0_6_mode2_reset(struct smu_context *smu)
continue;
}
- if (ret != 1) {
+ if (ret) {
dev_err(adev->dev,
- "failed to send mode2 message \tparam: 0x%08x response %#x\n",
+ "failed to send mode2 message \tparam: 0x%08x error code %d\n",
SMU_RESET_MODE_2, ret);
goto out;
}
- }
+ } while (ret == -ETIME && timeout);
- if (ret == 1)
- ret = 0;
out:
mutex_unlock(&smu->message_lock);
@@ -2032,11 +2165,9 @@ static const struct pptable_funcs smu_v13_0_6_ppt_funcs = {
.feature_is_enabled = smu_cmn_feature_is_enabled,
.set_power_limit = smu_v13_0_6_set_power_limit,
.set_xgmi_pstate = smu_v13_0_set_xgmi_pstate,
- /* TODO: Thermal limits unknown, skip these for now
- .register_irq_handler = smu_v13_0_register_irq_handler,
+ .register_irq_handler = smu_v13_0_6_register_irq_handler,
.enable_thermal_alert = smu_v13_0_enable_thermal_alert,
.disable_thermal_alert = smu_v13_0_disable_thermal_alert,
- */
.setup_pptable = smu_v13_0_6_setup_pptable,
.baco_is_support = smu_v13_0_6_is_baco_supported,
.get_dpm_ultimate_freq = smu_v13_0_6_get_dpm_ultimate_freq,
@@ -2065,5 +2196,6 @@ void smu_v13_0_6_set_ppt_funcs(struct smu_context *smu)
smu->clock_map = smu_v13_0_6_clk_map;
smu->feature_map = smu_v13_0_6_feature_mask_map;
smu->table_map = smu_v13_0_6_table_map;
+ smu->smc_driver_if_version = SMU13_0_6_DRIVER_IF_VERSION;
smu_v13_0_set_smu_mailbox_registers(smu);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
index bba621615abf..cda4e818aab7 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -206,6 +206,7 @@ static struct cmn2asic_mapping smu_v13_0_7_table_map[SMU_TABLE_COUNT] = {
TAB_MAP(DRIVER_SMU_CONFIG),
TAB_MAP(ACTIVITY_MONITOR_COEFF),
[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
+ TAB_MAP(OVERDRIVE),
};
static struct cmn2asic_mapping smu_v13_0_7_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
@@ -322,6 +323,10 @@ static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu)
struct smu_baco_context *smu_baco = &smu->smu_baco;
PPTable_t *smc_pptable = table_context->driver_pptable;
BoardTable_t *BoardTable = &smc_pptable->BoardTable;
+ const OverDriveLimits_t * const overdrive_upperlimits =
+ &smc_pptable->SkuTable.OverDriveLimitsBasicMax;
+ const OverDriveLimits_t * const overdrive_lowerlimits =
+ &smc_pptable->SkuTable.OverDriveLimitsMin;
if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC)
smu->dc_controlled_by_gpio = true;
@@ -333,6 +338,10 @@ static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu)
if (smu_baco->platform_support && (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled))
smu_baco->maco_support = true;
+ if (!overdrive_lowerlimits->FeatureCtrlMask ||
+ !overdrive_upperlimits->FeatureCtrlMask)
+ smu->od_enabled = false;
+
table_context->thermal_controller_type =
powerplay_table->thermal_controller_type;
@@ -479,7 +488,7 @@ static int smu_v13_0_7_tables_init(struct smu_context *smu)
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
- SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
+ SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTableExternal_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE,
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
@@ -1013,16 +1022,118 @@ static int smu_v13_0_7_get_current_clk_freq_by_table(struct smu_context *smu,
value);
}
+static bool smu_v13_0_7_is_od_feature_supported(struct smu_context *smu,
+ int od_feature_bit)
+{
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+ const OverDriveLimits_t * const overdrive_upperlimits =
+ &pptable->SkuTable.OverDriveLimitsBasicMax;
+
+ return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
+}
+
+static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
+ int od_feature_bit,
+ bool lower_boundary,
+ int32_t *min,
+ int32_t *max)
+{
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+ const OverDriveLimits_t * const overdrive_upperlimits =
+ &pptable->SkuTable.OverDriveLimitsBasicMax;
+ const OverDriveLimits_t * const overdrive_lowerlimits =
+ &pptable->SkuTable.OverDriveLimitsMin;
+ int32_t od_min_setting, od_max_setting;
+
+ switch (od_feature_bit) {
+ case PP_OD_FEATURE_GFXCLK_BIT:
+ if (lower_boundary) {
+ od_min_setting = overdrive_lowerlimits->GfxclkFmin;
+ od_max_setting = overdrive_upperlimits->GfxclkFmin;
+ } else {
+ od_min_setting = overdrive_lowerlimits->GfxclkFmax;
+ od_max_setting = overdrive_upperlimits->GfxclkFmax;
+ }
+ break;
+ case PP_OD_FEATURE_UCLK_BIT:
+ if (lower_boundary) {
+ od_min_setting = overdrive_lowerlimits->UclkFmin;
+ od_max_setting = overdrive_upperlimits->UclkFmin;
+ } else {
+ od_min_setting = overdrive_lowerlimits->UclkFmax;
+ od_max_setting = overdrive_upperlimits->UclkFmax;
+ }
+ break;
+ case PP_OD_FEATURE_GFX_VF_CURVE_BIT:
+ od_min_setting = overdrive_lowerlimits->VoltageOffsetPerZoneBoundary;
+ od_max_setting = overdrive_upperlimits->VoltageOffsetPerZoneBoundary;
+ break;
+ default:
+ break;
+ }
+
+ if (min)
+ *min = od_min_setting;
+ if (max)
+ *max = od_max_setting;
+}
+
+static void smu_v13_0_7_dump_od_table(struct smu_context *smu,
+ OverDriveTableExternal_t *od_table)
+{
+ struct amdgpu_device *adev = smu->adev;
+
+ dev_dbg(adev->dev, "OD: Gfxclk: (%d, %d)\n", od_table->OverDriveTable.GfxclkFmin,
+ od_table->OverDriveTable.GfxclkFmax);
+ dev_dbg(adev->dev, "OD: Uclk: (%d, %d)\n", od_table->OverDriveTable.UclkFmin,
+ od_table->OverDriveTable.UclkFmax);
+}
+
+static int smu_v13_0_7_get_overdrive_table(struct smu_context *smu,
+ OverDriveTableExternal_t *od_table)
+{
+ int ret = 0;
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_OVERDRIVE,
+ 0,
+ (void *)od_table,
+ false);
+ if (ret)
+ dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
+
+ return ret;
+}
+
+static int smu_v13_0_7_upload_overdrive_table(struct smu_context *smu,
+ OverDriveTableExternal_t *od_table)
+{
+ int ret = 0;
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_OVERDRIVE,
+ 0,
+ (void *)od_table,
+ true);
+ if (ret)
+ dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
+
+ return ret;
+}
+
static int smu_v13_0_7_print_clk_levels(struct smu_context *smu,
enum smu_clk_type clk_type,
char *buf)
{
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+ OverDriveTableExternal_t *od_table =
+ (OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
struct smu_13_0_dpm_table *single_dpm_table;
struct smu_13_0_pcie_table *pcie_table;
uint32_t gen_speed, lane_width;
int i, curr_freq, size = 0;
+ int32_t min_value, max_value;
int ret = 0;
smu_cmn_get_sysfs_buf(&buf, &size);
@@ -1139,6 +1250,89 @@ static int smu_v13_0_7_print_clk_levels(struct smu_context *smu,
"*" : "");
break;
+ case SMU_OD_SCLK:
+ if (!smu_v13_0_7_is_od_feature_supported(smu,
+ PP_OD_FEATURE_GFXCLK_BIT))
+ break;
+
+ size += sysfs_emit_at(buf, size, "OD_SCLK:\n");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
+ od_table->OverDriveTable.GfxclkFmin,
+ od_table->OverDriveTable.GfxclkFmax);
+ break;
+
+ case SMU_OD_MCLK:
+ if (!smu_v13_0_7_is_od_feature_supported(smu,
+ PP_OD_FEATURE_UCLK_BIT))
+ break;
+
+ size += sysfs_emit_at(buf, size, "OD_MCLK:\n");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMHz\n",
+ od_table->OverDriveTable.UclkFmin,
+ od_table->OverDriveTable.UclkFmax);
+ break;
+
+ case SMU_OD_VDDC_CURVE:
+ if (!smu_v13_0_7_is_od_feature_supported(smu,
+ PP_OD_FEATURE_GFX_VF_CURVE_BIT))
+ break;
+
+ size += sysfs_emit_at(buf, size, "OD_VDDC_CURVE:\n");
+ for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
+ size += sysfs_emit_at(buf, size, "%d: %dmv\n",
+ i,
+ od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i]);
+ break;
+
+ case SMU_OD_RANGE:
+ if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) &&
+ !smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) &&
+ !smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT))
+ break;
+
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
+
+ if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) {
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_GFXCLK_BIT,
+ true,
+ &min_value,
+ NULL);
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_GFXCLK_BIT,
+ false,
+ NULL,
+ &max_value);
+ size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
+ min_value, max_value);
+ }
+
+ if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) {
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_UCLK_BIT,
+ true,
+ &min_value,
+ NULL);
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_UCLK_BIT,
+ false,
+ NULL,
+ &max_value);
+ size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n",
+ min_value, max_value);
+ }
+
+ if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) {
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_GFX_VF_CURVE_BIT,
+ true,
+ &min_value,
+ &max_value);
+ size += sysfs_emit_at(buf, size, "VDDC_CURVE: %7dmv %10dmv\n",
+ min_value, max_value);
+ }
+ break;
+
default:
break;
}
@@ -1146,6 +1340,222 @@ static int smu_v13_0_7_print_clk_levels(struct smu_context *smu,
return size;
}
+static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu,
+ enum PP_OD_DPM_TABLE_COMMAND type,
+ long input[],
+ uint32_t size)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ OverDriveTableExternal_t *od_table =
+ (OverDriveTableExternal_t *)table_context->overdrive_table;
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t offset_of_featurectrlmask;
+ int32_t minimum, maximum;
+ uint32_t feature_ctrlmask;
+ int i, ret = 0;
+
+ switch (type) {
+ case PP_OD_EDIT_SCLK_VDDC_TABLE:
+ if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) {
+ dev_warn(adev->dev, "GFXCLK_LIMITS setting not supported!\n");
+ return -ENOTSUPP;
+ }
+
+ for (i = 0; i < size; i += 2) {
+ if (i + 2 > size) {
+ dev_info(adev->dev, "invalid number of input parameters %d\n", size);
+ return -EINVAL;
+ }
+
+ switch (input[i]) {
+ case 0:
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_GFXCLK_BIT,
+ true,
+ &minimum,
+ &maximum);
+ if (input[i + 1] < minimum ||
+ input[i + 1] > maximum) {
+ dev_info(adev->dev, "GfxclkFmin (%ld) must be within [%u, %u]!\n",
+ input[i + 1], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.GfxclkFmin = input[i + 1];
+ od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT;
+ break;
+
+ case 1:
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_GFXCLK_BIT,
+ false,
+ &minimum,
+ &maximum);
+ if (input[i + 1] < minimum ||
+ input[i + 1] > maximum) {
+ dev_info(adev->dev, "GfxclkFmax (%ld) must be within [%u, %u]!\n",
+ input[i + 1], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.GfxclkFmax = input[i + 1];
+ od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT;
+ break;
+
+ default:
+ dev_info(adev->dev, "Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]);
+ dev_info(adev->dev, "Supported indices: [0:min,1:max]\n");
+ return -EINVAL;
+ }
+ }
+
+ if (od_table->OverDriveTable.GfxclkFmin > od_table->OverDriveTable.GfxclkFmax) {
+ dev_err(adev->dev,
+ "Invalid setting: GfxclkFmin(%u) is bigger than GfxclkFmax(%u)\n",
+ (uint32_t)od_table->OverDriveTable.GfxclkFmin,
+ (uint32_t)od_table->OverDriveTable.GfxclkFmax);
+ return -EINVAL;
+ }
+ break;
+
+ case PP_OD_EDIT_MCLK_VDDC_TABLE:
+ if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) {
+ dev_warn(adev->dev, "UCLK_LIMITS setting not supported!\n");
+ return -ENOTSUPP;
+ }
+
+ for (i = 0; i < size; i += 2) {
+ if (i + 2 > size) {
+ dev_info(adev->dev, "invalid number of input parameters %d\n", size);
+ return -EINVAL;
+ }
+
+ switch (input[i]) {
+ case 0:
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_UCLK_BIT,
+ true,
+ &minimum,
+ &maximum);
+ if (input[i + 1] < minimum ||
+ input[i + 1] > maximum) {
+ dev_info(adev->dev, "UclkFmin (%ld) must be within [%u, %u]!\n",
+ input[i + 1], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.UclkFmin = input[i + 1];
+ od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT;
+ break;
+
+ case 1:
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_UCLK_BIT,
+ false,
+ &minimum,
+ &maximum);
+ if (input[i + 1] < minimum ||
+ input[i + 1] > maximum) {
+ dev_info(adev->dev, "UclkFmax (%ld) must be within [%u, %u]!\n",
+ input[i + 1], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.UclkFmax = input[i + 1];
+ od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT;
+ break;
+
+ default:
+ dev_info(adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[i]);
+ dev_info(adev->dev, "Supported indices: [0:min,1:max]\n");
+ return -EINVAL;
+ }
+ }
+
+ if (od_table->OverDriveTable.UclkFmin > od_table->OverDriveTable.UclkFmax) {
+ dev_err(adev->dev,
+ "Invalid setting: UclkFmin(%u) is bigger than UclkFmax(%u)\n",
+ (uint32_t)od_table->OverDriveTable.UclkFmin,
+ (uint32_t)od_table->OverDriveTable.UclkFmax);
+ return -EINVAL;
+ }
+ break;
+
+ case PP_OD_EDIT_VDDC_CURVE:
+ if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) {
+ dev_warn(adev->dev, "VF curve setting not supported!\n");
+ return -ENOTSUPP;
+ }
+
+ if (input[0] >= PP_NUM_OD_VF_CURVE_POINTS ||
+ input[0] < 0)
+ return -EINVAL;
+
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_GFX_VF_CURVE_BIT,
+ true,
+ &minimum,
+ &maximum);
+ if (input[1] < minimum ||
+ input[1] > maximum) {
+ dev_info(adev->dev, "Voltage offset (%ld) must be within [%d, %d]!\n",
+ input[1], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[input[0]] = input[1];
+ od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFX_VF_CURVE_BIT;
+ break;
+
+ case PP_OD_RESTORE_DEFAULT_TABLE:
+ feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask;
+ memcpy(od_table,
+ table_context->boot_overdrive_table,
+ sizeof(OverDriveTableExternal_t));
+ od_table->OverDriveTable.FeatureCtrlMask = feature_ctrlmask;
+ fallthrough;
+
+ case PP_OD_COMMIT_DPM_TABLE:
+ /*
+ * The member below instructs PMFW the settings focused in
+ * this single operation.
+ * `uint32_t FeatureCtrlMask;`
+ * It does not contain actual informations about user's custom
+ * settings. Thus we do not cache it.
+ */
+ offset_of_featurectrlmask = offsetof(OverDriveTable_t, FeatureCtrlMask);
+ if (memcmp((u8 *)od_table + offset_of_featurectrlmask,
+ table_context->user_overdrive_table + offset_of_featurectrlmask,
+ sizeof(OverDriveTableExternal_t) - offset_of_featurectrlmask)) {
+ smu_v13_0_7_dump_od_table(smu, od_table);
+
+ ret = smu_v13_0_7_upload_overdrive_table(smu, od_table);
+ if (ret) {
+ dev_err(adev->dev, "Failed to upload overdrive table!\n");
+ return ret;
+ }
+
+ od_table->OverDriveTable.FeatureCtrlMask = 0;
+ memcpy(table_context->user_overdrive_table + offset_of_featurectrlmask,
+ (u8 *)od_table + offset_of_featurectrlmask,
+ sizeof(OverDriveTableExternal_t) - offset_of_featurectrlmask);
+
+ if (!memcmp(table_context->user_overdrive_table,
+ table_context->boot_overdrive_table,
+ sizeof(OverDriveTableExternal_t)))
+ smu->user_dpm_profile.user_od = false;
+ else
+ smu->user_dpm_profile.user_od = true;
+ }
+ break;
+
+ default:
+ return -ENOSYS;
+ }
+
+ return ret;
+}
+
static int smu_v13_0_7_force_clk_levels(struct smu_context *smu,
enum smu_clk_type clk_type,
uint32_t mask)
@@ -1371,6 +1781,78 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
return sizeof(struct gpu_metrics_v1_3);
}
+static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu)
+{
+ OverDriveTableExternal_t *od_table =
+ (OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
+ OverDriveTableExternal_t *boot_od_table =
+ (OverDriveTableExternal_t *)smu->smu_table.boot_overdrive_table;
+ OverDriveTableExternal_t *user_od_table =
+ (OverDriveTableExternal_t *)smu->smu_table.user_overdrive_table;
+ OverDriveTableExternal_t user_od_table_bak;
+ int ret = 0;
+ int i;
+
+ ret = smu_v13_0_7_get_overdrive_table(smu, boot_od_table);
+ if (ret)
+ return ret;
+
+ smu_v13_0_7_dump_od_table(smu, boot_od_table);
+
+ memcpy(od_table,
+ boot_od_table,
+ sizeof(OverDriveTableExternal_t));
+
+ /*
+ * For S3/S4/Runpm resume, we need to setup those overdrive tables again,
+ * but we have to preserve user defined values in "user_od_table".
+ */
+ if (!smu->adev->in_suspend) {
+ memcpy(user_od_table,
+ boot_od_table,
+ sizeof(OverDriveTableExternal_t));
+ smu->user_dpm_profile.user_od = false;
+ } else if (smu->user_dpm_profile.user_od) {
+ memcpy(&user_od_table_bak,
+ user_od_table,
+ sizeof(OverDriveTableExternal_t));
+ memcpy(user_od_table,
+ boot_od_table,
+ sizeof(OverDriveTableExternal_t));
+ user_od_table->OverDriveTable.GfxclkFmin =
+ user_od_table_bak.OverDriveTable.GfxclkFmin;
+ user_od_table->OverDriveTable.GfxclkFmax =
+ user_od_table_bak.OverDriveTable.GfxclkFmax;
+ user_od_table->OverDriveTable.UclkFmin =
+ user_od_table_bak.OverDriveTable.UclkFmin;
+ user_od_table->OverDriveTable.UclkFmax =
+ user_od_table_bak.OverDriveTable.UclkFmax;
+ for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
+ user_od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] =
+ user_od_table_bak.OverDriveTable.VoltageOffsetPerZoneBoundary[i];
+ }
+
+ return 0;
+}
+
+static int smu_v13_0_7_restore_user_od_settings(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ OverDriveTableExternal_t *od_table = table_context->overdrive_table;
+ OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table;
+ int res;
+
+ user_od_table->OverDriveTable.FeatureCtrlMask = 1U << PP_OD_FEATURE_GFXCLK_BIT |
+ 1U << PP_OD_FEATURE_UCLK_BIT |
+ 1U << PP_OD_FEATURE_GFX_VF_CURVE_BIT;
+ res = smu_v13_0_7_upload_overdrive_table(smu, user_od_table);
+ user_od_table->OverDriveTable.FeatureCtrlMask = 0;
+ if (res == 0)
+ memcpy(od_table, user_od_table, sizeof(OverDriveTableExternal_t));
+
+ return res;
+}
+
static int smu_v13_0_7_populate_umd_state_clk(struct smu_context *smu)
{
struct smu_13_0_dpm_context *dpm_context =
@@ -1760,6 +2242,9 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
.notify_memory_pool_location = smu_v13_0_notify_memory_pool_location,
.get_gpu_metrics = smu_v13_0_7_get_gpu_metrics,
.set_soft_freq_limited_range = smu_v13_0_set_soft_freq_limited_range,
+ .set_default_od_settings = smu_v13_0_7_set_default_od_settings,
+ .restore_user_od_settings = smu_v13_0_7_restore_user_od_settings,
+ .od_edit_dpm_table = smu_v13_0_7_od_edit_dpm_table,
.set_performance_level = smu_v13_0_set_performance_level,
.gfx_off_control = smu_v13_0_gfx_off_control,
.get_fan_speed_pwm = smu_v13_0_7_get_fan_speed_pwm,
@@ -1798,5 +2283,6 @@ void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu)
smu->table_map = smu_v13_0_7_table_map;
smu->pwr_src_map = smu_v13_0_7_pwr_src_map;
smu->workload_map = smu_v13_0_7_workload_map;
+ smu->smc_driver_if_version = SMU13_0_7_DRIVER_IF_VERSION;
smu_v13_0_set_smu_mailbox_registers(smu);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
index 798f36cfcebd..a1be2029ba4a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
@@ -47,6 +47,14 @@
#define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK 0x00000006L
#define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT 0x1L
+#define SMU_13_0_8_UMD_PSTATE_GFXCLK 533
+#define SMU_13_0_8_UMD_PSTATE_SOCCLK 533
+#define SMU_13_0_8_UMD_PSTATE_FCLK 800
+
+#define SMU_13_0_1_UMD_PSTATE_GFXCLK 700
+#define SMU_13_0_1_UMD_PSTATE_SOCCLK 678
+#define SMU_13_0_1_UMD_PSTATE_FCLK 1800
+
#define FEATURE_MASK(feature) (1ULL << feature)
#define SMC_DPM_FEATURE ( \
FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \
@@ -957,6 +965,9 @@ static int yellow_carp_set_soft_freq_limited_range(struct smu_context *smu,
uint32_t max)
{
enum smu_message_type msg_set_min, msg_set_max;
+ uint32_t min_clk = min;
+ uint32_t max_clk = max;
+
int ret = 0;
if (!yellow_carp_clk_dpm_is_enabled(smu, clk_type))
@@ -985,11 +996,17 @@ static int yellow_carp_set_soft_freq_limited_range(struct smu_context *smu,
return -EINVAL;
}
- ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min, NULL);
+ if (clk_type == SMU_VCLK) {
+ min_clk = min << SMU_13_VCLK_SHIFT;
+ max_clk = max << SMU_13_VCLK_SHIFT;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min_clk, NULL);
+
if (ret)
goto out;
- ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_max, max, NULL);
+ ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_max, max_clk, NULL);
if (ret)
goto out;
@@ -997,12 +1014,49 @@ out:
return ret;
}
+static uint32_t yellow_carp_get_umd_pstate_clk_default(struct smu_context *smu,
+ enum smu_clk_type clk_type)
+{
+ uint32_t clk_limit = 0;
+ struct amdgpu_device *adev = smu->adev;
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ if ((adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 8))
+ clk_limit = SMU_13_0_8_UMD_PSTATE_GFXCLK;
+ if ((adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 1) ||
+ (adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 3))
+ clk_limit = SMU_13_0_1_UMD_PSTATE_GFXCLK;
+ break;
+ case SMU_SOCCLK:
+ if ((adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 8))
+ clk_limit = SMU_13_0_8_UMD_PSTATE_SOCCLK;
+ if ((adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 1) ||
+ (adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 3))
+ clk_limit = SMU_13_0_1_UMD_PSTATE_SOCCLK;
+ break;
+ case SMU_FCLK:
+ if ((adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 8))
+ clk_limit = SMU_13_0_8_UMD_PSTATE_FCLK;
+ if ((adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 1) ||
+ (adev->ip_versions[MP1_HWIP][0]) == IP_VERSION(13, 0, 3))
+ clk_limit = SMU_13_0_1_UMD_PSTATE_FCLK;
+ break;
+ default:
+ break;
+ }
+
+ return clk_limit;
+}
+
static int yellow_carp_print_clk_levels(struct smu_context *smu,
enum smu_clk_type clk_type, char *buf)
{
int i, idx, size = 0, ret = 0;
uint32_t cur_value = 0, value = 0, count = 0;
uint32_t min, max;
+ uint32_t clk_limit = 0;
smu_cmn_get_sysfs_buf(&buf, &size);
@@ -1044,6 +1098,7 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu,
break;
case SMU_GFXCLK:
case SMU_SCLK:
+ clk_limit = yellow_carp_get_umd_pstate_clk_default(smu, clk_type);
ret = yellow_carp_get_current_clk_freq(smu, clk_type, &cur_value);
if (ret)
goto print_clk_out;
@@ -1058,7 +1113,7 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu,
size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min,
i == 0 ? "*" : "");
size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
- i == 1 ? cur_value : YELLOW_CARP_UMD_PSTATE_GFXCLK,
+ i == 1 ? cur_value : clk_limit,
i == 1 ? "*" : "");
size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max,
i == 2 ? "*" : "");
@@ -1107,6 +1162,49 @@ force_level_out:
return ret;
}
+static int yellow_carp_get_dpm_profile_freq(struct smu_context *smu,
+ enum amd_dpm_forced_level level,
+ enum smu_clk_type clk_type,
+ uint32_t *min_clk,
+ uint32_t *max_clk)
+{
+ int ret = 0;
+ uint32_t clk_limit = 0;
+
+ clk_limit = yellow_carp_get_umd_pstate_clk_default(smu, clk_type);
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &clk_limit);
+ else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK)
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &clk_limit, NULL);
+ break;
+ case SMU_SOCCLK:
+ if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &clk_limit);
+ break;
+ case SMU_FCLK:
+ if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &clk_limit);
+ else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK)
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, &clk_limit, NULL);
+ break;
+ case SMU_VCLK:
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &clk_limit);
+ break;
+ case SMU_DCLK:
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &clk_limit);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ *min_clk = *max_clk = clk_limit;
+ return ret;
+}
+
static int yellow_carp_set_performance_level(struct smu_context *smu,
enum amd_dpm_forced_level level)
{
@@ -1114,6 +1212,9 @@ static int yellow_carp_set_performance_level(struct smu_context *smu,
uint32_t sclk_min = 0, sclk_max = 0;
uint32_t fclk_min = 0, fclk_max = 0;
uint32_t socclk_min = 0, socclk_max = 0;
+ uint32_t vclk_min = 0, vclk_max = 0;
+ uint32_t dclk_min = 0, dclk_max = 0;
+
int ret = 0;
switch (level) {
@@ -1121,28 +1222,42 @@ static int yellow_carp_set_performance_level(struct smu_context *smu,
yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max);
yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_max);
yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max);
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &vclk_max);
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &dclk_max);
sclk_min = sclk_max;
fclk_min = fclk_max;
socclk_min = socclk_max;
+ vclk_min = vclk_max;
+ dclk_min = dclk_max;
break;
case AMD_DPM_FORCED_LEVEL_LOW:
yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL);
yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, NULL);
yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL);
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, NULL);
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, NULL);
sclk_max = sclk_min;
fclk_max = fclk_min;
socclk_max = socclk_min;
+ vclk_max = vclk_min;
+ dclk_max = dclk_min;
break;
case AMD_DPM_FORCED_LEVEL_AUTO:
yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max);
yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, &fclk_max);
yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max);
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, &vclk_max);
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, &dclk_max);
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
- /* Temporarily do nothing since the optimal clocks haven't been provided yet */
+ yellow_carp_get_dpm_profile_freq(smu, level, SMU_SCLK, &sclk_min, &sclk_max);
+ yellow_carp_get_dpm_profile_freq(smu, level, SMU_FCLK, &fclk_min, &fclk_max);
+ yellow_carp_get_dpm_profile_freq(smu, level, SMU_SOCCLK, &socclk_min, &socclk_max);
+ yellow_carp_get_dpm_profile_freq(smu, level, SMU_VCLK, &vclk_min, &vclk_max);
+ yellow_carp_get_dpm_profile_freq(smu, level, SMU_DCLK, &dclk_min, &dclk_max);
break;
case AMD_DPM_FORCED_LEVEL_MANUAL:
case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
@@ -1182,6 +1297,24 @@ static int yellow_carp_set_performance_level(struct smu_context *smu,
return ret;
}
+ if (vclk_min && vclk_max) {
+ ret = yellow_carp_set_soft_freq_limited_range(smu,
+ SMU_VCLK,
+ vclk_min,
+ vclk_max);
+ if (ret)
+ return ret;
+ }
+
+ if (dclk_min && dclk_max) {
+ ret = yellow_carp_set_soft_freq_limited_range(smu,
+ SMU_DCLK,
+ dclk_min,
+ dclk_max);
+ if (ret)
+ return ret;
+ }
+
return ret;
}
@@ -1235,5 +1368,6 @@ void yellow_carp_set_ppt_funcs(struct smu_context *smu)
smu->feature_map = yellow_carp_feature_mask_map;
smu->table_map = yellow_carp_table_map;
smu->is_apu = true;
+ smu->smc_driver_if_version = SMU13_YELLOW_CARP_DRIVER_IF_VERSION;
smu_v13_0_set_smu_mailbox_registers(smu);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.h
index a9205a8ea3ad..b3ad8352c68a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.h
@@ -24,6 +24,5 @@
#define __YELLOW_CARP_PPT_H__
extern void yellow_carp_set_ppt_funcs(struct smu_context *smu);
-#define YELLOW_CARP_UMD_PSTATE_GFXCLK 1100
#endif
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 9020bf820bc8..12f5a2c7f03d 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -285,7 +285,7 @@ static int hdlcd_drm_bind(struct device *dev)
*/
if (hdlcd_read(hdlcd, HDLCD_REG_COMMAND)) {
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
- drm_aperture_remove_framebuffers(false, &hdlcd_driver);
+ drm_aperture_remove_framebuffers(&hdlcd_driver);
}
drm_mode_config_reset(drm);
diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
index f5c66d89ba99..5afade25e217 100644
--- a/drivers/gpu/drm/armada/Kconfig
+++ b/drivers/gpu/drm/armada/Kconfig
@@ -3,6 +3,7 @@ config DRM_ARMADA
tristate "DRM support for Marvell Armada SoCs"
depends on DRM && HAVE_CLK && ARM && MMU
select DRM_KMS_HELPER
+ select FB_IO_HELPERS if DRM_FBDEV_EMULATION
help
Support the "LCD" controllers found on the Marvell Armada 510
devices. There are two controllers on the device, each controller
diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile
index 9bc3c3213724..dc75a7db9ed3 100644
--- a/drivers/gpu/drm/armada/Makefile
+++ b/drivers/gpu/drm/armada/Makefile
@@ -1,7 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
-armada-y := armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
+armada-y := armada_crtc.o armada_drv.o armada_fb.o \
armada_gem.o armada_overlay.o armada_plane.o armada_trace.o
armada-y += armada_510.o
armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
+armada-$(CONFIG_DRM_FBDEV_EMULATION) += armada_fbdev.o
obj-$(CONFIG_DRM_ARMADA) := armada.o
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index 6a5a87932576..c303e8c7ff6c 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -16,7 +16,6 @@ struct armada_crtc;
struct armada_gem_object;
struct clk;
struct drm_display_mode;
-struct drm_fb_helper;
static inline void
armada_updatel(uint32_t val, uint32_t mask, void __iomem *ptr)
@@ -55,7 +54,6 @@ extern const struct armada_variant armada510_ops;
struct armada_private {
struct drm_device drm;
- struct drm_fb_helper *fbdev;
struct armada_crtc *dcrtc[2];
struct drm_mm linear; /* protected by linear_lock */
struct mutex linear_lock;
@@ -75,8 +73,12 @@ struct armada_private {
#define drm_to_armada_dev(dev) container_of(dev, struct armada_private, drm)
-int armada_fbdev_init(struct drm_device *);
-void armada_fbdev_fini(struct drm_device *);
+#if defined(CONFIG_DRM_FBDEV_EMULATION)
+void armada_fbdev_setup(struct drm_device *dev);
+#else
+static inline void armada_fbdev_setup(struct drm_device *dev)
+{ }
+#endif
int armada_overlay_plane_create(struct drm_device *, unsigned long);
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 142668cd6d7c..e120144d4b47 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -6,6 +6,7 @@
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
@@ -16,7 +17,6 @@
#include <drm/drm_managed.h>
#include <drm/drm_prime.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_vblank.h>
@@ -37,7 +37,6 @@ static const struct drm_ioctl_desc armada_ioctls[] = {
DEFINE_DRM_GEM_FOPS(armada_drm_fops);
static const struct drm_driver armada_drm_driver = {
- .lastclose = drm_fb_helper_lastclose,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_import = armada_gem_prime_import,
@@ -55,7 +54,6 @@ static const struct drm_driver armada_drm_driver = {
static const struct drm_mode_config_funcs armada_drm_mode_config_funcs = {
.fb_create = armada_fb_create,
- .output_poll_changed = drm_fb_helper_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
@@ -95,7 +93,7 @@ static int armada_drm_bind(struct device *dev)
}
/* Remove early framebuffers */
- ret = drm_aperture_remove_framebuffers(false, &armada_drm_driver);
+ ret = drm_aperture_remove_framebuffers(&armada_drm_driver);
if (ret) {
dev_err(dev, "[" DRM_NAME ":%s] can't kick out simple-fb: %d\n",
__func__, ret);
@@ -131,10 +129,6 @@ static int armada_drm_bind(struct device *dev)
drm_mode_config_reset(&priv->drm);
- ret = armada_fbdev_init(&priv->drm);
- if (ret)
- goto err_comp;
-
drm_kms_helper_poll_init(&priv->drm);
ret = drm_dev_register(&priv->drm, 0);
@@ -145,11 +139,12 @@ static int armada_drm_bind(struct device *dev)
armada_drm_debugfs_init(priv->drm.primary);
#endif
+ armada_fbdev_setup(&priv->drm);
+
return 0;
err_poll:
drm_kms_helper_poll_fini(&priv->drm);
- armada_fbdev_fini(&priv->drm);
err_comp:
component_unbind_all(dev, &priv->drm);
err_kms:
@@ -164,7 +159,6 @@ static void armada_drm_unbind(struct device *dev)
struct armada_private *priv = drm_to_armada_dev(drm);
drm_kms_helper_poll_fini(&priv->drm);
- armada_fbdev_fini(&priv->drm);
drm_dev_unregister(&priv->drm);
diff --git a/drivers/gpu/drm/armada/armada_fb.c b/drivers/gpu/drm/armada/armada_fb.c
index b87c71703c85..cf2e88218dc0 100644
--- a/drivers/gpu/drm/armada/armada_fb.c
+++ b/drivers/gpu/drm/armada/armada_fb.c
@@ -4,7 +4,6 @@
*/
#include <drm/drm_modeset_helper.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_framebuffer_helper.h>
diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
index 0e44f53e9fa4..3943e89cc06c 100644
--- a/drivers/gpu/drm/armada/armada_fbdev.c
+++ b/drivers/gpu/drm/armada/armada_fbdev.c
@@ -5,9 +5,12 @@
*/
#include <linux/errno.h>
+#include <linux/fb.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
@@ -16,14 +19,24 @@
#include "armada_fb.h"
#include "armada_gem.h"
+static void armada_fbdev_fb_destroy(struct fb_info *info)
+{
+ struct drm_fb_helper *fbh = info->par;
+
+ drm_fb_helper_fini(fbh);
+
+ fbh->fb->funcs->destroy(fbh->fb);
+
+ drm_client_release(&fbh->client);
+ drm_fb_helper_unprepare(fbh);
+ kfree(fbh);
+}
+
static const struct fb_ops armada_fb_ops = {
.owner = THIS_MODULE,
+ FB_DEFAULT_IO_OPS,
DRM_FB_HELPER_DEFAULT_OPS,
- .fb_read = drm_fb_helper_cfb_read,
- .fb_write = drm_fb_helper_cfb_write,
- .fb_fillrect = drm_fb_helper_cfb_fillrect,
- .fb_copyarea = drm_fb_helper_cfb_copyarea,
- .fb_imageblit = drm_fb_helper_cfb_imageblit,
+ .fb_destroy = armada_fbdev_fb_destroy,
};
static int armada_fbdev_create(struct drm_fb_helper *fbh,
@@ -117,56 +130,95 @@ static const struct drm_fb_helper_funcs armada_fb_helper_funcs = {
.fb_probe = armada_fb_probe,
};
-int armada_fbdev_init(struct drm_device *dev)
+/*
+ * Fbdev client and struct drm_client_funcs
+ */
+
+static void armada_fbdev_client_unregister(struct drm_client_dev *client)
{
- struct armada_private *priv = drm_to_armada_dev(dev);
- struct drm_fb_helper *fbh;
- int ret;
+ struct drm_fb_helper *fbh = drm_fb_helper_from_client(client);
- fbh = devm_kzalloc(dev->dev, sizeof(*fbh), GFP_KERNEL);
- if (!fbh)
- return -ENOMEM;
+ if (fbh->info) {
+ drm_fb_helper_unregister_info(fbh);
+ } else {
+ drm_client_release(&fbh->client);
+ drm_fb_helper_unprepare(fbh);
+ kfree(fbh);
+ }
+}
- priv->fbdev = fbh;
+static int armada_fbdev_client_restore(struct drm_client_dev *client)
+{
+ drm_fb_helper_lastclose(client->dev);
- drm_fb_helper_prepare(dev, fbh, 32, &armada_fb_helper_funcs);
+ return 0;
+}
+
+static int armada_fbdev_client_hotplug(struct drm_client_dev *client)
+{
+ struct drm_fb_helper *fbh = drm_fb_helper_from_client(client);
+ struct drm_device *dev = client->dev;
+ int ret;
+
+ if (dev->fb_helper)
+ return drm_fb_helper_hotplug_event(dev->fb_helper);
ret = drm_fb_helper_init(dev, fbh);
- if (ret) {
- DRM_ERROR("failed to initialize drm fb helper\n");
- goto err_fb_helper;
- }
+ if (ret)
+ goto err_drm_err;
+
+ if (!drm_drv_uses_atomic_modeset(dev))
+ drm_helper_disable_unused_functions(dev);
ret = drm_fb_helper_initial_config(fbh);
- if (ret) {
- DRM_ERROR("failed to set initial config\n");
- goto err_fb_setup;
- }
+ if (ret)
+ goto err_drm_fb_helper_fini;
return 0;
- err_fb_setup:
+
+err_drm_fb_helper_fini:
drm_fb_helper_fini(fbh);
- err_fb_helper:
- drm_fb_helper_unprepare(fbh);
- priv->fbdev = NULL;
+err_drm_err:
+ drm_err(dev, "armada: Failed to setup fbdev emulation (ret=%d)\n", ret);
return ret;
}
-void armada_fbdev_fini(struct drm_device *dev)
+static const struct drm_client_funcs armada_fbdev_client_funcs = {
+ .owner = THIS_MODULE,
+ .unregister = armada_fbdev_client_unregister,
+ .restore = armada_fbdev_client_restore,
+ .hotplug = armada_fbdev_client_hotplug,
+};
+
+void armada_fbdev_setup(struct drm_device *dev)
{
- struct armada_private *priv = drm_to_armada_dev(dev);
- struct drm_fb_helper *fbh = priv->fbdev;
+ struct drm_fb_helper *fbh;
+ int ret;
- if (fbh) {
- drm_fb_helper_unregister_info(fbh);
+ drm_WARN(dev, !dev->registered, "Device has not been registered.\n");
+ drm_WARN(dev, dev->fb_helper, "fb_helper is already set!\n");
+
+ fbh = kzalloc(sizeof(*fbh), GFP_KERNEL);
+ if (!fbh)
+ return;
+ drm_fb_helper_prepare(dev, fbh, 32, &armada_fb_helper_funcs);
- drm_fb_helper_fini(fbh);
+ ret = drm_client_init(dev, &fbh->client, "fbdev", &armada_fbdev_client_funcs);
+ if (ret) {
+ drm_err(dev, "Failed to register client: %d\n", ret);
+ goto err_drm_client_init;
+ }
- if (fbh->fb)
- fbh->fb->funcs->destroy(fbh->fb);
+ ret = armada_fbdev_client_hotplug(&fbh->client);
+ if (ret)
+ drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
- drm_fb_helper_unprepare(fbh);
+ drm_client_register(&fbh->client);
- priv->fbdev = NULL;
- }
+ return;
+
+err_drm_client_init:
+ drm_fb_helper_unprepare(fbh);
+ kfree(fbh);
+ return;
}
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index f076a09afac0..82c68b042444 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -227,6 +227,7 @@ config DRM_SAMSUNG_DSIM
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL_BRIDGE
+ select GENERIC_PHY_MIPI_DPHY
help
The Samsung MIPI DSIM bridge controller driver.
This MIPI DSIM bridge can be found it on Exynos SoCs and
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index ddceafa7b637..2254457ab5d0 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -1393,7 +1393,7 @@ static struct i2c_driver adv7511_driver = {
.of_match_table = adv7511_of_ids,
},
.id_table = adv7511_i2c_ids,
- .probe_new = adv7511_probe,
+ .probe = adv7511_probe,
.remove = adv7511_remove,
};
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
index 3577c532abb4..72ab2ab77081 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
@@ -815,7 +815,7 @@ static struct i2c_driver anx6345_driver = {
.name = "anx6345",
.of_match_table = of_match_ptr(anx6345_match_table),
},
- .probe_new = anx6345_i2c_probe,
+ .probe = anx6345_i2c_probe,
.remove = anx6345_i2c_remove,
.id_table = anx6345_id,
};
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
index a3a38bbe2786..06a3e3243e19 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
@@ -1389,7 +1389,7 @@ static struct i2c_driver anx78xx_driver = {
.name = "anx7814",
.of_match_table = of_match_ptr(anx78xx_match_table),
},
- .probe_new = anx78xx_i2c_probe,
+ .probe = anx78xx_i2c_probe,
.remove = anx78xx_i2c_remove,
.id_table = anx78xx_id,
};
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 6846199a2ee1..8b985efdc086 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -17,7 +17,6 @@
#include <linux/types.h>
#include <linux/workqueue.h>
-#include <linux/of_gpio.h>
#include <linux/of_graph.h>
#include <linux/of_platform.h>
@@ -1687,6 +1686,14 @@ static int anx7625_parse_dt(struct device *dev,
if (of_property_read_bool(np, "analogix,audio-enable"))
pdata->audio_en = 1;
+ return 0;
+}
+
+static int anx7625_parse_dt_panel(struct device *dev,
+ struct anx7625_platform_data *pdata)
+{
+ struct device_node *np = dev->of_node;
+
pdata->panel_bridge = devm_drm_of_get_bridge(dev, np, 1, 0);
if (IS_ERR(pdata->panel_bridge)) {
if (PTR_ERR(pdata->panel_bridge) == -ENODEV) {
@@ -2032,7 +2039,7 @@ static int anx7625_register_audio(struct device *dev, struct anx7625_data *ctx)
return 0;
}
-static int anx7625_attach_dsi(struct anx7625_data *ctx)
+static int anx7625_setup_dsi_device(struct anx7625_data *ctx)
{
struct mipi_dsi_device *dsi;
struct device *dev = &ctx->client->dev;
@@ -2042,9 +2049,6 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
.channel = 0,
.node = NULL,
};
- int ret;
-
- DRM_DEV_DEBUG_DRIVER(dev, "attach dsi\n");
host = of_find_mipi_dsi_host_by_node(ctx->pdata.mipi_host_node);
if (!host) {
@@ -2065,14 +2069,24 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
MIPI_DSI_MODE_VIDEO_HSE |
MIPI_DSI_HS_PKT_END_ALIGNED;
- ret = devm_mipi_dsi_attach(dev, dsi);
+ ctx->dsi = dsi;
+
+ return 0;
+}
+
+static int anx7625_attach_dsi(struct anx7625_data *ctx)
+{
+ struct device *dev = &ctx->client->dev;
+ int ret;
+
+ DRM_DEV_DEBUG_DRIVER(dev, "attach dsi\n");
+
+ ret = devm_mipi_dsi_attach(dev, ctx->dsi);
if (ret) {
DRM_DEV_ERROR(dev, "fail to attach dsi to host.\n");
return ret;
}
- ctx->dsi = dsi;
-
DRM_DEV_DEBUG_DRIVER(dev, "attach dsi succeeded.\n");
return 0;
@@ -2560,6 +2574,40 @@ static void anx7625_runtime_disable(void *data)
pm_runtime_disable(data);
}
+static int anx7625_link_bridge(struct drm_dp_aux *aux)
+{
+ struct anx7625_data *platform = container_of(aux, struct anx7625_data, aux);
+ struct device *dev = aux->dev;
+ int ret;
+
+ ret = anx7625_parse_dt_panel(dev, &platform->pdata);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "fail to parse DT for panel : %d\n", ret);
+ return ret;
+ }
+
+ platform->bridge.funcs = &anx7625_bridge_funcs;
+ platform->bridge.of_node = dev->of_node;
+ if (!anx7625_of_panel_on_aux_bus(dev))
+ platform->bridge.ops |= DRM_BRIDGE_OP_EDID;
+ if (!platform->pdata.panel_bridge)
+ platform->bridge.ops |= DRM_BRIDGE_OP_HPD |
+ DRM_BRIDGE_OP_DETECT;
+ platform->bridge.type = platform->pdata.panel_bridge ?
+ DRM_MODE_CONNECTOR_eDP :
+ DRM_MODE_CONNECTOR_DisplayPort;
+
+ drm_bridge_add(&platform->bridge);
+
+ if (!platform->pdata.is_dpi) {
+ ret = anx7625_attach_dsi(platform);
+ if (ret)
+ drm_bridge_remove(&platform->bridge);
+ }
+
+ return ret;
+}
+
static int anx7625_i2c_probe(struct i2c_client *client)
{
struct anx7625_data *platform;
@@ -2634,6 +2682,24 @@ static int anx7625_i2c_probe(struct i2c_client *client)
platform->aux.wait_hpd_asserted = anx7625_wait_hpd_asserted;
drm_dp_aux_init(&platform->aux);
+ ret = anx7625_parse_dt(dev, pdata);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ DRM_DEV_ERROR(dev, "fail to parse DT : %d\n", ret);
+ goto free_wq;
+ }
+
+ if (!platform->pdata.is_dpi) {
+ ret = anx7625_setup_dsi_device(platform);
+ if (ret < 0)
+ goto free_wq;
+ }
+
+ /*
+ * Registering the i2c devices will retrigger deferred probe, so it
+ * needs to be done after calls that might return EPROBE_DEFER,
+ * otherwise we can get an infinite loop.
+ */
if (anx7625_register_i2c_dummy_clients(platform, client) != 0) {
ret = -ENOMEM;
DRM_DEV_ERROR(dev, "fail to reserve I2C bus.\n");
@@ -2648,13 +2714,21 @@ static int anx7625_i2c_probe(struct i2c_client *client)
if (ret)
goto free_wq;
- devm_of_dp_aux_populate_ep_devices(&platform->aux);
-
- ret = anx7625_parse_dt(dev, pdata);
+ /*
+ * Populating the aux bus will retrigger deferred probe, so it needs to
+ * be done after calls that might return EPROBE_DEFER, otherwise we can
+ * get an infinite loop.
+ */
+ ret = devm_of_dp_aux_populate_bus(&platform->aux, anx7625_link_bridge);
if (ret) {
- if (ret != -EPROBE_DEFER)
- DRM_DEV_ERROR(dev, "fail to parse DT : %d\n", ret);
- goto free_wq;
+ if (ret != -ENODEV) {
+ DRM_DEV_ERROR(dev, "failed to populate aux bus : %d\n", ret);
+ goto free_wq;
+ }
+
+ ret = anx7625_link_bridge(&platform->aux);
+ if (ret)
+ goto free_wq;
}
if (!platform->pdata.low_power_mode) {
@@ -2667,27 +2741,6 @@ static int anx7625_i2c_probe(struct i2c_client *client)
if (platform->pdata.intp_irq)
queue_work(platform->workqueue, &platform->work);
- platform->bridge.funcs = &anx7625_bridge_funcs;
- platform->bridge.of_node = client->dev.of_node;
- if (!anx7625_of_panel_on_aux_bus(&client->dev))
- platform->bridge.ops |= DRM_BRIDGE_OP_EDID;
- if (!platform->pdata.panel_bridge)
- platform->bridge.ops |= DRM_BRIDGE_OP_HPD |
- DRM_BRIDGE_OP_DETECT;
- platform->bridge.type = platform->pdata.panel_bridge ?
- DRM_MODE_CONNECTOR_eDP :
- DRM_MODE_CONNECTOR_DisplayPort;
-
- drm_bridge_add(&platform->bridge);
-
- if (!platform->pdata.is_dpi) {
- ret = anx7625_attach_dsi(platform);
- if (ret) {
- DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
- goto unregister_bridge;
- }
- }
-
if (platform->pdata.audio_en)
anx7625_register_audio(dev, platform);
@@ -2695,12 +2748,6 @@ static int anx7625_i2c_probe(struct i2c_client *client)
return 0;
-unregister_bridge:
- drm_bridge_remove(&platform->bridge);
-
- if (!platform->pdata.low_power_mode)
- pm_runtime_put_sync_suspend(&client->dev);
-
free_wq:
if (platform->workqueue)
destroy_workqueue(platform->workqueue);
@@ -2753,7 +2800,7 @@ static struct i2c_driver anx7625_driver = {
.of_match_table = anx_match_table,
.pm = &anx7625_pm_ops,
},
- .probe_new = anx7625_i2c_probe,
+ .probe = anx7625_i2c_probe,
.remove = anx7625_i2c_remove,
.id_table = anx7625_id,
diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c
index 0e37840cd7a8..8bfce21d6b90 100644
--- a/drivers/gpu/drm/bridge/chipone-icn6211.c
+++ b/drivers/gpu/drm/bridge/chipone-icn6211.c
@@ -795,7 +795,7 @@ static struct i2c_device_id chipone_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, chipone_i2c_id);
static struct i2c_driver chipone_i2c_driver = {
- .probe_new = chipone_i2c_probe,
+ .probe = chipone_i2c_probe,
.id_table = chipone_i2c_id,
.driver = {
.name = "chipone-icn6211-i2c",
diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c b/drivers/gpu/drm/bridge/chrontel-ch7033.c
index 339b759e4c81..a854eb84e399 100644
--- a/drivers/gpu/drm/bridge/chrontel-ch7033.c
+++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c
@@ -603,7 +603,7 @@ static const struct i2c_device_id ch7033_ids[] = {
MODULE_DEVICE_TABLE(i2c, ch7033_ids);
static struct i2c_driver ch7033_driver = {
- .probe_new = ch7033_probe,
+ .probe = ch7033_probe,
.remove = ch7033_remove,
.driver = {
.name = "ch7033",
diff --git a/drivers/gpu/drm/bridge/cros-ec-anx7688.c b/drivers/gpu/drm/bridge/cros-ec-anx7688.c
index fa91bdeddef0..c8abd9920fee 100644
--- a/drivers/gpu/drm/bridge/cros-ec-anx7688.c
+++ b/drivers/gpu/drm/bridge/cros-ec-anx7688.c
@@ -173,7 +173,7 @@ static const struct of_device_id cros_ec_anx7688_bridge_match_table[] = {
MODULE_DEVICE_TABLE(of, cros_ec_anx7688_bridge_match_table);
static struct i2c_driver cros_ec_anx7688_bridge_driver = {
- .probe_new = cros_ec_anx7688_bridge_probe,
+ .probe = cros_ec_anx7688_bridge_probe,
.remove = cros_ec_anx7688_bridge_remove,
.driver = {
.name = "cros-ec-anx7688-bridge",
diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c
index 56ae511367b1..f7f436cf96e0 100644
--- a/drivers/gpu/drm/bridge/display-connector.c
+++ b/drivers/gpu/drm/bridge/display-connector.c
@@ -24,7 +24,7 @@ struct display_connector {
struct gpio_desc *hpd_gpio;
int hpd_irq;
- struct regulator *dp_pwr;
+ struct regulator *supply;
struct gpio_desc *ddc_en;
};
@@ -191,6 +191,18 @@ static irqreturn_t display_connector_hpd_irq(int irq, void *arg)
return IRQ_HANDLED;
}
+static int display_connector_get_supply(struct platform_device *pdev,
+ struct display_connector *conn,
+ const char *name)
+{
+ conn->supply = devm_regulator_get_optional(&pdev->dev, name);
+
+ if (conn->supply == ERR_PTR(-ENODEV))
+ conn->supply = NULL;
+
+ return PTR_ERR_OR_ZERO(conn->supply);
+}
+
static int display_connector_probe(struct platform_device *pdev)
{
struct display_connector *conn;
@@ -316,36 +328,15 @@ static int display_connector_probe(struct platform_device *pdev)
if (type == DRM_MODE_CONNECTOR_DisplayPort) {
int ret;
- conn->dp_pwr = devm_regulator_get_optional(&pdev->dev, "dp-pwr");
-
- if (IS_ERR(conn->dp_pwr)) {
- ret = PTR_ERR(conn->dp_pwr);
-
- switch (ret) {
- case -ENODEV:
- conn->dp_pwr = NULL;
- break;
-
- case -EPROBE_DEFER:
- return -EPROBE_DEFER;
-
- default:
- dev_err(&pdev->dev, "failed to get DP PWR regulator: %d\n", ret);
- return ret;
- }
- }
-
- if (conn->dp_pwr) {
- ret = regulator_enable(conn->dp_pwr);
- if (ret) {
- dev_err(&pdev->dev, "failed to enable DP PWR regulator: %d\n", ret);
- return ret;
- }
- }
+ ret = display_connector_get_supply(pdev, conn, "dp-pwr");
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret, "failed to get DP PWR regulator\n");
}
/* enable DDC */
if (type == DRM_MODE_CONNECTOR_HDMIA) {
+ int ret;
+
conn->ddc_en = devm_gpiod_get_optional(&pdev->dev, "ddc-en",
GPIOD_OUT_HIGH);
@@ -353,6 +344,18 @@ static int display_connector_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Couldn't get ddc-en gpio\n");
return PTR_ERR(conn->ddc_en);
}
+
+ ret = display_connector_get_supply(pdev, conn, "hdmi-pwr");
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret, "failed to get HDMI +5V Power regulator\n");
+ }
+
+ if (conn->supply) {
+ ret = regulator_enable(conn->supply);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable PWR regulator: %d\n", ret);
+ return ret;
+ }
}
conn->bridge.funcs = &display_connector_bridge_funcs;
@@ -386,8 +389,8 @@ static void display_connector_remove(struct platform_device *pdev)
if (conn->ddc_en)
gpiod_set_value(conn->ddc_en, 0);
- if (conn->dp_pwr)
- regulator_disable(conn->dp_pwr);
+ if (conn->supply)
+ regulator_disable(conn->supply);
drm_bridge_remove(&conn->bridge);
diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c
index 682623369498..b8e52156b07a 100644
--- a/drivers/gpu/drm/bridge/fsl-ldb.c
+++ b/drivers/gpu/drm/bridge/fsl-ldb.c
@@ -56,6 +56,7 @@
#define LVDS_CTRL_VBG_ADJ_MASK GENMASK(19, 17)
enum fsl_ldb_devtype {
+ IMX6SX_LDB,
IMX8MP_LDB,
IMX93_LDB,
};
@@ -64,9 +65,14 @@ struct fsl_ldb_devdata {
u32 ldb_ctrl;
u32 lvds_ctrl;
bool lvds_en_bit;
+ bool single_ctrl_reg;
};
static const struct fsl_ldb_devdata fsl_ldb_devdata[] = {
+ [IMX6SX_LDB] = {
+ .ldb_ctrl = 0x18,
+ .single_ctrl_reg = true,
+ },
[IMX8MP_LDB] = {
.ldb_ctrl = 0x5c,
.lvds_ctrl = 0x128,
@@ -201,6 +207,9 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge,
regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->ldb_ctrl, reg);
+ if (fsl_ldb->devdata->single_ctrl_reg)
+ return;
+
/* Program LVDS_CTRL */
reg = LVDS_CTRL_CC_ADJ(2) | LVDS_CTRL_PRE_EMPH_EN |
LVDS_CTRL_PRE_EMPH_ADJ(3) | LVDS_CTRL_VBG_EN;
@@ -226,7 +235,8 @@ static void fsl_ldb_atomic_disable(struct drm_bridge *bridge,
regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl,
LVDS_CTRL_LVDS_EN);
else
- regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl, 0);
+ if (!fsl_ldb->devdata->single_ctrl_reg)
+ regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl, 0);
regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->ldb_ctrl, 0);
clk_disable_unprepare(fsl_ldb->clk);
@@ -372,6 +382,8 @@ static void fsl_ldb_remove(struct platform_device *pdev)
}
static const struct of_device_id fsl_ldb_match[] = {
+ { .compatible = "fsl,imx6sx-ldb",
+ .data = &fsl_ldb_devdata[IMX6SX_LDB], },
{ .compatible = "fsl,imx8mp-ldb",
.data = &fsl_ldb_devdata[IMX8MP_LDB], },
{ .compatible = "fsl,imx93-ldb",
diff --git a/drivers/gpu/drm/bridge/imx/Kconfig b/drivers/gpu/drm/bridge/imx/Kconfig
index 608f47f41bcd..9fae28db6aa7 100644
--- a/drivers/gpu/drm/bridge/imx/Kconfig
+++ b/drivers/gpu/drm/bridge/imx/Kconfig
@@ -1,9 +1,13 @@
if ARCH_MXC || COMPILE_TEST
+config DRM_IMX_LDB_HELPER
+ tristate
+
config DRM_IMX8QM_LDB
tristate "Freescale i.MX8QM LVDS display bridge"
depends on OF
depends on COMMON_CLK
+ select DRM_IMX_LDB_HELPER
select DRM_KMS_HELPER
help
Choose this to enable the internal LVDS Display Bridge(LDB) found in
@@ -13,6 +17,7 @@ config DRM_IMX8QXP_LDB
tristate "Freescale i.MX8QXP LVDS display bridge"
depends on OF
depends on COMMON_CLK
+ select DRM_IMX_LDB_HELPER
select DRM_KMS_HELPER
help
Choose this to enable the internal LVDS Display Bridge(LDB) found in
diff --git a/drivers/gpu/drm/bridge/imx/Makefile b/drivers/gpu/drm/bridge/imx/Makefile
index aa90ec8d5433..8e2ebf3399a1 100644
--- a/drivers/gpu/drm/bridge/imx/Makefile
+++ b/drivers/gpu/drm/bridge/imx/Makefile
@@ -1,9 +1,6 @@
-imx8qm-ldb-objs := imx-ldb-helper.o imx8qm-ldb-drv.o
+obj-$(CONFIG_DRM_IMX_LDB_HELPER) += imx-ldb-helper.o
obj-$(CONFIG_DRM_IMX8QM_LDB) += imx8qm-ldb.o
-
-imx8qxp-ldb-objs := imx-ldb-helper.o imx8qxp-ldb-drv.o
obj-$(CONFIG_DRM_IMX8QXP_LDB) += imx8qxp-ldb.o
-
obj-$(CONFIG_DRM_IMX8QXP_PIXEL_COMBINER) += imx8qxp-pixel-combiner.o
obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK) += imx8qxp-pixel-link.o
obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI) += imx8qxp-pxl2dpi.o
diff --git a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c
index 7338b84bc83d..6967325cd8ee 100644
--- a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c
+++ b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c
@@ -4,8 +4,10 @@
* Copyright 2019,2020,2022 NXP
*/
+#include <linux/export.h>
#include <linux/media-bus-format.h>
#include <linux/mfd/syscon.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
@@ -19,12 +21,14 @@ bool ldb_channel_is_single_link(struct ldb_channel *ldb_ch)
{
return ldb_ch->link_type == LDB_CH_SINGLE_LINK;
}
+EXPORT_SYMBOL_GPL(ldb_channel_is_single_link);
bool ldb_channel_is_split_link(struct ldb_channel *ldb_ch)
{
return ldb_ch->link_type == LDB_CH_DUAL_LINK_EVEN_ODD_PIXELS ||
ldb_ch->link_type == LDB_CH_DUAL_LINK_ODD_EVEN_PIXELS;
}
+EXPORT_SYMBOL_GPL(ldb_channel_is_split_link);
int ldb_bridge_atomic_check_helper(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
@@ -38,6 +42,7 @@ int ldb_bridge_atomic_check_helper(struct drm_bridge *bridge,
return 0;
}
+EXPORT_SYMBOL_GPL(ldb_bridge_atomic_check_helper);
void ldb_bridge_mode_set_helper(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
@@ -69,6 +74,7 @@ void ldb_bridge_mode_set_helper(struct drm_bridge *bridge,
break;
}
}
+EXPORT_SYMBOL_GPL(ldb_bridge_mode_set_helper);
void ldb_bridge_enable_helper(struct drm_bridge *bridge)
{
@@ -81,6 +87,7 @@ void ldb_bridge_enable_helper(struct drm_bridge *bridge)
*/
regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ldb_ctrl);
}
+EXPORT_SYMBOL_GPL(ldb_bridge_enable_helper);
void ldb_bridge_disable_helper(struct drm_bridge *bridge)
{
@@ -95,6 +102,7 @@ void ldb_bridge_disable_helper(struct drm_bridge *bridge)
regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ldb_ctrl);
}
+EXPORT_SYMBOL_GPL(ldb_bridge_disable_helper);
int ldb_bridge_attach_helper(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
@@ -117,6 +125,7 @@ int ldb_bridge_attach_helper(struct drm_bridge *bridge,
ldb_ch->next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
}
+EXPORT_SYMBOL_GPL(ldb_bridge_attach_helper);
int ldb_init_helper(struct ldb *ldb)
{
@@ -157,6 +166,7 @@ int ldb_init_helper(struct ldb *ldb)
return 0;
}
+EXPORT_SYMBOL_GPL(ldb_init_helper);
int ldb_find_next_bridge_helper(struct ldb *ldb)
{
@@ -184,6 +194,7 @@ int ldb_find_next_bridge_helper(struct ldb *ldb)
return 0;
}
+EXPORT_SYMBOL_GPL(ldb_find_next_bridge_helper);
void ldb_add_bridge_helper(struct ldb *ldb,
const struct drm_bridge_funcs *bridge_funcs)
@@ -204,6 +215,7 @@ void ldb_add_bridge_helper(struct ldb *ldb,
drm_bridge_add(&ldb_ch->bridge);
}
}
+EXPORT_SYMBOL_GPL(ldb_add_bridge_helper);
void ldb_remove_bridge_helper(struct ldb *ldb)
{
@@ -219,3 +231,8 @@ void ldb_remove_bridge_helper(struct ldb *ldb)
drm_bridge_remove(&ldb_ch->bridge);
}
}
+EXPORT_SYMBOL_GPL(ldb_remove_bridge_helper);
+
+MODULE_DESCRIPTION("i.MX8 LVDS Display Bridge(LDB)/Pixel Mapper bridge helper");
+MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/bridge/imx/imx8qm-ldb-drv.c b/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c
index 386032a02599..386032a02599 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qm-ldb-drv.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c
diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb-drv.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
index c806576b1e22..c806576b1e22 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb-drv.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
index abaf6e23775e..504d51c42f79 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -3207,7 +3207,7 @@ static ssize_t receive_timing_debugfs_show(struct file *file, char __user *buf,
size_t len, loff_t *ppos)
{
struct it6505 *it6505 = file->private_data;
- struct drm_display_mode *vid = &it6505->video_info;
+ struct drm_display_mode *vid;
u8 read_buf[READ_BUFFER_SIZE];
u8 *str = read_buf, *end = read_buf + READ_BUFFER_SIZE;
ssize_t ret, count;
@@ -3216,6 +3216,7 @@ static ssize_t receive_timing_debugfs_show(struct file *file, char __user *buf,
return -ENODEV;
it6505_calc_video_info(it6505);
+ vid = &it6505->video_info;
str += scnprintf(str, end - str, "---video timing---\n");
str += scnprintf(str, end - str, "PCLK:%d.%03dMHz\n",
vid->clock / 1000, vid->clock % 1000);
@@ -3478,7 +3479,7 @@ static struct i2c_driver it6505_i2c_driver = {
.of_match_table = it6505_of_match,
.pm = &it6505_bridge_pm_ops,
},
- .probe_new = it6505_i2c_probe,
+ .probe = it6505_i2c_probe,
.remove = it6505_i2c_remove,
.shutdown = it6505_shutdown,
.id_table = it6505_id,
diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c
index a2d723d6a4be..466641c77fe9 100644
--- a/drivers/gpu/drm/bridge/ite-it66121.c
+++ b/drivers/gpu/drm/bridge/ite-it66121.c
@@ -1640,7 +1640,7 @@ static struct i2c_driver it66121_driver = {
.name = "it66121",
.of_match_table = it66121_dt_match,
},
- .probe_new = it66121_probe,
+ .probe = it66121_probe,
.remove = it66121_remove,
.id_table = it66121_id,
};
diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
index 13c131ade268..4eaea67fb71c 100644
--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
+++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
@@ -773,7 +773,7 @@ static struct i2c_driver lt8912_i2c_driver = {
.name = "lt8912",
.of_match_table = lt8912_dt_match,
},
- .probe_new = lt8912_probe,
+ .probe = lt8912_probe,
.remove = lt8912_remove,
.id_table = lt8912_id,
};
diff --git a/drivers/gpu/drm/bridge/lontium-lt9211.c b/drivers/gpu/drm/bridge/lontium-lt9211.c
index 3e19fff6547a..aa8d47e7f40d 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9211.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9211.c
@@ -709,7 +709,9 @@ static int lt9211_host_attach(struct lt9211 *ctx)
dsi->lanes = dsi_lanes;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
- MIPI_DSI_MODE_VIDEO_HSE;
+ MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO_NO_HSA |
+ MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP |
+ MIPI_DSI_MODE_NO_EOT_PACKET;
ret = devm_mipi_dsi_attach(dev, dsi);
if (ret < 0) {
@@ -785,7 +787,7 @@ static const struct of_device_id lt9211_match_table[] = {
MODULE_DEVICE_TABLE(of, lt9211_match_table);
static struct i2c_driver lt9211_driver = {
- .probe_new = lt9211_probe,
+ .probe = lt9211_probe,
.remove = lt9211_remove,
.id_table = lt9211_id,
.driver = {
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c
index a25d21a7d5c1..5163e5224aad 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
@@ -774,7 +774,9 @@ static struct mipi_dsi_device *lt9611_attach_dsi(struct lt9611 *lt9611,
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
- MIPI_DSI_MODE_VIDEO_HSE;
+ MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO_NO_HSA |
+ MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP |
+ MIPI_DSI_MODE_NO_EOT_PACKET;
ret = devm_mipi_dsi_attach(dev, dsi);
if (ret < 0) {
@@ -1190,7 +1192,7 @@ static struct i2c_driver lt9611_driver = {
.name = "lt9611",
.of_match_table = lt9611_match_table,
},
- .probe_new = lt9611_probe,
+ .probe = lt9611_probe,
.remove = lt9611_remove,
.id_table = lt9611_id,
};
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
index 583daacf3705..2a57e804ea02 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
@@ -1011,7 +1011,7 @@ static struct i2c_driver lt9611uxc_driver = {
.of_match_table = lt9611uxc_match_table,
.dev_groups = lt9611uxc_attr_groups,
},
- .probe_new = lt9611uxc_probe,
+ .probe = lt9611uxc_probe,
.remove = lt9611uxc_remove,
.id_table = lt9611uxc_id,
};
diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
index 4fc494d9084b..460db3c8a08c 100644
--- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
+++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
@@ -375,7 +375,7 @@ MODULE_DEVICE_TABLE(of, stdp4028_ge_b850v3_fw_match);
static struct i2c_driver stdp4028_ge_b850v3_fw_driver = {
.id_table = stdp4028_ge_b850v3_fw_i2c_table,
- .probe_new = stdp4028_ge_b850v3_fw_probe,
+ .probe = stdp4028_ge_b850v3_fw_probe,
.remove = stdp4028_ge_b850v3_fw_remove,
.driver = {
.name = "stdp4028-ge-b850v3-fw",
@@ -422,7 +422,7 @@ MODULE_DEVICE_TABLE(of, stdp2690_ge_b850v3_fw_match);
static struct i2c_driver stdp2690_ge_b850v3_fw_driver = {
.id_table = stdp2690_ge_b850v3_fw_i2c_table,
- .probe_new = stdp2690_ge_b850v3_fw_probe,
+ .probe = stdp2690_ge_b850v3_fw_probe,
.remove = stdp2690_ge_b850v3_fw_remove,
.driver = {
.name = "stdp2690-ge-b850v3-fw",
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index cd292a2f894c..d81920227a8a 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -335,7 +335,7 @@ MODULE_DEVICE_TABLE(of, ptn3460_match);
static struct i2c_driver ptn3460_driver = {
.id_table = ptn3460_i2c_table,
- .probe_new = ptn3460_probe,
+ .probe = ptn3460_probe,
.remove = ptn3460_remove,
.driver = {
.name = "nxp,ptn3460",
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index efa80e309b98..c9b6cb7678e3 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -538,7 +538,7 @@ MODULE_DEVICE_TABLE(i2c, ps8622_i2c_table);
static struct i2c_driver ps8622_driver = {
.id_table = ps8622_i2c_table,
- .probe_new = ps8622_probe,
+ .probe = ps8622_probe,
.remove = ps8622_remove,
.driver = {
.name = "ps8622",
diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c
index c3eb45179405..8801cdd033b5 100644
--- a/drivers/gpu/drm/bridge/parade-ps8640.c
+++ b/drivers/gpu/drm/bridge/parade-ps8640.c
@@ -791,7 +791,7 @@ static const struct of_device_id ps8640_match[] = {
MODULE_DEVICE_TABLE(of, ps8640_match);
static struct i2c_driver ps8640_driver = {
- .probe_new = ps8640_probe,
+ .probe = ps8640_probe,
.remove = ps8640_remove,
.driver = {
.name = "ps8640",
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index e0a402a85787..043b8109e64a 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -183,6 +183,8 @@
#define DSIM_AFC_CTL(x) (((x) & 0x7) << 5)
/* DSIM_PLLCTRL */
+#define DSIM_PLL_DPDNSWAP_CLK (1 << 25)
+#define DSIM_PLL_DPDNSWAP_DAT (1 << 24)
#define DSIM_FREQ_BAND(x) ((x) << 24)
#define DSIM_PLL_EN BIT(23)
#define DSIM_PLL_P(x, offset) ((x) << (offset))
@@ -218,6 +220,8 @@
#define OLD_SCLK_MIPI_CLK_NAME "pll_clk"
+#define PS_TO_CYCLE(ps, hz) DIV64_U64_ROUND_CLOSEST(((ps) * (hz)), 1000000000000ULL)
+
static const char *const clk_names[5] = {
"bus_clk",
"sclk_mipi",
@@ -405,6 +409,9 @@ static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
.num_bits_resol = 11,
.pll_p_offset = 13,
.reg_values = reg_values,
+ .m_min = 41,
+ .m_max = 125,
+ .min_freq = 500,
};
static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
@@ -418,6 +425,9 @@ static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
.num_bits_resol = 11,
.pll_p_offset = 13,
.reg_values = reg_values,
+ .m_min = 41,
+ .m_max = 125,
+ .min_freq = 500,
};
static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
@@ -429,6 +439,9 @@ static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
.num_bits_resol = 11,
.pll_p_offset = 13,
.reg_values = reg_values,
+ .m_min = 41,
+ .m_max = 125,
+ .min_freq = 500,
};
static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
@@ -441,6 +454,9 @@ static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
.num_bits_resol = 12,
.pll_p_offset = 13,
.reg_values = exynos5433_reg_values,
+ .m_min = 41,
+ .m_max = 125,
+ .min_freq = 500,
};
static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
@@ -453,6 +469,9 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
.num_bits_resol = 12,
.pll_p_offset = 13,
.reg_values = exynos5422_reg_values,
+ .m_min = 41,
+ .m_max = 125,
+ .min_freq = 500,
};
static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = {
@@ -469,6 +488,9 @@ static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = {
*/
.pll_p_offset = 14,
.reg_values = imx8mm_dsim_reg_values,
+ .m_min = 64,
+ .m_max = 1023,
+ .min_freq = 1050,
};
static const struct samsung_dsim_driver_data *
@@ -547,12 +569,12 @@ static unsigned long samsung_dsim_pll_find_pms(struct samsung_dsim *dsi,
tmp = (u64)fout * (_p << _s);
do_div(tmp, fin);
_m = tmp;
- if (_m < 41 || _m > 125)
+ if (_m < driver_data->m_min || _m > driver_data->m_max)
continue;
tmp = (u64)_m * fin;
do_div(tmp, _p);
- if (tmp < 500 * MHZ ||
+ if (tmp < driver_data->min_freq * MHZ ||
tmp > driver_data->max_freq * MHZ)
continue;
@@ -622,6 +644,11 @@ static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi,
reg |= DSIM_FREQ_BAND(band);
}
+ if (dsi->swap_dn_dp_clk)
+ reg |= DSIM_PLL_DPDNSWAP_CLK;
+ if (dsi->swap_dn_dp_data)
+ reg |= DSIM_PLL_DPDNSWAP_DAT;
+
samsung_dsim_write(dsi, DSIM_PLLCTRL_REG, reg);
timeout = 1000;
@@ -633,16 +660,28 @@ static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi,
reg = samsung_dsim_read(dsi, DSIM_STATUS_REG);
} while ((reg & DSIM_PLL_STABLE) == 0);
+ dsi->hs_clock = fout;
+
return fout;
}
static int samsung_dsim_enable_clock(struct samsung_dsim *dsi)
{
- unsigned long hs_clk, byte_clk, esc_clk;
+ unsigned long hs_clk, byte_clk, esc_clk, pix_clk;
unsigned long esc_div;
u32 reg;
+ struct drm_display_mode *m = &dsi->mode;
+ int bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+
+ /* m->clock is in KHz */
+ pix_clk = m->clock * 1000;
+
+ /* Use burst_clk_rate if available, otherwise use the pix_clk */
+ if (dsi->burst_clk_rate)
+ hs_clk = samsung_dsim_set_pll(dsi, dsi->burst_clk_rate);
+ else
+ hs_clk = samsung_dsim_set_pll(dsi, DIV_ROUND_UP(pix_clk * bpp, dsi->lanes));
- hs_clk = samsung_dsim_set_pll(dsi, dsi->burst_clk_rate);
if (!hs_clk) {
dev_err(dsi->dev, "failed to configure DSI PLL\n");
return -EFAULT;
@@ -680,13 +719,47 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
const unsigned int *reg_values = driver_data->reg_values;
u32 reg;
+ struct phy_configure_opts_mipi_dphy cfg;
+ int clk_prepare, lpx, clk_zero, clk_post, clk_trail;
+ int hs_exit, hs_prepare, hs_zero, hs_trail;
+ unsigned long long byte_clock = dsi->hs_clock / 8;
if (driver_data->has_freqband)
return;
+ phy_mipi_dphy_get_default_config_for_hsclk(dsi->hs_clock,
+ dsi->lanes, &cfg);
+
+ /*
+ * TODO:
+ * The tech Applications Processor manuals for i.MX8M Mini, Nano,
+ * and Plus don't state what the definition of the PHYTIMING
+ * bits are beyond their address and bit position.
+ * After reviewing NXP's downstream code, it appears
+ * that the various PHYTIMING registers take the number
+ * of cycles and use various dividers on them. This
+ * calculation does not result in an exact match to the
+ * downstream code, but it is very close to the values
+ * generated by their lookup table, and it appears
+ * to sync at a variety of resolutions. If someone
+ * can get a more accurate mathematical equation needed
+ * for these registers, this should be updated.
+ */
+
+ lpx = PS_TO_CYCLE(cfg.lpx, byte_clock);
+ hs_exit = PS_TO_CYCLE(cfg.hs_exit, byte_clock);
+ clk_prepare = PS_TO_CYCLE(cfg.clk_prepare, byte_clock);
+ clk_zero = PS_TO_CYCLE(cfg.clk_zero, byte_clock);
+ clk_post = PS_TO_CYCLE(cfg.clk_post, byte_clock);
+ clk_trail = PS_TO_CYCLE(cfg.clk_trail, byte_clock);
+ hs_prepare = PS_TO_CYCLE(cfg.hs_prepare, byte_clock);
+ hs_zero = PS_TO_CYCLE(cfg.hs_zero, byte_clock);
+ hs_trail = PS_TO_CYCLE(cfg.hs_trail, byte_clock);
+
/* B D-PHY: D-PHY Master & Slave Analog Block control */
reg = reg_values[PHYCTRL_ULPS_EXIT] | reg_values[PHYCTRL_VREG_LP] |
reg_values[PHYCTRL_SLEW_UP];
+
samsung_dsim_write(dsi, DSIM_PHYCTRL_REG, reg);
/*
@@ -694,7 +767,9 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
* T HS-EXIT: Time that the transmitter drives LP-11 following a HS
* burst
*/
- reg = reg_values[PHYTIMING_LPX] | reg_values[PHYTIMING_HS_EXIT];
+
+ reg = DSIM_PHYTIMING_LPX(lpx) | DSIM_PHYTIMING_HS_EXIT(hs_exit);
+
samsung_dsim_write(dsi, DSIM_PHYTIMING_REG, reg);
/*
@@ -710,10 +785,11 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
* T CLK-TRAIL: Time that the transmitter drives the HS-0 state after
* the last payload clock bit of a HS transmission burst
*/
- reg = reg_values[PHYTIMING_CLK_PREPARE] |
- reg_values[PHYTIMING_CLK_ZERO] |
- reg_values[PHYTIMING_CLK_POST] |
- reg_values[PHYTIMING_CLK_TRAIL];
+
+ reg = DSIM_PHYTIMING1_CLK_PREPARE(clk_prepare) |
+ DSIM_PHYTIMING1_CLK_ZERO(clk_zero) |
+ DSIM_PHYTIMING1_CLK_POST(clk_post) |
+ DSIM_PHYTIMING1_CLK_TRAIL(clk_trail);
samsung_dsim_write(dsi, DSIM_PHYTIMING1_REG, reg);
@@ -726,8 +802,11 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
* T HS-TRAIL: Time that the transmitter drives the flipped differential
* state after last payload data bit of a HS transmission burst
*/
- reg = reg_values[PHYTIMING_HS_PREPARE] | reg_values[PHYTIMING_HS_ZERO] |
- reg_values[PHYTIMING_HS_TRAIL];
+
+ reg = DSIM_PHYTIMING2_HS_PREPARE(hs_prepare) |
+ DSIM_PHYTIMING2_HS_ZERO(hs_zero) |
+ DSIM_PHYTIMING2_HS_TRAIL(hs_trail);
+
samsung_dsim_write(dsi, DSIM_PHYTIMING2_REG, reg);
}
@@ -859,6 +938,10 @@ static int samsung_dsim_init_link(struct samsung_dsim *dsi)
reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
reg &= ~DSIM_STOP_STATE_CNT_MASK;
reg |= DSIM_STOP_STATE_CNT(driver_data->reg_values[STOP_STATE_CNT]);
+
+ if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type))
+ reg |= DSIM_FORCE_STOP_STATE;
+
samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg);
reg = DSIM_BTA_TIMEOUT(0xff) | DSIM_LPDR_TIMEOUT(0xffff);
@@ -874,17 +957,29 @@ static void samsung_dsim_set_display_mode(struct samsung_dsim *dsi)
u32 reg;
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
+ int byte_clk_khz = dsi->hs_clock / 1000 / 8;
+ int hfp = (m->hsync_start - m->hdisplay) * byte_clk_khz / m->clock;
+ int hbp = (m->htotal - m->hsync_end) * byte_clk_khz / m->clock;
+ int hsa = (m->hsync_end - m->hsync_start) * byte_clk_khz / m->clock;
+
+ /* remove packet overhead when possible */
+ hfp = max(hfp - 6, 0);
+ hbp = max(hbp - 6, 0);
+ hsa = max(hsa - 6, 0);
+
+ dev_dbg(dsi->dev, "calculated hfp: %u, hbp: %u, hsa: %u",
+ hfp, hbp, hsa);
+
reg = DSIM_CMD_ALLOW(0xf)
| DSIM_STABLE_VFP(m->vsync_start - m->vdisplay)
| DSIM_MAIN_VBP(m->vtotal - m->vsync_end);
samsung_dsim_write(dsi, DSIM_MVPORCH_REG, reg);
- reg = DSIM_MAIN_HFP(m->hsync_start - m->hdisplay)
- | DSIM_MAIN_HBP(m->htotal - m->hsync_end);
+ reg = DSIM_MAIN_HFP(hfp) | DSIM_MAIN_HBP(hbp);
samsung_dsim_write(dsi, DSIM_MHPORCH_REG, reg);
reg = DSIM_MAIN_VSA(m->vsync_end - m->vsync_start)
- | DSIM_MAIN_HSA(m->hsync_end - m->hsync_start);
+ | DSIM_MAIN_HSA(hsa);
samsung_dsim_write(dsi, DSIM_MSYNC_REG, reg);
}
reg = DSIM_MAIN_HRESOL(m->hdisplay, num_bits_resol) |
@@ -1340,6 +1435,9 @@ static void samsung_dsim_atomic_pre_enable(struct drm_bridge *bridge,
ret = samsung_dsim_init(dsi);
if (ret)
return;
+
+ samsung_dsim_set_display_mode(dsi);
+ samsung_dsim_set_display_enable(dsi, true);
}
}
@@ -1347,9 +1445,16 @@ static void samsung_dsim_atomic_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
{
struct samsung_dsim *dsi = bridge_to_dsi(bridge);
+ u32 reg;
- samsung_dsim_set_display_mode(dsi);
- samsung_dsim_set_display_enable(dsi, true);
+ if (samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type)) {
+ samsung_dsim_set_display_mode(dsi);
+ samsung_dsim_set_display_enable(dsi, true);
+ } else {
+ reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
+ reg &= ~DSIM_FORCE_STOP_STATE;
+ samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg);
+ }
dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
}
@@ -1358,10 +1463,17 @@ static void samsung_dsim_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
{
struct samsung_dsim *dsi = bridge_to_dsi(bridge);
+ u32 reg;
if (!(dsi->state & DSIM_STATE_ENABLED))
return;
+ if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type)) {
+ reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
+ reg |= DSIM_FORCE_STOP_STATE;
+ samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg);
+ }
+
dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
}
@@ -1682,11 +1794,11 @@ static const struct mipi_dsi_host_ops samsung_dsim_ops = {
};
static int samsung_dsim_of_read_u32(const struct device_node *np,
- const char *propname, u32 *out_value)
+ const char *propname, u32 *out_value, bool optional)
{
int ret = of_property_read_u32(np, propname, out_value);
- if (ret < 0)
+ if (ret < 0 && !optional)
pr_err("%pOF: failed to get '%s' property\n", np, propname);
return ret;
@@ -1696,23 +1808,52 @@ static int samsung_dsim_parse_dt(struct samsung_dsim *dsi)
{
struct device *dev = dsi->dev;
struct device_node *node = dev->of_node;
- int ret;
+ u32 lane_polarities[5] = { 0 };
+ struct device_node *endpoint;
+ int i, nr_lanes, ret;
+ struct clk *pll_clk;
ret = samsung_dsim_of_read_u32(node, "samsung,pll-clock-frequency",
- &dsi->pll_clk_rate);
- if (ret < 0)
- return ret;
+ &dsi->pll_clk_rate, 1);
+ /* If it doesn't exist, read it from the clock instead of failing */
+ if (ret < 0) {
+ dev_dbg(dev, "Using sclk_mipi for pll clock frequency\n");
+ pll_clk = devm_clk_get(dev, "sclk_mipi");
+ if (!IS_ERR(pll_clk))
+ dsi->pll_clk_rate = clk_get_rate(pll_clk);
+ else
+ return PTR_ERR(pll_clk);
+ }
+ /* If it doesn't exist, use pixel clock instead of failing */
ret = samsung_dsim_of_read_u32(node, "samsung,burst-clock-frequency",
- &dsi->burst_clk_rate);
- if (ret < 0)
- return ret;
+ &dsi->burst_clk_rate, 1);
+ if (ret < 0) {
+ dev_dbg(dev, "Using pixel clock for HS clock frequency\n");
+ dsi->burst_clk_rate = 0;
+ }
ret = samsung_dsim_of_read_u32(node, "samsung,esc-clock-frequency",
- &dsi->esc_clk_rate);
+ &dsi->esc_clk_rate, 0);
if (ret < 0)
return ret;
+ endpoint = of_graph_get_endpoint_by_regs(node, 1, -1);
+ nr_lanes = of_property_count_u32_elems(endpoint, "data-lanes");
+ if (nr_lanes > 0 && nr_lanes <= 4) {
+ /* Polarity 0 is clock lane, 1..4 are data lanes. */
+ of_property_read_u32_array(endpoint, "lane-polarities",
+ lane_polarities, nr_lanes + 1);
+ for (i = 1; i <= nr_lanes; i++) {
+ if (lane_polarities[1] != lane_polarities[i])
+ DRM_DEV_ERROR(dsi->dev, "Data lanes polarities do not match");
+ }
+ if (lane_polarities[0])
+ dsi->swap_dn_dp_clk = true;
+ if (lane_polarities[1])
+ dsi->swap_dn_dp_data = true;
+ }
+
return 0;
}
@@ -1954,7 +2095,6 @@ static struct platform_driver samsung_dsim_driver = {
.remove = samsung_dsim_remove,
.driver = {
.name = "samsung-dsim",
- .owner = THIS_MODULE,
.pm = &samsung_dsim_pm_ops,
.of_match_table = samsung_dsim_of_match,
},
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index ef66461e7f7c..aac239729a1d 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -1151,7 +1151,7 @@ static const struct i2c_device_id sii902x_i2c_ids[] = {
MODULE_DEVICE_TABLE(i2c, sii902x_i2c_ids);
static struct i2c_driver sii902x_driver = {
- .probe_new = sii902x_probe,
+ .probe = sii902x_probe,
.remove = sii902x_remove,
.driver = {
.name = "sii902x",
diff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c
index 2d17f227867b..d8373d918324 100644
--- a/drivers/gpu/drm/bridge/sii9234.c
+++ b/drivers/gpu/drm/bridge/sii9234.c
@@ -955,7 +955,7 @@ static struct i2c_driver sii9234_driver = {
.name = "sii9234",
.of_match_table = sii9234_dt_match,
},
- .probe_new = sii9234_probe,
+ .probe = sii9234_probe,
.remove = sii9234_remove,
.id_table = sii9234_id,
};
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index b96d03cd878d..79b09ccd1353 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.c
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -2378,7 +2378,7 @@ static struct i2c_driver sii8620_driver = {
.name = "sii8620",
.of_match_table = of_match_ptr(sii8620_dt_match),
},
- .probe_new = sii8620_probe,
+ .probe = sii8620_probe,
.remove = sii8620_remove,
.id_table = sii8620_id,
};
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 603bb3c51027..9d6dcaf317a1 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -533,7 +533,7 @@ static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi)
adap->owner = THIS_MODULE;
adap->dev.parent = hdmi->dev;
adap->algo = &dw_hdmi_algorithm;
- strlcpy(adap->name, "DesignWare HDMI", sizeof(adap->name));
+ strscpy(adap->name, "DesignWare HDMI", sizeof(adap->name));
i2c_set_adapdata(adap, hdmi);
ret = i2c_add_adapter(adap);
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index 77f7f7f54757..5641395fd310 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -11,6 +11,7 @@
*/
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_graph.h>
@@ -63,6 +64,7 @@ struct tc358762 {
struct drm_bridge bridge;
struct regulator *regulator;
struct drm_bridge *panel_bridge;
+ struct gpio_desc *reset_gpio;
bool pre_enabled;
int error;
};
@@ -138,6 +140,9 @@ static void tc358762_post_disable(struct drm_bridge *bridge)
ctx->pre_enabled = false;
+ if (ctx->reset_gpio)
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+
ret = regulator_disable(ctx->regulator);
if (ret < 0)
dev_err(ctx->dev, "error disabling regulators (%d)\n", ret);
@@ -152,6 +157,11 @@ static void tc358762_pre_enable(struct drm_bridge *bridge)
if (ret < 0)
dev_err(ctx->dev, "error enabling regulators (%d)\n", ret);
+ if (ctx->reset_gpio) {
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ usleep_range(5000, 10000);
+ }
+
ret = tc358762_init(ctx);
if (ret < 0)
dev_err(ctx->dev, "error initializing bridge (%d)\n", ret);
@@ -185,6 +195,11 @@ static int tc358762_parse_dt(struct tc358762 *ctx)
ctx->panel_bridge = panel_bridge;
+ /* Reset GPIO is optional */
+ ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->reset_gpio))
+ return PTR_ERR(ctx->reset_gpio);
+
return 0;
}
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index 91f7cb56a654..65dc842e31f0 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -1781,7 +1781,200 @@ static const struct drm_bridge_funcs tc_edp_bridge_funcs = {
static bool tc_readable_reg(struct device *dev, unsigned int reg)
{
- return reg != SYSCTRL;
+ switch (reg) {
+ /* DSI D-PHY Layer */
+ case 0x004:
+ case 0x020:
+ case 0x024:
+ case 0x028:
+ case 0x02c:
+ case 0x030:
+ case 0x038:
+ case 0x040:
+ case 0x044:
+ case 0x048:
+ case 0x04c:
+ case 0x050:
+ case 0x054:
+ /* DSI PPI Layer */
+ case PPI_STARTPPI:
+ case 0x108:
+ case 0x110:
+ case PPI_LPTXTIMECNT:
+ case PPI_LANEENABLE:
+ case PPI_TX_RX_TA:
+ case 0x140:
+ case PPI_D0S_ATMR:
+ case PPI_D1S_ATMR:
+ case 0x14c:
+ case 0x150:
+ case PPI_D0S_CLRSIPOCOUNT:
+ case PPI_D1S_CLRSIPOCOUNT:
+ case PPI_D2S_CLRSIPOCOUNT:
+ case PPI_D3S_CLRSIPOCOUNT:
+ case 0x180:
+ case 0x184:
+ case 0x188:
+ case 0x18c:
+ case 0x190:
+ case 0x1a0:
+ case 0x1a4:
+ case 0x1a8:
+ case 0x1ac:
+ case 0x1b0:
+ case 0x1c0:
+ case 0x1c4:
+ case 0x1c8:
+ case 0x1cc:
+ case 0x1d0:
+ case 0x1e0:
+ case 0x1e4:
+ case 0x1f0:
+ case 0x1f4:
+ /* DSI Protocol Layer */
+ case DSI_STARTDSI:
+ case 0x208:
+ case DSI_LANEENABLE:
+ case 0x214:
+ case 0x218:
+ case 0x220:
+ case 0x224:
+ case 0x228:
+ case 0x230:
+ /* DSI General */
+ case 0x300:
+ /* DSI Application Layer */
+ case 0x400:
+ case 0x404:
+ /* DPI */
+ case DPIPXLFMT:
+ /* Parallel Output */
+ case POCTRL:
+ /* Video Path0 Configuration */
+ case VPCTRL0:
+ case HTIM01:
+ case HTIM02:
+ case VTIM01:
+ case VTIM02:
+ case VFUEN0:
+ /* System */
+ case TC_IDREG:
+ case 0x504:
+ case SYSSTAT:
+ case SYSRSTENB:
+ case SYSCTRL:
+ /* I2C */
+ case 0x520:
+ /* GPIO */
+ case GPIOM:
+ case GPIOC:
+ case GPIOO:
+ case GPIOI:
+ /* Interrupt */
+ case INTCTL_G:
+ case INTSTS_G:
+ case 0x570:
+ case 0x574:
+ case INT_GP0_LCNT:
+ case INT_GP1_LCNT:
+ /* DisplayPort Control */
+ case DP0CTL:
+ /* DisplayPort Clock */
+ case DP0_VIDMNGEN0:
+ case DP0_VIDMNGEN1:
+ case DP0_VMNGENSTATUS:
+ case 0x628:
+ case 0x62c:
+ case 0x630:
+ /* DisplayPort Main Channel */
+ case DP0_SECSAMPLE:
+ case DP0_VIDSYNCDELAY:
+ case DP0_TOTALVAL:
+ case DP0_STARTVAL:
+ case DP0_ACTIVEVAL:
+ case DP0_SYNCVAL:
+ case DP0_MISC:
+ /* DisplayPort Aux Channel */
+ case DP0_AUXCFG0:
+ case DP0_AUXCFG1:
+ case DP0_AUXADDR:
+ case 0x66c:
+ case 0x670:
+ case 0x674:
+ case 0x678:
+ case 0x67c:
+ case 0x680:
+ case 0x684:
+ case 0x688:
+ case DP0_AUXSTATUS:
+ case DP0_AUXI2CADR:
+ /* DisplayPort Link Training */
+ case DP0_SRCCTRL:
+ case DP0_LTSTAT:
+ case DP0_SNKLTCHGREQ:
+ case DP0_LTLOOPCTRL:
+ case DP0_SNKLTCTRL:
+ case 0x6e8:
+ case 0x6ec:
+ case 0x6f0:
+ case 0x6f4:
+ /* DisplayPort Audio */
+ case 0x700:
+ case 0x704:
+ case 0x708:
+ case 0x70c:
+ case 0x710:
+ case 0x714:
+ case 0x718:
+ case 0x71c:
+ case 0x720:
+ /* DisplayPort Source Control */
+ case DP1_SRCCTRL:
+ /* DisplayPort PHY */
+ case DP_PHY_CTRL:
+ case 0x810:
+ case 0x814:
+ case 0x820:
+ case 0x840:
+ /* I2S */
+ case 0x880:
+ case 0x888:
+ case 0x88c:
+ case 0x890:
+ case 0x894:
+ case 0x898:
+ case 0x89c:
+ case 0x8a0:
+ case 0x8a4:
+ case 0x8a8:
+ case 0x8ac:
+ case 0x8b0:
+ case 0x8b4:
+ /* PLL */
+ case DP0_PLLCTRL:
+ case DP1_PLLCTRL:
+ case PXL_PLLCTRL:
+ case PXL_PLLPARAM:
+ case SYS_PLLPARAM:
+ /* HDCP */
+ case 0x980:
+ case 0x984:
+ case 0x988:
+ case 0x98c:
+ case 0x990:
+ case 0x994:
+ case 0x998:
+ case 0x99c:
+ case 0x9a0:
+ case 0x9a4:
+ case 0x9a8:
+ case 0x9ac:
+ /* Debug */
+ case TSTCTL:
+ case PLL_DBG:
+ return true;
+ }
+ return false;
}
static const struct regmap_range tc_volatile_ranges[] = {
@@ -1890,7 +2083,7 @@ static int tc_mipi_dsi_host_attach(struct tc_data *tc)
if (dsi_lanes < 0)
return dsi_lanes;
- dsi = mipi_dsi_device_register_full(host, &info);
+ dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
if (IS_ERR(dsi))
return dev_err_probe(dev, PTR_ERR(dsi),
"failed to create dsi device\n");
@@ -1901,7 +2094,7 @@ static int tc_mipi_dsi_host_attach(struct tc_data *tc)
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS;
- ret = mipi_dsi_attach(dsi);
+ ret = devm_mipi_dsi_attach(dev, dsi);
if (ret < 0) {
dev_err(dev, "failed to attach dsi to host: %d\n", ret);
return ret;
@@ -2209,7 +2402,7 @@ static struct i2c_driver tc358767_driver = {
.of_match_table = tc358767_of_ids,
},
.id_table = tc358767_i2c_ids,
- .probe_new = tc_probe,
+ .probe = tc_probe,
.remove = tc_remove,
};
module_i2c_driver(tc358767_driver);
diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c
index 7c0cbe84611b..819a4b6ec2a0 100644
--- a/drivers/gpu/drm/bridge/tc358768.c
+++ b/drivers/gpu/drm/bridge/tc358768.c
@@ -9,6 +9,8 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
+#include <linux/media-bus-format.h>
+#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -146,6 +148,7 @@ struct tc358768_priv {
u32 pd_lines; /* number of Parallel Port Input Data Lines */
u32 dsi_lanes; /* number of DSI Lanes */
+ u32 dsi_bpp; /* number of Bits Per Pixel over DSI */
/* Parameters for PLL programming */
u32 fbd; /* PLL feedback divider */
@@ -284,12 +287,12 @@ static void tc358768_hw_disable(struct tc358768_priv *priv)
static u32 tc358768_pll_to_pclk(struct tc358768_priv *priv, u32 pll_clk)
{
- return (u32)div_u64((u64)pll_clk * priv->dsi_lanes, priv->pd_lines);
+ return (u32)div_u64((u64)pll_clk * priv->dsi_lanes, priv->dsi_bpp);
}
static u32 tc358768_pclk_to_pll(struct tc358768_priv *priv, u32 pclk)
{
- return (u32)div_u64((u64)pclk * priv->pd_lines, priv->dsi_lanes);
+ return (u32)div_u64((u64)pclk * priv->dsi_bpp, priv->dsi_lanes);
}
static int tc358768_calc_pll(struct tc358768_priv *priv,
@@ -334,13 +337,17 @@ static int tc358768_calc_pll(struct tc358768_priv *priv,
u32 fbd;
for (fbd = 0; fbd < 512; ++fbd) {
- u32 pll, diff;
+ u32 pll, diff, pll_in;
pll = (u32)div_u64((u64)refclk * (fbd + 1), divisor);
if (pll >= max_pll || pll < min_pll)
continue;
+ pll_in = (u32)div_u64((u64)refclk, prd + 1);
+ if (pll_in < 4000000)
+ continue;
+
diff = max(pll, target_pll) - min(pll, target_pll);
if (diff < best_diff) {
@@ -422,6 +429,7 @@ static int tc358768_dsi_host_attach(struct mipi_dsi_host *host,
priv->output.panel = panel;
priv->dsi_lanes = dev->lanes;
+ priv->dsi_bpp = mipi_dsi_pixel_format_to_bpp(dev->format);
/* get input ep (port0/endpoint0) */
ret = -EINVAL;
@@ -433,7 +441,7 @@ static int tc358768_dsi_host_attach(struct mipi_dsi_host *host,
}
if (ret)
- priv->pd_lines = mipi_dsi_pixel_format_to_bpp(dev->format);
+ priv->pd_lines = priv->dsi_bpp;
drm_bridge_add(&priv->bridge);
@@ -632,8 +640,9 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
struct mipi_dsi_device *dsi_dev = priv->output.dev;
unsigned long mode_flags = dsi_dev->mode_flags;
u32 val, val2, lptxcnt, hact, data_type;
+ s32 raw_val;
const struct drm_display_mode *mode;
- u32 dsibclk_nsk, dsiclk_nsk, ui_nsk, phy_delay_nsk;
+ u32 dsibclk_nsk, dsiclk_nsk, ui_nsk;
u32 dsiclk, dsibclk, video_start;
const u32 internal_delay = 40;
int ret, i;
@@ -717,11 +726,9 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
dsibclk);
dsiclk_nsk = (u32)div_u64((u64)1000000000 * TC358768_PRECISION, dsiclk);
ui_nsk = dsiclk_nsk / 2;
- phy_delay_nsk = dsibclk_nsk + 2 * dsiclk_nsk;
dev_dbg(priv->dev, "dsiclk_nsk: %u\n", dsiclk_nsk);
dev_dbg(priv->dev, "ui_nsk: %u\n", ui_nsk);
dev_dbg(priv->dev, "dsibclk_nsk: %u\n", dsibclk_nsk);
- dev_dbg(priv->dev, "phy_delay_nsk: %u\n", phy_delay_nsk);
/* LP11 > 100us for D-PHY Rx Init */
val = tc358768_ns_to_cnt(100 * 1000, dsibclk_nsk) - 1;
@@ -736,25 +743,26 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
/* 38ns < TCLK_PREPARE < 95ns */
val = tc358768_ns_to_cnt(65, dsibclk_nsk) - 1;
- /* TCLK_PREPARE > 300ns */
- val2 = tc358768_ns_to_cnt(300 + tc358768_to_ns(3 * ui_nsk),
- dsibclk_nsk);
- val |= (val2 - tc358768_to_ns(phy_delay_nsk - dsibclk_nsk)) << 8;
+ /* TCLK_PREPARE + TCLK_ZERO > 300ns */
+ val2 = tc358768_ns_to_cnt(300 - tc358768_to_ns(2 * ui_nsk),
+ dsibclk_nsk) - 2;
+ val |= val2 << 8;
dev_dbg(priv->dev, "TCLK_HEADERCNT: 0x%x\n", val);
tc358768_write(priv, TC358768_TCLK_HEADERCNT, val);
- /* TCLK_TRAIL > 60ns + 3*UI */
- val = 60 + tc358768_to_ns(3 * ui_nsk);
- val = tc358768_ns_to_cnt(val, dsibclk_nsk) - 5;
+ /* TCLK_TRAIL > 60ns AND TEOT <= 105 ns + 12*UI */
+ raw_val = tc358768_ns_to_cnt(60 + tc358768_to_ns(2 * ui_nsk), dsibclk_nsk) - 5;
+ val = clamp(raw_val, 0, 127);
dev_dbg(priv->dev, "TCLK_TRAILCNT: 0x%x\n", val);
tc358768_write(priv, TC358768_TCLK_TRAILCNT, val);
/* 40ns + 4*UI < THS_PREPARE < 85ns + 6*UI */
val = 50 + tc358768_to_ns(4 * ui_nsk);
val = tc358768_ns_to_cnt(val, dsibclk_nsk) - 1;
- /* THS_ZERO > 145ns + 10*UI */
- val2 = tc358768_ns_to_cnt(145 - tc358768_to_ns(ui_nsk), dsibclk_nsk);
- val |= (val2 - tc358768_to_ns(phy_delay_nsk)) << 8;
+ /* THS_PREPARE + THS_ZERO > 145ns + 10*UI */
+ raw_val = tc358768_ns_to_cnt(145 - tc358768_to_ns(3 * ui_nsk), dsibclk_nsk) - 10;
+ val2 = clamp(raw_val, 0, 127);
+ val |= val2 << 8;
dev_dbg(priv->dev, "THS_HEADERCNT: 0x%x\n", val);
tc358768_write(priv, TC358768_THS_HEADERCNT, val);
@@ -770,9 +778,10 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
dev_dbg(priv->dev, "TCLK_POSTCNT: 0x%x\n", val);
tc358768_write(priv, TC358768_TCLK_POSTCNT, val);
- /* 60ns + 4*UI < THS_PREPARE < 105ns + 12*UI */
- val = tc358768_ns_to_cnt(60 + tc358768_to_ns(15 * ui_nsk),
- dsibclk_nsk) - 5;
+ /* max(60ns + 4*UI, 8*UI) < THS_TRAILCNT < 105ns + 12*UI */
+ raw_val = tc358768_ns_to_cnt(60 + tc358768_to_ns(18 * ui_nsk),
+ dsibclk_nsk) - 4;
+ val = clamp(raw_val, 0, 15);
dev_dbg(priv->dev, "THS_TRAILCNT: 0x%x\n", val);
tc358768_write(priv, TC358768_THS_TRAILCNT, val);
@@ -786,7 +795,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
/* TXTAGOCNT[26:16] RXTASURECNT[10:0] */
val = tc358768_to_ns((lptxcnt + 1) * dsibclk_nsk * 4);
- val = tc358768_ns_to_cnt(val, dsibclk_nsk) - 1;
+ val = tc358768_ns_to_cnt(val, dsibclk_nsk) / 4 - 1;
val2 = tc358768_ns_to_cnt(tc358768_to_ns((lptxcnt + 1) * dsibclk_nsk),
dsibclk_nsk) - 2;
val = val << 16 | val2;
@@ -866,8 +875,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
val = TC358768_DSI_CONFW_MODE_SET | TC358768_DSI_CONFW_ADDR_DSI_CONTROL;
val |= (dsi_dev->lanes - 1) << 1;
- if (!(dsi_dev->mode_flags & MIPI_DSI_MODE_LPM))
- val |= TC358768_DSI_CONTROL_TXMD;
+ val |= TC358768_DSI_CONTROL_TXMD;
if (!(mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
val |= TC358768_DSI_CONTROL_HSCKMD;
@@ -913,6 +921,44 @@ static void tc358768_bridge_enable(struct drm_bridge *bridge)
}
}
+#define MAX_INPUT_SEL_FORMATS 1
+
+static u32 *
+tc358768_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ u32 output_fmt,
+ unsigned int *num_input_fmts)
+{
+ struct tc358768_priv *priv = bridge_to_tc358768(bridge);
+ u32 *input_fmts;
+
+ *num_input_fmts = 0;
+
+ input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts),
+ GFP_KERNEL);
+ if (!input_fmts)
+ return NULL;
+
+ switch (priv->pd_lines) {
+ case 16:
+ input_fmts[0] = MEDIA_BUS_FMT_RGB565_1X16;
+ break;
+ case 18:
+ input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X18;
+ break;
+ default:
+ case 24:
+ input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
+ break;
+ }
+
+ *num_input_fmts = MAX_INPUT_SEL_FORMATS;
+
+ return input_fmts;
+}
+
static const struct drm_bridge_funcs tc358768_bridge_funcs = {
.attach = tc358768_bridge_attach,
.mode_valid = tc358768_bridge_mode_valid,
@@ -920,6 +966,11 @@ static const struct drm_bridge_funcs tc358768_bridge_funcs = {
.enable = tc358768_bridge_enable,
.disable = tc358768_bridge_disable,
.post_disable = tc358768_bridge_post_disable,
+
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
+ .atomic_get_input_bus_fmts = tc358768_atomic_get_input_bus_fmts,
};
static const struct drm_bridge_timings default_tc358768_timings = {
@@ -1083,7 +1134,7 @@ static struct i2c_driver tc358768_driver = {
.of_match_table = tc358768_of_ids,
},
.id_table = tc358768_i2c_ids,
- .probe_new = tc358768_i2c_probe,
+ .probe = tc358768_i2c_probe,
.remove = tc358768_i2c_remove,
};
module_i2c_driver(tc358768_driver);
diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c
index 19316994ddd1..90a89d70d832 100644
--- a/drivers/gpu/drm/bridge/tc358775.c
+++ b/drivers/gpu/drm/bridge/tc358775.c
@@ -728,7 +728,7 @@ static struct i2c_driver tc358775_driver = {
.of_match_table = tc358775_of_ids,
},
.id_table = tc358775_i2c_ids,
- .probe_new = tc_probe,
+ .probe = tc_probe,
.remove = tc_remove,
};
module_i2c_driver(tc358775_driver);
diff --git a/drivers/gpu/drm/bridge/ti-dlpc3433.c b/drivers/gpu/drm/bridge/ti-dlpc3433.c
index 186a9e2ff24d..b65632ec7e7d 100644
--- a/drivers/gpu/drm/bridge/ti-dlpc3433.c
+++ b/drivers/gpu/drm/bridge/ti-dlpc3433.c
@@ -400,7 +400,7 @@ static const struct of_device_id dlpc3433_match_table[] = {
MODULE_DEVICE_TABLE(of, dlpc3433_match_table);
static struct i2c_driver dlpc3433_driver = {
- .probe_new = dlpc3433_probe,
+ .probe = dlpc3433_probe,
.remove = dlpc3433_remove,
.id_table = dlpc3433_id,
.driver = {
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index 75286c9afbb9..7e9f4ec8e780 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -321,8 +321,8 @@ static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx)
return dsi_div - 1;
}
-static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
- struct drm_bridge_state *old_bridge_state)
+static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
{
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
struct drm_atomic_state *state = old_bridge_state->base.state;
@@ -478,17 +478,29 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret);
/* On failure, disable PLL again and exit. */
regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);
+ regulator_disable(ctx->vcc);
return;
}
/* Trigger reset after CSR register update. */
regmap_write(ctx->regmap, REG_RC_RESET, REG_RC_RESET_SOFT_RESET);
+ /* Wait for 10ms after soft reset as specified in datasheet */
+ usleep_range(10000, 12000);
+}
+
+static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
+{
+ struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
+ unsigned int pval;
+
/* Clear all errors that got asserted during initialization. */
regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);
regmap_write(ctx->regmap, REG_IRQ_STAT, pval);
- usleep_range(10000, 12000);
+ /* Wait for 1ms and check for errors in status register */
+ usleep_range(1000, 1100);
regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);
if (pval)
dev_err(ctx->dev, "Unexpected link status 0x%02x\n", pval);
@@ -555,6 +567,7 @@ static const struct drm_bridge_funcs sn65dsi83_funcs = {
.attach = sn65dsi83_attach,
.detach = sn65dsi83_detach,
.atomic_enable = sn65dsi83_atomic_enable,
+ .atomic_pre_enable = sn65dsi83_atomic_pre_enable,
.atomic_disable = sn65dsi83_atomic_disable,
.mode_valid = sn65dsi83_mode_valid,
@@ -697,6 +710,7 @@ static int sn65dsi83_probe(struct i2c_client *client)
ctx->bridge.funcs = &sn65dsi83_funcs;
ctx->bridge.of_node = dev->of_node;
+ ctx->bridge.pre_enable_prev_first = true;
drm_bridge_add(&ctx->bridge);
ret = sn65dsi83_host_attach(ctx);
@@ -734,7 +748,7 @@ static const struct of_device_id sn65dsi83_match_table[] = {
MODULE_DEVICE_TABLE(of, sn65dsi83_match_table);
static struct i2c_driver sn65dsi83_driver = {
- .probe_new = sn65dsi83_probe,
+ .probe = sn65dsi83_probe,
.remove = sn65dsi83_remove,
.id_table = sn65dsi83_id,
.driver = {
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 4676cf2900df..c499a14d0b98 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -622,6 +622,24 @@ exit:
return len;
}
+static int ti_sn_aux_wait_hpd_asserted(struct drm_dp_aux *aux, unsigned long wait_us)
+{
+ /*
+ * The HPD in this chip is a bit useless (See comment in
+ * ti_sn65dsi86_enable_comms) so if our driver is expected to wait
+ * for HPD, we just assume it's asserted after the wait_us delay.
+ *
+ * In case we are asked to wait forever (wait_us=0) take conservative
+ * 500ms delay.
+ */
+ if (wait_us == 0)
+ wait_us = 500000;
+
+ usleep_range(wait_us, wait_us + 1000);
+
+ return 0;
+}
+
static int ti_sn_aux_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
@@ -631,6 +649,7 @@ static int ti_sn_aux_probe(struct auxiliary_device *adev,
pdata->aux.name = "ti-sn65dsi86-aux";
pdata->aux.dev = &adev->dev;
pdata->aux.transfer = ti_sn_aux_transfer;
+ pdata->aux.wait_hpd_asserted = ti_sn_aux_wait_hpd_asserted;
drm_dp_aux_init(&pdata->aux);
ret = devm_of_dp_aux_populate_ep_devices(&pdata->aux);
@@ -1955,7 +1974,7 @@ static struct i2c_driver ti_sn65dsi86_driver = {
.of_match_table = ti_sn65dsi86_match_table,
.pm = &ti_sn65dsi86_pm_ops,
},
- .probe_new = ti_sn65dsi86_probe,
+ .probe = ti_sn65dsi86_probe,
.id_table = ti_sn65dsi86_id,
};
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index ab63225cd635..c06390da9ffd 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -408,7 +408,7 @@ static struct i2c_driver tfp410_i2c_driver = {
.of_match_table = of_match_ptr(tfp410_match),
},
.id_table = tfp410_i2c_ids,
- .probe_new = tfp410_i2c_probe,
+ .probe = tfp410_i2c_probe,
.remove = tfp410_i2c_remove,
};
#endif /* IS_ENABLED(CONFIG_I2C) */
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 943a00db77d4..ed96cfcfa304 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -1823,7 +1823,7 @@ static void drm_dp_destroy_port(struct kref *kref)
return;
}
- kfree(port->cached_edid);
+ drm_edid_free(port->cached_edid);
/*
* we can't destroy the connector here, as we might be holding the
@@ -2272,8 +2272,8 @@ drm_dp_mst_port_add_connector(struct drm_dp_mst_branch *mstb,
if (port->pdt != DP_PEER_DEVICE_NONE &&
drm_dp_mst_is_end_device(port->pdt, port->mcs) &&
port->port_num >= DP_MST_LOGICAL_PORT_0)
- port->cached_edid = drm_get_edid(port->connector,
- &port->aux.ddc);
+ port->cached_edid = drm_edid_read_ddc(port->connector,
+ &port->aux.ddc);
drm_connector_register(port->connector);
return;
@@ -4053,17 +4053,28 @@ out:
}
/**
- * drm_dp_mst_hpd_irq() - MST hotplug IRQ notify
+ * drm_dp_mst_hpd_irq_handle_event() - MST hotplug IRQ handle MST event
* @mgr: manager to notify irq for.
* @esi: 4 bytes from SINK_COUNT_ESI
+ * @ack: 4 bytes used to ack events starting from SINK_COUNT_ESI
* @handled: whether the hpd interrupt was consumed or not
*
- * This should be called from the driver when it detects a short IRQ,
+ * This should be called from the driver when it detects a HPD IRQ,
* along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The
- * topology manager will process the sideband messages received as a result
- * of this.
+ * topology manager will process the sideband messages received
+ * as indicated in the DEVICE_SERVICE_IRQ_VECTOR_ESI0 and set the
+ * corresponding flags that Driver has to ack the DP receiver later.
+ *
+ * Note that driver shall also call
+ * drm_dp_mst_hpd_irq_send_new_request() if the 'handled' is set
+ * after calling this function, to try to kick off a new request in
+ * the queue if the previous message transaction is completed.
+ *
+ * See also:
+ * drm_dp_mst_hpd_irq_send_new_request()
*/
-int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled)
+int drm_dp_mst_hpd_irq_handle_event(struct drm_dp_mst_topology_mgr *mgr, const u8 *esi,
+ u8 *ack, bool *handled)
{
int ret = 0;
int sc;
@@ -4078,19 +4089,48 @@ int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handl
if (esi[1] & DP_DOWN_REP_MSG_RDY) {
ret = drm_dp_mst_handle_down_rep(mgr);
*handled = true;
+ ack[1] |= DP_DOWN_REP_MSG_RDY;
}
if (esi[1] & DP_UP_REQ_MSG_RDY) {
ret |= drm_dp_mst_handle_up_req(mgr);
*handled = true;
+ ack[1] |= DP_UP_REQ_MSG_RDY;
}
- drm_dp_mst_kick_tx(mgr);
return ret;
}
-EXPORT_SYMBOL(drm_dp_mst_hpd_irq);
+EXPORT_SYMBOL(drm_dp_mst_hpd_irq_handle_event);
/**
+ * drm_dp_mst_hpd_irq_send_new_request() - MST hotplug IRQ kick off new request
+ * @mgr: manager to notify irq for.
+ *
+ * This should be called from the driver when mst irq event is handled
+ * and acked. Note that new down request should only be sent when
+ * previous message transaction is completed. Source is not supposed to generate
+ * interleaved message transactions.
+ */
+void drm_dp_mst_hpd_irq_send_new_request(struct drm_dp_mst_topology_mgr *mgr)
+{
+ struct drm_dp_sideband_msg_tx *txmsg;
+ bool kick = true;
+
+ mutex_lock(&mgr->qlock);
+ txmsg = list_first_entry_or_null(&mgr->tx_msg_downq,
+ struct drm_dp_sideband_msg_tx, next);
+ /* If last transaction is not completed yet*/
+ if (!txmsg ||
+ txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND ||
+ txmsg->state == DRM_DP_SIDEBAND_TX_SENT)
+ kick = false;
+ mutex_unlock(&mgr->qlock);
+
+ if (kick)
+ drm_dp_mst_kick_tx(mgr);
+}
+EXPORT_SYMBOL(drm_dp_mst_hpd_irq_send_new_request);
+/**
* drm_dp_mst_detect_port() - get connection status for an MST port
* @connector: DRM connector for this port
* @ctx: The acquisition context to use for grabbing locks
@@ -4133,7 +4173,7 @@ drm_dp_mst_detect_port(struct drm_connector *connector,
ret = connector_status_connected;
/* for logical ports - cache the EDID */
if (port->port_num >= DP_MST_LOGICAL_PORT_0 && !port->cached_edid)
- port->cached_edid = drm_get_edid(connector, &port->aux.ddc);
+ port->cached_edid = drm_edid_read_ddc(connector, &port->aux.ddc);
break;
case DP_PEER_DEVICE_DP_LEGACY_CONV:
if (port->ldps)
@@ -4147,7 +4187,7 @@ out:
EXPORT_SYMBOL(drm_dp_mst_detect_port);
/**
- * drm_dp_mst_get_edid() - get EDID for an MST port
+ * drm_dp_mst_edid_read() - get EDID for an MST port
* @connector: toplevel connector to get EDID for
* @mgr: manager for this port
* @port: unverified pointer to a port.
@@ -4156,9 +4196,11 @@ EXPORT_SYMBOL(drm_dp_mst_detect_port);
* It validates the pointer still exists so the caller doesn't require a
* reference.
*/
-struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+const struct drm_edid *drm_dp_mst_edid_read(struct drm_connector *connector,
+ struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port)
{
- struct edid *edid = NULL;
+ const struct drm_edid *drm_edid;
/* we need to search for the port in the mgr in case it's gone */
port = drm_dp_mst_topology_get_port_validated(mgr, port);
@@ -4166,12 +4208,41 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
return NULL;
if (port->cached_edid)
- edid = drm_edid_duplicate(port->cached_edid);
- else {
- edid = drm_get_edid(connector, &port->aux.ddc);
- }
- port->has_audio = drm_detect_monitor_audio(edid);
+ drm_edid = drm_edid_dup(port->cached_edid);
+ else
+ drm_edid = drm_edid_read_ddc(connector, &port->aux.ddc);
+
drm_dp_mst_topology_put_port(port);
+
+ return drm_edid;
+}
+EXPORT_SYMBOL(drm_dp_mst_edid_read);
+
+/**
+ * drm_dp_mst_get_edid() - get EDID for an MST port
+ * @connector: toplevel connector to get EDID for
+ * @mgr: manager for this port
+ * @port: unverified pointer to a port.
+ *
+ * This function is deprecated; please use drm_dp_mst_edid_read() instead.
+ *
+ * This returns an EDID for the port connected to a connector,
+ * It validates the pointer still exists so the caller doesn't require a
+ * reference.
+ */
+struct edid *drm_dp_mst_get_edid(struct drm_connector *connector,
+ struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port)
+{
+ const struct drm_edid *drm_edid;
+ struct edid *edid;
+
+ drm_edid = drm_dp_mst_edid_read(connector, mgr, port);
+
+ edid = drm_edid_duplicate(drm_edid_raw(drm_edid));
+
+ drm_edid_free(drm_edid);
+
return edid;
}
EXPORT_SYMBOL(drm_dp_mst_get_edid);
diff --git a/drivers/gpu/drm/display/drm_dsc_helper.c b/drivers/gpu/drm/display/drm_dsc_helper.c
index c869c6e51e2b..4424380c6cb6 100644
--- a/drivers/gpu/drm/display/drm_dsc_helper.c
+++ b/drivers/gpu/drm/display/drm_dsc_helper.c
@@ -271,6 +271,1034 @@ void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_payload,
EXPORT_SYMBOL(drm_dsc_pps_payload_pack);
/**
+ * drm_dsc_set_const_params() - Set DSC parameters considered typically
+ * constant across operation modes
+ *
+ * @vdsc_cfg:
+ * DSC Configuration data partially filled by driver
+ */
+void drm_dsc_set_const_params(struct drm_dsc_config *vdsc_cfg)
+{
+ if (!vdsc_cfg->rc_model_size)
+ vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;
+ vdsc_cfg->rc_edge_factor = DSC_RC_EDGE_FACTOR_CONST;
+ vdsc_cfg->rc_tgt_offset_high = DSC_RC_TGT_OFFSET_HI_CONST;
+ vdsc_cfg->rc_tgt_offset_low = DSC_RC_TGT_OFFSET_LO_CONST;
+
+ if (vdsc_cfg->bits_per_component <= 10)
+ vdsc_cfg->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
+ else
+ vdsc_cfg->mux_word_size = DSC_MUX_WORD_SIZE_12_BPC;
+}
+EXPORT_SYMBOL(drm_dsc_set_const_params);
+
+/* From DSC_v1.11 spec, rc_parameter_Set syntax element typically constant */
+static const u16 drm_dsc_rc_buf_thresh[] = {
+ 896, 1792, 2688, 3584, 4480, 5376, 6272, 6720, 7168, 7616,
+ 7744, 7872, 8000, 8064
+};
+
+/**
+ * drm_dsc_set_rc_buf_thresh() - Set thresholds for the RC model
+ * in accordance with the DSC 1.2 specification.
+ *
+ * @vdsc_cfg: DSC Configuration data partially filled by driver
+ */
+void drm_dsc_set_rc_buf_thresh(struct drm_dsc_config *vdsc_cfg)
+{
+ int i;
+
+ BUILD_BUG_ON(ARRAY_SIZE(drm_dsc_rc_buf_thresh) !=
+ DSC_NUM_BUF_RANGES - 1);
+ BUILD_BUG_ON(ARRAY_SIZE(drm_dsc_rc_buf_thresh) !=
+ ARRAY_SIZE(vdsc_cfg->rc_buf_thresh));
+
+ for (i = 0; i < ARRAY_SIZE(drm_dsc_rc_buf_thresh); i++)
+ vdsc_cfg->rc_buf_thresh[i] = drm_dsc_rc_buf_thresh[i] >> 6;
+
+ /*
+ * For 6bpp, RC Buffer threshold 12 and 13 need a different value
+ * as per C Model
+ */
+ if (vdsc_cfg->bits_per_pixel == 6 << 4) {
+ vdsc_cfg->rc_buf_thresh[12] = 7936 >> 6;
+ vdsc_cfg->rc_buf_thresh[13] = 8000 >> 6;
+ }
+}
+EXPORT_SYMBOL(drm_dsc_set_rc_buf_thresh);
+
+struct rc_parameters {
+ u16 initial_xmit_delay;
+ u8 first_line_bpg_offset;
+ u16 initial_offset;
+ u8 flatness_min_qp;
+ u8 flatness_max_qp;
+ u8 rc_quant_incr_limit0;
+ u8 rc_quant_incr_limit1;
+ struct drm_dsc_rc_range_parameters rc_range_params[DSC_NUM_BUF_RANGES];
+};
+
+struct rc_parameters_data {
+ u8 bpp;
+ u8 bpc;
+ struct rc_parameters params;
+};
+
+#define DSC_BPP(bpp) ((bpp) << 4)
+
+/*
+ * Rate Control Related Parameter Recommended Values from DSC_v1.1 spec prior
+ * to DSC 1.1 fractional bpp underflow SCR (DSC_v1.1_E1.pdf)
+ *
+ * Cross-checked against C Model releases: DSC_model_20161212 and 20210623
+ */
+static const struct rc_parameters_data rc_parameters_pre_scr[] = {
+ {
+ .bpp = DSC_BPP(6), .bpc = 8,
+ { 683, 15, 6144, 3, 13, 11, 11, {
+ { 0, 2, 0 }, { 1, 4, -2 }, { 3, 6, -2 }, { 4, 6, -4 },
+ { 5, 7, -6 }, { 5, 7, -6 }, { 6, 7, -6 }, { 6, 8, -8 },
+ { 7, 9, -8 }, { 8, 10, -10 }, { 9, 11, -10 }, { 10, 12, -12 },
+ { 10, 13, -12 }, { 12, 14, -12 }, { 15, 15, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 8,
+ { 512, 12, 6144, 3, 12, 11, 11, {
+ { 0, 4, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 1, 6, -2 },
+ { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
+ { 3, 9, -8 }, { 3, 10, -10 }, { 5, 11, -10 }, { 5, 12, -12 },
+ { 5, 13, -12 }, { 7, 13, -12 }, { 13, 15, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 10,
+ { 512, 12, 6144, 7, 16, 15, 15, {
+ /*
+ * DSC model/pre-SCR-cfg has 8 for range_max_qp[0], however
+ * VESA DSC 1.1 Table E-5 sets it to 4.
+ */
+ { 0, 4, 2 }, { 4, 8, 0 }, { 5, 9, 0 }, { 5, 10, -2 },
+ { 7, 11, -4 }, { 7, 11, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
+ { 7, 13, -8 }, { 7, 14, -10 }, { 9, 15, -10 }, { 9, 16, -12 },
+ { 9, 17, -12 }, { 11, 17, -12 }, { 17, 19, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 12,
+ { 512, 12, 6144, 11, 20, 19, 19, {
+ { 0, 12, 2 }, { 4, 12, 0 }, { 9, 13, 0 }, { 9, 14, -2 },
+ { 11, 15, -4 }, { 11, 15, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
+ { 11, 17, -8 }, { 11, 18, -10 }, { 13, 19, -10 },
+ { 13, 20, -12 }, { 13, 21, -12 }, { 15, 21, -12 },
+ { 21, 23, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 8,
+ { 410, 12, 5632, 3, 12, 11, 11, {
+ { 0, 3, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 2, 6, -2 },
+ { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
+ { 3, 9, -8 }, { 3, 9, -10 }, { 5, 10, -10 }, { 5, 11, -10 },
+ { 5, 12, -12 }, { 7, 13, -12 }, { 13, 15, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 10,
+ { 410, 12, 5632, 7, 16, 15, 15, {
+ { 0, 7, 2 }, { 4, 8, 0 }, { 5, 9, 0 }, { 6, 10, -2 },
+ { 7, 11, -4 }, { 7, 11, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
+ { 7, 13, -8 }, { 7, 13, -10 }, { 9, 14, -10 }, { 9, 15, -10 },
+ { 9, 16, -12 }, { 11, 17, -12 }, { 17, 19, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 12,
+ { 410, 12, 5632, 11, 20, 19, 19, {
+ { 0, 11, 2 }, { 4, 12, 0 }, { 9, 13, 0 }, { 10, 14, -2 },
+ { 11, 15, -4 }, { 11, 15, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
+ { 11, 17, -8 }, { 11, 17, -10 }, { 13, 18, -10 },
+ { 13, 19, -10 }, { 13, 20, -12 }, { 15, 21, -12 },
+ { 21, 23, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(12), .bpc = 8,
+ { 341, 15, 2048, 3, 12, 11, 11, {
+ { 0, 2, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 1, 6, -2 },
+ { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
+ { 3, 9, -8 }, { 3, 10, -10 }, { 5, 11, -10 },
+ { 5, 12, -12 }, { 5, 13, -12 }, { 7, 13, -12 }, { 13, 15, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(12), .bpc = 10,
+ { 341, 15, 2048, 7, 16, 15, 15, {
+ { 0, 2, 2 }, { 2, 5, 0 }, { 3, 7, 0 }, { 4, 8, -2 },
+ { 6, 9, -4 }, { 7, 10, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
+ { 7, 13, -8 }, { 7, 14, -10 }, { 9, 15, -10 }, { 9, 16, -12 },
+ { 9, 17, -12 }, { 11, 17, -12 }, { 17, 19, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(12), .bpc = 12,
+ { 341, 15, 2048, 11, 20, 19, 19, {
+ { 0, 6, 2 }, { 4, 9, 0 }, { 7, 11, 0 }, { 8, 12, -2 },
+ { 10, 13, -4 }, { 11, 14, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
+ { 11, 17, -8 }, { 11, 18, -10 }, { 13, 19, -10 },
+ { 13, 20, -12 }, { 13, 21, -12 }, { 15, 21, -12 },
+ { 21, 23, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(15), .bpc = 8,
+ { 273, 15, 2048, 3, 12, 11, 11, {
+ { 0, 0, 10 }, { 0, 1, 8 }, { 0, 1, 6 }, { 0, 2, 4 },
+ { 1, 2, 2 }, { 1, 3, 0 }, { 1, 4, -2 }, { 2, 4, -4 },
+ { 3, 4, -6 }, { 3, 5, -8 }, { 4, 6, -10 }, { 5, 7, -10 },
+ { 5, 8, -12 }, { 7, 13, -12 }, { 13, 15, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(15), .bpc = 10,
+ { 273, 15, 2048, 7, 16, 15, 15, {
+ { 0, 2, 10 }, { 2, 5, 8 }, { 3, 5, 6 }, { 4, 6, 4 },
+ { 5, 6, 2 }, { 5, 7, 0 }, { 5, 8, -2 }, { 6, 8, -4 },
+ { 7, 8, -6 }, { 7, 9, -8 }, { 8, 10, -10 }, { 9, 11, -10 },
+ { 9, 12, -12 }, { 11, 17, -12 }, { 17, 19, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(15), .bpc = 12,
+ { 273, 15, 2048, 11, 20, 19, 19, {
+ { 0, 4, 10 }, { 2, 7, 8 }, { 4, 9, 6 }, { 6, 11, 4 },
+ { 9, 11, 2 }, { 9, 11, 0 }, { 9, 12, -2 }, { 10, 12, -4 },
+ { 11, 12, -6 }, { 11, 13, -8 }, { 12, 14, -10 },
+ { 13, 15, -10 }, { 13, 16, -12 }, { 15, 21, -12 },
+ { 21, 23, -12 }
+ }
+ }
+ },
+ { /* sentinel */ }
+};
+
+/*
+ * Selected Rate Control Related Parameter Recommended Values from DSC v1.2, v1.2a, v1.2b and
+ * DSC_v1.1_E1 specs.
+ *
+ * Cross-checked against C Model releases: DSC_model_20161212 and 20210623
+ */
+static const struct rc_parameters_data rc_parameters_1_2_444[] = {
+ {
+ .bpp = DSC_BPP(6), .bpc = 8,
+ { 768, 15, 6144, 3, 13, 11, 11, {
+ { 0, 4, 0 }, { 1, 6, -2 }, { 3, 8, -2 }, { 4, 8, -4 },
+ { 5, 9, -6 }, { 5, 9, -6 }, { 6, 9, -6 }, { 6, 10, -8 },
+ { 7, 11, -8 }, { 8, 12, -10 }, { 9, 12, -10 }, { 10, 12, -12 },
+ { 10, 12, -12 }, { 11, 12, -12 }, { 13, 14, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 10,
+ { 768, 15, 6144, 7, 17, 15, 15, {
+ { 0, 8, 0 }, { 3, 10, -2 }, { 7, 12, -2 }, { 8, 12, -4 },
+ { 9, 13, -6 }, { 9, 13, -6 }, { 10, 13, -6 }, { 10, 14, -8 },
+ { 11, 15, -8 }, { 12, 16, -10 }, { 13, 16, -10 },
+ { 14, 16, -12 }, { 14, 16, -12 }, { 15, 16, -12 },
+ { 17, 18, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 12,
+ { 768, 15, 6144, 11, 21, 19, 19, {
+ { 0, 12, 0 }, { 5, 14, -2 }, { 11, 16, -2 }, { 12, 16, -4 },
+ { 13, 17, -6 }, { 13, 17, -6 }, { 14, 17, -6 }, { 14, 18, -8 },
+ { 15, 19, -8 }, { 16, 20, -10 }, { 17, 20, -10 },
+ { 18, 20, -12 }, { 18, 20, -12 }, { 19, 20, -12 },
+ { 21, 22, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 14,
+ { 768, 15, 6144, 15, 25, 23, 23, {
+ { 0, 16, 0 }, { 7, 18, -2 }, { 15, 20, -2 }, { 16, 20, -4 },
+ { 17, 21, -6 }, { 17, 21, -6 }, { 18, 21, -6 }, { 18, 22, -8 },
+ { 19, 23, -8 }, { 20, 24, -10 }, { 21, 24, -10 },
+ { 22, 24, -12 }, { 22, 24, -12 }, { 23, 24, -12 },
+ { 25, 26, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 16,
+ { 768, 15, 6144, 19, 29, 27, 27, {
+ { 0, 20, 0 }, { 9, 22, -2 }, { 19, 24, -2 }, { 20, 24, -4 },
+ { 21, 25, -6 }, { 21, 25, -6 }, { 22, 25, -6 }, { 22, 26, -8 },
+ { 23, 27, -8 }, { 24, 28, -10 }, { 25, 28, -10 },
+ { 26, 28, -12 }, { 26, 28, -12 }, { 27, 28, -12 },
+ { 29, 30, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 8,
+ { 512, 12, 6144, 3, 12, 11, 11, {
+ { 0, 4, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 1, 6, -2 },
+ { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
+ { 3, 9, -8 }, { 3, 10, -10 }, { 5, 10, -10 }, { 5, 11, -12 },
+ { 5, 11, -12 }, { 9, 12, -12 }, { 12, 13, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 10,
+ { 512, 12, 6144, 7, 16, 15, 15, {
+ { 0, 8, 2 }, { 4, 8, 0 }, { 5, 9, 0 }, { 5, 10, -2 },
+ { 7, 11, -4 }, { 7, 11, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
+ { 7, 13, -8 }, { 7, 14, -10 }, { 9, 14, -10 }, { 9, 15, -12 },
+ { 9, 15, -12 }, { 13, 16, -12 }, { 16, 17, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 12,
+ { 512, 12, 6144, 11, 20, 19, 19, {
+ { 0, 12, 2 }, { 4, 12, 0 }, { 9, 13, 0 }, { 9, 14, -2 },
+ { 11, 15, -4 }, { 11, 15, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
+ { 11, 17, -8 }, { 11, 18, -10 }, { 13, 18, -10 },
+ { 13, 19, -12 }, { 13, 19, -12 }, { 17, 20, -12 },
+ { 20, 21, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 14,
+ { 512, 12, 6144, 15, 24, 23, 23, {
+ { 0, 12, 2 }, { 5, 13, 0 }, { 11, 15, 0 }, { 12, 17, -2 },
+ { 15, 19, -4 }, { 15, 19, -6 }, { 15, 19, -8 }, { 15, 20, -8 },
+ { 15, 21, -8 }, { 15, 22, -10 }, { 17, 22, -10 },
+ { 17, 23, -12 }, { 17, 23, -12 }, { 21, 24, -12 },
+ { 24, 25, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 16,
+ { 512, 12, 6144, 19, 28, 27, 27, {
+ { 0, 12, 2 }, { 6, 14, 0 }, { 13, 17, 0 }, { 15, 20, -2 },
+ { 19, 23, -4 }, { 19, 23, -6 }, { 19, 23, -8 }, { 19, 24, -8 },
+ { 19, 25, -8 }, { 19, 26, -10 }, { 21, 26, -10 },
+ { 21, 27, -12 }, { 21, 27, -12 }, { 25, 28, -12 },
+ { 28, 29, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 8,
+ { 410, 15, 5632, 3, 12, 11, 11, {
+ { 0, 3, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 2, 6, -2 },
+ { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
+ { 3, 9, -8 }, { 3, 9, -10 }, { 5, 10, -10 }, { 5, 10, -10 },
+ { 5, 11, -12 }, { 7, 11, -12 }, { 11, 12, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 10,
+ { 410, 15, 5632, 7, 16, 15, 15, {
+ { 0, 7, 2 }, { 4, 8, 0 }, { 5, 9, 0 }, { 6, 10, -2 },
+ { 7, 11, -4 }, { 7, 11, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
+ { 7, 13, -8 }, { 7, 13, -10 }, { 9, 14, -10 }, { 9, 14, -10 },
+ { 9, 15, -12 }, { 11, 15, -12 }, { 15, 16, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 12,
+ { 410, 15, 5632, 11, 20, 19, 19, {
+ { 0, 11, 2 }, { 4, 12, 0 }, { 9, 13, 0 }, { 10, 14, -2 },
+ { 11, 15, -4 }, { 11, 15, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
+ { 11, 17, -8 }, { 11, 17, -10 }, { 13, 18, -10 },
+ { 13, 18, -10 }, { 13, 19, -12 }, { 15, 19, -12 },
+ { 19, 20, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 14,
+ { 410, 15, 5632, 15, 24, 23, 23, {
+ { 0, 11, 2 }, { 5, 13, 0 }, { 11, 15, 0 }, { 13, 18, -2 },
+ { 15, 19, -4 }, { 15, 19, -6 }, { 15, 19, -8 }, { 15, 20, -8 },
+ { 15, 21, -8 }, { 15, 21, -10 }, { 17, 22, -10 },
+ { 17, 22, -10 }, { 17, 23, -12 }, { 19, 23, -12 },
+ { 23, 24, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 16,
+ { 410, 15, 5632, 19, 28, 27, 27, {
+ { 0, 11, 2 }, { 6, 14, 0 }, { 13, 17, 0 }, { 16, 20, -2 },
+ { 19, 23, -4 }, { 19, 23, -6 }, { 19, 23, -8 }, { 19, 24, -8 },
+ { 19, 25, -8 }, { 19, 25, -10 }, { 21, 26, -10 },
+ { 21, 26, -10 }, { 21, 27, -12 }, { 23, 27, -12 },
+ { 27, 28, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(12), .bpc = 8,
+ { 341, 15, 2048, 3, 12, 11, 11, {
+ { 0, 2, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 1, 6, -2 },
+ { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
+ { 3, 8, -8 }, { 3, 9, -10 }, { 5, 9, -10 }, { 5, 9, -12 },
+ { 5, 9, -12 }, { 7, 10, -12 }, { 10, 11, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(12), .bpc = 10,
+ { 341, 15, 2048, 7, 16, 15, 15, {
+ { 0, 2, 2 }, { 2, 5, 0 }, { 3, 7, 0 }, { 4, 8, -2 },
+ { 6, 9, -4 }, { 7, 10, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
+ { 7, 12, -8 }, { 7, 13, -10 }, { 9, 13, -10 }, { 9, 13, -12 },
+ { 9, 13, -12 }, { 11, 14, -12 }, { 14, 15, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(12), .bpc = 12,
+ { 341, 15, 2048, 11, 20, 19, 19, {
+ { 0, 6, 2 }, { 4, 9, 0 }, { 7, 11, 0 }, { 8, 12, -2 },
+ { 10, 13, -4 }, { 11, 14, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
+ { 11, 16, -8 }, { 11, 17, -10 }, { 13, 17, -10 },
+ { 13, 17, -12 }, { 13, 17, -12 }, { 15, 18, -12 },
+ { 18, 19, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(12), .bpc = 14,
+ { 341, 15, 2048, 15, 24, 23, 23, {
+ { 0, 6, 2 }, { 7, 10, 0 }, { 9, 13, 0 }, { 11, 16, -2 },
+ { 14, 17, -4 }, { 15, 18, -6 }, { 15, 19, -8 }, { 15, 20, -8 },
+ { 15, 20, -8 }, { 15, 21, -10 }, { 17, 21, -10 },
+ { 17, 21, -12 }, { 17, 21, -12 }, { 19, 22, -12 },
+ { 22, 23, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(12), .bpc = 16,
+ { 341, 15, 2048, 19, 28, 27, 27, {
+ { 0, 6, 2 }, { 6, 11, 0 }, { 11, 15, 0 }, { 14, 18, -2 },
+ { 18, 21, -4 }, { 19, 22, -6 }, { 19, 23, -8 }, { 19, 24, -8 },
+ { 19, 24, -8 }, { 19, 25, -10 }, { 21, 25, -10 },
+ { 21, 25, -12 }, { 21, 25, -12 }, { 23, 26, -12 },
+ { 26, 27, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(15), .bpc = 8,
+ { 273, 15, 2048, 3, 12, 11, 11, {
+ { 0, 0, 10 }, { 0, 1, 8 }, { 0, 1, 6 }, { 0, 2, 4 },
+ { 1, 2, 2 }, { 1, 3, 0 }, { 1, 3, -2 }, { 2, 4, -4 },
+ { 2, 5, -6 }, { 3, 5, -8 }, { 4, 6, -10 }, { 4, 7, -10 },
+ { 5, 7, -12 }, { 7, 8, -12 }, { 8, 9, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(15), .bpc = 10,
+ { 273, 15, 2048, 7, 16, 15, 15, {
+ { 0, 2, 10 }, { 2, 5, 8 }, { 3, 5, 6 }, { 4, 6, 4 },
+ { 5, 6, 2 }, { 5, 7, 0 }, { 5, 7, -2 }, { 6, 8, -4 },
+ { 6, 9, -6 }, { 7, 9, -8 }, { 8, 10, -10 }, { 8, 11, -10 },
+ { 9, 11, -12 }, { 11, 12, -12 }, { 12, 13, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(15), .bpc = 12,
+ { 273, 15, 2048, 11, 20, 19, 19, {
+ { 0, 4, 10 }, { 2, 7, 8 }, { 4, 9, 6 }, { 6, 11, 4 },
+ { 9, 11, 2 }, { 9, 11, 0 }, { 9, 12, -2 }, { 10, 12, -4 },
+ { 11, 13, -6 }, { 11, 13, -8 }, { 12, 14, -10 },
+ { 13, 15, -10 }, { 13, 15, -12 }, { 15, 16, -12 },
+ { 16, 17, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(15), .bpc = 14,
+ { 273, 15, 2048, 15, 24, 23, 23, {
+ { 0, 4, 10 }, { 3, 8, 8 }, { 6, 11, 6 }, { 9, 14, 4 },
+ { 13, 15, 2 }, { 13, 15, 0 }, { 13, 16, -2 }, { 14, 16, -4 },
+ { 15, 17, -6 }, { 15, 17, -8 }, { 16, 18, -10 },
+ { 17, 19, -10 }, { 17, 19, -12 }, { 19, 20, -12 },
+ { 20, 21, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(15), .bpc = 16,
+ { 273, 15, 2048, 19, 28, 27, 27, {
+ { 0, 4, 10 }, { 4, 9, 8 }, { 8, 13, 6 }, { 12, 17, 4 },
+ { 17, 19, 2 }, { 17, 20, 0 }, { 17, 20, -2 }, { 18, 20, -4 },
+ { 19, 21, -6 }, { 19, 21, -8 }, { 20, 22, -10 },
+ { 21, 23, -10 }, { 21, 23, -12 }, { 23, 24, -12 },
+ { 24, 25, -12 }
+ }
+ }
+ },
+ { /* sentinel */ }
+};
+
+/*
+ * Selected Rate Control Related Parameter Recommended Values for 4:2:2 from
+ * DSC v1.2, v1.2a, v1.2b
+ *
+ * Cross-checked against C Model releases: DSC_model_20161212 and 20210623
+ */
+static const struct rc_parameters_data rc_parameters_1_2_422[] = {
+ {
+ .bpp = DSC_BPP(6), .bpc = 8,
+ { 512, 15, 6144, 3, 12, 11, 11, {
+ { 0, 4, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 1, 6, -2 },
+ { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
+ { 3, 9, -8 }, { 3, 10, -10 }, { 5, 10, -10 }, { 5, 11, -12 },
+ { 5, 11, -12 }, { 9, 12, -12 }, { 12, 13, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 10,
+ { 512, 15, 6144, 7, 16, 15, 15, {
+ { 0, 8, 2 }, { 4, 8, 0 }, { 5, 9, 0 }, { 5, 10, -2 },
+ { 7, 11, -4 }, { 7, 11, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
+ { 7, 13, -8 }, { 7, 14, -10 }, { 9, 14, -10 }, { 9, 15, -12 },
+ { 9, 15, -12 }, { 13, 16, -12 }, { 16, 17, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 12,
+ { 512, 15, 6144, 11, 20, 19, 19, {
+ { 0, 12, 2 }, { 4, 12, 0 }, { 9, 13, 0 }, { 9, 14, -2 },
+ { 11, 15, -4 }, { 11, 15, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
+ { 11, 17, -8 }, { 11, 18, -10 }, { 13, 18, -10 },
+ { 13, 19, -12 }, { 13, 19, -12 }, { 17, 20, -12 },
+ { 20, 21, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 14,
+ { 512, 15, 6144, 15, 24, 23, 23, {
+ { 0, 12, 2 }, { 5, 13, 0 }, { 11, 15, 0 }, { 12, 17, -2 },
+ { 15, 19, -4 }, { 15, 19, -6 }, { 15, 19, -8 }, { 15, 20, -8 },
+ { 15, 21, -8 }, { 15, 22, -10 }, { 17, 22, -10 },
+ { 17, 23, -12 }, { 17, 23, -12 }, { 21, 24, -12 },
+ { 24, 25, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 16,
+ { 512, 15, 6144, 19, 28, 27, 27, {
+ { 0, 12, 2 }, { 6, 14, 0 }, { 13, 17, 0 }, { 15, 20, -2 },
+ { 19, 23, -4 }, { 19, 23, -6 }, { 19, 23, -8 }, { 19, 24, -8 },
+ { 19, 25, -8 }, { 19, 26, -10 }, { 21, 26, -10 },
+ { 21, 27, -12 }, { 21, 27, -12 }, { 25, 28, -12 },
+ { 28, 29, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(7), .bpc = 8,
+ { 410, 15, 5632, 3, 12, 11, 11, {
+ { 0, 3, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 2, 6, -2 },
+ { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
+ { 3, 9, -8 }, { 3, 9, -10 }, { 5, 10, -10 }, { 5, 10, -10 },
+ { 5, 11, -12 }, { 7, 11, -12 }, { 11, 12, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(7), .bpc = 10,
+ { 410, 15, 5632, 7, 16, 15, 15, {
+ { 0, 7, 2 }, { 4, 8, 0 }, { 5, 9, 0 }, { 6, 10, -2 },
+ { 7, 11, -4 }, { 7, 11, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
+ { 7, 13, -8 }, { 7, 13, -10 }, { 9, 14, -10 }, { 9, 14, -10 },
+ { 9, 15, -12 }, { 11, 15, -12 }, { 15, 16, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(7), .bpc = 12,
+ { 410, 15, 5632, 11, 20, 19, 19, {
+ { 0, 11, 2 }, { 4, 12, 0 }, { 9, 13, 0 }, { 10, 14, -2 },
+ { 11, 15, -4 }, { 11, 15, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
+ { 11, 17, -8 }, { 11, 17, -10 }, { 13, 18, -10 },
+ { 13, 18, -10 }, { 13, 19, -12 }, { 15, 19, -12 },
+ { 19, 20, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(7), .bpc = 14,
+ { 410, 15, 5632, 15, 24, 23, 23, {
+ { 0, 11, 2 }, { 5, 13, 0 }, { 11, 15, 0 }, { 13, 18, -2 },
+ { 15, 19, -4 }, { 15, 19, -6 }, { 15, 19, -8 }, { 15, 20, -8 },
+ { 15, 21, -8 }, { 15, 21, -10 }, { 17, 22, -10 },
+ { 17, 22, -10 }, { 17, 23, -12 }, { 19, 23, -12 },
+ { 23, 24, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(7), .bpc = 16,
+ { 410, 15, 5632, 19, 28, 27, 27, {
+ { 0, 11, 2 }, { 6, 14, 0 }, { 13, 17, 0 }, { 16, 20, -2 },
+ { 19, 23, -4 }, { 19, 23, -6 }, { 19, 23, -8 }, { 19, 24, -8 },
+ { 19, 25, -8 }, { 19, 25, -10 }, { 21, 26, -10 },
+ { 21, 26, -10 }, { 21, 27, -12 }, { 23, 27, -12 },
+ { 27, 28, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 8,
+ { 341, 15, 2048, 3, 12, 11, 11, {
+ { 0, 2, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 1, 6, -2 },
+ { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
+ { 3, 8, -8 }, { 3, 9, -10 }, { 5, 9, -10 }, { 5, 9, -12 },
+ { 5, 9, -12 }, { 7, 10, -12 }, { 10, 11, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 10,
+ { 341, 15, 2048, 7, 16, 15, 15, {
+ { 0, 2, 2 }, { 2, 5, 0 }, { 3, 7, 0 }, { 4, 8, -2 },
+ { 6, 9, -4 }, { 7, 10, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
+ { 7, 12, -8 }, { 7, 13, -10 }, { 9, 13, -10 }, { 9, 13, -12 },
+ { 9, 13, -12 }, { 11, 14, -12 }, { 14, 15, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 12,
+ { 341, 15, 2048, 11, 20, 19, 19, {
+ { 0, 6, 2 }, { 4, 9, 0 }, { 7, 11, 0 }, { 8, 12, -2 },
+ { 10, 13, -4 }, { 11, 14, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
+ { 11, 16, -8 }, { 11, 17, -10 }, { 13, 17, -10 },
+ { 13, 17, -12 }, { 13, 17, -12 }, { 15, 18, -12 },
+ { 18, 19, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 14,
+ { 341, 15, 2048, 15, 24, 23, 23, {
+ { 0, 6, 2 }, { 7, 10, 0 }, { 9, 13, 0 }, { 11, 16, -2 },
+ { 14, 17, -4 }, { 15, 18, -6 }, { 15, 19, -8 }, { 15, 20, -8 },
+ { 15, 20, -8 }, { 15, 21, -10 }, { 17, 21, -10 },
+ { 17, 21, -12 }, { 17, 21, -12 }, { 19, 22, -12 },
+ { 22, 23, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 16,
+ { 341, 15, 2048, 19, 28, 27, 27, {
+ { 0, 6, 2 }, { 6, 11, 0 }, { 11, 15, 0 }, { 14, 18, -2 },
+ { 18, 21, -4 }, { 19, 22, -6 }, { 19, 23, -8 }, { 19, 24, -8 },
+ { 19, 24, -8 }, { 19, 25, -10 }, { 21, 25, -10 },
+ { 21, 25, -12 }, { 21, 25, -12 }, { 23, 26, -12 },
+ { 26, 27, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 8,
+ { 273, 15, 2048, 3, 12, 11, 11, {
+ { 0, 0, 10 }, { 0, 1, 8 }, { 0, 1, 6 }, { 0, 2, 4 },
+ { 1, 2, 2 }, { 1, 3, 0 }, { 1, 3, -2 }, { 2, 4, -4 },
+ { 2, 5, -6 }, { 3, 5, -8 }, { 4, 6, -10 }, { 4, 7, -10 },
+ { 5, 7, -12 }, { 7, 8, -12 }, { 8, 9, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 10,
+ { 273, 15, 2048, 7, 16, 15, 15, {
+ { 0, 2, 10 }, { 2, 5, 8 }, { 3, 5, 6 }, { 4, 6, 4 },
+ { 5, 6, 2 }, { 5, 7, 0 }, { 5, 7, -2 }, { 6, 8, -4 },
+ { 6, 9, -6 }, { 7, 9, -8 }, { 8, 10, -10 }, { 8, 11, -10 },
+ { 9, 11, -12 }, { 11, 12, -12 }, { 12, 13, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 12,
+ { 273, 15, 2048, 11, 20, 19, 19, {
+ { 0, 4, 10 }, { 2, 7, 8 }, { 4, 9, 6 }, { 6, 11, 4 },
+ { 9, 11, 2 }, { 9, 11, 0 }, { 9, 12, -2 }, { 10, 12, -4 },
+ { 11, 13, -6 }, { 11, 13, -8 }, { 12, 14, -10 },
+ { 13, 15, -10 }, { 13, 15, -12 }, { 15, 16, -12 },
+ { 16, 17, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 14,
+ { 273, 15, 2048, 15, 24, 23, 23, {
+ { 0, 4, 10 }, { 3, 8, 8 }, { 6, 11, 6 }, { 9, 14, 4 },
+ { 13, 15, 2 }, { 13, 15, 0 }, { 13, 16, -2 }, { 14, 16, -4 },
+ { 15, 17, -6 }, { 15, 17, -8 }, { 16, 18, -10 },
+ { 17, 19, -10 }, { 17, 19, -12 }, { 19, 20, -12 },
+ { 20, 21, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(10), .bpc = 16,
+ { 273, 15, 2048, 19, 28, 27, 27, {
+ { 0, 4, 10 }, { 4, 9, 8 }, { 8, 13, 6 }, { 12, 17, 4 },
+ { 17, 19, 2 }, { 17, 20, 0 }, { 17, 20, -2 }, { 18, 20, -4 },
+ { 19, 21, -6 }, { 19, 21, -8 }, { 20, 22, -10 },
+ { 21, 23, -10 }, { 21, 23, -12 }, { 23, 24, -12 },
+ { 24, 25, -12 }
+ }
+ }
+ },
+ { /* sentinel */ }
+};
+
+/*
+ * Selected Rate Control Related Parameter Recommended Values for 4:2:2 from
+ * DSC v1.2, v1.2a, v1.2b
+ *
+ * Cross-checked against C Model releases: DSC_model_20161212 and 20210623
+ */
+static const struct rc_parameters_data rc_parameters_1_2_420[] = {
+ {
+ .bpp = DSC_BPP(4), .bpc = 8,
+ { 512, 12, 6144, 3, 12, 11, 11, {
+ { 0, 4, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 1, 6, -2 },
+ { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
+ { 3, 9, -8 }, { 3, 10, -10 }, { 5, 10, -10 }, { 5, 11, -12 },
+ { 5, 11, -12 }, { 9, 12, -12 }, { 12, 13, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(4), .bpc = 10,
+ { 512, 12, 6144, 7, 16, 15, 15, {
+ { 0, 8, 2 }, { 4, 8, 0 }, { 5, 9, 0 }, { 5, 10, -2 },
+ { 7, 11, -4 }, { 7, 11, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
+ { 7, 13, -8 }, { 7, 14, -10 }, { 9, 14, -10 }, { 9, 15, -12 },
+ { 9, 15, -12 }, { 13, 16, -12 }, { 16, 17, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(4), .bpc = 12,
+ { 512, 12, 6144, 11, 20, 19, 19, {
+ { 0, 12, 2 }, { 4, 12, 0 }, { 9, 13, 0 }, { 9, 14, -2 },
+ { 11, 15, -4 }, { 11, 15, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
+ { 11, 17, -8 }, { 11, 18, -10 }, { 13, 18, -10 },
+ { 13, 19, -12 }, { 13, 19, -12 }, { 17, 20, -12 },
+ { 20, 21, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(4), .bpc = 14,
+ { 512, 12, 6144, 15, 24, 23, 23, {
+ { 0, 12, 2 }, { 5, 13, 0 }, { 11, 15, 0 }, { 12, 17, -2 },
+ { 15, 19, -4 }, { 15, 19, -6 }, { 15, 19, -8 }, { 15, 20, -8 },
+ { 15, 21, -8 }, { 15, 22, -10 }, { 17, 22, -10 },
+ { 17, 23, -12 }, { 17, 23, -12 }, { 21, 24, -12 },
+ { 24, 25, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(4), .bpc = 16,
+ { 512, 12, 6144, 19, 28, 27, 27, {
+ { 0, 12, 2 }, { 6, 14, 0 }, { 13, 17, 0 }, { 15, 20, -2 },
+ { 19, 23, -4 }, { 19, 23, -6 }, { 19, 23, -8 }, { 19, 24, -8 },
+ { 19, 25, -8 }, { 19, 26, -10 }, { 21, 26, -10 },
+ { 21, 27, -12 }, { 21, 27, -12 }, { 25, 28, -12 },
+ { 28, 29, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(5), .bpc = 8,
+ { 410, 15, 5632, 3, 12, 11, 11, {
+ { 0, 3, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 2, 6, -2 },
+ { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
+ { 3, 9, -8 }, { 3, 9, -10 }, { 5, 10, -10 }, { 5, 10, -10 },
+ { 5, 11, -12 }, { 7, 11, -12 }, { 11, 12, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(5), .bpc = 10,
+ { 410, 15, 5632, 7, 16, 15, 15, {
+ { 0, 7, 2 }, { 4, 8, 0 }, { 5, 9, 0 }, { 6, 10, -2 },
+ { 7, 11, -4 }, { 7, 11, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
+ { 7, 13, -8 }, { 7, 13, -10 }, { 9, 14, -10 }, { 9, 14, -10 },
+ { 9, 15, -12 }, { 11, 15, -12 }, { 15, 16, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(5), .bpc = 12,
+ { 410, 15, 5632, 11, 20, 19, 19, {
+ { 0, 11, 2 }, { 4, 12, 0 }, { 9, 13, 0 }, { 10, 14, -2 },
+ { 11, 15, -4 }, { 11, 15, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
+ { 11, 17, -8 }, { 11, 17, -10 }, { 13, 18, -10 },
+ { 13, 18, -10 }, { 13, 19, -12 }, { 15, 19, -12 },
+ { 19, 20, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(5), .bpc = 14,
+ { 410, 15, 5632, 15, 24, 23, 23, {
+ { 0, 11, 2 }, { 5, 13, 0 }, { 11, 15, 0 }, { 13, 18, -2 },
+ { 15, 19, -4 }, { 15, 19, -6 }, { 15, 19, -8 }, { 15, 20, -8 },
+ { 15, 21, -8 }, { 15, 21, -10 }, { 17, 22, -10 },
+ { 17, 22, -10 }, { 17, 23, -12 }, { 19, 23, -12 },
+ { 23, 24, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(5), .bpc = 16,
+ { 410, 15, 5632, 19, 28, 27, 27, {
+ { 0, 11, 2 }, { 6, 14, 0 }, { 13, 17, 0 }, { 16, 20, -2 },
+ { 19, 23, -4 }, { 19, 23, -6 }, { 19, 23, -8 }, { 19, 24, -8 },
+ { 19, 25, -8 }, { 19, 25, -10 }, { 21, 26, -10 },
+ { 21, 26, -10 }, { 21, 27, -12 }, { 23, 27, -12 },
+ { 27, 28, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 8,
+ { 341, 15, 2048, 3, 12, 11, 11, {
+ { 0, 2, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 1, 6, -2 },
+ { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
+ { 3, 8, -8 }, { 3, 9, -10 }, { 5, 9, -10 }, { 5, 9, -12 },
+ { 5, 9, -12 }, { 7, 10, -12 }, { 10, 12, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 10,
+ { 341, 15, 2048, 7, 16, 15, 15, {
+ { 0, 2, 2 }, { 2, 5, 0 }, { 3, 7, 0 }, { 4, 8, -2 },
+ { 6, 9, -4 }, { 7, 10, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
+ { 7, 12, -8 }, { 7, 13, -10 }, { 9, 13, -10 }, { 9, 13, -12 },
+ { 9, 13, -12 }, { 11, 14, -12 }, { 14, 15, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 12,
+ { 341, 15, 2048, 11, 20, 19, 19, {
+ { 0, 6, 2 }, { 4, 9, 0 }, { 7, 11, 0 }, { 8, 12, -2 },
+ { 10, 13, -4 }, { 11, 14, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
+ { 11, 16, -8 }, { 11, 17, -10 }, { 13, 17, -10 },
+ { 13, 17, -12 }, { 13, 17, -12 }, { 15, 18, -12 },
+ { 18, 19, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 14,
+ { 341, 15, 2048, 15, 24, 23, 23, {
+ { 0, 6, 2 }, { 7, 10, 0 }, { 9, 13, 0 }, { 11, 16, -2 },
+ { 14, 17, -4 }, { 15, 18, -6 }, { 15, 19, -8 }, { 15, 20, -8 },
+ { 15, 20, -8 }, { 15, 21, -10 }, { 17, 21, -10 },
+ { 17, 21, -12 }, { 17, 21, -12 }, { 19, 22, -12 },
+ { 22, 23, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(6), .bpc = 16,
+ { 341, 15, 2048, 19, 28, 27, 27, {
+ { 0, 6, 2 }, { 6, 11, 0 }, { 11, 15, 0 }, { 14, 18, -2 },
+ { 18, 21, -4 }, { 19, 22, -6 }, { 19, 23, -8 }, { 19, 24, -8 },
+ { 19, 24, -8 }, { 19, 25, -10 }, { 21, 25, -10 },
+ { 21, 25, -12 }, { 21, 25, -12 }, { 23, 26, -12 },
+ { 26, 27, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 8,
+ { 256, 15, 2048, 3, 12, 11, 11, {
+ { 0, 0, 10 }, { 0, 1, 8 }, { 0, 1, 6 }, { 0, 2, 4 },
+ { 1, 2, 2 }, { 1, 3, 0 }, { 1, 3, -2 }, { 2, 4, -4 },
+ { 2, 5, -6 }, { 3, 5, -8 }, { 4, 6, -10 }, { 4, 7, -10 },
+ { 5, 7, -12 }, { 7, 8, -12 }, { 8, 9, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 10,
+ { 256, 15, 2048, 7, 16, 15, 15, {
+ { 0, 2, 10 }, { 2, 5, 8 }, { 3, 5, 6 }, { 4, 6, 4 },
+ { 5, 6, 2 }, { 5, 7, 0 }, { 5, 7, -2 }, { 6, 8, -4 },
+ { 6, 9, -6 }, { 7, 9, -8 }, { 8, 10, -10 }, { 8, 11, -10 },
+ { 9, 11, -12 }, { 11, 12, -12 }, { 12, 13, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 12,
+ { 256, 15, 2048, 11, 20, 19, 19, {
+ { 0, 4, 10 }, { 2, 7, 8 }, { 4, 9, 6 }, { 6, 11, 4 },
+ { 9, 11, 2 }, { 9, 11, 0 }, { 9, 12, -2 }, { 10, 12, -4 },
+ { 11, 13, -6 }, { 11, 13, -8 }, { 12, 14, -10 },
+ { 13, 15, -10 }, { 13, 15, -12 }, { 15, 16, -12 },
+ { 16, 17, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 14,
+ { 256, 15, 2048, 15, 24, 23, 23, {
+ { 0, 4, 10 }, { 3, 8, 8 }, { 6, 11, 6 }, { 9, 14, 4 },
+ { 13, 15, 2 }, { 13, 15, 0 }, { 13, 16, -2 }, { 14, 16, -4 },
+ { 15, 17, -6 }, { 15, 17, -8 }, { 16, 18, -10 },
+ { 17, 19, -10 }, { 17, 19, -12 }, { 19, 20, -12 },
+ { 20, 21, -12 }
+ }
+ }
+ },
+ {
+ .bpp = DSC_BPP(8), .bpc = 16,
+ { 256, 15, 2048, 19, 28, 27, 27, {
+ { 0, 4, 10 }, { 4, 9, 8 }, { 8, 13, 6 }, { 12, 17, 4 },
+ { 17, 19, 2 }, { 17, 20, 0 }, { 17, 20, -2 }, { 18, 20, -4 },
+ { 19, 21, -6 }, { 19, 21, -8 }, { 20, 22, -10 },
+ { 21, 23, -10 }, { 21, 23, -12 }, { 23, 24, -12 },
+ { 24, 25, -12 }
+ }
+ }
+ },
+ { /* sentinel */ }
+};
+
+static const struct rc_parameters *get_rc_params(const struct rc_parameters_data *rc_parameters,
+ u16 dsc_bpp,
+ u8 bits_per_component)
+{
+ int i;
+
+ for (i = 0; rc_parameters[i].bpp; i++)
+ if (rc_parameters[i].bpp == dsc_bpp &&
+ rc_parameters[i].bpc == bits_per_component)
+ return &rc_parameters[i].params;
+
+ return NULL;
+}
+
+/**
+ * drm_dsc_setup_rc_params() - Set parameters and limits for RC model in
+ * accordance with the DSC 1.1 or 1.2 specification and DSC C Model
+ * Required bits_per_pixel and bits_per_component to be set before calling this
+ * function.
+ *
+ * @vdsc_cfg: DSC Configuration data partially filled by driver
+ * @type: operating mode and standard to follow
+ *
+ * Return: 0 or -error code in case of an error
+ */
+int drm_dsc_setup_rc_params(struct drm_dsc_config *vdsc_cfg, enum drm_dsc_params_type type)
+{
+ const struct rc_parameters_data *data;
+ const struct rc_parameters *rc_params;
+ int i;
+
+ if (WARN_ON_ONCE(!vdsc_cfg->bits_per_pixel ||
+ !vdsc_cfg->bits_per_component))
+ return -EINVAL;
+
+ switch (type) {
+ case DRM_DSC_1_2_444:
+ data = rc_parameters_1_2_444;
+ break;
+ case DRM_DSC_1_1_PRE_SCR:
+ data = rc_parameters_pre_scr;
+ break;
+ case DRM_DSC_1_2_422:
+ data = rc_parameters_1_2_422;
+ break;
+ case DRM_DSC_1_2_420:
+ data = rc_parameters_1_2_420;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ rc_params = get_rc_params(data,
+ vdsc_cfg->bits_per_pixel,
+ vdsc_cfg->bits_per_component);
+ if (!rc_params)
+ return -EINVAL;
+
+ vdsc_cfg->first_line_bpg_offset = rc_params->first_line_bpg_offset;
+ vdsc_cfg->initial_xmit_delay = rc_params->initial_xmit_delay;
+ vdsc_cfg->initial_offset = rc_params->initial_offset;
+ vdsc_cfg->flatness_min_qp = rc_params->flatness_min_qp;
+ vdsc_cfg->flatness_max_qp = rc_params->flatness_max_qp;
+ vdsc_cfg->rc_quant_incr_limit0 = rc_params->rc_quant_incr_limit0;
+ vdsc_cfg->rc_quant_incr_limit1 = rc_params->rc_quant_incr_limit1;
+
+ for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
+ vdsc_cfg->rc_range_params[i].range_min_qp =
+ rc_params->rc_range_params[i].range_min_qp;
+ vdsc_cfg->rc_range_params[i].range_max_qp =
+ rc_params->rc_range_params[i].range_max_qp;
+ /*
+ * Range BPG Offset uses 2's complement and is only a 6 bits. So
+ * mask it to get only 6 bits.
+ */
+ vdsc_cfg->rc_range_params[i].range_bpg_offset =
+ rc_params->rc_range_params[i].range_bpg_offset &
+ DSC_RANGE_BPG_OFFSET_MASK;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_dsc_setup_rc_params);
+
+/**
* drm_dsc_compute_rc_parameters() - Write rate control
* parameters to the dsc configuration defined in
* &struct drm_dsc_config in accordance with the DSC 1.2
@@ -407,3 +1435,40 @@ int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg)
return 0;
}
EXPORT_SYMBOL(drm_dsc_compute_rc_parameters);
+
+/**
+ * drm_dsc_get_bpp_int() - Get integer bits per pixel value for the given DRM DSC config
+ * @vdsc_cfg: Pointer to DRM DSC config struct
+ *
+ * Return: Integer BPP value
+ */
+u32 drm_dsc_get_bpp_int(const struct drm_dsc_config *vdsc_cfg)
+{
+ WARN_ON_ONCE(vdsc_cfg->bits_per_pixel & 0xf);
+ return vdsc_cfg->bits_per_pixel >> 4;
+}
+EXPORT_SYMBOL(drm_dsc_get_bpp_int);
+
+/**
+ * drm_dsc_initial_scale_value() - Calculate the initial scale value for the given DSC config
+ * @dsc: Pointer to DRM DSC config struct
+ *
+ * Return: Calculated initial scale value
+ */
+u8 drm_dsc_initial_scale_value(const struct drm_dsc_config *dsc)
+{
+ return 8 * dsc->rc_model_size / (dsc->rc_model_size - dsc->initial_offset);
+}
+EXPORT_SYMBOL(drm_dsc_initial_scale_value);
+
+/**
+ * drm_dsc_flatness_det_thresh() - Calculate the flatness_det_thresh for the given DSC config
+ * @dsc: Pointer to DRM DSC config struct
+ *
+ * Return: Calculated flatness det thresh value
+ */
+u32 drm_dsc_flatness_det_thresh(const struct drm_dsc_config *dsc)
+{
+ return 2 << (dsc->bits_per_component - 8);
+}
+EXPORT_SYMBOL(drm_dsc_flatness_det_thresh);
diff --git a/drivers/gpu/drm/drm_aperture.c b/drivers/gpu/drm/drm_aperture.c
index 3b8fdeeafd53..5729f3bb4398 100644
--- a/drivers/gpu/drm/drm_aperture.c
+++ b/drivers/gpu/drm/drm_aperture.c
@@ -32,17 +32,13 @@
*
* static int remove_conflicting_framebuffers(struct pci_dev *pdev)
* {
- * bool primary = false;
* resource_size_t base, size;
* int ret;
*
* base = pci_resource_start(pdev, 0);
* size = pci_resource_len(pdev, 0);
- * #ifdef CONFIG_X86
- * primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
- * #endif
*
- * return drm_aperture_remove_conflicting_framebuffers(base, size, primary,
+ * return drm_aperture_remove_conflicting_framebuffers(base, size,
* &example_driver);
* }
*
@@ -161,7 +157,6 @@ EXPORT_SYMBOL(devm_aperture_acquire_from_firmware);
* drm_aperture_remove_conflicting_framebuffers - remove existing framebuffers in the given range
* @base: the aperture's base address in physical memory
* @size: aperture size in bytes
- * @primary: also kick vga16fb if present
* @req_driver: requesting DRM driver
*
* This function removes graphics device drivers which use the memory range described by
@@ -171,9 +166,9 @@ EXPORT_SYMBOL(devm_aperture_acquire_from_firmware);
* 0 on success, or a negative errno code otherwise
*/
int drm_aperture_remove_conflicting_framebuffers(resource_size_t base, resource_size_t size,
- bool primary, const struct drm_driver *req_driver)
+ const struct drm_driver *req_driver)
{
- return aperture_remove_conflicting_devices(base, size, primary, req_driver->name);
+ return aperture_remove_conflicting_devices(base, size, req_driver->name);
}
EXPORT_SYMBOL(drm_aperture_remove_conflicting_framebuffers);
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index b4c6ffc438da..2c454568a607 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1131,6 +1131,7 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
drm_printf(p, "\tself_refresh_aware=%d\n", state->self_refresh_aware);
drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc);
+ drm_printf(p, "\tcolorspace=%s\n", drm_get_colorspace_name(state->colorspace));
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
if (state->writeback_job && state->writeback_job->fb)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 2c2c9caf0be5..41b8066f61ff 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1209,7 +1209,16 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
continue;
ret = drm_crtc_vblank_get(crtc);
- WARN_ONCE(ret != -EINVAL, "driver forgot to call drm_crtc_vblank_off()\n");
+ /*
+ * Self-refresh is not a true "disable"; ensure vblank remains
+ * enabled.
+ */
+ if (new_crtc_state->self_refresh_active)
+ WARN_ONCE(ret != 0,
+ "driver disabled vblank in self-refresh\n");
+ else
+ WARN_ONCE(ret != -EINVAL,
+ "driver forgot to call drm_crtc_vblank_off()\n");
if (ret == 0)
drm_crtc_vblank_put(crtc);
}
@@ -3145,7 +3154,7 @@ fail:
EXPORT_SYMBOL(drm_atomic_helper_update_plane);
/**
- * drm_atomic_helper_disable_plane - Helper for primary plane disable using * atomic
+ * drm_atomic_helper_disable_plane - Helper for primary plane disable using atomic
* @plane: plane to disable
* @ctx: lock acquire context
*
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 48df7a5ea503..3ed4cfcb350c 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1055,64 +1055,85 @@ static const struct drm_prop_enum_list drm_dp_subconnector_enum_list[] = {
DRM_ENUM_NAME_FN(drm_get_dp_subconnector_name,
drm_dp_subconnector_enum_list)
-static const struct drm_prop_enum_list hdmi_colorspaces[] = {
+
+static const char * const colorspace_names[] = {
/* For Default case, driver will set the colorspace */
- { DRM_MODE_COLORIMETRY_DEFAULT, "Default" },
+ [DRM_MODE_COLORIMETRY_DEFAULT] = "Default",
/* Standard Definition Colorimetry based on CEA 861 */
- { DRM_MODE_COLORIMETRY_SMPTE_170M_YCC, "SMPTE_170M_YCC" },
- { DRM_MODE_COLORIMETRY_BT709_YCC, "BT709_YCC" },
+ [DRM_MODE_COLORIMETRY_SMPTE_170M_YCC] = "SMPTE_170M_YCC",
+ [DRM_MODE_COLORIMETRY_BT709_YCC] = "BT709_YCC",
/* Standard Definition Colorimetry based on IEC 61966-2-4 */
- { DRM_MODE_COLORIMETRY_XVYCC_601, "XVYCC_601" },
+ [DRM_MODE_COLORIMETRY_XVYCC_601] = "XVYCC_601",
/* High Definition Colorimetry based on IEC 61966-2-4 */
- { DRM_MODE_COLORIMETRY_XVYCC_709, "XVYCC_709" },
+ [DRM_MODE_COLORIMETRY_XVYCC_709] = "XVYCC_709",
/* Colorimetry based on IEC 61966-2-1/Amendment 1 */
- { DRM_MODE_COLORIMETRY_SYCC_601, "SYCC_601" },
+ [DRM_MODE_COLORIMETRY_SYCC_601] = "SYCC_601",
/* Colorimetry based on IEC 61966-2-5 [33] */
- { DRM_MODE_COLORIMETRY_OPYCC_601, "opYCC_601" },
+ [DRM_MODE_COLORIMETRY_OPYCC_601] = "opYCC_601",
/* Colorimetry based on IEC 61966-2-5 */
- { DRM_MODE_COLORIMETRY_OPRGB, "opRGB" },
+ [DRM_MODE_COLORIMETRY_OPRGB] = "opRGB",
/* Colorimetry based on ITU-R BT.2020 */
- { DRM_MODE_COLORIMETRY_BT2020_CYCC, "BT2020_CYCC" },
+ [DRM_MODE_COLORIMETRY_BT2020_CYCC] = "BT2020_CYCC",
/* Colorimetry based on ITU-R BT.2020 */
- { DRM_MODE_COLORIMETRY_BT2020_RGB, "BT2020_RGB" },
+ [DRM_MODE_COLORIMETRY_BT2020_RGB] = "BT2020_RGB",
/* Colorimetry based on ITU-R BT.2020 */
- { DRM_MODE_COLORIMETRY_BT2020_YCC, "BT2020_YCC" },
+ [DRM_MODE_COLORIMETRY_BT2020_YCC] = "BT2020_YCC",
/* Added as part of Additional Colorimetry Extension in 861.G */
- { DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65, "DCI-P3_RGB_D65" },
- { DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER, "DCI-P3_RGB_Theater" },
+ [DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65] = "DCI-P3_RGB_D65",
+ [DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER] = "DCI-P3_RGB_Theater",
+ [DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED] = "RGB_WIDE_FIXED",
+ /* Colorimetry based on scRGB (IEC 61966-2-2) */
+ [DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT] = "RGB_WIDE_FLOAT",
+ [DRM_MODE_COLORIMETRY_BT601_YCC] = "BT601_YCC",
};
+/**
+ * drm_get_colorspace_name - return a string for color encoding
+ * @colorspace: color space to compute name of
+ *
+ * In contrast to the other drm_get_*_name functions this one here returns a
+ * const pointer and hence is threadsafe.
+ */
+const char *drm_get_colorspace_name(enum drm_colorspace colorspace)
+{
+ if (colorspace < ARRAY_SIZE(colorspace_names) && colorspace_names[colorspace])
+ return colorspace_names[colorspace];
+ else
+ return "(null)";
+}
+
+static const u32 hdmi_colorspaces =
+ BIT(DRM_MODE_COLORIMETRY_SMPTE_170M_YCC) |
+ BIT(DRM_MODE_COLORIMETRY_BT709_YCC) |
+ BIT(DRM_MODE_COLORIMETRY_XVYCC_601) |
+ BIT(DRM_MODE_COLORIMETRY_XVYCC_709) |
+ BIT(DRM_MODE_COLORIMETRY_SYCC_601) |
+ BIT(DRM_MODE_COLORIMETRY_OPYCC_601) |
+ BIT(DRM_MODE_COLORIMETRY_OPRGB) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_CYCC) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_RGB) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_YCC) |
+ BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65) |
+ BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER);
+
/*
* As per DP 1.4a spec, 2.2.5.7.5 VSC SDP Payload for Pixel Encoding/Colorimetry
* Format Table 2-120
*/
-static const struct drm_prop_enum_list dp_colorspaces[] = {
- /* For Default case, driver will set the colorspace */
- { DRM_MODE_COLORIMETRY_DEFAULT, "Default" },
- { DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED, "RGB_Wide_Gamut_Fixed_Point" },
- /* Colorimetry based on scRGB (IEC 61966-2-2) */
- { DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT, "RGB_Wide_Gamut_Floating_Point" },
- /* Colorimetry based on IEC 61966-2-5 */
- { DRM_MODE_COLORIMETRY_OPRGB, "opRGB" },
- /* Colorimetry based on SMPTE RP 431-2 */
- { DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65, "DCI-P3_RGB_D65" },
- /* Colorimetry based on ITU-R BT.2020 */
- { DRM_MODE_COLORIMETRY_BT2020_RGB, "BT2020_RGB" },
- { DRM_MODE_COLORIMETRY_BT601_YCC, "BT601_YCC" },
- { DRM_MODE_COLORIMETRY_BT709_YCC, "BT709_YCC" },
- /* Standard Definition Colorimetry based on IEC 61966-2-4 */
- { DRM_MODE_COLORIMETRY_XVYCC_601, "XVYCC_601" },
- /* High Definition Colorimetry based on IEC 61966-2-4 */
- { DRM_MODE_COLORIMETRY_XVYCC_709, "XVYCC_709" },
- /* Colorimetry based on IEC 61966-2-1/Amendment 1 */
- { DRM_MODE_COLORIMETRY_SYCC_601, "SYCC_601" },
- /* Colorimetry based on IEC 61966-2-5 [33] */
- { DRM_MODE_COLORIMETRY_OPYCC_601, "opYCC_601" },
- /* Colorimetry based on ITU-R BT.2020 */
- { DRM_MODE_COLORIMETRY_BT2020_CYCC, "BT2020_CYCC" },
- /* Colorimetry based on ITU-R BT.2020 */
- { DRM_MODE_COLORIMETRY_BT2020_YCC, "BT2020_YCC" },
-};
+static const u32 dp_colorspaces =
+ BIT(DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED) |
+ BIT(DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT) |
+ BIT(DRM_MODE_COLORIMETRY_OPRGB) |
+ BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_RGB) |
+ BIT(DRM_MODE_COLORIMETRY_BT601_YCC) |
+ BIT(DRM_MODE_COLORIMETRY_BT709_YCC) |
+ BIT(DRM_MODE_COLORIMETRY_XVYCC_601) |
+ BIT(DRM_MODE_COLORIMETRY_XVYCC_709) |
+ BIT(DRM_MODE_COLORIMETRY_SYCC_601) |
+ BIT(DRM_MODE_COLORIMETRY_OPYCC_601) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_CYCC) |
+ BIT(DRM_MODE_COLORIMETRY_BT2020_YCC);
/**
* DOC: standard connector properties
@@ -2135,33 +2156,72 @@ EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
* drm_mode_create_dp_colorspace_property() is used for DP connector.
*/
-/**
- * drm_mode_create_hdmi_colorspace_property - create hdmi colorspace property
- * @connector: connector to create the Colorspace property on.
- *
- * Called by a driver the first time it's needed, must be attached to desired
- * HDMI connectors.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector)
+static int drm_mode_create_colorspace_property(struct drm_connector *connector,
+ u32 supported_colorspaces)
{
struct drm_device *dev = connector->dev;
+ u32 colorspaces = supported_colorspaces | BIT(DRM_MODE_COLORIMETRY_DEFAULT);
+ struct drm_prop_enum_list enum_list[DRM_MODE_COLORIMETRY_COUNT];
+ int i, len;
if (connector->colorspace_property)
return 0;
+ if (!supported_colorspaces) {
+ drm_err(dev, "No supported colorspaces provded on [CONNECTOR:%d:%s]\n",
+ connector->base.id, connector->name);
+ return -EINVAL;
+ }
+
+ if ((supported_colorspaces & -BIT(DRM_MODE_COLORIMETRY_COUNT)) != 0) {
+ drm_err(dev, "Unknown colorspace provded on [CONNECTOR:%d:%s]\n",
+ connector->base.id, connector->name);
+ return -EINVAL;
+ }
+
+ len = 0;
+ for (i = 0; i < DRM_MODE_COLORIMETRY_COUNT; i++) {
+ if ((colorspaces & BIT(i)) == 0)
+ continue;
+
+ enum_list[len].type = i;
+ enum_list[len].name = colorspace_names[i];
+ len++;
+ }
+
connector->colorspace_property =
drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "Colorspace",
- hdmi_colorspaces,
- ARRAY_SIZE(hdmi_colorspaces));
+ enum_list,
+ len);
if (!connector->colorspace_property)
return -ENOMEM;
return 0;
}
+
+/**
+ * drm_mode_create_hdmi_colorspace_property - create hdmi colorspace property
+ * @connector: connector to create the Colorspace property on.
+ *
+ * Called by a driver the first time it's needed, must be attached to desired
+ * HDMI connectors.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector,
+ u32 supported_colorspaces)
+{
+ u32 colorspaces;
+
+ if (supported_colorspaces)
+ colorspaces = supported_colorspaces & hdmi_colorspaces;
+ else
+ colorspaces = hdmi_colorspaces;
+
+ return drm_mode_create_colorspace_property(connector, colorspaces);
+}
EXPORT_SYMBOL(drm_mode_create_hdmi_colorspace_property);
/**
@@ -2174,22 +2234,17 @@ EXPORT_SYMBOL(drm_mode_create_hdmi_colorspace_property);
* Returns:
* Zero on success, negative errno on failure.
*/
-int drm_mode_create_dp_colorspace_property(struct drm_connector *connector)
+int drm_mode_create_dp_colorspace_property(struct drm_connector *connector,
+ u32 supported_colorspaces)
{
- struct drm_device *dev = connector->dev;
+ u32 colorspaces;
- if (connector->colorspace_property)
- return 0;
-
- connector->colorspace_property =
- drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "Colorspace",
- dp_colorspaces,
- ARRAY_SIZE(dp_colorspaces));
-
- if (!connector->colorspace_property)
- return -ENOMEM;
+ if (supported_colorspaces)
+ colorspaces = supported_colorspaces & dp_colorspaces;
+ else
+ colorspaces = dp_colorspaces;
- return 0;
+ return drm_mode_create_colorspace_property(connector, colorspaces);
}
EXPORT_SYMBOL(drm_mode_create_dp_colorspace_property);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index cee0cc522ed9..12687dd9e1ac 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -969,7 +969,9 @@ EXPORT_SYMBOL(drm_dev_register);
*
* Unregister the DRM device from the system. This does the reverse of
* drm_dev_register() but does not deallocate the device. The caller must call
- * drm_dev_put() to drop their final reference.
+ * drm_dev_put() to drop their final reference, unless it is managed with devres
+ * (as devices allocated with devm_drm_dev_alloc() are), in which case there is
+ * already an unwind action registered.
*
* A special form of unregistering for hotpluggable devices is drm_dev_unplug(),
* which can be called while there are still open users of @dev.
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 0454da505687..e0dbd9140726 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2845,6 +2845,35 @@ struct edid *drm_get_edid_switcheroo(struct drm_connector *connector,
EXPORT_SYMBOL(drm_get_edid_switcheroo);
/**
+ * drm_edid_read_switcheroo - get EDID data for a vga_switcheroo output
+ * @connector: connector we're probing
+ * @adapter: I2C adapter to use for DDC
+ *
+ * Wrapper around drm_edid_read_ddc() for laptops with dual GPUs using one set
+ * of outputs. The wrapper adds the requisite vga_switcheroo calls to
+ * temporarily switch DDC to the GPU which is retrieving EDID.
+ *
+ * Return: Pointer to valid EDID or %NULL if we couldn't find any.
+ */
+const struct drm_edid *drm_edid_read_switcheroo(struct drm_connector *connector,
+ struct i2c_adapter *adapter)
+{
+ struct drm_device *dev = connector->dev;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+ const struct drm_edid *drm_edid;
+
+ if (drm_WARN_ON_ONCE(dev, !dev_is_pci(dev->dev)))
+ return NULL;
+
+ vga_switcheroo_lock_ddc(pdev);
+ drm_edid = drm_edid_read_ddc(connector, adapter);
+ vga_switcheroo_unlock_ddc(pdev);
+
+ return drm_edid;
+}
+EXPORT_SYMBOL(drm_edid_read_switcheroo);
+
+/**
* drm_edid_duplicate - duplicate an EDID and the extensions
* @edid: EDID to duplicate
*
@@ -2852,6 +2881,9 @@ EXPORT_SYMBOL(drm_get_edid_switcheroo);
*/
struct edid *drm_edid_duplicate(const struct edid *edid)
{
+ if (!edid)
+ return NULL;
+
return kmemdup(edid, edid_size(edid), GFP_KERNEL);
}
EXPORT_SYMBOL(drm_edid_duplicate);
@@ -6243,6 +6275,9 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
info->color_formats |= DRM_COLOR_FORMAT_YCBCR444;
if (edid_ext[3] & EDID_CEA_YCRCB422)
info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
+ if (edid_ext[3] & EDID_BASIC_AUDIO)
+ info->has_audio = true;
+
}
drm_edid_iter_end(&edid_iter);
@@ -6268,6 +6303,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
drm_parse_hdr_metadata_block(connector, data);
else if (cea_db_tag(db) == CTA_DB_VIDEO)
parse_cta_vdb(connector, db);
+ else if (cea_db_tag(db) == CTA_DB_AUDIO)
+ info->has_audio = true;
}
cea_db_iter_end(&iter);
@@ -6424,6 +6461,7 @@ static void drm_reset_display_info(struct drm_connector *connector)
info->max_tmds_clock = 0;
info->dvi_dual = false;
info->is_hdmi = false;
+ info->has_audio = false;
info->has_hdmi_infoframe = false;
info->rgb_quant_range_selectable = false;
memset(&info->hdmi, 0, sizeof(info->hdmi));
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index fd27f1978635..61a5d450cc20 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -670,6 +670,28 @@ static void drm_fb_helper_memory_range_to_clip(struct fb_info *info, off_t off,
drm_rect_init(clip, x1, y1, x2 - x1, y2 - y1);
}
+/* Don't use in new code. */
+void drm_fb_helper_damage_range(struct fb_info *info, off_t off, size_t len)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct drm_rect damage_area;
+
+ drm_fb_helper_memory_range_to_clip(info, off, len, &damage_area);
+ drm_fb_helper_damage(fb_helper, damage_area.x1, damage_area.y1,
+ drm_rect_width(&damage_area),
+ drm_rect_height(&damage_area));
+}
+EXPORT_SYMBOL(drm_fb_helper_damage_range);
+
+/* Don't use in new code. */
+void drm_fb_helper_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ drm_fb_helper_damage(fb_helper, x, y, width, height);
+}
+EXPORT_SYMBOL(drm_fb_helper_damage_area);
+
/**
* drm_fb_helper_deferred_io() - fbdev deferred_io callback function
* @info: fb_info struct pointer
@@ -714,386 +736,6 @@ void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagerefli
}
EXPORT_SYMBOL(drm_fb_helper_deferred_io);
-typedef ssize_t (*drm_fb_helper_read_screen)(struct fb_info *info, char __user *buf,
- size_t count, loff_t pos);
-
-static ssize_t __drm_fb_helper_read(struct fb_info *info, char __user *buf, size_t count,
- loff_t *ppos, drm_fb_helper_read_screen read_screen)
-{
- loff_t pos = *ppos;
- size_t total_size;
- ssize_t ret;
-
- if (info->screen_size)
- total_size = info->screen_size;
- else
- total_size = info->fix.smem_len;
-
- if (pos >= total_size)
- return 0;
- if (count >= total_size)
- count = total_size;
- if (total_size - count < pos)
- count = total_size - pos;
-
- if (info->fbops->fb_sync)
- info->fbops->fb_sync(info);
-
- ret = read_screen(info, buf, count, pos);
- if (ret > 0)
- *ppos += ret;
-
- return ret;
-}
-
-typedef ssize_t (*drm_fb_helper_write_screen)(struct fb_info *info, const char __user *buf,
- size_t count, loff_t pos);
-
-static ssize_t __drm_fb_helper_write(struct fb_info *info, const char __user *buf, size_t count,
- loff_t *ppos, drm_fb_helper_write_screen write_screen)
-{
- loff_t pos = *ppos;
- size_t total_size;
- ssize_t ret;
- int err = 0;
-
- if (info->screen_size)
- total_size = info->screen_size;
- else
- total_size = info->fix.smem_len;
-
- if (pos > total_size)
- return -EFBIG;
- if (count > total_size) {
- err = -EFBIG;
- count = total_size;
- }
- if (total_size - count < pos) {
- if (!err)
- err = -ENOSPC;
- count = total_size - pos;
- }
-
- if (info->fbops->fb_sync)
- info->fbops->fb_sync(info);
-
- /*
- * Copy to framebuffer even if we already logged an error. Emulates
- * the behavior of the original fbdev implementation.
- */
- ret = write_screen(info, buf, count, pos);
- if (ret < 0)
- return ret; /* return last error, if any */
- else if (!ret)
- return err; /* return previous error, if any */
-
- *ppos += ret;
-
- return ret;
-}
-
-static ssize_t drm_fb_helper_read_screen_buffer(struct fb_info *info, char __user *buf,
- size_t count, loff_t pos)
-{
- const char *src = info->screen_buffer + pos;
-
- if (copy_to_user(buf, src, count))
- return -EFAULT;
-
- return count;
-}
-
-/**
- * drm_fb_helper_sys_read - Implements struct &fb_ops.fb_read for system memory
- * @info: fb_info struct pointer
- * @buf: userspace buffer to read from framebuffer memory
- * @count: number of bytes to read from framebuffer memory
- * @ppos: read offset within framebuffer memory
- *
- * Returns:
- * The number of bytes read on success, or an error code otherwise.
- */
-ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
- size_t count, loff_t *ppos)
-{
- return __drm_fb_helper_read(info, buf, count, ppos, drm_fb_helper_read_screen_buffer);
-}
-EXPORT_SYMBOL(drm_fb_helper_sys_read);
-
-static ssize_t drm_fb_helper_write_screen_buffer(struct fb_info *info, const char __user *buf,
- size_t count, loff_t pos)
-{
- char *dst = info->screen_buffer + pos;
-
- if (copy_from_user(dst, buf, count))
- return -EFAULT;
-
- return count;
-}
-
-/**
- * drm_fb_helper_sys_write - Implements struct &fb_ops.fb_write for system memory
- * @info: fb_info struct pointer
- * @buf: userspace buffer to write to framebuffer memory
- * @count: number of bytes to write to framebuffer memory
- * @ppos: write offset within framebuffer memory
- *
- * Returns:
- * The number of bytes written on success, or an error code otherwise.
- */
-ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct drm_fb_helper *helper = info->par;
- loff_t pos = *ppos;
- ssize_t ret;
- struct drm_rect damage_area;
-
- ret = __drm_fb_helper_write(info, buf, count, ppos, drm_fb_helper_write_screen_buffer);
- if (ret <= 0)
- return ret;
-
- if (helper->funcs->fb_dirty) {
- drm_fb_helper_memory_range_to_clip(info, pos, ret, &damage_area);
- drm_fb_helper_damage(helper, damage_area.x1, damage_area.y1,
- drm_rect_width(&damage_area),
- drm_rect_height(&damage_area));
- }
-
- return ret;
-}
-EXPORT_SYMBOL(drm_fb_helper_sys_write);
-
-/**
- * drm_fb_helper_sys_fillrect - wrapper around sys_fillrect
- * @info: fbdev registered by the helper
- * @rect: info about rectangle to fill
- *
- * A wrapper around sys_fillrect implemented by fbdev core
- */
-void drm_fb_helper_sys_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect)
-{
- struct drm_fb_helper *helper = info->par;
-
- sys_fillrect(info, rect);
-
- if (helper->funcs->fb_dirty)
- drm_fb_helper_damage(helper, rect->dx, rect->dy, rect->width, rect->height);
-}
-EXPORT_SYMBOL(drm_fb_helper_sys_fillrect);
-
-/**
- * drm_fb_helper_sys_copyarea - wrapper around sys_copyarea
- * @info: fbdev registered by the helper
- * @area: info about area to copy
- *
- * A wrapper around sys_copyarea implemented by fbdev core
- */
-void drm_fb_helper_sys_copyarea(struct fb_info *info,
- const struct fb_copyarea *area)
-{
- struct drm_fb_helper *helper = info->par;
-
- sys_copyarea(info, area);
-
- if (helper->funcs->fb_dirty)
- drm_fb_helper_damage(helper, area->dx, area->dy, area->width, area->height);
-}
-EXPORT_SYMBOL(drm_fb_helper_sys_copyarea);
-
-/**
- * drm_fb_helper_sys_imageblit - wrapper around sys_imageblit
- * @info: fbdev registered by the helper
- * @image: info about image to blit
- *
- * A wrapper around sys_imageblit implemented by fbdev core
- */
-void drm_fb_helper_sys_imageblit(struct fb_info *info,
- const struct fb_image *image)
-{
- struct drm_fb_helper *helper = info->par;
-
- sys_imageblit(info, image);
-
- if (helper->funcs->fb_dirty)
- drm_fb_helper_damage(helper, image->dx, image->dy, image->width, image->height);
-}
-EXPORT_SYMBOL(drm_fb_helper_sys_imageblit);
-
-static ssize_t fb_read_screen_base(struct fb_info *info, char __user *buf, size_t count,
- loff_t pos)
-{
- const char __iomem *src = info->screen_base + pos;
- size_t alloc_size = min_t(size_t, count, PAGE_SIZE);
- ssize_t ret = 0;
- int err = 0;
- char *tmp;
-
- tmp = kmalloc(alloc_size, GFP_KERNEL);
- if (!tmp)
- return -ENOMEM;
-
- while (count) {
- size_t c = min_t(size_t, count, alloc_size);
-
- memcpy_fromio(tmp, src, c);
- if (copy_to_user(buf, tmp, c)) {
- err = -EFAULT;
- break;
- }
-
- src += c;
- buf += c;
- ret += c;
- count -= c;
- }
-
- kfree(tmp);
-
- return ret ? ret : err;
-}
-
-/**
- * drm_fb_helper_cfb_read - Implements struct &fb_ops.fb_read for I/O memory
- * @info: fb_info struct pointer
- * @buf: userspace buffer to read from framebuffer memory
- * @count: number of bytes to read from framebuffer memory
- * @ppos: read offset within framebuffer memory
- *
- * Returns:
- * The number of bytes read on success, or an error code otherwise.
- */
-ssize_t drm_fb_helper_cfb_read(struct fb_info *info, char __user *buf,
- size_t count, loff_t *ppos)
-{
- return __drm_fb_helper_read(info, buf, count, ppos, fb_read_screen_base);
-}
-EXPORT_SYMBOL(drm_fb_helper_cfb_read);
-
-static ssize_t fb_write_screen_base(struct fb_info *info, const char __user *buf, size_t count,
- loff_t pos)
-{
- char __iomem *dst = info->screen_base + pos;
- size_t alloc_size = min_t(size_t, count, PAGE_SIZE);
- ssize_t ret = 0;
- int err = 0;
- u8 *tmp;
-
- tmp = kmalloc(alloc_size, GFP_KERNEL);
- if (!tmp)
- return -ENOMEM;
-
- while (count) {
- size_t c = min_t(size_t, count, alloc_size);
-
- if (copy_from_user(tmp, buf, c)) {
- err = -EFAULT;
- break;
- }
- memcpy_toio(dst, tmp, c);
-
- dst += c;
- buf += c;
- ret += c;
- count -= c;
- }
-
- kfree(tmp);
-
- return ret ? ret : err;
-}
-
-/**
- * drm_fb_helper_cfb_write - Implements struct &fb_ops.fb_write for I/O memory
- * @info: fb_info struct pointer
- * @buf: userspace buffer to write to framebuffer memory
- * @count: number of bytes to write to framebuffer memory
- * @ppos: write offset within framebuffer memory
- *
- * Returns:
- * The number of bytes written on success, or an error code otherwise.
- */
-ssize_t drm_fb_helper_cfb_write(struct fb_info *info, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct drm_fb_helper *helper = info->par;
- loff_t pos = *ppos;
- ssize_t ret;
- struct drm_rect damage_area;
-
- ret = __drm_fb_helper_write(info, buf, count, ppos, fb_write_screen_base);
- if (ret <= 0)
- return ret;
-
- if (helper->funcs->fb_dirty) {
- drm_fb_helper_memory_range_to_clip(info, pos, ret, &damage_area);
- drm_fb_helper_damage(helper, damage_area.x1, damage_area.y1,
- drm_rect_width(&damage_area),
- drm_rect_height(&damage_area));
- }
-
- return ret;
-}
-EXPORT_SYMBOL(drm_fb_helper_cfb_write);
-
-/**
- * drm_fb_helper_cfb_fillrect - wrapper around cfb_fillrect
- * @info: fbdev registered by the helper
- * @rect: info about rectangle to fill
- *
- * A wrapper around cfb_fillrect implemented by fbdev core
- */
-void drm_fb_helper_cfb_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect)
-{
- struct drm_fb_helper *helper = info->par;
-
- cfb_fillrect(info, rect);
-
- if (helper->funcs->fb_dirty)
- drm_fb_helper_damage(helper, rect->dx, rect->dy, rect->width, rect->height);
-}
-EXPORT_SYMBOL(drm_fb_helper_cfb_fillrect);
-
-/**
- * drm_fb_helper_cfb_copyarea - wrapper around cfb_copyarea
- * @info: fbdev registered by the helper
- * @area: info about area to copy
- *
- * A wrapper around cfb_copyarea implemented by fbdev core
- */
-void drm_fb_helper_cfb_copyarea(struct fb_info *info,
- const struct fb_copyarea *area)
-{
- struct drm_fb_helper *helper = info->par;
-
- cfb_copyarea(info, area);
-
- if (helper->funcs->fb_dirty)
- drm_fb_helper_damage(helper, area->dx, area->dy, area->width, area->height);
-}
-EXPORT_SYMBOL(drm_fb_helper_cfb_copyarea);
-
-/**
- * drm_fb_helper_cfb_imageblit - wrapper around cfb_imageblit
- * @info: fbdev registered by the helper
- * @image: info about image to blit
- *
- * A wrapper around cfb_imageblit implemented by fbdev core
- */
-void drm_fb_helper_cfb_imageblit(struct fb_info *info,
- const struct fb_image *image)
-{
- struct drm_fb_helper *helper = info->par;
-
- cfb_imageblit(info, image);
-
- if (helper->funcs->fb_dirty)
- drm_fb_helper_damage(helper, image->dx, image->dy, image->width, image->height);
-}
-EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
-
/**
* drm_fb_helper_set_suspend - wrapper around fb_set_suspend
* @fb_helper: driver-allocated fbdev helper, can be NULL
diff --git a/drivers/gpu/drm/drm_fbdev_dma.c b/drivers/gpu/drm/drm_fbdev_dma.c
index 728deffcc0d9..d86773fa8ab0 100644
--- a/drivers/gpu/drm/drm_fbdev_dma.c
+++ b/drivers/gpu/drm/drm_fbdev_dma.c
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: MIT
+#include <linux/fb.h>
+
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
@@ -64,14 +66,11 @@ static const struct fb_ops drm_fbdev_dma_fb_ops = {
.owner = THIS_MODULE,
.fb_open = drm_fbdev_dma_fb_open,
.fb_release = drm_fbdev_dma_fb_release,
- .fb_read = drm_fb_helper_sys_read,
- .fb_write = drm_fb_helper_sys_write,
+ __FB_DEFAULT_SYS_OPS_RDWR,
DRM_FB_HELPER_DEFAULT_OPS,
- .fb_fillrect = drm_fb_helper_sys_fillrect,
- .fb_copyarea = drm_fb_helper_sys_copyarea,
- .fb_imageblit = drm_fb_helper_sys_imageblit,
- .fb_destroy = drm_fbdev_dma_fb_destroy,
+ __FB_DEFAULT_SYS_OPS_DRAW,
.fb_mmap = drm_fbdev_dma_fb_mmap,
+ .fb_destroy = drm_fbdev_dma_fb_destroy,
};
/*
diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_generic.c
index 8e5148bf40bb..98ae703848a0 100644
--- a/drivers/gpu/drm/drm_fbdev_generic.c
+++ b/drivers/gpu/drm/drm_fbdev_generic.c
@@ -34,6 +34,10 @@ static int drm_fbdev_generic_fb_release(struct fb_info *info, int user)
return 0;
}
+FB_GEN_DEFAULT_DEFERRED_SYS_OPS(drm_fbdev_generic,
+ drm_fb_helper_damage_range,
+ drm_fb_helper_damage_area);
+
static void drm_fbdev_generic_fb_destroy(struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
@@ -56,13 +60,8 @@ static const struct fb_ops drm_fbdev_generic_fb_ops = {
.owner = THIS_MODULE,
.fb_open = drm_fbdev_generic_fb_open,
.fb_release = drm_fbdev_generic_fb_release,
- .fb_read = drm_fb_helper_sys_read,
- .fb_write = drm_fb_helper_sys_write,
+ FB_DEFAULT_DEFERRED_OPS(drm_fbdev_generic),
DRM_FB_HELPER_DEFAULT_OPS,
- .fb_fillrect = drm_fb_helper_sys_fillrect,
- .fb_copyarea = drm_fb_helper_sys_copyarea,
- .fb_imageblit = drm_fb_helper_sys_imageblit,
- .fb_mmap = fb_deferred_io_mmap,
.fb_destroy = drm_fbdev_generic_fb_destroy,
};
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index c1018c470047..883d83bc0e3d 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -42,6 +42,7 @@
#include <drm/drm_client.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
+#include <drm/drm_gem.h>
#include <drm/drm_print.h>
#include "drm_crtc_internal.h"
@@ -148,6 +149,7 @@ bool drm_dev_needs_global_mutex(struct drm_device *dev)
*/
struct drm_file *drm_file_alloc(struct drm_minor *minor)
{
+ static atomic64_t ident = ATOMIC_INIT(0);
struct drm_device *dev = minor->dev;
struct drm_file *file;
int ret;
@@ -156,6 +158,8 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor)
if (!file)
return ERR_PTR(-ENOMEM);
+ /* Get a unique identifier for fdinfo: */
+ file->client_id = atomic64_inc_return(&ident);
file->pid = get_pid(task_tgid(current));
file->minor = minor;
@@ -868,6 +872,134 @@ void drm_send_event(struct drm_device *dev, struct drm_pending_event *e)
}
EXPORT_SYMBOL(drm_send_event);
+static void print_size(struct drm_printer *p, const char *stat,
+ const char *region, u64 sz)
+{
+ const char *units[] = {"", " KiB", " MiB"};
+ unsigned u;
+
+ for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
+ if (sz < SZ_1K)
+ break;
+ sz = div_u64(sz, SZ_1K);
+ }
+
+ drm_printf(p, "drm-%s-%s:\t%llu%s\n", stat, region, sz, units[u]);
+}
+
+/**
+ * drm_print_memory_stats - A helper to print memory stats
+ * @p: The printer to print output to
+ * @stats: The collected memory stats
+ * @supported_status: Bitmask of optional stats which are available
+ * @region: The memory region
+ *
+ */
+void drm_print_memory_stats(struct drm_printer *p,
+ const struct drm_memory_stats *stats,
+ enum drm_gem_object_status supported_status,
+ const char *region)
+{
+ print_size(p, "total", region, stats->private + stats->shared);
+ print_size(p, "shared", region, stats->shared);
+ print_size(p, "active", region, stats->active);
+
+ if (supported_status & DRM_GEM_OBJECT_RESIDENT)
+ print_size(p, "resident", region, stats->resident);
+
+ if (supported_status & DRM_GEM_OBJECT_PURGEABLE)
+ print_size(p, "purgeable", region, stats->purgeable);
+}
+EXPORT_SYMBOL(drm_print_memory_stats);
+
+/**
+ * drm_show_memory_stats - Helper to collect and show standard fdinfo memory stats
+ * @p: the printer to print output to
+ * @file: the DRM file
+ *
+ * Helper to iterate over GEM objects with a handle allocated in the specified
+ * file.
+ */
+void drm_show_memory_stats(struct drm_printer *p, struct drm_file *file)
+{
+ struct drm_gem_object *obj;
+ struct drm_memory_stats status = {};
+ enum drm_gem_object_status supported_status;
+ int id;
+
+ spin_lock(&file->table_lock);
+ idr_for_each_entry (&file->object_idr, obj, id) {
+ enum drm_gem_object_status s = 0;
+
+ if (obj->funcs && obj->funcs->status) {
+ s = obj->funcs->status(obj);
+ supported_status = DRM_GEM_OBJECT_RESIDENT |
+ DRM_GEM_OBJECT_PURGEABLE;
+ }
+
+ if (obj->handle_count > 1) {
+ status.shared += obj->size;
+ } else {
+ status.private += obj->size;
+ }
+
+ if (s & DRM_GEM_OBJECT_RESIDENT) {
+ status.resident += obj->size;
+ } else {
+ /* If already purged or not yet backed by pages, don't
+ * count it as purgeable:
+ */
+ s &= ~DRM_GEM_OBJECT_PURGEABLE;
+ }
+
+ if (!dma_resv_test_signaled(obj->resv, dma_resv_usage_rw(true))) {
+ status.active += obj->size;
+
+ /* If still active, don't count as purgeable: */
+ s &= ~DRM_GEM_OBJECT_PURGEABLE;
+ }
+
+ if (s & DRM_GEM_OBJECT_PURGEABLE)
+ status.purgeable += obj->size;
+ }
+ spin_unlock(&file->table_lock);
+
+ drm_print_memory_stats(p, &status, supported_status, "memory");
+}
+EXPORT_SYMBOL(drm_show_memory_stats);
+
+/**
+ * drm_show_fdinfo - helper for drm file fops
+ * @m: output stream
+ * @f: the device file instance
+ *
+ * Helper to implement fdinfo, for userspace to query usage stats, etc, of a
+ * process using the GPU. See also &drm_driver.show_fdinfo.
+ *
+ * For text output format description please see Documentation/gpu/drm-usage-stats.rst
+ */
+void drm_show_fdinfo(struct seq_file *m, struct file *f)
+{
+ struct drm_file *file = f->private_data;
+ struct drm_device *dev = file->minor->dev;
+ struct drm_printer p = drm_seq_file_printer(m);
+
+ drm_printf(&p, "drm-driver:\t%s\n", dev->driver->name);
+ drm_printf(&p, "drm-client-id:\t%llu\n", file->client_id);
+
+ if (dev_is_pci(dev->dev)) {
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+
+ drm_printf(&p, "drm-pdev:\t%04x:%02x:%02x.%d\n",
+ pci_domain_nr(pdev->bus), pdev->bus->number,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+ }
+
+ if (dev->driver->show_fdinfo)
+ dev->driver->show_fdinfo(&p, file);
+}
+EXPORT_SYMBOL(drm_show_fdinfo);
+
/**
* mock_drm_getfile - Create a new struct file for the drm device
* @minor: drm minor to wrap (e.g. #drm_device.primary)
diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index e93533b86037..b8a615a138cd 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem.h>
@@ -164,6 +165,14 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
return -EINVAL;
}
+ if (drm_drv_uses_atomic_modeset(dev) &&
+ !drm_any_plane_has_format(dev, mode_cmd->pixel_format,
+ mode_cmd->modifier[0])) {
+ drm_dbg(dev, "Unsupported pixel format %p4cc / modifier 0x%llx\n",
+ &mode_cmd->pixel_format, mode_cmd->modifier[0]);
+ return -EINVAL;
+ }
+
for (i = 0; i < info->num_planes; i++) {
unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c
index 0bea3df2a16d..b67eafa55715 100644
--- a/drivers/gpu/drm/drm_gem_vram_helper.c
+++ b/drivers/gpu/drm/drm_gem_vram_helper.c
@@ -45,7 +45,7 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs;
* the frame's scanout buffer or the cursor image. If there's no more space
* left in VRAM, inactive GEM objects can be moved to system memory.
*
- * To initialize the VRAM helper library call drmm_vram_helper_alloc_mm().
+ * To initialize the VRAM helper library call drmm_vram_helper_init().
* The function allocates and initializes an instance of &struct drm_vram_mm
* in &struct drm_device.vram_mm . Use &DRM_GEM_VRAM_DRIVER to initialize
* &struct drm_driver and &DRM_VRAM_MM_FILE_OPERATIONS to initialize
@@ -73,7 +73,7 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs;
* // setup device, vram base and size
* // ...
*
- * ret = drmm_vram_helper_alloc_mm(dev, vram_base, vram_size);
+ * ret = drmm_vram_helper_init(dev, vram_base, vram_size);
* if (ret)
* return ret;
* return 0;
@@ -86,7 +86,7 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs;
* to userspace.
*
* You don't have to clean up the instance of VRAM MM.
- * drmm_vram_helper_alloc_mm() is a managed interface that installs a
+ * drmm_vram_helper_init() is a managed interface that installs a
* clean-up handler to run during the DRM device's release.
*
* For drawing or scanout operations, rsp. buffer objects have to be pinned
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 3c22a803201d..f62767ff34b2 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -11,12 +11,14 @@
*/
#include <linux/acpi.h>
+#include <linux/component.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/gfp.h>
#include <linux/i2c.h>
#include <linux/kdev_t.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include <drm/drm_accel.h>
@@ -96,6 +98,34 @@ static char *drm_devnode(const struct device *dev, umode_t *mode)
return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
}
+static int typec_connector_bind(struct device *dev,
+ struct device *typec_connector, void *data)
+{
+ int ret;
+
+ ret = sysfs_create_link(&dev->kobj, &typec_connector->kobj, "typec_connector");
+ if (ret)
+ return ret;
+
+ ret = sysfs_create_link(&typec_connector->kobj, &dev->kobj, "drm_connector");
+ if (ret)
+ sysfs_remove_link(&dev->kobj, "typec_connector");
+
+ return ret;
+}
+
+static void typec_connector_unbind(struct device *dev,
+ struct device *typec_connector, void *data)
+{
+ sysfs_remove_link(&typec_connector->kobj, "drm_connector");
+ sysfs_remove_link(&dev->kobj, "typec_connector");
+}
+
+static const struct component_ops typec_connector_ops = {
+ .bind = typec_connector_bind,
+ .unbind = typec_connector_unbind,
+};
+
static CLASS_ATTR_STRING(version, S_IRUGO, "drm 1.1.0 20060810");
/**
@@ -282,16 +312,27 @@ static ssize_t modes_show(struct device *device,
return written;
}
+static ssize_t connector_id_show(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_connector *connector = to_drm_connector(device);
+
+ return sysfs_emit(buf, "%d\n", connector->base.id);
+}
+
static DEVICE_ATTR_RW(status);
static DEVICE_ATTR_RO(enabled);
static DEVICE_ATTR_RO(dpms);
static DEVICE_ATTR_RO(modes);
+static DEVICE_ATTR_RO(connector_id);
static struct attribute *connector_dev_attrs[] = {
&dev_attr_status.attr,
&dev_attr_enabled.attr,
&dev_attr_dpms.attr,
&dev_attr_modes.attr,
+ &dev_attr_connector_id.attr,
NULL
};
@@ -353,9 +394,16 @@ int drm_sysfs_connector_add(struct drm_connector *connector)
connector->kdev = kdev;
+ if (dev_fwnode(kdev)) {
+ r = component_add(kdev, &typec_connector_ops);
+ if (r)
+ drm_err(dev, "failed to add component to create link to typec connector\n");
+ }
+
if (connector->ddc)
return sysfs_create_link(&connector->kdev->kobj,
&connector->ddc->dev.kobj, "ddc");
+
return 0;
err_free:
@@ -371,6 +419,9 @@ void drm_sysfs_connector_remove(struct drm_connector *connector)
if (connector->ddc)
sysfs_remove_link(&connector->kdev->kobj, "ddc");
+ if (dev_fwnode(connector->kdev))
+ component_del(connector->kdev, &typec_connector_ops);
+
DRM_DEBUG("removing \"%s\" from sysfs\n",
connector->name);
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 0cb92d651ff1..7ca7e1dab52c 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -7,6 +7,7 @@ config DRM_EXYNOS
select DRM_DISPLAY_HELPER if DRM_EXYNOS_DP
select DRM_KMS_HELPER
select VIDEOMODE_HELPERS
+ select FB_IO_HELPERS if DRM_FBDEV_EMULATION
select SND_SOC_HDMI_CODEC if SND_SOC
help
Choose this option if you have a Samsung SoC Exynos chipset.
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index ea4b3d248aac..fdf65587f1fe 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -8,6 +8,8 @@
* Seung-Woo Kim <sw0312.kim@samsung.com>
*/
+#include <linux/fb.h>
+
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
@@ -47,13 +49,10 @@ static void exynos_drm_fb_destroy(struct fb_info *info)
static const struct fb_ops exynos_drm_fb_ops = {
.owner = THIS_MODULE,
+ __FB_DEFAULT_IO_OPS_RDWR,
DRM_FB_HELPER_DEFAULT_OPS,
+ __FB_DEFAULT_IO_OPS_DRAW,
.fb_mmap = exynos_drm_fb_mmap,
- .fb_read = drm_fb_helper_cfb_read,
- .fb_write = drm_fb_helper_cfb_write,
- .fb_fillrect = drm_fb_helper_cfb_fillrect,
- .fb_copyarea = drm_fb_helper_cfb_copyarea,
- .fb_imageblit = drm_fb_helper_cfb_imageblit,
.fb_destroy = exynos_drm_fb_destroy,
};
diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig
index 2efc0eb41c64..cd3d92725ed4 100644
--- a/drivers/gpu/drm/gma500/Kconfig
+++ b/drivers/gpu/drm/gma500/Kconfig
@@ -3,6 +3,7 @@ config DRM_GMA500
tristate "Intel GMA500/600/3600/3650 KMS Framebuffer"
depends on DRM && PCI && X86 && MMU
select DRM_KMS_HELPER
+ select FB_IO_HELPERS if DRM_FBDEV_EMULATION
select I2C
select I2C_ALGOBIT
# GMA500 depends on ACPI_VIDEO when ACPI is enabled, just like i915
diff --git a/drivers/gpu/drm/gma500/fbdev.c b/drivers/gpu/drm/gma500/fbdev.c
index 62287407e717..955cbe9f05a7 100644
--- a/drivers/gpu/drm/gma500/fbdev.c
+++ b/drivers/gpu/drm/gma500/fbdev.c
@@ -5,6 +5,7 @@
*
**************************************************************************/
+#include <linux/fb.h>
#include <linux/pfn_t.h>
#include <drm/drm_crtc_helper.h>
@@ -134,13 +135,10 @@ static void psb_fbdev_fb_destroy(struct fb_info *info)
static const struct fb_ops psb_fbdev_fb_ops = {
.owner = THIS_MODULE,
+ __FB_DEFAULT_IO_OPS_RDWR,
DRM_FB_HELPER_DEFAULT_OPS,
.fb_setcolreg = psb_fbdev_fb_setcolreg,
- .fb_read = drm_fb_helper_cfb_read,
- .fb_write = drm_fb_helper_cfb_write,
- .fb_fillrect = drm_fb_helper_cfb_fillrect,
- .fb_copyarea = drm_fb_helper_cfb_copyarea,
- .fb_imageblit = drm_fb_helper_cfb_imageblit,
+ __FB_DEFAULT_IO_OPS_DRAW,
.fb_mmap = psb_fbdev_fb_mmap,
.fb_destroy = psb_fbdev_fb_destroy,
};
@@ -231,7 +229,7 @@ static int psb_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
info->fix.mmio_start = pci_resource_start(pdev, 0);
info->fix.mmio_len = pci_resource_len(pdev, 0);
- memset(info->screen_base, 0, info->screen_size);
+ fb_memset_io(info->screen_base, 0, info->screen_size);
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 2ce96b1b9c74..8b64f61ffaf9 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -7,6 +7,7 @@
*
**************************************************************************/
+#include <linux/aperture.h>
#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/notifier.h>
@@ -19,7 +20,6 @@
#include <acpi/video.h>
#include <drm/drm.h>
-#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
@@ -414,20 +414,45 @@ out_err:
return ret;
}
+/*
+ * Hardware for gma500 is a hybrid device, which both acts as a PCI
+ * device (for legacy vga functionality) but also more like an
+ * integrated display on a SoC where the framebuffer simply
+ * resides in main memory and not in a special PCI bar (that
+ * internally redirects to a stolen range of main memory) like all
+ * other integrated PCI display devices implement it.
+ *
+ * To catch all cases we need to remove conflicting firmware devices
+ * for the stolen system memory and for the VGA functionality. As we
+ * currently cannot easily find the framebuffer's location in stolen
+ * memory, we remove all framebuffers here.
+ *
+ * TODO: Refactor psb_driver_load() to map vdc_reg earlier. Then
+ * we might be able to read the framebuffer range from the
+ * device.
+ */
+static int gma_remove_conflicting_framebuffers(struct pci_dev *pdev,
+ const struct drm_driver *req_driver)
+{
+ resource_size_t base = 0;
+ resource_size_t size = U32_MAX; /* 4 GiB HW limit */
+ const char *name = req_driver->name;
+ int ret;
+
+ ret = aperture_remove_conflicting_devices(base, size, name);
+ if (ret)
+ return ret;
+
+ return __aperture_remove_legacy_vga_devices(pdev);
+}
+
static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct drm_psb_private *dev_priv;
struct drm_device *dev;
int ret;
- /*
- * We cannot yet easily find the framebuffer's location in memory. So
- * remove all framebuffers here.
- *
- * TODO: Refactor psb_driver_load() to map vdc_reg earlier. Then we
- * might be able to read the framebuffer range from the device.
- */
- ret = drm_aperture_remove_framebuffers(true, &driver);
+ ret = gma_remove_conflicting_framebuffers(pdev, &driver);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
index f830d62a5ce6..a7d2c92d6c6a 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
@@ -74,7 +74,6 @@ static int hyperv_setup_vram(struct hyperv_drm_device *hv,
drm_aperture_remove_conflicting_framebuffers(screen_info.lfb_base,
screen_info.lfb_size,
- false,
&hyperv_driver);
hv->fb_size = (unsigned long)hv->mmio_megabytes * 1024 * 1024;
diff --git a/drivers/gpu/drm/i2c/tda9950.c b/drivers/gpu/drm/i2c/tda9950.c
index b8c143e573e0..82d618c40dce 100644
--- a/drivers/gpu/drm/i2c/tda9950.c
+++ b/drivers/gpu/drm/i2c/tda9950.c
@@ -492,7 +492,7 @@ static struct i2c_device_id tda9950_ids[] = {
MODULE_DEVICE_TABLE(i2c, tda9950_ids);
static struct i2c_driver tda9950_driver = {
- .probe_new = tda9950_probe,
+ .probe = tda9950_probe,
.remove = tda9950_remove,
.driver = {
.name = "tda9950",
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 0918d80672bb..d8d7de18dd65 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -2099,7 +2099,7 @@ static const struct i2c_device_id tda998x_ids[] = {
MODULE_DEVICE_TABLE(i2c, tda998x_ids);
static struct i2c_driver tda998x_driver = {
- .probe_new = tda998x_probe,
+ .probe = tda998x_probe,
.remove = tda998x_remove,
.driver = {
.name = "tda998x",
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index e4f4d2e3fdfe..01b5a8272a27 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -17,6 +17,7 @@ config DRM_I915
select DRM_KMS_HELPER
select DRM_PANEL
select DRM_MIPI_DSI
+ select FB_IO_HELPERS if DRM_FBDEV_EMULATION
select RELAY
select I2C
select I2C_ALGOBIT
diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
index 47e845353ffa..2d21930d5501 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -157,6 +157,7 @@ config DRM_I915_SW_FENCE_CHECK_DAG
config DRM_I915_DEBUG_GUC
bool "Enable additional driver debugging for GuC"
depends on DRM_I915
+ select STACKDEPOT
default n
help
Choose this option to turn on extra driver debugging that may affect
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 97b0d4ae221a..789dce9e2608 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -19,14 +19,10 @@ subdir-ccflags-y += -Wno-type-limits
subdir-ccflags-y += -Wno-missing-field-initializers
subdir-ccflags-y += -Wno-sign-compare
subdir-ccflags-y += -Wno-shift-negative-value
-subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable)
+subdir-ccflags-y += $(call cc-option, -Wunused-but-set-variable)
subdir-ccflags-y += $(call cc-disable-warning, frame-address)
subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror
-# Fine grained warnings disable
-CFLAGS_i915_pci.o = $(call cc-disable-warning, override-init)
-CFLAGS_display/intel_fbdev.o = $(call cc-disable-warning, override-init)
-
subdir-ccflags-y += -I$(srctree)/$(src)
# Please keep these build lists sorted!
@@ -194,6 +190,7 @@ i915-y += \
# general-purpose microcontroller (GuC) support
i915-y += \
gt/uc/intel_gsc_fw.o \
+ gt/uc/intel_gsc_proxy.o \
gt/uc/intel_gsc_uc.o \
gt/uc/intel_gsc_uc_heci_cmd_submit.o\
gt/uc/intel_guc.o \
@@ -237,9 +234,12 @@ i915-y += \
display/intel_crtc_state_dump.o \
display/intel_cursor.o \
display/intel_display.o \
+ display/intel_display_driver.o \
+ display/intel_display_irq.o \
display/intel_display_power.o \
display/intel_display_power_map.o \
display/intel_display_power_well.o \
+ display/intel_display_reset.o \
display/intel_display_rps.o \
display/intel_dmc.o \
display/intel_dpio_phy.o \
@@ -258,14 +258,18 @@ i915-y += \
display/intel_hdcp.o \
display/intel_hdcp_gsc.o \
display/intel_hotplug.o \
+ display/intel_hotplug_irq.o \
display/intel_hti.o \
+ display/intel_load_detect.o \
display/intel_lpe_audio.o \
+ display/intel_modeset_lock.o \
display/intel_modeset_verify.o \
display/intel_modeset_setup.o \
display/intel_overlay.o \
display/intel_pch_display.o \
display/intel_pch_refclk.o \
display/intel_plane_initial.o \
+ display/intel_pmdemand.o \
display/intel_psr.o \
display/intel_quirks.o \
display/intel_sprite.o \
@@ -298,8 +302,10 @@ i915-y += \
display/icl_dsi.o \
display/intel_backlight.o \
display/intel_crt.o \
+ display/intel_cx0_phy.o \
display/intel_ddi.o \
display/intel_ddi_buf_trans.o \
+ display/intel_display_device.o \
display/intel_display_trace.o \
display/intel_dkl_phy.o \
display/intel_dp.o \
@@ -338,6 +344,7 @@ i915-y += \
i915-$(CONFIG_DRM_I915_PXP) += \
pxp/intel_pxp_cmd.o \
pxp/intel_pxp_debugfs.o \
+ pxp/intel_pxp_gsccs.o \
pxp/intel_pxp_irq.o \
pxp/intel_pxp_pm.o \
pxp/intel_pxp_session.o
@@ -373,7 +380,7 @@ obj-$(CONFIG_DRM_I915_GVT_KVMGT) += kvmgt.o
#
# Enable locally for CONFIG_DRM_I915_WERROR=y. See also scripts/Makefile.build
ifdef CONFIG_DRM_I915_WERROR
- cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $<
+ cmd_checkdoc = $(srctree)/scripts/kernel-doc -none -Werror $<
endif
# header test
@@ -388,7 +395,7 @@ always-$(CONFIG_DRM_I915_WERROR) += \
quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@)
cmd_hdrtest = $(CC) $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $<; \
- $(srctree)/scripts/kernel-doc -none $<; touch $@
+ $(srctree)/scripts/kernel-doc -none -Werror $<; touch $@
$(obj)/%.hdrtest: $(src)/%.h FORCE
$(call if_changed_dep,hdrtest)
diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c
index 920d570f7594..112d91d81fdc 100644
--- a/drivers/gpu/drm/i915/display/g4x_dp.c
+++ b/drivers/gpu/drm/i915/display/g4x_dp.c
@@ -169,7 +169,7 @@ static void assert_dp_port(struct intel_dp *intel_dp, bool state)
struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
bool cur_state = intel_de_read(dev_priv, intel_dp->output_reg) & DP_PORT_EN;
- I915_STATE_WARN(cur_state != state,
+ I915_STATE_WARN(dev_priv, cur_state != state,
"[ENCODER:%d:%s] state assertion failure (expected %s, current %s)\n",
dig_port->base.base.base.id, dig_port->base.base.name,
str_on_off(state), str_on_off(cur_state));
@@ -180,7 +180,7 @@ static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state)
{
bool cur_state = intel_de_read(dev_priv, DP_A) & DP_PLL_ENABLE;
- I915_STATE_WARN(cur_state != state,
+ I915_STATE_WARN(dev_priv, cur_state != state,
"eDP PLL state assertion failure (expected %s, current %s)\n",
str_on_off(state), str_on_off(cur_state));
}
diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c
index 448ea26786e0..5c187e6e0472 100644
--- a/drivers/gpu/drm/i915/display/g4x_hdmi.c
+++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c
@@ -7,6 +7,7 @@
#include "g4x_hdmi.h"
#include "i915_reg.h"
+#include "intel_atomic.h"
#include "intel_audio.h"
#include "intel_connector.h"
#include "intel_crtc.h"
@@ -80,15 +81,67 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
return ret;
}
+static bool connector_is_hdmi(struct drm_connector *connector)
+{
+ struct intel_encoder *encoder =
+ intel_attached_encoder(to_intel_connector(connector));
+
+ return encoder && encoder->type == INTEL_OUTPUT_HDMI;
+}
+
+static bool g4x_compute_has_hdmi_sink(struct intel_atomic_state *state,
+ struct intel_crtc *this_crtc)
+{
+ const struct drm_connector_state *conn_state;
+ struct drm_connector *connector;
+ int i;
+
+ /*
+ * On g4x only one HDMI port can transmit infoframes/audio at
+ * any given time. Select the first suitable port for this duty.
+ *
+ * See also g4x_hdmi_connector_atomic_check().
+ */
+ for_each_new_connector_in_state(&state->base, connector, conn_state, i) {
+ struct intel_encoder *encoder = to_intel_encoder(conn_state->best_encoder);
+ const struct intel_crtc_state *crtc_state;
+ struct intel_crtc *crtc;
+
+ if (!connector_is_hdmi(connector))
+ continue;
+
+ crtc = to_intel_crtc(conn_state->crtc);
+ if (!crtc)
+ continue;
+
+ crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
+
+ if (!intel_hdmi_compute_has_hdmi_sink(encoder, crtc_state, conn_state))
+ continue;
+
+ return crtc == this_crtc;
+ }
+
+ return false;
+}
+
static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
+ struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
if (HAS_PCH_SPLIT(i915))
crtc_state->has_pch_encoder = true;
+ if (IS_G4X(i915))
+ crtc_state->has_hdmi_sink = g4x_compute_has_hdmi_sink(state, crtc);
+ else
+ crtc_state->has_hdmi_sink =
+ intel_hdmi_compute_has_hdmi_sink(encoder, crtc_state, conn_state);
+
return intel_hdmi_compute_config(encoder, crtc_state, conn_state);
}
@@ -546,6 +599,66 @@ intel_hdmi_hotplug(struct intel_encoder *encoder,
return state;
}
+int g4x_hdmi_connector_atomic_check(struct drm_connector *connector,
+ struct drm_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->dev);
+ struct drm_connector_list_iter conn_iter;
+ struct drm_connector *conn;
+ int ret;
+
+ ret = intel_digital_connector_atomic_check(connector, state);
+ if (ret)
+ return ret;
+
+ if (!IS_G4X(i915))
+ return 0;
+
+ if (!intel_connector_needs_modeset(to_intel_atomic_state(state), connector))
+ return 0;
+
+ /*
+ * On g4x only one HDMI port can transmit infoframes/audio
+ * at any given time. Make sure all enabled HDMI ports are
+ * included in the state so that it's possible to select
+ * one of them for this duty.
+ *
+ * See also g4x_compute_has_hdmi_sink().
+ */
+ drm_connector_list_iter_begin(&i915->drm, &conn_iter);
+ drm_for_each_connector_iter(conn, &conn_iter) {
+ struct drm_connector_state *conn_state;
+ struct drm_crtc_state *crtc_state;
+ struct drm_crtc *crtc;
+
+ if (!connector_is_hdmi(conn))
+ continue;
+
+ drm_dbg_kms(&i915->drm, "Adding [CONNECTOR:%d:%s]\n",
+ conn->base.id, conn->name);
+
+ conn_state = drm_atomic_get_connector_state(state, conn);
+ if (IS_ERR(conn_state)) {
+ ret = PTR_ERR(conn_state);
+ break;
+ }
+
+ crtc = conn_state->crtc;
+ if (!crtc)
+ continue;
+
+ crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ crtc_state->mode_changed = true;
+
+ ret = drm_atomic_add_affected_planes(state, crtc);
+ if (ret)
+ break;
+ }
+ drm_connector_list_iter_end(&conn_iter);
+
+ return ret;
+}
+
void g4x_hdmi_init(struct drm_i915_private *dev_priv,
i915_reg_t hdmi_reg, enum port port)
{
diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.h b/drivers/gpu/drm/i915/display/g4x_hdmi.h
index db9a93bc9321..1e3ea7f3c846 100644
--- a/drivers/gpu/drm/i915/display/g4x_hdmi.h
+++ b/drivers/gpu/drm/i915/display/g4x_hdmi.h
@@ -11,9 +11,13 @@
#include "i915_reg_defs.h"
enum port;
+struct drm_atomic_state;
+struct drm_connector;
struct drm_i915_private;
void g4x_hdmi_init(struct drm_i915_private *dev_priv,
i915_reg_t hdmi_reg, enum port port);
+int g4x_hdmi_connector_atomic_check(struct drm_connector *connector,
+ struct drm_atomic_state *state);
#endif
diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c
index ecaeb7dc196b..b10488324457 100644
--- a/drivers/gpu/drm/i915/display/i9xx_plane.c
+++ b/drivers/gpu/drm/i915/display/i9xx_plane.c
@@ -8,12 +8,12 @@
#include <drm/drm_blend.h>
#include <drm/drm_fourcc.h>
-#include "i915_irq.h"
#include "i915_reg.h"
#include "i9xx_plane.h"
#include "intel_atomic.h"
#include "intel_atomic_plane.h"
#include "intel_de.h"
+#include "intel_display_irq.h"
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fbc.h"
@@ -1033,10 +1033,13 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
DSPLINOFF(i9xx_plane));
base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & DISP_ADDR_MASK;
} else {
+ offset = 0;
base = intel_de_read(dev_priv, DSPADDR(i9xx_plane));
}
plane_config->base = base;
+ drm_WARN_ON(&dev_priv->drm, offset != 0);
+
val = intel_de_read(dev_priv, PIPESRC(pipe));
fb->width = REG_FIELD_GET(PIPESRC_WIDTH_MASK, val) + 1;
fb->height = REG_FIELD_GET(PIPESRC_HEIGHT_MASK, val) + 1;
diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c
index caef72d38798..af0c79a4c9a4 100644
--- a/drivers/gpu/drm/i915/display/i9xx_wm.c
+++ b/drivers/gpu/drm/i915/display/i9xx_wm.c
@@ -4,6 +4,7 @@
*/
#include "i915_drv.h"
+#include "i915_reg.h"
#include "i9xx_wm.h"
#include "intel_atomic.h"
#include "intel_display.h"
@@ -3447,9 +3448,10 @@ void ilk_wm_sanitize(struct drm_i915_private *dev_priv)
drm_modeset_acquire_init(&ctx, 0);
-retry:
state->acquire_ctx = &ctx;
+ to_intel_atomic_state(state)->internal = true;
+retry:
/*
* Hardware readout is the only time we don't want to calculate
* intermediate watermarks (since we don't trust the current
diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.h b/drivers/gpu/drm/i915/display/i9xx_wm.h
index a7875cbcd05a..b87ae369685a 100644
--- a/drivers/gpu/drm/i915/display/i9xx_wm.h
+++ b/drivers/gpu/drm/i915/display/i9xx_wm.h
@@ -12,7 +12,6 @@ struct drm_i915_private;
struct intel_crtc_state;
struct intel_plane_state;
-int ilk_wm_max_level(const struct drm_i915_private *i915);
bool ilk_disable_lp_wm(struct drm_i915_private *i915);
void ilk_wm_sanitize(struct drm_i915_private *i915);
bool intel_set_memory_cxsr(struct drm_i915_private *i915, bool enable);
diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index c9aeba0ecf91..c133928a0655 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -1591,6 +1591,7 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder,
&pipe_config->hw.adjusted_mode;
int ret;
+ pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
ret = intel_panel_compute_config(intel_connector, adjusted_mode);
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
index a9a3f3715279..7cf51dd8c056 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -265,7 +265,6 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
crtc_state->update_wm_post = false;
crtc_state->fifo_changed = false;
crtc_state->preload_luts = false;
- crtc_state->inherited = false;
crtc_state->wm.need_postvbl_update = false;
crtc_state->do_async_flip = false;
crtc_state->fb_bits = 0;
@@ -311,262 +310,6 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
kfree(crtc_state);
}
-static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state,
- int num_scalers_need, struct intel_crtc *intel_crtc,
- const char *name, int idx,
- struct intel_plane_state *plane_state,
- int *scaler_id)
-{
- struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
- int j;
- u32 mode;
-
- if (*scaler_id < 0) {
- /* find a free scaler */
- for (j = 0; j < intel_crtc->num_scalers; j++) {
- if (scaler_state->scalers[j].in_use)
- continue;
-
- *scaler_id = j;
- scaler_state->scalers[*scaler_id].in_use = 1;
- break;
- }
- }
-
- if (drm_WARN(&dev_priv->drm, *scaler_id < 0,
- "Cannot find scaler for %s:%d\n", name, idx))
- return -EINVAL;
-
- /* set scaler mode */
- if (plane_state && plane_state->hw.fb &&
- plane_state->hw.fb->format->is_yuv &&
- plane_state->hw.fb->format->num_planes > 1) {
- struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
- if (DISPLAY_VER(dev_priv) == 9) {
- mode = SKL_PS_SCALER_MODE_NV12;
- } else if (icl_is_hdr_plane(dev_priv, plane->id)) {
- /*
- * On gen11+'s HDR planes we only use the scaler for
- * scaling. They have a dedicated chroma upsampler, so
- * we don't need the scaler to upsample the UV plane.
- */
- mode = PS_SCALER_MODE_NORMAL;
- } else {
- struct intel_plane *linked =
- plane_state->planar_linked_plane;
-
- mode = PS_SCALER_MODE_PLANAR;
-
- if (linked)
- mode |= PS_PLANE_Y_SEL(linked->id);
- }
- } else if (DISPLAY_VER(dev_priv) >= 10) {
- mode = PS_SCALER_MODE_NORMAL;
- } else if (num_scalers_need == 1 && intel_crtc->num_scalers > 1) {
- /*
- * when only 1 scaler is in use on a pipe with 2 scalers
- * scaler 0 operates in high quality (HQ) mode.
- * In this case use scaler 0 to take advantage of HQ mode
- */
- scaler_state->scalers[*scaler_id].in_use = 0;
- *scaler_id = 0;
- scaler_state->scalers[0].in_use = 1;
- mode = SKL_PS_SCALER_MODE_HQ;
- } else {
- mode = SKL_PS_SCALER_MODE_DYN;
- }
-
- /*
- * FIXME: we should also check the scaler factors for pfit, so
- * this shouldn't be tied directly to planes.
- */
- if (plane_state && plane_state->hw.fb) {
- const struct drm_framebuffer *fb = plane_state->hw.fb;
- const struct drm_rect *src = &plane_state->uapi.src;
- const struct drm_rect *dst = &plane_state->uapi.dst;
- int hscale, vscale, max_vscale, max_hscale;
-
- /*
- * FIXME: When two scalers are needed, but only one of
- * them needs to downscale, we should make sure that
- * the one that needs downscaling support is assigned
- * as the first scaler, so we don't reject downscaling
- * unnecessarily.
- */
-
- if (DISPLAY_VER(dev_priv) >= 14) {
- /*
- * On versions 14 and up, only the first
- * scaler supports a vertical scaling factor
- * of more than 1.0, while a horizontal
- * scaling factor of 3.0 is supported.
- */
- max_hscale = 0x30000 - 1;
- if (*scaler_id == 0)
- max_vscale = 0x30000 - 1;
- else
- max_vscale = 0x10000;
-
- } else if (DISPLAY_VER(dev_priv) >= 10 ||
- !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
- max_hscale = 0x30000 - 1;
- max_vscale = 0x30000 - 1;
- } else {
- max_hscale = 0x20000 - 1;
- max_vscale = 0x20000 - 1;
- }
-
- /*
- * FIXME: We should change the if-else block above to
- * support HQ vs dynamic scaler properly.
- */
-
- /* Check if required scaling is within limits */
- hscale = drm_rect_calc_hscale(src, dst, 1, max_hscale);
- vscale = drm_rect_calc_vscale(src, dst, 1, max_vscale);
-
- if (hscale < 0 || vscale < 0) {
- drm_dbg_kms(&dev_priv->drm,
- "Scaler %d doesn't support required plane scaling\n",
- *scaler_id);
- drm_rect_debug_print("src: ", src, true);
- drm_rect_debug_print("dst: ", dst, false);
-
- return -EINVAL;
- }
- }
-
- drm_dbg_kms(&dev_priv->drm, "Attached scaler id %u.%u to %s:%d\n",
- intel_crtc->pipe, *scaler_id, name, idx);
- scaler_state->scalers[*scaler_id].mode = mode;
-
- return 0;
-}
-
-/**
- * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
- * @dev_priv: i915 device
- * @intel_crtc: intel crtc
- * @crtc_state: incoming crtc_state to validate and setup scalers
- *
- * This function sets up scalers based on staged scaling requests for
- * a @crtc and its planes. It is called from crtc level check path. If request
- * is a supportable request, it attaches scalers to requested planes and crtc.
- *
- * This function takes into account the current scaler(s) in use by any planes
- * not being part of this atomic state
- *
- * Returns:
- * 0 - scalers were setup succesfully
- * error code - otherwise
- */
-int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
- struct intel_crtc *intel_crtc,
- struct intel_crtc_state *crtc_state)
-{
- struct drm_plane *plane = NULL;
- struct intel_plane *intel_plane;
- struct intel_plane_state *plane_state = NULL;
- struct intel_crtc_scaler_state *scaler_state =
- &crtc_state->scaler_state;
- struct drm_atomic_state *drm_state = crtc_state->uapi.state;
- struct intel_atomic_state *intel_state = to_intel_atomic_state(drm_state);
- int num_scalers_need;
- int i;
-
- num_scalers_need = hweight32(scaler_state->scaler_users);
-
- /*
- * High level flow:
- * - staged scaler requests are already in scaler_state->scaler_users
- * - check whether staged scaling requests can be supported
- * - add planes using scalers that aren't in current transaction
- * - assign scalers to requested users
- * - as part of plane commit, scalers will be committed
- * (i.e., either attached or detached) to respective planes in hw
- * - as part of crtc_commit, scaler will be either attached or detached
- * to crtc in hw
- */
-
- /* fail if required scalers > available scalers */
- if (num_scalers_need > intel_crtc->num_scalers){
- drm_dbg_kms(&dev_priv->drm,
- "Too many scaling requests %d > %d\n",
- num_scalers_need, intel_crtc->num_scalers);
- return -EINVAL;
- }
-
- /* walkthrough scaler_users bits and start assigning scalers */
- for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
- int *scaler_id;
- const char *name;
- int idx, ret;
-
- /* skip if scaler not required */
- if (!(scaler_state->scaler_users & (1 << i)))
- continue;
-
- if (i == SKL_CRTC_INDEX) {
- name = "CRTC";
- idx = intel_crtc->base.base.id;
-
- /* panel fitter case: assign as a crtc scaler */
- scaler_id = &scaler_state->scaler_id;
- } else {
- name = "PLANE";
-
- /* plane scaler case: assign as a plane scaler */
- /* find the plane that set the bit as scaler_user */
- plane = drm_state->planes[i].ptr;
-
- /*
- * to enable/disable hq mode, add planes that are using scaler
- * into this transaction
- */
- if (!plane) {
- struct drm_plane_state *state;
-
- /*
- * GLK+ scalers don't have a HQ mode so it
- * isn't necessary to change between HQ and dyn mode
- * on those platforms.
- */
- if (DISPLAY_VER(dev_priv) >= 10)
- continue;
-
- plane = drm_plane_from_index(&dev_priv->drm, i);
- state = drm_atomic_get_plane_state(drm_state, plane);
- if (IS_ERR(state)) {
- drm_dbg_kms(&dev_priv->drm,
- "Failed to add [PLANE:%d] to drm_state\n",
- plane->base.id);
- return PTR_ERR(state);
- }
- }
-
- intel_plane = to_intel_plane(plane);
- idx = plane->base.id;
-
- /* plane on different crtc cannot be a scaler user of this crtc */
- if (drm_WARN_ON(&dev_priv->drm,
- intel_plane->pipe != intel_crtc->pipe))
- continue;
-
- plane_state = intel_atomic_get_new_plane_state(intel_state,
- intel_plane);
- scaler_id = &plane_state->scaler_id;
- }
-
- ret = intel_atomic_setup_scaler(scaler_state, num_scalers_need,
- intel_crtc, name, idx,
- plane_state, scaler_id);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
struct drm_atomic_state *
intel_atomic_state_alloc(struct drm_device *dev)
{
@@ -599,6 +342,8 @@ void intel_atomic_state_clear(struct drm_atomic_state *s)
drm_atomic_state_default_clear(&state->base);
intel_atomic_clear_global_state(state);
+ /* state->internal not reset on purpose */
+
state->dpll_set = state->modeset = false;
}
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h
index 1dc439983dd9..e506f6a87344 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.h
+++ b/drivers/gpu/drm/i915/display/intel_atomic.h
@@ -52,8 +52,4 @@ struct intel_crtc_state *
intel_atomic_get_crtc_state(struct drm_atomic_state *state,
struct intel_crtc *crtc);
-int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
- struct intel_crtc *intel_crtc,
- struct intel_crtc_state *crtc_state);
-
#endif /* __INTEL_ATOMIC_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
index f33164b10292..7d9578ebae55 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -36,6 +36,7 @@
#include <drm/drm_fourcc.h>
#include "i915_config.h"
+#include "i915_reg.h"
#include "intel_atomic_plane.h"
#include "intel_cdclk.h"
#include "intel_display_rps.h"
@@ -721,7 +722,7 @@ skl_next_plane_to_commit(struct intel_atomic_state *state,
{
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
- struct intel_plane_state *plane_state;
+ struct intel_plane_state __maybe_unused *plane_state;
struct intel_plane *plane;
int i;
diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c
index 3d5a9bbc6fde..3d9c9b4f27f8 100644
--- a/drivers/gpu/drm/i915/display/intel_audio.c
+++ b/drivers/gpu/drm/i915/display/intel_audio.c
@@ -1039,6 +1039,7 @@ static void glk_force_audio_cdclk(struct drm_i915_private *i915,
return;
state->acquire_ctx = &ctx;
+ to_intel_atomic_state(state)->internal = true;
retry:
ret = glk_force_audio_cdclk_commit(to_intel_atomic_state(state), crtc,
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 75e69dffc5e9..34a397adbd6b 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -2141,58 +2141,58 @@ static u8 translate_iboost(u8 val)
static const u8 cnp_ddc_pin_map[] = {
[0] = 0, /* N/A */
- [DDC_BUS_DDI_B] = GMBUS_PIN_1_BXT,
- [DDC_BUS_DDI_C] = GMBUS_PIN_2_BXT,
- [DDC_BUS_DDI_D] = GMBUS_PIN_4_CNP, /* sic */
- [DDC_BUS_DDI_F] = GMBUS_PIN_3_BXT, /* sic */
+ [GMBUS_PIN_1_BXT] = DDC_BUS_DDI_B,
+ [GMBUS_PIN_2_BXT] = DDC_BUS_DDI_C,
+ [GMBUS_PIN_4_CNP] = DDC_BUS_DDI_D, /* sic */
+ [GMBUS_PIN_3_BXT] = DDC_BUS_DDI_F, /* sic */
};
static const u8 icp_ddc_pin_map[] = {
- [ICL_DDC_BUS_DDI_A] = GMBUS_PIN_1_BXT,
- [ICL_DDC_BUS_DDI_B] = GMBUS_PIN_2_BXT,
- [TGL_DDC_BUS_DDI_C] = GMBUS_PIN_3_BXT,
- [ICL_DDC_BUS_PORT_1] = GMBUS_PIN_9_TC1_ICP,
- [ICL_DDC_BUS_PORT_2] = GMBUS_PIN_10_TC2_ICP,
- [ICL_DDC_BUS_PORT_3] = GMBUS_PIN_11_TC3_ICP,
- [ICL_DDC_BUS_PORT_4] = GMBUS_PIN_12_TC4_ICP,
- [TGL_DDC_BUS_PORT_5] = GMBUS_PIN_13_TC5_TGP,
- [TGL_DDC_BUS_PORT_6] = GMBUS_PIN_14_TC6_TGP,
+ [GMBUS_PIN_1_BXT] = ICL_DDC_BUS_DDI_A,
+ [GMBUS_PIN_2_BXT] = ICL_DDC_BUS_DDI_B,
+ [GMBUS_PIN_3_BXT] = TGL_DDC_BUS_DDI_C,
+ [GMBUS_PIN_9_TC1_ICP] = ICL_DDC_BUS_PORT_1,
+ [GMBUS_PIN_10_TC2_ICP] = ICL_DDC_BUS_PORT_2,
+ [GMBUS_PIN_11_TC3_ICP] = ICL_DDC_BUS_PORT_3,
+ [GMBUS_PIN_12_TC4_ICP] = ICL_DDC_BUS_PORT_4,
+ [GMBUS_PIN_13_TC5_TGP] = TGL_DDC_BUS_PORT_5,
+ [GMBUS_PIN_14_TC6_TGP] = TGL_DDC_BUS_PORT_6,
};
static const u8 rkl_pch_tgp_ddc_pin_map[] = {
- [ICL_DDC_BUS_DDI_A] = GMBUS_PIN_1_BXT,
- [ICL_DDC_BUS_DDI_B] = GMBUS_PIN_2_BXT,
- [RKL_DDC_BUS_DDI_D] = GMBUS_PIN_9_TC1_ICP,
- [RKL_DDC_BUS_DDI_E] = GMBUS_PIN_10_TC2_ICP,
+ [GMBUS_PIN_1_BXT] = ICL_DDC_BUS_DDI_A,
+ [GMBUS_PIN_2_BXT] = ICL_DDC_BUS_DDI_B,
+ [GMBUS_PIN_9_TC1_ICP] = RKL_DDC_BUS_DDI_D,
+ [GMBUS_PIN_10_TC2_ICP] = RKL_DDC_BUS_DDI_E,
};
static const u8 adls_ddc_pin_map[] = {
- [ICL_DDC_BUS_DDI_A] = GMBUS_PIN_1_BXT,
- [ADLS_DDC_BUS_PORT_TC1] = GMBUS_PIN_9_TC1_ICP,
- [ADLS_DDC_BUS_PORT_TC2] = GMBUS_PIN_10_TC2_ICP,
- [ADLS_DDC_BUS_PORT_TC3] = GMBUS_PIN_11_TC3_ICP,
- [ADLS_DDC_BUS_PORT_TC4] = GMBUS_PIN_12_TC4_ICP,
+ [GMBUS_PIN_1_BXT] = ICL_DDC_BUS_DDI_A,
+ [GMBUS_PIN_9_TC1_ICP] = ADLS_DDC_BUS_PORT_TC1,
+ [GMBUS_PIN_10_TC2_ICP] = ADLS_DDC_BUS_PORT_TC2,
+ [GMBUS_PIN_11_TC3_ICP] = ADLS_DDC_BUS_PORT_TC3,
+ [GMBUS_PIN_12_TC4_ICP] = ADLS_DDC_BUS_PORT_TC4,
};
static const u8 gen9bc_tgp_ddc_pin_map[] = {
- [DDC_BUS_DDI_B] = GMBUS_PIN_2_BXT,
- [DDC_BUS_DDI_C] = GMBUS_PIN_9_TC1_ICP,
- [DDC_BUS_DDI_D] = GMBUS_PIN_10_TC2_ICP,
+ [GMBUS_PIN_2_BXT] = DDC_BUS_DDI_B,
+ [GMBUS_PIN_9_TC1_ICP] = DDC_BUS_DDI_C,
+ [GMBUS_PIN_10_TC2_ICP] = DDC_BUS_DDI_D,
};
static const u8 adlp_ddc_pin_map[] = {
- [ICL_DDC_BUS_DDI_A] = GMBUS_PIN_1_BXT,
- [ICL_DDC_BUS_DDI_B] = GMBUS_PIN_2_BXT,
- [ADLP_DDC_BUS_PORT_TC1] = GMBUS_PIN_9_TC1_ICP,
- [ADLP_DDC_BUS_PORT_TC2] = GMBUS_PIN_10_TC2_ICP,
- [ADLP_DDC_BUS_PORT_TC3] = GMBUS_PIN_11_TC3_ICP,
- [ADLP_DDC_BUS_PORT_TC4] = GMBUS_PIN_12_TC4_ICP,
+ [GMBUS_PIN_1_BXT] = ICL_DDC_BUS_DDI_A,
+ [GMBUS_PIN_2_BXT] = ICL_DDC_BUS_DDI_B,
+ [GMBUS_PIN_9_TC1_ICP] = ADLP_DDC_BUS_PORT_TC1,
+ [GMBUS_PIN_10_TC2_ICP] = ADLP_DDC_BUS_PORT_TC2,
+ [GMBUS_PIN_11_TC3_ICP] = ADLP_DDC_BUS_PORT_TC3,
+ [GMBUS_PIN_12_TC4_ICP] = ADLP_DDC_BUS_PORT_TC4,
};
static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin)
{
const u8 *ddc_pin_map;
- int n_entries;
+ int i, n_entries;
if (HAS_PCH_MTP(i915) || IS_ALDERLAKE_P(i915)) {
ddc_pin_map = adlp_ddc_pin_map;
@@ -2219,8 +2219,10 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin)
return vbt_pin;
}
- if (vbt_pin < n_entries && ddc_pin_map[vbt_pin] != 0)
- return ddc_pin_map[vbt_pin];
+ for (i = 0; i < n_entries; i++) {
+ if (ddc_pin_map[i] == vbt_pin)
+ return i;
+ }
drm_dbg_kms(&i915->drm,
"Ignoring alternate pin: VBT claims DDC pin %d, which is not valid for this platform\n",
@@ -2675,8 +2677,9 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata,
supports_tbt = intel_bios_encoder_supports_tbt(devdata);
drm_dbg_kms(&i915->drm,
- "Port %c VBT info: CRT:%d DVI:%d HDMI:%d DP:%d eDP:%d DSI:%d LSPCON:%d USB-Type-C:%d TBT:%d DSC:%d\n",
+ "Port %c VBT info: CRT:%d DVI:%d HDMI:%d DP:%d eDP:%d DSI:%d DP++:%d LSPCON:%d USB-Type-C:%d TBT:%d DSC:%d\n",
port_name(port), is_crt, is_dvi, is_hdmi, is_dp, is_edp, is_dsi,
+ intel_bios_encoder_supports_dp_dual_mode(devdata),
intel_bios_encoder_is_lspcon(devdata),
supports_typec_usb, supports_tbt,
devdata->dsc != NULL);
@@ -3030,6 +3033,13 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size)
return vbt;
}
+static u32 intel_spi_read(struct intel_uncore *uncore, u32 offset)
+{
+ intel_uncore_write(uncore, PRIMARY_SPI_ADDRESS, offset);
+
+ return intel_uncore_read(uncore, PRIMARY_SPI_TRIGGER);
+}
+
static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915)
{
u32 count, data, found, store = 0;
@@ -3046,9 +3056,7 @@ static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915)
oprom_offset &= OROM_OFFSET_MASK;
for (count = 0; count < oprom_size; count += 4) {
- intel_uncore_write(&i915->uncore, PRIMARY_SPI_ADDRESS, oprom_offset + count);
- data = intel_uncore_read(&i915->uncore, PRIMARY_SPI_TRIGGER);
-
+ data = intel_spi_read(&i915->uncore, oprom_offset + count);
if (data == *((const u32 *)"$VBT")) {
found = oprom_offset + count;
break;
@@ -3059,20 +3067,16 @@ static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915)
goto err_not_found;
/* Get VBT size and allocate space for the VBT */
- intel_uncore_write(&i915->uncore, PRIMARY_SPI_ADDRESS, found +
- offsetof(struct vbt_header, vbt_size));
- vbt_size = intel_uncore_read(&i915->uncore, PRIMARY_SPI_TRIGGER);
+ vbt_size = intel_spi_read(&i915->uncore,
+ found + offsetof(struct vbt_header, vbt_size));
vbt_size &= 0xffff;
vbt = kzalloc(round_up(vbt_size, 4), GFP_KERNEL);
if (!vbt)
goto err_not_found;
- for (count = 0; count < vbt_size; count += 4) {
- intel_uncore_write(&i915->uncore, PRIMARY_SPI_ADDRESS, found + count);
- data = intel_uncore_read(&i915->uncore, PRIMARY_SPI_TRIGGER);
- *(vbt + store++) = data;
- }
+ for (count = 0; count < vbt_size; count += 4)
+ *(vbt + store++) = intel_spi_read(&i915->uncore, found + count);
if (!intel_bios_is_valid_vbt(vbt, vbt_size))
goto err_free_vbt;
@@ -3424,7 +3428,7 @@ bool intel_bios_is_port_present(struct drm_i915_private *i915, enum port port)
return false;
}
-static bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata)
+bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata)
{
const struct child_device_config *child = &devdata->child;
@@ -3443,15 +3447,6 @@ static bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_enc
return false;
}
-bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *i915,
- enum port port)
-{
- const struct intel_bios_encoder_data *devdata =
- intel_bios_encoder_data_lookup(i915, port);
-
- return devdata && intel_bios_encoder_supports_dp_dual_mode(devdata);
-}
-
/**
* intel_bios_is_dsi_present - is DSI present in VBT
* @i915: i915 device instance
@@ -3578,84 +3573,82 @@ bool intel_bios_get_dsc_params(struct intel_encoder *encoder,
return false;
}
+static const u8 adlp_aux_ch_map[] = {
+ [AUX_CH_A] = DP_AUX_A,
+ [AUX_CH_B] = DP_AUX_B,
+ [AUX_CH_C] = DP_AUX_C,
+ [AUX_CH_D_XELPD] = DP_AUX_D,
+ [AUX_CH_E_XELPD] = DP_AUX_E,
+ [AUX_CH_USBC1] = DP_AUX_F,
+ [AUX_CH_USBC2] = DP_AUX_G,
+ [AUX_CH_USBC3] = DP_AUX_H,
+ [AUX_CH_USBC4] = DP_AUX_I,
+};
+
+/*
+ * ADL-S VBT uses PHY based mapping. Combo PHYs A,B,C,D,E
+ * map to DDI A,TC1,TC2,TC3,TC4 respectively.
+ */
+static const u8 adls_aux_ch_map[] = {
+ [AUX_CH_A] = DP_AUX_A,
+ [AUX_CH_USBC1] = DP_AUX_B,
+ [AUX_CH_USBC2] = DP_AUX_C,
+ [AUX_CH_USBC3] = DP_AUX_D,
+ [AUX_CH_USBC4] = DP_AUX_E,
+};
+
+/*
+ * RKL/DG1 VBT uses PHY based mapping. Combo PHYs A,B,C,D
+ * map to DDI A,B,TC1,TC2 respectively.
+ */
+static const u8 rkl_aux_ch_map[] = {
+ [AUX_CH_A] = DP_AUX_A,
+ [AUX_CH_B] = DP_AUX_B,
+ [AUX_CH_USBC1] = DP_AUX_C,
+ [AUX_CH_USBC2] = DP_AUX_D,
+};
+
+static const u8 direct_aux_ch_map[] = {
+ [AUX_CH_A] = DP_AUX_A,
+ [AUX_CH_B] = DP_AUX_B,
+ [AUX_CH_C] = DP_AUX_C,
+ [AUX_CH_D] = DP_AUX_D, /* aka AUX_CH_USBC1 */
+ [AUX_CH_E] = DP_AUX_E, /* aka AUX_CH_USBC2 */
+ [AUX_CH_F] = DP_AUX_F, /* aka AUX_CH_USBC3 */
+ [AUX_CH_G] = DP_AUX_G, /* aka AUX_CH_USBC4 */
+ [AUX_CH_H] = DP_AUX_H, /* aka AUX_CH_USBC5 */
+ [AUX_CH_I] = DP_AUX_I, /* aka AUX_CH_USBC6 */
+};
+
static enum aux_ch map_aux_ch(struct drm_i915_private *i915, u8 aux_channel)
{
- enum aux_ch aux_ch;
+ const u8 *aux_ch_map;
+ int i, n_entries;
- /*
- * RKL/DG1 VBT uses PHY based mapping. Combo PHYs A,B,C,D
- * map to DDI A,B,TC1,TC2 respectively.
- *
- * ADL-S VBT uses PHY based mapping. Combo PHYs A,B,C,D,E
- * map to DDI A,TC1,TC2,TC3,TC4 respectively.
- */
- switch (aux_channel) {
- case DP_AUX_A:
- aux_ch = AUX_CH_A;
- break;
- case DP_AUX_B:
- if (IS_ALDERLAKE_S(i915))
- aux_ch = AUX_CH_USBC1;
- else
- aux_ch = AUX_CH_B;
- break;
- case DP_AUX_C:
- if (IS_ALDERLAKE_S(i915))
- aux_ch = AUX_CH_USBC2;
- else if (IS_DG1(i915) || IS_ROCKETLAKE(i915))
- aux_ch = AUX_CH_USBC1;
- else
- aux_ch = AUX_CH_C;
- break;
- case DP_AUX_D:
- if (DISPLAY_VER(i915) >= 13)
- aux_ch = AUX_CH_D_XELPD;
- else if (IS_ALDERLAKE_S(i915))
- aux_ch = AUX_CH_USBC3;
- else if (IS_DG1(i915) || IS_ROCKETLAKE(i915))
- aux_ch = AUX_CH_USBC2;
- else
- aux_ch = AUX_CH_D;
- break;
- case DP_AUX_E:
- if (DISPLAY_VER(i915) >= 13)
- aux_ch = AUX_CH_E_XELPD;
- else if (IS_ALDERLAKE_S(i915))
- aux_ch = AUX_CH_USBC4;
- else
- aux_ch = AUX_CH_E;
- break;
- case DP_AUX_F:
- if (DISPLAY_VER(i915) >= 13)
- aux_ch = AUX_CH_USBC1;
- else
- aux_ch = AUX_CH_F;
- break;
- case DP_AUX_G:
- if (DISPLAY_VER(i915) >= 13)
- aux_ch = AUX_CH_USBC2;
- else
- aux_ch = AUX_CH_G;
- break;
- case DP_AUX_H:
- if (DISPLAY_VER(i915) >= 13)
- aux_ch = AUX_CH_USBC3;
- else
- aux_ch = AUX_CH_H;
- break;
- case DP_AUX_I:
- if (DISPLAY_VER(i915) >= 13)
- aux_ch = AUX_CH_USBC4;
- else
- aux_ch = AUX_CH_I;
- break;
- default:
- MISSING_CASE(aux_channel);
- aux_ch = AUX_CH_A;
- break;
+ if (DISPLAY_VER(i915) >= 13) {
+ aux_ch_map = adlp_aux_ch_map;
+ n_entries = ARRAY_SIZE(adlp_aux_ch_map);
+ } else if (IS_ALDERLAKE_S(i915)) {
+ aux_ch_map = adls_aux_ch_map;
+ n_entries = ARRAY_SIZE(adls_aux_ch_map);
+ } else if (IS_DG1(i915) || IS_ROCKETLAKE(i915)) {
+ aux_ch_map = rkl_aux_ch_map;
+ n_entries = ARRAY_SIZE(rkl_aux_ch_map);
+ } else {
+ aux_ch_map = direct_aux_ch_map;
+ n_entries = ARRAY_SIZE(direct_aux_ch_map);
+ }
+
+ for (i = 0; i < n_entries; i++) {
+ if (aux_ch_map[i] == aux_channel)
+ return i;
}
- return aux_ch;
+ drm_dbg_kms(&i915->drm,
+ "Ignoring alternate AUX CH: VBT claims AUX 0x%x, which is not valid for this platform\n",
+ aux_channel);
+
+ return AUX_CH_NONE;
}
enum aux_ch intel_bios_dp_aux_ch(const struct intel_bios_encoder_data *devdata)
diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
index 8a0730c9b48c..45fae97d9719 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.h
+++ b/drivers/gpu/drm/i915/display/intel_bios.h
@@ -247,7 +247,6 @@ bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin);
bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port);
bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
-bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum port port);
bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port);
bool intel_bios_get_dsc_params(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
@@ -264,6 +263,7 @@ bool intel_bios_encoder_supports_dp(const struct intel_bios_encoder_data *devdat
bool intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata);
bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata);
bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devdata);
+bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata);
bool intel_bios_encoder_is_lspcon(const struct intel_bios_encoder_data *devdata);
bool intel_bios_encoder_lane_reversal(const struct intel_bios_encoder_data *devdata);
bool intel_bios_encoder_hpd_invert(const struct intel_bios_encoder_data *devdata);
diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c
index 202321ffbe2a..bef96db62c80 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -150,6 +150,9 @@ int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
{
int ret;
+ if (DISPLAY_VER(dev_priv) >= 14)
+ return 0;
+
/* bspec says to keep retrying for at least 1 ms */
ret = skl_pcode_request(&dev_priv->uncore, ICL_PCODE_SAGV_DE_MEM_SS_CONFIG,
points_mask,
@@ -179,7 +182,7 @@ static int mtl_read_qgv_point_info(struct drm_i915_private *dev_priv,
val2 = intel_uncore_read(&dev_priv->uncore,
MTL_MEM_SS_INFO_QGV_POINT_HIGH(point));
dclk = REG_FIELD_GET(MTL_DCLK_MASK, val);
- sp->dclk = DIV_ROUND_UP((16667 * dclk), 1000);
+ sp->dclk = DIV_ROUND_CLOSEST(16667 * dclk, 1000);
sp->t_rp = REG_FIELD_GET(MTL_TRP_MASK, val);
sp->t_rcd = REG_FIELD_GET(MTL_TRCD_MASK, val);
@@ -376,7 +379,7 @@ static const struct intel_sa_info mtl_sa_info = {
.deburst = 32,
.deprogbwlimit = 38, /* GB/s */
.displayrtids = 256,
- .derating = 20,
+ .derating = 10,
};
static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel_sa_info *sa)
@@ -531,10 +534,14 @@ static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
bi->deratedbw[j] = min(maxdebw,
bw * (100 - sa->derating) / 100);
+ bi->peakbw[j] = DIV_ROUND_CLOSEST(sp->dclk *
+ num_channels *
+ qi.channel_width, 8);
drm_dbg_kms(&dev_priv->drm,
- "BW%d / QGV %d: num_planes=%d deratedbw=%u\n",
- i, j, bi->num_planes, bi->deratedbw[j]);
+ "BW%d / QGV %d: num_planes=%d deratedbw=%u peakbw: %u\n",
+ i, j, bi->num_planes, bi->deratedbw[j],
+ bi->peakbw[j]);
}
for (j = 0; j < qi.num_psf_points; j++) {
@@ -586,8 +593,8 @@ static void dg2_get_bw_info(struct drm_i915_private *i915)
i915->display.sagv.status = I915_SAGV_NOT_CONTROLLED;
}
-static unsigned int icl_max_bw(struct drm_i915_private *dev_priv,
- int num_planes, int qgv_point)
+static unsigned int icl_max_bw_index(struct drm_i915_private *dev_priv,
+ int num_planes, int qgv_point)
{
int i;
@@ -608,14 +615,14 @@ static unsigned int icl_max_bw(struct drm_i915_private *dev_priv,
return UINT_MAX;
if (num_planes >= bi->num_planes)
- return bi->deratedbw[qgv_point];
+ return i;
}
- return 0;
+ return UINT_MAX;
}
-static unsigned int tgl_max_bw(struct drm_i915_private *dev_priv,
- int num_planes, int qgv_point)
+static unsigned int tgl_max_bw_index(struct drm_i915_private *dev_priv,
+ int num_planes, int qgv_point)
{
int i;
@@ -636,10 +643,10 @@ static unsigned int tgl_max_bw(struct drm_i915_private *dev_priv,
return UINT_MAX;
if (num_planes <= bi->num_planes)
- return bi->deratedbw[qgv_point];
+ return i;
}
- return dev_priv->display.bw.max[0].deratedbw[qgv_point];
+ return 0;
}
static unsigned int adl_psf_bw(struct drm_i915_private *dev_priv,
@@ -796,6 +803,210 @@ intel_atomic_get_bw_state(struct intel_atomic_state *state)
return to_intel_bw_state(bw_state);
}
+static int mtl_find_qgv_points(struct drm_i915_private *i915,
+ unsigned int data_rate,
+ unsigned int num_active_planes,
+ struct intel_bw_state *new_bw_state)
+{
+ unsigned int best_rate = UINT_MAX;
+ unsigned int num_qgv_points = i915->display.bw.max[0].num_qgv_points;
+ unsigned int qgv_peak_bw = 0;
+ int i;
+ int ret;
+
+ ret = intel_atomic_lock_global_state(&new_bw_state->base);
+ if (ret)
+ return ret;
+
+ /*
+ * If SAGV cannot be enabled, disable the pcode SAGV by passing all 1's
+ * for qgv peak bw in PM Demand request. So assign UINT_MAX if SAGV is
+ * not enabled. PM Demand code will clamp the value for the register
+ */
+ if (!intel_can_enable_sagv(i915, new_bw_state)) {
+ new_bw_state->qgv_point_peakbw = U16_MAX;
+ drm_dbg_kms(&i915->drm, "No SAGV, use UINT_MAX as peak bw.");
+ return 0;
+ }
+
+ /*
+ * Find the best QGV point by comparing the data_rate with max data rate
+ * offered per plane group
+ */
+ for (i = 0; i < num_qgv_points; i++) {
+ unsigned int bw_index =
+ tgl_max_bw_index(i915, num_active_planes, i);
+ unsigned int max_data_rate;
+
+ if (bw_index >= ARRAY_SIZE(i915->display.bw.max))
+ continue;
+
+ max_data_rate = i915->display.bw.max[bw_index].deratedbw[i];
+
+ if (max_data_rate < data_rate)
+ continue;
+
+ if (max_data_rate - data_rate < best_rate) {
+ best_rate = max_data_rate - data_rate;
+ qgv_peak_bw = i915->display.bw.max[bw_index].peakbw[i];
+ }
+
+ drm_dbg_kms(&i915->drm, "QGV point %d: max bw %d required %d qgv_peak_bw: %d\n",
+ i, max_data_rate, data_rate, qgv_peak_bw);
+ }
+
+ drm_dbg_kms(&i915->drm, "Matching peaks QGV bw: %d for required data rate: %d\n",
+ qgv_peak_bw, data_rate);
+
+ /*
+ * The display configuration cannot be supported if no QGV point
+ * satisfying the required data rate is found
+ */
+ if (qgv_peak_bw == 0) {
+ drm_dbg_kms(&i915->drm, "No QGV points for bw %d for display configuration(%d active planes).\n",
+ data_rate, num_active_planes);
+ return -EINVAL;
+ }
+
+ /* MTL PM DEMAND expects QGV BW parameter in multiples of 100 mbps */
+ new_bw_state->qgv_point_peakbw = DIV_ROUND_CLOSEST(qgv_peak_bw, 100);
+
+ return 0;
+}
+
+static int icl_find_qgv_points(struct drm_i915_private *i915,
+ unsigned int data_rate,
+ unsigned int num_active_planes,
+ const struct intel_bw_state *old_bw_state,
+ struct intel_bw_state *new_bw_state)
+{
+ unsigned int max_bw_point = 0;
+ unsigned int max_bw = 0;
+ unsigned int num_psf_gv_points = i915->display.bw.max[0].num_psf_gv_points;
+ unsigned int num_qgv_points = i915->display.bw.max[0].num_qgv_points;
+ u16 psf_points = 0;
+ u16 qgv_points = 0;
+ int i;
+ int ret;
+
+ ret = intel_atomic_lock_global_state(&new_bw_state->base);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < num_qgv_points; i++) {
+ unsigned int idx;
+ unsigned int max_data_rate;
+
+ if (DISPLAY_VER(i915) > 11)
+ idx = tgl_max_bw_index(i915, num_active_planes, i);
+ else
+ idx = icl_max_bw_index(i915, num_active_planes, i);
+
+ if (idx >= ARRAY_SIZE(i915->display.bw.max))
+ continue;
+
+ max_data_rate = i915->display.bw.max[idx].deratedbw[i];
+
+ /*
+ * We need to know which qgv point gives us
+ * maximum bandwidth in order to disable SAGV
+ * if we find that we exceed SAGV block time
+ * with watermarks. By that moment we already
+ * have those, as it is calculated earlier in
+ * intel_atomic_check,
+ */
+ if (max_data_rate > max_bw) {
+ max_bw_point = i;
+ max_bw = max_data_rate;
+ }
+ if (max_data_rate >= data_rate)
+ qgv_points |= BIT(i);
+
+ drm_dbg_kms(&i915->drm, "QGV point %d: max bw %d required %d\n",
+ i, max_data_rate, data_rate);
+ }
+
+ for (i = 0; i < num_psf_gv_points; i++) {
+ unsigned int max_data_rate = adl_psf_bw(i915, i);
+
+ if (max_data_rate >= data_rate)
+ psf_points |= BIT(i);
+
+ drm_dbg_kms(&i915->drm, "PSF GV point %d: max bw %d"
+ " required %d\n",
+ i, max_data_rate, data_rate);
+ }
+
+ /*
+ * BSpec states that we always should have at least one allowed point
+ * left, so if we couldn't - simply reject the configuration for obvious
+ * reasons.
+ */
+ if (qgv_points == 0) {
+ drm_dbg_kms(&i915->drm, "No QGV points provide sufficient memory"
+ " bandwidth %d for display configuration(%d active planes).\n",
+ data_rate, num_active_planes);
+ return -EINVAL;
+ }
+
+ if (num_psf_gv_points > 0 && psf_points == 0) {
+ drm_dbg_kms(&i915->drm, "No PSF GV points provide sufficient memory"
+ " bandwidth %d for display configuration(%d active planes).\n",
+ data_rate, num_active_planes);
+ return -EINVAL;
+ }
+
+ /*
+ * Leave only single point with highest bandwidth, if
+ * we can't enable SAGV due to the increased memory latency it may
+ * cause.
+ */
+ if (!intel_can_enable_sagv(i915, new_bw_state)) {
+ qgv_points = BIT(max_bw_point);
+ drm_dbg_kms(&i915->drm, "No SAGV, using single QGV point %d\n",
+ max_bw_point);
+ }
+
+ /*
+ * We store the ones which need to be masked as that is what PCode
+ * actually accepts as a parameter.
+ */
+ new_bw_state->qgv_points_mask =
+ ~(ICL_PCODE_REQ_QGV_PT(qgv_points) |
+ ADLS_PCODE_REQ_PSF_PT(psf_points)) &
+ icl_qgv_points_mask(i915);
+
+ /*
+ * If the actual mask had changed we need to make sure that
+ * the commits are serialized(in case this is a nomodeset, nonblocking)
+ */
+ if (new_bw_state->qgv_points_mask != old_bw_state->qgv_points_mask) {
+ ret = intel_atomic_serialize_global_state(&new_bw_state->base);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int intel_bw_check_qgv_points(struct drm_i915_private *i915,
+ const struct intel_bw_state *old_bw_state,
+ struct intel_bw_state *new_bw_state)
+{
+ unsigned int data_rate = intel_bw_data_rate(i915, new_bw_state);
+ unsigned int num_active_planes =
+ intel_bw_num_active_planes(i915, new_bw_state);
+
+ data_rate = DIV_ROUND_UP(data_rate, 1000);
+
+ if (DISPLAY_VER(i915) >= 14)
+ return mtl_find_qgv_points(i915, data_rate, num_active_planes,
+ new_bw_state);
+ else
+ return icl_find_qgv_points(i915, data_rate, num_active_planes,
+ old_bw_state, new_bw_state);
+}
+
static bool intel_bw_state_changed(struct drm_i915_private *i915,
const struct intel_bw_state *old_bw_state,
const struct intel_bw_state *new_bw_state)
@@ -1042,20 +1253,14 @@ static int intel_bw_check_data_rate(struct intel_atomic_state *state, bool *chan
int intel_bw_atomic_check(struct intel_atomic_state *state)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
- const struct intel_bw_state *old_bw_state;
- struct intel_bw_state *new_bw_state;
- unsigned int data_rate;
- unsigned int num_active_planes;
- int i, ret;
- u16 qgv_points = 0, psf_points = 0;
- unsigned int max_bw_point = 0, max_bw = 0;
- unsigned int num_qgv_points = dev_priv->display.bw.max[0].num_qgv_points;
- unsigned int num_psf_gv_points = dev_priv->display.bw.max[0].num_psf_gv_points;
bool changed = false;
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_bw_state *new_bw_state;
+ const struct intel_bw_state *old_bw_state;
+ int ret;
/* FIXME earlier gens need some checks too */
- if (DISPLAY_VER(dev_priv) < 11)
+ if (DISPLAY_VER(i915) < 11)
return 0;
ret = intel_bw_check_data_rate(state, &changed);
@@ -1066,8 +1271,8 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
new_bw_state = intel_atomic_get_new_bw_state(state);
if (new_bw_state &&
- intel_can_enable_sagv(dev_priv, old_bw_state) !=
- intel_can_enable_sagv(dev_priv, new_bw_state))
+ intel_can_enable_sagv(i915, old_bw_state) !=
+ intel_can_enable_sagv(i915, new_bw_state))
changed = true;
/*
@@ -1077,101 +1282,10 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
if (!changed)
return 0;
- ret = intel_atomic_lock_global_state(&new_bw_state->base);
+ ret = intel_bw_check_qgv_points(i915, old_bw_state, new_bw_state);
if (ret)
return ret;
- data_rate = intel_bw_data_rate(dev_priv, new_bw_state);
- data_rate = DIV_ROUND_UP(data_rate, 1000);
-
- num_active_planes = intel_bw_num_active_planes(dev_priv, new_bw_state);
-
- for (i = 0; i < num_qgv_points; i++) {
- unsigned int max_data_rate;
-
- if (DISPLAY_VER(dev_priv) > 11)
- max_data_rate = tgl_max_bw(dev_priv, num_active_planes, i);
- else
- max_data_rate = icl_max_bw(dev_priv, num_active_planes, i);
- /*
- * We need to know which qgv point gives us
- * maximum bandwidth in order to disable SAGV
- * if we find that we exceed SAGV block time
- * with watermarks. By that moment we already
- * have those, as it is calculated earlier in
- * intel_atomic_check,
- */
- if (max_data_rate > max_bw) {
- max_bw_point = i;
- max_bw = max_data_rate;
- }
- if (max_data_rate >= data_rate)
- qgv_points |= BIT(i);
-
- drm_dbg_kms(&dev_priv->drm, "QGV point %d: max bw %d required %d\n",
- i, max_data_rate, data_rate);
- }
-
- for (i = 0; i < num_psf_gv_points; i++) {
- unsigned int max_data_rate = adl_psf_bw(dev_priv, i);
-
- if (max_data_rate >= data_rate)
- psf_points |= BIT(i);
-
- drm_dbg_kms(&dev_priv->drm, "PSF GV point %d: max bw %d"
- " required %d\n",
- i, max_data_rate, data_rate);
- }
-
- /*
- * BSpec states that we always should have at least one allowed point
- * left, so if we couldn't - simply reject the configuration for obvious
- * reasons.
- */
- if (qgv_points == 0) {
- drm_dbg_kms(&dev_priv->drm, "No QGV points provide sufficient memory"
- " bandwidth %d for display configuration(%d active planes).\n",
- data_rate, num_active_planes);
- return -EINVAL;
- }
-
- if (num_psf_gv_points > 0 && psf_points == 0) {
- drm_dbg_kms(&dev_priv->drm, "No PSF GV points provide sufficient memory"
- " bandwidth %d for display configuration(%d active planes).\n",
- data_rate, num_active_planes);
- return -EINVAL;
- }
-
- /*
- * Leave only single point with highest bandwidth, if
- * we can't enable SAGV due to the increased memory latency it may
- * cause.
- */
- if (!intel_can_enable_sagv(dev_priv, new_bw_state)) {
- qgv_points = BIT(max_bw_point);
- drm_dbg_kms(&dev_priv->drm, "No SAGV, using single QGV point %d\n",
- max_bw_point);
- }
-
- /*
- * We store the ones which need to be masked as that is what PCode
- * actually accepts as a parameter.
- */
- new_bw_state->qgv_points_mask =
- ~(ICL_PCODE_REQ_QGV_PT(qgv_points) |
- ADLS_PCODE_REQ_PSF_PT(psf_points)) &
- icl_qgv_points_mask(dev_priv);
-
- /*
- * If the actual mask had changed we need to make sure that
- * the commits are serialized(in case this is a nomodeset, nonblocking)
- */
- if (new_bw_state->qgv_points_mask != old_bw_state->qgv_points_mask) {
- ret = intel_atomic_serialize_global_state(&new_bw_state->base);
- if (ret)
- return ret;
- }
-
return 0;
}
diff --git a/drivers/gpu/drm/i915/display/intel_bw.h b/drivers/gpu/drm/i915/display/intel_bw.h
index f20292143745..59cb4fc5db76 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.h
+++ b/drivers/gpu/drm/i915/display/intel_bw.h
@@ -35,6 +35,12 @@ struct intel_bw_state {
u8 active_pipes;
/*
+ * From MTL onwards, to lock a QGV point, punit expects the peak BW of
+ * the selected QGV point as the parameter in multiples of 100MB/s
+ */
+ u16 qgv_point_peakbw;
+
+ /*
* Current QGV points mask, which restricts
* some particular SAGV states, not to confuse
* with pipe_sagv_mask.
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 2aaaba090cc0..4207863b7b2a 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -1908,7 +1908,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
* mailbox communication, skip
* this step.
*/
- if (DISPLAY_VER(dev_priv) >= 14)
+ if (DISPLAY_VER(dev_priv) >= 14 || IS_DG2(dev_priv))
/* NOOP */;
else if (DISPLAY_VER(dev_priv) >= 11)
ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
@@ -1944,10 +1944,10 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
* NOOP - No Pcode communication needed for
* Display versions 14 and beyond
*/;
- else if (DISPLAY_VER(dev_priv) >= 11)
+ else if (DISPLAY_VER(dev_priv) >= 11 && !IS_DG2(dev_priv))
ret = snb_pcode_write(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
cdclk_config->voltage_level);
- else
+ if (DISPLAY_VER(dev_priv) < 11) {
/*
* The timeout isn't specified, the 2ms used here is based on
* experiment.
@@ -1958,7 +1958,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
HSW_PCODE_DE_WRITE_FREQ_REQ,
cdclk_config->voltage_level,
150, 2);
-
+ }
if (ret) {
drm_err(&dev_priv->drm,
"PCode CDCLK freq set failed, (err %d, freq %d)\n",
@@ -2254,6 +2254,38 @@ void intel_cdclk_dump_config(struct drm_i915_private *i915,
cdclk_config->voltage_level);
}
+static void intel_pcode_notify(struct drm_i915_private *i915,
+ u8 voltage_level,
+ u8 active_pipe_count,
+ u16 cdclk,
+ bool cdclk_update_valid,
+ bool pipe_count_update_valid)
+{
+ int ret;
+ u32 update_mask = 0;
+
+ if (!IS_DG2(i915))
+ return;
+
+ update_mask = DISPLAY_TO_PCODE_UPDATE_MASK(cdclk, active_pipe_count, voltage_level);
+
+ if (cdclk_update_valid)
+ update_mask |= DISPLAY_TO_PCODE_CDCLK_VALID;
+
+ if (pipe_count_update_valid)
+ update_mask |= DISPLAY_TO_PCODE_PIPE_COUNT_VALID;
+
+ ret = skl_pcode_request(&i915->uncore, SKL_PCODE_CDCLK_CONTROL,
+ SKL_CDCLK_PREPARE_FOR_CHANGE |
+ update_mask,
+ SKL_CDCLK_READY_FOR_CHANGE,
+ SKL_CDCLK_READY_FOR_CHANGE, 3);
+ if (ret)
+ drm_err(&i915->drm,
+ "Failed to inform PCU about display config (err %d)\n",
+ ret);
+}
+
/**
* intel_set_cdclk - Push the CDCLK configuration to the hardware
* @dev_priv: i915 device
@@ -2323,6 +2355,88 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
}
}
+static void intel_cdclk_pcode_pre_notify(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_cdclk_state *old_cdclk_state =
+ intel_atomic_get_old_cdclk_state(state);
+ const struct intel_cdclk_state *new_cdclk_state =
+ intel_atomic_get_new_cdclk_state(state);
+ unsigned int cdclk = 0; u8 voltage_level, num_active_pipes = 0;
+ bool change_cdclk, update_pipe_count;
+
+ if (!intel_cdclk_changed(&old_cdclk_state->actual,
+ &new_cdclk_state->actual) &&
+ new_cdclk_state->active_pipes ==
+ old_cdclk_state->active_pipes)
+ return;
+
+ /* According to "Sequence Before Frequency Change", voltage level set to 0x3 */
+ voltage_level = DISPLAY_TO_PCODE_VOLTAGE_MAX;
+
+ change_cdclk = new_cdclk_state->actual.cdclk != old_cdclk_state->actual.cdclk;
+ update_pipe_count = hweight8(new_cdclk_state->active_pipes) >
+ hweight8(old_cdclk_state->active_pipes);
+
+ /*
+ * According to "Sequence Before Frequency Change",
+ * if CDCLK is increasing, set bits 25:16 to upcoming CDCLK,
+ * if CDCLK is decreasing or not changing, set bits 25:16 to current CDCLK,
+ * which basically means we choose the maximum of old and new CDCLK, if we know both
+ */
+ if (change_cdclk)
+ cdclk = max(new_cdclk_state->actual.cdclk, old_cdclk_state->actual.cdclk);
+
+ /*
+ * According to "Sequence For Pipe Count Change",
+ * if pipe count is increasing, set bits 25:16 to upcoming pipe count
+ * (power well is enabled)
+ * no action if it is decreasing, before the change
+ */
+ if (update_pipe_count)
+ num_active_pipes = hweight8(new_cdclk_state->active_pipes);
+
+ intel_pcode_notify(i915, voltage_level, num_active_pipes, cdclk,
+ change_cdclk, update_pipe_count);
+}
+
+static void intel_cdclk_pcode_post_notify(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_cdclk_state *new_cdclk_state =
+ intel_atomic_get_new_cdclk_state(state);
+ const struct intel_cdclk_state *old_cdclk_state =
+ intel_atomic_get_old_cdclk_state(state);
+ unsigned int cdclk = 0; u8 voltage_level, num_active_pipes = 0;
+ bool update_cdclk, update_pipe_count;
+
+ /* According to "Sequence After Frequency Change", set voltage to used level */
+ voltage_level = new_cdclk_state->actual.voltage_level;
+
+ update_cdclk = new_cdclk_state->actual.cdclk != old_cdclk_state->actual.cdclk;
+ update_pipe_count = hweight8(new_cdclk_state->active_pipes) <
+ hweight8(old_cdclk_state->active_pipes);
+
+ /*
+ * According to "Sequence After Frequency Change",
+ * set bits 25:16 to current CDCLK
+ */
+ if (update_cdclk)
+ cdclk = new_cdclk_state->actual.cdclk;
+
+ /*
+ * According to "Sequence For Pipe Count Change",
+ * if pipe count is decreasing, set bits 25:16 to current pipe count,
+ * after the change(power well is disabled)
+ * no action if it is increasing, after the change
+ */
+ if (update_pipe_count)
+ num_active_pipes = hweight8(new_cdclk_state->active_pipes);
+
+ intel_pcode_notify(i915, voltage_level, num_active_pipes, cdclk,
+ update_cdclk, update_pipe_count);
+}
+
/**
* intel_set_cdclk_pre_plane_update - Push the CDCLK state to the hardware
* @state: intel atomic state
@@ -2333,7 +2447,7 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
void
intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_cdclk_state *old_cdclk_state =
intel_atomic_get_old_cdclk_state(state);
const struct intel_cdclk_state *new_cdclk_state =
@@ -2344,11 +2458,14 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
&new_cdclk_state->actual))
return;
+ if (IS_DG2(i915))
+ intel_cdclk_pcode_pre_notify(state);
+
if (pipe == INVALID_PIPE ||
old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) {
- drm_WARN_ON(&dev_priv->drm, !new_cdclk_state->base.changed);
+ drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
- intel_set_cdclk(dev_priv, &new_cdclk_state->actual, pipe);
+ intel_set_cdclk(i915, &new_cdclk_state->actual, pipe);
}
}
@@ -2362,7 +2479,7 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
void
intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_cdclk_state *old_cdclk_state =
intel_atomic_get_old_cdclk_state(state);
const struct intel_cdclk_state *new_cdclk_state =
@@ -2373,11 +2490,14 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
&new_cdclk_state->actual))
return;
+ if (IS_DG2(i915))
+ intel_cdclk_pcode_post_notify(state);
+
if (pipe != INVALID_PIPE &&
old_cdclk_state->actual.cdclk > new_cdclk_state->actual.cdclk) {
- drm_WARN_ON(&dev_priv->drm, !new_cdclk_state->base.changed);
+ drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
- intel_set_cdclk(dev_priv, &new_cdclk_state->actual, pipe);
+ intel_set_cdclk(i915, &new_cdclk_state->actual, pipe);
}
}
@@ -2839,7 +2959,7 @@ int intel_cdclk_atomic_check(struct intel_atomic_state *state,
{
const struct intel_cdclk_state *old_cdclk_state;
const struct intel_cdclk_state *new_cdclk_state;
- struct intel_plane_state *plane_state;
+ struct intel_plane_state __maybe_unused *plane_state;
struct intel_plane *plane;
int ret;
int i;
@@ -2883,6 +3003,21 @@ int intel_cdclk_init(struct drm_i915_private *dev_priv)
return 0;
}
+static bool intel_cdclk_need_serialize(struct drm_i915_private *i915,
+ const struct intel_cdclk_state *old_cdclk_state,
+ const struct intel_cdclk_state *new_cdclk_state)
+{
+ bool power_well_cnt_changed = hweight8(old_cdclk_state->active_pipes) !=
+ hweight8(new_cdclk_state->active_pipes);
+ bool cdclk_changed = intel_cdclk_changed(&old_cdclk_state->actual,
+ &new_cdclk_state->actual);
+ /*
+ * We need to poke hw for gen >= 12, because we notify PCode if
+ * pipe power well count changes.
+ */
+ return cdclk_changed || (IS_DG2(i915) && power_well_cnt_changed);
+}
+
int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
{
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
@@ -2904,8 +3039,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
if (ret)
return ret;
- if (intel_cdclk_changed(&old_cdclk_state->actual,
- &new_cdclk_state->actual)) {
+ if (intel_cdclk_need_serialize(dev_priv, old_cdclk_state, new_cdclk_state)) {
/*
* Also serialize commits across all crtcs
* if the actual hw needs to be poked.
@@ -3247,6 +3381,27 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv)
return freq;
}
+static int i915_cdclk_info_show(struct seq_file *m, void *unused)
+{
+ struct drm_i915_private *i915 = m->private;
+
+ seq_printf(m, "Current CD clock frequency: %d kHz\n", i915->display.cdclk.hw.cdclk);
+ seq_printf(m, "Max CD clock frequency: %d kHz\n", i915->display.cdclk.max_cdclk_freq);
+ seq_printf(m, "Max pixel clock frequency: %d kHz\n", i915->max_dotclk_freq);
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(i915_cdclk_info);
+
+void intel_cdclk_debugfs_register(struct drm_i915_private *i915)
+{
+ struct drm_minor *minor = i915->drm.primary;
+
+ debugfs_create_file("i915_cdclk_info", 0444, minor->debugfs_root,
+ i915, &i915_cdclk_info_fops);
+}
+
static const struct intel_cdclk_funcs mtl_cdclk_funcs = {
.get_cdclk = bxt_get_cdclk,
.set_cdclk = bxt_set_cdclk,
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h
index 51e2f6a11ce4..48fd7d39e0cd 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.h
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.h
@@ -82,5 +82,6 @@ intel_atomic_get_cdclk_state(struct intel_atomic_state *state);
to_intel_cdclk_state(intel_atomic_get_new_global_obj_state(state, &to_i915(state->base.dev)->display.cdclk.obj))
int intel_cdclk_init(struct drm_i915_private *dev_priv);
+void intel_cdclk_debugfs_register(struct drm_i915_private *i915);
#endif /* __INTEL_CDCLK_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index 36aac88143ac..8966e6560516 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -70,6 +70,11 @@ struct intel_color_funcs {
const struct drm_property_blob *blob1,
const struct drm_property_blob *blob2,
bool is_pre_csc_lut);
+ /*
+ * Read out the CSCs (if any) from the hardware into the
+ * software state. Used by eg. the hardware state checker.
+ */
+ void (*read_csc)(struct intel_crtc_state *crtc_state);
};
#define CTM_COEFF_SIGN (1ULL << 63)
@@ -116,46 +121,52 @@ struct intel_color_funcs {
#define ILK_CSC_COEFF_FP(coeff, fbits) \
(clamp_val(((coeff) >> (32 - (fbits) - 3)) + 4, 0, 0xfff) & 0xff8)
-#define ILK_CSC_COEFF_LIMITED_RANGE 0x0dc0
#define ILK_CSC_COEFF_1_0 0x7800
-
-#define ILK_CSC_POSTOFF_LIMITED_RANGE (16 * (1 << 12) / 255)
-
-/* Nop pre/post offsets */
-static const u16 ilk_csc_off_zero[3] = {};
-
-/* Identity matrix */
-static const u16 ilk_csc_coeff_identity[9] = {
- ILK_CSC_COEFF_1_0, 0, 0,
- 0, ILK_CSC_COEFF_1_0, 0,
- 0, 0, ILK_CSC_COEFF_1_0,
-};
-
-/* Limited range RGB post offsets */
-static const u16 ilk_csc_postoff_limited_range[3] = {
- ILK_CSC_POSTOFF_LIMITED_RANGE,
- ILK_CSC_POSTOFF_LIMITED_RANGE,
- ILK_CSC_POSTOFF_LIMITED_RANGE,
+#define ILK_CSC_COEFF_LIMITED_RANGE ((235 - 16) << (12 - 8)) /* exponent 0 */
+#define ILK_CSC_POSTOFF_LIMITED_RANGE (16 << (12 - 8))
+
+static const struct intel_csc_matrix ilk_csc_matrix_identity = {
+ .preoff = {},
+ .coeff = {
+ ILK_CSC_COEFF_1_0, 0, 0,
+ 0, ILK_CSC_COEFF_1_0, 0,
+ 0, 0, ILK_CSC_COEFF_1_0,
+ },
+ .postoff = {},
};
/* Full range RGB -> limited range RGB matrix */
-static const u16 ilk_csc_coeff_limited_range[9] = {
- ILK_CSC_COEFF_LIMITED_RANGE, 0, 0,
- 0, ILK_CSC_COEFF_LIMITED_RANGE, 0,
- 0, 0, ILK_CSC_COEFF_LIMITED_RANGE,
+static const struct intel_csc_matrix ilk_csc_matrix_limited_range = {
+ .preoff = {},
+ .coeff = {
+ ILK_CSC_COEFF_LIMITED_RANGE, 0, 0,
+ 0, ILK_CSC_COEFF_LIMITED_RANGE, 0,
+ 0, 0, ILK_CSC_COEFF_LIMITED_RANGE,
+ },
+ .postoff = {
+ ILK_CSC_POSTOFF_LIMITED_RANGE,
+ ILK_CSC_POSTOFF_LIMITED_RANGE,
+ ILK_CSC_POSTOFF_LIMITED_RANGE,
+ },
};
/* BT.709 full range RGB -> limited range YCbCr matrix */
-static const u16 ilk_csc_coeff_rgb_to_ycbcr[9] = {
- 0x1e08, 0x9cc0, 0xb528,
- 0x2ba8, 0x09d8, 0x37e8,
- 0xbce8, 0x9ad8, 0x1e08,
+static const struct intel_csc_matrix ilk_csc_matrix_rgb_to_ycbcr = {
+ .preoff = {},
+ .coeff = {
+ 0x1e08, 0x9cc0, 0xb528,
+ 0x2ba8, 0x09d8, 0x37e8,
+ 0xbce8, 0x9ad8, 0x1e08,
+ },
+ .postoff = {
+ 0x0800, 0x0100, 0x0800,
+ },
};
-/* Limited range YCbCr post offsets */
-static const u16 ilk_csc_postoff_rgb_to_ycbcr[3] = {
- 0x0800, 0x0100, 0x0800,
-};
+static void intel_csc_clear(struct intel_csc_matrix *csc)
+{
+ memset(csc, 0, sizeof(*csc));
+}
static bool lut_is_legacy(const struct drm_property_blob *lut)
{
@@ -189,69 +200,182 @@ static u64 *ctm_mult_by_limited(u64 *result, const u64 *input)
}
static void ilk_update_pipe_csc(struct intel_crtc *crtc,
- const u16 preoff[3],
- const u16 coeff[9],
- const u16 postoff[3])
+ const struct intel_csc_matrix *csc)
{
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
- intel_de_write_fw(i915, PIPE_CSC_PREOFF_HI(pipe), preoff[0]);
- intel_de_write_fw(i915, PIPE_CSC_PREOFF_ME(pipe), preoff[1]);
- intel_de_write_fw(i915, PIPE_CSC_PREOFF_LO(pipe), preoff[2]);
+ intel_de_write_fw(i915, PIPE_CSC_PREOFF_HI(pipe), csc->preoff[0]);
+ intel_de_write_fw(i915, PIPE_CSC_PREOFF_ME(pipe), csc->preoff[1]);
+ intel_de_write_fw(i915, PIPE_CSC_PREOFF_LO(pipe), csc->preoff[2]);
intel_de_write_fw(i915, PIPE_CSC_COEFF_RY_GY(pipe),
- coeff[0] << 16 | coeff[1]);
- intel_de_write_fw(i915, PIPE_CSC_COEFF_BY(pipe), coeff[2] << 16);
+ csc->coeff[0] << 16 | csc->coeff[1]);
+ intel_de_write_fw(i915, PIPE_CSC_COEFF_BY(pipe),
+ csc->coeff[2] << 16);
intel_de_write_fw(i915, PIPE_CSC_COEFF_RU_GU(pipe),
- coeff[3] << 16 | coeff[4]);
- intel_de_write_fw(i915, PIPE_CSC_COEFF_BU(pipe), coeff[5] << 16);
+ csc->coeff[3] << 16 | csc->coeff[4]);
+ intel_de_write_fw(i915, PIPE_CSC_COEFF_BU(pipe),
+ csc->coeff[5] << 16);
intel_de_write_fw(i915, PIPE_CSC_COEFF_RV_GV(pipe),
- coeff[6] << 16 | coeff[7]);
- intel_de_write_fw(i915, PIPE_CSC_COEFF_BV(pipe), coeff[8] << 16);
+ csc->coeff[6] << 16 | csc->coeff[7]);
+ intel_de_write_fw(i915, PIPE_CSC_COEFF_BV(pipe),
+ csc->coeff[8] << 16);
- if (DISPLAY_VER(i915) >= 7) {
- intel_de_write_fw(i915, PIPE_CSC_POSTOFF_HI(pipe),
- postoff[0]);
- intel_de_write_fw(i915, PIPE_CSC_POSTOFF_ME(pipe),
- postoff[1]);
- intel_de_write_fw(i915, PIPE_CSC_POSTOFF_LO(pipe),
- postoff[2]);
- }
+ if (DISPLAY_VER(i915) < 7)
+ return;
+
+ intel_de_write_fw(i915, PIPE_CSC_POSTOFF_HI(pipe), csc->postoff[0]);
+ intel_de_write_fw(i915, PIPE_CSC_POSTOFF_ME(pipe), csc->postoff[1]);
+ intel_de_write_fw(i915, PIPE_CSC_POSTOFF_LO(pipe), csc->postoff[2]);
+}
+
+static void ilk_read_pipe_csc(struct intel_crtc *crtc,
+ struct intel_csc_matrix *csc)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
+ u32 tmp;
+
+ csc->preoff[0] = intel_de_read_fw(i915, PIPE_CSC_PREOFF_HI(pipe));
+ csc->preoff[1] = intel_de_read_fw(i915, PIPE_CSC_PREOFF_ME(pipe));
+ csc->preoff[2] = intel_de_read_fw(i915, PIPE_CSC_PREOFF_LO(pipe));
+
+ tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_RY_GY(pipe));
+ csc->coeff[0] = tmp >> 16;
+ csc->coeff[1] = tmp & 0xffff;
+ tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_BY(pipe));
+ csc->coeff[2] = tmp >> 16;
+
+ tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_RU_GU(pipe));
+ csc->coeff[3] = tmp >> 16;
+ csc->coeff[4] = tmp & 0xffff;
+ tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_BU(pipe));
+ csc->coeff[5] = tmp >> 16;
+
+ tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_RV_GV(pipe));
+ csc->coeff[6] = tmp >> 16;
+ csc->coeff[7] = tmp & 0xffff;
+ tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_BV(pipe));
+ csc->coeff[8] = tmp >> 16;
+
+ if (DISPLAY_VER(i915) < 7)
+ return;
+
+ csc->postoff[0] = intel_de_read_fw(i915, PIPE_CSC_POSTOFF_HI(pipe));
+ csc->postoff[1] = intel_de_read_fw(i915, PIPE_CSC_POSTOFF_ME(pipe));
+ csc->postoff[2] = intel_de_read_fw(i915, PIPE_CSC_POSTOFF_LO(pipe));
+}
+
+static void ilk_read_csc(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ if (crtc_state->csc_enable)
+ ilk_read_pipe_csc(crtc, &crtc_state->csc);
+}
+
+static void skl_read_csc(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ /*
+ * Display WA #1184: skl,glk
+ * Wa_1406463849: icl
+ *
+ * Danger! On SKL-ICL *reads* from the CSC coeff/offset registers
+ * will disarm an already armed CSC double buffer update.
+ * So this must not be called while armed. Fortunately the state checker
+ * readout happens only after the update has been already been latched.
+ *
+ * On earlier and later platforms only writes to said registers will
+ * disarm the update. This is considered normal behavior and also
+ * happens with various other hardware units.
+ */
+ if (crtc_state->csc_enable)
+ ilk_read_pipe_csc(crtc, &crtc_state->csc);
}
static void icl_update_output_csc(struct intel_crtc *crtc,
- const u16 preoff[3],
- const u16 coeff[9],
- const u16 postoff[3])
+ const struct intel_csc_matrix *csc)
{
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
- intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_HI(pipe), preoff[0]);
- intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_ME(pipe), preoff[1]);
- intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_LO(pipe), preoff[2]);
+ intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_HI(pipe), csc->preoff[0]);
+ intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_ME(pipe), csc->preoff[1]);
+ intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_LO(pipe), csc->preoff[2]);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe),
- coeff[0] << 16 | coeff[1]);
+ csc->coeff[0] << 16 | csc->coeff[1]);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BY(pipe),
- coeff[2] << 16);
+ csc->coeff[2] << 16);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe),
- coeff[3] << 16 | coeff[4]);
+ csc->coeff[3] << 16 | csc->coeff[4]);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BU(pipe),
- coeff[5] << 16);
+ csc->coeff[5] << 16);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe),
- coeff[6] << 16 | coeff[7]);
+ csc->coeff[6] << 16 | csc->coeff[7]);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BV(pipe),
- coeff[8] << 16);
+ csc->coeff[8] << 16);
+
+ intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_HI(pipe), csc->postoff[0]);
+ intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_ME(pipe), csc->postoff[1]);
+ intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe), csc->postoff[2]);
+}
+
+static void icl_read_output_csc(struct intel_crtc *crtc,
+ struct intel_csc_matrix *csc)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
+ u32 tmp;
+
+ csc->preoff[0] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_PREOFF_HI(pipe));
+ csc->preoff[1] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_PREOFF_ME(pipe));
+ csc->preoff[2] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_PREOFF_LO(pipe));
+
+ tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe));
+ csc->coeff[0] = tmp >> 16;
+ csc->coeff[1] = tmp & 0xffff;
+ tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_BY(pipe));
+ csc->coeff[2] = tmp >> 16;
+
+ tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe));
+ csc->coeff[3] = tmp >> 16;
+ csc->coeff[4] = tmp & 0xffff;
+ tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_BU(pipe));
+ csc->coeff[5] = tmp >> 16;
+
+ tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe));
+ csc->coeff[6] = tmp >> 16;
+ csc->coeff[7] = tmp & 0xffff;
+ tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_BV(pipe));
+ csc->coeff[8] = tmp >> 16;
- intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_HI(pipe), postoff[0]);
- intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_ME(pipe), postoff[1]);
- intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe), postoff[2]);
+ csc->postoff[0] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_HI(pipe));
+ csc->postoff[1] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_ME(pipe));
+ csc->postoff[2] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe));
+}
+
+static void icl_read_csc(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ /*
+ * Wa_1406463849: icl
+ *
+ * See skl_read_csc()
+ */
+ if (crtc_state->csc_mode & ICL_CSC_ENABLE)
+ ilk_read_pipe_csc(crtc, &crtc_state->csc);
+
+ if (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE)
+ icl_read_output_csc(crtc, &crtc_state->output_csc);
}
static bool ilk_limited_range(const struct intel_crtc_state *crtc_state)
@@ -294,14 +418,32 @@ static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state)
return !ilk_lut_limited_range(crtc_state);
}
+static void ilk_csc_copy(struct drm_i915_private *i915,
+ struct intel_csc_matrix *dst,
+ const struct intel_csc_matrix *src)
+{
+ *dst = *src;
+
+ if (DISPLAY_VER(i915) < 7)
+ memset(dst->postoff, 0, sizeof(dst->postoff));
+}
+
static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
- u16 coeffs[9], bool limited_color_range)
+ struct intel_csc_matrix *csc,
+ bool limited_color_range)
{
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data;
const u64 *input;
u64 temp[9];
int i;
+ /* for preoff/postoff */
+ if (limited_color_range)
+ ilk_csc_copy(i915, csc, &ilk_csc_matrix_limited_range);
+ else
+ ilk_csc_copy(i915, csc, &ilk_csc_matrix_identity);
+
if (limited_color_range)
input = ctm_mult_by_limited(temp, ctm->matrix);
else
@@ -320,54 +462,49 @@ static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
*/
abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1);
- coeffs[i] = 0;
+ csc->coeff[i] = 0;
/* sign bit */
if (CTM_COEFF_NEGATIVE(input[i]))
- coeffs[i] |= 1 << 15;
+ csc->coeff[i] |= 1 << 15;
if (abs_coeff < CTM_COEFF_0_125)
- coeffs[i] |= (3 << 12) |
+ csc->coeff[i] |= (3 << 12) |
ILK_CSC_COEFF_FP(abs_coeff, 12);
else if (abs_coeff < CTM_COEFF_0_25)
- coeffs[i] |= (2 << 12) |
+ csc->coeff[i] |= (2 << 12) |
ILK_CSC_COEFF_FP(abs_coeff, 11);
else if (abs_coeff < CTM_COEFF_0_5)
- coeffs[i] |= (1 << 12) |
+ csc->coeff[i] |= (1 << 12) |
ILK_CSC_COEFF_FP(abs_coeff, 10);
else if (abs_coeff < CTM_COEFF_1_0)
- coeffs[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9);
+ csc->coeff[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9);
else if (abs_coeff < CTM_COEFF_2_0)
- coeffs[i] |= (7 << 12) |
+ csc->coeff[i] |= (7 << 12) |
ILK_CSC_COEFF_FP(abs_coeff, 8);
else
- coeffs[i] |= (6 << 12) |
+ csc->coeff[i] |= (6 << 12) |
ILK_CSC_COEFF_FP(abs_coeff, 7);
}
}
-static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
+static void ilk_assign_csc(struct intel_crtc_state *crtc_state)
{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
bool limited_color_range = ilk_csc_limited_range(crtc_state);
if (crtc_state->hw.ctm) {
- u16 coeff[9];
+ drm_WARN_ON(&i915->drm, !crtc_state->csc_enable);
- ilk_csc_convert_ctm(crtc_state, coeff, limited_color_range);
- ilk_update_pipe_csc(crtc, ilk_csc_off_zero, coeff,
- limited_color_range ?
- ilk_csc_postoff_limited_range :
- ilk_csc_off_zero);
+ ilk_csc_convert_ctm(crtc_state, &crtc_state->csc, limited_color_range);
} else if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) {
- ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
- ilk_csc_coeff_rgb_to_ycbcr,
- ilk_csc_postoff_rgb_to_ycbcr);
+ drm_WARN_ON(&i915->drm, !crtc_state->csc_enable);
+
+ ilk_csc_copy(i915, &crtc_state->csc, &ilk_csc_matrix_rgb_to_ycbcr);
} else if (limited_color_range) {
- ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
- ilk_csc_coeff_limited_range,
- ilk_csc_postoff_limited_range);
+ drm_WARN_ON(&i915->drm, !crtc_state->csc_enable);
+
+ ilk_csc_copy(i915, &crtc_state->csc, &ilk_csc_matrix_limited_range);
} else if (crtc_state->csc_enable) {
/*
* On GLK both pipe CSC and degamma LUT are controlled
@@ -377,72 +514,267 @@ static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
*/
drm_WARN_ON(&i915->drm, !IS_GEMINILAKE(i915));
- ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
- ilk_csc_coeff_identity,
- ilk_csc_off_zero);
+ ilk_csc_copy(i915, &crtc_state->csc, &ilk_csc_matrix_identity);
+ } else {
+ intel_csc_clear(&crtc_state->csc);
}
}
-static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
+static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ if (crtc_state->csc_enable)
+ ilk_update_pipe_csc(crtc, &crtc_state->csc);
+}
+
+static void icl_assign_csc(struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
if (crtc_state->hw.ctm) {
- u16 coeff[9];
+ drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_CSC_ENABLE) == 0);
+
+ ilk_csc_convert_ctm(crtc_state, &crtc_state->csc, false);
+ } else {
+ drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_CSC_ENABLE) != 0);
- ilk_csc_convert_ctm(crtc_state, coeff, false);
- ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
- coeff, ilk_csc_off_zero);
+ intel_csc_clear(&crtc_state->csc);
}
if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) {
- icl_update_output_csc(crtc, ilk_csc_off_zero,
- ilk_csc_coeff_rgb_to_ycbcr,
- ilk_csc_postoff_rgb_to_ycbcr);
+ drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE) == 0);
+
+ ilk_csc_copy(i915, &crtc_state->output_csc, &ilk_csc_matrix_rgb_to_ycbcr);
} else if (crtc_state->limited_color_range) {
- icl_update_output_csc(crtc, ilk_csc_off_zero,
- ilk_csc_coeff_limited_range,
- ilk_csc_postoff_limited_range);
+ drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE) == 0);
+
+ ilk_csc_copy(i915, &crtc_state->output_csc, &ilk_csc_matrix_limited_range);
+ } else {
+ drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE) != 0);
+
+ intel_csc_clear(&crtc_state->output_csc);
}
}
-static void chv_load_cgm_csc(struct intel_crtc *crtc,
- const struct drm_property_blob *blob)
+static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
- const struct drm_color_ctm *ctm = blob->data;
- enum pipe pipe = crtc->pipe;
- u16 coeffs[9];
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ if (crtc_state->csc_mode & ICL_CSC_ENABLE)
+ ilk_update_pipe_csc(crtc, &crtc_state->csc);
+
+ if (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE)
+ icl_update_output_csc(crtc, &crtc_state->output_csc);
+}
+
+static u16 ctm_to_twos_complement(u64 coeff, int int_bits, int frac_bits)
+{
+ s64 c = CTM_COEFF_ABS(coeff);
+
+ /* leave an extra bit for rounding */
+ c >>= 32 - frac_bits - 1;
+
+ /* round and drop the extra bit */
+ c = (c + 1) >> 1;
+
+ if (CTM_COEFF_NEGATIVE(coeff))
+ c = -c;
+
+ c = clamp(c, -(s64)BIT(int_bits + frac_bits - 1),
+ (s64)(BIT(int_bits + frac_bits - 1) - 1));
+
+ return c & (BIT(int_bits + frac_bits) - 1);
+}
+
+/*
+ * VLV/CHV Wide Gamut Color Correction (WGC) CSC
+ * |r| | c0 c1 c2 | |r|
+ * |g| = | c3 c4 c5 | x |g|
+ * |b| | c6 c7 c8 | |b|
+ *
+ * Coefficients are two's complement s2.10.
+ */
+static void vlv_wgc_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
+ struct intel_csc_matrix *csc)
+{
+ const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data;
int i;
- for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
- u64 abs_coeff = ((1ULL << 63) - 1) & ctm->matrix[i];
+ for (i = 0; i < 9; i++)
+ csc->coeff[i] = ctm_to_twos_complement(ctm->matrix[i], 2, 10);
+}
+
+static void vlv_load_wgc_csc(struct intel_crtc *crtc,
+ const struct intel_csc_matrix *csc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
+
+ intel_de_write_fw(dev_priv, PIPE_WGC_C01_C00(pipe),
+ csc->coeff[1] << 16 | csc->coeff[0]);
+ intel_de_write_fw(dev_priv, PIPE_WGC_C02(pipe),
+ csc->coeff[2]);
+
+ intel_de_write_fw(dev_priv, PIPE_WGC_C11_C10(pipe),
+ csc->coeff[4] << 16 | csc->coeff[3]);
+ intel_de_write_fw(dev_priv, PIPE_WGC_C12(pipe),
+ csc->coeff[5]);
+
+ intel_de_write_fw(dev_priv, PIPE_WGC_C21_C20(pipe),
+ csc->coeff[7] << 16 | csc->coeff[6]);
+ intel_de_write_fw(dev_priv, PIPE_WGC_C22(pipe),
+ csc->coeff[8]);
+}
+
+static void vlv_read_wgc_csc(struct intel_crtc *crtc,
+ struct intel_csc_matrix *csc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
+ u32 tmp;
+
+ tmp = intel_de_read_fw(dev_priv, PIPE_WGC_C01_C00(pipe));
+ csc->coeff[0] = tmp & 0xffff;
+ csc->coeff[1] = tmp >> 16;
- /* Round coefficient. */
- abs_coeff += 1 << (32 - 13);
- /* Clamp to hardware limits. */
- abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
+ tmp = intel_de_read_fw(dev_priv, PIPE_WGC_C02(pipe));
+ csc->coeff[2] = tmp & 0xffff;
- coeffs[i] = 0;
+ tmp = intel_de_read_fw(dev_priv, PIPE_WGC_C11_C10(pipe));
+ csc->coeff[3] = tmp & 0xffff;
+ csc->coeff[4] = tmp >> 16;
- /* Write coefficients in S3.12 format. */
- if (ctm->matrix[i] & (1ULL << 63))
- coeffs[i] |= 1 << 15;
+ tmp = intel_de_read_fw(dev_priv, PIPE_WGC_C12(pipe));
+ csc->coeff[5] = tmp & 0xffff;
- coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
- coeffs[i] |= (abs_coeff >> 20) & 0xfff;
+ tmp = intel_de_read_fw(dev_priv, PIPE_WGC_C21_C20(pipe));
+ csc->coeff[6] = tmp & 0xffff;
+ csc->coeff[7] = tmp >> 16;
+
+ tmp = intel_de_read_fw(dev_priv, PIPE_WGC_C22(pipe));
+ csc->coeff[8] = tmp & 0xffff;
+}
+
+static void vlv_read_csc(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ if (crtc_state->wgc_enable)
+ vlv_read_wgc_csc(crtc, &crtc_state->csc);
+}
+
+static void vlv_assign_csc(struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
+ if (crtc_state->hw.ctm) {
+ drm_WARN_ON(&i915->drm, !crtc_state->wgc_enable);
+
+ vlv_wgc_csc_convert_ctm(crtc_state, &crtc_state->csc);
+ } else {
+ drm_WARN_ON(&i915->drm, crtc_state->wgc_enable);
+
+ intel_csc_clear(&crtc_state->csc);
}
+}
+
+/*
+ * CHV Color Gamut Mapping (CGM) CSC
+ * |r| | c0 c1 c2 | |r|
+ * |g| = | c3 c4 c5 | x |g|
+ * |b| | c6 c7 c8 | |b|
+ *
+ * Coefficients are two's complement s4.12.
+ */
+static void chv_cgm_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
+ struct intel_csc_matrix *csc)
+{
+ const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data;
+ int i;
+
+ for (i = 0; i < 9; i++)
+ csc->coeff[i] = ctm_to_twos_complement(ctm->matrix[i], 4, 12);
+}
+
+#define CHV_CGM_CSC_COEFF_1_0 (1 << 12)
+
+static const struct intel_csc_matrix chv_cgm_csc_matrix_identity = {
+ .coeff = {
+ CHV_CGM_CSC_COEFF_1_0, 0, 0,
+ 0, CHV_CGM_CSC_COEFF_1_0, 0,
+ 0, 0, CHV_CGM_CSC_COEFF_1_0,
+ },
+};
+
+static void chv_load_cgm_csc(struct intel_crtc *crtc,
+ const struct intel_csc_matrix *csc)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF01(pipe),
- coeffs[1] << 16 | coeffs[0]);
+ csc->coeff[1] << 16 | csc->coeff[0]);
intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF23(pipe),
- coeffs[3] << 16 | coeffs[2]);
+ csc->coeff[3] << 16 | csc->coeff[2]);
intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF45(pipe),
- coeffs[5] << 16 | coeffs[4]);
+ csc->coeff[5] << 16 | csc->coeff[4]);
intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF67(pipe),
- coeffs[7] << 16 | coeffs[6]);
+ csc->coeff[7] << 16 | csc->coeff[6]);
intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF8(pipe),
- coeffs[8]);
+ csc->coeff[8]);
+}
+
+static void chv_read_cgm_csc(struct intel_crtc *crtc,
+ struct intel_csc_matrix *csc)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
+ u32 tmp;
+
+ tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF01(pipe));
+ csc->coeff[0] = tmp & 0xffff;
+ csc->coeff[1] = tmp >> 16;
+
+ tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF23(pipe));
+ csc->coeff[2] = tmp & 0xffff;
+ csc->coeff[3] = tmp >> 16;
+
+ tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF45(pipe));
+ csc->coeff[4] = tmp & 0xffff;
+ csc->coeff[5] = tmp >> 16;
+
+ tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF67(pipe));
+ csc->coeff[6] = tmp & 0xffff;
+ csc->coeff[7] = tmp >> 16;
+
+ tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF8(pipe));
+ csc->coeff[8] = tmp & 0xffff;
+}
+
+static void chv_read_csc(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ if (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC)
+ chv_read_cgm_csc(crtc, &crtc_state->csc);
+}
+
+static void chv_assign_csc(struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
+ drm_WARN_ON(&i915->drm, crtc_state->wgc_enable);
+
+ if (crtc_state->hw.ctm) {
+ drm_WARN_ON(&i915->drm, (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC) == 0);
+
+ chv_cgm_csc_convert_ctm(crtc_state, &crtc_state->csc);
+ } else {
+ drm_WARN_ON(&i915->drm, (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC) == 0);
+
+ crtc_state->csc = chv_cgm_csc_matrix_identity;
+ }
}
/* convert hw value with given bit_precision to lut property val */
@@ -1336,6 +1668,16 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state)
}
}
+static void vlv_load_luts(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ if (crtc_state->wgc_enable)
+ vlv_load_wgc_csc(crtc, &crtc_state->csc);
+
+ i965_load_luts(crtc_state);
+}
+
static u32 chv_cgm_degamma_ldw(const struct drm_color_lut *color)
{
return REG_FIELD_PREP(CGM_PIPE_DEGAMMA_GREEN_LDW_MASK, drm_color_lut_extract(color->green, 14)) |
@@ -1410,10 +1752,9 @@ static void chv_load_luts(const struct intel_crtc_state *crtc_state)
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut;
const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
- const struct drm_property_blob *ctm = crtc_state->hw.ctm;
if (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC)
- chv_load_cgm_csc(crtc, ctm);
+ chv_load_cgm_csc(crtc, &crtc_state->csc);
if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA)
chv_load_cgm_degamma(crtc, pre_csc_lut);
@@ -1491,6 +1832,18 @@ static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state
!old_crtc_state->pre_csc_lut;
}
+static bool vlv_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
+ struct intel_atomic_state *state =
+ to_intel_atomic_state(new_crtc_state->uapi.state);
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
+
+ return !old_crtc_state->wgc_enable &&
+ !old_crtc_state->post_csc_lut;
+}
+
static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
@@ -1507,7 +1860,7 @@ static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
if (old_crtc_state->cgm_mode || new_crtc_state->cgm_mode)
return false;
- return !old_crtc_state->post_csc_lut;
+ return vlv_can_preload_luts(new_crtc_state);
}
int intel_color_check(struct intel_crtc_state *crtc_state)
@@ -1522,6 +1875,9 @@ void intel_color_get_config(struct intel_crtc_state *crtc_state)
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
i915->display.funcs.color->read_luts(crtc_state);
+
+ if (i915->display.funcs.color->read_csc)
+ i915->display.funcs.color->read_csc(crtc_state);
}
bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
@@ -1606,14 +1962,14 @@ static u32 intel_gamma_lut_tests(const struct intel_crtc_state *crtc_state)
if (lut_is_legacy(gamma_lut))
return 0;
- return INTEL_INFO(i915)->display.color.gamma_lut_tests;
+ return DISPLAY_INFO(i915)->color.gamma_lut_tests;
}
static u32 intel_degamma_lut_tests(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
- return INTEL_INFO(i915)->display.color.degamma_lut_tests;
+ return DISPLAY_INFO(i915)->color.degamma_lut_tests;
}
static int intel_gamma_lut_size(const struct intel_crtc_state *crtc_state)
@@ -1624,14 +1980,14 @@ static int intel_gamma_lut_size(const struct intel_crtc_state *crtc_state)
if (lut_is_legacy(gamma_lut))
return LEGACY_LUT_LENGTH;
- return INTEL_INFO(i915)->display.color.gamma_lut_size;
+ return DISPLAY_INFO(i915)->color.gamma_lut_size;
}
static u32 intel_degamma_lut_size(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
- return INTEL_INFO(i915)->display.color.degamma_lut_size;
+ return DISPLAY_INFO(i915)->color.degamma_lut_size;
}
static int check_lut_size(const struct drm_property_blob *lut, int expected)
@@ -1791,6 +2147,39 @@ static int i9xx_color_check(struct intel_crtc_state *crtc_state)
return 0;
}
+/*
+ * VLV color pipeline:
+ * u0.10 -> WGC csc -> u0.10 -> pipe gamma -> u0.10
+ */
+static int vlv_color_check(struct intel_crtc_state *crtc_state)
+{
+ int ret;
+
+ ret = check_luts(crtc_state);
+ if (ret)
+ return ret;
+
+ crtc_state->gamma_enable =
+ crtc_state->hw.gamma_lut &&
+ !crtc_state->c8_planes;
+
+ crtc_state->gamma_mode = i9xx_gamma_mode(crtc_state);
+
+ crtc_state->wgc_enable = crtc_state->hw.ctm;
+
+ ret = intel_color_add_affected_planes(crtc_state);
+ if (ret)
+ return ret;
+
+ intel_assign_luts(crtc_state);
+
+ vlv_assign_csc(crtc_state);
+
+ crtc_state->preload_luts = vlv_can_preload_luts(crtc_state);
+
+ return 0;
+}
+
static u32 chv_cgm_mode(const struct intel_crtc_state *crtc_state)
{
u32 cgm_mode = 0;
@@ -1803,6 +2192,13 @@ static u32 chv_cgm_mode(const struct intel_crtc_state *crtc_state)
!lut_is_legacy(crtc_state->hw.gamma_lut))
cgm_mode |= CGM_PIPE_MODE_GAMMA;
+ /*
+ * Toggling the CGM CSC on/off outside of the tiny window
+ * between start of vblank and frame start causes underruns.
+ * Always enable the CGM CSC as a workaround.
+ */
+ cgm_mode |= CGM_PIPE_MODE_CSC;
+
return cgm_mode;
}
@@ -1834,12 +2230,20 @@ static int chv_color_check(struct intel_crtc_state *crtc_state)
crtc_state->cgm_mode = chv_cgm_mode(crtc_state);
+ /*
+ * We always bypass the WGC CSC and use the CGM CSC
+ * instead since it has degamma and better precision.
+ */
+ crtc_state->wgc_enable = false;
+
ret = intel_color_add_affected_planes(crtc_state);
if (ret)
return ret;
intel_assign_luts(crtc_state);
+ chv_assign_csc(crtc_state);
+
crtc_state->preload_luts = chv_can_preload_luts(crtc_state);
return 0;
@@ -1962,6 +2366,8 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state)
if (ret)
return ret;
+ ilk_assign_csc(crtc_state);
+
crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
return 0;
@@ -2068,6 +2474,8 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state)
if (ret)
return ret;
+ ilk_assign_csc(crtc_state);
+
crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
return 0;
@@ -2097,7 +2505,7 @@ static int glk_assign_luts(struct intel_crtc_state *crtc_state)
struct drm_property_blob *gamma_lut;
gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut,
- INTEL_INFO(i915)->display.color.degamma_lut_size,
+ DISPLAY_INFO(i915)->color.degamma_lut_size,
false);
if (IS_ERR(gamma_lut))
return PTR_ERR(gamma_lut);
@@ -2199,6 +2607,8 @@ static int glk_color_check(struct intel_crtc_state *crtc_state)
if (ret)
return ret;
+ ilk_assign_csc(crtc_state);
+
crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
return 0;
@@ -2261,6 +2671,8 @@ static int icl_color_check(struct intel_crtc_state *crtc_state)
intel_assign_luts(crtc_state);
+ icl_assign_csc(crtc_state);
+
crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
return 0;
@@ -2627,7 +3039,7 @@ static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc)
static struct drm_property_blob *i9xx_read_lut_10(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- u32 lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size;
+ u32 lut_size = DISPLAY_INFO(dev_priv)->color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
@@ -2676,7 +3088,7 @@ static void i9xx_read_luts(struct intel_crtc_state *crtc_state)
static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- int i, lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size;
+ int i, lut_size = DISPLAY_INFO(dev_priv)->color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
@@ -2726,7 +3138,7 @@ static void i965_read_luts(struct intel_crtc_state *crtc_state)
static struct drm_property_blob *chv_read_cgm_degamma(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- int i, lut_size = INTEL_INFO(dev_priv)->display.color.degamma_lut_size;
+ int i, lut_size = DISPLAY_INFO(dev_priv)->color.degamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
@@ -2752,7 +3164,7 @@ static struct drm_property_blob *chv_read_cgm_degamma(struct intel_crtc *crtc)
static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
- int i, lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size;
+ int i, lut_size = DISPLAY_INFO(i915)->color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
@@ -2816,7 +3228,7 @@ static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc)
static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
- int i, lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size;
+ int i, lut_size = DISPLAY_INFO(i915)->color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
@@ -3000,7 +3412,7 @@ static void bdw_read_luts(struct intel_crtc_state *crtc_state)
static struct drm_property_blob *glk_read_degamma_lut(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- int i, lut_size = INTEL_INFO(dev_priv)->display.color.degamma_lut_size;
+ int i, lut_size = DISPLAY_INFO(dev_priv)->color.degamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
@@ -3065,7 +3477,7 @@ static struct drm_property_blob *
icl_read_lut_multi_segment(struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
- int i, lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size;
+ int i, lut_size = DISPLAY_INFO(i915)->color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
@@ -3135,6 +3547,16 @@ static const struct intel_color_funcs chv_color_funcs = {
.load_luts = chv_load_luts,
.read_luts = chv_read_luts,
.lut_equal = chv_lut_equal,
+ .read_csc = chv_read_csc,
+};
+
+static const struct intel_color_funcs vlv_color_funcs = {
+ .color_check = vlv_color_check,
+ .color_commit_arm = i9xx_color_commit_arm,
+ .load_luts = vlv_load_luts,
+ .read_luts = i965_read_luts,
+ .lut_equal = i965_lut_equal,
+ .read_csc = vlv_read_csc,
};
static const struct intel_color_funcs i965_color_funcs = {
@@ -3160,6 +3582,7 @@ static const struct intel_color_funcs tgl_color_funcs = {
.load_luts = icl_load_luts,
.read_luts = icl_read_luts,
.lut_equal = icl_lut_equal,
+ .read_csc = icl_read_csc,
};
static const struct intel_color_funcs icl_color_funcs = {
@@ -3170,6 +3593,7 @@ static const struct intel_color_funcs icl_color_funcs = {
.load_luts = icl_load_luts,
.read_luts = icl_read_luts,
.lut_equal = icl_lut_equal,
+ .read_csc = icl_read_csc,
};
static const struct intel_color_funcs glk_color_funcs = {
@@ -3179,6 +3603,7 @@ static const struct intel_color_funcs glk_color_funcs = {
.load_luts = glk_load_luts,
.read_luts = glk_read_luts,
.lut_equal = glk_lut_equal,
+ .read_csc = skl_read_csc,
};
static const struct intel_color_funcs skl_color_funcs = {
@@ -3188,6 +3613,7 @@ static const struct intel_color_funcs skl_color_funcs = {
.load_luts = bdw_load_luts,
.read_luts = bdw_read_luts,
.lut_equal = ivb_lut_equal,
+ .read_csc = skl_read_csc,
};
static const struct intel_color_funcs bdw_color_funcs = {
@@ -3197,6 +3623,7 @@ static const struct intel_color_funcs bdw_color_funcs = {
.load_luts = bdw_load_luts,
.read_luts = bdw_read_luts,
.lut_equal = ivb_lut_equal,
+ .read_csc = ilk_read_csc,
};
static const struct intel_color_funcs hsw_color_funcs = {
@@ -3206,6 +3633,7 @@ static const struct intel_color_funcs hsw_color_funcs = {
.load_luts = ivb_load_luts,
.read_luts = ivb_read_luts,
.lut_equal = ivb_lut_equal,
+ .read_csc = ilk_read_csc,
};
static const struct intel_color_funcs ivb_color_funcs = {
@@ -3215,6 +3643,7 @@ static const struct intel_color_funcs ivb_color_funcs = {
.load_luts = ivb_load_luts,
.read_luts = ivb_read_luts,
.lut_equal = ivb_lut_equal,
+ .read_csc = ilk_read_csc,
};
static const struct intel_color_funcs ilk_color_funcs = {
@@ -3224,6 +3653,7 @@ static const struct intel_color_funcs ilk_color_funcs = {
.load_luts = ilk_load_luts,
.read_luts = ilk_read_luts,
.lut_equal = ilk_lut_equal,
+ .read_csc = ilk_read_csc,
};
void intel_color_crtc_init(struct intel_crtc *crtc)
@@ -3234,9 +3664,9 @@ void intel_color_crtc_init(struct intel_crtc *crtc)
drm_mode_crtc_set_gamma_size(&crtc->base, 256);
- gamma_lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size;
- degamma_lut_size = INTEL_INFO(i915)->display.color.degamma_lut_size;
- has_ctm = degamma_lut_size != 0;
+ gamma_lut_size = DISPLAY_INFO(i915)->color.gamma_lut_size;
+ degamma_lut_size = DISPLAY_INFO(i915)->color.degamma_lut_size;
+ has_ctm = DISPLAY_VER(i915) >= 5;
/*
* "DPALETTE_A: NOTE: The 8-bit (non-10-bit) mode is the
@@ -3260,7 +3690,8 @@ int intel_color_init(struct drm_i915_private *i915)
if (DISPLAY_VER(i915) != 10)
return 0;
- blob = create_linear_lut(i915, INTEL_INFO(i915)->display.color.degamma_lut_size);
+ blob = create_linear_lut(i915,
+ DISPLAY_INFO(i915)->color.degamma_lut_size);
if (IS_ERR(blob))
return PTR_ERR(blob);
@@ -3274,6 +3705,8 @@ void intel_color_init_hooks(struct drm_i915_private *i915)
if (HAS_GMCH(i915)) {
if (IS_CHERRYVIEW(i915))
i915->display.funcs.color = &chv_color_funcs;
+ else if (IS_VALLEYVIEW(i915))
+ i915->display.funcs.color = &vlv_color_funcs;
else if (DISPLAY_VER(i915) >= 4)
i915->display.funcs.color = &i965_color_funcs;
else
diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c
index 257afac34839..ff3bcadebe59 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.c
+++ b/drivers/gpu/drm/i915/display/intel_connector.c
@@ -176,15 +176,15 @@ enum pipe intel_connector_get_pipe(struct intel_connector *connector)
/**
* intel_connector_update_modes - update connector from edid
* @connector: DRM connector device to use
- * @edid: previously read EDID information
+ * @drm_edid: previously read EDID information
*/
int intel_connector_update_modes(struct drm_connector *connector,
- struct edid *edid)
+ const struct drm_edid *drm_edid)
{
int ret;
- drm_connector_update_edid_property(connector, edid);
- ret = drm_add_edid_modes(connector, edid);
+ drm_edid_connector_update(connector, drm_edid);
+ ret = drm_edid_connector_add_modes(connector);
return ret;
}
@@ -199,15 +199,15 @@ int intel_connector_update_modes(struct drm_connector *connector,
int intel_ddc_get_modes(struct drm_connector *connector,
struct i2c_adapter *adapter)
{
- struct edid *edid;
+ const struct drm_edid *drm_edid;
int ret;
- edid = drm_get_edid(connector, adapter);
- if (!edid)
+ drm_edid = drm_edid_read_ddc(connector, adapter);
+ if (!drm_edid)
return 0;
- ret = intel_connector_update_modes(connector, edid);
- kfree(edid);
+ ret = intel_connector_update_modes(connector, drm_edid);
+ drm_edid_free(drm_edid);
return ret;
}
@@ -280,14 +280,14 @@ intel_attach_aspect_ratio_property(struct drm_connector *connector)
void
intel_attach_hdmi_colorspace_property(struct drm_connector *connector)
{
- if (!drm_mode_create_hdmi_colorspace_property(connector))
+ if (!drm_mode_create_hdmi_colorspace_property(connector, 0))
drm_connector_attach_colorspace_property(connector);
}
void
intel_attach_dp_colorspace_property(struct drm_connector *connector)
{
- if (!drm_mode_create_dp_colorspace_property(connector))
+ if (!drm_mode_create_dp_colorspace_property(connector, 0))
drm_connector_attach_colorspace_property(connector);
}
diff --git a/drivers/gpu/drm/i915/display/intel_connector.h b/drivers/gpu/drm/i915/display/intel_connector.h
index 9d2bc261b204..aaf7281462dc 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.h
+++ b/drivers/gpu/drm/i915/display/intel_connector.h
@@ -9,7 +9,7 @@
#include <linux/types.h>
struct drm_connector;
-struct edid;
+struct drm_edid;
struct i2c_adapter;
struct intel_connector;
struct intel_encoder;
@@ -25,7 +25,7 @@ void intel_connector_attach_encoder(struct intel_connector *connector,
bool intel_connector_get_hw_state(struct intel_connector *connector);
enum pipe intel_connector_get_pipe(struct intel_connector *connector);
int intel_connector_update_modes(struct drm_connector *connector,
- struct edid *edid);
+ const struct drm_edid *drm_edid);
int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
void intel_attach_force_audio_property(struct drm_connector *connector);
void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
index 38e9c61c2344..ab7cd5e60a0a 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -48,6 +48,8 @@
#include "intel_fifo_underrun.h"
#include "intel_gmbus.h"
#include "intel_hotplug.h"
+#include "intel_hotplug_irq.h"
+#include "intel_load_detect.h"
#include "intel_pch_display.h"
#include "intel_pch_refclk.h"
@@ -394,6 +396,7 @@ static int intel_crt_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
+ pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
return 0;
@@ -606,37 +609,38 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
return ret;
}
-static struct edid *intel_crt_get_edid(struct drm_connector *connector,
- struct i2c_adapter *i2c)
+static const struct drm_edid *intel_crt_get_edid(struct drm_connector *connector,
+ struct i2c_adapter *i2c)
{
- struct edid *edid;
+ const struct drm_edid *drm_edid;
- edid = drm_get_edid(connector, i2c);
+ drm_edid = drm_edid_read_ddc(connector, i2c);
- if (!edid && !intel_gmbus_is_forced_bit(i2c)) {
+ if (!drm_edid && !intel_gmbus_is_forced_bit(i2c)) {
drm_dbg_kms(connector->dev,
"CRT GMBUS EDID read failed, retry using GPIO bit-banging\n");
intel_gmbus_force_bit(i2c, true);
- edid = drm_get_edid(connector, i2c);
+ drm_edid = drm_edid_read_ddc(connector, i2c);
intel_gmbus_force_bit(i2c, false);
}
- return edid;
+ return drm_edid;
}
/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */
static int intel_crt_ddc_get_modes(struct drm_connector *connector,
struct i2c_adapter *adapter)
{
- struct edid *edid;
+ const struct drm_edid *drm_edid;
int ret;
- edid = intel_crt_get_edid(connector, adapter);
- if (!edid)
+ drm_edid = intel_crt_get_edid(connector, adapter);
+ if (!drm_edid)
return 0;
- ret = intel_connector_update_modes(connector, edid);
- kfree(edid);
+ ret = intel_connector_update_modes(connector, drm_edid);
+
+ drm_edid_free(drm_edid);
return ret;
}
@@ -645,14 +649,15 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
{
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(crt->base.base.dev);
- struct edid *edid;
+ const struct drm_edid *drm_edid;
struct i2c_adapter *i2c;
bool ret = false;
i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->display.vbt.crt_ddc_pin);
- edid = intel_crt_get_edid(connector, i2c);
+ drm_edid = intel_crt_get_edid(connector, i2c);
- if (edid) {
+ if (drm_edid) {
+ const struct edid *edid = drm_edid_raw(drm_edid);
bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
/*
@@ -673,7 +678,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
"CRT not detected via DDC:0x50 [no valid EDID found]\n");
}
- kfree(edid);
+ drm_edid_free(drm_edid);
return ret;
}
@@ -821,9 +826,9 @@ intel_crt_detect(struct drm_connector *connector,
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct intel_encoder *intel_encoder = &crt->base;
+ struct drm_atomic_state *state;
intel_wakeref_t wakeref;
- int status, ret;
- struct intel_load_detect_pipe tmp;
+ int status;
drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] force=%d\n",
connector->base.id, connector->name,
@@ -881,8 +886,12 @@ load_detect:
}
/* for pre-945g platforms use load detect */
- ret = intel_get_load_detect_pipe(connector, &tmp, ctx);
- if (ret > 0) {
+ state = intel_load_detect_get_pipe(connector, ctx);
+ if (IS_ERR(state)) {
+ status = PTR_ERR(state);
+ } else if (!state) {
+ status = connector_status_unknown;
+ } else {
if (intel_crt_detect_ddc(connector))
status = connector_status_connected;
else if (DISPLAY_VER(dev_priv) < 4)
@@ -892,11 +901,7 @@ load_detect:
status = connector_status_disconnected;
else
status = connector_status_unknown;
- intel_release_load_detect_pipe(connector, &tmp, ctx);
- } else if (ret == 0) {
- status = connector_status_unknown;
- } else {
- status = ret;
+ intel_load_detect_release_pipe(connector, state, ctx);
}
out:
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index ed45a6934854..182c6dd64f47 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -11,7 +11,6 @@
#include <drm/drm_plane.h>
#include <drm/drm_vblank_work.h>
-#include "i915_irq.h"
#include "i915_vgpu.h"
#include "i9xx_plane.h"
#include "icl_dsi.h"
@@ -21,6 +20,7 @@
#include "intel_crtc.h"
#include "intel_cursor.h"
#include "intel_display_debugfs.h"
+#include "intel_display_irq.h"
#include "intel_display_trace.h"
#include "intel_display_types.h"
#include "intel_drrs.h"
@@ -35,7 +35,11 @@
static void assert_vblank_disabled(struct drm_crtc *crtc)
{
- if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0))
+ struct drm_i915_private *i915 = to_i915(crtc->dev);
+
+ if (I915_STATE_WARN(i915, drm_crtc_vblank_get(crtc) == 0,
+ "[CRTC:%d:%s] vblank assertion failure (expected off, current on)\n",
+ crtc->base.id, crtc->name))
drm_crtc_vblank_put(crtc);
}
@@ -302,7 +306,7 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
return PTR_ERR(crtc);
crtc->pipe = pipe;
- crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe];
+ crtc->num_scalers = DISPLAY_RUNTIME_INFO(dev_priv)->num_scalers[pipe];
if (DISPLAY_VER(dev_priv) >= 9)
primary = skl_universal_plane_create(dev_priv, pipe,
@@ -510,6 +514,13 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
VBLANK_EVASION_TIME_US);
max = vblank_start - 1;
+ /*
+ * M/N is double buffered on the transcoder's undelayed vblank,
+ * so with seamless M/N we must evade both vblanks.
+ */
+ if (new_crtc_state->seamless_m_n && intel_crtc_needs_fastset(new_crtc_state))
+ min -= adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay;
+
if (min <= 0 || max <= 0)
goto irq_disable;
@@ -692,7 +703,8 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
* FIXME Should be synchronized with the start of vblank somehow...
*/
if (new_crtc_state->seamless_m_n && intel_crtc_needs_fastset(new_crtc_state))
- intel_crtc_update_active_timings(new_crtc_state);
+ intel_crtc_update_active_timings(new_crtc_state,
+ new_crtc_state->vrr.enable);
local_irq_enable();
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.h b/drivers/gpu/drm/i915/display/intel_crtc.h
index 73077137fb99..51a4c8df9e65 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.h
+++ b/drivers/gpu/drm/i915/display/intel_crtc.h
@@ -16,6 +16,16 @@ struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
+/*
+ * FIXME: We should instead only take spinlocks once for the entire update
+ * instead of once per mmio.
+ */
+#if IS_ENABLED(CONFIG_PROVE_LOCKING)
+#define VBLANK_EVASION_TIME_US 250
+#else
+#define VBLANK_EVASION_TIME_US 100
+#endif
+
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
int usecs);
u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
index 54c8adc0702e..8d4640d0fd34 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
@@ -158,6 +158,45 @@ static void intel_dump_plane_state(const struct intel_plane_state *plane_state)
DRM_RECT_ARG(&plane_state->uapi.dst));
}
+static void
+ilk_dump_csc(struct drm_i915_private *i915, const char *name,
+ const struct intel_csc_matrix *csc)
+{
+ int i;
+
+ drm_dbg_kms(&i915->drm,
+ "%s: pre offsets: 0x%04x 0x%04x 0x%04x\n", name,
+ csc->preoff[0], csc->preoff[1], csc->preoff[2]);
+
+ for (i = 0; i < 3; i++)
+ drm_dbg_kms(&i915->drm,
+ "%s: coefficients: 0x%04x 0x%04x 0x%04x\n", name,
+ csc->coeff[3 * i + 0],
+ csc->coeff[3 * i + 1],
+ csc->coeff[3 * i + 2]);
+
+ if (DISPLAY_VER(i915) < 7)
+ return;
+
+ drm_dbg_kms(&i915->drm,
+ "%s: post offsets: 0x%04x 0x%04x 0x%04x\n", name,
+ csc->postoff[0], csc->postoff[1], csc->postoff[2]);
+}
+
+static void
+vlv_dump_csc(struct drm_i915_private *i915, const char *name,
+ const struct intel_csc_matrix *csc)
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ drm_dbg_kms(&i915->drm,
+ "%s: coefficients: 0x%04x 0x%04x 0x%04x\n", name,
+ csc->coeff[3 * i + 0],
+ csc->coeff[3 * i + 1],
+ csc->coeff[3 * i + 2]);
+}
+
void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
struct intel_atomic_state *state,
const char *context)
@@ -178,10 +217,11 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
snprintf_output_types(buf, sizeof(buf), pipe_config->output_types);
drm_dbg_kms(&i915->drm,
- "active: %s, output_types: %s (0x%x), output format: %s\n",
+ "active: %s, output_types: %s (0x%x), output format: %s, sink format: %s\n",
str_yes_no(pipe_config->hw.active),
buf, pipe_config->output_types,
- intel_output_format_name(pipe_config->output_format));
+ intel_output_format_name(pipe_config->output_format),
+ intel_output_format_name(pipe_config->sink_format));
drm_dbg_kms(&i915->drm,
"cpu_transcoder: %s, pipe bpp: %i, dithering: %i\n",
@@ -325,6 +365,16 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
pipe_config->post_csc_lut ?
drm_color_lut_size(pipe_config->post_csc_lut) : 0);
+ if (DISPLAY_VER(i915) >= 11)
+ ilk_dump_csc(i915, "output csc", &pipe_config->output_csc);
+
+ if (!HAS_GMCH(i915))
+ ilk_dump_csc(i915, "pipe csc", &pipe_config->csc);
+ else if (IS_CHERRYVIEW(i915))
+ vlv_dump_csc(i915, "cgm csc", &pipe_config->csc);
+ else if (IS_VALLEYVIEW(i915))
+ vlv_dump_csc(i915, "wgc csc", &pipe_config->csc);
+
dump_planes:
if (!state)
return;
diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
index 31bef0427377..b342fad180ca 100644
--- a/drivers/gpu/drm/i915/display/intel_cursor.c
+++ b/drivers/gpu/drm/i915/display/intel_cursor.c
@@ -36,7 +36,7 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
u32 base;
- if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
+ if (DISPLAY_INFO(dev_priv)->cursor_needs_physical)
base = sg_dma_address(obj->mm.pages->sgl);
else
base = intel_plane_ggtt_offset(plane_state);
@@ -814,7 +814,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
DRM_MODE_ROTATE_0 |
DRM_MODE_ROTATE_180);
- zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
+ zpos = DISPLAY_RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
if (DISPLAY_VER(dev_priv) >= 12)
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
new file mode 100644
index 000000000000..0600fdcd06ef
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -0,0 +1,3046 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include <linux/log2.h>
+#include <linux/math64.h>
+#include "i915_reg.h"
+#include "intel_cx0_phy.h"
+#include "intel_cx0_phy_regs.h"
+#include "intel_ddi.h"
+#include "intel_ddi_buf_trans.h"
+#include "intel_de.h"
+#include "intel_display_types.h"
+#include "intel_dp.h"
+#include "intel_hdmi.h"
+#include "intel_panel.h"
+#include "intel_psr.h"
+#include "intel_tc.h"
+
+#define MB_WRITE_COMMITTED true
+#define MB_WRITE_UNCOMMITTED false
+
+#define for_each_cx0_lane_in_mask(__lane_mask, __lane) \
+ for ((__lane) = 0; (__lane) < 2; (__lane)++) \
+ for_each_if((__lane_mask) & BIT(__lane))
+
+#define INTEL_CX0_LANE0 BIT(0)
+#define INTEL_CX0_LANE1 BIT(1)
+#define INTEL_CX0_BOTH_LANES (INTEL_CX0_LANE1 | INTEL_CX0_LANE0)
+
+bool intel_is_c10phy(struct drm_i915_private *i915, enum phy phy)
+{
+ if (IS_METEORLAKE(i915) && (phy < PHY_C))
+ return true;
+
+ return false;
+}
+
+static int lane_mask_to_lane(u8 lane_mask)
+{
+ if (WARN_ON((lane_mask & ~INTEL_CX0_BOTH_LANES) ||
+ hweight8(lane_mask) != 1))
+ return 0;
+
+ return ilog2(lane_mask);
+}
+
+static void
+assert_dc_off(struct drm_i915_private *i915)
+{
+ bool enabled;
+
+ enabled = intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF);
+ drm_WARN_ON(&i915->drm, !enabled);
+}
+
+/*
+ * Prepare HW for CX0 phy transactions.
+ *
+ * It is required that PSR and DC5/6 are disabled before any CX0 message
+ * bus transaction is executed.
+ */
+static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ intel_psr_pause(intel_dp);
+ return intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
+}
+
+static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, intel_wakeref_t wakeref)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ intel_psr_resume(intel_dp);
+ intel_display_power_put(i915, POWER_DOMAIN_DC_OFF, wakeref);
+}
+
+static void intel_clear_response_ready_flag(struct drm_i915_private *i915,
+ enum port port, int lane)
+{
+ intel_de_rmw(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane),
+ 0, XELPDP_PORT_P2M_RESPONSE_READY | XELPDP_PORT_P2M_ERROR_SET);
+}
+
+static void intel_cx0_bus_reset(struct drm_i915_private *i915, enum port port, int lane)
+{
+ enum phy phy = intel_port_to_phy(i915, port);
+
+ intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
+ XELPDP_PORT_M2P_TRANSACTION_RESET);
+
+ if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
+ XELPDP_PORT_M2P_TRANSACTION_RESET,
+ XELPDP_MSGBUS_TIMEOUT_SLOW)) {
+ drm_err_once(&i915->drm, "Failed to bring PHY %c to idle.\n", phy_name(phy));
+ return;
+ }
+
+ intel_clear_response_ready_flag(i915, port, lane);
+}
+
+static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port port,
+ int command, int lane, u32 *val)
+{
+ enum phy phy = intel_port_to_phy(i915, port);
+
+ if (__intel_de_wait_for_register(i915,
+ XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane),
+ XELPDP_PORT_P2M_RESPONSE_READY,
+ XELPDP_PORT_P2M_RESPONSE_READY,
+ XELPDP_MSGBUS_TIMEOUT_FAST_US,
+ XELPDP_MSGBUS_TIMEOUT_SLOW, val)) {
+ drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for message ACK. Status: 0x%x\n",
+ phy_name(phy), *val);
+ return -ETIMEDOUT;
+ }
+
+ if (*val & XELPDP_PORT_P2M_ERROR_SET) {
+ drm_dbg_kms(&i915->drm, "PHY %c Error occurred during %s command. Status: 0x%x\n", phy_name(phy),
+ command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val);
+ intel_cx0_bus_reset(i915, port, lane);
+ return -EINVAL;
+ }
+
+ if (REG_FIELD_GET(XELPDP_PORT_P2M_COMMAND_TYPE_MASK, *val) != command) {
+ drm_dbg_kms(&i915->drm, "PHY %c Not a %s response. MSGBUS Status: 0x%x.\n", phy_name(phy),
+ command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val);
+ intel_cx0_bus_reset(i915, port, lane);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __intel_cx0_read_once(struct drm_i915_private *i915, enum port port,
+ int lane, u16 addr)
+{
+ enum phy phy = intel_port_to_phy(i915, port);
+ int ack;
+ u32 val;
+
+ if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
+ XELPDP_PORT_M2P_TRANSACTION_PENDING,
+ XELPDP_MSGBUS_TIMEOUT_SLOW)) {
+ drm_dbg_kms(&i915->drm,
+ "PHY %c Timeout waiting for previous transaction to complete. Reset the bus and retry.\n", phy_name(phy));
+ intel_cx0_bus_reset(i915, port, lane);
+ return -ETIMEDOUT;
+ }
+
+ intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
+ XELPDP_PORT_M2P_TRANSACTION_PENDING |
+ XELPDP_PORT_M2P_COMMAND_READ |
+ XELPDP_PORT_M2P_ADDRESS(addr));
+
+ ack = intel_cx0_wait_for_ack(i915, port, XELPDP_PORT_P2M_COMMAND_READ_ACK, lane, &val);
+ if (ack < 0) {
+ intel_cx0_bus_reset(i915, port, lane);
+ return ack;
+ }
+
+ intel_clear_response_ready_flag(i915, port, lane);
+
+ return REG_FIELD_GET(XELPDP_PORT_P2M_DATA_MASK, val);
+}
+
+static u8 __intel_cx0_read(struct drm_i915_private *i915, enum port port,
+ int lane, u16 addr)
+{
+ enum phy phy = intel_port_to_phy(i915, port);
+ int i, status;
+
+ assert_dc_off(i915);
+
+ /* 3 tries is assumed to be enough to read successfully */
+ for (i = 0; i < 3; i++) {
+ status = __intel_cx0_read_once(i915, port, lane, addr);
+
+ if (status >= 0)
+ return status;
+ }
+
+ drm_err_once(&i915->drm, "PHY %c Read %04x failed after %d retries.\n",
+ phy_name(phy), addr, i);
+
+ return 0;
+}
+
+static u8 intel_cx0_read(struct drm_i915_private *i915, enum port port,
+ u8 lane_mask, u16 addr)
+{
+ int lane = lane_mask_to_lane(lane_mask);
+
+ return __intel_cx0_read(i915, port, lane, addr);
+}
+
+static int __intel_cx0_write_once(struct drm_i915_private *i915, enum port port,
+ int lane, u16 addr, u8 data, bool committed)
+{
+ enum phy phy = intel_port_to_phy(i915, port);
+ u32 val;
+
+ if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
+ XELPDP_PORT_M2P_TRANSACTION_PENDING,
+ XELPDP_MSGBUS_TIMEOUT_SLOW)) {
+ drm_dbg_kms(&i915->drm,
+ "PHY %c Timeout waiting for previous transaction to complete. Resetting the bus.\n", phy_name(phy));
+ intel_cx0_bus_reset(i915, port, lane);
+ return -ETIMEDOUT;
+ }
+
+ intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
+ XELPDP_PORT_M2P_TRANSACTION_PENDING |
+ (committed ? XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED :
+ XELPDP_PORT_M2P_COMMAND_WRITE_UNCOMMITTED) |
+ XELPDP_PORT_M2P_DATA(data) |
+ XELPDP_PORT_M2P_ADDRESS(addr));
+
+ if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
+ XELPDP_PORT_M2P_TRANSACTION_PENDING,
+ XELPDP_MSGBUS_TIMEOUT_SLOW)) {
+ drm_dbg_kms(&i915->drm,
+ "PHY %c Timeout waiting for write to complete. Resetting the bus.\n", phy_name(phy));
+ intel_cx0_bus_reset(i915, port, lane);
+ return -ETIMEDOUT;
+ }
+
+ if (committed) {
+ if (intel_cx0_wait_for_ack(i915, port, XELPDP_PORT_P2M_COMMAND_WRITE_ACK, lane, &val) < 0) {
+ intel_cx0_bus_reset(i915, port, lane);
+ return -EINVAL;
+ }
+ } else if ((intel_de_read(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane)) &
+ XELPDP_PORT_P2M_ERROR_SET)) {
+ drm_dbg_kms(&i915->drm,
+ "PHY %c Error occurred during write command.\n", phy_name(phy));
+ intel_cx0_bus_reset(i915, port, lane);
+ return -EINVAL;
+ }
+
+ intel_clear_response_ready_flag(i915, port, lane);
+
+ return 0;
+}
+
+static void __intel_cx0_write(struct drm_i915_private *i915, enum port port,
+ int lane, u16 addr, u8 data, bool committed)
+{
+ enum phy phy = intel_port_to_phy(i915, port);
+ int i, status;
+
+ assert_dc_off(i915);
+
+ /* 3 tries is assumed to be enough to write successfully */
+ for (i = 0; i < 3; i++) {
+ status = __intel_cx0_write_once(i915, port, lane, addr, data, committed);
+
+ if (status == 0)
+ return;
+ }
+
+ drm_err_once(&i915->drm,
+ "PHY %c Write %04x failed after %d retries.\n", phy_name(phy), addr, i);
+}
+
+static void intel_cx0_write(struct drm_i915_private *i915, enum port port,
+ u8 lane_mask, u16 addr, u8 data, bool committed)
+{
+ int lane;
+
+ for_each_cx0_lane_in_mask(lane_mask, lane)
+ __intel_cx0_write(i915, port, lane, addr, data, committed);
+}
+
+static void intel_c20_sram_write(struct drm_i915_private *i915, enum port port,
+ int lane, u16 addr, u16 data)
+{
+ assert_dc_off(i915);
+
+ intel_cx0_write(i915, port, lane, PHY_C20_WR_ADDRESS_H, addr >> 8, 0);
+ intel_cx0_write(i915, port, lane, PHY_C20_WR_ADDRESS_L, addr & 0xff, 0);
+
+ intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_H, data >> 8, 0);
+ intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_L, data & 0xff, 1);
+}
+
+static u16 intel_c20_sram_read(struct drm_i915_private *i915, enum port port,
+ int lane, u16 addr)
+{
+ u16 val;
+
+ assert_dc_off(i915);
+
+ intel_cx0_write(i915, port, lane, PHY_C20_RD_ADDRESS_H, addr >> 8, 0);
+ intel_cx0_write(i915, port, lane, PHY_C20_RD_ADDRESS_L, addr & 0xff, 1);
+
+ val = intel_cx0_read(i915, port, lane, PHY_C20_RD_DATA_H);
+ val <<= 8;
+ val |= intel_cx0_read(i915, port, lane, PHY_C20_RD_DATA_L);
+
+ return val;
+}
+
+static void __intel_cx0_rmw(struct drm_i915_private *i915, enum port port,
+ int lane, u16 addr, u8 clear, u8 set, bool committed)
+{
+ u8 old, val;
+
+ old = __intel_cx0_read(i915, port, lane, addr);
+ val = (old & ~clear) | set;
+
+ if (val != old)
+ __intel_cx0_write(i915, port, lane, addr, val, committed);
+}
+
+static void intel_cx0_rmw(struct drm_i915_private *i915, enum port port,
+ u8 lane_mask, u16 addr, u8 clear, u8 set, bool committed)
+{
+ u8 lane;
+
+ for_each_cx0_lane_in_mask(lane_mask, lane)
+ __intel_cx0_rmw(i915, port, lane, addr, clear, set, committed);
+}
+
+static u8 intel_c10_get_tx_vboost_lvl(const struct intel_crtc_state *crtc_state)
+{
+ if (intel_crtc_has_dp_encoder(crtc_state)) {
+ if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
+ (crtc_state->port_clock == 540000 ||
+ crtc_state->port_clock == 810000))
+ return 5;
+ else
+ return 4;
+ } else {
+ return 5;
+ }
+}
+
+static u8 intel_c10_get_tx_term_ctl(const struct intel_crtc_state *crtc_state)
+{
+ if (intel_crtc_has_dp_encoder(crtc_state)) {
+ if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
+ (crtc_state->port_clock == 540000 ||
+ crtc_state->port_clock == 810000))
+ return 5;
+ else
+ return 2;
+ } else {
+ return 6;
+ }
+}
+
+void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ const struct intel_ddi_buf_trans *trans;
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
+ intel_wakeref_t wakeref;
+ int n_entries, ln;
+
+ wakeref = intel_cx0_phy_transaction_begin(encoder);
+
+ trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
+ if (drm_WARN_ON_ONCE(&i915->drm, !trans)) {
+ intel_cx0_phy_transaction_end(encoder, wakeref);
+ return;
+ }
+
+ if (intel_is_c10phy(i915, phy)) {
+ intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
+ 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED);
+ intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CMN(3),
+ C10_CMN3_TXVBOOST_MASK,
+ C10_CMN3_TXVBOOST(intel_c10_get_tx_vboost_lvl(crtc_state)),
+ MB_WRITE_UNCOMMITTED);
+ intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_TX(1),
+ C10_TX1_TERMCTL_MASK,
+ C10_TX1_TERMCTL(intel_c10_get_tx_term_ctl(crtc_state)),
+ MB_WRITE_COMMITTED);
+ }
+
+ for (ln = 0; ln < crtc_state->lane_count; ln++) {
+ int level = intel_ddi_level(encoder, crtc_state, ln);
+ int lane, tx;
+
+ lane = ln / 2;
+ tx = ln % 2;
+
+ intel_cx0_rmw(i915, encoder->port, BIT(lane), PHY_CX0_VDROVRD_CTL(lane, tx, 0),
+ C10_PHY_OVRD_LEVEL_MASK,
+ C10_PHY_OVRD_LEVEL(trans->entries[level].snps.pre_cursor),
+ MB_WRITE_COMMITTED);
+ intel_cx0_rmw(i915, encoder->port, BIT(lane), PHY_CX0_VDROVRD_CTL(lane, tx, 1),
+ C10_PHY_OVRD_LEVEL_MASK,
+ C10_PHY_OVRD_LEVEL(trans->entries[level].snps.vswing),
+ MB_WRITE_COMMITTED);
+ intel_cx0_rmw(i915, encoder->port, BIT(lane), PHY_CX0_VDROVRD_CTL(lane, tx, 2),
+ C10_PHY_OVRD_LEVEL_MASK,
+ C10_PHY_OVRD_LEVEL(trans->entries[level].snps.post_cursor),
+ MB_WRITE_COMMITTED);
+ }
+
+ /* Write Override enables in 0xD71 */
+ intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_OVRD,
+ 0, PHY_C10_VDR_OVRD_TX1 | PHY_C10_VDR_OVRD_TX2,
+ MB_WRITE_COMMITTED);
+
+ if (intel_is_c10phy(i915, phy))
+ intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
+ 0, C10_VDR_CTRL_UPDATE_CFG, MB_WRITE_COMMITTED);
+
+ intel_cx0_phy_transaction_end(encoder, wakeref);
+}
+
+/*
+ * Basic DP link rates with 38.4 MHz reference clock.
+ * Note: The tables below are with SSC. In non-ssc
+ * registers 0xC04 to 0xC08(pll[4] to pll[8]) will be
+ * programmed 0.
+ */
+
+static const struct intel_c10pll_state mtl_c10_dp_rbr = {
+ .clock = 162000,
+ .tx = 0x10,
+ .cmn = 0x21,
+ .pll[0] = 0xB4,
+ .pll[1] = 0,
+ .pll[2] = 0x30,
+ .pll[3] = 0x1,
+ .pll[4] = 0x26,
+ .pll[5] = 0x0C,
+ .pll[6] = 0x98,
+ .pll[7] = 0x46,
+ .pll[8] = 0x1,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0xC0,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0x2,
+ .pll[16] = 0x84,
+ .pll[17] = 0x4F,
+ .pll[18] = 0xE5,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_edp_r216 = {
+ .clock = 216000,
+ .tx = 0x10,
+ .cmn = 0x21,
+ .pll[0] = 0x4,
+ .pll[1] = 0,
+ .pll[2] = 0xA2,
+ .pll[3] = 0x1,
+ .pll[4] = 0x33,
+ .pll[5] = 0x10,
+ .pll[6] = 0x75,
+ .pll[7] = 0xB3,
+ .pll[8] = 0x1,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0x2,
+ .pll[16] = 0x85,
+ .pll[17] = 0x0F,
+ .pll[18] = 0xE6,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_edp_r243 = {
+ .clock = 243000,
+ .tx = 0x10,
+ .cmn = 0x21,
+ .pll[0] = 0x34,
+ .pll[1] = 0,
+ .pll[2] = 0xDA,
+ .pll[3] = 0x1,
+ .pll[4] = 0x39,
+ .pll[5] = 0x12,
+ .pll[6] = 0xE3,
+ .pll[7] = 0xE9,
+ .pll[8] = 0x1,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0x20,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0x2,
+ .pll[16] = 0x85,
+ .pll[17] = 0x8F,
+ .pll[18] = 0xE6,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_dp_hbr1 = {
+ .clock = 270000,
+ .tx = 0x10,
+ .cmn = 0x21,
+ .pll[0] = 0xF4,
+ .pll[1] = 0,
+ .pll[2] = 0xF8,
+ .pll[3] = 0x0,
+ .pll[4] = 0x20,
+ .pll[5] = 0x0A,
+ .pll[6] = 0x29,
+ .pll[7] = 0x10,
+ .pll[8] = 0x1, /* Verify */
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0xA0,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0x1,
+ .pll[16] = 0x84,
+ .pll[17] = 0x4F,
+ .pll[18] = 0xE5,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_edp_r324 = {
+ .clock = 324000,
+ .tx = 0x10,
+ .cmn = 0x21,
+ .pll[0] = 0xB4,
+ .pll[1] = 0,
+ .pll[2] = 0x30,
+ .pll[3] = 0x1,
+ .pll[4] = 0x26,
+ .pll[5] = 0x0C,
+ .pll[6] = 0x98,
+ .pll[7] = 0x46,
+ .pll[8] = 0x1,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0xC0,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0x1,
+ .pll[16] = 0x85,
+ .pll[17] = 0x4F,
+ .pll[18] = 0xE6,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_edp_r432 = {
+ .clock = 432000,
+ .tx = 0x10,
+ .cmn = 0x21,
+ .pll[0] = 0x4,
+ .pll[1] = 0,
+ .pll[2] = 0xA2,
+ .pll[3] = 0x1,
+ .pll[4] = 0x33,
+ .pll[5] = 0x10,
+ .pll[6] = 0x75,
+ .pll[7] = 0xB3,
+ .pll[8] = 0x1,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0x1,
+ .pll[16] = 0x85,
+ .pll[17] = 0x0F,
+ .pll[18] = 0xE6,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_dp_hbr2 = {
+ .clock = 540000,
+ .tx = 0x10,
+ .cmn = 0x21,
+ .pll[0] = 0xF4,
+ .pll[1] = 0,
+ .pll[2] = 0xF8,
+ .pll[3] = 0,
+ .pll[4] = 0x20,
+ .pll[5] = 0x0A,
+ .pll[6] = 0x29,
+ .pll[7] = 0x10,
+ .pll[8] = 0x1,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0xA0,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0,
+ .pll[16] = 0x84,
+ .pll[17] = 0x4F,
+ .pll[18] = 0xE5,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_edp_r675 = {
+ .clock = 675000,
+ .tx = 0x10,
+ .cmn = 0x21,
+ .pll[0] = 0xB4,
+ .pll[1] = 0,
+ .pll[2] = 0x3E,
+ .pll[3] = 0x1,
+ .pll[4] = 0xA8,
+ .pll[5] = 0x0C,
+ .pll[6] = 0x33,
+ .pll[7] = 0x54,
+ .pll[8] = 0x1,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0xC8,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0,
+ .pll[16] = 0x85,
+ .pll[17] = 0x8F,
+ .pll[18] = 0xE6,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_dp_hbr3 = {
+ .clock = 810000,
+ .tx = 0x10,
+ .cmn = 0x21,
+ .pll[0] = 0x34,
+ .pll[1] = 0,
+ .pll[2] = 0x84,
+ .pll[3] = 0x1,
+ .pll[4] = 0x30,
+ .pll[5] = 0x0F,
+ .pll[6] = 0x3D,
+ .pll[7] = 0x98,
+ .pll[8] = 0x1,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0xF0,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0,
+ .pll[16] = 0x84,
+ .pll[17] = 0x0F,
+ .pll[18] = 0xE5,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state * const mtl_c10_dp_tables[] = {
+ &mtl_c10_dp_rbr,
+ &mtl_c10_dp_hbr1,
+ &mtl_c10_dp_hbr2,
+ &mtl_c10_dp_hbr3,
+ NULL,
+};
+
+static const struct intel_c10pll_state * const mtl_c10_edp_tables[] = {
+ &mtl_c10_dp_rbr,
+ &mtl_c10_edp_r216,
+ &mtl_c10_edp_r243,
+ &mtl_c10_dp_hbr1,
+ &mtl_c10_edp_r324,
+ &mtl_c10_edp_r432,
+ &mtl_c10_dp_hbr2,
+ &mtl_c10_edp_r675,
+ &mtl_c10_dp_hbr3,
+ NULL,
+};
+
+/* C20 basic DP 1.4 tables */
+static const struct intel_c20pll_state mtl_c20_dp_rbr = {
+ .link_bit_rate = 162000,
+ .clock = 162000,
+ .tx = { 0xbe88, /* tx cfg0 */
+ 0x5800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = {0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x50a8, /* mpllb cfg0 */
+ 0x2120, /* mpllb cfg1 */
+ 0xcd9a, /* mpllb cfg2 */
+ 0xbfc1, /* mpllb cfg3 */
+ 0x5ab8, /* mpllb cfg4 */
+ 0x4c34, /* mpllb cfg5 */
+ 0x2000, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x6000, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0000, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_dp_hbr1 = {
+ .link_bit_rate = 270000,
+ .clock = 270000,
+ .tx = { 0xbe88, /* tx cfg0 */
+ 0x4800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = {0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x308c, /* mpllb cfg0 */
+ 0x2110, /* mpllb cfg1 */
+ 0xcc9c, /* mpllb cfg2 */
+ 0xbfc1, /* mpllb cfg3 */
+ 0x4b9a, /* mpllb cfg4 */
+ 0x3f81, /* mpllb cfg5 */
+ 0x2000, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x5000, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0000, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_dp_hbr2 = {
+ .link_bit_rate = 540000,
+ .clock = 540000,
+ .tx = { 0xbe88, /* tx cfg0 */
+ 0x4800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = {0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x108c, /* mpllb cfg0 */
+ 0x2108, /* mpllb cfg1 */
+ 0xcc9c, /* mpllb cfg2 */
+ 0xbfc1, /* mpllb cfg3 */
+ 0x4b9a, /* mpllb cfg4 */
+ 0x3f81, /* mpllb cfg5 */
+ 0x2000, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x5000, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0000, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_dp_hbr3 = {
+ .link_bit_rate = 810000,
+ .clock = 810000,
+ .tx = { 0xbe88, /* tx cfg0 */
+ 0x4800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = {0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x10d2, /* mpllb cfg0 */
+ 0x2108, /* mpllb cfg1 */
+ 0x8d98, /* mpllb cfg2 */
+ 0xbfc1, /* mpllb cfg3 */
+ 0x7166, /* mpllb cfg4 */
+ 0x5f42, /* mpllb cfg5 */
+ 0x2000, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x7800, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0000, /* mpllb cfg10 */
+ },
+};
+
+/* C20 basic DP 2.0 tables */
+static const struct intel_c20pll_state mtl_c20_dp_uhbr10 = {
+ .link_bit_rate = 1000000, /* 10 Gbps */
+ .clock = 312500,
+ .tx = { 0xbe21, /* tx cfg0 */
+ 0x4800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = {0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mplla = { 0x3104, /* mplla cfg0 */
+ 0xd105, /* mplla cfg1 */
+ 0xc025, /* mplla cfg2 */
+ 0xc025, /* mplla cfg3 */
+ 0x8c00, /* mplla cfg4 */
+ 0x759a, /* mplla cfg5 */
+ 0x4000, /* mplla cfg6 */
+ 0x0003, /* mplla cfg7 */
+ 0x3555, /* mplla cfg8 */
+ 0x0001, /* mplla cfg9 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_dp_uhbr13_5 = {
+ .link_bit_rate = 1350000, /* 13.5 Gbps */
+ .clock = 421875,
+ .tx = { 0xbea0, /* tx cfg0 */
+ 0x4800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = {0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x015f, /* mpllb cfg0 */
+ 0x2205, /* mpllb cfg1 */
+ 0x1b17, /* mpllb cfg2 */
+ 0xffc1, /* mpllb cfg3 */
+ 0xe100, /* mpllb cfg4 */
+ 0xbd00, /* mpllb cfg5 */
+ 0x2000, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x4800, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0000, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_dp_uhbr20 = {
+ .link_bit_rate = 2000000, /* 20 Gbps */
+ .clock = 625000,
+ .tx = { 0xbe20, /* tx cfg0 */
+ 0x4800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = {0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mplla = { 0x3104, /* mplla cfg0 */
+ 0xd105, /* mplla cfg1 */
+ 0xc025, /* mplla cfg2 */
+ 0xc025, /* mplla cfg3 */
+ 0xa6ab, /* mplla cfg4 */
+ 0x8c00, /* mplla cfg5 */
+ 0x4000, /* mplla cfg6 */
+ 0x0003, /* mplla cfg7 */
+ 0x3555, /* mplla cfg8 */
+ 0x0001, /* mplla cfg9 */
+ },
+};
+
+static const struct intel_c20pll_state * const mtl_c20_dp_tables[] = {
+ &mtl_c20_dp_rbr,
+ &mtl_c20_dp_hbr1,
+ &mtl_c20_dp_hbr2,
+ &mtl_c20_dp_hbr3,
+ &mtl_c20_dp_uhbr10,
+ &mtl_c20_dp_uhbr13_5,
+ &mtl_c20_dp_uhbr20,
+ NULL,
+};
+
+/*
+ * HDMI link rates with 38.4 MHz reference clock.
+ */
+
+static const struct intel_c10pll_state mtl_c10_hdmi_25_2 = {
+ .clock = 25200,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x4,
+ .pll[1] = 0,
+ .pll[2] = 0xB2,
+ .pll[3] = 0,
+ .pll[4] = 0,
+ .pll[5] = 0,
+ .pll[6] = 0,
+ .pll[7] = 0,
+ .pll[8] = 0x20,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0xD,
+ .pll[16] = 0x6,
+ .pll[17] = 0x8F,
+ .pll[18] = 0x84,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_27_0 = {
+ .clock = 27000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x34,
+ .pll[1] = 0,
+ .pll[2] = 0xC0,
+ .pll[3] = 0,
+ .pll[4] = 0,
+ .pll[5] = 0,
+ .pll[6] = 0,
+ .pll[7] = 0,
+ .pll[8] = 0x20,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0x80,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0xD,
+ .pll[16] = 0x6,
+ .pll[17] = 0xCF,
+ .pll[18] = 0x84,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_74_25 = {
+ .clock = 74250,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4,
+ .pll[1] = 0,
+ .pll[2] = 0x7A,
+ .pll[3] = 0,
+ .pll[4] = 0,
+ .pll[5] = 0,
+ .pll[6] = 0,
+ .pll[7] = 0,
+ .pll[8] = 0x20,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0x58,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0xB,
+ .pll[16] = 0x6,
+ .pll[17] = 0xF,
+ .pll[18] = 0x85,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_148_5 = {
+ .clock = 148500,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4,
+ .pll[1] = 0,
+ .pll[2] = 0x7A,
+ .pll[3] = 0,
+ .pll[4] = 0,
+ .pll[5] = 0,
+ .pll[6] = 0,
+ .pll[7] = 0,
+ .pll[8] = 0x20,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0x58,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0xA,
+ .pll[16] = 0x6,
+ .pll[17] = 0xF,
+ .pll[18] = 0x85,
+ .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_594 = {
+ .clock = 594000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4,
+ .pll[1] = 0,
+ .pll[2] = 0x7A,
+ .pll[3] = 0,
+ .pll[4] = 0,
+ .pll[5] = 0,
+ .pll[6] = 0,
+ .pll[7] = 0,
+ .pll[8] = 0x20,
+ .pll[9] = 0x1,
+ .pll[10] = 0,
+ .pll[11] = 0,
+ .pll[12] = 0x58,
+ .pll[13] = 0,
+ .pll[14] = 0,
+ .pll[15] = 0x8,
+ .pll[16] = 0x6,
+ .pll[17] = 0xF,
+ .pll[18] = 0x85,
+ .pll[19] = 0x23,
+};
+
+/* Precomputed C10 HDMI PLL tables */
+static const struct intel_c10pll_state mtl_c10_hdmi_27027 = {
+ .clock = 27027,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xC0, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0xCC, .pll[12] = 0x9C, .pll[13] = 0xCB, .pll[14] = 0xCC,
+ .pll[15] = 0x0D, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_28320 = {
+ .clock = 28320,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x04, .pll[1] = 0x00, .pll[2] = 0xCC, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x00, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0D, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_30240 = {
+ .clock = 30240,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x04, .pll[1] = 0x00, .pll[2] = 0xDC, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x00, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0D, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_31500 = {
+ .clock = 31500,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x62, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0xA0, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0C, .pll[16] = 0x09, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_36000 = {
+ .clock = 36000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xC4, .pll[1] = 0x00, .pll[2] = 0x76, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x00, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_40000 = {
+ .clock = 40000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x86, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x55, .pll[13] = 0x55, .pll[14] = 0x55,
+ .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_49500 = {
+ .clock = 49500,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0xAE, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x20, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_50000 = {
+ .clock = 50000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0xB0, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x2A, .pll[13] = 0xA9, .pll[14] = 0xAA,
+ .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_57284 = {
+ .clock = 57284,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xCE, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x77, .pll[12] = 0x57, .pll[13] = 0x77, .pll[14] = 0x77,
+ .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_58000 = {
+ .clock = 58000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xD0, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xD5, .pll[13] = 0x55, .pll[14] = 0x55,
+ .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_65000 = {
+ .clock = 65000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x66, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xB5, .pll[13] = 0x55, .pll[14] = 0x55,
+ .pll[15] = 0x0B, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_71000 = {
+ .clock = 71000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x72, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xF5, .pll[13] = 0x55, .pll[14] = 0x55,
+ .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_74176 = {
+ .clock = 74176,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x44, .pll[12] = 0x44, .pll[13] = 0x44, .pll[14] = 0x44,
+ .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_75000 = {
+ .clock = 75000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7C, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x20, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_78750 = {
+ .clock = 78750,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x84, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x08, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_85500 = {
+ .clock = 85500,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x92, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x10, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_88750 = {
+ .clock = 88750,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0x98, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x72, .pll[13] = 0xA9, .pll[14] = 0xAA,
+ .pll[15] = 0x0B, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_106500 = {
+ .clock = 106500,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xBC, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0xF0, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_108000 = {
+ .clock = 108000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xC0, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x80, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_115500 = {
+ .clock = 115500,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xD0, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x50, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_119000 = {
+ .clock = 119000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xD6, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xF5, .pll[13] = 0x55, .pll[14] = 0x55,
+ .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_135000 = {
+ .clock = 135000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x6C, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x50, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0A, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_138500 = {
+ .clock = 138500,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x70, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x22, .pll[13] = 0xA9, .pll[14] = 0xAA,
+ .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_147160 = {
+ .clock = 147160,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x78, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xA5, .pll[13] = 0x55, .pll[14] = 0x55,
+ .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_148352 = {
+ .clock = 148352,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x44, .pll[12] = 0x44, .pll[13] = 0x44, .pll[14] = 0x44,
+ .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_154000 = {
+ .clock = 154000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x80, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x35, .pll[13] = 0x55, .pll[14] = 0x55,
+ .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_162000 = {
+ .clock = 162000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x88, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x60, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_167000 = {
+ .clock = 167000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x8C, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0xFA, .pll[13] = 0xA9, .pll[14] = 0xAA,
+ .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_197802 = {
+ .clock = 197802,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0xAE, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x99, .pll[12] = 0x05, .pll[13] = 0x98, .pll[14] = 0x99,
+ .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_198000 = {
+ .clock = 198000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0xAE, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x20, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_209800 = {
+ .clock = 209800,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xBA, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x45, .pll[13] = 0x55, .pll[14] = 0x55,
+ .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_241500 = {
+ .clock = 241500,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xDA, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0xC8, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_262750 = {
+ .clock = 262750,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x68, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x6C, .pll[13] = 0xA9, .pll[14] = 0xAA,
+ .pll[15] = 0x09, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_268500 = {
+ .clock = 268500,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x6A, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0xEC, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x09, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_296703 = {
+ .clock = 296703,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x33, .pll[12] = 0x44, .pll[13] = 0x33, .pll[14] = 0x33,
+ .pll[15] = 0x09, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_297000 = {
+ .clock = 297000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x58, .pll[13] = 0x00, .pll[14] = 0x00,
+ .pll[15] = 0x09, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_319750 = {
+ .clock = 319750,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x86, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x44, .pll[13] = 0xA9, .pll[14] = 0xAA,
+ .pll[15] = 0x09, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_497750 = {
+ .clock = 497750,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xE2, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x9F, .pll[13] = 0x55, .pll[14] = 0x55,
+ .pll[15] = 0x09, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_592000 = {
+ .clock = 592000,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x15, .pll[13] = 0x55, .pll[14] = 0x55,
+ .pll[15] = 0x08, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state mtl_c10_hdmi_593407 = {
+ .clock = 593407,
+ .tx = 0x10,
+ .cmn = 0x1,
+ .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00,
+ .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
+ .pll[10] = 0xFF, .pll[11] = 0x3B, .pll[12] = 0x44, .pll[13] = 0xBA, .pll[14] = 0xBB,
+ .pll[15] = 0x08, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
+};
+
+static const struct intel_c10pll_state * const mtl_c10_hdmi_tables[] = {
+ &mtl_c10_hdmi_25_2, /* Consolidated Table */
+ &mtl_c10_hdmi_27_0, /* Consolidated Table */
+ &mtl_c10_hdmi_27027,
+ &mtl_c10_hdmi_28320,
+ &mtl_c10_hdmi_30240,
+ &mtl_c10_hdmi_31500,
+ &mtl_c10_hdmi_36000,
+ &mtl_c10_hdmi_40000,
+ &mtl_c10_hdmi_49500,
+ &mtl_c10_hdmi_50000,
+ &mtl_c10_hdmi_57284,
+ &mtl_c10_hdmi_58000,
+ &mtl_c10_hdmi_65000,
+ &mtl_c10_hdmi_71000,
+ &mtl_c10_hdmi_74176,
+ &mtl_c10_hdmi_74_25, /* Consolidated Table */
+ &mtl_c10_hdmi_75000,
+ &mtl_c10_hdmi_78750,
+ &mtl_c10_hdmi_85500,
+ &mtl_c10_hdmi_88750,
+ &mtl_c10_hdmi_106500,
+ &mtl_c10_hdmi_108000,
+ &mtl_c10_hdmi_115500,
+ &mtl_c10_hdmi_119000,
+ &mtl_c10_hdmi_135000,
+ &mtl_c10_hdmi_138500,
+ &mtl_c10_hdmi_147160,
+ &mtl_c10_hdmi_148352,
+ &mtl_c10_hdmi_148_5, /* Consolidated Table */
+ &mtl_c10_hdmi_154000,
+ &mtl_c10_hdmi_162000,
+ &mtl_c10_hdmi_167000,
+ &mtl_c10_hdmi_197802,
+ &mtl_c10_hdmi_198000,
+ &mtl_c10_hdmi_209800,
+ &mtl_c10_hdmi_241500,
+ &mtl_c10_hdmi_262750,
+ &mtl_c10_hdmi_268500,
+ &mtl_c10_hdmi_296703,
+ &mtl_c10_hdmi_297000,
+ &mtl_c10_hdmi_319750,
+ &mtl_c10_hdmi_497750,
+ &mtl_c10_hdmi_592000,
+ &mtl_c10_hdmi_593407,
+ &mtl_c10_hdmi_594, /* Consolidated Table */
+ NULL,
+};
+
+static const struct intel_c20pll_state mtl_c20_hdmi_25_175 = {
+ .link_bit_rate = 25175,
+ .clock = 25175,
+ .tx = { 0xbe88, /* tx cfg0 */
+ 0x9800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = { 0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0xa0d2, /* mpllb cfg0 */
+ 0x7d80, /* mpllb cfg1 */
+ 0x0906, /* mpllb cfg2 */
+ 0xbe40, /* mpllb cfg3 */
+ 0x0000, /* mpllb cfg4 */
+ 0x0000, /* mpllb cfg5 */
+ 0x0200, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x0000, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0001, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_hdmi_27_0 = {
+ .link_bit_rate = 27000,
+ .clock = 27000,
+ .tx = { 0xbe88, /* tx cfg0 */
+ 0x9800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = { 0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0xa0e0, /* mpllb cfg0 */
+ 0x7d80, /* mpllb cfg1 */
+ 0x0906, /* mpllb cfg2 */
+ 0xbe40, /* mpllb cfg3 */
+ 0x0000, /* mpllb cfg4 */
+ 0x0000, /* mpllb cfg5 */
+ 0x2200, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x8000, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0001, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_hdmi_74_25 = {
+ .link_bit_rate = 74250,
+ .clock = 74250,
+ .tx = { 0xbe88, /* tx cfg0 */
+ 0x9800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = { 0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x609a, /* mpllb cfg0 */
+ 0x7d40, /* mpllb cfg1 */
+ 0xca06, /* mpllb cfg2 */
+ 0xbe40, /* mpllb cfg3 */
+ 0x0000, /* mpllb cfg4 */
+ 0x0000, /* mpllb cfg5 */
+ 0x2200, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x5800, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0001, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_hdmi_148_5 = {
+ .link_bit_rate = 148500,
+ .clock = 148500,
+ .tx = { 0xbe88, /* tx cfg0 */
+ 0x9800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = { 0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x409a, /* mpllb cfg0 */
+ 0x7d20, /* mpllb cfg1 */
+ 0xca06, /* mpllb cfg2 */
+ 0xbe40, /* mpllb cfg3 */
+ 0x0000, /* mpllb cfg4 */
+ 0x0000, /* mpllb cfg5 */
+ 0x2200, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x5800, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0001, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_hdmi_594 = {
+ .link_bit_rate = 594000,
+ .clock = 594000,
+ .tx = { 0xbe88, /* tx cfg0 */
+ 0x9800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = { 0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x009a, /* mpllb cfg0 */
+ 0x7d08, /* mpllb cfg1 */
+ 0xca06, /* mpllb cfg2 */
+ 0xbe40, /* mpllb cfg3 */
+ 0x0000, /* mpllb cfg4 */
+ 0x0000, /* mpllb cfg5 */
+ 0x2200, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x5800, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0001, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_hdmi_300 = {
+ .link_bit_rate = 3000000,
+ .clock = 166670,
+ .tx = { 0xbe98, /* tx cfg0 */
+ 0x9800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = { 0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x209c, /* mpllb cfg0 */
+ 0x7d10, /* mpllb cfg1 */
+ 0xca06, /* mpllb cfg2 */
+ 0xbe40, /* mpllb cfg3 */
+ 0x0000, /* mpllb cfg4 */
+ 0x0000, /* mpllb cfg5 */
+ 0x2200, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x2000, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0004, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_hdmi_600 = {
+ .link_bit_rate = 6000000,
+ .clock = 333330,
+ .tx = { 0xbe98, /* tx cfg0 */
+ 0x9800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = { 0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x009c, /* mpllb cfg0 */
+ 0x7d08, /* mpllb cfg1 */
+ 0xca06, /* mpllb cfg2 */
+ 0xbe40, /* mpllb cfg3 */
+ 0x0000, /* mpllb cfg4 */
+ 0x0000, /* mpllb cfg5 */
+ 0x2200, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x2000, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0004, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_hdmi_800 = {
+ .link_bit_rate = 8000000,
+ .clock = 444440,
+ .tx = { 0xbe98, /* tx cfg0 */
+ 0x9800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = { 0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x00d0, /* mpllb cfg0 */
+ 0x7d08, /* mpllb cfg1 */
+ 0x4a06, /* mpllb cfg2 */
+ 0xbe40, /* mpllb cfg3 */
+ 0x0000, /* mpllb cfg4 */
+ 0x0000, /* mpllb cfg5 */
+ 0x2200, /* mpllb cfg6 */
+ 0x0003, /* mpllb cfg7 */
+ 0x2aaa, /* mpllb cfg8 */
+ 0x0002, /* mpllb cfg9 */
+ 0x0004, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_hdmi_1000 = {
+ .link_bit_rate = 10000000,
+ .clock = 555560,
+ .tx = { 0xbe98, /* tx cfg0 */
+ 0x9800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = { 0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x1104, /* mpllb cfg0 */
+ 0x7d08, /* mpllb cfg1 */
+ 0x0a06, /* mpllb cfg2 */
+ 0xbe40, /* mpllb cfg3 */
+ 0x0000, /* mpllb cfg4 */
+ 0x0000, /* mpllb cfg5 */
+ 0x2200, /* mpllb cfg6 */
+ 0x0003, /* mpllb cfg7 */
+ 0x3555, /* mpllb cfg8 */
+ 0x0001, /* mpllb cfg9 */
+ 0x0004, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state mtl_c20_hdmi_1200 = {
+ .link_bit_rate = 12000000,
+ .clock = 666670,
+ .tx = { 0xbe98, /* tx cfg0 */
+ 0x9800, /* tx cfg1 */
+ 0x0000, /* tx cfg2 */
+ },
+ .cmn = { 0x0500, /* cmn cfg0*/
+ 0x0005, /* cmn cfg1 */
+ 0x0000, /* cmn cfg2 */
+ 0x0000, /* cmn cfg3 */
+ },
+ .mpllb = { 0x0138, /* mpllb cfg0 */
+ 0x7d08, /* mpllb cfg1 */
+ 0x5486, /* mpllb cfg2 */
+ 0xfe40, /* mpllb cfg3 */
+ 0x0000, /* mpllb cfg4 */
+ 0x0000, /* mpllb cfg5 */
+ 0x2200, /* mpllb cfg6 */
+ 0x0001, /* mpllb cfg7 */
+ 0x4000, /* mpllb cfg8 */
+ 0x0000, /* mpllb cfg9 */
+ 0x0004, /* mpllb cfg10 */
+ },
+};
+
+static const struct intel_c20pll_state * const mtl_c20_hdmi_tables[] = {
+ &mtl_c20_hdmi_25_175,
+ &mtl_c20_hdmi_27_0,
+ &mtl_c20_hdmi_74_25,
+ &mtl_c20_hdmi_148_5,
+ &mtl_c20_hdmi_594,
+ &mtl_c20_hdmi_300,
+ &mtl_c20_hdmi_600,
+ &mtl_c20_hdmi_800,
+ &mtl_c20_hdmi_1000,
+ &mtl_c20_hdmi_1200,
+ NULL,
+};
+
+static int intel_c10_phy_check_hdmi_link_rate(int clock)
+{
+ const struct intel_c10pll_state * const *tables = mtl_c10_hdmi_tables;
+ int i;
+
+ for (i = 0; tables[i]; i++) {
+ if (clock == tables[i]->clock)
+ return MODE_OK;
+ }
+
+ return MODE_CLOCK_RANGE;
+}
+
+static const struct intel_c10pll_state * const *
+intel_c10pll_tables_get(struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder)
+{
+ if (intel_crtc_has_dp_encoder(crtc_state)) {
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
+ return mtl_c10_edp_tables;
+ else
+ return mtl_c10_dp_tables;
+ } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
+ return mtl_c10_hdmi_tables;
+ }
+
+ MISSING_CASE(encoder->type);
+ return NULL;
+}
+
+static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_cx0pll_state *pll_state = &crtc_state->cx0pll_state;
+ int i;
+
+ if (intel_crtc_has_dp_encoder(crtc_state)) {
+ if (intel_panel_use_ssc(i915)) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ pll_state->ssc_enabled =
+ (intel_dp->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5);
+ }
+ }
+
+ if (pll_state->ssc_enabled)
+ return;
+
+ drm_WARN_ON(&i915->drm, ARRAY_SIZE(pll_state->c10.pll) < 9);
+ for (i = 4; i < 9; i++)
+ pll_state->c10.pll[i] = 0;
+}
+
+static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder)
+{
+ const struct intel_c10pll_state * const *tables;
+ int i;
+
+ tables = intel_c10pll_tables_get(crtc_state, encoder);
+ if (!tables)
+ return -EINVAL;
+
+ for (i = 0; tables[i]; i++) {
+ if (crtc_state->port_clock == tables[i]->clock) {
+ crtc_state->cx0pll_state.c10 = *tables[i];
+ intel_c10pll_update_pll(crtc_state, encoder);
+
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
+ struct intel_c10pll_state *pll_state)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ u8 lane = INTEL_CX0_LANE0;
+ intel_wakeref_t wakeref;
+ int i;
+
+ wakeref = intel_cx0_phy_transaction_begin(encoder);
+
+ /*
+ * According to C10 VDR Register programming Sequence we need
+ * to do this to read PHY internal registers from MsgBus.
+ */
+ intel_cx0_rmw(i915, encoder->port, lane, PHY_C10_VDR_CONTROL(1),
+ 0, C10_VDR_CTRL_MSGBUS_ACCESS,
+ MB_WRITE_COMMITTED);
+
+ for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++)
+ pll_state->pll[i] = intel_cx0_read(i915, encoder->port, lane,
+ PHY_C10_VDR_PLL(i));
+
+ pll_state->cmn = intel_cx0_read(i915, encoder->port, lane, PHY_C10_VDR_CMN(0));
+ pll_state->tx = intel_cx0_read(i915, encoder->port, lane, PHY_C10_VDR_TX(0));
+
+ intel_cx0_phy_transaction_end(encoder, wakeref);
+}
+
+static void intel_c10_pll_program(struct drm_i915_private *i915,
+ const struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder)
+{
+ const struct intel_c10pll_state *pll_state = &crtc_state->cx0pll_state.c10;
+ int i;
+
+ intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
+ 0, C10_VDR_CTRL_MSGBUS_ACCESS,
+ MB_WRITE_COMMITTED);
+
+ /* Custom width needs to be programmed to 0 for both the phy lanes */
+ intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CUSTOM_WIDTH,
+ C10_VDR_CUSTOM_WIDTH_MASK, C10_VDR_CUSTOM_WIDTH_8_10,
+ MB_WRITE_COMMITTED);
+ intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
+ 0, C10_VDR_CTRL_UPDATE_CFG,
+ MB_WRITE_COMMITTED);
+
+ /* Program the pll values only for the master lane */
+ for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++)
+ intel_cx0_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C10_VDR_PLL(i),
+ pll_state->pll[i],
+ (i % 4) ? MB_WRITE_UNCOMMITTED : MB_WRITE_COMMITTED);
+
+ intel_cx0_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C10_VDR_CMN(0), pll_state->cmn, MB_WRITE_COMMITTED);
+ intel_cx0_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C10_VDR_TX(0), pll_state->tx, MB_WRITE_COMMITTED);
+
+ intel_cx0_rmw(i915, encoder->port, INTEL_CX0_LANE0, PHY_C10_VDR_CONTROL(1),
+ 0, C10_VDR_CTRL_MASTER_LANE | C10_VDR_CTRL_UPDATE_CFG,
+ MB_WRITE_COMMITTED);
+}
+
+void intel_c10pll_dump_hw_state(struct drm_i915_private *i915,
+ const struct intel_c10pll_state *hw_state)
+{
+ bool fracen;
+ int i;
+ unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1;
+ unsigned int multiplier, tx_clk_div;
+
+ fracen = hw_state->pll[0] & C10_PLL0_FRACEN;
+ drm_dbg_kms(&i915->drm, "c10pll_hw_state: fracen: %s, ",
+ str_yes_no(fracen));
+
+ if (fracen) {
+ frac_quot = hw_state->pll[12] << 8 | hw_state->pll[11];
+ frac_rem = hw_state->pll[14] << 8 | hw_state->pll[13];
+ frac_den = hw_state->pll[10] << 8 | hw_state->pll[9];
+ drm_dbg_kms(&i915->drm, "quot: %u, rem: %u, den: %u,\n",
+ frac_quot, frac_rem, frac_den);
+ }
+
+ multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, hw_state->pll[3]) << 8 |
+ hw_state->pll[2]) / 2 + 16;
+ tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, hw_state->pll[15]);
+ drm_dbg_kms(&i915->drm,
+ "multiplier: %u, tx_clk_div: %u.\n", multiplier, tx_clk_div);
+
+ drm_dbg_kms(&i915->drm, "c10pll_rawhw_state:");
+ drm_dbg_kms(&i915->drm, "tx: 0x%x, cmn: 0x%x\n", hw_state->tx, hw_state->cmn);
+
+ BUILD_BUG_ON(ARRAY_SIZE(hw_state->pll) % 4);
+ for (i = 0; i < ARRAY_SIZE(hw_state->pll); i = i + 4)
+ drm_dbg_kms(&i915->drm, "pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x\n",
+ i, hw_state->pll[i], i + 1, hw_state->pll[i + 1],
+ i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]);
+}
+
+static int intel_c20_compute_hdmi_tmds_pll(u64 pixel_clock, struct intel_c20pll_state *pll_state)
+{
+ u64 datarate;
+ u64 mpll_tx_clk_div;
+ u64 vco_freq_shift;
+ u64 vco_freq;
+ u64 multiplier;
+ u64 mpll_multiplier;
+ u64 mpll_fracn_quot;
+ u64 mpll_fracn_rem;
+ u8 mpllb_ana_freq_vco;
+ u8 mpll_div_multiplier;
+
+ if (pixel_clock < 25175 || pixel_clock > 600000)
+ return -EINVAL;
+
+ datarate = ((u64)pixel_clock * 1000) * 10;
+ mpll_tx_clk_div = ilog2(div64_u64((u64)CLOCK_9999MHZ, (u64)datarate));
+ vco_freq_shift = ilog2(div64_u64((u64)CLOCK_4999MHZ * (u64)256, (u64)datarate));
+ vco_freq = (datarate << vco_freq_shift) >> 8;
+ multiplier = div64_u64((vco_freq << 28), (REFCLK_38_4_MHZ >> 4));
+ mpll_multiplier = 2 * (multiplier >> 32);
+
+ mpll_fracn_quot = (multiplier >> 16) & 0xFFFF;
+ mpll_fracn_rem = multiplier & 0xFFFF;
+
+ mpll_div_multiplier = min_t(u8, div64_u64((vco_freq * 16 + (datarate >> 1)),
+ datarate), 255);
+
+ if (vco_freq <= DATARATE_3000000000)
+ mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_3;
+ else if (vco_freq <= DATARATE_3500000000)
+ mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_2;
+ else if (vco_freq <= DATARATE_4000000000)
+ mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_1;
+ else
+ mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_0;
+
+ pll_state->link_bit_rate = pixel_clock;
+ pll_state->clock = pixel_clock;
+ pll_state->tx[0] = 0xbe88;
+ pll_state->tx[1] = 0x9800;
+ pll_state->tx[2] = 0x0000;
+ pll_state->cmn[0] = 0x0500;
+ pll_state->cmn[1] = 0x0005;
+ pll_state->cmn[2] = 0x0000;
+ pll_state->cmn[3] = 0x0000;
+ pll_state->mpllb[0] = (MPLL_TX_CLK_DIV(mpll_tx_clk_div) |
+ MPLL_MULTIPLIER(mpll_multiplier));
+ pll_state->mpllb[1] = (CAL_DAC_CODE(CAL_DAC_CODE_31) |
+ WORD_CLK_DIV |
+ MPLL_DIV_MULTIPLIER(mpll_div_multiplier));
+ pll_state->mpllb[2] = (MPLLB_ANA_FREQ_VCO(mpllb_ana_freq_vco) |
+ CP_PROP(CP_PROP_20) |
+ CP_INT(CP_INT_6));
+ pll_state->mpllb[3] = (V2I(V2I_2) |
+ CP_PROP_GS(CP_PROP_GS_30) |
+ CP_INT_GS(CP_INT_GS_28));
+ pll_state->mpllb[4] = 0x0000;
+ pll_state->mpllb[5] = 0x0000;
+ pll_state->mpllb[6] = (C20_MPLLB_FRACEN | SSC_UP_SPREAD);
+ pll_state->mpllb[7] = MPLL_FRACN_DEN;
+ pll_state->mpllb[8] = mpll_fracn_quot;
+ pll_state->mpllb[9] = mpll_fracn_rem;
+ pll_state->mpllb[10] = HDMI_DIV(HDMI_DIV_1);
+
+ return 0;
+}
+
+static int intel_c20_phy_check_hdmi_link_rate(int clock)
+{
+ const struct intel_c20pll_state * const *tables = mtl_c20_hdmi_tables;
+ int i;
+
+ for (i = 0; tables[i]; i++) {
+ if (clock == tables[i]->link_bit_rate)
+ return MODE_OK;
+ }
+
+ if (clock >= 25175 && clock <= 594000)
+ return MODE_OK;
+
+ return MODE_CLOCK_RANGE;
+}
+
+int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock)
+{
+ struct intel_digital_port *dig_port = hdmi_to_dig_port(hdmi);
+ struct drm_i915_private *i915 = intel_hdmi_to_i915(hdmi);
+ enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
+
+ if (intel_is_c10phy(i915, phy))
+ return intel_c10_phy_check_hdmi_link_rate(clock);
+ return intel_c20_phy_check_hdmi_link_rate(clock);
+}
+
+static const struct intel_c20pll_state * const *
+intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder)
+{
+ if (intel_crtc_has_dp_encoder(crtc_state))
+ return mtl_c20_dp_tables;
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return mtl_c20_hdmi_tables;
+
+ MISSING_CASE(encoder->type);
+ return NULL;
+}
+
+static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder)
+{
+ const struct intel_c20pll_state * const *tables;
+ int i;
+
+ /* try computed C20 HDMI tables before using consolidated tables */
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
+ if (intel_c20_compute_hdmi_tmds_pll(crtc_state->port_clock,
+ &crtc_state->cx0pll_state.c20) == 0)
+ return 0;
+ }
+
+ tables = intel_c20_pll_tables_get(crtc_state, encoder);
+ if (!tables)
+ return -EINVAL;
+
+ for (i = 0; tables[i]; i++) {
+ if (crtc_state->port_clock == tables[i]->link_bit_rate) {
+ crtc_state->cx0pll_state.c20 = *tables[i];
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
+
+ if (intel_is_c10phy(i915, phy))
+ return intel_c10pll_calc_state(crtc_state, encoder);
+ return intel_c20pll_calc_state(crtc_state, encoder);
+}
+
+static bool intel_c20_use_mplla(u32 clock)
+{
+ /* 10G and 20G rates use MPLLA */
+ if (clock == 312500 || clock == 625000)
+ return true;
+
+ return false;
+}
+
+void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
+ struct intel_c20pll_state *pll_state)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ bool cntx;
+ intel_wakeref_t wakeref;
+ int i;
+
+ wakeref = intel_cx0_phy_transaction_begin(encoder);
+
+ /* 1. Read current context selection */
+ cntx = intel_cx0_read(i915, encoder->port, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & PHY_C20_CONTEXT_TOGGLE;
+
+ /* Read Tx configuration */
+ for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) {
+ if (cntx)
+ pll_state->tx[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0,
+ PHY_C20_B_TX_CNTX_CFG(i));
+ else
+ pll_state->tx[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0,
+ PHY_C20_A_TX_CNTX_CFG(i));
+ }
+
+ /* Read common configuration */
+ for (i = 0; i < ARRAY_SIZE(pll_state->cmn); i++) {
+ if (cntx)
+ pll_state->cmn[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0,
+ PHY_C20_B_CMN_CNTX_CFG(i));
+ else
+ pll_state->cmn[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0,
+ PHY_C20_A_CMN_CNTX_CFG(i));
+ }
+
+ if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
+ /* MPLLB configuration */
+ for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
+ if (cntx)
+ pll_state->mpllb[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0,
+ PHY_C20_B_MPLLB_CNTX_CFG(i));
+ else
+ pll_state->mpllb[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0,
+ PHY_C20_A_MPLLB_CNTX_CFG(i));
+ }
+ } else {
+ /* MPLLA configuration */
+ for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) {
+ if (cntx)
+ pll_state->mplla[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0,
+ PHY_C20_B_MPLLA_CNTX_CFG(i));
+ else
+ pll_state->mplla[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0,
+ PHY_C20_A_MPLLA_CNTX_CFG(i));
+ }
+ }
+
+ intel_cx0_phy_transaction_end(encoder, wakeref);
+}
+
+void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
+ const struct intel_c20pll_state *hw_state)
+{
+ int i;
+
+ drm_dbg_kms(&i915->drm, "c20pll_hw_state:\n");
+ drm_dbg_kms(&i915->drm, "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 0x%.4x\n",
+ hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]);
+ drm_dbg_kms(&i915->drm, "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 0x%.4x, cmn[3] = 0x%.4x\n",
+ hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], hw_state->cmn[3]);
+
+ if (intel_c20_use_mplla(hw_state->clock)) {
+ for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++)
+ drm_dbg_kms(&i915->drm, "mplla[%d] = 0x%.4x\n", i, hw_state->mplla[i]);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++)
+ drm_dbg_kms(&i915->drm, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]);
+ }
+}
+
+static u8 intel_c20_get_dp_rate(u32 clock)
+{
+ switch (clock) {
+ case 162000: /* 1.62 Gbps DP1.4 */
+ return 0;
+ case 270000: /* 2.7 Gbps DP1.4 */
+ return 1;
+ case 540000: /* 5.4 Gbps DP 1.4 */
+ return 2;
+ case 810000: /* 8.1 Gbps DP1.4 */
+ return 3;
+ case 216000: /* 2.16 Gbps eDP */
+ return 4;
+ case 243000: /* 2.43 Gbps eDP */
+ return 5;
+ case 324000: /* 3.24 Gbps eDP */
+ return 6;
+ case 432000: /* 4.32 Gbps eDP */
+ return 7;
+ case 312500: /* 10 Gbps DP2.0 */
+ return 8;
+ case 421875: /* 13.5 Gbps DP2.0 */
+ return 9;
+ case 625000: /* 20 Gbps DP2.0*/
+ return 10;
+ case 648000: /* 6.48 Gbps eDP*/
+ return 11;
+ case 675000: /* 6.75 Gbps eDP*/
+ return 12;
+ default:
+ MISSING_CASE(clock);
+ return 0;
+ }
+}
+
+static u8 intel_c20_get_hdmi_rate(u32 clock)
+{
+ if (clock >= 25175 && clock <= 600000)
+ return 0;
+
+ switch (clock) {
+ case 166670: /* 3 Gbps */
+ case 333330: /* 6 Gbps */
+ case 666670: /* 12 Gbps */
+ return 1;
+ case 444440: /* 8 Gbps */
+ return 2;
+ case 555560: /* 10 Gbps */
+ return 3;
+ default:
+ MISSING_CASE(clock);
+ return 0;
+ }
+}
+
+static bool is_dp2(u32 clock)
+{
+ /* DP2.0 clock rates */
+ if (clock == 312500 || clock == 421875 || clock == 625000)
+ return true;
+
+ return false;
+}
+
+static bool is_hdmi_frl(u32 clock)
+{
+ switch (clock) {
+ case 166670: /* 3 Gbps */
+ case 333330: /* 6 Gbps */
+ case 444440: /* 8 Gbps */
+ case 555560: /* 10 Gbps */
+ case 666670: /* 12 Gbps */
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder)
+{
+ struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+
+ /* banks should not be cleared for DPALT/USB4/TBT modes */
+ /* TODO: optimize re-calibration in legacy mode */
+ return intel_tc_port_in_legacy_mode(intel_dig_port);
+}
+
+static int intel_get_c20_custom_width(u32 clock, bool dp)
+{
+ if (dp && is_dp2(clock))
+ return 2;
+ else if (is_hdmi_frl(clock))
+ return 1;
+ else
+ return 0;
+}
+
+static void intel_c20_pll_program(struct drm_i915_private *i915,
+ const struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder)
+{
+ const struct intel_c20pll_state *pll_state = &crtc_state->cx0pll_state.c20;
+ bool dp = false;
+ int lane = crtc_state->lane_count > 2 ? INTEL_CX0_BOTH_LANES : INTEL_CX0_LANE0;
+ bool cntx;
+ int i;
+
+ if (intel_crtc_has_dp_encoder(crtc_state))
+ dp = true;
+
+ /* 1. Read current context selection */
+ cntx = intel_cx0_read(i915, encoder->port, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & BIT(0);
+
+ /*
+ * 2. If there is a protocol switch from HDMI to DP or vice versa, clear
+ * the lane #0 MPLLB CAL_DONE_BANK DP2.0 10G and 20G rates enable MPLLA.
+ * Protocol switch is only applicable for MPLLA
+ */
+ if (intel_c20_protocol_switch_valid(encoder)) {
+ for (i = 0; i < 4; i++)
+ intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, RAWLANEAONX_DIG_TX_MPLLB_CAL_DONE_BANK(i), 0);
+ usleep_range(4000, 4100);
+ }
+
+ /* 3. Write SRAM configuration context. If A in use, write configuration to B context */
+ /* 3.1 Tx configuration */
+ for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) {
+ if (cntx)
+ intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C20_A_TX_CNTX_CFG(i), pll_state->tx[i]);
+ else
+ intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C20_B_TX_CNTX_CFG(i), pll_state->tx[i]);
+ }
+
+ /* 3.2 common configuration */
+ for (i = 0; i < ARRAY_SIZE(pll_state->cmn); i++) {
+ if (cntx)
+ intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C20_A_CMN_CNTX_CFG(i), pll_state->cmn[i]);
+ else
+ intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C20_B_CMN_CNTX_CFG(i), pll_state->cmn[i]);
+ }
+
+ /* 3.3 mpllb or mplla configuration */
+ if (intel_c20_use_mplla(pll_state->clock)) {
+ for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) {
+ if (cntx)
+ intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0,
+ PHY_C20_A_MPLLA_CNTX_CFG(i),
+ pll_state->mplla[i]);
+ else
+ intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0,
+ PHY_C20_B_MPLLA_CNTX_CFG(i),
+ pll_state->mplla[i]);
+ }
+ } else {
+ for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
+ if (cntx)
+ intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0,
+ PHY_C20_A_MPLLB_CNTX_CFG(i),
+ pll_state->mpllb[i]);
+ else
+ intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0,
+ PHY_C20_B_MPLLB_CNTX_CFG(i),
+ pll_state->mpllb[i]);
+ }
+ }
+
+ /* 4. Program custom width to match the link protocol */
+ intel_cx0_rmw(i915, encoder->port, lane, PHY_C20_VDR_CUSTOM_WIDTH,
+ PHY_C20_CUSTOM_WIDTH_MASK,
+ PHY_C20_CUSTOM_WIDTH(intel_get_c20_custom_width(pll_state->clock, dp)),
+ MB_WRITE_COMMITTED);
+
+ /* 5. For DP or 6. For HDMI */
+ if (dp) {
+ intel_cx0_rmw(i915, encoder->port, lane, PHY_C20_VDR_CUSTOM_SERDES_RATE,
+ BIT(6) | PHY_C20_CUSTOM_SERDES_MASK,
+ BIT(6) | PHY_C20_CUSTOM_SERDES(intel_c20_get_dp_rate(pll_state->clock)),
+ MB_WRITE_COMMITTED);
+ } else {
+ intel_cx0_rmw(i915, encoder->port, lane, PHY_C20_VDR_CUSTOM_SERDES_RATE,
+ BIT(7) | PHY_C20_CUSTOM_SERDES_MASK,
+ is_hdmi_frl(pll_state->clock) ? BIT(7) : 0,
+ MB_WRITE_COMMITTED);
+
+ intel_cx0_write(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE,
+ intel_c20_get_hdmi_rate(pll_state->clock),
+ MB_WRITE_COMMITTED);
+ }
+
+ /*
+ * 7. Write Vendor specific registers to toggle context setting to load
+ * the updated programming toggle context bit
+ */
+ intel_cx0_rmw(i915, encoder->port, lane, PHY_C20_VDR_CUSTOM_SERDES_RATE,
+ BIT(0), cntx ? 0 : 1, MB_WRITE_COMMITTED);
+}
+
+int intel_c10pll_calc_port_clock(struct intel_encoder *encoder,
+ const struct intel_c10pll_state *pll_state)
+{
+ unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1;
+ unsigned int multiplier, tx_clk_div, hdmi_div, refclk = 38400;
+ int tmpclk = 0;
+
+ if (pll_state->pll[0] & C10_PLL0_FRACEN) {
+ frac_quot = pll_state->pll[12] << 8 | pll_state->pll[11];
+ frac_rem = pll_state->pll[14] << 8 | pll_state->pll[13];
+ frac_den = pll_state->pll[10] << 8 | pll_state->pll[9];
+ }
+
+ multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, pll_state->pll[3]) << 8 |
+ pll_state->pll[2]) / 2 + 16;
+
+ tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, pll_state->pll[15]);
+ hdmi_div = REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]);
+
+ tmpclk = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, (multiplier << 16) + frac_quot) +
+ DIV_ROUND_CLOSEST(refclk * frac_rem, frac_den),
+ 10 << (tx_clk_div + 16));
+ tmpclk *= (hdmi_div ? 2 : 1);
+
+ return tmpclk;
+}
+
+int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
+ const struct intel_c20pll_state *pll_state)
+{
+ unsigned int frac, frac_en, frac_quot, frac_rem, frac_den;
+ unsigned int multiplier, refclk = 38400;
+ unsigned int tx_clk_div;
+ unsigned int ref_clk_mpllb_div;
+ unsigned int fb_clk_div4_en;
+ unsigned int ref, vco;
+ unsigned int tx_rate_mult;
+ unsigned int tx_rate = REG_FIELD_GET(C20_PHY_TX_RATE, pll_state->tx[0]);
+
+ if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
+ tx_rate_mult = 1;
+ frac_en = REG_FIELD_GET(C20_MPLLB_FRACEN, pll_state->mpllb[6]);
+ frac_quot = pll_state->mpllb[8];
+ frac_rem = pll_state->mpllb[9];
+ frac_den = pll_state->mpllb[7];
+ multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, pll_state->mpllb[0]);
+ tx_clk_div = REG_FIELD_GET(C20_MPLLB_TX_CLK_DIV_MASK, pll_state->mpllb[0]);
+ ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, pll_state->mpllb[6]);
+ fb_clk_div4_en = 0;
+ } else {
+ tx_rate_mult = 2;
+ frac_en = REG_FIELD_GET(C20_MPLLA_FRACEN, pll_state->mplla[6]);
+ frac_quot = pll_state->mplla[8];
+ frac_rem = pll_state->mplla[9];
+ frac_den = pll_state->mplla[7];
+ multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, pll_state->mplla[0]);
+ tx_clk_div = REG_FIELD_GET(C20_MPLLA_TX_CLK_DIV_MASK, pll_state->mplla[1]);
+ ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, pll_state->mplla[6]);
+ fb_clk_div4_en = REG_FIELD_GET(C20_FB_CLK_DIV4_EN, pll_state->mplla[0]);
+ }
+
+ if (frac_en)
+ frac = frac_quot + DIV_ROUND_CLOSEST(frac_rem, frac_den);
+ else
+ frac = 0;
+
+ ref = DIV_ROUND_CLOSEST(refclk * (1 << (1 + fb_clk_div4_en)), 1 << ref_clk_mpllb_div);
+ vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(ref, (multiplier << (17 - 2)) + frac) >> 17, 10);
+
+ return vco << tx_rate_mult >> tx_clk_div >> tx_rate;
+}
+
+static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ bool lane_reversal)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ u32 val = 0;
+
+ intel_de_rmw(i915, XELPDP_PORT_BUF_CTL1(encoder->port), XELPDP_PORT_REVERSAL,
+ lane_reversal ? XELPDP_PORT_REVERSAL : 0);
+
+ if (lane_reversal)
+ val |= XELPDP_LANE1_PHY_CLOCK_SELECT;
+
+ val |= XELPDP_FORWARD_CLOCK_UNGATE;
+
+ if (is_hdmi_frl(crtc_state->port_clock))
+ val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_DIV18CLK);
+ else
+ val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
+
+ /* TODO: HDMI FRL */
+ /* DP2.0 10G and 20G rates enable MPLLA*/
+ if (crtc_state->port_clock == 1000000 || crtc_state->port_clock == 2000000)
+ val |= crtc_state->cx0pll_state.ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
+ else
+ val |= crtc_state->cx0pll_state.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
+
+ intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+ XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE |
+ XELPDP_DDI_CLOCK_SELECT_MASK | XELPDP_SSC_ENABLE_PLLB, val);
+}
+
+static u32 intel_cx0_get_powerdown_update(u8 lane_mask)
+{
+ u32 val = 0;
+ int lane = 0;
+
+ for_each_cx0_lane_in_mask(lane_mask, lane)
+ val |= XELPDP_LANE_POWERDOWN_UPDATE(lane);
+
+ return val;
+}
+
+static u32 intel_cx0_get_powerdown_state(u8 lane_mask, u8 state)
+{
+ u32 val = 0;
+ int lane = 0;
+
+ for_each_cx0_lane_in_mask(lane_mask, lane)
+ val |= XELPDP_LANE_POWERDOWN_NEW_STATE(lane, state);
+
+ return val;
+}
+
+static void intel_cx0_powerdown_change_sequence(struct drm_i915_private *i915,
+ enum port port,
+ u8 lane_mask, u8 state)
+{
+ enum phy phy = intel_port_to_phy(i915, port);
+ int lane;
+
+ intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
+ intel_cx0_get_powerdown_state(INTEL_CX0_BOTH_LANES, XELPDP_LANE_POWERDOWN_NEW_STATE_MASK),
+ intel_cx0_get_powerdown_state(lane_mask, state));
+
+ /* Wait for pending transactions.*/
+ for_each_cx0_lane_in_mask(lane_mask, lane)
+ if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
+ XELPDP_PORT_M2P_TRANSACTION_PENDING,
+ XELPDP_MSGBUS_TIMEOUT_SLOW)) {
+ drm_dbg_kms(&i915->drm,
+ "PHY %c Timeout waiting for previous transaction to complete. Reset the bus.\n",
+ phy_name(phy));
+ intel_cx0_bus_reset(i915, port, lane);
+ }
+
+ intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
+ intel_cx0_get_powerdown_update(INTEL_CX0_BOTH_LANES),
+ intel_cx0_get_powerdown_update(lane_mask));
+
+ /* Update Timeout Value */
+ if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL2(port),
+ intel_cx0_get_powerdown_update(lane_mask), 0,
+ XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US, 0, NULL))
+ drm_warn(&i915->drm, "PHY %c failed to bring out of Lane reset after %dus.\n",
+ phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US);
+}
+
+static void intel_cx0_setup_powerdown(struct drm_i915_private *i915, enum port port)
+{
+ intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
+ XELPDP_POWER_STATE_READY_MASK,
+ XELPDP_POWER_STATE_READY(CX0_P2_STATE_READY));
+ intel_de_rmw(i915, XELPDP_PORT_BUF_CTL3(port),
+ XELPDP_POWER_STATE_ACTIVE_MASK |
+ XELPDP_PLL_LANE_STAGGERING_DELAY_MASK,
+ XELPDP_POWER_STATE_ACTIVE(CX0_P0_STATE_ACTIVE) |
+ XELPDP_PLL_LANE_STAGGERING_DELAY(0));
+}
+
+static u32 intel_cx0_get_pclk_refclk_request(u8 lane_mask)
+{
+ u32 val = 0;
+ int lane = 0;
+
+ for_each_cx0_lane_in_mask(lane_mask, lane)
+ val |= XELPDP_LANE_PCLK_REFCLK_REQUEST(lane);
+
+ return val;
+}
+
+static u32 intel_cx0_get_pclk_refclk_ack(u8 lane_mask)
+{
+ u32 val = 0;
+ int lane = 0;
+
+ for_each_cx0_lane_in_mask(lane_mask, lane)
+ val |= XELPDP_LANE_PCLK_REFCLK_ACK(lane);
+
+ return val;
+}
+
+static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915,
+ struct intel_encoder *encoder,
+ bool lane_reversal)
+{
+ enum port port = encoder->port;
+ enum phy phy = intel_port_to_phy(i915, port);
+ bool both_lanes = intel_tc_port_fia_max_lane_count(enc_to_dig_port(encoder)) > 2;
+ u8 lane_mask = lane_reversal ? INTEL_CX0_LANE1 :
+ INTEL_CX0_LANE0;
+ u32 lane_pipe_reset = both_lanes ?
+ XELPDP_LANE_PIPE_RESET(0) |
+ XELPDP_LANE_PIPE_RESET(1) :
+ XELPDP_LANE_PIPE_RESET(0);
+ u32 lane_phy_current_status = both_lanes ?
+ XELPDP_LANE_PHY_CURRENT_STATUS(0) |
+ XELPDP_LANE_PHY_CURRENT_STATUS(1) :
+ XELPDP_LANE_PHY_CURRENT_STATUS(0);
+
+ if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL1(port),
+ XELPDP_PORT_BUF_SOC_PHY_READY,
+ XELPDP_PORT_BUF_SOC_PHY_READY,
+ XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US, 0, NULL))
+ drm_warn(&i915->drm, "PHY %c failed to bring out of SOC reset after %dus.\n",
+ phy_name(phy), XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US);
+
+ intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
+ XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1),
+ lane_pipe_reset);
+
+ if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL2(port),
+ lane_phy_current_status, lane_phy_current_status,
+ XELPDP_PORT_RESET_START_TIMEOUT_US, 0, NULL))
+ drm_warn(&i915->drm, "PHY %c failed to bring out of Lane reset after %dus.\n",
+ phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US);
+
+ intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(port),
+ intel_cx0_get_pclk_refclk_request(both_lanes ?
+ INTEL_CX0_BOTH_LANES :
+ INTEL_CX0_LANE0),
+ intel_cx0_get_pclk_refclk_request(lane_mask));
+
+ if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(port),
+ intel_cx0_get_pclk_refclk_ack(both_lanes ?
+ INTEL_CX0_BOTH_LANES :
+ INTEL_CX0_LANE0),
+ intel_cx0_get_pclk_refclk_ack(lane_mask),
+ XELPDP_REFCLK_ENABLE_TIMEOUT_US, 0, NULL))
+ drm_warn(&i915->drm, "PHY %c failed to request refclk after %dus.\n",
+ phy_name(phy), XELPDP_REFCLK_ENABLE_TIMEOUT_US);
+
+ intel_cx0_powerdown_change_sequence(i915, port, INTEL_CX0_BOTH_LANES,
+ CX0_P2_STATE_RESET);
+ intel_cx0_setup_powerdown(i915, port);
+
+ intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port), lane_pipe_reset, 0);
+
+ if (intel_de_wait_for_clear(i915, XELPDP_PORT_BUF_CTL2(port), lane_phy_current_status,
+ XELPDP_PORT_RESET_END_TIMEOUT))
+ drm_warn(&i915->drm, "PHY %c failed to bring out of Lane reset after %dms.\n",
+ phy_name(phy), XELPDP_PORT_RESET_END_TIMEOUT);
+}
+
+static void intel_cx0_program_phy_lane(struct drm_i915_private *i915,
+ struct intel_encoder *encoder, int lane_count,
+ bool lane_reversal)
+{
+ u8 l0t1, l0t2, l1t1, l1t2;
+ bool dp_alt_mode = intel_tc_port_in_dp_alt_mode(enc_to_dig_port(encoder));
+ enum port port = encoder->port;
+
+ if (intel_is_c10phy(i915, intel_port_to_phy(i915, port)))
+ intel_cx0_rmw(i915, port, INTEL_CX0_BOTH_LANES,
+ PHY_C10_VDR_CONTROL(1), 0,
+ C10_VDR_CTRL_MSGBUS_ACCESS,
+ MB_WRITE_COMMITTED);
+
+ /* TODO: DP-alt MFD case where only one PHY lane should be programmed. */
+ l0t1 = intel_cx0_read(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(1, 2));
+ l0t2 = intel_cx0_read(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(2, 2));
+ l1t1 = intel_cx0_read(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(1, 2));
+ l1t2 = intel_cx0_read(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(2, 2));
+
+ l0t1 |= CONTROL2_DISABLE_SINGLE_TX;
+ l0t2 |= CONTROL2_DISABLE_SINGLE_TX;
+ l1t1 |= CONTROL2_DISABLE_SINGLE_TX;
+ l1t2 |= CONTROL2_DISABLE_SINGLE_TX;
+
+ if (lane_reversal) {
+ switch (lane_count) {
+ case 4:
+ l0t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
+ fallthrough;
+ case 3:
+ l0t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
+ fallthrough;
+ case 2:
+ l1t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
+ fallthrough;
+ case 1:
+ l1t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
+ break;
+ default:
+ MISSING_CASE(lane_count);
+ }
+ } else {
+ switch (lane_count) {
+ case 4:
+ l1t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
+ fallthrough;
+ case 3:
+ l1t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
+ fallthrough;
+ case 2:
+ l0t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
+ l0t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
+ break;
+ case 1:
+ if (dp_alt_mode)
+ l0t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
+ else
+ l0t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
+ break;
+ default:
+ MISSING_CASE(lane_count);
+ }
+ }
+
+ /* disable MLs */
+ intel_cx0_write(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(1, 2),
+ l0t1, MB_WRITE_COMMITTED);
+ intel_cx0_write(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(2, 2),
+ l0t2, MB_WRITE_COMMITTED);
+ intel_cx0_write(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(1, 2),
+ l1t1, MB_WRITE_COMMITTED);
+ intel_cx0_write(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(2, 2),
+ l1t2, MB_WRITE_COMMITTED);
+
+ if (intel_is_c10phy(i915, intel_port_to_phy(i915, port)))
+ intel_cx0_rmw(i915, port, INTEL_CX0_BOTH_LANES,
+ PHY_C10_VDR_CONTROL(1), 0,
+ C10_VDR_CTRL_UPDATE_CFG,
+ MB_WRITE_COMMITTED);
+}
+
+static u32 intel_cx0_get_pclk_pll_request(u8 lane_mask)
+{
+ u32 val = 0;
+ int lane = 0;
+
+ for_each_cx0_lane_in_mask(lane_mask, lane)
+ val |= XELPDP_LANE_PCLK_PLL_REQUEST(lane);
+
+ return val;
+}
+
+static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
+{
+ u32 val = 0;
+ int lane = 0;
+
+ for_each_cx0_lane_in_mask(lane_mask, lane)
+ val |= XELPDP_LANE_PCLK_PLL_ACK(lane);
+
+ return val;
+}
+
+static void intel_cx0pll_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+ bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
+ u8 maxpclk_lane = lane_reversal ? INTEL_CX0_LANE1 :
+ INTEL_CX0_LANE0;
+ intel_wakeref_t wakeref = intel_cx0_phy_transaction_begin(encoder);
+
+ /*
+ * 1. Program PORT_CLOCK_CTL REGISTER to configure
+ * clock muxes, gating and SSC
+ */
+ intel_program_port_clock_ctl(encoder, crtc_state, lane_reversal);
+
+ /* 2. Bring PHY out of reset. */
+ intel_cx0_phy_lane_reset(i915, encoder, lane_reversal);
+
+ /*
+ * 3. Change Phy power state to Ready.
+ * TODO: For DP alt mode use only one lane.
+ */
+ intel_cx0_powerdown_change_sequence(i915, encoder->port, INTEL_CX0_BOTH_LANES,
+ CX0_P2_STATE_READY);
+
+ /* 4. Program PHY internal PLL internal registers. */
+ if (intel_is_c10phy(i915, phy))
+ intel_c10_pll_program(i915, crtc_state, encoder);
+ else
+ intel_c20_pll_program(i915, crtc_state, encoder);
+
+ /*
+ * 5. Program the enabled and disabled owned PHY lane
+ * transmitters over message bus
+ */
+ intel_cx0_program_phy_lane(i915, encoder, crtc_state->lane_count, lane_reversal);
+
+ /*
+ * 6. Follow the Display Voltage Frequency Switching - Sequence
+ * Before Frequency Change. We handle this step in bxt_set_cdclk().
+ */
+
+ /*
+ * 7. Program DDI_CLK_VALFREQ to match intended DDI
+ * clock frequency.
+ */
+ intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port),
+ crtc_state->port_clock);
+
+ /*
+ * 8. Set PORT_CLOCK_CTL register PCLK PLL Request
+ * LN<Lane for maxPCLK> to "1" to enable PLL.
+ */
+ intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+ intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES),
+ intel_cx0_get_pclk_pll_request(maxpclk_lane));
+
+ /* 9. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK> == "1". */
+ if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+ intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES),
+ intel_cx0_get_pclk_pll_ack(maxpclk_lane),
+ XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US, 0, NULL))
+ drm_warn(&i915->drm, "Port %c PLL not locked after %dus.\n",
+ phy_name(phy), XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US);
+
+ /*
+ * 10. Follow the Display Voltage Frequency Switching Sequence After
+ * Frequency Change. We handle this step in bxt_set_cdclk().
+ */
+
+ /* TODO: enable TBT-ALT mode */
+ intel_cx0_phy_transaction_end(encoder, wakeref);
+}
+
+int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ u32 clock;
+ u32 val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+
+ clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
+
+ drm_WARN_ON(&i915->drm, !(val & XELPDP_FORWARD_CLOCK_UNGATE));
+ drm_WARN_ON(&i915->drm, !(val & XELPDP_TBT_CLOCK_REQUEST));
+ drm_WARN_ON(&i915->drm, !(val & XELPDP_TBT_CLOCK_ACK));
+
+ switch (clock) {
+ case XELPDP_DDI_CLOCK_SELECT_TBT_162:
+ return 162000;
+ case XELPDP_DDI_CLOCK_SELECT_TBT_270:
+ return 270000;
+ case XELPDP_DDI_CLOCK_SELECT_TBT_540:
+ return 540000;
+ case XELPDP_DDI_CLOCK_SELECT_TBT_810:
+ return 810000;
+ default:
+ MISSING_CASE(clock);
+ return 162000;
+ }
+}
+
+static int intel_mtl_tbt_clock_select(struct drm_i915_private *i915, int clock)
+{
+ switch (clock) {
+ case 162000:
+ return XELPDP_DDI_CLOCK_SELECT_TBT_162;
+ case 270000:
+ return XELPDP_DDI_CLOCK_SELECT_TBT_270;
+ case 540000:
+ return XELPDP_DDI_CLOCK_SELECT_TBT_540;
+ case 810000:
+ return XELPDP_DDI_CLOCK_SELECT_TBT_810;
+ default:
+ MISSING_CASE(clock);
+ return XELPDP_DDI_CLOCK_SELECT_TBT_162;
+ }
+}
+
+static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
+ u32 val = 0;
+
+ /*
+ * 1. Program PORT_CLOCK_CTL REGISTER to configure
+ * clock muxes, gating and SSC
+ */
+ val |= XELPDP_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(i915, crtc_state->port_clock));
+ val |= XELPDP_FORWARD_CLOCK_UNGATE;
+ intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+ XELPDP_DDI_CLOCK_SELECT_MASK | XELPDP_FORWARD_CLOCK_UNGATE, val);
+
+ /* 2. Read back PORT_CLOCK_CTL REGISTER */
+ val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+
+ /*
+ * 3. Follow the Display Voltage Frequency Switching - Sequence
+ * Before Frequency Change. We handle this step in bxt_set_cdclk().
+ */
+
+ /*
+ * 4. Set PORT_CLOCK_CTL register TBT CLOCK Request to "1" to enable PLL.
+ */
+ val |= XELPDP_TBT_CLOCK_REQUEST;
+ intel_de_write(i915, XELPDP_PORT_CLOCK_CTL(encoder->port), val);
+
+ /* 5. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "1". */
+ if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+ XELPDP_TBT_CLOCK_ACK,
+ XELPDP_TBT_CLOCK_ACK,
+ 100, 0, NULL))
+ drm_warn(&i915->drm, "[ENCODER:%d:%s][%c] PHY PLL not locked after 100us.\n",
+ encoder->base.base.id, encoder->base.name, phy_name(phy));
+
+ /*
+ * 6. Follow the Display Voltage Frequency Switching Sequence After
+ * Frequency Change. We handle this step in bxt_set_cdclk().
+ */
+
+ /*
+ * 7. Program DDI_CLK_VALFREQ to match intended DDI
+ * clock frequency.
+ */
+ intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port),
+ crtc_state->port_clock);
+}
+
+void intel_mtl_pll_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+ if (intel_tc_port_in_tbt_alt_mode(dig_port))
+ intel_mtl_tbt_pll_enable(encoder, crtc_state);
+ else
+ intel_cx0pll_enable(encoder, crtc_state);
+}
+
+static void intel_cx0pll_disable(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
+ bool is_c10 = intel_is_c10phy(i915, phy);
+ intel_wakeref_t wakeref = intel_cx0_phy_transaction_begin(encoder);
+
+ /* 1. Change owned PHY lane power to Disable state. */
+ intel_cx0_powerdown_change_sequence(i915, encoder->port, INTEL_CX0_BOTH_LANES,
+ is_c10 ? CX0_P2PG_STATE_DISABLE :
+ CX0_P4PG_STATE_DISABLE);
+
+ /*
+ * 2. Follow the Display Voltage Frequency Switching Sequence Before
+ * Frequency Change. We handle this step in bxt_set_cdclk().
+ */
+
+ /*
+ * 3. Set PORT_CLOCK_CTL register PCLK PLL Request LN<Lane for maxPCLK>
+ * to "0" to disable PLL.
+ */
+ intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+ intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES) |
+ intel_cx0_get_pclk_refclk_request(INTEL_CX0_BOTH_LANES), 0);
+
+ /* 4. Program DDI_CLK_VALFREQ to 0. */
+ intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port), 0);
+
+ /*
+ * 5. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK**> == "0".
+ */
+ if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+ intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES) |
+ intel_cx0_get_pclk_refclk_ack(INTEL_CX0_BOTH_LANES), 0,
+ XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US, 0, NULL))
+ drm_warn(&i915->drm, "Port %c PLL not unlocked after %dus.\n",
+ phy_name(phy), XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US);
+
+ /*
+ * 6. Follow the Display Voltage Frequency Switching Sequence After
+ * Frequency Change. We handle this step in bxt_set_cdclk().
+ */
+
+ /* 7. Program PORT_CLOCK_CTL register to disable and gate clocks. */
+ intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+ XELPDP_DDI_CLOCK_SELECT_MASK, 0);
+ intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+ XELPDP_FORWARD_CLOCK_UNGATE, 0);
+
+ intel_cx0_phy_transaction_end(encoder, wakeref);
+}
+
+static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
+
+ /*
+ * 1. Follow the Display Voltage Frequency Switching Sequence Before
+ * Frequency Change. We handle this step in bxt_set_cdclk().
+ */
+
+ /*
+ * 2. Set PORT_CLOCK_CTL register TBT CLOCK Request to "0" to disable PLL.
+ */
+ intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+ XELPDP_TBT_CLOCK_REQUEST, 0);
+
+ /* 3. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "0". */
+ if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+ XELPDP_TBT_CLOCK_ACK, 0, 10, 0, NULL))
+ drm_warn(&i915->drm, "[ENCODER:%d:%s][%c] PHY PLL not unlocked after 10us.\n",
+ encoder->base.base.id, encoder->base.name, phy_name(phy));
+
+ /*
+ * 4. Follow the Display Voltage Frequency Switching Sequence After
+ * Frequency Change. We handle this step in bxt_set_cdclk().
+ */
+
+ /*
+ * 5. Program PORT CLOCK CTRL register to disable and gate clocks
+ */
+ intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+ XELPDP_DDI_CLOCK_SELECT_MASK |
+ XELPDP_FORWARD_CLOCK_UNGATE, 0);
+
+ /* 6. Program DDI_CLK_VALFREQ to 0. */
+ intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port), 0);
+}
+
+void intel_mtl_pll_disable(struct intel_encoder *encoder)
+{
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+ if (intel_tc_port_in_tbt_alt_mode(dig_port))
+ intel_mtl_tbt_pll_disable(encoder);
+ else
+ intel_cx0pll_disable(encoder);
+}
+
+enum icl_port_dpll_id
+intel_mtl_port_pll_type(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ /*
+ * TODO: Determine the PLL type from the SW state, once MTL PLL
+ * handling is done via the standard shared DPLL framework.
+ */
+ u32 val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+ u32 clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
+
+ if (clock == XELPDP_DDI_CLOCK_SELECT_MAXPCLK ||
+ clock == XELPDP_DDI_CLOCK_SELECT_DIV18CLK)
+ return ICL_PORT_DPLL_MG_PHY;
+ else
+ return ICL_PORT_DPLL_DEFAULT;
+}
+
+void intel_c10pll_state_verify(struct intel_atomic_state *state,
+ struct intel_crtc_state *new_crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_c10pll_state mpllb_hw_state = { 0 };
+ struct intel_c10pll_state *mpllb_sw_state = &new_crtc_state->cx0pll_state.c10;
+ struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
+ struct intel_encoder *encoder;
+ enum phy phy;
+ int i;
+
+ if (DISPLAY_VER(i915) < 14)
+ return;
+
+ if (!new_crtc_state->hw.active)
+ return;
+
+ /* intel_get_crtc_new_encoder() only works for modeset/fastset commits */
+ if (!intel_crtc_needs_modeset(new_crtc_state) &&
+ !intel_crtc_needs_fastset(new_crtc_state))
+ return;
+
+ encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
+ phy = intel_port_to_phy(i915, encoder->port);
+
+ if (!intel_is_c10phy(i915, phy))
+ return;
+
+ intel_c10pll_readout_hw_state(encoder, &mpllb_hw_state);
+
+ for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) {
+ u8 expected = mpllb_sw_state->pll[i];
+
+ I915_STATE_WARN(i915, mpllb_hw_state.pll[i] != expected,
+ "[CRTC:%d:%s] mismatch in C10MPLLB: Register[%d] (expected 0x%02x, found 0x%02x)",
+ crtc->base.base.id, crtc->base.name, i,
+ expected, mpllb_hw_state.pll[i]);
+ }
+
+ I915_STATE_WARN(i915, mpllb_hw_state.tx != mpllb_sw_state->tx,
+ "[CRTC:%d:%s] mismatch in C10MPLLB: Register TX0 (expected 0x%02x, found 0x%02x)",
+ crtc->base.base.id, crtc->base.name,
+ mpllb_sw_state->tx, mpllb_hw_state.tx);
+
+ I915_STATE_WARN(i915, mpllb_hw_state.cmn != mpllb_sw_state->cmn,
+ "[CRTC:%d:%s] mismatch in C10MPLLB: Register CMN0 (expected 0x%02x, found 0x%02x)",
+ crtc->base.base.id, crtc->base.name,
+ mpllb_sw_state->cmn, mpllb_hw_state.cmn);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
new file mode 100644
index 000000000000..f99809af257d
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_CX0_PHY_H__
+#define __INTEL_CX0_PHY_H__
+
+#include <linux/types.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+
+#include "i915_drv.h"
+#include "intel_display_types.h"
+
+struct drm_i915_private;
+struct intel_encoder;
+struct intel_crtc_state;
+enum icl_port_dpll_id;
+enum phy;
+
+bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy);
+void intel_mtl_pll_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state);
+void intel_mtl_pll_disable(struct intel_encoder *encoder);
+enum icl_port_dpll_id
+intel_mtl_port_pll_type(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state);
+void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, struct intel_c10pll_state *pll_state);
+int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder);
+void intel_c10pll_dump_hw_state(struct drm_i915_private *dev_priv,
+ const struct intel_c10pll_state *hw_state);
+int intel_c10pll_calc_port_clock(struct intel_encoder *encoder,
+ const struct intel_c10pll_state *pll_state);
+void intel_c10pll_state_verify(struct intel_atomic_state *state,
+ struct intel_crtc_state *new_crtc_state);
+void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
+ struct intel_c20pll_state *pll_state);
+void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
+ const struct intel_c20pll_state *hw_state);
+int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
+ const struct intel_c20pll_state *pll_state);
+void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state);
+int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock);
+void intel_cx0_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ u32 level);
+int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
+#endif /* __INTEL_CX0_PHY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
new file mode 100644
index 000000000000..cb5d1be2ba19
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -0,0 +1,274 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_CX0_PHY_REGS_H__
+#define __INTEL_CX0_PHY_REGS_H__
+
+#include "i915_reg_defs.h"
+
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A 0x64040
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B 0x64140
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1 0x16F240
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2 0x16F440
+#define XELPDP_PORT_M2P_MSGBUS_CTL(port, lane) _MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+ _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A, \
+ _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B, \
+ _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1, \
+ _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2) + (lane) * 4)
+#define XELPDP_PORT_M2P_TRANSACTION_PENDING REG_BIT(31)
+#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
+#define XELPDP_PORT_M2P_COMMAND_WRITE_UNCOMMITTED REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x1)
+#define XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x2)
+#define XELPDP_PORT_M2P_COMMAND_READ REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x3)
+#define XELPDP_PORT_M2P_DATA_MASK REG_GENMASK(23, 16)
+#define XELPDP_PORT_M2P_DATA(val) REG_FIELD_PREP(XELPDP_PORT_M2P_DATA_MASK, val)
+#define XELPDP_PORT_M2P_TRANSACTION_RESET REG_BIT(15)
+#define XELPDP_PORT_M2P_ADDRESS_MASK REG_GENMASK(11, 0)
+#define XELPDP_PORT_M2P_ADDRESS(val) REG_FIELD_PREP(XELPDP_PORT_M2P_ADDRESS_MASK, val)
+#define XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane) _MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+ _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A, \
+ _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B, \
+ _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1, \
+ _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2) + (lane) * 4 + 8)
+#define XELPDP_PORT_P2M_RESPONSE_READY REG_BIT(31)
+#define XELPDP_PORT_P2M_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
+#define XELPDP_PORT_P2M_COMMAND_READ_ACK 0x4
+#define XELPDP_PORT_P2M_COMMAND_WRITE_ACK 0x5
+#define XELPDP_PORT_P2M_DATA_MASK REG_GENMASK(23, 16)
+#define XELPDP_PORT_P2M_DATA(val) REG_FIELD_PREP(XELPDP_PORT_P2M_DATA_MASK, val)
+#define XELPDP_PORT_P2M_ERROR_SET REG_BIT(15)
+
+#define XELPDP_MSGBUS_TIMEOUT_SLOW 1
+#define XELPDP_MSGBUS_TIMEOUT_FAST_US 2
+#define XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US 3200
+#define XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US 20
+#define XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US 100
+#define XELPDP_PORT_RESET_START_TIMEOUT_US 5
+#define XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US 100
+#define XELPDP_PORT_RESET_END_TIMEOUT 15
+#define XELPDP_REFCLK_ENABLE_TIMEOUT_US 1
+
+#define _XELPDP_PORT_BUF_CTL1_LN0_A 0x64004
+#define _XELPDP_PORT_BUF_CTL1_LN0_B 0x64104
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC1 0x16F200
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC2 0x16F400
+#define XELPDP_PORT_BUF_CTL1(port) _MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+ _XELPDP_PORT_BUF_CTL1_LN0_A, \
+ _XELPDP_PORT_BUF_CTL1_LN0_B, \
+ _XELPDP_PORT_BUF_CTL1_LN0_USBC1, \
+ _XELPDP_PORT_BUF_CTL1_LN0_USBC2))
+#define XELPDP_PORT_BUF_D2D_LINK_ENABLE REG_BIT(29)
+#define XELPDP_PORT_BUF_D2D_LINK_STATE REG_BIT(28)
+#define XELPDP_PORT_BUF_SOC_PHY_READY REG_BIT(24)
+#define XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK REG_GENMASK(19, 18)
+#define XELPDP_PORT_BUF_PORT_DATA_10BIT REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 0)
+#define XELPDP_PORT_BUF_PORT_DATA_20BIT REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 1)
+#define XELPDP_PORT_BUF_PORT_DATA_40BIT REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 2)
+#define XELPDP_PORT_REVERSAL REG_BIT(16)
+#define XELPDP_PORT_BUF_IO_SELECT_TBT REG_BIT(11)
+#define XELPDP_PORT_BUF_PHY_IDLE REG_BIT(7)
+#define XELPDP_TC_PHY_OWNERSHIP REG_BIT(6)
+#define XELPDP_TCSS_POWER_REQUEST REG_BIT(5)
+#define XELPDP_TCSS_POWER_STATE REG_BIT(4)
+#define XELPDP_PORT_WIDTH_MASK REG_GENMASK(3, 1)
+#define XELPDP_PORT_WIDTH(val) REG_FIELD_PREP(XELPDP_PORT_WIDTH_MASK, val)
+
+#define XELPDP_PORT_BUF_CTL2(port) _MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+ _XELPDP_PORT_BUF_CTL1_LN0_A, \
+ _XELPDP_PORT_BUF_CTL1_LN0_B, \
+ _XELPDP_PORT_BUF_CTL1_LN0_USBC1, \
+ _XELPDP_PORT_BUF_CTL1_LN0_USBC2) + 4)
+
+#define XELPDP_LANE_PIPE_RESET(lane) _PICK(lane, REG_BIT(31), REG_BIT(30))
+#define XELPDP_LANE_PHY_CURRENT_STATUS(lane) _PICK(lane, REG_BIT(29), REG_BIT(28))
+#define XELPDP_LANE_POWERDOWN_UPDATE(lane) _PICK(lane, REG_BIT(25), REG_BIT(24))
+#define _XELPDP_LANE0_POWERDOWN_NEW_STATE_MASK REG_GENMASK(23, 20)
+#define _XELPDP_LANE0_POWERDOWN_NEW_STATE(val) REG_FIELD_PREP(_XELPDP_LANE0_POWERDOWN_NEW_STATE_MASK, val)
+#define _XELPDP_LANE1_POWERDOWN_NEW_STATE_MASK REG_GENMASK(19, 16)
+#define _XELPDP_LANE1_POWERDOWN_NEW_STATE(val) REG_FIELD_PREP(_XELPDP_LANE1_POWERDOWN_NEW_STATE_MASK, val)
+#define XELPDP_LANE_POWERDOWN_NEW_STATE(lane, val) _PICK(lane, \
+ _XELPDP_LANE0_POWERDOWN_NEW_STATE(val), \
+ _XELPDP_LANE1_POWERDOWN_NEW_STATE(val))
+#define XELPDP_LANE_POWERDOWN_NEW_STATE_MASK REG_GENMASK(3, 0)
+#define XELPDP_POWER_STATE_READY_MASK REG_GENMASK(7, 4)
+#define XELPDP_POWER_STATE_READY(val) REG_FIELD_PREP(XELPDP_POWER_STATE_READY_MASK, val)
+
+#define XELPDP_PORT_BUF_CTL3(port) _MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+ _XELPDP_PORT_BUF_CTL1_LN0_A, \
+ _XELPDP_PORT_BUF_CTL1_LN0_B, \
+ _XELPDP_PORT_BUF_CTL1_LN0_USBC1, \
+ _XELPDP_PORT_BUF_CTL1_LN0_USBC2) + 8)
+#define XELPDP_PLL_LANE_STAGGERING_DELAY_MASK REG_GENMASK(15, 8)
+#define XELPDP_PLL_LANE_STAGGERING_DELAY(val) REG_FIELD_PREP(XELPDP_PLL_LANE_STAGGERING_DELAY_MASK, val)
+#define XELPDP_POWER_STATE_ACTIVE_MASK REG_GENMASK(3, 0)
+#define XELPDP_POWER_STATE_ACTIVE(val) REG_FIELD_PREP(XELPDP_POWER_STATE_ACTIVE_MASK, val)
+#define CX0_P0_STATE_ACTIVE 0x0
+#define CX0_P2_STATE_READY 0x2
+#define CX0_P2PG_STATE_DISABLE 0x9
+#define CX0_P4PG_STATE_DISABLE 0xC
+#define CX0_P2_STATE_RESET 0x2
+
+#define _XELPDP_PORT_CLOCK_CTL_A 0x640E0
+#define _XELPDP_PORT_CLOCK_CTL_B 0x641E0
+#define _XELPDP_PORT_CLOCK_CTL_USBC1 0x16F260
+#define _XELPDP_PORT_CLOCK_CTL_USBC2 0x16F460
+#define XELPDP_PORT_CLOCK_CTL(port) _MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+ _XELPDP_PORT_CLOCK_CTL_A, \
+ _XELPDP_PORT_CLOCK_CTL_B, \
+ _XELPDP_PORT_CLOCK_CTL_USBC1, \
+ _XELPDP_PORT_CLOCK_CTL_USBC2))
+#define XELPDP_LANE_PCLK_PLL_REQUEST(lane) REG_BIT(31 - ((lane) * 4))
+#define XELPDP_LANE_PCLK_PLL_ACK(lane) REG_BIT(30 - ((lane) * 4))
+#define XELPDP_LANE_PCLK_REFCLK_REQUEST(lane) REG_BIT(29 - ((lane) * 4))
+#define XELPDP_LANE_PCLK_REFCLK_ACK(lane) REG_BIT(28 - ((lane) * 4))
+
+#define XELPDP_TBT_CLOCK_REQUEST REG_BIT(19)
+#define XELPDP_TBT_CLOCK_ACK REG_BIT(18)
+#define XELPDP_DDI_CLOCK_SELECT_MASK REG_GENMASK(15, 12)
+#define XELPDP_DDI_CLOCK_SELECT(val) REG_FIELD_PREP(XELPDP_DDI_CLOCK_SELECT_MASK, val)
+#define XELPDP_DDI_CLOCK_SELECT_NONE 0x0
+#define XELPDP_DDI_CLOCK_SELECT_MAXPCLK 0x8
+#define XELPDP_DDI_CLOCK_SELECT_DIV18CLK 0x9
+#define XELPDP_DDI_CLOCK_SELECT_TBT_162 0xc
+#define XELPDP_DDI_CLOCK_SELECT_TBT_270 0xd
+#define XELPDP_DDI_CLOCK_SELECT_TBT_540 0xe
+#define XELPDP_DDI_CLOCK_SELECT_TBT_810 0xf
+#define XELPDP_FORWARD_CLOCK_UNGATE REG_BIT(10)
+#define XELPDP_LANE1_PHY_CLOCK_SELECT REG_BIT(8)
+#define XELPDP_SSC_ENABLE_PLLA REG_BIT(1)
+#define XELPDP_SSC_ENABLE_PLLB REG_BIT(0)
+
+/* C10 Vendor Registers */
+#define PHY_C10_VDR_PLL(idx) (0xC00 + (idx))
+#define C10_PLL0_FRACEN REG_BIT8(4)
+#define C10_PLL3_MULTIPLIERH_MASK REG_GENMASK8(3, 0)
+#define C10_PLL15_TXCLKDIV_MASK REG_GENMASK8(2, 0)
+#define C10_PLL15_HDMIDIV_MASK REG_GENMASK8(5, 3)
+
+#define PHY_C10_VDR_CMN(idx) (0xC20 + (idx))
+#define C10_CMN0_REF_RANGE REG_FIELD_PREP(REG_GENMASK(4, 0), 1)
+#define C10_CMN0_REF_CLK_MPLLB_DIV REG_FIELD_PREP(REG_GENMASK(7, 5), 1)
+#define C10_CMN3_TXVBOOST_MASK REG_GENMASK8(7, 5)
+#define C10_CMN3_TXVBOOST(val) REG_FIELD_PREP8(C10_CMN3_TXVBOOST_MASK, val)
+#define PHY_C10_VDR_TX(idx) (0xC30 + (idx))
+#define C10_TX0_TX_MPLLB_SEL REG_BIT(4)
+#define C10_TX1_TERMCTL_MASK REG_GENMASK8(7, 5)
+#define C10_TX1_TERMCTL(val) REG_FIELD_PREP8(C10_TX1_TERMCTL_MASK, val)
+#define PHY_C10_VDR_CONTROL(idx) (0xC70 + (idx) - 1)
+#define C10_VDR_CTRL_MSGBUS_ACCESS REG_BIT8(2)
+#define C10_VDR_CTRL_MASTER_LANE REG_BIT8(1)
+#define C10_VDR_CTRL_UPDATE_CFG REG_BIT8(0)
+#define PHY_C10_VDR_CUSTOM_WIDTH 0xD02
+#define C10_VDR_CUSTOM_WIDTH_MASK REG_GENMASK(1, 0)
+#define C10_VDR_CUSTOM_WIDTH_8_10 REG_FIELD_PREP(C10_VDR_CUSTOM_WIDTH_MASK, 0)
+#define PHY_C10_VDR_OVRD 0xD71
+#define PHY_C10_VDR_OVRD_TX1 REG_BIT8(0)
+#define PHY_C10_VDR_OVRD_TX2 REG_BIT8(2)
+#define PHY_C10_VDR_PRE_OVRD_TX1 0xD80
+#define C10_PHY_OVRD_LEVEL_MASK REG_GENMASK8(5, 0)
+#define C10_PHY_OVRD_LEVEL(val) REG_FIELD_PREP8(C10_PHY_OVRD_LEVEL_MASK, val)
+#define PHY_CX0_VDROVRD_CTL(lane, tx, control) \
+ (PHY_C10_VDR_PRE_OVRD_TX1 + \
+ ((lane) ^ (tx)) * 0x10 + (control))
+
+/* PIPE SPEC Defined Registers */
+#define PHY_CX0_TX_CONTROL(tx, control) (0x400 + ((tx) - 1) * 0x200 + (control))
+#define CONTROL2_DISABLE_SINGLE_TX REG_BIT(6)
+
+/* C20 Registers */
+#define PHY_C20_WR_ADDRESS_L 0xC02
+#define PHY_C20_WR_ADDRESS_H 0xC03
+#define PHY_C20_WR_DATA_L 0xC04
+#define PHY_C20_WR_DATA_H 0xC05
+#define PHY_C20_RD_ADDRESS_L 0xC06
+#define PHY_C20_RD_ADDRESS_H 0xC07
+#define PHY_C20_RD_DATA_L 0xC08
+#define PHY_C20_RD_DATA_H 0xC09
+#define PHY_C20_VDR_CUSTOM_SERDES_RATE 0xD00
+#define PHY_C20_VDR_HDMI_RATE 0xD01
+#define PHY_C20_CONTEXT_TOGGLE REG_BIT8(0)
+#define PHY_C20_CUSTOM_SERDES_MASK REG_GENMASK8(4, 1)
+#define PHY_C20_CUSTOM_SERDES(val) REG_FIELD_PREP8(PHY_C20_CUSTOM_SERDES_MASK, val)
+#define PHY_C20_VDR_CUSTOM_WIDTH 0xD02
+#define PHY_C20_CUSTOM_WIDTH_MASK REG_GENMASK(1, 0)
+#define PHY_C20_CUSTOM_WIDTH(val) REG_FIELD_PREP8(PHY_C20_CUSTOM_WIDTH_MASK, val)
+#define PHY_C20_A_TX_CNTX_CFG(idx) (0xCF2E - (idx))
+#define PHY_C20_B_TX_CNTX_CFG(idx) (0xCF2A - (idx))
+#define C20_PHY_TX_RATE REG_GENMASK(2, 0)
+#define PHY_C20_A_CMN_CNTX_CFG(idx) (0xCDAA - (idx))
+#define PHY_C20_B_CMN_CNTX_CFG(idx) (0xCDA5 - (idx))
+#define PHY_C20_A_MPLLA_CNTX_CFG(idx) (0xCCF0 - (idx))
+#define PHY_C20_B_MPLLA_CNTX_CFG(idx) (0xCCE5 - (idx))
+#define C20_MPLLA_FRACEN REG_BIT(14)
+#define C20_FB_CLK_DIV4_EN REG_BIT(13)
+#define C20_MPLLA_TX_CLK_DIV_MASK REG_GENMASK(10, 8)
+#define PHY_C20_A_MPLLB_CNTX_CFG(idx) (0xCB5A - (idx))
+#define PHY_C20_B_MPLLB_CNTX_CFG(idx) (0xCB4E - (idx))
+#define C20_MPLLB_TX_CLK_DIV_MASK REG_GENMASK(15, 13)
+#define C20_MPLLB_FRACEN REG_BIT(13)
+#define C20_REF_CLK_MPLLB_DIV_MASK REG_GENMASK(12, 10)
+#define C20_MULTIPLIER_MASK REG_GENMASK(11, 0)
+#define C20_PHY_USE_MPLLB REG_BIT(7)
+
+/* C20 Phy VSwing Masks */
+#define C20_PHY_VSWING_PREEMPH_MASK REG_GENMASK8(5, 0)
+#define C20_PHY_VSWING_PREEMPH(val) REG_FIELD_PREP8(C20_PHY_VSWING_PREEMPH_MASK, val)
+
+#define RAWLANEAONX_DIG_TX_MPLLB_CAL_DONE_BANK(idx) (0x303D + (idx))
+
+/* C20 HDMI computed pll definitions */
+#define REFCLK_38_4_MHZ 38400000
+#define CLOCK_4999MHZ 4999999999
+#define CLOCK_9999MHZ 9999999999
+#define DATARATE_3000000000 3000000000
+#define DATARATE_3500000000 3500000000
+#define DATARATE_4000000000 4000000000
+#define MPLL_FRACN_DEN 0xFFFF
+
+#define SSC_UP_SPREAD REG_BIT16(9)
+#define WORD_CLK_DIV REG_BIT16(8)
+
+#define MPLL_TX_CLK_DIV(val) REG_FIELD_PREP16(C20_MPLLB_TX_CLK_DIV_MASK, val)
+#define MPLL_MULTIPLIER(val) REG_FIELD_PREP16(C20_MULTIPLIER_MASK, val)
+
+#define MPLLB_ANA_FREQ_VCO_0 0
+#define MPLLB_ANA_FREQ_VCO_1 1
+#define MPLLB_ANA_FREQ_VCO_2 2
+#define MPLLB_ANA_FREQ_VCO_3 3
+#define MPLLB_ANA_FREQ_VCO_MASK REG_GENMASK16(15, 14)
+#define MPLLB_ANA_FREQ_VCO(val) REG_FIELD_PREP16(MPLLB_ANA_FREQ_VCO_MASK, val)
+
+#define MPLL_DIV_MULTIPLIER_MASK REG_GENMASK16(7, 0)
+#define MPLL_DIV_MULTIPLIER(val) REG_FIELD_PREP16(MPLL_DIV_MULTIPLIER_MASK, val)
+
+#define CAL_DAC_CODE_31 31
+#define CAL_DAC_CODE_MASK REG_GENMASK16(14, 10)
+#define CAL_DAC_CODE(val) REG_FIELD_PREP16(CAL_DAC_CODE_MASK, val)
+
+#define CP_INT_GS_28 28
+#define CP_INT_GS_MASK REG_GENMASK16(6, 0)
+#define CP_INT_GS(val) REG_FIELD_PREP16(CP_INT_GS_MASK, val)
+
+#define CP_PROP_GS_30 30
+#define CP_PROP_GS_MASK REG_GENMASK16(13, 7)
+#define CP_PROP_GS(val) REG_FIELD_PREP16(CP_PROP_GS_MASK, val)
+
+#define CP_INT_6 6
+#define CP_INT_MASK REG_GENMASK16(6, 0)
+#define CP_INT(val) REG_FIELD_PREP16(CP_INT_MASK, val)
+
+#define CP_PROP_20 20
+#define CP_PROP_MASK REG_GENMASK16(13, 7)
+#define CP_PROP(val) REG_FIELD_PREP16(CP_PROP_MASK, val)
+
+#define V2I_2 2
+#define V2I_MASK REG_GENMASK16(15, 14)
+#define V2I(val) REG_FIELD_PREP16(V2I_MASK, val)
+
+#define HDMI_DIV_1 1
+#define HDMI_DIV_MASK REG_GENMASK16(2, 0)
+#define HDMI_DIV(val) REG_FIELD_PREP16(HDMI_DIV_MASK, val)
+
+#endif /* __INTEL_CX0_REG_DEFS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 3a7b98837516..090f242e610c 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -39,6 +39,8 @@
#include "intel_combo_phy_regs.h"
#include "intel_connector.h"
#include "intel_crtc.h"
+#include "intel_cx0_phy.h"
+#include "intel_cx0_phy_regs.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
@@ -61,6 +63,7 @@
#include "intel_hti.h"
#include "intel_lspcon.h"
#include "intel_mg_phy_regs.h"
+#include "intel_modeset_lock.h"
#include "intel_pps.h"
#include "intel_psr.h"
#include "intel_quirks.h"
@@ -68,7 +71,6 @@
#include "intel_tc.h"
#include "intel_vdsc.h"
#include "intel_vdsc_regs.h"
-#include "intel_vrr.h"
#include "skl_scaler.h"
#include "skl_universal_plane.h"
@@ -169,6 +171,18 @@ static void hsw_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
trans->entries[level].hsw.trans2);
}
+static void mtl_wait_ddi_buf_idle(struct drm_i915_private *i915, enum port port)
+{
+ int ret;
+
+ /* FIXME: find out why Bspec's 100us timeout is too short */
+ ret = wait_for_us((intel_de_read(i915, XELPDP_PORT_BUF_CTL1(port)) &
+ XELPDP_PORT_BUF_PHY_IDLE), 10000);
+ if (ret)
+ drm_err(&i915->drm, "Timeout waiting for DDI BUF %c to get idle\n",
+ port_name(port));
+}
+
void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
enum port port)
{
@@ -196,7 +210,9 @@ static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv,
return;
}
- if (IS_DG2(dev_priv)) {
+ if (DISPLAY_VER(dev_priv) >= 14) {
+ timeout_us = 10000;
+ } else if (IS_DG2(dev_priv)) {
timeout_us = 1200;
} else if (DISPLAY_VER(dev_priv) >= 12) {
if (intel_phy_is_tc(dev_priv, phy))
@@ -207,8 +223,12 @@ static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv,
timeout_us = 500;
}
- ret = _wait_for(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
- DDI_BUF_IS_IDLE), timeout_us, 10, 10);
+ if (DISPLAY_VER(dev_priv) >= 14)
+ ret = _wait_for(!(intel_de_read(dev_priv, XELPDP_PORT_BUF_CTL1(port)) & XELPDP_PORT_BUF_PHY_IDLE),
+ timeout_us, 10, 10);
+ else
+ ret = _wait_for(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) & DDI_BUF_IS_IDLE),
+ timeout_us, 10, 10);
if (ret)
drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get active\n",
@@ -313,6 +333,13 @@ static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder,
DDI_PORT_WIDTH(crtc_state->lane_count) |
DDI_BUF_TRANS_SELECT(0);
+ if (DISPLAY_VER(i915) >= 14) {
+ if (intel_dp_is_uhbr(crtc_state))
+ intel_dp->DP |= DDI_BUF_PORT_DATA_40BIT;
+ else
+ intel_dp->DP |= DDI_BUF_PORT_DATA_10BIT;
+ }
+
if (IS_ALDERLAKE_P(i915) && intel_phy_is_tc(i915, phy)) {
intel_dp->DP |= ddi_buf_phy_link_rate(crtc_state->port_clock);
if (!intel_tc_port_in_tbt_alt_mode(dig_port))
@@ -515,6 +542,8 @@ intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder,
temp |= TRANS_DDI_HDMI_SCRAMBLING;
if (crtc_state->hdmi_high_tmds_clock_ratio)
temp |= TRANS_DDI_HIGH_TMDS_CHAR_RATE;
+ if (DISPLAY_VER(dev_priv) >= 14)
+ temp |= TRANS_DDI_PORT_WIDTH(crtc_state->lane_count);
} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
temp |= TRANS_DDI_MODE_SELECT_FDI_OR_128B132B;
temp |= (crtc_state->fdi_lanes - 1) << 1;
@@ -2196,12 +2225,10 @@ static void intel_ddi_enable_fec(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_dp *intel_dp;
if (!crtc_state->fec_enable)
return;
- intel_dp = enc_to_intel_dp(encoder);
intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
0, DP_TP_CTL_FEC_ENABLE);
}
@@ -2210,12 +2237,10 @@ static void intel_ddi_disable_fec_state(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_dp *intel_dp;
if (!crtc_state->fec_enable)
return;
- intel_dp = enc_to_intel_dp(encoder);
intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
DP_TP_CTL_FEC_ENABLE, 0);
intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
@@ -2309,6 +2334,179 @@ static void intel_ddi_mso_configure(const struct intel_crtc_state *crtc_state)
OVERLAP_PIXELS_MASK, dss1);
}
+static u8 mtl_get_port_width(u8 lane_count)
+{
+ switch (lane_count) {
+ case 1:
+ return 0;
+ case 2:
+ return 1;
+ case 3:
+ return 4;
+ case 4:
+ return 3;
+ default:
+ MISSING_CASE(lane_count);
+ return 4;
+ }
+}
+
+static void
+mtl_ddi_enable_d2d(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum port port = encoder->port;
+
+ intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(port), 0,
+ XELPDP_PORT_BUF_D2D_LINK_ENABLE);
+
+ if (wait_for_us((intel_de_read(dev_priv, XELPDP_PORT_BUF_CTL1(port)) &
+ XELPDP_PORT_BUF_D2D_LINK_STATE), 100)) {
+ drm_err(&dev_priv->drm, "Timeout waiting for D2D Link enable for PORT_BUF_CTL %c\n",
+ port_name(port));
+ }
+}
+
+static void mtl_port_buf_ctl_program(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+ enum port port = encoder->port;
+ u32 val;
+
+ val = intel_de_read(i915, XELPDP_PORT_BUF_CTL1(port));
+ val &= ~XELPDP_PORT_WIDTH_MASK;
+ val |= XELPDP_PORT_WIDTH(mtl_get_port_width(crtc_state->lane_count));
+
+ val &= ~XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK;
+ if (intel_dp_is_uhbr(crtc_state))
+ val |= XELPDP_PORT_BUF_PORT_DATA_40BIT;
+ else
+ val |= XELPDP_PORT_BUF_PORT_DATA_10BIT;
+
+ if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL)
+ val |= XELPDP_PORT_REVERSAL;
+
+ intel_de_write(i915, XELPDP_PORT_BUF_CTL1(port), val);
+}
+
+static void mtl_port_buf_ctl_io_selection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+ u32 val;
+
+ val = intel_tc_port_in_tbt_alt_mode(dig_port) ?
+ XELPDP_PORT_BUF_IO_SELECT_TBT : 0;
+ intel_de_rmw(i915, XELPDP_PORT_BUF_CTL1(encoder->port),
+ XELPDP_PORT_BUF_IO_SELECT_TBT, val);
+}
+
+static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
+ struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
+{
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
+
+ intel_dp_set_link_params(intel_dp,
+ crtc_state->port_clock,
+ crtc_state->lane_count);
+
+ /*
+ * We only configure what the register value will be here. Actual
+ * enabling happens during link training farther down.
+ */
+ intel_ddi_init_dp_buf_reg(encoder, crtc_state);
+
+ /*
+ * 1. Enable Power Wells
+ *
+ * This was handled at the beginning of intel_atomic_commit_tail(),
+ * before we called down into this function.
+ */
+
+ /* 2. PMdemand was already set */
+
+ /* 3. Select Thunderbolt */
+ mtl_port_buf_ctl_io_selection(encoder);
+
+ /* 4. Enable Panel Power if PPS is required */
+ intel_pps_on(intel_dp);
+
+ /* 5. Enable the port PLL */
+ intel_ddi_enable_clock(encoder, crtc_state);
+
+ /*
+ * 6.a Configure Transcoder Clock Select to direct the Port clock to the
+ * Transcoder.
+ */
+ intel_ddi_enable_transcoder_clock(encoder, crtc_state);
+
+ /*
+ * 6.b If DP v2.0/128b mode - Configure TRANS_DP2_CTL register settings.
+ */
+ intel_ddi_config_transcoder_dp2(encoder, crtc_state);
+
+ /*
+ * 6.c Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
+ * Transport Select
+ */
+ intel_ddi_config_transcoder_func(encoder, crtc_state);
+
+ /*
+ * 6.e Program CoG/MSO configuration bits in DSS_CTL1 if selected.
+ */
+ intel_ddi_mso_configure(crtc_state);
+
+ if (!is_mst)
+ intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
+
+ intel_dp_configure_protocol_converter(intel_dp, crtc_state);
+ intel_dp_sink_set_decompression_state(intel_dp, crtc_state, true);
+ /*
+ * DDI FEC: "anticipates enabling FEC encoding sets the FEC_READY bit
+ * in the FEC_CONFIGURATION register to 1 before initiating link
+ * training
+ */
+ intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
+
+ intel_dp_check_frl_training(intel_dp);
+ intel_dp_pcon_dsc_configure(intel_dp, crtc_state);
+
+ /*
+ * 6. The rest of the below are substeps under the bspec's "Enable and
+ * Train Display Port" step. Note that steps that are specific to
+ * MST will be handled by intel_mst_pre_enable_dp() before/after it
+ * calls into this function. Also intel_mst_pre_enable_dp() only calls
+ * us when active_mst_links==0, so any steps designated for "single
+ * stream or multi-stream master transcoder" can just be performed
+ * unconditionally here.
+ *
+ * mtl_ddi_prepare_link_retrain() that is called by
+ * intel_dp_start_link_train() will execute steps: 6.d, 6.f, 6.g, 6.h,
+ * 6.i and 6.j
+ *
+ * 6.k Follow DisplayPort specification training sequence (see notes for
+ * failure handling)
+ * 6.m If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle
+ * Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent)
+ * (timeout after 800 us)
+ */
+ intel_dp_start_link_train(intel_dp, crtc_state);
+
+ /* 6.n Set DP_TP_CTL link training to Normal */
+ if (!is_trans_port_sync_mode(crtc_state))
+ intel_dp_stop_link_train(intel_dp, crtc_state);
+
+ /* 6.o Configure and enable FEC if needed */
+ intel_ddi_enable_fec(encoder, crtc_state);
+
+ intel_dsc_dp_pps_write(encoder, crtc_state);
+}
+
static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
@@ -2523,7 +2721,9 @@ static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
intel_dp_128b132b_sdp_crc16(enc_to_intel_dp(encoder),
crtc_state);
- if (DISPLAY_VER(dev_priv) >= 12)
+ if (DISPLAY_VER(dev_priv) >= 14)
+ mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
+ else if (DISPLAY_VER(dev_priv) >= 12)
tgl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
else
hsw_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
@@ -2597,15 +2797,57 @@ static void intel_ddi_pre_enable(struct intel_atomic_state *state,
/* FIXME precompute everything properly */
/* FIXME how do we turn infoframes off again? */
- if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink)
+ if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp))
dig_port->set_infoframes(encoder,
crtc_state->has_infoframe,
crtc_state, conn_state);
}
}
-static void intel_disable_ddi_buf(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+static void
+mtl_ddi_disable_d2d_link(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum port port = encoder->port;
+
+ intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(port),
+ XELPDP_PORT_BUF_D2D_LINK_ENABLE, 0);
+
+ if (wait_for_us(!(intel_de_read(dev_priv, XELPDP_PORT_BUF_CTL1(port)) &
+ XELPDP_PORT_BUF_D2D_LINK_STATE), 100))
+ drm_err(&dev_priv->drm, "Timeout waiting for D2D Link disable for PORT_BUF_CTL %c\n",
+ port_name(port));
+}
+
+static void mtl_disable_ddi_buf(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum port port = encoder->port;
+ u32 val;
+
+ /* 3.b Clear DDI_CTL_DE Enable to 0. */
+ val = intel_de_read(dev_priv, DDI_BUF_CTL(port));
+ if (val & DDI_BUF_CTL_ENABLE) {
+ val &= ~DDI_BUF_CTL_ENABLE;
+ intel_de_write(dev_priv, DDI_BUF_CTL(port), val);
+
+ /* 3.c Poll for PORT_BUF_CTL Idle Status == 1, timeout after 100us */
+ mtl_wait_ddi_buf_idle(dev_priv, port);
+ }
+
+ /* 3.d Disable D2D Link */
+ mtl_ddi_disable_d2d_link(encoder);
+
+ /* 3.e Disable DP_TP_CTL */
+ if (intel_crtc_has_dp_encoder(crtc_state)) {
+ intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
+ DP_TP_CTL_ENABLE, 0);
+ }
+}
+
+static void disable_ddi_buf(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum port port = encoder->port;
@@ -2630,6 +2872,21 @@ static void intel_disable_ddi_buf(struct intel_encoder *encoder,
intel_wait_ddi_buf_idle(dev_priv, port);
}
+static void intel_disable_ddi_buf(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+
+ if (DISPLAY_VER(dev_priv) >= 14) {
+ mtl_disable_ddi_buf(encoder, crtc_state);
+
+ /* 3.f Disable DP_TP_CTL FEC Enable if it is needed */
+ intel_ddi_disable_fec_state(encoder, crtc_state);
+ } else {
+ disable_ddi_buf(encoder, crtc_state);
+ }
+}
+
static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
@@ -2638,6 +2895,7 @@ static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct intel_dp *intel_dp = &dig_port->dp;
+ intel_wakeref_t wakeref;
bool is_mst = intel_crtc_has_type(old_crtc_state,
INTEL_OUTPUT_DP_MST);
@@ -2677,12 +2935,19 @@ static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
intel_pps_vdd_on(intel_dp);
intel_pps_off(intel_dp);
- if (!intel_tc_port_in_tbt_alt_mode(dig_port))
+ wakeref = fetch_and_zero(&dig_port->ddi_io_wakeref);
+
+ if (wakeref)
intel_display_power_put(dev_priv,
dig_port->ddi_io_power_domain,
- fetch_and_zero(&dig_port->ddi_io_wakeref));
+ wakeref);
intel_ddi_disable_clock(encoder);
+
+ /* De-select Thunderbolt */
+ if (DISPLAY_VER(dev_priv) >= 14)
+ intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(encoder->port),
+ XELPDP_PORT_BUF_IO_SELECT_TBT, 0);
}
static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state,
@@ -2693,6 +2958,7 @@ static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state,
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
+ intel_wakeref_t wakeref;
dig_port->set_infoframes(encoder, false,
old_crtc_state, old_conn_state);
@@ -2705,9 +2971,11 @@ static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state,
if (DISPLAY_VER(dev_priv) >= 12)
intel_ddi_disable_transcoder_clock(old_crtc_state);
- intel_display_power_put(dev_priv,
- dig_port->ddi_io_power_domain,
- fetch_and_zero(&dig_port->ddi_io_wakeref));
+ wakeref = fetch_and_zero(&dig_port->ddi_io_wakeref);
+ if (wakeref)
+ intel_display_power_put(dev_priv,
+ dig_port->ddi_io_power_domain,
+ wakeref);
intel_ddi_disable_clock(encoder);
@@ -2725,8 +2993,6 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state,
if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) {
intel_crtc_vblank_off(old_crtc_state);
- intel_vrr_disable(old_crtc_state);
-
intel_disable_transcoder(old_crtc_state);
intel_ddi_disable_transcoder_func(old_crtc_state);
@@ -2840,7 +3106,7 @@ static void intel_enable_ddi_dp(struct intel_atomic_state *state,
drm_connector_update_privacy_screen(conn_state);
intel_edp_backlight_on(crtc_state, conn_state);
- if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink)
+ if (!dig_port->lspcon.active || intel_dp_has_hdmi_sink(&dig_port->dp))
intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
intel_audio_codec_enable(encoder, crtc_state, conn_state);
@@ -2890,6 +3156,10 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
if (has_buf_trans_select(dev_priv))
hsw_prepare_hdmi_ddi_buffers(encoder, crtc_state);
+ /* e. Enable D2D Link for C10/C20 Phy */
+ if (DISPLAY_VER(dev_priv) >= 14)
+ mtl_ddi_enable_d2d(encoder);
+
encoder->set_signal_levels(encoder, crtc_state);
/* Display WA #1143: skl,kbl,cfl */
@@ -2935,12 +3205,30 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
*
* On ADL_P the PHY link rate and lane count must be programmed but
* these are both 0 for HDMI.
+ *
+ * But MTL onwards HDMI2.1 is supported and in TMDS mode this
+ * is filled with lane count, already set in the crtc_state.
+ * The same is required to be filled in PORT_BUF_CTL for C10/20 Phy.
*/
buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE;
- if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) {
+ if (DISPLAY_VER(dev_priv) >= 14) {
+ u8 lane_count = mtl_get_port_width(crtc_state->lane_count);
+ u32 port_buf = 0;
+
+ port_buf |= XELPDP_PORT_WIDTH(lane_count);
+
+ if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL)
+ port_buf |= XELPDP_PORT_REVERSAL;
+
+ intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(port),
+ XELPDP_PORT_WIDTH_MASK | XELPDP_PORT_REVERSAL, port_buf);
+
+ buf_ctl |= DDI_PORT_WIDTH(lane_count);
+ } else if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) {
drm_WARN_ON(&dev_priv->drm, !intel_tc_port_in_legacy_mode(dig_port));
buf_ctl |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
}
+
intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl);
intel_wait_ddi_buf_active(dev_priv, port);
@@ -2963,8 +3251,6 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
intel_enable_transcoder(crtc_state);
- intel_vrr_enable(encoder, crtc_state);
-
intel_crtc_vblank_on(crtc_state);
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
@@ -2975,9 +3261,7 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
/* Enable hdcp if it's desired */
if (conn_state->content_protection ==
DRM_MODE_CONTENT_PROTECTION_DESIRED)
- intel_hdcp_enable(to_intel_connector(conn_state->connector),
- crtc_state,
- (u8)conn_state->hdcp_content_type);
+ intel_hdcp_enable(state, encoder, crtc_state, conn_state);
}
static void intel_disable_ddi_dp(struct intel_atomic_state *state,
@@ -3023,6 +3307,8 @@ static void intel_disable_ddi(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
+ intel_tc_port_link_cancel_reset_work(enc_to_dig_port(encoder));
+
intel_hdcp_disable(to_intel_connector(old_conn_state->connector));
if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
@@ -3070,7 +3356,8 @@ void intel_ddi_update_active_dpll(struct intel_atomic_state *state,
struct intel_crtc *slave_crtc;
enum phy phy = intel_port_to_phy(i915, encoder->port);
- if (!intel_phy_is_tc(i915, phy))
+ /* FIXME: Add MTL pll_mgr */
+ if (DISPLAY_VER(i915) >= 14 || !intel_phy_is_tc(i915, phy))
return;
intel_update_active_dpll(state, crtc, encoder);
@@ -3121,6 +3408,53 @@ static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder)
intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port, ln), DKL_PCS_DW5_CORE_SOFTRESET, 0);
}
+static void mtl_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct intel_encoder *encoder = &dig_port->base;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum port port = encoder->port;
+ u32 dp_tp_ctl;
+
+ /*
+ * TODO: To train with only a different voltage swing entry is not
+ * necessary disable and enable port
+ */
+ dp_tp_ctl = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
+ if (dp_tp_ctl & DP_TP_CTL_ENABLE)
+ mtl_disable_ddi_buf(encoder, crtc_state);
+
+ /* 6.d Configure and enable DP_TP_CTL with link training pattern 1 selected */
+ dp_tp_ctl = DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT1;
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
+ dp_tp_ctl |= DP_TP_CTL_MODE_MST;
+ } else {
+ dp_tp_ctl |= DP_TP_CTL_MODE_SST;
+ if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+ dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
+ }
+ intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
+ intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
+
+ /* 6.f Enable D2D Link */
+ mtl_ddi_enable_d2d(encoder);
+
+ /* 6.g Configure voltage swing and related IO settings */
+ encoder->set_signal_levels(encoder, crtc_state);
+
+ /* 6.h Configure PORT_BUF_CTL1 */
+ mtl_port_buf_ctl_program(encoder, crtc_state);
+
+ /* 6.i Configure and enable DDI_CTL_DE to start sending valid data to port slice */
+ intel_dp->DP |= DDI_BUF_CTL_ENABLE;
+ intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
+ intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
+
+ /* 6.j Poll for PORT_BUF_CTL Idle Status == 0, timeout after 100 us */
+ intel_wait_ddi_buf_active(dev_priv, port);
+}
+
static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
@@ -3369,7 +3703,11 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
fallthrough;
case TRANS_DDI_MODE_SELECT_DVI:
pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI);
- pipe_config->lane_count = 4;
+ if (DISPLAY_VER(dev_priv) >= 14)
+ pipe_config->lane_count =
+ ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
+ else
+ pipe_config->lane_count = 4;
break;
case TRANS_DDI_MODE_SELECT_DP_SST:
if (encoder->type == INTEL_OUTPUT_EDP)
@@ -3396,7 +3734,7 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
pipe_config->fec_enable);
}
- if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink)
+ if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp))
pipe_config->infoframes.enable |=
intel_lspcon_infoframes_enabled(encoder, pipe_config);
else
@@ -3506,6 +3844,28 @@ void intel_ddi_get_clock(struct intel_encoder *encoder,
&crtc_state->dpll_hw_state);
}
+static void mtl_ddi_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+ if (intel_tc_port_in_tbt_alt_mode(dig_port)) {
+ crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
+ } else if (intel_is_c10phy(i915, phy)) {
+ intel_c10pll_readout_hw_state(encoder, &crtc_state->cx0pll_state.c10);
+ intel_c10pll_dump_hw_state(i915, &crtc_state->cx0pll_state.c10);
+ crtc_state->port_clock = intel_c10pll_calc_port_clock(encoder, &crtc_state->cx0pll_state.c10);
+ } else {
+ intel_c20pll_readout_hw_state(encoder, &crtc_state->cx0pll_state.c20);
+ intel_c20pll_dump_hw_state(i915, &crtc_state->cx0pll_state.c20);
+ crtc_state->port_clock = intel_c20pll_calc_port_clock(encoder, &crtc_state->cx0pll_state.c20);
+ }
+
+ intel_ddi_get_config(encoder, crtc_state);
+}
+
static void dg2_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state)
{
@@ -3700,6 +4060,9 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
pipe_config->cpu_transcoder = TRANSCODER_EDP;
if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI)) {
+ pipe_config->has_hdmi_sink =
+ intel_hdmi_compute_has_hdmi_sink(encoder, pipe_config, conn_state);
+
ret = intel_hdmi_compute_config(encoder, pipe_config, conn_state);
} else {
ret = intel_dp_compute_config(encoder, pipe_config, conn_state);
@@ -3865,14 +4228,25 @@ static void intel_ddi_encoder_reset(struct drm_encoder *encoder)
intel_tc_port_init_mode(dig_port);
}
+static int intel_ddi_encoder_late_register(struct drm_encoder *_encoder)
+{
+ struct intel_encoder *encoder = to_intel_encoder(_encoder);
+
+ intel_tc_port_link_reset(enc_to_dig_port(encoder));
+
+ return 0;
+}
+
static const struct drm_encoder_funcs intel_ddi_funcs = {
.reset = intel_ddi_encoder_reset,
.destroy = intel_ddi_encoder_destroy,
+ .late_register = intel_ddi_encoder_late_register,
};
static struct intel_connector *
intel_ddi_init_dp_connector(struct intel_digital_port *dig_port)
{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_connector *connector;
enum port port = dig_port->base.port;
@@ -3881,7 +4255,10 @@ intel_ddi_init_dp_connector(struct intel_digital_port *dig_port)
return NULL;
dig_port->dp.output_reg = DDI_BUF_CTL(port);
- dig_port->dp.prepare_link_retrain = intel_ddi_prepare_link_retrain;
+ if (DISPLAY_VER(i915) >= 14)
+ dig_port->dp.prepare_link_retrain = mtl_ddi_prepare_link_retrain;
+ else
+ dig_port->dp.prepare_link_retrain = intel_ddi_prepare_link_retrain;
dig_port->dp.set_link_train = intel_ddi_set_link_train;
dig_port->dp.set_idle_link_train = intel_ddi_set_idle_link_train;
@@ -3921,6 +4298,7 @@ static int modeset_pipe(struct drm_crtc *crtc,
return -ENOMEM;
state->acquire_ctx = ctx;
+ to_intel_atomic_state(state)->internal = true;
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state)) {
@@ -4032,27 +4410,17 @@ intel_ddi_hotplug(struct intel_encoder *encoder,
state = intel_encoder_hotplug(encoder, connector);
- drm_modeset_acquire_init(&ctx, 0);
-
- for (;;) {
- if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA)
- ret = intel_hdmi_reset_link(encoder, &ctx);
- else
- ret = intel_dp_retrain_link(encoder, &ctx);
-
- if (ret == -EDEADLK) {
- drm_modeset_backoff(&ctx);
- continue;
+ if (!intel_tc_port_link_reset(dig_port)) {
+ intel_modeset_lock_ctx_retry(&ctx, NULL, 0, ret) {
+ if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA)
+ ret = intel_hdmi_reset_link(encoder, &ctx);
+ else
+ ret = intel_dp_retrain_link(encoder, &ctx);
}
- break;
+ drm_WARN_ON(encoder->base.dev, ret);
}
- drm_modeset_drop_locks(&ctx);
- drm_modeset_acquire_fini(&ctx);
- drm_WARN(encoder->base.dev, ret,
- "Acquiring modeset locks failed with %i\n", ret);
-
/*
* Unpowered type-c dongles can take some time to boot and be
* responsible, so here giving some time to those dongles to power up
@@ -4257,31 +4625,27 @@ static bool intel_ddi_is_tc(struct drm_i915_private *i915, enum port port)
static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
{
- struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
- struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
- enum phy phy = intel_port_to_phy(i915, encoder->port);
-
intel_dp_encoder_suspend(encoder);
-
- if (!intel_phy_is_tc(i915, phy))
- return;
-
- intel_tc_port_flush_work(dig_port);
}
-static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder)
+static void intel_ddi_tc_encoder_suspend_complete(struct intel_encoder *encoder)
{
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
- enum phy phy = intel_port_to_phy(i915, encoder->port);
+ intel_tc_port_suspend(dig_port);
+}
+
+static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder)
+{
intel_dp_encoder_shutdown(encoder);
intel_hdmi_encoder_shutdown(encoder);
+}
- if (!intel_phy_is_tc(i915, phy))
- return;
+static void intel_ddi_tc_encoder_shutdown_complete(struct intel_encoder *encoder)
+{
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
intel_tc_port_cleanup(dig_port);
}
@@ -4413,7 +4777,12 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
encoder->cloneable = 0;
encoder->pipe_mask = ~0;
- if (IS_DG2(dev_priv)) {
+ if (DISPLAY_VER(dev_priv) >= 14) {
+ encoder->enable_clock = intel_mtl_pll_enable;
+ encoder->disable_clock = intel_mtl_pll_disable;
+ encoder->port_pll_type = intel_mtl_port_pll_type;
+ encoder->get_config = mtl_ddi_get_config;
+ } else if (IS_DG2(dev_priv)) {
encoder->enable_clock = intel_mpllb_enable;
encoder->disable_clock = intel_mpllb_disable;
encoder->get_config = dg2_ddi_get_config;
@@ -4473,7 +4842,9 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
encoder->get_config = hsw_ddi_get_config;
}
- if (IS_DG2(dev_priv)) {
+ if (DISPLAY_VER(dev_priv) >= 14) {
+ encoder->set_signal_levels = intel_cx0_phy_set_signal_levels;
+ } else if (IS_DG2(dev_priv)) {
encoder->set_signal_levels = intel_snps_phy_set_signal_levels;
} else if (DISPLAY_VER(dev_priv) >= 12) {
if (intel_phy_is_combo(dev_priv, phy))
@@ -4541,6 +4912,9 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
is_legacy ? "legacy" : "non-legacy");
}
+ encoder->suspend_complete = intel_ddi_tc_encoder_suspend_complete;
+ encoder->shutdown_complete = intel_ddi_tc_encoder_shutdown_complete;
+
if (intel_tc_port_init(dig_port, is_legacy) < 0)
goto err;
}
diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
index 006a2e979000..b7d20485bde5 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
@@ -9,6 +9,7 @@
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
+#include "intel_cx0_phy.h"
/* HDMI/DVI modes ignore everything but the last 2 items. So we share
* them for both DP and FDI transports, allowing those ports to
@@ -1035,6 +1036,65 @@ static const struct intel_ddi_buf_trans dg2_snps_trans_uhbr = {
.num_entries = ARRAY_SIZE(_dg2_snps_trans_uhbr),
};
+static const union intel_ddi_buf_trans_entry _mtl_c10_trans_dp14[] = {
+ { .snps = { 26, 0, 0 } }, /* preset 0 */
+ { .snps = { 33, 0, 6 } }, /* preset 1 */
+ { .snps = { 38, 0, 11 } }, /* preset 2 */
+ { .snps = { 43, 0, 19 } }, /* preset 3 */
+ { .snps = { 39, 0, 0 } }, /* preset 4 */
+ { .snps = { 45, 0, 7 } }, /* preset 5 */
+ { .snps = { 46, 0, 13 } }, /* preset 6 */
+ { .snps = { 46, 0, 0 } }, /* preset 7 */
+ { .snps = { 55, 0, 7 } }, /* preset 8 */
+ { .snps = { 62, 0, 0 } }, /* preset 9 */
+};
+
+static const struct intel_ddi_buf_trans mtl_cx0_trans = {
+ .entries = _mtl_c10_trans_dp14,
+ .num_entries = ARRAY_SIZE(_mtl_c10_trans_dp14),
+ .hdmi_default_entry = ARRAY_SIZE(_mtl_c10_trans_dp14) - 1,
+};
+
+/* DP2.0 */
+static const union intel_ddi_buf_trans_entry _mtl_c20_trans_uhbr[] = {
+ { .snps = { 48, 0, 0 } }, /* preset 0 */
+ { .snps = { 43, 0, 5 } }, /* preset 1 */
+ { .snps = { 40, 0, 8 } }, /* preset 2 */
+ { .snps = { 37, 0, 11 } }, /* preset 3 */
+ { .snps = { 33, 0, 15 } }, /* preset 4 */
+ { .snps = { 46, 2, 0 } }, /* preset 5 */
+ { .snps = { 42, 2, 4 } }, /* preset 6 */
+ { .snps = { 38, 2, 8 } }, /* preset 7 */
+ { .snps = { 35, 2, 11 } }, /* preset 8 */
+ { .snps = { 33, 2, 13 } }, /* preset 9 */
+ { .snps = { 44, 4, 0 } }, /* preset 10 */
+ { .snps = { 40, 4, 4 } }, /* preset 11 */
+ { .snps = { 37, 4, 7 } }, /* preset 12 */
+ { .snps = { 33, 4, 11 } }, /* preset 13 */
+ { .snps = { 40, 8, 0 } }, /* preset 14 */
+ { .snps = { 28, 2, 2 } }, /* preset 15 */
+};
+
+/* HDMI2.0 */
+static const union intel_ddi_buf_trans_entry _mtl_c20_trans_hdmi[] = {
+ { .snps = { 48, 0, 0 } }, /* preset 0 */
+ { .snps = { 38, 4, 6 } }, /* preset 1 */
+ { .snps = { 36, 4, 8 } }, /* preset 2 */
+ { .snps = { 34, 4, 10 } }, /* preset 3 */
+ { .snps = { 32, 4, 12 } }, /* preset 4 */
+};
+
+static const struct intel_ddi_buf_trans mtl_c20_trans_hdmi = {
+ .entries = _mtl_c20_trans_hdmi,
+ .num_entries = ARRAY_SIZE(_mtl_c20_trans_hdmi),
+ .hdmi_default_entry = 0,
+};
+
+static const struct intel_ddi_buf_trans mtl_c20_trans_uhbr = {
+ .entries = _mtl_c20_trans_uhbr,
+ .num_entries = ARRAY_SIZE(_mtl_c20_trans_uhbr),
+};
+
bool is_hobl_buf_trans(const struct intel_ddi_buf_trans *table)
{
return table == &tgl_combo_phy_trans_edp_hbr2_hobl;
@@ -1606,12 +1666,30 @@ dg2_get_snps_buf_trans(struct intel_encoder *encoder,
return intel_get_buf_trans(&dg2_snps_trans, n_entries);
}
+static const struct intel_ddi_buf_trans *
+mtl_get_cx0_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
+
+ if (intel_crtc_has_dp_encoder(crtc_state) && crtc_state->port_clock >= 1000000)
+ return intel_get_buf_trans(&mtl_c20_trans_uhbr, n_entries);
+ else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && !(intel_is_c10phy(i915, phy)))
+ return intel_get_buf_trans(&mtl_c20_trans_hdmi, n_entries);
+ else
+ return intel_get_buf_trans(&mtl_cx0_trans, n_entries);
+}
+
void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
- if (IS_DG2(i915)) {
+ if (DISPLAY_VER(i915) >= 14) {
+ encoder->get_buf_trans = mtl_get_cx0_buf_trans;
+ } else if (IS_DG2(i915)) {
encoder->get_buf_trans = dg2_get_snps_buf_trans;
} else if (IS_ALDERLAKE_P(i915)) {
if (intel_phy_is_combo(i915, phy))
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 0aae9a1eb3d5..d8533603ad05 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -31,8 +31,6 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string_helpers.h>
-#include <linux/vga_switcheroo.h>
-#include <acpi/video.h>
#include <drm/display/drm_dp_helper.h>
#include <drm/drm_atomic.h>
@@ -41,7 +39,6 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_fourcc.h>
-#include <drm/drm_privacy_screen_consumer.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_rect.h>
@@ -57,7 +54,6 @@
#include "i9xx_plane.h"
#include "i9xx_wm.h"
#include "icl_dsi.h"
-#include "intel_acpi.h"
#include "intel_atomic.h"
#include "intel_atomic_plane.h"
#include "intel_audio.h"
@@ -70,7 +66,7 @@
#include "intel_crtc_state_dump.h"
#include "intel_ddi.h"
#include "intel_de.h"
-#include "intel_display_debugfs.h"
+#include "intel_display_driver.h"
#include "intel_display_power.h"
#include "intel_display_types.h"
#include "intel_dmc.h"
@@ -90,11 +86,8 @@
#include "intel_fdi.h"
#include "intel_fifo_underrun.h"
#include "intel_frontbuffer.h"
-#include "intel_gmbus.h"
-#include "intel_hdcp.h"
#include "intel_hdmi.h"
#include "intel_hotplug.h"
-#include "intel_hti.h"
#include "intel_lvds.h"
#include "intel_lvds_regs.h"
#include "intel_modeset_setup.h"
@@ -106,9 +99,9 @@
#include "intel_pcode.h"
#include "intel_pipe_crc.h"
#include "intel_plane_initial.h"
+#include "intel_pmdemand.h"
#include "intel_pps.h"
#include "intel_psr.h"
-#include "intel_quirks.h"
#include "intel_sdvo.h"
#include "intel_snps_phy.h"
#include "intel_tc.h"
@@ -131,7 +124,6 @@ static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_sta
static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state);
static void hsw_set_transconf(const struct intel_crtc_state *crtc_state);
static void bdw_set_pipe_misc(const struct intel_crtc_state *crtc_state);
-static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state);
/* returns HPLL frequency in kHz */
int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
@@ -178,7 +170,7 @@ int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
return hpll;
}
-static void intel_update_czclk(struct drm_i915_private *dev_priv)
+void intel_update_czclk(struct drm_i915_private *dev_priv)
{
if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
return;
@@ -234,7 +226,7 @@ is_trans_port_sync_slave(const struct intel_crtc_state *crtc_state)
return crtc_state->master_transcoder != INVALID_TRANSCODER;
}
-static bool
+bool
is_trans_port_sync_master(const struct intel_crtc_state *crtc_state)
{
return crtc_state->sync_mode_slaves_mask != 0;
@@ -331,20 +323,21 @@ void assert_transcoder(struct drm_i915_private *dev_priv,
cur_state = false;
}
- I915_STATE_WARN(cur_state != state,
+ I915_STATE_WARN(dev_priv, cur_state != state,
"transcoder %s assertion failure (expected %s, current %s)\n",
- transcoder_name(cpu_transcoder),
- str_on_off(state), str_on_off(cur_state));
+ transcoder_name(cpu_transcoder), str_on_off(state),
+ str_on_off(cur_state));
}
static void assert_plane(struct intel_plane *plane, bool state)
{
+ struct drm_i915_private *i915 = to_i915(plane->base.dev);
enum pipe pipe;
bool cur_state;
cur_state = plane->get_hw_state(plane, &pipe);
- I915_STATE_WARN(cur_state != state,
+ I915_STATE_WARN(i915, cur_state != state,
"%s assertion failure (expected %s, current %s)\n",
plane->base.name, str_on_off(state),
str_on_off(cur_state));
@@ -701,175 +694,6 @@ intel_plane_fence_y_offset(const struct intel_plane_state *plane_state)
return y;
}
-static int
-intel_display_commit_duplicated_state(struct intel_atomic_state *state,
- struct drm_modeset_acquire_ctx *ctx)
-{
- struct drm_i915_private *i915 = to_i915(state->base.dev);
- int ret;
-
- ret = drm_atomic_helper_commit_duplicated_state(&state->base, ctx);
-
- drm_WARN_ON(&i915->drm, ret == -EDEADLK);
-
- return ret;
-}
-
-static int
-__intel_display_resume(struct drm_i915_private *i915,
- struct drm_atomic_state *state,
- struct drm_modeset_acquire_ctx *ctx)
-{
- struct drm_crtc_state *crtc_state;
- struct drm_crtc *crtc;
- int i;
-
- intel_modeset_setup_hw_state(i915, ctx);
- intel_vga_redisable(i915);
-
- if (!state)
- return 0;
-
- /*
- * We've duplicated the state, pointers to the old state are invalid.
- *
- * Don't attempt to use the old state until we commit the duplicated state.
- */
- for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
- /*
- * Force recalculation even if we restore
- * current state. With fast modeset this may not result
- * in a modeset when the state is compatible.
- */
- crtc_state->mode_changed = true;
- }
-
- /* ignore any reset values/BIOS leftovers in the WM registers */
- if (!HAS_GMCH(i915))
- to_intel_atomic_state(state)->skip_intermediate_wm = true;
-
- return intel_display_commit_duplicated_state(to_intel_atomic_state(state), ctx);
-}
-
-static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv)
-{
- return (INTEL_INFO(dev_priv)->gpu_reset_clobbers_display &&
- intel_has_gpu_reset(to_gt(dev_priv)));
-}
-
-void intel_display_prepare_reset(struct drm_i915_private *dev_priv)
-{
- struct drm_modeset_acquire_ctx *ctx = &dev_priv->display.restore.reset_ctx;
- struct drm_atomic_state *state;
- int ret;
-
- if (!HAS_DISPLAY(dev_priv))
- return;
-
- /* reset doesn't touch the display */
- if (!dev_priv->params.force_reset_modeset_test &&
- !gpu_reset_clobbers_display(dev_priv))
- return;
-
- /* We have a modeset vs reset deadlock, defensively unbreak it. */
- set_bit(I915_RESET_MODESET, &to_gt(dev_priv)->reset.flags);
- smp_mb__after_atomic();
- wake_up_bit(&to_gt(dev_priv)->reset.flags, I915_RESET_MODESET);
-
- if (atomic_read(&dev_priv->gpu_error.pending_fb_pin)) {
- drm_dbg_kms(&dev_priv->drm,
- "Modeset potentially stuck, unbreaking through wedging\n");
- intel_gt_set_wedged(to_gt(dev_priv));
- }
-
- /*
- * Need mode_config.mutex so that we don't
- * trample ongoing ->detect() and whatnot.
- */
- mutex_lock(&dev_priv->drm.mode_config.mutex);
- drm_modeset_acquire_init(ctx, 0);
- while (1) {
- ret = drm_modeset_lock_all_ctx(&dev_priv->drm, ctx);
- if (ret != -EDEADLK)
- break;
-
- drm_modeset_backoff(ctx);
- }
- /*
- * Disabling the crtcs gracefully seems nicer. Also the
- * g33 docs say we should at least disable all the planes.
- */
- state = drm_atomic_helper_duplicate_state(&dev_priv->drm, ctx);
- if (IS_ERR(state)) {
- ret = PTR_ERR(state);
- drm_err(&dev_priv->drm, "Duplicating state failed with %i\n",
- ret);
- return;
- }
-
- ret = drm_atomic_helper_disable_all(&dev_priv->drm, ctx);
- if (ret) {
- drm_err(&dev_priv->drm, "Suspending crtc's failed with %i\n",
- ret);
- drm_atomic_state_put(state);
- return;
- }
-
- dev_priv->display.restore.modeset_state = state;
- state->acquire_ctx = ctx;
-}
-
-void intel_display_finish_reset(struct drm_i915_private *i915)
-{
- struct drm_modeset_acquire_ctx *ctx = &i915->display.restore.reset_ctx;
- struct drm_atomic_state *state;
- int ret;
-
- if (!HAS_DISPLAY(i915))
- return;
-
- /* reset doesn't touch the display */
- if (!test_bit(I915_RESET_MODESET, &to_gt(i915)->reset.flags))
- return;
-
- state = fetch_and_zero(&i915->display.restore.modeset_state);
- if (!state)
- goto unlock;
-
- /* reset doesn't touch the display */
- if (!gpu_reset_clobbers_display(i915)) {
- /* for testing only restore the display */
- ret = intel_display_commit_duplicated_state(to_intel_atomic_state(state), ctx);
- if (ret)
- drm_err(&i915->drm,
- "Restoring old state failed with %i\n", ret);
- } else {
- /*
- * The display has been reset as well,
- * so need a full re-initialization.
- */
- intel_pps_unlock_regs_wa(i915);
- intel_modeset_init_hw(i915);
- intel_clock_gating_init(i915);
- intel_hpd_init(i915);
-
- ret = __intel_display_resume(i915, state, ctx);
- if (ret)
- drm_err(&i915->drm,
- "Restoring old state failed with %i\n", ret);
-
- intel_hpd_poll_disable(i915);
- }
-
- drm_atomic_state_put(state);
-unlock:
- drm_modeset_drop_locks(ctx);
- drm_modeset_acquire_fini(ctx);
- mutex_unlock(&i915->drm.mode_config.mutex);
-
- clear_bit_unlock(I915_RESET_MODESET, &to_gt(i915)->reset.flags);
-}
-
static void icl_set_pipe_chicken(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -990,8 +814,10 @@ static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state)
else
intel_de_write_fw(dev_priv, PF_CTL(pipe), PF_ENABLE |
PF_FILTER_MED_3x3);
- intel_de_write_fw(dev_priv, PF_WIN_POS(pipe), x << 16 | y);
- intel_de_write_fw(dev_priv, PF_WIN_SZ(pipe), width << 16 | height);
+ intel_de_write_fw(dev_priv, PF_WIN_POS(pipe),
+ PF_WIN_XPOS(x) | PF_WIN_YPOS(y));
+ intel_de_write_fw(dev_priv, PF_WIN_SZ(pipe),
+ PF_WIN_XSIZE(width) | PF_WIN_YSIZE(height));
}
static void intel_crtc_dpms_overlay_disable(struct intel_crtc *crtc)
@@ -1069,20 +895,40 @@ static bool needs_async_flip_vtd_wa(const struct intel_crtc_state *crtc_state)
(DISPLAY_VER(i915) == 9 || IS_BROADWELL(i915) || IS_HASWELL(i915));
}
+#define is_enabling(feature, old_crtc_state, new_crtc_state) \
+ ((!(old_crtc_state)->feature || intel_crtc_needs_modeset(new_crtc_state)) && \
+ (new_crtc_state)->feature)
+#define is_disabling(feature, old_crtc_state, new_crtc_state) \
+ ((old_crtc_state)->feature && \
+ (!(new_crtc_state)->feature || intel_crtc_needs_modeset(new_crtc_state)))
+
static bool planes_enabling(const struct intel_crtc_state *old_crtc_state,
const struct intel_crtc_state *new_crtc_state)
{
- return (!old_crtc_state->active_planes || intel_crtc_needs_modeset(new_crtc_state)) &&
- new_crtc_state->active_planes;
+ return is_enabling(active_planes, old_crtc_state, new_crtc_state);
}
static bool planes_disabling(const struct intel_crtc_state *old_crtc_state,
const struct intel_crtc_state *new_crtc_state)
{
- return old_crtc_state->active_planes &&
- (!new_crtc_state->active_planes || intel_crtc_needs_modeset(new_crtc_state));
+ return is_disabling(active_planes, old_crtc_state, new_crtc_state);
+}
+
+static bool vrr_enabling(const struct intel_crtc_state *old_crtc_state,
+ const struct intel_crtc_state *new_crtc_state)
+{
+ return is_enabling(vrr.enable, old_crtc_state, new_crtc_state);
+}
+
+static bool vrr_disabling(const struct intel_crtc_state *old_crtc_state,
+ const struct intel_crtc_state *new_crtc_state)
+{
+ return is_disabling(vrr.enable, old_crtc_state, new_crtc_state);
}
+#undef is_disabling
+#undef is_enabling
+
static void intel_post_plane_update(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -1126,7 +972,7 @@ static void intel_crtc_enable_flip_done(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
u8 update_planes = crtc_state->update_planes;
- const struct intel_plane_state *plane_state;
+ const struct intel_plane_state __maybe_unused *plane_state;
struct intel_plane *plane;
int i;
@@ -1143,7 +989,7 @@ static void intel_crtc_disable_flip_done(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
u8 update_planes = crtc_state->update_planes;
- const struct intel_plane_state *plane_state;
+ const struct intel_plane_state __maybe_unused *plane_state;
struct intel_plane *plane;
int i;
@@ -1196,6 +1042,11 @@ static void intel_pre_plane_update(struct intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
enum pipe pipe = crtc->pipe;
+ if (vrr_disabling(old_crtc_state, new_crtc_state)) {
+ intel_vrr_disable(old_crtc_state);
+ intel_crtc_update_active_timings(old_crtc_state, false);
+ }
+
intel_drrs_deactivate(old_crtc_state);
intel_psr_pre_plane_update(state, crtc);
@@ -1676,6 +1527,8 @@ static void hsw_configure_cpu_transcoder(const struct intel_crtc_state *crtc_sta
}
intel_set_transcoder_timings(crtc_state);
+ if (HAS_VRR(dev_priv))
+ intel_vrr_set_transcoder_timings(crtc_state);
if (cpu_transcoder != TRANSCODER_EDP)
intel_de_write(dev_priv, TRANS_MULT(cpu_transcoder),
@@ -1915,7 +1768,7 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy)
if (IS_DG2(dev_priv))
/* DG2's "TC1" output uses a SNPS PHY */
return false;
- else if (IS_ALDERLAKE_P(dev_priv))
+ else if (IS_ALDERLAKE_P(dev_priv) || IS_METEORLAKE(dev_priv))
return phy >= PHY_F && phy <= PHY_I;
else if (IS_TIGERLAKE(dev_priv))
return phy >= PHY_D && phy <= PHY_I;
@@ -2222,30 +2075,6 @@ static void i9xx_crtc_disable(struct intel_atomic_state *state,
i830_enable_pipe(dev_priv, pipe);
}
-
-/*
- * turn all crtc's off, but do not adjust state
- * This has to be paired with a call to intel_modeset_setup_hw_state.
- */
-int intel_display_suspend(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_atomic_state *state;
- int ret;
-
- if (!HAS_DISPLAY(dev_priv))
- return 0;
-
- state = drm_atomic_helper_suspend(dev);
- ret = PTR_ERR_OR_ZERO(state);
- if (ret)
- drm_err(&dev_priv->drm, "Suspending crtc's failed with %i\n",
- ret);
- else
- dev_priv->display.restore.modeset_state = state;
- return ret;
-}
-
void intel_encoder_destroy(struct drm_encoder *encoder)
{
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
@@ -2575,7 +2404,7 @@ intel_link_compute_m_n(u16 bits_per_pixel, int nlanes,
0x80000);
}
-static void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv)
+void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv)
{
/*
* There may be no VBT; and if the BIOS enabled SSC we can
@@ -2912,6 +2741,9 @@ void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
val |= TRANSCONF_GAMMA_MODE(crtc_state->gamma_mode);
+ if (crtc_state->wgc_enable)
+ val |= TRANSCONF_WGC_ENABLE;
+
val |= TRANSCONF_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
intel_de_write(dev_priv, TRANSCONF(cpu_transcoder), val);
@@ -2931,6 +2763,7 @@ static void i9xx_get_pfit_config(struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum pipe pipe;
u32 tmp;
if (!i9xx_has_pfit(dev_priv))
@@ -2941,13 +2774,13 @@ static void i9xx_get_pfit_config(struct intel_crtc_state *crtc_state)
return;
/* Check whether the pfit is attached to our pipe. */
- if (DISPLAY_VER(dev_priv) < 4) {
- if (crtc->pipe != PIPE_B)
- return;
- } else {
- if ((tmp & PFIT_PIPE_MASK) != (crtc->pipe << PFIT_PIPE_SHIFT))
- return;
- }
+ if (DISPLAY_VER(dev_priv) >= 4)
+ pipe = REG_FIELD_GET(PFIT_PIPE_MASK, tmp);
+ else
+ pipe = PIPE_B;
+
+ if (pipe != crtc->pipe)
+ return;
crtc_state->gmch_pfit.control = tmp;
crtc_state->gmch_pfit.pgm_ratios =
@@ -3069,6 +2902,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
return false;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
+ pipe_config->sink_format = pipe_config->output_format;
pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
pipe_config->shared_dpll = NULL;
@@ -3104,6 +2938,10 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
pipe_config->framestart_delay = REG_FIELD_GET(TRANSCONF_FRAME_START_DELAY_MASK, tmp) + 1;
+ if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+ (tmp & TRANSCONF_WGC_ENABLE))
+ pipe_config->wgc_enable = true;
+
if (IS_CHERRYVIEW(dev_priv))
pipe_config->cgm_mode = intel_de_read(dev_priv,
CGM_PIPE_MODE(crtc->pipe));
@@ -3406,73 +3244,39 @@ void intel_cpu_transcoder_get_m2_n2(struct intel_crtc *crtc,
PIPE_LINK_M2(transcoder), PIPE_LINK_N2(transcoder));
}
-static void ilk_get_pfit_pos_size(struct intel_crtc_state *crtc_state,
- u32 pos, u32 size)
-{
- drm_rect_init(&crtc_state->pch_pfit.dst,
- pos >> 16, pos & 0xffff,
- size >> 16, size & 0xffff);
-}
-
-static void skl_get_pfit_config(struct intel_crtc_state *crtc_state)
-{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
- int id = -1;
- int i;
-
- /* find scaler attached to this pipe */
- for (i = 0; i < crtc->num_scalers; i++) {
- u32 ctl, pos, size;
-
- ctl = intel_de_read(dev_priv, SKL_PS_CTRL(crtc->pipe, i));
- if ((ctl & (PS_SCALER_EN | PS_PLANE_SEL_MASK)) != PS_SCALER_EN)
- continue;
-
- id = i;
- crtc_state->pch_pfit.enabled = true;
-
- pos = intel_de_read(dev_priv, SKL_PS_WIN_POS(crtc->pipe, i));
- size = intel_de_read(dev_priv, SKL_PS_WIN_SZ(crtc->pipe, i));
-
- ilk_get_pfit_pos_size(crtc_state, pos, size);
-
- scaler_state->scalers[i].in_use = true;
- break;
- }
-
- scaler_state->scaler_id = id;
- if (id >= 0)
- scaler_state->scaler_users |= (1 << SKL_CRTC_INDEX);
- else
- scaler_state->scaler_users &= ~(1 << SKL_CRTC_INDEX);
-}
-
static void ilk_get_pfit_config(struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 ctl, pos, size;
+ enum pipe pipe;
ctl = intel_de_read(dev_priv, PF_CTL(crtc->pipe));
if ((ctl & PF_ENABLE) == 0)
return;
+ if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv))
+ pipe = REG_FIELD_GET(PF_PIPE_SEL_MASK_IVB, ctl);
+ else
+ pipe = crtc->pipe;
+
crtc_state->pch_pfit.enabled = true;
pos = intel_de_read(dev_priv, PF_WIN_POS(crtc->pipe));
size = intel_de_read(dev_priv, PF_WIN_SZ(crtc->pipe));
- ilk_get_pfit_pos_size(crtc_state, pos, size);
+ drm_rect_init(&crtc_state->pch_pfit.dst,
+ REG_FIELD_GET(PF_WIN_XPOS_MASK, pos),
+ REG_FIELD_GET(PF_WIN_YPOS_MASK, pos),
+ REG_FIELD_GET(PF_WIN_XSIZE_MASK, size),
+ REG_FIELD_GET(PF_WIN_YSIZE_MASK, size));
/*
* We currently do not free assignements of panel fitters on
* ivb/hsw (since we don't use the higher upscaling modes which
* differentiates them) so just WARN about this case for now.
*/
- drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) == 7 &&
- (ctl & PF_PIPE_SEL_MASK_IVB) != PF_PIPE_SEL_IVB(crtc->pipe));
+ drm_WARN_ON(&dev_priv->drm, pipe != crtc->pipe);
}
static bool ilk_get_pipe_config(struct intel_crtc *crtc,
@@ -3528,6 +3332,8 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc,
break;
}
+ pipe_config->sink_format = pipe_config->output_format;
+
pipe_config->gamma_mode = REG_FIELD_GET(TRANSCONF_GAMMA_MODE_MASK_ILK, tmp);
pipe_config->framestart_delay = REG_FIELD_GET(TRANSCONF_FRAME_START_DELAY_MASK, tmp) + 1;
@@ -3568,7 +3374,7 @@ static u8 bigjoiner_pipes(struct drm_i915_private *i915)
else
pipes = 0;
- return pipes & RUNTIME_INFO(i915)->pipe_mask;
+ return pipes & DISPLAY_RUNTIME_INFO(i915)->pipe_mask;
}
static bool transcoder_ddi_func_is_enabled(struct drm_i915_private *dev_priv,
@@ -3909,7 +3715,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
intel_get_transcoder_timings(crtc, pipe_config);
if (HAS_VRR(dev_priv) && !transcoder_is_dsi(pipe_config->cpu_transcoder))
- intel_vrr_get_config(crtc, pipe_config);
+ intel_vrr_get_config(pipe_config);
intel_get_pipe_src_size(crtc, pipe_config);
@@ -3926,6 +3732,8 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
bdw_get_pipe_misc_output_format(crtc);
}
+ pipe_config->sink_format = pipe_config->output_format;
+
pipe_config->gamma_mode = intel_de_read(dev_priv,
GAMMA_MODE(crtc->pipe));
@@ -3955,7 +3763,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
if (intel_display_power_get_in_set_if_enabled(dev_priv, &crtc->hw_readout_power_domains,
POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe))) {
if (DISPLAY_VER(dev_priv) >= 9)
- skl_get_pfit_config(pipe_config);
+ skl_scaler_get_config(pipe_config);
else
ilk_get_pfit_config(pipe_config);
}
@@ -4003,218 +3811,6 @@ bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state)
return true;
}
-/* VESA 640x480x72Hz mode to set on the pipe */
-static const struct drm_display_mode load_detect_mode = {
- DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
- 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-};
-
-static int intel_modeset_disable_planes(struct drm_atomic_state *state,
- struct drm_crtc *crtc)
-{
- struct drm_plane *plane;
- struct drm_plane_state *plane_state;
- int ret, i;
-
- ret = drm_atomic_add_affected_planes(state, crtc);
- if (ret)
- return ret;
-
- for_each_new_plane_in_state(state, plane, plane_state, i) {
- if (plane_state->crtc != crtc)
- continue;
-
- ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
- if (ret)
- return ret;
-
- drm_atomic_set_fb_for_plane(plane_state, NULL);
- }
-
- return 0;
-}
-
-int intel_get_load_detect_pipe(struct drm_connector *connector,
- struct intel_load_detect_pipe *old,
- struct drm_modeset_acquire_ctx *ctx)
-{
- struct intel_encoder *encoder =
- intel_attached_encoder(to_intel_connector(connector));
- struct intel_crtc *possible_crtc;
- struct intel_crtc *crtc = NULL;
- struct drm_device *dev = encoder->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_mode_config *config = &dev->mode_config;
- struct drm_atomic_state *state = NULL, *restore_state = NULL;
- struct drm_connector_state *connector_state;
- struct intel_crtc_state *crtc_state;
- int ret;
-
- drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
- connector->base.id, connector->name,
- encoder->base.base.id, encoder->base.name);
-
- old->restore_state = NULL;
-
- drm_WARN_ON(dev, !drm_modeset_is_locked(&config->connection_mutex));
-
- /*
- * Algorithm gets a little messy:
- *
- * - if the connector already has an assigned crtc, use it (but make
- * sure it's on first)
- *
- * - try to find the first unused crtc that can drive this connector,
- * and use that if we find one
- */
-
- /* See if we already have a CRTC for this connector */
- if (connector->state->crtc) {
- crtc = to_intel_crtc(connector->state->crtc);
-
- ret = drm_modeset_lock(&crtc->base.mutex, ctx);
- if (ret)
- goto fail;
-
- /* Make sure the crtc and connector are running */
- goto found;
- }
-
- /* Find an unused one (if possible) */
- for_each_intel_crtc(dev, possible_crtc) {
- if (!(encoder->base.possible_crtcs &
- drm_crtc_mask(&possible_crtc->base)))
- continue;
-
- ret = drm_modeset_lock(&possible_crtc->base.mutex, ctx);
- if (ret)
- goto fail;
-
- if (possible_crtc->base.state->enable) {
- drm_modeset_unlock(&possible_crtc->base.mutex);
- continue;
- }
-
- crtc = possible_crtc;
- break;
- }
-
- /*
- * If we didn't find an unused CRTC, don't use any.
- */
- if (!crtc) {
- drm_dbg_kms(&dev_priv->drm,
- "no pipe available for load-detect\n");
- ret = -ENODEV;
- goto fail;
- }
-
-found:
- state = drm_atomic_state_alloc(dev);
- restore_state = drm_atomic_state_alloc(dev);
- if (!state || !restore_state) {
- ret = -ENOMEM;
- goto fail;
- }
-
- state->acquire_ctx = ctx;
- restore_state->acquire_ctx = ctx;
-
- connector_state = drm_atomic_get_connector_state(state, connector);
- if (IS_ERR(connector_state)) {
- ret = PTR_ERR(connector_state);
- goto fail;
- }
-
- ret = drm_atomic_set_crtc_for_connector(connector_state, &crtc->base);
- if (ret)
- goto fail;
-
- crtc_state = intel_atomic_get_crtc_state(state, crtc);
- if (IS_ERR(crtc_state)) {
- ret = PTR_ERR(crtc_state);
- goto fail;
- }
-
- crtc_state->uapi.active = true;
-
- ret = drm_atomic_set_mode_for_crtc(&crtc_state->uapi,
- &load_detect_mode);
- if (ret)
- goto fail;
-
- ret = intel_modeset_disable_planes(state, &crtc->base);
- if (ret)
- goto fail;
-
- ret = PTR_ERR_OR_ZERO(drm_atomic_get_connector_state(restore_state, connector));
- if (!ret)
- ret = PTR_ERR_OR_ZERO(drm_atomic_get_crtc_state(restore_state, &crtc->base));
- if (!ret)
- ret = drm_atomic_add_affected_planes(restore_state, &crtc->base);
- if (ret) {
- drm_dbg_kms(&dev_priv->drm,
- "Failed to create a copy of old state to restore: %i\n",
- ret);
- goto fail;
- }
-
- ret = drm_atomic_commit(state);
- if (ret) {
- drm_dbg_kms(&dev_priv->drm,
- "failed to set mode on load-detect pipe\n");
- goto fail;
- }
-
- old->restore_state = restore_state;
- drm_atomic_state_put(state);
-
- /* let the connector get through one full cycle before testing */
- intel_crtc_wait_for_next_vblank(crtc);
-
- return true;
-
-fail:
- if (state) {
- drm_atomic_state_put(state);
- state = NULL;
- }
- if (restore_state) {
- drm_atomic_state_put(restore_state);
- restore_state = NULL;
- }
-
- if (ret == -EDEADLK)
- return ret;
-
- return false;
-}
-
-void intel_release_load_detect_pipe(struct drm_connector *connector,
- struct intel_load_detect_pipe *old,
- struct drm_modeset_acquire_ctx *ctx)
-{
- struct intel_encoder *intel_encoder =
- intel_attached_encoder(to_intel_connector(connector));
- struct drm_i915_private *i915 = to_i915(intel_encoder->base.dev);
- struct drm_encoder *encoder = &intel_encoder->base;
- struct drm_atomic_state *state = old->restore_state;
- int ret;
-
- drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
- connector->base.id, connector->name,
- encoder->base.id, encoder->name);
-
- if (!state)
- return;
-
- ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
- if (ret)
- drm_dbg_kms(&i915->drm,
- "Couldn't release load detect pipe: %i\n", ret);
- drm_atomic_state_put(state);
-}
-
static int i9xx_pll_refclk(struct drm_device *dev,
const struct intel_crtc_state *pipe_config)
{
@@ -5277,7 +4873,7 @@ pipe_config_infoframe_mismatch(struct drm_i915_private *dev_priv,
return;
drm_dbg_kms(&dev_priv->drm,
- "fastset mismatch in %s infoframe\n", name);
+ "fastset requirement not met in %s infoframe\n", name);
drm_dbg_kms(&dev_priv->drm, "expected:\n");
hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, a);
drm_dbg_kms(&dev_priv->drm, "found:\n");
@@ -5302,7 +4898,7 @@ pipe_config_dp_vsc_sdp_mismatch(struct drm_i915_private *dev_priv,
return;
drm_dbg_kms(&dev_priv->drm,
- "fastset mismatch in %s dp sdp\n", name);
+ "fastset requirement not met in %s dp sdp\n", name);
drm_dbg_kms(&dev_priv->drm, "expected:\n");
drm_dp_vsc_sdp_log(KERN_DEBUG, dev_priv->drm.dev, a);
drm_dbg_kms(&dev_priv->drm, "found:\n");
@@ -5343,7 +4939,7 @@ pipe_config_buffer_mismatch(struct drm_i915_private *dev_priv,
len = memcmp_diff_len(a, b, len);
drm_dbg_kms(&dev_priv->drm,
- "fastset mismatch in %s buffer\n", name);
+ "fastset requirement not met in %s buffer\n", name);
print_hex_dump(KERN_DEBUG, "expected: ", DUMP_PREFIX_NONE,
16, 0, a, len, false);
print_hex_dump(KERN_DEBUG, "found: ", DUMP_PREFIX_NONE,
@@ -5374,7 +4970,7 @@ pipe_config_mismatch(bool fastset, const struct intel_crtc *crtc,
if (fastset)
drm_dbg_kms(&i915->drm,
- "[CRTC:%d:%s] fastset mismatch in %s %pV\n",
+ "[CRTC:%d:%s] fastset requirement not met in %s %pV\n",
crtc->base.base.id, crtc->base.name, name, &vaf);
else
drm_err(&i915->drm, "[CRTC:%d:%s] mismatch in %s %pV\n",
@@ -5581,6 +5177,24 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
} \
} while (0)
+#define PIPE_CONF_CHECK_CSC(name) do { \
+ PIPE_CONF_CHECK_X(name.preoff[0]); \
+ PIPE_CONF_CHECK_X(name.preoff[1]); \
+ PIPE_CONF_CHECK_X(name.preoff[2]); \
+ PIPE_CONF_CHECK_X(name.coeff[0]); \
+ PIPE_CONF_CHECK_X(name.coeff[1]); \
+ PIPE_CONF_CHECK_X(name.coeff[2]); \
+ PIPE_CONF_CHECK_X(name.coeff[3]); \
+ PIPE_CONF_CHECK_X(name.coeff[4]); \
+ PIPE_CONF_CHECK_X(name.coeff[5]); \
+ PIPE_CONF_CHECK_X(name.coeff[6]); \
+ PIPE_CONF_CHECK_X(name.coeff[7]); \
+ PIPE_CONF_CHECK_X(name.coeff[8]); \
+ PIPE_CONF_CHECK_X(name.postoff[0]); \
+ PIPE_CONF_CHECK_X(name.postoff[1]); \
+ PIPE_CONF_CHECK_X(name.postoff[2]); \
+} while (0)
+
#define PIPE_CONF_QUIRK(quirk) \
((current_config->quirks | pipe_config->quirks) & (quirk))
@@ -5671,6 +5285,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_X(csc_mode);
PIPE_CONF_CHECK_BOOL(gamma_enable);
PIPE_CONF_CHECK_BOOL(csc_enable);
+ PIPE_CONF_CHECK_BOOL(wgc_enable);
PIPE_CONF_CHECK_I(linetime);
PIPE_CONF_CHECK_I(ips_linetime);
@@ -5678,6 +5293,9 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_COLOR_LUT(pre_csc_lut, true);
PIPE_CONF_CHECK_COLOR_LUT(post_csc_lut, false);
+ PIPE_CONF_CHECK_CSC(csc);
+ PIPE_CONF_CHECK_CSC(output_csc);
+
if (current_config->active_planes) {
PIPE_CONF_CHECK_BOOL(has_psr);
PIPE_CONF_CHECK_BOOL(has_psr2);
@@ -5764,7 +5382,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(splitter.link_count);
PIPE_CONF_CHECK_I(splitter.pixel_overlap);
- PIPE_CONF_CHECK_BOOL(vrr.enable);
+ if (!fastset)
+ PIPE_CONF_CHECK_BOOL(vrr.enable);
PIPE_CONF_CHECK_I(vrr.vmin);
PIPE_CONF_CHECK_I(vrr.vmax);
PIPE_CONF_CHECK_I(vrr.flipline);
@@ -5940,8 +5559,13 @@ static int intel_modeset_checks(struct intel_atomic_state *state)
static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_state,
struct intel_crtc_state *new_crtc_state)
{
- if (!intel_pipe_config_compare(old_crtc_state, new_crtc_state, true))
+ struct drm_i915_private *i915 = to_i915(old_crtc_state->uapi.crtc->dev);
+
+ if (!intel_pipe_config_compare(old_crtc_state, new_crtc_state, true)) {
+ drm_dbg_kms(&i915->drm, "fastset requirement not met, forcing full modeset\n");
+
return;
+ }
new_crtc_state->uapi.mode_changed = false;
if (!intel_crtc_needs_modeset(new_crtc_state))
@@ -5994,7 +5618,7 @@ static int intel_crtc_add_bigjoiner_planes(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_crtc *other)
{
- const struct intel_plane_state *plane_state;
+ const struct intel_plane_state __maybe_unused *plane_state;
struct intel_plane *plane;
u8 plane_ids = 0;
int i;
@@ -6037,7 +5661,7 @@ static int intel_atomic_check_planes(struct intel_atomic_state *state)
{
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_crtc_state *old_crtc_state, *new_crtc_state;
- struct intel_plane_state *plane_state;
+ struct intel_plane_state __maybe_unused *plane_state;
struct intel_plane *plane;
struct intel_crtc *crtc;
int i, ret;
@@ -6092,7 +5716,7 @@ static int intel_atomic_check_planes(struct intel_atomic_state *state)
static int intel_atomic_check_crtcs(struct intel_atomic_state *state)
{
- struct intel_crtc_state *crtc_state;
+ struct intel_crtc_state __maybe_unused *crtc_state;
struct intel_crtc *crtc;
int i;
@@ -6380,6 +6004,22 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in
* this selectively if required.
*/
switch (new_plane_state->hw.fb->modifier) {
+ case DRM_FORMAT_MOD_LINEAR:
+ /*
+ * FIXME: Async on Linear buffer is supported on ICL as
+ * but with additional alignment and fbc restrictions
+ * need to be taken care of. These aren't applicable for
+ * gen12+.
+ */
+ if (DISPLAY_VER(i915) < 12) {
+ drm_dbg_kms(&i915->drm,
+ "[PLANE:%d:%s] Modifier 0x%llx does not support async flip on display ver %d\n",
+ plane->base.base.id, plane->base.name,
+ new_plane_state->hw.fb->modifier, DISPLAY_VER(i915));
+ return -EINVAL;
+ }
+ break;
+
case I915_FORMAT_MOD_X_TILED:
case I915_FORMAT_MOD_Y_TILED:
case I915_FORMAT_MOD_Yf_TILED:
@@ -6387,8 +6027,9 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in
break;
default:
drm_dbg_kms(&i915->drm,
- "[PLANE:%d:%s] Modifier does not support async flips\n",
- plane->base.base.id, plane->base.name);
+ "[PLANE:%d:%s] Modifier 0x%llx does not support async flip\n",
+ plane->base.base.id, plane->base.name,
+ new_plane_state->hw.fb->modifier);
return -EINVAL;
}
@@ -6544,6 +6185,13 @@ int intel_atomic_check(struct drm_device *dev,
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
+ /*
+ * crtc's state no longer considered to be inherited
+ * after the first userspace/client initiated commit.
+ */
+ if (!state->internal)
+ new_crtc_state->inherited = false;
+
if (new_crtc_state->inherited != old_crtc_state->inherited)
new_crtc_state->uapi.mode_changed = true;
@@ -6707,6 +6355,10 @@ int intel_atomic_check(struct drm_device *dev,
return ret;
}
+ ret = intel_pmdemand_atomic_check(state);
+ if (ret)
+ goto fail;
+
ret = intel_atomic_check_crtcs(state);
if (ret)
goto fail;
@@ -6889,7 +6541,8 @@ static void intel_enable_crtc(struct intel_atomic_state *state,
if (!intel_crtc_needs_modeset(new_crtc_state))
return;
- intel_crtc_update_active_timings(new_crtc_state);
+ /* VRR will be enable later, if required */
+ intel_crtc_update_active_timings(new_crtc_state, false);
dev_priv->display.funcs.display->crtc_enable(state, crtc);
@@ -6916,6 +6569,12 @@ static void intel_update_crtc(struct intel_atomic_state *state,
intel_dpt_configure(crtc);
}
+ if (vrr_enabling(old_crtc_state, new_crtc_state)) {
+ intel_vrr_enable(new_crtc_state);
+ intel_crtc_update_active_timings(new_crtc_state,
+ new_crtc_state->vrr.enable);
+ }
+
if (!modeset) {
if (new_crtc_state->preload_luts &&
intel_crtc_needs_color_update(new_crtc_state))
@@ -7189,7 +6848,7 @@ static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv)
drm_atomic_state_put(&state->base);
}
-static void intel_atomic_helper_free_state_worker(struct work_struct *work)
+void intel_atomic_helper_free_state_worker(struct work_struct *work)
{
struct drm_i915_private *dev_priv =
container_of(work, typeof(*dev_priv), display.atomic_helper.free_work);
@@ -7321,6 +6980,12 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
* 7. New _arm() registers are finally written
* 8. Hardware finally latches a complete set of new
* register values, and subsequent frames will be OK again
+ *
+ * Also note that due to the pipe CSC hardware issues on
+ * SKL/GLK DC states must remain off until the pipe CSC
+ * state readout has happened. Otherwise we risk corrupting
+ * the CSC latched register values with the readout (see
+ * skl_read_csc() and skl_color_commit_noarm()).
*/
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DC_OFF);
@@ -7339,6 +7004,14 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
crtc->config = new_crtc_state;
+ /*
+ * In XE_LPD+ Pmdemand combines many parameters such as voltage index,
+ * plls, cdclk frequency, QGV point selection parameter etc. Voltage
+ * index, cdclk/ddiclk frequencies are supposed to be configured before
+ * the cdclk config is set.
+ */
+ intel_pmdemand_pre_plane_update(state);
+
if (state->modeset) {
drm_atomic_helper_update_legacy_modeset_state(dev, &state->base);
@@ -7458,6 +7131,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
intel_verify_planes(state);
intel_sagv_post_plane_update(state);
+ intel_pmdemand_post_plane_update(state);
drm_atomic_helper_commit_hw_done(&state->base);
@@ -7506,11 +7180,12 @@ intel_atomic_commit_ready(struct i915_sw_fence *fence,
break;
case FENCE_FREE:
{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_atomic_helper *helper =
- &to_i915(state->base.dev)->display.atomic_helper;
+ &i915->display.atomic_helper;
if (llist_add(&state->freed, &helper->free_list))
- schedule_work(&helper->free_work);
+ queue_work(i915->unordered_wq, &helper->free_work);
break;
}
}
@@ -7531,9 +7206,8 @@ static void intel_atomic_track_fbs(struct intel_atomic_state *state)
plane->frontbuffer_bit);
}
-static int intel_atomic_commit(struct drm_device *dev,
- struct drm_atomic_state *_state,
- bool nonblock)
+int intel_atomic_commit(struct drm_device *dev, struct drm_atomic_state *_state,
+ bool nonblock)
{
struct intel_atomic_state *state = to_intel_atomic_state(_state);
struct drm_i915_private *dev_priv = to_i915(dev);
@@ -7635,19 +7309,6 @@ void intel_plane_destroy(struct drm_plane *plane)
kfree(to_intel_plane(plane));
}
-static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
-{
- struct intel_plane *plane;
-
- for_each_intel_plane(&dev_priv->drm, plane) {
- struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv,
- plane->pipe);
-
- plane->base.possible_crtcs = drm_crtc_mask(&crtc->base);
- }
-}
-
-
int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
@@ -7727,7 +7388,7 @@ static bool intel_ddi_crt_present(struct drm_i915_private *dev_priv)
return true;
}
-static void intel_setup_outputs(struct drm_i915_private *dev_priv)
+void intel_setup_outputs(struct drm_i915_private *dev_priv)
{
struct intel_encoder *encoder;
bool dpd_is_edp = false;
@@ -7737,7 +7398,14 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
- if (IS_DG2(dev_priv)) {
+ if (IS_METEORLAKE(dev_priv)) {
+ intel_ddi_init(dev_priv, PORT_A);
+ intel_ddi_init(dev_priv, PORT_B);
+ intel_ddi_init(dev_priv, PORT_TC1);
+ intel_ddi_init(dev_priv, PORT_TC2);
+ intel_ddi_init(dev_priv, PORT_TC3);
+ intel_ddi_init(dev_priv, PORT_TC4);
+ } else if (IS_DG2(dev_priv)) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
intel_ddi_init(dev_priv, PORT_C);
@@ -7979,9 +7647,8 @@ static int max_dotclock(struct drm_i915_private *i915)
return max_dotclock;
}
-static enum drm_mode_status
-intel_mode_valid(struct drm_device *dev,
- const struct drm_display_mode *mode)
+enum drm_mode_status intel_mode_valid(struct drm_device *dev,
+ const struct drm_display_mode *mode)
{
struct drm_i915_private *dev_priv = to_i915(dev);
int hdisplay_max, htotal_max;
@@ -8121,18 +7788,6 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
return MODE_OK;
}
-static const struct drm_mode_config_funcs intel_mode_funcs = {
- .fb_create = intel_user_framebuffer_create,
- .get_format_info = intel_fb_get_format_info,
- .output_poll_changed = intel_fbdev_output_poll_changed,
- .mode_valid = intel_mode_valid,
- .atomic_check = intel_atomic_check,
- .atomic_commit = intel_atomic_commit,
- .atomic_state_alloc = intel_atomic_state_alloc,
- .atomic_state_clear = intel_atomic_state_clear,
- .atomic_state_free = intel_atomic_state_free,
-};
-
static const struct intel_display_funcs skl_display_funcs = {
.get_pipe_config = hsw_get_pipe_config,
.crtc_enable = hsw_crtc_enable,
@@ -8179,15 +7834,6 @@ static const struct intel_display_funcs i9xx_display_funcs = {
*/
void intel_init_display_hooks(struct drm_i915_private *dev_priv)
{
- if (!HAS_DISPLAY(dev_priv))
- return;
-
- intel_color_init_hooks(dev_priv);
- intel_init_cdclk_hooks(dev_priv);
- intel_audio_hooks_init(dev_priv);
-
- intel_dpll_init_clock_hook(dev_priv);
-
if (DISPLAY_VER(dev_priv) >= 9) {
dev_priv->display.funcs.display = &skl_display_funcs;
} else if (HAS_DDI(dev_priv)) {
@@ -8200,25 +7846,9 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
} else {
dev_priv->display.funcs.display = &i9xx_display_funcs;
}
-
- intel_fdi_init_hook(dev_priv);
-}
-
-void intel_modeset_init_hw(struct drm_i915_private *i915)
-{
- struct intel_cdclk_state *cdclk_state;
-
- if (!HAS_DISPLAY(i915))
- return;
-
- cdclk_state = to_intel_cdclk_state(i915->display.cdclk.obj.state);
-
- intel_update_cdclk(i915);
- intel_cdclk_dump_config(i915, &i915->display.cdclk.hw, "Current CDCLK");
- cdclk_state->logical = cdclk_state->actual = i915->display.cdclk.hw;
}
-static int intel_initial_commit(struct drm_device *dev)
+int intel_initial_commit(struct drm_device *dev)
{
struct drm_atomic_state *state = NULL;
struct drm_modeset_acquire_ctx ctx;
@@ -8231,9 +7861,10 @@ static int intel_initial_commit(struct drm_device *dev)
drm_modeset_acquire_init(&ctx, 0);
-retry:
state->acquire_ctx = &ctx;
+ to_intel_atomic_state(state)->internal = true;
+retry:
for_each_intel_crtc(dev, crtc) {
struct intel_crtc_state *crtc_state =
intel_atomic_get_crtc_state(state, crtc);
@@ -8246,15 +7877,6 @@ retry:
if (crtc_state->hw.active) {
struct intel_encoder *encoder;
- /*
- * We've not yet detected sink capabilities
- * (audio,infoframes,etc.) and thus we don't want to
- * force a full state recomputation yet. We want that to
- * happen only for the first real commit from userspace.
- * So preserve the inherited flag for the time being.
- */
- crtc_state->inherited = true;
-
ret = drm_atomic_add_affected_planes(state, &crtc->base);
if (ret)
goto out;
@@ -8297,246 +7919,6 @@ out:
return ret;
}
-static const struct drm_mode_config_helper_funcs intel_mode_config_funcs = {
- .atomic_commit_setup = drm_dp_mst_atomic_setup_commit,
-};
-
-static void intel_mode_config_init(struct drm_i915_private *i915)
-{
- struct drm_mode_config *mode_config = &i915->drm.mode_config;
-
- drm_mode_config_init(&i915->drm);
- INIT_LIST_HEAD(&i915->display.global.obj_list);
-
- mode_config->min_width = 0;
- mode_config->min_height = 0;
-
- mode_config->preferred_depth = 24;
- mode_config->prefer_shadow = 1;
-
- mode_config->funcs = &intel_mode_funcs;
- mode_config->helper_private = &intel_mode_config_funcs;
-
- mode_config->async_page_flip = HAS_ASYNC_FLIPS(i915);
-
- /*
- * Maximum framebuffer dimensions, chosen to match
- * the maximum render engine surface size on gen4+.
- */
- if (DISPLAY_VER(i915) >= 7) {
- mode_config->max_width = 16384;
- mode_config->max_height = 16384;
- } else if (DISPLAY_VER(i915) >= 4) {
- mode_config->max_width = 8192;
- mode_config->max_height = 8192;
- } else if (DISPLAY_VER(i915) == 3) {
- mode_config->max_width = 4096;
- mode_config->max_height = 4096;
- } else {
- mode_config->max_width = 2048;
- mode_config->max_height = 2048;
- }
-
- if (IS_I845G(i915) || IS_I865G(i915)) {
- mode_config->cursor_width = IS_I845G(i915) ? 64 : 512;
- mode_config->cursor_height = 1023;
- } else if (IS_I830(i915) || IS_I85X(i915) ||
- IS_I915G(i915) || IS_I915GM(i915)) {
- mode_config->cursor_width = 64;
- mode_config->cursor_height = 64;
- } else {
- mode_config->cursor_width = 256;
- mode_config->cursor_height = 256;
- }
-}
-
-static void intel_mode_config_cleanup(struct drm_i915_private *i915)
-{
- intel_atomic_global_obj_cleanup(i915);
- drm_mode_config_cleanup(&i915->drm);
-}
-
-/* part #1: call before irq install */
-int intel_modeset_init_noirq(struct drm_i915_private *i915)
-{
- int ret;
-
- if (i915_inject_probe_failure(i915))
- return -ENODEV;
-
- if (HAS_DISPLAY(i915)) {
- ret = drm_vblank_init(&i915->drm,
- INTEL_NUM_PIPES(i915));
- if (ret)
- return ret;
- }
-
- intel_bios_init(i915);
-
- ret = intel_vga_register(i915);
- if (ret)
- goto cleanup_bios;
-
- /* FIXME: completely on the wrong abstraction layer */
- ret = intel_power_domains_init(i915);
- if (ret < 0)
- goto cleanup_vga;
-
- intel_power_domains_init_hw(i915, false);
-
- if (!HAS_DISPLAY(i915))
- return 0;
-
- intel_dmc_init(i915);
-
- i915->display.wq.modeset = alloc_ordered_workqueue("i915_modeset", 0);
- i915->display.wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI |
- WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE);
-
- intel_mode_config_init(i915);
-
- ret = intel_cdclk_init(i915);
- if (ret)
- goto cleanup_vga_client_pw_domain_dmc;
-
- ret = intel_color_init(i915);
- if (ret)
- goto cleanup_vga_client_pw_domain_dmc;
-
- ret = intel_dbuf_init(i915);
- if (ret)
- goto cleanup_vga_client_pw_domain_dmc;
-
- ret = intel_bw_init(i915);
- if (ret)
- goto cleanup_vga_client_pw_domain_dmc;
-
- init_llist_head(&i915->display.atomic_helper.free_list);
- INIT_WORK(&i915->display.atomic_helper.free_work,
- intel_atomic_helper_free_state_worker);
-
- intel_init_quirks(i915);
-
- intel_fbc_init(i915);
-
- return 0;
-
-cleanup_vga_client_pw_domain_dmc:
- intel_dmc_fini(i915);
- intel_power_domains_driver_remove(i915);
-cleanup_vga:
- intel_vga_unregister(i915);
-cleanup_bios:
- intel_bios_driver_remove(i915);
-
- return ret;
-}
-
-/* part #2: call after irq install, but before gem init */
-int intel_modeset_init_nogem(struct drm_i915_private *i915)
-{
- struct drm_device *dev = &i915->drm;
- enum pipe pipe;
- struct intel_crtc *crtc;
- int ret;
-
- if (!HAS_DISPLAY(i915))
- return 0;
-
- intel_wm_init(i915);
-
- intel_panel_sanitize_ssc(i915);
-
- intel_pps_setup(i915);
-
- intel_gmbus_setup(i915);
-
- drm_dbg_kms(&i915->drm, "%d display pipe%s available.\n",
- INTEL_NUM_PIPES(i915),
- INTEL_NUM_PIPES(i915) > 1 ? "s" : "");
-
- for_each_pipe(i915, pipe) {
- ret = intel_crtc_init(i915, pipe);
- if (ret) {
- intel_mode_config_cleanup(i915);
- return ret;
- }
- }
-
- intel_plane_possible_crtcs_init(i915);
- intel_shared_dpll_init(i915);
- intel_fdi_pll_freq_update(i915);
-
- intel_update_czclk(i915);
- intel_modeset_init_hw(i915);
- intel_dpll_update_ref_clks(i915);
-
- intel_hdcp_component_init(i915);
-
- if (i915->display.cdclk.max_cdclk_freq == 0)
- intel_update_max_cdclk(i915);
-
- intel_hti_init(i915);
-
- /* Just disable it once at startup */
- intel_vga_disable(i915);
- intel_setup_outputs(i915);
-
- drm_modeset_lock_all(dev);
- intel_modeset_setup_hw_state(i915, dev->mode_config.acquire_ctx);
- intel_acpi_assign_connector_fwnodes(i915);
- drm_modeset_unlock_all(dev);
-
- for_each_intel_crtc(dev, crtc) {
- if (!to_intel_crtc_state(crtc->base.state)->uapi.active)
- continue;
- intel_crtc_initial_plane_config(crtc);
- }
-
- /*
- * Make sure hardware watermarks really match the state we read out.
- * Note that we need to do this after reconstructing the BIOS fb's
- * since the watermark calculation done here will use pstate->fb.
- */
- if (!HAS_GMCH(i915))
- ilk_wm_sanitize(i915);
-
- return 0;
-}
-
-/* part #3: call after gem init */
-int intel_modeset_init(struct drm_i915_private *i915)
-{
- int ret;
-
- if (!HAS_DISPLAY(i915))
- return 0;
-
- /*
- * Force all active planes to recompute their states. So that on
- * mode_setcrtc after probe, all the intel_plane_state variables
- * are already calculated and there is no assert_plane warnings
- * during bootup.
- */
- ret = intel_initial_commit(&i915->drm);
- if (ret)
- drm_dbg_kms(&i915->drm, "Initial modeset failed, %d\n", ret);
-
- intel_overlay_setup(i915);
-
- ret = intel_fbdev_init(&i915->drm);
- if (ret)
- return ret;
-
- /* Only enable hotplug handling once the fbdev is fully set up. */
- intel_hpd_init(i915);
- intel_hpd_poll_disable(i915);
-
- skl_watermark_ipc_init(i915);
-
- return 0;
-}
-
void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
{
struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
@@ -8644,45 +8026,7 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
intel_de_posting_read(dev_priv, DPLL(pipe));
}
-void intel_display_resume(struct drm_device *dev)
-{
- struct drm_i915_private *i915 = to_i915(dev);
- struct drm_atomic_state *state = i915->display.restore.modeset_state;
- struct drm_modeset_acquire_ctx ctx;
- int ret;
-
- if (!HAS_DISPLAY(i915))
- return;
-
- i915->display.restore.modeset_state = NULL;
- if (state)
- state->acquire_ctx = &ctx;
-
- drm_modeset_acquire_init(&ctx, 0);
-
- while (1) {
- ret = drm_modeset_lock_all_ctx(dev, &ctx);
- if (ret != -EDEADLK)
- break;
-
- drm_modeset_backoff(&ctx);
- }
-
- if (!ret)
- ret = __intel_display_resume(i915, state, &ctx);
-
- skl_watermark_ipc_update(i915);
- drm_modeset_drop_locks(&ctx);
- drm_modeset_acquire_fini(&ctx);
-
- if (ret)
- drm_err(&i915->drm,
- "Restoring old state failed with %i\n", ret);
- if (state)
- drm_atomic_state_put(state);
-}
-
-static void intel_hpd_poll_fini(struct drm_i915_private *i915)
+void intel_hpd_poll_fini(struct drm_i915_private *i915)
{
struct intel_connector *connector;
struct drm_connector_list_iter conn_iter;
@@ -8700,144 +8044,6 @@ static void intel_hpd_poll_fini(struct drm_i915_private *i915)
drm_connector_list_iter_end(&conn_iter);
}
-/* part #1: call before irq uninstall */
-void intel_modeset_driver_remove(struct drm_i915_private *i915)
-{
- if (!HAS_DISPLAY(i915))
- return;
-
- flush_workqueue(i915->display.wq.flip);
- flush_workqueue(i915->display.wq.modeset);
-
- flush_work(&i915->display.atomic_helper.free_work);
- drm_WARN_ON(&i915->drm, !llist_empty(&i915->display.atomic_helper.free_list));
-
- /*
- * MST topology needs to be suspended so we don't have any calls to
- * fbdev after it's finalized. MST will be destroyed later as part of
- * drm_mode_config_cleanup()
- */
- intel_dp_mst_suspend(i915);
-}
-
-/* part #2: call after irq uninstall */
-void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915)
-{
- if (!HAS_DISPLAY(i915))
- return;
-
- /*
- * Due to the hpd irq storm handling the hotplug work can re-arm the
- * poll handlers. Hence disable polling after hpd handling is shut down.
- */
- intel_hpd_poll_fini(i915);
-
- /* poll work can call into fbdev, hence clean that up afterwards */
- intel_fbdev_fini(i915);
-
- intel_unregister_dsm_handler();
-
- /* flush any delayed tasks or pending work */
- flush_scheduled_work();
-
- intel_hdcp_component_fini(i915);
-
- intel_mode_config_cleanup(i915);
-
- intel_overlay_cleanup(i915);
-
- intel_gmbus_teardown(i915);
-
- destroy_workqueue(i915->display.wq.flip);
- destroy_workqueue(i915->display.wq.modeset);
-
- intel_fbc_cleanup(i915);
-}
-
-/* part #3: call after gem init */
-void intel_modeset_driver_remove_nogem(struct drm_i915_private *i915)
-{
- intel_dmc_fini(i915);
-
- intel_power_domains_driver_remove(i915);
-
- intel_vga_unregister(i915);
-
- intel_bios_driver_remove(i915);
-}
-
-bool intel_modeset_probe_defer(struct pci_dev *pdev)
-{
- struct drm_privacy_screen *privacy_screen;
-
- /*
- * apple-gmux is needed on dual GPU MacBook Pro
- * to probe the panel if we're the inactive GPU.
- */
- if (vga_switcheroo_client_probe_defer(pdev))
- return true;
-
- /* If the LCD panel has a privacy-screen, wait for it */
- privacy_screen = drm_privacy_screen_get(&pdev->dev, NULL);
- if (IS_ERR(privacy_screen) && PTR_ERR(privacy_screen) == -EPROBE_DEFER)
- return true;
-
- drm_privacy_screen_put(privacy_screen);
-
- return false;
-}
-
-void intel_display_driver_register(struct drm_i915_private *i915)
-{
- if (!HAS_DISPLAY(i915))
- return;
-
- /* Must be done after probing outputs */
- intel_opregion_register(i915);
- intel_acpi_video_register(i915);
-
- intel_audio_init(i915);
-
- intel_display_debugfs_register(i915);
-
- /*
- * Some ports require correctly set-up hpd registers for
- * detection to work properly (leading to ghost connected
- * connector status), e.g. VGA on gm45. Hence we can only set
- * up the initial fbdev config after hpd irqs are fully
- * enabled. We do it last so that the async config cannot run
- * before the connectors are registered.
- */
- intel_fbdev_initial_config_async(i915);
-
- /*
- * We need to coordinate the hotplugs with the asynchronous
- * fbdev configuration, for which we use the
- * fbdev->async_cookie.
- */
- drm_kms_helper_poll_init(&i915->drm);
-}
-
-void intel_display_driver_unregister(struct drm_i915_private *i915)
-{
- if (!HAS_DISPLAY(i915))
- return;
-
- intel_fbdev_unregister(i915);
- intel_audio_deinit(i915);
-
- /*
- * After flushing the fbdev (incl. a late async config which
- * will have delayed queuing of a hotplug event), then flush
- * the hotplug events.
- */
- drm_kms_helper_poll_fini(&i915->drm);
- drm_atomic_helper_shutdown(&i915->drm);
-
- acpi_video_unregister();
- intel_opregion_unregister(i915);
-}
-
bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915)
{
return DISPLAY_VER(i915) >= 6 && i915_vtd_active(i915);
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 287159bdeb0d..c744c021af23 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -56,13 +56,13 @@ struct intel_dp;
struct intel_encoder;
struct intel_initial_plane_config;
struct intel_link_m_n;
-struct intel_load_detect_pipe;
struct intel_plane;
struct intel_plane_state;
struct intel_power_domain_mask;
struct intel_remapped_info;
struct intel_rotation_info;
struct pci_dev;
+struct work_struct;
#define pipe_name(p) ((p) + 'A')
@@ -105,7 +105,7 @@ enum i9xx_plane_id {
};
#define plane_name(p) ((p) + 'A')
-#define sprite_name(p, s) ((p) * RUNTIME_INFO(dev_priv)->num_sprites[(p)] + (s) + 'A')
+#define sprite_name(p, s) ((p) * DISPLAY_RUNTIME_INFO(dev_priv)->num_sprites[(p)] + (s) + 'A')
#define for_each_plane_id_on_crtc(__crtc, __p) \
for ((__p) = PLANE_PRIMARY; (__p) < I915_MAX_PLANES; (__p)++) \
@@ -113,7 +113,7 @@ enum i9xx_plane_id {
#define for_each_dbuf_slice(__dev_priv, __slice) \
for ((__slice) = DBUF_S1; (__slice) < I915_MAX_DBUF_SLICES; (__slice)++) \
- for_each_if(INTEL_INFO(__dev_priv)->display.dbuf.slice_mask & BIT(__slice))
+ for_each_if(INTEL_INFO(__dev_priv)->display->dbuf.slice_mask & BIT(__slice))
#define for_each_dbuf_slice_in_mask(__dev_priv, __slice, __mask) \
for_each_dbuf_slice((__dev_priv), (__slice)) \
@@ -221,7 +221,7 @@ enum phy_fia {
#define for_each_pipe(__dev_priv, __p) \
for ((__p) = 0; (__p) < I915_MAX_PIPES; (__p)++) \
- for_each_if(RUNTIME_INFO(__dev_priv)->pipe_mask & BIT(__p))
+ for_each_if(DISPLAY_RUNTIME_INFO(__dev_priv)->pipe_mask & BIT(__p))
#define for_each_pipe_masked(__dev_priv, __p, __mask) \
for_each_pipe(__dev_priv, __p) \
@@ -229,7 +229,7 @@ enum phy_fia {
#define for_each_cpu_transcoder(__dev_priv, __t) \
for ((__t) = 0; (__t) < I915_MAX_TRANSCODERS; (__t)++) \
- for_each_if (RUNTIME_INFO(__dev_priv)->cpu_transcoder_mask & BIT(__t))
+ for_each_if (DISPLAY_RUNTIME_INFO(__dev_priv)->cpu_transcoder_mask & BIT(__t))
#define for_each_cpu_transcoder_masked(__dev_priv, __t, __mask) \
for_each_cpu_transcoder(__dev_priv, __t) \
@@ -237,7 +237,7 @@ enum phy_fia {
#define for_each_sprite(__dev_priv, __p, __s) \
for ((__s) = 0; \
- (__s) < RUNTIME_INFO(__dev_priv)->num_sprites[(__p)]; \
+ (__s) < DISPLAY_RUNTIME_INFO(__dev_priv)->num_sprites[(__p)]; \
(__s)++)
#define for_each_port(__port) \
@@ -407,6 +407,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
bool bigjoiner);
enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port);
bool is_trans_port_sync_mode(const struct intel_crtc_state *state);
+bool is_trans_port_sync_master(const struct intel_crtc_state *state);
bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state);
bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state);
u8 intel_crtc_bigjoiner_slave_pipes(const struct intel_crtc_state *crtc_state);
@@ -437,7 +438,6 @@ void intel_add_fb_offsets(int *x, int *y,
unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info);
unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info);
bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv);
-int intel_display_suspend(struct drm_device *dev);
void intel_encoder_destroy(struct drm_encoder *encoder);
struct drm_display_mode *
intel_encoder_current_mode(struct intel_encoder *encoder);
@@ -455,20 +455,12 @@ int ilk_get_lanes_required(int target_clock, int link_bw, int bpp);
void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
struct intel_digital_port *dig_port,
unsigned int expected_mask);
-int intel_get_load_detect_pipe(struct drm_connector *connector,
- struct intel_load_detect_pipe *old,
- struct drm_modeset_acquire_ctx *ctx);
-void intel_release_load_detect_pipe(struct drm_connector *connector,
- struct intel_load_detect_pipe *old,
- struct drm_modeset_acquire_ctx *ctx);
struct drm_framebuffer *
intel_framebuffer_create(struct drm_i915_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd);
bool intel_fuzzy_clock_check(int clock1, int clock2);
-void intel_display_prepare_reset(struct drm_i915_private *dev_priv);
-void intel_display_finish_reset(struct drm_i915_private *dev_priv);
void intel_zero_m_n(struct intel_link_m_n *m_n);
void intel_set_m_n(struct drm_i915_private *i915,
const struct intel_link_m_n *m_n,
@@ -518,21 +510,9 @@ void intel_set_plane_visible(struct intel_crtc_state *crtc_state,
bool visible);
void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state);
-void intel_display_driver_register(struct drm_i915_private *i915);
-void intel_display_driver_unregister(struct drm_i915_private *i915);
-
void intel_update_watermarks(struct drm_i915_private *i915);
/* modesetting */
-bool intel_modeset_probe_defer(struct pci_dev *pdev);
-void intel_modeset_init_hw(struct drm_i915_private *i915);
-int intel_modeset_init_noirq(struct drm_i915_private *i915);
-int intel_modeset_init_nogem(struct drm_i915_private *i915);
-int intel_modeset_init(struct drm_i915_private *i915);
-void intel_modeset_driver_remove(struct drm_i915_private *i915);
-void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915);
-void intel_modeset_driver_remove_nogem(struct drm_i915_private *i915);
-void intel_display_resume(struct drm_device *dev);
int intel_modeset_all_pipes(struct intel_atomic_state *state,
const char *reason);
void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
@@ -540,30 +520,41 @@ void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc,
struct intel_power_domain_mask *domains);
+/* interface for intel_display_driver.c */
+void intel_setup_outputs(struct drm_i915_private *i915);
+int intel_initial_commit(struct drm_device *dev);
+void intel_panel_sanitize_ssc(struct drm_i915_private *i915);
+void intel_update_czclk(struct drm_i915_private *i915);
+void intel_atomic_helper_free_state_worker(struct work_struct *work);
+enum drm_mode_status intel_mode_valid(struct drm_device *dev,
+ const struct drm_display_mode *mode);
+int intel_atomic_commit(struct drm_device *dev, struct drm_atomic_state *_state,
+ bool nonblock);
+
+void intel_hpd_poll_fini(struct drm_i915_private *i915);
+
/* modesetting asserts */
void assert_transcoder(struct drm_i915_private *dev_priv,
enum transcoder cpu_transcoder, bool state);
#define assert_transcoder_enabled(d, t) assert_transcoder(d, t, true)
#define assert_transcoder_disabled(d, t) assert_transcoder(d, t, false)
-/* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and
- * WARN_ON()) for hw state sanity checks to check for unexpected conditions
- * which may not necessarily be a user visible problem. This will either
- * WARN() or DRM_ERROR() depending on the verbose_checks moduleparam, to
- * enable distros and users to tailor their preferred amount of i915 abrt
- * spam.
+/*
+ * Use I915_STATE_WARN(x) (rather than WARN() and WARN_ON()) for hw state sanity
+ * checks to check for unexpected conditions which may not necessarily be a user
+ * visible problem. This will either WARN() or DRM_ERROR() depending on the
+ * verbose_state_checks module param, to enable distros and users to tailor
+ * their preferred amount of i915 abrt spam.
*/
-#define I915_STATE_WARN(condition, format...) ({ \
+#define I915_STATE_WARN(__i915, condition, format...) ({ \
+ struct drm_device *drm = &(__i915)->drm; \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
- if (!WARN(i915_modparams.verbose_state_checks, format)) \
- DRM_ERROR(format); \
+ if (!drm_WARN(drm, i915_modparams.verbose_state_checks, format)) \
+ drm_err(drm, format); \
unlikely(__ret_warn_on); \
})
-#define I915_STATE_WARN_ON(x) \
- I915_STATE_WARN((x), "%s", "WARN_ON(" __stringify(x) ")")
-
bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915);
#endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
index e36f88a39b86..8d2243c71dd8 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -30,7 +30,7 @@ struct drm_i915_private;
struct drm_property;
struct drm_property_blob;
struct i915_audio_component;
-struct i915_hdcp_comp_master;
+struct i915_hdcp_arbiter;
struct intel_atomic_state;
struct intel_audio_funcs;
struct intel_bios_encoder_data;
@@ -314,6 +314,8 @@ struct intel_display {
unsigned int deratedbw[I915_NUM_QGV_POINTS];
/* for each PSF GV point */
unsigned int psf_bw[I915_NUM_PSF_GV_POINTS];
+ /* Peak BW for each QGV point */
+ unsigned int peakbw[I915_NUM_QGV_POINTS];
u8 num_qgv_points;
u8 num_psf_gv_points;
u8 num_planes;
@@ -344,6 +346,15 @@ struct intel_display {
} dbuf;
struct {
+ wait_queue_head_t waitqueue;
+
+ /* mutex to protect pmdemand programming sequence */
+ struct mutex lock;
+
+ struct intel_global_obj obj;
+ } pmdemand;
+
+ struct {
/*
* dkl.phy_lock protects against concurrent access of the
* Dekel TypeC PHYs.
@@ -395,7 +406,7 @@ struct intel_display {
} gmbus;
struct {
- struct i915_hdcp_master *master;
+ struct i915_hdcp_arbiter *arbiter;
bool comp_added;
/*
@@ -404,8 +415,8 @@ struct intel_display {
* this is only populated post Meteorlake
*/
struct intel_hdcp_gsc_message *hdcp_message;
- /* Mutex to protect the above hdcp component related values. */
- struct mutex comp_mutex;
+ /* Mutex to protect the above hdcp related values. */
+ struct mutex hdcp_mutex;
} hdcp;
struct {
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 45113ae107ba..165e2c7e3126 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -6,12 +6,14 @@
#include <linux/string_helpers.h>
#include <drm/drm_debugfs.h>
+#include <drm/drm_edid.h>
#include <drm/drm_fourcc.h>
#include "hsw_ips.h"
#include "i915_debugfs.h"
#include "i915_irq.h"
#include "i915_reg.h"
+#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_crtc_state_dump.h"
#include "intel_display_debugfs.h"
@@ -30,7 +32,6 @@
#include "intel_panel.h"
#include "intel_psr.h"
#include "intel_psr_regs.h"
-#include "intel_sprite.h"
#include "intel_wm.h"
static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node)
@@ -228,37 +229,34 @@ out:
seq_puts(m, "\n");
}
-static void intel_dp_info(struct seq_file *m,
- struct intel_connector *intel_connector)
+static void intel_dp_info(struct seq_file *m, struct intel_connector *connector)
{
- struct intel_encoder *intel_encoder = intel_attached_encoder(intel_connector);
+ struct intel_encoder *intel_encoder = intel_attached_encoder(connector);
struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
- const struct drm_property_blob *edid = intel_connector->base.edid_blob_ptr;
+ const struct edid *edid = drm_edid_raw(connector->detect_edid);
seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
seq_printf(m, "\taudio support: %s\n",
- str_yes_no(intel_dp->has_audio));
+ str_yes_no(connector->base.display_info.has_audio));
drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
- edid ? edid->data : NULL, &intel_dp->aux);
+ edid, &intel_dp->aux);
}
static void intel_dp_mst_info(struct seq_file *m,
- struct intel_connector *intel_connector)
+ struct intel_connector *connector)
{
- bool has_audio = intel_connector->port->has_audio;
+ bool has_audio = connector->base.display_info.has_audio;
seq_printf(m, "\taudio support: %s\n", str_yes_no(has_audio));
}
static void intel_hdmi_info(struct seq_file *m,
- struct intel_connector *intel_connector)
+ struct intel_connector *connector)
{
- struct intel_encoder *intel_encoder = intel_attached_encoder(intel_connector);
- struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(intel_encoder);
+ bool has_audio = connector->base.display_info.has_audio;
- seq_printf(m, "\taudio support: %s\n",
- str_yes_no(intel_hdmi->has_audio));
+ seq_printf(m, "\taudio support: %s\n", str_yes_no(has_audio));
}
static void intel_connector_info(struct seq_file *m,
@@ -1094,6 +1092,7 @@ void intel_display_debugfs_register(struct drm_i915_private *i915)
ARRAY_SIZE(intel_display_debugfs_list),
minor->debugfs_root, minor);
+ intel_cdclk_debugfs_register(i915);
intel_dmc_debugfs_register(i915);
intel_fbc_debugfs_register(i915);
intel_hpd_debugfs_register(i915);
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c
new file mode 100644
index 000000000000..3fd30e7f0062
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_device.c
@@ -0,0 +1,917 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include <drm/i915_pciids.h>
+#include <drm/drm_color_mgmt.h>
+#include <linux/pci.h>
+
+#include "i915_drv.h"
+#include "i915_reg.h"
+#include "intel_de.h"
+#include "intel_display.h"
+#include "intel_display_device.h"
+#include "intel_display_power.h"
+#include "intel_display_reg_defs.h"
+#include "intel_fbc.h"
+
+__diag_push();
+__diag_ignore_all("-Woverride-init", "Allow overriding inherited members");
+
+static const struct intel_display_device_info no_display = {};
+
+#define PIPE_A_OFFSET 0x70000
+#define PIPE_B_OFFSET 0x71000
+#define PIPE_C_OFFSET 0x72000
+#define PIPE_D_OFFSET 0x73000
+#define CHV_PIPE_C_OFFSET 0x74000
+/*
+ * There's actually no pipe EDP. Some pipe registers have
+ * simply shifted from the pipe to the transcoder, while
+ * keeping their original offset. Thus we need PIPE_EDP_OFFSET
+ * to access such registers in transcoder EDP.
+ */
+#define PIPE_EDP_OFFSET 0x7f000
+
+/* ICL DSI 0 and 1 */
+#define PIPE_DSI0_OFFSET 0x7b000
+#define PIPE_DSI1_OFFSET 0x7b800
+
+#define TRANSCODER_A_OFFSET 0x60000
+#define TRANSCODER_B_OFFSET 0x61000
+#define TRANSCODER_C_OFFSET 0x62000
+#define CHV_TRANSCODER_C_OFFSET 0x63000
+#define TRANSCODER_D_OFFSET 0x63000
+#define TRANSCODER_EDP_OFFSET 0x6f000
+#define TRANSCODER_DSI0_OFFSET 0x6b000
+#define TRANSCODER_DSI1_OFFSET 0x6b800
+
+#define CURSOR_A_OFFSET 0x70080
+#define CURSOR_B_OFFSET 0x700c0
+#define CHV_CURSOR_C_OFFSET 0x700e0
+#define IVB_CURSOR_B_OFFSET 0x71080
+#define IVB_CURSOR_C_OFFSET 0x72080
+#define TGL_CURSOR_D_OFFSET 0x73080
+
+#define I845_PIPE_OFFSETS \
+ .pipe_offsets = { \
+ [TRANSCODER_A] = PIPE_A_OFFSET, \
+ }, \
+ .trans_offsets = { \
+ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
+ }
+
+#define I9XX_PIPE_OFFSETS \
+ .pipe_offsets = { \
+ [TRANSCODER_A] = PIPE_A_OFFSET, \
+ [TRANSCODER_B] = PIPE_B_OFFSET, \
+ }, \
+ .trans_offsets = { \
+ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
+ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
+ }
+
+#define IVB_PIPE_OFFSETS \
+ .pipe_offsets = { \
+ [TRANSCODER_A] = PIPE_A_OFFSET, \
+ [TRANSCODER_B] = PIPE_B_OFFSET, \
+ [TRANSCODER_C] = PIPE_C_OFFSET, \
+ }, \
+ .trans_offsets = { \
+ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
+ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
+ [TRANSCODER_C] = TRANSCODER_C_OFFSET, \
+ }
+
+#define HSW_PIPE_OFFSETS \
+ .pipe_offsets = { \
+ [TRANSCODER_A] = PIPE_A_OFFSET, \
+ [TRANSCODER_B] = PIPE_B_OFFSET, \
+ [TRANSCODER_C] = PIPE_C_OFFSET, \
+ [TRANSCODER_EDP] = PIPE_EDP_OFFSET, \
+ }, \
+ .trans_offsets = { \
+ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
+ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
+ [TRANSCODER_C] = TRANSCODER_C_OFFSET, \
+ [TRANSCODER_EDP] = TRANSCODER_EDP_OFFSET, \
+ }
+
+#define CHV_PIPE_OFFSETS \
+ .pipe_offsets = { \
+ [TRANSCODER_A] = PIPE_A_OFFSET, \
+ [TRANSCODER_B] = PIPE_B_OFFSET, \
+ [TRANSCODER_C] = CHV_PIPE_C_OFFSET, \
+ }, \
+ .trans_offsets = { \
+ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
+ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
+ [TRANSCODER_C] = CHV_TRANSCODER_C_OFFSET, \
+ }
+
+#define I845_CURSOR_OFFSETS \
+ .cursor_offsets = { \
+ [PIPE_A] = CURSOR_A_OFFSET, \
+ }
+
+#define I9XX_CURSOR_OFFSETS \
+ .cursor_offsets = { \
+ [PIPE_A] = CURSOR_A_OFFSET, \
+ [PIPE_B] = CURSOR_B_OFFSET, \
+ }
+
+#define CHV_CURSOR_OFFSETS \
+ .cursor_offsets = { \
+ [PIPE_A] = CURSOR_A_OFFSET, \
+ [PIPE_B] = CURSOR_B_OFFSET, \
+ [PIPE_C] = CHV_CURSOR_C_OFFSET, \
+ }
+
+#define IVB_CURSOR_OFFSETS \
+ .cursor_offsets = { \
+ [PIPE_A] = CURSOR_A_OFFSET, \
+ [PIPE_B] = IVB_CURSOR_B_OFFSET, \
+ [PIPE_C] = IVB_CURSOR_C_OFFSET, \
+ }
+
+#define TGL_CURSOR_OFFSETS \
+ .cursor_offsets = { \
+ [PIPE_A] = CURSOR_A_OFFSET, \
+ [PIPE_B] = IVB_CURSOR_B_OFFSET, \
+ [PIPE_C] = IVB_CURSOR_C_OFFSET, \
+ [PIPE_D] = TGL_CURSOR_D_OFFSET, \
+ }
+
+#define I845_COLORS \
+ .color = { .gamma_lut_size = 256 }
+#define I9XX_COLORS \
+ .color = { .gamma_lut_size = 129, \
+ .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \
+ }
+#define ILK_COLORS \
+ .color = { .gamma_lut_size = 1024 }
+#define IVB_COLORS \
+ .color = { .degamma_lut_size = 1024, .gamma_lut_size = 1024 }
+#define CHV_COLORS \
+ .color = { \
+ .degamma_lut_size = 65, .gamma_lut_size = 257, \
+ .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \
+ .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \
+ }
+#define GLK_COLORS \
+ .color = { \
+ .degamma_lut_size = 33, .gamma_lut_size = 1024, \
+ .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \
+ DRM_COLOR_LUT_EQUAL_CHANNELS, \
+ }
+#define ICL_COLORS \
+ .color = { \
+ .degamma_lut_size = 33, .gamma_lut_size = 262145, \
+ .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \
+ DRM_COLOR_LUT_EQUAL_CHANNELS, \
+ .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \
+ }
+
+#define I830_DISPLAY \
+ .has_overlay = 1, \
+ .cursor_needs_physical = 1, \
+ .overlay_needs_physical = 1, \
+ .has_gmch = 1, \
+ I9XX_PIPE_OFFSETS, \
+ I9XX_CURSOR_OFFSETS, \
+ I9XX_COLORS, \
+ \
+ .__runtime_defaults.ip.ver = 2, \
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \
+ .__runtime_defaults.cpu_transcoder_mask = \
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B)
+
+static const struct intel_display_device_info i830_display = {
+ I830_DISPLAY,
+};
+
+#define I845_DISPLAY \
+ .has_overlay = 1, \
+ .overlay_needs_physical = 1, \
+ .has_gmch = 1, \
+ I845_PIPE_OFFSETS, \
+ I845_CURSOR_OFFSETS, \
+ I845_COLORS, \
+ \
+ .__runtime_defaults.ip.ver = 2, \
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A), \
+ .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A)
+
+static const struct intel_display_device_info i845_display = {
+ I845_DISPLAY,
+};
+
+static const struct intel_display_device_info i85x_display = {
+ I830_DISPLAY,
+
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+static const struct intel_display_device_info i865g_display = {
+ I845_DISPLAY,
+
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+#define GEN3_DISPLAY \
+ .has_gmch = 1, \
+ .has_overlay = 1, \
+ I9XX_PIPE_OFFSETS, \
+ I9XX_CURSOR_OFFSETS, \
+ \
+ .__runtime_defaults.ip.ver = 3, \
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \
+ .__runtime_defaults.cpu_transcoder_mask = \
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B)
+
+static const struct intel_display_device_info i915g_display = {
+ GEN3_DISPLAY,
+ I845_COLORS,
+ .cursor_needs_physical = 1,
+ .overlay_needs_physical = 1,
+};
+
+static const struct intel_display_device_info i915gm_display = {
+ GEN3_DISPLAY,
+ I9XX_COLORS,
+ .cursor_needs_physical = 1,
+ .overlay_needs_physical = 1,
+ .supports_tv = 1,
+
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+static const struct intel_display_device_info i945g_display = {
+ GEN3_DISPLAY,
+ I845_COLORS,
+ .has_hotplug = 1,
+ .cursor_needs_physical = 1,
+ .overlay_needs_physical = 1,
+};
+
+static const struct intel_display_device_info i945gm_display = {
+ GEN3_DISPLAY,
+ I9XX_COLORS,
+ .has_hotplug = 1,
+ .cursor_needs_physical = 1,
+ .overlay_needs_physical = 1,
+ .supports_tv = 1,
+
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+static const struct intel_display_device_info g33_display = {
+ GEN3_DISPLAY,
+ I845_COLORS,
+ .has_hotplug = 1,
+};
+
+static const struct intel_display_device_info pnv_display = {
+ GEN3_DISPLAY,
+ I9XX_COLORS,
+ .has_hotplug = 1,
+};
+
+#define GEN4_DISPLAY \
+ .has_hotplug = 1, \
+ .has_gmch = 1, \
+ I9XX_PIPE_OFFSETS, \
+ I9XX_CURSOR_OFFSETS, \
+ I9XX_COLORS, \
+ \
+ .__runtime_defaults.ip.ver = 4, \
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \
+ .__runtime_defaults.cpu_transcoder_mask = \
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B)
+
+static const struct intel_display_device_info i965g_display = {
+ GEN4_DISPLAY,
+ .has_overlay = 1,
+};
+
+static const struct intel_display_device_info i965gm_display = {
+ GEN4_DISPLAY,
+ .has_overlay = 1,
+ .supports_tv = 1,
+
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+static const struct intel_display_device_info g45_display = {
+ GEN4_DISPLAY,
+};
+
+static const struct intel_display_device_info gm45_display = {
+ GEN4_DISPLAY,
+ .supports_tv = 1,
+
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+#define ILK_DISPLAY \
+ .has_hotplug = 1, \
+ I9XX_PIPE_OFFSETS, \
+ I9XX_CURSOR_OFFSETS, \
+ ILK_COLORS, \
+ \
+ .__runtime_defaults.ip.ver = 5, \
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \
+ .__runtime_defaults.cpu_transcoder_mask = \
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B)
+
+static const struct intel_display_device_info ilk_d_display = {
+ ILK_DISPLAY,
+};
+
+static const struct intel_display_device_info ilk_m_display = {
+ ILK_DISPLAY,
+
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+static const struct intel_display_device_info snb_display = {
+ .has_hotplug = 1,
+ I9XX_PIPE_OFFSETS,
+ I9XX_CURSOR_OFFSETS,
+ ILK_COLORS,
+
+ .__runtime_defaults.ip.ver = 6,
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B),
+ .__runtime_defaults.cpu_transcoder_mask =
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B),
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+static const struct intel_display_device_info ivb_display = {
+ .has_hotplug = 1,
+ IVB_PIPE_OFFSETS,
+ IVB_CURSOR_OFFSETS,
+ IVB_COLORS,
+
+ .__runtime_defaults.ip.ver = 7,
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
+ .__runtime_defaults.cpu_transcoder_mask =
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C),
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+static const struct intel_display_device_info vlv_display = {
+ .has_gmch = 1,
+ .has_hotplug = 1,
+ .mmio_offset = VLV_DISPLAY_BASE,
+ I9XX_PIPE_OFFSETS,
+ I9XX_CURSOR_OFFSETS,
+ I9XX_COLORS,
+
+ .__runtime_defaults.ip.ver = 7,
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B),
+ .__runtime_defaults.cpu_transcoder_mask =
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B),
+};
+
+static const struct intel_display_device_info hsw_display = {
+ .has_ddi = 1,
+ .has_dp_mst = 1,
+ .has_fpga_dbg = 1,
+ .has_hotplug = 1,
+ HSW_PIPE_OFFSETS,
+ IVB_CURSOR_OFFSETS,
+ IVB_COLORS,
+
+ .__runtime_defaults.ip.ver = 7,
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
+ .__runtime_defaults.cpu_transcoder_mask =
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP),
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+static const struct intel_display_device_info bdw_display = {
+ .has_ddi = 1,
+ .has_dp_mst = 1,
+ .has_fpga_dbg = 1,
+ .has_hotplug = 1,
+ HSW_PIPE_OFFSETS,
+ IVB_CURSOR_OFFSETS,
+ IVB_COLORS,
+
+ .__runtime_defaults.ip.ver = 8,
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
+ .__runtime_defaults.cpu_transcoder_mask =
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP),
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+static const struct intel_display_device_info chv_display = {
+ .has_hotplug = 1,
+ .has_gmch = 1,
+ .mmio_offset = VLV_DISPLAY_BASE,
+ CHV_PIPE_OFFSETS,
+ CHV_CURSOR_OFFSETS,
+ CHV_COLORS,
+
+ .__runtime_defaults.ip.ver = 8,
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
+ .__runtime_defaults.cpu_transcoder_mask =
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C),
+};
+
+static const struct intel_display_device_info skl_display = {
+ .dbuf.size = 896 - 4, /* 4 blocks for bypass path allocation */
+ .dbuf.slice_mask = BIT(DBUF_S1),
+ .has_ddi = 1,
+ .has_dp_mst = 1,
+ .has_fpga_dbg = 1,
+ .has_hotplug = 1,
+ .has_ipc = 1,
+ .has_psr = 1,
+ .has_psr_hw_tracking = 1,
+ HSW_PIPE_OFFSETS,
+ IVB_CURSOR_OFFSETS,
+ IVB_COLORS,
+
+ .__runtime_defaults.ip.ver = 9,
+ .__runtime_defaults.has_dmc = 1,
+ .__runtime_defaults.has_hdcp = 1,
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
+ .__runtime_defaults.cpu_transcoder_mask =
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP),
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+#define GEN9_LP_DISPLAY \
+ .dbuf.slice_mask = BIT(DBUF_S1), \
+ .has_dp_mst = 1, \
+ .has_ddi = 1, \
+ .has_fpga_dbg = 1, \
+ .has_hotplug = 1, \
+ .has_ipc = 1, \
+ .has_psr = 1, \
+ .has_psr_hw_tracking = 1, \
+ HSW_PIPE_OFFSETS, \
+ IVB_CURSOR_OFFSETS, \
+ IVB_COLORS, \
+ \
+ .__runtime_defaults.has_dmc = 1, \
+ .__runtime_defaults.has_hdcp = 1, \
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), \
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \
+ .__runtime_defaults.cpu_transcoder_mask = \
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP) | \
+ BIT(TRANSCODER_DSI_A) | BIT(TRANSCODER_DSI_C)
+
+static const struct intel_display_device_info bxt_display = {
+ GEN9_LP_DISPLAY,
+ .dbuf.size = 512 - 4, /* 4 blocks for bypass path allocation */
+
+ .__runtime_defaults.ip.ver = 9,
+};
+
+static const struct intel_display_device_info glk_display = {
+ GEN9_LP_DISPLAY,
+ .dbuf.size = 1024 - 4, /* 4 blocks for bypass path allocation */
+ GLK_COLORS,
+
+ .__runtime_defaults.ip.ver = 10,
+};
+
+static const struct intel_display_device_info gen11_display = {
+ .abox_mask = BIT(0),
+ .dbuf.size = 2048,
+ .dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2),
+ .has_ddi = 1,
+ .has_dp_mst = 1,
+ .has_fpga_dbg = 1,
+ .has_hotplug = 1,
+ .has_ipc = 1,
+ .has_psr = 1,
+ .has_psr_hw_tracking = 1,
+ .pipe_offsets = {
+ [TRANSCODER_A] = PIPE_A_OFFSET,
+ [TRANSCODER_B] = PIPE_B_OFFSET,
+ [TRANSCODER_C] = PIPE_C_OFFSET,
+ [TRANSCODER_EDP] = PIPE_EDP_OFFSET,
+ [TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET,
+ [TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET,
+ },
+ .trans_offsets = {
+ [TRANSCODER_A] = TRANSCODER_A_OFFSET,
+ [TRANSCODER_B] = TRANSCODER_B_OFFSET,
+ [TRANSCODER_C] = TRANSCODER_C_OFFSET,
+ [TRANSCODER_EDP] = TRANSCODER_EDP_OFFSET,
+ [TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET,
+ [TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET,
+ },
+ IVB_CURSOR_OFFSETS,
+ ICL_COLORS,
+
+ .__runtime_defaults.ip.ver = 11,
+ .__runtime_defaults.has_dmc = 1,
+ .__runtime_defaults.has_dsc = 1,
+ .__runtime_defaults.has_hdcp = 1,
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
+ .__runtime_defaults.cpu_transcoder_mask =
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP) |
+ BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1),
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
+};
+
+#define XE_D_DISPLAY \
+ .abox_mask = GENMASK(2, 1), \
+ .dbuf.size = 2048, \
+ .dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2), \
+ .has_ddi = 1, \
+ .has_dp_mst = 1, \
+ .has_dsb = 1, \
+ .has_fpga_dbg = 1, \
+ .has_hotplug = 1, \
+ .has_ipc = 1, \
+ .has_psr = 1, \
+ .has_psr_hw_tracking = 1, \
+ .pipe_offsets = { \
+ [TRANSCODER_A] = PIPE_A_OFFSET, \
+ [TRANSCODER_B] = PIPE_B_OFFSET, \
+ [TRANSCODER_C] = PIPE_C_OFFSET, \
+ [TRANSCODER_D] = PIPE_D_OFFSET, \
+ [TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \
+ [TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \
+ }, \
+ .trans_offsets = { \
+ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
+ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
+ [TRANSCODER_C] = TRANSCODER_C_OFFSET, \
+ [TRANSCODER_D] = TRANSCODER_D_OFFSET, \
+ [TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \
+ [TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \
+ }, \
+ TGL_CURSOR_OFFSETS, \
+ ICL_COLORS, \
+ \
+ .__runtime_defaults.ip.ver = 12, \
+ .__runtime_defaults.has_dmc = 1, \
+ .__runtime_defaults.has_dsc = 1, \
+ .__runtime_defaults.has_hdcp = 1, \
+ .__runtime_defaults.pipe_mask = \
+ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \
+ .__runtime_defaults.cpu_transcoder_mask = \
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_D) | \
+ BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A)
+
+static const struct intel_display_device_info tgl_display = {
+ XE_D_DISPLAY,
+};
+
+static const struct intel_display_device_info rkl_display = {
+ XE_D_DISPLAY,
+ .abox_mask = BIT(0),
+ .has_hti = 1,
+ .has_psr_hw_tracking = 0,
+
+ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
+ .__runtime_defaults.cpu_transcoder_mask =
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C),
+};
+
+static const struct intel_display_device_info adl_s_display = {
+ XE_D_DISPLAY,
+ .has_hti = 1,
+ .has_psr_hw_tracking = 0,
+};
+
+#define XE_LPD_FEATURES \
+ .abox_mask = GENMASK(1, 0), \
+ .color = { \
+ .degamma_lut_size = 129, .gamma_lut_size = 1024, \
+ .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \
+ DRM_COLOR_LUT_EQUAL_CHANNELS, \
+ }, \
+ .dbuf.size = 4096, \
+ .dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | \
+ BIT(DBUF_S4), \
+ .has_ddi = 1, \
+ .has_dp_mst = 1, \
+ .has_dsb = 1, \
+ .has_fpga_dbg = 1, \
+ .has_hotplug = 1, \
+ .has_ipc = 1, \
+ .has_psr = 1, \
+ .pipe_offsets = { \
+ [TRANSCODER_A] = PIPE_A_OFFSET, \
+ [TRANSCODER_B] = PIPE_B_OFFSET, \
+ [TRANSCODER_C] = PIPE_C_OFFSET, \
+ [TRANSCODER_D] = PIPE_D_OFFSET, \
+ [TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \
+ [TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \
+ }, \
+ .trans_offsets = { \
+ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
+ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
+ [TRANSCODER_C] = TRANSCODER_C_OFFSET, \
+ [TRANSCODER_D] = TRANSCODER_D_OFFSET, \
+ [TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \
+ [TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \
+ }, \
+ TGL_CURSOR_OFFSETS, \
+ \
+ .__runtime_defaults.ip.ver = 13, \
+ .__runtime_defaults.has_dmc = 1, \
+ .__runtime_defaults.has_dsc = 1, \
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), \
+ .__runtime_defaults.has_hdcp = 1, \
+ .__runtime_defaults.pipe_mask = \
+ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D)
+
+static const struct intel_display_device_info xe_lpd_display = {
+ XE_LPD_FEATURES,
+ .has_cdclk_crawl = 1,
+ .has_psr_hw_tracking = 0,
+
+ .__runtime_defaults.cpu_transcoder_mask =
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_D) |
+ BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1),
+};
+
+static const struct intel_display_device_info xe_hpd_display = {
+ XE_LPD_FEATURES,
+ .has_cdclk_squash = 1,
+
+ .__runtime_defaults.cpu_transcoder_mask =
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_D),
+};
+
+static const struct intel_display_device_info xe_lpdp_display = {
+ XE_LPD_FEATURES,
+ .has_cdclk_crawl = 1,
+ .has_cdclk_squash = 1,
+
+ .__runtime_defaults.ip.ver = 14,
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B),
+ .__runtime_defaults.cpu_transcoder_mask =
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_D),
+};
+
+__diag_pop();
+
+#undef INTEL_VGA_DEVICE
+#undef INTEL_QUANTA_VGA_DEVICE
+#define INTEL_VGA_DEVICE(id, info) { id, info }
+#define INTEL_QUANTA_VGA_DEVICE(info) { 0x16a, info }
+
+static const struct {
+ u32 devid;
+ const struct intel_display_device_info *info;
+} intel_display_ids[] = {
+ INTEL_I830_IDS(&i830_display),
+ INTEL_I845G_IDS(&i845_display),
+ INTEL_I85X_IDS(&i85x_display),
+ INTEL_I865G_IDS(&i865g_display),
+ INTEL_I915G_IDS(&i915g_display),
+ INTEL_I915GM_IDS(&i915gm_display),
+ INTEL_I945G_IDS(&i945g_display),
+ INTEL_I945GM_IDS(&i945gm_display),
+ INTEL_I965G_IDS(&i965g_display),
+ INTEL_G33_IDS(&g33_display),
+ INTEL_I965GM_IDS(&i965gm_display),
+ INTEL_GM45_IDS(&gm45_display),
+ INTEL_G45_IDS(&g45_display),
+ INTEL_PINEVIEW_G_IDS(&pnv_display),
+ INTEL_PINEVIEW_M_IDS(&pnv_display),
+ INTEL_IRONLAKE_D_IDS(&ilk_d_display),
+ INTEL_IRONLAKE_M_IDS(&ilk_m_display),
+ INTEL_SNB_D_IDS(&snb_display),
+ INTEL_SNB_M_IDS(&snb_display),
+ INTEL_IVB_Q_IDS(NULL), /* must be first IVB in list */
+ INTEL_IVB_M_IDS(&ivb_display),
+ INTEL_IVB_D_IDS(&ivb_display),
+ INTEL_HSW_IDS(&hsw_display),
+ INTEL_VLV_IDS(&vlv_display),
+ INTEL_BDW_IDS(&bdw_display),
+ INTEL_CHV_IDS(&chv_display),
+ INTEL_SKL_IDS(&skl_display),
+ INTEL_BXT_IDS(&bxt_display),
+ INTEL_GLK_IDS(&glk_display),
+ INTEL_KBL_IDS(&skl_display),
+ INTEL_CFL_IDS(&skl_display),
+ INTEL_ICL_11_IDS(&gen11_display),
+ INTEL_EHL_IDS(&gen11_display),
+ INTEL_JSL_IDS(&gen11_display),
+ INTEL_TGL_12_IDS(&tgl_display),
+ INTEL_DG1_IDS(&tgl_display),
+ INTEL_RKL_IDS(&rkl_display),
+ INTEL_ADLS_IDS(&adl_s_display),
+ INTEL_RPLS_IDS(&adl_s_display),
+ INTEL_ADLP_IDS(&xe_lpd_display),
+ INTEL_ADLN_IDS(&xe_lpd_display),
+ INTEL_RPLP_IDS(&xe_lpd_display),
+ INTEL_DG2_IDS(&xe_hpd_display),
+
+ /*
+ * Do not add any GMD_ID-based platforms to this list. They will
+ * be probed automatically based on the IP version reported by
+ * the hardware.
+ */
+};
+
+static const struct {
+ u16 ver;
+ u16 rel;
+ const struct intel_display_device_info *display;
+} gmdid_display_map[] = {
+ { 14, 0, &xe_lpdp_display },
+};
+
+static const struct intel_display_device_info *
+probe_gmdid_display(struct drm_i915_private *i915, u16 *ver, u16 *rel, u16 *step)
+{
+ struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
+ void __iomem *addr;
+ u32 val;
+ int i;
+
+ addr = pci_iomap_range(pdev, 0, i915_mmio_reg_offset(GMD_ID_DISPLAY), sizeof(u32));
+ if (!addr) {
+ drm_err(&i915->drm, "Cannot map MMIO BAR to read display GMD_ID\n");
+ return &no_display;
+ }
+
+ val = ioread32(addr);
+ pci_iounmap(pdev, addr);
+
+ if (val == 0)
+ /* Platform doesn't have display */
+ return &no_display;
+
+ *ver = REG_FIELD_GET(GMD_ID_ARCH_MASK, val);
+ *rel = REG_FIELD_GET(GMD_ID_RELEASE_MASK, val);
+ *step = REG_FIELD_GET(GMD_ID_STEP, val);
+
+ for (i = 0; i < ARRAY_SIZE(gmdid_display_map); i++)
+ if (*ver == gmdid_display_map[i].ver &&
+ *rel == gmdid_display_map[i].rel)
+ return gmdid_display_map[i].display;
+
+ drm_err(&i915->drm, "Unrecognized display IP version %d.%02d; disabling display.\n",
+ *ver, *rel);
+ return &no_display;
+}
+
+const struct intel_display_device_info *
+intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid,
+ u16 *gmdid_ver, u16 *gmdid_rel, u16 *gmdid_step)
+{
+ struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
+ int i;
+
+ if (has_gmdid)
+ return probe_gmdid_display(i915, gmdid_ver, gmdid_rel, gmdid_step);
+
+ for (i = 0; i < ARRAY_SIZE(intel_display_ids); i++) {
+ if (intel_display_ids[i].devid == pdev->device)
+ return intel_display_ids[i].info;
+ }
+
+ drm_dbg(&i915->drm, "No display ID found for device ID %04x; disabling display.\n",
+ pdev->device);
+
+ return &no_display;
+}
+
+void intel_display_device_info_runtime_init(struct drm_i915_private *i915)
+{
+ struct intel_display_runtime_info *display_runtime = DISPLAY_RUNTIME_INFO(i915);
+ enum pipe pipe;
+
+ /* Wa_14011765242: adl-s A0,A1 */
+ if (IS_ADLS_DISPLAY_STEP(i915, STEP_A0, STEP_A2))
+ for_each_pipe(i915, pipe)
+ display_runtime->num_scalers[pipe] = 0;
+ else if (DISPLAY_VER(i915) >= 11) {
+ for_each_pipe(i915, pipe)
+ display_runtime->num_scalers[pipe] = 2;
+ } else if (DISPLAY_VER(i915) >= 9) {
+ display_runtime->num_scalers[PIPE_A] = 2;
+ display_runtime->num_scalers[PIPE_B] = 2;
+ display_runtime->num_scalers[PIPE_C] = 1;
+ }
+
+ if (DISPLAY_VER(i915) >= 13 || HAS_D12_PLANE_MINIMIZATION(i915))
+ for_each_pipe(i915, pipe)
+ display_runtime->num_sprites[pipe] = 4;
+ else if (DISPLAY_VER(i915) >= 11)
+ for_each_pipe(i915, pipe)
+ display_runtime->num_sprites[pipe] = 6;
+ else if (DISPLAY_VER(i915) == 10)
+ for_each_pipe(i915, pipe)
+ display_runtime->num_sprites[pipe] = 3;
+ else if (IS_BROXTON(i915)) {
+ /*
+ * Skylake and Broxton currently don't expose the topmost plane as its
+ * use is exclusive with the legacy cursor and we only want to expose
+ * one of those, not both. Until we can safely expose the topmost plane
+ * as a DRM_PLANE_TYPE_CURSOR with all the features exposed/supported,
+ * we don't expose the topmost plane at all to prevent ABI breakage
+ * down the line.
+ */
+
+ display_runtime->num_sprites[PIPE_A] = 2;
+ display_runtime->num_sprites[PIPE_B] = 2;
+ display_runtime->num_sprites[PIPE_C] = 1;
+ } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
+ for_each_pipe(i915, pipe)
+ display_runtime->num_sprites[pipe] = 2;
+ } else if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915)) {
+ for_each_pipe(i915, pipe)
+ display_runtime->num_sprites[pipe] = 1;
+ }
+
+ if ((IS_DGFX(i915) || DISPLAY_VER(i915) >= 14) &&
+ !(intel_de_read(i915, GU_CNTL_PROTECTED) & DEPRESENT)) {
+ drm_info(&i915->drm, "Display not present, disabling\n");
+ goto display_fused_off;
+ }
+
+ if (IS_GRAPHICS_VER(i915, 7, 8) && HAS_PCH_SPLIT(i915)) {
+ u32 fuse_strap = intel_de_read(i915, FUSE_STRAP);
+ u32 sfuse_strap = intel_de_read(i915, SFUSE_STRAP);
+
+ /*
+ * SFUSE_STRAP is supposed to have a bit signalling the display
+ * is fused off. Unfortunately it seems that, at least in
+ * certain cases, fused off display means that PCH display
+ * reads don't land anywhere. In that case, we read 0s.
+ *
+ * On CPT/PPT, we can detect this case as SFUSE_STRAP_FUSE_LOCK
+ * should be set when taking over after the firmware.
+ */
+ if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE ||
+ sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED ||
+ (HAS_PCH_CPT(i915) &&
+ !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) {
+ drm_info(&i915->drm,
+ "Display fused off, disabling\n");
+ goto display_fused_off;
+ } else if (fuse_strap & IVB_PIPE_C_DISABLE) {
+ drm_info(&i915->drm, "PipeC fused off\n");
+ display_runtime->pipe_mask &= ~BIT(PIPE_C);
+ display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_C);
+ }
+ } else if (DISPLAY_VER(i915) >= 9) {
+ u32 dfsm = intel_de_read(i915, SKL_DFSM);
+
+ if (dfsm & SKL_DFSM_PIPE_A_DISABLE) {
+ display_runtime->pipe_mask &= ~BIT(PIPE_A);
+ display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_A);
+ display_runtime->fbc_mask &= ~BIT(INTEL_FBC_A);
+ }
+ if (dfsm & SKL_DFSM_PIPE_B_DISABLE) {
+ display_runtime->pipe_mask &= ~BIT(PIPE_B);
+ display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_B);
+ }
+ if (dfsm & SKL_DFSM_PIPE_C_DISABLE) {
+ display_runtime->pipe_mask &= ~BIT(PIPE_C);
+ display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_C);
+ }
+
+ if (DISPLAY_VER(i915) >= 12 &&
+ (dfsm & TGL_DFSM_PIPE_D_DISABLE)) {
+ display_runtime->pipe_mask &= ~BIT(PIPE_D);
+ display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_D);
+ }
+
+ if (!display_runtime->pipe_mask)
+ goto display_fused_off;
+
+ if (dfsm & SKL_DFSM_DISPLAY_HDCP_DISABLE)
+ display_runtime->has_hdcp = 0;
+
+ if (dfsm & SKL_DFSM_DISPLAY_PM_DISABLE)
+ display_runtime->fbc_mask = 0;
+
+ if (DISPLAY_VER(i915) >= 11 && (dfsm & ICL_DFSM_DMC_DISABLE))
+ display_runtime->has_dmc = 0;
+
+ if (IS_DISPLAY_VER(i915, 10, 12) &&
+ (dfsm & GLK_DFSM_DISPLAY_DSC_DISABLE))
+ display_runtime->has_dsc = 0;
+ }
+
+ return;
+
+display_fused_off:
+ memset(display_runtime, 0, sizeof(*display_runtime));
+}
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
new file mode 100644
index 000000000000..706ff2aa1f55
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_device.h
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_DISPLAY_DEVICE_H__
+#define __INTEL_DISPLAY_DEVICE_H__
+
+#include <linux/types.h>
+
+#include "intel_display_limits.h"
+
+struct drm_i915_private;
+
+#define DEV_INFO_DISPLAY_FOR_EACH_FLAG(func) \
+ /* Keep in alphabetical order */ \
+ func(cursor_needs_physical); \
+ func(has_cdclk_crawl); \
+ func(has_cdclk_squash); \
+ func(has_ddi); \
+ func(has_dp_mst); \
+ func(has_dsb); \
+ func(has_fpga_dbg); \
+ func(has_gmch); \
+ func(has_hotplug); \
+ func(has_hti); \
+ func(has_ipc); \
+ func(has_overlay); \
+ func(has_psr); \
+ func(has_psr_hw_tracking); \
+ func(overlay_needs_physical); \
+ func(supports_tv);
+
+#define HAS_ASYNC_FLIPS(i915) (DISPLAY_VER(i915) >= 5)
+#define HAS_CDCLK_CRAWL(i915) (DISPLAY_INFO(i915)->has_cdclk_crawl)
+#define HAS_CDCLK_SQUASH(i915) (DISPLAY_INFO(i915)->has_cdclk_squash)
+#define HAS_CUR_FBC(i915) (!HAS_GMCH(i915) && DISPLAY_VER(i915) >= 7)
+#define HAS_D12_PLANE_MINIMIZATION(i915) (IS_ROCKETLAKE(i915) || IS_ALDERLAKE_S(i915))
+#define HAS_DDI(i915) (DISPLAY_INFO(i915)->has_ddi)
+#define HAS_DISPLAY(i915) (DISPLAY_RUNTIME_INFO(i915)->pipe_mask != 0)
+#define HAS_DMC(i915) (DISPLAY_RUNTIME_INFO(i915)->has_dmc)
+#define HAS_DOUBLE_BUFFERED_M_N(i915) (DISPLAY_VER(i915) >= 9 || IS_BROADWELL(i915))
+#define HAS_DP_MST(i915) (DISPLAY_INFO(i915)->has_dp_mst)
+#define HAS_DP20(i915) (IS_DG2(i915) || DISPLAY_VER(i915) >= 14)
+#define HAS_DPT(i915) (DISPLAY_VER(i915) >= 13)
+#define HAS_DSB(i915) (DISPLAY_INFO(i915)->has_dsb)
+#define HAS_DSC(__i915) (DISPLAY_RUNTIME_INFO(__i915)->has_dsc)
+#define HAS_FBC(i915) (DISPLAY_RUNTIME_INFO(i915)->fbc_mask != 0)
+#define HAS_FPGA_DBG_UNCLAIMED(i915) (DISPLAY_INFO(i915)->has_fpga_dbg)
+#define HAS_FW_BLC(i915) (DISPLAY_VER(i915) > 2)
+#define HAS_GMBUS_IRQ(i915) (DISPLAY_VER(i915) >= 4)
+#define HAS_GMBUS_BURST_READ(i915) (DISPLAY_VER(i915) >= 10 || IS_KABYLAKE(i915))
+#define HAS_GMCH(i915) (DISPLAY_INFO(i915)->has_gmch)
+#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915))
+#define HAS_IPC(i915) (DISPLAY_INFO(i915)->has_ipc)
+#define HAS_IPS(i915) (IS_HSW_ULT(i915) || IS_BROADWELL(i915))
+#define HAS_LSPCON(i915) (IS_DISPLAY_VER(i915, 9, 10))
+#define HAS_MBUS_JOINING(i915) (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14)
+#define HAS_MSO(i915) (DISPLAY_VER(i915) >= 12)
+#define HAS_OVERLAY(i915) (DISPLAY_INFO(i915)->has_overlay)
+#define HAS_PSR(i915) (DISPLAY_INFO(i915)->has_psr)
+#define HAS_PSR_HW_TRACKING(i915) (DISPLAY_INFO(i915)->has_psr_hw_tracking)
+#define HAS_PSR2_SEL_FETCH(i915) (DISPLAY_VER(i915) >= 12)
+#define HAS_SAGV(i915) (DISPLAY_VER(i915) >= 9 && !IS_LP(i915))
+#define HAS_TRANSCODER(i915, trans) ((DISPLAY_RUNTIME_INFO(i915)->cpu_transcoder_mask & \
+ BIT(trans)) != 0)
+#define HAS_VRR(i915) (DISPLAY_VER(i915) >= 11)
+#define INTEL_NUM_PIPES(i915) (hweight8(DISPLAY_RUNTIME_INFO(i915)->pipe_mask))
+#define I915_HAS_HOTPLUG(i915) (DISPLAY_INFO(i915)->has_hotplug)
+#define OVERLAY_NEEDS_PHYSICAL(i915) (DISPLAY_INFO(i915)->overlay_needs_physical)
+#define SUPPORTS_TV(i915) (DISPLAY_INFO(i915)->supports_tv)
+
+struct intel_display_runtime_info {
+ struct {
+ u16 ver;
+ u16 rel;
+ u16 step;
+ } ip;
+
+ u8 pipe_mask;
+ u8 cpu_transcoder_mask;
+
+ u8 num_sprites[I915_MAX_PIPES];
+ u8 num_scalers[I915_MAX_PIPES];
+
+ u8 fbc_mask;
+
+ bool has_hdcp;
+ bool has_dmc;
+ bool has_dsc;
+};
+
+struct intel_display_device_info {
+ /* Initial runtime info. */
+ const struct intel_display_runtime_info __runtime_defaults;
+
+ u8 abox_mask;
+
+ struct {
+ u16 size; /* in blocks */
+ u8 slice_mask;
+ } dbuf;
+
+#define DEFINE_FLAG(name) u8 name:1
+ DEV_INFO_DISPLAY_FOR_EACH_FLAG(DEFINE_FLAG);
+#undef DEFINE_FLAG
+
+ /* Global register offset for the display engine */
+ u32 mmio_offset;
+
+ /* Register offsets for the various display pipes and transcoders */
+ u32 pipe_offsets[I915_MAX_TRANSCODERS];
+ u32 trans_offsets[I915_MAX_TRANSCODERS];
+ u32 cursor_offsets[I915_MAX_PIPES];
+
+ struct {
+ u32 degamma_lut_size;
+ u32 gamma_lut_size;
+ u32 degamma_lut_tests;
+ u32 gamma_lut_tests;
+ } color;
+};
+
+const struct intel_display_device_info *
+intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid,
+ u16 *ver, u16 *rel, u16 *step);
+void intel_display_device_info_runtime_init(struct drm_i915_private *i915);
+
+#endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c
new file mode 100644
index 000000000000..b909814ae02b
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -0,0 +1,590 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2022-2023 Intel Corporation
+ *
+ * High level display driver entry points. This is a layer between top level
+ * driver code and low level display functionality; no low level display code or
+ * details here.
+ */
+
+#include <linux/vga_switcheroo.h>
+#include <acpi/video.h>
+#include <drm/display/drm_dp_mst_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_mode_config.h>
+#include <drm/drm_privacy_screen_consumer.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
+
+#include "i915_drv.h"
+#include "i9xx_wm.h"
+#include "intel_acpi.h"
+#include "intel_atomic.h"
+#include "intel_audio.h"
+#include "intel_bios.h"
+#include "intel_bw.h"
+#include "intel_cdclk.h"
+#include "intel_color.h"
+#include "intel_crtc.h"
+#include "intel_display_debugfs.h"
+#include "intel_display_driver.h"
+#include "intel_display_power.h"
+#include "intel_display_types.h"
+#include "intel_dkl_phy.h"
+#include "intel_dmc.h"
+#include "intel_dp.h"
+#include "intel_dpll.h"
+#include "intel_dpll_mgr.h"
+#include "intel_fb.h"
+#include "intel_fbc.h"
+#include "intel_fbdev.h"
+#include "intel_fdi.h"
+#include "intel_gmbus.h"
+#include "intel_hdcp.h"
+#include "intel_hotplug.h"
+#include "intel_hti.h"
+#include "intel_modeset_setup.h"
+#include "intel_opregion.h"
+#include "intel_overlay.h"
+#include "intel_plane_initial.h"
+#include "intel_pmdemand.h"
+#include "intel_pps.h"
+#include "intel_quirks.h"
+#include "intel_vga.h"
+#include "intel_wm.h"
+#include "skl_watermark.h"
+
+bool intel_display_driver_probe_defer(struct pci_dev *pdev)
+{
+ struct drm_privacy_screen *privacy_screen;
+
+ /*
+ * apple-gmux is needed on dual GPU MacBook Pro
+ * to probe the panel if we're the inactive GPU.
+ */
+ if (vga_switcheroo_client_probe_defer(pdev))
+ return true;
+
+ /* If the LCD panel has a privacy-screen, wait for it */
+ privacy_screen = drm_privacy_screen_get(&pdev->dev, NULL);
+ if (IS_ERR(privacy_screen) && PTR_ERR(privacy_screen) == -EPROBE_DEFER)
+ return true;
+
+ drm_privacy_screen_put(privacy_screen);
+
+ return false;
+}
+
+void intel_display_driver_init_hw(struct drm_i915_private *i915)
+{
+ struct intel_cdclk_state *cdclk_state;
+
+ if (!HAS_DISPLAY(i915))
+ return;
+
+ cdclk_state = to_intel_cdclk_state(i915->display.cdclk.obj.state);
+
+ intel_update_cdclk(i915);
+ intel_cdclk_dump_config(i915, &i915->display.cdclk.hw, "Current CDCLK");
+ cdclk_state->logical = cdclk_state->actual = i915->display.cdclk.hw;
+}
+
+static const struct drm_mode_config_funcs intel_mode_funcs = {
+ .fb_create = intel_user_framebuffer_create,
+ .get_format_info = intel_fb_get_format_info,
+ .output_poll_changed = intel_fbdev_output_poll_changed,
+ .mode_valid = intel_mode_valid,
+ .atomic_check = intel_atomic_check,
+ .atomic_commit = intel_atomic_commit,
+ .atomic_state_alloc = intel_atomic_state_alloc,
+ .atomic_state_clear = intel_atomic_state_clear,
+ .atomic_state_free = intel_atomic_state_free,
+};
+
+static const struct drm_mode_config_helper_funcs intel_mode_config_funcs = {
+ .atomic_commit_setup = drm_dp_mst_atomic_setup_commit,
+};
+
+static void intel_mode_config_init(struct drm_i915_private *i915)
+{
+ struct drm_mode_config *mode_config = &i915->drm.mode_config;
+
+ drm_mode_config_init(&i915->drm);
+ INIT_LIST_HEAD(&i915->display.global.obj_list);
+
+ mode_config->min_width = 0;
+ mode_config->min_height = 0;
+
+ mode_config->preferred_depth = 24;
+ mode_config->prefer_shadow = 1;
+
+ mode_config->funcs = &intel_mode_funcs;
+ mode_config->helper_private = &intel_mode_config_funcs;
+
+ mode_config->async_page_flip = HAS_ASYNC_FLIPS(i915);
+
+ /*
+ * Maximum framebuffer dimensions, chosen to match
+ * the maximum render engine surface size on gen4+.
+ */
+ if (DISPLAY_VER(i915) >= 7) {
+ mode_config->max_width = 16384;
+ mode_config->max_height = 16384;
+ } else if (DISPLAY_VER(i915) >= 4) {
+ mode_config->max_width = 8192;
+ mode_config->max_height = 8192;
+ } else if (DISPLAY_VER(i915) == 3) {
+ mode_config->max_width = 4096;
+ mode_config->max_height = 4096;
+ } else {
+ mode_config->max_width = 2048;
+ mode_config->max_height = 2048;
+ }
+
+ if (IS_I845G(i915) || IS_I865G(i915)) {
+ mode_config->cursor_width = IS_I845G(i915) ? 64 : 512;
+ mode_config->cursor_height = 1023;
+ } else if (IS_I830(i915) || IS_I85X(i915) ||
+ IS_I915G(i915) || IS_I915GM(i915)) {
+ mode_config->cursor_width = 64;
+ mode_config->cursor_height = 64;
+ } else {
+ mode_config->cursor_width = 256;
+ mode_config->cursor_height = 256;
+ }
+}
+
+static void intel_mode_config_cleanup(struct drm_i915_private *i915)
+{
+ intel_atomic_global_obj_cleanup(i915);
+ drm_mode_config_cleanup(&i915->drm);
+}
+
+static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
+{
+ struct intel_plane *plane;
+
+ for_each_intel_plane(&dev_priv->drm, plane) {
+ struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv,
+ plane->pipe);
+
+ plane->base.possible_crtcs = drm_crtc_mask(&crtc->base);
+ }
+}
+
+void intel_display_driver_early_probe(struct drm_i915_private *i915)
+{
+ if (!HAS_DISPLAY(i915))
+ return;
+
+ intel_dkl_phy_init(i915);
+ intel_color_init_hooks(i915);
+ intel_init_cdclk_hooks(i915);
+ intel_audio_hooks_init(i915);
+ intel_dpll_init_clock_hook(i915);
+ intel_init_display_hooks(i915);
+ intel_fdi_init_hook(i915);
+}
+
+/* part #1: call before irq install */
+int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
+{
+ int ret;
+
+ if (i915_inject_probe_failure(i915))
+ return -ENODEV;
+
+ if (HAS_DISPLAY(i915)) {
+ ret = drm_vblank_init(&i915->drm,
+ INTEL_NUM_PIPES(i915));
+ if (ret)
+ return ret;
+ }
+
+ intel_bios_init(i915);
+
+ ret = intel_vga_register(i915);
+ if (ret)
+ goto cleanup_bios;
+
+ /* FIXME: completely on the wrong abstraction layer */
+ ret = intel_power_domains_init(i915);
+ if (ret < 0)
+ goto cleanup_vga;
+
+ intel_pmdemand_init_early(i915);
+
+ intel_power_domains_init_hw(i915, false);
+
+ if (!HAS_DISPLAY(i915))
+ return 0;
+
+ intel_dmc_init(i915);
+
+ i915->display.wq.modeset = alloc_ordered_workqueue("i915_modeset", 0);
+ i915->display.wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI |
+ WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE);
+
+ intel_mode_config_init(i915);
+
+ ret = intel_cdclk_init(i915);
+ if (ret)
+ goto cleanup_vga_client_pw_domain_dmc;
+
+ ret = intel_color_init(i915);
+ if (ret)
+ goto cleanup_vga_client_pw_domain_dmc;
+
+ ret = intel_dbuf_init(i915);
+ if (ret)
+ goto cleanup_vga_client_pw_domain_dmc;
+
+ ret = intel_bw_init(i915);
+ if (ret)
+ goto cleanup_vga_client_pw_domain_dmc;
+
+ ret = intel_pmdemand_init(i915);
+ if (ret)
+ goto cleanup_vga_client_pw_domain_dmc;
+
+ init_llist_head(&i915->display.atomic_helper.free_list);
+ INIT_WORK(&i915->display.atomic_helper.free_work,
+ intel_atomic_helper_free_state_worker);
+
+ intel_init_quirks(i915);
+
+ intel_fbc_init(i915);
+
+ return 0;
+
+cleanup_vga_client_pw_domain_dmc:
+ intel_dmc_fini(i915);
+ intel_power_domains_driver_remove(i915);
+cleanup_vga:
+ intel_vga_unregister(i915);
+cleanup_bios:
+ intel_bios_driver_remove(i915);
+
+ return ret;
+}
+
+/* part #2: call after irq install, but before gem init */
+int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
+{
+ struct drm_device *dev = &i915->drm;
+ enum pipe pipe;
+ struct intel_crtc *crtc;
+ int ret;
+
+ if (!HAS_DISPLAY(i915))
+ return 0;
+
+ intel_wm_init(i915);
+
+ intel_panel_sanitize_ssc(i915);
+
+ intel_pps_setup(i915);
+
+ intel_gmbus_setup(i915);
+
+ drm_dbg_kms(&i915->drm, "%d display pipe%s available.\n",
+ INTEL_NUM_PIPES(i915),
+ INTEL_NUM_PIPES(i915) > 1 ? "s" : "");
+
+ for_each_pipe(i915, pipe) {
+ ret = intel_crtc_init(i915, pipe);
+ if (ret) {
+ intel_mode_config_cleanup(i915);
+ return ret;
+ }
+ }
+
+ intel_plane_possible_crtcs_init(i915);
+ intel_shared_dpll_init(i915);
+ intel_fdi_pll_freq_update(i915);
+
+ intel_update_czclk(i915);
+ intel_display_driver_init_hw(i915);
+ intel_dpll_update_ref_clks(i915);
+
+ intel_hdcp_component_init(i915);
+
+ if (i915->display.cdclk.max_cdclk_freq == 0)
+ intel_update_max_cdclk(i915);
+
+ intel_hti_init(i915);
+
+ /* Just disable it once at startup */
+ intel_vga_disable(i915);
+ intel_setup_outputs(i915);
+
+ drm_modeset_lock_all(dev);
+ intel_modeset_setup_hw_state(i915, dev->mode_config.acquire_ctx);
+ intel_acpi_assign_connector_fwnodes(i915);
+ drm_modeset_unlock_all(dev);
+
+ for_each_intel_crtc(dev, crtc) {
+ if (!to_intel_crtc_state(crtc->base.state)->uapi.active)
+ continue;
+ intel_crtc_initial_plane_config(crtc);
+ }
+
+ /*
+ * Make sure hardware watermarks really match the state we read out.
+ * Note that we need to do this after reconstructing the BIOS fb's
+ * since the watermark calculation done here will use pstate->fb.
+ */
+ if (!HAS_GMCH(i915))
+ ilk_wm_sanitize(i915);
+
+ return 0;
+}
+
+/* part #3: call after gem init */
+int intel_display_driver_probe(struct drm_i915_private *i915)
+{
+ int ret;
+
+ if (!HAS_DISPLAY(i915))
+ return 0;
+
+ /*
+ * Force all active planes to recompute their states. So that on
+ * mode_setcrtc after probe, all the intel_plane_state variables
+ * are already calculated and there is no assert_plane warnings
+ * during bootup.
+ */
+ ret = intel_initial_commit(&i915->drm);
+ if (ret)
+ drm_dbg_kms(&i915->drm, "Initial modeset failed, %d\n", ret);
+
+ intel_overlay_setup(i915);
+
+ ret = intel_fbdev_init(&i915->drm);
+ if (ret)
+ return ret;
+
+ /* Only enable hotplug handling once the fbdev is fully set up. */
+ intel_hpd_init(i915);
+ intel_hpd_poll_disable(i915);
+
+ skl_watermark_ipc_init(i915);
+
+ return 0;
+}
+
+void intel_display_driver_register(struct drm_i915_private *i915)
+{
+ if (!HAS_DISPLAY(i915))
+ return;
+
+ /* Must be done after probing outputs */
+ intel_opregion_register(i915);
+ intel_acpi_video_register(i915);
+
+ intel_audio_init(i915);
+
+ intel_display_debugfs_register(i915);
+
+ /*
+ * Some ports require correctly set-up hpd registers for
+ * detection to work properly (leading to ghost connected
+ * connector status), e.g. VGA on gm45. Hence we can only set
+ * up the initial fbdev config after hpd irqs are fully
+ * enabled. We do it last so that the async config cannot run
+ * before the connectors are registered.
+ */
+ intel_fbdev_initial_config_async(i915);
+
+ /*
+ * We need to coordinate the hotplugs with the asynchronous
+ * fbdev configuration, for which we use the
+ * fbdev->async_cookie.
+ */
+ drm_kms_helper_poll_init(&i915->drm);
+}
+
+/* part #1: call before irq uninstall */
+void intel_display_driver_remove(struct drm_i915_private *i915)
+{
+ if (!HAS_DISPLAY(i915))
+ return;
+
+ flush_workqueue(i915->display.wq.flip);
+ flush_workqueue(i915->display.wq.modeset);
+
+ flush_work(&i915->display.atomic_helper.free_work);
+ drm_WARN_ON(&i915->drm, !llist_empty(&i915->display.atomic_helper.free_list));
+
+ /*
+ * MST topology needs to be suspended so we don't have any calls to
+ * fbdev after it's finalized. MST will be destroyed later as part of
+ * drm_mode_config_cleanup()
+ */
+ intel_dp_mst_suspend(i915);
+}
+
+/* part #2: call after irq uninstall */
+void intel_display_driver_remove_noirq(struct drm_i915_private *i915)
+{
+ if (!HAS_DISPLAY(i915))
+ return;
+
+ /*
+ * Due to the hpd irq storm handling the hotplug work can re-arm the
+ * poll handlers. Hence disable polling after hpd handling is shut down.
+ */
+ intel_hpd_poll_fini(i915);
+
+ /* poll work can call into fbdev, hence clean that up afterwards */
+ intel_fbdev_fini(i915);
+
+ intel_unregister_dsm_handler();
+
+ /* flush any delayed tasks or pending work */
+ flush_workqueue(i915->unordered_wq);
+
+ intel_hdcp_component_fini(i915);
+
+ intel_mode_config_cleanup(i915);
+
+ intel_overlay_cleanup(i915);
+
+ intel_gmbus_teardown(i915);
+
+ destroy_workqueue(i915->display.wq.flip);
+ destroy_workqueue(i915->display.wq.modeset);
+
+ intel_fbc_cleanup(i915);
+}
+
+/* part #3: call after gem init */
+void intel_display_driver_remove_nogem(struct drm_i915_private *i915)
+{
+ intel_dmc_fini(i915);
+
+ intel_power_domains_driver_remove(i915);
+
+ intel_vga_unregister(i915);
+
+ intel_bios_driver_remove(i915);
+}
+
+void intel_display_driver_unregister(struct drm_i915_private *i915)
+{
+ if (!HAS_DISPLAY(i915))
+ return;
+
+ intel_fbdev_unregister(i915);
+ intel_audio_deinit(i915);
+
+ /*
+ * After flushing the fbdev (incl. a late async config which
+ * will have delayed queuing of a hotplug event), then flush
+ * the hotplug events.
+ */
+ drm_kms_helper_poll_fini(&i915->drm);
+ drm_atomic_helper_shutdown(&i915->drm);
+
+ acpi_video_unregister();
+ intel_opregion_unregister(i915);
+}
+
+/*
+ * turn all crtc's off, but do not adjust state
+ * This has to be paired with a call to intel_modeset_setup_hw_state.
+ */
+int intel_display_driver_suspend(struct drm_i915_private *i915)
+{
+ struct drm_atomic_state *state;
+ int ret;
+
+ if (!HAS_DISPLAY(i915))
+ return 0;
+
+ state = drm_atomic_helper_suspend(&i915->drm);
+ ret = PTR_ERR_OR_ZERO(state);
+ if (ret)
+ drm_err(&i915->drm, "Suspending crtc's failed with %i\n",
+ ret);
+ else
+ i915->display.restore.modeset_state = state;
+ return ret;
+}
+
+int
+__intel_display_driver_resume(struct drm_i915_private *i915,
+ struct drm_atomic_state *state,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_crtc *crtc;
+ int ret, i;
+
+ intel_modeset_setup_hw_state(i915, ctx);
+ intel_vga_redisable(i915);
+
+ if (!state)
+ return 0;
+
+ /*
+ * We've duplicated the state, pointers to the old state are invalid.
+ *
+ * Don't attempt to use the old state until we commit the duplicated state.
+ */
+ for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+ /*
+ * Force recalculation even if we restore
+ * current state. With fast modeset this may not result
+ * in a modeset when the state is compatible.
+ */
+ crtc_state->mode_changed = true;
+ }
+
+ /* ignore any reset values/BIOS leftovers in the WM registers */
+ if (!HAS_GMCH(i915))
+ to_intel_atomic_state(state)->skip_intermediate_wm = true;
+
+ ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
+
+ drm_WARN_ON(&i915->drm, ret == -EDEADLK);
+
+ return ret;
+}
+
+void intel_display_driver_resume(struct drm_i915_private *i915)
+{
+ struct drm_atomic_state *state = i915->display.restore.modeset_state;
+ struct drm_modeset_acquire_ctx ctx;
+ int ret;
+
+ if (!HAS_DISPLAY(i915))
+ return;
+
+ i915->display.restore.modeset_state = NULL;
+ if (state)
+ state->acquire_ctx = &ctx;
+
+ drm_modeset_acquire_init(&ctx, 0);
+
+ while (1) {
+ ret = drm_modeset_lock_all_ctx(&i915->drm, &ctx);
+ if (ret != -EDEADLK)
+ break;
+
+ drm_modeset_backoff(&ctx);
+ }
+
+ if (!ret)
+ ret = __intel_display_driver_resume(i915, state, &ctx);
+
+ skl_watermark_ipc_update(i915);
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
+
+ if (ret)
+ drm_err(&i915->drm,
+ "Restoring old state failed with %i\n", ret);
+ if (state)
+ drm_atomic_state_put(state);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.h b/drivers/gpu/drm/i915/display/intel_display_driver.h
new file mode 100644
index 000000000000..c276a58ee329
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022-2023 Intel Corporation
+ */
+
+#ifndef __INTEL_DISPLAY_DRIVER_H__
+#define __INTEL_DISPLAY_DRIVER_H__
+
+#include <linux/types.h>
+
+struct drm_atomic_state;
+struct drm_i915_private;
+struct drm_modeset_acquire_ctx;
+struct pci_dev;
+
+bool intel_display_driver_probe_defer(struct pci_dev *pdev);
+void intel_display_driver_init_hw(struct drm_i915_private *i915);
+void intel_display_driver_early_probe(struct drm_i915_private *i915);
+int intel_display_driver_probe_noirq(struct drm_i915_private *i915);
+int intel_display_driver_probe_nogem(struct drm_i915_private *i915);
+int intel_display_driver_probe(struct drm_i915_private *i915);
+void intel_display_driver_register(struct drm_i915_private *i915);
+void intel_display_driver_remove(struct drm_i915_private *i915);
+void intel_display_driver_remove_noirq(struct drm_i915_private *i915);
+void intel_display_driver_remove_nogem(struct drm_i915_private *i915);
+void intel_display_driver_unregister(struct drm_i915_private *i915);
+int intel_display_driver_suspend(struct drm_i915_private *i915);
+void intel_display_driver_resume(struct drm_i915_private *i915);
+
+/* interface for intel_display_reset.c */
+int __intel_display_driver_resume(struct drm_i915_private *i915,
+ struct drm_atomic_state *state,
+ struct drm_modeset_acquire_ctx *ctx);
+
+#endif /* __INTEL_DISPLAY_DRIVER_H__ */
+
diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c
new file mode 100644
index 000000000000..ae2578741dfe
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
@@ -0,0 +1,1687 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include "gt/intel_rps.h"
+#include "i915_drv.h"
+#include "i915_irq.h"
+#include "i915_reg.h"
+#include "icl_dsi_regs.h"
+#include "intel_crtc.h"
+#include "intel_de.h"
+#include "intel_display_irq.h"
+#include "intel_display_trace.h"
+#include "intel_display_types.h"
+#include "intel_dp_aux.h"
+#include "intel_fdi_regs.h"
+#include "intel_fifo_underrun.h"
+#include "intel_gmbus.h"
+#include "intel_hotplug_irq.h"
+#include "intel_pmdemand.h"
+#include "intel_psr.h"
+#include "intel_psr_regs.h"
+
+static void
+intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+ struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
+
+ drm_crtc_handle_vblank(&crtc->base);
+}
+
+/**
+ * ilk_update_display_irq - update DEIMR
+ * @dev_priv: driver private
+ * @interrupt_mask: mask of interrupt bits to update
+ * @enabled_irq_mask: mask of interrupt bits to enable
+ */
+void ilk_update_display_irq(struct drm_i915_private *dev_priv,
+ u32 interrupt_mask, u32 enabled_irq_mask)
+{
+ u32 new_val;
+
+ lockdep_assert_held(&dev_priv->irq_lock);
+ drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
+
+ new_val = dev_priv->irq_mask;
+ new_val &= ~interrupt_mask;
+ new_val |= (~enabled_irq_mask & interrupt_mask);
+
+ if (new_val != dev_priv->irq_mask &&
+ !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) {
+ dev_priv->irq_mask = new_val;
+ intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask);
+ intel_uncore_posting_read(&dev_priv->uncore, DEIMR);
+ }
+}
+
+void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits)
+{
+ ilk_update_display_irq(i915, bits, bits);
+}
+
+void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits)
+{
+ ilk_update_display_irq(i915, bits, 0);
+}
+
+/**
+ * bdw_update_port_irq - update DE port interrupt
+ * @dev_priv: driver private
+ * @interrupt_mask: mask of interrupt bits to update
+ * @enabled_irq_mask: mask of interrupt bits to enable
+ */
+void bdw_update_port_irq(struct drm_i915_private *dev_priv,
+ u32 interrupt_mask, u32 enabled_irq_mask)
+{
+ u32 new_val;
+ u32 old_val;
+
+ lockdep_assert_held(&dev_priv->irq_lock);
+
+ drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
+
+ if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
+ return;
+
+ old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR);
+
+ new_val = old_val;
+ new_val &= ~interrupt_mask;
+ new_val |= (~enabled_irq_mask & interrupt_mask);
+
+ if (new_val != old_val) {
+ intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val);
+ intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR);
+ }
+}
+
+/**
+ * bdw_update_pipe_irq - update DE pipe interrupt
+ * @dev_priv: driver private
+ * @pipe: pipe whose interrupt to update
+ * @interrupt_mask: mask of interrupt bits to update
+ * @enabled_irq_mask: mask of interrupt bits to enable
+ */
+static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
+ enum pipe pipe, u32 interrupt_mask,
+ u32 enabled_irq_mask)
+{
+ u32 new_val;
+
+ lockdep_assert_held(&dev_priv->irq_lock);
+
+ drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
+
+ if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
+ return;
+
+ new_val = dev_priv->de_irq_mask[pipe];
+ new_val &= ~interrupt_mask;
+ new_val |= (~enabled_irq_mask & interrupt_mask);
+
+ if (new_val != dev_priv->de_irq_mask[pipe]) {
+ dev_priv->de_irq_mask[pipe] = new_val;
+ intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
+ intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe));
+ }
+}
+
+void bdw_enable_pipe_irq(struct drm_i915_private *i915,
+ enum pipe pipe, u32 bits)
+{
+ bdw_update_pipe_irq(i915, pipe, bits, bits);
+}
+
+void bdw_disable_pipe_irq(struct drm_i915_private *i915,
+ enum pipe pipe, u32 bits)
+{
+ bdw_update_pipe_irq(i915, pipe, bits, 0);
+}
+
+/**
+ * ibx_display_interrupt_update - update SDEIMR
+ * @dev_priv: driver private
+ * @interrupt_mask: mask of interrupt bits to update
+ * @enabled_irq_mask: mask of interrupt bits to enable
+ */
+void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
+ u32 interrupt_mask,
+ u32 enabled_irq_mask)
+{
+ u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR);
+
+ sdeimr &= ~interrupt_mask;
+ sdeimr |= (~enabled_irq_mask & interrupt_mask);
+
+ drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
+
+ lockdep_assert_held(&dev_priv->irq_lock);
+
+ if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
+ return;
+
+ intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr);
+ intel_uncore_posting_read(&dev_priv->uncore, SDEIMR);
+}
+
+void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits)
+{
+ ibx_display_interrupt_update(i915, bits, bits);
+}
+
+void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits)
+{
+ ibx_display_interrupt_update(i915, bits, 0);
+}
+
+u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv,
+ enum pipe pipe)
+{
+ u32 status_mask = dev_priv->pipestat_irq_mask[pipe];
+ u32 enable_mask = status_mask << 16;
+
+ lockdep_assert_held(&dev_priv->irq_lock);
+
+ if (DISPLAY_VER(dev_priv) < 5)
+ goto out;
+
+ /*
+ * On pipe A we don't support the PSR interrupt yet,
+ * on pipe B and C the same bit MBZ.
+ */
+ if (drm_WARN_ON_ONCE(&dev_priv->drm,
+ status_mask & PIPE_A_PSR_STATUS_VLV))
+ return 0;
+ /*
+ * On pipe B and C we don't support the PSR interrupt yet, on pipe
+ * A the same bit is for perf counters which we don't use either.
+ */
+ if (drm_WARN_ON_ONCE(&dev_priv->drm,
+ status_mask & PIPE_B_PSR_STATUS_VLV))
+ return 0;
+
+ enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS |
+ SPRITE0_FLIP_DONE_INT_EN_VLV |
+ SPRITE1_FLIP_DONE_INT_EN_VLV);
+ if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV)
+ enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV;
+ if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV)
+ enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV;
+
+out:
+ drm_WARN_ONCE(&dev_priv->drm,
+ enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
+ status_mask & ~PIPESTAT_INT_STATUS_MASK,
+ "pipe %c: enable_mask=0x%x, status_mask=0x%x\n",
+ pipe_name(pipe), enable_mask, status_mask);
+
+ return enable_mask;
+}
+
+void i915_enable_pipestat(struct drm_i915_private *dev_priv,
+ enum pipe pipe, u32 status_mask)
+{
+ i915_reg_t reg = PIPESTAT(pipe);
+ u32 enable_mask;
+
+ drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK,
+ "pipe %c: status_mask=0x%x\n",
+ pipe_name(pipe), status_mask);
+
+ lockdep_assert_held(&dev_priv->irq_lock);
+ drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
+
+ if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask)
+ return;
+
+ dev_priv->pipestat_irq_mask[pipe] |= status_mask;
+ enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
+
+ intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask);
+ intel_uncore_posting_read(&dev_priv->uncore, reg);
+}
+
+void i915_disable_pipestat(struct drm_i915_private *dev_priv,
+ enum pipe pipe, u32 status_mask)
+{
+ i915_reg_t reg = PIPESTAT(pipe);
+ u32 enable_mask;
+
+ drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK,
+ "pipe %c: status_mask=0x%x\n",
+ pipe_name(pipe), status_mask);
+
+ lockdep_assert_held(&dev_priv->irq_lock);
+ drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
+
+ if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0)
+ return;
+
+ dev_priv->pipestat_irq_mask[pipe] &= ~status_mask;
+ enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
+
+ intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask);
+ intel_uncore_posting_read(&dev_priv->uncore, reg);
+}
+
+static bool i915_has_asle(struct drm_i915_private *dev_priv)
+{
+ if (!dev_priv->display.opregion.asle)
+ return false;
+
+ return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv);
+}
+
+/**
+ * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion
+ * @dev_priv: i915 device private
+ */
+void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv)
+{
+ if (!i915_has_asle(dev_priv))
+ return;
+
+ spin_lock_irq(&dev_priv->irq_lock);
+
+ i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS);
+ if (DISPLAY_VER(dev_priv) >= 4)
+ i915_enable_pipestat(dev_priv, PIPE_A,
+ PIPE_LEGACY_BLC_EVENT_STATUS);
+
+ spin_unlock_irq(&dev_priv->irq_lock);
+}
+
+#if defined(CONFIG_DEBUG_FS)
+static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
+ enum pipe pipe,
+ u32 crc0, u32 crc1,
+ u32 crc2, u32 crc3,
+ u32 crc4)
+{
+ struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
+ struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
+ u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 };
+
+ trace_intel_pipe_crc(crtc, crcs);
+
+ spin_lock(&pipe_crc->lock);
+ /*
+ * For some not yet identified reason, the first CRC is
+ * bonkers. So let's just wait for the next vblank and read
+ * out the buggy result.
+ *
+ * On GEN8+ sometimes the second CRC is bonkers as well, so
+ * don't trust that one either.
+ */
+ if (pipe_crc->skipped <= 0 ||
+ (DISPLAY_VER(dev_priv) >= 8 && pipe_crc->skipped == 1)) {
+ pipe_crc->skipped++;
+ spin_unlock(&pipe_crc->lock);
+ return;
+ }
+ spin_unlock(&pipe_crc->lock);
+
+ drm_crtc_add_crc_entry(&crtc->base, true,
+ drm_crtc_accurate_vblank_count(&crtc->base),
+ crcs);
+}
+#else
+static inline void
+display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
+ enum pipe pipe,
+ u32 crc0, u32 crc1,
+ u32 crc2, u32 crc3,
+ u32 crc4) {}
+#endif
+
+static void flip_done_handler(struct drm_i915_private *i915,
+ enum pipe pipe)
+{
+ struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe);
+ struct drm_crtc_state *crtc_state = crtc->base.state;
+ struct drm_pending_vblank_event *e = crtc_state->event;
+ struct drm_device *dev = &i915->drm;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev->event_lock, irqflags);
+
+ crtc_state->event = NULL;
+
+ drm_crtc_send_vblank_event(&crtc->base, e);
+
+ spin_unlock_irqrestore(&dev->event_lock, irqflags);
+}
+
+static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
+ enum pipe pipe)
+{
+ display_pipe_crc_irq_handler(dev_priv, pipe,
+ intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)),
+ 0, 0, 0, 0);
+}
+
+static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
+ enum pipe pipe)
+{
+ display_pipe_crc_irq_handler(dev_priv, pipe,
+ intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)),
+ intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)),
+ intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)),
+ intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)),
+ intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe)));
+}
+
+static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
+ enum pipe pipe)
+{
+ u32 res1, res2;
+
+ if (DISPLAY_VER(dev_priv) >= 3)
+ res1 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES1_I915(pipe));
+ else
+ res1 = 0;
+
+ if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
+ res2 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES2_G4X(pipe));
+ else
+ res2 = 0;
+
+ display_pipe_crc_irq_handler(dev_priv, pipe,
+ intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(pipe)),
+ intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(pipe)),
+ intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(pipe)),
+ res1, res2);
+}
+
+void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv)
+{
+ enum pipe pipe;
+
+ for_each_pipe(dev_priv, pipe) {
+ intel_uncore_write(&dev_priv->uncore, PIPESTAT(pipe),
+ PIPESTAT_INT_STATUS_MASK |
+ PIPE_FIFO_UNDERRUN_STATUS);
+
+ dev_priv->pipestat_irq_mask[pipe] = 0;
+ }
+}
+
+void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv,
+ u32 iir, u32 pipe_stats[I915_MAX_PIPES])
+{
+ enum pipe pipe;
+
+ spin_lock(&dev_priv->irq_lock);
+
+ if (!dev_priv->display_irqs_enabled) {
+ spin_unlock(&dev_priv->irq_lock);
+ return;
+ }
+
+ for_each_pipe(dev_priv, pipe) {
+ i915_reg_t reg;
+ u32 status_mask, enable_mask, iir_bit = 0;
+
+ /*
+ * PIPESTAT bits get signalled even when the interrupt is
+ * disabled with the mask bits, and some of the status bits do
+ * not generate interrupts at all (like the underrun bit). Hence
+ * we need to be careful that we only handle what we want to
+ * handle.
+ */
+
+ /* fifo underruns are filterered in the underrun handler. */
+ status_mask = PIPE_FIFO_UNDERRUN_STATUS;
+
+ switch (pipe) {
+ default:
+ case PIPE_A:
+ iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
+ break;
+ case PIPE_B:
+ iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+ break;
+ case PIPE_C:
+ iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
+ break;
+ }
+ if (iir & iir_bit)
+ status_mask |= dev_priv->pipestat_irq_mask[pipe];
+
+ if (!status_mask)
+ continue;
+
+ reg = PIPESTAT(pipe);
+ pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask;
+ enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
+
+ /*
+ * Clear the PIPE*STAT regs before the IIR
+ *
+ * Toggle the enable bits to make sure we get an
+ * edge in the ISR pipe event bit if we don't clear
+ * all the enabled status bits. Otherwise the edge
+ * triggered IIR on i965/g4x wouldn't notice that
+ * an interrupt is still pending.
+ */
+ if (pipe_stats[pipe]) {
+ intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]);
+ intel_uncore_write(&dev_priv->uncore, reg, enable_mask);
+ }
+ }
+ spin_unlock(&dev_priv->irq_lock);
+}
+
+void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv,
+ u16 iir, u32 pipe_stats[I915_MAX_PIPES])
+{
+ enum pipe pipe;
+
+ for_each_pipe(dev_priv, pipe) {
+ if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
+ intel_handle_vblank(dev_priv, pipe);
+
+ if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
+ i9xx_pipe_crc_irq_handler(dev_priv, pipe);
+
+ if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+ intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
+ }
+}
+
+void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv,
+ u32 iir, u32 pipe_stats[I915_MAX_PIPES])
+{
+ bool blc_event = false;
+ enum pipe pipe;
+
+ for_each_pipe(dev_priv, pipe) {
+ if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
+ intel_handle_vblank(dev_priv, pipe);
+
+ if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
+ blc_event = true;
+
+ if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
+ i9xx_pipe_crc_irq_handler(dev_priv, pipe);
+
+ if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+ intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
+ }
+
+ if (blc_event || (iir & I915_ASLE_INTERRUPT))
+ intel_opregion_asle_intr(dev_priv);
+}
+
+void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv,
+ u32 iir, u32 pipe_stats[I915_MAX_PIPES])
+{
+ bool blc_event = false;
+ enum pipe pipe;
+
+ for_each_pipe(dev_priv, pipe) {
+ if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
+ intel_handle_vblank(dev_priv, pipe);
+
+ if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
+ blc_event = true;
+
+ if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
+ i9xx_pipe_crc_irq_handler(dev_priv, pipe);
+
+ if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+ intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
+ }
+
+ if (blc_event || (iir & I915_ASLE_INTERRUPT))
+ intel_opregion_asle_intr(dev_priv);
+
+ if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
+ intel_gmbus_irq_handler(dev_priv);
+}
+
+void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
+ u32 pipe_stats[I915_MAX_PIPES])
+{
+ enum pipe pipe;
+
+ for_each_pipe(dev_priv, pipe) {
+ if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
+ intel_handle_vblank(dev_priv, pipe);
+
+ if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV)
+ flip_done_handler(dev_priv, pipe);
+
+ if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
+ i9xx_pipe_crc_irq_handler(dev_priv, pipe);
+
+ if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+ intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
+ }
+
+ if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
+ intel_gmbus_irq_handler(dev_priv);
+}
+
+static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
+{
+ enum pipe pipe;
+ u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
+
+ ibx_hpd_irq_handler(dev_priv, hotplug_trigger);
+
+ if (pch_iir & SDE_AUDIO_POWER_MASK) {
+ int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >>
+ SDE_AUDIO_POWER_SHIFT);
+ drm_dbg(&dev_priv->drm, "PCH audio power change on port %d\n",
+ port_name(port));
+ }
+
+ if (pch_iir & SDE_AUX_MASK)
+ intel_dp_aux_irq_handler(dev_priv);
+
+ if (pch_iir & SDE_GMBUS)
+ intel_gmbus_irq_handler(dev_priv);
+
+ if (pch_iir & SDE_AUDIO_HDCP_MASK)
+ drm_dbg(&dev_priv->drm, "PCH HDCP audio interrupt\n");
+
+ if (pch_iir & SDE_AUDIO_TRANS_MASK)
+ drm_dbg(&dev_priv->drm, "PCH transcoder audio interrupt\n");
+
+ if (pch_iir & SDE_POISON)
+ drm_err(&dev_priv->drm, "PCH poison interrupt\n");
+
+ if (pch_iir & SDE_FDI_MASK) {
+ for_each_pipe(dev_priv, pipe)
+ drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n",
+ pipe_name(pipe),
+ intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe)));
+ }
+
+ if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE))
+ drm_dbg(&dev_priv->drm, "PCH transcoder CRC done interrupt\n");
+
+ if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
+ drm_dbg(&dev_priv->drm,
+ "PCH transcoder CRC error interrupt\n");
+
+ if (pch_iir & SDE_TRANSA_FIFO_UNDER)
+ intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A);
+
+ if (pch_iir & SDE_TRANSB_FIFO_UNDER)
+ intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B);
+}
+
+static void ivb_err_int_handler(struct drm_i915_private *dev_priv)
+{
+ u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT);
+ enum pipe pipe;
+
+ if (err_int & ERR_INT_POISON)
+ drm_err(&dev_priv->drm, "Poison interrupt\n");
+
+ for_each_pipe(dev_priv, pipe) {
+ if (err_int & ERR_INT_FIFO_UNDERRUN(pipe))
+ intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
+
+ if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) {
+ if (IS_IVYBRIDGE(dev_priv))
+ ivb_pipe_crc_irq_handler(dev_priv, pipe);
+ else
+ hsw_pipe_crc_irq_handler(dev_priv, pipe);
+ }
+ }
+
+ intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int);
+}
+
+static void cpt_serr_int_handler(struct drm_i915_private *dev_priv)
+{
+ u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT);
+ enum pipe pipe;
+
+ if (serr_int & SERR_INT_POISON)
+ drm_err(&dev_priv->drm, "PCH poison interrupt\n");
+
+ for_each_pipe(dev_priv, pipe)
+ if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe))
+ intel_pch_fifo_underrun_irq_handler(dev_priv, pipe);
+
+ intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int);
+}
+
+static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
+{
+ enum pipe pipe;
+ u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
+
+ ibx_hpd_irq_handler(dev_priv, hotplug_trigger);
+
+ if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) {
+ int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
+ SDE_AUDIO_POWER_SHIFT_CPT);
+ drm_dbg(&dev_priv->drm, "PCH audio power change on port %c\n",
+ port_name(port));
+ }
+
+ if (pch_iir & SDE_AUX_MASK_CPT)
+ intel_dp_aux_irq_handler(dev_priv);
+
+ if (pch_iir & SDE_GMBUS_CPT)
+ intel_gmbus_irq_handler(dev_priv);
+
+ if (pch_iir & SDE_AUDIO_CP_REQ_CPT)
+ drm_dbg(&dev_priv->drm, "Audio CP request interrupt\n");
+
+ if (pch_iir & SDE_AUDIO_CP_CHG_CPT)
+ drm_dbg(&dev_priv->drm, "Audio CP change interrupt\n");
+
+ if (pch_iir & SDE_FDI_MASK_CPT) {
+ for_each_pipe(dev_priv, pipe)
+ drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n",
+ pipe_name(pipe),
+ intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe)));
+ }
+
+ if (pch_iir & SDE_ERROR_CPT)
+ cpt_serr_int_handler(dev_priv);
+}
+
+void ilk_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir)
+{
+ enum pipe pipe;
+ u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG;
+
+ if (hotplug_trigger)
+ ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
+
+ if (de_iir & DE_AUX_CHANNEL_A)
+ intel_dp_aux_irq_handler(dev_priv);
+
+ if (de_iir & DE_GSE)
+ intel_opregion_asle_intr(dev_priv);
+
+ if (de_iir & DE_POISON)
+ drm_err(&dev_priv->drm, "Poison interrupt\n");
+
+ for_each_pipe(dev_priv, pipe) {
+ if (de_iir & DE_PIPE_VBLANK(pipe))
+ intel_handle_vblank(dev_priv, pipe);
+
+ if (de_iir & DE_PLANE_FLIP_DONE(pipe))
+ flip_done_handler(dev_priv, pipe);
+
+ if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
+ intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
+
+ if (de_iir & DE_PIPE_CRC_DONE(pipe))
+ i9xx_pipe_crc_irq_handler(dev_priv, pipe);
+ }
+
+ /* check event from PCH */
+ if (de_iir & DE_PCH_EVENT) {
+ u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
+
+ if (HAS_PCH_CPT(dev_priv))
+ cpt_irq_handler(dev_priv, pch_iir);
+ else
+ ibx_irq_handler(dev_priv, pch_iir);
+
+ /* should clear PCH hotplug event before clear CPU irq */
+ intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir);
+ }
+
+ if (DISPLAY_VER(dev_priv) == 5 && de_iir & DE_PCU_EVENT)
+ gen5_rps_irq_handler(&to_gt(dev_priv)->rps);
+}
+
+void ivb_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir)
+{
+ enum pipe pipe;
+ u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB;
+
+ if (hotplug_trigger)
+ ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
+
+ if (de_iir & DE_ERR_INT_IVB)
+ ivb_err_int_handler(dev_priv);
+
+ if (de_iir & DE_AUX_CHANNEL_A_IVB)
+ intel_dp_aux_irq_handler(dev_priv);
+
+ if (de_iir & DE_GSE_IVB)
+ intel_opregion_asle_intr(dev_priv);
+
+ for_each_pipe(dev_priv, pipe) {
+ if (de_iir & DE_PIPE_VBLANK_IVB(pipe))
+ intel_handle_vblank(dev_priv, pipe);
+
+ if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe))
+ flip_done_handler(dev_priv, pipe);
+ }
+
+ /* check event from PCH */
+ if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) {
+ u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
+
+ cpt_irq_handler(dev_priv, pch_iir);
+
+ /* clear PCH hotplug event before clear CPU irq */
+ intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir);
+ }
+}
+
+static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
+{
+ u32 mask;
+
+ if (DISPLAY_VER(dev_priv) >= 14)
+ return TGL_DE_PORT_AUX_DDIA |
+ TGL_DE_PORT_AUX_DDIB;
+ else if (DISPLAY_VER(dev_priv) >= 13)
+ return TGL_DE_PORT_AUX_DDIA |
+ TGL_DE_PORT_AUX_DDIB |
+ TGL_DE_PORT_AUX_DDIC |
+ XELPD_DE_PORT_AUX_DDID |
+ XELPD_DE_PORT_AUX_DDIE |
+ TGL_DE_PORT_AUX_USBC1 |
+ TGL_DE_PORT_AUX_USBC2 |
+ TGL_DE_PORT_AUX_USBC3 |
+ TGL_DE_PORT_AUX_USBC4;
+ else if (DISPLAY_VER(dev_priv) >= 12)
+ return TGL_DE_PORT_AUX_DDIA |
+ TGL_DE_PORT_AUX_DDIB |
+ TGL_DE_PORT_AUX_DDIC |
+ TGL_DE_PORT_AUX_USBC1 |
+ TGL_DE_PORT_AUX_USBC2 |
+ TGL_DE_PORT_AUX_USBC3 |
+ TGL_DE_PORT_AUX_USBC4 |
+ TGL_DE_PORT_AUX_USBC5 |
+ TGL_DE_PORT_AUX_USBC6;
+
+ mask = GEN8_AUX_CHANNEL_A;
+ if (DISPLAY_VER(dev_priv) >= 9)
+ mask |= GEN9_AUX_CHANNEL_B |
+ GEN9_AUX_CHANNEL_C |
+ GEN9_AUX_CHANNEL_D;
+
+ if (DISPLAY_VER(dev_priv) == 11) {
+ mask |= ICL_AUX_CHANNEL_F;
+ mask |= ICL_AUX_CHANNEL_E;
+ }
+
+ return mask;
+}
+
+static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
+{
+ if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv))
+ return RKL_DE_PIPE_IRQ_FAULT_ERRORS;
+ else if (DISPLAY_VER(dev_priv) >= 11)
+ return GEN11_DE_PIPE_IRQ_FAULT_ERRORS;
+ else if (DISPLAY_VER(dev_priv) >= 9)
+ return GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
+ else
+ return GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
+}
+
+static void intel_pmdemand_irq_handler(struct drm_i915_private *dev_priv)
+{
+ wake_up_all(&dev_priv->display.pmdemand.waitqueue);
+}
+
+static void
+gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
+{
+ bool found = false;
+
+ if (DISPLAY_VER(dev_priv) >= 14) {
+ if (iir & (XELPDP_PMDEMAND_RSP |
+ XELPDP_PMDEMAND_RSPTOUT_ERR)) {
+ if (iir & XELPDP_PMDEMAND_RSPTOUT_ERR)
+ drm_dbg(&dev_priv->drm,
+ "Error waiting for Punit PM Demand Response\n");
+
+ intel_pmdemand_irq_handler(dev_priv);
+ found = true;
+ }
+ } else if (iir & GEN8_DE_MISC_GSE) {
+ intel_opregion_asle_intr(dev_priv);
+ found = true;
+ }
+
+ if (iir & GEN8_DE_EDP_PSR) {
+ struct intel_encoder *encoder;
+ u32 psr_iir;
+ i915_reg_t iir_reg;
+
+ for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ if (DISPLAY_VER(dev_priv) >= 12)
+ iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder);
+ else
+ iir_reg = EDP_PSR_IIR;
+
+ psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0);
+
+ if (psr_iir)
+ found = true;
+
+ intel_psr_irq_handler(intel_dp, psr_iir);
+
+ /* prior GEN12 only have one EDP PSR */
+ if (DISPLAY_VER(dev_priv) < 12)
+ break;
+ }
+ }
+
+ if (!found)
+ drm_err(&dev_priv->drm, "Unexpected DE Misc interrupt\n");
+}
+
+static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv,
+ u32 te_trigger)
+{
+ enum pipe pipe = INVALID_PIPE;
+ enum transcoder dsi_trans;
+ enum port port;
+ u32 val;
+
+ /*
+ * Incase of dual link, TE comes from DSI_1
+ * this is to check if dual link is enabled
+ */
+ val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0));
+ val &= PORT_SYNC_MODE_ENABLE;
+
+ /*
+ * if dual link is enabled, then read DSI_0
+ * transcoder registers
+ */
+ port = ((te_trigger & DSI1_TE && val) || (te_trigger & DSI0_TE)) ?
+ PORT_A : PORT_B;
+ dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1;
+
+ /* Check if DSI configured in command mode */
+ val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans));
+ val = val & OP_MODE_MASK;
+
+ if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) {
+ drm_err(&dev_priv->drm, "DSI trancoder not configured in command mode\n");
+ return;
+ }
+
+ /* Get PIPE for handling VBLANK event */
+ val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL(dsi_trans));
+ switch (val & TRANS_DDI_EDP_INPUT_MASK) {
+ case TRANS_DDI_EDP_INPUT_A_ON:
+ pipe = PIPE_A;
+ break;
+ case TRANS_DDI_EDP_INPUT_B_ONOFF:
+ pipe = PIPE_B;
+ break;
+ case TRANS_DDI_EDP_INPUT_C_ONOFF:
+ pipe = PIPE_C;
+ break;
+ default:
+ drm_err(&dev_priv->drm, "Invalid PIPE\n");
+ return;
+ }
+
+ intel_handle_vblank(dev_priv, pipe);
+
+ /* clear TE in dsi IIR */
+ port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A;
+ intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
+}
+
+static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915)
+{
+ if (DISPLAY_VER(i915) >= 9)
+ return GEN9_PIPE_PLANE1_FLIP_DONE;
+ else
+ return GEN8_PIPE_PRIMARY_FLIP_DONE;
+}
+
+u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv)
+{
+ u32 mask = GEN8_PIPE_FIFO_UNDERRUN;
+
+ if (DISPLAY_VER(dev_priv) >= 13)
+ mask |= XELPD_PIPE_SOFT_UNDERRUN |
+ XELPD_PIPE_HARD_UNDERRUN;
+
+ return mask;
+}
+
+static void gen8_read_and_ack_pch_irqs(struct drm_i915_private *i915, u32 *pch_iir, u32 *pica_iir)
+{
+ u32 pica_ier = 0;
+
+ *pica_iir = 0;
+ *pch_iir = intel_de_read(i915, SDEIIR);
+ if (!*pch_iir)
+ return;
+
+ /**
+ * PICA IER must be disabled/re-enabled around clearing PICA IIR and
+ * SDEIIR, to avoid losing PICA IRQs and to ensure that such IRQs set
+ * their flags both in the PICA and SDE IIR.
+ */
+ if (*pch_iir & SDE_PICAINTERRUPT) {
+ drm_WARN_ON(&i915->drm, INTEL_PCH_TYPE(i915) < PCH_MTP);
+
+ pica_ier = intel_de_rmw(i915, PICAINTERRUPT_IER, ~0, 0);
+ *pica_iir = intel_de_read(i915, PICAINTERRUPT_IIR);
+ intel_de_write(i915, PICAINTERRUPT_IIR, *pica_iir);
+ }
+
+ intel_de_write(i915, SDEIIR, *pch_iir);
+
+ if (pica_ier)
+ intel_de_write(i915, PICAINTERRUPT_IER, pica_ier);
+}
+
+void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
+{
+ u32 iir;
+ enum pipe pipe;
+
+ drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DISPLAY(dev_priv));
+
+ if (master_ctl & GEN8_DE_MISC_IRQ) {
+ iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR);
+ if (iir) {
+ intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir);
+ gen8_de_misc_irq_handler(dev_priv, iir);
+ } else {
+ drm_err_ratelimited(&dev_priv->drm,
+ "The master control interrupt lied (DE MISC)!\n");
+ }
+ }
+
+ if (DISPLAY_VER(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) {
+ iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR);
+ if (iir) {
+ intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir);
+ gen11_hpd_irq_handler(dev_priv, iir);
+ } else {
+ drm_err_ratelimited(&dev_priv->drm,
+ "The master control interrupt lied, (DE HPD)!\n");
+ }
+ }
+
+ if (master_ctl & GEN8_DE_PORT_IRQ) {
+ iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR);
+ if (iir) {
+ bool found = false;
+
+ intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir);
+
+ if (iir & gen8_de_port_aux_mask(dev_priv)) {
+ intel_dp_aux_irq_handler(dev_priv);
+ found = true;
+ }
+
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
+ u32 hotplug_trigger = iir & BXT_DE_PORT_HOTPLUG_MASK;
+
+ if (hotplug_trigger) {
+ bxt_hpd_irq_handler(dev_priv, hotplug_trigger);
+ found = true;
+ }
+ } else if (IS_BROADWELL(dev_priv)) {
+ u32 hotplug_trigger = iir & BDW_DE_PORT_HOTPLUG_MASK;
+
+ if (hotplug_trigger) {
+ ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
+ found = true;
+ }
+ }
+
+ if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
+ (iir & BXT_DE_PORT_GMBUS)) {
+ intel_gmbus_irq_handler(dev_priv);
+ found = true;
+ }
+
+ if (DISPLAY_VER(dev_priv) >= 11) {
+ u32 te_trigger = iir & (DSI0_TE | DSI1_TE);
+
+ if (te_trigger) {
+ gen11_dsi_te_interrupt_handler(dev_priv, te_trigger);
+ found = true;
+ }
+ }
+
+ if (!found)
+ drm_err_ratelimited(&dev_priv->drm,
+ "Unexpected DE Port interrupt\n");
+ } else {
+ drm_err_ratelimited(&dev_priv->drm,
+ "The master control interrupt lied (DE PORT)!\n");
+ }
+ }
+
+ for_each_pipe(dev_priv, pipe) {
+ u32 fault_errors;
+
+ if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe)))
+ continue;
+
+ iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe));
+ if (!iir) {
+ drm_err_ratelimited(&dev_priv->drm,
+ "The master control interrupt lied (DE PIPE)!\n");
+ continue;
+ }
+
+ intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir);
+
+ if (iir & GEN8_PIPE_VBLANK)
+ intel_handle_vblank(dev_priv, pipe);
+
+ if (iir & gen8_de_pipe_flip_done_mask(dev_priv))
+ flip_done_handler(dev_priv, pipe);
+
+ if (iir & GEN8_PIPE_CDCLK_CRC_DONE)
+ hsw_pipe_crc_irq_handler(dev_priv, pipe);
+
+ if (iir & gen8_de_pipe_underrun_mask(dev_priv))
+ intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
+
+ fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
+ if (fault_errors)
+ drm_err_ratelimited(&dev_priv->drm,
+ "Fault errors on pipe %c: 0x%08x\n",
+ pipe_name(pipe),
+ fault_errors);
+ }
+
+ if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
+ master_ctl & GEN8_DE_PCH_IRQ) {
+ u32 pica_iir;
+
+ /*
+ * FIXME(BDW): Assume for now that the new interrupt handling
+ * scheme also closed the SDE interrupt handling race we've seen
+ * on older pch-split platforms. But this needs testing.
+ */
+ gen8_read_and_ack_pch_irqs(dev_priv, &iir, &pica_iir);
+ if (iir) {
+ if (pica_iir)
+ xelpdp_pica_irq_handler(dev_priv, pica_iir);
+
+ if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
+ icp_irq_handler(dev_priv, iir);
+ else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
+ spt_irq_handler(dev_priv, iir);
+ else
+ cpt_irq_handler(dev_priv, iir);
+ } else {
+ /*
+ * Like on previous PCH there seems to be something
+ * fishy going on with forwarding PCH interrupts.
+ */
+ drm_dbg(&dev_priv->drm,
+ "The master control interrupt lied (SDE)!\n");
+ }
+ }
+}
+
+u32 gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl)
+{
+ void __iomem * const regs = i915->uncore.regs;
+ u32 iir;
+
+ if (!(master_ctl & GEN11_GU_MISC_IRQ))
+ return 0;
+
+ iir = raw_reg_read(regs, GEN11_GU_MISC_IIR);
+ if (likely(iir))
+ raw_reg_write(regs, GEN11_GU_MISC_IIR, iir);
+
+ return iir;
+}
+
+void gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir)
+{
+ if (iir & GEN11_GU_MISC_GSE)
+ intel_opregion_asle_intr(i915);
+}
+
+void gen11_display_irq_handler(struct drm_i915_private *i915)
+{
+ void __iomem * const regs = i915->uncore.regs;
+ const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL);
+
+ disable_rpm_wakeref_asserts(&i915->runtime_pm);
+ /*
+ * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ
+ * for the display related bits.
+ */
+ raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0);
+ gen8_de_irq_handler(i915, disp_ctl);
+ raw_reg_write(regs, GEN11_DISPLAY_INT_CTL,
+ GEN11_DISPLAY_IRQ_ENABLE);
+
+ enable_rpm_wakeref_asserts(&i915->runtime_pm);
+}
+
+/* Called from drm generic code, passed 'crtc' which
+ * we use as a pipe index
+ */
+int i8xx_enable_vblank(struct drm_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+ enum pipe pipe = to_intel_crtc(crtc)->pipe;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+ i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+ return 0;
+}
+
+int i915gm_enable_vblank(struct drm_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+
+ /*
+ * Vblank interrupts fail to wake the device up from C2+.
+ * Disabling render clock gating during C-states avoids
+ * the problem. There is a small power cost so we do this
+ * only when vblank interrupts are actually enabled.
+ */
+ if (dev_priv->vblank_enabled++ == 0)
+ intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
+
+ return i8xx_enable_vblank(crtc);
+}
+
+int i965_enable_vblank(struct drm_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+ enum pipe pipe = to_intel_crtc(crtc)->pipe;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+ i915_enable_pipestat(dev_priv, pipe,
+ PIPE_START_VBLANK_INTERRUPT_STATUS);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+ return 0;
+}
+
+int ilk_enable_vblank(struct drm_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+ enum pipe pipe = to_intel_crtc(crtc)->pipe;
+ unsigned long irqflags;
+ u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
+ DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+ ilk_enable_display_irq(dev_priv, bit);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+ /* Even though there is no DMC, frame counter can get stuck when
+ * PSR is active as no frames are generated.
+ */
+ if (HAS_PSR(dev_priv))
+ drm_crtc_vblank_restore(crtc);
+
+ return 0;
+}
+
+static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
+ bool enable)
+{
+ struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+ enum port port;
+
+ if (!(intel_crtc->mode_flags &
+ (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0)))
+ return false;
+
+ /* for dual link cases we consider TE from slave */
+ if (intel_crtc->mode_flags & I915_MODE_FLAG_DSI_USE_TE1)
+ port = PORT_B;
+ else
+ port = PORT_A;
+
+ intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT,
+ enable ? 0 : DSI_TE_EVENT);
+
+ intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
+
+ return true;
+}
+
+int bdw_enable_vblank(struct drm_crtc *_crtc)
+{
+ struct intel_crtc *crtc = to_intel_crtc(_crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
+ unsigned long irqflags;
+
+ if (gen11_dsi_configure_te(crtc, true))
+ return 0;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+ bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+ /* Even if there is no DMC, frame counter can get stuck when
+ * PSR is active as no frames are generated, so check only for PSR.
+ */
+ if (HAS_PSR(dev_priv))
+ drm_crtc_vblank_restore(&crtc->base);
+
+ return 0;
+}
+
+/* Called from drm generic code, passed 'crtc' which
+ * we use as a pipe index
+ */
+void i8xx_disable_vblank(struct drm_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+ enum pipe pipe = to_intel_crtc(crtc)->pipe;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+ i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+}
+
+void i915gm_disable_vblank(struct drm_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+
+ i8xx_disable_vblank(crtc);
+
+ if (--dev_priv->vblank_enabled == 0)
+ intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
+}
+
+void i965_disable_vblank(struct drm_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+ enum pipe pipe = to_intel_crtc(crtc)->pipe;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+ i915_disable_pipestat(dev_priv, pipe,
+ PIPE_START_VBLANK_INTERRUPT_STATUS);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+}
+
+void ilk_disable_vblank(struct drm_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+ enum pipe pipe = to_intel_crtc(crtc)->pipe;
+ unsigned long irqflags;
+ u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
+ DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+ ilk_disable_display_irq(dev_priv, bit);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+}
+
+void bdw_disable_vblank(struct drm_crtc *_crtc)
+{
+ struct intel_crtc *crtc = to_intel_crtc(_crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
+ unsigned long irqflags;
+
+ if (gen11_dsi_configure_te(crtc, false))
+ return;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+ bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+}
+
+void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
+{
+ struct intel_uncore *uncore = &dev_priv->uncore;
+
+ if (IS_CHERRYVIEW(dev_priv))
+ intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV);
+ else
+ intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV);
+
+ i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0);
+ intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
+
+ i9xx_pipestat_irq_reset(dev_priv);
+
+ GEN3_IRQ_RESET(uncore, VLV_);
+ dev_priv->irq_mask = ~0u;
+}
+
+void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
+{
+ struct intel_uncore *uncore = &dev_priv->uncore;
+
+ u32 pipestat_mask;
+ u32 enable_mask;
+ enum pipe pipe;
+
+ pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS;
+
+ i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
+ for_each_pipe(dev_priv, pipe)
+ i915_enable_pipestat(dev_priv, pipe, pipestat_mask);
+
+ enable_mask = I915_DISPLAY_PORT_INTERRUPT |
+ I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+ I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+ I915_LPE_PIPE_A_INTERRUPT |
+ I915_LPE_PIPE_B_INTERRUPT;
+
+ if (IS_CHERRYVIEW(dev_priv))
+ enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT |
+ I915_LPE_PIPE_C_INTERRUPT;
+
+ drm_WARN_ON(&dev_priv->drm, dev_priv->irq_mask != ~0u);
+
+ dev_priv->irq_mask = ~enable_mask;
+
+ GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask);
+}
+
+void gen8_display_irq_reset(struct drm_i915_private *dev_priv)
+{
+ struct intel_uncore *uncore = &dev_priv->uncore;
+ enum pipe pipe;
+
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
+ intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
+ intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
+
+ for_each_pipe(dev_priv, pipe)
+ if (intel_display_power_is_enabled(dev_priv,
+ POWER_DOMAIN_PIPE(pipe)))
+ GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
+
+ GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
+ GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
+}
+
+void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
+{
+ struct intel_uncore *uncore = &dev_priv->uncore;
+ enum pipe pipe;
+ u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
+
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
+ intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0);
+
+ if (DISPLAY_VER(dev_priv) >= 12) {
+ enum transcoder trans;
+
+ for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
+ enum intel_display_power_domain domain;
+
+ domain = POWER_DOMAIN_TRANSCODER(trans);
+ if (!intel_display_power_is_enabled(dev_priv, domain))
+ continue;
+
+ intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff);
+ intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff);
+ }
+ } else {
+ intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
+ intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
+ }
+
+ for_each_pipe(dev_priv, pipe)
+ if (intel_display_power_is_enabled(dev_priv,
+ POWER_DOMAIN_PIPE(pipe)))
+ GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
+
+ GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
+ GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
+
+ if (DISPLAY_VER(dev_priv) >= 14)
+ GEN3_IRQ_RESET(uncore, PICAINTERRUPT_);
+ else
+ GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_);
+
+ if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
+ GEN3_IRQ_RESET(uncore, SDE);
+}
+
+void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
+ u8 pipe_mask)
+{
+ struct intel_uncore *uncore = &dev_priv->uncore;
+ u32 extra_ier = GEN8_PIPE_VBLANK |
+ gen8_de_pipe_underrun_mask(dev_priv) |
+ gen8_de_pipe_flip_done_mask(dev_priv);
+ enum pipe pipe;
+
+ spin_lock_irq(&dev_priv->irq_lock);
+
+ if (!intel_irqs_enabled(dev_priv)) {
+ spin_unlock_irq(&dev_priv->irq_lock);
+ return;
+ }
+
+ for_each_pipe_masked(dev_priv, pipe, pipe_mask)
+ GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
+ dev_priv->de_irq_mask[pipe],
+ ~dev_priv->de_irq_mask[pipe] | extra_ier);
+
+ spin_unlock_irq(&dev_priv->irq_lock);
+}
+
+void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
+ u8 pipe_mask)
+{
+ struct intel_uncore *uncore = &dev_priv->uncore;
+ enum pipe pipe;
+
+ spin_lock_irq(&dev_priv->irq_lock);
+
+ if (!intel_irqs_enabled(dev_priv)) {
+ spin_unlock_irq(&dev_priv->irq_lock);
+ return;
+ }
+
+ for_each_pipe_masked(dev_priv, pipe, pipe_mask)
+ GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
+
+ spin_unlock_irq(&dev_priv->irq_lock);
+
+ /* make sure we're done processing display irqs */
+ intel_synchronize_irq(dev_priv);
+}
+
+/*
+ * SDEIER is also touched by the interrupt handler to work around missed PCH
+ * interrupts. Hence we can't update it after the interrupt handler is enabled -
+ * instead we unconditionally enable all PCH interrupt sources here, but then
+ * only unmask them as needed with SDEIMR.
+ *
+ * Note that we currently do this after installing the interrupt handler,
+ * but before we enable the master interrupt. That should be sufficient
+ * to avoid races with the irq handler, assuming we have MSI. Shared legacy
+ * interrupts could still race.
+ */
+void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
+{
+ struct intel_uncore *uncore = &dev_priv->uncore;
+ u32 mask;
+
+ if (HAS_PCH_NOP(dev_priv))
+ return;
+
+ if (HAS_PCH_IBX(dev_priv))
+ mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
+ else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
+ mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
+ else
+ mask = SDE_GMBUS_CPT;
+
+ GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
+}
+
+void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
+{
+ lockdep_assert_held(&dev_priv->irq_lock);
+
+ if (dev_priv->display_irqs_enabled)
+ return;
+
+ dev_priv->display_irqs_enabled = true;
+
+ if (intel_irqs_enabled(dev_priv)) {
+ vlv_display_irq_reset(dev_priv);
+ vlv_display_irq_postinstall(dev_priv);
+ }
+}
+
+void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
+{
+ lockdep_assert_held(&dev_priv->irq_lock);
+
+ if (!dev_priv->display_irqs_enabled)
+ return;
+
+ dev_priv->display_irqs_enabled = false;
+
+ if (intel_irqs_enabled(dev_priv))
+ vlv_display_irq_reset(dev_priv);
+}
+
+void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
+{
+ struct intel_uncore *uncore = &dev_priv->uncore;
+
+ u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) |
+ GEN8_PIPE_CDCLK_CRC_DONE;
+ u32 de_pipe_enables;
+ u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
+ u32 de_port_enables;
+ u32 de_misc_masked = GEN8_DE_EDP_PSR;
+ u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
+ enum pipe pipe;
+
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
+ if (DISPLAY_VER(dev_priv) <= 10)
+ de_misc_masked |= GEN8_DE_MISC_GSE;
+
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
+ de_port_masked |= BXT_DE_PORT_GMBUS;
+
+ if (DISPLAY_VER(dev_priv) >= 14) {
+ de_misc_masked |= XELPDP_PMDEMAND_RSPTOUT_ERR |
+ XELPDP_PMDEMAND_RSP;
+ } else if (DISPLAY_VER(dev_priv) >= 11) {
+ enum port port;
+
+ if (intel_bios_is_dsi_present(dev_priv, &port))
+ de_port_masked |= DSI0_TE | DSI1_TE;
+ }
+
+ de_pipe_enables = de_pipe_masked |
+ GEN8_PIPE_VBLANK |
+ gen8_de_pipe_underrun_mask(dev_priv) |
+ gen8_de_pipe_flip_done_mask(dev_priv);
+
+ de_port_enables = de_port_masked;
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
+ de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK;
+ else if (IS_BROADWELL(dev_priv))
+ de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK;
+
+ if (DISPLAY_VER(dev_priv) >= 12) {
+ enum transcoder trans;
+
+ for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
+ enum intel_display_power_domain domain;
+
+ domain = POWER_DOMAIN_TRANSCODER(trans);
+ if (!intel_display_power_is_enabled(dev_priv, domain))
+ continue;
+
+ gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans));
+ }
+ } else {
+ gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
+ }
+
+ for_each_pipe(dev_priv, pipe) {
+ dev_priv->de_irq_mask[pipe] = ~de_pipe_masked;
+
+ if (intel_display_power_is_enabled(dev_priv,
+ POWER_DOMAIN_PIPE(pipe)))
+ GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
+ dev_priv->de_irq_mask[pipe],
+ de_pipe_enables);
+ }
+
+ GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
+ GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
+
+ if (IS_DISPLAY_VER(dev_priv, 11, 13)) {
+ u32 de_hpd_masked = 0;
+ u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK |
+ GEN11_DE_TBT_HOTPLUG_MASK;
+
+ GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked,
+ de_hpd_enables);
+ }
+}
+
+void mtp_irq_postinstall(struct drm_i915_private *i915)
+{
+ struct intel_uncore *uncore = &i915->uncore;
+ u32 sde_mask = SDE_GMBUS_ICP | SDE_PICAINTERRUPT;
+ u32 de_hpd_mask = XELPDP_AUX_TC_MASK;
+ u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK |
+ XELPDP_TBT_HOTPLUG_MASK;
+
+ GEN3_IRQ_INIT(uncore, PICAINTERRUPT_, ~de_hpd_mask,
+ de_hpd_enables);
+
+ GEN3_IRQ_INIT(uncore, SDE, ~sde_mask, 0xffffffff);
+}
+
+void icp_irq_postinstall(struct drm_i915_private *dev_priv)
+{
+ struct intel_uncore *uncore = &dev_priv->uncore;
+ u32 mask = SDE_GMBUS_ICP;
+
+ GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
+}
+
+void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv)
+{
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
+ gen8_de_irq_postinstall(dev_priv);
+
+ intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
+ GEN11_DISPLAY_IRQ_ENABLE);
+}
+
diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.h b/drivers/gpu/drm/i915/display/intel_display_irq.h
new file mode 100644
index 000000000000..874893f4f16d
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_DISPLAY_IRQ_H__
+#define __INTEL_DISPLAY_IRQ_H__
+
+#include <linux/types.h>
+
+#include "intel_display_limits.h"
+
+enum pipe;
+struct drm_i915_private;
+struct drm_crtc;
+
+void valleyview_enable_display_irqs(struct drm_i915_private *i915);
+void valleyview_disable_display_irqs(struct drm_i915_private *i915);
+
+void ilk_update_display_irq(struct drm_i915_private *i915,
+ u32 interrupt_mask, u32 enabled_irq_mask);
+void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits);
+void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits);
+
+void bdw_update_port_irq(struct drm_i915_private *i915, u32 interrupt_mask, u32 enabled_irq_mask);
+void bdw_enable_pipe_irq(struct drm_i915_private *i915, enum pipe pipe, u32 bits);
+void bdw_disable_pipe_irq(struct drm_i915_private *i915, enum pipe pipe, u32 bits);
+
+void ibx_display_interrupt_update(struct drm_i915_private *i915,
+ u32 interrupt_mask, u32 enabled_irq_mask);
+void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits);
+void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits);
+
+void gen8_irq_power_well_post_enable(struct drm_i915_private *i915, u8 pipe_mask);
+void gen8_irq_power_well_pre_disable(struct drm_i915_private *i915, u8 pipe_mask);
+u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *i915);
+
+int i8xx_enable_vblank(struct drm_crtc *crtc);
+int i915gm_enable_vblank(struct drm_crtc *crtc);
+int i965_enable_vblank(struct drm_crtc *crtc);
+int ilk_enable_vblank(struct drm_crtc *crtc);
+int bdw_enable_vblank(struct drm_crtc *crtc);
+void i8xx_disable_vblank(struct drm_crtc *crtc);
+void i915gm_disable_vblank(struct drm_crtc *crtc);
+void i965_disable_vblank(struct drm_crtc *crtc);
+void ilk_disable_vblank(struct drm_crtc *crtc);
+void bdw_disable_vblank(struct drm_crtc *crtc);
+
+void ivb_display_irq_handler(struct drm_i915_private *i915, u32 de_iir);
+void ilk_display_irq_handler(struct drm_i915_private *i915, u32 de_iir);
+void gen8_de_irq_handler(struct drm_i915_private *i915, u32 master_ctl);
+void gen11_display_irq_handler(struct drm_i915_private *i915);
+
+u32 gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl);
+void gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir);
+
+void vlv_display_irq_reset(struct drm_i915_private *i915);
+void gen8_display_irq_reset(struct drm_i915_private *i915);
+void gen11_display_irq_reset(struct drm_i915_private *i915);
+
+void ibx_irq_postinstall(struct drm_i915_private *i915);
+void vlv_display_irq_postinstall(struct drm_i915_private *i915);
+void icp_irq_postinstall(struct drm_i915_private *i915);
+void gen8_de_irq_postinstall(struct drm_i915_private *i915);
+void mtp_irq_postinstall(struct drm_i915_private *i915);
+void gen11_de_irq_postinstall(struct drm_i915_private *i915);
+
+u32 i915_pipestat_enable_mask(struct drm_i915_private *i915, enum pipe pipe);
+void i915_enable_pipestat(struct drm_i915_private *i915, enum pipe pipe, u32 status_mask);
+void i915_disable_pipestat(struct drm_i915_private *i915, enum pipe pipe, u32 status_mask);
+void i915_enable_asle_pipestat(struct drm_i915_private *i915);
+void i9xx_pipestat_irq_reset(struct drm_i915_private *i915);
+
+void i9xx_pipestat_irq_ack(struct drm_i915_private *i915, u32 iir, u32 pipe_stats[I915_MAX_PIPES]);
+
+void i915_pipestat_irq_handler(struct drm_i915_private *i915, u32 iir, u32 pipe_stats[I915_MAX_PIPES]);
+void i965_pipestat_irq_handler(struct drm_i915_private *i915, u32 iir, u32 pipe_stats[I915_MAX_PIPES]);
+void valleyview_pipestat_irq_handler(struct drm_i915_private *i915, u32 pipe_stats[I915_MAX_PIPES]);
+void i8xx_pipestat_irq_handler(struct drm_i915_private *i915, u16 iir, u32 pipe_stats[I915_MAX_PIPES]);
+
+#endif /* __INTEL_DISPLAY_IRQ_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index 7c9f4288329e..db5437043904 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -7,6 +7,7 @@
#include "i915_drv.h"
#include "i915_irq.h"
+#include "i915_reg.h"
#include "intel_backlight_regs.h"
#include "intel_cdclk.h"
#include "intel_combo_phy.h"
@@ -19,6 +20,7 @@
#include "intel_mchbar_regs.h"
#include "intel_pch_refclk.h"
#include "intel_pcode.h"
+#include "intel_pmdemand.h"
#include "intel_pps_regs.h"
#include "intel_snps_phy.h"
#include "skl_watermark.h"
@@ -1052,7 +1054,7 @@ void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,
u8 req_slices)
{
struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
- u8 slice_mask = INTEL_INFO(dev_priv)->display.dbuf.slice_mask;
+ u8 slice_mask = DISPLAY_INFO(dev_priv)->dbuf.slice_mask;
enum dbuf_slice slice;
drm_WARN(&dev_priv->drm, req_slices & ~slice_mask,
@@ -1081,20 +1083,29 @@ void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,
static void gen9_dbuf_enable(struct drm_i915_private *dev_priv)
{
+ u8 slices_mask;
+
dev_priv->display.dbuf.enabled_slices =
intel_enabled_dbuf_slices_mask(dev_priv);
+ slices_mask = BIT(DBUF_S1) | dev_priv->display.dbuf.enabled_slices;
+
+ if (DISPLAY_VER(dev_priv) >= 14)
+ intel_pmdemand_program_dbuf(dev_priv, slices_mask);
+
/*
* Just power up at least 1 slice, we will
* figure out later which slices we have and what we need.
*/
- gen9_dbuf_slices_update(dev_priv, BIT(DBUF_S1) |
- dev_priv->display.dbuf.enabled_slices);
+ gen9_dbuf_slices_update(dev_priv, slices_mask);
}
static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
{
gen9_dbuf_slices_update(dev_priv, 0);
+
+ if (DISPLAY_VER(dev_priv) >= 14)
+ intel_pmdemand_program_dbuf(dev_priv, 0);
}
static void gen12_dbuf_slices_config(struct drm_i915_private *dev_priv)
@@ -1112,7 +1123,7 @@ static void gen12_dbuf_slices_config(struct drm_i915_private *dev_priv)
static void icl_mbus_init(struct drm_i915_private *dev_priv)
{
- unsigned long abox_regs = INTEL_INFO(dev_priv)->display.abox_mask;
+ unsigned long abox_regs = DISPLAY_INFO(dev_priv)->abox_mask;
u32 mask, val, i;
if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14)
@@ -1164,31 +1175,39 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
struct intel_crtc *crtc;
for_each_intel_crtc(&dev_priv->drm, crtc)
- I915_STATE_WARN(crtc->active, "CRTC for pipe %c enabled\n",
+ I915_STATE_WARN(dev_priv, crtc->active,
+ "CRTC for pipe %c enabled\n",
pipe_name(crtc->pipe));
- I915_STATE_WARN(intel_de_read(dev_priv, HSW_PWR_WELL_CTL2),
+ I915_STATE_WARN(dev_priv, intel_de_read(dev_priv, HSW_PWR_WELL_CTL2),
"Display power well on\n");
- I915_STATE_WARN(intel_de_read(dev_priv, SPLL_CTL) & SPLL_PLL_ENABLE,
+ I915_STATE_WARN(dev_priv,
+ intel_de_read(dev_priv, SPLL_CTL) & SPLL_PLL_ENABLE,
"SPLL enabled\n");
- I915_STATE_WARN(intel_de_read(dev_priv, WRPLL_CTL(0)) & WRPLL_PLL_ENABLE,
+ I915_STATE_WARN(dev_priv,
+ intel_de_read(dev_priv, WRPLL_CTL(0)) & WRPLL_PLL_ENABLE,
"WRPLL1 enabled\n");
- I915_STATE_WARN(intel_de_read(dev_priv, WRPLL_CTL(1)) & WRPLL_PLL_ENABLE,
+ I915_STATE_WARN(dev_priv,
+ intel_de_read(dev_priv, WRPLL_CTL(1)) & WRPLL_PLL_ENABLE,
"WRPLL2 enabled\n");
- I915_STATE_WARN(intel_de_read(dev_priv, PP_STATUS(0)) & PP_ON,
+ I915_STATE_WARN(dev_priv,
+ intel_de_read(dev_priv, PP_STATUS(0)) & PP_ON,
"Panel power on\n");
- I915_STATE_WARN(intel_de_read(dev_priv, BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
+ I915_STATE_WARN(dev_priv,
+ intel_de_read(dev_priv, BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
"CPU PWM1 enabled\n");
if (IS_HASWELL(dev_priv))
- I915_STATE_WARN(intel_de_read(dev_priv, HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
+ I915_STATE_WARN(dev_priv,
+ intel_de_read(dev_priv, HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
"CPU PWM2 enabled\n");
- I915_STATE_WARN(intel_de_read(dev_priv, BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE,
+ I915_STATE_WARN(dev_priv,
+ intel_de_read(dev_priv, BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE,
"PCH PWM1 enabled\n");
- I915_STATE_WARN((intel_de_read(dev_priv, UTIL_PIN_CTL) &
- (UTIL_PIN_ENABLE | UTIL_PIN_MODE_MASK)) ==
- (UTIL_PIN_ENABLE | UTIL_PIN_MODE_PWM),
+ I915_STATE_WARN(dev_priv,
+ (intel_de_read(dev_priv, UTIL_PIN_CTL) & (UTIL_PIN_ENABLE | UTIL_PIN_MODE_MASK)) == (UTIL_PIN_ENABLE | UTIL_PIN_MODE_PWM),
"Utility pin enabled in PWM mode\n");
- I915_STATE_WARN(intel_de_read(dev_priv, PCH_GTC_CTL) & PCH_GTC_ENABLE,
+ I915_STATE_WARN(dev_priv,
+ intel_de_read(dev_priv, PCH_GTC_CTL) & PCH_GTC_ENABLE,
"PCH GTC enabled\n");
/*
@@ -1197,7 +1216,8 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
* gen-specific and since we only disable LCPLL after we fully disable
* the interrupts, the check below should be enough.
*/
- I915_STATE_WARN(intel_irqs_enabled(dev_priv), "IRQs enabled\n");
+ I915_STATE_WARN(dev_priv, intel_irqs_enabled(dev_priv),
+ "IRQs enabled\n");
}
static u32 hsw_read_dcomp(struct drm_i915_private *dev_priv)
@@ -1558,7 +1578,7 @@ static void tgl_bw_buddy_init(struct drm_i915_private *dev_priv)
enum intel_dram_type type = dev_priv->dram_info.type;
u8 num_channels = dev_priv->dram_info.num_channels;
const struct buddy_page_mask *table;
- unsigned long abox_mask = INTEL_INFO(dev_priv)->display.abox_mask;
+ unsigned long abox_mask = DISPLAY_INFO(dev_priv)->abox_mask;
int config, i;
/* BW_BUDDY registers are not used on dgpu's beyond DG1 */
@@ -2021,7 +2041,7 @@ void intel_power_domains_disable(struct drm_i915_private *i915)
/**
* intel_power_domains_suspend - suspend power domain state
* @i915: i915 device instance
- * @suspend_mode: specifies the target suspend state (idle, mem, hibernation)
+ * @s2idle: specifies whether we go to idle, or deeper sleep
*
* This function prepares the hardware power domain state before entering
* system suspend.
@@ -2029,8 +2049,7 @@ void intel_power_domains_disable(struct drm_i915_private *i915)
* It must be called with power domains already disabled (after a call to
* intel_power_domains_disable()) and paired with intel_power_domains_resume().
*/
-void intel_power_domains_suspend(struct drm_i915_private *i915,
- enum i915_drm_suspend_mode suspend_mode)
+void intel_power_domains_suspend(struct drm_i915_private *i915, bool s2idle)
{
struct i915_power_domains *power_domains = &i915->display.power.domains;
intel_wakeref_t wakeref __maybe_unused =
@@ -2045,8 +2064,7 @@ void intel_power_domains_suspend(struct drm_i915_private *i915,
* resources as required and also enable deeper system power states
* that would be blocked if the firmware was inactive.
*/
- if (!(power_domains->allowed_dc_mask & DC_STATE_EN_DC9) &&
- suspend_mode == I915_DRM_SUSPEND_IDLE &&
+ if (!(power_domains->allowed_dc_mask & DC_STATE_EN_DC9) && s2idle &&
intel_dmc_has_payload(i915)) {
intel_display_power_flush_work(i915);
intel_power_domains_verify_state(i915);
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h
index 8e96be8e6330..be1a87bde0c9 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power.h
@@ -171,8 +171,7 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
void intel_power_domains_driver_remove(struct drm_i915_private *dev_priv);
void intel_power_domains_enable(struct drm_i915_private *dev_priv);
void intel_power_domains_disable(struct drm_i915_private *dev_priv);
-void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
- enum i915_drm_suspend_mode);
+void intel_power_domains_suspend(struct drm_i915_private *dev_priv, bool s2idle);
void intel_power_domains_resume(struct drm_i915_private *dev_priv);
void intel_power_domains_sanitize_state(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/display/intel_display_power_map.c b/drivers/gpu/drm/i915/display/intel_display_power_map.c
index 6645eb1911d8..1118ee9d224c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_map.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c
@@ -1251,22 +1251,11 @@ I915_DECL_PW_DOMAINS(xelpd_pwdoms_pw_a,
POWER_DOMAIN_PIPE_PANEL_FITTER_A,
POWER_DOMAIN_INIT);
-#define XELPD_PW_2_POWER_DOMAINS \
- XELPD_PW_B_POWER_DOMAINS, \
- XELPD_PW_C_POWER_DOMAINS, \
- XELPD_PW_D_POWER_DOMAINS, \
- POWER_DOMAIN_PORT_DDI_LANES_C, \
- POWER_DOMAIN_PORT_DDI_LANES_D, \
- POWER_DOMAIN_PORT_DDI_LANES_E, \
+#define XELPD_DC_OFF_PORT_POWER_DOMAINS \
POWER_DOMAIN_PORT_DDI_LANES_TC1, \
POWER_DOMAIN_PORT_DDI_LANES_TC2, \
POWER_DOMAIN_PORT_DDI_LANES_TC3, \
POWER_DOMAIN_PORT_DDI_LANES_TC4, \
- POWER_DOMAIN_VGA, \
- POWER_DOMAIN_AUDIO_PLAYBACK, \
- POWER_DOMAIN_AUX_IO_C, \
- POWER_DOMAIN_AUX_IO_D, \
- POWER_DOMAIN_AUX_IO_E, \
POWER_DOMAIN_AUX_C, \
POWER_DOMAIN_AUX_D, \
POWER_DOMAIN_AUX_E, \
@@ -1279,6 +1268,20 @@ I915_DECL_PW_DOMAINS(xelpd_pwdoms_pw_a,
POWER_DOMAIN_AUX_TBT3, \
POWER_DOMAIN_AUX_TBT4
+#define XELPD_PW_2_POWER_DOMAINS \
+ XELPD_PW_B_POWER_DOMAINS, \
+ XELPD_PW_C_POWER_DOMAINS, \
+ XELPD_PW_D_POWER_DOMAINS, \
+ POWER_DOMAIN_PORT_DDI_LANES_C, \
+ POWER_DOMAIN_PORT_DDI_LANES_D, \
+ POWER_DOMAIN_PORT_DDI_LANES_E, \
+ POWER_DOMAIN_VGA, \
+ POWER_DOMAIN_AUDIO_PLAYBACK, \
+ POWER_DOMAIN_AUX_IO_C, \
+ POWER_DOMAIN_AUX_IO_D, \
+ POWER_DOMAIN_AUX_IO_E, \
+ XELPD_DC_OFF_PORT_POWER_DOMAINS
+
I915_DECL_PW_DOMAINS(xelpd_pwdoms_pw_2,
XELPD_PW_2_POWER_DOMAINS,
POWER_DOMAIN_INIT);
@@ -1301,7 +1304,9 @@ I915_DECL_PW_DOMAINS(xelpd_pwdoms_pw_2,
*/
I915_DECL_PW_DOMAINS(xelpd_pwdoms_dc_off,
- XELPD_PW_2_POWER_DOMAINS,
+ XELPD_DC_OFF_PORT_POWER_DOMAINS,
+ XELPD_PW_C_POWER_DOMAINS,
+ XELPD_PW_D_POWER_DOMAINS,
POWER_DOMAIN_PORT_DSI,
POWER_DOMAIN_AUDIO_MMIO,
POWER_DOMAIN_AUX_A,
@@ -1310,14 +1315,18 @@ I915_DECL_PW_DOMAINS(xelpd_pwdoms_dc_off,
POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
-static const struct i915_power_well_desc xelpd_power_wells_main[] = {
+static const struct i915_power_well_desc xelpd_power_wells_dc_off[] = {
{
.instances = &I915_PW_INSTANCES(
I915_PW("DC_off", &xelpd_pwdoms_dc_off,
.id = SKL_DISP_DC_OFF),
),
.ops = &gen9_dc_off_power_well_ops,
- }, {
+ }
+};
+
+static const struct i915_power_well_desc xelpd_power_wells_main[] = {
+ {
.instances = &I915_PW_INSTANCES(
I915_PW("PW_2", &xelpd_pwdoms_pw_2,
.hsw.idx = ICL_PW_CTL_IDX_PW_2,
@@ -1378,6 +1387,11 @@ static const struct i915_power_well_desc xelpd_power_wells_main[] = {
I915_PW("AUX_C", &icl_pwdoms_aux_c, .hsw.idx = ICL_PW_CTL_IDX_AUX_C),
I915_PW("AUX_D", &icl_pwdoms_aux_d, .hsw.idx = XELPD_PW_CTL_IDX_AUX_D),
I915_PW("AUX_E", &icl_pwdoms_aux_e, .hsw.idx = XELPD_PW_CTL_IDX_AUX_E),
+ ),
+ .ops = &icl_aux_power_well_ops,
+ .fixed_enable_delay = true,
+ }, {
+ .instances = &I915_PW_INSTANCES(
I915_PW("AUX_USBC1", &tgl_pwdoms_aux_usbc1, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1),
I915_PW("AUX_USBC2", &tgl_pwdoms_aux_usbc2, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2),
I915_PW("AUX_USBC3", &tgl_pwdoms_aux_usbc3, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC3),
@@ -1385,6 +1399,8 @@ static const struct i915_power_well_desc xelpd_power_wells_main[] = {
),
.ops = &icl_aux_power_well_ops,
.fixed_enable_delay = true,
+ /* WA_14017248603: adlp */
+ .enable_timeout = 500,
}, {
.instances = &I915_PW_INSTANCES(
I915_PW("AUX_TBT1", &icl_pwdoms_aux_tbt1, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT1),
@@ -1400,6 +1416,34 @@ static const struct i915_power_well_desc xelpd_power_wells_main[] = {
static const struct i915_power_well_desc_list xelpd_power_wells[] = {
I915_PW_DESCRIPTORS(i9xx_power_wells_always_on),
I915_PW_DESCRIPTORS(icl_power_wells_pw_1),
+ I915_PW_DESCRIPTORS(xelpd_power_wells_dc_off),
+ I915_PW_DESCRIPTORS(xelpd_power_wells_main),
+};
+
+I915_DECL_PW_DOMAINS(xehpd_pwdoms_dc_off,
+ XELPD_PW_2_POWER_DOMAINS,
+ POWER_DOMAIN_PORT_DSI,
+ POWER_DOMAIN_AUDIO_MMIO,
+ POWER_DOMAIN_AUX_A,
+ POWER_DOMAIN_AUX_B,
+ POWER_DOMAIN_MODESET,
+ POWER_DOMAIN_DC_OFF,
+ POWER_DOMAIN_INIT);
+
+static const struct i915_power_well_desc xehpd_power_wells_dc_off[] = {
+ {
+ .instances = &I915_PW_INSTANCES(
+ I915_PW("DC_off", &xehpd_pwdoms_dc_off,
+ .id = SKL_DISP_DC_OFF),
+ ),
+ .ops = &gen9_dc_off_power_well_ops,
+ }
+};
+
+static const struct i915_power_well_desc_list xehpd_power_wells[] = {
+ I915_PW_DESCRIPTORS(i9xx_power_wells_always_on),
+ I915_PW_DESCRIPTORS(icl_power_wells_pw_1),
+ I915_PW_DESCRIPTORS(xehpd_power_wells_dc_off),
I915_PW_DESCRIPTORS(xelpd_power_wells_main),
};
@@ -1423,15 +1467,6 @@ I915_DECL_PW_DOMAINS(xelpdp_pwdoms_pw_2,
XELPDP_PW_2_POWER_DOMAINS,
POWER_DOMAIN_INIT);
-I915_DECL_PW_DOMAINS(xelpdp_pwdoms_dc_off,
- XELPDP_PW_2_POWER_DOMAINS,
- POWER_DOMAIN_AUDIO_MMIO,
- POWER_DOMAIN_MODESET,
- POWER_DOMAIN_AUX_A,
- POWER_DOMAIN_AUX_B,
- POWER_DOMAIN_DC_OFF,
- POWER_DOMAIN_INIT);
-
I915_DECL_PW_DOMAINS(xelpdp_pwdoms_aux_tc1,
POWER_DOMAIN_AUX_USBC1,
POWER_DOMAIN_AUX_TBT1);
@@ -1451,12 +1486,6 @@ I915_DECL_PW_DOMAINS(xelpdp_pwdoms_aux_tc4,
static const struct i915_power_well_desc xelpdp_power_wells_main[] = {
{
.instances = &I915_PW_INSTANCES(
- I915_PW("DC_off", &xelpdp_pwdoms_dc_off,
- .id = SKL_DISP_DC_OFF),
- ),
- .ops = &gen9_dc_off_power_well_ops,
- }, {
- .instances = &I915_PW_INSTANCES(
I915_PW("PW_2", &xelpdp_pwdoms_pw_2,
.hsw.idx = ICL_PW_CTL_IDX_PW_2,
.id = SKL_DISP_PW_2),
@@ -1512,6 +1541,7 @@ static const struct i915_power_well_desc xelpdp_power_wells_main[] = {
static const struct i915_power_well_desc_list xelpdp_power_wells[] = {
I915_PW_DESCRIPTORS(i9xx_power_wells_always_on),
I915_PW_DESCRIPTORS(icl_power_wells_pw_1),
+ I915_PW_DESCRIPTORS(xelpd_power_wells_dc_off),
I915_PW_DESCRIPTORS(xelpdp_power_wells_main),
};
@@ -1624,6 +1654,8 @@ int intel_display_power_map_init(struct i915_power_domains *power_domains)
if (DISPLAY_VER(i915) >= 14)
return set_power_wells(power_domains, xelpdp_power_wells);
+ else if (IS_DG2(i915))
+ return set_power_wells(power_domains, xehpd_power_wells);
else if (DISPLAY_VER(i915) >= 13)
return set_power_wells(power_domains, xelpd_power_wells);
else if (IS_DG1(i915))
diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c
index 62bafcbc7937..916009894d89 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -5,11 +5,13 @@
#include "i915_drv.h"
#include "i915_irq.h"
+#include "i915_reg.h"
#include "intel_backlight_regs.h"
#include "intel_combo_phy.h"
#include "intel_combo_phy_regs.h"
#include "intel_crt.h"
#include "intel_de.h"
+#include "intel_display_irq.h"
#include "intel_display_power_well.h"
#include "intel_display_types.h"
#include "intel_dkl_phy.h"
@@ -253,6 +255,7 @@ static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv,
{
const struct i915_power_well_regs *regs = power_well->desc->ops->regs;
int pw_idx = i915_power_well_instance(power_well)->hsw.idx;
+ int timeout = power_well->desc->enable_timeout ? : 1;
/*
* For some power wells we're not supposed to watch the status bit for
@@ -266,7 +269,7 @@ static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv,
/* Timeout for PW1:10 us, AUX:not specified, other PWs:20 us. */
if (intel_de_wait_for_set(dev_priv, regs->driver,
- HSW_PWR_WELL_CTL_STATE(pw_idx), 1)) {
+ HSW_PWR_WELL_CTL_STATE(pw_idx), timeout)) {
drm_dbg_kms(&dev_priv->drm, "%s power well enable timeout\n",
intel_power_well_name(power_well));
diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.h b/drivers/gpu/drm/i915/display/intel_display_power_well.h
index ba7cb977e7c7..e494df379e6c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h
@@ -110,6 +110,8 @@ struct i915_power_well_desc {
* Thunderbolt mode.
*/
u16 is_tc_tbt:1;
+ /* Enable timeout if greater than the default 1ms */
+ u16 enable_timeout;
};
struct i915_power_well {
diff --git a/drivers/gpu/drm/i915/display/intel_display_reg_defs.h b/drivers/gpu/drm/i915/display/intel_display_reg_defs.h
index 755c1ea8225c..2f07b7afa3bf 100644
--- a/drivers/gpu/drm/i915/display/intel_display_reg_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_display_reg_defs.h
@@ -8,7 +8,7 @@
#include "i915_reg_defs.h"
-#define DISPLAY_MMIO_BASE(dev_priv) (INTEL_INFO(dev_priv)->display.mmio_offset)
+#define DISPLAY_MMIO_BASE(dev_priv) (DISPLAY_INFO(dev_priv)->mmio_offset)
#define VLV_DISPLAY_BASE 0x180000
@@ -36,14 +36,14 @@
* Device info offset array based helpers for groups of registers with unevenly
* spaced base offsets.
*/
-#define _MMIO_PIPE2(pipe, reg) _MMIO(INTEL_INFO(dev_priv)->display.pipe_offsets[(pipe)] - \
- INTEL_INFO(dev_priv)->display.pipe_offsets[PIPE_A] + \
+#define _MMIO_PIPE2(pipe, reg) _MMIO(DISPLAY_INFO(dev_priv)->pipe_offsets[(pipe)] - \
+ DISPLAY_INFO(dev_priv)->pipe_offsets[PIPE_A] + \
DISPLAY_MMIO_BASE(dev_priv) + (reg))
-#define _MMIO_TRANS2(tran, reg) _MMIO(INTEL_INFO(dev_priv)->display.trans_offsets[(tran)] - \
- INTEL_INFO(dev_priv)->display.trans_offsets[TRANSCODER_A] + \
+#define _MMIO_TRANS2(tran, reg) _MMIO(DISPLAY_INFO(dev_priv)->trans_offsets[(tran)] - \
+ DISPLAY_INFO(dev_priv)->trans_offsets[TRANSCODER_A] + \
DISPLAY_MMIO_BASE(dev_priv) + (reg))
-#define _MMIO_CURSOR2(pipe, reg) _MMIO(INTEL_INFO(dev_priv)->display.cursor_offsets[(pipe)] - \
- INTEL_INFO(dev_priv)->display.cursor_offsets[PIPE_A] + \
+#define _MMIO_CURSOR2(pipe, reg) _MMIO(DISPLAY_INFO(dev_priv)->cursor_offsets[(pipe)] - \
+ DISPLAY_INFO(dev_priv)->cursor_offsets[PIPE_A] + \
DISPLAY_MMIO_BASE(dev_priv) + (reg))
#endif /* __INTEL_DISPLAY_REG_DEFS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.c b/drivers/gpu/drm/i915/display/intel_display_reset.c
new file mode 100644
index 000000000000..17178d5d7788
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_reset.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include <drm/drm_atomic_helper.h>
+
+#include "i915_drv.h"
+#include "intel_clock_gating.h"
+#include "intel_display_driver.h"
+#include "intel_display_reset.h"
+#include "intel_display_types.h"
+#include "intel_hotplug.h"
+#include "intel_pps.h"
+
+static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv)
+{
+ return (INTEL_INFO(dev_priv)->gpu_reset_clobbers_display &&
+ intel_has_gpu_reset(to_gt(dev_priv)));
+}
+
+void intel_display_reset_prepare(struct drm_i915_private *dev_priv)
+{
+ struct drm_modeset_acquire_ctx *ctx = &dev_priv->display.restore.reset_ctx;
+ struct drm_atomic_state *state;
+ int ret;
+
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
+ /* reset doesn't touch the display */
+ if (!dev_priv->params.force_reset_modeset_test &&
+ !gpu_reset_clobbers_display(dev_priv))
+ return;
+
+ /* We have a modeset vs reset deadlock, defensively unbreak it. */
+ set_bit(I915_RESET_MODESET, &to_gt(dev_priv)->reset.flags);
+ smp_mb__after_atomic();
+ wake_up_bit(&to_gt(dev_priv)->reset.flags, I915_RESET_MODESET);
+
+ if (atomic_read(&dev_priv->gpu_error.pending_fb_pin)) {
+ drm_dbg_kms(&dev_priv->drm,
+ "Modeset potentially stuck, unbreaking through wedging\n");
+ intel_gt_set_wedged(to_gt(dev_priv));
+ }
+
+ /*
+ * Need mode_config.mutex so that we don't
+ * trample ongoing ->detect() and whatnot.
+ */
+ mutex_lock(&dev_priv->drm.mode_config.mutex);
+ drm_modeset_acquire_init(ctx, 0);
+ while (1) {
+ ret = drm_modeset_lock_all_ctx(&dev_priv->drm, ctx);
+ if (ret != -EDEADLK)
+ break;
+
+ drm_modeset_backoff(ctx);
+ }
+ /*
+ * Disabling the crtcs gracefully seems nicer. Also the
+ * g33 docs say we should at least disable all the planes.
+ */
+ state = drm_atomic_helper_duplicate_state(&dev_priv->drm, ctx);
+ if (IS_ERR(state)) {
+ ret = PTR_ERR(state);
+ drm_err(&dev_priv->drm, "Duplicating state failed with %i\n",
+ ret);
+ return;
+ }
+
+ ret = drm_atomic_helper_disable_all(&dev_priv->drm, ctx);
+ if (ret) {
+ drm_err(&dev_priv->drm, "Suspending crtc's failed with %i\n",
+ ret);
+ drm_atomic_state_put(state);
+ return;
+ }
+
+ dev_priv->display.restore.modeset_state = state;
+ state->acquire_ctx = ctx;
+}
+
+void intel_display_reset_finish(struct drm_i915_private *i915)
+{
+ struct drm_modeset_acquire_ctx *ctx = &i915->display.restore.reset_ctx;
+ struct drm_atomic_state *state;
+ int ret;
+
+ if (!HAS_DISPLAY(i915))
+ return;
+
+ /* reset doesn't touch the display */
+ if (!test_bit(I915_RESET_MODESET, &to_gt(i915)->reset.flags))
+ return;
+
+ state = fetch_and_zero(&i915->display.restore.modeset_state);
+ if (!state)
+ goto unlock;
+
+ /* reset doesn't touch the display */
+ if (!gpu_reset_clobbers_display(i915)) {
+ /* for testing only restore the display */
+ ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
+ if (ret) {
+ drm_WARN_ON(&i915->drm, ret == -EDEADLK);
+ drm_err(&i915->drm,
+ "Restoring old state failed with %i\n", ret);
+ }
+ } else {
+ /*
+ * The display has been reset as well,
+ * so need a full re-initialization.
+ */
+ intel_pps_unlock_regs_wa(i915);
+ intel_display_driver_init_hw(i915);
+ intel_clock_gating_init(i915);
+ intel_hpd_init(i915);
+
+ ret = __intel_display_driver_resume(i915, state, ctx);
+ if (ret)
+ drm_err(&i915->drm,
+ "Restoring old state failed with %i\n", ret);
+
+ intel_hpd_poll_disable(i915);
+ }
+
+ drm_atomic_state_put(state);
+unlock:
+ drm_modeset_drop_locks(ctx);
+ drm_modeset_acquire_fini(ctx);
+ mutex_unlock(&i915->drm.mode_config.mutex);
+
+ clear_bit_unlock(I915_RESET_MODESET, &to_gt(i915)->reset.flags);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.h b/drivers/gpu/drm/i915/display/intel_display_reset.h
new file mode 100644
index 000000000000..f06d0d35b86b
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_reset.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_RESET_H__
+#define __INTEL_RESET_H__
+
+struct drm_i915_private;
+
+void intel_display_reset_prepare(struct drm_i915_private *i915);
+void intel_display_reset_finish(struct drm_i915_private *i915);
+
+#endif /* __INTEL_RESET_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h
index 651ea8564e1b..99bdb833591c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_trace.h
+++ b/drivers/gpu/drm/i915/display/intel_display_trace.h
@@ -14,7 +14,6 @@
#include <linux/tracepoint.h>
#include "i915_drv.h"
-#include "i915_irq.h"
#include "intel_crtc.h"
#include "intel_display_types.h"
#include "intel_vblank.h"
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 47395b39c8f4..731f2ec04d5c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -233,14 +233,26 @@ struct intel_encoder {
* Called during system suspend after all pending requests for the
* encoder are flushed (for example for DP AUX transactions) and
* device interrupts are disabled.
+ * All modeset locks are held while the hook is called.
*/
void (*suspend)(struct intel_encoder *);
/*
+ * Called without the modeset locks held after the suspend() hook for
+ * all encoders have been called.
+ */
+ void (*suspend_complete)(struct intel_encoder *encoder);
+ /*
* Called during system reboot/shutdown after all the
* encoders have been disabled and suspended.
+ * All modeset locks are held while the hook is called.
*/
void (*shutdown)(struct intel_encoder *encoder);
/*
+ * Called without the modeset locks held after the shutdown() hook for
+ * all encoders have been called.
+ */
+ void (*shutdown_complete)(struct intel_encoder *encoder);
+ /*
* Enable/disable the clock to the port.
*/
void (*enable_clock)(struct intel_encoder *encoder,
@@ -643,6 +655,9 @@ struct intel_atomic_state {
struct __intel_global_objs_state *global_objs;
int num_global_objs;
+ /* Internal commit, as opposed to userspace/client initiated one */
+ bool internal;
+
bool dpll_set, modeset;
struct intel_shared_dpll_state shared_dpll[I915_NUM_PLLS];
@@ -980,6 +995,38 @@ struct intel_link_m_n {
u32 link_n;
};
+struct intel_csc_matrix {
+ u16 coeff[9];
+ u16 preoff[3];
+ u16 postoff[3];
+};
+
+struct intel_c10pll_state {
+ u32 clock; /* in KHz */
+ u8 tx;
+ u8 cmn;
+ u8 pll[20];
+};
+
+struct intel_c20pll_state {
+ u32 link_bit_rate;
+ u32 clock; /* in kHz */
+ u16 tx[3];
+ u16 cmn[4];
+ union {
+ u16 mplla[10];
+ u16 mpllb[11];
+ };
+};
+
+struct intel_cx0pll_state {
+ union {
+ struct intel_c10pll_state c10;
+ struct intel_c20pll_state c20;
+ };
+ bool ssc_enabled;
+};
+
struct intel_crtc_state {
/*
* uapi (drm) state. This is the software state shown to userspace.
@@ -1021,6 +1068,8 @@ struct intel_crtc_state {
/* actual state of LUTs */
struct drm_property_blob *pre_csc_lut, *post_csc_lut;
+ struct intel_csc_matrix csc, output_csc;
+
/**
* quirks - bitfield with hw state readout quirks
*
@@ -1123,6 +1172,7 @@ struct intel_crtc_state {
union {
struct intel_dpll_hw_state dpll_hw_state;
struct intel_mpllb_state mpllb_state;
+ struct intel_cx0pll_state cx0pll_state;
};
/*
@@ -1275,15 +1325,27 @@ struct intel_crtc_state {
/* HDMI High TMDS char rate ratio */
bool hdmi_high_tmds_clock_ratio;
- /* Output format RGB/YCBCR etc */
+ /*
+ * Output format RGB/YCBCR etc., that is coming out
+ * at the end of the pipe.
+ */
enum intel_output_format output_format;
+ /*
+ * Sink output format RGB/YCBCR etc., that is going
+ * into the sink.
+ */
+ enum intel_output_format sink_format;
+
/* enable pipe gamma? */
bool gamma_enable;
/* enable pipe csc? */
bool csc_enable;
+ /* enable vlv/chv wgc csc? */
+ bool wgc_enable;
+
/* big joiner pipe bitmask */
u8 bigjoiner_pipes;
@@ -1524,8 +1586,6 @@ struct intel_hdmi {
enum drm_dp_dual_mode_type type;
int max_tmds_clock;
} dp_dual_mode;
- bool has_hdmi_sink;
- bool has_audio;
struct intel_connector *attached_connector;
struct cec_notifier *cec_notifier;
};
@@ -1645,8 +1705,6 @@ struct intel_dp {
u8 lane_count;
u8 sink_count;
bool link_trained;
- bool has_hdmi_sink;
- bool has_audio;
bool reset_link_params;
bool use_max_params;
u8 dpcd[DP_RECEIVER_CAP_SIZE];
@@ -1728,6 +1786,7 @@ struct intel_dp {
int pcon_max_frl_bw;
u8 max_bpc;
bool ycbcr_444_to_420;
+ bool ycbcr420_passthrough;
bool rgb_to_ycbcr;
} dfp;
@@ -1814,10 +1873,6 @@ struct intel_dp_mst_encoder {
struct intel_connector *connector;
};
-struct intel_load_detect_pipe {
- struct drm_atomic_state *restore_state;
-};
-
static inline struct intel_encoder *
intel_attached_encoder(struct intel_connector *connector)
{
diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.c b/drivers/gpu/drm/i915/display/intel_dkl_phy.c
index 57cc3edba016..a001232ad445 100644
--- a/drivers/gpu/drm/i915/display/intel_dkl_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_dkl_phy.c
@@ -11,6 +11,15 @@
#include "intel_dkl_phy.h"
#include "intel_dkl_phy_regs.h"
+/**
+ * intel_dkl_phy_init - initialize Dekel PHY
+ * @i915: i915 device instance
+ */
+void intel_dkl_phy_init(struct drm_i915_private *i915)
+{
+ spin_lock_init(&i915->display.dkl.phy_lock);
+}
+
static void
dkl_phy_set_hip_idx(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg)
{
diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.h b/drivers/gpu/drm/i915/display/intel_dkl_phy.h
index 570ee36f9386..5956ec3e940b 100644
--- a/drivers/gpu/drm/i915/display/intel_dkl_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_dkl_phy.h
@@ -12,6 +12,7 @@
struct drm_i915_private;
+void intel_dkl_phy_init(struct drm_i915_private *i915);
u32
intel_dkl_phy_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg);
void
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index 8a88de67ff0a..5f479f3828bb 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -1057,7 +1057,7 @@ void intel_dmc_init(struct drm_i915_private *i915)
i915->display.dmc.dmc = dmc;
drm_dbg_kms(&i915->drm, "Loading %s\n", dmc->fw_path);
- schedule_work(&dmc->work);
+ queue_work(i915->unordered_wq, &dmc->work);
return;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 529ee22be872..9f40da20e88d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -44,8 +44,8 @@
#include <drm/drm_probe_helper.h>
#include "g4x_dp.h"
-#include "i915_debugfs.h"
#include "i915_drv.h"
+#include "i915_irq.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_audio.h"
@@ -53,6 +53,7 @@
#include "intel_combo_phy_regs.h"
#include "intel_connector.h"
#include "intel_crtc.h"
+#include "intel_cx0_phy.h"
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_types.h"
@@ -67,6 +68,7 @@
#include "intel_hdcp.h"
#include "intel_hdmi.h"
#include "intel_hotplug.h"
+#include "intel_hotplug_irq.h"
#include "intel_lspcon.h"
#include "intel_lvds.h"
#include "intel_panel.h"
@@ -421,6 +423,18 @@ static int ehl_max_source_rate(struct intel_dp *intel_dp)
return 810000;
}
+static int mtl_max_source_rate(struct intel_dp *intel_dp)
+{
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
+
+ if (intel_is_c10phy(i915, phy))
+ return intel_dp_is_edp(intel_dp) ? 675000 : 810000;
+
+ return 2000000;
+}
+
static int vbt_max_link_rate(struct intel_dp *intel_dp)
{
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
@@ -445,6 +459,10 @@ static void
intel_dp_set_source_rates(struct intel_dp *intel_dp)
{
/* The values must be in increasing order */
+ static const int mtl_rates[] = {
+ 162000, 216000, 243000, 270000, 324000, 432000, 540000, 675000,
+ 810000, 1000000, 1350000, 2000000,
+ };
static const int icl_rates[] = {
162000, 216000, 270000, 324000, 432000, 540000, 648000, 810000,
1000000, 1350000,
@@ -470,7 +488,11 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp)
drm_WARN_ON(&dev_priv->drm,
intel_dp->source_rates || intel_dp->num_source_rates);
- if (DISPLAY_VER(dev_priv) >= 11) {
+ if (DISPLAY_VER(dev_priv) >= 14) {
+ source_rates = mtl_rates;
+ size = ARRAY_SIZE(mtl_rates);
+ max_rate = mtl_max_source_rate(intel_dp);
+ } else if (DISPLAY_VER(dev_priv) >= 11) {
source_rates = icl_rates;
size = ARRAY_SIZE(icl_rates);
if (IS_DG2(dev_priv))
@@ -828,26 +850,88 @@ u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
return 0;
}
+static bool source_can_output(struct intel_dp *intel_dp,
+ enum intel_output_format format)
+{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+ switch (format) {
+ case INTEL_OUTPUT_FORMAT_RGB:
+ return true;
+
+ case INTEL_OUTPUT_FORMAT_YCBCR444:
+ /*
+ * No YCbCr output support on gmch platforms.
+ * Also, ILK doesn't seem capable of DP YCbCr output.
+ * The displayed image is severly corrupted. SNB+ is fine.
+ */
+ return !HAS_GMCH(i915) && !IS_IRONLAKE(i915);
+
+ case INTEL_OUTPUT_FORMAT_YCBCR420:
+ /* Platform < Gen 11 cannot output YCbCr420 format */
+ return DISPLAY_VER(i915) >= 11;
+
+ default:
+ MISSING_CASE(format);
+ return false;
+ }
+}
+
+static bool
+dfp_can_convert_from_rgb(struct intel_dp *intel_dp,
+ enum intel_output_format sink_format)
+{
+ if (!drm_dp_is_branch(intel_dp->dpcd))
+ return false;
+
+ if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR444)
+ return intel_dp->dfp.rgb_to_ycbcr;
+
+ if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
+ return intel_dp->dfp.rgb_to_ycbcr &&
+ intel_dp->dfp.ycbcr_444_to_420;
+
+ return false;
+}
+
+static bool
+dfp_can_convert_from_ycbcr444(struct intel_dp *intel_dp,
+ enum intel_output_format sink_format)
+{
+ if (!drm_dp_is_branch(intel_dp->dpcd))
+ return false;
+
+ if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
+ return intel_dp->dfp.ycbcr_444_to_420;
+
+ return false;
+}
+
static enum intel_output_format
intel_dp_output_format(struct intel_connector *connector,
- bool ycbcr_420_output)
+ enum intel_output_format sink_format)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ enum intel_output_format output_format;
if (intel_dp->force_dsc_output_format)
return intel_dp->force_dsc_output_format;
- if (!connector->base.ycbcr_420_allowed || !ycbcr_420_output)
- return INTEL_OUTPUT_FORMAT_RGB;
+ if (sink_format == INTEL_OUTPUT_FORMAT_RGB ||
+ dfp_can_convert_from_rgb(intel_dp, sink_format))
+ output_format = INTEL_OUTPUT_FORMAT_RGB;
- if (intel_dp->dfp.rgb_to_ycbcr &&
- intel_dp->dfp.ycbcr_444_to_420)
- return INTEL_OUTPUT_FORMAT_RGB;
+ else if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR444 ||
+ dfp_can_convert_from_ycbcr444(intel_dp, sink_format))
+ output_format = INTEL_OUTPUT_FORMAT_YCBCR444;
- if (intel_dp->dfp.ycbcr_444_to_420)
- return INTEL_OUTPUT_FORMAT_YCBCR444;
else
- return INTEL_OUTPUT_FORMAT_YCBCR420;
+ output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+
+ drm_WARN_ON(&i915->drm, !source_can_output(intel_dp, output_format));
+
+ return output_format;
}
int intel_dp_min_bpp(enum intel_output_format output_format)
@@ -871,13 +955,27 @@ static int intel_dp_output_bpp(enum intel_output_format output_format, int bpp)
return bpp;
}
+static enum intel_output_format
+intel_dp_sink_format(struct intel_connector *connector,
+ const struct drm_display_mode *mode)
+{
+ const struct drm_display_info *info = &connector->base.display_info;
+
+ if (drm_mode_is_420_only(info, mode))
+ return INTEL_OUTPUT_FORMAT_YCBCR420;
+
+ return INTEL_OUTPUT_FORMAT_RGB;
+}
+
static int
intel_dp_mode_min_output_bpp(struct intel_connector *connector,
const struct drm_display_mode *mode)
{
- const struct drm_display_info *info = &connector->base.display_info;
- enum intel_output_format output_format =
- intel_dp_output_format(connector, drm_mode_is_420_only(info, mode));
+ enum intel_output_format output_format, sink_format;
+
+ sink_format = intel_dp_sink_format(connector, mode);
+
+ output_format = intel_dp_output_format(connector, sink_format);
return intel_dp_output_bpp(output_format, intel_dp_min_bpp(output_format));
}
@@ -916,7 +1014,8 @@ static int intel_dp_max_tmds_clock(struct intel_dp *intel_dp)
static enum drm_mode_status
intel_dp_tmds_clock_valid(struct intel_dp *intel_dp,
- int clock, int bpc, bool ycbcr420_output,
+ int clock, int bpc,
+ enum intel_output_format sink_format,
bool respect_downstream_limits)
{
int tmds_clock, min_tmds_clock, max_tmds_clock;
@@ -924,7 +1023,7 @@ intel_dp_tmds_clock_valid(struct intel_dp *intel_dp,
if (!respect_downstream_limits)
return MODE_OK;
- tmds_clock = intel_hdmi_tmds_clock(clock, bpc, ycbcr420_output);
+ tmds_clock = intel_hdmi_tmds_clock(clock, bpc, sink_format);
min_tmds_clock = intel_dp->dfp.min_tmds_clock;
max_tmds_clock = intel_dp_max_tmds_clock(intel_dp);
@@ -946,7 +1045,7 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
struct intel_dp *intel_dp = intel_attached_dp(connector);
const struct drm_display_info *info = &connector->base.display_info;
enum drm_mode_status status;
- bool ycbcr_420_only;
+ enum intel_output_format sink_format;
/* If PCON supports FRL MODE, check FRL bandwidth constraints */
if (intel_dp->dfp.pcon_max_frl_bw) {
@@ -971,20 +1070,20 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
target_clock > intel_dp->dfp.max_dotclock)
return MODE_CLOCK_HIGH;
- ycbcr_420_only = drm_mode_is_420_only(info, mode);
+ sink_format = intel_dp_sink_format(connector, mode);
/* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */
status = intel_dp_tmds_clock_valid(intel_dp, target_clock,
- 8, ycbcr_420_only, true);
+ 8, sink_format, true);
if (status != MODE_OK) {
- if (ycbcr_420_only ||
+ if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
!connector->base.ycbcr_420_allowed ||
!drm_mode_is_420_also(info, mode))
return status;
-
+ sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
status = intel_dp_tmds_clock_valid(intel_dp, target_clock,
- 8, true, true);
+ 8, sink_format, true);
if (status != MODE_OK)
return status;
}
@@ -1041,6 +1140,9 @@ intel_dp_mode_valid(struct drm_connector *_connector,
if (target_clock > max_dotclk)
return MODE_CLOCK_HIGH;
+ if (intel_dp_hdisplay_bad(dev_priv, mode->hdisplay))
+ return MODE_H_ILLEGAL;
+
max_link_clock = intel_dp_max_link_rate(intel_dp);
max_lanes = intel_dp_max_lane_count(intel_dp);
@@ -1048,13 +1150,6 @@ intel_dp_mode_valid(struct drm_connector *_connector,
mode_rate = intel_dp_link_required(target_clock,
intel_dp_mode_min_output_bpp(connector, mode));
- if (intel_dp_hdisplay_bad(dev_priv, mode->hdisplay))
- return MODE_H_ILLEGAL;
-
- /*
- * Output bpp is stored in 6.4 format so right shift by 4 to get the
- * integer value since we support only integer values of bpp.
- */
if (HAS_DSC(dev_priv) &&
drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)) {
/*
@@ -1063,6 +1158,10 @@ intel_dp_mode_valid(struct drm_connector *_connector,
*/
int pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, U8_MAX);
+ /*
+ * Output bpp is stored in 6.4 format so right shift by 4 to get the
+ * integer value since we support only integer values of bpp.
+ */
if (intel_dp_is_edp(intel_dp)) {
dsc_max_output_bpp =
drm_edp_dsc_sink_output_bpp(intel_dp->dsc_dpcd) >> 4;
@@ -1188,6 +1287,13 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
}
}
+bool intel_dp_has_hdmi_sink(struct intel_dp *intel_dp)
+{
+ struct intel_connector *connector = intel_dp->attached_connector;
+
+ return connector->base.display_info.is_hdmi;
+}
+
static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp,
const struct intel_crtc_state *pipe_config)
{
@@ -1220,19 +1326,10 @@ static bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd);
}
-static bool intel_dp_is_ycbcr420(struct intel_dp *intel_dp,
- const struct intel_crtc_state *crtc_state)
-{
- return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
- (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 &&
- intel_dp->dfp.ycbcr_444_to_420);
-}
-
static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
int bpc, bool respect_downstream_limits)
{
- bool ycbcr420_output = intel_dp_is_ycbcr420(intel_dp, crtc_state);
int clock = crtc_state->hw.adjusted_mode.crtc_clock;
/*
@@ -1252,8 +1349,8 @@ static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp,
for (; bpc >= 8; bpc -= 2) {
if (intel_hdmi_bpc_possible(crtc_state, bpc,
- intel_dp->has_hdmi_sink, ycbcr420_output) &&
- intel_dp_tmds_clock_valid(intel_dp, clock, bpc, ycbcr420_output,
+ intel_dp_has_hdmi_sink(intel_dp)) &&
+ intel_dp_tmds_clock_valid(intel_dp, clock, bpc, crtc_state->sink_format,
respect_downstream_limits) == MODE_OK)
return bpc;
}
@@ -2069,6 +2166,7 @@ static bool intel_dp_has_audio(struct intel_encoder *encoder,
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ struct intel_connector *connector = intel_dp->attached_connector;
const struct intel_digital_connector_state *intel_conn_state =
to_intel_digital_connector_state(conn_state);
@@ -2076,7 +2174,7 @@ static bool intel_dp_has_audio(struct intel_encoder *encoder,
return false;
if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
- return intel_dp->has_audio;
+ return connector->base.display_info.has_audio;
else
return intel_conn_state->force_audio == HDMI_AUDIO_ON;
}
@@ -2097,23 +2195,27 @@ intel_dp_compute_output_format(struct intel_encoder *encoder,
ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode);
- crtc_state->output_format = intel_dp_output_format(connector, ycbcr_420_only);
-
- if (ycbcr_420_only && !intel_dp_is_ycbcr420(intel_dp, crtc_state)) {
+ if (ycbcr_420_only && !connector->base.ycbcr_420_allowed) {
drm_dbg_kms(&i915->drm,
"YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n");
- crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
+ crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB;
+ } else {
+ crtc_state->sink_format = intel_dp_sink_format(connector, adjusted_mode);
}
+ crtc_state->output_format = intel_dp_output_format(connector, crtc_state->sink_format);
+
ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state,
respect_downstream_limits);
if (ret) {
- if (intel_dp_is_ycbcr420(intel_dp, crtc_state) ||
+ if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
!connector->base.ycbcr_420_allowed ||
!drm_mode_is_420_also(info, adjusted_mode))
return ret;
- crtc_state->output_format = intel_dp_output_format(connector, true);
+ crtc_state->sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+ crtc_state->output_format = intel_dp_output_format(connector,
+ crtc_state->sink_format);
ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state,
respect_downstream_limits);
}
@@ -2637,7 +2739,7 @@ frl_trained:
static bool intel_dp_is_hdmi_2_1_sink(struct intel_dp *intel_dp)
{
if (drm_dp_is_branch(intel_dp->dpcd) &&
- intel_dp->has_hdmi_sink &&
+ intel_dp_has_hdmi_sink(intel_dp) &&
intel_dp_hdmi_sink_max_frl(intel_dp) > 0)
return true;
@@ -2795,6 +2897,8 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ bool ycbcr444_to_420 = false;
+ bool rgb_to_ycbcr = false;
u8 tmp;
if (intel_dp->dpcd[DP_DPCD_REV] < 0x13)
@@ -2803,16 +2907,42 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
if (!drm_dp_is_branch(intel_dp->dpcd))
return;
- tmp = intel_dp->has_hdmi_sink ?
- DP_HDMI_DVI_OUTPUT_CONFIG : 0;
+ tmp = intel_dp_has_hdmi_sink(intel_dp) ? DP_HDMI_DVI_OUTPUT_CONFIG : 0;
if (drm_dp_dpcd_writeb(&intel_dp->aux,
DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) != 1)
drm_dbg_kms(&i915->drm, "Failed to %s protocol converter HDMI mode\n",
- str_enable_disable(intel_dp->has_hdmi_sink));
+ str_enable_disable(intel_dp_has_hdmi_sink(intel_dp)));
- tmp = crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 &&
- intel_dp->dfp.ycbcr_444_to_420 ? DP_CONVERSION_TO_YCBCR420_ENABLE : 0;
+ if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
+ switch (crtc_state->output_format) {
+ case INTEL_OUTPUT_FORMAT_YCBCR420:
+ break;
+ case INTEL_OUTPUT_FORMAT_YCBCR444:
+ ycbcr444_to_420 = true;
+ break;
+ case INTEL_OUTPUT_FORMAT_RGB:
+ rgb_to_ycbcr = true;
+ ycbcr444_to_420 = true;
+ break;
+ default:
+ MISSING_CASE(crtc_state->output_format);
+ break;
+ }
+ } else if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR444) {
+ switch (crtc_state->output_format) {
+ case INTEL_OUTPUT_FORMAT_YCBCR444:
+ break;
+ case INTEL_OUTPUT_FORMAT_RGB:
+ rgb_to_ycbcr = true;
+ break;
+ default:
+ MISSING_CASE(crtc_state->output_format);
+ break;
+ }
+ }
+
+ tmp = ycbcr444_to_420 ? DP_CONVERSION_TO_YCBCR420_ENABLE : 0;
if (drm_dp_dpcd_writeb(&intel_dp->aux,
DP_PROTOCOL_CONVERTER_CONTROL_1, tmp) != 1)
@@ -2820,13 +2950,12 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
"Failed to %s protocol converter YCbCr 4:2:0 conversion mode\n",
str_enable_disable(intel_dp->dfp.ycbcr_444_to_420));
- tmp = intel_dp->dfp.rgb_to_ycbcr ?
- DP_CONVERSION_BT709_RGB_YCBCR_ENABLE : 0;
+ tmp = rgb_to_ycbcr ? DP_CONVERSION_BT709_RGB_YCBCR_ENABLE : 0;
if (drm_dp_pcon_convert_rgb_to_ycbcr(&intel_dp->aux, tmp) < 0)
drm_dbg_kms(&i915->drm,
- "Failed to %s protocol converter RGB->YCbCr conversion mode\n",
- str_enable_disable(tmp));
+ "Failed to %s protocol converter RGB->YCbCr conversion mode\n",
+ str_enable_disable(tmp));
}
bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
@@ -3940,9 +4069,7 @@ intel_dp_mst_hpd_irq(struct intel_dp *intel_dp, u8 *esi, u8 *ack)
{
bool handled = false;
- drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
- if (handled)
- ack[1] |= esi[1] & (DP_DOWN_REP_MSG_RDY | DP_UP_REQ_MSG_RDY);
+ drm_dp_mst_hpd_irq_handle_event(&intel_dp->mst_mgr, esi, ack, &handled);
if (esi[1] & DP_CP_IRQ) {
intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
@@ -4017,6 +4144,9 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
if (!intel_dp_ack_sink_irq_esi(intel_dp, ack))
drm_dbg_kms(&i915->drm, "Failed to ack ESI\n");
+
+ if (ack[1] & (DP_DOWN_REP_MSG_RDY | DP_UP_REQ_MSG_RDY))
+ drm_dp_mst_hpd_irq_send_new_request(&intel_dp->mst_mgr);
}
return link_ok;
@@ -4110,9 +4240,9 @@ static bool intel_dp_has_connector(struct intel_dp *intel_dp,
return false;
}
-static int intel_dp_prep_link_retrain(struct intel_dp *intel_dp,
- struct drm_modeset_acquire_ctx *ctx,
- u8 *pipe_mask)
+int intel_dp_get_active_pipes(struct intel_dp *intel_dp,
+ struct drm_modeset_acquire_ctx *ctx,
+ u8 *pipe_mask)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct drm_connector_list_iter conn_iter;
@@ -4121,9 +4251,6 @@ static int intel_dp_prep_link_retrain(struct intel_dp *intel_dp,
*pipe_mask = 0;
- if (!intel_dp_needs_link_retrain(intel_dp))
- return 0;
-
drm_connector_list_iter_begin(&i915->drm, &conn_iter);
for_each_intel_connector_iter(connector, &conn_iter) {
struct drm_connector_state *conn_state =
@@ -4157,9 +4284,6 @@ static int intel_dp_prep_link_retrain(struct intel_dp *intel_dp,
}
drm_connector_list_iter_end(&conn_iter);
- if (!intel_dp_needs_link_retrain(intel_dp))
- *pipe_mask = 0;
-
return ret;
}
@@ -4188,13 +4312,19 @@ int intel_dp_retrain_link(struct intel_encoder *encoder,
if (ret)
return ret;
- ret = intel_dp_prep_link_retrain(intel_dp, ctx, &pipe_mask);
+ if (!intel_dp_needs_link_retrain(intel_dp))
+ return 0;
+
+ ret = intel_dp_get_active_pipes(intel_dp, ctx, &pipe_mask);
if (ret)
return ret;
if (pipe_mask == 0)
return 0;
+ if (!intel_dp_needs_link_retrain(intel_dp))
+ return 0;
+
drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] retraining link\n",
encoder->base.base.id, encoder->base.name);
@@ -4616,57 +4746,44 @@ intel_dp_update_dfp(struct intel_dp *intel_dp,
intel_dp_get_pcon_dsc_cap(intel_dp);
}
+static bool
+intel_dp_can_ycbcr420(struct intel_dp *intel_dp)
+{
+ if (source_can_output(intel_dp, INTEL_OUTPUT_FORMAT_YCBCR420) &&
+ (!drm_dp_is_branch(intel_dp->dpcd) || intel_dp->dfp.ycbcr420_passthrough))
+ return true;
+
+ if (source_can_output(intel_dp, INTEL_OUTPUT_FORMAT_RGB) &&
+ dfp_can_convert_from_rgb(intel_dp, INTEL_OUTPUT_FORMAT_YCBCR420))
+ return true;
+
+ if (source_can_output(intel_dp, INTEL_OUTPUT_FORMAT_YCBCR444) &&
+ dfp_can_convert_from_ycbcr444(intel_dp, INTEL_OUTPUT_FORMAT_YCBCR420))
+ return true;
+
+ return false;
+}
+
static void
intel_dp_update_420(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct intel_connector *connector = intel_dp->attached_connector;
- bool is_branch, ycbcr_420_passthrough, ycbcr_444_to_420, rgb_to_ycbcr;
-
- /* No YCbCr output support on gmch platforms */
- if (HAS_GMCH(i915))
- return;
-
- /*
- * ILK doesn't seem capable of DP YCbCr output. The
- * displayed image is severly corrupted. SNB+ is fine.
- */
- if (IS_IRONLAKE(i915))
- return;
- is_branch = drm_dp_is_branch(intel_dp->dpcd);
- ycbcr_420_passthrough =
+ intel_dp->dfp.ycbcr420_passthrough =
drm_dp_downstream_420_passthrough(intel_dp->dpcd,
intel_dp->downstream_ports);
/* on-board LSPCON always assumed to support 4:4:4->4:2:0 conversion */
- ycbcr_444_to_420 =
+ intel_dp->dfp.ycbcr_444_to_420 =
dp_to_dig_port(intel_dp)->lspcon.active ||
drm_dp_downstream_444_to_420_conversion(intel_dp->dpcd,
intel_dp->downstream_ports);
- rgb_to_ycbcr = drm_dp_downstream_rgb_to_ycbcr_conversion(intel_dp->dpcd,
- intel_dp->downstream_ports,
- DP_DS_HDMI_BT709_RGB_YCBCR_CONV);
-
- if (DISPLAY_VER(i915) >= 11) {
- /* Let PCON convert from RGB->YCbCr if possible */
- if (is_branch && rgb_to_ycbcr && ycbcr_444_to_420) {
- intel_dp->dfp.rgb_to_ycbcr = true;
- intel_dp->dfp.ycbcr_444_to_420 = true;
- connector->base.ycbcr_420_allowed = true;
- } else {
- /* Prefer 4:2:0 passthrough over 4:4:4->4:2:0 conversion */
- intel_dp->dfp.ycbcr_444_to_420 =
- ycbcr_444_to_420 && !ycbcr_420_passthrough;
-
- connector->base.ycbcr_420_allowed =
- !is_branch || ycbcr_444_to_420 || ycbcr_420_passthrough;
- }
- } else {
- /* 4:4:4->4:2:0 conversion is the only way */
- intel_dp->dfp.ycbcr_444_to_420 = ycbcr_444_to_420;
+ intel_dp->dfp.rgb_to_ycbcr =
+ drm_dp_downstream_rgb_to_ycbcr_conversion(intel_dp->dpcd,
+ intel_dp->downstream_ports,
+ DP_DS_HDMI_BT709_RGB_YCBCR_CONV);
- connector->base.ycbcr_420_allowed = ycbcr_444_to_420;
- }
+ connector->base.ycbcr_420_allowed = intel_dp_can_ycbcr420(intel_dp);
drm_dbg_kms(&i915->drm,
"[CONNECTOR:%d:%s] RGB->YcbCr conversion? %s, YCbCr 4:2:0 allowed? %s, YCbCr 4:4:4->4:2:0 conversion? %s\n",
@@ -4702,10 +4819,6 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
/* FIXME: Get rid of drm_edid_raw() */
edid = drm_edid_raw(drm_edid);
- if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
- intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
- intel_dp->has_audio = drm_detect_monitor_audio(edid);
- }
drm_dp_cec_set_edid(&intel_dp->aux, edid);
}
@@ -4719,9 +4832,6 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
drm_edid_free(connector->detect_edid);
connector->detect_edid = NULL;
- intel_dp->has_hdmi_sink = false;
- intel_dp->has_audio = false;
-
intel_dp->dfp.max_bpc = 0;
intel_dp->dfp.max_dotclock = 0;
intel_dp->dfp.min_tmds_clock = 0;
@@ -5142,7 +5252,7 @@ static void intel_dp_oob_hotplug_event(struct drm_connector *connector)
spin_lock_irq(&i915->irq_lock);
i915->display.hotplug.event_bits |= BIT(encoder->hpd_pin);
spin_unlock_irq(&i915->irq_lock);
- queue_delayed_work(system_wq, &i915->display.hotplug.hotplug_work, 0);
+ queue_delayed_work(i915->unordered_wq, &i915->display.hotplug.hotplug_work, 0);
}
static const struct drm_connector_funcs intel_dp_connector_funcs = {
@@ -5370,6 +5480,15 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
goto out_vdd_off;
}
+ /*
+ * Enable HPD sense for live status check.
+ * intel_hpd_irq_setup() will turn it off again
+ * if it's no longer needed later.
+ *
+ * The DPCD probe below will make sure VDD is on.
+ */
+ intel_hpd_enable_detection(encoder);
+
/* Cache DPCD and EDID for edp. */
has_dpcd = intel_edp_init_dpcd(intel_dp);
@@ -5381,6 +5500,24 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
goto out_vdd_off;
}
+ /*
+ * VBT and straps are liars. Also check HPD as that seems
+ * to be the most reliable piece of information available.
+ */
+ if (!intel_digital_port_connected(encoder)) {
+ /*
+ * If this fails, presume the DPCD answer came
+ * from some other port using the same AUX CH.
+ *
+ * FIXME maybe cleaner to check this before the
+ * DPCD read? Would need sort out the VDD handling...
+ */
+ drm_info(&dev_priv->drm,
+ "[ENCODER:%d:%s] HPD is down, disabling eDP\n",
+ encoder->base.base.id, encoder->base.name);
+ goto out_vdd_off;
+ }
+
mutex_lock(&dev_priv->drm.mode_config.mutex);
drm_edid = drm_edid_read_ddc(connector, &intel_dp->aux.ddc);
if (!drm_edid) {
@@ -5583,6 +5720,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
return true;
fail:
+ intel_display_power_flush_work(dev_priv);
drm_connector_cleanup(connector);
return false;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index ef39e4f7a329..22099de3ca45 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -42,6 +42,9 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp,
int link_rate, int lane_count);
int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
int link_rate, u8 lane_count);
+int intel_dp_get_active_pipes(struct intel_dp *intel_dp,
+ struct drm_modeset_acquire_ctx *ctx,
+ u8 *pipe_mask);
int intel_dp_retrain_link(struct intel_encoder *encoder,
struct drm_modeset_acquire_ctx *ctx);
void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode);
@@ -62,6 +65,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
struct link_config_limits *limits,
int timeslots,
bool recompute_pipe_bpp);
+bool intel_dp_has_hdmi_sink(struct intel_dp *intel_dp);
bool intel_dp_is_edp(struct intel_dp *intel_dp);
bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state);
bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c
index 524bd6da260c..197c6e81db14 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
@@ -161,14 +161,14 @@ static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
timeout = DP_AUX_CH_CTL_TIME_OUT_400us;
return DP_AUX_CH_CTL_SEND_BUSY |
- DP_AUX_CH_CTL_DONE |
- DP_AUX_CH_CTL_INTERRUPT |
- DP_AUX_CH_CTL_TIME_OUT_ERROR |
- timeout |
- DP_AUX_CH_CTL_RECEIVE_ERROR |
- (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
- (g4x_dp_aux_precharge_len() << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
- (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT);
+ DP_AUX_CH_CTL_DONE |
+ DP_AUX_CH_CTL_INTERRUPT |
+ DP_AUX_CH_CTL_TIME_OUT_ERROR |
+ timeout |
+ DP_AUX_CH_CTL_RECEIVE_ERROR |
+ DP_AUX_CH_CTL_MESSAGE_SIZE(send_bytes) |
+ DP_AUX_CH_CTL_PRECHARGE_2US(g4x_dp_aux_precharge_len()) |
+ DP_AUX_CH_CTL_BIT_CLOCK_2X(aux_clock_divider);
}
static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
@@ -185,14 +185,14 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
* ICL+: 4ms
*/
ret = DP_AUX_CH_CTL_SEND_BUSY |
- DP_AUX_CH_CTL_DONE |
- DP_AUX_CH_CTL_INTERRUPT |
- DP_AUX_CH_CTL_TIME_OUT_ERROR |
- DP_AUX_CH_CTL_TIME_OUT_MAX |
- DP_AUX_CH_CTL_RECEIVE_ERROR |
- (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
- DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(intel_dp_aux_fw_sync_len()) |
- DP_AUX_CH_CTL_SYNC_PULSE_SKL(intel_dp_aux_sync_len());
+ DP_AUX_CH_CTL_DONE |
+ DP_AUX_CH_CTL_INTERRUPT |
+ DP_AUX_CH_CTL_TIME_OUT_ERROR |
+ DP_AUX_CH_CTL_TIME_OUT_MAX |
+ DP_AUX_CH_CTL_RECEIVE_ERROR |
+ DP_AUX_CH_CTL_MESSAGE_SIZE(send_bytes) |
+ DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(intel_dp_aux_fw_sync_len()) |
+ DP_AUX_CH_CTL_SYNC_PULSE_SKL(intel_dp_aux_sync_len());
if (intel_tc_port_in_tbt_alt_mode(dig_port))
ret |= DP_AUX_CH_CTL_TBT_IO;
@@ -268,6 +268,11 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
intel_pps_check_power_unlocked(intel_dp);
+ /*
+ * FIXME PSR should be disabled here to prevent
+ * it using the same AUX CH simultaneously
+ */
+
/* Try to wait for any previous AUX channel activity */
for (try = 0; try < 3; try++) {
status = intel_de_read_notrace(i915, ch_ctl);
@@ -373,8 +378,7 @@ done:
}
/* Unload any bytes sent back from the other side */
- recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
- DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
+ recv_bytes = REG_FIELD_GET(DP_AUX_CH_CTL_MESSAGE_SIZE_MASK, status);
/*
* By BSpec: "Message sizes of 0 or >20 are not allowed."
@@ -810,3 +814,8 @@ enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder)
return aux_ch;
}
+
+void intel_dp_aux_irq_handler(struct drm_i915_private *i915)
+{
+ wake_up_all(&i915->display.gmbus.wait_queue);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.h b/drivers/gpu/drm/i915/display/intel_dp_aux.h
index 138e340f94ee..5b608f9d3499 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.h
@@ -7,6 +7,7 @@
#define __INTEL_DP_AUX_H__
enum aux_ch;
+struct drm_i915_private;
struct intel_dp;
struct intel_encoder;
@@ -15,4 +16,6 @@ void intel_dp_aux_init(struct intel_dp *intel_dp);
enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder);
+void intel_dp_aux_irq_handler(struct drm_i915_private *i915);
+
#endif /* __INTEL_DP_AUX_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h b/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h
index 5702f318d537..5185345277c7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h
@@ -50,35 +50,37 @@
_XELPDP_USBC3_AUX_CH_DATA1, \
_XELPDP_USBC4_AUX_CH_DATA1) + (i) * 4)
-#define DP_AUX_CH_CTL_SEND_BUSY (1 << 31)
-#define DP_AUX_CH_CTL_DONE (1 << 30)
-#define DP_AUX_CH_CTL_INTERRUPT (1 << 29)
-#define DP_AUX_CH_CTL_TIME_OUT_ERROR (1 << 28)
-#define DP_AUX_CH_CTL_TIME_OUT_400us (0 << 26)
-#define DP_AUX_CH_CTL_TIME_OUT_600us (1 << 26)
-#define DP_AUX_CH_CTL_TIME_OUT_800us (2 << 26)
-#define DP_AUX_CH_CTL_TIME_OUT_MAX (3 << 26) /* Varies per platform */
-#define DP_AUX_CH_CTL_TIME_OUT_MASK (3 << 26)
-#define DP_AUX_CH_CTL_RECEIVE_ERROR (1 << 25)
-#define DP_AUX_CH_CTL_MESSAGE_SIZE_MASK (0x1f << 20)
-#define DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT 20
-#define XELPDP_DP_AUX_CH_CTL_POWER_REQUEST REG_BIT(19)
-#define XELPDP_DP_AUX_CH_CTL_POWER_STATUS REG_BIT(18)
-#define DP_AUX_CH_CTL_PRECHARGE_2US_MASK (0xf << 16)
-#define DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT 16
-#define DP_AUX_CH_CTL_AUX_AKSV_SELECT (1 << 15)
-#define DP_AUX_CH_CTL_MANCHESTER_TEST (1 << 14)
-#define DP_AUX_CH_CTL_SYNC_TEST (1 << 13)
-#define DP_AUX_CH_CTL_DEGLITCH_TEST (1 << 12)
-#define DP_AUX_CH_CTL_PRECHARGE_TEST (1 << 11)
-#define DP_AUX_CH_CTL_BIT_CLOCK_2X_MASK (0x7ff)
-#define DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT 0
-#define DP_AUX_CH_CTL_PSR_DATA_AUX_REG_SKL (1 << 14)
-#define DP_AUX_CH_CTL_FS_DATA_AUX_REG_SKL (1 << 13)
-#define DP_AUX_CH_CTL_GTC_DATA_AUX_REG_SKL (1 << 12)
-#define DP_AUX_CH_CTL_TBT_IO (1 << 11)
-#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL_MASK (0x1f << 5)
-#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(c) (((c) - 1) << 5)
-#define DP_AUX_CH_CTL_SYNC_PULSE_SKL(c) ((c) - 1)
+#define DP_AUX_CH_CTL_SEND_BUSY REG_BIT(31)
+#define DP_AUX_CH_CTL_DONE REG_BIT(30)
+#define DP_AUX_CH_CTL_INTERRUPT REG_BIT(29)
+#define DP_AUX_CH_CTL_TIME_OUT_ERROR REG_BIT(28)
+
+#define DP_AUX_CH_CTL_TIME_OUT_MASK REG_GENMASK(27, 26)
+#define DP_AUX_CH_CTL_TIME_OUT_400us REG_FIELD_PREP(DP_AUX_CH_CTL_TIME_OUT_MASK, 0)
+#define DP_AUX_CH_CTL_TIME_OUT_600us REG_FIELD_PREP(DP_AUX_CH_CTL_TIME_OUT_MASK, 1)
+#define DP_AUX_CH_CTL_TIME_OUT_800us REG_FIELD_PREP(DP_AUX_CH_CTL_TIME_OUT_MASK, 2)
+#define DP_AUX_CH_CTL_TIME_OUT_MAX REG_FIELD_PREP(DP_AUX_CH_CTL_TIME_OUT_MASK, 3) /* Varies per platform */
+#define DP_AUX_CH_CTL_RECEIVE_ERROR REG_BIT(25)
+#define DP_AUX_CH_CTL_MESSAGE_SIZE_MASK REG_GENMASK(24, 20)
+#define DP_AUX_CH_CTL_MESSAGE_SIZE(x) REG_FIELD_PREP(DP_AUX_CH_CTL_MESSAGE_SIZE_MASK, (x))
+#define DP_AUX_CH_CTL_PRECHARGE_2US_MASK REG_GENMASK(19, 16) /* pre-skl */
+#define DP_AUX_CH_CTL_PRECHARGE_2US(x) REG_FIELD_PREP(DP_AUX_CH_CTL_PRECHARGE_2US_MASK, (x))
+#define XELPDP_DP_AUX_CH_CTL_POWER_REQUEST REG_BIT(19) /* mtl+ */
+#define XELPDP_DP_AUX_CH_CTL_POWER_STATUS REG_BIT(18) /* mtl+ */
+#define DP_AUX_CH_CTL_AUX_AKSV_SELECT REG_BIT(15)
+#define DP_AUX_CH_CTL_MANCHESTER_TEST REG_BIT(14) /* pre-hsw */
+#define DP_AUX_CH_CTL_PSR_DATA_AUX_REG_SKL REG_BIT(14) /* skl+ */
+#define DP_AUX_CH_CTL_SYNC_TEST REG_BIT(13) /* pre-hsw */
+#define DP_AUX_CH_CTL_FS_DATA_AUX_REG_SKL REG_BIT(13) /* skl+ */
+#define DP_AUX_CH_CTL_DEGLITCH_TEST REG_BIT(12) /* pre-hsw */
+#define DP_AUX_CH_CTL_GTC_DATA_AUX_REG_SKL REG_BIT(12) /* skl+ */
+#define DP_AUX_CH_CTL_PRECHARGE_TEST REG_BIT(11) /* pre-hsw */
+#define DP_AUX_CH_CTL_TBT_IO REG_BIT(11) /* icl+ */
+#define DP_AUX_CH_CTL_BIT_CLOCK_2X_MASK REG_GENMASK(10, 0) /* pre-skl */
+#define DP_AUX_CH_CTL_BIT_CLOCK_2X(x) REG_FIELD_PREP(DP_AUX_CH_CTL_BIT_CLOCK_2X_MASK, (x))
+#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL_MASK REG_GENMASK(9, 5) /* skl+ */
+#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(c) REG_FIELD_PREP(DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL_MASK, (c) - 1)
+#define DP_AUX_CH_CTL_SYNC_PULSE_SKL_MASK REG_GENMASK(4, 0) /* skl+ */
+#define DP_AUX_CH_CTL_SYNC_PULSE_SKL(c) REG_FIELD_PREP(DP_AUX_CH_CTL_SYNC_PULSE_SKL_MASK, (c) - 1)
#endif /* __INTEL_DP_AUX_REGS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index d638054c74ac..a263773f4d68 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -26,6 +26,27 @@
#include "intel_dp.h"
#include "intel_dp_link_training.h"
+#define LT_MSG_PREFIX "[CONNECTOR:%d:%s][ENCODER:%d:%s][%s] "
+#define LT_MSG_ARGS(_intel_dp, _dp_phy) (_intel_dp)->attached_connector->base.base.id, \
+ (_intel_dp)->attached_connector->base.name, \
+ dp_to_dig_port(_intel_dp)->base.base.base.id, \
+ dp_to_dig_port(_intel_dp)->base.base.name, \
+ drm_dp_phy_name(_dp_phy)
+
+#define lt_dbg(_intel_dp, _dp_phy, _format, ...) \
+ drm_dbg_kms(&dp_to_i915(_intel_dp)->drm, \
+ LT_MSG_PREFIX _format, \
+ LT_MSG_ARGS(_intel_dp, _dp_phy), ## __VA_ARGS__)
+
+#define lt_err(_intel_dp, _dp_phy, _format, ...) do { \
+ if (intel_digital_port_connected(&dp_to_dig_port(_intel_dp)->base)) \
+ drm_err(&dp_to_i915(_intel_dp)->drm, \
+ LT_MSG_PREFIX _format, \
+ LT_MSG_ARGS(_intel_dp, _dp_phy), ## __VA_ARGS__); \
+ else \
+ lt_dbg(_intel_dp, _dp_phy, "Sink disconnected: " _format, ## __VA_ARGS__); \
+} while (0)
+
static void intel_dp_reset_lttpr_common_caps(struct intel_dp *intel_dp)
{
memset(intel_dp->lttpr_common_caps, 0, sizeof(intel_dp->lttpr_common_caps));
@@ -47,29 +68,21 @@ static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
const u8 dpcd[DP_RECEIVER_CAP_SIZE],
enum drm_dp_phy dp_phy)
{
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
u8 *phy_caps = intel_dp_lttpr_phy_caps(intel_dp, dp_phy);
if (drm_dp_read_lttpr_phy_caps(&intel_dp->aux, dpcd, dp_phy, phy_caps) < 0) {
- drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
- "[ENCODER:%d:%s][%s] failed to read the PHY caps\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_dbg(intel_dp, dp_phy, "failed to read the PHY caps\n");
return;
}
- drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
- "[ENCODER:%d:%s][%s] PHY capabilities: %*ph\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy),
- (int)sizeof(intel_dp->lttpr_phy_caps[0]),
- phy_caps);
+ lt_dbg(intel_dp, dp_phy, "PHY capabilities: %*ph\n",
+ (int)sizeof(intel_dp->lttpr_phy_caps[0]),
+ phy_caps);
}
static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp,
const u8 dpcd[DP_RECEIVER_CAP_SIZE])
{
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
int ret;
ret = drm_dp_read_lttpr_common_caps(&intel_dp->aux, dpcd,
@@ -77,11 +90,9 @@ static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp,
if (ret < 0)
goto reset_caps;
- drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
- "[ENCODER:%d:%s] LTTPR common capabilities: %*ph\n",
- encoder->base.base.id, encoder->base.name,
- (int)sizeof(intel_dp->lttpr_common_caps),
- intel_dp->lttpr_common_caps);
+ lt_dbg(intel_dp, DP_PHY_DPRX, "LTTPR common capabilities: %*ph\n",
+ (int)sizeof(intel_dp->lttpr_common_caps),
+ intel_dp->lttpr_common_caps);
/* The minimum value of LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV is 1.4 */
if (intel_dp->lttpr_common_caps[0] < 0x14)
@@ -105,8 +116,6 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE])
{
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
int lttpr_count;
int i;
@@ -138,9 +147,8 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEI
return 0;
if (!intel_dp_set_lttpr_transparent_mode(intel_dp, false)) {
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s] Switching to LTTPR non-transparent LT mode failed, fall-back to transparent mode\n",
- encoder->base.base.id, encoder->base.name);
+ lt_dbg(intel_dp, DP_PHY_DPRX,
+ "Switching to LTTPR non-transparent LT mode failed, fall-back to transparent mode\n");
intel_dp_set_lttpr_transparent_mode(intel_dp, true);
intel_dp_reset_lttpr_count(intel_dp);
@@ -409,26 +417,22 @@ intel_dp_get_adjust_train(struct intel_dp *intel_dp,
enum drm_dp_phy dp_phy,
const u8 link_status[DP_LINK_STATUS_SIZE])
{
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
int lane;
if (intel_dp_is_uhbr(crtc_state)) {
- drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s][%s] 128b/132b, lanes: %d, "
- "TX FFE request: " TRAIN_REQ_FMT "\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy),
- crtc_state->lane_count,
- TRAIN_REQ_TX_FFE_ARGS(link_status));
+ lt_dbg(intel_dp, dp_phy,
+ "128b/132b, lanes: %d, "
+ "TX FFE request: " TRAIN_REQ_FMT "\n",
+ crtc_state->lane_count,
+ TRAIN_REQ_TX_FFE_ARGS(link_status));
} else {
- drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s][%s] 8b/10b, lanes: %d, "
- "vswing request: " TRAIN_REQ_FMT ", "
- "pre-emphasis request: " TRAIN_REQ_FMT "\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy),
- crtc_state->lane_count,
- TRAIN_REQ_VSWING_ARGS(link_status),
- TRAIN_REQ_PREEMPH_ARGS(link_status));
+ lt_dbg(intel_dp, dp_phy,
+ "8b/10b, lanes: %d, "
+ "vswing request: " TRAIN_REQ_FMT ", "
+ "pre-emphasis request: " TRAIN_REQ_FMT "\n",
+ crtc_state->lane_count,
+ TRAIN_REQ_VSWING_ARGS(link_status),
+ TRAIN_REQ_PREEMPH_ARGS(link_status));
}
for (lane = 0; lane < 4; lane++)
@@ -487,16 +491,11 @@ intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
enum drm_dp_phy dp_phy,
u8 dp_train_pat)
{
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
u8 train_pat = intel_dp_training_pattern_symbol(dp_train_pat);
if (train_pat != DP_TRAINING_PATTERN_DISABLE)
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s][%s] Using DP training pattern TPS%c\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy),
- dp_training_pattern_name(train_pat));
+ lt_dbg(intel_dp, dp_phy, "Using DP training pattern TPS%c\n",
+ dp_training_pattern_name(train_pat));
intel_dp->set_link_train(intel_dp, crtc_state, dp_train_pat);
}
@@ -531,24 +530,21 @@ void intel_dp_set_signal_levels(struct intel_dp *intel_dp,
enum drm_dp_phy dp_phy)
{
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
if (intel_dp_is_uhbr(crtc_state)) {
- drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s][%s] 128b/132b, lanes: %d, "
- "TX FFE presets: " TRAIN_SET_FMT "\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy),
- crtc_state->lane_count,
- TRAIN_SET_TX_FFE_ARGS(intel_dp->train_set));
+ lt_dbg(intel_dp, dp_phy,
+ "128b/132b, lanes: %d, "
+ "TX FFE presets: " TRAIN_SET_FMT "\n",
+ crtc_state->lane_count,
+ TRAIN_SET_TX_FFE_ARGS(intel_dp->train_set));
} else {
- drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s][%s] 8b/10b, lanes: %d, "
- "vswing levels: " TRAIN_SET_FMT ", "
- "pre-emphasis levels: " TRAIN_SET_FMT "\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy),
- crtc_state->lane_count,
- TRAIN_SET_VSWING_ARGS(intel_dp->train_set),
- TRAIN_SET_PREEMPH_ARGS(intel_dp->train_set));
+ lt_dbg(intel_dp, dp_phy,
+ "8b/10b, lanes: %d, "
+ "vswing levels: " TRAIN_SET_FMT ", "
+ "pre-emphasis levels: " TRAIN_SET_FMT "\n",
+ crtc_state->lane_count,
+ TRAIN_SET_VSWING_ARGS(intel_dp->train_set),
+ TRAIN_SET_PREEMPH_ARGS(intel_dp->train_set));
}
if (intel_dp_phy_is_downstream_of_source(intel_dp, dp_phy))
@@ -637,6 +633,38 @@ static bool intel_dp_link_max_vswing_reached(struct intel_dp *intel_dp,
return true;
}
+static void
+intel_dp_update_downspread_ctrl(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state)
+{
+ u8 link_config[2];
+
+ link_config[0] = crtc_state->vrr.flipline ? DP_MSA_TIMING_PAR_IGNORE_EN : 0;
+ link_config[1] = intel_dp_is_uhbr(crtc_state) ?
+ DP_SET_ANSI_128B132B : DP_SET_ANSI_8B10B;
+ drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2);
+}
+
+static void
+intel_dp_update_link_bw_set(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state,
+ u8 link_bw, u8 rate_select)
+{
+ u8 link_config[2];
+
+ /* Write the link configuration data */
+ link_config[0] = link_bw;
+ link_config[1] = crtc_state->lane_count;
+ if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+ link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+ drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
+
+ /* eDP 1.4 rate select method. */
+ if (!link_bw)
+ drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET,
+ &rate_select, 1);
+}
+
/*
* Prepare link training by configuring the link parameters. On DDI platforms
* also enable the port here.
@@ -645,9 +673,6 @@ static bool
intel_dp_prepare_link_train(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- u8 link_config[2];
u8 link_bw, rate_select;
if (intel_dp->prepare_link_retrain)
@@ -668,41 +693,28 @@ intel_dp_prepare_link_train(struct intel_dp *intel_dp,
* link rates are not stable.
*/
if (!link_bw) {
- struct intel_connector *connector = intel_dp->attached_connector;
__le16 sink_rates[DP_MAX_SUPPORTED_RATES];
- drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] Reloading eDP link rates\n",
- connector->base.base.id, connector->base.name);
+ lt_dbg(intel_dp, DP_PHY_DPRX, "Reloading eDP link rates\n");
drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES,
sink_rates, sizeof(sink_rates));
}
if (link_bw)
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s] Using LINK_BW_SET value %02x\n",
- encoder->base.base.id, encoder->base.name, link_bw);
+ lt_dbg(intel_dp, DP_PHY_DPRX, "Using LINK_BW_SET value %02x\n",
+ link_bw);
else
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s] Using LINK_RATE_SET value %02x\n",
- encoder->base.base.id, encoder->base.name, rate_select);
-
- /* Write the link configuration data */
- link_config[0] = link_bw;
- link_config[1] = crtc_state->lane_count;
- if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
- link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
- drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
-
- /* eDP 1.4 rate select method. */
- if (!link_bw)
- drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET,
- &rate_select, 1);
-
- link_config[0] = crtc_state->vrr.enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0;
- link_config[1] = intel_dp_is_uhbr(crtc_state) ?
- DP_SET_ANSI_128B132B : DP_SET_ANSI_8B10B;
- drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2);
+ lt_dbg(intel_dp, DP_PHY_DPRX,
+ "Using LINK_RATE_SET value %02x\n",
+ rate_select);
+ /*
+ * Spec DP2.1 Section 3.5.2.16
+ * Prior to LT DPTX should set 128b/132b DP Channel coding and then set link rate
+ */
+ intel_dp_update_downspread_ctrl(intel_dp, crtc_state);
+ intel_dp_update_link_bw_set(intel_dp, crtc_state, link_bw,
+ rate_select);
return true;
}
@@ -737,15 +749,10 @@ void
intel_dp_dump_link_status(struct intel_dp *intel_dp, enum drm_dp_phy dp_phy,
const u8 link_status[DP_LINK_STATUS_SIZE])
{
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
-
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s][%s] ln0_1:0x%x ln2_3:0x%x align:0x%x sink:0x%x adj_req0_1:0x%x adj_req2_3:0x%x\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy),
- link_status[0], link_status[1], link_status[2],
- link_status[3], link_status[4], link_status[5]);
+ lt_dbg(intel_dp, dp_phy,
+ "ln0_1:0x%x ln2_3:0x%x align:0x%x sink:0x%x adj_req0_1:0x%x adj_req2_3:0x%x\n",
+ link_status[0], link_status[1], link_status[2],
+ link_status[3], link_status[4], link_status[5]);
}
/*
@@ -757,8 +764,6 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
enum drm_dp_phy dp_phy)
{
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
u8 old_link_status[DP_LINK_STATUS_SIZE] = {};
int voltage_tries, cr_tries, max_cr_tries;
u8 link_status[DP_LINK_STATUS_SIZE];
@@ -773,9 +778,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp,
if (!intel_dp_reset_link_train(intel_dp, crtc_state, dp_phy,
DP_TRAINING_PATTERN_1 |
DP_LINK_SCRAMBLING_DISABLE)) {
- drm_err(&i915->drm, "[ENCODER:%d:%s][%s] Failed to enable link training\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_err(intel_dp, dp_phy, "Failed to enable link training\n");
return false;
}
@@ -798,35 +801,24 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp,
if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, dp_phy,
link_status) < 0) {
- drm_err(&i915->drm, "[ENCODER:%d:%s][%s] Failed to get link status\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_err(intel_dp, dp_phy, "Failed to get link status\n");
return false;
}
if (drm_dp_clock_recovery_ok(link_status, crtc_state->lane_count)) {
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s][%s] Clock recovery OK\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_dbg(intel_dp, dp_phy, "Clock recovery OK\n");
return true;
}
if (voltage_tries == 5) {
intel_dp_dump_link_status(intel_dp, dp_phy, link_status);
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s][%s] Same voltage tried 5 times\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_dbg(intel_dp, dp_phy, "Same voltage tried 5 times\n");
return false;
}
if (max_vswing_reached) {
intel_dp_dump_link_status(intel_dp, dp_phy, link_status);
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s][%s] Max Voltage Swing reached\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_dbg(intel_dp, dp_phy, "Max Voltage Swing reached\n");
return false;
}
@@ -834,10 +826,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp,
intel_dp_get_adjust_train(intel_dp, crtc_state, dp_phy,
link_status);
if (!intel_dp_update_link_train(intel_dp, crtc_state, dp_phy)) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s][%s] Failed to update link training\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_err(intel_dp, dp_phy, "Failed to update link training\n");
return false;
}
@@ -853,10 +842,8 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp,
}
intel_dp_dump_link_status(intel_dp, dp_phy, link_status);
- drm_err(&i915->drm,
- "[ENCODER:%d:%s][%s] Failed clock recovery %d times, giving up!\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy), max_cr_tries);
+ lt_err(intel_dp, dp_phy, "Failed clock recovery %d times, giving up!\n",
+ max_cr_tries);
return false;
}
@@ -890,11 +877,11 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp,
return DP_TRAINING_PATTERN_4;
} else if (crtc_state->port_clock == 810000) {
if (!source_tps4)
- drm_dbg_kms(&i915->drm,
- "8.1 Gbps link rate without source TPS4 support\n");
+ lt_dbg(intel_dp, dp_phy,
+ "8.1 Gbps link rate without source TPS4 support\n");
if (!sink_tps4)
- drm_dbg_kms(&i915->drm,
- "8.1 Gbps link rate without sink TPS4 support\n");
+ lt_dbg(intel_dp, dp_phy,
+ "8.1 Gbps link rate without sink TPS4 support\n");
}
/*
@@ -908,11 +895,11 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp,
return DP_TRAINING_PATTERN_3;
} else if (crtc_state->port_clock >= 540000) {
if (!source_tps3)
- drm_dbg_kms(&i915->drm,
- ">=5.4/6.48 Gbps link rate without source TPS3 support\n");
+ lt_dbg(intel_dp, dp_phy,
+ ">=5.4/6.48 Gbps link rate without source TPS3 support\n");
if (!sink_tps3)
- drm_dbg_kms(&i915->drm,
- ">=5.4/6.48 Gbps link rate without sink TPS3 support\n");
+ lt_dbg(intel_dp, dp_phy,
+ ">=5.4/6.48 Gbps link rate without sink TPS3 support\n");
}
return DP_TRAINING_PATTERN_2;
@@ -928,8 +915,6 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
enum drm_dp_phy dp_phy)
{
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
int tries;
u32 training_pattern;
u8 link_status[DP_LINK_STATUS_SIZE];
@@ -948,10 +933,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp,
/* channel equalization */
if (!intel_dp_set_link_train(intel_dp, crtc_state, dp_phy,
training_pattern)) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s][%s] Failed to start channel equalization\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_err(intel_dp, dp_phy, "Failed to start channel equalization\n");
return false;
}
@@ -960,10 +942,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp,
if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, dp_phy,
link_status) < 0) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s][%s] Failed to get link status\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_err(intel_dp, dp_phy, "Failed to get link status\n");
break;
}
@@ -971,21 +950,15 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp,
if (!drm_dp_clock_recovery_ok(link_status,
crtc_state->lane_count)) {
intel_dp_dump_link_status(intel_dp, dp_phy, link_status);
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s][%s] Clock recovery check failed, cannot "
- "continue channel equalization\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_dbg(intel_dp, dp_phy,
+ "Clock recovery check failed, cannot continue channel equalization\n");
break;
}
if (drm_dp_channel_eq_ok(link_status,
crtc_state->lane_count)) {
channel_eq = true;
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s][%s] Channel EQ done. DP Training successful\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_dbg(intel_dp, dp_phy, "Channel EQ done. DP Training successful\n");
break;
}
@@ -993,10 +966,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp,
intel_dp_get_adjust_train(intel_dp, crtc_state, dp_phy,
link_status);
if (!intel_dp_update_link_train(intel_dp, crtc_state, dp_phy)) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s][%s] Failed to update link training\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_err(intel_dp, dp_phy, "Failed to update link training\n");
break;
}
}
@@ -1004,10 +974,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp,
/* Try 5 times, else fail and try at lower BW */
if (tries == 5) {
intel_dp_dump_link_status(intel_dp, dp_phy, link_status);
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s][%s] Channel equalization failed 5 times\n",
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy));
+ lt_dbg(intel_dp, dp_phy, "Channel equalization failed 5 times\n");
}
return channel_eq;
@@ -1026,13 +993,12 @@ static int
intel_dp_128b132b_intra_hop(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
u8 sink_status;
int ret;
ret = drm_dp_dpcd_readb(&intel_dp->aux, DP_SINK_STATUS, &sink_status);
if (ret != 1) {
- drm_dbg_kms(&i915->drm, "Failed to read sink status\n");
+ lt_dbg(intel_dp, DP_PHY_DPRX, "Failed to read sink status\n");
return ret < 0 ? ret : -EIO;
}
@@ -1058,9 +1024,6 @@ intel_dp_128b132b_intra_hop(struct intel_dp *intel_dp,
void intel_dp_stop_link_train(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
-
intel_dp->link_trained = true;
intel_dp_disable_dpcd_training_pattern(intel_dp, DP_PHY_DPRX);
@@ -1069,9 +1032,7 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp,
if (intel_dp_is_uhbr(crtc_state) &&
wait_for(intel_dp_128b132b_intra_hop(intel_dp, crtc_state) == 0, 500)) {
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s] 128b/132b intra-hop not clearing\n",
- encoder->base.base.id, encoder->base.name);
+ lt_dbg(intel_dp, DP_PHY_DPRX, "128b/132b intra-hop not clearing\n");
}
}
@@ -1080,8 +1041,6 @@ intel_dp_link_train_phy(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
enum drm_dp_phy dp_phy)
{
- struct intel_connector *connector = intel_dp->attached_connector;
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
bool ret = false;
if (!intel_dp_link_training_clock_recovery(intel_dp, crtc_state, dp_phy))
@@ -1093,13 +1052,10 @@ intel_dp_link_train_phy(struct intel_dp *intel_dp,
ret = true;
out:
- drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
- "[CONNECTOR:%d:%s][ENCODER:%d:%s][%s] Link Training %s at link rate = %d, lane count = %d\n",
- connector->base.base.id, connector->base.name,
- encoder->base.base.id, encoder->base.name,
- drm_dp_phy_name(dp_phy),
- ret ? "passed" : "failed",
- crtc_state->port_clock, crtc_state->lane_count);
+ lt_dbg(intel_dp, dp_phy,
+ "Link Training %s at link rate = %d, lane count = %d\n",
+ ret ? "passed" : "failed",
+ crtc_state->port_clock, crtc_state->lane_count);
return ret;
}
@@ -1108,13 +1064,16 @@ static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct intel_connector *intel_connector = intel_dp->attached_connector;
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+ if (!intel_digital_port_connected(&dp_to_dig_port(intel_dp)->base)) {
+ lt_dbg(intel_dp, DP_PHY_DPRX, "Link Training failed on disconnected sink.\n");
+ return;
+ }
if (intel_dp->hobl_active) {
- drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
- "[ENCODER:%d:%s] Link Training failed with HOBL active, "
- "not enabling it from now on",
- encoder->base.base.id, encoder->base.name);
+ lt_dbg(intel_dp, DP_PHY_DPRX,
+ "Link Training failed with HOBL active, not enabling it from now on\n");
intel_dp->hobl_failed = true;
} else if (intel_dp_get_link_train_fallback_values(intel_dp,
crtc_state->port_clock,
@@ -1123,7 +1082,7 @@ static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp,
}
/* Schedule a Hotplug Uevent to userspace to start modeset */
- schedule_work(&intel_connector->modeset_retry_work);
+ queue_work(i915->unordered_wq, &intel_connector->modeset_retry_work);
}
/* Perform the link training on all LTTPRs and the DPRX on a link. */
@@ -1161,8 +1120,6 @@ static bool
intel_dp_128b132b_lane_eq(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
u8 link_status[DP_LINK_STATUS_SIZE];
int delay_us;
int try, max_tries = 20;
@@ -1177,9 +1134,7 @@ intel_dp_128b132b_lane_eq(struct intel_dp *intel_dp,
*/
if (!intel_dp_reset_link_train(intel_dp, crtc_state, DP_PHY_DPRX,
DP_TRAINING_PATTERN_1)) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Failed to start 128b/132b TPS1\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Failed to start 128b/132b TPS1\n");
return false;
}
@@ -1187,27 +1142,21 @@ intel_dp_128b132b_lane_eq(struct intel_dp *intel_dp,
/* Read the initial TX FFE settings. */
if (drm_dp_dpcd_read_link_status(&intel_dp->aux, link_status) < 0) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Failed to read TX FFE presets\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Failed to read TX FFE presets\n");
return false;
}
/* Update signal levels and training set as requested. */
intel_dp_get_adjust_train(intel_dp, crtc_state, DP_PHY_DPRX, link_status);
if (!intel_dp_update_link_train(intel_dp, crtc_state, DP_PHY_DPRX)) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Failed to set initial TX FFE settings\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Failed to set initial TX FFE settings\n");
return false;
}
/* Start transmitting 128b/132b TPS2. */
if (!intel_dp_set_link_train(intel_dp, crtc_state, DP_PHY_DPRX,
DP_TRAINING_PATTERN_2)) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Failed to start 128b/132b TPS2\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Failed to start 128b/132b TPS2\n");
return false;
}
@@ -1224,32 +1173,25 @@ intel_dp_128b132b_lane_eq(struct intel_dp *intel_dp,
delay_us = drm_dp_128b132b_read_aux_rd_interval(&intel_dp->aux);
if (drm_dp_dpcd_read_link_status(&intel_dp->aux, link_status) < 0) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Failed to read link status\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Failed to read link status\n");
return false;
}
if (drm_dp_128b132b_link_training_failed(link_status)) {
intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status);
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Downstream link training failure\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX,
+ "Downstream link training failure\n");
return false;
}
if (drm_dp_128b132b_lane_channel_eq_done(link_status, crtc_state->lane_count)) {
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s] Lane channel eq done\n",
- encoder->base.base.id, encoder->base.name);
+ lt_dbg(intel_dp, DP_PHY_DPRX, "Lane channel eq done\n");
break;
}
if (timeout) {
intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status);
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Lane channel eq timeout\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Lane channel eq timeout\n");
return false;
}
@@ -1259,18 +1201,14 @@ intel_dp_128b132b_lane_eq(struct intel_dp *intel_dp,
/* Update signal levels and training set as requested. */
intel_dp_get_adjust_train(intel_dp, crtc_state, DP_PHY_DPRX, link_status);
if (!intel_dp_update_link_train(intel_dp, crtc_state, DP_PHY_DPRX)) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Failed to update TX FFE settings\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Failed to update TX FFE settings\n");
return false;
}
}
if (try == max_tries) {
intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status);
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Max loop count reached\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Max loop count reached\n");
return false;
}
@@ -1279,32 +1217,24 @@ intel_dp_128b132b_lane_eq(struct intel_dp *intel_dp,
timeout = true; /* try one last time after deadline */
if (drm_dp_dpcd_read_link_status(&intel_dp->aux, link_status) < 0) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Failed to read link status\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Failed to read link status\n");
return false;
}
if (drm_dp_128b132b_link_training_failed(link_status)) {
intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status);
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Downstream link training failure\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Downstream link training failure\n");
return false;
}
if (drm_dp_128b132b_eq_interlane_align_done(link_status)) {
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s] Interlane align done\n",
- encoder->base.base.id, encoder->base.name);
+ lt_dbg(intel_dp, DP_PHY_DPRX, "Interlane align done\n");
break;
}
if (timeout) {
intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status);
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Interlane align timeout\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Interlane align timeout\n");
return false;
}
@@ -1322,16 +1252,12 @@ intel_dp_128b132b_lane_cds(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
int lttpr_count)
{
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
u8 link_status[DP_LINK_STATUS_SIZE];
unsigned long deadline;
if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TRAINING_PATTERN_SET,
DP_TRAINING_PATTERN_2_CDS) != 1) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Failed to start 128b/132b TPS2 CDS\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Failed to start 128b/132b TPS2 CDS\n");
return false;
}
@@ -1347,34 +1273,26 @@ intel_dp_128b132b_lane_cds(struct intel_dp *intel_dp,
usleep_range(2000, 3000);
if (drm_dp_dpcd_read_link_status(&intel_dp->aux, link_status) < 0) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Failed to read link status\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Failed to read link status\n");
return false;
}
if (drm_dp_128b132b_eq_interlane_align_done(link_status) &&
drm_dp_128b132b_cds_interlane_align_done(link_status) &&
drm_dp_128b132b_lane_symbol_locked(link_status, crtc_state->lane_count)) {
- drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s] CDS interlane align done\n",
- encoder->base.base.id, encoder->base.name);
+ lt_dbg(intel_dp, DP_PHY_DPRX, "CDS interlane align done\n");
break;
}
if (drm_dp_128b132b_link_training_failed(link_status)) {
intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status);
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] Downstream link training failure\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "Downstream link training failure\n");
return false;
}
if (timeout) {
intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status);
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] CDS timeout\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "CDS timeout\n");
return false;
}
}
@@ -1390,15 +1308,10 @@ intel_dp_128b132b_link_train(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
int lttpr_count)
{
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
- struct intel_connector *connector = intel_dp->attached_connector;
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
bool passed = false;
if (wait_for(intel_dp_128b132b_intra_hop(intel_dp, crtc_state) == 0, 500)) {
- drm_err(&i915->drm,
- "[ENCODER:%d:%s] 128b/132b intra-hop not clear\n",
- encoder->base.base.id, encoder->base.name);
+ lt_err(intel_dp, DP_PHY_DPRX, "128b/132b intra-hop not clear\n");
return false;
}
@@ -1406,12 +1319,10 @@ intel_dp_128b132b_link_train(struct intel_dp *intel_dp,
intel_dp_128b132b_lane_cds(intel_dp, crtc_state, lttpr_count))
passed = true;
- drm_dbg_kms(&i915->drm,
- "[CONNECTOR:%d:%s][ENCODER:%d:%s] 128b/132b Link Training %s at link rate = %d, lane count = %d\n",
- connector->base.base.id, connector->base.name,
- encoder->base.base.id, encoder->base.name,
- passed ? "passed" : "failed",
- crtc_state->port_clock, crtc_state->lane_count);
+ lt_dbg(intel_dp, DP_PHY_DPRX,
+ "128b/132b Link Training %s at link rate = %d, lane count = %d\n",
+ passed ? "passed" : "failed",
+ crtc_state->port_clock, crtc_state->lane_count);
return passed;
}
@@ -1430,8 +1341,6 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
- struct intel_connector *connector = intel_dp->attached_connector;
- struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
bool passed;
/*
@@ -1464,10 +1373,7 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp,
* ignore_long_hpd flag can unset from the testcase.
*/
if (!passed && i915->display.hotplug.ignore_long_hpd) {
- drm_dbg_kms(&i915->drm,
- "[CONNECTOR:%d:%s][ENCODER:%d:%s] Ignore the link failure\n",
- connector->base.base.id, connector->base.name,
- encoder->base.base.id, encoder->base.name);
+ lt_dbg(intel_dp, DP_PHY_DPRX, "Ignore the link failure\n");
return;
}
@@ -1478,8 +1384,6 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp,
void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-
/*
* VIDEO_DIP_CTL register bit 31 should be set to '0' to not
* disable SDP CRC. This is applicable for Display version 13.
@@ -1492,5 +1396,5 @@ void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp,
DP_SDP_ERROR_DETECTION_CONFIGURATION,
DP_SDP_CRC16_128B132B_EN);
- drm_dbg_kms(&i915->drm, "DP2.0 SDP CRC16 for 128b/132b enabled\n");
+ lt_dbg(intel_dp, DP_PHY_DPRX, "DP2.0 SDP CRC16 for 128b/132b enabled\n");
}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 2c49d9ab86a2..e3f176a093d2 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -298,7 +298,7 @@ static bool intel_dp_mst_has_audio(const struct drm_connector_state *conn_state)
to_intel_connector(conn_state->connector);
if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
- return connector->port->has_audio;
+ return connector->base.display_info.has_audio;
else
return intel_conn_state->force_audio == HDMI_AUDIO_ON;
}
@@ -318,6 +318,7 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
+ pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->has_pch_encoder = false;
@@ -800,9 +801,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
/* Enable hdcp if it's desired */
if (conn_state->content_protection ==
DRM_MODE_CONTENT_PROTECTION_DESIRED)
- intel_hdcp_enable(to_intel_connector(conn_state->connector),
- pipe_config,
- (u8)conn_state->hdcp_content_type);
+ intel_hdcp_enable(state, encoder, pipe_config, conn_state);
}
static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder,
@@ -837,15 +836,17 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector)
{
struct intel_connector *intel_connector = to_intel_connector(connector);
struct intel_dp *intel_dp = intel_connector->mst_port;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
int ret;
if (drm_connector_is_unregistered(connector))
return intel_connector_update_modes(connector, NULL);
- edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port);
- ret = intel_connector_update_modes(connector, edid);
- kfree(edid);
+ drm_edid = drm_dp_mst_edid_read(connector, &intel_dp->mst_mgr, intel_connector->port);
+
+ ret = intel_connector_update_modes(connector, drm_edid);
+
+ drm_edid_free(drm_edid);
return ret;
}
diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c
index 4e9c18be7e1f..999badfe2906 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll.c
@@ -8,6 +8,7 @@
#include "i915_reg.h"
#include "intel_crtc.h"
+#include "intel_cx0_phy.h"
#include "intel_de.h"
#include "intel_display.h"
#include "intel_display_types.h"
@@ -995,6 +996,32 @@ static int dg2_crtc_compute_clock(struct intel_atomic_state *state,
return 0;
}
+static int mtl_crtc_compute_clock(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ struct intel_encoder *encoder =
+ intel_get_crtc_new_encoder(state, crtc_state);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
+ int ret;
+
+ ret = intel_cx0pll_calc_state(crtc_state, encoder);
+ if (ret)
+ return ret;
+
+ /* TODO: Do the readback via intel_compute_shared_dplls() */
+ if (intel_is_c10phy(i915, phy))
+ crtc_state->port_clock = intel_c10pll_calc_port_clock(encoder, &crtc_state->cx0pll_state.c10);
+ else
+ crtc_state->port_clock = intel_c20pll_calc_port_clock(encoder, &crtc_state->cx0pll_state.c20);
+
+ crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state);
+
+ return 0;
+}
+
static bool ilk_needs_fb_cb_tune(const struct dpll *dpll, int factor)
{
return dpll->m < factor * dpll->n;
@@ -1423,6 +1450,10 @@ static int i8xx_crtc_compute_clock(struct intel_atomic_state *state,
return 0;
}
+static const struct intel_dpll_funcs mtl_dpll_funcs = {
+ .crtc_compute_clock = mtl_crtc_compute_clock,
+};
+
static const struct intel_dpll_funcs dg2_dpll_funcs = {
.crtc_compute_clock = dg2_crtc_compute_clock,
};
@@ -1517,7 +1548,9 @@ int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state,
void
intel_dpll_init_clock_hook(struct drm_i915_private *dev_priv)
{
- if (IS_DG2(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 14)
+ dev_priv->display.funcs.dpll = &mtl_dpll_funcs;
+ else if (IS_DG2(dev_priv))
dev_priv->display.funcs.dpll = &dg2_dpll_funcs;
else if (DISPLAY_VER(dev_priv) >= 9 || HAS_DDI(dev_priv))
dev_priv->display.funcs.dpll = &hsw_dpll_funcs;
@@ -1760,13 +1793,11 @@ static void chv_prepare_pll(const struct intel_crtc_state *crtc_state)
enum pipe pipe = crtc->pipe;
enum dpio_channel port = vlv_pipe_to_channel(pipe);
u32 loopfilter, tribuf_calcntr;
- u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
+ u32 bestm2, bestp1, bestp2, bestm2_frac;
u32 dpio_val;
int vco;
- bestn = crtc_state->dpll.n;
bestm2_frac = crtc_state->dpll.m2 & 0x3fffff;
- bestm1 = crtc_state->dpll.m1;
bestm2 = crtc_state->dpll.m2 >> 22;
bestp1 = crtc_state->dpll.p1;
bestp2 = crtc_state->dpll.p2;
@@ -2047,7 +2078,7 @@ static void assert_pll(struct drm_i915_private *dev_priv,
bool cur_state;
cur_state = intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE;
- I915_STATE_WARN(cur_state != state,
+ I915_STATE_WARN(dev_priv, cur_state != state,
"PLL state assertion failure (expected %s, current %s)\n",
str_on_off(state), str_on_off(cur_state));
}
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
index 22fc908b7e5d..6b2d8a1e2aa9 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
@@ -169,8 +169,8 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
return;
cur_state = intel_dpll_get_hw_state(dev_priv, pll, &hw_state);
- I915_STATE_WARN(cur_state != state,
- "%s assertion failure (expected %s, current %s)\n",
+ I915_STATE_WARN(dev_priv, cur_state != state,
+ "%s assertion failure (expected %s, current %s)\n",
pll->info->name, str_on_off(state),
str_on_off(cur_state));
}
@@ -351,13 +351,35 @@ intel_find_shared_dpll(struct intel_atomic_state *state,
return NULL;
}
+/**
+ * intel_reference_shared_dpll_crtc - Get a DPLL reference for a CRTC
+ * @crtc: CRTC on which behalf the reference is taken
+ * @pll: DPLL for which the reference is taken
+ * @shared_dpll_state: the DPLL atomic state in which the reference is tracked
+ *
+ * Take a reference for @pll tracking the use of it by @crtc.
+ */
+static void
+intel_reference_shared_dpll_crtc(const struct intel_crtc *crtc,
+ const struct intel_shared_dpll *pll,
+ struct intel_shared_dpll_state *shared_dpll_state)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+
+ drm_WARN_ON(&i915->drm, (shared_dpll_state->pipe_mask & BIT(crtc->pipe)) != 0);
+
+ shared_dpll_state->pipe_mask |= BIT(crtc->pipe);
+
+ drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] reserving %s\n",
+ crtc->base.base.id, crtc->base.name, pll->info->name);
+}
+
static void
intel_reference_shared_dpll(struct intel_atomic_state *state,
const struct intel_crtc *crtc,
const struct intel_shared_dpll *pll,
const struct intel_dpll_hw_state *pll_state)
{
- struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_shared_dpll_state *shared_dpll;
const enum intel_dpll_id id = pll->info->id;
@@ -366,11 +388,29 @@ intel_reference_shared_dpll(struct intel_atomic_state *state,
if (shared_dpll[id].pipe_mask == 0)
shared_dpll[id].hw_state = *pll_state;
- drm_WARN_ON(&i915->drm, (shared_dpll[id].pipe_mask & BIT(crtc->pipe)) != 0);
+ intel_reference_shared_dpll_crtc(crtc, pll, &shared_dpll[id]);
+}
+
+/**
+ * intel_unreference_shared_dpll_crtc - Drop a DPLL reference for a CRTC
+ * @crtc: CRTC on which behalf the reference is dropped
+ * @pll: DPLL for which the reference is dropped
+ * @shared_dpll_state: the DPLL atomic state in which the reference is tracked
+ *
+ * Drop a reference for @pll tracking the end of use of it by @crtc.
+ */
+void
+intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc,
+ const struct intel_shared_dpll *pll,
+ struct intel_shared_dpll_state *shared_dpll_state)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+
+ drm_WARN_ON(&i915->drm, (shared_dpll_state->pipe_mask & BIT(crtc->pipe)) == 0);
- shared_dpll[id].pipe_mask |= BIT(crtc->pipe);
+ shared_dpll_state->pipe_mask &= ~BIT(crtc->pipe);
- drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] reserving %s\n",
+ drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] releasing %s\n",
crtc->base.base.id, crtc->base.name, pll->info->name);
}
@@ -378,18 +418,12 @@ static void intel_unreference_shared_dpll(struct intel_atomic_state *state,
const struct intel_crtc *crtc,
const struct intel_shared_dpll *pll)
{
- struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_shared_dpll_state *shared_dpll;
const enum intel_dpll_id id = pll->info->id;
shared_dpll = intel_atomic_get_shared_dpll_state(&state->base);
- drm_WARN_ON(&i915->drm, (shared_dpll[id].pipe_mask & BIT(crtc->pipe)) == 0);
-
- shared_dpll[id].pipe_mask &= ~BIT(crtc->pipe);
-
- drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] releasing %s\n",
- crtc->base.base.id, crtc->base.name, pll->info->name);
+ intel_unreference_shared_dpll_crtc(crtc, pll, &shared_dpll[id]);
}
static void intel_put_dpll(struct intel_atomic_state *state,
@@ -464,12 +498,11 @@ static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
u32 val;
bool enabled;
- I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
-
val = intel_de_read(dev_priv, PCH_DREF_CONTROL);
enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
DREF_SUPERSPREAD_SOURCE_MASK));
- I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
+ I915_STATE_WARN(dev_priv, !enabled,
+ "PCH refclk assertion failure, should be active but is disabled\n");
}
static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
@@ -4104,7 +4137,7 @@ void intel_shared_dpll_init(struct drm_i915_private *dev_priv)
mutex_init(&dev_priv->display.dpll.lock);
- if (IS_DG2(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 14 || IS_DG2(dev_priv))
/* No shared DPLLs on DG2; port PLLs are part of the PHY */
dpll_mgr = NULL;
else if (IS_ALDERLAKE_P(dev_priv))
@@ -4314,7 +4347,7 @@ static void readout_dpll_hw_state(struct drm_i915_private *i915,
to_intel_crtc_state(crtc->base.state);
if (crtc_state->hw.active && crtc_state->shared_dpll == pll)
- pll->state.pipe_mask |= BIT(crtc->pipe);
+ intel_reference_shared_dpll_crtc(crtc, pll, &pll->state);
}
pll->active_mask = pll->state.pipe_mask;
@@ -4407,17 +4440,18 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv,
active = intel_dpll_get_hw_state(dev_priv, pll, &dpll_hw_state);
if (!(pll->info->flags & INTEL_DPLL_ALWAYS_ON)) {
- I915_STATE_WARN(!pll->on && pll->active_mask,
+ I915_STATE_WARN(dev_priv, !pll->on && pll->active_mask,
"pll in active use but not on in sw tracking\n");
- I915_STATE_WARN(pll->on && !pll->active_mask,
+ I915_STATE_WARN(dev_priv, pll->on && !pll->active_mask,
"pll is on but not used by any active pipe\n");
- I915_STATE_WARN(pll->on != active,
+ I915_STATE_WARN(dev_priv, pll->on != active,
"pll on state mismatch (expected %i, found %i)\n",
pll->on, active);
}
if (!crtc) {
- I915_STATE_WARN(pll->active_mask & ~pll->state.pipe_mask,
+ I915_STATE_WARN(dev_priv,
+ pll->active_mask & ~pll->state.pipe_mask,
"more active pll users than references: 0x%x vs 0x%x\n",
pll->active_mask, pll->state.pipe_mask);
@@ -4427,20 +4461,20 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv,
pipe_mask = BIT(crtc->pipe);
if (new_crtc_state->hw.active)
- I915_STATE_WARN(!(pll->active_mask & pipe_mask),
+ I915_STATE_WARN(dev_priv, !(pll->active_mask & pipe_mask),
"pll active mismatch (expected pipe %c in active mask 0x%x)\n",
pipe_name(crtc->pipe), pll->active_mask);
else
- I915_STATE_WARN(pll->active_mask & pipe_mask,
+ I915_STATE_WARN(dev_priv, pll->active_mask & pipe_mask,
"pll active mismatch (didn't expect pipe %c in active mask 0x%x)\n",
pipe_name(crtc->pipe), pll->active_mask);
- I915_STATE_WARN(!(pll->state.pipe_mask & pipe_mask),
+ I915_STATE_WARN(dev_priv, !(pll->state.pipe_mask & pipe_mask),
"pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n",
pipe_mask, pll->state.pipe_mask);
- I915_STATE_WARN(pll->on && memcmp(&pll->state.hw_state,
- &dpll_hw_state,
+ I915_STATE_WARN(dev_priv,
+ pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state,
sizeof(dpll_hw_state)),
"pll hw state mismatch\n");
}
@@ -4460,10 +4494,10 @@ void intel_shared_dpll_state_verify(struct intel_crtc *crtc,
u8 pipe_mask = BIT(crtc->pipe);
struct intel_shared_dpll *pll = old_crtc_state->shared_dpll;
- I915_STATE_WARN(pll->active_mask & pipe_mask,
+ I915_STATE_WARN(dev_priv, pll->active_mask & pipe_mask,
"pll active mismatch (didn't expect pipe %c in active mask (0x%x))\n",
pipe_name(crtc->pipe), pll->active_mask);
- I915_STATE_WARN(pll->state.pipe_mask & pipe_mask,
+ I915_STATE_WARN(dev_priv, pll->state.pipe_mask & pipe_mask,
"pll enabled crtcs mismatch (found %x in enabled mask (0x%x))\n",
pipe_name(crtc->pipe), pll->state.pipe_mask);
}
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
index 3854f1b4299a..ba62eb5d7c51 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
@@ -341,6 +341,9 @@ int intel_reserve_shared_dplls(struct intel_atomic_state *state,
struct intel_encoder *encoder);
void intel_release_shared_dplls(struct intel_atomic_state *state,
struct intel_crtc *crtc);
+void intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc,
+ const struct intel_shared_dpll *pll,
+ struct intel_shared_dpll_state *shared_dpll_state);
void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state,
enum icl_port_dpll_id port_dpll_id);
void intel_update_active_dpll(struct intel_atomic_state *state,
diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c
index b8027392144d..7c5fddb203ba 100644
--- a/drivers/gpu/drm/i915/display/intel_dpt.c
+++ b/drivers/gpu/drm/i915/display/intel_dpt.c
@@ -43,24 +43,24 @@ static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
static void dpt_insert_page(struct i915_address_space *vm,
dma_addr_t addr,
u64 offset,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
gen8_pte_t __iomem *base = dpt->iomem;
gen8_set_pte(base + offset / I915_GTT_PAGE_SIZE,
- vm->pte_encode(addr, level, flags));
+ vm->pte_encode(addr, pat_index, flags));
}
static void dpt_insert_entries(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
gen8_pte_t __iomem *base = dpt->iomem;
- const gen8_pte_t pte_encode = vm->pte_encode(0, level, flags);
+ const gen8_pte_t pte_encode = vm->pte_encode(0, pat_index, flags);
struct sgt_iter sgt_iter;
dma_addr_t addr;
int i;
@@ -83,7 +83,7 @@ static void dpt_clear_range(struct i915_address_space *vm,
static void dpt_bind_vma(struct i915_address_space *vm,
struct i915_vm_pt_stash *stash,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags)
{
u32 pte_flags;
@@ -98,7 +98,7 @@ static void dpt_bind_vma(struct i915_address_space *vm,
if (vma_res->bi.lmem)
pte_flags |= PTE_LM;
- vm->insert_entries(vm, vma_res, cache_level, pte_flags);
+ vm->insert_entries(vm, vma_res, pat_index, pte_flags);
vma_res->page_sizes_gtt = I915_GTT_PAGE_SIZE;
@@ -300,7 +300,7 @@ intel_dpt_create(struct intel_framebuffer *fb)
vm->vma_ops.bind_vma = dpt_bind_vma;
vm->vma_ops.unbind_vma = dpt_unbind_vma;
- vm->pte_encode = gen8_ggtt_pte_encode;
+ vm->pte_encode = vm->gt->ggtt->vm.pte_encode;
dpt->obj = dpt_obj;
dpt->obj->is_dpt = true;
diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c
index 760e63cdc0c8..0d35b6be5b6a 100644
--- a/drivers/gpu/drm/i915/display/intel_drrs.c
+++ b/drivers/gpu/drm/i915/display/intel_drrs.c
@@ -111,7 +111,9 @@ static void intel_drrs_set_state(struct intel_crtc *crtc,
static void intel_drrs_schedule_work(struct intel_crtc *crtc)
{
- mod_delayed_work(system_wq, &crtc->drrs.work, msecs_to_jiffies(1000));
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+
+ mod_delayed_work(i915->unordered_wq, &crtc->drrs.work, msecs_to_jiffies(1000));
}
static unsigned int intel_drrs_frontbuffer_bits(const struct intel_crtc_state *crtc_state)
diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c
index eb2dcd866cc8..9884678743b6 100644
--- a/drivers/gpu/drm/i915/display/intel_dvo.c
+++ b/drivers/gpu/drm/i915/display/intel_dvo.c
@@ -271,6 +271,7 @@ static int intel_dvo_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
+ pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c
index e5f637897b5e..446bbf7986b6 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -157,6 +157,32 @@ struct intel_modifier_desc {
static const struct intel_modifier_desc intel_modifiers[] = {
{
+ .modifier = I915_FORMAT_MOD_4_TILED_MTL_MC_CCS,
+ .display_ver = { 14, 14 },
+ .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_MC,
+
+ .ccs.packed_aux_planes = BIT(1),
+ .ccs.planar_aux_planes = BIT(2) | BIT(3),
+
+ FORMAT_OVERRIDE(gen12_ccs_formats),
+ }, {
+ .modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS,
+ .display_ver = { 14, 14 },
+ .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC,
+
+ .ccs.packed_aux_planes = BIT(1),
+
+ FORMAT_OVERRIDE(gen12_ccs_formats),
+ }, {
+ .modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC,
+ .display_ver = { 14, 14 },
+ .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC_CC,
+
+ .ccs.cc_planes = BIT(2),
+ .ccs.packed_aux_planes = BIT(1),
+
+ FORMAT_OVERRIDE(gen12_ccs_cc_formats),
+ }, {
.modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS,
.display_ver = { 13, 13 },
.plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_MC,
@@ -370,6 +396,14 @@ static bool plane_has_modifier(struct drm_i915_private *i915,
if (!plane_caps_contain_all(plane_caps, md->plane_caps))
return false;
+ /*
+ * Separate AuxCCS and Flat CCS modifiers to be run only on platforms
+ * where supported.
+ */
+ if (intel_fb_is_ccs_modifier(md->modifier) &&
+ HAS_FLAT_CCS(i915) != !md->ccs.packed_aux_planes)
+ return false;
+
return true;
}
@@ -489,7 +523,7 @@ static bool intel_fb_is_gen12_ccs_aux_plane(const struct drm_framebuffer *fb, in
{
const struct intel_modifier_desc *md = lookup_modifier(fb->modifier);
- return check_modifier_display_ver_range(md, 12, 13) &&
+ return check_modifier_display_ver_range(md, 12, 14) &&
ccs_aux_plane_mask(md, fb->format) & BIT(color_plane);
}
@@ -605,6 +639,9 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
if (intel_fb_is_ccs_aux_plane(fb, color_plane))
return 128;
fallthrough;
+ case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
+ case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
+ case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
@@ -791,6 +828,9 @@ unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
+ case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
+ case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
+ case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
return 16 * 1024;
case I915_FORMAT_MOD_Y_TILED_CCS:
case I915_FORMAT_MOD_Yf_TILED_CCS:
@@ -1190,7 +1230,8 @@ bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb)
{
struct drm_i915_private *i915 = to_i915(fb->base.dev);
- return IS_ALDERLAKE_P(i915) && intel_fb_uses_dpt(&fb->base);
+ return (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14) &&
+ intel_fb_uses_dpt(&fb->base);
}
static int intel_fb_pitch(const struct intel_framebuffer *fb, int color_plane, unsigned int rotation)
@@ -1326,9 +1367,10 @@ plane_view_scanout_stride(const struct intel_framebuffer *fb, int color_plane,
unsigned int tile_width,
unsigned int src_stride_tiles, unsigned int dst_stride_tiles)
{
+ struct drm_i915_private *i915 = to_i915(fb->base.dev);
unsigned int stride_tiles;
- if (IS_ALDERLAKE_P(to_i915(fb->base.dev)))
+ if (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14)
stride_tiles = src_stride_tiles;
else
stride_tiles = dst_stride_tiles;
@@ -1522,7 +1564,8 @@ static void intel_fb_view_init(struct drm_i915_private *i915, struct intel_fb_vi
memset(view, 0, sizeof(*view));
view->gtt.type = view_type;
- if (view_type == I915_GTT_VIEW_REMAPPED && IS_ALDERLAKE_P(i915))
+ if (view_type == I915_GTT_VIEW_REMAPPED &&
+ (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14))
view->gtt.remapped.plane_alignment = SZ_2M / PAGE_SIZE;
}
@@ -1558,7 +1601,7 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *
for (i = 0; i < num_planes; i++) {
struct fb_plane_view_dims view_dims;
unsigned int width, height;
- unsigned int cpp, size;
+ unsigned int size;
u32 offset;
int x, y;
int ret;
@@ -1575,7 +1618,6 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *
return -EINVAL;
}
- cpp = fb->base.format->cpp[i];
intel_fb_plane_dims(fb, i, &width, &height);
ret = convert_plane_offset_to_xy(fb, i, width, &x, &y);
diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c b/drivers/gpu/drm/i915/display/intel_fb_pin.c
index 1aca7552a85d..fffd568070d4 100644
--- a/drivers/gpu/drm/i915/display/intel_fb_pin.c
+++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c
@@ -243,7 +243,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state)
struct i915_vma *vma;
bool phys_cursor =
plane->id == PLANE_CURSOR &&
- INTEL_INFO(dev_priv)->display.cursor_needs_physical;
+ DISPLAY_INFO(dev_priv)->cursor_needs_physical;
if (!intel_fb_uses_dpt(fb)) {
vma = intel_pin_and_fence_fb_obj(fb, phys_cursor,
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
index b507ff944864..7f8b2d7713c7 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -44,6 +44,7 @@
#include <drm/drm_fourcc.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "i915_utils.h"
#include "i915_vgpu.h"
#include "intel_cdclk.h"
@@ -55,7 +56,7 @@
#define for_each_fbc_id(__dev_priv, __fbc_id) \
for ((__fbc_id) = INTEL_FBC_A; (__fbc_id) < I915_MAX_FBCS; (__fbc_id)++) \
- for_each_if(RUNTIME_INFO(__dev_priv)->fbc_mask & BIT(__fbc_id))
+ for_each_if(DISPLAY_RUNTIME_INFO(__dev_priv)->fbc_mask & BIT(__fbc_id))
#define for_each_intel_fbc(__dev_priv, __fbc, __fbc_id) \
for_each_fbc_id((__dev_priv), (__fbc_id)) \
@@ -1253,7 +1254,7 @@ static bool __intel_fbc_pre_update(struct intel_atomic_state *state,
bool intel_fbc_pre_update(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- const struct intel_plane_state *plane_state;
+ const struct intel_plane_state __maybe_unused *plane_state;
bool need_vblank_wait = false;
struct intel_plane *plane;
int i;
@@ -1308,7 +1309,7 @@ static void __intel_fbc_post_update(struct intel_fbc *fbc)
void intel_fbc_post_update(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- const struct intel_plane_state *plane_state;
+ const struct intel_plane_state __maybe_unused *plane_state;
struct intel_plane *plane;
int i;
@@ -1407,7 +1408,7 @@ void intel_fbc_flush(struct drm_i915_private *i915,
int intel_fbc_atomic_check(struct intel_atomic_state *state)
{
- struct intel_plane_state *plane_state;
+ struct intel_plane_state __maybe_unused *plane_state;
struct intel_plane *plane;
int i;
@@ -1599,7 +1600,7 @@ static void __intel_fbc_handle_fifo_underrun_irq(struct intel_fbc *fbc)
if (READ_ONCE(fbc->underrun_detected))
return;
- schedule_work(&fbc->underrun_work);
+ queue_work(fbc->i915->unordered_wq, &fbc->underrun_work);
}
/**
@@ -1707,10 +1708,10 @@ void intel_fbc_init(struct drm_i915_private *i915)
enum intel_fbc_id fbc_id;
if (!drm_mm_initialized(&i915->mm.stolen))
- RUNTIME_INFO(i915)->fbc_mask = 0;
+ DISPLAY_RUNTIME_INFO(i915)->fbc_mask = 0;
if (need_fbc_vtd_wa(i915))
- RUNTIME_INFO(i915)->fbc_mask = 0;
+ DISPLAY_RUNTIME_INFO(i915)->fbc_mask = 0;
i915->params.enable_fbc = intel_sanitize_fbc_option(i915);
drm_dbg_kms(&i915->drm, "Sanitized enable_fbc value: %d\n",
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c
index 673bcdfb7ff6..1cc0ddc6a310 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
@@ -28,6 +28,7 @@
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/errno.h>
+#include <linux/fb.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -40,8 +41,10 @@
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_framebuffer_helper.h>
#include "gem/i915_gem_lmem.h"
+#include "gem/i915_gem_mman.h"
#include "i915_drv.h"
#include "intel_display_types.h"
@@ -67,6 +70,11 @@ struct intel_fbdev {
struct mutex hpd_lock;
};
+static struct intel_fbdev *to_intel_fbdev(struct drm_fb_helper *fb_helper)
+{
+ return container_of(fb_helper, struct intel_fbdev, helper);
+}
+
static struct intel_frontbuffer *to_frontbuffer(struct intel_fbdev *ifbdev)
{
return ifbdev->fb->frontbuffer;
@@ -77,11 +85,13 @@ static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev)
intel_frontbuffer_invalidate(to_frontbuffer(ifbdev), ORIGIN_CPU);
}
+FB_GEN_DEFAULT_DEFERRED_IO_OPS(intel_fbdev,
+ drm_fb_helper_damage_range,
+ drm_fb_helper_damage_area)
+
static int intel_fbdev_set_par(struct fb_info *info)
{
- struct drm_fb_helper *fb_helper = info->par;
- struct intel_fbdev *ifbdev =
- container_of(fb_helper, struct intel_fbdev, helper);
+ struct intel_fbdev *ifbdev = to_intel_fbdev(info->par);
int ret;
ret = drm_fb_helper_set_par(info);
@@ -93,9 +103,7 @@ static int intel_fbdev_set_par(struct fb_info *info)
static int intel_fbdev_blank(int blank, struct fb_info *info)
{
- struct drm_fb_helper *fb_helper = info->par;
- struct intel_fbdev *ifbdev =
- container_of(fb_helper, struct intel_fbdev, helper);
+ struct intel_fbdev *ifbdev = to_intel_fbdev(info->par);
int ret;
ret = drm_fb_helper_blank(blank, info);
@@ -108,9 +116,7 @@ static int intel_fbdev_blank(int blank, struct fb_info *info)
static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct drm_fb_helper *fb_helper = info->par;
- struct intel_fbdev *ifbdev =
- container_of(fb_helper, struct intel_fbdev, helper);
+ struct intel_fbdev *ifbdev = to_intel_fbdev(info->par);
int ret;
ret = drm_fb_helper_pan_display(var, info);
@@ -120,24 +126,35 @@ static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
return ret;
}
+static int intel_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ struct intel_fbdev *fbdev = to_intel_fbdev(info->par);
+ struct drm_gem_object *bo = drm_gem_fb_get_obj(&fbdev->fb->base, 0);
+ struct drm_i915_gem_object *obj = to_intel_bo(bo);
+
+ return i915_gem_fb_mmap(obj, vma);
+}
+
+__diag_push();
+__diag_ignore_all("-Woverride-init", "Allow overriding the default ops");
+
static const struct fb_ops intelfb_ops = {
.owner = THIS_MODULE,
+ __FB_DEFAULT_DEFERRED_OPS_RDWR(intel_fbdev),
DRM_FB_HELPER_DEFAULT_OPS,
.fb_set_par = intel_fbdev_set_par,
- .fb_read = drm_fb_helper_cfb_read,
- .fb_write = drm_fb_helper_cfb_write,
- .fb_fillrect = drm_fb_helper_cfb_fillrect,
- .fb_copyarea = drm_fb_helper_cfb_copyarea,
- .fb_imageblit = drm_fb_helper_cfb_imageblit,
- .fb_pan_display = intel_fbdev_pan_display,
.fb_blank = intel_fbdev_blank,
+ .fb_pan_display = intel_fbdev_pan_display,
+ __FB_DEFAULT_DEFERRED_OPS_DRAW(intel_fbdev),
+ .fb_mmap = intel_fbdev_mmap,
};
+__diag_pop();
+
static int intelfb_alloc(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
- struct intel_fbdev *ifbdev =
- container_of(helper, struct intel_fbdev, helper);
+ struct intel_fbdev *ifbdev = to_intel_fbdev(helper);
struct drm_framebuffer *fb;
struct drm_device *dev = helper->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
@@ -163,7 +180,8 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
obj = ERR_PTR(-ENODEV);
if (HAS_LMEM(dev_priv)) {
obj = i915_gem_object_create_lmem(dev_priv, size,
- I915_BO_ALLOC_CONTIGUOUS);
+ I915_BO_ALLOC_CONTIGUOUS |
+ I915_BO_ALLOC_USER);
} else {
/*
* If the FB is too big, just don't use it since fbdev is not very
@@ -193,8 +211,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
static int intelfb_create(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
- struct intel_fbdev *ifbdev =
- container_of(helper, struct intel_fbdev, helper);
+ struct intel_fbdev *ifbdev = to_intel_fbdev(helper);
struct intel_framebuffer *intel_fb = ifbdev->fb;
struct drm_device *dev = helper->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
@@ -679,7 +696,8 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
/* Don't block our own workqueue as this can
* be run in parallel with other i915.ko tasks.
*/
- schedule_work(&dev_priv->display.fbdev.suspend_work);
+ queue_work(dev_priv->unordered_wq,
+ &dev_priv->display.fbdev.suspend_work);
return;
}
}
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
index 55283677c45a..e12b46a84fa1 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -36,7 +36,7 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,
} else {
cur_state = intel_de_read(dev_priv, FDI_TX_CTL(pipe)) & FDI_TX_ENABLE;
}
- I915_STATE_WARN(cur_state != state,
+ I915_STATE_WARN(dev_priv, cur_state != state,
"FDI TX state assertion failure (expected %s, current %s)\n",
str_on_off(state), str_on_off(cur_state));
}
@@ -57,7 +57,7 @@ static void assert_fdi_rx(struct drm_i915_private *dev_priv,
bool cur_state;
cur_state = intel_de_read(dev_priv, FDI_RX_CTL(pipe)) & FDI_RX_ENABLE;
- I915_STATE_WARN(cur_state != state,
+ I915_STATE_WARN(dev_priv, cur_state != state,
"FDI RX state assertion failure (expected %s, current %s)\n",
str_on_off(state), str_on_off(cur_state));
}
@@ -86,7 +86,8 @@ void assert_fdi_tx_pll_enabled(struct drm_i915_private *i915,
return;
cur_state = intel_de_read(i915, FDI_TX_CTL(pipe)) & FDI_TX_PLL_ENABLE;
- I915_STATE_WARN(!cur_state, "FDI TX PLL assertion failure, should be active but is disabled\n");
+ I915_STATE_WARN(i915, !cur_state,
+ "FDI TX PLL assertion failure, should be active but is disabled\n");
}
static void assert_fdi_rx_pll(struct drm_i915_private *i915,
@@ -95,7 +96,7 @@ static void assert_fdi_rx_pll(struct drm_i915_private *i915,
bool cur_state;
cur_state = intel_de_read(i915, FDI_RX_CTL(pipe)) & FDI_RX_PLL_ENABLE;
- I915_STATE_WARN(cur_state != state,
+ I915_STATE_WARN(i915, cur_state != state,
"FDI RX PLL assertion failure (expected %s, current %s)\n",
str_on_off(state), str_on_off(cur_state));
}
diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
index b708a62e509a..09a7fa6c0c37 100644
--- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
+++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
@@ -26,7 +26,9 @@
*/
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_de.h"
+#include "intel_display_irq.h"
#include "intel_display_trace.h"
#include "intel_display_types.h"
#include "intel_fbc.h"
diff --git a/drivers/gpu/drm/i915/display/intel_global_state.c b/drivers/gpu/drm/i915/display/intel_global_state.c
index 02b593b1e2ea..e8e8be54143b 100644
--- a/drivers/gpu/drm/i915/display/intel_global_state.c
+++ b/drivers/gpu/drm/i915/display/intel_global_state.c
@@ -255,3 +255,15 @@ int intel_atomic_serialize_global_state(struct intel_global_state *obj_state)
return 0;
}
+
+bool
+intel_atomic_global_state_is_serialized(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_crtc *crtc;
+
+ for_each_intel_crtc(&i915->drm, crtc)
+ if (!intel_atomic_get_new_crtc_state(state, crtc))
+ return false;
+ return true;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_global_state.h b/drivers/gpu/drm/i915/display/intel_global_state.h
index f01ee0bb3e5a..5477de8f0b30 100644
--- a/drivers/gpu/drm/i915/display/intel_global_state.h
+++ b/drivers/gpu/drm/i915/display/intel_global_state.h
@@ -87,4 +87,6 @@ void intel_atomic_clear_global_state(struct intel_atomic_state *state);
int intel_atomic_lock_global_state(struct intel_global_state *obj_state);
int intel_atomic_serialize_global_state(struct intel_global_state *obj_state);
+bool intel_atomic_global_state_is_serialized(struct intel_atomic_state *state);
+
#endif
diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
index 3ddfc8080ee8..e95ddb580ef6 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
+++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
@@ -991,3 +991,8 @@ void intel_gmbus_teardown(struct drm_i915_private *i915)
i915->display.gmbus.bus[pin] = NULL;
}
}
+
+void intel_gmbus_irq_handler(struct drm_i915_private *i915)
+{
+ wake_up_all(&i915->display.gmbus.wait_queue);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.h b/drivers/gpu/drm/i915/display/intel_gmbus.h
index 20f704bd4e70..8111eb23e2af 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus.h
+++ b/drivers/gpu/drm/i915/display/intel_gmbus.h
@@ -46,4 +46,6 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);
bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter);
void intel_gmbus_reset(struct drm_i915_private *dev_priv);
+void intel_gmbus_irq_handler(struct drm_i915_private *i915);
+
#endif /* __INTEL_GMBUS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c
index b183efab04a1..5ed450111f77 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -30,7 +30,8 @@
#define KEY_LOAD_TRIES 5
#define HDCP2_LC_RETRY_CNT 3
-static int intel_conn_to_vcpi(struct intel_connector *connector)
+static int intel_conn_to_vcpi(struct drm_atomic_state *state,
+ struct intel_connector *connector)
{
struct drm_dp_mst_topology_mgr *mgr;
struct drm_dp_mst_atomic_payload *payload;
@@ -42,7 +43,7 @@ static int intel_conn_to_vcpi(struct intel_connector *connector)
return 0;
mgr = connector->port->mgr;
- drm_modeset_lock(&mgr->base.lock, NULL);
+ drm_modeset_lock(&mgr->base.lock, state->acquire_ctx);
mst_state = to_drm_dp_mst_topology_state(mgr->base.state);
payload = drm_atomic_get_mst_payload_state(mst_state, connector->port);
if (drm_WARN_ON(mgr->dev, !payload))
@@ -54,7 +55,6 @@ static int intel_conn_to_vcpi(struct intel_connector *connector)
goto out;
}
out:
- drm_modeset_unlock(&mgr->base.lock);
return vcpi;
}
@@ -68,48 +68,18 @@ out:
* DP MST topology. Though it is not compulsory, security fw should change its
* policy to mark different content_types for different streams.
*/
-static int
+static void
intel_hdcp_required_content_stream(struct intel_digital_port *dig_port)
{
- struct drm_connector_list_iter conn_iter;
- struct intel_digital_port *conn_dig_port;
- struct intel_connector *connector;
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
bool enforce_type0 = false;
int k;
- data->k = 0;
-
if (dig_port->hdcp_auth_status)
- return 0;
-
- drm_connector_list_iter_begin(&i915->drm, &conn_iter);
- for_each_intel_connector_iter(connector, &conn_iter) {
- if (connector->base.status == connector_status_disconnected)
- continue;
-
- if (!intel_encoder_is_mst(intel_attached_encoder(connector)))
- continue;
-
- conn_dig_port = intel_attached_dig_port(connector);
- if (conn_dig_port != dig_port)
- continue;
-
- if (!enforce_type0 && !dig_port->hdcp_mst_type1_capable)
- enforce_type0 = true;
-
- data->streams[data->k].stream_id = intel_conn_to_vcpi(connector);
- data->k++;
-
- /* if there is only one active stream */
- if (dig_port->dp.active_mst_links <= 1)
- break;
- }
- drm_connector_list_iter_end(&conn_iter);
+ return;
- if (drm_WARN_ON(&i915->drm, data->k > INTEL_NUM_PIPES(i915) || data->k == 0))
- return -EINVAL;
+ if (!dig_port->hdcp_mst_type1_capable)
+ enforce_type0 = true;
/*
* Apply common protection level across all streams in DP MST Topology.
@@ -118,27 +88,19 @@ intel_hdcp_required_content_stream(struct intel_digital_port *dig_port)
for (k = 0; k < data->k; k++)
data->streams[k].stream_type =
enforce_type0 ? DRM_MODE_HDCP_CONTENT_TYPE0 : DRM_MODE_HDCP_CONTENT_TYPE1;
-
- return 0;
}
-static int intel_hdcp_prepare_streams(struct intel_connector *connector)
+static void intel_hdcp_prepare_streams(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
struct intel_hdcp *hdcp = &connector->hdcp;
- int ret;
if (!intel_encoder_is_mst(intel_attached_encoder(connector))) {
- data->k = 1;
data->streams[0].stream_type = hdcp->content_type;
} else {
- ret = intel_hdcp_required_content_stream(dig_port);
- if (ret)
- return ret;
+ intel_hdcp_required_content_stream(dig_port);
}
-
- return 0;
}
static
@@ -202,7 +164,7 @@ bool intel_hdcp_capable(struct intel_connector *connector)
bool intel_hdcp2_capable(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
bool capable = false;
@@ -211,8 +173,8 @@ bool intel_hdcp2_capable(struct intel_connector *connector)
return false;
/* If MTL+ make sure gsc is loaded and proxy is setup */
- if (intel_hdcp_gsc_cs_required(dev_priv)) {
- struct intel_gt *gt = dev_priv->media_gt;
+ if (intel_hdcp_gsc_cs_required(i915)) {
+ struct intel_gt *gt = i915->media_gt;
struct intel_gsc_uc *gsc = gt ? &gt->uc.gsc : NULL;
if (!gsc || !intel_uc_fw_is_running(&gsc->fw))
@@ -220,12 +182,12 @@ bool intel_hdcp2_capable(struct intel_connector *connector)
}
/* MEI/GSC interface is solid depending on which is used */
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- if (!dev_priv->display.hdcp.comp_added || !dev_priv->display.hdcp.master) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ if (!i915->display.hdcp.comp_added || !i915->display.hdcp.arbiter) {
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return false;
}
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
/* Sink's capability for HDCP2.2 */
hdcp->shim->hdcp_2_2_capable(dig_port, &capable);
@@ -233,20 +195,20 @@ bool intel_hdcp2_capable(struct intel_connector *connector)
return capable;
}
-static bool intel_hdcp_in_use(struct drm_i915_private *dev_priv,
+static bool intel_hdcp_in_use(struct drm_i915_private *i915,
enum transcoder cpu_transcoder, enum port port)
{
- return intel_de_read(dev_priv,
- HDCP_STATUS(dev_priv, cpu_transcoder, port)) &
- HDCP_STATUS_ENC;
+ return intel_de_read(i915,
+ HDCP_STATUS(i915, cpu_transcoder, port)) &
+ HDCP_STATUS_ENC;
}
-static bool intel_hdcp2_in_use(struct drm_i915_private *dev_priv,
+static bool intel_hdcp2_in_use(struct drm_i915_private *i915,
enum transcoder cpu_transcoder, enum port port)
{
- return intel_de_read(dev_priv,
- HDCP2_STATUS(dev_priv, cpu_transcoder, port)) &
- LINK_ENCRYPTION_STATUS;
+ return intel_de_read(i915,
+ HDCP2_STATUS(i915, cpu_transcoder, port)) &
+ LINK_ENCRYPTION_STATUS;
}
static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *dig_port,
@@ -270,7 +232,7 @@ static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *dig_port,
return 0;
}
-static bool hdcp_key_loadable(struct drm_i915_private *dev_priv)
+static bool hdcp_key_loadable(struct drm_i915_private *i915)
{
enum i915_power_well_id id;
intel_wakeref_t wakeref;
@@ -280,14 +242,14 @@ static bool hdcp_key_loadable(struct drm_i915_private *dev_priv)
* On HSW and BDW, Display HW loads the Key as soon as Display resumes.
* On all BXT+, SW can load the keys only when the PW#1 is turned on.
*/
- if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+ if (IS_HASWELL(i915) || IS_BROADWELL(i915))
id = HSW_DISP_PW_GLOBAL;
else
id = SKL_DISP_PW_1;
/* PG1 (power well #1) needs to be enabled */
- with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)
- enabled = intel_display_power_well_is_enabled(dev_priv, id);
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref)
+ enabled = intel_display_power_well_is_enabled(i915, id);
/*
* Another req for hdcp key loadability is enabled state of pll for
@@ -298,19 +260,19 @@ static bool hdcp_key_loadable(struct drm_i915_private *dev_priv)
return enabled;
}
-static void intel_hdcp_clear_keys(struct drm_i915_private *dev_priv)
+static void intel_hdcp_clear_keys(struct drm_i915_private *i915)
{
- intel_de_write(dev_priv, HDCP_KEY_CONF, HDCP_CLEAR_KEYS_TRIGGER);
- intel_de_write(dev_priv, HDCP_KEY_STATUS,
+ intel_de_write(i915, HDCP_KEY_CONF, HDCP_CLEAR_KEYS_TRIGGER);
+ intel_de_write(i915, HDCP_KEY_STATUS,
HDCP_KEY_LOAD_DONE | HDCP_KEY_LOAD_STATUS | HDCP_FUSE_IN_PROGRESS | HDCP_FUSE_ERROR | HDCP_FUSE_DONE);
}
-static int intel_hdcp_load_keys(struct drm_i915_private *dev_priv)
+static int intel_hdcp_load_keys(struct drm_i915_private *i915)
{
int ret;
u32 val;
- val = intel_de_read(dev_priv, HDCP_KEY_STATUS);
+ val = intel_de_read(i915, HDCP_KEY_STATUS);
if ((val & HDCP_KEY_LOAD_DONE) && (val & HDCP_KEY_LOAD_STATUS))
return 0;
@@ -318,8 +280,8 @@ static int intel_hdcp_load_keys(struct drm_i915_private *dev_priv)
* On HSW and BDW HW loads the HDCP1.4 Key when Display comes
* out of reset. So if Key is not already loaded, its an error state.
*/
- if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
- if (!(intel_de_read(dev_priv, HDCP_KEY_STATUS) & HDCP_KEY_LOAD_DONE))
+ if (IS_HASWELL(i915) || IS_BROADWELL(i915))
+ if (!(intel_de_read(i915, HDCP_KEY_STATUS) & HDCP_KEY_LOAD_DONE))
return -ENXIO;
/*
@@ -330,20 +292,20 @@ static int intel_hdcp_load_keys(struct drm_i915_private *dev_priv)
* process from other platforms. These platforms use the GT Driver
* Mailbox interface.
*/
- if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) {
- ret = snb_pcode_write(&dev_priv->uncore, SKL_PCODE_LOAD_HDCP_KEYS, 1);
+ if (DISPLAY_VER(i915) == 9 && !IS_BROXTON(i915)) {
+ ret = snb_pcode_write(&i915->uncore, SKL_PCODE_LOAD_HDCP_KEYS, 1);
if (ret) {
- drm_err(&dev_priv->drm,
+ drm_err(&i915->drm,
"Failed to initiate HDCP key load (%d)\n",
ret);
return ret;
}
} else {
- intel_de_write(dev_priv, HDCP_KEY_CONF, HDCP_KEY_LOAD_TRIGGER);
+ intel_de_write(i915, HDCP_KEY_CONF, HDCP_KEY_LOAD_TRIGGER);
}
/* Wait for the keys to load (500us) */
- ret = __intel_wait_for_register(&dev_priv->uncore, HDCP_KEY_STATUS,
+ ret = __intel_wait_for_register(&i915->uncore, HDCP_KEY_STATUS,
HDCP_KEY_LOAD_DONE, HDCP_KEY_LOAD_DONE,
10, 1, &val);
if (ret)
@@ -352,27 +314,27 @@ static int intel_hdcp_load_keys(struct drm_i915_private *dev_priv)
return -ENXIO;
/* Send Aksv over to PCH display for use in authentication */
- intel_de_write(dev_priv, HDCP_KEY_CONF, HDCP_AKSV_SEND_TRIGGER);
+ intel_de_write(i915, HDCP_KEY_CONF, HDCP_AKSV_SEND_TRIGGER);
return 0;
}
/* Returns updated SHA-1 index */
-static int intel_write_sha_text(struct drm_i915_private *dev_priv, u32 sha_text)
+static int intel_write_sha_text(struct drm_i915_private *i915, u32 sha_text)
{
- intel_de_write(dev_priv, HDCP_SHA_TEXT, sha_text);
- if (intel_de_wait_for_set(dev_priv, HDCP_REP_CTL, HDCP_SHA1_READY, 1)) {
- drm_err(&dev_priv->drm, "Timed out waiting for SHA1 ready\n");
+ intel_de_write(i915, HDCP_SHA_TEXT, sha_text);
+ if (intel_de_wait_for_set(i915, HDCP_REP_CTL, HDCP_SHA1_READY, 1)) {
+ drm_err(&i915->drm, "Timed out waiting for SHA1 ready\n");
return -ETIMEDOUT;
}
return 0;
}
static
-u32 intel_hdcp_get_repeater_ctl(struct drm_i915_private *dev_priv,
+u32 intel_hdcp_get_repeater_ctl(struct drm_i915_private *i915,
enum transcoder cpu_transcoder, enum port port)
{
- if (DISPLAY_VER(dev_priv) >= 12) {
+ if (DISPLAY_VER(i915) >= 12) {
switch (cpu_transcoder) {
case TRANSCODER_A:
return HDCP_TRANSA_REP_PRESENT |
@@ -387,7 +349,7 @@ u32 intel_hdcp_get_repeater_ctl(struct drm_i915_private *dev_priv,
return HDCP_TRANSD_REP_PRESENT |
HDCP_TRANSD_SHA1_M0;
default:
- drm_err(&dev_priv->drm, "Unknown transcoder %d\n",
+ drm_err(&i915->drm, "Unknown transcoder %d\n",
cpu_transcoder);
return -EINVAL;
}
@@ -405,7 +367,7 @@ u32 intel_hdcp_get_repeater_ctl(struct drm_i915_private *dev_priv,
case PORT_E:
return HDCP_DDIE_REP_PRESENT | HDCP_DDIE_SHA1_M0;
default:
- drm_err(&dev_priv->drm, "Unknown port %d\n", port);
+ drm_err(&i915->drm, "Unknown port %d\n", port);
return -EINVAL;
}
}
@@ -416,7 +378,7 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
u8 *ksv_fifo, u8 num_downstream, u8 *bstatus)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
enum transcoder cpu_transcoder = connector->hdcp.cpu_transcoder;
enum port port = dig_port->base.port;
u32 vprime, sha_text, sha_leftovers, rep_ctl;
@@ -427,7 +389,7 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
ret = shim->read_v_prime_part(dig_port, i, &vprime);
if (ret)
return ret;
- intel_de_write(dev_priv, HDCP_SHA_V_PRIME(i), vprime);
+ intel_de_write(i915, HDCP_SHA_V_PRIME(i), vprime);
}
/*
@@ -443,8 +405,8 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
sha_idx = 0;
sha_text = 0;
sha_leftovers = 0;
- rep_ctl = intel_hdcp_get_repeater_ctl(dev_priv, cpu_transcoder, port);
- intel_de_write(dev_priv, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_32);
+ rep_ctl = intel_hdcp_get_repeater_ctl(i915, cpu_transcoder, port);
+ intel_de_write(i915, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_32);
for (i = 0; i < num_downstream; i++) {
unsigned int sha_empty;
u8 *ksv = &ksv_fifo[i * DRM_HDCP_KSV_LEN];
@@ -456,14 +418,14 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
sha_text |= ksv[j] << off;
}
- ret = intel_write_sha_text(dev_priv, sha_text);
+ ret = intel_write_sha_text(i915, sha_text);
if (ret < 0)
return ret;
/* Programming guide writes this every 64 bytes */
sha_idx += sizeof(sha_text);
if (!(sha_idx % 64))
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_32);
/* Store the leftover bytes from the ksv in sha_text */
@@ -480,7 +442,7 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
if (sizeof(sha_text) > sha_leftovers)
continue;
- ret = intel_write_sha_text(dev_priv, sha_text);
+ ret = intel_write_sha_text(i915, sha_text);
if (ret < 0)
return ret;
sha_leftovers = 0;
@@ -496,73 +458,73 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
*/
if (sha_leftovers == 0) {
/* Write 16 bits of text, 16 bits of M0 */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_16);
- ret = intel_write_sha_text(dev_priv,
+ ret = intel_write_sha_text(i915,
bstatus[0] << 8 | bstatus[1]);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
/* Write 32 bits of M0 */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_0);
- ret = intel_write_sha_text(dev_priv, 0);
+ ret = intel_write_sha_text(i915, 0);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
/* Write 16 bits of M0 */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_16);
- ret = intel_write_sha_text(dev_priv, 0);
+ ret = intel_write_sha_text(i915, 0);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
} else if (sha_leftovers == 1) {
/* Write 24 bits of text, 8 bits of M0 */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_24);
sha_text |= bstatus[0] << 16 | bstatus[1] << 8;
/* Only 24-bits of data, must be in the LSB */
sha_text = (sha_text & 0xffffff00) >> 8;
- ret = intel_write_sha_text(dev_priv, sha_text);
+ ret = intel_write_sha_text(i915, sha_text);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
/* Write 32 bits of M0 */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_0);
- ret = intel_write_sha_text(dev_priv, 0);
+ ret = intel_write_sha_text(i915, 0);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
/* Write 24 bits of M0 */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_8);
- ret = intel_write_sha_text(dev_priv, 0);
+ ret = intel_write_sha_text(i915, 0);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
} else if (sha_leftovers == 2) {
/* Write 32 bits of text */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_32);
sha_text |= bstatus[0] << 8 | bstatus[1];
- ret = intel_write_sha_text(dev_priv, sha_text);
+ ret = intel_write_sha_text(i915, sha_text);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
/* Write 64 bits of M0 */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_0);
for (i = 0; i < 2; i++) {
- ret = intel_write_sha_text(dev_priv, 0);
+ ret = intel_write_sha_text(i915, 0);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
@@ -572,56 +534,56 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
* Terminate the SHA-1 stream by hand. For the other leftover
* cases this is appended by the hardware.
*/
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_32);
sha_text = DRM_HDCP_SHA1_TERMINATOR << 24;
- ret = intel_write_sha_text(dev_priv, sha_text);
+ ret = intel_write_sha_text(i915, sha_text);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
} else if (sha_leftovers == 3) {
/* Write 32 bits of text (filled from LSB) */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_32);
sha_text |= bstatus[0];
- ret = intel_write_sha_text(dev_priv, sha_text);
+ ret = intel_write_sha_text(i915, sha_text);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
/* Write 8 bits of text (filled from LSB), 24 bits of M0 */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_8);
- ret = intel_write_sha_text(dev_priv, bstatus[1]);
+ ret = intel_write_sha_text(i915, bstatus[1]);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
/* Write 32 bits of M0 */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_0);
- ret = intel_write_sha_text(dev_priv, 0);
+ ret = intel_write_sha_text(i915, 0);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
/* Write 8 bits of M0 */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_TEXT_24);
- ret = intel_write_sha_text(dev_priv, 0);
+ ret = intel_write_sha_text(i915, 0);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
} else {
- drm_dbg_kms(&dev_priv->drm, "Invalid number of leftovers %d\n",
+ drm_dbg_kms(&i915->drm, "Invalid number of leftovers %d\n",
sha_leftovers);
return -EINVAL;
}
- intel_de_write(dev_priv, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_32);
+ intel_de_write(i915, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_32);
/* Fill up to 64-4 bytes with zeros (leave the last write for length) */
while ((sha_idx % 64) < (64 - sizeof(sha_text))) {
- ret = intel_write_sha_text(dev_priv, 0);
+ ret = intel_write_sha_text(i915, 0);
if (ret < 0)
return ret;
sha_idx += sizeof(sha_text);
@@ -633,20 +595,20 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
* - 10 bytes for BINFO/BSTATUS(2), M0(8)
*/
sha_text = (num_downstream * 5 + 10) * 8;
- ret = intel_write_sha_text(dev_priv, sha_text);
+ ret = intel_write_sha_text(i915, sha_text);
if (ret < 0)
return ret;
/* Tell the HW we're done with the hash and wait for it to ACK */
- intel_de_write(dev_priv, HDCP_REP_CTL,
+ intel_de_write(i915, HDCP_REP_CTL,
rep_ctl | HDCP_SHA1_COMPLETE_HASH);
- if (intel_de_wait_for_set(dev_priv, HDCP_REP_CTL,
+ if (intel_de_wait_for_set(i915, HDCP_REP_CTL,
HDCP_SHA1_COMPLETE, 1)) {
- drm_err(&dev_priv->drm, "Timed out waiting for SHA1 complete\n");
+ drm_err(&i915->drm, "Timed out waiting for SHA1 complete\n");
return -ETIMEDOUT;
}
- if (!(intel_de_read(dev_priv, HDCP_REP_CTL) & HDCP_SHA1_V_MATCH)) {
- drm_dbg_kms(&dev_priv->drm, "SHA-1 mismatch, HDCP failed\n");
+ if (!(intel_de_read(i915, HDCP_REP_CTL) & HDCP_SHA1_V_MATCH)) {
+ drm_dbg_kms(&i915->drm, "SHA-1 mismatch, HDCP failed\n");
return -ENXIO;
}
@@ -658,14 +620,14 @@ static
int intel_hdcp_auth_downstream(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
const struct intel_hdcp_shim *shim = connector->hdcp.shim;
u8 bstatus[2], num_downstream, *ksv_fifo;
int ret, i, tries = 3;
ret = intel_hdcp_poll_ksv_fifo(dig_port, shim);
if (ret) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"KSV list failed to become ready (%d)\n", ret);
return ret;
}
@@ -676,7 +638,7 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
if (DRM_HDCP_MAX_DEVICE_EXCEEDED(bstatus[0]) ||
DRM_HDCP_MAX_CASCADE_EXCEEDED(bstatus[1])) {
- drm_dbg_kms(&dev_priv->drm, "Max Topology Limit Exceeded\n");
+ drm_dbg_kms(&i915->drm, "Max Topology Limit Exceeded\n");
return -EPERM;
}
@@ -689,14 +651,14 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
*/
num_downstream = DRM_HDCP_NUM_DOWNSTREAM(bstatus[0]);
if (num_downstream == 0) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"Repeater with zero downstream devices\n");
return -EINVAL;
}
ksv_fifo = kcalloc(DRM_HDCP_KSV_LEN, num_downstream, GFP_KERNEL);
if (!ksv_fifo) {
- drm_dbg_kms(&dev_priv->drm, "Out of mem: ksv_fifo\n");
+ drm_dbg_kms(&i915->drm, "Out of mem: ksv_fifo\n");
return -ENOMEM;
}
@@ -704,9 +666,9 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
if (ret)
goto err;
- if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, ksv_fifo,
+ if (drm_hdcp_check_ksvs_revoked(&i915->drm, ksv_fifo,
num_downstream) > 0) {
- drm_err(&dev_priv->drm, "Revoked Ksv(s) in ksv_fifo\n");
+ drm_err(&i915->drm, "Revoked Ksv(s) in ksv_fifo\n");
ret = -EPERM;
goto err;
}
@@ -724,12 +686,12 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
}
if (i == tries) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"V Prime validation failed.(%d)\n", ret);
goto err;
}
- drm_dbg_kms(&dev_priv->drm, "HDCP is enabled (%d downstream devices)\n",
+ drm_dbg_kms(&i915->drm, "HDCP is enabled (%d downstream devices)\n",
num_downstream);
ret = 0;
err:
@@ -741,7 +703,7 @@ err:
static int intel_hdcp_auth(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
const struct intel_hdcp_shim *shim = hdcp->shim;
enum transcoder cpu_transcoder = connector->hdcp.cpu_transcoder;
@@ -773,7 +735,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
if (ret)
return ret;
if (!hdcp_capable) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"Panel is not HDCP capable\n");
return -EINVAL;
}
@@ -781,24 +743,24 @@ static int intel_hdcp_auth(struct intel_connector *connector)
/* Initialize An with 2 random values and acquire it */
for (i = 0; i < 2; i++)
- intel_de_write(dev_priv,
- HDCP_ANINIT(dev_priv, cpu_transcoder, port),
+ intel_de_write(i915,
+ HDCP_ANINIT(i915, cpu_transcoder, port),
get_random_u32());
- intel_de_write(dev_priv, HDCP_CONF(dev_priv, cpu_transcoder, port),
+ intel_de_write(i915, HDCP_CONF(i915, cpu_transcoder, port),
HDCP_CONF_CAPTURE_AN);
/* Wait for An to be acquired */
- if (intel_de_wait_for_set(dev_priv,
- HDCP_STATUS(dev_priv, cpu_transcoder, port),
+ if (intel_de_wait_for_set(i915,
+ HDCP_STATUS(i915, cpu_transcoder, port),
HDCP_STATUS_AN_READY, 1)) {
- drm_err(&dev_priv->drm, "Timed out waiting for An\n");
+ drm_err(&i915->drm, "Timed out waiting for An\n");
return -ETIMEDOUT;
}
- an.reg[0] = intel_de_read(dev_priv,
- HDCP_ANLO(dev_priv, cpu_transcoder, port));
- an.reg[1] = intel_de_read(dev_priv,
- HDCP_ANHI(dev_priv, cpu_transcoder, port));
+ an.reg[0] = intel_de_read(i915,
+ HDCP_ANLO(i915, cpu_transcoder, port));
+ an.reg[1] = intel_de_read(i915,
+ HDCP_ANHI(i915, cpu_transcoder, port));
ret = shim->write_an_aksv(dig_port, an.shim);
if (ret)
return ret;
@@ -811,34 +773,34 @@ static int intel_hdcp_auth(struct intel_connector *connector)
if (ret < 0)
return ret;
- if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, bksv.shim, 1) > 0) {
- drm_err(&dev_priv->drm, "BKSV is revoked\n");
+ if (drm_hdcp_check_ksvs_revoked(&i915->drm, bksv.shim, 1) > 0) {
+ drm_err(&i915->drm, "BKSV is revoked\n");
return -EPERM;
}
- intel_de_write(dev_priv, HDCP_BKSVLO(dev_priv, cpu_transcoder, port),
+ intel_de_write(i915, HDCP_BKSVLO(i915, cpu_transcoder, port),
bksv.reg[0]);
- intel_de_write(dev_priv, HDCP_BKSVHI(dev_priv, cpu_transcoder, port),
+ intel_de_write(i915, HDCP_BKSVHI(i915, cpu_transcoder, port),
bksv.reg[1]);
ret = shim->repeater_present(dig_port, &repeater_present);
if (ret)
return ret;
if (repeater_present)
- intel_de_write(dev_priv, HDCP_REP_CTL,
- intel_hdcp_get_repeater_ctl(dev_priv, cpu_transcoder, port));
+ intel_de_write(i915, HDCP_REP_CTL,
+ intel_hdcp_get_repeater_ctl(i915, cpu_transcoder, port));
ret = shim->toggle_signalling(dig_port, cpu_transcoder, true);
if (ret)
return ret;
- intel_de_write(dev_priv, HDCP_CONF(dev_priv, cpu_transcoder, port),
+ intel_de_write(i915, HDCP_CONF(i915, cpu_transcoder, port),
HDCP_CONF_AUTH_AND_ENC);
/* Wait for R0 ready */
- if (wait_for(intel_de_read(dev_priv, HDCP_STATUS(dev_priv, cpu_transcoder, port)) &
+ if (wait_for(intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder, port)) &
(HDCP_STATUS_R0_READY | HDCP_STATUS_ENC), 1)) {
- drm_err(&dev_priv->drm, "Timed out waiting for R0 ready\n");
+ drm_err(&i915->drm, "Timed out waiting for R0 ready\n");
return -ETIMEDOUT;
}
@@ -864,30 +826,30 @@ static int intel_hdcp_auth(struct intel_connector *connector)
ret = shim->read_ri_prime(dig_port, ri.shim);
if (ret)
return ret;
- intel_de_write(dev_priv,
- HDCP_RPRIME(dev_priv, cpu_transcoder, port),
+ intel_de_write(i915,
+ HDCP_RPRIME(i915, cpu_transcoder, port),
ri.reg);
/* Wait for Ri prime match */
- if (!wait_for(intel_de_read(dev_priv, HDCP_STATUS(dev_priv, cpu_transcoder, port)) &
+ if (!wait_for(intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder, port)) &
(HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC), 1))
break;
}
if (i == tries) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"Timed out waiting for Ri prime match (%x)\n",
- intel_de_read(dev_priv, HDCP_STATUS(dev_priv,
- cpu_transcoder, port)));
+ intel_de_read(i915,
+ HDCP_STATUS(i915, cpu_transcoder, port)));
return -ETIMEDOUT;
}
/* Wait for encryption confirmation */
- if (intel_de_wait_for_set(dev_priv,
- HDCP_STATUS(dev_priv, cpu_transcoder, port),
+ if (intel_de_wait_for_set(i915,
+ HDCP_STATUS(i915, cpu_transcoder, port),
HDCP_STATUS_ENC,
HDCP_ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
- drm_err(&dev_priv->drm, "Timed out waiting for encryption\n");
+ drm_err(&i915->drm, "Timed out waiting for encryption\n");
return -ETIMEDOUT;
}
@@ -895,42 +857,42 @@ static int intel_hdcp_auth(struct intel_connector *connector)
if (shim->stream_encryption) {
ret = shim->stream_encryption(connector, true);
if (ret) {
- drm_err(&dev_priv->drm, "[%s:%d] Failed to enable HDCP 1.4 stream enc\n",
+ drm_err(&i915->drm, "[%s:%d] Failed to enable HDCP 1.4 stream enc\n",
connector->base.name, connector->base.base.id);
return ret;
}
- drm_dbg_kms(&dev_priv->drm, "HDCP 1.4 transcoder: %s stream encrypted\n",
+ drm_dbg_kms(&i915->drm, "HDCP 1.4 transcoder: %s stream encrypted\n",
transcoder_name(hdcp->stream_transcoder));
}
if (repeater_present)
return intel_hdcp_auth_downstream(connector);
- drm_dbg_kms(&dev_priv->drm, "HDCP is enabled (no repeater present)\n");
+ drm_dbg_kms(&i915->drm, "HDCP is enabled (no repeater present)\n");
return 0;
}
static int _intel_hdcp_disable(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
enum port port = dig_port->base.port;
enum transcoder cpu_transcoder = hdcp->cpu_transcoder;
u32 repeater_ctl;
int ret;
- drm_dbg_kms(&dev_priv->drm, "[%s:%d] HDCP is being disabled...\n",
+ drm_dbg_kms(&i915->drm, "[%s:%d] HDCP is being disabled...\n",
connector->base.name, connector->base.base.id);
if (hdcp->shim->stream_encryption) {
ret = hdcp->shim->stream_encryption(connector, false);
if (ret) {
- drm_err(&dev_priv->drm, "[%s:%d] Failed to disable HDCP 1.4 stream enc\n",
+ drm_err(&i915->drm, "[%s:%d] Failed to disable HDCP 1.4 stream enc\n",
connector->base.name, connector->base.base.id);
return ret;
}
- drm_dbg_kms(&dev_priv->drm, "HDCP 1.4 transcoder: %s stream encryption disabled\n",
+ drm_dbg_kms(&i915->drm, "HDCP 1.4 transcoder: %s stream encryption disabled\n",
transcoder_name(hdcp->stream_transcoder));
/*
* If there are other connectors on this port using HDCP,
@@ -942,51 +904,51 @@ static int _intel_hdcp_disable(struct intel_connector *connector)
}
hdcp->hdcp_encrypted = false;
- intel_de_write(dev_priv, HDCP_CONF(dev_priv, cpu_transcoder, port), 0);
- if (intel_de_wait_for_clear(dev_priv,
- HDCP_STATUS(dev_priv, cpu_transcoder, port),
+ intel_de_write(i915, HDCP_CONF(i915, cpu_transcoder, port), 0);
+ if (intel_de_wait_for_clear(i915,
+ HDCP_STATUS(i915, cpu_transcoder, port),
~0, HDCP_ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
- drm_err(&dev_priv->drm,
+ drm_err(&i915->drm,
"Failed to disable HDCP, timeout clearing status\n");
return -ETIMEDOUT;
}
- repeater_ctl = intel_hdcp_get_repeater_ctl(dev_priv, cpu_transcoder,
+ repeater_ctl = intel_hdcp_get_repeater_ctl(i915, cpu_transcoder,
port);
- intel_de_rmw(dev_priv, HDCP_REP_CTL, repeater_ctl, 0);
+ intel_de_rmw(i915, HDCP_REP_CTL, repeater_ctl, 0);
ret = hdcp->shim->toggle_signalling(dig_port, cpu_transcoder, false);
if (ret) {
- drm_err(&dev_priv->drm, "Failed to disable HDCP signalling\n");
+ drm_err(&i915->drm, "Failed to disable HDCP signalling\n");
return ret;
}
- drm_dbg_kms(&dev_priv->drm, "HDCP is disabled\n");
+ drm_dbg_kms(&i915->drm, "HDCP is disabled\n");
return 0;
}
static int _intel_hdcp_enable(struct intel_connector *connector)
{
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
int i, ret, tries = 3;
- drm_dbg_kms(&dev_priv->drm, "[%s:%d] HDCP is being enabled...\n",
+ drm_dbg_kms(&i915->drm, "[%s:%d] HDCP is being enabled...\n",
connector->base.name, connector->base.base.id);
- if (!hdcp_key_loadable(dev_priv)) {
- drm_err(&dev_priv->drm, "HDCP key Load is not possible\n");
+ if (!hdcp_key_loadable(i915)) {
+ drm_err(&i915->drm, "HDCP key Load is not possible\n");
return -ENXIO;
}
for (i = 0; i < KEY_LOAD_TRIES; i++) {
- ret = intel_hdcp_load_keys(dev_priv);
+ ret = intel_hdcp_load_keys(i915);
if (!ret)
break;
- intel_hdcp_clear_keys(dev_priv);
+ intel_hdcp_clear_keys(i915);
}
if (ret) {
- drm_err(&dev_priv->drm, "Could not load HDCP keys, (%d)\n",
+ drm_err(&i915->drm, "Could not load HDCP keys, (%d)\n",
ret);
return ret;
}
@@ -999,13 +961,13 @@ static int _intel_hdcp_enable(struct intel_connector *connector)
return 0;
}
- drm_dbg_kms(&dev_priv->drm, "HDCP Auth failure (%d)\n", ret);
+ drm_dbg_kms(&i915->drm, "HDCP Auth failure (%d)\n", ret);
/* Ensuring HDCP encryption and signalling are stopped. */
_intel_hdcp_disable(connector);
}
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"HDCP authentication failed (%d tries/%d)\n", tries, ret);
return ret;
}
@@ -1021,6 +983,7 @@ static void intel_hdcp_update_value(struct intel_connector *connector,
struct drm_device *dev = connector->base.dev;
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct intel_hdcp *hdcp = &connector->hdcp;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
drm_WARN_ON(connector->base.dev, !mutex_is_locked(&hdcp->mutex));
@@ -1039,7 +1002,7 @@ static void intel_hdcp_update_value(struct intel_connector *connector,
hdcp->value = value;
if (update_property) {
drm_connector_get(&connector->base);
- schedule_work(&hdcp->prop_work);
+ queue_work(i915->unordered_wq, &hdcp->prop_work);
}
}
@@ -1047,7 +1010,7 @@ static void intel_hdcp_update_value(struct intel_connector *connector,
static int intel_hdcp_check_link(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
enum port port = dig_port->base.port;
enum transcoder cpu_transcoder;
@@ -1065,12 +1028,12 @@ static int intel_hdcp_check_link(struct intel_connector *connector)
goto out;
}
- if (drm_WARN_ON(&dev_priv->drm,
- !intel_hdcp_in_use(dev_priv, cpu_transcoder, port))) {
- drm_err(&dev_priv->drm,
+ if (drm_WARN_ON(&i915->drm,
+ !intel_hdcp_in_use(i915, cpu_transcoder, port))) {
+ drm_err(&i915->drm,
"%s:%d HDCP link stopped encryption,%x\n",
connector->base.name, connector->base.base.id,
- intel_de_read(dev_priv, HDCP_STATUS(dev_priv, cpu_transcoder, port)));
+ intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder, port)));
ret = -ENXIO;
intel_hdcp_update_value(connector,
DRM_MODE_CONTENT_PROTECTION_DESIRED,
@@ -1086,13 +1049,13 @@ static int intel_hdcp_check_link(struct intel_connector *connector)
goto out;
}
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"[%s:%d] HDCP link failed, retrying authentication\n",
connector->base.name, connector->base.base.id);
ret = _intel_hdcp_disable(connector);
if (ret) {
- drm_err(&dev_priv->drm, "Failed to disable hdcp (%d)\n", ret);
+ drm_err(&i915->drm, "Failed to disable hdcp (%d)\n", ret);
intel_hdcp_update_value(connector,
DRM_MODE_CONTENT_PROTECTION_DESIRED,
true);
@@ -1101,7 +1064,7 @@ static int intel_hdcp_check_link(struct intel_connector *connector)
ret = _intel_hdcp_enable(connector);
if (ret) {
- drm_err(&dev_priv->drm, "Failed to enable hdcp (%d)\n", ret);
+ drm_err(&i915->drm, "Failed to enable hdcp (%d)\n", ret);
intel_hdcp_update_value(connector,
DRM_MODE_CONTENT_PROTECTION_DESIRED,
true);
@@ -1119,9 +1082,9 @@ static void intel_hdcp_prop_work(struct work_struct *work)
struct intel_hdcp *hdcp = container_of(work, struct intel_hdcp,
prop_work);
struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
- drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex, NULL);
+ drm_modeset_lock(&i915->drm.mode_config.connection_mutex, NULL);
mutex_lock(&hdcp->mutex);
/*
@@ -1134,15 +1097,15 @@ static void intel_hdcp_prop_work(struct work_struct *work)
hdcp->value);
mutex_unlock(&hdcp->mutex);
- drm_modeset_unlock(&dev_priv->drm.mode_config.connection_mutex);
+ drm_modeset_unlock(&i915->drm.mode_config.connection_mutex);
drm_connector_put(&connector->base);
}
-bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
+bool is_hdcp_supported(struct drm_i915_private *i915, enum port port)
{
- return RUNTIME_INFO(dev_priv)->has_hdcp &&
- (DISPLAY_VER(dev_priv) >= 12 || port < PORT_E);
+ return DISPLAY_RUNTIME_INFO(i915)->has_hdcp &&
+ (DISPLAY_VER(i915) >= 12 || port < PORT_E);
}
static int
@@ -1151,23 +1114,23 @@ hdcp2_prepare_ake_init(struct intel_connector *connector,
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct i915_hdcp_master *arbiter;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- arbiter = dev_priv->display.hdcp.master;
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ arbiter = i915->display.hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->initiate_hdcp2_session(arbiter->hdcp_dev, data, ake_data);
if (ret)
- drm_dbg_kms(&dev_priv->drm, "Prepare_ake_init failed. %d\n",
+ drm_dbg_kms(&i915->drm, "Prepare_ake_init failed. %d\n",
ret);
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return ret;
}
@@ -1181,15 +1144,15 @@ hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct i915_hdcp_master *arbiter;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- arbiter = dev_priv->display.hdcp.master;
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ arbiter = i915->display.hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return -EINVAL;
}
@@ -1197,9 +1160,9 @@ hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
rx_cert, paired,
ek_pub_km, msg_sz);
if (ret < 0)
- drm_dbg_kms(&dev_priv->drm, "Verify rx_cert failed. %d\n",
+ drm_dbg_kms(&i915->drm, "Verify rx_cert failed. %d\n",
ret);
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return ret;
}
@@ -1209,22 +1172,22 @@ static int hdcp2_verify_hprime(struct intel_connector *connector,
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct i915_hdcp_master *arbiter;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- arbiter = dev_priv->display.hdcp.master;
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ arbiter = i915->display.hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->verify_hprime(arbiter->hdcp_dev, data, rx_hprime);
if (ret < 0)
- drm_dbg_kms(&dev_priv->drm, "Verify hprime failed. %d\n", ret);
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ drm_dbg_kms(&i915->drm, "Verify hprime failed. %d\n", ret);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return ret;
}
@@ -1235,23 +1198,23 @@ hdcp2_store_pairing_info(struct intel_connector *connector,
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct i915_hdcp_master *arbiter;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- arbiter = dev_priv->display.hdcp.master;
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ arbiter = i915->display.hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->store_pairing_info(arbiter->hdcp_dev, data, pairing_info);
if (ret < 0)
- drm_dbg_kms(&dev_priv->drm, "Store pairing info failed. %d\n",
+ drm_dbg_kms(&i915->drm, "Store pairing info failed. %d\n",
ret);
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return ret;
}
@@ -1262,23 +1225,23 @@ hdcp2_prepare_lc_init(struct intel_connector *connector,
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct i915_hdcp_master *arbiter;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- arbiter = dev_priv->display.hdcp.master;
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ arbiter = i915->display.hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->initiate_locality_check(arbiter->hdcp_dev, data, lc_init);
if (ret < 0)
- drm_dbg_kms(&dev_priv->drm, "Prepare lc_init failed. %d\n",
+ drm_dbg_kms(&i915->drm, "Prepare lc_init failed. %d\n",
ret);
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return ret;
}
@@ -1289,23 +1252,23 @@ hdcp2_verify_lprime(struct intel_connector *connector,
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct i915_hdcp_master *arbiter;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- arbiter = dev_priv->display.hdcp.master;
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ arbiter = i915->display.hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->verify_lprime(arbiter->hdcp_dev, data, rx_lprime);
if (ret < 0)
- drm_dbg_kms(&dev_priv->drm, "Verify L_Prime failed. %d\n",
+ drm_dbg_kms(&i915->drm, "Verify L_Prime failed. %d\n",
ret);
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return ret;
}
@@ -1315,23 +1278,23 @@ static int hdcp2_prepare_skey(struct intel_connector *connector,
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct i915_hdcp_master *arbiter;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- arbiter = dev_priv->display.hdcp.master;
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ arbiter = i915->display.hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->get_session_key(arbiter->hdcp_dev, data, ske_data);
if (ret < 0)
- drm_dbg_kms(&dev_priv->drm, "Get session key failed. %d\n",
+ drm_dbg_kms(&i915->drm, "Get session key failed. %d\n",
ret);
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return ret;
}
@@ -1344,15 +1307,15 @@ hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct i915_hdcp_master *arbiter;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- arbiter = dev_priv->display.hdcp.master;
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ arbiter = i915->display.hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return -EINVAL;
}
@@ -1361,9 +1324,9 @@ hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
rep_topology,
rep_send_ack);
if (ret < 0)
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"Verify rep topology failed. %d\n", ret);
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return ret;
}
@@ -1374,22 +1337,22 @@ hdcp2_verify_mprime(struct intel_connector *connector,
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct i915_hdcp_master *arbiter;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- arbiter = dev_priv->display.hdcp.master;
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ arbiter = i915->display.hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->verify_mprime(arbiter->hdcp_dev, data, stream_ready);
if (ret < 0)
- drm_dbg_kms(&dev_priv->drm, "Verify mprime failed. %d\n", ret);
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ drm_dbg_kms(&i915->drm, "Verify mprime failed. %d\n", ret);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return ret;
}
@@ -1398,23 +1361,23 @@ static int hdcp2_authenticate_port(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct i915_hdcp_master *arbiter;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- arbiter = dev_priv->display.hdcp.master;
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ arbiter = i915->display.hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->enable_hdcp_authentication(arbiter->hdcp_dev, data);
if (ret < 0)
- drm_dbg_kms(&dev_priv->drm, "Enable hdcp auth failed. %d\n",
+ drm_dbg_kms(&i915->drm, "Enable hdcp auth failed. %d\n",
ret);
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return ret;
}
@@ -1422,21 +1385,21 @@ static int hdcp2_authenticate_port(struct intel_connector *connector)
static int hdcp2_close_session(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct i915_hdcp_master *arbiter;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- arbiter = dev_priv->display.hdcp.master;
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ arbiter = i915->display.hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->close_hdcp_session(arbiter->hdcp_dev,
&dig_port->hdcp_port_data);
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return ret;
}
@@ -1450,7 +1413,7 @@ static int hdcp2_deauthenticate_port(struct intel_connector *connector)
static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
union {
struct hdcp2_ake_init ake_init;
@@ -1482,16 +1445,16 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
return ret;
if (msgs.send_cert.rx_caps[0] != HDCP_2_2_RX_CAPS_VERSION_VAL) {
- drm_dbg_kms(&dev_priv->drm, "cert.rx_caps dont claim HDCP2.2\n");
+ drm_dbg_kms(&i915->drm, "cert.rx_caps dont claim HDCP2.2\n");
return -EINVAL;
}
hdcp->is_repeater = HDCP_2_2_RX_REPEATER(msgs.send_cert.rx_caps[2]);
- if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm,
+ if (drm_hdcp_check_ksvs_revoked(&i915->drm,
msgs.send_cert.cert_rx.receiver_id,
1) > 0) {
- drm_err(&dev_priv->drm, "Receiver ID is revoked\n");
+ drm_err(&i915->drm, "Receiver ID is revoked\n");
return -EPERM;
}
@@ -1645,7 +1608,7 @@ static
int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
union {
struct hdcp2_rep_send_receiverid_list recvid_list;
@@ -1665,7 +1628,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
if (HDCP_2_2_MAX_CASCADE_EXCEEDED(rx_info[1]) ||
HDCP_2_2_MAX_DEVS_EXCEEDED(rx_info[1])) {
- drm_dbg_kms(&dev_priv->drm, "Topology Max Size Exceeded\n");
+ drm_dbg_kms(&i915->drm, "Topology Max Size Exceeded\n");
return -EINVAL;
}
@@ -1682,23 +1645,23 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
drm_hdcp_be24_to_cpu((const u8 *)msgs.recvid_list.seq_num_v);
if (!hdcp->hdcp2_encrypted && seq_num_v) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"Non zero Seq_num_v at first RecvId_List msg\n");
return -EINVAL;
}
if (seq_num_v < hdcp->seq_num_v) {
/* Roll over of the seq_num_v from repeater. Reauthenticate. */
- drm_dbg_kms(&dev_priv->drm, "Seq_num_v roll over.\n");
+ drm_dbg_kms(&i915->drm, "Seq_num_v roll over.\n");
return -EINVAL;
}
device_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
HDCP_2_2_DEV_COUNT_LO(rx_info[1]));
- if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm,
+ if (drm_hdcp_check_ksvs_revoked(&i915->drm,
msgs.recvid_list.receiver_ids,
device_cnt) > 0) {
- drm_err(&dev_priv->drm, "Revoked receiver ID(s) is in list\n");
+ drm_err(&i915->drm, "Revoked receiver ID(s) is in list\n");
return -EPERM;
}
@@ -1767,16 +1730,16 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
static int hdcp2_enable_stream_encryption(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
struct intel_hdcp *hdcp = &connector->hdcp;
enum transcoder cpu_transcoder = hdcp->cpu_transcoder;
enum port port = dig_port->base.port;
int ret = 0;
- if (!(intel_de_read(dev_priv, HDCP2_STATUS(dev_priv, cpu_transcoder, port)) &
+ if (!(intel_de_read(i915, HDCP2_STATUS(i915, cpu_transcoder, port)) &
LINK_ENCRYPTION_STATUS)) {
- drm_err(&dev_priv->drm, "[%s:%d] HDCP 2.2 Link is not encrypted\n",
+ drm_err(&i915->drm, "[%s:%d] HDCP 2.2 Link is not encrypted\n",
connector->base.name, connector->base.base.id);
ret = -EPERM;
goto link_recover;
@@ -1785,11 +1748,11 @@ static int hdcp2_enable_stream_encryption(struct intel_connector *connector)
if (hdcp->shim->stream_2_2_encryption) {
ret = hdcp->shim->stream_2_2_encryption(connector, true);
if (ret) {
- drm_err(&dev_priv->drm, "[%s:%d] Failed to enable HDCP 2.2 stream enc\n",
+ drm_err(&i915->drm, "[%s:%d] Failed to enable HDCP 2.2 stream enc\n",
connector->base.name, connector->base.base.id);
return ret;
}
- drm_dbg_kms(&dev_priv->drm, "HDCP 2.2 transcoder: %s stream encrypted\n",
+ drm_dbg_kms(&i915->drm, "HDCP 2.2 transcoder: %s stream encrypted\n",
transcoder_name(hdcp->stream_transcoder));
}
@@ -1797,7 +1760,7 @@ static int hdcp2_enable_stream_encryption(struct intel_connector *connector)
link_recover:
if (hdcp2_deauthenticate_port(connector) < 0)
- drm_dbg_kms(&dev_priv->drm, "Port deauth failed.\n");
+ drm_dbg_kms(&i915->drm, "Port deauth failed.\n");
dig_port->hdcp_auth_status = false;
data->k = 0;
@@ -1808,34 +1771,34 @@ link_recover:
static int hdcp2_enable_encryption(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
enum port port = dig_port->base.port;
enum transcoder cpu_transcoder = hdcp->cpu_transcoder;
int ret;
- drm_WARN_ON(&dev_priv->drm,
- intel_de_read(dev_priv, HDCP2_STATUS(dev_priv, cpu_transcoder, port)) &
+ drm_WARN_ON(&i915->drm,
+ intel_de_read(i915, HDCP2_STATUS(i915, cpu_transcoder, port)) &
LINK_ENCRYPTION_STATUS);
if (hdcp->shim->toggle_signalling) {
ret = hdcp->shim->toggle_signalling(dig_port, cpu_transcoder,
true);
if (ret) {
- drm_err(&dev_priv->drm,
+ drm_err(&i915->drm,
"Failed to enable HDCP signalling. %d\n",
ret);
return ret;
}
}
- if (intel_de_read(dev_priv, HDCP2_STATUS(dev_priv, cpu_transcoder, port)) &
+ if (intel_de_read(i915, HDCP2_STATUS(i915, cpu_transcoder, port)) &
LINK_AUTH_STATUS)
/* Link is Authenticated. Now set for Encryption */
- intel_de_rmw(dev_priv, HDCP2_CTL(dev_priv, cpu_transcoder, port),
+ intel_de_rmw(i915, HDCP2_CTL(i915, cpu_transcoder, port),
0, CTL_LINK_ENCRYPTION_REQ);
- ret = intel_de_wait_for_set(dev_priv,
- HDCP2_STATUS(dev_priv, cpu_transcoder,
+ ret = intel_de_wait_for_set(i915,
+ HDCP2_STATUS(i915, cpu_transcoder,
port),
LINK_ENCRYPTION_STATUS,
HDCP_ENCRYPT_STATUS_CHANGE_TIMEOUT_MS);
@@ -1847,31 +1810,31 @@ static int hdcp2_enable_encryption(struct intel_connector *connector)
static int hdcp2_disable_encryption(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
enum port port = dig_port->base.port;
enum transcoder cpu_transcoder = hdcp->cpu_transcoder;
int ret;
- drm_WARN_ON(&dev_priv->drm, !(intel_de_read(dev_priv, HDCP2_STATUS(dev_priv, cpu_transcoder, port)) &
+ drm_WARN_ON(&i915->drm, !(intel_de_read(i915, HDCP2_STATUS(i915, cpu_transcoder, port)) &
LINK_ENCRYPTION_STATUS));
- intel_de_rmw(dev_priv, HDCP2_CTL(dev_priv, cpu_transcoder, port),
+ intel_de_rmw(i915, HDCP2_CTL(i915, cpu_transcoder, port),
CTL_LINK_ENCRYPTION_REQ, 0);
- ret = intel_de_wait_for_clear(dev_priv,
- HDCP2_STATUS(dev_priv, cpu_transcoder,
+ ret = intel_de_wait_for_clear(i915,
+ HDCP2_STATUS(i915, cpu_transcoder,
port),
LINK_ENCRYPTION_STATUS,
HDCP_ENCRYPT_STATUS_CHANGE_TIMEOUT_MS);
if (ret == -ETIMEDOUT)
- drm_dbg_kms(&dev_priv->drm, "Disable Encryption Timedout");
+ drm_dbg_kms(&i915->drm, "Disable Encryption Timedout");
if (hdcp->shim->toggle_signalling) {
ret = hdcp->shim->toggle_signalling(dig_port, cpu_transcoder,
false);
if (ret) {
- drm_err(&dev_priv->drm,
+ drm_err(&i915->drm,
"Failed to disable HDCP signalling. %d\n",
ret);
return ret;
@@ -1919,13 +1882,7 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
for (i = 0; i < tries && !dig_port->hdcp_auth_status; i++) {
ret = hdcp2_authenticate_sink(connector);
if (!ret) {
- ret = intel_hdcp_prepare_streams(connector);
- if (ret) {
- drm_dbg_kms(&i915->drm,
- "Prepare streams failed.(%d)\n",
- ret);
- break;
- }
+ intel_hdcp_prepare_streams(connector);
ret = hdcp2_propagate_stream_management_info(connector);
if (ret) {
@@ -2037,7 +1994,7 @@ _intel_hdcp2_disable(struct intel_connector *connector, bool hdcp2_link_recovery
static int intel_hdcp2_check_link(struct intel_connector *connector)
{
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
enum port port = dig_port->base.port;
enum transcoder cpu_transcoder;
@@ -2054,11 +2011,11 @@ static int intel_hdcp2_check_link(struct intel_connector *connector)
goto out;
}
- if (drm_WARN_ON(&dev_priv->drm,
- !intel_hdcp2_in_use(dev_priv, cpu_transcoder, port))) {
- drm_err(&dev_priv->drm,
+ if (drm_WARN_ON(&i915->drm,
+ !intel_hdcp2_in_use(i915, cpu_transcoder, port))) {
+ drm_err(&i915->drm,
"HDCP2.2 link stopped the encryption, %x\n",
- intel_de_read(dev_priv, HDCP2_STATUS(dev_priv, cpu_transcoder, port)));
+ intel_de_read(i915, HDCP2_STATUS(i915, cpu_transcoder, port)));
ret = -ENXIO;
_intel_hdcp2_disable(connector, true);
intel_hdcp_update_value(connector,
@@ -2081,7 +2038,7 @@ static int intel_hdcp2_check_link(struct intel_connector *connector)
if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
goto out;
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"HDCP2.2 Downstream topology change\n");
ret = hdcp2_authenticate_repeater_topology(connector);
if (!ret) {
@@ -2090,19 +2047,19 @@ static int intel_hdcp2_check_link(struct intel_connector *connector)
true);
goto out;
}
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"[%s:%d] Repeater topology auth failed.(%d)\n",
connector->base.name, connector->base.base.id,
ret);
} else {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"[%s:%d] HDCP2.2 link failed, retrying auth\n",
connector->base.name, connector->base.base.id);
}
ret = _intel_hdcp2_disable(connector, true);
if (ret) {
- drm_err(&dev_priv->drm,
+ drm_err(&i915->drm,
"[%s:%d] Failed to disable hdcp2.2 (%d)\n",
connector->base.name, connector->base.base.id, ret);
intel_hdcp_update_value(connector,
@@ -2112,7 +2069,7 @@ static int intel_hdcp2_check_link(struct intel_connector *connector)
ret = _intel_hdcp2_enable(connector);
if (ret) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"[%s:%d] Failed to enable hdcp2.2 (%d)\n",
connector->base.name, connector->base.base.id,
ret);
@@ -2134,28 +2091,29 @@ static void intel_hdcp_check_work(struct work_struct *work)
struct intel_hdcp,
check_work);
struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
if (drm_connector_is_unregistered(&connector->base))
return;
if (!intel_hdcp2_check_link(connector))
- schedule_delayed_work(&hdcp->check_work,
- DRM_HDCP2_CHECK_PERIOD_MS);
+ queue_delayed_work(i915->unordered_wq, &hdcp->check_work,
+ DRM_HDCP2_CHECK_PERIOD_MS);
else if (!intel_hdcp_check_link(connector))
- schedule_delayed_work(&hdcp->check_work,
- DRM_HDCP_CHECK_PERIOD_MS);
+ queue_delayed_work(i915->unordered_wq, &hdcp->check_work,
+ DRM_HDCP_CHECK_PERIOD_MS);
}
static int i915_hdcp_component_bind(struct device *i915_kdev,
struct device *mei_kdev, void *data)
{
- struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev);
+ struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
- drm_dbg(&dev_priv->drm, "I915 HDCP comp bind\n");
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- dev_priv->display.hdcp.master = (struct i915_hdcp_master *)data;
- dev_priv->display.hdcp.master->hdcp_dev = mei_kdev;
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ drm_dbg(&i915->drm, "I915 HDCP comp bind\n");
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ i915->display.hdcp.arbiter = (struct i915_hdcp_arbiter *)data;
+ i915->display.hdcp.arbiter->hdcp_dev = mei_kdev;
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return 0;
}
@@ -2163,12 +2121,12 @@ static int i915_hdcp_component_bind(struct device *i915_kdev,
static void i915_hdcp_component_unbind(struct device *i915_kdev,
struct device *mei_kdev, void *data)
{
- struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev);
+ struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
- drm_dbg(&dev_priv->drm, "I915 HDCP comp unbind\n");
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- dev_priv->display.hdcp.master = NULL;
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ drm_dbg(&i915->drm, "I915 HDCP comp unbind\n");
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ i915->display.hdcp.arbiter = NULL;
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
}
static const struct component_ops i915_hdcp_ops = {
@@ -2202,12 +2160,11 @@ static int initialize_hdcp_port_data(struct intel_connector *connector,
struct intel_digital_port *dig_port,
const struct intel_hdcp_shim *shim)
{
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct intel_hdcp *hdcp = &connector->hdcp;
enum port port = dig_port->base.port;
- if (DISPLAY_VER(dev_priv) < 12)
+ if (DISPLAY_VER(i915) < 12)
data->hdcp_ddi = intel_get_hdcp_ddi_index(port);
else
/*
@@ -2227,58 +2184,55 @@ static int initialize_hdcp_port_data(struct intel_connector *connector,
data->protocol = (u8)shim->protocol;
if (!data->streams)
- data->streams = kcalloc(INTEL_NUM_PIPES(dev_priv),
+ data->streams = kcalloc(INTEL_NUM_PIPES(i915),
sizeof(struct hdcp2_streamid_type),
GFP_KERNEL);
if (!data->streams) {
- drm_err(&dev_priv->drm, "Out of Memory\n");
+ drm_err(&i915->drm, "Out of Memory\n");
return -ENOMEM;
}
- /* For SST */
- data->streams[0].stream_id = 0;
- data->streams[0].stream_type = hdcp->content_type;
return 0;
}
-static bool is_hdcp2_supported(struct drm_i915_private *dev_priv)
+static bool is_hdcp2_supported(struct drm_i915_private *i915)
{
- if (intel_hdcp_gsc_cs_required(dev_priv))
+ if (intel_hdcp_gsc_cs_required(i915))
return true;
if (!IS_ENABLED(CONFIG_INTEL_MEI_HDCP))
return false;
- return (DISPLAY_VER(dev_priv) >= 10 ||
- IS_KABYLAKE(dev_priv) ||
- IS_COFFEELAKE(dev_priv) ||
- IS_COMETLAKE(dev_priv));
+ return (DISPLAY_VER(i915) >= 10 ||
+ IS_KABYLAKE(i915) ||
+ IS_COFFEELAKE(i915) ||
+ IS_COMETLAKE(i915));
}
-void intel_hdcp_component_init(struct drm_i915_private *dev_priv)
+void intel_hdcp_component_init(struct drm_i915_private *i915)
{
int ret;
- if (!is_hdcp2_supported(dev_priv))
+ if (!is_hdcp2_supported(i915))
return;
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- drm_WARN_ON(&dev_priv->drm, dev_priv->display.hdcp.comp_added);
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ drm_WARN_ON(&i915->drm, i915->display.hdcp.comp_added);
- dev_priv->display.hdcp.comp_added = true;
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
- if (intel_hdcp_gsc_cs_required(dev_priv))
- ret = intel_hdcp_gsc_init(dev_priv);
+ i915->display.hdcp.comp_added = true;
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ if (intel_hdcp_gsc_cs_required(i915))
+ ret = intel_hdcp_gsc_init(i915);
else
- ret = component_add_typed(dev_priv->drm.dev, &i915_hdcp_ops,
+ ret = component_add_typed(i915->drm.dev, &i915_hdcp_ops,
I915_COMPONENT_HDCP);
if (ret < 0) {
- drm_dbg_kms(&dev_priv->drm, "Failed at fw component add(%d)\n",
+ drm_dbg_kms(&i915->drm, "Failed at fw component add(%d)\n",
ret);
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- dev_priv->display.hdcp.comp_added = false;
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ i915->display.hdcp.comp_added = false;
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return;
}
}
@@ -2304,14 +2258,14 @@ int intel_hdcp_init(struct intel_connector *connector,
struct intel_digital_port *dig_port,
const struct intel_hdcp_shim *shim)
{
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
if (!shim)
return -EINVAL;
- if (is_hdcp2_supported(dev_priv))
+ if (is_hdcp2_supported(i915))
intel_hdcp2_init(connector, dig_port, shim);
ret =
@@ -2332,10 +2286,60 @@ int intel_hdcp_init(struct intel_connector *connector,
return 0;
}
-int intel_hdcp_enable(struct intel_connector *connector,
- const struct intel_crtc_state *pipe_config, u8 content_type)
+static int
+intel_hdcp_set_streams(struct intel_digital_port *dig_port,
+ struct intel_atomic_state *state)
+{
+ struct drm_connector_list_iter conn_iter;
+ struct intel_digital_port *conn_dig_port;
+ struct intel_connector *connector;
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct hdcp_port_data *data = &dig_port->hdcp_port_data;
+
+ if (!intel_encoder_is_mst(&dig_port->base)) {
+ data->k = 1;
+ data->streams[0].stream_id = 0;
+ return 0;
+ }
+
+ data->k = 0;
+
+ drm_connector_list_iter_begin(&i915->drm, &conn_iter);
+ for_each_intel_connector_iter(connector, &conn_iter) {
+ if (connector->base.status == connector_status_disconnected)
+ continue;
+
+ if (!intel_encoder_is_mst(intel_attached_encoder(connector)))
+ continue;
+
+ conn_dig_port = intel_attached_dig_port(connector);
+ if (conn_dig_port != dig_port)
+ continue;
+
+ data->streams[data->k].stream_id =
+ intel_conn_to_vcpi(&state->base, connector);
+ data->k++;
+
+ /* if there is only one active stream */
+ if (dig_port->dp.active_mst_links <= 1)
+ break;
+ }
+ drm_connector_list_iter_end(&conn_iter);
+
+ if (drm_WARN_ON(&i915->drm, data->k > INTEL_NUM_PIPES(i915) || data->k == 0))
+ return -EINVAL;
+
+ return 0;
+}
+
+int intel_hdcp_enable(struct intel_atomic_state *state,
+ struct intel_encoder *encoder,
+ const struct intel_crtc_state *pipe_config,
+ const struct drm_connector_state *conn_state)
{
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_connector *connector =
+ to_intel_connector(conn_state->connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct intel_hdcp *hdcp = &connector->hdcp;
unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS;
@@ -2345,16 +2349,16 @@ int intel_hdcp_enable(struct intel_connector *connector,
return -ENOENT;
if (!connector->encoder) {
- drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n",
+ drm_err(&i915->drm, "[%s:%d] encoder is not initialized\n",
connector->base.name, connector->base.base.id);
return -ENODEV;
}
mutex_lock(&hdcp->mutex);
mutex_lock(&dig_port->hdcp_mutex);
- drm_WARN_ON(&dev_priv->drm,
+ drm_WARN_ON(&i915->drm,
hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED);
- hdcp->content_type = content_type;
+ hdcp->content_type = (u8)conn_state->content_type;
if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) {
hdcp->cpu_transcoder = pipe_config->mst_master_transcoder;
@@ -2364,7 +2368,7 @@ int intel_hdcp_enable(struct intel_connector *connector,
hdcp->stream_transcoder = INVALID_TRANSCODER;
}
- if (DISPLAY_VER(dev_priv) >= 12)
+ if (DISPLAY_VER(i915) >= 12)
dig_port->hdcp_port_data.hdcp_transcoder =
intel_get_hdcp_transcoder(hdcp->cpu_transcoder);
@@ -2373,9 +2377,17 @@ int intel_hdcp_enable(struct intel_connector *connector,
* is capable of HDCP2.2, it is preferred to use HDCP2.2.
*/
if (intel_hdcp2_capable(connector)) {
- ret = _intel_hdcp2_enable(connector);
- if (!ret)
- check_link_interval = DRM_HDCP2_CHECK_PERIOD_MS;
+ ret = intel_hdcp_set_streams(dig_port, state);
+ if (!ret) {
+ ret = _intel_hdcp2_enable(connector);
+ if (!ret)
+ check_link_interval =
+ DRM_HDCP2_CHECK_PERIOD_MS;
+ } else {
+ drm_dbg_kms(&i915->drm,
+ "Set content streams failed: (%d)\n",
+ ret);
+ }
}
/*
@@ -2388,7 +2400,8 @@ int intel_hdcp_enable(struct intel_connector *connector,
}
if (!ret) {
- schedule_delayed_work(&hdcp->check_work, check_link_interval);
+ queue_delayed_work(i915->unordered_wq, &hdcp->check_work,
+ check_link_interval);
intel_hdcp_update_value(connector,
DRM_MODE_CONTENT_PROTECTION_ENABLED,
true);
@@ -2437,6 +2450,7 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state,
to_intel_connector(conn_state->connector);
struct intel_hdcp *hdcp = &connector->hdcp;
bool content_protection_type_changed, desired_and_not_enabled = false;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
if (!connector->hdcp.shim)
return;
@@ -2463,7 +2477,7 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state,
mutex_lock(&hdcp->mutex);
hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
drm_connector_get(&connector->base);
- schedule_work(&hdcp->prop_work);
+ queue_work(i915->unordered_wq, &hdcp->prop_work);
mutex_unlock(&hdcp->mutex);
}
@@ -2480,31 +2494,29 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state,
*/
if (!desired_and_not_enabled && !content_protection_type_changed) {
drm_connector_get(&connector->base);
- schedule_work(&hdcp->prop_work);
+ queue_work(i915->unordered_wq, &hdcp->prop_work);
}
}
if (desired_and_not_enabled || content_protection_type_changed)
- intel_hdcp_enable(connector,
- crtc_state,
- (u8)conn_state->hdcp_content_type);
+ intel_hdcp_enable(state, encoder, crtc_state, conn_state);
}
-void intel_hdcp_component_fini(struct drm_i915_private *dev_priv)
+void intel_hdcp_component_fini(struct drm_i915_private *i915)
{
- mutex_lock(&dev_priv->display.hdcp.comp_mutex);
- if (!dev_priv->display.hdcp.comp_added) {
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ if (!i915->display.hdcp.comp_added) {
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return;
}
- dev_priv->display.hdcp.comp_added = false;
- mutex_unlock(&dev_priv->display.hdcp.comp_mutex);
+ i915->display.hdcp.comp_added = false;
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
- if (intel_hdcp_gsc_cs_required(dev_priv))
- intel_hdcp_gsc_fini(dev_priv);
+ if (intel_hdcp_gsc_cs_required(i915))
+ intel_hdcp_gsc_fini(i915);
else
- component_del(dev_priv->drm.dev, &i915_hdcp_ops);
+ component_del(i915->drm.dev, &i915_hdcp_ops);
}
void intel_hdcp_cleanup(struct intel_connector *connector)
@@ -2594,6 +2606,7 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
{
struct intel_hdcp *hdcp = &connector->hdcp;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
if (!hdcp->shim)
return;
@@ -2601,5 +2614,5 @@ void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
atomic_inc(&connector->hdcp.cp_irq_count);
wake_up_all(&connector->hdcp.cp_irq_queue);
- schedule_delayed_work(&hdcp->check_work, 0);
+ queue_delayed_work(i915->unordered_wq, &hdcp->check_work, 0);
}
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.h b/drivers/gpu/drm/i915/display/intel_hdcp.h
index 8f53b0c7fe5c..5997c52a0958 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.h
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.h
@@ -28,18 +28,20 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
int intel_hdcp_init(struct intel_connector *connector,
struct intel_digital_port *dig_port,
const struct intel_hdcp_shim *hdcp_shim);
-int intel_hdcp_enable(struct intel_connector *connector,
- const struct intel_crtc_state *pipe_config, u8 content_type);
+int intel_hdcp_enable(struct intel_atomic_state *state,
+ struct intel_encoder *encoder,
+ const struct intel_crtc_state *pipe_config,
+ const struct drm_connector_state *conn_state);
int intel_hdcp_disable(struct intel_connector *connector);
void intel_hdcp_update_pipe(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
-bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
+bool is_hdcp_supported(struct drm_i915_private *i915, enum port port);
bool intel_hdcp_capable(struct intel_connector *connector);
bool intel_hdcp2_capable(struct intel_connector *connector);
-void intel_hdcp_component_init(struct drm_i915_private *dev_priv);
-void intel_hdcp_component_fini(struct drm_i915_private *dev_priv);
+void intel_hdcp_component_init(struct drm_i915_private *i915);
+void intel_hdcp_component_fini(struct drm_i915_private *i915);
void intel_hdcp_cleanup(struct intel_connector *connector);
void intel_hdcp_handle_cp_irq(struct intel_connector *connector);
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c
index 7e52aea6aa17..72573ce1d0e9 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c
@@ -5,11 +5,11 @@
#include <drm/i915_hdcp_interface.h>
-#include "display/intel_hdcp_gsc.h"
#include "gem/i915_gem_region.h"
#include "gt/uc/intel_gsc_uc_heci_cmd_submit.h"
#include "i915_drv.h"
#include "i915_utils.h"
+#include "intel_hdcp_gsc.h"
bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915)
{
@@ -697,19 +697,19 @@ static void intel_hdcp_gsc_free_message(struct drm_i915_private *i915)
int intel_hdcp_gsc_init(struct drm_i915_private *i915)
{
- struct i915_hdcp_master *data;
+ struct i915_hdcp_arbiter *data;
int ret;
- data = kzalloc(sizeof(struct i915_hdcp_master), GFP_KERNEL);
+ data = kzalloc(sizeof(struct i915_hdcp_arbiter), GFP_KERNEL);
if (!data)
return -ENOMEM;
- mutex_lock(&i915->display.hdcp.comp_mutex);
- i915->display.hdcp.master = data;
- i915->display.hdcp.master->hdcp_dev = i915->drm.dev;
- i915->display.hdcp.master->ops = &gsc_hdcp_ops;
+ mutex_lock(&i915->display.hdcp.hdcp_mutex);
+ i915->display.hdcp.arbiter = data;
+ i915->display.hdcp.arbiter->hdcp_dev = i915->drm.dev;
+ i915->display.hdcp.arbiter->ops = &gsc_hdcp_ops;
ret = intel_hdcp_gsc_hdcp2_init(i915);
- mutex_unlock(&i915->display.hdcp.comp_mutex);
+ mutex_unlock(&i915->display.hdcp.hdcp_mutex);
return ret;
}
@@ -717,7 +717,7 @@ int intel_hdcp_gsc_init(struct drm_i915_private *i915)
void intel_hdcp_gsc_fini(struct drm_i915_private *i915)
{
intel_hdcp_gsc_free_message(i915);
- kfree(i915->display.hdcp.master);
+ kfree(i915->display.hdcp.arbiter);
}
static int intel_gsc_send_sync(struct drm_i915_private *i915,
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index a690a5616506..7ac5e6c5e00d 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -40,12 +40,13 @@
#include <drm/drm_edid.h>
#include <drm/intel_lpe_audio.h>
-#include "i915_debugfs.h"
+#include "g4x_hdmi.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_audio.h"
#include "intel_connector.h"
+#include "intel_cx0_phy.h"
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_types.h"
@@ -58,7 +59,7 @@
#include "intel_panel.h"
#include "intel_snps_phy.h"
-static struct drm_i915_private *intel_hdmi_to_i915(struct intel_hdmi *intel_hdmi)
+inline struct drm_i915_private *intel_hdmi_to_i915(struct intel_hdmi *intel_hdmi)
{
return to_i915(hdmi_to_dig_port(intel_hdmi)->base.base.dev);
}
@@ -1789,7 +1790,9 @@ static int intel_hdmi_source_max_tmds_clock(struct intel_encoder *encoder)
static bool intel_has_hdmi_sink(struct intel_hdmi *hdmi,
const struct drm_connector_state *conn_state)
{
- return hdmi->has_hdmi_sink &&
+ struct intel_connector *connector = hdmi->attached_connector;
+
+ return connector->base.display_info.is_hdmi &&
READ_ONCE(to_intel_digital_connector_state(conn_state)->force_audio) != HDMI_AUDIO_OFF_DVI;
}
@@ -1865,16 +1868,19 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
* FIXME: We will hopefully get an algorithmic way of programming
* the MPLLB for HDMI in the future.
*/
- if (IS_DG2(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 14)
+ return intel_cx0_phy_check_hdmi_link_rate(hdmi, clock);
+ else if (IS_DG2(dev_priv))
return intel_snps_phy_check_hdmi_link_rate(clock);
return MODE_OK;
}
-int intel_hdmi_tmds_clock(int clock, int bpc, bool ycbcr420_output)
+int intel_hdmi_tmds_clock(int clock, int bpc,
+ enum intel_output_format sink_format)
{
/* YCBCR420 TMDS rate requirement is half the pixel clock */
- if (ycbcr420_output)
+ if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
clock /= 2;
/*
@@ -1901,7 +1907,8 @@ static bool intel_hdmi_source_bpc_possible(struct drm_i915_private *i915, int bp
}
static bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector,
- int bpc, bool has_hdmi_sink, bool ycbcr420_output)
+ int bpc, bool has_hdmi_sink,
+ enum intel_output_format sink_format)
{
const struct drm_display_info *info = &connector->display_info;
const struct drm_hdmi_info *hdmi = &info->hdmi;
@@ -1911,7 +1918,7 @@ static bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector,
if (!has_hdmi_sink)
return false;
- if (ycbcr420_output)
+ if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36;
else
return info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36;
@@ -1919,7 +1926,7 @@ static bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector,
if (!has_hdmi_sink)
return false;
- if (ycbcr420_output)
+ if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_30;
else
return info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30;
@@ -1933,7 +1940,8 @@ static bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector,
static enum drm_mode_status
intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock,
- bool has_hdmi_sink, bool ycbcr420_output)
+ bool has_hdmi_sink,
+ enum intel_output_format sink_format)
{
struct drm_i915_private *i915 = to_i915(connector->dev);
struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector));
@@ -1946,12 +1954,12 @@ intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock,
* least one color depth is accepted.
*/
for (bpc = 12; bpc >= 8; bpc -= 2) {
- int tmds_clock = intel_hdmi_tmds_clock(clock, bpc, ycbcr420_output);
+ int tmds_clock = intel_hdmi_tmds_clock(clock, bpc, sink_format);
if (!intel_hdmi_source_bpc_possible(i915, bpc))
continue;
- if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink, ycbcr420_output))
+ if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink, sink_format))
continue;
status = hdmi_port_clock_valid(hdmi, tmds_clock, true, has_hdmi_sink);
@@ -1976,6 +1984,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->state);
bool ycbcr_420_only;
+ enum intel_output_format sink_format;
if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
clock *= 2;
@@ -2000,14 +2009,20 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, mode);
- status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, ycbcr_420_only);
+ if (ycbcr_420_only)
+ sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+ else
+ sink_format = INTEL_OUTPUT_FORMAT_RGB;
+
+ status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, sink_format);
if (status != MODE_OK) {
if (ycbcr_420_only ||
!connector->ycbcr_420_allowed ||
!drm_mode_is_420_also(&connector->display_info, mode))
return status;
- status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, true);
+ sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+ status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, sink_format);
if (status != MODE_OK)
return status;
}
@@ -2016,7 +2031,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
}
bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
- int bpc, bool has_hdmi_sink, bool ycbcr420_output)
+ int bpc, bool has_hdmi_sink)
{
struct drm_atomic_state *state = crtc_state->uapi.state;
struct drm_connector_state *connector_state;
@@ -2027,7 +2042,8 @@ bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
if (connector_state->crtc != crtc_state->uapi.crtc)
continue;
- if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink, ycbcr420_output))
+ if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink,
+ crtc_state->sink_format))
return false;
}
@@ -2051,8 +2067,7 @@ static bool hdmi_bpc_possible(const struct intel_crtc_state *crtc_state, int bpc
adjusted_mode->crtc_hblank_start) % 8 == 2)
return false;
- return intel_hdmi_bpc_possible(crtc_state, bpc, crtc_state->has_hdmi_sink,
- intel_hdmi_is_ycbcr420(crtc_state));
+ return intel_hdmi_bpc_possible(crtc_state, bpc, crtc_state->has_hdmi_sink);
}
static int intel_hdmi_compute_bpc(struct intel_encoder *encoder,
@@ -2060,7 +2075,6 @@ static int intel_hdmi_compute_bpc(struct intel_encoder *encoder,
int clock, bool respect_downstream_limits)
{
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
- bool ycbcr420_output = intel_hdmi_is_ycbcr420(crtc_state);
int bpc;
/*
@@ -2078,7 +2092,8 @@ static int intel_hdmi_compute_bpc(struct intel_encoder *encoder,
bpc = 8;
for (; bpc >= 8; bpc -= 2) {
- int tmds_clock = intel_hdmi_tmds_clock(clock, bpc, ycbcr420_output);
+ int tmds_clock = intel_hdmi_tmds_clock(clock, bpc,
+ crtc_state->sink_format);
if (hdmi_bpc_possible(crtc_state, bpc) &&
hdmi_port_clock_valid(intel_hdmi, tmds_clock,
@@ -2108,7 +2123,7 @@ static int intel_hdmi_compute_clock(struct intel_encoder *encoder,
return bpc;
crtc_state->port_clock =
- intel_hdmi_tmds_clock(clock, bpc, intel_hdmi_is_ycbcr420(crtc_state));
+ intel_hdmi_tmds_clock(clock, bpc, crtc_state->sink_format);
/*
* pipe_bpp could already be below 8bpc due to
@@ -2156,7 +2171,7 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
- struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+ struct drm_connector *connector = conn_state->connector;
const struct intel_digital_connector_state *intel_conn_state =
to_intel_digital_connector_state(conn_state);
@@ -2164,15 +2179,15 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
return false;
if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
- return intel_hdmi->has_audio;
+ return connector->display_info.has_audio;
else
return intel_conn_state->force_audio == HDMI_AUDIO_ON;
}
static enum intel_output_format
-intel_hdmi_output_format(const struct intel_crtc_state *crtc_state,
- struct intel_connector *connector,
- bool ycbcr_420_output)
+intel_hdmi_sink_format(const struct intel_crtc_state *crtc_state,
+ struct intel_connector *connector,
+ bool ycbcr_420_output)
{
if (!crtc_state->has_hdmi_sink)
return INTEL_OUTPUT_FORMAT_RGB;
@@ -2183,6 +2198,12 @@ intel_hdmi_output_format(const struct intel_crtc_state *crtc_state,
return INTEL_OUTPUT_FORMAT_RGB;
}
+static enum intel_output_format
+intel_hdmi_output_format(const struct intel_crtc_state *crtc_state)
+{
+ return crtc_state->sink_format;
+}
+
static int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state,
@@ -2195,23 +2216,26 @@ static int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
bool ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode);
int ret;
- crtc_state->output_format =
- intel_hdmi_output_format(crtc_state, connector, ycbcr_420_only);
+ crtc_state->sink_format =
+ intel_hdmi_sink_format(crtc_state, connector, ycbcr_420_only);
- if (ycbcr_420_only && !intel_hdmi_is_ycbcr420(crtc_state)) {
+ if (ycbcr_420_only && crtc_state->sink_format != INTEL_OUTPUT_FORMAT_YCBCR420) {
drm_dbg_kms(&i915->drm,
"YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n");
- crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
+ crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB;
}
+ crtc_state->output_format = intel_hdmi_output_format(crtc_state);
ret = intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits);
if (ret) {
- if (intel_hdmi_is_ycbcr420(crtc_state) ||
+ if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
+ !crtc_state->has_hdmi_sink ||
!connector->base.ycbcr_420_allowed ||
!drm_mode_is_420_also(info, adjusted_mode))
return ret;
- crtc_state->output_format = intel_hdmi_output_format(crtc_state, connector, true);
+ crtc_state->sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+ crtc_state->output_format = intel_hdmi_output_format(crtc_state);
ret = intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits);
}
@@ -2243,11 +2267,20 @@ static bool source_supports_scrambling(struct intel_encoder *encoder)
return intel_hdmi_source_max_tmds_clock(encoder) > 340000;
}
+bool intel_hdmi_compute_has_hdmi_sink(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
+{
+ struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder);
+
+ return intel_has_hdmi_sink(hdmi, conn_state) &&
+ !intel_hdmi_is_cloned(crtc_state);
+}
+
int intel_hdmi_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
- struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
struct drm_connector *connector = conn_state->connector;
@@ -2262,9 +2295,6 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
return -EINVAL;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
- pipe_config->has_hdmi_sink =
- intel_has_hdmi_sink(intel_hdmi, conn_state) &&
- !intel_hdmi_is_cloned(pipe_config);
if (pipe_config->has_hdmi_sink)
pipe_config->has_infoframe = true;
@@ -2357,9 +2387,6 @@ intel_hdmi_unset_edid(struct drm_connector *connector)
{
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector));
- intel_hdmi->has_hdmi_sink = false;
- intel_hdmi->has_audio = false;
-
intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE;
intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
@@ -2372,7 +2399,7 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector)
{
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector));
- enum port port = hdmi_to_dig_port(hdmi)->base.port;
+ struct intel_encoder *encoder = &hdmi_to_dig_port(hdmi)->base;
struct i2c_adapter *adapter =
intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
enum drm_dp_dual_mode_type type = drm_dp_dual_mode_detect(&dev_priv->drm, adapter);
@@ -2388,7 +2415,7 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector)
*/
if (type == DRM_DP_DUAL_MODE_UNKNOWN) {
if (!connector->force &&
- intel_bios_is_port_dp_dual_mode(dev_priv, port)) {
+ intel_bios_encoder_supports_dp_dual_mode(encoder->devdata)) {
drm_dbg_kms(&dev_priv->drm,
"Assuming DP dual mode adaptor presence based on VBT\n");
type = DRM_DP_DUAL_MODE_TYPE1_DVI;
@@ -2411,7 +2438,7 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector)
/* Older VBTs are often buggy and can't be trusted :( Play it safe. */
if ((DISPLAY_VER(dev_priv) >= 8 || IS_HASWELL(dev_priv)) &&
- !intel_bios_is_port_dp_dual_mode(dev_priv, port)) {
+ !intel_bios_encoder_supports_dp_dual_mode(encoder->devdata)) {
drm_dbg_kms(&dev_priv->drm,
"Ignoring DP dual mode adaptor max TMDS clock for native HDMI port\n");
hdmi->dp_dual_mode.max_tmds_clock = 0;
@@ -2451,9 +2478,6 @@ intel_hdmi_set_edid(struct drm_connector *connector)
/* FIXME: Get rid of drm_edid_raw() */
edid = drm_edid_raw(drm_edid);
if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
- intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
- intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
-
intel_hdmi_dp_dual_mode_detect(connector);
connected = true;
@@ -2597,10 +2621,21 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
.atomic_duplicate_state = intel_digital_connector_duplicate_state,
};
+static int intel_hdmi_connector_atomic_check(struct drm_connector *connector,
+ struct drm_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->dev);
+
+ if (HAS_DDI(i915))
+ return intel_digital_connector_atomic_check(connector, state);
+ else
+ return g4x_hdmi_connector_atomic_check(connector, state);
+}
+
static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = {
.get_modes = intel_hdmi_get_modes,
.mode_valid = intel_hdmi_mode_valid,
- .atomic_check = intel_digital_connector_atomic_check,
+ .atomic_check = intel_hdmi_connector_atomic_check,
};
static void
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h
index 774dda2376ed..6b39df38d57a 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.h
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.h
@@ -9,6 +9,7 @@
#include <linux/types.h>
enum hdmi_infoframe_type;
+enum intel_output_format;
enum port;
struct drm_connector;
struct drm_connector_state;
@@ -23,6 +24,9 @@ union hdmi_infoframe;
void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
struct intel_connector *intel_connector);
+bool intel_hdmi_compute_has_hdmi_sink(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state);
int intel_hdmi_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state);
@@ -45,8 +49,8 @@ void intel_read_infoframe(struct intel_encoder *encoder,
bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
- int bpc, bool has_hdmi_sink, bool ycbcr420_output);
-int intel_hdmi_tmds_clock(int clock, int bpc, bool ycbcr420_output);
+ int bpc, bool has_hdmi_sink);
+int intel_hdmi_tmds_clock(int clock, int bpc, enum intel_output_format sink_format);
int intel_hdmi_dsc_get_bpp(int src_fractional_bpp, int slice_width,
int num_slices, int output_format, bool hdmi_all_bpp,
int hdmi_max_chunk_bytes);
@@ -54,5 +58,6 @@ int intel_hdmi_dsc_get_num_slices(const struct intel_crtc_state *crtc_state,
int src_max_slices, int src_max_slice_width,
int hdmi_max_slices, int hdmi_throughput);
int intel_hdmi_dsc_get_slice_height(int vactive);
+struct drm_i915_private *intel_hdmi_to_i915(struct intel_hdmi *intel_hdmi);
#endif /* __INTEL_HDMI_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c
index b12900446828..1160fa20433b 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.c
@@ -27,6 +27,7 @@
#include "i915_irq.h"
#include "intel_display_types.h"
#include "intel_hotplug.h"
+#include "intel_hotplug_irq.h"
/**
* DOC: Hotplug
@@ -211,7 +212,8 @@ intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv)
/* Enable polling and queue hotplug re-enabling. */
if (hpd_disabled) {
drm_kms_helper_poll_enable(&dev_priv->drm);
- mod_delayed_work(system_wq, &dev_priv->display.hotplug.reenable_work,
+ mod_delayed_work(dev_priv->unordered_wq,
+ &dev_priv->display.hotplug.reenable_work,
msecs_to_jiffies(HPD_STORM_REENABLE_DELAY));
}
}
@@ -338,7 +340,8 @@ static void i915_digport_work_func(struct work_struct *work)
spin_lock_irq(&dev_priv->irq_lock);
dev_priv->display.hotplug.event_bits |= old_bits;
spin_unlock_irq(&dev_priv->irq_lock);
- queue_delayed_work(system_wq, &dev_priv->display.hotplug.hotplug_work, 0);
+ queue_delayed_work(dev_priv->unordered_wq,
+ &dev_priv->display.hotplug.hotplug_work, 0);
}
}
@@ -445,7 +448,8 @@ static void i915_hotplug_work_func(struct work_struct *work)
dev_priv->display.hotplug.retry_bits |= retry;
spin_unlock_irq(&dev_priv->irq_lock);
- mod_delayed_work(system_wq, &dev_priv->display.hotplug.hotplug_work,
+ mod_delayed_work(dev_priv->unordered_wq,
+ &dev_priv->display.hotplug.hotplug_work,
msecs_to_jiffies(HPD_RETRY_DELAY));
}
}
@@ -576,7 +580,8 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
if (queue_dig)
queue_work(dev_priv->display.hotplug.dp_wq, &dev_priv->display.hotplug.dig_port_work);
if (queue_hp)
- queue_delayed_work(system_wq, &dev_priv->display.hotplug.hotplug_work, 0);
+ queue_delayed_work(dev_priv->unordered_wq,
+ &dev_priv->display.hotplug.hotplug_work, 0);
}
/**
@@ -686,7 +691,8 @@ void intel_hpd_poll_enable(struct drm_i915_private *dev_priv)
* As well, there's no issue if we race here since we always reschedule
* this worker anyway
*/
- schedule_work(&dev_priv->display.hotplug.poll_init_work);
+ queue_work(dev_priv->unordered_wq,
+ &dev_priv->display.hotplug.poll_init_work);
}
/**
@@ -714,7 +720,8 @@ void intel_hpd_poll_disable(struct drm_i915_private *dev_priv)
return;
WRITE_ONCE(dev_priv->display.hotplug.poll_enabled, false);
- schedule_work(&dev_priv->display.hotplug.poll_init_work);
+ queue_work(dev_priv->unordered_wq,
+ &dev_priv->display.hotplug.poll_init_work);
}
void intel_hpd_init_early(struct drm_i915_private *i915)
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
new file mode 100644
index 000000000000..f95fa793fabb
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
@@ -0,0 +1,1442 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "i915_reg.h"
+#include "intel_de.h"
+#include "intel_display_irq.h"
+#include "intel_display_types.h"
+#include "intel_dp_aux.h"
+#include "intel_gmbus.h"
+#include "intel_hotplug.h"
+#include "intel_hotplug_irq.h"
+
+typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val);
+typedef u32 (*hotplug_enables_func)(struct intel_encoder *encoder);
+typedef u32 (*hotplug_mask_func)(enum hpd_pin pin);
+
+static const u32 hpd_ilk[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = DE_DP_A_HOTPLUG,
+};
+
+static const u32 hpd_ivb[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB,
+};
+
+static const u32 hpd_bdw[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A),
+};
+
+static const u32 hpd_ibx[HPD_NUM_PINS] = {
+ [HPD_CRT] = SDE_CRT_HOTPLUG,
+ [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
+ [HPD_PORT_B] = SDE_PORTB_HOTPLUG,
+ [HPD_PORT_C] = SDE_PORTC_HOTPLUG,
+ [HPD_PORT_D] = SDE_PORTD_HOTPLUG,
+};
+
+static const u32 hpd_cpt[HPD_NUM_PINS] = {
+ [HPD_CRT] = SDE_CRT_HOTPLUG_CPT,
+ [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT,
+ [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
+ [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
+ [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
+};
+
+static const u32 hpd_spt[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT,
+ [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
+ [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
+ [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
+ [HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT,
+};
+
+static const u32 hpd_mask_i915[HPD_NUM_PINS] = {
+ [HPD_CRT] = CRT_HOTPLUG_INT_EN,
+ [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
+ [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN,
+ [HPD_PORT_B] = PORTB_HOTPLUG_INT_EN,
+ [HPD_PORT_C] = PORTC_HOTPLUG_INT_EN,
+ [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN,
+};
+
+static const u32 hpd_status_g4x[HPD_NUM_PINS] = {
+ [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
+ [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
+ [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
+ [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
+ [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
+ [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS,
+};
+
+static const u32 hpd_status_i915[HPD_NUM_PINS] = {
+ [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
+ [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
+ [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915,
+ [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
+ [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
+ [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS,
+};
+
+static const u32 hpd_bxt[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A),
+ [HPD_PORT_B] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_B),
+ [HPD_PORT_C] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_C),
+};
+
+static const u32 hpd_gen11[HPD_NUM_PINS] = {
+ [HPD_PORT_TC1] = GEN11_TC_HOTPLUG(HPD_PORT_TC1) | GEN11_TBT_HOTPLUG(HPD_PORT_TC1),
+ [HPD_PORT_TC2] = GEN11_TC_HOTPLUG(HPD_PORT_TC2) | GEN11_TBT_HOTPLUG(HPD_PORT_TC2),
+ [HPD_PORT_TC3] = GEN11_TC_HOTPLUG(HPD_PORT_TC3) | GEN11_TBT_HOTPLUG(HPD_PORT_TC3),
+ [HPD_PORT_TC4] = GEN11_TC_HOTPLUG(HPD_PORT_TC4) | GEN11_TBT_HOTPLUG(HPD_PORT_TC4),
+ [HPD_PORT_TC5] = GEN11_TC_HOTPLUG(HPD_PORT_TC5) | GEN11_TBT_HOTPLUG(HPD_PORT_TC5),
+ [HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | GEN11_TBT_HOTPLUG(HPD_PORT_TC6),
+};
+
+static const u32 hpd_xelpdp[HPD_NUM_PINS] = {
+ [HPD_PORT_TC1] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC1) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC1),
+ [HPD_PORT_TC2] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC2) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC2),
+ [HPD_PORT_TC3] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC3) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC3),
+ [HPD_PORT_TC4] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC4) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC4),
+};
+
+static const u32 hpd_icp[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
+ [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
+ [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C),
+ [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
+ [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
+ [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
+ [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
+ [HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC5),
+ [HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC6),
+};
+
+static const u32 hpd_sde_dg1[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
+ [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
+ [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C),
+ [HPD_PORT_D] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_D),
+ [HPD_PORT_TC1] = SDE_TC_HOTPLUG_DG2(HPD_PORT_TC1),
+};
+
+static const u32 hpd_mtp[HPD_NUM_PINS] = {
+ [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
+ [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
+ [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
+ [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
+ [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
+ [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
+};
+
+static void intel_hpd_init_pins(struct drm_i915_private *dev_priv)
+{
+ struct intel_hotplug *hpd = &dev_priv->display.hotplug;
+
+ if (HAS_GMCH(dev_priv)) {
+ if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
+ IS_CHERRYVIEW(dev_priv))
+ hpd->hpd = hpd_status_g4x;
+ else
+ hpd->hpd = hpd_status_i915;
+ return;
+ }
+
+ if (DISPLAY_VER(dev_priv) >= 14)
+ hpd->hpd = hpd_xelpdp;
+ else if (DISPLAY_VER(dev_priv) >= 11)
+ hpd->hpd = hpd_gen11;
+ else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
+ hpd->hpd = hpd_bxt;
+ else if (DISPLAY_VER(dev_priv) == 9)
+ hpd->hpd = NULL; /* no north HPD on SKL */
+ else if (DISPLAY_VER(dev_priv) >= 8)
+ hpd->hpd = hpd_bdw;
+ else if (DISPLAY_VER(dev_priv) >= 7)
+ hpd->hpd = hpd_ivb;
+ else
+ hpd->hpd = hpd_ilk;
+
+ if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) &&
+ (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)))
+ return;
+
+ if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
+ hpd->pch_hpd = hpd_sde_dg1;
+ else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
+ hpd->pch_hpd = hpd_mtp;
+ else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
+ hpd->pch_hpd = hpd_icp;
+ else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv))
+ hpd->pch_hpd = hpd_spt;
+ else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_CPT(dev_priv))
+ hpd->pch_hpd = hpd_cpt;
+ else if (HAS_PCH_IBX(dev_priv))
+ hpd->pch_hpd = hpd_ibx;
+ else
+ MISSING_CASE(INTEL_PCH_TYPE(dev_priv));
+}
+
+/* For display hotplug interrupt */
+void i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv,
+ u32 mask, u32 bits)
+{
+ lockdep_assert_held(&dev_priv->irq_lock);
+ drm_WARN_ON(&dev_priv->drm, bits & ~mask);
+
+ intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_EN, mask, bits);
+}
+
+/**
+ * i915_hotplug_interrupt_update - update hotplug interrupt enable
+ * @dev_priv: driver private
+ * @mask: bits to update
+ * @bits: bits to enable
+ * NOTE: the HPD enable bits are modified both inside and outside
+ * of an interrupt context. To avoid that read-modify-write cycles
+ * interfer, these bits are protected by a spinlock. Since this
+ * function is usually not called from a context where the lock is
+ * held already, this function acquires the lock itself. A non-locking
+ * version is also available.
+ */
+void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
+ u32 mask,
+ u32 bits)
+{
+ spin_lock_irq(&dev_priv->irq_lock);
+ i915_hotplug_interrupt_update_locked(dev_priv, mask, bits);
+ spin_unlock_irq(&dev_priv->irq_lock);
+}
+
+static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
+{
+ switch (pin) {
+ case HPD_PORT_TC1:
+ case HPD_PORT_TC2:
+ case HPD_PORT_TC3:
+ case HPD_PORT_TC4:
+ case HPD_PORT_TC5:
+ case HPD_PORT_TC6:
+ return val & GEN11_HOTPLUG_CTL_LONG_DETECT(pin);
+ default:
+ return false;
+ }
+}
+
+static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
+{
+ switch (pin) {
+ case HPD_PORT_A:
+ return val & PORTA_HOTPLUG_LONG_DETECT;
+ case HPD_PORT_B:
+ return val & PORTB_HOTPLUG_LONG_DETECT;
+ case HPD_PORT_C:
+ return val & PORTC_HOTPLUG_LONG_DETECT;
+ default:
+ return false;
+ }
+}
+
+static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
+{
+ switch (pin) {
+ case HPD_PORT_A:
+ case HPD_PORT_B:
+ case HPD_PORT_C:
+ case HPD_PORT_D:
+ return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(pin);
+ default:
+ return false;
+ }
+}
+
+static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
+{
+ switch (pin) {
+ case HPD_PORT_TC1:
+ case HPD_PORT_TC2:
+ case HPD_PORT_TC3:
+ case HPD_PORT_TC4:
+ case HPD_PORT_TC5:
+ case HPD_PORT_TC6:
+ return val & ICP_TC_HPD_LONG_DETECT(pin);
+ default:
+ return false;
+ }
+}
+
+static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val)
+{
+ switch (pin) {
+ case HPD_PORT_E:
+ return val & PORTE_HOTPLUG_LONG_DETECT;
+ default:
+ return false;
+ }
+}
+
+static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
+{
+ switch (pin) {
+ case HPD_PORT_A:
+ return val & PORTA_HOTPLUG_LONG_DETECT;
+ case HPD_PORT_B:
+ return val & PORTB_HOTPLUG_LONG_DETECT;
+ case HPD_PORT_C:
+ return val & PORTC_HOTPLUG_LONG_DETECT;
+ case HPD_PORT_D:
+ return val & PORTD_HOTPLUG_LONG_DETECT;
+ default:
+ return false;
+ }
+}
+
+static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
+{
+ switch (pin) {
+ case HPD_PORT_A:
+ return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT;
+ default:
+ return false;
+ }
+}
+
+static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
+{
+ switch (pin) {
+ case HPD_PORT_B:
+ return val & PORTB_HOTPLUG_LONG_DETECT;
+ case HPD_PORT_C:
+ return val & PORTC_HOTPLUG_LONG_DETECT;
+ case HPD_PORT_D:
+ return val & PORTD_HOTPLUG_LONG_DETECT;
+ default:
+ return false;
+ }
+}
+
+static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
+{
+ switch (pin) {
+ case HPD_PORT_B:
+ return val & PORTB_HOTPLUG_INT_LONG_PULSE;
+ case HPD_PORT_C:
+ return val & PORTC_HOTPLUG_INT_LONG_PULSE;
+ case HPD_PORT_D:
+ return val & PORTD_HOTPLUG_INT_LONG_PULSE;
+ default:
+ return false;
+ }
+}
+
+/*
+ * Get a bit mask of pins that have triggered, and which ones may be long.
+ * This can be called multiple times with the same masks to accumulate
+ * hotplug detection results from several registers.
+ *
+ * Note that the caller is expected to zero out the masks initially.
+ */
+static void intel_get_hpd_pins(struct drm_i915_private *dev_priv,
+ u32 *pin_mask, u32 *long_mask,
+ u32 hotplug_trigger, u32 dig_hotplug_reg,
+ const u32 hpd[HPD_NUM_PINS],
+ bool long_pulse_detect(enum hpd_pin pin, u32 val))
+{
+ enum hpd_pin pin;
+
+ BUILD_BUG_ON(BITS_PER_TYPE(*pin_mask) < HPD_NUM_PINS);
+
+ for_each_hpd_pin(pin) {
+ if ((hpd[pin] & hotplug_trigger) == 0)
+ continue;
+
+ *pin_mask |= BIT(pin);
+
+ if (long_pulse_detect(pin, dig_hotplug_reg))
+ *long_mask |= BIT(pin);
+ }
+
+ drm_dbg(&dev_priv->drm,
+ "hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n",
+ hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask);
+}
+
+static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv,
+ const u32 hpd[HPD_NUM_PINS])
+{
+ struct intel_encoder *encoder;
+ u32 enabled_irqs = 0;
+
+ for_each_intel_encoder(&dev_priv->drm, encoder)
+ if (dev_priv->display.hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED)
+ enabled_irqs |= hpd[encoder->hpd_pin];
+
+ return enabled_irqs;
+}
+
+static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv,
+ const u32 hpd[HPD_NUM_PINS])
+{
+ struct intel_encoder *encoder;
+ u32 hotplug_irqs = 0;
+
+ for_each_intel_encoder(&dev_priv->drm, encoder)
+ hotplug_irqs |= hpd[encoder->hpd_pin];
+
+ return hotplug_irqs;
+}
+
+static u32 intel_hpd_hotplug_mask(struct drm_i915_private *i915,
+ hotplug_mask_func hotplug_mask)
+{
+ enum hpd_pin pin;
+ u32 hotplug = 0;
+
+ for_each_hpd_pin(pin)
+ hotplug |= hotplug_mask(pin);
+
+ return hotplug;
+}
+
+static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915,
+ hotplug_enables_func hotplug_enables)
+{
+ struct intel_encoder *encoder;
+ u32 hotplug = 0;
+
+ for_each_intel_encoder(&i915->drm, encoder)
+ hotplug |= hotplug_enables(encoder);
+
+ return hotplug;
+}
+
+u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv)
+{
+ u32 hotplug_status = 0, hotplug_status_mask;
+ int i;
+
+ if (IS_G4X(dev_priv) ||
+ IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+ hotplug_status_mask = HOTPLUG_INT_STATUS_G4X |
+ DP_AUX_CHANNEL_MASK_INT_STATUS_G4X;
+ else
+ hotplug_status_mask = HOTPLUG_INT_STATUS_I915;
+
+ /*
+ * We absolutely have to clear all the pending interrupt
+ * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port
+ * interrupt bit won't have an edge, and the i965/g4x
+ * edge triggered IIR will not notice that an interrupt
+ * is still pending. We can't use PORT_HOTPLUG_EN to
+ * guarantee the edge as the act of toggling the enable
+ * bits can itself generate a new hotplug interrupt :(
+ */
+ for (i = 0; i < 10; i++) {
+ u32 tmp = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT) & hotplug_status_mask;
+
+ if (tmp == 0)
+ return hotplug_status;
+
+ hotplug_status |= tmp;
+ intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, hotplug_status);
+ }
+
+ drm_WARN_ONCE(&dev_priv->drm, 1,
+ "PORT_HOTPLUG_STAT did not clear (0x%08x)\n",
+ intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT));
+
+ return hotplug_status;
+}
+
+void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_status)
+{
+ u32 pin_mask = 0, long_mask = 0;
+ u32 hotplug_trigger;
+
+ if (IS_G4X(dev_priv) ||
+ IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+ hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
+ else
+ hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
+
+ if (hotplug_trigger) {
+ intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
+ hotplug_trigger, hotplug_trigger,
+ dev_priv->display.hotplug.hpd,
+ i9xx_port_hotplug_long_detect);
+
+ intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
+ }
+
+ if ((IS_G4X(dev_priv) ||
+ IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+ hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
+ intel_dp_aux_irq_handler(dev_priv);
+}
+
+void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_trigger)
+{
+ u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
+
+ /*
+ * Somehow the PCH doesn't seem to really ack the interrupt to the CPU
+ * unless we touch the hotplug register, even if hotplug_trigger is
+ * zero. Not acking leads to "The master control interrupt lied (SDE)!"
+ * errors.
+ */
+ dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG);
+ if (!hotplug_trigger) {
+ u32 mask = PORTA_HOTPLUG_STATUS_MASK |
+ PORTD_HOTPLUG_STATUS_MASK |
+ PORTC_HOTPLUG_STATUS_MASK |
+ PORTB_HOTPLUG_STATUS_MASK;
+ dig_hotplug_reg &= ~mask;
+ }
+
+ intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg);
+ if (!hotplug_trigger)
+ return;
+
+ intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
+ hotplug_trigger, dig_hotplug_reg,
+ dev_priv->display.hotplug.pch_hpd,
+ pch_port_hotplug_long_detect);
+
+ intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
+}
+
+void xelpdp_pica_irq_handler(struct drm_i915_private *i915, u32 iir)
+{
+ enum hpd_pin pin;
+ u32 hotplug_trigger = iir & (XELPDP_DP_ALT_HOTPLUG_MASK | XELPDP_TBT_HOTPLUG_MASK);
+ u32 trigger_aux = iir & XELPDP_AUX_TC_MASK;
+ u32 pin_mask = 0, long_mask = 0;
+
+ for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
+ u32 val;
+
+ if (!(i915->display.hotplug.hpd[pin] & hotplug_trigger))
+ continue;
+
+ pin_mask |= BIT(pin);
+
+ val = intel_de_read(i915, XELPDP_PORT_HOTPLUG_CTL(pin));
+ intel_de_write(i915, XELPDP_PORT_HOTPLUG_CTL(pin), val);
+
+ if (val & (XELPDP_DP_ALT_HPD_LONG_DETECT | XELPDP_TBT_HPD_LONG_DETECT))
+ long_mask |= BIT(pin);
+ }
+
+ if (pin_mask) {
+ drm_dbg(&i915->drm,
+ "pica hotplug event received, stat 0x%08x, pins 0x%08x, long 0x%08x\n",
+ hotplug_trigger, pin_mask, long_mask);
+
+ intel_hpd_irq_handler(i915, pin_mask, long_mask);
+ }
+
+ if (trigger_aux)
+ intel_dp_aux_irq_handler(i915);
+
+ if (!pin_mask && !trigger_aux)
+ drm_err(&i915->drm,
+ "Unexpected DE HPD/AUX interrupt 0x%08x\n", iir);
+}
+
+void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
+{
+ u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP;
+ u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP;
+ u32 pin_mask = 0, long_mask = 0;
+
+ if (ddi_hotplug_trigger) {
+ u32 dig_hotplug_reg;
+
+ /* Locking due to DSI native GPIO sequences */
+ spin_lock(&dev_priv->irq_lock);
+ dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0);
+ spin_unlock(&dev_priv->irq_lock);
+
+ intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
+ ddi_hotplug_trigger, dig_hotplug_reg,
+ dev_priv->display.hotplug.pch_hpd,
+ icp_ddi_port_hotplug_long_detect);
+ }
+
+ if (tc_hotplug_trigger) {
+ u32 dig_hotplug_reg;
+
+ dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC, 0, 0);
+
+ intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
+ tc_hotplug_trigger, dig_hotplug_reg,
+ dev_priv->display.hotplug.pch_hpd,
+ icp_tc_port_hotplug_long_detect);
+ }
+
+ if (pin_mask)
+ intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
+
+ if (pch_iir & SDE_GMBUS_ICP)
+ intel_gmbus_irq_handler(dev_priv);
+}
+
+void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
+{
+ u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT &
+ ~SDE_PORTE_HOTPLUG_SPT;
+ u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT;
+ u32 pin_mask = 0, long_mask = 0;
+
+ if (hotplug_trigger) {
+ u32 dig_hotplug_reg;
+
+ dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0);
+
+ intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
+ hotplug_trigger, dig_hotplug_reg,
+ dev_priv->display.hotplug.pch_hpd,
+ spt_port_hotplug_long_detect);
+ }
+
+ if (hotplug2_trigger) {
+ u32 dig_hotplug_reg;
+
+ dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, 0, 0);
+
+ intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
+ hotplug2_trigger, dig_hotplug_reg,
+ dev_priv->display.hotplug.pch_hpd,
+ spt_port_hotplug2_long_detect);
+ }
+
+ if (pin_mask)
+ intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
+
+ if (pch_iir & SDE_GMBUS_CPT)
+ intel_gmbus_irq_handler(dev_priv);
+}
+
+void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_trigger)
+{
+ u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
+
+ dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, 0, 0);
+
+ intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
+ hotplug_trigger, dig_hotplug_reg,
+ dev_priv->display.hotplug.hpd,
+ ilk_port_hotplug_long_detect);
+
+ intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
+}
+
+void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_trigger)
+{
+ u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
+
+ dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0);
+
+ intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
+ hotplug_trigger, dig_hotplug_reg,
+ dev_priv->display.hotplug.hpd,
+ bxt_port_hotplug_long_detect);
+
+ intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
+}
+
+void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
+{
+ u32 pin_mask = 0, long_mask = 0;
+ u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK;
+ u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK;
+
+ if (trigger_tc) {
+ u32 dig_hotplug_reg;
+
+ dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, 0, 0);
+
+ intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
+ trigger_tc, dig_hotplug_reg,
+ dev_priv->display.hotplug.hpd,
+ gen11_port_hotplug_long_detect);
+ }
+
+ if (trigger_tbt) {
+ u32 dig_hotplug_reg;
+
+ dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, 0, 0);
+
+ intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
+ trigger_tbt, dig_hotplug_reg,
+ dev_priv->display.hotplug.hpd,
+ gen11_port_hotplug_long_detect);
+ }
+
+ if (pin_mask)
+ intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
+ else
+ drm_err(&dev_priv->drm,
+ "Unexpected DE HPD interrupt 0x%08x\n", iir);
+}
+
+static u32 ibx_hotplug_mask(enum hpd_pin hpd_pin)
+{
+ switch (hpd_pin) {
+ case HPD_PORT_A:
+ return PORTA_HOTPLUG_ENABLE;
+ case HPD_PORT_B:
+ return PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_MASK;
+ case HPD_PORT_C:
+ return PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_MASK;
+ case HPD_PORT_D:
+ return PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_MASK;
+ default:
+ return 0;
+ }
+}
+
+static u32 ibx_hotplug_enables(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ switch (encoder->hpd_pin) {
+ case HPD_PORT_A:
+ /*
+ * When CPU and PCH are on the same package, port A
+ * HPD must be enabled in both north and south.
+ */
+ return HAS_PCH_LPT_LP(i915) ?
+ PORTA_HOTPLUG_ENABLE : 0;
+ case HPD_PORT_B:
+ return PORTB_HOTPLUG_ENABLE |
+ PORTB_PULSE_DURATION_2ms;
+ case HPD_PORT_C:
+ return PORTC_HOTPLUG_ENABLE |
+ PORTC_PULSE_DURATION_2ms;
+ case HPD_PORT_D:
+ return PORTD_HOTPLUG_ENABLE |
+ PORTD_PULSE_DURATION_2ms;
+ default:
+ return 0;
+ }
+}
+
+static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
+{
+ /*
+ * Enable digital hotplug on the PCH, and configure the DP short pulse
+ * duration to 2ms (which is the minimum in the Display Port spec).
+ * The pulse duration bits are reserved on LPT+.
+ */
+ intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
+ intel_hpd_hotplug_mask(dev_priv, ibx_hotplug_mask),
+ intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables));
+}
+
+static void ibx_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
+ ibx_hotplug_mask(encoder->hpd_pin),
+ ibx_hotplug_enables(encoder));
+}
+
+static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
+{
+ u32 hotplug_irqs, enabled_irqs;
+
+ enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
+ hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
+
+ ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
+
+ ibx_hpd_detection_setup(dev_priv);
+}
+
+static u32 icp_ddi_hotplug_mask(enum hpd_pin hpd_pin)
+{
+ switch (hpd_pin) {
+ case HPD_PORT_A:
+ case HPD_PORT_B:
+ case HPD_PORT_C:
+ case HPD_PORT_D:
+ return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin);
+ default:
+ return 0;
+ }
+}
+
+static u32 icp_ddi_hotplug_enables(struct intel_encoder *encoder)
+{
+ return icp_ddi_hotplug_mask(encoder->hpd_pin);
+}
+
+static u32 icp_tc_hotplug_mask(enum hpd_pin hpd_pin)
+{
+ switch (hpd_pin) {
+ case HPD_PORT_TC1:
+ case HPD_PORT_TC2:
+ case HPD_PORT_TC3:
+ case HPD_PORT_TC4:
+ case HPD_PORT_TC5:
+ case HPD_PORT_TC6:
+ return ICP_TC_HPD_ENABLE(hpd_pin);
+ default:
+ return 0;
+ }
+}
+
+static u32 icp_tc_hotplug_enables(struct intel_encoder *encoder)
+{
+ return icp_tc_hotplug_mask(encoder->hpd_pin);
+}
+
+static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv)
+{
+ intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI,
+ intel_hpd_hotplug_mask(dev_priv, icp_ddi_hotplug_mask),
+ intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables));
+}
+
+static void icp_ddi_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, SHOTPLUG_CTL_DDI,
+ icp_ddi_hotplug_mask(encoder->hpd_pin),
+ icp_ddi_hotplug_enables(encoder));
+}
+
+static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
+{
+ intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC,
+ intel_hpd_hotplug_mask(dev_priv, icp_tc_hotplug_mask),
+ intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables));
+}
+
+static void icp_tc_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, SHOTPLUG_CTL_TC,
+ icp_tc_hotplug_mask(encoder->hpd_pin),
+ icp_tc_hotplug_enables(encoder));
+}
+
+static void icp_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ icp_ddi_hpd_enable_detection(encoder);
+ icp_tc_hpd_enable_detection(encoder);
+}
+
+static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv)
+{
+ u32 hotplug_irqs, enabled_irqs;
+
+ enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
+ hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
+
+ if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP)
+ intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
+
+ ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
+
+ icp_ddi_hpd_detection_setup(dev_priv);
+ icp_tc_hpd_detection_setup(dev_priv);
+}
+
+static u32 gen11_hotplug_mask(enum hpd_pin hpd_pin)
+{
+ switch (hpd_pin) {
+ case HPD_PORT_TC1:
+ case HPD_PORT_TC2:
+ case HPD_PORT_TC3:
+ case HPD_PORT_TC4:
+ case HPD_PORT_TC5:
+ case HPD_PORT_TC6:
+ return GEN11_HOTPLUG_CTL_ENABLE(hpd_pin);
+ default:
+ return 0;
+ }
+}
+
+static u32 gen11_hotplug_enables(struct intel_encoder *encoder)
+{
+ return gen11_hotplug_mask(encoder->hpd_pin);
+}
+
+static void dg1_hpd_invert(struct drm_i915_private *i915)
+{
+ u32 val = (INVERT_DDIA_HPD |
+ INVERT_DDIB_HPD |
+ INVERT_DDIC_HPD |
+ INVERT_DDID_HPD);
+ intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1, 0, val);
+}
+
+static void dg1_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ dg1_hpd_invert(i915);
+ icp_hpd_enable_detection(encoder);
+}
+
+static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv)
+{
+ dg1_hpd_invert(dev_priv);
+ icp_hpd_irq_setup(dev_priv);
+}
+
+static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
+{
+ intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL,
+ intel_hpd_hotplug_mask(dev_priv, gen11_hotplug_mask),
+ intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
+}
+
+static void gen11_tc_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, GEN11_TC_HOTPLUG_CTL,
+ gen11_hotplug_mask(encoder->hpd_pin),
+ gen11_hotplug_enables(encoder));
+}
+
+static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv)
+{
+ intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL,
+ intel_hpd_hotplug_mask(dev_priv, gen11_hotplug_mask),
+ intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
+}
+
+static void gen11_tbt_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, GEN11_TBT_HOTPLUG_CTL,
+ gen11_hotplug_mask(encoder->hpd_pin),
+ gen11_hotplug_enables(encoder));
+}
+
+static void gen11_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ gen11_tc_hpd_enable_detection(encoder);
+ gen11_tbt_hpd_enable_detection(encoder);
+
+ if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
+ icp_hpd_enable_detection(encoder);
+}
+
+static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
+{
+ u32 hotplug_irqs, enabled_irqs;
+
+ enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
+ hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
+
+ intel_uncore_rmw(&dev_priv->uncore, GEN11_DE_HPD_IMR, hotplug_irqs,
+ ~enabled_irqs & hotplug_irqs);
+ intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR);
+
+ gen11_tc_hpd_detection_setup(dev_priv);
+ gen11_tbt_hpd_detection_setup(dev_priv);
+
+ if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
+ icp_hpd_irq_setup(dev_priv);
+}
+
+static u32 mtp_ddi_hotplug_mask(enum hpd_pin hpd_pin)
+{
+ switch (hpd_pin) {
+ case HPD_PORT_A:
+ case HPD_PORT_B:
+ return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin);
+ default:
+ return 0;
+ }
+}
+
+static u32 mtp_ddi_hotplug_enables(struct intel_encoder *encoder)
+{
+ return mtp_ddi_hotplug_mask(encoder->hpd_pin);
+}
+
+static u32 mtp_tc_hotplug_mask(enum hpd_pin hpd_pin)
+{
+ switch (hpd_pin) {
+ case HPD_PORT_TC1:
+ case HPD_PORT_TC2:
+ case HPD_PORT_TC3:
+ case HPD_PORT_TC4:
+ return ICP_TC_HPD_ENABLE(hpd_pin);
+ default:
+ return 0;
+ }
+}
+
+static u32 mtp_tc_hotplug_enables(struct intel_encoder *encoder)
+{
+ return mtp_tc_hotplug_mask(encoder->hpd_pin);
+}
+
+static void mtp_ddi_hpd_detection_setup(struct drm_i915_private *i915)
+{
+ intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
+ intel_hpd_hotplug_mask(i915, mtp_ddi_hotplug_mask),
+ intel_hpd_hotplug_enables(i915, mtp_ddi_hotplug_enables));
+}
+
+static void mtp_ddi_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
+ mtp_ddi_hotplug_mask(encoder->hpd_pin),
+ mtp_ddi_hotplug_enables(encoder));
+}
+
+static void mtp_tc_hpd_detection_setup(struct drm_i915_private *i915)
+{
+ intel_de_rmw(i915, SHOTPLUG_CTL_TC,
+ intel_hpd_hotplug_mask(i915, mtp_tc_hotplug_mask),
+ intel_hpd_hotplug_enables(i915, mtp_tc_hotplug_enables));
+}
+
+static void mtp_tc_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
+ mtp_tc_hotplug_mask(encoder->hpd_pin),
+ mtp_tc_hotplug_enables(encoder));
+}
+
+static void mtp_hpd_invert(struct drm_i915_private *i915)
+{
+ u32 val = (INVERT_DDIA_HPD |
+ INVERT_DDIB_HPD |
+ INVERT_DDIC_HPD |
+ INVERT_TC1_HPD |
+ INVERT_TC2_HPD |
+ INVERT_TC3_HPD |
+ INVERT_TC4_HPD |
+ INVERT_DDID_HPD_MTP |
+ INVERT_DDIE_HPD);
+ intel_de_rmw(i915, SOUTH_CHICKEN1, 0, val);
+}
+
+static void mtp_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ mtp_hpd_invert(i915);
+ mtp_ddi_hpd_enable_detection(encoder);
+ mtp_tc_hpd_enable_detection(encoder);
+}
+
+static void mtp_hpd_irq_setup(struct drm_i915_private *i915)
+{
+ u32 hotplug_irqs, enabled_irqs;
+
+ enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.pch_hpd);
+ hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.pch_hpd);
+
+ intel_de_write(i915, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
+
+ mtp_hpd_invert(i915);
+ ibx_display_interrupt_update(i915, hotplug_irqs, enabled_irqs);
+
+ mtp_ddi_hpd_detection_setup(i915);
+ mtp_tc_hpd_detection_setup(i915);
+}
+
+static bool is_xelpdp_pica_hpd_pin(enum hpd_pin hpd_pin)
+{
+ return hpd_pin >= HPD_PORT_TC1 && hpd_pin <= HPD_PORT_TC4;
+}
+
+static void _xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915,
+ enum hpd_pin hpd_pin, bool enable)
+{
+ u32 mask = XELPDP_TBT_HOTPLUG_ENABLE |
+ XELPDP_DP_ALT_HOTPLUG_ENABLE;
+
+ if (!is_xelpdp_pica_hpd_pin(hpd_pin))
+ return;
+
+ intel_de_rmw(i915, XELPDP_PORT_HOTPLUG_CTL(hpd_pin),
+ mask, enable ? mask : 0);
+}
+
+static void xelpdp_pica_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ _xelpdp_pica_hpd_detection_setup(i915, encoder->hpd_pin, true);
+}
+
+static void xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915)
+{
+ struct intel_encoder *encoder;
+ u32 available_pins = 0;
+ enum hpd_pin pin;
+
+ BUILD_BUG_ON(BITS_PER_TYPE(available_pins) < HPD_NUM_PINS);
+
+ for_each_intel_encoder(&i915->drm, encoder)
+ available_pins |= BIT(encoder->hpd_pin);
+
+ for_each_hpd_pin(pin)
+ _xelpdp_pica_hpd_detection_setup(i915, pin, available_pins & BIT(pin));
+}
+
+static void xelpdp_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ xelpdp_pica_hpd_enable_detection(encoder);
+ mtp_hpd_enable_detection(encoder);
+}
+
+static void xelpdp_hpd_irq_setup(struct drm_i915_private *i915)
+{
+ u32 hotplug_irqs, enabled_irqs;
+
+ enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.hpd);
+ hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.hpd);
+
+ intel_de_rmw(i915, PICAINTERRUPT_IMR, hotplug_irqs,
+ ~enabled_irqs & hotplug_irqs);
+ intel_uncore_posting_read(&i915->uncore, PICAINTERRUPT_IMR);
+
+ xelpdp_pica_hpd_detection_setup(i915);
+
+ if (INTEL_PCH_TYPE(i915) >= PCH_MTP)
+ mtp_hpd_irq_setup(i915);
+}
+
+static u32 spt_hotplug_mask(enum hpd_pin hpd_pin)
+{
+ switch (hpd_pin) {
+ case HPD_PORT_A:
+ return PORTA_HOTPLUG_ENABLE;
+ case HPD_PORT_B:
+ return PORTB_HOTPLUG_ENABLE;
+ case HPD_PORT_C:
+ return PORTC_HOTPLUG_ENABLE;
+ case HPD_PORT_D:
+ return PORTD_HOTPLUG_ENABLE;
+ default:
+ return 0;
+ }
+}
+
+static u32 spt_hotplug_enables(struct intel_encoder *encoder)
+{
+ return spt_hotplug_mask(encoder->hpd_pin);
+}
+
+static u32 spt_hotplug2_mask(enum hpd_pin hpd_pin)
+{
+ switch (hpd_pin) {
+ case HPD_PORT_E:
+ return PORTE_HOTPLUG_ENABLE;
+ default:
+ return 0;
+ }
+}
+
+static u32 spt_hotplug2_enables(struct intel_encoder *encoder)
+{
+ return spt_hotplug2_mask(encoder->hpd_pin);
+}
+
+static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
+{
+ /* Display WA #1179 WaHardHangonHotPlug: cnp */
+ if (HAS_PCH_CNP(dev_priv)) {
+ intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK,
+ CHASSIS_CLK_REQ_DURATION(0xf));
+ }
+
+ /* Enable digital hotplug on the PCH */
+ intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
+ intel_hpd_hotplug_mask(dev_priv, spt_hotplug_mask),
+ intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables));
+
+ intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2,
+ intel_hpd_hotplug_mask(dev_priv, spt_hotplug2_mask),
+ intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables));
+}
+
+static void spt_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ /* Display WA #1179 WaHardHangonHotPlug: cnp */
+ if (HAS_PCH_CNP(i915)) {
+ intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1,
+ CHASSIS_CLK_REQ_DURATION_MASK,
+ CHASSIS_CLK_REQ_DURATION(0xf));
+ }
+
+ intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
+ spt_hotplug_mask(encoder->hpd_pin),
+ spt_hotplug_enables(encoder));
+
+ intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG2,
+ spt_hotplug2_mask(encoder->hpd_pin),
+ spt_hotplug2_enables(encoder));
+}
+
+static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
+{
+ u32 hotplug_irqs, enabled_irqs;
+
+ if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
+ intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
+
+ enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
+ hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
+
+ ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
+
+ spt_hpd_detection_setup(dev_priv);
+}
+
+static u32 ilk_hotplug_mask(enum hpd_pin hpd_pin)
+{
+ switch (hpd_pin) {
+ case HPD_PORT_A:
+ return DIGITAL_PORTA_HOTPLUG_ENABLE |
+ DIGITAL_PORTA_PULSE_DURATION_MASK;
+ default:
+ return 0;
+ }
+}
+
+static u32 ilk_hotplug_enables(struct intel_encoder *encoder)
+{
+ switch (encoder->hpd_pin) {
+ case HPD_PORT_A:
+ return DIGITAL_PORTA_HOTPLUG_ENABLE |
+ DIGITAL_PORTA_PULSE_DURATION_2ms;
+ default:
+ return 0;
+ }
+}
+
+static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
+{
+ /*
+ * Enable digital hotplug on the CPU, and configure the DP short pulse
+ * duration to 2ms (which is the minimum in the Display Port spec)
+ * The pulse duration bits are reserved on HSW+.
+ */
+ intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
+ intel_hpd_hotplug_mask(dev_priv, ilk_hotplug_mask),
+ intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables));
+}
+
+static void ilk_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
+ ilk_hotplug_mask(encoder->hpd_pin),
+ ilk_hotplug_enables(encoder));
+
+ ibx_hpd_enable_detection(encoder);
+}
+
+static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
+{
+ u32 hotplug_irqs, enabled_irqs;
+
+ enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
+ hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
+
+ if (DISPLAY_VER(dev_priv) >= 8)
+ bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
+ else
+ ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
+
+ ilk_hpd_detection_setup(dev_priv);
+
+ ibx_hpd_irq_setup(dev_priv);
+}
+
+static u32 bxt_hotplug_mask(enum hpd_pin hpd_pin)
+{
+ switch (hpd_pin) {
+ case HPD_PORT_A:
+ return PORTA_HOTPLUG_ENABLE | BXT_DDIA_HPD_INVERT;
+ case HPD_PORT_B:
+ return PORTB_HOTPLUG_ENABLE | BXT_DDIB_HPD_INVERT;
+ case HPD_PORT_C:
+ return PORTC_HOTPLUG_ENABLE | BXT_DDIC_HPD_INVERT;
+ default:
+ return 0;
+ }
+}
+
+static u32 bxt_hotplug_enables(struct intel_encoder *encoder)
+{
+ u32 hotplug;
+
+ switch (encoder->hpd_pin) {
+ case HPD_PORT_A:
+ hotplug = PORTA_HOTPLUG_ENABLE;
+ if (intel_bios_encoder_hpd_invert(encoder->devdata))
+ hotplug |= BXT_DDIA_HPD_INVERT;
+ return hotplug;
+ case HPD_PORT_B:
+ hotplug = PORTB_HOTPLUG_ENABLE;
+ if (intel_bios_encoder_hpd_invert(encoder->devdata))
+ hotplug |= BXT_DDIB_HPD_INVERT;
+ return hotplug;
+ case HPD_PORT_C:
+ hotplug = PORTC_HOTPLUG_ENABLE;
+ if (intel_bios_encoder_hpd_invert(encoder->devdata))
+ hotplug |= BXT_DDIC_HPD_INVERT;
+ return hotplug;
+ default:
+ return 0;
+ }
+}
+
+static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv)
+{
+ intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
+ intel_hpd_hotplug_mask(dev_priv, bxt_hotplug_mask),
+ intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables));
+}
+
+static void bxt_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
+ bxt_hotplug_mask(encoder->hpd_pin),
+ bxt_hotplug_enables(encoder));
+}
+
+static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
+{
+ u32 hotplug_irqs, enabled_irqs;
+
+ enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
+ hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
+
+ bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
+
+ bxt_hpd_detection_setup(dev_priv);
+}
+
+static void i915_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ u32 hotplug_en = hpd_mask_i915[encoder->hpd_pin];
+
+ /* HPD sense and interrupt enable are one and the same */
+ i915_hotplug_interrupt_update(i915, hotplug_en, hotplug_en);
+}
+
+static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv)
+{
+ u32 hotplug_en;
+
+ lockdep_assert_held(&dev_priv->irq_lock);
+
+ /*
+ * Note HDMI and DP share hotplug bits. Enable bits are the same for all
+ * generations.
+ */
+ hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915);
+ /*
+ * Programming the CRT detection parameters tends to generate a spurious
+ * hotplug event about three seconds later. So just do it once.
+ */
+ if (IS_G4X(dev_priv))
+ hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
+ hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
+
+ /* Ignore TV since it's buggy */
+ i915_hotplug_interrupt_update_locked(dev_priv,
+ HOTPLUG_INT_EN_MASK |
+ CRT_HOTPLUG_VOLTAGE_COMPARE_MASK |
+ CRT_HOTPLUG_ACTIVATION_PERIOD_64,
+ hotplug_en);
+}
+
+struct intel_hotplug_funcs {
+ /* Enable HPD sense and interrupts for all present encoders */
+ void (*hpd_irq_setup)(struct drm_i915_private *i915);
+ /* Enable HPD sense for a single encoder */
+ void (*hpd_enable_detection)(struct intel_encoder *encoder);
+};
+
+#define HPD_FUNCS(platform) \
+static const struct intel_hotplug_funcs platform##_hpd_funcs = { \
+ .hpd_irq_setup = platform##_hpd_irq_setup, \
+ .hpd_enable_detection = platform##_hpd_enable_detection, \
+}
+
+HPD_FUNCS(i915);
+HPD_FUNCS(xelpdp);
+HPD_FUNCS(dg1);
+HPD_FUNCS(gen11);
+HPD_FUNCS(bxt);
+HPD_FUNCS(icp);
+HPD_FUNCS(spt);
+HPD_FUNCS(ilk);
+#undef HPD_FUNCS
+
+void intel_hpd_enable_detection(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ if (i915->display.funcs.hotplug)
+ i915->display.funcs.hotplug->hpd_enable_detection(encoder);
+}
+
+void intel_hpd_irq_setup(struct drm_i915_private *i915)
+{
+ if (i915->display_irqs_enabled && i915->display.funcs.hotplug)
+ i915->display.funcs.hotplug->hpd_irq_setup(i915);
+}
+
+void intel_hotplug_irq_init(struct drm_i915_private *i915)
+{
+ intel_hpd_init_pins(i915);
+
+ intel_hpd_init_early(i915);
+
+ if (HAS_GMCH(i915)) {
+ if (I915_HAS_HOTPLUG(i915))
+ i915->display.funcs.hotplug = &i915_hpd_funcs;
+ } else {
+ if (HAS_PCH_DG2(i915))
+ i915->display.funcs.hotplug = &icp_hpd_funcs;
+ else if (HAS_PCH_DG1(i915))
+ i915->display.funcs.hotplug = &dg1_hpd_funcs;
+ else if (DISPLAY_VER(i915) >= 14)
+ i915->display.funcs.hotplug = &xelpdp_hpd_funcs;
+ else if (DISPLAY_VER(i915) >= 11)
+ i915->display.funcs.hotplug = &gen11_hpd_funcs;
+ else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
+ i915->display.funcs.hotplug = &bxt_hpd_funcs;
+ else if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
+ i915->display.funcs.hotplug = &icp_hpd_funcs;
+ else if (INTEL_PCH_TYPE(i915) >= PCH_SPT)
+ i915->display.funcs.hotplug = &spt_hpd_funcs;
+ else
+ i915->display.funcs.hotplug = &ilk_hpd_funcs;
+ }
+}
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug_irq.h b/drivers/gpu/drm/i915/display/intel_hotplug_irq.h
new file mode 100644
index 000000000000..e4db752df096
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_hotplug_irq.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_HOTPLUG_IRQ_H__
+#define __INTEL_HOTPLUG_IRQ_H__
+
+#include <linux/types.h>
+
+struct drm_i915_private;
+struct intel_encoder;
+
+u32 i9xx_hpd_irq_ack(struct drm_i915_private *i915);
+
+void i9xx_hpd_irq_handler(struct drm_i915_private *i915, u32 hotplug_status);
+void ibx_hpd_irq_handler(struct drm_i915_private *i915, u32 hotplug_trigger);
+void ilk_hpd_irq_handler(struct drm_i915_private *i915, u32 hotplug_trigger);
+void gen11_hpd_irq_handler(struct drm_i915_private *i915, u32 iir);
+void bxt_hpd_irq_handler(struct drm_i915_private *i915, u32 hotplug_trigger);
+void xelpdp_pica_irq_handler(struct drm_i915_private *i915, u32 iir);
+void icp_irq_handler(struct drm_i915_private *i915, u32 pch_iir);
+void spt_irq_handler(struct drm_i915_private *i915, u32 pch_iir);
+
+void i915_hotplug_interrupt_update_locked(struct drm_i915_private *i915,
+ u32 mask, u32 bits);
+void i915_hotplug_interrupt_update(struct drm_i915_private *i915,
+ u32 mask, u32 bits);
+
+void intel_hpd_enable_detection(struct intel_encoder *encoder);
+void intel_hpd_irq_setup(struct drm_i915_private *i915);
+
+void intel_hotplug_irq_init(struct drm_i915_private *i915);
+
+#endif /* __INTEL_HOTPLUG_IRQ_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_hti.c b/drivers/gpu/drm/i915/display/intel_hti.c
index c518efebdf77..a92d008d4e6e 100644
--- a/drivers/gpu/drm/i915/display/intel_hti.c
+++ b/drivers/gpu/drm/i915/display/intel_hti.c
@@ -15,7 +15,7 @@ void intel_hti_init(struct drm_i915_private *i915)
* If the platform has HTI, we need to find out whether it has reserved
* any display resources before we create our display outputs.
*/
- if (INTEL_INFO(i915)->display.has_hti)
+ if (DISPLAY_INFO(i915)->has_hti)
i915->display.hti.state = intel_de_read(i915, HDPORT_STATE);
}
diff --git a/drivers/gpu/drm/i915/display/intel_load_detect.c b/drivers/gpu/drm/i915/display/intel_load_detect.c
new file mode 100644
index 000000000000..d5a0aecf3e8f
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_load_detect.c
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic_uapi.h>
+
+#include "i915_drv.h"
+#include "intel_atomic.h"
+#include "intel_crtc.h"
+#include "intel_display_types.h"
+#include "intel_load_detect.h"
+
+/* VESA 640x480x72Hz mode to set on the pipe */
+static const struct drm_display_mode load_detect_mode = {
+ DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
+ 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
+};
+
+static int intel_modeset_disable_planes(struct drm_atomic_state *state,
+ struct drm_crtc *crtc)
+{
+ struct drm_plane *plane;
+ struct drm_plane_state *plane_state;
+ int ret, i;
+
+ ret = drm_atomic_add_affected_planes(state, crtc);
+ if (ret)
+ return ret;
+
+ for_each_new_plane_in_state(state, plane, plane_state, i) {
+ if (plane_state->crtc != crtc)
+ continue;
+
+ ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
+ if (ret)
+ return ret;
+
+ drm_atomic_set_fb_for_plane(plane_state, NULL);
+ }
+
+ return 0;
+}
+
+struct drm_atomic_state *
+intel_load_detect_get_pipe(struct drm_connector *connector,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct intel_encoder *encoder =
+ intel_attached_encoder(to_intel_connector(connector));
+ struct intel_crtc *possible_crtc;
+ struct intel_crtc *crtc = NULL;
+ struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_mode_config *config = &dev->mode_config;
+ struct drm_atomic_state *state = NULL, *restore_state = NULL;
+ struct drm_connector_state *connector_state;
+ struct intel_crtc_state *crtc_state;
+ int ret;
+
+ drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
+ connector->base.id, connector->name,
+ encoder->base.base.id, encoder->base.name);
+
+ drm_WARN_ON(dev, !drm_modeset_is_locked(&config->connection_mutex));
+
+ /*
+ * Algorithm gets a little messy:
+ *
+ * - if the connector already has an assigned crtc, use it (but make
+ * sure it's on first)
+ *
+ * - try to find the first unused crtc that can drive this connector,
+ * and use that if we find one
+ */
+
+ /* See if we already have a CRTC for this connector */
+ if (connector->state->crtc) {
+ crtc = to_intel_crtc(connector->state->crtc);
+
+ ret = drm_modeset_lock(&crtc->base.mutex, ctx);
+ if (ret)
+ goto fail;
+
+ /* Make sure the crtc and connector are running */
+ goto found;
+ }
+
+ /* Find an unused one (if possible) */
+ for_each_intel_crtc(dev, possible_crtc) {
+ if (!(encoder->base.possible_crtcs &
+ drm_crtc_mask(&possible_crtc->base)))
+ continue;
+
+ ret = drm_modeset_lock(&possible_crtc->base.mutex, ctx);
+ if (ret)
+ goto fail;
+
+ if (possible_crtc->base.state->enable) {
+ drm_modeset_unlock(&possible_crtc->base.mutex);
+ continue;
+ }
+
+ crtc = possible_crtc;
+ break;
+ }
+
+ /*
+ * If we didn't find an unused CRTC, don't use any.
+ */
+ if (!crtc) {
+ drm_dbg_kms(&dev_priv->drm,
+ "no pipe available for load-detect\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+found:
+ state = drm_atomic_state_alloc(dev);
+ restore_state = drm_atomic_state_alloc(dev);
+ if (!state || !restore_state) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ state->acquire_ctx = ctx;
+ to_intel_atomic_state(state)->internal = true;
+
+ restore_state->acquire_ctx = ctx;
+ to_intel_atomic_state(restore_state)->internal = true;
+
+ connector_state = drm_atomic_get_connector_state(state, connector);
+ if (IS_ERR(connector_state)) {
+ ret = PTR_ERR(connector_state);
+ goto fail;
+ }
+
+ ret = drm_atomic_set_crtc_for_connector(connector_state, &crtc->base);
+ if (ret)
+ goto fail;
+
+ crtc_state = intel_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(crtc_state)) {
+ ret = PTR_ERR(crtc_state);
+ goto fail;
+ }
+
+ crtc_state->uapi.active = true;
+
+ ret = drm_atomic_set_mode_for_crtc(&crtc_state->uapi,
+ &load_detect_mode);
+ if (ret)
+ goto fail;
+
+ ret = intel_modeset_disable_planes(state, &crtc->base);
+ if (ret)
+ goto fail;
+
+ ret = PTR_ERR_OR_ZERO(drm_atomic_get_connector_state(restore_state, connector));
+ if (!ret)
+ ret = PTR_ERR_OR_ZERO(drm_atomic_get_crtc_state(restore_state, &crtc->base));
+ if (!ret)
+ ret = drm_atomic_add_affected_planes(restore_state, &crtc->base);
+ if (ret) {
+ drm_dbg_kms(&dev_priv->drm,
+ "Failed to create a copy of old state to restore: %i\n",
+ ret);
+ goto fail;
+ }
+
+ ret = drm_atomic_commit(state);
+ if (ret) {
+ drm_dbg_kms(&dev_priv->drm,
+ "failed to set mode on load-detect pipe\n");
+ goto fail;
+ }
+
+ drm_atomic_state_put(state);
+
+ /* let the connector get through one full cycle before testing */
+ intel_crtc_wait_for_next_vblank(crtc);
+
+ return restore_state;
+
+fail:
+ if (state) {
+ drm_atomic_state_put(state);
+ state = NULL;
+ }
+ if (restore_state) {
+ drm_atomic_state_put(restore_state);
+ restore_state = NULL;
+ }
+
+ if (ret == -EDEADLK)
+ return ERR_PTR(ret);
+
+ return NULL;
+}
+
+void intel_load_detect_release_pipe(struct drm_connector *connector,
+ struct drm_atomic_state *state,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct intel_encoder *intel_encoder =
+ intel_attached_encoder(to_intel_connector(connector));
+ struct drm_i915_private *i915 = to_i915(intel_encoder->base.dev);
+ struct drm_encoder *encoder = &intel_encoder->base;
+ int ret;
+
+ drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
+ connector->base.id, connector->name,
+ encoder->base.id, encoder->name);
+
+ if (IS_ERR_OR_NULL(state))
+ return;
+
+ ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
+ if (ret)
+ drm_dbg_kms(&i915->drm,
+ "Couldn't release load detect pipe: %i\n", ret);
+ drm_atomic_state_put(state);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_load_detect.h b/drivers/gpu/drm/i915/display/intel_load_detect.h
new file mode 100644
index 000000000000..aed51901b9ba
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_load_detect.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_LOAD_DETECT_H__
+#define __INTEL_LOAD_DETECT_H__
+
+struct drm_atomic_state;
+struct drm_connector;
+struct drm_modeset_acquire_ctx;
+
+struct drm_atomic_state *
+intel_load_detect_get_pipe(struct drm_connector *connector,
+ struct drm_modeset_acquire_ctx *ctx);
+void intel_load_detect_release_pipe(struct drm_connector *connector,
+ struct drm_atomic_state *old,
+ struct drm_modeset_acquire_ctx *ctx);
+
+#endif /* __INTEL_LOAD_DETECT_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index 0de44b3631cd..3ace56979b70 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -150,7 +150,7 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
if (DISPLAY_VER(dev_priv) < 4) {
tmp = intel_de_read(dev_priv, PFIT_CONTROL);
- crtc_state->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE;
+ crtc_state->gmch_pfit.control |= tmp & PFIT_PANEL_8TO6_DITHER_ENABLE;
}
crtc_state->hw.adjusted_mode.crtc_clock = crtc_state->port_clock;
@@ -437,6 +437,7 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
crtc_state->pipe_bpp = lvds_bpp;
}
+ crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB;
crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
/*
@@ -943,17 +944,8 @@ void intel_lvds_init(struct drm_i915_private *i915)
*/
mutex_lock(&i915->drm.mode_config.mutex);
if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) {
- const struct edid *edid;
-
- /* FIXME: Make drm_get_edid_switcheroo() return drm_edid */
- edid = drm_get_edid_switcheroo(&connector->base,
- intel_gmbus_get_adapter(i915, pin));
- if (edid) {
- drm_edid = drm_edid_alloc(edid, (edid->extensions + 1) * EDID_LENGTH);
- kfree(edid);
- } else {
- drm_edid = NULL;
- }
+ drm_edid = drm_edid_read_switcheroo(&connector->base,
+ intel_gmbus_get_adapter(i915, pin));
} else {
drm_edid = drm_edid_read_ddc(&connector->base,
intel_gmbus_get_adapter(i915, pin));
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_lock.c b/drivers/gpu/drm/i915/display/intel_modeset_lock.c
new file mode 100644
index 000000000000..8fb6fd849a75
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_modeset_lock.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include <drm/drm_modeset_lock.h>
+
+#include "intel_display_types.h"
+#include "intel_modeset_lock.h"
+
+void _intel_modeset_lock_begin(struct drm_modeset_acquire_ctx *ctx,
+ struct intel_atomic_state *state,
+ unsigned int flags, int *ret)
+{
+ drm_modeset_acquire_init(ctx, flags);
+
+ if (state)
+ state->base.acquire_ctx = ctx;
+
+ *ret = -EDEADLK;
+}
+
+bool _intel_modeset_lock_loop(int *ret)
+{
+ if (*ret == -EDEADLK) {
+ *ret = 0;
+ return true;
+ }
+
+ return false;
+}
+
+void _intel_modeset_lock_end(struct drm_modeset_acquire_ctx *ctx,
+ struct intel_atomic_state *state,
+ int *ret)
+{
+ if (*ret == -EDEADLK) {
+ if (state)
+ drm_atomic_state_clear(&state->base);
+
+ *ret = drm_modeset_backoff(ctx);
+ if (*ret == 0) {
+ *ret = -EDEADLK;
+ return;
+ }
+ }
+
+ drm_modeset_drop_locks(ctx);
+ drm_modeset_acquire_fini(ctx);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_lock.h b/drivers/gpu/drm/i915/display/intel_modeset_lock.h
new file mode 100644
index 000000000000..edb5099bcd99
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_modeset_lock.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_MODESET_LOCK_H__
+#define __INTEL_MODESET_LOCK_H__
+
+#include <linux/types.h>
+
+struct drm_modeset_acquire_ctx;
+struct intel_atomic_state;
+
+void _intel_modeset_lock_begin(struct drm_modeset_acquire_ctx *ctx,
+ struct intel_atomic_state *state,
+ unsigned int flags,
+ int *ret);
+bool _intel_modeset_lock_loop(int *ret);
+void _intel_modeset_lock_end(struct drm_modeset_acquire_ctx *ctx,
+ struct intel_atomic_state *state,
+ int *ret);
+
+/*
+ * Note that one must always use "continue" rather than
+ * "break" or "return" to handle errors within the
+ * intel_modeset_lock_ctx_retry() block.
+ */
+#define intel_modeset_lock_ctx_retry(ctx, state, flags, ret) \
+ for (_intel_modeset_lock_begin((ctx), (state), (flags), &(ret)); \
+ _intel_modeset_lock_loop(&(ret)); \
+ _intel_modeset_lock_end((ctx), (state), &(ret)))
+
+#endif /* __INTEL_MODESET_LOCK_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
index 134b943f1953..b8f43efb0ab5 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
@@ -26,28 +26,22 @@
#include "intel_fifo_underrun.h"
#include "intel_modeset_setup.h"
#include "intel_pch_display.h"
+#include "intel_pmdemand.h"
+#include "intel_tc.h"
#include "intel_vblank.h"
#include "intel_wm.h"
#include "skl_watermark.h"
-static void intel_crtc_disable_noatomic(struct intel_crtc *crtc,
- struct drm_modeset_acquire_ctx *ctx)
+static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc,
+ struct drm_modeset_acquire_ctx *ctx)
{
- struct intel_encoder *encoder;
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
- struct intel_bw_state *bw_state =
- to_intel_bw_state(i915->display.bw.obj.state);
- struct intel_cdclk_state *cdclk_state =
- to_intel_cdclk_state(i915->display.cdclk.obj.state);
- struct intel_dbuf_state *dbuf_state =
- to_intel_dbuf_state(i915->display.dbuf.obj.state);
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct intel_plane *plane;
struct drm_atomic_state *state;
- struct intel_crtc_state *temp_crtc_state;
+ struct intel_crtc *temp_crtc;
enum pipe pipe = crtc->pipe;
- int ret;
if (!crtc_state->hw.active)
return;
@@ -69,12 +63,20 @@ static void intel_crtc_disable_noatomic(struct intel_crtc *crtc,
}
state->acquire_ctx = ctx;
+ to_intel_atomic_state(state)->internal = true;
/* Everything's already locked, -EDEADLK can't happen. */
- temp_crtc_state = intel_atomic_get_crtc_state(state, crtc);
- ret = drm_atomic_add_affected_connectors(state, &crtc->base);
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc,
+ BIT(pipe) |
+ intel_crtc_bigjoiner_slave_pipes(crtc_state)) {
+ struct intel_crtc_state *temp_crtc_state =
+ intel_atomic_get_crtc_state(state, temp_crtc);
+ int ret;
+
+ ret = drm_atomic_add_affected_connectors(state, &temp_crtc->base);
- drm_WARN_ON(&i915->drm, IS_ERR(temp_crtc_state) || ret);
+ drm_WARN_ON(&i915->drm, IS_ERR(temp_crtc_state) || ret);
+ }
i915->display.funcs.display->crtc_disable(to_intel_atomic_state(state), crtc);
@@ -87,16 +89,86 @@ static void intel_crtc_disable_noatomic(struct intel_crtc *crtc,
crtc->active = false;
crtc->base.enabled = false;
- drm_WARN_ON(&i915->drm,
- drm_atomic_set_mode_for_crtc(&crtc_state->uapi, NULL) < 0);
- crtc_state->uapi.active = false;
- crtc_state->uapi.connector_mask = 0;
- crtc_state->uapi.encoder_mask = 0;
- intel_crtc_free_hw_state(crtc_state);
- memset(&crtc_state->hw, 0, sizeof(crtc_state->hw));
+ if (crtc_state->shared_dpll)
+ intel_unreference_shared_dpll_crtc(crtc,
+ crtc_state->shared_dpll,
+ &crtc_state->shared_dpll->state);
+}
+
+static void set_encoder_for_connector(struct intel_connector *connector,
+ struct intel_encoder *encoder)
+{
+ struct drm_connector_state *conn_state = connector->base.state;
+
+ if (conn_state->crtc)
+ drm_connector_put(&connector->base);
+
+ if (encoder) {
+ conn_state->best_encoder = &encoder->base;
+ conn_state->crtc = encoder->base.crtc;
+ drm_connector_get(&connector->base);
+ } else {
+ conn_state->best_encoder = NULL;
+ conn_state->crtc = NULL;
+ }
+}
+
+static void reset_encoder_connector_state(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_pmdemand_state *pmdemand_state =
+ to_intel_pmdemand_state(i915->display.pmdemand.obj.state);
+ struct intel_connector *connector;
+ struct drm_connector_list_iter conn_iter;
+
+ drm_connector_list_iter_begin(&i915->drm, &conn_iter);
+ for_each_intel_connector_iter(connector, &conn_iter) {
+ if (connector->base.encoder != &encoder->base)
+ continue;
+
+ /* Clear the corresponding bit in pmdemand active phys mask */
+ intel_pmdemand_update_phys_mask(i915, encoder,
+ pmdemand_state, false);
+
+ set_encoder_for_connector(connector, NULL);
+
+ connector->base.dpms = DRM_MODE_DPMS_OFF;
+ connector->base.encoder = NULL;
+ }
+ drm_connector_list_iter_end(&conn_iter);
+}
- for_each_encoder_on_crtc(&i915->drm, &crtc->base, encoder)
+static void reset_crtc_encoder_state(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_encoder *encoder;
+
+ for_each_encoder_on_crtc(&i915->drm, &crtc->base, encoder) {
+ reset_encoder_connector_state(encoder);
encoder->base.crtc = NULL;
+ }
+}
+
+static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_bw_state *bw_state =
+ to_intel_bw_state(i915->display.bw.obj.state);
+ struct intel_cdclk_state *cdclk_state =
+ to_intel_cdclk_state(i915->display.cdclk.obj.state);
+ struct intel_dbuf_state *dbuf_state =
+ to_intel_dbuf_state(i915->display.dbuf.obj.state);
+ struct intel_pmdemand_state *pmdemand_state =
+ to_intel_pmdemand_state(i915->display.pmdemand.obj.state);
+ struct intel_crtc_state *crtc_state =
+ to_intel_crtc_state(crtc->base.state);
+ enum pipe pipe = crtc->pipe;
+
+ __drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi);
+ intel_crtc_free_hw_state(crtc_state);
+ intel_crtc_state_reset(crtc_state, crtc);
+
+ reset_crtc_encoder_state(crtc);
intel_fbc_disable(crtc);
intel_update_watermarks(i915);
@@ -111,6 +183,120 @@ static void intel_crtc_disable_noatomic(struct intel_crtc *crtc,
bw_state->data_rate[pipe] = 0;
bw_state->num_active_planes[pipe] = 0;
+
+ intel_pmdemand_update_port_clock(i915, pmdemand_state, pipe, 0);
+}
+
+/*
+ * Return all the pipes using a transcoder in @transcoder_mask.
+ * For bigjoiner configs return only the bigjoiner master.
+ */
+static u8 get_transcoder_pipes(struct drm_i915_private *i915,
+ u8 transcoder_mask)
+{
+ struct intel_crtc *temp_crtc;
+ u8 pipes = 0;
+
+ for_each_intel_crtc(&i915->drm, temp_crtc) {
+ struct intel_crtc_state *temp_crtc_state =
+ to_intel_crtc_state(temp_crtc->base.state);
+
+ if (temp_crtc_state->cpu_transcoder == INVALID_TRANSCODER)
+ continue;
+
+ if (intel_crtc_is_bigjoiner_slave(temp_crtc_state))
+ continue;
+
+ if (transcoder_mask & BIT(temp_crtc_state->cpu_transcoder))
+ pipes |= BIT(temp_crtc->pipe);
+ }
+
+ return pipes;
+}
+
+/*
+ * Return the port sync master and slave pipes linked to @crtc.
+ * For bigjoiner configs return only the bigjoiner master pipes.
+ */
+static void get_portsync_pipes(struct intel_crtc *crtc,
+ u8 *master_pipe_mask, u8 *slave_pipes_mask)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_crtc_state *crtc_state =
+ to_intel_crtc_state(crtc->base.state);
+ struct intel_crtc *master_crtc;
+ struct intel_crtc_state *master_crtc_state;
+ enum transcoder master_transcoder;
+
+ if (!is_trans_port_sync_mode(crtc_state)) {
+ *master_pipe_mask = BIT(crtc->pipe);
+ *slave_pipes_mask = 0;
+
+ return;
+ }
+
+ if (is_trans_port_sync_master(crtc_state))
+ master_transcoder = crtc_state->cpu_transcoder;
+ else
+ master_transcoder = crtc_state->master_transcoder;
+
+ *master_pipe_mask = get_transcoder_pipes(i915, BIT(master_transcoder));
+ drm_WARN_ON(&i915->drm, !is_power_of_2(*master_pipe_mask));
+
+ master_crtc = intel_crtc_for_pipe(i915, ffs(*master_pipe_mask) - 1);
+ master_crtc_state = to_intel_crtc_state(master_crtc->base.state);
+ *slave_pipes_mask = get_transcoder_pipes(i915, master_crtc_state->sync_mode_slaves_mask);
+}
+
+static u8 get_bigjoiner_slave_pipes(struct drm_i915_private *i915, u8 master_pipes_mask)
+{
+ struct intel_crtc *master_crtc;
+ u8 pipes = 0;
+
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, master_crtc, master_pipes_mask) {
+ struct intel_crtc_state *master_crtc_state =
+ to_intel_crtc_state(master_crtc->base.state);
+
+ pipes |= intel_crtc_bigjoiner_slave_pipes(master_crtc_state);
+ }
+
+ return pipes;
+}
+
+static void intel_crtc_disable_noatomic(struct intel_crtc *crtc,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ u8 portsync_master_mask;
+ u8 portsync_slaves_mask;
+ u8 bigjoiner_slaves_mask;
+ struct intel_crtc *temp_crtc;
+
+ /* TODO: Add support for MST */
+ get_portsync_pipes(crtc, &portsync_master_mask, &portsync_slaves_mask);
+ bigjoiner_slaves_mask = get_bigjoiner_slave_pipes(i915,
+ portsync_master_mask |
+ portsync_slaves_mask);
+
+ drm_WARN_ON(&i915->drm,
+ portsync_master_mask & portsync_slaves_mask ||
+ portsync_master_mask & bigjoiner_slaves_mask ||
+ portsync_slaves_mask & bigjoiner_slaves_mask);
+
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc, bigjoiner_slaves_mask)
+ intel_crtc_disable_noatomic_begin(temp_crtc, ctx);
+
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc, portsync_slaves_mask)
+ intel_crtc_disable_noatomic_begin(temp_crtc, ctx);
+
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc, portsync_master_mask)
+ intel_crtc_disable_noatomic_begin(temp_crtc, ctx);
+
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc,
+ bigjoiner_slaves_mask |
+ portsync_slaves_mask |
+ portsync_master_mask)
+ intel_crtc_disable_noatomic_complete(temp_crtc);
}
static void intel_modeset_update_connector_atomic_state(struct drm_i915_private *i915)
@@ -124,8 +310,7 @@ static void intel_modeset_update_connector_atomic_state(struct drm_i915_private
struct intel_encoder *encoder =
to_intel_encoder(connector->base.encoder);
- if (conn_state->crtc)
- drm_connector_put(&connector->base);
+ set_encoder_for_connector(connector, encoder);
if (encoder) {
struct intel_crtc *crtc =
@@ -133,14 +318,7 @@ static void intel_modeset_update_connector_atomic_state(struct drm_i915_private
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
- conn_state->best_encoder = &encoder->base;
- conn_state->crtc = &crtc->base;
conn_state->max_bpc = (crtc_state->pipe_bpp ?: 24) / 3;
-
- drm_connector_get(&connector->base);
- } else {
- conn_state->best_encoder = NULL;
- conn_state->crtc = NULL;
}
}
drm_connector_list_iter_end(&conn_iter);
@@ -213,6 +391,21 @@ static bool intel_crtc_has_encoders(struct intel_crtc *crtc)
return false;
}
+static bool intel_crtc_needs_link_reset(struct intel_crtc *crtc)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct intel_encoder *encoder;
+
+ for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+ if (dig_port && intel_tc_port_link_needs_reset(dig_port))
+ return true;
+ }
+
+ return false;
+}
+
static struct intel_connector *intel_encoder_find_connector(struct intel_encoder *encoder)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
@@ -255,11 +448,12 @@ static void intel_sanitize_fifo_underrun_reporting(const struct intel_crtc_state
!HAS_GMCH(i915));
}
-static void intel_sanitize_crtc(struct intel_crtc *crtc,
+static bool intel_sanitize_crtc(struct intel_crtc *crtc,
struct drm_modeset_acquire_ctx *ctx)
{
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
+ bool needs_link_reset;
if (crtc_state->hw.active) {
struct intel_plane *plane;
@@ -279,13 +473,67 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
intel_color_commit_arm(crtc_state);
}
+ if (!crtc_state->hw.active ||
+ intel_crtc_is_bigjoiner_slave(crtc_state))
+ return false;
+
+ needs_link_reset = intel_crtc_needs_link_reset(crtc);
+
/*
* Adjust the state of the output pipe according to whether we have
* active connectors/encoders.
*/
- if (crtc_state->hw.active && !intel_crtc_has_encoders(crtc) &&
- !intel_crtc_is_bigjoiner_slave(crtc_state))
- intel_crtc_disable_noatomic(crtc, ctx);
+ if (!needs_link_reset && intel_crtc_has_encoders(crtc))
+ return false;
+
+ intel_crtc_disable_noatomic(crtc, ctx);
+
+ /*
+ * The HPD state on other active/disconnected TC ports may be stuck in
+ * the connected state until this port is disabled and a ~10ms delay has
+ * passed, wait here for that so that sanitizing other CRTCs will see the
+ * up-to-date HPD state.
+ */
+ if (needs_link_reset)
+ msleep(20);
+
+ return true;
+}
+
+static void intel_sanitize_all_crtcs(struct drm_i915_private *i915,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct intel_crtc *crtc;
+ u32 crtcs_forced_off = 0;
+
+ /*
+ * An active and disconnected TypeC port prevents the HPD live state
+ * to get updated on other active/disconnected TypeC ports, so after
+ * a port gets disabled the CRTCs using other TypeC ports must be
+ * rechecked wrt. their link status.
+ */
+ for (;;) {
+ u32 old_mask = crtcs_forced_off;
+
+ for_each_intel_crtc(&i915->drm, crtc) {
+ u32 crtc_mask = drm_crtc_mask(&crtc->base);
+
+ if (crtcs_forced_off & crtc_mask)
+ continue;
+
+ if (intel_sanitize_crtc(crtc, ctx))
+ crtcs_forced_off |= crtc_mask;
+ }
+ if (crtcs_forced_off == old_mask)
+ break;
+ }
+
+ for_each_intel_crtc(&i915->drm, crtc) {
+ struct intel_crtc_state *crtc_state =
+ to_intel_crtc_state(crtc->base.state);
+
+ intel_crtc_state_dump(crtc_state, NULL, "setup_hw_state");
+ }
}
static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)
@@ -315,6 +563,8 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
struct intel_crtc_state *crtc_state = crtc ?
to_intel_crtc_state(crtc->base.state) : NULL;
+ struct intel_pmdemand_state *pmdemand_state =
+ to_intel_pmdemand_state(i915->display.pmdemand.obj.state);
/*
* We need to check both for a crtc link (meaning that the encoder is
@@ -338,6 +588,10 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
encoder->base.base.id,
encoder->base.name);
+ /* Clear the corresponding bit in pmdemand active phys mask */
+ intel_pmdemand_update_phys_mask(i915, encoder,
+ pmdemand_state, false);
+
/*
* Connector is active, but has no active pipe. This is fallout
* from our resume register restoring. Disable the encoder
@@ -424,6 +678,8 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
to_intel_cdclk_state(i915->display.cdclk.obj.state);
struct intel_dbuf_state *dbuf_state =
to_intel_dbuf_state(i915->display.dbuf.obj.state);
+ struct intel_pmdemand_state *pmdemand_state =
+ to_intel_pmdemand_state(i915->display.pmdemand.obj.state);
enum pipe pipe;
struct intel_crtc *crtc;
struct intel_encoder *encoder;
@@ -487,7 +743,15 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
intel_encoder_get_config(encoder, slave_crtc_state);
}
}
+
+ intel_pmdemand_update_phys_mask(i915, encoder,
+ pmdemand_state,
+ true);
} else {
+ intel_pmdemand_update_phys_mask(i915, encoder,
+ pmdemand_state,
+ false);
+
encoder->base.crtc = NULL;
}
@@ -559,7 +823,8 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
*/
crtc_state->inherited = true;
- intel_crtc_update_active_timings(crtc_state);
+ intel_crtc_update_active_timings(crtc_state,
+ crtc_state->vrr.enable);
intel_crtc_copy_hw_to_uapi_state(crtc_state);
}
@@ -603,8 +868,13 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
cdclk_state->min_voltage_level[crtc->pipe] =
crtc_state->min_voltage_level;
+ intel_pmdemand_update_port_clock(i915, pmdemand_state, pipe,
+ crtc_state->port_clock);
+
intel_bw_crtc_update(bw_state, crtc_state);
}
+
+ intel_pmdemand_init_pmdemand_params(i915, pmdemand_state);
}
static void
@@ -698,16 +968,14 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915,
for_each_intel_encoder(&i915->drm, encoder)
intel_sanitize_encoder(encoder);
- for_each_intel_crtc(&i915->drm, crtc) {
- struct intel_crtc_state *crtc_state =
- to_intel_crtc_state(crtc->base.state);
-
- intel_sanitize_crtc(crtc, ctx);
- intel_crtc_state_dump(crtc_state, NULL, "setup_hw_state");
- }
-
+ /*
+ * Sanitizing CRTCs needs their connector atomic state to be
+ * up-to-date, so ensure that already here.
+ */
intel_modeset_update_connector_atomic_state(i915);
+ intel_sanitize_all_crtcs(i915, ctx);
+
intel_dpll_sanitize_state(i915);
intel_wm_get_hw_state(i915);
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
index 842d70f0dfd2..138144a65a45 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
@@ -11,6 +11,7 @@
#include "intel_atomic.h"
#include "intel_crtc.h"
#include "intel_crtc_state_dump.h"
+#include "intel_cx0_phy.h"
#include "intel_display.h"
#include "intel_display_types.h"
#include "intel_fdi.h"
@@ -34,27 +35,28 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,
if (connector->get_hw_state(connector)) {
struct intel_encoder *encoder = intel_attached_encoder(connector);
- I915_STATE_WARN(!crtc_state,
+ I915_STATE_WARN(i915, !crtc_state,
"connector enabled without attached crtc\n");
if (!crtc_state)
return;
- I915_STATE_WARN(!crtc_state->hw.active,
+ I915_STATE_WARN(i915, !crtc_state->hw.active,
"connector is active, but attached crtc isn't\n");
if (!encoder || encoder->type == INTEL_OUTPUT_DP_MST)
return;
- I915_STATE_WARN(conn_state->best_encoder != &encoder->base,
+ I915_STATE_WARN(i915,
+ conn_state->best_encoder != &encoder->base,
"atomic encoder doesn't match attached encoder\n");
- I915_STATE_WARN(conn_state->crtc != encoder->base.crtc,
+ I915_STATE_WARN(i915, conn_state->crtc != encoder->base.crtc,
"attached encoder crtc differs from connector crtc\n");
} else {
- I915_STATE_WARN(crtc_state && crtc_state->hw.active,
+ I915_STATE_WARN(i915, crtc_state && crtc_state->hw.active,
"attached crtc is active, but connector isn't\n");
- I915_STATE_WARN(!crtc_state && conn_state->best_encoder,
+ I915_STATE_WARN(i915, !crtc_state && conn_state->best_encoder,
"best encoder set without crtc!\n");
}
}
@@ -79,7 +81,7 @@ verify_connector_state(struct intel_atomic_state *state,
intel_connector_verify_state(crtc_state, new_conn_state);
- I915_STATE_WARN(new_conn_state->best_encoder != encoder,
+ I915_STATE_WARN(to_i915(connector->dev), new_conn_state->best_encoder != encoder,
"connector's atomic encoder doesn't match legacy encoder\n");
}
}
@@ -130,15 +132,15 @@ verify_encoder_state(struct drm_i915_private *dev_priv, struct intel_atomic_stat
found = true;
enabled = true;
- I915_STATE_WARN(new_conn_state->crtc !=
- encoder->base.crtc,
+ I915_STATE_WARN(dev_priv,
+ new_conn_state->crtc != encoder->base.crtc,
"connector's crtc doesn't match encoder crtc\n");
}
if (!found)
continue;
- I915_STATE_WARN(!!encoder->base.crtc != enabled,
+ I915_STATE_WARN(dev_priv, !!encoder->base.crtc != enabled,
"encoder's enabled state mismatch (expected %i, found %i)\n",
!!encoder->base.crtc, enabled);
@@ -146,7 +148,7 @@ verify_encoder_state(struct drm_i915_private *dev_priv, struct intel_atomic_stat
bool active;
active = encoder->get_hw_state(encoder, &pipe);
- I915_STATE_WARN(active,
+ I915_STATE_WARN(dev_priv, active,
"encoder detached but still enabled on pipe %c.\n",
pipe_name(pipe));
}
@@ -181,11 +183,12 @@ verify_crtc_state(struct intel_crtc *crtc,
if (IS_I830(dev_priv) && pipe_config->hw.active)
pipe_config->hw.active = new_crtc_state->hw.active;
- I915_STATE_WARN(new_crtc_state->hw.active != pipe_config->hw.active,
+ I915_STATE_WARN(dev_priv,
+ new_crtc_state->hw.active != pipe_config->hw.active,
"crtc active state doesn't match with hw state (expected %i, found %i)\n",
new_crtc_state->hw.active, pipe_config->hw.active);
- I915_STATE_WARN(crtc->active != new_crtc_state->hw.active,
+ I915_STATE_WARN(dev_priv, crtc->active != new_crtc_state->hw.active,
"transitional active state does not match atomic hw state (expected %i, found %i)\n",
new_crtc_state->hw.active, crtc->active);
@@ -196,12 +199,12 @@ verify_crtc_state(struct intel_crtc *crtc,
bool active;
active = encoder->get_hw_state(encoder, &pipe);
- I915_STATE_WARN(active != new_crtc_state->hw.active,
+ I915_STATE_WARN(dev_priv, active != new_crtc_state->hw.active,
"[ENCODER:%i] active %i with crtc active %i\n",
encoder->base.base.id, active,
new_crtc_state->hw.active);
- I915_STATE_WARN(active && master_crtc->pipe != pipe,
+ I915_STATE_WARN(dev_priv, active && master_crtc->pipe != pipe,
"Encoder connected to wrong pipe %c\n",
pipe_name(pipe));
@@ -216,7 +219,7 @@ verify_crtc_state(struct intel_crtc *crtc,
if (!intel_pipe_config_compare(new_crtc_state,
pipe_config, false)) {
- I915_STATE_WARN(1, "pipe state doesn't match!\n");
+ I915_STATE_WARN(dev_priv, 1, "pipe state doesn't match!\n");
intel_crtc_state_dump(pipe_config, NULL, "hw state");
intel_crtc_state_dump(new_crtc_state, NULL, "sw state");
}
@@ -236,6 +239,7 @@ void intel_modeset_verify_crtc(struct intel_crtc *crtc,
verify_crtc_state(crtc, old_crtc_state, new_crtc_state);
intel_shared_dpll_state_verify(crtc, old_crtc_state, new_crtc_state);
intel_mpllb_state_verify(state, new_crtc_state);
+ intel_c10pll_state_verify(state, new_crtc_state);
}
void intel_modeset_verify_disabled(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c
index b7973a05d022..84078fb82b2f 100644
--- a/drivers/gpu/drm/i915/display/intel_opregion.c
+++ b/drivers/gpu/drm/i915/display/intel_opregion.c
@@ -635,7 +635,8 @@ static void asle_work(struct work_struct *work)
void intel_opregion_asle_intr(struct drm_i915_private *dev_priv)
{
if (dev_priv->display.opregion.asle)
- schedule_work(&dev_priv->display.opregion.asle_work);
+ queue_work(dev_priv->unordered_wq,
+ &dev_priv->display.opregion.asle_work);
}
#define ACPI_EV_DISPLAY_SWITCH (1<<0)
diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c
index c12bdca8da9b..d6fe2bbabe55 100644
--- a/drivers/gpu/drm/i915/display/intel_overlay.c
+++ b/drivers/gpu/drm/i915/display/intel_overlay.c
@@ -935,21 +935,25 @@ static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
- u32 pfit_control = intel_de_read(dev_priv, PFIT_CONTROL);
u32 ratio;
/* XXX: This is not the same logic as in the xorg driver, but more in
* line with the intel documentation for the i965
*/
if (DISPLAY_VER(dev_priv) >= 4) {
+ u32 tmp = intel_de_read(dev_priv, PFIT_PGM_RATIOS);
+
/* on i965 use the PGM reg to read out the autoscaler values */
- ratio = intel_de_read(dev_priv, PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
+ ratio = REG_FIELD_GET(PFIT_VERT_SCALE_MASK_965, tmp);
} else {
- if (pfit_control & VERT_AUTO_SCALE)
- ratio = intel_de_read(dev_priv, PFIT_AUTO_RATIOS);
+ u32 tmp;
+
+ if (intel_de_read(dev_priv, PFIT_CONTROL) & PFIT_VERT_AUTO_SCALE)
+ tmp = intel_de_read(dev_priv, PFIT_AUTO_RATIOS);
else
- ratio = intel_de_read(dev_priv, PFIT_PGM_RATIOS);
- ratio >>= PFIT_VERT_SCALE_SHIFT;
+ tmp = intel_de_read(dev_priv, PFIT_PGM_RATIOS);
+
+ ratio = REG_FIELD_GET(PFIT_VERT_SCALE_MASK, tmp);
}
overlay->pfit_vscale_ratio = ratio;
diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
index ce2a34a25211..9232a305b1e6 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -42,6 +42,7 @@
#include "intel_lvds_regs.h"
#include "intel_panel.h"
#include "intel_quirks.h"
+#include "intel_vrr.h"
bool intel_panel_use_ssc(struct drm_i915_private *i915)
{
@@ -58,6 +59,38 @@ intel_panel_preferred_fixed_mode(struct intel_connector *connector)
struct drm_display_mode, head);
}
+static bool is_in_vrr_range(struct intel_connector *connector, int vrefresh)
+{
+ const struct drm_display_info *info = &connector->base.display_info;
+
+ return intel_vrr_is_capable(connector) &&
+ vrefresh >= info->monitor_range.min_vfreq &&
+ vrefresh <= info->monitor_range.max_vfreq;
+}
+
+static bool is_best_fixed_mode(struct intel_connector *connector,
+ int vrefresh, int fixed_mode_vrefresh,
+ const struct drm_display_mode *best_mode)
+{
+ /* we want to always return something */
+ if (!best_mode)
+ return true;
+
+ /*
+ * With VRR always pick a mode with equal/higher than requested
+ * vrefresh, which we can then reduce to match the requested
+ * vrefresh by extending the vblank length.
+ */
+ if (is_in_vrr_range(connector, vrefresh) &&
+ is_in_vrr_range(connector, fixed_mode_vrefresh) &&
+ fixed_mode_vrefresh < vrefresh)
+ return false;
+
+ /* pick the fixed_mode that is closest in terms of vrefresh */
+ return abs(fixed_mode_vrefresh - vrefresh) <
+ abs(drm_mode_vrefresh(best_mode) - vrefresh);
+}
+
const struct drm_display_mode *
intel_panel_fixed_mode(struct intel_connector *connector,
const struct drm_display_mode *mode)
@@ -65,11 +98,11 @@ intel_panel_fixed_mode(struct intel_connector *connector,
const struct drm_display_mode *fixed_mode, *best_mode = NULL;
int vrefresh = drm_mode_vrefresh(mode);
- /* pick the fixed_mode that is closest in terms of vrefresh */
list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
- if (!best_mode ||
- abs(drm_mode_vrefresh(fixed_mode) - vrefresh) <
- abs(drm_mode_vrefresh(best_mode) - vrefresh))
+ int fixed_mode_vrefresh = drm_mode_vrefresh(fixed_mode);
+
+ if (is_best_fixed_mode(connector, vrefresh,
+ fixed_mode_vrefresh, best_mode))
best_mode = fixed_mode;
}
@@ -178,27 +211,46 @@ int intel_panel_compute_config(struct intel_connector *connector,
{
const struct drm_display_mode *fixed_mode =
intel_panel_fixed_mode(connector, adjusted_mode);
+ int vrefresh, fixed_mode_vrefresh;
+ bool is_vrr;
if (!fixed_mode)
return 0;
+ vrefresh = drm_mode_vrefresh(adjusted_mode);
+ fixed_mode_vrefresh = drm_mode_vrefresh(fixed_mode);
+
/*
- * We don't want to lie too much to the user about the refresh
- * rate they're going to get. But we have to allow a bit of latitude
- * for Xorg since it likes to automagically cook up modes with slightly
- * off refresh rates.
+ * Assume that we shouldn't muck about with the
+ * timings if they don't land in the VRR range.
*/
- if (abs(drm_mode_vrefresh(adjusted_mode) - drm_mode_vrefresh(fixed_mode)) > 1) {
- drm_dbg_kms(connector->base.dev,
- "[CONNECTOR:%d:%s] Requested mode vrefresh (%d Hz) does not match fixed mode vrefresh (%d Hz)\n",
- connector->base.base.id, connector->base.name,
- drm_mode_vrefresh(adjusted_mode), drm_mode_vrefresh(fixed_mode));
+ is_vrr = is_in_vrr_range(connector, vrefresh) &&
+ is_in_vrr_range(connector, fixed_mode_vrefresh);
- return -EINVAL;
+ if (!is_vrr) {
+ /*
+ * We don't want to lie too much to the user about the refresh
+ * rate they're going to get. But we have to allow a bit of latitude
+ * for Xorg since it likes to automagically cook up modes with slightly
+ * off refresh rates.
+ */
+ if (abs(vrefresh - fixed_mode_vrefresh) > 1) {
+ drm_dbg_kms(connector->base.dev,
+ "[CONNECTOR:%d:%s] Requested mode vrefresh (%d Hz) does not match fixed mode vrefresh (%d Hz)\n",
+ connector->base.base.id, connector->base.name,
+ vrefresh, fixed_mode_vrefresh);
+
+ return -EINVAL;
+ }
}
drm_mode_copy(adjusted_mode, fixed_mode);
+ if (is_vrr && fixed_mode_vrefresh != vrefresh)
+ adjusted_mode->vtotal =
+ DIV_ROUND_CLOSEST(adjusted_mode->clock * 1000,
+ adjusted_mode->htotal * vrefresh);
+
drm_mode_set_crtcinfo(adjusted_mode, 0);
return 0;
@@ -512,11 +564,11 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state,
bits = panel_fitter_scaling(pipe_src_h,
adjusted_mode->crtc_vdisplay);
- *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
- bits << PFIT_VERT_SCALE_SHIFT);
+ *pfit_pgm_ratios |= (PFIT_HORIZ_SCALE(bits) |
+ PFIT_VERT_SCALE(bits));
*pfit_control |= (PFIT_ENABLE |
- VERT_INTERP_BILINEAR |
- HORIZ_INTERP_BILINEAR);
+ PFIT_VERT_INTERP_BILINEAR |
+ PFIT_HORIZ_INTERP_BILINEAR);
}
} else if (scaled_width < scaled_height) { /* letter */
centre_vertically(adjusted_mode,
@@ -527,18 +579,19 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state,
bits = panel_fitter_scaling(pipe_src_w,
adjusted_mode->crtc_hdisplay);
- *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
- bits << PFIT_VERT_SCALE_SHIFT);
+ *pfit_pgm_ratios |= (PFIT_HORIZ_SCALE(bits) |
+ PFIT_VERT_SCALE(bits));
*pfit_control |= (PFIT_ENABLE |
- VERT_INTERP_BILINEAR |
- HORIZ_INTERP_BILINEAR);
+ PFIT_VERT_INTERP_BILINEAR |
+ PFIT_HORIZ_INTERP_BILINEAR);
}
} else {
/* Aspects match, Let hw scale both directions */
*pfit_control |= (PFIT_ENABLE |
- VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
- VERT_INTERP_BILINEAR |
- HORIZ_INTERP_BILINEAR);
+ PFIT_VERT_AUTO_SCALE |
+ PFIT_HORIZ_AUTO_SCALE |
+ PFIT_VERT_INTERP_BILINEAR |
+ PFIT_HORIZ_INTERP_BILINEAR);
}
}
@@ -586,10 +639,10 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state,
if (DISPLAY_VER(dev_priv) >= 4)
pfit_control |= PFIT_SCALING_AUTO;
else
- pfit_control |= (VERT_AUTO_SCALE |
- VERT_INTERP_BILINEAR |
- HORIZ_AUTO_SCALE |
- HORIZ_INTERP_BILINEAR);
+ pfit_control |= (PFIT_VERT_AUTO_SCALE |
+ PFIT_VERT_INTERP_BILINEAR |
+ PFIT_HORIZ_AUTO_SCALE |
+ PFIT_HORIZ_INTERP_BILINEAR);
}
break;
default:
@@ -610,7 +663,7 @@ out:
/* Make sure pre-965 set dither correctly for 18bpp panels. */
if (DISPLAY_VER(dev_priv) < 4 && crtc_state->pipe_bpp == 18)
- pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+ pfit_control |= PFIT_PANEL_8TO6_DITHER_ENABLE;
crtc_state->gmch_pfit.control = pfit_control;
crtc_state->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c
index 2411fe4dee8b..866786e6b32f 100644
--- a/drivers/gpu/drm/i915/display/intel_pch_display.c
+++ b/drivers/gpu/drm/i915/display/intel_pch_display.c
@@ -43,11 +43,12 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
state = g4x_dp_port_enabled(dev_priv, dp_reg, port, &port_pipe);
- I915_STATE_WARN(state && port_pipe == pipe,
+ I915_STATE_WARN(dev_priv, state && port_pipe == pipe,
"PCH DP %c enabled on transcoder %c, should be disabled\n",
port_name(port), pipe_name(pipe));
- I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
+ I915_STATE_WARN(dev_priv,
+ HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
"IBX PCH DP %c still using transcoder B\n",
port_name(port));
}
@@ -61,11 +62,12 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
state = intel_sdvo_port_enabled(dev_priv, hdmi_reg, &port_pipe);
- I915_STATE_WARN(state && port_pipe == pipe,
+ I915_STATE_WARN(dev_priv, state && port_pipe == pipe,
"PCH HDMI %c enabled on transcoder %c, should be disabled\n",
port_name(port), pipe_name(pipe));
- I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
+ I915_STATE_WARN(dev_priv,
+ HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
"IBX PCH HDMI %c still using transcoder B\n",
port_name(port));
}
@@ -79,13 +81,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
assert_pch_dp_disabled(dev_priv, pipe, PORT_C, PCH_DP_C);
assert_pch_dp_disabled(dev_priv, pipe, PORT_D, PCH_DP_D);
- I915_STATE_WARN(intel_crt_port_enabled(dev_priv, PCH_ADPA, &port_pipe) &&
- port_pipe == pipe,
+ I915_STATE_WARN(dev_priv,
+ intel_crt_port_enabled(dev_priv, PCH_ADPA, &port_pipe) && port_pipe == pipe,
"PCH VGA enabled on transcoder %c, should be disabled\n",
pipe_name(pipe));
- I915_STATE_WARN(intel_lvds_port_enabled(dev_priv, PCH_LVDS, &port_pipe) &&
- port_pipe == pipe,
+ I915_STATE_WARN(dev_priv,
+ intel_lvds_port_enabled(dev_priv, PCH_LVDS, &port_pipe) && port_pipe == pipe,
"PCH LVDS enabled on transcoder %c, should be disabled\n",
pipe_name(pipe));
@@ -103,7 +105,7 @@ static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
val = intel_de_read(dev_priv, PCH_TRANSCONF(pipe));
enabled = !!(val & TRANS_ENABLE);
- I915_STATE_WARN(enabled,
+ I915_STATE_WARN(dev_priv, enabled,
"transcoder assertion failed, should be off on pipe %c but is still active\n",
pipe_name(pipe));
}
diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c
index 8d3ea8d7b737..5a468ed6e26c 100644
--- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c
+++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c
@@ -293,6 +293,7 @@ intel_crtc_crc_setup_workarounds(struct intel_crtc *crtc, bool enable)
}
state->acquire_ctx = &ctx;
+ to_intel_atomic_state(state)->internal = true;
retry:
pipe_config = intel_atomic_get_crtc_state(state, crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c
index bb6ea7de5c61..736072a8b2b0 100644
--- a/drivers/gpu/drm/i915/display/intel_plane_initial.c
+++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c
@@ -110,7 +110,9 @@ initial_plane_vma(struct drm_i915_private *i915,
size * 2 > i915->dsm.usable_size)
return NULL;
- obj = i915_gem_object_create_region_at(mem, phys_base, size, 0);
+ obj = i915_gem_object_create_region_at(mem, phys_base, size,
+ I915_BO_ALLOC_USER |
+ I915_BO_PREALLOC);
if (IS_ERR(obj))
return NULL;
diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c
new file mode 100644
index 000000000000..f7608d363634
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c
@@ -0,0 +1,620 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include <linux/bitops.h>
+
+#include "i915_drv.h"
+#include "i915_reg.h"
+#include "intel_atomic.h"
+#include "intel_bw.h"
+#include "intel_cdclk.h"
+#include "intel_de.h"
+#include "intel_display_trace.h"
+#include "intel_pmdemand.h"
+#include "skl_watermark.h"
+
+static struct intel_global_state *
+intel_pmdemand_duplicate_state(struct intel_global_obj *obj)
+{
+ struct intel_pmdemand_state *pmdemand_state;
+
+ pmdemand_state = kmemdup(obj->state, sizeof(*pmdemand_state), GFP_KERNEL);
+ if (!pmdemand_state)
+ return NULL;
+
+ return &pmdemand_state->base;
+}
+
+static void intel_pmdemand_destroy_state(struct intel_global_obj *obj,
+ struct intel_global_state *state)
+{
+ kfree(state);
+}
+
+static const struct intel_global_state_funcs intel_pmdemand_funcs = {
+ .atomic_duplicate_state = intel_pmdemand_duplicate_state,
+ .atomic_destroy_state = intel_pmdemand_destroy_state,
+};
+
+static struct intel_pmdemand_state *
+intel_atomic_get_pmdemand_state(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_global_state *pmdemand_state =
+ intel_atomic_get_global_obj_state(state,
+ &i915->display.pmdemand.obj);
+
+ if (IS_ERR(pmdemand_state))
+ return ERR_CAST(pmdemand_state);
+
+ return to_intel_pmdemand_state(pmdemand_state);
+}
+
+static struct intel_pmdemand_state *
+intel_atomic_get_old_pmdemand_state(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_global_state *pmdemand_state =
+ intel_atomic_get_old_global_obj_state(state,
+ &i915->display.pmdemand.obj);
+
+ if (!pmdemand_state)
+ return NULL;
+
+ return to_intel_pmdemand_state(pmdemand_state);
+}
+
+static struct intel_pmdemand_state *
+intel_atomic_get_new_pmdemand_state(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_global_state *pmdemand_state =
+ intel_atomic_get_new_global_obj_state(state,
+ &i915->display.pmdemand.obj);
+
+ if (!pmdemand_state)
+ return NULL;
+
+ return to_intel_pmdemand_state(pmdemand_state);
+}
+
+int intel_pmdemand_init(struct drm_i915_private *i915)
+{
+ struct intel_pmdemand_state *pmdemand_state;
+
+ pmdemand_state = kzalloc(sizeof(*pmdemand_state), GFP_KERNEL);
+ if (!pmdemand_state)
+ return -ENOMEM;
+
+ intel_atomic_global_obj_init(i915, &i915->display.pmdemand.obj,
+ &pmdemand_state->base,
+ &intel_pmdemand_funcs);
+
+ if (IS_MTL_DISPLAY_STEP(i915, STEP_A0, STEP_C0))
+ /* Wa_14016740474 */
+ intel_de_rmw(i915, XELPD_CHICKEN_DCPR_3, 0, DMD_RSP_TIMEOUT_DISABLE);
+
+ return 0;
+}
+
+void intel_pmdemand_init_early(struct drm_i915_private *i915)
+{
+ mutex_init(&i915->display.pmdemand.lock);
+ init_waitqueue_head(&i915->display.pmdemand.waitqueue);
+}
+
+void
+intel_pmdemand_update_phys_mask(struct drm_i915_private *i915,
+ struct intel_encoder *encoder,
+ struct intel_pmdemand_state *pmdemand_state,
+ bool set_bit)
+{
+ enum phy phy;
+
+ if (DISPLAY_VER(i915) < 14)
+ return;
+
+ if (!encoder)
+ return;
+
+ phy = intel_port_to_phy(i915, encoder->port);
+ if (intel_phy_is_tc(i915, phy))
+ return;
+
+ if (set_bit)
+ pmdemand_state->active_combo_phys_mask |= BIT(phy);
+ else
+ pmdemand_state->active_combo_phys_mask &= ~BIT(phy);
+}
+
+void
+intel_pmdemand_update_port_clock(struct drm_i915_private *i915,
+ struct intel_pmdemand_state *pmdemand_state,
+ enum pipe pipe, int port_clock)
+{
+ if (DISPLAY_VER(i915) < 14)
+ return;
+
+ pmdemand_state->ddi_clocks[pipe] = port_clock;
+}
+
+static void
+intel_pmdemand_update_max_ddiclk(struct drm_i915_private *i915,
+ struct intel_atomic_state *state,
+ struct intel_pmdemand_state *pmdemand_state)
+{
+ int max_ddiclk = 0;
+ const struct intel_crtc_state *new_crtc_state;
+ struct intel_crtc *crtc;
+ int i;
+
+ for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
+ intel_pmdemand_update_port_clock(i915, pmdemand_state,
+ crtc->pipe,
+ new_crtc_state->port_clock);
+
+ for (i = 0; i < ARRAY_SIZE(pmdemand_state->ddi_clocks); i++)
+ max_ddiclk = max(pmdemand_state->ddi_clocks[i], max_ddiclk);
+
+ pmdemand_state->params.ddiclk_max = DIV_ROUND_UP(max_ddiclk, 1000);
+}
+
+static void
+intel_pmdemand_update_connector_phys(struct drm_i915_private *i915,
+ struct intel_atomic_state *state,
+ struct drm_connector_state *conn_state,
+ bool set_bit,
+ struct intel_pmdemand_state *pmdemand_state)
+{
+ struct intel_encoder *encoder = to_intel_encoder(conn_state->best_encoder);
+ struct intel_crtc *crtc = to_intel_crtc(conn_state->crtc);
+ struct intel_crtc_state *crtc_state;
+
+ if (!crtc)
+ return;
+
+ if (set_bit)
+ crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
+ else
+ crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
+
+ if (!crtc_state->hw.active)
+ return;
+
+ intel_pmdemand_update_phys_mask(i915, encoder, pmdemand_state,
+ set_bit);
+}
+
+static void
+intel_pmdemand_update_active_non_tc_phys(struct drm_i915_private *i915,
+ struct intel_atomic_state *state,
+ struct intel_pmdemand_state *pmdemand_state)
+{
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_connector *connector;
+ int i;
+
+ for_each_oldnew_connector_in_state(&state->base, connector,
+ old_conn_state, new_conn_state, i) {
+ if (!intel_connector_needs_modeset(state, connector))
+ continue;
+
+ /* First clear the active phys in the old connector state */
+ intel_pmdemand_update_connector_phys(i915, state,
+ old_conn_state, false,
+ pmdemand_state);
+
+ /* Then set the active phys in new connector state */
+ intel_pmdemand_update_connector_phys(i915, state,
+ new_conn_state, true,
+ pmdemand_state);
+ }
+
+ pmdemand_state->params.active_phys =
+ min_t(u16, hweight16(pmdemand_state->active_combo_phys_mask),
+ 7);
+}
+
+static bool
+intel_pmdemand_encoder_has_tc_phy(struct drm_i915_private *i915,
+ struct intel_encoder *encoder)
+{
+ enum phy phy;
+
+ if (!encoder)
+ return false;
+
+ phy = intel_port_to_phy(i915, encoder->port);
+
+ return intel_phy_is_tc(i915, phy);
+}
+
+static bool
+intel_pmdemand_connector_needs_update(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_connector *connector;
+ int i;
+
+ for_each_oldnew_connector_in_state(&state->base, connector,
+ old_conn_state, new_conn_state, i) {
+ struct intel_encoder *old_encoder =
+ to_intel_encoder(old_conn_state->best_encoder);
+ struct intel_encoder *new_encoder =
+ to_intel_encoder(new_conn_state->best_encoder);
+
+ if (!intel_connector_needs_modeset(state, connector))
+ continue;
+
+ if (old_encoder == new_encoder ||
+ (intel_pmdemand_encoder_has_tc_phy(i915, old_encoder) &&
+ intel_pmdemand_encoder_has_tc_phy(i915, new_encoder)))
+ continue;
+
+ return true;
+ }
+
+ return false;
+}
+
+static bool intel_pmdemand_needs_update(struct intel_atomic_state *state)
+{
+ const struct intel_bw_state *new_bw_state, *old_bw_state;
+ const struct intel_cdclk_state *new_cdclk_state, *old_cdclk_state;
+ const struct intel_crtc_state *new_crtc_state, *old_crtc_state;
+ const struct intel_dbuf_state *new_dbuf_state, *old_dbuf_state;
+ struct intel_crtc *crtc;
+ int i;
+
+ new_bw_state = intel_atomic_get_new_bw_state(state);
+ old_bw_state = intel_atomic_get_old_bw_state(state);
+ if (new_bw_state && new_bw_state->qgv_point_peakbw !=
+ old_bw_state->qgv_point_peakbw)
+ return true;
+
+ new_dbuf_state = intel_atomic_get_new_dbuf_state(state);
+ old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
+ if (new_dbuf_state &&
+ (new_dbuf_state->active_pipes !=
+ old_dbuf_state->active_pipes ||
+ new_dbuf_state->enabled_slices !=
+ old_dbuf_state->enabled_slices))
+ return true;
+
+ new_cdclk_state = intel_atomic_get_new_cdclk_state(state);
+ old_cdclk_state = intel_atomic_get_old_cdclk_state(state);
+ if (new_cdclk_state &&
+ (new_cdclk_state->actual.cdclk !=
+ old_cdclk_state->actual.cdclk ||
+ new_cdclk_state->actual.voltage_level !=
+ old_cdclk_state->actual.voltage_level))
+ return true;
+
+ for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
+ new_crtc_state, i)
+ if (new_crtc_state->port_clock != old_crtc_state->port_clock)
+ return true;
+
+ return intel_pmdemand_connector_needs_update(state);
+}
+
+int intel_pmdemand_atomic_check(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_bw_state *new_bw_state;
+ const struct intel_cdclk_state *new_cdclk_state;
+ const struct intel_dbuf_state *new_dbuf_state;
+ struct intel_pmdemand_state *new_pmdemand_state;
+
+ if (DISPLAY_VER(i915) < 14)
+ return 0;
+
+ if (!intel_pmdemand_needs_update(state))
+ return 0;
+
+ new_pmdemand_state = intel_atomic_get_pmdemand_state(state);
+ if (IS_ERR(new_pmdemand_state))
+ return PTR_ERR(new_pmdemand_state);
+
+ new_bw_state = intel_atomic_get_bw_state(state);
+ if (IS_ERR(new_bw_state))
+ return PTR_ERR(new_bw_state);
+
+ /* firmware will calculate the qclk_gv_index, requirement is set to 0 */
+ new_pmdemand_state->params.qclk_gv_index = 0;
+ new_pmdemand_state->params.qclk_gv_bw = new_bw_state->qgv_point_peakbw;
+
+ new_dbuf_state = intel_atomic_get_dbuf_state(state);
+ if (IS_ERR(new_dbuf_state))
+ return PTR_ERR(new_dbuf_state);
+
+ new_pmdemand_state->params.active_pipes =
+ min_t(u8, hweight8(new_dbuf_state->active_pipes), 3);
+ new_pmdemand_state->params.active_dbufs =
+ min_t(u8, hweight8(new_dbuf_state->enabled_slices), 3);
+
+ new_cdclk_state = intel_atomic_get_cdclk_state(state);
+ if (IS_ERR(new_cdclk_state))
+ return PTR_ERR(new_cdclk_state);
+
+ new_pmdemand_state->params.voltage_index =
+ new_cdclk_state->actual.voltage_level;
+ new_pmdemand_state->params.cdclk_freq_mhz =
+ DIV_ROUND_UP(new_cdclk_state->actual.cdclk, 1000);
+
+ intel_pmdemand_update_max_ddiclk(i915, state, new_pmdemand_state);
+
+ intel_pmdemand_update_active_non_tc_phys(i915, state, new_pmdemand_state);
+
+ /*
+ * Active_PLLs starts with 1 because of CDCLK PLL.
+ * TODO: Missing to account genlock filter when it gets used.
+ */
+ new_pmdemand_state->params.plls =
+ min_t(u16, new_pmdemand_state->params.active_phys + 1, 7);
+
+ /*
+ * Setting scalers to max as it can not be calculated during flips and
+ * fastsets without taking global states locks.
+ */
+ new_pmdemand_state->params.scalers = 7;
+
+ if (state->base.allow_modeset)
+ return intel_atomic_serialize_global_state(&new_pmdemand_state->base);
+ else
+ return intel_atomic_lock_global_state(&new_pmdemand_state->base);
+}
+
+static bool intel_pmdemand_check_prev_transaction(struct drm_i915_private *i915)
+{
+ return !(intel_de_wait_for_clear(i915,
+ XELPDP_INITIATE_PMDEMAND_REQUEST(1),
+ XELPDP_PMDEMAND_REQ_ENABLE, 10) ||
+ intel_de_wait_for_clear(i915,
+ GEN12_DCPR_STATUS_1,
+ XELPDP_PMDEMAND_INFLIGHT_STATUS, 10));
+}
+
+void
+intel_pmdemand_init_pmdemand_params(struct drm_i915_private *i915,
+ struct intel_pmdemand_state *pmdemand_state)
+{
+ u32 reg1, reg2;
+
+ if (DISPLAY_VER(i915) < 14)
+ return;
+
+ mutex_lock(&i915->display.pmdemand.lock);
+ if (drm_WARN_ON(&i915->drm,
+ !intel_pmdemand_check_prev_transaction(i915))) {
+ memset(&pmdemand_state->params, 0,
+ sizeof(pmdemand_state->params));
+ goto unlock;
+ }
+
+ reg1 = intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(0));
+
+ reg2 = intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1));
+
+ /* Set 1*/
+ pmdemand_state->params.qclk_gv_bw =
+ REG_FIELD_GET(XELPDP_PMDEMAND_QCLK_GV_BW_MASK, reg1);
+ pmdemand_state->params.voltage_index =
+ REG_FIELD_GET(XELPDP_PMDEMAND_VOLTAGE_INDEX_MASK, reg1);
+ pmdemand_state->params.qclk_gv_index =
+ REG_FIELD_GET(XELPDP_PMDEMAND_QCLK_GV_INDEX_MASK, reg1);
+ pmdemand_state->params.active_pipes =
+ REG_FIELD_GET(XELPDP_PMDEMAND_PIPES_MASK, reg1);
+ pmdemand_state->params.active_dbufs =
+ REG_FIELD_GET(XELPDP_PMDEMAND_DBUFS_MASK, reg1);
+ pmdemand_state->params.active_phys =
+ REG_FIELD_GET(XELPDP_PMDEMAND_PHYS_MASK, reg1);
+
+ /* Set 2*/
+ pmdemand_state->params.cdclk_freq_mhz =
+ REG_FIELD_GET(XELPDP_PMDEMAND_CDCLK_FREQ_MASK, reg2);
+ pmdemand_state->params.ddiclk_max =
+ REG_FIELD_GET(XELPDP_PMDEMAND_DDICLK_FREQ_MASK, reg2);
+ pmdemand_state->params.scalers =
+ REG_FIELD_GET(XELPDP_PMDEMAND_SCALERS_MASK, reg2);
+
+unlock:
+ mutex_unlock(&i915->display.pmdemand.lock);
+}
+
+static bool intel_pmdemand_req_complete(struct drm_i915_private *i915)
+{
+ return !(intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1)) &
+ XELPDP_PMDEMAND_REQ_ENABLE);
+}
+
+static void intel_pmdemand_wait(struct drm_i915_private *i915)
+{
+ if (!wait_event_timeout(i915->display.pmdemand.waitqueue,
+ intel_pmdemand_req_complete(i915),
+ msecs_to_jiffies_timeout(10)))
+ drm_err(&i915->drm,
+ "timed out waiting for Punit PM Demand Response\n");
+}
+
+/* Required to be programmed during Display Init Sequences. */
+void intel_pmdemand_program_dbuf(struct drm_i915_private *i915,
+ u8 dbuf_slices)
+{
+ u32 dbufs = min_t(u32, hweight8(dbuf_slices), 3);
+
+ mutex_lock(&i915->display.pmdemand.lock);
+ if (drm_WARN_ON(&i915->drm,
+ !intel_pmdemand_check_prev_transaction(i915)))
+ goto unlock;
+
+ intel_de_rmw(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(0),
+ XELPDP_PMDEMAND_DBUFS_MASK,
+ REG_FIELD_PREP(XELPDP_PMDEMAND_DBUFS_MASK, dbufs));
+ intel_de_rmw(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1), 0,
+ XELPDP_PMDEMAND_REQ_ENABLE);
+
+ intel_pmdemand_wait(i915);
+
+unlock:
+ mutex_unlock(&i915->display.pmdemand.lock);
+}
+
+static void
+intel_pmdemand_update_params(const struct intel_pmdemand_state *new,
+ const struct intel_pmdemand_state *old,
+ u32 *reg1, u32 *reg2, bool serialized)
+{
+ /*
+ * The pmdemand parameter updates happens in two steps. Pre plane and
+ * post plane updates. During the pre plane, as DE might still be
+ * handling with some old operations, to avoid unexpected performance
+ * issues, program the pmdemand parameters with higher of old and new
+ * values. And then after once settled, use the new parameter values
+ * as part of the post plane update.
+ *
+ * If the pmdemand params update happens without modeset allowed, this
+ * means we can't serialize the updates. So that implies possibility of
+ * some parallel atomic commits affecting the pmdemand parameters. In
+ * that case, we need to consider the current values from the register
+ * as well. So in pre-plane case, we need to check the max of old, new
+ * and current register value if not serialized. In post plane update
+ * we need to consider max of new and current register value if not
+ * serialized
+ */
+
+#define update_reg(reg, field, mask) do { \
+ u32 current_val = serialized ? 0 : REG_FIELD_GET((mask), *(reg)); \
+ u32 old_val = old ? old->params.field : 0; \
+ u32 new_val = new->params.field; \
+\
+ *(reg) &= ~(mask); \
+ *(reg) |= REG_FIELD_PREP((mask), max3(old_val, new_val, current_val)); \
+} while (0)
+
+ /* Set 1*/
+ update_reg(reg1, qclk_gv_bw, XELPDP_PMDEMAND_QCLK_GV_BW_MASK);
+ update_reg(reg1, voltage_index, XELPDP_PMDEMAND_VOLTAGE_INDEX_MASK);
+ update_reg(reg1, qclk_gv_index, XELPDP_PMDEMAND_QCLK_GV_INDEX_MASK);
+ update_reg(reg1, active_pipes, XELPDP_PMDEMAND_PIPES_MASK);
+ update_reg(reg1, active_dbufs, XELPDP_PMDEMAND_DBUFS_MASK);
+ update_reg(reg1, active_phys, XELPDP_PMDEMAND_PHYS_MASK);
+
+ /* Set 2*/
+ update_reg(reg2, cdclk_freq_mhz, XELPDP_PMDEMAND_CDCLK_FREQ_MASK);
+ update_reg(reg2, ddiclk_max, XELPDP_PMDEMAND_DDICLK_FREQ_MASK);
+ update_reg(reg2, scalers, XELPDP_PMDEMAND_SCALERS_MASK);
+ update_reg(reg2, plls, XELPDP_PMDEMAND_PLLS_MASK);
+
+#undef update_reg
+}
+
+static void
+intel_pmdemand_program_params(struct drm_i915_private *i915,
+ const struct intel_pmdemand_state *new,
+ const struct intel_pmdemand_state *old,
+ bool serialized)
+{
+ bool changed = false;
+ u32 reg1, mod_reg1;
+ u32 reg2, mod_reg2;
+
+ mutex_lock(&i915->display.pmdemand.lock);
+ if (drm_WARN_ON(&i915->drm,
+ !intel_pmdemand_check_prev_transaction(i915)))
+ goto unlock;
+
+ reg1 = intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(0));
+ mod_reg1 = reg1;
+
+ reg2 = intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1));
+ mod_reg2 = reg2;
+
+ intel_pmdemand_update_params(new, old, &mod_reg1, &mod_reg2,
+ serialized);
+
+ if (reg1 != mod_reg1) {
+ intel_de_write(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(0),
+ mod_reg1);
+ changed = true;
+ }
+
+ if (reg2 != mod_reg2) {
+ intel_de_write(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1),
+ mod_reg2);
+ changed = true;
+ }
+
+ /* Initiate pm demand request only if register values are changed */
+ if (!changed)
+ goto unlock;
+
+ drm_dbg_kms(&i915->drm,
+ "initate pmdemand request values: (0x%x 0x%x)\n",
+ mod_reg1, mod_reg2);
+
+ intel_de_rmw(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1), 0,
+ XELPDP_PMDEMAND_REQ_ENABLE);
+
+ intel_pmdemand_wait(i915);
+
+unlock:
+ mutex_unlock(&i915->display.pmdemand.lock);
+}
+
+static bool
+intel_pmdemand_state_changed(const struct intel_pmdemand_state *new,
+ const struct intel_pmdemand_state *old)
+{
+ return memcmp(&new->params, &old->params, sizeof(new->params)) != 0;
+}
+
+void intel_pmdemand_pre_plane_update(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_pmdemand_state *new_pmdemand_state =
+ intel_atomic_get_new_pmdemand_state(state);
+ const struct intel_pmdemand_state *old_pmdemand_state =
+ intel_atomic_get_old_pmdemand_state(state);
+
+ if (DISPLAY_VER(i915) < 14)
+ return;
+
+ if (!new_pmdemand_state ||
+ !intel_pmdemand_state_changed(new_pmdemand_state,
+ old_pmdemand_state))
+ return;
+
+ WARN_ON(!new_pmdemand_state->base.changed);
+
+ intel_pmdemand_program_params(i915, new_pmdemand_state,
+ old_pmdemand_state,
+ intel_atomic_global_state_is_serialized(state));
+}
+
+void intel_pmdemand_post_plane_update(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_pmdemand_state *new_pmdemand_state =
+ intel_atomic_get_new_pmdemand_state(state);
+ const struct intel_pmdemand_state *old_pmdemand_state =
+ intel_atomic_get_old_pmdemand_state(state);
+
+ if (DISPLAY_VER(i915) < 14)
+ return;
+
+ if (!new_pmdemand_state ||
+ !intel_pmdemand_state_changed(new_pmdemand_state,
+ old_pmdemand_state))
+ return;
+
+ WARN_ON(!new_pmdemand_state->base.changed);
+
+ intel_pmdemand_program_params(i915, new_pmdemand_state, NULL,
+ intel_atomic_global_state_is_serialized(state));
+}
diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.h b/drivers/gpu/drm/i915/display/intel_pmdemand.h
new file mode 100644
index 000000000000..2941a1a18b72
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_pmdemand.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_PMDEMAND_H__
+#define __INTEL_PMDEMAND_H__
+
+#include "intel_display_limits.h"
+#include "intel_global_state.h"
+
+struct drm_i915_private;
+struct intel_atomic_state;
+struct intel_crtc_state;
+struct intel_encoder;
+struct intel_plane_state;
+
+struct pmdemand_params {
+ u16 qclk_gv_bw;
+ u8 voltage_index;
+ u8 qclk_gv_index;
+ u8 active_pipes;
+ u8 active_dbufs;
+ /* Total number of non type C active phys from active_phys_mask */
+ u8 active_phys;
+ u8 plls;
+ u16 cdclk_freq_mhz;
+ /* max from ddi_clocks[] */
+ u16 ddiclk_max;
+ u8 scalers;
+};
+
+struct intel_pmdemand_state {
+ struct intel_global_state base;
+
+ /* Maintain a persistent list of port clocks across all crtcs */
+ int ddi_clocks[I915_MAX_PIPES];
+
+ /* Maintain a persistent list of non type C phys mask */
+ u16 active_combo_phys_mask;
+
+ /* Parameters to be configured in the pmdemand registers */
+ struct pmdemand_params params;
+};
+
+#define to_intel_pmdemand_state(x) container_of((x), \
+ struct intel_pmdemand_state, \
+ base)
+
+void intel_pmdemand_init_early(struct drm_i915_private *i915);
+int intel_pmdemand_init(struct drm_i915_private *i915);
+void intel_pmdemand_init_pmdemand_params(struct drm_i915_private *i915,
+ struct intel_pmdemand_state *pmdemand_state);
+void intel_pmdemand_update_port_clock(struct drm_i915_private *i915,
+ struct intel_pmdemand_state *pmdemand_state,
+ enum pipe pipe, int port_clock);
+void intel_pmdemand_update_phys_mask(struct drm_i915_private *i915,
+ struct intel_encoder *encoder,
+ struct intel_pmdemand_state *pmdemand_state,
+ bool clear_bit);
+void intel_pmdemand_program_dbuf(struct drm_i915_private *i915,
+ u8 dbuf_slices);
+void intel_pmdemand_pre_plane_update(struct intel_atomic_state *state);
+void intel_pmdemand_post_plane_update(struct intel_atomic_state *state);
+int intel_pmdemand_atomic_check(struct intel_atomic_state *state);
+
+#endif /* __INTEL_PMDEMAND_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 7f9926672a6a..73f0f1714b37 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -787,7 +787,7 @@ void intel_pps_vdd_on(struct intel_dp *intel_dp)
vdd = false;
with_intel_pps_lock(intel_dp, wakeref)
vdd = intel_pps_vdd_on_unlocked(intel_dp);
- I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] %s VDD already requested on\n",
+ I915_STATE_WARN(i915, !vdd, "[ENCODER:%d:%s] %s VDD already requested on\n",
dp_to_dig_port(intel_dp)->base.base.base.id,
dp_to_dig_port(intel_dp)->base.base.name,
pps_name(i915, &intel_dp->pps));
@@ -867,6 +867,7 @@ static void edp_panel_vdd_work(struct work_struct *__work)
static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
unsigned long delay;
/*
@@ -882,7 +883,8 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
* operations.
*/
delay = msecs_to_jiffies(intel_dp->pps.panel_power_cycle_delay * 5);
- schedule_delayed_work(&intel_dp->pps.panel_vdd_work, delay);
+ queue_delayed_work(i915->unordered_wq,
+ &intel_dp->pps.panel_vdd_work, delay);
}
/*
@@ -899,7 +901,8 @@ void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync)
if (!intel_dp_is_edp(intel_dp))
return;
- I915_STATE_WARN(!intel_dp->pps.want_panel_vdd, "[ENCODER:%d:%s] %s VDD not forced on",
+ I915_STATE_WARN(dev_priv, !intel_dp->pps.want_panel_vdd,
+ "[ENCODER:%d:%s] %s VDD not forced on",
dp_to_dig_port(intel_dp)->base.base.base.id,
dp_to_dig_port(intel_dp)->base.base.name,
pps_name(dev_priv, &intel_dp->pps));
@@ -1653,12 +1656,9 @@ void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
*/
pps_num = intel_num_pps(dev_priv);
- for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
- u32 val = intel_de_read(dev_priv, PP_CONTROL(pps_idx));
-
- val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
- intel_de_write(dev_priv, PP_CONTROL(pps_idx), val);
- }
+ for (pps_idx = 0; pps_idx < pps_num; pps_idx++)
+ intel_de_rmw(dev_priv, PP_CONTROL(pps_idx),
+ PANEL_UNLOCK_MASK, PANEL_UNLOCK_REGS);
}
void intel_pps_setup(struct drm_i915_private *i915)
@@ -1724,7 +1724,7 @@ void assert_pps_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe)
((val & PANEL_UNLOCK_MASK) == PANEL_UNLOCK_REGS))
locked = false;
- I915_STATE_WARN(panel_pipe == pipe && locked,
+ I915_STATE_WARN(dev_priv, panel_pipe == pipe && locked,
"panel assertion failure, pipe %c regs locked\n",
pipe_name(pipe));
}
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 6badfff2b4a2..d58ed9b62e67 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -85,6 +85,91 @@
* use page flips.
*/
+/*
+ * Description of PSR mask bits:
+ *
+ * EDP_PSR_DEBUG[16]/EDP_PSR_DEBUG_MASK_DISP_REG_WRITE (hsw-skl):
+ *
+ * When unmasked (nearly) all display register writes (eg. even
+ * SWF) trigger a PSR exit. Some registers are excluded from this
+ * and they have a more specific mask (described below). On icl+
+ * this bit no longer exists and is effectively always set.
+ *
+ * PIPE_MISC[21]/PIPE_MISC_PSR_MASK_PIPE_REG_WRITE (skl+):
+ *
+ * When unmasked (nearly) all pipe/plane register writes
+ * trigger a PSR exit. Some plane registers are excluded from this
+ * and they have a more specific mask (described below).
+ *
+ * CHICKEN_PIPESL_1[11]/SKL_PSR_MASK_PLANE_FLIP (skl+):
+ * PIPE_MISC[23]/PIPE_MISC_PSR_MASK_PRIMARY_FLIP (bdw):
+ * EDP_PSR_DEBUG[23]/EDP_PSR_DEBUG_MASK_PRIMARY_FLIP (hsw):
+ *
+ * When unmasked PRI_SURF/PLANE_SURF writes trigger a PSR exit.
+ * SPR_SURF/CURBASE are not included in this and instead are
+ * controlled by PIPE_MISC_PSR_MASK_PIPE_REG_WRITE (skl+) or
+ * EDP_PSR_DEBUG_MASK_DISP_REG_WRITE (hsw/bdw).
+ *
+ * PIPE_MISC[22]/PIPE_MISC_PSR_MASK_SPRITE_ENABLE (bdw):
+ * EDP_PSR_DEBUG[21]/EDP_PSR_DEBUG_MASK_SPRITE_ENABLE (hsw):
+ *
+ * When unmasked PSR is blocked as long as the sprite
+ * plane is enabled. skl+ with their universal planes no
+ * longer have a mask bit like this, and no plane being
+ * enabledb blocks PSR.
+ *
+ * PIPE_MISC[21]/PIPE_MISC_PSR_MASK_CURSOR_MOVE (bdw):
+ * EDP_PSR_DEBUG[20]/EDP_PSR_DEBUG_MASK_CURSOR_MOVE (hsw):
+ *
+ * When umasked CURPOS writes trigger a PSR exit. On skl+
+ * this doesn't exit but CURPOS is included in the
+ * PIPE_MISC_PSR_MASK_PIPE_REG_WRITE mask.
+ *
+ * PIPE_MISC[20]/PIPE_MISC_PSR_MASK_VBLANK_VSYNC_INT (bdw+):
+ * EDP_PSR_DEBUG[19]/EDP_PSR_DEBUG_MASK_VBLANK_VSYNC_INT (hsw):
+ *
+ * When unmasked PSR is blocked as long as vblank and/or vsync
+ * interrupt is unmasked in IMR *and* enabled in IER.
+ *
+ * CHICKEN_TRANS[30]/SKL_UNMASK_VBL_TO_PIPE_IN_SRD (skl+):
+ * CHICKEN_PAR1_1[15]/HSW_MASK_VBL_TO_PIPE_IN_SRD (hsw/bdw):
+ *
+ * Selectcs whether PSR exit generates an extra vblank before
+ * the first frame is transmitted. Also note the opposite polarity
+ * if the bit on hsw/bdw vs. skl+ (masked==generate the extra vblank,
+ * unmasked==do not generate the extra vblank).
+ *
+ * With DC states enabled the extra vblank happens after link training,
+ * with DC states disabled it happens immediately upuon PSR exit trigger.
+ * No idea as of now why there is a difference. HSW/BDW (which don't
+ * even have DMC) always generate it after link training. Go figure.
+ *
+ * Unfortunately CHICKEN_TRANS itself seems to be double buffered
+ * and thus won't latch until the first vblank. So with DC states
+ * enabled the register effctively uses the reset value during DC5
+ * exit+PSR exit sequence, and thus the bit does nothing until
+ * latched by the vblank that it was trying to prevent from being
+ * generated in the first place. So we should probably call this
+ * one a chicken/egg bit instead on skl+.
+ *
+ * In standby mode (as opposed to link-off) this makes no difference
+ * as the timing generator keeps running the whole time generating
+ * normal periodic vblanks.
+ *
+ * WaPsrDPAMaskVBlankInSRD asks us to set the bit on hsw/bdw,
+ * and doing so makes the behaviour match the skl+ reset value.
+ *
+ * CHICKEN_PIPESL_1[0]/BDW_UNMASK_VBL_TO_REGS_IN_SRD (bdw):
+ * CHICKEN_PIPESL_1[15]/HSW_UNMASK_VBL_TO_REGS_IN_SRD (hsw):
+ *
+ * On BDW without this bit is no vblanks whatsoever are
+ * generated after PSR exit. On HSW this has no apparant effect.
+ * WaPsrDPRSUnmaskVBlankInSRD says to set this.
+ *
+ * The rest of the bits are more self-explanatory and/or
+ * irrelevant for normal operation.
+ */
+
static bool psr_global_enabled(struct intel_dp *intel_dp)
{
struct intel_connector *connector = intel_dp->attached_connector;
@@ -208,13 +293,13 @@ static void psr_event_print(struct drm_i915_private *i915,
void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir)
{
- enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
ktime_t time_ns = ktime_get();
i915_reg_t imr_reg;
if (DISPLAY_VER(dev_priv) >= 12)
- imr_reg = TRANS_PSR_IMR(intel_dp->psr.transcoder);
+ imr_reg = TRANS_PSR_IMR(cpu_transcoder);
else
imr_reg = EDP_PSR_IMR;
@@ -232,13 +317,11 @@ void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir)
transcoder_name(cpu_transcoder));
if (DISPLAY_VER(dev_priv) >= 9) {
- u32 val = intel_de_read(dev_priv,
- PSR_EVENT(cpu_transcoder));
- bool psr2_enabled = intel_dp->psr.psr2_enabled;
+ u32 val;
+
+ val = intel_de_rmw(dev_priv, PSR_EVENT(cpu_transcoder), 0, 0);
- intel_de_write(dev_priv, PSR_EVENT(cpu_transcoder),
- val);
- psr_event_print(dev_priv, val, psr2_enabled);
+ psr_event_print(dev_priv, val, intel_dp->psr.psr2_enabled);
}
}
@@ -258,7 +341,7 @@ void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir)
*/
intel_de_rmw(dev_priv, imr_reg, 0, psr_irq_psr_error_bit_get(intel_dp));
- schedule_work(&intel_dp->psr.work);
+ queue_work(dev_priv->unordered_wq, &intel_dp->psr.work);
}
}
@@ -419,7 +502,7 @@ static u32 intel_psr1_get_tp_time(struct intel_dp *intel_dp)
u32 val = 0;
if (DISPLAY_VER(dev_priv) >= 11)
- val |= EDP_PSR_TP4_TIME_0US;
+ val |= EDP_PSR_TP4_TIME_0us;
if (dev_priv->params.psr_safest_params) {
val |= EDP_PSR_TP1_TIME_2500us;
@@ -448,9 +531,9 @@ static u32 intel_psr1_get_tp_time(struct intel_dp *intel_dp)
check_tp3_sel:
if (intel_dp_source_supports_tps3(dev_priv) &&
drm_dp_tps3_supported(intel_dp->dpcd))
- val |= EDP_PSR_TP1_TP3_SEL;
+ val |= EDP_PSR_TP_TP1_TP3;
else
- val |= EDP_PSR_TP1_TP2_SEL;
+ val |= EDP_PSR_TP_TP1_TP2;
return val;
}
@@ -476,12 +559,13 @@ static u8 psr_compute_idle_frames(struct intel_dp *intel_dp)
static void hsw_activate_psr1(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 max_sleep_time = 0x1f;
u32 val = EDP_PSR_ENABLE;
- val |= psr_compute_idle_frames(intel_dp) << EDP_PSR_IDLE_FRAME_SHIFT;
+ val |= EDP_PSR_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
- val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT;
+ val |= EDP_PSR_MAX_SLEEP_TIME(max_sleep_time);
if (IS_HASWELL(dev_priv))
val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
@@ -493,9 +577,8 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
if (DISPLAY_VER(dev_priv) >= 8)
val |= EDP_PSR_CRC_ENABLE;
- val |= (intel_de_read(dev_priv, EDP_PSR_CTL(intel_dp->psr.transcoder)) &
- EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK);
- intel_de_write(dev_priv, EDP_PSR_CTL(intel_dp->psr.transcoder), val);
+ intel_de_rmw(dev_priv, EDP_PSR_CTL(cpu_transcoder),
+ ~EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK, val);
}
static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp)
@@ -534,9 +617,10 @@ static int psr2_block_count(struct intel_dp *intel_dp)
static void hsw_activate_psr2(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 val = EDP_PSR2_ENABLE;
- val |= psr_compute_idle_frames(intel_dp) << EDP_PSR2_IDLE_FRAME_SHIFT;
+ val |= EDP_PSR2_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
if (DISPLAY_VER(dev_priv) <= 13 && !IS_ALDERLAKE_P(dev_priv))
val |= EDP_SU_TRACK_ENABLE;
@@ -570,15 +654,13 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
* Still using the default IO_BUFFER_WAKE and FAST_WAKE, see
* comments bellow for more information
*/
- u32 tmp;
+ int tmp;
tmp = map[intel_dp->psr.io_wake_lines - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES];
- tmp = tmp << TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT;
- val |= tmp;
+ val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(tmp + TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES);
tmp = map[intel_dp->psr.fast_wake_lines - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
- tmp = tmp << TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT;
- val |= tmp;
+ val |= TGL_EDP_PSR2_FAST_WAKE(tmp + TGL_EDP_PSR2_FAST_WAKE_MIN_LINES);
} else if (DISPLAY_VER(dev_priv) >= 12) {
val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->psr.io_wake_lines);
val |= TGL_EDP_PSR2_FAST_WAKE(intel_dp->psr.fast_wake_lines);
@@ -593,31 +675,30 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
if (intel_dp->psr.psr2_sel_fetch_enabled) {
u32 tmp;
- tmp = intel_de_read(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder));
+ tmp = intel_de_read(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder));
drm_WARN_ON(&dev_priv->drm, !(tmp & PSR2_MAN_TRK_CTL_ENABLE));
} else if (HAS_PSR2_SEL_FETCH(dev_priv)) {
- intel_de_write(dev_priv,
- PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), 0);
+ intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder), 0);
}
/*
* PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is
* recommending keep this bit unset while PSR2 is enabled.
*/
- intel_de_write(dev_priv, EDP_PSR_CTL(intel_dp->psr.transcoder), 0);
+ intel_de_write(dev_priv, EDP_PSR_CTL(cpu_transcoder), 0);
- intel_de_write(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder), val);
+ intel_de_write(dev_priv, EDP_PSR2_CTL(cpu_transcoder), val);
}
static bool
-transcoder_has_psr2(struct drm_i915_private *dev_priv, enum transcoder trans)
+transcoder_has_psr2(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder)
{
if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14)
- return trans == TRANSCODER_A || trans == TRANSCODER_B;
+ return cpu_transcoder == TRANSCODER_A || cpu_transcoder == TRANSCODER_B;
else if (DISPLAY_VER(dev_priv) >= 12)
- return trans == TRANSCODER_A;
+ return cpu_transcoder == TRANSCODER_A;
else
- return trans == TRANSCODER_EDP;
+ return cpu_transcoder == TRANSCODER_EDP;
}
static u32 intel_get_frame_time_us(const struct intel_crtc_state *cstate)
@@ -633,10 +714,11 @@ static void psr2_program_idle_frames(struct intel_dp *intel_dp,
u32 idle_frames)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
- idle_frames <<= EDP_PSR2_IDLE_FRAME_SHIFT;
- intel_de_rmw(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder),
- EDP_PSR2_IDLE_FRAME_MASK, idle_frames);
+ intel_de_rmw(dev_priv, EDP_PSR2_CTL(cpu_transcoder),
+ EDP_PSR2_IDLE_FRAMES_MASK,
+ EDP_PSR2_IDLE_FRAMES(idle_frames));
}
static void tgl_psr2_enable_dc3co(struct intel_dp *intel_dp)
@@ -1074,6 +1156,7 @@ void intel_psr_get_config(struct intel_encoder *encoder,
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+ enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
struct intel_dp *intel_dp;
u32 val;
@@ -1100,15 +1183,14 @@ void intel_psr_get_config(struct intel_encoder *encoder,
goto unlock;
if (HAS_PSR2_SEL_FETCH(dev_priv)) {
- val = intel_de_read(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder));
+ val = intel_de_read(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder));
if (val & PSR2_MAN_TRK_CTL_ENABLE)
pipe_config->enable_psr2_sel_fetch = true;
}
if (DISPLAY_VER(dev_priv) >= 12) {
- val = intel_de_read(dev_priv, TRANS_EXITLINE(intel_dp->psr.transcoder));
- val &= EXITLINE_MASK;
- pipe_config->dc3co_exitline = val;
+ val = intel_de_read(dev_priv, TRANS_EXITLINE(cpu_transcoder));
+ pipe_config->dc3co_exitline = REG_FIELD_GET(EXITLINE_MASK, val);
}
unlock:
mutex_unlock(&intel_dp->psr.lock);
@@ -1117,14 +1199,14 @@ unlock:
static void intel_psr_activate(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
- enum transcoder transcoder = intel_dp->psr.transcoder;
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
- if (transcoder_has_psr2(dev_priv, transcoder))
+ if (transcoder_has_psr2(dev_priv, cpu_transcoder))
drm_WARN_ON(&dev_priv->drm,
- intel_de_read(dev_priv, EDP_PSR2_CTL(transcoder)) & EDP_PSR2_ENABLE);
+ intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder)) & EDP_PSR2_ENABLE);
drm_WARN_ON(&dev_priv->drm,
- intel_de_read(dev_priv, EDP_PSR_CTL(transcoder)) & EDP_PSR_ENABLE);
+ intel_de_read(dev_priv, EDP_PSR_CTL(cpu_transcoder)) & EDP_PSR_ENABLE);
drm_WARN_ON(&dev_priv->drm, intel_dp->psr.active);
lockdep_assert_held(&intel_dp->psr.lock);
@@ -1203,7 +1285,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
if (DISPLAY_VER(dev_priv) < 11)
mask |= EDP_PSR_DEBUG_MASK_DISP_REG_WRITE;
- intel_de_write(dev_priv, EDP_PSR_DEBUG(intel_dp->psr.transcoder),
+ intel_de_write(dev_priv, EDP_PSR_DEBUG(cpu_transcoder),
mask);
psr_irq_control(intel_dp);
@@ -1259,6 +1341,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
static bool psr_interrupt_error_check(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 val;
/*
@@ -1270,8 +1353,7 @@ static bool psr_interrupt_error_check(struct intel_dp *intel_dp)
* to avoid any rendering problems.
*/
if (DISPLAY_VER(dev_priv) >= 12)
- val = intel_de_read(dev_priv,
- TRANS_PSR_IIR(intel_dp->psr.transcoder));
+ val = intel_de_read(dev_priv, TRANS_PSR_IIR(cpu_transcoder));
else
val = intel_de_read(dev_priv, EDP_PSR_IIR);
val &= psr_irq_psr_error_bit_get(intel_dp);
@@ -1327,17 +1409,16 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
static void intel_psr_exit(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 val;
if (!intel_dp->psr.active) {
- if (transcoder_has_psr2(dev_priv, intel_dp->psr.transcoder)) {
- val = intel_de_read(dev_priv,
- EDP_PSR2_CTL(intel_dp->psr.transcoder));
+ if (transcoder_has_psr2(dev_priv, cpu_transcoder)) {
+ val = intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder));
drm_WARN_ON(&dev_priv->drm, val & EDP_PSR2_ENABLE);
}
- val = intel_de_read(dev_priv,
- EDP_PSR_CTL(intel_dp->psr.transcoder));
+ val = intel_de_read(dev_priv, EDP_PSR_CTL(cpu_transcoder));
drm_WARN_ON(&dev_priv->drm, val & EDP_PSR_ENABLE);
return;
@@ -1345,19 +1426,16 @@ static void intel_psr_exit(struct intel_dp *intel_dp)
if (intel_dp->psr.psr2_enabled) {
tgl_disallow_dc3co_on_psr2_exit(intel_dp);
- val = intel_de_read(dev_priv,
- EDP_PSR2_CTL(intel_dp->psr.transcoder));
+
+ val = intel_de_rmw(dev_priv, EDP_PSR2_CTL(cpu_transcoder),
+ EDP_PSR2_ENABLE, 0);
+
drm_WARN_ON(&dev_priv->drm, !(val & EDP_PSR2_ENABLE));
- val &= ~EDP_PSR2_ENABLE;
- intel_de_write(dev_priv,
- EDP_PSR2_CTL(intel_dp->psr.transcoder), val);
} else {
- val = intel_de_read(dev_priv,
- EDP_PSR_CTL(intel_dp->psr.transcoder));
+ val = intel_de_rmw(dev_priv, EDP_PSR_CTL(cpu_transcoder),
+ EDP_PSR_ENABLE, 0);
+
drm_WARN_ON(&dev_priv->drm, !(val & EDP_PSR_ENABLE));
- val &= ~EDP_PSR_ENABLE;
- intel_de_write(dev_priv,
- EDP_PSR_CTL(intel_dp->psr.transcoder), val);
}
intel_dp->psr.active = false;
}
@@ -1365,14 +1443,15 @@ static void intel_psr_exit(struct intel_dp *intel_dp)
static void intel_psr_wait_exit_locked(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
i915_reg_t psr_status;
u32 psr_status_mask;
if (intel_dp->psr.psr2_enabled) {
- psr_status = EDP_PSR2_STATUS(intel_dp->psr.transcoder);
+ psr_status = EDP_PSR2_STATUS(cpu_transcoder);
psr_status_mask = EDP_PSR2_STATUS_STATE_MASK;
} else {
- psr_status = EDP_PSR_STATUS(intel_dp->psr.transcoder);
+ psr_status = EDP_PSR_STATUS(cpu_transcoder);
psr_status_mask = EDP_PSR_STATUS_STATE_MASK;
}
@@ -1385,6 +1464,7 @@ static void intel_psr_wait_exit_locked(struct intel_dp *intel_dp)
static void intel_psr_disable_locked(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
enum phy phy = intel_port_to_phy(dev_priv,
dp_to_dig_port(intel_dp)->base.port);
@@ -1411,7 +1491,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
/* Wa_16012604467:adlp,mtl[a0,b0] */
if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
intel_de_rmw(dev_priv,
- MTL_CLKGATE_DIS_TRANS(intel_dp->psr.transcoder),
+ MTL_CLKGATE_DIS_TRANS(cpu_transcoder),
MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS, 0);
else if (IS_ALDERLAKE_P(dev_priv))
intel_de_rmw(dev_priv, CLKGATE_DIS_MISC,
@@ -1548,10 +1628,11 @@ static u32 man_trk_ctl_continuos_full_frame(struct drm_i915_private *dev_priv)
static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
if (intel_dp->psr.psr2_sel_fetch_enabled)
intel_de_write(dev_priv,
- PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
+ PSR2_MAN_TRK_CTL(cpu_transcoder),
man_trk_ctl_enable_bit_get(dev_priv) |
man_trk_ctl_partial_frame_bit_get(dev_priv) |
man_trk_ctl_single_full_frame_bit_get(dev_priv) |
@@ -1651,6 +1732,7 @@ void intel_psr2_program_plane_sel_fetch_noarm(struct intel_plane *plane,
void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
struct intel_encoder *encoder;
if (!crtc_state->enable_psr2_sel_fetch)
@@ -1666,7 +1748,7 @@ void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_st
break;
}
- intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(crtc_state->cpu_transcoder),
+ intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder),
crtc_state->psr2_man_track_ctl);
}
@@ -2045,6 +2127,7 @@ void intel_psr_post_plane_update(const struct intel_atomic_state *state)
static int _psr2_ready_for_pipe_update_locked(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
/*
* Any state lower than EDP_PSR2_STATUS_STATE_DEEP_SLEEP is enough.
@@ -2052,13 +2135,14 @@ static int _psr2_ready_for_pipe_update_locked(struct intel_dp *intel_dp)
* EDP_PSR2_STATUS_STATE_DEEP_SLEEP to be cleared.
*/
return intel_de_wait_for_clear(dev_priv,
- EDP_PSR2_STATUS(intel_dp->psr.transcoder),
+ EDP_PSR2_STATUS(cpu_transcoder),
EDP_PSR2_STATUS_STATE_DEEP_SLEEP, 50);
}
static int _psr1_ready_for_pipe_update_locked(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
/*
* From bspec: Panel Self Refresh (BDW+)
@@ -2067,7 +2151,7 @@ static int _psr1_ready_for_pipe_update_locked(struct intel_dp *intel_dp)
* defensive enough to cover everything.
*/
return intel_de_wait_for_clear(dev_priv,
- EDP_PSR_STATUS(intel_dp->psr.transcoder),
+ EDP_PSR_STATUS(cpu_transcoder),
EDP_PSR_STATUS_STATE_MASK, 50);
}
@@ -2109,6 +2193,7 @@ void intel_psr_wait_for_idle_locked(const struct intel_crtc_state *new_crtc_stat
static bool __psr_wait_for_idle_locked(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
i915_reg_t reg;
u32 mask;
int err;
@@ -2117,10 +2202,10 @@ static bool __psr_wait_for_idle_locked(struct intel_dp *intel_dp)
return false;
if (intel_dp->psr.psr2_enabled) {
- reg = EDP_PSR2_STATUS(intel_dp->psr.transcoder);
+ reg = EDP_PSR2_STATUS(cpu_transcoder);
mask = EDP_PSR2_STATUS_STATE_MASK;
} else {
- reg = EDP_PSR_STATUS(intel_dp->psr.transcoder);
+ reg = EDP_PSR_STATUS(cpu_transcoder);
mask = EDP_PSR_STATUS_STATE_MASK;
}
@@ -2149,10 +2234,11 @@ static int intel_psr_fastset_force(struct drm_i915_private *dev_priv)
return -ENOMEM;
drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
+
state->acquire_ctx = &ctx;
+ to_intel_atomic_state(state)->internal = true;
retry:
-
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_for_each_connector_iter(conn, &conn_iter) {
struct drm_connector_state *conn_state;
@@ -2281,6 +2367,7 @@ unlock:
static void _psr_invalidate_handle(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
if (intel_dp->psr.psr2_sel_fetch_enabled) {
u32 val;
@@ -2294,7 +2381,7 @@ static void _psr_invalidate_handle(struct intel_dp *intel_dp)
val = man_trk_ctl_enable_bit_get(dev_priv) |
man_trk_ctl_partial_frame_bit_get(dev_priv) |
man_trk_ctl_continuos_full_frame(dev_priv);
- intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), val);
+ intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder), val);
intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0);
intel_dp->psr.psr2_sel_fetch_cff_enabled = true;
} else {
@@ -2353,6 +2440,8 @@ static void
tgl_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
enum fb_op_origin origin)
{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
if (!intel_dp->psr.dc3co_exitline || !intel_dp->psr.psr2_enabled ||
!intel_dp->psr.active)
return;
@@ -2366,13 +2455,14 @@ tgl_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
return;
tgl_psr2_enable_dc3co(intel_dp);
- mod_delayed_work(system_wq, &intel_dp->psr.dc3co_work,
+ mod_delayed_work(i915->unordered_wq, &intel_dp->psr.dc3co_work,
intel_dp->psr.dc3co_exit_delay);
}
static void _psr_flush_handle(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
if (intel_dp->psr.psr2_sel_fetch_enabled) {
if (intel_dp->psr.psr2_sel_fetch_cff_enabled) {
@@ -2389,7 +2479,7 @@ static void _psr_flush_handle(struct intel_dp *intel_dp)
* SU configuration in case update is sent for any reason after
* sff bit gets cleared by the HW on next vblank.
*/
- intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
+ intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder),
val);
intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0);
intel_dp->psr.psr2_sel_fetch_cff_enabled = false;
@@ -2405,7 +2495,7 @@ static void _psr_flush_handle(struct intel_dp *intel_dp)
psr_force_hw_tracking_exit(intel_dp);
if (!intel_dp->psr.active && !intel_dp->psr.busy_frontbuffer_bits)
- schedule_work(&intel_dp->psr.work);
+ queue_work(dev_priv->unordered_wq, &intel_dp->psr.work);
}
}
@@ -2702,6 +2792,7 @@ static void
psr_source_status(struct intel_dp *intel_dp, struct seq_file *m)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
const char *status = "unknown";
u32 val, status_val;
@@ -2719,8 +2810,7 @@ psr_source_status(struct intel_dp *intel_dp, struct seq_file *m)
"BUF_ON",
"TG_ON"
};
- val = intel_de_read(dev_priv,
- EDP_PSR2_STATUS(intel_dp->psr.transcoder));
+ val = intel_de_read(dev_priv, EDP_PSR2_STATUS(cpu_transcoder));
status_val = REG_FIELD_GET(EDP_PSR2_STATUS_STATE_MASK, val);
if (status_val < ARRAY_SIZE(live_status))
status = live_status[status_val];
@@ -2735,10 +2825,8 @@ psr_source_status(struct intel_dp *intel_dp, struct seq_file *m)
"SRDOFFACK",
"SRDENT_ON",
};
- val = intel_de_read(dev_priv,
- EDP_PSR_STATUS(intel_dp->psr.transcoder));
- status_val = (val & EDP_PSR_STATUS_STATE_MASK) >>
- EDP_PSR_STATUS_STATE_SHIFT;
+ val = intel_de_read(dev_priv, EDP_PSR_STATUS(cpu_transcoder));
+ status_val = REG_FIELD_GET(EDP_PSR_STATUS_STATE_MASK, val);
if (status_val < ARRAY_SIZE(live_status))
status = live_status[status_val];
}
@@ -2749,6 +2837,7 @@ psr_source_status(struct intel_dp *intel_dp, struct seq_file *m)
static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
struct intel_psr *psr = &intel_dp->psr;
intel_wakeref_t wakeref;
const char *status;
@@ -2780,12 +2869,10 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
}
if (psr->psr2_enabled) {
- val = intel_de_read(dev_priv,
- EDP_PSR2_CTL(intel_dp->psr.transcoder));
+ val = intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder));
enabled = val & EDP_PSR2_ENABLE;
} else {
- val = intel_de_read(dev_priv,
- EDP_PSR_CTL(intel_dp->psr.transcoder));
+ val = intel_de_read(dev_priv, EDP_PSR_CTL(cpu_transcoder));
enabled = val & EDP_PSR_ENABLE;
}
seq_printf(m, "Source PSR ctl: %s [0x%08x]\n",
@@ -2797,12 +2884,9 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
/*
* SKL+ Perf counter is reset to 0 everytime DC state is entered
*/
- if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
- val = intel_de_read(dev_priv,
- EDP_PSR_PERF_CNT(intel_dp->psr.transcoder));
- val &= EDP_PSR_PERF_CNT_MASK;
- seq_printf(m, "Performance counter: %u\n", val);
- }
+ val = intel_de_read(dev_priv, EDP_PSR_PERF_CNT(cpu_transcoder));
+ seq_printf(m, "Performance counter: %u\n",
+ REG_FIELD_GET(EDP_PSR_PERF_CNT_MASK, val));
if (psr->debug & I915_PSR_DEBUG_IRQ) {
seq_printf(m, "Last attempted entry at: %lld\n",
@@ -2819,8 +2903,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
* frame boundary between register reads
*/
for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame += 3) {
- val = intel_de_read(dev_priv,
- PSR2_SU_STATUS(intel_dp->psr.transcoder, frame));
+ val = intel_de_read(dev_priv, PSR2_SU_STATUS(cpu_transcoder, frame));
su_frames_val[frame / 3] = val;
}
diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h
index 958d8cabc44b..0f7db617425a 100644
--- a/drivers/gpu/drm/i915/display/intel_psr_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h
@@ -22,30 +22,36 @@
#define _SRD_CTL_A 0x60800
#define _SRD_CTL_EDP 0x6f800
#define EDP_PSR_CTL(tran) _MMIO_TRANS2(tran, _SRD_CTL_A)
-#define EDP_PSR_ENABLE (1 << 31)
-#define BDW_PSR_SINGLE_FRAME (1 << 30)
-#define EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK (1 << 29) /* SW can't modify */
-#define EDP_PSR_LINK_STANDBY (1 << 27)
-#define EDP_PSR_MIN_LINK_ENTRY_TIME_MASK (3 << 25)
-#define EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES (0 << 25)
-#define EDP_PSR_MIN_LINK_ENTRY_TIME_4_LINES (1 << 25)
-#define EDP_PSR_MIN_LINK_ENTRY_TIME_2_LINES (2 << 25)
-#define EDP_PSR_MIN_LINK_ENTRY_TIME_0_LINES (3 << 25)
-#define EDP_PSR_MAX_SLEEP_TIME_SHIFT 20
-#define EDP_PSR_SKIP_AUX_EXIT (1 << 12)
-#define EDP_PSR_TP1_TP2_SEL (0 << 11)
-#define EDP_PSR_TP1_TP3_SEL (1 << 11)
-#define EDP_PSR_CRC_ENABLE (1 << 10) /* BDW+ */
-#define EDP_PSR_TP2_TP3_TIME_500us (0 << 8)
-#define EDP_PSR_TP2_TP3_TIME_100us (1 << 8)
-#define EDP_PSR_TP2_TP3_TIME_2500us (2 << 8)
-#define EDP_PSR_TP2_TP3_TIME_0us (3 << 8)
-#define EDP_PSR_TP4_TIME_0US (3 << 6) /* ICL+ */
-#define EDP_PSR_TP1_TIME_500us (0 << 4)
-#define EDP_PSR_TP1_TIME_100us (1 << 4)
-#define EDP_PSR_TP1_TIME_2500us (2 << 4)
-#define EDP_PSR_TP1_TIME_0us (3 << 4)
-#define EDP_PSR_IDLE_FRAME_SHIFT 0
+#define EDP_PSR_ENABLE REG_BIT(31)
+#define BDW_PSR_SINGLE_FRAME REG_BIT(30)
+#define EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK REG_BIT(29) /* SW can't modify */
+#define EDP_PSR_LINK_STANDBY REG_BIT(27)
+#define EDP_PSR_MIN_LINK_ENTRY_TIME_MASK REG_GENMASK(26, 25)
+#define EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES REG_FIELD_PREP(EDP_PSR_MIN_LINK_ENTRY_TIME_MASK, 0)
+#define EDP_PSR_MIN_LINK_ENTRY_TIME_4_LINES REG_FIELD_PREP(EDP_PSR_MIN_LINK_ENTRY_TIME_MASK, 1)
+#define EDP_PSR_MIN_LINK_ENTRY_TIME_2_LINES REG_FIELD_PREP(EDP_PSR_MIN_LINK_ENTRY_TIME_MASK, 2)
+#define EDP_PSR_MIN_LINK_ENTRY_TIME_0_LINES REG_FIELD_PREP(EDP_PSR_MIN_LINK_ENTRY_TIME_MASK, 3)
+#define EDP_PSR_MAX_SLEEP_TIME_MASK REG_GENMASK(24, 20)
+#define EDP_PSR_MAX_SLEEP_TIME(x) REG_FIELD_PREP(EDP_PSR_MAX_SLEEP_TIME_MASK, (x))
+#define EDP_PSR_SKIP_AUX_EXIT REG_BIT(12)
+#define EDP_PSR_TP_MASK REG_BIT(11)
+#define EDP_PSR_TP_TP1_TP2 REG_FIELD_PREP(EDP_PSR_TP_MASK, 0)
+#define EDP_PSR_TP_TP1_TP3 REG_FIELD_PREP(EDP_PSR_TP_MASK, 1)
+#define EDP_PSR_CRC_ENABLE REG_BIT(10) /* BDW+ */
+#define EDP_PSR_TP2_TP3_TIME_MASK REG_GENMASK(9, 8)
+#define EDP_PSR_TP2_TP3_TIME_500us REG_FIELD_PREP(EDP_PSR_TP2_TP3_TIME_MASK, 0)
+#define EDP_PSR_TP2_TP3_TIME_100us REG_FIELD_PREP(EDP_PSR_TP2_TP3_TIME_MASK, 1)
+#define EDP_PSR_TP2_TP3_TIME_2500us REG_FIELD_PREP(EDP_PSR_TP2_TP3_TIME_MASK, 2)
+#define EDP_PSR_TP2_TP3_TIME_0us REG_FIELD_PREP(EDP_PSR_TP2_TP3_TIME_MASK, 3)
+#define EDP_PSR_TP4_TIME_MASK REG_GENMASK(7, 6)
+#define EDP_PSR_TP4_TIME_0us REG_FIELD_PREP(EDP_PSR_TP4_TIME_MASK, 3) /* ICL+ */
+#define EDP_PSR_TP1_TIME_MASK REG_GENMASK(5, 4)
+#define EDP_PSR_TP1_TIME_500us REG_FIELD_PREP(EDP_PSR_TP1_TIME_MASK, 0)
+#define EDP_PSR_TP1_TIME_100us REG_FIELD_PREP(EDP_PSR_TP1_TIME_MASK, 1)
+#define EDP_PSR_TP1_TIME_2500us REG_FIELD_PREP(EDP_PSR_TP1_TIME_MASK, 2)
+#define EDP_PSR_TP1_TIME_0us REG_FIELD_PREP(EDP_PSR_TP1_TIME_MASK, 3)
+#define EDP_PSR_IDLE_FRAMES_MASK REG_GENMASK(3, 0)
+#define EDP_PSR_IDLE_FRAMES(x) REG_FIELD_PREP(EDP_PSR_IDLE_FRAMES_MASK, (x))
/*
* Until TGL, IMR/IIR are fixed at 0x648xx. On TGL+ those registers are relative
@@ -80,81 +86,90 @@
#define _SRD_STATUS_A 0x60840
#define _SRD_STATUS_EDP 0x6f840
#define EDP_PSR_STATUS(tran) _MMIO_TRANS2(tran, _SRD_STATUS_A)
-#define EDP_PSR_STATUS_STATE_MASK (7 << 29)
-#define EDP_PSR_STATUS_STATE_SHIFT 29
-#define EDP_PSR_STATUS_STATE_IDLE (0 << 29)
-#define EDP_PSR_STATUS_STATE_SRDONACK (1 << 29)
-#define EDP_PSR_STATUS_STATE_SRDENT (2 << 29)
-#define EDP_PSR_STATUS_STATE_BUFOFF (3 << 29)
-#define EDP_PSR_STATUS_STATE_BUFON (4 << 29)
-#define EDP_PSR_STATUS_STATE_AUXACK (5 << 29)
-#define EDP_PSR_STATUS_STATE_SRDOFFACK (6 << 29)
-#define EDP_PSR_STATUS_LINK_MASK (3 << 26)
-#define EDP_PSR_STATUS_LINK_FULL_OFF (0 << 26)
-#define EDP_PSR_STATUS_LINK_FULL_ON (1 << 26)
-#define EDP_PSR_STATUS_LINK_STANDBY (2 << 26)
-#define EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT 20
-#define EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK 0x1f
-#define EDP_PSR_STATUS_COUNT_SHIFT 16
-#define EDP_PSR_STATUS_COUNT_MASK 0xf
-#define EDP_PSR_STATUS_AUX_ERROR (1 << 15)
-#define EDP_PSR_STATUS_AUX_SENDING (1 << 12)
-#define EDP_PSR_STATUS_SENDING_IDLE (1 << 9)
-#define EDP_PSR_STATUS_SENDING_TP2_TP3 (1 << 8)
-#define EDP_PSR_STATUS_SENDING_TP1 (1 << 4)
-#define EDP_PSR_STATUS_IDLE_MASK 0xf
+#define EDP_PSR_STATUS_STATE_MASK REG_GENMASK(31, 29)
+#define EDP_PSR_STATUS_STATE_IDLE REG_FIELD_PREP(EDP_PSR_STATUS_STATE_MASK, 0)
+#define EDP_PSR_STATUS_STATE_SRDONACK REG_FIELD_PREP(EDP_PSR_STATUS_STATE_MASK, 1)
+#define EDP_PSR_STATUS_STATE_SRDENT REG_FIELD_PREP(EDP_PSR_STATUS_STATE_MASK, 2)
+#define EDP_PSR_STATUS_STATE_BUFOFF REG_FIELD_PREP(EDP_PSR_STATUS_STATE_MASK, 3)
+#define EDP_PSR_STATUS_STATE_BUFON REG_FIELD_PREP(EDP_PSR_STATUS_STATE_MASK, 4)
+#define EDP_PSR_STATUS_STATE_AUXACK REG_FIELD_PREP(EDP_PSR_STATUS_STATE_MASK, 5)
+#define EDP_PSR_STATUS_STATE_SRDOFFACK REG_FIELD_PREP(EDP_PSR_STATUS_STATE_MASK, 6)
+#define EDP_PSR_STATUS_LINK_MASK REG_GENMASK(27, 26)
+#define EDP_PSR_STATUS_LINK_FULL_OFF REG_FIELD_PREP(EDP_PSR_STATUS_LINK_MASK, 0)
+#define EDP_PSR_STATUS_LINK_FULL_ON REG_FIELD_PREP(EDP_PSR_STATUS_LINK_MASK, 1)
+#define EDP_PSR_STATUS_LINK_STANDBY REG_FIELD_PREP(EDP_PSR_STATUS_LINK_MASK, 2)
+#define EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK REG_GENMASK(24, 20)
+#define EDP_PSR_STATUS_COUNT_MASK REG_GENMASK(19, 16)
+#define EDP_PSR_STATUS_AUX_ERROR REG_BIT(15)
+#define EDP_PSR_STATUS_AUX_SENDING REG_BIT(12)
+#define EDP_PSR_STATUS_SENDING_IDLE REG_BIT(9)
+#define EDP_PSR_STATUS_SENDING_TP2_TP3 REG_BIT(8)
+#define EDP_PSR_STATUS_SENDING_TP1 REG_BIT(4)
+#define EDP_PSR_STATUS_IDLE_MASK REG_GENMASK(3, 0)
#define _SRD_PERF_CNT_A 0x60844
#define _SRD_PERF_CNT_EDP 0x6f844
#define EDP_PSR_PERF_CNT(tran) _MMIO_TRANS2(tran, _SRD_PERF_CNT_A)
-#define EDP_PSR_PERF_CNT_MASK 0xffffff
+#define EDP_PSR_PERF_CNT_MASK REG_GENMASK(23, 0)
/* PSR_MASK on SKL+ */
#define _SRD_DEBUG_A 0x60860
#define _SRD_DEBUG_EDP 0x6f860
#define EDP_PSR_DEBUG(tran) _MMIO_TRANS2(tran, _SRD_DEBUG_A)
-#define EDP_PSR_DEBUG_MASK_MAX_SLEEP (1 << 28)
-#define EDP_PSR_DEBUG_MASK_LPSP (1 << 27)
-#define EDP_PSR_DEBUG_MASK_MEMUP (1 << 26)
-#define EDP_PSR_DEBUG_MASK_HPD (1 << 25)
-#define EDP_PSR_DEBUG_MASK_DISP_REG_WRITE (1 << 16) /* Reserved in ICL+ */
-#define EDP_PSR_DEBUG_EXIT_ON_PIXEL_UNDERRUN (1 << 15) /* SKL+ */
+#define EDP_PSR_DEBUG_MASK_MAX_SLEEP REG_BIT(28)
+#define EDP_PSR_DEBUG_MASK_LPSP REG_BIT(27)
+#define EDP_PSR_DEBUG_MASK_MEMUP REG_BIT(26)
+#define EDP_PSR_DEBUG_MASK_HPD REG_BIT(25)
+#define EDP_PSR_DEBUG_MASK_FBC_MODIFY REG_BIT(24)
+#define EDP_PSR_DEBUG_MASK_PRIMARY_FLIP REG_BIT(23) /* hsw */
+#define EDP_PSR_DEBUG_MASK_HDCP_ENABLE REG_BIT(22) /* hsw/bdw */
+#define EDP_PSR_DEBUG_MASK_SPRITE_ENABLE REG_BIT(21) /* hsw */
+#define EDP_PSR_DEBUG_MASK_CURSOR_MOVE REG_BIT(20) /* hsw */
+#define EDP_PSR_DEBUG_MASK_VBLANK_VSYNC_INT REG_BIT(19) /* hsw */
+#define EDP_PSR_DEBUG_MASK_DPST_PHASE_IN REG_BIT(18) /* hsw */
+#define EDP_PSR_DEBUG_MASK_KVMR_SESSION_EN REG_BIT(17)
+#define EDP_PSR_DEBUG_MASK_DISP_REG_WRITE REG_BIT(16) /* hsw-skl */
+#define EDP_PSR_DEBUG_EXIT_ON_PIXEL_UNDERRUN REG_BIT(15) /* skl+ */
+#define EDP_PSR_DEBUG_RFB_UPDATE_SENT REG_BIT(2) /* bdw */
+#define EDP_PSR_DEBUG_ENTRY_COMPLETION REG_BIT(1) /* hsw/bdw */
#define _PSR2_CTL_A 0x60900
#define _PSR2_CTL_EDP 0x6f900
#define EDP_PSR2_CTL(tran) _MMIO_TRANS2(tran, _PSR2_CTL_A)
-#define EDP_PSR2_ENABLE (1 << 31)
-#define EDP_SU_TRACK_ENABLE (1 << 30) /* up to adl-p */
-#define TGL_EDP_PSR2_BLOCK_COUNT_NUM_2 (0 << 28)
-#define TGL_EDP_PSR2_BLOCK_COUNT_NUM_3 (1 << 28)
+#define EDP_PSR2_ENABLE REG_BIT(31)
+#define EDP_SU_TRACK_ENABLE REG_BIT(30) /* up to adl-p */
+#define TGL_EDP_PSR2_BLOCK_COUNT_MASK REG_BIT(28)
+#define TGL_EDP_PSR2_BLOCK_COUNT_NUM_2 REG_FIELD_PREP(TGL_EDP_PSR2_BLOCK_COUNT_MASK, 0)
+#define TGL_EDP_PSR2_BLOCK_COUNT_NUM_3 REG_FIELD_PREP(TGL_EDP_PSR2_BLOCK_COUNT_MASK, 1)
#define EDP_Y_COORDINATE_ENABLE REG_BIT(25) /* display 10, 11 and 12 */
#define EDP_PSR2_SU_SDP_SCANLINE REG_BIT(25) /* display 13+ */
-#define EDP_MAX_SU_DISABLE_TIME(t) ((t) << 20)
-#define EDP_MAX_SU_DISABLE_TIME_MASK (0x1f << 20)
+#define EDP_MAX_SU_DISABLE_TIME_MASK REG_GENMASK(24, 20)
+#define EDP_MAX_SU_DISABLE_TIME(t) REG_FIELD_PREP(EDP_MAX_SU_DISABLE_TIME, (t))
+#define EDP_PSR2_IO_BUFFER_WAKE_MASK REG_GENMASK(14, 13)
#define EDP_PSR2_IO_BUFFER_WAKE_MAX_LINES 8
-#define EDP_PSR2_IO_BUFFER_WAKE(lines) ((EDP_PSR2_IO_BUFFER_WAKE_MAX_LINES - (lines)) << 13)
-#define EDP_PSR2_IO_BUFFER_WAKE_MASK (3 << 13)
+#define EDP_PSR2_IO_BUFFER_WAKE(lines) REG_FIELD_PREP(EDP_PSR2_IO_BUFFER_WAKE_MASK, \
+ EDP_PSR2_IO_BUFFER_WAKE_MAX_LINES - (lines))
+#define TGL_EDP_PSR2_IO_BUFFER_WAKE_MASK REG_GENMASK(15, 13)
#define TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES 5
-#define TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT 13
-#define TGL_EDP_PSR2_IO_BUFFER_WAKE(lines) (((lines) - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES) << TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT)
-#define TGL_EDP_PSR2_IO_BUFFER_WAKE_MASK (7 << 13)
+#define TGL_EDP_PSR2_IO_BUFFER_WAKE(lines) REG_FIELD_PREP(TGL_EDP_PSR2_IO_BUFFER_WAKE_MASK, \
+ (lines) - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES)
+#define EDP_PSR2_FAST_WAKE_MASK REG_GENMASK(12, 11)
#define EDP_PSR2_FAST_WAKE_MAX_LINES 8
-#define EDP_PSR2_FAST_WAKE(lines) ((EDP_PSR2_FAST_WAKE_MAX_LINES - (lines)) << 11)
-#define EDP_PSR2_FAST_WAKE_MASK (3 << 11)
+#define EDP_PSR2_FAST_WAKE(lines) REG_FIELD_PREP(EDP_PSR2_FAST_WAKE_MASK, \
+ EDP_PSR2_FAST_WAKE_MAX_LINES - (lines))
+#define TGL_EDP_PSR2_FAST_WAKE_MASK REG_GENMASK(12, 10)
#define TGL_EDP_PSR2_FAST_WAKE_MIN_LINES 5
-#define TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT 10
-#define TGL_EDP_PSR2_FAST_WAKE(lines) (((lines) - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES) << TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT)
-#define TGL_EDP_PSR2_FAST_WAKE_MASK (7 << 10)
-#define EDP_PSR2_TP2_TIME_500us (0 << 8)
-#define EDP_PSR2_TP2_TIME_100us (1 << 8)
-#define EDP_PSR2_TP2_TIME_2500us (2 << 8)
-#define EDP_PSR2_TP2_TIME_50us (3 << 8)
-#define EDP_PSR2_TP2_TIME_MASK (3 << 8)
-#define EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4
-#define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf << 4)
-#define EDP_PSR2_FRAME_BEFORE_SU(a) ((a) << 4)
-#define EDP_PSR2_IDLE_FRAME_MASK 0xf
-#define EDP_PSR2_IDLE_FRAME_SHIFT 0
+#define TGL_EDP_PSR2_FAST_WAKE(lines) REG_FIELD_PREP(TGL_EDP_PSR2_FAST_WAKE_MASK, \
+ (lines) - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES)
+#define EDP_PSR2_TP2_TIME_MASK REG_GENMASK(9, 8)
+#define EDP_PSR2_TP2_TIME_500us REG_FIELD_PREP(EDP_PSR2_TP2_TIME_MASK, 0)
+#define EDP_PSR2_TP2_TIME_100us REG_FIELD_PREP(EDP_PSR2_TP2_TIME_MASK, 1)
+#define EDP_PSR2_TP2_TIME_2500us REG_FIELD_PREP(EDP_PSR2_TP2_TIME_MASK, 2)
+#define EDP_PSR2_TP2_TIME_50us REG_FIELD_PREP(EDP_PSR2_TP2_TIME_MASK, 3)
+#define EDP_PSR2_FRAME_BEFORE_SU_MASK REG_GENMASK(7, 4)
+#define EDP_PSR2_FRAME_BEFORE_SU(a) REG_FIELD_PREP(EDP_PSR2_FRAME_BEFORE_SU_MASK, (a))
+#define EDP_PSR2_IDLE_FRAMES_MASK REG_GENMASK(3, 0)
+#define EDP_PSR2_IDLE_FRAMES(x) REG_FIELD_PREP(EDP_PSR2_IDLE_FRAMES_MASK, (x))
#define _PSR_EVENT_TRANS_A 0x60848
#define _PSR_EVENT_TRANS_B 0x61848
@@ -162,22 +177,22 @@
#define _PSR_EVENT_TRANS_D 0x63848
#define _PSR_EVENT_TRANS_EDP 0x6f848
#define PSR_EVENT(tran) _MMIO_TRANS2(tran, _PSR_EVENT_TRANS_A)
-#define PSR_EVENT_PSR2_WD_TIMER_EXPIRE (1 << 17)
-#define PSR_EVENT_PSR2_DISABLED (1 << 16)
-#define PSR_EVENT_SU_DIRTY_FIFO_UNDERRUN (1 << 15)
-#define PSR_EVENT_SU_CRC_FIFO_UNDERRUN (1 << 14)
-#define PSR_EVENT_GRAPHICS_RESET (1 << 12)
-#define PSR_EVENT_PCH_INTERRUPT (1 << 11)
-#define PSR_EVENT_MEMORY_UP (1 << 10)
-#define PSR_EVENT_FRONT_BUFFER_MODIFY (1 << 9)
-#define PSR_EVENT_WD_TIMER_EXPIRE (1 << 8)
-#define PSR_EVENT_PIPE_REGISTERS_UPDATE (1 << 6)
-#define PSR_EVENT_REGISTER_UPDATE (1 << 5) /* Reserved in ICL+ */
-#define PSR_EVENT_HDCP_ENABLE (1 << 4)
-#define PSR_EVENT_KVMR_SESSION_ENABLE (1 << 3)
-#define PSR_EVENT_VBI_ENABLE (1 << 2)
-#define PSR_EVENT_LPSP_MODE_EXIT (1 << 1)
-#define PSR_EVENT_PSR_DISABLE (1 << 0)
+#define PSR_EVENT_PSR2_WD_TIMER_EXPIRE REG_BIT(17)
+#define PSR_EVENT_PSR2_DISABLED REG_BIT(16)
+#define PSR_EVENT_SU_DIRTY_FIFO_UNDERRUN REG_BIT(15)
+#define PSR_EVENT_SU_CRC_FIFO_UNDERRUN REG_BIT(14)
+#define PSR_EVENT_GRAPHICS_RESET REG_BIT(12)
+#define PSR_EVENT_PCH_INTERRUPT REG_BIT(11)
+#define PSR_EVENT_MEMORY_UP REG_BIT(10)
+#define PSR_EVENT_FRONT_BUFFER_MODIFY REG_BIT(9)
+#define PSR_EVENT_WD_TIMER_EXPIRE REG_BIT(8)
+#define PSR_EVENT_PIPE_REGISTERS_UPDATE REG_BIT(6)
+#define PSR_EVENT_REGISTER_UPDATE REG_BIT(5) /* Reserved in ICL+ */
+#define PSR_EVENT_HDCP_ENABLE REG_BIT(4)
+#define PSR_EVENT_KVMR_SESSION_ENABLE REG_BIT(3)
+#define PSR_EVENT_VBI_ENABLE REG_BIT(2)
+#define PSR_EVENT_LPSP_MODE_EXIT REG_BIT(1)
+#define PSR_EVENT_PSR_DISABLE REG_BIT(0)
#define _PSR2_STATUS_A 0x60940
#define _PSR2_STATUS_EDP 0x6f940
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index e12ba458636c..21f92123c844 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -117,9 +117,6 @@ struct intel_sdvo {
enum port port;
- bool has_hdmi_monitor;
- bool has_hdmi_audio;
-
/* DDC bus used by this SDVO encoder */
u8 ddc_bus;
@@ -1303,10 +1300,13 @@ static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config)
pipe_config->clock_set = true;
}
-static bool intel_has_hdmi_sink(struct intel_sdvo *sdvo,
+static bool intel_has_hdmi_sink(struct intel_sdvo_connector *intel_sdvo_connector,
const struct drm_connector_state *conn_state)
{
- return sdvo->has_hdmi_monitor &&
+ struct drm_connector *connector = conn_state->connector;
+
+ return intel_sdvo_connector->is_hdmi &&
+ connector->display_info.is_hdmi &&
READ_ONCE(to_intel_digital_connector_state(conn_state)->force_audio) != HDMI_AUDIO_OFF_DVI;
}
@@ -1326,7 +1326,9 @@ static bool intel_sdvo_has_audio(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
- struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
+ struct drm_connector *connector = conn_state->connector;
+ struct intel_sdvo_connector *intel_sdvo_connector =
+ to_intel_sdvo_connector(connector);
const struct intel_digital_connector_state *intel_conn_state =
to_intel_digital_connector_state(conn_state);
@@ -1334,7 +1336,8 @@ static bool intel_sdvo_has_audio(struct intel_encoder *encoder,
return false;
if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
- return intel_sdvo->has_hdmi_audio;
+ return intel_sdvo_connector->is_hdmi &&
+ connector->display_info.has_audio;
else
return intel_conn_state->force_audio == HDMI_AUDIO_ON;
}
@@ -1351,6 +1354,7 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n");
pipe_config->pipe_bpp = 8*3;
+ pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
if (HAS_PCH_SPLIT(to_i915(encoder->base.dev)))
@@ -1400,7 +1404,7 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
pipe_config->pixel_multiplier =
intel_sdvo_get_pixel_multiplier(adjusted_mode);
- pipe_config->has_hdmi_sink = intel_has_hdmi_sink(intel_sdvo, conn_state);
+ pipe_config->has_hdmi_sink = intel_has_hdmi_sink(intel_sdvo_connector, conn_state);
pipe_config->has_audio =
intel_sdvo_has_audio(encoder, pipe_config, conn_state) &&
@@ -1906,7 +1910,7 @@ intel_sdvo_mode_valid(struct drm_connector *connector,
struct intel_sdvo_connector *intel_sdvo_connector =
to_intel_sdvo_connector(connector);
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
- bool has_hdmi_sink = intel_has_hdmi_sink(intel_sdvo, connector->state);
+ bool has_hdmi_sink = intel_has_hdmi_sink(intel_sdvo_connector, connector->state);
int clock = mode->clock;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@ -2032,36 +2036,35 @@ intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
return hweight16(intel_sdvo->caps.output_flags) > 1;
}
-static struct edid *
+static const struct drm_edid *
intel_sdvo_get_edid(struct drm_connector *connector)
{
struct intel_sdvo *sdvo = intel_attached_sdvo(to_intel_connector(connector));
- return drm_get_edid(connector, &sdvo->ddc);
+ return drm_edid_read_ddc(connector, &sdvo->ddc);
}
/* Mac mini hack -- use the same DDC as the analog connector */
-static struct edid *
+static const struct drm_edid *
intel_sdvo_get_analog_edid(struct drm_connector *connector)
{
- struct drm_i915_private *dev_priv = to_i915(connector->dev);
+ struct drm_i915_private *i915 = to_i915(connector->dev);
+ struct i2c_adapter *i2c;
- return drm_get_edid(connector,
- intel_gmbus_get_adapter(dev_priv,
- dev_priv->display.vbt.crt_ddc_pin));
+ i2c = intel_gmbus_get_adapter(i915, i915->display.vbt.crt_ddc_pin);
+
+ return drm_edid_read_ddc(connector, i2c);
}
static enum drm_connector_status
intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
{
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector));
- struct intel_sdvo_connector *intel_sdvo_connector =
- to_intel_sdvo_connector(connector);
enum drm_connector_status status;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
- edid = intel_sdvo_get_edid(connector);
+ drm_edid = intel_sdvo_get_edid(connector);
- if (edid == NULL && intel_sdvo_multifunc_encoder(intel_sdvo)) {
+ if (!drm_edid && intel_sdvo_multifunc_encoder(intel_sdvo)) {
u8 ddc, saved_ddc = intel_sdvo->ddc_bus;
/*
@@ -2070,15 +2073,15 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
*/
for (ddc = intel_sdvo->ddc_bus >> 1; ddc > 1; ddc >>= 1) {
intel_sdvo->ddc_bus = ddc;
- edid = intel_sdvo_get_edid(connector);
- if (edid)
+ drm_edid = intel_sdvo_get_edid(connector);
+ if (drm_edid)
break;
}
/*
* If we found the EDID on the other bus,
* assume that is the correct DDC bus.
*/
- if (edid == NULL)
+ if (!drm_edid)
intel_sdvo->ddc_bus = saved_ddc;
}
@@ -2086,21 +2089,19 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
* When there is no edid and no monitor is connected with VGA
* port, try to use the CRT ddc to read the EDID for DVI-connector.
*/
- if (edid == NULL)
- edid = intel_sdvo_get_analog_edid(connector);
+ if (!drm_edid)
+ drm_edid = intel_sdvo_get_analog_edid(connector);
status = connector_status_unknown;
- if (edid != NULL) {
+ if (drm_edid) {
+ const struct edid *edid = drm_edid_raw(drm_edid);
+
/* DDC bus is shared, match EDID to connector type */
- if (edid->input & DRM_EDID_INPUT_DIGITAL) {
+ if (edid->input & DRM_EDID_INPUT_DIGITAL)
status = connector_status_connected;
- if (intel_sdvo_connector->is_hdmi) {
- intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid);
- intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid);
- }
- } else
+ else
status = connector_status_disconnected;
- kfree(edid);
+ drm_edid_free(drm_edid);
}
return status;
@@ -2108,8 +2109,9 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
static bool
intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo,
- struct edid *edid)
+ const struct drm_edid *drm_edid)
{
+ const struct edid *edid = drm_edid_raw(drm_edid);
bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL);
bool connector_is_digital = !!IS_DIGITAL(sdvo);
@@ -2147,30 +2149,28 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
intel_sdvo->attached_output = response;
- intel_sdvo->has_hdmi_monitor = false;
- intel_sdvo->has_hdmi_audio = false;
-
if ((intel_sdvo_connector->output_flag & response) == 0)
ret = connector_status_disconnected;
else if (IS_TMDS(intel_sdvo_connector))
ret = intel_sdvo_tmds_sink_detect(connector);
else {
- struct edid *edid;
+ const struct drm_edid *drm_edid;
/* if we have an edid check it matches the connection */
- edid = intel_sdvo_get_edid(connector);
- if (edid == NULL)
- edid = intel_sdvo_get_analog_edid(connector);
- if (edid != NULL) {
+ drm_edid = intel_sdvo_get_edid(connector);
+ if (!drm_edid)
+ drm_edid = intel_sdvo_get_analog_edid(connector);
+ if (drm_edid) {
if (intel_sdvo_connector_matches_edid(intel_sdvo_connector,
- edid))
+ drm_edid))
ret = connector_status_connected;
else
ret = connector_status_disconnected;
- kfree(edid);
- } else
+ drm_edid_free(drm_edid);
+ } else {
ret = connector_status_connected;
+ }
}
return ret;
@@ -2179,13 +2179,13 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
static int intel_sdvo_get_ddc_modes(struct drm_connector *connector)
{
int num_modes = 0;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
/* set the bus switch and get the modes */
- edid = intel_sdvo_get_edid(connector);
+ drm_edid = intel_sdvo_get_edid(connector);
/*
* Mac mini hack. On this device, the DVI-I connector shares one DDC
@@ -2193,17 +2193,17 @@ static int intel_sdvo_get_ddc_modes(struct drm_connector *connector)
* DDC fails, check to see if the analog output is disconnected, in
* which case we'll look there for the digital DDC data.
*/
- if (!edid)
- edid = intel_sdvo_get_analog_edid(connector);
+ if (!drm_edid)
+ drm_edid = intel_sdvo_get_analog_edid(connector);
- if (!edid)
+ if (!drm_edid)
return 0;
if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector),
- edid))
- num_modes += intel_connector_update_modes(connector, edid);
+ drm_edid))
+ num_modes += intel_connector_update_modes(connector, drm_edid);
- kfree(edid);
+ drm_edid_free(drm_edid);
return num_modes;
}
diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c
index 1cfb94b5cedb..88ef56b6e0fd 100644
--- a/drivers/gpu/drm/i915/display/intel_snps_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c
@@ -2007,11 +2007,16 @@ void intel_mpllb_state_verify(struct intel_atomic_state *state,
if (!new_crtc_state->hw.active)
return;
+ /* intel_get_crtc_new_encoder() only works for modeset/fastset commits */
+ if (!intel_crtc_needs_modeset(new_crtc_state) &&
+ !intel_crtc_needs_fastset(new_crtc_state))
+ return;
+
encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
intel_mpllb_readout_hw_state(encoder, &mpllb_hw_state);
#define MPLLB_CHECK(__name) \
- I915_STATE_WARN(mpllb_sw_state->__name != mpllb_hw_state.__name, \
+ I915_STATE_WARN(i915, mpllb_sw_state->__name != mpllb_hw_state.__name, \
"[CRTC:%d:%s] mismatch in MPLLB: %s (expected 0x%08x, found 0x%08x)", \
crtc->base.base.id, crtc->base.name, \
__stringify(__name), \
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.h b/drivers/gpu/drm/i915/display/intel_sprite.h
index 4635c7ad23f9..91c6dca342b2 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.h
+++ b/drivers/gpu/drm/i915/display/intel_sprite.h
@@ -16,16 +16,6 @@ struct intel_crtc_state;
struct intel_plane_state;
enum pipe;
-/*
- * FIXME: We should instead only take spinlocks once for the entire update
- * instead of once per mmio.
- */
-#if IS_ENABLED(CONFIG_PROVE_LOCKING)
-#define VBLANK_EVASION_TIME_US 250
-#else
-#define VBLANK_EVASION_TIME_US 100
-#endif
-
struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv,
enum pipe pipe, int plane);
int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/display/intel_sprite_uapi.c b/drivers/gpu/drm/i915/display/intel_sprite_uapi.c
index 70a391083751..a76b48ebc2d3 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite_uapi.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite_uapi.c
@@ -86,6 +86,7 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
goto out;
}
state->acquire_ctx = &ctx;
+ to_intel_atomic_state(state)->internal = true;
while (1) {
plane_state = drm_atomic_get_plane_state(state, plane);
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
index 3b60995e9dfb..3ebf41859043 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -5,16 +5,25 @@
#include "i915_drv.h"
#include "i915_reg.h"
+#include "intel_atomic.h"
+#include "intel_cx0_phy_regs.h"
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display.h"
+#include "intel_display_driver.h"
#include "intel_display_power_map.h"
#include "intel_display_types.h"
#include "intel_dkl_phy_regs.h"
+#include "intel_dp.h"
#include "intel_dp_mst.h"
#include "intel_mg_phy_regs.h"
+#include "intel_modeset_lock.h"
#include "intel_tc.h"
+#define DP_PIN_ASSIGNMENT_C 0x3
+#define DP_PIN_ASSIGNMENT_D 0x4
+#define DP_PIN_ASSIGNMENT_E 0x5
+
enum tc_port_mode {
TC_PORT_DISCONNECTED,
TC_PORT_TBT_ALT,
@@ -46,6 +55,7 @@ struct intel_tc_port {
enum intel_display_power_domain lock_power_domain;
#endif
struct delayed_work disconnect_phy_work;
+ struct delayed_work link_reset_work;
int link_refcount;
bool legacy_port:1;
char port_name[8];
@@ -59,6 +69,7 @@ static enum intel_display_power_domain
tc_phy_cold_off_domain(struct intel_tc_port *);
static u32 tc_phy_hpd_live_status(struct intel_tc_port *tc);
static bool tc_phy_is_ready(struct intel_tc_port *tc);
+static bool tc_phy_wait_for_ready(struct intel_tc_port *tc);
static enum tc_port_mode tc_phy_get_current_mode(struct intel_tc_port *tc);
static const char *tc_port_mode_name(enum tc_port_mode mode)
@@ -141,15 +152,23 @@ bool intel_tc_port_in_legacy_mode(struct intel_digital_port *dig_port)
*
* POWER_DOMAIN_TC_COLD_OFF:
* -------------------------
- * TGL/legacy, DP-alt modes:
+ * ICL/DP-alt, TBT mode:
+ * - TCSS/TBT: block TC-cold power state for using the (direct or
+ * TBT DP-IN) AUX and main lanes.
+ *
+ * TGL/all modes:
* - TCSS/IOM,FIA access for PHY ready, owned and HPD live state
- * - TCSS/PHY: block TC-cold power state for using the PHY AUX and
- * main lanes.
+ * - TCSS/PHY: block TC-cold power state for using the (direct or
+ * TBT DP-IN) AUX and main lanes.
*
- * ICL, TGL, ADLP/TBT mode:
- * - TCSS/IOM,FIA access for HPD live state
+ * ADLP/TBT mode:
* - TCSS/TBT: block TC-cold power state for using the (TBT DP-IN)
* AUX and main lanes.
+ *
+ * XELPDP+/all modes:
+ * - TCSS/IOM,FIA access for PHY ready, owned state
+ * - TCSS/PHY: block TC-cold power state for using the (direct or
+ * TBT DP-IN) AUX and main lanes.
*/
bool intel_tc_cold_requires_aux_pw(struct intel_digital_port *dig_port)
{
@@ -271,6 +290,27 @@ u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port)
DP_PIN_ASSIGNMENT_SHIFT(tc->phy_fia_idx);
}
+static int mtl_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port)
+{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ intel_wakeref_t wakeref;
+ u32 pin_mask;
+
+ with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
+ pin_mask = intel_tc_port_get_pin_assignment_mask(dig_port);
+
+ switch (pin_mask) {
+ default:
+ MISSING_CASE(pin_mask);
+ fallthrough;
+ case DP_PIN_ASSIGNMENT_D:
+ return 2;
+ case DP_PIN_ASSIGNMENT_C:
+ case DP_PIN_ASSIGNMENT_E:
+ return 4;
+ }
+}
+
int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
@@ -284,6 +324,9 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
assert_tc_cold_blocked(tc);
+ if (DISPLAY_VER(i915) >= 14)
+ return mtl_tc_port_get_pin_assignment_mask(dig_port);
+
lane_mask = 0;
with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
lane_mask = intel_tc_port_get_lane_mask(dig_port);
@@ -873,6 +916,200 @@ static const struct intel_tc_phy_ops adlp_tc_phy_ops = {
};
/*
+ * XELPDP TC PHY handlers
+ * ----------------------
+ */
+static u32 xelpdp_tc_phy_hpd_live_status(struct intel_tc_port *tc)
+{
+ struct drm_i915_private *i915 = tc_to_i915(tc);
+ struct intel_digital_port *dig_port = tc->dig_port;
+ enum hpd_pin hpd_pin = dig_port->base.hpd_pin;
+ u32 pica_isr_bits = i915->display.hotplug.hpd[hpd_pin];
+ u32 pch_isr_bit = i915->display.hotplug.pch_hpd[hpd_pin];
+ intel_wakeref_t wakeref;
+ u32 pica_isr;
+ u32 pch_isr;
+ u32 mask = 0;
+
+ with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
+ pica_isr = intel_de_read(i915, PICAINTERRUPT_ISR);
+ pch_isr = intel_de_read(i915, SDEISR);
+ }
+
+ if (pica_isr & (pica_isr_bits & XELPDP_DP_ALT_HOTPLUG_MASK))
+ mask |= BIT(TC_PORT_DP_ALT);
+ if (pica_isr & (pica_isr_bits & XELPDP_TBT_HOTPLUG_MASK))
+ mask |= BIT(TC_PORT_TBT_ALT);
+
+ if (tc->legacy_port && (pch_isr & pch_isr_bit))
+ mask |= BIT(TC_PORT_LEGACY);
+
+ return mask;
+}
+
+static bool
+xelpdp_tc_phy_tcss_power_is_enabled(struct intel_tc_port *tc)
+{
+ struct drm_i915_private *i915 = tc_to_i915(tc);
+ enum port port = tc->dig_port->base.port;
+
+ assert_tc_cold_blocked(tc);
+
+ return intel_de_read(i915, XELPDP_PORT_BUF_CTL1(port)) & XELPDP_TCSS_POWER_STATE;
+}
+
+static bool
+xelpdp_tc_phy_wait_for_tcss_power(struct intel_tc_port *tc, bool enabled)
+{
+ struct drm_i915_private *i915 = tc_to_i915(tc);
+
+ if (wait_for(xelpdp_tc_phy_tcss_power_is_enabled(tc) == enabled, 5)) {
+ drm_dbg_kms(&i915->drm,
+ "Port %s: timeout waiting for TCSS power to get %s\n",
+ enabled ? "enabled" : "disabled",
+ tc->port_name);
+ return false;
+ }
+
+ return true;
+}
+
+static void __xelpdp_tc_phy_enable_tcss_power(struct intel_tc_port *tc, bool enable)
+{
+ struct drm_i915_private *i915 = tc_to_i915(tc);
+ enum port port = tc->dig_port->base.port;
+ u32 val;
+
+ assert_tc_cold_blocked(tc);
+
+ val = intel_de_read(i915, XELPDP_PORT_BUF_CTL1(port));
+ if (enable)
+ val |= XELPDP_TCSS_POWER_REQUEST;
+ else
+ val &= ~XELPDP_TCSS_POWER_REQUEST;
+ intel_de_write(i915, XELPDP_PORT_BUF_CTL1(port), val);
+}
+
+static bool xelpdp_tc_phy_enable_tcss_power(struct intel_tc_port *tc, bool enable)
+{
+ struct drm_i915_private *i915 = tc_to_i915(tc);
+
+ __xelpdp_tc_phy_enable_tcss_power(tc, enable);
+
+ if ((!tc_phy_wait_for_ready(tc) ||
+ !xelpdp_tc_phy_wait_for_tcss_power(tc, enable)) &&
+ !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) {
+ if (enable) {
+ __xelpdp_tc_phy_enable_tcss_power(tc, false);
+ xelpdp_tc_phy_wait_for_tcss_power(tc, false);
+ }
+
+ return false;
+ }
+
+ return true;
+}
+
+static void xelpdp_tc_phy_take_ownership(struct intel_tc_port *tc, bool take)
+{
+ struct drm_i915_private *i915 = tc_to_i915(tc);
+ enum port port = tc->dig_port->base.port;
+ u32 val;
+
+ assert_tc_cold_blocked(tc);
+
+ val = intel_de_read(i915, XELPDP_PORT_BUF_CTL1(port));
+ if (take)
+ val |= XELPDP_TC_PHY_OWNERSHIP;
+ else
+ val &= ~XELPDP_TC_PHY_OWNERSHIP;
+ intel_de_write(i915, XELPDP_PORT_BUF_CTL1(port), val);
+}
+
+static bool xelpdp_tc_phy_is_owned(struct intel_tc_port *tc)
+{
+ struct drm_i915_private *i915 = tc_to_i915(tc);
+ enum port port = tc->dig_port->base.port;
+
+ assert_tc_cold_blocked(tc);
+
+ return intel_de_read(i915, XELPDP_PORT_BUF_CTL1(port)) & XELPDP_TC_PHY_OWNERSHIP;
+}
+
+static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
+{
+ struct drm_i915_private *i915 = tc_to_i915(tc);
+ intel_wakeref_t tc_cold_wref;
+ enum intel_display_power_domain domain;
+
+ tc_cold_wref = __tc_cold_block(tc, &domain);
+
+ tc->mode = tc_phy_get_current_mode(tc);
+ if (tc->mode != TC_PORT_DISCONNECTED)
+ tc->lock_wakeref = tc_cold_block(tc);
+
+ drm_WARN_ON(&i915->drm,
+ (tc->mode == TC_PORT_DP_ALT || tc->mode == TC_PORT_LEGACY) &&
+ !xelpdp_tc_phy_tcss_power_is_enabled(tc));
+
+ __tc_cold_unblock(tc, domain, tc_cold_wref);
+}
+
+static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
+{
+ tc->lock_wakeref = tc_cold_block(tc);
+
+ if (tc->mode == TC_PORT_TBT_ALT)
+ return true;
+
+ if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
+ goto out_unblock_tccold;
+
+ xelpdp_tc_phy_take_ownership(tc, true);
+
+ if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes))
+ goto out_release_phy;
+
+ return true;
+
+out_release_phy:
+ xelpdp_tc_phy_take_ownership(tc, false);
+ xelpdp_tc_phy_wait_for_tcss_power(tc, false);
+
+out_unblock_tccold:
+ tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
+
+ return false;
+}
+
+static void xelpdp_tc_phy_disconnect(struct intel_tc_port *tc)
+{
+ switch (tc->mode) {
+ case TC_PORT_LEGACY:
+ case TC_PORT_DP_ALT:
+ xelpdp_tc_phy_take_ownership(tc, false);
+ xelpdp_tc_phy_enable_tcss_power(tc, false);
+ fallthrough;
+ case TC_PORT_TBT_ALT:
+ tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
+ break;
+ default:
+ MISSING_CASE(tc->mode);
+ }
+}
+
+static const struct intel_tc_phy_ops xelpdp_tc_phy_ops = {
+ .cold_off_domain = tgl_tc_phy_cold_off_domain,
+ .hpd_live_status = xelpdp_tc_phy_hpd_live_status,
+ .is_ready = adlp_tc_phy_is_ready,
+ .is_owned = xelpdp_tc_phy_is_owned,
+ .get_hw_state = xelpdp_tc_phy_get_hw_state,
+ .connect = xelpdp_tc_phy_connect,
+ .disconnect = xelpdp_tc_phy_disconnect,
+ .init = adlp_tc_phy_init,
+};
+
+/*
* Generic TC PHY handlers
* -----------------------
*/
@@ -945,13 +1182,18 @@ static bool tc_phy_is_connected(struct intel_tc_port *tc,
return is_connected;
}
-static void tc_phy_wait_for_ready(struct intel_tc_port *tc)
+static bool tc_phy_wait_for_ready(struct intel_tc_port *tc)
{
struct drm_i915_private *i915 = tc_to_i915(tc);
- if (wait_for(tc_phy_is_ready(tc), 100))
+ if (wait_for(tc_phy_is_ready(tc), 500)) {
drm_err(&i915->drm, "Port %s: timeout waiting for PHY ready\n",
tc->port_name);
+
+ return false;
+ }
+
+ return true;
}
static enum tc_port_mode
@@ -1335,6 +1577,138 @@ bool intel_tc_port_connected(struct intel_encoder *encoder)
return is_connected;
}
+static bool __intel_tc_port_link_needs_reset(struct intel_tc_port *tc)
+{
+ bool ret;
+
+ mutex_lock(&tc->lock);
+
+ ret = tc->link_refcount &&
+ tc->mode == TC_PORT_DP_ALT &&
+ intel_tc_port_needs_reset(tc);
+
+ mutex_unlock(&tc->lock);
+
+ return ret;
+}
+
+bool intel_tc_port_link_needs_reset(struct intel_digital_port *dig_port)
+{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
+
+ if (!intel_phy_is_tc(i915, phy))
+ return false;
+
+ return __intel_tc_port_link_needs_reset(to_tc_port(dig_port));
+}
+
+static int reset_link_commit(struct intel_tc_port *tc,
+ struct intel_atomic_state *state,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct drm_i915_private *i915 = tc_to_i915(tc);
+ struct intel_digital_port *dig_port = tc->dig_port;
+ struct intel_dp *intel_dp = enc_to_intel_dp(&dig_port->base);
+ struct intel_crtc *crtc;
+ u8 pipe_mask;
+ int ret;
+
+ ret = drm_modeset_lock(&i915->drm.mode_config.connection_mutex, ctx);
+ if (ret)
+ return ret;
+
+ ret = intel_dp_get_active_pipes(intel_dp, ctx, &pipe_mask);
+ if (ret)
+ return ret;
+
+ if (!pipe_mask)
+ return 0;
+
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) {
+ struct intel_crtc_state *crtc_state;
+
+ crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ crtc_state->uapi.connectors_changed = true;
+ }
+
+ if (!__intel_tc_port_link_needs_reset(tc))
+ return 0;
+
+ return drm_atomic_commit(&state->base);
+}
+
+static int reset_link(struct intel_tc_port *tc)
+{
+ struct drm_i915_private *i915 = tc_to_i915(tc);
+ struct drm_modeset_acquire_ctx ctx;
+ struct drm_atomic_state *_state;
+ struct intel_atomic_state *state;
+ int ret;
+
+ _state = drm_atomic_state_alloc(&i915->drm);
+ if (!_state)
+ return -ENOMEM;
+
+ state = to_intel_atomic_state(_state);
+ state->internal = true;
+
+ intel_modeset_lock_ctx_retry(&ctx, state, 0, ret)
+ ret = reset_link_commit(tc, state, &ctx);
+
+ drm_atomic_state_put(&state->base);
+
+ return ret;
+}
+
+static void intel_tc_port_link_reset_work(struct work_struct *work)
+{
+ struct intel_tc_port *tc =
+ container_of(work, struct intel_tc_port, link_reset_work.work);
+ struct drm_i915_private *i915 = tc_to_i915(tc);
+ int ret;
+
+ if (!__intel_tc_port_link_needs_reset(tc))
+ return;
+
+ mutex_lock(&i915->drm.mode_config.mutex);
+
+ drm_dbg_kms(&i915->drm,
+ "Port %s: TypeC DP-alt sink disconnected, resetting link\n",
+ tc->port_name);
+ ret = reset_link(tc);
+ drm_WARN_ON(&i915->drm, ret);
+
+ mutex_unlock(&i915->drm.mode_config.mutex);
+}
+
+bool intel_tc_port_link_reset(struct intel_digital_port *dig_port)
+{
+ if (!intel_tc_port_link_needs_reset(dig_port))
+ return false;
+
+ queue_delayed_work(system_unbound_wq,
+ &to_tc_port(dig_port)->link_reset_work,
+ msecs_to_jiffies(2000));
+
+ return true;
+}
+
+void intel_tc_port_link_cancel_reset_work(struct intel_digital_port *dig_port)
+{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
+ struct intel_tc_port *tc = to_tc_port(dig_port);
+
+ if (!intel_phy_is_tc(i915, phy))
+ return;
+
+ cancel_delayed_work(&tc->link_reset_work);
+}
+
static void __intel_tc_port_lock(struct intel_tc_port *tc,
int required_lanes)
{
@@ -1382,11 +1756,19 @@ static void intel_tc_port_disconnect_phy_work(struct work_struct *work)
*
* Flush the delayed work disconnecting an idle PHY.
*/
-void intel_tc_port_flush_work(struct intel_digital_port *dig_port)
+static void intel_tc_port_flush_work(struct intel_digital_port *dig_port)
{
flush_delayed_work(&to_tc_port(dig_port)->disconnect_phy_work);
}
+void intel_tc_port_suspend(struct intel_digital_port *dig_port)
+{
+ struct intel_tc_port *tc = to_tc_port(dig_port);
+
+ cancel_delayed_work_sync(&tc->link_reset_work);
+ intel_tc_port_flush_work(dig_port);
+}
+
void intel_tc_port_unlock(struct intel_digital_port *dig_port)
{
struct intel_tc_port *tc = to_tc_port(dig_port);
@@ -1423,6 +1805,14 @@ void intel_tc_port_put_link(struct intel_digital_port *dig_port)
intel_tc_port_lock(dig_port);
__intel_tc_port_put_link(tc);
intel_tc_port_unlock(dig_port);
+
+ /*
+ * The firmware will not update the HPD status of other TypeC ports
+ * that are active in DP-alt mode with their sink disconnected, until
+ * this port is disabled and its PHY gets disconnected. Make sure this
+ * happens in a timely manner by disconnecting the PHY synchronously.
+ */
+ intel_tc_port_flush_work(dig_port);
}
int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
@@ -1442,7 +1832,9 @@ int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
dig_port->tc = tc;
tc->dig_port = dig_port;
- if (DISPLAY_VER(i915) >= 13)
+ if (DISPLAY_VER(i915) >= 14)
+ tc->phy_ops = &xelpdp_tc_phy_ops;
+ else if (DISPLAY_VER(i915) >= 13)
tc->phy_ops = &adlp_tc_phy_ops;
else if (DISPLAY_VER(i915) >= 12)
tc->phy_ops = &tgl_tc_phy_ops;
@@ -1453,7 +1845,9 @@ int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
"%c/TC#%d", port_name(port), tc_port + 1);
mutex_init(&tc->lock);
+ /* TODO: Combine the two works */
INIT_DELAYED_WORK(&tc->disconnect_phy_work, intel_tc_port_disconnect_phy_work);
+ INIT_DELAYED_WORK(&tc->link_reset_work, intel_tc_port_link_reset_work);
tc->legacy_port = is_legacy;
tc->mode = TC_PORT_DISCONNECTED;
tc->link_refcount = 0;
@@ -1467,7 +1861,7 @@ int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
void intel_tc_port_cleanup(struct intel_digital_port *dig_port)
{
- intel_tc_port_flush_work(dig_port);
+ intel_tc_port_suspend(dig_port);
kfree(dig_port->tc);
dig_port->tc = NULL;
diff --git a/drivers/gpu/drm/i915/display/intel_tc.h b/drivers/gpu/drm/i915/display/intel_tc.h
index dd0810f9ea95..3b16491925fa 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.h
+++ b/drivers/gpu/drm/i915/display/intel_tc.h
@@ -30,11 +30,14 @@ void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port,
const struct intel_crtc_state *crtc_state);
void intel_tc_port_lock(struct intel_digital_port *dig_port);
void intel_tc_port_unlock(struct intel_digital_port *dig_port);
-void intel_tc_port_flush_work(struct intel_digital_port *dig_port);
+void intel_tc_port_suspend(struct intel_digital_port *dig_port);
void intel_tc_port_get_link(struct intel_digital_port *dig_port,
int required_lanes);
void intel_tc_port_put_link(struct intel_digital_port *dig_port);
bool intel_tc_port_ref_held(struct intel_digital_port *dig_port);
+bool intel_tc_port_link_needs_reset(struct intel_digital_port *dig_port);
+bool intel_tc_port_link_reset(struct intel_digital_port *dig_port);
+void intel_tc_port_link_cancel_reset_work(struct intel_digital_port *dig_port);
int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy);
void intel_tc_port_cleanup(struct intel_digital_port *dig_port);
diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c
index 557ec5b62afa..36b479b46b60 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.c
+++ b/drivers/gpu/drm/i915/display/intel_tv.c
@@ -35,14 +35,15 @@
#include <drm/drm_edid.h>
#include "i915_drv.h"
-#include "i915_irq.h"
#include "i915_reg.h"
#include "intel_connector.h"
#include "intel_crtc.h"
#include "intel_de.h"
+#include "intel_display_irq.h"
#include "intel_display_types.h"
#include "intel_dpll.h"
#include "intel_hotplug.h"
+#include "intel_load_detect.h"
#include "intel_tv.h"
#include "intel_tv_regs.h"
@@ -1205,6 +1206,7 @@ intel_tv_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
+ pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
drm_dbg_kms(&dev_priv->drm, "forcing bpc to 8 for TV\n");
@@ -1722,21 +1724,21 @@ intel_tv_detect(struct drm_connector *connector,
return connector_status_disconnected;
if (force) {
- struct intel_load_detect_pipe tmp;
- int ret;
+ struct drm_atomic_state *state;
- ret = intel_get_load_detect_pipe(connector, &tmp, ctx);
- if (ret < 0)
- return ret;
+ state = intel_load_detect_get_pipe(connector, ctx);
+ if (IS_ERR(state))
+ return PTR_ERR(state);
- if (ret > 0) {
+ if (state) {
type = intel_tv_detect_type(intel_tv, connector);
- intel_release_load_detect_pipe(connector, &tmp, ctx);
+ intel_load_detect_release_pipe(connector, state, ctx);
status = type < 0 ?
connector_status_disconnected :
connector_status_connected;
- } else
+ } else {
status = connector_status_unknown;
+ }
if (status == connector_status_connected) {
intel_tv->type = type;
diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c
index f8bf9810527d..f5659ebd08eb 100644
--- a/drivers/gpu/drm/i915/display/intel_vblank.c
+++ b/drivers/gpu/drm/i915/display/intel_vblank.c
@@ -340,8 +340,7 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc,
* matches how the scanline counter based position works since
* the scanline counter doesn't count the two half lines.
*/
- if (position >= vtotal)
- position = vtotal - 1;
+ position = min(position, vtotal - 1);
/*
* Start of vblank interrupt is triggered at start of hsync,
@@ -488,21 +487,27 @@ static int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state)
}
}
-void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state)
+void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state,
+ bool vrr_enable)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ u8 mode_flags = crtc_state->mode_flags;
struct drm_display_mode adjusted_mode;
int vmax_vblank_start = 0;
unsigned long irqflags;
drm_mode_init(&adjusted_mode, &crtc_state->hw.adjusted_mode);
- if (crtc_state->vrr.enable) {
+ if (vrr_enable) {
+ drm_WARN_ON(&i915->drm, (mode_flags & I915_MODE_FLAG_VRR) == 0);
+
adjusted_mode.crtc_vtotal = crtc_state->vrr.vmax;
adjusted_mode.crtc_vblank_end = crtc_state->vrr.vmax;
adjusted_mode.crtc_vblank_start = intel_vrr_vmin_vblank_start(crtc_state);
vmax_vblank_start = intel_vrr_vmax_vblank_start(crtc_state);
+ } else {
+ mode_flags &= ~I915_MODE_FLAG_VRR;
}
/*
@@ -524,7 +529,7 @@ void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state)
crtc->vmax_vblank_start = vmax_vblank_start;
- crtc->mode_flags = crtc_state->mode_flags;
+ crtc->mode_flags = mode_flags;
crtc->scanline_offset = intel_crtc_scanline_offset(crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_vblank.h b/drivers/gpu/drm/i915/display/intel_vblank.h
index 0884db7e76ae..08e706b29149 100644
--- a/drivers/gpu/drm/i915/display/intel_vblank.h
+++ b/drivers/gpu/drm/i915/display/intel_vblank.h
@@ -20,6 +20,7 @@ bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error,
int intel_get_crtc_scanline(struct intel_crtc *crtc);
void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc);
void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc);
-void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state);
+void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state,
+ bool vrr_enable);
#endif /* __INTEL_VBLANK_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 8e787c13d26d..bd9116d2cd76 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -19,327 +19,6 @@
#include "intel_vdsc.h"
#include "intel_vdsc_regs.h"
-enum ROW_INDEX_BPP {
- ROW_INDEX_6BPP = 0,
- ROW_INDEX_8BPP,
- ROW_INDEX_10BPP,
- ROW_INDEX_12BPP,
- ROW_INDEX_15BPP,
- MAX_ROW_INDEX
-};
-
-enum COLUMN_INDEX_BPC {
- COLUMN_INDEX_8BPC = 0,
- COLUMN_INDEX_10BPC,
- COLUMN_INDEX_12BPC,
- COLUMN_INDEX_14BPC,
- COLUMN_INDEX_16BPC,
- MAX_COLUMN_INDEX
-};
-
-/* From DSC_v1.11 spec, rc_parameter_Set syntax element typically constant */
-static const u16 rc_buf_thresh[] = {
- 896, 1792, 2688, 3584, 4480, 5376, 6272, 6720, 7168, 7616,
- 7744, 7872, 8000, 8064
-};
-
-struct rc_parameters {
- u16 initial_xmit_delay;
- u8 first_line_bpg_offset;
- u16 initial_offset;
- u8 flatness_min_qp;
- u8 flatness_max_qp;
- u8 rc_quant_incr_limit0;
- u8 rc_quant_incr_limit1;
- struct drm_dsc_rc_range_parameters rc_range_params[DSC_NUM_BUF_RANGES];
-};
-
-/*
- * Selected Rate Control Related Parameter Recommended Values
- * from DSC_v1.11 spec & C Model release: DSC_model_20161212
- */
-static const struct rc_parameters rc_parameters[][MAX_COLUMN_INDEX] = {
-{
- /* 6BPP/8BPC */
- { 768, 15, 6144, 3, 13, 11, 11, {
- { 0, 4, 0 }, { 1, 6, -2 }, { 3, 8, -2 }, { 4, 8, -4 },
- { 5, 9, -6 }, { 5, 9, -6 }, { 6, 9, -6 }, { 6, 10, -8 },
- { 7, 11, -8 }, { 8, 12, -10 }, { 9, 12, -10 }, { 10, 12, -12 },
- { 10, 12, -12 }, { 11, 12, -12 }, { 13, 14, -12 }
- }
- },
- /* 6BPP/10BPC */
- { 768, 15, 6144, 7, 17, 15, 15, {
- { 0, 8, 0 }, { 3, 10, -2 }, { 7, 12, -2 }, { 8, 12, -4 },
- { 9, 13, -6 }, { 9, 13, -6 }, { 10, 13, -6 }, { 10, 14, -8 },
- { 11, 15, -8 }, { 12, 16, -10 }, { 13, 16, -10 },
- { 14, 16, -12 }, { 14, 16, -12 }, { 15, 16, -12 },
- { 17, 18, -12 }
- }
- },
- /* 6BPP/12BPC */
- { 768, 15, 6144, 11, 21, 19, 19, {
- { 0, 12, 0 }, { 5, 14, -2 }, { 11, 16, -2 }, { 12, 16, -4 },
- { 13, 17, -6 }, { 13, 17, -6 }, { 14, 17, -6 }, { 14, 18, -8 },
- { 15, 19, -8 }, { 16, 20, -10 }, { 17, 20, -10 },
- { 18, 20, -12 }, { 18, 20, -12 }, { 19, 20, -12 },
- { 21, 22, -12 }
- }
- },
- /* 6BPP/14BPC */
- { 768, 15, 6144, 15, 25, 23, 27, {
- { 0, 16, 0 }, { 7, 18, -2 }, { 15, 20, -2 }, { 16, 20, -4 },
- { 17, 21, -6 }, { 17, 21, -6 }, { 18, 21, -6 }, { 18, 22, -8 },
- { 19, 23, -8 }, { 20, 24, -10 }, { 21, 24, -10 },
- { 22, 24, -12 }, { 22, 24, -12 }, { 23, 24, -12 },
- { 25, 26, -12 }
- }
- },
- /* 6BPP/16BPC */
- { 768, 15, 6144, 19, 29, 27, 27, {
- { 0, 20, 0 }, { 9, 22, -2 }, { 19, 24, -2 }, { 20, 24, -4 },
- { 21, 25, -6 }, { 21, 25, -6 }, { 22, 25, -6 }, { 22, 26, -8 },
- { 23, 27, -8 }, { 24, 28, -10 }, { 25, 28, -10 },
- { 26, 28, -12 }, { 26, 28, -12 }, { 27, 28, -12 },
- { 29, 30, -12 }
- }
- },
-},
-{
- /* 8BPP/8BPC */
- { 512, 12, 6144, 3, 12, 11, 11, {
- { 0, 4, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 1, 6, -2 },
- { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
- { 3, 9, -8 }, { 3, 10, -10 }, { 5, 11, -10 }, { 5, 12, -12 },
- { 5, 13, -12 }, { 7, 13, -12 }, { 13, 15, -12 }
- }
- },
- /* 8BPP/10BPC */
- { 512, 12, 6144, 7, 16, 15, 15, {
- { 0, 4, 2 }, { 4, 8, 0 }, { 5, 9, 0 }, { 5, 10, -2 },
- { 7, 11, -4 }, { 7, 11, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
- { 7, 13, -8 }, { 7, 14, -10 }, { 9, 15, -10 }, { 9, 16, -12 },
- { 9, 17, -12 }, { 11, 17, -12 }, { 17, 19, -12 }
- }
- },
- /* 8BPP/12BPC */
- { 512, 12, 6144, 11, 20, 19, 19, {
- { 0, 12, 2 }, { 4, 12, 0 }, { 9, 13, 0 }, { 9, 14, -2 },
- { 11, 15, -4 }, { 11, 15, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
- { 11, 17, -8 }, { 11, 18, -10 }, { 13, 19, -10 },
- { 13, 20, -12 }, { 13, 21, -12 }, { 15, 21, -12 },
- { 21, 23, -12 }
- }
- },
- /* 8BPP/14BPC */
- { 512, 12, 6144, 15, 24, 23, 23, {
- { 0, 12, 0 }, { 5, 13, 0 }, { 11, 15, 0 }, { 12, 17, -2 },
- { 15, 19, -4 }, { 15, 19, -6 }, { 15, 19, -8 }, { 15, 20, -8 },
- { 15, 21, -8 }, { 15, 22, -10 }, { 17, 22, -10 },
- { 17, 23, -12 }, { 17, 23, -12 }, { 21, 24, -12 },
- { 24, 25, -12 }
- }
- },
- /* 8BPP/16BPC */
- { 512, 12, 6144, 19, 28, 27, 27, {
- { 0, 12, 2 }, { 6, 14, 0 }, { 13, 17, 0 }, { 15, 20, -2 },
- { 19, 23, -4 }, { 19, 23, -6 }, { 19, 23, -8 }, { 19, 24, -8 },
- { 19, 25, -8 }, { 19, 26, -10 }, { 21, 26, -10 },
- { 21, 27, -12 }, { 21, 27, -12 }, { 25, 28, -12 },
- { 28, 29, -12 }
- }
- },
-},
-{
- /* 10BPP/8BPC */
- { 410, 15, 5632, 3, 12, 11, 11, {
- { 0, 3, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 2, 6, -2 },
- { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
- { 3, 9, -8 }, { 3, 9, -10 }, { 5, 10, -10 }, { 5, 10, -10 },
- { 5, 11, -12 }, { 7, 11, -12 }, { 11, 12, -12 }
- }
- },
- /* 10BPP/10BPC */
- { 410, 15, 5632, 7, 16, 15, 15, {
- { 0, 7, 2 }, { 4, 8, 0 }, { 5, 9, 0 }, { 6, 10, -2 },
- { 7, 11, -4 }, { 7, 11, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
- { 7, 13, -8 }, { 7, 13, -10 }, { 9, 14, -10 }, { 9, 14, -10 },
- { 9, 15, -12 }, { 11, 15, -12 }, { 15, 16, -12 }
- }
- },
- /* 10BPP/12BPC */
- { 410, 15, 5632, 11, 20, 19, 19, {
- { 0, 11, 2 }, { 4, 12, 0 }, { 9, 13, 0 }, { 10, 14, -2 },
- { 11, 15, -4 }, { 11, 15, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
- { 11, 17, -8 }, { 11, 17, -10 }, { 13, 18, -10 },
- { 13, 18, -10 }, { 13, 19, -12 }, { 15, 19, -12 },
- { 19, 20, -12 }
- }
- },
- /* 10BPP/14BPC */
- { 410, 15, 5632, 15, 24, 23, 23, {
- { 0, 11, 2 }, { 5, 13, 0 }, { 11, 15, 0 }, { 13, 18, -2 },
- { 15, 19, -4 }, { 15, 19, -6 }, { 15, 19, -8 }, { 15, 20, -8 },
- { 15, 21, -8 }, { 15, 21, -10 }, { 17, 22, -10 },
- { 17, 22, -10 }, { 17, 23, -12 }, { 19, 23, -12 },
- { 23, 24, -12 }
- }
- },
- /* 10BPP/16BPC */
- { 410, 15, 5632, 19, 28, 27, 27, {
- { 0, 11, 2 }, { 6, 14, 0 }, { 13, 17, 0 }, { 16, 20, -2 },
- { 19, 23, -4 }, { 19, 23, -6 }, { 19, 23, -8 }, { 19, 24, -8 },
- { 19, 25, -8 }, { 19, 25, -10 }, { 21, 26, -10 },
- { 21, 26, -10 }, { 21, 27, -12 }, { 23, 27, -12 },
- { 27, 28, -12 }
- }
- },
-},
-{
- /* 12BPP/8BPC */
- { 341, 15, 2048, 3, 12, 11, 11, {
- { 0, 2, 2 }, { 0, 4, 0 }, { 1, 5, 0 }, { 1, 6, -2 },
- { 3, 7, -4 }, { 3, 7, -6 }, { 3, 7, -8 }, { 3, 8, -8 },
- { 3, 9, -8 }, { 3, 10, -10 }, { 5, 11, -10 },
- { 5, 12, -12 }, { 5, 13, -12 }, { 7, 13, -12 }, { 13, 15, -12 }
- }
- },
- /* 12BPP/10BPC */
- { 341, 15, 2048, 7, 16, 15, 15, {
- { 0, 2, 2 }, { 2, 5, 0 }, { 3, 7, 0 }, { 4, 8, -2 },
- { 6, 9, -4 }, { 7, 10, -6 }, { 7, 11, -8 }, { 7, 12, -8 },
- { 7, 13, -8 }, { 7, 14, -10 }, { 9, 15, -10 }, { 9, 16, -12 },
- { 9, 17, -12 }, { 11, 17, -12 }, { 17, 19, -12 }
- }
- },
- /* 12BPP/12BPC */
- { 341, 15, 2048, 11, 20, 19, 19, {
- { 0, 6, 2 }, { 4, 9, 0 }, { 7, 11, 0 }, { 8, 12, -2 },
- { 10, 13, -4 }, { 11, 14, -6 }, { 11, 15, -8 }, { 11, 16, -8 },
- { 11, 17, -8 }, { 11, 18, -10 }, { 13, 19, -10 },
- { 13, 20, -12 }, { 13, 21, -12 }, { 15, 21, -12 },
- { 21, 23, -12 }
- }
- },
- /* 12BPP/14BPC */
- { 341, 15, 2048, 15, 24, 23, 23, {
- { 0, 6, 2 }, { 7, 10, 0 }, { 9, 13, 0 }, { 11, 16, -2 },
- { 14, 17, -4 }, { 15, 18, -6 }, { 15, 19, -8 }, { 15, 20, -8 },
- { 15, 20, -8 }, { 15, 21, -10 }, { 17, 21, -10 },
- { 17, 21, -12 }, { 17, 21, -12 }, { 19, 22, -12 },
- { 22, 23, -12 }
- }
- },
- /* 12BPP/16BPC */
- { 341, 15, 2048, 19, 28, 27, 27, {
- { 0, 6, 2 }, { 6, 11, 0 }, { 11, 15, 0 }, { 14, 18, -2 },
- { 18, 21, -4 }, { 19, 22, -6 }, { 19, 23, -8 }, { 19, 24, -8 },
- { 19, 24, -8 }, { 19, 25, -10 }, { 21, 25, -10 },
- { 21, 25, -12 }, { 21, 25, -12 }, { 23, 26, -12 },
- { 26, 27, -12 }
- }
- },
-},
-{
- /* 15BPP/8BPC */
- { 273, 15, 2048, 3, 12, 11, 11, {
- { 0, 0, 10 }, { 0, 1, 8 }, { 0, 1, 6 }, { 0, 2, 4 },
- { 1, 2, 2 }, { 1, 3, 0 }, { 1, 3, -2 }, { 2, 4, -4 },
- { 2, 5, -6 }, { 3, 5, -8 }, { 4, 6, -10 }, { 4, 7, -10 },
- { 5, 7, -12 }, { 7, 8, -12 }, { 8, 9, -12 }
- }
- },
- /* 15BPP/10BPC */
- { 273, 15, 2048, 7, 16, 15, 15, {
- { 0, 2, 10 }, { 2, 5, 8 }, { 3, 5, 6 }, { 4, 6, 4 },
- { 5, 6, 2 }, { 5, 7, 0 }, { 5, 7, -2 }, { 6, 8, -4 },
- { 6, 9, -6 }, { 7, 9, -8 }, { 8, 10, -10 }, { 8, 11, -10 },
- { 9, 11, -12 }, { 11, 12, -12 }, { 12, 13, -12 }
- }
- },
- /* 15BPP/12BPC */
- { 273, 15, 2048, 11, 20, 19, 19, {
- { 0, 4, 10 }, { 2, 7, 8 }, { 4, 9, 6 }, { 6, 11, 4 },
- { 9, 11, 2 }, { 9, 11, 0 }, { 9, 12, -2 }, { 10, 12, -4 },
- { 11, 13, -6 }, { 11, 13, -8 }, { 12, 14, -10 },
- { 13, 15, -10 }, { 13, 15, -12 }, { 15, 16, -12 },
- { 16, 17, -12 }
- }
- },
- /* 15BPP/14BPC */
- { 273, 15, 2048, 15, 24, 23, 23, {
- { 0, 4, 10 }, { 3, 8, 8 }, { 6, 11, 6 }, { 9, 14, 4 },
- { 13, 15, 2 }, { 13, 15, 0 }, { 13, 16, -2 }, { 14, 16, -4 },
- { 15, 17, -6 }, { 15, 17, -8 }, { 16, 18, -10 },
- { 17, 19, -10 }, { 17, 19, -12 }, { 19, 20, -12 },
- { 20, 21, -12 }
- }
- },
- /* 15BPP/16BPC */
- { 273, 15, 2048, 19, 28, 27, 27, {
- { 0, 4, 10 }, { 4, 9, 8 }, { 8, 13, 6 }, { 12, 17, 4 },
- { 17, 19, 2 }, { 17, 20, 0 }, { 17, 20, -2 }, { 18, 20, -4 },
- { 19, 21, -6 }, { 19, 21, -8 }, { 20, 22, -10 },
- { 21, 23, -10 }, { 21, 23, -12 }, { 23, 24, -12 },
- { 24, 25, -12 }
- }
- }
-}
-
-};
-
-static int get_row_index_for_rc_params(u16 compressed_bpp)
-{
- switch (compressed_bpp) {
- case 6:
- return ROW_INDEX_6BPP;
- case 8:
- return ROW_INDEX_8BPP;
- case 10:
- return ROW_INDEX_10BPP;
- case 12:
- return ROW_INDEX_12BPP;
- case 15:
- return ROW_INDEX_15BPP;
- default:
- return -EINVAL;
- }
-}
-
-static int get_column_index_for_rc_params(u8 bits_per_component)
-{
- switch (bits_per_component) {
- case 8:
- return COLUMN_INDEX_8BPC;
- case 10:
- return COLUMN_INDEX_10BPC;
- case 12:
- return COLUMN_INDEX_12BPC;
- case 14:
- return COLUMN_INDEX_14BPC;
- case 16:
- return COLUMN_INDEX_16BPC;
- default:
- return -EINVAL;
- }
-}
-
-static const struct rc_parameters *get_rc_params(u16 compressed_bpp,
- u8 bits_per_component)
-{
- int row_index, column_index;
-
- row_index = get_row_index_for_rc_params(compressed_bpp);
- if (row_index < 0)
- return NULL;
-
- column_index = get_column_index_for_rc_params(bits_per_component);
- if (column_index < 0)
- return NULL;
-
- return &rc_parameters[row_index][column_index];
-}
-
bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state)
{
const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -374,8 +53,7 @@ static bool is_pipe_dsc(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
}
static void
-calculate_rc_params(struct rc_parameters *rc,
- struct drm_dsc_config *vdsc_cfg)
+calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
{
int bpc = vdsc_cfg->bits_per_component;
int bpp = vdsc_cfg->bits_per_pixel >> 4;
@@ -395,56 +73,57 @@ calculate_rc_params(struct rc_parameters *rc,
u32 res, buf_i, bpp_i;
if (vdsc_cfg->slice_height >= 8)
- rc->first_line_bpg_offset =
+ vdsc_cfg->first_line_bpg_offset =
12 + DIV_ROUND_UP((9 * min(34, vdsc_cfg->slice_height - 8)), 100);
else
- rc->first_line_bpg_offset = 2 * (vdsc_cfg->slice_height - 1);
+ vdsc_cfg->first_line_bpg_offset = 2 * (vdsc_cfg->slice_height - 1);
/* Our hw supports only 444 modes as of today */
if (bpp >= 12)
- rc->initial_offset = 2048;
+ vdsc_cfg->initial_offset = 2048;
else if (bpp >= 10)
- rc->initial_offset = 5632 - DIV_ROUND_UP(((bpp - 10) * 3584), 2);
+ vdsc_cfg->initial_offset = 5632 - DIV_ROUND_UP(((bpp - 10) * 3584), 2);
else if (bpp >= 8)
- rc->initial_offset = 6144 - DIV_ROUND_UP(((bpp - 8) * 512), 2);
+ vdsc_cfg->initial_offset = 6144 - DIV_ROUND_UP(((bpp - 8) * 512), 2);
else
- rc->initial_offset = 6144;
+ vdsc_cfg->initial_offset = 6144;
/* initial_xmit_delay = rc_model_size/2/compression_bpp */
- rc->initial_xmit_delay = DIV_ROUND_UP(DSC_RC_MODEL_SIZE_CONST, 2 * bpp);
+ vdsc_cfg->initial_xmit_delay = DIV_ROUND_UP(DSC_RC_MODEL_SIZE_CONST, 2 * bpp);
- rc->flatness_min_qp = 3 + qp_bpc_modifier;
- rc->flatness_max_qp = 12 + qp_bpc_modifier;
+ vdsc_cfg->flatness_min_qp = 3 + qp_bpc_modifier;
+ vdsc_cfg->flatness_max_qp = 12 + qp_bpc_modifier;
- rc->rc_quant_incr_limit0 = 11 + qp_bpc_modifier;
- rc->rc_quant_incr_limit1 = 11 + qp_bpc_modifier;
+ vdsc_cfg->rc_quant_incr_limit0 = 11 + qp_bpc_modifier;
+ vdsc_cfg->rc_quant_incr_limit1 = 11 + qp_bpc_modifier;
bpp_i = (2 * (bpp - 6));
for (buf_i = 0; buf_i < DSC_NUM_BUF_RANGES; buf_i++) {
+ u8 range_bpg_offset;
+
/* Read range_minqp and range_max_qp from qp tables */
- rc->rc_range_params[buf_i].range_min_qp =
+ vdsc_cfg->rc_range_params[buf_i].range_min_qp =
intel_lookup_range_min_qp(bpc, buf_i, bpp_i, vdsc_cfg->native_420);
- rc->rc_range_params[buf_i].range_max_qp =
+ vdsc_cfg->rc_range_params[buf_i].range_max_qp =
intel_lookup_range_max_qp(bpc, buf_i, bpp_i, vdsc_cfg->native_420);
- /* Calculate range_bgp_offset */
+ /* Calculate range_bpg_offset */
if (bpp <= 6) {
- rc->rc_range_params[buf_i].range_bpg_offset = ofs_und6[buf_i];
+ range_bpg_offset = ofs_und6[buf_i];
} else if (bpp <= 8) {
res = DIV_ROUND_UP(((bpp - 6) * (ofs_und8[buf_i] - ofs_und6[buf_i])), 2);
- rc->rc_range_params[buf_i].range_bpg_offset =
- ofs_und6[buf_i] + res;
+ range_bpg_offset = ofs_und6[buf_i] + res;
} else if (bpp <= 12) {
- rc->rc_range_params[buf_i].range_bpg_offset =
- ofs_und8[buf_i];
+ range_bpg_offset = ofs_und8[buf_i];
} else if (bpp <= 15) {
res = DIV_ROUND_UP(((bpp - 12) * (ofs_und15[buf_i] - ofs_und12[buf_i])), 3);
- rc->rc_range_params[buf_i].range_bpg_offset =
- ofs_und12[buf_i] + res;
+ range_bpg_offset = ofs_und12[buf_i] + res;
} else {
- rc->rc_range_params[buf_i].range_bpg_offset =
- ofs_und15[buf_i];
+ range_bpg_offset = ofs_und15[buf_i];
}
+
+ vdsc_cfg->rc_range_params[buf_i].range_bpg_offset =
+ range_bpg_offset & DSC_RANGE_BPG_OFFSET_MASK;
}
}
@@ -477,10 +156,8 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct drm_dsc_config *vdsc_cfg = &pipe_config->dsc.config;
u16 compressed_bpp = pipe_config->dsc.compressed_bpp;
- const struct rc_parameters *rc_params;
- struct rc_parameters *rc = NULL;
int err;
- u8 i = 0;
+ int ret;
vdsc_cfg->pic_width = pipe_config->hw.adjusted_mode.crtc_hdisplay;
vdsc_cfg->slice_width = DIV_ROUND_UP(vdsc_cfg->pic_width,
@@ -539,23 +216,7 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
vdsc_cfg->bits_per_component = pipe_config->pipe_bpp / 3;
- for (i = 0; i < DSC_NUM_BUF_RANGES - 1; i++) {
- /*
- * six 0s are appended to the lsb of each threshold value
- * internally in h/w.
- * Only 8 bits are allowed for programming RcBufThreshold
- */
- vdsc_cfg->rc_buf_thresh[i] = rc_buf_thresh[i] >> 6;
- }
-
- /*
- * For 6bpp, RC Buffer threshold 12 and 13 need a different value
- * as per C Model
- */
- if (compressed_bpp == 6) {
- vdsc_cfg->rc_buf_thresh[12] = 0x7C;
- vdsc_cfg->rc_buf_thresh[13] = 0x7D;
- }
+ drm_dsc_set_rc_buf_thresh(vdsc_cfg);
/*
* From XE_LPD onwards we supports compression bpps in steps of 1
@@ -563,39 +224,31 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
* parameters
*/
if (DISPLAY_VER(dev_priv) >= 13) {
- rc = kmalloc(sizeof(*rc), GFP_KERNEL);
- if (!rc)
- return -ENOMEM;
-
- calculate_rc_params(rc, vdsc_cfg);
- rc_params = rc;
+ calculate_rc_params(vdsc_cfg);
} else {
- rc_params = get_rc_params(compressed_bpp,
- vdsc_cfg->bits_per_component);
- if (!rc_params)
- return -EINVAL;
- }
+ if ((compressed_bpp == 8 ||
+ compressed_bpp == 12) &&
+ (vdsc_cfg->bits_per_component == 8 ||
+ vdsc_cfg->bits_per_component == 10 ||
+ vdsc_cfg->bits_per_component == 12))
+ ret = drm_dsc_setup_rc_params(vdsc_cfg, DRM_DSC_1_1_PRE_SCR);
+ else
+ ret = drm_dsc_setup_rc_params(vdsc_cfg, DRM_DSC_1_2_444);
- vdsc_cfg->first_line_bpg_offset = rc_params->first_line_bpg_offset;
- vdsc_cfg->initial_xmit_delay = rc_params->initial_xmit_delay;
- vdsc_cfg->initial_offset = rc_params->initial_offset;
- vdsc_cfg->flatness_min_qp = rc_params->flatness_min_qp;
- vdsc_cfg->flatness_max_qp = rc_params->flatness_max_qp;
- vdsc_cfg->rc_quant_incr_limit0 = rc_params->rc_quant_incr_limit0;
- vdsc_cfg->rc_quant_incr_limit1 = rc_params->rc_quant_incr_limit1;
+ if (ret)
+ return ret;
- for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
- vdsc_cfg->rc_range_params[i].range_min_qp =
- rc_params->rc_range_params[i].range_min_qp;
- vdsc_cfg->rc_range_params[i].range_max_qp =
- rc_params->rc_range_params[i].range_max_qp;
/*
- * Range BPG Offset uses 2's complement and is only a 6 bits. So
- * mask it to get only 6 bits.
+ * FIXME: verify that the hardware actually needs these
+ * modifications rather than them being simple typos.
*/
- vdsc_cfg->rc_range_params[i].range_bpg_offset =
- rc_params->rc_range_params[i].range_bpg_offset &
- DSC_RANGE_BPG_OFFSET_MASK;
+ if (compressed_bpp == 6 &&
+ vdsc_cfg->bits_per_component == 8)
+ vdsc_cfg->rc_quant_incr_limit1 = 23;
+
+ if (compressed_bpp == 8 &&
+ vdsc_cfg->bits_per_component == 14)
+ vdsc_cfg->rc_range_params[0].range_bpg_offset = 0;
}
/*
@@ -612,8 +265,6 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
vdsc_cfg->initial_scale_value = (vdsc_cfg->rc_model_size << 3) /
(vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset);
- kfree(rc);
-
return 0;
}
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
index 4228f26b4c11..88e4759b538b 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -114,9 +114,6 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return;
- if (!crtc_state->uapi.vrr_enabled)
- return;
-
vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000,
adjusted_mode->crtc_htotal * info->monitor_range.max_vfreq);
vmax = adjusted_mode->crtc_clock * 1000 /
@@ -135,7 +132,6 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
*/
crtc_state->vrr.vmin = vmin - 1;
crtc_state->vrr.vmax = vmax;
- crtc_state->vrr.enable = true;
crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1;
@@ -152,7 +148,10 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
crtc_state->framestart_delay - 1);
}
- crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
+ if (crtc_state->uapi.vrr_enabled) {
+ crtc_state->vrr.enable = true;
+ crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
+ }
}
static u32 trans_vrr_ctl(const struct intel_crtc_state *crtc_state)
@@ -168,23 +167,28 @@ static u32 trans_vrr_ctl(const struct intel_crtc_state *crtc_state)
VRR_CTL_PIPELINE_FULL_OVERRIDE;
}
-void intel_vrr_enable(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
- if (!crtc_state->vrr.enable)
+ /*
+ * TRANS_SET_CONTEXT_LATENCY with VRR enabled
+ * requires this chicken bit on ADL/DG2.
+ */
+ if (DISPLAY_VER(dev_priv) == 13)
+ intel_de_rmw(dev_priv, CHICKEN_TRANS(cpu_transcoder),
+ 0, PIPE_VBLANK_WITH_DELAY);
+
+ if (!crtc_state->vrr.flipline) {
+ intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), 0);
return;
+ }
intel_de_write(dev_priv, TRANS_VRR_VMIN(cpu_transcoder), crtc_state->vrr.vmin - 1);
intel_de_write(dev_priv, TRANS_VRR_VMAX(cpu_transcoder), crtc_state->vrr.vmax - 1);
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), trans_vrr_ctl(crtc_state));
intel_de_write(dev_priv, TRANS_VRR_FLIPLINE(cpu_transcoder), crtc_state->vrr.flipline - 1);
- intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), TRANS_PUSH_EN);
-
- intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder),
- VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state));
}
void intel_vrr_send_push(const struct intel_crtc_state *crtc_state)
@@ -212,6 +216,19 @@ bool intel_vrr_is_push_sent(const struct intel_crtc_state *crtc_state)
return intel_de_read(dev_priv, TRANS_PUSH(cpu_transcoder)) & TRANS_PUSH_SEND;
}
+void intel_vrr_enable(const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+
+ if (!crtc_state->vrr.enable)
+ return;
+
+ intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), TRANS_PUSH_EN);
+ intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder),
+ VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state));
+}
+
void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
@@ -225,22 +242,18 @@ void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state)
trans_vrr_ctl(old_crtc_state));
intel_de_wait_for_clear(dev_priv, TRANS_VRR_STATUS(cpu_transcoder),
VRR_STATUS_VRR_EN_LIVE, 1000);
-
intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), 0);
- intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), 0);
}
-void intel_vrr_get_config(struct intel_crtc *crtc,
- struct intel_crtc_state *crtc_state)
+void intel_vrr_get_config(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
u32 trans_vrr_ctl;
trans_vrr_ctl = intel_de_read(dev_priv, TRANS_VRR_CTL(cpu_transcoder));
+
crtc_state->vrr.enable = trans_vrr_ctl & VRR_CTL_VRR_ENABLE;
- if (!crtc_state->vrr.enable)
- return;
if (DISPLAY_VER(dev_priv) >= 13)
crtc_state->vrr.guardband =
@@ -249,10 +262,13 @@ void intel_vrr_get_config(struct intel_crtc *crtc,
if (trans_vrr_ctl & VRR_CTL_PIPELINE_FULL_OVERRIDE)
crtc_state->vrr.pipeline_full =
REG_FIELD_GET(VRR_CTL_PIPELINE_FULL_MASK, trans_vrr_ctl);
- if (trans_vrr_ctl & VRR_CTL_FLIP_LINE_EN)
+
+ if (trans_vrr_ctl & VRR_CTL_FLIP_LINE_EN) {
crtc_state->vrr.flipline = intel_de_read(dev_priv, TRANS_VRR_FLIPLINE(cpu_transcoder)) + 1;
- crtc_state->vrr.vmax = intel_de_read(dev_priv, TRANS_VRR_VMAX(cpu_transcoder)) + 1;
- crtc_state->vrr.vmin = intel_de_read(dev_priv, TRANS_VRR_VMIN(cpu_transcoder)) + 1;
+ crtc_state->vrr.vmax = intel_de_read(dev_priv, TRANS_VRR_VMAX(cpu_transcoder)) + 1;
+ crtc_state->vrr.vmin = intel_de_read(dev_priv, TRANS_VRR_VMIN(cpu_transcoder)) + 1;
+ }
- crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
+ if (crtc_state->vrr.enable)
+ crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
}
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h
index 9fda1135b0dd..de16960c4929 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.h
+++ b/drivers/gpu/drm/i915/display/intel_vrr.h
@@ -11,22 +11,18 @@
struct drm_connector_state;
struct intel_atomic_state;
struct intel_connector;
-struct intel_crtc;
struct intel_crtc_state;
-struct intel_dp;
-struct intel_encoder;
bool intel_vrr_is_capable(struct intel_connector *connector);
void intel_vrr_check_modeset(struct intel_atomic_state *state);
void intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
-void intel_vrr_enable(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state);
+void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state);
+void intel_vrr_enable(const struct intel_crtc_state *crtc_state);
void intel_vrr_send_push(const struct intel_crtc_state *crtc_state);
bool intel_vrr_is_push_sent(const struct intel_crtc_state *crtc_state);
void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state);
-void intel_vrr_get_config(struct intel_crtc *crtc,
- struct intel_crtc_state *crtc_state);
+void intel_vrr_get_config(struct intel_crtc_state *crtc_state);
int intel_vrr_vmax_vblank_start(const struct intel_crtc_state *crtc_state);
int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state);
diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c
index 0e7e014fcc71..1e7c97243fcf 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.c
+++ b/drivers/gpu/drm/i915/display/skl_scaler.c
@@ -348,6 +348,263 @@ int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
return 0;
}
+static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state,
+ int num_scalers_need, struct intel_crtc *intel_crtc,
+ const char *name, int idx,
+ struct intel_plane_state *plane_state,
+ int *scaler_id)
+{
+ struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+ int j;
+ u32 mode;
+
+ if (*scaler_id < 0) {
+ /* find a free scaler */
+ for (j = 0; j < intel_crtc->num_scalers; j++) {
+ if (scaler_state->scalers[j].in_use)
+ continue;
+
+ *scaler_id = j;
+ scaler_state->scalers[*scaler_id].in_use = 1;
+ break;
+ }
+ }
+
+ if (drm_WARN(&dev_priv->drm, *scaler_id < 0,
+ "Cannot find scaler for %s:%d\n", name, idx))
+ return -EINVAL;
+
+ /* set scaler mode */
+ if (plane_state && plane_state->hw.fb &&
+ plane_state->hw.fb->format->is_yuv &&
+ plane_state->hw.fb->format->num_planes > 1) {
+ struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+
+ if (DISPLAY_VER(dev_priv) == 9) {
+ mode = SKL_PS_SCALER_MODE_NV12;
+ } else if (icl_is_hdr_plane(dev_priv, plane->id)) {
+ /*
+ * On gen11+'s HDR planes we only use the scaler for
+ * scaling. They have a dedicated chroma upsampler, so
+ * we don't need the scaler to upsample the UV plane.
+ */
+ mode = PS_SCALER_MODE_NORMAL;
+ } else {
+ struct intel_plane *linked =
+ plane_state->planar_linked_plane;
+
+ mode = PS_SCALER_MODE_PLANAR;
+
+ if (linked)
+ mode |= PS_BINDING_Y_PLANE(linked->id);
+ }
+ } else if (DISPLAY_VER(dev_priv) >= 10) {
+ mode = PS_SCALER_MODE_NORMAL;
+ } else if (num_scalers_need == 1 && intel_crtc->num_scalers > 1) {
+ /*
+ * when only 1 scaler is in use on a pipe with 2 scalers
+ * scaler 0 operates in high quality (HQ) mode.
+ * In this case use scaler 0 to take advantage of HQ mode
+ */
+ scaler_state->scalers[*scaler_id].in_use = 0;
+ *scaler_id = 0;
+ scaler_state->scalers[0].in_use = 1;
+ mode = SKL_PS_SCALER_MODE_HQ;
+ } else {
+ mode = SKL_PS_SCALER_MODE_DYN;
+ }
+
+ /*
+ * FIXME: we should also check the scaler factors for pfit, so
+ * this shouldn't be tied directly to planes.
+ */
+ if (plane_state && plane_state->hw.fb) {
+ const struct drm_framebuffer *fb = plane_state->hw.fb;
+ const struct drm_rect *src = &plane_state->uapi.src;
+ const struct drm_rect *dst = &plane_state->uapi.dst;
+ int hscale, vscale, max_vscale, max_hscale;
+
+ /*
+ * FIXME: When two scalers are needed, but only one of
+ * them needs to downscale, we should make sure that
+ * the one that needs downscaling support is assigned
+ * as the first scaler, so we don't reject downscaling
+ * unnecessarily.
+ */
+
+ if (DISPLAY_VER(dev_priv) >= 14) {
+ /*
+ * On versions 14 and up, only the first
+ * scaler supports a vertical scaling factor
+ * of more than 1.0, while a horizontal
+ * scaling factor of 3.0 is supported.
+ */
+ max_hscale = 0x30000 - 1;
+ if (*scaler_id == 0)
+ max_vscale = 0x30000 - 1;
+ else
+ max_vscale = 0x10000;
+
+ } else if (DISPLAY_VER(dev_priv) >= 10 ||
+ !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
+ max_hscale = 0x30000 - 1;
+ max_vscale = 0x30000 - 1;
+ } else {
+ max_hscale = 0x20000 - 1;
+ max_vscale = 0x20000 - 1;
+ }
+
+ /*
+ * FIXME: We should change the if-else block above to
+ * support HQ vs dynamic scaler properly.
+ */
+
+ /* Check if required scaling is within limits */
+ hscale = drm_rect_calc_hscale(src, dst, 1, max_hscale);
+ vscale = drm_rect_calc_vscale(src, dst, 1, max_vscale);
+
+ if (hscale < 0 || vscale < 0) {
+ drm_dbg_kms(&dev_priv->drm,
+ "Scaler %d doesn't support required plane scaling\n",
+ *scaler_id);
+ drm_rect_debug_print("src: ", src, true);
+ drm_rect_debug_print("dst: ", dst, false);
+
+ return -EINVAL;
+ }
+ }
+
+ drm_dbg_kms(&dev_priv->drm, "Attached scaler id %u.%u to %s:%d\n",
+ intel_crtc->pipe, *scaler_id, name, idx);
+ scaler_state->scalers[*scaler_id].mode = mode;
+
+ return 0;
+}
+
+/**
+ * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
+ * @dev_priv: i915 device
+ * @intel_crtc: intel crtc
+ * @crtc_state: incoming crtc_state to validate and setup scalers
+ *
+ * This function sets up scalers based on staged scaling requests for
+ * a @crtc and its planes. It is called from crtc level check path. If request
+ * is a supportable request, it attaches scalers to requested planes and crtc.
+ *
+ * This function takes into account the current scaler(s) in use by any planes
+ * not being part of this atomic state
+ *
+ * Returns:
+ * 0 - scalers were setup successfully
+ * error code - otherwise
+ */
+int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
+ struct intel_crtc *intel_crtc,
+ struct intel_crtc_state *crtc_state)
+{
+ struct drm_plane *plane = NULL;
+ struct intel_plane *intel_plane;
+ struct intel_plane_state *plane_state = NULL;
+ struct intel_crtc_scaler_state *scaler_state =
+ &crtc_state->scaler_state;
+ struct drm_atomic_state *drm_state = crtc_state->uapi.state;
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(drm_state);
+ int num_scalers_need;
+ int i;
+
+ num_scalers_need = hweight32(scaler_state->scaler_users);
+
+ /*
+ * High level flow:
+ * - staged scaler requests are already in scaler_state->scaler_users
+ * - check whether staged scaling requests can be supported
+ * - add planes using scalers that aren't in current transaction
+ * - assign scalers to requested users
+ * - as part of plane commit, scalers will be committed
+ * (i.e., either attached or detached) to respective planes in hw
+ * - as part of crtc_commit, scaler will be either attached or detached
+ * to crtc in hw
+ */
+
+ /* fail if required scalers > available scalers */
+ if (num_scalers_need > intel_crtc->num_scalers) {
+ drm_dbg_kms(&dev_priv->drm,
+ "Too many scaling requests %d > %d\n",
+ num_scalers_need, intel_crtc->num_scalers);
+ return -EINVAL;
+ }
+
+ /* walkthrough scaler_users bits and start assigning scalers */
+ for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
+ int *scaler_id;
+ const char *name;
+ int idx, ret;
+
+ /* skip if scaler not required */
+ if (!(scaler_state->scaler_users & (1 << i)))
+ continue;
+
+ if (i == SKL_CRTC_INDEX) {
+ name = "CRTC";
+ idx = intel_crtc->base.base.id;
+
+ /* panel fitter case: assign as a crtc scaler */
+ scaler_id = &scaler_state->scaler_id;
+ } else {
+ name = "PLANE";
+
+ /* plane scaler case: assign as a plane scaler */
+ /* find the plane that set the bit as scaler_user */
+ plane = drm_state->planes[i].ptr;
+
+ /*
+ * to enable/disable hq mode, add planes that are using scaler
+ * into this transaction
+ */
+ if (!plane) {
+ struct drm_plane_state *state;
+
+ /*
+ * GLK+ scalers don't have a HQ mode so it
+ * isn't necessary to change between HQ and dyn mode
+ * on those platforms.
+ */
+ if (DISPLAY_VER(dev_priv) >= 10)
+ continue;
+
+ plane = drm_plane_from_index(&dev_priv->drm, i);
+ state = drm_atomic_get_plane_state(drm_state, plane);
+ if (IS_ERR(state)) {
+ drm_dbg_kms(&dev_priv->drm,
+ "Failed to add [PLANE:%d] to drm_state\n",
+ plane->base.id);
+ return PTR_ERR(state);
+ }
+ }
+
+ intel_plane = to_intel_plane(plane);
+ idx = plane->base.id;
+
+ /* plane on different crtc cannot be a scaler user of this crtc */
+ if (drm_WARN_ON(&dev_priv->drm,
+ intel_plane->pipe != intel_crtc->pipe))
+ continue;
+
+ plane_state = intel_atomic_get_new_plane_state(intel_state,
+ intel_plane);
+ scaler_id = &plane_state->scaler_id;
+ }
+
+ ret = intel_atomic_setup_scaler(scaler_state, num_scalers_need,
+ intel_crtc, name, idx,
+ plane_state, scaler_id);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
static int glk_coef_tap(int i)
{
return i % 7;
@@ -401,7 +658,7 @@ static void glk_program_nearest_filter_coefs(struct drm_i915_private *dev_priv,
int i;
intel_de_write_fw(dev_priv, GLK_PS_COEF_INDEX_SET(pipe, id, set),
- PS_COEE_INDEX_AUTO_INC);
+ PS_COEF_INDEX_AUTO_INC);
for (i = 0; i < 17 * 7; i += 2) {
u32 tmp;
@@ -484,8 +741,8 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
id = scaler_state->scaler_id;
- ps_ctrl = skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0);
- ps_ctrl |= PS_SCALER_EN | scaler_state->scalers[id].mode;
+ ps_ctrl = PS_SCALER_EN | PS_BINDING_PIPE | scaler_state->scalers[id].mode |
+ skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0);
skl_scaler_setup_filter(dev_priv, pipe, id, 0,
crtc_state->hw.scaling_filter);
@@ -497,9 +754,9 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, id),
PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_hphase));
intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(pipe, id),
- x << 16 | y);
+ PS_WIN_XPOS(x) | PS_WIN_YPOS(y));
intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, id),
- width << 16 | height);
+ PS_WIN_XSIZE(width) | PS_WIN_YSIZE(height));
}
void
@@ -547,8 +804,8 @@ skl_program_plane_scaler(struct intel_plane *plane,
uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
}
- ps_ctrl = skl_scaler_get_filter_select(plane_state->hw.scaling_filter, 0);
- ps_ctrl |= PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode;
+ ps_ctrl = PS_SCALER_EN | PS_BINDING_PLANE(plane->id) | scaler->mode |
+ skl_scaler_get_filter_select(plane_state->hw.scaling_filter, 0);
skl_scaler_setup_filter(dev_priv, pipe, scaler_id, 0,
plane_state->hw.scaling_filter);
@@ -559,9 +816,9 @@ skl_program_plane_scaler(struct intel_plane *plane,
intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, scaler_id),
PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(pipe, scaler_id),
- (crtc_x << 16) | crtc_y);
+ PS_WIN_XPOS(crtc_x) | PS_WIN_YPOS(crtc_y));
intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, scaler_id),
- (crtc_w << 16) | crtc_h);
+ PS_WIN_XSIZE(crtc_w) | PS_WIN_YSIZE(crtc_h));
}
static void skl_detach_scaler(struct intel_crtc *crtc, int id)
@@ -599,3 +856,42 @@ void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state)
for (i = 0; i < crtc->num_scalers; i++)
skl_detach_scaler(crtc, i);
}
+
+void skl_scaler_get_config(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
+ int id = -1;
+ int i;
+
+ /* find scaler attached to this pipe */
+ for (i = 0; i < crtc->num_scalers; i++) {
+ u32 ctl, pos, size;
+
+ ctl = intel_de_read(dev_priv, SKL_PS_CTRL(crtc->pipe, i));
+ if ((ctl & (PS_SCALER_EN | PS_BINDING_MASK)) != (PS_SCALER_EN | PS_BINDING_PIPE))
+ continue;
+
+ id = i;
+ crtc_state->pch_pfit.enabled = true;
+
+ pos = intel_de_read(dev_priv, SKL_PS_WIN_POS(crtc->pipe, i));
+ size = intel_de_read(dev_priv, SKL_PS_WIN_SZ(crtc->pipe, i));
+
+ drm_rect_init(&crtc_state->pch_pfit.dst,
+ REG_FIELD_GET(PS_WIN_XPOS_MASK, pos),
+ REG_FIELD_GET(PS_WIN_YPOS_MASK, pos),
+ REG_FIELD_GET(PS_WIN_XSIZE_MASK, size),
+ REG_FIELD_GET(PS_WIN_YSIZE_MASK, size));
+
+ scaler_state->scalers[i].in_use = true;
+ break;
+ }
+
+ scaler_state->scaler_id = id;
+ if (id >= 0)
+ scaler_state->scaler_users |= (1 << SKL_CRTC_INDEX);
+ else
+ scaler_state->scaler_users &= ~(1 << SKL_CRTC_INDEX);
+}
diff --git a/drivers/gpu/drm/i915/display/skl_scaler.h b/drivers/gpu/drm/i915/display/skl_scaler.h
index 0097d5d08e10..63f93ca03c89 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.h
+++ b/drivers/gpu/drm/i915/display/skl_scaler.h
@@ -8,17 +8,22 @@
#include <linux/types.h>
enum drm_scaling_filter;
+enum pipe;
struct drm_i915_private;
+struct intel_crtc;
struct intel_crtc_state;
-struct intel_plane_state;
struct intel_plane;
-enum pipe;
+struct intel_plane_state;
int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state);
+int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
+ struct intel_crtc *intel_crtc,
+ struct intel_crtc_state *crtc_state);
+
void skl_pfit_enable(const struct intel_crtc_state *crtc_state);
void skl_program_plane_scaler(struct intel_plane *plane,
@@ -26,4 +31,7 @@ void skl_program_plane_scaler(struct intel_plane *plane,
const struct intel_plane_state *plane_state);
void skl_detach_scalers(const struct intel_crtc_state *crtc_state);
void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state);
+
+void skl_scaler_get_config(struct intel_crtc_state *crtc_state);
+
#endif
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 8ea0598a5a07..6b01a0b68b97 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -9,10 +9,10 @@
#include <drm/drm_fourcc.h>
#include "i915_drv.h"
-#include "i915_irq.h"
#include "i915_reg.h"
#include "intel_atomic_plane.h"
#include "intel_de.h"
+#include "intel_display_irq.h"
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fbc.h"
@@ -789,6 +789,14 @@ static u32 skl_plane_ctl_tiling(u64 fb_modifier)
PLANE_CTL_CLEAR_COLOR_DISABLE;
case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
+ case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
+ return PLANE_CTL_TILED_4 |
+ PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
+ PLANE_CTL_CLEAR_COLOR_DISABLE;
+ case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
+ return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
+ case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
+ return PLANE_CTL_TILED_4 | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
case I915_FORMAT_MOD_Y_TILED_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
@@ -1936,7 +1944,7 @@ static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe)
static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
enum intel_fbc_id fbc_id, enum plane_id plane_id)
{
- if ((RUNTIME_INFO(dev_priv)->fbc_mask & BIT(fbc_id)) == 0)
+ if ((DISPLAY_RUNTIME_INFO(dev_priv)->fbc_mask & BIT(fbc_id)) == 0)
return false;
return plane_id == PLANE_PRIMARY;
@@ -2160,6 +2168,11 @@ skl_plane_disable_flip_done(struct intel_plane *plane)
static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915,
enum pipe pipe, enum plane_id plane_id)
{
+ /* Wa_14017240301 */
+ if (IS_MTL_GRAPHICS_STEP(i915, M, STEP_A0, STEP_B0) ||
+ IS_MTL_GRAPHICS_STEP(i915, P, STEP_A0, STEP_B0))
+ return false;
+
/* Wa_22011186057 */
if (IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
return false;
@@ -2441,12 +2454,17 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
case PLANE_CTL_TILED_Y:
plane_config->tiling = I915_TILING_Y;
if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
- if (DISPLAY_VER(dev_priv) >= 12)
+ if (DISPLAY_VER(dev_priv) >= 14)
+ fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS;
+ else if (DISPLAY_VER(dev_priv) >= 12)
fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS;
else
fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS;
else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
- fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
+ if (DISPLAY_VER(dev_priv) >= 14)
+ fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_MC_CCS;
+ else
+ fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
else
fb->modifier = I915_FORMAT_MOD_Y_TILED;
break;
@@ -2511,6 +2529,7 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
plane_config->base = base;
offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id));
+ drm_WARN_ON(&dev_priv->drm, offset != 0);
val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id));
fb->height = REG_FIELD_GET(PLANE_HEIGHT_MASK, val) + 1;
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 1c7e6468f3e3..063929a42a42 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -507,8 +507,8 @@ static u16 skl_ddb_entry_init(struct skl_ddb_entry *entry,
static int intel_dbuf_slice_size(struct drm_i915_private *i915)
{
- return INTEL_INFO(i915)->display.dbuf.size /
- hweight8(INTEL_INFO(i915)->display.dbuf.slice_mask);
+ return DISPLAY_INFO(i915)->dbuf.size /
+ hweight8(DISPLAY_INFO(i915)->dbuf.slice_mask);
}
static void
@@ -527,7 +527,7 @@ skl_ddb_entry_for_slices(struct drm_i915_private *i915, u8 slice_mask,
ddb->end = fls(slice_mask) * slice_size;
WARN_ON(ddb->start >= ddb->end);
- WARN_ON(ddb->end > INTEL_INFO(i915)->display.dbuf.size);
+ WARN_ON(ddb->end > DISPLAY_INFO(i915)->dbuf.size);
}
static unsigned int mbus_ddb_offset(struct drm_i915_private *i915, u8 slice_mask)
@@ -2625,7 +2625,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
"Enabled dbuf slices 0x%x -> 0x%x (total dbuf slices 0x%x), mbus joined? %s->%s\n",
old_dbuf_state->enabled_slices,
new_dbuf_state->enabled_slices,
- INTEL_INFO(i915)->display.dbuf.slice_mask,
+ DISPLAY_INFO(i915)->dbuf.slice_mask,
str_yes_no(old_dbuf_state->joined_mbus),
str_yes_no(new_dbuf_state->joined_mbus));
}
@@ -2900,7 +2900,7 @@ static int
skl_compute_wm(struct intel_atomic_state *state)
{
struct intel_crtc *crtc;
- struct intel_crtc_state *new_crtc_state;
+ struct intel_crtc_state __maybe_unused *new_crtc_state;
int ret, i;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 61d008d4e5f1..ae2f3ab3e73d 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -136,7 +136,7 @@ static ssize_t intel_dsi_host_transfer(struct mipi_dsi_host *host,
enum port port = intel_dsi_host->port;
struct mipi_dsi_packet packet;
ssize_t ret;
- const u8 *header, *data;
+ const u8 *header;
i915_reg_t data_reg, ctrl_reg;
u32 data_mask, ctrl_mask;
@@ -145,7 +145,6 @@ static ssize_t intel_dsi_host_transfer(struct mipi_dsi_host *host,
return ret;
header = packet.header;
- data = packet.payload;
if (msg->flags & MIPI_DSI_MSG_USE_LPM) {
data_reg = MIPI_LP_GEN_DATA(port);
@@ -280,6 +279,7 @@ static int intel_dsi_compute_config(struct intel_encoder *encoder,
int ret;
drm_dbg_kms(&dev_priv->drm, "\n");
+ pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
ret = intel_panel_compute_config(intel_connector, adjusted_mode);
@@ -1039,7 +1039,7 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder,
unsigned int lane_count = intel_dsi->lane_count;
unsigned int bpp, fmt;
enum port port;
- u16 hactive, hfp, hsync, hbp, vfp, vsync, vbp;
+ u16 hactive, hfp, hsync, hbp, vfp, vsync;
u16 hfp_sw, hsync_sw, hbp_sw;
u16 crtc_htotal_sw, crtc_hsync_start_sw, crtc_hsync_end_sw,
crtc_hblank_start_sw, crtc_hblank_end_sw;
@@ -1104,7 +1104,6 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder,
/* vertical values are in terms of lines */
vfp = intel_de_read(dev_priv, MIPI_VFP_COUNT(port));
vsync = intel_de_read(dev_priv, MIPI_VSYNC_PADDING_COUNT(port));
- vbp = intel_de_read(dev_priv, MIPI_VBP_COUNT(port));
adjusted_mode->crtc_htotal = hactive + hfp + hsync + hbp;
adjusted_mode->crtc_hsync_start = hfp + adjusted_mode->crtc_hdisplay;
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c
index b697badbbe71..ae0a0b11bae3 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c
@@ -598,7 +598,7 @@ static void assert_dsi_pll(struct drm_i915_private *i915, bool state)
cur_state = vlv_cck_read(i915, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_VCO_EN;
vlv_cck_put(i915);
- I915_STATE_WARN(cur_state != state,
+ I915_STATE_WARN(i915, cur_state != state,
"DSI PLL state assertion failure (expected %s, current %s)\n",
str_on_off(state), str_on_off(cur_state));
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 5402a7bbcb1d..9a9ff84c90d7 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -964,7 +964,11 @@ static int intel_context_set_gem(struct intel_context *ce,
RCU_INIT_POINTER(ce->gem_context, ctx);
GEM_BUG_ON(intel_context_is_pinned(ce));
- ce->ring_size = SZ_16K;
+
+ if (ce->engine->class == COMPUTE_CLASS)
+ ce->ring_size = SZ_512K;
+ else
+ ce->ring_size = SZ_16K;
i915_vm_put(ce->vm);
ce->vm = i915_gem_context_get_eb_vm(ctx);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_create.c b/drivers/gpu/drm/i915/gem/i915_gem_create.c
index bfe1dbda4cb7..d24c0ce8805c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_create.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_create.c
@@ -245,6 +245,7 @@ struct create_ext {
unsigned int n_placements;
unsigned int placement_mask;
unsigned long flags;
+ unsigned int pat_index;
};
static void repr_placements(char *buf, size_t size,
@@ -394,11 +395,43 @@ static int ext_set_protected(struct i915_user_extension __user *base, void *data
return 0;
}
+static int ext_set_pat(struct i915_user_extension __user *base, void *data)
+{
+ struct create_ext *ext_data = data;
+ struct drm_i915_private *i915 = ext_data->i915;
+ struct drm_i915_gem_create_ext_set_pat ext;
+ unsigned int max_pat_index;
+
+ BUILD_BUG_ON(sizeof(struct drm_i915_gem_create_ext_set_pat) !=
+ offsetofend(struct drm_i915_gem_create_ext_set_pat, rsvd));
+
+ /* Limiting the extension only to Meteor Lake */
+ if (!IS_METEORLAKE(i915))
+ return -ENODEV;
+
+ if (copy_from_user(&ext, base, sizeof(ext)))
+ return -EFAULT;
+
+ max_pat_index = INTEL_INFO(i915)->max_pat_index;
+
+ if (ext.pat_index > max_pat_index) {
+ drm_dbg(&i915->drm, "PAT index is invalid: %u\n",
+ ext.pat_index);
+ return -EINVAL;
+ }
+
+ ext_data->pat_index = ext.pat_index;
+
+ return 0;
+}
+
static const i915_user_extension_fn create_extensions[] = {
[I915_GEM_CREATE_EXT_MEMORY_REGIONS] = ext_set_placements,
[I915_GEM_CREATE_EXT_PROTECTED_CONTENT] = ext_set_protected,
+ [I915_GEM_CREATE_EXT_SET_PAT] = ext_set_pat,
};
+#define PAT_INDEX_NOT_SET 0xffff
/**
* i915_gem_create_ext_ioctl - Creates a new mm object and returns a handle to it.
* @dev: drm device pointer
@@ -418,6 +451,7 @@ i915_gem_create_ext_ioctl(struct drm_device *dev, void *data,
if (args->flags & ~I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS)
return -EINVAL;
+ ext_data.pat_index = PAT_INDEX_NOT_SET;
ret = i915_user_extensions(u64_to_user_ptr(args->extensions),
create_extensions,
ARRAY_SIZE(create_extensions),
@@ -454,5 +488,11 @@ i915_gem_create_ext_ioctl(struct drm_device *dev, void *data,
if (IS_ERR(obj))
return PTR_ERR(obj);
+ if (ext_data.pat_index != PAT_INDEX_NOT_SET) {
+ i915_gem_object_set_pat_index(obj, ext_data.pat_index);
+ /* Mark pat_index is set by UMD */
+ obj->pat_set_by_user = true;
+ }
+
return i915_gem_publish(obj, file, &args->size, &args->handle);
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
index d2d5a24301b2..dfaaa8b66ac3 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
@@ -27,8 +27,15 @@ static bool gpu_write_needs_clflush(struct drm_i915_gem_object *obj)
if (IS_DGFX(i915))
return false;
- return !(obj->cache_level == I915_CACHE_NONE ||
- obj->cache_level == I915_CACHE_WT);
+ /*
+ * For objects created by userspace through GEM_CREATE with pat_index
+ * set by set_pat extension, i915_gem_object_has_cache_level() will
+ * always return true, because the coherency of such object is managed
+ * by userspace. Othereise the call here would fall back to checking
+ * whether the object is un-cached or write-through.
+ */
+ return !(i915_gem_object_has_cache_level(obj, I915_CACHE_NONE) ||
+ i915_gem_object_has_cache_level(obj, I915_CACHE_WT));
}
bool i915_gem_cpu_write_needs_clflush(struct drm_i915_gem_object *obj)
@@ -267,7 +274,13 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
{
int ret;
- if (obj->cache_level == cache_level)
+ /*
+ * For objects created by userspace through GEM_CREATE with pat_index
+ * set by set_pat extension, simply return 0 here without touching
+ * the cache setting, because such objects should have an immutable
+ * cache setting by desgin and always managed by userspace.
+ */
+ if (i915_gem_object_has_cache_level(obj, cache_level))
return 0;
ret = i915_gem_object_wait(obj,
@@ -278,10 +291,8 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
return ret;
/* Always invalidate stale cachelines */
- if (obj->cache_level != cache_level) {
- i915_gem_object_set_cache_coherency(obj, cache_level);
- obj->cache_dirty = true;
- }
+ i915_gem_object_set_cache_coherency(obj, cache_level);
+ obj->cache_dirty = true;
/* The cache-level will be applied when each vma is rebound. */
return i915_gem_object_unbind(obj,
@@ -306,20 +317,22 @@ int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data,
goto out;
}
- switch (obj->cache_level) {
- case I915_CACHE_LLC:
- case I915_CACHE_L3_LLC:
- args->caching = I915_CACHING_CACHED;
- break;
+ /*
+ * This ioctl should be disabled for the objects with pat_index
+ * set by user space.
+ */
+ if (obj->pat_set_by_user) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
- case I915_CACHE_WT:
+ if (i915_gem_object_has_cache_level(obj, I915_CACHE_LLC) ||
+ i915_gem_object_has_cache_level(obj, I915_CACHE_L3_LLC))
+ args->caching = I915_CACHING_CACHED;
+ else if (i915_gem_object_has_cache_level(obj, I915_CACHE_WT))
args->caching = I915_CACHING_DISPLAY;
- break;
-
- default:
+ else
args->caching = I915_CACHING_NONE;
- break;
- }
out:
rcu_read_unlock();
return err;
@@ -337,6 +350,9 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
if (IS_DGFX(i915))
return -ENODEV;
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))
+ return -EOPNOTSUPP;
+
switch (args->caching) {
case I915_CACHING_NONE:
level = I915_CACHE_NONE;
@@ -365,6 +381,15 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
return -ENOENT;
/*
+ * This ioctl should be disabled for the objects with pat_index
+ * set by user space.
+ */
+ if (obj->pat_set_by_user) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /*
* The caching mode of proxy object is handled by its generator, and
* not allowed to be changed by userspace.
*/
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 3aeede6aee4d..cfd7929587d8 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -640,9 +640,15 @@ static inline int use_cpu_reloc(const struct reloc_cache *cache,
if (DBG_FORCE_RELOC == FORCE_GTT_RELOC)
return false;
+ /*
+ * For objects created by userspace through GEM_CREATE with pat_index
+ * set by set_pat extension, i915_gem_object_has_cache_level() always
+ * return true, otherwise the call would fall back to checking whether
+ * the object is un-cached.
+ */
return (cache->has_llc ||
obj->cache_dirty ||
- obj->cache_level != I915_CACHE_NONE);
+ !i915_gem_object_has_cache_level(obj, I915_CACHE_NONE));
}
static int eb_reserve_vma(struct i915_execbuffer *eb,
@@ -730,7 +736,6 @@ static int eb_reserve(struct i915_execbuffer *eb)
struct eb_vma *ev;
unsigned int pass;
int err = 0;
- bool unpinned;
/*
* We have one more buffers that we couldn't bind, which could be due to
@@ -770,7 +775,7 @@ static int eb_reserve(struct i915_execbuffer *eb)
pin_flags |= PIN_NONBLOCK;
if (pass >= 1)
- unpinned = eb_unbind(eb, pass >= 2);
+ eb_unbind(eb, pass >= 2);
if (pass == 2) {
err = mutex_lock_interruptible(&eb->context->vm->mutex);
@@ -1324,7 +1329,10 @@ static void *reloc_iomap(struct i915_vma *batch,
if (drm_mm_node_allocated(&cache->node)) {
ggtt->vm.insert_page(&ggtt->vm,
i915_gem_object_get_dma_address(obj, page),
- offset, I915_CACHE_NONE, 0);
+ offset,
+ i915_gem_get_pat_index(ggtt->vm.i915,
+ I915_CACHE_NONE),
+ 0);
} else {
offset += page << PAGE_SHIFT;
}
@@ -1464,7 +1472,7 @@ eb_relocate_entry(struct i915_execbuffer *eb,
reloc_cache_unmap(&eb->reloc_cache);
mutex_lock(&vma->vm->mutex);
err = i915_vma_bind(target->vma,
- target->vma->obj->cache_level,
+ target->vma->obj->pat_index,
PIN_GLOBAL, NULL, NULL);
mutex_unlock(&vma->vm->mutex);
reloc_cache_remap(&eb->reloc_cache, ev->vma->obj);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
index d3c1dee16af2..aa4d842d4c5a 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -383,7 +383,16 @@ retry:
}
/* Access to snoopable pages through the GTT is incoherent. */
- if (obj->cache_level != I915_CACHE_NONE && !HAS_LLC(i915)) {
+ /*
+ * For objects created by userspace through GEM_CREATE with pat_index
+ * set by set_pat extension, coherency is managed by userspace, make
+ * sure we don't fail handling the vm fault by calling
+ * i915_gem_object_has_cache_level() which always return true for such
+ * objects. Otherwise this helper function would fall back to checking
+ * whether the object is un-cached.
+ */
+ if (!(i915_gem_object_has_cache_level(obj, I915_CACHE_NONE) ||
+ HAS_LLC(i915))) {
ret = -EFAULT;
goto err_unpin;
}
@@ -927,53 +936,15 @@ static struct file *mmap_singleton(struct drm_i915_private *i915)
return file;
}
-/*
- * This overcomes the limitation in drm_gem_mmap's assignment of a
- * drm_gem_object as the vma->vm_private_data. Since we need to
- * be able to resolve multiple mmap offsets which could be tied
- * to a single gem object.
- */
-int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+static int
+i915_gem_object_mmap(struct drm_i915_gem_object *obj,
+ struct i915_mmap_offset *mmo,
+ struct vm_area_struct *vma)
{
- struct drm_vma_offset_node *node;
- struct drm_file *priv = filp->private_data;
- struct drm_device *dev = priv->minor->dev;
- struct drm_i915_gem_object *obj = NULL;
- struct i915_mmap_offset *mmo = NULL;
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+ struct drm_device *dev = &i915->drm;
struct file *anon;
- if (drm_dev_is_unplugged(dev))
- return -ENODEV;
-
- rcu_read_lock();
- drm_vma_offset_lock_lookup(dev->vma_offset_manager);
- node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
- vma->vm_pgoff,
- vma_pages(vma));
- if (node && drm_vma_node_is_allowed(node, priv)) {
- /*
- * Skip 0-refcnted objects as it is in the process of being
- * destroyed and will be invalid when the vma manager lock
- * is released.
- */
- if (!node->driver_private) {
- mmo = container_of(node, struct i915_mmap_offset, vma_node);
- obj = i915_gem_object_get_rcu(mmo->obj);
-
- GEM_BUG_ON(obj && obj->ops->mmap_ops);
- } else {
- obj = i915_gem_object_get_rcu
- (container_of(node, struct drm_i915_gem_object,
- base.vma_node));
-
- GEM_BUG_ON(obj && !obj->ops->mmap_ops);
- }
- }
- drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
- rcu_read_unlock();
- if (!obj)
- return node ? -EACCES : -EINVAL;
-
if (i915_gem_object_is_readonly(obj)) {
if (vma->vm_flags & VM_WRITE) {
i915_gem_object_put(obj);
@@ -1005,7 +976,7 @@ int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
if (obj->ops->mmap_ops) {
vma->vm_page_prot = pgprot_decrypted(vm_get_page_prot(vma->vm_flags));
vma->vm_ops = obj->ops->mmap_ops;
- vma->vm_private_data = node->driver_private;
+ vma->vm_private_data = obj->base.vma_node.driver_private;
return 0;
}
@@ -1043,6 +1014,91 @@ int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
return 0;
}
+/*
+ * This overcomes the limitation in drm_gem_mmap's assignment of a
+ * drm_gem_object as the vma->vm_private_data. Since we need to
+ * be able to resolve multiple mmap offsets which could be tied
+ * to a single gem object.
+ */
+int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct drm_vma_offset_node *node;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->minor->dev;
+ struct drm_i915_gem_object *obj = NULL;
+ struct i915_mmap_offset *mmo = NULL;
+
+ if (drm_dev_is_unplugged(dev))
+ return -ENODEV;
+
+ rcu_read_lock();
+ drm_vma_offset_lock_lookup(dev->vma_offset_manager);
+ node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
+ vma->vm_pgoff,
+ vma_pages(vma));
+ if (node && drm_vma_node_is_allowed(node, priv)) {
+ /*
+ * Skip 0-refcnted objects as it is in the process of being
+ * destroyed and will be invalid when the vma manager lock
+ * is released.
+ */
+ if (!node->driver_private) {
+ mmo = container_of(node, struct i915_mmap_offset, vma_node);
+ obj = i915_gem_object_get_rcu(mmo->obj);
+
+ GEM_BUG_ON(obj && obj->ops->mmap_ops);
+ } else {
+ obj = i915_gem_object_get_rcu
+ (container_of(node, struct drm_i915_gem_object,
+ base.vma_node));
+
+ GEM_BUG_ON(obj && !obj->ops->mmap_ops);
+ }
+ }
+ drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
+ rcu_read_unlock();
+ if (!obj)
+ return node ? -EACCES : -EINVAL;
+
+ return i915_gem_object_mmap(obj, mmo, vma);
+}
+
+int i915_gem_fb_mmap(struct drm_i915_gem_object *obj, struct vm_area_struct *vma)
+{
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+ struct drm_device *dev = &i915->drm;
+ struct i915_mmap_offset *mmo = NULL;
+ enum i915_mmap_type mmap_type;
+ struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
+
+ if (drm_dev_is_unplugged(dev))
+ return -ENODEV;
+
+ /* handle ttm object */
+ if (obj->ops->mmap_ops) {
+ /*
+ * ttm fault handler, ttm_bo_vm_fault_reserved() uses fake offset
+ * to calculate page offset so set that up.
+ */
+ vma->vm_pgoff += drm_vma_node_start(&obj->base.vma_node);
+ } else {
+ /* handle stolen and smem objects */
+ mmap_type = i915_ggtt_has_aperture(ggtt) ? I915_MMAP_TYPE_GTT : I915_MMAP_TYPE_WC;
+ mmo = mmap_offset_attach(obj, mmap_type, NULL);
+ if (IS_ERR(mmo))
+ return PTR_ERR(mmo);
+ }
+
+ /*
+ * When we install vm_ops for mmap we are too late for
+ * the vm_ops->open() which increases the ref_count of
+ * this obj and then it gets decreased by the vm_ops->close().
+ * To balance this increase the obj ref_count here.
+ */
+ obj = i915_gem_object_get(obj);
+ return i915_gem_object_mmap(obj, mmo, vma);
+}
+
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/i915_gem_mman.c"
#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.h b/drivers/gpu/drm/i915/gem/i915_gem_mman.h
index 1fa91b3033b3..196417fd0f5c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.h
@@ -29,5 +29,5 @@ void i915_gem_object_release_mmap_gtt(struct drm_i915_gem_object *obj);
void i915_gem_object_runtime_pm_release_mmap_offset(struct drm_i915_gem_object *obj);
void i915_gem_object_release_mmap_offset(struct drm_i915_gem_object *obj);
-
+int i915_gem_fb_mmap(struct drm_i915_gem_object *obj, struct vm_area_struct *vma);
#endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 4666bb82f312..97ac6fb37958 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -45,6 +45,33 @@ static struct kmem_cache *slab_objects;
static const struct drm_gem_object_funcs i915_gem_object_funcs;
+unsigned int i915_gem_get_pat_index(struct drm_i915_private *i915,
+ enum i915_cache_level level)
+{
+ if (drm_WARN_ON(&i915->drm, level >= I915_MAX_CACHE_LEVEL))
+ return 0;
+
+ return INTEL_INFO(i915)->cachelevel_to_pat[level];
+}
+
+bool i915_gem_object_has_cache_level(const struct drm_i915_gem_object *obj,
+ enum i915_cache_level lvl)
+{
+ /*
+ * In case the pat_index is set by user space, this kernel mode
+ * driver should leave the coherency to be managed by user space,
+ * simply return true here.
+ */
+ if (obj->pat_set_by_user)
+ return true;
+
+ /*
+ * Otherwise the pat_index should have been converted from cache_level
+ * so that the following comparison is valid.
+ */
+ return obj->pat_index == i915_gem_get_pat_index(obj_to_i915(obj), lvl);
+}
+
struct drm_i915_gem_object *i915_gem_object_alloc(void)
{
struct drm_i915_gem_object *obj;
@@ -124,7 +151,7 @@ void i915_gem_object_set_cache_coherency(struct drm_i915_gem_object *obj,
{
struct drm_i915_private *i915 = to_i915(obj->base.dev);
- obj->cache_level = cache_level;
+ obj->pat_index = i915_gem_get_pat_index(i915, cache_level);
if (cache_level != I915_CACHE_NONE)
obj->cache_coherent = (I915_BO_CACHE_COHERENT_FOR_READ |
@@ -139,6 +166,37 @@ void i915_gem_object_set_cache_coherency(struct drm_i915_gem_object *obj,
!IS_DGFX(i915);
}
+/**
+ * i915_gem_object_set_pat_index - set PAT index to be used in PTE encode
+ * @obj: #drm_i915_gem_object
+ * @pat_index: PAT index
+ *
+ * This is a clone of i915_gem_object_set_cache_coherency taking pat index
+ * instead of cache_level as its second argument.
+ */
+void i915_gem_object_set_pat_index(struct drm_i915_gem_object *obj,
+ unsigned int pat_index)
+{
+ struct drm_i915_private *i915 = to_i915(obj->base.dev);
+
+ if (obj->pat_index == pat_index)
+ return;
+
+ obj->pat_index = pat_index;
+
+ if (pat_index != i915_gem_get_pat_index(i915, I915_CACHE_NONE))
+ obj->cache_coherent = (I915_BO_CACHE_COHERENT_FOR_READ |
+ I915_BO_CACHE_COHERENT_FOR_WRITE);
+ else if (HAS_LLC(i915))
+ obj->cache_coherent = I915_BO_CACHE_COHERENT_FOR_READ;
+ else
+ obj->cache_coherent = 0;
+
+ obj->cache_dirty =
+ !(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE) &&
+ !IS_DGFX(i915);
+}
+
bool i915_gem_object_can_bypass_llc(struct drm_i915_gem_object *obj)
{
struct drm_i915_private *i915 = to_i915(obj->base.dev);
@@ -151,6 +209,12 @@ bool i915_gem_object_can_bypass_llc(struct drm_i915_gem_object *obj)
return false;
/*
+ * Always flush cache for UMD objects at creation time.
+ */
+ if (obj->pat_set_by_user)
+ return true;
+
+ /*
* EHL and JSL add the 'Bypass LLC' MOCS entry, which should make it
* possible for userspace to bypass the GTT caching bits set by the
* kernel, as per the given object cache_level. This is troublesome
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 885ccde9dc3c..884a17275b3a 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -20,6 +20,8 @@
enum intel_region_id;
+#define obj_to_i915(obj__) to_i915((obj__)->base.dev)
+
static inline bool i915_gem_object_size_2big(u64 size)
{
struct drm_i915_gem_object *obj;
@@ -30,6 +32,10 @@ static inline bool i915_gem_object_size_2big(u64 size)
return false;
}
+unsigned int i915_gem_get_pat_index(struct drm_i915_private *i915,
+ enum i915_cache_level level);
+bool i915_gem_object_has_cache_level(const struct drm_i915_gem_object *obj,
+ enum i915_cache_level lvl);
void i915_gem_init__objects(struct drm_i915_private *i915);
void i915_objects_module_exit(void);
@@ -80,7 +86,7 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj);
/**
* i915_gem_object_lookup_rcu - look up a temporary GEM object from its handle
- * @filp: DRM file private date
+ * @file: DRM file private date
* @handle: userspace handle
*
* Returns:
@@ -760,6 +766,8 @@ bool i915_gem_object_has_unknown_state(struct drm_i915_gem_object *obj);
void i915_gem_object_set_cache_coherency(struct drm_i915_gem_object *obj,
unsigned int cache_level);
+void i915_gem_object_set_pat_index(struct drm_i915_gem_object *obj,
+ unsigned int pat_index);
bool i915_gem_object_can_bypass_llc(struct drm_i915_gem_object *obj);
void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj);
void i915_gem_object_flush_if_display_locked(struct drm_i915_gem_object *obj);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index 5dcbbef31d44..e72c57716bee 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -194,6 +194,13 @@ enum i915_cache_level {
* engine.
*/
I915_CACHE_WT,
+ /**
+ * @I915_MAX_CACHE_LEVEL:
+ *
+ * Mark the last entry in the enum. Used for defining cachelevel_to_pat
+ * array for cache_level to pat translation table.
+ */
+ I915_MAX_CACHE_LEVEL,
};
enum i915_map_type {
@@ -328,6 +335,12 @@ struct drm_i915_gem_object {
*/
#define I915_BO_ALLOC_GPU_ONLY BIT(6)
#define I915_BO_ALLOC_CCS_AUX BIT(7)
+/*
+ * Object is allowed to retain its initial data and will not be cleared on first
+ * access if used along with I915_BO_ALLOC_USER. This is mainly to keep
+ * preallocated framebuffer data intact while transitioning it to i915drmfb.
+ */
+#define I915_BO_PREALLOC BIT(8)
#define I915_BO_ALLOC_FLAGS (I915_BO_ALLOC_CONTIGUOUS | \
I915_BO_ALLOC_VOLATILE | \
I915_BO_ALLOC_CPU_CLEAR | \
@@ -335,10 +348,11 @@ struct drm_i915_gem_object {
I915_BO_ALLOC_PM_VOLATILE | \
I915_BO_ALLOC_PM_EARLY | \
I915_BO_ALLOC_GPU_ONLY | \
- I915_BO_ALLOC_CCS_AUX)
-#define I915_BO_READONLY BIT(8)
-#define I915_TILING_QUIRK_BIT 9 /* unknown swizzling; do not release! */
-#define I915_BO_PROTECTED BIT(10)
+ I915_BO_ALLOC_CCS_AUX | \
+ I915_BO_PREALLOC)
+#define I915_BO_READONLY BIT(9)
+#define I915_TILING_QUIRK_BIT 10 /* unknown swizzling; do not release! */
+#define I915_BO_PROTECTED BIT(11)
/**
* @mem_flags - Mutable placement-related flags
*
@@ -350,15 +364,43 @@ struct drm_i915_gem_object {
#define I915_BO_FLAG_STRUCT_PAGE BIT(0) /* Object backed by struct pages */
#define I915_BO_FLAG_IOMEM BIT(1) /* Object backed by IO memory */
/**
- * @cache_level: The desired GTT caching level.
+ * @pat_index: The desired PAT index.
+ *
+ * See hardware specification for valid PAT indices for each platform.
+ * This field replaces the @cache_level that contains a value of enum
+ * i915_cache_level since PAT indices are being used by both userspace
+ * and kernel mode driver for caching policy control after GEN12.
+ * In the meantime platform specific tables are created to translate
+ * i915_cache_level into pat index, for more details check the macros
+ * defined i915/i915_pci.c, e.g. PVC_CACHELEVEL.
+ * For backward compatibility, this field contains values exactly match
+ * the entries of enum i915_cache_level for pre-GEN12 platforms (See
+ * LEGACY_CACHELEVEL), so that the PTE encode functions for these
+ * legacy platforms can stay the same.
+ */
+ unsigned int pat_index:6;
+ /**
+ * @pat_set_by_user: Indicate whether pat_index is set by user space
*
- * See enum i915_cache_level for possible values, along with what
- * each does.
+ * This field is set to false by default, only set to true if the
+ * pat_index is set by user space. By design, user space is capable of
+ * managing caching behavior by setting pat_index, in which case this
+ * kernel mode driver should never touch the pat_index.
*/
- unsigned int cache_level:3;
+ unsigned int pat_set_by_user:1;
/**
* @cache_coherent:
*
+ * Note: with the change above which replaced @cache_level with pat_index,
+ * the use of @cache_coherent is limited to the objects created by kernel
+ * or by userspace without pat index specified.
+ * Check for @pat_set_by_user to find out if an object has pat index set
+ * by userspace. The ioctl's to change cache settings have also been
+ * disabled for the objects with pat index set by userspace. Please don't
+ * assume @cache_coherent having the flags set as describe here. A helper
+ * function i915_gem_object_has_cache_level() provides one way to bypass
+ * the use of this field.
+ *
* Track whether the pages are coherent with the GPU if reading or
* writing through the CPU caches. The largely depends on the
* @cache_level setting.
@@ -432,6 +474,16 @@ struct drm_i915_gem_object {
/**
* @cache_dirty:
*
+ * Note: with the change above which replaced cache_level with pat_index,
+ * the use of @cache_dirty is limited to the objects created by kernel
+ * or by userspace without pat index specified.
+ * Check for @pat_set_by_user to find out if an object has pat index set
+ * by userspace. The ioctl's to change cache settings have also been
+ * disabled for the objects with pat_index set by userspace. Please don't
+ * assume @cache_dirty is set as describe here. Also see helper function
+ * i915_gem_object_has_cache_level() for possible ways to bypass the use
+ * of this field.
+ *
* Track if we are we dirty with writes through the CPU cache for this
* object. As a result reading directly from main memory might yield
* stale data.
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
index ecd86130b74f..89fc8ea6bcfc 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -469,7 +469,10 @@ enum i915_map_type i915_coherent_map_type(struct drm_i915_private *i915,
struct drm_i915_gem_object *obj,
bool always_coherent)
{
- if (i915_gem_object_is_lmem(obj))
+ /*
+ * Wa_22016122933: always return I915_MAP_WC for MTL
+ */
+ if (i915_gem_object_is_lmem(obj) || IS_METEORLAKE(i915))
return I915_MAP_WC;
if (HAS_LLC(i915) || always_coherent)
return I915_MAP_WB;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.h b/drivers/gpu/drm/i915/gem/i915_gem_region.h
index 2dfcc41c0170..8a7650b27cc2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_region.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_region.h
@@ -22,9 +22,7 @@ struct i915_gem_apply_to_region;
*/
struct i915_gem_apply_to_region_ops {
/**
- * process_obj - Process the current object
- * @apply: Embed this for private data.
- * @obj: The current object.
+ * @process_obj: Process the current object
*
* Note that if this function is part of a ww transaction, and
* if returns -EDEADLK for one of the objects, it may be
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
index adf1154c0e10..8f1633c3fb93 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -462,7 +462,7 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
struct page *page;
void *data, *vaddr;
int err;
- char c;
+ char __maybe_unused c;
len = PAGE_SIZE - pg;
if (len > remain)
@@ -608,7 +608,14 @@ static int shmem_object_init(struct intel_memory_region *mem,
obj->write_domain = I915_GEM_DOMAIN_CPU;
obj->read_domains = I915_GEM_DOMAIN_CPU;
- if (HAS_LLC(i915))
+ /*
+ * MTL doesn't snoop CPU cache by default for GPU access (namely
+ * 1-way coherency). However some UMD's are currently depending on
+ * that. Make 1-way coherent the default setting for MTL. A follow
+ * up patch will extend the GEM_CREATE uAPI to allow UMD's specify
+ * caching mode at BO creation time
+ */
+ if (HAS_LLC(i915) || (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70)))
/* On some devices, we can have the GPU use the LLC (the CPU
* cache) for about a 10% performance improvement
* compared to uncached. Graphics requests other than
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c
index b1672e054b21..214763942aa2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c
@@ -460,8 +460,6 @@ void i915_gem_shrinker_taints_mutex(struct drm_i915_private *i915,
fs_reclaim_release(GFP_KERNEL);
}
-#define obj_to_i915(obj__) to_i915((obj__)->base.dev)
-
/**
* i915_gem_object_make_unshrinkable - Hide the object from the shrinker. By
* default all object types that support shrinking(see IS_SHRINKABLE), will also
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
index 8ac376c24aa2..3b094d36a0b0 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
@@ -535,6 +535,14 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem)
/* Basic memrange allocator for stolen space. */
drm_mm_init(&i915->mm.stolen, 0, i915->dsm.usable_size);
+ /*
+ * Access to stolen lmem beyond certain size for MTL A0 stepping
+ * would crash the machine. Disable stolen lmem for userspace access
+ * by setting usable_size to zero.
+ */
+ if (IS_METEORLAKE(i915) && INTEL_REVID(i915) == 0x0)
+ i915->dsm.usable_size = 0;
+
return 0;
}
@@ -557,7 +565,9 @@ static void dbg_poison(struct i915_ggtt *ggtt,
ggtt->vm.insert_page(&ggtt->vm, addr,
ggtt->error_capture.start,
- I915_CACHE_NONE, 0);
+ i915_gem_get_pat_index(ggtt->vm.i915,
+ I915_CACHE_NONE),
+ 0);
mb();
s = io_mapping_map_wc(&ggtt->iomap,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
index f8f6bed1b297..67347e62e29b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
@@ -42,8 +42,9 @@ static inline bool i915_ttm_is_ghost_object(struct ttm_buffer_object *bo)
/**
* i915_ttm_to_gem - Convert a struct ttm_buffer_object to an embedding
* struct drm_i915_gem_object.
+ * @bo: Pointer to the ttm buffer object
*
- * Return: Pointer to the embedding struct ttm_buffer_object.
+ * Return: Pointer to the embedding struct drm_i915_gem_object.
*/
static inline struct drm_i915_gem_object *
i915_ttm_to_gem(struct ttm_buffer_object *bo)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
index dd188dfcc423..7078af2f8f79 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
@@ -214,7 +214,8 @@ static struct dma_fence *i915_ttm_accel_move(struct ttm_buffer_object *bo,
intel_engine_pm_get(to_gt(i915)->migrate.context->engine);
ret = intel_context_migrate_clear(to_gt(i915)->migrate.context, deps,
- dst_st->sgl, dst_level,
+ dst_st->sgl,
+ i915_gem_get_pat_index(i915, dst_level),
i915_ttm_gtt_binds_lmem(dst_mem),
0, &rq);
} else {
@@ -228,9 +229,10 @@ static struct dma_fence *i915_ttm_accel_move(struct ttm_buffer_object *bo,
intel_engine_pm_get(to_gt(i915)->migrate.context->engine);
ret = intel_context_migrate_copy(to_gt(i915)->migrate.context,
deps, src_rsgt->table.sgl,
- src_level,
+ i915_gem_get_pat_index(i915, src_level),
i915_ttm_gtt_binds_lmem(bo->resource),
- dst_st->sgl, dst_level,
+ dst_st->sgl,
+ i915_gem_get_pat_index(i915, dst_level),
i915_ttm_gtt_binds_lmem(dst_mem),
&rq);
@@ -576,7 +578,7 @@ int i915_ttm_move(struct ttm_buffer_object *bo, bool evict,
struct dma_fence *migration_fence = NULL;
struct ttm_tt *ttm = bo->ttm;
struct i915_refct_sgt *dst_rsgt;
- bool clear;
+ bool clear, prealloc_bo;
int ret;
if (GEM_WARN_ON(i915_ttm_is_ghost_object(bo))) {
@@ -632,7 +634,8 @@ int i915_ttm_move(struct ttm_buffer_object *bo, bool evict,
return PTR_ERR(dst_rsgt);
clear = !i915_ttm_cpu_maps_iomem(bo->resource) && (!ttm || !ttm_tt_is_populated(ttm));
- if (!(clear && ttm && !(ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC))) {
+ prealloc_bo = obj->flags & I915_BO_PREALLOC;
+ if (!(clear && ttm && !((ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC) && !prealloc_bo))) {
struct i915_deps deps;
i915_deps_init(&deps, GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
index 99f39a5feca1..df6c9a84252c 100644
--- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
+++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
@@ -354,7 +354,7 @@ fake_huge_pages_object(struct drm_i915_private *i915, u64 size, bool single)
obj->write_domain = I915_GEM_DOMAIN_CPU;
obj->read_domains = I915_GEM_DOMAIN_CPU;
- obj->cache_level = I915_CACHE_NONE;
+ obj->pat_index = i915_gem_get_pat_index(i915, I915_CACHE_NONE);
return obj;
}
@@ -695,8 +695,7 @@ out_put:
return err;
}
-static void close_object_list(struct list_head *objects,
- struct i915_ppgtt *ppgtt)
+static void close_object_list(struct list_head *objects)
{
struct drm_i915_gem_object *obj, *on;
@@ -710,17 +709,36 @@ static void close_object_list(struct list_head *objects,
}
}
-static int igt_mock_ppgtt_huge_fill(void *arg)
+static int igt_ppgtt_huge_fill(void *arg)
{
- struct i915_ppgtt *ppgtt = arg;
- struct drm_i915_private *i915 = ppgtt->vm.i915;
- unsigned long max_pages = ppgtt->vm.total >> PAGE_SHIFT;
+ struct drm_i915_private *i915 = arg;
+ unsigned int supported = RUNTIME_INFO(i915)->page_sizes;
+ bool has_pte64 = GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50);
+ struct i915_address_space *vm;
+ struct i915_gem_context *ctx;
+ unsigned long max_pages;
unsigned long page_num;
+ struct file *file;
bool single = false;
LIST_HEAD(objects);
IGT_TIMEOUT(end_time);
int err = -ENODEV;
+ if (supported == I915_GTT_PAGE_SIZE_4K)
+ return 0;
+
+ file = mock_file(i915);
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+
+ ctx = hugepage_ctx(i915, file);
+ if (IS_ERR(ctx)) {
+ err = PTR_ERR(ctx);
+ goto out;
+ }
+ vm = i915_gem_context_get_eb_vm(ctx);
+ max_pages = vm->total >> PAGE_SHIFT;
+
for_each_prime_number_from(page_num, 1, max_pages) {
struct drm_i915_gem_object *obj;
u64 size = page_num << PAGE_SHIFT;
@@ -750,13 +768,14 @@ static int igt_mock_ppgtt_huge_fill(void *arg)
list_add(&obj->st_link, &objects);
- vma = i915_vma_instance(obj, &ppgtt->vm, NULL);
+ vma = i915_vma_instance(obj, vm, NULL);
if (IS_ERR(vma)) {
err = PTR_ERR(vma);
break;
}
- err = i915_vma_pin(vma, 0, 0, PIN_USER);
+ /* vma start must be aligned to BIT(21) to allow 2M PTEs */
+ err = i915_vma_pin(vma, 0, BIT(21), PIN_USER);
if (err)
break;
@@ -784,12 +803,13 @@ static int igt_mock_ppgtt_huge_fill(void *arg)
GEM_BUG_ON(!expected_gtt);
GEM_BUG_ON(size);
- if (expected_gtt & I915_GTT_PAGE_SIZE_4K)
+ if (!has_pte64 && (obj->base.size < I915_GTT_PAGE_SIZE_2M ||
+ expected_gtt & I915_GTT_PAGE_SIZE_2M))
expected_gtt &= ~I915_GTT_PAGE_SIZE_64K;
i915_vma_unpin(vma);
- if (vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K) {
+ if (!has_pte64 && vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K) {
if (!IS_ALIGNED(vma->node.start,
I915_GTT_PAGE_SIZE_2M)) {
pr_err("node.start(%llx) not aligned to 2M\n",
@@ -808,7 +828,7 @@ static int igt_mock_ppgtt_huge_fill(void *arg)
}
if (vma->resource->page_sizes_gtt != expected_gtt) {
- pr_err("gtt=%u, expected=%u, size=%zd, single=%s\n",
+ pr_err("gtt=%#x, expected=%#x, size=0x%zx, single=%s\n",
vma->resource->page_sizes_gtt, expected_gtt,
obj->base.size, str_yes_no(!!single));
err = -EINVAL;
@@ -823,19 +843,25 @@ static int igt_mock_ppgtt_huge_fill(void *arg)
single = !single;
}
- close_object_list(&objects, ppgtt);
+ close_object_list(&objects);
if (err == -ENOMEM || err == -ENOSPC)
err = 0;
+ i915_vm_put(vm);
+out:
+ fput(file);
return err;
}
-static int igt_mock_ppgtt_64K(void *arg)
+static int igt_ppgtt_64K(void *arg)
{
- struct i915_ppgtt *ppgtt = arg;
- struct drm_i915_private *i915 = ppgtt->vm.i915;
+ struct drm_i915_private *i915 = arg;
+ bool has_pte64 = GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50);
struct drm_i915_gem_object *obj;
+ struct i915_address_space *vm;
+ struct i915_gem_context *ctx;
+ struct file *file;
const struct object_info {
unsigned int size;
unsigned int gtt;
@@ -907,16 +933,41 @@ static int igt_mock_ppgtt_64K(void *arg)
if (!HAS_PAGE_SIZES(i915, I915_GTT_PAGE_SIZE_64K))
return 0;
+ file = mock_file(i915);
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+
+ ctx = hugepage_ctx(i915, file);
+ if (IS_ERR(ctx)) {
+ err = PTR_ERR(ctx);
+ goto out;
+ }
+ vm = i915_gem_context_get_eb_vm(ctx);
+
for (i = 0; i < ARRAY_SIZE(objects); ++i) {
unsigned int size = objects[i].size;
unsigned int expected_gtt = objects[i].gtt;
unsigned int offset = objects[i].offset;
unsigned int flags = PIN_USER;
+ /*
+ * For modern GTT models, the requirements for marking a page-table
+ * as 64K have been relaxed. Account for this.
+ */
+ if (has_pte64) {
+ expected_gtt = 0;
+ if (size >= SZ_64K)
+ expected_gtt |= I915_GTT_PAGE_SIZE_64K;
+ if (size & (SZ_64K - 1))
+ expected_gtt |= I915_GTT_PAGE_SIZE_4K;
+ }
+
for (single = 0; single <= 1; single++) {
obj = fake_huge_pages_object(i915, size, !!single);
- if (IS_ERR(obj))
- return PTR_ERR(obj);
+ if (IS_ERR(obj)) {
+ err = PTR_ERR(obj);
+ goto out_vm;
+ }
err = i915_gem_object_pin_pages_unlocked(obj);
if (err)
@@ -928,7 +979,7 @@ static int igt_mock_ppgtt_64K(void *arg)
*/
obj->mm.page_sizes.sg &= ~I915_GTT_PAGE_SIZE_2M;
- vma = i915_vma_instance(obj, &ppgtt->vm, NULL);
+ vma = i915_vma_instance(obj, vm, NULL);
if (IS_ERR(vma)) {
err = PTR_ERR(vma);
goto out_object_unpin;
@@ -945,7 +996,8 @@ static int igt_mock_ppgtt_64K(void *arg)
if (err)
goto out_vma_unpin;
- if (!offset && vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K) {
+ if (!has_pte64 && !offset &&
+ vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K) {
if (!IS_ALIGNED(vma->node.start,
I915_GTT_PAGE_SIZE_2M)) {
pr_err("node.start(%llx) not aligned to 2M\n",
@@ -964,9 +1016,10 @@ static int igt_mock_ppgtt_64K(void *arg)
}
if (vma->resource->page_sizes_gtt != expected_gtt) {
- pr_err("gtt=%u, expected=%u, i=%d, single=%s\n",
+ pr_err("gtt=%#x, expected=%#x, i=%d, single=%s offset=%#x size=%#x\n",
vma->resource->page_sizes_gtt,
- expected_gtt, i, str_yes_no(!!single));
+ expected_gtt, i, str_yes_no(!!single),
+ offset, size);
err = -EINVAL;
goto out_vma_unpin;
}
@@ -982,7 +1035,7 @@ static int igt_mock_ppgtt_64K(void *arg)
}
}
- return 0;
+ goto out_vm;
out_vma_unpin:
i915_vma_unpin(vma);
@@ -992,7 +1045,10 @@ out_object_unpin:
i915_gem_object_unlock(obj);
out_object_put:
i915_gem_object_put(obj);
-
+out_vm:
+ i915_vm_put(vm);
+out:
+ fput(file);
return err;
}
@@ -1910,8 +1966,6 @@ int i915_gem_huge_page_mock_selftests(void)
SUBTEST(igt_mock_exhaust_device_supported_pages),
SUBTEST(igt_mock_memory_region_huge_pages),
SUBTEST(igt_mock_ppgtt_misaligned_dma),
- SUBTEST(igt_mock_ppgtt_huge_fill),
- SUBTEST(igt_mock_ppgtt_64K),
};
struct drm_i915_private *dev_priv;
struct i915_ppgtt *ppgtt;
@@ -1962,6 +2016,8 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *i915)
SUBTEST(igt_ppgtt_sanity_check),
SUBTEST(igt_ppgtt_compact),
SUBTEST(igt_ppgtt_mixed),
+ SUBTEST(igt_ppgtt_huge_fill),
+ SUBTEST(igt_ppgtt_64K),
};
if (!HAS_PPGTT(i915)) {
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
index 7b516b1a4915..7021b6e9b219 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
@@ -66,7 +66,7 @@ static int live_nop_switch(void *arg)
ctx[n] = live_context(i915, file);
if (IS_ERR(ctx[n])) {
err = PTR_ERR(ctx[n]);
- goto out_file;
+ goto out_ctx;
}
}
@@ -82,7 +82,7 @@ static int live_nop_switch(void *arg)
this = igt_request_alloc(ctx[n], engine);
if (IS_ERR(this)) {
err = PTR_ERR(this);
- goto out_file;
+ goto out_ctx;
}
if (rq) {
i915_request_await_dma_fence(this, &rq->fence);
@@ -93,10 +93,10 @@ static int live_nop_switch(void *arg)
}
if (i915_request_wait(rq, 0, 10 * HZ) < 0) {
pr_err("Failed to populated %d contexts\n", nctx);
- intel_gt_set_wedged(to_gt(i915));
+ intel_gt_set_wedged(engine->gt);
i915_request_put(rq);
err = -EIO;
- goto out_file;
+ goto out_ctx;
}
i915_request_put(rq);
@@ -107,7 +107,7 @@ static int live_nop_switch(void *arg)
err = igt_live_test_begin(&t, i915, __func__, engine->name);
if (err)
- goto out_file;
+ goto out_ctx;
end_time = jiffies + i915_selftest.timeout_jiffies;
for_each_prime_number_from(prime, 2, 8192) {
@@ -120,7 +120,7 @@ static int live_nop_switch(void *arg)
this = igt_request_alloc(ctx[n % nctx], engine);
if (IS_ERR(this)) {
err = PTR_ERR(this);
- goto out_file;
+ goto out_ctx;
}
if (rq) { /* Force submission order */
@@ -149,7 +149,7 @@ static int live_nop_switch(void *arg)
if (i915_request_wait(rq, 0, HZ / 5) < 0) {
pr_err("Switching between %ld contexts timed out\n",
prime);
- intel_gt_set_wedged(to_gt(i915));
+ intel_gt_set_wedged(engine->gt);
i915_request_put(rq);
break;
}
@@ -165,7 +165,7 @@ static int live_nop_switch(void *arg)
err = igt_live_test_end(&t);
if (err)
- goto out_file;
+ goto out_ctx;
pr_info("Switch latencies on %s: 1 = %lluns, %lu = %lluns\n",
engine->name,
@@ -173,6 +173,8 @@ static int live_nop_switch(void *arg)
prime - 1, div64_u64(ktime_to_ns(times[1]), prime - 1));
}
+out_ctx:
+ kfree(ctx);
out_file:
fput(file);
return err;
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
index fe6c37fd7859..a93a90b15907 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c
@@ -219,7 +219,7 @@ static int __igt_lmem_pages_migrate(struct intel_gt *gt,
continue;
err = intel_migrate_clear(&gt->migrate, &ww, deps,
- obj->mm.pages->sgl, obj->cache_level,
+ obj->mm.pages->sgl, obj->pat_index,
i915_gem_object_is_lmem(obj),
0xdeadbeaf, &rq);
if (rq) {
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
index 01e271b6ad21..72957a36a36b 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
@@ -1222,7 +1222,7 @@ static int __igt_mmap_migrate(struct intel_memory_region **placements,
}
err = intel_context_migrate_clear(to_gt(i915)->migrate.context, NULL,
- obj->mm.pages->sgl, obj->cache_level,
+ obj->mm.pages->sgl, obj->pat_index,
i915_gem_object_is_lmem(obj),
expand32(POISON_INUSE), &rq);
i915_gem_object_unpin_pages(obj);
diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c
index 5aaacc53fa4c..c2bdc133c89a 100644
--- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c
+++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c
@@ -109,7 +109,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags)
{
struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
@@ -117,7 +117,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
unsigned int first_entry = vma_res->start / I915_GTT_PAGE_SIZE;
unsigned int act_pt = first_entry / GEN6_PTES;
unsigned int act_pte = first_entry % GEN6_PTES;
- const u32 pte_encode = vm->pte_encode(0, cache_level, flags);
+ const u32 pte_encode = vm->pte_encode(0, pat_index, flags);
struct sgt_dma iter = sgt_dma(vma_res);
gen6_pte_t *vaddr;
@@ -227,7 +227,9 @@ static int gen6_ppgtt_init_scratch(struct gen6_ppgtt *ppgtt)
vm->scratch[0]->encode =
vm->pte_encode(px_dma(vm->scratch[0]),
- I915_CACHE_NONE, PTE_READ_ONLY);
+ i915_gem_get_pat_index(vm->i915,
+ I915_CACHE_NONE),
+ PTE_READ_ONLY);
vm->scratch[1] = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K);
if (IS_ERR(vm->scratch[1])) {
@@ -278,7 +280,7 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
static void pd_vma_bind(struct i915_address_space *vm,
struct i915_vm_pt_stash *stash,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 unused)
{
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
index e1c76e5bfa82..23857cc08eca 100644
--- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
@@ -177,14 +177,40 @@ u32 *gen12_emit_aux_table_inv(struct intel_gt *gt, u32 *cs, const i915_reg_t inv
return cs;
}
+static int mtl_dummy_pipe_control(struct i915_request *rq)
+{
+ /* Wa_14016712196 */
+ if (IS_MTL_GRAPHICS_STEP(rq->engine->i915, M, STEP_A0, STEP_B0) ||
+ IS_MTL_GRAPHICS_STEP(rq->engine->i915, P, STEP_A0, STEP_B0)) {
+ u32 *cs;
+
+ /* dummy PIPE_CONTROL + depth flush */
+ cs = intel_ring_begin(rq, 6);
+ if (IS_ERR(cs))
+ return PTR_ERR(cs);
+ cs = gen12_emit_pipe_control(cs,
+ 0,
+ PIPE_CONTROL_DEPTH_CACHE_FLUSH,
+ LRC_PPHWSP_SCRATCH_ADDR);
+ intel_ring_advance(rq, cs);
+ }
+
+ return 0;
+}
+
int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
{
struct intel_engine_cs *engine = rq->engine;
if (mode & EMIT_FLUSH) {
u32 flags = 0;
+ int err;
u32 *cs;
+ err = mtl_dummy_pipe_control(rq);
+ if (err)
+ return err;
+
flags |= PIPE_CONTROL_TILE_CACHE_FLUSH;
flags |= PIPE_CONTROL_FLUSH_L3;
flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
@@ -217,6 +243,11 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
if (mode & EMIT_INVALIDATE) {
u32 flags = 0;
u32 *cs, count;
+ int err;
+
+ err = mtl_dummy_pipe_control(rq);
+ if (err)
+ return err;
flags |= PIPE_CONTROL_COMMAND_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_TLB_INVALIDATE;
@@ -733,6 +764,13 @@ u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs)
PIPE_CONTROL_DC_FLUSH_ENABLE |
PIPE_CONTROL_FLUSH_ENABLE);
+ /* Wa_14016712196 */
+ if (IS_MTL_GRAPHICS_STEP(i915, M, STEP_A0, STEP_B0) ||
+ IS_MTL_GRAPHICS_STEP(i915, P, STEP_A0, STEP_B0))
+ /* dummy PIPE_CONTROL + depth flush */
+ cs = gen12_emit_pipe_control(cs, 0,
+ PIPE_CONTROL_DEPTH_CACHE_FLUSH, 0);
+
if (GRAPHICS_VER(i915) == 12 && GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
/* Wa_1409600907 */
flags |= PIPE_CONTROL_DEPTH_STALL;
diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
index 4daaa6f55668..f948d33e5ec5 100644
--- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
+++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
@@ -29,7 +29,7 @@ static u64 gen8_pde_encode(const dma_addr_t addr,
}
static u64 gen8_pte_encode(dma_addr_t addr,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
gen8_pte_t pte = addr | GEN8_PAGE_PRESENT | GEN8_PAGE_RW;
@@ -40,7 +40,12 @@ static u64 gen8_pte_encode(dma_addr_t addr,
if (flags & PTE_LM)
pte |= GEN12_PPGTT_PTE_LM;
- switch (level) {
+ /*
+ * For pre-gen12 platforms pat_index is the same as enum
+ * i915_cache_level, so the switch-case here is still valid.
+ * See translation table defined by LEGACY_CACHELEVEL.
+ */
+ switch (pat_index) {
case I915_CACHE_NONE:
pte |= PPAT_UNCACHED;
break;
@@ -55,6 +60,33 @@ static u64 gen8_pte_encode(dma_addr_t addr,
return pte;
}
+static u64 gen12_pte_encode(dma_addr_t addr,
+ unsigned int pat_index,
+ u32 flags)
+{
+ gen8_pte_t pte = addr | GEN8_PAGE_PRESENT | GEN8_PAGE_RW;
+
+ if (unlikely(flags & PTE_READ_ONLY))
+ pte &= ~GEN8_PAGE_RW;
+
+ if (flags & PTE_LM)
+ pte |= GEN12_PPGTT_PTE_LM;
+
+ if (pat_index & BIT(0))
+ pte |= GEN12_PPGTT_PTE_PAT0;
+
+ if (pat_index & BIT(1))
+ pte |= GEN12_PPGTT_PTE_PAT1;
+
+ if (pat_index & BIT(2))
+ pte |= GEN12_PPGTT_PTE_PAT2;
+
+ if (pat_index & BIT(3))
+ pte |= MTL_PPGTT_PTE_PAT3;
+
+ return pte;
+}
+
static void gen8_ppgtt_notify_vgt(struct i915_ppgtt *ppgtt, bool create)
{
struct drm_i915_private *i915 = ppgtt->vm.i915;
@@ -423,11 +455,11 @@ gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt,
struct i915_page_directory *pdp,
struct sgt_dma *iter,
u64 idx,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags)
{
struct i915_page_directory *pd;
- const gen8_pte_t pte_encode = gen8_pte_encode(0, cache_level, flags);
+ const gen8_pte_t pte_encode = ppgtt->vm.pte_encode(0, pat_index, flags);
gen8_pte_t *vaddr;
pd = i915_pd_entry(pdp, gen8_pd_index(idx, 2));
@@ -470,10 +502,10 @@ static void
xehpsdv_ppgtt_insert_huge(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
struct sgt_dma *iter,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags)
{
- const gen8_pte_t pte_encode = vm->pte_encode(0, cache_level, flags);
+ const gen8_pte_t pte_encode = vm->pte_encode(0, pat_index, flags);
unsigned int rem = sg_dma_len(iter->sg);
u64 start = vma_res->start;
u64 end = start + vma_res->vma_size;
@@ -570,6 +602,7 @@ xehpsdv_ppgtt_insert_huge(struct i915_address_space *vm,
}
} while (rem >= page_size && index < max);
+ drm_clflush_virt_range(vaddr, PAGE_SIZE);
vma_res->page_sizes_gtt |= page_size;
} while (iter->sg && sg_dma_len(iter->sg));
}
@@ -577,10 +610,10 @@ xehpsdv_ppgtt_insert_huge(struct i915_address_space *vm,
static void gen8_ppgtt_insert_huge(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
struct sgt_dma *iter,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags)
{
- const gen8_pte_t pte_encode = gen8_pte_encode(0, cache_level, flags);
+ const gen8_pte_t pte_encode = vm->pte_encode(0, pat_index, flags);
unsigned int rem = sg_dma_len(iter->sg);
u64 start = vma_res->start;
@@ -700,17 +733,17 @@ static void gen8_ppgtt_insert_huge(struct i915_address_space *vm,
static void gen8_ppgtt_insert(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags)
{
struct i915_ppgtt * const ppgtt = i915_vm_to_ppgtt(vm);
struct sgt_dma iter = sgt_dma(vma_res);
if (vma_res->bi.page_sizes.sg > I915_GTT_PAGE_SIZE) {
- if (HAS_64K_PAGES(vm->i915))
- xehpsdv_ppgtt_insert_huge(vm, vma_res, &iter, cache_level, flags);
+ if (GRAPHICS_VER_FULL(vm->i915) >= IP_VER(12, 50))
+ xehpsdv_ppgtt_insert_huge(vm, vma_res, &iter, pat_index, flags);
else
- gen8_ppgtt_insert_huge(vm, vma_res, &iter, cache_level, flags);
+ gen8_ppgtt_insert_huge(vm, vma_res, &iter, pat_index, flags);
} else {
u64 idx = vma_res->start >> GEN8_PTE_SHIFT;
@@ -719,7 +752,7 @@ static void gen8_ppgtt_insert(struct i915_address_space *vm,
gen8_pdp_for_page_index(vm, idx);
idx = gen8_ppgtt_insert_pte(ppgtt, pdp, &iter, idx,
- cache_level, flags);
+ pat_index, flags);
} while (idx);
vma_res->page_sizes_gtt = I915_GTT_PAGE_SIZE;
@@ -729,7 +762,7 @@ static void gen8_ppgtt_insert(struct i915_address_space *vm,
static void gen8_ppgtt_insert_entry(struct i915_address_space *vm,
dma_addr_t addr,
u64 offset,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
u64 idx = offset >> GEN8_PTE_SHIFT;
@@ -743,14 +776,14 @@ static void gen8_ppgtt_insert_entry(struct i915_address_space *vm,
GEM_BUG_ON(pt->is_compact);
vaddr = px_vaddr(pt);
- vaddr[gen8_pd_index(idx, 0)] = gen8_pte_encode(addr, level, flags);
+ vaddr[gen8_pd_index(idx, 0)] = vm->pte_encode(addr, pat_index, flags);
drm_clflush_virt_range(&vaddr[gen8_pd_index(idx, 0)], sizeof(*vaddr));
}
static void __xehpsdv_ppgtt_insert_entry_lm(struct i915_address_space *vm,
dma_addr_t addr,
u64 offset,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
u64 idx = offset >> GEN8_PTE_SHIFT;
@@ -773,20 +806,20 @@ static void __xehpsdv_ppgtt_insert_entry_lm(struct i915_address_space *vm,
}
vaddr = px_vaddr(pt);
- vaddr[gen8_pd_index(idx, 0) / 16] = gen8_pte_encode(addr, level, flags);
+ vaddr[gen8_pd_index(idx, 0) / 16] = vm->pte_encode(addr, pat_index, flags);
}
static void xehpsdv_ppgtt_insert_entry(struct i915_address_space *vm,
dma_addr_t addr,
u64 offset,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
if (flags & PTE_LM)
return __xehpsdv_ppgtt_insert_entry_lm(vm, addr, offset,
- level, flags);
+ pat_index, flags);
- return gen8_ppgtt_insert_entry(vm, addr, offset, level, flags);
+ return gen8_ppgtt_insert_entry(vm, addr, offset, pat_index, flags);
}
static int gen8_init_scratch(struct i915_address_space *vm)
@@ -820,8 +853,10 @@ static int gen8_init_scratch(struct i915_address_space *vm)
pte_flags |= PTE_LM;
vm->scratch[0]->encode =
- gen8_pte_encode(px_dma(vm->scratch[0]),
- I915_CACHE_NONE, pte_flags);
+ vm->pte_encode(px_dma(vm->scratch[0]),
+ i915_gem_get_pat_index(vm->i915,
+ I915_CACHE_NONE),
+ pte_flags);
for (i = 1; i <= vm->top; i++) {
struct drm_i915_gem_object *obj;
@@ -963,7 +998,10 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt,
*/
ppgtt->vm.alloc_scratch_dma = alloc_pt_dma;
- ppgtt->vm.pte_encode = gen8_pte_encode;
+ if (GRAPHICS_VER(gt->i915) >= 12)
+ ppgtt->vm.pte_encode = gen12_pte_encode;
+ else
+ ppgtt->vm.pte_encode = gen8_pte_encode;
ppgtt->vm.bind_async_flags = I915_VMA_LOCAL_BIND;
ppgtt->vm.insert_entries = gen8_ppgtt_insert;
diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.h b/drivers/gpu/drm/i915/gt/gen8_ppgtt.h
index f541d19264b4..19c635441642 100644
--- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.h
+++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.h
@@ -10,13 +10,12 @@
struct i915_address_space;
struct intel_gt;
-enum i915_cache_level;
struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt,
unsigned long lmem_pt_obj_flags);
u64 gen8_ggtt_pte_encode(dma_addr_t addr,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags);
#endif
diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c
index 2aa63ec521b8..a53b26178f0a 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.c
+++ b/drivers/gpu/drm/i915/gt/intel_context.c
@@ -578,10 +578,13 @@ void intel_context_bind_parent_child(struct intel_context *parent,
child->parallel.parent = parent;
}
-u64 intel_context_get_total_runtime_ns(const struct intel_context *ce)
+u64 intel_context_get_total_runtime_ns(struct intel_context *ce)
{
u64 total, active;
+ if (ce->ops->update_stats)
+ ce->ops->update_stats(ce);
+
total = ce->stats.runtime.total;
if (ce->ops->flags & COPS_RUNTIME_CYCLES)
total *= ce->engine->gt->clock_period_ns;
diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h
index 48f888c3da08..a80e3b7c24ff 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.h
+++ b/drivers/gpu/drm/i915/gt/intel_context.h
@@ -97,7 +97,7 @@ void intel_context_bind_parent_child(struct intel_context *parent,
/**
* intel_context_lock_pinned - Stablises the 'pinned' status of the HW context
- * @ce - the context
+ * @ce: the context
*
* Acquire a lock on the pinned status of the HW context, such that the context
* can neither be bound to the GPU or unbound whilst the lock is held, i.e.
@@ -111,7 +111,7 @@ static inline int intel_context_lock_pinned(struct intel_context *ce)
/**
* intel_context_is_pinned - Reports the 'pinned' status
- * @ce - the context
+ * @ce: the context
*
* While in use by the GPU, the context, along with its ring and page
* tables is pinned into memory and the GTT.
@@ -133,7 +133,7 @@ static inline void intel_context_cancel_request(struct intel_context *ce,
/**
* intel_context_unlock_pinned - Releases the earlier locking of 'pinned' status
- * @ce - the context
+ * @ce: the context
*
* Releases the lock earlier acquired by intel_context_unlock_pinned().
*/
@@ -375,7 +375,7 @@ intel_context_clear_nopreempt(struct intel_context *ce)
clear_bit(CONTEXT_NOPREEMPT, &ce->flags);
}
-u64 intel_context_get_total_runtime_ns(const struct intel_context *ce);
+u64 intel_context_get_total_runtime_ns(struct intel_context *ce);
u64 intel_context_get_avg_runtime_ns(struct intel_context *ce);
static inline u64 intel_context_clock(void)
diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h
index e36670f2e626..aceaac28a33e 100644
--- a/drivers/gpu/drm/i915/gt/intel_context_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_context_types.h
@@ -58,6 +58,8 @@ struct intel_context_ops {
void (*sched_disable)(struct intel_context *ce);
+ void (*update_stats)(struct intel_context *ce);
+
void (*reset)(struct intel_context *ce);
void (*destroy)(struct kref *kref);
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index 5c6c9a6d469c..0aff5bb13c53 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -1515,7 +1515,7 @@ int intel_engines_init(struct intel_gt *gt)
}
/**
- * intel_engines_cleanup_common - cleans up the engine state created by
+ * intel_engine_cleanup_common - cleans up the engine state created by
* the common initiailizers.
* @engine: Engine to cleanup.
*
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c
index ee531a5c142c..21af0ec52223 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c
@@ -296,9 +296,7 @@ static const struct intel_wakeref_ops wf_ops = {
void intel_engine_init__pm(struct intel_engine_cs *engine)
{
- struct intel_runtime_pm *rpm = engine->uncore->rpm;
-
- intel_wakeref_init(&engine->wakeref, rpm, &wf_ops);
+ intel_wakeref_init(&engine->wakeref, engine->i915, &wf_ops);
intel_engine_init_heartbeat(engine);
intel_gsc_idle_msg_enable(engine);
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index 960291f88fd6..e99a6fa03d45 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -289,6 +289,7 @@ struct intel_engine_execlists {
*/
u8 csb_head;
+ /* private: selftest */
I915_SELFTEST_DECLARE(struct st_preempt_hang preempt_hang;)
};
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c
index cd4f1b126f75..dcedff41a825 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_user.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c
@@ -117,7 +117,7 @@ static void set_scheduler_caps(struct drm_i915_private *i915)
disabled |= (I915_SCHEDULER_CAP_ENABLED |
I915_SCHEDULER_CAP_PRIORITY);
- if (intel_uc_uses_guc_submission(&to_gt(i915)->uc))
+ if (intel_uc_uses_guc_submission(&engine->gt->uc))
enabled |= I915_SCHEDULER_CAP_STATIC_PRIORITY_MAP;
for (i = 0; i < ARRAY_SIZE(map); i++) {
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index 750326434677..2ebd937f3b4c 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -2327,6 +2327,7 @@ static u32 active_ccid(struct intel_engine_cs *engine)
static void execlists_capture(struct intel_engine_cs *engine)
{
+ struct drm_i915_private *i915 = engine->i915;
struct execlists_capture *cap;
if (!IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR))
@@ -2375,7 +2376,7 @@ static void execlists_capture(struct intel_engine_cs *engine)
goto err_rq;
INIT_WORK(&cap->work, execlists_capture_work);
- schedule_work(&cap->work);
+ queue_work(i915->unordered_wq, &cap->work);
return;
err_rq:
@@ -3680,7 +3681,7 @@ static void virtual_context_destroy(struct kref *kref)
* lock, we can delegate the free of the engine to an RCU worker.
*/
INIT_RCU_WORK(&ve->rcu, rcu_virtual_context_destroy);
- queue_rcu_work(system_wq, &ve->rcu);
+ queue_rcu_work(ve->context.engine->i915->unordered_wq, &ve->rcu);
}
static void virtual_engine_initial_hint(struct virtual_engine *ve)
diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c
index 3c7f1ed92f5b..dd0ed941441a 100644
--- a/drivers/gpu/drm/i915/gt/intel_ggtt.c
+++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c
@@ -220,8 +220,28 @@ static void guc_ggtt_invalidate(struct i915_ggtt *ggtt)
}
}
+static u64 mtl_ggtt_pte_encode(dma_addr_t addr,
+ unsigned int pat_index,
+ u32 flags)
+{
+ gen8_pte_t pte = addr | GEN8_PAGE_PRESENT;
+
+ WARN_ON_ONCE(addr & ~GEN12_GGTT_PTE_ADDR_MASK);
+
+ if (flags & PTE_LM)
+ pte |= GEN12_GGTT_PTE_LM;
+
+ if (pat_index & BIT(0))
+ pte |= MTL_GGTT_PTE_PAT0;
+
+ if (pat_index & BIT(1))
+ pte |= MTL_GGTT_PTE_PAT1;
+
+ return pte;
+}
+
u64 gen8_ggtt_pte_encode(dma_addr_t addr,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
gen8_pte_t pte = addr | GEN8_PAGE_PRESENT;
@@ -240,25 +260,25 @@ static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
static void gen8_ggtt_insert_page(struct i915_address_space *vm,
dma_addr_t addr,
u64 offset,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
gen8_pte_t __iomem *pte =
(gen8_pte_t __iomem *)ggtt->gsm + offset / I915_GTT_PAGE_SIZE;
- gen8_set_pte(pte, gen8_ggtt_pte_encode(addr, level, flags));
+ gen8_set_pte(pte, ggtt->vm.pte_encode(addr, pat_index, flags));
ggtt->invalidate(ggtt);
}
static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
- const gen8_pte_t pte_encode = gen8_ggtt_pte_encode(0, level, flags);
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
+ const gen8_pte_t pte_encode = ggtt->vm.pte_encode(0, pat_index, flags);
gen8_pte_t __iomem *gte;
gen8_pte_t __iomem *end;
struct sgt_iter iter;
@@ -315,14 +335,14 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
static void gen6_ggtt_insert_page(struct i915_address_space *vm,
dma_addr_t addr,
u64 offset,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
gen6_pte_t __iomem *pte =
(gen6_pte_t __iomem *)ggtt->gsm + offset / I915_GTT_PAGE_SIZE;
- iowrite32(vm->pte_encode(addr, level, flags), pte);
+ iowrite32(vm->pte_encode(addr, pat_index, flags), pte);
ggtt->invalidate(ggtt);
}
@@ -335,7 +355,7 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm,
*/
static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
@@ -352,7 +372,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
iowrite32(vm->scratch[0]->encode, gte++);
end += (vma_res->node_size + vma_res->guard) / I915_GTT_PAGE_SIZE;
for_each_sgt_daddr(addr, iter, vma_res->bi.pages)
- iowrite32(vm->pte_encode(addr, level, flags), gte++);
+ iowrite32(vm->pte_encode(addr, pat_index, flags), gte++);
GEM_BUG_ON(gte > end);
/* Fill the allocated but "unused" space beyond the end of the buffer */
@@ -387,14 +407,15 @@ struct insert_page {
struct i915_address_space *vm;
dma_addr_t addr;
u64 offset;
- enum i915_cache_level level;
+ unsigned int pat_index;
};
static int bxt_vtd_ggtt_insert_page__cb(void *_arg)
{
struct insert_page *arg = _arg;
- gen8_ggtt_insert_page(arg->vm, arg->addr, arg->offset, arg->level, 0);
+ gen8_ggtt_insert_page(arg->vm, arg->addr, arg->offset,
+ arg->pat_index, 0);
bxt_vtd_ggtt_wa(arg->vm);
return 0;
@@ -403,10 +424,10 @@ static int bxt_vtd_ggtt_insert_page__cb(void *_arg)
static void bxt_vtd_ggtt_insert_page__BKL(struct i915_address_space *vm,
dma_addr_t addr,
u64 offset,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 unused)
{
- struct insert_page arg = { vm, addr, offset, level };
+ struct insert_page arg = { vm, addr, offset, pat_index };
stop_machine(bxt_vtd_ggtt_insert_page__cb, &arg, NULL);
}
@@ -414,7 +435,7 @@ static void bxt_vtd_ggtt_insert_page__BKL(struct i915_address_space *vm,
struct insert_entries {
struct i915_address_space *vm;
struct i915_vma_resource *vma_res;
- enum i915_cache_level level;
+ unsigned int pat_index;
u32 flags;
};
@@ -422,7 +443,8 @@ static int bxt_vtd_ggtt_insert_entries__cb(void *_arg)
{
struct insert_entries *arg = _arg;
- gen8_ggtt_insert_entries(arg->vm, arg->vma_res, arg->level, arg->flags);
+ gen8_ggtt_insert_entries(arg->vm, arg->vma_res,
+ arg->pat_index, arg->flags);
bxt_vtd_ggtt_wa(arg->vm);
return 0;
@@ -430,10 +452,10 @@ static int bxt_vtd_ggtt_insert_entries__cb(void *_arg)
static void bxt_vtd_ggtt_insert_entries__BKL(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
- struct insert_entries arg = { vm, vma_res, level, flags };
+ struct insert_entries arg = { vm, vma_res, pat_index, flags };
stop_machine(bxt_vtd_ggtt_insert_entries__cb, &arg, NULL);
}
@@ -462,7 +484,7 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
void intel_ggtt_bind_vma(struct i915_address_space *vm,
struct i915_vm_pt_stash *stash,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags)
{
u32 pte_flags;
@@ -479,7 +501,7 @@ void intel_ggtt_bind_vma(struct i915_address_space *vm,
if (vma_res->bi.lmem)
pte_flags |= PTE_LM;
- vm->insert_entries(vm, vma_res, cache_level, pte_flags);
+ vm->insert_entries(vm, vma_res, pat_index, pte_flags);
vma_res->page_sizes_gtt = I915_GTT_PAGE_SIZE;
}
@@ -628,7 +650,7 @@ err:
static void aliasing_gtt_bind_vma(struct i915_address_space *vm,
struct i915_vm_pt_stash *stash,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags)
{
u32 pte_flags;
@@ -640,10 +662,10 @@ static void aliasing_gtt_bind_vma(struct i915_address_space *vm,
if (flags & I915_VMA_LOCAL_BIND)
ppgtt_bind_vma(&i915_vm_to_ggtt(vm)->alias->vm,
- stash, vma_res, cache_level, flags);
+ stash, vma_res, pat_index, flags);
if (flags & I915_VMA_GLOBAL_BIND)
- vm->insert_entries(vm, vma_res, cache_level, pte_flags);
+ vm->insert_entries(vm, vma_res, pat_index, pte_flags);
vma_res->bound_flags |= flags;
}
@@ -900,7 +922,9 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
ggtt->vm.scratch[0]->encode =
ggtt->vm.pte_encode(px_dma(ggtt->vm.scratch[0]),
- I915_CACHE_NONE, pte_flags);
+ i915_gem_get_pat_index(i915,
+ I915_CACHE_NONE),
+ pte_flags);
return 0;
}
@@ -981,18 +1005,26 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
ggtt->vm.vma_ops.bind_vma = intel_ggtt_bind_vma;
ggtt->vm.vma_ops.unbind_vma = intel_ggtt_unbind_vma;
- ggtt->vm.pte_encode = gen8_ggtt_pte_encode;
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))
+ ggtt->vm.pte_encode = mtl_ggtt_pte_encode;
+ else
+ ggtt->vm.pte_encode = gen8_ggtt_pte_encode;
return ggtt_probe_common(ggtt, size);
}
+/*
+ * For pre-gen8 platforms pat_index is the same as enum i915_cache_level,
+ * so the switch-case statements in these PTE encode functions are still valid.
+ * See translation table LEGACY_CACHELEVEL.
+ */
static u64 snb_pte_encode(dma_addr_t addr,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
gen6_pte_t pte = GEN6_PTE_ADDR_ENCODE(addr) | GEN6_PTE_VALID;
- switch (level) {
+ switch (pat_index) {
case I915_CACHE_L3_LLC:
case I915_CACHE_LLC:
pte |= GEN6_PTE_CACHE_LLC;
@@ -1001,19 +1033,19 @@ static u64 snb_pte_encode(dma_addr_t addr,
pte |= GEN6_PTE_UNCACHED;
break;
default:
- MISSING_CASE(level);
+ MISSING_CASE(pat_index);
}
return pte;
}
static u64 ivb_pte_encode(dma_addr_t addr,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
gen6_pte_t pte = GEN6_PTE_ADDR_ENCODE(addr) | GEN6_PTE_VALID;
- switch (level) {
+ switch (pat_index) {
case I915_CACHE_L3_LLC:
pte |= GEN7_PTE_CACHE_L3_LLC;
break;
@@ -1024,14 +1056,14 @@ static u64 ivb_pte_encode(dma_addr_t addr,
pte |= GEN6_PTE_UNCACHED;
break;
default:
- MISSING_CASE(level);
+ MISSING_CASE(pat_index);
}
return pte;
}
static u64 byt_pte_encode(dma_addr_t addr,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
gen6_pte_t pte = GEN6_PTE_ADDR_ENCODE(addr) | GEN6_PTE_VALID;
@@ -1039,31 +1071,31 @@ static u64 byt_pte_encode(dma_addr_t addr,
if (!(flags & PTE_READ_ONLY))
pte |= BYT_PTE_WRITEABLE;
- if (level != I915_CACHE_NONE)
+ if (pat_index != I915_CACHE_NONE)
pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES;
return pte;
}
static u64 hsw_pte_encode(dma_addr_t addr,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
gen6_pte_t pte = HSW_PTE_ADDR_ENCODE(addr) | GEN6_PTE_VALID;
- if (level != I915_CACHE_NONE)
+ if (pat_index != I915_CACHE_NONE)
pte |= HSW_WB_LLC_AGE3;
return pte;
}
static u64 iris_pte_encode(dma_addr_t addr,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
gen6_pte_t pte = HSW_PTE_ADDR_ENCODE(addr) | GEN6_PTE_VALID;
- switch (level) {
+ switch (pat_index) {
case I915_CACHE_NONE:
break;
case I915_CACHE_WT:
@@ -1266,7 +1298,9 @@ bool i915_ggtt_resume_vm(struct i915_address_space *vm)
*/
vma->resource->bound_flags = 0;
vma->ops->bind_vma(vm, NULL, vma->resource,
- obj ? obj->cache_level : 0,
+ obj ? obj->pat_index :
+ i915_gem_get_pat_index(vm->i915,
+ I915_CACHE_NONE),
was_bound);
if (obj) { /* only used during resume => exclusive access */
@@ -1292,6 +1326,9 @@ void i915_ggtt_resume(struct i915_ggtt *ggtt)
ggtt->vm.scratch_range(&ggtt->vm, ggtt->error_capture.start,
ggtt->error_capture.size);
+ list_for_each_entry(gt, &ggtt->gt_list, ggtt_link)
+ intel_uc_resume_mappings(&gt->uc);
+
ggtt->invalidate(ggtt);
if (flush)
diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c
index d6a74ae2527b..866c416afb73 100644
--- a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c
+++ b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c
@@ -18,10 +18,10 @@
static void gmch_ggtt_insert_page(struct i915_address_space *vm,
dma_addr_t addr,
u64 offset,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 unused)
{
- unsigned int flags = (cache_level == I915_CACHE_NONE) ?
+ unsigned int flags = (pat_index == I915_CACHE_NONE) ?
AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
intel_gmch_gtt_insert_page(addr, offset >> PAGE_SHIFT, flags);
@@ -29,10 +29,10 @@ static void gmch_ggtt_insert_page(struct i915_address_space *vm,
static void gmch_ggtt_insert_entries(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 unused)
{
- unsigned int flags = (cache_level == I915_CACHE_NONE) ?
+ unsigned int flags = (pat_index == I915_CACHE_NONE) ?
AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
intel_gmch_gtt_insert_sg_entries(vma_res->bi.pages, vma_res->start >> PAGE_SHIFT,
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c
index cadfd85785b1..86b5a9ba323d 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c
@@ -88,10 +88,11 @@ static void pool_free_work(struct work_struct *wrk)
{
struct intel_gt_buffer_pool *pool =
container_of(wrk, typeof(*pool), work.work);
+ struct intel_gt *gt = container_of(pool, struct intel_gt, buffer_pool);
if (pool_free_older_than(pool, HZ))
- schedule_delayed_work(&pool->work,
- round_jiffies_up_relative(HZ));
+ queue_delayed_work(gt->i915->unordered_wq, &pool->work,
+ round_jiffies_up_relative(HZ));
}
static void pool_retire(struct i915_active *ref)
@@ -99,6 +100,7 @@ static void pool_retire(struct i915_active *ref)
struct intel_gt_buffer_pool_node *node =
container_of(ref, typeof(*node), active);
struct intel_gt_buffer_pool *pool = node->pool;
+ struct intel_gt *gt = container_of(pool, struct intel_gt, buffer_pool);
struct list_head *list = bucket_for_size(pool, node->obj->base.size);
unsigned long flags;
@@ -116,8 +118,8 @@ static void pool_retire(struct i915_active *ref)
WRITE_ONCE(node->age, jiffies ?: 1); /* 0 reserved for active nodes */
spin_unlock_irqrestore(&pool->lock, flags);
- schedule_delayed_work(&pool->work,
- round_jiffies_up_relative(HZ));
+ queue_delayed_work(gt->i915->unordered_wq, &pool->work,
+ round_jiffies_up_relative(HZ));
}
void intel_gt_buffer_pool_mark_used(struct intel_gt_buffer_pool_node *node)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
index 1b25a6039152..62fd00c9e519 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
@@ -7,6 +7,7 @@
#include "i915_drv.h"
#include "i915_irq.h"
+#include "i915_reg.h"
#include "intel_breadcrumbs.h"
#include "intel_gt.h"
#include "intel_gt_irq.h"
@@ -15,6 +16,7 @@
#include "intel_uncore.h"
#include "intel_rps.h"
#include "pxp/intel_pxp_irq.h"
+#include "uc/intel_gsc_proxy.h"
static void guc_irq_handler(struct intel_guc *guc, u16 iir)
{
@@ -81,6 +83,9 @@ gen11_other_irq_handler(struct intel_gt *gt, const u8 instance,
if (instance == OTHER_GSC_INSTANCE)
return intel_gsc_irq_handler(gt, iir);
+ if (instance == OTHER_GSC_HECI_2_INSTANCE)
+ return intel_gsc_proxy_irq_handler(&gt->uc.gsc, iir);
+
WARN_ONCE(1, "unhandled other interrupt instance=0x%x, iir=0x%x\n",
instance, iir);
}
@@ -100,7 +105,10 @@ static struct intel_gt *pick_gt(struct intel_gt *gt, u8 class, u8 instance)
case VIDEO_ENHANCEMENT_CLASS:
return media_gt;
case OTHER_CLASS:
- if (instance == OTHER_GSC_INSTANCE && HAS_ENGINE(media_gt, GSC0))
+ if (instance == OTHER_GSC_HECI_2_INSTANCE)
+ return media_gt;
+ if ((instance == OTHER_GSC_INSTANCE || instance == OTHER_KCR_INSTANCE) &&
+ HAS_ENGINE(media_gt, GSC0))
return media_gt;
fallthrough;
default:
@@ -256,6 +264,7 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
u32 irqs = GT_RENDER_USER_INTERRUPT;
u32 guc_mask = intel_uc_wants_guc(&gt->uc) ? GUC_INTR_GUC2HOST : 0;
u32 gsc_mask = 0;
+ u32 heci_mask = 0;
u32 dmask;
u32 smask;
@@ -267,10 +276,16 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
dmask = irqs << 16 | irqs;
smask = irqs << 16;
- if (HAS_ENGINE(gt, GSC0))
+ if (HAS_ENGINE(gt, GSC0)) {
+ /*
+ * the heci2 interrupt is enabled via the same register as the
+ * GSC interrupt, but it has its own mask register.
+ */
gsc_mask = irqs;
- else if (HAS_HECI_GSC(gt->i915))
+ heci_mask = GSC_IRQ_INTF(1); /* HECI2 IRQ for SW Proxy*/
+ } else if (HAS_HECI_GSC(gt->i915)) {
gsc_mask = GSC_IRQ_INTF(0) | GSC_IRQ_INTF(1);
+ }
BUILD_BUG_ON(irqs & 0xffff0000);
@@ -280,7 +295,7 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
if (CCS_MASK(gt))
intel_uncore_write(uncore, GEN12_CCS_RSVD_INTR_ENABLE, smask);
if (gsc_mask)
- intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_ENABLE, gsc_mask);
+ intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_ENABLE, gsc_mask | heci_mask);
/* Unmask irqs on RCS, BCS, VCS and VECS engines. */
intel_uncore_write(uncore, GEN11_RCS0_RSVD_INTR_MASK, ~smask);
@@ -308,6 +323,9 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
intel_uncore_write(uncore, GEN12_CCS2_CCS3_INTR_MASK, ~dmask);
if (gsc_mask)
intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_MASK, ~gsc_mask);
+ if (heci_mask)
+ intel_uncore_write(uncore, GEN12_HECI2_RSVD_INTR_MASK,
+ ~REG_FIELD_PREP(ENGINE1_MASK, heci_mask));
if (guc_mask) {
/* the enable bit is common for both GTs but the masks are separate */
@@ -358,7 +376,7 @@ static void gen7_parity_error_irq_handler(struct intel_gt *gt, u32 iir)
if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT)
gt->i915->l3_parity.which_slice |= 1 << 0;
- schedule_work(&gt->i915->l3_parity.error_work);
+ queue_work(gt->i915->unordered_wq, &gt->i915->l3_parity.error_work);
}
void gen6_gt_irq_handler(struct intel_gt *gt, u32 gt_iir)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
index e02cb90723ae..5a942af0a14e 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
@@ -87,7 +87,7 @@ static int __gt_unpark(struct intel_wakeref *wf)
intel_rc6_unpark(&gt->rc6);
intel_rps_unpark(&gt->rps);
- i915_pmu_gt_unparked(i915);
+ i915_pmu_gt_unparked(gt);
intel_guc_busyness_unpark(gt);
intel_gt_unpark_requests(gt);
@@ -109,7 +109,7 @@ static int __gt_park(struct intel_wakeref *wf)
intel_guc_busyness_park(gt);
i915_vma_parked(gt);
- i915_pmu_gt_parked(i915);
+ i915_pmu_gt_parked(gt);
intel_rps_park(&gt->rps);
intel_rc6_park(&gt->rc6);
@@ -137,7 +137,7 @@ void intel_gt_pm_init_early(struct intel_gt *gt)
* runtime_pm is per-device rather than per-tile, so this is still the
* correct structure.
*/
- intel_wakeref_init(&gt->wakeref, &gt->i915->runtime_pm, &wf_ops);
+ intel_wakeref_init(&gt->wakeref, gt->i915, &wf_ops);
seqcount_mutex_init(&gt->stats.lock, &gt->wakeref.mutex);
}
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c
index 80dbbef86b1d..357e2f865727 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c
@@ -539,7 +539,10 @@ static bool rps_eval(void *data)
{
struct intel_gt *gt = data;
- return HAS_RPS(gt->i915);
+ if (intel_guc_slpc_is_used(&gt->uc.guc))
+ return false;
+ else
+ return HAS_RPS(gt->i915);
}
DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(rps_boost);
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
index fd1f9cd35e9d..718cb2c80f79 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
@@ -7,7 +7,8 @@
#define __INTEL_GT_REGS__
#include "i915_reg_defs.h"
-#include "display/intel_display_reg_defs.h" /* VLV_DISPLAY_BASE */
+
+#define VLV_GUNIT_BASE 0x180000
/*
* The perf control registers are technically multicast registers, but the
@@ -356,7 +357,11 @@
#define GEN7_TLB_RD_ADDR _MMIO(0x4700)
#define GEN12_PAT_INDEX(index) _MMIO(0x4800 + (index) * 4)
-#define XEHP_PAT_INDEX(index) MCR_REG(0x4800 + (index) * 4)
+#define _PAT_INDEX(index) _PICK_EVEN_2RANGES(index, 8, \
+ 0x4800, 0x4804, \
+ 0x4848, 0x484c)
+#define XEHP_PAT_INDEX(index) MCR_REG(_PAT_INDEX(index))
+#define XELPMP_PAT_INDEX(index) _MMIO(_PAT_INDEX(index))
#define XEHP_TILE0_ADDR_RANGE MCR_REG(0x4900)
#define XEHP_TILE_LMEM_RANGE_SHIFT 8
@@ -525,6 +530,11 @@
#define GEN8_RC6_CTX_INFO _MMIO(0x8504)
+#define GEN12_SQCNT1 _MMIO(0x8718)
+#define GEN12_SQCNT1_PMON_ENABLE REG_BIT(30)
+#define GEN12_SQCNT1_OABPC REG_BIT(29)
+#define GEN12_STRICT_RAR_ENABLE REG_BIT(23)
+
#define XEHP_SQCM MCR_REG(0x8724)
#define EN_32B_ACCESS REG_BIT(30)
@@ -1460,7 +1470,7 @@
#define GEN12_RCU_MODE _MMIO(0x14800)
#define GEN12_RCU_MODE_CCS_ENABLE REG_BIT(0)
-#define CHV_FUSE_GT _MMIO(VLV_DISPLAY_BASE + 0x2168)
+#define CHV_FUSE_GT _MMIO(VLV_GUNIT_BASE + 0x2168)
#define CHV_FGT_DISABLE_SS0 (1 << 10)
#define CHV_FGT_DISABLE_SS1 (1 << 11)
#define CHV_FGT_EU_DIS_SS0_R0_SHIFT 16
@@ -1587,6 +1597,7 @@
#define GEN11_GT_INTR_DW(x) _MMIO(0x190018 + ((x) * 4))
#define GEN11_CSME (31)
+#define GEN12_HECI_2 (30)
#define GEN11_GUNIT (28)
#define GEN11_GUC (25)
#define MTL_MGUC (24)
@@ -1628,6 +1639,7 @@
/* irq instances for OTHER_CLASS */
#define OTHER_GUC_INSTANCE 0
#define OTHER_GTPM_INSTANCE 1
+#define OTHER_GSC_HECI_2_INSTANCE 3
#define OTHER_KCR_INSTANCE 4
#define OTHER_GSC_INSTANCE 6
#define OTHER_MEDIA_GUC_INSTANCE 16
@@ -1643,6 +1655,7 @@
#define GEN12_VCS6_VCS7_INTR_MASK _MMIO(0x1900b4)
#define GEN11_VECS0_VECS1_INTR_MASK _MMIO(0x1900d0)
#define GEN12_VECS2_VECS3_INTR_MASK _MMIO(0x1900d4)
+#define GEN12_HECI2_RSVD_INTR_MASK _MMIO(0x1900e4)
#define GEN11_GUC_SG_INTR_MASK _MMIO(0x1900e8)
#define MTL_GUC_MGUC_INTR_MASK _MMIO(0x1900e8) /* MTL+ */
#define GEN11_GPM_WGBOXPERF_INTR_MASK _MMIO(0x1900ec)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c
index 1dfd01668c79..d1a382dfaa1d 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c
@@ -116,7 +116,7 @@ void intel_engine_add_retire(struct intel_engine_cs *engine,
GEM_BUG_ON(intel_engine_is_virtual(engine));
if (add_retire(engine, tl))
- schedule_work(&engine->retire_work);
+ queue_work(engine->i915->unordered_wq, &engine->retire_work);
}
void intel_engine_init_retire(struct intel_engine_cs *engine)
@@ -207,8 +207,8 @@ static void retire_work_handler(struct work_struct *work)
struct intel_gt *gt =
container_of(work, typeof(*gt), requests.retire_work.work);
- schedule_delayed_work(&gt->requests.retire_work,
- round_jiffies_up_relative(HZ));
+ queue_delayed_work(gt->i915->unordered_wq, &gt->requests.retire_work,
+ round_jiffies_up_relative(HZ));
intel_gt_retire_requests(gt);
}
@@ -224,8 +224,8 @@ void intel_gt_park_requests(struct intel_gt *gt)
void intel_gt_unpark_requests(struct intel_gt *gt)
{
- schedule_delayed_work(&gt->requests.retire_work,
- round_jiffies_up_relative(HZ));
+ queue_delayed_work(gt->i915->unordered_wq, &gt->requests.retire_work,
+ round_jiffies_up_relative(HZ));
}
void intel_gt_fini_requests(struct intel_gt *gt)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
index 28f27091cd3b..ee2b44f896a2 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
@@ -451,6 +451,33 @@ static ssize_t punit_req_freq_mhz_show(struct kobject *kobj,
return sysfs_emit(buff, "%u\n", preq);
}
+static ssize_t slpc_ignore_eff_freq_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buff)
+{
+ struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
+ struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
+
+ return sysfs_emit(buff, "%u\n", slpc->ignore_eff_freq);
+}
+
+static ssize_t slpc_ignore_eff_freq_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buff, size_t count)
+{
+ struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
+ struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
+ int err;
+ u32 val;
+
+ err = kstrtou32(buff, 0, &val);
+ if (err)
+ return err;
+
+ err = intel_guc_slpc_set_ignore_eff_freq(slpc, val);
+ return err ?: count;
+}
+
struct intel_gt_bool_throttle_attr {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
@@ -663,6 +690,8 @@ static struct kobj_attribute attr_media_freq_factor_scale =
INTEL_GT_ATTR_RO(media_RP0_freq_mhz);
INTEL_GT_ATTR_RO(media_RPn_freq_mhz);
+INTEL_GT_ATTR_RW(slpc_ignore_eff_freq);
+
static const struct attribute *media_perf_power_attrs[] = {
&attr_media_freq_factor.attr,
&attr_media_freq_factor_scale.attr,
@@ -744,6 +773,12 @@ void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
if (ret)
gt_warn(gt, "failed to create punit_req_freq_mhz sysfs (%pe)", ERR_PTR(ret));
+ if (intel_uc_uses_guc_slpc(&gt->uc)) {
+ ret = sysfs_create_file(kobj, &attr_slpc_ignore_eff_freq.attr);
+ if (ret)
+ gt_warn(gt, "failed to create ignore_eff_freq sysfs (%pe)", ERR_PTR(ret));
+ }
+
if (i915_mmio_reg_valid(intel_gt_perf_limit_reasons_reg(gt))) {
ret = sysfs_create_files(kobj, throttle_reason_attrs);
if (ret)
diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c
index 4f436ba7a3c8..2f6a9be0ffe6 100644
--- a/drivers/gpu/drm/i915/gt/intel_gtt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gtt.c
@@ -468,6 +468,44 @@ void gtt_write_workarounds(struct intel_gt *gt)
}
}
+static void xelpmp_setup_private_ppat(struct intel_uncore *uncore)
+{
+ intel_uncore_write(uncore, XELPMP_PAT_INDEX(0),
+ MTL_PPAT_L4_0_WB);
+ intel_uncore_write(uncore, XELPMP_PAT_INDEX(1),
+ MTL_PPAT_L4_1_WT);
+ intel_uncore_write(uncore, XELPMP_PAT_INDEX(2),
+ MTL_PPAT_L4_3_UC);
+ intel_uncore_write(uncore, XELPMP_PAT_INDEX(3),
+ MTL_PPAT_L4_0_WB | MTL_2_COH_1W);
+ intel_uncore_write(uncore, XELPMP_PAT_INDEX(4),
+ MTL_PPAT_L4_0_WB | MTL_3_COH_2W);
+
+ /*
+ * Remaining PAT entries are left at the hardware-default
+ * fully-cached setting
+ */
+}
+
+static void xelpg_setup_private_ppat(struct intel_gt *gt)
+{
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(0),
+ MTL_PPAT_L4_0_WB);
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(1),
+ MTL_PPAT_L4_1_WT);
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(2),
+ MTL_PPAT_L4_3_UC);
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(3),
+ MTL_PPAT_L4_0_WB | MTL_2_COH_1W);
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(4),
+ MTL_PPAT_L4_0_WB | MTL_3_COH_2W);
+
+ /*
+ * Remaining PAT entries are left at the hardware-default
+ * fully-cached setting
+ */
+}
+
static void tgl_setup_private_ppat(struct intel_uncore *uncore)
{
/* TGL doesn't support LLC or AGE settings */
@@ -603,7 +641,14 @@ void setup_private_pat(struct intel_gt *gt)
GEM_BUG_ON(GRAPHICS_VER(i915) < 8);
- if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
+ if (gt->type == GT_MEDIA) {
+ xelpmp_setup_private_ppat(gt->uncore);
+ return;
+ }
+
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))
+ xelpg_setup_private_ppat(gt);
+ else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
xehp_setup_private_ppat(gt);
else if (GRAPHICS_VER(i915) >= 12)
tgl_setup_private_ppat(uncore);
diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h
index 69ce55f517f5..4d6296cdbcfd 100644
--- a/drivers/gpu/drm/i915/gt/intel_gtt.h
+++ b/drivers/gpu/drm/i915/gt/intel_gtt.h
@@ -88,9 +88,17 @@ typedef u64 gen8_pte_t;
#define BYT_PTE_SNOOPED_BY_CPU_CACHES REG_BIT(2)
#define BYT_PTE_WRITEABLE REG_BIT(1)
+#define MTL_PPGTT_PTE_PAT3 BIT_ULL(62)
#define GEN12_PPGTT_PTE_LM BIT_ULL(11)
+#define GEN12_PPGTT_PTE_PAT2 BIT_ULL(7)
+#define GEN12_PPGTT_PTE_PAT1 BIT_ULL(4)
+#define GEN12_PPGTT_PTE_PAT0 BIT_ULL(3)
-#define GEN12_GGTT_PTE_LM BIT_ULL(1)
+#define GEN12_GGTT_PTE_LM BIT_ULL(1)
+#define MTL_GGTT_PTE_PAT0 BIT_ULL(52)
+#define MTL_GGTT_PTE_PAT1 BIT_ULL(53)
+#define GEN12_GGTT_PTE_ADDR_MASK GENMASK_ULL(45, 12)
+#define MTL_GGTT_PTE_PAT_MASK GENMASK_ULL(53, 52)
#define GEN12_PDE_64K BIT(6)
#define GEN12_PTE_PS64 BIT(8)
@@ -147,7 +155,13 @@ typedef u64 gen8_pte_t;
#define GEN8_PDE_IPS_64K BIT(11)
#define GEN8_PDE_PS_2M BIT(7)
-enum i915_cache_level;
+#define MTL_PPAT_L4_CACHE_POLICY_MASK REG_GENMASK(3, 2)
+#define MTL_PAT_INDEX_COH_MODE_MASK REG_GENMASK(1, 0)
+#define MTL_PPAT_L4_3_UC REG_FIELD_PREP(MTL_PPAT_L4_CACHE_POLICY_MASK, 3)
+#define MTL_PPAT_L4_1_WT REG_FIELD_PREP(MTL_PPAT_L4_CACHE_POLICY_MASK, 1)
+#define MTL_PPAT_L4_0_WB REG_FIELD_PREP(MTL_PPAT_L4_CACHE_POLICY_MASK, 0)
+#define MTL_3_COH_2W REG_FIELD_PREP(MTL_PAT_INDEX_COH_MODE_MASK, 3)
+#define MTL_2_COH_1W REG_FIELD_PREP(MTL_PAT_INDEX_COH_MODE_MASK, 2)
struct drm_i915_gem_object;
struct i915_fence_reg;
@@ -216,7 +230,7 @@ struct i915_vma_ops {
void (*bind_vma)(struct i915_address_space *vm,
struct i915_vm_pt_stash *stash,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags);
/*
* Unmap an object from an address space. This usually consists of
@@ -288,7 +302,7 @@ struct i915_address_space {
(*alloc_scratch_dma)(struct i915_address_space *vm, int sz);
u64 (*pte_encode)(dma_addr_t addr,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags); /* Create a valid PTE */
#define PTE_READ_ONLY BIT(0)
#define PTE_LM BIT(1)
@@ -303,20 +317,20 @@ struct i915_address_space {
void (*insert_page)(struct i915_address_space *vm,
dma_addr_t addr,
u64 offset,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags);
void (*insert_entries)(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags);
void (*raw_insert_page)(struct i915_address_space *vm,
dma_addr_t addr,
u64 offset,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags);
void (*raw_insert_entries)(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags);
void (*cleanup)(struct i915_address_space *vm);
@@ -493,7 +507,7 @@ static inline void i915_vm_put(struct i915_address_space *vm)
/**
* i915_vm_resv_put - Release a reference on the vm's reservation lock
- * @resv: Pointer to a reservation lock obtained from i915_vm_resv_get()
+ * @vm: The vm whose reservation lock reference we want to release
*/
static inline void i915_vm_resv_put(struct i915_address_space *vm)
{
@@ -563,7 +577,7 @@ void ppgtt_init(struct i915_ppgtt *ppgtt, struct intel_gt *gt,
void intel_ggtt_bind_vma(struct i915_address_space *vm,
struct i915_vm_pt_stash *stash,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags);
void intel_ggtt_unbind_vma(struct i915_address_space *vm,
struct i915_vma_resource *vma_res);
@@ -641,7 +655,7 @@ void gen6_ggtt_invalidate(struct i915_ggtt *ggtt);
void ppgtt_bind_vma(struct i915_address_space *vm,
struct i915_vm_pt_stash *stash,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags);
void ppgtt_unbind_vma(struct i915_address_space *vm,
struct i915_vma_resource *vma_res);
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index 81a96c52a92b..a4ec20aaafe2 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1370,7 +1370,9 @@ gen12_emit_indirect_ctx_rcs(const struct intel_context *ce, u32 *cs)
cs, GEN12_GFX_CCS_AUX_NV);
/* Wa_16014892111 */
- if (IS_DG2(ce->engine->i915))
+ if (IS_MTL_GRAPHICS_STEP(ce->engine->i915, M, STEP_A0, STEP_B0) ||
+ IS_MTL_GRAPHICS_STEP(ce->engine->i915, P, STEP_A0, STEP_B0) ||
+ IS_DG2(ce->engine->i915))
cs = dg2_emit_draw_watermark_setting(cs);
return cs;
diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.c b/drivers/gpu/drm/i915/gt/intel_migrate.c
index 3f638f198796..6023288b0e2d 100644
--- a/drivers/gpu/drm/i915/gt/intel_migrate.c
+++ b/drivers/gpu/drm/i915/gt/intel_migrate.c
@@ -45,7 +45,9 @@ static void xehpsdv_toggle_pdes(struct i915_address_space *vm,
* Insert a dummy PTE into every PT that will map to LMEM to ensure
* we have a correctly setup PDE structure for later use.
*/
- vm->insert_page(vm, 0, d->offset, I915_CACHE_NONE, PTE_LM);
+ vm->insert_page(vm, 0, d->offset,
+ i915_gem_get_pat_index(vm->i915, I915_CACHE_NONE),
+ PTE_LM);
GEM_BUG_ON(!pt->is_compact);
d->offset += SZ_2M;
}
@@ -63,7 +65,9 @@ static void xehpsdv_insert_pte(struct i915_address_space *vm,
* alignment is 64K underneath for the pt, and we are careful
* not to access the space in the void.
*/
- vm->insert_page(vm, px_dma(pt), d->offset, I915_CACHE_NONE, PTE_LM);
+ vm->insert_page(vm, px_dma(pt), d->offset,
+ i915_gem_get_pat_index(vm->i915, I915_CACHE_NONE),
+ PTE_LM);
d->offset += SZ_64K;
}
@@ -73,7 +77,8 @@ static void insert_pte(struct i915_address_space *vm,
{
struct insert_pte_data *d = data;
- vm->insert_page(vm, px_dma(pt), d->offset, I915_CACHE_NONE,
+ vm->insert_page(vm, px_dma(pt), d->offset,
+ i915_gem_get_pat_index(vm->i915, I915_CACHE_NONE),
i915_gem_object_is_lmem(pt->base) ? PTE_LM : 0);
d->offset += PAGE_SIZE;
}
@@ -356,13 +361,13 @@ static int max_pte_pkt_size(struct i915_request *rq, int pkt)
static int emit_pte(struct i915_request *rq,
struct sgt_dma *it,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
bool is_lmem,
u64 offset,
int length)
{
bool has_64K_pages = HAS_64K_PAGES(rq->engine->i915);
- const u64 encode = rq->context->vm->pte_encode(0, cache_level,
+ const u64 encode = rq->context->vm->pte_encode(0, pat_index,
is_lmem ? PTE_LM : 0);
struct intel_ring *ring = rq->ring;
int pkt, dword_length;
@@ -673,17 +678,17 @@ int
intel_context_migrate_copy(struct intel_context *ce,
const struct i915_deps *deps,
struct scatterlist *src,
- enum i915_cache_level src_cache_level,
+ unsigned int src_pat_index,
bool src_is_lmem,
struct scatterlist *dst,
- enum i915_cache_level dst_cache_level,
+ unsigned int dst_pat_index,
bool dst_is_lmem,
struct i915_request **out)
{
struct sgt_dma it_src = sg_sgt(src), it_dst = sg_sgt(dst), it_ccs;
struct drm_i915_private *i915 = ce->engine->i915;
u64 ccs_bytes_to_cpy = 0, bytes_to_cpy;
- enum i915_cache_level ccs_cache_level;
+ unsigned int ccs_pat_index;
u32 src_offset, dst_offset;
u8 src_access, dst_access;
struct i915_request *rq;
@@ -707,12 +712,12 @@ intel_context_migrate_copy(struct intel_context *ce,
dst_sz = scatter_list_length(dst);
if (src_is_lmem) {
it_ccs = it_dst;
- ccs_cache_level = dst_cache_level;
+ ccs_pat_index = dst_pat_index;
ccs_is_src = false;
} else if (dst_is_lmem) {
bytes_to_cpy = dst_sz;
it_ccs = it_src;
- ccs_cache_level = src_cache_level;
+ ccs_pat_index = src_pat_index;
ccs_is_src = true;
}
@@ -773,7 +778,7 @@ intel_context_migrate_copy(struct intel_context *ce,
src_sz = calculate_chunk_sz(i915, src_is_lmem,
bytes_to_cpy, ccs_bytes_to_cpy);
- len = emit_pte(rq, &it_src, src_cache_level, src_is_lmem,
+ len = emit_pte(rq, &it_src, src_pat_index, src_is_lmem,
src_offset, src_sz);
if (!len) {
err = -EINVAL;
@@ -784,7 +789,7 @@ intel_context_migrate_copy(struct intel_context *ce,
goto out_rq;
}
- err = emit_pte(rq, &it_dst, dst_cache_level, dst_is_lmem,
+ err = emit_pte(rq, &it_dst, dst_pat_index, dst_is_lmem,
dst_offset, len);
if (err < 0)
goto out_rq;
@@ -811,7 +816,7 @@ intel_context_migrate_copy(struct intel_context *ce,
goto out_rq;
ccs_sz = GET_CCS_BYTES(i915, len);
- err = emit_pte(rq, &it_ccs, ccs_cache_level, false,
+ err = emit_pte(rq, &it_ccs, ccs_pat_index, false,
ccs_is_src ? src_offset : dst_offset,
ccs_sz);
if (err < 0)
@@ -920,7 +925,7 @@ static int emit_clear(struct i915_request *rq, u32 offset, int size,
GEM_BUG_ON(size >> PAGE_SHIFT > S16_MAX);
- if (HAS_FLAT_CCS(i915) && ver >= 12)
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
ring_sz = XY_FAST_COLOR_BLT_DW;
else if (ver >= 8)
ring_sz = 8;
@@ -931,7 +936,7 @@ static int emit_clear(struct i915_request *rq, u32 offset, int size,
if (IS_ERR(cs))
return PTR_ERR(cs);
- if (HAS_FLAT_CCS(i915) && ver >= 12) {
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) {
*cs++ = XY_FAST_COLOR_BLT_CMD | XY_FAST_COLOR_BLT_DEPTH_32 |
(XY_FAST_COLOR_BLT_DW - 2);
*cs++ = FIELD_PREP(XY_FAST_COLOR_BLT_MOCS_MASK, mocs) |
@@ -979,7 +984,7 @@ int
intel_context_migrate_clear(struct intel_context *ce,
const struct i915_deps *deps,
struct scatterlist *sg,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
bool is_lmem,
u32 value,
struct i915_request **out)
@@ -1027,7 +1032,7 @@ intel_context_migrate_clear(struct intel_context *ce,
if (err)
goto out_rq;
- len = emit_pte(rq, &it, cache_level, is_lmem, offset, CHUNK_SZ);
+ len = emit_pte(rq, &it, pat_index, is_lmem, offset, CHUNK_SZ);
if (len <= 0) {
err = len;
goto out_rq;
@@ -1074,10 +1079,10 @@ int intel_migrate_copy(struct intel_migrate *m,
struct i915_gem_ww_ctx *ww,
const struct i915_deps *deps,
struct scatterlist *src,
- enum i915_cache_level src_cache_level,
+ unsigned int src_pat_index,
bool src_is_lmem,
struct scatterlist *dst,
- enum i915_cache_level dst_cache_level,
+ unsigned int dst_pat_index,
bool dst_is_lmem,
struct i915_request **out)
{
@@ -1098,8 +1103,8 @@ int intel_migrate_copy(struct intel_migrate *m,
goto out;
err = intel_context_migrate_copy(ce, deps,
- src, src_cache_level, src_is_lmem,
- dst, dst_cache_level, dst_is_lmem,
+ src, src_pat_index, src_is_lmem,
+ dst, dst_pat_index, dst_is_lmem,
out);
intel_context_unpin(ce);
@@ -1113,7 +1118,7 @@ intel_migrate_clear(struct intel_migrate *m,
struct i915_gem_ww_ctx *ww,
const struct i915_deps *deps,
struct scatterlist *sg,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
bool is_lmem,
u32 value,
struct i915_request **out)
@@ -1134,7 +1139,7 @@ intel_migrate_clear(struct intel_migrate *m,
if (err)
goto out;
- err = intel_context_migrate_clear(ce, deps, sg, cache_level,
+ err = intel_context_migrate_clear(ce, deps, sg, pat_index,
is_lmem, value, out);
intel_context_unpin(ce);
diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.h b/drivers/gpu/drm/i915/gt/intel_migrate.h
index ccc677ec4aa3..11fc09a00c4b 100644
--- a/drivers/gpu/drm/i915/gt/intel_migrate.h
+++ b/drivers/gpu/drm/i915/gt/intel_migrate.h
@@ -16,7 +16,6 @@ struct i915_request;
struct i915_gem_ww_ctx;
struct intel_gt;
struct scatterlist;
-enum i915_cache_level;
int intel_migrate_init(struct intel_migrate *m, struct intel_gt *gt);
@@ -26,20 +25,20 @@ int intel_migrate_copy(struct intel_migrate *m,
struct i915_gem_ww_ctx *ww,
const struct i915_deps *deps,
struct scatterlist *src,
- enum i915_cache_level src_cache_level,
+ unsigned int src_pat_index,
bool src_is_lmem,
struct scatterlist *dst,
- enum i915_cache_level dst_cache_level,
+ unsigned int dst_pat_index,
bool dst_is_lmem,
struct i915_request **out);
int intel_context_migrate_copy(struct intel_context *ce,
const struct i915_deps *deps,
struct scatterlist *src,
- enum i915_cache_level src_cache_level,
+ unsigned int src_pat_index,
bool src_is_lmem,
struct scatterlist *dst,
- enum i915_cache_level dst_cache_level,
+ unsigned int dst_pat_index,
bool dst_is_lmem,
struct i915_request **out);
@@ -48,7 +47,7 @@ intel_migrate_clear(struct intel_migrate *m,
struct i915_gem_ww_ctx *ww,
const struct i915_deps *deps,
struct scatterlist *sg,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
bool is_lmem,
u32 value,
struct i915_request **out);
@@ -56,7 +55,7 @@ int
intel_context_migrate_clear(struct intel_context *ce,
const struct i915_deps *deps,
struct scatterlist *sg,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
bool is_lmem,
u32 value,
struct i915_request **out);
diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c
index 69b489e8dfed..2c014407225c 100644
--- a/drivers/gpu/drm/i915/gt/intel_mocs.c
+++ b/drivers/gpu/drm/i915/gt/intel_mocs.c
@@ -40,6 +40,10 @@ struct drm_i915_mocs_table {
#define LE_COS(value) ((value) << 15)
#define LE_SSE(value) ((value) << 17)
+/* Defines for the tables (GLOB_MOCS_0 - GLOB_MOCS_16) */
+#define _L4_CACHEABILITY(value) ((value) << 2)
+#define IG_PAT(value) ((value) << 8)
+
/* Defines for the tables (LNCFMOCS0 - LNCFMOCS31) - two entries per word */
#define L3_ESC(value) ((value) << 0)
#define L3_SCC(value) ((value) << 1)
@@ -50,6 +54,7 @@ struct drm_i915_mocs_table {
/* Helper defines */
#define GEN9_NUM_MOCS_ENTRIES 64 /* 63-64 are reserved, but configured. */
#define PVC_NUM_MOCS_ENTRIES 3
+#define MTL_NUM_MOCS_ENTRIES 16
/* (e)LLC caching options */
/*
@@ -73,6 +78,12 @@ struct drm_i915_mocs_table {
#define L3_2_RESERVED _L3_CACHEABILITY(2)
#define L3_3_WB _L3_CACHEABILITY(3)
+/* L4 caching options */
+#define L4_0_WB _L4_CACHEABILITY(0)
+#define L4_1_WT _L4_CACHEABILITY(1)
+#define L4_2_RESERVED _L4_CACHEABILITY(2)
+#define L4_3_UC _L4_CACHEABILITY(3)
+
#define MOCS_ENTRY(__idx, __control_value, __l3cc_value) \
[__idx] = { \
.control_value = __control_value, \
@@ -416,6 +427,57 @@ static const struct drm_i915_mocs_entry pvc_mocs_table[] = {
MOCS_ENTRY(2, 0, L3_3_WB),
};
+static const struct drm_i915_mocs_entry mtl_mocs_table[] = {
+ /* Error - Reserved for Non-Use */
+ MOCS_ENTRY(0,
+ IG_PAT(0),
+ L3_LKUP(1) | L3_3_WB),
+ /* Cached - L3 + L4 */
+ MOCS_ENTRY(1,
+ IG_PAT(1),
+ L3_LKUP(1) | L3_3_WB),
+ /* L4 - GO:L3 */
+ MOCS_ENTRY(2,
+ IG_PAT(1),
+ L3_LKUP(1) | L3_1_UC),
+ /* Uncached - GO:L3 */
+ MOCS_ENTRY(3,
+ IG_PAT(1) | L4_3_UC,
+ L3_LKUP(1) | L3_1_UC),
+ /* L4 - GO:Mem */
+ MOCS_ENTRY(4,
+ IG_PAT(1),
+ L3_LKUP(1) | L3_GLBGO(1) | L3_1_UC),
+ /* Uncached - GO:Mem */
+ MOCS_ENTRY(5,
+ IG_PAT(1) | L4_3_UC,
+ L3_LKUP(1) | L3_GLBGO(1) | L3_1_UC),
+ /* L4 - L3:NoLKUP; GO:L3 */
+ MOCS_ENTRY(6,
+ IG_PAT(1),
+ L3_1_UC),
+ /* Uncached - L3:NoLKUP; GO:L3 */
+ MOCS_ENTRY(7,
+ IG_PAT(1) | L4_3_UC,
+ L3_1_UC),
+ /* L4 - L3:NoLKUP; GO:Mem */
+ MOCS_ENTRY(8,
+ IG_PAT(1),
+ L3_GLBGO(1) | L3_1_UC),
+ /* Uncached - L3:NoLKUP; GO:Mem */
+ MOCS_ENTRY(9,
+ IG_PAT(1) | L4_3_UC,
+ L3_GLBGO(1) | L3_1_UC),
+ /* Display - L3; L4:WT */
+ MOCS_ENTRY(14,
+ IG_PAT(1) | L4_1_WT,
+ L3_LKUP(1) | L3_3_WB),
+ /* CCS - Non-Displayable */
+ MOCS_ENTRY(15,
+ IG_PAT(1),
+ L3_GLBGO(1) | L3_1_UC),
+};
+
enum {
HAS_GLOBAL_MOCS = BIT(0),
HAS_ENGINE_MOCS = BIT(1),
@@ -445,7 +507,13 @@ static unsigned int get_mocs_settings(const struct drm_i915_private *i915,
memset(table, 0, sizeof(struct drm_i915_mocs_table));
table->unused_entries_index = I915_MOCS_PTE;
- if (IS_PONTEVECCHIO(i915)) {
+ if (IS_METEORLAKE(i915)) {
+ table->size = ARRAY_SIZE(mtl_mocs_table);
+ table->table = mtl_mocs_table;
+ table->n_entries = MTL_NUM_MOCS_ENTRIES;
+ table->uc_index = 9;
+ table->unused_entries_index = 1;
+ } else if (IS_PONTEVECCHIO(i915)) {
table->size = ARRAY_SIZE(pvc_mocs_table);
table->table = pvc_mocs_table;
table->n_entries = PVC_NUM_MOCS_ENTRIES;
diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c
index 7ecfa672f738..436756bfbb1a 100644
--- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c
+++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c
@@ -181,7 +181,7 @@ struct i915_ppgtt *i915_ppgtt_create(struct intel_gt *gt,
void ppgtt_bind_vma(struct i915_address_space *vm,
struct i915_vm_pt_stash *stash,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags)
{
u32 pte_flags;
@@ -199,7 +199,7 @@ void ppgtt_bind_vma(struct i915_address_space *vm,
if (vma_res->bi.lmem)
pte_flags |= PTE_LM;
- vm->insert_entries(vm, vma_res, cache_level, pte_flags);
+ vm->insert_entries(vm, vma_res, pat_index, pte_flags);
wmb();
}
diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c
index 8f3cd68d14f8..58bb1c55294c 100644
--- a/drivers/gpu/drm/i915/gt/intel_rc6.c
+++ b/drivers/gpu/drm/i915/gt/intel_rc6.c
@@ -53,11 +53,6 @@ static struct drm_i915_private *rc6_to_i915(struct intel_rc6 *rc)
return rc6_to_gt(rc)->i915;
}
-static void set(struct intel_uncore *uncore, i915_reg_t reg, u32 val)
-{
- intel_uncore_write_fw(uncore, reg, val);
-}
-
static void gen11_rc6_enable(struct intel_rc6 *rc6)
{
struct intel_gt *gt = rc6_to_gt(rc6);
@@ -72,19 +67,19 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
*/
if (!intel_uc_uses_guc_rc(&gt->uc)) {
/* 2b: Program RC6 thresholds.*/
- set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85);
- set(uncore, GEN10_MEDIA_WAKE_RATE_LIMIT, 150);
+ intel_uncore_write_fw(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85);
+ intel_uncore_write_fw(uncore, GEN10_MEDIA_WAKE_RATE_LIMIT, 150);
- set(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
- set(uncore, GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
+ intel_uncore_write_fw(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
+ intel_uncore_write_fw(uncore, GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
for_each_engine(engine, rc6_to_gt(rc6), id)
- set(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
+ intel_uncore_write_fw(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
- set(uncore, GUC_MAX_IDLE_COUNT, 0xA);
+ intel_uncore_write_fw(uncore, GUC_MAX_IDLE_COUNT, 0xA);
- set(uncore, GEN6_RC_SLEEP, 0);
+ intel_uncore_write_fw(uncore, GEN6_RC_SLEEP, 0);
- set(uncore, GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
+ intel_uncore_write_fw(uncore, GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
}
/*
@@ -105,8 +100,8 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
* Broadwell+, To be conservative, we want to factor in a context
* switch on top (due to ksoftirqd).
*/
- set(uncore, GEN9_MEDIA_PG_IDLE_HYSTERESIS, 60);
- set(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 60);
+ intel_uncore_write_fw(uncore, GEN9_MEDIA_PG_IDLE_HYSTERESIS, 60);
+ intel_uncore_write_fw(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 60);
/* 3a: Enable RC6
*
@@ -122,8 +117,14 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
GEN6_RC_CTL_RC6_ENABLE |
GEN6_RC_CTL_EI_MODE(1);
- /* Wa_16011777198 - Render powergating must remain disabled */
- if (IS_DG2_GRAPHICS_STEP(gt->i915, G10, STEP_A0, STEP_C0) ||
+ /*
+ * Wa_16011777198 and BSpec 52698 - Render powergating must be off.
+ * FIXME BSpec is outdated, disabling powergating for MTL is just
+ * temporary wa and should be removed after fixing real cause
+ * of forcewake timeouts.
+ */
+ if (IS_METEORLAKE(gt->i915) ||
+ IS_DG2_GRAPHICS_STEP(gt->i915, G10, STEP_A0, STEP_C0) ||
IS_DG2_GRAPHICS_STEP(gt->i915, G11, STEP_A0, STEP_B0))
pg_enable =
GEN9_MEDIA_PG_ENABLE |
@@ -141,7 +142,7 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
VDN_MFX_POWERGATE_ENABLE(i));
}
- set(uncore, GEN9_PG_ENABLE, pg_enable);
+ intel_uncore_write_fw(uncore, GEN9_PG_ENABLE, pg_enable);
}
static void gen9_rc6_enable(struct intel_rc6 *rc6)
@@ -152,26 +153,26 @@ static void gen9_rc6_enable(struct intel_rc6 *rc6)
/* 2b: Program RC6 thresholds.*/
if (GRAPHICS_VER(rc6_to_i915(rc6)) >= 11) {
- set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85);
- set(uncore, GEN10_MEDIA_WAKE_RATE_LIMIT, 150);
+ intel_uncore_write_fw(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85);
+ intel_uncore_write_fw(uncore, GEN10_MEDIA_WAKE_RATE_LIMIT, 150);
} else if (IS_SKYLAKE(rc6_to_i915(rc6))) {
/*
* WaRsDoubleRc6WrlWithCoarsePowerGating:skl Doubling WRL only
* when CPG is enabled
*/
- set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 108 << 16);
+ intel_uncore_write_fw(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 108 << 16);
} else {
- set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16);
+ intel_uncore_write_fw(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16);
}
- set(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
- set(uncore, GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
+ intel_uncore_write_fw(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
+ intel_uncore_write_fw(uncore, GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
for_each_engine(engine, rc6_to_gt(rc6), id)
- set(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
+ intel_uncore_write_fw(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
- set(uncore, GUC_MAX_IDLE_COUNT, 0xA);
+ intel_uncore_write_fw(uncore, GUC_MAX_IDLE_COUNT, 0xA);
- set(uncore, GEN6_RC_SLEEP, 0);
+ intel_uncore_write_fw(uncore, GEN6_RC_SLEEP, 0);
/*
* 2c: Program Coarse Power Gating Policies.
@@ -194,11 +195,11 @@ static void gen9_rc6_enable(struct intel_rc6 *rc6)
* conservative, we have to factor in a context switch on top (due
* to ksoftirqd).
*/
- set(uncore, GEN9_MEDIA_PG_IDLE_HYSTERESIS, 250);
- set(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 250);
+ intel_uncore_write_fw(uncore, GEN9_MEDIA_PG_IDLE_HYSTERESIS, 250);
+ intel_uncore_write_fw(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 250);
/* 3a: Enable RC6 */
- set(uncore, GEN6_RC6_THRESHOLD, 37500); /* 37.5/125ms per EI */
+ intel_uncore_write_fw(uncore, GEN6_RC6_THRESHOLD, 37500); /* 37.5/125ms per EI */
rc6->ctl_enable =
GEN6_RC_CTL_HW_ENABLE |
@@ -210,8 +211,8 @@ static void gen9_rc6_enable(struct intel_rc6 *rc6)
* - Render/Media PG need to be disabled with RC6.
*/
if (!NEEDS_WaRsDisableCoarsePowerGating(rc6_to_i915(rc6)))
- set(uncore, GEN9_PG_ENABLE,
- GEN9_RENDER_PG_ENABLE | GEN9_MEDIA_PG_ENABLE);
+ intel_uncore_write_fw(uncore, GEN9_PG_ENABLE,
+ GEN9_RENDER_PG_ENABLE | GEN9_MEDIA_PG_ENABLE);
}
static void gen8_rc6_enable(struct intel_rc6 *rc6)
@@ -221,13 +222,13 @@ static void gen8_rc6_enable(struct intel_rc6 *rc6)
enum intel_engine_id id;
/* 2b: Program RC6 thresholds.*/
- set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
- set(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
- set(uncore, GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
+ intel_uncore_write_fw(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
+ intel_uncore_write_fw(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
+ intel_uncore_write_fw(uncore, GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
for_each_engine(engine, rc6_to_gt(rc6), id)
- set(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
- set(uncore, GEN6_RC_SLEEP, 0);
- set(uncore, GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */
+ intel_uncore_write_fw(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
+ intel_uncore_write_fw(uncore, GEN6_RC_SLEEP, 0);
+ intel_uncore_write_fw(uncore, GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */
/* 3: Enable RC6 */
rc6->ctl_enable =
@@ -245,20 +246,20 @@ static void gen6_rc6_enable(struct intel_rc6 *rc6)
u32 rc6vids, rc6_mask;
int ret;
- set(uncore, GEN6_RC1_WAKE_RATE_LIMIT, 1000 << 16);
- set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30);
- set(uncore, GEN6_RC6pp_WAKE_RATE_LIMIT, 30);
- set(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000);
- set(uncore, GEN6_RC_IDLE_HYSTERSIS, 25);
+ intel_uncore_write_fw(uncore, GEN6_RC1_WAKE_RATE_LIMIT, 1000 << 16);
+ intel_uncore_write_fw(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30);
+ intel_uncore_write_fw(uncore, GEN6_RC6pp_WAKE_RATE_LIMIT, 30);
+ intel_uncore_write_fw(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000);
+ intel_uncore_write_fw(uncore, GEN6_RC_IDLE_HYSTERSIS, 25);
for_each_engine(engine, rc6_to_gt(rc6), id)
- set(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
+ intel_uncore_write_fw(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
- set(uncore, GEN6_RC_SLEEP, 0);
- set(uncore, GEN6_RC1e_THRESHOLD, 1000);
- set(uncore, GEN6_RC6_THRESHOLD, 50000);
- set(uncore, GEN6_RC6p_THRESHOLD, 150000);
- set(uncore, GEN6_RC6pp_THRESHOLD, 64000); /* unused */
+ intel_uncore_write_fw(uncore, GEN6_RC_SLEEP, 0);
+ intel_uncore_write_fw(uncore, GEN6_RC1e_THRESHOLD, 1000);
+ intel_uncore_write_fw(uncore, GEN6_RC6_THRESHOLD, 50000);
+ intel_uncore_write_fw(uncore, GEN6_RC6p_THRESHOLD, 150000);
+ intel_uncore_write_fw(uncore, GEN6_RC6pp_THRESHOLD, 64000); /* unused */
/* We don't use those on Haswell */
rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
@@ -372,22 +373,22 @@ static void chv_rc6_enable(struct intel_rc6 *rc6)
enum intel_engine_id id;
/* 2a: Program RC6 thresholds.*/
- set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
- set(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
- set(uncore, GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
+ intel_uncore_write_fw(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
+ intel_uncore_write_fw(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
+ intel_uncore_write_fw(uncore, GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
for_each_engine(engine, rc6_to_gt(rc6), id)
- set(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
- set(uncore, GEN6_RC_SLEEP, 0);
+ intel_uncore_write_fw(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
+ intel_uncore_write_fw(uncore, GEN6_RC_SLEEP, 0);
/* TO threshold set to 500 us (0x186 * 1.28 us) */
- set(uncore, GEN6_RC6_THRESHOLD, 0x186);
+ intel_uncore_write_fw(uncore, GEN6_RC6_THRESHOLD, 0x186);
/* Allows RC6 residency counter to work */
- set(uncore, VLV_COUNTER_CONTROL,
- _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
- VLV_MEDIA_RC6_COUNT_EN |
- VLV_RENDER_RC6_COUNT_EN));
+ intel_uncore_write_fw(uncore, VLV_COUNTER_CONTROL,
+ _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
+ VLV_MEDIA_RC6_COUNT_EN |
+ VLV_RENDER_RC6_COUNT_EN));
/* 3: Enable RC6 */
rc6->ctl_enable = GEN7_RC_CTL_TO_MODE;
@@ -399,22 +400,22 @@ static void vlv_rc6_enable(struct intel_rc6 *rc6)
struct intel_engine_cs *engine;
enum intel_engine_id id;
- set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 0x00280000);
- set(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000);
- set(uncore, GEN6_RC_IDLE_HYSTERSIS, 25);
+ intel_uncore_write_fw(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 0x00280000);
+ intel_uncore_write_fw(uncore, GEN6_RC_EVALUATION_INTERVAL, 125000);
+ intel_uncore_write_fw(uncore, GEN6_RC_IDLE_HYSTERSIS, 25);
for_each_engine(engine, rc6_to_gt(rc6), id)
- set(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
+ intel_uncore_write_fw(uncore, RING_MAX_IDLE(engine->mmio_base), 10);
- set(uncore, GEN6_RC6_THRESHOLD, 0x557);
+ intel_uncore_write_fw(uncore, GEN6_RC6_THRESHOLD, 0x557);
/* Allows RC6 residency counter to work */
- set(uncore, VLV_COUNTER_CONTROL,
- _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
- VLV_MEDIA_RC0_COUNT_EN |
- VLV_RENDER_RC0_COUNT_EN |
- VLV_MEDIA_RC6_COUNT_EN |
- VLV_RENDER_RC6_COUNT_EN));
+ intel_uncore_write_fw(uncore, VLV_COUNTER_CONTROL,
+ _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
+ VLV_MEDIA_RC0_COUNT_EN |
+ VLV_RENDER_RC0_COUNT_EN |
+ VLV_MEDIA_RC6_COUNT_EN |
+ VLV_RENDER_RC6_COUNT_EN));
rc6->ctl_enable =
GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL;
@@ -575,9 +576,9 @@ static void __intel_rc6_disable(struct intel_rc6 *rc6)
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
if (GRAPHICS_VER(i915) >= 9)
- set(uncore, GEN9_PG_ENABLE, 0);
- set(uncore, GEN6_RC_CONTROL, 0);
- set(uncore, GEN6_RC_STATE, 0);
+ intel_uncore_write_fw(uncore, GEN9_PG_ENABLE, 0);
+ intel_uncore_write_fw(uncore, GEN6_RC_CONTROL, 0);
+ intel_uncore_write_fw(uncore, GEN6_RC_STATE, 0);
intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
}
@@ -684,7 +685,7 @@ void intel_rc6_unpark(struct intel_rc6 *rc6)
return;
/* Restore HW timers for automatic RC6 entry while busy */
- set(uncore, GEN6_RC_CONTROL, rc6->ctl_enable);
+ intel_uncore_write_fw(uncore, GEN6_RC_CONTROL, rc6->ctl_enable);
}
void intel_rc6_park(struct intel_rc6 *rc6)
@@ -704,7 +705,7 @@ void intel_rc6_park(struct intel_rc6 *rc6)
return;
/* Turn off the HW timers and go directly to rc6 */
- set(uncore, GEN6_RC_CONTROL, GEN6_RC_CTL_RC6_ENABLE);
+ intel_uncore_write_fw(uncore, GEN6_RC_CONTROL, GEN6_RC_CTL_RC6_ENABLE);
if (HAS_RC6pp(rc6_to_i915(rc6)))
target = 0x6; /* deepest rc6 */
@@ -712,7 +713,7 @@ void intel_rc6_park(struct intel_rc6 *rc6)
target = 0x5; /* deep rc6 */
else
target = 0x4; /* normal rc6 */
- set(uncore, GEN6_RC_STATE, target << RC_SW_TARGET_STATE_SHIFT);
+ intel_uncore_write_fw(uncore, GEN6_RC_STATE, target << RC_SW_TARGET_STATE_SHIFT);
}
void intel_rc6_disable(struct intel_rc6 *rc6)
@@ -735,7 +736,7 @@ void intel_rc6_fini(struct intel_rc6 *rc6)
/* We want the BIOS C6 state preserved across loads for MTL */
if (IS_METEORLAKE(rc6_to_i915(rc6)) && rc6->bios_state_captured)
- set(uncore, GEN6_RC_STATE, rc6->bios_rc_state);
+ intel_uncore_write_fw(uncore, GEN6_RC_STATE, rc6->bios_rc_state);
pctx = fetch_and_zero(&rc6->pctx);
if (pctx)
@@ -766,18 +767,18 @@ static u64 vlv_residency_raw(struct intel_uncore *uncore, const i915_reg_t reg)
* before we have set the default VLV_COUNTER_CONTROL value. So always
* set the high bit to be safe.
*/
- set(uncore, VLV_COUNTER_CONTROL,
- _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH));
+ intel_uncore_write_fw(uncore, VLV_COUNTER_CONTROL,
+ _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH));
upper = intel_uncore_read_fw(uncore, reg);
do {
tmp = upper;
- set(uncore, VLV_COUNTER_CONTROL,
- _MASKED_BIT_DISABLE(VLV_COUNT_RANGE_HIGH));
+ intel_uncore_write_fw(uncore, VLV_COUNTER_CONTROL,
+ _MASKED_BIT_DISABLE(VLV_COUNT_RANGE_HIGH));
lower = intel_uncore_read_fw(uncore, reg);
- set(uncore, VLV_COUNTER_CONTROL,
- _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH));
+ intel_uncore_write_fw(uncore, VLV_COUNTER_CONTROL,
+ _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH));
upper = intel_uncore_read_fw(uncore, reg);
} while (upper != tmp && --loop);
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c
index 797ea8340467..e2152f75ba2e 100644
--- a/drivers/gpu/drm/i915/gt/intel_reset.c
+++ b/drivers/gpu/drm/i915/gt/intel_reset.c
@@ -7,7 +7,7 @@
#include <linux/stop_machine.h>
#include <linux/string_helpers.h>
-#include "display/intel_display.h"
+#include "display/intel_display_reset.h"
#include "display/intel_overlay.h"
#include "gem/i915_gem_context.h"
@@ -20,6 +20,7 @@
#include "i915_file_private.h"
#include "i915_gpu_error.h"
#include "i915_irq.h"
+#include "i915_reg.h"
#include "intel_breadcrumbs.h"
#include "intel_engine_pm.h"
#include "intel_engine_regs.h"
@@ -1370,11 +1371,11 @@ static void intel_gt_reset_global(struct intel_gt *gt,
/* Use a watchdog to ensure that our reset completes */
intel_wedge_on_timeout(&w, gt, 60 * HZ) {
- intel_display_prepare_reset(gt->i915);
+ intel_display_reset_prepare(gt->i915);
intel_gt_reset(gt, engine_mask, reason);
- intel_display_finish_reset(gt->i915);
+ intel_display_reset_finish(gt->i915);
}
if (!test_bit(I915_WEDGED, &gt->reset.flags))
@@ -1624,7 +1625,7 @@ void __intel_init_wedge(struct intel_wedge_me *w,
w->name = name;
INIT_DELAYED_WORK_ONSTACK(&w->work, intel_wedge_me);
- schedule_delayed_work(&w->work, timeout);
+ queue_delayed_work(gt->i915->unordered_wq, &w->work, timeout);
}
void __intel_fini_wedge(struct intel_wedge_me *w)
diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c
index b2671ac59dc0..e92e626d4994 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.c
+++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@ -8,8 +8,10 @@
#include <drm/i915_drm.h>
#include "display/intel_display.h"
+#include "display/intel_display_irq.h"
#include "i915_drv.h"
#include "i915_irq.h"
+#include "i915_reg.h"
#include "intel_breadcrumbs.h"
#include "intel_gt.h"
#include "intel_gt_clock_utils.h"
@@ -71,13 +73,14 @@ static void set(struct intel_uncore *uncore, i915_reg_t reg, u32 val)
static void rps_timer(struct timer_list *t)
{
struct intel_rps *rps = from_timer(rps, t, timer);
+ struct intel_gt *gt = rps_to_gt(rps);
struct intel_engine_cs *engine;
ktime_t dt, last, timestamp;
enum intel_engine_id id;
s64 max_busy[3] = {};
timestamp = 0;
- for_each_engine(engine, rps_to_gt(rps), id) {
+ for_each_engine(engine, gt, id) {
s64 busy;
int i;
@@ -121,7 +124,7 @@ static void rps_timer(struct timer_list *t)
busy += div_u64(max_busy[i], 1 << i);
}
- GT_TRACE(rps_to_gt(rps),
+ GT_TRACE(gt,
"busy:%lld [%d%%], max:[%lld, %lld, %lld], interval:%d\n",
busy, (int)div64_u64(100 * busy, dt),
max_busy[0], max_busy[1], max_busy[2],
@@ -131,12 +134,12 @@ static void rps_timer(struct timer_list *t)
rps->cur_freq < rps->max_freq_softlimit) {
rps->pm_iir |= GEN6_PM_RP_UP_THRESHOLD;
rps->pm_interval = 1;
- schedule_work(&rps->work);
+ queue_work(gt->i915->unordered_wq, &rps->work);
} else if (100 * busy < rps->power.down_threshold * dt &&
rps->cur_freq > rps->min_freq_softlimit) {
rps->pm_iir |= GEN6_PM_RP_DOWN_THRESHOLD;
rps->pm_interval = 1;
- schedule_work(&rps->work);
+ queue_work(gt->i915->unordered_wq, &rps->work);
} else {
rps->last_adj = 0;
}
@@ -971,7 +974,7 @@ static int rps_set_boost_freq(struct intel_rps *rps, u32 val)
}
mutex_unlock(&rps->lock);
if (boost)
- schedule_work(&rps->work);
+ queue_work(rps_to_gt(rps)->i915->unordered_wq, &rps->work);
return 0;
}
@@ -1023,7 +1026,8 @@ void intel_rps_boost(struct i915_request *rq)
if (!atomic_fetch_inc(&slpc->num_waiters)) {
GT_TRACE(rps_to_gt(rps), "boost fence:%llx:%llx\n",
rq->fence.context, rq->fence.seqno);
- schedule_work(&slpc->boost_work);
+ queue_work(rps_to_gt(rps)->i915->unordered_wq,
+ &slpc->boost_work);
}
return;
@@ -1039,7 +1043,7 @@ void intel_rps_boost(struct i915_request *rq)
rq->fence.context, rq->fence.seqno);
if (READ_ONCE(rps->cur_freq) < rps->boost_freq)
- schedule_work(&rps->work);
+ queue_work(rps_to_gt(rps)->i915->unordered_wq, &rps->work);
WRITE_ONCE(rps->boosts, rps->boosts + 1); /* debug only */
}
@@ -1898,7 +1902,7 @@ void gen11_rps_irq_handler(struct intel_rps *rps, u32 pm_iir)
gen6_gt_pm_mask_irq(gt, events);
rps->pm_iir |= events;
- schedule_work(&rps->work);
+ queue_work(gt->i915->unordered_wq, &rps->work);
}
void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir)
@@ -1915,7 +1919,7 @@ void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir)
gen6_gt_pm_mask_irq(gt, events);
rps->pm_iir |= events;
- schedule_work(&rps->work);
+ queue_work(gt->i915->unordered_wq, &rps->work);
spin_unlock(gt->irq_lock);
}
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index b925ef47304b..4d2dece96011 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -812,11 +812,25 @@ static void dg2_ctx_workarounds_init(struct intel_engine_cs *engine,
wa_masked_en(wal, CACHE_MODE_1, MSAA_OPTIMIZATION_REDUC_DISABLE);
}
+static void mtl_ctx_gt_tuning_init(struct intel_engine_cs *engine,
+ struct i915_wa_list *wal)
+{
+ struct drm_i915_private *i915 = engine->i915;
+
+ dg2_ctx_gt_tuning_init(engine, wal);
+
+ if (IS_MTL_GRAPHICS_STEP(i915, M, STEP_B0, STEP_FOREVER) ||
+ IS_MTL_GRAPHICS_STEP(i915, P, STEP_B0, STEP_FOREVER))
+ wa_add(wal, DRAW_WATERMARK, VERT_WM_VAL, 0x3FF, 0, false);
+}
+
static void mtl_ctx_workarounds_init(struct intel_engine_cs *engine,
struct i915_wa_list *wal)
{
struct drm_i915_private *i915 = engine->i915;
+ mtl_ctx_gt_tuning_init(engine, wal);
+
if (IS_MTL_GRAPHICS_STEP(i915, M, STEP_A0, STEP_B0) ||
IS_MTL_GRAPHICS_STEP(i915, P, STEP_A0, STEP_B0)) {
/* Wa_14014947963 */
@@ -1695,14 +1709,20 @@ pvc_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
static void
xelpg_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
{
+ /* Wa_14018778641 / Wa_18018781329 */
+ wa_mcr_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB);
+ wa_mcr_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB);
+
+ /* Wa_22016670082 */
+ wa_write_or(wal, GEN12_SQCNT1, GEN12_STRICT_RAR_ENABLE);
+
if (IS_MTL_GRAPHICS_STEP(gt->i915, M, STEP_A0, STEP_B0) ||
IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0)) {
/* Wa_14014830051 */
wa_mcr_write_clr(wal, SARB_CHICKEN1, COMP_CKN_IN);
- /* Wa_18018781329 */
- wa_mcr_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB);
- wa_mcr_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB);
+ /* Wa_14015795083 */
+ wa_write_clr(wal, GEN7_MISCCPCTL, GEN12_DOP_CLOCK_GATE_RENDER_ENABLE);
}
/*
@@ -1715,17 +1735,16 @@ xelpg_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
static void
xelpmp_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
{
- if (IS_MTL_MEDIA_STEP(gt->i915, STEP_A0, STEP_B0)) {
- /*
- * Wa_18018781329
- *
- * Note that although these registers are MCR on the primary
- * GT, the media GT's versions are regular singleton registers.
- */
- wa_write_or(wal, XELPMP_GSC_MOD_CTRL, FORCE_MISS_FTLB);
- wa_write_or(wal, XELPMP_VDBX_MOD_CTRL, FORCE_MISS_FTLB);
- wa_write_or(wal, XELPMP_VEBX_MOD_CTRL, FORCE_MISS_FTLB);
- }
+ /*
+ * Wa_14018778641
+ * Wa_18018781329
+ *
+ * Note that although these registers are MCR on the primary
+ * GT, the media GT's versions are regular singleton registers.
+ */
+ wa_write_or(wal, XELPMP_GSC_MOD_CTRL, FORCE_MISS_FTLB);
+ wa_write_or(wal, XELPMP_VDBX_MOD_CTRL, FORCE_MISS_FTLB);
+ wa_write_or(wal, XELPMP_VEBX_MOD_CTRL, FORCE_MISS_FTLB);
debug_dump_steering(gt);
}
@@ -1743,6 +1762,13 @@ xelpmp_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
*/
static void gt_tuning_settings(struct intel_gt *gt, struct i915_wa_list *wal)
{
+ if (IS_METEORLAKE(gt->i915)) {
+ if (gt->type != GT_MEDIA)
+ wa_mcr_write_or(wal, XEHP_L3SCQREG7, BLEND_FILL_CACHING_OPT_DIS);
+
+ wa_mcr_write_or(wal, XEHP_SQCM, EN_32B_ACCESS);
+ }
+
if (IS_PONTEVECCHIO(gt->i915)) {
wa_mcr_write(wal, XEHPC_L3SCRUB,
SCRUB_CL_DWNGRADE_SHARED | SCRUB_RATE_4B_PER_CLK);
@@ -2939,7 +2965,7 @@ static void
add_render_compute_tuning_settings(struct drm_i915_private *i915,
struct i915_wa_list *wal)
{
- if (IS_DG2(i915))
+ if (IS_METEORLAKE(i915) || IS_DG2(i915))
wa_mcr_write_clr_set(wal, RT_CTRL, STACKID_CTRL, STACKID_CTRL_512);
/*
diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
index 542ce6d2de19..78cdfc6f315f 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
@@ -27,7 +27,7 @@ static void perf_begin(struct intel_gt *gt)
/* Boost gpufreq to max [waitboost] and keep it fixed */
atomic_inc(&gt->rps.num_waiters);
- schedule_work(&gt->rps.work);
+ queue_work(gt->i915->unordered_wq, &gt->rps.work);
flush_work(&gt->rps.work);
}
diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c
index 87c94314cf67..10e556a7eac4 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c
@@ -5,6 +5,7 @@
#include <linux/sort.h>
+#include "gt/intel_gt_print.h"
#include "i915_selftest.h"
#include "intel_engine_regs.h"
#include "intel_gpu_commands.h"
@@ -402,7 +403,7 @@ static int live_engine_pm(void *arg)
/* gt wakeref is async (deferred to workqueue) */
if (intel_gt_pm_wait_for_idle(gt)) {
- pr_err("GT failed to idle\n");
+ gt_err(gt, "GT failed to idle\n");
return -EINVAL;
}
}
diff --git a/drivers/gpu/drm/i915/gt/selftest_migrate.c b/drivers/gpu/drm/i915/gt/selftest_migrate.c
index e677f2da093d..3def5ca72dec 100644
--- a/drivers/gpu/drm/i915/gt/selftest_migrate.c
+++ b/drivers/gpu/drm/i915/gt/selftest_migrate.c
@@ -137,7 +137,7 @@ err_free_src:
static int intel_context_copy_ccs(struct intel_context *ce,
const struct i915_deps *deps,
struct scatterlist *sg,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
bool write_to_ccs,
struct i915_request **out)
{
@@ -185,7 +185,7 @@ static int intel_context_copy_ccs(struct intel_context *ce,
if (err)
goto out_rq;
- len = emit_pte(rq, &it, cache_level, true, offset, CHUNK_SZ);
+ len = emit_pte(rq, &it, pat_index, true, offset, CHUNK_SZ);
if (len <= 0) {
err = len;
goto out_rq;
@@ -223,7 +223,7 @@ intel_migrate_ccs_copy(struct intel_migrate *m,
struct i915_gem_ww_ctx *ww,
const struct i915_deps *deps,
struct scatterlist *sg,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
bool write_to_ccs,
struct i915_request **out)
{
@@ -243,7 +243,7 @@ intel_migrate_ccs_copy(struct intel_migrate *m,
if (err)
goto out;
- err = intel_context_copy_ccs(ce, deps, sg, cache_level,
+ err = intel_context_copy_ccs(ce, deps, sg, pat_index,
write_to_ccs, out);
intel_context_unpin(ce);
@@ -300,7 +300,7 @@ static int clear(struct intel_migrate *migrate,
/* Write the obj data into ccs surface */
err = intel_migrate_ccs_copy(migrate, &ww, NULL,
obj->mm.pages->sgl,
- obj->cache_level,
+ obj->pat_index,
true, &rq);
if (rq && !err) {
if (i915_request_wait(rq, 0, HZ) < 0) {
@@ -351,7 +351,7 @@ static int clear(struct intel_migrate *migrate,
err = intel_migrate_ccs_copy(migrate, &ww, NULL,
obj->mm.pages->sgl,
- obj->cache_level,
+ obj->pat_index,
false, &rq);
if (rq && !err) {
if (i915_request_wait(rq, 0, HZ) < 0) {
@@ -414,9 +414,9 @@ static int __migrate_copy(struct intel_migrate *migrate,
struct i915_request **out)
{
return intel_migrate_copy(migrate, ww, NULL,
- src->mm.pages->sgl, src->cache_level,
+ src->mm.pages->sgl, src->pat_index,
i915_gem_object_is_lmem(src),
- dst->mm.pages->sgl, dst->cache_level,
+ dst->mm.pages->sgl, dst->pat_index,
i915_gem_object_is_lmem(dst),
out);
}
@@ -428,9 +428,9 @@ static int __global_copy(struct intel_migrate *migrate,
struct i915_request **out)
{
return intel_context_migrate_copy(migrate->context, NULL,
- src->mm.pages->sgl, src->cache_level,
+ src->mm.pages->sgl, src->pat_index,
i915_gem_object_is_lmem(src),
- dst->mm.pages->sgl, dst->cache_level,
+ dst->mm.pages->sgl, dst->pat_index,
i915_gem_object_is_lmem(dst),
out);
}
@@ -455,7 +455,7 @@ static int __migrate_clear(struct intel_migrate *migrate,
{
return intel_migrate_clear(migrate, ww, NULL,
obj->mm.pages->sgl,
- obj->cache_level,
+ obj->pat_index,
i915_gem_object_is_lmem(obj),
value, out);
}
@@ -468,7 +468,7 @@ static int __global_clear(struct intel_migrate *migrate,
{
return intel_context_migrate_clear(migrate->context, NULL,
obj->mm.pages->sgl,
- obj->cache_level,
+ obj->pat_index,
i915_gem_object_is_lmem(obj),
value, out);
}
@@ -648,7 +648,7 @@ static int live_emit_pte_full_ring(void *arg)
*/
pr_info("%s emite_pte ring space=%u\n", __func__, rq->ring->space);
it = sg_sgt(obj->mm.pages->sgl);
- len = emit_pte(rq, &it, obj->cache_level, false, 0, CHUNK_SZ);
+ len = emit_pte(rq, &it, obj->pat_index, false, 0, CHUNK_SZ);
if (!len) {
err = -EINVAL;
goto out_rq;
@@ -844,7 +844,7 @@ static int wrap_ktime_compare(const void *A, const void *B)
static int __perf_clear_blt(struct intel_context *ce,
struct scatterlist *sg,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
bool is_lmem,
size_t sz)
{
@@ -858,7 +858,7 @@ static int __perf_clear_blt(struct intel_context *ce,
t0 = ktime_get();
- err = intel_context_migrate_clear(ce, NULL, sg, cache_level,
+ err = intel_context_migrate_clear(ce, NULL, sg, pat_index,
is_lmem, 0, &rq);
if (rq) {
if (i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT) < 0)
@@ -904,7 +904,8 @@ static int perf_clear_blt(void *arg)
err = __perf_clear_blt(gt->migrate.context,
dst->mm.pages->sgl,
- I915_CACHE_NONE,
+ i915_gem_get_pat_index(gt->i915,
+ I915_CACHE_NONE),
i915_gem_object_is_lmem(dst),
sizes[i]);
@@ -919,10 +920,10 @@ static int perf_clear_blt(void *arg)
static int __perf_copy_blt(struct intel_context *ce,
struct scatterlist *src,
- enum i915_cache_level src_cache_level,
+ unsigned int src_pat_index,
bool src_is_lmem,
struct scatterlist *dst,
- enum i915_cache_level dst_cache_level,
+ unsigned int dst_pat_index,
bool dst_is_lmem,
size_t sz)
{
@@ -937,9 +938,9 @@ static int __perf_copy_blt(struct intel_context *ce,
t0 = ktime_get();
err = intel_context_migrate_copy(ce, NULL,
- src, src_cache_level,
+ src, src_pat_index,
src_is_lmem,
- dst, dst_cache_level,
+ dst, dst_pat_index,
dst_is_lmem,
&rq);
if (rq) {
@@ -994,10 +995,12 @@ static int perf_copy_blt(void *arg)
err = __perf_copy_blt(gt->migrate.context,
src->mm.pages->sgl,
- I915_CACHE_NONE,
+ i915_gem_get_pat_index(gt->i915,
+ I915_CACHE_NONE),
i915_gem_object_is_lmem(src),
dst->mm.pages->sgl,
- I915_CACHE_NONE,
+ i915_gem_get_pat_index(gt->i915,
+ I915_CACHE_NONE),
i915_gem_object_is_lmem(dst),
sz);
diff --git a/drivers/gpu/drm/i915/gt/selftest_mocs.c b/drivers/gpu/drm/i915/gt/selftest_mocs.c
index ca009a6a13bd..a8446ab82501 100644
--- a/drivers/gpu/drm/i915/gt/selftest_mocs.c
+++ b/drivers/gpu/drm/i915/gt/selftest_mocs.c
@@ -131,13 +131,14 @@ static int read_mocs_table(struct i915_request *rq,
const struct drm_i915_mocs_table *table,
u32 *offset)
{
+ struct intel_gt *gt = rq->engine->gt;
u32 addr;
if (!table)
return 0;
if (HAS_GLOBAL_MOCS_REGISTERS(rq->engine->i915))
- addr = global_mocs_offset();
+ addr = global_mocs_offset() + gt->uncore->gsi_offset;
else
addr = mocs_offset(rq->engine);
diff --git a/drivers/gpu/drm/i915/gt/selftest_reset.c b/drivers/gpu/drm/i915/gt/selftest_reset.c
index a9e0a91bc0e0..79aa6ac66ad2 100644
--- a/drivers/gpu/drm/i915/gt/selftest_reset.c
+++ b/drivers/gpu/drm/i915/gt/selftest_reset.c
@@ -86,7 +86,9 @@ __igt_reset_stolen(struct intel_gt *gt,
ggtt->vm.insert_page(&ggtt->vm, dma,
ggtt->error_capture.start,
- I915_CACHE_NONE, 0);
+ i915_gem_get_pat_index(gt->i915,
+ I915_CACHE_NONE),
+ 0);
mb();
s = io_mapping_map_wc(&ggtt->iomap,
@@ -127,7 +129,9 @@ __igt_reset_stolen(struct intel_gt *gt,
ggtt->vm.insert_page(&ggtt->vm, dma,
ggtt->error_capture.start,
- I915_CACHE_NONE, 0);
+ i915_gem_get_pat_index(gt->i915,
+ I915_CACHE_NONE),
+ 0);
mb();
s = io_mapping_map_wc(&ggtt->iomap,
diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c b/drivers/gpu/drm/i915/gt/selftest_rps.c
index 84e77e8dbba1..fb30f733b036 100644
--- a/drivers/gpu/drm/i915/gt/selftest_rps.c
+++ b/drivers/gpu/drm/i915/gt/selftest_rps.c
@@ -8,6 +8,7 @@
#include "gem/i915_gem_internal.h"
+#include "i915_reg.h"
#include "intel_engine_heartbeat.h"
#include "intel_engine_pm.h"
#include "intel_engine_regs.h"
diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c
index bd44ce73a504..952c8d52d68a 100644
--- a/drivers/gpu/drm/i915/gt/selftest_slpc.c
+++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c
@@ -70,6 +70,31 @@ static int slpc_set_freq(struct intel_gt *gt, u32 freq)
return err;
}
+static int slpc_restore_freq(struct intel_guc_slpc *slpc, u32 min, u32 max)
+{
+ int err;
+
+ err = slpc_set_max_freq(slpc, max);
+ if (err) {
+ pr_err("Unable to restore max freq");
+ return err;
+ }
+
+ err = slpc_set_min_freq(slpc, min);
+ if (err) {
+ pr_err("Unable to restore min freq");
+ return err;
+ }
+
+ err = intel_guc_slpc_set_ignore_eff_freq(slpc, false);
+ if (err) {
+ pr_err("Unable to restore efficient freq");
+ return err;
+ }
+
+ return 0;
+}
+
static u64 measure_power_at_freq(struct intel_gt *gt, int *freq, u64 *power)
{
int err = 0;
@@ -268,8 +293,7 @@ static int run_test(struct intel_gt *gt, int test_type)
/*
* Set min frequency to RPn so that we can test the whole
- * range of RPn-RP0. This also turns off efficient freq
- * usage and makes results more predictable.
+ * range of RPn-RP0.
*/
err = slpc_set_min_freq(slpc, slpc->min_freq);
if (err) {
@@ -277,6 +301,15 @@ static int run_test(struct intel_gt *gt, int test_type)
return err;
}
+ /*
+ * Turn off efficient frequency so RPn/RP0 ranges are obeyed.
+ */
+ err = intel_guc_slpc_set_ignore_eff_freq(slpc, true);
+ if (err) {
+ pr_err("Unable to turn off efficient freq!");
+ return err;
+ }
+
intel_gt_pm_wait_for_idle(gt);
intel_gt_pm_get(gt);
for_each_engine(engine, gt, id) {
@@ -358,9 +391,8 @@ static int run_test(struct intel_gt *gt, int test_type)
break;
}
- /* Restore min/max frequencies */
- slpc_set_max_freq(slpc, slpc_max_freq);
- slpc_set_min_freq(slpc, slpc_min_freq);
+ /* Restore min/max/efficient frequencies */
+ err = slpc_restore_freq(slpc, slpc_min_freq, slpc_max_freq);
if (igt_flush_test(gt->i915))
err = -EIO;
diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c
index 9f536c251179..39c3ec12df1a 100644
--- a/drivers/gpu/drm/i915/gt/selftest_timeline.c
+++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c
@@ -836,7 +836,7 @@ static int setup_watcher(struct hwsp_watcher *w, struct intel_gt *gt,
return PTR_ERR(obj);
/* keep the same cache settings as timeline */
- i915_gem_object_set_cache_coherency(obj, tl->hwsp_ggtt->obj->cache_level);
+ i915_gem_object_set_pat_index(obj, tl->hwsp_ggtt->obj->pat_index);
w->map = i915_gem_object_pin_map_unlocked(obj,
page_unmask_bits(tl->hwsp_ggtt->obj->mm.mapping));
if (IS_ERR(w->map)) {
diff --git a/drivers/gpu/drm/i915/gt/selftest_tlb.c b/drivers/gpu/drm/i915/gt/selftest_tlb.c
index e6cac1f15d6e..3bd6b540257b 100644
--- a/drivers/gpu/drm/i915/gt/selftest_tlb.c
+++ b/drivers/gpu/drm/i915/gt/selftest_tlb.c
@@ -36,6 +36,8 @@ pte_tlbinv(struct intel_context *ce,
u64 length,
struct rnd_state *prng)
{
+ const unsigned int pat_index =
+ i915_gem_get_pat_index(ce->vm->i915, I915_CACHE_NONE);
struct drm_i915_gem_object *batch;
struct drm_mm_node vb_node;
struct i915_request *rq;
@@ -155,7 +157,7 @@ pte_tlbinv(struct intel_context *ce,
/* Flip the PTE between A and B */
if (i915_gem_object_is_lmem(vb->obj))
pte_flags |= PTE_LM;
- ce->vm->insert_entries(ce->vm, &vb_res, 0, pte_flags);
+ ce->vm->insert_entries(ce->vm, &vb_res, pat_index, pte_flags);
/* Flush the PTE update to concurrent HW */
tlbinv(ce->vm, addr & -length, length);
@@ -188,11 +190,18 @@ out:
static struct drm_i915_gem_object *create_lmem(struct intel_gt *gt)
{
+ struct intel_memory_region *mr = gt->i915->mm.regions[INTEL_REGION_LMEM_0];
+ resource_size_t size = SZ_1G;
+
/*
* Allocation of largest possible page size allows to test all types
- * of pages.
+ * of pages. To succeed with both allocations, especially in case of Small
+ * BAR, try to allocate no more than quarter of mappable memory.
*/
- return i915_gem_object_create_lmem(gt->i915, SZ_1G, I915_BO_ALLOC_CONTIGUOUS);
+ if (mr && size > mr->io_size / 4)
+ size = mr->io_size / 4;
+
+ return i915_gem_object_create_lmem(gt->i915, size, I915_BO_ALLOC_CONTIGUOUS);
}
static struct drm_i915_gem_object *create_smem(struct intel_gt *gt)
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h
index 28b8387f97b7..f7d70db16d76 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h
@@ -167,25 +167,4 @@ static_assert(sizeof(struct guc_ct_buffer_desc) == 64);
* - **flags**, holds various bits to control message handling
*/
-/*
- * Definition of the command transport message header (DW0)
- *
- * bit[4..0] message len (in dwords)
- * bit[7..5] reserved
- * bit[8] response (G2H only)
- * bit[8] write fence to desc (H2G only)
- * bit[9] write status to H2G buff (H2G only)
- * bit[10] send status back via G2H (H2G only)
- * bit[15..11] reserved
- * bit[31..16] action code
- */
-#define GUC_CT_MSG_LEN_SHIFT 0
-#define GUC_CT_MSG_LEN_MASK 0x1F
-#define GUC_CT_MSG_IS_RESPONSE (1 << 8)
-#define GUC_CT_MSG_WRITE_FENCE_TO_DESC (1 << 8)
-#define GUC_CT_MSG_WRITE_STATUS_TO_BUFF (1 << 9)
-#define GUC_CT_MSG_SEND_STATUS (1 << 10)
-#define GUC_CT_MSG_ACTION_SHIFT 16
-#define GUC_CT_MSG_ACTION_MASK 0xFFFF
-
#endif /* _ABI_GUC_COMMUNICATION_CTB_ABI_H */
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h
index bcb1129b3610..dabeaf4f245f 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h
@@ -44,6 +44,7 @@ enum intel_guc_load_status {
enum intel_bootrom_load_status {
INTEL_BOOTROM_STATUS_NO_KEY_FOUND = 0x13,
INTEL_BOOTROM_STATUS_AES_PROD_KEY_FOUND = 0x1A,
+ INTEL_BOOTROM_STATUS_PROD_KEY_CHECK_FAILURE = 0x2B,
INTEL_BOOTROM_STATUS_RSA_FAILED = 0x50,
INTEL_BOOTROM_STATUS_PAVPC_FAILED = 0x73,
INTEL_BOOTROM_STATUS_WOPCM_FAILED = 0x74,
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h
index 7d5ba4d97d70..98eb4f46572b 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h
@@ -24,6 +24,7 @@
* | | 30:28 | **TYPE** - message type |
* | | | - _`GUC_HXG_TYPE_REQUEST` = 0 |
* | | | - _`GUC_HXG_TYPE_EVENT` = 1 |
+ * | | | - _`GUC_HXG_TYPE_FAST_REQUEST` = 2 |
* | | | - _`GUC_HXG_TYPE_NO_RESPONSE_BUSY` = 3 |
* | | | - _`GUC_HXG_TYPE_NO_RESPONSE_RETRY` = 5 |
* | | | - _`GUC_HXG_TYPE_RESPONSE_FAILURE` = 6 |
@@ -46,6 +47,7 @@
#define GUC_HXG_MSG_0_TYPE (0x7 << 28)
#define GUC_HXG_TYPE_REQUEST 0u
#define GUC_HXG_TYPE_EVENT 1u
+#define GUC_HXG_TYPE_FAST_REQUEST 2u
#define GUC_HXG_TYPE_NO_RESPONSE_BUSY 3u
#define GUC_HXG_TYPE_NO_RESPONSE_RETRY 5u
#define GUC_HXG_TYPE_RESPONSE_FAILURE 6u
@@ -90,6 +92,34 @@
#define GUC_HXG_REQUEST_MSG_n_DATAn GUC_HXG_MSG_n_PAYLOAD
/**
+ * DOC: HXG Fast Request
+ *
+ * The `HXG Request`_ message should be used to initiate asynchronous activity
+ * for which confirmation or return data is not expected.
+ *
+ * If confirmation is required then `HXG Request`_ shall be used instead.
+ *
+ * The recipient of this message may only use `HXG Failure`_ message if it was
+ * unable to accept this request (like invalid data).
+ *
+ * Format of `HXG Fast Request`_ message is same as `HXG Request`_ except @TYPE.
+ *
+ * +---+-------+--------------------------------------------------------------+
+ * | | Bits | Description |
+ * +===+=======+==============================================================+
+ * | 0 | 31 | ORIGIN - see `HXG Message`_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 30:28 | TYPE = `GUC_HXG_TYPE_FAST_REQUEST`_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 27:16 | DATA0 - see `HXG Request`_ |
+ * | +-------+--------------------------------------------------------------+
+ * | | 15:0 | ACTION - see `HXG Request`_ |
+ * +---+-------+--------------------------------------------------------------+
+ * |...| | DATAn - see `HXG Request`_ |
+ * +---+-------+--------------------------------------------------------------+
+ */
+
+/**
* DOC: HXG Event
*
* The `HXG Event`_ message should be used to initiate asynchronous activity
diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h
index 9d589c28f40f..1fc0c17b1230 100644
--- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h
+++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h
@@ -12,7 +12,7 @@
struct intel_guc;
struct file;
-/**
+/*
* struct __guc_capture_bufstate
*
* Book-keeping structure used to track read and write pointers
@@ -26,7 +26,7 @@ struct __guc_capture_bufstate {
u32 wr;
};
-/**
+/*
* struct __guc_capture_parsed_output - extracted error capture node
*
* A single unit of extracted error-capture output data grouped together
@@ -58,7 +58,7 @@ struct __guc_capture_parsed_output {
#define GCAP_PARSED_REGLIST_INDEX_ENGINST BIT(GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE)
};
-/**
+/*
* struct guc_debug_capture_list_header / struct guc_debug_capture_list
*
* As part of ADS registration, these header structures (followed by
@@ -76,7 +76,7 @@ struct guc_debug_capture_list {
struct guc_mmio_reg regs[];
} __packed;
-/**
+/*
* struct __guc_mmio_reg_descr / struct __guc_mmio_reg_descr_group
*
* intel_guc_capture module uses these structures to maintain static
@@ -101,7 +101,7 @@ struct __guc_mmio_reg_descr_group {
struct __guc_mmio_reg_descr *extlist; /* only used for steered registers */
};
-/**
+/*
* struct guc_state_capture_header_t / struct guc_state_capture_t /
* guc_state_capture_group_header_t / guc_state_capture_group_t
*
@@ -148,7 +148,7 @@ struct guc_state_capture_group_t {
struct guc_state_capture_t capture_entries[];
} __packed;
-/**
+/*
* struct __guc_capture_ads_cache
*
* A structure to cache register lists that were populated and registered
@@ -187,6 +187,10 @@ struct intel_guc_state_capture {
struct __guc_capture_ads_cache ads_cache[GUC_CAPTURE_LIST_INDEX_MAX]
[GUC_CAPTURE_LIST_TYPE_MAX]
[GUC_MAX_ENGINE_CLASSES];
+
+ /**
+ * @ads_null_cache: ADS null cache.
+ */
void *ads_null_cache;
/**
@@ -202,6 +206,10 @@ struct intel_guc_state_capture {
struct list_head cachelist;
#define PREALLOC_NODES_MAX_COUNT (3 * GUC_MAX_ENGINE_CLASSES * GUC_MAX_INSTANCES_PER_CLASS)
#define PREALLOC_NODES_DEFAULT_NUMREGS 64
+
+ /**
+ * @max_mmio_per_node: Max MMIO per node.
+ */
int max_mmio_per_node;
/**
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_binary_headers.h b/drivers/gpu/drm/i915/gt/uc/intel_gsc_binary_headers.h
new file mode 100644
index 000000000000..714f0c256118
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_binary_headers.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef _INTEL_GSC_BINARY_HEADERS_H_
+#define _INTEL_GSC_BINARY_HEADERS_H_
+
+#include <linux/types.h>
+
+/* Code partition directory (CPD) structures */
+struct intel_gsc_cpd_header_v2 {
+ u32 header_marker;
+#define INTEL_GSC_CPD_HEADER_MARKER 0x44504324
+
+ u32 num_of_entries;
+ u8 header_version;
+ u8 entry_version;
+ u8 header_length; /* in bytes */
+ u8 flags;
+ u32 partition_name;
+ u32 crc32;
+} __packed;
+
+struct intel_gsc_cpd_entry {
+ u8 name[12];
+
+ /*
+ * Bits 0-24: offset from the beginning of the code partition
+ * Bit 25: huffman compressed
+ * Bits 26-31: reserved
+ */
+ u32 offset;
+#define INTEL_GSC_CPD_ENTRY_OFFSET_MASK GENMASK(24, 0)
+#define INTEL_GSC_CPD_ENTRY_HUFFMAN_COMP BIT(25)
+
+ /*
+ * Module/Item length, in bytes. For Huffman-compressed modules, this
+ * refers to the uncompressed size. For software-compressed modules,
+ * this refers to the compressed size.
+ */
+ u32 length;
+
+ u8 reserved[4];
+} __packed;
+
+struct intel_gsc_version {
+ u16 major;
+ u16 minor;
+ u16 hotfix;
+ u16 build;
+} __packed;
+
+struct intel_gsc_manifest_header {
+ u32 header_type; /* 0x4 for manifest type */
+ u32 header_length; /* in dwords */
+ u32 header_version;
+ u32 flags;
+ u32 vendor;
+ u32 date;
+ u32 size; /* In dwords, size of entire manifest (header + extensions) */
+ u32 header_id;
+ u32 internal_data;
+ struct intel_gsc_version fw_version;
+ u32 security_version;
+ struct intel_gsc_version meu_kit_version;
+ u32 meu_manifest_version;
+ u8 general_data[4];
+ u8 reserved3[56];
+ u32 modulus_size; /* in dwords */
+ u32 exponent_size; /* in dwords */
+} __packed;
+
+#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c
index 1d9fdfb11268..60e9c6c9e775 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c
@@ -13,6 +13,7 @@
#define GSC_FW_STATUS_REG _MMIO(0x116C40)
#define GSC_FW_CURRENT_STATE REG_GENMASK(3, 0)
#define GSC_FW_CURRENT_STATE_RESET 0
+#define GSC_FW_PROXY_STATE_NORMAL 5
#define GSC_FW_INIT_COMPLETE_BIT REG_BIT(9)
static bool gsc_is_in_reset(struct intel_uncore *uncore)
@@ -23,12 +24,27 @@ static bool gsc_is_in_reset(struct intel_uncore *uncore)
GSC_FW_CURRENT_STATE_RESET;
}
-bool intel_gsc_uc_fw_init_done(struct intel_gsc_uc *gsc)
+static u32 gsc_uc_get_fw_status(struct intel_uncore *uncore)
{
- struct intel_uncore *uncore = gsc_uc_to_gt(gsc)->uncore;
- u32 fw_status = intel_uncore_read(uncore, GSC_FW_STATUS_REG);
+ intel_wakeref_t wakeref;
+ u32 fw_status = 0;
+
+ with_intel_runtime_pm(uncore->rpm, wakeref)
+ fw_status = intel_uncore_read(uncore, GSC_FW_STATUS_REG);
+
+ return fw_status;
+}
+
+bool intel_gsc_uc_fw_proxy_init_done(struct intel_gsc_uc *gsc)
+{
+ return REG_FIELD_GET(GSC_FW_CURRENT_STATE,
+ gsc_uc_get_fw_status(gsc_uc_to_gt(gsc)->uncore)) ==
+ GSC_FW_PROXY_STATE_NORMAL;
+}
- return fw_status & GSC_FW_INIT_COMPLETE_BIT;
+bool intel_gsc_uc_fw_init_done(struct intel_gsc_uc *gsc)
+{
+ return gsc_uc_get_fw_status(gsc_uc_to_gt(gsc)->uncore) & GSC_FW_INIT_COMPLETE_BIT;
}
static int emit_gsc_fw_load(struct i915_request *rq, struct intel_gsc_uc *gsc)
@@ -110,6 +126,13 @@ static int gsc_fw_load_prepare(struct intel_gsc_uc *gsc)
if (obj->base.size < gsc->fw.size)
return -ENOSPC;
+ /*
+ * Wa_22016122933: For MTL the shared memory needs to be mapped
+ * as WC on CPU side and UC (PAT index 2) on GPU side
+ */
+ if (IS_METEORLAKE(i915))
+ i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
+
dst = i915_gem_object_pin_map_unlocked(obj,
i915_coherent_map_type(i915, obj, true));
if (IS_ERR(dst))
@@ -125,6 +148,12 @@ static int gsc_fw_load_prepare(struct intel_gsc_uc *gsc)
memset(dst, 0, obj->base.size);
memcpy(dst, src, gsc->fw.size);
+ /*
+ * Wa_22016122933: Making sure the data in dst is
+ * visible to GSC right away
+ */
+ intel_guc_write_barrier(&gt->uc.guc);
+
i915_gem_object_unpin_map(gsc->fw.obj);
i915_gem_object_unpin_map(obj);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h
index f4c1106bb2a9..fff8928218df 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h
@@ -13,5 +13,6 @@ struct intel_uncore;
int intel_gsc_uc_fw_upload(struct intel_gsc_uc *gsc);
bool intel_gsc_uc_fw_init_done(struct intel_gsc_uc *gsc);
+bool intel_gsc_uc_fw_proxy_init_done(struct intel_gsc_uc *gsc);
#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c
new file mode 100644
index 000000000000..5f138de3c14f
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c
@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include <linux/component.h>
+
+#include <drm/i915_component.h>
+#include <drm/i915_gsc_proxy_mei_interface.h>
+
+#include "gt/intel_gt.h"
+#include "gt/intel_gt_print.h"
+#include "intel_gsc_proxy.h"
+#include "intel_gsc_uc.h"
+#include "intel_gsc_uc_heci_cmd_submit.h"
+#include "i915_drv.h"
+#include "i915_reg.h"
+
+/*
+ * GSC proxy:
+ * The GSC uC needs to communicate with the CSME to perform certain operations.
+ * Since the GSC can't perform this communication directly on platforms where it
+ * is integrated in GT, i915 needs to transfer the messages from GSC to CSME
+ * and back. i915 must manually start the proxy flow after the GSC is loaded to
+ * signal to GSC that we're ready to handle its messages and allow it to query
+ * its init data from CSME; GSC will then trigger an HECI2 interrupt if it needs
+ * to send messages to CSME again.
+ * The proxy flow is as follow:
+ * 1 - i915 submits a request to GSC asking for the message to CSME
+ * 2 - GSC replies with the proxy header + payload for CSME
+ * 3 - i915 sends the reply from GSC as-is to CSME via the mei proxy component
+ * 4 - CSME replies with the proxy header + payload for GSC
+ * 5 - i915 submits a request to GSC with the reply from CSME
+ * 6 - GSC replies either with a new header + payload (same as step 2, so we
+ * restart from there) or with an end message.
+ */
+
+/*
+ * The component should load quite quickly in most cases, but it could take
+ * a bit. Using a very big timeout just to cover the worst case scenario
+ */
+#define GSC_PROXY_INIT_TIMEOUT_MS 20000
+
+/* the protocol supports up to 32K in each direction */
+#define GSC_PROXY_BUFFER_SIZE SZ_32K
+#define GSC_PROXY_CHANNEL_SIZE (GSC_PROXY_BUFFER_SIZE * 2)
+#define GSC_PROXY_MAX_MSG_SIZE (GSC_PROXY_BUFFER_SIZE - sizeof(struct intel_gsc_mtl_header))
+
+/* FW-defined proxy header */
+struct intel_gsc_proxy_header {
+ /*
+ * hdr:
+ * Bits 0-7: type of the proxy message (see enum intel_gsc_proxy_type)
+ * Bits 8-15: rsvd
+ * Bits 16-31: length in bytes of the payload following the proxy header
+ */
+ u32 hdr;
+#define GSC_PROXY_TYPE GENMASK(7, 0)
+#define GSC_PROXY_PAYLOAD_LENGTH GENMASK(31, 16)
+
+ u32 source; /* Source of the Proxy message */
+ u32 destination; /* Destination of the Proxy message */
+#define GSC_PROXY_ADDRESSING_KMD 0x10000
+#define GSC_PROXY_ADDRESSING_GSC 0x20000
+#define GSC_PROXY_ADDRESSING_CSME 0x30000
+
+ u32 status; /* Command status */
+} __packed;
+
+/* FW-defined proxy types */
+enum intel_gsc_proxy_type {
+ GSC_PROXY_MSG_TYPE_PROXY_INVALID = 0,
+ GSC_PROXY_MSG_TYPE_PROXY_QUERY = 1,
+ GSC_PROXY_MSG_TYPE_PROXY_PAYLOAD = 2,
+ GSC_PROXY_MSG_TYPE_PROXY_END = 3,
+ GSC_PROXY_MSG_TYPE_PROXY_NOTIFICATION = 4,
+};
+
+struct gsc_proxy_msg {
+ struct intel_gsc_mtl_header header;
+ struct intel_gsc_proxy_header proxy_header;
+} __packed;
+
+static int proxy_send_to_csme(struct intel_gsc_uc *gsc)
+{
+ struct intel_gt *gt = gsc_uc_to_gt(gsc);
+ struct i915_gsc_proxy_component *comp = gsc->proxy.component;
+ struct intel_gsc_mtl_header *hdr;
+ void *in = gsc->proxy.to_csme;
+ void *out = gsc->proxy.to_gsc;
+ u32 in_size;
+ int ret;
+
+ /* CSME msg only includes the proxy */
+ hdr = in;
+ in += sizeof(struct intel_gsc_mtl_header);
+ out += sizeof(struct intel_gsc_mtl_header);
+
+ in_size = hdr->message_size - sizeof(struct intel_gsc_mtl_header);
+
+ /* the message must contain at least the proxy header */
+ if (in_size < sizeof(struct intel_gsc_proxy_header) ||
+ in_size > GSC_PROXY_MAX_MSG_SIZE) {
+ gt_err(gt, "Invalid CSME message size: %u\n", in_size);
+ return -EINVAL;
+ }
+
+ ret = comp->ops->send(comp->mei_dev, in, in_size);
+ if (ret < 0) {
+ gt_err(gt, "Failed to send CSME message\n");
+ return ret;
+ }
+
+ ret = comp->ops->recv(comp->mei_dev, out, GSC_PROXY_MAX_MSG_SIZE);
+ if (ret < 0) {
+ gt_err(gt, "Failed to receive CSME message\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static int proxy_send_to_gsc(struct intel_gsc_uc *gsc)
+{
+ struct intel_gt *gt = gsc_uc_to_gt(gsc);
+ u32 *marker = gsc->proxy.to_csme; /* first dw of the reply header */
+ u64 addr_in = i915_ggtt_offset(gsc->proxy.vma);
+ u64 addr_out = addr_in + GSC_PROXY_BUFFER_SIZE;
+ u32 size = ((struct gsc_proxy_msg *)gsc->proxy.to_gsc)->header.message_size;
+ int err;
+
+ /* the message must contain at least the gsc and proxy headers */
+ if (size < sizeof(struct gsc_proxy_msg) || size > GSC_PROXY_BUFFER_SIZE) {
+ gt_err(gt, "Invalid GSC proxy message size: %u\n", size);
+ return -EINVAL;
+ }
+
+ /* clear the message marker */
+ *marker = 0;
+
+ /* make sure the marker write is flushed */
+ wmb();
+
+ /* send the request */
+ err = intel_gsc_uc_heci_cmd_submit_packet(gsc, addr_in, size,
+ addr_out, GSC_PROXY_BUFFER_SIZE);
+
+ if (!err) {
+ /* wait for the reply to show up */
+ err = wait_for(*marker != 0, 300);
+ if (err)
+ gt_err(gt, "Failed to get a proxy reply from gsc\n");
+ }
+
+ return err;
+}
+
+static int validate_proxy_header(struct intel_gsc_proxy_header *header,
+ u32 source, u32 dest)
+{
+ u32 type = FIELD_GET(GSC_PROXY_TYPE, header->hdr);
+ u32 length = FIELD_GET(GSC_PROXY_PAYLOAD_LENGTH, header->hdr);
+ int ret = 0;
+
+ if (header->destination != dest || header->source != source) {
+ ret = -ENOEXEC;
+ goto fail;
+ }
+
+ switch (type) {
+ case GSC_PROXY_MSG_TYPE_PROXY_PAYLOAD:
+ if (length > 0)
+ break;
+ fallthrough;
+ case GSC_PROXY_MSG_TYPE_PROXY_INVALID:
+ ret = -EIO;
+ goto fail;
+ default:
+ break;
+ }
+
+fail:
+ return ret;
+}
+
+static int proxy_query(struct intel_gsc_uc *gsc)
+{
+ struct intel_gt *gt = gsc_uc_to_gt(gsc);
+ struct gsc_proxy_msg *to_gsc = gsc->proxy.to_gsc;
+ struct gsc_proxy_msg *to_csme = gsc->proxy.to_csme;
+ int ret;
+
+ intel_gsc_uc_heci_cmd_emit_mtl_header(&to_gsc->header,
+ HECI_MEADDRESS_PROXY,
+ sizeof(struct gsc_proxy_msg),
+ 0);
+
+ to_gsc->proxy_header.hdr =
+ FIELD_PREP(GSC_PROXY_TYPE, GSC_PROXY_MSG_TYPE_PROXY_QUERY) |
+ FIELD_PREP(GSC_PROXY_PAYLOAD_LENGTH, 0);
+
+ to_gsc->proxy_header.source = GSC_PROXY_ADDRESSING_KMD;
+ to_gsc->proxy_header.destination = GSC_PROXY_ADDRESSING_GSC;
+ to_gsc->proxy_header.status = 0;
+
+ while (1) {
+ /* clear the GSC response header space */
+ memset(gsc->proxy.to_csme, 0, sizeof(struct gsc_proxy_msg));
+
+ /* send proxy message to GSC */
+ ret = proxy_send_to_gsc(gsc);
+ if (ret) {
+ gt_err(gt, "failed to send proxy message to GSC! %d\n", ret);
+ goto proxy_error;
+ }
+
+ /* stop if this was the last message */
+ if (FIELD_GET(GSC_PROXY_TYPE, to_csme->proxy_header.hdr) ==
+ GSC_PROXY_MSG_TYPE_PROXY_END)
+ break;
+
+ /* make sure the GSC-to-CSME proxy header is sane */
+ ret = validate_proxy_header(&to_csme->proxy_header,
+ GSC_PROXY_ADDRESSING_GSC,
+ GSC_PROXY_ADDRESSING_CSME);
+ if (ret) {
+ gt_err(gt, "invalid GSC to CSME proxy header! %d\n", ret);
+ goto proxy_error;
+ }
+
+ /* send the GSC message to the CSME */
+ ret = proxy_send_to_csme(gsc);
+ if (ret < 0) {
+ gt_err(gt, "failed to send proxy message to CSME! %d\n", ret);
+ goto proxy_error;
+ }
+
+ /* update the GSC message size with the returned value from CSME */
+ to_gsc->header.message_size = ret + sizeof(struct intel_gsc_mtl_header);
+
+ /* make sure the CSME-to-GSC proxy header is sane */
+ ret = validate_proxy_header(&to_gsc->proxy_header,
+ GSC_PROXY_ADDRESSING_CSME,
+ GSC_PROXY_ADDRESSING_GSC);
+ if (ret) {
+ gt_err(gt, "invalid CSME to GSC proxy header! %d\n", ret);
+ goto proxy_error;
+ }
+ }
+
+proxy_error:
+ return ret < 0 ? ret : 0;
+}
+
+int intel_gsc_proxy_request_handler(struct intel_gsc_uc *gsc)
+{
+ struct intel_gt *gt = gsc_uc_to_gt(gsc);
+ int err;
+
+ if (!gsc->proxy.component_added)
+ return -ENODEV;
+
+ assert_rpm_wakelock_held(gt->uncore->rpm);
+
+ /* when GSC is loaded, we can queue this before the component is bound */
+ err = wait_for(gsc->proxy.component, GSC_PROXY_INIT_TIMEOUT_MS);
+ if (err) {
+ gt_err(gt, "GSC proxy component didn't bind within the expected timeout\n");
+ return -EIO;
+ }
+
+ mutex_lock(&gsc->proxy.mutex);
+ if (!gsc->proxy.component) {
+ gt_err(gt, "GSC proxy worker called without the component being bound!\n");
+ err = -EIO;
+ } else {
+ /*
+ * write the status bit to clear it and allow new proxy
+ * interrupts to be generated while we handle the current
+ * request, but be sure not to write the reset bit
+ */
+ intel_uncore_rmw(gt->uncore, HECI_H_CSR(MTL_GSC_HECI2_BASE),
+ HECI_H_CSR_RST, HECI_H_CSR_IS);
+ err = proxy_query(gsc);
+ }
+ mutex_unlock(&gsc->proxy.mutex);
+ return err;
+}
+
+void intel_gsc_proxy_irq_handler(struct intel_gsc_uc *gsc, u32 iir)
+{
+ struct intel_gt *gt = gsc_uc_to_gt(gsc);
+
+ if (unlikely(!iir))
+ return;
+
+ lockdep_assert_held(gt->irq_lock);
+
+ if (!gsc->proxy.component) {
+ gt_err(gt, "GSC proxy irq received without the component being bound!\n");
+ return;
+ }
+
+ gsc->gsc_work_actions |= GSC_ACTION_SW_PROXY;
+ queue_work(gsc->wq, &gsc->work);
+}
+
+static int i915_gsc_proxy_component_bind(struct device *i915_kdev,
+ struct device *mei_kdev, void *data)
+{
+ struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
+ struct intel_gt *gt = i915->media_gt;
+ struct intel_gsc_uc *gsc = &gt->uc.gsc;
+ intel_wakeref_t wakeref;
+
+ /* enable HECI2 IRQs */
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref)
+ intel_uncore_rmw(gt->uncore, HECI_H_CSR(MTL_GSC_HECI2_BASE),
+ HECI_H_CSR_RST, HECI_H_CSR_IE);
+
+ mutex_lock(&gsc->proxy.mutex);
+ gsc->proxy.component = data;
+ gsc->proxy.component->mei_dev = mei_kdev;
+ mutex_unlock(&gsc->proxy.mutex);
+
+ return 0;
+}
+
+static void i915_gsc_proxy_component_unbind(struct device *i915_kdev,
+ struct device *mei_kdev, void *data)
+{
+ struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
+ struct intel_gt *gt = i915->media_gt;
+ struct intel_gsc_uc *gsc = &gt->uc.gsc;
+ intel_wakeref_t wakeref;
+
+ mutex_lock(&gsc->proxy.mutex);
+ gsc->proxy.component = NULL;
+ mutex_unlock(&gsc->proxy.mutex);
+
+ /* disable HECI2 IRQs */
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref)
+ intel_uncore_rmw(gt->uncore, HECI_H_CSR(MTL_GSC_HECI2_BASE),
+ HECI_H_CSR_IE | HECI_H_CSR_RST, 0);
+}
+
+static const struct component_ops i915_gsc_proxy_component_ops = {
+ .bind = i915_gsc_proxy_component_bind,
+ .unbind = i915_gsc_proxy_component_unbind,
+};
+
+static int proxy_channel_alloc(struct intel_gsc_uc *gsc)
+{
+ struct intel_gt *gt = gsc_uc_to_gt(gsc);
+ struct i915_vma *vma;
+ void *vaddr;
+ int err;
+
+ err = intel_guc_allocate_and_map_vma(&gt->uc.guc, GSC_PROXY_CHANNEL_SIZE,
+ &vma, &vaddr);
+ if (err)
+ return err;
+
+ gsc->proxy.vma = vma;
+ gsc->proxy.to_gsc = vaddr;
+ gsc->proxy.to_csme = vaddr + GSC_PROXY_BUFFER_SIZE;
+
+ return 0;
+}
+
+static void proxy_channel_free(struct intel_gsc_uc *gsc)
+{
+ if (!gsc->proxy.vma)
+ return;
+
+ gsc->proxy.to_gsc = NULL;
+ gsc->proxy.to_csme = NULL;
+ i915_vma_unpin_and_release(&gsc->proxy.vma, I915_VMA_RELEASE_MAP);
+}
+
+void intel_gsc_proxy_fini(struct intel_gsc_uc *gsc)
+{
+ struct intel_gt *gt = gsc_uc_to_gt(gsc);
+ struct drm_i915_private *i915 = gt->i915;
+
+ if (fetch_and_zero(&gsc->proxy.component_added))
+ component_del(i915->drm.dev, &i915_gsc_proxy_component_ops);
+
+ proxy_channel_free(gsc);
+}
+
+int intel_gsc_proxy_init(struct intel_gsc_uc *gsc)
+{
+ int err;
+ struct intel_gt *gt = gsc_uc_to_gt(gsc);
+ struct drm_i915_private *i915 = gt->i915;
+
+ mutex_init(&gsc->proxy.mutex);
+
+ if (!IS_ENABLED(CONFIG_INTEL_MEI_GSC_PROXY)) {
+ gt_info(gt, "can't init GSC proxy due to missing mei component\n");
+ return -ENODEV;
+ }
+
+ err = proxy_channel_alloc(gsc);
+ if (err)
+ return err;
+
+ err = component_add_typed(i915->drm.dev, &i915_gsc_proxy_component_ops,
+ I915_COMPONENT_GSC_PROXY);
+ if (err < 0) {
+ gt_err(gt, "Failed to add GSC_PROXY component (%d)\n", err);
+ goto out_free;
+ }
+
+ gsc->proxy.component_added = true;
+
+ return 0;
+
+out_free:
+ proxy_channel_free(gsc);
+ return err;
+}
+
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.h b/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.h
new file mode 100644
index 000000000000..fc5aef10bfb4
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef _INTEL_GSC_PROXY_H_
+#define _INTEL_GSC_PROXY_H_
+
+#include <linux/types.h>
+
+struct intel_gsc_uc;
+
+int intel_gsc_proxy_init(struct intel_gsc_uc *gsc);
+void intel_gsc_proxy_fini(struct intel_gsc_uc *gsc);
+int intel_gsc_proxy_request_handler(struct intel_gsc_uc *gsc);
+void intel_gsc_proxy_irq_handler(struct intel_gsc_uc *gsc, u32 iir);
+
+#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c
index 2d5b70b3384c..c659cc01f32f 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c
@@ -10,15 +10,79 @@
#include "intel_gsc_uc.h"
#include "intel_gsc_fw.h"
#include "i915_drv.h"
+#include "intel_gsc_proxy.h"
static void gsc_work(struct work_struct *work)
{
struct intel_gsc_uc *gsc = container_of(work, typeof(*gsc), work);
struct intel_gt *gt = gsc_uc_to_gt(gsc);
intel_wakeref_t wakeref;
+ u32 actions;
+ int ret;
+
+ wakeref = intel_runtime_pm_get(gt->uncore->rpm);
+
+ spin_lock_irq(gt->irq_lock);
+ actions = gsc->gsc_work_actions;
+ gsc->gsc_work_actions = 0;
+ spin_unlock_irq(gt->irq_lock);
+
+ if (actions & GSC_ACTION_FW_LOAD) {
+ ret = intel_gsc_uc_fw_upload(gsc);
+ if (!ret)
+ /* setup proxy on a new load */
+ actions |= GSC_ACTION_SW_PROXY;
+ else if (ret != -EEXIST)
+ goto out_put;
+
+ /*
+ * The HuC auth can be done both before or after the proxy init;
+ * if done after, a proxy request will be issued and must be
+ * serviced before the authentication can complete.
+ * Since this worker also handles proxy requests, we can't
+ * perform an action that requires the proxy from within it and
+ * then stall waiting for it, because we'd be blocking the
+ * service path. Therefore, it is easier for us to load HuC
+ * first and do proxy later. The GSC will ack the HuC auth and
+ * then send the HuC proxy request as part of the proxy init
+ * flow.
+ * Note that we can only do the GSC auth if the GuC auth was
+ * successful.
+ */
+ if (intel_uc_uses_huc(&gt->uc) &&
+ intel_huc_is_authenticated(&gt->uc.huc, INTEL_HUC_AUTH_BY_GUC))
+ intel_huc_auth(&gt->uc.huc, INTEL_HUC_AUTH_BY_GSC);
+ }
+
+ if (actions & GSC_ACTION_SW_PROXY) {
+ if (!intel_gsc_uc_fw_init_done(gsc)) {
+ gt_err(gt, "Proxy request received with GSC not loaded!\n");
+ goto out_put;
+ }
+
+ ret = intel_gsc_proxy_request_handler(gsc);
+ if (ret)
+ goto out_put;
+
+ /* mark the GSC FW init as done the first time we run this */
+ if (actions & GSC_ACTION_FW_LOAD) {
+ /*
+ * If there is a proxy establishment error, the GSC might still
+ * complete the request handling cleanly, so we need to check the
+ * status register to check if the proxy init was actually successful
+ */
+ if (intel_gsc_uc_fw_proxy_init_done(gsc)) {
+ drm_dbg(&gt->i915->drm, "GSC Proxy initialized\n");
+ intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_RUNNING);
+ } else {
+ drm_err(&gt->i915->drm,
+ "GSC status reports proxy init not complete\n");
+ }
+ }
+ }
- with_intel_runtime_pm(gt->uncore->rpm, wakeref)
- intel_gsc_uc_fw_upload(gsc);
+out_put:
+ intel_runtime_pm_put(gt->uncore->rpm, wakeref);
}
static bool gsc_engine_supported(struct intel_gt *gt)
@@ -43,17 +107,30 @@ static bool gsc_engine_supported(struct intel_gt *gt)
void intel_gsc_uc_init_early(struct intel_gsc_uc *gsc)
{
- intel_uc_fw_init_early(&gsc->fw, INTEL_UC_FW_TYPE_GSC);
+ struct intel_gt *gt = gsc_uc_to_gt(gsc);
+
+ /*
+ * GSC FW needs to be copied to a dedicated memory allocations for
+ * loading (see gsc->local), so we don't need to GGTT map the FW image
+ * itself into GGTT.
+ */
+ intel_uc_fw_init_early(&gsc->fw, INTEL_UC_FW_TYPE_GSC, false);
INIT_WORK(&gsc->work, gsc_work);
/* we can arrive here from i915_driver_early_probe for primary
* GT with it being not fully setup hence check device info's
* engine mask
*/
- if (!gsc_engine_supported(gsc_uc_to_gt(gsc))) {
+ if (!gsc_engine_supported(gt)) {
intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_NOT_SUPPORTED);
return;
}
+
+ gsc->wq = alloc_ordered_workqueue("i915_gsc", 0);
+ if (!gsc->wq) {
+ gt_err(gt, "failed to allocate WQ for GSC, disabling FW\n");
+ intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_NOT_SUPPORTED);
+ }
}
int intel_gsc_uc_init(struct intel_gsc_uc *gsc)
@@ -88,6 +165,9 @@ int intel_gsc_uc_init(struct intel_gsc_uc *gsc)
gsc->ce = ce;
+ /* if we fail to init proxy we still want to load GSC for PM */
+ intel_gsc_proxy_init(gsc);
+
intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOADABLE);
return 0;
@@ -107,6 +187,12 @@ void intel_gsc_uc_fini(struct intel_gsc_uc *gsc)
return;
flush_work(&gsc->work);
+ if (gsc->wq) {
+ destroy_workqueue(gsc->wq);
+ gsc->wq = NULL;
+ }
+
+ intel_gsc_proxy_fini(gsc);
if (gsc->ce)
intel_engine_destroy_pinned_context(fetch_and_zero(&gsc->ce));
@@ -145,11 +231,17 @@ void intel_gsc_uc_resume(struct intel_gsc_uc *gsc)
void intel_gsc_uc_load_start(struct intel_gsc_uc *gsc)
{
+ struct intel_gt *gt = gsc_uc_to_gt(gsc);
+
if (!intel_uc_fw_is_loadable(&gsc->fw))
return;
if (intel_gsc_uc_fw_init_done(gsc))
return;
- queue_work(system_unbound_wq, &gsc->work);
+ spin_lock_irq(gt->irq_lock);
+ gsc->gsc_work_actions |= GSC_ACTION_FW_LOAD;
+ spin_unlock_irq(gt->irq_lock);
+
+ queue_work(gsc->wq, &gsc->work);
}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h
index 5f50fa1ff8b9..a2a0813b8a76 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h
@@ -10,6 +10,7 @@
struct i915_vma;
struct intel_context;
+struct i915_gsc_proxy_component;
struct intel_gsc_uc {
/* Generic uC firmware management */
@@ -19,7 +20,21 @@ struct intel_gsc_uc {
struct i915_vma *local; /* private memory for GSC usage */
struct intel_context *ce; /* for submission to GSC FW via GSC engine */
- struct work_struct work; /* for delayed load */
+ /* for delayed load and proxy handling */
+ struct workqueue_struct *wq;
+ struct work_struct work;
+ u32 gsc_work_actions; /* protected by gt->irq_lock */
+#define GSC_ACTION_FW_LOAD BIT(0)
+#define GSC_ACTION_SW_PROXY BIT(1)
+
+ struct {
+ struct i915_gsc_proxy_component *component;
+ bool component_added;
+ struct i915_vma *vma;
+ void *to_gsc;
+ void *to_csme;
+ struct mutex mutex; /* protects the tee channel binding */
+ } proxy;
};
void intel_gsc_uc_init_early(struct intel_gsc_uc *gsc);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.c
index ea0da06e2f39..89ed5ee9cded 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.c
@@ -3,6 +3,7 @@
* Copyright © 2023 Intel Corporation
*/
+#include "gt/intel_context.h"
#include "gt/intel_engine_pm.h"
#include "gt/intel_gpu_commands.h"
#include "gt/intel_gt.h"
@@ -98,7 +99,7 @@ void intel_gsc_uc_heci_cmd_emit_mtl_header(struct intel_gsc_mtl_header *header,
u64 host_session_id)
{
host_session_id &= ~HOST_SESSION_MASK;
- if (heci_client_id == HECI_MEADDRESS_PXP)
+ if (host_session_id && heci_client_id == HECI_MEADDRESS_PXP)
host_session_id |= HOST_SESSION_PXP_SINGLE;
header->validity_marker = GSC_HECI_VALIDITY_MARKER;
@@ -107,3 +108,104 @@ void intel_gsc_uc_heci_cmd_emit_mtl_header(struct intel_gsc_mtl_header *header,
header->header_version = MTL_GSC_HEADER_VERSION;
header->message_size = message_size;
}
+
+static void
+emit_gsc_heci_pkt_nonpriv(u32 *cmd, struct intel_gsc_heci_non_priv_pkt *pkt)
+{
+ *cmd++ = GSC_HECI_CMD_PKT;
+ *cmd++ = lower_32_bits(pkt->addr_in);
+ *cmd++ = upper_32_bits(pkt->addr_in);
+ *cmd++ = pkt->size_in;
+ *cmd++ = lower_32_bits(pkt->addr_out);
+ *cmd++ = upper_32_bits(pkt->addr_out);
+ *cmd++ = pkt->size_out;
+ *cmd++ = 0;
+ *cmd++ = MI_BATCH_BUFFER_END;
+}
+
+int
+intel_gsc_uc_heci_cmd_submit_nonpriv(struct intel_gsc_uc *gsc,
+ struct intel_context *ce,
+ struct intel_gsc_heci_non_priv_pkt *pkt,
+ u32 *cmd, int timeout_ms)
+{
+ struct intel_engine_cs *engine;
+ struct i915_gem_ww_ctx ww;
+ struct i915_request *rq;
+ int err, trials = 0;
+
+ i915_gem_ww_ctx_init(&ww, false);
+retry:
+ err = i915_gem_object_lock(pkt->bb_vma->obj, &ww);
+ if (err)
+ goto out_ww;
+ err = i915_gem_object_lock(pkt->heci_pkt_vma->obj, &ww);
+ if (err)
+ goto out_ww;
+ err = intel_context_pin_ww(ce, &ww);
+ if (err)
+ goto out_ww;
+
+ rq = i915_request_create(ce);
+ if (IS_ERR(rq)) {
+ err = PTR_ERR(rq);
+ goto out_unpin_ce;
+ }
+
+ emit_gsc_heci_pkt_nonpriv(cmd, pkt);
+
+ err = i915_vma_move_to_active(pkt->bb_vma, rq, 0);
+ if (err)
+ goto out_rq;
+ err = i915_vma_move_to_active(pkt->heci_pkt_vma, rq, EXEC_OBJECT_WRITE);
+ if (err)
+ goto out_rq;
+
+ engine = rq->context->engine;
+ if (engine->emit_init_breadcrumb) {
+ err = engine->emit_init_breadcrumb(rq);
+ if (err)
+ goto out_rq;
+ }
+
+ err = engine->emit_bb_start(rq, i915_vma_offset(pkt->bb_vma), PAGE_SIZE, 0);
+ if (err)
+ goto out_rq;
+
+ err = ce->engine->emit_flush(rq, 0);
+ if (err)
+ drm_err(&gsc_uc_to_gt(gsc)->i915->drm,
+ "Failed emit-flush for gsc-heci-non-priv-pkterr=%d\n", err);
+
+out_rq:
+ i915_request_get(rq);
+
+ if (unlikely(err))
+ i915_request_set_error_once(rq, err);
+
+ i915_request_add(rq);
+
+ if (!err) {
+ if (i915_request_wait(rq, I915_WAIT_INTERRUPTIBLE,
+ msecs_to_jiffies(timeout_ms)) < 0)
+ err = -ETIME;
+ }
+
+ i915_request_put(rq);
+
+out_unpin_ce:
+ intel_context_unpin(ce);
+out_ww:
+ if (err == -EDEADLK) {
+ err = i915_gem_ww_ctx_backoff(&ww);
+ if (!err) {
+ if (++trials < 10)
+ goto retry;
+ else
+ err = -EAGAIN;
+ }
+ }
+ i915_gem_ww_ctx_fini(&ww);
+
+ return err;
+}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.h b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.h
index 3d56ae501991..ef70e304904a 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.h
@@ -8,12 +8,16 @@
#include <linux/types.h>
+struct i915_vma;
+struct intel_context;
struct intel_gsc_uc;
+
struct intel_gsc_mtl_header {
u32 validity_marker;
#define GSC_HECI_VALIDITY_MARKER 0xA578875A
u8 heci_client_id;
+#define HECI_MEADDRESS_PROXY 10
#define HECI_MEADDRESS_PXP 17
#define HECI_MEADDRESS_HDCP 18
@@ -47,7 +51,8 @@ struct intel_gsc_mtl_header {
* we distinguish the flags using OUTFLAG or INFLAG
*/
u32 flags;
-#define GSC_OUTFLAG_MSG_PENDING 1
+#define GSC_OUTFLAG_MSG_PENDING BIT(0)
+#define GSC_INFLAG_MSG_CLEANUP BIT(1)
u32 status;
} __packed;
@@ -58,4 +63,24 @@ int intel_gsc_uc_heci_cmd_submit_packet(struct intel_gsc_uc *gsc,
void intel_gsc_uc_heci_cmd_emit_mtl_header(struct intel_gsc_mtl_header *header,
u8 heci_client_id, u32 message_size,
u64 host_session_id);
+
+struct intel_gsc_heci_non_priv_pkt {
+ u64 addr_in;
+ u32 size_in;
+ u64 addr_out;
+ u32 size_out;
+ struct i915_vma *heci_pkt_vma;
+ struct i915_vma *bb_vma;
+};
+
+void
+intel_gsc_uc_heci_cmd_emit_mtl_header(struct intel_gsc_mtl_header *header,
+ u8 heci_client_id, u32 msg_size,
+ u64 host_session_id);
+
+int
+intel_gsc_uc_heci_cmd_submit_nonpriv(struct intel_gsc_uc *gsc,
+ struct intel_context *ce,
+ struct intel_gsc_heci_non_priv_pkt *pkt,
+ u32 *cs, int timeout_ms);
#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index d76508fa3af7..2eb891b270ae 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -16,6 +16,7 @@
#include "intel_guc_submission.h"
#include "i915_drv.h"
#include "i915_irq.h"
+#include "i915_reg.h"
/**
* DOC: GuC
@@ -163,7 +164,7 @@ void intel_guc_init_early(struct intel_guc *guc)
struct intel_gt *gt = guc_to_gt(guc);
struct drm_i915_private *i915 = gt->i915;
- intel_uc_fw_init_early(&guc->fw, INTEL_UC_FW_TYPE_GUC);
+ intel_uc_fw_init_early(&guc->fw, INTEL_UC_FW_TYPE_GUC, true);
intel_guc_ct_init_early(&guc->ct);
intel_guc_log_init_early(&guc->log);
intel_guc_submission_init_early(guc);
@@ -743,6 +744,13 @@ struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size)
if (IS_ERR(obj))
return ERR_CAST(obj);
+ /*
+ * Wa_22016122933: For MTL the shared memory needs to be mapped
+ * as WC on CPU side and UC (PAT index 2) on GPU side
+ */
+ if (IS_METEORLAKE(gt->i915))
+ i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
+
vma = i915_vma_instance(obj, &gt->ggtt->vm, NULL);
if (IS_ERR(vma))
goto err;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index e46aac1a41e6..8dc291ff0093 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -42,6 +42,7 @@ struct intel_guc {
/** @capture: the error-state-capture module's data and objects */
struct intel_guc_state_capture *capture;
+ /** @dbgfs_node: debugfs node */
struct dentry *dbgfs_node;
/** @sched_engine: Global engine used to submit requests to GuC */
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
index 69ce06faf8cd..63724e17829a 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -643,6 +643,39 @@ static void guc_init_golden_context(struct intel_guc *guc)
GEM_BUG_ON(guc->ads_golden_ctxt_size != total_size);
}
+static u32 guc_get_capture_engine_mask(struct iosys_map *info_map, u32 capture_class)
+{
+ u32 mask;
+
+ switch (capture_class) {
+ case GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE:
+ mask = info_map_read(info_map, engine_enabled_masks[GUC_RENDER_CLASS]);
+ mask |= info_map_read(info_map, engine_enabled_masks[GUC_COMPUTE_CLASS]);
+ break;
+
+ case GUC_CAPTURE_LIST_CLASS_VIDEO:
+ mask = info_map_read(info_map, engine_enabled_masks[GUC_VIDEO_CLASS]);
+ break;
+
+ case GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE:
+ mask = info_map_read(info_map, engine_enabled_masks[GUC_VIDEOENHANCE_CLASS]);
+ break;
+
+ case GUC_CAPTURE_LIST_CLASS_BLITTER:
+ mask = info_map_read(info_map, engine_enabled_masks[GUC_BLITTER_CLASS]);
+ break;
+
+ case GUC_CAPTURE_LIST_CLASS_GSC_OTHER:
+ mask = info_map_read(info_map, engine_enabled_masks[GUC_GSC_OTHER_CLASS]);
+ break;
+
+ default:
+ mask = 0;
+ }
+
+ return mask;
+}
+
static int
guc_capture_prep_lists(struct intel_guc *guc)
{
@@ -678,9 +711,10 @@ guc_capture_prep_lists(struct intel_guc *guc)
for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) {
for (j = 0; j < GUC_MAX_ENGINE_CLASSES; j++) {
+ u32 engine_mask = guc_get_capture_engine_mask(&info_map, j);
/* null list if we dont have said engine or list */
- if (!info_map_read(&info_map, engine_enabled_masks[j])) {
+ if (!engine_mask) {
if (ads_is_mapped) {
ads_blob_write(guc, ads.capture_class[i][j], null_ggtt);
ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
index e0e793167d61..331cec07c125 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
@@ -30,12 +30,12 @@
#define COMMON_BASE_GLOBAL \
{ FORCEWAKE_MT, 0, 0, "FORCEWAKE" }
-#define COMMON_GEN9BASE_GLOBAL \
+#define COMMON_GEN8BASE_GLOBAL \
{ ERROR_GEN6, 0, 0, "ERROR_GEN6" }, \
{ DONE_REG, 0, 0, "DONE_REG" }, \
{ HSW_GTT_CACHE_EN, 0, 0, "HSW_GTT_CACHE_EN" }
-#define GEN9_GLOBAL \
+#define GEN8_GLOBAL \
{ GEN8_FAULT_TLB_DATA0, 0, 0, "GEN8_FAULT_TLB_DATA0" }, \
{ GEN8_FAULT_TLB_DATA1, 0, 0, "GEN8_FAULT_TLB_DATA1" }
@@ -96,67 +96,65 @@
{ GEN12_SFC_DONE(2), 0, 0, "SFC_DONE[2]" }, \
{ GEN12_SFC_DONE(3), 0, 0, "SFC_DONE[3]" }
-/* XE_LPD - Global */
-static const struct __guc_mmio_reg_descr xe_lpd_global_regs[] = {
+/* XE_LP Global */
+static const struct __guc_mmio_reg_descr xe_lp_global_regs[] = {
COMMON_BASE_GLOBAL,
- COMMON_GEN9BASE_GLOBAL,
+ COMMON_GEN8BASE_GLOBAL,
COMMON_GEN12BASE_GLOBAL,
};
-/* XE_LPD - Render / Compute Per-Class */
-static const struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = {
+/* XE_LP Render / Compute Per-Class */
+static const struct __guc_mmio_reg_descr xe_lp_rc_class_regs[] = {
COMMON_BASE_HAS_EU,
COMMON_BASE_RENDER,
COMMON_GEN12BASE_RENDER,
};
-/* GEN9/XE_LPD - Render / Compute Per-Engine-Instance */
-static const struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = {
+/* GEN8+ Render / Compute Per-Engine-Instance */
+static const struct __guc_mmio_reg_descr gen8_rc_inst_regs[] = {
COMMON_BASE_ENGINE_INSTANCE,
};
-/* GEN9/XE_LPD - Media Decode/Encode Per-Engine-Instance */
-static const struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = {
+/* GEN8+ Media Decode/Encode Per-Engine-Instance */
+static const struct __guc_mmio_reg_descr gen8_vd_inst_regs[] = {
COMMON_BASE_ENGINE_INSTANCE,
};
-/* XE_LPD - Video Enhancement Per-Class */
-static const struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = {
+/* XE_LP Video Enhancement Per-Class */
+static const struct __guc_mmio_reg_descr xe_lp_vec_class_regs[] = {
COMMON_GEN12BASE_VEC,
};
-/* GEN9/XE_LPD - Video Enhancement Per-Engine-Instance */
-static const struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = {
+/* GEN8+ Video Enhancement Per-Engine-Instance */
+static const struct __guc_mmio_reg_descr gen8_vec_inst_regs[] = {
COMMON_BASE_ENGINE_INSTANCE,
};
-/* GEN9/XE_LPD - Blitter Per-Engine-Instance */
-static const struct __guc_mmio_reg_descr xe_lpd_blt_inst_regs[] = {
+/* GEN8+ Blitter Per-Engine-Instance */
+static const struct __guc_mmio_reg_descr gen8_blt_inst_regs[] = {
COMMON_BASE_ENGINE_INSTANCE,
};
-/* XE_LPD - GSC Per-Engine-Instance */
-static const struct __guc_mmio_reg_descr xe_lpd_gsc_inst_regs[] = {
+/* XE_LP - GSC Per-Engine-Instance */
+static const struct __guc_mmio_reg_descr xe_lp_gsc_inst_regs[] = {
COMMON_BASE_ENGINE_INSTANCE,
};
-/* GEN9 - Global */
-static const struct __guc_mmio_reg_descr default_global_regs[] = {
+/* GEN8 - Global */
+static const struct __guc_mmio_reg_descr gen8_global_regs[] = {
COMMON_BASE_GLOBAL,
- COMMON_GEN9BASE_GLOBAL,
- GEN9_GLOBAL,
+ COMMON_GEN8BASE_GLOBAL,
+ GEN8_GLOBAL,
};
-static const struct __guc_mmio_reg_descr default_rc_class_regs[] = {
+static const struct __guc_mmio_reg_descr gen8_rc_class_regs[] = {
COMMON_BASE_HAS_EU,
COMMON_BASE_RENDER,
};
/*
- * Empty lists:
- * GEN9/XE_LPD - Blitter Per-Class
- * GEN9/XE_LPD - Media Decode/Encode Per-Class
- * GEN9 - VEC Class
+ * Empty list to prevent warnings about unknown class/instance types
+ * as not all class/instanace types have entries on all platforms.
*/
static const struct __guc_mmio_reg_descr empty_regs_list[] = {
};
@@ -174,37 +172,33 @@ static const struct __guc_mmio_reg_descr empty_regs_list[] = {
}
/* List of lists */
-static const struct __guc_mmio_reg_descr_group default_lists[] = {
- MAKE_REGLIST(default_global_regs, PF, GLOBAL, 0),
- MAKE_REGLIST(default_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS),
- MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS),
- MAKE_REGLIST(default_rc_class_regs, PF, ENGINE_CLASS, GUC_COMPUTE_CLASS),
- MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_COMPUTE_CLASS),
- MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS),
- MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS),
- MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS),
- MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS),
- MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS),
- MAKE_REGLIST(xe_lpd_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS),
- MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_GSC_OTHER_CLASS),
- MAKE_REGLIST(xe_lpd_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_GSC_OTHER_CLASS),
+static const struct __guc_mmio_reg_descr_group gen8_lists[] = {
+ MAKE_REGLIST(gen8_global_regs, PF, GLOBAL, 0),
+ MAKE_REGLIST(gen8_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE),
+ MAKE_REGLIST(gen8_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE),
+ MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO),
+ MAKE_REGLIST(gen8_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO),
+ MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE),
+ MAKE_REGLIST(gen8_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE),
+ MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER),
+ MAKE_REGLIST(gen8_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER),
+ MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER),
+ MAKE_REGLIST(empty_regs_list, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER),
{}
};
-static const struct __guc_mmio_reg_descr_group xe_lpd_lists[] = {
- MAKE_REGLIST(xe_lpd_global_regs, PF, GLOBAL, 0),
- MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS),
- MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS),
- MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_COMPUTE_CLASS),
- MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_COMPUTE_CLASS),
- MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS),
- MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS),
- MAKE_REGLIST(xe_lpd_vec_class_regs, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS),
- MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS),
- MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS),
- MAKE_REGLIST(xe_lpd_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS),
- MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_GSC_OTHER_CLASS),
- MAKE_REGLIST(xe_lpd_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_GSC_OTHER_CLASS),
+static const struct __guc_mmio_reg_descr_group xe_lp_lists[] = {
+ MAKE_REGLIST(xe_lp_global_regs, PF, GLOBAL, 0),
+ MAKE_REGLIST(xe_lp_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE),
+ MAKE_REGLIST(gen8_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE),
+ MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO),
+ MAKE_REGLIST(gen8_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO),
+ MAKE_REGLIST(xe_lp_vec_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE),
+ MAKE_REGLIST(gen8_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE),
+ MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER),
+ MAKE_REGLIST(gen8_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER),
+ MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER),
+ MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER),
{}
};
@@ -260,11 +254,15 @@ struct __ext_steer_reg {
i915_mcr_reg_t reg;
};
-static const struct __ext_steer_reg xe_extregs[] = {
+static const struct __ext_steer_reg gen8_extregs[] = {
{"GEN8_SAMPLER_INSTDONE", GEN8_SAMPLER_INSTDONE},
{"GEN8_ROW_INSTDONE", GEN8_ROW_INSTDONE}
};
+static const struct __ext_steer_reg xehpg_extregs[] = {
+ {"XEHPG_INSTDONE_GEOM_SVG", XEHPG_INSTDONE_GEOM_SVG}
+};
+
static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext,
const struct __ext_steer_reg *extlist,
int slice_id, int subslice_id)
@@ -295,86 +293,30 @@ __alloc_ext_regs(struct __guc_mmio_reg_descr_group *newlist,
}
static void
-guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc,
- const struct __guc_mmio_reg_descr_group *lists)
+guc_capture_alloc_steered_lists(struct intel_guc *guc,
+ const struct __guc_mmio_reg_descr_group *lists)
{
struct intel_gt *gt = guc_to_gt(guc);
int slice, subslice, iter, i, num_steer_regs, num_tot_regs = 0;
const struct __guc_mmio_reg_descr_group *list;
struct __guc_mmio_reg_descr_group *extlists;
struct __guc_mmio_reg_descr *extarray;
- struct sseu_dev_info *sseu;
+ bool has_xehpg_extregs;
- /* In XE_LPD we only have steered registers for the render-class */
+ /* steered registers currently only exist for the render-class */
list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF,
- GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS);
+ GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS,
+ GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE);
/* skip if extlists was previously allocated */
if (!list || guc->capture->extlists)
return;
- num_steer_regs = ARRAY_SIZE(xe_extregs);
-
- sseu = &gt->info.sseu;
- for_each_ss_steering(iter, gt, slice, subslice)
- num_tot_regs += num_steer_regs;
-
- if (!num_tot_regs)
- return;
-
- /* allocate an extra for an end marker */
- extlists = kcalloc(2, sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL);
- if (!extlists)
- return;
-
- if (__alloc_ext_regs(&extlists[0], list, num_tot_regs)) {
- kfree(extlists);
- return;
- }
-
- extarray = extlists[0].extlist;
- for_each_ss_steering(iter, gt, slice, subslice) {
- for (i = 0; i < num_steer_regs; ++i) {
- __fill_ext_reg(extarray, &xe_extregs[i], slice, subslice);
- ++extarray;
- }
- }
-
- guc->capture->extlists = extlists;
-}
-
-static const struct __ext_steer_reg xehpg_extregs[] = {
- {"XEHPG_INSTDONE_GEOM_SVG", XEHPG_INSTDONE_GEOM_SVG}
-};
-
-static bool __has_xehpg_extregs(u32 ipver)
-{
- return (ipver >= IP_VER(12, 55));
-}
-
-static void
-guc_capture_alloc_steered_lists_xe_hpg(struct intel_guc *guc,
- const struct __guc_mmio_reg_descr_group *lists,
- u32 ipver)
-{
- struct intel_gt *gt = guc_to_gt(guc);
- struct sseu_dev_info *sseu;
- int slice, subslice, i, iter, num_steer_regs, num_tot_regs = 0;
- const struct __guc_mmio_reg_descr_group *list;
- struct __guc_mmio_reg_descr_group *extlists;
- struct __guc_mmio_reg_descr *extarray;
-
- /* In XE_LP / HPG we only have render-class steering registers during error-capture */
- list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF,
- GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS);
- /* skip if extlists was previously allocated */
- if (!list || guc->capture->extlists)
- return;
+ has_xehpg_extregs = GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 55);
- num_steer_regs = ARRAY_SIZE(xe_extregs);
- if (__has_xehpg_extregs(ipver))
+ num_steer_regs = ARRAY_SIZE(gen8_extregs);
+ if (has_xehpg_extregs)
num_steer_regs += ARRAY_SIZE(xehpg_extregs);
- sseu = &gt->info.sseu;
for_each_ss_steering(iter, gt, slice, subslice)
num_tot_regs += num_steer_regs;
@@ -393,11 +335,12 @@ guc_capture_alloc_steered_lists_xe_hpg(struct intel_guc *guc,
extarray = extlists[0].extlist;
for_each_ss_steering(iter, gt, slice, subslice) {
- for (i = 0; i < ARRAY_SIZE(xe_extregs); ++i) {
- __fill_ext_reg(extarray, &xe_extregs[i], slice, subslice);
+ for (i = 0; i < ARRAY_SIZE(gen8_extregs); ++i) {
+ __fill_ext_reg(extarray, &gen8_extregs[i], slice, subslice);
++extarray;
}
- if (__has_xehpg_extregs(ipver)) {
+
+ if (has_xehpg_extregs) {
for (i = 0; i < ARRAY_SIZE(xehpg_extregs); ++i) {
__fill_ext_reg(extarray, &xehpg_extregs[i], slice, subslice);
++extarray;
@@ -413,26 +356,22 @@ static const struct __guc_mmio_reg_descr_group *
guc_capture_get_device_reglist(struct intel_guc *guc)
{
struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
+ const struct __guc_mmio_reg_descr_group *lists;
- if (GRAPHICS_VER(i915) > 11) {
- /*
- * For certain engine classes, there are slice and subslice
- * level registers requiring steering. We allocate and populate
- * these at init time based on hw config add it as an extension
- * list at the end of the pre-populated render list.
- */
- if (IS_DG2(i915))
- guc_capture_alloc_steered_lists_xe_hpg(guc, xe_lpd_lists, IP_VER(12, 55));
- else if (IS_XEHPSDV(i915))
- guc_capture_alloc_steered_lists_xe_hpg(guc, xe_lpd_lists, IP_VER(12, 50));
- else
- guc_capture_alloc_steered_lists_xe_lpd(guc, xe_lpd_lists);
+ if (GRAPHICS_VER(i915) >= 12)
+ lists = xe_lp_lists;
+ else
+ lists = gen8_lists;
- return xe_lpd_lists;
- }
+ /*
+ * For certain engine classes, there are slice and subslice
+ * level registers requiring steering. We allocate and populate
+ * these at init time based on hw config add it as an extension
+ * list at the end of the pre-populated render list.
+ */
+ guc_capture_alloc_steered_lists(guc, lists);
- /* if GuC submission is enabled on a non-POR platform, just use a common baseline */
- return default_lists;
+ return lists;
}
static const char *
@@ -456,17 +395,15 @@ static const char *
__stringify_engclass(u32 class)
{
switch (class) {
- case GUC_RENDER_CLASS:
- return "Render";
- case GUC_VIDEO_CLASS:
+ case GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE:
+ return "Render/Compute";
+ case GUC_CAPTURE_LIST_CLASS_VIDEO:
return "Video";
- case GUC_VIDEOENHANCE_CLASS:
+ case GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE:
return "VideoEnhance";
- case GUC_BLITTER_CLASS:
+ case GUC_CAPTURE_LIST_CLASS_BLITTER:
return "Blitter";
- case GUC_COMPUTE_CLASS:
- return "Compute";
- case GUC_GSC_OTHER_CLASS:
+ case GUC_CAPTURE_LIST_CLASS_GSC_OTHER:
return "GSC-Other";
default:
break;
@@ -1596,6 +1533,36 @@ void intel_guc_capture_free_node(struct intel_engine_coredump *ee)
ee->guc_capture_node = NULL;
}
+bool intel_guc_capture_is_matching_engine(struct intel_gt *gt,
+ struct intel_context *ce,
+ struct intel_engine_cs *engine)
+{
+ struct __guc_capture_parsed_output *n;
+ struct intel_guc *guc;
+
+ if (!gt || !ce || !engine)
+ return false;
+
+ guc = &gt->uc.guc;
+ if (!guc->capture)
+ return false;
+
+ /*
+ * Look for a matching GuC reported error capture node from
+ * the internal output link-list based on lrca, guc-id and engine
+ * identification.
+ */
+ list_for_each_entry(n, &guc->capture->outlist, link) {
+ if (n->eng_inst == GUC_ID_TO_ENGINE_INSTANCE(engine->guc_id) &&
+ n->eng_class == GUC_ID_TO_ENGINE_CLASS(engine->guc_id) &&
+ n->guc_id == ce->guc_id.id &&
+ (n->lrca & CTX_GTT_ADDRESS_MASK) == (ce->lrc.lrca & CTX_GTT_ADDRESS_MASK))
+ return true;
+ }
+
+ return false;
+}
+
void intel_guc_capture_get_matching_node(struct intel_gt *gt,
struct intel_engine_coredump *ee,
struct intel_context *ce)
@@ -1611,6 +1578,7 @@ void intel_guc_capture_get_matching_node(struct intel_gt *gt,
return;
GEM_BUG_ON(ee->guc_capture_node);
+
/*
* Look for a matching GuC reported error capture node from
* the internal output link-list based on lrca, guc-id and engine
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h
index fbd3713c7832..302256d45431 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h
@@ -11,6 +11,7 @@
struct drm_i915_error_state_buf;
struct guc_gt_system_info;
struct intel_engine_coredump;
+struct intel_engine_cs;
struct intel_context;
struct intel_gt;
struct intel_guc;
@@ -20,6 +21,8 @@ int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *m,
const struct intel_engine_coredump *ee);
void intel_guc_capture_get_matching_node(struct intel_gt *gt, struct intel_engine_coredump *ee,
struct intel_context *ce);
+bool intel_guc_capture_is_matching_engine(struct intel_gt *gt, struct intel_context *ce,
+ struct intel_engine_cs *engine);
void intel_guc_capture_process(struct intel_guc *guc);
int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
void **outptr);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
index 1803a633ed64..f28a3a83742d 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
@@ -13,6 +13,30 @@
#include "intel_guc_ct.h"
#include "intel_guc_print.h"
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
+enum {
+ CT_DEAD_ALIVE = 0,
+ CT_DEAD_SETUP,
+ CT_DEAD_WRITE,
+ CT_DEAD_DEADLOCK,
+ CT_DEAD_H2G_HAS_ROOM,
+ CT_DEAD_READ,
+ CT_DEAD_PROCESS_FAILED,
+};
+
+static void ct_dead_ct_worker_func(struct work_struct *w);
+
+#define CT_DEAD(ct, reason) \
+ do { \
+ if (!(ct)->dead_ct_reported) { \
+ (ct)->dead_ct_reason |= 1 << CT_DEAD_##reason; \
+ queue_work(system_unbound_wq, &(ct)->dead_ct_worker); \
+ } \
+ } while (0)
+#else
+#define CT_DEAD(ct, reason) do { } while (0)
+#endif
+
static inline struct intel_guc *ct_to_guc(struct intel_guc_ct *ct)
{
return container_of(ct, struct intel_guc, ct);
@@ -93,6 +117,9 @@ void intel_guc_ct_init_early(struct intel_guc_ct *ct)
spin_lock_init(&ct->requests.lock);
INIT_LIST_HEAD(&ct->requests.pending);
INIT_LIST_HEAD(&ct->requests.incoming);
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
+ INIT_WORK(&ct->dead_ct_worker, ct_dead_ct_worker_func);
+#endif
INIT_WORK(&ct->requests.worker, ct_incoming_request_worker_func);
tasklet_setup(&ct->receive_tasklet, ct_receive_tasklet_func);
init_waitqueue_head(&ct->wq);
@@ -319,11 +346,16 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct)
ct->enabled = true;
ct->stall_time = KTIME_MAX;
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
+ ct->dead_ct_reported = false;
+ ct->dead_ct_reason = CT_DEAD_ALIVE;
+#endif
return 0;
err_out:
CT_PROBE_ERROR(ct, "Failed to enable CTB (%pe)\n", ERR_PTR(err));
+ CT_DEAD(ct, SETUP);
return err;
}
@@ -344,6 +376,24 @@ void intel_guc_ct_disable(struct intel_guc_ct *ct)
}
}
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+static void ct_track_lost_and_found(struct intel_guc_ct *ct, u32 fence, u32 action)
+{
+ unsigned int lost = fence % ARRAY_SIZE(ct->requests.lost_and_found);
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
+ unsigned long entries[SZ_32];
+ unsigned int n;
+
+ n = stack_trace_save(entries, ARRAY_SIZE(entries), 1);
+
+ /* May be called under spinlock, so avoid sleeping */
+ ct->requests.lost_and_found[lost].stack = stack_depot_save(entries, n, GFP_NOWAIT);
+#endif
+ ct->requests.lost_and_found[lost].fence = fence;
+ ct->requests.lost_and_found[lost].action = action;
+}
+#endif
+
static u32 ct_get_next_fence(struct intel_guc_ct *ct)
{
/* For now it's trivial */
@@ -394,11 +444,11 @@ static int ct_write(struct intel_guc_ct *ct,
FIELD_PREP(GUC_CTB_MSG_0_NUM_DWORDS, len) |
FIELD_PREP(GUC_CTB_MSG_0_FENCE, fence);
- type = (flags & INTEL_GUC_CT_SEND_NB) ? GUC_HXG_TYPE_EVENT :
+ type = (flags & INTEL_GUC_CT_SEND_NB) ? GUC_HXG_TYPE_FAST_REQUEST :
GUC_HXG_TYPE_REQUEST;
hxg = FIELD_PREP(GUC_HXG_MSG_0_TYPE, type) |
- FIELD_PREP(GUC_HXG_EVENT_MSG_0_ACTION |
- GUC_HXG_EVENT_MSG_0_DATA0, action[0]);
+ FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION |
+ GUC_HXG_REQUEST_MSG_0_DATA0, action[0]);
CT_DEBUG(ct, "writing (tail %u) %*ph %*ph %*ph\n",
tail, 4, &header, 4, &hxg, 4 * (len - 1), &action[1]);
@@ -415,6 +465,11 @@ static int ct_write(struct intel_guc_ct *ct,
}
GEM_BUG_ON(tail > size);
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+ ct_track_lost_and_found(ct, fence,
+ FIELD_GET(GUC_HXG_EVENT_MSG_0_ACTION, action[0]));
+#endif
+
/*
* make sure H2G buffer update and LRC tail update (if this triggering a
* submission) are visible before updating the descriptor tail
@@ -434,6 +489,7 @@ static int ct_write(struct intel_guc_ct *ct,
corrupted:
CT_ERROR(ct, "Corrupted descriptor head=%u tail=%u status=%#x\n",
desc->head, desc->tail, desc->status);
+ CT_DEAD(ct, WRITE);
ctb->broken = true;
return -EPIPE;
}
@@ -504,6 +560,7 @@ static inline bool ct_deadlocked(struct intel_guc_ct *ct)
CT_ERROR(ct, "Head: %u\n (Dwords)", ct->ctbs.recv.desc->head);
CT_ERROR(ct, "Tail: %u\n (Dwords)", ct->ctbs.recv.desc->tail);
+ CT_DEAD(ct, DEADLOCK);
ct->ctbs.send.broken = true;
}
@@ -552,6 +609,7 @@ static inline bool h2g_has_room(struct intel_guc_ct *ct, u32 len_dw)
head, ctb->size);
desc->status |= GUC_CTB_STATUS_OVERFLOW;
ctb->broken = true;
+ CT_DEAD(ct, H2G_HAS_ROOM);
return false;
}
@@ -640,7 +698,7 @@ static int ct_send(struct intel_guc_ct *ct,
GEM_BUG_ON(!ct->enabled);
GEM_BUG_ON(!len);
- GEM_BUG_ON(len & ~GUC_CT_MSG_LEN_MASK);
+ GEM_BUG_ON(len > GUC_CTB_HXG_MSG_MAX_LEN - GUC_CTB_HDR_LEN);
GEM_BUG_ON(!response_buf && response_buf_size);
might_sleep();
@@ -902,15 +960,59 @@ static int ct_read(struct intel_guc_ct *ct, struct ct_incoming_msg **msg)
/* now update descriptor */
WRITE_ONCE(desc->head, head);
+ /*
+ * Wa_22016122933: Making sure the head update is
+ * visible to GuC right away
+ */
+ intel_guc_write_barrier(ct_to_guc(ct));
+
return available - len;
corrupted:
CT_ERROR(ct, "Corrupted descriptor head=%u tail=%u status=%#x\n",
desc->head, desc->tail, desc->status);
ctb->broken = true;
+ CT_DEAD(ct, READ);
return -EPIPE;
}
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+static bool ct_check_lost_and_found(struct intel_guc_ct *ct, u32 fence)
+{
+ unsigned int n;
+ char *buf = NULL;
+ bool found = false;
+
+ lockdep_assert_held(&ct->requests.lock);
+
+ for (n = 0; n < ARRAY_SIZE(ct->requests.lost_and_found); n++) {
+ if (ct->requests.lost_and_found[n].fence != fence)
+ continue;
+ found = true;
+
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
+ buf = kmalloc(SZ_4K, GFP_NOWAIT);
+ if (buf && stack_depot_snprint(ct->requests.lost_and_found[n].stack,
+ buf, SZ_4K, 0)) {
+ CT_ERROR(ct, "Fence %u was used by action %#04x sent at\n%s",
+ fence, ct->requests.lost_and_found[n].action, buf);
+ break;
+ }
+#endif
+ CT_ERROR(ct, "Fence %u was used by action %#04x\n",
+ fence, ct->requests.lost_and_found[n].action);
+ break;
+ }
+ kfree(buf);
+ return found;
+}
+#else
+static bool ct_check_lost_and_found(struct intel_guc_ct *ct, u32 fence)
+{
+ return false;
+}
+#endif
+
static int ct_handle_response(struct intel_guc_ct *ct, struct ct_incoming_msg *response)
{
u32 len = FIELD_GET(GUC_CTB_MSG_0_NUM_DWORDS, response->msg[0]);
@@ -952,12 +1054,13 @@ static int ct_handle_response(struct intel_guc_ct *ct, struct ct_incoming_msg *r
break;
}
if (!found) {
- CT_ERROR(ct, "Unsolicited response (fence %u)\n", fence);
- CT_ERROR(ct, "Could not find fence=%u, last_fence=%u\n", fence,
- ct->requests.last_fence);
- list_for_each_entry(req, &ct->requests.pending, link)
- CT_ERROR(ct, "request %u awaits response\n",
- req->fence);
+ CT_ERROR(ct, "Unsolicited response message: len %u, data %#x (fence %u, last %u)\n",
+ len, hxg[0], fence, ct->requests.last_fence);
+ if (!ct_check_lost_and_found(ct, fence)) {
+ list_for_each_entry(req, &ct->requests.pending, link)
+ CT_ERROR(ct, "request %u awaits response\n",
+ req->fence);
+ }
err = -ENOKEY;
}
spin_unlock_irqrestore(&ct->requests.lock, flags);
@@ -1057,6 +1160,7 @@ static bool ct_process_incoming_requests(struct intel_guc_ct *ct)
if (unlikely(err)) {
CT_ERROR(ct, "Failed to process CT message (%pe) %*ph\n",
ERR_PTR(err), 4 * request->size, request->msg);
+ CT_DEAD(ct, PROCESS_FAILED);
ct_free_msg(request);
}
@@ -1233,3 +1337,19 @@ void intel_guc_ct_print_info(struct intel_guc_ct *ct,
drm_printf(p, "Tail: %u\n",
ct->ctbs.recv.desc->tail);
}
+
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
+static void ct_dead_ct_worker_func(struct work_struct *w)
+{
+ struct intel_guc_ct *ct = container_of(w, struct intel_guc_ct, dead_ct_worker);
+ struct intel_guc *guc = ct_to_guc(ct);
+
+ if (ct->dead_ct_reported)
+ return;
+
+ ct->dead_ct_reported = true;
+
+ guc_info(guc, "CTB is dead - reason=0x%X\n", ct->dead_ct_reason);
+ intel_klog_error_capture(guc_to_gt(guc), (intel_engine_mask_t)~0U);
+}
+#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
index f709a19c7e21..58e42901ff49 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
@@ -8,6 +8,7 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
+#include <linux/stackdepot.h>
#include <linux/workqueue.h>
#include <linux/ktime.h>
#include <linux/wait.h>
@@ -81,10 +82,26 @@ struct intel_guc_ct {
struct list_head incoming; /* incoming requests */
struct work_struct worker; /* handler for incoming requests */
+
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+ struct {
+ u16 fence;
+ u16 action;
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
+ depot_stack_handle_t stack;
+#endif
+ } lost_and_found[SZ_16];
+#endif
} requests;
/** @stall_time: time of first time a CTB submission is stalled */
ktime_t stall_time;
+
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
+ int dead_ct_reason;
+ bool dead_ct_reported;
+ struct work_struct dead_ct_worker;
+#endif
};
void intel_guc_ct_init_early(struct intel_guc_ct *ct);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c
index 6fda3aec5c66..364d0d546ec8 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c
@@ -129,6 +129,7 @@ static inline bool guc_load_done(struct intel_uncore *uncore, u32 *status, bool
case INTEL_BOOTROM_STATUS_RC6CTXCONFIG_FAILED:
case INTEL_BOOTROM_STATUS_MPUMAP_INCORRECT:
case INTEL_BOOTROM_STATUS_EXCEPTION:
+ case INTEL_BOOTROM_STATUS_PROD_KEY_CHECK_FAILURE:
*success = false;
return true;
}
@@ -190,8 +191,10 @@ static int guc_wait_ucode(struct intel_guc *guc)
if (!ret || !success)
break;
- guc_dbg(guc, "load still in progress, count = %d, freq = %dMHz\n",
- count, intel_rps_read_actual_frequency(&uncore->gt->rps));
+ guc_dbg(guc, "load still in progress, count = %d, freq = %dMHz, status = 0x%08X [0x%02X/%02X]\n",
+ count, intel_rps_read_actual_frequency(&uncore->gt->rps), status,
+ REG_FIELD_GET(GS_BOOTROM_MASK, status),
+ REG_FIELD_GET(GS_UKERNEL_MASK, status));
}
after = ktime_get();
delta = ktime_sub(after, before);
@@ -219,6 +222,11 @@ static int guc_wait_ucode(struct intel_guc *guc)
guc_info(guc, "firmware signature verification failed\n");
ret = -ENOEXEC;
break;
+
+ case INTEL_BOOTROM_STATUS_PROD_KEY_CHECK_FAILURE:
+ guc_info(guc, "firmware production part check failure\n");
+ ret = -ENOEXEC;
+ break;
}
switch (ukernel) {
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
index 4ae5fc2f6002..b4d56eccfb1f 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
@@ -35,13 +35,6 @@
#define GUC_MAX_CONTEXT_ID 65535
#define GUC_INVALID_CONTEXT_ID GUC_MAX_CONTEXT_ID
-#define GUC_RENDER_ENGINE 0
-#define GUC_VIDEO_ENGINE 1
-#define GUC_BLITTER_ENGINE 2
-#define GUC_VIDEOENHANCE_ENGINE 3
-#define GUC_VIDEO_ENGINE2 4
-#define GUC_MAX_ENGINES_NUM (GUC_VIDEO_ENGINE2 + 1)
-
#define GUC_RENDER_CLASS 0
#define GUC_VIDEO_CLASS 1
#define GUC_VIDEOENHANCE_CLASS 2
@@ -411,6 +404,15 @@ enum guc_capture_type {
GUC_CAPTURE_LIST_TYPE_MAX,
};
+/* Class indecies for capture_class and capture_instance arrays */
+enum {
+ GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE = 0,
+ GUC_CAPTURE_LIST_CLASS_VIDEO = 1,
+ GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE = 2,
+ GUC_CAPTURE_LIST_CLASS_BLITTER = 3,
+ GUC_CAPTURE_LIST_CLASS_GSC_OTHER = 4,
+};
+
/* GuC Additional Data Struct */
struct guc_ads {
struct guc_mmio_reg_set reg_state_list[GUC_MAX_ENGINE_CLASSES][GUC_MAX_INSTANCES_PER_CLASS];
@@ -451,7 +453,7 @@ enum guc_log_buffer_type {
GUC_MAX_LOG_BUFFER
};
-/**
+/*
* struct guc_log_buffer_state - GuC log buffer state
*
* Below state structure is used for coordination of retrieval of GuC firmware
@@ -490,32 +492,6 @@ struct guc_log_buffer_state {
u32 version;
} __packed;
-struct guc_ctx_report {
- u32 report_return_status;
- u32 reserved1[64];
- u32 affected_count;
- u32 reserved2[2];
-} __packed;
-
-/* GuC Shared Context Data Struct */
-struct guc_shared_ctx_data {
- u32 addr_of_last_preempted_data_low;
- u32 addr_of_last_preempted_data_high;
- u32 addr_of_last_preempted_data_high_tmp;
- u32 padding;
- u32 is_mapped_to_proxy;
- u32 proxy_ctx_id;
- u32 engine_reset_ctx_id;
- u32 media_reset_count;
- u32 reserved1[8];
- u32 uk_last_ctx_switch_reason;
- u32 was_reset;
- u32 lrca_gpu_addr;
- u64 execlist_ctx;
- u32 reserved2[66];
- struct guc_ctx_report preempt_ctx_report[GUC_MAX_ENGINES_NUM];
-} __packed;
-
/* This action will be programmed in C1BC - SOFT_SCRATCH_15_REG */
enum intel_guc_recv_message {
INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED = BIT(1),
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index 026d73855f36..01b75529311c 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -277,6 +277,7 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
slpc->max_freq_softlimit = 0;
slpc->min_freq_softlimit = 0;
+ slpc->ignore_eff_freq = false;
slpc->min_is_rpmax = false;
slpc->boost_freq = 0;
@@ -457,6 +458,29 @@ int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val)
return ret;
}
+int intel_guc_slpc_set_ignore_eff_freq(struct intel_guc_slpc *slpc, bool val)
+{
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ intel_wakeref_t wakeref;
+ int ret;
+
+ mutex_lock(&slpc->lock);
+ wakeref = intel_runtime_pm_get(&i915->runtime_pm);
+
+ ret = slpc_set_param(slpc,
+ SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY,
+ val);
+ if (ret)
+ guc_probe_error(slpc_to_guc(slpc), "Failed to set efficient freq(%d): %pe\n",
+ val, ERR_PTR(ret));
+ else
+ slpc->ignore_eff_freq = val;
+
+ intel_runtime_pm_put(&i915->runtime_pm, wakeref);
+ mutex_unlock(&slpc->lock);
+ return ret;
+}
+
/**
* intel_guc_slpc_set_min_freq() - Set min frequency limit for SLPC.
* @slpc: pointer to intel_guc_slpc.
@@ -482,16 +506,6 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
mutex_lock(&slpc->lock);
wakeref = intel_runtime_pm_get(&i915->runtime_pm);
- /* Ignore efficient freq if lower min freq is requested */
- ret = slpc_set_param(slpc,
- SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY,
- val < slpc->rp1_freq);
- if (ret) {
- guc_probe_error(slpc_to_guc(slpc), "Failed to toggle efficient freq: %pe\n",
- ERR_PTR(ret));
- goto out;
- }
-
ret = slpc_set_param(slpc,
SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
val);
@@ -499,7 +513,6 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
if (!ret)
slpc->min_freq_softlimit = val;
-out:
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
mutex_unlock(&slpc->lock);
@@ -752,6 +765,9 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
/* Set cached media freq ratio mode */
intel_guc_slpc_set_media_ratio_mode(slpc, slpc->media_ratio_mode);
+ /* Set cached value of ignore efficient freq */
+ intel_guc_slpc_set_ignore_eff_freq(slpc, slpc->ignore_eff_freq);
+
return 0;
}
@@ -821,6 +837,8 @@ int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p
slpc_decode_min_freq(slpc));
drm_printf(p, "\twaitboosts: %u\n",
slpc->num_boosts);
+ drm_printf(p, "\tBoosts outstanding: %u\n",
+ atomic_read(&slpc->num_waiters));
}
}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
index 17ed515f6a85..597eb5413ddf 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
@@ -46,5 +46,6 @@ void intel_guc_slpc_boost(struct intel_guc_slpc *slpc);
void intel_guc_slpc_dec_waiters(struct intel_guc_slpc *slpc);
int intel_guc_slpc_unset_gucrc_mode(struct intel_guc_slpc *slpc);
int intel_guc_slpc_override_gucrc_mode(struct intel_guc_slpc *slpc, u32 mode);
+int intel_guc_slpc_set_ignore_eff_freq(struct intel_guc_slpc *slpc, bool val);
#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h
index a6ef53b04e04..a88651331497 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h
@@ -31,6 +31,7 @@ struct intel_guc_slpc {
/* frequency softlimits */
u32 min_freq_softlimit;
u32 max_freq_softlimit;
+ bool ignore_eff_freq;
/* cached media ratio mode */
u32 media_ratio_mode;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index 88e881b100cf..a0e3ef1c65d2 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -1402,13 +1402,34 @@ static void __update_guc_busyness_stats(struct intel_guc *guc)
spin_unlock_irqrestore(&guc->timestamp.lock, flags);
}
+static void __guc_context_update_stats(struct intel_context *ce)
+{
+ struct intel_guc *guc = ce_to_guc(ce);
+ unsigned long flags;
+
+ spin_lock_irqsave(&guc->timestamp.lock, flags);
+ lrc_update_runtime(ce);
+ spin_unlock_irqrestore(&guc->timestamp.lock, flags);
+}
+
+static void guc_context_update_stats(struct intel_context *ce)
+{
+ if (!intel_context_pin_if_active(ce))
+ return;
+
+ __guc_context_update_stats(ce);
+ intel_context_unpin(ce);
+}
+
static void guc_timestamp_ping(struct work_struct *wrk)
{
struct intel_guc *guc = container_of(wrk, typeof(*guc),
timestamp.work.work);
struct intel_uc *uc = container_of(guc, typeof(*uc), guc);
struct intel_gt *gt = guc_to_gt(guc);
+ struct intel_context *ce;
intel_wakeref_t wakeref;
+ unsigned long index;
int srcu, ret;
/*
@@ -1424,6 +1445,10 @@ static void guc_timestamp_ping(struct work_struct *wrk)
with_intel_runtime_pm(&gt->i915->runtime_pm, wakeref)
__update_guc_busyness_stats(guc);
+ /* adjust context stats for overflow */
+ xa_for_each(&guc->context_lookup, index, ce)
+ guc_context_update_stats(ce);
+
intel_gt_reset_unlock(gt, srcu);
guc_enable_busyness_worker(guc);
@@ -1629,16 +1654,16 @@ static void guc_reset_state(struct intel_context *ce, u32 head, bool scrub)
static void guc_engine_reset_prepare(struct intel_engine_cs *engine)
{
- if (!IS_GRAPHICS_VER(engine->i915, 11, 12))
- return;
-
- intel_engine_stop_cs(engine);
-
/*
* Wa_22011802037: In addition to stopping the cs, we need
* to wait for any pending mi force wakeups
*/
- intel_engine_wait_for_pending_mi_fw(engine);
+ if (IS_MTL_GRAPHICS_STEP(engine->i915, M, STEP_A0, STEP_B0) ||
+ (GRAPHICS_VER(engine->i915) >= 11 &&
+ GRAPHICS_VER_FULL(engine->i915) < IP_VER(12, 70))) {
+ intel_engine_stop_cs(engine);
+ intel_engine_wait_for_pending_mi_fw(engine);
+ }
}
static void guc_reset_nop(struct intel_engine_cs *engine)
@@ -2774,6 +2799,7 @@ static void guc_context_unpin(struct intel_context *ce)
{
struct intel_guc *guc = ce_to_guc(ce);
+ __guc_context_update_stats(ce);
unpin_guc_id(guc, ce);
lrc_unpin(ce);
@@ -3455,6 +3481,7 @@ static void remove_from_context(struct i915_request *rq)
}
static const struct intel_context_ops guc_context_ops = {
+ .flags = COPS_RUNTIME_CYCLES,
.alloc = guc_context_alloc,
.close = guc_context_close,
@@ -3473,6 +3500,8 @@ static const struct intel_context_ops guc_context_ops = {
.sched_disable = guc_context_sched_disable,
+ .update_stats = guc_context_update_stats,
+
.reset = lrc_reset,
.destroy = guc_context_destroy,
@@ -3728,6 +3757,7 @@ static int guc_virtual_context_alloc(struct intel_context *ce)
}
static const struct intel_context_ops virtual_guc_context_ops = {
+ .flags = COPS_RUNTIME_CYCLES,
.alloc = guc_virtual_context_alloc,
.close = guc_context_close,
@@ -3745,6 +3775,7 @@ static const struct intel_context_ops virtual_guc_context_ops = {
.exit = guc_virtual_context_exit,
.sched_disable = guc_context_sched_disable,
+ .update_stats = guc_context_update_stats,
.destroy = guc_context_destroy,
@@ -4697,13 +4728,37 @@ static void capture_error_state(struct intel_guc *guc,
{
struct intel_gt *gt = guc_to_gt(guc);
struct drm_i915_private *i915 = gt->i915;
- struct intel_engine_cs *engine = __context_to_physical_engine(ce);
intel_wakeref_t wakeref;
+ intel_engine_mask_t engine_mask;
+
+ if (intel_engine_is_virtual(ce->engine)) {
+ struct intel_engine_cs *e;
+ intel_engine_mask_t tmp, virtual_mask = ce->engine->mask;
+
+ engine_mask = 0;
+ for_each_engine_masked(e, ce->engine->gt, virtual_mask, tmp) {
+ bool match = intel_guc_capture_is_matching_engine(gt, ce, e);
+
+ if (match) {
+ intel_engine_set_hung_context(e, ce);
+ engine_mask |= e->mask;
+ atomic_inc(&i915->gpu_error.reset_engine_count[e->uabi_class]);
+ }
+ }
+
+ if (!engine_mask) {
+ guc_warn(guc, "No matching physical engine capture for virtual engine context 0x%04X / %s",
+ ce->guc_id.id, ce->engine->name);
+ engine_mask = ~0U;
+ }
+ } else {
+ intel_engine_set_hung_context(ce->engine, ce);
+ engine_mask = ce->engine->mask;
+ atomic_inc(&i915->gpu_error.reset_engine_count[ce->engine->uabi_class]);
+ }
- intel_engine_set_hung_context(engine, ce);
with_intel_runtime_pm(&i915->runtime_pm, wakeref)
- i915_capture_error_state(gt, engine->mask, CORE_DUMP_FLAG_IS_GUC_CAPTURE);
- atomic_inc(&i915->gpu_error.reset_engine_count[engine->uabi_class]);
+ i915_capture_error_state(gt, engine_mask, CORE_DUMP_FLAG_IS_GUC_CAPTURE);
}
static void guc_context_replay(struct intel_context *ce)
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
index 04724ff56ded..ddd146265beb 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
@@ -6,23 +6,16 @@
#include <linux/types.h>
#include "gt/intel_gt.h"
-#include "gt/intel_gt_print.h"
#include "intel_guc_reg.h"
#include "intel_huc.h"
+#include "intel_huc_print.h"
#include "i915_drv.h"
+#include "i915_reg.h"
+#include "pxp/intel_pxp_cmd_interface_43.h"
#include <linux/device/bus.h>
#include <linux/mei_aux.h>
-#define huc_printk(_huc, _level, _fmt, ...) \
- gt_##_level(huc_to_gt(_huc), "HuC: " _fmt, ##__VA_ARGS__)
-#define huc_err(_huc, _fmt, ...) huc_printk((_huc), err, _fmt, ##__VA_ARGS__)
-#define huc_warn(_huc, _fmt, ...) huc_printk((_huc), warn, _fmt, ##__VA_ARGS__)
-#define huc_notice(_huc, _fmt, ...) huc_printk((_huc), notice, _fmt, ##__VA_ARGS__)
-#define huc_info(_huc, _fmt, ...) huc_printk((_huc), info, _fmt, ##__VA_ARGS__)
-#define huc_dbg(_huc, _fmt, ...) huc_printk((_huc), dbg, _fmt, ##__VA_ARGS__)
-#define huc_probe_error(_huc, _fmt, ...) huc_printk((_huc), probe_error, _fmt, ##__VA_ARGS__)
-
/**
* DOC: HuC
*
@@ -31,15 +24,23 @@
* capabilities by adding HuC specific commands to batch buffers.
*
* The kernel driver is only responsible for loading the HuC firmware and
- * triggering its security authentication, which is performed by the GuC on
- * older platforms and by the GSC on newer ones. For the GuC to correctly
- * perform the authentication, the HuC binary must be loaded before the GuC one.
+ * triggering its security authentication. This is done differently depending
+ * on the platform:
+ * - older platforms (from Gen9 to most Gen12s): the load is performed via DMA
+ * and the authentication via GuC
+ * - DG2: load and authentication are both performed via GSC.
+ * - MTL and newer platforms: the load is performed via DMA (same as with
+ * not-DG2 older platforms), while the authentication is done in 2-steps,
+ * a first auth for clear-media workloads via GuC and a second one for all
+ * workloads via GSC.
+ * On platforms where the GuC does the authentication, to correctly do so the
+ * HuC binary must be loaded before the GuC one.
* Loading the HuC is optional; however, not using the HuC might negatively
* impact power usage and/or performance of media workloads, depending on the
* use-cases.
* HuC must be reloaded on events that cause the WOPCM to lose its contents
- * (S3/S4, FLR); GuC-authenticated HuC must also be reloaded on GuC/GT reset,
- * while GSC-managed HuC will survive that.
+ * (S3/S4, FLR); on older platforms the HuC must also be reloaded on GuC/GT
+ * reset, while on newer ones it will survive that.
*
* See https://github.com/intel/media-driver for the latest details on HuC
* functionality.
@@ -115,7 +116,7 @@ static enum hrtimer_restart huc_delayed_load_timer_callback(struct hrtimer *hrti
{
struct intel_huc *huc = container_of(hrtimer, struct intel_huc, delayed_load.timer);
- if (!intel_huc_is_authenticated(huc)) {
+ if (!intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GSC)) {
if (huc->delayed_load.status == INTEL_HUC_WAITING_ON_GSC)
huc_notice(huc, "timed out waiting for MEI GSC\n");
else if (huc->delayed_load.status == INTEL_HUC_WAITING_ON_PXP)
@@ -133,7 +134,7 @@ static void huc_delayed_load_start(struct intel_huc *huc)
{
ktime_t delay;
- GEM_BUG_ON(intel_huc_is_authenticated(huc));
+ GEM_BUG_ON(intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GSC));
/*
* On resume we don't have to wait for MEI-GSC to be re-probed, but we
@@ -276,7 +277,7 @@ void intel_huc_init_early(struct intel_huc *huc)
struct drm_i915_private *i915 = huc_to_gt(huc)->i915;
struct intel_gt *gt = huc_to_gt(huc);
- intel_uc_fw_init_early(&huc->fw, INTEL_UC_FW_TYPE_HUC);
+ intel_uc_fw_init_early(&huc->fw, INTEL_UC_FW_TYPE_HUC, true);
/*
* we always init the fence as already completed, even if HuC is not
@@ -293,13 +294,23 @@ void intel_huc_init_early(struct intel_huc *huc)
}
if (GRAPHICS_VER(i915) >= 11) {
- huc->status.reg = GEN11_HUC_KERNEL_LOAD_INFO;
- huc->status.mask = HUC_LOAD_SUCCESSFUL;
- huc->status.value = HUC_LOAD_SUCCESSFUL;
+ huc->status[INTEL_HUC_AUTH_BY_GUC].reg = GEN11_HUC_KERNEL_LOAD_INFO;
+ huc->status[INTEL_HUC_AUTH_BY_GUC].mask = HUC_LOAD_SUCCESSFUL;
+ huc->status[INTEL_HUC_AUTH_BY_GUC].value = HUC_LOAD_SUCCESSFUL;
+ } else {
+ huc->status[INTEL_HUC_AUTH_BY_GUC].reg = HUC_STATUS2;
+ huc->status[INTEL_HUC_AUTH_BY_GUC].mask = HUC_FW_VERIFIED;
+ huc->status[INTEL_HUC_AUTH_BY_GUC].value = HUC_FW_VERIFIED;
+ }
+
+ if (IS_DG2(i915)) {
+ huc->status[INTEL_HUC_AUTH_BY_GSC].reg = GEN11_HUC_KERNEL_LOAD_INFO;
+ huc->status[INTEL_HUC_AUTH_BY_GSC].mask = HUC_LOAD_SUCCESSFUL;
+ huc->status[INTEL_HUC_AUTH_BY_GSC].value = HUC_LOAD_SUCCESSFUL;
} else {
- huc->status.reg = HUC_STATUS2;
- huc->status.mask = HUC_FW_VERIFIED;
- huc->status.value = HUC_FW_VERIFIED;
+ huc->status[INTEL_HUC_AUTH_BY_GSC].reg = HECI_FWSTS5(MTL_GSC_HECI1_BASE);
+ huc->status[INTEL_HUC_AUTH_BY_GSC].mask = HECI_FWSTS5_HUC_AUTH_DONE;
+ huc->status[INTEL_HUC_AUTH_BY_GSC].value = HECI_FWSTS5_HUC_AUTH_DONE;
}
}
@@ -307,51 +318,91 @@ void intel_huc_init_early(struct intel_huc *huc)
static int check_huc_loading_mode(struct intel_huc *huc)
{
struct intel_gt *gt = huc_to_gt(huc);
- bool fw_needs_gsc = intel_huc_is_loaded_by_gsc(huc);
- bool hw_uses_gsc = false;
+ bool gsc_enabled = huc->fw.has_gsc_headers;
/*
* The fuse for HuC load via GSC is only valid on platforms that have
* GuC deprivilege.
*/
if (HAS_GUC_DEPRIVILEGE(gt->i915))
- hw_uses_gsc = intel_uncore_read(gt->uncore, GUC_SHIM_CONTROL2) &
- GSC_LOADS_HUC;
+ huc->loaded_via_gsc = intel_uncore_read(gt->uncore, GUC_SHIM_CONTROL2) &
+ GSC_LOADS_HUC;
- if (fw_needs_gsc != hw_uses_gsc) {
- huc_err(huc, "mismatch between FW (%s) and HW (%s) load modes\n",
- HUC_LOAD_MODE_STRING(fw_needs_gsc), HUC_LOAD_MODE_STRING(hw_uses_gsc));
+ if (huc->loaded_via_gsc && !gsc_enabled) {
+ huc_err(huc, "HW requires a GSC-enabled blob, but we found a legacy one\n");
return -ENOEXEC;
}
- /* make sure we can access the GSC via the mei driver if we need it */
- if (!(IS_ENABLED(CONFIG_INTEL_MEI_PXP) && IS_ENABLED(CONFIG_INTEL_MEI_GSC)) &&
- fw_needs_gsc) {
- huc_info(huc, "can't load due to missing MEI modules\n");
- return -EIO;
+ /*
+ * On newer platforms we have GSC-enabled binaries but we load the HuC
+ * via DMA. To do so we need to find the location of the legacy-style
+ * binary inside the GSC-enabled one, which we do at fetch time. Make
+ * sure that we were able to do so if the fuse says we need to load via
+ * DMA and the binary is GSC-enabled.
+ */
+ if (!huc->loaded_via_gsc && gsc_enabled && !huc->fw.dma_start_offset) {
+ huc_err(huc, "HW in DMA mode, but we have an incompatible GSC-enabled blob\n");
+ return -ENOEXEC;
+ }
+
+ /*
+ * If the HuC is loaded via GSC, we need to be able to access the GSC.
+ * On DG2 this is done via the mei components, while on newer platforms
+ * it is done via the GSCCS,
+ */
+ if (huc->loaded_via_gsc) {
+ if (IS_DG2(gt->i915)) {
+ if (!IS_ENABLED(CONFIG_INTEL_MEI_PXP) ||
+ !IS_ENABLED(CONFIG_INTEL_MEI_GSC)) {
+ huc_info(huc, "can't load due to missing mei modules\n");
+ return -EIO;
+ }
+ } else {
+ if (!HAS_ENGINE(gt, GSC0)) {
+ huc_info(huc, "can't load due to missing GSCCS\n");
+ return -EIO;
+ }
+ }
}
- huc_dbg(huc, "loaded by GSC = %s\n", str_yes_no(fw_needs_gsc));
+ huc_dbg(huc, "loaded by GSC = %s\n", str_yes_no(huc->loaded_via_gsc));
return 0;
}
int intel_huc_init(struct intel_huc *huc)
{
+ struct intel_gt *gt = huc_to_gt(huc);
int err;
err = check_huc_loading_mode(huc);
if (err)
goto out;
+ if (HAS_ENGINE(gt, GSC0)) {
+ struct i915_vma *vma;
+
+ vma = intel_guc_allocate_vma(&gt->uc.guc, PXP43_HUC_AUTH_INOUT_SIZE * 2);
+ if (IS_ERR(vma)) {
+ err = PTR_ERR(vma);
+ huc_info(huc, "Failed to allocate heci pkt\n");
+ goto out;
+ }
+
+ huc->heci_pkt = vma;
+ }
+
err = intel_uc_fw_init(&huc->fw);
if (err)
- goto out;
+ goto out_pkt;
intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_LOADABLE);
return 0;
+out_pkt:
+ if (huc->heci_pkt)
+ i915_vma_unpin_and_release(&huc->heci_pkt, 0);
out:
intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_INIT_FAIL);
huc_info(huc, "initialization failed %pe\n", ERR_PTR(err));
@@ -366,6 +417,9 @@ void intel_huc_fini(struct intel_huc *huc)
*/
delayed_huc_load_fini(huc);
+ if (huc->heci_pkt)
+ i915_vma_unpin_and_release(&huc->heci_pkt, 0);
+
if (intel_uc_fw_is_loadable(&huc->fw))
intel_uc_fw_fini(&huc->fw);
}
@@ -383,34 +437,45 @@ void intel_huc_suspend(struct intel_huc *huc)
delayed_huc_load_complete(huc);
}
-int intel_huc_wait_for_auth_complete(struct intel_huc *huc)
+static const char *auth_mode_string(struct intel_huc *huc,
+ enum intel_huc_authentication_type type)
+{
+ bool partial = huc->fw.has_gsc_headers && type == INTEL_HUC_AUTH_BY_GUC;
+
+ return partial ? "clear media" : "all workloads";
+}
+
+int intel_huc_wait_for_auth_complete(struct intel_huc *huc,
+ enum intel_huc_authentication_type type)
{
struct intel_gt *gt = huc_to_gt(huc);
int ret;
ret = __intel_wait_for_register(gt->uncore,
- huc->status.reg,
- huc->status.mask,
- huc->status.value,
+ huc->status[type].reg,
+ huc->status[type].mask,
+ huc->status[type].value,
2, 50, NULL);
/* mark the load process as complete even if the wait failed */
delayed_huc_load_complete(huc);
if (ret) {
- huc_err(huc, "firmware not verified %pe\n", ERR_PTR(ret));
+ huc_err(huc, "firmware not verified for %s: %pe\n",
+ auth_mode_string(huc, type), ERR_PTR(ret));
intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
return ret;
}
intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_RUNNING);
- huc_info(huc, "authenticated!\n");
+ huc_info(huc, "authenticated for %s\n", auth_mode_string(huc, type));
return 0;
}
/**
* intel_huc_auth() - Authenticate HuC uCode
* @huc: intel_huc structure
+ * @type: authentication type (via GuC or via GSC)
*
* Called after HuC and GuC firmware loading during intel_uc_init_hw().
*
@@ -418,7 +483,7 @@ int intel_huc_wait_for_auth_complete(struct intel_huc *huc)
* passing the offset of the RSA signature to intel_guc_auth_huc(). It then
* waits for up to 50ms for firmware verification ACK.
*/
-int intel_huc_auth(struct intel_huc *huc)
+int intel_huc_auth(struct intel_huc *huc, enum intel_huc_authentication_type type)
{
struct intel_gt *gt = huc_to_gt(huc);
struct intel_guc *guc = &gt->uc.guc;
@@ -427,44 +492,67 @@ int intel_huc_auth(struct intel_huc *huc)
if (!intel_uc_fw_is_loaded(&huc->fw))
return -ENOEXEC;
- /* GSC will do the auth */
+ /* GSC will do the auth with the load */
if (intel_huc_is_loaded_by_gsc(huc))
return -ENODEV;
+ if (intel_huc_is_authenticated(huc, type))
+ return -EEXIST;
+
ret = i915_inject_probe_error(gt->i915, -ENXIO);
if (ret)
goto fail;
- GEM_BUG_ON(intel_uc_fw_is_running(&huc->fw));
-
- ret = intel_guc_auth_huc(guc, intel_guc_ggtt_offset(guc, huc->fw.rsa_data));
- if (ret) {
- huc_err(huc, "authentication by GuC failed %pe\n", ERR_PTR(ret));
- goto fail;
+ switch (type) {
+ case INTEL_HUC_AUTH_BY_GUC:
+ ret = intel_guc_auth_huc(guc, intel_guc_ggtt_offset(guc, huc->fw.rsa_data));
+ break;
+ case INTEL_HUC_AUTH_BY_GSC:
+ ret = intel_huc_fw_auth_via_gsccs(huc);
+ break;
+ default:
+ MISSING_CASE(type);
+ ret = -EINVAL;
}
+ if (ret)
+ goto fail;
/* Check authentication status, it should be done by now */
- ret = intel_huc_wait_for_auth_complete(huc);
+ ret = intel_huc_wait_for_auth_complete(huc, type);
if (ret)
goto fail;
return 0;
fail:
- huc_probe_error(huc, "authentication failed %pe\n", ERR_PTR(ret));
+ huc_probe_error(huc, "%s authentication failed %pe\n",
+ auth_mode_string(huc, type), ERR_PTR(ret));
return ret;
}
-bool intel_huc_is_authenticated(struct intel_huc *huc)
+bool intel_huc_is_authenticated(struct intel_huc *huc,
+ enum intel_huc_authentication_type type)
{
struct intel_gt *gt = huc_to_gt(huc);
intel_wakeref_t wakeref;
u32 status = 0;
with_intel_runtime_pm(gt->uncore->rpm, wakeref)
- status = intel_uncore_read(gt->uncore, huc->status.reg);
+ status = intel_uncore_read(gt->uncore, huc->status[type].reg);
+
+ return (status & huc->status[type].mask) == huc->status[type].value;
+}
+
+static bool huc_is_fully_authenticated(struct intel_huc *huc)
+{
+ struct intel_uc_fw *huc_fw = &huc->fw;
- return (status & huc->status.mask) == huc->status.value;
+ if (!huc_fw->has_gsc_headers)
+ return intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GUC);
+ else if (intel_huc_is_loaded_by_gsc(huc) || HAS_ENGINE(huc_to_gt(huc), GSC0))
+ return intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GSC);
+ else
+ return false;
}
/**
@@ -479,7 +567,9 @@ bool intel_huc_is_authenticated(struct intel_huc *huc)
*/
int intel_huc_check_status(struct intel_huc *huc)
{
- switch (__intel_uc_fw_status(&huc->fw)) {
+ struct intel_uc_fw *huc_fw = &huc->fw;
+
+ switch (__intel_uc_fw_status(huc_fw)) {
case INTEL_UC_FIRMWARE_NOT_SUPPORTED:
return -ENODEV;
case INTEL_UC_FIRMWARE_DISABLED:
@@ -496,7 +586,17 @@ int intel_huc_check_status(struct intel_huc *huc)
break;
}
- return intel_huc_is_authenticated(huc);
+ /*
+ * GSC-enabled binaries loaded via DMA are first partially
+ * authenticated by GuC and then fully authenticated by GSC
+ */
+ if (huc_is_fully_authenticated(huc))
+ return 1; /* full auth */
+ else if (huc_fw->has_gsc_headers && !intel_huc_is_loaded_by_gsc(huc) &&
+ intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GUC))
+ return 2; /* clear media only */
+ else
+ return 0;
}
static bool huc_has_delayed_load(struct intel_huc *huc)
@@ -510,7 +610,10 @@ void intel_huc_update_auth_status(struct intel_huc *huc)
if (!intel_uc_fw_is_loadable(&huc->fw))
return;
- if (intel_huc_is_authenticated(huc))
+ if (!huc->fw.has_gsc_headers)
+ return;
+
+ if (huc_is_fully_authenticated(huc))
intel_uc_fw_change_status(&huc->fw,
INTEL_UC_FIRMWARE_RUNNING);
else if (huc_has_delayed_load(huc))
@@ -543,5 +646,5 @@ void intel_huc_load_status(struct intel_huc *huc, struct drm_printer *p)
with_intel_runtime_pm(gt->uncore->rpm, wakeref)
drm_printf(p, "HuC status: 0x%08x\n",
- intel_uncore_read(gt->uncore, huc->status.reg));
+ intel_uncore_read(gt->uncore, huc->status[INTEL_HUC_AUTH_BY_GUC].reg));
}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.h b/drivers/gpu/drm/i915/gt/uc/intel_huc.h
index 0789184d81a2..ba5cb08e9e7b 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.h
@@ -15,6 +15,7 @@
#include <linux/hrtimer.h>
struct bus_type;
+struct i915_vma;
enum intel_huc_delayed_load_status {
INTEL_HUC_WAITING_ON_GSC = 0,
@@ -22,6 +23,12 @@ enum intel_huc_delayed_load_status {
INTEL_HUC_DELAYED_LOAD_ERROR,
};
+enum intel_huc_authentication_type {
+ INTEL_HUC_AUTH_BY_GUC = 0,
+ INTEL_HUC_AUTH_BY_GSC,
+ INTEL_HUC_AUTH_MAX_MODES
+};
+
struct intel_huc {
/* Generic uC firmware management */
struct intel_uc_fw fw;
@@ -31,7 +38,7 @@ struct intel_huc {
i915_reg_t reg;
u32 mask;
u32 value;
- } status;
+ } status[INTEL_HUC_AUTH_MAX_MODES];
struct {
struct i915_sw_fence fence;
@@ -39,6 +46,11 @@ struct intel_huc {
struct notifier_block nb;
enum intel_huc_delayed_load_status status;
} delayed_load;
+
+ /* for load via GSCCS */
+ struct i915_vma *heci_pkt;
+
+ bool loaded_via_gsc;
};
int intel_huc_sanitize(struct intel_huc *huc);
@@ -46,11 +58,13 @@ void intel_huc_init_early(struct intel_huc *huc);
int intel_huc_init(struct intel_huc *huc);
void intel_huc_fini(struct intel_huc *huc);
void intel_huc_suspend(struct intel_huc *huc);
-int intel_huc_auth(struct intel_huc *huc);
-int intel_huc_wait_for_auth_complete(struct intel_huc *huc);
+int intel_huc_auth(struct intel_huc *huc, enum intel_huc_authentication_type type);
+int intel_huc_wait_for_auth_complete(struct intel_huc *huc,
+ enum intel_huc_authentication_type type);
+bool intel_huc_is_authenticated(struct intel_huc *huc,
+ enum intel_huc_authentication_type type);
int intel_huc_check_status(struct intel_huc *huc);
void intel_huc_update_auth_status(struct intel_huc *huc);
-bool intel_huc_is_authenticated(struct intel_huc *huc);
void intel_huc_register_gsc_notifier(struct intel_huc *huc, const struct bus_type *bus);
void intel_huc_unregister_gsc_notifier(struct intel_huc *huc, const struct bus_type *bus);
@@ -73,13 +87,13 @@ static inline bool intel_huc_is_used(struct intel_huc *huc)
static inline bool intel_huc_is_loaded_by_gsc(const struct intel_huc *huc)
{
- return huc->fw.loaded_via_gsc;
+ return huc->loaded_via_gsc;
}
static inline bool intel_huc_wait_required(struct intel_huc *huc)
{
return intel_huc_is_used(huc) && intel_huc_is_loaded_by_gsc(huc) &&
- !intel_huc_is_authenticated(huc);
+ !intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GSC);
}
void intel_huc_load_status(struct intel_huc *huc, struct drm_printer *p);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c
index 534b0aa43316..e608152fecfc 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c
@@ -5,10 +5,241 @@
#include "gt/intel_gsc.h"
#include "gt/intel_gt.h"
+#include "intel_gsc_binary_headers.h"
+#include "intel_gsc_uc_heci_cmd_submit.h"
#include "intel_huc.h"
#include "intel_huc_fw.h"
+#include "intel_huc_print.h"
#include "i915_drv.h"
#include "pxp/intel_pxp_huc.h"
+#include "pxp/intel_pxp_cmd_interface_43.h"
+
+struct mtl_huc_auth_msg_in {
+ struct intel_gsc_mtl_header header;
+ struct pxp43_new_huc_auth_in huc_in;
+} __packed;
+
+struct mtl_huc_auth_msg_out {
+ struct intel_gsc_mtl_header header;
+ struct pxp43_huc_auth_out huc_out;
+} __packed;
+
+int intel_huc_fw_auth_via_gsccs(struct intel_huc *huc)
+{
+ struct intel_gt *gt = huc_to_gt(huc);
+ struct drm_i915_private *i915 = gt->i915;
+ struct drm_i915_gem_object *obj;
+ struct mtl_huc_auth_msg_in *msg_in;
+ struct mtl_huc_auth_msg_out *msg_out;
+ void *pkt_vaddr;
+ u64 pkt_offset;
+ int retry = 5;
+ int err = 0;
+
+ if (!huc->heci_pkt)
+ return -ENODEV;
+
+ obj = huc->heci_pkt->obj;
+ pkt_offset = i915_ggtt_offset(huc->heci_pkt);
+
+ pkt_vaddr = i915_gem_object_pin_map_unlocked(obj,
+ i915_coherent_map_type(i915, obj, true));
+ if (IS_ERR(pkt_vaddr))
+ return PTR_ERR(pkt_vaddr);
+
+ msg_in = pkt_vaddr;
+ msg_out = pkt_vaddr + PXP43_HUC_AUTH_INOUT_SIZE;
+
+ intel_gsc_uc_heci_cmd_emit_mtl_header(&msg_in->header,
+ HECI_MEADDRESS_PXP,
+ sizeof(*msg_in), 0);
+
+ msg_in->huc_in.header.api_version = PXP_APIVER(4, 3);
+ msg_in->huc_in.header.command_id = PXP43_CMDID_NEW_HUC_AUTH;
+ msg_in->huc_in.header.status = 0;
+ msg_in->huc_in.header.buffer_len = sizeof(msg_in->huc_in) -
+ sizeof(msg_in->huc_in.header);
+ msg_in->huc_in.huc_base_address = huc->fw.vma_res.start;
+ msg_in->huc_in.huc_size = huc->fw.obj->base.size;
+
+ do {
+ err = intel_gsc_uc_heci_cmd_submit_packet(&gt->uc.gsc,
+ pkt_offset, sizeof(*msg_in),
+ pkt_offset + PXP43_HUC_AUTH_INOUT_SIZE,
+ PXP43_HUC_AUTH_INOUT_SIZE);
+ if (err) {
+ huc_err(huc, "failed to submit GSC request to auth: %d\n", err);
+ goto out_unpin;
+ }
+
+ if (msg_out->header.flags & GSC_OUTFLAG_MSG_PENDING) {
+ msg_in->header.gsc_message_handle = msg_out->header.gsc_message_handle;
+ err = -EBUSY;
+ msleep(50);
+ }
+ } while (--retry && err == -EBUSY);
+
+ if (err)
+ goto out_unpin;
+
+ if (msg_out->header.message_size != sizeof(*msg_out)) {
+ huc_err(huc, "invalid GSC reply length %u [expected %zu]\n",
+ msg_out->header.message_size, sizeof(*msg_out));
+ err = -EPROTO;
+ goto out_unpin;
+ }
+
+ /*
+ * The GSC will return PXP_STATUS_OP_NOT_PERMITTED if the HuC is already
+ * loaded. If the same error is ever returned with HuC not loaded we'll
+ * still catch it when we check the authentication bit later.
+ */
+ if (msg_out->huc_out.header.status != PXP_STATUS_SUCCESS &&
+ msg_out->huc_out.header.status != PXP_STATUS_OP_NOT_PERMITTED) {
+ huc_err(huc, "auth failed with GSC error = 0x%x\n",
+ msg_out->huc_out.header.status);
+ err = -EIO;
+ goto out_unpin;
+ }
+
+out_unpin:
+ i915_gem_object_unpin_map(obj);
+ return err;
+}
+
+static void get_version_from_gsc_manifest(struct intel_uc_fw_ver *ver, const void *data)
+{
+ const struct intel_gsc_manifest_header *manifest = data;
+
+ ver->major = manifest->fw_version.major;
+ ver->minor = manifest->fw_version.minor;
+ ver->patch = manifest->fw_version.hotfix;
+}
+
+static bool css_valid(const void *data, size_t size)
+{
+ const struct uc_css_header *css = data;
+
+ if (unlikely(size < sizeof(struct uc_css_header)))
+ return false;
+
+ if (css->module_type != 0x6)
+ return false;
+
+ if (css->module_vendor != PCI_VENDOR_ID_INTEL)
+ return false;
+
+ return true;
+}
+
+static inline u32 entry_offset(const struct intel_gsc_cpd_entry *entry)
+{
+ return entry->offset & INTEL_GSC_CPD_ENTRY_OFFSET_MASK;
+}
+
+int intel_huc_fw_get_binary_info(struct intel_uc_fw *huc_fw, const void *data, size_t size)
+{
+ struct intel_huc *huc = container_of(huc_fw, struct intel_huc, fw);
+ const struct intel_gsc_cpd_header_v2 *header = data;
+ const struct intel_gsc_cpd_entry *entry;
+ size_t min_size = sizeof(*header);
+ int i;
+
+ if (!huc_fw->has_gsc_headers) {
+ huc_err(huc, "Invalid FW type for GSC header parsing!\n");
+ return -EINVAL;
+ }
+
+ if (size < sizeof(*header)) {
+ huc_err(huc, "FW too small! %zu < %zu\n", size, min_size);
+ return -ENODATA;
+ }
+
+ /*
+ * The GSC-enabled HuC binary starts with a directory header, followed
+ * by a series of entries. Each entry is identified by a name and
+ * points to a specific section of the binary containing the relevant
+ * data. The entries we're interested in are:
+ * - "HUCP.man": points to the GSC manifest header for the HuC, which
+ * contains the version info.
+ * - "huc_fw": points to the legacy-style binary that can be used for
+ * load via the DMA. This entry only contains a valid CSS
+ * on binaries for platforms that support 2-step HuC load
+ * via dma and auth via GSC (like MTL).
+ *
+ * --------------------------------------------------
+ * [ intel_gsc_cpd_header_v2 ]
+ * --------------------------------------------------
+ * [ intel_gsc_cpd_entry[] ]
+ * [ entry1 ]
+ * [ ... ]
+ * [ entryX ]
+ * [ "HUCP.man" ]
+ * [ ... ]
+ * [ offset >----------------------------]------o
+ * [ ... ] |
+ * [ entryY ] |
+ * [ "huc_fw" ] |
+ * [ ... ] |
+ * [ offset >----------------------------]----------o
+ * -------------------------------------------------- | |
+ * | |
+ * -------------------------------------------------- | |
+ * [ intel_gsc_manifest_header ]<-----o |
+ * [ ... ] |
+ * [ intel_gsc_version fw_version ] |
+ * [ ... ] |
+ * -------------------------------------------------- |
+ * |
+ * -------------------------------------------------- |
+ * [ data[] ]<---------o
+ * [ ... ]
+ * [ ... ]
+ * --------------------------------------------------
+ */
+
+ if (header->header_marker != INTEL_GSC_CPD_HEADER_MARKER) {
+ huc_err(huc, "invalid marker for CPD header: 0x%08x!\n",
+ header->header_marker);
+ return -EINVAL;
+ }
+
+ /* we only have binaries with header v2 and entry v1 for now */
+ if (header->header_version != 2 || header->entry_version != 1) {
+ huc_err(huc, "invalid CPD header/entry version %u:%u!\n",
+ header->header_version, header->entry_version);
+ return -EINVAL;
+ }
+
+ if (header->header_length < sizeof(struct intel_gsc_cpd_header_v2)) {
+ huc_err(huc, "invalid CPD header length %u!\n",
+ header->header_length);
+ return -EINVAL;
+ }
+
+ min_size = header->header_length + sizeof(*entry) * header->num_of_entries;
+ if (size < min_size) {
+ huc_err(huc, "FW too small! %zu < %zu\n", size, min_size);
+ return -ENODATA;
+ }
+
+ entry = data + header->header_length;
+
+ for (i = 0; i < header->num_of_entries; i++, entry++) {
+ if (strcmp(entry->name, "HUCP.man") == 0)
+ get_version_from_gsc_manifest(&huc_fw->file_selected.ver,
+ data + entry_offset(entry));
+
+ if (strcmp(entry->name, "huc_fw") == 0) {
+ u32 offset = entry_offset(entry);
+
+ if (offset < size && css_valid(data + offset, size - offset))
+ huc_fw->dma_start_offset = offset;
+ }
+ }
+
+ return 0;
+}
int intel_huc_fw_load_and_auth_via_gsc(struct intel_huc *huc)
{
@@ -25,7 +256,7 @@ int intel_huc_fw_load_and_auth_via_gsc(struct intel_huc *huc)
* component gets re-bound and this function called again. If so, just
* mark the HuC as loaded.
*/
- if (intel_huc_is_authenticated(huc)) {
+ if (intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GSC)) {
intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_RUNNING);
return 0;
}
@@ -38,7 +269,7 @@ int intel_huc_fw_load_and_auth_via_gsc(struct intel_huc *huc)
intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_TRANSFERRED);
- return intel_huc_wait_for_auth_complete(huc);
+ return intel_huc_wait_for_auth_complete(huc, INTEL_HUC_AUTH_BY_GSC);
}
/**
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.h
index db42e238b45f..307ab45e6b09 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.h
@@ -7,8 +7,12 @@
#define _INTEL_HUC_FW_H_
struct intel_huc;
+struct intel_uc_fw;
+
+#include <linux/types.h>
int intel_huc_fw_load_and_auth_via_gsc(struct intel_huc *huc);
+int intel_huc_fw_auth_via_gsccs(struct intel_huc *huc);
int intel_huc_fw_upload(struct intel_huc *huc);
-
+int intel_huc_fw_get_binary_info(struct intel_uc_fw *huc_fw, const void *data, size_t size);
#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc_print.h b/drivers/gpu/drm/i915/gt/uc/intel_huc_print.h
new file mode 100644
index 000000000000..915d310ee1df
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc_print.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_HUC_PRINT__
+#define __INTEL_HUC_PRINT__
+
+#include "gt/intel_gt.h"
+#include "gt/intel_gt_print.h"
+
+#define huc_printk(_huc, _level, _fmt, ...) \
+ gt_##_level(huc_to_gt(_huc), "HuC: " _fmt, ##__VA_ARGS__)
+#define huc_err(_huc, _fmt, ...) huc_printk((_huc), err, _fmt, ##__VA_ARGS__)
+#define huc_warn(_huc, _fmt, ...) huc_printk((_huc), warn, _fmt, ##__VA_ARGS__)
+#define huc_notice(_huc, _fmt, ...) huc_printk((_huc), notice, _fmt, ##__VA_ARGS__)
+#define huc_info(_huc, _fmt, ...) huc_printk((_huc), info, _fmt, ##__VA_ARGS__)
+#define huc_dbg(_huc, _fmt, ...) huc_printk((_huc), dbg, _fmt, ##__VA_ARGS__)
+#define huc_probe_error(_huc, _fmt, ...) huc_printk((_huc), probe_error, _fmt, ##__VA_ARGS__)
+
+#endif /* __INTEL_HUC_PRINT__ */
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
index 4ccb4be4c9cb..18250fb64bd8 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
@@ -18,6 +18,7 @@
#include "intel_uc.h"
#include "i915_drv.h"
+#include "i915_hwmon.h"
static const struct intel_uc_ops uc_ops_off;
static const struct intel_uc_ops uc_ops_on;
@@ -431,6 +432,9 @@ static bool uc_is_wopcm_locked(struct intel_uc *uc)
static int __uc_check_hw(struct intel_uc *uc)
{
+ if (uc->fw_table_invalid)
+ return -EIO;
+
if (!intel_uc_supports_guc(uc))
return 0;
@@ -461,6 +465,7 @@ static int __uc_init_hw(struct intel_uc *uc)
struct intel_guc *guc = &uc->guc;
struct intel_huc *huc = &uc->huc;
int ret, attempts;
+ bool pl1en = false;
GEM_BUG_ON(!intel_uc_supports_guc(uc));
GEM_BUG_ON(!intel_uc_wants_guc(uc));
@@ -491,6 +496,9 @@ static int __uc_init_hw(struct intel_uc *uc)
else
attempts = 1;
+ /* Disable a potentially low PL1 power limit to allow freq to be raised */
+ i915_hwmon_power_max_disable(gt->i915, &pl1en);
+
intel_rps_raise_unslice(&uc_to_gt(uc)->rps);
while (attempts--) {
@@ -500,7 +508,7 @@ static int __uc_init_hw(struct intel_uc *uc)
*/
ret = __uc_sanitize(uc);
if (ret)
- goto err_out;
+ goto err_rps;
intel_huc_fw_upload(huc);
intel_guc_ads_reset(guc);
@@ -530,7 +538,7 @@ static int __uc_init_hw(struct intel_uc *uc)
if (intel_huc_is_loaded_by_gsc(huc))
intel_huc_update_auth_status(huc);
else
- intel_huc_auth(huc);
+ intel_huc_auth(huc, INTEL_HUC_AUTH_BY_GUC);
if (intel_uc_uses_guc_submission(uc)) {
ret = intel_guc_submission_enable(guc);
@@ -547,6 +555,8 @@ static int __uc_init_hw(struct intel_uc *uc)
intel_rps_lower_unslice(&uc_to_gt(uc)->rps);
}
+ i915_hwmon_power_max_restore(gt->i915, pl1en);
+
guc_info(guc, "submission %s\n", str_enabled_disabled(intel_uc_uses_guc_submission(uc)));
guc_info(guc, "SLPC %s\n", str_enabled_disabled(intel_uc_uses_guc_slpc(uc)));
@@ -559,10 +569,12 @@ err_submission:
intel_guc_submission_disable(guc);
err_log_capture:
__uc_capture_load_err_log(uc);
-err_out:
+err_rps:
/* Return GT back to RPn */
intel_rps_lower_unslice(&uc_to_gt(uc)->rps);
+ i915_hwmon_power_max_restore(gt->i915, pl1en);
+err_out:
__uc_sanitize(uc);
if (!ret) {
@@ -688,6 +700,12 @@ void intel_uc_suspend(struct intel_uc *uc)
}
}
+static void __uc_resume_mappings(struct intel_uc *uc)
+{
+ intel_uc_fw_resume_mapping(&uc->guc.fw);
+ intel_uc_fw_resume_mapping(&uc->huc.fw);
+}
+
static int __uc_resume(struct intel_uc *uc, bool enable_communication)
{
struct intel_guc *guc = &uc->guc;
@@ -755,4 +773,6 @@ static const struct intel_uc_ops uc_ops_on = {
.init_hw = __uc_init_hw,
.fini_hw = __uc_fini_hw,
+
+ .resume_mappings = __uc_resume_mappings,
};
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
index 5d0f1bcc381e..014bb7d83689 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h
@@ -24,6 +24,7 @@ struct intel_uc_ops {
void (*fini)(struct intel_uc *uc);
int (*init_hw)(struct intel_uc *uc);
void (*fini_hw)(struct intel_uc *uc);
+ void (*resume_mappings)(struct intel_uc *uc);
};
struct intel_uc {
@@ -36,6 +37,7 @@ struct intel_uc {
struct drm_i915_gem_object *load_err_log;
bool reset_in_progress;
+ bool fw_table_invalid;
};
void intel_uc_init_early(struct intel_uc *uc);
@@ -113,6 +115,7 @@ intel_uc_ops_function(init, init, int, 0);
intel_uc_ops_function(fini, fini, void, );
intel_uc_ops_function(init_hw, init_hw, int, 0);
intel_uc_ops_function(fini_hw, fini_hw, void, );
+intel_uc_ops_function(resume_mappings, resume_mappings, void, );
#undef intel_uc_ops_function
#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
index c36e68e23a14..944725e62414 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
@@ -17,6 +17,12 @@
#include "i915_drv.h"
#include "i915_reg.h"
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+#define UNEXPECTED gt_probe_error
+#else
+#define UNEXPECTED gt_notice
+#endif
+
static inline struct intel_gt *
____uc_fw_to_gt(struct intel_uc_fw *uc_fw, enum intel_uc_fw_type type)
{
@@ -79,14 +85,15 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
* security fixes, etc. to be enabled.
*/
#define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_maj, guc_mmp) \
- fw_def(DG2, 0, guc_maj(dg2, 70, 5)) \
- fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5)) \
+ fw_def(METEORLAKE, 0, guc_maj(mtl, 70, 6, 6)) \
+ fw_def(DG2, 0, guc_maj(dg2, 70, 5, 1)) \
+ fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5, 1)) \
fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 70, 1, 1)) \
fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 69, 0, 3)) \
- fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5)) \
+ fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5, 1)) \
fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 70, 1, 1)) \
fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 69, 0, 3)) \
- fw_def(DG1, 0, guc_maj(dg1, 70, 5)) \
+ fw_def(DG1, 0, guc_maj(dg1, 70, 5, 1)) \
fw_def(ROCKETLAKE, 0, guc_mmp(tgl, 70, 1, 1)) \
fw_def(TIGERLAKE, 0, guc_mmp(tgl, 70, 1, 1)) \
fw_def(JASPERLAKE, 0, guc_mmp(ehl, 70, 1, 1)) \
@@ -101,6 +108,7 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
fw_def(SKYLAKE, 0, guc_mmp(skl, 70, 1, 1))
#define INTEL_HUC_FIRMWARE_DEFS(fw_def, huc_raw, huc_mmp, huc_gsc) \
+ fw_def(METEORLAKE, 0, huc_gsc(mtl)) \
fw_def(DG2, 0, huc_gsc(dg2)) \
fw_def(ALDERLAKE_P, 0, huc_raw(tgl)) \
fw_def(ALDERLAKE_P, 0, huc_mmp(tgl, 7, 9, 3)) \
@@ -140,7 +148,7 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
__stringify(patch_) ".bin"
/* Minor for internal driver use, not part of file name */
-#define MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_) \
+#define MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_, patch_) \
__MAKE_UC_FW_PATH_MAJOR(prefix_, "guc", major_)
#define MAKE_GUC_FW_PATH_MMP(prefix_, major_, minor_, patch_) \
@@ -179,7 +187,7 @@ struct __packed uc_fw_blob {
u8 major;
u8 minor;
u8 patch;
- bool loaded_via_gsc;
+ bool has_gsc_headers;
};
#define UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \
@@ -190,15 +198,15 @@ struct __packed uc_fw_blob {
#define UC_FW_BLOB_NEW(major_, minor_, patch_, gsc_, path_) \
{ UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \
- .legacy = false, .loaded_via_gsc = gsc_ }
+ .legacy = false, .has_gsc_headers = gsc_ }
#define UC_FW_BLOB_OLD(major_, minor_, patch_, path_) \
{ UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \
.legacy = true }
-#define GUC_FW_BLOB(prefix_, major_, minor_) \
- UC_FW_BLOB_NEW(major_, minor_, 0, false, \
- MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_))
+#define GUC_FW_BLOB(prefix_, major_, minor_, patch_) \
+ UC_FW_BLOB_NEW(major_, minor_, patch_, false, \
+ MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_, patch_))
#define GUC_FW_BLOB_MMP(prefix_, major_, minor_, patch_) \
UC_FW_BLOB_OLD(major_, minor_, patch_, \
@@ -232,20 +240,22 @@ struct fw_blobs_by_type {
u32 count;
};
+static const struct uc_fw_platform_requirement blobs_guc[] = {
+ INTEL_GUC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, GUC_FW_BLOB_MMP)
+};
+
+static const struct uc_fw_platform_requirement blobs_huc[] = {
+ INTEL_HUC_FIRMWARE_DEFS(MAKE_FW_LIST, HUC_FW_BLOB, HUC_FW_BLOB_MMP, HUC_FW_BLOB_GSC)
+};
+
+static const struct fw_blobs_by_type blobs_all[INTEL_UC_FW_NUM_TYPES] = {
+ [INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc) },
+ [INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc) },
+};
+
static void
__uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
{
- static const struct uc_fw_platform_requirement blobs_guc[] = {
- INTEL_GUC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, GUC_FW_BLOB_MMP)
- };
- static const struct uc_fw_platform_requirement blobs_huc[] = {
- INTEL_HUC_FIRMWARE_DEFS(MAKE_FW_LIST, HUC_FW_BLOB, HUC_FW_BLOB_MMP, HUC_FW_BLOB_GSC)
- };
- static const struct fw_blobs_by_type blobs_all[INTEL_UC_FW_NUM_TYPES] = {
- [INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc) },
- [INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc) },
- };
- static bool verified[INTEL_UC_FW_NUM_TYPES];
const struct uc_fw_platform_requirement *fw_blobs;
enum intel_platform p = INTEL_INFO(i915)->platform;
u32 fw_count;
@@ -285,6 +295,11 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
continue;
if (uc_fw->file_selected.path) {
+ /*
+ * Continuing an earlier search after a found blob failed to load.
+ * Once the previously chosen path has been found, clear it out
+ * and let the search continue from there.
+ */
if (uc_fw->file_selected.path == blob->path)
uc_fw->file_selected.path = NULL;
@@ -295,7 +310,8 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
uc_fw->file_wanted.path = blob->path;
uc_fw->file_wanted.ver.major = blob->major;
uc_fw->file_wanted.ver.minor = blob->minor;
- uc_fw->loaded_via_gsc = blob->loaded_via_gsc;
+ uc_fw->file_wanted.ver.patch = blob->patch;
+ uc_fw->has_gsc_headers = blob->has_gsc_headers;
found = true;
break;
}
@@ -304,76 +320,111 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
/* Failed to find a match for the last attempt?! */
uc_fw->file_selected.path = NULL;
}
+}
- /* make sure the list is ordered as expected */
- if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST) && !verified[uc_fw->type]) {
- verified[uc_fw->type] = true;
+static bool validate_fw_table_type(struct drm_i915_private *i915, enum intel_uc_fw_type type)
+{
+ const struct uc_fw_platform_requirement *fw_blobs;
+ u32 fw_count;
+ int i, j;
+
+ if (type >= ARRAY_SIZE(blobs_all)) {
+ drm_err(&i915->drm, "No blob array for %s\n", intel_uc_fw_type_repr(type));
+ return false;
+ }
+
+ fw_blobs = blobs_all[type].blobs;
+ fw_count = blobs_all[type].count;
- for (i = 1; i < fw_count; i++) {
- /* Next platform is good: */
- if (fw_blobs[i].p < fw_blobs[i - 1].p)
+ if (!fw_count)
+ return true;
+
+ /* make sure the list is ordered as expected */
+ for (i = 1; i < fw_count; i++) {
+ /* Versionless file names must be unique per platform: */
+ for (j = i + 1; j < fw_count; j++) {
+ /* Same platform? */
+ if (fw_blobs[i].p != fw_blobs[j].p)
continue;
- /* Next platform revision is good: */
- if (fw_blobs[i].p == fw_blobs[i - 1].p &&
- fw_blobs[i].rev < fw_blobs[i - 1].rev)
+ if (fw_blobs[i].blob.path != fw_blobs[j].blob.path)
continue;
- /* Platform/revision must be in order: */
- if (fw_blobs[i].p != fw_blobs[i - 1].p ||
- fw_blobs[i].rev != fw_blobs[i - 1].rev)
- goto bad;
+ drm_err(&i915->drm, "Duplicate %s blobs: %s r%u %s%d.%d.%d [%s] matches %s%d.%d.%d [%s]\n",
+ intel_uc_fw_type_repr(type),
+ intel_platform_name(fw_blobs[j].p), fw_blobs[j].rev,
+ fw_blobs[j].blob.legacy ? "L" : "v",
+ fw_blobs[j].blob.major, fw_blobs[j].blob.minor,
+ fw_blobs[j].blob.patch, fw_blobs[j].blob.path,
+ fw_blobs[i].blob.legacy ? "L" : "v",
+ fw_blobs[i].blob.major, fw_blobs[i].blob.minor,
+ fw_blobs[i].blob.patch, fw_blobs[i].blob.path);
+ }
- /* Next major version is good: */
- if (fw_blobs[i].blob.major < fw_blobs[i - 1].blob.major)
- continue;
+ /* Next platform is good: */
+ if (fw_blobs[i].p < fw_blobs[i - 1].p)
+ continue;
- /* New must be before legacy: */
- if (!fw_blobs[i].blob.legacy && fw_blobs[i - 1].blob.legacy)
- goto bad;
+ /* Next platform revision is good: */
+ if (fw_blobs[i].p == fw_blobs[i - 1].p &&
+ fw_blobs[i].rev < fw_blobs[i - 1].rev)
+ continue;
- /* New to legacy also means 0.0 to X.Y (HuC), or X.0 to X.Y (GuC) */
- if (fw_blobs[i].blob.legacy && !fw_blobs[i - 1].blob.legacy) {
- if (!fw_blobs[i - 1].blob.major)
- continue;
+ /* Platform/revision must be in order: */
+ if (fw_blobs[i].p != fw_blobs[i - 1].p ||
+ fw_blobs[i].rev != fw_blobs[i - 1].rev)
+ goto bad;
- if (fw_blobs[i].blob.major == fw_blobs[i - 1].blob.major)
- continue;
- }
+ /* Next major version is good: */
+ if (fw_blobs[i].blob.major < fw_blobs[i - 1].blob.major)
+ continue;
- /* Major versions must be in order: */
- if (fw_blobs[i].blob.major != fw_blobs[i - 1].blob.major)
- goto bad;
+ /* New must be before legacy: */
+ if (!fw_blobs[i].blob.legacy && fw_blobs[i - 1].blob.legacy)
+ goto bad;
- /* Next minor version is good: */
- if (fw_blobs[i].blob.minor < fw_blobs[i - 1].blob.minor)
+ /* New to legacy also means 0.0 to X.Y (HuC), or X.0 to X.Y (GuC) */
+ if (fw_blobs[i].blob.legacy && !fw_blobs[i - 1].blob.legacy) {
+ if (!fw_blobs[i - 1].blob.major)
continue;
- /* Minor versions must be in order: */
- if (fw_blobs[i].blob.minor != fw_blobs[i - 1].blob.minor)
- goto bad;
-
- /* Patch versions must be in order: */
- if (fw_blobs[i].blob.patch <= fw_blobs[i - 1].blob.patch)
+ if (fw_blobs[i].blob.major == fw_blobs[i - 1].blob.major)
continue;
+ }
-bad:
- drm_err(&i915->drm, "Invalid %s blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%d\n",
- intel_uc_fw_type_repr(uc_fw->type),
- intel_platform_name(fw_blobs[i - 1].p), fw_blobs[i - 1].rev,
- fw_blobs[i - 1].blob.legacy ? "L" : "v",
- fw_blobs[i - 1].blob.major,
- fw_blobs[i - 1].blob.minor,
- fw_blobs[i - 1].blob.patch,
- intel_platform_name(fw_blobs[i].p), fw_blobs[i].rev,
- fw_blobs[i].blob.legacy ? "L" : "v",
- fw_blobs[i].blob.major,
- fw_blobs[i].blob.minor,
- fw_blobs[i].blob.patch);
+ /* Major versions must be in order: */
+ if (fw_blobs[i].blob.major != fw_blobs[i - 1].blob.major)
+ goto bad;
- uc_fw->file_selected.path = NULL;
- }
+ /* Next minor version is good: */
+ if (fw_blobs[i].blob.minor < fw_blobs[i - 1].blob.minor)
+ continue;
+
+ /* Minor versions must be in order: */
+ if (fw_blobs[i].blob.minor != fw_blobs[i - 1].blob.minor)
+ goto bad;
+
+ /* Patch versions must be in order and unique: */
+ if (fw_blobs[i].blob.patch < fw_blobs[i - 1].blob.patch)
+ continue;
+
+bad:
+ drm_err(&i915->drm, "Invalid %s blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%d\n",
+ intel_uc_fw_type_repr(type),
+ intel_platform_name(fw_blobs[i - 1].p), fw_blobs[i - 1].rev,
+ fw_blobs[i - 1].blob.legacy ? "L" : "v",
+ fw_blobs[i - 1].blob.major,
+ fw_blobs[i - 1].blob.minor,
+ fw_blobs[i - 1].blob.patch,
+ intel_platform_name(fw_blobs[i].p), fw_blobs[i].rev,
+ fw_blobs[i].blob.legacy ? "L" : "v",
+ fw_blobs[i].blob.major,
+ fw_blobs[i].blob.minor,
+ fw_blobs[i].blob.patch);
+ return false;
}
+
+ return true;
}
static const char *__override_guc_firmware_path(struct drm_i915_private *i915)
@@ -421,14 +472,17 @@ static void __uc_fw_user_override(struct drm_i915_private *i915, struct intel_uc
* intel_uc_fw_init_early - initialize the uC object and select the firmware
* @uc_fw: uC firmware
* @type: type of uC
+ * @needs_ggtt_mapping: whether the FW needs to be GGTT mapped for loading
*
* Initialize the state of our uC object and relevant tracking and select the
* firmware to fetch and load.
*/
void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
- enum intel_uc_fw_type type)
+ enum intel_uc_fw_type type,
+ bool needs_ggtt_mapping)
{
- struct drm_i915_private *i915 = ____uc_fw_to_gt(uc_fw, type)->i915;
+ struct intel_gt *gt = ____uc_fw_to_gt(uc_fw, type);
+ struct drm_i915_private *i915 = gt->i915;
/*
* we use FIRMWARE_UNINITIALIZED to detect checks against uc_fw->status
@@ -439,8 +493,15 @@ void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
GEM_BUG_ON(uc_fw->file_selected.path);
uc_fw->type = type;
+ uc_fw->needs_ggtt_mapping = needs_ggtt_mapping;
if (HAS_GT_UC(i915)) {
+ if (!validate_fw_table_type(i915, type)) {
+ gt->uc.fw_table_invalid = true;
+ intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_NOT_SUPPORTED);
+ return;
+ }
+
__uc_fw_auto_select(i915, uc_fw);
__uc_fw_user_override(i915, uc_fw);
}
@@ -488,33 +549,6 @@ static void __force_fw_fetch_failures(struct intel_uc_fw *uc_fw, int e)
}
}
-static int check_gsc_manifest(struct intel_gt *gt,
- const struct firmware *fw,
- struct intel_uc_fw *uc_fw)
-{
- u32 *dw = (u32 *)fw->data;
- u32 version_hi, version_lo;
- size_t min_size;
-
- /* Check the size of the blob before examining buffer contents */
- min_size = sizeof(u32) * (HUC_GSC_VERSION_LO_DW + 1);
- if (unlikely(fw->size < min_size)) {
- gt_warn(gt, "%s firmware %s: invalid size: %zu < %zu\n",
- intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
- fw->size, min_size);
- return -ENODATA;
- }
-
- version_hi = dw[HUC_GSC_VERSION_HI_DW];
- version_lo = dw[HUC_GSC_VERSION_LO_DW];
-
- uc_fw->file_selected.ver.major = FIELD_GET(HUC_GSC_MAJOR_VER_HI_MASK, version_hi);
- uc_fw->file_selected.ver.minor = FIELD_GET(HUC_GSC_MINOR_VER_HI_MASK, version_hi);
- uc_fw->file_selected.ver.patch = FIELD_GET(HUC_GSC_PATCH_VER_LO_MASK, version_lo);
-
- return 0;
-}
-
static void uc_unpack_css_version(struct intel_uc_fw_ver *ver, u32 css_value)
{
/* Get version numbers from the CSS header */
@@ -571,22 +605,22 @@ static void guc_read_css_info(struct intel_uc_fw *uc_fw, struct uc_css_header *c
uc_fw->private_data_size = css->private_data_size;
}
-static int check_ccs_header(struct intel_gt *gt,
- const struct firmware *fw,
- struct intel_uc_fw *uc_fw)
+static int __check_ccs_header(struct intel_gt *gt,
+ const void *fw_data, size_t fw_size,
+ struct intel_uc_fw *uc_fw)
{
struct uc_css_header *css;
size_t size;
/* Check the size of the blob before examining buffer contents */
- if (unlikely(fw->size < sizeof(struct uc_css_header))) {
+ if (unlikely(fw_size < sizeof(struct uc_css_header))) {
gt_warn(gt, "%s firmware %s: invalid size: %zu < %zu\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
- fw->size, sizeof(struct uc_css_header));
+ fw_size, sizeof(struct uc_css_header));
return -ENODATA;
}
- css = (struct uc_css_header *)fw->data;
+ css = (struct uc_css_header *)fw_data;
/* Check integrity of size values inside CSS header */
size = (css->header_size_dw - css->key_size_dw - css->modulus_size_dw -
@@ -594,7 +628,7 @@ static int check_ccs_header(struct intel_gt *gt,
if (unlikely(size != sizeof(struct uc_css_header))) {
gt_warn(gt, "%s firmware %s: unexpected header size: %zu != %zu\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
- fw->size, sizeof(struct uc_css_header));
+ fw_size, sizeof(struct uc_css_header));
return -EPROTO;
}
@@ -606,10 +640,10 @@ static int check_ccs_header(struct intel_gt *gt,
/* At least, it should have header, uCode and RSA. Size of all three. */
size = sizeof(struct uc_css_header) + uc_fw->ucode_size + uc_fw->rsa_size;
- if (unlikely(fw->size < size)) {
+ if (unlikely(fw_size < size)) {
gt_warn(gt, "%s firmware %s: invalid size: %zu < %zu\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
- fw->size, size);
+ fw_size, size);
return -ENOEXEC;
}
@@ -630,6 +664,33 @@ static int check_ccs_header(struct intel_gt *gt,
return 0;
}
+static int check_gsc_manifest(struct intel_gt *gt,
+ const struct firmware *fw,
+ struct intel_uc_fw *uc_fw)
+{
+ if (uc_fw->type != INTEL_UC_FW_TYPE_HUC) {
+ gt_err(gt, "trying to GSC-parse a non-HuC binary");
+ return -EINVAL;
+ }
+
+ intel_huc_fw_get_binary_info(uc_fw, fw->data, fw->size);
+
+ if (uc_fw->dma_start_offset) {
+ u32 delta = uc_fw->dma_start_offset;
+
+ __check_ccs_header(gt, fw->data + delta, fw->size - delta, uc_fw);
+ }
+
+ return 0;
+}
+
+static int check_ccs_header(struct intel_gt *gt,
+ const struct firmware *fw,
+ struct intel_uc_fw *uc_fw)
+{
+ return __check_ccs_header(gt, fw->data, fw->size, uc_fw);
+}
+
static bool is_ver_8bit(struct intel_uc_fw_ver *ver)
{
return ver->major < 0xFF && ver->minor < 0xFF && ver->patch < 0xFF;
@@ -677,7 +738,7 @@ static int check_fw_header(struct intel_gt *gt,
if (uc_fw->type == INTEL_UC_FW_TYPE_GSC)
return 0;
- if (uc_fw->loaded_via_gsc)
+ if (uc_fw->has_gsc_headers)
err = check_gsc_manifest(gt, fw, uc_fw);
else
err = check_ccs_header(gt, fw, uc_fw);
@@ -698,7 +759,7 @@ static int try_firmware_load(struct intel_uc_fw *uc_fw, const struct firmware **
if (err)
return err;
- if ((*fw)->size > INTEL_UC_RSVD_GGTT_PER_FW) {
+ if (uc_fw->needs_ggtt_mapping && (*fw)->size > INTEL_UC_RSVD_GGTT_PER_FW) {
gt_err(gt, "%s firmware %s: size (%zuKB) exceeds max supported size (%uKB)\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
(*fw)->size / SZ_1K, INTEL_UC_RSVD_GGTT_PER_FW / SZ_1K);
@@ -782,10 +843,10 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
if (uc_fw->file_wanted.ver.major && uc_fw->file_selected.ver.major) {
/* Check the file's major version was as it claimed */
if (uc_fw->file_selected.ver.major != uc_fw->file_wanted.ver.major) {
- gt_notice(gt, "%s firmware %s: unexpected version: %u.%u != %u.%u\n",
- intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
- uc_fw->file_selected.ver.major, uc_fw->file_selected.ver.minor,
- uc_fw->file_wanted.ver.major, uc_fw->file_wanted.ver.minor);
+ UNEXPECTED(gt, "%s firmware %s: unexpected version: %u.%u != %u.%u\n",
+ intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
+ uc_fw->file_selected.ver.major, uc_fw->file_selected.ver.minor,
+ uc_fw->file_wanted.ver.major, uc_fw->file_wanted.ver.minor);
if (!intel_uc_fw_is_overridden(uc_fw)) {
err = -ENOEXEC;
goto fail;
@@ -793,6 +854,9 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
} else {
if (uc_fw->file_selected.ver.minor < uc_fw->file_wanted.ver.minor)
old_ver = true;
+ else if ((uc_fw->file_selected.ver.minor == uc_fw->file_wanted.ver.minor) &&
+ (uc_fw->file_selected.ver.patch < uc_fw->file_wanted.ver.patch))
+ old_ver = true;
}
}
@@ -800,12 +864,16 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
/* Preserve the version that was really wanted */
memcpy(&uc_fw->file_wanted, &file_ideal, sizeof(uc_fw->file_wanted));
- gt_notice(gt, "%s firmware %s (%d.%d) is recommended, but only %s (%d.%d) was found\n",
- intel_uc_fw_type_repr(uc_fw->type),
- uc_fw->file_wanted.path,
- uc_fw->file_wanted.ver.major, uc_fw->file_wanted.ver.minor,
- uc_fw->file_selected.path,
- uc_fw->file_selected.ver.major, uc_fw->file_selected.ver.minor);
+ UNEXPECTED(gt, "%s firmware %s (%d.%d.%d) is recommended, but only %s (%d.%d.%d) was found\n",
+ intel_uc_fw_type_repr(uc_fw->type),
+ uc_fw->file_wanted.path,
+ uc_fw->file_wanted.ver.major,
+ uc_fw->file_wanted.ver.minor,
+ uc_fw->file_wanted.ver.patch,
+ uc_fw->file_selected.path,
+ uc_fw->file_selected.ver.major,
+ uc_fw->file_selected.ver.minor,
+ uc_fw->file_selected.ver.patch);
gt_info(gt, "Consider updating your linux-firmware pkg or downloading from %s\n",
INTEL_UC_FIRMWARE_URL);
}
@@ -876,35 +944,46 @@ static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw)
{
struct drm_i915_gem_object *obj = uc_fw->obj;
struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
- struct i915_vma_resource *dummy = &uc_fw->dummy;
+ struct i915_vma_resource *vma_res = &uc_fw->vma_res;
u32 pte_flags = 0;
- dummy->start = uc_fw_ggtt_offset(uc_fw);
- dummy->node_size = obj->base.size;
- dummy->bi.pages = obj->mm.pages;
+ if (!uc_fw->needs_ggtt_mapping)
+ return;
+
+ vma_res->start = uc_fw_ggtt_offset(uc_fw);
+ vma_res->node_size = obj->base.size;
+ vma_res->bi.pages = obj->mm.pages;
GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
/* uc_fw->obj cache domains were not controlled across suspend */
if (i915_gem_object_has_struct_page(obj))
- drm_clflush_sg(dummy->bi.pages);
+ drm_clflush_sg(vma_res->bi.pages);
if (i915_gem_object_is_lmem(obj))
pte_flags |= PTE_LM;
if (ggtt->vm.raw_insert_entries)
- ggtt->vm.raw_insert_entries(&ggtt->vm, dummy, I915_CACHE_NONE, pte_flags);
+ ggtt->vm.raw_insert_entries(&ggtt->vm, vma_res,
+ i915_gem_get_pat_index(ggtt->vm.i915,
+ I915_CACHE_NONE),
+ pte_flags);
else
- ggtt->vm.insert_entries(&ggtt->vm, dummy, I915_CACHE_NONE, pte_flags);
+ ggtt->vm.insert_entries(&ggtt->vm, vma_res,
+ i915_gem_get_pat_index(ggtt->vm.i915,
+ I915_CACHE_NONE),
+ pte_flags);
}
static void uc_fw_unbind_ggtt(struct intel_uc_fw *uc_fw)
{
- struct drm_i915_gem_object *obj = uc_fw->obj;
struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
- u64 start = uc_fw_ggtt_offset(uc_fw);
+ struct i915_vma_resource *vma_res = &uc_fw->vma_res;
- ggtt->vm.clear_range(&ggtt->vm, start, obj->base.size);
+ if (!vma_res->node_size)
+ return;
+
+ ggtt->vm.clear_range(&ggtt->vm, vma_res->start, vma_res->node_size);
}
static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
@@ -921,7 +1000,7 @@ static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
/* Set the source address for the uCode */
- offset = uc_fw_ggtt_offset(uc_fw);
+ offset = uc_fw->vma_res.start + uc_fw->dma_start_offset;
GEM_BUG_ON(upper_32_bits(offset) & 0xFFFF0000);
intel_uncore_write_fw(uncore, DMA_ADDR_0_LOW, lower_32_bits(offset));
intel_uncore_write_fw(uncore, DMA_ADDR_0_HIGH, upper_32_bits(offset));
@@ -995,9 +1074,7 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
return -ENOEXEC;
/* Call custom loader */
- uc_fw_bind_ggtt(uc_fw);
err = uc_fw_xfer(uc_fw, dst_offset, dma_flags);
- uc_fw_unbind_ggtt(uc_fw);
if (err)
goto fail;
@@ -1101,6 +1178,8 @@ int intel_uc_fw_init(struct intel_uc_fw *uc_fw)
goto out_unpin;
}
+ uc_fw_bind_ggtt(uc_fw);
+
return 0;
out_unpin:
@@ -1111,6 +1190,7 @@ out:
void intel_uc_fw_fini(struct intel_uc_fw *uc_fw)
{
+ uc_fw_unbind_ggtt(uc_fw);
uc_fw_rsa_data_destroy(uc_fw);
if (i915_gem_object_has_pinned_pages(uc_fw->obj))
@@ -1119,6 +1199,17 @@ void intel_uc_fw_fini(struct intel_uc_fw *uc_fw)
intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_AVAILABLE);
}
+void intel_uc_fw_resume_mapping(struct intel_uc_fw *uc_fw)
+{
+ if (!intel_uc_fw_is_available(uc_fw))
+ return;
+
+ if (!i915_gem_object_has_pinned_pages(uc_fw->obj))
+ return;
+
+ uc_fw_bind_ggtt(uc_fw);
+}
+
/**
* intel_uc_fw_cleanup_fetch - cleanup uC firmware
* @uc_fw: uC firmware
@@ -1148,7 +1239,7 @@ size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len)
{
struct intel_memory_region *mr = uc_fw->obj->mm.region;
u32 size = min_t(u32, uc_fw->rsa_size, max_len);
- u32 offset = sizeof(struct uc_css_header) + uc_fw->ucode_size;
+ u32 offset = uc_fw->dma_start_offset + sizeof(struct uc_css_header) + uc_fw->ucode_size;
struct sgt_iter iter;
size_t count = 0;
int idx;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
index 6ba00e6b3975..054f02811971 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
@@ -99,20 +99,28 @@ struct intel_uc_fw {
struct drm_i915_gem_object *obj;
/**
- * @dummy: A vma used in binding the uc fw to ggtt. We can't define this
- * vma on the stack as it can lead to a stack overflow, so we define it
- * here. Safe to have 1 copy per uc fw because the binding is single
- * threaded as it done during driver load (inherently single threaded)
- * or during a GT reset (mutex guarantees single threaded).
+ * @needs_ggtt_mapping: indicates whether the fw object needs to be
+ * pinned to ggtt. If true, the fw is pinned at init time and unpinned
+ * during driver unload.
*/
- struct i915_vma_resource dummy;
+ bool needs_ggtt_mapping;
+
+ /**
+ * @vma_res: A vma resource used in binding the uc fw to ggtt. The fw is
+ * pinned in a reserved area of the ggtt (above the maximum address
+ * usable by GuC); therefore, we can't use the normal vma functions to
+ * do the pinning and we instead use this resource to do so.
+ */
+ struct i915_vma_resource vma_res;
struct i915_vma *rsa_data;
u32 rsa_size;
u32 ucode_size;
u32 private_data_size;
- bool loaded_via_gsc;
+ u32 dma_start_offset;
+
+ bool has_gsc_headers;
};
/*
@@ -282,12 +290,14 @@ static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw)
}
void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
- enum intel_uc_fw_type type);
+ enum intel_uc_fw_type type,
+ bool needs_ggtt_mapping);
int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw);
void intel_uc_fw_cleanup_fetch(struct intel_uc_fw *uc_fw);
int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 offset, u32 dma_flags);
int intel_uc_fw_init(struct intel_uc_fw *uc_fw);
void intel_uc_fw_fini(struct intel_uc_fw *uc_fw);
+void intel_uc_fw_resume_mapping(struct intel_uc_fw *uc_fw);
size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len);
int intel_uc_fw_mark_load_failed(struct intel_uc_fw *uc_fw, int err);
void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h
index 646fa8aa6cf1..7fe405126249 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h
@@ -84,10 +84,4 @@ struct uc_css_header {
} __packed;
static_assert(sizeof(struct uc_css_header) == 128);
-#define HUC_GSC_VERSION_HI_DW 44
-#define HUC_GSC_MAJOR_VER_HI_MASK (0xFF << 0)
-#define HUC_GSC_MINOR_VER_HI_MASK (0xFF << 16)
-#define HUC_GSC_VERSION_LO_DW 45
-#define HUC_GSC_PATCH_VER_LO_MASK (0xFF << 0)
-
#endif /* _INTEL_UC_FW_ABI_H */
diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c
index 076c779f776a..eedd1865bb98 100644
--- a/drivers/gpu/drm/i915/gvt/aperture_gm.c
+++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c
@@ -330,7 +330,7 @@ void intel_vgpu_reset_resource(struct intel_vgpu *vgpu)
/**
* intel_vgpu_alloc_resource() - allocate HW resource for a vGPU
* @vgpu: vGPU
- * @param: vGPU creation params
+ * @conf: vGPU creation params
*
* This function is used to allocate HW resource for a vGPU. User specifies
* the resource configuration through the creation params.
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c
index 3c4ae1da0d41..05f9348b7a9d 100644
--- a/drivers/gpu/drm/i915/gvt/cmd_parser.c
+++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c
@@ -2833,7 +2833,7 @@ static int command_scan(struct parser_exec_state *s,
static int scan_workload(struct intel_vgpu_workload *workload)
{
- unsigned long gma_head, gma_tail, gma_bottom;
+ unsigned long gma_head, gma_tail;
struct parser_exec_state s;
int ret = 0;
@@ -2843,7 +2843,6 @@ static int scan_workload(struct intel_vgpu_workload *workload)
gma_head = workload->rb_start + workload->rb_head;
gma_tail = workload->rb_start + workload->rb_tail;
- gma_bottom = workload->rb_start + _RING_CTL_BUF_SIZE(workload->rb_ctl);
s.buf_type = RING_BUFFER_INSTRUCTION;
s.buf_addr_type = GTT_BUFFER;
@@ -2874,7 +2873,7 @@ out:
static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
{
- unsigned long gma_head, gma_tail, gma_bottom, ring_size, ring_tail;
+ unsigned long gma_head, gma_tail, ring_size, ring_tail;
struct parser_exec_state s;
int ret = 0;
struct intel_vgpu_workload *workload = container_of(wa_ctx,
@@ -2891,7 +2890,6 @@ static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
PAGE_SIZE);
gma_head = wa_ctx->indirect_ctx.guest_gma;
gma_tail = wa_ctx->indirect_ctx.guest_gma + ring_tail;
- gma_bottom = wa_ctx->indirect_ctx.guest_gma + ring_size;
s.buf_type = RING_BUFFER_INSTRUCTION;
s.buf_addr_type = GTT_BUFFER;
diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c
index 7c49a3d673a5..2a0438f12a14 100644
--- a/drivers/gpu/drm/i915/gvt/edid.c
+++ b/drivers/gpu/drm/i915/gvt/edid.c
@@ -463,10 +463,6 @@ static inline int get_aux_ch_reg(unsigned int offset)
return reg;
}
-#define AUX_CTL_MSG_LENGTH(reg) \
- ((reg & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> \
- DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT)
-
/**
* intel_gvt_i2c_handle_aux_ch_write - emulate AUX channel register write
* @vgpu: a vGPU
@@ -495,7 +491,8 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
return;
}
- msg_length = AUX_CTL_MSG_LENGTH(value);
+ msg_length = REG_FIELD_GET(DP_AUX_CH_CTL_MESSAGE_SIZE_MASK, reg);
+
// check the msg in DATA register.
msg = vgpu_vreg(vgpu, offset + 4);
addr = (msg >> 8) & 0xffff;
@@ -510,8 +507,7 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
ret_msg_size = (((op & 0x1) == GVT_AUX_I2C_READ) ? 2 : 1);
vgpu_vreg(vgpu, offset) =
DP_AUX_CH_CTL_DONE |
- ((ret_msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) &
- DP_AUX_CH_CTL_MESSAGE_SIZE_MASK);
+ DP_AUX_CH_CTL_MESSAGE_SIZE(ret_msg_size);
if (msg_length == 3) {
if (!(op & GVT_AUX_I2C_MOT)) {
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c
index 4b45a041ac5c..a9f7fa9b90bd 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -1562,7 +1562,7 @@ static int pf_write(struct intel_vgpu *vgpu,
if ((offset == _PS_1A_CTRL || offset == _PS_2A_CTRL ||
offset == _PS_1B_CTRL || offset == _PS_2B_CTRL ||
- offset == _PS_1C_CTRL) && (val & PS_PLANE_SEL_MASK) != 0) {
+ offset == _PS_1C_CTRL) && (val & PS_BINDING_MASK) != PS_BINDING_PIPE) {
drm_WARN_ONCE(&i915->drm, true,
"VM(%d): guest is trying to scaling a plane\n",
vgpu->id);
diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h
index 7eb44132183a..77c676ecc263 100644
--- a/drivers/gpu/drm/i915/i915_active.h
+++ b/drivers/gpu/drm/i915/i915_active.h
@@ -49,9 +49,9 @@ void i915_active_noop(struct dma_fence *fence, struct dma_fence_cb *cb);
/**
* __i915_active_fence_init - prepares the activity tracker for use
- * @active - the active tracker
- * @fence - initial fence to track, can be NULL
- * @func - a callback when then the tracker is retired (becomes idle),
+ * @active: the active tracker
+ * @fence: initial fence to track, can be NULL
+ * @fn: a callback when then the tracker is retired (becomes idle),
* can be NULL
*
* i915_active_fence_init() prepares the embedded @active struct for use as
@@ -77,8 +77,8 @@ __i915_active_fence_set(struct i915_active_fence *active,
/**
* i915_active_fence_set - updates the tracker to watch the current fence
- * @active - the active tracker
- * @rq - the request to watch
+ * @active: the active tracker
+ * @rq: the request to watch
*
* i915_active_fence_set() watches the given @rq for completion. While
* that @rq is busy, the @active reports busy. When that @rq is signaled
@@ -89,7 +89,7 @@ i915_active_fence_set(struct i915_active_fence *active,
struct i915_request *rq);
/**
* i915_active_fence_get - return a reference to the active fence
- * @active - the active tracker
+ * @active: the active tracker
*
* i915_active_fence_get() returns a reference to the active fence,
* or NULL if the active tracker is idle. The reference is obtained under RCU,
@@ -111,7 +111,7 @@ i915_active_fence_get(struct i915_active_fence *active)
/**
* i915_active_fence_isset - report whether the active tracker is assigned
- * @active - the active tracker
+ * @active: the active tracker
*
* i915_active_fence_isset() returns true if the active tracker is currently
* assigned to a fence. Due to the lazy retiring, that fence may be idle
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 80c2bf98e341..76ccd4e03e31 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -50,6 +50,7 @@
#include "i915_debugfs_params.h"
#include "i915_driver.h"
#include "i915_irq.h"
+#include "i915_reg.h"
#include "i915_scheduler.h"
#include "intel_mchbar_regs.h"
@@ -138,21 +139,54 @@ static const char *stringify_vma_type(const struct i915_vma *vma)
return "ppgtt";
}
-static const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
+static const char *i915_cache_level_str(struct drm_i915_gem_object *obj)
{
- switch (type) {
- case I915_CACHE_NONE: return " uncached";
- case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped";
- case I915_CACHE_L3_LLC: return " L3+LLC";
- case I915_CACHE_WT: return " WT";
- default: return "";
+ struct drm_i915_private *i915 = obj_to_i915(obj);
+
+ if (IS_METEORLAKE(i915)) {
+ switch (obj->pat_index) {
+ case 0: return " WB";
+ case 1: return " WT";
+ case 2: return " UC";
+ case 3: return " WB (1-Way Coh)";
+ case 4: return " WB (2-Way Coh)";
+ default: return " not defined";
+ }
+ } else if (IS_PONTEVECCHIO(i915)) {
+ switch (obj->pat_index) {
+ case 0: return " UC";
+ case 1: return " WC";
+ case 2: return " WT";
+ case 3: return " WB";
+ case 4: return " WT (CLOS1)";
+ case 5: return " WB (CLOS1)";
+ case 6: return " WT (CLOS2)";
+ case 7: return " WT (CLOS2)";
+ default: return " not defined";
+ }
+ } else if (GRAPHICS_VER(i915) >= 12) {
+ switch (obj->pat_index) {
+ case 0: return " WB";
+ case 1: return " WC";
+ case 2: return " WT";
+ case 3: return " UC";
+ default: return " not defined";
+ }
+ } else {
+ switch (obj->pat_index) {
+ case 0: return " UC";
+ case 1: return HAS_LLC(i915) ?
+ " LLC" : " snooped";
+ case 2: return " L3+LLC";
+ case 3: return " WT";
+ default: return " not defined";
+ }
}
}
void
i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
{
- struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
struct i915_vma *vma;
int pin_count = 0;
@@ -164,7 +198,7 @@ i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
obj->base.size / 1024,
obj->read_domains,
obj->write_domain,
- i915_cache_level_str(dev_priv, obj->cache_level),
+ i915_cache_level_str(obj),
obj->mm.dirty ? " dirty" : "",
obj->mm.madv == I915_MADV_DONTNEED ? " purgeable" : "");
if (obj->base.name)
diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c
index 93fdc40d724f..0ad0c5885ec2 100644
--- a/drivers/gpu/drm/i915/i915_driver.c
+++ b/drivers/gpu/drm/i915/i915_driver.c
@@ -48,6 +48,7 @@
#include "display/intel_acpi.h"
#include "display/intel_bw.h"
#include "display/intel_cdclk.h"
+#include "display/intel_display_driver.h"
#include "display/intel_display_types.h"
#include "display/intel_dmc.h"
#include "display/intel_dp.h"
@@ -131,8 +132,20 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv)
if (dev_priv->display.hotplug.dp_wq == NULL)
goto out_free_wq;
+ /*
+ * The unordered i915 workqueue should be used for all work
+ * scheduling that do not require running in order, which used
+ * to be scheduled on the system_wq before moving to a driver
+ * instance due deprecation of flush_scheduled_work().
+ */
+ dev_priv->unordered_wq = alloc_workqueue("i915-unordered", 0, 0);
+ if (dev_priv->unordered_wq == NULL)
+ goto out_free_dp_wq;
+
return 0;
+out_free_dp_wq:
+ destroy_workqueue(dev_priv->display.hotplug.dp_wq);
out_free_wq:
destroy_workqueue(dev_priv->wq);
out_err:
@@ -143,6 +156,7 @@ out_err:
static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
{
+ destroy_workqueue(dev_priv->unordered_wq);
destroy_workqueue(dev_priv->display.hotplug.dp_wq);
destroy_workqueue(dev_priv->wq);
}
@@ -221,8 +235,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
mutex_init(&dev_priv->display.audio.mutex);
mutex_init(&dev_priv->display.wm.wm_mutex);
mutex_init(&dev_priv->display.pps.mutex);
- mutex_init(&dev_priv->display.hdcp.comp_mutex);
- spin_lock_init(&dev_priv->display.dkl.phy_lock);
+ mutex_init(&dev_priv->display.hdcp.hdcp_mutex);
i915_memcpy_init_early(dev_priv);
intel_runtime_pm_init_early(&dev_priv->runtime_pm);
@@ -243,15 +256,13 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
if (ret < 0)
goto err_rootgt;
- i915_drm_clients_init(&dev_priv->clients, dev_priv);
-
i915_gem_init_early(dev_priv);
/* This must be called before any calls to HAS_PCH_* */
intel_detect_pch(dev_priv);
intel_irq_init(dev_priv);
- intel_init_display_hooks(dev_priv);
+ intel_display_driver_early_probe(dev_priv);
intel_clock_gating_hooks_init(dev_priv);
intel_detect_preproduction_hw(dev_priv);
@@ -278,7 +289,6 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv)
intel_power_domains_cleanup(dev_priv);
i915_gem_cleanup_early(dev_priv);
intel_gt_driver_late_release_all(dev_priv);
- i915_drm_clients_fini(&dev_priv->clients);
intel_region_ttm_device_fini(dev_priv);
vlv_suspend_cleanup(dev_priv);
i915_workqueues_cleanup(dev_priv);
@@ -720,8 +730,6 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent)
{
const struct intel_device_info *match_info =
(struct intel_device_info *)ent->driver_data;
- struct intel_device_info *device_info;
- struct intel_runtime_info *runtime;
struct drm_i915_private *i915;
i915 = devm_drm_dev_alloc(&pdev->dev, &i915_drm_driver,
@@ -734,14 +742,8 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Device parameters start as a copy of module parameters. */
i915_params_copy(&i915->params, &i915_modparams);
- /* Setup the write-once "constant" device info */
- device_info = mkwrite_device_info(i915);
- memcpy(device_info, match_info, sizeof(*device_info));
-
- /* Initialize initial runtime info from static const data and pdev. */
- runtime = RUNTIME_INFO(i915);
- memcpy(runtime, &INTEL_INFO(i915)->__runtime, sizeof(*runtime));
- runtime->device_id = pdev->device;
+ /* Set up device info and initial runtime info. */
+ intel_device_info_driver_create(i915, pdev->device, match_info);
return i915;
}
@@ -752,7 +754,7 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent)
* @ent: matching PCI ID entry
*
* The driver probe routine has to do several things:
- * - drive output discovery via intel_modeset_init()
+ * - drive output discovery via intel_display_driver_probe()
* - initialize the memory manager
* - allocate initial config memory
* - setup the DRM framebuffer with the allocated memory
@@ -762,13 +764,17 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct drm_i915_private *i915;
int ret;
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ pr_err("Failed to enable graphics device: %pe\n", ERR_PTR(ret));
+ return ret;
+ }
+
i915 = i915_driver_create(pdev, ent);
- if (IS_ERR(i915))
+ if (IS_ERR(i915)) {
+ pci_disable_device(pdev);
return PTR_ERR(i915);
-
- ret = pci_enable_device(pdev);
- if (ret)
- goto out_fini;
+ }
ret = i915_driver_early_probe(i915);
if (ret < 0)
@@ -790,7 +796,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret < 0)
goto out_cleanup_mmio;
- ret = intel_modeset_init_noirq(i915);
+ ret = intel_display_driver_probe_noirq(i915);
if (ret < 0)
goto out_cleanup_hw;
@@ -798,7 +804,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
goto out_cleanup_modeset;
- ret = intel_modeset_init_nogem(i915);
+ ret = intel_display_driver_probe_nogem(i915);
if (ret)
goto out_cleanup_irq;
@@ -808,7 +814,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
intel_pxp_init(i915);
- ret = intel_modeset_init(i915);
+ ret = intel_display_driver_probe(i915);
if (ret)
goto out_cleanup_gem;
@@ -828,14 +834,14 @@ out_cleanup_gem:
i915_gem_driver_release(i915);
out_cleanup_modeset2:
/* FIXME clean up the error path */
- intel_modeset_driver_remove(i915);
+ intel_display_driver_remove(i915);
intel_irq_uninstall(i915);
- intel_modeset_driver_remove_noirq(i915);
+ intel_display_driver_remove_noirq(i915);
goto out_cleanup_modeset;
out_cleanup_irq:
intel_irq_uninstall(i915);
out_cleanup_modeset:
- intel_modeset_driver_remove_nogem(i915);
+ intel_display_driver_remove_nogem(i915);
out_cleanup_hw:
i915_driver_hw_remove(i915);
intel_memory_regions_driver_release(i915);
@@ -851,7 +857,6 @@ out_runtime_pm_put:
i915_driver_late_release(i915);
out_pci_disable:
pci_disable_device(pdev);
-out_fini:
i915_probe_error(i915, "Device initialization failed (%d)\n", ret);
return ret;
}
@@ -871,16 +876,16 @@ void i915_driver_remove(struct drm_i915_private *i915)
intel_gvt_driver_remove(i915);
- intel_modeset_driver_remove(i915);
+ intel_display_driver_remove(i915);
intel_irq_uninstall(i915);
- intel_modeset_driver_remove_noirq(i915);
+ intel_display_driver_remove_noirq(i915);
i915_reset_error_state(i915);
i915_gem_driver_remove(i915);
- intel_modeset_driver_remove_nogem(i915);
+ intel_display_driver_remove_nogem(i915);
i915_driver_hw_remove(i915);
@@ -967,11 +972,19 @@ static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
+ /*
+ * TODO: check and remove holding the modeset locks if none of
+ * the encoders depends on this.
+ */
drm_modeset_lock_all(&dev_priv->drm);
for_each_intel_encoder(&dev_priv->drm, encoder)
if (encoder->suspend)
encoder->suspend(encoder);
drm_modeset_unlock_all(&dev_priv->drm);
+
+ for_each_intel_encoder(&dev_priv->drm, encoder)
+ if (encoder->suspend_complete)
+ encoder->suspend_complete(encoder);
}
static void intel_shutdown_encoders(struct drm_i915_private *dev_priv)
@@ -981,11 +994,19 @@ static void intel_shutdown_encoders(struct drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
+ /*
+ * TODO: check and remove holding the modeset locks if none of
+ * the encoders depends on this.
+ */
drm_modeset_lock_all(&dev_priv->drm);
for_each_intel_encoder(&dev_priv->drm, encoder)
if (encoder->shutdown)
encoder->shutdown(encoder);
drm_modeset_unlock_all(&dev_priv->drm);
+
+ for_each_intel_encoder(&dev_priv->drm, encoder)
+ if (encoder->shutdown_complete)
+ encoder->shutdown_complete(encoder);
}
void i915_driver_shutdown(struct drm_i915_private *i915)
@@ -1052,7 +1073,7 @@ static int i915_drm_prepare(struct drm_device *dev)
intel_pxp_suspend_prepare(i915->pxp);
/*
- * NB intel_display_suspend() may issue new requests after we've
+ * NB intel_display_driver_suspend() may issue new requests after we've
* ostensibly marked the GPU as ready-to-sleep here. We need to
* split out that work and pull it forward so that after point,
* the GPU is not woken again.
@@ -1076,7 +1097,7 @@ static int i915_drm_suspend(struct drm_device *dev)
pci_save_state(pdev);
- intel_display_suspend(dev);
+ intel_display_driver_suspend(dev_priv);
intel_dp_mst_suspend(dev_priv);
@@ -1107,18 +1128,6 @@ static int i915_drm_suspend(struct drm_device *dev)
return 0;
}
-static enum i915_drm_suspend_mode
-get_suspend_mode(struct drm_i915_private *dev_priv, bool hibernate)
-{
- if (hibernate)
- return I915_DRM_SUSPEND_HIBERNATE;
-
- if (suspend_to_idle(dev_priv))
- return I915_DRM_SUSPEND_IDLE;
-
- return I915_DRM_SUSPEND_MEM;
-}
-
static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
{
struct drm_i915_private *dev_priv = to_i915(dev);
@@ -1126,6 +1135,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
struct intel_gt *gt;
int ret, i;
+ bool s2idle = !hibernation && suspend_to_idle(dev_priv);
disable_rpm_wakeref_asserts(rpm);
@@ -1136,8 +1146,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
for_each_gt(gt, dev_priv, i)
intel_uncore_suspend(gt->uncore);
- intel_power_domains_suspend(dev_priv,
- get_suspend_mode(dev_priv, hibernation));
+ intel_power_domains_suspend(dev_priv, s2idle);
intel_display_power_suspend_late(dev_priv);
@@ -1233,7 +1242,7 @@ static int i915_drm_resume(struct drm_device *dev)
*
* drm_mode_config_reset() needs AUX interrupts.
*
- * Modeset enabling in intel_modeset_init_hw() also needs working
+ * Modeset enabling in intel_display_driver_init_hw() also needs working
* interrupts.
*/
intel_runtime_pm_enable_interrupts(dev_priv);
@@ -1243,13 +1252,14 @@ static int i915_drm_resume(struct drm_device *dev)
i915_gem_resume(dev_priv);
- intel_modeset_init_hw(dev_priv);
+ intel_display_driver_init_hw(dev_priv);
+
intel_clock_gating_init(dev_priv);
intel_hpd_init(dev_priv);
/* MST sideband requires HPD interrupts enabled */
intel_dp_mst_resume(dev_priv);
- intel_display_resume(dev);
+ intel_display_driver_resume(dev_priv);
intel_hpd_poll_disable(dev_priv);
if (HAS_DISPLAY(dev_priv))
@@ -1706,7 +1716,7 @@ static const struct file_operations i915_driver_fops = {
.compat_ioctl = i915_ioc32_compat_ioctl,
.llseek = noop_llseek,
#ifdef CONFIG_PROC_FS
- .show_fdinfo = i915_drm_client_fdinfo,
+ .show_fdinfo = drm_show_fdinfo,
#endif
};
@@ -1806,6 +1816,7 @@ static const struct drm_driver i915_drm_driver = {
.open = i915_driver_open,
.lastclose = i915_driver_lastclose,
.postclose = i915_driver_postclose,
+ .show_fdinfo = PTR_IF(IS_ENABLED(CONFIG_PROC_FS), i915_drm_client_fdinfo),
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/i915_drm_client.c
index e8fa172ebe5e..2a44b3876cb5 100644
--- a/drivers/gpu/drm/i915/i915_drm_client.c
+++ b/drivers/gpu/drm/i915/i915_drm_client.c
@@ -17,64 +17,29 @@
#include "i915_gem.h"
#include "i915_utils.h"
-void i915_drm_clients_init(struct i915_drm_clients *clients,
- struct drm_i915_private *i915)
-{
- clients->i915 = i915;
- clients->next_id = 0;
-
- xa_init_flags(&clients->xarray, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
-}
-
-struct i915_drm_client *i915_drm_client_add(struct i915_drm_clients *clients)
+struct i915_drm_client *i915_drm_client_alloc(void)
{
struct i915_drm_client *client;
- struct xarray *xa = &clients->xarray;
- int ret;
client = kzalloc(sizeof(*client), GFP_KERNEL);
if (!client)
- return ERR_PTR(-ENOMEM);
-
- xa_lock_irq(xa);
- ret = __xa_alloc_cyclic(xa, &client->id, client, xa_limit_32b,
- &clients->next_id, GFP_KERNEL);
- xa_unlock_irq(xa);
- if (ret < 0)
- goto err;
+ return NULL;
kref_init(&client->kref);
spin_lock_init(&client->ctx_lock);
INIT_LIST_HEAD(&client->ctx_list);
- client->clients = clients;
return client;
-
-err:
- kfree(client);
-
- return ERR_PTR(ret);
}
void __i915_drm_client_free(struct kref *kref)
{
struct i915_drm_client *client =
container_of(kref, typeof(*client), kref);
- struct xarray *xa = &client->clients->xarray;
- unsigned long flags;
- xa_lock_irqsave(xa, flags);
- __xa_erase(xa, client->id);
- xa_unlock_irqrestore(xa, flags);
kfree(client);
}
-void i915_drm_clients_fini(struct i915_drm_clients *clients)
-{
- GEM_BUG_ON(!xa_empty(&clients->xarray));
- xa_destroy(&clients->xarray);
-}
-
#ifdef CONFIG_PROC_FS
static const char * const uabi_class_names[] = {
[I915_ENGINE_CLASS_RENDER] = "render",
@@ -101,38 +66,34 @@ static u64 busy_add(struct i915_gem_context *ctx, unsigned int class)
}
static void
-show_client_class(struct seq_file *m,
+show_client_class(struct drm_printer *p,
+ struct drm_i915_private *i915,
struct i915_drm_client *client,
unsigned int class)
{
- const struct list_head *list = &client->ctx_list;
+ const unsigned int capacity = i915->engine_uabi_class_count[class];
u64 total = atomic64_read(&client->past_runtime[class]);
- const unsigned int capacity =
- client->clients->i915->engine_uabi_class_count[class];
struct i915_gem_context *ctx;
rcu_read_lock();
- list_for_each_entry_rcu(ctx, list, client_link)
+ list_for_each_entry_rcu(ctx, &client->ctx_list, client_link)
total += busy_add(ctx, class);
rcu_read_unlock();
if (capacity)
- seq_printf(m, "drm-engine-%s:\t%llu ns\n",
+ drm_printf(p, "drm-engine-%s:\t%llu ns\n",
uabi_class_names[class], total);
if (capacity > 1)
- seq_printf(m, "drm-engine-capacity-%s:\t%u\n",
+ drm_printf(p, "drm-engine-capacity-%s:\t%u\n",
uabi_class_names[class],
capacity);
}
-void i915_drm_client_fdinfo(struct seq_file *m, struct file *f)
+void i915_drm_client_fdinfo(struct drm_printer *p, struct drm_file *file)
{
- struct drm_file *file = f->private_data;
struct drm_i915_file_private *file_priv = file->driver_priv;
struct drm_i915_private *i915 = file_priv->i915;
- struct i915_drm_client *client = file_priv->client;
- struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
unsigned int i;
/*
@@ -141,20 +102,10 @@ void i915_drm_client_fdinfo(struct seq_file *m, struct file *f)
* ******************************************************************
*/
- seq_printf(m, "drm-driver:\t%s\n", i915->drm.driver->name);
- seq_printf(m, "drm-pdev:\t%04x:%02x:%02x.%d\n",
- pci_domain_nr(pdev->bus), pdev->bus->number,
- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
- seq_printf(m, "drm-client-id:\t%u\n", client->id);
-
- /*
- * Temporarily skip showing client engine information with GuC submission till
- * fetching engine busyness is implemented in the GuC submission backend
- */
- if (GRAPHICS_VER(i915) < 8 || intel_uc_uses_guc_submission(&i915->gt0.uc))
+ if (GRAPHICS_VER(i915) < 8)
return;
for (i = 0; i < ARRAY_SIZE(uabi_class_names); i++)
- show_client_class(m, client, i);
+ show_client_class(p, i915, file_priv->client, i);
}
#endif
diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/i915_drm_client.h
index 69496af996d9..67816c912bca 100644
--- a/drivers/gpu/drm/i915/i915_drm_client.h
+++ b/drivers/gpu/drm/i915/i915_drm_client.h
@@ -9,20 +9,13 @@
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/spinlock.h>
-#include <linux/xarray.h>
#include <uapi/drm/i915_drm.h>
#define I915_LAST_UABI_ENGINE_CLASS I915_ENGINE_CLASS_COMPUTE
-struct drm_i915_private;
-
-struct i915_drm_clients {
- struct drm_i915_private *i915;
-
- struct xarray xarray;
- u32 next_id;
-};
+struct drm_file;
+struct drm_printer;
struct i915_drm_client {
struct kref kref;
@@ -32,17 +25,12 @@ struct i915_drm_client {
spinlock_t ctx_lock; /* For add/remove from ctx_list. */
struct list_head ctx_list; /* List of contexts belonging to client. */
- struct i915_drm_clients *clients;
-
/**
* @past_runtime: Accumulation of pphwsp runtimes from closed contexts.
*/
atomic64_t past_runtime[I915_LAST_UABI_ENGINE_CLASS + 1];
};
-void i915_drm_clients_init(struct i915_drm_clients *clients,
- struct drm_i915_private *i915);
-
static inline struct i915_drm_client *
i915_drm_client_get(struct i915_drm_client *client)
{
@@ -57,12 +45,8 @@ static inline void i915_drm_client_put(struct i915_drm_client *client)
kref_put(&client->kref, __i915_drm_client_free);
}
-struct i915_drm_client *i915_drm_client_add(struct i915_drm_clients *clients);
-
-#ifdef CONFIG_PROC_FS
-void i915_drm_client_fdinfo(struct seq_file *m, struct file *f);
-#endif
+struct i915_drm_client *i915_drm_client_alloc(void);
-void i915_drm_clients_fini(struct i915_drm_clients *clients);
+void i915_drm_client_fdinfo(struct drm_printer *p, struct drm_file *file);
#endif /* !__I915_DRM_CLIENT_H__ */
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e771fdc3099c..b4cf6f0f636d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -205,6 +205,7 @@ struct drm_i915_private {
const struct intel_device_info __info; /* Use INTEL_INFO() to access. */
struct intel_runtime_info __runtime; /* Use RUNTIME_INFO() to access. */
+ struct intel_display_runtime_info __display_runtime; /* Access with DISPLAY_RUNTIME_INFO() */
struct intel_driver_caps caps;
struct i915_dsm dsm;
@@ -259,6 +260,16 @@ struct drm_i915_private {
*/
struct workqueue_struct *wq;
+ /**
+ * unordered_wq - internal workqueue for unordered work
+ *
+ * This workqueue should be used for all unordered work
+ * scheduling within i915, which used to be scheduled on the
+ * system_wq before moving to a driver instance due
+ * deprecation of flush_scheduled_work().
+ */
+ struct workqueue_struct *unordered_wq;
+
/* pm private clock gating functions */
const struct drm_i915_clock_gating_funcs *clock_gating_funcs;
@@ -313,7 +324,7 @@ struct drm_i915_private {
/*
* i915->gt[0] == &i915->gt0
*/
-#define I915_MAX_GT 4
+#define I915_MAX_GT 2
struct intel_gt *gt[I915_MAX_GT];
struct kobject *sysfs_gt;
@@ -347,8 +358,6 @@ struct drm_i915_private {
struct i915_pmu pmu;
- struct i915_drm_clients clients;
-
/* The TTM device structure. */
struct ttm_device bdev;
@@ -381,11 +390,11 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915)
}
/* Simple iterator over all initialised engines */
-#define for_each_engine(engine__, dev_priv__, id__) \
+#define for_each_engine(engine__, gt__, id__) \
for ((id__) = 0; \
(id__) < I915_NUM_ENGINES; \
(id__)++) \
- for_each_if ((engine__) = (dev_priv__)->engine[(id__)])
+ for_each_if ((engine__) = (gt__)->engine[(id__)])
/* Iterator over subset of engines selected by mask */
#define for_each_engine_masked(engine__, gt__, mask__, tmp__) \
@@ -407,11 +416,13 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915)
(engine__) && (engine__)->uabi_class == (class__); \
(engine__) = rb_to_uabi_engine(rb_next(&(engine__)->uabi_node)))
-#define INTEL_INFO(dev_priv) (&(dev_priv)->__info)
-#define RUNTIME_INFO(dev_priv) (&(dev_priv)->__runtime)
-#define DRIVER_CAPS(dev_priv) (&(dev_priv)->caps)
+#define INTEL_INFO(i915) (&(i915)->__info)
+#define DISPLAY_INFO(i915) (INTEL_INFO(i915)->display)
+#define RUNTIME_INFO(i915) (&(i915)->__runtime)
+#define DISPLAY_RUNTIME_INFO(i915) (&(i915)->__display_runtime)
+#define DRIVER_CAPS(i915) (&(i915)->caps)
-#define INTEL_DEVID(dev_priv) (RUNTIME_INFO(dev_priv)->device_id)
+#define INTEL_DEVID(i915) (RUNTIME_INFO(i915)->device_id)
#define IP_VER(ver, rel) ((ver) << 8 | (rel))
@@ -427,11 +438,11 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915)
#define IS_MEDIA_VER(i915, from, until) \
(MEDIA_VER(i915) >= (from) && MEDIA_VER(i915) <= (until))
-#define DISPLAY_VER(i915) (RUNTIME_INFO(i915)->display.ip.ver)
+#define DISPLAY_VER(i915) (DISPLAY_RUNTIME_INFO(i915)->ip.ver)
#define IS_DISPLAY_VER(i915, from, until) \
(DISPLAY_VER(i915) >= (from) && DISPLAY_VER(i915) <= (until))
-#define INTEL_REVID(dev_priv) (to_pci_dev((dev_priv)->drm.dev)->revision)
+#define INTEL_REVID(i915) (to_pci_dev((i915)->drm.dev)->revision)
#define INTEL_DISPLAY_STEP(__i915) (RUNTIME_INFO(__i915)->step.display_step)
#define INTEL_GRAPHICS_STEP(__i915) (RUNTIME_INFO(__i915)->step.graphics_step)
@@ -516,135 +527,135 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
return ((mask << (msb - pb)) & (mask << (msb - s))) & BIT(msb);
}
-#define IS_MOBILE(dev_priv) (INTEL_INFO(dev_priv)->is_mobile)
-#define IS_DGFX(dev_priv) (INTEL_INFO(dev_priv)->is_dgfx)
-
-#define IS_I830(dev_priv) IS_PLATFORM(dev_priv, INTEL_I830)
-#define IS_I845G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I845G)
-#define IS_I85X(dev_priv) IS_PLATFORM(dev_priv, INTEL_I85X)
-#define IS_I865G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I865G)
-#define IS_I915G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I915G)
-#define IS_I915GM(dev_priv) IS_PLATFORM(dev_priv, INTEL_I915GM)
-#define IS_I945G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I945G)
-#define IS_I945GM(dev_priv) IS_PLATFORM(dev_priv, INTEL_I945GM)
-#define IS_I965G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I965G)
-#define IS_I965GM(dev_priv) IS_PLATFORM(dev_priv, INTEL_I965GM)
-#define IS_G45(dev_priv) IS_PLATFORM(dev_priv, INTEL_G45)
-#define IS_GM45(dev_priv) IS_PLATFORM(dev_priv, INTEL_GM45)
-#define IS_G4X(dev_priv) (IS_G45(dev_priv) || IS_GM45(dev_priv))
-#define IS_PINEVIEW(dev_priv) IS_PLATFORM(dev_priv, INTEL_PINEVIEW)
-#define IS_G33(dev_priv) IS_PLATFORM(dev_priv, INTEL_G33)
-#define IS_IRONLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_IRONLAKE)
-#define IS_IRONLAKE_M(dev_priv) \
- (IS_PLATFORM(dev_priv, INTEL_IRONLAKE) && IS_MOBILE(dev_priv))
-#define IS_SANDYBRIDGE(dev_priv) IS_PLATFORM(dev_priv, INTEL_SANDYBRIDGE)
-#define IS_IVYBRIDGE(dev_priv) IS_PLATFORM(dev_priv, INTEL_IVYBRIDGE)
-#define IS_IVB_GT1(dev_priv) (IS_IVYBRIDGE(dev_priv) && \
- INTEL_INFO(dev_priv)->gt == 1)
-#define IS_VALLEYVIEW(dev_priv) IS_PLATFORM(dev_priv, INTEL_VALLEYVIEW)
-#define IS_CHERRYVIEW(dev_priv) IS_PLATFORM(dev_priv, INTEL_CHERRYVIEW)
-#define IS_HASWELL(dev_priv) IS_PLATFORM(dev_priv, INTEL_HASWELL)
-#define IS_BROADWELL(dev_priv) IS_PLATFORM(dev_priv, INTEL_BROADWELL)
-#define IS_SKYLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_SKYLAKE)
-#define IS_BROXTON(dev_priv) IS_PLATFORM(dev_priv, INTEL_BROXTON)
-#define IS_KABYLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_KABYLAKE)
-#define IS_GEMINILAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_GEMINILAKE)
-#define IS_COFFEELAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_COFFEELAKE)
-#define IS_COMETLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_COMETLAKE)
-#define IS_ICELAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_ICELAKE)
-#define IS_JSL_EHL(dev_priv) (IS_PLATFORM(dev_priv, INTEL_JASPERLAKE) || \
- IS_PLATFORM(dev_priv, INTEL_ELKHARTLAKE))
-#define IS_TIGERLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_TIGERLAKE)
-#define IS_ROCKETLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_ROCKETLAKE)
-#define IS_DG1(dev_priv) IS_PLATFORM(dev_priv, INTEL_DG1)
-#define IS_ALDERLAKE_S(dev_priv) IS_PLATFORM(dev_priv, INTEL_ALDERLAKE_S)
-#define IS_ALDERLAKE_P(dev_priv) IS_PLATFORM(dev_priv, INTEL_ALDERLAKE_P)
-#define IS_XEHPSDV(dev_priv) IS_PLATFORM(dev_priv, INTEL_XEHPSDV)
-#define IS_DG2(dev_priv) IS_PLATFORM(dev_priv, INTEL_DG2)
-#define IS_PONTEVECCHIO(dev_priv) IS_PLATFORM(dev_priv, INTEL_PONTEVECCHIO)
-#define IS_METEORLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_METEORLAKE)
-
-#define IS_METEORLAKE_M(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_METEORLAKE, INTEL_SUBPLATFORM_M)
-#define IS_METEORLAKE_P(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_METEORLAKE, INTEL_SUBPLATFORM_P)
-#define IS_DG2_G10(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_DG2, INTEL_SUBPLATFORM_G10)
-#define IS_DG2_G11(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_DG2, INTEL_SUBPLATFORM_G11)
-#define IS_DG2_G12(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_DG2, INTEL_SUBPLATFORM_G12)
-#define IS_ADLS_RPLS(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_ALDERLAKE_S, INTEL_SUBPLATFORM_RPL)
-#define IS_ADLP_N(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_ALDERLAKE_P, INTEL_SUBPLATFORM_N)
-#define IS_ADLP_RPLP(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_ALDERLAKE_P, INTEL_SUBPLATFORM_RPL)
-#define IS_ADLP_RPLU(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_ALDERLAKE_P, INTEL_SUBPLATFORM_RPLU)
-#define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \
- (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0C00)
-#define IS_BDW_ULT(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_BROADWELL, INTEL_SUBPLATFORM_ULT)
-#define IS_BDW_ULX(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_BROADWELL, INTEL_SUBPLATFORM_ULX)
-#define IS_BDW_GT3(dev_priv) (IS_BROADWELL(dev_priv) && \
- INTEL_INFO(dev_priv)->gt == 3)
-#define IS_HSW_ULT(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_HASWELL, INTEL_SUBPLATFORM_ULT)
-#define IS_HSW_GT3(dev_priv) (IS_HASWELL(dev_priv) && \
- INTEL_INFO(dev_priv)->gt == 3)
-#define IS_HSW_GT1(dev_priv) (IS_HASWELL(dev_priv) && \
- INTEL_INFO(dev_priv)->gt == 1)
+#define IS_MOBILE(i915) (INTEL_INFO(i915)->is_mobile)
+#define IS_DGFX(i915) (INTEL_INFO(i915)->is_dgfx)
+
+#define IS_I830(i915) IS_PLATFORM(i915, INTEL_I830)
+#define IS_I845G(i915) IS_PLATFORM(i915, INTEL_I845G)
+#define IS_I85X(i915) IS_PLATFORM(i915, INTEL_I85X)
+#define IS_I865G(i915) IS_PLATFORM(i915, INTEL_I865G)
+#define IS_I915G(i915) IS_PLATFORM(i915, INTEL_I915G)
+#define IS_I915GM(i915) IS_PLATFORM(i915, INTEL_I915GM)
+#define IS_I945G(i915) IS_PLATFORM(i915, INTEL_I945G)
+#define IS_I945GM(i915) IS_PLATFORM(i915, INTEL_I945GM)
+#define IS_I965G(i915) IS_PLATFORM(i915, INTEL_I965G)
+#define IS_I965GM(i915) IS_PLATFORM(i915, INTEL_I965GM)
+#define IS_G45(i915) IS_PLATFORM(i915, INTEL_G45)
+#define IS_GM45(i915) IS_PLATFORM(i915, INTEL_GM45)
+#define IS_G4X(i915) (IS_G45(i915) || IS_GM45(i915))
+#define IS_PINEVIEW(i915) IS_PLATFORM(i915, INTEL_PINEVIEW)
+#define IS_G33(i915) IS_PLATFORM(i915, INTEL_G33)
+#define IS_IRONLAKE(i915) IS_PLATFORM(i915, INTEL_IRONLAKE)
+#define IS_IRONLAKE_M(i915) \
+ (IS_PLATFORM(i915, INTEL_IRONLAKE) && IS_MOBILE(i915))
+#define IS_SANDYBRIDGE(i915) IS_PLATFORM(i915, INTEL_SANDYBRIDGE)
+#define IS_IVYBRIDGE(i915) IS_PLATFORM(i915, INTEL_IVYBRIDGE)
+#define IS_IVB_GT1(i915) (IS_IVYBRIDGE(i915) && \
+ INTEL_INFO(i915)->gt == 1)
+#define IS_VALLEYVIEW(i915) IS_PLATFORM(i915, INTEL_VALLEYVIEW)
+#define IS_CHERRYVIEW(i915) IS_PLATFORM(i915, INTEL_CHERRYVIEW)
+#define IS_HASWELL(i915) IS_PLATFORM(i915, INTEL_HASWELL)
+#define IS_BROADWELL(i915) IS_PLATFORM(i915, INTEL_BROADWELL)
+#define IS_SKYLAKE(i915) IS_PLATFORM(i915, INTEL_SKYLAKE)
+#define IS_BROXTON(i915) IS_PLATFORM(i915, INTEL_BROXTON)
+#define IS_KABYLAKE(i915) IS_PLATFORM(i915, INTEL_KABYLAKE)
+#define IS_GEMINILAKE(i915) IS_PLATFORM(i915, INTEL_GEMINILAKE)
+#define IS_COFFEELAKE(i915) IS_PLATFORM(i915, INTEL_COFFEELAKE)
+#define IS_COMETLAKE(i915) IS_PLATFORM(i915, INTEL_COMETLAKE)
+#define IS_ICELAKE(i915) IS_PLATFORM(i915, INTEL_ICELAKE)
+#define IS_JSL_EHL(i915) (IS_PLATFORM(i915, INTEL_JASPERLAKE) || \
+ IS_PLATFORM(i915, INTEL_ELKHARTLAKE))
+#define IS_TIGERLAKE(i915) IS_PLATFORM(i915, INTEL_TIGERLAKE)
+#define IS_ROCKETLAKE(i915) IS_PLATFORM(i915, INTEL_ROCKETLAKE)
+#define IS_DG1(i915) IS_PLATFORM(i915, INTEL_DG1)
+#define IS_ALDERLAKE_S(i915) IS_PLATFORM(i915, INTEL_ALDERLAKE_S)
+#define IS_ALDERLAKE_P(i915) IS_PLATFORM(i915, INTEL_ALDERLAKE_P)
+#define IS_XEHPSDV(i915) IS_PLATFORM(i915, INTEL_XEHPSDV)
+#define IS_DG2(i915) IS_PLATFORM(i915, INTEL_DG2)
+#define IS_PONTEVECCHIO(i915) IS_PLATFORM(i915, INTEL_PONTEVECCHIO)
+#define IS_METEORLAKE(i915) IS_PLATFORM(i915, INTEL_METEORLAKE)
+
+#define IS_METEORLAKE_M(i915) \
+ IS_SUBPLATFORM(i915, INTEL_METEORLAKE, INTEL_SUBPLATFORM_M)
+#define IS_METEORLAKE_P(i915) \
+ IS_SUBPLATFORM(i915, INTEL_METEORLAKE, INTEL_SUBPLATFORM_P)
+#define IS_DG2_G10(i915) \
+ IS_SUBPLATFORM(i915, INTEL_DG2, INTEL_SUBPLATFORM_G10)
+#define IS_DG2_G11(i915) \
+ IS_SUBPLATFORM(i915, INTEL_DG2, INTEL_SUBPLATFORM_G11)
+#define IS_DG2_G12(i915) \
+ IS_SUBPLATFORM(i915, INTEL_DG2, INTEL_SUBPLATFORM_G12)
+#define IS_ADLS_RPLS(i915) \
+ IS_SUBPLATFORM(i915, INTEL_ALDERLAKE_S, INTEL_SUBPLATFORM_RPL)
+#define IS_ADLP_N(i915) \
+ IS_SUBPLATFORM(i915, INTEL_ALDERLAKE_P, INTEL_SUBPLATFORM_N)
+#define IS_ADLP_RPLP(i915) \
+ IS_SUBPLATFORM(i915, INTEL_ALDERLAKE_P, INTEL_SUBPLATFORM_RPL)
+#define IS_ADLP_RPLU(i915) \
+ IS_SUBPLATFORM(i915, INTEL_ALDERLAKE_P, INTEL_SUBPLATFORM_RPLU)
+#define IS_HSW_EARLY_SDV(i915) (IS_HASWELL(i915) && \
+ (INTEL_DEVID(i915) & 0xFF00) == 0x0C00)
+#define IS_BDW_ULT(i915) \
+ IS_SUBPLATFORM(i915, INTEL_BROADWELL, INTEL_SUBPLATFORM_ULT)
+#define IS_BDW_ULX(i915) \
+ IS_SUBPLATFORM(i915, INTEL_BROADWELL, INTEL_SUBPLATFORM_ULX)
+#define IS_BDW_GT3(i915) (IS_BROADWELL(i915) && \
+ INTEL_INFO(i915)->gt == 3)
+#define IS_HSW_ULT(i915) \
+ IS_SUBPLATFORM(i915, INTEL_HASWELL, INTEL_SUBPLATFORM_ULT)
+#define IS_HSW_GT3(i915) (IS_HASWELL(i915) && \
+ INTEL_INFO(i915)->gt == 3)
+#define IS_HSW_GT1(i915) (IS_HASWELL(i915) && \
+ INTEL_INFO(i915)->gt == 1)
/* ULX machines are also considered ULT. */
-#define IS_HSW_ULX(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_HASWELL, INTEL_SUBPLATFORM_ULX)
-#define IS_SKL_ULT(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_SKYLAKE, INTEL_SUBPLATFORM_ULT)
-#define IS_SKL_ULX(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_SKYLAKE, INTEL_SUBPLATFORM_ULX)
-#define IS_KBL_ULT(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_KABYLAKE, INTEL_SUBPLATFORM_ULT)
-#define IS_KBL_ULX(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_KABYLAKE, INTEL_SUBPLATFORM_ULX)
-#define IS_SKL_GT2(dev_priv) (IS_SKYLAKE(dev_priv) && \
- INTEL_INFO(dev_priv)->gt == 2)
-#define IS_SKL_GT3(dev_priv) (IS_SKYLAKE(dev_priv) && \
- INTEL_INFO(dev_priv)->gt == 3)
-#define IS_SKL_GT4(dev_priv) (IS_SKYLAKE(dev_priv) && \
- INTEL_INFO(dev_priv)->gt == 4)
-#define IS_KBL_GT2(dev_priv) (IS_KABYLAKE(dev_priv) && \
- INTEL_INFO(dev_priv)->gt == 2)
-#define IS_KBL_GT3(dev_priv) (IS_KABYLAKE(dev_priv) && \
- INTEL_INFO(dev_priv)->gt == 3)
-#define IS_CFL_ULT(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_COFFEELAKE, INTEL_SUBPLATFORM_ULT)
-#define IS_CFL_ULX(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_COFFEELAKE, INTEL_SUBPLATFORM_ULX)
-#define IS_CFL_GT2(dev_priv) (IS_COFFEELAKE(dev_priv) && \
- INTEL_INFO(dev_priv)->gt == 2)
-#define IS_CFL_GT3(dev_priv) (IS_COFFEELAKE(dev_priv) && \
- INTEL_INFO(dev_priv)->gt == 3)
-
-#define IS_CML_ULT(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_COMETLAKE, INTEL_SUBPLATFORM_ULT)
-#define IS_CML_ULX(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_COMETLAKE, INTEL_SUBPLATFORM_ULX)
-#define IS_CML_GT2(dev_priv) (IS_COMETLAKE(dev_priv) && \
- INTEL_INFO(dev_priv)->gt == 2)
-
-#define IS_ICL_WITH_PORT_F(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_ICELAKE, INTEL_SUBPLATFORM_PORTF)
-
-#define IS_TGL_UY(dev_priv) \
- IS_SUBPLATFORM(dev_priv, INTEL_TIGERLAKE, INTEL_SUBPLATFORM_UY)
+#define IS_HSW_ULX(i915) \
+ IS_SUBPLATFORM(i915, INTEL_HASWELL, INTEL_SUBPLATFORM_ULX)
+#define IS_SKL_ULT(i915) \
+ IS_SUBPLATFORM(i915, INTEL_SKYLAKE, INTEL_SUBPLATFORM_ULT)
+#define IS_SKL_ULX(i915) \
+ IS_SUBPLATFORM(i915, INTEL_SKYLAKE, INTEL_SUBPLATFORM_ULX)
+#define IS_KBL_ULT(i915) \
+ IS_SUBPLATFORM(i915, INTEL_KABYLAKE, INTEL_SUBPLATFORM_ULT)
+#define IS_KBL_ULX(i915) \
+ IS_SUBPLATFORM(i915, INTEL_KABYLAKE, INTEL_SUBPLATFORM_ULX)
+#define IS_SKL_GT2(i915) (IS_SKYLAKE(i915) && \
+ INTEL_INFO(i915)->gt == 2)
+#define IS_SKL_GT3(i915) (IS_SKYLAKE(i915) && \
+ INTEL_INFO(i915)->gt == 3)
+#define IS_SKL_GT4(i915) (IS_SKYLAKE(i915) && \
+ INTEL_INFO(i915)->gt == 4)
+#define IS_KBL_GT2(i915) (IS_KABYLAKE(i915) && \
+ INTEL_INFO(i915)->gt == 2)
+#define IS_KBL_GT3(i915) (IS_KABYLAKE(i915) && \
+ INTEL_INFO(i915)->gt == 3)
+#define IS_CFL_ULT(i915) \
+ IS_SUBPLATFORM(i915, INTEL_COFFEELAKE, INTEL_SUBPLATFORM_ULT)
+#define IS_CFL_ULX(i915) \
+ IS_SUBPLATFORM(i915, INTEL_COFFEELAKE, INTEL_SUBPLATFORM_ULX)
+#define IS_CFL_GT2(i915) (IS_COFFEELAKE(i915) && \
+ INTEL_INFO(i915)->gt == 2)
+#define IS_CFL_GT3(i915) (IS_COFFEELAKE(i915) && \
+ INTEL_INFO(i915)->gt == 3)
+
+#define IS_CML_ULT(i915) \
+ IS_SUBPLATFORM(i915, INTEL_COMETLAKE, INTEL_SUBPLATFORM_ULT)
+#define IS_CML_ULX(i915) \
+ IS_SUBPLATFORM(i915, INTEL_COMETLAKE, INTEL_SUBPLATFORM_ULX)
+#define IS_CML_GT2(i915) (IS_COMETLAKE(i915) && \
+ INTEL_INFO(i915)->gt == 2)
+
+#define IS_ICL_WITH_PORT_F(i915) \
+ IS_SUBPLATFORM(i915, INTEL_ICELAKE, INTEL_SUBPLATFORM_PORTF)
+
+#define IS_TGL_UY(i915) \
+ IS_SUBPLATFORM(i915, INTEL_TIGERLAKE, INTEL_SUBPLATFORM_UY)
#define IS_SKL_GRAPHICS_STEP(p, since, until) (IS_SKYLAKE(p) && IS_GRAPHICS_STEP(p, since, until))
-#define IS_KBL_GRAPHICS_STEP(dev_priv, since, until) \
- (IS_KABYLAKE(dev_priv) && IS_GRAPHICS_STEP(dev_priv, since, until))
-#define IS_KBL_DISPLAY_STEP(dev_priv, since, until) \
- (IS_KABYLAKE(dev_priv) && IS_DISPLAY_STEP(dev_priv, since, until))
+#define IS_KBL_GRAPHICS_STEP(i915, since, until) \
+ (IS_KABYLAKE(i915) && IS_GRAPHICS_STEP(i915, since, until))
+#define IS_KBL_DISPLAY_STEP(i915, since, until) \
+ (IS_KABYLAKE(i915) && IS_DISPLAY_STEP(i915, since, until))
#define IS_JSL_EHL_GRAPHICS_STEP(p, since, until) \
(IS_JSL_EHL(p) && IS_GRAPHICS_STEP(p, since, until))
@@ -720,9 +731,9 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
(IS_PONTEVECCHIO(__i915) && \
IS_GRAPHICS_STEP(__i915, since, until))
-#define IS_LP(dev_priv) (INTEL_INFO(dev_priv)->is_lp)
-#define IS_GEN9_LP(dev_priv) (GRAPHICS_VER(dev_priv) == 9 && IS_LP(dev_priv))
-#define IS_GEN9_BC(dev_priv) (GRAPHICS_VER(dev_priv) == 9 && !IS_LP(dev_priv))
+#define IS_LP(i915) (INTEL_INFO(i915)->is_lp)
+#define IS_GEN9_LP(i915) (GRAPHICS_VER(i915) == 9 && IS_LP(i915))
+#define IS_GEN9_BC(i915) (GRAPHICS_VER(i915) == 9 && !IS_LP(i915))
#define __HAS_ENGINE(engine_mask, id) ((engine_mask) & BIT(id))
#define HAS_ENGINE(gt, id) __HAS_ENGINE((gt)->info.engine_mask, id)
@@ -747,182 +758,121 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define CCS_MASK(gt) \
ENGINE_INSTANCES_MASK(gt, CCS0, I915_MAX_CCS)
-#define HAS_MEDIA_RATIO_MODE(dev_priv) (INTEL_INFO(dev_priv)->has_media_ratio_mode)
+#define HAS_MEDIA_RATIO_MODE(i915) (INTEL_INFO(i915)->has_media_ratio_mode)
/*
* The Gen7 cmdparser copies the scanned buffer to the ggtt for execution
* All later gens can run the final buffer from the ppgtt
*/
-#define CMDPARSER_USES_GGTT(dev_priv) (GRAPHICS_VER(dev_priv) == 7)
+#define CMDPARSER_USES_GGTT(i915) (GRAPHICS_VER(i915) == 7)
-#define HAS_LLC(dev_priv) (INTEL_INFO(dev_priv)->has_llc)
-#define HAS_4TILE(dev_priv) (INTEL_INFO(dev_priv)->has_4tile)
-#define HAS_SNOOP(dev_priv) (INTEL_INFO(dev_priv)->has_snoop)
-#define HAS_EDRAM(dev_priv) ((dev_priv)->edram_size_mb)
-#define HAS_SECURE_BATCHES(dev_priv) (GRAPHICS_VER(dev_priv) < 6)
-#define HAS_WT(dev_priv) HAS_EDRAM(dev_priv)
+#define HAS_LLC(i915) (INTEL_INFO(i915)->has_llc)
+#define HAS_4TILE(i915) (INTEL_INFO(i915)->has_4tile)
+#define HAS_SNOOP(i915) (INTEL_INFO(i915)->has_snoop)
+#define HAS_EDRAM(i915) ((i915)->edram_size_mb)
+#define HAS_SECURE_BATCHES(i915) (GRAPHICS_VER(i915) < 6)
+#define HAS_WT(i915) HAS_EDRAM(i915)
-#define HWS_NEEDS_PHYSICAL(dev_priv) (INTEL_INFO(dev_priv)->hws_needs_physical)
+#define HWS_NEEDS_PHYSICAL(i915) (INTEL_INFO(i915)->hws_needs_physical)
-#define HAS_LOGICAL_RING_CONTEXTS(dev_priv) \
- (INTEL_INFO(dev_priv)->has_logical_ring_contexts)
-#define HAS_LOGICAL_RING_ELSQ(dev_priv) \
- (INTEL_INFO(dev_priv)->has_logical_ring_elsq)
+#define HAS_LOGICAL_RING_CONTEXTS(i915) \
+ (INTEL_INFO(i915)->has_logical_ring_contexts)
+#define HAS_LOGICAL_RING_ELSQ(i915) \
+ (INTEL_INFO(i915)->has_logical_ring_elsq)
-#define HAS_EXECLISTS(dev_priv) HAS_LOGICAL_RING_CONTEXTS(dev_priv)
+#define HAS_EXECLISTS(i915) HAS_LOGICAL_RING_CONTEXTS(i915)
-#define INTEL_PPGTT(dev_priv) (RUNTIME_INFO(dev_priv)->ppgtt_type)
-#define HAS_PPGTT(dev_priv) \
- (INTEL_PPGTT(dev_priv) != INTEL_PPGTT_NONE)
-#define HAS_FULL_PPGTT(dev_priv) \
- (INTEL_PPGTT(dev_priv) >= INTEL_PPGTT_FULL)
+#define INTEL_PPGTT(i915) (RUNTIME_INFO(i915)->ppgtt_type)
+#define HAS_PPGTT(i915) \
+ (INTEL_PPGTT(i915) != INTEL_PPGTT_NONE)
+#define HAS_FULL_PPGTT(i915) \
+ (INTEL_PPGTT(i915) >= INTEL_PPGTT_FULL)
-#define HAS_PAGE_SIZES(dev_priv, sizes) ({ \
+#define HAS_PAGE_SIZES(i915, sizes) ({ \
GEM_BUG_ON((sizes) == 0); \
- ((sizes) & ~RUNTIME_INFO(dev_priv)->page_sizes) == 0; \
+ ((sizes) & ~RUNTIME_INFO(i915)->page_sizes) == 0; \
})
-#define HAS_OVERLAY(dev_priv) (INTEL_INFO(dev_priv)->display.has_overlay)
-#define OVERLAY_NEEDS_PHYSICAL(dev_priv) \
- (INTEL_INFO(dev_priv)->display.overlay_needs_physical)
-
/* Early gen2 have a totally busted CS tlb and require pinned batches. */
-#define HAS_BROKEN_CS_TLB(dev_priv) (IS_I830(dev_priv) || IS_I845G(dev_priv))
+#define HAS_BROKEN_CS_TLB(i915) (IS_I830(i915) || IS_I845G(i915))
-#define NEEDS_RC6_CTX_CORRUPTION_WA(dev_priv) \
- (IS_BROADWELL(dev_priv) || GRAPHICS_VER(dev_priv) == 9)
+#define NEEDS_RC6_CTX_CORRUPTION_WA(i915) \
+ (IS_BROADWELL(i915) || GRAPHICS_VER(i915) == 9)
/* WaRsDisableCoarsePowerGating:skl,cnl */
-#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
- (IS_SKL_GT3(dev_priv) || IS_SKL_GT4(dev_priv))
-
-#define HAS_GMBUS_IRQ(dev_priv) (DISPLAY_VER(dev_priv) >= 4)
-#define HAS_GMBUS_BURST_READ(dev_priv) (DISPLAY_VER(dev_priv) >= 11 || \
- IS_GEMINILAKE(dev_priv) || \
- IS_KABYLAKE(dev_priv))
+#define NEEDS_WaRsDisableCoarsePowerGating(i915) \
+ (IS_SKL_GT3(i915) || IS_SKL_GT4(i915))
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
* rows, which changed the alignment requirements and fence programming.
*/
-#define HAS_128_BYTE_Y_TILING(dev_priv) (GRAPHICS_VER(dev_priv) != 2 && \
- !(IS_I915G(dev_priv) || IS_I915GM(dev_priv)))
-#define SUPPORTS_TV(dev_priv) (INTEL_INFO(dev_priv)->display.supports_tv)
-#define I915_HAS_HOTPLUG(dev_priv) (INTEL_INFO(dev_priv)->display.has_hotplug)
-
-#define HAS_FW_BLC(dev_priv) (DISPLAY_VER(dev_priv) > 2)
-#define HAS_FBC(dev_priv) (RUNTIME_INFO(dev_priv)->fbc_mask != 0)
-#define HAS_CUR_FBC(dev_priv) (!HAS_GMCH(dev_priv) && DISPLAY_VER(dev_priv) >= 7)
-
-#define HAS_DPT(dev_priv) (DISPLAY_VER(dev_priv) >= 13)
-
-#define HAS_IPS(dev_priv) (IS_HSW_ULT(dev_priv) || IS_BROADWELL(dev_priv))
-
-#define HAS_DP_MST(dev_priv) (INTEL_INFO(dev_priv)->display.has_dp_mst)
-#define HAS_DP20(dev_priv) (IS_DG2(dev_priv) || DISPLAY_VER(dev_priv) >= 14)
-
-#define HAS_DOUBLE_BUFFERED_M_N(dev_priv) (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
-
-#define HAS_CDCLK_CRAWL(dev_priv) (INTEL_INFO(dev_priv)->display.has_cdclk_crawl)
-#define HAS_CDCLK_SQUASH(dev_priv) (INTEL_INFO(dev_priv)->display.has_cdclk_squash)
-#define HAS_DDI(dev_priv) (INTEL_INFO(dev_priv)->display.has_ddi)
-#define HAS_FPGA_DBG_UNCLAIMED(dev_priv) (INTEL_INFO(dev_priv)->display.has_fpga_dbg)
-#define HAS_PSR(dev_priv) (INTEL_INFO(dev_priv)->display.has_psr)
-#define HAS_PSR_HW_TRACKING(dev_priv) \
- (INTEL_INFO(dev_priv)->display.has_psr_hw_tracking)
-#define HAS_PSR2_SEL_FETCH(dev_priv) (DISPLAY_VER(dev_priv) >= 12)
-#define HAS_TRANSCODER(dev_priv, trans) ((RUNTIME_INFO(dev_priv)->cpu_transcoder_mask & BIT(trans)) != 0)
-
-#define HAS_RC6(dev_priv) (INTEL_INFO(dev_priv)->has_rc6)
-#define HAS_RC6p(dev_priv) (INTEL_INFO(dev_priv)->has_rc6p)
-#define HAS_RC6pp(dev_priv) (false) /* HW was never validated */
+#define HAS_128_BYTE_Y_TILING(i915) (GRAPHICS_VER(i915) != 2 && \
+ !(IS_I915G(i915) || IS_I915GM(i915)))
-#define HAS_RPS(dev_priv) (INTEL_INFO(dev_priv)->has_rps)
+#define HAS_RC6(i915) (INTEL_INFO(i915)->has_rc6)
+#define HAS_RC6p(i915) (INTEL_INFO(i915)->has_rc6p)
+#define HAS_RC6pp(i915) (false) /* HW was never validated */
-#define HAS_DMC(dev_priv) (RUNTIME_INFO(dev_priv)->has_dmc)
-#define HAS_DSB(dev_priv) (INTEL_INFO(dev_priv)->display.has_dsb)
-#define HAS_DSC(__i915) (RUNTIME_INFO(__i915)->has_dsc)
-#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915))
+#define HAS_RPS(i915) (INTEL_INFO(i915)->has_rps)
-#define HAS_HECI_PXP(dev_priv) \
- (INTEL_INFO(dev_priv)->has_heci_pxp)
+#define HAS_HECI_PXP(i915) \
+ (INTEL_INFO(i915)->has_heci_pxp)
-#define HAS_HECI_GSCFI(dev_priv) \
- (INTEL_INFO(dev_priv)->has_heci_gscfi)
+#define HAS_HECI_GSCFI(i915) \
+ (INTEL_INFO(i915)->has_heci_gscfi)
-#define HAS_HECI_GSC(dev_priv) (HAS_HECI_PXP(dev_priv) || HAS_HECI_GSCFI(dev_priv))
+#define HAS_HECI_GSC(i915) (HAS_HECI_PXP(i915) || HAS_HECI_GSCFI(i915))
-#define HAS_MSO(i915) (DISPLAY_VER(i915) >= 12)
+#define HAS_RUNTIME_PM(i915) (INTEL_INFO(i915)->has_runtime_pm)
+#define HAS_64BIT_RELOC(i915) (INTEL_INFO(i915)->has_64bit_reloc)
-#define HAS_RUNTIME_PM(dev_priv) (INTEL_INFO(dev_priv)->has_runtime_pm)
-#define HAS_64BIT_RELOC(dev_priv) (INTEL_INFO(dev_priv)->has_64bit_reloc)
-
-#define HAS_OA_BPC_REPORTING(dev_priv) \
- (INTEL_INFO(dev_priv)->has_oa_bpc_reporting)
-#define HAS_OA_SLICE_CONTRIB_LIMITS(dev_priv) \
- (INTEL_INFO(dev_priv)->has_oa_slice_contrib_limits)
-#define HAS_OAM(dev_priv) \
- (INTEL_INFO(dev_priv)->has_oam)
+#define HAS_OA_BPC_REPORTING(i915) \
+ (INTEL_INFO(i915)->has_oa_bpc_reporting)
+#define HAS_OA_SLICE_CONTRIB_LIMITS(i915) \
+ (INTEL_INFO(i915)->has_oa_slice_contrib_limits)
+#define HAS_OAM(i915) \
+ (INTEL_INFO(i915)->has_oam)
/*
* Set this flag, when platform requires 64K GTT page sizes or larger for
* device local memory access.
*/
-#define HAS_64K_PAGES(dev_priv) (INTEL_INFO(dev_priv)->has_64k_pages)
-
-#define HAS_IPC(dev_priv) (INTEL_INFO(dev_priv)->display.has_ipc)
-#define HAS_SAGV(dev_priv) (DISPLAY_VER(dev_priv) >= 9 && !IS_LP(dev_priv))
+#define HAS_64K_PAGES(i915) (INTEL_INFO(i915)->has_64k_pages)
#define HAS_REGION(i915, i) (RUNTIME_INFO(i915)->memory_regions & (i))
#define HAS_LMEM(i915) HAS_REGION(i915, REGION_LMEM)
-#define HAS_EXTRA_GT_LIST(dev_priv) (INTEL_INFO(dev_priv)->extra_gt_list)
+#define HAS_EXTRA_GT_LIST(i915) (INTEL_INFO(i915)->extra_gt_list)
/*
* Platform has the dedicated compression control state for each lmem surfaces
* stored in lmem to support the 3D and media compression formats.
*/
-#define HAS_FLAT_CCS(dev_priv) (INTEL_INFO(dev_priv)->has_flat_ccs)
+#define HAS_FLAT_CCS(i915) (INTEL_INFO(i915)->has_flat_ccs)
-#define HAS_GT_UC(dev_priv) (INTEL_INFO(dev_priv)->has_gt_uc)
+#define HAS_GT_UC(i915) (INTEL_INFO(i915)->has_gt_uc)
-#define HAS_POOLED_EU(dev_priv) (RUNTIME_INFO(dev_priv)->has_pooled_eu)
+#define HAS_POOLED_EU(i915) (RUNTIME_INFO(i915)->has_pooled_eu)
-#define HAS_GLOBAL_MOCS_REGISTERS(dev_priv) (INTEL_INFO(dev_priv)->has_global_mocs)
-
-#define HAS_GMCH(dev_priv) (INTEL_INFO(dev_priv)->display.has_gmch)
+#define HAS_GLOBAL_MOCS_REGISTERS(i915) (INTEL_INFO(i915)->has_global_mocs)
#define HAS_GMD_ID(i915) (INTEL_INFO(i915)->has_gmd_id)
-#define HAS_LSPCON(dev_priv) (IS_DISPLAY_VER(dev_priv, 9, 10))
-
#define HAS_L3_CCS_READ(i915) (INTEL_INFO(i915)->has_l3_ccs_read)
/* DPF == dynamic parity feature */
-#define HAS_L3_DPF(dev_priv) (INTEL_INFO(dev_priv)->has_l3_dpf)
-#define NUM_L3_SLICES(dev_priv) (IS_HSW_GT3(dev_priv) ? \
- 2 : HAS_L3_DPF(dev_priv))
-
-#define INTEL_NUM_PIPES(dev_priv) (hweight8(RUNTIME_INFO(dev_priv)->pipe_mask))
-
-#define HAS_DISPLAY(dev_priv) (RUNTIME_INFO(dev_priv)->pipe_mask != 0)
-
-#define HAS_VRR(i915) (DISPLAY_VER(i915) >= 11)
-
-#define HAS_ASYNC_FLIPS(i915) (DISPLAY_VER(i915) >= 5)
+#define HAS_L3_DPF(i915) (INTEL_INFO(i915)->has_l3_dpf)
+#define NUM_L3_SLICES(i915) (IS_HSW_GT3(i915) ? \
+ 2 : HAS_L3_DPF(i915))
/* Only valid when HAS_DISPLAY() is true */
-#define INTEL_DISPLAY_ENABLED(dev_priv) \
- (drm_WARN_ON(&(dev_priv)->drm, !HAS_DISPLAY(dev_priv)), \
- !(dev_priv)->params.disable_display && \
- !intel_opregion_headless_sku(dev_priv))
-
-#define HAS_GUC_DEPRIVILEGE(dev_priv) \
- (INTEL_INFO(dev_priv)->has_guc_deprivilege)
-
-#define HAS_D12_PLANE_MINIMIZATION(dev_priv) (IS_ROCKETLAKE(dev_priv) || \
- IS_ALDERLAKE_S(dev_priv))
+#define INTEL_DISPLAY_ENABLED(i915) \
+ (drm_WARN_ON(&(i915)->drm, !HAS_DISPLAY(i915)), \
+ !(i915)->params.disable_display && \
+ !intel_opregion_headless_sku(i915))
-#define HAS_MBUS_JOINING(i915) (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14)
+#define HAS_GUC_DEPRIVILEGE(i915) \
+ (INTEL_INFO(i915)->has_guc_deprivilege)
#define HAS_3D_PIPELINE(i915) (INTEL_INFO(i915)->has_3d_pipeline)
@@ -931,11 +881,4 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define HAS_LMEMBAR_SMEM_STOLEN(i915) (!HAS_LMEM(i915) && \
GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))
-/* intel_device_info.c */
-static inline struct intel_device_info *
-mkwrite_device_info(struct drm_i915_private *dev_priv)
-{
- return (struct intel_device_info *)INTEL_INFO(dev_priv);
-}
-
#endif
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0a78bdbd36b1..1f65bb33dd21 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -420,8 +420,11 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
page_length = remain < page_length ? remain : page_length;
if (drm_mm_node_allocated(&node)) {
ggtt->vm.insert_page(&ggtt->vm,
- i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT),
- node.start, I915_CACHE_NONE, 0);
+ i915_gem_object_get_dma_address(obj,
+ offset >> PAGE_SHIFT),
+ node.start,
+ i915_gem_get_pat_index(i915,
+ I915_CACHE_NONE), 0);
} else {
page_base += offset & PAGE_MASK;
}
@@ -598,8 +601,11 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
/* flush the write before we modify the GGTT */
intel_gt_flush_ggtt_writes(ggtt->vm.gt);
ggtt->vm.insert_page(&ggtt->vm,
- i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT),
- node.start, I915_CACHE_NONE, 0);
+ i915_gem_object_get_dma_address(obj,
+ offset >> PAGE_SHIFT),
+ node.start,
+ i915_gem_get_pat_index(i915,
+ I915_CACHE_NONE), 0);
wmb(); /* flush modifications to the GGTT (insert_page) */
} else {
page_base += offset & PAGE_MASK;
@@ -1142,6 +1148,19 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
unsigned int i;
int ret;
+ /*
+ * In the proccess of replacing cache_level with pat_index a tricky
+ * dependency is created on the definition of the enum i915_cache_level.
+ * in case this enum is changed, PTE encode would be broken.
+ * Add a WARNING here. And remove when we completely quit using this
+ * enum
+ */
+ BUILD_BUG_ON(I915_CACHE_NONE != 0 ||
+ I915_CACHE_LLC != 1 ||
+ I915_CACHE_L3_LLC != 2 ||
+ I915_CACHE_WT != 3 ||
+ I915_MAX_CACHE_LEVEL != 4);
+
/* We need to fallback to 4K pages if host doesn't support huge gtt. */
if (intel_vgpu_active(dev_priv) && !intel_vgpu_has_huge_gtt(dev_priv))
RUNTIME_INFO(dev_priv)->page_sizes = I915_GTT_PAGE_SIZE_4K;
@@ -1306,11 +1325,9 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file)
if (!file_priv)
goto err_alloc;
- client = i915_drm_client_add(&i915->clients);
- if (IS_ERR(client)) {
- ret = PTR_ERR(client);
+ client = i915_drm_client_alloc();
+ if (!client)
goto err_client;
- }
file->driver_priv = file_priv;
file_priv->i915 = i915;
diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
index 2238e096c957..890f2b382bee 100644
--- a/drivers/gpu/drm/i915/i915_getparam.c
+++ b/drivers/gpu/drm/i915/i915_getparam.c
@@ -5,6 +5,8 @@
#include "gem/i915_gem_mman.h"
#include "gt/intel_engine_user.h"
+#include "pxp/intel_pxp.h"
+
#include "i915_cmd_parser.h"
#include "i915_drv.h"
#include "i915_getparam.h"
@@ -98,7 +100,16 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
value = sseu->min_eu_in_pool;
break;
case I915_PARAM_HUC_STATUS:
- value = intel_huc_check_status(&to_gt(i915)->uc.huc);
+ /* On platform with a media GT, the HuC is on that GT */
+ if (i915->media_gt)
+ value = intel_huc_check_status(&i915->media_gt->uc.huc);
+ else
+ value = intel_huc_check_status(&to_gt(i915)->uc.huc);
+ if (value < 0)
+ return value;
+ break;
+ case I915_PARAM_PXP_STATUS:
+ value = intel_pxp_get_readiness_status(i915->pxp);
if (value < 0)
return value;
break;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 35f70bb8e4fb..0c38bfb60c9a 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -808,10 +808,15 @@ static void err_print_gt_engines(struct drm_i915_error_state_buf *m,
for (ee = gt->engine; ee; ee = ee->next) {
const struct i915_vma_coredump *vma;
- if (ee->guc_capture_node)
- intel_guc_capture_print_engine_node(m, ee);
- else
+ if (gt->uc && gt->uc->guc.is_guc_capture) {
+ if (ee->guc_capture_node)
+ intel_guc_capture_print_engine_node(m, ee);
+ else
+ err_printf(m, " Missing GuC capture node for %s\n",
+ ee->engine->name);
+ } else {
error_print_engine(m, ee);
+ }
err_printf(m, " hung: %u\n", ee->hung);
err_printf(m, " engine reset count: %u\n", ee->reset_count);
@@ -1117,10 +1122,14 @@ i915_vma_coredump_create(const struct intel_gt *gt,
mutex_lock(&ggtt->error_mutex);
if (ggtt->vm.raw_insert_page)
ggtt->vm.raw_insert_page(&ggtt->vm, dma, slot,
- I915_CACHE_NONE, 0);
+ i915_gem_get_pat_index(gt->i915,
+ I915_CACHE_NONE),
+ 0);
else
ggtt->vm.insert_page(&ggtt->vm, dma, slot,
- I915_CACHE_NONE, 0);
+ i915_gem_get_pat_index(gt->i915,
+ I915_CACHE_NONE),
+ 0);
mb();
s = io_mapping_map_wc(&ggtt->iomap, slot, PAGE_SIZE);
@@ -2162,7 +2171,7 @@ void i915_error_state_store(struct i915_gpu_coredump *error)
* i915_capture_error_state - capture an error record for later analysis
* @gt: intel_gt which originated the hang
* @engine_mask: hung engines
- *
+ * @dump_flags: dump flags
*
* Should be called when an error is detected (either a hang or an error
* interrupt) to capture error state from the time of the error. Fills
@@ -2219,3 +2228,135 @@ void i915_disable_error_state(struct drm_i915_private *i915, int err)
i915->gpu_error.first_error = ERR_PTR(err);
spin_unlock_irq(&i915->gpu_error.lock);
}
+
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+void intel_klog_error_capture(struct intel_gt *gt,
+ intel_engine_mask_t engine_mask)
+{
+ static int g_count;
+ struct drm_i915_private *i915 = gt->i915;
+ struct i915_gpu_coredump *error;
+ intel_wakeref_t wakeref;
+ size_t buf_size = PAGE_SIZE * 128;
+ size_t pos_err;
+ char *buf, *ptr, *next;
+ int l_count = g_count++;
+ int line = 0;
+
+ /* Can't allocate memory during a reset */
+ if (test_bit(I915_RESET_BACKOFF, &gt->reset.flags)) {
+ drm_err(&gt->i915->drm, "[Capture/%d.%d] Inside GT reset, skipping error capture :(\n",
+ l_count, line++);
+ return;
+ }
+
+ error = READ_ONCE(i915->gpu_error.first_error);
+ if (error) {
+ drm_err(&i915->drm, "[Capture/%d.%d] Clearing existing error capture first...\n",
+ l_count, line++);
+ i915_reset_error_state(i915);
+ }
+
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref)
+ error = i915_gpu_coredump(gt, engine_mask, CORE_DUMP_FLAG_NONE);
+
+ if (IS_ERR(error)) {
+ drm_err(&i915->drm, "[Capture/%d.%d] Failed to capture error capture: %ld!\n",
+ l_count, line++, PTR_ERR(error));
+ return;
+ }
+
+ buf = kvmalloc(buf_size, GFP_KERNEL);
+ if (!buf) {
+ drm_err(&i915->drm, "[Capture/%d.%d] Failed to allocate buffer for error capture!\n",
+ l_count, line++);
+ i915_gpu_coredump_put(error);
+ return;
+ }
+
+ drm_info(&i915->drm, "[Capture/%d.%d] Dumping i915 error capture for %ps...\n",
+ l_count, line++, __builtin_return_address(0));
+
+ /* Largest string length safe to print via dmesg */
+# define MAX_CHUNK 800
+
+ pos_err = 0;
+ while (1) {
+ ssize_t got = i915_gpu_coredump_copy_to_buffer(error, buf, pos_err, buf_size - 1);
+
+ if (got <= 0)
+ break;
+
+ buf[got] = 0;
+ pos_err += got;
+
+ ptr = buf;
+ while (got > 0) {
+ size_t count;
+ char tag[2];
+
+ next = strnchr(ptr, got, '\n');
+ if (next) {
+ count = next - ptr;
+ *next = 0;
+ tag[0] = '>';
+ tag[1] = '<';
+ } else {
+ count = got;
+ tag[0] = '}';
+ tag[1] = '{';
+ }
+
+ if (count > MAX_CHUNK) {
+ size_t pos;
+ char *ptr2 = ptr;
+
+ for (pos = MAX_CHUNK; pos < count; pos += MAX_CHUNK) {
+ char chr = ptr[pos];
+
+ ptr[pos] = 0;
+ drm_info(&i915->drm, "[Capture/%d.%d] }%s{\n",
+ l_count, line++, ptr2);
+ ptr[pos] = chr;
+ ptr2 = ptr + pos;
+
+ /*
+ * If spewing large amounts of data via a serial console,
+ * this can be a very slow process. So be friendly and try
+ * not to cause 'softlockup on CPU' problems.
+ */
+ cond_resched();
+ }
+
+ if (ptr2 < (ptr + count))
+ drm_info(&i915->drm, "[Capture/%d.%d] %c%s%c\n",
+ l_count, line++, tag[0], ptr2, tag[1]);
+ else if (tag[0] == '>')
+ drm_info(&i915->drm, "[Capture/%d.%d] ><\n",
+ l_count, line++);
+ } else {
+ drm_info(&i915->drm, "[Capture/%d.%d] %c%s%c\n",
+ l_count, line++, tag[0], ptr, tag[1]);
+ }
+
+ ptr = next;
+ got -= count;
+ if (next) {
+ ptr++;
+ got--;
+ }
+
+ /* As above. */
+ cond_resched();
+ }
+
+ if (got)
+ drm_info(&i915->drm, "[Capture/%d.%d] Got %zd bytes remaining!\n",
+ l_count, line++, got);
+ }
+
+ kvfree(buf);
+
+ drm_info(&i915->drm, "[Capture/%d.%d] Dumped %zd bytes\n", l_count, line++, pos_err);
+}
+#endif
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h
index a91932cc6531..a78c061ce26f 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.h
+++ b/drivers/gpu/drm/i915/i915_gpu_error.h
@@ -258,6 +258,16 @@ static inline u32 i915_reset_engine_count(struct i915_gpu_error *error,
#define CORE_DUMP_FLAG_NONE 0x0
#define CORE_DUMP_FLAG_IS_GUC_CAPTURE BIT(0)
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) && IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+void intel_klog_error_capture(struct intel_gt *gt,
+ intel_engine_mask_t engine_mask);
+#else
+static inline void intel_klog_error_capture(struct intel_gt *gt,
+ intel_engine_mask_t engine_mask)
+{
+}
+#endif
+
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
__printf(2, 3)
diff --git a/drivers/gpu/drm/i915/i915_hwmon.c b/drivers/gpu/drm/i915/i915_hwmon.c
index 8e7dccc8d3a0..975da8e7f2a9 100644
--- a/drivers/gpu/drm/i915/i915_hwmon.c
+++ b/drivers/gpu/drm/i915/i915_hwmon.c
@@ -50,6 +50,8 @@ struct hwm_drvdata {
struct hwm_energy_info ei; /* Energy info for energy1_input */
char name[12];
int gt_n;
+ bool reset_in_progress;
+ wait_queue_head_t waitq;
};
struct i915_hwmon {
@@ -267,7 +269,7 @@ static const struct attribute_group *hwm_groups[] = {
NULL
};
-static const struct hwmon_channel_info *hwm_info[] = {
+static const struct hwmon_channel_info * const hwm_info[] = {
HWMON_CHANNEL_INFO(in, HWMON_I_INPUT),
HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_CRIT),
HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT),
@@ -275,7 +277,7 @@ static const struct hwmon_channel_info *hwm_info[] = {
NULL
};
-static const struct hwmon_channel_info *hwm_gt_info[] = {
+static const struct hwmon_channel_info * const hwm_gt_info[] = {
HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT),
NULL
};
@@ -396,31 +398,56 @@ hwm_power_max_write(struct hwm_drvdata *ddat, long val)
{
struct i915_hwmon *hwmon = ddat->hwmon;
intel_wakeref_t wakeref;
+ DEFINE_WAIT(wait);
+ int ret = 0;
u32 nval;
- /* Disable PL1 limit and verify, because the limit cannot be disabled on all platforms */
- if (val == PL1_DISABLE) {
+ /* Block waiting for GuC reset to complete when needed */
+ for (;;) {
mutex_lock(&hwmon->hwmon_lock);
- with_intel_runtime_pm(ddat->uncore->rpm, wakeref) {
- intel_uncore_rmw(ddat->uncore, hwmon->rg.pkg_rapl_limit,
- PKG_PWR_LIM_1_EN, 0);
- nval = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
+
+ prepare_to_wait(&ddat->waitq, &wait, TASK_INTERRUPTIBLE);
+
+ if (!hwmon->ddat.reset_in_progress)
+ break;
+
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ break;
}
+
mutex_unlock(&hwmon->hwmon_lock);
+ schedule();
+ }
+ finish_wait(&ddat->waitq, &wait);
+ if (ret)
+ goto unlock;
+
+ wakeref = intel_runtime_pm_get(ddat->uncore->rpm);
+
+ /* Disable PL1 limit and verify, because the limit cannot be disabled on all platforms */
+ if (val == PL1_DISABLE) {
+ intel_uncore_rmw(ddat->uncore, hwmon->rg.pkg_rapl_limit,
+ PKG_PWR_LIM_1_EN, 0);
+ nval = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
+
if (nval & PKG_PWR_LIM_1_EN)
- return -ENODEV;
- return 0;
+ ret = -ENODEV;
+ goto exit;
}
/* Computation in 64-bits to avoid overflow. Round to nearest. */
nval = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_power, SF_POWER);
nval = PKG_PWR_LIM_1_EN | REG_FIELD_PREP(PKG_PWR_LIM_1, nval);
- hwm_locked_with_pm_intel_uncore_rmw(ddat, hwmon->rg.pkg_rapl_limit,
- PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1,
- nval);
- return 0;
+ intel_uncore_rmw(ddat->uncore, hwmon->rg.pkg_rapl_limit,
+ PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1, nval);
+exit:
+ intel_runtime_pm_put(ddat->uncore->rpm, wakeref);
+unlock:
+ mutex_unlock(&hwmon->hwmon_lock);
+ return ret;
}
static int
@@ -470,6 +497,41 @@ hwm_power_write(struct hwm_drvdata *ddat, u32 attr, int chan, long val)
}
}
+void i915_hwmon_power_max_disable(struct drm_i915_private *i915, bool *old)
+{
+ struct i915_hwmon *hwmon = i915->hwmon;
+ u32 r;
+
+ if (!hwmon || !i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit))
+ return;
+
+ mutex_lock(&hwmon->hwmon_lock);
+
+ hwmon->ddat.reset_in_progress = true;
+ r = intel_uncore_rmw(hwmon->ddat.uncore, hwmon->rg.pkg_rapl_limit,
+ PKG_PWR_LIM_1_EN, 0);
+ *old = !!(r & PKG_PWR_LIM_1_EN);
+
+ mutex_unlock(&hwmon->hwmon_lock);
+}
+
+void i915_hwmon_power_max_restore(struct drm_i915_private *i915, bool old)
+{
+ struct i915_hwmon *hwmon = i915->hwmon;
+
+ if (!hwmon || !i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit))
+ return;
+
+ mutex_lock(&hwmon->hwmon_lock);
+
+ intel_uncore_rmw(hwmon->ddat.uncore, hwmon->rg.pkg_rapl_limit,
+ PKG_PWR_LIM_1_EN, old ? PKG_PWR_LIM_1_EN : 0);
+ hwmon->ddat.reset_in_progress = false;
+ wake_up_all(&hwmon->ddat.waitq);
+
+ mutex_unlock(&hwmon->hwmon_lock);
+}
+
static umode_t
hwm_energy_is_visible(const struct hwm_drvdata *ddat, u32 attr)
{
@@ -742,6 +804,7 @@ void i915_hwmon_register(struct drm_i915_private *i915)
ddat->uncore = &i915->uncore;
snprintf(ddat->name, sizeof(ddat->name), "i915");
ddat->gt_n = -1;
+ init_waitqueue_head(&ddat->waitq);
for_each_gt(gt, i915, i) {
ddat_gt = hwmon->ddat_gt + i;
diff --git a/drivers/gpu/drm/i915/i915_hwmon.h b/drivers/gpu/drm/i915/i915_hwmon.h
index 7ca9cf2c34c9..0fcb7de84406 100644
--- a/drivers/gpu/drm/i915/i915_hwmon.h
+++ b/drivers/gpu/drm/i915/i915_hwmon.h
@@ -7,14 +7,21 @@
#ifndef __I915_HWMON_H__
#define __I915_HWMON_H__
+#include <linux/types.h>
+
struct drm_i915_private;
+struct intel_gt;
#if IS_REACHABLE(CONFIG_HWMON)
void i915_hwmon_register(struct drm_i915_private *i915);
void i915_hwmon_unregister(struct drm_i915_private *i915);
+void i915_hwmon_power_max_disable(struct drm_i915_private *i915, bool *old);
+void i915_hwmon_power_max_restore(struct drm_i915_private *i915, bool old);
#else
static inline void i915_hwmon_register(struct drm_i915_private *i915) { };
static inline void i915_hwmon_unregister(struct drm_i915_private *i915) { };
+static inline void i915_hwmon_power_max_disable(struct drm_i915_private *i915, bool *old) { };
+static inline void i915_hwmon_power_max_restore(struct drm_i915_private *i915, bool old) { };
#endif
#endif /* __I915_HWMON_H__ */
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index d24bdea65a3d..82fbabcdd7a5 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -33,15 +33,11 @@
#include <drm/drm_drv.h>
-#include "display/icl_dsi_regs.h"
-#include "display/intel_de.h"
-#include "display/intel_display_trace.h"
+#include "display/intel_display_irq.h"
#include "display/intel_display_types.h"
-#include "display/intel_fdi_regs.h"
-#include "display/intel_fifo_underrun.h"
#include "display/intel_hotplug.h"
+#include "display/intel_hotplug_irq.h"
#include "display/intel_lpe_audio.h"
-#include "display/intel_psr.h"
#include "display/intel_psr_regs.h"
#include "gt/intel_breadcrumbs.h"
@@ -54,6 +50,7 @@
#include "i915_driver.h"
#include "i915_drv.h"
#include "i915_irq.h"
+#include "i915_reg.h"
/**
* DOC: interrupt handling
@@ -81,159 +78,6 @@ static inline void pmu_irq_stats(struct drm_i915_private *i915,
WRITE_ONCE(i915->pmu.irq_count, i915->pmu.irq_count + 1);
}
-typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val);
-typedef u32 (*hotplug_enables_func)(struct intel_encoder *encoder);
-
-static const u32 hpd_ilk[HPD_NUM_PINS] = {
- [HPD_PORT_A] = DE_DP_A_HOTPLUG,
-};
-
-static const u32 hpd_ivb[HPD_NUM_PINS] = {
- [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB,
-};
-
-static const u32 hpd_bdw[HPD_NUM_PINS] = {
- [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A),
-};
-
-static const u32 hpd_ibx[HPD_NUM_PINS] = {
- [HPD_CRT] = SDE_CRT_HOTPLUG,
- [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
- [HPD_PORT_B] = SDE_PORTB_HOTPLUG,
- [HPD_PORT_C] = SDE_PORTC_HOTPLUG,
- [HPD_PORT_D] = SDE_PORTD_HOTPLUG,
-};
-
-static const u32 hpd_cpt[HPD_NUM_PINS] = {
- [HPD_CRT] = SDE_CRT_HOTPLUG_CPT,
- [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT,
- [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
- [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
- [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
-};
-
-static const u32 hpd_spt[HPD_NUM_PINS] = {
- [HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT,
- [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
- [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
- [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
- [HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT,
-};
-
-static const u32 hpd_mask_i915[HPD_NUM_PINS] = {
- [HPD_CRT] = CRT_HOTPLUG_INT_EN,
- [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
- [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN,
- [HPD_PORT_B] = PORTB_HOTPLUG_INT_EN,
- [HPD_PORT_C] = PORTC_HOTPLUG_INT_EN,
- [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN,
-};
-
-static const u32 hpd_status_g4x[HPD_NUM_PINS] = {
- [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
- [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
- [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
- [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
- [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
- [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS,
-};
-
-static const u32 hpd_status_i915[HPD_NUM_PINS] = {
- [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
- [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
- [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915,
- [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
- [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
- [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS,
-};
-
-static const u32 hpd_bxt[HPD_NUM_PINS] = {
- [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A),
- [HPD_PORT_B] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_B),
- [HPD_PORT_C] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_C),
-};
-
-static const u32 hpd_gen11[HPD_NUM_PINS] = {
- [HPD_PORT_TC1] = GEN11_TC_HOTPLUG(HPD_PORT_TC1) | GEN11_TBT_HOTPLUG(HPD_PORT_TC1),
- [HPD_PORT_TC2] = GEN11_TC_HOTPLUG(HPD_PORT_TC2) | GEN11_TBT_HOTPLUG(HPD_PORT_TC2),
- [HPD_PORT_TC3] = GEN11_TC_HOTPLUG(HPD_PORT_TC3) | GEN11_TBT_HOTPLUG(HPD_PORT_TC3),
- [HPD_PORT_TC4] = GEN11_TC_HOTPLUG(HPD_PORT_TC4) | GEN11_TBT_HOTPLUG(HPD_PORT_TC4),
- [HPD_PORT_TC5] = GEN11_TC_HOTPLUG(HPD_PORT_TC5) | GEN11_TBT_HOTPLUG(HPD_PORT_TC5),
- [HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | GEN11_TBT_HOTPLUG(HPD_PORT_TC6),
-};
-
-static const u32 hpd_icp[HPD_NUM_PINS] = {
- [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
- [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
- [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C),
- [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
- [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
- [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
- [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
- [HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC5),
- [HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC6),
-};
-
-static const u32 hpd_sde_dg1[HPD_NUM_PINS] = {
- [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
- [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
- [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C),
- [HPD_PORT_D] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_D),
- [HPD_PORT_TC1] = SDE_TC_HOTPLUG_DG2(HPD_PORT_TC1),
-};
-
-static void intel_hpd_init_pins(struct drm_i915_private *dev_priv)
-{
- struct intel_hotplug *hpd = &dev_priv->display.hotplug;
-
- if (HAS_GMCH(dev_priv)) {
- if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
- IS_CHERRYVIEW(dev_priv))
- hpd->hpd = hpd_status_g4x;
- else
- hpd->hpd = hpd_status_i915;
- return;
- }
-
- if (DISPLAY_VER(dev_priv) >= 11)
- hpd->hpd = hpd_gen11;
- else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
- hpd->hpd = hpd_bxt;
- else if (DISPLAY_VER(dev_priv) == 9)
- hpd->hpd = NULL; /* no north HPD on SKL */
- else if (DISPLAY_VER(dev_priv) >= 8)
- hpd->hpd = hpd_bdw;
- else if (DISPLAY_VER(dev_priv) >= 7)
- hpd->hpd = hpd_ivb;
- else
- hpd->hpd = hpd_ilk;
-
- if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) &&
- (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)))
- return;
-
- if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
- hpd->pch_hpd = hpd_sde_dg1;
- else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
- hpd->pch_hpd = hpd_icp;
- else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv))
- hpd->pch_hpd = hpd_spt;
- else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_CPT(dev_priv))
- hpd->pch_hpd = hpd_cpt;
- else if (HAS_PCH_IBX(dev_priv))
- hpd->pch_hpd = hpd_ibx;
- else
- MISSING_CASE(INTEL_PCH_TYPE(dev_priv));
-}
-
-static void
-intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
-{
- struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
-
- drm_crtc_handle_vblank(&crtc->base);
-}
-
void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr,
i915_reg_t iir, i915_reg_t ier)
{
@@ -266,7 +110,7 @@ static void gen2_irq_reset(struct intel_uncore *uncore)
/*
* We should clear IMR at preinstall/uninstall, and just check at postinstall.
*/
-static void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg)
+void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg)
{
u32 val = intel_uncore_read(uncore, reg);
@@ -320,302 +164,6 @@ static void gen2_irq_init(struct intel_uncore *uncore,
intel_uncore_posting_read16(uncore, GEN2_IMR);
}
-/* For display hotplug interrupt */
-static inline void
-i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv,
- u32 mask,
- u32 bits)
-{
- lockdep_assert_held(&dev_priv->irq_lock);
- drm_WARN_ON(&dev_priv->drm, bits & ~mask);
-
- intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_EN, mask, bits);
-}
-
-/**
- * i915_hotplug_interrupt_update - update hotplug interrupt enable
- * @dev_priv: driver private
- * @mask: bits to update
- * @bits: bits to enable
- * NOTE: the HPD enable bits are modified both inside and outside
- * of an interrupt context. To avoid that read-modify-write cycles
- * interfer, these bits are protected by a spinlock. Since this
- * function is usually not called from a context where the lock is
- * held already, this function acquires the lock itself. A non-locking
- * version is also available.
- */
-void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
- u32 mask,
- u32 bits)
-{
- spin_lock_irq(&dev_priv->irq_lock);
- i915_hotplug_interrupt_update_locked(dev_priv, mask, bits);
- spin_unlock_irq(&dev_priv->irq_lock);
-}
-
-/**
- * ilk_update_display_irq - update DEIMR
- * @dev_priv: driver private
- * @interrupt_mask: mask of interrupt bits to update
- * @enabled_irq_mask: mask of interrupt bits to enable
- */
-static void ilk_update_display_irq(struct drm_i915_private *dev_priv,
- u32 interrupt_mask, u32 enabled_irq_mask)
-{
- u32 new_val;
-
- lockdep_assert_held(&dev_priv->irq_lock);
- drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
-
- new_val = dev_priv->irq_mask;
- new_val &= ~interrupt_mask;
- new_val |= (~enabled_irq_mask & interrupt_mask);
-
- if (new_val != dev_priv->irq_mask &&
- !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) {
- dev_priv->irq_mask = new_val;
- intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask);
- intel_uncore_posting_read(&dev_priv->uncore, DEIMR);
- }
-}
-
-void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits)
-{
- ilk_update_display_irq(i915, bits, bits);
-}
-
-void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits)
-{
- ilk_update_display_irq(i915, bits, 0);
-}
-
-/**
- * bdw_update_port_irq - update DE port interrupt
- * @dev_priv: driver private
- * @interrupt_mask: mask of interrupt bits to update
- * @enabled_irq_mask: mask of interrupt bits to enable
- */
-static void bdw_update_port_irq(struct drm_i915_private *dev_priv,
- u32 interrupt_mask,
- u32 enabled_irq_mask)
-{
- u32 new_val;
- u32 old_val;
-
- lockdep_assert_held(&dev_priv->irq_lock);
-
- drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
-
- if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
- return;
-
- old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR);
-
- new_val = old_val;
- new_val &= ~interrupt_mask;
- new_val |= (~enabled_irq_mask & interrupt_mask);
-
- if (new_val != old_val) {
- intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val);
- intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR);
- }
-}
-
-/**
- * bdw_update_pipe_irq - update DE pipe interrupt
- * @dev_priv: driver private
- * @pipe: pipe whose interrupt to update
- * @interrupt_mask: mask of interrupt bits to update
- * @enabled_irq_mask: mask of interrupt bits to enable
- */
-static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
- enum pipe pipe, u32 interrupt_mask,
- u32 enabled_irq_mask)
-{
- u32 new_val;
-
- lockdep_assert_held(&dev_priv->irq_lock);
-
- drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
-
- if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
- return;
-
- new_val = dev_priv->de_irq_mask[pipe];
- new_val &= ~interrupt_mask;
- new_val |= (~enabled_irq_mask & interrupt_mask);
-
- if (new_val != dev_priv->de_irq_mask[pipe]) {
- dev_priv->de_irq_mask[pipe] = new_val;
- intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
- intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe));
- }
-}
-
-void bdw_enable_pipe_irq(struct drm_i915_private *i915,
- enum pipe pipe, u32 bits)
-{
- bdw_update_pipe_irq(i915, pipe, bits, bits);
-}
-
-void bdw_disable_pipe_irq(struct drm_i915_private *i915,
- enum pipe pipe, u32 bits)
-{
- bdw_update_pipe_irq(i915, pipe, bits, 0);
-}
-
-/**
- * ibx_display_interrupt_update - update SDEIMR
- * @dev_priv: driver private
- * @interrupt_mask: mask of interrupt bits to update
- * @enabled_irq_mask: mask of interrupt bits to enable
- */
-static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
- u32 interrupt_mask,
- u32 enabled_irq_mask)
-{
- u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR);
- sdeimr &= ~interrupt_mask;
- sdeimr |= (~enabled_irq_mask & interrupt_mask);
-
- drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
-
- lockdep_assert_held(&dev_priv->irq_lock);
-
- if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
- return;
-
- intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr);
- intel_uncore_posting_read(&dev_priv->uncore, SDEIMR);
-}
-
-void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits)
-{
- ibx_display_interrupt_update(i915, bits, bits);
-}
-
-void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits)
-{
- ibx_display_interrupt_update(i915, bits, 0);
-}
-
-u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv,
- enum pipe pipe)
-{
- u32 status_mask = dev_priv->pipestat_irq_mask[pipe];
- u32 enable_mask = status_mask << 16;
-
- lockdep_assert_held(&dev_priv->irq_lock);
-
- if (DISPLAY_VER(dev_priv) < 5)
- goto out;
-
- /*
- * On pipe A we don't support the PSR interrupt yet,
- * on pipe B and C the same bit MBZ.
- */
- if (drm_WARN_ON_ONCE(&dev_priv->drm,
- status_mask & PIPE_A_PSR_STATUS_VLV))
- return 0;
- /*
- * On pipe B and C we don't support the PSR interrupt yet, on pipe
- * A the same bit is for perf counters which we don't use either.
- */
- if (drm_WARN_ON_ONCE(&dev_priv->drm,
- status_mask & PIPE_B_PSR_STATUS_VLV))
- return 0;
-
- enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS |
- SPRITE0_FLIP_DONE_INT_EN_VLV |
- SPRITE1_FLIP_DONE_INT_EN_VLV);
- if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV)
- enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV;
- if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV)
- enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV;
-
-out:
- drm_WARN_ONCE(&dev_priv->drm,
- enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
- status_mask & ~PIPESTAT_INT_STATUS_MASK,
- "pipe %c: enable_mask=0x%x, status_mask=0x%x\n",
- pipe_name(pipe), enable_mask, status_mask);
-
- return enable_mask;
-}
-
-void i915_enable_pipestat(struct drm_i915_private *dev_priv,
- enum pipe pipe, u32 status_mask)
-{
- i915_reg_t reg = PIPESTAT(pipe);
- u32 enable_mask;
-
- drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK,
- "pipe %c: status_mask=0x%x\n",
- pipe_name(pipe), status_mask);
-
- lockdep_assert_held(&dev_priv->irq_lock);
- drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
-
- if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask)
- return;
-
- dev_priv->pipestat_irq_mask[pipe] |= status_mask;
- enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
-
- intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask);
- intel_uncore_posting_read(&dev_priv->uncore, reg);
-}
-
-void i915_disable_pipestat(struct drm_i915_private *dev_priv,
- enum pipe pipe, u32 status_mask)
-{
- i915_reg_t reg = PIPESTAT(pipe);
- u32 enable_mask;
-
- drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK,
- "pipe %c: status_mask=0x%x\n",
- pipe_name(pipe), status_mask);
-
- lockdep_assert_held(&dev_priv->irq_lock);
- drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
-
- if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0)
- return;
-
- dev_priv->pipestat_irq_mask[pipe] &= ~status_mask;
- enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
-
- intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask);
- intel_uncore_posting_read(&dev_priv->uncore, reg);
-}
-
-static bool i915_has_asle(struct drm_i915_private *dev_priv)
-{
- if (!dev_priv->display.opregion.asle)
- return false;
-
- return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv);
-}
-
-/**
- * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion
- * @dev_priv: i915 device private
- */
-static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv)
-{
- if (!i915_has_asle(dev_priv))
- return;
-
- spin_lock_irq(&dev_priv->irq_lock);
-
- i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS);
- if (DISPLAY_VER(dev_priv) >= 4)
- i915_enable_pipestat(dev_priv, PIPE_A,
- PIPE_LEGACY_BLC_EVENT_STATUS);
-
- spin_unlock_irq(&dev_priv->irq_lock);
-}
-
/**
* ivb_parity_work - Workqueue called when a parity error interrupt
* occurred.
@@ -700,544 +248,6 @@ out:
mutex_unlock(&dev_priv->drm.struct_mutex);
}
-static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
-{
- switch (pin) {
- case HPD_PORT_TC1:
- case HPD_PORT_TC2:
- case HPD_PORT_TC3:
- case HPD_PORT_TC4:
- case HPD_PORT_TC5:
- case HPD_PORT_TC6:
- return val & GEN11_HOTPLUG_CTL_LONG_DETECT(pin);
- default:
- return false;
- }
-}
-
-static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
-{
- switch (pin) {
- case HPD_PORT_A:
- return val & PORTA_HOTPLUG_LONG_DETECT;
- case HPD_PORT_B:
- return val & PORTB_HOTPLUG_LONG_DETECT;
- case HPD_PORT_C:
- return val & PORTC_HOTPLUG_LONG_DETECT;
- default:
- return false;
- }
-}
-
-static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
-{
- switch (pin) {
- case HPD_PORT_A:
- case HPD_PORT_B:
- case HPD_PORT_C:
- case HPD_PORT_D:
- return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(pin);
- default:
- return false;
- }
-}
-
-static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
-{
- switch (pin) {
- case HPD_PORT_TC1:
- case HPD_PORT_TC2:
- case HPD_PORT_TC3:
- case HPD_PORT_TC4:
- case HPD_PORT_TC5:
- case HPD_PORT_TC6:
- return val & ICP_TC_HPD_LONG_DETECT(pin);
- default:
- return false;
- }
-}
-
-static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val)
-{
- switch (pin) {
- case HPD_PORT_E:
- return val & PORTE_HOTPLUG_LONG_DETECT;
- default:
- return false;
- }
-}
-
-static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
-{
- switch (pin) {
- case HPD_PORT_A:
- return val & PORTA_HOTPLUG_LONG_DETECT;
- case HPD_PORT_B:
- return val & PORTB_HOTPLUG_LONG_DETECT;
- case HPD_PORT_C:
- return val & PORTC_HOTPLUG_LONG_DETECT;
- case HPD_PORT_D:
- return val & PORTD_HOTPLUG_LONG_DETECT;
- default:
- return false;
- }
-}
-
-static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
-{
- switch (pin) {
- case HPD_PORT_A:
- return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT;
- default:
- return false;
- }
-}
-
-static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
-{
- switch (pin) {
- case HPD_PORT_B:
- return val & PORTB_HOTPLUG_LONG_DETECT;
- case HPD_PORT_C:
- return val & PORTC_HOTPLUG_LONG_DETECT;
- case HPD_PORT_D:
- return val & PORTD_HOTPLUG_LONG_DETECT;
- default:
- return false;
- }
-}
-
-static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
-{
- switch (pin) {
- case HPD_PORT_B:
- return val & PORTB_HOTPLUG_INT_LONG_PULSE;
- case HPD_PORT_C:
- return val & PORTC_HOTPLUG_INT_LONG_PULSE;
- case HPD_PORT_D:
- return val & PORTD_HOTPLUG_INT_LONG_PULSE;
- default:
- return false;
- }
-}
-
-/*
- * Get a bit mask of pins that have triggered, and which ones may be long.
- * This can be called multiple times with the same masks to accumulate
- * hotplug detection results from several registers.
- *
- * Note that the caller is expected to zero out the masks initially.
- */
-static void intel_get_hpd_pins(struct drm_i915_private *dev_priv,
- u32 *pin_mask, u32 *long_mask,
- u32 hotplug_trigger, u32 dig_hotplug_reg,
- const u32 hpd[HPD_NUM_PINS],
- bool long_pulse_detect(enum hpd_pin pin, u32 val))
-{
- enum hpd_pin pin;
-
- BUILD_BUG_ON(BITS_PER_TYPE(*pin_mask) < HPD_NUM_PINS);
-
- for_each_hpd_pin(pin) {
- if ((hpd[pin] & hotplug_trigger) == 0)
- continue;
-
- *pin_mask |= BIT(pin);
-
- if (long_pulse_detect(pin, dig_hotplug_reg))
- *long_mask |= BIT(pin);
- }
-
- drm_dbg(&dev_priv->drm,
- "hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n",
- hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask);
-
-}
-
-static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv,
- const u32 hpd[HPD_NUM_PINS])
-{
- struct intel_encoder *encoder;
- u32 enabled_irqs = 0;
-
- for_each_intel_encoder(&dev_priv->drm, encoder)
- if (dev_priv->display.hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED)
- enabled_irqs |= hpd[encoder->hpd_pin];
-
- return enabled_irqs;
-}
-
-static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv,
- const u32 hpd[HPD_NUM_PINS])
-{
- struct intel_encoder *encoder;
- u32 hotplug_irqs = 0;
-
- for_each_intel_encoder(&dev_priv->drm, encoder)
- hotplug_irqs |= hpd[encoder->hpd_pin];
-
- return hotplug_irqs;
-}
-
-static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915,
- hotplug_enables_func hotplug_enables)
-{
- struct intel_encoder *encoder;
- u32 hotplug = 0;
-
- for_each_intel_encoder(&i915->drm, encoder)
- hotplug |= hotplug_enables(encoder);
-
- return hotplug;
-}
-
-static void gmbus_irq_handler(struct drm_i915_private *dev_priv)
-{
- wake_up_all(&dev_priv->display.gmbus.wait_queue);
-}
-
-static void dp_aux_irq_handler(struct drm_i915_private *dev_priv)
-{
- wake_up_all(&dev_priv->display.gmbus.wait_queue);
-}
-
-#if defined(CONFIG_DEBUG_FS)
-static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
- enum pipe pipe,
- u32 crc0, u32 crc1,
- u32 crc2, u32 crc3,
- u32 crc4)
-{
- struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
- struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
- u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 };
-
- trace_intel_pipe_crc(crtc, crcs);
-
- spin_lock(&pipe_crc->lock);
- /*
- * For some not yet identified reason, the first CRC is
- * bonkers. So let's just wait for the next vblank and read
- * out the buggy result.
- *
- * On GEN8+ sometimes the second CRC is bonkers as well, so
- * don't trust that one either.
- */
- if (pipe_crc->skipped <= 0 ||
- (DISPLAY_VER(dev_priv) >= 8 && pipe_crc->skipped == 1)) {
- pipe_crc->skipped++;
- spin_unlock(&pipe_crc->lock);
- return;
- }
- spin_unlock(&pipe_crc->lock);
-
- drm_crtc_add_crc_entry(&crtc->base, true,
- drm_crtc_accurate_vblank_count(&crtc->base),
- crcs);
-}
-#else
-static inline void
-display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
- enum pipe pipe,
- u32 crc0, u32 crc1,
- u32 crc2, u32 crc3,
- u32 crc4) {}
-#endif
-
-static void flip_done_handler(struct drm_i915_private *i915,
- enum pipe pipe)
-{
- struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe);
- struct drm_crtc_state *crtc_state = crtc->base.state;
- struct drm_pending_vblank_event *e = crtc_state->event;
- struct drm_device *dev = &i915->drm;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev->event_lock, irqflags);
-
- crtc_state->event = NULL;
-
- drm_crtc_send_vblank_event(&crtc->base, e);
-
- spin_unlock_irqrestore(&dev->event_lock, irqflags);
-}
-
-static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
- enum pipe pipe)
-{
- display_pipe_crc_irq_handler(dev_priv, pipe,
- intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)),
- 0, 0, 0, 0);
-}
-
-static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
- enum pipe pipe)
-{
- display_pipe_crc_irq_handler(dev_priv, pipe,
- intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)),
- intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)),
- intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)),
- intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)),
- intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe)));
-}
-
-static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
- enum pipe pipe)
-{
- u32 res1, res2;
-
- if (DISPLAY_VER(dev_priv) >= 3)
- res1 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES1_I915(pipe));
- else
- res1 = 0;
-
- if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
- res2 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES2_G4X(pipe));
- else
- res2 = 0;
-
- display_pipe_crc_irq_handler(dev_priv, pipe,
- intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(pipe)),
- intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(pipe)),
- intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(pipe)),
- res1, res2);
-}
-
-static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv)
-{
- enum pipe pipe;
-
- for_each_pipe(dev_priv, pipe) {
- intel_uncore_write(&dev_priv->uncore, PIPESTAT(pipe),
- PIPESTAT_INT_STATUS_MASK |
- PIPE_FIFO_UNDERRUN_STATUS);
-
- dev_priv->pipestat_irq_mask[pipe] = 0;
- }
-}
-
-static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv,
- u32 iir, u32 pipe_stats[I915_MAX_PIPES])
-{
- enum pipe pipe;
-
- spin_lock(&dev_priv->irq_lock);
-
- if (!dev_priv->display_irqs_enabled) {
- spin_unlock(&dev_priv->irq_lock);
- return;
- }
-
- for_each_pipe(dev_priv, pipe) {
- i915_reg_t reg;
- u32 status_mask, enable_mask, iir_bit = 0;
-
- /*
- * PIPESTAT bits get signalled even when the interrupt is
- * disabled with the mask bits, and some of the status bits do
- * not generate interrupts at all (like the underrun bit). Hence
- * we need to be careful that we only handle what we want to
- * handle.
- */
-
- /* fifo underruns are filterered in the underrun handler. */
- status_mask = PIPE_FIFO_UNDERRUN_STATUS;
-
- switch (pipe) {
- default:
- case PIPE_A:
- iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
- break;
- case PIPE_B:
- iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
- break;
- case PIPE_C:
- iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
- break;
- }
- if (iir & iir_bit)
- status_mask |= dev_priv->pipestat_irq_mask[pipe];
-
- if (!status_mask)
- continue;
-
- reg = PIPESTAT(pipe);
- pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask;
- enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
-
- /*
- * Clear the PIPE*STAT regs before the IIR
- *
- * Toggle the enable bits to make sure we get an
- * edge in the ISR pipe event bit if we don't clear
- * all the enabled status bits. Otherwise the edge
- * triggered IIR on i965/g4x wouldn't notice that
- * an interrupt is still pending.
- */
- if (pipe_stats[pipe]) {
- intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]);
- intel_uncore_write(&dev_priv->uncore, reg, enable_mask);
- }
- }
- spin_unlock(&dev_priv->irq_lock);
-}
-
-static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv,
- u16 iir, u32 pipe_stats[I915_MAX_PIPES])
-{
- enum pipe pipe;
-
- for_each_pipe(dev_priv, pipe) {
- if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
- intel_handle_vblank(dev_priv, pipe);
-
- if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
- i9xx_pipe_crc_irq_handler(dev_priv, pipe);
-
- if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
- intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
- }
-}
-
-static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv,
- u32 iir, u32 pipe_stats[I915_MAX_PIPES])
-{
- bool blc_event = false;
- enum pipe pipe;
-
- for_each_pipe(dev_priv, pipe) {
- if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
- intel_handle_vblank(dev_priv, pipe);
-
- if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
- blc_event = true;
-
- if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
- i9xx_pipe_crc_irq_handler(dev_priv, pipe);
-
- if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
- intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
- }
-
- if (blc_event || (iir & I915_ASLE_INTERRUPT))
- intel_opregion_asle_intr(dev_priv);
-}
-
-static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv,
- u32 iir, u32 pipe_stats[I915_MAX_PIPES])
-{
- bool blc_event = false;
- enum pipe pipe;
-
- for_each_pipe(dev_priv, pipe) {
- if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
- intel_handle_vblank(dev_priv, pipe);
-
- if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
- blc_event = true;
-
- if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
- i9xx_pipe_crc_irq_handler(dev_priv, pipe);
-
- if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
- intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
- }
-
- if (blc_event || (iir & I915_ASLE_INTERRUPT))
- intel_opregion_asle_intr(dev_priv);
-
- if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
- gmbus_irq_handler(dev_priv);
-}
-
-static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
- u32 pipe_stats[I915_MAX_PIPES])
-{
- enum pipe pipe;
-
- for_each_pipe(dev_priv, pipe) {
- if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
- intel_handle_vblank(dev_priv, pipe);
-
- if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV)
- flip_done_handler(dev_priv, pipe);
-
- if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
- i9xx_pipe_crc_irq_handler(dev_priv, pipe);
-
- if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
- intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
- }
-
- if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
- gmbus_irq_handler(dev_priv);
-}
-
-static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv)
-{
- u32 hotplug_status = 0, hotplug_status_mask;
- int i;
-
- if (IS_G4X(dev_priv) ||
- IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
- hotplug_status_mask = HOTPLUG_INT_STATUS_G4X |
- DP_AUX_CHANNEL_MASK_INT_STATUS_G4X;
- else
- hotplug_status_mask = HOTPLUG_INT_STATUS_I915;
-
- /*
- * We absolutely have to clear all the pending interrupt
- * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port
- * interrupt bit won't have an edge, and the i965/g4x
- * edge triggered IIR will not notice that an interrupt
- * is still pending. We can't use PORT_HOTPLUG_EN to
- * guarantee the edge as the act of toggling the enable
- * bits can itself generate a new hotplug interrupt :(
- */
- for (i = 0; i < 10; i++) {
- u32 tmp = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT) & hotplug_status_mask;
-
- if (tmp == 0)
- return hotplug_status;
-
- hotplug_status |= tmp;
- intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, hotplug_status);
- }
-
- drm_WARN_ONCE(&dev_priv->drm, 1,
- "PORT_HOTPLUG_STAT did not clear (0x%08x)\n",
- intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT));
-
- return hotplug_status;
-}
-
-static void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv,
- u32 hotplug_status)
-{
- u32 pin_mask = 0, long_mask = 0;
- u32 hotplug_trigger;
-
- if (IS_G4X(dev_priv) ||
- IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
- hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
- else
- hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
-
- if (hotplug_trigger) {
- intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
- hotplug_trigger, hotplug_trigger,
- dev_priv->display.hotplug.hpd,
- i9xx_port_hotplug_long_detect);
-
- intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
- }
-
- if ((IS_G4X(dev_priv) ||
- IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
- hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
- dp_aux_irq_handler(dev_priv);
-}
-
static irqreturn_t valleyview_irq_handler(int irq, void *arg)
{
struct drm_i915_private *dev_priv = arg;
@@ -1402,338 +412,6 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
return ret;
}
-static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv,
- u32 hotplug_trigger)
-{
- u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
-
- /*
- * Somehow the PCH doesn't seem to really ack the interrupt to the CPU
- * unless we touch the hotplug register, even if hotplug_trigger is
- * zero. Not acking leads to "The master control interrupt lied (SDE)!"
- * errors.
- */
- dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG);
- if (!hotplug_trigger) {
- u32 mask = PORTA_HOTPLUG_STATUS_MASK |
- PORTD_HOTPLUG_STATUS_MASK |
- PORTC_HOTPLUG_STATUS_MASK |
- PORTB_HOTPLUG_STATUS_MASK;
- dig_hotplug_reg &= ~mask;
- }
-
- intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg);
- if (!hotplug_trigger)
- return;
-
- intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
- hotplug_trigger, dig_hotplug_reg,
- dev_priv->display.hotplug.pch_hpd,
- pch_port_hotplug_long_detect);
-
- intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
-}
-
-static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
-{
- enum pipe pipe;
- u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
-
- ibx_hpd_irq_handler(dev_priv, hotplug_trigger);
-
- if (pch_iir & SDE_AUDIO_POWER_MASK) {
- int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >>
- SDE_AUDIO_POWER_SHIFT);
- drm_dbg(&dev_priv->drm, "PCH audio power change on port %d\n",
- port_name(port));
- }
-
- if (pch_iir & SDE_AUX_MASK)
- dp_aux_irq_handler(dev_priv);
-
- if (pch_iir & SDE_GMBUS)
- gmbus_irq_handler(dev_priv);
-
- if (pch_iir & SDE_AUDIO_HDCP_MASK)
- drm_dbg(&dev_priv->drm, "PCH HDCP audio interrupt\n");
-
- if (pch_iir & SDE_AUDIO_TRANS_MASK)
- drm_dbg(&dev_priv->drm, "PCH transcoder audio interrupt\n");
-
- if (pch_iir & SDE_POISON)
- drm_err(&dev_priv->drm, "PCH poison interrupt\n");
-
- if (pch_iir & SDE_FDI_MASK) {
- for_each_pipe(dev_priv, pipe)
- drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n",
- pipe_name(pipe),
- intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe)));
- }
-
- if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE))
- drm_dbg(&dev_priv->drm, "PCH transcoder CRC done interrupt\n");
-
- if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
- drm_dbg(&dev_priv->drm,
- "PCH transcoder CRC error interrupt\n");
-
- if (pch_iir & SDE_TRANSA_FIFO_UNDER)
- intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A);
-
- if (pch_iir & SDE_TRANSB_FIFO_UNDER)
- intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B);
-}
-
-static void ivb_err_int_handler(struct drm_i915_private *dev_priv)
-{
- u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT);
- enum pipe pipe;
-
- if (err_int & ERR_INT_POISON)
- drm_err(&dev_priv->drm, "Poison interrupt\n");
-
- for_each_pipe(dev_priv, pipe) {
- if (err_int & ERR_INT_FIFO_UNDERRUN(pipe))
- intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
-
- if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) {
- if (IS_IVYBRIDGE(dev_priv))
- ivb_pipe_crc_irq_handler(dev_priv, pipe);
- else
- hsw_pipe_crc_irq_handler(dev_priv, pipe);
- }
- }
-
- intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int);
-}
-
-static void cpt_serr_int_handler(struct drm_i915_private *dev_priv)
-{
- u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT);
- enum pipe pipe;
-
- if (serr_int & SERR_INT_POISON)
- drm_err(&dev_priv->drm, "PCH poison interrupt\n");
-
- for_each_pipe(dev_priv, pipe)
- if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe))
- intel_pch_fifo_underrun_irq_handler(dev_priv, pipe);
-
- intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int);
-}
-
-static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
-{
- enum pipe pipe;
- u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
-
- ibx_hpd_irq_handler(dev_priv, hotplug_trigger);
-
- if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) {
- int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
- SDE_AUDIO_POWER_SHIFT_CPT);
- drm_dbg(&dev_priv->drm, "PCH audio power change on port %c\n",
- port_name(port));
- }
-
- if (pch_iir & SDE_AUX_MASK_CPT)
- dp_aux_irq_handler(dev_priv);
-
- if (pch_iir & SDE_GMBUS_CPT)
- gmbus_irq_handler(dev_priv);
-
- if (pch_iir & SDE_AUDIO_CP_REQ_CPT)
- drm_dbg(&dev_priv->drm, "Audio CP request interrupt\n");
-
- if (pch_iir & SDE_AUDIO_CP_CHG_CPT)
- drm_dbg(&dev_priv->drm, "Audio CP change interrupt\n");
-
- if (pch_iir & SDE_FDI_MASK_CPT) {
- for_each_pipe(dev_priv, pipe)
- drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n",
- pipe_name(pipe),
- intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe)));
- }
-
- if (pch_iir & SDE_ERROR_CPT)
- cpt_serr_int_handler(dev_priv);
-}
-
-static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
-{
- u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP;
- u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP;
- u32 pin_mask = 0, long_mask = 0;
-
- if (ddi_hotplug_trigger) {
- u32 dig_hotplug_reg;
-
- /* Locking due to DSI native GPIO sequences */
- spin_lock(&dev_priv->irq_lock);
- dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0);
- spin_unlock(&dev_priv->irq_lock);
-
- intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
- ddi_hotplug_trigger, dig_hotplug_reg,
- dev_priv->display.hotplug.pch_hpd,
- icp_ddi_port_hotplug_long_detect);
- }
-
- if (tc_hotplug_trigger) {
- u32 dig_hotplug_reg;
-
- dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC, 0, 0);
-
- intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
- tc_hotplug_trigger, dig_hotplug_reg,
- dev_priv->display.hotplug.pch_hpd,
- icp_tc_port_hotplug_long_detect);
- }
-
- if (pin_mask)
- intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
-
- if (pch_iir & SDE_GMBUS_ICP)
- gmbus_irq_handler(dev_priv);
-}
-
-static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
-{
- u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT &
- ~SDE_PORTE_HOTPLUG_SPT;
- u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT;
- u32 pin_mask = 0, long_mask = 0;
-
- if (hotplug_trigger) {
- u32 dig_hotplug_reg;
-
- dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0);
-
- intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
- hotplug_trigger, dig_hotplug_reg,
- dev_priv->display.hotplug.pch_hpd,
- spt_port_hotplug_long_detect);
- }
-
- if (hotplug2_trigger) {
- u32 dig_hotplug_reg;
-
- dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, 0, 0);
-
- intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
- hotplug2_trigger, dig_hotplug_reg,
- dev_priv->display.hotplug.pch_hpd,
- spt_port_hotplug2_long_detect);
- }
-
- if (pin_mask)
- intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
-
- if (pch_iir & SDE_GMBUS_CPT)
- gmbus_irq_handler(dev_priv);
-}
-
-static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv,
- u32 hotplug_trigger)
-{
- u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
-
- dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, 0, 0);
-
- intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
- hotplug_trigger, dig_hotplug_reg,
- dev_priv->display.hotplug.hpd,
- ilk_port_hotplug_long_detect);
-
- intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
-}
-
-static void ilk_display_irq_handler(struct drm_i915_private *dev_priv,
- u32 de_iir)
-{
- enum pipe pipe;
- u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG;
-
- if (hotplug_trigger)
- ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
-
- if (de_iir & DE_AUX_CHANNEL_A)
- dp_aux_irq_handler(dev_priv);
-
- if (de_iir & DE_GSE)
- intel_opregion_asle_intr(dev_priv);
-
- if (de_iir & DE_POISON)
- drm_err(&dev_priv->drm, "Poison interrupt\n");
-
- for_each_pipe(dev_priv, pipe) {
- if (de_iir & DE_PIPE_VBLANK(pipe))
- intel_handle_vblank(dev_priv, pipe);
-
- if (de_iir & DE_PLANE_FLIP_DONE(pipe))
- flip_done_handler(dev_priv, pipe);
-
- if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
- intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
-
- if (de_iir & DE_PIPE_CRC_DONE(pipe))
- i9xx_pipe_crc_irq_handler(dev_priv, pipe);
- }
-
- /* check event from PCH */
- if (de_iir & DE_PCH_EVENT) {
- u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
-
- if (HAS_PCH_CPT(dev_priv))
- cpt_irq_handler(dev_priv, pch_iir);
- else
- ibx_irq_handler(dev_priv, pch_iir);
-
- /* should clear PCH hotplug event before clear CPU irq */
- intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir);
- }
-
- if (DISPLAY_VER(dev_priv) == 5 && de_iir & DE_PCU_EVENT)
- gen5_rps_irq_handler(&to_gt(dev_priv)->rps);
-}
-
-static void ivb_display_irq_handler(struct drm_i915_private *dev_priv,
- u32 de_iir)
-{
- enum pipe pipe;
- u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB;
-
- if (hotplug_trigger)
- ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
-
- if (de_iir & DE_ERR_INT_IVB)
- ivb_err_int_handler(dev_priv);
-
- if (de_iir & DE_AUX_CHANNEL_A_IVB)
- dp_aux_irq_handler(dev_priv);
-
- if (de_iir & DE_GSE_IVB)
- intel_opregion_asle_intr(dev_priv);
-
- for_each_pipe(dev_priv, pipe) {
- if (de_iir & DE_PIPE_VBLANK_IVB(pipe))
- intel_handle_vblank(dev_priv, pipe);
-
- if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe))
- flip_done_handler(dev_priv, pipe);
- }
-
- /* check event from PCH */
- if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) {
- u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
-
- cpt_irq_handler(dev_priv, pch_iir);
-
- /* clear PCH hotplug event before clear CPU irq */
- intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir);
- }
-}
-
/*
* To handle irqs with the minimum potential races with fresh interrupts, we:
* 1 - Disable Master Interrupt Control.
@@ -1812,376 +490,6 @@ static irqreturn_t ilk_irq_handler(int irq, void *arg)
return ret;
}
-static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv,
- u32 hotplug_trigger)
-{
- u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
-
- dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0);
-
- intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
- hotplug_trigger, dig_hotplug_reg,
- dev_priv->display.hotplug.hpd,
- bxt_port_hotplug_long_detect);
-
- intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
-}
-
-static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
-{
- u32 pin_mask = 0, long_mask = 0;
- u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK;
- u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK;
-
- if (trigger_tc) {
- u32 dig_hotplug_reg;
-
- dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, 0, 0);
-
- intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
- trigger_tc, dig_hotplug_reg,
- dev_priv->display.hotplug.hpd,
- gen11_port_hotplug_long_detect);
- }
-
- if (trigger_tbt) {
- u32 dig_hotplug_reg;
-
- dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, 0, 0);
-
- intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
- trigger_tbt, dig_hotplug_reg,
- dev_priv->display.hotplug.hpd,
- gen11_port_hotplug_long_detect);
- }
-
- if (pin_mask)
- intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
- else
- drm_err(&dev_priv->drm,
- "Unexpected DE HPD interrupt 0x%08x\n", iir);
-}
-
-static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
-{
- u32 mask;
-
- if (DISPLAY_VER(dev_priv) >= 13)
- return TGL_DE_PORT_AUX_DDIA |
- TGL_DE_PORT_AUX_DDIB |
- TGL_DE_PORT_AUX_DDIC |
- XELPD_DE_PORT_AUX_DDID |
- XELPD_DE_PORT_AUX_DDIE |
- TGL_DE_PORT_AUX_USBC1 |
- TGL_DE_PORT_AUX_USBC2 |
- TGL_DE_PORT_AUX_USBC3 |
- TGL_DE_PORT_AUX_USBC4;
- else if (DISPLAY_VER(dev_priv) >= 12)
- return TGL_DE_PORT_AUX_DDIA |
- TGL_DE_PORT_AUX_DDIB |
- TGL_DE_PORT_AUX_DDIC |
- TGL_DE_PORT_AUX_USBC1 |
- TGL_DE_PORT_AUX_USBC2 |
- TGL_DE_PORT_AUX_USBC3 |
- TGL_DE_PORT_AUX_USBC4 |
- TGL_DE_PORT_AUX_USBC5 |
- TGL_DE_PORT_AUX_USBC6;
-
-
- mask = GEN8_AUX_CHANNEL_A;
- if (DISPLAY_VER(dev_priv) >= 9)
- mask |= GEN9_AUX_CHANNEL_B |
- GEN9_AUX_CHANNEL_C |
- GEN9_AUX_CHANNEL_D;
-
- if (DISPLAY_VER(dev_priv) == 11) {
- mask |= ICL_AUX_CHANNEL_F;
- mask |= ICL_AUX_CHANNEL_E;
- }
-
- return mask;
-}
-
-static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
-{
- if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv))
- return RKL_DE_PIPE_IRQ_FAULT_ERRORS;
- else if (DISPLAY_VER(dev_priv) >= 11)
- return GEN11_DE_PIPE_IRQ_FAULT_ERRORS;
- else if (DISPLAY_VER(dev_priv) >= 9)
- return GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
- else
- return GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
-}
-
-static void
-gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
-{
- bool found = false;
-
- if (iir & GEN8_DE_MISC_GSE) {
- intel_opregion_asle_intr(dev_priv);
- found = true;
- }
-
- if (iir & GEN8_DE_EDP_PSR) {
- struct intel_encoder *encoder;
- u32 psr_iir;
- i915_reg_t iir_reg;
-
- for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
- struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
- if (DISPLAY_VER(dev_priv) >= 12)
- iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder);
- else
- iir_reg = EDP_PSR_IIR;
-
- psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0);
-
- if (psr_iir)
- found = true;
-
- intel_psr_irq_handler(intel_dp, psr_iir);
-
- /* prior GEN12 only have one EDP PSR */
- if (DISPLAY_VER(dev_priv) < 12)
- break;
- }
- }
-
- if (!found)
- drm_err(&dev_priv->drm, "Unexpected DE Misc interrupt\n");
-}
-
-static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv,
- u32 te_trigger)
-{
- enum pipe pipe = INVALID_PIPE;
- enum transcoder dsi_trans;
- enum port port;
- u32 val, tmp;
-
- /*
- * Incase of dual link, TE comes from DSI_1
- * this is to check if dual link is enabled
- */
- val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0));
- val &= PORT_SYNC_MODE_ENABLE;
-
- /*
- * if dual link is enabled, then read DSI_0
- * transcoder registers
- */
- port = ((te_trigger & DSI1_TE && val) || (te_trigger & DSI0_TE)) ?
- PORT_A : PORT_B;
- dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1;
-
- /* Check if DSI configured in command mode */
- val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans));
- val = val & OP_MODE_MASK;
-
- if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) {
- drm_err(&dev_priv->drm, "DSI trancoder not configured in command mode\n");
- return;
- }
-
- /* Get PIPE for handling VBLANK event */
- val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL(dsi_trans));
- switch (val & TRANS_DDI_EDP_INPUT_MASK) {
- case TRANS_DDI_EDP_INPUT_A_ON:
- pipe = PIPE_A;
- break;
- case TRANS_DDI_EDP_INPUT_B_ONOFF:
- pipe = PIPE_B;
- break;
- case TRANS_DDI_EDP_INPUT_C_ONOFF:
- pipe = PIPE_C;
- break;
- default:
- drm_err(&dev_priv->drm, "Invalid PIPE\n");
- return;
- }
-
- intel_handle_vblank(dev_priv, pipe);
-
- /* clear TE in dsi IIR */
- port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A;
- tmp = intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
-}
-
-static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915)
-{
- if (DISPLAY_VER(i915) >= 9)
- return GEN9_PIPE_PLANE1_FLIP_DONE;
- else
- return GEN8_PIPE_PRIMARY_FLIP_DONE;
-}
-
-u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv)
-{
- u32 mask = GEN8_PIPE_FIFO_UNDERRUN;
-
- if (DISPLAY_VER(dev_priv) >= 13)
- mask |= XELPD_PIPE_SOFT_UNDERRUN |
- XELPD_PIPE_HARD_UNDERRUN;
-
- return mask;
-}
-
-static irqreturn_t
-gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
-{
- irqreturn_t ret = IRQ_NONE;
- u32 iir;
- enum pipe pipe;
-
- drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DISPLAY(dev_priv));
-
- if (master_ctl & GEN8_DE_MISC_IRQ) {
- iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR);
- if (iir) {
- intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir);
- ret = IRQ_HANDLED;
- gen8_de_misc_irq_handler(dev_priv, iir);
- } else {
- drm_err_ratelimited(&dev_priv->drm,
- "The master control interrupt lied (DE MISC)!\n");
- }
- }
-
- if (DISPLAY_VER(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) {
- iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR);
- if (iir) {
- intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir);
- ret = IRQ_HANDLED;
- gen11_hpd_irq_handler(dev_priv, iir);
- } else {
- drm_err_ratelimited(&dev_priv->drm,
- "The master control interrupt lied, (DE HPD)!\n");
- }
- }
-
- if (master_ctl & GEN8_DE_PORT_IRQ) {
- iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR);
- if (iir) {
- bool found = false;
-
- intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir);
- ret = IRQ_HANDLED;
-
- if (iir & gen8_de_port_aux_mask(dev_priv)) {
- dp_aux_irq_handler(dev_priv);
- found = true;
- }
-
- if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
- u32 hotplug_trigger = iir & BXT_DE_PORT_HOTPLUG_MASK;
-
- if (hotplug_trigger) {
- bxt_hpd_irq_handler(dev_priv, hotplug_trigger);
- found = true;
- }
- } else if (IS_BROADWELL(dev_priv)) {
- u32 hotplug_trigger = iir & BDW_DE_PORT_HOTPLUG_MASK;
-
- if (hotplug_trigger) {
- ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
- found = true;
- }
- }
-
- if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
- (iir & BXT_DE_PORT_GMBUS)) {
- gmbus_irq_handler(dev_priv);
- found = true;
- }
-
- if (DISPLAY_VER(dev_priv) >= 11) {
- u32 te_trigger = iir & (DSI0_TE | DSI1_TE);
-
- if (te_trigger) {
- gen11_dsi_te_interrupt_handler(dev_priv, te_trigger);
- found = true;
- }
- }
-
- if (!found)
- drm_err_ratelimited(&dev_priv->drm,
- "Unexpected DE Port interrupt\n");
- }
- else
- drm_err_ratelimited(&dev_priv->drm,
- "The master control interrupt lied (DE PORT)!\n");
- }
-
- for_each_pipe(dev_priv, pipe) {
- u32 fault_errors;
-
- if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe)))
- continue;
-
- iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe));
- if (!iir) {
- drm_err_ratelimited(&dev_priv->drm,
- "The master control interrupt lied (DE PIPE)!\n");
- continue;
- }
-
- ret = IRQ_HANDLED;
- intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir);
-
- if (iir & GEN8_PIPE_VBLANK)
- intel_handle_vblank(dev_priv, pipe);
-
- if (iir & gen8_de_pipe_flip_done_mask(dev_priv))
- flip_done_handler(dev_priv, pipe);
-
- if (iir & GEN8_PIPE_CDCLK_CRC_DONE)
- hsw_pipe_crc_irq_handler(dev_priv, pipe);
-
- if (iir & gen8_de_pipe_underrun_mask(dev_priv))
- intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
-
- fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
- if (fault_errors)
- drm_err_ratelimited(&dev_priv->drm,
- "Fault errors on pipe %c: 0x%08x\n",
- pipe_name(pipe),
- fault_errors);
- }
-
- if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
- master_ctl & GEN8_DE_PCH_IRQ) {
- /*
- * FIXME(BDW): Assume for now that the new interrupt handling
- * scheme also closed the SDE interrupt handling race we've seen
- * on older pch-split platforms. But this needs testing.
- */
- iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
- if (iir) {
- intel_uncore_write(&dev_priv->uncore, SDEIIR, iir);
- ret = IRQ_HANDLED;
-
- if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
- icp_irq_handler(dev_priv, iir);
- else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
- spt_irq_handler(dev_priv, iir);
- else
- cpt_irq_handler(dev_priv, iir);
- } else {
- /*
- * Like on previous PCH there seems to be something
- * fishy going on with forwarding PCH interrupts.
- */
- drm_dbg(&dev_priv->drm,
- "The master control interrupt lied (SDE)!\n");
- }
- }
-
- return ret;
-}
-
static inline u32 gen8_master_intr_disable(void __iomem * const regs)
{
raw_reg_write(regs, GEN8_MASTER_IRQ, 0);
@@ -2232,29 +540,6 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
return IRQ_HANDLED;
}
-static u32
-gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl)
-{
- void __iomem * const regs = i915->uncore.regs;
- u32 iir;
-
- if (!(master_ctl & GEN11_GU_MISC_IRQ))
- return 0;
-
- iir = raw_reg_read(regs, GEN11_GU_MISC_IIR);
- if (likely(iir))
- raw_reg_write(regs, GEN11_GU_MISC_IIR, iir);
-
- return iir;
-}
-
-static void
-gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir)
-{
- if (iir & GEN11_GU_MISC_GSE)
- intel_opregion_asle_intr(i915);
-}
-
static inline u32 gen11_master_intr_disable(void __iomem * const regs)
{
raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0);
@@ -2273,25 +558,6 @@ static inline void gen11_master_intr_enable(void __iomem * const regs)
raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ);
}
-static void
-gen11_display_irq_handler(struct drm_i915_private *i915)
-{
- void __iomem * const regs = i915->uncore.regs;
- const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL);
-
- disable_rpm_wakeref_asserts(&i915->runtime_pm);
- /*
- * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ
- * for the display related bits.
- */
- raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0);
- gen8_de_irq_handler(i915, disp_ctl);
- raw_reg_write(regs, GEN11_DISPLAY_INT_CTL,
- GEN11_DISPLAY_IRQ_ENABLE);
-
- enable_rpm_wakeref_asserts(&i915->runtime_pm);
-}
-
static irqreturn_t gen11_irq_handler(int irq, void *arg)
{
struct drm_i915_private *i915 = arg;
@@ -2393,184 +659,6 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg)
return IRQ_HANDLED;
}
-/* Called from drm generic code, passed 'crtc' which
- * we use as a pipe index
- */
-int i8xx_enable_vblank(struct drm_crtc *crtc)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
- enum pipe pipe = to_intel_crtc(crtc)->pipe;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-
- return 0;
-}
-
-int i915gm_enable_vblank(struct drm_crtc *crtc)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
-
- /*
- * Vblank interrupts fail to wake the device up from C2+.
- * Disabling render clock gating during C-states avoids
- * the problem. There is a small power cost so we do this
- * only when vblank interrupts are actually enabled.
- */
- if (dev_priv->vblank_enabled++ == 0)
- intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
-
- return i8xx_enable_vblank(crtc);
-}
-
-int i965_enable_vblank(struct drm_crtc *crtc)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
- enum pipe pipe = to_intel_crtc(crtc)->pipe;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- i915_enable_pipestat(dev_priv, pipe,
- PIPE_START_VBLANK_INTERRUPT_STATUS);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-
- return 0;
-}
-
-int ilk_enable_vblank(struct drm_crtc *crtc)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
- enum pipe pipe = to_intel_crtc(crtc)->pipe;
- unsigned long irqflags;
- u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
- DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
-
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- ilk_enable_display_irq(dev_priv, bit);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-
- /* Even though there is no DMC, frame counter can get stuck when
- * PSR is active as no frames are generated.
- */
- if (HAS_PSR(dev_priv))
- drm_crtc_vblank_restore(crtc);
-
- return 0;
-}
-
-static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
- bool enable)
-{
- struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
- enum port port;
-
- if (!(intel_crtc->mode_flags &
- (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0)))
- return false;
-
- /* for dual link cases we consider TE from slave */
- if (intel_crtc->mode_flags & I915_MODE_FLAG_DSI_USE_TE1)
- port = PORT_B;
- else
- port = PORT_A;
-
- intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT,
- enable ? 0 : DSI_TE_EVENT);
-
- intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
-
- return true;
-}
-
-int bdw_enable_vblank(struct drm_crtc *_crtc)
-{
- struct intel_crtc *crtc = to_intel_crtc(_crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- enum pipe pipe = crtc->pipe;
- unsigned long irqflags;
-
- if (gen11_dsi_configure_te(crtc, true))
- return 0;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-
- /* Even if there is no DMC, frame counter can get stuck when
- * PSR is active as no frames are generated, so check only for PSR.
- */
- if (HAS_PSR(dev_priv))
- drm_crtc_vblank_restore(&crtc->base);
-
- return 0;
-}
-
-/* Called from drm generic code, passed 'crtc' which
- * we use as a pipe index
- */
-void i8xx_disable_vblank(struct drm_crtc *crtc)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
- enum pipe pipe = to_intel_crtc(crtc)->pipe;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-}
-
-void i915gm_disable_vblank(struct drm_crtc *crtc)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
-
- i8xx_disable_vblank(crtc);
-
- if (--dev_priv->vblank_enabled == 0)
- intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
-}
-
-void i965_disable_vblank(struct drm_crtc *crtc)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
- enum pipe pipe = to_intel_crtc(crtc)->pipe;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- i915_disable_pipestat(dev_priv, pipe,
- PIPE_START_VBLANK_INTERRUPT_STATUS);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-}
-
-void ilk_disable_vblank(struct drm_crtc *crtc)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
- enum pipe pipe = to_intel_crtc(crtc)->pipe;
- unsigned long irqflags;
- u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
- DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
-
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- ilk_disable_display_irq(dev_priv, bit);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-}
-
-void bdw_disable_vblank(struct drm_crtc *_crtc)
-{
- struct intel_crtc *crtc = to_intel_crtc(_crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- enum pipe pipe = crtc->pipe;
- unsigned long irqflags;
-
- if (gen11_dsi_configure_te(crtc, false))
- return;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-}
-
static void ibx_irq_reset(struct drm_i915_private *dev_priv)
{
struct intel_uncore *uncore = &dev_priv->uncore;
@@ -2584,55 +672,6 @@ static void ibx_irq_reset(struct drm_i915_private *dev_priv)
intel_uncore_write(&dev_priv->uncore, SERR_INT, 0xffffffff);
}
-static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
-{
- struct intel_uncore *uncore = &dev_priv->uncore;
-
- if (IS_CHERRYVIEW(dev_priv))
- intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV);
- else
- intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV);
-
- i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0);
- intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
-
- i9xx_pipestat_irq_reset(dev_priv);
-
- GEN3_IRQ_RESET(uncore, VLV_);
- dev_priv->irq_mask = ~0u;
-}
-
-static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
-{
- struct intel_uncore *uncore = &dev_priv->uncore;
-
- u32 pipestat_mask;
- u32 enable_mask;
- enum pipe pipe;
-
- pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS;
-
- i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
- for_each_pipe(dev_priv, pipe)
- i915_enable_pipestat(dev_priv, pipe, pipestat_mask);
-
- enable_mask = I915_DISPLAY_PORT_INTERRUPT |
- I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
- I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
- I915_LPE_PIPE_A_INTERRUPT |
- I915_LPE_PIPE_B_INTERRUPT;
-
- if (IS_CHERRYVIEW(dev_priv))
- enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT |
- I915_LPE_PIPE_C_INTERRUPT;
-
- drm_WARN_ON(&dev_priv->drm, dev_priv->irq_mask != ~0u);
-
- dev_priv->irq_mask = ~enable_mask;
-
- GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask);
-}
-
/* drm_dma.h hooks
*/
static void ilk_irq_reset(struct drm_i915_private *dev_priv)
@@ -2668,26 +707,6 @@ static void valleyview_irq_reset(struct drm_i915_private *dev_priv)
spin_unlock_irq(&dev_priv->irq_lock);
}
-static void gen8_display_irq_reset(struct drm_i915_private *dev_priv)
-{
- struct intel_uncore *uncore = &dev_priv->uncore;
- enum pipe pipe;
-
- if (!HAS_DISPLAY(dev_priv))
- return;
-
- intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
- intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
-
- for_each_pipe(dev_priv, pipe)
- if (intel_display_power_is_enabled(dev_priv,
- POWER_DOMAIN_PIPE(pipe)))
- GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
-
- GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
- GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
-}
-
static void gen8_irq_reset(struct drm_i915_private *dev_priv)
{
struct intel_uncore *uncore = &dev_priv->uncore;
@@ -2703,49 +722,6 @@ static void gen8_irq_reset(struct drm_i915_private *dev_priv)
}
-static void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
-{
- struct intel_uncore *uncore = &dev_priv->uncore;
- enum pipe pipe;
- u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
- BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
-
- if (!HAS_DISPLAY(dev_priv))
- return;
-
- intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0);
-
- if (DISPLAY_VER(dev_priv) >= 12) {
- enum transcoder trans;
-
- for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
- enum intel_display_power_domain domain;
-
- domain = POWER_DOMAIN_TRANSCODER(trans);
- if (!intel_display_power_is_enabled(dev_priv, domain))
- continue;
-
- intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff);
- intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff);
- }
- } else {
- intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
- intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
- }
-
- for_each_pipe(dev_priv, pipe)
- if (intel_display_power_is_enabled(dev_priv,
- POWER_DOMAIN_PIPE(pipe)))
- GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
-
- GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
- GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
- GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_);
-
- if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
- GEN3_IRQ_RESET(uncore, SDE);
-}
-
static void gen11_irq_reset(struct drm_i915_private *dev_priv)
{
struct intel_gt *gt = to_gt(dev_priv);
@@ -2762,64 +738,21 @@ static void gen11_irq_reset(struct drm_i915_private *dev_priv)
static void dg1_irq_reset(struct drm_i915_private *dev_priv)
{
- struct intel_gt *gt = to_gt(dev_priv);
- struct intel_uncore *uncore = gt->uncore;
+ struct intel_uncore *uncore = &dev_priv->uncore;
+ struct intel_gt *gt;
+ unsigned int i;
dg1_master_intr_disable(dev_priv->uncore.regs);
- gen11_gt_irq_reset(gt);
+ for_each_gt(gt, dev_priv, i)
+ gen11_gt_irq_reset(gt);
+
gen11_display_irq_reset(dev_priv);
GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_);
GEN3_IRQ_RESET(uncore, GEN8_PCU_);
}
-void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
- u8 pipe_mask)
-{
- struct intel_uncore *uncore = &dev_priv->uncore;
- u32 extra_ier = GEN8_PIPE_VBLANK |
- gen8_de_pipe_underrun_mask(dev_priv) |
- gen8_de_pipe_flip_done_mask(dev_priv);
- enum pipe pipe;
-
- spin_lock_irq(&dev_priv->irq_lock);
-
- if (!intel_irqs_enabled(dev_priv)) {
- spin_unlock_irq(&dev_priv->irq_lock);
- return;
- }
-
- for_each_pipe_masked(dev_priv, pipe, pipe_mask)
- GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
- dev_priv->de_irq_mask[pipe],
- ~dev_priv->de_irq_mask[pipe] | extra_ier);
-
- spin_unlock_irq(&dev_priv->irq_lock);
-}
-
-void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
- u8 pipe_mask)
-{
- struct intel_uncore *uncore = &dev_priv->uncore;
- enum pipe pipe;
-
- spin_lock_irq(&dev_priv->irq_lock);
-
- if (!intel_irqs_enabled(dev_priv)) {
- spin_unlock_irq(&dev_priv->irq_lock);
- return;
- }
-
- for_each_pipe_masked(dev_priv, pipe, pipe_mask)
- GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
-
- spin_unlock_irq(&dev_priv->irq_lock);
-
- /* make sure we're done processing display irqs */
- intel_synchronize_irq(dev_priv);
-}
-
static void cherryview_irq_reset(struct drm_i915_private *dev_priv)
{
struct intel_uncore *uncore = &dev_priv->uncore;
@@ -2837,377 +770,6 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv)
spin_unlock_irq(&dev_priv->irq_lock);
}
-static u32 ibx_hotplug_enables(struct intel_encoder *encoder)
-{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
-
- switch (encoder->hpd_pin) {
- case HPD_PORT_A:
- /*
- * When CPU and PCH are on the same package, port A
- * HPD must be enabled in both north and south.
- */
- return HAS_PCH_LPT_LP(i915) ?
- PORTA_HOTPLUG_ENABLE : 0;
- case HPD_PORT_B:
- return PORTB_HOTPLUG_ENABLE |
- PORTB_PULSE_DURATION_2ms;
- case HPD_PORT_C:
- return PORTC_HOTPLUG_ENABLE |
- PORTC_PULSE_DURATION_2ms;
- case HPD_PORT_D:
- return PORTD_HOTPLUG_ENABLE |
- PORTD_PULSE_DURATION_2ms;
- default:
- return 0;
- }
-}
-
-static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
-{
- /*
- * Enable digital hotplug on the PCH, and configure the DP short pulse
- * duration to 2ms (which is the minimum in the Display Port spec).
- * The pulse duration bits are reserved on LPT+.
- */
- intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
- PORTA_HOTPLUG_ENABLE |
- PORTB_HOTPLUG_ENABLE |
- PORTC_HOTPLUG_ENABLE |
- PORTD_HOTPLUG_ENABLE |
- PORTB_PULSE_DURATION_MASK |
- PORTC_PULSE_DURATION_MASK |
- PORTD_PULSE_DURATION_MASK,
- intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables));
-}
-
-static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
-{
- u32 hotplug_irqs, enabled_irqs;
-
- enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
- hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
-
- ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
-
- ibx_hpd_detection_setup(dev_priv);
-}
-
-static u32 icp_ddi_hotplug_enables(struct intel_encoder *encoder)
-{
- switch (encoder->hpd_pin) {
- case HPD_PORT_A:
- case HPD_PORT_B:
- case HPD_PORT_C:
- case HPD_PORT_D:
- return SHOTPLUG_CTL_DDI_HPD_ENABLE(encoder->hpd_pin);
- default:
- return 0;
- }
-}
-
-static u32 icp_tc_hotplug_enables(struct intel_encoder *encoder)
-{
- switch (encoder->hpd_pin) {
- case HPD_PORT_TC1:
- case HPD_PORT_TC2:
- case HPD_PORT_TC3:
- case HPD_PORT_TC4:
- case HPD_PORT_TC5:
- case HPD_PORT_TC6:
- return ICP_TC_HPD_ENABLE(encoder->hpd_pin);
- default:
- return 0;
- }
-}
-
-static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv)
-{
- intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI,
- SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A) |
- SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) |
- SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C) |
- SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_D),
- intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables));
-}
-
-static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
-{
- intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC,
- ICP_TC_HPD_ENABLE(HPD_PORT_TC1) |
- ICP_TC_HPD_ENABLE(HPD_PORT_TC2) |
- ICP_TC_HPD_ENABLE(HPD_PORT_TC3) |
- ICP_TC_HPD_ENABLE(HPD_PORT_TC4) |
- ICP_TC_HPD_ENABLE(HPD_PORT_TC5) |
- ICP_TC_HPD_ENABLE(HPD_PORT_TC6),
- intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables));
-}
-
-static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv)
-{
- u32 hotplug_irqs, enabled_irqs;
-
- enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
- hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
-
- if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP)
- intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
-
- ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
-
- icp_ddi_hpd_detection_setup(dev_priv);
- icp_tc_hpd_detection_setup(dev_priv);
-}
-
-static u32 gen11_hotplug_enables(struct intel_encoder *encoder)
-{
- switch (encoder->hpd_pin) {
- case HPD_PORT_TC1:
- case HPD_PORT_TC2:
- case HPD_PORT_TC3:
- case HPD_PORT_TC4:
- case HPD_PORT_TC5:
- case HPD_PORT_TC6:
- return GEN11_HOTPLUG_CTL_ENABLE(encoder->hpd_pin);
- default:
- return 0;
- }
-}
-
-static void dg1_hpd_invert(struct drm_i915_private *i915)
-{
- u32 val = (INVERT_DDIA_HPD |
- INVERT_DDIB_HPD |
- INVERT_DDIC_HPD |
- INVERT_DDID_HPD);
- intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1, 0, val);
-}
-
-static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv)
-{
- dg1_hpd_invert(dev_priv);
- icp_hpd_irq_setup(dev_priv);
-}
-
-static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
-{
- intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL,
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6),
- intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
-}
-
-static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv)
-{
- intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL,
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) |
- GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6),
- intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
-}
-
-static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
-{
- u32 hotplug_irqs, enabled_irqs;
-
- enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
- hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
-
- intel_uncore_rmw(&dev_priv->uncore, GEN11_DE_HPD_IMR, hotplug_irqs,
- ~enabled_irqs & hotplug_irqs);
- intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR);
-
- gen11_tc_hpd_detection_setup(dev_priv);
- gen11_tbt_hpd_detection_setup(dev_priv);
-
- if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
- icp_hpd_irq_setup(dev_priv);
-}
-
-static u32 spt_hotplug_enables(struct intel_encoder *encoder)
-{
- switch (encoder->hpd_pin) {
- case HPD_PORT_A:
- return PORTA_HOTPLUG_ENABLE;
- case HPD_PORT_B:
- return PORTB_HOTPLUG_ENABLE;
- case HPD_PORT_C:
- return PORTC_HOTPLUG_ENABLE;
- case HPD_PORT_D:
- return PORTD_HOTPLUG_ENABLE;
- default:
- return 0;
- }
-}
-
-static u32 spt_hotplug2_enables(struct intel_encoder *encoder)
-{
- switch (encoder->hpd_pin) {
- case HPD_PORT_E:
- return PORTE_HOTPLUG_ENABLE;
- default:
- return 0;
- }
-}
-
-static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
-{
- /* Display WA #1179 WaHardHangonHotPlug: cnp */
- if (HAS_PCH_CNP(dev_priv)) {
- intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK,
- CHASSIS_CLK_REQ_DURATION(0xf));
- }
-
- /* Enable digital hotplug on the PCH */
- intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
- PORTA_HOTPLUG_ENABLE |
- PORTB_HOTPLUG_ENABLE |
- PORTC_HOTPLUG_ENABLE |
- PORTD_HOTPLUG_ENABLE,
- intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables));
-
- intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, PORTE_HOTPLUG_ENABLE,
- intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables));
-}
-
-static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
-{
- u32 hotplug_irqs, enabled_irqs;
-
- if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
- intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
-
- enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
- hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
-
- ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
-
- spt_hpd_detection_setup(dev_priv);
-}
-
-static u32 ilk_hotplug_enables(struct intel_encoder *encoder)
-{
- switch (encoder->hpd_pin) {
- case HPD_PORT_A:
- return DIGITAL_PORTA_HOTPLUG_ENABLE |
- DIGITAL_PORTA_PULSE_DURATION_2ms;
- default:
- return 0;
- }
-}
-
-static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
-{
- /*
- * Enable digital hotplug on the CPU, and configure the DP short pulse
- * duration to 2ms (which is the minimum in the Display Port spec)
- * The pulse duration bits are reserved on HSW+.
- */
- intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
- DIGITAL_PORTA_HOTPLUG_ENABLE | DIGITAL_PORTA_PULSE_DURATION_MASK,
- intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables));
-}
-
-static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
-{
- u32 hotplug_irqs, enabled_irqs;
-
- enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
- hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
-
- if (DISPLAY_VER(dev_priv) >= 8)
- bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
- else
- ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
-
- ilk_hpd_detection_setup(dev_priv);
-
- ibx_hpd_irq_setup(dev_priv);
-}
-
-static u32 bxt_hotplug_enables(struct intel_encoder *encoder)
-{
- u32 hotplug;
-
- switch (encoder->hpd_pin) {
- case HPD_PORT_A:
- hotplug = PORTA_HOTPLUG_ENABLE;
- if (intel_bios_encoder_hpd_invert(encoder->devdata))
- hotplug |= BXT_DDIA_HPD_INVERT;
- return hotplug;
- case HPD_PORT_B:
- hotplug = PORTB_HOTPLUG_ENABLE;
- if (intel_bios_encoder_hpd_invert(encoder->devdata))
- hotplug |= BXT_DDIB_HPD_INVERT;
- return hotplug;
- case HPD_PORT_C:
- hotplug = PORTC_HOTPLUG_ENABLE;
- if (intel_bios_encoder_hpd_invert(encoder->devdata))
- hotplug |= BXT_DDIC_HPD_INVERT;
- return hotplug;
- default:
- return 0;
- }
-}
-
-static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv)
-{
- intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
- PORTA_HOTPLUG_ENABLE |
- PORTB_HOTPLUG_ENABLE |
- PORTC_HOTPLUG_ENABLE |
- BXT_DDI_HPD_INVERT_MASK,
- intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables));
-}
-
-static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
-{
- u32 hotplug_irqs, enabled_irqs;
-
- enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
- hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
-
- bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
-
- bxt_hpd_detection_setup(dev_priv);
-}
-
-/*
- * SDEIER is also touched by the interrupt handler to work around missed PCH
- * interrupts. Hence we can't update it after the interrupt handler is enabled -
- * instead we unconditionally enable all PCH interrupt sources here, but then
- * only unmask them as needed with SDEIMR.
- *
- * Note that we currently do this after installing the interrupt handler,
- * but before we enable the master interrupt. That should be sufficient
- * to avoid races with the irq handler, assuming we have MSI. Shared legacy
- * interrupts could still race.
- */
-static void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
-{
- struct intel_uncore *uncore = &dev_priv->uncore;
- u32 mask;
-
- if (HAS_PCH_NOP(dev_priv))
- return;
-
- if (HAS_PCH_IBX(dev_priv))
- mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
- else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
- mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
- else
- mask = SDE_GMBUS_CPT;
-
- GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
-}
-
static void ilk_irq_postinstall(struct drm_i915_private *dev_priv)
{
struct intel_uncore *uncore = &dev_priv->uncore;
@@ -3251,35 +813,6 @@ static void ilk_irq_postinstall(struct drm_i915_private *dev_priv)
display_mask | extra_mask);
}
-void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
-{
- lockdep_assert_held(&dev_priv->irq_lock);
-
- if (dev_priv->display_irqs_enabled)
- return;
-
- dev_priv->display_irqs_enabled = true;
-
- if (intel_irqs_enabled(dev_priv)) {
- vlv_display_irq_reset(dev_priv);
- vlv_display_irq_postinstall(dev_priv);
- }
-}
-
-void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
-{
- lockdep_assert_held(&dev_priv->irq_lock);
-
- if (!dev_priv->display_irqs_enabled)
- return;
-
- dev_priv->display_irqs_enabled = false;
-
- if (intel_irqs_enabled(dev_priv))
- vlv_display_irq_reset(dev_priv);
-}
-
-
static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv)
{
gen5_gt_irq_postinstall(to_gt(dev_priv));
@@ -3293,94 +826,6 @@ static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv)
intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER);
}
-static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
-{
- struct intel_uncore *uncore = &dev_priv->uncore;
-
- u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) |
- GEN8_PIPE_CDCLK_CRC_DONE;
- u32 de_pipe_enables;
- u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
- u32 de_port_enables;
- u32 de_misc_masked = GEN8_DE_EDP_PSR;
- u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
- BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
- enum pipe pipe;
-
- if (!HAS_DISPLAY(dev_priv))
- return;
-
- if (DISPLAY_VER(dev_priv) <= 10)
- de_misc_masked |= GEN8_DE_MISC_GSE;
-
- if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
- de_port_masked |= BXT_DE_PORT_GMBUS;
-
- if (DISPLAY_VER(dev_priv) >= 11) {
- enum port port;
-
- if (intel_bios_is_dsi_present(dev_priv, &port))
- de_port_masked |= DSI0_TE | DSI1_TE;
- }
-
- de_pipe_enables = de_pipe_masked |
- GEN8_PIPE_VBLANK |
- gen8_de_pipe_underrun_mask(dev_priv) |
- gen8_de_pipe_flip_done_mask(dev_priv);
-
- de_port_enables = de_port_masked;
- if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
- de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK;
- else if (IS_BROADWELL(dev_priv))
- de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK;
-
- if (DISPLAY_VER(dev_priv) >= 12) {
- enum transcoder trans;
-
- for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
- enum intel_display_power_domain domain;
-
- domain = POWER_DOMAIN_TRANSCODER(trans);
- if (!intel_display_power_is_enabled(dev_priv, domain))
- continue;
-
- gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans));
- }
- } else {
- gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
- }
-
- for_each_pipe(dev_priv, pipe) {
- dev_priv->de_irq_mask[pipe] = ~de_pipe_masked;
-
- if (intel_display_power_is_enabled(dev_priv,
- POWER_DOMAIN_PIPE(pipe)))
- GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
- dev_priv->de_irq_mask[pipe],
- de_pipe_enables);
- }
-
- GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
- GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
-
- if (DISPLAY_VER(dev_priv) >= 11) {
- u32 de_hpd_masked = 0;
- u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK |
- GEN11_DE_TBT_HOTPLUG_MASK;
-
- GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked,
- de_hpd_enables);
- }
-}
-
-static void icp_irq_postinstall(struct drm_i915_private *dev_priv)
-{
- struct intel_uncore *uncore = &dev_priv->uncore;
- u32 mask = SDE_GMBUS_ICP;
-
- GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
-}
-
static void gen8_irq_postinstall(struct drm_i915_private *dev_priv)
{
if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
@@ -3394,17 +839,6 @@ static void gen8_irq_postinstall(struct drm_i915_private *dev_priv)
gen8_master_intr_enable(dev_priv->uncore.regs);
}
-static void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv)
-{
- if (!HAS_DISPLAY(dev_priv))
- return;
-
- gen8_de_irq_postinstall(dev_priv);
-
- intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
- GEN11_DISPLAY_IRQ_ENABLE);
-}
-
static void gen11_irq_postinstall(struct drm_i915_private *dev_priv)
{
struct intel_gt *gt = to_gt(dev_priv);
@@ -3425,16 +859,22 @@ static void gen11_irq_postinstall(struct drm_i915_private *dev_priv)
static void dg1_irq_postinstall(struct drm_i915_private *dev_priv)
{
- struct intel_gt *gt = to_gt(dev_priv);
- struct intel_uncore *uncore = gt->uncore;
+ struct intel_uncore *uncore = &dev_priv->uncore;
u32 gu_misc_masked = GEN11_GU_MISC_GSE;
+ struct intel_gt *gt;
+ unsigned int i;
- gen11_gt_irq_postinstall(gt);
+ for_each_gt(gt, dev_priv, i)
+ gen11_gt_irq_postinstall(gt);
GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
if (HAS_DISPLAY(dev_priv)) {
- icp_irq_postinstall(dev_priv);
+ if (DISPLAY_VER(dev_priv) >= 14)
+ mtp_irq_postinstall(dev_priv);
+ else
+ icp_irq_postinstall(dev_priv);
+
gen8_de_irq_postinstall(dev_priv);
intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
GEN11_DISPLAY_IRQ_ENABLE);
@@ -3826,31 +1266,6 @@ static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
i915_enable_asle_pipestat(dev_priv);
}
-static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv)
-{
- u32 hotplug_en;
-
- lockdep_assert_held(&dev_priv->irq_lock);
-
- /* Note HDMI and DP share hotplug bits */
- /* enable bits are the same for all generations */
- hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915);
- /* Programming the CRT detection parameters tends
- to generate a spurious hotplug event about three
- seconds later. So just do it once.
- */
- if (IS_G4X(dev_priv))
- hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
- hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-
- /* Ignore TV since it's buggy */
- i915_hotplug_interrupt_update_locked(dev_priv,
- HOTPLUG_INT_EN_MASK |
- CRT_HOTPLUG_VOLTAGE_COMPARE_MASK |
- CRT_HOTPLUG_ACTIVATION_PERIOD_64,
- hotplug_en);
-}
-
static irqreturn_t i965_irq_handler(int irq, void *arg)
{
struct drm_i915_private *dev_priv = arg;
@@ -3910,30 +1325,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
return ret;
}
-struct intel_hotplug_funcs {
- void (*hpd_irq_setup)(struct drm_i915_private *i915);
-};
-
-#define HPD_FUNCS(platform) \
-static const struct intel_hotplug_funcs platform##_hpd_funcs = { \
- .hpd_irq_setup = platform##_hpd_irq_setup, \
-}
-
-HPD_FUNCS(i915);
-HPD_FUNCS(dg1);
-HPD_FUNCS(gen11);
-HPD_FUNCS(bxt);
-HPD_FUNCS(icp);
-HPD_FUNCS(spt);
-HPD_FUNCS(ilk);
-#undef HPD_FUNCS
-
-void intel_hpd_irq_setup(struct drm_i915_private *i915)
-{
- if (i915->display_irqs_enabled && i915->display.funcs.hotplug)
- i915->display.funcs.hotplug->hpd_irq_setup(i915);
-}
-
/**
* intel_irq_init - initializes irq support
* @dev_priv: i915 device instance
@@ -3956,10 +1347,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
- intel_hpd_init_pins(dev_priv);
-
- intel_hpd_init_early(dev_priv);
-
dev_priv->drm.vblank_disable_immediate = true;
/* Most platforms treat the display irq block as an always-on
@@ -3972,25 +1359,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
dev_priv->display_irqs_enabled = false;
- if (HAS_GMCH(dev_priv)) {
- if (I915_HAS_HOTPLUG(dev_priv))
- dev_priv->display.funcs.hotplug = &i915_hpd_funcs;
- } else {
- if (HAS_PCH_DG2(dev_priv))
- dev_priv->display.funcs.hotplug = &icp_hpd_funcs;
- else if (HAS_PCH_DG1(dev_priv))
- dev_priv->display.funcs.hotplug = &dg1_hpd_funcs;
- else if (DISPLAY_VER(dev_priv) >= 11)
- dev_priv->display.funcs.hotplug = &gen11_hpd_funcs;
- else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
- dev_priv->display.funcs.hotplug = &bxt_hpd_funcs;
- else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
- dev_priv->display.funcs.hotplug = &icp_hpd_funcs;
- else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
- dev_priv->display.funcs.hotplug = &spt_hpd_funcs;
- else
- dev_priv->display.funcs.hotplug = &ilk_hpd_funcs;
- }
+ intel_hotplug_irq_init(dev_priv);
}
/**
@@ -4135,7 +1504,7 @@ void intel_irq_uninstall(struct drm_i915_private *dev_priv)
/*
* FIXME we can get called twice during driver probe
* error handling as well as during driver remove due to
- * intel_modeset_driver_remove() calling us out of sequence.
+ * intel_display_driver_remove() calling us out of sequence.
* Would be nice if it didn't do that...
*/
if (!dev_priv->irq_enabled)
diff --git a/drivers/gpu/drm/i915/i915_irq.h b/drivers/gpu/drm/i915/i915_irq.h
index 03ee4c8b1ed3..e665a1b007dc 100644
--- a/drivers/gpu/drm/i915/i915_irq.h
+++ b/drivers/gpu/drm/i915/i915_irq.h
@@ -9,7 +9,7 @@
#include <linux/ktime.h>
#include <linux/types.h>
-#include "i915_reg.h"
+#include "i915_reg_defs.h"
enum pipe;
struct drm_crtc;
@@ -17,6 +17,7 @@ struct drm_device;
struct drm_display_mode;
struct drm_i915_private;
struct intel_crtc;
+struct intel_encoder;
struct intel_uncore;
void intel_irq_init(struct drm_i915_private *dev_priv);
@@ -24,33 +25,6 @@ void intel_irq_fini(struct drm_i915_private *dev_priv);
int intel_irq_install(struct drm_i915_private *dev_priv);
void intel_irq_uninstall(struct drm_i915_private *dev_priv);
-u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv,
- enum pipe pipe);
-void
-i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
- u32 status_mask);
-
-void
-i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
- u32 status_mask);
-
-void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv);
-void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv);
-
-void intel_hpd_irq_setup(struct drm_i915_private *i915);
-void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
- u32 mask,
- u32 bits);
-
-void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits);
-void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits);
-
-void bdw_enable_pipe_irq(struct drm_i915_private *i915, enum pipe pipe, u32 bits);
-void bdw_disable_pipe_irq(struct drm_i915_private *i915, enum pipe pipe, u32 bits);
-
-void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits);
-void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits);
-
void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, u32 mask);
void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, u32 mask);
void gen11_reset_rps_interrupts(struct drm_i915_private *dev_priv);
@@ -66,23 +40,7 @@ bool intel_irqs_enabled(struct drm_i915_private *dev_priv);
void intel_synchronize_irq(struct drm_i915_private *i915);
void intel_synchronize_hardirq(struct drm_i915_private *i915);
-void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
- u8 pipe_mask);
-void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
- u8 pipe_mask);
-u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv);
-
-
-int i8xx_enable_vblank(struct drm_crtc *crtc);
-int i915gm_enable_vblank(struct drm_crtc *crtc);
-int i965_enable_vblank(struct drm_crtc *crtc);
-int ilk_enable_vblank(struct drm_crtc *crtc);
-int bdw_enable_vblank(struct drm_crtc *crtc);
-void i8xx_disable_vblank(struct drm_crtc *crtc);
-void i915gm_disable_vblank(struct drm_crtc *crtc);
-void i965_disable_vblank(struct drm_crtc *crtc);
-void ilk_disable_vblank(struct drm_crtc *crtc);
-void bdw_disable_vblank(struct drm_crtc *crtc);
+void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg);
void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr,
i915_reg_t iir, i915_reg_t ier);
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index edcfb5fe20b2..3d7a5db9833b 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -27,8 +27,10 @@
#include <drm/i915_pciids.h>
#include "display/intel_display.h"
+#include "display/intel_display_driver.h"
#include "gt/intel_gt_regs.h"
#include "gt/intel_sa_media.h"
+#include "gem/i915_gem_object_types.h"
#include "i915_driver.h"
#include "i915_drv.h"
@@ -36,131 +38,44 @@
#include "i915_reg.h"
#include "intel_pci_config.h"
+__diag_push();
+__diag_ignore_all("-Woverride-init", "Allow overriding inherited members");
+
#define PLATFORM(x) .platform = (x)
#define GEN(x) \
.__runtime.graphics.ip.ver = (x), \
- .__runtime.media.ip.ver = (x), \
- .__runtime.display.ip.ver = (x)
-
-#define NO_DISPLAY .__runtime.pipe_mask = 0
-
-#define I845_PIPE_OFFSETS \
- .display.pipe_offsets = { \
- [TRANSCODER_A] = PIPE_A_OFFSET, \
- }, \
- .display.trans_offsets = { \
- [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
- }
-
-#define I9XX_PIPE_OFFSETS \
- .display.pipe_offsets = { \
- [TRANSCODER_A] = PIPE_A_OFFSET, \
- [TRANSCODER_B] = PIPE_B_OFFSET, \
- }, \
- .display.trans_offsets = { \
- [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
- [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
- }
-
-#define IVB_PIPE_OFFSETS \
- .display.pipe_offsets = { \
- [TRANSCODER_A] = PIPE_A_OFFSET, \
- [TRANSCODER_B] = PIPE_B_OFFSET, \
- [TRANSCODER_C] = PIPE_C_OFFSET, \
- }, \
- .display.trans_offsets = { \
- [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
- [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
- [TRANSCODER_C] = TRANSCODER_C_OFFSET, \
- }
-
-#define HSW_PIPE_OFFSETS \
- .display.pipe_offsets = { \
- [TRANSCODER_A] = PIPE_A_OFFSET, \
- [TRANSCODER_B] = PIPE_B_OFFSET, \
- [TRANSCODER_C] = PIPE_C_OFFSET, \
- [TRANSCODER_EDP] = PIPE_EDP_OFFSET, \
- }, \
- .display.trans_offsets = { \
- [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
- [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
- [TRANSCODER_C] = TRANSCODER_C_OFFSET, \
- [TRANSCODER_EDP] = TRANSCODER_EDP_OFFSET, \
- }
-
-#define CHV_PIPE_OFFSETS \
- .display.pipe_offsets = { \
- [TRANSCODER_A] = PIPE_A_OFFSET, \
- [TRANSCODER_B] = PIPE_B_OFFSET, \
- [TRANSCODER_C] = CHV_PIPE_C_OFFSET, \
- }, \
- .display.trans_offsets = { \
- [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
- [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
- [TRANSCODER_C] = CHV_TRANSCODER_C_OFFSET, \
- }
-
-#define I845_CURSOR_OFFSETS \
- .display.cursor_offsets = { \
- [PIPE_A] = CURSOR_A_OFFSET, \
- }
-
-#define I9XX_CURSOR_OFFSETS \
- .display.cursor_offsets = { \
- [PIPE_A] = CURSOR_A_OFFSET, \
- [PIPE_B] = CURSOR_B_OFFSET, \
+ .__runtime.media.ip.ver = (x)
+
+#define LEGACY_CACHELEVEL \
+ .cachelevel_to_pat = { \
+ [I915_CACHE_NONE] = 0, \
+ [I915_CACHE_LLC] = 1, \
+ [I915_CACHE_L3_LLC] = 2, \
+ [I915_CACHE_WT] = 3, \
}
-#define CHV_CURSOR_OFFSETS \
- .display.cursor_offsets = { \
- [PIPE_A] = CURSOR_A_OFFSET, \
- [PIPE_B] = CURSOR_B_OFFSET, \
- [PIPE_C] = CHV_CURSOR_C_OFFSET, \
+#define TGL_CACHELEVEL \
+ .cachelevel_to_pat = { \
+ [I915_CACHE_NONE] = 3, \
+ [I915_CACHE_LLC] = 0, \
+ [I915_CACHE_L3_LLC] = 0, \
+ [I915_CACHE_WT] = 2, \
}
-#define IVB_CURSOR_OFFSETS \
- .display.cursor_offsets = { \
- [PIPE_A] = CURSOR_A_OFFSET, \
- [PIPE_B] = IVB_CURSOR_B_OFFSET, \
- [PIPE_C] = IVB_CURSOR_C_OFFSET, \
+#define PVC_CACHELEVEL \
+ .cachelevel_to_pat = { \
+ [I915_CACHE_NONE] = 0, \
+ [I915_CACHE_LLC] = 3, \
+ [I915_CACHE_L3_LLC] = 3, \
+ [I915_CACHE_WT] = 2, \
}
-#define TGL_CURSOR_OFFSETS \
- .display.cursor_offsets = { \
- [PIPE_A] = CURSOR_A_OFFSET, \
- [PIPE_B] = IVB_CURSOR_B_OFFSET, \
- [PIPE_C] = IVB_CURSOR_C_OFFSET, \
- [PIPE_D] = TGL_CURSOR_D_OFFSET, \
- }
-
-#define I845_COLORS \
- .display.color = { .gamma_lut_size = 256 }
-#define I9XX_COLORS \
- .display.color = { .gamma_lut_size = 129, \
- .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \
- }
-#define ILK_COLORS \
- .display.color = { .gamma_lut_size = 1024 }
-#define IVB_COLORS \
- .display.color = { .degamma_lut_size = 1024, .gamma_lut_size = 1024 }
-#define CHV_COLORS \
- .display.color = { \
- .degamma_lut_size = 65, .gamma_lut_size = 257, \
- .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \
- .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \
- }
-#define GLK_COLORS \
- .display.color = { \
- .degamma_lut_size = 33, .gamma_lut_size = 1024, \
- .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \
- DRM_COLOR_LUT_EQUAL_CHANNELS, \
- }
-#define ICL_COLORS \
- .display.color = { \
- .degamma_lut_size = 33, .gamma_lut_size = 262145, \
- .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \
- DRM_COLOR_LUT_EQUAL_CHANNELS, \
- .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \
+#define MTL_CACHELEVEL \
+ .cachelevel_to_pat = { \
+ [I915_CACHE_NONE] = 2, \
+ [I915_CACHE_LLC] = 3, \
+ [I915_CACHE_L3_LLC] = 3, \
+ [I915_CACHE_WT] = 1, \
}
/* Keep in gen based order, and chronological order within a gen */
@@ -174,12 +89,6 @@
#define I830_FEATURES \
GEN(2), \
.is_mobile = 1, \
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \
- .display.has_overlay = 1, \
- .display.cursor_needs_physical = 1, \
- .display.overlay_needs_physical = 1, \
- .display.has_gmch = 1, \
.gpu_reset_clobbers_display = true, \
.has_3d_pipeline = 1, \
.hws_needs_physical = 1, \
@@ -188,19 +97,13 @@
.has_snoop = true, \
.has_coherent_ggtt = false, \
.dma_mask_size = 32, \
- I9XX_PIPE_OFFSETS, \
- I9XX_CURSOR_OFFSETS, \
- I9XX_COLORS, \
+ .max_pat_index = 3, \
GEN_DEFAULT_PAGE_SIZES, \
- GEN_DEFAULT_REGIONS
+ GEN_DEFAULT_REGIONS, \
+ LEGACY_CACHELEVEL
#define I845_FEATURES \
GEN(2), \
- .__runtime.pipe_mask = BIT(PIPE_A), \
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A), \
- .display.has_overlay = 1, \
- .display.overlay_needs_physical = 1, \
- .display.has_gmch = 1, \
.has_3d_pipeline = 1, \
.gpu_reset_clobbers_display = true, \
.hws_needs_physical = 1, \
@@ -209,11 +112,10 @@
.has_snoop = true, \
.has_coherent_ggtt = false, \
.dma_mask_size = 32, \
- I845_PIPE_OFFSETS, \
- I845_CURSOR_OFFSETS, \
- I845_COLORS, \
+ .max_pat_index = 3, \
GEN_DEFAULT_PAGE_SIZES, \
- GEN_DEFAULT_REGIONS
+ GEN_DEFAULT_REGIONS, \
+ LEGACY_CACHELEVEL
static const struct intel_device_info i830_info = {
I830_FEATURES,
@@ -228,39 +130,30 @@ static const struct intel_device_info i845g_info = {
static const struct intel_device_info i85x_info = {
I830_FEATURES,
PLATFORM(INTEL_I85X),
- .__runtime.fbc_mask = BIT(INTEL_FBC_A),
};
static const struct intel_device_info i865g_info = {
I845_FEATURES,
PLATFORM(INTEL_I865G),
- .__runtime.fbc_mask = BIT(INTEL_FBC_A),
};
#define GEN3_FEATURES \
GEN(3), \
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \
- .display.has_gmch = 1, \
.gpu_reset_clobbers_display = true, \
.__runtime.platform_engine_mask = BIT(RCS0), \
.has_3d_pipeline = 1, \
.has_snoop = true, \
.has_coherent_ggtt = true, \
.dma_mask_size = 32, \
- I9XX_PIPE_OFFSETS, \
- I9XX_CURSOR_OFFSETS, \
- I9XX_COLORS, \
+ .max_pat_index = 3, \
GEN_DEFAULT_PAGE_SIZES, \
- GEN_DEFAULT_REGIONS
+ GEN_DEFAULT_REGIONS, \
+ LEGACY_CACHELEVEL
static const struct intel_device_info i915g_info = {
GEN3_FEATURES,
PLATFORM(INTEL_I915G),
.has_coherent_ggtt = false,
- .display.cursor_needs_physical = 1,
- .display.has_overlay = 1,
- .display.overlay_needs_physical = 1,
.hws_needs_physical = 1,
.unfenced_needs_alignment = 1,
};
@@ -269,11 +162,6 @@ static const struct intel_device_info i915gm_info = {
GEN3_FEATURES,
PLATFORM(INTEL_I915GM),
.is_mobile = 1,
- .display.cursor_needs_physical = 1,
- .display.has_overlay = 1,
- .display.overlay_needs_physical = 1,
- .display.supports_tv = 1,
- .__runtime.fbc_mask = BIT(INTEL_FBC_A),
.hws_needs_physical = 1,
.unfenced_needs_alignment = 1,
};
@@ -281,10 +169,6 @@ static const struct intel_device_info i915gm_info = {
static const struct intel_device_info i945g_info = {
GEN3_FEATURES,
PLATFORM(INTEL_I945G),
- .display.has_hotplug = 1,
- .display.cursor_needs_physical = 1,
- .display.has_overlay = 1,
- .display.overlay_needs_physical = 1,
.hws_needs_physical = 1,
.unfenced_needs_alignment = 1,
};
@@ -293,12 +177,6 @@ static const struct intel_device_info i945gm_info = {
GEN3_FEATURES,
PLATFORM(INTEL_I945GM),
.is_mobile = 1,
- .display.has_hotplug = 1,
- .display.cursor_needs_physical = 1,
- .display.has_overlay = 1,
- .display.overlay_needs_physical = 1,
- .display.supports_tv = 1,
- .__runtime.fbc_mask = BIT(INTEL_FBC_A),
.hws_needs_physical = 1,
.unfenced_needs_alignment = 1,
};
@@ -306,16 +184,12 @@ static const struct intel_device_info i945gm_info = {
static const struct intel_device_info g33_info = {
GEN3_FEATURES,
PLATFORM(INTEL_G33),
- .display.has_hotplug = 1,
- .display.has_overlay = 1,
.dma_mask_size = 36,
};
static const struct intel_device_info pnv_g_info = {
GEN3_FEATURES,
PLATFORM(INTEL_PINEVIEW),
- .display.has_hotplug = 1,
- .display.has_overlay = 1,
.dma_mask_size = 36,
};
@@ -323,33 +197,25 @@ static const struct intel_device_info pnv_m_info = {
GEN3_FEATURES,
PLATFORM(INTEL_PINEVIEW),
.is_mobile = 1,
- .display.has_hotplug = 1,
- .display.has_overlay = 1,
.dma_mask_size = 36,
};
#define GEN4_FEATURES \
GEN(4), \
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \
- .display.has_hotplug = 1, \
- .display.has_gmch = 1, \
.gpu_reset_clobbers_display = true, \
.__runtime.platform_engine_mask = BIT(RCS0), \
.has_3d_pipeline = 1, \
.has_snoop = true, \
.has_coherent_ggtt = true, \
.dma_mask_size = 36, \
- I9XX_PIPE_OFFSETS, \
- I9XX_CURSOR_OFFSETS, \
- I9XX_COLORS, \
+ .max_pat_index = 3, \
GEN_DEFAULT_PAGE_SIZES, \
- GEN_DEFAULT_REGIONS
+ GEN_DEFAULT_REGIONS, \
+ LEGACY_CACHELEVEL
static const struct intel_device_info i965g_info = {
GEN4_FEATURES,
PLATFORM(INTEL_I965G),
- .display.has_overlay = 1,
.hws_needs_physical = 1,
.has_snoop = false,
};
@@ -358,9 +224,6 @@ static const struct intel_device_info i965gm_info = {
GEN4_FEATURES,
PLATFORM(INTEL_I965GM),
.is_mobile = 1,
- .__runtime.fbc_mask = BIT(INTEL_FBC_A),
- .display.has_overlay = 1,
- .display.supports_tv = 1,
.hws_needs_physical = 1,
.has_snoop = false,
};
@@ -376,17 +239,12 @@ static const struct intel_device_info gm45_info = {
GEN4_FEATURES,
PLATFORM(INTEL_GM45),
.is_mobile = 1,
- .__runtime.fbc_mask = BIT(INTEL_FBC_A),
- .display.supports_tv = 1,
.__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0),
.gpu_reset_clobbers_display = false,
};
#define GEN5_FEATURES \
GEN(5), \
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \
- .display.has_hotplug = 1, \
.__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0), \
.has_3d_pipeline = 1, \
.has_snoop = true, \
@@ -394,11 +252,10 @@ static const struct intel_device_info gm45_info = {
/* ilk does support rc6, but we do not implement [power] contexts */ \
.has_rc6 = 0, \
.dma_mask_size = 36, \
- I9XX_PIPE_OFFSETS, \
- I9XX_CURSOR_OFFSETS, \
- ILK_COLORS, \
+ .max_pat_index = 3, \
GEN_DEFAULT_PAGE_SIZES, \
- GEN_DEFAULT_REGIONS
+ GEN_DEFAULT_REGIONS, \
+ LEGACY_CACHELEVEL
static const struct intel_device_info ilk_d_info = {
GEN5_FEATURES,
@@ -410,15 +267,10 @@ static const struct intel_device_info ilk_m_info = {
PLATFORM(INTEL_IRONLAKE),
.is_mobile = 1,
.has_rps = true,
- .__runtime.fbc_mask = BIT(INTEL_FBC_A),
};
#define GEN6_FEATURES \
GEN(6), \
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \
- .display.has_hotplug = 1, \
- .__runtime.fbc_mask = BIT(INTEL_FBC_A), \
.__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), \
.has_3d_pipeline = 1, \
.has_coherent_ggtt = true, \
@@ -428,13 +280,12 @@ static const struct intel_device_info ilk_m_info = {
.has_rc6p = 0, \
.has_rps = true, \
.dma_mask_size = 40, \
+ .max_pat_index = 3, \
.__runtime.ppgtt_type = INTEL_PPGTT_ALIASING, \
.__runtime.ppgtt_size = 31, \
- I9XX_PIPE_OFFSETS, \
- I9XX_CURSOR_OFFSETS, \
- ILK_COLORS, \
GEN_DEFAULT_PAGE_SIZES, \
- GEN_DEFAULT_REGIONS
+ GEN_DEFAULT_REGIONS, \
+ LEGACY_CACHELEVEL
#define SNB_D_PLATFORM \
GEN6_FEATURES, \
@@ -468,10 +319,6 @@ static const struct intel_device_info snb_m_gt2_info = {
#define GEN7_FEATURES \
GEN(7), \
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), \
- .display.has_hotplug = 1, \
- .__runtime.fbc_mask = BIT(INTEL_FBC_A), \
.__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), \
.has_3d_pipeline = 1, \
.has_coherent_ggtt = true, \
@@ -481,13 +328,12 @@ static const struct intel_device_info snb_m_gt2_info = {
.has_reset_engine = true, \
.has_rps = true, \
.dma_mask_size = 40, \
+ .max_pat_index = 3, \
.__runtime.ppgtt_type = INTEL_PPGTT_ALIASING, \
.__runtime.ppgtt_size = 31, \
- IVB_PIPE_OFFSETS, \
- IVB_CURSOR_OFFSETS, \
- IVB_COLORS, \
GEN_DEFAULT_PAGE_SIZES, \
- GEN_DEFAULT_REGIONS
+ GEN_DEFAULT_REGIONS, \
+ LEGACY_CACHELEVEL
#define IVB_D_PLATFORM \
GEN7_FEATURES, \
@@ -523,7 +369,6 @@ static const struct intel_device_info ivb_m_gt2_info = {
static const struct intel_device_info ivb_q_info = {
GEN7_FEATURES,
PLATFORM(INTEL_IVYBRIDGE),
- NO_DISPLAY,
.gt = 2,
.has_l3_dpf = 1,
};
@@ -532,38 +377,26 @@ static const struct intel_device_info vlv_info = {
PLATFORM(INTEL_VALLEYVIEW),
GEN(7),
.is_lp = 1,
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B),
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B),
.has_runtime_pm = 1,
.has_rc6 = 1,
.has_reset_engine = true,
.has_rps = true,
- .display.has_gmch = 1,
- .display.has_hotplug = 1,
.dma_mask_size = 40,
+ .max_pat_index = 3,
.__runtime.ppgtt_type = INTEL_PPGTT_ALIASING,
.__runtime.ppgtt_size = 31,
.has_snoop = true,
.has_coherent_ggtt = false,
.__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0),
- .display.mmio_offset = VLV_DISPLAY_BASE,
- I9XX_PIPE_OFFSETS,
- I9XX_CURSOR_OFFSETS,
- I9XX_COLORS,
GEN_DEFAULT_PAGE_SIZES,
GEN_DEFAULT_REGIONS,
+ LEGACY_CACHELEVEL,
};
#define G75_FEATURES \
GEN7_FEATURES, \
.__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
- BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP), \
- .display.has_ddi = 1, \
- .display.has_fpga_dbg = 1, \
- .display.has_dp_mst = 1, \
.has_rc6p = 0 /* RC6p removed-by HSW */, \
- HSW_PIPE_OFFSETS, \
.has_runtime_pm = 1
#define HSW_PLATFORM \
@@ -627,9 +460,6 @@ static const struct intel_device_info bdw_gt3_info = {
static const struct intel_device_info chv_info = {
PLATFORM(INTEL_CHERRYVIEW),
GEN(8),
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C),
- .display.has_hotplug = 1,
.is_lp = 1,
.__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0),
.has_64bit_reloc = 1,
@@ -637,19 +467,16 @@ static const struct intel_device_info chv_info = {
.has_rc6 = 1,
.has_rps = true,
.has_logical_ring_contexts = 1,
- .display.has_gmch = 1,
.dma_mask_size = 39,
+ .max_pat_index = 3,
.__runtime.ppgtt_type = INTEL_PPGTT_FULL,
.__runtime.ppgtt_size = 32,
.has_reset_engine = 1,
.has_snoop = true,
.has_coherent_ggtt = false,
- .display.mmio_offset = VLV_DISPLAY_BASE,
- CHV_PIPE_OFFSETS,
- CHV_CURSOR_OFFSETS,
- CHV_COLORS,
GEN_DEFAULT_PAGE_SIZES,
GEN_DEFAULT_REGIONS,
+ LEGACY_CACHELEVEL,
};
#define GEN9_DEFAULT_PAGE_SIZES \
@@ -660,14 +487,7 @@ static const struct intel_device_info chv_info = {
GEN8_FEATURES, \
GEN(9), \
GEN9_DEFAULT_PAGE_SIZES, \
- .__runtime.has_dmc = 1, \
- .has_gt_uc = 1, \
- .__runtime.has_hdcp = 1, \
- .display.has_ipc = 1, \
- .display.has_psr = 1, \
- .display.has_psr_hw_tracking = 1, \
- .display.dbuf.size = 896 - 4, /* 4 blocks for bypass path allocation */ \
- .display.dbuf.slice_mask = BIT(DBUF_S1)
+ .has_gt_uc = 1
#define SKL_PLATFORM \
GEN9_FEATURES, \
@@ -702,26 +522,12 @@ static const struct intel_device_info skl_gt4_info = {
#define GEN9_LP_FEATURES \
GEN(9), \
.is_lp = 1, \
- .display.dbuf.slice_mask = BIT(DBUF_S1), \
- .display.has_hotplug = 1, \
.__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
- BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP) | \
- BIT(TRANSCODER_DSI_A) | BIT(TRANSCODER_DSI_C), \
.has_3d_pipeline = 1, \
.has_64bit_reloc = 1, \
- .display.has_ddi = 1, \
- .display.has_fpga_dbg = 1, \
- .__runtime.fbc_mask = BIT(INTEL_FBC_A), \
- .__runtime.has_hdcp = 1, \
- .display.has_psr = 1, \
- .display.has_psr_hw_tracking = 1, \
.has_runtime_pm = 1, \
- .__runtime.has_dmc = 1, \
.has_rc6 = 1, \
.has_rps = true, \
- .display.has_dp_mst = 1, \
.has_logical_ring_contexts = 1, \
.has_gt_uc = 1, \
.dma_mask_size = 39, \
@@ -730,25 +536,19 @@ static const struct intel_device_info skl_gt4_info = {
.has_reset_engine = 1, \
.has_snoop = true, \
.has_coherent_ggtt = false, \
- .display.has_ipc = 1, \
- HSW_PIPE_OFFSETS, \
- IVB_CURSOR_OFFSETS, \
- IVB_COLORS, \
+ .max_pat_index = 3, \
GEN9_DEFAULT_PAGE_SIZES, \
- GEN_DEFAULT_REGIONS
+ GEN_DEFAULT_REGIONS, \
+ LEGACY_CACHELEVEL
static const struct intel_device_info bxt_info = {
GEN9_LP_FEATURES,
PLATFORM(INTEL_BROXTON),
- .display.dbuf.size = 512 - 4, /* 4 blocks for bypass path allocation */
};
static const struct intel_device_info glk_info = {
GEN9_LP_FEATURES,
PLATFORM(INTEL_GEMINILAKE),
- .__runtime.display.ip.ver = 10,
- .display.dbuf.size = 1024 - 4, /* 4 blocks for bypass path allocation */
- GLK_COLORS,
};
#define KBL_PLATFORM \
@@ -815,31 +615,7 @@ static const struct intel_device_info cml_gt2_info = {
#define GEN11_FEATURES \
GEN9_FEATURES, \
GEN11_DEFAULT_PAGE_SIZES, \
- .display.abox_mask = BIT(0), \
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
- BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP) | \
- BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \
- .display.pipe_offsets = { \
- [TRANSCODER_A] = PIPE_A_OFFSET, \
- [TRANSCODER_B] = PIPE_B_OFFSET, \
- [TRANSCODER_C] = PIPE_C_OFFSET, \
- [TRANSCODER_EDP] = PIPE_EDP_OFFSET, \
- [TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \
- [TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \
- }, \
- .display.trans_offsets = { \
- [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
- [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
- [TRANSCODER_C] = TRANSCODER_C_OFFSET, \
- [TRANSCODER_EDP] = TRANSCODER_EDP_OFFSET, \
- [TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \
- [TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \
- }, \
GEN(11), \
- ICL_COLORS, \
- .display.dbuf.size = 2048, \
- .display.dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2), \
- .__runtime.has_dsc = 1, \
.has_coherent_ggtt = false, \
.has_logical_ring_elsq = 1
@@ -867,31 +643,10 @@ static const struct intel_device_info jsl_info = {
#define GEN12_FEATURES \
GEN11_FEATURES, \
GEN(12), \
- .display.abox_mask = GENMASK(2, 1), \
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
- BIT(TRANSCODER_C) | BIT(TRANSCODER_D) | \
- BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \
- .display.pipe_offsets = { \
- [TRANSCODER_A] = PIPE_A_OFFSET, \
- [TRANSCODER_B] = PIPE_B_OFFSET, \
- [TRANSCODER_C] = PIPE_C_OFFSET, \
- [TRANSCODER_D] = PIPE_D_OFFSET, \
- [TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \
- [TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \
- }, \
- .display.trans_offsets = { \
- [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
- [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
- [TRANSCODER_C] = TRANSCODER_C_OFFSET, \
- [TRANSCODER_D] = TRANSCODER_D_OFFSET, \
- [TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \
- [TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \
- }, \
- TGL_CURSOR_OFFSETS, \
+ TGL_CACHELEVEL, \
.has_global_mocs = 1, \
.has_pxp = 1, \
- .display.has_dsb = 1
+ .max_pat_index = 3
static const struct intel_device_info tgl_info = {
GEN12_FEATURES,
@@ -903,12 +658,6 @@ static const struct intel_device_info tgl_info = {
static const struct intel_device_info rkl_info = {
GEN12_FEATURES,
PLATFORM(INTEL_ROCKETLAKE),
- .display.abox_mask = BIT(0),
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
- BIT(TRANSCODER_C),
- .display.has_hti = 1,
- .display.has_psr_hw_tracking = 0,
.__runtime.platform_engine_mask =
BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0),
};
@@ -926,7 +675,6 @@ static const struct intel_device_info dg1_info = {
DGFX_FEATURES,
.__runtime.graphics.ip.rel = 10,
PLATFORM(INTEL_DG1),
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
.require_force_probe = 1,
.__runtime.platform_engine_mask =
BIT(RCS0) | BIT(BCS0) | BIT(VECS0) |
@@ -938,64 +686,14 @@ static const struct intel_device_info dg1_info = {
static const struct intel_device_info adl_s_info = {
GEN12_FEATURES,
PLATFORM(INTEL_ALDERLAKE_S),
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
- .display.has_hti = 1,
- .display.has_psr_hw_tracking = 0,
.__runtime.platform_engine_mask =
BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2),
.dma_mask_size = 39,
};
-#define XE_LPD_FEATURES \
- .display.abox_mask = GENMASK(1, 0), \
- .display.color = { \
- .degamma_lut_size = 129, .gamma_lut_size = 1024, \
- .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \
- DRM_COLOR_LUT_EQUAL_CHANNELS, \
- }, \
- .display.dbuf.size = 4096, \
- .display.dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | \
- BIT(DBUF_S4), \
- .display.has_ddi = 1, \
- .__runtime.has_dmc = 1, \
- .display.has_dp_mst = 1, \
- .display.has_dsb = 1, \
- .__runtime.has_dsc = 1, \
- .__runtime.fbc_mask = BIT(INTEL_FBC_A), \
- .display.has_fpga_dbg = 1, \
- .__runtime.has_hdcp = 1, \
- .display.has_hotplug = 1, \
- .display.has_ipc = 1, \
- .display.has_psr = 1, \
- .__runtime.display.ip.ver = 13, \
- .__runtime.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \
- .display.pipe_offsets = { \
- [TRANSCODER_A] = PIPE_A_OFFSET, \
- [TRANSCODER_B] = PIPE_B_OFFSET, \
- [TRANSCODER_C] = PIPE_C_OFFSET, \
- [TRANSCODER_D] = PIPE_D_OFFSET, \
- [TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \
- [TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \
- }, \
- .display.trans_offsets = { \
- [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
- [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
- [TRANSCODER_C] = TRANSCODER_C_OFFSET, \
- [TRANSCODER_D] = TRANSCODER_D_OFFSET, \
- [TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \
- [TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \
- }, \
- TGL_CURSOR_OFFSETS
-
static const struct intel_device_info adl_p_info = {
GEN12_FEATURES,
- XE_LPD_FEATURES,
PLATFORM(INTEL_ALDERLAKE_P),
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
- BIT(TRANSCODER_C) | BIT(TRANSCODER_D) |
- BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1),
- .display.has_cdclk_crawl = 1,
- .display.has_psr_hw_tracking = 0,
.__runtime.platform_engine_mask =
BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2),
.__runtime.ppgtt_size = 48,
@@ -1013,6 +711,7 @@ static const struct intel_device_info adl_p_info = {
.__runtime.graphics.ip.ver = 12, \
.__runtime.graphics.ip.rel = 50, \
XE_HP_PAGE_SIZES, \
+ TGL_CACHELEVEL, \
.dma_mask_size = 46, \
.has_3d_pipeline = 1, \
.has_64bit_reloc = 1, \
@@ -1031,6 +730,7 @@ static const struct intel_device_info adl_p_info = {
.has_reset_engine = 1, \
.has_rps = 1, \
.has_runtime_pm = 1, \
+ .max_pat_index = 3, \
.__runtime.ppgtt_size = 48, \
.__runtime.ppgtt_type = INTEL_PPGTT_FULL
@@ -1044,7 +744,6 @@ static const struct intel_device_info xehpsdv_info = {
XE_HPM_FEATURES,
DGFX_FEATURES,
PLATFORM(INTEL_XEHPSDV),
- NO_DISPLAY,
.has_64k_pages = 1,
.has_media_ratio_mode = 1,
.__runtime.platform_engine_mask =
@@ -1067,7 +766,6 @@ static const struct intel_device_info xehpsdv_info = {
.has_guc_deprivilege = 1, \
.has_heci_pxp = 1, \
.has_media_ratio_mode = 1, \
- .display.has_cdclk_squash = 1, \
.__runtime.platform_engine_mask = \
BIT(RCS0) | BIT(BCS0) | \
BIT(VECS0) | BIT(VECS1) | \
@@ -1076,14 +774,10 @@ static const struct intel_device_info xehpsdv_info = {
static const struct intel_device_info dg2_info = {
DG2_FEATURES,
- XE_LPD_FEATURES,
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
- BIT(TRANSCODER_C) | BIT(TRANSCODER_D),
};
static const struct intel_device_info ats_m_info = {
DG2_FEATURES,
- NO_DISPLAY,
.require_force_probe = 1,
.tuning_thread_rr_after_dep = 1,
};
@@ -1105,22 +799,16 @@ static const struct intel_device_info pvc_info = {
.__runtime.graphics.ip.rel = 60,
.__runtime.media.ip.rel = 60,
PLATFORM(INTEL_PONTEVECCHIO),
- NO_DISPLAY,
.has_flat_ccs = 0,
+ .max_pat_index = 7,
.__runtime.platform_engine_mask =
BIT(BCS0) |
BIT(VCS0) |
BIT(CCS0) | BIT(CCS1) | BIT(CCS2) | BIT(CCS3),
.require_force_probe = 1,
+ PVC_CACHELEVEL,
};
-#define XE_LPDP_FEATURES \
- XE_LPD_FEATURES, \
- .__runtime.display.ip.ver = 14, \
- .display.has_cdclk_crawl = 1, \
- .display.has_cdclk_squash = 1, \
- .__runtime.fbc_mask = BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B)
-
static const struct intel_gt_definition xelpmp_extra_gt[] = {
{
.type = GT_MEDIA,
@@ -1133,9 +821,6 @@ static const struct intel_gt_definition xelpmp_extra_gt[] = {
static const struct intel_device_info mtl_info = {
XE_HP_FEATURES,
- XE_LPDP_FEATURES,
- .__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
- BIT(TRANSCODER_C) | BIT(TRANSCODER_D),
/*
* Real graphics IP version will be obtained from hardware GMD_ID
* register. Value provided here is just for sanity checking.
@@ -1148,15 +833,21 @@ static const struct intel_device_info mtl_info = {
.has_flat_ccs = 0,
.has_gmd_id = 1,
.has_guc_deprivilege = 1,
+ .has_llc = 0,
.has_mslice_steering = 0,
.has_snoop = 1,
+ .max_pat_index = 4,
+ .has_pxp = 1,
.__runtime.memory_regions = REGION_SMEM | REGION_STOLEN_LMEM,
.__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(CCS0),
.require_force_probe = 1,
+ MTL_CACHELEVEL,
};
#undef PLATFORM
+__diag_pop();
+
/*
* Make sure any device matches here are from most specific to most
* general. For example, since the Quanta match is based on the subsystem
@@ -1362,7 +1053,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENXIO;
/* Detect if we need to wait for other drivers early on */
- if (intel_modeset_probe_defer(pdev))
+ if (intel_display_driver_probe_defer(pdev))
return -EPROBE_DEFER;
err = i915_driver_probe(pdev, ent);
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index 3035cba2c6a2..0a111b281578 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -531,8 +531,7 @@ static void oa_context_id_squash(struct i915_perf_stream *stream, u32 *report)
* (See description of OA_TAIL_MARGIN_NSEC above for further details.)
*
* Besides returning true when there is data available to read() this function
- * also updates the tail, aging_tail and aging_timestamp in the oa_buffer
- * object.
+ * also updates the tail in the oa_buffer object.
*
* Note: It's safe to read OA config state here unlocked, assuming that this is
* only called while the stream is enabled, while the global OA configuration
@@ -544,10 +543,10 @@ static bool oa_buffer_check_unlocked(struct i915_perf_stream *stream)
{
u32 gtt_offset = i915_ggtt_offset(stream->oa_buffer.vma);
int report_size = stream->oa_buffer.format->size;
+ u32 head, tail, read_tail;
unsigned long flags;
bool pollin;
u32 hw_tail;
- u64 now;
u32 partial_report_size;
/* We have to consider the (unlikely) possibility that read() errors
@@ -566,64 +565,48 @@ static bool oa_buffer_check_unlocked(struct i915_perf_stream *stream)
partial_report_size %= report_size;
/* Subtract partial amount off the tail */
- hw_tail = gtt_offset + OA_TAKEN(hw_tail, partial_report_size);
+ hw_tail = OA_TAKEN(hw_tail, partial_report_size);
- now = ktime_get_mono_fast_ns();
+ /* NB: The head we observe here might effectively be a little
+ * out of date. If a read() is in progress, the head could be
+ * anywhere between this head and stream->oa_buffer.tail.
+ */
+ head = stream->oa_buffer.head - gtt_offset;
+ read_tail = stream->oa_buffer.tail - gtt_offset;
- if (hw_tail == stream->oa_buffer.aging_tail &&
- (now - stream->oa_buffer.aging_timestamp) > OA_TAIL_MARGIN_NSEC) {
- /* If the HW tail hasn't move since the last check and the HW
- * tail has been aging for long enough, declare it the new
- * tail.
- */
- stream->oa_buffer.tail = stream->oa_buffer.aging_tail;
- } else {
- u32 head, tail, aged_tail;
+ tail = hw_tail;
- /* NB: The head we observe here might effectively be a little
- * out of date. If a read() is in progress, the head could be
- * anywhere between this head and stream->oa_buffer.tail.
- */
- head = stream->oa_buffer.head - gtt_offset;
- aged_tail = stream->oa_buffer.tail - gtt_offset;
-
- hw_tail -= gtt_offset;
- tail = hw_tail;
-
- /* Walk the stream backward until we find a report with report
- * id and timestmap not at 0. Since the circular buffer pointers
- * progress by increments of 64 bytes and that reports can be up
- * to 256 bytes long, we can't tell whether a report has fully
- * landed in memory before the report id and timestamp of the
- * following report have effectively landed.
- *
- * This is assuming that the writes of the OA unit land in
- * memory in the order they were written to.
- * If not : (╯°□°)╯︵ ┻━┻
- */
- while (OA_TAKEN(tail, aged_tail) >= report_size) {
- void *report = stream->oa_buffer.vaddr + tail;
+ /* Walk the stream backward until we find a report with report
+ * id and timestmap not at 0. Since the circular buffer pointers
+ * progress by increments of 64 bytes and that reports can be up
+ * to 256 bytes long, we can't tell whether a report has fully
+ * landed in memory before the report id and timestamp of the
+ * following report have effectively landed.
+ *
+ * This is assuming that the writes of the OA unit land in
+ * memory in the order they were written to.
+ * If not : (╯°□°)╯︵ ┻━┻
+ */
+ while (OA_TAKEN(tail, read_tail) >= report_size) {
+ void *report = stream->oa_buffer.vaddr + tail;
- if (oa_report_id(stream, report) ||
- oa_timestamp(stream, report))
- break;
+ if (oa_report_id(stream, report) ||
+ oa_timestamp(stream, report))
+ break;
- tail = (tail - report_size) & (OA_BUFFER_SIZE - 1);
- }
+ tail = (tail - report_size) & (OA_BUFFER_SIZE - 1);
+ }
- if (OA_TAKEN(hw_tail, tail) > report_size &&
- __ratelimit(&stream->perf->tail_pointer_race))
- drm_notice(&stream->uncore->i915->drm,
- "unlanded report(s) head=0x%x tail=0x%x hw_tail=0x%x\n",
- head, tail, hw_tail);
+ if (OA_TAKEN(hw_tail, tail) > report_size &&
+ __ratelimit(&stream->perf->tail_pointer_race))
+ drm_notice(&stream->uncore->i915->drm,
+ "unlanded report(s) head=0x%x tail=0x%x hw_tail=0x%x\n",
+ head, tail, hw_tail);
- stream->oa_buffer.tail = gtt_offset + tail;
- stream->oa_buffer.aging_tail = gtt_offset + hw_tail;
- stream->oa_buffer.aging_timestamp = now;
- }
+ stream->oa_buffer.tail = gtt_offset + tail;
- pollin = OA_TAKEN(stream->oa_buffer.tail - gtt_offset,
- stream->oa_buffer.head - gtt_offset) >= report_size;
+ pollin = OA_TAKEN(stream->oa_buffer.tail,
+ stream->oa_buffer.head) >= report_size;
spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
@@ -1727,7 +1710,6 @@ static void gen7_init_oa_buffer(struct i915_perf_stream *stream)
gtt_offset | OABUFFER_SIZE_16M);
/* Mark that we need updated tail pointers to read from... */
- stream->oa_buffer.aging_tail = INVALID_TAIL_PTR;
stream->oa_buffer.tail = gtt_offset;
spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
@@ -1779,7 +1761,6 @@ static void gen8_init_oa_buffer(struct i915_perf_stream *stream)
intel_uncore_write(uncore, GEN8_OATAILPTR, gtt_offset & GEN8_OATAILPTR_MASK);
/* Mark that we need updated tail pointers to read from... */
- stream->oa_buffer.aging_tail = INVALID_TAIL_PTR;
stream->oa_buffer.tail = gtt_offset;
/*
@@ -1833,7 +1814,6 @@ static void gen12_init_oa_buffer(struct i915_perf_stream *stream)
gtt_offset & GEN12_OAG_OATAILPTR_MASK);
/* Mark that we need updated tail pointers to read from... */
- stream->oa_buffer.aging_tail = INVALID_TAIL_PTR;
stream->oa_buffer.tail = gtt_offset;
/*
@@ -5305,6 +5285,7 @@ void i915_perf_fini(struct drm_i915_private *i915)
/**
* i915_perf_ioctl_version - Version of the i915-perf subsystem
+ * @i915: The i915 device
*
* This version number is used by userspace to detect available features.
*/
diff --git a/drivers/gpu/drm/i915/i915_perf_oa_regs.h b/drivers/gpu/drm/i915/i915_perf_oa_regs.h
index ba103875e19f..e5ac7a8b5cb6 100644
--- a/drivers/gpu/drm/i915/i915_perf_oa_regs.h
+++ b/drivers/gpu/drm/i915/i915_perf_oa_regs.h
@@ -134,10 +134,6 @@
#define GDT_CHICKEN_BITS _MMIO(0x9840)
#define GT_NOA_ENABLE 0x00000080
-#define GEN12_SQCNT1 _MMIO(0x8718)
-#define GEN12_SQCNT1_PMON_ENABLE REG_BIT(30)
-#define GEN12_SQCNT1_OABPC REG_BIT(29)
-
/* Gen12 OAM unit */
#define GEN12_OAM_HEAD_POINTER_OFFSET (0x1a0)
#define GEN12_OAM_HEAD_POINTER_MASK 0xffffffc0
diff --git a/drivers/gpu/drm/i915/i915_perf_types.h b/drivers/gpu/drm/i915/i915_perf_types.h
index 66dd5f74de05..fe3a5dae8c22 100644
--- a/drivers/gpu/drm/i915/i915_perf_types.h
+++ b/drivers/gpu/drm/i915/i915_perf_types.h
@@ -313,18 +313,6 @@ struct i915_perf_stream {
spinlock_t ptr_lock;
/**
- * @aging_tail: The last HW tail reported by HW. The data
- * might not have made it to memory yet though.
- */
- u32 aging_tail;
-
- /**
- * @aging_timestamp: A monotonic timestamp for when the current aging tail pointer
- * was read; used to determine when it is old enough to trust.
- */
- u64 aging_timestamp;
-
- /**
* @head: Although we can always read back the head pointer register,
* we prefer to avoid trusting the HW state, just to avoid any
* risk that some hardware condition could * somehow bump the
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
index 7ece883a7d95..d35973b41186 100644
--- a/drivers/gpu/drm/i915/i915_pmu.c
+++ b/drivers/gpu/drm/i915/i915_pmu.c
@@ -10,6 +10,7 @@
#include "gt/intel_engine_pm.h"
#include "gt/intel_engine_regs.h"
#include "gt/intel_engine_user.h"
+#include "gt/intel_gt.h"
#include "gt/intel_gt_pm.h"
#include "gt/intel_gt_regs.h"
#include "gt/intel_rc6.h"
@@ -50,16 +51,26 @@ static u8 engine_event_instance(struct perf_event *event)
return (event->attr.config >> I915_PMU_SAMPLE_BITS) & 0xff;
}
-static bool is_engine_config(u64 config)
+static bool is_engine_config(const u64 config)
{
return config < __I915_PMU_OTHER(0);
}
+static unsigned int config_gt_id(const u64 config)
+{
+ return config >> __I915_PMU_GT_SHIFT;
+}
+
+static u64 config_counter(const u64 config)
+{
+ return config & ~(~0ULL << __I915_PMU_GT_SHIFT);
+}
+
static unsigned int other_bit(const u64 config)
{
unsigned int val;
- switch (config) {
+ switch (config_counter(config)) {
case I915_PMU_ACTUAL_FREQUENCY:
val = __I915_PMU_ACTUAL_FREQUENCY_ENABLED;
break;
@@ -77,7 +88,9 @@ static unsigned int other_bit(const u64 config)
return -1;
}
- return I915_ENGINE_SAMPLE_COUNT + val;
+ return I915_ENGINE_SAMPLE_COUNT +
+ config_gt_id(config) * __I915_PMU_TRACKED_EVENT_COUNT +
+ val;
}
static unsigned int config_bit(const u64 config)
@@ -88,9 +101,20 @@ static unsigned int config_bit(const u64 config)
return other_bit(config);
}
-static u64 config_mask(u64 config)
+static u32 config_mask(const u64 config)
{
- return BIT_ULL(config_bit(config));
+ unsigned int bit = config_bit(config);
+
+ if (__builtin_constant_p(config))
+ BUILD_BUG_ON(bit >
+ BITS_PER_TYPE(typeof_member(struct i915_pmu,
+ enable)) - 1);
+ else
+ WARN_ON_ONCE(bit >
+ BITS_PER_TYPE(typeof_member(struct i915_pmu,
+ enable)) - 1);
+
+ return BIT(config_bit(config));
}
static bool is_engine_event(struct perf_event *event)
@@ -103,7 +127,19 @@ static unsigned int event_bit(struct perf_event *event)
return config_bit(event->attr.config);
}
-static bool pmu_needs_timer(struct i915_pmu *pmu, bool gpu_active)
+static u32 frequency_enabled_mask(void)
+{
+ unsigned int i;
+ u32 mask = 0;
+
+ for (i = 0; i < I915_PMU_MAX_GT; i++)
+ mask |= config_mask(__I915_PMU_ACTUAL_FREQUENCY(i)) |
+ config_mask(__I915_PMU_REQUESTED_FREQUENCY(i));
+
+ return mask;
+}
+
+static bool pmu_needs_timer(struct i915_pmu *pmu)
{
struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
u32 enable;
@@ -119,21 +155,13 @@ static bool pmu_needs_timer(struct i915_pmu *pmu, bool gpu_active)
* Mask out all the ones which do not need the timer, or in
* other words keep all the ones that could need the timer.
*/
- enable &= config_mask(I915_PMU_ACTUAL_FREQUENCY) |
- config_mask(I915_PMU_REQUESTED_FREQUENCY) |
- ENGINE_SAMPLE_MASK;
+ enable &= frequency_enabled_mask() | ENGINE_SAMPLE_MASK;
/*
- * When the GPU is idle per-engine counters do not need to be
- * running so clear those bits out.
- */
- if (!gpu_active)
- enable &= ~ENGINE_SAMPLE_MASK;
- /*
* Also there is software busyness tracking available we do not
* need the timer for I915_SAMPLE_BUSY counter.
*/
- else if (i915->caps.scheduler & I915_SCHEDULER_CAP_ENGINE_BUSY_STATS)
+ if (i915->caps.scheduler & I915_SCHEDULER_CAP_ENGINE_BUSY_STATS)
enable &= ~BIT(I915_SAMPLE_BUSY);
/*
@@ -163,9 +191,27 @@ static inline s64 ktime_since_raw(const ktime_t kt)
return ktime_to_ns(ktime_sub(ktime_get_raw(), kt));
}
+static u64 read_sample(struct i915_pmu *pmu, unsigned int gt_id, int sample)
+{
+ return pmu->sample[gt_id][sample].cur;
+}
+
+static void
+store_sample(struct i915_pmu *pmu, unsigned int gt_id, int sample, u64 val)
+{
+ pmu->sample[gt_id][sample].cur = val;
+}
+
+static void
+add_sample_mult(struct i915_pmu *pmu, unsigned int gt_id, int sample, u32 val, u32 mul)
+{
+ pmu->sample[gt_id][sample].cur += mul_u32_u32(val, mul);
+}
+
static u64 get_rc6(struct intel_gt *gt)
{
struct drm_i915_private *i915 = gt->i915;
+ const unsigned int gt_id = gt->info.id;
struct i915_pmu *pmu = &i915->pmu;
unsigned long flags;
bool awake = false;
@@ -180,7 +226,7 @@ static u64 get_rc6(struct intel_gt *gt)
spin_lock_irqsave(&pmu->lock, flags);
if (awake) {
- pmu->sample[__I915_SAMPLE_RC6].cur = val;
+ store_sample(pmu, gt_id, __I915_SAMPLE_RC6, val);
} else {
/*
* We think we are runtime suspended.
@@ -189,14 +235,14 @@ static u64 get_rc6(struct intel_gt *gt)
* on top of the last known real value, as the approximated RC6
* counter value.
*/
- val = ktime_since_raw(pmu->sleep_last);
- val += pmu->sample[__I915_SAMPLE_RC6].cur;
+ val = ktime_since_raw(pmu->sleep_last[gt_id]);
+ val += read_sample(pmu, gt_id, __I915_SAMPLE_RC6);
}
- if (val < pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur)
- val = pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur;
+ if (val < read_sample(pmu, gt_id, __I915_SAMPLE_RC6_LAST_REPORTED))
+ val = read_sample(pmu, gt_id, __I915_SAMPLE_RC6_LAST_REPORTED);
else
- pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur = val;
+ store_sample(pmu, gt_id, __I915_SAMPLE_RC6_LAST_REPORTED, val);
spin_unlock_irqrestore(&pmu->lock, flags);
@@ -206,27 +252,34 @@ static u64 get_rc6(struct intel_gt *gt)
static void init_rc6(struct i915_pmu *pmu)
{
struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
- intel_wakeref_t wakeref;
+ struct intel_gt *gt;
+ unsigned int i;
+
+ for_each_gt(gt, i915, i) {
+ intel_wakeref_t wakeref;
+
+ with_intel_runtime_pm(gt->uncore->rpm, wakeref) {
+ u64 val = __get_rc6(gt);
- with_intel_runtime_pm(to_gt(i915)->uncore->rpm, wakeref) {
- pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(to_gt(i915));
- pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur =
- pmu->sample[__I915_SAMPLE_RC6].cur;
- pmu->sleep_last = ktime_get_raw();
+ store_sample(pmu, i, __I915_SAMPLE_RC6, val);
+ store_sample(pmu, i, __I915_SAMPLE_RC6_LAST_REPORTED,
+ val);
+ pmu->sleep_last[i] = ktime_get_raw();
+ }
}
}
-static void park_rc6(struct drm_i915_private *i915)
+static void park_rc6(struct intel_gt *gt)
{
- struct i915_pmu *pmu = &i915->pmu;
+ struct i915_pmu *pmu = &gt->i915->pmu;
- pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(to_gt(i915));
- pmu->sleep_last = ktime_get_raw();
+ store_sample(pmu, gt->info.id, __I915_SAMPLE_RC6, __get_rc6(gt));
+ pmu->sleep_last[gt->info.id] = ktime_get_raw();
}
static void __i915_pmu_maybe_start_timer(struct i915_pmu *pmu)
{
- if (!pmu->timer_enabled && pmu_needs_timer(pmu, true)) {
+ if (!pmu->timer_enabled && pmu_needs_timer(pmu)) {
pmu->timer_enabled = true;
pmu->timer_last = ktime_get();
hrtimer_start_range_ns(&pmu->timer,
@@ -235,29 +288,31 @@ static void __i915_pmu_maybe_start_timer(struct i915_pmu *pmu)
}
}
-void i915_pmu_gt_parked(struct drm_i915_private *i915)
+void i915_pmu_gt_parked(struct intel_gt *gt)
{
- struct i915_pmu *pmu = &i915->pmu;
+ struct i915_pmu *pmu = &gt->i915->pmu;
if (!pmu->base.event_init)
return;
spin_lock_irq(&pmu->lock);
- park_rc6(i915);
+ park_rc6(gt);
/*
* Signal sampling timer to stop if only engine events are enabled and
* GPU went idle.
*/
- pmu->timer_enabled = pmu_needs_timer(pmu, false);
+ pmu->unparked &= ~BIT(gt->info.id);
+ if (pmu->unparked == 0)
+ pmu->timer_enabled = false;
spin_unlock_irq(&pmu->lock);
}
-void i915_pmu_gt_unparked(struct drm_i915_private *i915)
+void i915_pmu_gt_unparked(struct intel_gt *gt)
{
- struct i915_pmu *pmu = &i915->pmu;
+ struct i915_pmu *pmu = &gt->i915->pmu;
if (!pmu->base.event_init)
return;
@@ -267,7 +322,10 @@ void i915_pmu_gt_unparked(struct drm_i915_private *i915)
/*
* Re-enable sampling timer when GPU goes active.
*/
- __i915_pmu_maybe_start_timer(pmu);
+ if (pmu->unparked == 0)
+ __i915_pmu_maybe_start_timer(pmu);
+
+ pmu->unparked |= BIT(gt->info.id);
spin_unlock_irq(&pmu->lock);
}
@@ -338,6 +396,9 @@ engines_sample(struct intel_gt *gt, unsigned int period_ns)
return;
for_each_engine(engine, gt, id) {
+ if (!engine->pmu.enable)
+ continue;
+
if (!intel_engine_pm_get_if_awake(engine))
continue;
@@ -353,34 +414,30 @@ engines_sample(struct intel_gt *gt, unsigned int period_ns)
}
}
-static void
-add_sample_mult(struct i915_pmu_sample *sample, u32 val, u32 mul)
-{
- sample->cur += mul_u32_u32(val, mul);
-}
-
-static bool frequency_sampling_enabled(struct i915_pmu *pmu)
+static bool
+frequency_sampling_enabled(struct i915_pmu *pmu, unsigned int gt)
{
return pmu->enable &
- (config_mask(I915_PMU_ACTUAL_FREQUENCY) |
- config_mask(I915_PMU_REQUESTED_FREQUENCY));
+ (config_mask(__I915_PMU_ACTUAL_FREQUENCY(gt)) |
+ config_mask(__I915_PMU_REQUESTED_FREQUENCY(gt)));
}
static void
frequency_sample(struct intel_gt *gt, unsigned int period_ns)
{
struct drm_i915_private *i915 = gt->i915;
+ const unsigned int gt_id = gt->info.id;
struct i915_pmu *pmu = &i915->pmu;
struct intel_rps *rps = &gt->rps;
- if (!frequency_sampling_enabled(pmu))
+ if (!frequency_sampling_enabled(pmu, gt_id))
return;
/* Report 0/0 (actual/requested) frequency while parked. */
if (!intel_gt_pm_get_if_awake(gt))
return;
- if (pmu->enable & config_mask(I915_PMU_ACTUAL_FREQUENCY)) {
+ if (pmu->enable & config_mask(__I915_PMU_ACTUAL_FREQUENCY(gt_id))) {
u32 val;
/*
@@ -396,12 +453,12 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns)
if (!val)
val = intel_gpu_freq(rps, rps->cur_freq);
- add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_ACT],
+ add_sample_mult(pmu, gt_id, __I915_SAMPLE_FREQ_ACT,
val, period_ns / 1000);
}
- if (pmu->enable & config_mask(I915_PMU_REQUESTED_FREQUENCY)) {
- add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_REQ],
+ if (pmu->enable & config_mask(__I915_PMU_REQUESTED_FREQUENCY(gt_id))) {
+ add_sample_mult(pmu, gt_id, __I915_SAMPLE_FREQ_REQ,
intel_rps_get_requested_frequency(rps),
period_ns / 1000);
}
@@ -414,8 +471,9 @@ static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer)
struct drm_i915_private *i915 =
container_of(hrtimer, struct drm_i915_private, pmu.timer);
struct i915_pmu *pmu = &i915->pmu;
- struct intel_gt *gt = to_gt(i915);
unsigned int period_ns;
+ struct intel_gt *gt;
+ unsigned int i;
ktime_t now;
if (!READ_ONCE(pmu->timer_enabled))
@@ -431,8 +489,14 @@ static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer)
* grabbing the forcewake. However the potential error from timer call-
* back delay greatly dominates this so we keep it simple.
*/
- engines_sample(gt, period_ns);
- frequency_sample(gt, period_ns);
+
+ for_each_gt(gt, i915, i) {
+ if (!(pmu->unparked & BIT(i)))
+ continue;
+
+ engines_sample(gt, period_ns);
+ frequency_sample(gt, period_ns);
+ }
hrtimer_forward(hrtimer, now, ns_to_ktime(PERIOD));
@@ -473,7 +537,13 @@ config_status(struct drm_i915_private *i915, u64 config)
{
struct intel_gt *gt = to_gt(i915);
- switch (config) {
+ unsigned int gt_id = config_gt_id(config);
+ unsigned int max_gt_id = HAS_EXTRA_GT_LIST(i915) ? 1 : 0;
+
+ if (gt_id > max_gt_id)
+ return -ENOENT;
+
+ switch (config_counter(config)) {
case I915_PMU_ACTUAL_FREQUENCY:
if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
/* Requires a mutex for sampling! */
@@ -484,6 +554,8 @@ config_status(struct drm_i915_private *i915, u64 config)
return -ENODEV;
break;
case I915_PMU_INTERRUPTS:
+ if (gt_id)
+ return -ENOENT;
break;
case I915_PMU_RC6_RESIDENCY:
if (!gt->rc6.supported)
@@ -581,22 +653,27 @@ static u64 __i915_pmu_event_read(struct perf_event *event)
val = engine->pmu.sample[sample].cur;
}
} else {
- switch (event->attr.config) {
+ const unsigned int gt_id = config_gt_id(event->attr.config);
+ const u64 config = config_counter(event->attr.config);
+
+ switch (config) {
case I915_PMU_ACTUAL_FREQUENCY:
val =
- div_u64(pmu->sample[__I915_SAMPLE_FREQ_ACT].cur,
+ div_u64(read_sample(pmu, gt_id,
+ __I915_SAMPLE_FREQ_ACT),
USEC_PER_SEC /* to MHz */);
break;
case I915_PMU_REQUESTED_FREQUENCY:
val =
- div_u64(pmu->sample[__I915_SAMPLE_FREQ_REQ].cur,
+ div_u64(read_sample(pmu, gt_id,
+ __I915_SAMPLE_FREQ_REQ),
USEC_PER_SEC /* to MHz */);
break;
case I915_PMU_INTERRUPTS:
val = READ_ONCE(pmu->irq_count);
break;
case I915_PMU_RC6_RESIDENCY:
- val = get_rc6(to_gt(i915));
+ val = get_rc6(i915->gt[gt_id]);
break;
case I915_PMU_SOFTWARE_GT_AWAKE_TIME:
val = ktime_to_ns(intel_gt_get_awake_time(to_gt(i915)));
@@ -633,11 +710,10 @@ static void i915_pmu_enable(struct perf_event *event)
{
struct drm_i915_private *i915 =
container_of(event->pmu, typeof(*i915), pmu.base);
+ const unsigned int bit = event_bit(event);
struct i915_pmu *pmu = &i915->pmu;
unsigned long flags;
- unsigned int bit;
- bit = event_bit(event);
if (bit == -1)
goto update;
@@ -651,7 +727,7 @@ static void i915_pmu_enable(struct perf_event *event)
GEM_BUG_ON(bit >= ARRAY_SIZE(pmu->enable_count));
GEM_BUG_ON(pmu->enable_count[bit] == ~0);
- pmu->enable |= BIT_ULL(bit);
+ pmu->enable |= BIT(bit);
pmu->enable_count[bit]++;
/*
@@ -698,7 +774,7 @@ static void i915_pmu_disable(struct perf_event *event)
{
struct drm_i915_private *i915 =
container_of(event->pmu, typeof(*i915), pmu.base);
- unsigned int bit = event_bit(event);
+ const unsigned int bit = event_bit(event);
struct i915_pmu *pmu = &i915->pmu;
unsigned long flags;
@@ -734,8 +810,8 @@ static void i915_pmu_disable(struct perf_event *event)
* bitmask when the last listener on an event goes away.
*/
if (--pmu->enable_count[bit] == 0) {
- pmu->enable &= ~BIT_ULL(bit);
- pmu->timer_enabled &= pmu_needs_timer(pmu, true);
+ pmu->enable &= ~BIT(bit);
+ pmu->timer_enabled &= pmu_needs_timer(pmu);
}
spin_unlock_irqrestore(&pmu->lock, flags);
@@ -848,11 +924,20 @@ static const struct attribute_group i915_pmu_cpumask_attr_group = {
.attrs = i915_cpumask_attrs,
};
-#define __event(__config, __name, __unit) \
+#define __event(__counter, __name, __unit) \
{ \
- .config = (__config), \
+ .counter = (__counter), \
.name = (__name), \
.unit = (__unit), \
+ .global = false, \
+}
+
+#define __global_event(__counter, __name, __unit) \
+{ \
+ .counter = (__counter), \
+ .name = (__name), \
+ .unit = (__unit), \
+ .global = true, \
}
#define __engine_event(__sample, __name) \
@@ -891,15 +976,16 @@ create_event_attributes(struct i915_pmu *pmu)
{
struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
static const struct {
- u64 config;
+ unsigned int counter;
const char *name;
const char *unit;
+ bool global;
} events[] = {
- __event(I915_PMU_ACTUAL_FREQUENCY, "actual-frequency", "M"),
- __event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "M"),
- __event(I915_PMU_INTERRUPTS, "interrupts", NULL),
- __event(I915_PMU_RC6_RESIDENCY, "rc6-residency", "ns"),
- __event(I915_PMU_SOFTWARE_GT_AWAKE_TIME, "software-gt-awake-time", "ns"),
+ __event(0, "actual-frequency", "M"),
+ __event(1, "requested-frequency", "M"),
+ __global_event(2, "interrupts", NULL),
+ __event(3, "rc6-residency", "ns"),
+ __event(4, "software-gt-awake-time", "ns"),
};
static const struct {
enum drm_i915_pmu_engine_sample sample;
@@ -914,12 +1000,17 @@ create_event_attributes(struct i915_pmu *pmu)
struct i915_ext_attribute *i915_attr = NULL, *i915_iter;
struct attribute **attr = NULL, **attr_iter;
struct intel_engine_cs *engine;
- unsigned int i;
+ struct intel_gt *gt;
+ unsigned int i, j;
/* Count how many counters we will be exposing. */
- for (i = 0; i < ARRAY_SIZE(events); i++) {
- if (!config_status(i915, events[i].config))
- count++;
+ for_each_gt(gt, i915, j) {
+ for (i = 0; i < ARRAY_SIZE(events); i++) {
+ u64 config = ___I915_PMU_OTHER(j, events[i].counter);
+
+ if (!config_status(i915, config))
+ count++;
+ }
}
for_each_uabi_engine(engine, i915) {
@@ -949,26 +1040,39 @@ create_event_attributes(struct i915_pmu *pmu)
attr_iter = attr;
/* Initialize supported non-engine counters. */
- for (i = 0; i < ARRAY_SIZE(events); i++) {
- char *str;
-
- if (config_status(i915, events[i].config))
- continue;
-
- str = kstrdup(events[i].name, GFP_KERNEL);
- if (!str)
- goto err;
+ for_each_gt(gt, i915, j) {
+ for (i = 0; i < ARRAY_SIZE(events); i++) {
+ u64 config = ___I915_PMU_OTHER(j, events[i].counter);
+ char *str;
- *attr_iter++ = &i915_iter->attr.attr;
- i915_iter = add_i915_attr(i915_iter, str, events[i].config);
+ if (config_status(i915, config))
+ continue;
- if (events[i].unit) {
- str = kasprintf(GFP_KERNEL, "%s.unit", events[i].name);
+ if (events[i].global || !HAS_EXTRA_GT_LIST(i915))
+ str = kstrdup(events[i].name, GFP_KERNEL);
+ else
+ str = kasprintf(GFP_KERNEL, "%s-gt%u",
+ events[i].name, j);
if (!str)
goto err;
- *attr_iter++ = &pmu_iter->attr.attr;
- pmu_iter = add_pmu_attr(pmu_iter, str, events[i].unit);
+ *attr_iter++ = &i915_iter->attr.attr;
+ i915_iter = add_i915_attr(i915_iter, str, config);
+
+ if (events[i].unit) {
+ if (events[i].global || !HAS_EXTRA_GT_LIST(i915))
+ str = kasprintf(GFP_KERNEL, "%s.unit",
+ events[i].name);
+ else
+ str = kasprintf(GFP_KERNEL, "%s-gt%u.unit",
+ events[i].name, j);
+ if (!str)
+ goto err;
+
+ *attr_iter++ = &pmu_iter->attr.attr;
+ pmu_iter = add_pmu_attr(pmu_iter, str,
+ events[i].unit);
+ }
}
}
diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h
index 449057648f39..41af038c3738 100644
--- a/drivers/gpu/drm/i915/i915_pmu.h
+++ b/drivers/gpu/drm/i915/i915_pmu.h
@@ -13,8 +13,9 @@
#include <uapi/drm/i915_drm.h>
struct drm_i915_private;
+struct intel_gt;
-/**
+/*
* Non-engine events that we need to track enabled-disabled transition and
* current state.
*/
@@ -25,7 +26,7 @@ enum i915_pmu_tracked_events {
__I915_PMU_TRACKED_EVENT_COUNT, /* count marker */
};
-/**
+/*
* Slots used from the sampling timer (non-engine events) with some extras for
* convenience.
*/
@@ -37,13 +38,16 @@ enum {
__I915_NUM_PMU_SAMPLERS
};
-/**
+#define I915_PMU_MAX_GT 2
+
+/*
* How many different events we track in the global PMU mask.
*
* It is also used to know to needed number of event reference counters.
*/
#define I915_PMU_MASK_BITS \
- (I915_ENGINE_SAMPLE_COUNT + __I915_PMU_TRACKED_EVENT_COUNT)
+ (I915_ENGINE_SAMPLE_COUNT + \
+ I915_PMU_MAX_GT * __I915_PMU_TRACKED_EVENT_COUNT)
#define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1)
@@ -76,6 +80,10 @@ struct i915_pmu {
*/
spinlock_t lock;
/**
+ * @unparked: GT unparked mask.
+ */
+ unsigned int unparked;
+ /**
* @timer: Timer for internal i915 PMU sampling.
*/
struct hrtimer timer;
@@ -119,11 +127,11 @@ struct i915_pmu {
* Only global counters are held here, while the per-engine ones are in
* struct intel_engine_cs.
*/
- struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS];
+ struct i915_pmu_sample sample[I915_PMU_MAX_GT][__I915_NUM_PMU_SAMPLERS];
/**
* @sleep_last: Last time GT parked for RC6 estimation.
*/
- ktime_t sleep_last;
+ ktime_t sleep_last[I915_PMU_MAX_GT];
/**
* @irq_count: Number of interrupts
*
@@ -151,15 +159,15 @@ int i915_pmu_init(void);
void i915_pmu_exit(void);
void i915_pmu_register(struct drm_i915_private *i915);
void i915_pmu_unregister(struct drm_i915_private *i915);
-void i915_pmu_gt_parked(struct drm_i915_private *i915);
-void i915_pmu_gt_unparked(struct drm_i915_private *i915);
+void i915_pmu_gt_parked(struct intel_gt *gt);
+void i915_pmu_gt_unparked(struct intel_gt *gt);
#else
static inline int i915_pmu_init(void) { return 0; }
static inline void i915_pmu_exit(void) {}
static inline void i915_pmu_register(struct drm_i915_private *i915) {}
static inline void i915_pmu_unregister(struct drm_i915_private *i915) {}
-static inline void i915_pmu_gt_parked(struct drm_i915_private *i915) {}
-static inline void i915_pmu_gt_unparked(struct drm_i915_private *i915) {}
+static inline void i915_pmu_gt_parked(struct intel_gt *gt) {}
+static inline void i915_pmu_gt_unparked(struct intel_gt *gt) {}
#endif
#endif
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index c4197e31962e..7a4f462e8b70 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -941,6 +941,9 @@
#define HECI_H_GS1(base) _MMIO((base) + 0xc4c)
#define HECI_H_GS1_ER_PREP REG_BIT(0)
+#define HECI_FWSTS5(base) _MMIO((base) + 0xc68)
+#define HECI_FWSTS5_HUC_AUTH_DONE (1 << 19)
+
#define HSW_GTT_CACHE_EN _MMIO(0x4024)
#define GTT_CACHE_EN_ALL 0xF0007FFF
#define GEN7_WR_WATERMARK _MMIO(0x4028)
@@ -1343,9 +1346,9 @@
#define SNB_FBC_FRONT_BUFFER REG_BIT(1)
#define ILK_DISPLAY_CHICKEN1 _MMIO(0x42000)
-#define ILK_FBCQ_DIS (1 << 22)
-#define ILK_PABSTRETCH_DIS REG_BIT(21)
-#define ILK_SABSTRETCH_DIS REG_BIT(20)
+#define ILK_FBCQ_DIS REG_BIT(22)
+#define ILK_PABSTRETCH_DIS REG_BIT(21)
+#define ILK_SABSTRETCH_DIS REG_BIT(20)
#define IVB_PRI_STRETCH_MAX_MASK REG_GENMASK(21, 20)
#define IVB_PRI_STRETCH_MAX_X8 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 0)
#define IVB_PRI_STRETCH_MAX_X4 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 1)
@@ -1809,6 +1812,11 @@
#define CLKGATE_DIS_PSL_EXT(pipe) \
_MMIO_PIPE(pipe, _CLKGATE_DIS_PSL_EXT_A, _CLKGATE_DIS_PSL_EXT_B)
+/* DDI Buffer Control */
+#define _DDI_CLK_VALFREQ_A 0x64030
+#define _DDI_CLK_VALFREQ_B 0x64130
+#define DDI_CLK_VALFREQ(port) _MMIO_PORT(port, _DDI_CLK_VALFREQ_A, _DDI_CLK_VALFREQ_B)
+
/*
* Display engine regs
*/
@@ -1961,15 +1969,6 @@
#define _TRANS_VSYNC_DSI1 0x6b814
#define _TRANS_VSYNCSHIFT_DSI1 0x6b828
-#define TRANSCODER_A_OFFSET 0x60000
-#define TRANSCODER_B_OFFSET 0x61000
-#define TRANSCODER_C_OFFSET 0x62000
-#define CHV_TRANSCODER_C_OFFSET 0x63000
-#define TRANSCODER_D_OFFSET 0x63000
-#define TRANSCODER_EDP_OFFSET 0x6f000
-#define TRANSCODER_DSI0_OFFSET 0x6b000
-#define TRANSCODER_DSI1_OFFSET 0x6b800
-
#define TRANS_HTOTAL(trans) _MMIO_TRANS2((trans), _TRANS_HTOTAL_A)
#define TRANS_HBLANK(trans) _MMIO_TRANS2((trans), _TRANS_HBLANK_A)
#define TRANS_HSYNC(trans) _MMIO_TRANS2((trans), _TRANS_HSYNC_A)
@@ -2332,35 +2331,33 @@
/* Panel fitting */
#define PFIT_CONTROL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61230)
-#define PFIT_ENABLE (1 << 31)
-#define PFIT_PIPE_MASK (3 << 29)
-#define PFIT_PIPE_SHIFT 29
-#define PFIT_PIPE(pipe) ((pipe) << 29)
-#define VERT_INTERP_DISABLE (0 << 10)
-#define VERT_INTERP_BILINEAR (1 << 10)
-#define VERT_INTERP_MASK (3 << 10)
-#define VERT_AUTO_SCALE (1 << 9)
-#define HORIZ_INTERP_DISABLE (0 << 6)
-#define HORIZ_INTERP_BILINEAR (1 << 6)
-#define HORIZ_INTERP_MASK (3 << 6)
-#define HORIZ_AUTO_SCALE (1 << 5)
-#define PANEL_8TO6_DITHER_ENABLE (1 << 3)
-#define PFIT_FILTER_FUZZY (0 << 24)
-#define PFIT_SCALING_AUTO (0 << 26)
-#define PFIT_SCALING_PROGRAMMED (1 << 26)
-#define PFIT_SCALING_PILLAR (2 << 26)
-#define PFIT_SCALING_LETTER (3 << 26)
+#define PFIT_ENABLE REG_BIT(31)
+#define PFIT_PIPE_MASK REG_GENMASK(30, 29) /* 965+ */
+#define PFIT_PIPE(pipe) REG_FIELD_PREP(PFIT_PIPE_MASK, (pipe))
+#define PFIT_SCALING_MASK REG_GENMASK(28, 26) /* 965+ */
+#define PFIT_SCALING_AUTO REG_FIELD_PREP(PFIT_SCALING_MASK, 0)
+#define PFIT_SCALING_PROGRAMMED REG_FIELD_PREP(PFIT_SCALING_MASK, 1)
+#define PFIT_SCALING_PILLAR REG_FIELD_PREP(PFIT_SCALING_MASK, 2)
+#define PFIT_SCALING_LETTER REG_FIELD_PREP(PFIT_SCALING_MASK, 3)
+#define PFIT_FILTER_MASK REG_GENMASK(25, 24) /* 965+ */
+#define PFIT_FILTER_FUZZY REG_FIELD_PREP(PFIT_FILTER_MASK, 0)
+#define PFIT_FILTER_CRISP REG_FIELD_PREP(PFIT_FILTER_MASK, 1)
+#define PFIT_FILTER_MEDIAN REG_FIELD_PREP(PFIT_FILTER_MASK, 2)
+#define PFIT_VERT_INTERP_MASK REG_GENMASK(11, 10) /* pre-965 */
+#define PFIT_VERT_INTERP_BILINEAR REG_FIELD_PREP(PFIT_VERT_INTERP_MASK, 1)
+#define PFIT_VERT_AUTO_SCALE REG_BIT(9) /* pre-965 */
+#define PFIT_HORIZ_INTERP_MASK REG_GENMASK(7, 6) /* pre-965 */
+#define PFIT_HORIZ_INTERP_BILINEAR REG_FIELD_PREP(PFIT_HORIZ_INTERP_MASK, 1)
+#define PFIT_HORIZ_AUTO_SCALE REG_BIT(5) /* pre-965 */
+#define PFIT_PANEL_8TO6_DITHER_ENABLE REG_BIT(3) /* pre-965 */
+
#define PFIT_PGM_RATIOS _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61234)
-/* Pre-965 */
-#define PFIT_VERT_SCALE_SHIFT 20
-#define PFIT_VERT_SCALE_MASK 0xfff00000
-#define PFIT_HORIZ_SCALE_SHIFT 4
-#define PFIT_HORIZ_SCALE_MASK 0x0000fff0
-/* 965+ */
-#define PFIT_VERT_SCALE_SHIFT_965 16
-#define PFIT_VERT_SCALE_MASK_965 0x1fff0000
-#define PFIT_HORIZ_SCALE_SHIFT_965 0
-#define PFIT_HORIZ_SCALE_MASK_965 0x00001fff
+#define PFIT_VERT_SCALE_MASK REG_GENMASK(31, 20) /* pre-965 */
+#define PFIT_VERT_SCALE(x) REG_FIELD_PREP(PFIT_VERT_SCALE_MASK, (x))
+#define PFIT_HORIZ_SCALE_MASK REG_GENMASK(15, 4) /* pre-965 */
+#define PFIT_HORIZ_SCALE(x) REG_FIELD_PREP(PFIT_HORIZ_SCALE_MASK, (x))
+#define PFIT_VERT_SCALE_MASK_965 REG_GENMASK(28, 16) /* 965+ */
+#define PFIT_HORIZ_SCALE_MASK_965 REG_GENMASK(12, 0) /* 965+ */
#define PFIT_AUTO_RATIOS _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61238)
@@ -2550,6 +2547,7 @@
#define TRANSCONF_MSA_TIMING_DELAY_MASK REG_GENMASK(19, 18) /* ilk/snb/ivb */
#define TRANSCONF_MSA_TIMING_DELAY(x) REG_FIELD_PREP(TRANSCONF_MSA_TIMING_DELAY_MASK, (x))
#define TRANSCONF_CXSR_DOWNCLOCK REG_BIT(16)
+#define TRANSCONF_WGC_ENABLE REG_BIT(15) /* vlv/chv only */
#define TRANSCONF_REFRESH_RATE_ALT_VLV REG_BIT(14)
#define TRANSCONF_COLOR_RANGE_SELECT REG_BIT(13)
#define TRANSCONF_OUTPUT_COLORSPACE_MASK REG_GENMASK(12, 11) /* ilk-ivb */
@@ -2619,23 +2617,6 @@
#define PIPESTAT_INT_ENABLE_MASK 0x7fff0000
#define PIPESTAT_INT_STATUS_MASK 0x0000ffff
-#define PIPE_A_OFFSET 0x70000
-#define PIPE_B_OFFSET 0x71000
-#define PIPE_C_OFFSET 0x72000
-#define PIPE_D_OFFSET 0x73000
-#define CHV_PIPE_C_OFFSET 0x74000
-/*
- * There's actually no pipe EDP. Some pipe registers have
- * simply shifted from the pipe to the transcoder, while
- * keeping their original offset. Thus we need PIPE_EDP_OFFSET
- * to access such registers in transcoder EDP.
- */
-#define PIPE_EDP_OFFSET 0x7f000
-
-/* ICL DSI 0 and 1 */
-#define PIPE_DSI0_OFFSET 0x7b000
-#define PIPE_DSI1_OFFSET 0x7b800
-
#define TRANSCONF(trans) _MMIO_PIPE2((trans), _TRANSACONF)
#define PIPEDSL(pipe) _MMIO_PIPE2(pipe, _PIPEADSL)
#define PIPEFRAME(pipe) _MMIO_PIPE2(pipe, _PIPEAFRAMEHIGH)
@@ -2655,8 +2636,13 @@
#define PIPE_MISC_YUV420_ENABLE REG_BIT(27) /* glk+ */
#define PIPE_MISC_YUV420_MODE_FULL_BLEND REG_BIT(26) /* glk+ */
#define PIPE_MISC_HDR_MODE_PRECISION REG_BIT(23) /* icl+ */
+#define PIPE_MISC_PSR_MASK_PRIMARY_FLIP REG_BIT(23) /* bdw */
+#define PIPE_MISC_PSR_MASK_SPRITE_ENABLE REG_BIT(22) /* bdw */
+#define PIPE_MISC_PSR_MASK_PIPE_REG_WRITE REG_BIT(21) /* skl+ */
+#define PIPE_MISC_PSR_MASK_CURSOR_MOVE REG_BIT(21) /* bdw */
+#define PIPE_MISC_PSR_MASK_VBLANK_VSYNC_INT REG_BIT(20)
#define PIPE_MISC_OUTPUT_COLORSPACE_YUV REG_BIT(11)
-#define PIPE_MISC_PIXEL_ROUNDING_TRUNC REG_BIT(8) /* tgl+ */
+#define PIPE_MISC_PIXEL_ROUNDING_TRUNC REG_BIT(8) /* tgl+ */
/*
* For Display < 13, Bits 5-7 of PIPE MISC represent DITHER BPC with
* valid values of: 6, 8, 10 BPC.
@@ -3091,13 +3077,6 @@
#define CUR_CHICKEN(pipe) _MMIO_CURSOR2(pipe, _CUR_CHICKEN_A)
#define CURSURFLIVE(pipe) _MMIO_CURSOR2(pipe, _CURASURFLIVE)
-#define CURSOR_A_OFFSET 0x70080
-#define CURSOR_B_OFFSET 0x700c0
-#define CHV_CURSOR_C_OFFSET 0x700e0
-#define IVB_CURSOR_B_OFFSET 0x71080
-#define IVB_CURSOR_C_OFFSET 0x72080
-#define TGL_CURSOR_D_OFFSET 0x73080
-
/* Display A control */
#define _DSPAADDR_VLV 0x7017C /* vlv/chv */
#define _DSPACNTR 0x70180
@@ -4005,20 +3984,28 @@
/* CPU panel fitter */
/* IVB+ has 3 fitters, 0 is 7x5 capable, the other two only 3x3 */
-#define _PFA_CTL_1 0x68080
-#define _PFB_CTL_1 0x68880
-#define PF_ENABLE (1 << 31)
-#define PF_PIPE_SEL_MASK_IVB (3 << 29)
-#define PF_PIPE_SEL_IVB(pipe) ((pipe) << 29)
-#define PF_FILTER_MASK (3 << 23)
-#define PF_FILTER_PROGRAMMED (0 << 23)
-#define PF_FILTER_MED_3x3 (1 << 23)
-#define PF_FILTER_EDGE_ENHANCE (2 << 23)
-#define PF_FILTER_EDGE_SOFTEN (3 << 23)
+#define _PFA_CTL_1 0x68080
+#define _PFB_CTL_1 0x68880
+#define PF_ENABLE REG_BIT(31)
+#define PF_PIPE_SEL_MASK_IVB REG_GENMASK(30, 29) /* ivb/hsw */
+#define PF_PIPE_SEL_IVB(pipe) REG_FIELD_PREP(PF_PIPE_SEL_MASK_IVB, (pipe))
+#define PF_FILTER_MASK REG_GENMASK(24, 23)
+#define PF_FILTER_PROGRAMMED REG_FIELD_PREP(PF_FILTER_MASK, 0)
+#define PF_FILTER_MED_3x3 REG_FIELD_PREP(PF_FILTER_MASK, 1)
+#define PF_FILTER_EDGE_ENHANCE REG_FIELD_PREP(PF_FILTER_EDGE_MASK, 2)
+#define PF_FILTER_EDGE_SOFTEN REG_FIELD_PREP(PF_FILTER_EDGE_MASK, 3)
#define _PFA_WIN_SZ 0x68074
#define _PFB_WIN_SZ 0x68874
+#define PF_WIN_XSIZE_MASK REG_GENMASK(31, 16)
+#define PF_WIN_XSIZE(w) REG_FIELD_PREP(PF_WIN_XSIZE_MASK, (w))
+#define PF_WIN_YSIZE_MASK REG_GENMASK(15, 0)
+#define PF_WIN_YSIZE(h) REG_FIELD_PREP(PF_WIN_YSIZE_MASK, (h))
#define _PFA_WIN_POS 0x68070
#define _PFB_WIN_POS 0x68870
+#define PF_WIN_XPOS_MASK REG_GENMASK(31, 16)
+#define PF_WIN_XPOS(x) REG_FIELD_PREP(PF_WIN_XPOS_MASK, (x))
+#define PF_WIN_YPOS_MASK REG_GENMASK(15, 0)
+#define PF_WIN_YPOS(y) REG_FIELD_PREP(PF_WIN_YPOS_MASK, (y))
#define _PFA_VSCALE 0x68084
#define _PFB_VSCALE 0x68884
#define _PFA_HSCALE 0x68090
@@ -4030,18 +4017,6 @@
#define PF_VSCALE(pipe) _MMIO_PIPE(pipe, _PFA_VSCALE, _PFB_VSCALE)
#define PF_HSCALE(pipe) _MMIO_PIPE(pipe, _PFA_HSCALE, _PFB_HSCALE)
-#define _PSA_CTL 0x68180
-#define _PSB_CTL 0x68980
-#define PS_ENABLE (1 << 31)
-#define _PSA_WIN_SZ 0x68174
-#define _PSB_WIN_SZ 0x68974
-#define _PSA_WIN_POS 0x68170
-#define _PSB_WIN_POS 0x68970
-
-#define PS_CTL(pipe) _MMIO_PIPE(pipe, _PSA_CTL, _PSB_CTL)
-#define PS_WIN_SZ(pipe) _MMIO_PIPE(pipe, _PSA_WIN_SZ, _PSB_WIN_SZ)
-#define PS_WIN_POS(pipe) _MMIO_PIPE(pipe, _PSA_WIN_POS, _PSB_WIN_POS)
-
/*
* Skylake scalers
*/
@@ -4050,63 +4025,89 @@
#define _PS_1B_CTRL 0x68980
#define _PS_2B_CTRL 0x68A80
#define _PS_1C_CTRL 0x69180
-#define PS_SCALER_EN (1 << 31)
-#define SKL_PS_SCALER_MODE_MASK (3 << 28)
-#define SKL_PS_SCALER_MODE_DYN (0 << 28)
-#define SKL_PS_SCALER_MODE_HQ (1 << 28)
-#define SKL_PS_SCALER_MODE_NV12 (2 << 28)
-#define PS_SCALER_MODE_PLANAR (1 << 29)
-#define PS_SCALER_MODE_NORMAL (0 << 29)
-#define PS_PLANE_SEL_MASK (7 << 25)
-#define PS_PLANE_SEL(plane) (((plane) + 1) << 25)
-#define PS_FILTER_MASK (3 << 23)
-#define PS_FILTER_MEDIUM (0 << 23)
-#define PS_FILTER_PROGRAMMED (1 << 23)
-#define PS_FILTER_EDGE_ENHANCE (2 << 23)
-#define PS_FILTER_BILINEAR (3 << 23)
-#define PS_VERT3TAP (1 << 21)
-#define PS_VERT_INT_INVERT_FIELD1 (0 << 20)
-#define PS_VERT_INT_INVERT_FIELD0 (1 << 20)
-#define PS_PWRUP_PROGRESS (1 << 17)
-#define PS_V_FILTER_BYPASS (1 << 8)
-#define PS_VADAPT_EN (1 << 7)
-#define PS_VADAPT_MODE_MASK (3 << 5)
-#define PS_VADAPT_MODE_LEAST_ADAPT (0 << 5)
-#define PS_VADAPT_MODE_MOD_ADAPT (1 << 5)
-#define PS_VADAPT_MODE_MOST_ADAPT (3 << 5)
-#define PS_PLANE_Y_SEL_MASK (7 << 5)
-#define PS_PLANE_Y_SEL(plane) (((plane) + 1) << 5)
-#define PS_Y_VERT_FILTER_SELECT(set) ((set) << 4)
-#define PS_Y_HORZ_FILTER_SELECT(set) ((set) << 3)
-#define PS_UV_VERT_FILTER_SELECT(set) ((set) << 2)
-#define PS_UV_HORZ_FILTER_SELECT(set) ((set) << 1)
+#define PS_SCALER_EN REG_BIT(31)
+#define PS_SCALER_TYPE_MASK REG_BIT(30) /* icl+ */
+#define PS_SCALER_TYPE_NON_LINEAR REG_FIELD_PREP(PS_SCALER_TYPE_MASK, 0)
+#define PS_SCALER_TYPE_LINEAR REG_FIELD_PREP(PS_SCALER_TYPE_MASK, 1)
+#define SKL_PS_SCALER_MODE_MASK REG_GENMASK(29, 28) /* skl/bxt */
+#define SKL_PS_SCALER_MODE_DYN REG_FIELD_PREP(SKL_PS_SCALER_MODE_MASK, 0)
+#define SKL_PS_SCALER_MODE_HQ REG_FIELD_PREP(SKL_PS_SCALER_MODE_MASK, 1)
+#define SKL_PS_SCALER_MODE_NV12 REG_FIELD_PREP(SKL_PS_SCALER_MODE_MASK, 2)
+#define PS_SCALER_MODE_MASK REG_BIT(29) /* glk-tgl */
+#define PS_SCALER_MODE_NORMAL REG_FIELD_PREP(PS_SCALER_MODE_MASK, 0)
+#define PS_SCALER_MODE_PLANAR REG_FIELD_PREP(PS_SCALER_MODE_MASK, 1)
+#define PS_ADAPTIVE_FILTERING_EN REG_BIT(28) /* icl+ */
+#define PS_BINDING_MASK REG_GENMASK(27, 25)
+#define PS_BINDING_PIPE REG_FIELD_PREP(PS_BINDING_MASK, 0)
+#define PS_BINDING_PLANE(plane_id) REG_FIELD_PREP(PS_BINDING_MASK, (plane_id) + 1)
+#define PS_FILTER_MASK REG_GENMASK(24, 23)
+#define PS_FILTER_MEDIUM REG_FIELD_PREP(PS_FILTER_MASK, 0)
+#define PS_FILTER_PROGRAMMED REG_FIELD_PREP(PS_FILTER_MASK, 1)
+#define PS_FILTER_EDGE_ENHANCE REG_FIELD_PREP(PS_FILTER_MASK, 2)
+#define PS_FILTER_BILINEAR REG_FIELD_PREP(PS_FILTER_MASK, 3)
+#define PS_ADAPTIVE_FILTER_MASK REG_BIT(22) /* icl+ */
+#define PS_ADAPTIVE_FILTER_MEDIUM REG_FIELD_PREP(PS_ADAPTIVE_FILTER_MASK, 0)
+#define PS_ADAPTIVE_FILTER_EDGE_ENHANCE REG_FIELD_PREP(PS_ADAPTIVE_FILTER_MASK, 1)
+#define PS_PIPE_SCALER_LOC_MASK REG_BIT(21) /* icl+ */
+#define PS_PIPE_SCALER_LOC_AFTER_OUTPUT_CSC REG_FIELD_PREP(PS_SCALER_LOCATION_MASK, 0) /* non-linear */
+#define PS_PIPE_SCALER_LOC_AFTER_CSC REG_FIELD_PREP(PS_SCALER_LOCATION_MASK, 1) /* linear */
+#define PS_VERT3TAP REG_BIT(21) /* skl/bxt */
+#define PS_VERT_INT_INVERT_FIELD REG_BIT(20)
+#define PS_PROG_SCALE_FACTOR REG_BIT(19) /* tgl+ */
+#define PS_PWRUP_PROGRESS REG_BIT(17)
+#define PS_V_FILTER_BYPASS REG_BIT(8)
+#define PS_VADAPT_EN REG_BIT(7) /* skl/bxt */
+#define PS_VADAPT_MODE_MASK REG_GENMASK(6, 5) /* skl/bxt */
+#define PS_VADAPT_MODE_LEAST_ADAPT REG_FIELD_PREP(PS_VADAPT_MODE_MASK, 0)
+#define PS_VADAPT_MODE_MOD_ADAPT REG_FIELD_PREP(PS_VADAPT_MODE_MASK, 1)
+#define PS_VADAPT_MODE_MOST_ADAPT REG_FIELD_PREP(PS_VADAPT_MODE_MASK, 3)
+#define PS_BINDING_Y_MASK REG_GENMASK(7, 5) /* icl-tgl */
+#define PS_BINDING_Y_PLANE(plane_id) REG_FIELD_PREP(PS_BINDING_Y_MASK, (plane_id) + 1)
+#define PS_Y_VERT_FILTER_SELECT_MASK REG_BIT(4) /* glk+ */
+#define PS_Y_VERT_FILTER_SELECT(set) REG_FIELD_PREP(PS_Y_VERT_FILTER_SELECT_MASK, (set))
+#define PS_Y_HORZ_FILTER_SELECT_MASK REG_BIT(3) /* glk+ */
+#define PS_Y_HORZ_FILTER_SELECT(set) REG_FIELD_PREP(PS_Y_HORZ_FILTER_SELECT_MASK, (set))
+#define PS_UV_VERT_FILTER_SELECT_MASK REG_BIT(2) /* glk+ */
+#define PS_UV_VERT_FILTER_SELECT(set) REG_FIELD_PREP(PS_UV_VERT_FILTER_SELECT_MASK, (set))
+#define PS_UV_HORZ_FILTER_SELECT_MASK REG_BIT(1) /* glk+ */
+#define PS_UV_HORZ_FILTER_SELECT(set) REG_FIELD_PREP(PS_UV_HORZ_FILTER_SELECT_MASK, (set))
#define _PS_PWR_GATE_1A 0x68160
#define _PS_PWR_GATE_2A 0x68260
#define _PS_PWR_GATE_1B 0x68960
#define _PS_PWR_GATE_2B 0x68A60
#define _PS_PWR_GATE_1C 0x69160
-#define PS_PWR_GATE_DIS_OVERRIDE (1 << 31)
-#define PS_PWR_GATE_SETTLING_TIME_32 (0 << 3)
-#define PS_PWR_GATE_SETTLING_TIME_64 (1 << 3)
-#define PS_PWR_GATE_SETTLING_TIME_96 (2 << 3)
-#define PS_PWR_GATE_SETTLING_TIME_128 (3 << 3)
-#define PS_PWR_GATE_SLPEN_8 0
-#define PS_PWR_GATE_SLPEN_16 1
-#define PS_PWR_GATE_SLPEN_24 2
-#define PS_PWR_GATE_SLPEN_32 3
+#define PS_PWR_GATE_DIS_OVERRIDE REG_BIT(31)
+#define PS_PWR_GATE_SETTLING_TIME_MASK REG_GENMASK(4, 3)
+#define PS_PWR_GATE_SETTLING_TIME_32 REG_FIELD_PREP(PS_PWR_GATE_SETTLING_TIME_MASK, 0)
+#define PS_PWR_GATE_SETTLING_TIME_64 REG_FIELD_PREP(PS_PWR_GATE_SETTLING_TIME_MASK, 1)
+#define PS_PWR_GATE_SETTLING_TIME_96 REG_FIELD_PREP(PS_PWR_GATE_SETTLING_TIME_MASK, 2)
+#define PS_PWR_GATE_SETTLING_TIME_128 REG_FIELD_PREP(PS_PWR_GATE_SETTLING_TIME_MASK, 3)
+#define PS_PWR_GATE_SLPEN_MASK REG_GENMASK(1, 0)
+#define PS_PWR_GATE_SLPEN_8 REG_FIELD_PREP(PS_PWR_GATE_SLPEN_MASK, 0)
+#define PS_PWR_GATE_SLPEN_16 REG_FIELD_PREP(PS_PWR_GATE_SLPEN_MASK, 1)
+#define PS_PWR_GATE_SLPEN_24 REG_FIELD_PREP(PS_PWR_GATE_SLPEN_MASK, 2)
+#define PS_PWR_GATE_SLPEN_32 REG_FIELD_PREP(PS_PWR_GATE_SLPEN_MASK, 3)
#define _PS_WIN_POS_1A 0x68170
#define _PS_WIN_POS_2A 0x68270
#define _PS_WIN_POS_1B 0x68970
#define _PS_WIN_POS_2B 0x68A70
#define _PS_WIN_POS_1C 0x69170
+#define PS_WIN_XPOS_MASK REG_GENMASK(31, 16)
+#define PS_WIN_XPOS(x) REG_FIELD_PREP(PS_WIN_XPOS_MASK, (x))
+#define PS_WIN_YPOS_MASK REG_GENMASK(15, 0)
+#define PS_WIN_YPOS(y) REG_FIELD_PREP(PS_WIN_YPOS_MASK, (y))
#define _PS_WIN_SZ_1A 0x68174
#define _PS_WIN_SZ_2A 0x68274
#define _PS_WIN_SZ_1B 0x68974
#define _PS_WIN_SZ_2B 0x68A74
#define _PS_WIN_SZ_1C 0x69174
+#define PS_WIN_XSIZE_MASK REG_GENMASK(31, 16)
+#define PS_WIN_XSIZE(w) REG_FIELD_PREP(PS_WIN_XSIZE_MASK, (w))
+#define PS_WIN_YSIZE_MASK REG_GENMASK(15, 0)
+#define PS_WIN_YSIZE(h) REG_FIELD_PREP(PS_WIN_YSIZE_MASK, (h))
#define _PS_VSCALE_1A 0x68184
#define _PS_VSCALE_2A 0x68284
@@ -4125,10 +4126,12 @@
#define _PS_VPHASE_1B 0x68988
#define _PS_VPHASE_2B 0x68A88
#define _PS_VPHASE_1C 0x69188
-#define PS_Y_PHASE(x) ((x) << 16)
-#define PS_UV_RGB_PHASE(x) ((x) << 0)
-#define PS_PHASE_MASK (0x7fff << 1) /* u2.13 */
-#define PS_PHASE_TRIP (1 << 0)
+#define PS_Y_PHASE_MASK REG_GENMASK(31, 16)
+#define PS_Y_PHASE(x) REG_FIELD_PREP(PS_Y_PHASE_MASK, (x))
+#define PS_UV_RGB_PHASE_MASK REG_GENMASK(15, 0)
+#define PS_UV_RGB_PHASE(x) REG_FIELD_PREP(PS_UV_RGB_PHASE_MASK, (x))
+#define PS_PHASE_MASK (0x7fff << 1) /* u2.13 */
+#define PS_PHASE_TRIP (1 << 0)
#define _PS_HPHASE_1A 0x68194
#define _PS_HPHASE_2A 0x68294
@@ -4146,7 +4149,7 @@
#define _PS_COEF_SET0_INDEX_2A 0x68298
#define _PS_COEF_SET0_INDEX_1B 0x68998
#define _PS_COEF_SET0_INDEX_2B 0x68A98
-#define PS_COEE_INDEX_AUTO_INC (1 << 10)
+#define PS_COEF_INDEX_AUTO_INC REG_BIT(10)
#define _PS_COEF_SET0_DATA_1A 0x6819C
#define _PS_COEF_SET0_DATA_2A 0x6829C
@@ -4418,8 +4421,10 @@
#define GEN8_DE_MISC_IMR _MMIO(0x44464)
#define GEN8_DE_MISC_IIR _MMIO(0x44468)
#define GEN8_DE_MISC_IER _MMIO(0x4446c)
-#define GEN8_DE_MISC_GSE (1 << 27)
-#define GEN8_DE_EDP_PSR (1 << 19)
+#define XELPDP_PMDEMAND_RSPTOUT_ERR REG_BIT(27)
+#define GEN8_DE_MISC_GSE REG_BIT(27)
+#define GEN8_DE_EDP_PSR REG_BIT(19)
+#define XELPDP_PMDEMAND_RSP REG_BIT(3)
#define GEN8_PCU_ISR _MMIO(0x444e0)
#define GEN8_PCU_IMR _MMIO(0x444e4)
@@ -4482,56 +4487,96 @@
#define GEN11_HOTPLUG_CTL_SHORT_DETECT(hpd_pin) (1 << (_HPD_PIN_TC(hpd_pin) * 4))
#define GEN11_HOTPLUG_CTL_NO_DETECT(hpd_pin) (0 << (_HPD_PIN_TC(hpd_pin) * 4))
+#define PICAINTERRUPT_ISR _MMIO(0x16FE50)
+#define PICAINTERRUPT_IMR _MMIO(0x16FE54)
+#define PICAINTERRUPT_IIR _MMIO(0x16FE58)
+#define PICAINTERRUPT_IER _MMIO(0x16FE5C)
+
+#define XELPDP_DP_ALT_HOTPLUG(hpd_pin) REG_BIT(16 + _HPD_PIN_TC(hpd_pin))
+#define XELPDP_DP_ALT_HOTPLUG_MASK REG_GENMASK(19, 16)
+
+#define XELPDP_AUX_TC(hpd_pin) REG_BIT(8 + _HPD_PIN_TC(hpd_pin))
+#define XELPDP_AUX_TC_MASK REG_GENMASK(11, 8)
+
+#define XELPDP_TBT_HOTPLUG(hpd_pin) REG_BIT(_HPD_PIN_TC(hpd_pin))
+#define XELPDP_TBT_HOTPLUG_MASK REG_GENMASK(3, 0)
+
+#define XELPDP_PORT_HOTPLUG_CTL(hpd_pin) _MMIO(0x16F270 + (_HPD_PIN_TC(hpd_pin) * 0x200))
+#define XELPDP_TBT_HOTPLUG_ENABLE REG_BIT(6)
+#define XELPDP_TBT_HPD_LONG_DETECT REG_BIT(5)
+#define XELPDP_TBT_HPD_SHORT_DETECT REG_BIT(4)
+#define XELPDP_DP_ALT_HOTPLUG_ENABLE REG_BIT(2)
+#define XELPDP_DP_ALT_HPD_LONG_DETECT REG_BIT(1)
+#define XELPDP_DP_ALT_HPD_SHORT_DETECT REG_BIT(0)
+
+#define XELPDP_INITIATE_PMDEMAND_REQUEST(dword) _MMIO(0x45230 + 4 * (dword))
+#define XELPDP_PMDEMAND_QCLK_GV_BW_MASK REG_GENMASK(31, 16)
+#define XELPDP_PMDEMAND_VOLTAGE_INDEX_MASK REG_GENMASK(14, 12)
+#define XELPDP_PMDEMAND_QCLK_GV_INDEX_MASK REG_GENMASK(11, 8)
+#define XELPDP_PMDEMAND_PIPES_MASK REG_GENMASK(7, 6)
+#define XELPDP_PMDEMAND_DBUFS_MASK REG_GENMASK(5, 4)
+#define XELPDP_PMDEMAND_PHYS_MASK REG_GENMASK(2, 0)
+
+#define XELPDP_PMDEMAND_REQ_ENABLE REG_BIT(31)
+#define XELPDP_PMDEMAND_CDCLK_FREQ_MASK REG_GENMASK(30, 20)
+#define XELPDP_PMDEMAND_DDICLK_FREQ_MASK REG_GENMASK(18, 8)
+#define XELPDP_PMDEMAND_SCALERS_MASK REG_GENMASK(6, 4)
+#define XELPDP_PMDEMAND_PLLS_MASK REG_GENMASK(2, 0)
+
+#define GEN12_DCPR_STATUS_1 _MMIO(0x46440)
+#define XELPDP_PMDEMAND_INFLIGHT_STATUS REG_BIT(26)
+
#define ILK_DISPLAY_CHICKEN2 _MMIO(0x42004)
/* Required on all Ironlake and Sandybridge according to the B-Spec. */
-#define ILK_ELPIN_409_SELECT (1 << 25)
-#define ILK_DPARB_GATE (1 << 22)
-#define ILK_VSDPFD_FULL (1 << 21)
-#define FUSE_STRAP _MMIO(0x42014)
-#define ILK_INTERNAL_GRAPHICS_DISABLE (1 << 31)
-#define ILK_INTERNAL_DISPLAY_DISABLE (1 << 30)
-#define ILK_DISPLAY_DEBUG_DISABLE (1 << 29)
-#define IVB_PIPE_C_DISABLE (1 << 28)
-#define ILK_HDCP_DISABLE (1 << 25)
-#define ILK_eDP_A_DISABLE (1 << 24)
-#define HSW_CDCLK_LIMIT (1 << 24)
-#define ILK_DESKTOP (1 << 23)
-#define HSW_CPU_SSC_ENABLE (1 << 21)
-
-#define FUSE_STRAP3 _MMIO(0x42020)
-#define HSW_REF_CLK_SELECT (1 << 1)
-
-#define ILK_DSPCLK_GATE_D _MMIO(0x42020)
-#define ILK_VRHUNIT_CLOCK_GATE_DISABLE (1 << 28)
-#define ILK_DPFCUNIT_CLOCK_GATE_DISABLE (1 << 9)
-#define ILK_DPFCRUNIT_CLOCK_GATE_DISABLE (1 << 8)
-#define ILK_DPFDUNIT_CLOCK_GATE_ENABLE (1 << 7)
-#define ILK_DPARBUNIT_CLOCK_GATE_ENABLE (1 << 5)
-
-#define IVB_CHICKEN3 _MMIO(0x4200c)
-# define CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE (1 << 5)
-# define CHICKEN3_DGMG_DONE_FIX_DISABLE (1 << 2)
-
-#define CHICKEN_PAR1_1 _MMIO(0x42080)
-#define IGNORE_KVMR_PIPE_A REG_BIT(23)
-#define KBL_ARB_FILL_SPARE_22 REG_BIT(22)
-#define DIS_RAM_BYPASS_PSR2_MAN_TRACK (1 << 16)
-#define SKL_DE_COMPRESSED_HASH_MODE (1 << 15)
-#define DPA_MASK_VBLANK_SRD (1 << 15)
-#define FORCE_ARB_IDLE_PLANES (1 << 14)
-#define SKL_EDP_PSR_FIX_RDWRAP (1 << 3)
-#define IGNORE_PSR2_HW_TRACKING (1 << 1)
+#define ILK_ELPIN_409_SELECT REG_BIT(25)
+#define ILK_DPARB_GATE REG_BIT(22)
+#define ILK_VSDPFD_FULL REG_BIT(21)
+
+#define FUSE_STRAP _MMIO(0x42014)
+#define ILK_INTERNAL_GRAPHICS_DISABLE REG_BIT(31)
+#define ILK_INTERNAL_DISPLAY_DISABLE REG_BIT(30)
+#define ILK_DISPLAY_DEBUG_DISABLE REG_BIT(29)
+#define IVB_PIPE_C_DISABLE REG_BIT(28)
+#define ILK_HDCP_DISABLE REG_BIT(25)
+#define ILK_eDP_A_DISABLE REG_BIT(24)
+#define HSW_CDCLK_LIMIT REG_BIT(24)
+#define ILK_DESKTOP REG_BIT(23)
+#define HSW_CPU_SSC_ENABLE REG_BIT(21)
+
+#define FUSE_STRAP3 _MMIO(0x42020)
+#define HSW_REF_CLK_SELECT REG_BIT(1)
+
+#define ILK_DSPCLK_GATE_D _MMIO(0x42020)
+#define ILK_VRHUNIT_CLOCK_GATE_DISABLE REG_BIT(28)
+#define ILK_DPFCUNIT_CLOCK_GATE_DISABLE REG_BIT(9)
+#define ILK_DPFCRUNIT_CLOCK_GATE_DISABLE REG_BIT(8)
+#define ILK_DPFDUNIT_CLOCK_GATE_ENABLE REG_BIT(7)
+#define ILK_DPARBUNIT_CLOCK_GATE_ENABLE REG_BIT(5)
+
+#define IVB_CHICKEN3 _MMIO(0x4200c)
+#define CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE REG_BIT(5)
+#define CHICKEN3_DGMG_DONE_FIX_DISABLE REG_BIT(2)
+
+#define CHICKEN_PAR1_1 _MMIO(0x42080)
+#define IGNORE_KVMR_PIPE_A REG_BIT(23)
+#define KBL_ARB_FILL_SPARE_22 REG_BIT(22)
+#define DIS_RAM_BYPASS_PSR2_MAN_TRACK REG_BIT(16)
+#define SKL_DE_COMPRESSED_HASH_MODE REG_BIT(15)
+#define HSW_MASK_VBL_TO_PIPE_IN_SRD REG_BIT(15) /* hsw/bdw */
+#define FORCE_ARB_IDLE_PLANES REG_BIT(14)
+#define SKL_EDP_PSR_FIX_RDWRAP REG_BIT(3)
+#define IGNORE_PSR2_HW_TRACKING REG_BIT(1)
#define CHICKEN_PAR2_1 _MMIO(0x42090)
-#define KVM_CONFIG_CHANGE_NOTIFICATION_SELECT (1 << 14)
+#define KVM_CONFIG_CHANGE_NOTIFICATION_SELECT REG_BIT(14)
#define CHICKEN_MISC_2 _MMIO(0x42084)
-#define CHICKEN_MISC_DISABLE_DPT REG_BIT(30) /* adl,dg2 */
-#define KBL_ARB_FILL_SPARE_14 REG_BIT(14)
-#define KBL_ARB_FILL_SPARE_13 REG_BIT(13)
-#define GLK_CL2_PWR_DOWN (1 << 12)
-#define GLK_CL1_PWR_DOWN (1 << 11)
-#define GLK_CL0_PWR_DOWN (1 << 10)
+#define CHICKEN_MISC_DISABLE_DPT REG_BIT(30) /* adl,dg2 */
+#define KBL_ARB_FILL_SPARE_14 REG_BIT(14)
+#define KBL_ARB_FILL_SPARE_13 REG_BIT(13)
+#define GLK_CL2_PWR_DOWN REG_BIT(12)
+#define GLK_CL1_PWR_DOWN REG_BIT(11)
+#define GLK_CL0_PWR_DOWN REG_BIT(10)
#define CHICKEN_MISC_4 _MMIO(0x4208c)
#define CHICKEN_FBC_STRIDE_OVERRIDE REG_BIT(13)
@@ -4540,24 +4585,26 @@
#define _CHICKEN_PIPESL_1_A 0x420b0
#define _CHICKEN_PIPESL_1_B 0x420b4
-#define HSW_PRI_STRETCH_MAX_MASK REG_GENMASK(28, 27)
-#define HSW_PRI_STRETCH_MAX_X8 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 0)
-#define HSW_PRI_STRETCH_MAX_X4 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 1)
-#define HSW_PRI_STRETCH_MAX_X2 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 2)
-#define HSW_PRI_STRETCH_MAX_X1 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 3)
-#define HSW_SPR_STRETCH_MAX_MASK REG_GENMASK(26, 25)
-#define HSW_SPR_STRETCH_MAX_X8 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 0)
-#define HSW_SPR_STRETCH_MAX_X4 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 1)
-#define HSW_SPR_STRETCH_MAX_X2 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 2)
-#define HSW_SPR_STRETCH_MAX_X1 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 3)
-#define HSW_FBCQ_DIS (1 << 22)
-#define BDW_DPRS_MASK_VBLANK_SRD (1 << 0)
-#define SKL_PLANE1_STRETCH_MAX_MASK REG_GENMASK(1, 0)
-#define SKL_PLANE1_STRETCH_MAX_X8 REG_FIELD_PREP(SKL_PLANE1_STRETCH_MAX_MASK, 0)
-#define SKL_PLANE1_STRETCH_MAX_X4 REG_FIELD_PREP(SKL_PLANE1_STRETCH_MAX_MASK, 1)
-#define SKL_PLANE1_STRETCH_MAX_X2 REG_FIELD_PREP(SKL_PLANE1_STRETCH_MAX_MASK, 2)
-#define SKL_PLANE1_STRETCH_MAX_X1 REG_FIELD_PREP(SKL_PLANE1_STRETCH_MAX_MASK, 3)
-#define CHICKEN_PIPESL_1(pipe) _MMIO_PIPE(pipe, _CHICKEN_PIPESL_1_A, _CHICKEN_PIPESL_1_B)
+#define CHICKEN_PIPESL_1(pipe) _MMIO_PIPE(pipe, _CHICKEN_PIPESL_1_A, _CHICKEN_PIPESL_1_B)
+#define HSW_PRI_STRETCH_MAX_MASK REG_GENMASK(28, 27)
+#define HSW_PRI_STRETCH_MAX_X8 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 0)
+#define HSW_PRI_STRETCH_MAX_X4 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 1)
+#define HSW_PRI_STRETCH_MAX_X2 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 2)
+#define HSW_PRI_STRETCH_MAX_X1 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 3)
+#define HSW_SPR_STRETCH_MAX_MASK REG_GENMASK(26, 25)
+#define HSW_SPR_STRETCH_MAX_X8 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 0)
+#define HSW_SPR_STRETCH_MAX_X4 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 1)
+#define HSW_SPR_STRETCH_MAX_X2 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 2)
+#define HSW_SPR_STRETCH_MAX_X1 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 3)
+#define HSW_FBCQ_DIS REG_BIT(22)
+#define HSW_UNMASK_VBL_TO_REGS_IN_SRD REG_BIT(15) /* hsw */
+#define SKL_PSR_MASK_PLANE_FLIP REG_BIT(11) /* skl+ */
+#define SKL_PLANE1_STRETCH_MAX_MASK REG_GENMASK(1, 0)
+#define SKL_PLANE1_STRETCH_MAX_X8 REG_FIELD_PREP(SKL_PLANE1_STRETCH_MAX_MASK, 0)
+#define SKL_PLANE1_STRETCH_MAX_X4 REG_FIELD_PREP(SKL_PLANE1_STRETCH_MAX_MASK, 1)
+#define SKL_PLANE1_STRETCH_MAX_X2 REG_FIELD_PREP(SKL_PLANE1_STRETCH_MAX_MASK, 2)
+#define SKL_PLANE1_STRETCH_MAX_X1 REG_FIELD_PREP(SKL_PLANE1_STRETCH_MAX_MASK, 3)
+#define BDW_UNMASK_VBL_TO_REGS_IN_SRD REG_BIT(0) /* bdw */
#define _CHICKEN_TRANS_A 0x420c0
#define _CHICKEN_TRANS_B 0x420c4
@@ -4570,32 +4617,33 @@
[TRANSCODER_B] = _CHICKEN_TRANS_B, \
[TRANSCODER_C] = _CHICKEN_TRANS_C, \
[TRANSCODER_D] = _CHICKEN_TRANS_D))
-
#define _MTL_CHICKEN_TRANS_A 0x604e0
#define _MTL_CHICKEN_TRANS_B 0x614e0
#define MTL_CHICKEN_TRANS(trans) _MMIO_TRANS((trans), \
_MTL_CHICKEN_TRANS_A, \
_MTL_CHICKEN_TRANS_B)
-
-#define HSW_FRAME_START_DELAY_MASK REG_GENMASK(28, 27)
-#define HSW_FRAME_START_DELAY(x) REG_FIELD_PREP(HSW_FRAME_START_DELAY_MASK, x)
-#define VSC_DATA_SEL_SOFTWARE_CONTROL REG_BIT(25) /* GLK */
-#define FECSTALL_DIS_DPTSTREAM_DPTTG REG_BIT(23)
-#define DDI_TRAINING_OVERRIDE_ENABLE REG_BIT(19)
-#define ADLP_1_BASED_X_GRANULARITY REG_BIT(18)
-#define DDI_TRAINING_OVERRIDE_VALUE REG_BIT(18)
-#define DDIE_TRAINING_OVERRIDE_ENABLE REG_BIT(17) /* CHICKEN_TRANS_A only */
-#define DDIE_TRAINING_OVERRIDE_VALUE REG_BIT(16) /* CHICKEN_TRANS_A only */
-#define PSR2_ADD_VERTICAL_LINE_COUNT REG_BIT(15)
-#define PSR2_VSC_ENABLE_PROG_HEADER REG_BIT(12)
+#define PIPE_VBLANK_WITH_DELAY REG_BIT(31) /* ADL/DG2 */
+#define SKL_UNMASK_VBL_TO_PIPE_IN_SRD REG_BIT(30) /* skl+ */
+#define HSW_FRAME_START_DELAY_MASK REG_GENMASK(28, 27)
+#define HSW_FRAME_START_DELAY(x) REG_FIELD_PREP(HSW_FRAME_START_DELAY_MASK, x)
+#define VSC_DATA_SEL_SOFTWARE_CONTROL REG_BIT(25) /* GLK */
+#define FECSTALL_DIS_DPTSTREAM_DPTTG REG_BIT(23)
+#define DDI_TRAINING_OVERRIDE_ENABLE REG_BIT(19)
+#define ADLP_1_BASED_X_GRANULARITY REG_BIT(18)
+#define DDI_TRAINING_OVERRIDE_VALUE REG_BIT(18)
+#define DDIE_TRAINING_OVERRIDE_ENABLE REG_BIT(17) /* CHICKEN_TRANS_A only */
+#define DDIE_TRAINING_OVERRIDE_VALUE REG_BIT(16) /* CHICKEN_TRANS_A only */
+#define PSR2_ADD_VERTICAL_LINE_COUNT REG_BIT(15)
+#define PSR2_VSC_ENABLE_PROG_HEADER REG_BIT(12)
#define DISP_ARB_CTL _MMIO(0x45000)
-#define DISP_FBC_MEMORY_WAKE (1 << 31)
-#define DISP_TILE_SURFACE_SWIZZLING (1 << 13)
-#define DISP_FBC_WM_DIS (1 << 15)
+#define DISP_FBC_MEMORY_WAKE REG_BIT(31)
+#define DISP_TILE_SURFACE_SWIZZLING REG_BIT(13)
+#define DISP_FBC_WM_DIS REG_BIT(15)
+
#define DISP_ARB_CTL2 _MMIO(0x45004)
-#define DISP_DATA_PARTITION_5_6 (1 << 6)
-#define DISP_IPC_ENABLE (1 << 3)
+#define DISP_DATA_PARTITION_5_6 REG_BIT(6)
+#define DISP_IPC_ENABLE REG_BIT(3)
#define GEN7_MSG_CTL _MMIO(0x45010)
#define WAIT_FOR_PCH_RESET_ACK (1 << 1)
@@ -4637,6 +4685,9 @@
#define DCPR_SEND_RESP_IMM REG_BIT(25)
#define DCPR_CLEAR_MEMSTAT_DIS REG_BIT(24)
+#define XELPD_CHICKEN_DCPR_3 _MMIO(0x46438)
+#define DMD_RSP_TIMEOUT_DISABLE REG_BIT(19)
+
#define SKL_DFSM _MMIO(0x51000)
#define SKL_DFSM_DISPLAY_PM_DISABLE (1 << 27)
#define SKL_DFSM_DISPLAY_HDCP_DISABLE (1 << 25)
@@ -4768,7 +4819,8 @@
SDE_FDI_RXB_CPT | \
SDE_FDI_RXA_CPT)
-/* south display engine interrupt: ICP/TGP */
+/* south display engine interrupt: ICP/TGP/MTP */
+#define SDE_PICAINTERRUPT REG_BIT(31)
#define SDE_GMBUS_ICP (1 << 23)
#define SDE_TC_HOTPLUG_ICP(hpd_pin) REG_BIT(24 + _HPD_PIN_TC(hpd_pin))
#define SDE_TC_HOTPLUG_DG2(hpd_pin) REG_BIT(25 + _HPD_PIN_TC(hpd_pin)) /* sigh */
@@ -5104,24 +5156,32 @@
#define TRANS_BPC_10 REG_FIELD_PREP(TRANS_BPC_MASK, 1)
#define TRANS_BPC_6 REG_FIELD_PREP(TRANS_BPC_MASK, 2)
#define TRANS_BPC_12 REG_FIELD_PREP(TRANS_BPC_MASK, 3)
+
#define _TRANSA_CHICKEN1 0xf0060
#define _TRANSB_CHICKEN1 0xf1060
#define TRANS_CHICKEN1(pipe) _MMIO_PIPE(pipe, _TRANSA_CHICKEN1, _TRANSB_CHICKEN1)
-#define TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE (1 << 10)
-#define TRANS_CHICKEN1_DP0UNIT_GC_DISABLE (1 << 4)
+#define TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE REG_BIT(10)
+#define TRANS_CHICKEN1_DP0UNIT_GC_DISABLE REG_BIT(4)
+
#define _TRANSA_CHICKEN2 0xf0064
#define _TRANSB_CHICKEN2 0xf1064
#define TRANS_CHICKEN2(pipe) _MMIO_PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2)
-#define TRANS_CHICKEN2_TIMING_OVERRIDE (1 << 31)
-#define TRANS_CHICKEN2_FDI_POLARITY_REVERSED (1 << 29)
-#define TRANS_CHICKEN2_FRAME_START_DELAY_MASK (3 << 27)
-#define TRANS_CHICKEN2_FRAME_START_DELAY(x) ((x) << 27) /* 0-3 */
-#define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER (1 << 26)
-#define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH (1 << 25)
+#define TRANS_CHICKEN2_TIMING_OVERRIDE REG_BIT(31)
+#define TRANS_CHICKEN2_FDI_POLARITY_REVERSED REG_BIT(29)
+#define TRANS_CHICKEN2_FRAME_START_DELAY_MASK REG_GENMASK(28, 27)
+#define TRANS_CHICKEN2_FRAME_START_DELAY(x) REG_FIELD_PREP(TRANS_CHICKEN2_FRAME_START_DELAY_MASK, (x)) /* 0-3 */
+#define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER REG_BIT(26)
+#define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH REG_BIT(25)
#define SOUTH_CHICKEN1 _MMIO(0xc2000)
#define FDIA_PHASE_SYNC_SHIFT_OVR 19
#define FDIA_PHASE_SYNC_SHIFT_EN 18
+#define INVERT_DDIE_HPD REG_BIT(28)
+#define INVERT_DDID_HPD_MTP REG_BIT(27)
+#define INVERT_TC4_HPD REG_BIT(26)
+#define INVERT_TC3_HPD REG_BIT(25)
+#define INVERT_TC2_HPD REG_BIT(24)
+#define INVERT_TC1_HPD REG_BIT(23)
#define INVERT_DDID_HPD (1 << 18)
#define INVERT_DDIC_HPD (1 << 17)
#define INVERT_DDIB_HPD (1 << 16)
@@ -5303,6 +5363,20 @@
#define ICL_PCODE_MEM_SS_READ_GLOBAL_INFO (0x0 << 8)
#define ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point) (((point) << 16) | (0x1 << 8))
#define ADL_PCODE_MEM_SS_READ_PSF_GV_INFO ((0) | (0x2 << 8))
+#define DISPLAY_TO_PCODE_CDCLK_MAX 0x28D
+#define DISPLAY_TO_PCODE_VOLTAGE_MASK REG_GENMASK(1, 0)
+#define DISPLAY_TO_PCODE_VOLTAGE_MAX DISPLAY_TO_PCODE_VOLTAGE_MASK
+#define DISPLAY_TO_PCODE_CDCLK_VALID REG_BIT(27)
+#define DISPLAY_TO_PCODE_PIPE_COUNT_VALID REG_BIT(31)
+#define DISPLAY_TO_PCODE_CDCLK_MASK REG_GENMASK(25, 16)
+#define DISPLAY_TO_PCODE_PIPE_COUNT_MASK REG_GENMASK(30, 28)
+#define DISPLAY_TO_PCODE_CDCLK(x) REG_FIELD_PREP(DISPLAY_TO_PCODE_CDCLK_MASK, (x))
+#define DISPLAY_TO_PCODE_PIPE_COUNT(x) REG_FIELD_PREP(DISPLAY_TO_PCODE_PIPE_COUNT_MASK, (x))
+#define DISPLAY_TO_PCODE_VOLTAGE(x) REG_FIELD_PREP(DISPLAY_TO_PCODE_VOLTAGE_MASK, (x))
+#define DISPLAY_TO_PCODE_UPDATE_MASK(cdclk, num_pipes, voltage_level) \
+ ((DISPLAY_TO_PCODE_CDCLK(cdclk)) | \
+ (DISPLAY_TO_PCODE_PIPE_COUNT(num_pipes)) | \
+ (DISPLAY_TO_PCODE_VOLTAGE(voltage_level)))
#define ICL_PCODE_SAGV_DE_MEM_SS_CONFIG 0xe
#define ICL_PCODE_REP_QGV_MASK REG_GENMASK(1, 0)
#define ICL_PCODE_REP_QGV_SAFE REG_FIELD_PREP(ICL_PCODE_REP_QGV_MASK, 0)
@@ -5563,6 +5637,8 @@ enum skl_power_gate {
#define TRANS_DDI_HDCP_SELECT REG_BIT(5)
#define TRANS_DDI_BFI_ENABLE (1 << 4)
#define TRANS_DDI_HIGH_TMDS_CHAR_RATE (1 << 4)
+#define TRANS_DDI_PORT_WIDTH_MASK REG_GENMASK(3, 1)
+#define TRANS_DDI_PORT_WIDTH(width) REG_FIELD_PREP(TRANS_DDI_PORT_WIDTH_MASK, (width) - 1)
#define TRANS_DDI_HDMI_SCRAMBLING (1 << 0)
#define TRANS_DDI_HDMI_SCRAMBLING_MASK (TRANS_DDI_HDMI_SCRAMBLER_CTS_ENABLE \
| TRANS_DDI_HDMI_SCRAMBLER_RESET_FREQ \
@@ -5622,11 +5698,16 @@ enum skl_power_gate {
/* DDI Buffer Control */
#define _DDI_BUF_CTL_A 0x64000
#define _DDI_BUF_CTL_B 0x64100
+/* Known as DDI_CTL_DE in MTL+ */
#define DDI_BUF_CTL(port) _MMIO_PORT(port, _DDI_BUF_CTL_A, _DDI_BUF_CTL_B)
#define DDI_BUF_CTL_ENABLE (1 << 31)
#define DDI_BUF_TRANS_SELECT(n) ((n) << 24)
#define DDI_BUF_EMP_MASK (0xf << 24)
#define DDI_BUF_PHY_LINK_RATE(r) ((r) << 20)
+#define DDI_BUF_PORT_DATA_MASK REG_GENMASK(19, 18)
+#define DDI_BUF_PORT_DATA_10BIT REG_FIELD_PREP(DDI_BUF_PORT_DATA_MASK, 0)
+#define DDI_BUF_PORT_DATA_20BIT REG_FIELD_PREP(DDI_BUF_PORT_DATA_MASK, 1)
+#define DDI_BUF_PORT_DATA_40BIT REG_FIELD_PREP(DDI_BUF_PORT_DATA_MASK, 2)
#define DDI_BUF_PORT_REVERSAL (1 << 16)
#define DDI_BUF_IS_IDLE (1 << 7)
#define DDI_BUF_CTL_TC_PHY_OWNERSHIP REG_BIT(6)
@@ -6383,6 +6464,20 @@ enum skl_power_gate {
(index) * 4, _PLANE_CSC_POSTOFF_HI_2(pipe) + \
(index) * 4)
+#define _PIPE_A_WGC_C01_C00 0x600B0 /* s2.10 */
+#define _PIPE_A_WGC_C02 0x600B4 /* s2.10 */
+#define _PIPE_A_WGC_C11_C10 0x600B8 /* s2.10 */
+#define _PIPE_A_WGC_C12 0x600BC /* s2.10 */
+#define _PIPE_A_WGC_C21_C20 0x600C0 /* s2.10 */
+#define _PIPE_A_WGC_C22 0x600C4 /* s2.10 */
+
+#define PIPE_WGC_C01_C00(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C01_C00)
+#define PIPE_WGC_C02(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C02)
+#define PIPE_WGC_C11_C10(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C11_C10)
+#define PIPE_WGC_C12(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C12)
+#define PIPE_WGC_C21_C20(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C21_C20)
+#define PIPE_WGC_C22(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C22)
+
/* pipe CSC & degamma/gamma LUTs on CHV */
#define _CGM_PIPE_A_CSC_COEFF01 (VLV_DISPLAY_BASE + 0x67900)
#define _CGM_PIPE_A_CSC_COEFF23 (VLV_DISPLAY_BASE + 0x67904)
diff --git a/drivers/gpu/drm/i915/i915_reg_defs.h b/drivers/gpu/drm/i915/i915_reg_defs.h
index db26de6b57bc..a685db1e815d 100644
--- a/drivers/gpu/drm/i915/i915_reg_defs.h
+++ b/drivers/gpu/drm/i915/i915_reg_defs.h
@@ -23,6 +23,19 @@
((__n) < 0 || (__n) > 31))))
/**
+ * REG_BIT8() - Prepare a u8 bit value
+ * @__n: 0-based bit number
+ *
+ * Local wrapper for BIT() to force u8, with compile time checks.
+ *
+ * @return: Value with bit @__n set.
+ */
+#define REG_BIT8(__n) \
+ ((u8)(BIT(__n) + \
+ BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
+ ((__n) < 0 || (__n) > 7))))
+
+/**
* REG_GENMASK() - Prepare a continuous u32 bitmask
* @__high: 0-based high bit
* @__low: 0-based low bit
@@ -52,6 +65,21 @@
__is_constexpr(__low) && \
((__low) < 0 || (__high) > 63 || (__low) > (__high)))))
+/**
+ * REG_GENMASK8() - Prepare a continuous u8 bitmask
+ * @__high: 0-based high bit
+ * @__low: 0-based low bit
+ *
+ * Local wrapper for GENMASK() to force u8, with compile time checks.
+ *
+ * @return: Continuous bitmask from @__high to @__low, inclusive.
+ */
+#define REG_GENMASK8(__high, __low) \
+ ((u8)(GENMASK(__high, __low) + \
+ BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
+ __is_constexpr(__low) && \
+ ((__low) < 0 || (__high) > 7 || (__low) > (__high)))))
+
/*
* Local integer constant expression version of is_power_of_2().
*/
@@ -75,6 +103,23 @@
BUILD_BUG_ON_ZERO(__builtin_choose_expr(__is_constexpr(__val), (~((__mask) >> __bf_shf(__mask)) & (__val)), 0))))
/**
+ * REG_FIELD_PREP8() - Prepare a u8 bitfield value
+ * @__mask: shifted mask defining the field's length and position
+ * @__val: value to put in the field
+ *
+ * Local copy of FIELD_PREP() to generate an integer constant expression, force
+ * u8 and for consistency with REG_FIELD_GET8(), REG_BIT8() and REG_GENMASK8().
+ *
+ * @return: @__val masked and shifted into the field defined by @__mask.
+ */
+#define REG_FIELD_PREP8(__mask, __val) \
+ ((u8)((((typeof(__mask))(__val) << __bf_shf(__mask)) & (__mask)) + \
+ BUILD_BUG_ON_ZERO(!__is_constexpr(__mask)) + \
+ BUILD_BUG_ON_ZERO((__mask) == 0 || (__mask) > U8_MAX) + \
+ BUILD_BUG_ON_ZERO(!IS_POWER_OF_2((__mask) + (1ULL << __bf_shf(__mask)))) + \
+ BUILD_BUG_ON_ZERO(__builtin_choose_expr(__is_constexpr(__val), (~((__mask) >> __bf_shf(__mask)) & (__val)), 0))))
+
+/**
* REG_FIELD_GET() - Extract a u32 bitfield value
* @__mask: shifted mask defining the field's length and position
* @__val: value to extract the bitfield value from
@@ -98,6 +143,54 @@
*/
#define REG_FIELD_GET64(__mask, __val) ((u64)FIELD_GET(__mask, __val))
+/**
+ * REG_BIT16() - Prepare a u16 bit value
+ * @__n: 0-based bit number
+ *
+ * Local wrapper for BIT() to force u16, with compile time
+ * checks.
+ *
+ * @return: Value with bit @__n set.
+ */
+#define REG_BIT16(__n) \
+ ((u16)(BIT(__n) + \
+ BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
+ ((__n) < 0 || (__n) > 15))))
+
+/**
+ * REG_GENMASK16() - Prepare a continuous u8 bitmask
+ * @__high: 0-based high bit
+ * @__low: 0-based low bit
+ *
+ * Local wrapper for GENMASK() to force u16, with compile time
+ * checks.
+ *
+ * @return: Continuous bitmask from @__high to @__low, inclusive.
+ */
+#define REG_GENMASK16(__high, __low) \
+ ((u16)(GENMASK(__high, __low) + \
+ BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
+ __is_constexpr(__low) && \
+ ((__low) < 0 || (__high) > 15 || (__low) > (__high)))))
+
+/**
+ * REG_FIELD_PREP16() - Prepare a u16 bitfield value
+ * @__mask: shifted mask defining the field's length and position
+ * @__val: value to put in the field
+ *
+ * Local copy of FIELD_PREP16() to generate an integer constant
+ * expression, force u8 and for consistency with
+ * REG_FIELD_GET16(), REG_BIT16() and REG_GENMASK16().
+ *
+ * @return: @__val masked and shifted into the field defined by @__mask.
+ */
+#define REG_FIELD_PREP16(__mask, __val) \
+ ((u16)((((typeof(__mask))(__val) << __bf_shf(__mask)) & (__mask)) + \
+ BUILD_BUG_ON_ZERO(!__is_constexpr(__mask)) + \
+ BUILD_BUG_ON_ZERO((__mask) == 0 || (__mask) > U16_MAX) + \
+ BUILD_BUG_ON_ZERO(!IS_POWER_OF_2((__mask) + (1ULL << __bf_shf(__mask)))) + \
+ BUILD_BUG_ON_ZERO(__builtin_choose_expr(__is_constexpr(__val), (~((__mask) >> __bf_shf(__mask)) & (__val)), 0))))
+
#define __MASKED_FIELD(mask, value) ((mask) << 16 | (value))
#define _MASKED_FIELD(mask, value) ({ \
if (__builtin_constant_p(mask)) \
@@ -155,6 +248,18 @@
*/
#define _PICK(__index, ...) (((const u32 []){ __VA_ARGS__ })[__index])
+/**
+ * REG_FIELD_GET8() - Extract a u8 bitfield value
+ * @__mask: shifted mask defining the field's length and position
+ * @__val: value to extract the bitfield value from
+ *
+ * Local wrapper for FIELD_GET() to force u8 and for consistency with
+ * REG_FIELD_PREP(), REG_BIT() and REG_GENMASK().
+ *
+ * @return: Masked and shifted value of the field defined by @__mask in @__val.
+ */
+#define REG_FIELD_GET8(__mask, __val) ((u8)FIELD_GET(__mask, __val))
+
typedef struct {
u32 reg;
} i915_reg_t;
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index 630a732aaecc..894068bb37b6 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -290,7 +290,7 @@ static enum hrtimer_restart __rq_watchdog_expired(struct hrtimer *hrtimer)
if (!i915_request_completed(rq)) {
if (llist_add(&rq->watchdog.link, &gt->watchdog.list))
- schedule_work(&gt->watchdog.work);
+ queue_work(gt->i915->unordered_wq, &gt->watchdog.work);
} else {
i915_request_put(rq);
}
diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h
index f5e1bb5e857a..0ac55b2e4223 100644
--- a/drivers/gpu/drm/i915/i915_request.h
+++ b/drivers/gpu/drm/i915/i915_request.h
@@ -172,7 +172,7 @@ enum {
I915_FENCE_FLAG_COMPOSITE,
};
-/**
+/*
* Request queue structure.
*
* The request queue allows us to note sequence numbers that have been emitted
@@ -198,7 +198,7 @@ struct i915_request {
struct drm_i915_private *i915;
- /**
+ /*
* Context and ring buffer related to this request
* Contexts are refcounted, so when this request is associated with a
* context, we must increment the context's refcount, to guarantee that
@@ -251,9 +251,9 @@ struct i915_request {
};
struct llist_head execute_cb;
struct i915_sw_fence semaphore;
- /**
- * @submit_work: complete submit fence from an IRQ if needed for
- * locking hierarchy reasons.
+ /*
+ * complete submit fence from an IRQ if needed for locking hierarchy
+ * reasons.
*/
struct irq_work submit_work;
@@ -277,35 +277,35 @@ struct i915_request {
*/
const u32 *hwsp_seqno;
- /** Position in the ring of the start of the request */
+ /* Position in the ring of the start of the request */
u32 head;
- /** Position in the ring of the start of the user packets */
+ /* Position in the ring of the start of the user packets */
u32 infix;
- /**
+ /*
* Position in the ring of the start of the postfix.
* This is required to calculate the maximum available ring space
* without overwriting the postfix.
*/
u32 postfix;
- /** Position in the ring of the end of the whole request */
+ /* Position in the ring of the end of the whole request */
u32 tail;
- /** Position in the ring of the end of any workarounds after the tail */
+ /* Position in the ring of the end of any workarounds after the tail */
u32 wa_tail;
- /** Preallocate space in the ring for the emitting the request */
+ /* Preallocate space in the ring for the emitting the request */
u32 reserved_space;
- /** Batch buffer pointer for selftest internal use. */
+ /* Batch buffer pointer for selftest internal use. */
I915_SELFTEST_DECLARE(struct i915_vma *batch);
struct i915_vma_resource *batch_res;
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
- /**
+ /*
* Additional buffers requested by userspace to be captured upon
* a GPU hang. The vma/obj on this list are protected by their
* active reference - all objects on this list must also be
@@ -314,29 +314,29 @@ struct i915_request {
struct i915_capture_list *capture_list;
#endif
- /** Time at which this request was emitted, in jiffies. */
+ /* Time at which this request was emitted, in jiffies. */
unsigned long emitted_jiffies;
- /** timeline->request entry for this request */
+ /* timeline->request entry for this request */
struct list_head link;
- /** Watchdog support fields. */
+ /* Watchdog support fields. */
struct i915_request_watchdog {
struct llist_node link;
struct hrtimer timer;
} watchdog;
- /**
- * @guc_fence_link: Requests may need to be stalled when using GuC
- * submission waiting for certain GuC operations to complete. If that is
- * the case, stalled requests are added to a per context list of stalled
- * requests. The below list_head is the link in that list. Protected by
+ /*
+ * Requests may need to be stalled when using GuC submission waiting for
+ * certain GuC operations to complete. If that is the case, stalled
+ * requests are added to a per context list of stalled requests. The
+ * below list_head is the link in that list. Protected by
* ce->guc_state.lock.
*/
struct list_head guc_fence_link;
- /**
- * @guc_prio: Priority level while the request is in flight. Differs
+ /*
+ * Priority level while the request is in flight. Differs
* from i915 scheduler priority. See comment above
* I915_SCHEDULER_CAP_STATIC_PRIORITY_MAP for details. Protected by
* ce->guc_active.lock. Two special values (GUC_PRIO_INIT and
@@ -348,8 +348,8 @@ struct i915_request {
#define GUC_PRIO_FINI 0xfe
u8 guc_prio;
- /**
- * @hucq: wait queue entry used to wait on the HuC load to complete
+ /*
+ * wait queue entry used to wait on the HuC load to complete
*/
wait_queue_entry_t hucq;
@@ -473,7 +473,7 @@ i915_request_has_initial_breadcrumb(const struct i915_request *rq)
return test_bit(I915_FENCE_FLAG_INITIAL_BREADCRUMB, &rq->fence.flags);
}
-/**
+/*
* Returns true if seq1 is later than seq2.
*/
static inline bool i915_seqno_passed(u32 seq1, u32 seq2)
diff --git a/drivers/gpu/drm/i915/i915_scatterlist.h b/drivers/gpu/drm/i915/i915_scatterlist.h
index b0a1db44f895..5a10c1a31183 100644
--- a/drivers/gpu/drm/i915/i915_scatterlist.h
+++ b/drivers/gpu/drm/i915/i915_scatterlist.h
@@ -157,8 +157,7 @@ bool i915_sg_trim(struct sg_table *orig_st);
*/
struct i915_refct_sgt_ops {
/**
- * release() - Free the memory of the struct i915_refct_sgt
- * @ref: struct kref that is embedded in the struct i915_refct_sgt
+ * @release: Free the memory of the struct i915_refct_sgt
*/
void (*release)(struct kref *ref);
};
@@ -181,7 +180,7 @@ struct i915_refct_sgt {
/**
* i915_refct_sgt_put - Put a refcounted sg-table
- * @rsgt the struct i915_refct_sgt to put.
+ * @rsgt: the struct i915_refct_sgt to put.
*/
static inline void i915_refct_sgt_put(struct i915_refct_sgt *rsgt)
{
@@ -191,7 +190,7 @@ static inline void i915_refct_sgt_put(struct i915_refct_sgt *rsgt)
/**
* i915_refct_sgt_get - Get a refcounted sg-table
- * @rsgt the struct i915_refct_sgt to get.
+ * @rsgt: the struct i915_refct_sgt to get.
*/
static inline struct i915_refct_sgt *
i915_refct_sgt_get(struct i915_refct_sgt *rsgt)
@@ -203,7 +202,7 @@ i915_refct_sgt_get(struct i915_refct_sgt *rsgt)
/**
* __i915_refct_sgt_init - Initialize a refcounted sg-list with a custom
* operations structure
- * @rsgt The struct i915_refct_sgt to initialize.
+ * @rsgt: The struct i915_refct_sgt to initialize.
* @size: Size in bytes of the underlying memory buffer.
* @ops: A customized operations structure in case the refcounted sg-list
* is embedded into another structure.
diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
index 2c430c0c3bad..c61066498bf2 100644
--- a/drivers/gpu/drm/i915/i915_utils.h
+++ b/drivers/gpu/drm/i915/i915_utils.h
@@ -250,7 +250,7 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms)
}
}
-/**
+/*
* __wait_for - magic wait macro
*
* Macro to help avoid open coding check/wait/timeout patterns. Note that it's
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index 20a44788999e..ffb425ba591c 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -315,7 +315,7 @@ struct i915_vma_work {
struct i915_vma_resource *vma_res;
struct drm_i915_gem_object *obj;
struct i915_sw_dma_fence_cb cb;
- enum i915_cache_level cache_level;
+ unsigned int pat_index;
unsigned int flags;
};
@@ -334,7 +334,7 @@ static void __vma_bind(struct dma_fence_work *work)
return;
vma_res->ops->bind_vma(vma_res->vm, &vw->stash,
- vma_res, vw->cache_level, vw->flags);
+ vma_res, vw->pat_index, vw->flags);
}
static void __vma_release(struct dma_fence_work *work)
@@ -426,7 +426,7 @@ i915_vma_resource_init_from_vma(struct i915_vma_resource *vma_res,
/**
* i915_vma_bind - Sets up PTEs for an VMA in it's corresponding address space.
* @vma: VMA to map
- * @cache_level: mapping cache level
+ * @pat_index: PAT index to set in PTE
* @flags: flags like global or local mapping
* @work: preallocated worker for allocating and binding the PTE
* @vma_res: pointer to a preallocated vma resource. The resource is either
@@ -437,7 +437,7 @@ i915_vma_resource_init_from_vma(struct i915_vma_resource *vma_res,
* Note that DMA addresses are also the only part of the SG table we care about.
*/
int i915_vma_bind(struct i915_vma *vma,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags,
struct i915_vma_work *work,
struct i915_vma_resource *vma_res)
@@ -507,7 +507,7 @@ int i915_vma_bind(struct i915_vma *vma,
struct dma_fence *prev;
work->vma_res = i915_vma_resource_get(vma->resource);
- work->cache_level = cache_level;
+ work->pat_index = pat_index;
work->flags = bind_flags;
/*
@@ -537,7 +537,7 @@ int i915_vma_bind(struct i915_vma *vma,
return ret;
}
- vma->ops->bind_vma(vma->vm, NULL, vma->resource, cache_level,
+ vma->ops->bind_vma(vma->vm, NULL, vma->resource, pat_index,
bind_flags);
}
@@ -814,7 +814,7 @@ i915_vma_insert(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
color = 0;
if (i915_vm_has_cache_coloring(vma->vm))
- color = vma->obj->cache_level;
+ color = vma->obj->pat_index;
if (flags & PIN_OFFSET_FIXED) {
u64 offset = flags & PIN_OFFSET_MASK;
@@ -1518,7 +1518,7 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
GEM_BUG_ON(!vma->pages);
err = i915_vma_bind(vma,
- vma->obj->cache_level,
+ vma->obj->pat_index,
flags, work, vma_res);
vma_res = NULL;
if (err)
@@ -1710,6 +1710,8 @@ static void release_references(struct i915_vma *vma, struct intel_gt *gt,
if (vm_ddestroy)
i915_vm_resv_put(vma->vm);
+ /* Wait for async active retire */
+ i915_active_wait(&vma->active);
i915_active_fini(&vma->active);
GEM_WARN_ON(vma->resource);
i915_vma_free(vma);
diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h
index ed5c9d682a1b..9a9729205d5b 100644
--- a/drivers/gpu/drm/i915/i915_vma.h
+++ b/drivers/gpu/drm/i915/i915_vma.h
@@ -132,7 +132,7 @@ static inline u64 __i915_vma_size(const struct i915_vma *vma)
}
/**
- * i915_vma_offset - Obtain the va range size of the vma
+ * i915_vma_size - Obtain the va range size of the vma
* @vma: The vma
*
* GPU virtual address space may be allocated with padding. This
@@ -250,7 +250,7 @@ i915_vma_compare(struct i915_vma *vma,
struct i915_vma_work *i915_vma_work(void);
int i915_vma_bind(struct i915_vma *vma,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags,
struct i915_vma_work *work,
struct i915_vma_resource *vma_res);
diff --git a/drivers/gpu/drm/i915/i915_vma_resource.h b/drivers/gpu/drm/i915/i915_vma_resource.h
index c1864e3d0b43..ca2b0f7f59bc 100644
--- a/drivers/gpu/drm/i915/i915_vma_resource.h
+++ b/drivers/gpu/drm/i915/i915_vma_resource.h
@@ -34,6 +34,27 @@ struct i915_page_sizes {
};
/**
+ * struct i915_vma_bindinfo - Information needed for async bind
+ * only but that can be dropped after the bind has taken place.
+ * Consider making this a separate argument to the bind_vma
+ * op, coalescing with other arguments like vm, stash, cache_level
+ * and flags
+ * @pages: The pages sg-table.
+ * @page_sizes: Page sizes of the pages.
+ * @pages_rsgt: Refcounted sg-table when delayed object destruction
+ * is supported. May be NULL.
+ * @readonly: Whether the vma should be bound read-only.
+ * @lmem: Whether the vma points to lmem.
+ */
+struct i915_vma_bindinfo {
+ struct sg_table *pages;
+ struct i915_page_sizes page_sizes;
+ struct i915_refct_sgt *pages_rsgt;
+ bool readonly:1;
+ bool lmem:1;
+};
+
+/**
* struct i915_vma_resource - Snapshotted unbind information.
* @unbind_fence: Fence to mark unbinding complete. Note that this fence
* is not considered published until unbind is scheduled, and as such it
@@ -47,6 +68,7 @@ struct i915_page_sizes {
* @chain: Pointer to struct i915_sw_fence used to await dependencies.
* @rb: Rb node for the vm's pending unbind interval tree.
* @__subtree_last: Interval tree private member.
+ * @wakeref: wakeref.
* @vm: non-refcounted pointer to the vm. This is for internal use only and
* this member is cleared after vm_resource unbind.
* @mr: The memory region of the object pointed to by the vma.
@@ -88,25 +110,13 @@ struct i915_vma_resource {
intel_wakeref_t wakeref;
/**
- * struct i915_vma_bindinfo - Information needed for async bind
- * only but that can be dropped after the bind has taken place.
- * Consider making this a separate argument to the bind_vma
- * op, coalescing with other arguments like vm, stash, cache_level
- * and flags
- * @pages: The pages sg-table.
- * @page_sizes: Page sizes of the pages.
- * @pages_rsgt: Refcounted sg-table when delayed object destruction
- * is supported. May be NULL.
- * @readonly: Whether the vma should be bound read-only.
- * @lmem: Whether the vma points to lmem.
+ * @bi: Information needed for async bind only but that can be dropped
+ * after the bind has taken place.
+ *
+ * Consider making this a separate argument to the bind_vma op,
+ * coalescing with other arguments like vm, stash, cache_level and flags
*/
- struct i915_vma_bindinfo {
- struct sg_table *pages;
- struct i915_page_sizes page_sizes;
- struct i915_refct_sgt *pages_rsgt;
- bool readonly:1;
- bool lmem:1;
- } bi;
+ struct i915_vma_bindinfo bi;
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
struct intel_memory_region *mr;
diff --git a/drivers/gpu/drm/i915/i915_vma_types.h b/drivers/gpu/drm/i915/i915_vma_types.h
index 77fda2244d16..64472b7f0e77 100644
--- a/drivers/gpu/drm/i915/i915_vma_types.h
+++ b/drivers/gpu/drm/i915/i915_vma_types.h
@@ -32,8 +32,6 @@
#include "gem/i915_gem_object_types.h"
-enum i915_cache_level;
-
/**
* DOC: Global GTT views
*
diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c
index 2c5302bcba19..a27600bc5976 100644
--- a/drivers/gpu/drm/i915/intel_clock_gating.c
+++ b/drivers/gpu/drm/i915/intel_clock_gating.c
@@ -36,6 +36,7 @@
#include "gt/intel_gt_regs.h"
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_clock_gating.h"
#include "intel_mchbar_regs.h"
#include "vlv_sideband.h"
@@ -520,12 +521,12 @@ static void bdw_init_clock_gating(struct drm_i915_private *i915)
intel_uncore_rmw(&i915->uncore, GAM_ECOCHK, 0, HSW_ECOCHK_ARB_PRIO_SOL);
/* WaPsrDPAMaskVBlankInSRD:bdw */
- intel_uncore_rmw(&i915->uncore, CHICKEN_PAR1_1, 0, DPA_MASK_VBLANK_SRD);
+ intel_uncore_rmw(&i915->uncore, CHICKEN_PAR1_1, 0, HSW_MASK_VBL_TO_PIPE_IN_SRD);
for_each_pipe(i915, pipe) {
/* WaPsrDPRSUnmaskVBlankInSRD:bdw */
intel_uncore_rmw(&i915->uncore, CHICKEN_PIPESL_1(pipe),
- 0, BDW_DPRS_MASK_VBLANK_SRD);
+ 0, BDW_UNMASK_VBL_TO_REGS_IN_SRD);
}
/* WaVSRefCountFullforceMissDisable:bdw */
diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c
index fc5cd14adfcc..6e49caf241a5 100644
--- a/drivers/gpu/drm/i915/intel_device_info.c
+++ b/drivers/gpu/drm/i915/intel_device_info.c
@@ -27,9 +27,7 @@
#include <drm/drm_print.h>
#include <drm/i915_pciids.h>
-#include "display/intel_cdclk.h"
-#include "display/intel_de.h"
-#include "display/intel_display.h"
+#include "display/intel_display_device.h"
#include "gt/intel_gt_regs.h"
#include "i915_drv.h"
#include "i915_reg.h"
@@ -95,6 +93,9 @@ void intel_device_info_print(const struct intel_device_info *info,
const struct intel_runtime_info *runtime,
struct drm_printer *p)
{
+ const struct intel_display_runtime_info *display_runtime =
+ &info->display->__runtime_defaults;
+
if (runtime->graphics.ip.rel)
drm_printf(p, "graphics version: %u.%02u\n",
runtime->graphics.ip.ver,
@@ -111,13 +112,13 @@ void intel_device_info_print(const struct intel_device_info *info,
drm_printf(p, "media version: %u\n",
runtime->media.ip.ver);
- if (runtime->display.ip.rel)
+ if (display_runtime->ip.rel)
drm_printf(p, "display version: %u.%02u\n",
- runtime->display.ip.ver,
- runtime->display.ip.rel);
+ display_runtime->ip.ver,
+ display_runtime->ip.rel);
else
drm_printf(p, "display version: %u\n",
- runtime->display.ip.ver);
+ display_runtime->ip.ver);
drm_printf(p, "graphics stepping: %s\n", intel_step_name(runtime->step.graphics_step));
drm_printf(p, "media stepping: %s\n", intel_step_name(runtime->step.media_step));
@@ -138,13 +139,13 @@ void intel_device_info_print(const struct intel_device_info *info,
drm_printf(p, "has_pooled_eu: %s\n", str_yes_no(runtime->has_pooled_eu));
-#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, str_yes_no(info->display.name))
+#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, str_yes_no(info->display->name))
DEV_INFO_DISPLAY_FOR_EACH_FLAG(PRINT_FLAG);
#undef PRINT_FLAG
- drm_printf(p, "has_hdcp: %s\n", str_yes_no(runtime->has_hdcp));
- drm_printf(p, "has_dmc: %s\n", str_yes_no(runtime->has_dmc));
- drm_printf(p, "has_dsc: %s\n", str_yes_no(runtime->has_dsc));
+ drm_printf(p, "has_hdcp: %s\n", str_yes_no(display_runtime->has_hdcp));
+ drm_printf(p, "has_dmc: %s\n", str_yes_no(display_runtime->has_dmc));
+ drm_printf(p, "has_dsc: %s\n", str_yes_no(display_runtime->has_dsc));
drm_printf(p, "rawclk rate: %u kHz\n", runtime->rawclk_freq);
}
@@ -362,8 +363,6 @@ static void intel_ipver_early_init(struct drm_i915_private *i915)
RUNTIME_INFO(i915)->graphics.ip.ver = 12;
RUNTIME_INFO(i915)->graphics.ip.rel = 70;
}
- ip_ver_read(i915, i915_mmio_reg_offset(GMD_ID_DISPLAY),
- &runtime->display.ip);
ip_ver_read(i915, i915_mmio_reg_offset(GMD_ID_MEDIA),
&runtime->media.ip);
}
@@ -381,6 +380,15 @@ void intel_device_info_runtime_init_early(struct drm_i915_private *i915)
intel_device_info_subplatform_init(i915);
}
+/* FIXME: Remove this, and make device info a const pointer to rodata. */
+static struct intel_device_info *
+mkwrite_device_info(struct drm_i915_private *i915)
+{
+ return (struct intel_device_info *)INTEL_INFO(i915);
+}
+
+static const struct intel_display_device_info no_display = {};
+
/**
* intel_device_info_runtime_init - initialize runtime info
* @dev_priv: the i915 device
@@ -401,123 +409,23 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
{
struct intel_device_info *info = mkwrite_device_info(dev_priv);
struct intel_runtime_info *runtime = RUNTIME_INFO(dev_priv);
- enum pipe pipe;
-
- /* Wa_14011765242: adl-s A0,A1 */
- if (IS_ADLS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A2))
- for_each_pipe(dev_priv, pipe)
- runtime->num_scalers[pipe] = 0;
- else if (DISPLAY_VER(dev_priv) >= 11) {
- for_each_pipe(dev_priv, pipe)
- runtime->num_scalers[pipe] = 2;
- } else if (DISPLAY_VER(dev_priv) >= 9) {
- runtime->num_scalers[PIPE_A] = 2;
- runtime->num_scalers[PIPE_B] = 2;
- runtime->num_scalers[PIPE_C] = 1;
- }
-
- BUILD_BUG_ON(BITS_PER_TYPE(intel_engine_mask_t) < I915_NUM_ENGINES);
-
- if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv))
- for_each_pipe(dev_priv, pipe)
- runtime->num_sprites[pipe] = 4;
- else if (DISPLAY_VER(dev_priv) >= 11)
- for_each_pipe(dev_priv, pipe)
- runtime->num_sprites[pipe] = 6;
- else if (DISPLAY_VER(dev_priv) == 10)
- for_each_pipe(dev_priv, pipe)
- runtime->num_sprites[pipe] = 3;
- else if (IS_BROXTON(dev_priv)) {
- /*
- * Skylake and Broxton currently don't expose the topmost plane as its
- * use is exclusive with the legacy cursor and we only want to expose
- * one of those, not both. Until we can safely expose the topmost plane
- * as a DRM_PLANE_TYPE_CURSOR with all the features exposed/supported,
- * we don't expose the topmost plane at all to prevent ABI breakage
- * down the line.
- */
-
- runtime->num_sprites[PIPE_A] = 2;
- runtime->num_sprites[PIPE_B] = 2;
- runtime->num_sprites[PIPE_C] = 1;
- } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
- for_each_pipe(dev_priv, pipe)
- runtime->num_sprites[pipe] = 2;
- } else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) {
- for_each_pipe(dev_priv, pipe)
- runtime->num_sprites[pipe] = 1;
- }
- if (HAS_DISPLAY(dev_priv) &&
- (IS_DGFX(dev_priv) || DISPLAY_VER(dev_priv) >= 14) &&
- !(intel_de_read(dev_priv, GU_CNTL_PROTECTED) & DEPRESENT)) {
- drm_info(&dev_priv->drm, "Display not present, disabling\n");
+ if (HAS_DISPLAY(dev_priv))
+ intel_display_device_info_runtime_init(dev_priv);
- runtime->pipe_mask = 0;
+ /* Display may have been disabled by runtime init */
+ if (!HAS_DISPLAY(dev_priv)) {
+ dev_priv->drm.driver_features &= ~(DRIVER_MODESET |
+ DRIVER_ATOMIC);
+ info->display = &no_display;
}
- if (HAS_DISPLAY(dev_priv) && IS_GRAPHICS_VER(dev_priv, 7, 8) &&
- HAS_PCH_SPLIT(dev_priv)) {
- u32 fuse_strap = intel_de_read(dev_priv, FUSE_STRAP);
- u32 sfuse_strap = intel_de_read(dev_priv, SFUSE_STRAP);
-
- /*
- * SFUSE_STRAP is supposed to have a bit signalling the display
- * is fused off. Unfortunately it seems that, at least in
- * certain cases, fused off display means that PCH display
- * reads don't land anywhere. In that case, we read 0s.
- *
- * On CPT/PPT, we can detect this case as SFUSE_STRAP_FUSE_LOCK
- * should be set when taking over after the firmware.
- */
- if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE ||
- sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED ||
- (HAS_PCH_CPT(dev_priv) &&
- !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) {
- drm_info(&dev_priv->drm,
- "Display fused off, disabling\n");
- runtime->pipe_mask = 0;
- } else if (fuse_strap & IVB_PIPE_C_DISABLE) {
- drm_info(&dev_priv->drm, "PipeC fused off\n");
- runtime->pipe_mask &= ~BIT(PIPE_C);
- runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_C);
- }
- } else if (HAS_DISPLAY(dev_priv) && DISPLAY_VER(dev_priv) >= 9) {
- u32 dfsm = intel_de_read(dev_priv, SKL_DFSM);
-
- if (dfsm & SKL_DFSM_PIPE_A_DISABLE) {
- runtime->pipe_mask &= ~BIT(PIPE_A);
- runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_A);
- runtime->fbc_mask &= ~BIT(INTEL_FBC_A);
- }
- if (dfsm & SKL_DFSM_PIPE_B_DISABLE) {
- runtime->pipe_mask &= ~BIT(PIPE_B);
- runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_B);
- }
- if (dfsm & SKL_DFSM_PIPE_C_DISABLE) {
- runtime->pipe_mask &= ~BIT(PIPE_C);
- runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_C);
- }
-
- if (DISPLAY_VER(dev_priv) >= 12 &&
- (dfsm & TGL_DFSM_PIPE_D_DISABLE)) {
- runtime->pipe_mask &= ~BIT(PIPE_D);
- runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_D);
- }
-
- if (dfsm & SKL_DFSM_DISPLAY_HDCP_DISABLE)
- runtime->has_hdcp = 0;
-
- if (dfsm & SKL_DFSM_DISPLAY_PM_DISABLE)
- runtime->fbc_mask = 0;
-
- if (DISPLAY_VER(dev_priv) >= 11 && (dfsm & ICL_DFSM_DMC_DISABLE))
- runtime->has_dmc = 0;
+ /* Disable nuclear pageflip by default on pre-g4x */
+ if (!dev_priv->params.nuclear_pageflip &&
+ DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
+ dev_priv->drm.driver_features &= ~DRIVER_ATOMIC;
- if (IS_DISPLAY_VER(dev_priv, 10, 12) &&
- (dfsm & GLK_DFSM_DISPLAY_DSC_DISABLE))
- runtime->has_dsc = 0;
- }
+ BUILD_BUG_ON(BITS_PER_TYPE(intel_engine_mask_t) < I915_NUM_ENGINES);
if (GRAPHICS_VER(dev_priv) == 6 && i915_vtd_active(dev_priv)) {
drm_info(&dev_priv->drm,
@@ -528,24 +436,43 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
runtime->rawclk_freq = intel_read_rawclk(dev_priv);
drm_dbg(&dev_priv->drm, "rawclk rate: %d kHz\n", runtime->rawclk_freq);
- if (!HAS_DISPLAY(dev_priv)) {
- dev_priv->drm.driver_features &= ~(DRIVER_MODESET |
- DRIVER_ATOMIC);
- memset(&info->display, 0, sizeof(info->display));
-
- runtime->cpu_transcoder_mask = 0;
- memset(runtime->num_sprites, 0, sizeof(runtime->num_sprites));
- memset(runtime->num_scalers, 0, sizeof(runtime->num_scalers));
- runtime->fbc_mask = 0;
- runtime->has_hdcp = false;
- runtime->has_dmc = false;
- runtime->has_dsc = false;
+}
+
+/*
+ * Set up device info and initial runtime info at driver create.
+ *
+ * Note: i915 is only an allocated blob of memory at this point.
+ */
+void intel_device_info_driver_create(struct drm_i915_private *i915,
+ u16 device_id,
+ const struct intel_device_info *match_info)
+{
+ struct intel_device_info *info;
+ struct intel_runtime_info *runtime;
+ u16 ver, rel, step;
+
+ /* Setup the write-once "constant" device info */
+ info = mkwrite_device_info(i915);
+ memcpy(info, match_info, sizeof(*info));
+
+ /* Initialize initial runtime info from static const data and pdev. */
+ runtime = RUNTIME_INFO(i915);
+ memcpy(runtime, &INTEL_INFO(i915)->__runtime, sizeof(*runtime));
+
+ /* Probe display support */
+ info->display = intel_display_device_probe(i915, info->has_gmd_id,
+ &ver, &rel, &step);
+ memcpy(DISPLAY_RUNTIME_INFO(i915),
+ &DISPLAY_INFO(i915)->__runtime_defaults,
+ sizeof(*DISPLAY_RUNTIME_INFO(i915)));
+
+ if (info->has_gmd_id) {
+ DISPLAY_RUNTIME_INFO(i915)->ip.ver = ver;
+ DISPLAY_RUNTIME_INFO(i915)->ip.rel = rel;
+ DISPLAY_RUNTIME_INFO(i915)->ip.step = step;
}
- /* Disable nuclear pageflip by default on pre-g4x */
- if (!dev_priv->params.nuclear_pageflip &&
- DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
- dev_priv->drm.driver_features &= ~DRIVER_ATOMIC;
+ runtime->device_id = device_id;
}
void intel_driver_caps_print(const struct intel_driver_caps *caps,
diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h
index 080a4557899b..069291b3bd37 100644
--- a/drivers/gpu/drm/i915/intel_device_info.h
+++ b/drivers/gpu/drm/i915/intel_device_info.h
@@ -29,12 +29,14 @@
#include "intel_step.h"
-#include "display/intel_display_limits.h"
+#include "display/intel_display_device.h"
#include "gt/intel_engine_types.h"
#include "gt/intel_context_types.h"
#include "gt/intel_sseu.h"
+#include "gem/i915_gem_object_types.h"
+
struct drm_printer;
struct drm_i915_private;
struct intel_gt_definition;
@@ -180,25 +182,6 @@ enum intel_ppgtt_type {
func(unfenced_needs_alignment); \
func(hws_needs_physical);
-#define DEV_INFO_DISPLAY_FOR_EACH_FLAG(func) \
- /* Keep in alphabetical order */ \
- func(cursor_needs_physical); \
- func(has_cdclk_crawl); \
- func(has_cdclk_squash); \
- func(has_ddi); \
- func(has_dp_mst); \
- func(has_dsb); \
- func(has_fpga_dbg); \
- func(has_gmch); \
- func(has_hotplug); \
- func(has_hti); \
- func(has_ipc); \
- func(has_overlay); \
- func(has_psr); \
- func(has_psr_hw_tracking); \
- func(overlay_needs_physical); \
- func(supports_tv);
-
struct intel_ip_version {
u8 ver;
u8 rel;
@@ -216,9 +199,6 @@ struct intel_runtime_info {
struct {
struct intel_ip_version ip;
} media;
- struct {
- struct intel_ip_version ip;
- } display;
/*
* Platform mask is used for optimizing or-ed IS_PLATFORM calls into
@@ -246,21 +226,6 @@ struct intel_runtime_info {
u32 memory_regions; /* regions supported by the HW */
bool has_pooled_eu;
-
- /* display */
- struct {
- u8 pipe_mask;
- u8 cpu_transcoder_mask;
-
- u8 num_sprites[I915_MAX_PIPES];
- u8 num_scalers[I915_MAX_PIPES];
-
- u8 fbc_mask;
-
- bool has_hdcp;
- bool has_dmc;
- bool has_dsc;
- };
};
struct intel_device_info {
@@ -276,38 +241,15 @@ struct intel_device_info {
DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG);
#undef DEFINE_FLAG
- struct {
- u8 abox_mask;
-
- struct {
- u16 size; /* in blocks */
- u8 slice_mask;
- } dbuf;
-
-#define DEFINE_FLAG(name) u8 name:1
- DEV_INFO_DISPLAY_FOR_EACH_FLAG(DEFINE_FLAG);
-#undef DEFINE_FLAG
-
- /* Global register offset for the display engine */
- u32 mmio_offset;
-
- /* Register offsets for the various display pipes and transcoders */
- u32 pipe_offsets[I915_MAX_TRANSCODERS];
- u32 trans_offsets[I915_MAX_TRANSCODERS];
- u32 cursor_offsets[I915_MAX_PIPES];
-
- struct {
- u32 degamma_lut_size;
- u32 gamma_lut_size;
- u32 degamma_lut_tests;
- u32 gamma_lut_tests;
- } color;
- } display;
+ const struct intel_display_device_info *display;
/*
* Initial runtime info. Do not access outside of i915_driver_create().
*/
const struct intel_runtime_info __runtime;
+
+ u32 cachelevel_to_pat[I915_MAX_CACHE_LEVEL];
+ u32 max_pat_index;
};
struct intel_driver_caps {
@@ -317,6 +259,8 @@ struct intel_driver_caps {
const char *intel_platform_name(enum intel_platform platform);
+void intel_device_info_driver_create(struct drm_i915_private *i915, u16 device_id,
+ const struct intel_device_info *match_info);
void intel_device_info_runtime_init_early(struct drm_i915_private *dev_priv);
void intel_device_info_runtime_init(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index cf5122299b6b..6d8e5e5c0cba 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -658,5 +658,5 @@ void intel_runtime_pm_init_early(struct intel_runtime_pm *rpm)
init_intel_runtime_pm_wakeref(rpm);
INIT_LIST_HEAD(&rpm->lmem_userfault_list);
spin_lock_init(&rpm->lmem_userfault_lock);
- intel_wakeref_auto_init(&rpm->userfault_wakeref, rpm);
+ intel_wakeref_auto_init(&rpm->userfault_wakeref, i915);
}
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.h b/drivers/gpu/drm/i915/intel_runtime_pm.h
index e592e8d6499a..764b183ae452 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.h
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.h
@@ -16,12 +16,6 @@ struct device;
struct drm_i915_private;
struct drm_printer;
-enum i915_drm_suspend_mode {
- I915_DRM_SUSPEND_IDLE,
- I915_DRM_SUSPEND_MEM,
- I915_DRM_SUSPEND_HIBERNATE,
-};
-
/*
* This struct helps tracking the state needed for runtime PM, which puts the
* device in PCI D3 state. Notice that when this happens, nothing on the
diff --git a/drivers/gpu/drm/i915/intel_step.c b/drivers/gpu/drm/i915/intel_step.c
index 84a6fe736a3b..8a9ff6227e53 100644
--- a/drivers/gpu/drm/i915/intel_step.c
+++ b/drivers/gpu/drm/i915/intel_step.c
@@ -166,8 +166,12 @@ void intel_step_init(struct drm_i915_private *i915)
&RUNTIME_INFO(i915)->graphics.ip);
step.media_step = gmd_to_intel_step(i915,
&RUNTIME_INFO(i915)->media.ip);
- step.display_step = gmd_to_intel_step(i915,
- &RUNTIME_INFO(i915)->display.ip);
+ step.display_step = STEP_A0 + DISPLAY_RUNTIME_INFO(i915)->ip.step;
+ if (step.display_step >= STEP_FUTURE) {
+ drm_dbg(&i915->drm, "Using future display steppings\n");
+ step.display_step = STEP_FUTURE;
+ }
+
RUNTIME_INFO(i915)->step = step;
return;
diff --git a/drivers/gpu/drm/i915/intel_wakeref.c b/drivers/gpu/drm/i915/intel_wakeref.c
index dfd87d082218..718f2f1b6174 100644
--- a/drivers/gpu/drm/i915/intel_wakeref.c
+++ b/drivers/gpu/drm/i915/intel_wakeref.c
@@ -8,17 +8,18 @@
#include "intel_runtime_pm.h"
#include "intel_wakeref.h"
+#include "i915_drv.h"
static void rpm_get(struct intel_wakeref *wf)
{
- wf->wakeref = intel_runtime_pm_get(wf->rpm);
+ wf->wakeref = intel_runtime_pm_get(&wf->i915->runtime_pm);
}
static void rpm_put(struct intel_wakeref *wf)
{
intel_wakeref_t wakeref = fetch_and_zero(&wf->wakeref);
- intel_runtime_pm_put(wf->rpm, wakeref);
+ intel_runtime_pm_put(&wf->i915->runtime_pm, wakeref);
INTEL_WAKEREF_BUG_ON(!wakeref);
}
@@ -74,7 +75,7 @@ void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags)
/* Assume we are not in process context and so cannot sleep. */
if (flags & INTEL_WAKEREF_PUT_ASYNC || !mutex_trylock(&wf->mutex)) {
- mod_delayed_work(system_wq, &wf->work,
+ mod_delayed_work(wf->i915->unordered_wq, &wf->work,
FIELD_GET(INTEL_WAKEREF_PUT_DELAY, flags));
return;
}
@@ -94,11 +95,11 @@ static void __intel_wakeref_put_work(struct work_struct *wrk)
}
void __intel_wakeref_init(struct intel_wakeref *wf,
- struct intel_runtime_pm *rpm,
+ struct drm_i915_private *i915,
const struct intel_wakeref_ops *ops,
struct intel_wakeref_lockclass *key)
{
- wf->rpm = rpm;
+ wf->i915 = i915;
wf->ops = ops;
__mutex_init(&wf->mutex, "wakeref.mutex", &key->mutex);
@@ -137,17 +138,17 @@ static void wakeref_auto_timeout(struct timer_list *t)
wakeref = fetch_and_zero(&wf->wakeref);
spin_unlock_irqrestore(&wf->lock, flags);
- intel_runtime_pm_put(wf->rpm, wakeref);
+ intel_runtime_pm_put(&wf->i915->runtime_pm, wakeref);
}
void intel_wakeref_auto_init(struct intel_wakeref_auto *wf,
- struct intel_runtime_pm *rpm)
+ struct drm_i915_private *i915)
{
spin_lock_init(&wf->lock);
timer_setup(&wf->timer, wakeref_auto_timeout, 0);
refcount_set(&wf->count, 0);
wf->wakeref = 0;
- wf->rpm = rpm;
+ wf->i915 = i915;
}
void intel_wakeref_auto(struct intel_wakeref_auto *wf, unsigned long timeout)
@@ -161,13 +162,14 @@ void intel_wakeref_auto(struct intel_wakeref_auto *wf, unsigned long timeout)
}
/* Our mission is that we only extend an already active wakeref */
- assert_rpm_wakelock_held(wf->rpm);
+ assert_rpm_wakelock_held(&wf->i915->runtime_pm);
if (!refcount_inc_not_zero(&wf->count)) {
spin_lock_irqsave(&wf->lock, flags);
if (!refcount_inc_not_zero(&wf->count)) {
INTEL_WAKEREF_BUG_ON(wf->wakeref);
- wf->wakeref = intel_runtime_pm_get_if_in_use(wf->rpm);
+ wf->wakeref =
+ intel_runtime_pm_get_if_in_use(&wf->i915->runtime_pm);
refcount_set(&wf->count, 1);
}
spin_unlock_irqrestore(&wf->lock, flags);
diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h
index 0b6b4852ab23..ec881b097368 100644
--- a/drivers/gpu/drm/i915/intel_wakeref.h
+++ b/drivers/gpu/drm/i915/intel_wakeref.h
@@ -39,7 +39,7 @@ struct intel_wakeref {
intel_wakeref_t wakeref;
- struct intel_runtime_pm *rpm;
+ struct drm_i915_private *i915;
const struct intel_wakeref_ops *ops;
struct delayed_work work;
@@ -51,13 +51,13 @@ struct intel_wakeref_lockclass {
};
void __intel_wakeref_init(struct intel_wakeref *wf,
- struct intel_runtime_pm *rpm,
+ struct drm_i915_private *i915,
const struct intel_wakeref_ops *ops,
struct intel_wakeref_lockclass *key);
-#define intel_wakeref_init(wf, rpm, ops) do { \
+#define intel_wakeref_init(wf, i915, ops) do { \
static struct intel_wakeref_lockclass __key; \
\
- __intel_wakeref_init((wf), (rpm), (ops), &__key); \
+ __intel_wakeref_init((wf), (i915), (ops), &__key); \
} while (0)
int __intel_wakeref_get_first(struct intel_wakeref *wf);
@@ -262,7 +262,7 @@ __intel_wakeref_defer_park(struct intel_wakeref *wf)
int intel_wakeref_wait_for_idle(struct intel_wakeref *wf);
struct intel_wakeref_auto {
- struct intel_runtime_pm *rpm;
+ struct drm_i915_private *i915;
struct timer_list timer;
intel_wakeref_t wakeref;
spinlock_t lock;
@@ -287,7 +287,7 @@ struct intel_wakeref_auto {
void intel_wakeref_auto(struct intel_wakeref_auto *wf, unsigned long timeout);
void intel_wakeref_auto_init(struct intel_wakeref_auto *wf,
- struct intel_runtime_pm *rpm);
+ struct drm_i915_private *i915);
void intel_wakeref_auto_fini(struct intel_wakeref_auto *wf);
#endif /* INTEL_WAKEREF_H */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c b/drivers/gpu/drm/i915/pxp/intel_pxp.c
index 9d4c7724e98e..bb2e15329f34 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
@@ -12,7 +12,9 @@
#include "i915_drv.h"
#include "intel_pxp.h"
+#include "intel_pxp_gsccs.h"
#include "intel_pxp_irq.h"
+#include "intel_pxp_regs.h"
#include "intel_pxp_session.h"
#include "intel_pxp_tee.h"
#include "intel_pxp_types.h"
@@ -60,21 +62,22 @@ bool intel_pxp_is_active(const struct intel_pxp *pxp)
return IS_ENABLED(CONFIG_DRM_I915_PXP) && pxp && pxp->arb_is_valid;
}
-/* KCR register definitions */
-#define KCR_INIT _MMIO(0x320f0)
-/* Setting KCR Init bit is required after system boot */
-#define KCR_INIT_ALLOW_DISPLAY_ME_WRITES REG_BIT(14)
+static void kcr_pxp_set_status(const struct intel_pxp *pxp, bool enable)
+{
+ u32 val = enable ? _MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES) :
+ _MASKED_BIT_DISABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES);
+
+ intel_uncore_write(pxp->ctrl_gt->uncore, KCR_INIT(pxp->kcr_base), val);
+}
-static void kcr_pxp_enable(struct intel_gt *gt)
+static void kcr_pxp_enable(const struct intel_pxp *pxp)
{
- intel_uncore_write(gt->uncore, KCR_INIT,
- _MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES));
+ kcr_pxp_set_status(pxp, true);
}
-static void kcr_pxp_disable(struct intel_gt *gt)
+static void kcr_pxp_disable(const struct intel_pxp *pxp)
{
- intel_uncore_write(gt->uncore, KCR_INIT,
- _MASKED_BIT_DISABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES));
+ kcr_pxp_set_status(pxp, false);
}
static int create_vcs_context(struct intel_pxp *pxp)
@@ -126,13 +129,21 @@ static void pxp_init_full(struct intel_pxp *pxp)
init_completion(&pxp->termination);
complete_all(&pxp->termination);
+ if (pxp->ctrl_gt->type == GT_MEDIA)
+ pxp->kcr_base = MTL_KCR_BASE;
+ else
+ pxp->kcr_base = GEN12_KCR_BASE;
+
intel_pxp_session_management_init(pxp);
ret = create_vcs_context(pxp);
if (ret)
return;
- ret = intel_pxp_tee_component_init(pxp);
+ if (HAS_ENGINE(pxp->ctrl_gt, GSC0))
+ ret = intel_pxp_gsccs_init(pxp);
+ else
+ ret = intel_pxp_tee_component_init(pxp);
if (ret)
goto out_context;
@@ -165,9 +176,12 @@ static struct intel_gt *find_gt_for_required_protected_content(struct drm_i915_p
/*
* For MTL onwards, PXP-controller-GT needs to have a valid GSC engine
* on the media GT. NOTE: if we have a media-tile with a GSC-engine,
- * the VDBOX is already present so skip that check
+ * the VDBOX is already present so skip that check. We also have to
+ * ensure the GSC and HUC firmware are coming online
*/
- if (i915->media_gt && HAS_ENGINE(i915->media_gt, GSC0))
+ if (i915->media_gt && HAS_ENGINE(i915->media_gt, GSC0) &&
+ intel_uc_fw_is_loadable(&i915->media_gt->uc.gsc.fw) &&
+ intel_uc_fw_is_loadable(&i915->media_gt->uc.huc.fw))
return i915->media_gt;
/*
@@ -207,7 +221,9 @@ int intel_pxp_init(struct drm_i915_private *i915)
if (!i915->pxp)
return -ENOMEM;
+ /* init common info used by all feature-mode usages*/
i915->pxp->ctrl_gt = gt;
+ mutex_init(&i915->pxp->tee_mutex);
/*
* If full PXP feature is not available but HuC is loaded by GSC on pre-MTL
@@ -229,7 +245,10 @@ void intel_pxp_fini(struct drm_i915_private *i915)
i915->pxp->arb_is_valid = false;
- intel_pxp_tee_component_fini(i915->pxp);
+ if (HAS_ENGINE(i915->pxp->ctrl_gt, GSC0))
+ intel_pxp_gsccs_fini(i915->pxp);
+ else
+ intel_pxp_tee_component_fini(i915->pxp);
destroy_vcs_context(i915->pxp);
@@ -270,8 +289,18 @@ static bool pxp_component_bound(struct intel_pxp *pxp)
return bound;
}
+int intel_pxp_get_backend_timeout_ms(struct intel_pxp *pxp)
+{
+ if (HAS_ENGINE(pxp->ctrl_gt, GSC0))
+ return GSCFW_MAX_ROUND_TRIP_LATENCY_MS;
+ else
+ return 250;
+}
+
static int __pxp_global_teardown_final(struct intel_pxp *pxp)
{
+ int timeout;
+
if (!pxp->arb_is_valid)
return 0;
/*
@@ -281,7 +310,9 @@ static int __pxp_global_teardown_final(struct intel_pxp *pxp)
intel_pxp_mark_termination_in_progress(pxp);
intel_pxp_terminate(pxp, false);
- if (!wait_for_completion_timeout(&pxp->termination, msecs_to_jiffies(250)))
+ timeout = intel_pxp_get_backend_timeout_ms(pxp);
+
+ if (!wait_for_completion_timeout(&pxp->termination, msecs_to_jiffies(timeout)))
return -ETIMEDOUT;
return 0;
@@ -289,6 +320,8 @@ static int __pxp_global_teardown_final(struct intel_pxp *pxp)
static int __pxp_global_teardown_restart(struct intel_pxp *pxp)
{
+ int timeout;
+
if (pxp->arb_is_valid)
return 0;
/*
@@ -297,7 +330,9 @@ static int __pxp_global_teardown_restart(struct intel_pxp *pxp)
*/
pxp_queue_termination(pxp);
- if (!wait_for_completion_timeout(&pxp->termination, msecs_to_jiffies(250)))
+ timeout = intel_pxp_get_backend_timeout_ms(pxp);
+
+ if (!wait_for_completion_timeout(&pxp->termination, msecs_to_jiffies(timeout)))
return -ETIMEDOUT;
return 0;
@@ -325,6 +360,26 @@ void intel_pxp_end(struct intel_pxp *pxp)
}
/*
+ * this helper is used by both intel_pxp_start and by
+ * the GET_PARAM IOCTL that user space calls. Thus, the
+ * return values here should match the UAPI spec.
+ */
+int intel_pxp_get_readiness_status(struct intel_pxp *pxp)
+{
+ if (!intel_pxp_is_enabled(pxp))
+ return -ENODEV;
+
+ if (HAS_ENGINE(pxp->ctrl_gt, GSC0)) {
+ if (wait_for(intel_pxp_gsccs_is_ready_for_sessions(pxp), 250))
+ return 2;
+ } else {
+ if (wait_for(pxp_component_bound(pxp), 250))
+ return 2;
+ }
+ return 1;
+}
+
+/*
* the arb session is restarted from the irq work when we receive the
* termination completion interrupt
*/
@@ -332,11 +387,11 @@ int intel_pxp_start(struct intel_pxp *pxp)
{
int ret = 0;
- if (!intel_pxp_is_enabled(pxp))
- return -ENODEV;
-
- if (wait_for(pxp_component_bound(pxp), 250))
- return -ENXIO;
+ ret = intel_pxp_get_readiness_status(pxp);
+ if (ret < 0)
+ return ret;
+ else if (ret > 1)
+ return -EIO; /* per UAPI spec, user may retry later */
mutex_lock(&pxp->arb_mutex);
@@ -357,14 +412,13 @@ unlock:
void intel_pxp_init_hw(struct intel_pxp *pxp)
{
- kcr_pxp_enable(pxp->ctrl_gt);
+ kcr_pxp_enable(pxp);
intel_pxp_irq_enable(pxp);
}
void intel_pxp_fini_hw(struct intel_pxp *pxp)
{
- kcr_pxp_disable(pxp->ctrl_gt);
-
+ kcr_pxp_disable(pxp);
intel_pxp_irq_disable(pxp);
}
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.h b/drivers/gpu/drm/i915/pxp/intel_pxp.h
index 3ded0890cd27..17254c3f1267 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.h
@@ -26,6 +26,8 @@ void intel_pxp_fini_hw(struct intel_pxp *pxp);
void intel_pxp_mark_termination_in_progress(struct intel_pxp *pxp);
void intel_pxp_tee_end_arb_fw_session(struct intel_pxp *pxp, u32 arb_session_id);
+int intel_pxp_get_readiness_status(struct intel_pxp *pxp);
+int intel_pxp_get_backend_timeout_ms(struct intel_pxp *pxp);
int intel_pxp_start(struct intel_pxp *pxp);
void intel_pxp_end(struct intel_pxp *pxp);
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h
index ad67e3f49c20..0165d38fbead 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h
@@ -11,16 +11,51 @@
/* PXP-Cmd-Op definitions */
#define PXP43_CMDID_START_HUC_AUTH 0x0000003A
+#define PXP43_CMDID_NEW_HUC_AUTH 0x0000003F /* MTL+ */
+#define PXP43_CMDID_INIT_SESSION 0x00000036
-/* PXP-Input-Packet: HUC-Authentication */
+/* PXP-Packet sizes for MTL's GSCCS-HECI instruction */
+#define PXP43_MAX_HECI_INOUT_SIZE (SZ_32K)
+
+/* PXP-Packet size for MTL's NEW_HUC_AUTH instruction */
+#define PXP43_HUC_AUTH_INOUT_SIZE (SZ_4K)
+
+/* PXP-Input-Packet: HUC Load and Authentication */
struct pxp43_start_huc_auth_in {
struct pxp_cmd_header header;
__le64 huc_base_address;
} __packed;
-/* PXP-Output-Packet: HUC-Authentication */
-struct pxp43_start_huc_auth_out {
+/* PXP-Input-Packet: HUC Auth-only */
+struct pxp43_new_huc_auth_in {
+ struct pxp_cmd_header header;
+ u64 huc_base_address;
+ u32 huc_size;
+} __packed;
+
+/* PXP-Output-Packet: HUC Load and Authentication or Auth-only */
+struct pxp43_huc_auth_out {
+ struct pxp_cmd_header header;
+} __packed;
+
+/* PXP-Input-Packet: Init PXP session */
+struct pxp43_create_arb_in {
+ struct pxp_cmd_header header;
+ /* header.stream_id fields for vesion 4.3 of Init PXP session: */
+ #define PXP43_INIT_SESSION_VALID BIT(0)
+ #define PXP43_INIT_SESSION_APPTYPE BIT(1)
+ #define PXP43_INIT_SESSION_APPID GENMASK(17, 2)
+ u32 protection_mode;
+ #define PXP43_INIT_SESSION_PROTECTION_ARB 0x2
+ u32 sub_session_id;
+ u32 init_flags;
+ u32 rsvd[12];
+} __packed;
+
+/* PXP-Input-Packet: Init PXP session */
+struct pxp43_create_arb_out {
struct pxp_cmd_header header;
+ u32 rsvd[8];
} __packed;
#endif /* __INTEL_PXP_FW_INTERFACE_43_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c b/drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c
index 4b8e70caa3ad..e07c5b380789 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c
@@ -14,6 +14,7 @@
#include "intel_pxp.h"
#include "intel_pxp_debugfs.h"
+#include "intel_pxp_gsccs.h"
#include "intel_pxp_irq.h"
#include "intel_pxp_types.h"
@@ -45,6 +46,7 @@ static int pxp_terminate_set(void *data, u64 val)
{
struct intel_pxp *pxp = data;
struct intel_gt *gt = pxp->ctrl_gt;
+ int timeout_ms;
if (!intel_pxp_is_active(pxp))
return -ENODEV;
@@ -54,8 +56,10 @@ static int pxp_terminate_set(void *data, u64 val)
intel_pxp_irq_handler(pxp, GEN12_DISPLAY_PXP_STATE_TERMINATED_INTERRUPT);
spin_unlock_irq(gt->irq_lock);
+ timeout_ms = intel_pxp_get_backend_timeout_ms(pxp);
+
if (!wait_for_completion_timeout(&pxp->termination,
- msecs_to_jiffies(100)))
+ msecs_to_jiffies(timeout_ms)))
return -ETIMEDOUT;
return 0;
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.c b/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.c
new file mode 100644
index 000000000000..f13890ec7db1
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.c
@@ -0,0 +1,444 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2023 Intel Corporation.
+ */
+
+#include "gem/i915_gem_internal.h"
+
+#include "gt/intel_context.h"
+#include "gt/uc/intel_gsc_fw.h"
+#include "gt/uc/intel_gsc_uc_heci_cmd_submit.h"
+
+#include "i915_drv.h"
+#include "intel_pxp.h"
+#include "intel_pxp_cmd_interface_42.h"
+#include "intel_pxp_cmd_interface_43.h"
+#include "intel_pxp_gsccs.h"
+#include "intel_pxp_types.h"
+
+static bool
+is_fw_err_platform_config(u32 type)
+{
+ switch (type) {
+ case PXP_STATUS_ERROR_API_VERSION:
+ case PXP_STATUS_PLATFCONFIG_KF1_NOVERIF:
+ case PXP_STATUS_PLATFCONFIG_KF1_BAD:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static const char *
+fw_err_to_string(u32 type)
+{
+ switch (type) {
+ case PXP_STATUS_ERROR_API_VERSION:
+ return "ERR_API_VERSION";
+ case PXP_STATUS_NOT_READY:
+ return "ERR_NOT_READY";
+ case PXP_STATUS_PLATFCONFIG_KF1_NOVERIF:
+ case PXP_STATUS_PLATFCONFIG_KF1_BAD:
+ return "ERR_PLATFORM_CONFIG";
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static int
+gsccs_send_message(struct intel_pxp *pxp,
+ void *msg_in, size_t msg_in_size,
+ void *msg_out, size_t msg_out_size_max,
+ size_t *msg_out_len,
+ u64 *gsc_msg_handle_retry)
+{
+ struct intel_gt *gt = pxp->ctrl_gt;
+ struct drm_i915_private *i915 = gt->i915;
+ struct gsccs_session_resources *exec_res = &pxp->gsccs_res;
+ struct intel_gsc_mtl_header *header = exec_res->pkt_vaddr;
+ struct intel_gsc_heci_non_priv_pkt pkt;
+ size_t max_msg_size;
+ u32 reply_size;
+ int ret;
+
+ if (!exec_res->ce)
+ return -ENODEV;
+
+ max_msg_size = PXP43_MAX_HECI_INOUT_SIZE - sizeof(*header);
+
+ if (msg_in_size > max_msg_size || msg_out_size_max > max_msg_size)
+ return -ENOSPC;
+
+ if (!exec_res->pkt_vma || !exec_res->bb_vma)
+ return -ENOENT;
+
+ GEM_BUG_ON(exec_res->pkt_vma->size < (2 * PXP43_MAX_HECI_INOUT_SIZE));
+
+ mutex_lock(&pxp->tee_mutex);
+
+ memset(header, 0, sizeof(*header));
+ intel_gsc_uc_heci_cmd_emit_mtl_header(header, HECI_MEADDRESS_PXP,
+ msg_in_size + sizeof(*header),
+ exec_res->host_session_handle);
+
+ /* check if this is a host-session-handle cleanup call (empty packet) */
+ if (!msg_in && !msg_out)
+ header->flags |= GSC_INFLAG_MSG_CLEANUP;
+
+ /* copy caller provided gsc message handle if this is polling for a prior msg completion */
+ header->gsc_message_handle = *gsc_msg_handle_retry;
+
+ /* NOTE: zero size packets are used for session-cleanups */
+ if (msg_in && msg_in_size)
+ memcpy(exec_res->pkt_vaddr + sizeof(*header), msg_in, msg_in_size);
+
+ pkt.addr_in = i915_vma_offset(exec_res->pkt_vma);
+ pkt.size_in = header->message_size;
+ pkt.addr_out = pkt.addr_in + PXP43_MAX_HECI_INOUT_SIZE;
+ pkt.size_out = msg_out_size_max + sizeof(*header);
+ pkt.heci_pkt_vma = exec_res->pkt_vma;
+ pkt.bb_vma = exec_res->bb_vma;
+
+ /*
+ * Before submitting, let's clear-out the validity marker on the reply offset.
+ * We use offset PXP43_MAX_HECI_INOUT_SIZE for reply location so point header there.
+ */
+ header = exec_res->pkt_vaddr + PXP43_MAX_HECI_INOUT_SIZE;
+ header->validity_marker = 0;
+
+ ret = intel_gsc_uc_heci_cmd_submit_nonpriv(&gt->uc.gsc,
+ exec_res->ce, &pkt, exec_res->bb_vaddr,
+ GSC_REPLY_LATENCY_MS);
+ if (ret) {
+ drm_err(&i915->drm, "failed to send gsc PXP msg (%d)\n", ret);
+ goto unlock;
+ }
+
+ /* Response validity marker, status and busyness */
+ if (header->validity_marker != GSC_HECI_VALIDITY_MARKER) {
+ drm_err(&i915->drm, "gsc PXP reply with invalid validity marker\n");
+ ret = -EINVAL;
+ goto unlock;
+ }
+ if (header->status != 0) {
+ drm_dbg(&i915->drm, "gsc PXP reply status has error = 0x%08x\n",
+ header->status);
+ ret = -EINVAL;
+ goto unlock;
+ }
+ if (header->flags & GSC_OUTFLAG_MSG_PENDING) {
+ drm_dbg(&i915->drm, "gsc PXP reply is busy\n");
+ /*
+ * When the GSC firmware replies with pending bit, it means that the requested
+ * operation has begun but the completion is pending and the caller needs
+ * to re-request with the gsc_message_handle that was returned by the firmware.
+ * until the pending bit is turned off.
+ */
+ *gsc_msg_handle_retry = header->gsc_message_handle;
+ ret = -EAGAIN;
+ goto unlock;
+ }
+
+ reply_size = header->message_size - sizeof(*header);
+ if (reply_size > msg_out_size_max) {
+ drm_warn(&i915->drm, "caller with insufficient PXP reply size %u (%zu)\n",
+ reply_size, msg_out_size_max);
+ reply_size = msg_out_size_max;
+ }
+
+ if (msg_out)
+ memcpy(msg_out, exec_res->pkt_vaddr + PXP43_MAX_HECI_INOUT_SIZE + sizeof(*header),
+ reply_size);
+ if (msg_out_len)
+ *msg_out_len = reply_size;
+
+unlock:
+ mutex_unlock(&pxp->tee_mutex);
+ return ret;
+}
+
+static int
+gsccs_send_message_retry_complete(struct intel_pxp *pxp,
+ void *msg_in, size_t msg_in_size,
+ void *msg_out, size_t msg_out_size_max,
+ size_t *msg_out_len)
+{
+ u64 gsc_session_retry = 0;
+ int ret, tries = 0;
+
+ /*
+ * Keep sending request if GSC firmware was busy. Based on fw specs +
+ * sw overhead (and testing) we expect a worst case pending-bit delay of
+ * GSC_PENDING_RETRY_MAXCOUNT x GSC_PENDING_RETRY_PAUSE_MS millisecs.
+ */
+ do {
+ ret = gsccs_send_message(pxp, msg_in, msg_in_size, msg_out, msg_out_size_max,
+ msg_out_len, &gsc_session_retry);
+ /* Only try again if gsc says so */
+ if (ret != -EAGAIN)
+ break;
+
+ msleep(GSC_PENDING_RETRY_PAUSE_MS);
+ } while (++tries < GSC_PENDING_RETRY_MAXCOUNT);
+
+ return ret;
+}
+
+bool intel_pxp_gsccs_is_ready_for_sessions(struct intel_pxp *pxp)
+{
+ /*
+ * GSC-fw loading, HuC-fw loading, HuC-fw authentication and
+ * GSC-proxy init flow (requiring an mei component driver)
+ * must all occur first before we can start requesting for PXP
+ * sessions. Checking for completion on HuC authentication and
+ * gsc-proxy init flow (the last set of dependencies that
+ * are out of order) will suffice.
+ */
+ if (intel_huc_is_authenticated(&pxp->ctrl_gt->uc.huc, INTEL_HUC_AUTH_BY_GSC) &&
+ intel_gsc_uc_fw_proxy_init_done(&pxp->ctrl_gt->uc.gsc))
+ return true;
+
+ return false;
+}
+
+int intel_pxp_gsccs_create_session(struct intel_pxp *pxp,
+ int arb_session_id)
+{
+ struct drm_i915_private *i915 = pxp->ctrl_gt->i915;
+ struct pxp43_create_arb_in msg_in = {0};
+ struct pxp43_create_arb_out msg_out = {0};
+ int ret;
+
+ msg_in.header.api_version = PXP_APIVER(4, 3);
+ msg_in.header.command_id = PXP43_CMDID_INIT_SESSION;
+ msg_in.header.stream_id = (FIELD_PREP(PXP43_INIT_SESSION_APPID, arb_session_id) |
+ FIELD_PREP(PXP43_INIT_SESSION_VALID, 1) |
+ FIELD_PREP(PXP43_INIT_SESSION_APPTYPE, 0));
+ msg_in.header.buffer_len = sizeof(msg_in) - sizeof(msg_in.header);
+ msg_in.protection_mode = PXP43_INIT_SESSION_PROTECTION_ARB;
+
+ ret = gsccs_send_message_retry_complete(pxp,
+ &msg_in, sizeof(msg_in),
+ &msg_out, sizeof(msg_out), NULL);
+ if (ret) {
+ drm_err(&i915->drm, "Failed to init session %d, ret=[%d]\n", arb_session_id, ret);
+ } else if (msg_out.header.status != 0) {
+ if (is_fw_err_platform_config(msg_out.header.status)) {
+ drm_info_once(&i915->drm,
+ "PXP init-session-%d failed due to BIOS/SOC:0x%08x:%s\n",
+ arb_session_id, msg_out.header.status,
+ fw_err_to_string(msg_out.header.status));
+ } else {
+ drm_dbg(&i915->drm, "PXP init-session-%d failed 0x%08x:%st:\n",
+ arb_session_id, msg_out.header.status,
+ fw_err_to_string(msg_out.header.status));
+ drm_dbg(&i915->drm, " cmd-detail: ID=[0x%08x],API-Ver-[0x%08x]\n",
+ msg_in.header.command_id, msg_in.header.api_version);
+ }
+ }
+
+ return ret;
+}
+
+void intel_pxp_gsccs_end_arb_fw_session(struct intel_pxp *pxp, u32 session_id)
+{
+ struct drm_i915_private *i915 = pxp->ctrl_gt->i915;
+ struct pxp42_inv_stream_key_in msg_in = {0};
+ struct pxp42_inv_stream_key_out msg_out = {0};
+ int ret = 0;
+
+ /*
+ * Stream key invalidation reuses the same version 4.2 input/output
+ * command format but firmware requires 4.3 API interaction
+ */
+ msg_in.header.api_version = PXP_APIVER(4, 3);
+ msg_in.header.command_id = PXP42_CMDID_INVALIDATE_STREAM_KEY;
+ msg_in.header.buffer_len = sizeof(msg_in) - sizeof(msg_in.header);
+
+ msg_in.header.stream_id = FIELD_PREP(PXP_CMDHDR_EXTDATA_SESSION_VALID, 1);
+ msg_in.header.stream_id |= FIELD_PREP(PXP_CMDHDR_EXTDATA_APP_TYPE, 0);
+ msg_in.header.stream_id |= FIELD_PREP(PXP_CMDHDR_EXTDATA_SESSION_ID, session_id);
+
+ ret = gsccs_send_message_retry_complete(pxp,
+ &msg_in, sizeof(msg_in),
+ &msg_out, sizeof(msg_out), NULL);
+ if (ret) {
+ drm_err(&i915->drm, "Failed to inv-stream-key-%u, ret=[%d]\n",
+ session_id, ret);
+ } else if (msg_out.header.status != 0) {
+ if (is_fw_err_platform_config(msg_out.header.status)) {
+ drm_info_once(&i915->drm,
+ "PXP inv-stream-key-%u failed due to BIOS/SOC :0x%08x:%s\n",
+ session_id, msg_out.header.status,
+ fw_err_to_string(msg_out.header.status));
+ } else {
+ drm_dbg(&i915->drm, "PXP inv-stream-key-%u failed 0x%08x:%s:\n",
+ session_id, msg_out.header.status,
+ fw_err_to_string(msg_out.header.status));
+ drm_dbg(&i915->drm, " cmd-detail: ID=[0x%08x],API-Ver-[0x%08x]\n",
+ msg_in.header.command_id, msg_in.header.api_version);
+ }
+ }
+}
+
+static void
+gsccs_cleanup_fw_host_session_handle(struct intel_pxp *pxp)
+{
+ struct drm_i915_private *i915 = pxp->ctrl_gt->i915;
+ int ret;
+
+ ret = gsccs_send_message_retry_complete(pxp, NULL, 0, NULL, 0, NULL);
+ if (ret)
+ drm_dbg(&i915->drm, "Failed to send gsccs msg host-session-cleanup: ret=[%d]\n",
+ ret);
+}
+
+static void
+gsccs_destroy_execution_resource(struct intel_pxp *pxp)
+{
+ struct gsccs_session_resources *exec_res = &pxp->gsccs_res;
+
+ if (exec_res->host_session_handle)
+ gsccs_cleanup_fw_host_session_handle(pxp);
+ if (exec_res->ce)
+ intel_context_put(exec_res->ce);
+ if (exec_res->bb_vma)
+ i915_vma_unpin_and_release(&exec_res->bb_vma, I915_VMA_RELEASE_MAP);
+ if (exec_res->pkt_vma)
+ i915_vma_unpin_and_release(&exec_res->pkt_vma, I915_VMA_RELEASE_MAP);
+
+ memset(exec_res, 0, sizeof(*exec_res));
+}
+
+static int
+gsccs_create_buffer(struct intel_gt *gt,
+ const char *bufname, size_t size,
+ struct i915_vma **vma, void **map)
+{
+ struct drm_i915_private *i915 = gt->i915;
+ struct drm_i915_gem_object *obj;
+ int err = 0;
+
+ obj = i915_gem_object_create_internal(i915, size);
+ if (IS_ERR(obj)) {
+ drm_err(&i915->drm, "Failed to allocate gsccs backend %s.\n", bufname);
+ err = PTR_ERR(obj);
+ goto out_none;
+ }
+
+ *vma = i915_vma_instance(obj, gt->vm, NULL);
+ if (IS_ERR(*vma)) {
+ drm_err(&i915->drm, "Failed to vma-instance gsccs backend %s.\n", bufname);
+ err = PTR_ERR(*vma);
+ goto out_put;
+ }
+
+ /* return a virtual pointer */
+ *map = i915_gem_object_pin_map_unlocked(obj, i915_coherent_map_type(i915, obj, true));
+ if (IS_ERR(*map)) {
+ drm_err(&i915->drm, "Failed to map gsccs backend %s.\n", bufname);
+ err = PTR_ERR(*map);
+ goto out_put;
+ }
+
+ /* all PXP sessions commands are treated as non-privileged */
+ err = i915_vma_pin(*vma, 0, 0, PIN_USER);
+ if (err) {
+ drm_err(&i915->drm, "Failed to vma-pin gsccs backend %s.\n", bufname);
+ goto out_unmap;
+ }
+
+ return 0;
+
+out_unmap:
+ i915_gem_object_unpin_map(obj);
+out_put:
+ i915_gem_object_put(obj);
+out_none:
+ *vma = NULL;
+ *map = NULL;
+
+ return err;
+}
+
+static int
+gsccs_allocate_execution_resource(struct intel_pxp *pxp)
+{
+ struct intel_gt *gt = pxp->ctrl_gt;
+ struct gsccs_session_resources *exec_res = &pxp->gsccs_res;
+ struct intel_engine_cs *engine = gt->engine[GSC0];
+ struct intel_context *ce;
+ int err = 0;
+
+ /*
+ * First, ensure the GSC engine is present.
+ * NOTE: Backend would only be called with the correct gt.
+ */
+ if (!engine)
+ return -ENODEV;
+
+ /*
+ * Now, allocate, pin and map two objects, one for the heci message packet
+ * and another for the batch buffer we submit into GSC engine (that includes the packet).
+ * NOTE: GSC-CS backend is currently only supported on MTL, so we allocate shmem.
+ */
+ err = gsccs_create_buffer(pxp->ctrl_gt, "Heci Packet",
+ 2 * PXP43_MAX_HECI_INOUT_SIZE,
+ &exec_res->pkt_vma, &exec_res->pkt_vaddr);
+ if (err)
+ return err;
+
+ err = gsccs_create_buffer(pxp->ctrl_gt, "Batch Buffer", PAGE_SIZE,
+ &exec_res->bb_vma, &exec_res->bb_vaddr);
+ if (err)
+ goto free_pkt;
+
+ /* Finally, create an intel_context to be used during the submission */
+ ce = intel_context_create(engine);
+ if (IS_ERR(ce)) {
+ drm_err(&gt->i915->drm, "Failed creating gsccs backend ctx\n");
+ err = PTR_ERR(ce);
+ goto free_batch;
+ }
+
+ i915_vm_put(ce->vm);
+ ce->vm = i915_vm_get(pxp->ctrl_gt->vm);
+ exec_res->ce = ce;
+
+ /* initialize host-session-handle (for all i915-to-gsc-firmware PXP cmds) */
+ get_random_bytes(&exec_res->host_session_handle, sizeof(exec_res->host_session_handle));
+
+ return 0;
+
+free_batch:
+ i915_vma_unpin_and_release(&exec_res->bb_vma, I915_VMA_RELEASE_MAP);
+free_pkt:
+ i915_vma_unpin_and_release(&exec_res->pkt_vma, I915_VMA_RELEASE_MAP);
+ memset(exec_res, 0, sizeof(*exec_res));
+
+ return err;
+}
+
+void intel_pxp_gsccs_fini(struct intel_pxp *pxp)
+{
+ intel_wakeref_t wakeref;
+
+ gsccs_destroy_execution_resource(pxp);
+ with_intel_runtime_pm(&pxp->ctrl_gt->i915->runtime_pm, wakeref)
+ intel_pxp_fini_hw(pxp);
+}
+
+int intel_pxp_gsccs_init(struct intel_pxp *pxp)
+{
+ int ret;
+ intel_wakeref_t wakeref;
+
+ ret = gsccs_allocate_execution_resource(pxp);
+ if (!ret) {
+ with_intel_runtime_pm(&pxp->ctrl_gt->i915->runtime_pm, wakeref)
+ intel_pxp_init_hw(pxp);
+ }
+ return ret;
+}
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.h b/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.h
new file mode 100644
index 000000000000..298ad38e6c7d
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright(c) 2022, Intel Corporation. All rights reserved.
+ */
+
+#ifndef __INTEL_PXP_GSCCS_H__
+#define __INTEL_PXP_GSCCS_H__
+
+#include <linux/types.h>
+
+struct intel_pxp;
+
+#define GSC_REPLY_LATENCY_MS 210
+/*
+ * Max FW response time is 200ms, to which we add 10ms to account for overhead
+ * such as request preparation, GuC submission to hw and pipeline completion times.
+ */
+#define GSC_PENDING_RETRY_MAXCOUNT 40
+#define GSC_PENDING_RETRY_PAUSE_MS 50
+#define GSCFW_MAX_ROUND_TRIP_LATENCY_MS (GSC_PENDING_RETRY_MAXCOUNT * GSC_PENDING_RETRY_PAUSE_MS)
+
+#ifdef CONFIG_DRM_I915_PXP
+void intel_pxp_gsccs_fini(struct intel_pxp *pxp);
+int intel_pxp_gsccs_init(struct intel_pxp *pxp);
+
+int intel_pxp_gsccs_create_session(struct intel_pxp *pxp, int arb_session_id);
+void intel_pxp_gsccs_end_arb_fw_session(struct intel_pxp *pxp, u32 arb_session_id);
+
+#else
+static inline void intel_pxp_gsccs_fini(struct intel_pxp *pxp)
+{
+}
+
+static inline int intel_pxp_gsccs_init(struct intel_pxp *pxp)
+{
+ return 0;
+}
+
+#endif
+
+bool intel_pxp_gsccs_is_ready_for_sessions(struct intel_pxp *pxp);
+
+#endif /*__INTEL_PXP_GSCCS_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c b/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c
index 23431c36b60b..5eedce916942 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c
@@ -19,7 +19,7 @@ int intel_pxp_huc_load_and_auth(struct intel_pxp *pxp)
struct intel_gt *gt;
struct intel_huc *huc;
struct pxp43_start_huc_auth_in huc_in = {0};
- struct pxp43_start_huc_auth_out huc_out = {0};
+ struct pxp43_huc_auth_out huc_out = {0};
dma_addr_t huc_phys_addr;
u8 client_id = 0;
u8 fence_id = 0;
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_pm.c b/drivers/gpu/drm/i915/pxp/intel_pxp_pm.c
index 4f836b317424..1a04067f61fc 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_pm.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_pm.c
@@ -43,8 +43,9 @@ void intel_pxp_resume_complete(struct intel_pxp *pxp)
* The PXP component gets automatically unbound when we go into S3 and
* re-bound after we come out, so in that scenario we can defer the
* hw init to the bind call.
+ * NOTE: GSC-CS backend doesn't rely on components.
*/
- if (!pxp->pxp_component)
+ if (!HAS_ENGINE(pxp->ctrl_gt, GSC0) && !pxp->pxp_component)
return;
intel_pxp_init_hw(pxp);
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_regs.h b/drivers/gpu/drm/i915/pxp/intel_pxp_regs.h
new file mode 100644
index 000000000000..a9e7e6efa4c7
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_regs.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright(c) 2023, Intel Corporation. All rights reserved.
+ */
+
+#ifndef __INTEL_PXP_REGS_H__
+#define __INTEL_PXP_REGS_H__
+
+#include "i915_reg_defs.h"
+
+/* KCR subsystem register base address */
+#define GEN12_KCR_BASE 0x32000
+#define MTL_KCR_BASE 0x386000
+
+/* KCR enable/disable control */
+#define KCR_INIT(base) _MMIO((base) + 0xf0)
+
+/* Setting KCR Init bit is required after system boot */
+#define KCR_INIT_ALLOW_DISPLAY_ME_WRITES REG_BIT(14)
+
+/* KCR hwdrm session in play status 0-31 */
+#define KCR_SIP(base) _MMIO((base) + 0x260)
+
+/* PXP global terminate register for session termination */
+#define KCR_GLOBAL_TERMINATE(base) _MMIO((base) + 0xf8)
+
+#endif /* __INTEL_PXP_REGS_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c
index 7de849cb6c47..0a3e66b0265e 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c
@@ -7,17 +7,14 @@
#include "intel_pxp.h"
#include "intel_pxp_cmd.h"
+#include "intel_pxp_gsccs.h"
#include "intel_pxp_session.h"
#include "intel_pxp_tee.h"
#include "intel_pxp_types.h"
+#include "intel_pxp_regs.h"
#define ARB_SESSION I915_PROTECTED_CONTENT_DEFAULT_SESSION /* shorter define */
-#define GEN12_KCR_SIP _MMIO(0x32260) /* KCR hwdrm session in play 0-31 */
-
-/* PXP global terminate register for session termination */
-#define PXP_GLOBAL_TERMINATE _MMIO(0x320f8)
-
static bool intel_pxp_session_is_in_play(struct intel_pxp *pxp, u32 id)
{
struct intel_uncore *uncore = pxp->ctrl_gt->uncore;
@@ -26,7 +23,7 @@ static bool intel_pxp_session_is_in_play(struct intel_pxp *pxp, u32 id)
/* if we're suspended the session is considered off */
with_intel_runtime_pm_if_in_use(uncore->rpm, wakeref)
- sip = intel_uncore_read(uncore, GEN12_KCR_SIP);
+ sip = intel_uncore_read(uncore, KCR_SIP(pxp->kcr_base));
return sip & BIT(id);
}
@@ -44,10 +41,10 @@ static int pxp_wait_for_session_state(struct intel_pxp *pxp, u32 id, bool in_pla
return in_play ? -ENODEV : 0;
ret = intel_wait_for_register(uncore,
- GEN12_KCR_SIP,
+ KCR_SIP(pxp->kcr_base),
mask,
in_play ? mask : 0,
- 100);
+ 250);
intel_runtime_pm_put(uncore->rpm, wakeref);
@@ -66,7 +63,10 @@ static int pxp_create_arb_session(struct intel_pxp *pxp)
return -EEXIST;
}
- ret = intel_pxp_tee_cmd_create_arb_session(pxp, ARB_SESSION);
+ if (HAS_ENGINE(pxp->ctrl_gt, GSC0))
+ ret = intel_pxp_gsccs_create_session(pxp, ARB_SESSION);
+ else
+ ret = intel_pxp_tee_cmd_create_arb_session(pxp, ARB_SESSION);
if (ret) {
drm_err(&gt->i915->drm, "tee cmd for arb session creation failed\n");
return ret;
@@ -108,9 +108,12 @@ static int pxp_terminate_arb_session_and_global(struct intel_pxp *pxp)
return ret;
}
- intel_uncore_write(gt->uncore, PXP_GLOBAL_TERMINATE, 1);
+ intel_uncore_write(gt->uncore, KCR_GLOBAL_TERMINATE(pxp->kcr_base), 1);
- intel_pxp_tee_end_arb_fw_session(pxp, ARB_SESSION);
+ if (HAS_ENGINE(gt, GSC0))
+ intel_pxp_gsccs_end_arb_fw_session(pxp, ARB_SESSION);
+ else
+ intel_pxp_tee_end_arb_fw_session(pxp, ARB_SESSION);
return ret;
}
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
index a2846b1dbbee..1ce07d7e8769 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
@@ -284,8 +284,6 @@ int intel_pxp_tee_component_init(struct intel_pxp *pxp)
struct intel_gt *gt = pxp->ctrl_gt;
struct drm_i915_private *i915 = gt->i915;
- mutex_init(&pxp->tee_mutex);
-
ret = alloc_streaming_command(pxp);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_types.h b/drivers/gpu/drm/i915/pxp/intel_pxp_types.h
index 007de49e1ea4..1a8765866b8b 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_types.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_types.h
@@ -27,13 +27,35 @@ struct intel_pxp {
struct intel_gt *ctrl_gt;
/**
+ * @kcr_base: base mmio offset for the KCR engine which is different on legacy platforms
+ * vs newer platforms where the KCR is inside the media-tile.
+ */
+ u32 kcr_base;
+
+ /**
+ * @gsccs_res: resources for request submission for platforms that have a GSC engine.
+ */
+ struct gsccs_session_resources {
+ u64 host_session_handle; /* used by firmware to link commands to sessions */
+ struct intel_context *ce; /* context for gsc command submission */
+
+ struct i915_vma *pkt_vma; /* GSC FW cmd packet vma */
+ void *pkt_vaddr; /* GSC FW cmd packet virt pointer */
+
+ struct i915_vma *bb_vma; /* HECI_PKT batch buffer vma */
+ void *bb_vaddr; /* HECI_PKT batch buffer virt pointer */
+ } gsccs_res;
+
+ /**
* @pxp_component: i915_pxp_component struct of the bound mei_pxp
* module. Only set and cleared inside component bind/unbind functions,
* which are protected by &tee_mutex.
*/
struct i915_pxp_component *pxp_component;
- /* @dev_link: Enforce module relationship for power management ordering. */
+ /**
+ * @dev_link: Enforce module relationship for power management ordering.
+ */
struct device_link *dev_link;
/**
* @pxp_component_added: track if the pxp component has been added.
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c
index d91d0ade8abd..61da4ed9d521 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem.c
@@ -57,7 +57,10 @@ static void trash_stolen(struct drm_i915_private *i915)
u32 __iomem *s;
int x;
- ggtt->vm.insert_page(&ggtt->vm, dma, slot, I915_CACHE_NONE, 0);
+ ggtt->vm.insert_page(&ggtt->vm, dma, slot,
+ i915_gem_get_pat_index(i915,
+ I915_CACHE_NONE),
+ 0);
s = io_mapping_map_atomic_wc(&ggtt->iomap, slot);
for (x = 0; x < PAGE_SIZE / sizeof(u32); x++) {
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
index 37068542aafe..f8fe3681c3dc 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
@@ -27,6 +27,7 @@
#include "gem/selftests/igt_gem_utils.h"
#include "gem/selftests/mock_context.h"
#include "gt/intel_gt.h"
+#include "gt/intel_gt_print.h"
#include "i915_selftest.h"
@@ -245,7 +246,7 @@ static int igt_evict_for_cache_color(void *arg)
struct drm_mm_node target = {
.start = I915_GTT_PAGE_SIZE * 2,
.size = I915_GTT_PAGE_SIZE,
- .color = I915_CACHE_LLC,
+ .color = i915_gem_get_pat_index(gt->i915, I915_CACHE_LLC),
};
struct drm_i915_gem_object *obj;
struct i915_vma *vma;
@@ -308,7 +309,7 @@ static int igt_evict_for_cache_color(void *arg)
/* Attempt to remove the first *pinned* vma, by removing the (empty)
* neighbour -- this should fail.
*/
- target.color = I915_CACHE_L3_LLC;
+ target.color = i915_gem_get_pat_index(gt->i915, I915_CACHE_L3_LLC);
mutex_lock(&ggtt->vm.mutex);
err = i915_gem_evict_for_node(&ggtt->vm, NULL, &target, 0);
@@ -507,7 +508,8 @@ static int igt_evict_contexts(void *arg)
}
err = intel_gt_wait_for_idle(engine->gt, HZ * 3);
if (err) {
- pr_err("Failed to idle GT (on %s)", engine->name);
+ gt_err(engine->gt, "Failed to idle GT (on %s)",
+ engine->name);
break;
}
}
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
index 154801f1c468..5c397a2df70e 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
@@ -135,7 +135,7 @@ fake_dma_object(struct drm_i915_private *i915, u64 size)
obj->write_domain = I915_GEM_DOMAIN_CPU;
obj->read_domains = I915_GEM_DOMAIN_CPU;
- obj->cache_level = I915_CACHE_NONE;
+ obj->pat_index = i915_gem_get_pat_index(i915, I915_CACHE_NONE);
/* Preallocate the "backing storage" */
if (i915_gem_object_pin_pages_unlocked(obj))
@@ -359,7 +359,9 @@ alloc_vm_end:
with_intel_runtime_pm(vm->gt->uncore->rpm, wakeref)
vm->insert_entries(vm, mock_vma_res,
- I915_CACHE_NONE, 0);
+ i915_gem_get_pat_index(vm->i915,
+ I915_CACHE_NONE),
+ 0);
}
count = n;
@@ -389,7 +391,7 @@ static void close_object_list(struct list_head *objects,
struct i915_address_space *vm)
{
struct drm_i915_gem_object *obj, *on;
- int ignored;
+ int __maybe_unused ignored;
list_for_each_entry_safe(obj, on, objects, st_link) {
struct i915_vma *vma;
@@ -1377,7 +1379,10 @@ static int igt_ggtt_page(void *arg)
ggtt->vm.insert_page(&ggtt->vm,
i915_gem_object_get_dma_address(obj, 0),
- offset, I915_CACHE_NONE, 0);
+ offset,
+ i915_gem_get_pat_index(i915,
+ I915_CACHE_NONE),
+ 0);
}
order = i915_random_order(count, &prng);
@@ -1510,7 +1515,7 @@ static int reserve_gtt_with_resource(struct i915_vma *vma, u64 offset)
mutex_lock(&vm->mutex);
err = i915_gem_gtt_reserve(vm, NULL, &vma->node, obj->base.size,
offset,
- obj->cache_level,
+ obj->pat_index,
0);
if (!err) {
i915_vma_resource_init_from_vma(vma_res, vma);
@@ -1690,7 +1695,7 @@ static int insert_gtt_with_resource(struct i915_vma *vma)
mutex_lock(&vm->mutex);
err = i915_gem_gtt_insert(vm, NULL, &vma->node, obj->base.size, 0,
- obj->cache_level, 0, vm->total, 0);
+ obj->pat_index, 0, vm->total, 0);
if (!err) {
i915_vma_resource_init_from_vma(vma_res, vma);
vma->resource = vma_res;
diff --git a/drivers/gpu/drm/i915/selftests/i915_perf.c b/drivers/gpu/drm/i915/selftests/i915_perf.c
index 24dde5531423..d4608b220123 100644
--- a/drivers/gpu/drm/i915/selftests/i915_perf.c
+++ b/drivers/gpu/drm/i915/selftests/i915_perf.c
@@ -28,7 +28,7 @@ alloc_empty_config(struct i915_perf *perf)
oa_config->perf = perf;
kref_init(&oa_config->ref);
- strlcpy(oa_config->uuid, TEST_OA_CONFIG_UUID, sizeof(oa_config->uuid));
+ strscpy(oa_config->uuid, TEST_OA_CONFIG_UUID, sizeof(oa_config->uuid));
mutex_lock(&perf->metrics_lock);
diff --git a/drivers/gpu/drm/i915/selftests/i915_sw_fence.c b/drivers/gpu/drm/i915/selftests/i915_sw_fence.c
index daa985e5a19b..8f5ce71fa453 100644
--- a/drivers/gpu/drm/i915/selftests/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/selftests/i915_sw_fence.c
@@ -523,12 +523,19 @@ static void task_ipc(struct work_struct *work)
static int test_ipc(void *arg)
{
struct task_ipc ipc;
+ struct workqueue_struct *wq;
int ret = 0;
+ wq = alloc_workqueue("i1915-selftest", 0, 0);
+ if (wq == NULL)
+ return -ENOMEM;
+
/* Test use of i915_sw_fence as an interprocess signaling mechanism */
ipc.in = alloc_fence();
- if (!ipc.in)
- return -ENOMEM;
+ if (!ipc.in) {
+ ret = -ENOMEM;
+ goto err_work;
+ }
ipc.out = alloc_fence();
if (!ipc.out) {
ret = -ENOMEM;
@@ -540,7 +547,7 @@ static int test_ipc(void *arg)
ipc.value = 0;
INIT_WORK_ONSTACK(&ipc.work, task_ipc);
- schedule_work(&ipc.work);
+ queue_work(wq, &ipc.work);
wait_for_completion(&ipc.started);
@@ -563,6 +570,9 @@ static int test_ipc(void *arg)
free_fence(ipc.out);
err_in:
free_fence(ipc.in);
+err_work:
+ destroy_workqueue(wq);
+
return ret;
}
diff --git a/drivers/gpu/drm/i915/selftests/igt_live_test.c b/drivers/gpu/drm/i915/selftests/igt_live_test.c
index 72b58b66692a..4ddc6d902752 100644
--- a/drivers/gpu/drm/i915/selftests/igt_live_test.c
+++ b/drivers/gpu/drm/i915/selftests/igt_live_test.c
@@ -6,6 +6,7 @@
#include "i915_drv.h"
#include "gt/intel_gt.h"
+#include "gt/intel_gt_print.h"
#include "../i915_selftest.h"
#include "igt_flush_test.h"
@@ -16,27 +17,31 @@ int igt_live_test_begin(struct igt_live_test *t,
const char *func,
const char *name)
{
- struct intel_gt *gt = to_gt(i915);
struct intel_engine_cs *engine;
enum intel_engine_id id;
+ struct intel_gt *gt;
+ unsigned int i;
int err;
t->i915 = i915;
t->func = func;
t->name = name;
- err = intel_gt_wait_for_idle(gt, MAX_SCHEDULE_TIMEOUT);
- if (err) {
- pr_err("%s(%s): failed to idle before, with err=%d!",
- func, name, err);
- return err;
- }
+ for_each_gt(gt, i915, i) {
- t->reset_global = i915_reset_count(&i915->gpu_error);
+ err = intel_gt_wait_for_idle(gt, MAX_SCHEDULE_TIMEOUT);
+ if (err) {
+ gt_err(gt, "%s(%s): GT failed to idle before, with err=%d!",
+ func, name, err);
+ return err;
+ }
- for_each_engine(engine, gt, id)
- t->reset_engine[id] =
+ for_each_engine(engine, gt, id)
+ t->reset_engine[id] =
i915_reset_engine_count(&i915->gpu_error, engine);
+ }
+
+ t->reset_global = i915_reset_count(&i915->gpu_error);
return 0;
}
@@ -46,6 +51,8 @@ int igt_live_test_end(struct igt_live_test *t)
struct drm_i915_private *i915 = t->i915;
struct intel_engine_cs *engine;
enum intel_engine_id id;
+ struct intel_gt *gt;
+ unsigned int i;
if (igt_flush_test(i915))
return -EIO;
@@ -57,16 +64,18 @@ int igt_live_test_end(struct igt_live_test *t)
return -EIO;
}
- for_each_engine(engine, to_gt(i915), id) {
- if (t->reset_engine[id] ==
- i915_reset_engine_count(&i915->gpu_error, engine))
- continue;
+ for_each_gt(gt, i915, i) {
+ for_each_engine(engine, gt, id) {
+ if (t->reset_engine[id] ==
+ i915_reset_engine_count(&i915->gpu_error, engine))
+ continue;
- pr_err("%s(%s): engine '%s' was reset %d times!\n",
- t->func, t->name, engine->name,
- i915_reset_engine_count(&i915->gpu_error, engine) -
- t->reset_engine[id]);
- return -EIO;
+ gt_err(gt, "%s(%s): engine '%s' was reset %d times!\n",
+ t->func, t->name, engine->name,
+ i915_reset_engine_count(&i915->gpu_error, engine) -
+ t->reset_engine[id]);
+ return -EIO;
+ }
}
return 0;
diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c
index 3b18e5905c86..d985d9bae2e8 100644
--- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c
@@ -1070,7 +1070,9 @@ static int igt_lmem_write_cpu(void *arg)
/* Put the pages into a known state -- from the gpu for added fun */
intel_engine_pm_get(engine);
err = intel_context_migrate_clear(engine->gt->migrate.context, NULL,
- obj->mm.pages->sgl, I915_CACHE_NONE,
+ obj->mm.pages->sgl,
+ i915_gem_get_pat_index(i915,
+ I915_CACHE_NONE),
true, 0xdeadbeaf, &rq);
if (rq) {
dma_resv_add_fence(obj->base.resv, &rq->fence,
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index f6a7c0bd2955..09d4bbcdcdbf 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -69,6 +69,7 @@ static void mock_device_release(struct drm_device *dev)
i915_gem_drain_workqueue(i915);
mock_fini_ggtt(to_gt(i915)->ggtt);
+ destroy_workqueue(i915->unordered_wq);
destroy_workqueue(i915->wq);
intel_region_ttm_device_fini(i915);
@@ -123,7 +124,9 @@ struct drm_i915_private *mock_gem_device(void)
static struct dev_iommu fake_iommu = { .priv = (void *)-1 };
#endif
struct drm_i915_private *i915;
+ struct intel_device_info *i915_info;
struct pci_dev *pdev;
+ unsigned int i;
int ret;
pdev = kzalloc(sizeof(*pdev), GFP_KERNEL);
@@ -180,6 +183,13 @@ struct drm_i915_private *mock_gem_device(void)
I915_GTT_PAGE_SIZE_2M;
RUNTIME_INFO(i915)->memory_regions = REGION_SMEM;
+
+ /* simply use legacy cache level for mock device */
+ i915_info = (struct intel_device_info *)INTEL_INFO(i915);
+ i915_info->max_pat_index = 3;
+ for (i = 0; i < I915_MAX_CACHE_LEVEL; i++)
+ i915_info->cachelevel_to_pat[i] = i;
+
intel_memory_regions_hw_probe(i915);
spin_lock_init(&i915->gpu_error.lock);
@@ -199,6 +209,10 @@ struct drm_i915_private *mock_gem_device(void)
if (!i915->wq)
goto err_drv;
+ i915->unordered_wq = alloc_workqueue("mock-unordered", 0, 0);
+ if (!i915->unordered_wq)
+ goto err_wq;
+
mock_init_contexts(i915);
/* allocate the ggtt */
@@ -230,6 +244,8 @@ struct drm_i915_private *mock_gem_device(void)
err_context:
intel_gt_driver_remove(to_gt(i915));
err_unlock:
+ destroy_workqueue(i915->unordered_wq);
+err_wq:
destroy_workqueue(i915->wq);
err_drv:
intel_region_ttm_device_fini(i915);
diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c
index ece97e4faacb..a516c0aa88fd 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gtt.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c
@@ -27,21 +27,21 @@
static void mock_insert_page(struct i915_address_space *vm,
dma_addr_t addr,
u64 offset,
- enum i915_cache_level level,
+ unsigned int pat_index,
u32 flags)
{
}
static void mock_insert_entries(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
- enum i915_cache_level level, u32 flags)
+ unsigned int pat_index, u32 flags)
{
}
static void mock_bind_ppgtt(struct i915_address_space *vm,
struct i915_vm_pt_stash *stash,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags)
{
GEM_BUG_ON(flags & I915_VMA_GLOBAL_BIND);
@@ -94,7 +94,7 @@ struct i915_ppgtt *mock_ppgtt(struct drm_i915_private *i915, const char *name)
static void mock_bind_ggtt(struct i915_address_space *vm,
struct i915_vm_pt_stash *stash,
struct i915_vma_resource *vma_res,
- enum i915_cache_level cache_level,
+ unsigned int pat_index,
u32 flags)
{
}
diff --git a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
index 8e6d457917da..277ead6a459a 100644
--- a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
+++ b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
@@ -400,8 +400,8 @@ static int imx_lcdc_probe(struct platform_device *pdev)
lcdc = devm_drm_dev_alloc(dev, &imx_lcdc_drm_driver,
struct imx_lcdc, drm);
- if (!lcdc)
- return -ENOMEM;
+ if (IS_ERR(lcdc))
+ return PTR_ERR(lcdc);
drm = &lcdc->drm;
diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig
index 823909da87db..615fdd0ce41b 100644
--- a/drivers/gpu/drm/meson/Kconfig
+++ b/drivers/gpu/drm/meson/Kconfig
@@ -17,3 +17,10 @@ config DRM_MESON_DW_HDMI
default y if DRM_MESON
select DRM_DW_HDMI
imply DRM_DW_HDMI_I2S_AUDIO
+
+config DRM_MESON_DW_MIPI_DSI
+ tristate "MIPI DSI Synopsys Controller support for Amlogic Meson Display"
+ depends on DRM_MESON
+ default y if DRM_MESON
+ select DRM_DW_MIPI_DSI
+ select GENERIC_PHY_MIPI_DPHY
diff --git a/drivers/gpu/drm/meson/Makefile b/drivers/gpu/drm/meson/Makefile
index 3afa31bdc950..43071bdbd4b9 100644
--- a/drivers/gpu/drm/meson/Makefile
+++ b/drivers/gpu/drm/meson/Makefile
@@ -2,7 +2,8 @@
meson-drm-y := meson_drv.o meson_plane.o meson_crtc.o meson_encoder_cvbs.o
meson-drm-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_overlay.o
meson-drm-y += meson_rdma.o meson_osd_afbcd.o
-meson-drm-y += meson_encoder_hdmi.o
+meson-drm-y += meson_encoder_hdmi.o meson_encoder_dsi.o
obj-$(CONFIG_DRM_MESON) += meson-drm.o
obj-$(CONFIG_DRM_MESON_DW_HDMI) += meson_dw_hdmi.o
+obj-$(CONFIG_DRM_MESON_DW_MIPI_DSI) += meson_dw_mipi_dsi.o
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index bb72fda9106d..747b639ea0c4 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -34,6 +34,7 @@
#include "meson_registers.h"
#include "meson_encoder_cvbs.h"
#include "meson_encoder_hdmi.h"
+#include "meson_encoder_dsi.h"
#include "meson_viu.h"
#include "meson_vpp.h"
#include "meson_rdma.h"
@@ -285,7 +286,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
* Remove early framebuffers (ie. simplefb). The framebuffer can be
* located anywhere in RAM
*/
- ret = drm_aperture_remove_framebuffers(false, &meson_driver);
+ ret = drm_aperture_remove_framebuffers(&meson_driver);
if (ret)
goto free_drm;
@@ -316,32 +317,40 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
goto exit_afbcd;
if (has_components) {
- ret = component_bind_all(drm->dev, drm);
+ ret = component_bind_all(dev, drm);
if (ret) {
dev_err(drm->dev, "Couldn't bind all components\n");
+ /* Do not try to unbind */
+ has_components = false;
goto exit_afbcd;
}
}
ret = meson_encoder_hdmi_init(priv);
if (ret)
- goto unbind_all;
+ goto exit_afbcd;
+
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+ ret = meson_encoder_dsi_init(priv);
+ if (ret)
+ goto exit_afbcd;
+ }
ret = meson_plane_create(priv);
if (ret)
- goto unbind_all;
+ goto exit_afbcd;
ret = meson_overlay_create(priv);
if (ret)
- goto unbind_all;
+ goto exit_afbcd;
ret = meson_crtc_create(priv);
if (ret)
- goto unbind_all;
+ goto exit_afbcd;
ret = request_irq(priv->vsync_irq, meson_irq, 0, drm->driver->name, drm);
if (ret)
- goto unbind_all;
+ goto exit_afbcd;
drm_mode_config_reset(drm);
@@ -359,15 +368,19 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
uninstall_irq:
free_irq(priv->vsync_irq, drm);
-unbind_all:
- if (has_components)
- component_unbind_all(drm->dev, drm);
exit_afbcd:
if (priv->afbcd.ops)
priv->afbcd.ops->exit(priv);
free_drm:
drm_dev_put(drm);
+ meson_encoder_dsi_remove(priv);
+ meson_encoder_hdmi_remove(priv);
+ meson_encoder_cvbs_remove(priv);
+
+ if (has_components)
+ component_unbind_all(dev, drm);
+
return ret;
}
@@ -394,6 +407,7 @@ static void meson_drv_unbind(struct device *dev)
free_irq(priv->vsync_irq, drm);
drm_dev_put(drm);
+ meson_encoder_dsi_remove(priv);
meson_encoder_hdmi_remove(priv);
meson_encoder_cvbs_remove(priv);
@@ -446,10 +460,17 @@ static void meson_drv_shutdown(struct platform_device *pdev)
drm_atomic_helper_shutdown(priv->drm);
}
-/* Possible connectors nodes to ignore */
-static const struct of_device_id connectors_match[] = {
- { .compatible = "composite-video-connector" },
- { .compatible = "svideo-connector" },
+/*
+ * Only devices to use as components
+ * TOFIX: get rid of components when we can finally
+ * get meson_dx_hdmi to stop using the meson_drm
+ * private structure for HHI registers.
+ */
+static const struct of_device_id components_dev_match[] = {
+ { .compatible = "amlogic,meson-gxbb-dw-hdmi" },
+ { .compatible = "amlogic,meson-gxl-dw-hdmi" },
+ { .compatible = "amlogic,meson-gxm-dw-hdmi" },
+ { .compatible = "amlogic,meson-g12a-dw-hdmi" },
{}
};
@@ -467,17 +488,12 @@ static int meson_drv_probe(struct platform_device *pdev)
continue;
}
- /* If an analog connector is detected, count it as an output */
- if (of_match_node(connectors_match, remote)) {
- ++count;
- of_node_put(remote);
- continue;
- }
+ if (of_match_node(components_dev_match, remote)) {
+ component_match_add(&pdev->dev, &match, component_compare_of, remote);
- dev_dbg(&pdev->dev, "parent %pOF remote match add %pOF parent %s\n",
- np, remote, dev_name(&pdev->dev));
-
- component_match_add(&pdev->dev, &match, component_compare_of, remote);
+ dev_dbg(&pdev->dev, "parent %pOF remote match add %pOF parent %s\n",
+ np, remote, dev_name(&pdev->dev));
+ }
of_node_put(remote);
diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h
index c62ee358456f..b23009a3380f 100644
--- a/drivers/gpu/drm/meson/meson_drv.h
+++ b/drivers/gpu/drm/meson/meson_drv.h
@@ -28,6 +28,7 @@ enum vpu_compatible {
enum {
MESON_ENC_CVBS = 0,
MESON_ENC_HDMI,
+ MESON_ENC_DSI,
MESON_ENC_LAST,
};
diff --git a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
new file mode 100644
index 000000000000..57447abf1a29
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2021 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/reset.h>
+#include <linux/phy/phy.h>
+#include <linux/bitfield.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/bridge/dw_mipi_dsi.h>
+#include <drm/drm_mipi_dsi.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_device.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_print.h>
+
+#include "meson_drv.h"
+#include "meson_dw_mipi_dsi.h"
+#include "meson_registers.h"
+#include "meson_venc.h"
+
+#define DRIVER_NAME "meson-dw-mipi-dsi"
+#define DRIVER_DESC "Amlogic Meson MIPI-DSI DRM driver"
+
+struct meson_dw_mipi_dsi {
+ struct meson_drm *priv;
+ struct device *dev;
+ void __iomem *base;
+ struct phy *phy;
+ union phy_configure_opts phy_opts;
+ struct dw_mipi_dsi *dmd;
+ struct dw_mipi_dsi_plat_data pdata;
+ struct mipi_dsi_device *dsi_device;
+ const struct drm_display_mode *mode;
+ struct clk *bit_clk;
+ struct clk *px_clk;
+ struct reset_control *top_rst;
+};
+
+#define encoder_to_meson_dw_mipi_dsi(x) \
+ container_of(x, struct meson_dw_mipi_dsi, encoder)
+
+static void meson_dw_mipi_dsi_hw_init(struct meson_dw_mipi_dsi *mipi_dsi)
+{
+ /* Software reset */
+ writel_bits_relaxed(MIPI_DSI_TOP_SW_RESET_DWC | MIPI_DSI_TOP_SW_RESET_INTR |
+ MIPI_DSI_TOP_SW_RESET_DPI | MIPI_DSI_TOP_SW_RESET_TIMING,
+ MIPI_DSI_TOP_SW_RESET_DWC | MIPI_DSI_TOP_SW_RESET_INTR |
+ MIPI_DSI_TOP_SW_RESET_DPI | MIPI_DSI_TOP_SW_RESET_TIMING,
+ mipi_dsi->base + MIPI_DSI_TOP_SW_RESET);
+ writel_bits_relaxed(MIPI_DSI_TOP_SW_RESET_DWC | MIPI_DSI_TOP_SW_RESET_INTR |
+ MIPI_DSI_TOP_SW_RESET_DPI | MIPI_DSI_TOP_SW_RESET_TIMING,
+ 0, mipi_dsi->base + MIPI_DSI_TOP_SW_RESET);
+
+ /* Enable clocks */
+ writel_bits_relaxed(MIPI_DSI_TOP_CLK_SYSCLK_EN | MIPI_DSI_TOP_CLK_PIXCLK_EN,
+ MIPI_DSI_TOP_CLK_SYSCLK_EN | MIPI_DSI_TOP_CLK_PIXCLK_EN,
+ mipi_dsi->base + MIPI_DSI_TOP_CLK_CNTL);
+
+ /* Take memory out of power down */
+ writel_relaxed(0, mipi_dsi->base + MIPI_DSI_TOP_MEM_PD);
+}
+
+static int dw_mipi_dsi_phy_init(void *priv_data)
+{
+ struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
+ unsigned int dpi_data_format, venc_data_width;
+ int ret;
+
+ /* Set the bit clock rate to hs_clk_rate */
+ ret = clk_set_rate(mipi_dsi->bit_clk,
+ mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate);
+ if (ret) {
+ dev_err(mipi_dsi->dev, "Failed to set DSI Bit clock rate %lu (ret %d)\n",
+ mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate, ret);
+ return ret;
+ }
+
+ /* Make sure the rate of the bit clock is not modified by someone else */
+ ret = clk_rate_exclusive_get(mipi_dsi->bit_clk);
+ if (ret) {
+ dev_err(mipi_dsi->dev,
+ "Failed to set the exclusivity on the bit clock rate (ret %d)\n", ret);
+ return ret;
+ }
+
+ ret = clk_set_rate(mipi_dsi->px_clk, mipi_dsi->mode->clock * 1000);
+
+ if (ret) {
+ dev_err(mipi_dsi->dev, "Failed to set DSI Pixel clock rate %u (%d)\n",
+ mipi_dsi->mode->clock * 1000, ret);
+ return ret;
+ }
+
+ switch (mipi_dsi->dsi_device->format) {
+ case MIPI_DSI_FMT_RGB888:
+ dpi_data_format = DPI_COLOR_24BIT;
+ venc_data_width = VENC_IN_COLOR_24B;
+ break;
+ case MIPI_DSI_FMT_RGB666:
+ dpi_data_format = DPI_COLOR_18BIT_CFG_2;
+ venc_data_width = VENC_IN_COLOR_18B;
+ break;
+ case MIPI_DSI_FMT_RGB666_PACKED:
+ case MIPI_DSI_FMT_RGB565:
+ return -EINVAL;
+ }
+
+ /* Configure color format for DPI register */
+ writel_relaxed(FIELD_PREP(MIPI_DSI_TOP_DPI_COLOR_MODE, dpi_data_format) |
+ FIELD_PREP(MIPI_DSI_TOP_IN_COLOR_MODE, venc_data_width) |
+ FIELD_PREP(MIPI_DSI_TOP_COMP2_SEL, 2) |
+ FIELD_PREP(MIPI_DSI_TOP_COMP1_SEL, 1) |
+ FIELD_PREP(MIPI_DSI_TOP_COMP0_SEL, 0),
+ mipi_dsi->base + MIPI_DSI_TOP_CNTL);
+
+ return phy_configure(mipi_dsi->phy, &mipi_dsi->phy_opts);
+}
+
+static void dw_mipi_dsi_phy_power_on(void *priv_data)
+{
+ struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
+
+ if (phy_power_on(mipi_dsi->phy))
+ dev_warn(mipi_dsi->dev, "Failed to power on PHY\n");
+}
+
+static void dw_mipi_dsi_phy_power_off(void *priv_data)
+{
+ struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
+
+ if (phy_power_off(mipi_dsi->phy))
+ dev_warn(mipi_dsi->dev, "Failed to power off PHY\n");
+
+ /* Remove the exclusivity on the bit clock rate */
+ clk_rate_exclusive_put(mipi_dsi->bit_clk);
+}
+
+static int
+dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
+ unsigned long mode_flags, u32 lanes, u32 format,
+ unsigned int *lane_mbps)
+{
+ struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
+ int bpp;
+
+ mipi_dsi->mode = mode;
+
+ bpp = mipi_dsi_pixel_format_to_bpp(mipi_dsi->dsi_device->format);
+
+ phy_mipi_dphy_get_default_config(mode->clock * 1000,
+ bpp, mipi_dsi->dsi_device->lanes,
+ &mipi_dsi->phy_opts.mipi_dphy);
+
+ *lane_mbps = DIV_ROUND_UP(mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate, USEC_PER_SEC);
+
+ return 0;
+}
+
+static int
+dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,
+ struct dw_mipi_dsi_dphy_timing *timing)
+{
+ struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
+
+ switch (mipi_dsi->mode->hdisplay) {
+ case 240:
+ case 768:
+ case 1920:
+ case 2560:
+ timing->clk_lp2hs = 23;
+ timing->clk_hs2lp = 38;
+ timing->data_lp2hs = 15;
+ timing->data_hs2lp = 9;
+ break;
+
+ default:
+ timing->clk_lp2hs = 37;
+ timing->clk_hs2lp = 135;
+ timing->data_lp2hs = 50;
+ timing->data_hs2lp = 3;
+ }
+
+ return 0;
+}
+
+static int
+dw_mipi_dsi_get_esc_clk_rate(void *priv_data, unsigned int *esc_clk_rate)
+{
+ *esc_clk_rate = 4; /* Mhz */
+
+ return 0;
+}
+
+static const struct dw_mipi_dsi_phy_ops meson_dw_mipi_dsi_phy_ops = {
+ .init = dw_mipi_dsi_phy_init,
+ .power_on = dw_mipi_dsi_phy_power_on,
+ .power_off = dw_mipi_dsi_phy_power_off,
+ .get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
+ .get_timing = dw_mipi_dsi_phy_get_timing,
+ .get_esc_clk_rate = dw_mipi_dsi_get_esc_clk_rate,
+};
+
+static int meson_dw_mipi_dsi_host_attach(void *priv_data,
+ struct mipi_dsi_device *device)
+{
+ struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
+ int ret;
+
+ mipi_dsi->dsi_device = device;
+
+ switch (device->format) {
+ case MIPI_DSI_FMT_RGB888:
+ break;
+ case MIPI_DSI_FMT_RGB666:
+ break;
+ case MIPI_DSI_FMT_RGB666_PACKED:
+ case MIPI_DSI_FMT_RGB565:
+ dev_err(mipi_dsi->dev, "invalid pixel format %d\n", device->format);
+ return -EINVAL;
+ }
+
+ ret = phy_init(mipi_dsi->phy);
+ if (ret)
+ return ret;
+
+ meson_dw_mipi_dsi_hw_init(mipi_dsi);
+
+ return 0;
+}
+
+static int meson_dw_mipi_dsi_host_detach(void *priv_data,
+ struct mipi_dsi_device *device)
+{
+ struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
+
+ if (device == mipi_dsi->dsi_device)
+ mipi_dsi->dsi_device = NULL;
+ else
+ return -EINVAL;
+
+ return phy_exit(mipi_dsi->phy);
+}
+
+static const struct dw_mipi_dsi_host_ops meson_dw_mipi_dsi_host_ops = {
+ .attach = meson_dw_mipi_dsi_host_attach,
+ .detach = meson_dw_mipi_dsi_host_detach,
+};
+
+static int meson_dw_mipi_dsi_probe(struct platform_device *pdev)
+{
+ struct meson_dw_mipi_dsi *mipi_dsi;
+ struct device *dev = &pdev->dev;
+
+ mipi_dsi = devm_kzalloc(dev, sizeof(*mipi_dsi), GFP_KERNEL);
+ if (!mipi_dsi)
+ return -ENOMEM;
+
+ mipi_dsi->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(mipi_dsi->base))
+ return PTR_ERR(mipi_dsi->base);
+
+ mipi_dsi->phy = devm_phy_get(dev, "dphy");
+ if (IS_ERR(mipi_dsi->phy))
+ return dev_err_probe(dev, PTR_ERR(mipi_dsi->phy),
+ "failed to get mipi dphy\n");
+
+ mipi_dsi->bit_clk = devm_clk_get_enabled(dev, "bit");
+ if (IS_ERR(mipi_dsi->bit_clk)) {
+ int ret = PTR_ERR(mipi_dsi->bit_clk);
+
+ /* TOFIX GP0 on some platforms fails to lock in early boot, defer probe */
+ if (ret == -EIO)
+ ret = -EPROBE_DEFER;
+
+ return dev_err_probe(dev, ret, "Unable to get enabled bit_clk\n");
+ }
+
+ mipi_dsi->px_clk = devm_clk_get_enabled(dev, "px");
+ if (IS_ERR(mipi_dsi->px_clk))
+ return dev_err_probe(dev, PTR_ERR(mipi_dsi->px_clk),
+ "Unable to get enabled px_clk\n");
+
+ /*
+ * We use a TOP reset signal because the APB reset signal
+ * is handled by the TOP control registers.
+ */
+ mipi_dsi->top_rst = devm_reset_control_get_exclusive(dev, "top");
+ if (IS_ERR(mipi_dsi->top_rst))
+ return dev_err_probe(dev, PTR_ERR(mipi_dsi->top_rst),
+ "Unable to get reset control\n");
+
+ reset_control_assert(mipi_dsi->top_rst);
+ usleep_range(10, 20);
+ reset_control_deassert(mipi_dsi->top_rst);
+
+ /* MIPI DSI Controller */
+
+ mipi_dsi->dev = dev;
+ mipi_dsi->pdata.base = mipi_dsi->base;
+ mipi_dsi->pdata.max_data_lanes = 4;
+ mipi_dsi->pdata.phy_ops = &meson_dw_mipi_dsi_phy_ops;
+ mipi_dsi->pdata.host_ops = &meson_dw_mipi_dsi_host_ops;
+ mipi_dsi->pdata.priv_data = mipi_dsi;
+ platform_set_drvdata(pdev, mipi_dsi);
+
+ mipi_dsi->dmd = dw_mipi_dsi_probe(pdev, &mipi_dsi->pdata);
+ if (IS_ERR(mipi_dsi->dmd))
+ return dev_err_probe(dev, PTR_ERR(mipi_dsi->dmd),
+ "Failed to probe dw_mipi_dsi\n");
+
+ return 0;
+}
+
+static int meson_dw_mipi_dsi_remove(struct platform_device *pdev)
+{
+ struct meson_dw_mipi_dsi *mipi_dsi = platform_get_drvdata(pdev);
+
+ dw_mipi_dsi_remove(mipi_dsi->dmd);
+
+ return 0;
+}
+
+static const struct of_device_id meson_dw_mipi_dsi_of_table[] = {
+ { .compatible = "amlogic,meson-g12a-dw-mipi-dsi", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, meson_dw_mipi_dsi_of_table);
+
+static struct platform_driver meson_dw_mipi_dsi_platform_driver = {
+ .probe = meson_dw_mipi_dsi_probe,
+ .remove = meson_dw_mipi_dsi_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = meson_dw_mipi_dsi_of_table,
+ },
+};
+module_platform_driver(meson_dw_mipi_dsi_platform_driver);
+
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.h b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.h
new file mode 100644
index 000000000000..e1bd6b85d6a3
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.h
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved.
+ */
+
+#ifndef __MESON_DW_MIPI_DSI_H
+#define __MESON_DW_MIPI_DSI_H
+
+/* Top-level registers */
+/* [31: 4] Reserved. Default 0.
+ * [3] RW timing_rst_n: Default 1.
+ * 1=Assert SW reset of timing feature. 0=Release reset.
+ * [2] RW dpi_rst_n: Default 1.
+ * 1=Assert SW reset on mipi_dsi_host_dpi block. 0=Release reset.
+ * [1] RW intr_rst_n: Default 1.
+ * 1=Assert SW reset on mipi_dsi_host_intr block. 0=Release reset.
+ * [0] RW dwc_rst_n: Default 1.
+ * 1=Assert SW reset on IP core. 0=Release reset.
+ */
+#define MIPI_DSI_TOP_SW_RESET 0x3c0
+
+#define MIPI_DSI_TOP_SW_RESET_DWC BIT(0)
+#define MIPI_DSI_TOP_SW_RESET_INTR BIT(1)
+#define MIPI_DSI_TOP_SW_RESET_DPI BIT(2)
+#define MIPI_DSI_TOP_SW_RESET_TIMING BIT(3)
+
+/* [31: 5] Reserved. Default 0.
+ * [4] RW manual_edpihalt: Default 0.
+ * 1=Manual suspend VencL; 0=do not suspend VencL.
+ * [3] RW auto_edpihalt_en: Default 0.
+ * 1=Enable IP's edpihalt signal to suspend VencL;
+ * 0=IP's edpihalt signal does not affect VencL.
+ * [2] RW clock_freerun: Apply to auto-clock gate only. Default 0.
+ * 0=Default, use auto-clock gating to save power;
+ * 1=use free-run clock, disable auto-clock gating, for debug mode.
+ * [1] RW enable_pixclk: A manual clock gate option, due to DWC IP does not
+ * have auto-clock gating. 1=Enable pixclk. Default 0.
+ * [0] RW enable_sysclk: A manual clock gate option, due to DWC IP does not
+ * have auto-clock gating. 1=Enable sysclk. Default 0.
+ */
+#define MIPI_DSI_TOP_CLK_CNTL 0x3c4
+
+#define MIPI_DSI_TOP_CLK_SYSCLK_EN BIT(0)
+#define MIPI_DSI_TOP_CLK_PIXCLK_EN BIT(1)
+
+/* [31:24] Reserved. Default 0.
+ * [23:20] RW dpi_color_mode: Define DPI pixel format. Default 0.
+ * 0=16-bit RGB565 config 1;
+ * 1=16-bit RGB565 config 2;
+ * 2=16-bit RGB565 config 3;
+ * 3=18-bit RGB666 config 1;
+ * 4=18-bit RGB666 config 2;
+ * 5=24-bit RGB888;
+ * 6=20-bit YCbCr 4:2:2;
+ * 7=24-bit YCbCr 4:2:2;
+ * 8=16-bit YCbCr 4:2:2;
+ * 9=30-bit RGB;
+ * 10=36-bit RGB;
+ * 11=12-bit YCbCr 4:2:0.
+ * [19] Reserved. Default 0.
+ * [18:16] RW in_color_mode: Define VENC data width. Default 0.
+ * 0=30-bit pixel;
+ * 1=24-bit pixel;
+ * 2=18-bit pixel, RGB666;
+ * 3=16-bit pixel, RGB565.
+ * [15:14] RW chroma_subsample: Define method of chroma subsampling. Default 0.
+ * Applicable to YUV422 or YUV420 only.
+ * 0=Use even pixel's chroma;
+ * 1=Use odd pixel's chroma;
+ * 2=Use averaged value between even and odd pair.
+ * [13:12] RW comp2_sel: Select which component to be Cr or B: Default 2.
+ * 0=comp0; 1=comp1; 2=comp2.
+ * [11:10] RW comp1_sel: Select which component to be Cb or G: Default 1.
+ * 0=comp0; 1=comp1; 2=comp2.
+ * [9: 8] RW comp0_sel: Select which component to be Y or R: Default 0.
+ * 0=comp0; 1=comp1; 2=comp2.
+ * [7] Reserved. Default 0.
+ * [6] RW de_pol: Default 0.
+ * If DE input is active low, set to 1 to invert to active high.
+ * [5] RW hsync_pol: Default 0.
+ * If HS input is active low, set to 1 to invert to active high.
+ * [4] RW vsync_pol: Default 0.
+ * If VS input is active low, set to 1 to invert to active high.
+ * [3] RW dpicolorm: Signal to IP. Default 0.
+ * [2] RW dpishutdn: Signal to IP. Default 0.
+ * [1] Reserved. Default 0.
+ * [0] Reserved. Default 0.
+ */
+#define MIPI_DSI_TOP_CNTL 0x3c8
+
+/* VENC data width */
+#define VENC_IN_COLOR_30B 0x0
+#define VENC_IN_COLOR_24B 0x1
+#define VENC_IN_COLOR_18B 0x2
+#define VENC_IN_COLOR_16B 0x3
+
+/* DPI pixel format */
+#define DPI_COLOR_16BIT_CFG_1 0
+#define DPI_COLOR_16BIT_CFG_2 1
+#define DPI_COLOR_16BIT_CFG_3 2
+#define DPI_COLOR_18BIT_CFG_1 3
+#define DPI_COLOR_18BIT_CFG_2 4
+#define DPI_COLOR_24BIT 5
+#define DPI_COLOR_20BIT_YCBCR_422 6
+#define DPI_COLOR_24BIT_YCBCR_422 7
+#define DPI_COLOR_16BIT_YCBCR_422 8
+#define DPI_COLOR_30BIT 9
+#define DPI_COLOR_36BIT 10
+#define DPI_COLOR_12BIT_YCBCR_420 11
+
+#define MIPI_DSI_TOP_DPI_COLOR_MODE GENMASK(23, 20)
+#define MIPI_DSI_TOP_IN_COLOR_MODE GENMASK(18, 16)
+#define MIPI_DSI_TOP_CHROMA_SUBSAMPLE GENMASK(15, 14)
+#define MIPI_DSI_TOP_COMP2_SEL GENMASK(13, 12)
+#define MIPI_DSI_TOP_COMP1_SEL GENMASK(11, 10)
+#define MIPI_DSI_TOP_COMP0_SEL GENMASK(9, 8)
+#define MIPI_DSI_TOP_DE_INVERT BIT(6)
+#define MIPI_DSI_TOP_HSYNC_INVERT BIT(5)
+#define MIPI_DSI_TOP_VSYNC_INVERT BIT(4)
+#define MIPI_DSI_TOP_DPICOLORM BIT(3)
+#define MIPI_DSI_TOP_DPISHUTDN BIT(2)
+
+#define MIPI_DSI_TOP_SUSPEND_CNTL 0x3cc
+#define MIPI_DSI_TOP_SUSPEND_LINE 0x3d0
+#define MIPI_DSI_TOP_SUSPEND_PIX 0x3d4
+#define MIPI_DSI_TOP_MEAS_CNTL 0x3d8
+/* [0] R stat_edpihalt: edpihalt signal from IP. Default 0. */
+#define MIPI_DSI_TOP_STAT 0x3dc
+#define MIPI_DSI_TOP_MEAS_STAT_TE0 0x3e0
+#define MIPI_DSI_TOP_MEAS_STAT_TE1 0x3e4
+#define MIPI_DSI_TOP_MEAS_STAT_VS0 0x3e8
+#define MIPI_DSI_TOP_MEAS_STAT_VS1 0x3ec
+/* [31:16] RW intr_stat/clr. Default 0.
+ * For each bit, read as this interrupt level status,
+ * write 1 to clear.
+ * [31:22] Reserved
+ * [ 21] stat/clr of eof interrupt
+ * [ 21] vde_fall interrupt
+ * [ 19] stat/clr of de_rise interrupt
+ * [ 18] stat/clr of vs_fall interrupt
+ * [ 17] stat/clr of vs_rise interrupt
+ * [ 16] stat/clr of dwc_edpite interrupt
+ * [15: 0] RW intr_enable. Default 0.
+ * For each bit, 1=enable this interrupt, 0=disable.
+ * [15: 6] Reserved
+ * [ 5] eof interrupt
+ * [ 4] de_fall interrupt
+ * [ 3] de_rise interrupt
+ * [ 2] vs_fall interrupt
+ * [ 1] vs_rise interrupt
+ * [ 0] dwc_edpite interrupt
+ */
+#define MIPI_DSI_TOP_INTR_CNTL_STAT 0x3f0
+// 31: 2 Reserved. Default 0.
+// 1: 0 RW mem_pd. Default 3.
+#define MIPI_DSI_TOP_MEM_PD 0x3f4
+
+#endif /* __MESON_DW_MIPI_DSI_H */
diff --git a/drivers/gpu/drm/meson/meson_encoder_dsi.c b/drivers/gpu/drm/meson/meson_encoder_dsi.c
new file mode 100644
index 000000000000..812e172dec63
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_encoder_dsi.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_bridge_connector.h>
+#include <drm/drm_device.h>
+#include <drm/drm_probe_helper.h>
+
+#include "meson_drv.h"
+#include "meson_encoder_dsi.h"
+#include "meson_registers.h"
+#include "meson_venc.h"
+#include "meson_vclk.h"
+
+struct meson_encoder_dsi {
+ struct drm_encoder encoder;
+ struct drm_bridge bridge;
+ struct drm_bridge *next_bridge;
+ struct meson_drm *priv;
+};
+
+#define bridge_to_meson_encoder_dsi(x) \
+ container_of(x, struct meson_encoder_dsi, bridge)
+
+static int meson_encoder_dsi_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
+{
+ struct meson_encoder_dsi *encoder_dsi = bridge_to_meson_encoder_dsi(bridge);
+
+ return drm_bridge_attach(bridge->encoder, encoder_dsi->next_bridge,
+ &encoder_dsi->bridge, flags);
+}
+
+static void meson_encoder_dsi_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state)
+{
+ struct meson_encoder_dsi *encoder_dsi = bridge_to_meson_encoder_dsi(bridge);
+ struct drm_atomic_state *state = bridge_state->base.state;
+ struct meson_drm *priv = encoder_dsi->priv;
+ struct drm_connector_state *conn_state;
+ struct drm_crtc_state *crtc_state;
+ struct drm_connector *connector;
+
+ connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
+ if (WARN_ON(!connector))
+ return;
+
+ conn_state = drm_atomic_get_new_connector_state(state, connector);
+ if (WARN_ON(!conn_state))
+ return;
+
+ crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+ if (WARN_ON(!crtc_state))
+ return;
+
+ /* ENCL clock setup is handled by CCF */
+
+ meson_venc_mipi_dsi_mode_set(priv, &crtc_state->adjusted_mode);
+ meson_encl_load_gamma(priv);
+
+ writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));
+
+ writel_bits_relaxed(ENCL_VIDEO_MODE_ADV_VFIFO_EN, ENCL_VIDEO_MODE_ADV_VFIFO_EN,
+ priv->io_base + _REG(ENCL_VIDEO_MODE_ADV));
+ writel_relaxed(0, priv->io_base + _REG(ENCL_TST_EN));
+
+ writel_bits_relaxed(BIT(0), 0, priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
+
+ writel_relaxed(1, priv->io_base + _REG(ENCL_VIDEO_EN));
+}
+
+static void meson_encoder_dsi_atomic_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state)
+{
+ struct meson_encoder_dsi *meson_encoder_dsi =
+ bridge_to_meson_encoder_dsi(bridge);
+ struct meson_drm *priv = meson_encoder_dsi->priv;
+
+ writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));
+
+ writel_bits_relaxed(BIT(0), BIT(0), priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
+}
+
+static const struct drm_bridge_funcs meson_encoder_dsi_bridge_funcs = {
+ .attach = meson_encoder_dsi_attach,
+ .atomic_enable = meson_encoder_dsi_atomic_enable,
+ .atomic_disable = meson_encoder_dsi_atomic_disable,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
+};
+
+int meson_encoder_dsi_init(struct meson_drm *priv)
+{
+ struct meson_encoder_dsi *meson_encoder_dsi;
+ struct device_node *remote;
+ int ret;
+
+ meson_encoder_dsi = devm_kzalloc(priv->dev, sizeof(*meson_encoder_dsi), GFP_KERNEL);
+ if (!meson_encoder_dsi)
+ return -ENOMEM;
+
+ /* DSI Transceiver Bridge */
+ remote = of_graph_get_remote_node(priv->dev->of_node, 2, 0);
+ if (!remote) {
+ dev_err(priv->dev, "DSI transceiver device is disabled");
+ return 0;
+ }
+
+ meson_encoder_dsi->next_bridge = of_drm_find_bridge(remote);
+ if (!meson_encoder_dsi->next_bridge) {
+ dev_dbg(priv->dev, "Failed to find DSI transceiver bridge\n");
+ return -EPROBE_DEFER;
+ }
+
+ /* DSI Encoder Bridge */
+ meson_encoder_dsi->bridge.funcs = &meson_encoder_dsi_bridge_funcs;
+ meson_encoder_dsi->bridge.of_node = priv->dev->of_node;
+ meson_encoder_dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
+
+ drm_bridge_add(&meson_encoder_dsi->bridge);
+
+ meson_encoder_dsi->priv = priv;
+
+ /* Encoder */
+ ret = drm_simple_encoder_init(priv->drm, &meson_encoder_dsi->encoder,
+ DRM_MODE_ENCODER_DSI);
+ if (ret) {
+ dev_err(priv->dev, "Failed to init DSI encoder: %d\n", ret);
+ return ret;
+ }
+
+ meson_encoder_dsi->encoder.possible_crtcs = BIT(0);
+
+ /* Attach DSI Encoder Bridge to Encoder */
+ ret = drm_bridge_attach(&meson_encoder_dsi->encoder, &meson_encoder_dsi->bridge, NULL, 0);
+ if (ret) {
+ dev_err(priv->dev, "Failed to attach bridge: %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * We should have now in place:
+ * encoder->[dsi encoder bridge]->[dw-mipi-dsi bridge]->[panel bridge]->[panel]
+ */
+
+ priv->encoders[MESON_ENC_DSI] = meson_encoder_dsi;
+
+ dev_dbg(priv->dev, "DSI encoder initialized\n");
+
+ return 0;
+}
+
+void meson_encoder_dsi_remove(struct meson_drm *priv)
+{
+ struct meson_encoder_dsi *meson_encoder_dsi;
+
+ if (priv->encoders[MESON_ENC_DSI]) {
+ meson_encoder_dsi = priv->encoders[MESON_ENC_DSI];
+ drm_bridge_remove(&meson_encoder_dsi->bridge);
+ drm_bridge_remove(meson_encoder_dsi->next_bridge);
+ }
+}
diff --git a/drivers/gpu/drm/meson/meson_encoder_dsi.h b/drivers/gpu/drm/meson/meson_encoder_dsi.h
new file mode 100644
index 000000000000..9277d7015193
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_encoder_dsi.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2021 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#ifndef __MESON_ENCODER_DSI_H
+#define __MESON_ENCODER_DSI_H
+
+int meson_encoder_dsi_init(struct meson_drm *priv);
+void meson_encoder_dsi_remove(struct meson_drm *priv);
+
+#endif /* __MESON_ENCODER_DSI_H */
diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h
index 0f3cafab8860..3d73d00a1f4c 100644
--- a/drivers/gpu/drm/meson/meson_registers.h
+++ b/drivers/gpu/drm/meson/meson_registers.h
@@ -812,6 +812,7 @@
#define VENC_STATA 0x1b6d
#define VENC_INTCTRL 0x1b6e
#define VENC_INTCTRL_ENCI_LNRST_INT_EN BIT(1)
+#define VENC_INTCTRL_ENCP_LNRST_INT_EN BIT(9)
#define VENC_INTFLAG 0x1b6f
#define VENC_VIDEO_TST_EN 0x1b70
#define VENC_VIDEO_TST_MDSEL 0x1b71
@@ -1192,7 +1193,11 @@
#define ENCL_VIDEO_PB_OFFST 0x1ca5
#define ENCL_VIDEO_PR_OFFST 0x1ca6
#define ENCL_VIDEO_MODE 0x1ca7
+#define ENCL_PX_LN_CNT_SHADOW_EN BIT(15)
#define ENCL_VIDEO_MODE_ADV 0x1ca8
+#define ENCL_VIDEO_MODE_ADV_VFIFO_EN BIT(3)
+#define ENCL_VIDEO_MODE_ADV_GAIN_HDTV BIT(4)
+#define ENCL_SEL_GAMMA_RGB_IN BIT(10)
#define ENCL_DBG_PX_RST 0x1ca9
#define ENCL_DBG_LN_RST 0x1caa
#define ENCL_DBG_PX_INT 0x1cab
@@ -1219,11 +1224,14 @@
#define ENCL_VIDEO_VOFFST 0x1cc0
#define ENCL_VIDEO_RGB_CTRL 0x1cc1
#define ENCL_VIDEO_FILT_CTRL 0x1cc2
+#define ENCL_VIDEO_FILT_CTRL_BYPASS_FILTER BIT(12)
#define ENCL_VIDEO_OFLD_VPEQ_OFST 0x1cc3
#define ENCL_VIDEO_OFLD_VOAV_OFST 0x1cc4
#define ENCL_VIDEO_MATRIX_CB 0x1cc5
#define ENCL_VIDEO_MATRIX_CR 0x1cc6
#define ENCL_VIDEO_RGBIN_CTRL 0x1cc7
+#define ENCL_VIDEO_RGBIN_RGB BIT(0)
+#define ENCL_VIDEO_RGBIN_ZBLK BIT(1)
#define ENCL_MAX_LINE_SWITCH_POINT 0x1cc8
#define ENCL_DACSEL_0 0x1cc9
#define ENCL_DACSEL_1 0x1cca
@@ -1300,13 +1308,28 @@
#define RDMA_STATUS2 0x1116
#define RDMA_STATUS3 0x1117
#define L_GAMMA_CNTL_PORT 0x1400
+#define L_GAMMA_CNTL_PORT_VCOM_POL BIT(7) /* RW */
+#define L_GAMMA_CNTL_PORT_RVS_OUT BIT(6) /* RW */
+#define L_GAMMA_CNTL_PORT_ADR_RDY BIT(5) /* Read Only */
+#define L_GAMMA_CNTL_PORT_WR_RDY BIT(4) /* Read Only */
+#define L_GAMMA_CNTL_PORT_RD_RDY BIT(3) /* Read Only */
+#define L_GAMMA_CNTL_PORT_TR BIT(2) /* RW */
+#define L_GAMMA_CNTL_PORT_SET BIT(1) /* RW */
+#define L_GAMMA_CNTL_PORT_EN BIT(0) /* RW */
#define L_GAMMA_DATA_PORT 0x1401
#define L_GAMMA_ADDR_PORT 0x1402
+#define L_GAMMA_ADDR_PORT_RD BIT(12)
+#define L_GAMMA_ADDR_PORT_AUTO_INC BIT(11)
+#define L_GAMMA_ADDR_PORT_SEL_R BIT(10)
+#define L_GAMMA_ADDR_PORT_SEL_G BIT(9)
+#define L_GAMMA_ADDR_PORT_SEL_B BIT(8)
+#define L_GAMMA_ADDR_PORT_ADDR GENMASK(7, 0)
#define L_GAMMA_VCOM_HSWITCH_ADDR 0x1403
#define L_RGB_BASE_ADDR 0x1405
#define L_RGB_COEFF_ADDR 0x1406
#define L_POL_CNTL_ADDR 0x1407
#define L_DITH_CNTL_ADDR 0x1408
+#define L_DITH_CNTL_DITH10_EN BIT(10)
#define L_GAMMA_PROBE_CTRL 0x1409
#define L_GAMMA_PROBE_COLOR_L 0x140a
#define L_GAMMA_PROBE_COLOR_H 0x140b
@@ -1363,6 +1386,8 @@
#define L_LCD_PWM1_HI_ADDR 0x143f
#define L_INV_CNT_ADDR 0x1440
#define L_TCON_MISC_SEL_ADDR 0x1441
+#define L_TCON_MISC_SEL_STV1 BIT(4)
+#define L_TCON_MISC_SEL_STV2 BIT(5)
#define L_DUAL_PORT_CNTL_ADDR 0x1442
#define MLVDS_CLK_CTL1_HI 0x1443
#define MLVDS_CLK_CTL1_LO 0x1444
diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
index fcd532db19c1..3bf0d6e4fc30 100644
--- a/drivers/gpu/drm/meson/meson_venc.c
+++ b/drivers/gpu/drm/meson/meson_venc.c
@@ -5,7 +5,9 @@
* Copyright (C) 2015 Amlogic, Inc. All rights reserved.
*/
+#include <linux/bitfield.h>
#include <linux/export.h>
+#include <linux/iopoll.h>
#include <drm/drm_modes.h>
@@ -186,7 +188,7 @@ union meson_hdmi_venc_mode {
} encp;
};
-union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
+static union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
.enci = {
.hso_begin = 5,
.hso_end = 129,
@@ -206,7 +208,7 @@ union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
+static union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
.enci = {
.hso_begin = 3,
.hso_end = 129,
@@ -226,7 +228,7 @@ union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_480p = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_480p = {
.encp = {
.dvi_settings = 0x21,
.video_mode = 0x4000,
@@ -272,7 +274,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_480p = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_576p = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_576p = {
.encp = {
.dvi_settings = 0x21,
.video_mode = 0x4000,
@@ -318,7 +320,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_576p = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p60 = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p60 = {
.encp = {
.dvi_settings = 0x2029,
.video_mode = 0x4040,
@@ -360,7 +362,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p60 = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p50 = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p50 = {
.encp = {
.dvi_settings = 0x202d,
.video_mode = 0x4040,
@@ -405,7 +407,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p50 = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i60 = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i60 = {
.encp = {
.dvi_settings = 0x2029,
.video_mode = 0x5ffc,
@@ -454,7 +456,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i60 = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i50 = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i50 = {
.encp = {
.dvi_settings = 0x202d,
.video_mode = 0x5ffc,
@@ -503,7 +505,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i50 = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p24 = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p24 = {
.encp = {
.dvi_settings = 0xd,
.video_mode = 0x4040,
@@ -552,7 +554,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p24 = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p30 = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p30 = {
.encp = {
.dvi_settings = 0x1,
.video_mode = 0x4040,
@@ -596,7 +598,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p30 = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p50 = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p50 = {
.encp = {
.dvi_settings = 0xd,
.video_mode = 0x4040,
@@ -644,7 +646,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p50 = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
.encp = {
.dvi_settings = 0x1,
.video_mode = 0x4040,
@@ -688,7 +690,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p24 = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p24 = {
.encp = {
.dvi_settings = 0x1,
.video_mode = 0x4040,
@@ -730,7 +732,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p24 = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p25 = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p25 = {
.encp = {
.dvi_settings = 0x1,
.video_mode = 0x4040,
@@ -772,7 +774,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p25 = {
},
};
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p30 = {
+static union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p30 = {
.encp = {
.dvi_settings = 0x1,
.video_mode = 0x4040,
@@ -814,7 +816,7 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p30 = {
},
};
-struct meson_hdmi_venc_vic_mode {
+static struct meson_hdmi_venc_vic_mode {
unsigned int vic;
union meson_hdmi_venc_mode *mode;
} meson_hdmi_venc_vic_modes[] = {
@@ -1557,6 +1559,205 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
}
EXPORT_SYMBOL_GPL(meson_venc_hdmi_mode_set);
+static unsigned short meson_encl_gamma_table[256] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
+ 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124,
+ 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188,
+ 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252,
+ 256, 260, 264, 268, 272, 276, 280, 284, 288, 292, 296, 300, 304, 308, 312, 316,
+ 320, 324, 328, 332, 336, 340, 344, 348, 352, 356, 360, 364, 368, 372, 376, 380,
+ 384, 388, 392, 396, 400, 404, 408, 412, 416, 420, 424, 428, 432, 436, 440, 444,
+ 448, 452, 456, 460, 464, 468, 472, 476, 480, 484, 488, 492, 496, 500, 504, 508,
+ 512, 516, 520, 524, 528, 532, 536, 540, 544, 548, 552, 556, 560, 564, 568, 572,
+ 576, 580, 584, 588, 592, 596, 600, 604, 608, 612, 616, 620, 624, 628, 632, 636,
+ 640, 644, 648, 652, 656, 660, 664, 668, 672, 676, 680, 684, 688, 692, 696, 700,
+ 704, 708, 712, 716, 720, 724, 728, 732, 736, 740, 744, 748, 752, 756, 760, 764,
+ 768, 772, 776, 780, 784, 788, 792, 796, 800, 804, 808, 812, 816, 820, 824, 828,
+ 832, 836, 840, 844, 848, 852, 856, 860, 864, 868, 872, 876, 880, 884, 888, 892,
+ 896, 900, 904, 908, 912, 916, 920, 924, 928, 932, 936, 940, 944, 948, 952, 956,
+ 960, 964, 968, 972, 976, 980, 984, 988, 992, 996, 1000, 1004, 1008, 1012, 1016, 1020,
+};
+
+static void meson_encl_set_gamma_table(struct meson_drm *priv, u16 *data,
+ u32 rgb_mask)
+{
+ int i, ret;
+ u32 reg;
+
+ writel_bits_relaxed(L_GAMMA_CNTL_PORT_EN, 0,
+ priv->io_base + _REG(L_GAMMA_CNTL_PORT));
+
+ ret = readl_relaxed_poll_timeout(priv->io_base + _REG(L_GAMMA_CNTL_PORT),
+ reg, reg & L_GAMMA_CNTL_PORT_ADR_RDY, 10, 10000);
+ if (ret)
+ pr_warn("%s: GAMMA ADR_RDY timeout\n", __func__);
+
+ writel_relaxed(L_GAMMA_ADDR_PORT_AUTO_INC | rgb_mask |
+ FIELD_PREP(L_GAMMA_ADDR_PORT_ADDR, 0),
+ priv->io_base + _REG(L_GAMMA_ADDR_PORT));
+
+ for (i = 0; i < 256; i++) {
+ ret = readl_relaxed_poll_timeout(priv->io_base + _REG(L_GAMMA_CNTL_PORT),
+ reg, reg & L_GAMMA_CNTL_PORT_WR_RDY,
+ 10, 10000);
+ if (ret)
+ pr_warn_once("%s: GAMMA WR_RDY timeout\n", __func__);
+
+ writel_relaxed(data[i], priv->io_base + _REG(L_GAMMA_DATA_PORT));
+ }
+
+ ret = readl_relaxed_poll_timeout(priv->io_base + _REG(L_GAMMA_CNTL_PORT),
+ reg, reg & L_GAMMA_CNTL_PORT_ADR_RDY, 10, 10000);
+ if (ret)
+ pr_warn("%s: GAMMA ADR_RDY timeout\n", __func__);
+
+ writel_relaxed(L_GAMMA_ADDR_PORT_AUTO_INC | rgb_mask |
+ FIELD_PREP(L_GAMMA_ADDR_PORT_ADDR, 0x23),
+ priv->io_base + _REG(L_GAMMA_ADDR_PORT));
+}
+
+void meson_encl_load_gamma(struct meson_drm *priv)
+{
+ meson_encl_set_gamma_table(priv, meson_encl_gamma_table, L_GAMMA_ADDR_PORT_SEL_R);
+ meson_encl_set_gamma_table(priv, meson_encl_gamma_table, L_GAMMA_ADDR_PORT_SEL_G);
+ meson_encl_set_gamma_table(priv, meson_encl_gamma_table, L_GAMMA_ADDR_PORT_SEL_B);
+
+ writel_bits_relaxed(L_GAMMA_CNTL_PORT_EN, L_GAMMA_CNTL_PORT_EN,
+ priv->io_base + _REG(L_GAMMA_CNTL_PORT));
+}
+
+void meson_venc_mipi_dsi_mode_set(struct meson_drm *priv,
+ const struct drm_display_mode *mode)
+{
+ unsigned int max_pxcnt;
+ unsigned int max_lncnt;
+ unsigned int havon_begin;
+ unsigned int havon_end;
+ unsigned int vavon_bline;
+ unsigned int vavon_eline;
+ unsigned int hso_begin;
+ unsigned int hso_end;
+ unsigned int vso_begin;
+ unsigned int vso_end;
+ unsigned int vso_bline;
+ unsigned int vso_eline;
+
+ max_pxcnt = mode->htotal - 1;
+ max_lncnt = mode->vtotal - 1;
+ havon_begin = mode->htotal - mode->hsync_start;
+ havon_end = havon_begin + mode->hdisplay - 1;
+ vavon_bline = mode->vtotal - mode->vsync_start;
+ vavon_eline = vavon_bline + mode->vdisplay - 1;
+ hso_begin = 0;
+ hso_end = mode->hsync_end - mode->hsync_start;
+ vso_begin = 0;
+ vso_end = 0;
+ vso_bline = 0;
+ vso_eline = mode->vsync_end - mode->vsync_start;
+
+ meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCL);
+
+ writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));
+
+ writel_relaxed(ENCL_PX_LN_CNT_SHADOW_EN, priv->io_base + _REG(ENCL_VIDEO_MODE));
+ writel_relaxed(ENCL_VIDEO_MODE_ADV_VFIFO_EN |
+ ENCL_VIDEO_MODE_ADV_GAIN_HDTV |
+ ENCL_SEL_GAMMA_RGB_IN, priv->io_base + _REG(ENCL_VIDEO_MODE_ADV));
+
+ writel_relaxed(ENCL_VIDEO_FILT_CTRL_BYPASS_FILTER,
+ priv->io_base + _REG(ENCL_VIDEO_FILT_CTRL));
+ writel_relaxed(max_pxcnt, priv->io_base + _REG(ENCL_VIDEO_MAX_PXCNT));
+ writel_relaxed(max_lncnt, priv->io_base + _REG(ENCL_VIDEO_MAX_LNCNT));
+ writel_relaxed(havon_begin, priv->io_base + _REG(ENCL_VIDEO_HAVON_BEGIN));
+ writel_relaxed(havon_end, priv->io_base + _REG(ENCL_VIDEO_HAVON_END));
+ writel_relaxed(vavon_bline, priv->io_base + _REG(ENCL_VIDEO_VAVON_BLINE));
+ writel_relaxed(vavon_eline, priv->io_base + _REG(ENCL_VIDEO_VAVON_ELINE));
+
+ writel_relaxed(hso_begin, priv->io_base + _REG(ENCL_VIDEO_HSO_BEGIN));
+ writel_relaxed(hso_end, priv->io_base + _REG(ENCL_VIDEO_HSO_END));
+ writel_relaxed(vso_begin, priv->io_base + _REG(ENCL_VIDEO_VSO_BEGIN));
+ writel_relaxed(vso_end, priv->io_base + _REG(ENCL_VIDEO_VSO_END));
+ writel_relaxed(vso_bline, priv->io_base + _REG(ENCL_VIDEO_VSO_BLINE));
+ writel_relaxed(vso_eline, priv->io_base + _REG(ENCL_VIDEO_VSO_ELINE));
+ writel_relaxed(ENCL_VIDEO_RGBIN_RGB | ENCL_VIDEO_RGBIN_ZBLK,
+ priv->io_base + _REG(ENCL_VIDEO_RGBIN_CTRL));
+
+ /* default black pattern */
+ writel_relaxed(0, priv->io_base + _REG(ENCL_TST_MDSEL));
+ writel_relaxed(0, priv->io_base + _REG(ENCL_TST_Y));
+ writel_relaxed(0, priv->io_base + _REG(ENCL_TST_CB));
+ writel_relaxed(0, priv->io_base + _REG(ENCL_TST_CR));
+ writel_relaxed(1, priv->io_base + _REG(ENCL_TST_EN));
+ writel_bits_relaxed(ENCL_VIDEO_MODE_ADV_VFIFO_EN, 0,
+ priv->io_base + _REG(ENCL_VIDEO_MODE_ADV));
+
+ writel_relaxed(1, priv->io_base + _REG(ENCL_VIDEO_EN));
+
+ writel_relaxed(0, priv->io_base + _REG(L_RGB_BASE_ADDR));
+ writel_relaxed(0x400, priv->io_base + _REG(L_RGB_COEFF_ADDR)); /* Magic value */
+
+ writel_relaxed(L_DITH_CNTL_DITH10_EN, priv->io_base + _REG(L_DITH_CNTL_ADDR));
+
+ /* DE signal for TTL */
+ writel_relaxed(havon_begin, priv->io_base + _REG(L_OEH_HS_ADDR));
+ writel_relaxed(havon_end + 1, priv->io_base + _REG(L_OEH_HE_ADDR));
+ writel_relaxed(vavon_bline, priv->io_base + _REG(L_OEH_VS_ADDR));
+ writel_relaxed(vavon_eline, priv->io_base + _REG(L_OEH_VE_ADDR));
+
+ /* DE signal for TTL */
+ writel_relaxed(havon_begin, priv->io_base + _REG(L_OEV1_HS_ADDR));
+ writel_relaxed(havon_end + 1, priv->io_base + _REG(L_OEV1_HE_ADDR));
+ writel_relaxed(vavon_bline, priv->io_base + _REG(L_OEV1_VS_ADDR));
+ writel_relaxed(vavon_eline, priv->io_base + _REG(L_OEV1_VE_ADDR));
+
+ /* Hsync signal for TTL */
+ if (mode->flags & DRM_MODE_FLAG_PHSYNC) {
+ writel_relaxed(hso_begin, priv->io_base + _REG(L_STH1_HS_ADDR));
+ writel_relaxed(hso_end, priv->io_base + _REG(L_STH1_HE_ADDR));
+ } else {
+ writel_relaxed(hso_end, priv->io_base + _REG(L_STH1_HS_ADDR));
+ writel_relaxed(hso_begin, priv->io_base + _REG(L_STH1_HE_ADDR));
+ }
+ writel_relaxed(0, priv->io_base + _REG(L_STH1_VS_ADDR));
+ writel_relaxed(max_lncnt, priv->io_base + _REG(L_STH1_VE_ADDR));
+
+ /* Vsync signal for TTL */
+ writel_relaxed(vso_begin, priv->io_base + _REG(L_STV1_HS_ADDR));
+ writel_relaxed(vso_end, priv->io_base + _REG(L_STV1_HE_ADDR));
+ if (mode->flags & DRM_MODE_FLAG_PVSYNC) {
+ writel_relaxed(vso_bline, priv->io_base + _REG(L_STV1_VS_ADDR));
+ writel_relaxed(vso_eline, priv->io_base + _REG(L_STV1_VE_ADDR));
+ } else {
+ writel_relaxed(vso_eline, priv->io_base + _REG(L_STV1_VS_ADDR));
+ writel_relaxed(vso_bline, priv->io_base + _REG(L_STV1_VE_ADDR));
+ }
+
+ /* DE signal */
+ writel_relaxed(havon_begin, priv->io_base + _REG(L_DE_HS_ADDR));
+ writel_relaxed(havon_end + 1, priv->io_base + _REG(L_DE_HE_ADDR));
+ writel_relaxed(vavon_bline, priv->io_base + _REG(L_DE_VS_ADDR));
+ writel_relaxed(vavon_eline, priv->io_base + _REG(L_DE_VE_ADDR));
+
+ /* Hsync signal */
+ writel_relaxed(hso_begin, priv->io_base + _REG(L_HSYNC_HS_ADDR));
+ writel_relaxed(hso_end, priv->io_base + _REG(L_HSYNC_HE_ADDR));
+ writel_relaxed(0, priv->io_base + _REG(L_HSYNC_VS_ADDR));
+ writel_relaxed(max_lncnt, priv->io_base + _REG(L_HSYNC_VE_ADDR));
+
+ /* Vsync signal */
+ writel_relaxed(vso_begin, priv->io_base + _REG(L_VSYNC_HS_ADDR));
+ writel_relaxed(vso_end, priv->io_base + _REG(L_VSYNC_HE_ADDR));
+ writel_relaxed(vso_bline, priv->io_base + _REG(L_VSYNC_VS_ADDR));
+ writel_relaxed(vso_eline, priv->io_base + _REG(L_VSYNC_VE_ADDR));
+
+ writel_relaxed(0, priv->io_base + _REG(L_INV_CNT_ADDR));
+ writel_relaxed(L_TCON_MISC_SEL_STV1 | L_TCON_MISC_SEL_STV2,
+ priv->io_base + _REG(L_TCON_MISC_SEL_ADDR));
+
+ priv->venc.current_mode = MESON_VENC_MODE_MIPI_DSI;
+}
+EXPORT_SYMBOL_GPL(meson_venc_mipi_dsi_mode_set);
+
void meson_venci_cvbs_mode_set(struct meson_drm *priv,
struct meson_cvbs_enci_mode *mode)
{
@@ -1747,8 +1948,15 @@ unsigned int meson_venci_get_field(struct meson_drm *priv)
void meson_venc_enable_vsync(struct meson_drm *priv)
{
- writel_relaxed(VENC_INTCTRL_ENCI_LNRST_INT_EN,
- priv->io_base + _REG(VENC_INTCTRL));
+ switch (priv->venc.current_mode) {
+ case MESON_VENC_MODE_MIPI_DSI:
+ writel_relaxed(VENC_INTCTRL_ENCP_LNRST_INT_EN,
+ priv->io_base + _REG(VENC_INTCTRL));
+ break;
+ default:
+ writel_relaxed(VENC_INTCTRL_ENCI_LNRST_INT_EN,
+ priv->io_base + _REG(VENC_INTCTRL));
+ }
regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), BIT(25));
}
diff --git a/drivers/gpu/drm/meson/meson_venc.h b/drivers/gpu/drm/meson/meson_venc.h
index 9138255ffc9e..0f59adb1c6db 100644
--- a/drivers/gpu/drm/meson/meson_venc.h
+++ b/drivers/gpu/drm/meson/meson_venc.h
@@ -21,6 +21,7 @@ enum {
MESON_VENC_MODE_CVBS_PAL,
MESON_VENC_MODE_CVBS_NTSC,
MESON_VENC_MODE_HDMI,
+ MESON_VENC_MODE_MIPI_DSI,
};
struct meson_cvbs_enci_mode {
@@ -47,6 +48,9 @@ struct meson_cvbs_enci_mode {
unsigned int analog_sync_adj;
};
+/* LCD Encoder gamma setup */
+void meson_encl_load_gamma(struct meson_drm *priv);
+
/* HDMI Clock parameters */
enum drm_mode_status
meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode);
@@ -63,6 +67,8 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
unsigned int ycrcb_map,
bool yuv420_mode,
const struct drm_display_mode *mode);
+void meson_venc_mipi_dsi_mode_set(struct meson_drm *priv,
+ const struct drm_display_mode *mode);
unsigned int meson_venci_get_field(struct meson_drm *priv);
void meson_venc_enable_vsync(struct meson_drm *priv);
diff --git a/drivers/gpu/drm/meson/meson_vpp.h b/drivers/gpu/drm/meson/meson_vpp.h
index afc9553ed8d3..b790042a1650 100644
--- a/drivers/gpu/drm/meson/meson_vpp.h
+++ b/drivers/gpu/drm/meson/meson_vpp.h
@@ -12,6 +12,8 @@
struct drm_rect;
struct meson_drm;
+/* Mux VIU/VPP to ENCL */
+#define MESON_VIU_VPP_MUX_ENCL 0x0
/* Mux VIU/VPP to ENCI */
#define MESON_VIU_VPP_MUX_ENCI 0x5
/* Mux VIU/VPP to ENCP */
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 85f5ab1d552c..a78662bd6273 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -21,6 +21,7 @@ config DRM_MSM
select DRM_BRIDGE
select DRM_PANEL_BRIDGE
select DRM_SCHED
+ select FB_SYS_HELPERS if DRM_FBDEV_EMULATION
select SHMEM
select TMPFS
select QCOM_SCM
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 7274c41228ed..8d02d8c33069 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -65,6 +65,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
disp/dpu1/dpu_hw_catalog.o \
disp/dpu1/dpu_hw_ctl.o \
disp/dpu1/dpu_hw_dsc.o \
+ disp/dpu1/dpu_hw_dsc_1_2.o \
disp/dpu1/dpu_hw_interrupts.o \
disp/dpu1/dpu_hw_intf.o \
disp/dpu1/dpu_hw_lm.o \
@@ -122,7 +123,6 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \
dp/dp_ctrl.o \
dp/dp_display.o \
dp/dp_drm.o \
- dp/dp_hpd.o \
dp/dp_link.o \
dp/dp_panel.o \
dp/dp_parser.o \
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
index 6bd397a85834..169b8fe688f8 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
@@ -69,7 +69,7 @@ static void roq_print(struct msm_gpu *gpu, struct drm_printer *p)
static int show(struct seq_file *m, void *arg)
{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_info_node *node = m->private;
struct drm_device *dev = node->minor->dev;
struct msm_drm_private *priv = dev->dev_private;
struct drm_printer p = drm_seq_file_printer(m);
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 1e8d2982d603..a99310b68793 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -1743,6 +1743,7 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
{
struct msm_drm_private *priv = dev->dev_private;
struct platform_device *pdev = priv->gpu_pdev;
+ struct adreno_platform_config *config = pdev->dev.platform_data;
struct a5xx_gpu *a5xx_gpu = NULL;
struct adreno_gpu *adreno_gpu;
struct msm_gpu *gpu;
@@ -1769,7 +1770,7 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
nr_rings = 4;
- if (adreno_is_a510(adreno_gpu))
+ if (adreno_cmp_rev(ADRENO_REV(5, 1, 0, ANY_ID), config->rev))
nr_rings = 1;
ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, nr_rings);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 8914992378f2..5deb79924897 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -354,7 +354,7 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
}
/* Enable CPU control of SPTP power power collapse */
-static int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
+int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
{
int ret;
u32 val;
@@ -376,7 +376,7 @@ static int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
}
/* Disable CPU control of SPTP power power collapse */
-static void a6xx_sptprac_disable(struct a6xx_gmu *gmu)
+void a6xx_sptprac_disable(struct a6xx_gmu *gmu)
{
u32 val;
int ret;
@@ -479,12 +479,6 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu)
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0);
- /* Set up CX GMU counter 0 to count busy ticks */
- gmu_write(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000);
- gmu_rmw(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, 0x20);
-
- /* Enable the power counter */
- gmu_write(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1);
return 0;
}
@@ -868,43 +862,6 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu)
(val & 1), 100, 1000);
}
-#define GBIF_CLIENT_HALT_MASK BIT(0)
-#define GBIF_ARB_HALT_MASK BIT(1)
-
-static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu,
- bool gx_off)
-{
- struct msm_gpu *gpu = &adreno_gpu->base;
-
- if (!a6xx_has_gbif(adreno_gpu)) {
- gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf);
- spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) &
- 0xf) == 0xf);
- gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0);
-
- return;
- }
-
- if (gx_off) {
- /* Halt the gx side of GBIF */
- gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 1);
- spin_until(gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT_ACK) & 1);
- }
-
- /* Halt new client requests on GBIF */
- gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK);
- spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) &
- (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK);
-
- /* Halt all AXI requests on GBIF */
- gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK);
- spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) &
- (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK);
-
- /* The GBIF halt needs to be explicitly cleared */
- gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0);
-}
-
/* Force the GMU off in case it isn't responsive */
static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
{
@@ -912,6 +869,12 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
struct msm_gpu *gpu = &adreno_gpu->base;
+ /*
+ * Turn off keep alive that might have been enabled by the hang
+ * interrupt
+ */
+ gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 0);
+
/* Flush all the queues */
a6xx_hfi_stop(gmu);
@@ -930,8 +893,7 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu)
a6xx_bus_clear_pending_transactions(adreno_gpu, true);
/* Reset GPU core blocks */
- gpu_write(gpu, REG_A6XX_RBBM_SW_RESET_CMD, 1);
- udelay(100);
+ a6xx_gpu_sw_reset(gpu, true);
}
static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu)
@@ -1469,6 +1431,7 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev,
void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
{
+ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
struct platform_device *pdev = to_platform_device(gmu->dev);
@@ -1494,10 +1457,12 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
gmu->mmio = NULL;
gmu->rscc = NULL;
- a6xx_gmu_memory_free(gmu);
+ if (!adreno_has_gmu_wrapper(adreno_gpu)) {
+ a6xx_gmu_memory_free(gmu);
- free_irq(gmu->gmu_irq, gmu);
- free_irq(gmu->hfi_irq, gmu);
+ free_irq(gmu->gmu_irq, gmu);
+ free_irq(gmu->hfi_irq, gmu);
+ }
/* Drop reference taken in of_find_device_by_node */
put_device(gmu->dev);
@@ -1516,6 +1481,69 @@ static int cxpd_notifier_cb(struct notifier_block *nb,
return 0;
}
+int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
+{
+ struct platform_device *pdev = of_find_device_by_node(node);
+ struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+ int ret;
+
+ if (!pdev)
+ return -ENODEV;
+
+ gmu->dev = &pdev->dev;
+
+ of_dma_configure(gmu->dev, node, true);
+
+ pm_runtime_enable(gmu->dev);
+
+ /* Mark legacy for manual SPTPRAC control */
+ gmu->legacy = true;
+
+ /* Map the GMU registers */
+ gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
+ if (IS_ERR(gmu->mmio)) {
+ ret = PTR_ERR(gmu->mmio);
+ goto err_mmio;
+ }
+
+ gmu->cxpd = dev_pm_domain_attach_by_name(gmu->dev, "cx");
+ if (IS_ERR(gmu->cxpd)) {
+ ret = PTR_ERR(gmu->cxpd);
+ goto err_mmio;
+ }
+
+ if (!device_link_add(gmu->dev, gmu->cxpd, DL_FLAG_PM_RUNTIME)) {
+ ret = -ENODEV;
+ goto detach_cxpd;
+ }
+
+ init_completion(&gmu->pd_gate);
+ complete_all(&gmu->pd_gate);
+ gmu->pd_nb.notifier_call = cxpd_notifier_cb;
+
+ /* Get a link to the GX power domain to reset the GPU */
+ gmu->gxpd = dev_pm_domain_attach_by_name(gmu->dev, "gx");
+ if (IS_ERR(gmu->gxpd)) {
+ ret = PTR_ERR(gmu->gxpd);
+ goto err_mmio;
+ }
+
+ gmu->initialized = true;
+
+ return 0;
+
+detach_cxpd:
+ dev_pm_domain_detach(gmu->cxpd, false);
+
+err_mmio:
+ iounmap(gmu->mmio);
+
+ /* Drop reference taken in of_find_device_by_node */
+ put_device(gmu->dev);
+
+ return ret;
+}
+
int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
{
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 0bc3eb443fec..236f81a43caa 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -51,8 +51,8 @@ struct a6xx_gmu {
struct msm_gem_address_space *aspace;
- void * __iomem mmio;
- void * __iomem rscc;
+ void __iomem *mmio;
+ void __iomem *rscc;
int hfi_irq;
int gmu_irq;
@@ -193,5 +193,7 @@ int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index);
bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu);
bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);
+void a6xx_sptprac_disable(struct a6xx_gmu *gmu);
+int a6xx_sptprac_enable(struct a6xx_gmu *gmu);
#endif
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 52da3795b175..b3ada1e7b598 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -21,7 +21,7 @@ static inline bool _a6xx_check_idle(struct msm_gpu *gpu)
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
/* Check that the GMU is idle */
- if (!a6xx_gmu_isidle(&a6xx_gpu->gmu))
+ if (!adreno_has_gmu_wrapper(adreno_gpu) && !a6xx_gmu_isidle(&a6xx_gpu->gmu))
return false;
/* Check tha the CX master is idle */
@@ -252,6 +252,56 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
a6xx_flush(gpu, ring);
}
+const struct adreno_reglist a612_hwcg[] = {
+ {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
+ {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000081},
+ {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000f3cf},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01202222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040f00},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x05522022},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
+ {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
+ {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+ {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+ {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
+ {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+ {REG_A6XX_RBBM_ISDB_CNT, 0x00000182},
+ {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000},
+ {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
+ {},
+};
+
/* For a615 family (a615, a616, a618 and a619) */
const struct adreno_reglist a615_hwcg[] = {
{REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
@@ -588,6 +638,63 @@ const struct adreno_reglist a660_hwcg[] = {
{},
};
+const struct adreno_reglist a690_hwcg[] = {
+ {REG_A6XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
+ {REG_A6XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
+ {REG_A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
+ {REG_A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
+ {REG_A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777},
+ {REG_A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01002222},
+ {REG_A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
+ {REG_A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
+ {REG_A6XX_RBBM_CLOCK_CNTL_RAC, 0x25222022},
+ {REG_A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
+ {REG_A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
+ {REG_A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+ {REG_A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_MODE_GPC, 0x00222222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+ {REG_A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+ {REG_A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+ {REG_A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_TEX_FCHE, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_TEX_FCHE, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_TEX_FCHE, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+ {REG_A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
+ {REG_A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+ {REG_A6XX_RBBM_CLOCK_CNTL, 0x8AA8AA82},
+ {REG_A6XX_RBBM_ISDB_CNT, 0x00000182},
+ {REG_A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000},
+ {REG_A6XX_RBBM_SP_HYST_CNT, 0x00000000},
+ {REG_A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
+ {REG_A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
+ {REG_A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555},
+ {REG_A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL, 0x20200},
+ {REG_A6XX_GPU_GMU_AO_GMU_CGC_DELAY_CNTL, 0x10111},
+ {REG_A6XX_GPU_GMU_AO_GMU_CGC_HYST_CNTL, 0x5555},
+ {}
+};
+
static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -602,6 +709,8 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
if (adreno_is_a630(adreno_gpu))
clock_cntl_on = 0x8aa8aa02;
+ else if (adreno_is_a610(adreno_gpu))
+ clock_cntl_on = 0xaaa8aa82;
else
clock_cntl_on = 0x8aa8aa82;
@@ -612,13 +721,15 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
return;
/* Disable SP clock before programming HWCG registers */
- gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 1, 0);
+ if (!adreno_is_a610(adreno_gpu))
+ gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 1, 0);
for (i = 0; (reg = &adreno_gpu->info->hwcg[i], reg->offset); i++)
gpu_write(gpu, reg->offset, state ? reg->value : 0);
/* Enable SP clock */
- gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 0, 1);
+ if (!adreno_is_a610(adreno_gpu))
+ gmu_rmw(gmu, REG_A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 0, 1);
gpu_write(gpu, REG_A6XX_RBBM_CLOCK_CNTL, state ? clock_cntl_on : 0);
}
@@ -747,6 +858,45 @@ static const u32 a660_protect[] = {
A6XX_PROTECT_NORDWR(0x1f8c0, 0x0000), /* note: infinite range */
};
+/* These are for a690 */
+static const u32 a690_protect[] = {
+ A6XX_PROTECT_RDONLY(0x00000, 0x004ff),
+ A6XX_PROTECT_RDONLY(0x00501, 0x00001),
+ A6XX_PROTECT_RDONLY(0x0050b, 0x002f4),
+ A6XX_PROTECT_NORDWR(0x0050e, 0x00000),
+ A6XX_PROTECT_NORDWR(0x00510, 0x00000),
+ A6XX_PROTECT_NORDWR(0x00534, 0x00000),
+ A6XX_PROTECT_NORDWR(0x00800, 0x00082),
+ A6XX_PROTECT_NORDWR(0x008a0, 0x00008),
+ A6XX_PROTECT_NORDWR(0x008ab, 0x00024),
+ A6XX_PROTECT_RDONLY(0x008de, 0x000ae),
+ A6XX_PROTECT_NORDWR(0x00900, 0x0004d),
+ A6XX_PROTECT_NORDWR(0x0098d, 0x00272),
+ A6XX_PROTECT_NORDWR(0x00e00, 0x00001),
+ A6XX_PROTECT_NORDWR(0x00e03, 0x0000c),
+ A6XX_PROTECT_NORDWR(0x03c00, 0x000c3),
+ A6XX_PROTECT_RDONLY(0x03cc4, 0x01fff),
+ A6XX_PROTECT_NORDWR(0x08630, 0x001cf),
+ A6XX_PROTECT_NORDWR(0x08e00, 0x00000),
+ A6XX_PROTECT_NORDWR(0x08e08, 0x00007),
+ A6XX_PROTECT_NORDWR(0x08e50, 0x0001f),
+ A6XX_PROTECT_NORDWR(0x08e80, 0x0027f),
+ A6XX_PROTECT_NORDWR(0x09624, 0x001db),
+ A6XX_PROTECT_NORDWR(0x09e60, 0x00011),
+ A6XX_PROTECT_NORDWR(0x09e78, 0x00187),
+ A6XX_PROTECT_NORDWR(0x0a630, 0x001cf),
+ A6XX_PROTECT_NORDWR(0x0ae02, 0x00000),
+ A6XX_PROTECT_NORDWR(0x0ae50, 0x0012f),
+ A6XX_PROTECT_NORDWR(0x0b604, 0x00000),
+ A6XX_PROTECT_NORDWR(0x0b608, 0x00006),
+ A6XX_PROTECT_NORDWR(0x0be02, 0x00001),
+ A6XX_PROTECT_NORDWR(0x0be20, 0x0015f),
+ A6XX_PROTECT_NORDWR(0x0d000, 0x005ff),
+ A6XX_PROTECT_NORDWR(0x0f000, 0x00bff),
+ A6XX_PROTECT_RDONLY(0x0fc00, 0x01fff),
+ A6XX_PROTECT_NORDWR(0x11c00, 0x00000), /*note: infiite range */
+};
+
static void a6xx_set_cp_protect(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -758,6 +908,11 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu)
count = ARRAY_SIZE(a650_protect);
count_max = 48;
BUILD_BUG_ON(ARRAY_SIZE(a650_protect) > 48);
+ } else if (adreno_is_a690(adreno_gpu)) {
+ regs = a690_protect;
+ count = ARRAY_SIZE(a690_protect);
+ count_max = 48;
+ BUILD_BUG_ON(ARRAY_SIZE(a690_protect) > 48);
} else if (adreno_is_a660_family(adreno_gpu)) {
regs = a660_protect;
count = ARRAY_SIZE(a660_protect);
@@ -786,39 +941,77 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu)
static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
- u32 lower_bit = 2;
- u32 amsbc = 0;
+ /* Unknown, introduced with A650 family, related to UBWC mode/ver 4 */
u32 rgb565_predicator = 0;
+ /* Unknown, introduced with A650 family */
u32 uavflagprd_inv = 0;
+ /* Whether the minimum access length is 64 bits */
+ u32 min_acc_len = 0;
+ /* Entirely magic, per-GPU-gen value */
+ u32 ubwc_mode = 0;
+ /*
+ * The Highest Bank Bit value represents the bit of the highest DDR bank.
+ * We then subtract 13 from it (13 is the minimum value allowed by hw) and
+ * write the lowest two bits of the remaining value as hbb_lo and the
+ * one above it as hbb_hi to the hardware. This should ideally use DRAM
+ * type detection.
+ */
+ u32 hbb_hi = 0;
+ u32 hbb_lo = 2;
+ /* Unknown, introduced with A640/680 */
+ u32 amsbc = 0;
+
+ if (adreno_is_a610(adreno_gpu)) {
+ /* HBB = 14 */
+ hbb_lo = 1;
+ min_acc_len = 1;
+ ubwc_mode = 1;
+ }
/* a618 is using the hw default values */
if (adreno_is_a618(adreno_gpu))
return;
+ if (adreno_is_a619_holi(adreno_gpu))
+ hbb_lo = 0;
+
if (adreno_is_a640_family(adreno_gpu))
amsbc = 1;
if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu)) {
/* TODO: get ddr type from bootloader and use 2 for LPDDR4 */
- lower_bit = 3;
+ hbb_lo = 3;
+ amsbc = 1;
+ rgb565_predicator = 1;
+ uavflagprd_inv = 2;
+ }
+
+ if (adreno_is_a690(adreno_gpu)) {
+ hbb_lo = 2;
amsbc = 1;
rgb565_predicator = 1;
uavflagprd_inv = 2;
}
if (adreno_is_7c3(adreno_gpu)) {
- lower_bit = 1;
+ hbb_lo = 1;
amsbc = 1;
rgb565_predicator = 1;
uavflagprd_inv = 2;
}
gpu_write(gpu, REG_A6XX_RB_NC_MODE_CNTL,
- rgb565_predicator << 11 | amsbc << 4 | lower_bit << 1);
- gpu_write(gpu, REG_A6XX_TPL1_NC_MODE_CNTL, lower_bit << 1);
- gpu_write(gpu, REG_A6XX_SP_NC_MODE_CNTL,
- uavflagprd_inv << 4 | lower_bit << 1);
- gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL, lower_bit << 21);
+ rgb565_predicator << 11 | hbb_hi << 10 | amsbc << 4 |
+ min_acc_len << 3 | hbb_lo << 1 | ubwc_mode);
+
+ gpu_write(gpu, REG_A6XX_TPL1_NC_MODE_CNTL, hbb_hi << 4 |
+ min_acc_len << 3 | hbb_lo << 1 | ubwc_mode);
+
+ gpu_write(gpu, REG_A6XX_SP_NC_MODE_CNTL, hbb_hi << 10 |
+ uavflagprd_inv << 4 | min_acc_len << 3 |
+ hbb_lo << 1 | ubwc_mode);
+
+ gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL, min_acc_len << 23 | hbb_lo << 21);
}
static int a6xx_cp_init(struct msm_gpu *gpu)
@@ -997,17 +1190,32 @@ static int hw_init(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
int ret;
- /* Make sure the GMU keeps the GPU on while we set it up */
- a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
+ if (!adreno_has_gmu_wrapper(adreno_gpu)) {
+ /* Make sure the GMU keeps the GPU on while we set it up */
+ a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
+ }
/* Clear GBIF halt in case GX domain was not collapsed */
- if (a6xx_has_gbif(adreno_gpu))
+ if (adreno_is_a619_holi(adreno_gpu)) {
+ gpu_write(gpu, REG_A6XX_GBIF_HALT, 0);
+ gpu_write(gpu, REG_A6XX_RBBM_GPR0_CNTL, 0);
+ /* Let's make extra sure that the GPU can access the memory.. */
+ mb();
+ } else if (a6xx_has_gbif(adreno_gpu)) {
+ gpu_write(gpu, REG_A6XX_GBIF_HALT, 0);
gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 0);
+ /* Let's make extra sure that the GPU can access the memory.. */
+ mb();
+ }
gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_CNTL, 0);
+ if (adreno_is_a619_holi(adreno_gpu))
+ a6xx_sptprac_enable(gmu);
+
/*
* Disable the trusted memory range - we don't actually supported secure
* memory rendering at this point in time and we don't want to block off
@@ -1034,13 +1242,13 @@ static int hw_init(struct msm_gpu *gpu)
a6xx_set_hwcg(gpu, true);
/* VBIF/GBIF start*/
- if (adreno_is_a640_family(adreno_gpu) ||
+ if (adreno_is_a610(adreno_gpu) ||
+ adreno_is_a640_family(adreno_gpu) ||
adreno_is_a650_family(adreno_gpu)) {
gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE0, 0x00071620);
gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE1, 0x00071620);
gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE2, 0x00071620);
gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620);
- gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620);
gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x3);
} else {
gpu_write(gpu, REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3);
@@ -1068,28 +1276,40 @@ static int hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_A6XX_UCHE_FILTER_CNTL, 0x804);
gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, 0x4);
- if (adreno_is_a640_family(adreno_gpu) ||
- adreno_is_a650_family(adreno_gpu))
+ if (adreno_is_a640_family(adreno_gpu) || adreno_is_a650_family(adreno_gpu)) {
gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x02000140);
- else
+ gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c);
+ } else if (adreno_is_a610(adreno_gpu)) {
+ gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x00800060);
+ gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x40201b16);
+ } else {
gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0);
- gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c);
+ gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c);
+ }
if (adreno_is_a660_family(adreno_gpu))
gpu_write(gpu, REG_A6XX_CP_LPAC_PROG_FIFO_SIZE, 0x00000020);
/* Setting the mem pool size */
- gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 128);
+ if (adreno_is_a610(adreno_gpu)) {
+ gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 48);
+ gpu_write(gpu, REG_A6XX_CP_MEM_POOL_DBG_ADDR, 47);
+ } else
+ gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 128);
/* Setting the primFifo thresholds default values,
* and vccCacheSkipDis=1 bit (0x200) for A640 and newer
*/
- if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu))
+ if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu) || adreno_is_a690(adreno_gpu))
gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00300200);
else if (adreno_is_a640_family(adreno_gpu) || adreno_is_7c3(adreno_gpu))
gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00200200);
else if (adreno_is_a650(adreno_gpu) || adreno_is_a660(adreno_gpu))
gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00300200);
+ else if (adreno_is_a619(adreno_gpu))
+ gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00018000);
+ else if (adreno_is_a610(adreno_gpu))
+ gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00080000);
else
gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00180000);
@@ -1105,8 +1325,12 @@ static int hw_init(struct msm_gpu *gpu)
a6xx_set_ubwc_config(gpu);
/* Enable fault detection */
- gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL,
- (1 << 30) | 0x1fffff);
+ if (adreno_is_a619(adreno_gpu))
+ gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, (1 << 30) | 0x3fffff);
+ else if (adreno_is_a610(adreno_gpu))
+ gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, (1 << 30) | 0x3ffff);
+ else
+ gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL, (1 << 30) | 0x1fffff);
gpu_write(gpu, REG_A6XX_UCHE_CLIENT_PF, 1);
@@ -1123,6 +1347,13 @@ static int hw_init(struct msm_gpu *gpu)
0x3f0243f0);
}
+ /* Set up the CX GMU counter 0 to count busy ticks */
+ gmu_write(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000);
+
+ /* Enable the power counter */
+ gmu_rmw(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, BIT(5));
+ gmu_write(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1);
+
/* Protect registers from the CP */
a6xx_set_cp_protect(gpu);
@@ -1212,6 +1443,8 @@ static int hw_init(struct msm_gpu *gpu)
}
out:
+ if (adreno_has_gmu_wrapper(adreno_gpu))
+ return ret;
/*
* Tell the GMU that we are done touching the GPU and it can start power
* management
@@ -1246,9 +1479,6 @@ static void a6xx_dump(struct msm_gpu *gpu)
adreno_dump(gpu);
}
-#define VBIF_RESET_ACK_TIMEOUT 100
-#define VBIF_RESET_ACK_MASK 0x00f0
-
static void a6xx_recover(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -1274,12 +1504,6 @@ static void a6xx_recover(struct msm_gpu *gpu)
/* Halt SQE first */
gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 3);
- /*
- * Turn off keep alive that might have been enabled by the hang
- * interrupt
- */
- gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 0);
-
pm_runtime_dont_use_autosuspend(&gpu->pdev->dev);
/* active_submit won't change until we make a submission */
@@ -1292,6 +1516,15 @@ static void a6xx_recover(struct msm_gpu *gpu)
*/
gpu->active_submits = 0;
+ if (adreno_has_gmu_wrapper(adreno_gpu)) {
+ /* Drain the outstanding traffic on memory buses */
+ a6xx_bus_clear_pending_transactions(adreno_gpu, true);
+
+ /* Reset the GPU to a clean state */
+ a6xx_gpu_sw_reset(gpu, true);
+ a6xx_gpu_sw_reset(gpu, false);
+ }
+
reinit_completion(&gmu->pd_gate);
dev_pm_genpd_add_notifier(gmu->cxpd, &gmu->pd_nb);
dev_pm_genpd_synced_poweroff(gmu->cxpd);
@@ -1442,7 +1675,8 @@ static void a6xx_fault_detect_irq(struct msm_gpu *gpu)
* Force the GPU to stay on until after we finish
* collecting information
*/
- gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 1);
+ if (!adreno_has_gmu_wrapper(adreno_gpu))
+ gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_GMU_PWR_COL_KEEPALIVE, 1);
DRM_DEV_ERROR(&gpu->pdev->dev,
"gpu fault ring %d fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n",
@@ -1573,6 +1807,10 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu)
static void a6xx_llc_slices_destroy(struct a6xx_gpu *a6xx_gpu)
{
+ /* No LLCC on non-RPMh (and by extension, non-GMU) SoCs */
+ if (adreno_has_gmu_wrapper(&a6xx_gpu->base))
+ return;
+
llcc_slice_putd(a6xx_gpu->llc_slice);
llcc_slice_putd(a6xx_gpu->htw_llc_slice);
}
@@ -1582,6 +1820,10 @@ static void a6xx_llc_slices_init(struct platform_device *pdev,
{
struct device_node *phandle;
+ /* No LLCC on non-RPMh (and by extension, non-GMU) SoCs */
+ if (adreno_has_gmu_wrapper(&a6xx_gpu->base))
+ return;
+
/*
* There is a different programming path for targets with an mmu500
* attached, so detect if that is the case
@@ -1603,7 +1845,66 @@ static void a6xx_llc_slices_init(struct platform_device *pdev,
a6xx_gpu->llc_mmio = ERR_PTR(-EINVAL);
}
-static int a6xx_pm_resume(struct msm_gpu *gpu)
+#define GBIF_CLIENT_HALT_MASK BIT(0)
+#define GBIF_ARB_HALT_MASK BIT(1)
+#define VBIF_XIN_HALT_CTRL0_MASK GENMASK(3, 0)
+#define VBIF_RESET_ACK_MASK 0xF0
+#define GPR0_GBIF_HALT_REQUEST 0x1E0
+
+void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off)
+{
+ struct msm_gpu *gpu = &adreno_gpu->base;
+
+ if (adreno_is_a619_holi(adreno_gpu)) {
+ gpu_write(gpu, REG_A6XX_RBBM_GPR0_CNTL, GPR0_GBIF_HALT_REQUEST);
+ spin_until((gpu_read(gpu, REG_A6XX_RBBM_VBIF_GX_RESET_STATUS) &
+ (VBIF_RESET_ACK_MASK)) == VBIF_RESET_ACK_MASK);
+ } else if (!a6xx_has_gbif(adreno_gpu)) {
+ gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, VBIF_XIN_HALT_CTRL0_MASK);
+ spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) &
+ (VBIF_XIN_HALT_CTRL0_MASK)) == VBIF_XIN_HALT_CTRL0_MASK);
+ gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0);
+
+ return;
+ }
+
+ if (gx_off) {
+ /* Halt the gx side of GBIF */
+ gpu_write(gpu, REG_A6XX_RBBM_GBIF_HALT, 1);
+ spin_until(gpu_read(gpu, REG_A6XX_RBBM_GBIF_HALT_ACK) & 1);
+ }
+
+ /* Halt new client requests on GBIF */
+ gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK);
+ spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) &
+ (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK);
+
+ /* Halt all AXI requests on GBIF */
+ gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK);
+ spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) &
+ (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK);
+
+ /* The GBIF halt needs to be explicitly cleared */
+ gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0);
+}
+
+void a6xx_gpu_sw_reset(struct msm_gpu *gpu, bool assert)
+{
+ /* 11nm chips (e.g. ones with A610) have hw issues with the reset line! */
+ if (adreno_is_a610(to_adreno_gpu(gpu)))
+ return;
+
+ gpu_write(gpu, REG_A6XX_RBBM_SW_RESET_CMD, assert);
+ /* Perform a bogus read and add a brief delay to ensure ordering. */
+ gpu_read(gpu, REG_A6XX_RBBM_SW_RESET_CMD);
+ udelay(1);
+
+ /* The reset line needs to be asserted for at least 100 us */
+ if (assert)
+ udelay(100);
+}
+
+static int a6xx_gmu_pm_resume(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
@@ -1623,10 +1924,61 @@ static int a6xx_pm_resume(struct msm_gpu *gpu)
a6xx_llc_activate(a6xx_gpu);
- return 0;
+ return ret;
}
-static int a6xx_pm_suspend(struct msm_gpu *gpu)
+static int a6xx_pm_resume(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+ unsigned long freq = gpu->fast_rate;
+ struct dev_pm_opp *opp;
+ int ret;
+
+ gpu->needs_hw_init = true;
+
+ trace_msm_gpu_resume(0);
+
+ mutex_lock(&a6xx_gpu->gmu.lock);
+
+ opp = dev_pm_opp_find_freq_ceil(&gpu->pdev->dev, &freq);
+ if (IS_ERR(opp)) {
+ ret = PTR_ERR(opp);
+ goto err_set_opp;
+ }
+ dev_pm_opp_put(opp);
+
+ /* Set the core clock and bus bw, having VDD scaling in mind */
+ dev_pm_opp_set_opp(&gpu->pdev->dev, opp);
+
+ pm_runtime_resume_and_get(gmu->dev);
+ pm_runtime_resume_and_get(gmu->gxpd);
+
+ ret = clk_bulk_prepare_enable(gpu->nr_clocks, gpu->grp_clks);
+ if (ret)
+ goto err_bulk_clk;
+
+ if (adreno_is_a619_holi(adreno_gpu))
+ a6xx_sptprac_enable(gmu);
+
+ /* If anything goes south, tear the GPU down piece by piece.. */
+ if (ret) {
+err_bulk_clk:
+ pm_runtime_put(gmu->gxpd);
+ pm_runtime_put(gmu->dev);
+ dev_pm_opp_set_opp(&gpu->pdev->dev, NULL);
+ }
+err_set_opp:
+ mutex_unlock(&a6xx_gpu->gmu.lock);
+
+ if (!ret)
+ msm_devfreq_resume(gpu);
+
+ return ret;
+}
+
+static int a6xx_gmu_pm_suspend(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
@@ -1653,7 +2005,43 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
return 0;
}
-static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
+static int a6xx_pm_suspend(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+ int i;
+
+ trace_msm_gpu_suspend(0);
+
+ msm_devfreq_suspend(gpu);
+
+ mutex_lock(&a6xx_gpu->gmu.lock);
+
+ /* Drain the outstanding traffic on memory buses */
+ a6xx_bus_clear_pending_transactions(adreno_gpu, true);
+
+ if (adreno_is_a619_holi(adreno_gpu))
+ a6xx_sptprac_disable(gmu);
+
+ clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks);
+
+ pm_runtime_put_sync(gmu->gxpd);
+ dev_pm_opp_set_opp(&gpu->pdev->dev, NULL);
+ pm_runtime_put_sync(gmu->dev);
+
+ mutex_unlock(&a6xx_gpu->gmu.lock);
+
+ if (a6xx_gpu->shadow_bo)
+ for (i = 0; i < gpu->nr_rings; i++)
+ a6xx_gpu->shadow[i] = 0;
+
+ gpu->suspend_count++;
+
+ return 0;
+}
+
+static int a6xx_gmu_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
@@ -1672,6 +2060,12 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
return 0;
}
+static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
+{
+ *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER);
+ return 0;
+}
+
static struct msm_ringbuffer *a6xx_active_ring(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -1744,7 +2138,8 @@ a6xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev)
* This allows GPU to set the bus attributes required to use system
* cache on behalf of the iommu page table walker.
*/
- if (!IS_ERR_OR_NULL(a6xx_gpu->htw_llc_slice))
+ if (!IS_ERR_OR_NULL(a6xx_gpu->htw_llc_slice) &&
+ !device_iommu_capable(&pdev->dev, IOMMU_CAP_CACHE_COHERENCY))
quirks |= IO_PGTABLE_QUIRK_ARM_OUTER_WBWA;
return adreno_iommu_create_address_space(gpu, pdev, quirks);
@@ -1809,6 +2204,30 @@ static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
return progress;
}
+static u32 a610_get_speed_bin(u32 fuse)
+{
+ /*
+ * There are (at least) three SoCs implementing A610: SM6125 (trinket),
+ * SM6115 (bengal) and SM6225 (khaje). Trinket does not have speedbinning,
+ * as only a single SKU exists and we don't support khaje upstream yet.
+ * Hence, this matching table is only valid for bengal and can be easily
+ * expanded if need be.
+ */
+
+ if (fuse == 0)
+ return 0;
+ else if (fuse == 206)
+ return 1;
+ else if (fuse == 200)
+ return 2;
+ else if (fuse == 157)
+ return 3;
+ else if (fuse == 127)
+ return 4;
+
+ return UINT_MAX;
+}
+
static u32 a618_get_speed_bin(u32 fuse)
{
if (fuse == 0)
@@ -1821,6 +2240,34 @@ static u32 a618_get_speed_bin(u32 fuse)
return UINT_MAX;
}
+static u32 a619_holi_get_speed_bin(u32 fuse)
+{
+ /*
+ * There are (at least) two SoCs implementing A619_holi: SM4350 (holi)
+ * and SM6375 (blair). Limit the fuse matching to the corresponding
+ * SoC to prevent bogus frequency setting (as improbable as it may be,
+ * given unexpected fuse values are.. unexpected! But still possible.)
+ */
+
+ if (fuse == 0)
+ return 0;
+
+ if (of_machine_is_compatible("qcom,sm4350")) {
+ if (fuse == 138)
+ return 1;
+ else if (fuse == 92)
+ return 2;
+ } else if (of_machine_is_compatible("qcom,sm6375")) {
+ if (fuse == 190)
+ return 1;
+ else if (fuse == 177)
+ return 2;
+ } else
+ pr_warn("Unknown SoC implementing A619_holi!\n");
+
+ return UINT_MAX;
+}
+
static u32 a619_get_speed_bin(u32 fuse)
{
if (fuse == 0)
@@ -1874,23 +2321,29 @@ static u32 adreno_7c3_get_speed_bin(u32 fuse)
return UINT_MAX;
}
-static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse)
+static u32 fuse_to_supp_hw(struct device *dev, struct adreno_gpu *adreno_gpu, u32 fuse)
{
u32 val = UINT_MAX;
- if (adreno_cmp_rev(ADRENO_REV(6, 1, 8, ANY_ID), rev))
+ if (adreno_is_a610(adreno_gpu))
+ val = a610_get_speed_bin(fuse);
+
+ if (adreno_is_a618(adreno_gpu))
val = a618_get_speed_bin(fuse);
- if (adreno_cmp_rev(ADRENO_REV(6, 1, 9, ANY_ID), rev))
+ else if (adreno_is_a619_holi(adreno_gpu))
+ val = a619_holi_get_speed_bin(fuse);
+
+ else if (adreno_is_a619(adreno_gpu))
val = a619_get_speed_bin(fuse);
- if (adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), rev))
+ else if (adreno_is_7c3(adreno_gpu))
val = adreno_7c3_get_speed_bin(fuse);
- if (adreno_cmp_rev(ADRENO_REV(6, 4, 0, ANY_ID), rev))
+ else if (adreno_is_a640(adreno_gpu))
val = a640_get_speed_bin(fuse);
- if (adreno_cmp_rev(ADRENO_REV(6, 5, 0, ANY_ID), rev))
+ else if (adreno_is_a650(adreno_gpu))
val = a650_get_speed_bin(fuse);
if (val == UINT_MAX) {
@@ -1903,7 +2356,7 @@ static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse)
return (1 << val);
}
-static int a6xx_set_supported_hw(struct device *dev, struct adreno_rev rev)
+static int a6xx_set_supported_hw(struct device *dev, struct adreno_gpu *adreno_gpu)
{
u32 supp_hw;
u32 speedbin;
@@ -1922,7 +2375,7 @@ static int a6xx_set_supported_hw(struct device *dev, struct adreno_rev rev)
return ret;
}
- supp_hw = fuse_to_supp_hw(dev, rev, speedbin);
+ supp_hw = fuse_to_supp_hw(dev, adreno_gpu, speedbin);
ret = devm_pm_opp_set_supported_hw(dev, &supp_hw, 1);
if (ret)
@@ -1937,8 +2390,8 @@ static const struct adreno_gpu_funcs funcs = {
.set_param = adreno_set_param,
.hw_init = a6xx_hw_init,
.ucode_load = a6xx_ucode_load,
- .pm_suspend = a6xx_pm_suspend,
- .pm_resume = a6xx_pm_resume,
+ .pm_suspend = a6xx_gmu_pm_suspend,
+ .pm_resume = a6xx_gmu_pm_resume,
.recover = a6xx_recover,
.submit = a6xx_submit,
.active_ring = a6xx_active_ring,
@@ -1959,6 +2412,35 @@ static const struct adreno_gpu_funcs funcs = {
.get_rptr = a6xx_get_rptr,
.progress = a6xx_progress,
},
+ .get_timestamp = a6xx_gmu_get_timestamp,
+};
+
+static const struct adreno_gpu_funcs funcs_gmuwrapper = {
+ .base = {
+ .get_param = adreno_get_param,
+ .set_param = adreno_set_param,
+ .hw_init = a6xx_hw_init,
+ .ucode_load = a6xx_ucode_load,
+ .pm_suspend = a6xx_pm_suspend,
+ .pm_resume = a6xx_pm_resume,
+ .recover = a6xx_recover,
+ .submit = a6xx_submit,
+ .active_ring = a6xx_active_ring,
+ .irq = a6xx_irq,
+ .destroy = a6xx_destroy,
+#if defined(CONFIG_DRM_MSM_GPU_STATE)
+ .show = a6xx_show,
+#endif
+ .gpu_busy = a6xx_gpu_busy,
+#if defined(CONFIG_DRM_MSM_GPU_STATE)
+ .gpu_state_get = a6xx_gpu_state_get,
+ .gpu_state_put = a6xx_gpu_state_put,
+#endif
+ .create_address_space = a6xx_create_address_space,
+ .create_private_address_space = a6xx_create_private_address_space,
+ .get_rptr = a6xx_get_rptr,
+ .progress = a6xx_progress,
+ },
.get_timestamp = a6xx_get_timestamp,
};
@@ -1985,26 +2467,45 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
adreno_gpu->registers = NULL;
+ /* Check if there is a GMU phandle and set it up */
+ node = of_parse_phandle(pdev->dev.of_node, "qcom,gmu", 0);
+ /* FIXME: How do we gracefully handle this? */
+ BUG_ON(!node);
+
+ adreno_gpu->gmu_is_wrapper = of_device_is_compatible(node, "qcom,adreno-gmu-wrapper");
+
/*
* We need to know the platform type before calling into adreno_gpu_init
* so that the hw_apriv flag can be correctly set. Snoop into the info
* and grab the revision number
*/
info = adreno_info(config->rev);
-
- if (info && (info->revn == 650 || info->revn == 660 ||
- adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), info->rev)))
+ if (!info)
+ return ERR_PTR(-EINVAL);
+
+ /* Assign these early so that we can use the is_aXYZ helpers */
+ /* Numeric revision IDs (e.g. 630) */
+ adreno_gpu->revn = info->revn;
+ /* New-style ADRENO_REV()-only */
+ adreno_gpu->rev = info->rev;
+ /* Quirk data */
+ adreno_gpu->info = info;
+
+ if (adreno_is_a650(adreno_gpu) || adreno_is_a660_family(adreno_gpu))
adreno_gpu->base.hw_apriv = true;
a6xx_llc_slices_init(pdev, a6xx_gpu);
- ret = a6xx_set_supported_hw(&pdev->dev, config->rev);
+ ret = a6xx_set_supported_hw(&pdev->dev, adreno_gpu);
if (ret) {
a6xx_destroy(&(a6xx_gpu->base.base));
return ERR_PTR(ret);
}
- ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
+ if (adreno_has_gmu_wrapper(adreno_gpu))
+ ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_gmuwrapper, 1);
+ else
+ ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
if (ret) {
a6xx_destroy(&(a6xx_gpu->base.base));
return ERR_PTR(ret);
@@ -2017,13 +2518,10 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
if (adreno_is_a618(adreno_gpu) || adreno_is_7c3(adreno_gpu))
priv->gpu_clamp_to_idle = true;
- /* Check if there is a GMU phandle and set it up */
- node = of_parse_phandle(pdev->dev.of_node, "qcom,gmu", 0);
-
- /* FIXME: How do we gracefully handle this? */
- BUG_ON(!node);
-
- ret = a6xx_gmu_init(a6xx_gpu, node);
+ if (adreno_has_gmu_wrapper(adreno_gpu))
+ ret = a6xx_gmu_wrapper_init(a6xx_gpu, node);
+ else
+ ret = a6xx_gmu_init(a6xx_gpu, node);
of_node_put(node);
if (ret) {
a6xx_destroy(&(a6xx_gpu->base.base));
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index eea2e60ce3b7..c788b06e72da 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -76,6 +76,7 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
+int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu);
void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp,
@@ -88,4 +89,7 @@ void a6xx_show(struct msm_gpu *gpu, struct msm_gpu_state *state,
struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu);
int a6xx_gpu_state_put(struct msm_gpu_state *state);
+void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu, bool gx_off);
+void a6xx_gpu_sw_reset(struct msm_gpu *gpu, bool assert);
+
#endif /* __A6XX_GPU_H__ */
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
index 30ecdff363e7..4e5d650578c6 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
@@ -1041,16 +1041,18 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu)
/* Get the generic state from the adreno core */
adreno_gpu_state_get(gpu, &a6xx_state->base);
- a6xx_get_gmu_registers(gpu, a6xx_state);
+ if (!adreno_has_gmu_wrapper(adreno_gpu)) {
+ a6xx_get_gmu_registers(gpu, a6xx_state);
- a6xx_state->gmu_log = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.log);
- a6xx_state->gmu_hfi = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.hfi);
- a6xx_state->gmu_debug = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.debug);
+ a6xx_state->gmu_log = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.log);
+ a6xx_state->gmu_hfi = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.hfi);
+ a6xx_state->gmu_debug = a6xx_snapshot_gmu_bo(a6xx_state, &a6xx_gpu->gmu.debug);
- a6xx_snapshot_gmu_hfi_history(gpu, a6xx_state);
+ a6xx_snapshot_gmu_hfi_history(gpu, a6xx_state);
+ }
/* If GX isn't on the rest of the data isn't going to be accessible */
- if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu))
+ if (!adreno_has_gmu_wrapper(adreno_gpu) && !a6xx_gmu_gx_is_on(&a6xx_gpu->gmu))
return &a6xx_state->base;
/* Get the banks of indexed registers */
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
index 2cc83e049613..25b235b49ebc 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
@@ -414,6 +414,37 @@ static void a650_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
msg->cnoc_cmds_data[1][0] = 0x60000001;
}
+static void a690_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
+{
+ /*
+ * Send a single "off" entry just to get things running
+ * TODO: bus scaling
+ */
+ msg->bw_level_num = 1;
+
+ msg->ddr_cmds_num = 3;
+ msg->ddr_wait_bitmask = 0x01;
+
+ msg->ddr_cmds_addrs[0] = 0x50004;
+ msg->ddr_cmds_addrs[1] = 0x50000;
+ msg->ddr_cmds_addrs[2] = 0x500ac;
+
+ msg->ddr_cmds_data[0][0] = 0x40000000;
+ msg->ddr_cmds_data[0][1] = 0x40000000;
+ msg->ddr_cmds_data[0][2] = 0x40000000;
+
+ /*
+ * These are the CX (CNOC) votes - these are used by the GMU but the
+ * votes are known and fixed for the target
+ */
+ msg->cnoc_cmds_num = 1;
+ msg->cnoc_wait_bitmask = 0x01;
+
+ msg->cnoc_cmds_addrs[0] = 0x5003c;
+ msg->cnoc_cmds_data[0][0] = 0x40000000;
+ msg->cnoc_cmds_data[1][0] = 0x60000001;
+}
+
static void a660_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
{
/*
@@ -531,6 +562,8 @@ static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu)
adreno_7c3_build_bw_table(&msg);
else if (adreno_is_a660(adreno_gpu))
a660_build_bw_table(&msg);
+ else if (adreno_is_a690(adreno_gpu))
+ a690_build_bw_table(&msg);
else
a6xx_build_bw_table(&msg);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 8cff86e9d35c..cb94cfd137a8 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -254,6 +254,18 @@ static const struct adreno_info gpulist[] = {
.init = a5xx_gpu_init,
.zapfw = "a540_zap.mdt",
}, {
+ .rev = ADRENO_REV(6, 1, 0, ANY_ID),
+ .revn = 610,
+ .name = "A610",
+ .fw = {
+ [ADRENO_FW_SQE] = "a630_sqe.fw",
+ },
+ .gmem = (SZ_128K + SZ_4K),
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a6xx_gpu_init,
+ .zapfw = "a610_zap.mdt",
+ .hwcg = a612_hwcg,
+ }, {
.rev = ADRENO_REV(6, 1, 8, ANY_ID),
.revn = 618,
.name = "A618",
@@ -355,6 +367,20 @@ static const struct adreno_info gpulist[] = {
.init = a6xx_gpu_init,
.zapfw = "a640_zap.mdt",
.hwcg = a640_hwcg,
+ }, {
+ .rev = ADRENO_REV(6, 9, 0, ANY_ID),
+ .revn = 690,
+ .name = "A690",
+ .fw = {
+ [ADRENO_FW_SQE] = "a660_sqe.fw",
+ [ADRENO_FW_GMU] = "a690_gmu.bin",
+ },
+ .gmem = SZ_4M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .init = a6xx_gpu_init,
+ .zapfw = "a690_zap.mdt",
+ .hwcg = a690_hwcg,
+ .address_space_size = SZ_16G,
},
};
@@ -551,7 +577,6 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
config.rev.minor, config.rev.patchid);
priv->is_a2xx = config.rev.core == 2;
- priv->has_cached_coherent = config.rev.core >= 6;
gpu = info->init(drm);
if (IS_ERR(gpu)) {
@@ -563,6 +588,10 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
if (ret)
return ret;
+ if (config.rev.core >= 6)
+ if (!adreno_has_gmu_wrapper(to_adreno_gpu(gpu)))
+ priv->has_cached_coherent = true;
+
return 0;
}
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 6934cee07d42..5c5901d65950 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -528,6 +528,10 @@ int adreno_load_fw(struct adreno_gpu *adreno_gpu)
if (!adreno_gpu->info->fw[i])
continue;
+ /* Skip loading GMU firwmare with GMU Wrapper */
+ if (adreno_has_gmu_wrapper(adreno_gpu) && i == ADRENO_FW_GMU)
+ continue;
+
/* Skip if the firmware has already been loaded */
if (adreno_gpu->fw[i])
continue;
@@ -1074,8 +1078,8 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
u32 speedbin;
int ret;
- /* Only handle the core clock when GMU is not in use */
- if (config->rev.core < 6) {
+ /* Only handle the core clock when GMU is not in use (or is absent). */
+ if (adreno_has_gmu_wrapper(adreno_gpu) || config->rev.core < 6) {
/*
* This can only be done before devm_pm_opp_of_add_table(), or
* dev_pm_opp_set_config() will WARN_ON()
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index f62612a5c70f..d8c9e8cc3753 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -55,7 +55,8 @@ struct adreno_reglist {
u32 value;
};
-extern const struct adreno_reglist a615_hwcg[], a630_hwcg[], a640_hwcg[], a650_hwcg[], a660_hwcg[];
+extern const struct adreno_reglist a612_hwcg[], a615_hwcg[], a630_hwcg[], a640_hwcg[], a650_hwcg[];
+extern const struct adreno_reglist a660_hwcg[], a690_hwcg[];
struct adreno_info {
struct adreno_rev rev;
@@ -115,6 +116,7 @@ struct adreno_gpu {
* code (a3xx_gpu.c) and stored in this common location.
*/
const unsigned int *reg_offsets;
+ bool gmu_is_wrapper;
};
#define to_adreno_gpu(x) container_of(x, struct adreno_gpu, base)
@@ -145,148 +147,194 @@ struct adreno_platform_config {
bool adreno_cmp_rev(struct adreno_rev rev1, struct adreno_rev rev2);
-static inline bool adreno_is_a2xx(struct adreno_gpu *gpu)
+static inline bool adreno_is_revn(const struct adreno_gpu *gpu, uint32_t revn)
{
+ WARN_ON_ONCE(!gpu->revn);
+
+ return gpu->revn == revn;
+}
+
+static inline bool adreno_has_gmu_wrapper(const struct adreno_gpu *gpu)
+{
+ return gpu->gmu_is_wrapper;
+}
+
+static inline bool adreno_is_a2xx(const struct adreno_gpu *gpu)
+{
+ WARN_ON_ONCE(!gpu->revn);
+
return (gpu->revn < 300);
}
-static inline bool adreno_is_a20x(struct adreno_gpu *gpu)
+static inline bool adreno_is_a20x(const struct adreno_gpu *gpu)
{
+ WARN_ON_ONCE(!gpu->revn);
+
return (gpu->revn < 210);
}
-static inline bool adreno_is_a225(struct adreno_gpu *gpu)
+static inline bool adreno_is_a225(const struct adreno_gpu *gpu)
{
- return gpu->revn == 225;
+ return adreno_is_revn(gpu, 225);
}
-static inline bool adreno_is_a305(struct adreno_gpu *gpu)
+static inline bool adreno_is_a305(const struct adreno_gpu *gpu)
{
- return gpu->revn == 305;
+ return adreno_is_revn(gpu, 305);
}
-static inline bool adreno_is_a306(struct adreno_gpu *gpu)
+static inline bool adreno_is_a306(const struct adreno_gpu *gpu)
{
/* yes, 307, because a305c is 306 */
- return gpu->revn == 307;
+ return adreno_is_revn(gpu, 307);
}
-static inline bool adreno_is_a320(struct adreno_gpu *gpu)
+static inline bool adreno_is_a320(const struct adreno_gpu *gpu)
{
- return gpu->revn == 320;
+ return adreno_is_revn(gpu, 320);
}
-static inline bool adreno_is_a330(struct adreno_gpu *gpu)
+static inline bool adreno_is_a330(const struct adreno_gpu *gpu)
{
- return gpu->revn == 330;
+ return adreno_is_revn(gpu, 330);
}
-static inline bool adreno_is_a330v2(struct adreno_gpu *gpu)
+static inline bool adreno_is_a330v2(const struct adreno_gpu *gpu)
{
return adreno_is_a330(gpu) && (gpu->rev.patchid > 0);
}
-static inline int adreno_is_a405(struct adreno_gpu *gpu)
+static inline int adreno_is_a405(const struct adreno_gpu *gpu)
+{
+ return adreno_is_revn(gpu, 405);
+}
+
+static inline int adreno_is_a420(const struct adreno_gpu *gpu)
{
- return gpu->revn == 405;
+ return adreno_is_revn(gpu, 420);
}
-static inline int adreno_is_a420(struct adreno_gpu *gpu)
+static inline int adreno_is_a430(const struct adreno_gpu *gpu)
{
- return gpu->revn == 420;
+ return adreno_is_revn(gpu, 430);
}
-static inline int adreno_is_a430(struct adreno_gpu *gpu)
+static inline int adreno_is_a506(const struct adreno_gpu *gpu)
{
- return gpu->revn == 430;
+ return adreno_is_revn(gpu, 506);
}
-static inline int adreno_is_a506(struct adreno_gpu *gpu)
+static inline int adreno_is_a508(const struct adreno_gpu *gpu)
{
- return gpu->revn == 506;
+ return adreno_is_revn(gpu, 508);
}
-static inline int adreno_is_a508(struct adreno_gpu *gpu)
+static inline int adreno_is_a509(const struct adreno_gpu *gpu)
{
- return gpu->revn == 508;
+ return adreno_is_revn(gpu, 509);
}
-static inline int adreno_is_a509(struct adreno_gpu *gpu)
+static inline int adreno_is_a510(const struct adreno_gpu *gpu)
{
- return gpu->revn == 509;
+ return adreno_is_revn(gpu, 510);
}
-static inline int adreno_is_a510(struct adreno_gpu *gpu)
+static inline int adreno_is_a512(const struct adreno_gpu *gpu)
{
- return gpu->revn == 510;
+ return adreno_is_revn(gpu, 512);
}
-static inline int adreno_is_a512(struct adreno_gpu *gpu)
+static inline int adreno_is_a530(const struct adreno_gpu *gpu)
{
- return gpu->revn == 512;
+ return adreno_is_revn(gpu, 530);
}
-static inline int adreno_is_a530(struct adreno_gpu *gpu)
+static inline int adreno_is_a540(const struct adreno_gpu *gpu)
{
- return gpu->revn == 530;
+ return adreno_is_revn(gpu, 540);
}
-static inline int adreno_is_a540(struct adreno_gpu *gpu)
+static inline int adreno_is_a610(const struct adreno_gpu *gpu)
{
- return gpu->revn == 540;
+ return adreno_is_revn(gpu, 610);
}
-static inline int adreno_is_a618(struct adreno_gpu *gpu)
+static inline int adreno_is_a618(const struct adreno_gpu *gpu)
{
- return gpu->revn == 618;
+ return adreno_is_revn(gpu, 618);
}
-static inline int adreno_is_a619(struct adreno_gpu *gpu)
+static inline int adreno_is_a619(const struct adreno_gpu *gpu)
{
- return gpu->revn == 619;
+ return adreno_is_revn(gpu, 619);
}
-static inline int adreno_is_a630(struct adreno_gpu *gpu)
+static inline int adreno_is_a619_holi(const struct adreno_gpu *gpu)
{
- return gpu->revn == 630;
+ return adreno_is_a619(gpu) && adreno_has_gmu_wrapper(gpu);
}
-static inline int adreno_is_a640_family(struct adreno_gpu *gpu)
+static inline int adreno_is_a630(const struct adreno_gpu *gpu)
{
- return (gpu->revn == 640) || (gpu->revn == 680);
+ return adreno_is_revn(gpu, 630);
}
-static inline int adreno_is_a650(struct adreno_gpu *gpu)
+static inline int adreno_is_a640(const struct adreno_gpu *gpu)
{
- return gpu->revn == 650;
+ return adreno_is_revn(gpu, 640);
}
-static inline int adreno_is_7c3(struct adreno_gpu *gpu)
+static inline int adreno_is_a650(const struct adreno_gpu *gpu)
+{
+ return adreno_is_revn(gpu, 650);
+}
+
+static inline int adreno_is_7c3(const struct adreno_gpu *gpu)
{
/* The order of args is important here to handle ANY_ID correctly */
return adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), gpu->rev);
}
-static inline int adreno_is_a660(struct adreno_gpu *gpu)
+static inline int adreno_is_a660(const struct adreno_gpu *gpu)
+{
+ return adreno_is_revn(gpu, 660);
+}
+
+static inline int adreno_is_a680(const struct adreno_gpu *gpu)
{
- return gpu->revn == 660;
+ return adreno_is_revn(gpu, 680);
}
+static inline int adreno_is_a690(const struct adreno_gpu *gpu)
+{
+ return adreno_is_revn(gpu, 690);
+};
+
/* check for a615, a616, a618, a619 or any derivatives */
-static inline int adreno_is_a615_family(struct adreno_gpu *gpu)
+static inline int adreno_is_a615_family(const struct adreno_gpu *gpu)
{
- return gpu->revn == 615 || gpu->revn == 616 || gpu->revn == 618 || gpu->revn == 619;
+ return adreno_is_revn(gpu, 615) ||
+ adreno_is_revn(gpu, 616) ||
+ adreno_is_revn(gpu, 618) ||
+ adreno_is_revn(gpu, 619);
}
-static inline int adreno_is_a660_family(struct adreno_gpu *gpu)
+static inline int adreno_is_a660_family(const struct adreno_gpu *gpu)
{
- return adreno_is_a660(gpu) || adreno_is_7c3(gpu);
+ return adreno_is_a660(gpu) || adreno_is_a690(gpu) || adreno_is_7c3(gpu);
}
/* check for a650, a660, or any derivatives */
-static inline int adreno_is_a650_family(struct adreno_gpu *gpu)
+static inline int adreno_is_a650_family(const struct adreno_gpu *gpu)
+{
+ return adreno_is_revn(gpu, 650) ||
+ adreno_is_revn(gpu, 620) ||
+ adreno_is_a660_family(gpu);
+}
+
+static inline int adreno_is_a640_family(const struct adreno_gpu *gpu)
{
- return gpu->revn == 650 || gpu->revn == 620 || adreno_is_a660_family(gpu);
+ return adreno_is_a640(gpu) || adreno_is_a680(gpu);
}
u64 adreno_private_address_space_size(struct msm_gpu *gpu);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
index bdcd554fc8a8..7d0d0e74c3b0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
@@ -30,7 +30,7 @@ static const struct dpu_mdp_cfg msm8998_mdp[] = {
{
.name = "top_0", .id = MDP_TOP,
.base = 0x0, .len = 0x458,
- .features = 0,
+ .features = BIT(DPU_MDP_VSYNC_SEL),
.clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
.clk_ctrls[DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 },
.clk_ctrls[DPU_CLK_CTRL_VIG2] = { .reg_off = 0x2bc, .bit_off = 0 },
@@ -39,8 +39,8 @@ static const struct dpu_mdp_cfg msm8998_mdp[] = {
.clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 },
.clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2c4, .bit_off = 8 },
.clk_ctrls[DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2c4, .bit_off = 12 },
- .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 15 },
- .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { .reg_off = 0x3b0, .bit_off = 15 },
+ .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 },
+ .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { .reg_off = 0x3b0, .bit_off = 16 },
},
};
@@ -104,40 +104,53 @@ static const struct dpu_lm_cfg msm8998_lm[] = {
LM_BLK("lm_2", LM_2, 0x46000, MIXER_MSM8998_MASK,
&msm8998_lm_sblk, PINGPONG_2, LM_5, 0),
LM_BLK("lm_3", LM_3, 0x47000, MIXER_MSM8998_MASK,
- &msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
+ &msm8998_lm_sblk, PINGPONG_NONE, 0, 0),
LM_BLK("lm_4", LM_4, 0x48000, MIXER_MSM8998_MASK,
- &msm8998_lm_sblk, PINGPONG_MAX, 0, 0),
+ &msm8998_lm_sblk, PINGPONG_NONE, 0, 0),
LM_BLK("lm_5", LM_5, 0x49000, MIXER_MSM8998_MASK,
&msm8998_lm_sblk, PINGPONG_3, LM_2, 0),
};
static const struct dpu_pingpong_cfg msm8998_pp[] = {
- PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk_te,
+ PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SDM845_TE2_MASK, 0, sdm845_pp_sblk_te,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
- PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, 0, sdm845_pp_sblk_te,
+ PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SDM845_TE2_MASK, 0, sdm845_pp_sblk_te,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
- PP_BLK("pingpong_2", PINGPONG_2, 0x71000, 0, sdm845_pp_sblk,
+ PP_BLK("pingpong_2", PINGPONG_2, 0x71000, PINGPONG_SDM845_MASK, 0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)),
- PP_BLK("pingpong_3", PINGPONG_3, 0x71800, 0, sdm845_pp_sblk,
+ PP_BLK("pingpong_3", PINGPONG_3, 0x71800, PINGPONG_SDM845_MASK, 0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)),
};
+static const struct dpu_dsc_cfg msm8998_dsc[] = {
+ DSC_BLK("dsc_0", DSC_0, 0x80000, 0),
+ DSC_BLK("dsc_1", DSC_1, 0x80400, 0),
+};
+
static const struct dpu_dspp_cfg msm8998_dspp[] = {
- DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_MSM8998_MASK,
+ DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK,
&msm8998_dspp_sblk),
- DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_MSM8998_MASK,
+ DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_SC7180_MASK,
&msm8998_dspp_sblk),
};
static const struct dpu_intf_cfg msm8998_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
- INTF_BLK("intf_1", INTF_1, 0x6a800, 0x280, INTF_DSI, 0, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
- INTF_BLK("intf_2", INTF_2, 0x6b000, 0x280, INTF_DSI, 1, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
- INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_HDMI, 0, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
+ INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 21, INTF_SDM845_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)),
+ INTF_BLK("intf_1", INTF_1, 0x6a800, 0x280, INTF_DSI, 0, 21, INTF_SDM845_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27)),
+ INTF_BLK("intf_2", INTF_2, 0x6b000, 0x280, INTF_DSI, 1, 21, INTF_SDM845_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29)),
+ INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_HDMI, 0, 21, INTF_SDM845_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)),
};
static const struct dpu_perf_cfg msm8998_perf_data = {
@@ -191,11 +204,12 @@ const struct dpu_mdss_cfg dpu_msm8998_cfg = {
.dspp = msm8998_dspp,
.pingpong_count = ARRAY_SIZE(msm8998_pp),
.pingpong = msm8998_pp,
+ .dsc_count = ARRAY_SIZE(msm8998_dsc),
+ .dsc = msm8998_dsc,
.intf_count = ARRAY_SIZE(msm8998_intf),
.intf = msm8998_intf,
.vbif_count = ARRAY_SIZE(msm8998_vbif),
.vbif = msm8998_vbif,
- .reg_dma_count = 0,
.perf = &msm8998_perf_data,
.mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
BIT(MDP_SSPP_TOP0_INTR2) | \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
index ceca741e93c9..b6098141bb9b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
@@ -30,7 +30,7 @@ static const struct dpu_mdp_cfg sdm845_mdp[] = {
{
.name = "top_0", .id = MDP_TOP,
.base = 0x0, .len = 0x45c,
- .features = BIT(DPU_MDP_AUDIO_SELECT),
+ .features = BIT(DPU_MDP_AUDIO_SELECT) | BIT(DPU_MDP_VSYNC_SEL),
.clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
.clk_ctrls[DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 },
.clk_ctrls[DPU_CLK_CTRL_VIG2] = { .reg_off = 0x2bc, .bit_off = 0 },
@@ -96,30 +96,41 @@ static const struct dpu_sspp_cfg sdm845_sspp[] = {
static const struct dpu_lm_cfg sdm845_lm[] = {
LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
- &sdm845_lm_sblk, PINGPONG_0, LM_1, 0),
+ &sdm845_lm_sblk, PINGPONG_0, LM_1, DSPP_0),
LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
- &sdm845_lm_sblk, PINGPONG_1, LM_0, 0),
+ &sdm845_lm_sblk, PINGPONG_1, LM_0, DSPP_1),
LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,
- &sdm845_lm_sblk, PINGPONG_2, LM_5, 0),
+ &sdm845_lm_sblk, PINGPONG_2, LM_5, DSPP_2),
LM_BLK("lm_3", LM_3, 0x0, MIXER_SDM845_MASK,
- &sdm845_lm_sblk, PINGPONG_MAX, 0, 0),
+ &sdm845_lm_sblk, PINGPONG_NONE, 0, DSPP_3),
LM_BLK("lm_4", LM_4, 0x0, MIXER_SDM845_MASK,
- &sdm845_lm_sblk, PINGPONG_MAX, 0, 0),
+ &sdm845_lm_sblk, PINGPONG_NONE, 0, 0),
LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK,
&sdm845_lm_sblk, PINGPONG_3, LM_2, 0),
};
+static const struct dpu_dspp_cfg sdm845_dspp[] = {
+ DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK,
+ &sm8150_dspp_sblk),
+ DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_SC7180_MASK,
+ &sm8150_dspp_sblk),
+ DSPP_BLK("dspp_2", DSPP_2, 0x58000, DSPP_SC7180_MASK,
+ &sm8150_dspp_sblk),
+ DSPP_BLK("dspp_3", DSPP_3, 0x5a000, DSPP_SC7180_MASK,
+ &sm8150_dspp_sblk),
+};
+
static const struct dpu_pingpong_cfg sdm845_pp[] = {
- PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk_te,
+ PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SDM845_TE2_MASK, 0, sdm845_pp_sblk_te,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
- PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, 0, sdm845_pp_sblk_te,
+ PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SDM845_TE2_MASK, 0, sdm845_pp_sblk_te,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
- PP_BLK("pingpong_2", PINGPONG_2, 0x71000, 0, sdm845_pp_sblk,
+ PP_BLK("pingpong_2", PINGPONG_2, 0x71000, PINGPONG_SDM845_MASK, 0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)),
- PP_BLK("pingpong_3", PINGPONG_3, 0x71800, 0, sdm845_pp_sblk,
+ PP_BLK("pingpong_3", PINGPONG_3, 0x71800, PINGPONG_SDM845_MASK, 0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)),
};
@@ -132,10 +143,18 @@ static const struct dpu_dsc_cfg sdm845_dsc[] = {
};
static const struct dpu_intf_cfg sdm845_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
- INTF_BLK("intf_1", INTF_1, 0x6a800, 0x280, INTF_DSI, 0, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
- INTF_BLK("intf_2", INTF_2, 0x6b000, 0x280, INTF_DSI, 1, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
- INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 1, 24, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
+ INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 24, INTF_SDM845_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)),
+ INTF_BLK("intf_1", INTF_1, 0x6a800, 0x280, INTF_DSI, 0, 24, INTF_SDM845_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27)),
+ INTF_BLK("intf_2", INTF_2, 0x6b000, 0x280, INTF_DSI, 1, 24, INTF_SDM845_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29)),
+ INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 1, 24, INTF_SDM845_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)),
};
static const struct dpu_perf_cfg sdm845_perf_data = {
@@ -185,6 +204,8 @@ const struct dpu_mdss_cfg dpu_sdm845_cfg = {
.sspp = sdm845_sspp,
.mixer_count = ARRAY_SIZE(sdm845_lm),
.mixer = sdm845_lm,
+ .dspp_count = ARRAY_SIZE(sdm845_dspp),
+ .dspp = sdm845_dspp,
.pingpong_count = ARRAY_SIZE(sdm845_pp),
.pingpong = sdm845_pp,
.dsc_count = ARRAY_SIZE(sdm845_dsc),
@@ -193,8 +214,6 @@ const struct dpu_mdss_cfg dpu_sdm845_cfg = {
.intf = sdm845_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
.vbif = sdm845_vbif,
- .reg_dma_count = 1,
- .dma_cfg = &sdm845_regdma,
.perf = &sdm845_perf_data,
.mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
BIT(MDP_SSPP_TOP0_INTR2) | \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h
index 42b0e58624d0..b5f751354267 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h
@@ -128,22 +128,22 @@ static const struct dpu_dspp_cfg sm8150_dspp[] = {
};
static const struct dpu_pingpong_cfg sm8150_pp[] = {
- PP_BLK("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk,
+ PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, MERGE_3D_0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
- PP_BLK("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk,
+ -1),
+ PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SM8150_MASK, MERGE_3D_0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
- PP_BLK("pingpong_2", PINGPONG_2, 0x71000, MERGE_3D_1, sdm845_pp_sblk,
+ -1),
+ PP_BLK("pingpong_2", PINGPONG_2, 0x71000, PINGPONG_SM8150_MASK, MERGE_3D_1, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)),
- PP_BLK("pingpong_3", PINGPONG_3, 0x71800, MERGE_3D_1, sdm845_pp_sblk,
+ -1),
+ PP_BLK("pingpong_3", PINGPONG_3, 0x71800, PINGPONG_SM8150_MASK, MERGE_3D_1, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)),
- PP_BLK("pingpong_4", PINGPONG_4, 0x72000, MERGE_3D_2, sdm845_pp_sblk,
+ -1),
+ PP_BLK("pingpong_4", PINGPONG_4, 0x72000, PINGPONG_SM8150_MASK, MERGE_3D_2, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
-1),
- PP_BLK("pingpong_5", PINGPONG_5, 0x72800, MERGE_3D_2, sdm845_pp_sblk,
+ PP_BLK("pingpong_5", PINGPONG_5, 0x72800, PINGPONG_SM8150_MASK, MERGE_3D_2, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
-1),
};
@@ -162,10 +162,20 @@ static const struct dpu_dsc_cfg sm8150_dsc[] = {
};
static const struct dpu_intf_cfg sm8150_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
- INTF_BLK("intf_1", INTF_1, 0x6a800, 0x2bc, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
- INTF_BLK("intf_2", INTF_2, 0x6b000, 0x2bc, INTF_DSI, 1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
- INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
+ INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)),
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2bc, INTF_DSI, 0, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)),
+ INTF_BLK_DSI_TE("intf_2", INTF_2, 0x6b000, 0x2bc, INTF_DSI, 1, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+ DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2)),
+ INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 1, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)),
};
static const struct dpu_perf_cfg sm8150_perf_data = {
@@ -220,15 +230,15 @@ const struct dpu_mdss_cfg dpu_sm8150_cfg = {
.intf = sm8150_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
.vbif = sdm845_vbif,
- .reg_dma_count = 1,
- .dma_cfg = &sm8150_regdma,
.perf = &sm8150_perf_data,
.mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
BIT(MDP_SSPP_TOP0_INTR2) | \
BIT(MDP_SSPP_TOP0_HIST_INTR) | \
BIT(MDP_INTF0_INTR) | \
BIT(MDP_INTF1_INTR) | \
+ BIT(MDP_INTF1_TEAR_INTR) | \
BIT(MDP_INTF2_INTR) | \
+ BIT(MDP_INTF2_TEAR_INTR) | \
BIT(MDP_INTF3_INTR) | \
BIT(MDP_AD4_0_INTR) | \
BIT(MDP_AD4_1_INTR),
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h
index e3bdfe7b30f1..8ed2b263c5ea 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h
@@ -102,9 +102,9 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = {
static const struct dpu_lm_cfg sc8180x_lm[] = {
LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
- &sdm845_lm_sblk, PINGPONG_0, LM_1, 0),
+ &sdm845_lm_sblk, PINGPONG_0, LM_1, DSPP_0),
LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
- &sdm845_lm_sblk, PINGPONG_1, LM_0, 0),
+ &sdm845_lm_sblk, PINGPONG_1, LM_0, DSPP_1),
LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,
&sdm845_lm_sblk, PINGPONG_2, LM_3, 0),
LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK,
@@ -115,23 +115,34 @@ static const struct dpu_lm_cfg sc8180x_lm[] = {
&sdm845_lm_sblk, PINGPONG_5, LM_4, 0),
};
+static const struct dpu_dspp_cfg sc8180x_dspp[] = {
+ DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK,
+ &sm8150_dspp_sblk),
+ DSPP_BLK("dspp_1", DSPP_1, 0x56000, DSPP_SC7180_MASK,
+ &sm8150_dspp_sblk),
+ DSPP_BLK("dspp_2", DSPP_2, 0x58000, DSPP_SC7180_MASK,
+ &sm8150_dspp_sblk),
+ DSPP_BLK("dspp_3", DSPP_3, 0x5a000, DSPP_SC7180_MASK,
+ &sm8150_dspp_sblk),
+};
+
static const struct dpu_pingpong_cfg sc8180x_pp[] = {
- PP_BLK("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk,
+ PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, MERGE_3D_0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
- PP_BLK("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk,
+ -1),
+ PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SM8150_MASK, MERGE_3D_0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
- PP_BLK("pingpong_2", PINGPONG_2, 0x71000, MERGE_3D_1, sdm845_pp_sblk,
+ -1),
+ PP_BLK("pingpong_2", PINGPONG_2, 0x71000, PINGPONG_SM8150_MASK, MERGE_3D_1, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)),
- PP_BLK("pingpong_3", PINGPONG_3, 0x71800, MERGE_3D_1, sdm845_pp_sblk,
+ -1),
+ PP_BLK("pingpong_3", PINGPONG_3, 0x71800, PINGPONG_SM8150_MASK, MERGE_3D_1, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)),
- PP_BLK("pingpong_4", PINGPONG_4, 0x72000, MERGE_3D_2, sdm845_pp_sblk,
+ -1),
+ PP_BLK("pingpong_4", PINGPONG_4, 0x72000, PINGPONG_SM8150_MASK, MERGE_3D_2, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
-1),
- PP_BLK("pingpong_5", PINGPONG_5, 0x72800, MERGE_3D_2, sdm845_pp_sblk,
+ PP_BLK("pingpong_5", PINGPONG_5, 0x72800, PINGPONG_SM8150_MASK, MERGE_3D_2, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
-1),
};
@@ -142,14 +153,37 @@ static const struct dpu_merge_3d_cfg sc8180x_merge_3d[] = {
MERGE_3D_BLK("merge_3d_2", MERGE_3D_2, 0x83200),
};
+static const struct dpu_dsc_cfg sc8180x_dsc[] = {
+ DSC_BLK("dsc_0", DSC_0, 0x80000, BIT(DPU_DSC_OUTPUT_CTRL)),
+ DSC_BLK("dsc_1", DSC_1, 0x80400, BIT(DPU_DSC_OUTPUT_CTRL)),
+ DSC_BLK("dsc_2", DSC_2, 0x80800, BIT(DPU_DSC_OUTPUT_CTRL)),
+ DSC_BLK("dsc_3", DSC_3, 0x80c00, BIT(DPU_DSC_OUTPUT_CTRL)),
+ DSC_BLK("dsc_4", DSC_4, 0x81000, BIT(DPU_DSC_OUTPUT_CTRL)),
+ DSC_BLK("dsc_5", DSC_5, 0x81400, BIT(DPU_DSC_OUTPUT_CTRL)),
+};
+
static const struct dpu_intf_cfg sc8180x_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
- INTF_BLK("intf_1", INTF_1, 0x6a800, 0x2bc, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
- INTF_BLK("intf_2", INTF_2, 0x6b000, 0x2bc, INTF_DSI, 1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
+ INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)),
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2bc, INTF_DSI, 0, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)),
+ INTF_BLK_DSI_TE("intf_2", INTF_2, 0x6b000, 0x2bc, INTF_DSI, 1, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+ DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2)),
/* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index until this is supported */
- INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 999, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
- INTF_BLK("intf_4", INTF_4, 0x6c000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 20, 21),
- INTF_BLK("intf_5", INTF_5, 0x6c800, 0x280, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 22, 23),
+ INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 999, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)),
+ INTF_BLK("intf_4", INTF_4, 0x6c000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21)),
+ INTF_BLK("intf_5", INTF_5, 0x6c800, 0x280, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23)),
};
static const struct dpu_perf_cfg sc8180x_perf_data = {
@@ -190,6 +224,10 @@ const struct dpu_mdss_cfg dpu_sc8180x_cfg = {
.sspp = sc8180x_sspp,
.mixer_count = ARRAY_SIZE(sc8180x_lm),
.mixer = sc8180x_lm,
+ .dspp_count = ARRAY_SIZE(sc8180x_dspp),
+ .dspp = sc8180x_dspp,
+ .dsc_count = ARRAY_SIZE(sc8180x_dsc),
+ .dsc = sc8180x_dsc,
.pingpong_count = ARRAY_SIZE(sc8180x_pp),
.pingpong = sc8180x_pp,
.merge_3d_count = ARRAY_SIZE(sc8180x_merge_3d),
@@ -198,15 +236,15 @@ const struct dpu_mdss_cfg dpu_sc8180x_cfg = {
.intf = sc8180x_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
.vbif = sdm845_vbif,
- .reg_dma_count = 1,
- .dma_cfg = &sm8150_regdma,
.perf = &sc8180x_perf_data,
.mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
BIT(MDP_SSPP_TOP0_INTR2) | \
BIT(MDP_SSPP_TOP0_HIST_INTR) | \
BIT(MDP_INTF0_INTR) | \
BIT(MDP_INTF1_INTR) | \
+ BIT(MDP_INTF1_TEAR_INTR) | \
BIT(MDP_INTF2_INTR) | \
+ BIT(MDP_INTF2_TEAR_INTR) | \
BIT(MDP_INTF3_INTR) | \
BIT(MDP_INTF4_INTR) | \
BIT(MDP_INTF5_INTR) | \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
index ed130582873c..daebd2170041 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
@@ -129,22 +129,22 @@ static const struct dpu_dspp_cfg sm8250_dspp[] = {
};
static const struct dpu_pingpong_cfg sm8250_pp[] = {
- PP_BLK("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk,
+ PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, MERGE_3D_0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
- PP_BLK("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk,
+ -1),
+ PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SM8150_MASK, MERGE_3D_0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
- PP_BLK("pingpong_2", PINGPONG_2, 0x71000, MERGE_3D_1, sdm845_pp_sblk,
+ -1),
+ PP_BLK("pingpong_2", PINGPONG_2, 0x71000, PINGPONG_SM8150_MASK, MERGE_3D_1, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)),
- PP_BLK("pingpong_3", PINGPONG_3, 0x71800, MERGE_3D_1, sdm845_pp_sblk,
+ -1),
+ PP_BLK("pingpong_3", PINGPONG_3, 0x71800, PINGPONG_SM8150_MASK, MERGE_3D_1, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)),
- PP_BLK("pingpong_4", PINGPONG_4, 0x72000, MERGE_3D_2, sdm845_pp_sblk,
+ -1),
+ PP_BLK("pingpong_4", PINGPONG_4, 0x72000, PINGPONG_SM8150_MASK, MERGE_3D_2, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
-1),
- PP_BLK("pingpong_5", PINGPONG_5, 0x72800, MERGE_3D_2, sdm845_pp_sblk,
+ PP_BLK("pingpong_5", PINGPONG_5, 0x72800, PINGPONG_SM8150_MASK, MERGE_3D_2, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
-1),
};
@@ -163,10 +163,20 @@ static const struct dpu_dsc_cfg sm8250_dsc[] = {
};
static const struct dpu_intf_cfg sm8250_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
- INTF_BLK("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
- INTF_BLK("intf_2", INTF_2, 0x6b000, 0x2c0, INTF_DSI, 1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
- INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
+ INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)),
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)),
+ INTF_BLK_DSI_TE("intf_2", INTF_2, 0x6b000, 0x2c0, INTF_DSI, 1, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+ DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2)),
+ INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_DP, 1, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)),
};
static const struct dpu_wb_cfg sm8250_wb[] = {
@@ -228,15 +238,15 @@ const struct dpu_mdss_cfg dpu_sm8250_cfg = {
.vbif = sdm845_vbif,
.wb_count = ARRAY_SIZE(sm8250_wb),
.wb = sm8250_wb,
- .reg_dma_count = 1,
- .dma_cfg = &sm8250_regdma,
.perf = &sm8250_perf_data,
.mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
BIT(MDP_SSPP_TOP0_INTR2) | \
BIT(MDP_SSPP_TOP0_HIST_INTR) | \
BIT(MDP_INTF0_INTR) | \
BIT(MDP_INTF1_INTR) | \
+ BIT(MDP_INTF1_TEAR_INTR) | \
BIT(MDP_INTF2_INTR) | \
+ BIT(MDP_INTF2_TEAR_INTR) | \
BIT(MDP_INTF3_INTR) | \
BIT(MDP_INTF4_INTR),
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h
index a46b11730a4d..67566b07195a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h
@@ -76,17 +76,26 @@ static const struct dpu_lm_cfg sc7180_lm[] = {
static const struct dpu_dspp_cfg sc7180_dspp[] = {
DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK,
- &sc7180_dspp_sblk),
+ &sm8150_dspp_sblk),
};
static const struct dpu_pingpong_cfg sc7180_pp[] = {
- PP_BLK("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk, -1, -1),
- PP_BLK("pingpong_1", PINGPONG_1, 0x70800, 0, sdm845_pp_sblk, -1, -1),
+ PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+ -1),
+ PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
+ -1),
};
static const struct dpu_intf_cfg sc7180_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
- INTF_BLK("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
+ INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)),
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)),
};
static const struct dpu_wb_cfg sc7180_wb[] = {
@@ -143,14 +152,13 @@ const struct dpu_mdss_cfg dpu_sc7180_cfg = {
.wb = sc7180_wb,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
.vbif = sdm845_vbif,
- .reg_dma_count = 1,
- .dma_cfg = &sdm845_regdma,
.perf = &sc7180_perf_data,
.mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
BIT(MDP_SSPP_TOP0_INTR2) | \
BIT(MDP_SSPP_TOP0_HIST_INTR) | \
BIT(MDP_INTF0_INTR) | \
- BIT(MDP_INTF1_INTR),
+ BIT(MDP_INTF1_INTR) | \
+ BIT(MDP_INTF1_TEAR_INTR),
};
#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h
index 988d820f7ef2..031fc8dae3c6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h
@@ -60,14 +60,16 @@ static const struct dpu_dspp_cfg sm6115_dspp[] = {
};
static const struct dpu_pingpong_cfg sm6115_pp[] = {
- PP_BLK("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk,
+ PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
+ -1),
};
static const struct dpu_intf_cfg sm6115_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x00000, 0x280, INTF_NONE, 0, 0, 0, 0, 0, 0),
- INTF_BLK("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)),
};
static const struct dpu_perf_cfg sm6115_perf_data = {
@@ -122,7 +124,8 @@ const struct dpu_mdss_cfg dpu_sm6115_cfg = {
.mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
BIT(MDP_SSPP_TOP0_INTR2) | \
BIT(MDP_SSPP_TOP0_HIST_INTR) | \
- BIT(MDP_INTF1_INTR),
+ BIT(MDP_INTF1_INTR) | \
+ BIT(MDP_INTF1_TEAR_INTR),
};
#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h
new file mode 100644
index 000000000000..06eba23b0236
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h
@@ -0,0 +1,173 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef _DPU_6_4_SM6350_H
+#define _DPU_6_4_SM6350_H
+
+static const struct dpu_caps sm6350_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .max_mixer_blendstages = 0x7,
+ .qseed_type = DPU_SSPP_SCALER_QSEED4,
+ .has_src_split = true,
+ .has_dim_layer = true,
+ .has_idle_pc = true,
+ .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+};
+
+static const struct dpu_ubwc_cfg sm6350_ubwc_cfg = {
+ .ubwc_version = DPU_HW_UBWC_VER_20,
+ .ubwc_swizzle = 6,
+ .highest_bank_bit = 1,
+};
+
+static const struct dpu_mdp_cfg sm6350_mdp[] = {
+ {
+ .name = "top_0", .id = MDP_TOP,
+ .base = 0x0, .len = 0x494,
+ .features = 0,
+ .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
+ .clk_ctrls[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
+ .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 },
+ .clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2c4, .bit_off = 8 },
+ .clk_ctrls[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 },
+ },
+};
+
+static const struct dpu_ctl_cfg sm6350_ctl[] = {
+ {
+ .name = "ctl_0", .id = CTL_0,
+ .base = 0x1000, .len = 0x1dc,
+ .features = BIT(DPU_CTL_ACTIVE_CFG),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
+ },
+ {
+ .name = "ctl_1", .id = CTL_1,
+ .base = 0x1200, .len = 0x1dc,
+ .features = BIT(DPU_CTL_ACTIVE_CFG),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
+ },
+ {
+ .name = "ctl_2", .id = CTL_2,
+ .base = 0x1400, .len = 0x1dc,
+ .features = BIT(DPU_CTL_ACTIVE_CFG),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
+ },
+ {
+ .name = "ctl_3", .id = CTL_3,
+ .base = 0x1600, .len = 0x1dc,
+ .features = BIT(DPU_CTL_ACTIVE_CFG),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
+ },
+};
+
+static const struct dpu_sspp_cfg sm6350_sspp[] = {
+ SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, 0x1f8, VIG_SC7180_MASK,
+ sc7180_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
+ SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, 0x1f8, DMA_SDM845_MASK,
+ sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
+ SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, 0x1f8, DMA_CURSOR_SDM845_MASK,
+ sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),
+ SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, 0x1f8, DMA_CURSOR_SDM845_MASK,
+ sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2),
+};
+
+static const struct dpu_lm_cfg sm6350_lm[] = {
+ LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
+ &sc7180_lm_sblk, PINGPONG_0, LM_1, DSPP_0),
+ LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
+ &sc7180_lm_sblk, PINGPONG_1, LM_0, 0),
+};
+
+static const struct dpu_dspp_cfg sm6350_dspp[] = {
+ DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK,
+ &sm8150_dspp_sblk),
+};
+
+static struct dpu_pingpong_cfg sm6350_pp[] = {
+ PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+ -1),
+ PP_BLK("pingpong_1", PINGPONG_1, 0x70800, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
+ -1),
+};
+
+static const struct dpu_dsc_cfg sm6350_dsc[] = {
+ DSC_BLK("dsc_0", DSC_0, 0x80000, BIT(DPU_DSC_OUTPUT_CTRL)),
+};
+
+static const struct dpu_intf_cfg sm6350_intf[] = {
+ INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 35, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)),
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 35, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)),
+};
+
+static const struct dpu_perf_cfg sm6350_perf_data = {
+ .max_bw_low = 4200000,
+ .max_bw_high = 5100000,
+ .min_core_ib = 2500000,
+ .min_llcc_ib = 0,
+ .min_dram_ib = 1600000,
+ .min_prefill_lines = 35,
+ /* TODO: confirm danger_lut_tbl */
+ .danger_lut_tbl = {0xffff, 0xffff, 0x0},
+ .safe_lut_tbl = {0xff00, 0xff00, 0xffff},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile),
+ .entries = sm6350_qos_linear_macrotile
+ },
+ {.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile),
+ .entries = sm6350_qos_linear_macrotile
+ },
+ {.nentry = ARRAY_SIZE(sc7180_qos_nrt),
+ .entries = sc7180_qos_nrt
+ },
+ },
+ .cdp_cfg = {
+ {.rd_enable = 1, .wr_enable = 1},
+ {.rd_enable = 1, .wr_enable = 0}
+ },
+ .clk_inefficiency_factor = 105,
+ .bw_inefficiency_factor = 120,
+};
+
+const struct dpu_mdss_cfg dpu_sm6350_cfg = {
+ .caps = &sm6350_dpu_caps,
+ .ubwc = &sm6350_ubwc_cfg,
+ .mdp_count = ARRAY_SIZE(sm6350_mdp),
+ .mdp = sm6350_mdp,
+ .ctl_count = ARRAY_SIZE(sm6350_ctl),
+ .ctl = sm6350_ctl,
+ .sspp_count = ARRAY_SIZE(sm6350_sspp),
+ .sspp = sm6350_sspp,
+ .mixer_count = ARRAY_SIZE(sm6350_lm),
+ .mixer = sm6350_lm,
+ .dspp_count = ARRAY_SIZE(sm6350_dspp),
+ .dspp = sm6350_dspp,
+ .dsc_count = ARRAY_SIZE(sm6350_dsc),
+ .dsc = sm6350_dsc,
+ .pingpong_count = ARRAY_SIZE(sm6350_pp),
+ .pingpong = sm6350_pp,
+ .intf_count = ARRAY_SIZE(sm6350_intf),
+ .intf = sm6350_intf,
+ .vbif_count = ARRAY_SIZE(sdm845_vbif),
+ .vbif = sdm845_vbif,
+ .perf = &sm6350_perf_data,
+ .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
+ BIT(MDP_SSPP_TOP0_INTR2) | \
+ BIT(MDP_SSPP_TOP0_HIST_INTR) | \
+ BIT(MDP_INTF0_INTR) | \
+ BIT(MDP_INTF1_INTR) | \
+ BIT(MDP_INTF1_TEAR_INTR),
+};
+
+#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h
index c9003dcc1a59..f2808098af39 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h
@@ -57,14 +57,16 @@ static const struct dpu_dspp_cfg qcm2290_dspp[] = {
};
static const struct dpu_pingpong_cfg qcm2290_pp[] = {
- PP_BLK("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk,
+ PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
+ -1),
};
static const struct dpu_intf_cfg qcm2290_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x00000, 0x280, INTF_NONE, 0, 0, 0, 0, 0, 0),
- INTF_BLK("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)),
};
static const struct dpu_perf_cfg qcm2290_perf_data = {
@@ -112,7 +114,8 @@ const struct dpu_mdss_cfg dpu_qcm2290_cfg = {
.mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
BIT(MDP_SSPP_TOP0_INTR2) | \
BIT(MDP_SSPP_TOP0_HIST_INTR) | \
- BIT(MDP_INTF1_INTR),
+ BIT(MDP_INTF1_INTR) | \
+ BIT(MDP_INTF1_TEAR_INTR),
};
#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h
new file mode 100644
index 000000000000..241fa6746674
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h
@@ -0,0 +1,138 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef _DPU_6_9_SM6375_H
+#define _DPU_6_9_SM6375_H
+
+static const struct dpu_caps sm6375_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_LINE_WIDTH,
+ .max_mixer_blendstages = 0x4,
+ .qseed_type = DPU_SSPP_SCALER_QSEED4,
+ .has_dim_layer = true,
+ .has_idle_pc = true,
+ .max_linewidth = 2160,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+};
+
+static const struct dpu_ubwc_cfg sm6375_ubwc_cfg = {
+ .ubwc_version = DPU_HW_UBWC_VER_20,
+ .ubwc_swizzle = 6,
+ .highest_bank_bit = 1,
+};
+
+static const struct dpu_mdp_cfg sm6375_mdp[] = {
+ {
+ .name = "top_0", .id = MDP_TOP,
+ .base = 0x0, .len = 0x494,
+ .features = 0,
+ .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
+ .clk_ctrls[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
+ },
+};
+
+static const struct dpu_ctl_cfg sm6375_ctl[] = {
+ {
+ .name = "ctl_0", .id = CTL_0,
+ .base = 0x1000, .len = 0x1dc,
+ .features = BIT(DPU_CTL_ACTIVE_CFG),
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
+ },
+};
+
+static const struct dpu_sspp_cfg sm6375_sspp[] = {
+ SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, 0x1f8, VIG_SC7180_MASK,
+ sm6115_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
+ SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, 0x1f8, DMA_SDM845_MASK,
+ sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
+};
+
+static const struct dpu_lm_cfg sm6375_lm[] = {
+ LM_BLK("lm_0", LM_0, 0x44000, MIXER_QCM2290_MASK,
+ &qcm2290_lm_sblk, PINGPONG_0, 0, DSPP_0),
+};
+
+static const struct dpu_dspp_cfg sm6375_dspp[] = {
+ DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK,
+ &sm8150_dspp_sblk),
+};
+
+static const struct dpu_pingpong_cfg sm6375_pp[] = {
+ PP_BLK("pingpong_0", PINGPONG_0, 0x70000, PINGPONG_SM8150_MASK, 0, sdm845_pp_sblk,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+ -1),
+};
+
+static const struct dpu_dsc_cfg sm6375_dsc[] = {
+ DSC_BLK("dsc_0", DSC_0, 0x80000, BIT(DPU_DSC_OUTPUT_CTRL)),
+};
+
+static const struct dpu_intf_cfg sm6375_intf[] = {
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x6a800, 0x2c0, INTF_DSI, 0, 24, INTF_SC7180_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2)),
+};
+
+static const struct dpu_perf_cfg sm6375_perf_data = {
+ .max_bw_low = 5200000,
+ .max_bw_high = 6200000,
+ .min_core_ib = 2500000,
+ .min_llcc_ib = 0, /* No LLCC on this SoC */
+ .min_dram_ib = 1600000,
+ .min_prefill_lines = 24,
+ /* TODO: confirm danger_lut_tbl */
+ .danger_lut_tbl = {0xffff, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile),
+ .entries = sm6350_qos_linear_macrotile
+ },
+ {.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile),
+ .entries = sm6350_qos_linear_macrotile
+ },
+ {.nentry = ARRAY_SIZE(sc7180_qos_nrt),
+ .entries = sc7180_qos_nrt
+ },
+ },
+ .cdp_cfg = {
+ {.rd_enable = 1, .wr_enable = 1},
+ {.rd_enable = 1, .wr_enable = 0}
+ },
+ .clk_inefficiency_factor = 105,
+ .bw_inefficiency_factor = 120,
+};
+
+const struct dpu_mdss_cfg dpu_sm6375_cfg = {
+ .caps = &sm6375_dpu_caps,
+ .ubwc = &sm6375_ubwc_cfg,
+ .mdp_count = ARRAY_SIZE(sm6375_mdp),
+ .mdp = sm6375_mdp,
+ .ctl_count = ARRAY_SIZE(sm6375_ctl),
+ .ctl = sm6375_ctl,
+ .sspp_count = ARRAY_SIZE(sm6375_sspp),
+ .sspp = sm6375_sspp,
+ .mixer_count = ARRAY_SIZE(sm6375_lm),
+ .mixer = sm6375_lm,
+ .dspp_count = ARRAY_SIZE(sm6375_dspp),
+ .dspp = sm6375_dspp,
+ .dsc_count = ARRAY_SIZE(sm6375_dsc),
+ .dsc = sm6375_dsc,
+ .pingpong_count = ARRAY_SIZE(sm6375_pp),
+ .pingpong = sm6375_pp,
+ .intf_count = ARRAY_SIZE(sm6375_intf),
+ .intf = sm6375_intf,
+ .vbif_count = ARRAY_SIZE(sdm845_vbif),
+ .vbif = sdm845_vbif,
+ .perf = &sm6375_perf_data,
+ .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
+ BIT(MDP_SSPP_TOP0_INTR2) | \
+ BIT(MDP_SSPP_TOP0_HIST_INTR) | \
+ BIT(MDP_INTF1_INTR) | \
+ BIT(MDP_INTF1_TEAR_INTR),
+};
+
+#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
index 4f6a965bcd90..8da424eaee6a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
@@ -129,16 +129,16 @@ static const struct dpu_dspp_cfg sm8350_dspp[] = {
static const struct dpu_pingpong_cfg sm8350_pp[] = {
PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
+ -1),
PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
+ -1),
PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)),
+ -1),
PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)),
+ -1),
PP_BLK_DITHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
-1),
@@ -153,11 +153,33 @@ static const struct dpu_merge_3d_cfg sm8350_merge_3d[] = {
MERGE_3D_BLK("merge_3d_2", MERGE_3D_2, 0x50000),
};
+/*
+ * NOTE: Each display compression engine (DCE) contains dual hard
+ * slice DSC encoders so both share same base address but with
+ * its own different sub block address.
+ */
+static const struct dpu_dsc_cfg sm8350_dsc[] = {
+ DSC_BLK_1_2("dce_0_0", DSC_0, 0x80000, 0x29c, 0, dsc_sblk_0),
+ DSC_BLK_1_2("dce_0_1", DSC_1, 0x80000, 0x29c, 0, dsc_sblk_1),
+ DSC_BLK_1_2("dce_1_0", DSC_2, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_0),
+ DSC_BLK_1_2("dce_1_1", DSC_3, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_1),
+};
+
static const struct dpu_intf_cfg sm8350_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
- INTF_BLK("intf_1", INTF_1, 0x35000, 0x2c4, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
- INTF_BLK("intf_2", INTF_2, 0x36000, 0x2c4, INTF_DSI, 1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
- INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
+ INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)),
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x35000, 0x2c4, INTF_DSI, 0, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_7xxx_TEAR_INTR, 2)),
+ INTF_BLK_DSI_TE("intf_2", INTF_2, 0x36000, 0x2c4, INTF_DSI, 1, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+ DPU_IRQ_IDX(MDP_INTF2_7xxx_TEAR_INTR, 2)),
+ INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)),
};
static const struct dpu_perf_cfg sm8350_perf_data = {
@@ -205,21 +227,23 @@ const struct dpu_mdss_cfg dpu_sm8350_cfg = {
.dspp = sm8350_dspp,
.pingpong_count = ARRAY_SIZE(sm8350_pp),
.pingpong = sm8350_pp,
+ .dsc_count = ARRAY_SIZE(sm8350_dsc),
+ .dsc = sm8350_dsc,
.merge_3d_count = ARRAY_SIZE(sm8350_merge_3d),
.merge_3d = sm8350_merge_3d,
.intf_count = ARRAY_SIZE(sm8350_intf),
.intf = sm8350_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
.vbif = sdm845_vbif,
- .reg_dma_count = 1,
- .dma_cfg = &sm8350_regdma,
.perf = &sm8350_perf_data,
.mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
BIT(MDP_SSPP_TOP0_INTR2) | \
BIT(MDP_SSPP_TOP0_HIST_INTR) | \
BIT(MDP_INTF0_7xxx_INTR) | \
BIT(MDP_INTF1_7xxx_INTR) | \
+ BIT(MDP_INTF1_7xxx_TEAR_INTR) | \
BIT(MDP_INTF2_7xxx_INTR) | \
+ BIT(MDP_INTF2_7xxx_TEAR_INTR) | \
BIT(MDP_INTF3_7xxx_INTR),
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
index 6b2c7eae71d9..900fee410e11 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
@@ -31,6 +31,7 @@ static const struct dpu_mdp_cfg sc7280_mdp[] = {
.clk_ctrls[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
.clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 },
.clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2c4, .bit_off = 8 },
+ .clk_ctrls[DPU_CLK_CTRL_WB2] = { .reg_off = 0x3b8, .bit_off = 24 },
},
};
@@ -83,20 +84,45 @@ static const struct dpu_lm_cfg sc7280_lm[] = {
static const struct dpu_dspp_cfg sc7280_dspp[] = {
DSPP_BLK("dspp_0", DSPP_0, 0x54000, DSPP_SC7180_MASK,
- &sc7180_dspp_sblk),
+ &sm8150_dspp_sblk),
};
static const struct dpu_pingpong_cfg sc7280_pp[] = {
- PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, 0, sc7280_pp_sblk, -1, -1),
- PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk, -1, -1),
- PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1),
- PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1),
+ PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, 0, sc7280_pp_sblk,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+ -1),
+ PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
+ -1),
+ PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
+ -1),
+ PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
+ -1),
+};
+
+/* NOTE: sc7280 only has one DSC hard slice encoder */
+static const struct dpu_dsc_cfg sc7280_dsc[] = {
+ DSC_BLK_1_2("dce_0_0", DSC_0, 0x80000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_0),
+};
+
+static const struct dpu_wb_cfg sc7280_wb[] = {
+ WB_BLK("wb_2", WB_2, 0x65000, WB_SM8250_MASK, DPU_CLK_CTRL_WB2, 6,
+ VBIF_RT, MDP_SSPP_TOP0_INTR, 4096, 4),
};
static const struct dpu_intf_cfg sc7280_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
- INTF_BLK("intf_1", INTF_1, 0x35000, 0x2c4, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
- INTF_BLK("intf_5", INTF_5, 0x39000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23),
+ INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)),
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x35000, 0x2c4, INTF_DSI, 0, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_7xxx_TEAR_INTR, 2)),
+ INTF_BLK("intf_5", INTF_5, 0x39000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23)),
};
static const struct dpu_perf_cfg sc7280_perf_data = {
@@ -142,6 +168,10 @@ const struct dpu_mdss_cfg dpu_sc7280_cfg = {
.mixer = sc7280_lm,
.pingpong_count = ARRAY_SIZE(sc7280_pp),
.pingpong = sc7280_pp,
+ .dsc_count = ARRAY_SIZE(sc7280_dsc),
+ .dsc = sc7280_dsc,
+ .wb_count = ARRAY_SIZE(sc7280_wb),
+ .wb = sc7280_wb,
.intf_count = ARRAY_SIZE(sc7280_intf),
.intf = sc7280_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
@@ -152,6 +182,7 @@ const struct dpu_mdss_cfg dpu_sc7280_cfg = {
BIT(MDP_SSPP_TOP0_HIST_INTR) | \
BIT(MDP_INTF0_7xxx_INTR) | \
BIT(MDP_INTF1_7xxx_INTR) | \
+ BIT(MDP_INTF1_7xxx_TEAR_INTR) | \
BIT(MDP_INTF5_7xxx_INTR),
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
index 706d0f13b598..f6ce6b090f71 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
@@ -42,17 +42,18 @@ static const struct dpu_mdp_cfg sc8280xp_mdp[] = {
},
};
+/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */
static const struct dpu_ctl_cfg sc8280xp_ctl[] = {
{
.name = "ctl_0", .id = CTL_0,
.base = 0x15000, .len = 0x204,
- .features = CTL_SC7280_MASK,
+ .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK,
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
},
{
.name = "ctl_1", .id = CTL_1,
.base = 0x16000, .len = 0x204,
- .features = CTL_SC7280_MASK,
+ .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK,
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
},
{
@@ -141,17 +142,51 @@ static const struct dpu_merge_3d_cfg sc8280xp_merge_3d[] = {
MERGE_3D_BLK("merge_3d_2", MERGE_3D_2, 0x50000),
};
+/*
+ * NOTE: Each display compression engine (DCE) contains dual hard
+ * slice DSC encoders so both share same base address but with
+ * its own different sub block address.
+ */
+static const struct dpu_dsc_cfg sc8280xp_dsc[] = {
+ DSC_BLK_1_2("dce_0_0", DSC_0, 0x80000, 0x29c, 0, dsc_sblk_0),
+ DSC_BLK_1_2("dce_0_1", DSC_1, 0x80000, 0x29c, 0, dsc_sblk_1),
+ DSC_BLK_1_2("dce_1_0", DSC_2, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_0),
+ DSC_BLK_1_2("dce_1_1", DSC_3, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_1),
+ DSC_BLK_1_2("dce_2_0", DSC_4, 0x82000, 0x29c, 0, dsc_sblk_0),
+ DSC_BLK_1_2("dce_2_1", DSC_5, 0x82000, 0x29c, 0, dsc_sblk_1),
+};
+
/* TODO: INTF 3, 8 and 7 are used for MST, marked as INTF_NONE for now */
static const struct dpu_intf_cfg sc8280xp_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
- INTF_BLK("intf_1", INTF_1, 0x35000, 0x300, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
- INTF_BLK("intf_2", INTF_2, 0x36000, 0x300, INTF_DSI, 1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
- INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_NONE, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
- INTF_BLK("intf_4", INTF_4, 0x38000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 20, 21),
- INTF_BLK("intf_5", INTF_5, 0x39000, 0x280, INTF_DP, MSM_DP_CONTROLLER_3, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23),
- INTF_BLK("intf_6", INTF_6, 0x3a000, 0x280, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 16, 17),
- INTF_BLK("intf_7", INTF_7, 0x3b000, 0x280, INTF_NONE, MSM_DP_CONTROLLER_2, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 18, 19),
- INTF_BLK("intf_8", INTF_8, 0x3c000, 0x280, INTF_NONE, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 12, 13),
+ INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)),
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x35000, 0x300, INTF_DSI, 0, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_7xxx_TEAR_INTR, 2)),
+ INTF_BLK_DSI_TE("intf_2", INTF_2, 0x36000, 0x300, INTF_DSI, 1, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+ DPU_IRQ_IDX(MDP_INTF2_7xxx_TEAR_INTR, 2)),
+ INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_NONE, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)),
+ INTF_BLK("intf_4", INTF_4, 0x38000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21)),
+ INTF_BLK("intf_5", INTF_5, 0x39000, 0x280, INTF_DP, MSM_DP_CONTROLLER_3, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23)),
+ INTF_BLK("intf_6", INTF_6, 0x3a000, 0x280, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17)),
+ INTF_BLK("intf_7", INTF_7, 0x3b000, 0x280, INTF_NONE, MSM_DP_CONTROLLER_2, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 18),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 19)),
+ INTF_BLK("intf_8", INTF_8, 0x3c000, 0x280, INTF_NONE, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
};
static const struct dpu_perf_cfg sc8280xp_perf_data = {
@@ -196,21 +231,23 @@ const struct dpu_mdss_cfg dpu_sc8280xp_cfg = {
.dspp = sc8280xp_dspp,
.pingpong_count = ARRAY_SIZE(sc8280xp_pp),
.pingpong = sc8280xp_pp,
+ .dsc_count = ARRAY_SIZE(sc8280xp_dsc),
+ .dsc = sc8280xp_dsc,
.merge_3d_count = ARRAY_SIZE(sc8280xp_merge_3d),
.merge_3d = sc8280xp_merge_3d,
.intf_count = ARRAY_SIZE(sc8280xp_intf),
.intf = sc8280xp_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
.vbif = sdm845_vbif,
- .reg_dma_count = 1,
- .dma_cfg = &sc8280xp_regdma,
.perf = &sc8280xp_perf_data,
.mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
BIT(MDP_SSPP_TOP0_INTR2) | \
BIT(MDP_SSPP_TOP0_HIST_INTR) | \
BIT(MDP_INTF0_7xxx_INTR) | \
BIT(MDP_INTF1_7xxx_INTR) | \
+ BIT(MDP_INTF1_7xxx_TEAR_INTR) | \
BIT(MDP_INTF2_7xxx_INTR) | \
+ BIT(MDP_INTF2_7xxx_TEAR_INTR) | \
BIT(MDP_INTF3_7xxx_INTR) | \
BIT(MDP_INTF4_7xxx_INTR) | \
BIT(MDP_INTF5_7xxx_INTR) | \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
index 4ecb3df5cbc0..8d13c369213c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
@@ -47,7 +47,7 @@ static const struct dpu_ctl_cfg sm8450_ctl[] = {
{
.name = "ctl_0", .id = CTL_0,
.base = 0x15000, .len = 0x204,
- .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY) | BIT(DPU_CTL_FETCH_ACTIVE),
+ .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK,
.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
},
{
@@ -107,9 +107,9 @@ static const struct dpu_lm_cfg sm8450_lm[] = {
LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
&sdm845_lm_sblk, PINGPONG_1, LM_0, DSPP_1),
LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,
- &sdm845_lm_sblk, PINGPONG_2, LM_3, 0),
+ &sdm845_lm_sblk, PINGPONG_2, LM_3, DSPP_2),
LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK,
- &sdm845_lm_sblk, PINGPONG_3, LM_2, 0),
+ &sdm845_lm_sblk, PINGPONG_3, LM_2, DSPP_3),
LM_BLK("lm_4", LM_4, 0x48000, MIXER_SDM845_MASK,
&sdm845_lm_sblk, PINGPONG_4, LM_5, 0),
LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK,
@@ -126,20 +126,20 @@ static const struct dpu_dspp_cfg sm8450_dspp[] = {
DSPP_BLK("dspp_3", DSPP_3, 0x5a000, DSPP_SC7180_MASK,
&sm8150_dspp_sblk),
};
-/* FIXME: interrupts */
+
static const struct dpu_pingpong_cfg sm8450_pp[] = {
PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)),
+ -1),
PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)),
+ -1),
PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)),
+ -1),
PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
- DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)),
+ -1),
PP_BLK_DITHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
-1),
@@ -161,11 +161,33 @@ static const struct dpu_merge_3d_cfg sm8450_merge_3d[] = {
MERGE_3D_BLK("merge_3d_3", MERGE_3D_3, 0x65f00),
};
+/*
+ * NOTE: Each display compression engine (DCE) contains dual hard
+ * slice DSC encoders so both share same base address but with
+ * its own different sub block address.
+ */
+static const struct dpu_dsc_cfg sm8450_dsc[] = {
+ DSC_BLK_1_2("dce_0_0", DSC_0, 0x80000, 0x29c, 0, dsc_sblk_0),
+ DSC_BLK_1_2("dce_0_1", DSC_1, 0x80000, 0x29c, 0, dsc_sblk_1),
+ DSC_BLK_1_2("dce_1_0", DSC_2, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_0),
+ DSC_BLK_1_2("dce_1_1", DSC_3, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_1),
+};
+
static const struct dpu_intf_cfg sm8450_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
- INTF_BLK("intf_1", INTF_1, 0x35000, 0x300, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
- INTF_BLK("intf_2", INTF_2, 0x36000, 0x300, INTF_DSI, 1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
- INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
+ INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)),
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x35000, 0x300, INTF_DSI, 0, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_7xxx_TEAR_INTR, 2)),
+ INTF_BLK_DSI_TE("intf_2", INTF_2, 0x36000, 0x300, INTF_DSI, 1, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+ DPU_IRQ_IDX(MDP_INTF2_7xxx_TEAR_INTR, 2)),
+ INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)),
};
static const struct dpu_perf_cfg sm8450_perf_data = {
@@ -213,21 +235,23 @@ const struct dpu_mdss_cfg dpu_sm8450_cfg = {
.dspp = sm8450_dspp,
.pingpong_count = ARRAY_SIZE(sm8450_pp),
.pingpong = sm8450_pp,
+ .dsc_count = ARRAY_SIZE(sm8450_dsc),
+ .dsc = sm8450_dsc,
.merge_3d_count = ARRAY_SIZE(sm8450_merge_3d),
.merge_3d = sm8450_merge_3d,
.intf_count = ARRAY_SIZE(sm8450_intf),
.intf = sm8450_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
.vbif = sdm845_vbif,
- .reg_dma_count = 1,
- .dma_cfg = &sm8450_regdma,
.perf = &sm8450_perf_data,
.mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
BIT(MDP_SSPP_TOP0_INTR2) | \
BIT(MDP_SSPP_TOP0_HIST_INTR) | \
BIT(MDP_INTF0_7xxx_INTR) | \
BIT(MDP_INTF1_7xxx_INTR) | \
+ BIT(MDP_INTF1_7xxx_TEAR_INTR) | \
BIT(MDP_INTF2_7xxx_INTR) | \
+ BIT(MDP_INTF2_7xxx_TEAR_INTR) | \
BIT(MDP_INTF3_7xxx_INTR),
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
index d0ab351b6a8b..f17b9a7fee85 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
@@ -165,12 +165,33 @@ static const struct dpu_merge_3d_cfg sm8550_merge_3d[] = {
MERGE_3D_BLK("merge_3d_3", MERGE_3D_3, 0x66700),
};
+/*
+ * NOTE: Each display compression engine (DCE) contains dual hard
+ * slice DSC encoders so both share same base address but with
+ * its own different sub block address.
+ */
+static const struct dpu_dsc_cfg sm8550_dsc[] = {
+ DSC_BLK_1_2("dce_0_0", DSC_0, 0x80000, 0x29c, 0, dsc_sblk_0),
+ DSC_BLK_1_2("dce_0_1", DSC_1, 0x80000, 0x29c, 0, dsc_sblk_1),
+ DSC_BLK_1_2("dce_1_0", DSC_2, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_0),
+ DSC_BLK_1_2("dce_1_1", DSC_3, 0x81000, 0x29c, BIT(DPU_DSC_NATIVE_42x_EN), dsc_sblk_1),
+};
+
static const struct dpu_intf_cfg sm8550_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25),
- /* TODO TE sub-blocks for intf1 & intf2 */
- INTF_BLK("intf_1", INTF_1, 0x35000, 0x300, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27),
- INTF_BLK("intf_2", INTF_2, 0x36000, 0x300, INTF_DSI, 1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 28, 29),
- INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 30, 31),
+ INTF_BLK("intf_0", INTF_0, 0x34000, 0x280, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25)),
+ INTF_BLK_DSI_TE("intf_1", INTF_1, 0x35000, 0x300, INTF_DSI, 0, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ DPU_IRQ_IDX(MDP_INTF1_7xxx_TEAR_INTR, 2)),
+ INTF_BLK_DSI_TE("intf_2", INTF_2, 0x36000, 0x300, INTF_DSI, 1, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+ DPU_IRQ_IDX(MDP_INTF2_7xxx_TEAR_INTR, 2)),
+ INTF_BLK("intf_3", INTF_3, 0x37000, 0x280, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK,
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+ DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31)),
};
static const struct dpu_perf_cfg sm8550_perf_data = {
@@ -218,21 +239,23 @@ const struct dpu_mdss_cfg dpu_sm8550_cfg = {
.dspp = sm8550_dspp,
.pingpong_count = ARRAY_SIZE(sm8550_pp),
.pingpong = sm8550_pp,
+ .dsc_count = ARRAY_SIZE(sm8550_dsc),
+ .dsc = sm8550_dsc,
.merge_3d_count = ARRAY_SIZE(sm8550_merge_3d),
.merge_3d = sm8550_merge_3d,
.intf_count = ARRAY_SIZE(sm8550_intf),
.intf = sm8550_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
.vbif = sdm845_vbif,
- .reg_dma_count = 1,
- .dma_cfg = &sm8450_regdma,
.perf = &sm8550_perf_data,
.mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \
BIT(MDP_SSPP_TOP0_INTR2) | \
BIT(MDP_SSPP_TOP0_HIST_INTR) | \
BIT(MDP_INTF0_7xxx_INTR) | \
BIT(MDP_INTF1_7xxx_INTR) | \
+ BIT(MDP_INTF1_7xxx_TEAR_INTR) | \
BIT(MDP_INTF2_7xxx_INTR) | \
+ BIT(MDP_INTF2_7xxx_TEAR_INTR) | \
BIT(MDP_INTF3_7xxx_INTR),
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index cc66ddffe672..1edf2b6b0a26 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1392,7 +1392,7 @@ DEFINE_SHOW_ATTRIBUTE(_dpu_debugfs_status);
static int dpu_crtc_debugfs_state_show(struct seq_file *s, void *v)
{
- struct drm_crtc *crtc = (struct drm_crtc *) s->private;
+ struct drm_crtc *crtc = s->private;
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
seq_printf(s, "client type: %d\n", dpu_crtc_get_client_type(crtc));
@@ -1463,6 +1463,8 @@ static const struct drm_crtc_helper_funcs dpu_crtc_helper_funcs = {
struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
struct drm_plane *cursor)
{
+ struct msm_drm_private *priv = dev->dev_private;
+ struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
struct drm_crtc *crtc = NULL;
struct dpu_crtc *dpu_crtc = NULL;
int i, ret;
@@ -1494,7 +1496,8 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs);
- drm_crtc_enable_color_mgmt(crtc, 0, true, 0);
+ if (dpu_kms->catalog->dspp_count)
+ drm_crtc_enable_color_mgmt(crtc, 0, true, 0);
/* save user friendly CRTC name for later */
snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 1dc5dbe58572..493905a5b63a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -339,7 +339,8 @@ void dpu_encoder_helper_report_irq_timeout(struct dpu_encoder_phys *phys_enc,
DRM_ERROR("irq timeout id=%u, intf_mode=%s intf=%d wb=%d, pp=%d, intr=%d\n",
DRMID(phys_enc->parent),
dpu_encoder_helper_get_intf_type(phys_enc->intf_mode),
- phys_enc->intf_idx - INTF_0, phys_enc->wb_idx - WB_0,
+ phys_enc->hw_intf ? phys_enc->hw_intf->idx - INTF_0 : -1,
+ phys_enc->hw_wb ? phys_enc->hw_wb->idx - WB_0 : -1,
phys_enc->hw_pp->idx - PINGPONG_0, intr_idx);
dpu_encoder_frame_done_callback(phys_enc->parent, phys_enc,
@@ -495,7 +496,7 @@ void dpu_encoder_helper_split_config(
hw_mdptop = phys_enc->hw_mdptop;
disp_info = &dpu_enc->disp_info;
- if (disp_info->intf_type != DRM_MODE_ENCODER_DSI)
+ if (disp_info->intf_type != INTF_DSI)
return;
/**
@@ -666,6 +667,7 @@ static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc,
struct dpu_kms *dpu_kms;
struct dpu_hw_mdp *hw_mdptop;
struct drm_encoder *drm_enc;
+ struct dpu_encoder_phys *phys_enc;
int i;
if (!dpu_enc || !disp_info) {
@@ -696,12 +698,22 @@ static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc,
vsync_cfg.ppnumber[i] = dpu_enc->hw_pp[i]->idx;
vsync_cfg.pp_count = dpu_enc->num_phys_encs;
+ vsync_cfg.frame_rate = drm_mode_vrefresh(&dpu_enc->base.crtc->state->adjusted_mode);
+
if (disp_info->is_te_using_watchdog_timer)
vsync_cfg.vsync_source = DPU_VSYNC_SOURCE_WD_TIMER_0;
else
vsync_cfg.vsync_source = DPU_VSYNC0_SOURCE_GPIO;
hw_mdptop->ops.setup_vsync_source(hw_mdptop, &vsync_cfg);
+
+ for (i = 0; i < dpu_enc->num_phys_encs; i++) {
+ phys_enc = dpu_enc->phys_encs[i];
+
+ if (phys_enc->has_intf_te && phys_enc->hw_intf->ops.vsync_sel)
+ phys_enc->hw_intf->ops.vsync_sel(phys_enc->hw_intf,
+ vsync_cfg.vsync_source);
+ }
}
}
@@ -1127,7 +1139,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
}
- if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_TMDS &&
+ if (dpu_enc->disp_info.intf_type == INTF_DP &&
dpu_enc->cur_master->hw_mdptop &&
dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select)
dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select(
@@ -1135,7 +1147,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
_dpu_encoder_update_vsync_source(dpu_enc, &dpu_enc->disp_info);
- if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI &&
+ if (dpu_enc->disp_info.intf_type == INTF_DSI &&
!WARN_ON(dpu_enc->num_phys_encs == 0)) {
unsigned bpc = dpu_enc->connector->display_info.bpc;
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
@@ -1258,38 +1270,23 @@ static void dpu_encoder_virt_atomic_disable(struct drm_encoder *drm_enc,
mutex_unlock(&dpu_enc->enc_lock);
}
-static enum dpu_intf dpu_encoder_get_intf(const struct dpu_mdss_cfg *catalog,
+static struct dpu_hw_intf *dpu_encoder_get_intf(const struct dpu_mdss_cfg *catalog,
+ struct dpu_rm *dpu_rm,
enum dpu_intf_type type, u32 controller_id)
{
int i = 0;
if (type == INTF_WB)
- return INTF_MAX;
+ return NULL;
for (i = 0; i < catalog->intf_count; i++) {
if (catalog->intf[i].type == type
&& catalog->intf[i].controller_id == controller_id) {
- return catalog->intf[i].id;
+ return dpu_rm_get_intf(dpu_rm, catalog->intf[i].id);
}
}
- return INTF_MAX;
-}
-
-static enum dpu_wb dpu_encoder_get_wb(const struct dpu_mdss_cfg *catalog,
- enum dpu_intf_type type, u32 controller_id)
-{
- int i = 0;
-
- if (type != INTF_WB)
- return WB_MAX;
-
- for (i = 0; i < catalog->wb_count; i++) {
- if (catalog->wb[i].id == controller_id)
- return catalog->wb[i].id;
- }
-
- return WB_MAX;
+ return NULL;
}
void dpu_encoder_vblank_callback(struct drm_encoder *drm_enc,
@@ -1408,7 +1405,8 @@ void dpu_encoder_frame_done_callback(
*/
trace_dpu_enc_frame_done_cb_not_busy(DRMID(drm_enc), event,
dpu_encoder_helper_get_intf_type(ready_phys->intf_mode),
- ready_phys->intf_idx, ready_phys->wb_idx);
+ ready_phys->hw_intf ? ready_phys->hw_intf->idx : -1,
+ ready_phys->hw_wb ? ready_phys->hw_wb->idx : -1);
return;
}
@@ -1488,7 +1486,8 @@ static void _dpu_encoder_trigger_flush(struct drm_encoder *drm_enc,
trace_dpu_enc_trigger_flush(DRMID(drm_enc),
dpu_encoder_helper_get_intf_type(phys->intf_mode),
- phys->intf_idx, phys->wb_idx,
+ phys->hw_intf ? phys->hw_intf->idx : -1,
+ phys->hw_wb ? phys->hw_wb->idx : -1,
pending_kickoff_cnt, ctl->idx,
extra_flush_bits, ret);
}
@@ -1823,7 +1822,8 @@ dpu_encoder_dsc_initial_line_calc(struct drm_dsc_config *dsc,
return DIV_ROUND_UP(total_pixels, dsc->slice_width);
}
-static void dpu_encoder_dsc_pipe_cfg(struct dpu_hw_dsc *hw_dsc,
+static void dpu_encoder_dsc_pipe_cfg(struct dpu_hw_ctl *ctl,
+ struct dpu_hw_dsc *hw_dsc,
struct dpu_hw_pingpong *hw_pp,
struct drm_dsc_config *dsc,
u32 common_mode,
@@ -1839,10 +1839,13 @@ static void dpu_encoder_dsc_pipe_cfg(struct dpu_hw_dsc *hw_dsc,
hw_pp->ops.setup_dsc(hw_pp);
if (hw_dsc->ops.dsc_bind_pingpong_blk)
- hw_dsc->ops.dsc_bind_pingpong_blk(hw_dsc, true, hw_pp->idx);
+ hw_dsc->ops.dsc_bind_pingpong_blk(hw_dsc, hw_pp->idx);
if (hw_pp->ops.enable_dsc)
hw_pp->ops.enable_dsc(hw_pp);
+
+ if (ctl->ops.update_pending_flush_dsc)
+ ctl->ops.update_pending_flush_dsc(ctl, hw_dsc->idx);
}
static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc,
@@ -1850,6 +1853,7 @@ static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc,
{
/* coding only for 2LM, 2enc, 1 dsc config */
struct dpu_encoder_phys *enc_master = dpu_enc->cur_master;
+ struct dpu_hw_ctl *ctl = enc_master->hw_ctl;
struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
int this_frame_slices;
@@ -1887,7 +1891,8 @@ static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc,
initial_lines = dpu_encoder_dsc_initial_line_calc(dsc, enc_ip_w);
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
- dpu_encoder_dsc_pipe_cfg(hw_dsc[i], hw_pp[i], dsc, dsc_common_mode, initial_lines);
+ dpu_encoder_dsc_pipe_cfg(ctl, hw_dsc[i], hw_pp[i],
+ dsc, dsc_common_mode, initial_lines);
}
void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
@@ -1977,7 +1982,7 @@ void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
phys->ops.handle_post_kickoff(phys);
}
- if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI &&
+ if (dpu_enc->disp_info.intf_type == INTF_DSI &&
!dpu_encoder_vsync_time(drm_enc, &wakeup_time)) {
trace_dpu_enc_early_kickoff(DRMID(drm_enc),
ktime_to_ms(wakeup_time));
@@ -2019,6 +2024,41 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
}
}
+static void dpu_encoder_dsc_pipe_clr(struct dpu_hw_ctl *ctl,
+ struct dpu_hw_dsc *hw_dsc,
+ struct dpu_hw_pingpong *hw_pp)
+{
+ if (hw_dsc->ops.dsc_disable)
+ hw_dsc->ops.dsc_disable(hw_dsc);
+
+ if (hw_pp->ops.disable_dsc)
+ hw_pp->ops.disable_dsc(hw_pp);
+
+ if (hw_dsc->ops.dsc_bind_pingpong_blk)
+ hw_dsc->ops.dsc_bind_pingpong_blk(hw_dsc, PINGPONG_NONE);
+
+ if (ctl->ops.update_pending_flush_dsc)
+ ctl->ops.update_pending_flush_dsc(ctl, hw_dsc->idx);
+}
+
+static void dpu_encoder_unprep_dsc(struct dpu_encoder_virt *dpu_enc)
+{
+ /* coding only for 2LM, 2enc, 1 dsc config */
+ struct dpu_encoder_phys *enc_master = dpu_enc->cur_master;
+ struct dpu_hw_ctl *ctl = enc_master->hw_ctl;
+ struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
+ struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
+ int i;
+
+ for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
+ hw_pp[i] = dpu_enc->hw_pp[i];
+ hw_dsc[i] = dpu_enc->hw_dsc[i];
+
+ if (hw_pp[i] && hw_dsc[i])
+ dpu_encoder_dsc_pipe_clr(ctl, hw_dsc[i], hw_pp[i]);
+ }
+}
+
void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
{
struct dpu_hw_ctl *ctl = phys_enc->hw_ctl;
@@ -2040,8 +2080,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
if (phys_enc->hw_wb) {
/* disable the PP block */
if (phys_enc->hw_wb->ops.bind_pingpong_blk)
- phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb, false,
- phys_enc->hw_pp->idx);
+ phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb, PINGPONG_NONE);
/* mark WB flush as pending */
if (phys_enc->hw_ctl->ops.update_pending_flush_wb)
@@ -2050,8 +2089,8 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
if (dpu_enc->phys_encs[i] && phys_enc->hw_intf->ops.bind_pingpong_blk)
phys_enc->hw_intf->ops.bind_pingpong_blk(
- dpu_enc->phys_encs[i]->hw_intf, false,
- dpu_enc->phys_encs[i]->hw_pp->idx);
+ dpu_enc->phys_encs[i]->hw_intf,
+ PINGPONG_NONE);
/* mark INTF flush as pending */
if (phys_enc->hw_ctl->ops.update_pending_flush_intf)
@@ -2069,8 +2108,12 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
phys_enc->hw_pp->merge_3d->idx);
}
+ if (dpu_enc->dsc)
+ dpu_encoder_unprep_dsc(dpu_enc);
+
intf_cfg.stream_sel = 0; /* Don't care value for video mode */
intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
+ intf_cfg.dsc = dpu_encoder_helper_get_dsc(phys_enc);
if (phys_enc->hw_intf)
intf_cfg.intf = phys_enc->hw_intf->idx;
@@ -2099,7 +2142,8 @@ static int _dpu_encoder_status_show(struct seq_file *s, void *data)
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
seq_printf(s, "intf:%d wb:%d vsync:%8d underrun:%8d ",
- phys->intf_idx - INTF_0, phys->wb_idx - WB_0,
+ phys->hw_intf ? phys->hw_intf->idx - INTF_0 : -1,
+ phys->hw_wb ? phys->hw_wb->idx - WB_0 : -1,
atomic_read(&phys->vsync_cnt),
atomic_read(&phys->underrun_cnt));
@@ -2115,16 +2159,15 @@ DEFINE_SHOW_ATTRIBUTE(_dpu_encoder_status);
static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
- int i;
- char name[DPU_NAME_SIZE];
+ char name[12];
if (!drm_enc->dev) {
DPU_ERROR("invalid encoder or kms\n");
return -EINVAL;
}
- snprintf(name, DPU_NAME_SIZE, "encoder%u", drm_enc->base.id);
+ snprintf(name, sizeof(name), "encoder%u", drm_enc->base.id);
/* create overall sub-directory for the encoder */
dpu_enc->debugfs_root = debugfs_create_dir(name,
@@ -2134,12 +2177,6 @@ static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc)
debugfs_create_file("status", 0600,
dpu_enc->debugfs_root, dpu_enc, &_dpu_encoder_status_fops);
- for (i = 0; i < dpu_enc->num_phys_encs; i++)
- if (dpu_enc->phys_encs[i]->ops.late_register)
- dpu_enc->phys_encs[i]->ops.late_register(
- dpu_enc->phys_encs[i],
- dpu_enc->debugfs_root);
-
return 0;
}
#else
@@ -2182,7 +2219,7 @@ static int dpu_encoder_virt_add_phys_encs(
}
- if (disp_info->intf_type == DRM_MODE_ENCODER_VIRTUAL) {
+ if (disp_info->intf_type == INTF_WB) {
enc = dpu_encoder_phys_wb_init(params);
if (IS_ERR(enc)) {
@@ -2231,7 +2268,6 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc,
{
int ret = 0;
int i = 0;
- enum dpu_intf_type intf_type = INTF_NONE;
struct dpu_enc_phys_init_params phys_params;
if (!dpu_enc) {
@@ -2246,23 +2282,11 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc,
phys_params.parent = &dpu_enc->base;
phys_params.enc_spinlock = &dpu_enc->enc_spinlock;
- switch (disp_info->intf_type) {
- case DRM_MODE_ENCODER_DSI:
- intf_type = INTF_DSI;
- break;
- case DRM_MODE_ENCODER_TMDS:
- intf_type = INTF_DP;
- break;
- case DRM_MODE_ENCODER_VIRTUAL:
- intf_type = INTF_WB;
- break;
- }
-
WARN_ON(disp_info->num_of_h_tiles < 1);
DPU_DEBUG("dsi_info->num_of_h_tiles %d\n", disp_info->num_of_h_tiles);
- if (disp_info->intf_type != DRM_MODE_ENCODER_VIRTUAL)
+ if (disp_info->intf_type != INTF_WB)
dpu_enc->idle_pc_supported =
dpu_kms->catalog->caps->has_idle_pc;
@@ -2289,58 +2313,31 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc,
DPU_DEBUG("h_tile_instance %d = %d, split_role %d\n",
i, controller_id, phys_params.split_role);
- phys_params.intf_idx = dpu_encoder_get_intf(dpu_kms->catalog,
- intf_type,
- controller_id);
-
- phys_params.wb_idx = dpu_encoder_get_wb(dpu_kms->catalog,
- intf_type, controller_id);
- /*
- * The phys_params might represent either an INTF or a WB unit, but not
- * both of them at the same time.
- */
- if ((phys_params.intf_idx == INTF_MAX) &&
- (phys_params.wb_idx == WB_MAX)) {
- DPU_ERROR_ENC(dpu_enc, "could not get intf or wb: type %d, id %d\n",
- intf_type, controller_id);
- ret = -EINVAL;
- }
-
- if ((phys_params.intf_idx != INTF_MAX) &&
- (phys_params.wb_idx != WB_MAX)) {
- DPU_ERROR_ENC(dpu_enc, "both intf and wb present: type %d, id %d\n",
- intf_type, controller_id);
- ret = -EINVAL;
- }
-
- if (!ret) {
- ret = dpu_encoder_virt_add_phys_encs(disp_info,
- dpu_enc, &phys_params);
- if (ret)
- DPU_ERROR_ENC(dpu_enc, "failed to add phys encs\n");
- }
- }
-
- for (i = 0; i < dpu_enc->num_phys_encs; i++) {
- struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
- atomic_set(&phys->vsync_cnt, 0);
- atomic_set(&phys->underrun_cnt, 0);
-
- if (phys->intf_idx >= INTF_0 && phys->intf_idx < INTF_MAX)
- phys->hw_intf = dpu_rm_get_intf(&dpu_kms->rm, phys->intf_idx);
+ phys_params.hw_intf = dpu_encoder_get_intf(dpu_kms->catalog, &dpu_kms->rm,
+ disp_info->intf_type,
+ controller_id);
- if (phys->wb_idx >= WB_0 && phys->wb_idx < WB_MAX)
- phys->hw_wb = dpu_rm_get_wb(&dpu_kms->rm, phys->wb_idx);
+ if (disp_info->intf_type == INTF_WB && controller_id < WB_MAX)
+ phys_params.hw_wb = dpu_rm_get_wb(&dpu_kms->rm, controller_id);
- if (!phys->hw_intf && !phys->hw_wb) {
+ if (!phys_params.hw_intf && !phys_params.hw_wb) {
DPU_ERROR_ENC(dpu_enc, "no intf or wb block assigned at idx: %d\n", i);
ret = -EINVAL;
+ break;
}
- if (phys->hw_intf && phys->hw_wb) {
+ if (phys_params.hw_intf && phys_params.hw_wb) {
DPU_ERROR_ENC(dpu_enc,
"invalid phys both intf and wb block at idx: %d\n", i);
ret = -EINVAL;
+ break;
+ }
+
+ ret = dpu_encoder_virt_add_phys_encs(disp_info,
+ dpu_enc, &phys_params);
+ if (ret) {
+ DPU_ERROR_ENC(dpu_enc, "failed to add phys encs\n");
+ break;
}
}
@@ -2390,7 +2387,8 @@ static const struct drm_encoder_funcs dpu_encoder_funcs = {
.early_unregister = dpu_encoder_early_unregister,
};
-int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
+struct drm_encoder *dpu_encoder_init(struct drm_device *dev,
+ int drm_enc_mode,
struct msm_display_info *disp_info)
{
struct msm_drm_private *priv = dev->dev_private;
@@ -2399,7 +2397,23 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
struct dpu_encoder_virt *dpu_enc = NULL;
int ret = 0;
- dpu_enc = to_dpu_encoder_virt(enc);
+ dpu_enc = devm_kzalloc(dev->dev, sizeof(*dpu_enc), GFP_KERNEL);
+ if (!dpu_enc)
+ return ERR_PTR(-ENOMEM);
+
+ ret = drm_encoder_init(dev, &dpu_enc->base, &dpu_encoder_funcs,
+ drm_enc_mode, NULL);
+ if (ret) {
+ devm_kfree(dev->dev, dpu_enc);
+ return ERR_PTR(ret);
+ }
+
+ drm_encoder_helper_add(&dpu_enc->base, &dpu_encoder_helper_funcs);
+
+ spin_lock_init(&dpu_enc->enc_spinlock);
+ dpu_enc->enabled = false;
+ mutex_init(&dpu_enc->enc_lock);
+ mutex_init(&dpu_enc->rc_lock);
ret = dpu_encoder_setup_display(dpu_enc, dpu_kms, disp_info);
if (ret)
@@ -2409,11 +2423,11 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
timer_setup(&dpu_enc->frame_done_timer,
dpu_encoder_frame_done_timeout, 0);
- if (disp_info->intf_type == DRM_MODE_ENCODER_DSI)
+ if (disp_info->intf_type == INTF_DSI)
timer_setup(&dpu_enc->vsync_event_timer,
dpu_encoder_vsync_event_handler,
0);
- else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS)
+ else if (disp_info->intf_type == INTF_DP)
dpu_enc->wide_bus_en = msm_dp_wide_bus_available(
priv->dp[disp_info->h_tile_instance[0]]);
@@ -2428,44 +2442,14 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
DPU_DEBUG_ENC(dpu_enc, "created\n");
- return ret;
+ return &dpu_enc->base;
fail:
DPU_ERROR("failed to create encoder\n");
if (drm_enc)
dpu_encoder_destroy(drm_enc);
- return ret;
-
-
-}
-
-struct drm_encoder *dpu_encoder_init(struct drm_device *dev,
- int drm_enc_mode)
-{
- struct dpu_encoder_virt *dpu_enc = NULL;
- int rc = 0;
-
- dpu_enc = devm_kzalloc(dev->dev, sizeof(*dpu_enc), GFP_KERNEL);
- if (!dpu_enc)
- return ERR_PTR(-ENOMEM);
-
-
- rc = drm_encoder_init(dev, &dpu_enc->base, &dpu_encoder_funcs,
- drm_enc_mode, NULL);
- if (rc) {
- devm_kfree(dev->dev, dpu_enc);
- return ERR_PTR(rc);
- }
-
- drm_encoder_helper_add(&dpu_enc->base, &dpu_encoder_helper_funcs);
-
- spin_lock_init(&dpu_enc->enc_spinlock);
- dpu_enc->enabled = false;
- mutex_init(&dpu_enc->enc_lock);
- mutex_init(&dpu_enc->rc_lock);
-
- return &dpu_enc->base;
+ return ERR_PTR(ret);
}
int dpu_encoder_wait_for_event(struct drm_encoder *drm_enc,
@@ -2539,3 +2523,30 @@ unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc)
return dpu_enc->dsc_mask;
}
+
+void dpu_encoder_phys_init(struct dpu_encoder_phys *phys_enc,
+ struct dpu_enc_phys_init_params *p)
+{
+ int i;
+
+ phys_enc->hw_mdptop = p->dpu_kms->hw_mdp;
+ phys_enc->hw_intf = p->hw_intf;
+ phys_enc->hw_wb = p->hw_wb;
+ phys_enc->parent = p->parent;
+ phys_enc->dpu_kms = p->dpu_kms;
+ phys_enc->split_role = p->split_role;
+ phys_enc->enc_spinlock = p->enc_spinlock;
+ phys_enc->enable_state = DPU_ENC_DISABLED;
+
+ for (i = 0; i < ARRAY_SIZE(phys_enc->irq); i++)
+ phys_enc->irq[i] = -EINVAL;
+
+ atomic_set(&phys_enc->vblank_refcount, 0);
+ atomic_set(&phys_enc->pending_kickoff_cnt, 0);
+ atomic_set(&phys_enc->pending_ctlstart_cnt, 0);
+
+ atomic_set(&phys_enc->vsync_cnt, 0);
+ atomic_set(&phys_enc->underrun_cnt, 0);
+
+ init_waitqueue_head(&phys_enc->pending_kickoff_wq);
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 2c9ef8d1b877..90e1925d7770 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -21,7 +21,7 @@
/**
* struct msm_display_info - defines display properties
- * @intf_type: DRM_MODE_ENCODER_ type
+ * @intf_type: INTF_ type
* @num_of_h_tiles: Number of horizontal tiles in case of split interface
* @h_tile_instance: Controller instance used per tile. Number of elements is
* based on num_of_h_tiles
@@ -31,7 +31,7 @@
* @dsc: DSC configuration data for DSC-enabled displays
*/
struct msm_display_info {
- int intf_type;
+ enum dpu_intf_type intf_type;
uint32_t num_of_h_tiles;
uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY];
bool is_cmd_mode;
@@ -130,20 +130,12 @@ void dpu_encoder_virt_runtime_resume(struct drm_encoder *encoder);
/**
* dpu_encoder_init - initialize virtual encoder object
* @dev: Pointer to drm device structure
+ * @drm_enc_mode: corresponding DRM_MODE_ENCODER_* constant
* @disp_info: Pointer to display information structure
* Returns: Pointer to newly created drm encoder
*/
-struct drm_encoder *dpu_encoder_init(
- struct drm_device *dev,
- int drm_enc_mode);
-
-/**
- * dpu_encoder_setup - setup dpu_encoder for the display probed
- * @dev: Pointer to drm device structure
- * @enc: Pointer to the drm_encoder
- * @disp_info: Pointer to the display info
- */
-int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
+struct drm_encoder *dpu_encoder_init(struct drm_device *dev,
+ int drm_enc_mode,
struct msm_display_info *disp_info);
/**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 1d434b22180d..d48558ede488 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -63,7 +63,6 @@ struct dpu_encoder_phys;
/**
* struct dpu_encoder_phys_ops - Interface the physical encoders provide to
* the containing virtual encoder.
- * @late_register: DRM Call. Add Userspace interfaces, debugfs.
* @prepare_commit: MSM Atomic Call, start of atomic commit sequence
* @is_master: Whether this phys_enc is the current master
* encoder. Can be switched at enable time. Based
@@ -93,8 +92,6 @@ struct dpu_encoder_phys;
*/
struct dpu_encoder_phys_ops {
- int (*late_register)(struct dpu_encoder_phys *encoder,
- struct dentry *debugfs_root);
void (*prepare_commit)(struct dpu_encoder_phys *encoder);
bool (*is_master)(struct dpu_encoder_phys *encoder);
void (*atomic_mode_set)(struct dpu_encoder_phys *encoder,
@@ -129,10 +126,10 @@ struct dpu_encoder_phys_ops {
/**
* enum dpu_intr_idx - dpu encoder interrupt index
* @INTR_IDX_VSYNC: Vsync interrupt for video mode panel
- * @INTR_IDX_PINGPONG: Pingpong done unterrupt for cmd mode panel
- * @INTR_IDX_UNDERRUN: Underrun unterrupt for video and cmd mode panel
- * @INTR_IDX_RDPTR: Readpointer done unterrupt for cmd mode panel
- * @INTR_IDX_WB_DONE: Writeback fone interrupt for virtual connector
+ * @INTR_IDX_PINGPONG: Pingpong done interrupt for cmd mode panel
+ * @INTR_IDX_UNDERRUN: Underrun interrupt for video and cmd mode panel
+ * @INTR_IDX_RDPTR: Readpointer done interrupt for cmd mode panel
+ * @INTR_IDX_WB_DONE: Writeback done interrupt for virtual connector
*/
enum dpu_intr_idx {
INTR_IDX_VSYNC,
@@ -161,8 +158,6 @@ enum dpu_intr_idx {
* @enabled: Whether the encoder has enabled and running a mode
* @split_role: Role to play in a split-panel configuration
* @intf_mode: Interface mode
- * @intf_idx: Interface index on dpu hardware
- * @wb_idx: Writeback index on dpu hardware
* @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes
* @enable_state: Enable state tracking
* @vblank_refcount: Reference count of vblank request
@@ -176,6 +171,7 @@ enum dpu_intr_idx {
* pending.
* @pending_kickoff_wq: Wait queue for blocking until kickoff completes
* @irq: IRQ indices
+ * @has_intf_te: Interface TE configuration support
*/
struct dpu_encoder_phys {
struct drm_encoder *parent;
@@ -189,8 +185,6 @@ struct dpu_encoder_phys {
struct drm_display_mode cached_mode;
enum dpu_enc_split_role split_role;
enum dpu_intf_mode intf_mode;
- enum dpu_intf intf_idx;
- enum dpu_wb wb_idx;
spinlock_t *enc_spinlock;
enum dpu_enc_enable_state enable_state;
atomic_t vblank_refcount;
@@ -200,6 +194,7 @@ struct dpu_encoder_phys {
atomic_t pending_kickoff_cnt;
wait_queue_head_t pending_kickoff_wq;
int irq[INTR_IDX_MAX];
+ bool has_intf_te;
};
static inline int dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
@@ -256,16 +251,16 @@ struct dpu_encoder_phys_cmd {
* @parent: Pointer to the containing virtual encoder
* @parent_ops: Callbacks exposed by the parent to the phys_enc
* @split_role: Role to play in a split-panel configuration
- * @intf_idx: Interface index this phys_enc will control
- * @wb_idx: Writeback index this phys_enc will control
+ * @hw_intf: Hardware interface to the intf registers
+ * @hw_wb: Hardware interface to the wb registers
* @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes
*/
struct dpu_enc_phys_init_params {
struct dpu_kms *dpu_kms;
struct drm_encoder *parent;
enum dpu_enc_split_role split_role;
- enum dpu_intf intf_idx;
- enum dpu_wb wb_idx;
+ struct dpu_hw_intf *hw_intf;
+ struct dpu_hw_wb *hw_wb;
spinlock_t *enc_spinlock;
};
@@ -405,4 +400,7 @@ void dpu_encoder_frame_done_callback(
struct drm_encoder *drm_enc,
struct dpu_encoder_phys *ready_phys, u32 event);
+void dpu_encoder_phys_init(struct dpu_encoder_phys *phys,
+ struct dpu_enc_phys_init_params *p);
+
#endif /* __dpu_encoder_phys_H__ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index 74470d068622..b856c6286c85 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -16,12 +16,12 @@
#define DPU_DEBUG_CMDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \
(e) && (e)->base.parent ? \
(e)->base.parent->base.id : -1, \
- (e) ? (e)->base.intf_idx - INTF_0 : -1, ##__VA_ARGS__)
+ (e) ? (e)->base.hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__)
#define DPU_ERROR_CMDENC(e, fmt, ...) DPU_ERROR("enc%d intf%d " fmt, \
(e) && (e)->base.parent ? \
(e)->base.parent->base.id : -1, \
- (e) ? (e)->base.intf_idx - INTF_0 : -1, ##__VA_ARGS__)
+ (e) ? (e)->base.hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__)
#define to_dpu_encoder_phys_cmd(x) \
container_of(x, struct dpu_encoder_phys_cmd, base)
@@ -36,10 +36,6 @@
#define DEFAULT_TEARCHECK_SYNC_THRESH_START 4
#define DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE 4
-#define DPU_ENC_WR_PTR_START_TIMEOUT_US 20000
-
-#define DPU_ENC_MAX_POLL_TIMEOUT_US 2000
-
static void dpu_encoder_phys_cmd_enable_te(struct dpu_encoder_phys *phys_enc);
static bool dpu_encoder_phys_cmd_is_master(struct dpu_encoder_phys *phys_enc)
@@ -59,7 +55,7 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
if (!ctl->ops.setup_intf_cfg)
return;
- intf_cfg.intf = phys_enc->intf_idx;
+ intf_cfg.intf = phys_enc->hw_intf->idx;
intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
intf_cfg.stream_sel = cmd_enc->stream_sel;
intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
@@ -70,8 +66,10 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
if (test_bit(DPU_CTL_ACTIVE_CFG, &ctl->caps->features) && phys_enc->hw_intf->ops.bind_pingpong_blk)
phys_enc->hw_intf->ops.bind_pingpong_blk(
phys_enc->hw_intf,
- true,
phys_enc->hw_pp->idx);
+
+ if (intf_cfg.dsc != 0 && phys_enc->hw_intf->ops.enable_compression)
+ phys_enc->hw_intf->ops.enable_compression(phys_enc->hw_intf);
}
static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
@@ -101,13 +99,18 @@ static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
DPU_ATRACE_END("pp_done_irq");
}
-static void dpu_encoder_phys_cmd_pp_rd_ptr_irq(void *arg, int irq_idx)
+static void dpu_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx)
{
struct dpu_encoder_phys *phys_enc = arg;
struct dpu_encoder_phys_cmd *cmd_enc;
- if (!phys_enc->hw_pp)
- return;
+ if (phys_enc->has_intf_te) {
+ if (!phys_enc->hw_intf)
+ return;
+ } else {
+ if (!phys_enc->hw_pp)
+ return;
+ }
DPU_ATRACE_BEGIN("rd_ptr_irq");
cmd_enc = to_dpu_encoder_phys_cmd(phys_enc);
@@ -148,7 +151,10 @@ static void dpu_encoder_phys_cmd_atomic_mode_set(
phys_enc->irq[INTR_IDX_PINGPONG] = phys_enc->hw_pp->caps->intr_done;
- phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr;
+ if (phys_enc->has_intf_te)
+ phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_intf->cap->intr_tear_rd_ptr;
+ else
+ phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr;
phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun;
}
@@ -259,7 +265,7 @@ static int dpu_encoder_phys_cmd_control_vblank_irq(
if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
ret = dpu_core_irq_register_callback(phys_enc->dpu_kms,
phys_enc->irq[INTR_IDX_RDPTR],
- dpu_encoder_phys_cmd_pp_rd_ptr_irq,
+ dpu_encoder_phys_cmd_te_rd_ptr_irq,
phys_enc);
else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms,
@@ -320,23 +326,29 @@ static void dpu_encoder_phys_cmd_tearcheck_config(
struct dpu_hw_tear_check tc_cfg = { 0 };
struct drm_display_mode *mode;
bool tc_enable = true;
- u32 vsync_hz;
+ unsigned long vsync_hz;
struct dpu_kms *dpu_kms;
- if (!phys_enc->hw_pp) {
- DPU_ERROR("invalid encoder\n");
- return;
- }
- mode = &phys_enc->cached_mode;
+ if (phys_enc->has_intf_te) {
+ if (!phys_enc->hw_intf ||
+ !phys_enc->hw_intf->ops.enable_tearcheck) {
+ DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n");
+ return;
+ }
- DPU_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
+ DPU_DEBUG_CMDENC(cmd_enc, "");
+ } else {
+ if (!phys_enc->hw_pp ||
+ !phys_enc->hw_pp->ops.enable_tearcheck) {
+ DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n");
+ return;
+ }
- if (!phys_enc->hw_pp->ops.setup_tearcheck ||
- !phys_enc->hw_pp->ops.enable_tearcheck) {
- DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n");
- return;
+ DPU_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
}
+ mode = &phys_enc->cached_mode;
+
dpu_kms = phys_enc->dpu_kms;
/*
@@ -349,9 +361,8 @@ static void dpu_encoder_phys_cmd_tearcheck_config(
* frequency divided by the no. of rows (lines) in the LCDpanel.
*/
vsync_hz = dpu_kms_get_clk_rate(dpu_kms, "vsync");
- if (vsync_hz <= 0) {
- DPU_DEBUG_CMDENC(cmd_enc, "invalid - vsync_hz %u\n",
- vsync_hz);
+ if (!vsync_hz) {
+ DPU_DEBUG_CMDENC(cmd_enc, "invalid - no vsync clock\n");
return;
}
@@ -371,24 +382,24 @@ static void dpu_encoder_phys_cmd_tearcheck_config(
tc_cfg.rd_ptr_irq = mode->vdisplay + 1;
DPU_DEBUG_CMDENC(cmd_enc,
- "tc %d vsync_clk_speed_hz %u vtotal %u vrefresh %u\n",
- phys_enc->hw_pp->idx - PINGPONG_0, vsync_hz,
- mode->vtotal, drm_mode_vrefresh(mode));
+ "tc vsync_clk_speed_hz %lu vtotal %u vrefresh %u\n",
+ vsync_hz, mode->vtotal, drm_mode_vrefresh(mode));
DPU_DEBUG_CMDENC(cmd_enc,
- "tc %d enable %u start_pos %u rd_ptr_irq %u\n",
- phys_enc->hw_pp->idx - PINGPONG_0, tc_enable, tc_cfg.start_pos,
- tc_cfg.rd_ptr_irq);
+ "tc enable %u start_pos %u rd_ptr_irq %u\n",
+ tc_enable, tc_cfg.start_pos, tc_cfg.rd_ptr_irq);
DPU_DEBUG_CMDENC(cmd_enc,
- "tc %d hw_vsync_mode %u vsync_count %u vsync_init_val %u\n",
- phys_enc->hw_pp->idx - PINGPONG_0, tc_cfg.hw_vsync_mode,
- tc_cfg.vsync_count, tc_cfg.vsync_init_val);
+ "tc hw_vsync_mode %u vsync_count %u vsync_init_val %u\n",
+ tc_cfg.hw_vsync_mode, tc_cfg.vsync_count,
+ tc_cfg.vsync_init_val);
DPU_DEBUG_CMDENC(cmd_enc,
- "tc %d cfgheight %u thresh_start %u thresh_cont %u\n",
- phys_enc->hw_pp->idx - PINGPONG_0, tc_cfg.sync_cfg_height,
- tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue);
+ "tc cfgheight %u thresh_start %u thresh_cont %u\n",
+ tc_cfg.sync_cfg_height, tc_cfg.sync_threshold_start,
+ tc_cfg.sync_threshold_continue);
- phys_enc->hw_pp->ops.setup_tearcheck(phys_enc->hw_pp, &tc_cfg);
- phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, tc_enable);
+ if (phys_enc->has_intf_te)
+ phys_enc->hw_intf->ops.enable_tearcheck(phys_enc->hw_intf, &tc_cfg);
+ else
+ phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, &tc_cfg);
}
static void _dpu_encoder_phys_cmd_pingpong_config(
@@ -430,7 +441,7 @@ static void dpu_encoder_phys_cmd_enable_helper(
return;
}
- dpu_encoder_helper_split_config(phys_enc, phys_enc->intf_idx);
+ dpu_encoder_helper_split_config(phys_enc, phys_enc->hw_intf->idx);
_dpu_encoder_phys_cmd_pingpong_config(phys_enc);
@@ -438,7 +449,7 @@ static void dpu_encoder_phys_cmd_enable_helper(
return;
ctl = phys_enc->hw_ctl;
- ctl->ops.update_pending_flush_intf(ctl, phys_enc->intf_idx);
+ ctl->ops.update_pending_flush_intf(ctl, phys_enc->hw_intf->idx);
}
static void dpu_encoder_phys_cmd_enable(struct dpu_encoder_phys *phys_enc)
@@ -465,11 +476,19 @@ static void dpu_encoder_phys_cmd_enable(struct dpu_encoder_phys *phys_enc)
static void _dpu_encoder_phys_cmd_connect_te(
struct dpu_encoder_phys *phys_enc, bool enable)
{
- if (!phys_enc->hw_pp || !phys_enc->hw_pp->ops.connect_external_te)
- return;
+ if (phys_enc->has_intf_te) {
+ if (!phys_enc->hw_intf || !phys_enc->hw_intf->ops.connect_external_te)
+ return;
- trace_dpu_enc_phys_cmd_connect_te(DRMID(phys_enc->parent), enable);
- phys_enc->hw_pp->ops.connect_external_te(phys_enc->hw_pp, enable);
+ trace_dpu_enc_phys_cmd_connect_te(DRMID(phys_enc->parent), enable);
+ phys_enc->hw_intf->ops.connect_external_te(phys_enc->hw_intf, enable);
+ } else {
+ if (!phys_enc->hw_pp || !phys_enc->hw_pp->ops.connect_external_te)
+ return;
+
+ trace_dpu_enc_phys_cmd_connect_te(DRMID(phys_enc->parent), enable);
+ phys_enc->hw_pp->ops.connect_external_te(phys_enc->hw_pp, enable);
+ }
}
static void dpu_encoder_phys_cmd_prepare_idle_pc(
@@ -482,17 +501,21 @@ static int dpu_encoder_phys_cmd_get_line_count(
struct dpu_encoder_phys *phys_enc)
{
struct dpu_hw_pingpong *hw_pp;
-
- if (!phys_enc->hw_pp)
- return -EINVAL;
+ struct dpu_hw_intf *hw_intf;
if (!dpu_encoder_phys_cmd_is_master(phys_enc))
return -EINVAL;
+ if (phys_enc->has_intf_te) {
+ hw_intf = phys_enc->hw_intf;
+ if (!hw_intf || !hw_intf->ops.get_line_count)
+ return -EINVAL;
+ return hw_intf->ops.get_line_count(hw_intf);
+ }
+
hw_pp = phys_enc->hw_pp;
- if (!hw_pp->ops.get_line_count)
+ if (!hw_pp || !hw_pp->ops.get_line_count)
return -EINVAL;
-
return hw_pp->ops.get_line_count(hw_pp);
}
@@ -502,30 +525,39 @@ static void dpu_encoder_phys_cmd_disable(struct dpu_encoder_phys *phys_enc)
to_dpu_encoder_phys_cmd(phys_enc);
struct dpu_hw_ctl *ctl;
- if (!phys_enc->hw_pp) {
- DPU_ERROR("invalid encoder\n");
- return;
- }
- DRM_DEBUG_KMS("id:%u pp:%d state:%d\n", DRMID(phys_enc->parent),
- phys_enc->hw_pp->idx - PINGPONG_0,
- phys_enc->enable_state);
-
if (phys_enc->enable_state == DPU_ENC_DISABLED) {
DPU_ERROR_CMDENC(cmd_enc, "already disabled\n");
return;
}
- if (phys_enc->hw_pp->ops.enable_tearcheck)
- phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, false);
+ if (phys_enc->has_intf_te) {
+ DRM_DEBUG_KMS("id:%u intf:%d state:%d\n", DRMID(phys_enc->parent),
+ phys_enc->hw_intf->idx - INTF_0,
+ phys_enc->enable_state);
+
+ if (phys_enc->hw_intf->ops.disable_tearcheck)
+ phys_enc->hw_intf->ops.disable_tearcheck(phys_enc->hw_intf);
+ } else {
+ if (!phys_enc->hw_pp) {
+ DPU_ERROR("invalid encoder\n");
+ return;
+ }
+
+ DRM_DEBUG_KMS("id:%u pp:%d state:%d\n", DRMID(phys_enc->parent),
+ phys_enc->hw_pp->idx - PINGPONG_0,
+ phys_enc->enable_state);
+
+ if (phys_enc->hw_pp->ops.disable_tearcheck)
+ phys_enc->hw_pp->ops.disable_tearcheck(phys_enc->hw_pp);
+ }
if (phys_enc->hw_intf->ops.bind_pingpong_blk) {
phys_enc->hw_intf->ops.bind_pingpong_blk(
phys_enc->hw_intf,
- false,
- phys_enc->hw_pp->idx);
+ PINGPONG_NONE);
ctl = phys_enc->hw_ctl;
- ctl->ops.update_pending_flush_intf(ctl, phys_enc->intf_idx);
+ ctl->ops.update_pending_flush_intf(ctl, phys_enc->hw_intf->idx);
}
phys_enc->enable_state = DPU_ENC_DISABLED;
@@ -574,66 +606,31 @@ static void dpu_encoder_phys_cmd_prepare_for_kickoff(
atomic_read(&phys_enc->pending_kickoff_cnt));
}
-static bool dpu_encoder_phys_cmd_is_ongoing_pptx(
- struct dpu_encoder_phys *phys_enc)
-{
- struct dpu_hw_pp_vsync_info info;
-
- if (!phys_enc)
- return false;
-
- phys_enc->hw_pp->ops.get_vsync_info(phys_enc->hw_pp, &info);
- if (info.wr_ptr_line_count > 0 &&
- info.wr_ptr_line_count < phys_enc->cached_mode.vdisplay)
- return true;
-
- return false;
-}
-
static void dpu_encoder_phys_cmd_enable_te(struct dpu_encoder_phys *phys_enc)
{
- struct dpu_encoder_phys_cmd *cmd_enc =
- to_dpu_encoder_phys_cmd(phys_enc);
- int trial = 0;
-
if (!phys_enc)
return;
- if (!phys_enc->hw_pp)
- return;
if (!dpu_encoder_phys_cmd_is_master(phys_enc))
return;
- /* If autorefresh is already disabled, we have nothing to do */
- if (!phys_enc->hw_pp->ops.get_autorefresh(phys_enc->hw_pp, NULL))
- return;
-
- /*
- * If autorefresh is enabled, disable it and make sure it is safe to
- * proceed with current frame commit/push. Sequence fallowed is,
- * 1. Disable TE
- * 2. Disable autorefresh config
- * 4. Poll for frame transfer ongoing to be false
- * 5. Enable TE back
- */
- _dpu_encoder_phys_cmd_connect_te(phys_enc, false);
- phys_enc->hw_pp->ops.setup_autorefresh(phys_enc->hw_pp, 0, false);
-
- do {
- udelay(DPU_ENC_MAX_POLL_TIMEOUT_US);
- if ((trial * DPU_ENC_MAX_POLL_TIMEOUT_US)
- > (KICKOFF_TIMEOUT_MS * USEC_PER_MSEC)) {
- DPU_ERROR_CMDENC(cmd_enc,
- "disable autorefresh failed\n");
- break;
- }
-
- trial++;
- } while (dpu_encoder_phys_cmd_is_ongoing_pptx(phys_enc));
+ if (phys_enc->has_intf_te) {
+ if (!phys_enc->hw_intf->ops.disable_autorefresh)
+ return;
- _dpu_encoder_phys_cmd_connect_te(phys_enc, true);
-
- DPU_DEBUG_CMDENC(to_dpu_encoder_phys_cmd(phys_enc),
- "disabled autorefresh\n");
+ phys_enc->hw_intf->ops.disable_autorefresh(
+ phys_enc->hw_intf,
+ DRMID(phys_enc->parent),
+ phys_enc->cached_mode.vdisplay);
+ } else {
+ if (!phys_enc->hw_pp ||
+ !phys_enc->hw_pp->ops.disable_autorefresh)
+ return;
+
+ phys_enc->hw_pp->ops.disable_autorefresh(
+ phys_enc->hw_pp,
+ DRMID(phys_enc->parent),
+ phys_enc->cached_mode.vdisplay);
+ }
}
static int _dpu_encoder_phys_cmd_wait_for_ctl_start(
@@ -670,7 +667,7 @@ static int dpu_encoder_phys_cmd_wait_for_tx_complete(
if (rc) {
DRM_ERROR("failed wait_for_idle: id:%u ret:%d intf:%d\n",
DRMID(phys_enc->parent), rc,
- phys_enc->intf_idx - INTF_0);
+ phys_enc->hw_intf->idx - INTF_0);
}
return rc;
@@ -710,7 +707,7 @@ static int dpu_encoder_phys_cmd_wait_for_vblank(
rc = dpu_encoder_helper_wait_for_irq(phys_enc,
phys_enc->irq[INTR_IDX_RDPTR],
- dpu_encoder_phys_cmd_pp_rd_ptr_irq,
+ dpu_encoder_phys_cmd_te_rd_ptr_irq,
&wait_info);
return rc;
@@ -759,36 +756,26 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
{
struct dpu_encoder_phys *phys_enc = NULL;
struct dpu_encoder_phys_cmd *cmd_enc = NULL;
- int i, ret = 0;
- DPU_DEBUG("intf %d\n", p->intf_idx - INTF_0);
+ DPU_DEBUG("intf\n");
cmd_enc = kzalloc(sizeof(*cmd_enc), GFP_KERNEL);
if (!cmd_enc) {
- ret = -ENOMEM;
DPU_ERROR("failed to allocate\n");
- return ERR_PTR(ret);
+ return ERR_PTR(-ENOMEM);
}
phys_enc = &cmd_enc->base;
- phys_enc->hw_mdptop = p->dpu_kms->hw_mdp;
- phys_enc->intf_idx = p->intf_idx;
+
+ dpu_encoder_phys_init(phys_enc, p);
dpu_encoder_phys_cmd_init_ops(&phys_enc->ops);
- phys_enc->parent = p->parent;
- phys_enc->dpu_kms = p->dpu_kms;
- phys_enc->split_role = p->split_role;
phys_enc->intf_mode = INTF_MODE_CMD;
- phys_enc->enc_spinlock = p->enc_spinlock;
cmd_enc->stream_sel = 0;
- phys_enc->enable_state = DPU_ENC_DISABLED;
- for (i = 0; i < ARRAY_SIZE(phys_enc->irq); i++)
- phys_enc->irq[i] = -EINVAL;
- atomic_set(&phys_enc->vblank_refcount, 0);
- atomic_set(&phys_enc->pending_kickoff_cnt, 0);
- atomic_set(&phys_enc->pending_ctlstart_cnt, 0);
+ phys_enc->has_intf_te = test_bit(DPU_INTF_TE,
+ &phys_enc->hw_intf->cap->features);
+
atomic_set(&cmd_enc->pending_vblank_cnt, 0);
- init_waitqueue_head(&phys_enc->pending_kickoff_wq);
init_waitqueue_head(&cmd_enc->pending_vblank_wq);
DPU_DEBUG_CMDENC(cmd_enc, "created\n");
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index 3a374292f311..662d74ded1b9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -287,7 +287,6 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
if (phys_enc->hw_intf->ops.bind_pingpong_blk)
phys_enc->hw_intf->ops.bind_pingpong_blk(
phys_enc->hw_intf,
- true,
phys_enc->hw_pp->idx);
if (phys_enc->hw_pp->merge_3d)
@@ -699,7 +698,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
struct dpu_enc_phys_init_params *p)
{
struct dpu_encoder_phys *phys_enc = NULL;
- int i;
if (!p) {
DPU_ERROR("failed to create encoder due to invalid parameter\n");
@@ -712,26 +710,14 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
return ERR_PTR(-ENOMEM);
}
- phys_enc->hw_mdptop = p->dpu_kms->hw_mdp;
- phys_enc->intf_idx = p->intf_idx;
-
DPU_DEBUG_VIDENC(phys_enc, "\n");
+ dpu_encoder_phys_init(phys_enc, p);
+
dpu_encoder_phys_vid_init_ops(&phys_enc->ops);
- phys_enc->parent = p->parent;
- phys_enc->dpu_kms = p->dpu_kms;
- phys_enc->split_role = p->split_role;
phys_enc->intf_mode = INTF_MODE_VIDEO;
- phys_enc->enc_spinlock = p->enc_spinlock;
- for (i = 0; i < ARRAY_SIZE(phys_enc->irq); i++)
- phys_enc->irq[i] = -EINVAL;
-
- atomic_set(&phys_enc->vblank_refcount, 0);
- atomic_set(&phys_enc->pending_kickoff_cnt, 0);
- init_waitqueue_head(&phys_enc->pending_kickoff_wq);
- phys_enc->enable_state = DPU_ENC_DISABLED;
- DPU_DEBUG_VIDENC(phys_enc, "created intf idx:%d\n", p->intf_idx);
+ DPU_DEBUG_VIDENC(phys_enc, "created intf idx:%d\n", p->hw_intf->idx);
return phys_enc;
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index bac4aa807b4b..a466ff70a4d6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -102,7 +102,7 @@ static void dpu_encoder_phys_wb_set_qos_remap(
static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc)
{
struct dpu_hw_wb *hw_wb;
- struct dpu_hw_wb_qos_cfg qos_cfg;
+ struct dpu_hw_qos_cfg qos_cfg;
const struct dpu_mdss_cfg *catalog;
const struct dpu_qos_lut_tbl *qos_lut_tb;
@@ -115,7 +115,7 @@ static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc)
hw_wb = phys_enc->hw_wb;
- memset(&qos_cfg, 0, sizeof(struct dpu_hw_wb_qos_cfg));
+ memset(&qos_cfg, 0, sizeof(struct dpu_hw_qos_cfg));
qos_cfg.danger_safe_en = true;
qos_cfg.danger_lut =
catalog->perf->danger_lut_tbl[DPU_QOS_LUT_USAGE_NRT];
@@ -140,7 +140,6 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc);
struct dpu_hw_wb *hw_wb;
struct dpu_hw_wb_cfg *wb_cfg;
- struct dpu_hw_cdp_cfg cdp_cfg;
if (!phys_enc || !phys_enc->dpu_kms || !phys_enc->dpu_kms->catalog) {
DPU_ERROR("invalid encoder\n");
@@ -163,18 +162,10 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
hw_wb->ops.setup_outformat(hw_wb, wb_cfg);
if (hw_wb->ops.setup_cdp) {
- memset(&cdp_cfg, 0, sizeof(struct dpu_hw_cdp_cfg));
-
- cdp_cfg.enable = phys_enc->dpu_kms->catalog->perf->cdp_cfg
- [DPU_PERF_CDP_USAGE_NRT].wr_enable;
- cdp_cfg.ubwc_meta_enable =
- DPU_FORMAT_IS_UBWC(wb_cfg->dest.format);
- cdp_cfg.tile_amortize_enable =
- DPU_FORMAT_IS_UBWC(wb_cfg->dest.format) ||
- DPU_FORMAT_IS_TILE(wb_cfg->dest.format);
- cdp_cfg.preload_ahead = DPU_WB_CDP_PRELOAD_AHEAD_64;
-
- hw_wb->ops.setup_cdp(hw_wb, &cdp_cfg);
+ const struct dpu_perf_cfg *perf = phys_enc->dpu_kms->catalog->perf;
+
+ hw_wb->ops.setup_cdp(hw_wb, wb_cfg->dest.format,
+ perf->cdp_cfg[DPU_PERF_CDP_USAGE_NRT].wr_enable);
}
if (hw_wb->ops.setup_outaddress)
@@ -219,7 +210,7 @@ static void dpu_encoder_phys_wb_setup_cdp(struct dpu_encoder_phys *phys_enc)
/* setup which pp blk will connect to this wb */
if (hw_pp && phys_enc->hw_wb->ops.bind_pingpong_blk)
- phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb, true,
+ phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb,
phys_enc->hw_pp->idx);
phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg);
@@ -249,7 +240,7 @@ static int dpu_encoder_phys_wb_atomic_check(
const struct drm_display_mode *mode = &crtc_state->mode;
DPU_DEBUG("[atomic_check:%d, \"%s\",%d,%d]\n",
- phys_enc->wb_idx, mode->name, mode->hdisplay, mode->vdisplay);
+ phys_enc->hw_wb->idx, mode->name, mode->hdisplay, mode->vdisplay);
if (!conn_state || !conn_state->connector) {
DPU_ERROR("invalid connector state\n");
@@ -570,7 +561,7 @@ static void dpu_encoder_phys_wb_destroy(struct dpu_encoder_phys *phys_enc)
if (!phys_enc)
return;
- DPU_DEBUG("[wb:%d]\n", phys_enc->wb_idx - WB_0);
+ DPU_DEBUG("[wb:%d]\n", phys_enc->hw_wb->idx - WB_0);
kfree(phys_enc);
}
@@ -693,53 +684,32 @@ struct dpu_encoder_phys *dpu_encoder_phys_wb_init(
{
struct dpu_encoder_phys *phys_enc = NULL;
struct dpu_encoder_phys_wb *wb_enc = NULL;
- int ret = 0;
- int i;
DPU_DEBUG("\n");
if (!p || !p->parent) {
DPU_ERROR("invalid params\n");
- ret = -EINVAL;
- goto fail_alloc;
+ return ERR_PTR(-EINVAL);
}
wb_enc = kzalloc(sizeof(*wb_enc), GFP_KERNEL);
if (!wb_enc) {
DPU_ERROR("failed to allocate wb phys_enc enc\n");
- ret = -ENOMEM;
- goto fail_alloc;
+ return ERR_PTR(-ENOMEM);
}
phys_enc = &wb_enc->base;
- phys_enc->hw_mdptop = p->dpu_kms->hw_mdp;
- phys_enc->wb_idx = p->wb_idx;
+
+ dpu_encoder_phys_init(phys_enc, p);
dpu_encoder_phys_wb_init_ops(&phys_enc->ops);
- phys_enc->parent = p->parent;
- phys_enc->dpu_kms = p->dpu_kms;
- phys_enc->split_role = p->split_role;
phys_enc->intf_mode = INTF_MODE_WB_LINE;
- phys_enc->wb_idx = p->wb_idx;
- phys_enc->enc_spinlock = p->enc_spinlock;
atomic_set(&wb_enc->wbirq_refcount, 0);
- for (i = 0; i < ARRAY_SIZE(phys_enc->irq); i++)
- phys_enc->irq[i] = -EINVAL;
-
- atomic_set(&phys_enc->pending_kickoff_cnt, 0);
- atomic_set(&phys_enc->vblank_refcount, 0);
wb_enc->wb_done_timeout_cnt = 0;
- init_waitqueue_head(&phys_enc->pending_kickoff_wq);
- phys_enc->enable_state = DPU_ENC_DISABLED;
-
- DPU_DEBUG("Created dpu_encoder_phys for wb %d\n",
- phys_enc->wb_idx);
+ DPU_DEBUG("Created dpu_encoder_phys for wb %d\n", phys_enc->hw_wb->idx);
return phys_enc;
-
-fail_alloc:
- return ERR_PTR(ret);
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 5d994bce696f..0de507d4d7b7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
@@ -13,7 +13,7 @@
#include "dpu_kms.h"
#define VIG_BASE_MASK \
- (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\
+ (BIT(DPU_SSPP_QOS) |\
BIT(DPU_SSPP_CDP) |\
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_EXCL_RECT))
@@ -39,7 +39,7 @@
#define VIG_QCM2290_MASK (VIG_BASE_MASK | BIT(DPU_SSPP_QOS_8LVL))
#define DMA_MSM8998_MASK \
- (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\
+ (BIT(DPU_SSPP_QOS) |\
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT))
@@ -50,7 +50,7 @@
(VIG_SC7280_MASK | BIT(DPU_SSPP_SMART_DMA_V2))
#define DMA_SDM845_MASK \
- (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\
+ (BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT))
@@ -75,11 +75,15 @@
#define MIXER_QCM2290_MASK \
(BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA))
-#define PINGPONG_SDM845_MASK BIT(DPU_PINGPONG_DITHER)
+#define PINGPONG_SDM845_MASK \
+ (BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_TE) | BIT(DPU_PINGPONG_DSC))
-#define PINGPONG_SDM845_SPLIT_MASK \
+#define PINGPONG_SDM845_TE2_MASK \
(PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2))
+#define PINGPONG_SM8150_MASK \
+ (BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_DSC))
+
#define CTL_SC7280_MASK \
(BIT(DPU_CTL_ACTIVE_CFG) | \
BIT(DPU_CTL_FETCH_ACTIVE) | \
@@ -91,16 +95,17 @@
#define MERGE_3D_SM8150_MASK (0)
-#define DSPP_MSM8998_MASK BIT(DPU_DSPP_PCC) | BIT(DPU_DSPP_GC)
-
#define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC)
#define INTF_SDM845_MASK (0)
#define INTF_SC7180_MASK \
- (BIT(DPU_INTF_INPUT_CTRL) | BIT(DPU_INTF_TE) | BIT(DPU_INTF_STATUS_SUPPORTED))
+ (BIT(DPU_INTF_INPUT_CTRL) | \
+ BIT(DPU_INTF_TE) | \
+ BIT(DPU_INTF_STATUS_SUPPORTED) | \
+ BIT(DPU_DATA_HCTL_EN))
-#define INTF_SC7280_MASK INTF_SC7180_MASK | BIT(DPU_DATA_HCTL_EN)
+#define INTF_SC7280_MASK (INTF_SC7180_MASK | BIT(DPU_INTF_DATA_COMPRESS))
#define WB_SM8250_MASK (BIT(DPU_WB_LINE_MODE) | \
BIT(DPU_WB_UBWC) | \
@@ -252,8 +257,6 @@ static const uint32_t wb2_formats[] = {
.maxdwnscale = MAX_DOWNSCALE_RATIO, \
.maxupscale = MAX_UPSCALE_RATIO, \
.smart_dma_priority = sdma_pri, \
- .src_blk = {.name = STRCAT("sspp_src_", num), \
- .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \
.scaler_blk = {.name = STRCAT("sspp_scaler", num), \
.id = qseed_ver, \
.base = 0xa00, .len = 0xa0,}, \
@@ -272,8 +275,6 @@ static const uint32_t wb2_formats[] = {
.maxdwnscale = MAX_DOWNSCALE_RATIO, \
.maxupscale = MAX_UPSCALE_RATIO, \
.smart_dma_priority = sdma_pri, \
- .src_blk = {.name = STRCAT("sspp_src_", num), \
- .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \
.scaler_blk = {.name = STRCAT("sspp_scaler", num), \
.id = qseed_ver, \
.base = 0xa00, .len = 0xa0,}, \
@@ -292,8 +293,6 @@ static const uint32_t wb2_formats[] = {
.maxdwnscale = SSPP_UNITY_SCALE, \
.maxupscale = SSPP_UNITY_SCALE, \
.smart_dma_priority = sdma_pri, \
- .src_blk = {.name = STRCAT("sspp_src_", num), \
- .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \
.format_list = plane_formats, \
.num_formats = ARRAY_SIZE(plane_formats), \
.virt_format_list = plane_formats, \
@@ -375,8 +374,6 @@ static const struct dpu_sspp_sub_blks sm8550_dma_sblk_5 = _DMA_SBLK("13", 6);
.maxdwnscale = SSPP_UNITY_SCALE, \
.maxupscale = SSPP_UNITY_SCALE, \
.smart_dma_priority = sdma_pri, \
- .src_blk = {.name = STRCAT("sspp_src_", num), \
- .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \
.format_list = plane_formats_yuv, \
.num_formats = ARRAY_SIZE(plane_formats_yuv), \
.virt_format_list = plane_formats, \
@@ -449,13 +446,6 @@ static const struct dpu_lm_sub_blks qcm2290_lm_sblk = {
static const struct dpu_dspp_sub_blks msm8998_dspp_sblk = {
.pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
.len = 0x90, .version = 0x10007},
- .gc = { .id = DPU_DSPP_GC, .base = 0x17c0,
- .len = 0x90, .version = 0x10007},
-};
-
-static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = {
- .pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
- .len = 0x90, .version = 0x10000},
};
static const struct dpu_dspp_sub_blks sm8150_dspp_sblk = {
@@ -501,21 +491,11 @@ static const struct dpu_pingpong_sub_blks sc7280_pp_sblk = {
.intr_done = _done, \
.intr_rdptr = _rdptr, \
}
-#define PP_BLK_TE(_name, _id, _base, _merge_3d, _sblk, _done, _rdptr) \
- {\
- .name = _name, .id = _id, \
- .base = _base, .len = 0xd4, \
- .features = PINGPONG_SDM845_SPLIT_MASK, \
- .merge_3d = _merge_3d, \
- .sblk = &_sblk, \
- .intr_done = _done, \
- .intr_rdptr = _rdptr, \
- }
-#define PP_BLK(_name, _id, _base, _merge_3d, _sblk, _done, _rdptr) \
+#define PP_BLK(_name, _id, _base, _features, _merge_3d, _sblk, _done, _rdptr) \
{\
.name = _name, .id = _id, \
.base = _base, .len = 0xd4, \
- .features = PINGPONG_SDM845_MASK, \
+ .features = _features, \
.merge_3d = _merge_3d, \
.sblk = &_sblk, \
.intr_done = _done, \
@@ -528,7 +508,7 @@ static const struct dpu_pingpong_sub_blks sc7280_pp_sblk = {
#define MERGE_3D_BLK(_name, _id, _base) \
{\
.name = _name, .id = _id, \
- .base = _base, .len = 0x100, \
+ .base = _base, .len = 0x8, \
.features = MERGE_3D_SM8150_MASK, \
.sblk = NULL \
}
@@ -536,6 +516,16 @@ static const struct dpu_pingpong_sub_blks sc7280_pp_sblk = {
/*************************************************************
* DSC sub blocks config
*************************************************************/
+static const struct dpu_dsc_sub_blks dsc_sblk_0 = {
+ .enc = {.base = 0x100, .len = 0x100},
+ .ctl = {.base = 0xF00, .len = 0x10},
+};
+
+static const struct dpu_dsc_sub_blks dsc_sblk_1 = {
+ .enc = {.base = 0x200, .len = 0x100},
+ .ctl = {.base = 0xF80, .len = 0x10},
+};
+
#define DSC_BLK(_name, _id, _base, _features) \
{\
.name = _name, .id = _id, \
@@ -543,10 +533,32 @@ static const struct dpu_pingpong_sub_blks sc7280_pp_sblk = {
.features = _features, \
}
+#define DSC_BLK_1_2(_name, _id, _base, _len, _features, _sblk) \
+ {\
+ .name = _name, .id = _id, \
+ .base = _base, .len = _len, \
+ .features = BIT(DPU_DSC_HW_REV_1_2) | _features, \
+ .sblk = &_sblk, \
+ }
+
/*************************************************************
* INTF sub blocks config
*************************************************************/
-#define INTF_BLK(_name, _id, _base, _len, _type, _ctrl_id, _progfetch, _features, _reg, _underrun_bit, _vsync_bit) \
+#define INTF_BLK(_name, _id, _base, _len, _type, _ctrl_id, _progfetch, _features, _underrun, _vsync) \
+ {\
+ .name = _name, .id = _id, \
+ .base = _base, .len = _len, \
+ .features = _features, \
+ .type = _type, \
+ .controller_id = _ctrl_id, \
+ .prog_fetch_lines_worst_case = _progfetch, \
+ .intr_underrun = _underrun, \
+ .intr_vsync = _vsync, \
+ .intr_tear_rd_ptr = -1, \
+ }
+
+/* DSI Interface sub-block with TEAR registers (since DPU 5.0.0) */
+#define INTF_BLK_DSI_TE(_name, _id, _base, _len, _type, _ctrl_id, _progfetch, _features, _underrun, _vsync, _tear_rd_ptr) \
{\
.name = _name, .id = _id, \
.base = _base, .len = _len, \
@@ -554,8 +566,9 @@ static const struct dpu_pingpong_sub_blks sc7280_pp_sblk = {
.type = _type, \
.controller_id = _ctrl_id, \
.prog_fetch_lines_worst_case = _progfetch, \
- .intr_underrun = DPU_IRQ_IDX(_reg, _underrun_bit), \
- .intr_vsync = DPU_IRQ_IDX(_reg, _vsync_bit), \
+ .intr_underrun = _underrun, \
+ .intr_vsync = _vsync, \
+ .intr_tear_rd_ptr = _tear_rd_ptr, \
}
/*************************************************************
@@ -650,46 +663,6 @@ static const struct dpu_vbif_cfg sdm845_vbif[] = {
},
};
-static const struct dpu_reg_dma_cfg sc8280xp_regdma = {
- .base = 0x0,
- .version = 0x00020000,
- .trigger_sel_off = 0x119c,
- .xin_id = 7,
- .clk_ctrl = DPU_CLK_CTRL_REG_DMA,
-};
-
-static const struct dpu_reg_dma_cfg sdm845_regdma = {
- .base = 0x0, .version = 0x1, .trigger_sel_off = 0x119c
-};
-
-static const struct dpu_reg_dma_cfg sm8150_regdma = {
- .base = 0x0, .version = 0x00010001, .trigger_sel_off = 0x119c
-};
-
-static const struct dpu_reg_dma_cfg sm8250_regdma = {
- .base = 0x0,
- .version = 0x00010002,
- .trigger_sel_off = 0x119c,
- .xin_id = 7,
- .clk_ctrl = DPU_CLK_CTRL_REG_DMA,
-};
-
-static const struct dpu_reg_dma_cfg sm8350_regdma = {
- .base = 0x400,
- .version = 0x00020000,
- .trigger_sel_off = 0x119c,
- .xin_id = 7,
- .clk_ctrl = DPU_CLK_CTRL_REG_DMA,
-};
-
-static const struct dpu_reg_dma_cfg sm8450_regdma = {
- .base = 0x0,
- .version = 0x00020000,
- .trigger_sel_off = 0x119c,
- .xin_id = 7,
- .clk_ctrl = DPU_CLK_CTRL_REG_DMA,
-};
-
/*************************************************************
* PERF data config
*************************************************************/
@@ -734,6 +707,10 @@ static const struct dpu_qos_lut_entry sc7180_qos_linear[] = {
{.fl = 0, .lut = 0x0011222222335777},
};
+static const struct dpu_qos_lut_entry sm6350_qos_linear_macrotile[] = {
+ {.fl = 0, .lut = 0x0011223445566777 },
+};
+
static const struct dpu_qos_lut_entry sm8150_qos_linear[] = {
{.fl = 0, .lut = 0x0011222222223357 },
};
@@ -789,7 +766,9 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
#include "catalog/dpu_6_0_sm8250.h"
#include "catalog/dpu_6_2_sc7180.h"
#include "catalog/dpu_6_3_sm6115.h"
+#include "catalog/dpu_6_4_sm6350.h"
#include "catalog/dpu_6_5_qcm2290.h"
+#include "catalog/dpu_6_9_sm6375.h"
#include "catalog/dpu_7_0_sm8350.h"
#include "catalog/dpu_7_2_sc7280.h"
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 71584cd56fd7..b860784ade72 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved.
*/
@@ -48,6 +48,8 @@ enum {
* @DPU_MDP_UBWC_1_5, Universal Bandwidth compression version 1.5
* @DPU_MDP_PERIPH_0_REMOVED Indicates that access to periph top0 block results
* in a failure
+ * @DPU_MDP_VSYNC_SEL Enables vsync source selection via MDP_VSYNC_SEL register
+ * (moved into INTF block since DPU 5.0.0)
* @DPU_MDP_MAX Maximum value
*/
@@ -59,12 +61,12 @@ enum {
DPU_MDP_UBWC_1_5,
DPU_MDP_AUDIO_SELECT,
DPU_MDP_PERIPH_0_REMOVED,
+ DPU_MDP_VSYNC_SEL,
DPU_MDP_MAX
};
/**
* SSPP sub-blocks/features
- * @DPU_SSPP_SRC Src and fetch part of the pipes,
* @DPU_SSPP_SCALER_QSEED2, QSEED2 algorithm support
* @DPU_SSPP_SCALER_QSEED3, QSEED3 alogorithm support
* @DPU_SSPP_SCALER_QSEED3LITE, QSEED3 Lite alogorithm support
@@ -85,8 +87,7 @@ enum {
* @DPU_SSPP_MAX maximum value
*/
enum {
- DPU_SSPP_SRC = 0x1,
- DPU_SSPP_SCALER_QSEED2,
+ DPU_SSPP_SCALER_QSEED2 = 0x1,
DPU_SSPP_SCALER_QSEED3,
DPU_SSPP_SCALER_QSEED3LITE,
DPU_SSPP_SCALER_QSEED4,
@@ -127,13 +128,9 @@ enum {
/**
* DSPP sub-blocks
* @DPU_DSPP_PCC Panel color correction block
- * @DPU_DSPP_GC Gamma correction block
- * @DPU_DSPP_IGC Inverse gamma correction block
*/
enum {
DPU_DSPP_PCC = 0x1,
- DPU_DSPP_GC,
- DPU_DSPP_IGC,
DPU_DSPP_MAX
};
@@ -143,7 +140,8 @@ enum {
* @DPU_PINGPONG_TE2 Additional tear check block for split pipes
* @DPU_PINGPONG_SPLIT PP block supports split fifo
* @DPU_PINGPONG_SLAVE PP block is a suitable slave for split fifo
- * @DPU_PINGPONG_DITHER, Dither blocks
+ * @DPU_PINGPONG_DITHER Dither blocks
+ * @DPU_PINGPONG_DSC PP block supports DSC
* @DPU_PINGPONG_MAX
*/
enum {
@@ -152,6 +150,7 @@ enum {
DPU_PINGPONG_SPLIT,
DPU_PINGPONG_SLAVE,
DPU_PINGPONG_DITHER,
+ DPU_PINGPONG_DSC,
DPU_PINGPONG_MAX
};
@@ -182,6 +181,7 @@ enum {
* @DPU_DATA_HCTL_EN Allows data to be transferred at different rate
* than video timing
* @DPU_INTF_STATUS_SUPPORTED INTF block has INTF_STATUS register
+ * @DPU_INTF_DATA_COMPRESS INTF block has DATA_COMPRESS register
* @DPU_INTF_MAX
*/
enum {
@@ -189,6 +189,7 @@ enum {
DPU_INTF_TE,
DPU_DATA_HCTL_EN,
DPU_INTF_STATUS_SUPPORTED,
+ DPU_INTF_DATA_COMPRESS,
DPU_INTF_MAX
};
@@ -241,12 +242,18 @@ enum {
};
/**
- * DSC features
+ * DSC sub-blocks/features
* @DPU_DSC_OUTPUT_CTRL Configure which PINGPONG block gets
* the pixel output from this DSC.
+ * @DPU_DSC_HW_REV_1_2 DSC block supports DSC 1.1 and 1.2
+ * @DPU_DSC_NATIVE_42x_EN Supports NATIVE_422_EN and NATIVE_420_EN encoding
+ * @DPU_DSC_MAX
*/
enum {
DPU_DSC_OUTPUT_CTRL = 0x1,
+ DPU_DSC_HW_REV_1_2,
+ DPU_DSC_NATIVE_42x_EN,
+ DPU_DSC_MAX
};
/**
@@ -279,14 +286,6 @@ enum {
u32 len
/**
- * struct dpu_src_blk: SSPP part of the source pipes
- * @info: HW register and features supported by this sub-blk
- */
-struct dpu_src_blk {
- DPU_HW_SUBBLK_INFO;
-};
-
-/**
* struct dpu_scaler_blk: Scaler information
* @info: HW register and features supported by this sub-blk
* @version: qseed block revision
@@ -311,6 +310,14 @@ struct dpu_pp_blk {
};
/**
+ * struct dpu_dsc_blk - DSC Encoder sub-blk information
+ * @info: HW register and features supported by this sub-blk
+ */
+struct dpu_dsc_blk {
+ DPU_HW_SUBBLK_INFO;
+};
+
+/**
* enum dpu_qos_lut_usage - define QoS LUT use cases
*/
enum dpu_qos_lut_usage {
@@ -385,20 +392,13 @@ struct dpu_caps {
/**
* struct dpu_sspp_sub_blks : SSPP sub-blocks
* common: Pointer to common configurations shared by sub blocks
- * @creq_vblank: creq priority during vertical blanking
- * @danger_vblank: danger priority during vertical blanking
* @maxdwnscale: max downscale ratio supported(without DECIMATION)
* @maxupscale: maxupscale ratio supported
* @smart_dma_priority: hw priority of rect1 of multirect pipe
* @max_per_pipe_bw: maximum allowable bandwidth of this pipe in kBps
* @qseed_ver: qseed version
- * @src_blk:
* @scaler_blk:
* @csc_blk:
- * @hsic:
- * @memcolor:
- * @pcc_blk:
- * @igc_blk:
* @format_list: Pointer to list of supported formats
* @num_formats: Number of supported formats
* @virt_format_list: Pointer to list of supported formats for virtual planes
@@ -406,20 +406,13 @@ struct dpu_caps {
* @dpu_rotation_cfg: inline rotation configuration
*/
struct dpu_sspp_sub_blks {
- u32 creq_vblank;
- u32 danger_vblank;
u32 maxdwnscale;
u32 maxupscale;
u32 smart_dma_priority;
u32 max_per_pipe_bw;
u32 qseed_ver;
- struct dpu_src_blk src_blk;
struct dpu_scaler_blk scaler_blk;
struct dpu_pp_blk csc_blk;
- struct dpu_pp_blk hsic_blk;
- struct dpu_pp_blk memcolor_blk;
- struct dpu_pp_blk pcc_blk;
- struct dpu_pp_blk igc_blk;
const u32 *format_list;
u32 num_formats;
@@ -433,22 +426,18 @@ struct dpu_sspp_sub_blks {
* @maxwidth: Max pixel width supported by this mixer
* @maxblendstages: Max number of blend-stages supported
* @blendstage_base: Blend-stage register base offset
- * @gc: gamma correction block
*/
struct dpu_lm_sub_blks {
u32 maxwidth;
u32 maxblendstages;
u32 blendstage_base[MAX_BLOCKS];
- struct dpu_pp_blk gc;
};
/**
* struct dpu_dspp_sub_blks: Information of DSPP block
- * @gc : gamma correction block
* @pcc: pixel color correction block
*/
struct dpu_dspp_sub_blks {
- struct dpu_pp_blk gc;
struct dpu_pp_blk pcc;
};
@@ -459,6 +448,16 @@ struct dpu_pingpong_sub_blks {
};
/**
+ * struct dpu_dsc_sub_blks - DSC sub-blks
+ * @enc: DSC encoder sub-block
+ * @ctl: DSC controller sub-block
+ */
+struct dpu_dsc_sub_blks {
+ struct dpu_dsc_blk enc;
+ struct dpu_dsc_blk ctl;
+};
+
+/**
* dpu_clk_ctrl_type - Defines top level clock control signals
*/
enum dpu_clk_ctrl_type {
@@ -554,7 +553,7 @@ struct dpu_sspp_cfg {
* @base register offset of this block
* @features bit mask identifying sub-blocks/features
* @sblk: LM Sub-blocks information
- * @pingpong: ID of connected PingPong, PINGPONG_MAX if unsupported
+ * @pingpong: ID of connected PingPong, PINGPONG_NONE if unsupported
* @lm_pair_mask: Bitmask of LMs that can be controlled by same CTL
*/
struct dpu_lm_cfg {
@@ -612,10 +611,13 @@ struct dpu_merge_3d_cfg {
* struct dpu_dsc_cfg - information of DSC blocks
* @id enum identifying this block
* @base register offset of this block
+ * @len: length of hardware block
* @features bit mask identifying sub-blocks/features
+ * @sblk: sub-blocks information
*/
struct dpu_dsc_cfg {
DPU_HW_BLK_INFO;
+ const struct dpu_dsc_sub_blks *sblk;
};
/**
@@ -628,6 +630,7 @@ struct dpu_dsc_cfg {
* @prog_fetch_lines_worst_case Worst case latency num lines needed to prefetch
* @intr_underrun: index for INTF underrun interrupt
* @intr_vsync: index for INTF VSYNC interrupt
+ * @intr_tear_rd_ptr: Index for INTF TEAR_RD_PTR interrupt
*/
struct dpu_intf_cfg {
DPU_HW_BLK_INFO;
@@ -636,6 +639,7 @@ struct dpu_intf_cfg {
u32 prog_fetch_lines_worst_case;
s32 intr_underrun;
s32 intr_vsync;
+ s32 intr_tear_rd_ptr;
};
/**
@@ -720,21 +724,6 @@ struct dpu_vbif_cfg {
u32 memtype_count;
u32 memtype[MAX_XIN_COUNT];
};
-/**
- * struct dpu_reg_dma_cfg - information of lut dma blocks
- * @id enum identifying this block
- * @base register offset of this block
- * @features bit mask identifying sub-blocks/features
- * @version version of lutdma hw block
- * @trigger_sel_off offset to trigger select registers of lutdma
- */
-struct dpu_reg_dma_cfg {
- DPU_HW_BLK_INFO;
- u32 version;
- u32 trigger_sel_off;
- u32 xin_id;
- enum dpu_clk_ctrl_type clk_ctrl;
-};
/**
* Define CDP use cases
@@ -850,9 +839,6 @@ struct dpu_mdss_cfg {
u32 wb_count;
const struct dpu_wb_cfg *wb;
- u32 reg_dma_count;
- const struct dpu_reg_dma_cfg *dma_cfg;
-
u32 ad_count;
u32 dspp_count;
@@ -875,7 +861,9 @@ extern const struct dpu_mdss_cfg dpu_sc8180x_cfg;
extern const struct dpu_mdss_cfg dpu_sm8250_cfg;
extern const struct dpu_mdss_cfg dpu_sc7180_cfg;
extern const struct dpu_mdss_cfg dpu_sm6115_cfg;
+extern const struct dpu_mdss_cfg dpu_sm6350_cfg;
extern const struct dpu_mdss_cfg dpu_qcm2290_cfg;
+extern const struct dpu_mdss_cfg dpu_sm6375_cfg;
extern const struct dpu_mdss_cfg dpu_sm8350_cfg;
extern const struct dpu_mdss_cfg dpu_sc7280_cfg;
extern const struct dpu_mdss_cfg dpu_sc8280xp_cfg;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index bbdc95ce374a..c278fb9d2b5b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -53,23 +53,6 @@ static const u32 fetch_tbl[SSPP_MAX] = {CTL_INVALID_BIT, 16, 17, 18, 19,
CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, 0,
1, 2, 3, CTL_INVALID_BIT, CTL_INVALID_BIT};
-static const struct dpu_ctl_cfg *_ctl_offset(enum dpu_ctl ctl,
- const struct dpu_mdss_cfg *m,
- void __iomem *addr,
- struct dpu_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->ctl_count; i++) {
- if (ctl == m->ctl[i].id) {
- b->blk_addr = addr + m->ctl[i].base;
- b->log_mask = DPU_DBG_MASK_CTL;
- return &m->ctl[i];
- }
- }
- return ERR_PTR(-ENOMEM);
-}
-
static int _mixer_stages(const struct dpu_lm_cfg *mixer, int count,
enum dpu_lm lm)
{
@@ -117,6 +100,10 @@ static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)
trace_dpu_hw_ctl_clear_pending_flush(ctx->pending_flush_mask,
dpu_hw_ctl_get_flush_register(ctx));
ctx->pending_flush_mask = 0x0;
+ ctx->pending_intf_flush_mask = 0;
+ ctx->pending_wb_flush_mask = 0;
+ ctx->pending_merge_3d_flush_mask = 0;
+ ctx->pending_dsc_flush_mask = 0;
memset(ctx->pending_dspp_flush_mask, 0,
sizeof(ctx->pending_dspp_flush_mask));
@@ -156,6 +143,11 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
CTL_DSPP_n_FLUSH(dspp - DSPP_0),
ctx->pending_dspp_flush_mask[dspp - DSPP_0]);
}
+
+ if (ctx->pending_flush_mask & BIT(DSC_IDX))
+ DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
+ ctx->pending_dsc_flush_mask);
+
DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
}
@@ -302,6 +294,13 @@ static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct dpu_hw_ctl *ctx,
ctx->pending_flush_mask |= BIT(MERGE_3D_IDX);
}
+static void dpu_hw_ctl_update_pending_flush_dsc_v1(struct dpu_hw_ctl *ctx,
+ enum dpu_dsc dsc_num)
+{
+ ctx->pending_dsc_flush_mask |= BIT(dsc_num - DSC_0);
+ ctx->pending_flush_mask |= BIT(DSC_IDX);
+}
+
static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,
enum dpu_dspp dspp, u32 dspp_sub_blk)
{
@@ -330,15 +329,9 @@ static void dpu_hw_ctl_update_pending_flush_dspp_sub_blocks(
return;
switch (dspp_sub_blk) {
- case DPU_DSPP_IGC:
- ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(2);
- break;
case DPU_DSPP_PCC:
ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(4);
break;
- case DPU_DSPP_GC:
- ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(5);
- break;
default:
return;
}
@@ -519,9 +512,6 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
if ((test_bit(DPU_CTL_VM_CFG, &ctx->caps->features)))
mode_sel = CTL_DEFAULT_GROUP_ID << 28;
- if (cfg->dsc)
- DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, cfg->dsc);
-
if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD)
mode_sel |= BIT(17);
@@ -541,10 +531,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
if (cfg->merge_3d)
DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
BIT(cfg->merge_3d - MERGE_3D_0));
- if (cfg->dsc) {
- DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, DSC_IDX);
+
+ if (cfg->dsc)
DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
- }
}
static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
@@ -587,6 +576,7 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
u32 intf_active = 0;
u32 wb_active = 0;
u32 merge3d_active = 0;
+ u32 dsc_active;
/*
* This API resets each portion of the CTL path namely,
@@ -616,6 +606,12 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
wb_active &= ~BIT(cfg->wb - WB_0);
DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
}
+
+ if (cfg->dsc) {
+ dsc_active = DPU_REG_READ(c, CTL_DSC_ACTIVE);
+ dsc_active &= ~cfg->dsc;
+ DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);
+ }
}
static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx,
@@ -647,6 +643,8 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->update_pending_flush_merge_3d =
dpu_hw_ctl_update_pending_flush_merge_3d_v1;
ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;
+ ops->update_pending_flush_dsc =
+ dpu_hw_ctl_update_pending_flush_dsc_v1;
} else {
ops->trigger_flush = dpu_hw_ctl_trigger_flush;
ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg;
@@ -676,29 +674,25 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active;
};
-struct dpu_hw_ctl *dpu_hw_ctl_init(enum dpu_ctl idx,
+struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg,
void __iomem *addr,
- const struct dpu_mdss_cfg *m)
+ u32 mixer_count,
+ const struct dpu_lm_cfg *mixer)
{
struct dpu_hw_ctl *c;
- const struct dpu_ctl_cfg *cfg;
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
- cfg = _ctl_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- pr_err("failed to create dpu_hw_ctl %d\n", idx);
- return ERR_PTR(-EINVAL);
- }
+ c->hw.blk_addr = addr + cfg->base;
+ c->hw.log_mask = DPU_DBG_MASK_CTL;
c->caps = cfg;
_setup_ctl_ops(&c->ops, c->caps->features);
- c->idx = idx;
- c->mixer_count = m->mixer_count;
- c->mixer_hw_caps = m->mixer;
+ c->idx = cfg->id;
+ c->mixer_count = mixer_count;
+ c->mixer_hw_caps = mixer;
return c;
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index 78611a831697..1c242298ff2e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -158,6 +158,15 @@ struct dpu_hw_ctl_ops {
enum dpu_dspp blk, u32 dspp_sub_blk);
/**
+ * OR in the given flushbits to the cached pending_(dsc_)flush_mask
+ * No effect on hardware
+ * @ctx: ctl path ctx pointer
+ * @blk: interface block index
+ */
+ void (*update_pending_flush_dsc)(struct dpu_hw_ctl *ctx,
+ enum dpu_dsc blk);
+
+ /**
* Write the value of the pending_flush_mask to hardware
* @ctx : ctl path ctx pointer
*/
@@ -229,6 +238,7 @@ struct dpu_hw_ctl_ops {
* @pending_flush_mask: storage for pending ctl_flush managed via ops
* @pending_intf_flush_mask: pending INTF flush
* @pending_wb_flush_mask: pending WB flush
+ * @pending_dsc_flush_mask: pending DSC flush
* @ops: operation list
*/
struct dpu_hw_ctl {
@@ -245,6 +255,7 @@ struct dpu_hw_ctl {
u32 pending_wb_flush_mask;
u32 pending_merge_3d_flush_mask;
u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
+ u32 pending_dsc_flush_mask;
/* ops */
struct dpu_hw_ctl_ops ops;
@@ -261,15 +272,17 @@ static inline struct dpu_hw_ctl *to_dpu_hw_ctl(struct dpu_hw_blk *hw)
}
/**
- * dpu_hw_ctl_init(): Initializes the ctl_path hw driver object.
- * should be called before accessing every ctl path registers.
- * @idx: ctl_path index for which driver object is required
+ * dpu_hw_ctl_init() - Initializes the ctl_path hw driver object.
+ * Should be called before accessing any ctl_path register.
+ * @cfg: ctl_path catalog entry for which driver object is required
* @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
+ * @mixer_count: Number of mixers in @mixer
+ * @mixer: Pointer to an array of Layer Mixers defined in the catalog
*/
-struct dpu_hw_ctl *dpu_hw_ctl_init(enum dpu_ctl idx,
+struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg,
void __iomem *addr,
- const struct dpu_mdss_cfg *m);
+ u32 mixer_count,
+ const struct dpu_lm_cfg *mixer);
/**
* dpu_hw_ctl_destroy(): Destroys ctl driver context
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
index 4e1396575e6a..509dbaa51d87 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -3,6 +3,8 @@
* Copyright (c) 2020-2022, Linaro Limited
*/
+#include <drm/display/drm_dsc_helper.h>
+
#include "dpu_kms.h"
#include "dpu_hw_catalog.h"
#include "dpu_hwio.h"
@@ -54,9 +56,10 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
if (is_cmd_mode)
initial_lines += 1;
- slice_last_group_size = 3 - (dsc->slice_width % 3);
+ slice_last_group_size = (dsc->slice_width + 2) % 3;
+
data = (initial_lines << 20);
- data |= ((slice_last_group_size - 1) << 18);
+ data |= (slice_last_group_size << 18);
/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
data |= (dsc->bits_per_pixel << 8);
data |= (dsc->block_pred_enable << 7);
@@ -102,7 +105,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
data |= dsc->final_offset;
DPU_REG_WRITE(c, DSC_DSC_OFFSET, data);
- det_thresh_flatness = 7 + 2 * (dsc->bits_per_component - 8);
+ det_thresh_flatness = drm_dsc_flatness_det_thresh(dsc);
data = det_thresh_flatness << 10;
data |= dsc->flatness_max_qp << 5;
data |= dsc->flatness_min_qp;
@@ -154,7 +157,6 @@ static void dpu_hw_dsc_config_thresh(struct dpu_hw_dsc *hw_dsc,
static void dpu_hw_dsc_bind_pingpong_blk(
struct dpu_hw_dsc *hw_dsc,
- bool enable,
const enum dpu_pingpong pp)
{
struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
@@ -163,36 +165,19 @@ static void dpu_hw_dsc_bind_pingpong_blk(
dsc_ctl_offset = DSC_CTL(hw_dsc->idx);
- if (enable)
+ if (pp)
mux_cfg = (pp - PINGPONG_0) & 0x7;
- DRM_DEBUG_KMS("%s dsc:%d %s pp:%d\n",
- enable ? "Binding" : "Unbinding",
- hw_dsc->idx - DSC_0,
- enable ? "to" : "from",
- pp - PINGPONG_0);
+ if (pp)
+ DRM_DEBUG_KMS("Binding dsc:%d to pp:%d\n",
+ hw_dsc->idx - DSC_0, pp - PINGPONG_0);
+ else
+ DRM_DEBUG_KMS("Unbinding dsc:%d from any pp\n",
+ hw_dsc->idx - DSC_0);
DPU_REG_WRITE(c, dsc_ctl_offset, mux_cfg);
}
-static const struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc,
- const struct dpu_mdss_cfg *m,
- void __iomem *addr,
- struct dpu_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->dsc_count; i++) {
- if (dsc == m->dsc[i].id) {
- b->blk_addr = addr + m->dsc[i].base;
- b->log_mask = DPU_DBG_MASK_DSC;
- return &m->dsc[i];
- }
- }
-
- return NULL;
-}
-
static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
unsigned long cap)
{
@@ -203,23 +188,19 @@ static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk;
};
-struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
- const struct dpu_mdss_cfg *m)
+struct dpu_hw_dsc *dpu_hw_dsc_init(const struct dpu_dsc_cfg *cfg,
+ void __iomem *addr)
{
struct dpu_hw_dsc *c;
- const struct dpu_dsc_cfg *cfg;
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
- cfg = _dsc_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
+ c->hw.blk_addr = addr + cfg->base;
+ c->hw.log_mask = DPU_DBG_MASK_DSC;
- c->idx = idx;
+ c->idx = cfg->id;
c->caps = cfg;
_setup_dsc_ops(&c->ops, c->caps->features);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
index ae9b5db53d7f..d5b597ab8c5c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
@@ -1,5 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2020-2022, Linaro Limited */
+/*
+ * Copyright (c) 2020-2022, Linaro Limited
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved
+ */
#ifndef _DPU_HW_DSC_H
#define _DPU_HW_DSC_H
@@ -44,7 +47,6 @@ struct dpu_hw_dsc_ops {
struct drm_dsc_config *dsc);
void (*dsc_bind_pingpong_blk)(struct dpu_hw_dsc *hw_dsc,
- bool enable,
enum dpu_pingpong pp);
};
@@ -61,14 +63,22 @@ struct dpu_hw_dsc {
};
/**
- * dpu_hw_dsc_init - initializes the dsc block for the passed dsc idx.
- * @idx: DSC index for which driver object is required
+ * dpu_hw_dsc_init() - Initializes the DSC hw driver object.
+ * @cfg: DSC catalog entry for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * Return: Error code or allocated dpu_hw_dsc context
+ */
+struct dpu_hw_dsc *dpu_hw_dsc_init(const struct dpu_dsc_cfg *cfg,
+ void __iomem *addr);
+
+/**
+ * dpu_hw_dsc_init_1_2() - initializes the v1.2 DSC hw driver object
+ * @cfg: DSC catalog entry for which driver object is required
* @addr: Mapped register io address of MDP
- * @m: Pointer to mdss catalog data
* Returns: Error code or allocated dpu_hw_dsc context
*/
-struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
- const struct dpu_mdss_cfg *m);
+struct dpu_hw_dsc *dpu_hw_dsc_init_1_2(const struct dpu_dsc_cfg *cfg,
+ void __iomem *addr);
/**
* dpu_hw_dsc_destroy - destroys dsc driver context
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c
new file mode 100644
index 000000000000..24fe1d98eb86
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c
@@ -0,0 +1,387 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved
+ */
+
+#include <drm/display/drm_dsc_helper.h>
+
+#include "dpu_kms.h"
+#include "dpu_hw_catalog.h"
+#include "dpu_hwio.h"
+#include "dpu_hw_mdss.h"
+#include "dpu_hw_dsc.h"
+
+#define DSC_CMN_MAIN_CNF 0x00
+
+/* DPU_DSC_ENC register offsets */
+#define ENC_DF_CTRL 0x00
+#define ENC_GENERAL_STATUS 0x04
+#define ENC_HSLICE_STATUS 0x08
+#define ENC_OUT_STATUS 0x0C
+#define ENC_INT_STAT 0x10
+#define ENC_INT_CLR 0x14
+#define ENC_INT_MASK 0x18
+#define DSC_MAIN_CONF 0x30
+#define DSC_PICTURE_SIZE 0x34
+#define DSC_SLICE_SIZE 0x38
+#define DSC_MISC_SIZE 0x3C
+#define DSC_HRD_DELAYS 0x40
+#define DSC_RC_SCALE 0x44
+#define DSC_RC_SCALE_INC_DEC 0x48
+#define DSC_RC_OFFSETS_1 0x4C
+#define DSC_RC_OFFSETS_2 0x50
+#define DSC_RC_OFFSETS_3 0x54
+#define DSC_RC_OFFSETS_4 0x58
+#define DSC_FLATNESS_QP 0x5C
+#define DSC_RC_MODEL_SIZE 0x60
+#define DSC_RC_CONFIG 0x64
+#define DSC_RC_BUF_THRESH_0 0x68
+#define DSC_RC_BUF_THRESH_1 0x6C
+#define DSC_RC_BUF_THRESH_2 0x70
+#define DSC_RC_BUF_THRESH_3 0x74
+#define DSC_RC_MIN_QP_0 0x78
+#define DSC_RC_MIN_QP_1 0x7C
+#define DSC_RC_MIN_QP_2 0x80
+#define DSC_RC_MAX_QP_0 0x84
+#define DSC_RC_MAX_QP_1 0x88
+#define DSC_RC_MAX_QP_2 0x8C
+#define DSC_RC_RANGE_BPG_OFFSETS_0 0x90
+#define DSC_RC_RANGE_BPG_OFFSETS_1 0x94
+#define DSC_RC_RANGE_BPG_OFFSETS_2 0x98
+
+/* DPU_DSC_CTL register offsets */
+#define DSC_CTL 0x00
+#define DSC_CFG 0x04
+#define DSC_DATA_IN_SWAP 0x08
+#define DSC_CLK_CTRL 0x0C
+
+static int _dsc_calc_output_buf_max_addr(struct dpu_hw_dsc *hw_dsc, int num_softslice)
+{
+ int max_addr = 2400 / num_softslice;
+
+ if (hw_dsc->caps->features & BIT(DPU_DSC_NATIVE_42x_EN))
+ max_addr /= 2;
+
+ return max_addr - 1;
+};
+
+static void dpu_hw_dsc_disable_1_2(struct dpu_hw_dsc *hw_dsc)
+{
+ struct dpu_hw_blk_reg_map *hw;
+ const struct dpu_dsc_sub_blks *sblk;
+
+ if (!hw_dsc)
+ return;
+
+ hw = &hw_dsc->hw;
+ sblk = hw_dsc->caps->sblk;
+ DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CFG, 0);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + ENC_DF_CTRL, 0);
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_MAIN_CONF, 0);
+}
+
+static void dpu_hw_dsc_config_1_2(struct dpu_hw_dsc *hw_dsc,
+ struct drm_dsc_config *dsc,
+ u32 mode,
+ u32 initial_lines)
+{
+ struct dpu_hw_blk_reg_map *hw;
+ const struct dpu_dsc_sub_blks *sblk;
+ u32 data = 0;
+ u32 det_thresh_flatness;
+ u32 num_active_slice_per_enc;
+ u32 bpp;
+
+ if (!hw_dsc || !dsc)
+ return;
+
+ hw = &hw_dsc->hw;
+
+ sblk = hw_dsc->caps->sblk;
+
+ if (mode & DSC_MODE_SPLIT_PANEL)
+ data |= BIT(0);
+
+ if (mode & DSC_MODE_MULTIPLEX)
+ data |= BIT(1);
+
+ num_active_slice_per_enc = dsc->slice_count;
+ if (mode & DSC_MODE_MULTIPLEX)
+ num_active_slice_per_enc = dsc->slice_count / 2;
+
+ data |= (num_active_slice_per_enc & 0x3) << 7;
+
+ DPU_REG_WRITE(hw, DSC_CMN_MAIN_CNF, data);
+
+ data = (initial_lines & 0xff);
+
+ if (mode & DSC_MODE_VIDEO)
+ data |= BIT(9);
+
+ data |= (_dsc_calc_output_buf_max_addr(hw_dsc, num_active_slice_per_enc) << 18);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + ENC_DF_CTRL, data);
+
+ data = (dsc->dsc_version_minor & 0xf) << 28;
+ if (dsc->dsc_version_minor == 0x2) {
+ if (dsc->native_422)
+ data |= BIT(22);
+ if (dsc->native_420)
+ data |= BIT(21);
+ }
+
+ bpp = dsc->bits_per_pixel;
+ /* as per hw requirement bpp should be programmed
+ * twice the actual value in case of 420 or 422 encoding
+ */
+ if (dsc->native_422 || dsc->native_420)
+ bpp = 2 * bpp;
+
+ data |= bpp << 10;
+
+ if (dsc->block_pred_enable)
+ data |= BIT(20);
+
+ if (dsc->convert_rgb)
+ data |= BIT(4);
+
+ data |= (dsc->line_buf_depth & 0xf) << 6;
+ data |= dsc->bits_per_component & 0xf;
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_MAIN_CONF, data);
+
+ data = (dsc->pic_width & 0xffff) |
+ ((dsc->pic_height & 0xffff) << 16);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_PICTURE_SIZE, data);
+
+ data = (dsc->slice_width & 0xffff) |
+ ((dsc->slice_height & 0xffff) << 16);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_SLICE_SIZE, data);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_MISC_SIZE,
+ (dsc->slice_chunk_size) & 0xffff);
+
+ data = (dsc->initial_xmit_delay & 0xffff) |
+ ((dsc->initial_dec_delay & 0xffff) << 16);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_HRD_DELAYS, data);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_SCALE,
+ dsc->initial_scale_value & 0x3f);
+
+ data = (dsc->scale_increment_interval & 0xffff) |
+ ((dsc->scale_decrement_interval & 0x7ff) << 16);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_SCALE_INC_DEC, data);
+
+ data = (dsc->first_line_bpg_offset & 0x1f) |
+ ((dsc->second_line_bpg_offset & 0x1f) << 5);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_1, data);
+
+ data = (dsc->nfl_bpg_offset & 0xffff) |
+ ((dsc->slice_bpg_offset & 0xffff) << 16);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_2, data);
+
+ data = (dsc->initial_offset & 0xffff) |
+ ((dsc->final_offset & 0xffff) << 16);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_3, data);
+
+ data = (dsc->nsl_bpg_offset & 0xffff) |
+ ((dsc->second_line_offset_adj & 0xffff) << 16);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_4, data);
+
+ det_thresh_flatness = drm_dsc_flatness_det_thresh(dsc);
+ data = (dsc->flatness_min_qp & 0x1f) |
+ ((dsc->flatness_max_qp & 0x1f) << 5) |
+ ((det_thresh_flatness & 0xff) << 10);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_FLATNESS_QP, data);
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MODEL_SIZE,
+ (dsc->rc_model_size) & 0xffff);
+
+ data = dsc->rc_edge_factor & 0xf;
+ data |= (dsc->rc_quant_incr_limit0 & 0x1f) << 8;
+ data |= (dsc->rc_quant_incr_limit1 & 0x1f) << 13;
+ data |= (dsc->rc_tgt_offset_high & 0xf) << 20;
+ data |= (dsc->rc_tgt_offset_low & 0xf) << 24;
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_CONFIG, data);
+
+ /* program the dsc wrapper */
+ data = BIT(0); /* encoder enable */
+ if (dsc->native_422)
+ data |= BIT(8);
+ else if (dsc->native_420)
+ data |= BIT(9);
+ if (!dsc->convert_rgb)
+ data |= BIT(10);
+ if (dsc->bits_per_component == 8)
+ data |= BIT(11);
+ if (mode & DSC_MODE_SPLIT_PANEL)
+ data |= BIT(12);
+ if (mode & DSC_MODE_MULTIPLEX)
+ data |= BIT(13);
+ if (!(mode & DSC_MODE_VIDEO))
+ data |= BIT(17);
+
+ DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CFG, data);
+}
+
+static void dpu_hw_dsc_config_thresh_1_2(struct dpu_hw_dsc *hw_dsc,
+ struct drm_dsc_config *dsc)
+{
+ struct dpu_hw_blk_reg_map *hw;
+ const struct dpu_dsc_sub_blks *sblk;
+ struct drm_dsc_rc_range_parameters *rc;
+
+ if (!hw_dsc || !dsc)
+ return;
+
+ hw = &hw_dsc->hw;
+
+ sblk = hw_dsc->caps->sblk;
+
+ rc = dsc->rc_range_params;
+
+ /*
+ * With BUF_THRESH -- 14 in total
+ * each register contains 4 thresh values with the last register
+ * containing only 2 thresh values
+ */
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_0,
+ (dsc->rc_buf_thresh[0] << 0) |
+ (dsc->rc_buf_thresh[1] << 8) |
+ (dsc->rc_buf_thresh[2] << 16) |
+ (dsc->rc_buf_thresh[3] << 24));
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_1,
+ (dsc->rc_buf_thresh[4] << 0) |
+ (dsc->rc_buf_thresh[5] << 8) |
+ (dsc->rc_buf_thresh[6] << 16) |
+ (dsc->rc_buf_thresh[7] << 24));
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_2,
+ (dsc->rc_buf_thresh[8] << 0) |
+ (dsc->rc_buf_thresh[9] << 8) |
+ (dsc->rc_buf_thresh[10] << 16) |
+ (dsc->rc_buf_thresh[11] << 24));
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_3,
+ (dsc->rc_buf_thresh[12] << 0) |
+ (dsc->rc_buf_thresh[13] << 8));
+
+ /*
+ * with min/max_QP -- 5 bits
+ * each register contains 5 min_qp or max_qp for total of 15
+ *
+ * With BPG_OFFSET -- 6 bits
+ * each register contains 5 BPG_offset for total of 15
+ */
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MIN_QP_0,
+ (rc[0].range_min_qp << 0) |
+ (rc[1].range_min_qp << 5) |
+ (rc[2].range_min_qp << 10) |
+ (rc[3].range_min_qp << 15) |
+ (rc[4].range_min_qp << 20));
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MAX_QP_0,
+ (rc[0].range_max_qp << 0) |
+ (rc[1].range_max_qp << 5) |
+ (rc[2].range_max_qp << 10) |
+ (rc[3].range_max_qp << 15) |
+ (rc[4].range_max_qp << 20));
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_RANGE_BPG_OFFSETS_0,
+ (rc[0].range_bpg_offset << 0) |
+ (rc[1].range_bpg_offset << 6) |
+ (rc[2].range_bpg_offset << 12) |
+ (rc[3].range_bpg_offset << 18) |
+ (rc[4].range_bpg_offset << 24));
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MIN_QP_1,
+ (rc[5].range_min_qp << 0) |
+ (rc[6].range_min_qp << 5) |
+ (rc[7].range_min_qp << 10) |
+ (rc[8].range_min_qp << 15) |
+ (rc[9].range_min_qp << 20));
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MAX_QP_1,
+ (rc[5].range_max_qp << 0) |
+ (rc[6].range_max_qp << 5) |
+ (rc[7].range_max_qp << 10) |
+ (rc[8].range_max_qp << 15) |
+ (rc[9].range_max_qp << 20));
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_RANGE_BPG_OFFSETS_1,
+ (rc[5].range_bpg_offset << 0) |
+ (rc[6].range_bpg_offset << 6) |
+ (rc[7].range_bpg_offset << 12) |
+ (rc[8].range_bpg_offset << 18) |
+ (rc[9].range_bpg_offset << 24));
+
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MIN_QP_2,
+ (rc[10].range_min_qp << 0) |
+ (rc[11].range_min_qp << 5) |
+ (rc[12].range_min_qp << 10) |
+ (rc[13].range_min_qp << 15) |
+ (rc[14].range_min_qp << 20));
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MAX_QP_2,
+ (rc[10].range_max_qp << 0) |
+ (rc[11].range_max_qp << 5) |
+ (rc[12].range_max_qp << 10) |
+ (rc[13].range_max_qp << 15) |
+ (rc[14].range_max_qp << 20));
+ DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_RANGE_BPG_OFFSETS_2,
+ (rc[10].range_bpg_offset << 0) |
+ (rc[11].range_bpg_offset << 6) |
+ (rc[12].range_bpg_offset << 12) |
+ (rc[13].range_bpg_offset << 18) |
+ (rc[14].range_bpg_offset << 24));
+}
+
+static void dpu_hw_dsc_bind_pingpong_blk_1_2(struct dpu_hw_dsc *hw_dsc,
+ const enum dpu_pingpong pp)
+{
+ struct dpu_hw_blk_reg_map *hw;
+ const struct dpu_dsc_sub_blks *sblk;
+ int mux_cfg = 0xf; /* Disabled */
+
+ hw = &hw_dsc->hw;
+
+ sblk = hw_dsc->caps->sblk;
+
+ if (pp)
+ mux_cfg = (pp - PINGPONG_0) & 0x7;
+
+ DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CTL, mux_cfg);
+}
+
+static void _setup_dcs_ops_1_2(struct dpu_hw_dsc_ops *ops,
+ const unsigned long features)
+{
+ ops->dsc_disable = dpu_hw_dsc_disable_1_2;
+ ops->dsc_config = dpu_hw_dsc_config_1_2;
+ ops->dsc_config_thresh = dpu_hw_dsc_config_thresh_1_2;
+ ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk_1_2;
+}
+
+struct dpu_hw_dsc *dpu_hw_dsc_init_1_2(const struct dpu_dsc_cfg *cfg,
+ void __iomem *addr)
+{
+ struct dpu_hw_dsc *c;
+
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
+ if (!c)
+ return ERR_PTR(-ENOMEM);
+
+ c->hw.blk_addr = addr + cfg->base;
+ c->hw.log_mask = DPU_DBG_MASK_DSC;
+
+ c->idx = cfg->id;
+ c->caps = cfg;
+ _setup_dcs_ops_1_2(&c->ops, c->caps->features);
+
+ return c;
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
index 8ab5ace34a2d..9419b2209af8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
@@ -68,49 +68,23 @@ static void _setup_dspp_ops(struct dpu_hw_dspp *c,
c->ops.setup_pcc = dpu_setup_dspp_pcc;
}
-static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp,
- const struct dpu_mdss_cfg *m,
- void __iomem *addr,
- struct dpu_hw_blk_reg_map *b)
-{
- int i;
-
- if (!m || !addr || !b)
- return ERR_PTR(-EINVAL);
-
- for (i = 0; i < m->dspp_count; i++) {
- if (dspp == m->dspp[i].id) {
- b->blk_addr = addr + m->dspp[i].base;
- b->log_mask = DPU_DBG_MASK_DSPP;
- return &m->dspp[i];
- }
- }
-
- return ERR_PTR(-EINVAL);
-}
-
-struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx,
- void __iomem *addr,
- const struct dpu_mdss_cfg *m)
+struct dpu_hw_dspp *dpu_hw_dspp_init(const struct dpu_dspp_cfg *cfg,
+ void __iomem *addr)
{
struct dpu_hw_dspp *c;
- const struct dpu_dspp_cfg *cfg;
- if (!addr || !m)
+ if (!addr)
return ERR_PTR(-EINVAL);
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
- cfg = _dspp_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
+ c->hw.blk_addr = addr + cfg->base;
+ c->hw.log_mask = DPU_DBG_MASK_DSPP;
/* Assign ops */
- c->idx = idx;
+ c->idx = cfg->id;
c->cap = cfg;
_setup_dspp_ops(c, c->cap->features);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
index 05ecfdfac93b..bea965681330 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
@@ -79,14 +79,14 @@ static inline struct dpu_hw_dspp *to_dpu_hw_dspp(struct dpu_hw_blk *hw)
}
/**
- * dpu_hw_dspp_init - initializes the dspp hw driver object.
- * should be called once before accessing every dspp.
- * @idx: DSPP index for which driver object is required
+ * dpu_hw_dspp_init() - Initializes the DSPP hw driver object.
+ * should be called once before accessing every DSPP.
+ * @cfg: DSPP catalog entry for which driver object is required
* @addr: Mapped register io address of MDP
- * @Return: pointer to structure or ERR_PTR
+ * Return: pointer to structure or ERR_PTR
*/
-struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx,
- void __iomem *addr, const struct dpu_mdss_cfg *m);
+struct dpu_hw_dspp *dpu_hw_dspp_init(const struct dpu_dspp_cfg *cfg,
+ void __iomem *addr);
/**
* dpu_hw_dspp_destroy(): Destroys DSPP driver context
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
index 17f3e7e4f194..5e2d68ebb113 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
@@ -17,30 +17,26 @@
* Register offsets in MDSS register file for the interrupt registers
* w.r.t. the MDP base
*/
-#define MDP_SSPP_TOP0_OFF 0x0
-#define MDP_INTF_0_OFF 0x6A000
-#define MDP_INTF_1_OFF 0x6A800
-#define MDP_INTF_2_OFF 0x6B000
-#define MDP_INTF_3_OFF 0x6B800
-#define MDP_INTF_4_OFF 0x6C000
-#define MDP_INTF_5_OFF 0x6C800
-#define INTF_INTR_EN 0x1c0
-#define INTF_INTR_STATUS 0x1c4
-#define INTF_INTR_CLEAR 0x1c8
-#define MDP_AD4_0_OFF 0x7C000
-#define MDP_AD4_1_OFF 0x7D000
-#define MDP_AD4_INTR_EN_OFF 0x41c
-#define MDP_AD4_INTR_CLEAR_OFF 0x424
-#define MDP_AD4_INTR_STATUS_OFF 0x420
-#define MDP_INTF_0_OFF_REV_7xxx 0x34000
-#define MDP_INTF_1_OFF_REV_7xxx 0x35000
-#define MDP_INTF_2_OFF_REV_7xxx 0x36000
-#define MDP_INTF_3_OFF_REV_7xxx 0x37000
-#define MDP_INTF_4_OFF_REV_7xxx 0x38000
-#define MDP_INTF_5_OFF_REV_7xxx 0x39000
-#define MDP_INTF_6_OFF_REV_7xxx 0x3a000
-#define MDP_INTF_7_OFF_REV_7xxx 0x3b000
-#define MDP_INTF_8_OFF_REV_7xxx 0x3c000
+#define MDP_INTF_OFF(intf) (0x6A000 + 0x800 * (intf))
+#define MDP_INTF_INTR_EN(intf) (MDP_INTF_OFF(intf) + 0x1c0)
+#define MDP_INTF_INTR_STATUS(intf) (MDP_INTF_OFF(intf) + 0x1c4)
+#define MDP_INTF_INTR_CLEAR(intf) (MDP_INTF_OFF(intf) + 0x1c8)
+#define MDP_INTF_TEAR_OFF(intf) (0x6D700 + 0x100 * (intf))
+#define MDP_INTF_INTR_TEAR_EN(intf) (MDP_INTF_TEAR_OFF(intf) + 0x000)
+#define MDP_INTF_INTR_TEAR_STATUS(intf) (MDP_INTF_TEAR_OFF(intf) + 0x004)
+#define MDP_INTF_INTR_TEAR_CLEAR(intf) (MDP_INTF_TEAR_OFF(intf) + 0x008)
+#define MDP_AD4_OFF(ad4) (0x7C000 + 0x1000 * (ad4))
+#define MDP_AD4_INTR_EN_OFF(ad4) (MDP_AD4_OFF(ad4) + 0x41c)
+#define MDP_AD4_INTR_CLEAR_OFF(ad4) (MDP_AD4_OFF(ad4) + 0x424)
+#define MDP_AD4_INTR_STATUS_OFF(ad4) (MDP_AD4_OFF(ad4) + 0x420)
+#define MDP_INTF_REV_7xxx_OFF(intf) (0x34000 + 0x1000 * (intf))
+#define MDP_INTF_REV_7xxx_INTR_EN(intf) (MDP_INTF_REV_7xxx_OFF(intf) + 0x1c0)
+#define MDP_INTF_REV_7xxx_INTR_STATUS(intf) (MDP_INTF_REV_7xxx_OFF(intf) + 0x1c4)
+#define MDP_INTF_REV_7xxx_INTR_CLEAR(intf) (MDP_INTF_REV_7xxx_OFF(intf) + 0x1c8)
+#define MDP_INTF_REV_7xxx_TEAR_OFF(intf) (0x34800 + 0x1000 * (intf))
+#define MDP_INTF_REV_7xxx_INTR_TEAR_EN(intf) (MDP_INTF_REV_7xxx_TEAR_OFF(intf) + 0x000)
+#define MDP_INTF_REV_7xxx_INTR_TEAR_STATUS(intf) (MDP_INTF_REV_7xxx_TEAR_OFF(intf) + 0x004)
+#define MDP_INTF_REV_7xxx_INTR_TEAR_CLEAR(intf) (MDP_INTF_REV_7xxx_TEAR_OFF(intf) + 0x008)
/**
* struct dpu_intr_reg - array of DPU register sets
@@ -61,104 +57,124 @@ struct dpu_intr_reg {
*/
static const struct dpu_intr_reg dpu_intr_set[] = {
[MDP_SSPP_TOP0_INTR] = {
- MDP_SSPP_TOP0_OFF+INTR_CLEAR,
- MDP_SSPP_TOP0_OFF+INTR_EN,
- MDP_SSPP_TOP0_OFF+INTR_STATUS
+ INTR_CLEAR,
+ INTR_EN,
+ INTR_STATUS
},
[MDP_SSPP_TOP0_INTR2] = {
- MDP_SSPP_TOP0_OFF+INTR2_CLEAR,
- MDP_SSPP_TOP0_OFF+INTR2_EN,
- MDP_SSPP_TOP0_OFF+INTR2_STATUS
+ INTR2_CLEAR,
+ INTR2_EN,
+ INTR2_STATUS
},
[MDP_SSPP_TOP0_HIST_INTR] = {
- MDP_SSPP_TOP0_OFF+HIST_INTR_CLEAR,
- MDP_SSPP_TOP0_OFF+HIST_INTR_EN,
- MDP_SSPP_TOP0_OFF+HIST_INTR_STATUS
+ HIST_INTR_CLEAR,
+ HIST_INTR_EN,
+ HIST_INTR_STATUS
},
[MDP_INTF0_INTR] = {
- MDP_INTF_0_OFF+INTF_INTR_CLEAR,
- MDP_INTF_0_OFF+INTF_INTR_EN,
- MDP_INTF_0_OFF+INTF_INTR_STATUS
+ MDP_INTF_INTR_CLEAR(0),
+ MDP_INTF_INTR_EN(0),
+ MDP_INTF_INTR_STATUS(0)
},
[MDP_INTF1_INTR] = {
- MDP_INTF_1_OFF+INTF_INTR_CLEAR,
- MDP_INTF_1_OFF+INTF_INTR_EN,
- MDP_INTF_1_OFF+INTF_INTR_STATUS
+ MDP_INTF_INTR_CLEAR(1),
+ MDP_INTF_INTR_EN(1),
+ MDP_INTF_INTR_STATUS(1)
},
[MDP_INTF2_INTR] = {
- MDP_INTF_2_OFF+INTF_INTR_CLEAR,
- MDP_INTF_2_OFF+INTF_INTR_EN,
- MDP_INTF_2_OFF+INTF_INTR_STATUS
+ MDP_INTF_INTR_CLEAR(2),
+ MDP_INTF_INTR_EN(2),
+ MDP_INTF_INTR_STATUS(2)
},
[MDP_INTF3_INTR] = {
- MDP_INTF_3_OFF+INTF_INTR_CLEAR,
- MDP_INTF_3_OFF+INTF_INTR_EN,
- MDP_INTF_3_OFF+INTF_INTR_STATUS
+ MDP_INTF_INTR_CLEAR(3),
+ MDP_INTF_INTR_EN(3),
+ MDP_INTF_INTR_STATUS(3)
},
[MDP_INTF4_INTR] = {
- MDP_INTF_4_OFF+INTF_INTR_CLEAR,
- MDP_INTF_4_OFF+INTF_INTR_EN,
- MDP_INTF_4_OFF+INTF_INTR_STATUS
+ MDP_INTF_INTR_CLEAR(4),
+ MDP_INTF_INTR_EN(4),
+ MDP_INTF_INTR_STATUS(4)
},
[MDP_INTF5_INTR] = {
- MDP_INTF_5_OFF+INTF_INTR_CLEAR,
- MDP_INTF_5_OFF+INTF_INTR_EN,
- MDP_INTF_5_OFF+INTF_INTR_STATUS
+ MDP_INTF_INTR_CLEAR(5),
+ MDP_INTF_INTR_EN(5),
+ MDP_INTF_INTR_STATUS(5)
+ },
+ [MDP_INTF1_TEAR_INTR] = {
+ MDP_INTF_INTR_TEAR_CLEAR(1),
+ MDP_INTF_INTR_TEAR_EN(1),
+ MDP_INTF_INTR_TEAR_STATUS(1)
+ },
+ [MDP_INTF2_TEAR_INTR] = {
+ MDP_INTF_INTR_TEAR_CLEAR(2),
+ MDP_INTF_INTR_TEAR_EN(2),
+ MDP_INTF_INTR_TEAR_STATUS(2)
},
[MDP_AD4_0_INTR] = {
- MDP_AD4_0_OFF + MDP_AD4_INTR_CLEAR_OFF,
- MDP_AD4_0_OFF + MDP_AD4_INTR_EN_OFF,
- MDP_AD4_0_OFF + MDP_AD4_INTR_STATUS_OFF,
+ MDP_AD4_INTR_CLEAR_OFF(0),
+ MDP_AD4_INTR_EN_OFF(0),
+ MDP_AD4_INTR_STATUS_OFF(0),
},
[MDP_AD4_1_INTR] = {
- MDP_AD4_1_OFF + MDP_AD4_INTR_CLEAR_OFF,
- MDP_AD4_1_OFF + MDP_AD4_INTR_EN_OFF,
- MDP_AD4_1_OFF + MDP_AD4_INTR_STATUS_OFF,
+ MDP_AD4_INTR_CLEAR_OFF(1),
+ MDP_AD4_INTR_EN_OFF(1),
+ MDP_AD4_INTR_STATUS_OFF(1),
},
[MDP_INTF0_7xxx_INTR] = {
- MDP_INTF_0_OFF_REV_7xxx+INTF_INTR_CLEAR,
- MDP_INTF_0_OFF_REV_7xxx+INTF_INTR_EN,
- MDP_INTF_0_OFF_REV_7xxx+INTF_INTR_STATUS
+ MDP_INTF_REV_7xxx_INTR_CLEAR(0),
+ MDP_INTF_REV_7xxx_INTR_EN(0),
+ MDP_INTF_REV_7xxx_INTR_STATUS(0)
},
[MDP_INTF1_7xxx_INTR] = {
- MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_CLEAR,
- MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_EN,
- MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_STATUS
+ MDP_INTF_REV_7xxx_INTR_CLEAR(1),
+ MDP_INTF_REV_7xxx_INTR_EN(1),
+ MDP_INTF_REV_7xxx_INTR_STATUS(1)
+ },
+ [MDP_INTF1_7xxx_TEAR_INTR] = {
+ MDP_INTF_REV_7xxx_INTR_TEAR_CLEAR(1),
+ MDP_INTF_REV_7xxx_INTR_TEAR_EN(1),
+ MDP_INTF_REV_7xxx_INTR_TEAR_STATUS(1)
},
[MDP_INTF2_7xxx_INTR] = {
- MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_CLEAR,
- MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_EN,
- MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_STATUS
+ MDP_INTF_REV_7xxx_INTR_CLEAR(2),
+ MDP_INTF_REV_7xxx_INTR_EN(2),
+ MDP_INTF_REV_7xxx_INTR_STATUS(2)
+ },
+ [MDP_INTF2_7xxx_TEAR_INTR] = {
+ MDP_INTF_REV_7xxx_INTR_TEAR_CLEAR(2),
+ MDP_INTF_REV_7xxx_INTR_TEAR_EN(2),
+ MDP_INTF_REV_7xxx_INTR_TEAR_STATUS(2)
},
[MDP_INTF3_7xxx_INTR] = {
- MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_CLEAR,
- MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_EN,
- MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_STATUS
+ MDP_INTF_REV_7xxx_INTR_CLEAR(3),
+ MDP_INTF_REV_7xxx_INTR_EN(3),
+ MDP_INTF_REV_7xxx_INTR_STATUS(3)
},
[MDP_INTF4_7xxx_INTR] = {
- MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_CLEAR,
- MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_EN,
- MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_STATUS
+ MDP_INTF_REV_7xxx_INTR_CLEAR(4),
+ MDP_INTF_REV_7xxx_INTR_EN(4),
+ MDP_INTF_REV_7xxx_INTR_STATUS(4)
},
[MDP_INTF5_7xxx_INTR] = {
- MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_CLEAR,
- MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_EN,
- MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_STATUS
+ MDP_INTF_REV_7xxx_INTR_CLEAR(5),
+ MDP_INTF_REV_7xxx_INTR_EN(5),
+ MDP_INTF_REV_7xxx_INTR_STATUS(5)
},
[MDP_INTF6_7xxx_INTR] = {
- MDP_INTF_6_OFF_REV_7xxx+INTF_INTR_CLEAR,
- MDP_INTF_6_OFF_REV_7xxx+INTF_INTR_EN,
- MDP_INTF_6_OFF_REV_7xxx+INTF_INTR_STATUS
+ MDP_INTF_REV_7xxx_INTR_CLEAR(6),
+ MDP_INTF_REV_7xxx_INTR_EN(6),
+ MDP_INTF_REV_7xxx_INTR_STATUS(6)
},
[MDP_INTF7_7xxx_INTR] = {
- MDP_INTF_7_OFF_REV_7xxx+INTF_INTR_CLEAR,
- MDP_INTF_7_OFF_REV_7xxx+INTF_INTR_EN,
- MDP_INTF_7_OFF_REV_7xxx+INTF_INTR_STATUS
+ MDP_INTF_REV_7xxx_INTR_CLEAR(7),
+ MDP_INTF_REV_7xxx_INTR_EN(7),
+ MDP_INTF_REV_7xxx_INTR_STATUS(7)
},
[MDP_INTF8_7xxx_INTR] = {
- MDP_INTF_8_OFF_REV_7xxx+INTF_INTR_CLEAR,
- MDP_INTF_8_OFF_REV_7xxx+INTF_INTR_EN,
- MDP_INTF_8_OFF_REV_7xxx+INTF_INTR_STATUS
+ MDP_INTF_REV_7xxx_INTR_CLEAR(8),
+ MDP_INTF_REV_7xxx_INTR_EN(8),
+ MDP_INTF_REV_7xxx_INTR_STATUS(8)
},
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
index 425465011c80..1f2dabc54c22 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
@@ -23,11 +23,15 @@ enum dpu_hw_intr_reg {
MDP_INTF3_INTR,
MDP_INTF4_INTR,
MDP_INTF5_INTR,
+ MDP_INTF1_TEAR_INTR,
+ MDP_INTF2_TEAR_INTR,
MDP_AD4_0_INTR,
MDP_AD4_1_INTR,
MDP_INTF0_7xxx_INTR,
MDP_INTF1_7xxx_INTR,
+ MDP_INTF1_7xxx_TEAR_INTR,
MDP_INTF2_7xxx_INTR,
+ MDP_INTF2_7xxx_TEAR_INTR,
MDP_INTF3_7xxx_INTR,
MDP_INTF4_7xxx_INTR,
MDP_INTF5_7xxx_INTR,
@@ -67,7 +71,7 @@ struct dpu_hw_intr {
/**
* dpu_hw_intr_init(): Initializes the interrupts hw object
* @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
+ * @m: pointer to MDSS catalog data
*/
struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
const struct dpu_mdss_cfg *m);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
index b9dddf576c02..5b0f6627e29b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
@@ -8,6 +8,9 @@
#include "dpu_hw_catalog.h"
#include "dpu_hw_intf.h"
#include "dpu_kms.h"
+#include "dpu_trace.h"
+
+#include <linux/iopoll.h>
#define INTF_TIMING_ENGINE_EN 0x000
#define INTF_CONFIG 0x004
@@ -36,56 +39,60 @@
#define INTF_CONFIG2 0x060
#define INTF_DISPLAY_DATA_HCTL 0x064
#define INTF_ACTIVE_DATA_HCTL 0x068
+
+#define INTF_DSI_CMD_MODE_TRIGGER_EN 0x084
+#define INTF_PANEL_FORMAT 0x090
+
#define INTF_FRAME_LINE_COUNT_EN 0x0A8
#define INTF_FRAME_COUNT 0x0AC
-#define INTF_LINE_COUNT 0x0B0
-
-#define INTF_DEFLICKER_CONFIG 0x0F0
-#define INTF_DEFLICKER_STRNG_COEFF 0x0F4
-#define INTF_DEFLICKER_WEAK_COEFF 0x0F8
-
-#define INTF_DSI_CMD_MODE_TRIGGER_EN 0x084
-#define INTF_PANEL_FORMAT 0x090
-#define INTF_TPG_ENABLE 0x100
-#define INTF_TPG_MAIN_CONTROL 0x104
-#define INTF_TPG_VIDEO_CONFIG 0x108
-#define INTF_TPG_COMPONENT_LIMITS 0x10C
-#define INTF_TPG_RECTANGLE 0x110
-#define INTF_TPG_INITIAL_VALUE 0x114
-#define INTF_TPG_BLK_WHITE_PATTERN_FRAMES 0x118
-#define INTF_TPG_RGB_MAPPING 0x11C
-#define INTF_PROG_FETCH_START 0x170
-#define INTF_PROG_ROT_START 0x174
-#define INTF_MUX 0x25C
-#define INTF_STATUS 0x26C
+#define INTF_LINE_COUNT 0x0B0
+
+#define INTF_DEFLICKER_CONFIG 0x0F0
+#define INTF_DEFLICKER_STRNG_COEFF 0x0F4
+#define INTF_DEFLICKER_WEAK_COEFF 0x0F8
+
+#define INTF_TPG_ENABLE 0x100
+#define INTF_TPG_MAIN_CONTROL 0x104
+#define INTF_TPG_VIDEO_CONFIG 0x108
+#define INTF_TPG_COMPONENT_LIMITS 0x10C
+#define INTF_TPG_RECTANGLE 0x110
+#define INTF_TPG_INITIAL_VALUE 0x114
+#define INTF_TPG_BLK_WHITE_PATTERN_FRAMES 0x118
+#define INTF_TPG_RGB_MAPPING 0x11C
+#define INTF_PROG_FETCH_START 0x170
+#define INTF_PROG_ROT_START 0x174
+
+#define INTF_MISR_CTRL 0x180
+#define INTF_MISR_SIGNATURE 0x184
+
+#define INTF_MUX 0x25C
+#define INTF_STATUS 0x26C
+#define INTF_AVR_CONTROL 0x270
+#define INTF_AVR_MODE 0x274
+#define INTF_AVR_TRIGGER 0x278
+#define INTF_AVR_VTOTAL 0x27C
+#define INTF_TEAR_MDP_VSYNC_SEL 0x280
+#define INTF_TEAR_TEAR_CHECK_EN 0x284
+#define INTF_TEAR_SYNC_CONFIG_VSYNC 0x288
+#define INTF_TEAR_SYNC_CONFIG_HEIGHT 0x28C
+#define INTF_TEAR_SYNC_WRCOUNT 0x290
+#define INTF_TEAR_VSYNC_INIT_VAL 0x294
+#define INTF_TEAR_INT_COUNT_VAL 0x298
+#define INTF_TEAR_SYNC_THRESH 0x29C
+#define INTF_TEAR_START_POS 0x2A0
+#define INTF_TEAR_RD_PTR_IRQ 0x2A4
+#define INTF_TEAR_WR_PTR_IRQ 0x2A8
+#define INTF_TEAR_OUT_LINE_COUNT 0x2AC
+#define INTF_TEAR_LINE_COUNT 0x2B0
+#define INTF_TEAR_AUTOREFRESH_CONFIG 0x2B4
#define INTF_CFG_ACTIVE_H_EN BIT(29)
#define INTF_CFG_ACTIVE_V_EN BIT(30)
#define INTF_CFG2_DATABUS_WIDEN BIT(0)
#define INTF_CFG2_DATA_HCTL_EN BIT(4)
+#define INTF_CFG2_DCE_DATA_COMPRESS BIT(12)
-#define INTF_MISR_CTRL 0x180
-#define INTF_MISR_SIGNATURE 0x184
-
-static const struct dpu_intf_cfg *_intf_offset(enum dpu_intf intf,
- const struct dpu_mdss_cfg *m,
- void __iomem *addr,
- struct dpu_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->intf_count; i++) {
- if ((intf == m->intf[i].id) &&
- (m->intf[i].type != INTF_NONE)) {
- b->blk_addr = addr + m->intf[i].base;
- b->log_mask = DPU_DBG_MASK_INTF;
- return &m->intf[i];
- }
- }
-
- return ERR_PTR(-EINVAL);
-}
static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
const struct intf_timing_params *p,
@@ -99,7 +106,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
u32 active_h_start, active_h_end;
u32 active_v_start, active_v_end;
u32 active_hctl, display_hctl, hsync_ctl;
- u32 polarity_ctl, den_polarity, hsync_polarity, vsync_polarity;
+ u32 polarity_ctl, den_polarity;
u32 panel_format;
u32 intf_cfg, intf_cfg2 = 0;
u32 display_data_hctl = 0, active_data_hctl = 0;
@@ -186,19 +193,9 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
}
den_polarity = 0;
- if (ctx->cap->type == INTF_HDMI) {
- hsync_polarity = p->yres >= 720 ? 0 : 1;
- vsync_polarity = p->yres >= 720 ? 0 : 1;
- } else if (ctx->cap->type == INTF_DP) {
- hsync_polarity = p->hsync_polarity;
- vsync_polarity = p->vsync_polarity;
- } else {
- hsync_polarity = 0;
- vsync_polarity = 0;
- }
polarity_ctl = (den_polarity << 2) | /* DEN Polarity */
- (vsync_polarity << 1) | /* VSYNC Polarity */
- (hsync_polarity << 0); /* HSYNC Polarity */
+ (p->vsync_polarity << 1) | /* VSYNC Polarity */
+ (p->hsync_polarity << 0); /* HSYNC Polarity */
if (!DPU_FORMAT_IS_YUV(fmt))
panel_format = (fmt->bits[C0_G_Y] |
@@ -271,7 +268,6 @@ static void dpu_hw_intf_setup_prg_fetch(
static void dpu_hw_intf_bind_pingpong_blk(
struct dpu_hw_intf *intf,
- bool enable,
const enum dpu_pingpong pp)
{
struct dpu_hw_blk_reg_map *c = &intf->hw;
@@ -280,7 +276,7 @@ static void dpu_hw_intf_bind_pingpong_blk(
mux_cfg = DPU_REG_READ(c, INTF_MUX);
mux_cfg &= ~0xf;
- if (enable)
+ if (pp)
mux_cfg |= (pp - PINGPONG_0) & 0x7;
else
mux_cfg |= 0xf;
@@ -332,6 +328,200 @@ static int dpu_hw_intf_collect_misr(struct dpu_hw_intf *intf, u32 *misr_value)
return dpu_hw_collect_misr(&intf->hw, INTF_MISR_CTRL, INTF_MISR_SIGNATURE, misr_value);
}
+static int dpu_hw_intf_enable_te(struct dpu_hw_intf *intf,
+ struct dpu_hw_tear_check *te)
+{
+ struct dpu_hw_blk_reg_map *c;
+ int cfg;
+
+ if (!intf)
+ return -EINVAL;
+
+ c = &intf->hw;
+
+ cfg = BIT(19); /* VSYNC_COUNTER_EN */
+ if (te->hw_vsync_mode)
+ cfg |= BIT(20);
+
+ cfg |= te->vsync_count;
+
+ DPU_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_VSYNC, cfg);
+ DPU_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_HEIGHT, te->sync_cfg_height);
+ DPU_REG_WRITE(c, INTF_TEAR_VSYNC_INIT_VAL, te->vsync_init_val);
+ DPU_REG_WRITE(c, INTF_TEAR_RD_PTR_IRQ, te->rd_ptr_irq);
+ DPU_REG_WRITE(c, INTF_TEAR_START_POS, te->start_pos);
+ DPU_REG_WRITE(c, INTF_TEAR_SYNC_THRESH,
+ ((te->sync_threshold_continue << 16) |
+ te->sync_threshold_start));
+ DPU_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT,
+ (te->start_pos + te->sync_threshold_start + 1));
+
+ DPU_REG_WRITE(c, INTF_TEAR_TEAR_CHECK_EN, 1);
+
+ return 0;
+}
+
+static void dpu_hw_intf_setup_autorefresh_config(struct dpu_hw_intf *intf,
+ u32 frame_count, bool enable)
+{
+ struct dpu_hw_blk_reg_map *c;
+ u32 refresh_cfg;
+
+ c = &intf->hw;
+ refresh_cfg = DPU_REG_READ(c, INTF_TEAR_AUTOREFRESH_CONFIG);
+ if (enable)
+ refresh_cfg = BIT(31) | frame_count;
+ else
+ refresh_cfg &= ~BIT(31);
+
+ DPU_REG_WRITE(c, INTF_TEAR_AUTOREFRESH_CONFIG, refresh_cfg);
+}
+
+/*
+ * dpu_hw_intf_get_autorefresh_config - Get autorefresh config from HW
+ * @intf: DPU intf structure
+ * @frame_count: Used to return the current frame count from hw
+ *
+ * Returns: True if autorefresh enabled, false if disabled.
+ */
+static bool dpu_hw_intf_get_autorefresh_config(struct dpu_hw_intf *intf,
+ u32 *frame_count)
+{
+ u32 val = DPU_REG_READ(&intf->hw, INTF_TEAR_AUTOREFRESH_CONFIG);
+
+ if (frame_count != NULL)
+ *frame_count = val & 0xffff;
+ return !!((val & BIT(31)) >> 31);
+}
+
+static int dpu_hw_intf_disable_te(struct dpu_hw_intf *intf)
+{
+ struct dpu_hw_blk_reg_map *c;
+
+ if (!intf)
+ return -EINVAL;
+
+ c = &intf->hw;
+ DPU_REG_WRITE(c, INTF_TEAR_TEAR_CHECK_EN, 0);
+ return 0;
+}
+
+static int dpu_hw_intf_connect_external_te(struct dpu_hw_intf *intf,
+ bool enable_external_te)
+{
+ struct dpu_hw_blk_reg_map *c = &intf->hw;
+ u32 cfg;
+ int orig;
+
+ if (!intf)
+ return -EINVAL;
+
+ c = &intf->hw;
+ cfg = DPU_REG_READ(c, INTF_TEAR_SYNC_CONFIG_VSYNC);
+ orig = (bool)(cfg & BIT(20));
+ if (enable_external_te)
+ cfg |= BIT(20);
+ else
+ cfg &= ~BIT(20);
+ DPU_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_VSYNC, cfg);
+ trace_dpu_intf_connect_ext_te(intf->idx - INTF_0, cfg);
+
+ return orig;
+}
+
+static int dpu_hw_intf_get_vsync_info(struct dpu_hw_intf *intf,
+ struct dpu_hw_pp_vsync_info *info)
+{
+ struct dpu_hw_blk_reg_map *c = &intf->hw;
+ u32 val;
+
+ if (!intf || !info)
+ return -EINVAL;
+
+ c = &intf->hw;
+
+ val = DPU_REG_READ(c, INTF_TEAR_VSYNC_INIT_VAL);
+ info->rd_ptr_init_val = val & 0xffff;
+
+ val = DPU_REG_READ(c, INTF_TEAR_INT_COUNT_VAL);
+ info->rd_ptr_frame_count = (val & 0xffff0000) >> 16;
+ info->rd_ptr_line_count = val & 0xffff;
+
+ val = DPU_REG_READ(c, INTF_TEAR_LINE_COUNT);
+ info->wr_ptr_line_count = val & 0xffff;
+
+ val = DPU_REG_READ(c, INTF_FRAME_COUNT);
+ info->intf_frame_count = val;
+
+ return 0;
+}
+
+static void dpu_hw_intf_vsync_sel(struct dpu_hw_intf *intf,
+ u32 vsync_source)
+{
+ struct dpu_hw_blk_reg_map *c;
+
+ if (!intf)
+ return;
+
+ c = &intf->hw;
+
+ DPU_REG_WRITE(c, INTF_TEAR_MDP_VSYNC_SEL, (vsync_source & 0xf));
+}
+
+static void dpu_hw_intf_disable_autorefresh(struct dpu_hw_intf *intf,
+ uint32_t encoder_id, u16 vdisplay)
+{
+ struct dpu_hw_pp_vsync_info info;
+ int trial = 0;
+
+ /* If autorefresh is already disabled, we have nothing to do */
+ if (!dpu_hw_intf_get_autorefresh_config(intf, NULL))
+ return;
+
+ /*
+ * If autorefresh is enabled, disable it and make sure it is safe to
+ * proceed with current frame commit/push. Sequence followed is,
+ * 1. Disable TE
+ * 2. Disable autorefresh config
+ * 4. Poll for frame transfer ongoing to be false
+ * 5. Enable TE back
+ */
+
+ dpu_hw_intf_connect_external_te(intf, false);
+ dpu_hw_intf_setup_autorefresh_config(intf, 0, false);
+
+ do {
+ udelay(DPU_ENC_MAX_POLL_TIMEOUT_US);
+ if ((trial * DPU_ENC_MAX_POLL_TIMEOUT_US)
+ > (KICKOFF_TIMEOUT_MS * USEC_PER_MSEC)) {
+ DPU_ERROR("enc%d intf%d disable autorefresh failed\n",
+ encoder_id, intf->idx - INTF_0);
+ break;
+ }
+
+ trial++;
+
+ dpu_hw_intf_get_vsync_info(intf, &info);
+ } while (info.wr_ptr_line_count > 0 &&
+ info.wr_ptr_line_count < vdisplay);
+
+ dpu_hw_intf_connect_external_te(intf, true);
+
+ DPU_DEBUG("enc%d intf%d disabled autorefresh\n",
+ encoder_id, intf->idx - INTF_0);
+
+}
+
+static void dpu_hw_intf_enable_compression(struct dpu_hw_intf *ctx)
+{
+ u32 intf_cfg2 = DPU_REG_READ(&ctx->hw, INTF_CONFIG2);
+
+ intf_cfg2 |= INTF_CFG2_DCE_DATA_COMPRESS;
+
+ DPU_REG_WRITE(&ctx->hw, INTF_CONFIG2, intf_cfg2);
+}
+
static void _setup_intf_ops(struct dpu_hw_intf_ops *ops,
unsigned long cap)
{
@@ -344,32 +534,41 @@ static void _setup_intf_ops(struct dpu_hw_intf_ops *ops,
ops->bind_pingpong_blk = dpu_hw_intf_bind_pingpong_blk;
ops->setup_misr = dpu_hw_intf_setup_misr;
ops->collect_misr = dpu_hw_intf_collect_misr;
+
+ if (cap & BIT(DPU_INTF_TE)) {
+ ops->enable_tearcheck = dpu_hw_intf_enable_te;
+ ops->disable_tearcheck = dpu_hw_intf_disable_te;
+ ops->connect_external_te = dpu_hw_intf_connect_external_te;
+ ops->vsync_sel = dpu_hw_intf_vsync_sel;
+ ops->disable_autorefresh = dpu_hw_intf_disable_autorefresh;
+ }
+
+ if (cap & BIT(DPU_INTF_DATA_COMPRESS))
+ ops->enable_compression = dpu_hw_intf_enable_compression;
}
-struct dpu_hw_intf *dpu_hw_intf_init(enum dpu_intf idx,
- void __iomem *addr,
- const struct dpu_mdss_cfg *m)
+struct dpu_hw_intf *dpu_hw_intf_init(const struct dpu_intf_cfg *cfg,
+ void __iomem *addr)
{
struct dpu_hw_intf *c;
- const struct dpu_intf_cfg *cfg;
+
+ if (cfg->type == INTF_NONE) {
+ DPU_DEBUG("Skip intf %d with type NONE\n", cfg->id - INTF_0);
+ return NULL;
+ }
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
- cfg = _intf_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- pr_err("failed to create dpu_hw_intf %d\n", idx);
- return ERR_PTR(-EINVAL);
- }
+ c->hw.blk_addr = addr + cfg->base;
+ c->hw.log_mask = DPU_DBG_MASK_INTF;
/*
* Assign ops
*/
- c->idx = idx;
+ c->idx = cfg->id;
c->cap = cfg;
- c->mdss = m;
_setup_intf_ops(&c->ops, c->cap->features);
return c;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
index 643dd10bc030..99e21c4137f9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
@@ -60,6 +60,17 @@ struct intf_status {
* feed pixels to this interface
* @setup_misr: enable/disable MISR
* @collect_misr: read MISR signature
+ * @enable_tearcheck: Enables vsync generation and sets up init value of read
+ * pointer and programs the tear check configuration
+ * @disable_tearcheck: Disables tearcheck block
+ * @connect_external_te: Read, modify, write to either set or clear listening to external TE
+ * Return: 1 if TE was originally connected, 0 if not, or -ERROR
+ * @get_vsync_info: Provides the programmed and current line_count
+ * @setup_autorefresh: Configure and enable the autorefresh config
+ * @get_autorefresh: Retrieve autorefresh config from hardware
+ * Return: 0 on success, -ETIMEDOUT on timeout
+ * @vsync_sel: Select vsync signal for tear-effect configuration
+ * @enable_compression: Enable data compression
*/
struct dpu_hw_intf_ops {
void (*setup_timing_gen)(struct dpu_hw_intf *intf,
@@ -78,10 +89,26 @@ struct dpu_hw_intf_ops {
u32 (*get_line_count)(struct dpu_hw_intf *intf);
void (*bind_pingpong_blk)(struct dpu_hw_intf *intf,
- bool enable,
const enum dpu_pingpong pp);
void (*setup_misr)(struct dpu_hw_intf *intf, bool enable, u32 frame_count);
int (*collect_misr)(struct dpu_hw_intf *intf, u32 *misr_value);
+
+ // Tearcheck on INTF since DPU 5.0.0
+
+ int (*enable_tearcheck)(struct dpu_hw_intf *intf, struct dpu_hw_tear_check *cfg);
+
+ int (*disable_tearcheck)(struct dpu_hw_intf *intf);
+
+ int (*connect_external_te)(struct dpu_hw_intf *intf, bool enable_external_te);
+
+ void (*vsync_sel)(struct dpu_hw_intf *intf, u32 vsync_source);
+
+ /**
+ * Disable autorefresh if enabled
+ */
+ void (*disable_autorefresh)(struct dpu_hw_intf *intf, uint32_t encoder_id, u16 vdisplay);
+
+ void (*enable_compression)(struct dpu_hw_intf *intf);
};
struct dpu_hw_intf {
@@ -90,22 +117,19 @@ struct dpu_hw_intf {
/* intf */
enum dpu_intf idx;
const struct dpu_intf_cfg *cap;
- const struct dpu_mdss_cfg *mdss;
/* ops */
struct dpu_hw_intf_ops ops;
};
/**
- * dpu_hw_intf_init(): Initializes the intf driver for the passed
- * interface idx.
- * @idx: interface index for which driver object is required
+ * dpu_hw_intf_init() - Initializes the INTF driver for the passed
+ * interface catalog entry.
+ * @cfg: interface catalog entry for which driver object is required
* @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
*/
-struct dpu_hw_intf *dpu_hw_intf_init(enum dpu_intf idx,
- void __iomem *addr,
- const struct dpu_mdss_cfg *m);
+struct dpu_hw_intf *dpu_hw_intf_init(const struct dpu_intf_cfg *cfg,
+ void __iomem *addr);
/**
* dpu_hw_intf_destroy(): Destroys INTF driver context
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
index f5120ea91ede..d1c3bd8379ea 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
@@ -30,24 +30,6 @@
#define LM_MISR_SIGNATURE 0x314
-static const struct dpu_lm_cfg *_lm_offset(enum dpu_lm mixer,
- const struct dpu_mdss_cfg *m,
- void __iomem *addr,
- struct dpu_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->mixer_count; i++) {
- if (mixer == m->mixer[i].id) {
- b->blk_addr = addr + m->mixer[i].base;
- b->log_mask = DPU_DBG_MASK_LM;
- return &m->mixer[i];
- }
- }
-
- return ERR_PTR(-ENOMEM);
-}
-
/**
* _stage_offset(): returns the relative offset of the blend registers
* for the stage to be setup
@@ -160,8 +142,7 @@ static void dpu_hw_lm_setup_color3(struct dpu_hw_mixer *ctx,
DPU_REG_WRITE(c, LM_OP_MODE, op_mode);
}
-static void _setup_mixer_ops(const struct dpu_mdss_cfg *m,
- struct dpu_hw_lm_ops *ops,
+static void _setup_mixer_ops(struct dpu_hw_lm_ops *ops,
unsigned long features)
{
ops->setup_mixer_out = dpu_hw_lm_setup_out;
@@ -175,27 +156,27 @@ static void _setup_mixer_ops(const struct dpu_mdss_cfg *m,
ops->collect_misr = dpu_hw_lm_collect_misr;
}
-struct dpu_hw_mixer *dpu_hw_lm_init(enum dpu_lm idx,
- void __iomem *addr,
- const struct dpu_mdss_cfg *m)
+struct dpu_hw_mixer *dpu_hw_lm_init(const struct dpu_lm_cfg *cfg,
+ void __iomem *addr)
{
struct dpu_hw_mixer *c;
- const struct dpu_lm_cfg *cfg;
+
+ if (cfg->pingpong == PINGPONG_NONE) {
+ DPU_DEBUG("skip mixer %d without pingpong\n", cfg->id);
+ return NULL;
+ }
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
- cfg = _lm_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
+ c->hw.blk_addr = addr + cfg->base;
+ c->hw.log_mask = DPU_DBG_MASK_LM;
/* Assign ops */
- c->idx = idx;
+ c->idx = cfg->id;
c->cap = cfg;
- _setup_mixer_ops(m, &c->ops, c->cap->features);
+ _setup_mixer_ops(&c->ops, c->cap->features);
return c;
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
index 652ddfdedec3..36992d046a53 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
@@ -93,15 +93,13 @@ static inline struct dpu_hw_mixer *to_dpu_hw_mixer(struct dpu_hw_blk *hw)
}
/**
- * dpu_hw_lm_init(): Initializes the mixer hw driver object.
+ * dpu_hw_lm_init() - Initializes the mixer hw driver object.
* should be called once before accessing every mixer.
- * @idx: mixer index for which driver object is required
+ * @cfg: mixer catalog entry for which driver object is required
* @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
*/
-struct dpu_hw_mixer *dpu_hw_lm_init(enum dpu_lm idx,
- void __iomem *addr,
- const struct dpu_mdss_cfg *m);
+struct dpu_hw_mixer *dpu_hw_lm_init(const struct dpu_lm_cfg *cfg,
+ void __iomem *addr);
/**
* dpu_hw_lm_destroy(): Destroys layer mixer driver context
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index 2d9192a6ce00..02a0f48aac94 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -191,7 +191,8 @@ enum dpu_dsc {
};
enum dpu_pingpong {
- PINGPONG_0 = 1,
+ PINGPONG_NONE,
+ PINGPONG_0,
PINGPONG_1,
PINGPONG_2,
PINGPONG_3,
@@ -463,4 +464,52 @@ struct dpu_mdss_color {
#define DPU_DBG_MASK_DSPP (1 << 10)
#define DPU_DBG_MASK_DSC (1 << 11)
+/**
+ * struct dpu_hw_tear_check - Struct contains parameters to configure
+ * tear-effect module. This structure is used to configure tear-check
+ * logic present either in ping-pong or in interface module.
+ * @vsync_count: Ratio of MDP VSYNC clk freq(Hz) to refresh rate divided
+ * by no of lines
+ * @sync_cfg_height: Total vertical lines (display height - 1)
+ * @vsync_init_val: Init value to which the read pointer gets loaded at
+ * vsync edge
+ * @sync_threshold_start: Read pointer threshold start ROI for write operation
+ * @sync_threshold_continue: The minimum number of lines the write pointer
+ * needs to be above the read pointer
+ * @start_pos: The position from which the start_threshold value is added
+ * @rd_ptr_irq: The read pointer line at which interrupt has to be generated
+ * @hw_vsync_mode: Sync with external frame sync input
+ */
+struct dpu_hw_tear_check {
+ /*
+ * This is ratio of MDP VSYNC clk freq(Hz) to
+ * refresh rate divided by no of lines
+ */
+ u32 vsync_count;
+ u32 sync_cfg_height;
+ u32 vsync_init_val;
+ u32 sync_threshold_start;
+ u32 sync_threshold_continue;
+ u32 start_pos;
+ u32 rd_ptr_irq;
+ u8 hw_vsync_mode;
+};
+
+/**
+ * struct dpu_hw_pp_vsync_info - Struct contains parameters to configure
+ * read and write pointers for command mode panels
+ * @rd_ptr_init_val: Value of rd pointer at vsync edge
+ * @rd_ptr_frame_count: Num frames sent since enabling interface
+ * @rd_ptr_line_count: Current line on panel (rd ptr)
+ * @wr_ptr_line_count: Current line within pp fifo (wr ptr)
+ * @intf_frame_count: Frames read from intf
+ */
+struct dpu_hw_pp_vsync_info {
+ u32 rd_ptr_init_val;
+ u32 rd_ptr_frame_count;
+ u32 rd_ptr_line_count;
+ u32 wr_ptr_line_count;
+ u32 intf_frame_count;
+};
+
#endif /* _DPU_HW_MDSS_H */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c
index def0a87fdba5..90e0e05eff8d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c
@@ -14,24 +14,6 @@
#define MERGE_3D_MUX 0x000
#define MERGE_3D_MODE 0x004
-static const struct dpu_merge_3d_cfg *_merge_3d_offset(enum dpu_merge_3d idx,
- const struct dpu_mdss_cfg *m,
- void __iomem *addr,
- struct dpu_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->merge_3d_count; i++) {
- if (idx == m->merge_3d[i].id) {
- b->blk_addr = addr + m->merge_3d[i].base;
- b->log_mask = DPU_DBG_MASK_PINGPONG;
- return &m->merge_3d[i];
- }
- }
-
- return ERR_PTR(-EINVAL);
-}
-
static void dpu_hw_merge_3d_setup_3d_mode(struct dpu_hw_merge_3d *merge_3d,
enum dpu_3d_blend_mode mode_3d)
{
@@ -55,24 +37,19 @@ static void _setup_merge_3d_ops(struct dpu_hw_merge_3d *c,
c->ops.setup_3d_mode = dpu_hw_merge_3d_setup_3d_mode;
};
-struct dpu_hw_merge_3d *dpu_hw_merge_3d_init(enum dpu_merge_3d idx,
- void __iomem *addr,
- const struct dpu_mdss_cfg *m)
+struct dpu_hw_merge_3d *dpu_hw_merge_3d_init(const struct dpu_merge_3d_cfg *cfg,
+ void __iomem *addr)
{
struct dpu_hw_merge_3d *c;
- const struct dpu_merge_3d_cfg *cfg;
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
- cfg = _merge_3d_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
+ c->hw.blk_addr = addr + cfg->base;
+ c->hw.log_mask = DPU_DBG_MASK_PINGPONG;
- c->idx = idx;
+ c->idx = cfg->id;
c->caps = cfg;
_setup_merge_3d_ops(c, c->caps->features);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
index 81fd1d5f718e..19cec5e88722 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
@@ -46,16 +46,14 @@ static inline struct dpu_hw_merge_3d *to_dpu_hw_merge_3d(struct dpu_hw_blk *hw)
}
/**
- * dpu_hw_merge_3d_init - initializes the merge_3d driver for the passed
- * merge_3d idx.
- * @idx: Pingpong index for which driver object is required
+ * dpu_hw_merge_3d_init() - Initializes the merge_3d driver for the passed
+ * merge3d catalog entry.
+ * @cfg: Pingpong catalog entry for which driver object is required
* @addr: Mapped register io address of MDP
- * @m: Pointer to mdss catalog data
- * Returns: Error code or allocated dpu_hw_merge_3d context
+ * Return: Error code or allocated dpu_hw_merge_3d context
*/
-struct dpu_hw_merge_3d *dpu_hw_merge_3d_init(enum dpu_merge_3d idx,
- void __iomem *addr,
- const struct dpu_mdss_cfg *m);
+struct dpu_hw_merge_3d *dpu_hw_merge_3d_init(const struct dpu_merge_3d_cfg *cfg,
+ void __iomem *addr);
/**
* dpu_hw_merge_3d_destroy - destroys merge_3d driver context
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
index 0fcad9760b6f..437d9e62a841 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
@@ -42,24 +42,6 @@ static u32 dither_depth_map[DITHER_DEPTH_MAP_INDEX] = {
0, 0, 0, 0, 0, 0, 0, 1, 2
};
-static const struct dpu_pingpong_cfg *_pingpong_offset(enum dpu_pingpong pp,
- const struct dpu_mdss_cfg *m,
- void __iomem *addr,
- struct dpu_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->pingpong_count; i++) {
- if (pp == m->pingpong[i].id) {
- b->blk_addr = addr + m->pingpong[i].base;
- b->log_mask = DPU_DBG_MASK_PINGPONG;
- return &m->pingpong[i];
- }
- }
-
- return ERR_PTR(-EINVAL);
-}
-
static void dpu_hw_pp_setup_dither(struct dpu_hw_pingpong *pp,
struct dpu_hw_dither_cfg *cfg)
{
@@ -91,7 +73,7 @@ static void dpu_hw_pp_setup_dither(struct dpu_hw_pingpong *pp,
DPU_REG_WRITE(c, base + PP_DITHER_EN, 1);
}
-static int dpu_hw_pp_setup_te_config(struct dpu_hw_pingpong *pp,
+static int dpu_hw_pp_enable_te(struct dpu_hw_pingpong *pp,
struct dpu_hw_tear_check *te)
{
struct dpu_hw_blk_reg_map *c;
@@ -118,6 +100,8 @@ static int dpu_hw_pp_setup_te_config(struct dpu_hw_pingpong *pp,
DPU_REG_WRITE(c, PP_SYNC_WRCOUNT,
(te->start_pos + te->sync_threshold_start + 1));
+ DPU_REG_WRITE(c, PP_TEAR_CHECK_EN, 1);
+
return 0;
}
@@ -144,24 +128,7 @@ static bool dpu_hw_pp_get_autorefresh_config(struct dpu_hw_pingpong *pp,
return !!((val & BIT(31)) >> 31);
}
-static int dpu_hw_pp_poll_timeout_wr_ptr(struct dpu_hw_pingpong *pp,
- u32 timeout_us)
-{
- struct dpu_hw_blk_reg_map *c;
- u32 val;
- int rc;
-
- if (!pp)
- return -EINVAL;
-
- c = &pp->hw;
- rc = readl_poll_timeout(c->blk_addr + PP_LINE_COUNT,
- val, (val & 0xffff) >= 1, 10, timeout_us);
-
- return rc;
-}
-
-static int dpu_hw_pp_enable_te(struct dpu_hw_pingpong *pp, bool enable)
+static int dpu_hw_pp_disable_te(struct dpu_hw_pingpong *pp)
{
struct dpu_hw_blk_reg_map *c;
@@ -169,7 +136,7 @@ static int dpu_hw_pp_enable_te(struct dpu_hw_pingpong *pp, bool enable)
return -EINVAL;
c = &pp->hw;
- DPU_REG_WRITE(c, PP_TEAR_CHECK_EN, enable);
+ DPU_REG_WRITE(c, PP_TEAR_CHECK_EN, 0);
return 0;
}
@@ -245,6 +212,49 @@ static u32 dpu_hw_pp_get_line_count(struct dpu_hw_pingpong *pp)
return line;
}
+static void dpu_hw_pp_disable_autorefresh(struct dpu_hw_pingpong *pp,
+ uint32_t encoder_id, u16 vdisplay)
+{
+ struct dpu_hw_pp_vsync_info info;
+ int trial = 0;
+
+ /* If autorefresh is already disabled, we have nothing to do */
+ if (!dpu_hw_pp_get_autorefresh_config(pp, NULL))
+ return;
+
+ /*
+ * If autorefresh is enabled, disable it and make sure it is safe to
+ * proceed with current frame commit/push. Sequence followed is,
+ * 1. Disable TE
+ * 2. Disable autorefresh config
+ * 4. Poll for frame transfer ongoing to be false
+ * 5. Enable TE back
+ */
+
+ dpu_hw_pp_connect_external_te(pp, false);
+ dpu_hw_pp_setup_autorefresh_config(pp, 0, false);
+
+ do {
+ udelay(DPU_ENC_MAX_POLL_TIMEOUT_US);
+ if ((trial * DPU_ENC_MAX_POLL_TIMEOUT_US)
+ > (KICKOFF_TIMEOUT_MS * USEC_PER_MSEC)) {
+ DPU_ERROR("enc%d pp%d disable autorefresh failed\n",
+ encoder_id, pp->idx - PINGPONG_0);
+ break;
+ }
+
+ trial++;
+
+ dpu_hw_pp_get_vsync_info(pp, &info);
+ } while (info.wr_ptr_line_count > 0 &&
+ info.wr_ptr_line_count < vdisplay);
+
+ dpu_hw_pp_connect_external_te(pp, true);
+
+ DPU_DEBUG("enc%d pp%d disabled autorefresh\n",
+ encoder_id, pp->idx - PINGPONG_0);
+}
+
static int dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong *pp)
{
struct dpu_hw_blk_reg_map *c = &pp->hw;
@@ -274,40 +284,37 @@ static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp)
static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
unsigned long features)
{
- c->ops.setup_tearcheck = dpu_hw_pp_setup_te_config;
- c->ops.enable_tearcheck = dpu_hw_pp_enable_te;
- c->ops.connect_external_te = dpu_hw_pp_connect_external_te;
- c->ops.get_vsync_info = dpu_hw_pp_get_vsync_info;
- c->ops.setup_autorefresh = dpu_hw_pp_setup_autorefresh_config;
- c->ops.get_autorefresh = dpu_hw_pp_get_autorefresh_config;
- c->ops.poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr;
- c->ops.get_line_count = dpu_hw_pp_get_line_count;
- c->ops.setup_dsc = dpu_hw_pp_setup_dsc;
- c->ops.enable_dsc = dpu_hw_pp_dsc_enable;
- c->ops.disable_dsc = dpu_hw_pp_dsc_disable;
+ if (test_bit(DPU_PINGPONG_TE, &features)) {
+ c->ops.enable_tearcheck = dpu_hw_pp_enable_te;
+ c->ops.disable_tearcheck = dpu_hw_pp_disable_te;
+ c->ops.connect_external_te = dpu_hw_pp_connect_external_te;
+ c->ops.get_line_count = dpu_hw_pp_get_line_count;
+ c->ops.disable_autorefresh = dpu_hw_pp_disable_autorefresh;
+ }
+
+ if (test_bit(DPU_PINGPONG_DSC, &features)) {
+ c->ops.setup_dsc = dpu_hw_pp_setup_dsc;
+ c->ops.enable_dsc = dpu_hw_pp_dsc_enable;
+ c->ops.disable_dsc = dpu_hw_pp_dsc_disable;
+ }
if (test_bit(DPU_PINGPONG_DITHER, &features))
c->ops.setup_dither = dpu_hw_pp_setup_dither;
};
-struct dpu_hw_pingpong *dpu_hw_pingpong_init(enum dpu_pingpong idx,
- void __iomem *addr,
- const struct dpu_mdss_cfg *m)
+struct dpu_hw_pingpong *dpu_hw_pingpong_init(const struct dpu_pingpong_cfg *cfg,
+ void __iomem *addr)
{
struct dpu_hw_pingpong *c;
- const struct dpu_pingpong_cfg *cfg;
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
- cfg = _pingpong_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
+ c->hw.blk_addr = addr + cfg->base;
+ c->hw.log_mask = DPU_DBG_MASK_PINGPONG;
- c->idx = idx;
+ c->idx = cfg->id;
c->caps = cfg;
_setup_pingpong_ops(c, c->caps->features);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index c00223441d99..d3246a9a5808 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -13,28 +13,6 @@
struct dpu_hw_pingpong;
-struct dpu_hw_tear_check {
- /*
- * This is ratio of MDP VSYNC clk freq(Hz) to
- * refresh rate divided by no of lines
- */
- u32 vsync_count;
- u32 sync_cfg_height;
- u32 vsync_init_val;
- u32 sync_threshold_start;
- u32 sync_threshold_continue;
- u32 start_pos;
- u32 rd_ptr_irq;
- u8 hw_vsync_mode;
-};
-
-struct dpu_hw_pp_vsync_info {
- u32 rd_ptr_init_val; /* value of rd pointer at vsync edge */
- u32 rd_ptr_frame_count; /* num frames sent since enabling interface */
- u32 rd_ptr_line_count; /* current line on panel (rd ptr) */
- u32 wr_ptr_line_count; /* current line within pp fifo (wr ptr) */
-};
-
/**
* struct dpu_hw_dither_cfg - dither feature structure
* @flags: for customizing operations
@@ -59,11 +37,8 @@ struct dpu_hw_dither_cfg {
*
* struct dpu_hw_pingpong_ops : Interface to the pingpong Hw driver functions
* Assumption is these functions will be called after clocks are enabled
- * @setup_tearcheck : program tear check values
- * @enable_tearcheck : enables tear check
- * @get_vsync_info : retries timing info of the panel
- * @setup_autorefresh : configure and enable the autorefresh config
- * @get_autorefresh : retrieve autorefresh config from hardware
+ * @enable_tearcheck: program and enable tear check block
+ * @disable_tearcheck: disable able tear check block
* @setup_dither : function to program the dither hw block
* @get_line_count: obtain current vertical line counter
*/
@@ -72,14 +47,13 @@ struct dpu_hw_pingpong_ops {
* enables vysnc generation and sets up init value of
* read pointer and programs the tear check cofiguration
*/
- int (*setup_tearcheck)(struct dpu_hw_pingpong *pp,
+ int (*enable_tearcheck)(struct dpu_hw_pingpong *pp,
struct dpu_hw_tear_check *cfg);
/**
- * enables tear check block
+ * disables tear check block
*/
- int (*enable_tearcheck)(struct dpu_hw_pingpong *pp,
- bool enable);
+ int (*disable_tearcheck)(struct dpu_hw_pingpong *pp);
/**
* read, modify, write to either set or clear listening to external TE
@@ -89,34 +63,14 @@ struct dpu_hw_pingpong_ops {
bool enable_external_te);
/**
- * provides the programmed and current
- * line_count
- */
- int (*get_vsync_info)(struct dpu_hw_pingpong *pp,
- struct dpu_hw_pp_vsync_info *info);
-
- /**
- * configure and enable the autorefresh config
- */
- void (*setup_autorefresh)(struct dpu_hw_pingpong *pp,
- u32 frame_count, bool enable);
-
- /**
- * retrieve autorefresh config from hardware
- */
- bool (*get_autorefresh)(struct dpu_hw_pingpong *pp,
- u32 *frame_count);
-
- /**
- * poll until write pointer transmission starts
- * @Return: 0 on success, -ETIMEDOUT on timeout
+ * Obtain current vertical line counter
*/
- int (*poll_timeout_wr_ptr)(struct dpu_hw_pingpong *pp, u32 timeout_us);
+ u32 (*get_line_count)(struct dpu_hw_pingpong *pp);
/**
- * Obtain current vertical line counter
+ * Disable autorefresh if enabled
*/
- u32 (*get_line_count)(struct dpu_hw_pingpong *pp);
+ void (*disable_autorefresh)(struct dpu_hw_pingpong *pp, uint32_t encoder_id, u16 vdisplay);
/**
* Setup dither matix for pingpong block
@@ -165,16 +119,14 @@ static inline struct dpu_hw_pingpong *to_dpu_hw_pingpong(struct dpu_hw_blk *hw)
}
/**
- * dpu_hw_pingpong_init - initializes the pingpong driver for the passed
- * pingpong idx.
- * @idx: Pingpong index for which driver object is required
+ * dpu_hw_pingpong_init() - initializes the pingpong driver for the passed
+ * pingpong catalog entry.
+ * @cfg: Pingpong catalog entry for which driver object is required
* @addr: Mapped register io address of MDP
- * @m: Pointer to mdss catalog data
- * Returns: Error code or allocated dpu_hw_pingpong context
+ * Return: Error code or allocated dpu_hw_pingpong context
*/
-struct dpu_hw_pingpong *dpu_hw_pingpong_init(enum dpu_pingpong idx,
- void __iomem *addr,
- const struct dpu_mdss_cfg *m);
+struct dpu_hw_pingpong *dpu_hw_pingpong_init(const struct dpu_pingpong_cfg *cfg,
+ void __iomem *addr);
/**
* dpu_hw_pingpong_destroy - destroys pingpong driver context
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index cf70a9bd1034..b364cf75bb3f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -12,7 +12,7 @@
#define DPU_FETCH_CONFIG_RESET_VALUE 0x00000087
-/* DPU_SSPP_SRC */
+/* SSPP registers */
#define SSPP_SRC_SIZE 0x00
#define SSPP_SRC_XY 0x08
#define SSPP_OUT_SIZE 0x0c
@@ -26,45 +26,18 @@
#define SSPP_SRC_FORMAT 0x30
#define SSPP_SRC_UNPACK_PATTERN 0x34
#define SSPP_SRC_OP_MODE 0x38
-
-/* SSPP_MULTIRECT*/
-#define SSPP_SRC_SIZE_REC1 0x16C
-#define SSPP_SRC_XY_REC1 0x168
-#define SSPP_OUT_SIZE_REC1 0x160
-#define SSPP_OUT_XY_REC1 0x164
-#define SSPP_SRC_FORMAT_REC1 0x174
-#define SSPP_SRC_UNPACK_PATTERN_REC1 0x178
-#define SSPP_SRC_OP_MODE_REC1 0x17C
-#define SSPP_MULTIRECT_OPMODE 0x170
-#define SSPP_SRC_CONSTANT_COLOR_REC1 0x180
-#define SSPP_EXCL_REC_SIZE_REC1 0x184
-#define SSPP_EXCL_REC_XY_REC1 0x188
-
-#define MDSS_MDP_OP_DEINTERLACE BIT(22)
-#define MDSS_MDP_OP_DEINTERLACE_ODD BIT(23)
-#define MDSS_MDP_OP_IGC_ROM_1 BIT(18)
-#define MDSS_MDP_OP_IGC_ROM_0 BIT(17)
-#define MDSS_MDP_OP_IGC_EN BIT(16)
-#define MDSS_MDP_OP_FLIP_UD BIT(14)
-#define MDSS_MDP_OP_FLIP_LR BIT(13)
-#define MDSS_MDP_OP_BWC_EN BIT(0)
-#define MDSS_MDP_OP_PE_OVERRIDE BIT(31)
-#define MDSS_MDP_OP_BWC_LOSSLESS (0 << 1)
-#define MDSS_MDP_OP_BWC_Q_HIGH (1 << 1)
-#define MDSS_MDP_OP_BWC_Q_MED (2 << 1)
-
#define SSPP_SRC_CONSTANT_COLOR 0x3c
#define SSPP_EXCL_REC_CTL 0x40
#define SSPP_UBWC_STATIC_CTRL 0x44
-#define SSPP_FETCH_CONFIG 0x048
+#define SSPP_FETCH_CONFIG 0x48
#define SSPP_DANGER_LUT 0x60
#define SSPP_SAFE_LUT 0x64
#define SSPP_CREQ_LUT 0x68
#define SSPP_QOS_CTRL 0x6C
-#define SSPP_DECIMATION_CONFIG 0xB4
#define SSPP_SRC_ADDR_SW_STATUS 0x70
#define SSPP_CREQ_LUT_0 0x74
#define SSPP_CREQ_LUT_1 0x78
+#define SSPP_DECIMATION_CONFIG 0xB4
#define SSPP_SW_PIX_EXT_C0_LR 0x100
#define SSPP_SW_PIX_EXT_C0_TB 0x104
#define SSPP_SW_PIX_EXT_C0_REQ_PIXELS 0x108
@@ -81,11 +54,33 @@
#define SSPP_TRAFFIC_SHAPER_PREFILL 0x150
#define SSPP_TRAFFIC_SHAPER_REC1_PREFILL 0x154
#define SSPP_TRAFFIC_SHAPER_REC1 0x158
+#define SSPP_OUT_SIZE_REC1 0x160
+#define SSPP_OUT_XY_REC1 0x164
+#define SSPP_SRC_XY_REC1 0x168
+#define SSPP_SRC_SIZE_REC1 0x16C
+#define SSPP_MULTIRECT_OPMODE 0x170
+#define SSPP_SRC_FORMAT_REC1 0x174
+#define SSPP_SRC_UNPACK_PATTERN_REC1 0x178
+#define SSPP_SRC_OP_MODE_REC1 0x17C
+#define SSPP_SRC_CONSTANT_COLOR_REC1 0x180
+#define SSPP_EXCL_REC_SIZE_REC1 0x184
+#define SSPP_EXCL_REC_XY_REC1 0x188
#define SSPP_EXCL_REC_SIZE 0x1B4
#define SSPP_EXCL_REC_XY 0x1B8
-#define SSPP_VIG_OP_MODE 0x0
-#define SSPP_VIG_CSC_10_OP_MODE 0x0
-#define SSPP_TRAFFIC_SHAPER_BPC_MAX 0xFF
+
+/* SSPP_SRC_OP_MODE & OP_MODE_REC1 */
+#define MDSS_MDP_OP_DEINTERLACE BIT(22)
+#define MDSS_MDP_OP_DEINTERLACE_ODD BIT(23)
+#define MDSS_MDP_OP_IGC_ROM_1 BIT(18)
+#define MDSS_MDP_OP_IGC_ROM_0 BIT(17)
+#define MDSS_MDP_OP_IGC_EN BIT(16)
+#define MDSS_MDP_OP_FLIP_UD BIT(14)
+#define MDSS_MDP_OP_FLIP_LR BIT(13)
+#define MDSS_MDP_OP_BWC_EN BIT(0)
+#define MDSS_MDP_OP_PE_OVERRIDE BIT(31)
+#define MDSS_MDP_OP_BWC_LOSSLESS (0 << 1)
+#define MDSS_MDP_OP_BWC_Q_HIGH (1 << 1)
+#define MDSS_MDP_OP_BWC_Q_MED (2 << 1)
/* SSPP_QOS_CTRL */
#define SSPP_QOS_CTRL_VBLANK_EN BIT(16)
@@ -96,6 +91,7 @@
#define SSPP_QOS_CTRL_CREQ_VBLANK_OFF 20
/* DPU_SSPP_SCALER_QSEED2 */
+#define SSPP_VIG_OP_MODE 0x0
#define SCALE_CONFIG 0x04
#define COMP0_3_PHASE_STEP_X 0x10
#define COMP0_3_PHASE_STEP_Y 0x14
@@ -107,6 +103,9 @@
#define COMP1_2_INIT_PHASE_Y 0x2C
#define VIG_0_QSEED2_SHARP 0x30
+/* SSPP_TRAFFIC_SHAPER and _REC1 */
+#define SSPP_TRAFFIC_SHAPER_BPC_MAX 0xFF
+
/*
* Definitions for ViG op modes
*/
@@ -128,6 +127,7 @@
/*
* Definitions for CSC 10 op modes
*/
+#define SSPP_VIG_CSC_10_OP_MODE 0x0
#define VIG_CSC_10_SRC_DATAFMT BIT(1)
#define VIG_CSC_10_EN BIT(0)
#define CSC_10BIT_OFFSET 4
@@ -136,45 +136,12 @@
#define TS_CLK 19200000
-static int _sspp_subblk_offset(struct dpu_hw_sspp *ctx,
- int s_id,
- u32 *idx)
-{
- int rc = 0;
- const struct dpu_sspp_sub_blks *sblk;
-
- if (!ctx || !ctx->cap || !ctx->cap->sblk)
- return -EINVAL;
-
- sblk = ctx->cap->sblk;
-
- switch (s_id) {
- case DPU_SSPP_SRC:
- *idx = sblk->src_blk.base;
- break;
- case DPU_SSPP_SCALER_QSEED2:
- case DPU_SSPP_SCALER_QSEED3:
- case DPU_SSPP_SCALER_RGB:
- *idx = sblk->scaler_blk.base;
- break;
- case DPU_SSPP_CSC:
- case DPU_SSPP_CSC_10BIT:
- *idx = sblk->csc_blk.base;
- break;
- default:
- rc = -EINVAL;
- }
-
- return rc;
-}
-
static void dpu_hw_sspp_setup_multirect(struct dpu_sw_pipe *pipe)
{
struct dpu_hw_sspp *ctx = pipe->sspp;
u32 mode_mask;
- u32 idx;
- if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
+ if (!ctx)
return;
if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) {
@@ -185,7 +152,7 @@ static void dpu_hw_sspp_setup_multirect(struct dpu_sw_pipe *pipe)
*/
mode_mask = 0;
} else {
- mode_mask = DPU_REG_READ(&ctx->hw, SSPP_MULTIRECT_OPMODE + idx);
+ mode_mask = DPU_REG_READ(&ctx->hw, SSPP_MULTIRECT_OPMODE);
mode_mask |= pipe->multirect_index;
if (pipe->multirect_mode == DPU_SSPP_MULTIRECT_TIME_MX)
mode_mask |= BIT(2);
@@ -193,46 +160,42 @@ static void dpu_hw_sspp_setup_multirect(struct dpu_sw_pipe *pipe)
mode_mask &= ~BIT(2);
}
- DPU_REG_WRITE(&ctx->hw, SSPP_MULTIRECT_OPMODE + idx, mode_mask);
+ DPU_REG_WRITE(&ctx->hw, SSPP_MULTIRECT_OPMODE, mode_mask);
}
static void _sspp_setup_opmode(struct dpu_hw_sspp *ctx,
u32 mask, u8 en)
{
- u32 idx;
+ const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk;
u32 opmode;
if (!test_bit(DPU_SSPP_SCALER_QSEED2, &ctx->cap->features) ||
- _sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED2, &idx) ||
!test_bit(DPU_SSPP_CSC, &ctx->cap->features))
return;
- opmode = DPU_REG_READ(&ctx->hw, SSPP_VIG_OP_MODE + idx);
+ opmode = DPU_REG_READ(&ctx->hw, sblk->scaler_blk.base + SSPP_VIG_OP_MODE);
if (en)
opmode |= mask;
else
opmode &= ~mask;
- DPU_REG_WRITE(&ctx->hw, SSPP_VIG_OP_MODE + idx, opmode);
+ DPU_REG_WRITE(&ctx->hw, sblk->scaler_blk.base + SSPP_VIG_OP_MODE, opmode);
}
static void _sspp_setup_csc10_opmode(struct dpu_hw_sspp *ctx,
u32 mask, u8 en)
{
- u32 idx;
+ const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk;
u32 opmode;
- if (_sspp_subblk_offset(ctx, DPU_SSPP_CSC_10BIT, &idx))
- return;
-
- opmode = DPU_REG_READ(&ctx->hw, SSPP_VIG_CSC_10_OP_MODE + idx);
+ opmode = DPU_REG_READ(&ctx->hw, sblk->csc_blk.base + SSPP_VIG_CSC_10_OP_MODE);
if (en)
opmode |= mask;
else
opmode &= ~mask;
- DPU_REG_WRITE(&ctx->hw, SSPP_VIG_CSC_10_OP_MODE + idx, opmode);
+ DPU_REG_WRITE(&ctx->hw, sblk->csc_blk.base + SSPP_VIG_CSC_10_OP_MODE, opmode);
}
/*
@@ -247,9 +210,8 @@ static void dpu_hw_sspp_setup_format(struct dpu_sw_pipe *pipe,
u32 opmode = 0;
u32 fast_clear = 0;
u32 op_mode_off, unpack_pat_off, format_off;
- u32 idx;
- if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx) || !fmt)
+ if (!ctx || !fmt)
return;
if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||
@@ -264,7 +226,7 @@ static void dpu_hw_sspp_setup_format(struct dpu_sw_pipe *pipe,
}
c = &ctx->hw;
- opmode = DPU_REG_READ(c, op_mode_off + idx);
+ opmode = DPU_REG_READ(c, op_mode_off);
opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD |
MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE);
@@ -352,12 +314,12 @@ static void dpu_hw_sspp_setup_format(struct dpu_sw_pipe *pipe,
VIG_CSC_10_EN | VIG_CSC_10_SRC_DATAFMT,
DPU_FORMAT_IS_YUV(fmt));
- DPU_REG_WRITE(c, format_off + idx, src_format);
- DPU_REG_WRITE(c, unpack_pat_off + idx, unpack);
- DPU_REG_WRITE(c, op_mode_off + idx, opmode);
+ DPU_REG_WRITE(c, format_off, src_format);
+ DPU_REG_WRITE(c, unpack_pat_off, unpack);
+ DPU_REG_WRITE(c, op_mode_off, opmode);
/* clear previous UBWC error */
- DPU_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS + idx, BIT(31));
+ DPU_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS, BIT(31));
}
static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_sspp *ctx,
@@ -368,9 +330,8 @@ static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_sspp *ctx,
u32 lr_pe[4], tb_pe[4], tot_req_pixels[4];
const u32 bytemask = 0xff;
const u32 shortmask = 0xffff;
- u32 idx;
- if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx) || !pe_ext)
+ if (!ctx || !pe_ext)
return;
c = &ctx->hw;
@@ -400,21 +361,21 @@ static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_sspp *ctx,
}
/* color 0 */
- DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_LR + idx, lr_pe[0]);
- DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_TB + idx, tb_pe[0]);
- DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_REQ_PIXELS + idx,
+ DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_LR, lr_pe[0]);
+ DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_TB, tb_pe[0]);
+ DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_REQ_PIXELS,
tot_req_pixels[0]);
/* color 1 and color 2 */
- DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_LR + idx, lr_pe[1]);
- DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_TB + idx, tb_pe[1]);
- DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS + idx,
+ DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_LR, lr_pe[1]);
+ DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_TB, tb_pe[1]);
+ DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS,
tot_req_pixels[1]);
/* color 3 */
- DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_LR + idx, lr_pe[3]);
- DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_TB + idx, lr_pe[3]);
- DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_REQ_PIXELS + idx,
+ DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_LR, lr_pe[3]);
+ DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_TB, lr_pe[3]);
+ DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_REQ_PIXELS,
tot_req_pixels[3]);
}
@@ -422,25 +383,22 @@ static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_sspp *ctx,
struct dpu_hw_scaler3_cfg *scaler3_cfg,
const struct dpu_format *format)
{
- u32 idx;
-
- if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx)
- || !scaler3_cfg)
+ if (!ctx || !scaler3_cfg)
return;
- dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg, idx,
+ dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg,
+ ctx->cap->sblk->scaler_blk.base,
ctx->cap->sblk->scaler_blk.version,
format);
}
static u32 _dpu_hw_sspp_get_scaler3_ver(struct dpu_hw_sspp *ctx)
{
- u32 idx;
-
- if (!ctx || _sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx))
+ if (!ctx)
return 0;
- return dpu_hw_get_scaler3_ver(&ctx->hw, idx);
+ return dpu_hw_get_scaler3_ver(&ctx->hw,
+ ctx->cap->sblk->scaler_blk.base);
}
/*
@@ -453,9 +411,8 @@ static void dpu_hw_sspp_setup_rects(struct dpu_sw_pipe *pipe,
struct dpu_hw_blk_reg_map *c;
u32 src_size, src_xy, dst_size, dst_xy;
u32 src_size_off, src_xy_off, out_size_off, out_xy_off;
- u32 idx;
- if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx) || !cfg)
+ if (!ctx || !cfg)
return;
c = &ctx->hw;
@@ -483,10 +440,10 @@ static void dpu_hw_sspp_setup_rects(struct dpu_sw_pipe *pipe,
drm_rect_width(&cfg->dst_rect);
/* rectangle register programming */
- DPU_REG_WRITE(c, src_size_off + idx, src_size);
- DPU_REG_WRITE(c, src_xy_off + idx, src_xy);
- DPU_REG_WRITE(c, out_size_off + idx, dst_size);
- DPU_REG_WRITE(c, out_xy_off + idx, dst_xy);
+ DPU_REG_WRITE(c, src_size_off, src_size);
+ DPU_REG_WRITE(c, src_xy_off, src_xy);
+ DPU_REG_WRITE(c, out_size_off, dst_size);
+ DPU_REG_WRITE(c, out_xy_off, dst_xy);
}
static void dpu_hw_sspp_setup_sourceaddress(struct dpu_sw_pipe *pipe,
@@ -495,24 +452,23 @@ static void dpu_hw_sspp_setup_sourceaddress(struct dpu_sw_pipe *pipe,
struct dpu_hw_sspp *ctx = pipe->sspp;
u32 ystride0, ystride1;
int i;
- u32 idx;
- if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
+ if (!ctx)
return;
if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) {
for (i = 0; i < ARRAY_SIZE(layout->plane_addr); i++)
- DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + idx + i * 0x4,
+ DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + i * 0x4,
layout->plane_addr[i]);
} else if (pipe->multirect_index == DPU_SSPP_RECT_0) {
- DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + idx,
+ DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR,
layout->plane_addr[0]);
- DPU_REG_WRITE(&ctx->hw, SSPP_SRC2_ADDR + idx,
+ DPU_REG_WRITE(&ctx->hw, SSPP_SRC2_ADDR,
layout->plane_addr[2]);
} else {
- DPU_REG_WRITE(&ctx->hw, SSPP_SRC1_ADDR + idx,
+ DPU_REG_WRITE(&ctx->hw, SSPP_SRC1_ADDR,
layout->plane_addr[0]);
- DPU_REG_WRITE(&ctx->hw, SSPP_SRC3_ADDR + idx,
+ DPU_REG_WRITE(&ctx->hw, SSPP_SRC3_ADDR,
layout->plane_addr[2]);
}
@@ -522,8 +478,8 @@ static void dpu_hw_sspp_setup_sourceaddress(struct dpu_sw_pipe *pipe,
ystride1 = (layout->plane_pitch[2]) |
(layout->plane_pitch[3] << 16);
} else {
- ystride0 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE0 + idx);
- ystride1 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE1 + idx);
+ ystride0 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE0);
+ ystride1 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE1);
if (pipe->multirect_index == DPU_SSPP_RECT_0) {
ystride0 = (ystride0 & 0xFFFF0000) |
@@ -540,34 +496,35 @@ static void dpu_hw_sspp_setup_sourceaddress(struct dpu_sw_pipe *pipe,
}
}
- DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE0 + idx, ystride0);
- DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE1 + idx, ystride1);
+ DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE0, ystride0);
+ DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE1, ystride1);
}
static void dpu_hw_sspp_setup_csc(struct dpu_hw_sspp *ctx,
const struct dpu_csc_cfg *data)
{
- u32 idx;
+ u32 offset;
bool csc10 = false;
- if (_sspp_subblk_offset(ctx, DPU_SSPP_CSC, &idx) || !data)
+ if (!ctx || !data)
return;
+ offset = ctx->cap->sblk->csc_blk.base;
+
if (test_bit(DPU_SSPP_CSC_10BIT, &ctx->cap->features)) {
- idx += CSC_10BIT_OFFSET;
+ offset += CSC_10BIT_OFFSET;
csc10 = true;
}
- dpu_hw_csc_setup(&ctx->hw, idx, data, csc10);
+ dpu_hw_csc_setup(&ctx->hw, offset, data, csc10);
}
static void dpu_hw_sspp_setup_solidfill(struct dpu_sw_pipe *pipe, u32 color)
{
struct dpu_hw_sspp *ctx = pipe->sspp;
struct dpu_hw_fmt_layout cfg;
- u32 idx;
- if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
+ if (!ctx)
return;
/* cleanup source addresses */
@@ -576,79 +533,41 @@ static void dpu_hw_sspp_setup_solidfill(struct dpu_sw_pipe *pipe, u32 color)
if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||
pipe->multirect_index == DPU_SSPP_RECT_0)
- DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR + idx, color);
+ DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR, color);
else
- DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR_REC1 + idx,
+ DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR_REC1,
color);
}
-static void dpu_hw_sspp_setup_danger_safe_lut(struct dpu_hw_sspp *ctx,
- u32 danger_lut,
- u32 safe_lut)
+static void dpu_hw_sspp_setup_qos_lut(struct dpu_hw_sspp *ctx,
+ struct dpu_hw_qos_cfg *cfg)
{
- u32 idx;
-
- if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
- return;
-
- DPU_REG_WRITE(&ctx->hw, SSPP_DANGER_LUT + idx, danger_lut);
- DPU_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT + idx, safe_lut);
-}
-
-static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_sspp *ctx,
- u64 creq_lut)
-{
- u32 idx;
-
- if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
+ if (!ctx || !cfg)
return;
- if (ctx->cap && test_bit(DPU_SSPP_QOS_8LVL, &ctx->cap->features)) {
- DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT_0 + idx, creq_lut);
- DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT_1 + idx,
- creq_lut >> 32);
- } else {
- DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT + idx, creq_lut);
- }
+ _dpu_hw_setup_qos_lut(&ctx->hw, SSPP_DANGER_LUT,
+ test_bit(DPU_SSPP_QOS_8LVL, &ctx->cap->features),
+ cfg);
}
static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_sspp *ctx,
- struct dpu_hw_pipe_qos_cfg *cfg)
+ bool danger_safe_en)
{
- u32 idx;
- u32 qos_ctrl = 0;
-
- if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
+ if (!ctx)
return;
- if (cfg->vblank_en) {
- qos_ctrl |= ((cfg->creq_vblank &
- SSPP_QOS_CTRL_CREQ_VBLANK_MASK) <<
- SSPP_QOS_CTRL_CREQ_VBLANK_OFF);
- qos_ctrl |= ((cfg->danger_vblank &
- SSPP_QOS_CTRL_DANGER_VBLANK_MASK) <<
- SSPP_QOS_CTRL_DANGER_VBLANK_OFF);
- qos_ctrl |= SSPP_QOS_CTRL_VBLANK_EN;
- }
-
- if (cfg->danger_safe_en)
- qos_ctrl |= SSPP_QOS_CTRL_DANGER_SAFE_EN;
-
- DPU_REG_WRITE(&ctx->hw, SSPP_QOS_CTRL + idx, qos_ctrl);
+ DPU_REG_WRITE(&ctx->hw, SSPP_QOS_CTRL,
+ danger_safe_en ? SSPP_QOS_CTRL_DANGER_SAFE_EN : 0);
}
static void dpu_hw_sspp_setup_cdp(struct dpu_sw_pipe *pipe,
- struct dpu_hw_cdp_cfg *cfg)
+ const struct dpu_format *fmt,
+ bool enable)
{
struct dpu_hw_sspp *ctx = pipe->sspp;
- u32 idx;
- u32 cdp_cntl = 0;
u32 cdp_cntl_offset = 0;
- if (!ctx || !cfg)
- return;
-
- if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
+ if (!ctx)
return;
if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||
@@ -657,33 +576,20 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_sw_pipe *pipe,
else
cdp_cntl_offset = SSPP_CDP_CNTL_REC1;
- if (cfg->enable)
- cdp_cntl |= BIT(0);
- if (cfg->ubwc_meta_enable)
- cdp_cntl |= BIT(1);
- if (cfg->tile_amortize_enable)
- cdp_cntl |= BIT(2);
- if (cfg->preload_ahead == DPU_SSPP_CDP_PRELOAD_AHEAD_64)
- cdp_cntl |= BIT(3);
-
- DPU_REG_WRITE(&ctx->hw, cdp_cntl_offset, cdp_cntl);
+ dpu_setup_cdp(&ctx->hw, cdp_cntl_offset, fmt, enable);
}
static void _setup_layer_ops(struct dpu_hw_sspp *c,
unsigned long features)
{
- if (test_bit(DPU_SSPP_SRC, &features)) {
- c->ops.setup_format = dpu_hw_sspp_setup_format;
- c->ops.setup_rects = dpu_hw_sspp_setup_rects;
- c->ops.setup_sourceaddress = dpu_hw_sspp_setup_sourceaddress;
- c->ops.setup_solidfill = dpu_hw_sspp_setup_solidfill;
- c->ops.setup_pe = dpu_hw_sspp_setup_pe_config;
- }
+ c->ops.setup_format = dpu_hw_sspp_setup_format;
+ c->ops.setup_rects = dpu_hw_sspp_setup_rects;
+ c->ops.setup_sourceaddress = dpu_hw_sspp_setup_sourceaddress;
+ c->ops.setup_solidfill = dpu_hw_sspp_setup_solidfill;
+ c->ops.setup_pe = dpu_hw_sspp_setup_pe_config;
if (test_bit(DPU_SSPP_QOS, &features)) {
- c->ops.setup_danger_safe_lut =
- dpu_hw_sspp_setup_danger_safe_lut;
- c->ops.setup_creq_lut = dpu_hw_sspp_setup_creq_lut;
+ c->ops.setup_qos_lut = dpu_hw_sspp_setup_qos_lut;
c->ops.setup_qos_ctrl = dpu_hw_sspp_setup_qos_ctrl;
}
@@ -728,8 +634,8 @@ int _dpu_hw_sspp_init_debugfs(struct dpu_hw_sspp *hw_pipe, struct dpu_kms *kms,
/* add register dump support */
dpu_debugfs_create_regset32("src_blk", 0400,
debugfs_root,
- sblk->src_blk.base + cfg->base,
- sblk->src_blk.len,
+ cfg->base,
+ cfg->len,
kms);
if (cfg->features & BIT(DPU_SSPP_SCALER_QSEED3) ||
@@ -758,63 +664,29 @@ int _dpu_hw_sspp_init_debugfs(struct dpu_hw_sspp *hw_pipe, struct dpu_kms *kms,
0400,
debugfs_root,
(u32 *) &cfg->clk_ctrl);
- debugfs_create_x32("creq_vblank",
- 0600,
- debugfs_root,
- (u32 *) &sblk->creq_vblank);
- debugfs_create_x32("danger_vblank",
- 0600,
- debugfs_root,
- (u32 *) &sblk->danger_vblank);
return 0;
}
#endif
-
-static const struct dpu_sspp_cfg *_sspp_offset(enum dpu_sspp sspp,
- void __iomem *addr,
- const struct dpu_mdss_cfg *catalog,
- struct dpu_hw_blk_reg_map *b)
-{
- int i;
-
- if ((sspp < SSPP_MAX) && catalog && addr && b) {
- for (i = 0; i < catalog->sspp_count; i++) {
- if (sspp == catalog->sspp[i].id) {
- b->blk_addr = addr + catalog->sspp[i].base;
- b->log_mask = DPU_DBG_MASK_SSPP;
- return &catalog->sspp[i];
- }
- }
- }
-
- return ERR_PTR(-ENOMEM);
-}
-
-struct dpu_hw_sspp *dpu_hw_sspp_init(enum dpu_sspp idx,
- void __iomem *addr, const struct dpu_mdss_cfg *catalog)
+struct dpu_hw_sspp *dpu_hw_sspp_init(const struct dpu_sspp_cfg *cfg,
+ void __iomem *addr, const struct dpu_ubwc_cfg *ubwc)
{
struct dpu_hw_sspp *hw_pipe;
- const struct dpu_sspp_cfg *cfg;
- if (!addr || !catalog)
+ if (!addr || !ubwc)
return ERR_PTR(-EINVAL);
hw_pipe = kzalloc(sizeof(*hw_pipe), GFP_KERNEL);
if (!hw_pipe)
return ERR_PTR(-ENOMEM);
- cfg = _sspp_offset(idx, addr, catalog, &hw_pipe->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(hw_pipe);
- return ERR_PTR(-EINVAL);
- }
+ hw_pipe->hw.blk_addr = addr + cfg->base;
+ hw_pipe->hw.log_mask = DPU_DBG_MASK_SSPP;
/* Assign ops */
- hw_pipe->catalog = catalog;
- hw_pipe->ubwc = catalog->ubwc;
- hw_pipe->idx = idx;
+ hw_pipe->ubwc = ubwc;
+ hw_pipe->idx = cfg->id;
hw_pipe->cap = cfg;
_setup_layer_ops(hw_pipe, hw_pipe->cap->features);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index 74b98b6b3bc3..085f34bc6b88 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -164,28 +164,6 @@ struct dpu_sw_pipe_cfg {
};
/**
- * struct dpu_hw_pipe_qos_cfg : Source pipe QoS configuration
- * @creq_vblank: creq value generated to vbif during vertical blanking
- * @danger_vblank: danger value generated during vertical blanking
- * @vblank_en: enable creq_vblank and danger_vblank during vblank
- * @danger_safe_en: enable danger safe generation
- */
-struct dpu_hw_pipe_qos_cfg {
- u32 creq_vblank;
- u32 danger_vblank;
- bool vblank_en;
- bool danger_safe_en;
-};
-
-/**
- * enum CDP preload ahead address size
- */
-enum {
- DPU_SSPP_CDP_PRELOAD_AHEAD_32,
- DPU_SSPP_CDP_PRELOAD_AHEAD_64
-};
-
-/**
* struct dpu_hw_pipe_ts_cfg - traffic shaper configuration
* @size: size to prefill in bytes, or zero to disable
* @time: time to prefill in usec, or zero to disable
@@ -276,34 +254,22 @@ struct dpu_hw_sspp_ops {
void (*setup_sharpening)(struct dpu_hw_sspp *ctx,
struct dpu_hw_sharp_cfg *cfg);
- /**
- * setup_danger_safe_lut - setup danger safe LUTs
- * @ctx: Pointer to pipe context
- * @danger_lut: LUT for generate danger level based on fill level
- * @safe_lut: LUT for generate safe level based on fill level
- *
- */
- void (*setup_danger_safe_lut)(struct dpu_hw_sspp *ctx,
- u32 danger_lut,
- u32 safe_lut);
/**
- * setup_creq_lut - setup CREQ LUT
+ * setup_qos_lut - setup QoS LUTs
* @ctx: Pointer to pipe context
- * @creq_lut: LUT for generate creq level based on fill level
- *
+ * @cfg: LUT configuration
*/
- void (*setup_creq_lut)(struct dpu_hw_sspp *ctx,
- u64 creq_lut);
+ void (*setup_qos_lut)(struct dpu_hw_sspp *ctx,
+ struct dpu_hw_qos_cfg *cfg);
/**
* setup_qos_ctrl - setup QoS control
* @ctx: Pointer to pipe context
- * @cfg: Pointer to pipe QoS configuration
- *
+ * @danger_safe_en: flags controlling enabling of danger/safe QoS/LUT
*/
void (*setup_qos_ctrl)(struct dpu_hw_sspp *ctx,
- struct dpu_hw_pipe_qos_cfg *cfg);
+ bool danger_safe_en);
/**
* setup_histogram - setup histograms
@@ -331,18 +297,19 @@ struct dpu_hw_sspp_ops {
/**
* setup_cdp - setup client driven prefetch
* @pipe: Pointer to software pipe context
- * @cfg: Pointer to cdp configuration
+ * @fmt: format used by the sw pipe
+ * @enable: whether the CDP should be enabled for this pipe
*/
void (*setup_cdp)(struct dpu_sw_pipe *pipe,
- struct dpu_hw_cdp_cfg *cfg);
+ const struct dpu_format *fmt,
+ bool enable);
};
/**
* struct dpu_hw_sspp - pipe description
* @base: hardware block base structure
* @hw: block hardware details
- * @catalog: back pointer to catalog
- * @ubwc: ubwc configuration data
+ * @ubwc: UBWC configuration data
* @idx: pipe index
* @cap: pointer to layer_cfg
* @ops: pointer to operations possible for this pipe
@@ -350,7 +317,6 @@ struct dpu_hw_sspp_ops {
struct dpu_hw_sspp {
struct dpu_hw_blk base;
struct dpu_hw_blk_reg_map hw;
- const struct dpu_mdss_cfg *catalog;
const struct dpu_ubwc_cfg *ubwc;
/* Pipe */
@@ -363,14 +329,14 @@ struct dpu_hw_sspp {
struct dpu_kms;
/**
- * dpu_hw_sspp_init - initializes the sspp hw driver object.
+ * dpu_hw_sspp_init() - Initializes the sspp hw driver object.
* Should be called once before accessing every pipe.
- * @idx: Pipe index for which driver object is required
+ * @cfg: Pipe catalog entry for which driver object is required
* @addr: Mapped register io address of MDP
- * @catalog : Pointer to mdss catalog data
+ * @ubwc: UBWC configuration data
*/
-struct dpu_hw_sspp *dpu_hw_sspp_init(enum dpu_sspp idx,
- void __iomem *addr, const struct dpu_mdss_cfg *catalog);
+struct dpu_hw_sspp *dpu_hw_sspp_init(const struct dpu_sspp_cfg *cfg,
+ void __iomem *addr, const struct dpu_ubwc_cfg *ubwc);
/**
* dpu_hw_sspp_destroy(): Destroys SSPP driver context
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
index 2bb02e17ee52..963bdb5e0252 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
@@ -130,24 +130,12 @@ static void dpu_hw_setup_vsync_source(struct dpu_hw_mdp *mdp,
struct dpu_vsync_source_cfg *cfg)
{
struct dpu_hw_blk_reg_map *c;
- u32 reg, wd_load_value, wd_ctl, wd_ctl2, i;
- static const u32 pp_offset[PINGPONG_MAX] = {0xC, 0x8, 0x4, 0x13, 0x18};
+ u32 reg, wd_load_value, wd_ctl, wd_ctl2;
- if (!mdp || !cfg || (cfg->pp_count > ARRAY_SIZE(cfg->ppnumber)))
+ if (!mdp || !cfg)
return;
c = &mdp->hw;
- reg = DPU_REG_READ(c, MDP_VSYNC_SEL);
- for (i = 0; i < cfg->pp_count; i++) {
- int pp_idx = cfg->ppnumber[i] - PINGPONG_0;
-
- if (pp_idx >= ARRAY_SIZE(pp_offset))
- continue;
-
- reg &= ~(0xf << pp_offset[pp_idx]);
- reg |= (cfg->vsync_source & 0xf) << pp_offset[pp_idx];
- }
- DPU_REG_WRITE(c, MDP_VSYNC_SEL, reg);
if (cfg->vsync_source >= DPU_VSYNC_SOURCE_WD_TIMER_4 &&
cfg->vsync_source <= DPU_VSYNC_SOURCE_WD_TIMER_0) {
@@ -194,6 +182,33 @@ static void dpu_hw_setup_vsync_source(struct dpu_hw_mdp *mdp,
}
}
+static void dpu_hw_setup_vsync_source_and_vsync_sel(struct dpu_hw_mdp *mdp,
+ struct dpu_vsync_source_cfg *cfg)
+{
+ struct dpu_hw_blk_reg_map *c;
+ u32 reg, i;
+ static const u32 pp_offset[PINGPONG_MAX] = {0xC, 0x8, 0x4, 0x13, 0x18};
+
+ if (!mdp || !cfg || (cfg->pp_count > ARRAY_SIZE(cfg->ppnumber)))
+ return;
+
+ c = &mdp->hw;
+
+ reg = DPU_REG_READ(c, MDP_VSYNC_SEL);
+ for (i = 0; i < cfg->pp_count; i++) {
+ int pp_idx = cfg->ppnumber[i] - PINGPONG_0;
+
+ if (pp_idx >= ARRAY_SIZE(pp_offset))
+ continue;
+
+ reg &= ~(0xf << pp_offset[pp_idx]);
+ reg |= (cfg->vsync_source & 0xf) << pp_offset[pp_idx];
+ }
+ DPU_REG_WRITE(c, MDP_VSYNC_SEL, reg);
+
+ dpu_hw_setup_vsync_source(mdp, cfg);
+}
+
static void dpu_hw_get_safe_status(struct dpu_hw_mdp *mdp,
struct dpu_danger_safe_status *status)
{
@@ -241,7 +256,12 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops,
ops->setup_split_pipe = dpu_hw_setup_split_pipe;
ops->setup_clk_force_ctrl = dpu_hw_setup_clk_force_ctrl;
ops->get_danger_status = dpu_hw_get_danger_status;
- ops->setup_vsync_source = dpu_hw_setup_vsync_source;
+
+ if (cap & BIT(DPU_MDP_VSYNC_SEL))
+ ops->setup_vsync_source = dpu_hw_setup_vsync_source_and_vsync_sel;
+ else
+ ops->setup_vsync_source = dpu_hw_setup_vsync_source;
+
ops->get_safe_status = dpu_hw_get_safe_status;
if (cap & BIT(DPU_MDP_AUDIO_SELECT))
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
index 8062228eada6..9d2273fd2fed 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
@@ -73,6 +73,19 @@ static u32 dpu_hw_util_log_mask = DPU_DBG_MASK_NONE;
#define QSEED3LITE_SEP_LUT_SIZE \
(QSEED3LITE_LUT_SIZE * QSEED3LITE_SEPARABLE_LUTS * sizeof(u32))
+/* QOS_LUT */
+#define QOS_DANGER_LUT 0x00
+#define QOS_SAFE_LUT 0x04
+#define QOS_CREQ_LUT 0x08
+#define QOS_QOS_CTRL 0x0C
+#define QOS_CREQ_LUT_0 0x14
+#define QOS_CREQ_LUT_1 0x18
+
+/* QOS_QOS_CTRL */
+#define QOS_QOS_CTRL_DANGER_SAFE_EN BIT(0)
+#define QOS_QOS_CTRL_DANGER_VBLANK_MASK GENMASK(5, 4)
+#define QOS_QOS_CTRL_VBLANK_EN BIT(16)
+#define QOS_QOS_CTRL_CREQ_VBLANK_MASK GENMASK(21, 20)
void dpu_reg_write(struct dpu_hw_blk_reg_map *c,
u32 reg_off,
@@ -450,6 +463,24 @@ u64 _dpu_hw_get_qos_lut(const struct dpu_qos_lut_tbl *tbl,
return 0;
}
+void _dpu_hw_setup_qos_lut(struct dpu_hw_blk_reg_map *c, u32 offset,
+ bool qos_8lvl,
+ const struct dpu_hw_qos_cfg *cfg)
+{
+ DPU_REG_WRITE(c, offset + QOS_DANGER_LUT, cfg->danger_lut);
+ DPU_REG_WRITE(c, offset + QOS_SAFE_LUT, cfg->safe_lut);
+
+ if (qos_8lvl) {
+ DPU_REG_WRITE(c, offset + QOS_CREQ_LUT_0, cfg->creq_lut);
+ DPU_REG_WRITE(c, offset + QOS_CREQ_LUT_1, cfg->creq_lut >> 32);
+ } else {
+ DPU_REG_WRITE(c, offset + QOS_CREQ_LUT, cfg->creq_lut);
+ }
+
+ DPU_REG_WRITE(c, offset + QOS_QOS_CTRL,
+ cfg->danger_safe_en ? QOS_QOS_CTRL_DANGER_SAFE_EN : 0);
+}
+
void dpu_hw_setup_misr(struct dpu_hw_blk_reg_map *c,
u32 misr_ctrl_offset,
bool enable, u32 frame_count)
@@ -494,3 +525,24 @@ int dpu_hw_collect_misr(struct dpu_hw_blk_reg_map *c,
return 0;
}
+
+#define CDP_ENABLE BIT(0)
+#define CDP_UBWC_META_ENABLE BIT(1)
+#define CDP_TILE_AMORTIZE_ENABLE BIT(2)
+#define CDP_PRELOAD_AHEAD_64 BIT(3)
+
+void dpu_setup_cdp(struct dpu_hw_blk_reg_map *c, u32 offset,
+ const struct dpu_format *fmt, bool enable)
+{
+ u32 cdp_cntl = CDP_PRELOAD_AHEAD_64;
+
+ if (enable)
+ cdp_cntl |= CDP_ENABLE;
+ if (DPU_FORMAT_IS_UBWC(fmt))
+ cdp_cntl |= CDP_UBWC_META_ENABLE;
+ if (DPU_FORMAT_IS_UBWC(fmt) ||
+ DPU_FORMAT_IS_TILE(fmt))
+ cdp_cntl |= CDP_TILE_AMORTIZE_ENABLE;
+
+ DPU_REG_WRITE(c, offset, cdp_cntl);
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
index 27f4c39e35ab..1f6079f47071 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
@@ -306,19 +306,20 @@ struct dpu_drm_scaler_v2 {
};
/**
- * struct dpu_hw_cdp_cfg : CDP configuration
- * @enable: true to enable CDP
- * @ubwc_meta_enable: true to enable ubwc metadata preload
- * @tile_amortize_enable: true to enable amortization control for tile format
- * @preload_ahead: number of request to preload ahead
- * DPU_*_CDP_PRELOAD_AHEAD_32,
- * DPU_*_CDP_PRELOAD_AHEAD_64
+ * struct dpu_hw_qos_cfg: pipe QoS configuration
+ * @danger_lut: LUT for generate danger level based on fill level
+ * @safe_lut: LUT for generate safe level based on fill level
+ * @creq_lut: LUT for generate creq level based on fill level
+ * @creq_vblank: creq value generated to vbif during vertical blanking
+ * @danger_vblank: danger value generated during vertical blanking
+ * @vblank_en: enable creq_vblank and danger_vblank during vblank
+ * @danger_safe_en: enable danger safe generation
*/
-struct dpu_hw_cdp_cfg {
- bool enable;
- bool ubwc_meta_enable;
- bool tile_amortize_enable;
- u32 preload_ahead;
+struct dpu_hw_qos_cfg {
+ u32 danger_lut;
+ u32 safe_lut;
+ u64 creq_lut;
+ bool danger_safe_en;
};
u32 *dpu_hw_util_get_log_mask_ptr(void);
@@ -346,9 +347,16 @@ void dpu_hw_csc_setup(struct dpu_hw_blk_reg_map *c,
u32 csc_reg_off,
const struct dpu_csc_cfg *data, bool csc10);
+void dpu_setup_cdp(struct dpu_hw_blk_reg_map *c, u32 offset,
+ const struct dpu_format *fmt, bool enable);
+
u64 _dpu_hw_get_qos_lut(const struct dpu_qos_lut_tbl *tbl,
u32 total_fl);
+void _dpu_hw_setup_qos_lut(struct dpu_hw_blk_reg_map *c, u32 offset,
+ bool qos_8lvl,
+ const struct dpu_hw_qos_cfg *cfg);
+
void dpu_hw_setup_misr(struct dpu_hw_blk_reg_map *c,
u32 misr_ctrl_offset,
bool enable,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
index 16c56e240706..a5121a50b2bb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
@@ -211,45 +211,22 @@ static void _setup_vbif_ops(struct dpu_hw_vbif_ops *ops,
ops->set_write_gather_en = dpu_hw_set_write_gather_en;
}
-static const struct dpu_vbif_cfg *_top_offset(enum dpu_vbif vbif,
- const struct dpu_mdss_cfg *m,
- void __iomem *addr,
- struct dpu_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->vbif_count; i++) {
- if (vbif == m->vbif[i].id) {
- b->blk_addr = addr + m->vbif[i].base;
- b->log_mask = DPU_DBG_MASK_VBIF;
- return &m->vbif[i];
- }
- }
-
- return ERR_PTR(-EINVAL);
-}
-
-struct dpu_hw_vbif *dpu_hw_vbif_init(enum dpu_vbif idx,
- void __iomem *addr,
- const struct dpu_mdss_cfg *m)
+struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg,
+ void __iomem *addr)
{
struct dpu_hw_vbif *c;
- const struct dpu_vbif_cfg *cfg;
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
- cfg = _top_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
+ c->hw.blk_addr = addr + cfg->base;
+ c->hw.log_mask = DPU_DBG_MASK_VBIF;
/*
* Assign ops
*/
- c->idx = idx;
+ c->idx = cfg->id;
c->cap = cfg;
_setup_vbif_ops(&c->ops, c->cap->features);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
index 6417aa28d32c..7e10d2a172b4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
@@ -106,14 +106,13 @@ struct dpu_hw_vbif {
};
/**
- * dpu_hw_vbif_init - initializes the vbif driver for the passed interface idx
- * @idx: Interface index for which driver object is required
+ * dpu_hw_vbif_init() - Initializes the VBIF driver for the passed
+ * VBIF catalog entry.
+ * @cfg: VBIF catalog entry for which driver object is required
* @addr: Mapped register io address of MDSS
- * @m: Pointer to mdss catalog data
*/
-struct dpu_hw_vbif *dpu_hw_vbif_init(enum dpu_vbif idx,
- void __iomem *addr,
- const struct dpu_mdss_cfg *m);
+struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg,
+ void __iomem *addr);
void dpu_hw_vbif_destroy(struct dpu_hw_vbif *vbif);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
index a3e413d27717..ebc416400382 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
@@ -49,25 +49,6 @@
#define WB_OUT_IMAGE_SIZE 0x2C0
#define WB_OUT_XY 0x2C4
-/* WB_QOS_CTRL */
-#define WB_QOS_CTRL_DANGER_SAFE_EN BIT(0)
-
-static const struct dpu_wb_cfg *_wb_offset(enum dpu_wb wb,
- const struct dpu_mdss_cfg *m, void __iomem *addr,
- struct dpu_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->wb_count; i++) {
- if (wb == m->wb[i].id) {
- b->blk_addr = addr + m->wb[i].base;
- b->log_mask = DPU_DBG_MASK_WB;
- return &m->wb[i];
- }
- }
- return ERR_PTR(-EINVAL);
-}
-
static void dpu_hw_wb_setup_outaddress(struct dpu_hw_wb *ctx,
struct dpu_hw_wb_cfg *data)
{
@@ -151,58 +132,29 @@ static void dpu_hw_wb_roi(struct dpu_hw_wb *ctx, struct dpu_hw_wb_cfg *wb)
}
static void dpu_hw_wb_setup_qos_lut(struct dpu_hw_wb *ctx,
- struct dpu_hw_wb_qos_cfg *cfg)
+ struct dpu_hw_qos_cfg *cfg)
{
- struct dpu_hw_blk_reg_map *c = &ctx->hw;
- u32 qos_ctrl = 0;
-
if (!ctx || !cfg)
return;
- DPU_REG_WRITE(c, WB_DANGER_LUT, cfg->danger_lut);
- DPU_REG_WRITE(c, WB_SAFE_LUT, cfg->safe_lut);
-
- /*
- * for chipsets not using DPU_WB_QOS_8LVL but still using DPU
- * driver such as msm8998, the reset value of WB_CREQ_LUT is
- * sufficient for writeback to work. SW doesn't need to explicitly
- * program a value.
- */
- if (ctx->caps && test_bit(DPU_WB_QOS_8LVL, &ctx->caps->features)) {
- DPU_REG_WRITE(c, WB_CREQ_LUT_0, cfg->creq_lut);
- DPU_REG_WRITE(c, WB_CREQ_LUT_1, cfg->creq_lut >> 32);
- }
-
- if (cfg->danger_safe_en)
- qos_ctrl |= WB_QOS_CTRL_DANGER_SAFE_EN;
-
- DPU_REG_WRITE(c, WB_QOS_CTRL, qos_ctrl);
+ _dpu_hw_setup_qos_lut(&ctx->hw, WB_DANGER_LUT,
+ test_bit(DPU_WB_QOS_8LVL, &ctx->caps->features),
+ cfg);
}
static void dpu_hw_wb_setup_cdp(struct dpu_hw_wb *ctx,
- struct dpu_hw_cdp_cfg *cfg)
+ const struct dpu_format *fmt,
+ bool enable)
{
- struct dpu_hw_blk_reg_map *c;
- u32 cdp_cntl = 0;
-
- if (!ctx || !cfg)
+ if (!ctx)
return;
- c = &ctx->hw;
-
- if (cfg->enable)
- cdp_cntl |= BIT(0);
- if (cfg->ubwc_meta_enable)
- cdp_cntl |= BIT(1);
- if (cfg->preload_ahead == DPU_WB_CDP_PRELOAD_AHEAD_64)
- cdp_cntl |= BIT(3);
-
- DPU_REG_WRITE(c, WB_CDP_CNTL, cdp_cntl);
+ dpu_setup_cdp(&ctx->hw, WB_CDP_CNTL, fmt, enable);
}
static void dpu_hw_wb_bind_pingpong_blk(
struct dpu_hw_wb *ctx,
- bool enable, const enum dpu_pingpong pp)
+ const enum dpu_pingpong pp)
{
struct dpu_hw_blk_reg_map *c;
int mux_cfg;
@@ -215,7 +167,7 @@ static void dpu_hw_wb_bind_pingpong_blk(
mux_cfg = DPU_REG_READ(c, WB_MUX);
mux_cfg &= ~0xf;
- if (enable)
+ if (pp)
mux_cfg |= (pp - PINGPONG_0) & 0x7;
else
mux_cfg |= 0xf;
@@ -242,29 +194,23 @@ static void _setup_wb_ops(struct dpu_hw_wb_ops *ops,
ops->bind_pingpong_blk = dpu_hw_wb_bind_pingpong_blk;
}
-struct dpu_hw_wb *dpu_hw_wb_init(enum dpu_wb idx,
- void __iomem *addr, const struct dpu_mdss_cfg *m)
+struct dpu_hw_wb *dpu_hw_wb_init(const struct dpu_wb_cfg *cfg,
+ void __iomem *addr)
{
struct dpu_hw_wb *c;
- const struct dpu_wb_cfg *cfg;
- if (!addr || !m)
+ if (!addr)
return ERR_PTR(-EINVAL);
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
- cfg = _wb_offset(idx, m, addr, &c->hw);
- if (IS_ERR(cfg)) {
- WARN(1, "Unable to find wb idx=%d\n", idx);
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
+ c->hw.blk_addr = addr + cfg->base;
+ c->hw.log_mask = DPU_DBG_MASK_WB;
/* Assign ops */
- c->mdp = &m->mdp[0];
- c->idx = idx;
+ c->idx = cfg->id;
c->caps = cfg;
_setup_wb_ops(&c->ops, c->caps->features);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
index 3ff5a48541e2..2d7db2efa3d0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
@@ -22,28 +22,6 @@ struct dpu_hw_wb_cfg {
};
/**
- * enum CDP preload ahead address size
- */
-enum {
- DPU_WB_CDP_PRELOAD_AHEAD_32,
- DPU_WB_CDP_PRELOAD_AHEAD_64
-};
-
-/**
- * struct dpu_hw_wb_qos_cfg : Writeback pipe QoS configuration
- * @danger_lut: LUT for generate danger level based on fill level
- * @safe_lut: LUT for generate safe level based on fill level
- * @creq_lut: LUT for generate creq level based on fill level
- * @danger_safe_en: enable danger safe generation
- */
-struct dpu_hw_wb_qos_cfg {
- u32 danger_lut;
- u32 safe_lut;
- u64 creq_lut;
- bool danger_safe_en;
-};
-
-/**
*
* struct dpu_hw_wb_ops : Interface to the wb hw driver functions
* Assumption is these functions will be called after clocks are enabled
@@ -64,27 +42,25 @@ struct dpu_hw_wb_ops {
struct dpu_hw_wb_cfg *wb);
void (*setup_qos_lut)(struct dpu_hw_wb *ctx,
- struct dpu_hw_wb_qos_cfg *cfg);
+ struct dpu_hw_qos_cfg *cfg);
void (*setup_cdp)(struct dpu_hw_wb *ctx,
- struct dpu_hw_cdp_cfg *cfg);
+ const struct dpu_format *fmt,
+ bool enable);
void (*bind_pingpong_blk)(struct dpu_hw_wb *ctx,
- bool enable, const enum dpu_pingpong pp);
+ const enum dpu_pingpong pp);
};
/**
* struct dpu_hw_wb : WB driver object
* @hw: block hardware details
- * @mdp: pointer to associated mdp portion of the catalog
* @idx: hardware index number within type
* @wb_hw_caps: hardware capabilities
* @ops: function pointers
- * @hw_mdp: MDP top level hardware block
*/
struct dpu_hw_wb {
struct dpu_hw_blk_reg_map hw;
- const struct dpu_mdp_cfg *mdp;
/* wb path */
int idx;
@@ -92,19 +68,16 @@ struct dpu_hw_wb {
/* ops */
struct dpu_hw_wb_ops ops;
-
- struct dpu_hw_mdp *hw_mdp;
};
/**
- * dpu_hw_wb_init(): Initializes and return writeback hw driver object.
- * @idx: wb_path index for which driver object is required
+ * dpu_hw_wb_init() - Initializes the writeback hw driver object.
+ * @cfg: wb_path catalog entry for which driver object is required
* @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
+ * Return: Error code or allocated dpu_hw_wb context
*/
-struct dpu_hw_wb *dpu_hw_wb_init(enum dpu_wb idx,
- void __iomem *addr,
- const struct dpu_mdss_cfg *m);
+struct dpu_hw_wb *dpu_hw_wb_init(const struct dpu_wb_cfg *cfg,
+ void __iomem *addr);
/**
* dpu_hw_wb_destroy(): Destroy writeback hw driver object.
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 0e7a68714e9e..aa8499de1b9f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -57,8 +57,8 @@ static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);
static int _dpu_danger_signal_status(struct seq_file *s,
bool danger_status)
{
- struct dpu_kms *kms = (struct dpu_kms *)s->private;
struct dpu_danger_safe_status status;
+ struct dpu_kms *kms = s->private;
int i;
if (!kms->hw_mdp) {
@@ -535,15 +535,23 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev,
!msm_dsi_is_master_dsi(priv->dsi[i]))
continue;
- encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI);
+ memset(&info, 0, sizeof(info));
+ info.intf_type = INTF_DSI;
+
+ info.h_tile_instance[info.num_of_h_tiles++] = i;
+ if (msm_dsi_is_bonded_dsi(priv->dsi[i]))
+ info.h_tile_instance[info.num_of_h_tiles++] = other;
+
+ info.is_cmd_mode = msm_dsi_is_cmd_mode(priv->dsi[i]);
+
+ info.dsc = msm_dsi_get_dsc_config(priv->dsi[i]);
+
+ encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI, &info);
if (IS_ERR(encoder)) {
DPU_ERROR("encoder init failed for dsi display\n");
return PTR_ERR(encoder);
}
- memset(&info, 0, sizeof(info));
- info.intf_type = encoder->encoder_type;
-
rc = msm_dsi_modeset_init(priv->dsi[i], dev, encoder);
if (rc) {
DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n",
@@ -551,11 +559,6 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev,
break;
}
- info.h_tile_instance[info.num_of_h_tiles++] = i;
- info.is_cmd_mode = msm_dsi_is_cmd_mode(priv->dsi[i]);
-
- info.dsc = msm_dsi_get_dsc_config(priv->dsi[i]);
-
if (msm_dsi_is_bonded_dsi(priv->dsi[i]) && priv->dsi[other]) {
rc = msm_dsi_modeset_init(priv->dsi[other], dev, encoder);
if (rc) {
@@ -563,14 +566,7 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev,
other, rc);
break;
}
-
- info.h_tile_instance[info.num_of_h_tiles++] = other;
}
-
- rc = dpu_encoder_setup(dev, encoder, &info);
- if (rc)
- DPU_ERROR("failed to setup DPU encoder %d: rc:%d\n",
- encoder->base.id, rc);
}
return rc;
@@ -589,67 +585,86 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev,
if (!priv->dp[i])
continue;
- encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS);
+ memset(&info, 0, sizeof(info));
+ info.num_of_h_tiles = 1;
+ info.h_tile_instance[0] = i;
+ info.intf_type = INTF_DP;
+
+ encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS, &info);
if (IS_ERR(encoder)) {
DPU_ERROR("encoder init failed for dsi display\n");
return PTR_ERR(encoder);
}
- memset(&info, 0, sizeof(info));
rc = msm_dp_modeset_init(priv->dp[i], dev, encoder);
if (rc) {
DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc);
drm_encoder_cleanup(encoder);
return rc;
}
-
- info.num_of_h_tiles = 1;
- info.h_tile_instance[0] = i;
- info.intf_type = encoder->encoder_type;
- rc = dpu_encoder_setup(dev, encoder, &info);
- if (rc) {
- DPU_ERROR("failed to setup DPU encoder %d: rc:%d\n",
- encoder->base.id, rc);
- return rc;
- }
}
return 0;
}
-static int _dpu_kms_initialize_writeback(struct drm_device *dev,
- struct msm_drm_private *priv, struct dpu_kms *dpu_kms,
- const u32 *wb_formats, int n_formats)
+static int _dpu_kms_initialize_hdmi(struct drm_device *dev,
+ struct msm_drm_private *priv,
+ struct dpu_kms *dpu_kms)
{
struct drm_encoder *encoder = NULL;
struct msm_display_info info;
int rc;
- encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_VIRTUAL);
+ if (!priv->hdmi)
+ return 0;
+
+ memset(&info, 0, sizeof(info));
+ info.num_of_h_tiles = 1;
+ info.h_tile_instance[0] = 0;
+ info.intf_type = INTF_HDMI;
+
+ encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS, &info);
if (IS_ERR(encoder)) {
- DPU_ERROR("encoder init failed for dsi display\n");
+ DPU_ERROR("encoder init failed for HDMI display\n");
return PTR_ERR(encoder);
}
- memset(&info, 0, sizeof(info));
-
- rc = dpu_writeback_init(dev, encoder, wb_formats,
- n_formats);
+ rc = msm_hdmi_modeset_init(priv->hdmi, dev, encoder);
if (rc) {
- DPU_ERROR("dpu_writeback_init, rc = %d\n", rc);
+ DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc);
drm_encoder_cleanup(encoder);
return rc;
}
+ return 0;
+}
+
+static int _dpu_kms_initialize_writeback(struct drm_device *dev,
+ struct msm_drm_private *priv, struct dpu_kms *dpu_kms,
+ const u32 *wb_formats, int n_formats)
+{
+ struct drm_encoder *encoder = NULL;
+ struct msm_display_info info;
+ int rc;
+
+ memset(&info, 0, sizeof(info));
+
info.num_of_h_tiles = 1;
/* use only WB idx 2 instance for DPU */
info.h_tile_instance[0] = WB_2;
- info.intf_type = encoder->encoder_type;
+ info.intf_type = INTF_WB;
- rc = dpu_encoder_setup(dev, encoder, &info);
+ encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_VIRTUAL, &info);
+ if (IS_ERR(encoder)) {
+ DPU_ERROR("encoder init failed for dsi display\n");
+ return PTR_ERR(encoder);
+ }
+
+ rc = dpu_writeback_init(dev, encoder, wb_formats,
+ n_formats);
if (rc) {
- DPU_ERROR("failed to setup DPU encoder %d: rc:%d\n",
- encoder->base.id, rc);
+ DPU_ERROR("dpu_writeback_init, rc = %d\n", rc);
+ drm_encoder_cleanup(encoder);
return rc;
}
@@ -683,6 +698,12 @@ static int _dpu_kms_setup_displays(struct drm_device *dev,
return rc;
}
+ rc = _dpu_kms_initialize_hdmi(dev, priv, dpu_kms);
+ if (rc) {
+ DPU_ERROR("initialize HDMI failed, rc = %d\n", rc);
+ return rc;
+ }
+
/* Since WB isn't a driver check the catalog before initializing */
if (dpu_kms->catalog->wb_count) {
for (i = 0; i < dpu_kms->catalog->wb_count; i++) {
@@ -979,13 +1000,13 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms)
return 0;
}
-u64 dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name)
+unsigned long dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name)
{
struct clk *clk;
clk = msm_clk_bulk_get_clock(dpu_kms->clocks, dpu_kms->num_clocks, clock_name);
if (!clk)
- return -EINVAL;
+ return 0;
return clk_get_rate(clk);
}
@@ -1005,6 +1026,9 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
dpu_kms = to_dpu_kms(kms);
dev = dpu_kms->dev;
+ dev->mode_config.cursor_width = 512;
+ dev->mode_config.cursor_height = 512;
+
rc = dpu_kms_global_obj_init(dpu_kms);
if (rc)
return rc;
@@ -1033,12 +1057,6 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
DPU_DEBUG("VBIF NRT is not defined");
}
- dpu_kms->reg_dma = msm_ioremap_quiet(dpu_kms->pdev, "regdma");
- if (IS_ERR(dpu_kms->reg_dma)) {
- dpu_kms->reg_dma = NULL;
- DPU_DEBUG("REG_DMA is not defined");
- }
-
dpu_kms_parse_data_bus_icc_path(dpu_kms);
rc = pm_runtime_resume_and_get(&dpu_kms->pdev->dev);
@@ -1084,16 +1102,17 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
}
for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {
- u32 vbif_idx = dpu_kms->catalog->vbif[i].id;
-
- dpu_kms->hw_vbif[vbif_idx] = dpu_hw_vbif_init(vbif_idx,
- dpu_kms->vbif[vbif_idx], dpu_kms->catalog);
- if (IS_ERR(dpu_kms->hw_vbif[vbif_idx])) {
- rc = PTR_ERR(dpu_kms->hw_vbif[vbif_idx]);
- DPU_ERROR("failed to init vbif %d: %d\n", vbif_idx, rc);
- dpu_kms->hw_vbif[vbif_idx] = NULL;
+ struct dpu_hw_vbif *hw;
+ const struct dpu_vbif_cfg *vbif = &dpu_kms->catalog->vbif[i];
+
+ hw = dpu_hw_vbif_init(vbif, dpu_kms->vbif[vbif->id]);
+ if (IS_ERR(hw)) {
+ rc = PTR_ERR(hw);
+ DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc);
goto power_error;
}
+
+ dpu_kms->hw_vbif[vbif->id] = hw;
}
rc = dpu_core_perf_init(&dpu_kms->perf, dev, dpu_kms->catalog,
@@ -1286,6 +1305,8 @@ static const struct of_device_id dpu_dt_match[] = {
{ .compatible = "qcom,sc8180x-dpu", .data = &dpu_sc8180x_cfg, },
{ .compatible = "qcom,sc8280xp-dpu", .data = &dpu_sc8280xp_cfg, },
{ .compatible = "qcom,sm6115-dpu", .data = &dpu_sm6115_cfg, },
+ { .compatible = "qcom,sm6350-dpu", .data = &dpu_sm6350_cfg, },
+ { .compatible = "qcom,sm6375-dpu", .data = &dpu_sm6375_cfg, },
{ .compatible = "qcom,sm8150-dpu", .data = &dpu_sm8150_cfg, },
{ .compatible = "qcom,sm8250-dpu", .data = &dpu_sm8250_cfg, },
{ .compatible = "qcom,sm8350-dpu", .data = &dpu_sm8350_cfg, },
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index aca39a4689f4..f3bdd4f11108 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -63,15 +63,13 @@
#define ktime_compare_safe(A, B) \
ktime_compare(ktime_sub((A), (B)), ktime_set(0, 0))
-#define DPU_NAME_SIZE 12
-
struct dpu_kms {
struct msm_kms base;
struct drm_device *dev;
const struct dpu_mdss_cfg *catalog;
/* io/register spaces: */
- void __iomem *mmio, *vbif[VBIF_MAX], *reg_dma;
+ void __iomem *mmio, *vbif[VBIF_MAX];
struct regulator *vdd;
struct regulator *mmagic;
@@ -118,6 +116,10 @@ struct vsync_info {
u32 line_count;
};
+#define DPU_ENC_WR_PTR_START_TIMEOUT_US 20000
+
+#define DPU_ENC_MAX_POLL_TIMEOUT_US 2000
+
#define to_dpu_kms(x) container_of(x, struct dpu_kms, base)
#define to_dpu_global_state(x) container_of(x, struct dpu_global_state, base)
@@ -201,6 +203,6 @@ void dpu_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
*
* Return: current clock rate
*/
-u64 dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name);
+unsigned long dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name);
#endif /* __dpu_kms_H__ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 14b5cfe30611..c2aaaded07ed 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -42,8 +42,6 @@
#define SHARP_SMOOTH_THR_DEFAULT 8
#define SHARP_NOISE_THR_DEFAULT 2
-#define DPU_NAME_SIZE 12
-
#define DPU_PLANE_COLOR_FILL_FLAG BIT(31)
#define DPU_ZPOS_MAX 255
@@ -70,20 +68,6 @@ static const uint32_t qcom_compressed_supported_formats[] = {
DRM_FORMAT_P010,
};
-/**
- * enum dpu_plane_qos - Different qos configurations for each pipe
- *
- * @DPU_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
- * @DPU_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
- * this configuration is mutually exclusive from VBLANK_CTRL.
- * @DPU_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
- */
-enum dpu_plane_qos {
- DPU_PLANE_QOS_VBLANK_CTRL = BIT(0),
- DPU_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
- DPU_PLANE_QOS_PANIC_CTRL = BIT(2),
-};
-
/*
* struct dpu_plane - local dpu plane structure
* @aspace: address space pointer
@@ -204,12 +188,14 @@ static u64 _dpu_plane_calc_clk(const struct drm_display_mode *mode,
* _dpu_plane_calc_fill_level - calculate fill level of the given source format
* @plane: Pointer to drm plane
* @pipe: Pointer to software pipe
+ * @lut_usage: LUT usecase
* @fmt: Pointer to source buffer format
* @src_width: width of source buffer
* Return: fill level corresponding to the source buffer/format or 0 if error
*/
static int _dpu_plane_calc_fill_level(struct drm_plane *plane,
struct dpu_sw_pipe *pipe,
+ enum dpu_qos_lut_usage lut_usage,
const struct dpu_format *fmt, u32 src_width)
{
struct dpu_plane *pdpu;
@@ -221,6 +207,9 @@ static int _dpu_plane_calc_fill_level(struct drm_plane *plane,
return 0;
}
+ if (lut_usage == DPU_QOS_LUT_USAGE_NRT)
+ return 0;
+
pdpu = to_dpu_plane(plane);
fixed_buff_size = pdpu->catalog->caps->pixel_ram_size;
@@ -266,83 +255,58 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
const struct dpu_format *fmt, struct dpu_sw_pipe_cfg *pipe_cfg)
{
struct dpu_plane *pdpu = to_dpu_plane(plane);
- u64 qos_lut;
- u32 total_fl = 0, lut_usage;
+ struct dpu_hw_qos_cfg cfg;
+ u32 total_fl, lut_usage;
if (!pdpu->is_rt_pipe) {
lut_usage = DPU_QOS_LUT_USAGE_NRT;
} else {
- total_fl = _dpu_plane_calc_fill_level(plane, pipe, fmt,
- drm_rect_width(&pipe_cfg->src_rect));
-
if (fmt && DPU_FORMAT_IS_LINEAR(fmt))
lut_usage = DPU_QOS_LUT_USAGE_LINEAR;
else
lut_usage = DPU_QOS_LUT_USAGE_MACROTILE;
}
- qos_lut = _dpu_hw_get_qos_lut(
- &pdpu->catalog->perf->qos_lut_tbl[lut_usage], total_fl);
+ total_fl = _dpu_plane_calc_fill_level(plane, pipe, lut_usage, fmt,
+ drm_rect_width(&pipe_cfg->src_rect));
+
+ cfg.creq_lut = _dpu_hw_get_qos_lut(&pdpu->catalog->perf->qos_lut_tbl[lut_usage], total_fl);
+ cfg.danger_lut = pdpu->catalog->perf->danger_lut_tbl[lut_usage];
+ cfg.safe_lut = pdpu->catalog->perf->safe_lut_tbl[lut_usage];
+
+ if (pipe->sspp->idx != SSPP_CURSOR0 &&
+ pipe->sspp->idx != SSPP_CURSOR1 &&
+ pdpu->is_rt_pipe)
+ cfg.danger_safe_en = true;
+
+ DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d is_rt:%d\n",
+ pdpu->pipe - SSPP_VIG0,
+ cfg.danger_safe_en,
+ pdpu->is_rt_pipe);
trace_dpu_perf_set_qos_luts(pipe->sspp->idx - SSPP_VIG0,
(fmt) ? fmt->base.pixel_format : 0,
- pdpu->is_rt_pipe, total_fl, qos_lut, lut_usage);
+ pdpu->is_rt_pipe, total_fl, cfg.creq_lut, lut_usage);
DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n",
pdpu->pipe - SSPP_VIG0,
fmt ? (char *)&fmt->base.pixel_format : NULL,
- pdpu->is_rt_pipe, total_fl, qos_lut);
-
- pipe->sspp->ops.setup_creq_lut(pipe->sspp, qos_lut);
-}
-
-/**
- * _dpu_plane_set_danger_lut - set danger/safe LUT of the given plane
- * @plane: Pointer to drm plane
- * @pipe: Pointer to software pipe
- * @fmt: Pointer to source buffer format
- */
-static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
- struct dpu_sw_pipe *pipe,
- const struct dpu_format *fmt)
-{
- struct dpu_plane *pdpu = to_dpu_plane(plane);
- u32 danger_lut, safe_lut;
-
- if (!pdpu->is_rt_pipe) {
- danger_lut = pdpu->catalog->perf->danger_lut_tbl
- [DPU_QOS_LUT_USAGE_NRT];
- safe_lut = pdpu->catalog->perf->safe_lut_tbl
- [DPU_QOS_LUT_USAGE_NRT];
- } else {
- if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) {
- danger_lut = pdpu->catalog->perf->danger_lut_tbl
- [DPU_QOS_LUT_USAGE_LINEAR];
- safe_lut = pdpu->catalog->perf->safe_lut_tbl
- [DPU_QOS_LUT_USAGE_LINEAR];
- } else {
- danger_lut = pdpu->catalog->perf->danger_lut_tbl
- [DPU_QOS_LUT_USAGE_MACROTILE];
- safe_lut = pdpu->catalog->perf->safe_lut_tbl
- [DPU_QOS_LUT_USAGE_MACROTILE];
- }
- }
+ pdpu->is_rt_pipe, total_fl, cfg.creq_lut);
trace_dpu_perf_set_danger_luts(pdpu->pipe - SSPP_VIG0,
(fmt) ? fmt->base.pixel_format : 0,
(fmt) ? fmt->fetch_mode : 0,
- danger_lut,
- safe_lut);
+ cfg.danger_lut,
+ cfg.safe_lut);
DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n",
pdpu->pipe - SSPP_VIG0,
fmt ? (char *)&fmt->base.pixel_format : NULL,
fmt ? fmt->fetch_mode : -1,
- danger_lut,
- safe_lut);
+ cfg.danger_lut,
+ cfg.safe_lut);
- pipe->sspp->ops.setup_danger_safe_lut(pipe->sspp,
- danger_lut, safe_lut);
+ pipe->sspp->ops.setup_qos_lut(pipe->sspp, &cfg);
}
/**
@@ -350,48 +314,23 @@ static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
* @plane: Pointer to drm plane
* @pipe: Pointer to software pipe
* @enable: true to enable QoS control
- * @flags: QoS control mode (enum dpu_plane_qos)
*/
static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
struct dpu_sw_pipe *pipe,
- bool enable, u32 flags)
+ bool enable)
{
struct dpu_plane *pdpu = to_dpu_plane(plane);
- struct dpu_hw_pipe_qos_cfg pipe_qos_cfg;
-
- memset(&pipe_qos_cfg, 0, sizeof(pipe_qos_cfg));
-
- if (flags & DPU_PLANE_QOS_VBLANK_CTRL) {
- pipe_qos_cfg.creq_vblank = pipe->sspp->cap->sblk->creq_vblank;
- pipe_qos_cfg.danger_vblank =
- pipe->sspp->cap->sblk->danger_vblank;
- pipe_qos_cfg.vblank_en = enable;
- }
- if (flags & DPU_PLANE_QOS_VBLANK_AMORTIZE) {
- /* this feature overrules previous VBLANK_CTRL */
- pipe_qos_cfg.vblank_en = false;
- pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
- }
-
- if (flags & DPU_PLANE_QOS_PANIC_CTRL)
- pipe_qos_cfg.danger_safe_en = enable;
-
- if (!pdpu->is_rt_pipe) {
- pipe_qos_cfg.vblank_en = false;
- pipe_qos_cfg.danger_safe_en = false;
- }
+ if (!pdpu->is_rt_pipe)
+ enable = false;
- DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d vb:%d pri[0x%x, 0x%x] is_rt:%d\n",
+ DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d is_rt:%d\n",
pdpu->pipe - SSPP_VIG0,
- pipe_qos_cfg.danger_safe_en,
- pipe_qos_cfg.vblank_en,
- pipe_qos_cfg.creq_vblank,
- pipe_qos_cfg.danger_vblank,
+ enable,
pdpu->is_rt_pipe);
pipe->sspp->ops.setup_qos_ctrl(pipe->sspp,
- &pipe_qos_cfg);
+ enable);
}
/**
@@ -1079,10 +1018,10 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane *plane,
pipe->sspp->ops.setup_sourceaddress(pipe, layout);
}
- _dpu_plane_set_qos_ctrl(plane, pipe, false, DPU_PLANE_QOS_PANIC_CTRL);
-
/* override for color fill */
if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) {
+ _dpu_plane_set_qos_ctrl(plane, pipe, false);
+
/* skip remaining processing on color fill */
return;
}
@@ -1116,30 +1055,18 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane *plane,
pipe->sspp->ops.setup_format(pipe, fmt, src_flags);
if (pipe->sspp->ops.setup_cdp) {
- struct dpu_hw_cdp_cfg cdp_cfg;
-
- memset(&cdp_cfg, 0, sizeof(struct dpu_hw_cdp_cfg));
+ const struct dpu_perf_cfg *perf = pdpu->catalog->perf;
- cdp_cfg.enable = pdpu->catalog->perf->cdp_cfg
- [DPU_PERF_CDP_USAGE_RT].rd_enable;
- cdp_cfg.ubwc_meta_enable =
- DPU_FORMAT_IS_UBWC(fmt);
- cdp_cfg.tile_amortize_enable =
- DPU_FORMAT_IS_UBWC(fmt) ||
- DPU_FORMAT_IS_TILE(fmt);
- cdp_cfg.preload_ahead = DPU_SSPP_CDP_PRELOAD_AHEAD_64;
-
- pipe->sspp->ops.setup_cdp(pipe, &cdp_cfg);
+ pipe->sspp->ops.setup_cdp(pipe, fmt,
+ perf->cdp_cfg[DPU_PERF_CDP_USAGE_RT].rd_enable);
}
}
_dpu_plane_set_qos_lut(plane, pipe, fmt, pipe_cfg);
- _dpu_plane_set_danger_lut(plane, pipe, fmt);
- if (plane->type != DRM_PLANE_TYPE_CURSOR) {
- _dpu_plane_set_qos_ctrl(plane, pipe, true, DPU_PLANE_QOS_PANIC_CTRL);
+ if (pipe->sspp->idx != SSPP_CURSOR0 &&
+ pipe->sspp->idx != SSPP_CURSOR1)
_dpu_plane_set_ot_limit(plane, pipe, pipe_cfg, frame_rate);
- }
if (pstate->needs_qos_remap)
_dpu_plane_set_qos_remap(plane, pipe);
@@ -1254,10 +1181,10 @@ static void dpu_plane_destroy(struct drm_plane *plane)
if (pdpu) {
pstate = to_dpu_plane_state(plane->state);
- _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, false, DPU_PLANE_QOS_PANIC_CTRL);
+ _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, false);
if (pstate->r_pipe.sspp)
- _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, false, DPU_PLANE_QOS_PANIC_CTRL);
+ _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, false);
mutex_destroy(&pdpu->lock);
@@ -1414,9 +1341,9 @@ void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
return;
pm_runtime_get_sync(&dpu_kms->pdev->dev);
- _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, enable, DPU_PLANE_QOS_PANIC_CTRL);
+ _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, enable);
if (pstate->r_pipe.sspp)
- _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, enable, DPU_PLANE_QOS_PANIC_CTRL);
+ _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, enable);
pm_runtime_put_sync(&dpu_kms->pdev->dev);
}
#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index f4dda88a73f7..471842bbb950 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define pr_fmt(fmt) "[drm:%s] " fmt, __func__
@@ -117,16 +118,7 @@ int dpu_rm_init(struct dpu_rm *rm,
struct dpu_hw_mixer *hw;
const struct dpu_lm_cfg *lm = &cat->mixer[i];
- if (lm->pingpong == PINGPONG_MAX) {
- DPU_DEBUG("skip mixer %d without pingpong\n", lm->id);
- continue;
- }
-
- if (lm->id < LM_0 || lm->id >= LM_MAX) {
- DPU_ERROR("skip mixer %d with invalid id\n", lm->id);
- continue;
- }
- hw = dpu_hw_lm_init(lm->id, mmio, cat);
+ hw = dpu_hw_lm_init(lm, mmio);
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed lm object creation: err %d\n", rc);
@@ -139,11 +131,7 @@ int dpu_rm_init(struct dpu_rm *rm,
struct dpu_hw_merge_3d *hw;
const struct dpu_merge_3d_cfg *merge_3d = &cat->merge_3d[i];
- if (merge_3d->id < MERGE_3D_0 || merge_3d->id >= MERGE_3D_MAX) {
- DPU_ERROR("skip merge_3d %d with invalid id\n", merge_3d->id);
- continue;
- }
- hw = dpu_hw_merge_3d_init(merge_3d->id, mmio, cat);
+ hw = dpu_hw_merge_3d_init(merge_3d, mmio);
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed merge_3d object creation: err %d\n",
@@ -157,11 +145,7 @@ int dpu_rm_init(struct dpu_rm *rm,
struct dpu_hw_pingpong *hw;
const struct dpu_pingpong_cfg *pp = &cat->pingpong[i];
- if (pp->id < PINGPONG_0 || pp->id >= PINGPONG_MAX) {
- DPU_ERROR("skip pingpong %d with invalid id\n", pp->id);
- continue;
- }
- hw = dpu_hw_pingpong_init(pp->id, mmio, cat);
+ hw = dpu_hw_pingpong_init(pp, mmio);
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed pingpong object creation: err %d\n",
@@ -177,15 +161,7 @@ int dpu_rm_init(struct dpu_rm *rm,
struct dpu_hw_intf *hw;
const struct dpu_intf_cfg *intf = &cat->intf[i];
- if (intf->type == INTF_NONE) {
- DPU_DEBUG("skip intf %d with type none\n", i);
- continue;
- }
- if (intf->id < INTF_0 || intf->id >= INTF_MAX) {
- DPU_ERROR("skip intf %d with invalid id\n", intf->id);
- continue;
- }
- hw = dpu_hw_intf_init(intf->id, mmio, cat);
+ hw = dpu_hw_intf_init(intf, mmio);
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed intf object creation: err %d\n", rc);
@@ -198,12 +174,7 @@ int dpu_rm_init(struct dpu_rm *rm,
struct dpu_hw_wb *hw;
const struct dpu_wb_cfg *wb = &cat->wb[i];
- if (wb->id < WB_0 || wb->id >= WB_MAX) {
- DPU_ERROR("skip intf %d with invalid id\n", wb->id);
- continue;
- }
-
- hw = dpu_hw_wb_init(wb->id, mmio, cat);
+ hw = dpu_hw_wb_init(wb, mmio);
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed wb object creation: err %d\n", rc);
@@ -216,11 +187,7 @@ int dpu_rm_init(struct dpu_rm *rm,
struct dpu_hw_ctl *hw;
const struct dpu_ctl_cfg *ctl = &cat->ctl[i];
- if (ctl->id < CTL_0 || ctl->id >= CTL_MAX) {
- DPU_ERROR("skip ctl %d with invalid id\n", ctl->id);
- continue;
- }
- hw = dpu_hw_ctl_init(ctl->id, mmio, cat);
+ hw = dpu_hw_ctl_init(ctl, mmio, cat->mixer_count, cat->mixer);
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed ctl object creation: err %d\n", rc);
@@ -233,11 +200,7 @@ int dpu_rm_init(struct dpu_rm *rm,
struct dpu_hw_dspp *hw;
const struct dpu_dspp_cfg *dspp = &cat->dspp[i];
- if (dspp->id < DSPP_0 || dspp->id >= DSPP_MAX) {
- DPU_ERROR("skip dspp %d with invalid id\n", dspp->id);
- continue;
- }
- hw = dpu_hw_dspp_init(dspp->id, mmio, cat);
+ hw = dpu_hw_dspp_init(dspp, mmio);
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed dspp object creation: err %d\n", rc);
@@ -250,8 +213,12 @@ int dpu_rm_init(struct dpu_rm *rm,
struct dpu_hw_dsc *hw;
const struct dpu_dsc_cfg *dsc = &cat->dsc[i];
- hw = dpu_hw_dsc_init(dsc->id, mmio, cat);
- if (IS_ERR_OR_NULL(hw)) {
+ if (test_bit(DPU_DSC_HW_REV_1_2, &dsc->features))
+ hw = dpu_hw_dsc_init_1_2(dsc, mmio);
+ else
+ hw = dpu_hw_dsc_init(dsc, mmio);
+
+ if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed dsc object creation: err %d\n", rc);
goto fail;
@@ -263,12 +230,7 @@ int dpu_rm_init(struct dpu_rm *rm,
struct dpu_hw_sspp *hw;
const struct dpu_sspp_cfg *sspp = &cat->sspp[i];
- if (sspp->id < SSPP_NONE || sspp->id >= SSPP_MAX) {
- DPU_ERROR("skip intf %d with invalid id\n", sspp->id);
- continue;
- }
-
- hw = dpu_hw_sspp_init(sspp->id, mmio, cat);
+ hw = dpu_hw_sspp_init(sspp, mmio, cat->ubwc);
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed sspp object creation: err %d\n", rc);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
index 0ad148cc2fb8..1a92d21094f4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
@@ -871,6 +871,20 @@ TRACE_EVENT(dpu_pp_connect_ext_te,
TP_printk("pp:%d cfg:%u", __entry->pp, __entry->cfg)
);
+TRACE_EVENT(dpu_intf_connect_ext_te,
+ TP_PROTO(enum dpu_intf intf, u32 cfg),
+ TP_ARGS(intf, cfg),
+ TP_STRUCT__entry(
+ __field( enum dpu_intf, intf )
+ __field( u32, cfg )
+ ),
+ TP_fast_assign(
+ __entry->intf = intf;
+ __entry->cfg = cfg;
+ ),
+ TP_printk("intf:%d cfg:%u", __entry->intf, __entry->cfg)
+);
+
TRACE_EVENT(dpu_core_irq_register_callback,
TP_PROTO(int irq_idx, void *callback),
TP_ARGS(irq_idx, callback),
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
index 2eec2d78f32a..694d54341337 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
@@ -103,6 +103,87 @@ static const struct mdp5_cfg_hw msm8x74v1_config = {
.max_clk = 200000000,
};
+static const struct mdp5_cfg_hw msm8x26_config = {
+ .name = "msm8x26",
+ .mdp = {
+ .count = 1,
+ .caps = MDP_CAP_SMP |
+ 0,
+ },
+ .smp = {
+ .mmb_count = 7,
+ .mmb_size = 4096,
+ .clients = {
+ [SSPP_VIG0] = 1,
+ [SSPP_DMA0] = 4,
+ [SSPP_RGB0] = 7,
+ },
+ },
+ .ctl = {
+ .count = 2,
+ .base = { 0x00500, 0x00600 },
+ .flush_hw_mask = 0x0003ffff,
+ },
+ .pipe_vig = {
+ .count = 1,
+ .base = { 0x01100 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ MDP_PIPE_CAP_SCALE |
+ MDP_PIPE_CAP_CSC |
+ 0,
+ },
+ .pipe_rgb = {
+ .count = 1,
+ .base = { 0x01d00 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ MDP_PIPE_CAP_SCALE |
+ 0,
+ },
+ .pipe_dma = {
+ .count = 1,
+ .base = { 0x02900 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ 0,
+ },
+ .lm = {
+ .count = 2,
+ .base = { 0x03100, 0x03d00 },
+ .instances = {
+ { .id = 0, .pp = 0, .dspp = 0,
+ .caps = MDP_LM_CAP_DISPLAY, },
+ { .id = 1, .pp = -1, .dspp = -1,
+ .caps = MDP_LM_CAP_WB },
+ },
+ .nb_stages = 2,
+ .max_width = 2048,
+ .max_height = 0xFFFF,
+ },
+ .dspp = {
+ .count = 1,
+ .base = { 0x04500 },
+ },
+ .pp = {
+ .count = 1,
+ .base = { 0x21a00 },
+ },
+ .intf = {
+ .base = { 0x00000, 0x21200 },
+ .connect = {
+ [0] = INTF_DISABLED,
+ [1] = INTF_DSI,
+ },
+ },
+ .perf = {
+ .ab_inefficiency = 100,
+ .ib_inefficiency = 200,
+ .clk_inefficiency = 125
+ },
+ .max_clk = 200000000,
+};
+
static const struct mdp5_cfg_hw msm8x74v2_config = {
.name = "msm8x74",
.mdp = {
@@ -1236,6 +1317,7 @@ static const struct mdp5_cfg_hw sdm660_config = {
static const struct mdp5_cfg_handler cfg_handlers_v1[] = {
{ .revision = 0, .config = { .hw = &msm8x74v1_config } },
+ { .revision = 1, .config = { .hw = &msm8x26_config } },
{ .revision = 2, .config = { .hw = &msm8x74v2_config } },
{ .revision = 3, .config = { .hw = &apq8084_config } },
{ .revision = 6, .config = { .hw = &msm8x16_config } },
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 29ae5c9613f3..323079cfd698 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -229,7 +229,7 @@ static void mdp5_kms_destroy(struct msm_kms *kms)
#ifdef CONFIG_DEBUG_FS
static int smp_show(struct seq_file *m, void *arg)
{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_info_node *node = m->private;
struct drm_device *dev = node->minor->dev;
struct msm_drm_private *priv = dev->dev_private;
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index f712780149fd..b2c27d3532bf 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -14,7 +14,6 @@
#include "dp_catalog.h"
struct dp_ctrl {
- bool orientation;
atomic_t aborted;
bool wide_bus_en;
};
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index 5e35033ba3e4..3bba901afe33 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -21,7 +21,6 @@
struct dp_debug_private {
struct dentry *root;
- struct dp_usbpd *usbpd;
struct dp_link *link;
struct dp_panel *panel;
struct drm_connector *connector;
@@ -232,14 +231,14 @@ static void dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor)
}
struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
- struct dp_usbpd *usbpd, struct dp_link *link,
+ struct dp_link *link,
struct drm_connector *connector, struct drm_minor *minor)
{
struct dp_debug_private *debug;
struct dp_debug *dp_debug;
int rc;
- if (!dev || !panel || !usbpd || !link) {
+ if (!dev || !panel || !link) {
DRM_ERROR("invalid input\n");
rc = -EINVAL;
goto error;
@@ -252,7 +251,6 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
}
debug->dp_debug.debug_en = false;
- debug->usbpd = usbpd;
debug->link = link;
debug->panel = panel;
debug->dev = dev;
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h
index 8c0d0b5178fd..124227873d58 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.h
+++ b/drivers/gpu/drm/msm/dp/dp_debug.h
@@ -32,7 +32,6 @@ struct dp_debug {
*
* @dev: device instance of the caller
* @panel: instance of panel module
- * @usbpd: instance of usbpd module
* @link: instance of link module
* @connector: double pointer to display connector
* @minor: pointer to drm minor number after device registration
@@ -42,7 +41,7 @@ struct dp_debug {
* for debugfs input to be communicated with existing modules
*/
struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
- struct dp_usbpd *usbpd, struct dp_link *link,
+ struct dp_link *link,
struct drm_connector *connector,
struct drm_minor *minor);
@@ -59,7 +58,7 @@ void dp_debug_put(struct dp_debug *dp_debug);
static inline
struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
- struct dp_usbpd *usbpd, struct dp_link *link,
+ struct dp_link *link,
struct drm_connector *connector, struct drm_minor *minor)
{
return ERR_PTR(-EINVAL);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 03b0eda6df54..76f13954015b 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -14,7 +14,6 @@
#include "msm_drv.h"
#include "msm_kms.h"
-#include "dp_hpd.h"
#include "dp_parser.h"
#include "dp_power.h"
#include "dp_catalog.h"
@@ -92,7 +91,6 @@ struct dp_display_private {
struct platform_device *pdev;
struct dentry *root;
- struct dp_usbpd *usbpd;
struct dp_parser *parser;
struct dp_power *power;
struct dp_catalog *catalog;
@@ -102,7 +100,6 @@ struct dp_display_private {
struct dp_ctrl *ctrl;
struct dp_debug *debug;
- struct dp_usbpd_cb usbpd_cb;
struct dp_display_mode dp_mode;
struct msm_dp dp_display;
@@ -329,6 +326,8 @@ static void dp_display_unbind(struct device *dev, struct device *master,
kthread_stop(dp->ev_tsk);
+ of_dp_aux_depopulate_bus(dp->aux);
+
dp_power_client_deinit(dp->power);
dp_unregister_audio_driver(dev, dp->audio);
dp_aux_unregister(dp->aux);
@@ -467,7 +466,7 @@ static void dp_display_host_init(struct dp_display_private *dp)
dp->dp_display.connector_type, dp->core_initialized,
dp->phy_initialized);
- dp_power_init(dp->power, false);
+ dp_power_init(dp->power);
dp_ctrl_reset_irq_ctrl(dp->ctrl, true);
dp_aux_init(dp->aux);
dp->core_initialized = true;
@@ -494,11 +493,6 @@ static int dp_display_usbpd_configure_cb(struct device *dev)
return dp_display_process_hpd_high(dp);
}
-static int dp_display_usbpd_disconnect_cb(struct device *dev)
-{
- return 0;
-}
-
static int dp_display_notify_disconnect(struct device *dev)
{
struct dp_display_private *dp = dev_get_dp_display_private(dev);
@@ -583,13 +577,9 @@ static int dp_display_usbpd_attention_cb(struct device *dev)
static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
{
- struct dp_usbpd *hpd = dp->usbpd;
u32 state;
int ret;
- if (!hpd)
- return 0;
-
mutex_lock(&dp->event_mutex);
state = dp->hpd_state;
@@ -644,12 +634,8 @@ static void dp_display_handle_plugged_change(struct msm_dp *dp_display,
static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
{
- struct dp_usbpd *hpd = dp->usbpd;
u32 state;
- if (!hpd)
- return 0;
-
mutex_lock(&dp->event_mutex);
state = dp->hpd_state;
@@ -748,24 +734,10 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
{
int rc = 0;
struct device *dev = &dp->pdev->dev;
- struct dp_usbpd_cb *cb = &dp->usbpd_cb;
struct dp_panel_in panel_in = {
.dev = dev,
};
- /* Callback APIs used for cable status change event */
- cb->configure = dp_display_usbpd_configure_cb;
- cb->disconnect = dp_display_usbpd_disconnect_cb;
- cb->attention = dp_display_usbpd_attention_cb;
-
- dp->usbpd = dp_hpd_get(dev, cb);
- if (IS_ERR(dp->usbpd)) {
- rc = PTR_ERR(dp->usbpd);
- DRM_ERROR("failed to initialize hpd, rc = %d\n", rc);
- dp->usbpd = NULL;
- goto error;
- }
-
dp->parser = dp_parser_get(dp->pdev);
if (IS_ERR(dp->parser)) {
rc = PTR_ERR(dp->parser);
@@ -1328,9 +1300,9 @@ static int dp_display_remove(struct platform_device *pdev)
{
struct dp_display_private *dp = dev_get_dp_display_private(&pdev->dev);
+ component_del(&pdev->dev, &dp_display_comp_ops);
dp_display_deinit_sub_modules(dp);
- component_del(&pdev->dev, &dp_display_comp_ops);
platform_set_drvdata(pdev, NULL);
return 0;
@@ -1499,7 +1471,7 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor)
dp = container_of(dp_display, struct dp_display_private, dp_display);
dev = &dp->pdev->dev;
- dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd,
+ dp->debug = dp_debug_get(dev, dp->panel,
dp->link, dp->dp_display.connector,
minor);
if (IS_ERR(dp->debug)) {
@@ -1509,11 +1481,6 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor)
}
}
-static void of_dp_aux_depopulate_bus_void(void *data)
-{
- of_dp_aux_depopulate_bus(data);
-}
-
static int dp_display_get_next_bridge(struct msm_dp *dp)
{
int rc;
@@ -1541,12 +1508,6 @@ static int dp_display_get_next_bridge(struct msm_dp *dp)
of_node_put(aux_bus);
if (rc)
goto error;
-
- rc = devm_add_action_or_reset(dp->drm_dev->dev,
- of_dp_aux_depopulate_bus_void,
- dp_priv->aux);
- if (rc)
- goto error;
} else if (dp->is_edp) {
DRM_ERROR("eDP aux_bus not found\n");
return -ENODEV;
@@ -1570,6 +1531,7 @@ static int dp_display_get_next_bridge(struct msm_dp *dp)
error:
if (dp->is_edp) {
+ of_dp_aux_depopulate_bus(dp_priv->aux);
dp_display_host_phy_exit(dp_priv);
dp_display_host_deinit(dp_priv);
}
diff --git a/drivers/gpu/drm/msm/dp/dp_hpd.c b/drivers/gpu/drm/msm/dp/dp_hpd.c
deleted file mode 100644
index db98a1d431eb..000000000000
--- a/drivers/gpu/drm/msm/dp/dp_hpd.c
+++ /dev/null
@@ -1,67 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
- */
-
-#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
-
-#include <linux/slab.h>
-#include <linux/device.h>
-
-#include "dp_hpd.h"
-
-/* DP specific VDM commands */
-#define DP_USBPD_VDM_STATUS 0x10
-#define DP_USBPD_VDM_CONFIGURE 0x11
-
-/* USBPD-TypeC specific Macros */
-#define VDM_VERSION 0x0
-#define USB_C_DP_SID 0xFF01
-
-struct dp_hpd_private {
- struct device *dev;
- struct dp_usbpd_cb *dp_cb;
- struct dp_usbpd dp_usbpd;
-};
-
-int dp_hpd_connect(struct dp_usbpd *dp_usbpd, bool hpd)
-{
- int rc = 0;
- struct dp_hpd_private *hpd_priv;
-
- hpd_priv = container_of(dp_usbpd, struct dp_hpd_private,
- dp_usbpd);
-
- if (!hpd_priv->dp_cb || !hpd_priv->dp_cb->configure
- || !hpd_priv->dp_cb->disconnect) {
- pr_err("hpd dp_cb not initialized\n");
- return -EINVAL;
- }
- if (hpd)
- hpd_priv->dp_cb->configure(hpd_priv->dev);
- else
- hpd_priv->dp_cb->disconnect(hpd_priv->dev);
-
- return rc;
-}
-
-struct dp_usbpd *dp_hpd_get(struct device *dev, struct dp_usbpd_cb *cb)
-{
- struct dp_hpd_private *dp_hpd;
-
- if (!cb) {
- pr_err("invalid cb data\n");
- return ERR_PTR(-EINVAL);
- }
-
- dp_hpd = devm_kzalloc(dev, sizeof(*dp_hpd), GFP_KERNEL);
- if (!dp_hpd)
- return ERR_PTR(-ENOMEM);
-
- dp_hpd->dev = dev;
- dp_hpd->dp_cb = cb;
-
- dp_hpd->dp_usbpd.connect = dp_hpd_connect;
-
- return &dp_hpd->dp_usbpd;
-}
diff --git a/drivers/gpu/drm/msm/dp/dp_hpd.h b/drivers/gpu/drm/msm/dp/dp_hpd.h
deleted file mode 100644
index 8feec5aa5027..000000000000
--- a/drivers/gpu/drm/msm/dp/dp_hpd.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
- */
-
-#ifndef _DP_HPD_H_
-#define _DP_HPD_H_
-
-//#include <linux/usb/usbpd.h>
-
-#include <linux/types.h>
-#include <linux/device.h>
-
-enum plug_orientation {
- ORIENTATION_NONE,
- ORIENTATION_CC1,
- ORIENTATION_CC2,
-};
-
-/**
- * struct dp_usbpd - DisplayPort status
- *
- * @orientation: plug orientation configuration
- * @low_pow_st: low power state
- * @adaptor_dp_en: adaptor functionality enabled
- * @multi_func: multi-function preferred
- * @usb_config_req: request to switch to usb
- * @exit_dp_mode: request exit from displayport mode
- * @hpd_irq: Change in the status since last message
- * @alt_mode_cfg_done: bool to specify alt mode status
- * @debug_en: bool to specify debug mode
- * @connect: simulate disconnect or connect for debug mode
- */
-struct dp_usbpd {
- enum plug_orientation orientation;
- bool low_pow_st;
- bool adaptor_dp_en;
- bool multi_func;
- bool usb_config_req;
- bool exit_dp_mode;
- bool hpd_irq;
- bool alt_mode_cfg_done;
- bool debug_en;
-
- int (*connect)(struct dp_usbpd *dp_usbpd, bool hpd);
-};
-
-/**
- * struct dp_usbpd_cb - callback functions provided by the client
- *
- * @configure: called by usbpd module when PD communication has
- * been completed and the usb peripheral has been configured on
- * dp mode.
- * @disconnect: notify the cable disconnect issued by usb.
- * @attention: notify any attention message issued by usb.
- */
-struct dp_usbpd_cb {
- int (*configure)(struct device *dev);
- int (*disconnect)(struct device *dev);
- int (*attention)(struct device *dev);
-};
-
-/**
- * dp_hpd_get() - setup hpd module
- *
- * @dev: device instance of the caller
- * @cb: struct containing callback function pointers.
- *
- * This function allows the client to initialize the usbpd
- * module. The module will communicate with HPD module.
- */
-struct dp_usbpd *dp_hpd_get(struct device *dev, struct dp_usbpd_cb *cb);
-
-int dp_hpd_register(struct dp_usbpd *dp_usbpd);
-void dp_hpd_unregister(struct dp_usbpd *dp_usbpd);
-int dp_hpd_connect(struct dp_usbpd *dp_usbpd, bool hpd);
-
-#endif /* _DP_HPD_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index 45208b45eb53..ed1030e17e1b 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -10,7 +10,6 @@
#include "dp_aux.h"
#include "dp_link.h"
-#include "dp_hpd.h"
struct edid;
diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c
index c0aaabb03389..5cb84ca40e9e 100644
--- a/drivers/gpu/drm/msm/dp/dp_power.c
+++ b/drivers/gpu/drm/msm/dp/dp_power.c
@@ -14,7 +14,6 @@
struct dp_power_private {
struct dp_parser *parser;
- struct platform_device *pdev;
struct device *dev;
struct drm_device *drm_dev;
struct clk *link_clk_src;
@@ -28,32 +27,23 @@ static int dp_power_clk_init(struct dp_power_private *power)
{
int rc = 0;
struct dss_module_power *core, *ctrl, *stream;
- struct device *dev = &power->pdev->dev;
+ struct device *dev = power->dev;
core = &power->parser->mp[DP_CORE_PM];
ctrl = &power->parser->mp[DP_CTRL_PM];
stream = &power->parser->mp[DP_STREAM_PM];
rc = devm_clk_bulk_get(dev, core->num_clk, core->clocks);
- if (rc) {
- DRM_ERROR("failed to get %s clk. err=%d\n",
- dp_parser_pm_name(DP_CORE_PM), rc);
+ if (rc)
return rc;
- }
rc = devm_clk_bulk_get(dev, ctrl->num_clk, ctrl->clocks);
- if (rc) {
- DRM_ERROR("failed to get %s clk. err=%d\n",
- dp_parser_pm_name(DP_CTRL_PM), rc);
+ if (rc)
return -ENODEV;
- }
rc = devm_clk_bulk_get(dev, stream->num_clk, stream->clocks);
- if (rc) {
- DRM_ERROR("failed to get %s clk. err=%d\n",
- dp_parser_pm_name(DP_CTRL_PM), rc);
+ if (rc)
return -ENODEV;
- }
return 0;
}
@@ -121,11 +111,9 @@ int dp_power_clk_enable(struct dp_power *dp_power,
mp = &power->parser->mp[DP_CORE_PM];
rc = clk_bulk_prepare_enable(mp->num_clk, mp->clocks);
- if (rc) {
- DRM_ERROR("fail to enable clks: %s. err=%d\n",
- dp_parser_pm_name(DP_CORE_PM), rc);
+ if (rc)
return rc;
- }
+
dp_power->core_clks_on = true;
}
}
@@ -133,10 +121,8 @@ int dp_power_clk_enable(struct dp_power *dp_power,
mp = &power->parser->mp[pm_type];
if (enable) {
rc = clk_bulk_prepare_enable(mp->num_clk, mp->clocks);
- if (rc) {
- DRM_ERROR("failed to enable clks, err: %d\n", rc);
+ if (rc)
return rc;
- }
} else {
clk_bulk_disable_unprepare(mp->num_clk, mp->clocks);
}
@@ -162,63 +148,37 @@ int dp_power_clk_enable(struct dp_power *dp_power,
int dp_power_client_init(struct dp_power *dp_power)
{
- int rc = 0;
struct dp_power_private *power;
- if (!dp_power) {
- DRM_ERROR("invalid power data\n");
- return -EINVAL;
- }
-
power = container_of(dp_power, struct dp_power_private, dp_power);
- pm_runtime_enable(&power->pdev->dev);
-
- rc = dp_power_clk_init(power);
- if (rc)
- DRM_ERROR("failed to init clocks %d\n", rc);
+ pm_runtime_enable(power->dev);
- return rc;
+ return dp_power_clk_init(power);
}
void dp_power_client_deinit(struct dp_power *dp_power)
{
struct dp_power_private *power;
- if (!dp_power) {
- DRM_ERROR("invalid power data\n");
- return;
- }
-
power = container_of(dp_power, struct dp_power_private, dp_power);
- pm_runtime_disable(&power->pdev->dev);
+ pm_runtime_disable(power->dev);
}
-int dp_power_init(struct dp_power *dp_power, bool flip)
+int dp_power_init(struct dp_power *dp_power)
{
int rc = 0;
struct dp_power_private *power = NULL;
- if (!dp_power) {
- DRM_ERROR("invalid power data\n");
- return -EINVAL;
- }
-
power = container_of(dp_power, struct dp_power_private, dp_power);
- pm_runtime_get_sync(&power->pdev->dev);
+ pm_runtime_get_sync(power->dev);
rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true);
- if (rc) {
- DRM_ERROR("failed to enable DP core clocks, %d\n", rc);
- goto exit;
- }
-
- return 0;
+ if (rc)
+ pm_runtime_put_sync(power->dev);
-exit:
- pm_runtime_put_sync(&power->pdev->dev);
return rc;
}
@@ -229,7 +189,7 @@ int dp_power_deinit(struct dp_power *dp_power)
power = container_of(dp_power, struct dp_power_private, dp_power);
dp_power_clk_enable(dp_power, DP_CORE_PM, false);
- pm_runtime_put_sync(&power->pdev->dev);
+ pm_runtime_put_sync(power->dev);
return 0;
}
@@ -238,17 +198,11 @@ struct dp_power *dp_power_get(struct device *dev, struct dp_parser *parser)
struct dp_power_private *power;
struct dp_power *dp_power;
- if (!parser) {
- DRM_ERROR("invalid input\n");
- return ERR_PTR(-EINVAL);
- }
-
- power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL);
+ power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
if (!power)
return ERR_PTR(-ENOMEM);
power->parser = parser;
- power->pdev = parser->pdev;
power->dev = dev;
dp_power = &power->dp_power;
diff --git a/drivers/gpu/drm/msm/dp/dp_power.h b/drivers/gpu/drm/msm/dp/dp_power.h
index e3f959ffae12..a3dec200785e 100644
--- a/drivers/gpu/drm/msm/dp/dp_power.h
+++ b/drivers/gpu/drm/msm/dp/dp_power.h
@@ -26,13 +26,12 @@ struct dp_power {
* dp_power_init() - enable power supplies for display controller
*
* @power: instance of power module
- * @flip: bool for flipping gpio direction
* return: 0 if success or error if failure.
*
* This API will turn on the regulators and configures gpio's
* aux/hpd.
*/
-int dp_power_init(struct dp_power *power, bool flip);
+int dp_power_init(struct dp_power *power);
/**
* dp_power_deinit() - turn off regulators and gpios.
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
index 29ccd755cc2e..8a5fb6df7210 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -245,6 +245,8 @@ static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
&apq8064_dsi_cfg, &msm_dsi_v2_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_0,
&msm8974_apq8084_dsi_cfg, &msm_dsi_6g_host_ops},
+ {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_0_2,
+ &msm8974_apq8084_dsi_cfg, &msm_dsi_6g_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_1,
&msm8974_apq8084_dsi_cfg, &msm_dsi_6g_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_1_1,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
index 91bdaf50bb1a..43f0dd74edb6 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
@@ -11,6 +11,7 @@
#define MSM_DSI_VER_MAJOR_V2 0x02
#define MSM_DSI_VER_MAJOR_6G 0x03
#define MSM_DSI_6G_VER_MINOR_V1_0 0x10000000
+#define MSM_DSI_6G_VER_MINOR_V1_0_2 0x10000002
#define MSM_DSI_6G_VER_MINOR_V1_1 0x10010000
#define MSM_DSI_6G_VER_MINOR_V1_1_1 0x10010001
#define MSM_DSI_6G_VER_MINOR_V1_2 0x10020000
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 961689a255c4..3f6dfb4f9d5a 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -28,6 +28,7 @@
#include "dsi.xml.h"
#include "sfpb.xml.h"
#include "dsi_cfg.h"
+#include "msm_dsc_helper.h"
#include "msm_kms.h"
#include "msm_gem.h"
#include "phy/dsi_phy.h"
@@ -117,8 +118,6 @@ struct msm_dsi_host {
struct clk *byte_clk;
struct clk *esc_clk;
struct clk *pixel_clk;
- struct clk *byte_clk_src;
- struct clk *pixel_clk_src;
struct clk *byte_intf_clk;
unsigned long byte_clk_rate;
@@ -128,8 +127,6 @@ struct msm_dsi_host {
/* DSI v2 specific clocks */
struct clk *src_clk;
- struct clk *esc_clk_src;
- struct clk *dsi_clk_src;
unsigned long src_clk_rate;
@@ -266,21 +263,6 @@ int dsi_clk_init_v2(struct msm_dsi_host *msm_host)
return ret;
}
- msm_host->esc_clk_src = clk_get_parent(msm_host->esc_clk);
- if (!msm_host->esc_clk_src) {
- ret = -ENODEV;
- pr_err("%s: can't get esc clock parent. ret=%d\n",
- __func__, ret);
- return ret;
- }
-
- msm_host->dsi_clk_src = clk_get_parent(msm_host->src_clk);
- if (!msm_host->dsi_clk_src) {
- ret = -ENODEV;
- pr_err("%s: can't get src clock parent. ret=%d\n",
- __func__, ret);
- }
-
return ret;
}
@@ -345,20 +327,6 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host)
goto exit;
}
- msm_host->byte_clk_src = clk_get_parent(msm_host->byte_clk);
- if (IS_ERR(msm_host->byte_clk_src)) {
- ret = PTR_ERR(msm_host->byte_clk_src);
- pr_err("%s: can't find byte_clk clock. ret=%d\n", __func__, ret);
- goto exit;
- }
-
- msm_host->pixel_clk_src = clk_get_parent(msm_host->pixel_clk);
- if (IS_ERR(msm_host->pixel_clk_src)) {
- ret = PTR_ERR(msm_host->pixel_clk_src);
- pr_err("%s: can't find pixel_clk clock. ret=%d\n", __func__, ret);
- goto exit;
- }
-
if (cfg_hnd->ops->clk_init_ver)
ret = cfg_hnd->ops->clk_init_ver(msm_host);
exit:
@@ -560,12 +528,27 @@ void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host)
clk_disable_unprepare(msm_host->byte_clk);
}
-static unsigned long dsi_get_pclk_rate(const struct drm_display_mode *mode, bool is_bonded_dsi)
+static unsigned long dsi_adjust_pclk_for_compression(const struct drm_display_mode *mode,
+ const struct drm_dsc_config *dsc)
+{
+ int new_hdisplay = DIV_ROUND_UP(mode->hdisplay * drm_dsc_get_bpp_int(dsc),
+ dsc->bits_per_component * 3);
+
+ int new_htotal = mode->htotal - mode->hdisplay + new_hdisplay;
+
+ return new_htotal * mode->vtotal * drm_mode_vrefresh(mode);
+}
+
+static unsigned long dsi_get_pclk_rate(const struct drm_display_mode *mode,
+ const struct drm_dsc_config *dsc, bool is_bonded_dsi)
{
unsigned long pclk_rate;
pclk_rate = mode->clock * 1000;
+ if (dsc)
+ pclk_rate = dsi_adjust_pclk_for_compression(mode, dsc);
+
/*
* For bonded DSI mode, the current DRM mode has the complete width of the
* panel. Since, the complete panel is driven by two DSI controllers,
@@ -584,8 +567,8 @@ unsigned long dsi_byte_clk_get_rate(struct mipi_dsi_host *host, bool is_bonded_d
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
u8 lanes = msm_host->lanes;
u32 bpp = dsi_get_bpp(msm_host->format);
- unsigned long pclk_rate = dsi_get_pclk_rate(mode, is_bonded_dsi);
- u64 pclk_bpp = (u64)pclk_rate * bpp;
+ unsigned long pclk_rate = dsi_get_pclk_rate(mode, msm_host->dsc, is_bonded_dsi);
+ unsigned long pclk_bpp;
if (lanes == 0) {
pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
@@ -594,16 +577,16 @@ unsigned long dsi_byte_clk_get_rate(struct mipi_dsi_host *host, bool is_bonded_d
/* CPHY "byte_clk" is in units of 16 bits */
if (msm_host->cphy_mode)
- do_div(pclk_bpp, (16 * lanes));
+ pclk_bpp = mult_frac(pclk_rate, bpp, 16 * lanes);
else
- do_div(pclk_bpp, (8 * lanes));
+ pclk_bpp = mult_frac(pclk_rate, bpp, 8 * lanes);
return pclk_bpp;
}
static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
{
- msm_host->pixel_clk_rate = dsi_get_pclk_rate(msm_host->mode, is_bonded_dsi);
+ msm_host->pixel_clk_rate = dsi_get_pclk_rate(msm_host->mode, msm_host->dsc, is_bonded_dsi);
msm_host->byte_clk_rate = dsi_byte_clk_get_rate(&msm_host->base, is_bonded_dsi,
msm_host->mode);
@@ -627,15 +610,12 @@ int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
{
u32 bpp = dsi_get_bpp(msm_host->format);
- u64 pclk_bpp;
unsigned int esc_mhz, esc_div;
unsigned long byte_mhz;
dsi_calc_pclk(msm_host, is_bonded_dsi);
- pclk_bpp = (u64)dsi_get_pclk_rate(msm_host->mode, is_bonded_dsi) * bpp;
- do_div(pclk_bpp, 8);
- msm_host->src_clk_rate = pclk_bpp;
+ msm_host->src_clk_rate = mult_frac(msm_host->pixel_clk_rate, bpp, 8);
/*
* esc clock is byte clock followed by a 4 bit divider,
@@ -725,7 +705,12 @@ static inline enum dsi_cmd_dst_format dsi_get_cmd_fmt(
}
}
-static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
+static void dsi_ctrl_disable(struct msm_dsi_host *msm_host)
+{
+ dsi_write(msm_host, REG_DSI_CTRL, 0);
+}
+
+static void dsi_ctrl_enable(struct msm_dsi_host *msm_host,
struct msm_dsi_phy_shared_timings *phy_shared_timings, struct msm_dsi_phy *phy)
{
u32 flags = msm_host->mode_flags;
@@ -733,11 +718,6 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
u32 data = 0, lane_ctrl = 0;
- if (!enable) {
- dsi_write(msm_host, REG_DSI_CTRL, 0);
- return;
- }
-
if (flags & MIPI_DSI_MODE_VIDEO) {
if (flags & MIPI_DSI_MODE_VIDEO_HSE)
data |= DSI_VID_CFG0_PULSE_MODE_HSA_HE;
@@ -822,7 +802,7 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) {
lane_ctrl = dsi_read(msm_host, REG_DSI_LANE_CTRL);
- if (msm_dsi_phy_set_continuous_clock(phy, enable))
+ if (msm_dsi_phy_set_continuous_clock(phy, true))
lane_ctrl &= ~DSI_LANE_CTRL_HS_REQ_SEL_PHY;
dsi_write(msm_host, REG_DSI_LANE_CTRL,
@@ -848,20 +828,19 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod
/* first calculate dsc parameters and then program
* compress mode registers
*/
- slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->slice_width);
-
- /*
- * If slice_count is greater than slice_per_intf
- * then default to 1. This can happen during partial
- * update.
- */
- if (dsc->slice_count > slice_per_intf)
- dsc->slice_count = 1;
+ slice_per_intf = msm_dsc_get_slices_per_intf(dsc, hdisplay);
total_bytes_per_intf = dsc->slice_chunk_size * slice_per_intf;
eol_byte_num = total_bytes_per_intf % 3;
- pkt_per_line = slice_per_intf / dsc->slice_count;
+
+ /*
+ * Typically, pkt_per_line = slice_per_intf * slice_per_pkt.
+ *
+ * Since the current driver only supports slice_per_pkt = 1,
+ * pkt_per_line will be equal to slice per intf for now.
+ */
+ pkt_per_line = slice_per_intf;
if (is_cmd_mode) /* packet data type */
reg = DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE(MIPI_DSI_DCS_LONG_WRITE);
@@ -951,7 +930,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
* pulse width same
*/
h_total -= hdisplay;
- hdisplay /= 3;
+ hdisplay = DIV_ROUND_UP(msm_dsc_get_bytes_per_line(msm_host->dsc), 3);
h_total += hdisplay;
ha_end = ha_start + hdisplay;
}
@@ -985,7 +964,14 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
if (!msm_host->dsc)
wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
else
- wc = msm_host->dsc->slice_chunk_size * msm_host->dsc->slice_count + 1;
+ /*
+ * When DSC is enabled, WC = slice_chunk_size * slice_per_pkt + 1.
+ * Currently, the driver only supports default value of slice_per_pkt = 1
+ *
+ * TODO: Expand mipi_dsi_device struct to hold slice_per_pkt info
+ * and adjust DSC math to account for slice_per_pkt.
+ */
+ wc = msm_host->dsc->slice_chunk_size + 1;
dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL,
DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) |
@@ -1731,28 +1717,9 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host,
return -EINVAL;
}
-static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = {
- 0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62,
- 0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e
-};
-
-/* only 8bpc, 8bpp added */
-static char min_qp[DSC_NUM_BUF_RANGES] = {
- 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13
-};
-
-static char max_qp[DSC_NUM_BUF_RANGES] = {
- 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15
-};
-
-static char bpg_offset[DSC_NUM_BUF_RANGES] = {
- 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
-};
-
static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct drm_dsc_config *dsc)
{
- int i;
- u16 bpp = dsc->bits_per_pixel >> 4;
+ int ret;
if (dsc->bits_per_pixel & 0xf) {
DRM_DEV_ERROR(&msm_host->pdev->dev, "DSI does not support fractional bits_per_pixel\n");
@@ -1764,49 +1731,23 @@ static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct drm_dsc
return -EOPNOTSUPP;
}
- dsc->rc_model_size = 8192;
- dsc->first_line_bpg_offset = 12;
- dsc->rc_edge_factor = 6;
- dsc->rc_tgt_offset_high = 3;
- dsc->rc_tgt_offset_low = 3;
dsc->simple_422 = 0;
dsc->convert_rgb = 1;
dsc->vbr_enable = 0;
- /* handle only bpp = bpc = 8 */
- for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++)
- dsc->rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i];
+ drm_dsc_set_const_params(dsc);
+ drm_dsc_set_rc_buf_thresh(dsc);
- for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
- dsc->rc_range_params[i].range_min_qp = min_qp[i];
- dsc->rc_range_params[i].range_max_qp = max_qp[i];
- /*
- * Range BPG Offset contains two's-complement signed values that fill
- * 8 bits, yet the registers and DCS PPS field are only 6 bits wide.
- */
- dsc->rc_range_params[i].range_bpg_offset = bpg_offset[i] & DSC_RANGE_BPG_OFFSET_MASK;
+ /* handle only bpp = bpc = 8, pre-SCR panels */
+ ret = drm_dsc_setup_rc_params(dsc, DRM_DSC_1_1_PRE_SCR);
+ if (ret) {
+ DRM_DEV_ERROR(&msm_host->pdev->dev, "could not find DSC RC parameters\n");
+ return ret;
}
- dsc->initial_offset = 6144; /* Not bpp 12 */
- if (bpp != 8)
- dsc->initial_offset = 2048; /* bpp = 12 */
-
- if (dsc->bits_per_component <= 10)
- dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
- else
- dsc->mux_word_size = DSC_MUX_WORD_SIZE_12_BPC;
-
- dsc->initial_xmit_delay = 512;
- dsc->initial_scale_value = 32;
- dsc->first_line_bpg_offset = 12;
+ dsc->initial_scale_value = drm_dsc_initial_scale_value(dsc);
dsc->line_buf_depth = dsc->bits_per_component + 1;
- /* bpc 8 */
- dsc->flatness_min_qp = 3;
- dsc->flatness_max_qp = 12;
- dsc->rc_quant_incr_limit0 = 11;
- dsc->rc_quant_incr_limit1 = 11;
-
return drm_dsc_compute_rc_parameters(dsc);
}
@@ -2417,7 +2358,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host,
dsi_timing_setup(msm_host, is_bonded_dsi);
dsi_sw_reset(msm_host);
- dsi_ctrl_config(msm_host, true, phy_shared_timings, phy);
+ dsi_ctrl_enable(msm_host, phy_shared_timings, phy);
if (msm_host->disp_en_gpio)
gpiod_set_value(msm_host->disp_en_gpio, 1);
@@ -2449,7 +2390,7 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host)
goto unlock_ret;
}
- dsi_ctrl_config(msm_host, false, NULL, NULL);
+ dsi_ctrl_disable(msm_host);
if (msm_host->disp_en_gpio)
gpiod_set_value(msm_host->disp_en_gpio, 0);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 1bbac72dad35..28b8012a21f2 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -34,32 +34,6 @@ static struct msm_dsi_manager msm_dsim_glb;
#define IS_SYNC_NEEDED() (msm_dsim_glb.is_sync_needed)
#define IS_MASTER_DSI_LINK(id) (msm_dsim_glb.master_dsi_link_id == id)
-#ifdef CONFIG_OF
-static bool dsi_mgr_power_on_early(struct drm_bridge *bridge)
-{
- struct drm_bridge *next_bridge = drm_bridge_get_next_bridge(bridge);
-
- /*
- * If the next bridge in the chain is the Parade ps8640 bridge chip
- * then don't power on early since it seems to violate the expectations
- * of the firmware that the bridge chip is running.
- *
- * NOTE: this is expected to be a temporary special case. It's expected
- * that we'll eventually have a framework that allows the next level
- * bridge to indicate whether it needs us to power on before it or
- * after it. When that framework is in place then we'll use it and
- * remove this special case.
- */
- return !(next_bridge && next_bridge->of_node &&
- of_device_is_compatible(next_bridge->of_node, "parade,ps8640"));
-}
-#else
-static inline bool dsi_mgr_power_on_early(struct drm_bridge *bridge)
-{
- return true;
-}
-#endif
-
static inline struct msm_dsi *dsi_mgr_get_dsi(int id)
{
return msm_dsim_glb.dsi[id];
@@ -254,7 +228,7 @@ static void msm_dsi_manager_set_split_display(u8 id)
}
}
-static void dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
+static int dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
{
int id = dsi_mgr_bridge_get_id(bridge);
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
@@ -265,12 +239,6 @@ static void dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
int ret;
DBG("id=%d", id);
- if (!msm_dsi_device_connected(msm_dsi))
- return;
-
- /* Do nothing with the host if it is slave-DSI in case of bonded DSI */
- if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
- return;
ret = dsi_mgr_phy_enable(id, phy_shared_timings);
if (ret)
@@ -300,14 +268,31 @@ static void dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
if (is_bonded_dsi && msm_dsi1)
msm_dsi_host_enable_irq(msm_dsi1->host);
- return;
+ return 0;
host1_on_fail:
msm_dsi_host_power_off(host);
host_on_fail:
dsi_mgr_phy_disable(id);
phy_en_fail:
- return;
+ return ret;
+}
+
+static void dsi_mgr_bridge_power_off(struct drm_bridge *bridge)
+{
+ int id = dsi_mgr_bridge_get_id(bridge);
+ struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+ struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
+ struct mipi_dsi_host *host = msm_dsi->host;
+ bool is_bonded_dsi = IS_BONDED_DSI();
+
+ msm_dsi_host_disable_irq(host);
+ if (is_bonded_dsi && msm_dsi1) {
+ msm_dsi_host_disable_irq(msm_dsi1->host);
+ msm_dsi_host_power_off(msm_dsi1->host);
+ }
+ msm_dsi_host_power_off(host);
+ dsi_mgr_phy_disable(id);
}
static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
@@ -327,8 +312,11 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
return;
- if (!dsi_mgr_power_on_early(bridge))
- dsi_mgr_bridge_power_on(bridge);
+ ret = dsi_mgr_bridge_power_on(bridge);
+ if (ret) {
+ dev_err(&msm_dsi->pdev->dev, "Power on failed: %d\n", ret);
+ return;
+ }
ret = msm_dsi_host_enable(host);
if (ret) {
@@ -349,8 +337,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
host1_en_fail:
msm_dsi_host_disable(host);
host_en_fail:
-
- return;
+ dsi_mgr_bridge_power_off(bridge);
}
void msm_dsi_manager_tpg_enable(void)
@@ -438,9 +425,6 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
msm_dsi_host_set_display_mode(host, adjusted_mode);
if (is_bonded_dsi && other_dsi)
msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode);
-
- if (dsi_mgr_power_on_early(bridge))
- dsi_mgr_bridge_power_on(bridge);
}
static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge,
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index bb09cbe8ff86..9d5795c58a98 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -541,6 +541,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
.data = &dsi_phy_28nm_hpm_famb_cfgs },
{ .compatible = "qcom,dsi-phy-28nm-lp",
.data = &dsi_phy_28nm_lp_cfgs },
+ { .compatible = "qcom,dsi-phy-28nm-8226",
+ .data = &dsi_phy_28nm_8226_cfgs },
#endif
#ifdef CONFIG_DRM_MSM_DSI_20NM_PHY
{ .compatible = "qcom,dsi-phy-20nm",
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 7137a17ae523..8b640d174785 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -46,8 +46,9 @@ struct msm_dsi_phy_cfg {
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_famb_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs;
-extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8226_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_14nm_660_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_14nm_2290_cfgs;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
index 9f488adea7f5..3ce45b023e63 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
@@ -539,6 +539,9 @@ static int dsi_pll_14nm_vco_prepare(struct clk_hw *hw)
if (unlikely(pll_14nm->phy->pll_on))
return 0;
+ if (dsi_pll_14nm_vco_recalc_rate(hw, VCO_REF_CLK_RATE) == 0)
+ dsi_pll_14nm_vco_set_rate(hw, pll_14nm->phy->cfg->min_pll_rate, VCO_REF_CLK_RATE);
+
dsi_phy_write(base + REG_DSI_14nm_PHY_PLL_VREF_CFG1, 0x10);
dsi_phy_write(cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 1);
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
index 4c1bf55c5f38..ceec7bb87bf1 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
@@ -37,6 +37,7 @@
/* v2.0.0 28nm LP implementation */
#define DSI_PHY_28NM_QUIRK_PHY_LP BIT(0)
+#define DSI_PHY_28NM_QUIRK_PHY_8226 BIT(1)
#define LPFR_LUT_SIZE 10
struct lpfr_cfg {
@@ -377,6 +378,74 @@ static int dsi_pll_28nm_vco_prepare_hpm(struct clk_hw *hw)
return ret;
}
+static int dsi_pll_28nm_vco_prepare_8226(struct clk_hw *hw)
+{
+ struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
+ struct device *dev = &pll_28nm->phy->pdev->dev;
+ void __iomem *base = pll_28nm->phy->pll_base;
+ u32 max_reads = 5, timeout_us = 100;
+ bool locked;
+ u32 val;
+ int i;
+
+ DBG("id=%d", pll_28nm->phy->id);
+
+ pll_28nm_software_reset(pll_28nm);
+
+ /*
+ * PLL power up sequence.
+ * Add necessary delays recommended by hardware.
+ */
+ dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG1, 0x34);
+
+ val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
+ dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
+ dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
+ dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+
+ for (i = 0; i < 7; i++) {
+ /* DSI Uniphy lock detect setting */
+ dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
+ dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,
+ 0x0c, 100);
+ dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
+
+ /* poll for PLL ready status */
+ locked = pll_28nm_poll_for_ready(pll_28nm,
+ max_reads, timeout_us);
+ if (locked)
+ break;
+
+ pll_28nm_software_reset(pll_28nm);
+
+ /*
+ * PLL power up sequence.
+ * Add necessary delays recommended by hardware.
+ */
+ dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG, 0x00, 50);
+
+ val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
+ dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 100);
+
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
+ dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+ }
+
+ if (unlikely(!locked))
+ DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");
+ else
+ DBG("DSI PLL Lock success");
+
+ return locked ? 0 : -EINVAL;
+}
+
static int dsi_pll_28nm_vco_prepare_lp(struct clk_hw *hw)
{
struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
@@ -471,6 +540,15 @@ static const struct clk_ops clk_ops_dsi_pll_28nm_vco_lp = {
.is_enabled = dsi_pll_28nm_clk_is_enabled,
};
+static const struct clk_ops clk_ops_dsi_pll_28nm_vco_8226 = {
+ .round_rate = dsi_pll_28nm_clk_round_rate,
+ .set_rate = dsi_pll_28nm_clk_set_rate,
+ .recalc_rate = dsi_pll_28nm_clk_recalc_rate,
+ .prepare = dsi_pll_28nm_vco_prepare_8226,
+ .unprepare = dsi_pll_28nm_vco_unprepare,
+ .is_enabled = dsi_pll_28nm_clk_is_enabled,
+};
+
/*
* PLL Callbacks
*/
@@ -536,6 +614,8 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov
if (pll_28nm->phy->cfg->quirks & DSI_PHY_28NM_QUIRK_PHY_LP)
vco_init.ops = &clk_ops_dsi_pll_28nm_vco_lp;
+ else if (pll_28nm->phy->cfg->quirks & DSI_PHY_28NM_QUIRK_PHY_8226)
+ vco_init.ops = &clk_ops_dsi_pll_28nm_vco_8226;
else
vco_init.ops = &clk_ops_dsi_pll_28nm_vco_hpm;
@@ -820,3 +900,20 @@ const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs = {
.quirks = DSI_PHY_28NM_QUIRK_PHY_LP,
};
+const struct msm_dsi_phy_cfg dsi_phy_28nm_8226_cfgs = {
+ .has_phy_regulator = true,
+ .regulator_data = dsi_phy_28nm_regulators,
+ .num_regulators = ARRAY_SIZE(dsi_phy_28nm_regulators),
+ .ops = {
+ .enable = dsi_28nm_phy_enable,
+ .disable = dsi_28nm_phy_disable,
+ .pll_init = dsi_pll_28nm_init,
+ .save_pll_state = dsi_28nm_pll_save_state,
+ .restore_pll_state = dsi_28nm_pll_restore_state,
+ },
+ .min_pll_rate = VCO_MIN_RATE,
+ .max_pll_rate = VCO_MAX_RATE,
+ .io_start = { 0xfd922b00 },
+ .num_dsi_phy = 1,
+ .quirks = DSI_PHY_28NM_QUIRK_PHY_8226,
+};
diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c
index 9c0e633a3a61..a0a936f80ae3 100644
--- a/drivers/gpu/drm/msm/msm_debugfs.c
+++ b/drivers/gpu/drm/msm/msm_debugfs.c
@@ -211,7 +211,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(shrink_fops,
static int msm_gem_show(struct seq_file *m, void *arg)
{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_info_node *node = m->private;
struct drm_device *dev = node->minor->dev;
struct msm_drm_private *priv = dev->dev_private;
int ret;
@@ -229,7 +229,7 @@ static int msm_gem_show(struct seq_file *m, void *arg)
static int msm_mm_show(struct seq_file *m, void *arg)
{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_info_node *node = m->private;
struct drm_device *dev = node->minor->dev;
struct drm_printer p = drm_seq_file_printer(m);
@@ -240,7 +240,7 @@ static int msm_mm_show(struct seq_file *m, void *arg)
static int msm_fb_show(struct seq_file *m, void *arg)
{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_info_node *node = m->private;
struct drm_device *dev = node->minor->dev;
struct drm_framebuffer *fb, *fbdev_fb = NULL;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 463ca4164f5f..891eff8433a9 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -457,7 +457,7 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
goto err_deinit_vram;
/* the fw fb could be anywhere in memory */
- ret = drm_aperture_remove_framebuffers(false, drv);
+ ret = drm_aperture_remove_framebuffers(drv);
if (ret)
goto err_msm_uninit;
@@ -1057,23 +1057,23 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW),
};
-static void msm_fop_show_fdinfo(struct seq_file *m, struct file *f)
+static void msm_show_fdinfo(struct drm_printer *p, struct drm_file *file)
{
- struct drm_file *file = f->private_data;
struct drm_device *dev = file->minor->dev;
struct msm_drm_private *priv = dev->dev_private;
- struct drm_printer p = drm_seq_file_printer(m);
if (!priv->gpu)
return;
- msm_gpu_show_fdinfo(priv->gpu, file->driver_priv, &p);
+ msm_gpu_show_fdinfo(priv->gpu, file->driver_priv, p);
+
+ drm_show_memory_stats(p, file);
}
static const struct file_operations fops = {
.owner = THIS_MODULE,
DRM_GEM_FOPS,
- .show_fdinfo = msm_fop_show_fdinfo,
+ .show_fdinfo = drm_show_fdinfo,
};
static const struct drm_driver msm_driver = {
@@ -1083,7 +1083,7 @@ static const struct drm_driver msm_driver = {
DRIVER_MODESET |
DRIVER_SYNCOBJ,
.open = msm_open,
- .postclose = msm_postclose,
+ .postclose = msm_postclose,
.dumb_create = msm_gem_dumb_create,
.dumb_map_offset = msm_gem_dumb_map_offset,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
@@ -1093,6 +1093,7 @@ static const struct drm_driver msm_driver = {
#ifdef CONFIG_DEBUG_FS
.debugfs_init = msm_debugfs_init,
#endif
+ .show_fdinfo = msm_show_fdinfo,
.ioctls = msm_ioctls,
.num_ioctls = ARRAY_SIZE(msm_ioctls),
.fops = &fops,
diff --git a/drivers/gpu/drm/msm/msm_dsc_helper.h b/drivers/gpu/drm/msm/msm_dsc_helper.h
new file mode 100644
index 000000000000..b9049fe1e279
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_dsc_helper.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved
+ *
+ * Helper methods for MSM-specific DSC calculations that are common between timing engine,
+ * DSI, and DP.
+ */
+
+#ifndef MSM_DSC_HELPER_H_
+#define MSM_DSC_HELPER_H_
+
+#include <linux/math.h>
+#include <drm/display/drm_dsc_helper.h>
+
+/**
+ * msm_dsc_get_slices_per_intf() - calculate number of slices per interface
+ * @dsc: Pointer to drm dsc config struct
+ * @intf_width: interface width in pixels
+ * Returns: Integer representing the number of slices for the given interface
+ */
+static inline u32 msm_dsc_get_slices_per_intf(const struct drm_dsc_config *dsc, u32 intf_width)
+{
+ return DIV_ROUND_UP(intf_width, dsc->slice_width);
+}
+
+/**
+ * msm_dsc_get_bytes_per_line() - calculate bytes per line
+ * @dsc: Pointer to drm dsc config struct
+ * Returns: Integer value representing bytes per line. DSI and DP need
+ * to perform further calculations to turn this into pclk_per_intf,
+ * such as dividing by different values depending on if widebus is enabled.
+ */
+static inline u32 msm_dsc_get_bytes_per_line(const struct drm_dsc_config *dsc)
+{
+ return dsc->slice_count * dsc->slice_chunk_size;
+}
+
+#endif /* MSM_DSC_HELPER_H_ */
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index 2ebc86381e1c..b933a85420f6 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -4,6 +4,8 @@
* Author: Rob Clark <robdclark@gmail.com>
*/
+#include <linux/fb.h>
+
#include <drm/drm_drv.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
@@ -23,6 +25,10 @@ module_param(fbdev, bool, 0600);
* fbdev funcs, to implement legacy fbdev interface on top of drm driver
*/
+FB_GEN_DEFAULT_DEFERRED_SYS_OPS(msm_fbdev,
+ drm_fb_helper_damage_range,
+ drm_fb_helper_damage_area)
+
static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par;
@@ -52,16 +58,9 @@ static void msm_fbdev_fb_destroy(struct fb_info *info)
static const struct fb_ops msm_fb_ops = {
.owner = THIS_MODULE,
+ __FB_DEFAULT_DEFERRED_OPS_RDWR(msm_fbdev),
DRM_FB_HELPER_DEFAULT_OPS,
-
- /* Note: to properly handle manual update displays, we wrap the
- * basic fbdev ops which write to the framebuffer
- */
- .fb_read = drm_fb_helper_sys_read,
- .fb_write = drm_fb_helper_sys_write,
- .fb_fillrect = drm_fb_helper_sys_fillrect,
- .fb_copyarea = drm_fb_helper_sys_copyarea,
- .fb_imageblit = drm_fb_helper_sys_imageblit,
+ __FB_DEFAULT_DEFERRED_OPS_DRAW(msm_fbdev),
.fb_mmap = msm_fbdev_mmap,
.fb_destroy = msm_fbdev_fb_destroy,
};
@@ -121,9 +120,9 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
drm_fb_helper_fill_info(fbi, helper, sizes);
- fbi->screen_base = msm_gem_get_vaddr(bo);
- if (IS_ERR(fbi->screen_base)) {
- ret = PTR_ERR(fbi->screen_base);
+ fbi->screen_buffer = msm_gem_get_vaddr(bo);
+ if (IS_ERR(fbi->screen_buffer)) {
+ ret = PTR_ERR(fbi->screen_buffer);
goto fail;
}
fbi->screen_size = bo->size;
@@ -140,8 +139,28 @@ fail:
return ret;
}
+static int msm_fbdev_fb_dirty(struct drm_fb_helper *helper,
+ struct drm_clip_rect *clip)
+{
+ struct drm_device *dev = helper->dev;
+ int ret;
+
+ /* Call damage handlers only if necessary */
+ if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2))
+ return 0;
+
+ if (helper->fb->funcs->dirty) {
+ ret = helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1);
+ if (drm_WARN_ONCE(dev, ret, "Dirty helper failed: ret=%d\n", ret))
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct drm_fb_helper_funcs msm_fb_helper_funcs = {
.fb_probe = msm_fbdev_create,
+ .fb_dirty = msm_fbdev_fb_dirty,
};
/*
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index cd39b9d8abdb..20cfd86d2b32 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -1090,6 +1090,20 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
return ret;
}
+static enum drm_gem_object_status msm_gem_status(struct drm_gem_object *obj)
+{
+ struct msm_gem_object *msm_obj = to_msm_bo(obj);
+ enum drm_gem_object_status status = 0;
+
+ if (msm_obj->pages)
+ status |= DRM_GEM_OBJECT_RESIDENT;
+
+ if (msm_obj->madv == MSM_MADV_DONTNEED)
+ status |= DRM_GEM_OBJECT_PURGEABLE;
+
+ return status;
+}
+
static const struct vm_operations_struct vm_ops = {
.fault = msm_gem_fault,
.open = drm_gem_vm_open,
@@ -1104,6 +1118,7 @@ static const struct drm_gem_object_funcs msm_gem_object_funcs = {
.vmap = msm_gem_prime_vmap,
.vunmap = msm_gem_prime_vunmap,
.mmap = msm_gem_object_mmap,
+ .status = msm_gem_status,
.vm_ops = &vm_ops,
};
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 9f5933c75e3d..3f1aa4de3b87 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -558,8 +558,7 @@ static struct drm_syncobj **msm_parse_deps(struct msm_gem_submit *submit,
struct drm_file *file,
uint64_t in_syncobjs_addr,
uint32_t nr_in_syncobjs,
- size_t syncobj_stride,
- struct msm_ringbuffer *ring)
+ size_t syncobj_stride)
{
struct drm_syncobj **syncobjs = NULL;
struct drm_msm_gem_submit_syncobj syncobj_desc = {0};
@@ -808,7 +807,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
syncobjs_to_reset = msm_parse_deps(submit, file,
args->in_syncobjs,
args->nr_in_syncobjs,
- args->syncobj_stride, ring);
+ args->syncobj_stride);
if (IS_ERR(syncobjs_to_reset)) {
ret = PTR_ERR(syncobjs_to_reset);
goto out_unlock;
@@ -949,6 +948,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
/* The scheduler owns a ref now: */
msm_gem_submit_get(submit);
+ msm_rd_dump_submit(priv->rd, submit, NULL);
+
drm_sched_entity_push_job(&submit->base);
args->fence = submit->fence_id;
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 26ebda40be4f..52db90e34ead 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -151,8 +151,6 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
void msm_gpu_show_fdinfo(struct msm_gpu *gpu, struct msm_file_private *ctx,
struct drm_printer *p)
{
- drm_printf(p, "drm-driver:\t%s\n", gpu->dev->driver->name);
- drm_printf(p, "drm-client-id:\t%u\n", ctx->seqno);
drm_printf(p, "drm-engine-gpu:\t%llu ns\n", ctx->elapsed_ns);
drm_printf(p, "drm-cycles-gpu:\t%llu\n", ctx->cycles);
drm_printf(p, "drm-maxfreq-gpu:\t%u Hz\n", gpu->fast_rate);
@@ -748,8 +746,6 @@ void msm_gpu_retire(struct msm_gpu *gpu)
/* add bo's to gpu's ring, and kick gpu: */
void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
{
- struct drm_device *dev = gpu->dev;
- struct msm_drm_private *priv = dev->dev_private;
struct msm_ringbuffer *ring = submit->ring;
unsigned long flags;
@@ -761,8 +757,6 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
submit->seqno = submit->hw_fence->seqno;
- msm_rd_dump_submit(priv->rd, submit, NULL);
-
update_sw_cntrs(gpu);
/*
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index e8c93731aaa1..05648c910c68 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -538,6 +538,14 @@ static const struct msm_mdss_data sdm845_data = {
.highest_bank_bit = 2,
};
+static const struct msm_mdss_data sm6350_data = {
+ .ubwc_version = UBWC_2_0,
+ .ubwc_dec_version = UBWC_2_0,
+ .ubwc_swizzle = 6,
+ .ubwc_static = 0x1e,
+ .highest_bank_bit = 1,
+};
+
static const struct msm_mdss_data sm8150_data = {
.ubwc_version = UBWC_3_0,
.ubwc_dec_version = UBWC_3_0,
@@ -571,6 +579,8 @@ static const struct of_device_id mdss_dt_match[] = {
{ .compatible = "qcom,sc8180x-mdss", .data = &sc8180x_data },
{ .compatible = "qcom,sc8280xp-mdss", .data = &sc8280xp_data },
{ .compatible = "qcom,sm6115-mdss", .data = &sm6115_data },
+ { .compatible = "qcom,sm6350-mdss", .data = &sm6350_data },
+ { .compatible = "qcom,sm6375-mdss", .data = &sm6350_data },
{ .compatible = "qcom,sm8150-mdss", .data = &sm8150_data },
{ .compatible = "qcom,sm8250-mdss", .data = &sm8250_data },
{ .compatible = "qcom,sm8350-mdss", .data = &sm8250_data },
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c
index db2f847c8535..8d5687d5ed78 100644
--- a/drivers/gpu/drm/msm/msm_rd.c
+++ b/drivers/gpu/drm/msm/msm_rd.c
@@ -83,15 +83,10 @@ struct msm_rd_state {
bool open;
- /* current submit to read out: */
- struct msm_gem_submit *submit;
-
/* fifo access is synchronized on the producer side by
- * gpu->lock held by submit code (otherwise we could
- * end up w/ cmds logged in different order than they
- * were executed). And read_lock synchronizes the reads
+ * write_lock. And read_lock synchronizes the reads
*/
- struct mutex read_lock;
+ struct mutex read_lock, write_lock;
wait_queue_head_t fifo_event;
struct circ_buf fifo;
@@ -243,6 +238,7 @@ static void rd_cleanup(struct msm_rd_state *rd)
return;
mutex_destroy(&rd->read_lock);
+ mutex_destroy(&rd->write_lock);
kfree(rd);
}
@@ -258,6 +254,7 @@ static struct msm_rd_state *rd_init(struct drm_minor *minor, const char *name)
rd->fifo.buf = rd->buf;
mutex_init(&rd->read_lock);
+ mutex_init(&rd->write_lock);
init_waitqueue_head(&rd->fifo_event);
@@ -338,19 +335,15 @@ static void snapshot_buf(struct msm_rd_state *rd,
if (!(submit->bos[idx].flags & MSM_SUBMIT_BO_READ))
return;
- msm_gem_lock(&obj->base);
buf = msm_gem_get_vaddr_active(&obj->base);
if (IS_ERR(buf))
- goto out_unlock;
+ return;
buf += offset;
rd_write_section(rd, RD_BUFFER_CONTENTS, buf, size);
msm_gem_put_vaddr_locked(&obj->base);
-
-out_unlock:
- msm_gem_unlock(&obj->base);
}
/* called under gpu->lock */
@@ -364,10 +357,7 @@ void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
if (!rd->open)
return;
- /* writing into fifo is serialized by caller, and
- * rd->read_lock is used to serialize the reads
- */
- WARN_ON(!mutex_is_locked(&submit->gpu->lock));
+ mutex_lock(&rd->write_lock);
if (fmt) {
va_list args;
@@ -424,5 +414,7 @@ void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
break;
}
}
+
+ mutex_unlock(&rd->write_lock);
}
#endif
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index 6fb5b469ee5a..c9d8cbb21407 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -9,13 +9,16 @@
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_drv.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -38,21 +41,70 @@ static const struct drm_mode_config_helper_funcs lcdif_mode_config_helpers = {
.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
};
+static const struct drm_encoder_funcs lcdif_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static int lcdif_attach_bridge(struct lcdif_drm_private *lcdif)
{
- struct drm_device *drm = lcdif->drm;
+ struct device *dev = lcdif->drm->dev;
+ struct device_node *ep;
struct drm_bridge *bridge;
int ret;
- bridge = devm_drm_of_get_bridge(drm->dev, drm->dev->of_node, 0, 0);
- if (IS_ERR(bridge))
- return PTR_ERR(bridge);
-
- ret = drm_bridge_attach(&lcdif->encoder, bridge, NULL, 0);
- if (ret)
- return dev_err_probe(drm->dev, ret, "Failed to attach bridge\n");
-
- lcdif->bridge = bridge;
+ for_each_endpoint_of_node(dev->of_node, ep) {
+ struct device_node *remote;
+ struct of_endpoint of_ep;
+ struct drm_encoder *encoder;
+
+ remote = of_graph_get_remote_port_parent(ep);
+ if (!of_device_is_available(remote)) {
+ of_node_put(remote);
+ continue;
+ }
+ of_node_put(remote);
+
+ ret = of_graph_parse_endpoint(ep, &of_ep);
+ if (ret < 0) {
+ dev_err(dev, "Failed to parse endpoint %pOF\n", ep);
+ of_node_put(ep);
+ return ret;
+ }
+
+ bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, of_ep.id);
+ if (IS_ERR(bridge)) {
+ of_node_put(ep);
+ return dev_err_probe(dev, PTR_ERR(bridge),
+ "Failed to get bridge for endpoint%u\n",
+ of_ep.id);
+ }
+
+ encoder = devm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL);
+ if (!encoder) {
+ dev_err(dev, "Failed to allocate encoder for endpoint%u\n",
+ of_ep.id);
+ of_node_put(ep);
+ return -ENOMEM;
+ }
+
+ encoder->possible_crtcs = drm_crtc_mask(&lcdif->crtc);
+ ret = drm_encoder_init(lcdif->drm, encoder, &lcdif_encoder_funcs,
+ DRM_MODE_ENCODER_NONE, NULL);
+ if (ret) {
+ dev_err(dev, "Failed to initialize encoder for endpoint%u: %d\n",
+ of_ep.id, ret);
+ of_node_put(ep);
+ return ret;
+ }
+
+ ret = drm_bridge_attach(encoder, bridge, NULL, 0);
+ if (ret) {
+ of_node_put(ep);
+ return dev_err_probe(dev, ret,
+ "Failed to attach bridge for endpoint%u\n",
+ of_ep.id);
+ }
+ }
return 0;
}
@@ -199,6 +251,7 @@ static const struct drm_driver lcdif_driver = {
static const struct of_device_id lcdif_dt_ids[] = {
{ .compatible = "fsl,imx8mp-lcdif" },
+ { .compatible = "fsl,imx93-lcdif" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, lcdif_dt_ids);
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.h b/drivers/gpu/drm/mxsfb/lcdif_drv.h
index 6cdba6e20c02..61483a4e058d 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.h
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.h
@@ -11,7 +11,6 @@
#include <drm/drm_bridge.h>
#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
-#include <drm/drm_encoder.h>
#include <drm/drm_plane.h>
struct clk;
@@ -30,8 +29,6 @@ struct lcdif_drm_private {
/* i.MXRT does support overlay planes, add them here. */
} planes;
struct drm_crtc crtc;
- struct drm_encoder encoder;
- struct drm_bridge *bridge;
};
static inline struct lcdif_drm_private *
diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index 262bc43b1079..2541d2de4e45 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -17,6 +17,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_color_mgmt.h>
+#include <drm/drm_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_encoder.h>
#include <drm/drm_fb_dma_helper.h>
@@ -30,6 +31,18 @@
#include "lcdif_drv.h"
#include "lcdif_regs.h"
+struct lcdif_crtc_state {
+ struct drm_crtc_state base; /* always be the first member */
+ u32 bus_format;
+ u32 bus_flags;
+};
+
+static inline struct lcdif_crtc_state *
+to_lcdif_crtc_state(struct drm_crtc_state *s)
+{
+ return container_of(s, struct lcdif_crtc_state, base);
+}
+
/* -----------------------------------------------------------------------------
* CRTC
*/
@@ -385,48 +398,108 @@ static void lcdif_reset_block(struct lcdif_drm_private *lcdif)
readl(lcdif->base + LCDC_V8_CTRL);
}
-static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif,
- struct drm_plane_state *plane_state,
- struct drm_bridge_state *bridge_state,
- const u32 bus_format)
+static void lcdif_crtc_mode_set_nofb(struct drm_crtc_state *crtc_state,
+ struct drm_plane_state *plane_state)
{
- struct drm_device *drm = lcdif->crtc.dev;
- struct drm_display_mode *m = &lcdif->crtc.state->adjusted_mode;
- u32 bus_flags = 0;
-
- if (lcdif->bridge && lcdif->bridge->timings)
- bus_flags = lcdif->bridge->timings->input_bus_flags;
- else if (bridge_state)
- bus_flags = bridge_state->input_bus_cfg.flags;
+ struct lcdif_crtc_state *lcdif_crtc_state = to_lcdif_crtc_state(crtc_state);
+ struct drm_device *drm = crtc_state->crtc->dev;
+ struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
+ struct drm_display_mode *m = &crtc_state->adjusted_mode;
DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
m->crtc_clock,
(int)(clk_get_rate(lcdif->clk) / 1000));
DRM_DEV_DEBUG_DRIVER(drm->dev, "Bridge bus_flags: 0x%08X\n",
- bus_flags);
+ lcdif_crtc_state->bus_flags);
DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
/* Mandatory eLCDIF reset as per the Reference Manual */
lcdif_reset_block(lcdif);
- lcdif_set_formats(lcdif, plane_state, bus_format);
+ lcdif_set_formats(lcdif, plane_state, lcdif_crtc_state->bus_format);
- lcdif_set_mode(lcdif, bus_flags);
+ lcdif_set_mode(lcdif, lcdif_crtc_state->bus_flags);
}
static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
+ struct drm_device *drm = crtc->dev;
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
crtc);
+ struct lcdif_crtc_state *lcdif_crtc_state = to_lcdif_crtc_state(crtc_state);
bool has_primary = crtc_state->plane_mask &
drm_plane_mask(crtc->primary);
+ struct drm_connector_state *connector_state;
+ struct drm_connector *connector;
+ struct drm_encoder *encoder;
+ struct drm_bridge_state *bridge_state;
+ struct drm_bridge *bridge;
+ u32 bus_format, bus_flags;
+ bool format_set = false, flags_set = false;
+ int ret, i;
/* The primary plane has to be enabled when the CRTC is active. */
if (crtc_state->active && !has_primary)
return -EINVAL;
- return drm_atomic_add_affected_planes(state, crtc);
+ ret = drm_atomic_add_affected_planes(state, crtc);
+ if (ret)
+ return ret;
+
+ /* Try to find consistent bus format and flags across first bridges. */
+ for_each_new_connector_in_state(state, connector, connector_state, i) {
+ if (!connector_state->crtc)
+ continue;
+
+ encoder = connector_state->best_encoder;
+
+ bridge = drm_bridge_chain_get_first_bridge(encoder);
+ if (!bridge)
+ continue;
+
+ bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
+ if (!bridge_state)
+ bus_format = MEDIA_BUS_FMT_FIXED;
+ else
+ bus_format = bridge_state->input_bus_cfg.format;
+
+ if (bus_format == MEDIA_BUS_FMT_FIXED) {
+ dev_warn(drm->dev,
+ "[ENCODER:%d:%s]'s bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
+ "Please fix bridge driver by handling atomic_get_input_bus_fmts.\n",
+ encoder->base.id, encoder->name);
+ bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+ } else if (!bus_format) {
+ /* If all else fails, default to RGB888_1X24 */
+ bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+ }
+
+ if (!format_set) {
+ lcdif_crtc_state->bus_format = bus_format;
+ format_set = true;
+ } else if (lcdif_crtc_state->bus_format != bus_format) {
+ DRM_DEV_DEBUG_DRIVER(drm->dev, "inconsistent bus format\n");
+ return -EINVAL;
+ }
+
+ if (bridge->timings)
+ bus_flags = bridge->timings->input_bus_flags;
+ else if (bridge_state)
+ bus_flags = bridge_state->input_bus_cfg.flags;
+ else
+ bus_flags = 0;
+
+ if (!flags_set) {
+ lcdif_crtc_state->bus_flags = bus_flags;
+ flags_set = true;
+ } else if (lcdif_crtc_state->bus_flags != bus_flags) {
+ DRM_DEV_DEBUG_DRIVER(drm->dev, "inconsistent bus flags\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
}
static void lcdif_crtc_atomic_flush(struct drm_crtc *crtc,
@@ -458,41 +531,18 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev);
+ struct drm_crtc_state *new_cstate = drm_atomic_get_new_crtc_state(state, crtc);
struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state,
crtc->primary);
struct drm_display_mode *m = &lcdif->crtc.state->adjusted_mode;
- struct drm_bridge_state *bridge_state = NULL;
struct drm_device *drm = lcdif->drm;
- u32 bus_format = 0;
dma_addr_t paddr;
- /* If there is a bridge attached to the LCDIF, use its bus format */
- if (lcdif->bridge) {
- bridge_state =
- drm_atomic_get_new_bridge_state(state,
- lcdif->bridge);
- if (!bridge_state)
- bus_format = MEDIA_BUS_FMT_FIXED;
- else
- bus_format = bridge_state->input_bus_cfg.format;
-
- if (bus_format == MEDIA_BUS_FMT_FIXED) {
- dev_warn_once(drm->dev,
- "Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
- "Please fix bridge driver by handling atomic_get_input_bus_fmts.\n");
- bus_format = MEDIA_BUS_FMT_RGB888_1X24;
- }
- }
-
- /* If all else fails, default to RGB888_1X24 */
- if (!bus_format)
- bus_format = MEDIA_BUS_FMT_RGB888_1X24;
-
clk_set_rate(lcdif->clk, m->crtc_clock * 1000);
pm_runtime_get_sync(drm->dev);
- lcdif_crtc_mode_set_nofb(lcdif, new_pstate, bridge_state, bus_format);
+ lcdif_crtc_mode_set_nofb(new_cstate, new_pstate);
/* Write cur_buf as well to avoid an initial corrupt frame */
paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
@@ -529,6 +579,48 @@ static void lcdif_crtc_atomic_disable(struct drm_crtc *crtc,
pm_runtime_put_sync(drm->dev);
}
+static void lcdif_crtc_atomic_destroy_state(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ __drm_atomic_helper_crtc_destroy_state(state);
+ kfree(to_lcdif_crtc_state(state));
+}
+
+static void lcdif_crtc_reset(struct drm_crtc *crtc)
+{
+ struct lcdif_crtc_state *state;
+
+ if (crtc->state)
+ lcdif_crtc_atomic_destroy_state(crtc, crtc->state);
+
+ crtc->state = NULL;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (state)
+ __drm_atomic_helper_crtc_reset(crtc, &state->base);
+}
+
+static struct drm_crtc_state *
+lcdif_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
+{
+ struct lcdif_crtc_state *old = to_lcdif_crtc_state(crtc->state);
+ struct lcdif_crtc_state *new;
+
+ if (WARN_ON(!crtc->state))
+ return NULL;
+
+ new = kzalloc(sizeof(*new), GFP_KERNEL);
+ if (!new)
+ return NULL;
+
+ __drm_atomic_helper_crtc_duplicate_state(crtc, &new->base);
+
+ new->bus_format = old->bus_format;
+ new->bus_flags = old->bus_flags;
+
+ return &new->base;
+}
+
static int lcdif_crtc_enable_vblank(struct drm_crtc *crtc)
{
struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev);
@@ -557,25 +649,17 @@ static const struct drm_crtc_helper_funcs lcdif_crtc_helper_funcs = {
};
static const struct drm_crtc_funcs lcdif_crtc_funcs = {
- .reset = drm_atomic_helper_crtc_reset,
+ .reset = lcdif_crtc_reset,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
- .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+ .atomic_duplicate_state = lcdif_crtc_atomic_duplicate_state,
+ .atomic_destroy_state = lcdif_crtc_atomic_destroy_state,
.enable_vblank = lcdif_crtc_enable_vblank,
.disable_vblank = lcdif_crtc_disable_vblank,
};
/* -----------------------------------------------------------------------------
- * Encoder
- */
-
-static const struct drm_encoder_funcs lcdif_encoder_funcs = {
- .destroy = drm_encoder_cleanup,
-};
-
-/* -----------------------------------------------------------------------------
* Planes
*/
@@ -667,7 +751,6 @@ int lcdif_kms_init(struct lcdif_drm_private *lcdif)
BIT(DRM_COLOR_YCBCR_BT2020);
const u32 supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
BIT(DRM_COLOR_YCBCR_FULL_RANGE);
- struct drm_encoder *encoder = &lcdif->encoder;
struct drm_crtc *crtc = &lcdif->crtc;
int ret;
@@ -691,13 +774,7 @@ int lcdif_kms_init(struct lcdif_drm_private *lcdif)
return ret;
drm_crtc_helper_add(crtc, &lcdif_crtc_helper_funcs);
- ret = drm_crtc_init_with_planes(lcdif->drm, crtc,
- &lcdif->planes.primary, NULL,
- &lcdif_crtc_funcs, NULL);
- if (ret)
- return ret;
-
- encoder->possible_crtcs = drm_crtc_mask(crtc);
- return drm_encoder_init(lcdif->drm, encoder, &lcdif_encoder_funcs,
- DRM_MODE_ENCODER_NONE, NULL);
+ return drm_crtc_init_with_planes(lcdif->drm, crtc,
+ &lcdif->planes.primary, NULL,
+ &lcdif_crtc_funcs, NULL);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 5bb777ff1313..42e1665ba11a 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -64,6 +64,7 @@
#include "nouveau_connector.h"
#include "nouveau_encoder.h"
#include "nouveau_fence.h"
+#include "nv50_display.h"
#include <subdev/bios/dp.h>
@@ -1358,22 +1359,26 @@ nv50_mstm_service(struct nouveau_drm *drm,
u8 esi[8] = {};
while (handled) {
+ u8 ack[8] = {};
+
rc = drm_dp_dpcd_read(aux, DP_SINK_COUNT_ESI, esi, 8);
if (rc != 8) {
ret = false;
break;
}
- drm_dp_mst_hpd_irq(&mstm->mgr, esi, &handled);
+ drm_dp_mst_hpd_irq_handle_event(&mstm->mgr, esi, ack, &handled);
if (!handled)
break;
- rc = drm_dp_dpcd_write(aux, DP_SINK_COUNT_ESI + 1, &esi[1],
- 3);
- if (rc != 3) {
+ rc = drm_dp_dpcd_writeb(aux, DP_SINK_COUNT_ESI + 1, ack[1]);
+
+ if (rc != 1) {
ret = false;
break;
}
+
+ drm_dp_mst_hpd_irq_send_new_request(&mstm->mgr);
}
if (!ret)
diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
index 2a36d1ca8fda..99d022a91afc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
@@ -73,13 +73,14 @@ nouveau_debugfs_pstate_get(struct seq_file *m, void *data)
{
struct drm_device *drm = m->private;
struct nouveau_debugfs *debugfs = nouveau_debugfs(drm);
- struct nvif_object *ctrl = &debugfs->ctrl;
+ struct nvif_object *ctrl;
struct nvif_control_pstate_info_v0 info = {};
int ret, i;
if (!debugfs)
return -ENODEV;
+ ctrl = &debugfs->ctrl;
ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_INFO, &info, sizeof(info));
if (ret)
return ret;
@@ -119,19 +120,19 @@ nouveau_debugfs_pstate_get(struct seq_file *m, void *data)
if (state >= 0) {
if (info.ustate_ac == state)
- seq_printf(m, " AC");
+ seq_puts(m, " AC");
if (info.ustate_dc == state)
- seq_printf(m, " DC");
+ seq_puts(m, " DC");
if (info.pstate == state)
- seq_printf(m, " *");
+ seq_puts(m, " *");
} else {
if (info.ustate_ac < -1)
- seq_printf(m, " AC");
+ seq_puts(m, " AC");
if (info.ustate_dc < -1)
- seq_printf(m, " DC");
+ seq_puts(m, " DC");
}
- seq_printf(m, "\n");
+ seq_putc(m, '\n');
}
return 0;
@@ -144,7 +145,6 @@ nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf,
struct seq_file *m = file->private_data;
struct drm_device *drm = m->private;
struct nouveau_debugfs *debugfs = nouveau_debugfs(drm);
- struct nvif_object *ctrl = &debugfs->ctrl;
struct nvif_control_pstate_user_v0 args = { .pwrsrc = -EINVAL };
char buf[32] = {}, *tmp, *cur = buf;
long value, ret;
@@ -188,7 +188,8 @@ nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf,
return ret;
}
- ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_USER, &args, sizeof(args));
+ ret = nvif_mthd(&debugfs->ctrl, NVIF_CONTROL_PSTATE_USER,
+ &args, sizeof(args));
pm_runtime_put_autosuspend(drm->dev);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_hwmon.c b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
index e844be49e11e..db30a4c2cd4d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_hwmon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
@@ -211,7 +211,7 @@ static const struct attribute_group temp1_auto_point_sensor_group = {
#define N_ATTR_GROUPS 3
-static const struct hwmon_channel_info *nouveau_info[] = {
+static const struct hwmon_channel_info * const nouveau_info[] = {
HWMON_CHANNEL_INFO(chip,
HWMON_C_UPDATE_INTERVAL),
HWMON_CHANNEL_INFO(temp,
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c
index 1469a88910e4..486f39f31a38 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -24,9 +24,9 @@
*/
#include <linux/limits.h>
-#include <linux/swiotlb.h>
#include <drm/ttm/ttm_range_manager.h>
+#include <drm/drm_cache.h>
#include "nouveau_drv.h"
#include "nouveau_gem.h"
@@ -265,7 +265,6 @@ nouveau_ttm_init(struct nouveau_drm *drm)
struct nvkm_pci *pci = device->pci;
struct nvif_mmu *mmu = &drm->client.mmu;
struct drm_device *dev = drm->dev;
- bool need_swiotlb = false;
int typei, ret;
ret = nouveau_ttm_init_host(drm, 0);
@@ -300,13 +299,10 @@ nouveau_ttm_init(struct nouveau_drm *drm)
drm->agp.cma = pci->agp.cma;
}
-#if IS_ENABLED(CONFIG_SWIOTLB) && IS_ENABLED(CONFIG_X86)
- need_swiotlb = is_swiotlb_active(dev->dev);
-#endif
-
ret = ttm_device_init(&drm->ttm.bdev, &nouveau_bo_driver, drm->dev->dev,
dev->anon_inode->i_mapping,
- dev->vma_offset_manager, need_swiotlb,
+ dev->vma_offset_manager,
+ drm_need_swiotlb(drm->client.mmu.dmabits),
drm->client.mmu.dmabits <= 32);
if (ret) {
NV_ERROR(drm, "error initialising bo driver, %d\n", ret);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h
index fbd3b15583bc..60f77766766e 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.h
+++ b/drivers/gpu/drm/nouveau/nv50_display.h
@@ -31,7 +31,5 @@
#include "nouveau_reg.h"
int nv50_display_create(struct drm_device *);
-void nv50_display_destroy(struct drm_device *);
-int nv50_display_init(struct drm_device *);
-void nv50_display_fini(struct drm_device *);
+
#endif /* __NV50_DISPLAY_H__ */
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/power_budget.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/power_budget.c
index 03d2f970a29f..2ba992bdb19d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/power_budget.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/power_budget.c
@@ -59,7 +59,6 @@ int
nvbios_power_budget_header(struct nvkm_bios *bios,
struct nvbios_power_budget *budget)
{
- struct nvkm_subdev *subdev = &bios->subdev;
u8 ver, hdr, cnt, len, cap_entry;
u32 header;
@@ -82,7 +81,7 @@ nvbios_power_budget_header(struct nvkm_bios *bios,
}
if (cap_entry >= cnt && cap_entry != 0xff) {
- nvkm_warn(subdev,
+ nvkm_warn(&bios->subdev,
"invalid cap_entry in power budget table found\n");
budget->cap_entry = 0xff;
return -EINVAL;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
index da07a2fbef06..178dc56909c2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
@@ -417,7 +417,6 @@ nvkm_pstate_new(struct nvkm_clk *clk, int idx)
return 0;
pstate = kzalloc(sizeof(*pstate), GFP_KERNEL);
- cstate = &pstate->base;
if (!pstate)
return -ENOMEM;
@@ -427,6 +426,7 @@ nvkm_pstate_new(struct nvkm_clk *clk, int idx)
pstate->fanspeed = perfE.fanspeed;
pstate->pcie_speed = perfE.pcie_speed;
pstate->pcie_width = perfE.pcie_width;
+ cstate = &pstate->base;
cstate->voltage = perfE.voltage;
cstate->domain[nv_clk_src_core] = perfE.core;
cstate->domain[nv_clk_src_shader] = perfE.shader;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c
index 525267412c3e..a3996ceca995 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c
@@ -45,7 +45,7 @@ ga102_gsp_nofw(struct nvkm_gsp *gsp, int ver, const struct nvkm_gsp_fwif *fwif)
return 0;
}
-struct nvkm_gsp_fwif
+static struct nvkm_gsp_fwif
ga102_gsps[] = {
{ -1, ga102_gsp_nofw, &ga102_gsp },
{}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/pcie.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/pcie.c
index d71e5db5028a..dd18d9d0bade 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/pcie.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/pcie.c
@@ -114,18 +114,17 @@ nvkm_pcie_init(struct nvkm_pci *pci)
int
nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
{
- struct nvkm_subdev *subdev = &pci->subdev;
+ struct nvkm_subdev *subdev;
enum nvkm_pcie_speed cur_speed, max_speed;
- struct pci_bus *pbus;
int ret;
if (!pci || !pci_is_pcie(pci->pdev))
return 0;
- pbus = pci->pdev->bus;
if (!pci->func->pcie.set_link)
return -ENOSYS;
+ subdev = &pci->subdev;
nvkm_trace(subdev, "requested %s\n", nvkm_pcie_speeds[speed]);
if (pci->func->pcie.version(pci) < 2) {
@@ -134,7 +133,7 @@ nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
}
cur_speed = pci->func->pcie.cur_speed(pci);
- max_speed = min(nvkm_pcie_speed(pbus->max_bus_speed),
+ max_speed = min(nvkm_pcie_speed(pci->pdev->bus->max_bus_speed),
pci->func->pcie.max_speed(pci));
nvkm_trace(subdev, "current speed: %s\n", nvkm_pcie_speeds[cur_speed]);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c
index 340f37a299dc..b13ba9b2f6be 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c
@@ -98,10 +98,10 @@ nvkm_fanpwm_create(struct nvkm_therm *therm, struct dcb_gpio_func *func)
return -ENODEV;
fan = kzalloc(sizeof(*fan), GFP_KERNEL);
- therm->fan = &fan->base;
if (!fan)
return -ENOMEM;
+ therm->fan = &fan->base;
fan->base.type = "PWM";
fan->base.get = nvkm_fanpwm_get;
fan->base.set = nvkm_fanpwm_set;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c
index ff9fbe7950e5..bfdf4ca5625c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c
@@ -100,10 +100,10 @@ nvkm_fantog_create(struct nvkm_therm *therm, struct dcb_gpio_func *func)
}
fan = kzalloc(sizeof(*fan), GFP_KERNEL);
- therm->fan = &fan->base;
if (!fan)
return -ENOMEM;
+ therm->fan = &fan->base;
fan->base.type = "toggle";
fan->base.get = nvkm_fantog_get;
fan->base.set = nvkm_fantog_set;
diff --git a/drivers/gpu/drm/omapdrm/Kconfig b/drivers/gpu/drm/omapdrm/Kconfig
index 76ded1568bd0..b4ac76c9f31b 100644
--- a/drivers/gpu/drm/omapdrm/Kconfig
+++ b/drivers/gpu/drm/omapdrm/Kconfig
@@ -4,6 +4,7 @@ config DRM_OMAP
depends on DRM && OF
depends on ARCH_OMAP2PLUS
select DRM_KMS_HELPER
+ select FB_SYS_HELPERS if DRM_FBDEV_EMULATION
select VIDEOMODE_HELPERS
select HDMI
default n
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
index b950e93b3846..b7ccce0704a3 100644
--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
+++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
@@ -4,6 +4,8 @@
* Author: Rob Clark <rob@ti.com>
*/
+#include <linux/fb.h>
+
#include <drm/drm_drv.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
@@ -95,20 +97,13 @@ static void omap_fbdev_fb_destroy(struct fb_info *info)
static const struct fb_ops omap_fb_ops = {
.owner = THIS_MODULE,
-
+ FB_DEFAULT_SYS_OPS,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
.fb_setcmap = drm_fb_helper_setcmap,
.fb_blank = drm_fb_helper_blank,
.fb_pan_display = omap_fbdev_pan_display,
.fb_ioctl = drm_fb_helper_ioctl,
-
- .fb_read = drm_fb_helper_sys_read,
- .fb_write = drm_fb_helper_sys_write,
- .fb_fillrect = drm_fb_helper_sys_fillrect,
- .fb_copyarea = drm_fb_helper_sys_copyarea,
- .fb_imageblit = drm_fb_helper_sys_imageblit,
-
.fb_destroy = omap_fbdev_fb_destroy,
};
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 2b9d6db7860b..203c0ef0bbfd 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -553,6 +553,13 @@ config DRM_PANEL_SAMSUNG_S6D27A1
This panel can be found in Samsung Galaxy Ace 2
GT-I8160 mobile phone.
+config DRM_PANEL_SAMSUNG_S6D7AA0
+ tristate "Samsung S6D7AA0 MIPI-DSI video mode panel controller"
+ depends on OF
+ depends on BACKLIGHT_CLASS_DEVICE
+ select DRM_MIPI_DSI
+ select VIDEOMODE_HELPERS
+
config DRM_PANEL_SAMSUNG_S6E3HA2
tristate "Samsung S6E3HA2 DSI video mode panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index ff169781e82d..30cf553c8d1d 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D27A1) += panel-samsung-s6d27a1.o
+obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D7AA0) += panel-samsung-s6d7aa0.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o
diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
index 783234ae0f57..3cc9fb0d4f5d 100644
--- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
+++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
@@ -36,6 +36,7 @@ struct panel_desc {
const struct panel_init_cmd *init_cmds;
unsigned int lanes;
bool discharge_on_disable;
+ bool lp11_before_reset;
};
struct boe_panel {
@@ -451,11 +452,14 @@ static const struct panel_init_cmd inx_hj110iz_init_cmd[] = {
_INIT_DCS_CMD(0xFF, 0x20),
_INIT_DCS_CMD(0xFB, 0x01),
_INIT_DCS_CMD(0x05, 0xD1),
- _INIT_DCS_CMD(0x0D, 0x63),
- _INIT_DCS_CMD(0x07, 0x8C),
+ _INIT_DCS_CMD(0x06, 0xC0),
+ _INIT_DCS_CMD(0x07, 0x87),
_INIT_DCS_CMD(0x08, 0x4B),
+
+ _INIT_DCS_CMD(0x0D, 0x63),
_INIT_DCS_CMD(0x0E, 0x91),
_INIT_DCS_CMD(0x0F, 0x69),
+ _INIT_DCS_CMD(0x94, 0x00),
_INIT_DCS_CMD(0x95, 0xF5),
_INIT_DCS_CMD(0x96, 0xF5),
_INIT_DCS_CMD(0x9D, 0x00),
@@ -463,98 +467,96 @@ static const struct panel_init_cmd inx_hj110iz_init_cmd[] = {
_INIT_DCS_CMD(0x69, 0x98),
_INIT_DCS_CMD(0x75, 0xA2),
_INIT_DCS_CMD(0x77, 0xB3),
+
+ _INIT_DCS_CMD(0x58, 0x43),
_INIT_DCS_CMD(0xFF, 0x24),
_INIT_DCS_CMD(0xFB, 0x01),
_INIT_DCS_CMD(0x91, 0x44),
- _INIT_DCS_CMD(0x92, 0x7A),
- _INIT_DCS_CMD(0x93, 0x1A),
- _INIT_DCS_CMD(0x94, 0x40),
- _INIT_DCS_CMD(0x9A, 0x08),
+ _INIT_DCS_CMD(0x92, 0x4C),
+ _INIT_DCS_CMD(0x94, 0x86),
_INIT_DCS_CMD(0x60, 0x96),
_INIT_DCS_CMD(0x61, 0xD0),
_INIT_DCS_CMD(0x63, 0x70),
- _INIT_DCS_CMD(0xC2, 0xCF),
- _INIT_DCS_CMD(0x9B, 0x0F),
- _INIT_DCS_CMD(0x9A, 0x08),
+ _INIT_DCS_CMD(0xC2, 0xCA),
+
_INIT_DCS_CMD(0x00, 0x03),
_INIT_DCS_CMD(0x01, 0x03),
_INIT_DCS_CMD(0x02, 0x03),
- _INIT_DCS_CMD(0x03, 0x03),
- _INIT_DCS_CMD(0x04, 0x03),
- _INIT_DCS_CMD(0x05, 0x03),
- _INIT_DCS_CMD(0x06, 0x22),
- _INIT_DCS_CMD(0x07, 0x06),
- _INIT_DCS_CMD(0x08, 0x00),
- _INIT_DCS_CMD(0x09, 0x1D),
- _INIT_DCS_CMD(0x0A, 0x1C),
- _INIT_DCS_CMD(0x0B, 0x13),
- _INIT_DCS_CMD(0x0C, 0x12),
- _INIT_DCS_CMD(0x0D, 0x11),
- _INIT_DCS_CMD(0x0E, 0x10),
- _INIT_DCS_CMD(0x0F, 0x0F),
- _INIT_DCS_CMD(0x10, 0x0E),
- _INIT_DCS_CMD(0x11, 0x0D),
- _INIT_DCS_CMD(0x12, 0x0C),
+ _INIT_DCS_CMD(0x03, 0x29),
+ _INIT_DCS_CMD(0x04, 0x22),
+ _INIT_DCS_CMD(0x05, 0x22),
+ _INIT_DCS_CMD(0x06, 0x0B),
+ _INIT_DCS_CMD(0x07, 0x1D),
+ _INIT_DCS_CMD(0x08, 0x1C),
+ _INIT_DCS_CMD(0x09, 0x05),
+ _INIT_DCS_CMD(0x0A, 0x08),
+ _INIT_DCS_CMD(0x0B, 0x09),
+ _INIT_DCS_CMD(0x0C, 0x0A),
+ _INIT_DCS_CMD(0x0D, 0x0C),
+ _INIT_DCS_CMD(0x0E, 0x0D),
+ _INIT_DCS_CMD(0x0F, 0x0E),
+ _INIT_DCS_CMD(0x10, 0x0F),
+ _INIT_DCS_CMD(0x11, 0x10),
+ _INIT_DCS_CMD(0x12, 0x11),
_INIT_DCS_CMD(0x13, 0x04),
- _INIT_DCS_CMD(0x14, 0x03),
+ _INIT_DCS_CMD(0x14, 0x00),
_INIT_DCS_CMD(0x15, 0x03),
_INIT_DCS_CMD(0x16, 0x03),
_INIT_DCS_CMD(0x17, 0x03),
_INIT_DCS_CMD(0x18, 0x03),
- _INIT_DCS_CMD(0x19, 0x03),
- _INIT_DCS_CMD(0x1A, 0x03),
- _INIT_DCS_CMD(0x1B, 0x03),
- _INIT_DCS_CMD(0x1C, 0x22),
- _INIT_DCS_CMD(0x1D, 0x06),
- _INIT_DCS_CMD(0x1E, 0x00),
- _INIT_DCS_CMD(0x1F, 0x1D),
- _INIT_DCS_CMD(0x20, 0x1C),
- _INIT_DCS_CMD(0x21, 0x13),
- _INIT_DCS_CMD(0x22, 0x12),
- _INIT_DCS_CMD(0x23, 0x11),
- _INIT_DCS_CMD(0x24, 0x10),
- _INIT_DCS_CMD(0x25, 0x0F),
- _INIT_DCS_CMD(0x26, 0x0E),
- _INIT_DCS_CMD(0x27, 0x0D),
- _INIT_DCS_CMD(0x28, 0x0C),
+ _INIT_DCS_CMD(0x19, 0x29),
+ _INIT_DCS_CMD(0x1A, 0x22),
+ _INIT_DCS_CMD(0x1B, 0x22),
+ _INIT_DCS_CMD(0x1C, 0x0B),
+ _INIT_DCS_CMD(0x1D, 0x1D),
+ _INIT_DCS_CMD(0x1E, 0x1C),
+ _INIT_DCS_CMD(0x1F, 0x05),
+ _INIT_DCS_CMD(0x20, 0x08),
+ _INIT_DCS_CMD(0x21, 0x09),
+ _INIT_DCS_CMD(0x22, 0x0A),
+ _INIT_DCS_CMD(0x23, 0x0C),
+ _INIT_DCS_CMD(0x24, 0x0D),
+ _INIT_DCS_CMD(0x25, 0x0E),
+ _INIT_DCS_CMD(0x26, 0x0F),
+ _INIT_DCS_CMD(0x27, 0x10),
+ _INIT_DCS_CMD(0x28, 0x11),
_INIT_DCS_CMD(0x29, 0x04),
- _INIT_DCS_CMD(0x2A, 0x03),
+ _INIT_DCS_CMD(0x2A, 0x00),
_INIT_DCS_CMD(0x2B, 0x03),
- _INIT_DCS_CMD(0x2F, 0x05),
- _INIT_DCS_CMD(0x30, 0x32),
- _INIT_DCS_CMD(0x31, 0x43),
- _INIT_DCS_CMD(0x33, 0x05),
- _INIT_DCS_CMD(0x34, 0x32),
- _INIT_DCS_CMD(0x35, 0x43),
- _INIT_DCS_CMD(0x37, 0x44),
- _INIT_DCS_CMD(0x38, 0x40),
+ _INIT_DCS_CMD(0x2F, 0x0A),
+ _INIT_DCS_CMD(0x30, 0x35),
+ _INIT_DCS_CMD(0x37, 0xA7),
_INIT_DCS_CMD(0x39, 0x00),
- _INIT_DCS_CMD(0x3A, 0x18),
- _INIT_DCS_CMD(0x3B, 0x00),
- _INIT_DCS_CMD(0x3D, 0x93),
- _INIT_DCS_CMD(0xAB, 0x44),
- _INIT_DCS_CMD(0xAC, 0x40),
+ _INIT_DCS_CMD(0x3A, 0x46),
+ _INIT_DCS_CMD(0x3B, 0x32),
+ _INIT_DCS_CMD(0x3D, 0x12),
+
+ _INIT_DCS_CMD(0x3F, 0x33),
+ _INIT_DCS_CMD(0x40, 0x31),
+ _INIT_DCS_CMD(0x41, 0x40),
+ _INIT_DCS_CMD(0x42, 0x42),
+ _INIT_DCS_CMD(0x47, 0x77),
+ _INIT_DCS_CMD(0x48, 0x77),
+ _INIT_DCS_CMD(0x4A, 0x45),
+ _INIT_DCS_CMD(0x4B, 0x45),
+ _INIT_DCS_CMD(0x4C, 0x14),
_INIT_DCS_CMD(0x4D, 0x21),
_INIT_DCS_CMD(0x4E, 0x43),
_INIT_DCS_CMD(0x4F, 0x65),
- _INIT_DCS_CMD(0x50, 0x87),
- _INIT_DCS_CMD(0x51, 0x78),
- _INIT_DCS_CMD(0x52, 0x56),
- _INIT_DCS_CMD(0x53, 0x34),
- _INIT_DCS_CMD(0x54, 0x21),
- _INIT_DCS_CMD(0x55, 0x83),
- _INIT_DCS_CMD(0x56, 0x08),
+ _INIT_DCS_CMD(0x55, 0x06),
+ _INIT_DCS_CMD(0x56, 0x06),
_INIT_DCS_CMD(0x58, 0x21),
- _INIT_DCS_CMD(0x59, 0x40),
- _INIT_DCS_CMD(0x5A, 0x00),
- _INIT_DCS_CMD(0x5B, 0x2C),
- _INIT_DCS_CMD(0x5E, 0x00, 0x10),
+ _INIT_DCS_CMD(0x59, 0x70),
+ _INIT_DCS_CMD(0x5A, 0x46),
+ _INIT_DCS_CMD(0x5B, 0x32),
+ _INIT_DCS_CMD(0x5C, 0x88),
+ _INIT_DCS_CMD(0x5E, 0x00, 0x00),
_INIT_DCS_CMD(0x5F, 0x00),
- _INIT_DCS_CMD(0x7A, 0x00),
- _INIT_DCS_CMD(0x7B, 0x00),
+ _INIT_DCS_CMD(0x7A, 0xFF),
+ _INIT_DCS_CMD(0x7B, 0xFF),
_INIT_DCS_CMD(0x7C, 0x00),
_INIT_DCS_CMD(0x7D, 0x00),
_INIT_DCS_CMD(0x7E, 0x20),
@@ -564,152 +566,183 @@ static const struct panel_init_cmd inx_hj110iz_init_cmd[] = {
_INIT_DCS_CMD(0x82, 0x08),
_INIT_DCS_CMD(0x97, 0x02),
_INIT_DCS_CMD(0xC5, 0x10),
+
+ _INIT_DCS_CMD(0xD7, 0x55),
+ _INIT_DCS_CMD(0xD8, 0x55),
+ _INIT_DCS_CMD(0xD9, 0x23),
_INIT_DCS_CMD(0xDA, 0x05),
_INIT_DCS_CMD(0xDB, 0x01),
- _INIT_DCS_CMD(0xDC, 0x7A),
+ _INIT_DCS_CMD(0xDC, 0x65),
_INIT_DCS_CMD(0xDD, 0x55),
_INIT_DCS_CMD(0xDE, 0x27),
_INIT_DCS_CMD(0xDF, 0x01),
- _INIT_DCS_CMD(0xE0, 0x7A),
+ _INIT_DCS_CMD(0xE0, 0x65),
_INIT_DCS_CMD(0xE1, 0x01),
- _INIT_DCS_CMD(0xE2, 0x7A),
+ _INIT_DCS_CMD(0xE2, 0x65),
_INIT_DCS_CMD(0xE3, 0x01),
- _INIT_DCS_CMD(0xE4, 0x7A),
+ _INIT_DCS_CMD(0xE4, 0x65),
_INIT_DCS_CMD(0xE5, 0x01),
- _INIT_DCS_CMD(0xE6, 0x7A),
+ _INIT_DCS_CMD(0xE6, 0x65),
_INIT_DCS_CMD(0xE7, 0x00),
_INIT_DCS_CMD(0xE8, 0x00),
_INIT_DCS_CMD(0xE9, 0x01),
- _INIT_DCS_CMD(0xEA, 0x7A),
+ _INIT_DCS_CMD(0xEA, 0x65),
_INIT_DCS_CMD(0xEB, 0x01),
- _INIT_DCS_CMD(0xEE, 0x7A),
+ _INIT_DCS_CMD(0xEE, 0x65),
_INIT_DCS_CMD(0xEF, 0x01),
- _INIT_DCS_CMD(0xF0, 0x7A),
-
+ _INIT_DCS_CMD(0xF0, 0x65),
_INIT_DCS_CMD(0xB6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00),
+
_INIT_DCS_CMD(0xFF, 0x25),
- _INIT_DCS_CMD(0xFB, 0x01),
+ _INIT_DCS_CMD(0xFB, 0x01),
_INIT_DCS_CMD(0x05, 0x00),
-
- _INIT_DCS_CMD(0x13, 0x02),
- _INIT_DCS_CMD(0x14, 0xDF),
_INIT_DCS_CMD(0xF1, 0x10),
+
_INIT_DCS_CMD(0x1E, 0x00),
- _INIT_DCS_CMD(0x1F, 0x00),
- _INIT_DCS_CMD(0x20, 0x2C),
+ _INIT_DCS_CMD(0x1F, 0x46),
+ _INIT_DCS_CMD(0x20, 0x32),
+
_INIT_DCS_CMD(0x25, 0x00),
- _INIT_DCS_CMD(0x26, 0x00),
- _INIT_DCS_CMD(0x27, 0x2C),
+ _INIT_DCS_CMD(0x26, 0x46),
+ _INIT_DCS_CMD(0x27, 0x32),
+
_INIT_DCS_CMD(0x3F, 0x80),
_INIT_DCS_CMD(0x40, 0x00),
_INIT_DCS_CMD(0x43, 0x00),
- _INIT_DCS_CMD(0x44, 0x18),
- _INIT_DCS_CMD(0x45, 0x00),
+ _INIT_DCS_CMD(0x44, 0x46),
+ _INIT_DCS_CMD(0x45, 0x46),
+
+ _INIT_DCS_CMD(0x48, 0x46),
+ _INIT_DCS_CMD(0x49, 0x32),
- _INIT_DCS_CMD(0x48, 0x00),
- _INIT_DCS_CMD(0x49, 0x2C),
_INIT_DCS_CMD(0x5B, 0x80),
+
_INIT_DCS_CMD(0x5C, 0x00),
- _INIT_DCS_CMD(0x5D, 0x00),
- _INIT_DCS_CMD(0x5E, 0x00),
- _INIT_DCS_CMD(0x61, 0x00),
- _INIT_DCS_CMD(0x62, 0x2C),
- _INIT_DCS_CMD(0x68, 0x10),
+ _INIT_DCS_CMD(0x5D, 0x46),
+ _INIT_DCS_CMD(0x5E, 0x32),
+
+ _INIT_DCS_CMD(0x5F, 0x46),
+ _INIT_DCS_CMD(0x60, 0x32),
+
+ _INIT_DCS_CMD(0x61, 0x46),
+ _INIT_DCS_CMD(0x62, 0x32),
+ _INIT_DCS_CMD(0x68, 0x0C),
+
+ _INIT_DCS_CMD(0x6C, 0x0D),
+ _INIT_DCS_CMD(0x6E, 0x0D),
+ _INIT_DCS_CMD(0x78, 0x00),
+ _INIT_DCS_CMD(0x79, 0xC5),
+ _INIT_DCS_CMD(0x7A, 0x0C),
+ _INIT_DCS_CMD(0x7B, 0xB0),
+
_INIT_DCS_CMD(0xFF, 0x26),
_INIT_DCS_CMD(0xFB, 0x01),
_INIT_DCS_CMD(0x00, 0xA1),
_INIT_DCS_CMD(0x02, 0x31),
- _INIT_DCS_CMD(0x0A, 0xF2),
- _INIT_DCS_CMD(0x04, 0x28),
+ _INIT_DCS_CMD(0x0A, 0xF4),
+ _INIT_DCS_CMD(0x04, 0x50),
_INIT_DCS_CMD(0x06, 0x30),
_INIT_DCS_CMD(0x0C, 0x16),
_INIT_DCS_CMD(0x0D, 0x0D),
_INIT_DCS_CMD(0x0F, 0x00),
_INIT_DCS_CMD(0x11, 0x00),
_INIT_DCS_CMD(0x12, 0x50),
- _INIT_DCS_CMD(0x13, 0x56),
- _INIT_DCS_CMD(0x14, 0x57),
+ _INIT_DCS_CMD(0x13, 0x40),
+ _INIT_DCS_CMD(0x14, 0x58),
_INIT_DCS_CMD(0x15, 0x00),
_INIT_DCS_CMD(0x16, 0x10),
_INIT_DCS_CMD(0x17, 0xA0),
_INIT_DCS_CMD(0x18, 0x86),
_INIT_DCS_CMD(0x22, 0x00),
_INIT_DCS_CMD(0x23, 0x00),
- _INIT_DCS_CMD(0x19, 0x0D),
- _INIT_DCS_CMD(0x1A, 0x7F),
- _INIT_DCS_CMD(0x1B, 0x0C),
- _INIT_DCS_CMD(0x1C, 0xBF),
- _INIT_DCS_CMD(0x2A, 0x0D),
- _INIT_DCS_CMD(0x2B, 0x7F),
- _INIT_DCS_CMD(0x20, 0x00),
+
+ _INIT_DCS_CMD(0x19, 0x0E),
+ _INIT_DCS_CMD(0x1A, 0x31),
+ _INIT_DCS_CMD(0x1B, 0x0D),
+ _INIT_DCS_CMD(0x1C, 0x29),
+ _INIT_DCS_CMD(0x2A, 0x0E),
+ _INIT_DCS_CMD(0x2B, 0x31),
_INIT_DCS_CMD(0x1D, 0x00),
- _INIT_DCS_CMD(0x1E, 0x78),
- _INIT_DCS_CMD(0x1F, 0x78),
+ _INIT_DCS_CMD(0x1E, 0x62),
+ _INIT_DCS_CMD(0x1F, 0x62),
- _INIT_DCS_CMD(0x2F, 0x03),
- _INIT_DCS_CMD(0x30, 0x78),
- _INIT_DCS_CMD(0x33, 0x78),
- _INIT_DCS_CMD(0x34, 0x66),
- _INIT_DCS_CMD(0x35, 0x11),
+ _INIT_DCS_CMD(0x2F, 0x06),
+ _INIT_DCS_CMD(0x30, 0x62),
+ _INIT_DCS_CMD(0x31, 0x06),
+ _INIT_DCS_CMD(0x32, 0x7F),
+ _INIT_DCS_CMD(0x33, 0x11),
+ _INIT_DCS_CMD(0x34, 0x89),
+ _INIT_DCS_CMD(0x35, 0x67),
- _INIT_DCS_CMD(0x39, 0x10),
- _INIT_DCS_CMD(0x3A, 0x78),
+ _INIT_DCS_CMD(0x39, 0x0B),
+ _INIT_DCS_CMD(0x3A, 0x62),
_INIT_DCS_CMD(0x3B, 0x06),
_INIT_DCS_CMD(0xC8, 0x04),
- _INIT_DCS_CMD(0xC9, 0x84),
+ _INIT_DCS_CMD(0xC9, 0x89),
_INIT_DCS_CMD(0xCA, 0x4E),
_INIT_DCS_CMD(0xCB, 0x00),
+ _INIT_DCS_CMD(0xA9, 0x3F),
+ _INIT_DCS_CMD(0xAA, 0x3E),
+ _INIT_DCS_CMD(0xAB, 0x3D),
+ _INIT_DCS_CMD(0xAC, 0x3C),
+ _INIT_DCS_CMD(0xAD, 0x3B),
+ _INIT_DCS_CMD(0xAE, 0x3A),
+ _INIT_DCS_CMD(0xAF, 0x39),
+ _INIT_DCS_CMD(0xB0, 0x38),
- _INIT_DCS_CMD(0xA9, 0x50),
- _INIT_DCS_CMD(0xAA, 0x4F),
- _INIT_DCS_CMD(0xAB, 0x4D),
- _INIT_DCS_CMD(0xAC, 0x4A),
- _INIT_DCS_CMD(0xAD, 0x48),
- _INIT_DCS_CMD(0xAE, 0x46),
_INIT_DCS_CMD(0xFF, 0x27),
_INIT_DCS_CMD(0xFB, 0x01),
+
+ _INIT_DCS_CMD(0xD0, 0x11),
+ _INIT_DCS_CMD(0xD1, 0x54),
+ _INIT_DCS_CMD(0xDE, 0x43),
+ _INIT_DCS_CMD(0xDF, 0x02),
+
_INIT_DCS_CMD(0xC0, 0x18),
_INIT_DCS_CMD(0xC1, 0x00),
_INIT_DCS_CMD(0xC2, 0x00),
+ _INIT_DCS_CMD(0x00, 0x00),
+ _INIT_DCS_CMD(0xC3, 0x00),
_INIT_DCS_CMD(0x56, 0x06),
+
_INIT_DCS_CMD(0x58, 0x80),
- _INIT_DCS_CMD(0x59, 0x75),
+ _INIT_DCS_CMD(0x59, 0x78),
_INIT_DCS_CMD(0x5A, 0x00),
- _INIT_DCS_CMD(0x5B, 0x02),
+ _INIT_DCS_CMD(0x5B, 0x18),
_INIT_DCS_CMD(0x5C, 0x00),
- _INIT_DCS_CMD(0x5D, 0x00),
+ _INIT_DCS_CMD(0x5D, 0x01),
_INIT_DCS_CMD(0x5E, 0x20),
_INIT_DCS_CMD(0x5F, 0x10),
_INIT_DCS_CMD(0x60, 0x00),
- _INIT_DCS_CMD(0x61, 0x2E),
+ _INIT_DCS_CMD(0x61, 0x1C),
_INIT_DCS_CMD(0x62, 0x00),
_INIT_DCS_CMD(0x63, 0x01),
- _INIT_DCS_CMD(0x64, 0x43),
- _INIT_DCS_CMD(0x65, 0x2D),
+ _INIT_DCS_CMD(0x64, 0x44),
+ _INIT_DCS_CMD(0x65, 0x1B),
_INIT_DCS_CMD(0x66, 0x00),
_INIT_DCS_CMD(0x67, 0x01),
- _INIT_DCS_CMD(0x68, 0x43),
+ _INIT_DCS_CMD(0x68, 0x44),
+
_INIT_DCS_CMD(0x98, 0x01),
_INIT_DCS_CMD(0xB4, 0x03),
- _INIT_DCS_CMD(0x9B, 0xBD),
- _INIT_DCS_CMD(0xA0, 0x90),
- _INIT_DCS_CMD(0xAB, 0x1B),
- _INIT_DCS_CMD(0xBC, 0x0C),
+ _INIT_DCS_CMD(0x9B, 0xBE),
+
+ _INIT_DCS_CMD(0xAB, 0x14),
+ _INIT_DCS_CMD(0xBC, 0x08),
_INIT_DCS_CMD(0xBD, 0x28),
_INIT_DCS_CMD(0xFF, 0x2A),
_INIT_DCS_CMD(0xFB, 0x01),
-
_INIT_DCS_CMD(0x22, 0x2F),
_INIT_DCS_CMD(0x23, 0x08),
_INIT_DCS_CMD(0x24, 0x00),
- _INIT_DCS_CMD(0x25, 0x65),
+ _INIT_DCS_CMD(0x25, 0x62),
_INIT_DCS_CMD(0x26, 0xF8),
_INIT_DCS_CMD(0x27, 0x00),
_INIT_DCS_CMD(0x28, 0x1A),
@@ -719,18 +752,29 @@ static const struct panel_init_cmd inx_hj110iz_init_cmd[] = {
_INIT_DCS_CMD(0x2D, 0x1A),
_INIT_DCS_CMD(0x64, 0x96),
- _INIT_DCS_CMD(0x65, 0x00),
+ _INIT_DCS_CMD(0x65, 0x10),
_INIT_DCS_CMD(0x66, 0x00),
+ _INIT_DCS_CMD(0x67, 0x96),
+ _INIT_DCS_CMD(0x68, 0x10),
+ _INIT_DCS_CMD(0x69, 0x00),
_INIT_DCS_CMD(0x6A, 0x96),
- _INIT_DCS_CMD(0x6B, 0x00),
+ _INIT_DCS_CMD(0x6B, 0x10),
_INIT_DCS_CMD(0x6C, 0x00),
_INIT_DCS_CMD(0x70, 0x92),
- _INIT_DCS_CMD(0x71, 0x00),
+ _INIT_DCS_CMD(0x71, 0x10),
_INIT_DCS_CMD(0x72, 0x00),
- _INIT_DCS_CMD(0xA2, 0x33),
+ _INIT_DCS_CMD(0x79, 0x96),
+ _INIT_DCS_CMD(0x7A, 0x10),
+ _INIT_DCS_CMD(0x88, 0x96),
+ _INIT_DCS_CMD(0x89, 0x10),
+
+ _INIT_DCS_CMD(0xA2, 0x3F),
_INIT_DCS_CMD(0xA3, 0x30),
_INIT_DCS_CMD(0xA4, 0xC0),
+ _INIT_DCS_CMD(0xA5, 0x03),
+
_INIT_DCS_CMD(0xE8, 0x00),
+
_INIT_DCS_CMD(0x97, 0x3C),
_INIT_DCS_CMD(0x98, 0x02),
_INIT_DCS_CMD(0x99, 0x95),
@@ -739,38 +783,68 @@ static const struct panel_init_cmd inx_hj110iz_init_cmd[] = {
_INIT_DCS_CMD(0x9C, 0x0B),
_INIT_DCS_CMD(0x9D, 0x0A),
_INIT_DCS_CMD(0x9E, 0x90),
+
+ _INIT_DCS_CMD(0xFF, 0x25),
+ _INIT_DCS_CMD(0x13, 0x02),
+ _INIT_DCS_CMD(0x14, 0xD7),
+ _INIT_DCS_CMD(0xDB, 0x02),
+ _INIT_DCS_CMD(0xDC, 0xD7),
+ _INIT_DCS_CMD(0x17, 0xCF),
+ _INIT_DCS_CMD(0x19, 0x0F),
+ _INIT_DCS_CMD(0x1B, 0x5B),
+
+ _INIT_DCS_CMD(0xFF, 0x20),
+
+ _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x24, 0x00, 0x38, 0x00, 0x4C, 0x00, 0x5E, 0x00, 0x6F, 0x00, 0x7E),
+ _INIT_DCS_CMD(0xB1, 0x00, 0x8C, 0x00, 0xBE, 0x00, 0xE5, 0x01, 0x27, 0x01, 0x58, 0x01, 0xA8, 0x01, 0xE8, 0x01, 0xEA),
+ _INIT_DCS_CMD(0xB2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9E, 0x02, 0xDA, 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51),
+ _INIT_DCS_CMD(0xB3, 0x03, 0x62, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9C, 0x03, 0xAA, 0x03, 0xB2),
+
+ _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x27, 0x00, 0x3D, 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84),
+ _INIT_DCS_CMD(0xB5, 0x00, 0x93, 0x00, 0xC5, 0x00, 0xEC, 0x01, 0x2C, 0x01, 0x5D, 0x01, 0xAC, 0x01, 0xEC, 0x01, 0xEE),
+ _INIT_DCS_CMD(0xB6, 0x02, 0x2B, 0x02, 0x73, 0x02, 0xA0, 0x02, 0xDB, 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51),
+ _INIT_DCS_CMD(0xB7, 0x03, 0x63, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9C, 0x03, 0xAA, 0x03, 0xB2),
+
+ _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x2A, 0x00, 0x40, 0x00, 0x56, 0x00, 0x68, 0x00, 0x7A, 0x00, 0x89),
+ _INIT_DCS_CMD(0xB9, 0x00, 0x98, 0x00, 0xC9, 0x00, 0xF1, 0x01, 0x30, 0x01, 0x61, 0x01, 0xB0, 0x01, 0xEF, 0x01, 0xF1),
+ _INIT_DCS_CMD(0xBA, 0x02, 0x2E, 0x02, 0x76, 0x02, 0xA3, 0x02, 0xDD, 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53),
+ _INIT_DCS_CMD(0xBB, 0x03, 0x66, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9C, 0x03, 0xAA, 0x03, 0xB2),
+
+ _INIT_DCS_CMD(0xFF, 0x21),
+ _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x24, 0x00, 0x38, 0x00, 0x4C, 0x00, 0x5E, 0x00, 0x6F, 0x00, 0x7E),
+ _INIT_DCS_CMD(0xB1, 0x00, 0x8C, 0x00, 0xBE, 0x00, 0xE5, 0x01, 0x27, 0x01, 0x58, 0x01, 0xA8, 0x01, 0xE8, 0x01, 0xEA),
+ _INIT_DCS_CMD(0xB2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9E, 0x02, 0xDA, 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51),
+ _INIT_DCS_CMD(0xB3, 0x03, 0x62, 0x03, 0x77, 0x03, 0x90, 0x03, 0xAC, 0x03, 0xCA, 0x03, 0xDA),
+
+ _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x27, 0x00, 0x3D, 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84),
+ _INIT_DCS_CMD(0xB5, 0x00, 0x93, 0x00, 0xC5, 0x00, 0xEC, 0x01, 0x2C, 0x01, 0x5D, 0x01, 0xAC, 0x01, 0xEC, 0x01, 0xEE),
+ _INIT_DCS_CMD(0xB6, 0x02, 0x2B, 0x02, 0x73, 0x02, 0xA0, 0x02, 0xDB, 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51),
+ _INIT_DCS_CMD(0xB7, 0x03, 0x63, 0x03, 0x77, 0x03, 0x90, 0x03, 0xAC, 0x03, 0xCA, 0x03, 0xDA),
+
+ _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x2A, 0x00, 0x40, 0x00, 0x56, 0x00, 0x68, 0x00, 0x7A, 0x00, 0x89),
+ _INIT_DCS_CMD(0xB9, 0x00, 0x98, 0x00, 0xC9, 0x00, 0xF1, 0x01, 0x30, 0x01, 0x61, 0x01, 0xB0, 0x01, 0xEF, 0x01, 0xF1),
+ _INIT_DCS_CMD(0xBA, 0x02, 0x2E, 0x02, 0x76, 0x02, 0xA3, 0x02, 0xDD, 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53),
+ _INIT_DCS_CMD(0xBB, 0x03, 0x66, 0x03, 0x77, 0x03, 0x90, 0x03, 0xAC, 0x03, 0xCA, 0x03, 0xDA),
+
_INIT_DCS_CMD(0xFF, 0xF0),
_INIT_DCS_CMD(0xFB, 0x01),
_INIT_DCS_CMD(0x3A, 0x08),
- _INIT_DCS_CMD(0xFF, 0xD0),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x00, 0x33),
- _INIT_DCS_CMD(0x08, 0x01),
- _INIT_DCS_CMD(0x09, 0xBF),
- _INIT_DCS_CMD(0x2F, 0x33),
- _INIT_DCS_CMD(0xFF, 0x23),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x00, 0x80),
- _INIT_DCS_CMD(0x07, 0x00),
- _INIT_DCS_CMD(0xFF, 0x20),
- _INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0x30, 0x00),
- _INIT_DCS_CMD(0xFF, 0x24),
- _INIT_DCS_CMD(0x5C, 0x88),
- _INIT_DCS_CMD(0x5D, 0x08),
+
_INIT_DCS_CMD(0xFF, 0x10),
_INIT_DCS_CMD(0xB9, 0x01),
+
_INIT_DCS_CMD(0xFF, 0x20),
+
_INIT_DCS_CMD(0x18, 0x40),
_INIT_DCS_CMD(0xFF, 0x10),
+
_INIT_DCS_CMD(0xB9, 0x02),
_INIT_DCS_CMD(0xFF, 0x10),
+
_INIT_DCS_CMD(0xFB, 0x01),
- _INIT_DCS_CMD(0xBB, 0x13),
- _INIT_DCS_CMD(0x3B, 0x03, 0x96, 0x1A, 0x04, 0x04),
+ _INIT_DCS_CMD(0xB0, 0x01),
_INIT_DCS_CMD(0x35, 0x00),
- _INIT_DCS_CMD(0x51, 0x0F, 0xFF),
- _INIT_DCS_CMD(0x53, 0x24),
+ _INIT_DCS_CMD(0x3B, 0x03, 0xAE, 0x1A, 0x04, 0x04),
_INIT_DELAY_CMD(100),
_INIT_DCS_CMD(0x11),
_INIT_DELAY_CMD(200),
@@ -780,7 +854,6 @@ static const struct panel_init_cmd inx_hj110iz_init_cmd[] = {
};
static const struct panel_init_cmd boe_init_cmd[] = {
- _INIT_DELAY_CMD(24),
_INIT_DCS_CMD(0xB0, 0x05),
_INIT_DCS_CMD(0xB1, 0xE5),
_INIT_DCS_CMD(0xB3, 0x52),
@@ -1228,6 +1301,416 @@ static const struct panel_init_cmd starry_qfh032011_53g_init_cmd[] = {
{},
};
+static const struct panel_init_cmd starry_himax83102_j02_init_cmd[] = {
+ _INIT_DCS_CMD(0xB9, 0x83, 0x10, 0x21, 0x55, 0x00),
+ _INIT_DCS_CMD(0xB1, 0x2C, 0xB5, 0xB5, 0x31, 0xF1, 0x31, 0xD7, 0x2F, 0x36, 0x36, 0x36, 0x36, 0x1A, 0x8B, 0x11,
+ 0x65, 0x00, 0x88, 0xFA, 0xFF, 0xFF, 0x8F, 0xFF, 0x08, 0x74, 0x33),
+ _INIT_DCS_CMD(0xB2, 0x00, 0x47, 0xB0, 0x80, 0x00, 0x12, 0x72, 0x3C, 0xA3, 0x03, 0x03, 0x00, 0x00, 0x88, 0xF5),
+ _INIT_DCS_CMD(0xB4, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x63, 0x5C, 0x63, 0x5C, 0x01, 0x9E),
+ _INIT_DCS_CMD(0xE9, 0xCD),
+ _INIT_DCS_CMD(0xBA, 0x84),
+ _INIT_DCS_CMD(0xE9, 0x3F),
+ _INIT_DCS_CMD(0xBC, 0x1B, 0x04),
+ _INIT_DCS_CMD(0xBE, 0x20),
+ _INIT_DCS_CMD(0xBF, 0xFC, 0xC4),
+ _INIT_DCS_CMD(0xC0, 0x36, 0x36, 0x22, 0x11, 0x22, 0xA0, 0x61, 0x08, 0xF5, 0x03),
+ _INIT_DCS_CMD(0xE9, 0xCC),
+ _INIT_DCS_CMD(0xC7, 0x80),
+ _INIT_DCS_CMD(0xE9, 0x3F),
+ _INIT_DCS_CMD(0xE9, 0xC6),
+ _INIT_DCS_CMD(0xC8, 0x97),
+ _INIT_DCS_CMD(0xE9, 0x3F),
+ _INIT_DCS_CMD(0xC9, 0x00, 0x1E, 0x13, 0x88, 0x01),
+ _INIT_DCS_CMD(0xCB, 0x08, 0x13, 0x07, 0x00, 0x0F, 0x33),
+ _INIT_DCS_CMD(0xCC, 0x02),
+ _INIT_DCS_CMD(0xE9, 0xC4),
+ _INIT_DCS_CMD(0xD0, 0x03),
+ _INIT_DCS_CMD(0xE9, 0x3F),
+ _INIT_DCS_CMD(0xD1, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0C, 0xFF),
+ _INIT_DCS_CMD(0xD2, 0x1F, 0x11, 0x1F),
+ _INIT_DCS_CMD(0xD3, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x37, 0x47, 0x34, 0x3B, 0x12, 0x12, 0x03,
+ 0x03, 0x32, 0x10, 0x10, 0x00, 0x10, 0x32, 0x10, 0x08, 0x00, 0x08, 0x32, 0x17, 0x94, 0x07, 0x94, 0x00, 0x00),
+ _INIT_DCS_CMD(0xD5, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x40, 0x40, 0x1A, 0x1A,
+ 0x1B, 0x1B, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x28, 0x29, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18),
+ _INIT_DCS_CMD(0xD6, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x40, 0x40, 0x19, 0x19, 0x1A, 0x1A,
+ 0x1B, 0x1B, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x29, 0x28, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18),
+ _INIT_DCS_CMD(0xD8, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA,
+ 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0),
+ _INIT_DCS_CMD(0xE0, 0x00, 0x09, 0x14, 0x1E, 0x26, 0x48, 0x61, 0x67, 0x6C, 0x67, 0x7D, 0x7F, 0x80, 0x8B, 0x87, 0x8F, 0x98, 0xAB,
+ 0xAB, 0x55, 0x5C, 0x68, 0x73, 0x00, 0x09, 0x14, 0x1E, 0x26, 0x48, 0x61, 0x67, 0x6C, 0x67, 0x7D, 0x7F, 0x80, 0x8B, 0x87, 0x8F, 0x98, 0xAB, 0xAB, 0x55, 0x5C, 0x68, 0x73),
+ _INIT_DCS_CMD(0xE7, 0x0E, 0x10, 0x10, 0x21, 0x2B, 0x9A, 0x02, 0x54, 0x9A, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x05, 0x02, 0x02, 0x10),
+ _INIT_DCS_CMD(0xBD, 0x01),
+ _INIT_DCS_CMD(0xB1, 0x01, 0xBF, 0x11),
+ _INIT_DCS_CMD(0xCB, 0x86),
+ _INIT_DCS_CMD(0xD2, 0x3C, 0xFA),
+ _INIT_DCS_CMD(0xE9, 0xC5),
+ _INIT_DCS_CMD(0xD3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x01),
+ _INIT_DCS_CMD(0xE9, 0x3F),
+ _INIT_DCS_CMD(0xE7, 0x02, 0x00, 0x28, 0x01, 0x7E, 0x0F, 0x7E, 0x10, 0xA0, 0x00, 0x00, 0x20, 0x40, 0x50, 0x40),
+ _INIT_DCS_CMD(0xBD, 0x02),
+ _INIT_DCS_CMD(0xD8, 0xFF, 0xFF, 0xBF, 0xFE, 0xAA, 0xA0, 0xFF, 0xFF, 0xBF, 0xFE, 0xAA, 0xA0),
+ _INIT_DCS_CMD(0xE7, 0xFE, 0x04, 0xFE, 0x04, 0xFE, 0x04, 0x03, 0x03, 0x03, 0x26, 0x00, 0x26, 0x81, 0x02, 0x40, 0x00, 0x20, 0x9E, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00),
+ _INIT_DCS_CMD(0xBD, 0x03),
+ _INIT_DCS_CMD(0xE9, 0xC6),
+ _INIT_DCS_CMD(0xB4, 0x03, 0xFF, 0xF8),
+ _INIT_DCS_CMD(0xE9, 0x3F),
+ _INIT_DCS_CMD(0xD8, 0x00, 0x2A, 0xAA, 0xA8, 0x00, 0x00, 0x00, 0x2A, 0xAA, 0xA8, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x2A, 0xAA, 0xA8,
+ 0x00, 0x00, 0x00, 0x2A, 0xAA, 0xA8, 0x00, 0x00),
+ _INIT_DCS_CMD(0xBD, 0x00),
+ _INIT_DCS_CMD(0xE9, 0xC4),
+ _INIT_DCS_CMD(0xBA, 0x96),
+ _INIT_DCS_CMD(0xE9, 0x3F),
+ _INIT_DCS_CMD(0xBD, 0x01),
+ _INIT_DCS_CMD(0xE9, 0xC5),
+ _INIT_DCS_CMD(0xBA, 0x4F),
+ _INIT_DCS_CMD(0xE9, 0x3F),
+ _INIT_DCS_CMD(0xBD, 0x00),
+ _INIT_DCS_CMD(0x11),
+ _INIT_DELAY_CMD(120),
+ _INIT_DCS_CMD(0x29),
+ {},
+};
+
+static const struct panel_init_cmd starry_ili9882t_init_cmd[] = {
+ _INIT_DELAY_CMD(5),
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x01),
+ _INIT_DCS_CMD(0x00, 0x42),
+ _INIT_DCS_CMD(0x01, 0x11),
+ _INIT_DCS_CMD(0x02, 0x00),
+ _INIT_DCS_CMD(0x03, 0x00),
+
+ _INIT_DCS_CMD(0x04, 0x01),
+ _INIT_DCS_CMD(0x05, 0x11),
+ _INIT_DCS_CMD(0x06, 0x00),
+ _INIT_DCS_CMD(0x07, 0x00),
+
+ _INIT_DCS_CMD(0x08, 0x80),
+ _INIT_DCS_CMD(0x09, 0x81),
+ _INIT_DCS_CMD(0x0A, 0x71),
+ _INIT_DCS_CMD(0x0B, 0x00),
+
+ _INIT_DCS_CMD(0x0C, 0x00),
+ _INIT_DCS_CMD(0x0E, 0x1A),
+
+ _INIT_DCS_CMD(0x24, 0x00),
+ _INIT_DCS_CMD(0x25, 0x00),
+ _INIT_DCS_CMD(0x26, 0x00),
+ _INIT_DCS_CMD(0x27, 0x00),
+
+ _INIT_DCS_CMD(0x2C, 0xD4),
+ _INIT_DCS_CMD(0xB9, 0x40),
+
+ _INIT_DCS_CMD(0xB0, 0x11),
+
+ _INIT_DCS_CMD(0xE6, 0x32),
+ _INIT_DCS_CMD(0xD1, 0x30),
+
+ _INIT_DCS_CMD(0xD6, 0x55),
+
+ _INIT_DCS_CMD(0xD0, 0x01),
+ _INIT_DCS_CMD(0xE3, 0x93),
+ _INIT_DCS_CMD(0xE4, 0x00),
+ _INIT_DCS_CMD(0xE5, 0x80),
+
+ _INIT_DCS_CMD(0x31, 0x07),
+ _INIT_DCS_CMD(0x32, 0x07),
+ _INIT_DCS_CMD(0x33, 0x07),
+ _INIT_DCS_CMD(0x34, 0x07),
+ _INIT_DCS_CMD(0x35, 0x07),
+ _INIT_DCS_CMD(0x36, 0x01),
+ _INIT_DCS_CMD(0x37, 0x00),
+ _INIT_DCS_CMD(0x38, 0x28),
+ _INIT_DCS_CMD(0x39, 0x29),
+ _INIT_DCS_CMD(0x3A, 0x11),
+ _INIT_DCS_CMD(0x3B, 0x13),
+ _INIT_DCS_CMD(0x3C, 0x15),
+ _INIT_DCS_CMD(0x3D, 0x17),
+ _INIT_DCS_CMD(0x3E, 0x09),
+ _INIT_DCS_CMD(0x3F, 0x0D),
+ _INIT_DCS_CMD(0x40, 0x02),
+ _INIT_DCS_CMD(0x41, 0x02),
+ _INIT_DCS_CMD(0x42, 0x02),
+ _INIT_DCS_CMD(0x43, 0x02),
+ _INIT_DCS_CMD(0x44, 0x02),
+ _INIT_DCS_CMD(0x45, 0x02),
+ _INIT_DCS_CMD(0x46, 0x02),
+
+ _INIT_DCS_CMD(0x47, 0x07),
+ _INIT_DCS_CMD(0x48, 0x07),
+ _INIT_DCS_CMD(0x49, 0x07),
+ _INIT_DCS_CMD(0x4A, 0x07),
+ _INIT_DCS_CMD(0x4B, 0x07),
+ _INIT_DCS_CMD(0x4C, 0x01),
+ _INIT_DCS_CMD(0x4D, 0x00),
+ _INIT_DCS_CMD(0x4E, 0x28),
+ _INIT_DCS_CMD(0x4F, 0x29),
+ _INIT_DCS_CMD(0x50, 0x10),
+ _INIT_DCS_CMD(0x51, 0x12),
+ _INIT_DCS_CMD(0x52, 0x14),
+ _INIT_DCS_CMD(0x53, 0x16),
+ _INIT_DCS_CMD(0x54, 0x08),
+ _INIT_DCS_CMD(0x55, 0x0C),
+ _INIT_DCS_CMD(0x56, 0x02),
+ _INIT_DCS_CMD(0x57, 0x02),
+ _INIT_DCS_CMD(0x58, 0x02),
+ _INIT_DCS_CMD(0x59, 0x02),
+ _INIT_DCS_CMD(0x5A, 0x02),
+ _INIT_DCS_CMD(0x5B, 0x02),
+ _INIT_DCS_CMD(0x5C, 0x02),
+
+ _INIT_DCS_CMD(0x61, 0x07),
+ _INIT_DCS_CMD(0x62, 0x07),
+ _INIT_DCS_CMD(0x63, 0x07),
+ _INIT_DCS_CMD(0x64, 0x07),
+ _INIT_DCS_CMD(0x65, 0x07),
+ _INIT_DCS_CMD(0x66, 0x01),
+ _INIT_DCS_CMD(0x67, 0x00),
+ _INIT_DCS_CMD(0x68, 0x28),
+ _INIT_DCS_CMD(0x69, 0x29),
+ _INIT_DCS_CMD(0x6A, 0x16),
+ _INIT_DCS_CMD(0x6B, 0x14),
+ _INIT_DCS_CMD(0x6C, 0x12),
+ _INIT_DCS_CMD(0x6D, 0x10),
+ _INIT_DCS_CMD(0x6E, 0x0C),
+ _INIT_DCS_CMD(0x6F, 0x08),
+ _INIT_DCS_CMD(0x70, 0x02),
+ _INIT_DCS_CMD(0x71, 0x02),
+ _INIT_DCS_CMD(0x72, 0x02),
+ _INIT_DCS_CMD(0x73, 0x02),
+ _INIT_DCS_CMD(0x74, 0x02),
+ _INIT_DCS_CMD(0x75, 0x02),
+ _INIT_DCS_CMD(0x76, 0x02),
+
+ _INIT_DCS_CMD(0x77, 0x07),
+ _INIT_DCS_CMD(0x78, 0x07),
+ _INIT_DCS_CMD(0x79, 0x07),
+ _INIT_DCS_CMD(0x7A, 0x07),
+ _INIT_DCS_CMD(0x7B, 0x07),
+ _INIT_DCS_CMD(0x7C, 0x01),
+ _INIT_DCS_CMD(0x7D, 0x00),
+ _INIT_DCS_CMD(0x7E, 0x28),
+ _INIT_DCS_CMD(0x7F, 0x29),
+ _INIT_DCS_CMD(0x80, 0x17),
+ _INIT_DCS_CMD(0x81, 0x15),
+ _INIT_DCS_CMD(0x82, 0x13),
+ _INIT_DCS_CMD(0x83, 0x11),
+ _INIT_DCS_CMD(0x84, 0x0D),
+ _INIT_DCS_CMD(0x85, 0x09),
+ _INIT_DCS_CMD(0x86, 0x02),
+ _INIT_DCS_CMD(0x87, 0x07),
+ _INIT_DCS_CMD(0x88, 0x07),
+ _INIT_DCS_CMD(0x89, 0x07),
+ _INIT_DCS_CMD(0x8A, 0x07),
+ _INIT_DCS_CMD(0x8B, 0x07),
+ _INIT_DCS_CMD(0x8C, 0x07),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x02),
+ _INIT_DCS_CMD(0x29, 0x3A),
+ _INIT_DCS_CMD(0x2A, 0x3B),
+
+ _INIT_DCS_CMD(0x06, 0x01),
+ _INIT_DCS_CMD(0x07, 0x01),
+ _INIT_DCS_CMD(0x08, 0x0C),
+ _INIT_DCS_CMD(0x09, 0x44),
+
+ _INIT_DCS_CMD(0x3C, 0x0A),
+ _INIT_DCS_CMD(0x39, 0x11),
+ _INIT_DCS_CMD(0x3D, 0x00),
+ _INIT_DCS_CMD(0x3A, 0x0C),
+ _INIT_DCS_CMD(0x3B, 0x44),
+
+ _INIT_DCS_CMD(0x53, 0x1F),
+ _INIT_DCS_CMD(0x5E, 0x40),
+ _INIT_DCS_CMD(0x84, 0x00),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x03),
+ _INIT_DCS_CMD(0x20, 0x01),
+ _INIT_DCS_CMD(0x21, 0x3C),
+ _INIT_DCS_CMD(0x22, 0xFA),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x0A),
+ _INIT_DCS_CMD(0xE0, 0x01),
+ _INIT_DCS_CMD(0xE2, 0x01),
+ _INIT_DCS_CMD(0xE5, 0x91),
+ _INIT_DCS_CMD(0xE6, 0x3C),
+ _INIT_DCS_CMD(0xE7, 0x00),
+ _INIT_DCS_CMD(0xE8, 0xFA),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x12),
+ _INIT_DCS_CMD(0x87, 0x2C),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x05),
+ _INIT_DCS_CMD(0x73, 0xE5),
+ _INIT_DCS_CMD(0x7F, 0x6B),
+ _INIT_DCS_CMD(0x6D, 0xA4),
+ _INIT_DCS_CMD(0x79, 0x54),
+ _INIT_DCS_CMD(0x69, 0x97),
+ _INIT_DCS_CMD(0x6A, 0x97),
+ _INIT_DCS_CMD(0xA5, 0x3F),
+ _INIT_DCS_CMD(0x61, 0xDA),
+ _INIT_DCS_CMD(0xA7, 0xF1),
+ _INIT_DCS_CMD(0x5F, 0x01),
+ _INIT_DCS_CMD(0x62, 0x3F),
+ _INIT_DCS_CMD(0x1D, 0x90),
+ _INIT_DCS_CMD(0x86, 0x87),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x06),
+ _INIT_DCS_CMD(0xC0, 0x80),
+ _INIT_DCS_CMD(0xC1, 0x07),
+ _INIT_DCS_CMD(0xCA, 0x58),
+ _INIT_DCS_CMD(0xCB, 0x02),
+ _INIT_DCS_CMD(0xCE, 0x58),
+ _INIT_DCS_CMD(0xCF, 0x02),
+ _INIT_DCS_CMD(0x67, 0x60),
+ _INIT_DCS_CMD(0x10, 0x00),
+ _INIT_DCS_CMD(0x92, 0x22),
+ _INIT_DCS_CMD(0xD3, 0x08),
+ _INIT_DCS_CMD(0xD6, 0x55),
+ _INIT_DCS_CMD(0xDC, 0x38),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x08),
+ _INIT_DCS_CMD(0xE0, 0x00, 0x10, 0x2A, 0x4D, 0x61, 0x56, 0x6A, 0x6E, 0x79, 0x76, 0x8F, 0x95, 0x98, 0xAE, 0xAA, 0xB2, 0xBB, 0xCE, 0xC6, 0xBD, 0xD5, 0xE2, 0xE8),
+ _INIT_DCS_CMD(0xE1, 0x00, 0x10, 0x2A, 0x4D, 0x61, 0x56, 0x6A, 0x6E, 0x79, 0x76, 0x8F, 0x95, 0x98, 0xAE, 0xAA, 0xB2, 0xBB, 0xCE, 0xC6, 0xBD, 0xD5, 0xE2, 0xE8),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x04),
+ _INIT_DCS_CMD(0xBA, 0x81),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x0C),
+ _INIT_DCS_CMD(0x00, 0x02),
+ _INIT_DCS_CMD(0x01, 0x00),
+ _INIT_DCS_CMD(0x02, 0x03),
+ _INIT_DCS_CMD(0x03, 0x01),
+ _INIT_DCS_CMD(0x04, 0x03),
+ _INIT_DCS_CMD(0x05, 0x02),
+ _INIT_DCS_CMD(0x06, 0x04),
+ _INIT_DCS_CMD(0x07, 0x03),
+ _INIT_DCS_CMD(0x08, 0x03),
+ _INIT_DCS_CMD(0x09, 0x04),
+ _INIT_DCS_CMD(0x0A, 0x04),
+ _INIT_DCS_CMD(0x0B, 0x05),
+ _INIT_DCS_CMD(0x0C, 0x04),
+ _INIT_DCS_CMD(0x0D, 0x06),
+ _INIT_DCS_CMD(0x0E, 0x05),
+ _INIT_DCS_CMD(0x0F, 0x07),
+ _INIT_DCS_CMD(0x10, 0x04),
+ _INIT_DCS_CMD(0x11, 0x08),
+ _INIT_DCS_CMD(0x12, 0x05),
+ _INIT_DCS_CMD(0x13, 0x09),
+ _INIT_DCS_CMD(0x14, 0x05),
+ _INIT_DCS_CMD(0x15, 0x0A),
+ _INIT_DCS_CMD(0x16, 0x06),
+ _INIT_DCS_CMD(0x17, 0x0B),
+ _INIT_DCS_CMD(0x18, 0x05),
+ _INIT_DCS_CMD(0x19, 0x0C),
+ _INIT_DCS_CMD(0x1A, 0x06),
+ _INIT_DCS_CMD(0x1B, 0x0D),
+ _INIT_DCS_CMD(0x1C, 0x06),
+ _INIT_DCS_CMD(0x1D, 0x0E),
+ _INIT_DCS_CMD(0x1E, 0x07),
+ _INIT_DCS_CMD(0x1F, 0x0F),
+ _INIT_DCS_CMD(0x20, 0x06),
+ _INIT_DCS_CMD(0x21, 0x10),
+ _INIT_DCS_CMD(0x22, 0x07),
+ _INIT_DCS_CMD(0x23, 0x11),
+ _INIT_DCS_CMD(0x24, 0x07),
+ _INIT_DCS_CMD(0x25, 0x12),
+ _INIT_DCS_CMD(0x26, 0x08),
+ _INIT_DCS_CMD(0x27, 0x13),
+ _INIT_DCS_CMD(0x28, 0x07),
+ _INIT_DCS_CMD(0x29, 0x14),
+ _INIT_DCS_CMD(0x2A, 0x08),
+ _INIT_DCS_CMD(0x2B, 0x15),
+ _INIT_DCS_CMD(0x2C, 0x08),
+ _INIT_DCS_CMD(0x2D, 0x16),
+ _INIT_DCS_CMD(0x2E, 0x09),
+ _INIT_DCS_CMD(0x2F, 0x17),
+ _INIT_DCS_CMD(0x30, 0x08),
+ _INIT_DCS_CMD(0x31, 0x18),
+ _INIT_DCS_CMD(0x32, 0x09),
+ _INIT_DCS_CMD(0x33, 0x19),
+ _INIT_DCS_CMD(0x34, 0x09),
+ _INIT_DCS_CMD(0x35, 0x1A),
+ _INIT_DCS_CMD(0x36, 0x0A),
+ _INIT_DCS_CMD(0x37, 0x1B),
+ _INIT_DCS_CMD(0x38, 0x0A),
+ _INIT_DCS_CMD(0x39, 0x1C),
+ _INIT_DCS_CMD(0x3A, 0x0A),
+ _INIT_DCS_CMD(0x3B, 0x1D),
+ _INIT_DCS_CMD(0x3C, 0x0A),
+ _INIT_DCS_CMD(0x3D, 0x1E),
+ _INIT_DCS_CMD(0x3E, 0x0A),
+ _INIT_DCS_CMD(0x3F, 0x1F),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x04),
+ _INIT_DCS_CMD(0xBA, 0x01),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x0E),
+ _INIT_DCS_CMD(0x02, 0x0C),
+ _INIT_DCS_CMD(0x20, 0x10),
+ _INIT_DCS_CMD(0x25, 0x16),
+ _INIT_DCS_CMD(0x26, 0xE0),
+ _INIT_DCS_CMD(0x27, 0x00),
+ _INIT_DCS_CMD(0x29, 0x71),
+ _INIT_DCS_CMD(0x2A, 0x46),
+ _INIT_DCS_CMD(0x2B, 0x1F),
+ _INIT_DCS_CMD(0x2D, 0xC7),
+ _INIT_DCS_CMD(0x31, 0x02),
+ _INIT_DCS_CMD(0x32, 0xDF),
+ _INIT_DCS_CMD(0x33, 0x5A),
+ _INIT_DCS_CMD(0x34, 0xC0),
+ _INIT_DCS_CMD(0x35, 0x5A),
+ _INIT_DCS_CMD(0x36, 0xC0),
+ _INIT_DCS_CMD(0x38, 0x65),
+ _INIT_DCS_CMD(0x80, 0x3E),
+ _INIT_DCS_CMD(0x81, 0xA0),
+ _INIT_DCS_CMD(0xB0, 0x01),
+ _INIT_DCS_CMD(0xB1, 0xCC),
+ _INIT_DCS_CMD(0xC0, 0x12),
+ _INIT_DCS_CMD(0xC2, 0xCC),
+ _INIT_DCS_CMD(0xC3, 0xCC),
+ _INIT_DCS_CMD(0xC4, 0xCC),
+ _INIT_DCS_CMD(0xC5, 0xCC),
+ _INIT_DCS_CMD(0xC6, 0xCC),
+ _INIT_DCS_CMD(0xC7, 0xCC),
+ _INIT_DCS_CMD(0xC8, 0xCC),
+ _INIT_DCS_CMD(0xC9, 0xCC),
+ _INIT_DCS_CMD(0x30, 0x00),
+ _INIT_DCS_CMD(0x00, 0x81),
+ _INIT_DCS_CMD(0x08, 0x02),
+ _INIT_DCS_CMD(0x09, 0x00),
+ _INIT_DCS_CMD(0x07, 0x21),
+ _INIT_DCS_CMD(0x04, 0x10),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x1E),
+ _INIT_DCS_CMD(0x60, 0x00),
+ _INIT_DCS_CMD(0x64, 0x00),
+ _INIT_DCS_CMD(0x6D, 0x00),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x0B),
+ _INIT_DCS_CMD(0xA6, 0x44),
+ _INIT_DCS_CMD(0xA7, 0xB6),
+ _INIT_DCS_CMD(0xA8, 0x03),
+ _INIT_DCS_CMD(0xA9, 0x03),
+ _INIT_DCS_CMD(0xAA, 0x51),
+ _INIT_DCS_CMD(0xAB, 0x51),
+ _INIT_DCS_CMD(0xAC, 0x04),
+ _INIT_DCS_CMD(0xBD, 0x92),
+ _INIT_DCS_CMD(0xBE, 0xA1),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x05),
+ _INIT_DCS_CMD(0x86, 0x87),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x06),
+ _INIT_DCS_CMD(0x92, 0x22),
+
+ _INIT_DCS_CMD(0xFF, 0x98, 0x82, 0x00),
+ _INIT_DCS_CMD(0x11),
+ _INIT_DELAY_CMD(120),
+ _INIT_DCS_CMD(0x29),
+ _INIT_DELAY_CMD(20),
+ {},
+};
+
static inline struct boe_panel *to_boe_panel(struct drm_panel *panel)
{
return container_of(panel, struct boe_panel, base);
@@ -1366,6 +1849,10 @@ static int boe_panel_prepare(struct drm_panel *panel)
usleep_range(10000, 11000);
+ if (boe->desc->lp11_before_reset) {
+ mipi_dsi_dcs_nop(boe->dsi);
+ usleep_range(1000, 2000);
+ }
gpiod_set_value(boe->enable_gpio, 1);
usleep_range(1000, 2000);
gpiod_set_value(boe->enable_gpio, 0);
@@ -1431,15 +1918,15 @@ static const struct panel_desc boe_tv110c9m_desc = {
};
static const struct drm_display_mode inx_hj110iz_default_mode = {
- .clock = 166594,
+ .clock = 168432,
.hdisplay = 1200,
.hsync_start = 1200 + 40,
.hsync_end = 1200 + 40 + 8,
.htotal = 1200 + 40 + 8 + 28,
.vdisplay = 2000,
.vsync_start = 2000 + 26,
- .vsync_end = 2000 + 26 + 1,
- .vtotal = 2000 + 26 + 1 + 149,
+ .vsync_end = 2000 + 26 + 2,
+ .vtotal = 2000 + 26 + 2 + 172,
.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
};
@@ -1592,6 +2079,7 @@ static const struct panel_desc boe_tv105wum_nw0_desc = {
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
.init_cmds = boe_init_cmd,
+ .lp11_before_reset = true,
};
static const struct drm_display_mode starry_qfh032011_53g_default_mode = {
@@ -1620,6 +2108,62 @@ static const struct panel_desc starry_qfh032011_53g_desc = {
.init_cmds = starry_qfh032011_53g_init_cmd,
};
+static const struct drm_display_mode starry_himax83102_j02_default_mode = {
+ .clock = 161600,
+ .hdisplay = 1200,
+ .hsync_start = 1200 + 40,
+ .hsync_end = 1200 + 40 + 20,
+ .htotal = 1200 + 40 + 20 + 40,
+ .vdisplay = 1920,
+ .vsync_start = 1920 + 116,
+ .vsync_end = 1920 + 116 + 8,
+ .vtotal = 1920 + 116 + 8 + 12,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct panel_desc starry_himax83102_j02_desc = {
+ .modes = &starry_himax83102_j02_default_mode,
+ .bpc = 8,
+ .size = {
+ .width_mm = 141,
+ .height_mm = 226,
+ },
+ .lanes = 4,
+ .format = MIPI_DSI_FMT_RGB888,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_MODE_LPM,
+ .init_cmds = starry_himax83102_j02_init_cmd,
+ .lp11_before_reset = true,
+};
+
+static const struct drm_display_mode starry_ili9882t_default_mode = {
+ .clock = 165280,
+ .hdisplay = 1200,
+ .hsync_start = 1200 + 32,
+ .hsync_end = 1200 + 32 + 30,
+ .htotal = 1200 + 32 + 30 + 32,
+ .vdisplay = 1920,
+ .vsync_start = 1920 + 68,
+ .vsync_end = 1920 + 68 + 2,
+ .vtotal = 1920 + 68 + 2 + 10,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct panel_desc starry_ili9882t_desc = {
+ .modes = &starry_ili9882t_default_mode,
+ .bpc = 8,
+ .size = {
+ .width_mm = 141,
+ .height_mm = 226,
+ },
+ .lanes = 4,
+ .format = MIPI_DSI_FMT_RGB888,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_MODE_LPM,
+ .init_cmds = starry_ili9882t_init_cmd,
+ .lp11_before_reset = true,
+};
+
static int boe_panel_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
@@ -1793,6 +2337,12 @@ static const struct of_device_id boe_of_match[] = {
{ .compatible = "starry,2081101qfh032011-53g",
.data = &starry_qfh032011_53g_desc
},
+ { .compatible = "starry,himax83102-j02",
+ .data = &starry_himax83102_j02_desc
+ },
+ { .compatible = "starry,ili9882t",
+ .data = &starry_ili9882t_desc
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, boe_of_match);
diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
index e23ddab2126e..fbd114b4f0be 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -903,7 +903,7 @@ err_finished_ddc_init:
return err;
}
-static int panel_edp_remove(struct device *dev)
+static void panel_edp_remove(struct device *dev)
{
struct panel_edp *panel = dev_get_drvdata(dev);
@@ -918,8 +918,6 @@ static int panel_edp_remove(struct device *dev)
kfree(panel->edid);
panel->edid = NULL;
-
- return 0;
}
static void panel_edp_shutdown(struct device *dev)
@@ -1934,9 +1932,9 @@ static int panel_edp_platform_probe(struct platform_device *pdev)
return panel_edp_probe(&pdev->dev, id->data, NULL);
}
-static int panel_edp_platform_remove(struct platform_device *pdev)
+static void panel_edp_platform_remove(struct platform_device *pdev)
{
- return panel_edp_remove(&pdev->dev);
+ panel_edp_remove(&pdev->dev);
}
static void panel_edp_platform_shutdown(struct platform_device *pdev)
@@ -1957,7 +1955,7 @@ static struct platform_driver panel_edp_platform_driver = {
.pm = &panel_edp_pm_ops,
},
.probe = panel_edp_platform_probe,
- .remove = panel_edp_platform_remove,
+ .remove_new = panel_edp_platform_remove,
.shutdown = panel_edp_platform_shutdown,
};
diff --git a/drivers/gpu/drm/panel/panel-khadas-ts050.c b/drivers/gpu/drm/panel/panel-khadas-ts050.c
index 1ab1ebe30882..b942a0162274 100644
--- a/drivers/gpu/drm/panel/panel-khadas-ts050.c
+++ b/drivers/gpu/drm/panel/panel-khadas-ts050.c
@@ -568,7 +568,7 @@ static const struct khadas_ts050_panel_cmd init_code[] = {
{0xfb, 0x01},
/* Select CMD1 */
{0xff, 0x00},
- {0xd3, 0x05}, /* RGBMIPICTRL: VSYNC back porch = 5 */
+ {0xd3, 0x22}, /* RGBMIPICTRL: VSYNC back porch = 34 */
{0xd4, 0x04}, /* RGBMIPICTRL: VSYNC front porch = 4 */
};
@@ -717,15 +717,15 @@ static int khadas_ts050_panel_disable(struct drm_panel *panel)
}
static const struct drm_display_mode default_mode = {
- .clock = 120000,
- .hdisplay = 1088,
- .hsync_start = 1088 + 104,
- .hsync_end = 1088 + 104 + 4,
- .htotal = 1088 + 104 + 4 + 127,
+ .clock = 160000,
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 117,
+ .hsync_end = 1080 + 117 + 5,
+ .htotal = 1080 + 117 + 5 + 160,
.vdisplay = 1920,
.vsync_start = 1920 + 4,
- .vsync_end = 1920 + 4 + 2,
- .vtotal = 1920 + 4 + 2 + 3,
+ .vsync_end = 1920 + 4 + 3,
+ .vtotal = 1920 + 4 + 3 + 31,
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
};
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36523.c b/drivers/gpu/drm/panel/panel-novatek-nt36523.c
index d30dbbfb67b1..c3befa7f253d 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt36523.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt36523.c
@@ -5,6 +5,7 @@
* Copyright (c) 2022, 2023 Jianhua Lu <lujianhua000@gmail.com>
*/
+#include <linux/backlight.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
@@ -12,6 +13,8 @@
#include <linux/of_graph.h>
#include <linux/regulator/consumer.h>
+#include <video/mipi_display.h>
+
#include <drm/drm_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_mipi_dsi.h>
@@ -30,6 +33,7 @@ struct panel_info {
struct drm_panel panel;
struct mipi_dsi_device *dsi[2];
const struct panel_desc *desc;
+ enum drm_panel_orientation orientation;
struct gpio_desc *reset_gpio;
struct backlight_device *backlight;
@@ -53,6 +57,7 @@ struct panel_desc {
int (*init_sequence)(struct panel_info *pinfo);
bool is_dual_dsi;
+ bool has_dcs_backlight;
};
static inline struct panel_info *to_panel_info(struct drm_panel *panel)
@@ -478,6 +483,456 @@ static int elish_csot_init_sequence(struct panel_info *pinfo)
return 0;
}
+static int j606f_boe_init_sequence(struct panel_info *pinfo)
+{
+ struct mipi_dsi_device *dsi = pinfo->dsi[0];
+ struct device *dev = &dsi->dev;
+ int ret;
+
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x05, 0xd9);
+ mipi_dsi_dcs_write_seq(dsi, 0x07, 0x78);
+ mipi_dsi_dcs_write_seq(dsi, 0x08, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x63);
+ mipi_dsi_dcs_write_seq(dsi, 0x0e, 0x91);
+ mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x73);
+ mipi_dsi_dcs_write_seq(dsi, 0x95, 0xeb);
+ mipi_dsi_dcs_write_seq(dsi, 0x96, 0xeb);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x11);
+ mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x66);
+ mipi_dsi_dcs_write_seq(dsi, 0x75, 0xa2);
+ mipi_dsi_dcs_write_seq(dsi, 0x77, 0xb3);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, 0x00,
+ 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9);
+ mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, 0x01,
+ 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, 0x03,
+ 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b);
+ mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, 0x03,
+ 0xfd, 0x03, 0xff);
+ mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, 0x00,
+ 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9);
+ mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, 0x01,
+ 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, 0x03,
+ 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b);
+ mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, 0x03,
+ 0xfd, 0x03, 0xff);
+ mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, 0x00,
+ 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9);
+ mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, 0x01,
+ 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, 0x03,
+ 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b);
+ mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, 0x03,
+ 0xfd, 0x03, 0xff);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x21);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, 0x00,
+ 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1);
+ mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, 0x01,
+ 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29);
+ mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, 0x03,
+ 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73);
+ mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, 0x03,
+ 0xf5, 0x03, 0xf7);
+ mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, 0x00,
+ 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1);
+ mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, 0x01,
+ 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29);
+ mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, 0x03,
+ 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73);
+ mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, 0x03,
+ 0xf5, 0x03, 0xf7);
+ mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, 0x00,
+ 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1);
+ mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, 0x01,
+ 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29);
+ mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, 0x03,
+ 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73);
+ mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, 0x03,
+ 0xf5, 0x03, 0xf7);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x23);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x00, 0x80);
+ mipi_dsi_dcs_write_seq(dsi, 0x07, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x11, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x12, 0x77);
+ mipi_dsi_dcs_write_seq(dsi, 0x15, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0x16, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x01, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x02, 0x1c);
+ mipi_dsi_dcs_write_seq(dsi, 0x03, 0x1c);
+ mipi_dsi_dcs_write_seq(dsi, 0x04, 0x1d);
+ mipi_dsi_dcs_write_seq(dsi, 0x05, 0x1d);
+ mipi_dsi_dcs_write_seq(dsi, 0x06, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x07, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x08, 0x0f);
+ mipi_dsi_dcs_write_seq(dsi, 0x09, 0x0f);
+ mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x0e);
+ mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x0e);
+ mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x0d);
+ mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x0d);
+ mipi_dsi_dcs_write_seq(dsi, 0x0e, 0x0c);
+ mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x0c);
+ mipi_dsi_dcs_write_seq(dsi, 0x10, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0x11, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0x12, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x13, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x14, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x15, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x16, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x17, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x18, 0x1c);
+ mipi_dsi_dcs_write_seq(dsi, 0x19, 0x1c);
+ mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x1d);
+ mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x1d);
+ mipi_dsi_dcs_write_seq(dsi, 0x1c, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x0f);
+ mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x0f);
+ mipi_dsi_dcs_write_seq(dsi, 0x20, 0x0e);
+ mipi_dsi_dcs_write_seq(dsi, 0x21, 0x0e);
+ mipi_dsi_dcs_write_seq(dsi, 0x22, 0x0d);
+ mipi_dsi_dcs_write_seq(dsi, 0x23, 0x0d);
+ mipi_dsi_dcs_write_seq(dsi, 0x24, 0x0c);
+ mipi_dsi_dcs_write_seq(dsi, 0x25, 0x0c);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0x27, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0x28, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x29, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_LUT, 0x20);
+ mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x0a);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x44);
+ mipi_dsi_dcs_write_seq(dsi, 0x33, 0x0c);
+ mipi_dsi_dcs_write_seq(dsi, 0x34, 0x32);
+ mipi_dsi_dcs_write_seq(dsi, 0x37, 0x44);
+ mipi_dsi_dcs_write_seq(dsi, 0x38, 0x40);
+ mipi_dsi_dcs_write_seq(dsi, 0x39, 0x00);
+
+ ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x9a);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set pixel format: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0x3b, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_3D_CONTROL, 0x42);
+ mipi_dsi_dcs_write_seq(dsi, 0x3f, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0x43, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0x47, 0x66);
+ mipi_dsi_dcs_write_seq(dsi, 0x4a, 0x9a);
+ mipi_dsi_dcs_write_seq(dsi, 0x4b, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, 0x4c, 0x91);
+ mipi_dsi_dcs_write_seq(dsi, 0x4d, 0x21);
+ mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x43);
+
+ ret = mipi_dsi_dcs_set_display_brightness(dsi, 18);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display brightness: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0x52, 0x34);
+ mipi_dsi_dcs_write_seq(dsi, 0x55, 0x82, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x56, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x58, 0x21);
+ mipi_dsi_dcs_write_seq(dsi, 0x59, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0x5a, 0xba);
+ mipi_dsi_dcs_write_seq(dsi, 0x5b, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x00, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0x5f, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x65, 0x82);
+ mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x20);
+ mipi_dsi_dcs_write_seq(dsi, 0x7f, 0x3c);
+ mipi_dsi_dcs_write_seq(dsi, 0x82, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x97, 0xc0);
+ mipi_dsi_dcs_write_seq(dsi, 0xb6,
+ 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x05, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x92, 0xc4);
+ mipi_dsi_dcs_write_seq(dsi, 0x93, 0x1a);
+ mipi_dsi_dcs_write_seq(dsi, 0x94, 0x5f);
+ mipi_dsi_dcs_write_seq(dsi, 0xd7, 0x55);
+ mipi_dsi_dcs_write_seq(dsi, 0xda, 0x0a);
+ mipi_dsi_dcs_write_seq(dsi, 0xde, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0xdb, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xdc, 0xc4);
+ mipi_dsi_dcs_write_seq(dsi, 0xdd, 0x22);
+ mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xe0, 0xc4);
+ mipi_dsi_dcs_write_seq(dsi, 0xe1, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xe2, 0xc4);
+ mipi_dsi_dcs_write_seq(dsi, 0xe3, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xe4, 0xc4);
+ mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xe6, 0xc4);
+ mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x88);
+ mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x88);
+ mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x90);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x05, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x19, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0x1f, 0xba);
+ mipi_dsi_dcs_write_seq(dsi, 0x20, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0xba);
+ mipi_dsi_dcs_write_seq(dsi, 0x27, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, 0x33, 0xba);
+ mipi_dsi_dcs_write_seq(dsi, 0x34, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, 0x3f, 0xe0);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_VSYNC_TIMING, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x44, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_GET_SCANLINE, 0x40);
+ mipi_dsi_dcs_write_seq(dsi, 0x48, 0xba);
+ mipi_dsi_dcs_write_seq(dsi, 0x49, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0xd0);
+ mipi_dsi_dcs_write_seq(dsi, 0x61, 0xba);
+ mipi_dsi_dcs_write_seq(dsi, 0x62, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, 0xf1, 0x10);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x64, 0x16);
+ mipi_dsi_dcs_write_seq(dsi, 0x67, 0x16);
+ mipi_dsi_dcs_write_seq(dsi, 0x6a, 0x16);
+ mipi_dsi_dcs_write_seq(dsi, 0x70, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_READ_PPS_START, 0xf3);
+ mipi_dsi_dcs_write_seq(dsi, 0xa3, 0xff);
+ mipi_dsi_dcs_write_seq(dsi, 0xa4, 0xff);
+ mipi_dsi_dcs_write_seq(dsi, 0xa5, 0xff);
+ mipi_dsi_dcs_write_seq(dsi, 0xd6, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x00, 0xa1);
+ mipi_dsi_dcs_write_seq(dsi, 0x0a, 0xf2);
+ mipi_dsi_dcs_write_seq(dsi, 0x04, 0x28);
+ mipi_dsi_dcs_write_seq(dsi, 0x06, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x13);
+ mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x0a);
+ mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x0a);
+ mipi_dsi_dcs_write_seq(dsi, 0x11, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x12, 0x50);
+ mipi_dsi_dcs_write_seq(dsi, 0x13, 0x51);
+ mipi_dsi_dcs_write_seq(dsi, 0x14, 0x65);
+ mipi_dsi_dcs_write_seq(dsi, 0x15, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x16, 0x10);
+ mipi_dsi_dcs_write_seq(dsi, 0x17, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, 0x18, 0x86);
+ mipi_dsi_dcs_write_seq(dsi, 0x19, 0x11);
+ mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x7b);
+ mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x10);
+ mipi_dsi_dcs_write_seq(dsi, 0x1c, 0xbb);
+ mipi_dsi_dcs_write_seq(dsi, 0x22, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x23, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x11);
+ mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x7b);
+ mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x1e, 0xc3);
+ mipi_dsi_dcs_write_seq(dsi, 0x1f, 0xc3);
+ mipi_dsi_dcs_write_seq(dsi, 0x24, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x25, 0xc3);
+ mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0xc3);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x32, 0xc3);
+ mipi_dsi_dcs_write_seq(dsi, 0x39, 0x00);
+
+ ret = mipi_dsi_dcs_set_pixel_format(dsi, 0xc3);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set pixel format: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0x20, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x33, 0x11);
+ mipi_dsi_dcs_write_seq(dsi, 0x34, 0x78);
+ mipi_dsi_dcs_write_seq(dsi, 0x35, 0x16);
+ mipi_dsi_dcs_write_seq(dsi, 0xc8, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0xc9, 0x82);
+ mipi_dsi_dcs_write_seq(dsi, 0xca, 0x4e);
+ mipi_dsi_dcs_write_seq(dsi, 0xcb, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_READ_PPS_CONTINUE, 0x4c);
+ mipi_dsi_dcs_write_seq(dsi, 0xaa, 0x47);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x27);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x56, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0x58, 0x80);
+ mipi_dsi_dcs_write_seq(dsi, 0x59, 0x53);
+ mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x14);
+ mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x20);
+ mipi_dsi_dcs_write_seq(dsi, 0x5f, 0x10);
+ mipi_dsi_dcs_write_seq(dsi, 0x60, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x61, 0x1d);
+ mipi_dsi_dcs_write_seq(dsi, 0x62, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x63, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x64, 0x24);
+ mipi_dsi_dcs_write_seq(dsi, 0x65, 0x1c);
+ mipi_dsi_dcs_write_seq(dsi, 0x66, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x67, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x68, 0x25);
+ mipi_dsi_dcs_write_seq(dsi, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x78, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xc3, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xd1, 0x24);
+ mipi_dsi_dcs_write_seq(dsi, 0xd2, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x22, 0x2f);
+ mipi_dsi_dcs_write_seq(dsi, 0x23, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0x24, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x25, 0xc3);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0xf8);
+ mipi_dsi_dcs_write_seq(dsi, 0x27, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x28, 0x1a);
+ mipi_dsi_dcs_write_seq(dsi, 0x29, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x1a);
+ mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_LUT, 0x1a);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0xe0);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x14, 0x60);
+ mipi_dsi_dcs_write_seq(dsi, 0x16, 0xc0);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0xf0);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+
+ ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x08);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set pixel format: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+
+ ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x5d);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set pixel format: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0x3b, 0x60);
+ mipi_dsi_dcs_write_seq(dsi, 0x4a, 0x5d);
+ mipi_dsi_dcs_write_seq(dsi, 0x4b, 0x60);
+ mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x70);
+ mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x60);
+ mipi_dsi_dcs_write_seq(dsi, 0x91, 0x44);
+ mipi_dsi_dcs_write_seq(dsi, 0x92, 0x75);
+ mipi_dsi_dcs_write_seq(dsi, 0xdb, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xdc, 0x75);
+ mipi_dsi_dcs_write_seq(dsi, 0xdd, 0x22);
+ mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xe0, 0x75);
+ mipi_dsi_dcs_write_seq(dsi, 0xe1, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xe2, 0x75);
+ mipi_dsi_dcs_write_seq(dsi, 0xe3, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xe4, 0x75);
+ mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xe6, 0x75);
+ mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x70);
+ mipi_dsi_dcs_write_seq(dsi, 0x20, 0x60);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0x70);
+ mipi_dsi_dcs_write_seq(dsi, 0x27, 0x60);
+ mipi_dsi_dcs_write_seq(dsi, 0x33, 0x70);
+ mipi_dsi_dcs_write_seq(dsi, 0x34, 0x60);
+ mipi_dsi_dcs_write_seq(dsi, 0x48, 0x70);
+ mipi_dsi_dcs_write_seq(dsi, 0x49, 0x60);
+ mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x61, 0x70);
+ mipi_dsi_dcs_write_seq(dsi, 0x62, 0x60);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x02, 0x31);
+ mipi_dsi_dcs_write_seq(dsi, 0x19, 0x0a);
+ mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x7f);
+ mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x0a);
+ mipi_dsi_dcs_write_seq(dsi, 0x1c, 0x0c);
+ mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x0a);
+ mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x7f);
+ mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x75);
+ mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x75);
+ mipi_dsi_dcs_write_seq(dsi, 0x25, 0x75);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x75);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x32, 0x8d);
+
+ ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x75);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set pixel format: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x25, 0x75);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x18, 0x40);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x02);
+
+ ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set tear on: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x13);
+ mipi_dsi_dcs_write_seq(dsi, 0x3b, 0x03, 0x5f, 0x1a, 0x04, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
+ usleep_range(10000, 11000);
+ mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+
+ ret = mipi_dsi_dcs_set_display_brightness(dsi, 0);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display brightness: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x2c);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x68, 0x05, 0x01);
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+ return ret;
+ }
+ msleep(100);
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display on: %d\n", ret);
+ return ret;
+ }
+ msleep(30);
+
+ return 0;
+}
+
static const struct drm_display_mode elish_boe_modes[] = {
{
/* There is only one 120 Hz timing, but it doesn't work perfectly, 104 Hz preferred */
@@ -508,6 +963,22 @@ static const struct drm_display_mode elish_csot_modes[] = {
},
};
+static const struct drm_display_mode j606f_boe_modes[] = {
+ {
+ .clock = (1200 + 58 + 2 + 60) * (2000 + 26 + 2 + 93) * 60 / 1000,
+ .hdisplay = 1200,
+ .hsync_start = 1200 + 58,
+ .hsync_end = 1200 + 58 + 2,
+ .htotal = 1200 + 58 + 2 + 60,
+ .vdisplay = 2000,
+ .vsync_start = 2000 + 26,
+ .vsync_end = 2000 + 26 + 2,
+ .vtotal = 2000 + 26 + 2 + 93,
+ .width_mm = 143,
+ .height_mm = 235,
+ },
+};
+
static const struct panel_desc elish_boe_desc = {
.modes = elish_boe_modes,
.num_modes = ARRAY_SIZE(elish_boe_modes),
@@ -544,6 +1015,20 @@ static const struct panel_desc elish_csot_desc = {
.is_dual_dsi = true,
};
+static const struct panel_desc j606f_boe_desc = {
+ .modes = j606f_boe_modes,
+ .num_modes = ARRAY_SIZE(j606f_boe_modes),
+ .width_mm = 143,
+ .height_mm = 235,
+ .bpc = 8,
+ .lanes = 4,
+ .format = MIPI_DSI_FMT_RGB888,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
+ .init_sequence = j606f_boe_init_sequence,
+ .has_dcs_backlight = true,
+};
+
static void nt36523_reset(struct panel_info *pinfo)
{
gpiod_set_value_cansleep(pinfo->reset_gpio, 1);
@@ -672,13 +1157,74 @@ static int nt36523_get_modes(struct drm_panel *panel,
return pinfo->desc->num_modes;
}
+static enum drm_panel_orientation nt36523_get_orientation(struct drm_panel *panel)
+{
+ struct panel_info *pinfo = to_panel_info(panel);
+
+ return pinfo->orientation;
+}
+
static const struct drm_panel_funcs nt36523_panel_funcs = {
.disable = nt36523_disable,
.prepare = nt36523_prepare,
.unprepare = nt36523_unprepare,
.get_modes = nt36523_get_modes,
+ .get_orientation = nt36523_get_orientation,
};
+static int nt36523_bl_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness = backlight_get_brightness(bl);
+ int ret;
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
+ if (ret < 0)
+ return ret;
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ return 0;
+}
+
+static int nt36523_bl_get_brightness(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness;
+ int ret;
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_get_display_brightness_large(dsi, &brightness);
+ if (ret < 0)
+ return ret;
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ return brightness;
+}
+
+static const struct backlight_ops nt36523_bl_ops = {
+ .update_status = nt36523_bl_update_status,
+ .get_brightness = nt36523_bl_get_brightness,
+};
+
+static struct backlight_device *nt36523_create_backlight(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_RAW,
+ .brightness = 512,
+ .max_brightness = 4095,
+ .scale = BACKLIGHT_SCALE_NON_LINEAR,
+ };
+
+ return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+ &nt36523_bl_ops, &props);
+}
+
static int nt36523_probe(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
@@ -730,9 +1276,22 @@ static int nt36523_probe(struct mipi_dsi_device *dsi)
mipi_dsi_set_drvdata(dsi, pinfo);
drm_panel_init(&pinfo->panel, dev, &nt36523_panel_funcs, DRM_MODE_CONNECTOR_DSI);
- ret = drm_panel_of_backlight(&pinfo->panel);
- if (ret)
- return dev_err_probe(dev, ret, "failed to get backlight\n");
+ ret = of_drm_get_panel_orientation(dev->of_node, &pinfo->orientation);
+ if (ret < 0) {
+ dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, ret);
+ return ret;
+ }
+
+ if (pinfo->desc->has_dcs_backlight) {
+ pinfo->panel.backlight = nt36523_create_backlight(dsi);
+ if (IS_ERR(pinfo->panel.backlight))
+ return dev_err_probe(dev, PTR_ERR(pinfo->panel.backlight),
+ "Failed to create backlight\n");
+ } else {
+ ret = drm_panel_of_backlight(&pinfo->panel);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get backlight\n");
+ }
drm_panel_add(&pinfo->panel);
@@ -751,6 +1310,10 @@ static int nt36523_probe(struct mipi_dsi_device *dsi)
static const struct of_device_id nt36523_of_match[] = {
{
+ .compatible = "lenovo,j606f-boe-nt36523w",
+ .data = &j606f_boe_desc,
+ },
+ {
.compatible = "xiaomi,elish-boe-nt36523",
.data = &elish_boe_desc,
},
diff --git a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
index aba556c98300..4819ada69482 100644
--- a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
+++ b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
@@ -308,7 +308,7 @@ static struct i2c_driver lcd_olinuxino_driver = {
.name = "lcd_olinuxino",
.of_match_table = lcd_olinuxino_of_ids,
},
- .probe_new = lcd_olinuxino_probe,
+ .probe = lcd_olinuxino_probe,
.remove = lcd_olinuxino_remove,
};
diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
index 11d6ca276c1e..90ea91e4311d 100644
--- a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
+++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
@@ -489,7 +489,7 @@ static struct i2c_driver rpi_touchscreen_driver = {
.name = "rpi_touchscreen",
.of_match_table = rpi_touchscreen_of_ids,
},
- .probe_new = rpi_touchscreen_probe,
+ .probe = rpi_touchscreen_probe,
.remove = rpi_touchscreen_remove,
};
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c b/drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c
new file mode 100644
index 000000000000..102e1fc7ee38
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c
@@ -0,0 +1,585 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Samsung S6D7AA0 MIPI-DSI TFT LCD controller drm_panel driver.
+ *
+ * Copyright (C) 2022 Artur Weber <aweber.kernel@gmail.com>
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include <video/mipi_display.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+/* Manufacturer command set */
+#define MCS_BL_CTL 0xc3
+#define MCS_OTP_RELOAD 0xd0
+#define MCS_PASSWD1 0xf0
+#define MCS_PASSWD2 0xf1
+#define MCS_PASSWD3 0xfc
+
+struct s6d7aa0 {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[2];
+ const struct s6d7aa0_panel_desc *desc;
+};
+
+struct s6d7aa0_panel_desc {
+ unsigned int panel_type;
+ int (*init_func)(struct s6d7aa0 *ctx);
+ int (*off_func)(struct s6d7aa0 *ctx);
+ const struct drm_display_mode *drm_mode;
+ unsigned long mode_flags;
+ u32 bus_flags;
+ bool has_backlight;
+ bool use_passwd3;
+};
+
+enum s6d7aa0_panels {
+ S6D7AA0_PANEL_LSL080AL02,
+ S6D7AA0_PANEL_LSL080AL03,
+ S6D7AA0_PANEL_LTL101AT01,
+};
+
+static inline struct s6d7aa0 *panel_to_s6d7aa0(struct drm_panel *panel)
+{
+ return container_of(panel, struct s6d7aa0, panel);
+}
+
+static void s6d7aa0_reset(struct s6d7aa0 *ctx)
+{
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ msleep(50);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ msleep(50);
+}
+
+static int s6d7aa0_lock(struct s6d7aa0 *ctx, bool lock)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ int ret = 0;
+
+ if (lock) {
+ mipi_dsi_dcs_write_seq(dsi, MCS_PASSWD1, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_seq(dsi, MCS_PASSWD2, 0xa5, 0xa5);
+ if (ctx->desc->use_passwd3)
+ mipi_dsi_dcs_write_seq(dsi, MCS_PASSWD3, 0x5a, 0x5a);
+ } else {
+ mipi_dsi_dcs_write_seq(dsi, MCS_PASSWD1, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, MCS_PASSWD2, 0x5a, 0x5a);
+ if (ctx->desc->use_passwd3)
+ mipi_dsi_dcs_write_seq(dsi, MCS_PASSWD3, 0xa5, 0xa5);
+ }
+
+ return ret;
+}
+
+static int s6d7aa0_on(struct s6d7aa0 *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ int ret;
+
+ ret = ctx->desc->init_func(ctx);
+ if (ret < 0) {
+ dev_err(dev, "Failed to initialize panel: %d\n", ret);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ return ret;
+ }
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display on: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int s6d7aa0_off(struct s6d7aa0 *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ int ret;
+
+ ret = ctx->desc->off_func(ctx);
+ if (ret < 0) {
+ dev_err(dev, "Panel-specific off function failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = mipi_dsi_dcs_set_display_off(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display off: %d\n", ret);
+ return ret;
+ }
+ msleep(64);
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+ return ret;
+ }
+ msleep(120);
+
+ return 0;
+}
+
+static int s6d7aa0_prepare(struct drm_panel *panel)
+{
+ struct s6d7aa0 *ctx = panel_to_s6d7aa0(panel);
+ struct device *dev = &ctx->dsi->dev;
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+
+ s6d7aa0_reset(ctx);
+
+ ret = s6d7aa0_on(ctx);
+ if (ret < 0) {
+ dev_err(dev, "Failed to initialize panel: %d\n", ret);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int s6d7aa0_disable(struct drm_panel *panel)
+{
+ struct s6d7aa0 *ctx = panel_to_s6d7aa0(panel);
+ struct device *dev = &ctx->dsi->dev;
+ int ret;
+
+ ret = s6d7aa0_off(ctx);
+ if (ret < 0)
+ dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+ return 0;
+}
+
+static int s6d7aa0_unprepare(struct drm_panel *panel)
+{
+ struct s6d7aa0 *ctx = panel_to_s6d7aa0(panel);
+
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+ return 0;
+}
+
+/* Backlight control code */
+
+static int s6d7aa0_bl_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness = backlight_get_brightness(bl);
+ int ret;
+
+ ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int s6d7aa0_bl_get_brightness(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness;
+ int ret;
+
+ ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
+ if (ret < 0)
+ return ret;
+
+ return brightness & 0xff;
+}
+
+static const struct backlight_ops s6d7aa0_bl_ops = {
+ .update_status = s6d7aa0_bl_update_status,
+ .get_brightness = s6d7aa0_bl_get_brightness,
+};
+
+static struct backlight_device *
+s6d7aa0_create_backlight(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_RAW,
+ .brightness = 255,
+ .max_brightness = 255,
+ };
+
+ return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+ &s6d7aa0_bl_ops, &props);
+}
+
+/* Initialization code and structures for LSL080AL02 panel */
+
+static int s6d7aa0_lsl080al02_init(struct s6d7aa0 *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ int ret;
+
+ usleep_range(20000, 25000);
+
+ ret = s6d7aa0_lock(ctx, false);
+ if (ret < 0) {
+ dev_err(dev, "Failed to unlock registers: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, MCS_OTP_RELOAD, 0x00, 0x10);
+ usleep_range(1000, 1500);
+
+ /* SEQ_B6_PARAM_8_R01 */
+ mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x10);
+
+ /* BL_CTL_ON */
+ mipi_dsi_dcs_write_seq(dsi, MCS_BL_CTL, 0x40, 0x00, 0x28);
+
+ usleep_range(5000, 6000);
+
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x04);
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+ return ret;
+ }
+
+ msleep(120);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
+
+ ret = s6d7aa0_lock(ctx, true);
+ if (ret < 0) {
+ dev_err(dev, "Failed to lock registers: %d\n", ret);
+ return ret;
+ }
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display on: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int s6d7aa0_lsl080al02_off(struct s6d7aa0 *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+
+ /* BL_CTL_OFF */
+ mipi_dsi_dcs_write_seq(dsi, MCS_BL_CTL, 0x40, 0x00, 0x20);
+
+ return 0;
+}
+
+static const struct drm_display_mode s6d7aa0_lsl080al02_mode = {
+ .clock = (800 + 16 + 4 + 140) * (1280 + 8 + 4 + 4) * 60 / 1000,
+ .hdisplay = 800,
+ .hsync_start = 800 + 16,
+ .hsync_end = 800 + 16 + 4,
+ .htotal = 800 + 16 + 4 + 140,
+ .vdisplay = 1280,
+ .vsync_start = 1280 + 8,
+ .vsync_end = 1280 + 8 + 4,
+ .vtotal = 1280 + 8 + 4 + 4,
+ .width_mm = 108,
+ .height_mm = 173,
+};
+
+static const struct s6d7aa0_panel_desc s6d7aa0_lsl080al02_desc = {
+ .panel_type = S6D7AA0_PANEL_LSL080AL02,
+ .init_func = s6d7aa0_lsl080al02_init,
+ .off_func = s6d7aa0_lsl080al02_off,
+ .drm_mode = &s6d7aa0_lsl080al02_mode,
+ .mode_flags = MIPI_DSI_MODE_VSYNC_FLUSH | MIPI_DSI_MODE_VIDEO_NO_HFP,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+
+ .has_backlight = false,
+ .use_passwd3 = false,
+};
+
+/* Initialization code and structures for LSL080AL03 panel */
+
+static int s6d7aa0_lsl080al03_init(struct s6d7aa0 *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ int ret;
+
+ usleep_range(20000, 25000);
+
+ ret = s6d7aa0_lock(ctx, false);
+ if (ret < 0) {
+ dev_err(dev, "Failed to unlock registers: %d\n", ret);
+ return ret;
+ }
+
+ if (ctx->desc->panel_type == S6D7AA0_PANEL_LSL080AL03) {
+ mipi_dsi_dcs_write_seq(dsi, MCS_BL_CTL, 0xc7, 0x00, 0x29);
+ mipi_dsi_dcs_write_seq(dsi, 0xbc, 0x01, 0x4e, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, 0xfd, 0x16, 0x10, 0x11, 0x23,
+ 0x09);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x00, 0x02, 0x03, 0x21,
+ 0x80, 0x78);
+ } else if (ctx->desc->panel_type == S6D7AA0_PANEL_LTL101AT01) {
+ mipi_dsi_dcs_write_seq(dsi, MCS_BL_CTL, 0x40, 0x00, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0xbc, 0x01, 0x4e, 0x0b);
+ mipi_dsi_dcs_write_seq(dsi, 0xfd, 0x16, 0x10, 0x11, 0x23,
+ 0x09);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x00, 0x02, 0x03, 0x21,
+ 0x80, 0x68);
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x51);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+ mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x02, 0x08, 0x08);
+
+ usleep_range(10000, 11000);
+
+ mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x80, 0x80, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0xcd,
+ 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
+ 0x2e, 0x2e, 0x2e, 0x2e, 0x2e);
+ mipi_dsi_dcs_write_seq(dsi, 0xce,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x03);
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+ return ret;
+ }
+
+ ret = s6d7aa0_lock(ctx, true);
+ if (ret < 0) {
+ dev_err(dev, "Failed to lock registers: %d\n", ret);
+ return ret;
+ }
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display on: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int s6d7aa0_lsl080al03_off(struct s6d7aa0 *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+
+ mipi_dsi_dcs_write_seq(dsi, 0x22, 0x00);
+
+ return 0;
+}
+
+static const struct drm_display_mode s6d7aa0_lsl080al03_mode = {
+ .clock = (768 + 18 + 16 + 126) * (1024 + 8 + 2 + 6) * 60 / 1000,
+ .hdisplay = 768,
+ .hsync_start = 768 + 18,
+ .hsync_end = 768 + 18 + 16,
+ .htotal = 768 + 18 + 16 + 126,
+ .vdisplay = 1024,
+ .vsync_start = 1024 + 8,
+ .vsync_end = 1024 + 8 + 2,
+ .vtotal = 1024 + 8 + 2 + 6,
+ .width_mm = 122,
+ .height_mm = 163,
+};
+
+static const struct s6d7aa0_panel_desc s6d7aa0_lsl080al03_desc = {
+ .panel_type = S6D7AA0_PANEL_LSL080AL03,
+ .init_func = s6d7aa0_lsl080al03_init,
+ .off_func = s6d7aa0_lsl080al03_off,
+ .drm_mode = &s6d7aa0_lsl080al03_mode,
+ .mode_flags = MIPI_DSI_MODE_NO_EOT_PACKET,
+ .bus_flags = 0,
+
+ .has_backlight = true,
+ .use_passwd3 = true,
+};
+
+/* Initialization structures for LTL101AT01 panel */
+
+static const struct drm_display_mode s6d7aa0_ltl101at01_mode = {
+ .clock = (768 + 96 + 16 + 184) * (1024 + 8 + 2 + 6) * 60 / 1000,
+ .hdisplay = 768,
+ .hsync_start = 768 + 96,
+ .hsync_end = 768 + 96 + 16,
+ .htotal = 768 + 96 + 16 + 184,
+ .vdisplay = 1024,
+ .vsync_start = 1024 + 8,
+ .vsync_end = 1024 + 8 + 2,
+ .vtotal = 1024 + 8 + 2 + 6,
+ .width_mm = 148,
+ .height_mm = 197,
+};
+
+static const struct s6d7aa0_panel_desc s6d7aa0_ltl101at01_desc = {
+ .panel_type = S6D7AA0_PANEL_LTL101AT01,
+ .init_func = s6d7aa0_lsl080al03_init, /* Similar init to LSL080AL03 */
+ .off_func = s6d7aa0_lsl080al03_off,
+ .drm_mode = &s6d7aa0_ltl101at01_mode,
+ .mode_flags = MIPI_DSI_MODE_NO_EOT_PACKET,
+ .bus_flags = 0,
+
+ .has_backlight = true,
+ .use_passwd3 = true,
+};
+
+static int s6d7aa0_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct drm_display_mode *mode;
+ struct s6d7aa0 *ctx;
+
+ ctx = container_of(panel, struct s6d7aa0, panel);
+ if (!ctx)
+ return -EINVAL;
+
+ mode = drm_mode_duplicate(connector->dev, ctx->desc->drm_mode);
+ if (!mode)
+ return -ENOMEM;
+
+ drm_mode_set_name(mode);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+ connector->display_info.bus_flags = ctx->desc->bus_flags;
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs s6d7aa0_panel_funcs = {
+ .disable = s6d7aa0_disable,
+ .prepare = s6d7aa0_prepare,
+ .unprepare = s6d7aa0_unprepare,
+ .get_modes = s6d7aa0_get_modes,
+};
+
+static int s6d7aa0_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct s6d7aa0 *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->desc = of_device_get_match_data(dev);
+ if (!ctx->desc)
+ return -ENODEV;
+
+ ctx->supplies[0].supply = "power";
+ ctx->supplies[1].supply = "vmipi";
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+ ctx->supplies);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+ "Failed to get reset-gpios\n");
+
+ ctx->dsi = dsi;
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST
+ | ctx->desc->mode_flags;
+
+ drm_panel_init(&ctx->panel, dev, &s6d7aa0_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ ctx->panel.prepare_prev_first = true;
+
+ ret = drm_panel_of_backlight(&ctx->panel);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+ /* Use DSI-based backlight as fallback if available */
+ if (ctx->desc->has_backlight && !ctx->panel.backlight) {
+ ctx->panel.backlight = s6d7aa0_create_backlight(dsi);
+ if (IS_ERR(ctx->panel.backlight))
+ return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+ "Failed to create backlight\n");
+ }
+
+ drm_panel_add(&ctx->panel);
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+ drm_panel_remove(&ctx->panel);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void s6d7aa0_remove(struct mipi_dsi_device *dsi)
+{
+ struct s6d7aa0 *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = mipi_dsi_detach(dsi);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+ drm_panel_remove(&ctx->panel);
+}
+
+static const struct of_device_id s6d7aa0_of_match[] = {
+ {
+ .compatible = "samsung,lsl080al02",
+ .data = &s6d7aa0_lsl080al02_desc
+ },
+ {
+ .compatible = "samsung,lsl080al03",
+ .data = &s6d7aa0_lsl080al03_desc
+ },
+ {
+ .compatible = "samsung,ltl101at01",
+ .data = &s6d7aa0_ltl101at01_desc
+ },
+ { /* sentinel */ }
+};
+
+static struct mipi_dsi_driver s6d7aa0_driver = {
+ .probe = s6d7aa0_probe,
+ .remove = s6d7aa0_remove,
+ .driver = {
+ .name = "panel-samsung-s6d7aa0",
+ .of_match_table = s6d7aa0_of_match,
+ },
+};
+module_mipi_dsi_driver(s6d7aa0_driver);
+
+MODULE_AUTHOR("Artur Weber <aweber.kernel@gmail.com>");
+MODULE_DESCRIPTION("Samsung S6D7AA0 MIPI-DSI LCD controller driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
index d1ec80a3e3c7..855e64444daa 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
@@ -28,9 +28,6 @@ struct sharp_nt_panel {
struct gpio_desc *reset_gpio;
bool prepared;
- bool enabled;
-
- const struct drm_display_mode *mode;
};
static inline struct sharp_nt_panel *to_sharp_nt_panel(struct drm_panel *panel)
@@ -97,19 +94,6 @@ static int sharp_nt_panel_off(struct sharp_nt_panel *sharp_nt)
return 0;
}
-
-static int sharp_nt_panel_disable(struct drm_panel *panel)
-{
- struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
-
- if (!sharp_nt->enabled)
- return 0;
-
- sharp_nt->enabled = false;
-
- return 0;
-}
-
static int sharp_nt_panel_unprepare(struct drm_panel *panel)
{
struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
@@ -179,28 +163,16 @@ poweroff:
return ret;
}
-static int sharp_nt_panel_enable(struct drm_panel *panel)
-{
- struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
-
- if (sharp_nt->enabled)
- return 0;
-
- sharp_nt->enabled = true;
-
- return 0;
-}
-
static const struct drm_display_mode default_mode = {
- .clock = 41118,
+ .clock = (540 + 48 + 32 + 80) * (960 + 3 + 10 + 15) * 60 / 1000,
.hdisplay = 540,
.hsync_start = 540 + 48,
- .hsync_end = 540 + 48 + 80,
- .htotal = 540 + 48 + 80 + 32,
+ .hsync_end = 540 + 48 + 32,
+ .htotal = 540 + 48 + 32 + 80,
.vdisplay = 960,
.vsync_start = 960 + 3,
- .vsync_end = 960 + 3 + 15,
- .vtotal = 960 + 3 + 15 + 1,
+ .vsync_end = 960 + 3 + 10,
+ .vtotal = 960 + 3 + 10 + 15,
};
static int sharp_nt_panel_get_modes(struct drm_panel *panel,
@@ -227,10 +199,8 @@ static int sharp_nt_panel_get_modes(struct drm_panel *panel,
}
static const struct drm_panel_funcs sharp_nt_panel_funcs = {
- .disable = sharp_nt_panel_disable,
.unprepare = sharp_nt_panel_unprepare,
.prepare = sharp_nt_panel_prepare,
- .enable = sharp_nt_panel_enable,
.get_modes = sharp_nt_panel_get_modes,
};
@@ -239,8 +209,6 @@ static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt)
struct device *dev = &sharp_nt->dsi->dev;
int ret;
- sharp_nt->mode = &default_mode;
-
sharp_nt->supply = devm_regulator_get(dev, "avdd");
if (IS_ERR(sharp_nt->supply))
return PTR_ERR(sharp_nt->supply);
@@ -280,6 +248,7 @@ static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 2;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
+ MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_VIDEO_HSE |
MIPI_DSI_CLOCK_NON_CONTINUOUS |
MIPI_DSI_MODE_NO_EOT_PACKET;
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 065f378bba9d..a247a0e7c799 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -759,8 +759,8 @@ static const struct panel_desc ampire_am_480272h3tmqw_t01h = {
.num_modes = 1,
.bpc = 8,
.size = {
- .width = 105,
- .height = 67,
+ .width = 99,
+ .height = 58,
},
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
};
@@ -778,6 +778,36 @@ static const struct drm_display_mode ampire_am800480r3tmqwa1h_mode = {
.flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
};
+static const struct display_timing ampire_am_800480l1tmqw_t00h_timing = {
+ .pixelclock = { 29930000, 33260000, 36590000 },
+ .hactive = { 800, 800, 800 },
+ .hfront_porch = { 1, 40, 168 },
+ .hback_porch = { 88, 88, 88 },
+ .hsync_len = { 1, 128, 128 },
+ .vactive = { 480, 480, 480 },
+ .vfront_porch = { 1, 35, 37 },
+ .vback_porch = { 8, 8, 8 },
+ .vsync_len = { 1, 2, 2 },
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
+ DISPLAY_FLAGS_SYNC_POSEDGE,
+};
+
+static const struct panel_desc ampire_am_800480l1tmqw_t00h = {
+ .timings = &ampire_am_800480l1tmqw_t00h_timing,
+ .num_timings = 1,
+ .bpc = 8,
+ .size = {
+ .width = 111,
+ .height = 67,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH |
+ DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
+ DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
+};
+
static const struct panel_desc ampire_am800480r3tmqwa1h = {
.modes = &ampire_am800480r3tmqwa1h_mode,
.num_modes = 1,
@@ -1211,6 +1241,37 @@ static const struct panel_desc bananapi_s070wv20_ct16 = {
},
};
+static const struct display_timing boe_ev121wxm_n10_1850_timing = {
+ .pixelclock = { 69922000, 71000000, 72293000 },
+ .hactive = { 1280, 1280, 1280 },
+ .hfront_porch = { 48, 48, 48 },
+ .hback_porch = { 80, 80, 80 },
+ .hsync_len = { 32, 32, 32 },
+ .vactive = { 800, 800, 800 },
+ .vfront_porch = { 3, 3, 3 },
+ .vback_porch = { 14, 14, 14 },
+ .vsync_len = { 6, 6, 6 },
+};
+
+static const struct panel_desc boe_ev121wxm_n10_1850 = {
+ .timings = &boe_ev121wxm_n10_1850_timing,
+ .num_timings = 1,
+ .bpc = 8,
+ .size = {
+ .width = 261,
+ .height = 163,
+ },
+ .delay = {
+ .prepare = 9,
+ .enable = 300,
+ .unprepare = 300,
+ .disable = 560,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
static const struct drm_display_mode boe_hv070wsa_mode = {
.clock = 42105,
.hdisplay = 1024,
@@ -2142,6 +2203,38 @@ static const struct panel_desc innolux_at070tn92 = {
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
};
+static const struct display_timing innolux_g070ace_l01_timing = {
+ .pixelclock = { 25200000, 35000000, 35700000 },
+ .hactive = { 800, 800, 800 },
+ .hfront_porch = { 30, 32, 87 },
+ .hback_porch = { 30, 32, 87 },
+ .hsync_len = { 1, 1, 1 },
+ .vactive = { 480, 480, 480 },
+ .vfront_porch = { 3, 3, 3 },
+ .vback_porch = { 13, 13, 13 },
+ .vsync_len = { 1, 1, 4 },
+ .flags = DISPLAY_FLAGS_DE_HIGH,
+};
+
+static const struct panel_desc innolux_g070ace_l01 = {
+ .timings = &innolux_g070ace_l01_timing,
+ .num_timings = 1,
+ .bpc = 8,
+ .size = {
+ .width = 152,
+ .height = 91,
+ },
+ .delay = {
+ .prepare = 10,
+ .enable = 50,
+ .disable = 50,
+ .unprepare = 500,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
static const struct display_timing innolux_g070y2_l01_timing = {
.pixelclock = { 28000000, 29500000, 32000000 },
.hactive = { 800, 800, 800 },
@@ -3188,6 +3281,32 @@ static const struct panel_desc qishenglong_gopher2b_lcd = {
.connector_type = DRM_MODE_CONNECTOR_DPI,
};
+static const struct display_timing rocktech_rk043fn48h_timing = {
+ .pixelclock = { 6000000, 9000000, 12000000 },
+ .hactive = { 480, 480, 480 },
+ .hback_porch = { 8, 43, 43 },
+ .hfront_porch = { 2, 8, 8 },
+ .hsync_len = { 1, 1, 1 },
+ .vactive = { 272, 272, 272 },
+ .vback_porch = { 2, 12, 12 },
+ .vfront_porch = { 1, 4, 4 },
+ .vsync_len = { 1, 10, 10 },
+ .flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE,
+};
+
+static const struct panel_desc rocktech_rk043fn48h = {
+ .timings = &rocktech_rk043fn48h_timing,
+ .num_timings = 1,
+ .bpc = 8,
+ .size = {
+ .width = 95,
+ .height = 54,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
+};
+
static const struct display_timing rocktech_rk070er9427_timing = {
.pixelclock = { 26400000, 33300000, 46800000 },
.hactive = { 800, 800, 800 },
@@ -3931,6 +4050,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "ampire,am-480272h3tmqw-t01h",
.data = &ampire_am_480272h3tmqw_t01h,
}, {
+ .compatible = "ampire,am-800480l1tmqw-t00h",
+ .data = &ampire_am_800480l1tmqw_t00h,
+ }, {
.compatible = "ampire,am800480r3tmqwa1h",
.data = &ampire_am800480r3tmqwa1h,
}, {
@@ -3985,6 +4107,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "bananapi,s070wv20-ct16",
.data = &bananapi_s070wv20_ct16,
}, {
+ .compatible = "boe,ev121wxm-n10-1850",
+ .data = &boe_ev121wxm_n10_1850,
+ }, {
.compatible = "boe,hv070wsa-100",
.data = &boe_hv070wsa
}, {
@@ -4099,6 +4224,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "innolux,at070tn92",
.data = &innolux_at070tn92,
}, {
+ .compatible = "innolux,g070ace-l01",
+ .data = &innolux_g070ace_l01,
+ }, {
.compatible = "innolux,g070y2-l01",
.data = &innolux_g070y2_l01,
}, {
@@ -4219,6 +4347,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "qishenglong,gopher2b-lcd",
.data = &qishenglong_gopher2b_lcd,
}, {
+ .compatible = "rocktech,rk043fn48h",
+ .data = &rocktech_rk043fn48h,
+ }, {
.compatible = "rocktech,rk070er9427",
.data = &rocktech_rk070er9427,
}, {
diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
index 6747ca237ced..3aa31f3d6157 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -28,6 +28,7 @@
/* Manufacturer specific Commands send via DSI */
#define ST7703_CMD_ALL_PIXEL_OFF 0x22
#define ST7703_CMD_ALL_PIXEL_ON 0x23
+#define ST7703_CMD_SETAPID 0xB1
#define ST7703_CMD_SETDISP 0xB2
#define ST7703_CMD_SETRGBIF 0xB3
#define ST7703_CMD_SETCYC 0xB4
@@ -41,12 +42,15 @@
#define ST7703_CMD_UNKNOWN_BF 0xBF
#define ST7703_CMD_SETSCR 0xC0
#define ST7703_CMD_SETPOWER 0xC1
+#define ST7703_CMD_SETECO 0xC6
+#define ST7703_CMD_SETIO 0xC7
+#define ST7703_CMD_SETCABC 0xC8
#define ST7703_CMD_SETPANEL 0xCC
-#define ST7703_CMD_UNKNOWN_C6 0xC6
#define ST7703_CMD_SETGAMMA 0xE0
#define ST7703_CMD_SETEQ 0xE3
#define ST7703_CMD_SETGIP1 0xE9
#define ST7703_CMD_SETGIP2 0xEA
+#define ST7703_CMD_UNKNOWN_EF 0xEF
struct st7703 {
struct device *dev;
@@ -249,8 +253,7 @@ static int xbd599_init_sequence(struct st7703 *ctx)
* ESD_DET_TIME_SEL = 0 frames
*/);
- /* Undocumented command. */
- mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_C6, 0x01, 0x00, 0xFF, 0xFF, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x01, 0x00, 0xFF, 0xFF, 0x00);
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER,
0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
@@ -338,6 +341,98 @@ static const struct st7703_panel_desc xbd599_desc = {
.init_sequence = xbd599_init_sequence,
};
+static int rg353v2_init_sequence(struct st7703 *ctx)
+{
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+
+ /*
+ * Init sequence was supplied by the panel vendor.
+ */
+
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00,
+ 0xda, 0x80);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x00, 0x13, 0x70);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
+ 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x0a, 0x0a);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x92, 0x92);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22,
+ 0xf0, 0x63);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05,
+ 0xf9, 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a,
+ 0x00, 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x47);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
+ 0x00, 0x00, 0x12, 0x50, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x53, 0xc0, 0x32,
+ 0x32, 0x77, 0xe1, 0xdd, 0xdd, 0x77, 0x77, 0x33,
+ 0x33);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff,
+ 0x00, 0xff);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00,
+ 0x00, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e,
+ 0x02);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0d,
+ 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 0x0d,
+ 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a, 0x00, 0x07,
+ 0x0d, 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c,
+ 0x0d, 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
+ 0xc0, 0x10);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x02, 0x00,
+ 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x80,
+ 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
+ 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35,
+ 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02,
+ 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x81, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x80, 0x88, 0xba, 0x06, 0x42,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00,
+ 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00);
+ mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01);
+
+ return 0;
+}
+
+static const struct drm_display_mode rg353v2_mode = {
+ .hdisplay = 640,
+ .hsync_start = 640 + 40,
+ .hsync_end = 640 + 40 + 2,
+ .htotal = 640 + 40 + 2 + 80,
+ .vdisplay = 480,
+ .vsync_start = 480 + 18,
+ .vsync_end = 480 + 18 + 2,
+ .vtotal = 480 + 18 + 2 + 28,
+ .clock = 24150,
+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+ .width_mm = 70,
+ .height_mm = 57,
+};
+
+static const struct st7703_panel_desc rg353v2_desc = {
+ .mode = &rg353v2_mode,
+ .lanes = 4,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM,
+ .format = MIPI_DSI_FMT_RGB888,
+ .init_sequence = rg353v2_init_sequence,
+};
+
static int st7703_enable(struct drm_panel *panel)
{
struct st7703 *ctx = panel_to_st7703(panel);
@@ -598,6 +693,7 @@ static void st7703_remove(struct mipi_dsi_device *dsi)
}
static const struct of_device_id st7703_of_match[] = {
+ { .compatible = "anbernic,rg353v-panel-v2", .data = &rg353v2_desc },
{ .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc },
{ .compatible = "xingbangda,xbd599", .data = &xbd599_desc },
{ /* sentinel */ }
diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig
index e19d77d58810..fe498c8af1bb 100644
--- a/drivers/gpu/drm/radeon/Kconfig
+++ b/drivers/gpu/drm/radeon/Kconfig
@@ -11,6 +11,7 @@ config DRM_RADEON
select DRM_SUBALLOC_HELPER
select DRM_TTM
select DRM_TTM_HELPER
+ select FB_IO_HELPERS if DRM_FBDEV_EMULATION
select SND_HDA_COMPONENT if SND_HDA_CORE
select POWER_SUPPLY
select HWMON
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
index 8ef25ab305ae..b8f4dac68d85 100644
--- a/drivers/gpu/drm/radeon/ci_dpm.c
+++ b/drivers/gpu/drm/radeon/ci_dpm.c
@@ -5517,6 +5517,7 @@ static int ci_parse_power_table(struct radeon_device *rdev)
u8 frev, crev;
u8 *power_state_offset;
struct ci_ps *ps;
+ int ret;
if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset))
@@ -5546,11 +5547,15 @@ static int ci_parse_power_table(struct radeon_device *rdev)
non_clock_array_index = power_state->v2.nonClockInfoIndex;
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
&non_clock_info_array->nonClockInfo[non_clock_array_index];
- if (!rdev->pm.power_state[i].clock_info)
- return -EINVAL;
+ if (!rdev->pm.power_state[i].clock_info) {
+ ret = -EINVAL;
+ goto err_free_ps;
+ }
ps = kzalloc(sizeof(struct ci_ps), GFP_KERNEL);
- if (ps == NULL)
- return -ENOMEM;
+ if (ps == NULL) {
+ ret = -ENOMEM;
+ goto err_free_ps;
+ }
rdev->pm.dpm.ps[i].ps_priv = ps;
ci_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
non_clock_info,
@@ -5590,6 +5595,12 @@ static int ci_parse_power_table(struct radeon_device *rdev)
}
return 0;
+
+err_free_ps:
+ for (i = 0; i < rdev->pm.dpm.num_ps; i++)
+ kfree(rdev->pm.dpm.ps[i].ps_priv);
+ kfree(rdev->pm.dpm.ps);
+ return ret;
}
static int ci_get_vbios_boot_values(struct radeon_device *rdev,
@@ -5678,25 +5689,26 @@ int ci_dpm_init(struct radeon_device *rdev)
ret = ci_get_vbios_boot_values(rdev, &pi->vbios_boot_state);
if (ret) {
- ci_dpm_fini(rdev);
+ kfree(rdev->pm.dpm.priv);
return ret;
}
ret = r600_get_platform_caps(rdev);
if (ret) {
- ci_dpm_fini(rdev);
+ kfree(rdev->pm.dpm.priv);
return ret;
}
ret = r600_parse_extended_power_table(rdev);
if (ret) {
- ci_dpm_fini(rdev);
+ kfree(rdev->pm.dpm.priv);
return ret;
}
ret = ci_parse_power_table(rdev);
if (ret) {
- ci_dpm_fini(rdev);
+ kfree(rdev->pm.dpm.priv);
+ r600_free_extended_power_table(rdev);
return ret;
}
diff --git a/drivers/gpu/drm/radeon/cypress_dpm.c b/drivers/gpu/drm/radeon/cypress_dpm.c
index fdddbbaecbb7..72a0768df00f 100644
--- a/drivers/gpu/drm/radeon/cypress_dpm.c
+++ b/drivers/gpu/drm/radeon/cypress_dpm.c
@@ -557,8 +557,12 @@ static int cypress_populate_mclk_value(struct radeon_device *rdev,
ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
u32 reference_clock = rdev->clock.mpll.reference_freq;
u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div);
- u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
- u32 clk_v = ss.percentage *
+ u32 clk_s, clk_v;
+
+ if (!decoded_ref)
+ return -EINVAL;
+ clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
+ clk_v = ss.percentage *
(0x4000 * dividers.whole_fb_div + 0x800 * dividers.frac_fb_div) / (clk_s * 625);
mpll_ss1 &= ~CLKV_MASK;
diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c
index 672d2239293e..3e1c1a392fb7 100644
--- a/drivers/gpu/drm/radeon/ni_dpm.c
+++ b/drivers/gpu/drm/radeon/ni_dpm.c
@@ -2241,8 +2241,12 @@ static int ni_populate_mclk_value(struct radeon_device *rdev,
ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
u32 reference_clock = rdev->clock.mpll.reference_freq;
u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div);
- u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
- u32 clk_v = ss.percentage *
+ u32 clk_s, clk_v;
+
+ if (!decoded_ref)
+ return -EINVAL;
+ clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
+ clk_v = ss.percentage *
(0x4000 * dividers.whole_fb_div + 0x800 * dividers.frac_fb_div) / (clk_s * 625);
mpll_ss1 &= ~CLKV_MASK;
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index d4f09ecc3d22..affa9e0309b2 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -2929,7 +2929,7 @@ static void r100_set_safe_registers(struct radeon_device *rdev)
#if defined(CONFIG_DEBUG_FS)
static int r100_debugfs_rbbm_info_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
uint32_t reg, value;
unsigned i;
@@ -2948,7 +2948,7 @@ static int r100_debugfs_rbbm_info_show(struct seq_file *m, void *unused)
static int r100_debugfs_cp_ring_info_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
uint32_t rdp, wdp;
unsigned count, i, j;
@@ -2974,7 +2974,7 @@ static int r100_debugfs_cp_ring_info_show(struct seq_file *m, void *unused)
static int r100_debugfs_cp_csq_fifo_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
uint32_t csq_stat, csq2_stat, tmp;
unsigned r_rptr, r_wptr, ib1_rptr, ib1_wptr, ib2_rptr, ib2_wptr;
unsigned i;
@@ -3022,7 +3022,7 @@ static int r100_debugfs_cp_csq_fifo_show(struct seq_file *m, void *unused)
static int r100_debugfs_mc_info_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
uint32_t tmp;
tmp = RREG32(RADEON_CONFIG_MEMSIZE);
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 7b0cfeaddcec..9c1a92fa2af6 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -589,7 +589,7 @@ int rv370_get_pcie_lanes(struct radeon_device *rdev)
#if defined(CONFIG_DEBUG_FS)
static int rv370_debugfs_pcie_gart_info_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
uint32_t tmp;
tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
index 7e6320e8c6a0..eae8a6389f5e 100644
--- a/drivers/gpu/drm/radeon/r420.c
+++ b/drivers/gpu/drm/radeon/r420.c
@@ -474,7 +474,7 @@ int r420_init(struct radeon_device *rdev)
#if defined(CONFIG_DEBUG_FS)
static int r420_debugfs_pipes_info_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
uint32_t tmp;
tmp = RREG32(R400_GB_PIPE_SELECT);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index dd78fc499402..382795a8b3c0 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -4345,7 +4345,7 @@ restart_ih:
static int r600_debugfs_mc_info_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
DREG32_SYS(m, rdev, R_000E50_SRBM_STATUS);
DREG32_SYS(m, rdev, VM_L2_STATUS);
diff --git a/drivers/gpu/drm/radeon/radeon_acpi.h b/drivers/gpu/drm/radeon/radeon_acpi.h
index 35202a453e66..974fbb4ce2c2 100644
--- a/drivers/gpu/drm/radeon/radeon_acpi.h
+++ b/drivers/gpu/drm/radeon/radeon_acpi.h
@@ -453,4 +453,13 @@ struct acpi_bus_event;
* BYTE - number of active lanes
*/
+#if defined(CONFIG_VGA_SWITCHEROO)
+void radeon_register_atpx_handler(void);
+void radeon_unregister_atpx_handler(void);
+bool radeon_has_atpx_dgpu_power_cntl(void);
+bool radeon_is_atpx_hybrid(void);
+bool radeon_has_atpx(void);
+bool radeon_atpx_dgpu_req_power_for_displays(void);
+#endif
+
#endif
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index 6f93f54bf651..d0b450a06506 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -147,7 +147,7 @@ static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mas
}
/**
- * radeon_atpx_validate_functions - validate ATPX functions
+ * radeon_atpx_validate() - validate ATPX functions
*
* @atpx: radeon atpx struct
*
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 46a27ebf4588..a6700d7278bf 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -270,7 +270,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
{
struct drm_radeon_cs *cs = data;
uint64_t *chunk_array_ptr;
- unsigned size, i;
+ u64 size;
+ unsigned i;
u32 ring = RADEON_CS_RING_GFX;
s32 priority = 0;
diff --git a/drivers/gpu/drm/radeon/radeon_fbdev.c b/drivers/gpu/drm/radeon/radeon_fbdev.c
index 8f6c3aef0962..ab9c1abbac97 100644
--- a/drivers/gpu/drm/radeon/radeon_fbdev.c
+++ b/drivers/gpu/drm/radeon/radeon_fbdev.c
@@ -24,6 +24,7 @@
* David Airlie
*/
+#include <linux/fb.h>
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/vga_switcheroo.h>
@@ -190,14 +191,10 @@ static void radeon_fbdev_fb_destroy(struct fb_info *info)
static const struct fb_ops radeon_fbdev_fb_ops = {
.owner = THIS_MODULE,
- DRM_FB_HELPER_DEFAULT_OPS,
.fb_open = radeon_fbdev_fb_open,
.fb_release = radeon_fbdev_fb_release,
- .fb_read = drm_fb_helper_cfb_read,
- .fb_write = drm_fb_helper_cfb_write,
- .fb_fillrect = drm_fb_helper_cfb_fillrect,
- .fb_copyarea = drm_fb_helper_cfb_copyarea,
- .fb_imageblit = drm_fb_helper_cfb_imageblit,
+ FB_DEFAULT_IO_OPS,
+ DRM_FB_HELPER_DEFAULT_OPS,
.fb_destroy = radeon_fbdev_fb_destroy,
};
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index 73e3117420bf..2749dde5838f 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -955,7 +955,7 @@ void radeon_fence_driver_force_completion(struct radeon_device *rdev, int ring)
#if defined(CONFIG_DEBUG_FS)
static int radeon_debugfs_fence_info_show(struct seq_file *m, void *data)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
int i, j;
for (i = 0; i < RADEON_NUM_RINGS; ++i) {
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index d3f5ddbc1704..d0119c5f7eb3 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -877,7 +877,7 @@ int radeon_mode_dumb_create(struct drm_file *file_priv,
#if defined(CONFIG_DEBUG_FS)
static int radeon_debugfs_gem_info_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
struct radeon_bo *rbo;
unsigned i = 0;
diff --git a/drivers/gpu/drm/radeon/radeon_ib.c b/drivers/gpu/drm/radeon/radeon_ib.c
index 6a45a72488f9..fb9ecf5dbe2b 100644
--- a/drivers/gpu/drm/radeon/radeon_ib.c
+++ b/drivers/gpu/drm/radeon/radeon_ib.c
@@ -292,7 +292,7 @@ int radeon_ib_ring_tests(struct radeon_device *rdev)
static int radeon_debugfs_sa_info_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
radeon_sa_bo_dump_debug_info(&rdev->ring_tmp_bo, m);
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index cbc554928bcc..b73fd9ab0252 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -1916,7 +1916,7 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work)
static int radeon_debugfs_pm_info_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
struct drm_device *ddev = rdev->ddev;
if ((rdev->flags & RADEON_IS_PX) &&
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 7e207276df37..e6534fa9f1fb 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -464,7 +464,7 @@ void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring)
static int radeon_debugfs_ring_info_show(struct seq_file *m, void *unused)
{
- struct radeon_ring *ring = (struct radeon_ring *) m->private;
+ struct radeon_ring *ring = m->private;
struct radeon_device *rdev = ring->rdev;
uint32_t rptr, wptr, rptr_next;
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 3a9db030f98f..4eb83ccc4906 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -36,7 +36,6 @@
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/swap.h>
-#include <linux/swiotlb.h>
#include <drm/drm_device.h>
#include <drm/drm_file.h>
@@ -780,7 +779,7 @@ void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size)
static int radeon_ttm_page_pool_show(struct seq_file *m, void *data)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
return ttm_pool_debugfs(&rdev->mman.bdev.pool, m);
}
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c
index 6383f7a34bd8..922a29e58880 100644
--- a/drivers/gpu/drm/radeon/rs400.c
+++ b/drivers/gpu/drm/radeon/rs400.c
@@ -307,7 +307,7 @@ void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
#if defined(CONFIG_DEBUG_FS)
static int rs400_debugfs_gart_info_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
uint32_t tmp;
tmp = RREG32(RADEON_HOST_PATH_CNTL);
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c
index 63fb06e8e2d7..76260fdfbaa7 100644
--- a/drivers/gpu/drm/radeon/rv515.c
+++ b/drivers/gpu/drm/radeon/rv515.c
@@ -221,7 +221,7 @@ void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
#if defined(CONFIG_DEBUG_FS)
static int rv515_debugfs_pipes_info_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
uint32_t tmp;
tmp = RREG32(GB_PIPE_SELECT);
@@ -237,7 +237,7 @@ static int rv515_debugfs_pipes_info_show(struct seq_file *m, void *unused)
static int rv515_debugfs_ga_info_show(struct seq_file *m, void *unused)
{
- struct radeon_device *rdev = (struct radeon_device *)m->private;
+ struct radeon_device *rdev = m->private;
uint32_t tmp;
tmp = RREG32(0x2140);
diff --git a/drivers/gpu/drm/radeon/rv740_dpm.c b/drivers/gpu/drm/radeon/rv740_dpm.c
index d57a3e1df8d6..4464fd21a302 100644
--- a/drivers/gpu/drm/radeon/rv740_dpm.c
+++ b/drivers/gpu/drm/radeon/rv740_dpm.c
@@ -249,8 +249,12 @@ int rv740_populate_mclk_value(struct radeon_device *rdev,
ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
u32 reference_clock = rdev->clock.mpll.reference_freq;
u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div);
- u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
- u32 clk_v = 0x40000 * ss.percentage *
+ u32 clk_s, clk_v;
+
+ if (!decoded_ref)
+ return -EINVAL;
+ clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
+ clk_v = 0x40000 * ss.percentage *
(dividers.whole_fb_div + (dividers.frac_fb_div / 8)) / (clk_s * 10000);
mpll_ss1 &= ~CLKV_MASK;
diff --git a/drivers/gpu/drm/renesas/Kconfig b/drivers/gpu/drm/renesas/Kconfig
new file mode 100644
index 000000000000..3777dad17f81
--- /dev/null
+++ b/drivers/gpu/drm/renesas/Kconfig
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+source "drivers/gpu/drm/renesas/rcar-du/Kconfig"
+source "drivers/gpu/drm/renesas/shmobile/Kconfig"
diff --git a/drivers/gpu/drm/renesas/Makefile b/drivers/gpu/drm/renesas/Makefile
new file mode 100644
index 000000000000..ec0e89e7a592
--- /dev/null
+++ b/drivers/gpu/drm/renesas/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += rcar-du/
+obj-$(CONFIG_DRM_SHMOBILE) += shmobile/
diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/renesas/rcar-du/Kconfig
index 53c356aed5d5..53c356aed5d5 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/renesas/rcar-du/Kconfig
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/renesas/rcar-du/Makefile
index b8f2c82651d9..b8f2c82651d9 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/renesas/rcar-du/Makefile
diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c b/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c
index e2a67dda4658..e2a67dda4658 100644
--- a/drivers/gpu/drm/rcar-du/rcar_cmm.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c
diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h b/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.h
index 628072acc98b..628072acc98b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_cmm.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.h
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
index d6d29be6b4f4..7e175dbfd892 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
@@ -223,20 +223,6 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
* DU channels that have a display PLL can't use the internal
* system clock, and have no internal clock divider.
*/
-
- /*
- * The H3 ES1.x exhibits dot clock duty cycle stability issues.
- * We can work around them by configuring the DPLL to twice the
- * desired frequency, coupled with a /2 post-divider. Restrict
- * the workaround to H3 ES1.x as ES2.0 and all other SoCs have
- * no post-divider when a display PLL is present (as shown by
- * the workaround breaking HDMI output on M3-W during testing).
- */
- if (rcdu->info->quirks & RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY) {
- target *= 2;
- div = 1;
- }
-
extclk = clk_get_rate(rcrtc->extclock);
rcar_du_dpll_divider(rcrtc, &dpll, extclk, target);
@@ -245,30 +231,13 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
| DPLLCR_N(dpll.n) | DPLLCR_M(dpll.m)
| DPLLCR_STBY;
- if (rcrtc->index == 1) {
+ if (rcrtc->index == 1)
dpllcr |= DPLLCR_PLCS1
| DPLLCR_INCS_DOTCLKIN1;
- } else {
- dpllcr |= DPLLCR_PLCS0_PLL
+ else
+ dpllcr |= DPLLCR_PLCS0
| DPLLCR_INCS_DOTCLKIN0;
- /*
- * On ES2.x we have a single mux controlled via bit 21,
- * which selects between DCLKIN source (bit 21 = 0) and
- * a PLL source (bit 21 = 1), where the PLL is always
- * PLL1.
- *
- * On ES1.x we have an additional mux, controlled
- * via bit 20, for choosing between PLL0 (bit 20 = 0)
- * and PLL1 (bit 20 = 1). We always want to use PLL1,
- * so on ES1.x, in addition to setting bit 21, we need
- * to set the bit 20.
- */
-
- if (rcdu->info->quirks & RCAR_DU_QUIRK_H3_ES1_PLL)
- dpllcr |= DPLLCR_PLCS0_H3ES1X_PLL1;
- }
-
rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr);
escr = ESCR_DCLKSEL_DCLKIN | div;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h
index d0f38a8b3561..d0f38a8b3561 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.h
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
index b9a94c5260e9..1ffde19cb87f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
@@ -16,7 +16,6 @@
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/slab.h>
-#include <linux/sys_soc.h>
#include <linux/wait.h>
#include <drm/drm_atomic_helper.h>
@@ -387,43 +386,6 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
.dpll_mask = BIT(2) | BIT(1),
};
-static const struct rcar_du_device_info rcar_du_r8a7795_es1_info = {
- .gen = 3,
- .features = RCAR_DU_FEATURE_CRTC_IRQ
- | RCAR_DU_FEATURE_CRTC_CLOCK
- | RCAR_DU_FEATURE_VSP1_SOURCE
- | RCAR_DU_FEATURE_INTERLACED
- | RCAR_DU_FEATURE_TVM_SYNC,
- .quirks = RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY
- | RCAR_DU_QUIRK_H3_ES1_PLL,
- .channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
- .routes = {
- /*
- * R8A7795 has one RGB output, two HDMI outputs and one
- * LVDS output.
- */
- [RCAR_DU_OUTPUT_DPAD0] = {
- .possible_crtcs = BIT(3),
- .port = 0,
- },
- [RCAR_DU_OUTPUT_HDMI0] = {
- .possible_crtcs = BIT(1),
- .port = 1,
- },
- [RCAR_DU_OUTPUT_HDMI1] = {
- .possible_crtcs = BIT(2),
- .port = 2,
- },
- [RCAR_DU_OUTPUT_LVDS0] = {
- .possible_crtcs = BIT(0),
- .port = 3,
- },
- },
- .num_lvds = 1,
- .num_rpf = 5,
- .dpll_mask = BIT(2) | BIT(1),
-};
-
static const struct rcar_du_device_info rcar_du_r8a7796_info = {
.gen = 3,
.features = RCAR_DU_FEATURE_CRTC_IRQ
@@ -614,11 +576,6 @@ static const struct of_device_id rcar_du_of_table[] = {
MODULE_DEVICE_TABLE(of, rcar_du_of_table);
-static const struct soc_device_attribute rcar_du_soc_table[] = {
- { .soc_id = "r8a7795", .revision = "ES1.*", .data = &rcar_du_r8a7795_es1_info },
- { /* sentinel */ }
-};
-
const char *rcar_du_output_name(enum rcar_du_output output)
{
static const char * const names[] = {
@@ -707,7 +664,6 @@ static void rcar_du_shutdown(struct platform_device *pdev)
static int rcar_du_probe(struct platform_device *pdev)
{
- const struct soc_device_attribute *soc_attr;
struct rcar_du_device *rcdu;
unsigned int mask;
int ret;
@@ -725,10 +681,6 @@ static int rcar_du_probe(struct platform_device *pdev)
rcdu->info = of_device_get_match_data(rcdu->dev);
- soc_attr = soc_device_match(rcar_du_soc_table);
- if (soc_attr)
- rcdu->info = soc_attr->data;
-
platform_set_drvdata(pdev, rcdu);
/* I/O resources */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.h
index acc3673fefe1..5cfa2bb7ad93 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.h
@@ -34,8 +34,6 @@ struct rcar_du_device;
#define RCAR_DU_FEATURE_NO_BLENDING BIT(5) /* PnMR.SPIM does not have ALP nor EOR bits */
#define RCAR_DU_QUIRK_ALIGN_128B BIT(0) /* Align pitches to 128 bytes */
-#define RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY BIT(1) /* H3 ES1 has pclk stability issue */
-#define RCAR_DU_QUIRK_H3_ES1_PLL BIT(2) /* H3 ES1 PLL setup differs from non-ES1 */
enum rcar_du_output {
RCAR_DU_OUTPUT_DPAD0,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_encoder.c
index 7ecec7b04a8d..7ecec7b04a8d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_encoder.c
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_encoder.h
index e5ec8fbb3979..e5ec8fbb3979 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_encoder.h
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_group.c
index 2ccd2581f544..2ccd2581f544 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_group.c
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_group.h
index 55649ad86a10..55649ad86a10 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_group.h
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
index adfb36b0e815..adfb36b0e815 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.h
index f31afeeee05a..f31afeeee05a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.h
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.c
index d759e0192181..d759e0192181 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.c
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.h
index f9893d7d6dfc..f9893d7d6dfc 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.h
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_regs.h
index 6c750fab6ebb..391de6661d8b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_regs.h
@@ -283,8 +283,7 @@
#define DPLLCR 0x20044
#define DPLLCR_CODE (0x95 << 24)
#define DPLLCR_PLCS1 (1 << 23)
-#define DPLLCR_PLCS0_PLL (1 << 21)
-#define DPLLCR_PLCS0_H3ES1X_PLL1 (1 << 20)
+#define DPLLCR_PLCS0 (1 << 21)
#define DPLLCR_CLKE (1 << 18)
#define DPLLCR_FDPLL(n) ((n) << 12)
#define DPLLCR_N(n) ((n) << 5)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.c
index 45c05d0ffc70..45c05d0ffc70 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.c
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.h
index 67630f0b6599..67630f0b6599 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_vsp.h
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_writeback.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
index 8cd37d7b8ae2..8cd37d7b8ae2 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_writeback.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.c
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_writeback.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.h
index a71c9c08cafa..a71c9c08cafa 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_writeback.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_writeback.h
diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c
index 18ed14911b98..18ed14911b98 100644
--- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c
index ca215b588fd7..ca215b588fd7 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.h b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.h
index 887c63500000..887c63500000 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.h
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds_regs.h
index ab0406a27d33..ab0406a27d33 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds_regs.h
diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
index e10e4d4b89a2..e10e4d4b89a2 100644
--- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.h b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.h
index 528a196e6edd..528a196e6edd 100644
--- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.h
diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi_regs.h
index f8114d11f2d1..f8114d11f2d1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi_regs.h
diff --git a/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi.c
index aa95b85a2964..aa95b85a2964 100644
--- a/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi.c
diff --git a/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h b/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi_regs.h
index 1dbc16ec64a4..1dbc16ec64a4 100644
--- a/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h
+++ b/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi_regs.h
diff --git a/drivers/gpu/drm/shmobile/Kconfig b/drivers/gpu/drm/renesas/shmobile/Kconfig
index 4ec5dc74a6b0..ad14112999ad 100644
--- a/drivers/gpu/drm/shmobile/Kconfig
+++ b/drivers/gpu/drm/renesas/shmobile/Kconfig
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
config DRM_SHMOBILE
tristate "DRM Support for SH Mobile"
- depends on DRM && ARM
- depends on ARCH_SHMOBILE || COMPILE_TEST
+ depends on DRM
+ depends on ARCH_RENESAS || ARCH_SHMOBILE || COMPILE_TEST
select BACKLIGHT_CLASS_DEVICE
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
diff --git a/drivers/gpu/drm/shmobile/Makefile b/drivers/gpu/drm/renesas/shmobile/Makefile
index 861edafed856..861edafed856 100644
--- a/drivers/gpu/drm/shmobile/Makefile
+++ b/drivers/gpu/drm/renesas/shmobile/Makefile
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_backlight.c b/drivers/gpu/drm/renesas/shmobile/shmob_drm_backlight.c
index 794573badfe8..794573badfe8 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_backlight.c
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_backlight.c
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_backlight.h b/drivers/gpu/drm/renesas/shmobile/shmob_drm_backlight.h
index d9abb7a60be5..d9abb7a60be5 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_backlight.h
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_backlight.h
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c
index d354ab3077ce..11dd2bc803e7 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c
@@ -18,6 +18,7 @@
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_modeset_helper.h>
#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_plane_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_vblank.h>
@@ -232,6 +233,7 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
value = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
break;
case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
default:
value = LDDDSR_LS;
break;
@@ -355,8 +357,8 @@ static int shmob_drm_crtc_mode_set(struct drm_crtc *crtc,
format = shmob_drm_format_info(crtc->primary->fb->format->format);
if (format == NULL) {
- dev_dbg(sdev->dev, "mode_set: unsupported format %08x\n",
- crtc->primary->fb->format->format);
+ dev_dbg(sdev->dev, "mode_set: unsupported format %p4cc\n",
+ &crtc->primary->fb->format->format);
return -EINVAL;
}
@@ -477,16 +479,41 @@ static const struct drm_crtc_funcs crtc_funcs = {
.disable_vblank = shmob_drm_disable_vblank,
};
+static const uint32_t modeset_formats[] = {
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_XRGB8888,
+};
+
+static const struct drm_plane_funcs primary_plane_funcs = {
+ DRM_PLANE_NON_ATOMIC_FUNCS,
+};
+
int shmob_drm_crtc_create(struct shmob_drm_device *sdev)
{
struct drm_crtc *crtc = &sdev->crtc.crtc;
+ struct drm_plane *primary;
int ret;
sdev->crtc.dpms = DRM_MODE_DPMS_OFF;
- ret = drm_crtc_init(sdev->ddev, crtc, &crtc_funcs);
- if (ret < 0)
+ primary = __drm_universal_plane_alloc(sdev->ddev, sizeof(*primary), 0,
+ 0, &primary_plane_funcs,
+ modeset_formats,
+ ARRAY_SIZE(modeset_formats),
+ NULL, DRM_PLANE_TYPE_PRIMARY,
+ NULL);
+ if (IS_ERR(primary))
+ return PTR_ERR(primary);
+
+ ret = drm_crtc_init_with_planes(sdev->ddev, crtc, primary, NULL,
+ &crtc_funcs, NULL);
+ if (ret < 0) {
+ drm_plane_cleanup(primary);
+ kfree(primary);
return ret;
+ }
drm_crtc_helper_add(crtc, &crtc_helper_funcs);
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h b/drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.h
index 21718843f46d..21718843f46d 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.h
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c
index faacfee24763..30493ce87419 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <drm/drm_drv.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_module.h>
#include <drm/drm_probe_helper.h>
@@ -271,6 +272,8 @@ static int shmob_drm_probe(struct platform_device *pdev)
if (ret < 0)
goto err_irq_uninstall;
+ drm_fbdev_generic_setup(ddev, 16);
+
return 0;
err_irq_uninstall:
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.h b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.h
index 4964ddd5ab74..4964ddd5ab74 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_drv.h
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.h
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_kms.c b/drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.c
index 60a2c8d8a0d9..99381cc0abf3 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_kms.c
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.c
@@ -40,6 +40,11 @@ static const struct shmob_drm_format_info shmob_drm_format_infos[] = {
.yuv = false,
.lddfr = LDDFR_PKF_ARGB32,
}, {
+ .fourcc = DRM_FORMAT_XRGB8888,
+ .bpp = 32,
+ .yuv = false,
+ .lddfr = LDDFR_PKF_ARGB32,
+ }, {
.fourcc = DRM_FORMAT_NV12,
.bpp = 12,
.yuv = true,
@@ -96,8 +101,8 @@ shmob_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv,
format = shmob_drm_format_info(mode_cmd->pixel_format);
if (format == NULL) {
- dev_dbg(dev->dev, "unsupported pixel format %08x\n",
- mode_cmd->pixel_format);
+ dev_dbg(dev->dev, "unsupported pixel format %p4cc\n",
+ &mode_cmd->pixel_format);
return ERR_PTR(-EINVAL);
}
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_kms.h b/drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.h
index 0347b1fd2338..0347b1fd2338 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_kms.h
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.h
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.c
index 604ae23825da..850986cee848 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.c
@@ -80,6 +80,7 @@ static void __shmob_drm_plane_setup(struct shmob_drm_plane *splane,
format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB;
break;
case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
default:
format |= LDBBSIFR_SWPL;
break;
@@ -95,6 +96,9 @@ static void __shmob_drm_plane_setup(struct shmob_drm_plane *splane,
case DRM_FORMAT_ARGB8888:
format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
break;
+ case DRM_FORMAT_XRGB8888:
+ format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
+ break;
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV21:
format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420;
@@ -231,6 +235,7 @@ static const uint32_t formats[] = {
DRM_FORMAT_RGB565,
DRM_FORMAT_RGB888,
DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_XRGB8888,
DRM_FORMAT_NV12,
DRM_FORMAT_NV21,
DRM_FORMAT_NV16,
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.h b/drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.h
index e72b21a4288f..e72b21a4288f 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_plane.h
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.h
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_regs.h b/drivers/gpu/drm/renesas/shmobile/shmob_drm_regs.h
index 058533685c4c..058533685c4c 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_regs.h
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_regs.h
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 8526dda91931..b6afe3786b74 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -273,10 +273,9 @@ static int cdn_dp_connector_get_modes(struct drm_connector *connector)
edid->width_cm, edid->height_cm);
dp->sink_has_audio = drm_detect_monitor_audio(edid);
+
+ drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
- if (ret)
- drm_connector_update_edid_property(connector,
- edid);
}
mutex_unlock(&dp->lock);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 6e0788d14c10..d97f2edc646b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -140,7 +140,7 @@ static int rockchip_drm_bind(struct device *dev)
int ret;
/* Remove existing drivers that may own the framebuffer memory. */
- ret = drm_aperture_remove_framebuffers(false, &rockchip_drm_driver);
+ ret = drm_aperture_remove_framebuffers(&rockchip_drm_driver);
if (ret) {
DRM_DEV_ERROR(dev,
"Failed to remove existing framebuffers - %d.\n",
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index d8f5e064a1ba..a530ecc4d207 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -714,13 +714,13 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
if (crtc->state->self_refresh_active)
rockchip_drm_set_win_enabled(crtc, false);
+ if (crtc->state->self_refresh_active)
+ goto out;
+
mutex_lock(&vop->vop_lock);
drm_crtc_vblank_off(crtc);
- if (crtc->state->self_refresh_active)
- goto out;
-
/*
* Vop standby will take effect at end of current frame,
* if dsp hold valid irq happen, it means standby complete.
@@ -754,9 +754,9 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
vop_core_clks_disable(vop);
pm_runtime_put(vop->dev);
-out:
mutex_unlock(&vop->vop_lock);
+out:
if (crtc->state->event && !crtc->state->active) {
spin_lock_irq(&crtc->dev->event_lock);
drm_crtc_send_vblank_event(crtc, crtc->state->event);
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index e0a8890a62e2..b2bbc8a68b30 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -72,7 +72,7 @@ int drm_sched_entity_init(struct drm_sched_entity *entity,
entity->num_sched_list = num_sched_list;
entity->priority = priority;
entity->sched_list = num_sched_list > 1 ? sched_list : NULL;
- entity->last_scheduled = NULL;
+ RCU_INIT_POINTER(entity->last_scheduled, NULL);
RB_CLEAR_NODE(&entity->rb_tree_node);
if(num_sched_list)
@@ -140,11 +140,32 @@ bool drm_sched_entity_is_ready(struct drm_sched_entity *entity)
return true;
}
+/**
+ * drm_sched_entity_error - return error of last scheduled job
+ * @entity: scheduler entity to check
+ *
+ * Opportunistically return the error of the last scheduled job. Result can
+ * change any time when new jobs are pushed to the hw.
+ */
+int drm_sched_entity_error(struct drm_sched_entity *entity)
+{
+ struct dma_fence *fence;
+ int r;
+
+ rcu_read_lock();
+ fence = rcu_dereference(entity->last_scheduled);
+ r = fence ? fence->error : 0;
+ rcu_read_unlock();
+
+ return r;
+}
+EXPORT_SYMBOL(drm_sched_entity_error);
+
static void drm_sched_entity_kill_jobs_work(struct work_struct *wrk)
{
struct drm_sched_job *job = container_of(wrk, typeof(*job), work);
- drm_sched_fence_finished(job->s_fence);
+ drm_sched_fence_finished(job->s_fence, -ESRCH);
WARN_ON(job->s_fence->parent);
job->sched->ops->free_job(job);
}
@@ -191,12 +212,12 @@ static void drm_sched_entity_kill(struct drm_sched_entity *entity)
/* Make sure this entity is not used by the scheduler at the moment */
wait_for_completion(&entity->entity_idle);
- prev = dma_fence_get(entity->last_scheduled);
+ /* The entity is guaranteed to not be used by the scheduler */
+ prev = rcu_dereference_check(entity->last_scheduled, true);
+ dma_fence_get(prev);
while ((job = to_drm_sched_job(spsc_queue_pop(&entity->job_queue)))) {
struct drm_sched_fence *s_fence = job->s_fence;
- dma_fence_set_error(&s_fence->finished, -ESRCH);
-
dma_fence_get(&s_fence->finished);
if (!prev || dma_fence_add_callback(prev, &job->finish_cb,
drm_sched_entity_kill_jobs_cb))
@@ -280,8 +301,8 @@ void drm_sched_entity_fini(struct drm_sched_entity *entity)
entity->dependency = NULL;
}
- dma_fence_put(entity->last_scheduled);
- entity->last_scheduled = NULL;
+ dma_fence_put(rcu_dereference_check(entity->last_scheduled, true));
+ RCU_INIT_POINTER(entity->last_scheduled, NULL);
}
EXPORT_SYMBOL(drm_sched_entity_fini);
@@ -321,7 +342,7 @@ static void drm_sched_entity_wakeup(struct dma_fence *f,
container_of(cb, struct drm_sched_entity, cb);
drm_sched_entity_clear_dep(f, cb);
- drm_sched_wakeup(entity->rq->sched);
+ drm_sched_wakeup_if_can_queue(entity->rq->sched);
}
/**
@@ -363,7 +384,7 @@ static bool drm_sched_entity_add_dependency_cb(struct drm_sched_entity *entity)
}
s_fence = to_drm_sched_fence(fence);
- if (s_fence && s_fence->sched == sched &&
+ if (!fence->error && s_fence && s_fence->sched == sched &&
!test_bit(DRM_SCHED_FENCE_DONT_PIPELINE, &fence->flags)) {
/*
@@ -423,9 +444,9 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
if (entity->guilty && atomic_read(entity->guilty))
dma_fence_set_error(&sched_job->s_fence->finished, -ECANCELED);
- dma_fence_put(entity->last_scheduled);
-
- entity->last_scheduled = dma_fence_get(&sched_job->s_fence->finished);
+ dma_fence_put(rcu_dereference_check(entity->last_scheduled, true));
+ rcu_assign_pointer(entity->last_scheduled,
+ dma_fence_get(&sched_job->s_fence->finished));
/*
* If the queue is empty we allow drm_sched_entity_select_rq() to
@@ -448,6 +469,12 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
drm_sched_rq_update_fifo(entity, next->submit_ts);
}
+ /* Jobs and entities might have different lifecycles. Since we're
+ * removing the job from the entities queue, set the jobs entity pointer
+ * to NULL to prevent any future access of the entity through this job.
+ */
+ sched_job->entity = NULL;
+
return sched_job;
}
@@ -473,7 +500,7 @@ void drm_sched_entity_select_rq(struct drm_sched_entity *entity)
*/
smp_rmb();
- fence = entity->last_scheduled;
+ fence = rcu_dereference_check(entity->last_scheduled, true);
/* stay on the same engine if the previous job hasn't finished */
if (fence && !dma_fence_is_signaled(fence))
@@ -538,7 +565,7 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
drm_sched_rq_update_fifo(entity, submit_ts);
- drm_sched_wakeup(entity->rq->sched);
+ drm_sched_wakeup_if_can_queue(entity->rq->sched);
}
}
EXPORT_SYMBOL(drm_sched_entity_push_job);
diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c
index fe9c6468e440..ef120475e7c6 100644
--- a/drivers/gpu/drm/scheduler/sched_fence.c
+++ b/drivers/gpu/drm/scheduler/sched_fence.c
@@ -53,8 +53,10 @@ void drm_sched_fence_scheduled(struct drm_sched_fence *fence)
dma_fence_signal(&fence->scheduled);
}
-void drm_sched_fence_finished(struct drm_sched_fence *fence)
+void drm_sched_fence_finished(struct drm_sched_fence *fence, int result)
{
+ if (result)
+ dma_fence_set_error(&fence->finished, result);
dma_fence_signal(&fence->finished);
}
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index aea5a90ff98b..7b2bfc10c1a5 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -42,6 +42,10 @@
* the hardware.
*
* The jobs in a entity are always scheduled in the order that they were pushed.
+ *
+ * Note that once a job was taken from the entities queue and pushed to the
+ * hardware, i.e. the pending queue, the entity must not be referenced anymore
+ * through the jobs entity pointer.
*/
#include <linux/kthread.h>
@@ -258,7 +262,7 @@ drm_sched_rq_select_entity_fifo(struct drm_sched_rq *rq)
*
* Finish the job's fence and wake up the worker thread.
*/
-static void drm_sched_job_done(struct drm_sched_job *s_job)
+static void drm_sched_job_done(struct drm_sched_job *s_job, int result)
{
struct drm_sched_fence *s_fence = s_job->s_fence;
struct drm_gpu_scheduler *sched = s_fence->sched;
@@ -269,7 +273,7 @@ static void drm_sched_job_done(struct drm_sched_job *s_job)
trace_drm_sched_process_job(s_fence);
dma_fence_get(&s_fence->finished);
- drm_sched_fence_finished(s_fence);
+ drm_sched_fence_finished(s_fence, result);
dma_fence_put(&s_fence->finished);
wake_up_interruptible(&sched->wake_up_worker);
}
@@ -283,7 +287,7 @@ static void drm_sched_job_done_cb(struct dma_fence *f, struct dma_fence_cb *cb)
{
struct drm_sched_job *s_job = container_of(cb, struct drm_sched_job, cb);
- drm_sched_job_done(s_job);
+ drm_sched_job_done(s_job, f->error);
}
/**
@@ -534,12 +538,12 @@ void drm_sched_start(struct drm_gpu_scheduler *sched, bool full_recovery)
r = dma_fence_add_callback(fence, &s_job->cb,
drm_sched_job_done_cb);
if (r == -ENOENT)
- drm_sched_job_done(s_job);
+ drm_sched_job_done(s_job, fence->error);
else if (r)
DRM_DEV_ERROR(sched->dev, "fence add callback failed (%d)\n",
r);
} else
- drm_sched_job_done(s_job);
+ drm_sched_job_done(s_job, -ECANCELED);
}
if (full_recovery) {
@@ -844,27 +848,26 @@ void drm_sched_job_cleanup(struct drm_sched_job *job)
EXPORT_SYMBOL(drm_sched_job_cleanup);
/**
- * drm_sched_ready - is the scheduler ready
- *
+ * drm_sched_can_queue -- Can we queue more to the hardware?
* @sched: scheduler instance
*
* Return true if we can push more jobs to the hw, otherwise false.
*/
-static bool drm_sched_ready(struct drm_gpu_scheduler *sched)
+static bool drm_sched_can_queue(struct drm_gpu_scheduler *sched)
{
return atomic_read(&sched->hw_rq_count) <
sched->hw_submission_limit;
}
/**
- * drm_sched_wakeup - Wake up the scheduler when it is ready
- *
+ * drm_sched_wakeup_if_can_queue - Wake up the scheduler
* @sched: scheduler instance
*
+ * Wake up the scheduler if we can queue jobs.
*/
-void drm_sched_wakeup(struct drm_gpu_scheduler *sched)
+void drm_sched_wakeup_if_can_queue(struct drm_gpu_scheduler *sched)
{
- if (drm_sched_ready(sched))
+ if (drm_sched_can_queue(sched))
wake_up_interruptible(&sched->wake_up_worker);
}
@@ -881,7 +884,7 @@ drm_sched_select_entity(struct drm_gpu_scheduler *sched)
struct drm_sched_entity *entity;
int i;
- if (!drm_sched_ready(sched))
+ if (!drm_sched_can_queue(sched))
return NULL;
/* Kernel run queue has higher priority than normal run queue*/
@@ -1050,15 +1053,13 @@ static int drm_sched_main(void *param)
r = dma_fence_add_callback(fence, &sched_job->cb,
drm_sched_job_done_cb);
if (r == -ENOENT)
- drm_sched_job_done(sched_job);
+ drm_sched_job_done(sched_job, fence->error);
else if (r)
DRM_DEV_ERROR(sched->dev, "fence add callback failed (%d)\n",
r);
} else {
- if (IS_ERR(fence))
- dma_fence_set_error(&s_fence->finished, PTR_ERR(fence));
-
- drm_sched_job_done(sched_job);
+ drm_sched_job_done(sched_job, IS_ERR(fence) ?
+ PTR_ERR(fence) : 0);
}
wake_up(&sched->job_scheduled);
diff --git a/drivers/gpu/drm/solomon/ssd130x-i2c.c b/drivers/gpu/drm/solomon/ssd130x-i2c.c
index ddfa0bb5d9c9..b4eb2d64bf6e 100644
--- a/drivers/gpu/drm/solomon/ssd130x-i2c.c
+++ b/drivers/gpu/drm/solomon/ssd130x-i2c.c
@@ -100,7 +100,7 @@ static struct i2c_driver ssd130x_i2c_driver = {
.name = DRIVER_NAME,
.of_match_table = ssd130x_of_match,
},
- .probe_new = ssd130x_i2c_probe,
+ .probe = ssd130x_i2c_probe,
.remove = ssd130x_i2c_remove,
.shutdown = ssd130x_i2c_shutdown,
};
diff --git a/drivers/gpu/drm/solomon/ssd130x.h b/drivers/gpu/drm/solomon/ssd130x.h
index 03038c1b6476..db03ee5db392 100644
--- a/drivers/gpu/drm/solomon/ssd130x.h
+++ b/drivers/gpu/drm/solomon/ssd130x.h
@@ -10,8 +10,8 @@
* Copyright 2012 Free Electrons
*/
-#ifndef __SSD1307X_H__
-#define __SSD1307X_H__
+#ifndef __SSD130X_H__
+#define __SSD130X_H__
#include <drm/drm_connector.h>
#include <drm/drm_crtc.h>
@@ -94,4 +94,4 @@ struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap);
void ssd130x_remove(struct ssd130x_device *ssd130x);
void ssd130x_shutdown(struct ssd130x_device *ssd130x);
-#endif /* __SSD1307X_H__ */
+#endif /* __SSD130X_H__ */
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index 577c477b5f46..0c6679e361c8 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -8,7 +8,7 @@
#include <linux/component.h>
#include <linux/debugfs.h>
#include <linux/module.h>
-#include <linux/of_gpio.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <drm/drm_atomic_helper.h>
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 8539fe1fedc4..dc1562f14ceb 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -266,6 +266,7 @@ static void hdmi_active_area(struct sti_hdmi *hdmi)
*/
static void hdmi_config(struct sti_hdmi *hdmi)
{
+ struct drm_connector *connector = hdmi->drm_connector;
u32 conf;
DRM_DEBUG_DRIVER("\n");
@@ -275,7 +276,7 @@ static void hdmi_config(struct sti_hdmi *hdmi)
/* Select encryption type and the framing mode */
conf |= HDMI_CFG_ESS_NOT_OESS;
- if (hdmi->hdmi_monitor)
+ if (connector->display_info.is_hdmi)
conf |= HDMI_CFG_HDMI_NOT_DVI;
/* Set Hsync polarity */
@@ -985,15 +986,15 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
if (!edid)
goto fail;
- hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid);
- DRM_DEBUG_KMS("%s : %dx%d cm\n",
- (hdmi->hdmi_monitor ? "hdmi monitor" : "dvi monitor"),
- edid->width_cm, edid->height_cm);
cec_notifier_set_phys_addr_from_edid(hdmi->notifier, edid);
count = drm_add_edid_modes(connector, edid);
drm_connector_update_edid_property(connector, edid);
+ DRM_DEBUG_KMS("%s : %dx%d cm\n",
+ (connector->display_info.is_hdmi ? "hdmi monitor" : "dvi monitor"),
+ edid->width_cm, edid->height_cm);
+
kfree(edid);
return count;
diff --git a/drivers/gpu/drm/sti/sti_hdmi.h b/drivers/gpu/drm/sti/sti_hdmi.h
index 05b2f3d0d48d..6d4c3f57bc46 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.h
+++ b/drivers/gpu/drm/sti/sti_hdmi.h
@@ -57,7 +57,6 @@ struct hdmi_audio_params {
* @reset: reset control of the hdmi phy
* @ddc_adapt: i2c ddc adapter
* @colorspace: current colorspace selected
- * @hdmi_monitor: true if HDMI monitor detected else DVI monitor assumed
* @audio_pdev: ASoC hdmi-codec platform device
* @audio: hdmi audio parameters.
* @drm_connector: hdmi connector
@@ -83,7 +82,6 @@ struct sti_hdmi {
struct reset_control *reset;
struct i2c_adapter *ddc_adapt;
enum hdmi_colorspace colorspace;
- bool hdmi_monitor;
struct platform_device *audio_pdev;
struct hdmi_audio_params audio;
struct drm_connector *drm_connector;
diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
index 422220df7d8c..cb4404b3ce62 100644
--- a/drivers/gpu/drm/stm/drv.c
+++ b/drivers/gpu/drm/stm/drv.c
@@ -185,7 +185,7 @@ static int stm_drm_platform_probe(struct platform_device *pdev)
DRM_DEBUG("%s\n", __func__);
- ret = drm_aperture_remove_framebuffers(false, &drv_driver);
+ ret = drm_aperture_remove_framebuffers(&drv_driver);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
index 89897d5f5c72..1750b6a25e87 100644
--- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
+++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
@@ -444,15 +444,13 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct dw_mipi_dsi_stm *dsi;
struct clk *pclk;
- struct resource *res;
int ret;
dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
if (!dsi)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- dsi->base = devm_ioremap_resource(dev, res);
+ dsi->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dsi->base)) {
ret = PTR_ERR(dsi->base);
DRM_ERROR("Unable to get dsi registers %d\n", ret);
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index 03c6becda795..b8be4c1db423 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -1145,7 +1145,7 @@ static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc)
static int ltdc_crtc_set_crc_source(struct drm_crtc *crtc, const char *source)
{
- struct ltdc_device *ldev = crtc_to_ltdc(crtc);
+ struct ltdc_device *ldev;
int ret;
DRM_DEBUG_DRIVER("\n");
@@ -1153,6 +1153,8 @@ static int ltdc_crtc_set_crc_source(struct drm_crtc *crtc, const char *source)
if (!crtc)
return -ENODEV;
+ ldev = crtc_to_ltdc(crtc);
+
if (source && strcmp(source, "auto") == 0) {
ldev->crc_active = true;
ret = regmap_set_bits(ldev->regmap, LTDC_GCR, GCR_CRCEN);
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 0d04f2447b01..bad7497a0d11 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -19,7 +19,7 @@ sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \
sun8i_vi_scaler.o sun8i_csc.o
sun4i-tcon-y += sun4i_crtc.o
-sun4i-tcon-y += sun4i_dotclock.o
+sun4i-tcon-y += sun4i_tcon_dclk.o
sun4i-tcon-y += sun4i_lvds.o
sun4i-tcon-y += sun4i_tcon.o
sun4i-tcon-y += sun4i_rgb.o
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index e49f78a6a8cf..daa7faf72a4b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -98,7 +98,7 @@ static int sun4i_drv_bind(struct device *dev)
goto unbind_all;
/* Remove early framebuffers (ie. simplefb) */
- ret = drm_aperture_remove_framebuffers(false, &sun4i_drv_driver);
+ ret = drm_aperture_remove_framebuffers(&sun4i_drv_driver);
if (ret)
goto unbind_all;
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 523a6d787921..6a52fb12cbfb 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -31,12 +31,12 @@
#include <uapi/drm/drm_mode.h>
#include "sun4i_crtc.h"
-#include "sun4i_dotclock.h"
#include "sun4i_drv.h"
#include "sun4i_lvds.h"
#include "sun4i_rgb.h"
#include "sun4i_tcon.h"
#include "sun6i_mipi_dsi.h"
+#include "sun4i_tcon_dclk.h"
#include "sun8i_tcon_top.h"
#include "sunxi_engine.h"
@@ -291,18 +291,6 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
return delay;
}
-static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
- const struct drm_display_mode *mode)
-{
- /* Configure the dot clock */
- clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
-
- /* Set the resolution */
- regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
- SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
- SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
-}
-
static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
const struct drm_connector *connector)
{
@@ -367,10 +355,18 @@ static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
u32 block_space, start_delay;
u32 tcon_div;
+ /*
+ * dclk is required to run at 1/4 the DSI per-lane bit rate.
+ */
tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
+ clk_set_rate(tcon->dclk, mode->crtc_clock * 1000 * (bpp / lanes)
+ / SUN6I_DSI_TCON_DIV);
- sun4i_tcon0_mode_set_common(tcon, mode);
+ /* Set the resolution */
+ regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+ SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+ SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
@@ -438,7 +434,12 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
tcon->dclk_min_div = 7;
tcon->dclk_max_div = 7;
- sun4i_tcon0_mode_set_common(tcon, mode);
+ clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+ /* Set the resolution */
+ regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+ SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+ SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
@@ -515,7 +516,12 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
tcon->dclk_min_div = tcon->quirks->dclk_min_div;
tcon->dclk_max_div = 127;
- sun4i_tcon0_mode_set_common(tcon, mode);
+ clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+ /* Set the resolution */
+ regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+ SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+ SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, connector);
@@ -778,21 +784,19 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private)
static int sun4i_tcon_init_clocks(struct device *dev,
struct sun4i_tcon *tcon)
{
- tcon->clk = devm_clk_get(dev, "ahb");
+ tcon->clk = devm_clk_get_enabled(dev, "ahb");
if (IS_ERR(tcon->clk)) {
dev_err(dev, "Couldn't get the TCON bus clock\n");
return PTR_ERR(tcon->clk);
}
- clk_prepare_enable(tcon->clk);
if (tcon->quirks->has_channel_0) {
- tcon->sclk0 = devm_clk_get(dev, "tcon-ch0");
+ tcon->sclk0 = devm_clk_get_enabled(dev, "tcon-ch0");
if (IS_ERR(tcon->sclk0)) {
dev_err(dev, "Couldn't get the TCON channel 0 clock\n");
return PTR_ERR(tcon->sclk0);
}
}
- clk_prepare_enable(tcon->sclk0);
if (tcon->quirks->has_channel_1) {
tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
@@ -805,12 +809,6 @@ static int sun4i_tcon_init_clocks(struct device *dev,
return 0;
}
-static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
-{
- clk_disable_unprepare(tcon->sclk0);
- clk_disable_unprepare(tcon->clk);
-}
-
static int sun4i_tcon_init_irq(struct device *dev,
struct sun4i_tcon *tcon)
{
@@ -1223,28 +1221,28 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
ret = sun4i_tcon_init_regmap(dev, tcon);
if (ret) {
dev_err(dev, "Couldn't init our TCON regmap\n");
- goto err_free_clocks;
+ goto err_assert_reset;
}
if (tcon->quirks->has_channel_0) {
ret = sun4i_dclk_create(dev, tcon);
if (ret) {
dev_err(dev, "Couldn't create our TCON dot clock\n");
- goto err_free_clocks;
+ goto err_assert_reset;
}
}
ret = sun4i_tcon_init_irq(dev, tcon);
if (ret) {
dev_err(dev, "Couldn't init our TCON interrupts\n");
- goto err_free_dotclock;
+ goto err_free_dclk;
}
tcon->crtc = sun4i_crtc_init(drm, engine, tcon);
if (IS_ERR(tcon->crtc)) {
dev_err(dev, "Couldn't create our CRTC\n");
ret = PTR_ERR(tcon->crtc);
- goto err_free_dotclock;
+ goto err_free_dclk;
}
if (tcon->quirks->has_channel_0) {
@@ -1264,7 +1262,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
of_node_put(remote);
if (ret < 0)
- goto err_free_dotclock;
+ goto err_free_dclk;
}
if (tcon->quirks->needs_de_be_mux) {
@@ -1290,11 +1288,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
return 0;
-err_free_dotclock:
+err_free_dclk:
if (tcon->quirks->has_channel_0)
sun4i_dclk_free(tcon);
-err_free_clocks:
- sun4i_tcon_free_clocks(tcon);
err_assert_reset:
reset_control_assert(tcon->lcd_rst);
return ret;
@@ -1308,7 +1304,6 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master,
list_del(&tcon->list);
if (tcon->quirks->has_channel_0)
sun4i_dclk_free(tcon);
- sun4i_tcon_free_clocks(tcon);
}
static const struct component_ops sun4i_tcon_ops = {
diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_tcon_dclk.c
index 417ade3d2565..03d7de1911cd 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon_dclk.c
@@ -10,7 +10,7 @@
#include <linux/regmap.h>
#include "sun4i_tcon.h"
-#include "sun4i_dotclock.h"
+#include "sun4i_tcon_dclk.h"
struct sun4i_dclk {
struct clk_hw hw;
diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.h b/drivers/gpu/drm/sun4i/sun4i_tcon_dclk.h
index ac60da2455ca..ac60da2455ca 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon_dclk.h
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
index 56453ca277c2..498313778175 100644
--- a/drivers/gpu/drm/tegra/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -12,6 +12,7 @@ config DRM_TEGRA
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
+ select FB_SYS_HELPERS if DRM_FBDEV_EMULATION
select TEGRA_HOST1X
select INTERCONNECT
select IOMMU_IOVA
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 85ba96cddd51..35ff303c6674 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1244,7 +1244,7 @@ static int host1x_drm_probe(struct host1x_device *dev)
drm_mode_config_reset(drm);
- err = drm_aperture_remove_framebuffers(false, &tegra_drm_driver);
+ err = drm_aperture_remove_framebuffers(&tegra_drm_driver);
if (err < 0)
goto hub;
diff --git a/drivers/gpu/drm/tegra/fbdev.c b/drivers/gpu/drm/tegra/fbdev.c
index dca9eccae466..e74d9be981c7 100644
--- a/drivers/gpu/drm/tegra/fbdev.c
+++ b/drivers/gpu/drm/tegra/fbdev.c
@@ -8,6 +8,7 @@
*/
#include <linux/console.h>
+#include <linux/fb.h>
#include <linux/vmalloc.h>
#include <drm/drm_drv.h>
@@ -58,12 +59,9 @@ static void tegra_fbdev_fb_destroy(struct fb_info *info)
static const struct fb_ops tegra_fb_ops = {
.owner = THIS_MODULE,
+ __FB_DEFAULT_SYS_OPS_RDWR,
DRM_FB_HELPER_DEFAULT_OPS,
- .fb_read = drm_fb_helper_sys_read,
- .fb_write = drm_fb_helper_sys_write,
- .fb_fillrect = drm_fb_helper_sys_fillrect,
- .fb_copyarea = drm_fb_helper_sys_copyarea,
- .fb_imageblit = drm_fb_helper_sys_imageblit,
+ __FB_DEFAULT_SYS_OPS_DRAW,
.fb_mmap = tegra_fb_mmap,
.fb_destroy = tegra_fbdev_fb_destroy,
};
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index fbb63d755496..abd6e3b92293 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -586,6 +586,7 @@ static u8 tegra_clk_sor_pad_get_parent(struct clk_hw *hw)
}
static const struct clk_ops tegra_clk_sor_pad_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.set_parent = tegra_clk_sor_pad_set_parent,
.get_parent = tegra_clk_sor_pad_get_parent,
};
diff --git a/drivers/gpu/drm/tests/drm_rect_test.c b/drivers/gpu/drm/tests/drm_rect_test.c
index e9809ea32696..76332cd2ead8 100644
--- a/drivers/gpu/drm/tests/drm_rect_test.c
+++ b/drivers/gpu/drm/tests/drm_rect_test.c
@@ -8,6 +8,19 @@
#include <kunit/test.h>
#include <drm/drm_rect.h>
+#include <drm/drm_mode.h>
+
+#include <linux/string_helpers.h>
+#include <linux/errno.h>
+
+static void drm_rect_compare(struct kunit *test, const struct drm_rect *r,
+ const struct drm_rect *expected)
+{
+ KUNIT_EXPECT_EQ(test, r->x1, expected->x1);
+ KUNIT_EXPECT_EQ(test, r->y1, expected->y1);
+ KUNIT_EXPECT_EQ(test, drm_rect_width(r), drm_rect_width(expected));
+ KUNIT_EXPECT_EQ(test, drm_rect_height(r), drm_rect_height(expected));
+}
static void drm_test_rect_clip_scaled_div_by_zero(struct kunit *test)
{
@@ -196,11 +209,313 @@ static void drm_test_rect_clip_scaled_signed_vs_unsigned(struct kunit *test)
KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");
}
+struct drm_rect_intersect_case {
+ const char *description;
+ struct drm_rect r1, r2;
+ bool should_be_visible;
+ struct drm_rect expected_intersection;
+};
+
+static const struct drm_rect_intersect_case drm_rect_intersect_cases[] = {
+ {
+ .description = "top-left x bottom-right",
+ .r1 = DRM_RECT_INIT(1, 1, 2, 2),
+ .r2 = DRM_RECT_INIT(0, 0, 2, 2),
+ .should_be_visible = true,
+ .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1),
+ },
+ {
+ .description = "top-right x bottom-left",
+ .r1 = DRM_RECT_INIT(0, 0, 2, 2),
+ .r2 = DRM_RECT_INIT(1, -1, 2, 2),
+ .should_be_visible = true,
+ .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),
+ },
+ {
+ .description = "bottom-left x top-right",
+ .r1 = DRM_RECT_INIT(1, -1, 2, 2),
+ .r2 = DRM_RECT_INIT(0, 0, 2, 2),
+ .should_be_visible = true,
+ .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),
+ },
+ {
+ .description = "bottom-right x top-left",
+ .r1 = DRM_RECT_INIT(0, 0, 2, 2),
+ .r2 = DRM_RECT_INIT(1, 1, 2, 2),
+ .should_be_visible = true,
+ .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1),
+ },
+ {
+ .description = "right x left",
+ .r1 = DRM_RECT_INIT(0, 0, 2, 1),
+ .r2 = DRM_RECT_INIT(1, 0, 3, 1),
+ .should_be_visible = true,
+ .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),
+ },
+ {
+ .description = "left x right",
+ .r1 = DRM_RECT_INIT(1, 0, 3, 1),
+ .r2 = DRM_RECT_INIT(0, 0, 2, 1),
+ .should_be_visible = true,
+ .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),
+ },
+ {
+ .description = "up x bottom",
+ .r1 = DRM_RECT_INIT(0, 0, 1, 2),
+ .r2 = DRM_RECT_INIT(0, -1, 1, 3),
+ .should_be_visible = true,
+ .expected_intersection = DRM_RECT_INIT(0, 0, 1, 2),
+ },
+ {
+ .description = "bottom x up",
+ .r1 = DRM_RECT_INIT(0, -1, 1, 3),
+ .r2 = DRM_RECT_INIT(0, 0, 1, 2),
+ .should_be_visible = true,
+ .expected_intersection = DRM_RECT_INIT(0, 0, 1, 2),
+ },
+ {
+ .description = "touching corner",
+ .r1 = DRM_RECT_INIT(0, 0, 1, 1),
+ .r2 = DRM_RECT_INIT(1, 1, 2, 2),
+ .should_be_visible = false,
+ .expected_intersection = DRM_RECT_INIT(1, 1, 0, 0),
+ },
+ {
+ .description = "touching side",
+ .r1 = DRM_RECT_INIT(0, 0, 1, 1),
+ .r2 = DRM_RECT_INIT(1, 0, 1, 1),
+ .should_be_visible = false,
+ .expected_intersection = DRM_RECT_INIT(1, 0, 0, 1),
+ },
+ {
+ .description = "equal rects",
+ .r1 = DRM_RECT_INIT(0, 0, 2, 2),
+ .r2 = DRM_RECT_INIT(0, 0, 2, 2),
+ .should_be_visible = true,
+ .expected_intersection = DRM_RECT_INIT(0, 0, 2, 2),
+ },
+ {
+ .description = "inside another",
+ .r1 = DRM_RECT_INIT(0, 0, 2, 2),
+ .r2 = DRM_RECT_INIT(1, 1, 1, 1),
+ .should_be_visible = true,
+ .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1),
+ },
+ {
+ .description = "far away",
+ .r1 = DRM_RECT_INIT(0, 0, 1, 1),
+ .r2 = DRM_RECT_INIT(3, 6, 1, 1),
+ .should_be_visible = false,
+ .expected_intersection = DRM_RECT_INIT(3, 6, -2, -5),
+ },
+ {
+ .description = "points intersecting",
+ .r1 = DRM_RECT_INIT(5, 10, 0, 0),
+ .r2 = DRM_RECT_INIT(5, 10, 0, 0),
+ .should_be_visible = false,
+ .expected_intersection = DRM_RECT_INIT(5, 10, 0, 0),
+ },
+ {
+ .description = "points not intersecting",
+ .r1 = DRM_RECT_INIT(0, 0, 0, 0),
+ .r2 = DRM_RECT_INIT(5, 10, 0, 0),
+ .should_be_visible = false,
+ .expected_intersection = DRM_RECT_INIT(5, 10, -5, -10),
+ },
+};
+
+static void drm_rect_intersect_case_desc(const struct drm_rect_intersect_case *t, char *desc)
+{
+ snprintf(desc, KUNIT_PARAM_DESC_SIZE,
+ "%s: " DRM_RECT_FMT " x " DRM_RECT_FMT,
+ t->description, DRM_RECT_ARG(&t->r1), DRM_RECT_ARG(&t->r2));
+}
+
+KUNIT_ARRAY_PARAM(drm_rect_intersect, drm_rect_intersect_cases, drm_rect_intersect_case_desc);
+
+static void drm_test_rect_intersect(struct kunit *test)
+{
+ const struct drm_rect_intersect_case *params = test->param_value;
+ struct drm_rect r1_aux = params->r1;
+ bool visible;
+
+ visible = drm_rect_intersect(&r1_aux, &params->r2);
+
+ KUNIT_EXPECT_EQ(test, visible, params->should_be_visible);
+ drm_rect_compare(test, &r1_aux, &params->expected_intersection);
+}
+
+struct drm_rect_scale_case {
+ const char *name;
+ struct drm_rect src, dst;
+ int min_range, max_range;
+ int expected_scaling_factor;
+};
+
+static const struct drm_rect_scale_case drm_rect_scale_cases[] = {
+ {
+ .name = "normal use",
+ .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16),
+ .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),
+ .min_range = 0, .max_range = INT_MAX,
+ .expected_scaling_factor = 2,
+ },
+ {
+ .name = "out of max range",
+ .src = DRM_RECT_INIT(0, 0, 10 << 16, 10 << 16),
+ .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),
+ .min_range = 3, .max_range = 5,
+ .expected_scaling_factor = -ERANGE,
+ },
+ {
+ .name = "out of min range",
+ .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16),
+ .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),
+ .min_range = 3, .max_range = 5,
+ .expected_scaling_factor = -ERANGE,
+ },
+ {
+ .name = "zero dst",
+ .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16),
+ .dst = DRM_RECT_INIT(0, 0, 0 << 16, 0 << 16),
+ .min_range = 0, .max_range = INT_MAX,
+ .expected_scaling_factor = 0,
+ },
+ {
+ .name = "negative src",
+ .src = DRM_RECT_INIT(0, 0, -(1 << 16), -(1 << 16)),
+ .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),
+ .min_range = 0, .max_range = INT_MAX,
+ .expected_scaling_factor = -EINVAL,
+ },
+ {
+ .name = "negative dst",
+ .src = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16),
+ .dst = DRM_RECT_INIT(0, 0, -(1 << 16), -(1 << 16)),
+ .min_range = 0, .max_range = INT_MAX,
+ .expected_scaling_factor = -EINVAL,
+ },
+};
+
+static void drm_rect_scale_case_desc(const struct drm_rect_scale_case *t, char *desc)
+{
+ strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
+}
+
+KUNIT_ARRAY_PARAM(drm_rect_scale, drm_rect_scale_cases, drm_rect_scale_case_desc);
+
+static void drm_test_rect_calc_hscale(struct kunit *test)
+{
+ const struct drm_rect_scale_case *params = test->param_value;
+ int scaling_factor;
+
+ scaling_factor = drm_rect_calc_hscale(&params->src, &params->dst,
+ params->min_range, params->max_range);
+
+ KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);
+}
+
+static void drm_test_rect_calc_vscale(struct kunit *test)
+{
+ const struct drm_rect_scale_case *params = test->param_value;
+ int scaling_factor;
+
+ scaling_factor = drm_rect_calc_vscale(&params->src, &params->dst,
+ params->min_range, params->max_range);
+
+ KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);
+}
+
+struct drm_rect_rotate_case {
+ const char *name;
+ unsigned int rotation;
+ struct drm_rect rect;
+ int width, height;
+ struct drm_rect expected;
+};
+
+static const struct drm_rect_rotate_case drm_rect_rotate_cases[] = {
+ {
+ .name = "reflect-x",
+ .rotation = DRM_MODE_REFLECT_X,
+ .rect = DRM_RECT_INIT(0, 0, 5, 5),
+ .width = 5, .height = 10,
+ .expected = DRM_RECT_INIT(0, 0, 5, 5),
+ },
+ {
+ .name = "reflect-y",
+ .rotation = DRM_MODE_REFLECT_Y,
+ .rect = DRM_RECT_INIT(2, 0, 5, 5),
+ .width = 5, .height = 10,
+ .expected = DRM_RECT_INIT(2, 5, 5, 5),
+ },
+ {
+ .name = "rotate-0",
+ .rotation = DRM_MODE_ROTATE_0,
+ .rect = DRM_RECT_INIT(0, 2, 5, 5),
+ .width = 5, .height = 10,
+ .expected = DRM_RECT_INIT(0, 2, 5, 5),
+ },
+ {
+ .name = "rotate-90",
+ .rotation = DRM_MODE_ROTATE_90,
+ .rect = DRM_RECT_INIT(0, 0, 5, 10),
+ .width = 5, .height = 10,
+ .expected = DRM_RECT_INIT(0, 0, 10, 5),
+ },
+ {
+ .name = "rotate-180",
+ .rotation = DRM_MODE_ROTATE_180,
+ .rect = DRM_RECT_INIT(11, 3, 5, 10),
+ .width = 5, .height = 10,
+ .expected = DRM_RECT_INIT(-11, -3, 5, 10),
+ },
+ {
+ .name = "rotate-270",
+ .rotation = DRM_MODE_ROTATE_270,
+ .rect = DRM_RECT_INIT(6, 3, 5, 10),
+ .width = 5, .height = 10,
+ .expected = DRM_RECT_INIT(-3, 6, 10, 5),
+ },
+};
+
+static void drm_rect_rotate_case_desc(const struct drm_rect_rotate_case *t, char *desc)
+{
+ strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
+}
+
+KUNIT_ARRAY_PARAM(drm_rect_rotate, drm_rect_rotate_cases, drm_rect_rotate_case_desc);
+
+static void drm_test_rect_rotate(struct kunit *test)
+{
+ const struct drm_rect_rotate_case *params = test->param_value;
+ struct drm_rect r = params->rect;
+
+ drm_rect_rotate(&r, params->width, params->height, params->rotation);
+
+ drm_rect_compare(test, &r, &params->expected);
+}
+
+static void drm_test_rect_rotate_inv(struct kunit *test)
+{
+ const struct drm_rect_rotate_case *params = test->param_value;
+ struct drm_rect r = params->expected;
+
+ drm_rect_rotate_inv(&r, params->width, params->height, params->rotation);
+
+ drm_rect_compare(test, &r, &params->rect);
+}
+
static struct kunit_case drm_rect_tests[] = {
KUNIT_CASE(drm_test_rect_clip_scaled_div_by_zero),
KUNIT_CASE(drm_test_rect_clip_scaled_not_clipped),
KUNIT_CASE(drm_test_rect_clip_scaled_clipped),
KUNIT_CASE(drm_test_rect_clip_scaled_signed_vs_unsigned),
+ KUNIT_CASE_PARAM(drm_test_rect_intersect, drm_rect_intersect_gen_params),
+ KUNIT_CASE_PARAM(drm_test_rect_calc_hscale, drm_rect_scale_gen_params),
+ KUNIT_CASE_PARAM(drm_test_rect_calc_vscale, drm_rect_scale_gen_params),
+ KUNIT_CASE_PARAM(drm_test_rect_rotate, drm_rect_rotate_gen_params),
+ KUNIT_CASE_PARAM(drm_test_rect_rotate_inv, drm_rect_rotate_gen_params),
{ }
};
diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c
index 64a59f46f6c3..7726a72befc5 100644
--- a/drivers/gpu/drm/ttm/ttm_device.c
+++ b/drivers/gpu/drm/ttm/ttm_device.c
@@ -189,7 +189,7 @@ EXPORT_SYMBOL(ttm_device_swapout);
* Returns:
* !0: Failure.
*/
-int ttm_device_init(struct ttm_device *bdev, struct ttm_device_funcs *funcs,
+int ttm_device_init(struct ttm_device *bdev, const struct ttm_device_funcs *funcs,
struct device *dev, struct address_space *mapping,
struct drm_vma_offset_manager *vma_manager,
bool use_dma_alloc, bool use_dma32)
@@ -213,7 +213,7 @@ int ttm_device_init(struct ttm_device *bdev, struct ttm_device_funcs *funcs,
bdev->funcs = funcs;
ttm_sys_man_init(bdev);
- ttm_pool_init(&bdev->pool, dev, use_dma_alloc, use_dma32);
+ ttm_pool_init(&bdev->pool, dev, NUMA_NO_NODE, use_dma_alloc, use_dma32);
bdev->vma_manager = vma_manager;
spin_lock_init(&bdev->lru_lock);
diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
index 4db3982057be..cddb9151d20f 100644
--- a/drivers/gpu/drm/ttm/ttm_pool.c
+++ b/drivers/gpu/drm/ttm/ttm_pool.c
@@ -93,7 +93,7 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool *pool, gfp_t gfp_flags,
__GFP_KSWAPD_RECLAIM;
if (!pool->use_dma_alloc) {
- p = alloc_pages(gfp_flags, order);
+ p = alloc_pages_node(pool->nid, gfp_flags, order);
if (p)
p->private = order;
return p;
@@ -287,7 +287,7 @@ static struct ttm_pool_type *ttm_pool_select_type(struct ttm_pool *pool,
enum ttm_caching caching,
unsigned int order)
{
- if (pool->use_dma_alloc)
+ if (pool->use_dma_alloc || pool->nid != NUMA_NO_NODE)
return &pool->caching[caching].orders[order];
#ifdef CONFIG_X86
@@ -545,29 +545,32 @@ EXPORT_SYMBOL(ttm_pool_free);
*
* @pool: the pool to initialize
* @dev: device for DMA allocations and mappings
+ * @nid: NUMA node to use for allocations
* @use_dma_alloc: true if coherent DMA alloc should be used
* @use_dma32: true if GFP_DMA32 should be used
*
* Initialize the pool and its pool types.
*/
void ttm_pool_init(struct ttm_pool *pool, struct device *dev,
- bool use_dma_alloc, bool use_dma32)
+ int nid, bool use_dma_alloc, bool use_dma32)
{
unsigned int i, j;
WARN_ON(!dev && use_dma_alloc);
pool->dev = dev;
+ pool->nid = nid;
pool->use_dma_alloc = use_dma_alloc;
pool->use_dma32 = use_dma32;
- if (use_dma_alloc) {
+ if (use_dma_alloc || nid != NUMA_NO_NODE) {
for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i)
for (j = 0; j <= MAX_ORDER; ++j)
ttm_pool_type_init(&pool->caching[i].orders[j],
pool, i, j);
}
}
+EXPORT_SYMBOL(ttm_pool_init);
/**
* ttm_pool_fini - Cleanup a pool
@@ -581,7 +584,7 @@ void ttm_pool_fini(struct ttm_pool *pool)
{
unsigned int i, j;
- if (pool->use_dma_alloc) {
+ if (pool->use_dma_alloc || pool->nid != NUMA_NO_NODE) {
for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i)
for (j = 0; j <= MAX_ORDER; ++j)
ttm_pool_type_fini(&pool->caching[i].orders[j]);
@@ -592,6 +595,7 @@ void ttm_pool_fini(struct ttm_pool *pool)
*/
synchronize_shrinkers();
}
+EXPORT_SYMBOL(ttm_pool_fini);
/* As long as pages are available make sure to release at least one */
static unsigned long ttm_pool_shrinker_scan(struct shrinker *shrink,
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index ab725d9d14a6..e0a77671edd6 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -137,7 +137,6 @@ static void ttm_tt_init_fields(struct ttm_tt *ttm,
unsigned long extra_pages)
{
ttm->num_pages = (PAGE_ALIGN(bo->base.size) >> PAGE_SHIFT) + extra_pages;
- ttm->caching = ttm_cached;
ttm->page_flags = page_flags;
ttm->dma_address = NULL;
ttm->swap_storage = NULL;
@@ -450,3 +449,9 @@ ttm_kmap_iter_tt_init(struct ttm_kmap_iter_tt *iter_tt,
return &iter_tt->base;
}
EXPORT_SYMBOL(ttm_kmap_iter_tt_init);
+
+unsigned long ttm_tt_pages_limit(void)
+{
+ return ttm_pages_limit;
+}
+EXPORT_SYMBOL(ttm_tt_pages_limit);
diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c
index abd557332b28..40b1168ad671 100644
--- a/drivers/gpu/drm/tve200/tve200_drv.c
+++ b/drivers/gpu/drm/tve200/tve200_drv.c
@@ -156,7 +156,6 @@ static int tve200_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct tve200_drm_dev_private *priv;
struct drm_device *drm;
- struct resource *res;
int irq;
int ret;
@@ -192,8 +191,7 @@ static int tve200_probe(struct platform_device *pdev)
goto clk_disable;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->regs = devm_ioremap_resource(dev, res);
+ priv->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->regs)) {
dev_err(dev, "%s failed mmio\n", __func__);
ret = -EINVAL;
diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c
index 061cb88c08a2..3ebe2ce55dfd 100644
--- a/drivers/gpu/drm/udl/udl_main.c
+++ b/drivers/gpu/drm/udl/udl_main.c
@@ -255,7 +255,7 @@ static struct urb *udl_get_urb_locked(struct udl_device *udl, long timeout)
list_del_init(&unode->entry);
udl->urbs.available--;
- return unode ? unode->urb : NULL;
+ return unode->urb;
}
#define GET_URB_TIMEOUT HZ
diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.h b/drivers/gpu/drm/vc4/tests/vc4_mock.h
index db8e9a141ef8..2d0b339bd9f3 100644
--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h
+++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h
@@ -43,6 +43,9 @@ struct vc4_dummy_output {
struct drm_connector connector;
};
+#define encoder_to_vc4_dummy_output(_enc) \
+ container_of_const(_enc, struct vc4_dummy_output, encoder.base)
+
struct vc4_dummy_output *vc4_dummy_output(struct kunit *test,
struct drm_device *drm,
struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c
index 8d33be828d9a..6e11fcc9ef45 100644
--- a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c
+++ b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c
@@ -80,7 +80,7 @@ int vc4_mock_atomic_add_output(struct kunit *test,
crtc = vc4_find_crtc_for_encoder(test, drm, encoder);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
- output = container_of(encoder, struct vc4_dummy_output, encoder.base);
+ output = encoder_to_vc4_dummy_output(encoder);
conn = &output->connector;
conn_state = drm_atomic_get_connector_state(state, conn);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
@@ -126,7 +126,7 @@ int vc4_mock_atomic_del_output(struct kunit *test,
ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
KUNIT_ASSERT_EQ(test, ret, 0);
- output = container_of(encoder, struct vc4_dummy_output, encoder.base);
+ output = encoder_to_vc4_dummy_output(encoder);
conn = &output->connector;
conn_state = drm_atomic_get_connector_state(state, conn);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
index f518d6e59ed6..e68c07d86040 100644
--- a/drivers/gpu/drm/vc4/vc4_dpi.c
+++ b/drivers/gpu/drm/vc4/vc4_dpi.c
@@ -97,11 +97,8 @@ struct vc4_dpi {
struct debugfs_regset32 regset;
};
-static inline struct vc4_dpi *
-to_vc4_dpi(struct drm_encoder *encoder)
-{
- return container_of(encoder, struct vc4_dpi, encoder.base);
-}
+#define to_vc4_dpi(_encoder) \
+ container_of_const(_encoder, struct vc4_dpi, encoder.base)
#define DPI_READ(offset) \
({ \
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index c8bf954042e0..823395c23cc3 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -350,7 +350,7 @@ static int vc4_drm_bind(struct device *dev)
return -EPROBE_DEFER;
}
- ret = drm_aperture_remove_framebuffers(false, driver);
+ ret = drm_aperture_remove_framebuffers(driver);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 8768566c610b..bf66499765fb 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -232,11 +232,8 @@ struct vc4_dev {
struct kref bin_bo_kref;
};
-static inline struct vc4_dev *
-to_vc4_dev(const struct drm_device *dev)
-{
- return container_of(dev, struct vc4_dev, base);
-}
+#define to_vc4_dev(_dev) \
+ container_of_const(_dev, struct vc4_dev, base)
struct vc4_bo {
struct drm_gem_dma_object base;
@@ -285,11 +282,8 @@ struct vc4_bo {
struct mutex madv_lock;
};
-static inline struct vc4_bo *
-to_vc4_bo(const struct drm_gem_object *bo)
-{
- return container_of(to_drm_gem_dma_obj(bo), struct vc4_bo, base);
-}
+#define to_vc4_bo(_bo) \
+ container_of_const(to_drm_gem_dma_obj(_bo), struct vc4_bo, base)
struct vc4_fence {
struct dma_fence base;
@@ -298,11 +292,8 @@ struct vc4_fence {
uint64_t seqno;
};
-static inline struct vc4_fence *
-to_vc4_fence(const struct dma_fence *fence)
-{
- return container_of(fence, struct vc4_fence, base);
-}
+#define to_vc4_fence(_fence) \
+ container_of_const(_fence, struct vc4_fence, base)
struct vc4_seqno_cb {
struct work_struct work;
@@ -368,11 +359,8 @@ struct vc4_hvs_state {
} fifo_state[HVS_NUM_CHANNELS];
};
-static inline struct vc4_hvs_state *
-to_vc4_hvs_state(const struct drm_private_state *priv)
-{
- return container_of(priv, struct vc4_hvs_state, base);
-}
+#define to_vc4_hvs_state(_state) \
+ container_of_const(_state, struct vc4_hvs_state, base)
struct vc4_hvs_state *vc4_hvs_get_global_state(struct drm_atomic_state *state);
struct vc4_hvs_state *vc4_hvs_get_old_global_state(const struct drm_atomic_state *state);
@@ -382,11 +370,8 @@ struct vc4_plane {
struct drm_plane base;
};
-static inline struct vc4_plane *
-to_vc4_plane(const struct drm_plane *plane)
-{
- return container_of(plane, struct vc4_plane, base);
-}
+#define to_vc4_plane(_plane) \
+ container_of_const(_plane, struct vc4_plane, base)
enum vc4_scaling_mode {
VC4_SCALING_NONE,
@@ -458,11 +443,8 @@ struct vc4_plane_state {
u64 membus_load;
};
-static inline struct vc4_plane_state *
-to_vc4_plane_state(const struct drm_plane_state *state)
-{
- return container_of(state, struct vc4_plane_state, base);
-}
+#define to_vc4_plane_state(_state) \
+ container_of_const(_state, struct vc4_plane_state, base)
enum vc4_encoder_type {
VC4_ENCODER_TYPE_NONE,
@@ -489,11 +471,8 @@ struct vc4_encoder {
void (*post_crtc_powerdown)(struct drm_encoder *encoder, struct drm_atomic_state *state);
};
-static inline struct vc4_encoder *
-to_vc4_encoder(const struct drm_encoder *encoder)
-{
- return container_of(encoder, struct vc4_encoder, base);
-}
+#define to_vc4_encoder(_encoder) \
+ container_of_const(_encoder, struct vc4_encoder, base)
static inline
struct drm_encoder *vc4_find_encoder_by_type(struct drm_device *drm,
@@ -591,11 +570,8 @@ struct vc4_crtc {
unsigned int current_hvs_channel;
};
-static inline struct vc4_crtc *
-to_vc4_crtc(const struct drm_crtc *crtc)
-{
- return container_of(crtc, struct vc4_crtc, base);
-}
+#define to_vc4_crtc(_crtc) \
+ container_of_const(_crtc, struct vc4_crtc, base)
static inline const struct vc4_crtc_data *
vc4_crtc_to_vc4_crtc_data(const struct vc4_crtc *crtc)
@@ -608,7 +584,7 @@ vc4_crtc_to_vc4_pv_data(const struct vc4_crtc *crtc)
{
const struct vc4_crtc_data *data = vc4_crtc_to_vc4_crtc_data(crtc);
- return container_of(data, struct vc4_pv_data, base);
+ return container_of_const(data, struct vc4_pv_data, base);
}
struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc,
@@ -636,11 +612,8 @@ struct vc4_crtc_state {
#define VC4_HVS_CHANNEL_DISABLED ((unsigned int)-1)
-static inline struct vc4_crtc_state *
-to_vc4_crtc_state(const struct drm_crtc_state *crtc_state)
-{
- return container_of(crtc_state, struct vc4_crtc_state, base);
-}
+#define to_vc4_crtc_state(_state) \
+ container_of_const(_state, struct vc4_crtc_state, base)
#define V3D_READ(offset) \
({ \
diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
index a5c075f802e4..9e0c355b236f 100644
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -600,19 +600,14 @@ struct vc4_dsi {
struct debugfs_regset32 regset;
};
-#define host_to_dsi(host) container_of(host, struct vc4_dsi, dsi_host)
+#define host_to_dsi(host) \
+ container_of_const(host, struct vc4_dsi, dsi_host)
-static inline struct vc4_dsi *
-to_vc4_dsi(struct drm_encoder *encoder)
-{
- return container_of(encoder, struct vc4_dsi, encoder.base);
-}
+#define to_vc4_dsi(_encoder) \
+ container_of_const(_encoder, struct vc4_dsi, encoder.base)
-static inline struct vc4_dsi *
-bridge_to_vc4_dsi(struct drm_bridge *bridge)
-{
- return container_of(bridge, struct vc4_dsi, bridge);
-}
+#define bridge_to_vc4_dsi(_bridge) \
+ container_of_const(_bridge, struct vc4_dsi, bridge)
static inline void
dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 06713d8b82b5..5261526d286f 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -153,11 +153,17 @@ static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode,
return clock > HDMI_14_MAX_TMDS_CLK;
}
-static bool vc4_hdmi_is_full_range_rgb(struct vc4_hdmi *vc4_hdmi,
- const struct drm_display_mode *mode)
+static bool vc4_hdmi_is_full_range(struct vc4_hdmi *vc4_hdmi,
+ struct vc4_hdmi_connector_state *vc4_state)
{
+ const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
struct drm_display_info *display = &vc4_hdmi->connector.display_info;
+ if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_LIMITED)
+ return false;
+ else if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_FULL)
+ return true;
+
return !display->is_hdmi ||
drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_FULL;
}
@@ -528,14 +534,45 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector,
{
struct drm_connector_state *old_state =
drm_atomic_get_old_connector_state(state, connector);
+ struct vc4_hdmi_connector_state *old_vc4_state =
+ conn_state_to_vc4_hdmi_conn_state(old_state);
struct drm_connector_state *new_state =
drm_atomic_get_new_connector_state(state, connector);
+ struct vc4_hdmi_connector_state *new_vc4_state =
+ conn_state_to_vc4_hdmi_conn_state(new_state);
struct drm_crtc *crtc = new_state->crtc;
if (!crtc)
return 0;
+ if (old_state->tv.margins.left != new_state->tv.margins.left ||
+ old_state->tv.margins.right != new_state->tv.margins.right ||
+ old_state->tv.margins.top != new_state->tv.margins.top ||
+ old_state->tv.margins.bottom != new_state->tv.margins.bottom) {
+ struct drm_crtc_state *crtc_state;
+ int ret;
+
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ /*
+ * Strictly speaking, we should be calling
+ * drm_atomic_helper_check_planes() after our call to
+ * drm_atomic_add_affected_planes(). However, the
+ * connector atomic_check is called as part of
+ * drm_atomic_helper_check_modeset() that already
+ * happens before a call to
+ * drm_atomic_helper_check_planes() in
+ * drm_atomic_helper_check().
+ */
+ ret = drm_atomic_add_affected_planes(state, crtc);
+ if (ret)
+ return ret;
+ }
+
if (old_state->colorspace != new_state->colorspace ||
+ old_vc4_state->broadcast_rgb != new_vc4_state->broadcast_rgb ||
!drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) {
struct drm_crtc_state *crtc_state;
@@ -549,6 +586,49 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector,
return 0;
}
+static int vc4_hdmi_connector_get_property(struct drm_connector *connector,
+ const struct drm_connector_state *state,
+ struct drm_property *property,
+ uint64_t *val)
+{
+ struct drm_device *drm = connector->dev;
+ struct vc4_hdmi *vc4_hdmi =
+ connector_to_vc4_hdmi(connector);
+ const struct vc4_hdmi_connector_state *vc4_conn_state =
+ conn_state_to_vc4_hdmi_conn_state(state);
+
+ if (property == vc4_hdmi->broadcast_rgb_property) {
+ *val = vc4_conn_state->broadcast_rgb;
+ } else {
+ drm_dbg(drm, "Unknown property [PROP:%d:%s]\n",
+ property->base.id, property->name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vc4_hdmi_connector_set_property(struct drm_connector *connector,
+ struct drm_connector_state *state,
+ struct drm_property *property,
+ uint64_t val)
+{
+ struct drm_device *drm = connector->dev;
+ struct vc4_hdmi *vc4_hdmi =
+ connector_to_vc4_hdmi(connector);
+ struct vc4_hdmi_connector_state *vc4_conn_state =
+ conn_state_to_vc4_hdmi_conn_state(state);
+
+ if (property == vc4_hdmi->broadcast_rgb_property) {
+ vc4_conn_state->broadcast_rgb = val;
+ return 0;
+ }
+
+ drm_dbg(drm, "Unknown property [PROP:%d:%s]\n",
+ property->base.id, property->name);
+ return -EINVAL;
+}
+
static void vc4_hdmi_connector_reset(struct drm_connector *connector)
{
struct vc4_hdmi_connector_state *old_state =
@@ -568,6 +648,7 @@ static void vc4_hdmi_connector_reset(struct drm_connector *connector)
new_state->base.max_bpc = 8;
new_state->base.max_requested_bpc = 8;
new_state->output_format = VC4_HDMI_OUTPUT_RGB;
+ new_state->broadcast_rgb = VC4_HDMI_BROADCAST_RGB_AUTO;
drm_atomic_helper_connector_tv_margins_reset(connector);
}
@@ -585,6 +666,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
new_state->tmds_char_rate = vc4_state->tmds_char_rate;
new_state->output_bpc = vc4_state->output_bpc;
new_state->output_format = vc4_state->output_format;
+ new_state->broadcast_rgb = vc4_state->broadcast_rgb;
__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
return &new_state->base;
@@ -595,6 +677,8 @@ static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
.reset = vc4_hdmi_connector_reset,
.atomic_duplicate_state = vc4_hdmi_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+ .atomic_get_property = vc4_hdmi_connector_get_property,
+ .atomic_set_property = vc4_hdmi_connector_set_property,
};
static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = {
@@ -603,6 +687,33 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
.atomic_check = vc4_hdmi_connector_atomic_check,
};
+static const struct drm_prop_enum_list broadcast_rgb_names[] = {
+ { VC4_HDMI_BROADCAST_RGB_AUTO, "Automatic" },
+ { VC4_HDMI_BROADCAST_RGB_FULL, "Full" },
+ { VC4_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235" },
+};
+
+static void
+vc4_hdmi_attach_broadcast_rgb_property(struct drm_device *dev,
+ struct vc4_hdmi *vc4_hdmi)
+{
+ struct drm_property *prop = vc4_hdmi->broadcast_rgb_property;
+
+ if (!prop) {
+ prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
+ "Broadcast RGB",
+ broadcast_rgb_names,
+ ARRAY_SIZE(broadcast_rgb_names));
+ if (!prop)
+ return;
+
+ vc4_hdmi->broadcast_rgb_property = prop;
+ }
+
+ drm_object_attach_property(&vc4_hdmi->connector.base, prop,
+ VC4_HDMI_BROADCAST_RGB_AUTO);
+}
+
static int vc4_hdmi_connector_init(struct drm_device *dev,
struct vc4_hdmi *vc4_hdmi)
{
@@ -631,7 +742,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
if (ret)
return ret;
- ret = drm_mode_create_hdmi_colorspace_property(connector);
+ ret = drm_mode_create_hdmi_colorspace_property(connector, 0);
if (ret)
return ret;
@@ -649,6 +760,8 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
if (vc4_hdmi->variant->supports_hdr)
drm_connector_attach_hdr_output_metadata_property(connector);
+ vc4_hdmi_attach_broadcast_rgb_property(dev, vc4_hdmi);
+
drm_connector_attach_encoder(connector, encoder);
return 0;
@@ -803,7 +916,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
drm_hdmi_avi_infoframe_quant_range(&frame.avi,
connector, mode,
- vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode) ?
+ vc4_hdmi_is_full_range(vc4_hdmi, vc4_state) ?
HDMI_QUANTIZATION_RANGE_FULL :
HDMI_QUANTIZATION_RANGE_LIMITED);
drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate);
@@ -1046,6 +1159,8 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
struct drm_connector_state *state,
const struct drm_display_mode *mode)
{
+ struct vc4_hdmi_connector_state *vc4_state =
+ conn_state_to_vc4_hdmi_conn_state(state);
struct drm_device *drm = vc4_hdmi->connector.dev;
unsigned long flags;
u32 csc_ctl;
@@ -1059,7 +1174,7 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
VC4_HD_CSC_CTL_ORDER);
- if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode)) {
+ if (!vc4_hdmi_is_full_range(vc4_hdmi, vc4_state)) {
/* CEA VICs other than #1 requre limited range RGB
* output unless overridden by an AVI infoframe.
* Apply a colorspace conversion to squash 0-255 down
@@ -1092,68 +1207,134 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
}
/*
- * If we need to output Full Range RGB, then use the unity matrix
- *
- * [ 1 0 0 0]
- * [ 0 1 0 0]
- * [ 0 0 1 0]
+ * Matrices for (internal) RGB to RGB output.
*
- * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
+ * Matrices are signed 2p13 fixed point, with signed 9p6 offsets
*/
-static const u16 vc5_hdmi_csc_full_rgb_unity[3][4] = {
- { 0x2000, 0x0000, 0x0000, 0x0000 },
- { 0x0000, 0x2000, 0x0000, 0x0000 },
- { 0x0000, 0x0000, 0x2000, 0x0000 },
+static const u16 vc5_hdmi_csc_full_rgb_to_rgb[2][3][4] = {
+ {
+ /*
+ * Full range - unity
+ *
+ * [ 1 0 0 0]
+ * [ 0 1 0 0]
+ * [ 0 0 1 0]
+ */
+ { 0x2000, 0x0000, 0x0000, 0x0000 },
+ { 0x0000, 0x2000, 0x0000, 0x0000 },
+ { 0x0000, 0x0000, 0x2000, 0x0000 },
+ },
+ {
+ /*
+ * Limited range
+ *
+ * CEA VICs other than #1 require limited range RGB
+ * output unless overridden by an AVI infoframe. Apply a
+ * colorspace conversion to squash 0-255 down to 16-235.
+ * The matrix here is:
+ *
+ * [ 0.8594 0 0 16]
+ * [ 0 0.8594 0 16]
+ * [ 0 0 0.8594 16]
+ */
+ { 0x1b80, 0x0000, 0x0000, 0x0400 },
+ { 0x0000, 0x1b80, 0x0000, 0x0400 },
+ { 0x0000, 0x0000, 0x1b80, 0x0400 },
+ },
};
/*
- * CEA VICs other than #1 require limited range RGB output unless
- * overridden by an AVI infoframe. Apply a colorspace conversion to
- * squash 0-255 down to 16-235. The matrix here is:
- *
- * [ 0.8594 0 0 16]
- * [ 0 0.8594 0 16]
- * [ 0 0 0.8594 16]
+ * Conversion between Full Range RGB and YUV using the BT.601 Colorspace
*
- * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
+ * Matrices are signed 2p13 fixed point, with signed 9p6 offsets
*/
-static const u16 vc5_hdmi_csc_full_rgb_to_limited_rgb[3][4] = {
- { 0x1b80, 0x0000, 0x0000, 0x0400 },
- { 0x0000, 0x1b80, 0x0000, 0x0400 },
- { 0x0000, 0x0000, 0x1b80, 0x0400 },
+static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt601[2][3][4] = {
+ {
+ /*
+ * Full Range
+ *
+ * [ 0.299000 0.587000 0.114000 0 ]
+ * [ -0.168736 -0.331264 0.500000 128 ]
+ * [ 0.500000 -0.418688 -0.081312 128 ]
+ */
+ { 0x0991, 0x12c9, 0x03a6, 0x0000 },
+ { 0xfa9b, 0xf567, 0x1000, 0x2000 },
+ { 0x1000, 0xf29b, 0xfd67, 0x2000 },
+ },
+ {
+ /* Limited Range
+ *
+ * [ 0.255785 0.502160 0.097523 16 ]
+ * [ -0.147644 -0.289856 0.437500 128 ]
+ * [ 0.437500 -0.366352 -0.071148 128 ]
+ */
+ { 0x082f, 0x1012, 0x031f, 0x0400 },
+ { 0xfb48, 0xf6ba, 0x0e00, 0x2000 },
+ { 0x0e00, 0xf448, 0xfdba, 0x2000 },
+ },
};
/*
- * Conversion between Full Range RGB and Full Range YUV422 using the
- * BT.709 Colorspace
+ * Conversion between Full Range RGB and YUV using the BT.709 Colorspace
*
- *
- * [ 0.181906 0.611804 0.061758 16 ]
- * [ -0.100268 -0.337232 0.437500 128 ]
- * [ 0.437500 -0.397386 -0.040114 128 ]
- *
- * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
+ * Matrices are signed 2p13 fixed point, with signed 9p6 offsets
*/
-static const u16 vc5_hdmi_csc_full_rgb_to_limited_yuv422_bt709[3][4] = {
- { 0x05d2, 0x1394, 0x01fa, 0x0400 },
- { 0xfccc, 0xf536, 0x0e00, 0x2000 },
- { 0x0e00, 0xf34a, 0xfeb8, 0x2000 },
+static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt709[2][3][4] = {
+ {
+ /*
+ * Full Range
+ *
+ * [ 0.212600 0.715200 0.072200 0 ]
+ * [ -0.114572 -0.385428 0.500000 128 ]
+ * [ 0.500000 -0.454153 -0.045847 128 ]
+ */
+ { 0x06ce, 0x16e3, 0x024f, 0x0000 },
+ { 0xfc56, 0xf3ac, 0x1000, 0x2000 },
+ { 0x1000, 0xf179, 0xfe89, 0x2000 },
+ },
+ {
+ /*
+ * Limited Range
+ *
+ * [ 0.181906 0.611804 0.061758 16 ]
+ * [ -0.100268 -0.337232 0.437500 128 ]
+ * [ 0.437500 -0.397386 -0.040114 128 ]
+ */
+ { 0x05d2, 0x1394, 0x01fa, 0x0400 },
+ { 0xfccc, 0xf536, 0x0e00, 0x2000 },
+ { 0x0e00, 0xf34a, 0xfeb8, 0x2000 },
+ },
};
/*
- * Conversion between Full Range RGB and Full Range YUV444 using the
- * BT.709 Colorspace
+ * Conversion between Full Range RGB and YUV using the BT.2020 Colorspace
*
- * [ -0.100268 -0.337232 0.437500 128 ]
- * [ 0.437500 -0.397386 -0.040114 128 ]
- * [ 0.181906 0.611804 0.061758 16 ]
- *
- * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
+ * Matrices are signed 2p13 fixed point, with signed 9p6 offsets
*/
-static const u16 vc5_hdmi_csc_full_rgb_to_limited_yuv444_bt709[3][4] = {
- { 0xfccc, 0xf536, 0x0e00, 0x2000 },
- { 0x0e00, 0xf34a, 0xfeb8, 0x2000 },
- { 0x05d2, 0x1394, 0x01fa, 0x0400 },
+static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt2020[2][3][4] = {
+ {
+ /*
+ * Full Range
+ *
+ * [ 0.262700 0.678000 0.059300 0 ]
+ * [ -0.139630 -0.360370 0.500000 128 ]
+ * [ 0.500000 -0.459786 -0.040214 128 ]
+ */
+ { 0x0868, 0x15b2, 0x01e6, 0x0000 },
+ { 0xfb89, 0xf479, 0x1000, 0x2000 },
+ { 0x1000, 0xf14a, 0xfeb8, 0x2000 },
+ },
+ {
+ /* Limited Range
+ *
+ * [ 0.224732 0.580008 0.050729 16 ]
+ * [ -0.122176 -0.315324 0.437500 128 ]
+ * [ 0.437500 -0.402312 -0.035188 128 ]
+ */
+ { 0x082f, 0x1012, 0x031f, 0x0400 },
+ { 0xfb48, 0xf6ba, 0x0e00, 0x2000 },
+ { 0x0e00, 0xf448, 0xfdba, 0x2000 },
+ },
};
static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi,
@@ -1169,6 +1350,48 @@ static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi,
HDMI_WRITE(HDMI_CSC_34_33, (coeffs[2][3] << 16) | coeffs[2][2]);
}
+static void vc5_hdmi_set_csc_coeffs_swap(struct vc4_hdmi *vc4_hdmi,
+ const u16 coeffs[3][4])
+{
+ lockdep_assert_held(&vc4_hdmi->hw_lock);
+
+ /* YUV444 needs the CSC matrices using the channels in a different order */
+ HDMI_WRITE(HDMI_CSC_12_11, (coeffs[1][1] << 16) | coeffs[1][0]);
+ HDMI_WRITE(HDMI_CSC_14_13, (coeffs[1][3] << 16) | coeffs[1][2]);
+ HDMI_WRITE(HDMI_CSC_22_21, (coeffs[2][1] << 16) | coeffs[2][0]);
+ HDMI_WRITE(HDMI_CSC_24_23, (coeffs[2][3] << 16) | coeffs[2][2]);
+ HDMI_WRITE(HDMI_CSC_32_31, (coeffs[0][1] << 16) | coeffs[0][0]);
+ HDMI_WRITE(HDMI_CSC_34_33, (coeffs[0][3] << 16) | coeffs[0][2]);
+}
+
+static const u16
+(*vc5_hdmi_find_yuv_csc_coeffs(struct vc4_hdmi *vc4_hdmi, u32 colorspace, bool limited))[4]
+{
+ switch (colorspace) {
+ case DRM_MODE_COLORIMETRY_SMPTE_170M_YCC:
+ case DRM_MODE_COLORIMETRY_XVYCC_601:
+ case DRM_MODE_COLORIMETRY_SYCC_601:
+ case DRM_MODE_COLORIMETRY_OPYCC_601:
+ case DRM_MODE_COLORIMETRY_BT601_YCC:
+ return vc5_hdmi_csc_full_rgb_to_yuv_bt601[limited];
+
+ default:
+ case DRM_MODE_COLORIMETRY_NO_DATA:
+ case DRM_MODE_COLORIMETRY_BT709_YCC:
+ case DRM_MODE_COLORIMETRY_XVYCC_709:
+ case DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED:
+ case DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT:
+ return vc5_hdmi_csc_full_rgb_to_yuv_bt709[limited];
+
+ case DRM_MODE_COLORIMETRY_BT2020_CYCC:
+ case DRM_MODE_COLORIMETRY_BT2020_YCC:
+ case DRM_MODE_COLORIMETRY_BT2020_RGB:
+ case DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65:
+ case DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER:
+ return vc5_hdmi_csc_full_rgb_to_yuv_bt2020[limited];
+ }
+}
+
static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
struct drm_connector_state *state,
const struct drm_display_mode *mode)
@@ -1176,7 +1399,9 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
struct drm_device *drm = vc4_hdmi->connector.dev;
struct vc4_hdmi_connector_state *vc4_state =
conn_state_to_vc4_hdmi_conn_state(state);
+ unsigned int lim_range = vc4_hdmi_is_full_range(vc4_hdmi, vc4_state) ? 0 : 1;
unsigned long flags;
+ const u16 (*csc)[4];
u32 if_cfg = 0;
u32 if_xbar = 0x543210;
u32 csc_chan_ctl = 0;
@@ -1191,10 +1416,14 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
switch (vc4_state->output_format) {
case VC4_HDMI_OUTPUT_YUV444:
- vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_yuv444_bt709);
+ csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range);
+
+ vc5_hdmi_set_csc_coeffs_swap(vc4_hdmi, csc);
break;
case VC4_HDMI_OUTPUT_YUV422:
+ csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range);
+
csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD,
VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422) |
VC5_MT_CP_CSC_CTL_USE_444_TO_422 |
@@ -1206,16 +1435,13 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
if_cfg |= VC4_SET_FIELD(VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY,
VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422);
- vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_yuv422_bt709);
+ vc5_hdmi_set_csc_coeffs(vc4_hdmi, csc);
break;
case VC4_HDMI_OUTPUT_RGB:
if_xbar = 0x354021;
- if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode))
- vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_rgb);
- else
- vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_unity);
+ vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_rgb[lim_range]);
break;
default:
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index e3619836ca17..934d5d61485a 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -117,6 +117,12 @@ enum vc4_hdmi_output_format {
VC4_HDMI_OUTPUT_YUV420,
};
+enum vc4_hdmi_broadcast_rgb {
+ VC4_HDMI_BROADCAST_RGB_AUTO,
+ VC4_HDMI_BROADCAST_RGB_FULL,
+ VC4_HDMI_BROADCAST_RGB_LIMITED,
+};
+
/* General HDMI hardware state. */
struct vc4_hdmi {
struct vc4_hdmi_audio audio;
@@ -129,6 +135,8 @@ struct vc4_hdmi {
struct delayed_work scrambling_work;
+ struct drm_property *broadcast_rgb_property;
+
struct i2c_adapter *ddc;
void __iomem *hdmicore_regs;
void __iomem *hd_regs;
@@ -222,17 +230,14 @@ struct vc4_hdmi {
enum vc4_hdmi_output_format output_format;
};
-static inline struct vc4_hdmi *
-connector_to_vc4_hdmi(struct drm_connector *connector)
-{
- return container_of(connector, struct vc4_hdmi, connector);
-}
+#define connector_to_vc4_hdmi(_connector) \
+ container_of_const(_connector, struct vc4_hdmi, connector)
static inline struct vc4_hdmi *
encoder_to_vc4_hdmi(struct drm_encoder *encoder)
{
struct vc4_encoder *_encoder = to_vc4_encoder(encoder);
- return container_of(_encoder, struct vc4_hdmi, encoder);
+ return container_of_const(_encoder, struct vc4_hdmi, encoder);
}
struct vc4_hdmi_connector_state {
@@ -240,13 +245,11 @@ struct vc4_hdmi_connector_state {
unsigned long long tmds_char_rate;
unsigned int output_bpc;
enum vc4_hdmi_output_format output_format;
+ enum vc4_hdmi_broadcast_rgb broadcast_rgb;
};
-static inline struct vc4_hdmi_connector_state *
-conn_state_to_vc4_hdmi_conn_state(struct drm_connector_state *conn_state)
-{
- return container_of(conn_state, struct vc4_hdmi_connector_state, base);
-}
+#define conn_state_to_vc4_hdmi_conn_state(_state) \
+ container_of_const(_state, struct vc4_hdmi_connector_state, base)
void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
struct vc4_hdmi_connector_state *vc4_conn_state);
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index a7e3d47c50f4..5495f2a94fa9 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -31,11 +31,8 @@ struct vc4_ctm_state {
int fifo;
};
-static struct vc4_ctm_state *
-to_vc4_ctm_state(const struct drm_private_state *priv)
-{
- return container_of(priv, struct vc4_ctm_state, base);
-}
+#define to_vc4_ctm_state(_state) \
+ container_of_const(_state, struct vc4_ctm_state, base)
struct vc4_load_tracker_state {
struct drm_private_state base;
@@ -43,11 +40,8 @@ struct vc4_load_tracker_state {
u64 membus_load;
};
-static struct vc4_load_tracker_state *
-to_vc4_load_tracker_state(const struct drm_private_state *priv)
-{
- return container_of(priv, struct vc4_load_tracker_state, base);
-}
+#define to_vc4_load_tracker_state(_state) \
+ container_of_const(_state, struct vc4_load_tracker_state, base)
static struct vc4_ctm_state *vc4_get_ctm_state(struct drm_atomic_state *state,
struct drm_private_obj *manager)
@@ -717,7 +711,7 @@ static void vc4_hvs_channels_destroy_state(struct drm_private_obj *obj,
static void vc4_hvs_channels_print_state(struct drm_printer *p,
const struct drm_private_state *state)
{
- struct vc4_hvs_state *hvs_state = to_vc4_hvs_state(state);
+ const struct vc4_hvs_state *hvs_state = to_vc4_hvs_state(state);
unsigned int i;
drm_printf(p, "HVS State\n");
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 97c84a3f5a46..00e713faecd5 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -1334,8 +1334,7 @@ out:
u32 vc4_plane_dlist_size(const struct drm_plane_state *state)
{
- const struct vc4_plane_state *vc4_state =
- container_of(state, typeof(*vc4_state), base);
+ const struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
return vc4_state->dlist_count;
}
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index ef5cab2a3aa9..c5abdec03103 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -168,15 +168,11 @@ struct vc4_txp {
void __iomem *regs;
};
-static inline struct vc4_txp *encoder_to_vc4_txp(struct drm_encoder *encoder)
-{
- return container_of(encoder, struct vc4_txp, encoder.base);
-}
+#define encoder_to_vc4_txp(_encoder) \
+ container_of_const(_encoder, struct vc4_txp, encoder.base)
-static inline struct vc4_txp *connector_to_vc4_txp(struct drm_connector *conn)
-{
- return container_of(conn, struct vc4_txp, connector.base);
-}
+#define connector_to_vc4_txp(_connector) \
+ container_of_const(_connector, struct vc4_txp, connector.base)
static const struct debugfs_reg32 txp_regs[] = {
VC4_REG32(TXP_DST_PTR),
diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index a3782d05cd66..d6e6a1a22eba 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -219,17 +219,11 @@ struct vc4_vec {
writel(val, vec->regs + (offset)); \
} while (0)
-static inline struct vc4_vec *
-encoder_to_vc4_vec(struct drm_encoder *encoder)
-{
- return container_of(encoder, struct vc4_vec, encoder.base);
-}
+#define encoder_to_vc4_vec(_encoder) \
+ container_of_const(_encoder, struct vc4_vec, encoder.base)
-static inline struct vc4_vec *
-connector_to_vc4_vec(struct drm_connector *connector)
-{
- return container_of(connector, struct vc4_vec, connector);
-}
+#define connector_to_vc4_vec(_connector) \
+ container_of_const(_connector, struct vc4_vec, connector)
enum vc4_vec_tv_mode_id {
VC4_VEC_TV_MODE_NTSC,
diff --git a/drivers/gpu/drm/virtio/Makefile b/drivers/gpu/drm/virtio/Makefile
index b99fa4a73b68..d2e1788a8227 100644
--- a/drivers/gpu/drm/virtio/Makefile
+++ b/drivers/gpu/drm/virtio/Makefile
@@ -6,6 +6,6 @@
virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_gem.o virtgpu_vram.o \
virtgpu_display.o virtgpu_vq.o \
virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \
- virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o
+ virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o virtgpu_submit.o
obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio-gpu.o
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index af6ffb696086..4126c384286b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -486,4 +486,8 @@ void virtio_gpu_vram_unmap_dma_buf(struct device *dev,
struct sg_table *sgt,
enum dma_data_direction dir);
+/* virtgpu_submit.c */
+int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file);
+
#endif
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
index da45215a933d..b24b11f25197 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -38,36 +38,6 @@
VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \
VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)
-static int virtio_gpu_fence_event_create(struct drm_device *dev,
- struct drm_file *file,
- struct virtio_gpu_fence *fence,
- uint32_t ring_idx)
-{
- struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
- struct virtio_gpu_fence_event *e = NULL;
- int ret;
-
- if (!(vfpriv->ring_idx_mask & BIT_ULL(ring_idx)))
- return 0;
-
- e = kzalloc(sizeof(*e), GFP_KERNEL);
- if (!e)
- return -ENOMEM;
-
- e->event.type = VIRTGPU_EVENT_FENCE_SIGNALED;
- e->event.length = sizeof(e->event);
-
- ret = drm_event_reserve_init(dev, file, &e->base, &e->event);
- if (ret)
- goto free;
-
- fence->e = e;
- return 0;
-free:
- kfree(e);
- return ret;
-}
-
/* Must be called with &virtio_gpu_fpriv.struct_mutex held. */
static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev,
struct virtio_gpu_fpriv *vfpriv)
@@ -108,158 +78,6 @@ static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data,
&virtio_gpu_map->offset);
}
-/*
- * Usage of execbuffer:
- * Relocations need to take into account the full VIRTIO_GPUDrawable size.
- * However, the command as passed from user space must *not* contain the initial
- * VIRTIO_GPUReleaseInfo struct (first XXX bytes)
- */
-static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
- struct drm_virtgpu_execbuffer *exbuf = data;
- struct virtio_gpu_device *vgdev = dev->dev_private;
- struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
- struct virtio_gpu_fence *out_fence;
- int ret;
- uint32_t *bo_handles = NULL;
- void __user *user_bo_handles = NULL;
- struct virtio_gpu_object_array *buflist = NULL;
- struct sync_file *sync_file;
- int out_fence_fd = -1;
- void *buf;
- uint64_t fence_ctx;
- uint32_t ring_idx;
-
- fence_ctx = vgdev->fence_drv.context;
- ring_idx = 0;
-
- if (vgdev->has_virgl_3d == false)
- return -ENOSYS;
-
- if ((exbuf->flags & ~VIRTGPU_EXECBUF_FLAGS))
- return -EINVAL;
-
- if ((exbuf->flags & VIRTGPU_EXECBUF_RING_IDX)) {
- if (exbuf->ring_idx >= vfpriv->num_rings)
- return -EINVAL;
-
- if (!vfpriv->base_fence_ctx)
- return -EINVAL;
-
- fence_ctx = vfpriv->base_fence_ctx;
- ring_idx = exbuf->ring_idx;
- }
-
- virtio_gpu_create_context(dev, file);
- if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_IN) {
- struct dma_fence *in_fence;
-
- in_fence = sync_file_get_fence(exbuf->fence_fd);
-
- if (!in_fence)
- return -EINVAL;
-
- /*
- * Wait if the fence is from a foreign context, or if the fence
- * array contains any fence from a foreign context.
- */
- ret = 0;
- if (!dma_fence_match_context(in_fence, fence_ctx + ring_idx))
- ret = dma_fence_wait(in_fence, true);
-
- dma_fence_put(in_fence);
- if (ret)
- return ret;
- }
-
- if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_OUT) {
- out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
- if (out_fence_fd < 0)
- return out_fence_fd;
- }
-
- if (exbuf->num_bo_handles) {
- bo_handles = kvmalloc_array(exbuf->num_bo_handles,
- sizeof(uint32_t), GFP_KERNEL);
- if (!bo_handles) {
- ret = -ENOMEM;
- goto out_unused_fd;
- }
-
- user_bo_handles = u64_to_user_ptr(exbuf->bo_handles);
- if (copy_from_user(bo_handles, user_bo_handles,
- exbuf->num_bo_handles * sizeof(uint32_t))) {
- ret = -EFAULT;
- goto out_unused_fd;
- }
-
- buflist = virtio_gpu_array_from_handles(file, bo_handles,
- exbuf->num_bo_handles);
- if (!buflist) {
- ret = -ENOENT;
- goto out_unused_fd;
- }
- kvfree(bo_handles);
- bo_handles = NULL;
- }
-
- buf = vmemdup_user(u64_to_user_ptr(exbuf->command), exbuf->size);
- if (IS_ERR(buf)) {
- ret = PTR_ERR(buf);
- goto out_unused_fd;
- }
-
- if (buflist) {
- ret = virtio_gpu_array_lock_resv(buflist);
- if (ret)
- goto out_memdup;
- }
-
- out_fence = virtio_gpu_fence_alloc(vgdev, fence_ctx, ring_idx);
- if(!out_fence) {
- ret = -ENOMEM;
- goto out_unresv;
- }
-
- ret = virtio_gpu_fence_event_create(dev, file, out_fence, ring_idx);
- if (ret)
- goto out_unresv;
-
- if (out_fence_fd >= 0) {
- sync_file = sync_file_create(&out_fence->f);
- if (!sync_file) {
- dma_fence_put(&out_fence->f);
- ret = -ENOMEM;
- goto out_unresv;
- }
-
- exbuf->fence_fd = out_fence_fd;
- fd_install(out_fence_fd, sync_file->file);
- }
-
- virtio_gpu_cmd_submit(vgdev, buf, exbuf->size,
- vfpriv->ctx_id, buflist, out_fence);
- dma_fence_put(&out_fence->f);
- virtio_gpu_notify(vgdev);
- return 0;
-
-out_unresv:
- if (buflist)
- virtio_gpu_array_unlock_resv(buflist);
-out_memdup:
- kvfree(buf);
-out_unused_fd:
- kvfree(bo_handles);
- if (buflist)
- virtio_gpu_array_put_free(buflist);
-
- if (out_fence_fd >= 0)
- put_unused_fd(out_fence_fd);
-
- return ret;
-}
-
static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
diff --git a/drivers/gpu/drm/virtio/virtgpu_submit.c b/drivers/gpu/drm/virtio/virtgpu_submit.c
new file mode 100644
index 000000000000..cf3c04b16a7a
--- /dev/null
+++ b/drivers/gpu/drm/virtio/virtgpu_submit.c
@@ -0,0 +1,311 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ * All Rights Reserved.
+ *
+ * Authors:
+ * Dave Airlie
+ * Alon Levy
+ */
+
+#include <linux/dma-fence-unwrap.h>
+#include <linux/file.h>
+#include <linux/sync_file.h>
+#include <linux/uaccess.h>
+
+#include <drm/drm_file.h>
+#include <drm/virtgpu_drm.h>
+
+#include "virtgpu_drv.h"
+
+struct virtio_gpu_submit {
+ struct virtio_gpu_object_array *buflist;
+ struct drm_virtgpu_execbuffer *exbuf;
+ struct virtio_gpu_fence *out_fence;
+ struct virtio_gpu_fpriv *vfpriv;
+ struct virtio_gpu_device *vgdev;
+ struct sync_file *sync_file;
+ struct drm_file *file;
+ int out_fence_fd;
+ u64 fence_ctx;
+ u32 ring_idx;
+ void *buf;
+};
+
+static int virtio_gpu_do_fence_wait(struct virtio_gpu_submit *submit,
+ struct dma_fence *in_fence)
+{
+ u32 context = submit->fence_ctx + submit->ring_idx;
+
+ if (dma_fence_match_context(in_fence, context))
+ return 0;
+
+ return dma_fence_wait(in_fence, true);
+}
+
+static int virtio_gpu_dma_fence_wait(struct virtio_gpu_submit *submit,
+ struct dma_fence *fence)
+{
+ struct dma_fence_unwrap itr;
+ struct dma_fence *f;
+ int err;
+
+ dma_fence_unwrap_for_each(f, &itr, fence) {
+ err = virtio_gpu_do_fence_wait(submit, f);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int virtio_gpu_fence_event_create(struct drm_device *dev,
+ struct drm_file *file,
+ struct virtio_gpu_fence *fence,
+ u32 ring_idx)
+{
+ struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
+ struct virtio_gpu_fence_event *e = NULL;
+ int ret;
+
+ if (!(vfpriv->ring_idx_mask & BIT_ULL(ring_idx)))
+ return 0;
+
+ e = kzalloc(sizeof(*e), GFP_KERNEL);
+ if (!e)
+ return -ENOMEM;
+
+ e->event.type = VIRTGPU_EVENT_FENCE_SIGNALED;
+ e->event.length = sizeof(e->event);
+
+ ret = drm_event_reserve_init(dev, file, &e->base, &e->event);
+ if (ret) {
+ kfree(e);
+ return ret;
+ }
+
+ fence->e = e;
+
+ return 0;
+}
+
+static int virtio_gpu_init_submit_buflist(struct virtio_gpu_submit *submit)
+{
+ struct drm_virtgpu_execbuffer *exbuf = submit->exbuf;
+ u32 *bo_handles;
+
+ if (!exbuf->num_bo_handles)
+ return 0;
+
+ bo_handles = kvmalloc_array(exbuf->num_bo_handles, sizeof(*bo_handles),
+ GFP_KERNEL);
+ if (!bo_handles)
+ return -ENOMEM;
+
+ if (copy_from_user(bo_handles, u64_to_user_ptr(exbuf->bo_handles),
+ exbuf->num_bo_handles * sizeof(*bo_handles))) {
+ kvfree(bo_handles);
+ return -EFAULT;
+ }
+
+ submit->buflist = virtio_gpu_array_from_handles(submit->file, bo_handles,
+ exbuf->num_bo_handles);
+ if (!submit->buflist) {
+ kvfree(bo_handles);
+ return -ENOENT;
+ }
+
+ kvfree(bo_handles);
+
+ return 0;
+}
+
+static void virtio_gpu_cleanup_submit(struct virtio_gpu_submit *submit)
+{
+ if (!IS_ERR(submit->buf))
+ kvfree(submit->buf);
+
+ if (submit->buflist)
+ virtio_gpu_array_put_free(submit->buflist);
+
+ if (submit->out_fence_fd >= 0)
+ put_unused_fd(submit->out_fence_fd);
+
+ if (submit->out_fence)
+ dma_fence_put(&submit->out_fence->f);
+
+ if (submit->sync_file)
+ fput(submit->sync_file->file);
+}
+
+static void virtio_gpu_submit(struct virtio_gpu_submit *submit)
+{
+ virtio_gpu_cmd_submit(submit->vgdev, submit->buf, submit->exbuf->size,
+ submit->vfpriv->ctx_id, submit->buflist,
+ submit->out_fence);
+ virtio_gpu_notify(submit->vgdev);
+}
+
+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;
+}
+
+static int virtio_gpu_init_submit(struct virtio_gpu_submit *submit,
+ struct drm_virtgpu_execbuffer *exbuf,
+ struct drm_device *dev,
+ struct drm_file *file,
+ u64 fence_ctx, u32 ring_idx)
+{
+ struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct virtio_gpu_fence *out_fence;
+ int err;
+
+ memset(submit, 0, sizeof(*submit));
+
+ out_fence = virtio_gpu_fence_alloc(vgdev, fence_ctx, ring_idx);
+ if (!out_fence)
+ return -ENOMEM;
+
+ err = virtio_gpu_fence_event_create(dev, file, out_fence, ring_idx);
+ if (err) {
+ dma_fence_put(&out_fence->f);
+ return err;
+ }
+
+ submit->out_fence = out_fence;
+ submit->fence_ctx = fence_ctx;
+ submit->ring_idx = ring_idx;
+ submit->out_fence_fd = -1;
+ submit->vfpriv = vfpriv;
+ submit->vgdev = vgdev;
+ submit->exbuf = exbuf;
+ submit->file = file;
+
+ err = virtio_gpu_init_submit_buflist(submit);
+ if (err)
+ return err;
+
+ submit->buf = vmemdup_user(u64_to_user_ptr(exbuf->command), exbuf->size);
+ if (IS_ERR(submit->buf))
+ return PTR_ERR(submit->buf);
+
+ if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_OUT) {
+ err = get_unused_fd_flags(O_CLOEXEC);
+ if (err < 0)
+ return err;
+
+ submit->out_fence_fd = err;
+
+ submit->sync_file = sync_file_create(&out_fence->f);
+ if (!submit->sync_file)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int virtio_gpu_wait_in_fence(struct virtio_gpu_submit *submit)
+{
+ int ret = 0;
+
+ if (submit->exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_IN) {
+ struct dma_fence *in_fence =
+ sync_file_get_fence(submit->exbuf->fence_fd);
+ if (!in_fence)
+ return -EINVAL;
+
+ /*
+ * Wait if the fence is from a foreign context, or if the
+ * fence array contains any fence from a foreign context.
+ */
+ ret = virtio_gpu_dma_fence_wait(submit, in_fence);
+
+ dma_fence_put(in_fence);
+ }
+
+ return ret;
+}
+
+static void virtio_gpu_install_out_fence_fd(struct virtio_gpu_submit *submit)
+{
+ if (submit->sync_file) {
+ submit->exbuf->fence_fd = submit->out_fence_fd;
+ fd_install(submit->out_fence_fd, submit->sync_file->file);
+ }
+}
+
+static int virtio_gpu_lock_buflist(struct virtio_gpu_submit *submit)
+{
+ if (submit->buflist)
+ return virtio_gpu_array_lock_resv(submit->buflist);
+
+ return 0;
+}
+
+int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
+ u64 fence_ctx = vgdev->fence_drv.context;
+ struct drm_virtgpu_execbuffer *exbuf = data;
+ struct virtio_gpu_submit submit;
+ u32 ring_idx = 0;
+ int ret = -EINVAL;
+
+ if (!vgdev->has_virgl_3d)
+ return -ENOSYS;
+
+ if (exbuf->flags & ~VIRTGPU_EXECBUF_FLAGS)
+ return ret;
+
+ if (exbuf->flags & VIRTGPU_EXECBUF_RING_IDX) {
+ if (exbuf->ring_idx >= vfpriv->num_rings)
+ return ret;
+
+ if (!vfpriv->base_fence_ctx)
+ return ret;
+
+ fence_ctx = vfpriv->base_fence_ctx;
+ ring_idx = exbuf->ring_idx;
+ }
+
+ virtio_gpu_create_context(dev, file);
+
+ ret = virtio_gpu_init_submit(&submit, exbuf, dev, file,
+ fence_ctx, ring_idx);
+ if (ret)
+ goto cleanup;
+
+ /*
+ * Await in-fences in the end of the job submission path to
+ * optimize the path by proceeding directly to the submission
+ * to virtio after the waits.
+ */
+ ret = virtio_gpu_wait_in_fence(&submit);
+ if (ret)
+ goto cleanup;
+
+ ret = virtio_gpu_lock_buflist(&submit);
+ if (ret)
+ goto cleanup;
+
+ virtio_gpu_submit(&submit);
+
+ /*
+ * Set up usr-out data after submitting the job to optimize
+ * the job submission path.
+ */
+ virtio_gpu_install_out_fence_fd(&submit);
+ virtio_gpu_complete_submit(&submit);
+cleanup:
+ virtio_gpu_cleanup_submit(&submit);
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index 8e53fa80742b..906d3df40cdb 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -4,6 +4,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_blend.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_vblank.h>
@@ -53,10 +54,30 @@ static void pre_mul_alpha_blend(struct vkms_frame_info *frame_info,
}
}
-static bool check_y_limit(struct vkms_frame_info *frame_info, int y)
+static int get_y_pos(struct vkms_frame_info *frame_info, int y)
{
- if (y >= frame_info->dst.y1 && y < frame_info->dst.y2)
- return true;
+ if (frame_info->rotation & DRM_MODE_REFLECT_Y)
+ return drm_rect_height(&frame_info->rotated) - y - 1;
+
+ switch (frame_info->rotation & DRM_MODE_ROTATE_MASK) {
+ case DRM_MODE_ROTATE_90:
+ return frame_info->rotated.x2 - y - 1;
+ case DRM_MODE_ROTATE_270:
+ return y + frame_info->rotated.x1;
+ default:
+ return y;
+ }
+}
+
+static bool check_limit(struct vkms_frame_info *frame_info, int pos)
+{
+ if (drm_rotation_90_or_270(frame_info->rotation)) {
+ if (pos >= 0 && pos < drm_rect_width(&frame_info->rotated))
+ return true;
+ } else {
+ if (pos >= frame_info->rotated.y1 && pos < frame_info->rotated.y2)
+ return true;
+ }
return false;
}
@@ -86,6 +107,7 @@ static void blend(struct vkms_writeback_job *wb,
{
struct vkms_plane_state **plane = crtc_state->active_planes;
u32 n_active_planes = crtc_state->num_active_planes;
+ int y_pos;
const struct pixel_argb_u16 background_color = { .a = 0xffff };
@@ -96,10 +118,12 @@ static void blend(struct vkms_writeback_job *wb,
/* The active planes are composed associatively in z-order. */
for (size_t i = 0; i < n_active_planes; i++) {
- if (!check_y_limit(plane[i]->frame_info, y))
+ y_pos = get_y_pos(plane[i]->frame_info, y);
+
+ if (!check_limit(plane[i]->frame_info, y_pos))
continue;
- plane[i]->plane_read(stage_buffer, plane[i]->frame_info, y);
+ vkms_compose_row(stage_buffer, plane[i], y_pos);
pre_mul_alpha_blend(plane[i]->frame_info, stage_buffer,
output_buffer);
}
@@ -107,7 +131,7 @@ static void blend(struct vkms_writeback_job *wb,
*crc32 = crc32_le(*crc32, (void *)output_buffer->pixels, row_size);
if (wb)
- wb->wb_write(&wb->wb_frame_info, output_buffer, y);
+ wb->wb_write(&wb->wb_frame_info, output_buffer, y_pos);
}
}
@@ -118,7 +142,7 @@ static int check_format_funcs(struct vkms_crtc_state *crtc_state,
u32 n_active_planes = crtc_state->num_active_planes;
for (size_t i = 0; i < n_active_planes; i++)
- if (!planes[i]->plane_read)
+ if (!planes[i]->pixel_read)
return -1;
if (active_wb && !active_wb->wb_write)
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index 57bbd32e9beb..515f6772b866 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -161,7 +161,6 @@ static void vkms_atomic_crtc_reset(struct drm_crtc *crtc)
static const struct drm_crtc_funcs vkms_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
- .destroy = drm_crtc_cleanup,
.page_flip = drm_atomic_helper_page_flip,
.reset = vkms_atomic_crtc_reset,
.atomic_duplicate_state = vkms_atomic_crtc_duplicate_state,
@@ -282,8 +281,8 @@ int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
struct vkms_output *vkms_out = drm_crtc_to_vkms_output(crtc);
int ret;
- ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
- &vkms_crtc_funcs, NULL);
+ ret = drmm_crtc_init_with_planes(dev, crtc, primary, cursor,
+ &vkms_crtc_funcs, NULL);
if (ret) {
DRM_ERROR("Failed to init CRTC\n");
return ret;
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index 6d3a2d57d992..e3c9c9571c8d 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -133,8 +133,12 @@ static const struct drm_mode_config_helper_funcs vkms_mode_config_helpers = {
static int vkms_modeset_init(struct vkms_device *vkmsdev)
{
struct drm_device *dev = &vkmsdev->drm;
+ int ret;
+
+ ret = drmm_mode_config_init(dev);
+ if (ret)
+ return ret;
- drm_mode_config_init(dev);
dev->mode_config.funcs = &vkms_mode_funcs;
dev->mode_config.min_width = XRES_MIN;
dev->mode_config.min_height = YRES_MIN;
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index 4a248567efb2..5f1a0a44a78c 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -26,7 +26,9 @@
struct vkms_frame_info {
struct drm_framebuffer *fb;
struct drm_rect src, dst;
+ struct drm_rect rotated;
struct iosys_map map[DRM_FORMAT_MAX_PLANES];
+ unsigned int rotation;
unsigned int offset;
unsigned int pitch;
unsigned int cpp;
@@ -56,8 +58,7 @@ struct vkms_writeback_job {
struct vkms_plane_state {
struct drm_shadow_plane_state base;
struct vkms_frame_info *frame_info;
- void (*plane_read)(struct line_buffer *buffer,
- const struct vkms_frame_info *frame_info, int y);
+ void (*pixel_read)(u8 *src_buffer, struct pixel_argb_u16 *out_pixel);
};
struct vkms_plane {
@@ -155,6 +156,7 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
/* Composer Support */
void vkms_composer_worker(struct work_struct *work);
void vkms_set_composer(struct vkms_output *out, bool enabled);
+void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state *plane, int y);
/* Writeback */
int vkms_enable_writeback_connector(struct vkms_device *vkmsdev);
diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c
index d4950688b3f1..5945da0beba6 100644
--- a/drivers/gpu/drm/vkms/vkms_formats.c
+++ b/drivers/gpu/drm/vkms/vkms_formats.c
@@ -2,6 +2,8 @@
#include <linux/kernel.h>
#include <linux/minmax.h>
+
+#include <drm/drm_blend.h>
#include <drm/drm_rect.h>
#include <drm/drm_fixed.h>
@@ -37,104 +39,93 @@ static void *packed_pixels_addr(const struct vkms_frame_info *frame_info,
static void *get_packed_src_addr(const struct vkms_frame_info *frame_info, int y)
{
int x_src = frame_info->src.x1 >> 16;
- int y_src = y - frame_info->dst.y1 + (frame_info->src.y1 >> 16);
+ int y_src = y - frame_info->rotated.y1 + (frame_info->src.y1 >> 16);
return packed_pixels_addr(frame_info, x_src, y_src);
}
-static void ARGB8888_to_argb_u16(struct line_buffer *stage_buffer,
- const struct vkms_frame_info *frame_info, int y)
+static int get_x_position(const struct vkms_frame_info *frame_info, int limit, int x)
{
- struct pixel_argb_u16 *out_pixels = stage_buffer->pixels;
- u8 *src_pixels = get_packed_src_addr(frame_info, y);
- int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst),
- stage_buffer->n_pixels);
-
- for (size_t x = 0; x < x_limit; x++, src_pixels += 4) {
- /*
- * The 257 is the "conversion ratio". This number is obtained by the
- * (2^16 - 1) / (2^8 - 1) division. Which, in this case, tries to get
- * the best color value in a pixel format with more possibilities.
- * A similar idea applies to others RGB color conversions.
- */
- out_pixels[x].a = (u16)src_pixels[3] * 257;
- out_pixels[x].r = (u16)src_pixels[2] * 257;
- out_pixels[x].g = (u16)src_pixels[1] * 257;
- out_pixels[x].b = (u16)src_pixels[0] * 257;
- }
+ if (frame_info->rotation & (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_270))
+ return limit - x - 1;
+ return x;
}
-static void XRGB8888_to_argb_u16(struct line_buffer *stage_buffer,
- const struct vkms_frame_info *frame_info, int y)
+static void ARGB8888_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel)
{
- struct pixel_argb_u16 *out_pixels = stage_buffer->pixels;
- u8 *src_pixels = get_packed_src_addr(frame_info, y);
- int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst),
- stage_buffer->n_pixels);
+ /*
+ * The 257 is the "conversion ratio". This number is obtained by the
+ * (2^16 - 1) / (2^8 - 1) division. Which, in this case, tries to get
+ * the best color value in a pixel format with more possibilities.
+ * A similar idea applies to others RGB color conversions.
+ */
+ out_pixel->a = (u16)src_pixels[3] * 257;
+ out_pixel->r = (u16)src_pixels[2] * 257;
+ out_pixel->g = (u16)src_pixels[1] * 257;
+ out_pixel->b = (u16)src_pixels[0] * 257;
+}
- for (size_t x = 0; x < x_limit; x++, src_pixels += 4) {
- out_pixels[x].a = (u16)0xffff;
- out_pixels[x].r = (u16)src_pixels[2] * 257;
- out_pixels[x].g = (u16)src_pixels[1] * 257;
- out_pixels[x].b = (u16)src_pixels[0] * 257;
- }
+static void XRGB8888_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel)
+{
+ out_pixel->a = (u16)0xffff;
+ out_pixel->r = (u16)src_pixels[2] * 257;
+ out_pixel->g = (u16)src_pixels[1] * 257;
+ out_pixel->b = (u16)src_pixels[0] * 257;
}
-static void ARGB16161616_to_argb_u16(struct line_buffer *stage_buffer,
- const struct vkms_frame_info *frame_info,
- int y)
+static void ARGB16161616_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel)
{
- struct pixel_argb_u16 *out_pixels = stage_buffer->pixels;
- u16 *src_pixels = get_packed_src_addr(frame_info, y);
- int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst),
- stage_buffer->n_pixels);
+ u16 *pixels = (u16 *)src_pixels;
- for (size_t x = 0; x < x_limit; x++, src_pixels += 4) {
- out_pixels[x].a = le16_to_cpu(src_pixels[3]);
- out_pixels[x].r = le16_to_cpu(src_pixels[2]);
- out_pixels[x].g = le16_to_cpu(src_pixels[1]);
- out_pixels[x].b = le16_to_cpu(src_pixels[0]);
- }
+ out_pixel->a = le16_to_cpu(pixels[3]);
+ out_pixel->r = le16_to_cpu(pixels[2]);
+ out_pixel->g = le16_to_cpu(pixels[1]);
+ out_pixel->b = le16_to_cpu(pixels[0]);
}
-static void XRGB16161616_to_argb_u16(struct line_buffer *stage_buffer,
- const struct vkms_frame_info *frame_info,
- int y)
+static void XRGB16161616_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel)
{
- struct pixel_argb_u16 *out_pixels = stage_buffer->pixels;
- u16 *src_pixels = get_packed_src_addr(frame_info, y);
- int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst),
- stage_buffer->n_pixels);
+ u16 *pixels = (u16 *)src_pixels;
- for (size_t x = 0; x < x_limit; x++, src_pixels += 4) {
- out_pixels[x].a = (u16)0xffff;
- out_pixels[x].r = le16_to_cpu(src_pixels[2]);
- out_pixels[x].g = le16_to_cpu(src_pixels[1]);
- out_pixels[x].b = le16_to_cpu(src_pixels[0]);
- }
+ out_pixel->a = (u16)0xffff;
+ out_pixel->r = le16_to_cpu(pixels[2]);
+ out_pixel->g = le16_to_cpu(pixels[1]);
+ out_pixel->b = le16_to_cpu(pixels[0]);
}
-static void RGB565_to_argb_u16(struct line_buffer *stage_buffer,
- const struct vkms_frame_info *frame_info, int y)
+static void RGB565_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel)
{
- struct pixel_argb_u16 *out_pixels = stage_buffer->pixels;
- u16 *src_pixels = get_packed_src_addr(frame_info, y);
- int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst),
- stage_buffer->n_pixels);
+ u16 *pixels = (u16 *)src_pixels;
s64 fp_rb_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(31));
s64 fp_g_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(63));
- for (size_t x = 0; x < x_limit; x++, src_pixels++) {
- u16 rgb_565 = le16_to_cpu(*src_pixels);
- s64 fp_r = drm_int2fixp((rgb_565 >> 11) & 0x1f);
- s64 fp_g = drm_int2fixp((rgb_565 >> 5) & 0x3f);
- s64 fp_b = drm_int2fixp(rgb_565 & 0x1f);
+ u16 rgb_565 = le16_to_cpu(*pixels);
+ s64 fp_r = drm_int2fixp((rgb_565 >> 11) & 0x1f);
+ s64 fp_g = drm_int2fixp((rgb_565 >> 5) & 0x3f);
+ s64 fp_b = drm_int2fixp(rgb_565 & 0x1f);
+
+ out_pixel->a = (u16)0xffff;
+ out_pixel->r = drm_fixp2int_round(drm_fixp_mul(fp_r, fp_rb_ratio));
+ out_pixel->g = drm_fixp2int_round(drm_fixp_mul(fp_g, fp_g_ratio));
+ out_pixel->b = drm_fixp2int_round(drm_fixp_mul(fp_b, fp_rb_ratio));
+}
+
+void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state *plane, int y)
+{
+ struct pixel_argb_u16 *out_pixels = stage_buffer->pixels;
+ struct vkms_frame_info *frame_info = plane->frame_info;
+ u8 *src_pixels = get_packed_src_addr(frame_info, y);
+ int limit = min_t(size_t, drm_rect_width(&frame_info->dst), stage_buffer->n_pixels);
+
+ for (size_t x = 0; x < limit; x++, src_pixels += frame_info->cpp) {
+ int x_pos = get_x_position(frame_info, limit, x);
+
+ if (drm_rotation_90_or_270(frame_info->rotation))
+ src_pixels = get_packed_src_addr(frame_info, x + frame_info->rotated.y1)
+ + frame_info->cpp * y;
- out_pixels[x].a = (u16)0xffff;
- out_pixels[x].r = drm_fixp2int(drm_fixp_mul(fp_r, fp_rb_ratio));
- out_pixels[x].g = drm_fixp2int(drm_fixp_mul(fp_g, fp_g_ratio));
- out_pixels[x].b = drm_fixp2int(drm_fixp_mul(fp_b, fp_rb_ratio));
+ plane->pixel_read(src_pixels, &out_pixels[x_pos]);
}
}
@@ -241,15 +232,15 @@ static void argb_u16_to_RGB565(struct vkms_frame_info *frame_info,
s64 fp_g = drm_int2fixp(in_pixels[x].g);
s64 fp_b = drm_int2fixp(in_pixels[x].b);
- u16 r = drm_fixp2int(drm_fixp_div(fp_r, fp_rb_ratio));
- u16 g = drm_fixp2int(drm_fixp_div(fp_g, fp_g_ratio));
- u16 b = drm_fixp2int(drm_fixp_div(fp_b, fp_rb_ratio));
+ u16 r = drm_fixp2int_round(drm_fixp_div(fp_r, fp_rb_ratio));
+ u16 g = drm_fixp2int_round(drm_fixp_div(fp_g, fp_g_ratio));
+ u16 b = drm_fixp2int_round(drm_fixp_div(fp_b, fp_rb_ratio));
*dst_pixels = cpu_to_le16(r << 11 | g << 5 | b);
}
}
-void *get_frame_to_line_function(u32 format)
+void *get_pixel_conversion_function(u32 format)
{
switch (format) {
case DRM_FORMAT_ARGB8888:
diff --git a/drivers/gpu/drm/vkms/vkms_formats.h b/drivers/gpu/drm/vkms/vkms_formats.h
index 43b7c1979018..c5b113495d0c 100644
--- a/drivers/gpu/drm/vkms/vkms_formats.h
+++ b/drivers/gpu/drm/vkms/vkms_formats.h
@@ -5,7 +5,7 @@
#include "vkms_drv.h"
-void *get_frame_to_line_function(u32 format);
+void *get_pixel_conversion_function(u32 format);
void *get_line_to_frame_function(u32 format);
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index c41cec7dcb70..e5c625ab8e3e 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -4,6 +4,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_blend.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -12,12 +13,6 @@
#include "vkms_formats.h"
static const u32 vkms_formats[] = {
- DRM_FORMAT_XRGB8888,
- DRM_FORMAT_XRGB16161616,
- DRM_FORMAT_RGB565
-};
-
-static const u32 vkms_plane_formats[] = {
DRM_FORMAT_ARGB8888,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_XRGB16161616,
@@ -117,13 +112,23 @@ static void vkms_plane_atomic_update(struct drm_plane *plane,
frame_info = vkms_plane_state->frame_info;
memcpy(&frame_info->src, &new_state->src, sizeof(struct drm_rect));
memcpy(&frame_info->dst, &new_state->dst, sizeof(struct drm_rect));
+ memcpy(&frame_info->rotated, &new_state->dst, sizeof(struct drm_rect));
frame_info->fb = fb;
memcpy(&frame_info->map, &shadow_plane_state->data, sizeof(frame_info->map));
drm_framebuffer_get(frame_info->fb);
+ frame_info->rotation = drm_rotation_simplify(new_state->rotation, DRM_MODE_ROTATE_0 |
+ DRM_MODE_ROTATE_90 |
+ DRM_MODE_ROTATE_270 |
+ DRM_MODE_REFLECT_X |
+ DRM_MODE_REFLECT_Y);
+
+ drm_rect_rotate(&frame_info->rotated, drm_rect_width(&frame_info->rotated),
+ drm_rect_height(&frame_info->rotated), frame_info->rotation);
+
frame_info->offset = fb->offsets[0];
frame_info->pitch = fb->pitches[0];
frame_info->cpp = fb->format->cpp[0];
- vkms_plane_state->plane_read = get_frame_to_line_function(fmt);
+ vkms_plane_state->pixel_read = get_pixel_conversion_function(fmt);
}
static int vkms_plane_atomic_check(struct drm_plane *plane,
@@ -185,7 +190,7 @@ static void vkms_cleanup_fb(struct drm_plane *plane,
drm_gem_fb_vunmap(fb, shadow_plane_state->map);
}
-static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = {
+static const struct drm_plane_helper_funcs vkms_plane_helper_funcs = {
.atomic_update = vkms_plane_atomic_update,
.atomic_check = vkms_plane_atomic_check,
.prepare_fb = vkms_prepare_fb,
@@ -196,38 +201,19 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
enum drm_plane_type type, int index)
{
struct drm_device *dev = &vkmsdev->drm;
- const struct drm_plane_helper_funcs *funcs;
struct vkms_plane *plane;
- const u32 *formats;
- int nformats;
-
- switch (type) {
- case DRM_PLANE_TYPE_PRIMARY:
- formats = vkms_formats;
- nformats = ARRAY_SIZE(vkms_formats);
- funcs = &vkms_primary_helper_funcs;
- break;
- case DRM_PLANE_TYPE_CURSOR:
- case DRM_PLANE_TYPE_OVERLAY:
- formats = vkms_plane_formats;
- nformats = ARRAY_SIZE(vkms_plane_formats);
- funcs = &vkms_primary_helper_funcs;
- break;
- default:
- formats = vkms_formats;
- nformats = ARRAY_SIZE(vkms_formats);
- funcs = &vkms_primary_helper_funcs;
- break;
- }
plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 1 << index,
&vkms_plane_funcs,
- formats, nformats,
+ vkms_formats, ARRAY_SIZE(vkms_formats),
NULL, type, NULL);
if (IS_ERR(plane))
return plane;
- drm_plane_helper_add(&plane->base, funcs);
+ drm_plane_helper_add(&plane->base, &vkms_plane_helper_funcs);
+
+ drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0,
+ DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK);
return plane;
}
diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h
index 291ac1bab66d..d4621b1ea7f1 100644
--- a/drivers/gpu/ipu-v3/ipu-prv.h
+++ b/drivers/gpu/ipu-v3/ipu-prv.h
@@ -8,6 +8,7 @@
struct ipu_soc;
+#include <linux/io.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/clk.h>
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 4ce012f83253..e11c1c803676 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -788,6 +788,24 @@ config HID_NTRIG
help
Support for N-Trig touch screen.
+config HID_NVIDIA_SHIELD
+ tristate "NVIDIA SHIELD devices"
+ depends on USB_HID
+ depends on BT_HIDP
+ help
+ Support for NVIDIA SHIELD accessories.
+
+ Supported devices:
+ - Thunderstrike (NVIDIA SHIELD Controller 2017)
+
+config NVIDIA_SHIELD_FF
+ bool "NVIDIA SHIELD force feedback support"
+ depends on HID_NVIDIA_SHIELD
+ select INPUT_FF_MEMLESS
+ help
+ Say Y here if you would like to enable force feedback support for
+ NVIDIA SHIELD accessories with haptics capabilities.
+
config HID_ORTEK
tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad"
help
@@ -1285,7 +1303,7 @@ config HID_MCP2221
config HID_KUNIT_TEST
tristate "KUnit tests for HID" if !KUNIT_ALL_TESTS
- depends on KUNIT=y
+ depends on KUNIT
depends on HID_BATTERY_STRENGTH
depends on HID_UCLOGIC
default KUNIT_ALL_TESTS
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 5d37cacbde33..7a9e160158f7 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -87,6 +87,7 @@ obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o
obj-$(CONFIG_HID_NINTENDO) += hid-nintendo.o
obj-$(CONFIG_HID_NTI) += hid-nti.o
obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o
+obj-$(CONFIG_HID_NVIDIA_SHIELD) += hid-nvidia-shield.o
obj-$(CONFIG_HID_ORTEK) += hid-ortek.o
obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o
obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
index d9b7b01900b5..bdb578e0899f 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
@@ -215,7 +215,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
struct device *dev;
u32 feature_report_size;
u32 input_report_size;
- int rc, i, status;
+ int rc, i;
u8 cl_idx;
req_list = &cl_data->req_list;
@@ -286,56 +286,37 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
if (rc)
goto cleanup;
mp2_ops->start(privdata, info);
- status = amd_sfh_wait_for_response
- (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED);
- if (status == SENSOR_ENABLED) {
+ cl_data->sensor_sts[i] = amd_sfh_wait_for_response
+ (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED);
+ }
+
+ for (i = 0; i < cl_data->num_hid_devices; i++) {
+ cl_data->cur_hid_dev = i;
+ if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
cl_data->is_any_sensor_enabled = true;
- cl_data->sensor_sts[i] = SENSOR_ENABLED;
- rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
- if (rc) {
- mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
- status = amd_sfh_wait_for_response
- (privdata, cl_data->sensor_idx[i], SENSOR_DISABLED);
- if (status != SENSOR_ENABLED)
- cl_data->sensor_sts[i] = SENSOR_DISABLED;
- dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
- cl_data->sensor_idx[i],
- get_sensor_name(cl_data->sensor_idx[i]),
- cl_data->sensor_sts[i]);
+ rc = amdtp_hid_probe(i, cl_data);
+ if (rc)
goto cleanup;
- }
} else {
cl_data->sensor_sts[i] = SENSOR_DISABLED;
- dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
- cl_data->sensor_idx[i],
- get_sensor_name(cl_data->sensor_idx[i]),
- cl_data->sensor_sts[i]);
}
dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
cl_data->sensor_sts[i]);
}
+
if (!cl_data->is_any_sensor_enabled ||
(mp2_ops->discovery_status && mp2_ops->discovery_status(privdata) == 0)) {
- amd_sfh_hid_client_deinit(privdata);
- for (i = 0; i < cl_data->num_hid_devices; i++) {
- devm_kfree(dev, cl_data->feature_report[i]);
- devm_kfree(dev, in_data->input_report[i]);
- devm_kfree(dev, cl_data->report_descr[i]);
- }
dev_warn(dev, "Failed to discover, sensors not enabled is %d\n", cl_data->is_any_sensor_enabled);
- return -EOPNOTSUPP;
+ rc = -EOPNOTSUPP;
+ goto cleanup;
}
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
return 0;
cleanup:
+ amd_sfh_hid_client_deinit(privdata);
for (i = 0; i < cl_data->num_hid_devices; i++) {
- if (in_data->sensor_virt_addr[i]) {
- dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
- in_data->sensor_virt_addr[i],
- cl_data->sensor_dma_addr[i]);
- }
devm_kfree(dev, cl_data->feature_report[i]);
devm_kfree(dev, in_data->input_report[i]);
devm_kfree(dev, cl_data->report_descr[i]);
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
index bb8bd7892b67..e9c6413af24a 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
@@ -168,28 +168,16 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
status = amd_sfh_wait_for_response
(privdata, cl_data->sensor_idx[i], ENABLE_SENSOR);
- status = (status == 0) ? SENSOR_ENABLED : SENSOR_DISABLED;
+ cl_data->sensor_sts[i] = (status == 0) ? SENSOR_ENABLED : SENSOR_DISABLED;
+ }
- if (status == SENSOR_ENABLED) {
+ for (i = 0; i < cl_data->num_hid_devices; i++) {
+ cl_data->cur_hid_dev = i;
+ if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
cl_data->is_any_sensor_enabled = true;
- cl_data->sensor_sts[i] = SENSOR_ENABLED;
rc = amdtp_hid_probe(i, cl_data);
- if (rc) {
- mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
- status = amd_sfh_wait_for_response
- (privdata, cl_data->sensor_idx[i], DISABLE_SENSOR);
- if (status == 0)
- status = SENSOR_DISABLED;
- if (status != SENSOR_ENABLED)
- cl_data->sensor_sts[i] = SENSOR_DISABLED;
- dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
- cl_data->sensor_idx[i],
- get_sensor_name(cl_data->sensor_idx[i]),
- cl_data->sensor_sts[i]);
+ if (rc)
goto cleanup;
- }
- } else {
- cl_data->sensor_sts[i] = SENSOR_DISABLED;
}
dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index cc535d2d6e8c..d7b932925730 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -58,7 +58,7 @@ static unsigned int swap_opt_cmd;
module_param(swap_opt_cmd, uint, 0644);
MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\") keys. "
"(For people who want to keep Windows PC keyboard muscle memory. "
- "[0] = as-is, Mac layout. 1 = swapped, Windows layout.)");
+ "[0] = as-is, Mac layout. 1 = swapped, Windows layout., 2 = swapped, Swap only left side)");
static unsigned int swap_ctrl_cmd;
module_param(swap_ctrl_cmd, uint, 0644);
@@ -319,6 +319,12 @@ static const struct apple_key_translation swapped_option_cmd_keys[] = {
{ }
};
+static const struct apple_key_translation swapped_option_cmd_left_keys[] = {
+ { KEY_LEFTALT, KEY_LEFTMETA },
+ { KEY_LEFTMETA, KEY_LEFTALT },
+ { }
+};
+
static const struct apple_key_translation swapped_ctrl_cmd_keys[] = {
{ KEY_LEFTCTRL, KEY_LEFTMETA },
{ KEY_LEFTMETA, KEY_LEFTCTRL },
@@ -416,7 +422,10 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
}
if (swap_opt_cmd) {
- trans = apple_find_translation(swapped_option_cmd_keys, code);
+ if (swap_opt_cmd == 2)
+ trans = apple_find_translation(swapped_option_cmd_left_keys, code);
+ else
+ trans = apple_find_translation(swapped_option_cmd_keys, code);
if (trans)
code = trans->to;
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 01a27579ec02..fd61dba88233 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -884,33 +884,20 @@ static int asus_input_mapping(struct hid_device *hdev,
case 0xb5: asus_map_key_clear(KEY_CALC); break;
case 0xc4: asus_map_key_clear(KEY_KBDILLUMUP); break;
case 0xc5: asus_map_key_clear(KEY_KBDILLUMDOWN); break;
+ case 0xc7: asus_map_key_clear(KEY_KBDILLUMTOGGLE); break;
- /* ASUS touchpad toggle */
- case 0x6b: asus_map_key_clear(KEY_F21); break;
+ case 0x6b: asus_map_key_clear(KEY_F21); break; /* ASUS touchpad toggle */
+ case 0x38: asus_map_key_clear(KEY_PROG1); break; /* ROG key */
+ case 0xba: asus_map_key_clear(KEY_PROG2); break; /* Fn+C ASUS Splendid */
+ case 0x5c: asus_map_key_clear(KEY_PROG3); break; /* Fn+Space Power4Gear */
+ case 0x99: asus_map_key_clear(KEY_PROG4); break; /* Fn+F5 "fan" symbol */
+ case 0xae: asus_map_key_clear(KEY_PROG4); break; /* Fn+F5 "fan" symbol */
+ case 0x92: asus_map_key_clear(KEY_CALC); break; /* Fn+Ret "Calc" symbol */
+ case 0xb2: asus_map_key_clear(KEY_PROG2); break; /* Fn+Left previous aura */
+ case 0xb3: asus_map_key_clear(KEY_PROG3); break; /* Fn+Left next aura */
+ case 0x6a: asus_map_key_clear(KEY_F13); break; /* Screenpad toggle */
+ case 0x4b: asus_map_key_clear(KEY_F14); break; /* Arrows/Pg-Up/Dn toggle */
- /* ROG key */
- case 0x38: asus_map_key_clear(KEY_PROG1); break;
-
- /* Fn+C ASUS Splendid */
- case 0xba: asus_map_key_clear(KEY_PROG2); break;
-
- /* Fn+Space Power4Gear Hybrid */
- case 0x5c: asus_map_key_clear(KEY_PROG3); break;
-
- /* Fn+F5 "fan" symbol on FX503VD */
- case 0x99: asus_map_key_clear(KEY_PROG4); break;
-
- /* Fn+F5 "fan" symbol on N-Key keyboard */
- case 0xae: asus_map_key_clear(KEY_PROG4); break;
-
- /* Fn+Ret "Calc" symbol on N-Key keyboard */
- case 0x92: asus_map_key_clear(KEY_CALC); break;
-
- /* Fn+Left Aura mode previous on N-Key keyboard */
- case 0xb2: asus_map_key_clear(KEY_PROG2); break;
-
- /* Fn+Right Aura mode next on N-Key keyboard */
- case 0xb3: asus_map_key_clear(KEY_PROG3); break;
default:
/* ASUS lazily declares 256 usages, ignore the rest,
@@ -1269,6 +1256,9 @@ static const struct hid_device_id asus_devices[] = {
USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2),
QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
+ USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD3),
+ QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD),
QUIRK_ROG_CLAYMORE_II_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
@@ -1310,4 +1300,4 @@ static struct hid_driver asus_driver = {
};
module_hid_driver(asus_driver);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL"); \ No newline at end of file
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 22623eb4f72f..8992e3c1e769 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2587,64 +2587,84 @@ bool hid_compare_device_paths(struct hid_device *hdev_a,
}
EXPORT_SYMBOL_GPL(hid_compare_device_paths);
+static bool hid_check_device_match(struct hid_device *hdev,
+ struct hid_driver *hdrv,
+ const struct hid_device_id **id)
+{
+ *id = hid_match_device(hdev, hdrv);
+ if (!*id)
+ return false;
+
+ if (hdrv->match)
+ return hdrv->match(hdev, hid_ignore_special_drivers);
+
+ /*
+ * hid-generic implements .match(), so we must be dealing with a
+ * different HID driver here, and can simply check if
+ * hid_ignore_special_drivers is set or not.
+ */
+ return !hid_ignore_special_drivers;
+}
+
+static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv)
+{
+ const struct hid_device_id *id;
+ int ret;
+
+ if (!hid_check_device_match(hdev, hdrv, &id))
+ return -ENODEV;
+
+ hdev->devres_group_id = devres_open_group(&hdev->dev, NULL, GFP_KERNEL);
+ if (!hdev->devres_group_id)
+ return -ENOMEM;
+
+ /* reset the quirks that has been previously set */
+ hdev->quirks = hid_lookup_quirk(hdev);
+ hdev->driver = hdrv;
+
+ if (hdrv->probe) {
+ ret = hdrv->probe(hdev, id);
+ } else { /* default probe */
+ ret = hid_open_report(hdev);
+ if (!ret)
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ }
+
+ /*
+ * Note that we are not closing the devres group opened above so
+ * even resources that were attached to the device after probe is
+ * run are released when hid_device_remove() is executed. This is
+ * needed as some drivers would allocate additional resources,
+ * for example when updating firmware.
+ */
+
+ if (ret) {
+ devres_release_group(&hdev->dev, hdev->devres_group_id);
+ hid_close_report(hdev);
+ hdev->driver = NULL;
+ }
+
+ return ret;
+}
+
static int hid_device_probe(struct device *dev)
{
- struct hid_driver *hdrv = to_hid_driver(dev->driver);
struct hid_device *hdev = to_hid_device(dev);
- const struct hid_device_id *id;
+ struct hid_driver *hdrv = to_hid_driver(dev->driver);
int ret = 0;
- if (down_interruptible(&hdev->driver_input_lock)) {
- ret = -EINTR;
- goto end;
- }
- hdev->io_started = false;
+ if (down_interruptible(&hdev->driver_input_lock))
+ return -EINTR;
+ hdev->io_started = false;
clear_bit(ffs(HID_STAT_REPROBED), &hdev->status);
- if (!hdev->driver) {
- id = hid_match_device(hdev, hdrv);
- if (id == NULL) {
- ret = -ENODEV;
- goto unlock;
- }
-
- if (hdrv->match) {
- if (!hdrv->match(hdev, hid_ignore_special_drivers)) {
- ret = -ENODEV;
- goto unlock;
- }
- } else {
- /*
- * hid-generic implements .match(), so if
- * hid_ignore_special_drivers is set, we can safely
- * return.
- */
- if (hid_ignore_special_drivers) {
- ret = -ENODEV;
- goto unlock;
- }
- }
+ if (!hdev->driver)
+ ret = __hid_device_probe(hdev, hdrv);
- /* reset the quirks that has been previously set */
- hdev->quirks = hid_lookup_quirk(hdev);
- hdev->driver = hdrv;
- if (hdrv->probe) {
- ret = hdrv->probe(hdev, id);
- } else { /* default probe */
- ret = hid_open_report(hdev);
- if (!ret)
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- }
- if (ret) {
- hid_close_report(hdev);
- hdev->driver = NULL;
- }
- }
-unlock:
if (!hdev->io_started)
up(&hdev->driver_input_lock);
-end:
+
return ret;
}
@@ -2662,6 +2682,10 @@ static void hid_device_remove(struct device *dev)
hdrv->remove(hdev);
else /* default remove */
hid_hw_stop(hdev);
+
+ /* Release all devres resources allocated by the driver */
+ devres_release_group(&hdev->dev, hdev->devres_group_id);
+
hid_close_report(hdev);
hdev->driver = NULL;
}
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 5d29abac2300..8a310f8ff20f 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -207,6 +207,7 @@
#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3 0x1822
#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD 0x1866
#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2 0x19b6
+#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD3 0x1a30
#define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b
#define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869
@@ -620,6 +621,7 @@
#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030
#define USB_VENDOR_ID_HP 0x03f0
+#define USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A 0x464a
#define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A 0x0a4a
#define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A 0x0b4a
#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE 0x134a
@@ -934,7 +936,15 @@
#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9
#define USB_DEVICE_ID_MS_POWER_COVER 0x07da
#define USB_DEVICE_ID_MS_SURFACE3_COVER 0x07de
-#define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd
+/*
+ * For a description of the Xbox controller models, refer to:
+ * https://en.wikipedia.org/wiki/Xbox_Wireless_Controller#Summary
+ */
+#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708 0x02fd
+#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708_BLE 0x0b20
+#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1914 0x0b13
+#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797 0x0b05
+#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797_BLE 0x0b22
#define USB_DEVICE_ID_MS_PIXART_MOUSE 0x00cb
#define USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS 0x02e0
#define USB_DEVICE_ID_MS_MOUSE_0783 0x0783
@@ -1005,6 +1015,9 @@
#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18 0x0014
#define USB_DEVICE_ID_NTRIG_DUOSENSE 0x1500
+#define USB_VENDOR_ID_NVIDIA 0x0955
+#define USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER 0x7214
+
#define USB_VENDOR_ID_ONTRAK 0x0a07
#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 5e1a412fd28f..dfe8e09a18de 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -4553,7 +4553,7 @@ static const struct hid_device_id hidpp_devices[] = {
{ /* wireless touchpad T651 */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_LOGITECH_T651),
- .driver_data = HIDPP_QUIRK_CLASS_WTP },
+ .driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT },
{ /* Mouse Logitech Anywhere MX */
LDJ_DEVICE(0x1017), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 },
{ /* Mouse logitech M560 */
@@ -4608,6 +4608,8 @@ static const struct hid_device_id hidpp_devices[] = {
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC086) },
{ /* Logitech G903 Hero Gaming Mouse over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC091) },
+ { /* Logitech G915 TKL Keyboard over USB */
+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC343) },
{ /* Logitech G920 Wheel over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL),
.driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS},
@@ -4630,6 +4632,8 @@ static const struct hid_device_id hidpp_devices[] = {
{ /* MX5500 keyboard over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b),
.driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
+ { /* Logitech G915 TKL keyboard over Bluetooth */
+ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb35f) },
{ /* M-RCQ142 V470 Cordless Laser Mouse over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb008) },
{ /* MX Master mouse over Bluetooth */
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index 071fd093a5f4..9345e2bfd56e 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -446,7 +446,16 @@ static const struct hid_device_id ms_devices[] = {
.driver_data = MS_PRESENTER },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x091B),
.driver_data = MS_SURFACE_DIAL },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER),
+
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708),
+ .driver_data = MS_QUIRK_FF },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708_BLE),
+ .driver_data = MS_QUIRK_FF },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1914),
+ .driver_data = MS_QUIRK_FF },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797),
+ .driver_data = MS_QUIRK_FF },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797_BLE),
.driver_data = MS_QUIRK_FF },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS),
.driver_data = MS_QUIRK_FF },
diff --git a/drivers/hid/hid-nvidia-shield.c b/drivers/hid/hid-nvidia-shield.c
new file mode 100644
index 000000000000..85700cec5eac
--- /dev/null
+++ b/drivers/hid/hid-nvidia-shield.c
@@ -0,0 +1,738 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ *
+ * HID driver for NVIDIA SHIELD peripherals.
+ */
+
+#include <linux/hid.h>
+#include <linux/input-event-codes.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+#include "hid-ids.h"
+
+#define NOT_INIT_STR "NOT INITIALIZED"
+#define android_map_key(c) hid_map_usage(hi, usage, bit, max, EV_KEY, (c))
+
+enum {
+ HID_USAGE_ANDROID_PLAYPAUSE_BTN = 0xcd, /* Double-tap volume slider */
+ HID_USAGE_ANDROID_VOLUMEUP_BTN = 0xe9,
+ HID_USAGE_ANDROID_VOLUMEDOWN_BTN = 0xea,
+ HID_USAGE_ANDROID_SEARCH_BTN = 0x221, /* NVIDIA btn on Thunderstrike */
+ HID_USAGE_ANDROID_HOME_BTN = 0x223,
+ HID_USAGE_ANDROID_BACK_BTN = 0x224,
+};
+
+enum {
+ SHIELD_FW_VERSION_INITIALIZED = 0,
+ SHIELD_BOARD_INFO_INITIALIZED,
+};
+
+enum {
+ THUNDERSTRIKE_FW_VERSION_UPDATE = 0,
+ THUNDERSTRIKE_BOARD_INFO_UPDATE,
+ THUNDERSTRIKE_HAPTICS_UPDATE,
+ THUNDERSTRIKE_LED_UPDATE,
+};
+
+enum {
+ THUNDERSTRIKE_HOSTCMD_REPORT_SIZE = 33,
+ THUNDERSTRIKE_HOSTCMD_REQ_REPORT_ID = 0x4,
+ THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID = 0x3,
+};
+
+enum {
+ THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION = 1,
+ THUNDERSTRIKE_HOSTCMD_ID_LED = 6,
+ THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO = 16,
+ THUNDERSTRIKE_HOSTCMD_ID_USB_INIT = 53,
+ THUNDERSTRIKE_HOSTCMD_ID_HAPTICS = 57,
+ THUNDERSTRIKE_HOSTCMD_ID_BLUETOOTH_INIT = 58,
+};
+
+enum thunderstrike_led_state {
+ THUNDERSTRIKE_LED_OFF = 1,
+ THUNDERSTRIKE_LED_ON = 8,
+} __packed;
+static_assert(sizeof(enum thunderstrike_led_state) == 1);
+
+struct thunderstrike_hostcmd_board_info {
+ __le16 revision;
+ __le16 serial[7];
+};
+
+struct thunderstrike_hostcmd_haptics {
+ u8 motor_left;
+ u8 motor_right;
+};
+
+struct thunderstrike_hostcmd_resp_report {
+ u8 report_id; /* THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID */
+ u8 cmd_id;
+ u8 reserved_at_10;
+
+ union {
+ struct thunderstrike_hostcmd_board_info board_info;
+ struct thunderstrike_hostcmd_haptics motors;
+ __le16 fw_version;
+ enum thunderstrike_led_state led_state;
+ u8 payload[30];
+ };
+} __packed;
+static_assert(sizeof(struct thunderstrike_hostcmd_resp_report) ==
+ THUNDERSTRIKE_HOSTCMD_REPORT_SIZE);
+
+struct thunderstrike_hostcmd_req_report {
+ u8 report_id; /* THUNDERSTRIKE_HOSTCMD_REQ_REPORT_ID */
+ u8 cmd_id;
+ u8 reserved_at_10;
+
+ union {
+ struct {
+ u8 update;
+ enum thunderstrike_led_state state;
+ } led;
+ struct {
+ u8 update;
+ struct thunderstrike_hostcmd_haptics motors;
+ } haptics;
+ };
+ u8 reserved_at_30[27];
+} __packed;
+static_assert(sizeof(struct thunderstrike_hostcmd_req_report) ==
+ THUNDERSTRIKE_HOSTCMD_REPORT_SIZE);
+
+/* Common struct for shield accessories. */
+struct shield_device {
+ struct hid_device *hdev;
+
+ unsigned long initialized_flags;
+ const char *codename;
+ u16 fw_version;
+ struct {
+ u16 revision;
+ char serial_number[15];
+ } board_info;
+};
+
+struct thunderstrike {
+ struct shield_device base;
+
+ /* Sub-devices */
+ struct input_dev *haptics_dev;
+ struct led_classdev led_dev;
+
+ /* Resources */
+ void *req_report_dmabuf;
+ unsigned long update_flags;
+ struct thunderstrike_hostcmd_haptics haptics_val;
+ spinlock_t haptics_update_lock;
+ u8 led_state : 1;
+ enum thunderstrike_led_state led_value;
+ struct work_struct hostcmd_req_work;
+};
+
+static inline void thunderstrike_hostcmd_req_report_init(
+ struct thunderstrike_hostcmd_req_report *report, u8 cmd_id)
+{
+ memset(report, 0, sizeof(*report));
+ report->report_id = THUNDERSTRIKE_HOSTCMD_REQ_REPORT_ID;
+ report->cmd_id = cmd_id;
+}
+
+static inline void shield_strrev(char *dest, size_t len, u16 rev)
+{
+ dest[0] = ('A' - 1) + (rev >> 8);
+ snprintf(&dest[1], len - 1, "%02X", 0xff & rev);
+}
+
+static struct input_dev *shield_allocate_input_dev(struct hid_device *hdev,
+ const char *name_suffix)
+{
+ struct input_dev *idev;
+
+ idev = input_allocate_device();
+ if (!idev)
+ goto err_device;
+
+ idev->id.bustype = hdev->bus;
+ idev->id.vendor = hdev->vendor;
+ idev->id.product = hdev->product;
+ idev->id.version = hdev->version;
+ idev->uniq = hdev->uniq;
+ idev->name = devm_kasprintf(&idev->dev, GFP_KERNEL, "%s %s", hdev->name,
+ name_suffix);
+ if (!idev->name)
+ goto err_name;
+
+ input_set_drvdata(idev, hdev);
+
+ return idev;
+
+err_name:
+ input_free_device(idev);
+err_device:
+ return ERR_PTR(-ENOMEM);
+}
+
+static struct input_dev *shield_haptics_create(
+ struct shield_device *dev,
+ int (*play_effect)(struct input_dev *, void *, struct ff_effect *))
+{
+ struct input_dev *haptics;
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_NVIDIA_SHIELD_FF))
+ return NULL;
+
+ haptics = shield_allocate_input_dev(dev->hdev, "Haptics");
+ if (IS_ERR(haptics))
+ return haptics;
+
+ input_set_capability(haptics, EV_FF, FF_RUMBLE);
+ input_ff_create_memless(haptics, NULL, play_effect);
+
+ ret = input_register_device(haptics);
+ if (ret)
+ goto err;
+
+ return haptics;
+
+err:
+ input_free_device(haptics);
+ return ERR_PTR(ret);
+}
+
+static inline void thunderstrike_send_hostcmd_request(struct thunderstrike *ts)
+{
+ struct thunderstrike_hostcmd_req_report *report = ts->req_report_dmabuf;
+ struct shield_device *shield_dev = &ts->base;
+ int ret;
+
+ ret = hid_hw_raw_request(shield_dev->hdev, report->report_id,
+ ts->req_report_dmabuf,
+ THUNDERSTRIKE_HOSTCMD_REPORT_SIZE,
+ HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
+
+ if (ret < 0) {
+ hid_err(shield_dev->hdev,
+ "Failed to output Thunderstrike HOSTCMD request HID report due to %pe\n",
+ ERR_PTR(ret));
+ }
+}
+
+static void thunderstrike_hostcmd_req_work_handler(struct work_struct *work)
+{
+ struct thunderstrike *ts =
+ container_of(work, struct thunderstrike, hostcmd_req_work);
+ struct thunderstrike_hostcmd_req_report *report;
+ unsigned long flags;
+
+ report = ts->req_report_dmabuf;
+
+ if (test_and_clear_bit(THUNDERSTRIKE_FW_VERSION_UPDATE, &ts->update_flags)) {
+ thunderstrike_hostcmd_req_report_init(
+ report, THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION);
+ thunderstrike_send_hostcmd_request(ts);
+ }
+
+ if (test_and_clear_bit(THUNDERSTRIKE_LED_UPDATE, &ts->update_flags)) {
+ thunderstrike_hostcmd_req_report_init(report, THUNDERSTRIKE_HOSTCMD_ID_LED);
+ report->led.update = 1;
+ report->led.state = ts->led_value;
+ thunderstrike_send_hostcmd_request(ts);
+ }
+
+ if (test_and_clear_bit(THUNDERSTRIKE_BOARD_INFO_UPDATE, &ts->update_flags)) {
+ thunderstrike_hostcmd_req_report_init(
+ report, THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO);
+ thunderstrike_send_hostcmd_request(ts);
+ }
+
+ if (test_and_clear_bit(THUNDERSTRIKE_HAPTICS_UPDATE, &ts->update_flags)) {
+ thunderstrike_hostcmd_req_report_init(
+ report, THUNDERSTRIKE_HOSTCMD_ID_HAPTICS);
+
+ report->haptics.update = 1;
+ spin_lock_irqsave(&ts->haptics_update_lock, flags);
+ report->haptics.motors = ts->haptics_val;
+ spin_unlock_irqrestore(&ts->haptics_update_lock, flags);
+
+ thunderstrike_send_hostcmd_request(ts);
+ }
+}
+
+static inline void thunderstrike_request_firmware_version(struct thunderstrike *ts)
+{
+ set_bit(THUNDERSTRIKE_FW_VERSION_UPDATE, &ts->update_flags);
+ schedule_work(&ts->hostcmd_req_work);
+}
+
+static inline void thunderstrike_request_board_info(struct thunderstrike *ts)
+{
+ set_bit(THUNDERSTRIKE_BOARD_INFO_UPDATE, &ts->update_flags);
+ schedule_work(&ts->hostcmd_req_work);
+}
+
+static inline int
+thunderstrike_update_haptics(struct thunderstrike *ts,
+ struct thunderstrike_hostcmd_haptics *motors)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ts->haptics_update_lock, flags);
+ ts->haptics_val = *motors;
+ spin_unlock_irqrestore(&ts->haptics_update_lock, flags);
+
+ set_bit(THUNDERSTRIKE_HAPTICS_UPDATE, &ts->update_flags);
+ schedule_work(&ts->hostcmd_req_work);
+
+ return 0;
+}
+
+static int thunderstrike_play_effect(struct input_dev *idev, void *data,
+ struct ff_effect *effect)
+{
+ struct hid_device *hdev = input_get_drvdata(idev);
+ struct thunderstrike_hostcmd_haptics motors;
+ struct shield_device *shield_dev;
+ struct thunderstrike *ts;
+
+ if (effect->type != FF_RUMBLE)
+ return 0;
+
+ shield_dev = hid_get_drvdata(hdev);
+ ts = container_of(shield_dev, struct thunderstrike, base);
+
+ /* Thunderstrike motor values range from 0 to 32 inclusively */
+ motors.motor_left = effect->u.rumble.strong_magnitude / 2047;
+ motors.motor_right = effect->u.rumble.weak_magnitude / 2047;
+
+ hid_dbg(hdev, "Thunderstrike FF_RUMBLE request, left: %u right: %u\n",
+ motors.motor_left, motors.motor_right);
+
+ return thunderstrike_update_haptics(ts, &motors);
+}
+
+static enum led_brightness
+thunderstrike_led_get_brightness(struct led_classdev *led)
+{
+ struct hid_device *hdev = to_hid_device(led->dev->parent);
+ struct shield_device *shield_dev = hid_get_drvdata(hdev);
+ struct thunderstrike *ts;
+
+ ts = container_of(shield_dev, struct thunderstrike, base);
+
+ return ts->led_state;
+}
+
+static void thunderstrike_led_set_brightness(struct led_classdev *led,
+ enum led_brightness value)
+{
+ struct hid_device *hdev = to_hid_device(led->dev->parent);
+ struct shield_device *shield_dev = hid_get_drvdata(hdev);
+ struct thunderstrike *ts;
+
+ ts = container_of(shield_dev, struct thunderstrike, base);
+
+ switch (value) {
+ case LED_OFF:
+ ts->led_value = THUNDERSTRIKE_LED_OFF;
+ break;
+ default:
+ ts->led_value = THUNDERSTRIKE_LED_ON;
+ break;
+ }
+
+ set_bit(THUNDERSTRIKE_LED_UPDATE, &ts->update_flags);
+ schedule_work(&ts->hostcmd_req_work);
+}
+
+static void
+thunderstrike_parse_fw_version_payload(struct shield_device *shield_dev,
+ __le16 fw_version)
+{
+ shield_dev->fw_version = le16_to_cpu(fw_version);
+
+ set_bit(SHIELD_FW_VERSION_INITIALIZED, &shield_dev->initialized_flags);
+
+ hid_dbg(shield_dev->hdev, "Thunderstrike firmware version 0x%04X\n",
+ shield_dev->fw_version);
+}
+
+static void
+thunderstrike_parse_board_info_payload(struct shield_device *shield_dev,
+ struct thunderstrike_hostcmd_board_info *board_info)
+{
+ char board_revision_str[4];
+ int i;
+
+ shield_dev->board_info.revision = le16_to_cpu(board_info->revision);
+ for (i = 0; i < 7; ++i) {
+ u16 val = le16_to_cpu(board_info->serial[i]);
+
+ shield_dev->board_info.serial_number[2 * i] = val & 0xFF;
+ shield_dev->board_info.serial_number[2 * i + 1] = val >> 8;
+ }
+ shield_dev->board_info.serial_number[14] = '\0';
+
+ set_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags);
+
+ shield_strrev(board_revision_str, 4, shield_dev->board_info.revision);
+ hid_dbg(shield_dev->hdev,
+ "Thunderstrike BOARD_REVISION_%s (0x%04X) S/N: %s\n",
+ board_revision_str, shield_dev->board_info.revision,
+ shield_dev->board_info.serial_number);
+}
+
+static inline void
+thunderstrike_parse_haptics_payload(struct shield_device *shield_dev,
+ struct thunderstrike_hostcmd_haptics *haptics)
+{
+ hid_dbg(shield_dev->hdev,
+ "Thunderstrike haptics HOSTCMD response, left: %u right: %u\n",
+ haptics->motor_left, haptics->motor_right);
+}
+
+static void
+thunderstrike_parse_led_payload(struct shield_device *shield_dev,
+ enum thunderstrike_led_state led_state)
+{
+ struct thunderstrike *ts = container_of(shield_dev, struct thunderstrike, base);
+
+ switch (led_state) {
+ case THUNDERSTRIKE_LED_OFF:
+ ts->led_state = 0;
+ break;
+ case THUNDERSTRIKE_LED_ON:
+ ts->led_state = 1;
+ break;
+ }
+
+ hid_dbg(shield_dev->hdev, "Thunderstrike led HOSTCMD response, 0x%02X\n", led_state);
+}
+
+static int thunderstrike_parse_report(struct shield_device *shield_dev,
+ struct hid_report *report, u8 *data,
+ int size)
+{
+ struct thunderstrike_hostcmd_resp_report *hostcmd_resp_report;
+ struct thunderstrike *ts =
+ container_of(shield_dev, struct thunderstrike, base);
+ struct hid_device *hdev = shield_dev->hdev;
+
+ switch (report->id) {
+ case THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID:
+ if (size != THUNDERSTRIKE_HOSTCMD_REPORT_SIZE) {
+ hid_err(hdev,
+ "Encountered Thunderstrike HOSTCMD HID report with unexpected size %d\n",
+ size);
+ return -EINVAL;
+ }
+
+ hostcmd_resp_report =
+ (struct thunderstrike_hostcmd_resp_report *)data;
+
+ switch (hostcmd_resp_report->cmd_id) {
+ case THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION:
+ thunderstrike_parse_fw_version_payload(
+ shield_dev, hostcmd_resp_report->fw_version);
+ break;
+ case THUNDERSTRIKE_HOSTCMD_ID_LED:
+ thunderstrike_parse_led_payload(shield_dev, hostcmd_resp_report->led_state);
+ break;
+ case THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO:
+ thunderstrike_parse_board_info_payload(
+ shield_dev, &hostcmd_resp_report->board_info);
+ break;
+ case THUNDERSTRIKE_HOSTCMD_ID_HAPTICS:
+ thunderstrike_parse_haptics_payload(
+ shield_dev, &hostcmd_resp_report->motors);
+ break;
+
+ case THUNDERSTRIKE_HOSTCMD_ID_USB_INIT:
+ case THUNDERSTRIKE_HOSTCMD_ID_BLUETOOTH_INIT:
+ /* May block HOSTCMD requests till received initially */
+ thunderstrike_request_firmware_version(ts);
+ thunderstrike_request_board_info(ts);
+ /* Only HOSTCMD that can be triggered without a request */
+ return 0;
+ default:
+ hid_warn(hdev,
+ "Unhandled Thunderstrike HOSTCMD id %d\n",
+ hostcmd_resp_report->cmd_id);
+ return -ENOENT;
+ }
+
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static inline int thunderstrike_led_create(struct thunderstrike *ts)
+{
+ struct led_classdev *led = &ts->led_dev;
+
+ led->name = "thunderstrike:blue:led";
+ led->max_brightness = 1;
+ led->flags = LED_CORE_SUSPENDRESUME;
+ led->brightness_get = &thunderstrike_led_get_brightness;
+ led->brightness_set = &thunderstrike_led_set_brightness;
+
+ return led_classdev_register(&ts->base.hdev->dev, led);
+}
+
+static struct shield_device *thunderstrike_create(struct hid_device *hdev)
+{
+ struct shield_device *shield_dev;
+ struct thunderstrike *ts;
+ int ret;
+
+ ts = devm_kzalloc(&hdev->dev, sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ return ERR_PTR(-ENOMEM);
+
+ ts->req_report_dmabuf = devm_kzalloc(
+ &hdev->dev, THUNDERSTRIKE_HOSTCMD_REPORT_SIZE, GFP_KERNEL);
+ if (!ts->req_report_dmabuf)
+ return ERR_PTR(-ENOMEM);
+
+ shield_dev = &ts->base;
+ shield_dev->hdev = hdev;
+ shield_dev->codename = "Thunderstrike";
+
+ spin_lock_init(&ts->haptics_update_lock);
+ INIT_WORK(&ts->hostcmd_req_work, thunderstrike_hostcmd_req_work_handler);
+
+ hid_set_drvdata(hdev, shield_dev);
+
+ ret = thunderstrike_led_create(ts);
+ if (ret) {
+ hid_err(hdev, "Failed to create Thunderstrike LED instance\n");
+ return ERR_PTR(ret);
+ }
+
+ ts->haptics_dev = shield_haptics_create(shield_dev, thunderstrike_play_effect);
+ if (IS_ERR(ts->haptics_dev))
+ goto err;
+
+ hid_info(hdev, "Registered Thunderstrike controller\n");
+ return shield_dev;
+
+err:
+ led_classdev_unregister(&ts->led_dev);
+ return ERR_CAST(ts->haptics_dev);
+}
+
+static int android_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit,
+ int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ case HID_USAGE_ANDROID_PLAYPAUSE_BTN:
+ android_map_key(KEY_PLAYPAUSE);
+ break;
+ case HID_USAGE_ANDROID_VOLUMEUP_BTN:
+ android_map_key(KEY_VOLUMEUP);
+ break;
+ case HID_USAGE_ANDROID_VOLUMEDOWN_BTN:
+ android_map_key(KEY_VOLUMEDOWN);
+ break;
+ case HID_USAGE_ANDROID_SEARCH_BTN:
+ android_map_key(BTN_Z);
+ break;
+ case HID_USAGE_ANDROID_HOME_BTN:
+ android_map_key(BTN_MODE);
+ break;
+ case HID_USAGE_ANDROID_BACK_BTN:
+ android_map_key(BTN_SELECT);
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static ssize_t firmware_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hid_device *hdev = to_hid_device(dev);
+ struct shield_device *shield_dev;
+ int ret;
+
+ shield_dev = hid_get_drvdata(hdev);
+
+ if (test_bit(SHIELD_FW_VERSION_INITIALIZED, &shield_dev->initialized_flags))
+ ret = sysfs_emit(buf, "0x%04X\n", shield_dev->fw_version);
+ else
+ ret = sysfs_emit(buf, NOT_INIT_STR "\n");
+
+ return ret;
+}
+
+static DEVICE_ATTR_RO(firmware_version);
+
+static ssize_t hardware_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hid_device *hdev = to_hid_device(dev);
+ struct shield_device *shield_dev;
+ char board_revision_str[4];
+ int ret;
+
+ shield_dev = hid_get_drvdata(hdev);
+
+ if (test_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags)) {
+ shield_strrev(board_revision_str, 4, shield_dev->board_info.revision);
+ ret = sysfs_emit(buf, "%s BOARD_REVISION_%s (0x%04X)\n",
+ shield_dev->codename, board_revision_str,
+ shield_dev->board_info.revision);
+ } else
+ ret = sysfs_emit(buf, NOT_INIT_STR "\n");
+
+ return ret;
+}
+
+static DEVICE_ATTR_RO(hardware_version);
+
+static ssize_t serial_number_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hid_device *hdev = to_hid_device(dev);
+ struct shield_device *shield_dev;
+ int ret;
+
+ shield_dev = hid_get_drvdata(hdev);
+
+ if (test_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags))
+ ret = sysfs_emit(buf, "%s\n", shield_dev->board_info.serial_number);
+ else
+ ret = sysfs_emit(buf, NOT_INIT_STR "\n");
+
+ return ret;
+}
+
+static DEVICE_ATTR_RO(serial_number);
+
+static struct attribute *shield_device_attrs[] = {
+ &dev_attr_firmware_version.attr,
+ &dev_attr_hardware_version.attr,
+ &dev_attr_serial_number.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(shield_device);
+
+static int shield_raw_event(struct hid_device *hdev, struct hid_report *report,
+ u8 *data, int size)
+{
+ struct shield_device *dev = hid_get_drvdata(hdev);
+
+ return thunderstrike_parse_report(dev, report, data, size);
+}
+
+static int shield_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ struct shield_device *shield_dev = NULL;
+ struct thunderstrike *ts;
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ hid_err(hdev, "Parse failed\n");
+ return ret;
+ }
+
+ switch (id->product) {
+ case USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER:
+ shield_dev = thunderstrike_create(hdev);
+ break;
+ }
+
+ if (unlikely(!shield_dev)) {
+ hid_err(hdev, "Failed to identify SHIELD device\n");
+ return -ENODEV;
+ }
+ if (IS_ERR(shield_dev)) {
+ hid_err(hdev, "Failed to create SHIELD device\n");
+ return PTR_ERR(shield_dev);
+ }
+
+ ts = container_of(shield_dev, struct thunderstrike, base);
+
+ ret = hid_hw_start(hdev, HID_CONNECT_HIDINPUT);
+ if (ret) {
+ hid_err(hdev, "Failed to start HID device\n");
+ goto err_haptics;
+ }
+
+ ret = hid_hw_open(hdev);
+ if (ret) {
+ hid_err(hdev, "Failed to open HID device\n");
+ goto err_stop;
+ }
+
+ thunderstrike_request_firmware_version(ts);
+ thunderstrike_request_board_info(ts);
+
+ return ret;
+
+err_stop:
+ hid_hw_stop(hdev);
+err_haptics:
+ if (ts->haptics_dev)
+ input_unregister_device(ts->haptics_dev);
+ return ret;
+}
+
+static void shield_remove(struct hid_device *hdev)
+{
+ struct shield_device *dev = hid_get_drvdata(hdev);
+ struct thunderstrike *ts;
+
+ ts = container_of(dev, struct thunderstrike, base);
+
+ hid_hw_close(hdev);
+ led_classdev_unregister(&ts->led_dev);
+ if (ts->haptics_dev)
+ input_unregister_device(ts->haptics_dev);
+ cancel_work_sync(&ts->hostcmd_req_work);
+ hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id shield_devices[] = {
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NVIDIA,
+ USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NVIDIA,
+ USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, shield_devices);
+
+static struct hid_driver shield_driver = {
+ .name = "shield",
+ .id_table = shield_devices,
+ .input_mapping = android_input_mapping,
+ .probe = shield_probe,
+ .remove = shield_remove,
+ .raw_event = shield_raw_event,
+ .driver = {
+ .dev_groups = shield_device_groups,
+ },
+};
+module_hid_driver(shield_driver);
+
+MODULE_AUTHOR("Rahul Rameshbabu <rrameshbabu@nvidia.com>");
+MODULE_DESCRIPTION("HID Driver for NVIDIA SHIELD peripherals.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c
index de61c08fabea..dabcd054dad9 100644
--- a/drivers/hid/hid-picolcd_fb.c
+++ b/drivers/hid/hid-picolcd_fb.c
@@ -221,7 +221,7 @@ int picolcd_fb_reset(struct picolcd_data *data, int clear)
return 0;
}
-/* Update fb_vbitmap from the screen_base and send changed tiles to device */
+/* Update fb_vbitmap from the screen_buffer and send changed tiles to device */
static void picolcd_fb_update(struct fb_info *info)
{
int chip, tile, n;
@@ -541,7 +541,7 @@ int picolcd_init_framebuffer(struct picolcd_data *data)
dev_err(dev, "can't get a free page for framebuffer\n");
goto err_nomem;
}
- info->screen_base = (char __force __iomem *)fbdata->bitmap;
+ info->screen_buffer = fbdata->bitmap;
info->fix.smem_start = (unsigned long)fbdata->bitmap;
memset(fbdata->vbitmap, 0xff, PICOLCDFB_SIZE);
data->fb_info = info;
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 804fc03600cc..3983b4f282f8 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -96,6 +96,7 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A293), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A), HID_QUIRK_ALWAYS_POLL },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A), HID_QUIRK_ALWAYS_POLL },
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 93e62b161501..e63c56a0d57f 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -272,7 +272,12 @@ static int hidraw_open(struct inode *inode, struct file *file)
goto out;
}
- down_read(&minors_rwsem);
+ /*
+ * Technically not writing to the hidraw_table but a write lock is
+ * required to protect the device refcount. This is symmetrical to
+ * hidraw_release().
+ */
+ down_write(&minors_rwsem);
if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
err = -ENODEV;
goto out_unlock;
@@ -301,7 +306,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
file->private_data = list;
out_unlock:
- up_read(&minors_rwsem);
+ up_write(&minors_rwsem);
out:
if (err < 0)
kfree(list);
diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.c b/drivers/hid/i2c-hid/i2c-hid-acpi.c
index 3a7e2bcb5412..ac918a9ea8d3 100644
--- a/drivers/hid/i2c-hid/i2c-hid-acpi.c
+++ b/drivers/hid/i2c-hid/i2c-hid-acpi.c
@@ -118,7 +118,7 @@ static struct i2c_driver i2c_hid_acpi_driver = {
.acpi_match_table = i2c_hid_acpi_match,
},
- .probe_new = i2c_hid_acpi_probe,
+ .probe = i2c_hid_acpi_probe,
.remove = i2c_hid_core_remove,
.shutdown = i2c_hid_core_shutdown,
};
diff --git a/drivers/hid/i2c-hid/i2c-hid-of-elan.c b/drivers/hid/i2c-hid/i2c-hid-of-elan.c
index 76ddc8be1cbb..029045d9661c 100644
--- a/drivers/hid/i2c-hid/i2c-hid-of-elan.c
+++ b/drivers/hid/i2c-hid/i2c-hid-of-elan.c
@@ -118,7 +118,7 @@ static struct i2c_driver elan_i2c_hid_ts_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(elan_i2c_hid_of_match),
},
- .probe_new = i2c_hid_of_elan_probe,
+ .probe = i2c_hid_of_elan_probe,
.remove = i2c_hid_core_remove,
.shutdown = i2c_hid_core_shutdown,
};
diff --git a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c
index 0060e3dcd775..f1597ad67e7c 100644
--- a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c
+++ b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c
@@ -28,6 +28,7 @@ struct i2c_hid_of_goodix {
struct regulator *vdd;
struct regulator *vddio;
struct gpio_desc *reset_gpio;
+ bool no_reset_during_suspend;
const struct goodix_i2c_hid_timing_data *timings;
};
@@ -37,6 +38,14 @@ static int goodix_i2c_hid_power_up(struct i2chid_ops *ops)
container_of(ops, struct i2c_hid_of_goodix, ops);
int ret;
+ /*
+ * We assert reset GPIO here (instead of during power-down) to ensure
+ * the device will have a clean state after powering up, just like the
+ * normal scenarios will have.
+ */
+ if (ihid_goodix->no_reset_during_suspend)
+ gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1);
+
ret = regulator_enable(ihid_goodix->vdd);
if (ret)
return ret;
@@ -60,7 +69,9 @@ static void goodix_i2c_hid_power_down(struct i2chid_ops *ops)
struct i2c_hid_of_goodix *ihid_goodix =
container_of(ops, struct i2c_hid_of_goodix, ops);
- gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1);
+ if (!ihid_goodix->no_reset_during_suspend)
+ gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1);
+
regulator_disable(ihid_goodix->vddio);
regulator_disable(ihid_goodix->vdd);
}
@@ -91,6 +102,9 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client)
if (IS_ERR(ihid_goodix->vddio))
return PTR_ERR(ihid_goodix->vddio);
+ ihid_goodix->no_reset_during_suspend =
+ of_property_read_bool(client->dev.of_node, "goodix,no-reset-during-suspend");
+
ihid_goodix->timings = device_get_match_data(&client->dev);
return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0);
@@ -114,7 +128,7 @@ static struct i2c_driver goodix_i2c_hid_ts_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(goodix_i2c_hid_of_match),
},
- .probe_new = i2c_hid_of_goodix_probe,
+ .probe = i2c_hid_of_goodix_probe,
.remove = i2c_hid_core_remove,
.shutdown = i2c_hid_core_shutdown,
};
diff --git a/drivers/hid/i2c-hid/i2c-hid-of.c b/drivers/hid/i2c-hid/i2c-hid-of.c
index 855f53092f4e..c4e1fa0273c8 100644
--- a/drivers/hid/i2c-hid/i2c-hid-of.c
+++ b/drivers/hid/i2c-hid/i2c-hid-of.c
@@ -157,7 +157,7 @@ static struct i2c_driver i2c_hid_of_driver = {
.of_match_table = of_match_ptr(i2c_hid_of_match),
},
- .probe_new = i2c_hid_of_probe,
+ .probe = i2c_hid_of_probe,
.remove = i2c_hid_core_remove,
.shutdown = i2c_hid_core_shutdown,
.id_table = i2c_hid_of_id_table,
diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish.h b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
index fc108f19a64c..e99f3a3c65e1 100644
--- a/drivers/hid/intel-ish-hid/ipc/hw-ish.h
+++ b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
@@ -33,6 +33,7 @@
#define ADL_N_DEVICE_ID 0x54FC
#define RPL_S_DEVICE_ID 0x7A78
#define MTL_P_DEVICE_ID 0x7E45
+#define ARL_H_DEVICE_ID 0x7745
#define REVISION_ID_CHT_A0 0x6
#define REVISION_ID_CHT_Ax_SI 0x0
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
index 7120b30ac51d..55cb25038e63 100644
--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -44,6 +44,7 @@ static const struct pci_device_id ish_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_N_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, RPL_S_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MTL_P_DEVICE_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ARL_H_DEVICE_ID)},
{0, }
};
MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 2ccf83837134..174bf03908d7 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1314,7 +1314,7 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
struct input_dev *pen_input = wacom->pen_input;
unsigned char *data = wacom->data;
int number_of_valid_frames = 0;
- int time_interval = 15000000;
+ ktime_t time_interval = 15000000;
ktime_t time_packet_received = ktime_get();
int i;
@@ -1348,7 +1348,7 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
if (number_of_valid_frames) {
if (wacom->hid_data.time_delayed)
time_interval = ktime_get() - wacom->hid_data.time_delayed;
- time_interval /= number_of_valid_frames;
+ time_interval = div_u64(time_interval, number_of_valid_frames);
wacom->hid_data.time_delayed = time_packet_received;
}
@@ -1359,7 +1359,7 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
bool range = frame[0] & 0x20;
bool invert = frame[0] & 0x10;
int frames_number_reversed = number_of_valid_frames - i - 1;
- int event_timestamp = time_packet_received - frames_number_reversed * time_interval;
+ ktime_t event_timestamp = time_packet_received - frames_number_reversed * time_interval;
if (!valid)
continue;
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 1a40bb8c5810..ee21bb260f22 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -324,7 +324,7 @@ struct hid_data {
int ps_connected;
bool pad_input_event_flag;
unsigned short sequence_number;
- int time_delayed;
+ ktime_t time_delayed;
};
struct wacom_remote_data {
diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c
index 38e572faff43..da6a7abd584f 100644
--- a/drivers/hsi/clients/ssi_protocol.c
+++ b/drivers/hsi/clients/ssi_protocol.c
@@ -32,8 +32,6 @@
#include <linux/hsi/hsi.h>
#include <linux/hsi/ssi_protocol.h>
-void ssi_waketest(struct hsi_client *cl, unsigned int enable);
-
#define SSIP_TXQUEUE_LEN 100
#define SSIP_MAX_MTU 65535
#define SSIP_DEFAULT_MTU 4000
diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c
index 26f2c3c01297..84ba8b875199 100644
--- a/drivers/hsi/controllers/omap_ssi_core.c
+++ b/drivers/hsi/controllers/omap_ssi_core.c
@@ -17,6 +17,7 @@
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/delay.h>
+#include <linux/hsi/ssi_protocol.h>
#include <linux/seq_file.h>
#include <linux/scatterlist.h>
#include <linux/interrupt.h>
diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c
index b9495b720f1b..c78d9c9f7371 100644
--- a/drivers/hsi/controllers/omap_ssi_port.c
+++ b/drivers/hsi/controllers/omap_ssi_port.c
@@ -151,23 +151,17 @@ static int ssi_div_set(void *data, u64 val)
DEFINE_DEBUGFS_ATTRIBUTE(ssi_sst_div_fops, ssi_div_get, ssi_div_set, "%llu\n");
-static int ssi_debug_add_port(struct omap_ssi_port *omap_port,
+static void ssi_debug_add_port(struct omap_ssi_port *omap_port,
struct dentry *dir)
{
struct hsi_port *port = to_hsi_port(omap_port->dev);
dir = debugfs_create_dir(dev_name(omap_port->dev), dir);
- if (!dir)
- return -ENOMEM;
omap_port->dir = dir;
debugfs_create_file("regs", S_IRUGO, dir, port, &ssi_port_regs_fops);
dir = debugfs_create_dir("sst", dir);
- if (!dir)
- return -ENOMEM;
debugfs_create_file_unsafe("divisor", 0644, dir, port,
&ssi_sst_div_fops);
-
- return 0;
}
#endif
@@ -1217,11 +1211,7 @@ static int ssi_port_probe(struct platform_device *pd)
pm_runtime_enable(omap_port->pdev);
#ifdef CONFIG_DEBUG_FS
- err = ssi_debug_add_port(omap_port, omap_ssi->dir);
- if (err < 0) {
- pm_runtime_disable(omap_port->pdev);
- goto error;
- }
+ ssi_debug_add_port(omap_port, omap_ssi->dir);
#endif
hsi_add_clients_from_dt(port, np);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index fc640201a2de..307477b8a371 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -255,10 +255,11 @@ config SENSORS_ADT7475
will be called adt7475.
config SENSORS_AHT10
- tristate "Aosong AHT10"
+ tristate "Aosong AHT10, AHT20"
depends on I2C
+ select CRC8
help
- If you say yes here, you get support for the Aosong AHT10
+ If you say yes here, you get support for the Aosong AHT10 and AHT20
temperature and humidity sensors
This driver can also be built as a module. If so, the module
@@ -1097,6 +1098,17 @@ config SENSORS_MAX31760
This driver can also be built as a module. If so, the module
will be called max31760.
+config MAX31827
+ tristate "MAX31827 low-power temperature switch and similar devices"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ If you say yes here you get support for MAX31827, MAX31828 and
+ MAX31829 low-power temperature switches and sensors connected with I2C.
+
+ This driver can also be built as a module. If so, the module
+ will be called max31827.
+
config SENSORS_MAX6620
tristate "Maxim MAX6620 fan controller"
depends on I2C
@@ -2409,6 +2421,18 @@ config SENSORS_ASUS_EC
This driver can also be built as a module. If so, the module
will be called asus_ec_sensors.
+config SENSORS_HP_WMI
+ tristate "HP WMI Sensors"
+ depends on ACPI_WMI
+ help
+ If you say yes here you get support for the ACPI hardware monitoring
+ interface found in HP (and some HP Compaq) business-class computers.
+ Available sensors vary between systems. Temperature and fan speed
+ sensors are the most common.
+
+ This driver can also be built as a module. If so, the module
+ will be called hp_wmi_sensors.
+
endif # ACPI
endif # HWMON
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index cd8c568c80a9..3f4b0fda0998 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SENSORS_ACPI_POWER) += acpi_power_meter.o
obj-$(CONFIG_SENSORS_ATK0110) += asus_atk0110.o
obj-$(CONFIG_SENSORS_ASUS_EC) += asus-ec-sensors.o
obj-$(CONFIG_SENSORS_ASUS_WMI) += asus_wmi_sensors.o
+obj-$(CONFIG_SENSORS_HP_WMI) += hp-wmi-sensors.o
# Native drivers
# asb100, then w83781d go first, as they can override other drivers' addresses.
@@ -149,6 +150,7 @@ obj-$(CONFIG_SENSORS_MAX6642) += max6642.o
obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
obj-$(CONFIG_SENSORS_MAX6697) += max6697.o
obj-$(CONFIG_SENSORS_MAX31790) += max31790.o
+obj-$(CONFIG_MAX31827) += max31827.o
obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
obj-$(CONFIG_SENSORS_MC34VR500) += mc34vr500.o
obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o
@@ -224,4 +226,3 @@ obj-$(CONFIG_SENSORS_PECI) += peci/
obj-$(CONFIG_PMBUS) += pmbus/
ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
-
diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c
index 0afb89c4629d..7f1bef59046f 100644
--- a/drivers/hwmon/ad7414.c
+++ b/drivers/hwmon/ad7414.c
@@ -221,7 +221,7 @@ static struct i2c_driver ad7414_driver = {
.name = "ad7414",
.of_match_table = of_match_ptr(ad7414_of_match),
},
- .probe_new = ad7414_probe,
+ .probe = ad7414_probe,
.id_table = ad7414_id,
};
diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c
index 22bdb7e5b9e0..ffe81e445010 100644
--- a/drivers/hwmon/ad7418.c
+++ b/drivers/hwmon/ad7418.c
@@ -306,7 +306,7 @@ static struct i2c_driver ad7418_driver = {
.name = "ad7418",
.of_match_table = ad7418_dt_ids,
},
- .probe_new = ad7418_probe,
+ .probe = ad7418_probe,
.id_table = ad7418_id,
};
diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c
index 97b330b6c165..46e3c8c50765 100644
--- a/drivers/hwmon/adc128d818.c
+++ b/drivers/hwmon/adc128d818.c
@@ -521,7 +521,7 @@ static struct i2c_driver adc128_driver = {
.name = "adc128d818",
.of_match_table = of_match_ptr(adc128_of_match),
},
- .probe_new = adc128_probe,
+ .probe = adc128_probe,
.remove = adc128_remove,
.id_table = adc128_id,
.detect = adc128_detect,
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index 2dc45e958730..7c15398ebb37 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -488,7 +488,7 @@ static struct i2c_driver adm1021_driver = {
.driver = {
.name = "adm1021",
},
- .probe_new = adm1021_probe,
+ .probe = adm1021_probe,
.id_table = adm1021_id,
.detect = adm1021_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index 2984c4f98496..389382d54752 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -559,7 +559,7 @@ static struct i2c_driver adm1025_driver = {
.driver = {
.name = "adm1025",
},
- .probe_new = adm1025_probe,
+ .probe = adm1025_probe,
.id_table = adm1025_id,
.detect = adm1025_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index 1f084f708743..581d8edf70ea 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -1859,7 +1859,7 @@ static struct i2c_driver adm1026_driver = {
.driver = {
.name = "adm1026",
},
- .probe_new = adm1026_probe,
+ .probe = adm1026_probe,
.id_table = adm1026_id,
.detect = adm1026_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c
index eaf6e5e04aac..9a465f3f71c8 100644
--- a/drivers/hwmon/adm1029.c
+++ b/drivers/hwmon/adm1029.c
@@ -389,7 +389,7 @@ static struct i2c_driver adm1029_driver = {
.driver = {
.name = "adm1029",
},
- .probe_new = adm1029_probe,
+ .probe = adm1029_probe,
.id_table = adm1029_id,
.detect = adm1029_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index b42797bcb5b4..88c7e0d62d08 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -1068,7 +1068,7 @@ static struct i2c_driver adm1031_driver = {
.driver = {
.name = "adm1031",
},
- .probe_new = adm1031_probe,
+ .probe = adm1031_probe,
.id_table = adm1031_id,
.detect = adm1031_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/adm1177.c b/drivers/hwmon/adm1177.c
index bfe070a1b501..60a893f27159 100644
--- a/drivers/hwmon/adm1177.c
+++ b/drivers/hwmon/adm1177.c
@@ -255,7 +255,7 @@ static struct i2c_driver adm1177_driver = {
.name = "adm1177",
.of_match_table = adm1177_dt_ids,
},
- .probe_new = adm1177_probe,
+ .probe = adm1177_probe,
.id_table = adm1177_id,
};
module_i2c_driver(adm1177_driver);
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index 9eb973a38e4b..6dfbeb6acf00 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -819,7 +819,7 @@ static struct i2c_driver adm9240_driver = {
.driver = {
.name = "adm9240",
},
- .probe_new = adm9240_probe,
+ .probe = adm9240_probe,
.id_table = adm9240_id,
.detect = adm9240_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
index 7246198f0901..1932613ec095 100644
--- a/drivers/hwmon/ads7828.c
+++ b/drivers/hwmon/ads7828.c
@@ -208,7 +208,7 @@ static struct i2c_driver ads7828_driver = {
},
.id_table = ads7828_device_ids,
- .probe_new = ads7828_probe,
+ .probe = ads7828_probe,
};
module_i2c_driver(ads7828_driver);
diff --git a/drivers/hwmon/adt7410.c b/drivers/hwmon/adt7410.c
index 0cebf6777239..952506779336 100644
--- a/drivers/hwmon/adt7410.c
+++ b/drivers/hwmon/adt7410.c
@@ -100,7 +100,7 @@ static struct i2c_driver adt7410_driver = {
.name = "adt7410",
.pm = pm_sleep_ptr(&adt7x10_dev_pm_ops),
},
- .probe_new = adt7410_i2c_probe,
+ .probe = adt7410_i2c_probe,
.id_table = adt7410_ids,
.address_list = I2C_ADDRS(0x48, 0x49, 0x4a, 0x4b),
};
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
index 6ba84921614f..45fe4e8aae4e 100644
--- a/drivers/hwmon/adt7411.c
+++ b/drivers/hwmon/adt7411.c
@@ -706,7 +706,7 @@ static struct i2c_driver adt7411_driver = {
.driver = {
.name = "adt7411",
},
- .probe_new = adt7411_probe,
+ .probe = adt7411_probe,
.id_table = adt7411_id,
.detect = adt7411_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c
index 9c0235849d4b..429566c4245d 100644
--- a/drivers/hwmon/adt7462.c
+++ b/drivers/hwmon/adt7462.c
@@ -1819,7 +1819,7 @@ static struct i2c_driver adt7462_driver = {
.driver = {
.name = "adt7462",
},
- .probe_new = adt7462_probe,
+ .probe = adt7462_probe,
.id_table = adt7462_id,
.detect = adt7462_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c
index 64f801b859ff..c4b3a4a18670 100644
--- a/drivers/hwmon/adt7470.c
+++ b/drivers/hwmon/adt7470.c
@@ -1314,7 +1314,7 @@ static struct i2c_driver adt7470_driver = {
.driver = {
.name = "adt7470",
},
- .probe_new = adt7470_probe,
+ .probe = adt7470_probe,
.remove = adt7470_remove,
.id_table = adt7470_id,
.detect = adt7470_detect,
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index 6a6ebcc896b1..c0ce88324ea6 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -1468,7 +1468,7 @@ static int load_config3(const struct i2c_client *client, const char *propname)
u8 config3;
int ret;
- ret = of_property_read_string(client->dev.of_node, propname, &function);
+ ret = device_property_read_string(&client->dev, propname, &function);
if (!ret) {
ret = adt7475_read(REG_CONFIG3);
if (ret < 0)
@@ -1494,7 +1494,7 @@ static int load_config4(const struct i2c_client *client, const char *propname)
u8 config4;
int ret;
- ret = of_property_read_string(client->dev.of_node, propname, &function);
+ ret = device_property_read_string(&client->dev, propname, &function);
if (!ret) {
ret = adt7475_read(REG_CONFIG4);
if (ret < 0)
@@ -1556,8 +1556,8 @@ static int set_property_bit(const struct i2c_client *client, char *property,
u8 *config, u8 bit_index)
{
u32 prop_value = 0;
- int ret = of_property_read_u32(client->dev.of_node, property,
- &prop_value);
+ int ret = device_property_read_u32(&client->dev, property,
+ &prop_value);
if (!ret) {
if (prop_value)
@@ -1821,7 +1821,7 @@ static struct i2c_driver adt7475_driver = {
.name = "adt7475",
.of_match_table = of_match_ptr(adt7475_of_match),
},
- .probe_new = adt7475_probe,
+ .probe = adt7475_probe,
.id_table = adt7475_id,
.detect = adt7475_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/aht10.c b/drivers/hwmon/aht10.c
index b8fe3f7248ba..f136bf3ff40a 100644
--- a/drivers/hwmon/aht10.c
+++ b/drivers/hwmon/aht10.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * aht10.c - Linux hwmon driver for AHT10 Temperature and Humidity sensor
+ * aht10.c - Linux hwmon driver for AHT10/AHT20 Temperature and Humidity sensors
* Copyright (C) 2020 Johannes Cornelis Draaijer
*/
@@ -10,9 +10,13 @@
#include <linux/i2c.h>
#include <linux/ktime.h>
#include <linux/module.h>
+#include <linux/crc8.h>
#define AHT10_MEAS_SIZE 6
+#define AHT20_MEAS_SIZE 7
+#define AHT20_CRC8_POLY 0x31
+
/*
* Poll intervals (in milliseconds)
*/
@@ -44,9 +48,18 @@
#define AHT10_MAX_POLL_INTERVAL_LEN 30
+enum aht10_variant { aht10, aht20 };
+
+static const struct i2c_device_id aht10_id[] = {
+ { "aht10", aht10 },
+ { "aht20", aht20 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, aht10_id);
+
/**
- * struct aht10_data - All the data required to operate an AHT10 chip
- * @client: the i2c client associated with the AHT10
+ * struct aht10_data - All the data required to operate an AHT10/AHT20 chip
+ * @client: the i2c client associated with the AHT10/AHT20
* @lock: a mutex that is used to prevent parallel access to the
* i2c client
* @min_poll_interval: the minimum poll interval
@@ -56,12 +69,14 @@
* the chip from warming up due to the heat it generates.
* If it's unwanted, it can be ignored setting it to
* it to 0. Default value is 2000 ms
- * @previous_poll_time: the previous time that the AHT10
+ * @previous_poll_time: the previous time that the AHT10/AHT20
* was polled
* @temperature: the latest temperature value received from
- * the AHT10
+ * the AHT10/AHT20
* @humidity: the latest humidity value received from the
- * AHT10
+ * AHT10/AHT20
+ * @crc8: crc8 support flag
+ * @meas_size: measurements data size
*/
struct aht10_data {
@@ -75,12 +90,14 @@ struct aht10_data {
ktime_t previous_poll_time;
int temperature;
int humidity;
+ bool crc8;
+ unsigned int meas_size;
};
/**
- * aht10_init() - Initialize an AHT10 chip
- * @data: the data associated with this AHT10 chip
- * Return: 0 if succesfull, 1 if not
+ * aht10_init() - Initialize an AHT10/AHT20 chip
+ * @data: the data associated with this AHT10/AHT20 chip
+ * Return: 0 if successful, 1 if not
*/
static int aht10_init(struct aht10_data *data)
{
@@ -121,54 +138,78 @@ static int aht10_polltime_expired(struct aht10_data *data)
return ktime_after(difference, data->min_poll_interval);
}
+DECLARE_CRC8_TABLE(crc8_table);
+
/**
- * aht10_read_values() - read and parse the raw data from the AHT10
+ * crc8_check() - check crc of the sensor's measurements
+ * @raw_data: data frame received from sensor(including crc as the last byte)
+ * @count: size of the data frame
+ * Return: 0 if successful, 1 if not
+ */
+static int crc8_check(u8 *raw_data, int count)
+{
+ /*
+ * crc calculated on the whole frame(including crc byte) should yield
+ * zero in case of correctly received bytes
+ */
+ return crc8(crc8_table, raw_data, count, CRC8_INIT_VALUE);
+}
+
+/**
+ * aht10_read_values() - read and parse the raw data from the AHT10/AHT20
* @data: the struct aht10_data to use for the lock
- * Return: 0 if succesfull, 1 if not
+ * Return: 0 if successful, 1 if not
*/
static int aht10_read_values(struct aht10_data *data)
{
const u8 cmd_meas[] = {AHT10_CMD_MEAS, 0x33, 0x00};
u32 temp, hum;
int res;
- u8 raw_data[AHT10_MEAS_SIZE];
+ u8 raw_data[AHT20_MEAS_SIZE];
struct i2c_client *client = data->client;
mutex_lock(&data->lock);
- if (aht10_polltime_expired(data)) {
- res = i2c_master_send(client, cmd_meas, sizeof(cmd_meas));
- if (res < 0) {
- mutex_unlock(&data->lock);
- return res;
- }
-
- usleep_range(AHT10_MEAS_DELAY,
- AHT10_MEAS_DELAY + AHT10_DELAY_EXTRA);
-
- res = i2c_master_recv(client, raw_data, AHT10_MEAS_SIZE);
- if (res != AHT10_MEAS_SIZE) {
- mutex_unlock(&data->lock);
- if (res >= 0)
- return -ENODATA;
- else
- return res;
- }
-
- hum = ((u32)raw_data[1] << 12u) |
- ((u32)raw_data[2] << 4u) |
- ((raw_data[3] & 0xF0u) >> 4u);
-
- temp = ((u32)(raw_data[3] & 0x0Fu) << 16u) |
- ((u32)raw_data[4] << 8u) |
- raw_data[5];
-
- temp = ((temp * 625) >> 15u) * 10;
- hum = ((hum * 625) >> 16u) * 10;
-
- data->temperature = (int)temp - 50000;
- data->humidity = hum;
- data->previous_poll_time = ktime_get_boottime();
+ if (!aht10_polltime_expired(data)) {
+ mutex_unlock(&data->lock);
+ return 0;
+ }
+
+ res = i2c_master_send(client, cmd_meas, sizeof(cmd_meas));
+ if (res < 0) {
+ mutex_unlock(&data->lock);
+ return res;
}
+
+ usleep_range(AHT10_MEAS_DELAY, AHT10_MEAS_DELAY + AHT10_DELAY_EXTRA);
+
+ res = i2c_master_recv(client, raw_data, data->meas_size);
+ if (res != data->meas_size) {
+ mutex_unlock(&data->lock);
+ if (res >= 0)
+ return -ENODATA;
+ return res;
+ }
+
+ if (data->crc8 && crc8_check(raw_data, data->meas_size)) {
+ mutex_unlock(&data->lock);
+ return -EIO;
+ }
+
+ hum = ((u32)raw_data[1] << 12u) |
+ ((u32)raw_data[2] << 4u) |
+ ((raw_data[3] & 0xF0u) >> 4u);
+
+ temp = ((u32)(raw_data[3] & 0x0Fu) << 16u) |
+ ((u32)raw_data[4] << 8u) |
+ raw_data[5];
+
+ temp = ((temp * 625) >> 15u) * 10;
+ hum = ((hum * 625) >> 16u) * 10;
+
+ data->temperature = (int)temp - 50000;
+ data->humidity = hum;
+ data->previous_poll_time = ktime_get_boottime();
+
mutex_unlock(&data->lock);
return 0;
}
@@ -290,6 +331,8 @@ static const struct hwmon_chip_info aht10_chip_info = {
static int aht10_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_match_id(aht10_id, client);
+ enum aht10_variant variant = id->driver_data;
struct device *device = &client->dev;
struct device *hwmon_dev;
struct aht10_data *data;
@@ -305,6 +348,17 @@ static int aht10_probe(struct i2c_client *client)
data->min_poll_interval = ms_to_ktime(AHT10_DEFAULT_MIN_POLL_INTERVAL);
data->client = client;
+ switch (variant) {
+ case aht20:
+ data->meas_size = AHT20_MEAS_SIZE;
+ data->crc8 = true;
+ crc8_populate_msb(crc8_table, AHT20_CRC8_POLY);
+ break;
+ default:
+ data->meas_size = AHT10_MEAS_SIZE;
+ break;
+ }
+
mutex_init(&data->lock);
res = aht10_init(data);
@@ -324,23 +378,17 @@ static int aht10_probe(struct i2c_client *client)
return PTR_ERR_OR_ZERO(hwmon_dev);
}
-static const struct i2c_device_id aht10_id[] = {
- { "aht10", 0 },
- { },
-};
-MODULE_DEVICE_TABLE(i2c, aht10_id);
-
static struct i2c_driver aht10_driver = {
.driver = {
.name = "aht10",
},
- .probe_new = aht10_probe,
+ .probe = aht10_probe,
.id_table = aht10_id,
};
module_i2c_driver(aht10_driver);
MODULE_AUTHOR("Johannes Cornelis Draaijer <jcdra1@gmail.com>");
-MODULE_DESCRIPTION("AHT10 Temperature and Humidity sensor driver");
+MODULE_DESCRIPTION("AHT10/AHT20 Temperature and Humidity sensor driver");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c
index 3bfd12ff4b3c..2a7a4b6b0094 100644
--- a/drivers/hwmon/amc6821.c
+++ b/drivers/hwmon/amc6821.c
@@ -939,7 +939,7 @@ static struct i2c_driver amc6821_driver = {
.driver = {
.name = "amc6821",
},
- .probe_new = amc6821_probe,
+ .probe = amc6821_probe,
.id_table = amc6821_id,
.detect = amc6821_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
index a4fcd4ebf76c..a981f7086114 100644
--- a/drivers/hwmon/aquacomputer_d5next.c
+++ b/drivers/hwmon/aquacomputer_d5next.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* hwmon driver for Aquacomputer devices (D5 Next, Farbwerk, Farbwerk 360, Octo,
- * Quadro, High Flow Next, Aquaero, Aquastream Ultimate)
+ * Quadro, High Flow Next, Aquaero, Aquastream Ultimate, Leakshield)
*
* Aquacomputer devices send HID reports (with ID 0x01) every second to report
* sensor values, except for devices that communicate through the
@@ -29,6 +29,7 @@
#define USB_PRODUCT_ID_FARBWERK360 0xf010
#define USB_PRODUCT_ID_OCTO 0xf011
#define USB_PRODUCT_ID_HIGHFLOWNEXT 0xf012
+#define USB_PRODUCT_ID_LEAKSHIELD 0xf014
#define USB_PRODUCT_ID_AQUASTREAMXT 0xf0b6
#define USB_PRODUCT_ID_AQUASTREAMULT 0xf00b
#define USB_PRODUCT_ID_POWERADJUST3 0xf0bd
@@ -36,7 +37,7 @@
enum kinds {
d5next, farbwerk, farbwerk360, octo, quadro,
highflownext, aquaero, poweradjust3, aquastreamult,
- aquastreamxt
+ aquastreamxt, leakshield
};
static const char *const aqc_device_names[] = {
@@ -46,6 +47,7 @@ static const char *const aqc_device_names[] = {
[octo] = "octo",
[quadro] = "quadro",
[highflownext] = "highflownext",
+ [leakshield] = "leakshield",
[aquastreamxt] = "aquastreamxt",
[aquaero] = "aquaero",
[aquastreamult] = "aquastreamultimate",
@@ -93,7 +95,7 @@ static u8 aquaero_secondary_ctrl_report[] = {
#define AQC_FIRMWARE_VERSION 0xD
#define AQC_SENSOR_SIZE 0x02
-#define AQC_TEMP_SENSOR_DISCONNECTED 0x7FFF
+#define AQC_SENSOR_NA 0x7FFF
#define AQC_FAN_PERCENT_OFFSET 0x00
#define AQC_FAN_VOLTAGE_OFFSET 0x02
#define AQC_FAN_CURRENT_OFFSET 0x04
@@ -236,6 +238,21 @@ static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 }; /* Fan speed
#define HIGHFLOWNEXT_5V_VOLTAGE 97
#define HIGHFLOWNEXT_5V_VOLTAGE_USB 99
+/* Specs of the Leakshield */
+#define LEAKSHIELD_NUM_SENSORS 2
+
+/* Sensor report offsets for Leakshield */
+#define LEAKSHIELD_PRESSURE_ADJUSTED 285
+#define LEAKSHIELD_TEMPERATURE_1 265
+#define LEAKSHIELD_TEMPERATURE_2 287
+#define LEAKSHIELD_PRESSURE_MIN 291
+#define LEAKSHIELD_PRESSURE_TARGET 293
+#define LEAKSHIELD_PRESSURE_MAX 295
+#define LEAKSHIELD_PUMP_RPM_IN 101
+#define LEAKSHIELD_FLOW_IN 111
+#define LEAKSHIELD_RESERVOIR_VOLUME 313
+#define LEAKSHIELD_RESERVOIR_FILLED 311
+
/* Specs of the Aquastream XT pump */
#define AQUASTREAMXT_SERIAL_START 0x3a
#define AQUASTREAMXT_FIRMWARE_VERSION 0x32
@@ -411,6 +428,20 @@ static const char *const label_highflownext_voltage[] = {
"+5V USB voltage"
};
+/* Labels for Leakshield */
+static const char *const label_leakshield_temp_sensors[] = {
+ "Temperature 1",
+ "Temperature 2"
+};
+
+static const char *const label_leakshield_fan_speed[] = {
+ "Pressure [ubar]",
+ "User-Provided Pump Speed",
+ "User-Provided Flow [dL/h]",
+ "Reservoir Volume [ml]",
+ "Reservoir Filled [ml]",
+};
+
/* Labels for Aquastream XT */
static const char *const label_aquastreamxt_temp_sensors[] = {
"Fan IC temp",
@@ -529,7 +560,10 @@ struct aqc_data {
/* Sensor values */
s32 temp_input[20]; /* Max 4 physical and 16 virtual or 8 physical and 12 virtual */
- u16 speed_input[8];
+ s32 speed_input[8];
+ u32 speed_input_min[1];
+ u32 speed_input_target[1];
+ u32 speed_input_max[1];
u32 power_input[8];
u16 voltage_input[8];
u16 current_input[8];
@@ -747,6 +781,11 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
if (channel < 3)
return 0444;
break;
+ case leakshield:
+ /* Special case for Leakshield sensors */
+ if (channel < 5)
+ return 0444;
+ break;
case aquaero:
case quadro:
/* Special case to support flow sensors */
@@ -764,6 +803,13 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
if (priv->kind == quadro && channel == priv->num_fans)
return 0644;
break;
+ case hwmon_fan_min:
+ case hwmon_fan_max:
+ case hwmon_fan_target:
+ /* Special case for Leakshield pressure sensor */
+ if (priv->kind == leakshield && channel == 0)
+ return 0444;
+ break;
default:
break;
}
@@ -938,8 +984,20 @@ static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
case hwmon_fan:
switch (attr) {
case hwmon_fan_input:
+ if (priv->speed_input[channel] == -ENODATA)
+ return -ENODATA;
+
*val = priv->speed_input[channel];
break;
+ case hwmon_fan_min:
+ *val = priv->speed_input_min[channel];
+ break;
+ case hwmon_fan_max:
+ *val = priv->speed_input_max[channel];
+ break;
+ case hwmon_fan_target:
+ *val = priv->speed_input_target[channel];
+ break;
case hwmon_fan_pulses:
ret = aqc_get_ctrl_val(priv, priv->flow_pulses_ctrl_offset,
val, AQC_BE16);
@@ -1151,7 +1209,8 @@ static const struct hwmon_channel_info * const aqc_info[] = {
HWMON_T_INPUT | HWMON_T_LABEL,
HWMON_T_INPUT | HWMON_T_LABEL),
HWMON_CHANNEL_INFO(fan,
- HWMON_F_INPUT | HWMON_F_LABEL,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
+ HWMON_F_TARGET,
HWMON_F_INPUT | HWMON_F_LABEL,
HWMON_F_INPUT | HWMON_F_LABEL,
HWMON_F_INPUT | HWMON_F_LABEL,
@@ -1224,7 +1283,7 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
sensor_value = get_unaligned_be16(data +
priv->temp_sensor_start_offset +
i * AQC_SENSOR_SIZE);
- if (sensor_value == AQC_TEMP_SENSOR_DISCONNECTED)
+ if (sensor_value == AQC_SENSOR_NA)
priv->temp_input[i] = -ENODATA;
else
priv->temp_input[i] = sensor_value * 10;
@@ -1235,7 +1294,7 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
sensor_value = get_unaligned_be16(data +
priv->virtual_temp_sensor_start_offset +
j * AQC_SENSOR_SIZE);
- if (sensor_value == AQC_TEMP_SENSOR_DISCONNECTED)
+ if (sensor_value == AQC_SENSOR_NA)
priv->temp_input[i] = -ENODATA;
else
priv->temp_input[i] = sensor_value * 10;
@@ -1277,7 +1336,7 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
sensor_value = get_unaligned_be16(data +
priv->calc_virt_temp_sensor_start_offset +
j * AQC_SENSOR_SIZE);
- if (sensor_value == AQC_TEMP_SENSOR_DISCONNECTED)
+ if (sensor_value == AQC_SENSOR_NA)
priv->temp_input[i] = -ENODATA;
else
priv->temp_input[i] = sensor_value * 10;
@@ -1314,6 +1373,28 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
priv->speed_input[1] = get_unaligned_be16(data + HIGHFLOWNEXT_WATER_QUALITY);
priv->speed_input[2] = get_unaligned_be16(data + HIGHFLOWNEXT_CONDUCTIVITY);
break;
+ case leakshield:
+ priv->speed_input[0] =
+ ((s16)get_unaligned_be16(data + LEAKSHIELD_PRESSURE_ADJUSTED)) * 100;
+ priv->speed_input_min[0] = get_unaligned_be16(data + LEAKSHIELD_PRESSURE_MIN) * 100;
+ priv->speed_input_target[0] =
+ get_unaligned_be16(data + LEAKSHIELD_PRESSURE_TARGET) * 100;
+ priv->speed_input_max[0] = get_unaligned_be16(data + LEAKSHIELD_PRESSURE_MAX) * 100;
+
+ priv->speed_input[1] = get_unaligned_be16(data + LEAKSHIELD_PUMP_RPM_IN);
+ if (priv->speed_input[1] == AQC_SENSOR_NA)
+ priv->speed_input[1] = -ENODATA;
+
+ priv->speed_input[2] = get_unaligned_be16(data + LEAKSHIELD_FLOW_IN);
+ if (priv->speed_input[2] == AQC_SENSOR_NA)
+ priv->speed_input[2] = -ENODATA;
+
+ priv->speed_input[3] = get_unaligned_be16(data + LEAKSHIELD_RESERVOIR_VOLUME);
+ priv->speed_input[4] = get_unaligned_be16(data + LEAKSHIELD_RESERVOIR_FILLED);
+
+ /* Second temp sensor is not positioned after the first one, read it here */
+ priv->temp_input[1] = get_unaligned_be16(data + LEAKSHIELD_TEMPERATURE_2) * 10;
+ break;
default:
break;
}
@@ -1571,6 +1652,25 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->power_label = label_highflownext_power;
priv->voltage_label = label_highflownext_voltage;
break;
+ case USB_PRODUCT_ID_LEAKSHIELD:
+ /*
+ * Choose the right Leakshield device, because
+ * the other one acts as a keyboard
+ */
+ if (hdev->type != 2) {
+ ret = -ENODEV;
+ goto fail_and_close;
+ }
+
+ priv->kind = leakshield;
+
+ priv->num_fans = 0;
+ priv->num_temp_sensors = LEAKSHIELD_NUM_SENSORS;
+ priv->temp_sensor_start_offset = LEAKSHIELD_TEMPERATURE_1;
+
+ priv->temp_label = label_leakshield_temp_sensors;
+ priv->speed_label = label_leakshield_fan_speed;
+ break;
case USB_PRODUCT_ID_AQUASTREAMXT:
priv->kind = aquastreamxt;
@@ -1707,6 +1807,7 @@ static const struct hid_device_id aqc_table[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_OCTO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_QUADRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_HIGHFLOWNEXT) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_LEAKSHIELD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_AQUASTREAMXT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_AQUASTREAMULT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_POWERADJUST3) },
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index ce4da836765c..974521e9b6b4 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -223,7 +223,7 @@ static struct i2c_driver asb100_driver = {
.driver = {
.name = "asb100",
},
- .probe_new = asb100_probe,
+ .probe = asb100_probe,
.remove = asb100_remove,
.id_table = asb100_id,
.detect = asb100_detect,
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c
index 54595454537b..87e186700849 100644
--- a/drivers/hwmon/asc7621.c
+++ b/drivers/hwmon/asc7621.c
@@ -1191,7 +1191,7 @@ static struct i2c_driver asc7621_driver = {
.driver = {
.name = "asc7621",
},
- .probe_new = asc7621_probe,
+ .probe = asc7621_probe,
.remove = asc7621_remove,
.id_table = asc7621_id,
.detect = asc7621_detect,
diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c
index e5be0cf472fc..f52a539eb33e 100644
--- a/drivers/hwmon/asus-ec-sensors.c
+++ b/drivers/hwmon/asus-ec-sensors.c
@@ -101,6 +101,8 @@ enum ec_sensors {
ec_sensor_temp_chipset,
/* CPU temperature [℃] */
ec_sensor_temp_cpu,
+ /* CPU package temperature [℃] */
+ ec_sensor_temp_cpu_package,
/* motherboard temperature [℃] */
ec_sensor_temp_mb,
/* "T_Sensor" temperature sensor reading [℃] */
@@ -139,6 +141,7 @@ enum ec_sensors {
#define SENSOR_TEMP_CHIPSET BIT(ec_sensor_temp_chipset)
#define SENSOR_TEMP_CPU BIT(ec_sensor_temp_cpu)
+#define SENSOR_TEMP_CPU_PACKAGE BIT(ec_sensor_temp_cpu_package)
#define SENSOR_TEMP_MB BIT(ec_sensor_temp_mb)
#define SENSOR_TEMP_T_SENSOR BIT(ec_sensor_temp_t_sensor)
#define SENSOR_TEMP_VRM BIT(ec_sensor_temp_vrm)
@@ -161,6 +164,7 @@ enum board_family {
family_unknown,
family_amd_400_series,
family_amd_500_series,
+ family_amd_600_series,
family_intel_300_series,
family_intel_600_series
};
@@ -233,6 +237,19 @@ static const struct ec_sensor_info sensors_family_amd_500[] = {
EC_SENSOR("Extra_3", hwmon_temp, 1, 0x01, 0x0c),
};
+static const struct ec_sensor_info sensors_family_amd_600[] = {
+ [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x30),
+ [ec_sensor_temp_cpu_package] = EC_SENSOR("CPU Package", hwmon_temp, 1, 0x00, 0x31),
+ [ec_sensor_temp_mb] =
+ EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x32),
+ [ec_sensor_temp_vrm] =
+ EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x33),
+ [ec_sensor_temp_water_in] =
+ EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00),
+ [ec_sensor_temp_water_out] =
+ EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01),
+};
+
static const struct ec_sensor_info sensors_family_intel_300[] = {
[ec_sensor_temp_chipset] =
EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a),
@@ -319,6 +336,14 @@ static const struct ec_board_info board_info_pro_ws_x570_ace = {
.family = family_amd_500_series,
};
+static const struct ec_board_info board_info_crosshair_x670e_hero = {
+ .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE |
+ SENSOR_TEMP_MB | SENSOR_TEMP_VRM |
+ SENSOR_SET_TEMP_WATER,
+ .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX,
+ .family = family_amd_600_series,
+};
+
static const struct ec_board_info board_info_crosshair_viii_dark_hero = {
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
SENSOR_TEMP_T_SENSOR |
@@ -463,6 +488,8 @@ static const struct dmi_system_id dmi_table[] = {
&board_info_crosshair_viii_hero),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII HERO (WI-FI)",
&board_info_crosshair_viii_hero),
+ DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR X670E HERO",
+ &board_info_crosshair_x670e_hero),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS XI HERO",
&board_info_maximus_xi_hero),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS XI HERO (WI-FI)",
@@ -946,6 +973,9 @@ static int asus_ec_probe(struct platform_device *pdev)
case family_amd_500_series:
ec_data->sensors_info = sensors_family_amd_500;
break;
+ case family_amd_600_series:
+ ec_data->sensors_info = sensors_family_amd_600;
+ break;
case family_intel_300_series:
ec_data->sensors_info = sensors_family_intel_300;
break;
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index 118297ea1dcf..d1de020abec6 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -288,7 +288,7 @@ static struct i2c_driver atxp1_driver = {
.driver = {
.name = "atxp1",
},
- .probe_new = atxp1_probe,
+ .probe = atxp1_probe,
.id_table = atxp1_id,
};
diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
index dc24c566d08b..904890598c11 100644
--- a/drivers/hwmon/corsair-psu.c
+++ b/drivers/hwmon/corsair-psu.c
@@ -32,23 +32,25 @@
* but it is better to not rely on this (it is also hard to parse)
* - the driver uses raw events to be accessible from userspace (though this is not really
* supported, it is just there for convenience, may be removed in the future)
- * - a reply always start with the length and command in the same order the request used it
+ * - a reply always starts with the length and command in the same order the request used it
* - length of the reply data is specific to the command used
* - some of the commands work on a rail and can be switched to a specific rail (0 = 12v,
* 1 = 5v, 2 = 3.3v)
* - the format of the init command 0xFE is swapped length/command bytes
* - parameter bytes amount and values are specific to the command (rail setting is the only
- * for now that uses non-zero values)
- * - there are much more commands, especially for configuring the device, but they are not
- * supported because a wrong command/length can lockup the micro-controller
+ * one for now that uses non-zero values)
* - the driver supports debugfs for values not fitting into the hwmon class
- * - not every device class (HXi, RMi or AXi) supports all commands
- * - it is a pure sensors reading driver (will not support configuring)
+ * - not every device class (HXi or RMi) supports all commands
+ * - if configured wrong the PSU resets or shuts down, often before actually hitting the
+ * reported critical temperature
+ * - new models like HX1500i Series 2023 have changes in the reported vendor and product
+ * strings, both are slightly longer now, report vendor and product in one string and are
+ * the same now
*/
#define DRIVER_NAME "corsair-psu"
-#define REPLY_SIZE 16 /* max length of a reply to a single command */
+#define REPLY_SIZE 24 /* max length of a reply to a single command */
#define CMD_BUFFER_SIZE 64
#define CMD_TIMEOUT_MS 250
#define SECONDS_PER_HOUR (60 * 60)
@@ -58,7 +60,8 @@
#define OCP_MULTI_RAIL 0x02
#define PSU_CMD_SELECT_RAIL 0x00 /* expects length 2 */
-#define PSU_CMD_RAIL_VOLTS_HCRIT 0x40 /* the rest of the commands expect length 3 */
+#define PSU_CMD_FAN_PWM 0x3B /* the rest of the commands expect length 3 */
+#define PSU_CMD_RAIL_VOLTS_HCRIT 0x40
#define PSU_CMD_RAIL_VOLTS_LCRIT 0x44
#define PSU_CMD_RAIL_AMPS_HCRIT 0x46
#define PSU_CMD_TEMP_HCRIT 0x4F
@@ -76,6 +79,7 @@
#define PSU_CMD_UPTIME 0xD2
#define PSU_CMD_OCPMODE 0xD8
#define PSU_CMD_TOTAL_WATTS 0xEE
+#define PSU_CMD_FAN_PWM_ENABLE 0xF0
#define PSU_CMD_INIT 0xFE
#define L_IN_VOLTS "v_in"
@@ -145,6 +149,14 @@ static int corsairpsu_linear11_to_int(const u16 val, const int scale)
return (exp >= 0) ? (result << exp) : (result >> -exp);
}
+/* the micro-controller uses percentage values to control pwm */
+static int corsairpsu_dutycycle_to_pwm(const long dutycycle)
+{
+ const int result = (256 << 16) / 100;
+
+ return (result * dutycycle) >> 16;
+}
+
static int corsairpsu_usb_cmd(struct corsairpsu_data *priv, u8 p0, u8 p1, u8 p2, void *data)
{
unsigned long time;
@@ -244,8 +256,8 @@ static int corsairpsu_get_value(struct corsairpsu_data *priv, u8 cmd, u8 rail, l
/*
* the biggest value here comes from the uptime command and to exceed MAXINT total uptime
* needs to be about 68 years, the rest are u16 values and the biggest value coming out of
- * the LINEAR11 conversion are the watts values which are about 1200 for the strongest psu
- * supported (HX1200i)
+ * the LINEAR11 conversion are the watts values which are about 1500 for the strongest psu
+ * supported (HX1500i)
*/
tmp = ((long)data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0];
switch (cmd) {
@@ -264,6 +276,24 @@ static int corsairpsu_get_value(struct corsairpsu_data *priv, u8 cmd, u8 rail, l
case PSU_CMD_FAN:
*val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1);
break;
+ case PSU_CMD_FAN_PWM_ENABLE:
+ *val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1);
+ /*
+ * 0 = automatic mode, means the micro-controller controls the fan using a plan
+ * which can be modified, but changing this plan is not supported by this
+ * driver, the matching PWM mode is automatic fan speed control = PWM 2
+ * 1 = fixed mode, fan runs at a fixed speed represented by a percentage
+ * value 0-100, this matches the PWM manual fan speed control = PWM 1
+ * technically there is no PWM no fan speed control mode, it would be a combination
+ * of 1 at 100%
+ */
+ if (*val == 0)
+ *val = 2;
+ break;
+ case PSU_CMD_FAN_PWM:
+ *val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1);
+ *val = corsairpsu_dutycycle_to_pwm(*val);
+ break;
case PSU_CMD_RAIL_WATTS:
case PSU_CMD_TOTAL_WATTS:
*val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1000000);
@@ -349,6 +379,18 @@ static umode_t corsairpsu_hwmon_fan_is_visible(const struct corsairpsu_data *pri
}
}
+static umode_t corsairpsu_hwmon_pwm_is_visible(const struct corsairpsu_data *priv, u32 attr,
+ int channel)
+{
+ switch (attr) {
+ case hwmon_pwm_input:
+ case hwmon_pwm_enable:
+ return 0444;
+ default:
+ return 0;
+ }
+}
+
static umode_t corsairpsu_hwmon_power_is_visible(const struct corsairpsu_data *priv, u32 attr,
int channel)
{
@@ -416,6 +458,8 @@ static umode_t corsairpsu_hwmon_ops_is_visible(const void *data, enum hwmon_sens
return corsairpsu_hwmon_temp_is_visible(priv, attr, channel);
case hwmon_fan:
return corsairpsu_hwmon_fan_is_visible(priv, attr, channel);
+ case hwmon_pwm:
+ return corsairpsu_hwmon_pwm_is_visible(priv, attr, channel);
case hwmon_power:
return corsairpsu_hwmon_power_is_visible(priv, attr, channel);
case hwmon_in:
@@ -447,6 +491,20 @@ static int corsairpsu_hwmon_temp_read(struct corsairpsu_data *priv, u32 attr, in
return err;
}
+static int corsairpsu_hwmon_pwm_read(struct corsairpsu_data *priv, u32 attr, int channel, long *val)
+{
+ switch (attr) {
+ case hwmon_pwm_input:
+ return corsairpsu_get_value(priv, PSU_CMD_FAN_PWM, 0, val);
+ case hwmon_pwm_enable:
+ return corsairpsu_get_value(priv, PSU_CMD_FAN_PWM_ENABLE, 0, val);
+ default:
+ break;
+ }
+
+ return -EOPNOTSUPP;
+}
+
static int corsairpsu_hwmon_power_read(struct corsairpsu_data *priv, u32 attr, int channel,
long *val)
{
@@ -531,6 +589,8 @@ static int corsairpsu_hwmon_ops_read(struct device *dev, enum hwmon_sensor_types
if (attr == hwmon_fan_input)
return corsairpsu_get_value(priv, PSU_CMD_FAN, 0, val);
return -EOPNOTSUPP;
+ case hwmon_pwm:
+ return corsairpsu_hwmon_pwm_read(priv, attr, channel, val);
case hwmon_power:
return corsairpsu_hwmon_power_read(priv, attr, channel, val);
case hwmon_in:
@@ -571,7 +631,7 @@ static const struct hwmon_ops corsairpsu_hwmon_ops = {
.read_string = corsairpsu_hwmon_ops_read_string,
};
-static const struct hwmon_channel_info * const corsairpsu_info[] = {
+static const struct hwmon_channel_info *const corsairpsu_info[] = {
HWMON_CHANNEL_INFO(chip,
HWMON_C_REGISTER_TZ),
HWMON_CHANNEL_INFO(temp,
@@ -579,6 +639,8 @@ static const struct hwmon_channel_info * const corsairpsu_info[] = {
HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT),
HWMON_CHANNEL_INFO(fan,
HWMON_F_INPUT | HWMON_F_LABEL),
+ HWMON_CHANNEL_INFO(pwm,
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE),
HWMON_CHANNEL_INFO(power,
HWMON_P_INPUT | HWMON_P_LABEL,
HWMON_P_INPUT | HWMON_P_LABEL,
@@ -813,15 +875,15 @@ static const struct hid_device_id corsairpsu_idtable[] = {
{ HID_USB_DEVICE(0x1b1c, 0x1c04) }, /* Corsair HX650i */
{ HID_USB_DEVICE(0x1b1c, 0x1c05) }, /* Corsair HX750i */
{ HID_USB_DEVICE(0x1b1c, 0x1c06) }, /* Corsair HX850i */
- { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i revision 1 */
+ { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i Series 2022 */
{ HID_USB_DEVICE(0x1b1c, 0x1c08) }, /* Corsair HX1200i */
{ HID_USB_DEVICE(0x1b1c, 0x1c09) }, /* Corsair RM550i */
{ HID_USB_DEVICE(0x1b1c, 0x1c0a) }, /* Corsair RM650i */
{ HID_USB_DEVICE(0x1b1c, 0x1c0b) }, /* Corsair RM750i */
{ HID_USB_DEVICE(0x1b1c, 0x1c0c) }, /* Corsair RM850i */
{ HID_USB_DEVICE(0x1b1c, 0x1c0d) }, /* Corsair RM1000i */
- { HID_USB_DEVICE(0x1b1c, 0x1c1e) }, /* Corsair HX1000i revision 2 */
- { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i */
+ { HID_USB_DEVICE(0x1b1c, 0x1c1e) }, /* Corsair HX1000i Series 2023 */
+ { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i Series 2022 and 2023 */
{ },
};
MODULE_DEVICE_TABLE(hid, corsairpsu_idtable);
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index 66c48f70fae7..cdbf3dff9172 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -2528,7 +2528,7 @@ static struct i2c_driver dme1737_i2c_driver = {
.driver = {
.name = "dme1737",
},
- .probe_new = dme1737_i2c_probe,
+ .probe = dme1737_i2c_probe,
.remove = dme1737_i2c_remove,
.id_table = dme1737_id,
.detect = dme1737_i2c_detect,
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index e803d6393b9e..21b635046521 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -384,7 +384,7 @@ static struct i2c_driver ds1621_driver = {
.driver = {
.name = "ds1621",
},
- .probe_new = ds1621_probe,
+ .probe = ds1621_probe,
.id_table = ds1621_id,
};
diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c
index 82d7c3d58f49..2b09536630cb 100644
--- a/drivers/hwmon/ds620.c
+++ b/drivers/hwmon/ds620.c
@@ -245,7 +245,7 @@ static struct i2c_driver ds620_driver = {
.driver = {
.name = "ds620",
},
- .probe_new = ds620_probe,
+ .probe = ds620_probe,
.id_table = ds620_id,
};
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c
index 61d59189a6d1..bb7c859e799d 100644
--- a/drivers/hwmon/emc1403.c
+++ b/drivers/hwmon/emc1403.c
@@ -454,7 +454,7 @@ static struct i2c_driver sensor_emc1403 = {
.name = "emc1403",
},
.detect = emc1403_detect,
- .probe_new = emc1403_probe,
+ .probe = emc1403_probe,
.id_table = emc1403_idtable,
.address_list = emc1403_address_list,
};
diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c
index 361cf9292456..b59472bbe5bf 100644
--- a/drivers/hwmon/emc2103.c
+++ b/drivers/hwmon/emc2103.c
@@ -653,7 +653,7 @@ static struct i2c_driver emc2103_driver = {
.driver = {
.name = "emc2103",
},
- .probe_new = emc2103_probe,
+ .probe = emc2103_probe,
.id_table = emc2103_ids,
.detect = emc2103_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
index 723f57518c9a..29f0e4945f19 100644
--- a/drivers/hwmon/emc2305.c
+++ b/drivers/hwmon/emc2305.c
@@ -615,7 +615,7 @@ static struct i2c_driver emc2305_driver = {
.driver = {
.name = "emc2305",
},
- .probe_new = emc2305_probe,
+ .probe = emc2305_probe,
.remove = emc2305_remove,
.id_table = emc2305_ids,
.address_list = emc2305_normal_i2c,
diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c
index bcd93f0fe982..9a4f868bf1e6 100644
--- a/drivers/hwmon/emc6w201.c
+++ b/drivers/hwmon/emc6w201.c
@@ -474,7 +474,7 @@ static struct i2c_driver emc6w201_driver = {
.driver = {
.name = "emc6w201",
},
- .probe_new = emc6w201_probe,
+ .probe = emc6w201_probe,
.id_table = emc6w201_id,
.detect = emc6w201_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 70121482a617..27207ec6f7fe 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -1096,8 +1096,11 @@ static ssize_t show_pwm(struct device *dev,
val = data->pwm[nr];
else {
/* RPM mode */
- val = 255 * fan_from_reg(data->fan_target[nr])
- / fan_from_reg(data->fan_full_speed[nr]);
+ if (fan_from_reg(data->fan_full_speed[nr]))
+ val = 255 * fan_from_reg(data->fan_target[nr])
+ / fan_from_reg(data->fan_full_speed[nr]);
+ else
+ val = 0;
}
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", val);
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index 64fbb8cf687c..8c572bb64f5d 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -129,7 +129,7 @@ static struct i2c_driver f75375_driver = {
.driver = {
.name = "f75375",
},
- .probe_new = f75375_probe,
+ .probe = f75375_probe,
.remove = f75375_remove,
.id_table = f75375_id,
.detect = f75375_detect,
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index e1f426e86f36..b30512a705a7 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -241,7 +241,7 @@ static struct i2c_driver fschmd_driver = {
.driver = {
.name = "fschmd",
},
- .probe_new = fschmd_probe,
+ .probe = fschmd_probe,
.remove = fschmd_remove,
.id_table = fschmd_id,
.detect = fschmd_detect,
diff --git a/drivers/hwmon/ftsteutates.c b/drivers/hwmon/ftsteutates.c
index f5a4d91a7e90..b74a2665e733 100644
--- a/drivers/hwmon/ftsteutates.c
+++ b/drivers/hwmon/ftsteutates.c
@@ -678,7 +678,7 @@ static struct i2c_driver fts_driver = {
.name = "ftsteutates",
},
.id_table = fts_id,
- .probe_new = fts_probe,
+ .probe = fts_probe,
.detect = fts_detect,
.address_list = normal_i2c,
};
diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c
index 36717b524dbd..b5edee00267b 100644
--- a/drivers/hwmon/g760a.c
+++ b/drivers/hwmon/g760a.c
@@ -206,7 +206,7 @@ static struct i2c_driver g760a_driver = {
.driver = {
.name = "g760a",
},
- .probe_new = g760a_probe,
+ .probe = g760a_probe,
.id_table = g760a_id,
};
diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
index e2c3c34f06e8..1b6ff4712138 100644
--- a/drivers/hwmon/g762.c
+++ b/drivers/hwmon/g762.c
@@ -1084,7 +1084,7 @@ static struct i2c_driver g762_driver = {
.name = DRVNAME,
.of_match_table = of_match_ptr(g762_dt_match),
},
- .probe_new = g762_probe,
+ .probe = g762_probe,
.id_table = g762_id,
};
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index 95286c40f55a..03db6158b13a 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -652,7 +652,7 @@ static struct i2c_driver gl518_driver = {
.driver = {
.name = "gl518sm",
},
- .probe_new = gl518_probe,
+ .probe = gl518_probe,
.id_table = gl518_id,
.detect = gl518_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index 394da4ac977c..8bbc6a4f2928 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -895,7 +895,7 @@ static struct i2c_driver gl520_driver = {
.driver = {
.name = "gl520sm",
},
- .probe_new = gl520_probe,
+ .probe = gl520_probe,
.id_table = gl520_id,
.detect = gl520_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/gsc-hwmon.c b/drivers/hwmon/gsc-hwmon.c
index 73e5d92b200b..1501ceb551e7 100644
--- a/drivers/hwmon/gsc-hwmon.c
+++ b/drivers/hwmon/gsc-hwmon.c
@@ -82,8 +82,8 @@ static ssize_t pwm_auto_point_temp_store(struct device *dev,
if (kstrtol(buf, 10, &temp))
return -EINVAL;
- temp = clamp_val(temp, 0, 10000);
- temp = DIV_ROUND_CLOSEST(temp, 10);
+ temp = clamp_val(temp, 0, 100000);
+ temp = DIV_ROUND_CLOSEST(temp, 100);
regs[0] = temp & 0xff;
regs[1] = (temp >> 8) & 0xff;
@@ -100,7 +100,7 @@ static ssize_t pwm_auto_point_pwm_show(struct device *dev,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10)) / 100);
+ return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10)));
}
static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point1_pwm, pwm_auto_point_pwm, 0);
diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c
index 3a7582824f94..a9726b5370fb 100644
--- a/drivers/hwmon/hih6130.c
+++ b/drivers/hwmon/hih6130.c
@@ -249,7 +249,7 @@ static struct i2c_driver hih6130_driver = {
.name = "hih6130",
.of_match_table = of_match_ptr(hih6130_of_match),
},
- .probe_new = hih6130_probe,
+ .probe = hih6130_probe,
.id_table = hih6130_id,
};
diff --git a/drivers/hwmon/hp-wmi-sensors.c b/drivers/hwmon/hp-wmi-sensors.c
new file mode 100644
index 000000000000..ebe2fb513480
--- /dev/null
+++ b/drivers/hwmon/hp-wmi-sensors.c
@@ -0,0 +1,2004 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * hwmon driver for HP (and some HP Compaq) business-class computers that
+ * report numeric sensor data via Windows Management Instrumentation (WMI).
+ *
+ * Copyright (C) 2023 James Seo <james@equiv.tech>
+ *
+ * References:
+ * [1] Hewlett-Packard Development Company, L.P.,
+ * "HP Client Management Interface Technical White Paper", 2005. [Online].
+ * Available: https://h20331.www2.hp.com/hpsub/downloads/cmi_whitepaper.pdf
+ * [2] Hewlett-Packard Development Company, L.P.,
+ * "HP Retail Manageability", 2012. [Online].
+ * Available: http://h10032.www1.hp.com/ctg/Manual/c03291135.pdf
+ * [3] Linux Hardware Project, A. Ponomarenko et al.,
+ * "linuxhw/ACPI - Collect ACPI table dumps", 2018. [Online].
+ * Available: https://github.com/linuxhw/ACPI
+ * [4] P. Rohár, "bmfdec - Decompile binary MOF file (BMF) from WMI buffer",
+ * 2017. [Online]. Available: https://github.com/pali/bmfdec
+ */
+
+#include <linux/acpi.h>
+#include <linux/debugfs.h>
+#include <linux/hwmon.h>
+#include <linux/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/units.h>
+#include <linux/wmi.h>
+
+#define HP_WMI_EVENT_NAMESPACE "root\\WMI"
+#define HP_WMI_EVENT_CLASS "HPBIOS_BIOSEvent"
+#define HP_WMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
+#define HP_WMI_NUMERIC_SENSOR_GUID "8F1F6435-9F42-42C8-BADC-0E9424F20C9A"
+#define HP_WMI_PLATFORM_EVENTS_GUID "41227C2D-80E1-423F-8B8E-87E32755A0EB"
+
+/* Patterns for recognizing sensors and matching events to channels. */
+
+#define HP_WMI_PATTERN_SYS_TEMP "Chassis Thermal Index"
+#define HP_WMI_PATTERN_SYS_TEMP2 "System Ambient Temperature"
+#define HP_WMI_PATTERN_CPU_TEMP "CPU Thermal Index"
+#define HP_WMI_PATTERN_CPU_TEMP2 "CPU Temperature"
+#define HP_WMI_PATTERN_TEMP_SENSOR "Thermal Index"
+#define HP_WMI_PATTERN_TEMP_ALARM "Thermal Critical"
+#define HP_WMI_PATTERN_INTRUSION_ALARM "Hood Intrusion"
+#define HP_WMI_PATTERN_FAN_ALARM "Stall"
+#define HP_WMI_PATTERN_TEMP "Temperature"
+#define HP_WMI_PATTERN_CPU "CPU"
+
+/* These limits are arbitrary. The WMI implementation may vary by system. */
+
+#define HP_WMI_MAX_STR_SIZE 128U
+#define HP_WMI_MAX_PROPERTIES 32U
+#define HP_WMI_MAX_INSTANCES 32U
+
+enum hp_wmi_type {
+ HP_WMI_TYPE_OTHER = 1,
+ HP_WMI_TYPE_TEMPERATURE = 2,
+ HP_WMI_TYPE_VOLTAGE = 3,
+ HP_WMI_TYPE_CURRENT = 4,
+ HP_WMI_TYPE_AIR_FLOW = 12,
+ HP_WMI_TYPE_INTRUSION = 0xabadb01, /* Custom. */
+};
+
+enum hp_wmi_category {
+ HP_WMI_CATEGORY_SENSOR = 3,
+};
+
+enum hp_wmi_severity {
+ HP_WMI_SEVERITY_UNKNOWN = 0,
+ HP_WMI_SEVERITY_OK = 5,
+ HP_WMI_SEVERITY_DEGRADED_WARNING = 10,
+ HP_WMI_SEVERITY_MINOR_FAILURE = 15,
+ HP_WMI_SEVERITY_MAJOR_FAILURE = 20,
+ HP_WMI_SEVERITY_CRITICAL_FAILURE = 25,
+ HP_WMI_SEVERITY_NON_RECOVERABLE_ERROR = 30,
+};
+
+enum hp_wmi_status {
+ HP_WMI_STATUS_OK = 2,
+ HP_WMI_STATUS_DEGRADED = 3,
+ HP_WMI_STATUS_STRESSED = 4,
+ HP_WMI_STATUS_PREDICTIVE_FAILURE = 5,
+ HP_WMI_STATUS_ERROR = 6,
+ HP_WMI_STATUS_NON_RECOVERABLE_ERROR = 7,
+ HP_WMI_STATUS_NO_CONTACT = 12,
+ HP_WMI_STATUS_LOST_COMMUNICATION = 13,
+ HP_WMI_STATUS_ABORTED = 14,
+ HP_WMI_STATUS_SUPPORTING_ENTITY_IN_ERROR = 16,
+
+ /* Occurs combined with one of "OK", "Degraded", and "Error" [1]. */
+ HP_WMI_STATUS_COMPLETED = 17,
+};
+
+enum hp_wmi_units {
+ HP_WMI_UNITS_OTHER = 1,
+ HP_WMI_UNITS_DEGREES_C = 2,
+ HP_WMI_UNITS_DEGREES_F = 3,
+ HP_WMI_UNITS_DEGREES_K = 4,
+ HP_WMI_UNITS_VOLTS = 5,
+ HP_WMI_UNITS_AMPS = 6,
+ HP_WMI_UNITS_RPM = 19,
+};
+
+enum hp_wmi_property {
+ HP_WMI_PROPERTY_NAME = 0,
+ HP_WMI_PROPERTY_DESCRIPTION = 1,
+ HP_WMI_PROPERTY_SENSOR_TYPE = 2,
+ HP_WMI_PROPERTY_OTHER_SENSOR_TYPE = 3,
+ HP_WMI_PROPERTY_OPERATIONAL_STATUS = 4,
+ HP_WMI_PROPERTY_SIZE = 5,
+ HP_WMI_PROPERTY_POSSIBLE_STATES = 6,
+ HP_WMI_PROPERTY_CURRENT_STATE = 7,
+ HP_WMI_PROPERTY_BASE_UNITS = 8,
+ HP_WMI_PROPERTY_UNIT_MODIFIER = 9,
+ HP_WMI_PROPERTY_CURRENT_READING = 10,
+ HP_WMI_PROPERTY_RATE_UNITS = 11,
+};
+
+static const acpi_object_type hp_wmi_property_map[] = {
+ [HP_WMI_PROPERTY_NAME] = ACPI_TYPE_STRING,
+ [HP_WMI_PROPERTY_DESCRIPTION] = ACPI_TYPE_STRING,
+ [HP_WMI_PROPERTY_SENSOR_TYPE] = ACPI_TYPE_INTEGER,
+ [HP_WMI_PROPERTY_OTHER_SENSOR_TYPE] = ACPI_TYPE_STRING,
+ [HP_WMI_PROPERTY_OPERATIONAL_STATUS] = ACPI_TYPE_INTEGER,
+ [HP_WMI_PROPERTY_SIZE] = ACPI_TYPE_INTEGER,
+ [HP_WMI_PROPERTY_POSSIBLE_STATES] = ACPI_TYPE_STRING,
+ [HP_WMI_PROPERTY_CURRENT_STATE] = ACPI_TYPE_STRING,
+ [HP_WMI_PROPERTY_BASE_UNITS] = ACPI_TYPE_INTEGER,
+ [HP_WMI_PROPERTY_UNIT_MODIFIER] = ACPI_TYPE_INTEGER,
+ [HP_WMI_PROPERTY_CURRENT_READING] = ACPI_TYPE_INTEGER,
+ [HP_WMI_PROPERTY_RATE_UNITS] = ACPI_TYPE_INTEGER,
+};
+
+enum hp_wmi_platform_events_property {
+ HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME = 0,
+ HP_WMI_PLATFORM_EVENTS_PROPERTY_DESCRIPTION = 1,
+ HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_NAMESPACE = 2,
+ HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_CLASS = 3,
+ HP_WMI_PLATFORM_EVENTS_PROPERTY_CATEGORY = 4,
+ HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_SEVERITY = 5,
+ HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS = 6,
+};
+
+static const acpi_object_type hp_wmi_platform_events_property_map[] = {
+ [HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME] = ACPI_TYPE_STRING,
+ [HP_WMI_PLATFORM_EVENTS_PROPERTY_DESCRIPTION] = ACPI_TYPE_STRING,
+ [HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_NAMESPACE] = ACPI_TYPE_STRING,
+ [HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_CLASS] = ACPI_TYPE_STRING,
+ [HP_WMI_PLATFORM_EVENTS_PROPERTY_CATEGORY] = ACPI_TYPE_INTEGER,
+ [HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_SEVERITY] = ACPI_TYPE_INTEGER,
+ [HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS] = ACPI_TYPE_INTEGER,
+};
+
+enum hp_wmi_event_property {
+ HP_WMI_EVENT_PROPERTY_NAME = 0,
+ HP_WMI_EVENT_PROPERTY_DESCRIPTION = 1,
+ HP_WMI_EVENT_PROPERTY_CATEGORY = 2,
+ HP_WMI_EVENT_PROPERTY_SEVERITY = 3,
+ HP_WMI_EVENT_PROPERTY_STATUS = 4,
+};
+
+static const acpi_object_type hp_wmi_event_property_map[] = {
+ [HP_WMI_EVENT_PROPERTY_NAME] = ACPI_TYPE_STRING,
+ [HP_WMI_EVENT_PROPERTY_DESCRIPTION] = ACPI_TYPE_STRING,
+ [HP_WMI_EVENT_PROPERTY_CATEGORY] = ACPI_TYPE_INTEGER,
+ [HP_WMI_EVENT_PROPERTY_SEVERITY] = ACPI_TYPE_INTEGER,
+ [HP_WMI_EVENT_PROPERTY_STATUS] = ACPI_TYPE_INTEGER,
+};
+
+static const enum hwmon_sensor_types hp_wmi_hwmon_type_map[] = {
+ [HP_WMI_TYPE_TEMPERATURE] = hwmon_temp,
+ [HP_WMI_TYPE_VOLTAGE] = hwmon_in,
+ [HP_WMI_TYPE_CURRENT] = hwmon_curr,
+ [HP_WMI_TYPE_AIR_FLOW] = hwmon_fan,
+};
+
+static const u32 hp_wmi_hwmon_attributes[hwmon_max] = {
+ [hwmon_chip] = HWMON_C_REGISTER_TZ,
+ [hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_FAULT,
+ [hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
+ [hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL,
+ [hwmon_fan] = HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_FAULT,
+ [hwmon_intrusion] = HWMON_INTRUSION_ALARM,
+};
+
+/*
+ * struct hp_wmi_numeric_sensor - a HPBIOS_BIOSNumericSensor instance
+ *
+ * Two variants of HPBIOS_BIOSNumericSensor are known. The first is specified
+ * in [1] and appears to be much more widespread. The second was discovered by
+ * decoding BMOF blobs [4], seems to be found only in some newer ZBook systems
+ * [3], and has two new properties and a slightly different property order.
+ *
+ * These differences don't matter on Windows, where WMI object properties are
+ * accessed by name. For us, supporting both variants gets ugly and hacky at
+ * times. The fun begins now; this struct is defined as per the new variant.
+ *
+ * Effective MOF definition:
+ *
+ * #pragma namespace("\\\\.\\root\\HP\\InstrumentedBIOS");
+ * class HPBIOS_BIOSNumericSensor {
+ * [read] string Name;
+ * [read] string Description;
+ * [read, ValueMap {"0","1","2","3","4","5","6","7","8","9",
+ * "10","11","12"}, Values {"Unknown","Other","Temperature",
+ * "Voltage","Current","Tachometer","Counter","Switch","Lock",
+ * "Humidity","Smoke Detection","Presence","Air Flow"}]
+ * uint32 SensorType;
+ * [read] string OtherSensorType;
+ * [read, ValueMap {"0","1","2","3","4","5","6","7","8","9",
+ * "10","11","12","13","14","15","16","17","18","..",
+ * "0x8000.."}, Values {"Unknown","Other","OK","Degraded",
+ * "Stressed","Predictive Failure","Error",
+ * "Non-Recoverable Error","Starting","Stopping","Stopped",
+ * "In Service","No Contact","Lost Communication","Aborted",
+ * "Dormant","Supporting Entity in Error","Completed",
+ * "Power Mode","DMTF Reserved","Vendor Reserved"}]
+ * uint32 OperationalStatus;
+ * [read] uint32 Size;
+ * [read] string PossibleStates[];
+ * [read] string CurrentState;
+ * [read, ValueMap {"0","1","2","3","4","5","6","7","8","9",
+ * "10","11","12","13","14","15","16","17","18","19","20",
+ * "21","22","23","24","25","26","27","28","29","30","31",
+ * "32","33","34","35","36","37","38","39","40","41","42",
+ * "43","44","45","46","47","48","49","50","51","52","53",
+ * "54","55","56","57","58","59","60","61","62","63","64",
+ * "65"}, Values {"Unknown","Other","Degrees C","Degrees F",
+ * "Degrees K","Volts","Amps","Watts","Joules","Coulombs",
+ * "VA","Nits","Lumens","Lux","Candelas","kPa","PSI",
+ * "Newtons","CFM","RPM","Hertz","Seconds","Minutes",
+ * "Hours","Days","Weeks","Mils","Inches","Feet",
+ * "Cubic Inches","Cubic Feet","Meters","Cubic Centimeters",
+ * "Cubic Meters","Liters","Fluid Ounces","Radians",
+ * "Steradians","Revolutions","Cycles","Gravities","Ounces",
+ * "Pounds","Foot-Pounds","Ounce-Inches","Gauss","Gilberts",
+ * "Henries","Farads","Ohms","Siemens","Moles","Becquerels",
+ * "PPM (parts/million)","Decibels","DbA","DbC","Grays",
+ * "Sieverts","Color Temperature Degrees K","Bits","Bytes",
+ * "Words (data)","DoubleWords","QuadWords","Percentage"}]
+ * uint32 BaseUnits;
+ * [read] sint32 UnitModifier;
+ * [read] uint32 CurrentReading;
+ * [read] uint32 RateUnits;
+ * };
+ *
+ * Effective MOF definition of old variant [1] (sans redundant info):
+ *
+ * class HPBIOS_BIOSNumericSensor {
+ * [read] string Name;
+ * [read] string Description;
+ * [read] uint32 SensorType;
+ * [read] string OtherSensorType;
+ * [read] uint32 OperationalStatus;
+ * [read] string CurrentState;
+ * [read] string PossibleStates[];
+ * [read] uint32 BaseUnits;
+ * [read] sint32 UnitModifier;
+ * [read] uint32 CurrentReading;
+ * };
+ */
+struct hp_wmi_numeric_sensor {
+ const char *name;
+ const char *description;
+ u32 sensor_type;
+ const char *other_sensor_type; /* Explains "Other" SensorType. */
+ u32 operational_status;
+ u8 size; /* Count of PossibleStates[]. */
+ const char **possible_states;
+ const char *current_state;
+ u32 base_units;
+ s32 unit_modifier;
+ u32 current_reading;
+ u32 rate_units;
+};
+
+/*
+ * struct hp_wmi_platform_events - a HPBIOS_PlatformEvents instance
+ *
+ * Instances of this object reveal the set of possible HPBIOS_BIOSEvent
+ * instances for the current system, but it may not always be present.
+ *
+ * Effective MOF definition:
+ *
+ * #pragma namespace("\\\\.\\root\\HP\\InstrumentedBIOS");
+ * class HPBIOS_PlatformEvents {
+ * [read] string Name;
+ * [read] string Description;
+ * [read] string SourceNamespace;
+ * [read] string SourceClass;
+ * [read, ValueMap {"0","1","2","3","4",".."}, Values {
+ * "Unknown","Configuration Change","Button Pressed",
+ * "Sensor","BIOS Settings","Reserved"}]
+ * uint32 Category;
+ * [read, ValueMap{"0","5","10","15","20","25","30",".."},
+ * Values{"Unknown","OK","Degraded/Warning","Minor Failure",
+ * "Major Failure","Critical Failure","Non-recoverable Error",
+ * "DMTF Reserved"}]
+ * uint32 PossibleSeverity;
+ * [read, ValueMap {"0","1","2","3","4","5","6","7","8","9",
+ * "10","11","12","13","14","15","16","17","18","..",
+ * "0x8000.."}, Values {"Unknown","Other","OK","Degraded",
+ * "Stressed","Predictive Failure","Error",
+ * "Non-Recoverable Error","Starting","Stopping","Stopped",
+ * "In Service","No Contact","Lost Communication","Aborted",
+ * "Dormant","Supporting Entity in Error","Completed",
+ * "Power Mode","DMTF Reserved","Vendor Reserved"}]
+ * uint32 PossibleStatus;
+ * };
+ */
+struct hp_wmi_platform_events {
+ const char *name;
+ const char *description;
+ const char *source_namespace;
+ const char *source_class;
+ u32 category;
+ u32 possible_severity;
+ u32 possible_status;
+};
+
+/*
+ * struct hp_wmi_event - a HPBIOS_BIOSEvent instance
+ *
+ * Effective MOF definition [1] (corrected below from original):
+ *
+ * #pragma namespace("\\\\.\\root\\WMI");
+ * class HPBIOS_BIOSEvent : WMIEvent {
+ * [read] string Name;
+ * [read] string Description;
+ * [read ValueMap {"0","1","2","3","4"}, Values {"Unknown",
+ * "Configuration Change","Button Pressed","Sensor",
+ * "BIOS Settings"}]
+ * uint32 Category;
+ * [read, ValueMap {"0","5","10","15","20","25","30"},
+ * Values {"Unknown","OK","Degraded/Warning",
+ * "Minor Failure","Major Failure","Critical Failure",
+ * "Non-recoverable Error"}]
+ * uint32 Severity;
+ * [read, ValueMap {"0","1","2","3","4","5","6","7","8",
+ * "9","10","11","12","13","14","15","16","17","18","..",
+ * "0x8000.."}, Values {"Unknown","Other","OK","Degraded",
+ * "Stressed","Predictive Failure","Error",
+ * "Non-Recoverable Error","Starting","Stopping","Stopped",
+ * "In Service","No Contact","Lost Communication","Aborted",
+ * "Dormant","Supporting Entity in Error","Completed",
+ * "Power Mode","DMTF Reserved","Vendor Reserved"}]
+ * uint32 Status;
+ * };
+ */
+struct hp_wmi_event {
+ const char *name;
+ const char *description;
+ u32 category;
+};
+
+/*
+ * struct hp_wmi_info - sensor info
+ * @nsensor: numeric sensor properties
+ * @instance: its WMI instance number
+ * @state: pointer to driver state
+ * @has_alarm: whether sensor has an alarm flag
+ * @alarm: alarm flag
+ * @type: its hwmon sensor type
+ * @cached_val: current sensor reading value, scaled for hwmon
+ * @last_updated: when these readings were last updated
+ */
+struct hp_wmi_info {
+ struct hp_wmi_numeric_sensor nsensor;
+ u8 instance;
+ void *state; /* void *: Avoid forward declaration. */
+ bool has_alarm;
+ bool alarm;
+ enum hwmon_sensor_types type;
+ long cached_val;
+ unsigned long last_updated; /* In jiffies. */
+
+};
+
+/*
+ * struct hp_wmi_sensors - driver state
+ * @wdev: pointer to the parent WMI device
+ * @info_map: sensor info structs by hwmon type and channel number
+ * @channel_count: count of hwmon channels by hwmon type
+ * @has_intrusion: whether an intrusion sensor is present
+ * @intrusion: intrusion flag
+ * @lock: mutex to lock polling WMI and changes to driver state
+ */
+struct hp_wmi_sensors {
+ struct wmi_device *wdev;
+ struct hp_wmi_info **info_map[hwmon_max];
+ u8 channel_count[hwmon_max];
+ bool has_intrusion;
+ bool intrusion;
+
+ struct mutex lock; /* Lock polling WMI and driver state changes. */
+};
+
+/* hp_wmi_strdup - devm_kstrdup, but length-limited */
+static char *hp_wmi_strdup(struct device *dev, const char *src)
+{
+ char *dst;
+ size_t len;
+
+ len = strnlen(src, HP_WMI_MAX_STR_SIZE - 1);
+
+ dst = devm_kmalloc(dev, (len + 1) * sizeof(*dst), GFP_KERNEL);
+ if (!dst)
+ return NULL;
+
+ strscpy(dst, src, len + 1);
+
+ return dst;
+}
+
+/*
+ * hp_wmi_get_wobj - poll WMI for a WMI object instance
+ * @guid: WMI object GUID
+ * @instance: WMI object instance number
+ *
+ * Returns a new WMI object instance on success, or NULL on error.
+ * Caller must kfree() the result.
+ */
+static union acpi_object *hp_wmi_get_wobj(const char *guid, u8 instance)
+{
+ struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
+ acpi_status err;
+
+ err = wmi_query_block(guid, instance, &out);
+ if (ACPI_FAILURE(err))
+ return NULL;
+
+ return out.pointer;
+}
+
+/* hp_wmi_wobj_instance_count - find count of WMI object instances */
+static u8 hp_wmi_wobj_instance_count(const char *guid)
+{
+ u8 hi = HP_WMI_MAX_INSTANCES;
+ union acpi_object *wobj;
+ u8 lo = 0;
+ u8 mid;
+
+ while (lo < hi) {
+ mid = (lo + hi) / 2;
+
+ wobj = hp_wmi_get_wobj(guid, mid);
+ if (!wobj) {
+ hi = mid;
+ continue;
+ }
+
+ lo = mid + 1;
+ kfree(wobj);
+ }
+
+ return lo;
+}
+
+static int check_wobj(const union acpi_object *wobj,
+ const acpi_object_type property_map[], int last_prop)
+{
+ acpi_object_type type = wobj->type;
+ acpi_object_type valid_type;
+ union acpi_object *elements;
+ u32 elem_count;
+ int prop;
+
+ if (type != ACPI_TYPE_PACKAGE)
+ return -EINVAL;
+
+ elem_count = wobj->package.count;
+ if (elem_count != last_prop + 1)
+ return -EINVAL;
+
+ elements = wobj->package.elements;
+ for (prop = 0; prop <= last_prop; prop++) {
+ type = elements[prop].type;
+ valid_type = property_map[prop];
+ if (type != valid_type)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int extract_acpi_value(struct device *dev,
+ union acpi_object *element,
+ acpi_object_type type,
+ u32 *out_value, char **out_string)
+{
+ switch (type) {
+ case ACPI_TYPE_INTEGER:
+ *out_value = element->integer.value;
+ break;
+
+ case ACPI_TYPE_STRING:
+ *out_string = hp_wmi_strdup(dev, strim(element->string.pointer));
+ if (!*out_string)
+ return -ENOMEM;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * check_numeric_sensor_wobj - validate a HPBIOS_BIOSNumericSensor instance
+ * @wobj: pointer to WMI object instance to check
+ * @out_size: out pointer to count of possible states
+ * @out_is_new: out pointer to whether this is a "new" variant object
+ *
+ * Returns 0 on success, or a negative error code on error.
+ */
+static int check_numeric_sensor_wobj(const union acpi_object *wobj,
+ u8 *out_size, bool *out_is_new)
+{
+ acpi_object_type type = wobj->type;
+ int prop = HP_WMI_PROPERTY_NAME;
+ acpi_object_type valid_type;
+ union acpi_object *elements;
+ u32 elem_count;
+ int last_prop;
+ bool is_new;
+ u8 count;
+ u32 j;
+ u32 i;
+
+ if (type != ACPI_TYPE_PACKAGE)
+ return -EINVAL;
+
+ /*
+ * elements is a variable-length array of ACPI objects, one for
+ * each property of the WMI object instance, except that the
+ * strings in PossibleStates[] are flattened into this array
+ * as if each individual string were a property by itself.
+ */
+ elements = wobj->package.elements;
+
+ elem_count = wobj->package.count;
+ if (elem_count <= HP_WMI_PROPERTY_SIZE ||
+ elem_count > HP_WMI_MAX_PROPERTIES)
+ return -EINVAL;
+
+ type = elements[HP_WMI_PROPERTY_SIZE].type;
+ switch (type) {
+ case ACPI_TYPE_INTEGER:
+ is_new = true;
+ last_prop = HP_WMI_PROPERTY_RATE_UNITS;
+ break;
+
+ case ACPI_TYPE_STRING:
+ is_new = false;
+ last_prop = HP_WMI_PROPERTY_CURRENT_READING;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /*
+ * In general, the count of PossibleStates[] must be > 0.
+ * Also, the old variant lacks the Size property, so we may need to
+ * reduce the value of last_prop by 1 when doing arithmetic with it.
+ */
+ if (elem_count < last_prop - !is_new + 1)
+ return -EINVAL;
+
+ count = elem_count - (last_prop - !is_new);
+
+ for (i = 0; i < elem_count && prop <= last_prop; i++, prop++) {
+ type = elements[i].type;
+ valid_type = hp_wmi_property_map[prop];
+ if (type != valid_type)
+ return -EINVAL;
+
+ switch (prop) {
+ case HP_WMI_PROPERTY_OPERATIONAL_STATUS:
+ /* Old variant: CurrentState follows OperationalStatus. */
+ if (!is_new)
+ prop = HP_WMI_PROPERTY_CURRENT_STATE - 1;
+ break;
+
+ case HP_WMI_PROPERTY_SIZE:
+ /* New variant: Size == count of PossibleStates[]. */
+ if (count != elements[i].integer.value)
+ return -EINVAL;
+ break;
+
+ case HP_WMI_PROPERTY_POSSIBLE_STATES:
+ /* PossibleStates[0] has already been type-checked. */
+ for (j = 0; i + 1 < elem_count && j + 1 < count; j++) {
+ type = elements[++i].type;
+ if (type != valid_type)
+ return -EINVAL;
+ }
+
+ /* Old variant: BaseUnits follows PossibleStates[]. */
+ if (!is_new)
+ prop = HP_WMI_PROPERTY_BASE_UNITS - 1;
+ break;
+
+ case HP_WMI_PROPERTY_CURRENT_STATE:
+ /* Old variant: PossibleStates[] follows CurrentState. */
+ if (!is_new)
+ prop = HP_WMI_PROPERTY_POSSIBLE_STATES - 1;
+ break;
+ }
+ }
+
+ if (prop != last_prop + 1)
+ return -EINVAL;
+
+ *out_size = count;
+ *out_is_new = is_new;
+
+ return 0;
+}
+
+static int
+numeric_sensor_is_connected(const struct hp_wmi_numeric_sensor *nsensor)
+{
+ u32 operational_status = nsensor->operational_status;
+
+ return operational_status != HP_WMI_STATUS_NO_CONTACT;
+}
+
+static int numeric_sensor_has_fault(const struct hp_wmi_numeric_sensor *nsensor)
+{
+ u32 operational_status = nsensor->operational_status;
+
+ switch (operational_status) {
+ case HP_WMI_STATUS_DEGRADED:
+ case HP_WMI_STATUS_STRESSED: /* e.g. Overload, overtemp. */
+ case HP_WMI_STATUS_PREDICTIVE_FAILURE: /* e.g. Fan removed. */
+ case HP_WMI_STATUS_ERROR:
+ case HP_WMI_STATUS_NON_RECOVERABLE_ERROR:
+ case HP_WMI_STATUS_NO_CONTACT:
+ case HP_WMI_STATUS_LOST_COMMUNICATION:
+ case HP_WMI_STATUS_ABORTED:
+ case HP_WMI_STATUS_SUPPORTING_ENTITY_IN_ERROR:
+
+ /* Assume combination by addition; bitwise OR doesn't make sense. */
+ case HP_WMI_STATUS_COMPLETED + HP_WMI_STATUS_DEGRADED:
+ case HP_WMI_STATUS_COMPLETED + HP_WMI_STATUS_ERROR:
+ return true;
+ }
+
+ return false;
+}
+
+/* scale_numeric_sensor - scale sensor reading for hwmon */
+static long scale_numeric_sensor(const struct hp_wmi_numeric_sensor *nsensor)
+{
+ u32 current_reading = nsensor->current_reading;
+ s32 unit_modifier = nsensor->unit_modifier;
+ u32 sensor_type = nsensor->sensor_type;
+ u32 base_units = nsensor->base_units;
+ s32 target_modifier;
+ long val;
+
+ /* Fan readings are in RPM units; others are in milliunits. */
+ target_modifier = sensor_type == HP_WMI_TYPE_AIR_FLOW ? 0 : -3;
+
+ val = current_reading;
+
+ for (; unit_modifier < target_modifier; unit_modifier++)
+ val = DIV_ROUND_CLOSEST(val, 10);
+
+ for (; unit_modifier > target_modifier; unit_modifier--) {
+ if (val > LONG_MAX / 10) {
+ val = LONG_MAX;
+ break;
+ }
+ val *= 10;
+ }
+
+ if (sensor_type == HP_WMI_TYPE_TEMPERATURE) {
+ switch (base_units) {
+ case HP_WMI_UNITS_DEGREES_F:
+ val -= MILLI * 32;
+ val = val <= LONG_MAX / 5 ?
+ DIV_ROUND_CLOSEST(val * 5, 9) :
+ DIV_ROUND_CLOSEST(val, 9) * 5;
+ break;
+
+ case HP_WMI_UNITS_DEGREES_K:
+ val = milli_kelvin_to_millicelsius(val);
+ break;
+ }
+ }
+
+ return val;
+}
+
+/*
+ * classify_numeric_sensor - classify a numeric sensor
+ * @nsensor: pointer to numeric sensor struct
+ *
+ * Returns an enum hp_wmi_type value on success,
+ * or a negative value if the sensor type is unsupported.
+ */
+static int classify_numeric_sensor(const struct hp_wmi_numeric_sensor *nsensor)
+{
+ u32 sensor_type = nsensor->sensor_type;
+ u32 base_units = nsensor->base_units;
+ const char *name = nsensor->name;
+
+ switch (sensor_type) {
+ case HP_WMI_TYPE_TEMPERATURE:
+ /*
+ * Some systems have sensors named "X Thermal Index" in "Other"
+ * units. Tested CPU sensor examples were found to be in °C,
+ * albeit perhaps "differently" accurate; e.g. readings were
+ * reliably -6°C vs. coretemp on a HP Compaq Elite 8300, and
+ * +8°C on an EliteOne G1 800. But this is still within the
+ * realm of plausibility for cheaply implemented motherboard
+ * sensors, and chassis readings were about as expected.
+ */
+ if ((base_units == HP_WMI_UNITS_OTHER &&
+ strstr(name, HP_WMI_PATTERN_TEMP_SENSOR)) ||
+ base_units == HP_WMI_UNITS_DEGREES_C ||
+ base_units == HP_WMI_UNITS_DEGREES_F ||
+ base_units == HP_WMI_UNITS_DEGREES_K)
+ return HP_WMI_TYPE_TEMPERATURE;
+ break;
+
+ case HP_WMI_TYPE_VOLTAGE:
+ if (base_units == HP_WMI_UNITS_VOLTS)
+ return HP_WMI_TYPE_VOLTAGE;
+ break;
+
+ case HP_WMI_TYPE_CURRENT:
+ if (base_units == HP_WMI_UNITS_AMPS)
+ return HP_WMI_TYPE_CURRENT;
+ break;
+
+ case HP_WMI_TYPE_AIR_FLOW:
+ /*
+ * Strangely, HP considers fan RPM sensor type to be
+ * "Air Flow" instead of the more intuitive "Tachometer".
+ */
+ if (base_units == HP_WMI_UNITS_RPM)
+ return HP_WMI_TYPE_AIR_FLOW;
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int
+populate_numeric_sensor_from_wobj(struct device *dev,
+ struct hp_wmi_numeric_sensor *nsensor,
+ union acpi_object *wobj, bool *out_is_new)
+{
+ int last_prop = HP_WMI_PROPERTY_RATE_UNITS;
+ int prop = HP_WMI_PROPERTY_NAME;
+ const char **possible_states;
+ union acpi_object *element;
+ acpi_object_type type;
+ char *string;
+ bool is_new;
+ u32 value;
+ u8 size;
+ int err;
+
+ err = check_numeric_sensor_wobj(wobj, &size, &is_new);
+ if (err)
+ return err;
+
+ possible_states = devm_kcalloc(dev, size, sizeof(*possible_states),
+ GFP_KERNEL);
+ if (!possible_states)
+ return -ENOMEM;
+
+ element = wobj->package.elements;
+ nsensor->possible_states = possible_states;
+ nsensor->size = size;
+
+ if (!is_new)
+ last_prop = HP_WMI_PROPERTY_CURRENT_READING;
+
+ for (; prop <= last_prop; prop++) {
+ type = hp_wmi_property_map[prop];
+
+ err = extract_acpi_value(dev, element, type, &value, &string);
+ if (err)
+ return err;
+
+ element++;
+
+ switch (prop) {
+ case HP_WMI_PROPERTY_NAME:
+ nsensor->name = string;
+ break;
+
+ case HP_WMI_PROPERTY_DESCRIPTION:
+ nsensor->description = string;
+ break;
+
+ case HP_WMI_PROPERTY_SENSOR_TYPE:
+ if (value > HP_WMI_TYPE_AIR_FLOW)
+ return -EINVAL;
+
+ nsensor->sensor_type = value;
+ break;
+
+ case HP_WMI_PROPERTY_OTHER_SENSOR_TYPE:
+ nsensor->other_sensor_type = string;
+ break;
+
+ case HP_WMI_PROPERTY_OPERATIONAL_STATUS:
+ nsensor->operational_status = value;
+
+ /* Old variant: CurrentState follows OperationalStatus. */
+ if (!is_new)
+ prop = HP_WMI_PROPERTY_CURRENT_STATE - 1;
+ break;
+
+ case HP_WMI_PROPERTY_SIZE:
+ break; /* Already set. */
+
+ case HP_WMI_PROPERTY_POSSIBLE_STATES:
+ *possible_states++ = string;
+ if (--size)
+ prop--;
+
+ /* Old variant: BaseUnits follows PossibleStates[]. */
+ if (!is_new && !size)
+ prop = HP_WMI_PROPERTY_BASE_UNITS - 1;
+ break;
+
+ case HP_WMI_PROPERTY_CURRENT_STATE:
+ nsensor->current_state = string;
+
+ /* Old variant: PossibleStates[] follows CurrentState. */
+ if (!is_new)
+ prop = HP_WMI_PROPERTY_POSSIBLE_STATES - 1;
+ break;
+
+ case HP_WMI_PROPERTY_BASE_UNITS:
+ nsensor->base_units = value;
+ break;
+
+ case HP_WMI_PROPERTY_UNIT_MODIFIER:
+ /* UnitModifier is signed. */
+ nsensor->unit_modifier = (s32)value;
+ break;
+
+ case HP_WMI_PROPERTY_CURRENT_READING:
+ nsensor->current_reading = value;
+ break;
+
+ case HP_WMI_PROPERTY_RATE_UNITS:
+ nsensor->rate_units = value;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ }
+
+ *out_is_new = is_new;
+
+ return 0;
+}
+
+/* update_numeric_sensor_from_wobj - update fungible sensor properties */
+static void
+update_numeric_sensor_from_wobj(struct device *dev,
+ struct hp_wmi_numeric_sensor *nsensor,
+ const union acpi_object *wobj)
+{
+ const union acpi_object *elements;
+ const union acpi_object *element;
+ const char *string;
+ bool is_new;
+ int offset;
+ u8 size;
+ int err;
+
+ err = check_numeric_sensor_wobj(wobj, &size, &is_new);
+ if (err)
+ return;
+
+ elements = wobj->package.elements;
+
+ element = &elements[HP_WMI_PROPERTY_OPERATIONAL_STATUS];
+ nsensor->operational_status = element->integer.value;
+
+ /*
+ * In general, an index offset is needed after PossibleStates[0].
+ * On a new variant, CurrentState is after PossibleStates[]. This is
+ * not the case on an old variant, but we still need to offset the
+ * read because CurrentState is where Size would be on a new variant.
+ */
+ offset = is_new ? size - 1 : -2;
+
+ element = &elements[HP_WMI_PROPERTY_CURRENT_STATE + offset];
+ string = strim(element->string.pointer);
+
+ if (strcmp(string, nsensor->current_state)) {
+ devm_kfree(dev, nsensor->current_state);
+ nsensor->current_state = hp_wmi_strdup(dev, string);
+ }
+
+ /* Old variant: -2 (not -1) because it lacks the Size property. */
+ if (!is_new)
+ offset = (int)size - 2; /* size is > 0, i.e. may be 1. */
+
+ element = &elements[HP_WMI_PROPERTY_UNIT_MODIFIER + offset];
+ nsensor->unit_modifier = (s32)element->integer.value;
+
+ element = &elements[HP_WMI_PROPERTY_CURRENT_READING + offset];
+ nsensor->current_reading = element->integer.value;
+}
+
+/*
+ * check_platform_events_wobj - validate a HPBIOS_PlatformEvents instance
+ * @wobj: pointer to WMI object instance to check
+ *
+ * Returns 0 on success, or a negative error code on error.
+ */
+static int check_platform_events_wobj(const union acpi_object *wobj)
+{
+ return check_wobj(wobj, hp_wmi_platform_events_property_map,
+ HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS);
+}
+
+static int
+populate_platform_events_from_wobj(struct device *dev,
+ struct hp_wmi_platform_events *pevents,
+ union acpi_object *wobj)
+{
+ int last_prop = HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS;
+ int prop = HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME;
+ union acpi_object *element;
+ acpi_object_type type;
+ char *string;
+ u32 value;
+ int err;
+
+ err = check_platform_events_wobj(wobj);
+ if (err)
+ return err;
+
+ element = wobj->package.elements;
+
+ for (; prop <= last_prop; prop++, element++) {
+ type = hp_wmi_platform_events_property_map[prop];
+
+ err = extract_acpi_value(dev, element, type, &value, &string);
+ if (err)
+ return err;
+
+ switch (prop) {
+ case HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME:
+ pevents->name = string;
+ break;
+
+ case HP_WMI_PLATFORM_EVENTS_PROPERTY_DESCRIPTION:
+ pevents->description = string;
+ break;
+
+ case HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_NAMESPACE:
+ if (strcasecmp(HP_WMI_EVENT_NAMESPACE, string))
+ return -EINVAL;
+
+ pevents->source_namespace = string;
+ break;
+
+ case HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_CLASS:
+ if (strcasecmp(HP_WMI_EVENT_CLASS, string))
+ return -EINVAL;
+
+ pevents->source_class = string;
+ break;
+
+ case HP_WMI_PLATFORM_EVENTS_PROPERTY_CATEGORY:
+ pevents->category = value;
+ break;
+
+ case HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_SEVERITY:
+ pevents->possible_severity = value;
+ break;
+
+ case HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS:
+ pevents->possible_status = value;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * check_event_wobj - validate a HPBIOS_BIOSEvent instance
+ * @wobj: pointer to WMI object instance to check
+ *
+ * Returns 0 on success, or a negative error code on error.
+ */
+static int check_event_wobj(const union acpi_object *wobj)
+{
+ return check_wobj(wobj, hp_wmi_event_property_map,
+ HP_WMI_EVENT_PROPERTY_STATUS);
+}
+
+static int populate_event_from_wobj(struct hp_wmi_event *event,
+ union acpi_object *wobj)
+{
+ int prop = HP_WMI_EVENT_PROPERTY_NAME;
+ union acpi_object *element;
+ int err;
+
+ err = check_event_wobj(wobj);
+ if (err)
+ return err;
+
+ element = wobj->package.elements;
+
+ /* Extracted strings are NOT device-managed copies. */
+
+ for (; prop <= HP_WMI_EVENT_PROPERTY_CATEGORY; prop++, element++) {
+ switch (prop) {
+ case HP_WMI_EVENT_PROPERTY_NAME:
+ event->name = strim(element->string.pointer);
+ break;
+
+ case HP_WMI_EVENT_PROPERTY_DESCRIPTION:
+ event->description = strim(element->string.pointer);
+ break;
+
+ case HP_WMI_EVENT_PROPERTY_CATEGORY:
+ event->category = element->integer.value;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * classify_event - classify an event
+ * @name: event name
+ * @category: event category
+ *
+ * Classify instances of both HPBIOS_PlatformEvents and HPBIOS_BIOSEvent from
+ * property values. Recognition criteria are based on multiple ACPI dumps [3].
+ *
+ * Returns an enum hp_wmi_type value on success,
+ * or a negative value if the event type is unsupported.
+ */
+static int classify_event(const char *event_name, u32 category)
+{
+ if (category != HP_WMI_CATEGORY_SENSOR)
+ return -EINVAL;
+
+ /* Fan events have Name "X Stall". */
+ if (strstr(event_name, HP_WMI_PATTERN_FAN_ALARM))
+ return HP_WMI_TYPE_AIR_FLOW;
+
+ /* Intrusion events have Name "Hood Intrusion". */
+ if (!strcmp(event_name, HP_WMI_PATTERN_INTRUSION_ALARM))
+ return HP_WMI_TYPE_INTRUSION;
+
+ /*
+ * Temperature events have Name either "Thermal Caution" or
+ * "Thermal Critical". Deal only with "Thermal Critical" events.
+ *
+ * "Thermal Caution" events have Status "Stressed", informing us that
+ * the OperationalStatus of the related sensor has become "Stressed".
+ * However, this is already a fault condition that will clear itself
+ * when the sensor recovers, so we have no further interest in them.
+ */
+ if (!strcmp(event_name, HP_WMI_PATTERN_TEMP_ALARM))
+ return HP_WMI_TYPE_TEMPERATURE;
+
+ return -EINVAL;
+}
+
+/*
+ * interpret_info - interpret sensor for hwmon
+ * @info: pointer to sensor info struct
+ *
+ * Should be called after the numeric sensor member has been updated.
+ */
+static void interpret_info(struct hp_wmi_info *info)
+{
+ const struct hp_wmi_numeric_sensor *nsensor = &info->nsensor;
+
+ info->cached_val = scale_numeric_sensor(nsensor);
+ info->last_updated = jiffies;
+}
+
+/*
+ * hp_wmi_update_info - poll WMI to update sensor info
+ * @state: pointer to driver state
+ * @info: pointer to sensor info struct
+ *
+ * Returns 0 on success, or a negative error code on error.
+ */
+static int hp_wmi_update_info(struct hp_wmi_sensors *state,
+ struct hp_wmi_info *info)
+{
+ struct hp_wmi_numeric_sensor *nsensor = &info->nsensor;
+ struct device *dev = &state->wdev->dev;
+ const union acpi_object *wobj;
+ u8 instance = info->instance;
+ int ret = 0;
+
+ if (time_after(jiffies, info->last_updated + HZ)) {
+ mutex_lock(&state->lock);
+
+ wobj = hp_wmi_get_wobj(HP_WMI_NUMERIC_SENSOR_GUID, instance);
+ if (!wobj) {
+ ret = -EIO;
+ goto out_unlock;
+ }
+
+ update_numeric_sensor_from_wobj(dev, nsensor, wobj);
+
+ interpret_info(info);
+
+ kfree(wobj);
+
+out_unlock:
+ mutex_unlock(&state->lock);
+ }
+
+ return ret;
+}
+
+static int basic_string_show(struct seq_file *seqf, void *ignored)
+{
+ const char *str = seqf->private;
+
+ seq_printf(seqf, "%s\n", str);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(basic_string);
+
+static int fungible_show(struct seq_file *seqf, enum hp_wmi_property prop)
+{
+ struct hp_wmi_numeric_sensor *nsensor;
+ struct hp_wmi_sensors *state;
+ struct hp_wmi_info *info;
+ int err;
+
+ info = seqf->private;
+ state = info->state;
+ nsensor = &info->nsensor;
+
+ err = hp_wmi_update_info(state, info);
+ if (err)
+ return err;
+
+ switch (prop) {
+ case HP_WMI_PROPERTY_OPERATIONAL_STATUS:
+ seq_printf(seqf, "%u\n", nsensor->operational_status);
+ break;
+
+ case HP_WMI_PROPERTY_CURRENT_STATE:
+ seq_printf(seqf, "%s\n", nsensor->current_state);
+ break;
+
+ case HP_WMI_PROPERTY_UNIT_MODIFIER:
+ seq_printf(seqf, "%d\n", nsensor->unit_modifier);
+ break;
+
+ case HP_WMI_PROPERTY_CURRENT_READING:
+ seq_printf(seqf, "%u\n", nsensor->current_reading);
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int operational_status_show(struct seq_file *seqf, void *ignored)
+{
+ return fungible_show(seqf, HP_WMI_PROPERTY_OPERATIONAL_STATUS);
+}
+DEFINE_SHOW_ATTRIBUTE(operational_status);
+
+static int current_state_show(struct seq_file *seqf, void *ignored)
+{
+ return fungible_show(seqf, HP_WMI_PROPERTY_CURRENT_STATE);
+}
+DEFINE_SHOW_ATTRIBUTE(current_state);
+
+static int possible_states_show(struct seq_file *seqf, void *ignored)
+{
+ struct hp_wmi_numeric_sensor *nsensor = seqf->private;
+ u8 i;
+
+ for (i = 0; i < nsensor->size; i++)
+ seq_printf(seqf, "%s%s", i ? "," : "",
+ nsensor->possible_states[i]);
+
+ seq_puts(seqf, "\n");
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(possible_states);
+
+static int unit_modifier_show(struct seq_file *seqf, void *ignored)
+{
+ return fungible_show(seqf, HP_WMI_PROPERTY_UNIT_MODIFIER);
+}
+DEFINE_SHOW_ATTRIBUTE(unit_modifier);
+
+static int current_reading_show(struct seq_file *seqf, void *ignored)
+{
+ return fungible_show(seqf, HP_WMI_PROPERTY_CURRENT_READING);
+}
+DEFINE_SHOW_ATTRIBUTE(current_reading);
+
+/* hp_wmi_devm_debugfs_remove - devm callback for debugfs cleanup */
+static void hp_wmi_devm_debugfs_remove(void *res)
+{
+ debugfs_remove_recursive(res);
+}
+
+/* hp_wmi_debugfs_init - create and populate debugfs directory tree */
+static void hp_wmi_debugfs_init(struct device *dev, struct hp_wmi_info *info,
+ struct hp_wmi_platform_events *pevents,
+ u8 icount, u8 pcount, bool is_new)
+{
+ struct hp_wmi_numeric_sensor *nsensor;
+ char buf[HP_WMI_MAX_STR_SIZE];
+ struct dentry *debugfs;
+ struct dentry *entries;
+ struct dentry *dir;
+ int err;
+ u8 i;
+
+ /* dev_name() gives a not-very-friendly GUID for WMI devices. */
+ scnprintf(buf, sizeof(buf), "hp-wmi-sensors-%u", dev->id);
+
+ debugfs = debugfs_create_dir(buf, NULL);
+ if (IS_ERR(debugfs))
+ return;
+
+ err = devm_add_action_or_reset(dev, hp_wmi_devm_debugfs_remove,
+ debugfs);
+ if (err)
+ return;
+
+ entries = debugfs_create_dir("sensor", debugfs);
+
+ for (i = 0; i < icount; i++, info++) {
+ nsensor = &info->nsensor;
+
+ scnprintf(buf, sizeof(buf), "%u", i);
+ dir = debugfs_create_dir(buf, entries);
+
+ debugfs_create_file("name", 0444, dir,
+ (void *)nsensor->name,
+ &basic_string_fops);
+
+ debugfs_create_file("description", 0444, dir,
+ (void *)nsensor->description,
+ &basic_string_fops);
+
+ debugfs_create_u32("sensor_type", 0444, dir,
+ &nsensor->sensor_type);
+
+ debugfs_create_file("other_sensor_type", 0444, dir,
+ (void *)nsensor->other_sensor_type,
+ &basic_string_fops);
+
+ debugfs_create_file("operational_status", 0444, dir,
+ info, &operational_status_fops);
+
+ debugfs_create_file("possible_states", 0444, dir,
+ nsensor, &possible_states_fops);
+
+ debugfs_create_file("current_state", 0444, dir,
+ info, &current_state_fops);
+
+ debugfs_create_u32("base_units", 0444, dir,
+ &nsensor->base_units);
+
+ debugfs_create_file("unit_modifier", 0444, dir,
+ info, &unit_modifier_fops);
+
+ debugfs_create_file("current_reading", 0444, dir,
+ info, &current_reading_fops);
+
+ if (is_new)
+ debugfs_create_u32("rate_units", 0444, dir,
+ &nsensor->rate_units);
+ }
+
+ if (!pcount)
+ return;
+
+ entries = debugfs_create_dir("platform_events", debugfs);
+
+ for (i = 0; i < pcount; i++, pevents++) {
+ scnprintf(buf, sizeof(buf), "%u", i);
+ dir = debugfs_create_dir(buf, entries);
+
+ debugfs_create_file("name", 0444, dir,
+ (void *)pevents->name,
+ &basic_string_fops);
+
+ debugfs_create_file("description", 0444, dir,
+ (void *)pevents->description,
+ &basic_string_fops);
+
+ debugfs_create_file("source_namespace", 0444, dir,
+ (void *)pevents->source_namespace,
+ &basic_string_fops);
+
+ debugfs_create_file("source_class", 0444, dir,
+ (void *)pevents->source_class,
+ &basic_string_fops);
+
+ debugfs_create_u32("category", 0444, dir,
+ &pevents->category);
+
+ debugfs_create_u32("possible_severity", 0444, dir,
+ &pevents->possible_severity);
+
+ debugfs_create_u32("possible_status", 0444, dir,
+ &pevents->possible_status);
+ }
+}
+
+static umode_t hp_wmi_hwmon_is_visible(const void *drvdata,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ const struct hp_wmi_sensors *state = drvdata;
+ const struct hp_wmi_info *info;
+
+ if (type == hwmon_intrusion)
+ return state->has_intrusion ? 0644 : 0;
+
+ if (!state->info_map[type] || !state->info_map[type][channel])
+ return 0;
+
+ info = state->info_map[type][channel];
+
+ if ((type == hwmon_temp && attr == hwmon_temp_alarm) ||
+ (type == hwmon_fan && attr == hwmon_fan_alarm))
+ return info->has_alarm ? 0444 : 0;
+
+ return 0444;
+}
+
+static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *out_val)
+{
+ struct hp_wmi_sensors *state = dev_get_drvdata(dev);
+ const struct hp_wmi_numeric_sensor *nsensor;
+ struct hp_wmi_info *info;
+ int err;
+
+ if (type == hwmon_intrusion) {
+ *out_val = state->intrusion ? 1 : 0;
+
+ return 0;
+ }
+
+ info = state->info_map[type][channel];
+
+ if ((type == hwmon_temp && attr == hwmon_temp_alarm) ||
+ (type == hwmon_fan && attr == hwmon_fan_alarm)) {
+ *out_val = info->alarm ? 1 : 0;
+ info->alarm = false;
+
+ return 0;
+ }
+
+ nsensor = &info->nsensor;
+
+ err = hp_wmi_update_info(state, info);
+ if (err)
+ return err;
+
+ if ((type == hwmon_temp && attr == hwmon_temp_fault) ||
+ (type == hwmon_fan && attr == hwmon_fan_fault))
+ *out_val = numeric_sensor_has_fault(nsensor);
+ else
+ *out_val = info->cached_val;
+
+ return 0;
+}
+
+static int hp_wmi_hwmon_read_string(struct device *dev,
+ enum hwmon_sensor_types type, u32 attr,
+ int channel, const char **out_str)
+{
+ const struct hp_wmi_sensors *state = dev_get_drvdata(dev);
+ const struct hp_wmi_info *info;
+
+ info = state->info_map[type][channel];
+ *out_str = info->nsensor.name;
+
+ return 0;
+}
+
+static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ struct hp_wmi_sensors *state = dev_get_drvdata(dev);
+
+ if (val)
+ return -EINVAL;
+
+ mutex_lock(&state->lock);
+
+ state->intrusion = false;
+
+ mutex_unlock(&state->lock);
+
+ return 0;
+}
+
+static const struct hwmon_ops hp_wmi_hwmon_ops = {
+ .is_visible = hp_wmi_hwmon_is_visible,
+ .read = hp_wmi_hwmon_read,
+ .read_string = hp_wmi_hwmon_read_string,
+ .write = hp_wmi_hwmon_write,
+};
+
+static struct hwmon_chip_info hp_wmi_chip_info = {
+ .ops = &hp_wmi_hwmon_ops,
+ .info = NULL,
+};
+
+static struct hp_wmi_info *match_fan_event(struct hp_wmi_sensors *state,
+ const char *event_description)
+{
+ struct hp_wmi_info **ptr_info = state->info_map[hwmon_fan];
+ u8 fan_count = state->channel_count[hwmon_fan];
+ struct hp_wmi_info *info;
+ const char *name;
+ u8 i;
+
+ /* Fan event has Description "X Speed". Sensor has Name "X[ Speed]". */
+
+ for (i = 0; i < fan_count; i++, ptr_info++) {
+ info = *ptr_info;
+ name = info->nsensor.name;
+
+ if (strstr(event_description, name))
+ return info;
+ }
+
+ return NULL;
+}
+
+static u8 match_temp_events(struct hp_wmi_sensors *state,
+ const char *event_description,
+ struct hp_wmi_info *temp_info[])
+{
+ struct hp_wmi_info **ptr_info = state->info_map[hwmon_temp];
+ u8 temp_count = state->channel_count[hwmon_temp];
+ struct hp_wmi_info *info;
+ const char *name;
+ u8 count = 0;
+ bool is_cpu;
+ bool is_sys;
+ u8 i;
+
+ /* Description is either "CPU Thermal Index" or "Chassis Thermal Index". */
+
+ is_cpu = !strcmp(event_description, HP_WMI_PATTERN_CPU_TEMP);
+ is_sys = !strcmp(event_description, HP_WMI_PATTERN_SYS_TEMP);
+ if (!is_cpu && !is_sys)
+ return 0;
+
+ /*
+ * CPU event: Match one sensor with Name either "CPU Thermal Index" or
+ * "CPU Temperature", or multiple with Name(s) "CPU[#] Temperature".
+ *
+ * Chassis event: Match one sensor with Name either
+ * "Chassis Thermal Index" or "System Ambient Temperature".
+ */
+
+ for (i = 0; i < temp_count; i++, ptr_info++) {
+ info = *ptr_info;
+ name = info->nsensor.name;
+
+ if ((is_cpu && (!strcmp(name, HP_WMI_PATTERN_CPU_TEMP) ||
+ !strcmp(name, HP_WMI_PATTERN_CPU_TEMP2))) ||
+ (is_sys && (!strcmp(name, HP_WMI_PATTERN_SYS_TEMP) ||
+ !strcmp(name, HP_WMI_PATTERN_SYS_TEMP2)))) {
+ temp_info[0] = info;
+ return 1;
+ }
+
+ if (is_cpu && (strstr(name, HP_WMI_PATTERN_CPU) &&
+ strstr(name, HP_WMI_PATTERN_TEMP)))
+ temp_info[count++] = info;
+ }
+
+ return count;
+}
+
+/* hp_wmi_devm_debugfs_remove - devm callback for WMI event handler removal */
+static void hp_wmi_devm_notify_remove(void *ignored)
+{
+ wmi_remove_notify_handler(HP_WMI_EVENT_GUID);
+}
+
+/* hp_wmi_notify - WMI event notification handler */
+static void hp_wmi_notify(u32 value, void *context)
+{
+ struct hp_wmi_info *temp_info[HP_WMI_MAX_INSTANCES] = {};
+ struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct hp_wmi_sensors *state = context;
+ struct device *dev = &state->wdev->dev;
+ struct hp_wmi_info *fan_info;
+ struct hp_wmi_event event;
+ union acpi_object *wobj;
+ acpi_status err;
+ int event_type;
+ u8 count;
+
+ /*
+ * The following warning may occur in the kernel log:
+ *
+ * ACPI Warning: \_SB.WMID._WED: Return type mismatch -
+ * found Package, expected Integer/String/Buffer
+ *
+ * After using [4] to decode BMOF blobs found in [3], careless copying
+ * of BIOS code seems the most likely explanation for this warning.
+ * HP_WMI_EVENT_GUID refers to \\.\root\WMI\HPBIOS_BIOSEvent on
+ * business-class systems, but it refers to \\.\root\WMI\hpqBEvnt on
+ * non-business-class systems. Per the existing hp-wmi driver, it
+ * looks like an instance of hpqBEvnt delivered as event data may
+ * indeed take the form of a raw ACPI_BUFFER on non-business-class
+ * systems ("may" because ASL shows some BIOSes do strange things).
+ *
+ * In any case, we can ignore this warning, because we always validate
+ * the event data to ensure it is an ACPI_PACKAGE containing a
+ * HPBIOS_BIOSEvent instance.
+ */
+
+ mutex_lock(&state->lock);
+
+ err = wmi_get_event_data(value, &out);
+ if (ACPI_FAILURE(err))
+ goto out_unlock;
+
+ wobj = out.pointer;
+
+ err = populate_event_from_wobj(&event, wobj);
+ if (err) {
+ dev_warn(dev, "Bad event data (ACPI type %d)\n", wobj->type);
+ goto out_free_wobj;
+ }
+
+ event_type = classify_event(event.name, event.category);
+ switch (event_type) {
+ case HP_WMI_TYPE_AIR_FLOW:
+ fan_info = match_fan_event(state, event.description);
+ if (fan_info)
+ fan_info->alarm = true;
+ break;
+
+ case HP_WMI_TYPE_INTRUSION:
+ state->intrusion = true;
+ break;
+
+ case HP_WMI_TYPE_TEMPERATURE:
+ count = match_temp_events(state, event.description, temp_info);
+ while (count)
+ temp_info[--count]->alarm = true;
+ break;
+
+ default:
+ break;
+ }
+
+out_free_wobj:
+ kfree(wobj);
+
+out_unlock:
+ mutex_unlock(&state->lock);
+}
+
+static int init_platform_events(struct device *dev,
+ struct hp_wmi_platform_events **out_pevents,
+ u8 *out_pcount)
+{
+ struct hp_wmi_platform_events *pevents_arr;
+ struct hp_wmi_platform_events *pevents;
+ union acpi_object *wobj;
+ u8 count;
+ int err;
+ u8 i;
+
+ count = hp_wmi_wobj_instance_count(HP_WMI_PLATFORM_EVENTS_GUID);
+ if (!count) {
+ *out_pcount = 0;
+
+ dev_dbg(dev, "No platform events\n");
+
+ return 0;
+ }
+
+ pevents_arr = devm_kcalloc(dev, count, sizeof(*pevents), GFP_KERNEL);
+ if (!pevents_arr)
+ return -ENOMEM;
+
+ for (i = 0, pevents = pevents_arr; i < count; i++, pevents++) {
+ wobj = hp_wmi_get_wobj(HP_WMI_PLATFORM_EVENTS_GUID, i);
+ if (!wobj)
+ return -EIO;
+
+ err = populate_platform_events_from_wobj(dev, pevents, wobj);
+
+ kfree(wobj);
+
+ if (err)
+ return err;
+ }
+
+ *out_pevents = pevents_arr;
+ *out_pcount = count;
+
+ dev_dbg(dev, "Found %u platform events\n", count);
+
+ return 0;
+}
+
+static int init_numeric_sensors(struct hp_wmi_sensors *state,
+ struct hp_wmi_info *connected[],
+ struct hp_wmi_info **out_info,
+ u8 *out_icount, u8 *out_count,
+ bool *out_is_new)
+{
+ struct hp_wmi_info ***info_map = state->info_map;
+ u8 *channel_count = state->channel_count;
+ struct device *dev = &state->wdev->dev;
+ struct hp_wmi_numeric_sensor *nsensor;
+ u8 channel_index[hwmon_max] = {};
+ enum hwmon_sensor_types type;
+ struct hp_wmi_info *info_arr;
+ struct hp_wmi_info *info;
+ union acpi_object *wobj;
+ u8 count = 0;
+ bool is_new;
+ u8 icount;
+ int wtype;
+ int err;
+ u8 c;
+ u8 i;
+
+ icount = hp_wmi_wobj_instance_count(HP_WMI_NUMERIC_SENSOR_GUID);
+ if (!icount)
+ return -ENODATA;
+
+ info_arr = devm_kcalloc(dev, icount, sizeof(*info), GFP_KERNEL);
+ if (!info_arr)
+ return -ENOMEM;
+
+ for (i = 0, info = info_arr; i < icount; i++, info++) {
+ wobj = hp_wmi_get_wobj(HP_WMI_NUMERIC_SENSOR_GUID, i);
+ if (!wobj)
+ return -EIO;
+
+ info->instance = i;
+ info->state = state;
+ nsensor = &info->nsensor;
+
+ err = populate_numeric_sensor_from_wobj(dev, nsensor, wobj,
+ &is_new);
+
+ kfree(wobj);
+
+ if (err)
+ return err;
+
+ if (!numeric_sensor_is_connected(nsensor))
+ continue;
+
+ wtype = classify_numeric_sensor(nsensor);
+ if (wtype < 0)
+ continue;
+
+ type = hp_wmi_hwmon_type_map[wtype];
+
+ channel_count[type]++;
+
+ info->type = type;
+
+ interpret_info(info);
+
+ connected[count++] = info;
+ }
+
+ dev_dbg(dev, "Found %u sensors (%u connected)\n", i, count);
+
+ for (i = 0; i < count; i++) {
+ info = connected[i];
+ type = info->type;
+ c = channel_index[type]++;
+
+ if (!info_map[type]) {
+ info_map[type] = devm_kcalloc(dev, channel_count[type],
+ sizeof(*info_map),
+ GFP_KERNEL);
+ if (!info_map[type])
+ return -ENOMEM;
+ }
+
+ info_map[type][c] = info;
+ }
+
+ *out_info = info_arr;
+ *out_icount = icount;
+ *out_count = count;
+ *out_is_new = is_new;
+
+ return 0;
+}
+
+static bool find_event_attributes(struct hp_wmi_sensors *state,
+ struct hp_wmi_platform_events *pevents,
+ u8 pevents_count)
+{
+ /*
+ * The existence of this HPBIOS_PlatformEvents instance:
+ *
+ * {
+ * Name = "Rear Chassis Fan0 Stall";
+ * Description = "Rear Chassis Fan0 Speed";
+ * Category = 3; // "Sensor"
+ * PossibleSeverity = 25; // "Critical Failure"
+ * PossibleStatus = 5; // "Predictive Failure"
+ * [...]
+ * }
+ *
+ * means that this HPBIOS_BIOSEvent instance may occur:
+ *
+ * {
+ * Name = "Rear Chassis Fan0 Stall";
+ * Description = "Rear Chassis Fan0 Speed";
+ * Category = 3; // "Sensor"
+ * Severity = 25; // "Critical Failure"
+ * Status = 5; // "Predictive Failure"
+ * }
+ *
+ * After the event occurs (e.g. because the fan was unplugged),
+ * polling the related HPBIOS_BIOSNumericSensor instance gives:
+ *
+ * {
+ * Name = "Rear Chassis Fan0";
+ * Description = "Reports rear chassis fan0 speed";
+ * OperationalStatus = 5; // "Predictive Failure", was 3 ("OK")
+ * CurrentReading = 0;
+ * [...]
+ * }
+ *
+ * In this example, the hwmon fan channel for "Rear Chassis Fan0"
+ * should support the alarm flag and have it be set if the related
+ * HPBIOS_BIOSEvent instance occurs.
+ *
+ * In addition to fan events, temperature (CPU/chassis) and intrusion
+ * events are relevant to hwmon [2]. Note that much information in [2]
+ * is unreliable; it is referenced in addition to ACPI dumps [3] merely
+ * to support the conclusion that sensor and event names/descriptions
+ * are systematic enough to allow this driver to match them.
+ *
+ * Complications and limitations:
+ *
+ * - Strings are freeform and may vary, cf. sensor Name "CPU0 Fan"
+ * on a Z420 vs. "CPU Fan Speed" on an EliteOne 800 G1.
+ * - Leading/trailing whitespace is a rare but real possibility [3].
+ * - The HPBIOS_PlatformEvents object may not exist or its instances
+ * may show that the system only has e.g. BIOS setting-related
+ * events (cf. the ProBook 4540s and ProBook 470 G0 [3]).
+ */
+
+ struct hp_wmi_info *temp_info[HP_WMI_MAX_INSTANCES] = {};
+ const char *event_description;
+ struct hp_wmi_info *fan_info;
+ bool has_events = false;
+ const char *event_name;
+ u32 event_category;
+ int event_type;
+ u8 count;
+ u8 i;
+
+ for (i = 0; i < pevents_count; i++, pevents++) {
+ event_name = pevents->name;
+ event_description = pevents->description;
+ event_category = pevents->category;
+
+ event_type = classify_event(event_name, event_category);
+ switch (event_type) {
+ case HP_WMI_TYPE_AIR_FLOW:
+ fan_info = match_fan_event(state, event_description);
+ if (!fan_info)
+ break;
+
+ fan_info->has_alarm = true;
+ has_events = true;
+ break;
+
+ case HP_WMI_TYPE_INTRUSION:
+ state->has_intrusion = true;
+ has_events = true;
+ break;
+
+ case HP_WMI_TYPE_TEMPERATURE:
+ count = match_temp_events(state, event_description,
+ temp_info);
+ if (!count)
+ break;
+
+ while (count)
+ temp_info[--count]->has_alarm = true;
+ has_events = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return has_events;
+}
+
+static int make_chip_info(struct hp_wmi_sensors *state, bool has_events)
+{
+ const struct hwmon_channel_info **ptr_channel_info;
+ struct hp_wmi_info ***info_map = state->info_map;
+ u8 *channel_count = state->channel_count;
+ struct hwmon_channel_info *channel_info;
+ struct device *dev = &state->wdev->dev;
+ enum hwmon_sensor_types type;
+ u8 type_count = 0;
+ u32 *config;
+ u32 attr;
+ u8 count;
+ u8 i;
+
+ if (channel_count[hwmon_temp])
+ channel_count[hwmon_chip] = 1;
+
+ if (has_events && state->has_intrusion)
+ channel_count[hwmon_intrusion] = 1;
+
+ for (type = hwmon_chip; type < hwmon_max; type++)
+ if (channel_count[type])
+ type_count++;
+
+ channel_info = devm_kcalloc(dev, type_count,
+ sizeof(*channel_info), GFP_KERNEL);
+ if (!channel_info)
+ return -ENOMEM;
+
+ ptr_channel_info = devm_kcalloc(dev, type_count + 1,
+ sizeof(*ptr_channel_info), GFP_KERNEL);
+ if (!ptr_channel_info)
+ return -ENOMEM;
+
+ hp_wmi_chip_info.info = ptr_channel_info;
+
+ for (type = hwmon_chip; type < hwmon_max; type++) {
+ count = channel_count[type];
+ if (!count)
+ continue;
+
+ config = devm_kcalloc(dev, count + 1,
+ sizeof(*config), GFP_KERNEL);
+ if (!config)
+ return -ENOMEM;
+
+ attr = hp_wmi_hwmon_attributes[type];
+ channel_info->type = type;
+ channel_info->config = config;
+ memset32(config, attr, count);
+
+ *ptr_channel_info++ = channel_info++;
+
+ if (!has_events || (type != hwmon_temp && type != hwmon_fan))
+ continue;
+
+ attr = type == hwmon_temp ? HWMON_T_ALARM : HWMON_F_ALARM;
+
+ for (i = 0; i < count; i++)
+ if (info_map[type][i]->has_alarm)
+ config[i] |= attr;
+ }
+
+ return 0;
+}
+
+static bool add_event_handler(struct hp_wmi_sensors *state)
+{
+ struct device *dev = &state->wdev->dev;
+ int err;
+
+ err = wmi_install_notify_handler(HP_WMI_EVENT_GUID,
+ hp_wmi_notify, state);
+ if (err) {
+ dev_info(dev, "Failed to subscribe to WMI event\n");
+ return false;
+ }
+
+ err = devm_add_action_or_reset(dev, hp_wmi_devm_notify_remove, NULL);
+ if (err)
+ return false;
+
+ return true;
+}
+
+static int hp_wmi_sensors_init(struct hp_wmi_sensors *state)
+{
+ struct hp_wmi_info *connected[HP_WMI_MAX_INSTANCES];
+ struct hp_wmi_platform_events *pevents;
+ struct device *dev = &state->wdev->dev;
+ struct hp_wmi_info *info;
+ struct device *hwdev;
+ bool has_events;
+ bool is_new;
+ u8 icount;
+ u8 pcount;
+ u8 count;
+ int err;
+
+ err = init_platform_events(dev, &pevents, &pcount);
+ if (err)
+ return err;
+
+ err = init_numeric_sensors(state, connected, &info,
+ &icount, &count, &is_new);
+ if (err)
+ return err;
+
+ if (IS_ENABLED(CONFIG_DEBUG_FS))
+ hp_wmi_debugfs_init(dev, info, pevents, icount, pcount, is_new);
+
+ if (!count)
+ return 0; /* No connected sensors; debugfs only. */
+
+ has_events = find_event_attributes(state, pevents, pcount);
+
+ /* Survive failure to install WMI event handler. */
+ if (has_events && !add_event_handler(state))
+ has_events = false;
+
+ err = make_chip_info(state, has_events);
+ if (err)
+ return err;
+
+ hwdev = devm_hwmon_device_register_with_info(dev, "hp_wmi_sensors",
+ state, &hp_wmi_chip_info,
+ NULL);
+ return PTR_ERR_OR_ZERO(hwdev);
+}
+
+static int hp_wmi_sensors_probe(struct wmi_device *wdev, const void *context)
+{
+ struct device *dev = &wdev->dev;
+ struct hp_wmi_sensors *state;
+
+ state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->wdev = wdev;
+
+ mutex_init(&state->lock);
+
+ dev_set_drvdata(dev, state);
+
+ return hp_wmi_sensors_init(state);
+}
+
+static const struct wmi_device_id hp_wmi_sensors_id_table[] = {
+ { HP_WMI_NUMERIC_SENSOR_GUID, NULL },
+ {},
+};
+
+static struct wmi_driver hp_wmi_sensors_driver = {
+ .driver = { .name = "hp-wmi-sensors" },
+ .id_table = hp_wmi_sensors_id_table,
+ .probe = hp_wmi_sensors_probe,
+};
+module_wmi_driver(hp_wmi_sensors_driver);
+
+MODULE_AUTHOR("James Seo <james@equiv.tech>");
+MODULE_DESCRIPTION("HP WMI Sensors driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 573b83b6c08c..c7dd3f5b2bd5 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -456,6 +456,7 @@ static const char * const hwmon_chip_attrs[] = {
[hwmon_chip_in_samples] = "in_samples",
[hwmon_chip_power_samples] = "power_samples",
[hwmon_chip_temp_samples] = "temp_samples",
+ [hwmon_chip_beep_enable] = "beep_enable",
};
static const char * const hwmon_temp_attr_templates[] = {
@@ -486,6 +487,7 @@ static const char * const hwmon_temp_attr_templates[] = {
[hwmon_temp_reset_history] = "temp%d_reset_history",
[hwmon_temp_rated_min] = "temp%d_rated_min",
[hwmon_temp_rated_max] = "temp%d_rated_max",
+ [hwmon_temp_beep] = "temp%d_beep",
};
static const char * const hwmon_in_attr_templates[] = {
@@ -507,6 +509,7 @@ static const char * const hwmon_in_attr_templates[] = {
[hwmon_in_crit_alarm] = "in%d_crit_alarm",
[hwmon_in_rated_min] = "in%d_rated_min",
[hwmon_in_rated_max] = "in%d_rated_max",
+ [hwmon_in_beep] = "in%d_beep",
};
static const char * const hwmon_curr_attr_templates[] = {
@@ -528,6 +531,7 @@ static const char * const hwmon_curr_attr_templates[] = {
[hwmon_curr_crit_alarm] = "curr%d_crit_alarm",
[hwmon_curr_rated_min] = "curr%d_rated_min",
[hwmon_curr_rated_max] = "curr%d_rated_max",
+ [hwmon_curr_beep] = "curr%d_beep",
};
static const char * const hwmon_power_attr_templates[] = {
@@ -597,6 +601,7 @@ static const char * const hwmon_fan_attr_templates[] = {
[hwmon_fan_min_alarm] = "fan%d_min_alarm",
[hwmon_fan_max_alarm] = "fan%d_max_alarm",
[hwmon_fan_fault] = "fan%d_fault",
+ [hwmon_fan_beep] = "fan%d_beep",
};
static const char * const hwmon_pwm_attr_templates[] = {
@@ -1029,7 +1034,7 @@ EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_groups);
* @name: hwmon name attribute
* @drvdata: driver data to attach to created device
* @chip: pointer to hwmon chip information
- * @groups: pointer to list of driver specific attribute groups
+ * @extra_groups: pointer to list of driver specific attribute groups
*
* Returns the pointer to the new device. The new device is automatically
* unregistered with the parent device.
@@ -1038,7 +1043,7 @@ struct device *
devm_hwmon_device_register_with_info(struct device *dev, const char *name,
void *drvdata,
const struct hwmon_chip_info *chip,
- const struct attribute_group **groups)
+ const struct attribute_group **extra_groups)
{
struct device **ptr, *hwdev;
@@ -1050,7 +1055,7 @@ devm_hwmon_device_register_with_info(struct device *dev, const char *name,
return ERR_PTR(-ENOMEM);
hwdev = hwmon_device_register_with_info(dev, name, drvdata, chip,
- groups);
+ extra_groups);
if (IS_ERR(hwdev))
goto error;
diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c
index 9b58655d2de4..c558143e5285 100644
--- a/drivers/hwmon/ina209.c
+++ b/drivers/hwmon/ina209.c
@@ -594,7 +594,7 @@ static struct i2c_driver ina209_driver = {
.name = "ina209",
.of_match_table = of_match_ptr(ina209_of_match),
},
- .probe_new = ina209_probe,
+ .probe = ina209_probe,
.remove = ina209_remove,
.id_table = ina209_id,
};
diff --git a/drivers/hwmon/ina238.c b/drivers/hwmon/ina238.c
index 8af07bc0c50e..f519c22d3907 100644
--- a/drivers/hwmon/ina238.c
+++ b/drivers/hwmon/ina238.c
@@ -633,7 +633,7 @@ static struct i2c_driver ina238_driver = {
.name = "ina238",
.of_match_table = of_match_ptr(ina238_of_match),
},
- .probe_new = ina238_probe,
+ .probe = ina238_probe,
.id_table = ina238_id,
};
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index fd50d9785ccb..cfd7efef5cdf 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -721,7 +721,7 @@ static struct i2c_driver ina2xx_driver = {
.name = "ina2xx",
.of_match_table = of_match_ptr(ina2xx_of_match),
},
- .probe_new = ina2xx_probe,
+ .probe = ina2xx_probe,
.id_table = ina2xx_id,
};
diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c
index 2735e3782ffb..5ab944056ec0 100644
--- a/drivers/hwmon/ina3221.c
+++ b/drivers/hwmon/ina3221.c
@@ -1010,7 +1010,7 @@ static const struct i2c_device_id ina3221_ids[] = {
MODULE_DEVICE_TABLE(i2c, ina3221_ids);
static struct i2c_driver ina3221_i2c_driver = {
- .probe_new = ina3221_probe,
+ .probe = ina3221_probe,
.remove = ina3221_remove,
.driver = {
.name = INA3221_DRIVER_NAME,
diff --git a/drivers/hwmon/intel-m10-bmc-hwmon.c b/drivers/hwmon/intel-m10-bmc-hwmon.c
index 6512f4bec79a..6500ca548f9c 100644
--- a/drivers/hwmon/intel-m10-bmc-hwmon.c
+++ b/drivers/hwmon/intel-m10-bmc-hwmon.c
@@ -794,3 +794,4 @@ MODULE_DEVICE_TABLE(platform, intel_m10bmc_hwmon_ids);
MODULE_AUTHOR("Intel Corporation");
MODULE_DESCRIPTION("Intel MAX 10 BMC hardware monitor");
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(INTEL_M10_BMC_CORE);
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index eb38f54ebeb6..5deff5e5f693 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -317,31 +317,37 @@ struct it87_devices {
* chips to avoid the problem.
*/
#define FEAT_CONF_NOEXIT BIT(19) /* Chip should not exit conf mode */
+#define FEAT_FOUR_FANS BIT(20) /* Supports four fans */
+#define FEAT_FOUR_PWM BIT(21) /* Supports four fan controls */
+#define FEAT_FOUR_TEMP BIT(22)
+#define FEAT_FANCTL_ONOFF BIT(23) /* chip has FAN_CTL ON/OFF */
static const struct it87_devices it87_devices[] = {
[it87] = {
.name = "it87",
.model = "IT87F",
- .features = FEAT_OLD_AUTOPWM, /* may need to overwrite */
+ .features = FEAT_OLD_AUTOPWM | FEAT_FANCTL_ONOFF,
+ /* may need to overwrite */
},
[it8712] = {
.name = "it8712",
.model = "IT8712F",
- .features = FEAT_OLD_AUTOPWM | FEAT_VID,
- /* may need to overwrite */
+ .features = FEAT_OLD_AUTOPWM | FEAT_VID | FEAT_FANCTL_ONOFF,
+ /* may need to overwrite */
},
[it8716] = {
.name = "it8716",
.model = "IT8716F",
.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
- | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_PWM_FREQ2,
+ | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_PWM_FREQ2
+ | FEAT_FANCTL_ONOFF,
},
[it8718] = {
.name = "it8718",
.model = "IT8718F",
.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
| FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS
- | FEAT_PWM_FREQ2,
+ | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
.old_peci_mask = 0x4,
},
[it8720] = {
@@ -349,7 +355,7 @@ static const struct it87_devices it87_devices[] = {
.model = "IT8720F",
.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
| FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS
- | FEAT_PWM_FREQ2,
+ | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
.old_peci_mask = 0x4,
},
[it8721] = {
@@ -358,7 +364,7 @@ static const struct it87_devices it87_devices[] = {
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
| FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_IN7_INTERNAL
- | FEAT_PWM_FREQ2,
+ | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
.peci_mask = 0x05,
.old_peci_mask = 0x02, /* Actually reports PCH */
},
@@ -367,7 +373,8 @@ static const struct it87_devices it87_devices[] = {
.model = "IT8728F",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_FIVE_FANS
- | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2,
+ | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2
+ | FEAT_FANCTL_ONOFF,
.peci_mask = 0x07,
},
[it8732] = {
@@ -375,7 +382,8 @@ static const struct it87_devices it87_devices[] = {
.model = "IT8732F",
.features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
- | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL,
+ | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_FOUR_FANS
+ | FEAT_FOUR_PWM | FEAT_FANCTL_ONOFF,
.peci_mask = 0x07,
.old_peci_mask = 0x02, /* Actually reports PCH */
},
@@ -384,7 +392,7 @@ static const struct it87_devices it87_devices[] = {
.model = "IT8771E",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
- | FEAT_PWM_FREQ2,
+ | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
/* PECI: guesswork */
/* 12mV ADC (OHM) */
/* 16 bit fans (OHM) */
@@ -396,7 +404,7 @@ static const struct it87_devices it87_devices[] = {
.model = "IT8772E",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
- | FEAT_PWM_FREQ2,
+ | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
/* PECI (coreboot) */
/* 12mV ADC (HWSensors4, OHM) */
/* 16 bit fans (HWSensors4, OHM) */
@@ -407,21 +415,24 @@ static const struct it87_devices it87_devices[] = {
.name = "it8781",
.model = "IT8781F",
.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
- | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2,
+ | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2
+ | FEAT_FANCTL_ONOFF,
.old_peci_mask = 0x4,
},
[it8782] = {
.name = "it8782",
.model = "IT8782F",
.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
- | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2,
+ | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2
+ | FEAT_FANCTL_ONOFF,
.old_peci_mask = 0x4,
},
[it8783] = {
.name = "it8783",
.model = "IT8783E/F",
.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
- | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2,
+ | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2
+ | FEAT_FANCTL_ONOFF,
.old_peci_mask = 0x4,
},
[it8786] = {
@@ -429,7 +440,7 @@ static const struct it87_devices it87_devices[] = {
.model = "IT8786E",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
- | FEAT_PWM_FREQ2,
+ | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF,
.peci_mask = 0x07,
},
[it8790] = {
@@ -437,7 +448,7 @@ static const struct it87_devices it87_devices[] = {
.model = "IT8790E",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
- | FEAT_PWM_FREQ2 | FEAT_CONF_NOEXIT,
+ | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF | FEAT_CONF_NOEXIT,
.peci_mask = 0x07,
},
[it8792] = {
@@ -445,7 +456,8 @@ static const struct it87_devices it87_devices[] = {
.model = "IT8792E/IT8795E",
.features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
- | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_CONF_NOEXIT,
+ | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_FANCTL_ONOFF
+ | FEAT_CONF_NOEXIT,
.peci_mask = 0x07,
.old_peci_mask = 0x02, /* Actually reports PCH */
},
@@ -463,7 +475,7 @@ static const struct it87_devices it87_devices[] = {
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS
| FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2
- | FEAT_SIX_TEMP | FEAT_VIN3_5V,
+ | FEAT_SIX_TEMP | FEAT_VIN3_5V | FEAT_FANCTL_ONOFF,
.peci_mask = 0x07,
},
[it8622] = {
@@ -472,7 +484,7 @@ static const struct it87_devices it87_devices[] = {
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_FIVE_FANS
| FEAT_FIVE_PWM | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2
- | FEAT_AVCC3 | FEAT_VIN3_5V,
+ | FEAT_AVCC3 | FEAT_VIN3_5V | FEAT_FOUR_TEMP,
.peci_mask = 0x07,
.smbus_bitmap = BIT(1) | BIT(2),
},
@@ -482,7 +494,7 @@ static const struct it87_devices it87_devices[] = {
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS
| FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2
- | FEAT_SIX_TEMP | FEAT_VIN3_5V,
+ | FEAT_SIX_TEMP | FEAT_VIN3_5V | FEAT_FANCTL_ONOFF,
.peci_mask = 0x07,
},
[it87952] = {
@@ -490,7 +502,8 @@ static const struct it87_devices it87_devices[] = {
.model = "IT87952E",
.features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
- | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_CONF_NOEXIT,
+ | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_FANCTL_ONOFF
+ | FEAT_CONF_NOEXIT,
.peci_mask = 0x07,
.old_peci_mask = 0x02, /* Actually reports PCH */
},
@@ -508,21 +521,29 @@ static const struct it87_devices it87_devices[] = {
(((data)->features & FEAT_TEMP_OLD_PECI) && \
((data)->old_peci_mask & BIT(nr)))
#define has_fan16_config(data) ((data)->features & FEAT_FAN16_CONFIG)
+#define has_four_fans(data) ((data)->features & (FEAT_FOUR_FANS | \
+ FEAT_FIVE_FANS | \
+ FEAT_SIX_FANS))
#define has_five_fans(data) ((data)->features & (FEAT_FIVE_FANS | \
FEAT_SIX_FANS))
+#define has_six_fans(data) ((data)->features & FEAT_SIX_FANS)
#define has_vid(data) ((data)->features & FEAT_VID)
#define has_in7_internal(data) ((data)->features & FEAT_IN7_INTERNAL)
-#define has_six_fans(data) ((data)->features & FEAT_SIX_FANS)
#define has_avcc3(data) ((data)->features & FEAT_AVCC3)
-#define has_five_pwm(data) ((data)->features & (FEAT_FIVE_PWM \
- | FEAT_SIX_PWM))
+#define has_four_pwm(data) ((data)->features & (FEAT_FOUR_PWM | \
+ FEAT_FIVE_PWM | \
+ FEAT_SIX_PWM))
+#define has_five_pwm(data) ((data)->features & (FEAT_FIVE_PWM | \
+ FEAT_SIX_PWM))
#define has_six_pwm(data) ((data)->features & FEAT_SIX_PWM)
#define has_pwm_freq2(data) ((data)->features & FEAT_PWM_FREQ2)
+#define has_four_temp(data) ((data)->features & FEAT_FOUR_TEMP)
#define has_six_temp(data) ((data)->features & FEAT_SIX_TEMP)
#define has_vin3_5v(data) ((data)->features & FEAT_VIN3_5V)
#define has_conf_noexit(data) ((data)->features & FEAT_CONF_NOEXIT)
#define has_scaling(data) ((data)->features & (FEAT_12MV_ADC | \
FEAT_10_9MV_ADC))
+#define has_fanctl_onoff(data) ((data)->features & FEAT_FANCTL_ONOFF)
struct it87_sio_data {
int sioaddr;
@@ -1229,11 +1250,12 @@ static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type,
static int pwm_mode(const struct it87_data *data, int nr)
{
- if (data->type != it8603 && nr < 3 && !(data->fan_main_ctrl & BIT(nr)))
- return 0; /* Full speed */
+ if (has_fanctl_onoff(data) && nr < 3 &&
+ !(data->fan_main_ctrl & BIT(nr)))
+ return 0; /* Full speed */
if (data->pwm_ctrl[nr] & 0x80)
- return 2; /* Automatic mode */
- if ((data->type == it8603 || nr >= 3) &&
+ return 2; /* Automatic mode */
+ if ((!has_fanctl_onoff(data) || nr >= 3) &&
data->pwm_duty[nr] == pwm_to_reg(data, 0xff))
return 0; /* Full speed */
@@ -1470,7 +1492,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
return err;
if (val == 0) {
- if (nr < 3 && data->type != it8603) {
+ if (nr < 3 && has_fanctl_onoff(data)) {
int tmp;
/* make sure the fan is on when in on/off mode */
tmp = it87_read_value(data, IT87_REG_FAN_CTL);
@@ -1510,7 +1532,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
data->pwm_ctrl[nr] = ctrl;
it87_write_value(data, IT87_REG_PWM[nr], ctrl);
- if (data->type != it8603 && nr < 3) {
+ if (has_fanctl_onoff(data) && nr < 3) {
/* set SmartGuardian mode */
data->fan_main_ctrl |= BIT(nr);
it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
@@ -2730,8 +2752,10 @@ static int __init it87_find(int sioaddr, unsigned short *address,
else
sio_data->skip_in |= BIT(9);
- if (!has_five_pwm(config))
+ if (!has_four_pwm(config))
sio_data->skip_pwm |= BIT(3) | BIT(4) | BIT(5);
+ else if (!has_five_pwm(config))
+ sio_data->skip_pwm |= BIT(4) | BIT(5);
else if (!has_six_pwm(config))
sio_data->skip_pwm |= BIT(5);
@@ -2924,6 +2948,34 @@ static int __init it87_find(int sioaddr, unsigned short *address,
sio_data->beep_pin = superio_inb(sioaddr,
IT87_SIO_BEEP_PIN_REG) & 0x3f;
+ } else if (sio_data->type == it8732) {
+ int reg;
+
+ superio_select(sioaddr, GPIO);
+
+ /* Check for pwm2, fan2 */
+ reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG);
+ if (reg & BIT(1))
+ sio_data->skip_pwm |= BIT(1);
+ if (reg & BIT(2))
+ sio_data->skip_fan |= BIT(1);
+
+ /* Check for pwm3, fan3, fan4 */
+ reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
+ if (reg & BIT(6))
+ sio_data->skip_pwm |= BIT(2);
+ if (reg & BIT(7))
+ sio_data->skip_fan |= BIT(2);
+ if (reg & BIT(5))
+ sio_data->skip_fan |= BIT(3);
+
+ /* Check if AVCC is on VIN3 */
+ reg = superio_inb(sioaddr, IT87_SIO_PINX2_REG);
+ if (reg & BIT(0))
+ sio_data->internal |= BIT(0);
+
+ sio_data->beep_pin = superio_inb(sioaddr,
+ IT87_SIO_BEEP_PIN_REG) & 0x3f;
} else {
int reg;
bool uart6;
@@ -3169,16 +3221,14 @@ static void it87_init_device(struct platform_device *pdev)
it87_check_tachometers_16bit_mode(pdev);
/* Check for additional fans */
- if (has_five_fans(data)) {
- tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
-
- if (tmp & BIT(4))
- data->has_fan |= BIT(3); /* fan4 enabled */
- if (tmp & BIT(5))
- data->has_fan |= BIT(4); /* fan5 enabled */
- if (has_six_fans(data) && (tmp & BIT(2)))
- data->has_fan |= BIT(5); /* fan6 enabled */
- }
+ tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
+
+ if (has_four_fans(data) && (tmp & BIT(4)))
+ data->has_fan |= BIT(3); /* fan4 enabled */
+ if (has_five_fans(data) && (tmp & BIT(5)))
+ data->has_fan |= BIT(4); /* fan5 enabled */
+ if (has_six_fans(data) && (tmp & BIT(2)))
+ data->has_fan |= BIT(5); /* fan6 enabled */
/* Fan input pins may be used for alternative functions */
data->has_fan &= ~sio_data->skip_fan;
@@ -3356,7 +3406,9 @@ static int it87_probe(struct platform_device *pdev)
data->need_in7_reroute = sio_data->need_in7_reroute;
data->has_in = 0x3ff & ~sio_data->skip_in;
- if (has_six_temp(data)) {
+ if (has_four_temp(data)) {
+ data->has_temp |= BIT(3);
+ } else if (has_six_temp(data)) {
u8 reg = it87_read_value(data, IT87_REG_TEMP456_ENABLE);
/* Check for additional temperature sensors */
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c
index 4c60dc520b12..f958e830b23c 100644
--- a/drivers/hwmon/jc42.c
+++ b/drivers/hwmon/jc42.c
@@ -629,7 +629,7 @@ static struct i2c_driver jc42_driver = {
.pm = JC42_DEV_PM_OPS,
.of_match_table = of_match_ptr(jc42_of_ids),
},
- .probe_new = jc42_probe,
+ .probe = jc42_probe,
.remove = jc42_remove,
.id_table = jc42_id,
.detect = jc42_detect,
diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c
index ef5a49cd9149..df69c380cde7 100644
--- a/drivers/hwmon/lineage-pem.c
+++ b/drivers/hwmon/lineage-pem.c
@@ -511,7 +511,7 @@ static struct i2c_driver pem_driver = {
.driver = {
.name = "lineage_pem",
},
- .probe_new = pem_probe,
+ .probe = pem_probe,
.id_table = pem_id,
};
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 9ab2cab4c710..6972454eb4e0 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -1164,7 +1164,7 @@ static struct i2c_driver lm63_driver = {
.name = "lm63",
.of_match_table = of_match_ptr(lm63_of_match),
},
- .probe_new = lm63_probe,
+ .probe = lm63_probe,
.id_table = lm63_id,
.detect = lm63_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c
index b6433ae2d75c..637d35c5ae23 100644
--- a/drivers/hwmon/lm73.c
+++ b/drivers/hwmon/lm73.c
@@ -277,7 +277,7 @@ static struct i2c_driver lm73_driver = {
.name = "lm73",
.of_match_table = lm73_of_match,
},
- .probe_new = lm73_probe,
+ .probe = lm73_probe,
.id_table = lm73_ids,
.detect = lm73_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index dbb99ea4a0ec..72e634d1b857 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -548,7 +548,7 @@ static const struct regmap_config lm75_regmap_config = {
.writeable_reg = lm75_is_writeable_reg,
.volatile_reg = lm75_is_volatile_reg,
.val_format_endian = REGMAP_ENDIAN_BIG,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.use_single_read = true,
.use_single_write = true,
};
@@ -945,7 +945,7 @@ static struct i2c_driver lm75_driver = {
.of_match_table = of_match_ptr(lm75_of_match),
.pm = LM75_DEV_PM_OPS,
},
- .probe_new = lm75_probe,
+ .probe = lm75_probe,
.id_table = lm75_ids,
.detect = lm75_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 645cb2191abe..8b9862519178 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -348,7 +348,7 @@ static struct i2c_driver lm77_driver = {
.driver = {
.name = "lm77",
},
- .probe_new = lm77_probe,
+ .probe = lm77_probe,
.id_table = lm77_id,
.detect = lm77_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 694e171cab7f..b739c354311b 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -662,7 +662,7 @@ static struct i2c_driver lm78_driver = {
.driver = {
.name = "lm78",
},
- .probe_new = lm78_i2c_probe,
+ .probe = lm78_i2c_probe,
.id_table = lm78_i2c_id,
.detect = lm78_i2c_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 35db0b97f912..63c7831bd3e1 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -633,7 +633,7 @@ static struct i2c_driver lm80_driver = {
.driver = {
.name = "lm80",
},
- .probe_new = lm80_probe,
+ .probe = lm80_probe,
.id_table = lm80_id,
.detect = lm80_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index bcaf31ec176e..5befedca6abb 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -454,7 +454,7 @@ static struct i2c_driver lm83_driver = {
.driver = {
.name = "lm83",
},
- .probe_new = lm83_probe,
+ .probe = lm83_probe,
.id_table = lm83_id,
.detect = lm83_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index 8d33c2484755..8540178f5b74 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -1698,7 +1698,7 @@ static struct i2c_driver lm85_driver = {
.name = "lm85",
.of_match_table = of_match_ptr(lm85_of_match),
},
- .probe_new = lm85_probe,
+ .probe = lm85_probe,
.id_table = lm85_id,
.detect = lm85_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index 818fb6195245..2195a735d28e 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -994,7 +994,7 @@ static struct i2c_driver lm87_driver = {
.name = "lm87",
.of_match_table = lm87_of_match,
},
- .probe_new = lm87_probe,
+ .probe = lm87_probe,
.id_table = lm87_id,
.detect = lm87_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 6498d5acf705..90101c236f35 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -2972,7 +2972,7 @@ static struct i2c_driver lm90_driver = {
.of_match_table = of_match_ptr(lm90_of_match),
.pm = pm_sleep_ptr(&lm90_pm_ops),
},
- .probe_new = lm90_probe,
+ .probe = lm90_probe,
.alert = lm90_alert,
.id_table = lm90_id,
.detect = lm90_detect,
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 2ff3044a677d..46579a3e1715 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -330,7 +330,7 @@ static struct i2c_driver lm92_driver = {
.driver = {
.name = "lm92",
},
- .probe_new = lm92_probe,
+ .probe = lm92_probe,
.id_table = lm92_id,
.detect = lm92_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c
index 4cf50d5f4f59..75bca805720e 100644
--- a/drivers/hwmon/lm93.c
+++ b/drivers/hwmon/lm93.c
@@ -2635,7 +2635,7 @@ static struct i2c_driver lm93_driver = {
.driver = {
.name = "lm93",
},
- .probe_new = lm93_probe,
+ .probe = lm93_probe,
.id_table = lm93_id,
.detect = lm93_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm95234.c b/drivers/hwmon/lm95234.c
index b4a9d0c223c4..67b9d7636ee4 100644
--- a/drivers/hwmon/lm95234.c
+++ b/drivers/hwmon/lm95234.c
@@ -720,7 +720,7 @@ static struct i2c_driver lm95234_driver = {
.driver = {
.name = DRVNAME,
},
- .probe_new = lm95234_probe,
+ .probe = lm95234_probe,
.id_table = lm95234_id,
.detect = lm95234_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c
index 647a90570bc6..475551f5024b 100644
--- a/drivers/hwmon/lm95241.c
+++ b/drivers/hwmon/lm95241.c
@@ -468,7 +468,7 @@ static struct i2c_driver lm95241_driver = {
.driver = {
.name = DEVNAME,
},
- .probe_new = lm95241_probe,
+ .probe = lm95241_probe,
.id_table = lm95241_id,
.detect = lm95241_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c
index 4236d1e0544d..17ff54bd4015 100644
--- a/drivers/hwmon/lm95245.c
+++ b/drivers/hwmon/lm95245.c
@@ -518,7 +518,7 @@ static const struct regmap_config lm95245_regmap_config = {
.val_bits = 8,
.writeable_reg = lm95245_is_writeable_reg,
.volatile_reg = lm95245_is_volatile_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.use_single_read = true,
.use_single_write = true,
};
@@ -597,7 +597,7 @@ static struct i2c_driver lm95245_driver = {
.name = "lm95245",
.of_match_table = of_match_ptr(lm95245_of_match),
},
- .probe_new = lm95245_probe,
+ .probe = lm95245_probe,
.id_table = lm95245_id,
.detect = lm95245_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c
index 3494f7261ebf..45b87a863cae 100644
--- a/drivers/hwmon/ltc2945.c
+++ b/drivers/hwmon/ltc2945.c
@@ -519,7 +519,7 @@ static struct i2c_driver ltc2945_driver = {
.name = "ltc2945",
.of_match_table = of_match_ptr(ltc2945_of_match),
},
- .probe_new = ltc2945_probe,
+ .probe = ltc2945_probe,
.id_table = ltc2945_id,
};
diff --git a/drivers/hwmon/ltc2947-i2c.c b/drivers/hwmon/ltc2947-i2c.c
index 96852bc8a964..33f574bf2ce7 100644
--- a/drivers/hwmon/ltc2947-i2c.c
+++ b/drivers/hwmon/ltc2947-i2c.c
@@ -38,7 +38,7 @@ static struct i2c_driver ltc2947_driver = {
.of_match_table = ltc2947_of_match,
.pm = pm_sleep_ptr(&ltc2947_pm_ops),
},
- .probe_new = ltc2947_probe,
+ .probe = ltc2947_probe,
.id_table = ltc2947_id,
};
module_i2c_driver(ltc2947_driver);
diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c
index 689f788b8563..1ad362c0fd2c 100644
--- a/drivers/hwmon/ltc2990.c
+++ b/drivers/hwmon/ltc2990.c
@@ -268,7 +268,7 @@ static struct i2c_driver ltc2990_i2c_driver = {
.driver = {
.name = "ltc2990",
},
- .probe_new = ltc2990_i2c_probe,
+ .probe = ltc2990_i2c_probe,
.id_table = ltc2990_i2c_id,
};
diff --git a/drivers/hwmon/ltc2992.c b/drivers/hwmon/ltc2992.c
index 429a7f5837f0..589bcd07ce7f 100644
--- a/drivers/hwmon/ltc2992.c
+++ b/drivers/hwmon/ltc2992.c
@@ -928,7 +928,7 @@ static struct i2c_driver ltc2992_i2c_driver = {
.name = "ltc2992",
.of_match_table = ltc2992_of_match,
},
- .probe_new = ltc2992_i2c_probe,
+ .probe = ltc2992_i2c_probe,
.id_table = ltc2992_i2c_id,
};
diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c
index e3ac004c1ed1..f42ac3c9475e 100644
--- a/drivers/hwmon/ltc4151.c
+++ b/drivers/hwmon/ltc4151.c
@@ -205,7 +205,7 @@ static struct i2c_driver ltc4151_driver = {
.name = "ltc4151",
.of_match_table = of_match_ptr(ltc4151_match),
},
- .probe_new = ltc4151_probe,
+ .probe = ltc4151_probe,
.id_table = ltc4151_id,
};
diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c
index fa43d26ddd4f..66fd28f713ab 100644
--- a/drivers/hwmon/ltc4215.c
+++ b/drivers/hwmon/ltc4215.c
@@ -255,7 +255,7 @@ static struct i2c_driver ltc4215_driver = {
.driver = {
.name = "ltc4215",
},
- .probe_new = ltc4215_probe,
+ .probe = ltc4215_probe,
.id_table = ltc4215_id,
};
diff --git a/drivers/hwmon/ltc4222.c b/drivers/hwmon/ltc4222.c
index d2027ca5c925..9098ef521739 100644
--- a/drivers/hwmon/ltc4222.c
+++ b/drivers/hwmon/ltc4222.c
@@ -210,7 +210,7 @@ static struct i2c_driver ltc4222_driver = {
.driver = {
.name = "ltc4222",
},
- .probe_new = ltc4222_probe,
+ .probe = ltc4222_probe,
.id_table = ltc4222_id,
};
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
index fb9bc8dbe99b..b90184a3e0ec 100644
--- a/drivers/hwmon/ltc4245.c
+++ b/drivers/hwmon/ltc4245.c
@@ -479,7 +479,7 @@ static struct i2c_driver ltc4245_driver = {
.driver = {
.name = "ltc4245",
},
- .probe_new = ltc4245_probe,
+ .probe = ltc4245_probe,
.id_table = ltc4245_id,
};
diff --git a/drivers/hwmon/ltc4260.c b/drivers/hwmon/ltc4260.c
index 75e89cec381e..52f7a809b27b 100644
--- a/drivers/hwmon/ltc4260.c
+++ b/drivers/hwmon/ltc4260.c
@@ -173,7 +173,7 @@ static struct i2c_driver ltc4260_driver = {
.driver = {
.name = "ltc4260",
},
- .probe_new = ltc4260_probe,
+ .probe = ltc4260_probe,
.id_table = ltc4260_id,
};
diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c
index b91cc4fe84e5..509e68176c7a 100644
--- a/drivers/hwmon/ltc4261.c
+++ b/drivers/hwmon/ltc4261.c
@@ -233,7 +233,7 @@ static struct i2c_driver ltc4261_driver = {
.driver = {
.name = "ltc4261",
},
- .probe_new = ltc4261_probe,
+ .probe = ltc4261_probe,
.id_table = ltc4261_id,
};
diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
index 4c5487aeb3cf..5cc08c720b52 100644
--- a/drivers/hwmon/max1111.c
+++ b/drivers/hwmon/max1111.c
@@ -80,6 +80,7 @@ static int max1111_read(struct device *dev, int channel)
#ifdef CONFIG_SHARPSL_PM
static struct max1111_data *the_max1111;
+int max1111_read_channel(int channel);
int max1111_read_channel(int channel)
{
if (!the_max1111 || !the_max1111->spi)
diff --git a/drivers/hwmon/max127.c b/drivers/hwmon/max127.c
index 49de1d2be294..ee5ead06d612 100644
--- a/drivers/hwmon/max127.c
+++ b/drivers/hwmon/max127.c
@@ -339,7 +339,7 @@ static struct i2c_driver max127_driver = {
.driver = {
.name = "max127",
},
- .probe_new = max127_probe,
+ .probe = max127_probe,
.id_table = max127_id,
};
diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c
index daa5d8af1e69..aa38c45adc09 100644
--- a/drivers/hwmon/max16065.c
+++ b/drivers/hwmon/max16065.c
@@ -600,7 +600,7 @@ static struct i2c_driver max16065_driver = {
.driver = {
.name = "max16065",
},
- .probe_new = max16065_probe,
+ .probe = max16065_probe,
.id_table = max16065_id,
};
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 445c77197f69..500dc926a7a7 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -305,7 +305,7 @@ static struct i2c_driver max1619_driver = {
.name = "max1619",
.of_match_table = of_match_ptr(max1619_of_match),
},
- .probe_new = max1619_probe,
+ .probe = max1619_probe,
.id_table = max1619_id,
.detect = max1619_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c
index 9f748973d6a3..c4a02edefbee 100644
--- a/drivers/hwmon/max1668.c
+++ b/drivers/hwmon/max1668.c
@@ -435,7 +435,7 @@ static struct i2c_driver max1668_driver = {
.driver = {
.name = "max1668",
},
- .probe_new = max1668_probe,
+ .probe = max1668_probe,
.id_table = max1668_id,
.detect = max1668_detect,
.address_list = max1668_addr_list,
diff --git a/drivers/hwmon/max31730.c b/drivers/hwmon/max31730.c
index 924333d89ce4..b1300ca9db1f 100644
--- a/drivers/hwmon/max31730.c
+++ b/drivers/hwmon/max31730.c
@@ -427,7 +427,7 @@ static struct i2c_driver max31730_driver = {
.of_match_table = of_match_ptr(max31730_of_match),
.pm = pm_sleep_ptr(&max31730_pm_ops),
},
- .probe_new = max31730_probe,
+ .probe = max31730_probe,
.id_table = max31730_ids,
.detect = max31730_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/max31760.c b/drivers/hwmon/max31760.c
index 4489110f109c..79945eb466ae 100644
--- a/drivers/hwmon/max31760.c
+++ b/drivers/hwmon/max31760.c
@@ -584,7 +584,7 @@ static struct i2c_driver max31760_driver = {
.of_match_table = max31760_of_match,
.pm = pm_ptr(&max31760_pm_ops)
},
- .probe_new = max31760_probe,
+ .probe = max31760_probe,
.id_table = max31760_id
};
module_i2c_driver(max31760_driver);
diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c
index 6caba6e8ee8f..0cd44c1e998a 100644
--- a/drivers/hwmon/max31790.c
+++ b/drivers/hwmon/max31790.c
@@ -544,7 +544,7 @@ MODULE_DEVICE_TABLE(i2c, max31790_id);
static struct i2c_driver max31790_driver = {
.class = I2C_CLASS_HWMON,
- .probe_new = max31790_probe,
+ .probe = max31790_probe,
.driver = {
.name = "max31790",
},
diff --git a/drivers/hwmon/max31827.c b/drivers/hwmon/max31827.c
new file mode 100644
index 000000000000..602f4e4f81ff
--- /dev/null
+++ b/drivers/hwmon/max31827.c
@@ -0,0 +1,466 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * max31827.c - Support for Maxim Low-Power Switch
+ *
+ * Copyright (c) 2023 Daniel Matyas <daniel.matyas@analog.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/hwmon.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+
+#define MAX31827_T_REG 0x0
+#define MAX31827_CONFIGURATION_REG 0x2
+#define MAX31827_TH_REG 0x4
+#define MAX31827_TL_REG 0x6
+#define MAX31827_TH_HYST_REG 0x8
+#define MAX31827_TL_HYST_REG 0xA
+
+#define MAX31827_CONFIGURATION_1SHOT_MASK BIT(0)
+#define MAX31827_CONFIGURATION_CNV_RATE_MASK GENMASK(3, 1)
+#define MAX31827_CONFIGURATION_U_TEMP_STAT_MASK BIT(14)
+#define MAX31827_CONFIGURATION_O_TEMP_STAT_MASK BIT(15)
+
+#define MAX31827_12_BIT_CNV_TIME 141
+
+#define MAX31827_CNV_1_DIV_64_HZ 0x1
+#define MAX31827_CNV_1_DIV_32_HZ 0x2
+#define MAX31827_CNV_1_DIV_16_HZ 0x3
+#define MAX31827_CNV_1_DIV_4_HZ 0x4
+#define MAX31827_CNV_1_HZ 0x5
+#define MAX31827_CNV_4_HZ 0x6
+#define MAX31827_CNV_8_HZ 0x7
+
+#define MAX31827_16_BIT_TO_M_DGR(x) (sign_extend32(x, 15) * 1000 / 16)
+#define MAX31827_M_DGR_TO_16_BIT(x) (((x) << 4) / 1000)
+#define MAX31827_DEVICE_ENABLE(x) ((x) ? 0xA : 0x0)
+
+struct max31827_state {
+ /*
+ * Prevent simultaneous access to the i2c client.
+ */
+ struct mutex lock;
+ struct regmap *regmap;
+ bool enable;
+};
+
+static const struct regmap_config max31827_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = 0xA,
+};
+
+static int write_alarm_val(struct max31827_state *st, unsigned int reg,
+ long val)
+{
+ unsigned int cfg;
+ unsigned int tmp;
+ int ret;
+
+ val = MAX31827_M_DGR_TO_16_BIT(val);
+
+ /*
+ * Before the Temperature Threshold Alarm and Alarm Hysteresis Threshold
+ * register values are changed over I2C, the part must be in shutdown
+ * mode.
+ *
+ * Mutex is used to ensure, that some other process doesn't change the
+ * configuration register.
+ */
+ mutex_lock(&st->lock);
+
+ if (!st->enable) {
+ ret = regmap_write(st->regmap, reg, val);
+ goto unlock;
+ }
+
+ ret = regmap_read(st->regmap, MAX31827_CONFIGURATION_REG, &cfg);
+ if (ret)
+ goto unlock;
+
+ tmp = cfg & ~(MAX31827_CONFIGURATION_1SHOT_MASK |
+ MAX31827_CONFIGURATION_CNV_RATE_MASK);
+ ret = regmap_write(st->regmap, MAX31827_CONFIGURATION_REG, tmp);
+ if (ret)
+ goto unlock;
+
+ ret = regmap_write(st->regmap, reg, val);
+ if (ret)
+ goto unlock;
+
+ ret = regmap_write(st->regmap, MAX31827_CONFIGURATION_REG, cfg);
+
+unlock:
+ mutex_unlock(&st->lock);
+ return ret;
+}
+
+static umode_t max31827_is_visible(const void *state,
+ enum hwmon_sensor_types type, u32 attr,
+ int channel)
+{
+ if (type == hwmon_temp) {
+ switch (attr) {
+ case hwmon_temp_enable:
+ case hwmon_temp_max:
+ case hwmon_temp_min:
+ case hwmon_temp_max_hyst:
+ case hwmon_temp_min_hyst:
+ return 0644;
+ case hwmon_temp_input:
+ case hwmon_temp_min_alarm:
+ case hwmon_temp_max_alarm:
+ return 0444;
+ default:
+ return 0;
+ }
+ } else if (type == hwmon_chip) {
+ if (attr == hwmon_chip_update_interval)
+ return 0644;
+ }
+
+ return 0;
+}
+
+static int max31827_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct max31827_state *st = dev_get_drvdata(dev);
+ unsigned int uval;
+ int ret = 0;
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_enable:
+ ret = regmap_read(st->regmap,
+ MAX31827_CONFIGURATION_REG, &uval);
+ if (ret)
+ break;
+
+ uval = FIELD_GET(MAX31827_CONFIGURATION_1SHOT_MASK |
+ MAX31827_CONFIGURATION_CNV_RATE_MASK,
+ uval);
+ *val = !!uval;
+
+ break;
+ case hwmon_temp_input:
+ mutex_lock(&st->lock);
+
+ if (!st->enable) {
+ /*
+ * This operation requires mutex protection,
+ * because the chip configuration should not
+ * be changed during the conversion process.
+ */
+
+ ret = regmap_update_bits(st->regmap,
+ MAX31827_CONFIGURATION_REG,
+ MAX31827_CONFIGURATION_1SHOT_MASK,
+ 1);
+ if (ret) {
+ mutex_unlock(&st->lock);
+ return ret;
+ }
+
+ msleep(MAX31827_12_BIT_CNV_TIME);
+ }
+ ret = regmap_read(st->regmap, MAX31827_T_REG, &uval);
+
+ mutex_unlock(&st->lock);
+
+ if (ret)
+ break;
+
+ *val = MAX31827_16_BIT_TO_M_DGR(uval);
+
+ break;
+ case hwmon_temp_max:
+ ret = regmap_read(st->regmap, MAX31827_TH_REG, &uval);
+ if (ret)
+ break;
+
+ *val = MAX31827_16_BIT_TO_M_DGR(uval);
+ break;
+ case hwmon_temp_max_hyst:
+ ret = regmap_read(st->regmap, MAX31827_TH_HYST_REG,
+ &uval);
+ if (ret)
+ break;
+
+ *val = MAX31827_16_BIT_TO_M_DGR(uval);
+ break;
+ case hwmon_temp_max_alarm:
+ ret = regmap_read(st->regmap,
+ MAX31827_CONFIGURATION_REG, &uval);
+ if (ret)
+ break;
+
+ *val = FIELD_GET(MAX31827_CONFIGURATION_O_TEMP_STAT_MASK,
+ uval);
+ break;
+ case hwmon_temp_min:
+ ret = regmap_read(st->regmap, MAX31827_TL_REG, &uval);
+ if (ret)
+ break;
+
+ *val = MAX31827_16_BIT_TO_M_DGR(uval);
+ break;
+ case hwmon_temp_min_hyst:
+ ret = regmap_read(st->regmap, MAX31827_TL_HYST_REG,
+ &uval);
+ if (ret)
+ break;
+
+ *val = MAX31827_16_BIT_TO_M_DGR(uval);
+ break;
+ case hwmon_temp_min_alarm:
+ ret = regmap_read(st->regmap,
+ MAX31827_CONFIGURATION_REG, &uval);
+ if (ret)
+ break;
+
+ *val = FIELD_GET(MAX31827_CONFIGURATION_U_TEMP_STAT_MASK,
+ uval);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ break;
+
+ case hwmon_chip:
+ if (attr == hwmon_chip_update_interval) {
+ ret = regmap_read(st->regmap,
+ MAX31827_CONFIGURATION_REG, &uval);
+ if (ret)
+ break;
+
+ uval = FIELD_GET(MAX31827_CONFIGURATION_CNV_RATE_MASK,
+ uval);
+ switch (uval) {
+ case MAX31827_CNV_1_DIV_64_HZ:
+ *val = 64000;
+ break;
+ case MAX31827_CNV_1_DIV_32_HZ:
+ *val = 32000;
+ break;
+ case MAX31827_CNV_1_DIV_16_HZ:
+ *val = 16000;
+ break;
+ case MAX31827_CNV_1_DIV_4_HZ:
+ *val = 4000;
+ break;
+ case MAX31827_CNV_1_HZ:
+ *val = 1000;
+ break;
+ case MAX31827_CNV_4_HZ:
+ *val = 250;
+ break;
+ case MAX31827_CNV_8_HZ:
+ *val = 125;
+ break;
+ default:
+ *val = 0;
+ break;
+ }
+ }
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static int max31827_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ struct max31827_state *st = dev_get_drvdata(dev);
+ int ret;
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_enable:
+ if (val >> 1)
+ return -EINVAL;
+
+ mutex_lock(&st->lock);
+ /**
+ * The chip should not be enabled while a conversion is
+ * performed. Neither should the chip be enabled when
+ * the alarm values are changed.
+ */
+
+ st->enable = val;
+
+ ret = regmap_update_bits(st->regmap,
+ MAX31827_CONFIGURATION_REG,
+ MAX31827_CONFIGURATION_1SHOT_MASK |
+ MAX31827_CONFIGURATION_CNV_RATE_MASK,
+ MAX31827_DEVICE_ENABLE(val));
+
+ mutex_unlock(&st->lock);
+
+ return ret;
+
+ case hwmon_temp_max:
+ return write_alarm_val(st, MAX31827_TH_REG, val);
+
+ case hwmon_temp_max_hyst:
+ return write_alarm_val(st, MAX31827_TH_HYST_REG, val);
+
+ case hwmon_temp_min:
+ return write_alarm_val(st, MAX31827_TL_REG, val);
+
+ case hwmon_temp_min_hyst:
+ return write_alarm_val(st, MAX31827_TL_HYST_REG, val);
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ case hwmon_chip:
+ if (attr == hwmon_chip_update_interval) {
+ if (!st->enable)
+ return -EINVAL;
+
+ switch (val) {
+ case 125:
+ val = MAX31827_CNV_8_HZ;
+ break;
+ case 250:
+ val = MAX31827_CNV_4_HZ;
+ break;
+ case 1000:
+ val = MAX31827_CNV_1_HZ;
+ break;
+ case 4000:
+ val = MAX31827_CNV_1_DIV_4_HZ;
+ break;
+ case 16000:
+ val = MAX31827_CNV_1_DIV_16_HZ;
+ break;
+ case 32000:
+ val = MAX31827_CNV_1_DIV_32_HZ;
+ break;
+ case 64000:
+ val = MAX31827_CNV_1_DIV_64_HZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ val = FIELD_PREP(MAX31827_CONFIGURATION_CNV_RATE_MASK,
+ val);
+
+ return regmap_update_bits(st->regmap,
+ MAX31827_CONFIGURATION_REG,
+ MAX31827_CONFIGURATION_CNV_RATE_MASK,
+ val);
+ }
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static int max31827_init_client(struct max31827_state *st)
+{
+ st->enable = true;
+
+ return regmap_update_bits(st->regmap, MAX31827_CONFIGURATION_REG,
+ MAX31827_CONFIGURATION_1SHOT_MASK |
+ MAX31827_CONFIGURATION_CNV_RATE_MASK,
+ MAX31827_DEVICE_ENABLE(1));
+}
+
+static const struct hwmon_channel_info *max31827_info[] = {
+ HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT | HWMON_T_MIN |
+ HWMON_T_MIN_HYST | HWMON_T_MIN_ALARM |
+ HWMON_T_MAX | HWMON_T_MAX_HYST |
+ HWMON_T_MAX_ALARM),
+ HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL),
+ NULL,
+};
+
+static const struct hwmon_ops max31827_hwmon_ops = {
+ .is_visible = max31827_is_visible,
+ .read = max31827_read,
+ .write = max31827_write,
+};
+
+static const struct hwmon_chip_info max31827_chip_info = {
+ .ops = &max31827_hwmon_ops,
+ .info = max31827_info,
+};
+
+static int max31827_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct max31827_state *st;
+ int err;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
+ return -EOPNOTSUPP;
+
+ st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
+ if (!st)
+ return -ENOMEM;
+
+ mutex_init(&st->lock);
+
+ st->regmap = devm_regmap_init_i2c(client, &max31827_regmap);
+ if (IS_ERR(st->regmap))
+ return dev_err_probe(dev, PTR_ERR(st->regmap),
+ "Failed to allocate regmap.\n");
+
+ err = max31827_init_client(st);
+ if (err)
+ return err;
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, st,
+ &max31827_chip_info,
+ NULL);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id max31827_i2c_ids[] = {
+ { "max31827", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max31827_i2c_ids);
+
+static const struct of_device_id max31827_of_match[] = {
+ { .compatible = "adi,max31827" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max31827_of_match);
+
+static struct i2c_driver max31827_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "max31827",
+ .of_match_table = max31827_of_match,
+ },
+ .probe = max31827_probe,
+ .id_table = max31827_i2c_ids,
+};
+module_i2c_driver(max31827_driver);
+
+MODULE_AUTHOR("Daniel Matyas <daniel.matyas@analog.com>");
+MODULE_DESCRIPTION("Maxim MAX31827 low-power temperature switch driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/max6620.c b/drivers/hwmon/max6620.c
index 0f277d945ea2..5d12fb9c9786 100644
--- a/drivers/hwmon/max6620.c
+++ b/drivers/hwmon/max6620.c
@@ -503,7 +503,7 @@ static struct i2c_driver max6620_driver = {
.driver = {
.name = "max6620",
},
- .probe_new = max6620_probe,
+ .probe = max6620_probe,
.id_table = max6620_id,
};
diff --git a/drivers/hwmon/max6621.c b/drivers/hwmon/max6621.c
index 0656eb1e7959..7f709fd1af89 100644
--- a/drivers/hwmon/max6621.c
+++ b/drivers/hwmon/max6621.c
@@ -554,7 +554,7 @@ static struct i2c_driver max6621_driver = {
.name = MAX6621_DRV_NAME,
.of_match_table = of_match_ptr(max6621_of_match),
},
- .probe_new = max6621_probe,
+ .probe = max6621_probe,
.id_table = max6621_id,
};
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
index 9b895402c80d..caf527154fca 100644
--- a/drivers/hwmon/max6639.c
+++ b/drivers/hwmon/max6639.c
@@ -624,7 +624,7 @@ static struct i2c_driver max6639_driver = {
.name = "max6639",
.pm = pm_sleep_ptr(&max6639_pm_ops),
},
- .probe_new = max6639_probe,
+ .probe = max6639_probe,
.id_table = max6639_id,
.detect = max6639_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/max6642.c b/drivers/hwmon/max6642.c
index 47ea34ff78f3..8b2e4d6101a2 100644
--- a/drivers/hwmon/max6642.c
+++ b/drivers/hwmon/max6642.c
@@ -301,7 +301,7 @@ static struct i2c_driver max6642_driver = {
.driver = {
.name = "max6642",
},
- .probe_new = max6642_probe,
+ .probe = max6642_probe,
.id_table = max6642_id,
.detect = max6642_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c
index 19e2c762ed2d..cc8428a3045d 100644
--- a/drivers/hwmon/max6650.c
+++ b/drivers/hwmon/max6650.c
@@ -819,7 +819,7 @@ static struct i2c_driver max6650_driver = {
.name = "max6650",
.of_match_table = of_match_ptr(max6650_dt_match),
},
- .probe_new = max6650_probe,
+ .probe = max6650_probe,
.id_table = max6650_id,
};
diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c
index 2895cea54193..3a67778f111c 100644
--- a/drivers/hwmon/max6697.c
+++ b/drivers/hwmon/max6697.c
@@ -786,7 +786,7 @@ static struct i2c_driver max6697_driver = {
.name = "max6697",
.of_match_table = of_match_ptr(max6697_of_match),
},
- .probe_new = max6697_probe,
+ .probe = max6697_probe,
.id_table = max6697_id,
};
diff --git a/drivers/hwmon/mc34vr500.c b/drivers/hwmon/mc34vr500.c
index 6a7a950a9332..0c8fd3fce83e 100644
--- a/drivers/hwmon/mc34vr500.c
+++ b/drivers/hwmon/mc34vr500.c
@@ -251,7 +251,7 @@ static struct i2c_driver mc34vr500_driver = {
.name = "mc34vr500",
.of_match_table = of_match_ptr(mc34vr500_of_match),
},
- .probe_new = mc34vr500_probe,
+ .probe = mc34vr500_probe,
.id_table = mc34vr500_id,
};
diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c
index a5f7a294f33d..127e15ff3e76 100644
--- a/drivers/hwmon/mcp3021.c
+++ b/drivers/hwmon/mcp3021.c
@@ -198,7 +198,7 @@ static struct i2c_driver mcp3021_driver = {
.name = "mcp3021",
.of_match_table = of_match_ptr(of_mcp3021_match),
},
- .probe_new = mcp3021_probe,
+ .probe = mcp3021_probe,
.id_table = mcp3021_id,
};
diff --git a/drivers/hwmon/nct6683.c b/drivers/hwmon/nct6683.c
index a872f783e9cc..f673f7d07941 100644
--- a/drivers/hwmon/nct6683.c
+++ b/drivers/hwmon/nct6683.c
@@ -173,6 +173,7 @@ superio_exit(int ioreg)
#define NCT6683_CUSTOMER_ID_INTEL 0x805
#define NCT6683_CUSTOMER_ID_MITAC 0xa0e
#define NCT6683_CUSTOMER_ID_MSI 0x201
+#define NCT6683_CUSTOMER_ID_MSI2 0x200
#define NCT6683_CUSTOMER_ID_ASROCK 0xe2c
#define NCT6683_CUSTOMER_ID_ASROCK2 0xe1b
@@ -1220,6 +1221,8 @@ static int nct6683_probe(struct platform_device *pdev)
break;
case NCT6683_CUSTOMER_ID_MSI:
break;
+ case NCT6683_CUSTOMER_ID_MSI2:
+ break;
case NCT6683_CUSTOMER_ID_ASROCK:
break;
case NCT6683_CUSTOMER_ID_ASROCK2:
diff --git a/drivers/hwmon/nct6775-core.c b/drivers/hwmon/nct6775-core.c
index c54233f0369b..236dc97f4d22 100644
--- a/drivers/hwmon/nct6775-core.c
+++ b/drivers/hwmon/nct6775-core.c
@@ -33,6 +33,7 @@
* (0xd451)
* nct6798d 14 7 7 2+6 0xd428 0xc1 0x5ca3
* (0xd429)
+ * nct6799d 14 7 7 2+6 0xd802 0xc1 0x5ca3
*
* #temp lists the number of monitored temperature sources (first value) plus
* the number of directly connectable temperature sensors (second value).
@@ -73,6 +74,7 @@ static const char * const nct6775_device_names[] = {
"nct6796",
"nct6797",
"nct6798",
+ "nct6799",
};
/* Common and NCT6775 specific data */
@@ -381,7 +383,7 @@ static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
0x39, 0x155 };
static const u16 NCT6779_REG_TEMP_OFFSET[] = {
- 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
+ 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c, 0x44d, 0x449 };
static const char *const nct6779_temp_label[] = {
"",
@@ -654,6 +656,44 @@ static const char *const nct6798_temp_label[] = {
#define NCT6798_TEMP_MASK 0xbfff0ffe
#define NCT6798_VIRT_TEMP_MASK 0x80000c00
+static const char *const nct6799_temp_label[] = {
+ "",
+ "SYSTIN",
+ "CPUTIN",
+ "AUXTIN0",
+ "AUXTIN1",
+ "AUXTIN2",
+ "AUXTIN3",
+ "AUXTIN4",
+ "SMBUSMASTER 0",
+ "SMBUSMASTER 1",
+ "Virtual_TEMP",
+ "Virtual_TEMP",
+ "",
+ "AUXTIN5",
+ "",
+ "",
+ "PECI Agent 0",
+ "PECI Agent 1",
+ "PCH_CHIP_CPU_MAX_TEMP",
+ "PCH_CHIP_TEMP",
+ "PCH_CPU_TEMP",
+ "PCH_MCH_TEMP",
+ "Agent0 Dimm0",
+ "Agent0 Dimm1",
+ "Agent1 Dimm0",
+ "Agent1 Dimm1",
+ "BYTE_TEMP0",
+ "BYTE_TEMP1",
+ "PECI Agent 0 Calibration", /* undocumented */
+ "PECI Agent 1 Calibration", /* undocumented */
+ "",
+ "Virtual_TEMP"
+};
+
+#define NCT6799_TEMP_MASK 0xbfff2ffe
+#define NCT6799_VIRT_TEMP_MASK 0x80000c00
+
/* NCT6102D/NCT6106D specific data */
#define NCT6106_REG_VBAT 0x318
@@ -1109,6 +1149,7 @@ bool nct6775_reg_is_word_sized(struct nct6775_data *data, u16 reg)
case nct6796:
case nct6797:
case nct6798:
+ case nct6799:
return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
(reg & 0xfff0) == 0x4c0 ||
reg == 0x402 ||
@@ -1462,6 +1503,7 @@ static int nct6775_update_pwm_limits(struct device *dev)
case nct6796:
case nct6797:
case nct6798:
+ case nct6799:
err = nct6775_read_value(data, data->REG_CRITICAL_PWM_ENABLE[i], &reg);
if (err)
return err;
@@ -3109,6 +3151,7 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr,
case nct6796:
case nct6797:
case nct6798:
+ case nct6799:
err = nct6775_write_value(data, data->REG_CRITICAL_PWM[nr], val);
if (err)
break;
@@ -3807,10 +3850,12 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
case nct6796:
case nct6797:
case nct6798:
+ case nct6799:
data->in_num = 15;
data->pwm_num = (data->kind == nct6796 ||
data->kind == nct6797 ||
- data->kind == nct6798) ? 7 : 6;
+ data->kind == nct6798 ||
+ data->kind == nct6799) ? 7 : 6;
data->auto_pwm_num = 4;
data->has_fan_div = false;
data->temp_fixed_num = 6;
@@ -3859,6 +3904,11 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
data->temp_mask = NCT6798_TEMP_MASK;
data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK;
break;
+ case nct6799:
+ data->temp_label = nct6799_temp_label;
+ data->temp_mask = NCT6799_TEMP_MASK;
+ data->virt_temp_mask = NCT6799_VIRT_TEMP_MASK;
+ break;
}
data->REG_CONFIG = NCT6775_REG_CONFIG;
@@ -3918,6 +3968,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
case nct6796:
case nct6797:
case nct6798:
+ case nct6799:
data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP;
num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP);
break;
diff --git a/drivers/hwmon/nct6775-i2c.c b/drivers/hwmon/nct6775-i2c.c
index e1bcd1146191..87a4fc78c571 100644
--- a/drivers/hwmon/nct6775-i2c.c
+++ b/drivers/hwmon/nct6775-i2c.c
@@ -87,6 +87,7 @@ static const struct of_device_id __maybe_unused nct6775_i2c_of_match[] = {
{ .compatible = "nuvoton,nct6796", .data = (void *)nct6796, },
{ .compatible = "nuvoton,nct6797", .data = (void *)nct6797, },
{ .compatible = "nuvoton,nct6798", .data = (void *)nct6798, },
+ { .compatible = "nuvoton,nct6799", .data = (void *)nct6799, },
{ },
};
MODULE_DEVICE_TABLE(of, nct6775_i2c_of_match);
@@ -104,6 +105,7 @@ static const struct i2c_device_id nct6775_i2c_id[] = {
{ "nct6796", nct6796 },
{ "nct6797", nct6797 },
{ "nct6798", nct6798 },
+ { "nct6799", nct6799 },
{ }
};
MODULE_DEVICE_TABLE(i2c, nct6775_i2c_id);
@@ -183,7 +185,7 @@ static struct i2c_driver nct6775_i2c_driver = {
.name = "nct6775-i2c",
.of_match_table = of_match_ptr(nct6775_i2c_of_match),
},
- .probe_new = nct6775_i2c_probe,
+ .probe = nct6775_i2c_probe,
.id_table = nct6775_i2c_id,
};
diff --git a/drivers/hwmon/nct6775-platform.c b/drivers/hwmon/nct6775-platform.c
index 5782acfb4ee1..ada867d6b98a 100644
--- a/drivers/hwmon/nct6775-platform.c
+++ b/drivers/hwmon/nct6775-platform.c
@@ -35,6 +35,7 @@ static const char * const nct6775_sio_names[] __initconst = {
"NCT6796D",
"NCT6797D",
"NCT6798D",
+ "NCT6799D",
};
static unsigned short force_id;
@@ -85,6 +86,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
#define SIO_NCT6796_ID 0xd420
#define SIO_NCT6797_ID 0xd450
#define SIO_NCT6798_ID 0xd428
+#define SIO_NCT6799_ID 0xd800
#define SIO_ID_MASK 0xFFF8
/*
@@ -418,7 +420,7 @@ static int nct6775_resume(struct device *dev)
if (data->kind == nct6791 || data->kind == nct6792 ||
data->kind == nct6793 || data->kind == nct6795 ||
data->kind == nct6796 || data->kind == nct6797 ||
- data->kind == nct6798)
+ data->kind == nct6798 || data->kind == nct6799)
nct6791_enable_io_mapping(sio_data);
sio_data->sio_exit(sio_data);
@@ -565,7 +567,7 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio
} else {
/*
* NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D, NCT6796D,
- * NCT6797D, NCT6798D
+ * NCT6797D, NCT6798D, NCT6799D
*/
int cr1a = sio_data->sio_inb(sio_data, 0x1a);
int cr1b = sio_data->sio_inb(sio_data, 0x1b);
@@ -575,12 +577,17 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio
int cr2b = sio_data->sio_inb(sio_data, 0x2b);
int cr2d = sio_data->sio_inb(sio_data, 0x2d);
int cr2f = sio_data->sio_inb(sio_data, 0x2f);
+ bool vsb_ctl_en = cr2f & BIT(0);
bool dsw_en = cr2f & BIT(3);
bool ddr4_en = cr2f & BIT(4);
+ bool as_seq1_en = cr2f & BIT(7);
int cre0;
+ int cre6;
int creb;
int cred;
+ cre6 = sio_data->sio_inb(sio_data, 0xe0);
+
sio_data->sio_select(sio_data, NCT6775_LD_12);
cre0 = sio_data->sio_inb(sio_data, 0xe0);
creb = sio_data->sio_inb(sio_data, 0xeb);
@@ -684,6 +691,29 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio
pwm7pin |= cr2d & BIT(7);
pwm7pin |= creb & BIT(2);
break;
+ case nct6799:
+ fan4pin = cr1c & BIT(6);
+ fan5pin = cr1c & BIT(7);
+
+ fan6pin = !(cr1b & BIT(0)) && (cre0 & BIT(3));
+ fan6pin |= cre6 & BIT(5);
+ fan6pin |= creb & BIT(5);
+ fan6pin |= !as_seq1_en && (cr2a & BIT(4));
+
+ fan7pin = cr1b & BIT(5);
+ fan7pin |= !vsb_ctl_en && !(cr2b & BIT(2));
+ fan7pin |= creb & BIT(3);
+
+ pwm6pin = !(cr1b & BIT(0)) && (cre0 & BIT(4));
+ pwm6pin |= !as_seq1_en && !(cred & BIT(2)) && (cr2a & BIT(3));
+ pwm6pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
+ pwm6pin |= cre6 & BIT(3);
+
+ pwm7pin = !vsb_ctl_en && !(cr1d & (BIT(2) | BIT(3)));
+ pwm7pin |= creb & BIT(2);
+ pwm7pin |= cr2d & BIT(7);
+
+ break;
default: /* NCT6779D */
break;
}
@@ -838,6 +868,7 @@ static int nct6775_platform_probe_init(struct nct6775_data *data)
case nct6796:
case nct6797:
case nct6798:
+ case nct6799:
break;
}
@@ -876,6 +907,7 @@ static int nct6775_platform_probe_init(struct nct6775_data *data)
case nct6796:
case nct6797:
case nct6798:
+ case nct6799:
tmp |= 0x7e;
break;
}
@@ -1005,6 +1037,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
case SIO_NCT6798_ID:
sio_data->kind = nct6798;
break;
+ case SIO_NCT6799_ID:
+ sio_data->kind = nct6799;
+ break;
default:
if (val != 0xffff)
pr_debug("unsupported chip ID: 0x%04x\n", val);
@@ -1033,7 +1068,7 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
if (sio_data->kind == nct6791 || sio_data->kind == nct6792 ||
sio_data->kind == nct6793 || sio_data->kind == nct6795 ||
sio_data->kind == nct6796 || sio_data->kind == nct6797 ||
- sio_data->kind == nct6798)
+ sio_data->kind == nct6798 || sio_data->kind == nct6799)
nct6791_enable_io_mapping(sio_data);
sio_data->sio_exit(sio_data);
diff --git a/drivers/hwmon/nct6775.h b/drivers/hwmon/nct6775.h
index be41848c3cd2..44f79c5726a9 100644
--- a/drivers/hwmon/nct6775.h
+++ b/drivers/hwmon/nct6775.h
@@ -5,7 +5,7 @@
#include <linux/types.h>
enum kinds { nct6106, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792,
- nct6793, nct6795, nct6796, nct6797, nct6798 };
+ nct6793, nct6795, nct6796, nct6797, nct6798, nct6799 };
enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/
diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c
index a175f8283695..9339bfc02a3e 100644
--- a/drivers/hwmon/nct7802.c
+++ b/drivers/hwmon/nct7802.c
@@ -1223,7 +1223,7 @@ static struct i2c_driver nct7802_driver = {
.name = DRVNAME,
},
.detect = nct7802_detect,
- .probe_new = nct7802_probe,
+ .probe = nct7802_probe,
.id_table = nct7802_idtable,
.address_list = nct7802_address_list,
};
diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c
index 007bae4c7028..8f867d4570e1 100644
--- a/drivers/hwmon/nct7904.c
+++ b/drivers/hwmon/nct7904.c
@@ -1171,7 +1171,7 @@ static struct i2c_driver nct7904_driver = {
.driver = {
.name = "nct7904",
},
- .probe_new = nct7904_probe,
+ .probe = nct7904_probe,
.id_table = nct7904_id,
.detect = nct7904_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/occ/p8_i2c.c b/drivers/hwmon/occ/p8_i2c.c
index 9e1744fccb35..06095975f5c8 100644
--- a/drivers/hwmon/occ/p8_i2c.c
+++ b/drivers/hwmon/occ/p8_i2c.c
@@ -246,7 +246,7 @@ static struct i2c_driver p8_i2c_occ_driver = {
.name = "occ-hwmon",
.of_match_table = p8_i2c_occ_of_match,
},
- .probe_new = p8_i2c_occ_probe,
+ .probe = p8_i2c_occ_probe,
.remove = p8_i2c_occ_remove,
};
diff --git a/drivers/hwmon/oxp-sensors.c b/drivers/hwmon/oxp-sensors.c
index ae67207030e8..e1a907cae820 100644
--- a/drivers/hwmon/oxp-sensors.c
+++ b/drivers/hwmon/oxp-sensors.c
@@ -16,7 +16,6 @@
*/
#include <linux/acpi.h>
-#include <linux/dev_printk.h>
#include <linux/dmi.h>
#include <linux/hwmon.h>
#include <linux/init.h>
@@ -42,53 +41,97 @@ static bool unlock_global_acpi_lock(void)
enum oxp_board {
aok_zoe_a1 = 1,
+ aya_neo_2,
aya_neo_air,
aya_neo_air_pro,
+ aya_neo_geek,
oxp_mini_amd,
+ oxp_mini_amd_a07,
oxp_mini_amd_pro,
};
static enum oxp_board board;
+/* Fan reading and PWM */
#define OXP_SENSOR_FAN_REG 0x76 /* Fan reading is 2 registers long */
#define OXP_SENSOR_PWM_ENABLE_REG 0x4A /* PWM enable is 1 register long */
#define OXP_SENSOR_PWM_REG 0x4B /* PWM reading is 1 register long */
+/* Turbo button takeover function
+ * Older boards have different values and EC registers
+ * for the same function
+ */
+#define OXP_OLD_TURBO_SWITCH_REG 0x1E
+#define OXP_OLD_TURBO_TAKE_VAL 0x01
+#define OXP_OLD_TURBO_RETURN_VAL 0x00
+
+#define OXP_TURBO_SWITCH_REG 0xF1
+#define OXP_TURBO_TAKE_VAL 0x40
+#define OXP_TURBO_RETURN_VAL 0x00
+
static const struct dmi_system_id dmi_table[] = {
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AOKZOE"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "AOKZOE A1 AR07"),
},
- .driver_data = (void *) &(enum oxp_board) {aok_zoe_a1},
+ .driver_data = (void *)aok_zoe_a1,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AOKZOE"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "AOKZOE A1 Pro"),
+ },
+ .driver_data = (void *)aok_zoe_a1,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "AYANEO 2"),
+ },
+ .driver_data = (void *)aya_neo_2,
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "AIR"),
},
- .driver_data = (void *) &(enum oxp_board) {aya_neo_air},
+ .driver_data = (void *)aya_neo_air,
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "AIR Pro"),
},
- .driver_data = (void *) &(enum oxp_board) {aya_neo_air_pro},
+ .driver_data = (void *)aya_neo_air_pro,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "GEEK"),
+ },
+ .driver_data = (void *)aya_neo_geek,
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONE XPLAYER"),
},
- .driver_data = (void *) &(enum oxp_board) {oxp_mini_amd},
+ .driver_data = (void *)oxp_mini_amd,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER mini A07"),
+ },
+ .driver_data = (void *)oxp_mini_amd_a07,
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER Mini Pro"),
},
- .driver_data = (void *) &(enum oxp_board) {oxp_mini_amd_pro},
+ .driver_data = (void *)oxp_mini_amd_pro,
},
{},
};
@@ -118,7 +161,7 @@ static int read_from_ec(u8 reg, int size, long *val)
return 0;
}
-static int write_to_ec(const struct device *dev, u8 reg, u8 value)
+static int write_to_ec(u8 reg, u8 value)
{
int ret;
@@ -133,14 +176,109 @@ static int write_to_ec(const struct device *dev, u8 reg, u8 value)
return ret;
}
-static int oxp_pwm_enable(const struct device *dev)
+/* Turbo button toggle functions */
+static int tt_toggle_enable(void)
+{
+ u8 reg;
+ u8 val;
+
+ switch (board) {
+ case oxp_mini_amd_a07:
+ reg = OXP_OLD_TURBO_SWITCH_REG;
+ val = OXP_OLD_TURBO_TAKE_VAL;
+ break;
+ case oxp_mini_amd_pro:
+ case aok_zoe_a1:
+ reg = OXP_TURBO_SWITCH_REG;
+ val = OXP_TURBO_TAKE_VAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return write_to_ec(reg, val);
+}
+
+static int tt_toggle_disable(void)
+{
+ u8 reg;
+ u8 val;
+
+ switch (board) {
+ case oxp_mini_amd_a07:
+ reg = OXP_OLD_TURBO_SWITCH_REG;
+ val = OXP_OLD_TURBO_RETURN_VAL;
+ break;
+ case oxp_mini_amd_pro:
+ case aok_zoe_a1:
+ reg = OXP_TURBO_SWITCH_REG;
+ val = OXP_TURBO_RETURN_VAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return write_to_ec(reg, val);
+}
+
+/* Callbacks for turbo toggle attribute */
+static ssize_t tt_toggle_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ int rval;
+ bool value;
+
+ rval = kstrtobool(buf, &value);
+ if (rval)
+ return rval;
+
+ if (value) {
+ rval = tt_toggle_enable();
+ } else {
+ rval = tt_toggle_disable();
+ }
+ if (rval)
+ return rval;
+
+ return count;
+}
+
+static ssize_t tt_toggle_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int retval;
+ u8 reg;
+ long val;
+
+ switch (board) {
+ case oxp_mini_amd_a07:
+ reg = OXP_OLD_TURBO_SWITCH_REG;
+ break;
+ case oxp_mini_amd_pro:
+ case aok_zoe_a1:
+ reg = OXP_TURBO_SWITCH_REG;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ retval = read_from_ec(reg, 1, &val);
+ if (retval)
+ return retval;
+
+ return sysfs_emit(buf, "%d\n", !!val);
+}
+
+static DEVICE_ATTR_RW(tt_toggle);
+
+/* PWM enable/disable functions */
+static int oxp_pwm_enable(void)
{
- return write_to_ec(dev, OXP_SENSOR_PWM_ENABLE_REG, 0x01);
+ return write_to_ec(OXP_SENSOR_PWM_ENABLE_REG, 0x01);
}
-static int oxp_pwm_disable(const struct device *dev)
+static int oxp_pwm_disable(void)
{
- return write_to_ec(dev, OXP_SENSOR_PWM_ENABLE_REG, 0x00);
+ return write_to_ec(OXP_SENSOR_PWM_ENABLE_REG, 0x00);
}
/* Callbacks for hwmon interface */
@@ -178,9 +316,12 @@ static int oxp_platform_read(struct device *dev, enum hwmon_sensor_types type,
if (ret)
return ret;
switch (board) {
+ case aya_neo_2:
case aya_neo_air:
case aya_neo_air_pro:
+ case aya_neo_geek:
case oxp_mini_amd:
+ case oxp_mini_amd_a07:
*val = (*val * 255) / 100;
break;
case oxp_mini_amd_pro:
@@ -209,17 +350,20 @@ static int oxp_platform_write(struct device *dev, enum hwmon_sensor_types type,
switch (attr) {
case hwmon_pwm_enable:
if (val == 1)
- return oxp_pwm_enable(dev);
+ return oxp_pwm_enable();
else if (val == 0)
- return oxp_pwm_disable(dev);
+ return oxp_pwm_disable();
return -EINVAL;
case hwmon_pwm_input:
if (val < 0 || val > 255)
return -EINVAL;
switch (board) {
+ case aya_neo_2:
case aya_neo_air:
case aya_neo_air_pro:
+ case aya_neo_geek:
case oxp_mini_amd:
+ case oxp_mini_amd_a07:
val = (val * 100) / 255;
break;
case aok_zoe_a1:
@@ -227,7 +371,7 @@ static int oxp_platform_write(struct device *dev, enum hwmon_sensor_types type,
default:
break;
}
- return write_to_ec(dev, OXP_SENSOR_PWM_REG, val);
+ return write_to_ec(OXP_SENSOR_PWM_REG, val);
default:
break;
}
@@ -247,6 +391,13 @@ static const struct hwmon_channel_info * const oxp_platform_sensors[] = {
NULL,
};
+static struct attribute *oxp_ec_attrs[] = {
+ &dev_attr_tt_toggle.attr,
+ NULL
+};
+
+ATTRIBUTE_GROUPS(oxp_ec);
+
static const struct hwmon_ops oxp_ec_hwmon_ops = {
.is_visible = oxp_ec_hwmon_is_visible,
.read = oxp_platform_read,
@@ -264,6 +415,7 @@ static int oxp_platform_probe(struct platform_device *pdev)
const struct dmi_system_id *dmi_entry;
struct device *dev = &pdev->dev;
struct device *hwdev;
+ int ret;
/*
* Have to check for AMD processor here because DMI strings are the
@@ -276,7 +428,19 @@ static int oxp_platform_probe(struct platform_device *pdev)
if (!dmi_entry || boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
return -ENODEV;
- board = *((enum oxp_board *) dmi_entry->driver_data);
+ board = (enum oxp_board)(unsigned long)dmi_entry->driver_data;
+
+ switch (board) {
+ case aok_zoe_a1:
+ case oxp_mini_amd_a07:
+ case oxp_mini_amd_pro:
+ ret = devm_device_add_groups(dev, oxp_ec_groups);
+ if (ret)
+ return ret;
+ break;
+ default:
+ break;
+ }
hwdev = devm_hwmon_device_register_with_info(dev, "oxpec", NULL,
&oxp_ec_chip_info, NULL);
diff --git a/drivers/hwmon/pcf8591.c b/drivers/hwmon/pcf8591.c
index 1dbe209ae13f..66c76b28c9e0 100644
--- a/drivers/hwmon/pcf8591.c
+++ b/drivers/hwmon/pcf8591.c
@@ -294,7 +294,7 @@ static struct i2c_driver pcf8591_driver = {
.driver = {
.name = "pcf8591",
},
- .probe_new = pcf8591_probe,
+ .probe = pcf8591_probe,
.remove = pcf8591_remove,
.id_table = pcf8591_id,
};
diff --git a/drivers/hwmon/pmbus/acbel-fsg032.c b/drivers/hwmon/pmbus/acbel-fsg032.c
index 28a25f30e2cf..0a0ef4ce3493 100644
--- a/drivers/hwmon/pmbus/acbel-fsg032.c
+++ b/drivers/hwmon/pmbus/acbel-fsg032.c
@@ -73,7 +73,7 @@ static struct i2c_driver acbel_fsg032_driver = {
.name = "acbel-fsg032",
.of_match_table = acbel_fsg032_of_match,
},
- .probe_new = acbel_fsg032_probe,
+ .probe = acbel_fsg032_probe,
.id_table = acbel_fsg032_id,
};
diff --git a/drivers/hwmon/pmbus/adm1266.c b/drivers/hwmon/pmbus/adm1266.c
index 1ac2b2f4c570..ed0a7b9fae4b 100644
--- a/drivers/hwmon/pmbus/adm1266.c
+++ b/drivers/hwmon/pmbus/adm1266.c
@@ -340,8 +340,6 @@ static void adm1266_init_debugfs(struct adm1266_data *data)
return;
data->debugfs_dir = debugfs_create_dir(data->client->name, root);
- if (!data->debugfs_dir)
- return;
debugfs_create_devm_seqfile(&data->client->dev, "sequencer_state", data->debugfs_dir,
adm1266_state_read);
@@ -502,7 +500,7 @@ static struct i2c_driver adm1266_driver = {
.name = "adm1266",
.of_match_table = adm1266_of_match,
},
- .probe_new = adm1266_probe,
+ .probe = adm1266_probe,
.id_table = adm1266_id,
};
diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c
index 3b07bfb43e93..e2c61d6fa521 100644
--- a/drivers/hwmon/pmbus/adm1275.c
+++ b/drivers/hwmon/pmbus/adm1275.c
@@ -27,8 +27,11 @@ enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 };
#define ADM1275_PEAK_IOUT 0xd0
#define ADM1275_PEAK_VIN 0xd1
#define ADM1275_PEAK_VOUT 0xd2
+#define ADM1275_PMON_CONTROL 0xd3
#define ADM1275_PMON_CONFIG 0xd4
+#define ADM1275_CONVERT_EN BIT(0)
+
#define ADM1275_VIN_VOUT_SELECT BIT(6)
#define ADM1275_VRANGE BIT(5)
#define ADM1075_IRANGE_50 BIT(4)
@@ -37,10 +40,13 @@ enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 };
#define ADM1272_IRANGE BIT(0)
+#define ADM1278_TSFILT BIT(15)
#define ADM1278_TEMP1_EN BIT(3)
#define ADM1278_VIN_EN BIT(2)
#define ADM1278_VOUT_EN BIT(1)
+#define ADM1278_PMON_DEFCONFIG (ADM1278_VOUT_EN | ADM1278_TEMP1_EN | ADM1278_TSFILT)
+
#define ADM1293_IRANGE_25 0
#define ADM1293_IRANGE_50 BIT(6)
#define ADM1293_IRANGE_100 BIT(7)
@@ -170,8 +176,8 @@ static const struct coefficients adm1293_coefficients[] = {
[18] = { 7658, 0, -3 }, /* power, 21V, irange200 */
};
-static int adm1275_read_pmon_config(const struct adm1275_data *data,
- struct i2c_client *client, bool is_power)
+static int adm1275_read_samples(const struct adm1275_data *data,
+ struct i2c_client *client, bool is_power)
{
int shift, ret;
u16 mask;
@@ -197,8 +203,36 @@ static int adm1275_read_pmon_config(const struct adm1275_data *data,
}
static int adm1275_write_pmon_config(const struct adm1275_data *data,
- struct i2c_client *client,
- bool is_power, u16 word)
+ struct i2c_client *client, u16 word)
+{
+ int ret, ret2;
+
+ ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONTROL, 0);
+ if (ret)
+ return ret;
+
+ if (data->have_power_sampling)
+ ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG,
+ word);
+ else
+ ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG,
+ word);
+
+ /*
+ * We still want to re-enable conversions if writing into
+ * ADM1275_PMON_CONFIG failed.
+ */
+ ret2 = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONTROL,
+ ADM1275_CONVERT_EN);
+ if (!ret)
+ ret = ret2;
+
+ return ret;
+}
+
+static int adm1275_write_samples(const struct adm1275_data *data,
+ struct i2c_client *client,
+ bool is_power, u16 word)
{
int shift, ret;
u16 mask;
@@ -216,14 +250,8 @@ static int adm1275_write_pmon_config(const struct adm1275_data *data,
return ret;
word = (ret & ~mask) | ((word << shift) & mask);
- if (data->have_power_sampling)
- ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG,
- word);
- else
- ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG,
- word);
- return ret;
+ return adm1275_write_pmon_config(data, client, word);
}
static int adm1275_read_word_data(struct i2c_client *client, int page,
@@ -318,14 +346,14 @@ static int adm1275_read_word_data(struct i2c_client *client, int page,
case PMBUS_VIRT_POWER_SAMPLES:
if (!data->have_power_sampling)
return -ENXIO;
- ret = adm1275_read_pmon_config(data, client, true);
+ ret = adm1275_read_samples(data, client, true);
if (ret < 0)
break;
ret = BIT(ret);
break;
case PMBUS_VIRT_IN_SAMPLES:
case PMBUS_VIRT_CURR_SAMPLES:
- ret = adm1275_read_pmon_config(data, client, false);
+ ret = adm1275_read_samples(data, client, false);
if (ret < 0)
break;
ret = BIT(ret);
@@ -378,14 +406,12 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
if (!data->have_power_sampling)
return -ENXIO;
word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX);
- ret = adm1275_write_pmon_config(data, client, true,
- ilog2(word));
+ ret = adm1275_write_samples(data, client, true, ilog2(word));
break;
case PMBUS_VIRT_IN_SAMPLES:
case PMBUS_VIRT_CURR_SAMPLES:
word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX);
- ret = adm1275_write_pmon_config(data, client, false,
- ilog2(word));
+ ret = adm1275_write_samples(data, client, false, ilog2(word));
break;
default:
ret = -ENODATA;
@@ -462,6 +488,23 @@ static const struct i2c_device_id adm1275_id[] = {
};
MODULE_DEVICE_TABLE(i2c, adm1275_id);
+/* Enable VOUT & TEMP1 if not enabled (disabled by default) */
+static int adm1275_enable_vout_temp(struct adm1275_data *data,
+ struct i2c_client *client, int config)
+{
+ int ret;
+
+ if ((config & ADM1278_PMON_DEFCONFIG) != ADM1278_PMON_DEFCONFIG) {
+ config |= ADM1278_PMON_DEFCONFIG;
+ ret = adm1275_write_pmon_config(data, client, config);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to enable VOUT/TEMP1 monitoring\n");
+ return ret;
+ }
+ }
+ return 0;
+}
+
static int adm1275_probe(struct i2c_client *client)
{
s32 (*config_read_fn)(const struct i2c_client *client, u8 reg);
@@ -615,19 +658,10 @@ static int adm1275_probe(struct i2c_client *client)
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
- /* Enable VOUT & TEMP1 if not enabled (disabled by default) */
- if ((config & (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) !=
- (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) {
- config |= ADM1278_VOUT_EN | ADM1278_TEMP1_EN;
- ret = i2c_smbus_write_byte_data(client,
- ADM1275_PMON_CONFIG,
- config);
- if (ret < 0) {
- dev_err(&client->dev,
- "Failed to enable VOUT monitoring\n");
- return -ENODEV;
- }
- }
+ ret = adm1275_enable_vout_temp(data, client, config);
+ if (ret)
+ return ret;
+
if (config & ADM1278_VIN_EN)
info->func[0] |= PMBUS_HAVE_VIN;
break;
@@ -684,19 +718,9 @@ static int adm1275_probe(struct i2c_client *client)
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
- /* Enable VOUT & TEMP1 if not enabled (disabled by default) */
- if ((config & (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) !=
- (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) {
- config |= ADM1278_VOUT_EN | ADM1278_TEMP1_EN;
- ret = i2c_smbus_write_word_data(client,
- ADM1275_PMON_CONFIG,
- config);
- if (ret < 0) {
- dev_err(&client->dev,
- "Failed to enable VOUT monitoring\n");
- return -ENODEV;
- }
- }
+ ret = adm1275_enable_vout_temp(data, client, config);
+ if (ret)
+ return ret;
if (config & ADM1278_VIN_EN)
info->func[0] |= PMBUS_HAVE_VIN;
@@ -766,8 +790,7 @@ static int adm1275_probe(struct i2c_client *client)
"Invalid number of power samples");
return -EINVAL;
}
- ret = adm1275_write_pmon_config(data, client, true,
- ilog2(avg));
+ ret = adm1275_write_samples(data, client, true, ilog2(avg));
if (ret < 0) {
dev_err(&client->dev,
"Setting power sample averaging failed with error %d",
@@ -784,8 +807,7 @@ static int adm1275_probe(struct i2c_client *client)
"Invalid number of voltage/current samples");
return -EINVAL;
}
- ret = adm1275_write_pmon_config(data, client, false,
- ilog2(avg));
+ ret = adm1275_write_samples(data, client, false, ilog2(avg));
if (ret < 0) {
dev_err(&client->dev,
"Setting voltage and current sample averaging failed with error %d",
@@ -832,7 +854,7 @@ static struct i2c_driver adm1275_driver = {
.driver = {
.name = "adm1275",
},
- .probe_new = adm1275_probe,
+ .probe = adm1275_probe,
.id_table = adm1275_id,
};
diff --git a/drivers/hwmon/pmbus/bel-pfe.c b/drivers/hwmon/pmbus/bel-pfe.c
index 4100eefb7ac3..fa5070ae26bc 100644
--- a/drivers/hwmon/pmbus/bel-pfe.c
+++ b/drivers/hwmon/pmbus/bel-pfe.c
@@ -120,7 +120,7 @@ static struct i2c_driver pfe_pmbus_driver = {
.driver = {
.name = "bel-pfe",
},
- .probe_new = pfe_pmbus_probe,
+ .probe = pfe_pmbus_probe,
.id_table = pfe_device_id,
};
diff --git a/drivers/hwmon/pmbus/bpa-rs600.c b/drivers/hwmon/pmbus/bpa-rs600.c
index f2d4e378a775..0dce26c35556 100644
--- a/drivers/hwmon/pmbus/bpa-rs600.c
+++ b/drivers/hwmon/pmbus/bpa-rs600.c
@@ -196,7 +196,7 @@ static struct i2c_driver bpa_rs600_driver = {
.name = "bpa-rs600",
.of_match_table = of_match_ptr(bpa_rs600_of_match),
},
- .probe_new = bpa_rs600_probe,
+ .probe = bpa_rs600_probe,
.id_table = bpa_rs600_id,
};
diff --git a/drivers/hwmon/pmbus/delta-ahe50dc-fan.c b/drivers/hwmon/pmbus/delta-ahe50dc-fan.c
index f546f0c12497..4dd3b6686d6a 100644
--- a/drivers/hwmon/pmbus/delta-ahe50dc-fan.c
+++ b/drivers/hwmon/pmbus/delta-ahe50dc-fan.c
@@ -119,7 +119,7 @@ static struct i2c_driver ahe50dc_fan_driver = {
.name = "ahe50dc_fan",
.of_match_table = of_match_ptr(ahe50dc_fan_of_match),
},
- .probe_new = ahe50dc_fan_probe,
+ .probe = ahe50dc_fan_probe,
.id_table = ahe50dc_fan_id,
};
module_i2c_driver(ahe50dc_fan_driver);
diff --git a/drivers/hwmon/pmbus/dps920ab.c b/drivers/hwmon/pmbus/dps920ab.c
index d3941f6eb29a..f7ff3e4650b7 100644
--- a/drivers/hwmon/pmbus/dps920ab.c
+++ b/drivers/hwmon/pmbus/dps920ab.c
@@ -195,7 +195,7 @@ static struct i2c_driver dps920ab_driver = {
.name = "dps920ab",
.of_match_table = of_match_ptr(dps920ab_of_match),
},
- .probe_new = dps920ab_probe,
+ .probe = dps920ab_probe,
};
module_i2c_driver(dps920ab_driver);
diff --git a/drivers/hwmon/pmbus/fsp-3y.c b/drivers/hwmon/pmbus/fsp-3y.c
index c7469d2cdedc..72a7c261ef06 100644
--- a/drivers/hwmon/pmbus/fsp-3y.c
+++ b/drivers/hwmon/pmbus/fsp-3y.c
@@ -282,7 +282,7 @@ static struct i2c_driver fsp3y_driver = {
.driver = {
.name = "fsp3y",
},
- .probe_new = fsp3y_probe,
+ .probe = fsp3y_probe,
.id_table = fsp3y_id
};
diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c
index 76e72e9acda7..c791925b8907 100644
--- a/drivers/hwmon/pmbus/ibm-cffps.c
+++ b/drivers/hwmon/pmbus/ibm-cffps.c
@@ -605,7 +605,7 @@ static struct i2c_driver ibm_cffps_driver = {
.name = "ibm-cffps",
.of_match_table = ibm_cffps_of_match,
},
- .probe_new = ibm_cffps_probe,
+ .probe = ibm_cffps_probe,
.id_table = ibm_cffps_id,
};
diff --git a/drivers/hwmon/pmbus/inspur-ipsps.c b/drivers/hwmon/pmbus/inspur-ipsps.c
index 0f614e8d95f6..dfeae68b5e52 100644
--- a/drivers/hwmon/pmbus/inspur-ipsps.c
+++ b/drivers/hwmon/pmbus/inspur-ipsps.c
@@ -215,7 +215,7 @@ static struct i2c_driver ipsps_driver = {
.name = "inspur-ipsps",
.of_match_table = of_match_ptr(ipsps_of_match),
},
- .probe_new = ipsps_probe,
+ .probe = ipsps_probe,
.id_table = ipsps_id,
};
diff --git a/drivers/hwmon/pmbus/ir35221.c b/drivers/hwmon/pmbus/ir35221.c
index a6cf98e49666..e3ee5c1bd967 100644
--- a/drivers/hwmon/pmbus/ir35221.c
+++ b/drivers/hwmon/pmbus/ir35221.c
@@ -136,7 +136,7 @@ static struct i2c_driver ir35221_driver = {
.driver = {
.name = "ir35221",
},
- .probe_new = ir35221_probe,
+ .probe = ir35221_probe,
.id_table = ir35221_id,
};
diff --git a/drivers/hwmon/pmbus/ir36021.c b/drivers/hwmon/pmbus/ir36021.c
index 4dca4767f571..382ba6b6031a 100644
--- a/drivers/hwmon/pmbus/ir36021.c
+++ b/drivers/hwmon/pmbus/ir36021.c
@@ -68,7 +68,7 @@ static struct i2c_driver ir36021_driver = {
.name = "ir36021",
.of_match_table = of_match_ptr(ir36021_of_id),
},
- .probe_new = ir36021_probe,
+ .probe = ir36021_probe,
.id_table = ir36021_id,
};
diff --git a/drivers/hwmon/pmbus/ir38064.c b/drivers/hwmon/pmbus/ir38064.c
index 09276e397194..871c322d3d51 100644
--- a/drivers/hwmon/pmbus/ir38064.c
+++ b/drivers/hwmon/pmbus/ir38064.c
@@ -78,7 +78,7 @@ static struct i2c_driver ir38064_driver = {
.name = "ir38064",
.of_match_table = of_match_ptr(ir38064_of_match),
},
- .probe_new = ir38064_probe,
+ .probe = ir38064_probe,
.id_table = ir38064_id,
};
diff --git a/drivers/hwmon/pmbus/irps5401.c b/drivers/hwmon/pmbus/irps5401.c
index de3449e4d77a..146d32a35a7c 100644
--- a/drivers/hwmon/pmbus/irps5401.c
+++ b/drivers/hwmon/pmbus/irps5401.c
@@ -54,7 +54,7 @@ static struct i2c_driver irps5401_driver = {
.driver = {
.name = "irps5401",
},
- .probe_new = irps5401_probe,
+ .probe = irps5401_probe,
.id_table = irps5401_id,
};
diff --git a/drivers/hwmon/pmbus/isl68137.c b/drivers/hwmon/pmbus/isl68137.c
index 1a8caff1ac5f..7e53fb1d5ea3 100644
--- a/drivers/hwmon/pmbus/isl68137.c
+++ b/drivers/hwmon/pmbus/isl68137.c
@@ -323,7 +323,7 @@ static struct i2c_driver isl68137_driver = {
.driver = {
.name = "isl68137",
},
- .probe_new = isl68137_probe,
+ .probe = isl68137_probe,
.id_table = raa_dmpvr_id,
};
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
index 09792cd03d9f..929fa6d34efd 100644
--- a/drivers/hwmon/pmbus/lm25066.c
+++ b/drivers/hwmon/pmbus/lm25066.c
@@ -568,7 +568,7 @@ static struct i2c_driver lm25066_driver = {
.name = "lm25066",
.of_match_table = of_match_ptr(lm25066_of_match),
},
- .probe_new = lm25066_probe,
+ .probe = lm25066_probe,
.id_table = lm25066_id,
};
diff --git a/drivers/hwmon/pmbus/lt7182s.c b/drivers/hwmon/pmbus/lt7182s.c
index 4cfe476fc92d..28afc5f15ae8 100644
--- a/drivers/hwmon/pmbus/lt7182s.c
+++ b/drivers/hwmon/pmbus/lt7182s.c
@@ -183,7 +183,7 @@ static struct i2c_driver lt7182s_driver = {
.name = "lt7182s",
.of_match_table = of_match_ptr(lt7182s_of_match),
},
- .probe_new = lt7182s_probe,
+ .probe = lt7182s_probe,
.id_table = lt7182s_id,
};
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
index 91df8e895147..73a86f4d6472 100644
--- a/drivers/hwmon/pmbus/ltc2978.c
+++ b/drivers/hwmon/pmbus/ltc2978.c
@@ -927,7 +927,7 @@ static struct i2c_driver ltc2978_driver = {
.name = "ltc2978",
.of_match_table = of_match_ptr(ltc2978_of_match),
},
- .probe_new = ltc2978_probe,
+ .probe = ltc2978_probe,
.id_table = ltc2978_id,
};
diff --git a/drivers/hwmon/pmbus/ltc3815.c b/drivers/hwmon/pmbus/ltc3815.c
index 8e13a7ddcb42..f2023b17aa8d 100644
--- a/drivers/hwmon/pmbus/ltc3815.c
+++ b/drivers/hwmon/pmbus/ltc3815.c
@@ -199,7 +199,7 @@ static struct i2c_driver ltc3815_driver = {
.driver = {
.name = "ltc3815",
},
- .probe_new = ltc3815_probe,
+ .probe = ltc3815_probe,
.id_table = ltc3815_id,
};
diff --git a/drivers/hwmon/pmbus/max15301.c b/drivers/hwmon/pmbus/max15301.c
index 0b6f88428ea8..2cfaa62aedd6 100644
--- a/drivers/hwmon/pmbus/max15301.c
+++ b/drivers/hwmon/pmbus/max15301.c
@@ -178,7 +178,7 @@ static struct i2c_driver max15301_driver = {
.driver = {
.name = "max15301",
},
- .probe_new = max15301_probe,
+ .probe = max15301_probe,
.id_table = max15301_id,
};
diff --git a/drivers/hwmon/pmbus/max16064.c b/drivers/hwmon/pmbus/max16064.c
index 94f869039071..a573a0ab9e48 100644
--- a/drivers/hwmon/pmbus/max16064.c
+++ b/drivers/hwmon/pmbus/max16064.c
@@ -102,7 +102,7 @@ static struct i2c_driver max16064_driver = {
.driver = {
.name = "max16064",
},
- .probe_new = max16064_probe,
+ .probe = max16064_probe,
.id_table = max16064_id,
};
diff --git a/drivers/hwmon/pmbus/max16601.c b/drivers/hwmon/pmbus/max16601.c
index 6724f723f74c..3ab219504600 100644
--- a/drivers/hwmon/pmbus/max16601.c
+++ b/drivers/hwmon/pmbus/max16601.c
@@ -283,10 +283,10 @@ static int max16601_get_id(struct i2c_client *client)
return -ENODEV;
/*
- * PMBUS_IC_DEVICE_ID is expected to return MAX1660[012]y.xx" or
- * "MAX16500y.xx".cdxxcccccccccc
+ * PMBUS_IC_DEVICE_ID is expected to return MAX1660[012]y.xx",
+ * "MAX16500y.xx".cdxxcccccccccc, or "MAX16508y.xx".
*/
- if (!strncmp(buf, "MAX16500", 8)) {
+ if (!strncmp(buf, "MAX16500", 8) || !strncmp(buf, "MAX16508", 8)) {
id = max16508;
} else if (!strncmp(buf, "MAX16600", 8)) {
id = max16600;
@@ -357,7 +357,7 @@ static struct i2c_driver max16601_driver = {
.driver = {
.name = "max16601",
},
- .probe_new = max16601_probe,
+ .probe = max16601_probe,
.id_table = max16601_id,
};
diff --git a/drivers/hwmon/pmbus/max20730.c b/drivers/hwmon/pmbus/max20730.c
index ba39f03c6374..7bcf27995033 100644
--- a/drivers/hwmon/pmbus/max20730.c
+++ b/drivers/hwmon/pmbus/max20730.c
@@ -776,7 +776,7 @@ static struct i2c_driver max20730_driver = {
.name = "max20730",
.of_match_table = max20730_of_match,
},
- .probe_new = max20730_probe,
+ .probe = max20730_probe,
.id_table = max20730_id,
};
diff --git a/drivers/hwmon/pmbus/max20751.c b/drivers/hwmon/pmbus/max20751.c
index 2272dc8c2e38..6ebd71cd081b 100644
--- a/drivers/hwmon/pmbus/max20751.c
+++ b/drivers/hwmon/pmbus/max20751.c
@@ -42,7 +42,7 @@ static struct i2c_driver max20751_driver = {
.driver = {
.name = "max20751",
},
- .probe_new = max20751_probe,
+ .probe = max20751_probe,
.id_table = max20751_id,
};
diff --git a/drivers/hwmon/pmbus/max31785.c b/drivers/hwmon/pmbus/max31785.c
index 95d79a64b483..f9aa576495a5 100644
--- a/drivers/hwmon/pmbus/max31785.c
+++ b/drivers/hwmon/pmbus/max31785.c
@@ -394,7 +394,7 @@ static struct i2c_driver max31785_driver = {
.name = "max31785",
.of_match_table = max31785_of_match,
},
- .probe_new = max31785_probe,
+ .probe = max31785_probe,
.id_table = max31785_id,
};
diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c
index ea7609058a12..fe7f6b1b0985 100644
--- a/drivers/hwmon/pmbus/max34440.c
+++ b/drivers/hwmon/pmbus/max34440.c
@@ -520,7 +520,7 @@ static struct i2c_driver max34440_driver = {
.driver = {
.name = "max34440",
},
- .probe_new = max34440_probe,
+ .probe = max34440_probe,
.id_table = max34440_id,
};
diff --git a/drivers/hwmon/pmbus/max8688.c b/drivers/hwmon/pmbus/max8688.c
index 5e66c28c0b71..ae8573fdf5ba 100644
--- a/drivers/hwmon/pmbus/max8688.c
+++ b/drivers/hwmon/pmbus/max8688.c
@@ -182,7 +182,7 @@ static struct i2c_driver max8688_driver = {
.driver = {
.name = "max8688",
},
- .probe_new = max8688_probe,
+ .probe = max8688_probe,
.id_table = max8688_id,
};
diff --git a/drivers/hwmon/pmbus/mp2888.c b/drivers/hwmon/pmbus/mp2888.c
index 24e5194706cf..50662ed8e3d5 100644
--- a/drivers/hwmon/pmbus/mp2888.c
+++ b/drivers/hwmon/pmbus/mp2888.c
@@ -395,7 +395,7 @@ static struct i2c_driver mp2888_driver = {
.name = "mp2888",
.of_match_table = of_match_ptr(mp2888_of_match),
},
- .probe_new = mp2888_probe,
+ .probe = mp2888_probe,
.id_table = mp2888_id,
};
diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c
index 51986adfbf47..2109b0458a8b 100644
--- a/drivers/hwmon/pmbus/mp2975.c
+++ b/drivers/hwmon/pmbus/mp2975.c
@@ -757,7 +757,7 @@ static struct i2c_driver mp2975_driver = {
.name = "mp2975",
.of_match_table = of_match_ptr(mp2975_of_match),
},
- .probe_new = mp2975_probe,
+ .probe = mp2975_probe,
.id_table = mp2975_id,
};
diff --git a/drivers/hwmon/pmbus/mp5023.c b/drivers/hwmon/pmbus/mp5023.c
index 791a06c3c54a..c4c4324d2b74 100644
--- a/drivers/hwmon/pmbus/mp5023.c
+++ b/drivers/hwmon/pmbus/mp5023.c
@@ -56,7 +56,7 @@ static struct i2c_driver mp5023_driver = {
.name = "mp5023",
.of_match_table = of_match_ptr(mp5023_of_match),
},
- .probe_new = mp5023_probe,
+ .probe = mp5023_probe,
};
module_i2c_driver(mp5023_driver);
diff --git a/drivers/hwmon/pmbus/mpq7932.c b/drivers/hwmon/pmbus/mpq7932.c
index ff939881dc3b..865d42edda1a 100644
--- a/drivers/hwmon/pmbus/mpq7932.c
+++ b/drivers/hwmon/pmbus/mpq7932.c
@@ -145,7 +145,7 @@ static struct i2c_driver mpq7932_regulator_driver = {
.name = "mpq7932",
.of_match_table = mpq7932_of_match,
},
- .probe_new = mpq7932_probe,
+ .probe = mpq7932_probe,
.id_table = mpq7932_id,
};
module_i2c_driver(mpq7932_regulator_driver);
diff --git a/drivers/hwmon/pmbus/pim4328.c b/drivers/hwmon/pmbus/pim4328.c
index 273ff6e57654..31d9ae06379a 100644
--- a/drivers/hwmon/pmbus/pim4328.c
+++ b/drivers/hwmon/pmbus/pim4328.c
@@ -221,7 +221,7 @@ static struct i2c_driver pim4328_driver = {
.driver = {
.name = "pim4328",
},
- .probe_new = pim4328_probe,
+ .probe = pim4328_probe,
.id_table = pim4328_id,
};
diff --git a/drivers/hwmon/pmbus/pli1209bc.c b/drivers/hwmon/pmbus/pli1209bc.c
index 05b4ee35ba27..7d8bd3167b21 100644
--- a/drivers/hwmon/pmbus/pli1209bc.c
+++ b/drivers/hwmon/pmbus/pli1209bc.c
@@ -134,7 +134,7 @@ static struct i2c_driver pli1209bc_driver = {
.name = "pli1209bc",
.of_match_table = of_match_ptr(pli1209bc_of_match),
},
- .probe_new = pli1209bc_probe,
+ .probe = pli1209bc_probe,
.id_table = pli1209bc_id,
};
diff --git a/drivers/hwmon/pmbus/pm6764tr.c b/drivers/hwmon/pmbus/pm6764tr.c
index e0bbc8a30d21..2a16504c85b7 100644
--- a/drivers/hwmon/pmbus/pm6764tr.c
+++ b/drivers/hwmon/pmbus/pm6764tr.c
@@ -64,7 +64,7 @@ static struct i2c_driver pm6764tr_driver = {
.name = "pm6764tr",
.of_match_table = of_match_ptr(pm6764tr_of_match),
},
- .probe_new = pm6764tr_probe,
+ .probe = pm6764tr_probe,
.id_table = pm6764tr_id,
};
diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c
index d0d386990af5..ec40c5c59954 100644
--- a/drivers/hwmon/pmbus/pmbus.c
+++ b/drivers/hwmon/pmbus/pmbus.c
@@ -252,7 +252,7 @@ static struct i2c_driver pmbus_driver = {
.driver = {
.name = "pmbus",
},
- .probe_new = pmbus_probe,
+ .probe = pmbus_probe,
.id_table = pmbus_id,
};
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 9d14954da94f..fa06325f5a7c 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -1191,9 +1191,9 @@ static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr)
{
if (data->num_attributes >= data->max_attributes - 1) {
int new_max_attrs = data->max_attributes + PMBUS_ATTR_ALLOC_SIZE;
- void *new_attrs = devm_krealloc(data->dev, data->group.attrs,
- new_max_attrs * sizeof(void *),
- GFP_KERNEL);
+ void *new_attrs = devm_krealloc_array(data->dev, data->group.attrs,
+ new_max_attrs, sizeof(void *),
+ GFP_KERNEL);
if (!new_attrs)
return -ENOMEM;
data->group.attrs = new_attrs;
diff --git a/drivers/hwmon/pmbus/pxe1610.c b/drivers/hwmon/pmbus/pxe1610.c
index 52bee5de2988..e2790a682dc8 100644
--- a/drivers/hwmon/pmbus/pxe1610.c
+++ b/drivers/hwmon/pmbus/pxe1610.c
@@ -139,7 +139,7 @@ static struct i2c_driver pxe1610_driver = {
.driver = {
.name = "pxe1610",
},
- .probe_new = pxe1610_probe,
+ .probe = pxe1610_probe,
.id_table = pxe1610_id,
};
diff --git a/drivers/hwmon/pmbus/q54sj108a2.c b/drivers/hwmon/pmbus/q54sj108a2.c
index d3ba12951324..b830f3b02bcc 100644
--- a/drivers/hwmon/pmbus/q54sj108a2.c
+++ b/drivers/hwmon/pmbus/q54sj108a2.c
@@ -412,7 +412,7 @@ static struct i2c_driver q54sj108a2_driver = {
.name = "q54sj108a2",
.of_match_table = q54sj108a2_of_match,
},
- .probe_new = q54sj108a2_probe,
+ .probe = q54sj108a2_probe,
.id_table = q54sj108a2_id,
};
diff --git a/drivers/hwmon/pmbus/stpddc60.c b/drivers/hwmon/pmbus/stpddc60.c
index 357b9d9d896b..be9076dcc2db 100644
--- a/drivers/hwmon/pmbus/stpddc60.c
+++ b/drivers/hwmon/pmbus/stpddc60.c
@@ -237,7 +237,7 @@ static struct i2c_driver stpddc60_driver = {
.driver = {
.name = "stpddc60",
},
- .probe_new = stpddc60_probe,
+ .probe = stpddc60_probe,
.id_table = stpddc60_id,
};
diff --git a/drivers/hwmon/pmbus/tda38640.c b/drivers/hwmon/pmbus/tda38640.c
index c3e781319cd1..450b0273fb59 100644
--- a/drivers/hwmon/pmbus/tda38640.c
+++ b/drivers/hwmon/pmbus/tda38640.c
@@ -62,7 +62,7 @@ static struct i2c_driver tda38640_driver = {
.name = "tda38640",
.of_match_table = of_match_ptr(tda38640_of_match),
},
- .probe_new = tda38640_probe,
+ .probe = tda38640_probe,
.id_table = tda38640_id,
};
diff --git a/drivers/hwmon/pmbus/tps40422.c b/drivers/hwmon/pmbus/tps40422.c
index 31bb83c0ef3e..ea0074a6b9fc 100644
--- a/drivers/hwmon/pmbus/tps40422.c
+++ b/drivers/hwmon/pmbus/tps40422.c
@@ -42,7 +42,7 @@ static struct i2c_driver tps40422_driver = {
.driver = {
.name = "tps40422",
},
- .probe_new = tps40422_probe,
+ .probe = tps40422_probe,
.id_table = tps40422_id,
};
diff --git a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c
index 81b9d813655a..ef99005a3af5 100644
--- a/drivers/hwmon/pmbus/tps53679.c
+++ b/drivers/hwmon/pmbus/tps53679.c
@@ -299,7 +299,7 @@ static struct i2c_driver tps53679_driver = {
.name = "tps53679",
.of_match_table = of_match_ptr(tps53679_of_match),
},
- .probe_new = tps53679_probe,
+ .probe = tps53679_probe,
.id_table = tps53679_id,
};
diff --git a/drivers/hwmon/pmbus/tps546d24.c b/drivers/hwmon/pmbus/tps546d24.c
index 435f94304ad8..69bbdb6c680b 100644
--- a/drivers/hwmon/pmbus/tps546d24.c
+++ b/drivers/hwmon/pmbus/tps546d24.c
@@ -59,7 +59,7 @@ static struct i2c_driver tps546d24_driver = {
.name = "tps546d24",
.of_match_table = of_match_ptr(tps546d24_of_match),
},
- .probe_new = tps546d24_probe,
+ .probe = tps546d24_probe,
.id_table = tps546d24_id,
};
diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c
index 3daaf2237832..c404d306e8f7 100644
--- a/drivers/hwmon/pmbus/ucd9000.c
+++ b/drivers/hwmon/pmbus/ucd9000.c
@@ -512,8 +512,6 @@ static int ucd9000_init_debugfs(struct i2c_client *client,
return -ENOENT;
data->debugfs = debugfs_create_dir(client->name, debugfs);
- if (!data->debugfs)
- return -ENOENT;
/*
* Of the chips this driver supports, only the UCD9090, UCD90160,
@@ -695,7 +693,7 @@ static struct i2c_driver ucd9000_driver = {
.name = "ucd9000",
.of_match_table = of_match_ptr(ucd9000_of_match),
},
- .probe_new = ucd9000_probe,
+ .probe = ucd9000_probe,
.id_table = ucd9000_id,
};
diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c
index 3ad375a76f3e..a82847945508 100644
--- a/drivers/hwmon/pmbus/ucd9200.c
+++ b/drivers/hwmon/pmbus/ucd9200.c
@@ -200,7 +200,7 @@ static struct i2c_driver ucd9200_driver = {
.name = "ucd9200",
.of_match_table = of_match_ptr(ucd9200_of_match),
},
- .probe_new = ucd9200_probe,
+ .probe = ucd9200_probe,
.id_table = ucd9200_id,
};
diff --git a/drivers/hwmon/pmbus/xdpe12284.c b/drivers/hwmon/pmbus/xdpe12284.c
index 32bc7736d609..37d08dd427d5 100644
--- a/drivers/hwmon/pmbus/xdpe12284.c
+++ b/drivers/hwmon/pmbus/xdpe12284.c
@@ -185,7 +185,7 @@ static struct i2c_driver xdpe122_driver = {
.name = "xdpe12284",
.of_match_table = of_match_ptr(xdpe122_of_match),
},
- .probe_new = xdpe122_probe,
+ .probe = xdpe122_probe,
.id_table = xdpe122_id,
};
diff --git a/drivers/hwmon/pmbus/xdpe152c4.c b/drivers/hwmon/pmbus/xdpe152c4.c
index b8a36ef73e45..235e6b41ae4c 100644
--- a/drivers/hwmon/pmbus/xdpe152c4.c
+++ b/drivers/hwmon/pmbus/xdpe152c4.c
@@ -63,7 +63,7 @@ static struct i2c_driver xdpe152_driver = {
.name = "xdpe152c4",
.of_match_table = of_match_ptr(xdpe152_of_match),
},
- .probe_new = xdpe152_probe,
+ .probe = xdpe152_probe,
.id_table = xdpe152_id,
};
diff --git a/drivers/hwmon/pmbus/zl6100.c b/drivers/hwmon/pmbus/zl6100.c
index e9df0c56d91e..83458df0d0cf 100644
--- a/drivers/hwmon/pmbus/zl6100.c
+++ b/drivers/hwmon/pmbus/zl6100.c
@@ -461,7 +461,7 @@ static struct i2c_driver zl6100_driver = {
.driver = {
.name = "zl6100",
},
- .probe_new = zl6100_probe,
+ .probe = zl6100_probe,
.id_table = zl6100_id,
};
diff --git a/drivers/hwmon/powr1220.c b/drivers/hwmon/powr1220.c
index 9cb0c2de5219..4120cadb00ae 100644
--- a/drivers/hwmon/powr1220.c
+++ b/drivers/hwmon/powr1220.c
@@ -327,7 +327,7 @@ static struct i2c_driver powr1220_driver = {
.driver = {
.name = "powr1220",
},
- .probe_new = powr1220_probe,
+ .probe = powr1220_probe,
.id_table = powr1220_ids,
};
diff --git a/drivers/hwmon/sbrmi.c b/drivers/hwmon/sbrmi.c
index 529f0e766319..484703f0ea5f 100644
--- a/drivers/hwmon/sbrmi.c
+++ b/drivers/hwmon/sbrmi.c
@@ -347,7 +347,7 @@ static struct i2c_driver sbrmi_driver = {
.name = "sbrmi",
.of_match_table = of_match_ptr(sbrmi_of_match),
},
- .probe_new = sbrmi_probe,
+ .probe = sbrmi_probe,
.id_table = sbrmi_id,
};
diff --git a/drivers/hwmon/sbtsi_temp.c b/drivers/hwmon/sbtsi_temp.c
index 7049d9464ac6..b79cece4ac9a 100644
--- a/drivers/hwmon/sbtsi_temp.c
+++ b/drivers/hwmon/sbtsi_temp.c
@@ -238,7 +238,7 @@ static struct i2c_driver sbtsi_driver = {
.name = "sbtsi",
.of_match_table = of_match_ptr(sbtsi_of_match),
},
- .probe_new = sbtsi_probe,
+ .probe = sbtsi_probe,
.id_table = sbtsi_id,
};
diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c
index f50b90198f23..55c179475208 100644
--- a/drivers/hwmon/sht21.c
+++ b/drivers/hwmon/sht21.c
@@ -285,7 +285,7 @@ MODULE_DEVICE_TABLE(i2c, sht21_id);
static struct i2c_driver sht21_driver = {
.driver.name = "sht21",
- .probe_new = sht21_probe,
+ .probe = sht21_probe,
.id_table = sht21_id,
};
diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c
index 8305e44d9ab2..bf18630619e0 100644
--- a/drivers/hwmon/sht3x.c
+++ b/drivers/hwmon/sht3x.c
@@ -20,15 +20,15 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
-#include <linux/platform_data/sht3x.h>
-/* commands (high precision mode) */
-static const unsigned char sht3x_cmd_measure_blocking_hpm[] = { 0x2c, 0x06 };
-static const unsigned char sht3x_cmd_measure_nonblocking_hpm[] = { 0x24, 0x00 };
+/* commands (high repeatability mode) */
+static const unsigned char sht3x_cmd_measure_single_hpm[] = { 0x24, 0x00 };
-/* commands (low power mode) */
-static const unsigned char sht3x_cmd_measure_blocking_lpm[] = { 0x2c, 0x10 };
-static const unsigned char sht3x_cmd_measure_nonblocking_lpm[] = { 0x24, 0x16 };
+/* commands (medium repeatability mode) */
+static const unsigned char sht3x_cmd_measure_single_mpm[] = { 0x24, 0x0b };
+
+/* commands (low repeatability mode) */
+static const unsigned char sht3x_cmd_measure_single_lpm[] = { 0x24, 0x16 };
/* commands for periodic mode */
static const unsigned char sht3x_cmd_measure_periodic_mode[] = { 0xe0, 0x00 };
@@ -42,9 +42,10 @@ static const unsigned char sht3x_cmd_heater_off[] = { 0x30, 0x66 };
static const unsigned char sht3x_cmd_read_status_reg[] = { 0xf3, 0x2d };
static const unsigned char sht3x_cmd_clear_status_reg[] = { 0x30, 0x41 };
-/* delays for non-blocking i2c commands, both in us */
-#define SHT3X_NONBLOCKING_WAIT_TIME_HPM 15000
-#define SHT3X_NONBLOCKING_WAIT_TIME_LPM 4000
+/* delays for single-shot mode i2c commands, both in us */
+#define SHT3X_SINGLE_WAIT_TIME_HPM 15000
+#define SHT3X_SINGLE_WAIT_TIME_MPM 6000
+#define SHT3X_SINGLE_WAIT_TIME_LPM 4000
#define SHT3X_WORD_LEN 2
#define SHT3X_CMD_LENGTH 2
@@ -69,9 +70,15 @@ enum sht3x_limits {
limit_min_hyst,
};
+enum sht3x_repeatability {
+ low_repeatability,
+ medium_repeatability,
+ high_repeatability,
+};
+
DECLARE_CRC8_TABLE(sht3x_crc8_table);
-/* periodic measure commands (high precision mode) */
+/* periodic measure commands (high repeatability mode) */
static const char periodic_measure_commands_hpm[][SHT3X_CMD_LENGTH] = {
/* 0.5 measurements per second */
{0x20, 0x32},
@@ -85,7 +92,21 @@ static const char periodic_measure_commands_hpm[][SHT3X_CMD_LENGTH] = {
{0x27, 0x37},
};
-/* periodic measure commands (low power mode) */
+/* periodic measure commands (medium repeatability) */
+static const char periodic_measure_commands_mpm[][SHT3X_CMD_LENGTH] = {
+ /* 0.5 measurements per second */
+ {0x20, 0x24},
+ /* 1 measurements per second */
+ {0x21, 0x26},
+ /* 2 measurements per second */
+ {0x22, 0x20},
+ /* 4 measurements per second */
+ {0x23, 0x22},
+ /* 10 measurements per second */
+ {0x27, 0x21},
+};
+
+/* periodic measure commands (low repeatability mode) */
static const char periodic_measure_commands_lpm[][SHT3X_CMD_LENGTH] = {
/* 0.5 measurements per second */
{0x20, 0x2f},
@@ -135,8 +156,7 @@ struct sht3x_data {
const unsigned char *command;
u32 wait_time; /* in us*/
unsigned long last_update; /* last update in periodic mode*/
-
- struct sht3x_platform_data setup;
+ enum sht3x_repeatability repeatability;
/*
* cached values for temperature and humidity and limits
@@ -433,26 +453,22 @@ static ssize_t humidity1_limit_store(struct device *dev,
static void sht3x_select_command(struct sht3x_data *data)
{
/*
- * In blocking mode (clock stretching mode) the I2C bus
- * is blocked for other traffic, thus the call to i2c_master_recv()
- * will wait until the data is ready. For non blocking mode, we
- * have to wait ourselves.
+ * For single-shot mode, only non blocking mode is support,
+ * we have to wait ourselves for result.
*/
if (data->mode > 0) {
data->command = sht3x_cmd_measure_periodic_mode;
data->wait_time = 0;
- } else if (data->setup.blocking_io) {
- data->command = data->setup.high_precision ?
- sht3x_cmd_measure_blocking_hpm :
- sht3x_cmd_measure_blocking_lpm;
- data->wait_time = 0;
} else {
- if (data->setup.high_precision) {
- data->command = sht3x_cmd_measure_nonblocking_hpm;
- data->wait_time = SHT3X_NONBLOCKING_WAIT_TIME_HPM;
+ if (data->repeatability == high_repeatability) {
+ data->command = sht3x_cmd_measure_single_hpm;
+ data->wait_time = SHT3X_SINGLE_WAIT_TIME_HPM;
+ } else if (data->repeatability == medium_repeatability) {
+ data->command = sht3x_cmd_measure_single_mpm;
+ data->wait_time = SHT3X_SINGLE_WAIT_TIME_MPM;
} else {
- data->command = sht3x_cmd_measure_nonblocking_lpm;
- data->wait_time = SHT3X_NONBLOCKING_WAIT_TIME_LPM;
+ data->command = sht3x_cmd_measure_single_lpm;
+ data->wait_time = SHT3X_SINGLE_WAIT_TIME_LPM;
}
}
}
@@ -595,8 +611,10 @@ static ssize_t update_interval_store(struct device *dev,
}
if (mode > 0) {
- if (data->setup.high_precision)
+ if (data->repeatability == high_repeatability)
command = periodic_measure_commands_hpm[mode - 1];
+ else if (data->repeatability == medium_repeatability)
+ command = periodic_measure_commands_mpm[mode - 1];
else
command = periodic_measure_commands_lpm[mode - 1];
@@ -619,6 +637,37 @@ out:
return count;
}
+static ssize_t repeatability_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sht3x_data *data = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%d\n", data->repeatability);
+}
+
+static ssize_t repeatability_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int ret;
+ u8 val;
+
+ struct sht3x_data *data = dev_get_drvdata(dev);
+
+ ret = kstrtou8(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ if (val > 2)
+ return -EINVAL;
+
+ data->repeatability = val;
+
+ return count;
+}
+
static SENSOR_DEVICE_ATTR_RO(temp1_input, temp1_input, 0);
static SENSOR_DEVICE_ATTR_RO(humidity1_input, humidity1_input, 0);
static SENSOR_DEVICE_ATTR_RW(temp1_max, temp1_limit, limit_max);
@@ -635,6 +684,7 @@ static SENSOR_DEVICE_ATTR_RO(temp1_alarm, temp1_alarm, 0);
static SENSOR_DEVICE_ATTR_RO(humidity1_alarm, humidity1_alarm, 0);
static SENSOR_DEVICE_ATTR_RW(heater_enable, heater_enable, 0);
static SENSOR_DEVICE_ATTR_RW(update_interval, update_interval, 0);
+static SENSOR_DEVICE_ATTR_RW(repeatability, repeatability, 0);
static struct attribute *sht3x_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -651,11 +701,20 @@ static struct attribute *sht3x_attrs[] = {
&sensor_dev_attr_humidity1_alarm.dev_attr.attr,
&sensor_dev_attr_heater_enable.dev_attr.attr,
&sensor_dev_attr_update_interval.dev_attr.attr,
+ &sensor_dev_attr_repeatability.dev_attr.attr,
NULL
};
static struct attribute *sts3x_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_temp1_max.dev_attr.attr,
+ &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp1_min.dev_attr.attr,
+ &sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp1_alarm.dev_attr.attr,
+ &sensor_dev_attr_heater_enable.dev_attr.attr,
+ &sensor_dev_attr_update_interval.dev_attr.attr,
+ &sensor_dev_attr_repeatability.dev_attr.attr,
NULL
};
@@ -690,16 +749,12 @@ static int sht3x_probe(struct i2c_client *client)
if (!data)
return -ENOMEM;
- data->setup.blocking_io = false;
- data->setup.high_precision = true;
+ data->repeatability = high_repeatability;
data->mode = 0;
data->last_update = jiffies - msecs_to_jiffies(3000);
data->client = client;
crc8_populate_msb(sht3x_crc8_table, SHT3X_CRC8_POLYNOMIAL);
- if (client->dev.platform_data)
- data->setup = *(struct sht3x_platform_data *)dev->platform_data;
-
sht3x_select_command(data);
mutex_init(&data->i2c_lock);
@@ -743,7 +798,7 @@ MODULE_DEVICE_TABLE(i2c, sht3x_ids);
static struct i2c_driver sht3x_i2c_driver = {
.driver.name = "sht3x",
- .probe_new = sht3x_probe,
+ .probe = sht3x_probe,
.id_table = sht3x_ids,
};
diff --git a/drivers/hwmon/sht4x.c b/drivers/hwmon/sht4x.c
index 5bbe09135ab9..7ee797410458 100644
--- a/drivers/hwmon/sht4x.c
+++ b/drivers/hwmon/sht4x.c
@@ -291,7 +291,7 @@ static struct i2c_driver sht4x_driver = {
.name = "sht4x",
.of_match_table = sht4x_of_match,
},
- .probe_new = sht4x_probe,
+ .probe = sht4x_probe,
.id_table = sht4x_id,
};
diff --git a/drivers/hwmon/shtc1.c b/drivers/hwmon/shtc1.c
index 18546ebc8e9f..1f96e94967ee 100644
--- a/drivers/hwmon/shtc1.c
+++ b/drivers/hwmon/shtc1.c
@@ -279,7 +279,7 @@ static struct i2c_driver shtc1_i2c_driver = {
.name = "shtc1",
.of_match_table = shtc1_of_match,
},
- .probe_new = shtc1_probe,
+ .probe = shtc1_probe,
.id_table = shtc1_id,
};
diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c
index c36bdbe423de..026c76f8c22e 100644
--- a/drivers/hwmon/smm665.c
+++ b/drivers/hwmon/smm665.c
@@ -694,7 +694,7 @@ static struct i2c_driver smm665_driver = {
.driver = {
.name = "smm665",
},
- .probe_new = smm665_probe,
+ .probe = smm665_probe,
.remove = smm665_remove,
.id_table = smm665_id,
};
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c
index 70d2152234e2..d20800a1f02b 100644
--- a/drivers/hwmon/smsc47m192.c
+++ b/drivers/hwmon/smsc47m192.c
@@ -628,7 +628,7 @@ static struct i2c_driver smsc47m192_driver = {
.driver = {
.name = "smsc47m192",
},
- .probe_new = smsc47m192_probe,
+ .probe = smsc47m192_probe,
.id_table = smsc47m192_id,
.detect = smsc47m192_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c
index 2f67c6747ead..847c99376930 100644
--- a/drivers/hwmon/stts751.c
+++ b/drivers/hwmon/stts751.c
@@ -821,7 +821,7 @@ static struct i2c_driver stts751_driver = {
.name = DEVNAME,
.of_match_table = of_match_ptr(stts751_of_match),
},
- .probe_new = stts751_probe,
+ .probe = stts751_probe,
.id_table = stts751_id,
.detect = stts751_detect,
.alert = stts751_alert,
diff --git a/drivers/hwmon/tc654.c b/drivers/hwmon/tc654.c
index 54cd33d09688..42a9658f1bc2 100644
--- a/drivers/hwmon/tc654.c
+++ b/drivers/hwmon/tc654.c
@@ -561,7 +561,7 @@ static struct i2c_driver tc654_driver = {
.driver = {
.name = "tc654",
},
- .probe_new = tc654_probe,
+ .probe = tc654_probe,
.id_table = tc654_id,
};
diff --git a/drivers/hwmon/tc74.c b/drivers/hwmon/tc74.c
index ace55da97fc2..03950670bd78 100644
--- a/drivers/hwmon/tc74.c
+++ b/drivers/hwmon/tc74.c
@@ -160,7 +160,7 @@ static struct i2c_driver tc74_driver = {
.driver = {
.name = "tc74",
},
- .probe_new = tc74_probe,
+ .probe = tc74_probe,
.id_table = tc74_id,
};
diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c
index 81cdb012993c..68ba26bc9014 100644
--- a/drivers/hwmon/thmc50.c
+++ b/drivers/hwmon/thmc50.c
@@ -420,7 +420,7 @@ static struct i2c_driver thmc50_driver = {
.driver = {
.name = "thmc50",
},
- .probe_new = thmc50_probe,
+ .probe = thmc50_probe,
.id_table = thmc50_id,
.detect = thmc50_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index e271556efe0b..2506c78590af 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -184,7 +184,7 @@ static const struct regmap_config tmp102_regmap_config = {
.writeable_reg = tmp102_is_writeable_reg,
.volatile_reg = tmp102_is_volatile_reg,
.val_format_endian = REGMAP_ENDIAN_BIG,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.use_single_read = true,
.use_single_write = true,
};
@@ -301,7 +301,7 @@ static struct i2c_driver tmp102_driver = {
.driver.name = DRIVER_NAME,
.driver.of_match_table = of_match_ptr(tmp102_of_match),
.driver.pm = pm_sleep_ptr(&tmp102_dev_pm_ops),
- .probe_new = tmp102_probe,
+ .probe = tmp102_probe,
.id_table = tmp102_id,
};
diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c
index d257bb91fc69..a84c29a3a765 100644
--- a/drivers/hwmon/tmp103.c
+++ b/drivers/hwmon/tmp103.c
@@ -214,7 +214,7 @@ static struct i2c_driver tmp103_driver = {
.of_match_table = of_match_ptr(tmp103_of_match),
.pm = pm_sleep_ptr(&tmp103_dev_pm_ops),
},
- .probe_new = tmp103_probe,
+ .probe = tmp103_probe,
.id_table = tmp103_id,
};
diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c
index 43784c289a9e..d7a09ab2bc11 100644
--- a/drivers/hwmon/tmp108.c
+++ b/drivers/hwmon/tmp108.c
@@ -318,7 +318,7 @@ static const struct regmap_config tmp108_regmap_config = {
.writeable_reg = tmp108_is_writeable_reg,
.volatile_reg = tmp108_is_volatile_reg,
.val_format_endian = REGMAP_ENDIAN_BIG,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.use_single_read = true,
.use_single_write = true,
};
@@ -432,7 +432,7 @@ static struct i2c_driver tmp108_driver = {
.pm = pm_sleep_ptr(&tmp108_dev_pm_ops),
.of_match_table = of_match_ptr(tmp108_of_ids),
},
- .probe_new = tmp108_probe,
+ .probe = tmp108_probe,
.id_table = tmp108_i2c_ids,
};
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c
index f358ba679626..91f2314568cf 100644
--- a/drivers/hwmon/tmp401.c
+++ b/drivers/hwmon/tmp401.c
@@ -766,7 +766,7 @@ static struct i2c_driver tmp401_driver = {
.name = "tmp401",
.of_match_table = of_match_ptr(tmp4xx_of_match),
},
- .probe_new = tmp401_probe,
+ .probe = tmp401_probe,
.id_table = tmp401_id,
.detect = tmp401_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index 45fd7fb5ee01..3cde3916ab6d 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -487,7 +487,7 @@ static struct i2c_driver tmp421_driver = {
.name = "tmp421",
.of_match_table = of_match_ptr(tmp421_of_match),
},
- .probe_new = tmp421_probe,
+ .probe = tmp421_probe,
.id_table = tmp421_id,
.detect = tmp421_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/tmp464.c b/drivers/hwmon/tmp464.c
index 9213a493a590..4b79c3f4d9fe 100644
--- a/drivers/hwmon/tmp464.c
+++ b/drivers/hwmon/tmp464.c
@@ -644,7 +644,7 @@ static const struct regmap_config tmp464_regmap_config = {
.max_register = TMP464_DEVICE_ID_REG,
.volatile_reg = tmp464_is_volatile_reg,
.val_format_endian = REGMAP_ENDIAN_BIG,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.use_single_read = true,
.use_single_write = true,
};
@@ -699,7 +699,7 @@ static struct i2c_driver tmp464_driver = {
.name = "tmp464",
.of_match_table = of_match_ptr(tmp464_of_match),
},
- .probe_new = tmp464_probe,
+ .probe = tmp464_probe,
.id_table = tmp464_id,
.detect = tmp464_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/tmp513.c b/drivers/hwmon/tmp513.c
index 0693eaee054f..bff10f4b56e1 100644
--- a/drivers/hwmon/tmp513.c
+++ b/drivers/hwmon/tmp513.c
@@ -760,7 +760,7 @@ static struct i2c_driver tmp51x_driver = {
.name = "tmp51x",
.of_match_table = tmp51x_of_match,
},
- .probe_new = tmp51x_probe,
+ .probe = tmp51x_probe,
.id_table = tmp51x_id,
};
diff --git a/drivers/hwmon/tps23861.c b/drivers/hwmon/tps23861.c
index 85a75f551148..8fbbb29ae11d 100644
--- a/drivers/hwmon/tps23861.c
+++ b/drivers/hwmon/tps23861.c
@@ -581,7 +581,7 @@ static const struct of_device_id __maybe_unused tps23861_of_match[] = {
MODULE_DEVICE_TABLE(of, tps23861_of_match);
static struct i2c_driver tps23861_driver = {
- .probe_new = tps23861_probe,
+ .probe = tps23861_probe,
.remove = tps23861_remove,
.driver = {
.name = "tps23861",
diff --git a/drivers/hwmon/w83773g.c b/drivers/hwmon/w83773g.c
index 8dbcd05abd9a..7f3615f5587c 100644
--- a/drivers/hwmon/w83773g.c
+++ b/drivers/hwmon/w83773g.c
@@ -295,7 +295,7 @@ static struct i2c_driver w83773_driver = {
.name = "w83773g",
.of_match_table = of_match_ptr(w83773_of_match),
},
- .probe_new = w83773_probe,
+ .probe = w83773_probe,
.id_table = w83773_id,
};
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index dacabf25e83f..b33f382f238d 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1585,7 +1585,7 @@ static struct i2c_driver w83781d_driver = {
.name = "w83781d",
.of_match_table = w83781d_of_match,
},
- .probe_new = w83781d_probe,
+ .probe = w83781d_probe,
.remove = w83781d_remove,
.id_table = w83781d_ids,
.detect = w83781d_detect,
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index eaf691365023..9681eaa06c8e 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -338,7 +338,7 @@ static struct i2c_driver w83791d_driver = {
.driver = {
.name = "w83791d",
},
- .probe_new = w83791d_probe,
+ .probe = w83791d_probe,
.remove = w83791d_remove,
.id_table = w83791d_id,
.detect = w83791d_detect,
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 6d160eee1446..69ce379a9e13 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -306,7 +306,7 @@ static struct i2c_driver w83792d_driver = {
.driver = {
.name = "w83792d",
},
- .probe_new = w83792d_probe,
+ .probe = w83792d_probe,
.remove = w83792d_remove,
.id_table = w83792d_id,
.detect = w83792d_detect,
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index a4926d907198..96bab94ba899 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -301,7 +301,7 @@ static struct i2c_driver w83793_driver = {
.driver = {
.name = "w83793",
},
- .probe_new = w83793_probe,
+ .probe = w83793_probe,
.remove = w83793_remove,
.id_table = w83793_id,
.detect = w83793_detect,
diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c
index 84ff5c57e98c..c446e00db658 100644
--- a/drivers/hwmon/w83795.c
+++ b/drivers/hwmon/w83795.c
@@ -2255,7 +2255,7 @@ static struct i2c_driver w83795_driver = {
.driver = {
.name = "w83795",
},
- .probe_new = w83795_probe,
+ .probe = w83795_probe,
.remove = w83795_remove,
.id_table = w83795_id,
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index f3622de0d96f..9c11ed69c055 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -84,7 +84,7 @@ static struct i2c_driver w83l785ts_driver = {
.driver = {
.name = "w83l785ts",
},
- .probe_new = w83l785ts_probe,
+ .probe = w83l785ts_probe,
.remove = w83l785ts_remove,
.id_table = w83l785ts_id,
.detect = w83l785ts_detect,
diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c
index 5597e1c2d95c..75874cf7851c 100644
--- a/drivers/hwmon/w83l786ng.c
+++ b/drivers/hwmon/w83l786ng.c
@@ -751,7 +751,7 @@ static struct i2c_driver w83l786ng_driver = {
.driver = {
.name = "w83l786ng",
},
- .probe_new = w83l786ng_probe,
+ .probe = w83l786ng_probe,
.id_table = w83l786ng_id,
.detect = w83l786ng_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
index 1fb3a2550e29..dfe82952671b 100644
--- a/drivers/hwspinlock/omap_hwspinlock.c
+++ b/drivers/hwspinlock/omap_hwspinlock.c
@@ -174,7 +174,7 @@ static struct platform_driver omap_hwspinlock_driver = {
.remove = omap_hwspinlock_remove,
.driver = {
.name = "omap_hwspinlock",
- .of_match_table = of_match_ptr(omap_hwspinlock_of_match),
+ .of_match_table = omap_hwspinlock_of_match,
},
};
diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index 2b5bbfffbc4f..06f0a7594169 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -236,4 +236,15 @@ config CORESIGHT_TPDA
To compile this driver as a module, choose M here: the module will be
called coresight-tpda.
+
+config CORESIGHT_DUMMY
+ tristate "Dummy driver support"
+ help
+ Enables support for dummy driver. Dummy driver can be used for
+ CoreSight sources/sinks that are owned and configured by some
+ other subsystem and use Linux drivers to configure rest of trace
+ path.
+
+ To compile this driver as a module, choose M here: the module will be
+ called coresight-dummy.
endif
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 33bcc3f7b8ae..995d3b2c76df 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_CORESIGHT_TPDA) += coresight-tpda.o
coresight-cti-y := coresight-cti-core.o coresight-cti-platform.o \
coresight-cti-sysfs.o
obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
+obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index bc90a03f478f..3949ded0d4fa 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -395,13 +395,18 @@ static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1);
}
-static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
+static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
+ void *data)
{
int rc;
u32 control, mode;
- struct etr_buf *etr_buf = data;
+ struct etr_buf *etr_buf = NULL;
struct device *dev = &drvdata->csdev->dev;
struct coresight_device *csdev = drvdata->csdev;
+ struct coresight_device *etrdev;
+ union coresight_dev_subtype etr_subtype = {
+ .sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM
+ };
if (catu_wait_for_ready(drvdata))
dev_warn(dev, "Timeout while waiting for READY\n");
@@ -416,6 +421,13 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
if (rc)
return rc;
+ etrdev = coresight_find_input_type(
+ csdev->pdata, CORESIGHT_DEV_TYPE_SINK, etr_subtype);
+ if (etrdev) {
+ etr_buf = tmc_etr_get_buffer(etrdev, cs_mode, data);
+ if (IS_ERR(etr_buf))
+ return PTR_ERR(etr_buf);
+ }
control |= BIT(CATU_CONTROL_ENABLE);
if (etr_buf && etr_buf->mode == ETR_MODE_CATU) {
@@ -441,13 +453,14 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
return 0;
}
-static int catu_enable(struct coresight_device *csdev, void *data)
+static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,
+ void *data)
{
int rc;
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
CS_UNLOCK(catu_drvdata->base);
- rc = catu_enable_hw(catu_drvdata, data);
+ rc = catu_enable_hw(catu_drvdata, mode, data);
CS_LOCK(catu_drvdata->base);
return rc;
}
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index d3bf82c0de1d..118fcf27854d 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -3,6 +3,7 @@
* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*/
+#include <linux/build_bug.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
@@ -112,40 +113,24 @@ struct coresight_device *coresight_get_percpu_sink(int cpu)
}
EXPORT_SYMBOL_GPL(coresight_get_percpu_sink);
-static int coresight_find_link_inport(struct coresight_device *csdev,
- struct coresight_device *parent)
+static struct coresight_connection *
+coresight_find_out_connection(struct coresight_device *src_dev,
+ struct coresight_device *dest_dev)
{
int i;
struct coresight_connection *conn;
- for (i = 0; i < parent->pdata->nr_outport; i++) {
- conn = &parent->pdata->conns[i];
- if (conn->child_dev == csdev)
- return conn->child_port;
+ for (i = 0; i < src_dev->pdata->nr_outconns; i++) {
+ conn = src_dev->pdata->out_conns[i];
+ if (conn->dest_dev == dest_dev)
+ return conn;
}
- dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n",
- dev_name(&parent->dev), dev_name(&csdev->dev));
+ dev_err(&src_dev->dev,
+ "couldn't find output connection, src_dev: %s, dest_dev: %s\n",
+ dev_name(&src_dev->dev), dev_name(&dest_dev->dev));
- return -ENODEV;
-}
-
-static int coresight_find_link_outport(struct coresight_device *csdev,
- struct coresight_device *child)
-{
- int i;
- struct coresight_connection *conn;
-
- for (i = 0; i < csdev->pdata->nr_outport; i++) {
- conn = &csdev->pdata->conns[i];
- if (conn->child_dev == child)
- return conn->outport;
- }
-
- dev_err(&csdev->dev, "couldn't find outport, parent: %s, child: %s\n",
- dev_name(&csdev->dev), dev_name(&child->dev));
-
- return -ENODEV;
+ return ERR_PTR(-ENODEV);
}
static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
@@ -252,63 +237,47 @@ void coresight_disclaim_device(struct coresight_device *csdev)
}
EXPORT_SYMBOL_GPL(coresight_disclaim_device);
-/* enable or disable an associated CTI device of the supplied CS device */
-static int
-coresight_control_assoc_ectdev(struct coresight_device *csdev, bool enable)
+/*
+ * Add a helper as an output device. This function takes the @coresight_mutex
+ * because it's assumed that it's called from the helper device, outside of the
+ * core code where the mutex would already be held. Don't add new calls to this
+ * from inside the core code, instead try to add the new helper to the DT and
+ * ACPI where it will be picked up and linked automatically.
+ */
+void coresight_add_helper(struct coresight_device *csdev,
+ struct coresight_device *helper)
{
- int ect_ret = 0;
- struct coresight_device *ect_csdev = csdev->ect_dev;
- struct module *mod;
+ int i;
+ struct coresight_connection conn = {};
+ struct coresight_connection *new_conn;
- if (!ect_csdev)
- return 0;
- if ((!ect_ops(ect_csdev)->enable) || (!ect_ops(ect_csdev)->disable))
- return 0;
+ mutex_lock(&coresight_mutex);
+ conn.dest_fwnode = fwnode_handle_get(dev_fwnode(&helper->dev));
+ conn.dest_dev = helper;
+ conn.dest_port = conn.src_port = -1;
+ conn.src_dev = csdev;
- mod = ect_csdev->dev.parent->driver->owner;
- if (enable) {
- if (try_module_get(mod)) {
- ect_ret = ect_ops(ect_csdev)->enable(ect_csdev);
- if (ect_ret) {
- module_put(mod);
- } else {
- get_device(ect_csdev->dev.parent);
- csdev->ect_enabled = true;
- }
- } else
- ect_ret = -ENODEV;
- } else {
- if (csdev->ect_enabled) {
- ect_ret = ect_ops(ect_csdev)->disable(ect_csdev);
- put_device(ect_csdev->dev.parent);
- module_put(mod);
- csdev->ect_enabled = false;
- }
- }
+ /*
+ * Check for duplicates because this is called every time a helper
+ * device is re-loaded. Existing connections will get re-linked
+ * automatically.
+ */
+ for (i = 0; i < csdev->pdata->nr_outconns; ++i)
+ if (csdev->pdata->out_conns[i]->dest_fwnode == conn.dest_fwnode)
+ goto unlock;
- /* output warning if ECT enable is preventing trace operation */
- if (ect_ret)
- dev_info(&csdev->dev, "Associated ECT device (%s) %s failed\n",
- dev_name(&ect_csdev->dev),
- enable ? "enable" : "disable");
- return ect_ret;
-}
+ new_conn = coresight_add_out_conn(csdev->dev.parent, csdev->pdata,
+ &conn);
+ if (!IS_ERR(new_conn))
+ coresight_add_in_conn(new_conn);
-/*
- * Set the associated ect / cti device while holding the coresight_mutex
- * to avoid a race with coresight_enable that may try to use this value.
- */
-void coresight_set_assoc_ectdev_mutex(struct coresight_device *csdev,
- struct coresight_device *ect_csdev)
-{
- mutex_lock(&coresight_mutex);
- csdev->ect_dev = ect_csdev;
+unlock:
mutex_unlock(&coresight_mutex);
}
-EXPORT_SYMBOL_GPL(coresight_set_assoc_ectdev_mutex);
+EXPORT_SYMBOL_GPL(coresight_add_helper);
static int coresight_enable_sink(struct coresight_device *csdev,
- u32 mode, void *data)
+ enum cs_mode mode, void *data)
{
int ret;
@@ -319,14 +288,10 @@ static int coresight_enable_sink(struct coresight_device *csdev,
if (!sink_ops(csdev)->enable)
return -EINVAL;
- ret = coresight_control_assoc_ectdev(csdev, true);
- if (ret)
- return ret;
ret = sink_ops(csdev)->enable(csdev, mode, data);
- if (ret) {
- coresight_control_assoc_ectdev(csdev, false);
+ if (ret)
return ret;
- }
+
csdev->enable = true;
return 0;
@@ -342,7 +307,6 @@ static void coresight_disable_sink(struct coresight_device *csdev)
ret = sink_ops(csdev)->disable(csdev);
if (ret)
return;
- coresight_control_assoc_ectdev(csdev, false);
csdev->enable = false;
}
@@ -352,32 +316,26 @@ static int coresight_enable_link(struct coresight_device *csdev,
{
int ret = 0;
int link_subtype;
- int inport, outport;
+ struct coresight_connection *inconn, *outconn;
if (!parent || !child)
return -EINVAL;
- inport = coresight_find_link_inport(csdev, parent);
- outport = coresight_find_link_outport(csdev, child);
+ inconn = coresight_find_out_connection(parent, csdev);
+ outconn = coresight_find_out_connection(csdev, child);
link_subtype = csdev->subtype.link_subtype;
- if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && inport < 0)
- return inport;
- if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && outport < 0)
- return outport;
+ if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && IS_ERR(inconn))
+ return PTR_ERR(inconn);
+ if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && IS_ERR(outconn))
+ return PTR_ERR(outconn);
if (link_ops(csdev)->enable) {
- ret = coresight_control_assoc_ectdev(csdev, true);
- if (!ret) {
- ret = link_ops(csdev)->enable(csdev, inport, outport);
- if (ret)
- coresight_control_assoc_ectdev(csdev, false);
- }
+ ret = link_ops(csdev)->enable(csdev, inconn, outconn);
+ if (!ret)
+ csdev->enable = true;
}
- if (!ret)
- csdev->enable = true;
-
return ret;
}
@@ -385,78 +343,125 @@ static void coresight_disable_link(struct coresight_device *csdev,
struct coresight_device *parent,
struct coresight_device *child)
{
- int i, nr_conns;
+ int i;
int link_subtype;
- int inport, outport;
+ struct coresight_connection *inconn, *outconn;
if (!parent || !child)
return;
- inport = coresight_find_link_inport(csdev, parent);
- outport = coresight_find_link_outport(csdev, child);
+ inconn = coresight_find_out_connection(parent, csdev);
+ outconn = coresight_find_out_connection(csdev, child);
link_subtype = csdev->subtype.link_subtype;
- if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
- nr_conns = csdev->pdata->nr_inport;
- } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
- nr_conns = csdev->pdata->nr_outport;
- } else {
- nr_conns = 1;
- }
-
if (link_ops(csdev)->disable) {
- link_ops(csdev)->disable(csdev, inport, outport);
- coresight_control_assoc_ectdev(csdev, false);
+ link_ops(csdev)->disable(csdev, inconn, outconn);
}
- for (i = 0; i < nr_conns; i++)
- if (atomic_read(&csdev->refcnt[i]) != 0)
+ if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
+ for (i = 0; i < csdev->pdata->nr_inconns; i++)
+ if (atomic_read(&csdev->pdata->in_conns[i]->dest_refcnt) !=
+ 0)
+ return;
+ } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
+ for (i = 0; i < csdev->pdata->nr_outconns; i++)
+ if (atomic_read(&csdev->pdata->out_conns[i]->src_refcnt) !=
+ 0)
+ return;
+ } else {
+ if (atomic_read(&csdev->refcnt) != 0)
return;
+ }
csdev->enable = false;
}
-static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
+int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode,
+ void *data)
{
int ret;
if (!csdev->enable) {
if (source_ops(csdev)->enable) {
- ret = coresight_control_assoc_ectdev(csdev, true);
+ ret = source_ops(csdev)->enable(csdev, data, mode);
if (ret)
return ret;
- ret = source_ops(csdev)->enable(csdev, NULL, mode);
- if (ret) {
- coresight_control_assoc_ectdev(csdev, false);
- return ret;
- }
}
csdev->enable = true;
}
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(coresight_enable_source);
+
+static bool coresight_is_helper(struct coresight_device *csdev)
+{
+ return csdev->type == CORESIGHT_DEV_TYPE_HELPER;
+}
+
+static int coresight_enable_helper(struct coresight_device *csdev,
+ enum cs_mode mode, void *data)
+{
+ int ret;
+
+ if (!helper_ops(csdev)->enable)
+ return 0;
+ ret = helper_ops(csdev)->enable(csdev, mode, data);
+ if (ret)
+ return ret;
+ csdev->enable = true;
return 0;
}
+static void coresight_disable_helper(struct coresight_device *csdev)
+{
+ int ret;
+
+ if (!helper_ops(csdev)->disable)
+ return;
+
+ ret = helper_ops(csdev)->disable(csdev, NULL);
+ if (ret)
+ return;
+ csdev->enable = false;
+}
+
+static void coresight_disable_helpers(struct coresight_device *csdev)
+{
+ int i;
+ struct coresight_device *helper;
+
+ for (i = 0; i < csdev->pdata->nr_outconns; ++i) {
+ helper = csdev->pdata->out_conns[i]->dest_dev;
+ if (helper && coresight_is_helper(helper))
+ coresight_disable_helper(helper);
+ }
+}
+
/**
* coresight_disable_source - Drop the reference count by 1 and disable
* the device if there are no users left.
*
* @csdev: The coresight device to disable
+ * @data: Opaque data to pass on to the disable function of the source device.
+ * For example in perf mode this is a pointer to the struct perf_event.
*
* Returns true if the device has been disabled.
*/
-static bool coresight_disable_source(struct coresight_device *csdev)
+bool coresight_disable_source(struct coresight_device *csdev, void *data)
{
- if (atomic_dec_return(csdev->refcnt) == 0) {
+ if (atomic_dec_return(&csdev->refcnt) == 0) {
if (source_ops(csdev)->disable)
- source_ops(csdev)->disable(csdev, NULL);
- coresight_control_assoc_ectdev(csdev, false);
+ source_ops(csdev)->disable(csdev, data);
+ coresight_disable_helpers(csdev);
csdev->enable = false;
}
return !csdev->enable;
}
+EXPORT_SYMBOL_GPL(coresight_disable_source);
/*
* coresight_disable_path_from : Disable components in the given path beyond
@@ -507,6 +512,9 @@ static void coresight_disable_path_from(struct list_head *path,
default:
break;
}
+
+ /* Disable all helpers adjacent along the path last */
+ coresight_disable_helpers(csdev);
}
}
@@ -516,9 +524,28 @@ void coresight_disable_path(struct list_head *path)
}
EXPORT_SYMBOL_GPL(coresight_disable_path);
-int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data)
+static int coresight_enable_helpers(struct coresight_device *csdev,
+ enum cs_mode mode, void *data)
{
+ int i, ret = 0;
+ struct coresight_device *helper;
+ for (i = 0; i < csdev->pdata->nr_outconns; ++i) {
+ helper = csdev->pdata->out_conns[i]->dest_dev;
+ if (!helper || !coresight_is_helper(helper))
+ continue;
+
+ ret = coresight_enable_helper(helper, mode, data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int coresight_enable_path(struct list_head *path, enum cs_mode mode,
+ void *sink_data)
+{
int ret = 0;
u32 type;
struct coresight_node *nd;
@@ -528,6 +555,10 @@ int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data)
csdev = nd->csdev;
type = csdev->type;
+ /* Enable all helpers adjacent to the path first */
+ ret = coresight_enable_helpers(csdev, mode, sink_data);
+ if (ret)
+ goto err;
/*
* ETF devices are tricky... They can be a link or a sink,
* depending on how they are configured. If an ETF has been
@@ -602,10 +633,10 @@ coresight_find_enabled_sink(struct coresight_device *csdev)
/*
* Recursively explore each port found on this element.
*/
- for (i = 0; i < csdev->pdata->nr_outport; i++) {
+ for (i = 0; i < csdev->pdata->nr_outconns; i++) {
struct coresight_device *child_dev;
- child_dev = csdev->pdata->conns[i].child_dev;
+ child_dev = csdev->pdata->out_conns[i]->dest_dev;
if (child_dev)
sink = coresight_find_enabled_sink(child_dev);
if (sink)
@@ -718,11 +749,11 @@ static int coresight_grab_device(struct coresight_device *csdev)
{
int i;
- for (i = 0; i < csdev->pdata->nr_outport; i++) {
+ for (i = 0; i < csdev->pdata->nr_outconns; i++) {
struct coresight_device *child;
- child = csdev->pdata->conns[i].child_dev;
- if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
+ child = csdev->pdata->out_conns[i]->dest_dev;
+ if (child && coresight_is_helper(child))
if (!coresight_get_ref(child))
goto err;
}
@@ -732,8 +763,8 @@ err:
for (i--; i >= 0; i--) {
struct coresight_device *child;
- child = csdev->pdata->conns[i].child_dev;
- if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
+ child = csdev->pdata->out_conns[i]->dest_dev;
+ if (child && coresight_is_helper(child))
coresight_put_ref(child);
}
return -ENODEV;
@@ -748,11 +779,11 @@ static void coresight_drop_device(struct coresight_device *csdev)
int i;
coresight_put_ref(csdev);
- for (i = 0; i < csdev->pdata->nr_outport; i++) {
+ for (i = 0; i < csdev->pdata->nr_outconns; i++) {
struct coresight_device *child;
- child = csdev->pdata->conns[i].child_dev;
- if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
+ child = csdev->pdata->out_conns[i]->dest_dev;
+ if (child && coresight_is_helper(child))
coresight_put_ref(child);
}
}
@@ -790,10 +821,10 @@ static int _coresight_build_path(struct coresight_device *csdev,
}
/* Not a sink - recursively explore each port found on this element */
- for (i = 0; i < csdev->pdata->nr_outport; i++) {
+ for (i = 0; i < csdev->pdata->nr_outconns; i++) {
struct coresight_device *child_dev;
- child_dev = csdev->pdata->conns[i].child_dev;
+ child_dev = csdev->pdata->out_conns[i]->dest_dev;
if (child_dev &&
_coresight_build_path(child_dev, sink, path) == 0) {
found = true;
@@ -959,11 +990,11 @@ coresight_find_sink(struct coresight_device *csdev, int *depth)
* Not a sink we want - or possible child sink may be better.
* recursively explore each port found on this element.
*/
- for (i = 0; i < csdev->pdata->nr_outport; i++) {
+ for (i = 0; i < csdev->pdata->nr_outconns; i++) {
struct coresight_device *child_dev, *sink = NULL;
int child_depth = curr_depth;
- child_dev = csdev->pdata->conns[i].child_dev;
+ child_dev = csdev->pdata->out_conns[i]->dest_dev;
if (child_dev)
sink = coresight_find_sink(child_dev, &child_depth);
@@ -1093,7 +1124,7 @@ int coresight_enable(struct coresight_device *csdev)
* source is already enabled.
*/
if (subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE)
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
goto out;
}
@@ -1114,7 +1145,7 @@ int coresight_enable(struct coresight_device *csdev)
if (ret)
goto err_path;
- ret = coresight_enable_source(csdev, CS_MODE_SYSFS);
+ ret = coresight_enable_source(csdev, CS_MODE_SYSFS, NULL);
if (ret)
goto err_source;
@@ -1171,7 +1202,7 @@ void coresight_disable(struct coresight_device *csdev)
if (ret)
goto out;
- if (!csdev->enable || !coresight_disable_source(csdev))
+ if (!csdev->enable || !coresight_disable_source(csdev, NULL))
goto out;
switch (csdev->subtype.source_subtype) {
@@ -1296,18 +1327,16 @@ static struct device_type coresight_dev_type[] = {
},
{
.name = "helper",
- },
- {
- .name = "ect",
- },
+ }
};
+/* Ensure the enum matches the names and groups */
+static_assert(ARRAY_SIZE(coresight_dev_type) == CORESIGHT_DEV_TYPE_MAX);
static void coresight_device_release(struct device *dev)
{
struct coresight_device *csdev = to_coresight_device(dev);
fwnode_handle_put(csdev->dev.fwnode);
- kfree(csdev->refcnt);
kfree(csdev);
}
@@ -1315,45 +1344,57 @@ static int coresight_orphan_match(struct device *dev, void *data)
{
int i, ret = 0;
bool still_orphan = false;
- struct coresight_device *csdev, *i_csdev;
+ struct coresight_device *dst_csdev = data;
+ struct coresight_device *src_csdev = to_coresight_device(dev);
struct coresight_connection *conn;
-
- csdev = data;
- i_csdev = to_coresight_device(dev);
-
- /* No need to check oneself */
- if (csdev == i_csdev)
- return 0;
+ bool fixup_self = (src_csdev == dst_csdev);
/* Move on to another component if no connection is orphan */
- if (!i_csdev->orphan)
+ if (!src_csdev->orphan)
return 0;
/*
- * Circle throuch all the connection of that component. If we find
- * an orphan connection whose name matches @csdev, link it.
+ * Circle through all the connections of that component. If we find
+ * an orphan connection whose name matches @dst_csdev, link it.
*/
- for (i = 0; i < i_csdev->pdata->nr_outport; i++) {
- conn = &i_csdev->pdata->conns[i];
+ for (i = 0; i < src_csdev->pdata->nr_outconns; i++) {
+ conn = src_csdev->pdata->out_conns[i];
- /* Skip the port if FW doesn't describe it */
- if (!conn->child_fwnode)
+ /* Skip the port if it's already connected. */
+ if (conn->dest_dev)
continue;
- /* We have found at least one orphan connection */
- if (conn->child_dev == NULL) {
- /* Does it match this newly added device? */
- if (conn->child_fwnode == csdev->dev.fwnode) {
- ret = coresight_make_links(i_csdev,
- conn, csdev);
- if (ret)
- return ret;
- } else {
- /* This component still has an orphan */
- still_orphan = true;
- }
+
+ /*
+ * If we are at the "new" device, which triggered this search,
+ * we must find the remote device from the fwnode in the
+ * connection.
+ */
+ if (fixup_self)
+ dst_csdev = coresight_find_csdev_by_fwnode(
+ conn->dest_fwnode);
+
+ /* Does it match this newly added device? */
+ if (dst_csdev && conn->dest_fwnode == dst_csdev->dev.fwnode) {
+ ret = coresight_make_links(src_csdev, conn, dst_csdev);
+ if (ret)
+ return ret;
+
+ /*
+ * Install the device connection. This also indicates that
+ * the links are operational on both ends.
+ */
+ conn->dest_dev = dst_csdev;
+ conn->src_dev = src_csdev;
+
+ ret = coresight_add_in_conn(conn);
+ if (ret)
+ return ret;
+ } else {
+ /* This component still has an orphan */
+ still_orphan = true;
}
}
- i_csdev->orphan = still_orphan;
+ src_csdev->orphan = still_orphan;
/*
* Returning '0' in case we didn't encounter any error,
@@ -1368,91 +1409,43 @@ static int coresight_fixup_orphan_conns(struct coresight_device *csdev)
csdev, coresight_orphan_match);
}
-
-static int coresight_fixup_device_conns(struct coresight_device *csdev)
-{
- int i, ret = 0;
-
- for (i = 0; i < csdev->pdata->nr_outport; i++) {
- struct coresight_connection *conn = &csdev->pdata->conns[i];
-
- if (!conn->child_fwnode)
- continue;
- conn->child_dev =
- coresight_find_csdev_by_fwnode(conn->child_fwnode);
- if (conn->child_dev && conn->child_dev->has_conns_grp) {
- ret = coresight_make_links(csdev, conn,
- conn->child_dev);
- if (ret)
- break;
- } else {
- csdev->orphan = true;
- }
- }
-
- return ret;
-}
-
-static int coresight_remove_match(struct device *dev, void *data)
+/* coresight_remove_conns - Remove other device's references to this device */
+static void coresight_remove_conns(struct coresight_device *csdev)
{
- int i;
- struct coresight_device *csdev, *iterator;
+ int i, j;
struct coresight_connection *conn;
- csdev = data;
- iterator = to_coresight_device(dev);
-
- /* No need to check oneself */
- if (csdev == iterator)
- return 0;
-
/*
- * Circle throuch all the connection of that component. If we find
- * a connection whose name matches @csdev, remove it.
+ * Remove the input connection references from the destination device
+ * for each output connection.
*/
- for (i = 0; i < iterator->pdata->nr_outport; i++) {
- conn = &iterator->pdata->conns[i];
-
- if (conn->child_dev == NULL || conn->child_fwnode == NULL)
+ for (i = 0; i < csdev->pdata->nr_outconns; i++) {
+ conn = csdev->pdata->out_conns[i];
+ if (!conn->dest_dev)
continue;
- if (csdev->dev.fwnode == conn->child_fwnode) {
- iterator->orphan = true;
- coresight_remove_links(iterator, conn);
- /*
- * Drop the reference to the handle for the remote
- * device acquired in parsing the connections from
- * platform data.
- */
- fwnode_handle_put(conn->child_fwnode);
- conn->child_fwnode = NULL;
- /* No need to continue */
- break;
- }
+ for (j = 0; j < conn->dest_dev->pdata->nr_inconns; ++j)
+ if (conn->dest_dev->pdata->in_conns[j] == conn) {
+ conn->dest_dev->pdata->in_conns[j] = NULL;
+ break;
+ }
}
/*
- * Returning '0' ensures that all known component on the
- * bus will be checked.
+ * For all input connections, remove references to this device.
+ * Connection objects are shared so modifying this device's input
+ * connections affects the other device's output connection.
*/
- return 0;
-}
+ for (i = 0; i < csdev->pdata->nr_inconns; ++i) {
+ conn = csdev->pdata->in_conns[i];
+ /* Input conns array is sparse */
+ if (!conn)
+ continue;
-/*
- * coresight_remove_conns - Remove references to this given devices
- * from the connections of other devices.
- */
-static void coresight_remove_conns(struct coresight_device *csdev)
-{
- /*
- * Another device will point to this device only if there is
- * an output port connected to this one. i.e, if the device
- * doesn't have at least one input port, there is no point
- * in searching all the devices.
- */
- if (csdev->pdata->nr_inport)
- bus_for_each_dev(&coresight_bustype, NULL,
- csdev, coresight_remove_match);
+ conn->src_dev->orphan = true;
+ coresight_remove_links(conn->src_dev, conn);
+ conn->dest_dev = NULL;
+ }
}
/**
@@ -1544,24 +1537,27 @@ void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset)
* to the output port of this device.
*/
void coresight_release_platform_data(struct coresight_device *csdev,
+ struct device *dev,
struct coresight_platform_data *pdata)
{
int i;
- struct coresight_connection *conns = pdata->conns;
+ struct coresight_connection **conns = pdata->out_conns;
- for (i = 0; i < pdata->nr_outport; i++) {
+ for (i = 0; i < pdata->nr_outconns; i++) {
/* If we have made the links, remove them now */
- if (csdev && conns[i].child_dev)
- coresight_remove_links(csdev, &conns[i]);
+ if (csdev && conns[i]->dest_dev)
+ coresight_remove_links(csdev, conns[i]);
/*
* Drop the refcount and clear the handle as this device
* is going away
*/
- if (conns[i].child_fwnode) {
- fwnode_handle_put(conns[i].child_fwnode);
- pdata->conns[i].child_fwnode = NULL;
- }
+ fwnode_handle_put(conns[i]->dest_fwnode);
+ conns[i]->dest_fwnode = NULL;
+ devm_kfree(dev, conns[i]);
}
+ devm_kfree(dev, pdata->out_conns);
+ devm_kfree(dev, pdata->in_conns);
+ devm_kfree(dev, pdata);
if (csdev)
coresight_remove_conns_sysfs_group(csdev);
}
@@ -1569,9 +1565,6 @@ void coresight_release_platform_data(struct coresight_device *csdev,
struct coresight_device *coresight_register(struct coresight_desc *desc)
{
int ret;
- int link_subtype;
- int nr_refcnts = 1;
- atomic_t *refcnts = NULL;
struct coresight_device *csdev;
bool registered = false;
@@ -1581,32 +1574,13 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
goto err_out;
}
- if (desc->type == CORESIGHT_DEV_TYPE_LINK ||
- desc->type == CORESIGHT_DEV_TYPE_LINKSINK) {
- link_subtype = desc->subtype.link_subtype;
-
- if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
- nr_refcnts = desc->pdata->nr_inport;
- else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
- nr_refcnts = desc->pdata->nr_outport;
- }
-
- refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
- if (!refcnts) {
- ret = -ENOMEM;
- kfree(csdev);
- goto err_out;
- }
-
- csdev->refcnt = refcnts;
-
csdev->pdata = desc->pdata;
csdev->type = desc->type;
csdev->subtype = desc->subtype;
csdev->ops = desc->ops;
csdev->access = desc->access;
- csdev->orphan = false;
+ csdev->orphan = true;
csdev->dev.type = &coresight_dev_type[desc->type];
csdev->dev.groups = desc->groups;
@@ -1657,8 +1631,6 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
ret = coresight_create_conns_sysfs_group(csdev);
if (!ret)
- ret = coresight_fixup_device_conns(csdev);
- if (!ret)
ret = coresight_fixup_orphan_conns(csdev);
out_unlock:
@@ -1678,7 +1650,7 @@ out_unlock:
err_out:
/* Cleanup the connection information */
- coresight_release_platform_data(NULL, desc->pdata);
+ coresight_release_platform_data(NULL, desc->dev, desc->pdata);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(coresight_register);
@@ -1691,7 +1663,7 @@ void coresight_unregister(struct coresight_device *csdev)
cti_assoc_ops->remove(csdev);
coresight_remove_conns(csdev);
coresight_clear_default_sink(csdev);
- coresight_release_platform_data(csdev, csdev->pdata);
+ coresight_release_platform_data(csdev, csdev->dev.parent, csdev->pdata);
device_unregister(&csdev->dev);
}
EXPORT_SYMBOL_GPL(coresight_unregister);
@@ -1714,6 +1686,69 @@ static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
return -ENOENT;
}
+static bool coresight_compare_type(enum coresight_dev_type type_a,
+ union coresight_dev_subtype subtype_a,
+ enum coresight_dev_type type_b,
+ union coresight_dev_subtype subtype_b)
+{
+ if (type_a != type_b)
+ return false;
+
+ switch (type_a) {
+ case CORESIGHT_DEV_TYPE_SINK:
+ return subtype_a.sink_subtype == subtype_b.sink_subtype;
+ case CORESIGHT_DEV_TYPE_LINK:
+ return subtype_a.link_subtype == subtype_b.link_subtype;
+ case CORESIGHT_DEV_TYPE_LINKSINK:
+ return subtype_a.link_subtype == subtype_b.link_subtype &&
+ subtype_a.sink_subtype == subtype_b.sink_subtype;
+ case CORESIGHT_DEV_TYPE_SOURCE:
+ return subtype_a.source_subtype == subtype_b.source_subtype;
+ case CORESIGHT_DEV_TYPE_HELPER:
+ return subtype_a.helper_subtype == subtype_b.helper_subtype;
+ default:
+ return false;
+ }
+}
+
+struct coresight_device *
+coresight_find_input_type(struct coresight_platform_data *pdata,
+ enum coresight_dev_type type,
+ union coresight_dev_subtype subtype)
+{
+ int i;
+ struct coresight_connection *conn;
+
+ for (i = 0; i < pdata->nr_inconns; ++i) {
+ conn = pdata->in_conns[i];
+ if (conn &&
+ coresight_compare_type(type, subtype, conn->src_dev->type,
+ conn->src_dev->subtype))
+ return conn->src_dev;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(coresight_find_input_type);
+
+struct coresight_device *
+coresight_find_output_type(struct coresight_platform_data *pdata,
+ enum coresight_dev_type type,
+ union coresight_dev_subtype subtype)
+{
+ int i;
+ struct coresight_connection *conn;
+
+ for (i = 0; i < pdata->nr_outconns; ++i) {
+ conn = pdata->out_conns[i];
+ if (conn->dest_dev &&
+ coresight_compare_type(type, subtype, conn->dest_dev->type,
+ conn->dest_dev->subtype))
+ return conn->dest_dev;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(coresight_find_output_type);
+
bool coresight_loses_context_with_cpu(struct device *dev)
{
return fwnode_property_present(dev_fwnode(dev),
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index 277c890a1f1f..7023ff70cc28 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -555,7 +555,10 @@ static void cti_add_assoc_to_csdev(struct coresight_device *csdev)
mutex_lock(&ect_mutex);
/* exit if current is an ECT device.*/
- if ((csdev->type == CORESIGHT_DEV_TYPE_ECT) || list_empty(&ect_net))
+ if ((csdev->type == CORESIGHT_DEV_TYPE_HELPER &&
+ csdev->subtype.helper_subtype ==
+ CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI) ||
+ list_empty(&ect_net))
goto cti_add_done;
/* if we didn't find the csdev previously we used the fwnode name */
@@ -571,8 +574,7 @@ static void cti_add_assoc_to_csdev(struct coresight_device *csdev)
* if we found a matching csdev then update the ECT
* association pointer for the device with this CTI.
*/
- coresight_set_assoc_ectdev_mutex(csdev,
- ect_item->csdev);
+ coresight_add_helper(csdev, ect_item->csdev);
break;
}
}
@@ -582,26 +584,30 @@ cti_add_done:
/*
* Removing the associated devices is easier.
- * A CTI will not have a value for csdev->ect_dev.
*/
static void cti_remove_assoc_from_csdev(struct coresight_device *csdev)
{
struct cti_drvdata *ctidrv;
struct cti_trig_con *tc;
struct cti_device *ctidev;
+ union coresight_dev_subtype cti_subtype = {
+ .helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI
+ };
+ struct coresight_device *cti_csdev = coresight_find_output_type(
+ csdev->pdata, CORESIGHT_DEV_TYPE_HELPER, cti_subtype);
+
+ if (!cti_csdev)
+ return;
mutex_lock(&ect_mutex);
- if (csdev->ect_dev) {
- ctidrv = csdev_to_cti_drvdata(csdev->ect_dev);
- ctidev = &ctidrv->ctidev;
- list_for_each_entry(tc, &ctidev->trig_cons, node) {
- if (tc->con_dev == csdev) {
- cti_remove_sysfs_link(ctidrv, tc);
- tc->con_dev = NULL;
- break;
- }
+ ctidrv = csdev_to_cti_drvdata(cti_csdev);
+ ctidev = &ctidrv->ctidev;
+ list_for_each_entry(tc, &ctidev->trig_cons, node) {
+ if (tc->con_dev == csdev) {
+ cti_remove_sysfs_link(ctidrv, tc);
+ tc->con_dev = NULL;
+ break;
}
- csdev->ect_dev = NULL;
}
mutex_unlock(&ect_mutex);
}
@@ -630,8 +636,8 @@ static void cti_update_conn_xrefs(struct cti_drvdata *drvdata)
/* if we can set the sysfs link */
if (cti_add_sysfs_link(drvdata, tc))
/* set the CTI/csdev association */
- coresight_set_assoc_ectdev_mutex(tc->con_dev,
- drvdata->csdev);
+ coresight_add_helper(tc->con_dev,
+ drvdata->csdev);
else
/* otherwise remove reference from CTI */
tc->con_dev = NULL;
@@ -646,8 +652,6 @@ static void cti_remove_conn_xrefs(struct cti_drvdata *drvdata)
list_for_each_entry(tc, &ctidev->trig_cons, node) {
if (tc->con_dev) {
- coresight_set_assoc_ectdev_mutex(tc->con_dev,
- NULL);
cti_remove_sysfs_link(drvdata, tc);
tc->con_dev = NULL;
}
@@ -795,27 +799,27 @@ static void cti_pm_release(struct cti_drvdata *drvdata)
}
/** cti ect operations **/
-int cti_enable(struct coresight_device *csdev)
+int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data)
{
struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
return cti_enable_hw(drvdata);
}
-int cti_disable(struct coresight_device *csdev)
+int cti_disable(struct coresight_device *csdev, void *data)
{
struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
return cti_disable_hw(drvdata);
}
-static const struct coresight_ops_ect cti_ops_ect = {
+static const struct coresight_ops_helper cti_ops_ect = {
.enable = cti_enable,
.disable = cti_disable,
};
static const struct coresight_ops cti_ops = {
- .ect_ops = &cti_ops_ect,
+ .helper_ops = &cti_ops_ect,
};
/*
@@ -922,8 +926,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
/* set up coresight component description */
cti_desc.pdata = pdata;
- cti_desc.type = CORESIGHT_DEV_TYPE_ECT;
- cti_desc.subtype.ect_subtype = CORESIGHT_DEV_SUBTYPE_ECT_CTI;
+ cti_desc.type = CORESIGHT_DEV_TYPE_HELPER;
+ cti_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI;
cti_desc.ops = &cti_ops;
cti_desc.groups = drvdata->ctidev.con_groups;
cti_desc.dev = dev;
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index e528cff9d4e2..d25dd2737b49 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -112,11 +112,11 @@ static ssize_t enable_store(struct device *dev,
ret = pm_runtime_resume_and_get(dev->parent);
if (ret)
return ret;
- ret = cti_enable(drvdata->csdev);
+ ret = cti_enable(drvdata->csdev, CS_MODE_SYSFS, NULL);
if (ret)
pm_runtime_put(dev->parent);
} else {
- ret = cti_disable(drvdata->csdev);
+ ret = cti_disable(drvdata->csdev, NULL);
if (!ret)
pm_runtime_put(dev->parent);
}
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index 8b106b13a244..cb9ee616d01f 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -215,8 +215,8 @@ int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
const char *assoc_dev_name);
struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
int out_sigs);
-int cti_enable(struct coresight_device *csdev);
-int cti_disable(struct coresight_device *csdev);
+int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data);
+int cti_disable(struct coresight_device *csdev, void *data);
void cti_write_all_hw_regs(struct cti_drvdata *drvdata);
void cti_write_intack(struct device *dev, u32 ackval);
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c
new file mode 100644
index 000000000000..8035120b70b3
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-dummy.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/coresight.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include "coresight-priv.h"
+
+struct dummy_drvdata {
+ struct device *dev;
+ struct coresight_device *csdev;
+};
+
+DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source");
+DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink");
+
+static int dummy_source_enable(struct coresight_device *csdev,
+ struct perf_event *event, enum cs_mode mode)
+{
+ dev_dbg(csdev->dev.parent, "Dummy source enabled\n");
+
+ return 0;
+}
+
+static void dummy_source_disable(struct coresight_device *csdev,
+ struct perf_event *event)
+{
+ dev_dbg(csdev->dev.parent, "Dummy source disabled\n");
+}
+
+static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode,
+ void *data)
+{
+ dev_dbg(csdev->dev.parent, "Dummy sink enabled\n");
+
+ return 0;
+}
+
+static int dummy_sink_disable(struct coresight_device *csdev)
+{
+ dev_dbg(csdev->dev.parent, "Dummy sink disabled\n");
+
+ return 0;
+}
+
+static const struct coresight_ops_source dummy_source_ops = {
+ .enable = dummy_source_enable,
+ .disable = dummy_source_disable,
+};
+
+static const struct coresight_ops dummy_source_cs_ops = {
+ .source_ops = &dummy_source_ops,
+};
+
+static const struct coresight_ops_sink dummy_sink_ops = {
+ .enable = dummy_sink_enable,
+ .disable = dummy_sink_disable,
+};
+
+static const struct coresight_ops dummy_sink_cs_ops = {
+ .sink_ops = &dummy_sink_ops,
+};
+
+static int dummy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct coresight_platform_data *pdata;
+ struct dummy_drvdata *drvdata;
+ struct coresight_desc desc = { 0 };
+
+ if (of_device_is_compatible(node, "arm,coresight-dummy-source")) {
+
+ desc.name = coresight_alloc_device_name(&source_devs, dev);
+ if (!desc.name)
+ return -ENOMEM;
+
+ desc.type = CORESIGHT_DEV_TYPE_SOURCE;
+ desc.subtype.source_subtype =
+ CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS;
+ desc.ops = &dummy_source_cs_ops;
+ } else if (of_device_is_compatible(node, "arm,coresight-dummy-sink")) {
+ desc.name = coresight_alloc_device_name(&sink_devs, dev);
+ if (!desc.name)
+ return -ENOMEM;
+
+ desc.type = CORESIGHT_DEV_TYPE_SINK;
+ desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_DUMMY;
+ desc.ops = &dummy_sink_cs_ops;
+ } else {
+ dev_err(dev, "Device type not set\n");
+ return -EINVAL;
+ }
+
+ pdata = coresight_get_platform_data(dev);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
+
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
+ desc.pdata = pdev->dev.platform_data;
+ desc.dev = &pdev->dev;
+ drvdata->csdev = coresight_register(&desc);
+ if (IS_ERR(drvdata->csdev))
+ return PTR_ERR(drvdata->csdev);
+
+ pm_runtime_enable(dev);
+ dev_dbg(dev, "Dummy device initialized\n");
+
+ return 0;
+}
+
+static int dummy_remove(struct platform_device *pdev)
+{
+ struct dummy_drvdata *drvdata = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+
+ pm_runtime_disable(dev);
+ coresight_unregister(drvdata->csdev);
+ return 0;
+}
+
+static const struct of_device_id dummy_match[] = {
+ {.compatible = "arm,coresight-dummy-source"},
+ {.compatible = "arm,coresight-dummy-sink"},
+ {},
+};
+
+static struct platform_driver dummy_driver = {
+ .probe = dummy_probe,
+ .remove = dummy_remove,
+ .driver = {
+ .name = "coresight-dummy",
+ .of_match_table = dummy_match,
+ },
+};
+
+static int __init dummy_init(void)
+{
+ return platform_driver_register(&dummy_driver);
+}
+module_init(dummy_init);
+
+static void __exit dummy_exit(void)
+{
+ platform_driver_unregister(&dummy_driver);
+}
+module_exit(dummy_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CoreSight dummy driver");
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 8aa6e4f83e42..fa80039e0821 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -163,7 +163,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev)
drvdata->mode = CS_MODE_SYSFS;
}
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
return ret;
@@ -199,7 +199,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
* use for this session.
*/
if (drvdata->pid == pid) {
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
goto out;
}
@@ -217,7 +217,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
/* Associate with monitored process. */
drvdata->pid = pid;
drvdata->mode = CS_MODE_PERF;
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
}
out:
@@ -225,7 +225,8 @@ out:
return ret;
}
-static int etb_enable(struct coresight_device *csdev, u32 mode, void *data)
+static int etb_enable(struct coresight_device *csdev, enum cs_mode mode,
+ void *data)
{
int ret;
@@ -355,7 +356,7 @@ static int etb_disable(struct coresight_device *csdev)
spin_lock_irqsave(&drvdata->spinlock, flags);
- if (atomic_dec_return(csdev->refcnt)) {
+ if (atomic_dec_return(&csdev->refcnt)) {
spin_unlock_irqrestore(&drvdata->spinlock, flags);
return -EBUSY;
}
@@ -446,7 +447,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
spin_lock_irqsave(&drvdata->spinlock, flags);
/* Don't do anything if another tracer is using this sink */
- if (atomic_read(csdev->refcnt) != 1)
+ if (atomic_read(&csdev->refcnt) != 1)
goto out;
__etb_disable_hw(drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 89e8ed214ea4..5ca6278baff4 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -493,7 +493,7 @@ static void etm_event_start(struct perf_event *event, int flags)
goto fail_end_stop;
/* Finally enable the tracer */
- if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF))
+ if (coresight_enable_source(csdev, CS_MODE_PERF, event))
goto fail_disable_path;
/*
@@ -587,7 +587,7 @@ static void etm_event_stop(struct perf_event *event, int mode)
return;
/* stop tracer */
- source_ops(csdev)->disable(csdev, event);
+ coresight_disable_source(csdev, event);
/* tell the core */
event->hw.state = PERF_HES_STOPPED;
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
index afc57195ee52..116a91d90ac2 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
@@ -552,8 +552,8 @@ unlock_enable_sysfs:
return ret;
}
-static int etm_enable(struct coresight_device *csdev,
- struct perf_event *event, u32 mode)
+static int etm_enable(struct coresight_device *csdev, struct perf_event *event,
+ enum cs_mode mode)
{
int ret;
u32 val;
@@ -671,7 +671,7 @@ static void etm_disable_sysfs(struct coresight_device *csdev)
static void etm_disable(struct coresight_device *csdev,
struct perf_event *event)
{
- u32 mode;
+ enum cs_mode mode;
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
/*
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 4c15fae534f3..7e307022303a 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -822,8 +822,8 @@ unlock_sysfs_enable:
return ret;
}
-static int etm4_enable(struct coresight_device *csdev,
- struct perf_event *event, u32 mode)
+static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
+ enum cs_mode mode)
{
int ret;
u32 val;
@@ -989,7 +989,7 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
static void etm4_disable(struct coresight_device *csdev,
struct perf_event *event)
{
- u32 mode;
+ enum cs_mode mode;
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
/*
@@ -2190,7 +2190,7 @@ static void clear_etmdrvdata(void *info)
per_cpu(delayed_probe, cpu) = NULL;
}
-static int __exit etm4_remove_dev(struct etmv4_drvdata *drvdata)
+static void __exit etm4_remove_dev(struct etmv4_drvdata *drvdata)
{
bool had_delayed_probe;
/*
@@ -2217,8 +2217,6 @@ static int __exit etm4_remove_dev(struct etmv4_drvdata *drvdata)
cscfg_unregister_csdev(drvdata->csdev);
coresight_unregister(drvdata->csdev);
}
-
- return 0;
}
static void __exit etm4_remove_amba(struct amba_device *adev)
@@ -2231,13 +2229,12 @@ static void __exit etm4_remove_amba(struct amba_device *adev)
static int __exit etm4_remove_platform_dev(struct platform_device *pdev)
{
- int ret = 0;
struct etmv4_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
if (drvdata)
- ret = etm4_remove_dev(drvdata);
+ etm4_remove_dev(drvdata);
pm_runtime_disable(&pdev->dev);
- return ret;
+ return 0;
}
static const struct amba_id etm4_ids[] = {
@@ -2260,6 +2257,11 @@ static const struct amba_id etm4_ids[] = {
CS_AMBA_UCI_ID(0x000cc0af, uci_id_etm4),/* Marvell ThunderX2 */
CS_AMBA_UCI_ID(0x000b6d01, uci_id_etm4),/* HiSilicon-Hip08 */
CS_AMBA_UCI_ID(0x000b6d02, uci_id_etm4),/* HiSilicon-Hip09 */
+ /*
+ * Match all PIDs with ETM4 DEVARCH. No need for adding any of the new
+ * CPUs to the list here.
+ */
+ CS_AMBA_MATCH_ALL_UCI(uci_id_etm4),
{},
};
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index 5e62aa40ecd0..a9f19629f3f8 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -2411,7 +2411,6 @@ static ssize_t trctraceid_show(struct device *dev,
return sysfs_emit(buf, "0x%x\n", trace_id);
}
-static DEVICE_ATTR_RO(trctraceid);
struct etmv4_reg {
struct coresight_device *csdev;
@@ -2528,13 +2527,23 @@ coresight_etm4x_attr_reg_implemented(struct kobject *kobj,
return 0;
}
-#define coresight_etm4x_reg(name, offset) \
- &((struct dev_ext_attribute[]) { \
- { \
- __ATTR(name, 0444, coresight_etm4x_reg_show, NULL), \
- (void *)(unsigned long)offset \
- } \
- })[0].attr.attr
+/*
+ * Macro to set an RO ext attribute with offset and show function.
+ * Offset is used in mgmt group to ensure only correct registers for
+ * the ETM / ETE variant are visible.
+ */
+#define coresight_etm4x_reg_showfn(name, offset, showfn) ( \
+ &((struct dev_ext_attribute[]) { \
+ { \
+ __ATTR(name, 0444, showfn, NULL), \
+ (void *)(unsigned long)offset \
+ } \
+ })[0].attr.attr \
+ )
+
+/* macro using the default coresight_etm4x_reg_show function */
+#define coresight_etm4x_reg(name, offset) \
+ coresight_etm4x_reg_showfn(name, offset, coresight_etm4x_reg_show)
static struct attribute *coresight_etmv4_mgmt_attrs[] = {
coresight_etm4x_reg(trcpdcr, TRCPDCR),
@@ -2549,7 +2558,7 @@ static struct attribute *coresight_etmv4_mgmt_attrs[] = {
coresight_etm4x_reg(trcpidr3, TRCPIDR3),
coresight_etm4x_reg(trcoslsr, TRCOSLSR),
coresight_etm4x_reg(trcconfig, TRCCONFIGR),
- &dev_attr_trctraceid.attr,
+ coresight_etm4x_reg_showfn(trctraceid, TRCTRACEIDR, trctraceid_show),
coresight_etm4x_reg(trcdevarch, TRCDEVARCH),
NULL,
};
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index b363dd6bc510..b8e150e45b27 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -74,8 +74,9 @@ done:
return rc;
}
-static int funnel_enable(struct coresight_device *csdev, int inport,
- int outport)
+static int funnel_enable(struct coresight_device *csdev,
+ struct coresight_connection *in,
+ struct coresight_connection *out)
{
int rc = 0;
struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -83,18 +84,19 @@ static int funnel_enable(struct coresight_device *csdev, int inport,
bool first_enable = false;
spin_lock_irqsave(&drvdata->spinlock, flags);
- if (atomic_read(&csdev->refcnt[inport]) == 0) {
+ if (atomic_read(&in->dest_refcnt) == 0) {
if (drvdata->base)
- rc = dynamic_funnel_enable_hw(drvdata, inport);
+ rc = dynamic_funnel_enable_hw(drvdata, in->dest_port);
if (!rc)
first_enable = true;
}
if (!rc)
- atomic_inc(&csdev->refcnt[inport]);
+ atomic_inc(&in->dest_refcnt);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (first_enable)
- dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n", inport);
+ dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n",
+ in->dest_port);
return rc;
}
@@ -117,23 +119,25 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata,
CS_LOCK(drvdata->base);
}
-static void funnel_disable(struct coresight_device *csdev, int inport,
- int outport)
+static void funnel_disable(struct coresight_device *csdev,
+ struct coresight_connection *in,
+ struct coresight_connection *out)
{
struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
unsigned long flags;
bool last_disable = false;
spin_lock_irqsave(&drvdata->spinlock, flags);
- if (atomic_dec_return(&csdev->refcnt[inport]) == 0) {
+ if (atomic_dec_return(&in->dest_refcnt) == 0) {
if (drvdata->base)
- dynamic_funnel_disable_hw(drvdata, inport);
+ dynamic_funnel_disable_hw(drvdata, in->dest_port);
last_disable = true;
}
spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (last_disable)
- dev_dbg(&csdev->dev, "FUNNEL inport %d disabled\n", inport);
+ dev_dbg(&csdev->dev, "FUNNEL inport %d disabled\n",
+ in->dest_port);
}
static const struct coresight_ops_link funnel_link_ops = {
diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
index 475899714104..3e2e135cb8f6 100644
--- a/drivers/hwtracing/coresight/coresight-platform.c
+++ b/drivers/hwtracing/coresight/coresight-platform.c
@@ -19,22 +19,85 @@
#include <asm/smp_plat.h>
#include "coresight-priv.h"
+
/*
- * coresight_alloc_conns: Allocate connections record for each output
- * port from the device.
+ * Add an entry to the connection list and assign @conn's contents to it.
+ *
+ * If the output port is already assigned on this device, return -EINVAL
*/
-static int coresight_alloc_conns(struct device *dev,
- struct coresight_platform_data *pdata)
+struct coresight_connection *
+coresight_add_out_conn(struct device *dev,
+ struct coresight_platform_data *pdata,
+ const struct coresight_connection *new_conn)
{
- if (pdata->nr_outport) {
- pdata->conns = devm_kcalloc(dev, pdata->nr_outport,
- sizeof(*pdata->conns), GFP_KERNEL);
- if (!pdata->conns)
- return -ENOMEM;
+ int i;
+ struct coresight_connection *conn;
+
+ /*
+ * Warn on any existing duplicate output port.
+ */
+ for (i = 0; i < pdata->nr_outconns; ++i) {
+ conn = pdata->out_conns[i];
+ /* Output == -1 means ignore the port for example for helpers */
+ if (conn->src_port != -1 &&
+ conn->src_port == new_conn->src_port) {
+ dev_warn(dev, "Duplicate output port %d\n",
+ conn->src_port);
+ return ERR_PTR(-EINVAL);
+ }
}
+ pdata->nr_outconns++;
+ pdata->out_conns =
+ devm_krealloc_array(dev, pdata->out_conns, pdata->nr_outconns,
+ sizeof(*pdata->out_conns), GFP_KERNEL);
+ if (!pdata->out_conns)
+ return ERR_PTR(-ENOMEM);
+
+ conn = devm_kmalloc(dev, sizeof(struct coresight_connection),
+ GFP_KERNEL);
+ if (!conn)
+ return ERR_PTR(-ENOMEM);
+
+ /*
+ * Copy the new connection into the allocation, save the pointer to the
+ * end of the connection array and also return it in case it needs to be
+ * used right away.
+ */
+ *conn = *new_conn;
+ pdata->out_conns[pdata->nr_outconns - 1] = conn;
+ return conn;
+}
+EXPORT_SYMBOL_GPL(coresight_add_out_conn);
+
+/*
+ * Add an input connection reference to @out_conn in the target's in_conns array
+ *
+ * @out_conn: Existing output connection to store as an input on the
+ * connection's remote device.
+ */
+int coresight_add_in_conn(struct coresight_connection *out_conn)
+{
+ int i;
+ struct device *dev = out_conn->dest_dev->dev.parent;
+ struct coresight_platform_data *pdata = out_conn->dest_dev->pdata;
+
+ for (i = 0; i < pdata->nr_inconns; ++i)
+ if (!pdata->in_conns[i]) {
+ pdata->in_conns[i] = out_conn;
+ return 0;
+ }
+
+ pdata->nr_inconns++;
+ pdata->in_conns =
+ devm_krealloc_array(dev, pdata->in_conns, pdata->nr_inconns,
+ sizeof(*pdata->in_conns), GFP_KERNEL);
+ if (!pdata->in_conns)
+ return -ENOMEM;
+ pdata->in_conns[pdata->nr_inconns - 1] = out_conn;
return 0;
}
+EXPORT_SYMBOL_GPL(coresight_add_in_conn);
static struct device *
coresight_find_device_by_fwnode(struct fwnode_handle *fwnode)
@@ -83,41 +146,6 @@ static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep)
return of_property_read_bool(ep, "slave-mode");
}
-static void of_coresight_get_ports_legacy(const struct device_node *node,
- int *nr_inport, int *nr_outport)
-{
- struct device_node *ep = NULL;
- struct of_endpoint endpoint;
- int in = 0, out = 0;
-
- /*
- * Avoid warnings in of_graph_get_next_endpoint()
- * if the device doesn't have any graph connections
- */
- if (!of_graph_is_present(node))
- return;
- do {
- ep = of_graph_get_next_endpoint(node, ep);
- if (!ep)
- break;
-
- if (of_graph_parse_endpoint(ep, &endpoint))
- continue;
-
- if (of_coresight_legacy_ep_is_input(ep)) {
- in = (endpoint.port + 1 > in) ?
- endpoint.port + 1 : in;
- } else {
- out = (endpoint.port + 1) > out ?
- endpoint.port + 1 : out;
- }
-
- } while (ep);
-
- *nr_inport = in;
- *nr_outport = out;
-}
-
static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
{
struct device_node *parent = of_graph_get_port_parent(ep);
@@ -134,58 +162,11 @@ static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
}
static inline struct device_node *
-of_coresight_get_input_ports_node(const struct device_node *node)
-{
- return of_get_child_by_name(node, "in-ports");
-}
-
-static inline struct device_node *
of_coresight_get_output_ports_node(const struct device_node *node)
{
return of_get_child_by_name(node, "out-ports");
}
-static inline int
-of_coresight_count_ports(struct device_node *port_parent)
-{
- int i = 0;
- struct device_node *ep = NULL;
- struct of_endpoint endpoint;
-
- while ((ep = of_graph_get_next_endpoint(port_parent, ep))) {
- /* Defer error handling to parsing */
- if (of_graph_parse_endpoint(ep, &endpoint))
- continue;
- if (endpoint.port + 1 > i)
- i = endpoint.port + 1;
- }
-
- return i;
-}
-
-static void of_coresight_get_ports(const struct device_node *node,
- int *nr_inport, int *nr_outport)
-{
- struct device_node *input_ports = NULL, *output_ports = NULL;
-
- input_ports = of_coresight_get_input_ports_node(node);
- output_ports = of_coresight_get_output_ports_node(node);
-
- if (input_ports || output_ports) {
- if (input_ports) {
- *nr_inport = of_coresight_count_ports(input_ports);
- of_node_put(input_ports);
- }
- if (output_ports) {
- *nr_outport = of_coresight_count_ports(output_ports);
- of_node_put(output_ports);
- }
- } else {
- /* Fall back to legacy DT bindings parsing */
- of_coresight_get_ports_legacy(node, nr_inport, nr_outport);
- }
-}
-
static int of_coresight_get_cpu(struct device *dev)
{
int cpu;
@@ -206,7 +187,7 @@ static int of_coresight_get_cpu(struct device *dev)
/*
* of_coresight_parse_endpoint : Parse the given output endpoint @ep
- * and fill the connection information in @conn
+ * and fill the connection information in @pdata->out_conns
*
* Parses the local port, remote device name and the remote port.
*
@@ -224,7 +205,8 @@ static int of_coresight_parse_endpoint(struct device *dev,
struct device_node *rep = NULL;
struct device *rdev = NULL;
struct fwnode_handle *rdev_fwnode;
- struct coresight_connection *conn;
+ struct coresight_connection conn = {};
+ struct coresight_connection *new_conn;
do {
/* Parse the local port details */
@@ -251,14 +233,7 @@ static int of_coresight_parse_endpoint(struct device *dev,
break;
}
- conn = &pdata->conns[endpoint.port];
- if (conn->child_fwnode) {
- dev_warn(dev, "Duplicate output port %d\n",
- endpoint.port);
- ret = -EINVAL;
- break;
- }
- conn->outport = endpoint.port;
+ conn.src_port = endpoint.port;
/*
* Hold the refcount to the target device. This could be
* released via:
@@ -267,8 +242,14 @@ static int of_coresight_parse_endpoint(struct device *dev,
* 2) While removing the target device via
* coresight_remove_match()
*/
- conn->child_fwnode = fwnode_handle_get(rdev_fwnode);
- conn->child_port = rendpoint.port;
+ conn.dest_fwnode = fwnode_handle_get(rdev_fwnode);
+ conn.dest_port = rendpoint.port;
+
+ new_conn = coresight_add_out_conn(dev, pdata, &conn);
+ if (IS_ERR_VALUE(new_conn)) {
+ fwnode_handle_put(conn.dest_fwnode);
+ return PTR_ERR(new_conn);
+ }
/* Connection record updated */
} while (0);
@@ -288,17 +269,6 @@ static int of_get_coresight_platform_data(struct device *dev,
bool legacy_binding = false;
struct device_node *node = dev->of_node;
- /* Get the number of input and output port for this component */
- of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport);
-
- /* If there are no output connections, we are done */
- if (!pdata->nr_outport)
- return 0;
-
- ret = coresight_alloc_conns(dev, pdata);
- if (ret)
- return ret;
-
parent = of_coresight_get_output_ports_node(node);
/*
* If the DT uses obsoleted bindings, the ports are listed
@@ -306,6 +276,12 @@ static int of_get_coresight_platform_data(struct device *dev,
* ports.
*/
if (!parent) {
+ /*
+ * Avoid warnings in of_graph_get_next_endpoint()
+ * if the device doesn't have any graph connections
+ */
+ if (!of_graph_is_present(node))
+ return 0;
legacy_binding = true;
parent = node;
dev_warn_once(dev, "Uses obsolete Coresight DT bindings\n");
@@ -649,8 +625,8 @@ static int acpi_coresight_parse_link(struct acpi_device *adev,
dir = fields[3].integer.value;
if (dir == ACPI_CORESIGHT_LINK_MASTER) {
- conn->outport = fields[0].integer.value;
- conn->child_port = fields[1].integer.value;
+ conn->src_port = fields[0].integer.value;
+ conn->dest_port = fields[1].integer.value;
rdev = coresight_find_device_by_fwnode(&r_adev->fwnode);
if (!rdev)
return -EPROBE_DEFER;
@@ -662,14 +638,14 @@ static int acpi_coresight_parse_link(struct acpi_device *adev,
* 2) While removing the target device via
* coresight_remove_match().
*/
- conn->child_fwnode = fwnode_handle_get(&r_adev->fwnode);
+ conn->dest_fwnode = fwnode_handle_get(&r_adev->fwnode);
} else if (dir == ACPI_CORESIGHT_LINK_SLAVE) {
/*
* We are only interested in the port number
* for the input ports at this component.
* Store the port number in child_port.
*/
- conn->child_port = fields[0].integer.value;
+ conn->dest_port = fields[0].integer.value;
} else {
/* Invalid direction */
return -EINVAL;
@@ -683,14 +659,15 @@ static int acpi_coresight_parse_link(struct acpi_device *adev,
* connection information and populate the supplied coresight_platform_data
* instance.
*/
-static int acpi_coresight_parse_graph(struct acpi_device *adev,
+static int acpi_coresight_parse_graph(struct device *dev,
+ struct acpi_device *adev,
struct coresight_platform_data *pdata)
{
- int rc, i, nlinks;
+ int i, nlinks;
const union acpi_object *graph;
- struct coresight_connection *conns, *ptr;
+ struct coresight_connection conn, zero_conn = {};
+ struct coresight_connection *new_conn;
- pdata->nr_inport = pdata->nr_outport = 0;
graph = acpi_get_coresight_graph(adev);
if (!graph)
return -ENOENT;
@@ -699,56 +676,22 @@ static int acpi_coresight_parse_graph(struct acpi_device *adev,
if (!nlinks)
return 0;
- /*
- * To avoid scanning the table twice (once for finding the number of
- * output links and then later for parsing the output links),
- * cache the links information in one go and then later copy
- * it to the pdata.
- */
- conns = devm_kcalloc(&adev->dev, nlinks, sizeof(*conns), GFP_KERNEL);
- if (!conns)
- return -ENOMEM;
- ptr = conns;
for (i = 0; i < nlinks; i++) {
const union acpi_object *link = &graph->package.elements[3 + i];
int dir;
- dir = acpi_coresight_parse_link(adev, link, ptr);
+ conn = zero_conn;
+ dir = acpi_coresight_parse_link(adev, link, &conn);
if (dir < 0)
return dir;
if (dir == ACPI_CORESIGHT_LINK_MASTER) {
- if (ptr->outport >= pdata->nr_outport)
- pdata->nr_outport = ptr->outport + 1;
- ptr++;
- } else {
- WARN_ON(pdata->nr_inport == ptr->child_port + 1);
- /*
- * We do not track input port connections for a device.
- * However we need the highest port number described,
- * which can be recorded now and reuse this connection
- * record for an output connection. Hence, do not move
- * the ptr for input connections
- */
- if (ptr->child_port >= pdata->nr_inport)
- pdata->nr_inport = ptr->child_port + 1;
+ new_conn = coresight_add_out_conn(dev, pdata, &conn);
+ if (IS_ERR(new_conn))
+ return PTR_ERR(new_conn);
}
}
- rc = coresight_alloc_conns(&adev->dev, pdata);
- if (rc)
- return rc;
-
- /* Copy the connection information to the final location */
- for (i = 0; conns + i < ptr; i++) {
- int port = conns[i].outport;
-
- /* Duplicate output port */
- WARN_ON(pdata->conns[port].child_fwnode);
- pdata->conns[port] = conns[i];
- }
-
- devm_kfree(&adev->dev, conns);
return 0;
}
@@ -809,7 +752,7 @@ acpi_get_coresight_platform_data(struct device *dev,
if (!adev)
return -EINVAL;
- return acpi_coresight_parse_graph(adev, pdata);
+ return acpi_coresight_parse_graph(dev, adev, pdata);
}
#else
@@ -863,7 +806,7 @@ coresight_get_platform_data(struct device *dev)
error:
if (!IS_ERR_OR_NULL(pdata))
/* Cleanup the connection information */
- coresight_release_platform_data(NULL, pdata);
+ coresight_release_platform_data(NULL, dev, pdata);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(coresight_get_platform_data);
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 595ce5862056..767076e07970 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -82,12 +82,6 @@ enum etm_addr_type {
ETM_ADDR_TYPE_STOP,
};
-enum cs_mode {
- CS_MODE_DISABLED,
- CS_MODE_SYSFS,
- CS_MODE_PERF,
-};
-
/**
* struct cs_buffer - keep track of a recording session' specifics
* @cur: index of the current buffer
@@ -133,7 +127,8 @@ static inline void CS_UNLOCK(void __iomem *addr)
}
void coresight_disable_path(struct list_head *path);
-int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data);
+int coresight_enable_path(struct list_head *path, enum cs_mode mode,
+ void *sink_data);
struct coresight_device *coresight_get_sink(struct list_head *path);
struct coresight_device *
coresight_get_enabled_sink(struct coresight_device *source);
@@ -193,12 +188,27 @@ extern void coresight_remove_cti_ops(void);
}
/* coresight AMBA ID, full UCI structure: id table entry. */
-#define CS_AMBA_UCI_ID(pid, uci_ptr) \
+#define __CS_AMBA_UCI_ID(pid, m, uci_ptr) \
{ \
.id = pid, \
- .mask = 0x000fffff, \
+ .mask = m, \
.data = (void *)uci_ptr \
}
+#define CS_AMBA_UCI_ID(pid, uci) __CS_AMBA_UCI_ID(pid, 0x000fffff, uci)
+/*
+ * PIDR2[JEDEC], BIT(3) must be 1 (Read As One) to indicate that rest of the
+ * PIDR1, PIDR2 DES_* fields follow JEDEC encoding for the designer. Use that
+ * as a match value for blanket matching all devices in the given CoreSight
+ * device type and architecture.
+ */
+#define PIDR2_JEDEC BIT(3)
+#define PID_PIDR2_JEDEC (PIDR2_JEDEC << 16)
+/*
+ * Match all PIDs in a given CoreSight device type and architecture, defined
+ * by the uci.
+ */
+#define CS_AMBA_MATCH_ALL_UCI(uci) \
+ __CS_AMBA_UCI_ID(PID_PIDR2_JEDEC, PID_PIDR2_JEDEC, uci)
/* extract the data value from a UCI structure given amba_id pointer. */
static inline void *coresight_get_uci_data(const struct amba_id *id)
@@ -212,13 +222,17 @@ static inline void *coresight_get_uci_data(const struct amba_id *id)
}
void coresight_release_platform_data(struct coresight_device *csdev,
+ struct device *dev,
struct coresight_platform_data *pdata);
struct coresight_device *
coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode);
-void coresight_set_assoc_ectdev_mutex(struct coresight_device *csdev,
- struct coresight_device *ect_csdev);
+void coresight_add_helper(struct coresight_device *csdev,
+ struct coresight_device *helper);
void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
struct coresight_device *coresight_get_percpu_sink(int cpu);
+int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode,
+ void *data);
+bool coresight_disable_source(struct coresight_device *csdev, void *data);
#endif
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index 4dd50546d7e4..b6be73034996 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -114,8 +114,9 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata,
return rc;
}
-static int replicator_enable(struct coresight_device *csdev, int inport,
- int outport)
+static int replicator_enable(struct coresight_device *csdev,
+ struct coresight_connection *in,
+ struct coresight_connection *out)
{
int rc = 0;
struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -123,15 +124,15 @@ static int replicator_enable(struct coresight_device *csdev, int inport,
bool first_enable = false;
spin_lock_irqsave(&drvdata->spinlock, flags);
- if (atomic_read(&csdev->refcnt[outport]) == 0) {
+ if (atomic_read(&out->src_refcnt) == 0) {
if (drvdata->base)
- rc = dynamic_replicator_enable(drvdata, inport,
- outport);
+ rc = dynamic_replicator_enable(drvdata, in->dest_port,
+ out->src_port);
if (!rc)
first_enable = true;
}
if (!rc)
- atomic_inc(&csdev->refcnt[outport]);
+ atomic_inc(&out->src_refcnt);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (first_enable)
@@ -168,17 +169,19 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata,
CS_LOCK(drvdata->base);
}
-static void replicator_disable(struct coresight_device *csdev, int inport,
- int outport)
+static void replicator_disable(struct coresight_device *csdev,
+ struct coresight_connection *in,
+ struct coresight_connection *out)
{
struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
unsigned long flags;
bool last_disable = false;
spin_lock_irqsave(&drvdata->spinlock, flags);
- if (atomic_dec_return(&csdev->refcnt[outport]) == 0) {
+ if (atomic_dec_return(&out->src_refcnt) == 0) {
if (drvdata->base)
- dynamic_replicator_disable(drvdata, inport, outport);
+ dynamic_replicator_disable(drvdata, in->dest_port,
+ out->src_port);
last_disable = true;
}
spin_unlock_irqrestore(&drvdata->spinlock, flags);
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index 66a614c5492c..a1c27c901ad1 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -119,7 +119,7 @@ DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm");
* @spinlock: only one at a time pls.
* @chs: the channels accociated to this STM.
* @stm: structure associated to the generic STM interface.
- * @mode: this tracer's mode, i.e sysFS, or disabled.
+ * @mode: this tracer's mode (enum cs_mode), i.e sysFS, or disabled.
* @traceid: value of the current ID for this component.
* @write_bytes: Maximus bytes this STM can write at a time.
* @stmsper: settings for register STMSPER.
@@ -192,8 +192,8 @@ static void stm_enable_hw(struct stm_drvdata *drvdata)
CS_LOCK(drvdata->base);
}
-static int stm_enable(struct coresight_device *csdev,
- struct perf_event *event, u32 mode)
+static int stm_enable(struct coresight_device *csdev, struct perf_event *event,
+ enum cs_mode mode)
{
u32 val;
struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c
index 34d2a2d31d00..dd78e9fcfc4d 100644
--- a/drivers/hwtracing/coresight/coresight-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-sysfs.c
@@ -148,13 +148,17 @@ int coresight_make_links(struct coresight_device *orig,
char *outs = NULL, *ins = NULL;
struct coresight_sysfs_link *link = NULL;
+ /* Helper devices aren't shown in sysfs */
+ if (conn->dest_port == -1 && conn->src_port == -1)
+ return 0;
+
do {
outs = devm_kasprintf(&orig->dev, GFP_KERNEL,
- "out:%d", conn->outport);
+ "out:%d", conn->src_port);
if (!outs)
break;
ins = devm_kasprintf(&target->dev, GFP_KERNEL,
- "in:%d", conn->child_port);
+ "in:%d", conn->dest_port);
if (!ins)
break;
link = devm_kzalloc(&orig->dev,
@@ -173,12 +177,6 @@ int coresight_make_links(struct coresight_device *orig,
break;
conn->link = link;
-
- /*
- * Install the device connection. This also indicates that
- * the links are operational on both ends.
- */
- conn->child_dev = target;
return 0;
} while (0);
@@ -198,9 +196,8 @@ void coresight_remove_links(struct coresight_device *orig,
coresight_remove_sysfs_link(conn->link);
- devm_kfree(&conn->child_dev->dev, conn->link->target_name);
+ devm_kfree(&conn->dest_dev->dev, conn->link->target_name);
devm_kfree(&orig->dev, conn->link->orig_name);
devm_kfree(&orig->dev, conn->link);
conn->link = NULL;
- conn->child_dev = NULL;
}
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 0ab1f73c2d06..79d8c64eac49 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -206,7 +206,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
* touched.
*/
if (drvdata->mode == CS_MODE_SYSFS) {
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
goto out;
}
@@ -229,7 +229,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
ret = tmc_etb_enable_hw(drvdata);
if (!ret) {
drvdata->mode = CS_MODE_SYSFS;
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
} else {
/* Free up the buffer if we failed to enable */
used = false;
@@ -284,7 +284,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
* use for this session.
*/
if (drvdata->pid == pid) {
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
break;
}
@@ -293,7 +293,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
/* Associate with monitored process. */
drvdata->pid = pid;
drvdata->mode = CS_MODE_PERF;
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
}
} while (0);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -302,7 +302,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
}
static int tmc_enable_etf_sink(struct coresight_device *csdev,
- u32 mode, void *data)
+ enum cs_mode mode, void *data)
{
int ret;
@@ -338,7 +338,7 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev)
return -EBUSY;
}
- if (atomic_dec_return(csdev->refcnt)) {
+ if (atomic_dec_return(&csdev->refcnt)) {
spin_unlock_irqrestore(&drvdata->spinlock, flags);
return -EBUSY;
}
@@ -357,7 +357,8 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev)
}
static int tmc_enable_etf_link(struct coresight_device *csdev,
- int inport, int outport)
+ struct coresight_connection *in,
+ struct coresight_connection *out)
{
int ret = 0;
unsigned long flags;
@@ -370,7 +371,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
return -EBUSY;
}
- if (atomic_read(&csdev->refcnt[0]) == 0) {
+ if (atomic_read(&csdev->refcnt) == 0) {
ret = tmc_etf_enable_hw(drvdata);
if (!ret) {
drvdata->mode = CS_MODE_SYSFS;
@@ -378,7 +379,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
}
}
if (!ret)
- atomic_inc(&csdev->refcnt[0]);
+ atomic_inc(&csdev->refcnt);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (first_enable)
@@ -387,7 +388,8 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
}
static void tmc_disable_etf_link(struct coresight_device *csdev,
- int inport, int outport)
+ struct coresight_connection *in,
+ struct coresight_connection *out)
{
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -399,7 +401,7 @@ static void tmc_disable_etf_link(struct coresight_device *csdev,
return;
}
- if (atomic_dec_return(&csdev->refcnt[0]) == 0) {
+ if (atomic_dec_return(&csdev->refcnt) == 0) {
tmc_etf_disable_hw(drvdata);
drvdata->mode = CS_MODE_DISABLED;
last_disable = true;
@@ -487,7 +489,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
spin_lock_irqsave(&drvdata->spinlock, flags);
/* Don't do anything if another tracer is using this sink */
- if (atomic_read(csdev->refcnt) != 1)
+ if (atomic_read(&csdev->refcnt) != 1)
goto out;
CS_UNLOCK(drvdata->base);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index eaa296ced167..766325de0e29 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -775,40 +775,19 @@ static const struct etr_buf_operations etr_sg_buf_ops = {
struct coresight_device *
tmc_etr_get_catu_device(struct tmc_drvdata *drvdata)
{
- int i;
- struct coresight_device *tmp, *etr = drvdata->csdev;
+ struct coresight_device *etr = drvdata->csdev;
+ union coresight_dev_subtype catu_subtype = {
+ .helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU
+ };
if (!IS_ENABLED(CONFIG_CORESIGHT_CATU))
return NULL;
- for (i = 0; i < etr->pdata->nr_outport; i++) {
- tmp = etr->pdata->conns[i].child_dev;
- if (tmp && coresight_is_catu_device(tmp))
- return tmp;
- }
-
- return NULL;
+ return coresight_find_output_type(etr->pdata, CORESIGHT_DEV_TYPE_HELPER,
+ catu_subtype);
}
EXPORT_SYMBOL_GPL(tmc_etr_get_catu_device);
-static inline int tmc_etr_enable_catu(struct tmc_drvdata *drvdata,
- struct etr_buf *etr_buf)
-{
- struct coresight_device *catu = tmc_etr_get_catu_device(drvdata);
-
- if (catu && helper_ops(catu)->enable)
- return helper_ops(catu)->enable(catu, etr_buf);
- return 0;
-}
-
-static inline void tmc_etr_disable_catu(struct tmc_drvdata *drvdata)
-{
- struct coresight_device *catu = tmc_etr_get_catu_device(drvdata);
-
- if (catu && helper_ops(catu)->disable)
- helper_ops(catu)->disable(catu, drvdata->etr_buf);
-}
-
static const struct etr_buf_operations *etr_buf_ops[] = {
[ETR_MODE_FLAT] = &etr_flat_buf_ops,
[ETR_MODE_ETR_SG] = &etr_sg_buf_ops,
@@ -1058,13 +1037,6 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
if (WARN_ON(drvdata->etr_buf))
return -EBUSY;
- /*
- * If this ETR is connected to a CATU, enable it before we turn
- * this on.
- */
- rc = tmc_etr_enable_catu(drvdata, etr_buf);
- if (rc)
- return rc;
rc = coresight_claim_device(drvdata->csdev);
if (!rc) {
drvdata->etr_buf = etr_buf;
@@ -1072,7 +1044,6 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
if (rc) {
drvdata->etr_buf = NULL;
coresight_disclaim_device(drvdata->csdev);
- tmc_etr_disable_catu(drvdata);
}
}
@@ -1162,14 +1133,12 @@ static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
{
__tmc_etr_disable_hw(drvdata);
- /* Disable CATU device if this ETR is connected to one */
- tmc_etr_disable_catu(drvdata);
coresight_disclaim_device(drvdata->csdev);
/* Reset the ETR buf used by hardware */
drvdata->etr_buf = NULL;
}
-static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
+static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
{
int ret = 0;
unsigned long flags;
@@ -1192,7 +1161,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
/* Allocate memory with the locks released */
free_buf = new_buf = tmc_etr_setup_sysfs_buf(drvdata);
if (IS_ERR(new_buf))
- return PTR_ERR(new_buf);
+ return new_buf;
/* Let's try again */
spin_lock_irqsave(&drvdata->spinlock, flags);
@@ -1209,7 +1178,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
* touched, even if the buffer size has changed.
*/
if (drvdata->mode == CS_MODE_SYSFS) {
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
goto out;
}
@@ -1223,17 +1192,33 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
drvdata->sysfs_buf = new_buf;
}
- ret = tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf);
- if (!ret) {
- drvdata->mode = CS_MODE_SYSFS;
- atomic_inc(csdev->refcnt);
- }
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
/* Free memory outside the spinlock if need be */
if (free_buf)
tmc_etr_free_sysfs_buf(free_buf);
+ return ret ? ERR_PTR(ret) : drvdata->sysfs_buf;
+}
+
+static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
+{
+ int ret;
+ unsigned long flags;
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ struct etr_buf *sysfs_buf = tmc_etr_get_sysfs_buffer(csdev);
+
+ if (IS_ERR(sysfs_buf))
+ return PTR_ERR(sysfs_buf);
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ ret = tmc_etr_enable_hw(drvdata, sysfs_buf);
+ if (!ret) {
+ drvdata->mode = CS_MODE_SYSFS;
+ atomic_inc(&csdev->refcnt);
+ }
+
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (!ret)
dev_dbg(&csdev->dev, "TMC-ETR enabled\n");
@@ -1241,6 +1226,26 @@ out:
return ret;
}
+struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
+ enum cs_mode mode, void *data)
+{
+ struct perf_output_handle *handle = data;
+ struct etr_perf_buffer *etr_perf;
+
+ switch (mode) {
+ case CS_MODE_SYSFS:
+ return tmc_etr_get_sysfs_buffer(csdev);
+ case CS_MODE_PERF:
+ etr_perf = etm_perf_sink_config(handle);
+ if (WARN_ON(!etr_perf || !etr_perf->etr_buf))
+ return ERR_PTR(-EINVAL);
+ return etr_perf->etr_buf;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+}
+EXPORT_SYMBOL_GPL(tmc_etr_get_buffer);
+
/*
* alloc_etr_buf: Allocate ETR buffer for use by perf.
* The size of the hardware buffer is dependent on the size configured
@@ -1535,7 +1540,7 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
spin_lock_irqsave(&drvdata->spinlock, flags);
/* Don't do anything if another tracer is using this sink */
- if (atomic_read(csdev->refcnt) != 1) {
+ if (atomic_read(&csdev->refcnt) != 1) {
spin_unlock_irqrestore(&drvdata->spinlock, flags);
goto out;
}
@@ -1647,7 +1652,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
* use for this session.
*/
if (drvdata->pid == pid) {
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
goto unlock_out;
}
@@ -1657,7 +1662,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
drvdata->pid = pid;
drvdata->mode = CS_MODE_PERF;
drvdata->perf_buf = etr_perf->etr_buf;
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
}
unlock_out:
@@ -1666,17 +1671,16 @@ unlock_out:
}
static int tmc_enable_etr_sink(struct coresight_device *csdev,
- u32 mode, void *data)
+ enum cs_mode mode, void *data)
{
switch (mode) {
case CS_MODE_SYSFS:
return tmc_enable_etr_sink_sysfs(csdev);
case CS_MODE_PERF:
return tmc_enable_etr_sink_perf(csdev, data);
+ default:
+ return -EINVAL;
}
-
- /* We shouldn't be here */
- return -EINVAL;
}
static int tmc_disable_etr_sink(struct coresight_device *csdev)
@@ -1691,7 +1695,7 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
return -EBUSY;
}
- if (atomic_dec_return(csdev->refcnt)) {
+ if (atomic_dec_return(&csdev->refcnt)) {
spin_unlock_irqrestore(&drvdata->spinlock, flags);
return -EBUSY;
}
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 01c0382a29c0..b97da39652d2 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -332,5 +332,7 @@ struct coresight_device *tmc_etr_get_catu_device(struct tmc_drvdata *drvdata);
void tmc_etr_set_catu_ops(const struct etr_buf_operations *catu);
void tmc_etr_remove_catu_ops(void);
+struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
+ enum cs_mode mode, void *data);
#endif
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
index f712e112ecff..8d2b9d29237d 100644
--- a/drivers/hwtracing/coresight/coresight-tpda.c
+++ b/drivers/hwtracing/coresight/coresight-tpda.c
@@ -54,18 +54,20 @@ static void __tpda_enable(struct tpda_drvdata *drvdata, int port)
CS_LOCK(drvdata->base);
}
-static int tpda_enable(struct coresight_device *csdev, int inport, int outport)
+static int tpda_enable(struct coresight_device *csdev,
+ struct coresight_connection *in,
+ struct coresight_connection *out)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
spin_lock(&drvdata->spinlock);
- if (atomic_read(&csdev->refcnt[inport]) == 0)
- __tpda_enable(drvdata, inport);
+ if (atomic_read(&in->dest_refcnt) == 0)
+ __tpda_enable(drvdata, in->dest_port);
- atomic_inc(&csdev->refcnt[inport]);
+ atomic_inc(&in->dest_refcnt);
spin_unlock(&drvdata->spinlock);
- dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", inport);
+ dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
return 0;
}
@@ -82,18 +84,19 @@ static void __tpda_disable(struct tpda_drvdata *drvdata, int port)
CS_LOCK(drvdata->base);
}
-static void tpda_disable(struct coresight_device *csdev, int inport,
- int outport)
+static void tpda_disable(struct coresight_device *csdev,
+ struct coresight_connection *in,
+ struct coresight_connection *out)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
spin_lock(&drvdata->spinlock);
- if (atomic_dec_return(&csdev->refcnt[inport]) == 0)
- __tpda_disable(drvdata, inport);
+ if (atomic_dec_return(&in->dest_refcnt) == 0)
+ __tpda_disable(drvdata, in->dest_port);
spin_unlock(&drvdata->spinlock);
- dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", inport);
+ dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", in->dest_port);
}
static const struct coresight_ops_link tpda_link_ops = {
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 9479a5e8c672..f4854af0431e 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -42,8 +42,8 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata)
CS_LOCK(drvdata->base);
}
-static int tpdm_enable(struct coresight_device *csdev,
- struct perf_event *event, u32 mode)
+static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
+ enum cs_mode mode)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index 34d37abd2c8d..59eac93fd6bb 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -69,10 +69,11 @@ static void tpiu_enable_hw(struct csdev_access *csa)
CS_LOCK(csa->base);
}
-static int tpiu_enable(struct coresight_device *csdev, u32 mode, void *__unused)
+static int tpiu_enable(struct coresight_device *csdev, enum cs_mode mode,
+ void *__unused)
{
tpiu_enable_hw(&csdev->access);
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
dev_dbg(&csdev->dev, "TPIU enabled\n");
return 0;
}
@@ -95,7 +96,7 @@ static void tpiu_disable_hw(struct csdev_access *csa)
static int tpiu_disable(struct coresight_device *csdev)
{
- if (atomic_dec_return(csdev->refcnt))
+ if (atomic_dec_return(&csdev->refcnt))
return -EBUSY;
tpiu_disable_hw(&csdev->access);
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c
index 1bab91ce8e95..7720619909d6 100644
--- a/drivers/hwtracing/coresight/coresight-trbe.c
+++ b/drivers/hwtracing/coresight/coresight-trbe.c
@@ -1006,7 +1006,8 @@ err:
return ret;
}
-static int arm_trbe_enable(struct coresight_device *csdev, u32 mode, void *data)
+static int arm_trbe_enable(struct coresight_device *csdev, enum cs_mode mode,
+ void *data)
{
struct trbe_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct trbe_cpudata *cpudata = dev_get_drvdata(&csdev->dev);
diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c
index b317342c7ce5..e9a32a97fbee 100644
--- a/drivers/hwtracing/coresight/ultrasoc-smb.c
+++ b/drivers/hwtracing/coresight/ultrasoc-smb.c
@@ -106,7 +106,7 @@ static int smb_open(struct inode *inode, struct file *file)
goto out;
}
- if (atomic_read(drvdata->csdev->refcnt)) {
+ if (atomic_read(&drvdata->csdev->refcnt)) {
ret = -EBUSY;
goto out;
}
@@ -256,7 +256,8 @@ static int smb_enable_perf(struct coresight_device *csdev, void *data)
return 0;
}
-static int smb_enable(struct coresight_device *csdev, u32 mode, void *data)
+static int smb_enable(struct coresight_device *csdev, enum cs_mode mode,
+ void *data)
{
struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
int ret = 0;
@@ -289,7 +290,7 @@ static int smb_enable(struct coresight_device *csdev, u32 mode, void *data)
if (ret)
goto out;
- atomic_inc(csdev->refcnt);
+ atomic_inc(&csdev->refcnt);
dev_dbg(&csdev->dev, "Ultrasoc SMB enabled\n");
out:
@@ -310,7 +311,7 @@ static int smb_disable(struct coresight_device *csdev)
goto out;
}
- if (atomic_dec_return(csdev->refcnt)) {
+ if (atomic_dec_return(&csdev->refcnt)) {
ret = -EBUSY;
goto out;
}
@@ -410,7 +411,7 @@ static unsigned long smb_update_buffer(struct coresight_device *csdev,
mutex_lock(&drvdata->mutex);
/* Don't do anything if another tracer is using this sink. */
- if (atomic_read(csdev->refcnt) != 1)
+ if (atomic_read(&csdev->refcnt) != 1)
goto out;
smb_disable_hw(drvdata);
diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.h b/drivers/hwtracing/coresight/ultrasoc-smb.h
index 7dfbe42e37a0..d2e14e8d2c8a 100644
--- a/drivers/hwtracing/coresight/ultrasoc-smb.h
+++ b/drivers/hwtracing/coresight/ultrasoc-smb.h
@@ -119,7 +119,7 @@ struct smb_drv_data {
struct mutex mutex;
bool reading;
pid_t pid;
- u32 mode;
+ enum cs_mode mode;
};
#endif
diff --git a/drivers/hwtracing/ptt/hisi_ptt.c b/drivers/hwtracing/ptt/hisi_ptt.c
index 30f1525639b5..ba081b6d2435 100644
--- a/drivers/hwtracing/ptt/hisi_ptt.c
+++ b/drivers/hwtracing/ptt/hisi_ptt.c
@@ -341,19 +341,319 @@ static int hisi_ptt_register_irq(struct hisi_ptt *hisi_ptt)
if (ret < 0)
return ret;
- ret = devm_request_threaded_irq(&pdev->dev,
- pci_irq_vector(pdev, HISI_PTT_TRACE_DMA_IRQ),
+ hisi_ptt->trace_irq = pci_irq_vector(pdev, HISI_PTT_TRACE_DMA_IRQ);
+ ret = devm_request_threaded_irq(&pdev->dev, hisi_ptt->trace_irq,
NULL, hisi_ptt_isr, 0,
DRV_NAME, hisi_ptt);
if (ret) {
pci_err(pdev, "failed to request irq %d, ret = %d\n",
- pci_irq_vector(pdev, HISI_PTT_TRACE_DMA_IRQ), ret);
+ hisi_ptt->trace_irq, ret);
return ret;
}
return 0;
}
+static void hisi_ptt_del_free_filter(struct hisi_ptt *hisi_ptt,
+ struct hisi_ptt_filter_desc *filter)
+{
+ if (filter->is_port)
+ hisi_ptt->port_mask &= ~hisi_ptt_get_filter_val(filter->devid, true);
+
+ list_del(&filter->list);
+ kfree(filter->name);
+ kfree(filter);
+}
+
+static struct hisi_ptt_filter_desc *
+hisi_ptt_alloc_add_filter(struct hisi_ptt *hisi_ptt, u16 devid, bool is_port)
+{
+ struct hisi_ptt_filter_desc *filter;
+ u8 devfn = devid & 0xff;
+ char *filter_name;
+
+ filter_name = kasprintf(GFP_KERNEL, "%04x:%02x:%02x.%d", pci_domain_nr(hisi_ptt->pdev->bus),
+ PCI_BUS_NUM(devid), PCI_SLOT(devfn), PCI_FUNC(devfn));
+ if (!filter_name) {
+ pci_err(hisi_ptt->pdev, "failed to allocate name for filter %04x:%02x:%02x.%d\n",
+ pci_domain_nr(hisi_ptt->pdev->bus), PCI_BUS_NUM(devid),
+ PCI_SLOT(devfn), PCI_FUNC(devfn));
+ return NULL;
+ }
+
+ filter = kzalloc(sizeof(*filter), GFP_KERNEL);
+ if (!filter) {
+ pci_err(hisi_ptt->pdev, "failed to add filter for %s\n",
+ filter_name);
+ kfree(filter_name);
+ return NULL;
+ }
+
+ filter->name = filter_name;
+ filter->is_port = is_port;
+ filter->devid = devid;
+
+ if (filter->is_port) {
+ list_add_tail(&filter->list, &hisi_ptt->port_filters);
+
+ /* Update the available port mask */
+ hisi_ptt->port_mask |= hisi_ptt_get_filter_val(filter->devid, true);
+ } else {
+ list_add_tail(&filter->list, &hisi_ptt->req_filters);
+ }
+
+ return filter;
+}
+
+static ssize_t hisi_ptt_filter_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hisi_ptt_filter_desc *filter;
+ unsigned long filter_val;
+
+ filter = container_of(attr, struct hisi_ptt_filter_desc, attr);
+ filter_val = hisi_ptt_get_filter_val(filter->devid, filter->is_port) |
+ (filter->is_port ? HISI_PTT_PMU_FILTER_IS_PORT : 0);
+
+ return sysfs_emit(buf, "0x%05lx\n", filter_val);
+}
+
+static int hisi_ptt_create_rp_filter_attr(struct hisi_ptt *hisi_ptt,
+ struct hisi_ptt_filter_desc *filter)
+{
+ struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj;
+
+ sysfs_attr_init(&filter->attr.attr);
+ filter->attr.attr.name = filter->name;
+ filter->attr.attr.mode = 0400; /* DEVICE_ATTR_ADMIN_RO */
+ filter->attr.show = hisi_ptt_filter_show;
+
+ return sysfs_add_file_to_group(kobj, &filter->attr.attr,
+ HISI_PTT_RP_FILTERS_GRP_NAME);
+}
+
+static void hisi_ptt_remove_rp_filter_attr(struct hisi_ptt *hisi_ptt,
+ struct hisi_ptt_filter_desc *filter)
+{
+ struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj;
+
+ sysfs_remove_file_from_group(kobj, &filter->attr.attr,
+ HISI_PTT_RP_FILTERS_GRP_NAME);
+}
+
+static int hisi_ptt_create_req_filter_attr(struct hisi_ptt *hisi_ptt,
+ struct hisi_ptt_filter_desc *filter)
+{
+ struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj;
+
+ sysfs_attr_init(&filter->attr.attr);
+ filter->attr.attr.name = filter->name;
+ filter->attr.attr.mode = 0400; /* DEVICE_ATTR_ADMIN_RO */
+ filter->attr.show = hisi_ptt_filter_show;
+
+ return sysfs_add_file_to_group(kobj, &filter->attr.attr,
+ HISI_PTT_REQ_FILTERS_GRP_NAME);
+}
+
+static void hisi_ptt_remove_req_filter_attr(struct hisi_ptt *hisi_ptt,
+ struct hisi_ptt_filter_desc *filter)
+{
+ struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj;
+
+ sysfs_remove_file_from_group(kobj, &filter->attr.attr,
+ HISI_PTT_REQ_FILTERS_GRP_NAME);
+}
+
+static int hisi_ptt_create_filter_attr(struct hisi_ptt *hisi_ptt,
+ struct hisi_ptt_filter_desc *filter)
+{
+ int ret;
+
+ if (filter->is_port)
+ ret = hisi_ptt_create_rp_filter_attr(hisi_ptt, filter);
+ else
+ ret = hisi_ptt_create_req_filter_attr(hisi_ptt, filter);
+
+ if (ret)
+ pci_err(hisi_ptt->pdev, "failed to create sysfs attribute for filter %s\n",
+ filter->name);
+
+ return ret;
+}
+
+static void hisi_ptt_remove_filter_attr(struct hisi_ptt *hisi_ptt,
+ struct hisi_ptt_filter_desc *filter)
+{
+ if (filter->is_port)
+ hisi_ptt_remove_rp_filter_attr(hisi_ptt, filter);
+ else
+ hisi_ptt_remove_req_filter_attr(hisi_ptt, filter);
+}
+
+static void hisi_ptt_remove_all_filter_attributes(void *data)
+{
+ struct hisi_ptt_filter_desc *filter;
+ struct hisi_ptt *hisi_ptt = data;
+
+ mutex_lock(&hisi_ptt->filter_lock);
+
+ list_for_each_entry(filter, &hisi_ptt->req_filters, list)
+ hisi_ptt_remove_filter_attr(hisi_ptt, filter);
+
+ list_for_each_entry(filter, &hisi_ptt->port_filters, list)
+ hisi_ptt_remove_filter_attr(hisi_ptt, filter);
+
+ hisi_ptt->sysfs_inited = false;
+ mutex_unlock(&hisi_ptt->filter_lock);
+}
+
+static int hisi_ptt_init_filter_attributes(struct hisi_ptt *hisi_ptt)
+{
+ struct hisi_ptt_filter_desc *filter;
+ int ret;
+
+ mutex_lock(&hisi_ptt->filter_lock);
+
+ /*
+ * Register the reset callback in the first stage. In reset we traverse
+ * the filters list to remove the sysfs attributes so the callback can
+ * be called safely even without below filter attributes creation.
+ */
+ ret = devm_add_action(&hisi_ptt->pdev->dev,
+ hisi_ptt_remove_all_filter_attributes,
+ hisi_ptt);
+ if (ret)
+ goto out;
+
+ list_for_each_entry(filter, &hisi_ptt->port_filters, list) {
+ ret = hisi_ptt_create_filter_attr(hisi_ptt, filter);
+ if (ret)
+ goto out;
+ }
+
+ list_for_each_entry(filter, &hisi_ptt->req_filters, list) {
+ ret = hisi_ptt_create_filter_attr(hisi_ptt, filter);
+ if (ret)
+ goto out;
+ }
+
+ hisi_ptt->sysfs_inited = true;
+out:
+ mutex_unlock(&hisi_ptt->filter_lock);
+ return ret;
+}
+
+static void hisi_ptt_update_filters(struct work_struct *work)
+{
+ struct delayed_work *delayed_work = to_delayed_work(work);
+ struct hisi_ptt_filter_update_info info;
+ struct hisi_ptt_filter_desc *filter;
+ struct hisi_ptt *hisi_ptt;
+
+ hisi_ptt = container_of(delayed_work, struct hisi_ptt, work);
+
+ if (!mutex_trylock(&hisi_ptt->filter_lock)) {
+ schedule_delayed_work(&hisi_ptt->work, HISI_PTT_WORK_DELAY_MS);
+ return;
+ }
+
+ while (kfifo_get(&hisi_ptt->filter_update_kfifo, &info)) {
+ if (info.is_add) {
+ /*
+ * Notify the users if failed to add this filter, others
+ * still work and available. See the comments in
+ * hisi_ptt_init_filters().
+ */
+ filter = hisi_ptt_alloc_add_filter(hisi_ptt, info.devid, info.is_port);
+ if (!filter)
+ continue;
+
+ /*
+ * If filters' sysfs entries hasn't been initialized,
+ * then we're still at probe stage. Add the filters to
+ * the list and later hisi_ptt_init_filter_attributes()
+ * will create sysfs attributes for all the filters.
+ */
+ if (hisi_ptt->sysfs_inited &&
+ hisi_ptt_create_filter_attr(hisi_ptt, filter)) {
+ hisi_ptt_del_free_filter(hisi_ptt, filter);
+ continue;
+ }
+ } else {
+ struct hisi_ptt_filter_desc *tmp;
+ struct list_head *target_list;
+
+ target_list = info.is_port ? &hisi_ptt->port_filters :
+ &hisi_ptt->req_filters;
+
+ list_for_each_entry_safe(filter, tmp, target_list, list)
+ if (filter->devid == info.devid) {
+ if (hisi_ptt->sysfs_inited)
+ hisi_ptt_remove_filter_attr(hisi_ptt, filter);
+
+ hisi_ptt_del_free_filter(hisi_ptt, filter);
+ break;
+ }
+ }
+ }
+
+ mutex_unlock(&hisi_ptt->filter_lock);
+}
+
+/*
+ * A PCI bus notifier is used here for dynamically updating the filter
+ * list.
+ */
+static int hisi_ptt_notifier_call(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct hisi_ptt *hisi_ptt = container_of(nb, struct hisi_ptt, hisi_ptt_nb);
+ struct hisi_ptt_filter_update_info info;
+ struct pci_dev *pdev, *root_port;
+ struct device *dev = data;
+ u32 port_devid;
+
+ pdev = to_pci_dev(dev);
+ root_port = pcie_find_root_port(pdev);
+ if (!root_port)
+ return 0;
+
+ port_devid = PCI_DEVID(root_port->bus->number, root_port->devfn);
+ if (port_devid < hisi_ptt->lower_bdf ||
+ port_devid > hisi_ptt->upper_bdf)
+ return 0;
+
+ info.is_port = pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT;
+ info.devid = PCI_DEVID(pdev->bus->number, pdev->devfn);
+
+ switch (action) {
+ case BUS_NOTIFY_ADD_DEVICE:
+ info.is_add = true;
+ break;
+ case BUS_NOTIFY_DEL_DEVICE:
+ info.is_add = false;
+ break;
+ default:
+ return 0;
+ }
+
+ /*
+ * The FIFO size is 16 which is sufficient for almost all the cases,
+ * since each PCIe core will have most 8 Root Ports (typically only
+ * 1~4 Root Ports). On failure log the failed filter and let user
+ * handle it.
+ */
+ if (kfifo_in_spinlocked(&hisi_ptt->filter_update_kfifo, &info, 1,
+ &hisi_ptt->filter_update_lock))
+ schedule_delayed_work(&hisi_ptt->work, 0);
+ else
+ pci_warn(hisi_ptt->pdev,
+ "filter update fifo overflow for target %s\n",
+ pci_name(pdev));
+
+ return 0;
+}
+
static int hisi_ptt_init_filters(struct pci_dev *pdev, void *data)
{
struct pci_dev *root_port = pcie_find_root_port(pdev);
@@ -374,23 +674,10 @@ static int hisi_ptt_init_filters(struct pci_dev *pdev, void *data)
* should be partial initialized and users would know which filter fails
* through the log. Other functions of PTT device are still available.
*/
- filter = kzalloc(sizeof(*filter), GFP_KERNEL);
- if (!filter) {
- pci_err(hisi_ptt->pdev, "failed to add filter %s\n", pci_name(pdev));
+ filter = hisi_ptt_alloc_add_filter(hisi_ptt, PCI_DEVID(pdev->bus->number, pdev->devfn),
+ pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT);
+ if (!filter)
return -ENOMEM;
- }
-
- filter->devid = PCI_DEVID(pdev->bus->number, pdev->devfn);
-
- if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) {
- filter->is_port = true;
- list_add_tail(&filter->list, &hisi_ptt->port_filters);
-
- /* Update the available port mask */
- hisi_ptt->port_mask |= hisi_ptt_get_filter_val(filter->devid, true);
- } else {
- list_add_tail(&filter->list, &hisi_ptt->req_filters);
- }
return 0;
}
@@ -400,15 +687,11 @@ static void hisi_ptt_release_filters(void *data)
struct hisi_ptt_filter_desc *filter, *tmp;
struct hisi_ptt *hisi_ptt = data;
- list_for_each_entry_safe(filter, tmp, &hisi_ptt->req_filters, list) {
- list_del(&filter->list);
- kfree(filter);
- }
+ list_for_each_entry_safe(filter, tmp, &hisi_ptt->req_filters, list)
+ hisi_ptt_del_free_filter(hisi_ptt, filter);
- list_for_each_entry_safe(filter, tmp, &hisi_ptt->port_filters, list) {
- list_del(&filter->list);
- kfree(filter);
- }
+ list_for_each_entry_safe(filter, tmp, &hisi_ptt->port_filters, list)
+ hisi_ptt_del_free_filter(hisi_ptt, filter);
}
static int hisi_ptt_config_trace_buf(struct hisi_ptt *hisi_ptt)
@@ -451,8 +734,13 @@ static int hisi_ptt_init_ctrls(struct hisi_ptt *hisi_ptt)
int ret;
u32 reg;
+ INIT_DELAYED_WORK(&hisi_ptt->work, hisi_ptt_update_filters);
+ INIT_KFIFO(hisi_ptt->filter_update_kfifo);
+ spin_lock_init(&hisi_ptt->filter_update_lock);
+
INIT_LIST_HEAD(&hisi_ptt->port_filters);
INIT_LIST_HEAD(&hisi_ptt->req_filters);
+ mutex_init(&hisi_ptt->filter_lock);
ret = hisi_ptt_config_trace_buf(hisi_ptt);
if (ret)
@@ -528,10 +816,58 @@ static struct attribute_group hisi_ptt_pmu_format_group = {
.attrs = hisi_ptt_pmu_format_attrs,
};
+static ssize_t hisi_ptt_filter_multiselect_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct dev_ext_attribute *ext_attr;
+
+ ext_attr = container_of(attr, struct dev_ext_attribute, attr);
+ return sysfs_emit(buf, "%s\n", (char *)ext_attr->var);
+}
+
+static struct dev_ext_attribute root_port_filters_multiselect = {
+ .attr = {
+ .attr = { .name = "multiselect", .mode = 0400 },
+ .show = hisi_ptt_filter_multiselect_show,
+ },
+ .var = "1",
+};
+
+static struct attribute *hisi_ptt_pmu_root_ports_attrs[] = {
+ &root_port_filters_multiselect.attr.attr,
+ NULL
+};
+
+static struct attribute_group hisi_ptt_pmu_root_ports_group = {
+ .name = HISI_PTT_RP_FILTERS_GRP_NAME,
+ .attrs = hisi_ptt_pmu_root_ports_attrs,
+};
+
+static struct dev_ext_attribute requester_filters_multiselect = {
+ .attr = {
+ .attr = { .name = "multiselect", .mode = 0400 },
+ .show = hisi_ptt_filter_multiselect_show,
+ },
+ .var = "0",
+};
+
+static struct attribute *hisi_ptt_pmu_requesters_attrs[] = {
+ &requester_filters_multiselect.attr.attr,
+ NULL
+};
+
+static struct attribute_group hisi_ptt_pmu_requesters_group = {
+ .name = HISI_PTT_REQ_FILTERS_GRP_NAME,
+ .attrs = hisi_ptt_pmu_requesters_attrs,
+};
+
static const struct attribute_group *hisi_ptt_pmu_groups[] = {
&hisi_ptt_cpumask_attr_group,
&hisi_ptt_pmu_format_group,
&hisi_ptt_tune_group,
+ &hisi_ptt_pmu_root_ports_group,
+ &hisi_ptt_pmu_requesters_group,
NULL
};
@@ -605,6 +941,7 @@ static int hisi_ptt_trace_valid_filter(struct hisi_ptt *hisi_ptt, u64 config)
{
unsigned long val, port_mask = hisi_ptt->port_mask;
struct hisi_ptt_filter_desc *filter;
+ int ret = 0;
hisi_ptt->trace_ctrl.is_port = FIELD_GET(HISI_PTT_PMU_FILTER_IS_PORT, config);
val = FIELD_GET(HISI_PTT_PMU_FILTER_VAL_MASK, config);
@@ -618,16 +955,20 @@ static int hisi_ptt_trace_valid_filter(struct hisi_ptt *hisi_ptt, u64 config)
* For Requester ID filters, walk the available filter list to see
* whether we have one matched.
*/
+ mutex_lock(&hisi_ptt->filter_lock);
if (!hisi_ptt->trace_ctrl.is_port) {
list_for_each_entry(filter, &hisi_ptt->req_filters, list) {
if (val == hisi_ptt_get_filter_val(filter->devid, filter->is_port))
- return 0;
+ goto out;
}
} else if (bitmap_subset(&val, &port_mask, BITS_PER_LONG)) {
- return 0;
+ goto out;
}
- return -EINVAL;
+ ret = -EINVAL;
+out:
+ mutex_unlock(&hisi_ptt->filter_lock);
+ return ret;
}
static void hisi_ptt_pmu_init_configs(struct hisi_ptt *hisi_ptt, struct perf_event *event)
@@ -757,8 +1098,7 @@ static void hisi_ptt_pmu_start(struct perf_event *event, int flags)
* core in event_function_local(). If CPU passed is offline we'll fail
* here, just log it since we can do nothing here.
*/
- ret = irq_set_affinity(pci_irq_vector(hisi_ptt->pdev, HISI_PTT_TRACE_DMA_IRQ),
- cpumask_of(cpu));
+ ret = irq_set_affinity(hisi_ptt->trace_irq, cpumask_of(cpu));
if (ret)
dev_warn(dev, "failed to set the affinity of trace interrupt\n");
@@ -871,7 +1211,7 @@ static int hisi_ptt_register_pmu(struct hisi_ptt *hisi_ptt)
hisi_ptt->hisi_ptt_pmu = (struct pmu) {
.module = THIS_MODULE,
- .capabilities = PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE,
+ .capabilities = PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_NO_EXCLUDE,
.task_ctx_nr = perf_sw_context,
.attr_groups = hisi_ptt_pmu_groups,
.event_init = hisi_ptt_pmu_event_init,
@@ -901,6 +1241,31 @@ static int hisi_ptt_register_pmu(struct hisi_ptt *hisi_ptt)
&hisi_ptt->hisi_ptt_pmu);
}
+static void hisi_ptt_unregister_filter_update_notifier(void *data)
+{
+ struct hisi_ptt *hisi_ptt = data;
+
+ bus_unregister_notifier(&pci_bus_type, &hisi_ptt->hisi_ptt_nb);
+
+ /* Cancel any work that has been queued */
+ cancel_delayed_work_sync(&hisi_ptt->work);
+}
+
+/* Register the bus notifier for dynamically updating the filter list */
+static int hisi_ptt_register_filter_update_notifier(struct hisi_ptt *hisi_ptt)
+{
+ int ret;
+
+ hisi_ptt->hisi_ptt_nb.notifier_call = hisi_ptt_notifier_call;
+ ret = bus_register_notifier(&pci_bus_type, &hisi_ptt->hisi_ptt_nb);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(&hisi_ptt->pdev->dev,
+ hisi_ptt_unregister_filter_update_notifier,
+ hisi_ptt);
+}
+
/*
* The DMA of PTT trace can only use direct mappings due to some
* hardware restriction. Check whether there is no IOMMU or the
@@ -972,12 +1337,22 @@ static int hisi_ptt_probe(struct pci_dev *pdev,
return ret;
}
+ ret = hisi_ptt_register_filter_update_notifier(hisi_ptt);
+ if (ret)
+ pci_warn(pdev, "failed to register filter update notifier, ret = %d", ret);
+
ret = hisi_ptt_register_pmu(hisi_ptt);
if (ret) {
pci_err(pdev, "failed to register PMU device, ret = %d", ret);
return ret;
}
+ ret = hisi_ptt_init_filter_attributes(hisi_ptt);
+ if (ret) {
+ pci_err(pdev, "failed to init sysfs filter attributes, ret = %d", ret);
+ return ret;
+ }
+
return 0;
}
@@ -1018,8 +1393,7 @@ static int hisi_ptt_cpu_teardown(unsigned int cpu, struct hlist_node *node)
* Also make sure the interrupt bind to the migrated CPU as well. Warn
* the user on failure here.
*/
- if (irq_set_affinity(pci_irq_vector(hisi_ptt->pdev, HISI_PTT_TRACE_DMA_IRQ),
- cpumask_of(target)))
+ if (irq_set_affinity(hisi_ptt->trace_irq, cpumask_of(target)))
dev_warn(dev, "failed to set the affinity of trace interrupt\n");
hisi_ptt->trace_ctrl.on_cpu = target;
diff --git a/drivers/hwtracing/ptt/hisi_ptt.h b/drivers/hwtracing/ptt/hisi_ptt.h
index 5beb1648c93a..e17f045d7e72 100644
--- a/drivers/hwtracing/ptt/hisi_ptt.h
+++ b/drivers/hwtracing/ptt/hisi_ptt.h
@@ -11,12 +11,16 @@
#include <linux/bits.h>
#include <linux/cpumask.h>
+#include <linux/device.h>
+#include <linux/kfifo.h>
#include <linux/list.h>
#include <linux/mutex.h>
+#include <linux/notifier.h>
#include <linux/pci.h>
#include <linux/perf_event.h>
#include <linux/spinlock.h>
#include <linux/types.h>
+#include <linux/workqueue.h>
#define DRV_NAME "hisi_ptt"
@@ -71,6 +75,11 @@
#define HISI_PTT_WAIT_TRACE_TIMEOUT_US 100UL
#define HISI_PTT_WAIT_POLL_INTERVAL_US 10UL
+/* FIFO size for dynamically updating the PTT trace filter list. */
+#define HISI_PTT_FILTER_UPDATE_FIFO_SIZE 16
+/* Delay time for filter updating work */
+#define HISI_PTT_WORK_DELAY_MS 100UL
+
#define HISI_PCIE_CORE_PORT_ID(devfn) ((PCI_SLOT(devfn) & 0x7) << 1)
/* Definition of the PMU configs */
@@ -131,15 +140,40 @@ struct hisi_ptt_trace_ctrl {
u32 type:4;
};
+/*
+ * sysfs attribute group name for root port filters and requester filters:
+ * /sys/devices/hisi_ptt<sicl_id>_<core_id>/root_port_filters
+ * and
+ * /sys/devices/hisi_ptt<sicl_id>_<core_id>/requester_filters
+ */
+#define HISI_PTT_RP_FILTERS_GRP_NAME "root_port_filters"
+#define HISI_PTT_REQ_FILTERS_GRP_NAME "requester_filters"
+
/**
* struct hisi_ptt_filter_desc - Descriptor of the PTT trace filter
+ * @attr: sysfs attribute of this filter
* @list: entry of this descriptor in the filter list
* @is_port: the PCI device of the filter is a Root Port or not
+ * @name: name of this filter, same as the name of the related PCI device
* @devid: the PCI device's devid of the filter
*/
struct hisi_ptt_filter_desc {
+ struct device_attribute attr;
struct list_head list;
bool is_port;
+ char *name;
+ u16 devid;
+};
+
+/**
+ * struct hisi_ptt_filter_update_info - Information for PTT filter updating
+ * @is_port: the PCI device to update is a Root Port or not
+ * @is_add: adding to the filter or not
+ * @devid: the PCI device's devid of the filter
+ */
+struct hisi_ptt_filter_update_info {
+ bool is_port;
+ bool is_add;
u16 devid;
};
@@ -160,26 +194,35 @@ struct hisi_ptt_pmu_buf {
/**
* struct hisi_ptt - Per PTT device data
* @trace_ctrl: the control information of PTT trace
+ * @hisi_ptt_nb: dynamic filter update notifier
* @hotplug_node: node for register cpu hotplug event
* @hisi_ptt_pmu: the pum device of trace
* @iobase: base IO address of the device
* @pdev: pci_dev of this PTT device
* @tune_lock: lock to serialize the tune process
* @pmu_lock: lock to serialize the perf process
+ * @trace_irq: interrupt number used by trace
* @upper_bdf: the upper BDF range of the PCI devices managed by this PTT device
* @lower_bdf: the lower BDF range of the PCI devices managed by this PTT device
* @port_filters: the filter list of root ports
* @req_filters: the filter list of requester ID
+ * @filter_lock: lock to protect the filters
+ * @sysfs_inited: whether the filters' sysfs entries has been initialized
* @port_mask: port mask of the managed root ports
+ * @work: delayed work for filter updating
+ * @filter_update_lock: spinlock to protect the filter update fifo
+ * @filter_update_fifo: fifo of the filters waiting to update the filter list
*/
struct hisi_ptt {
struct hisi_ptt_trace_ctrl trace_ctrl;
+ struct notifier_block hisi_ptt_nb;
struct hlist_node hotplug_node;
struct pmu hisi_ptt_pmu;
void __iomem *iobase;
struct pci_dev *pdev;
struct mutex tune_lock;
spinlock_t pmu_lock;
+ int trace_irq;
u32 upper_bdf;
u32 lower_bdf;
@@ -192,7 +235,20 @@ struct hisi_ptt {
*/
struct list_head port_filters;
struct list_head req_filters;
+ struct mutex filter_lock;
+ bool sysfs_inited;
u16 port_mask;
+
+ /*
+ * We use a delayed work here to avoid indefinitely waiting for
+ * the hisi_ptt->mutex which protecting the filter list. The
+ * work will be delayed only if the mutex can not be held,
+ * otherwise no delay will be applied.
+ */
+ struct delayed_work work;
+ spinlock_t filter_update_lock;
+ DECLARE_KFIFO(filter_update_kfifo, struct hisi_ptt_filter_update_info,
+ HISI_PTT_FILTER_UPDATE_FIFO_SIZE);
};
#define to_hisi_ptt(pmu) container_of(pmu, struct hisi_ptt, hisi_ptt_pmu)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 87600b4aacb3..9cfe8fc509d7 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -157,7 +157,7 @@ config I2C_I801
Emmitsburg (PCH)
Alder Lake (PCH)
Raptor Lake (PCH)
- Meteor Lake (SOC)
+ Meteor Lake (SOC and PCH)
This driver can also be built as a module. If so, the module
will be called i2c-i801.
@@ -1025,7 +1025,7 @@ config I2C_RZV2M
depends on ARCH_RENESAS || COMPILE_TEST
help
If you say yes to this option, support will be included for the
- Renesas RZ/V2M I2C interface.
+ Renesas RZ/V2M I2C interface.
This driver can also be built as a module. If so, the module
will be called i2c-rzv2m.
diff --git a/drivers/i2c/busses/i2c-altera.c b/drivers/i2c/busses/i2c-altera.c
index 50e7f3f670b6..252fbd175fb1 100644
--- a/drivers/i2c/busses/i2c-altera.c
+++ b/drivers/i2c/busses/i2c-altera.c
@@ -465,14 +465,12 @@ static int altr_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int altr_i2c_remove(struct platform_device *pdev)
+static void altr_i2c_remove(struct platform_device *pdev)
{
struct altr_i2c_dev *idev = platform_get_drvdata(pdev);
clk_disable_unprepare(idev->i2c_clk);
i2c_del_adapter(&idev->adapter);
-
- return 0;
}
/* Match table for of_platform binding */
@@ -484,7 +482,7 @@ MODULE_DEVICE_TABLE(of, altr_i2c_of_match);
static struct platform_driver altr_i2c_driver = {
.probe = altr_i2c_probe,
- .remove = altr_i2c_remove,
+ .remove_new = altr_i2c_remove,
.driver = {
.name = "altera-i2c",
.of_match_table = altr_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-amd-mp2-plat.c b/drivers/i2c/busses/i2c-amd-mp2-plat.c
index 423fe0c8a471..112fe2bc5662 100644
--- a/drivers/i2c/busses/i2c-amd-mp2-plat.c
+++ b/drivers/i2c/busses/i2c-amd-mp2-plat.c
@@ -322,7 +322,7 @@ static int i2c_amd_probe(struct platform_device *pdev)
return ret;
}
-static int i2c_amd_remove(struct platform_device *pdev)
+static void i2c_amd_remove(struct platform_device *pdev)
{
struct amd_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
struct amd_i2c_common *i2c_common = &i2c_dev->common;
@@ -336,7 +336,6 @@ static int i2c_amd_remove(struct platform_device *pdev)
i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
i2c_del_adapter(&i2c_dev->adap);
- return 0;
}
static const struct acpi_device_id i2c_amd_acpi_match[] = {
@@ -347,7 +346,7 @@ MODULE_DEVICE_TABLE(acpi, i2c_amd_acpi_match);
static struct platform_driver i2c_amd_plat_driver = {
.probe = i2c_amd_probe,
- .remove = i2c_amd_remove,
+ .remove_new = i2c_amd_remove,
.driver = {
.name = "i2c_amd_mp2",
.acpi_match_table = ACPI_PTR(i2c_amd_acpi_match),
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index d3c99c5b3247..2e5acfeb76c8 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -1061,7 +1061,7 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
return 0;
}
-static int aspeed_i2c_remove_bus(struct platform_device *pdev)
+static void aspeed_i2c_remove_bus(struct platform_device *pdev)
{
struct aspeed_i2c_bus *bus = platform_get_drvdata(pdev);
unsigned long flags;
@@ -1077,13 +1077,11 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev)
reset_control_assert(bus->rst);
i2c_del_adapter(&bus->adap);
-
- return 0;
}
static struct platform_driver aspeed_i2c_bus_driver = {
.probe = aspeed_i2c_probe_bus,
- .remove = aspeed_i2c_remove_bus,
+ .remove_new = aspeed_i2c_remove_bus,
.driver = {
.name = "aspeed-i2c-bus",
.of_match_table = aspeed_i2c_bus_of_table,
diff --git a/drivers/i2c/busses/i2c-at91-core.c b/drivers/i2c/busses/i2c-at91-core.c
index 2df9df585131..05ad3bc3578a 100644
--- a/drivers/i2c/busses/i2c-at91-core.c
+++ b/drivers/i2c/busses/i2c-at91-core.c
@@ -273,7 +273,7 @@ static int at91_twi_probe(struct platform_device *pdev)
return 0;
}
-static int at91_twi_remove(struct platform_device *pdev)
+static void at91_twi_remove(struct platform_device *pdev)
{
struct at91_twi_dev *dev = platform_get_drvdata(pdev);
@@ -282,8 +282,6 @@ static int at91_twi_remove(struct platform_device *pdev)
pm_runtime_disable(dev->dev);
pm_runtime_set_suspended(dev->dev);
-
- return 0;
}
static int __maybe_unused at91_twi_runtime_suspend(struct device *dev)
@@ -342,7 +340,7 @@ static const struct dev_pm_ops __maybe_unused at91_twi_pm = {
static struct platform_driver at91_twi_driver = {
.probe = at91_twi_probe,
- .remove = at91_twi_remove,
+ .remove_new = at91_twi_remove,
.id_table = at91_twi_devtypes,
.driver = {
.name = "at91_i2c",
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index 7b42d35b1294..e66c12ecf270 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -334,13 +334,12 @@ i2c_au1550_probe(struct platform_device *pdev)
return 0;
}
-static int i2c_au1550_remove(struct platform_device *pdev)
+static void i2c_au1550_remove(struct platform_device *pdev)
{
struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
i2c_del_adapter(&priv->adap);
i2c_au1550_disable(priv);
- return 0;
}
#ifdef CONFIG_PM
@@ -379,7 +378,7 @@ static struct platform_driver au1xpsc_smbus_driver = {
.pm = AU1XPSC_SMBUS_PMOPS,
},
.probe = i2c_au1550_probe,
- .remove = i2c_au1550_remove,
+ .remove_new = i2c_au1550_remove,
};
module_platform_driver(au1xpsc_smbus_driver);
diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c
index c1c74ce08407..d7f1e98777ac 100644
--- a/drivers/i2c/busses/i2c-axxia.c
+++ b/drivers/i2c/busses/i2c-axxia.c
@@ -804,14 +804,12 @@ error_disable_clk:
return ret;
}
-static int axxia_i2c_remove(struct platform_device *pdev)
+static void axxia_i2c_remove(struct platform_device *pdev)
{
struct axxia_i2c_dev *idev = platform_get_drvdata(pdev);
clk_disable_unprepare(idev->i2c_clk);
i2c_del_adapter(&idev->adapter);
-
- return 0;
}
/* Match table for of_platform binding */
@@ -824,7 +822,7 @@ MODULE_DEVICE_TABLE(of, axxia_i2c_of_match);
static struct platform_driver axxia_i2c_driver = {
.probe = axxia_i2c_probe,
- .remove = axxia_i2c_remove,
+ .remove_new = axxia_i2c_remove,
.driver = {
.name = "axxia-i2c",
.of_match_table = axxia_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c
index 85d8a6b04885..2d8342fdc25d 100644
--- a/drivers/i2c/busses/i2c-bcm-iproc.c
+++ b/drivers/i2c/busses/i2c-bcm-iproc.c
@@ -1107,7 +1107,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev)
return i2c_add_adapter(adap);
}
-static int bcm_iproc_i2c_remove(struct platform_device *pdev)
+static void bcm_iproc_i2c_remove(struct platform_device *pdev)
{
struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev);
@@ -1123,8 +1123,6 @@ static int bcm_iproc_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&iproc_i2c->adapter);
bcm_iproc_i2c_enable_disable(iproc_i2c, false);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1260,7 +1258,7 @@ static struct platform_driver bcm_iproc_i2c_driver = {
.pm = BCM_IPROC_I2C_PM_OPS,
},
.probe = bcm_iproc_i2c_probe,
- .remove = bcm_iproc_i2c_remove,
+ .remove_new = bcm_iproc_i2c_remove,
};
module_platform_driver(bcm_iproc_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c
index f3e369f0fd40..a57088ec2b06 100644
--- a/drivers/i2c/busses/i2c-bcm-kona.c
+++ b/drivers/i2c/busses/i2c-bcm-kona.c
@@ -859,13 +859,11 @@ probe_disable_clk:
return rc;
}
-static int bcm_kona_i2c_remove(struct platform_device *pdev)
+static void bcm_kona_i2c_remove(struct platform_device *pdev)
{
struct bcm_kona_i2c_dev *dev = platform_get_drvdata(pdev);
i2c_del_adapter(&dev->adapter);
-
- return 0;
}
static const struct of_device_id bcm_kona_i2c_of_match[] = {
@@ -880,7 +878,7 @@ static struct platform_driver bcm_kona_i2c_driver = {
.of_match_table = bcm_kona_i2c_of_match,
},
.probe = bcm_kona_i2c_probe,
- .remove = bcm_kona_i2c_remove,
+ .remove_new = bcm_kona_i2c_remove,
};
module_platform_driver(bcm_kona_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
index 09a077b31bfe..8ce6d3f49551 100644
--- a/drivers/i2c/busses/i2c-bcm2835.c
+++ b/drivers/i2c/busses/i2c-bcm2835.c
@@ -503,7 +503,7 @@ err_put_exclusive_rate:
return ret;
}
-static int bcm2835_i2c_remove(struct platform_device *pdev)
+static void bcm2835_i2c_remove(struct platform_device *pdev)
{
struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
@@ -512,8 +512,6 @@ static int bcm2835_i2c_remove(struct platform_device *pdev)
free_irq(i2c_dev->irq, i2c_dev);
i2c_del_adapter(&i2c_dev->adapter);
-
- return 0;
}
static const struct of_device_id bcm2835_i2c_of_match[] = {
@@ -525,7 +523,7 @@ MODULE_DEVICE_TABLE(of, bcm2835_i2c_of_match);
static struct platform_driver bcm2835_i2c_driver = {
.probe = bcm2835_i2c_probe,
- .remove = bcm2835_i2c_remove,
+ .remove_new = bcm2835_i2c_remove,
.driver = {
.name = "i2c-bcm2835",
.of_match_table = bcm2835_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
index ef942714642a..cf92cbcb8c86 100644
--- a/drivers/i2c/busses/i2c-brcmstb.c
+++ b/drivers/i2c/busses/i2c-brcmstb.c
@@ -690,12 +690,11 @@ probe_errorout:
return rc;
}
-static int brcmstb_i2c_remove(struct platform_device *pdev)
+static void brcmstb_i2c_remove(struct platform_device *pdev)
{
struct brcmstb_i2c_dev *dev = platform_get_drvdata(pdev);
i2c_del_adapter(&dev->adapter);
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -736,7 +735,7 @@ static struct platform_driver brcmstb_i2c_driver = {
.pm = &brcmstb_i2c_pm,
},
.probe = brcmstb_i2c_probe,
- .remove = brcmstb_i2c_remove,
+ .remove_new = brcmstb_i2c_remove,
};
module_platform_driver(brcmstb_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
index 3a4edf7e75f9..9849f4502570 100644
--- a/drivers/i2c/busses/i2c-cadence.c
+++ b/drivers/i2c/busses/i2c-cadence.c
@@ -1415,7 +1415,7 @@ err_clk_dis:
*
* Return: 0 always
*/
-static int cdns_i2c_remove(struct platform_device *pdev)
+static void cdns_i2c_remove(struct platform_device *pdev)
{
struct cdns_i2c *id = platform_get_drvdata(pdev);
@@ -1427,8 +1427,6 @@ static int cdns_i2c_remove(struct platform_device *pdev)
clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
reset_control_assert(id->reset);
clk_disable_unprepare(id->clk);
-
- return 0;
}
static struct platform_driver cdns_i2c_drv = {
@@ -1438,7 +1436,7 @@ static struct platform_driver cdns_i2c_drv = {
.pm = &cdns_i2c_dev_pm_ops,
},
.probe = cdns_i2c_probe,
- .remove = cdns_i2c_remove,
+ .remove_new = cdns_i2c_remove,
};
module_platform_driver(cdns_i2c_drv);
diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c
index d97c61eec95c..fdc1758a3275 100644
--- a/drivers/i2c/busses/i2c-cbus-gpio.c
+++ b/drivers/i2c/busses/i2c-cbus-gpio.c
@@ -200,13 +200,11 @@ static const struct i2c_algorithm cbus_i2c_algo = {
.functionality = cbus_i2c_func,
};
-static int cbus_i2c_remove(struct platform_device *pdev)
+static void cbus_i2c_remove(struct platform_device *pdev)
{
struct i2c_adapter *adapter = platform_get_drvdata(pdev);
i2c_del_adapter(adapter);
-
- return 0;
}
static int cbus_i2c_probe(struct platform_device *pdev)
@@ -266,7 +264,7 @@ MODULE_DEVICE_TABLE(of, i2c_cbus_dt_ids);
static struct platform_driver cbus_i2c_driver = {
.probe = cbus_i2c_probe,
- .remove = cbus_i2c_remove,
+ .remove_new = cbus_i2c_remove,
.driver = {
.name = "i2c-cbus-gpio",
.of_match_table = of_match_ptr(i2c_cbus_dt_ids),
diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c
index 2b2c3d090089..0209933b9a84 100644
--- a/drivers/i2c/busses/i2c-cht-wc.c
+++ b/drivers/i2c/busses/i2c-cht-wc.c
@@ -529,15 +529,13 @@ remove_irq_domain:
return ret;
}
-static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev)
+static void cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev)
{
struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev);
i2c_unregister_device(adap->client);
i2c_del_adapter(&adap->adapter);
irq_domain_remove(adap->irq_domain);
-
- return 0;
}
static const struct platform_device_id cht_wc_i2c_adap_id_table[] = {
@@ -548,7 +546,7 @@ MODULE_DEVICE_TABLE(platform, cht_wc_i2c_adap_id_table);
static struct platform_driver cht_wc_i2c_adap_driver = {
.probe = cht_wc_i2c_adap_i2c_probe,
- .remove = cht_wc_i2c_adap_i2c_remove,
+ .remove_new = cht_wc_i2c_adap_i2c_remove,
.driver = {
.name = "cht_wcove_ext_chgr",
},
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index 24d584a1c9a7..732daf6a932b 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -676,7 +676,7 @@ out_free:
return result;
}
-static int cpm_i2c_remove(struct platform_device *ofdev)
+static void cpm_i2c_remove(struct platform_device *ofdev)
{
struct cpm_i2c *cpm = platform_get_drvdata(ofdev);
@@ -685,8 +685,6 @@ static int cpm_i2c_remove(struct platform_device *ofdev)
cpm_i2c_shutdown(cpm);
kfree(cpm);
-
- return 0;
}
static const struct of_device_id cpm_i2c_match[] = {
@@ -703,7 +701,7 @@ MODULE_DEVICE_TABLE(of, cpm_i2c_match);
static struct platform_driver cpm_i2c_driver = {
.probe = cpm_i2c_probe,
- .remove = cpm_i2c_remove,
+ .remove_new = cpm_i2c_remove,
.driver = {
.name = "fsl-i2c-cpm",
.of_match_table = cpm_i2c_match,
diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
index 8b3ff5bb14d8..2737fd8abd32 100644
--- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
+++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
@@ -283,13 +283,11 @@ static int ec_i2c_probe(struct platform_device *pdev)
return err;
}
-static int ec_i2c_remove(struct platform_device *dev)
+static void ec_i2c_remove(struct platform_device *dev)
{
struct ec_i2c_device *bus = platform_get_drvdata(dev);
i2c_del_adapter(&bus->adap);
-
- return 0;
}
static const struct of_device_id cros_ec_i2c_of_match[] __maybe_unused = {
@@ -306,7 +304,7 @@ MODULE_DEVICE_TABLE(acpi, cros_ec_i2c_tunnel_acpi_id);
static struct platform_driver ec_i2c_tunnel_driver = {
.probe = ec_i2c_probe,
- .remove = ec_i2c_remove,
+ .remove_new = ec_i2c_remove,
.driver = {
.name = "cros-ec-i2c-tunnel",
.acpi_match_table = ACPI_PTR(cros_ec_i2c_tunnel_acpi_id),
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 9750310f2c96..71b60778c643 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -767,12 +767,9 @@ static int davinci_i2c_probe(struct platform_device *pdev)
if (irq < 0)
return dev_err_probe(&pdev->dev, irq, "can't get irq resource\n");
- dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_i2c_dev),
- GFP_KERNEL);
- if (!dev) {
- dev_err(&pdev->dev, "Memory allocation failed\n");
+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
return -ENOMEM;
- }
init_completion(&dev->cmd_complete);
@@ -885,7 +882,7 @@ err_pm:
return r;
}
-static int davinci_i2c_remove(struct platform_device *pdev)
+static void davinci_i2c_remove(struct platform_device *pdev)
{
struct davinci_i2c_dev *dev = platform_get_drvdata(pdev);
int ret;
@@ -894,17 +891,15 @@ static int davinci_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&dev->adapter);
- ret = pm_runtime_resume_and_get(&pdev->dev);
+ ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0)
- return ret;
-
- davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0);
+ dev_err(&pdev->dev, "Failed to resume device\n");
+ else
+ davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0);
pm_runtime_dont_use_autosuspend(dev->dev);
pm_runtime_put_sync(dev->dev);
pm_runtime_disable(dev->dev);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -940,12 +935,16 @@ static const struct dev_pm_ops davinci_i2c_pm = {
#define davinci_i2c_pm_ops NULL
#endif
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:i2c_davinci");
+static const struct platform_device_id davinci_i2c_driver_ids[] = {
+ { .name = "i2c_davinci", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, davinci_i2c_driver_ids);
static struct platform_driver davinci_i2c_driver = {
.probe = davinci_i2c_probe,
- .remove = davinci_i2c_remove,
+ .remove_new = davinci_i2c_remove,
+ .id_table = davinci_i2c_driver_ids,
.driver = {
.name = "i2c_davinci",
.pm = davinci_i2c_pm_ops,
diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c
index 0dc6b1ce663f..cdd8c67d9129 100644
--- a/drivers/i2c/busses/i2c-designware-common.c
+++ b/drivers/i2c/busses/i2c-designware-common.c
@@ -575,6 +575,14 @@ int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
unsigned int param;
int ret;
+ /* DW_IC_COMP_PARAM_1 not implement for IP issue */
+ if ((dev->flags & MODEL_MASK) == MODEL_WANGXUN_SP) {
+ dev->tx_fifo_depth = TXGBE_TX_FIFO_DEPTH;
+ dev->rx_fifo_depth = TXGBE_RX_FIFO_DEPTH;
+
+ return 0;
+ }
+
/*
* Try to detect the FIFO depth if not set by interface driver,
* the depth could be from 2 to 256 from HW spec.
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index bf23bfb51aea..cf4f684f5356 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -304,6 +304,7 @@ struct dw_i2c_dev {
#define MODEL_MSCC_OCELOT BIT(8)
#define MODEL_BAIKAL_BT1 BIT(9)
#define MODEL_AMD_NAVI_GPU BIT(10)
+#define MODEL_WANGXUN_SP BIT(11)
#define MODEL_MASK GENMASK(11, 8)
/*
@@ -313,6 +314,9 @@ struct dw_i2c_dev {
#define AMD_UCSI_INTR_REG 0x474
#define AMD_UCSI_INTR_EN 0xd
+#define TXGBE_TX_FIFO_DEPTH 4
+#define TXGBE_RX_FIFO_DEPTH 0
+
struct i2c_dw_semaphore_callbacks {
int (*probe)(struct dw_i2c_dev *dev);
void (*remove)(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index 55ea91a63382..3bfd7a2232db 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -354,6 +354,68 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs,
return 0;
}
+static int i2c_dw_poll_tx_empty(struct dw_i2c_dev *dev)
+{
+ u32 val;
+
+ return regmap_read_poll_timeout(dev->map, DW_IC_RAW_INTR_STAT, val,
+ val & DW_IC_INTR_TX_EMPTY,
+ 100, 1000);
+}
+
+static int i2c_dw_poll_rx_full(struct dw_i2c_dev *dev)
+{
+ u32 val;
+
+ return regmap_read_poll_timeout(dev->map, DW_IC_RAW_INTR_STAT, val,
+ val & DW_IC_INTR_RX_FULL,
+ 100, 1000);
+}
+
+static int txgbe_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num_msgs)
+{
+ struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+ int msg_idx, buf_len, data_idx, ret;
+ unsigned int val, stop = 0;
+ u8 *buf;
+
+ dev->msgs = msgs;
+ dev->msgs_num = num_msgs;
+ i2c_dw_xfer_init(dev);
+ regmap_write(dev->map, DW_IC_INTR_MASK, 0);
+
+ for (msg_idx = 0; msg_idx < num_msgs; msg_idx++) {
+ buf = msgs[msg_idx].buf;
+ buf_len = msgs[msg_idx].len;
+
+ for (data_idx = 0; data_idx < buf_len; data_idx++) {
+ if (msg_idx == num_msgs - 1 && data_idx == buf_len - 1)
+ stop |= BIT(9);
+
+ if (msgs[msg_idx].flags & I2C_M_RD) {
+ regmap_write(dev->map, DW_IC_DATA_CMD, 0x100 | stop);
+
+ ret = i2c_dw_poll_rx_full(dev);
+ if (ret)
+ return ret;
+
+ regmap_read(dev->map, DW_IC_DATA_CMD, &val);
+ buf[data_idx] = val;
+ } else {
+ ret = i2c_dw_poll_tx_empty(dev);
+ if (ret)
+ return ret;
+
+ regmap_write(dev->map, DW_IC_DATA_CMD,
+ buf[data_idx] | stop);
+ }
+ }
+ }
+
+ return num_msgs;
+}
+
/*
* Initiate (and continue) low level master read/write transaction.
* This function is only called from i2c_dw_isr, and pumping i2c_msg
@@ -559,13 +621,19 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
pm_runtime_get_sync(dev->dev);
/*
- * Initiate I2C message transfer when AMD NAVI GPU card is enabled,
+ * Initiate I2C message transfer when polling mode is enabled,
* As it is polling based transfer mechanism, which does not support
* interrupt based functionalities of existing DesignWare driver.
*/
- if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) {
+ switch (dev->flags & MODEL_MASK) {
+ case MODEL_AMD_NAVI_GPU:
ret = amd_i2c_dw_xfer_quirk(adap, msgs, num);
goto done_nolock;
+ case MODEL_WANGXUN_SP:
+ ret = txgbe_i2c_dw_xfer_quirk(adap, msgs, num);
+ goto done_nolock;
+ default:
+ break;
}
reinit_completion(&dev->cmd_complete);
@@ -848,7 +916,7 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
return 0;
}
-static int amd_i2c_adap_quirk(struct dw_i2c_dev *dev)
+static int i2c_dw_poll_adap_quirk(struct dw_i2c_dev *dev)
{
struct i2c_adapter *adap = &dev->adapter;
int ret;
@@ -862,6 +930,17 @@ static int amd_i2c_adap_quirk(struct dw_i2c_dev *dev)
return ret;
}
+static bool i2c_dw_is_model_poll(struct dw_i2c_dev *dev)
+{
+ switch (dev->flags & MODEL_MASK) {
+ case MODEL_AMD_NAVI_GPU:
+ case MODEL_WANGXUN_SP:
+ return true;
+ default:
+ return false;
+ }
+}
+
int i2c_dw_probe_master(struct dw_i2c_dev *dev)
{
struct i2c_adapter *adap = &dev->adapter;
@@ -917,8 +996,8 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
adap->dev.parent = dev->dev;
i2c_set_adapdata(adap, dev);
- if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU)
- return amd_i2c_adap_quirk(dev);
+ if (i2c_dw_is_model_poll(dev))
+ return i2c_dw_poll_adap_quirk(dev);
if (dev->flags & ACCESS_NO_IRQ_SUSPEND) {
irq_flags = IRQF_NO_SUSPEND;
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 782fe1ef3ca1..61d7a27aa070 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pm_runtime.h>
+#include <linux/power_supply.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -234,6 +235,16 @@ static const struct dev_pm_ops i2c_dw_pm_ops = {
SET_RUNTIME_PM_OPS(i2c_dw_pci_runtime_suspend, i2c_dw_pci_runtime_resume, NULL)
};
+static const struct property_entry dgpu_properties[] = {
+ /* USB-C doesn't power the system */
+ PROPERTY_ENTRY_U8("scope", POWER_SUPPLY_SCOPE_DEVICE),
+ {}
+};
+
+static const struct software_node dgpu_node = {
+ .properties = dgpu_properties,
+};
+
static int i2c_dw_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@@ -325,7 +336,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
}
if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) {
- dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, NULL);
+ dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, &dgpu_node);
if (IS_ERR(dev->slave))
return dev_err_probe(dev->dev, PTR_ERR(dev->slave),
"register UCSI failed\n");
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 89ad88c54754..970c1c3b0402 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -168,6 +168,15 @@ static inline int dw_i2c_of_configure(struct platform_device *pdev)
}
#endif
+static int txgbe_i2c_request_regs(struct dw_i2c_dev *dev)
+{
+ dev->map = dev_get_regmap(dev->dev->parent, NULL);
+ if (!dev->map)
+ return -ENODEV;
+
+ return 0;
+}
+
static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev)
{
pm_runtime_disable(dev->dev);
@@ -185,6 +194,9 @@ static int dw_i2c_plat_request_regs(struct dw_i2c_dev *dev)
case MODEL_BAIKAL_BT1:
ret = bt1_i2c_request_regs(dev);
break;
+ case MODEL_WANGXUN_SP:
+ ret = txgbe_i2c_request_regs(dev);
+ break;
default:
dev->base = devm_platform_ioremap_resource(pdev, 0);
ret = PTR_ERR_OR_ZERO(dev->base);
@@ -277,6 +289,9 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
return -ENOMEM;
dev->flags = (uintptr_t)device_get_match_data(&pdev->dev);
+ if (device_property_present(&pdev->dev, "wx,i2c-snps-model"))
+ dev->flags = MODEL_WANGXUN_SP;
+
dev->dev = &pdev->dev;
dev->irq = irq;
platform_set_drvdata(pdev, dev);
@@ -384,7 +399,7 @@ exit_reset:
return ret;
}
-static int dw_i2c_plat_remove(struct platform_device *pdev)
+static void dw_i2c_plat_remove(struct platform_device *pdev)
{
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
@@ -401,8 +416,6 @@ static int dw_i2c_plat_remove(struct platform_device *pdev)
i2c_dw_remove_lock_support(dev);
reset_control_assert(dev->rst);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -481,7 +494,7 @@ MODULE_ALIAS("platform:i2c_designware");
static struct platform_driver dw_i2c_driver = {
.probe = dw_i2c_plat_probe,
- .remove = dw_i2c_plat_remove,
+ .remove_new = dw_i2c_plat_remove,
.driver = {
.name = "i2c_designware",
.of_match_table = of_match_ptr(dw_i2c_of_match),
diff --git a/drivers/i2c/busses/i2c-digicolor.c b/drivers/i2c/busses/i2c-digicolor.c
index 50925d97fa42..3462f2bc0fa8 100644
--- a/drivers/i2c/busses/i2c-digicolor.c
+++ b/drivers/i2c/busses/i2c-digicolor.c
@@ -347,14 +347,12 @@ static int dc_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int dc_i2c_remove(struct platform_device *pdev)
+static void dc_i2c_remove(struct platform_device *pdev)
{
struct dc_i2c *i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c->adap);
clk_disable_unprepare(i2c->clk);
-
- return 0;
}
static const struct of_device_id dc_i2c_match[] = {
@@ -365,7 +363,7 @@ MODULE_DEVICE_TABLE(of, dc_i2c_match);
static struct platform_driver dc_i2c_driver = {
.probe = dc_i2c_probe,
- .remove = dc_i2c_remove,
+ .remove_new = dc_i2c_remove,
.driver = {
.name = "digicolor-i2c",
.of_match_table = dc_i2c_match,
diff --git a/drivers/i2c/busses/i2c-dln2.c b/drivers/i2c/busses/i2c-dln2.c
index 2a2089db71a5..4f02cc2fb567 100644
--- a/drivers/i2c/busses/i2c-dln2.c
+++ b/drivers/i2c/busses/i2c-dln2.c
@@ -236,20 +236,18 @@ out_disable:
return ret;
}
-static int dln2_i2c_remove(struct platform_device *pdev)
+static void dln2_i2c_remove(struct platform_device *pdev)
{
struct dln2_i2c *dln2 = platform_get_drvdata(pdev);
i2c_del_adapter(&dln2->adapter);
dln2_i2c_enable(dln2, false);
-
- return 0;
}
static struct platform_driver dln2_i2c_driver = {
.driver.name = "dln2-i2c",
.probe = dln2_i2c_probe,
- .remove = dln2_i2c_remove,
+ .remove_new = dln2_i2c_remove,
};
module_platform_driver(dln2_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c
index f2e537b137b2..4ba93cd91c0f 100644
--- a/drivers/i2c/busses/i2c-emev2.c
+++ b/drivers/i2c/busses/i2c-emev2.c
@@ -419,14 +419,12 @@ err_clk:
return ret;
}
-static int em_i2c_remove(struct platform_device *dev)
+static void em_i2c_remove(struct platform_device *dev)
{
struct em_i2c_device *priv = platform_get_drvdata(dev);
i2c_del_adapter(&priv->adap);
clk_disable_unprepare(priv->sclk);
-
- return 0;
}
static const struct of_device_id em_i2c_ids[] = {
@@ -436,7 +434,7 @@ static const struct of_device_id em_i2c_ids[] = {
static struct platform_driver em_i2c_driver = {
.probe = em_i2c_probe,
- .remove = em_i2c_remove,
+ .remove_new = em_i2c_remove,
.driver = {
.name = "em-i2c",
.of_match_table = em_i2c_ids,
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
index 4a6260d04db2..f378cd479e55 100644
--- a/drivers/i2c/busses/i2c-exynos5.c
+++ b/drivers/i2c/busses/i2c-exynos5.c
@@ -882,7 +882,7 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
return ret;
}
-static int exynos5_i2c_remove(struct platform_device *pdev)
+static void exynos5_i2c_remove(struct platform_device *pdev)
{
struct exynos5_i2c *i2c = platform_get_drvdata(pdev);
@@ -890,8 +890,6 @@ static int exynos5_i2c_remove(struct platform_device *pdev)
clk_unprepare(i2c->clk);
clk_unprepare(i2c->pclk);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -945,7 +943,7 @@ static const struct dev_pm_ops exynos5_i2c_dev_pm_ops = {
static struct platform_driver exynos5_i2c_driver = {
.probe = exynos5_i2c_probe,
- .remove = exynos5_i2c_remove,
+ .remove_new = exynos5_i2c_remove,
.driver = {
.name = "exynos5-hsi2c",
.pm = &exynos5_i2c_dev_pm_ops,
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index 1794c0399f22..e5a5b9e8bf2c 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -475,7 +475,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)
return 0;
}
-static int i2c_gpio_remove(struct platform_device *pdev)
+static void i2c_gpio_remove(struct platform_device *pdev)
{
struct i2c_gpio_private_data *priv;
struct i2c_adapter *adap;
@@ -486,8 +486,6 @@ static int i2c_gpio_remove(struct platform_device *pdev)
adap = &priv->adap;
i2c_del_adapter(adap);
-
- return 0;
}
static const struct of_device_id i2c_gpio_dt_ids[] = {
@@ -510,7 +508,7 @@ static struct platform_driver i2c_gpio_driver = {
.acpi_match_table = i2c_gpio_acpi_match,
},
.probe = i2c_gpio_probe,
- .remove = i2c_gpio_remove,
+ .remove_new = i2c_gpio_remove,
};
static int __init i2c_gpio_init(void)
diff --git a/drivers/i2c/busses/i2c-gxp.c b/drivers/i2c/busses/i2c-gxp.c
index 8ea3fb5e4c7f..70b0de07ed99 100644
--- a/drivers/i2c/busses/i2c-gxp.c
+++ b/drivers/i2c/busses/i2c-gxp.c
@@ -577,15 +577,13 @@ static int gxp_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int gxp_i2c_remove(struct platform_device *pdev)
+static void gxp_i2c_remove(struct platform_device *pdev)
{
struct gxp_i2c_drvdata *drvdata = platform_get_drvdata(pdev);
/* Disable interrupt */
regmap_update_bits(i2cg_map, GXP_I2CINTEN, BIT(drvdata->engine), 0);
i2c_del_adapter(&drvdata->adapter);
-
- return 0;
}
static const struct of_device_id gxp_i2c_of_match[] = {
@@ -596,7 +594,7 @@ MODULE_DEVICE_TABLE(of, gxp_i2c_of_match);
static struct platform_driver gxp_i2c_driver = {
.probe = gxp_i2c_probe,
- .remove = gxp_i2c_remove,
+ .remove_new = gxp_i2c_remove,
.driver = {
.name = "gxp-i2c",
.of_match_table = gxp_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
index 4374a8677271..7922bc917c33 100644
--- a/drivers/i2c/busses/i2c-highlander.c
+++ b/drivers/i2c/busses/i2c-highlander.c
@@ -435,7 +435,7 @@ err:
return ret;
}
-static int highlander_i2c_remove(struct platform_device *pdev)
+static void highlander_i2c_remove(struct platform_device *pdev)
{
struct highlander_i2c_dev *dev = platform_get_drvdata(pdev);
@@ -446,8 +446,6 @@ static int highlander_i2c_remove(struct platform_device *pdev)
iounmap(dev->base);
kfree(dev);
-
- return 0;
}
static struct platform_driver highlander_i2c_driver = {
@@ -456,7 +454,7 @@ static struct platform_driver highlander_i2c_driver = {
},
.probe = highlander_i2c_probe,
- .remove = highlander_i2c_remove,
+ .remove_new = highlander_i2c_remove,
};
module_platform_driver(highlander_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c
index 0e34cbaca22d..784a5f56eb76 100644
--- a/drivers/i2c/busses/i2c-hix5hd2.c
+++ b/drivers/i2c/busses/i2c-hix5hd2.c
@@ -360,7 +360,11 @@ static int hix5hd2_i2c_xfer(struct i2c_adapter *adap,
pm_runtime_get_sync(priv->dev);
for (i = 0; i < num; i++, msgs++) {
- stop = (i == num - 1);
+ if ((i == num - 1) || (msgs->flags & I2C_M_STOP))
+ stop = 1;
+ else
+ stop = 0;
+
ret = hix5hd2_i2c_xfer_msg(priv, msgs, stop);
if (ret < 0)
goto out;
@@ -416,12 +420,11 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- priv->clk = devm_clk_get(&pdev->dev, NULL);
+ priv->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(priv->clk)) {
- dev_err(&pdev->dev, "cannot get clock\n");
+ dev_err(&pdev->dev, "cannot enable clock\n");
return PTR_ERR(priv->clk);
}
- clk_prepare_enable(priv->clk);
strscpy(priv->adap.name, "hix5hd2-i2c", sizeof(priv->adap.name));
priv->dev = &pdev->dev;
@@ -442,7 +445,7 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
IRQF_NO_SUSPEND, dev_name(&pdev->dev), priv);
if (ret != 0) {
dev_err(&pdev->dev, "cannot request HS-I2C IRQ %d\n", irq);
- goto err_clk;
+ return ret;
}
pm_runtime_set_autosuspend_delay(priv->dev, MSEC_PER_SEC);
@@ -459,21 +462,17 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
err_runtime:
pm_runtime_disable(priv->dev);
pm_runtime_set_suspended(priv->dev);
-err_clk:
- clk_disable_unprepare(priv->clk);
+
return ret;
}
-static int hix5hd2_i2c_remove(struct platform_device *pdev)
+static void hix5hd2_i2c_remove(struct platform_device *pdev)
{
struct hix5hd2_i2c_priv *priv = platform_get_drvdata(pdev);
i2c_del_adapter(&priv->adap);
pm_runtime_disable(priv->dev);
pm_runtime_set_suspended(priv->dev);
- clk_disable_unprepare(priv->clk);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -511,7 +510,7 @@ MODULE_DEVICE_TABLE(of, hix5hd2_i2c_match);
static struct platform_driver hix5hd2_i2c_driver = {
.probe = hix5hd2_i2c_probe,
- .remove = hix5hd2_i2c_remove,
+ .remove_new = hix5hd2_i2c_remove,
.driver = {
.name = "hix5hd2-i2c",
.pm = &hix5hd2_i2c_pm_ops,
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index ac5326747c51..943b8e6d026d 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -77,6 +77,8 @@
* Alder Lake-M (PCH) 0x54a3 32 hard yes yes yes
* Raptor Lake-S (PCH) 0x7a23 32 hard yes yes yes
* Meteor Lake-P (SOC) 0x7e22 32 hard yes yes yes
+ * Meteor Lake SoC-S (SOC) 0xae22 32 hard yes yes yes
+ * Meteor Lake PCH-S (PCH) 0x7f23 32 hard yes yes yes
*
* Features supported by this driver:
* Software PEC no
@@ -233,6 +235,7 @@
#define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_S_SMBUS 0x7a23
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3
#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_P_SMBUS 0x7e22
+#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_PCH_S_SMBUS 0x7f23
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22
#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS 0x8ca2
#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS 0x8d22
@@ -250,6 +253,7 @@
#define PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS 0xa2a3
#define PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS 0xa323
#define PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS 0xa3a3
+#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_SOC_S_SMBUS 0xae22
struct i801_mux_config {
char *gpio_chip;
@@ -977,67 +981,69 @@ static const struct i2c_algorithm smbus_algorithm = {
FEATURE_HOST_NOTIFY)
static const struct pci_device_id i801_ids[] = {
- { PCI_DEVICE_DATA(INTEL, 82801AA_3, 0) },
- { PCI_DEVICE_DATA(INTEL, 82801AB_3, 0) },
- { PCI_DEVICE_DATA(INTEL, 82801BA_2, 0) },
- { PCI_DEVICE_DATA(INTEL, 82801CA_3, FEATURE_HOST_NOTIFY) },
- { PCI_DEVICE_DATA(INTEL, 82801DB_3, FEATURES_ICH4) },
- { PCI_DEVICE_DATA(INTEL, 82801EB_3, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, ESB_4, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, ICH6_16, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, ICH7_17, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, ESB2_17, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, ICH8_5, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, ICH9_6, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, EP80579_1, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, ICH10_4, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, ICH10_5, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, 5_3400_SERIES_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, COUGARPOINT_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF0, FEATURES_ICH5 | FEATURE_IDF) },
- { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF1, FEATURES_ICH5 | FEATURE_IDF) },
- { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF2, FEATURES_ICH5 | FEATURE_IDF) },
- { PCI_DEVICE_DATA(INTEL, DH89XXCC_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, PANTHERPOINT_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, LYNXPOINT_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, LYNXPOINT_LP_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, AVOTON_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS0, FEATURES_ICH5 | FEATURE_IDF) },
- { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS1, FEATURES_ICH5 | FEATURE_IDF) },
- { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS2, FEATURES_ICH5 | FEATURE_IDF) },
- { PCI_DEVICE_DATA(INTEL, COLETOCREEK_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, GEMINILAKE_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_LP_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, BAYTRAIL_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, BRASWELL_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
- { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
- { PCI_DEVICE_DATA(INTEL, CDF_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, DNV_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
- { PCI_DEVICE_DATA(INTEL, EBG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, BROXTON_SMBUS, FEATURES_ICH5) },
- { PCI_DEVICE_DATA(INTEL, LEWISBURG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
- { PCI_DEVICE_DATA(INTEL, LEWISBURG_SSKU_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
- { PCI_DEVICE_DATA(INTEL, KABYLAKE_PCH_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
- { PCI_DEVICE_DATA(INTEL, CANNONLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, CANNONLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, ICELAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, ICELAKE_N_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, COMETLAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, COMETLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, COMETLAKE_V_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
- { PCI_DEVICE_DATA(INTEL, ELKHART_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, TIGERLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, TIGERLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, JASPER_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_M_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, RAPTOR_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
- { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, 82801AA_3, 0) },
+ { PCI_DEVICE_DATA(INTEL, 82801AB_3, 0) },
+ { PCI_DEVICE_DATA(INTEL, 82801BA_2, 0) },
+ { PCI_DEVICE_DATA(INTEL, 82801CA_3, FEATURE_HOST_NOTIFY) },
+ { PCI_DEVICE_DATA(INTEL, 82801DB_3, FEATURES_ICH4) },
+ { PCI_DEVICE_DATA(INTEL, 82801EB_3, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, ESB_4, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, ICH6_16, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, ICH7_17, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, ESB2_17, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, ICH8_5, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, ICH9_6, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, EP80579_1, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, ICH10_4, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, ICH10_5, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, 5_3400_SERIES_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, COUGARPOINT_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF0, FEATURES_ICH5 | FEATURE_IDF) },
+ { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF1, FEATURES_ICH5 | FEATURE_IDF) },
+ { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF2, FEATURES_ICH5 | FEATURE_IDF) },
+ { PCI_DEVICE_DATA(INTEL, DH89XXCC_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, PANTHERPOINT_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, LYNXPOINT_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, LYNXPOINT_LP_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, AVOTON_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS0, FEATURES_ICH5 | FEATURE_IDF) },
+ { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS1, FEATURES_ICH5 | FEATURE_IDF) },
+ { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS2, FEATURES_ICH5 | FEATURE_IDF) },
+ { PCI_DEVICE_DATA(INTEL, COLETOCREEK_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, GEMINILAKE_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_LP_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, BAYTRAIL_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, BRASWELL_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
+ { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
+ { PCI_DEVICE_DATA(INTEL, CDF_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, DNV_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
+ { PCI_DEVICE_DATA(INTEL, EBG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, BROXTON_SMBUS, FEATURES_ICH5) },
+ { PCI_DEVICE_DATA(INTEL, LEWISBURG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
+ { PCI_DEVICE_DATA(INTEL, LEWISBURG_SSKU_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
+ { PCI_DEVICE_DATA(INTEL, KABYLAKE_PCH_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
+ { PCI_DEVICE_DATA(INTEL, CANNONLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, CANNONLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, ICELAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, ICELAKE_N_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, COMETLAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, COMETLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, COMETLAKE_V_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) },
+ { PCI_DEVICE_DATA(INTEL, ELKHART_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, TIGERLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, TIGERLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, JASPER_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_M_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, RAPTOR_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_SOC_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_PCH_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index eeb80e34f9ad..1ad9d3b26dd3 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -694,10 +694,8 @@ static int iic_probe(struct platform_device *ofdev)
int ret;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev) {
- dev_err(&ofdev->dev, "failed to allocate device data\n");
+ if (!dev)
return -ENOMEM;
- }
platform_set_drvdata(ofdev, dev);
@@ -769,7 +767,7 @@ error_cleanup:
/*
* Cleanup initialized IIC interface
*/
-static int iic_remove(struct platform_device *ofdev)
+static void iic_remove(struct platform_device *ofdev)
{
struct ibm_iic_private *dev = platform_get_drvdata(ofdev);
@@ -782,8 +780,6 @@ static int iic_remove(struct platform_device *ofdev)
iounmap(dev->vaddr);
kfree(dev);
-
- return 0;
}
static const struct of_device_id ibm_iic_match[] = {
@@ -798,7 +794,7 @@ static struct platform_driver ibm_iic_driver = {
.of_match_table = ibm_iic_match,
},
.probe = iic_probe,
- .remove = iic_remove,
+ .remove_new = iic_remove,
};
module_platform_driver(ibm_iic_driver);
diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c
index 39c479f96eb5..66ba36949ab5 100644
--- a/drivers/i2c/busses/i2c-img-scb.c
+++ b/drivers/i2c/busses/i2c-img-scb.c
@@ -913,7 +913,7 @@ static unsigned int img_i2c_auto(struct img_i2c *i2c,
static irqreturn_t img_i2c_isr(int irq, void *dev_id)
{
- struct img_i2c *i2c = (struct img_i2c *)dev_id;
+ struct img_i2c *i2c = dev_id;
u32 int_status, line_status;
/* We handle transaction completion AFTER accessing registers */
unsigned int hret;
@@ -1413,7 +1413,7 @@ rpm_disable:
return ret;
}
-static int img_i2c_remove(struct platform_device *dev)
+static void img_i2c_remove(struct platform_device *dev)
{
struct img_i2c *i2c = platform_get_drvdata(dev);
@@ -1421,8 +1421,6 @@ static int img_i2c_remove(struct platform_device *dev)
pm_runtime_disable(&dev->dev);
if (!pm_runtime_status_suspended(&dev->dev))
img_i2c_runtime_suspend(&dev->dev);
-
- return 0;
}
static int img_i2c_runtime_suspend(struct device *dev)
@@ -1506,7 +1504,7 @@ static struct platform_driver img_scb_i2c_driver = {
.pm = &img_i2c_pm,
},
.probe = img_i2c_probe,
- .remove = img_i2c_remove,
+ .remove_new = img_i2c_remove,
};
module_platform_driver(img_scb_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 4d24ceb57ee7..c3287c887c6f 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -217,7 +217,7 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
for (prescale = 0; prescale <= 7; prescale++) {
clk_cycle = clk_rate / ((1 << prescale) * lpi2c_imx->bitrate)
- 3 - (filt >> 1);
- clkhi = (clk_cycle + I2C_CLK_RATIO) / (I2C_CLK_RATIO + 1);
+ clkhi = DIV_ROUND_UP(clk_cycle, I2C_CLK_RATIO + 1);
clklo = clk_cycle - clkhi;
if (clklo < 64)
break;
@@ -623,7 +623,7 @@ rpm_disable:
return ret;
}
-static int lpi2c_imx_remove(struct platform_device *pdev)
+static void lpi2c_imx_remove(struct platform_device *pdev)
{
struct lpi2c_imx_struct *lpi2c_imx = platform_get_drvdata(pdev);
@@ -631,8 +631,6 @@ static int lpi2c_imx_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
-
- return 0;
}
static int __maybe_unused lpi2c_runtime_suspend(struct device *dev)
@@ -669,7 +667,7 @@ static const struct dev_pm_ops lpi2c_pm_ops = {
static struct platform_driver lpi2c_imx_driver = {
.probe = lpi2c_imx_probe,
- .remove = lpi2c_imx_remove,
+ .remove_new = lpi2c_imx_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = lpi2c_imx_of_match,
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 42189a5f2905..65128a73e8a3 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1561,7 +1561,7 @@ rpm_disable:
return ret;
}
-static int i2c_imx_remove(struct platform_device *pdev)
+static void i2c_imx_remove(struct platform_device *pdev)
{
struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
int irq, ret;
@@ -1592,8 +1592,6 @@ static int i2c_imx_remove(struct platform_device *pdev)
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
static int __maybe_unused i2c_imx_runtime_suspend(struct device *dev)
@@ -1624,7 +1622,7 @@ static const struct dev_pm_ops i2c_imx_pm_ops = {
static struct platform_driver i2c_imx_driver = {
.probe = i2c_imx_probe,
- .remove = i2c_imx_remove,
+ .remove_new = i2c_imx_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &i2c_imx_pm_ops,
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 4a6ff54d87fe..f2f7ebeeaecb 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -388,7 +388,7 @@ static const struct i2c_algorithm iop3xx_i2c_algo = {
.functionality = iop3xx_i2c_func,
};
-static int
+static void
iop3xx_i2c_remove(struct platform_device *pdev)
{
struct i2c_adapter *padapter = platform_get_drvdata(pdev);
@@ -408,8 +408,6 @@ iop3xx_i2c_remove(struct platform_device *pdev)
release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
kfree(adapter_data);
kfree(padapter);
-
- return 0;
}
static int
@@ -529,7 +527,7 @@ MODULE_DEVICE_TABLE(of, i2c_iop3xx_match);
static struct platform_driver iop3xx_i2c_driver = {
.probe = iop3xx_i2c_probe,
- .remove = iop3xx_i2c_remove,
+ .remove_new = iop3xx_i2c_remove,
.driver = {
.name = "IOP3xx-I2C",
.of_match_table = i2c_iop3xx_match,
diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
index 2dc7ada06ac5..1dc1ceaa4443 100644
--- a/drivers/i2c/busses/i2c-isch.c
+++ b/drivers/i2c/busses/i2c-isch.c
@@ -286,14 +286,12 @@ static int smbus_sch_probe(struct platform_device *dev)
return retval;
}
-static int smbus_sch_remove(struct platform_device *pdev)
+static void smbus_sch_remove(struct platform_device *pdev)
{
if (sch_smba) {
i2c_del_adapter(&sch_adapter);
sch_smba = 0;
}
-
- return 0;
}
static struct platform_driver smbus_sch_driver = {
@@ -301,7 +299,7 @@ static struct platform_driver smbus_sch_driver = {
.name = "isch_smbus",
},
.probe = smbus_sch_probe,
- .remove = smbus_sch_remove,
+ .remove_new = smbus_sch_remove,
};
module_platform_driver(smbus_sch_driver);
diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c
index baa7319eee53..0dfe60399521 100644
--- a/drivers/i2c/busses/i2c-jz4780.c
+++ b/drivers/i2c/busses/i2c-jz4780.c
@@ -845,18 +845,17 @@ err:
return ret;
}
-static int jz4780_i2c_remove(struct platform_device *pdev)
+static void jz4780_i2c_remove(struct platform_device *pdev)
{
struct jz4780_i2c *i2c = platform_get_drvdata(pdev);
clk_disable_unprepare(i2c->clk);
i2c_del_adapter(&i2c->adap);
- return 0;
}
static struct platform_driver jz4780_i2c_driver = {
.probe = jz4780_i2c_probe,
- .remove = jz4780_i2c_remove,
+ .remove_new = jz4780_i2c_remove,
.driver = {
.name = "jz4780-i2c",
.of_match_table = jz4780_i2c_of_matches,
diff --git a/drivers/i2c/busses/i2c-kempld.c b/drivers/i2c/busses/i2c-kempld.c
index cf857cf22507..281058e3ea46 100644
--- a/drivers/i2c/busses/i2c-kempld.c
+++ b/drivers/i2c/busses/i2c-kempld.c
@@ -329,7 +329,7 @@ static int kempld_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int kempld_i2c_remove(struct platform_device *pdev)
+static void kempld_i2c_remove(struct platform_device *pdev)
{
struct kempld_i2c_data *i2c = platform_get_drvdata(pdev);
struct kempld_device_data *pld = i2c->pld;
@@ -348,8 +348,6 @@ static int kempld_i2c_remove(struct platform_device *pdev)
kempld_release_mutex(pld);
i2c_del_adapter(&i2c->adap);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -389,7 +387,7 @@ static struct platform_driver kempld_i2c_driver = {
.name = "kempld-i2c",
},
.probe = kempld_i2c_probe,
- .remove = kempld_i2c_remove,
+ .remove_new = kempld_i2c_remove,
.suspend = kempld_i2c_suspend,
.resume = kempld_i2c_resume,
};
diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c
index 8fff6fbb7065..5c6d96554753 100644
--- a/drivers/i2c/busses/i2c-lpc2k.c
+++ b/drivers/i2c/busses/i2c-lpc2k.c
@@ -365,23 +365,17 @@ static int i2c_lpc2k_probe(struct platform_device *pdev)
init_waitqueue_head(&i2c->wait);
- i2c->clk = devm_clk_get(&pdev->dev, NULL);
+ i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(i2c->clk)) {
- dev_err(&pdev->dev, "error getting clock\n");
+ dev_err(&pdev->dev, "failed to enable clock.\n");
return PTR_ERR(i2c->clk);
}
- ret = clk_prepare_enable(i2c->clk);
- if (ret) {
- dev_err(&pdev->dev, "unable to enable clock.\n");
- return ret;
- }
-
ret = devm_request_irq(&pdev->dev, i2c->irq, i2c_lpc2k_handler, 0,
dev_name(&pdev->dev), i2c);
if (ret < 0) {
dev_err(&pdev->dev, "can't request interrupt.\n");
- goto fail_clk;
+ return ret;
}
disable_irq_nosync(i2c->irq);
@@ -397,8 +391,7 @@ static int i2c_lpc2k_probe(struct platform_device *pdev)
clkrate = clk_get_rate(i2c->clk);
if (clkrate == 0) {
dev_err(&pdev->dev, "can't get I2C base clock\n");
- ret = -EINVAL;
- goto fail_clk;
+ return -EINVAL;
}
/* Setup I2C dividers to generate clock with proper duty cycle */
@@ -424,25 +417,18 @@ static int i2c_lpc2k_probe(struct platform_device *pdev)
ret = i2c_add_adapter(&i2c->adap);
if (ret < 0)
- goto fail_clk;
+ return ret;
dev_info(&pdev->dev, "LPC2K I2C adapter\n");
return 0;
-
-fail_clk:
- clk_disable_unprepare(i2c->clk);
- return ret;
}
-static int i2c_lpc2k_remove(struct platform_device *dev)
+static void i2c_lpc2k_remove(struct platform_device *dev)
{
struct lpc2k_i2c *i2c = platform_get_drvdata(dev);
i2c_del_adapter(&i2c->adap);
- clk_disable_unprepare(i2c->clk);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -483,7 +469,7 @@ MODULE_DEVICE_TABLE(of, lpc2k_i2c_match);
static struct platform_driver i2c_lpc2k_driver = {
.probe = i2c_lpc2k_probe,
- .remove = i2c_lpc2k_remove,
+ .remove_new = i2c_lpc2k_remove,
.driver = {
.name = "lpc2k-i2c",
.pm = I2C_LPC2K_DEV_PM_OPS,
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 889eff06b78f..16026c895bb6 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -535,14 +535,12 @@ static int meson_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int meson_i2c_remove(struct platform_device *pdev)
+static void meson_i2c_remove(struct platform_device *pdev)
{
struct meson_i2c *i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c->adap);
clk_disable_unprepare(i2c->clk);
-
- return 0;
}
static const struct meson_i2c_data i2c_meson6_data = {
@@ -568,7 +566,7 @@ MODULE_DEVICE_TABLE(of, meson_i2c_match);
static struct platform_driver meson_i2c_driver = {
.probe = meson_i2c_probe,
- .remove = meson_i2c_remove,
+ .remove_new = meson_i2c_remove,
.driver = {
.name = "meson-i2c",
.of_match_table = meson_i2c_match,
diff --git a/drivers/i2c/busses/i2c-microchip-corei2c.c b/drivers/i2c/busses/i2c-microchip-corei2c.c
index 4d7e9b25f018..7f58f7eaabb6 100644
--- a/drivers/i2c/busses/i2c-microchip-corei2c.c
+++ b/drivers/i2c/busses/i2c-microchip-corei2c.c
@@ -446,14 +446,12 @@ static int mchp_corei2c_probe(struct platform_device *pdev)
return 0;
}
-static int mchp_corei2c_remove(struct platform_device *pdev)
+static void mchp_corei2c_remove(struct platform_device *pdev)
{
struct mchp_corei2c_dev *idev = platform_get_drvdata(pdev);
clk_disable_unprepare(idev->i2c_clk);
i2c_del_adapter(&idev->adapter);
-
- return 0;
}
static const struct of_device_id mchp_corei2c_of_match[] = {
@@ -465,7 +463,7 @@ MODULE_DEVICE_TABLE(of, mchp_corei2c_of_match);
static struct platform_driver mchp_corei2c_driver = {
.probe = mchp_corei2c_probe,
- .remove = mchp_corei2c_remove,
+ .remove_new = mchp_corei2c_remove,
.driver = {
.name = "microchip-corei2c",
.of_match_table = mchp_corei2c_of_match,
diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c
index 1810d5791b3d..ae66bdd1b737 100644
--- a/drivers/i2c/busses/i2c-mlxbf.c
+++ b/drivers/i2c/busses/i2c-mlxbf.c
@@ -2433,7 +2433,7 @@ static int mlxbf_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int mlxbf_i2c_remove(struct platform_device *pdev)
+static void mlxbf_i2c_remove(struct platform_device *pdev)
{
struct mlxbf_i2c_priv *priv = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
@@ -2474,13 +2474,11 @@ static int mlxbf_i2c_remove(struct platform_device *pdev)
devm_free_irq(dev, priv->irq, priv);
i2c_del_adapter(&priv->adap);
-
- return 0;
}
static struct platform_driver mlxbf_i2c_driver = {
.probe = mlxbf_i2c_probe,
- .remove = mlxbf_i2c_remove,
+ .remove_new = mlxbf_i2c_remove,
.driver = {
.name = "i2c-mlxbf",
.acpi_match_table = ACPI_PTR(mlxbf_i2c_acpi_ids),
diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c
index 081f51ef0551..c42fd4b329e4 100644
--- a/drivers/i2c/busses/i2c-mlxcpld.c
+++ b/drivers/i2c/busses/i2c-mlxcpld.c
@@ -571,19 +571,17 @@ mlxcpld_i2_probe_failed:
return err;
}
-static int mlxcpld_i2c_remove(struct platform_device *pdev)
+static void mlxcpld_i2c_remove(struct platform_device *pdev)
{
struct mlxcpld_i2c_priv *priv = platform_get_drvdata(pdev);
i2c_del_adapter(&priv->adap);
mutex_destroy(&priv->lock);
-
- return 0;
}
static struct platform_driver mlxcpld_i2c_driver = {
.probe = mlxcpld_i2c_probe,
- .remove = mlxcpld_i2c_remove,
+ .remove_new = mlxcpld_i2c_remove,
.driver = {
.name = MLXCPLD_I2C_DEVICE_NAME,
},
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index cfd074ee6d54..fb1b640f33b7 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -316,9 +316,10 @@ static void mpc_i2c_setup_512x(struct device_node *node,
if (node_ctrl) {
ctrl = of_iomap(node_ctrl, 0);
if (ctrl) {
+ u64 addr;
/* Interrupt enable bits for i2c-0/1/2: bit 24/26/28 */
- pval = of_get_property(node, "reg", NULL);
- idx = (*pval & 0xff) / 0x20;
+ of_property_read_reg(node, 0, &addr, NULL);
+ idx = (addr & 0xff) / 0x20;
setbits32(ctrl, 1 << (24 + idx * 2));
iounmap(ctrl);
}
@@ -890,15 +891,13 @@ static int fsl_i2c_probe(struct platform_device *op)
return result;
};
-static int fsl_i2c_remove(struct platform_device *op)
+static void fsl_i2c_remove(struct platform_device *op)
{
struct mpc_i2c *i2c = platform_get_drvdata(op);
i2c_del_adapter(&i2c->adap);
clk_disable_unprepare(i2c->clk_per);
-
- return 0;
};
static int __maybe_unused mpc_i2c_suspend(struct device *dev)
@@ -959,7 +958,7 @@ MODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
/* Structure for a device driver */
static struct platform_driver mpc_i2c_driver = {
.probe = fsl_i2c_probe,
- .remove = fsl_i2c_remove,
+ .remove_new = fsl_i2c_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = mpc_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index a43c4d77739a..7ca3f2221ba6 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -1505,15 +1505,13 @@ err_bulk_unprepare:
return ret;
}
-static int mtk_i2c_remove(struct platform_device *pdev)
+static void mtk_i2c_remove(struct platform_device *pdev)
{
struct mtk_i2c *i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c->adap);
clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1555,7 +1553,7 @@ static const struct dev_pm_ops mtk_i2c_pm = {
static struct platform_driver mtk_i2c_driver = {
.probe = mtk_i2c_probe,
- .remove = mtk_i2c_remove,
+ .remove_new = mtk_i2c_remove,
.driver = {
.name = I2C_DRV_NAME,
.pm = &mtk_i2c_pm,
diff --git a/drivers/i2c/busses/i2c-mt7621.c b/drivers/i2c/busses/i2c-mt7621.c
index 20eda5738ac4..104bb194e990 100644
--- a/drivers/i2c/busses/i2c-mt7621.c
+++ b/drivers/i2c/busses/i2c-mt7621.c
@@ -282,16 +282,11 @@ static int mtk_i2c_probe(struct platform_device *pdev)
if (IS_ERR(i2c->base))
return PTR_ERR(i2c->base);
- i2c->clk = devm_clk_get(&pdev->dev, NULL);
+ i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(i2c->clk)) {
- dev_err(&pdev->dev, "no clock defined\n");
+ dev_err(&pdev->dev, "Failed to enable clock\n");
return PTR_ERR(i2c->clk);
}
- ret = clk_prepare_enable(i2c->clk);
- if (ret) {
- dev_err(&pdev->dev, "Unable to enable clock\n");
- return ret;
- }
i2c->dev = &pdev->dev;
@@ -301,8 +296,7 @@ static int mtk_i2c_probe(struct platform_device *pdev)
if (i2c->bus_freq == 0) {
dev_warn(i2c->dev, "clock-frequency 0 not supported\n");
- ret = -EINVAL;
- goto err_disable_clk;
+ return -EINVAL;
}
adap = &i2c->adap;
@@ -320,31 +314,23 @@ static int mtk_i2c_probe(struct platform_device *pdev)
ret = i2c_add_adapter(adap);
if (ret < 0)
- goto err_disable_clk;
+ return ret;
dev_info(&pdev->dev, "clock %u kHz\n", i2c->bus_freq / 1000);
return 0;
-
-err_disable_clk:
- clk_disable_unprepare(i2c->clk);
-
- return ret;
}
-static int mtk_i2c_remove(struct platform_device *pdev)
+static void mtk_i2c_remove(struct platform_device *pdev)
{
struct mtk_i2c *i2c = platform_get_drvdata(pdev);
- clk_disable_unprepare(i2c->clk);
i2c_del_adapter(&i2c->adap);
-
- return 0;
}
static struct platform_driver mtk_i2c_driver = {
.probe = mtk_i2c_probe,
- .remove = mtk_i2c_remove,
+ .remove_new = mtk_i2c_remove,
.driver = {
.name = "i2c-mt7621",
.of_match_table = i2c_mtk_dt_ids,
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 878c076ebdc6..fd8403b07fa6 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -1084,7 +1084,7 @@ exit_disable_pm:
return rc;
}
-static int
+static void
mv64xxx_i2c_remove(struct platform_device *pd)
{
struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(pd);
@@ -1094,8 +1094,6 @@ mv64xxx_i2c_remove(struct platform_device *pd)
pm_runtime_disable(&pd->dev);
if (!pm_runtime_status_suspended(&pd->dev))
mv64xxx_i2c_runtime_suspend(&pd->dev);
-
- return 0;
}
static const struct dev_pm_ops mv64xxx_i2c_pm_ops = {
@@ -1107,7 +1105,7 @@ static const struct dev_pm_ops mv64xxx_i2c_pm_ops = {
static struct platform_driver mv64xxx_i2c_driver = {
.probe = mv64xxx_i2c_probe,
- .remove = mv64xxx_i2c_remove,
+ .remove_new = mv64xxx_i2c_remove,
.driver = {
.name = MV64XXX_I2C_CTLR_NAME,
.pm = &mv64xxx_i2c_pm_ops,
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index e0f3b3545cfe..1d76f1c4dc06 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -864,7 +864,7 @@ static int mxs_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int mxs_i2c_remove(struct platform_device *pdev)
+static void mxs_i2c_remove(struct platform_device *pdev)
{
struct mxs_i2c_dev *i2c = platform_get_drvdata(pdev);
@@ -874,8 +874,6 @@ static int mxs_i2c_remove(struct platform_device *pdev)
dma_release_channel(i2c->dmach);
writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET);
-
- return 0;
}
static struct platform_driver mxs_i2c_driver = {
@@ -884,7 +882,7 @@ static struct platform_driver mxs_i2c_driver = {
.of_match_table = mxs_i2c_dt_ids,
},
.probe = mxs_i2c_probe,
- .remove = mxs_i2c_remove,
+ .remove_new = mxs_i2c_remove,
};
static int __init mxs_i2c_init(void)
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index a2d12a5b1c34..1e5fd23ef45c 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -970,12 +970,10 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
struct i2c_vendor_data *vendor = id->data;
u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1;
- dev = devm_kzalloc(&adev->dev, sizeof(struct nmk_i2c_dev), GFP_KERNEL);
- if (!dev) {
- dev_err(&adev->dev, "cannot allocate memory\n");
- ret = -ENOMEM;
- goto err_no_mem;
- }
+ dev = devm_kzalloc(&adev->dev, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
dev->vendor = vendor;
dev->adev = adev;
nmk_i2c_of_probe(np, dev);
@@ -996,31 +994,20 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
dev->virtbase = devm_ioremap(&adev->dev, adev->res.start,
resource_size(&adev->res));
- if (!dev->virtbase) {
- ret = -ENOMEM;
- goto err_no_mem;
- }
+ if (!dev->virtbase)
+ return -ENOMEM;
dev->irq = adev->irq[0];
ret = devm_request_irq(&adev->dev, dev->irq, i2c_irq_handler, 0,
DRIVER_NAME, dev);
- if (ret) {
- dev_err(&adev->dev, "cannot claim the irq %d\n", dev->irq);
- goto err_no_mem;
- }
-
- dev->clk = devm_clk_get(&adev->dev, NULL);
- if (IS_ERR(dev->clk)) {
- dev_err(&adev->dev, "could not get i2c clock\n");
- ret = PTR_ERR(dev->clk);
- goto err_no_mem;
- }
+ if (ret)
+ return dev_err_probe(&adev->dev, ret,
+ "cannot claim the irq %d\n", dev->irq);
- ret = clk_prepare_enable(dev->clk);
- if (ret) {
- dev_err(&adev->dev, "can't prepare_enable clock\n");
- goto err_no_mem;
- }
+ dev->clk = devm_clk_get_enabled(&adev->dev, NULL);
+ if (IS_ERR(dev->clk))
+ return dev_err_probe(&adev->dev, PTR_ERR(dev->clk),
+ "could enable i2c clock\n");
init_hw(dev);
@@ -1042,17 +1029,11 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
ret = i2c_add_adapter(adap);
if (ret)
- goto err_no_adap;
+ return ret;
pm_runtime_put(&adev->dev);
return 0;
-
- err_no_adap:
- clk_disable_unprepare(dev->clk);
- err_no_mem:
-
- return ret;
}
static void nmk_i2c_remove(struct amba_device *adev)
@@ -1066,7 +1047,6 @@ static void nmk_i2c_remove(struct amba_device *adev)
clear_all_interrupts(dev);
/* disable the controller */
i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE);
- clk_disable_unprepare(dev->clk);
release_mem_region(res->start, resource_size(res));
}
diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c
index 38d5864d0cb5..53b65ffb6a64 100644
--- a/drivers/i2c/busses/i2c-npcm7xx.c
+++ b/drivers/i2c/busses/i2c-npcm7xx.c
@@ -2361,7 +2361,7 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
return 0;
}
-static int npcm_i2c_remove_bus(struct platform_device *pdev)
+static void npcm_i2c_remove_bus(struct platform_device *pdev)
{
unsigned long lock_flags;
struct npcm_i2c *bus = platform_get_drvdata(pdev);
@@ -2371,7 +2371,6 @@ static int npcm_i2c_remove_bus(struct platform_device *pdev)
npcm_i2c_disable(bus);
spin_unlock_irqrestore(&bus->lock, lock_flags);
i2c_del_adapter(&bus->adap);
- return 0;
}
static const struct of_device_id npcm_i2c_bus_of_table[] = {
@@ -2383,7 +2382,7 @@ MODULE_DEVICE_TABLE(of, npcm_i2c_bus_of_table);
static struct platform_driver npcm_i2c_bus_driver = {
.probe = npcm_i2c_probe_bus,
- .remove = npcm_i2c_remove_bus,
+ .remove_new = npcm_i2c_remove_bus,
.driver = {
.name = "nuvoton-i2c",
.of_match_table = npcm_i2c_bus_of_table,
diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c
index a8b99e7f6262..26622d24bb1b 100644
--- a/drivers/i2c/busses/i2c-nvidia-gpu.c
+++ b/drivers/i2c/busses/i2c-nvidia-gpu.c
@@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
+#include <linux/power_supply.h>
#include <asm/unaligned.h>
@@ -261,6 +262,8 @@ MODULE_DEVICE_TABLE(pci, gpu_i2c_ids);
static const struct property_entry ccgx_props[] = {
/* Use FW built for NVIDIA GPU only */
PROPERTY_ENTRY_STRING("firmware-name", "nvidia,gpu"),
+ /* USB-C doesn't power the system */
+ PROPERTY_ENTRY_U8("scope", POWER_SUPPLY_SCOPE_DEVICE),
{ }
};
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 2e575856c5cd..4ac77e57bbbf 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -552,28 +552,20 @@ static int ocores_i2c_of_probe(struct platform_device *pdev,
&clock_frequency);
i2c->bus_clock_khz = 100;
- i2c->clk = devm_clk_get(&pdev->dev, NULL);
-
- if (!IS_ERR(i2c->clk)) {
- int ret = clk_prepare_enable(i2c->clk);
-
- if (ret) {
- dev_err(&pdev->dev,
- "clk_prepare_enable failed: %d\n", ret);
- return ret;
- }
- i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000;
- if (clock_frequency_present)
- i2c->bus_clock_khz = clock_frequency / 1000;
- }
-
+ i2c->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
+ if (IS_ERR(i2c->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk),
+ "devm_clk_get_optional_enabled failed\n");
+
+ i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000;
+ if (clock_frequency_present)
+ i2c->bus_clock_khz = clock_frequency / 1000;
if (i2c->ip_clock_khz == 0) {
if (of_property_read_u32(np, "opencores,ip-clock-frequency",
&val)) {
if (!clock_frequency_present) {
dev_err(&pdev->dev,
"Missing required parameter 'opencores,ip-clock-frequency'\n");
- clk_disable_unprepare(i2c->clk);
return -ENODEV;
}
i2c->ip_clock_khz = clock_frequency / 1000;
@@ -678,8 +670,7 @@ static int ocores_i2c_probe(struct platform_device *pdev)
default:
dev_err(&pdev->dev, "Unsupported I/O width (%d)\n",
i2c->reg_io_width);
- ret = -EINVAL;
- goto err_clk;
+ return -EINVAL;
}
}
@@ -710,13 +701,13 @@ static int ocores_i2c_probe(struct platform_device *pdev)
pdev->name, i2c);
if (ret) {
dev_err(&pdev->dev, "Cannot claim IRQ\n");
- goto err_clk;
+ return ret;
}
}
ret = ocores_init(&pdev->dev, i2c);
if (ret)
- goto err_clk;
+ return ret;
/* hook up driver to tree */
platform_set_drvdata(pdev, i2c);
@@ -728,7 +719,7 @@ static int ocores_i2c_probe(struct platform_device *pdev)
/* add i2c adapter to i2c tree */
ret = i2c_add_adapter(&i2c->adap);
if (ret)
- goto err_clk;
+ return ret;
/* add in known devices to the bus */
if (pdata) {
@@ -737,13 +728,9 @@ static int ocores_i2c_probe(struct platform_device *pdev)
}
return 0;
-
-err_clk:
- clk_disable_unprepare(i2c->clk);
- return ret;
}
-static int ocores_i2c_remove(struct platform_device *pdev)
+static void ocores_i2c_remove(struct platform_device *pdev)
{
struct ocores_i2c *i2c = platform_get_drvdata(pdev);
u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
@@ -754,11 +741,6 @@ static int ocores_i2c_remove(struct platform_device *pdev)
/* remove adapter & data */
i2c_del_adapter(&i2c->adap);
-
- if (!IS_ERR(i2c->clk))
- clk_disable_unprepare(i2c->clk);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -771,28 +753,22 @@ static int ocores_i2c_suspend(struct device *dev)
ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN);
oc_setreg(i2c, OCI2C_CONTROL, ctrl);
- if (!IS_ERR(i2c->clk))
- clk_disable_unprepare(i2c->clk);
+ clk_disable_unprepare(i2c->clk);
return 0;
}
static int ocores_i2c_resume(struct device *dev)
{
struct ocores_i2c *i2c = dev_get_drvdata(dev);
+ unsigned long rate;
+ int ret;
- if (!IS_ERR(i2c->clk)) {
- unsigned long rate;
- int ret = clk_prepare_enable(i2c->clk);
-
- if (ret) {
- dev_err(dev,
- "clk_prepare_enable failed: %d\n", ret);
- return ret;
- }
- rate = clk_get_rate(i2c->clk) / 1000;
- if (rate)
- i2c->ip_clock_khz = rate;
- }
+ ret = clk_prepare_enable(i2c->clk);
+ if (ret)
+ return dev_err_probe(dev, ret, "clk_prepare_enable failed\n");
+ rate = clk_get_rate(i2c->clk) / 1000;
+ if (rate)
+ i2c->ip_clock_khz = rate;
return ocores_init(dev, i2c);
}
@@ -804,7 +780,7 @@ static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume);
static struct platform_driver ocores_i2c_driver = {
.probe = ocores_i2c_probe,
- .remove = ocores_i2c_remove,
+ .remove_new = ocores_i2c_remove,
.driver = {
.name = "ocores-i2c",
.of_match_table = ocores_i2c_match,
diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c
index 0c227963c8d6..7d54b3203f71 100644
--- a/drivers/i2c/busses/i2c-octeon-platdrv.c
+++ b/drivers/i2c/busses/i2c-octeon-platdrv.c
@@ -253,12 +253,11 @@ out:
return result;
};
-static int octeon_i2c_remove(struct platform_device *pdev)
+static void octeon_i2c_remove(struct platform_device *pdev)
{
struct octeon_i2c *i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c->adap);
- return 0;
};
static const struct of_device_id octeon_i2c_match[] = {
@@ -270,7 +269,7 @@ MODULE_DEVICE_TABLE(of, octeon_i2c_match);
static struct platform_driver octeon_i2c_driver = {
.probe = octeon_i2c_probe,
- .remove = octeon_i2c_remove,
+ .remove_new = octeon_i2c_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = octeon_i2c_match,
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 4199f57a6bf2..58fd6fa3edf1 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1519,7 +1519,7 @@ err_disable_pm:
return r;
}
-static int omap_i2c_remove(struct platform_device *pdev)
+static void omap_i2c_remove(struct platform_device *pdev)
{
struct omap_i2c_dev *omap = platform_get_drvdata(pdev);
int ret;
@@ -1535,8 +1535,6 @@ static int omap_i2c_remove(struct platform_device *pdev)
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
static int __maybe_unused omap_i2c_runtime_suspend(struct device *dev)
@@ -1588,7 +1586,7 @@ static const struct dev_pm_ops omap_i2c_pm_ops = {
static struct platform_driver omap_i2c_driver = {
.probe = omap_i2c_probe,
- .remove = omap_i2c_remove,
+ .remove_new = omap_i2c_remove,
.driver = {
.name = "omap_i2c",
.pm = &omap_i2c_pm_ops,
diff --git a/drivers/i2c/busses/i2c-opal.c b/drivers/i2c/busses/i2c-opal.c
index 9f773b4f5ed8..17ef87d50f7c 100644
--- a/drivers/i2c/busses/i2c-opal.c
+++ b/drivers/i2c/busses/i2c-opal.c
@@ -232,13 +232,11 @@ static int i2c_opal_probe(struct platform_device *pdev)
return rc;
}
-static int i2c_opal_remove(struct platform_device *pdev)
+static void i2c_opal_remove(struct platform_device *pdev)
{
struct i2c_adapter *adapter = platform_get_drvdata(pdev);
i2c_del_adapter(adapter);
-
- return 0;
}
static const struct of_device_id i2c_opal_of_match[] = {
@@ -251,7 +249,7 @@ MODULE_DEVICE_TABLE(of, i2c_opal_of_match);
static struct platform_driver i2c_opal_driver = {
.probe = i2c_opal_probe,
- .remove = i2c_opal_remove,
+ .remove_new = i2c_opal_remove,
.driver = {
.name = "i2c-opal",
.of_match_table = i2c_opal_of_match,
diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c
index 99ddd8894964..5f0ef8c35141 100644
--- a/drivers/i2c/busses/i2c-owl.c
+++ b/drivers/i2c/busses/i2c-owl.c
@@ -461,21 +461,16 @@ static int owl_i2c_probe(struct platform_device *pdev)
return -EINVAL;
}
- i2c_dev->clk = devm_clk_get(dev, NULL);
+ i2c_dev->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(i2c_dev->clk)) {
- dev_err(dev, "failed to get clock\n");
+ dev_err(dev, "failed to enable clock\n");
return PTR_ERR(i2c_dev->clk);
}
- ret = clk_prepare_enable(i2c_dev->clk);
- if (ret)
- return ret;
-
i2c_dev->clk_rate = clk_get_rate(i2c_dev->clk);
if (!i2c_dev->clk_rate) {
dev_err(dev, "input clock rate should not be zero\n");
- ret = -EINVAL;
- goto disable_clk;
+ return -EINVAL;
}
init_completion(&i2c_dev->msg_complete);
@@ -496,15 +491,10 @@ static int owl_i2c_probe(struct platform_device *pdev)
i2c_dev);
if (ret) {
dev_err(dev, "failed to request irq %d\n", irq);
- goto disable_clk;
+ return ret;
}
return i2c_add_adapter(&i2c_dev->adap);
-
-disable_clk:
- clk_disable_unprepare(i2c_dev->clk);
-
- return ret;
}
static const struct of_device_id owl_i2c_of_match[] = {
diff --git a/drivers/i2c/busses/i2c-pasemi-platform.c b/drivers/i2c/busses/i2c-pasemi-platform.c
index e35945a91dbe..5fbfb9b41744 100644
--- a/drivers/i2c/busses/i2c-pasemi-platform.c
+++ b/drivers/i2c/busses/i2c-pasemi-platform.c
@@ -66,22 +66,18 @@ static int pasemi_platform_i2c_probe(struct platform_device *pdev)
if (of_property_read_u32(dev->of_node, "clock-frequency", &frequency))
frequency = I2C_MAX_STANDARD_MODE_FREQ;
- data->clk_ref = devm_clk_get(dev, NULL);
+ data->clk_ref = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(data->clk_ref))
return PTR_ERR(data->clk_ref);
- error = clk_prepare_enable(data->clk_ref);
- if (error)
- return error;
-
error = pasemi_platform_i2c_calc_clk_div(data, frequency);
if (error)
- goto out_clk_disable;
+ return error;
smbus->adapter.dev.of_node = pdev->dev.of_node;
error = pasemi_i2c_common_probe(smbus);
if (error)
- goto out_clk_disable;
+ return error;
irq_num = platform_get_irq(pdev, 0);
error = devm_request_irq(smbus->dev, irq_num, pasemi_irq_handler, 0, "pasemi_apple_i2c", (void *)smbus);
@@ -91,20 +87,9 @@ static int pasemi_platform_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
return 0;
-
-out_clk_disable:
- clk_disable_unprepare(data->clk_ref);
-
- return error;
}
-static int pasemi_platform_i2c_remove(struct platform_device *pdev)
-{
- struct pasemi_platform_i2c_data *data = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(data->clk_ref);
- return 0;
-}
+static void pasemi_platform_i2c_remove(struct platform_device *pdev) { }
static const struct of_device_id pasemi_platform_i2c_of_match[] = {
{ .compatible = "apple,t8103-i2c" },
@@ -119,7 +104,7 @@ static struct platform_driver pasemi_platform_i2c_driver = {
.of_match_table = pasemi_platform_i2c_of_match,
},
.probe = pasemi_platform_i2c_probe,
- .remove = pasemi_platform_i2c_remove,
+ .remove_new = pasemi_platform_i2c_remove,
};
module_platform_driver(pasemi_platform_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
index 86d4f75ef8d3..d2a9e7b61c1a 100644
--- a/drivers/i2c/busses/i2c-pca-platform.c
+++ b/drivers/i2c/busses/i2c-pca-platform.c
@@ -221,13 +221,11 @@ static int i2c_pca_pf_probe(struct platform_device *pdev)
return 0;
}
-static int i2c_pca_pf_remove(struct platform_device *pdev)
+static void i2c_pca_pf_remove(struct platform_device *pdev)
{
struct i2c_pca_pf_data *i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c->adap);
-
- return 0;
}
#ifdef CONFIG_OF
@@ -241,7 +239,7 @@ MODULE_DEVICE_TABLE(of, i2c_pca_of_match_table);
static struct platform_driver i2c_pca_pf_driver = {
.probe = i2c_pca_pf_probe,
- .remove = i2c_pca_pf_remove,
+ .remove_new = i2c_pca_pf_remove,
.driver = {
.name = "i2c-pca-platform",
.of_match_table = of_match_ptr(i2c_pca_of_match_table),
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index 50f21cdbe90d..82400057f810 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -743,14 +743,12 @@ out_clock:
return ret;
}
-static int i2c_pnx_remove(struct platform_device *pdev)
+static void i2c_pnx_remove(struct platform_device *pdev)
{
struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
i2c_del_adapter(&alg_data->adapter);
clk_disable_unprepare(alg_data->clk);
-
- return 0;
}
#ifdef CONFIG_OF
@@ -768,7 +766,7 @@ static struct platform_driver i2c_pnx_driver = {
.pm = PNX_I2C_PM,
},
.probe = i2c_pnx_probe,
- .remove = i2c_pnx_remove,
+ .remove_new = i2c_pnx_remove,
};
static int __init i2c_adap_pnx_init(void)
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index ec706a3aba26..4996a628fdae 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -188,14 +188,12 @@ static const struct i2c_adapter_quirks i2c_powermac_quirks = {
.max_num_msgs = 1,
};
-static int i2c_powermac_remove(struct platform_device *dev)
+static void i2c_powermac_remove(struct platform_device *dev)
{
struct i2c_adapter *adapter = platform_get_drvdata(dev);
i2c_del_adapter(adapter);
memset(adapter, 0, sizeof(*adapter));
-
- return 0;
}
static u32 i2c_powermac_get_addr(struct i2c_adapter *adap,
@@ -439,7 +437,7 @@ static int i2c_powermac_probe(struct platform_device *dev)
static struct platform_driver i2c_powermac_driver = {
.probe = i2c_powermac_probe,
- .remove = i2c_powermac_remove,
+ .remove_new = i2c_powermac_remove,
.driver = {
.name = "i2c-powermac",
.bus = &platform_bus_type,
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index f9fa5308556b..937f7eebe906 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -1482,15 +1482,13 @@ ereqirq:
return ret;
}
-static int i2c_pxa_remove(struct platform_device *dev)
+static void i2c_pxa_remove(struct platform_device *dev)
{
struct pxa_i2c *i2c = platform_get_drvdata(dev);
i2c_del_adapter(&i2c->adap);
clk_disable_unprepare(i2c->clk);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -1525,7 +1523,7 @@ static const struct dev_pm_ops i2c_pxa_dev_pm_ops = {
static struct platform_driver i2c_pxa_driver = {
.probe = i2c_pxa_probe,
- .remove = i2c_pxa_remove,
+ .remove_new = i2c_pxa_remove,
.driver = {
.name = "pxa2xx-i2c",
.pm = I2C_PXA_DEV_PM_OPS,
diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c
index 01358472680c..622dc14add9d 100644
--- a/drivers/i2c/busses/i2c-qcom-cci.c
+++ b/drivers/i2c/busses/i2c-qcom-cci.c
@@ -581,8 +581,7 @@ static int cci_probe(struct platform_device *pdev)
/* Memory */
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- cci->base = devm_ioremap_resource(dev, r);
+ cci->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
if (IS_ERR(cci->base))
return PTR_ERR(cci->base);
@@ -675,7 +674,7 @@ disable_clocks:
return ret;
}
-static int cci_remove(struct platform_device *pdev)
+static void cci_remove(struct platform_device *pdev)
{
struct cci *cci = platform_get_drvdata(pdev);
int i;
@@ -691,8 +690,6 @@ static int cci_remove(struct platform_device *pdev)
disable_irq(cci->irq);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
-
- return 0;
}
static const struct cci_data cci_v1_data = {
@@ -829,7 +826,7 @@ MODULE_DEVICE_TABLE(of, cci_dt_match);
static struct platform_driver qcom_cci_driver = {
.probe = cci_probe,
- .remove = cci_remove,
+ .remove_new = cci_remove,
.driver = {
.name = "i2c-qcom-cci",
.of_match_table = cci_dt_match,
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 83909b02a03e..b670a67c4fdd 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -936,14 +936,13 @@ err_dma:
return ret;
}
-static int geni_i2c_remove(struct platform_device *pdev)
+static void geni_i2c_remove(struct platform_device *pdev)
{
struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
i2c_del_adapter(&gi2c->adap);
release_gpi_dma(gi2c);
pm_runtime_disable(gi2c->se.dev);
- return 0;
}
static void geni_i2c_shutdown(struct platform_device *pdev)
@@ -1041,7 +1040,7 @@ MODULE_DEVICE_TABLE(of, geni_i2c_dt_match);
static struct platform_driver geni_i2c_driver = {
.probe = geni_i2c_probe,
- .remove = geni_i2c_remove,
+ .remove_new = geni_i2c_remove,
.shutdown = geni_i2c_shutdown,
.driver = {
.name = "geni_i2c",
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 78682388e02e..ae90170023b0 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1911,7 +1911,7 @@ fail_dma:
return ret;
}
-static int qup_i2c_remove(struct platform_device *pdev)
+static void qup_i2c_remove(struct platform_device *pdev)
{
struct qup_i2c_dev *qup = platform_get_drvdata(pdev);
@@ -1925,7 +1925,6 @@ static int qup_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&qup->adap);
pm_runtime_disable(qup->dev);
pm_runtime_set_suspended(qup->dev);
- return 0;
}
#ifdef CONFIG_PM
@@ -1985,7 +1984,7 @@ MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
static struct platform_driver qup_i2c_driver = {
.probe = qup_i2c_probe,
- .remove = qup_i2c_remove,
+ .remove_new = qup_i2c_remove,
.driver = {
.name = "i2c_qup",
.pm = &qup_i2c_qup_pm_ops,
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index cef82b205c26..2d9c37410ebd 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -1155,7 +1155,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
return ret;
}
-static int rcar_i2c_remove(struct platform_device *pdev)
+static void rcar_i2c_remove(struct platform_device *pdev)
{
struct rcar_i2c_priv *priv = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
@@ -1167,8 +1167,6 @@ static int rcar_i2c_remove(struct platform_device *pdev)
if (priv->flags & ID_P_PM_BLOCKED)
pm_runtime_put(dev);
pm_runtime_disable(dev);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1204,7 +1202,7 @@ static struct platform_driver rcar_i2c_driver = {
.pm = DEV_PM_OPS,
},
.probe = rcar_i2c_probe,
- .remove = rcar_i2c_remove,
+ .remove_new = rcar_i2c_remove,
};
module_platform_driver(rcar_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c
index 849848ccb080..5f8c0bd508d2 100644
--- a/drivers/i2c/busses/i2c-riic.c
+++ b/drivers/i2c/busses/i2c-riic.c
@@ -477,7 +477,7 @@ out:
return ret;
}
-static int riic_i2c_remove(struct platform_device *pdev)
+static void riic_i2c_remove(struct platform_device *pdev)
{
struct riic_dev *riic = platform_get_drvdata(pdev);
@@ -486,8 +486,6 @@ static int riic_i2c_remove(struct platform_device *pdev)
pm_runtime_put(&pdev->dev);
i2c_del_adapter(&riic->adapter);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
static const struct of_device_id riic_i2c_dt_ids[] = {
@@ -497,7 +495,7 @@ static const struct of_device_id riic_i2c_dt_ids[] = {
static struct platform_driver riic_i2c_driver = {
.probe = riic_i2c_probe,
- .remove = riic_i2c_remove,
+ .remove_new = riic_i2c_remove,
.driver = {
.name = "i2c-riic",
.of_match_table = riic_i2c_dt_ids,
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index b31cf4f18f85..a044ca0c35a1 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -1372,7 +1372,7 @@ err_clk:
return ret;
}
-static int rk3x_i2c_remove(struct platform_device *pdev)
+static void rk3x_i2c_remove(struct platform_device *pdev)
{
struct rk3x_i2c *i2c = platform_get_drvdata(pdev);
@@ -1381,15 +1381,13 @@ static int rk3x_i2c_remove(struct platform_device *pdev)
clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb);
clk_unprepare(i2c->pclk);
clk_unprepare(i2c->clk);
-
- return 0;
}
static SIMPLE_DEV_PM_OPS(rk3x_i2c_pm_ops, NULL, rk3x_i2c_resume);
static struct platform_driver rk3x_i2c_driver = {
.probe = rk3x_i2c_probe,
- .remove = rk3x_i2c_remove,
+ .remove_new = rk3x_i2c_remove,
.driver = {
.name = "rk3x-i2c",
.of_match_table = rk3x_i2c_match,
diff --git a/drivers/i2c/busses/i2c-rzv2m.c b/drivers/i2c/busses/i2c-rzv2m.c
index 56d0faee5c46..b0bfc96b9ede 100644
--- a/drivers/i2c/busses/i2c-rzv2m.c
+++ b/drivers/i2c/busses/i2c-rzv2m.c
@@ -50,9 +50,6 @@
#define IICB0MDSC BIT(7) /* Bus Mode */
#define IICB0SLSE BIT(1) /* Start condition output */
-#define bit_setl(addr, val) writel(readl(addr) | (val), (addr))
-#define bit_clrl(addr, val) writel(readl(addr) & ~(val), (addr))
-
struct rzv2m_i2c_priv {
void __iomem *base;
struct i2c_adapter adap;
@@ -78,6 +75,16 @@ static const struct bitrate_config bitrate_configs[] = {
[RZV2M_I2C_400K] = { 52, 900 },
};
+static inline void bit_setl(void __iomem *addr, u32 val)
+{
+ writel(readl(addr) | val, addr);
+}
+
+static inline void bit_clrl(void __iomem *addr, u32 val)
+{
+ writel(readl(addr) & ~val, addr);
+}
+
static irqreturn_t rzv2m_i2c_tia_irq_handler(int this_irq, void *dev_id)
{
struct rzv2m_i2c_priv *priv = dev_id;
@@ -382,6 +389,20 @@ static u32 rzv2m_i2c_func(struct i2c_adapter *adap)
I2C_FUNC_10BIT_ADDR;
}
+static int rzv2m_i2c_disable(struct device *dev, struct rzv2m_i2c_priv *priv)
+{
+ int ret;
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0)
+ return ret;
+
+ bit_clrl(priv->base + IICB0CTL0, IICB0IICE);
+ pm_runtime_put(dev);
+
+ return 0;
+}
+
static const struct i2c_adapter_quirks rzv2m_i2c_quirks = {
.flags = I2C_AQ_NO_ZERO_LEN,
};
@@ -454,37 +475,29 @@ static int rzv2m_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
ret = i2c_add_numbered_adapter(adap);
- if (ret < 0)
+ if (ret < 0) {
+ rzv2m_i2c_disable(dev, priv);
pm_runtime_disable(dev);
+ }
return ret;
}
-static int rzv2m_i2c_remove(struct platform_device *pdev)
+static void rzv2m_i2c_remove(struct platform_device *pdev)
{
struct rzv2m_i2c_priv *priv = platform_get_drvdata(pdev);
struct device *dev = priv->adap.dev.parent;
i2c_del_adapter(&priv->adap);
- bit_clrl(priv->base + IICB0CTL0, IICB0IICE);
+ rzv2m_i2c_disable(dev, priv);
pm_runtime_disable(dev);
-
- return 0;
}
static int rzv2m_i2c_suspend(struct device *dev)
{
struct rzv2m_i2c_priv *priv = dev_get_drvdata(dev);
- int ret;
- ret = pm_runtime_resume_and_get(dev);
- if (ret < 0)
- return ret;
-
- bit_clrl(priv->base + IICB0CTL0, IICB0IICE);
- pm_runtime_put(dev);
-
- return 0;
+ return rzv2m_i2c_disable(dev, priv);
}
static int rzv2m_i2c_resume(struct device *dev)
@@ -523,7 +536,7 @@ static struct platform_driver rzv2m_i2c_driver = {
.pm = pm_sleep_ptr(&rzv2m_i2c_pm_ops),
},
.probe = rzv2m_i2c_probe,
- .remove = rzv2m_i2c_remove,
+ .remove_new = rzv2m_i2c_remove,
};
module_platform_driver(rzv2m_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 45e9df81345a..28f0e5c64f32 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -1114,7 +1114,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int s3c24xx_i2c_remove(struct platform_device *pdev)
+static void s3c24xx_i2c_remove(struct platform_device *pdev)
{
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
@@ -1123,8 +1123,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
i2c_del_adapter(&i2c->adap);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1172,7 +1170,7 @@ static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
static struct platform_driver s3c24xx_i2c_driver = {
.probe = s3c24xx_i2c_probe,
- .remove = s3c24xx_i2c_remove,
+ .remove_new = s3c24xx_i2c_remove,
.id_table = s3c24xx_driver_ids,
.driver = {
.name = "s3c-i2c",
diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c
index 0239e134b90f..104570292241 100644
--- a/drivers/i2c/busses/i2c-scmi.c
+++ b/drivers/i2c/busses/i2c-scmi.c
@@ -404,19 +404,17 @@ err:
return ret;
}
-static int smbus_cmi_remove(struct platform_device *device)
+static void smbus_cmi_remove(struct platform_device *device)
{
struct acpi_smbus_cmi *smbus_cmi = platform_get_drvdata(device);
i2c_del_adapter(&smbus_cmi->adapter);
kfree(smbus_cmi);
-
- return 0;
}
static struct platform_driver smbus_cmi_driver = {
.probe = smbus_cmi_probe,
- .remove = smbus_cmi_remove,
+ .remove_new = smbus_cmi_remove,
.driver = {
.name = "smbus_cmi",
.acpi_match_table = acpi_smbus_cmi_ids,
diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
index 319d1fa617c8..1ad2a26156d1 100644
--- a/drivers/i2c/busses/i2c-sh7760.c
+++ b/drivers/i2c/busses/i2c-sh7760.c
@@ -443,9 +443,8 @@ static int sh7760_i2c_probe(struct platform_device *pdev)
goto out0;
}
- id = kzalloc(sizeof(struct cami2c), GFP_KERNEL);
+ id = kzalloc(sizeof(*id), GFP_KERNEL);
if (!id) {
- dev_err(&pdev->dev, "no mem for private data\n");
ret = -ENOMEM;
goto out0;
}
@@ -536,7 +535,7 @@ out0:
return ret;
}
-static int sh7760_i2c_remove(struct platform_device *pdev)
+static void sh7760_i2c_remove(struct platform_device *pdev)
{
struct cami2c *id = platform_get_drvdata(pdev);
@@ -546,8 +545,6 @@ static int sh7760_i2c_remove(struct platform_device *pdev)
release_resource(id->ioarea);
kfree(id->ioarea);
kfree(id);
-
- return 0;
}
static struct platform_driver sh7760_i2c_drv = {
@@ -555,7 +552,7 @@ static struct platform_driver sh7760_i2c_drv = {
.name = SH7760_I2C_DEVNAME,
},
.probe = sh7760_i2c_probe,
- .remove = sh7760_i2c_remove,
+ .remove_new = sh7760_i2c_remove,
};
module_platform_driver(sh7760_i2c_drv);
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 29330ee64c9c..21717b943a9e 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -956,14 +956,13 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
return 0;
}
-static int sh_mobile_i2c_remove(struct platform_device *dev)
+static void sh_mobile_i2c_remove(struct platform_device *dev)
{
struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
i2c_del_adapter(&pd->adap);
sh_mobile_i2c_release_dma(pd);
pm_runtime_disable(&dev->dev);
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1000,7 +999,7 @@ static struct platform_driver sh_mobile_i2c_driver = {
.pm = DEV_PM_OPS,
},
.probe = sh_mobile_i2c_probe,
- .remove = sh_mobile_i2c_remove,
+ .remove_new = sh_mobile_i2c_remove,
};
static int __init sh_mobile_i2c_adap_init(void)
diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c
index 87701744752f..18516bc64e04 100644
--- a/drivers/i2c/busses/i2c-simtec.c
+++ b/drivers/i2c/busses/i2c-simtec.c
@@ -126,7 +126,7 @@ static int simtec_i2c_probe(struct platform_device *dev)
return ret;
}
-static int simtec_i2c_remove(struct platform_device *dev)
+static void simtec_i2c_remove(struct platform_device *dev)
{
struct simtec_i2c_data *pd = platform_get_drvdata(dev);
@@ -135,8 +135,6 @@ static int simtec_i2c_remove(struct platform_device *dev)
iounmap(pd->reg);
release_mem_region(pd->ioarea->start, resource_size(pd->ioarea));
kfree(pd);
-
- return 0;
}
/* device driver */
@@ -146,7 +144,7 @@ static struct platform_driver simtec_i2c_driver = {
.name = "simtec-i2c",
},
.probe = simtec_i2c_probe,
- .remove = simtec_i2c_remove,
+ .remove_new = simtec_i2c_remove,
};
module_platform_driver(simtec_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c
index f823913b75a6..25c3521cae0e 100644
--- a/drivers/i2c/busses/i2c-st.c
+++ b/drivers/i2c/busses/i2c-st.c
@@ -876,13 +876,11 @@ static int st_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int st_i2c_remove(struct platform_device *pdev)
+static void st_i2c_remove(struct platform_device *pdev)
{
struct st_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c_dev->adap);
-
- return 0;
}
static const struct of_device_id st_i2c_match[] = {
@@ -899,7 +897,7 @@ static struct platform_driver st_i2c_driver = {
.pm = pm_sleep_ptr(&st_i2c_pm),
},
.probe = st_i2c_probe,
- .remove = st_i2c_remove,
+ .remove_new = st_i2c_remove,
};
module_platform_driver(st_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c
index eebce7ecef25..6ad06a5a22b4 100644
--- a/drivers/i2c/busses/i2c-stm32f4.c
+++ b/drivers/i2c/busses/i2c-stm32f4.c
@@ -861,15 +861,13 @@ clk_free:
return ret;
}
-static int stm32f4_i2c_remove(struct platform_device *pdev)
+static void stm32f4_i2c_remove(struct platform_device *pdev)
{
struct stm32f4_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c_dev->adap);
clk_unprepare(i2c_dev->clk);
-
- return 0;
}
static const struct of_device_id stm32f4_i2c_match[] = {
@@ -884,7 +882,7 @@ static struct platform_driver stm32f4_i2c_driver = {
.of_match_table = stm32f4_i2c_match,
},
.probe = stm32f4_i2c_probe,
- .remove = stm32f4_i2c_remove,
+ .remove_new = stm32f4_i2c_remove,
};
module_platform_driver(stm32f4_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
index d1c59d83a65b..e897d9101434 100644
--- a/drivers/i2c/busses/i2c-stm32f7.c
+++ b/drivers/i2c/busses/i2c-stm32f7.c
@@ -2309,7 +2309,7 @@ clk_free:
return ret;
}
-static int stm32f7_i2c_remove(struct platform_device *pdev)
+static void stm32f7_i2c_remove(struct platform_device *pdev)
{
struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
@@ -2341,8 +2341,6 @@ static int stm32f7_i2c_remove(struct platform_device *pdev)
stm32f7_i2c_write_fm_plus_bits(i2c_dev, false);
clk_disable_unprepare(i2c_dev->clk);
-
- return 0;
}
static int __maybe_unused stm32f7_i2c_runtime_suspend(struct device *dev)
@@ -2486,7 +2484,7 @@ static struct platform_driver stm32f7_i2c_driver = {
.pm = &stm32f7_i2c_pm_ops,
},
.probe = stm32f7_i2c_probe,
- .remove = stm32f7_i2c_remove,
+ .remove_new = stm32f7_i2c_remove,
};
module_platform_driver(stm32f7_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c
index 9e3483f507ff..ad8270cdbd3e 100644
--- a/drivers/i2c/busses/i2c-sun6i-p2wi.c
+++ b/drivers/i2c/busses/i2c-sun6i-p2wi.c
@@ -239,15 +239,9 @@ static int p2wi_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- p2wi->clk = devm_clk_get(dev, NULL);
+ p2wi->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(p2wi->clk)) {
ret = PTR_ERR(p2wi->clk);
- dev_err(dev, "failed to retrieve clk: %d\n", ret);
- return ret;
- }
-
- ret = clk_prepare_enable(p2wi->clk);
- if (ret) {
dev_err(dev, "failed to enable clk: %d\n", ret);
return ret;
}
@@ -256,15 +250,14 @@ static int p2wi_probe(struct platform_device *pdev)
p2wi->rstc = devm_reset_control_get_exclusive(dev, NULL);
if (IS_ERR(p2wi->rstc)) {
- ret = PTR_ERR(p2wi->rstc);
dev_err(dev, "failed to retrieve reset controller: %d\n", ret);
- goto err_clk_disable;
+ return PTR_ERR(p2wi->rstc);
}
ret = reset_control_deassert(p2wi->rstc);
if (ret) {
dev_err(dev, "failed to deassert reset line: %d\n", ret);
- goto err_clk_disable;
+ return ret;
}
init_completion(&p2wi->complete);
@@ -307,26 +300,20 @@ static int p2wi_probe(struct platform_device *pdev)
err_reset_assert:
reset_control_assert(p2wi->rstc);
-err_clk_disable:
- clk_disable_unprepare(p2wi->clk);
-
return ret;
}
-static int p2wi_remove(struct platform_device *dev)
+static void p2wi_remove(struct platform_device *dev)
{
struct p2wi *p2wi = platform_get_drvdata(dev);
reset_control_assert(p2wi->rstc);
- clk_disable_unprepare(p2wi->clk);
i2c_del_adapter(&p2wi->adapter);
-
- return 0;
}
static struct platform_driver p2wi_driver = {
.probe = p2wi_probe,
- .remove = p2wi_remove,
+ .remove_new = p2wi_remove,
.driver = {
.name = "i2c-sunxi-p2wi",
.of_match_table = p2wi_of_match_table,
diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c
index 50d19cf99a03..4cc196ca8f6d 100644
--- a/drivers/i2c/busses/i2c-synquacer.c
+++ b/drivers/i2c/busses/i2c-synquacer.c
@@ -618,15 +618,13 @@ static int synquacer_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int synquacer_i2c_remove(struct platform_device *pdev)
+static void synquacer_i2c_remove(struct platform_device *pdev)
{
struct synquacer_i2c *i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c->adapter);
if (!IS_ERR(i2c->pclk))
clk_disable_unprepare(i2c->pclk);
-
- return 0;
};
static const struct of_device_id synquacer_i2c_dt_ids[] __maybe_unused = {
@@ -645,7 +643,7 @@ MODULE_DEVICE_TABLE(acpi, synquacer_i2c_acpi_ids);
static struct platform_driver synquacer_i2c_driver = {
.probe = synquacer_i2c_probe,
- .remove = synquacer_i2c_remove,
+ .remove_new = synquacer_i2c_remove,
.driver = {
.name = "synquacer_i2c",
.of_match_table = of_match_ptr(synquacer_i2c_dt_ids),
diff --git a/drivers/i2c/busses/i2c-tegra-bpmp.c b/drivers/i2c/busses/i2c-tegra-bpmp.c
index 95139985b2d5..bc3f94561746 100644
--- a/drivers/i2c/busses/i2c-tegra-bpmp.c
+++ b/drivers/i2c/busses/i2c-tegra-bpmp.c
@@ -316,13 +316,11 @@ static int tegra_bpmp_i2c_probe(struct platform_device *pdev)
return i2c_add_adapter(&i2c->adapter);
}
-static int tegra_bpmp_i2c_remove(struct platform_device *pdev)
+static void tegra_bpmp_i2c_remove(struct platform_device *pdev)
{
struct tegra_bpmp_i2c *i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c->adapter);
-
- return 0;
}
static const struct of_device_id tegra_bpmp_i2c_of_match[] = {
@@ -337,7 +335,7 @@ static struct platform_driver tegra_bpmp_i2c_driver = {
.of_match_table = tegra_bpmp_i2c_of_match,
},
.probe = tegra_bpmp_i2c_probe,
- .remove = tegra_bpmp_i2c_remove,
+ .remove_new = tegra_bpmp_i2c_remove,
};
module_platform_driver(tegra_bpmp_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 157066f06a32..bcbbf23aa530 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -249,8 +249,7 @@ struct tegra_i2c_hw_feature {
* @msg_read: indicates that the transfer is a read access
* @timings: i2c timings information like bus frequency
* @multimaster_mode: indicates that I2C controller is in multi-master mode
- * @tx_dma_chan: DMA transmit channel
- * @rx_dma_chan: DMA receive channel
+ * @dma_chan: DMA channel
* @dma_phys: handle to DMA resources
* @dma_buf: pointer to allocated DMA buffer
* @dma_buf_size: DMA buffer size
@@ -283,8 +282,7 @@ struct tegra_i2c_dev {
u8 *msg_buf;
struct completion dma_complete;
- struct dma_chan *tx_dma_chan;
- struct dma_chan *rx_dma_chan;
+ struct dma_chan *dma_chan;
unsigned int dma_buf_size;
struct device *dma_dev;
dma_addr_t dma_phys;
@@ -298,6 +296,9 @@ struct tegra_i2c_dev {
bool is_vi;
};
+#define IS_DVC(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && (dev)->is_dvc)
+#define IS_VI(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && (dev)->is_vi)
+
static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
unsigned int reg)
{
@@ -315,9 +316,9 @@ static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
*/
static u32 tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
{
- if (i2c_dev->is_dvc)
+ if (IS_DVC(i2c_dev))
reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40;
- else if (i2c_dev->is_vi)
+ else if (IS_VI(i2c_dev))
reg = 0xc00 + (reg << 2);
return reg;
@@ -330,7 +331,7 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg)
/* read back register to make sure that register writes completed */
if (reg != I2C_TX_FIFO)
readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
- else if (i2c_dev->is_vi)
+ else if (IS_VI(i2c_dev))
readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, I2C_INT_STATUS));
}
@@ -393,16 +394,14 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len)
{
struct dma_async_tx_descriptor *dma_desc;
enum dma_transfer_direction dir;
- struct dma_chan *chan;
dev_dbg(i2c_dev->dev, "starting DMA for length: %zu\n", len);
reinit_completion(&i2c_dev->dma_complete);
dir = i2c_dev->msg_read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
- chan = i2c_dev->msg_read ? i2c_dev->rx_dma_chan : i2c_dev->tx_dma_chan;
- dma_desc = dmaengine_prep_slave_single(chan, i2c_dev->dma_phys,
+ dma_desc = dmaengine_prep_slave_single(i2c_dev->dma_chan, i2c_dev->dma_phys,
len, dir, DMA_PREP_INTERRUPT |
DMA_CTRL_ACK);
if (!dma_desc) {
@@ -415,7 +414,7 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len)
dma_desc->callback_param = i2c_dev;
dmaengine_submit(dma_desc);
- dma_async_issue_pending(chan);
+ dma_async_issue_pending(i2c_dev->dma_chan);
return 0;
}
@@ -428,25 +427,19 @@ static void tegra_i2c_release_dma(struct tegra_i2c_dev *i2c_dev)
i2c_dev->dma_buf = NULL;
}
- if (i2c_dev->tx_dma_chan) {
- dma_release_channel(i2c_dev->tx_dma_chan);
- i2c_dev->tx_dma_chan = NULL;
- }
-
- if (i2c_dev->rx_dma_chan) {
- dma_release_channel(i2c_dev->rx_dma_chan);
- i2c_dev->rx_dma_chan = NULL;
+ if (i2c_dev->dma_chan) {
+ dma_release_channel(i2c_dev->dma_chan);
+ i2c_dev->dma_chan = NULL;
}
}
static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
{
- struct dma_chan *chan;
dma_addr_t dma_phys;
u32 *dma_buf;
int err;
- if (i2c_dev->is_vi)
+ if (IS_VI(i2c_dev))
return 0;
if (!i2c_dev->hw->has_apb_dma) {
@@ -459,25 +452,18 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
return 0;
}
- chan = dma_request_chan(i2c_dev->dev, "rx");
- if (IS_ERR(chan)) {
- err = PTR_ERR(chan);
- goto err_out;
- }
-
- i2c_dev->rx_dma_chan = chan;
-
- chan = dma_request_chan(i2c_dev->dev, "tx");
- if (IS_ERR(chan)) {
- err = PTR_ERR(chan);
+ /*
+ * The same channel will be used for both RX and TX.
+ * Keeping the name as "tx" for backward compatibility
+ * with existing devicetrees.
+ */
+ i2c_dev->dma_chan = dma_request_chan(i2c_dev->dev, "tx");
+ if (IS_ERR(i2c_dev->dma_chan)) {
+ err = PTR_ERR(i2c_dev->dma_chan);
goto err_out;
}
- i2c_dev->tx_dma_chan = chan;
-
- WARN_ON(i2c_dev->tx_dma_chan->device != i2c_dev->rx_dma_chan->device);
- i2c_dev->dma_dev = chan->device->dev;
-
+ i2c_dev->dma_dev = i2c_dev->dma_chan->device->dev;
i2c_dev->dma_buf_size = i2c_dev->hw->quirks->max_write_len +
I2C_PACKET_HEADER_SIZE;
@@ -639,7 +625,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
WARN_ON_ONCE(err);
- if (i2c_dev->is_dvc)
+ if (IS_DVC(i2c_dev))
tegra_dvc_init(i2c_dev);
val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
@@ -651,7 +637,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
i2c_writel(i2c_dev, val, I2C_CNFG);
i2c_writel(i2c_dev, 0, I2C_INT_MASK);
- if (i2c_dev->is_vi)
+ if (IS_VI(i2c_dev))
tegra_i2c_vi_init(i2c_dev);
switch (t->bus_freq_hz) {
@@ -703,7 +689,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
return err;
}
- if (!i2c_dev->is_dvc && !i2c_dev->is_vi) {
+ if (!IS_DVC(i2c_dev) && !IS_VI(i2c_dev)) {
u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG);
sl_cfg |= I2C_SL_CNFG_NACK | I2C_SL_CNFG_NEWSL;
@@ -846,7 +832,7 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
i2c_dev->msg_buf_remaining = buf_remaining;
i2c_dev->msg_buf = buf + words_to_transfer * BYTES_PER_FIFO_WORD;
- if (i2c_dev->is_vi)
+ if (IS_VI(i2c_dev))
i2c_writesl_vi(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
else
i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
@@ -933,7 +919,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
}
i2c_writel(i2c_dev, status, I2C_INT_STATUS);
- if (i2c_dev->is_dvc)
+ if (IS_DVC(i2c_dev))
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
/*
@@ -972,15 +958,11 @@ err:
i2c_writel(i2c_dev, status, I2C_INT_STATUS);
- if (i2c_dev->is_dvc)
+ if (IS_DVC(i2c_dev))
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
if (i2c_dev->dma_mode) {
- if (i2c_dev->msg_read)
- dmaengine_terminate_async(i2c_dev->rx_dma_chan);
- else
- dmaengine_terminate_async(i2c_dev->tx_dma_chan);
-
+ dmaengine_terminate_async(i2c_dev->dma_chan);
complete(&i2c_dev->dma_complete);
}
@@ -994,7 +976,6 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
{
struct dma_slave_config slv_config = {0};
u32 val, reg, dma_burst, reg_offset;
- struct dma_chan *chan;
int err;
if (i2c_dev->hw->has_mst_fifo)
@@ -1011,7 +992,6 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
dma_burst = 8;
if (i2c_dev->msg_read) {
- chan = i2c_dev->rx_dma_chan;
reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_RX_FIFO);
slv_config.src_addr = i2c_dev->base_phys + reg_offset;
@@ -1023,7 +1003,6 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
else
val = I2C_FIFO_CONTROL_RX_TRIG(dma_burst);
} else {
- chan = i2c_dev->tx_dma_chan;
reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_TX_FIFO);
slv_config.dst_addr = i2c_dev->base_phys + reg_offset;
@@ -1037,7 +1016,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
}
slv_config.device_fc = true;
- err = dmaengine_slave_config(chan, &slv_config);
+ err = dmaengine_slave_config(i2c_dev->dma_chan, &slv_config);
if (err) {
dev_err(i2c_dev->dev, "DMA config failed: %d\n", err);
dev_err(i2c_dev->dev, "falling back to PIO\n");
@@ -1347,13 +1326,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
* performs synchronization after the transfer's termination
* and we want to get a completion if transfer succeeded.
*/
- dmaengine_synchronize(i2c_dev->msg_read ?
- i2c_dev->rx_dma_chan :
- i2c_dev->tx_dma_chan);
-
- dmaengine_terminate_sync(i2c_dev->msg_read ?
- i2c_dev->rx_dma_chan :
- i2c_dev->tx_dma_chan);
+ dmaengine_synchronize(i2c_dev->dma_chan);
+ dmaengine_terminate_sync(i2c_dev->dma_chan);
if (!time_left && !completion_done(&i2c_dev->dma_complete)) {
dev_err(i2c_dev->dev, "DMA transfer timed out\n");
@@ -1654,13 +1628,17 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
static const struct of_device_id tegra_i2c_of_match[] = {
{ .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, },
{ .compatible = "nvidia,tegra186-i2c", .data = &tegra186_i2c_hw, },
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
{ .compatible = "nvidia,tegra210-i2c-vi", .data = &tegra210_i2c_hw, },
+#endif
{ .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, },
{ .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, },
{ .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, },
{ .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, },
{ .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, },
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)
{ .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, },
+#endif
{},
};
MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
@@ -1675,10 +1653,12 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
multi_mode = device_property_read_bool(i2c_dev->dev, "multi-master");
i2c_dev->multimaster_mode = multi_mode;
- if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc"))
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
+ of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc"))
i2c_dev->is_dvc = true;
- if (of_device_is_compatible(np, "nvidia,tegra210-i2c-vi"))
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) &&
+ of_device_is_compatible(np, "nvidia,tegra210-i2c-vi"))
i2c_dev->is_vi = true;
}
@@ -1707,7 +1687,7 @@ static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
if (i2c_dev->hw == &tegra20_i2c_hw || i2c_dev->hw == &tegra30_i2c_hw)
i2c_dev->clocks[i2c_dev->nclocks++].id = "fast-clk";
- if (i2c_dev->is_vi)
+ if (IS_VI(i2c_dev))
i2c_dev->clocks[i2c_dev->nclocks++].id = "slow";
err = devm_clk_bulk_get(i2c_dev->dev, i2c_dev->nclocks,
@@ -1825,7 +1805,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
* VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't
* be used for atomic transfers.
*/
- if (!i2c_dev->is_vi)
+ if (!IS_VI(i2c_dev))
pm_runtime_irq_safe(i2c_dev->dev);
pm_runtime_enable(i2c_dev->dev);
@@ -1868,7 +1848,7 @@ release_clocks:
return err;
}
-static int tegra_i2c_remove(struct platform_device *pdev)
+static void tegra_i2c_remove(struct platform_device *pdev)
{
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
@@ -1877,8 +1857,6 @@ static int tegra_i2c_remove(struct platform_device *pdev)
tegra_i2c_release_dma(i2c_dev);
tegra_i2c_release_clocks(i2c_dev);
-
- return 0;
}
static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
@@ -1899,7 +1877,7 @@ static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
* power ON/OFF during runtime PM resume/suspend, meaning that
* controller needs to be re-initialized after power ON.
*/
- if (i2c_dev->is_vi) {
+ if (IS_VI(i2c_dev)) {
err = tegra_i2c_init(i2c_dev);
if (err)
goto disable_clocks;
@@ -1987,7 +1965,7 @@ MODULE_DEVICE_TABLE(acpi, tegra_i2c_acpi_match);
static struct platform_driver tegra_i2c_driver = {
.probe = tegra_i2c_probe,
- .remove = tegra_i2c_remove,
+ .remove_new = tegra_i2c_remove,
.driver = {
.name = "tegra-i2c",
.of_match_table = tegra_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c
index 7279ca0eaa2d..d1fa9ff5aeab 100644
--- a/drivers/i2c/busses/i2c-tiny-usb.c
+++ b/drivers/i2c/busses/i2c-tiny-usb.c
@@ -226,10 +226,8 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface,
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL) {
- dev_err(&interface->dev, "Out of memory\n");
+ if (!dev)
goto error;
- }
dev->usb_dev = usb_get_dev(interface_to_usbdev(interface));
dev->interface = interface;
diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c
index d7b622891e52..dbc91c7c3788 100644
--- a/drivers/i2c/busses/i2c-uniphier-f.c
+++ b/drivers/i2c/busses/i2c-uniphier-f.c
@@ -540,21 +540,16 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
return -EINVAL;
}
- priv->clk = devm_clk_get(dev, NULL);
+ priv->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(priv->clk)) {
- dev_err(dev, "failed to get clock\n");
+ dev_err(dev, "failed to enable clock\n");
return PTR_ERR(priv->clk);
}
- ret = clk_prepare_enable(priv->clk);
- if (ret)
- return ret;
-
clk_rate = clk_get_rate(priv->clk);
if (!clk_rate) {
dev_err(dev, "input clock rate should not be zero\n");
- ret = -EINVAL;
- goto disable_clk;
+ return -EINVAL;
}
priv->clk_cycle = clk_rate / bus_speed;
@@ -575,25 +570,17 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
pdev->name, priv);
if (ret) {
dev_err(dev, "failed to request irq %d\n", irq);
- goto disable_clk;
+ return ret;
}
- ret = i2c_add_adapter(&priv->adap);
-disable_clk:
- if (ret)
- clk_disable_unprepare(priv->clk);
-
- return ret;
+ return i2c_add_adapter(&priv->adap);
}
-static int uniphier_fi2c_remove(struct platform_device *pdev)
+static void uniphier_fi2c_remove(struct platform_device *pdev)
{
struct uniphier_fi2c_priv *priv = platform_get_drvdata(pdev);
i2c_del_adapter(&priv->adap);
- clk_disable_unprepare(priv->clk);
-
- return 0;
}
static int __maybe_unused uniphier_fi2c_suspend(struct device *dev)
@@ -631,7 +618,7 @@ MODULE_DEVICE_TABLE(of, uniphier_fi2c_match);
static struct platform_driver uniphier_fi2c_drv = {
.probe = uniphier_fi2c_probe,
- .remove = uniphier_fi2c_remove,
+ .remove_new = uniphier_fi2c_remove,
.driver = {
.name = "uniphier-fi2c",
.of_match_table = uniphier_fi2c_match,
diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c
index e3ebae381f08..854ac25b5862 100644
--- a/drivers/i2c/busses/i2c-uniphier.c
+++ b/drivers/i2c/busses/i2c-uniphier.c
@@ -335,21 +335,16 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
return -EINVAL;
}
- priv->clk = devm_clk_get(dev, NULL);
+ priv->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(priv->clk)) {
- dev_err(dev, "failed to get clock\n");
+ dev_err(dev, "failed to enable clock\n");
return PTR_ERR(priv->clk);
}
- ret = clk_prepare_enable(priv->clk);
- if (ret)
- return ret;
-
clk_rate = clk_get_rate(priv->clk);
if (!clk_rate) {
dev_err(dev, "input clock rate should not be zero\n");
- ret = -EINVAL;
- goto disable_clk;
+ return -EINVAL;
}
priv->clk_cycle = clk_rate / bus_speed;
@@ -369,25 +364,17 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
priv);
if (ret) {
dev_err(dev, "failed to request irq %d\n", irq);
- goto disable_clk;
+ return ret;
}
- ret = i2c_add_adapter(&priv->adap);
-disable_clk:
- if (ret)
- clk_disable_unprepare(priv->clk);
-
- return ret;
+ return i2c_add_adapter(&priv->adap);
}
-static int uniphier_i2c_remove(struct platform_device *pdev)
+static void uniphier_i2c_remove(struct platform_device *pdev)
{
struct uniphier_i2c_priv *priv = platform_get_drvdata(pdev);
i2c_del_adapter(&priv->adap);
- clk_disable_unprepare(priv->clk);
-
- return 0;
}
static int __maybe_unused uniphier_i2c_suspend(struct device *dev)
@@ -425,7 +412,7 @@ MODULE_DEVICE_TABLE(of, uniphier_i2c_match);
static struct platform_driver uniphier_i2c_drv = {
.probe = uniphier_i2c_probe,
- .remove = uniphier_i2c_remove,
+ .remove_new = uniphier_i2c_remove,
.driver = {
.name = "uniphier-i2c",
.of_match_table = uniphier_i2c_match,
diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c
index 1ab419f8fa52..76abfa77e200 100644
--- a/drivers/i2c/busses/i2c-versatile.c
+++ b/drivers/i2c/busses/i2c-versatile.c
@@ -64,15 +64,13 @@ static const struct i2c_algo_bit_data i2c_versatile_algo = {
static int i2c_versatile_probe(struct platform_device *dev)
{
struct i2c_versatile *i2c;
- struct resource *r;
int ret;
i2c = devm_kzalloc(&dev->dev, sizeof(struct i2c_versatile), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
- r = platform_get_resource(dev, IORESOURCE_MEM, 0);
- i2c->base = devm_ioremap_resource(&dev->dev, r);
+ i2c->base = devm_platform_get_and_ioremap_resource(dev, 0, NULL);
if (IS_ERR(i2c->base))
return PTR_ERR(i2c->base);
@@ -96,12 +94,11 @@ static int i2c_versatile_probe(struct platform_device *dev)
return 0;
}
-static int i2c_versatile_remove(struct platform_device *dev)
+static void i2c_versatile_remove(struct platform_device *dev)
{
struct i2c_versatile *i2c = platform_get_drvdata(dev);
i2c_del_adapter(&i2c->adap);
- return 0;
}
static const struct of_device_id i2c_versatile_match[] = {
@@ -112,7 +109,7 @@ MODULE_DEVICE_TABLE(of, i2c_versatile_match);
static struct platform_driver i2c_versatile_driver = {
.probe = i2c_versatile_probe,
- .remove = i2c_versatile_remove,
+ .remove_new = i2c_versatile_remove,
.driver = {
.name = "versatile-i2c",
.of_match_table = i2c_versatile_match,
diff --git a/drivers/i2c/busses/i2c-viperboard.c b/drivers/i2c/busses/i2c-viperboard.c
index 8b5322c3bce0..9e153b5b0e8e 100644
--- a/drivers/i2c/busses/i2c-viperboard.c
+++ b/drivers/i2c/busses/i2c-viperboard.c
@@ -407,20 +407,18 @@ static int vprbrd_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int vprbrd_i2c_remove(struct platform_device *pdev)
+static void vprbrd_i2c_remove(struct platform_device *pdev)
{
struct vprbrd_i2c *vb_i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&vb_i2c->i2c);
-
- return 0;
}
static struct platform_driver vprbrd_i2c_driver = {
.driver.name = "viperboard-i2c",
.driver.owner = THIS_MODULE,
.probe = vprbrd_i2c_probe,
- .remove = vprbrd_i2c_remove,
+ .remove_new = vprbrd_i2c_remove,
};
static int __init vprbrd_i2c_init(void)
diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c
index 7d4bc8736079..76118abc6e10 100644
--- a/drivers/i2c/busses/i2c-wmt.c
+++ b/drivers/i2c/busses/i2c-wmt.c
@@ -372,7 +372,6 @@ static int wmt_i2c_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct wmt_i2c_dev *i2c_dev;
struct i2c_adapter *adap;
- struct resource *res;
int err;
u32 clk_rate;
@@ -380,8 +379,7 @@ static int wmt_i2c_probe(struct platform_device *pdev)
if (!i2c_dev)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
+ i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(i2c_dev->base))
return PTR_ERR(i2c_dev->base);
@@ -436,7 +434,7 @@ static int wmt_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int wmt_i2c_remove(struct platform_device *pdev)
+static void wmt_i2c_remove(struct platform_device *pdev)
{
struct wmt_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
@@ -444,8 +442,6 @@ static int wmt_i2c_remove(struct platform_device *pdev)
writew(0, i2c_dev->base + REG_IMR);
clk_disable_unprepare(i2c_dev->clk);
i2c_del_adapter(&i2c_dev->adapter);
-
- return 0;
}
static const struct of_device_id wmt_i2c_dt_ids[] = {
@@ -455,7 +451,7 @@ static const struct of_device_id wmt_i2c_dt_ids[] = {
static struct platform_driver wmt_i2c_driver = {
.probe = wmt_i2c_probe,
- .remove = wmt_i2c_remove,
+ .remove_new = wmt_i2c_remove,
.driver = {
.name = "wmt-i2c",
.of_match_table = wmt_i2c_dt_ids,
diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c
index 3538d36368a9..fbc1ffbd2fa7 100644
--- a/drivers/i2c/busses/i2c-xgene-slimpro.c
+++ b/drivers/i2c/busses/i2c-xgene-slimpro.c
@@ -560,7 +560,7 @@ mbox_err:
return rc;
}
-static int xgene_slimpro_i2c_remove(struct platform_device *pdev)
+static void xgene_slimpro_i2c_remove(struct platform_device *pdev)
{
struct slimpro_i2c_dev *ctx = platform_get_drvdata(pdev);
@@ -570,8 +570,6 @@ static int xgene_slimpro_i2c_remove(struct platform_device *pdev)
mbox_free_channel(ctx->mbox_chan);
else
pcc_mbox_free_channel(ctx->pcc_chan);
-
- return 0;
}
static const struct of_device_id xgene_slimpro_i2c_dt_ids[] = {
@@ -591,7 +589,7 @@ MODULE_DEVICE_TABLE(acpi, xgene_slimpro_i2c_acpi_ids);
static struct platform_driver xgene_slimpro_i2c_driver = {
.probe = xgene_slimpro_i2c_probe,
- .remove = xgene_slimpro_i2c_remove,
+ .remove_new = xgene_slimpro_i2c_remove,
.driver = {
.name = "xgene-slimpro-i2c",
.of_match_table = of_match_ptr(xgene_slimpro_i2c_dt_ids),
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index 8a3d9817cb41..f879af4def5e 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -1256,16 +1256,11 @@ static int xiic_i2c_probe(struct platform_device *pdev)
mutex_init(&i2c->lock);
- i2c->clk = devm_clk_get(&pdev->dev, NULL);
+ i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(i2c->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk),
- "input clock not found.\n");
+ "failed to enable input clock.\n");
- ret = clk_prepare_enable(i2c->clk);
- if (ret) {
- dev_err(&pdev->dev, "Unable to enable clock.\n");
- return ret;
- }
i2c->dev = &pdev->dev;
pm_runtime_set_autosuspend_delay(i2c->dev, XIIC_PM_TIMEOUT);
pm_runtime_use_autosuspend(i2c->dev);
@@ -1286,7 +1281,7 @@ static int xiic_i2c_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(&pdev->dev, "Cannot claim IRQ\n");
- goto err_clk_dis;
+ goto err_pm_disable;
}
i2c->singlemaster =
@@ -1307,14 +1302,14 @@ static int xiic_i2c_probe(struct platform_device *pdev)
ret = xiic_reinit(i2c);
if (ret < 0) {
dev_err(&pdev->dev, "Cannot xiic_reinit\n");
- goto err_clk_dis;
+ goto err_pm_disable;
}
/* add i2c adapter to i2c tree */
ret = i2c_add_adapter(&i2c->adap);
if (ret) {
xiic_deinit(i2c);
- goto err_clk_dis;
+ goto err_pm_disable;
}
if (pdata) {
@@ -1328,14 +1323,14 @@ static int xiic_i2c_probe(struct platform_device *pdev)
return 0;
-err_clk_dis:
+err_pm_disable:
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_disable(&pdev->dev);
- clk_disable_unprepare(i2c->clk);
+
return ret;
}
-static int xiic_i2c_remove(struct platform_device *pdev)
+static void xiic_i2c_remove(struct platform_device *pdev)
{
struct xiic_i2c *i2c = platform_get_drvdata(pdev);
int ret;
@@ -1352,12 +1347,9 @@ static int xiic_i2c_remove(struct platform_device *pdev)
xiic_deinit(i2c);
pm_runtime_put_sync(i2c->dev);
- clk_disable_unprepare(i2c->clk);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
-
- return 0;
}
static int __maybe_unused xiic_i2c_runtime_suspend(struct device *dev)
@@ -1390,7 +1382,7 @@ static const struct dev_pm_ops xiic_dev_pm_ops = {
static struct platform_driver xiic_i2c_driver = {
.probe = xiic_i2c_probe,
- .remove = xiic_i2c_remove,
+ .remove_new = xiic_i2c_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(xiic_of_match),
diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c
index 4e3b11c0f732..f59e8c544f36 100644
--- a/drivers/i2c/busses/i2c-xlp9xx.c
+++ b/drivers/i2c/busses/i2c-xlp9xx.c
@@ -559,7 +559,7 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
return 0;
}
-static int xlp9xx_i2c_remove(struct platform_device *pdev)
+static void xlp9xx_i2c_remove(struct platform_device *pdev)
{
struct xlp9xx_i2c_dev *priv;
@@ -568,8 +568,6 @@ static int xlp9xx_i2c_remove(struct platform_device *pdev)
synchronize_irq(priv->irq);
i2c_del_adapter(&priv->adapter);
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, 0);
-
- return 0;
}
#ifdef CONFIG_ACPI
@@ -583,7 +581,7 @@ MODULE_DEVICE_TABLE(acpi, xlp9xx_i2c_acpi_ids);
static struct platform_driver xlp9xx_i2c_driver = {
.probe = xlp9xx_i2c_probe,
- .remove = xlp9xx_i2c_remove,
+ .remove_new = xlp9xx_i2c_remove,
.driver = {
.name = "xlp9xx-i2c",
.acpi_match_table = ACPI_PTR(xlp9xx_i2c_acpi_ids),
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 7b42a18bd05c..83c1db610f54 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -523,14 +523,12 @@ static void scx200_cleanup_iface(struct scx200_acb_iface *iface)
kfree(iface);
}
-static int scx200_remove(struct platform_device *pdev)
+static void scx200_remove(struct platform_device *pdev)
{
struct scx200_acb_iface *iface;
iface = platform_get_drvdata(pdev);
scx200_cleanup_iface(iface);
-
- return 0;
}
static struct platform_driver scx200_pci_driver = {
@@ -538,7 +536,7 @@ static struct platform_driver scx200_pci_driver = {
.name = "cs5535-smb",
},
.probe = scx200_probe,
- .remove = scx200_remove,
+ .remove_new = scx200_remove,
};
static const struct pci_device_id scx200_isa[] = {
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index ae3af738b03f..60746652fd52 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -114,6 +114,25 @@ const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
}
EXPORT_SYMBOL_GPL(i2c_match_id);
+const void *i2c_get_match_data(const struct i2c_client *client)
+{
+ struct i2c_driver *driver = to_i2c_driver(client->dev.driver);
+ const struct i2c_device_id *match;
+ const void *data;
+
+ data = device_get_match_data(&client->dev);
+ if (!data) {
+ match = i2c_match_id(driver->id_table, client);
+ if (!match)
+ return NULL;
+
+ data = (const void *)match->driver_data;
+ }
+
+ return data;
+}
+EXPORT_SYMBOL(i2c_get_match_data);
+
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client *client = i2c_verify_client(dev);
diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
index 1c78657631f4..24168e9f7df4 100644
--- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
+++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
@@ -174,13 +174,12 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
return ret;
}
-static int i2c_arbitrator_remove(struct platform_device *pdev)
+static void i2c_arbitrator_remove(struct platform_device *pdev)
{
struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
i2c_mux_del_adapters(muxc);
i2c_put_adapter(muxc->parent);
- return 0;
}
static const struct of_device_id i2c_arbitrator_of_match[] = {
@@ -191,7 +190,7 @@ MODULE_DEVICE_TABLE(of, i2c_arbitrator_of_match);
static struct platform_driver i2c_arbitrator_driver = {
.probe = i2c_arbitrator_probe,
- .remove = i2c_arbitrator_remove,
+ .remove_new = i2c_arbitrator_remove,
.driver = {
.name = "i2c-arb-gpio-challenge",
.of_match_table = i2c_arbitrator_of_match,
diff --git a/drivers/i2c/muxes/i2c-demux-pinctrl.c b/drivers/i2c/muxes/i2c-demux-pinctrl.c
index f7a7405d4350..a3a122fae71e 100644
--- a/drivers/i2c/muxes/i2c-demux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-demux-pinctrl.c
@@ -282,7 +282,7 @@ err_rollback:
return err;
}
-static int i2c_demux_pinctrl_remove(struct platform_device *pdev)
+static void i2c_demux_pinctrl_remove(struct platform_device *pdev)
{
struct i2c_demux_pinctrl_priv *priv = platform_get_drvdata(pdev);
int i;
@@ -296,8 +296,6 @@ static int i2c_demux_pinctrl_remove(struct platform_device *pdev)
of_node_put(priv->chan[i].parent_np);
of_changeset_destroy(&priv->chan[i].chgset);
}
-
- return 0;
}
static const struct of_device_id i2c_demux_pinctrl_of_match[] = {
@@ -312,7 +310,7 @@ static struct platform_driver i2c_demux_pinctrl_driver = {
.of_match_table = i2c_demux_pinctrl_of_match,
},
.probe = i2c_demux_pinctrl_probe,
- .remove = i2c_demux_pinctrl_remove,
+ .remove_new = i2c_demux_pinctrl_remove,
};
module_platform_driver(i2c_demux_pinctrl_driver);
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 73a23e117ebe..5d5cbe0130cd 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -225,14 +225,12 @@ alloc_failed:
return ret;
}
-static int i2c_mux_gpio_remove(struct platform_device *pdev)
+static void i2c_mux_gpio_remove(struct platform_device *pdev)
{
struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
i2c_mux_del_adapters(muxc);
i2c_put_adapter(muxc->parent);
-
- return 0;
}
static const struct of_device_id i2c_mux_gpio_of_match[] = {
@@ -243,7 +241,7 @@ MODULE_DEVICE_TABLE(of, i2c_mux_gpio_of_match);
static struct platform_driver i2c_mux_gpio_driver = {
.probe = i2c_mux_gpio_probe,
- .remove = i2c_mux_gpio_remove,
+ .remove_new = i2c_mux_gpio_remove,
.driver = {
.name = "i2c-mux-gpio",
.of_match_table = i2c_mux_gpio_of_match,
diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c b/drivers/i2c/muxes/i2c-mux-gpmux.c
index 33024acaac02..0405af0e1510 100644
--- a/drivers/i2c/muxes/i2c-mux-gpmux.c
+++ b/drivers/i2c/muxes/i2c-mux-gpmux.c
@@ -142,19 +142,17 @@ err_parent:
return ret;
}
-static int i2c_mux_remove(struct platform_device *pdev)
+static void i2c_mux_remove(struct platform_device *pdev)
{
struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
i2c_mux_del_adapters(muxc);
i2c_put_adapter(muxc->parent);
-
- return 0;
}
static struct platform_driver i2c_mux_driver = {
.probe = i2c_mux_probe,
- .remove = i2c_mux_remove,
+ .remove_new = i2c_mux_remove,
.driver = {
.name = "i2c-mux-gpmux",
.of_match_table = i2c_mux_of_match,
diff --git a/drivers/i2c/muxes/i2c-mux-mlxcpld.c b/drivers/i2c/muxes/i2c-mux-mlxcpld.c
index 1a879f6a31ef..3dda00f1df78 100644
--- a/drivers/i2c/muxes/i2c-mux-mlxcpld.c
+++ b/drivers/i2c/muxes/i2c-mux-mlxcpld.c
@@ -170,12 +170,11 @@ virt_reg_failed:
return err;
}
-static int mlxcpld_mux_remove(struct platform_device *pdev)
+static void mlxcpld_mux_remove(struct platform_device *pdev)
{
struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
i2c_mux_del_adapters(muxc);
- return 0;
}
static struct platform_driver mlxcpld_mux_driver = {
@@ -183,7 +182,7 @@ static struct platform_driver mlxcpld_mux_driver = {
.name = "i2c-mux-mlxcpld",
},
.probe = mlxcpld_mux_probe,
- .remove = mlxcpld_mux_remove,
+ .remove_new = mlxcpld_mux_remove,
};
module_platform_driver(mlxcpld_mux_driver);
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index d5ad904756fd..18236b9fa14a 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -166,14 +166,12 @@ err_put_parent:
return ret;
}
-static int i2c_mux_pinctrl_remove(struct platform_device *pdev)
+static void i2c_mux_pinctrl_remove(struct platform_device *pdev)
{
struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
i2c_mux_del_adapters(muxc);
i2c_put_adapter(muxc->parent);
-
- return 0;
}
static const struct of_device_id i2c_mux_pinctrl_of_match[] = {
@@ -188,7 +186,7 @@ static struct platform_driver i2c_mux_pinctrl_driver = {
.of_match_table = i2c_mux_pinctrl_of_match,
},
.probe = i2c_mux_pinctrl_probe,
- .remove = i2c_mux_pinctrl_remove,
+ .remove_new = i2c_mux_pinctrl_remove,
};
module_platform_driver(i2c_mux_pinctrl_driver);
diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
index 30a6de1694e0..9efc1ed01577 100644
--- a/drivers/i2c/muxes/i2c-mux-reg.c
+++ b/drivers/i2c/muxes/i2c-mux-reg.c
@@ -233,14 +233,12 @@ err_put_parent:
return ret;
}
-static int i2c_mux_reg_remove(struct platform_device *pdev)
+static void i2c_mux_reg_remove(struct platform_device *pdev)
{
struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
i2c_mux_del_adapters(muxc);
i2c_put_adapter(muxc->parent);
-
- return 0;
}
static const struct of_device_id i2c_mux_reg_of_match[] = {
@@ -251,7 +249,7 @@ MODULE_DEVICE_TABLE(of, i2c_mux_reg_of_match);
static struct platform_driver i2c_mux_reg_driver = {
.probe = i2c_mux_reg_probe,
- .remove = i2c_mux_reg_remove,
+ .remove_new = i2c_mux_reg_remove,
.driver = {
.name = "i2c-mux-reg",
.of_match_table = of_match_ptr(i2c_mux_reg_of_match),
diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index e3f454123805..0d63b732ef0c 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -92,6 +92,7 @@
#define SVC_I3C_MINTCLR 0x094
#define SVC_I3C_MINTMASKED 0x098
#define SVC_I3C_MERRWARN 0x09C
+#define SVC_I3C_MERRWARN_NACK BIT(2)
#define SVC_I3C_MDMACTRL 0x0A0
#define SVC_I3C_MDATACTRL 0x0AC
#define SVC_I3C_MDATACTRL_FLUSHTB BIT(0)
@@ -145,6 +146,11 @@ struct svc_i3c_xfer {
struct svc_i3c_cmd cmds[];
};
+struct svc_i3c_regs_save {
+ u32 mconfig;
+ u32 mdynaddr;
+};
+
/**
* struct svc_i3c_master - Silvaco I3C Master structure
* @base: I3C master controller
@@ -173,6 +179,7 @@ struct svc_i3c_master {
struct i3c_master_controller base;
struct device *dev;
void __iomem *regs;
+ struct svc_i3c_regs_save saved_regs;
u32 free_slots;
u8 addrs[SVC_I3C_MAX_DEVS];
struct i3c_dev_desc *descs[SVC_I3C_MAX_DEVS];
@@ -1008,6 +1015,11 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
if (ret)
goto emit_stop;
+ if (readl(master->regs + SVC_I3C_MERRWARN) & SVC_I3C_MERRWARN_NACK) {
+ ret = -ENXIO;
+ goto emit_stop;
+ }
+
if (rnw)
ret = svc_i3c_master_read(master, in, xfer_len);
else
@@ -1090,12 +1102,6 @@ static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master)
if (!xfer)
return;
- ret = pm_runtime_resume_and_get(master->dev);
- if (ret < 0) {
- dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__);
- return;
- }
-
svc_i3c_master_clear_merrwarn(master);
svc_i3c_master_flush_fifo(master);
@@ -1110,9 +1116,6 @@ static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master)
break;
}
- pm_runtime_mark_last_busy(master->dev);
- pm_runtime_put_autosuspend(master->dev);
-
xfer->ret = ret;
complete(&xfer->comp);
@@ -1133,6 +1136,13 @@ static void svc_i3c_master_enqueue_xfer(struct svc_i3c_master *master,
struct svc_i3c_xfer *xfer)
{
unsigned long flags;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(master->dev);
+ if (ret < 0) {
+ dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__);
+ return;
+ }
init_completion(&xfer->comp);
spin_lock_irqsave(&master->xferqueue.lock, flags);
@@ -1143,6 +1153,9 @@ static void svc_i3c_master_enqueue_xfer(struct svc_i3c_master *master,
svc_i3c_master_start_xfer_locked(master);
}
spin_unlock_irqrestore(&master->xferqueue.lock, flags);
+
+ pm_runtime_mark_last_busy(master->dev);
+ pm_runtime_put_autosuspend(master->dev);
}
static bool
@@ -1579,10 +1592,28 @@ static void svc_i3c_master_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
}
+static void svc_i3c_save_regs(struct svc_i3c_master *master)
+{
+ master->saved_regs.mconfig = readl(master->regs + SVC_I3C_MCONFIG);
+ master->saved_regs.mdynaddr = readl(master->regs + SVC_I3C_MDYNADDR);
+}
+
+static void svc_i3c_restore_regs(struct svc_i3c_master *master)
+{
+ if (readl(master->regs + SVC_I3C_MDYNADDR) !=
+ master->saved_regs.mdynaddr) {
+ writel(master->saved_regs.mconfig,
+ master->regs + SVC_I3C_MCONFIG);
+ writel(master->saved_regs.mdynaddr,
+ master->regs + SVC_I3C_MDYNADDR);
+ }
+}
+
static int __maybe_unused svc_i3c_runtime_suspend(struct device *dev)
{
struct svc_i3c_master *master = dev_get_drvdata(dev);
+ svc_i3c_save_regs(master);
svc_i3c_master_unprepare_clks(master);
pinctrl_pm_select_sleep_state(dev);
@@ -1596,6 +1627,8 @@ static int __maybe_unused svc_i3c_runtime_resume(struct device *dev)
pinctrl_pm_select_default_state(dev);
svc_i3c_master_prepare_clks(master);
+ svc_i3c_restore_regs(master);
+
return 0;
}
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 34201d7ef33e..b930036edbbe 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -2147,7 +2147,7 @@ static void __init intel_idle_cpuidle_devices_uninit(void)
* All our short idle states are dominated by vmexit/vmenter latencies,
* not the underlying hardware latencies so we keep our values for these.
*/
-static void matchup_vm_state_with_baremetal(void)
+static void __init matchup_vm_state_with_baremetal(void)
{
int cstate;
diff --git a/drivers/iio/accel/adxl313_i2c.c b/drivers/iio/accel/adxl313_i2c.c
index 99cc7fc29488..524327ea3663 100644
--- a/drivers/iio/accel/adxl313_i2c.c
+++ b/drivers/iio/accel/adxl313_i2c.c
@@ -85,7 +85,7 @@ static struct i2c_driver adxl313_i2c_driver = {
.name = "adxl313_i2c",
.of_match_table = adxl313_of_match,
},
- .probe_new = adxl313_i2c_probe,
+ .probe = adxl313_i2c_probe,
.id_table = adxl313_i2c_id,
};
diff --git a/drivers/iio/accel/adxl345_i2c.c b/drivers/iio/accel/adxl345_i2c.c
index 098cd83f95b2..e47d12f19602 100644
--- a/drivers/iio/accel/adxl345_i2c.c
+++ b/drivers/iio/accel/adxl345_i2c.c
@@ -56,7 +56,7 @@ static struct i2c_driver adxl345_i2c_driver = {
.of_match_table = adxl345_of_match,
.acpi_match_table = adxl345_acpi_match,
},
- .probe_new = adxl345_i2c_probe,
+ .probe = adxl345_i2c_probe,
.id_table = adxl345_i2c_id,
};
module_i2c_driver(adxl345_i2c_driver);
diff --git a/drivers/iio/accel/adxl355_i2c.c b/drivers/iio/accel/adxl355_i2c.c
index 6cde5ccac06b..d5beea61479d 100644
--- a/drivers/iio/accel/adxl355_i2c.c
+++ b/drivers/iio/accel/adxl355_i2c.c
@@ -68,7 +68,7 @@ static struct i2c_driver adxl355_i2c_driver = {
.name = "adxl355_i2c",
.of_match_table = adxl355_of_match,
},
- .probe_new = adxl355_i2c_probe,
+ .probe = adxl355_i2c_probe,
.id_table = adxl355_i2c_id,
};
module_i2c_driver(adxl355_i2c_driver);
diff --git a/drivers/iio/accel/adxl367_i2c.c b/drivers/iio/accel/adxl367_i2c.c
index 070aad724abd..b595fe94f3a3 100644
--- a/drivers/iio/accel/adxl367_i2c.c
+++ b/drivers/iio/accel/adxl367_i2c.c
@@ -77,7 +77,7 @@ static struct i2c_driver adxl367_i2c_driver = {
.name = "adxl367_i2c",
.of_match_table = adxl367_of_match,
},
- .probe_new = adxl367_i2c_probe,
+ .probe = adxl367_i2c_probe,
.id_table = adxl367_i2c_id,
};
diff --git a/drivers/iio/accel/adxl372_i2c.c b/drivers/iio/accel/adxl372_i2c.c
index e5f310ea65ff..d0690417fd36 100644
--- a/drivers/iio/accel/adxl372_i2c.c
+++ b/drivers/iio/accel/adxl372_i2c.c
@@ -58,7 +58,7 @@ static struct i2c_driver adxl372_i2c_driver = {
.name = "adxl372_i2c",
.of_match_table = adxl372_of_match,
},
- .probe_new = adxl372_i2c_probe,
+ .probe = adxl372_i2c_probe,
.id_table = adxl372_i2c_id,
};
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c
index eb697eeb4301..e8ab0d249351 100644
--- a/drivers/iio/accel/bma180.c
+++ b/drivers/iio/accel/bma180.c
@@ -1134,7 +1134,7 @@ static struct i2c_driver bma180_driver = {
.pm = pm_sleep_ptr(&bma180_pm_ops),
.of_match_table = bma180_of_match,
},
- .probe_new = bma180_probe,
+ .probe = bma180_probe,
.remove = bma180_remove,
.id_table = bma180_ids,
};
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index a68b845f5b4f..e90e2f01550a 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -868,8 +868,7 @@ static int bma400_init(struct bma400_data *data)
ARRAY_SIZE(regulator_names),
regulator_names);
if (ret)
- return dev_err_probe(data->dev, ret, "Failed to get regulators: %d\n",
- ret);
+ return dev_err_probe(data->dev, ret, "Failed to get regulators\n");
/* Try to read chip_id register. It must return 0x90. */
ret = regmap_read(data->regmap, BMA400_CHIP_ID_REG, &val);
diff --git a/drivers/iio/accel/bma400_i2c.c b/drivers/iio/accel/bma400_i2c.c
index 688b06dae669..adf4e3fd2e1d 100644
--- a/drivers/iio/accel/bma400_i2c.c
+++ b/drivers/iio/accel/bma400_i2c.c
@@ -44,7 +44,7 @@ static struct i2c_driver bma400_i2c_driver = {
.name = "bma400",
.of_match_table = bma400_of_i2c_match,
},
- .probe_new = bma400_i2c_probe,
+ .probe = bma400_i2c_probe,
.id_table = bma400_i2c_ids,
};
diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c
index 509cab2bd694..ee1ba134ad42 100644
--- a/drivers/iio/accel/bmc150-accel-i2c.c
+++ b/drivers/iio/accel/bmc150-accel-i2c.c
@@ -269,7 +269,7 @@ static struct i2c_driver bmc150_accel_driver = {
.acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),
.pm = &bmc150_accel_pm_ops,
},
- .probe_new = bmc150_accel_probe,
+ .probe = bmc150_accel_probe,
.remove = bmc150_accel_remove,
.id_table = bmc150_accel_id,
};
diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c
index 38a7d811610e..2f27a5ded94c 100644
--- a/drivers/iio/accel/da280.c
+++ b/drivers/iio/accel/da280.c
@@ -184,7 +184,7 @@ static struct i2c_driver da280_driver = {
.acpi_match_table = ACPI_PTR(da280_acpi_match),
.pm = pm_sleep_ptr(&da280_pm_ops),
},
- .probe_new = da280_probe,
+ .probe = da280_probe,
.id_table = da280_i2c_id,
};
diff --git a/drivers/iio/accel/da311.c b/drivers/iio/accel/da311.c
index 080335fa2ad6..8f919920ced5 100644
--- a/drivers/iio/accel/da311.c
+++ b/drivers/iio/accel/da311.c
@@ -278,7 +278,7 @@ static struct i2c_driver da311_driver = {
.name = "da311",
.pm = pm_sleep_ptr(&da311_pm_ops),
},
- .probe_new = da311_probe,
+ .probe = da311_probe,
.id_table = da311_i2c_id,
};
diff --git a/drivers/iio/accel/dmard06.c b/drivers/iio/accel/dmard06.c
index 7390509aaac0..2e719d60fff8 100644
--- a/drivers/iio/accel/dmard06.c
+++ b/drivers/iio/accel/dmard06.c
@@ -217,7 +217,7 @@ static const struct of_device_id dmard06_of_match[] = {
MODULE_DEVICE_TABLE(of, dmard06_of_match);
static struct i2c_driver dmard06_driver = {
- .probe_new = dmard06_probe,
+ .probe = dmard06_probe,
.id_table = dmard06_id,
.driver = {
.name = DMARD06_DRV_NAME,
diff --git a/drivers/iio/accel/dmard09.c b/drivers/iio/accel/dmard09.c
index 4b7a537f617d..fa98623de579 100644
--- a/drivers/iio/accel/dmard09.c
+++ b/drivers/iio/accel/dmard09.c
@@ -135,7 +135,7 @@ static struct i2c_driver dmard09_driver = {
.driver = {
.name = DMARD09_DRV_NAME
},
- .probe_new = dmard09_probe,
+ .probe = dmard09_probe,
.id_table = dmard09_id,
};
diff --git a/drivers/iio/accel/dmard10.c b/drivers/iio/accel/dmard10.c
index 07e68aed8a13..7745b6ffd1ad 100644
--- a/drivers/iio/accel/dmard10.c
+++ b/drivers/iio/accel/dmard10.c
@@ -241,7 +241,7 @@ static struct i2c_driver dmard10_driver = {
.name = "dmard10",
.pm = pm_sleep_ptr(&dmard10_pm_ops),
},
- .probe_new = dmard10_probe,
+ .probe = dmard10_probe,
.id_table = dmard10_i2c_id,
};
diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c
index 0d672b1469e8..be8a15cb945f 100644
--- a/drivers/iio/accel/fxls8962af-core.c
+++ b/drivers/iio/accel/fxls8962af-core.c
@@ -724,8 +724,7 @@ static const struct iio_event_spec fxls8962af_event[] = {
.sign = 's', \
.realbits = 12, \
.storagebits = 16, \
- .shift = 4, \
- .endianness = IIO_BE, \
+ .endianness = IIO_LE, \
}, \
.event_spec = fxls8962af_event, \
.num_event_specs = ARRAY_SIZE(fxls8962af_event), \
@@ -904,9 +903,10 @@ static int fxls8962af_fifo_transfer(struct fxls8962af_data *data,
int total_length = samples * sample_length;
int ret;
- if (i2c_verify_client(dev))
+ if (i2c_verify_client(dev) &&
+ data->chip_info->chip_id == FXLS8962AF_DEVICE_ID)
/*
- * Due to errata bug:
+ * Due to errata bug (only applicable on fxls8962af):
* E3: FIFO burst read operation error using I2C interface
* We have to avoid burst reads on I2C..
*/
diff --git a/drivers/iio/accel/fxls8962af-i2c.c b/drivers/iio/accel/fxls8962af-i2c.c
index 22640eaebac7..160124673308 100644
--- a/drivers/iio/accel/fxls8962af-i2c.c
+++ b/drivers/iio/accel/fxls8962af-i2c.c
@@ -47,7 +47,7 @@ static struct i2c_driver fxls8962af_driver = {
.of_match_table = fxls8962af_of_match,
.pm = pm_ptr(&fxls8962af_pm_ops),
},
- .probe_new = fxls8962af_probe,
+ .probe = fxls8962af_probe,
.id_table = fxls8962af_id,
};
module_i2c_driver(fxls8962af_driver);
diff --git a/drivers/iio/accel/kionix-kx022a-i2c.c b/drivers/iio/accel/kionix-kx022a-i2c.c
index e6fd02d931b6..b0ac78e85dad 100644
--- a/drivers/iio/accel/kionix-kx022a-i2c.c
+++ b/drivers/iio/accel/kionix-kx022a-i2c.c
@@ -40,8 +40,9 @@ static struct i2c_driver kx022a_i2c_driver = {
.driver = {
.name = "kx022a-i2c",
.of_match_table = kx022a_of_match,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = kx022a_i2c_probe,
+ .probe = kx022a_i2c_probe,
};
module_i2c_driver(kx022a_i2c_driver);
diff --git a/drivers/iio/accel/kionix-kx022a-spi.c b/drivers/iio/accel/kionix-kx022a-spi.c
index 9cd047f7b346..f45a46899a5f 100644
--- a/drivers/iio/accel/kionix-kx022a-spi.c
+++ b/drivers/iio/accel/kionix-kx022a-spi.c
@@ -46,6 +46,7 @@ static struct spi_driver kx022a_spi_driver = {
.driver = {
.name = "kx022a-spi",
.of_match_table = kx022a_of_match,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = kx022a_spi_probe,
.id_table = kx022a_id,
diff --git a/drivers/iio/accel/kionix-kx022a.c b/drivers/iio/accel/kionix-kx022a.c
index b8636fa8eaeb..4ea3c6718ed4 100644
--- a/drivers/iio/accel/kionix-kx022a.c
+++ b/drivers/iio/accel/kionix-kx022a.c
@@ -516,17 +516,6 @@ static int kx022a_read_raw(struct iio_dev *idev,
return -EINVAL;
};
-static int kx022a_validate_trigger(struct iio_dev *idev,
- struct iio_trigger *trig)
-{
- struct kx022a_data *data = iio_priv(idev);
-
- if (data->trig != trig)
- return -EINVAL;
-
- return 0;
-}
-
static int kx022a_set_watermark(struct iio_dev *idev, unsigned int val)
{
struct kx022a_data *data = iio_priv(idev);
@@ -725,7 +714,7 @@ static const struct iio_info kx022a_info = {
.write_raw = &kx022a_write_raw,
.read_avail = &kx022a_read_avail,
- .validate_trigger = kx022a_validate_trigger,
+ .validate_trigger = iio_validate_own_trigger,
.hwfifo_set_watermark = kx022a_set_watermark,
.hwfifo_flush_to_buffer = kx022a_fifo_flush,
};
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
index 98da4bda22df..894709286b0c 100644
--- a/drivers/iio/accel/kxcjk-1013.c
+++ b/drivers/iio/accel/kxcjk-1013.c
@@ -1732,7 +1732,7 @@ static struct i2c_driver kxcjk1013_driver = {
.of_match_table = kxcjk1013_of_match,
.pm = &kxcjk1013_pm_ops,
},
- .probe_new = kxcjk1013_probe,
+ .probe = kxcjk1013_probe,
.remove = kxcjk1013_remove,
.id_table = kxcjk1013_id,
};
diff --git a/drivers/iio/accel/kxsd9-i2c.c b/drivers/iio/accel/kxsd9-i2c.c
index 6b3683ddce36..3bc9ee1f9db3 100644
--- a/drivers/iio/accel/kxsd9-i2c.c
+++ b/drivers/iio/accel/kxsd9-i2c.c
@@ -54,7 +54,7 @@ static struct i2c_driver kxsd9_i2c_driver = {
.of_match_table = kxsd9_of_match,
.pm = pm_ptr(&kxsd9_dev_pm_ops),
},
- .probe_new = kxsd9_i2c_probe,
+ .probe = kxsd9_i2c_probe,
.remove = kxsd9_i2c_remove,
.id_table = kxsd9_i2c_id,
};
diff --git a/drivers/iio/accel/mc3230.c b/drivers/iio/accel/mc3230.c
index efc21871de42..6b87c2c9945c 100644
--- a/drivers/iio/accel/mc3230.c
+++ b/drivers/iio/accel/mc3230.c
@@ -190,7 +190,7 @@ static struct i2c_driver mc3230_driver = {
.name = "mc3230",
.pm = pm_sleep_ptr(&mc3230_pm_ops),
},
- .probe_new = mc3230_probe,
+ .probe = mc3230_probe,
.remove = mc3230_remove,
.id_table = mc3230_i2c_id,
};
diff --git a/drivers/iio/accel/mma7455_i2c.c b/drivers/iio/accel/mma7455_i2c.c
index a3864dbe2761..14f7850a22f0 100644
--- a/drivers/iio/accel/mma7455_i2c.c
+++ b/drivers/iio/accel/mma7455_i2c.c
@@ -46,7 +46,7 @@ static const struct of_device_id mma7455_of_match[] = {
MODULE_DEVICE_TABLE(of, mma7455_of_match);
static struct i2c_driver mma7455_i2c_driver = {
- .probe_new = mma7455_i2c_probe,
+ .probe = mma7455_i2c_probe,
.remove = mma7455_i2c_remove,
.id_table = mma7455_i2c_ids,
.driver = {
diff --git a/drivers/iio/accel/mma7660.c b/drivers/iio/accel/mma7660.c
index b279ca4dcdc0..260cbceaa151 100644
--- a/drivers/iio/accel/mma7660.c
+++ b/drivers/iio/accel/mma7660.c
@@ -266,7 +266,7 @@ static struct i2c_driver mma7660_driver = {
.of_match_table = mma7660_of_match,
.acpi_match_table = mma7660_acpi_id,
},
- .probe_new = mma7660_probe,
+ .probe = mma7660_probe,
.remove = mma7660_remove,
.id_table = mma7660_i2c_id,
};
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index ea14e3aaa30a..6e7399e72221 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -1846,7 +1846,7 @@ static struct i2c_driver mma8452_driver = {
.of_match_table = mma8452_dt_ids,
.pm = &mma8452_pm_ops,
},
- .probe_new = mma8452_probe,
+ .probe = mma8452_probe,
.remove = mma8452_remove,
.id_table = mma8452_id,
};
diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c
index aa4f5842859e..d823f2edc6d4 100644
--- a/drivers/iio/accel/mma9551.c
+++ b/drivers/iio/accel/mma9551.c
@@ -607,7 +607,7 @@ static struct i2c_driver mma9551_driver = {
.acpi_match_table = ACPI_PTR(mma9551_acpi_match),
.pm = pm_ptr(&mma9551_pm_ops),
},
- .probe_new = mma9551_probe,
+ .probe = mma9551_probe,
.remove = mma9551_remove,
.id_table = mma9551_id,
};
diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c
index 0af578ef9d3d..d01aba4aecba 100644
--- a/drivers/iio/accel/mma9553.c
+++ b/drivers/iio/accel/mma9553.c
@@ -1246,7 +1246,7 @@ static struct i2c_driver mma9553_driver = {
.acpi_match_table = ACPI_PTR(mma9553_acpi_match),
.pm = pm_ptr(&mma9553_pm_ops),
},
- .probe_new = mma9553_probe,
+ .probe = mma9553_probe,
.remove = mma9553_remove,
.id_table = mma9553_id,
};
diff --git a/drivers/iio/accel/msa311.c b/drivers/iio/accel/msa311.c
index 6690fa37da8f..6ddcc3c2f840 100644
--- a/drivers/iio/accel/msa311.c
+++ b/drivers/iio/accel/msa311.c
@@ -1294,7 +1294,7 @@ static struct i2c_driver msa311_driver = {
.of_match_table = msa311_of_match,
.pm = pm_ptr(&msa311_pm_ops),
},
- .probe_new = msa311_probe,
+ .probe = msa311_probe,
.id_table = msa311_i2c_id,
};
module_i2c_driver(msa311_driver);
diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c
index b146fc82738f..75d142bc14b4 100644
--- a/drivers/iio/accel/mxc4005.c
+++ b/drivers/iio/accel/mxc4005.c
@@ -488,7 +488,7 @@ static struct i2c_driver mxc4005_driver = {
.name = MXC4005_DRV_NAME,
.acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
},
- .probe_new = mxc4005_probe,
+ .probe = mxc4005_probe,
.id_table = mxc4005_id,
};
diff --git a/drivers/iio/accel/mxc6255.c b/drivers/iio/accel/mxc6255.c
index aa2e660545f8..33c2253561e6 100644
--- a/drivers/iio/accel/mxc6255.c
+++ b/drivers/iio/accel/mxc6255.c
@@ -183,7 +183,7 @@ static struct i2c_driver mxc6255_driver = {
.name = MXC6255_DRV_NAME,
.acpi_match_table = ACPI_PTR(mxc6255_acpi_match),
},
- .probe_new = mxc6255_probe,
+ .probe = mxc6255_probe,
.id_table = mxc6255_id,
};
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 282e539157f8..d2104e14e255 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -1007,6 +1007,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LSM9DS0_IMU_DEV_NAME,
+ [1] = LSM303D_IMU_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_accel_16bit_channels,
.odr = {
diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
index fb9e2d6f4210..71ee861b2980 100644
--- a/drivers/iio/accel/st_accel_i2c.c
+++ b/drivers/iio/accel/st_accel_i2c.c
@@ -206,7 +206,7 @@ static struct i2c_driver st_accel_driver = {
.of_match_table = st_accel_of_match,
.acpi_match_table = ACPI_PTR(st_accel_acpi_match),
},
- .probe_new = st_accel_i2c_probe,
+ .probe = st_accel_i2c_probe,
.id_table = st_accel_id_table,
};
module_i2c_driver(st_accel_driver);
diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c
index 68f680db7505..ef0ae7672253 100644
--- a/drivers/iio/accel/stk8312.c
+++ b/drivers/iio/accel/stk8312.c
@@ -644,7 +644,7 @@ static struct i2c_driver stk8312_driver = {
.name = STK8312_DRIVER_NAME,
.pm = pm_sleep_ptr(&stk8312_pm_ops),
},
- .probe_new = stk8312_probe,
+ .probe = stk8312_probe,
.remove = stk8312_remove,
.id_table = stk8312_i2c_id,
};
diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c
index 44f6e0fbdfcc..3415ac1b4495 100644
--- a/drivers/iio/accel/stk8ba50.c
+++ b/drivers/iio/accel/stk8ba50.c
@@ -543,7 +543,7 @@ static struct i2c_driver stk8ba50_driver = {
.pm = pm_sleep_ptr(&stk8ba50_pm_ops),
.acpi_match_table = ACPI_PTR(stk8ba50_acpi_id),
},
- .probe_new = stk8ba50_probe,
+ .probe = stk8ba50_probe,
.remove = stk8ba50_remove,
.id_table = stk8ba50_i2c_id,
};
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index eb2b09ef5d5b..dc14bde31ac1 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -145,7 +145,7 @@ config AD7606
config AD7606_IFACE_PARALLEL
tristate "Analog Devices AD7606 ADC driver with parallel interface support"
- depends on HAS_IOMEM
+ depends on HAS_IOPORT
select AD7606
help
Say yes here to build parallel interface support for Analog Devices:
@@ -735,6 +735,17 @@ config MAX1363
To compile this driver as a module, choose M here: the module will be
called max1363.
+config MAX77541_ADC
+ tristate "Analog Devices MAX77541 ADC driver"
+ depends on MFD_MAX77541
+ help
+ This driver controls a Analog Devices MAX77541 ADC
+ via I2C bus. This device has one adc. Say yes here to build
+ support for Analog Devices MAX77541 ADC interface.
+
+ To compile this driver as a module, choose M here:
+ the module will be called max77541-adc.
+
config MAX9611
tristate "Maxim max9611/max9612 ADC driver"
depends on I2C
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index e07e4a3e6237..eb6e891790fb 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_MAX11205) += max11205.o
obj-$(CONFIG_MAX11410) += max11410.o
obj-$(CONFIG_MAX1241) += max1241.o
obj-$(CONFIG_MAX1363) += max1363.o
+obj-$(CONFIG_MAX77541_ADC) += max77541-adc.o
obj-$(CONFIG_MAX9611) += max9611.o
obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_MCP3422) += mcp3422.o
diff --git a/drivers/iio/adc/ad7091r5.c b/drivers/iio/adc/ad7091r5.c
index 7d6709da1005..2f048527b7b7 100644
--- a/drivers/iio/adc/ad7091r5.c
+++ b/drivers/iio/adc/ad7091r5.c
@@ -103,7 +103,7 @@ static struct i2c_driver ad7091r5_driver = {
.name = "ad7091r5",
.of_match_table = ad7091r5_dt_ids,
},
- .probe_new = ad7091r5_i2c_probe,
+ .probe = ad7091r5_i2c_probe,
.id_table = ad7091r5_i2c_ids,
};
module_i2c_driver(ad7091r5_driver);
diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index 99bb604b78c8..8685e0b58a83 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -367,7 +367,7 @@ static int ad7192_of_clock_select(struct ad7192_state *st)
clock_sel = AD7192_CLK_INT;
/* use internal clock */
- if (st->mclk) {
+ if (!st->mclk) {
if (of_property_read_bool(np, "adi,int-clock-output-enable"))
clock_sel = AD7192_CLK_INT_CO;
} else {
@@ -380,9 +380,9 @@ static int ad7192_of_clock_select(struct ad7192_state *st)
return clock_sel;
}
-static int ad7192_setup(struct ad7192_state *st, struct device_node *np)
+static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
{
- struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi);
+ struct ad7192_state *st = iio_priv(indio_dev);
bool rej60_en, refin2_en;
bool buf_en, bipolar, burnout_curr_en;
unsigned long long scale_uv;
@@ -1069,7 +1069,7 @@ static int ad7192_probe(struct spi_device *spi)
}
}
- ret = ad7192_setup(st, spi->dev.of_node);
+ ret = ad7192_setup(indio_dev, spi->dev.of_node);
if (ret)
return ret;
diff --git a/drivers/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c
index f9ee189925de..14d02b085d3b 100644
--- a/drivers/iio/adc/ad7291.c
+++ b/drivers/iio/adc/ad7291.c
@@ -553,7 +553,7 @@ static struct i2c_driver ad7291_driver = {
.name = KBUILD_MODNAME,
.of_match_table = ad7291_of_match,
},
- .probe_new = ad7291_probe,
+ .probe = ad7291_probe,
.id_table = ad7291_id,
};
module_i2c_driver(ad7291_driver);
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
index 8f0a3a35e727..b757cc45c4de 100644
--- a/drivers/iio/adc/ad799x.c
+++ b/drivers/iio/adc/ad799x.c
@@ -968,7 +968,7 @@ static struct i2c_driver ad799x_driver = {
.name = "ad799x",
.pm = pm_sleep_ptr(&ad799x_pm_ops),
},
- .probe_new = ad799x_probe,
+ .probe = ad799x_probe,
.remove = ad799x_remove,
.id_table = ad799x_id,
};
diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c
index 38d9d7b2313e..213526c1592f 100644
--- a/drivers/iio/adc/ina2xx-adc.c
+++ b/drivers/iio/adc/ina2xx-adc.c
@@ -1090,7 +1090,7 @@ static struct i2c_driver ina2xx_driver = {
.name = KBUILD_MODNAME,
.of_match_table = ina2xx_of_match,
},
- .probe_new = ina2xx_probe,
+ .probe = ina2xx_probe,
.remove = ina2xx_remove,
.id_table = ina2xx_id,
};
diff --git a/drivers/iio/adc/ltc2471.c b/drivers/iio/adc/ltc2471.c
index eeb2945829eb..97c417c3a4eb 100644
--- a/drivers/iio/adc/ltc2471.c
+++ b/drivers/iio/adc/ltc2471.c
@@ -146,7 +146,7 @@ static struct i2c_driver ltc2471_i2c_driver = {
.driver = {
.name = "ltc2471",
},
- .probe_new = ltc2471_i2c_probe,
+ .probe = ltc2471_i2c_probe,
.id_table = ltc2471_i2c_id,
};
diff --git a/drivers/iio/adc/ltc2485.c b/drivers/iio/adc/ltc2485.c
index 6a23427344ec..859e4314cfa2 100644
--- a/drivers/iio/adc/ltc2485.c
+++ b/drivers/iio/adc/ltc2485.c
@@ -133,7 +133,7 @@ static struct i2c_driver ltc2485_driver = {
.driver = {
.name = "ltc2485",
},
- .probe_new = ltc2485_probe,
+ .probe = ltc2485_probe,
.id_table = ltc2485_id,
};
module_i2c_driver(ltc2485_driver);
diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c
index ec198c6f13d6..5bdd40729611 100644
--- a/drivers/iio/adc/ltc2497.c
+++ b/drivers/iio/adc/ltc2497.c
@@ -163,7 +163,7 @@ static struct i2c_driver ltc2497_driver = {
.name = "ltc2497",
.of_match_table = ltc2497_of_match,
},
- .probe_new = ltc2497_probe,
+ .probe = ltc2497_probe,
.remove = ltc2497_remove,
.id_table = ltc2497_id,
};
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index 73b783b430d7..b31581616ce3 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -1718,7 +1718,7 @@ static struct i2c_driver max1363_driver = {
.name = "max1363",
.of_match_table = max1363_of_match,
},
- .probe_new = max1363_probe,
+ .probe = max1363_probe,
.id_table = max1363_id,
};
module_i2c_driver(max1363_driver);
diff --git a/drivers/iio/adc/max77541-adc.c b/drivers/iio/adc/max77541-adc.c
new file mode 100644
index 000000000000..21d024bde16b
--- /dev/null
+++ b/drivers/iio/adc/max77541-adc.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022 Analog Devices, Inc.
+ * ADI MAX77541 ADC Driver with IIO interface
+ */
+
+#include <linux/bitfield.h>
+#include <linux/iio/iio.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/units.h>
+
+#include <linux/mfd/max77541.h>
+
+enum max77541_adc_range {
+ LOW_RANGE,
+ MID_RANGE,
+ HIGH_RANGE,
+};
+
+enum max77541_adc_channel {
+ MAX77541_ADC_VSYS_V,
+ MAX77541_ADC_VOUT1_V,
+ MAX77541_ADC_VOUT2_V,
+ MAX77541_ADC_TEMP,
+};
+
+static int max77541_adc_offset(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2)
+{
+ switch (chan->channel) {
+ case MAX77541_ADC_TEMP:
+ *val = DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS, 1725);
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int max77541_adc_scale(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2)
+{
+ struct regmap **regmap = iio_priv(indio_dev);
+ unsigned int reg_val;
+ int ret;
+
+ switch (chan->channel) {
+ case MAX77541_ADC_VSYS_V:
+ *val = 25;
+ return IIO_VAL_INT;
+ case MAX77541_ADC_VOUT1_V:
+ case MAX77541_ADC_VOUT2_V:
+ ret = regmap_read(*regmap, MAX77541_REG_M2_CFG1, &reg_val);
+ if (ret)
+ return ret;
+
+ reg_val = FIELD_GET(MAX77541_BITS_MX_CFG1_RNG, reg_val);
+ switch (reg_val) {
+ case LOW_RANGE:
+ *val = 6;
+ *val2 = 250000;
+ break;
+ case MID_RANGE:
+ *val = 12;
+ *val2 = 500000;
+ break;
+ case HIGH_RANGE:
+ *val = 25;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ case MAX77541_ADC_TEMP:
+ *val = 1725;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int max77541_adc_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val)
+{
+ struct regmap **regmap = iio_priv(indio_dev);
+ int ret;
+
+ ret = regmap_read(*regmap, chan->address, val);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+}
+
+#define MAX77541_ADC_CHANNEL_V(_channel, _name, _type, _reg) \
+ { \
+ .type = _type, \
+ .indexed = 1, \
+ .channel = _channel, \
+ .address = _reg, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .datasheet_name = _name, \
+ }
+
+#define MAX77541_ADC_CHANNEL_TEMP(_channel, _name, _type, _reg) \
+ { \
+ .type = _type, \
+ .indexed = 1, \
+ .channel = _channel, \
+ .address = _reg, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE) |\
+ BIT(IIO_CHAN_INFO_OFFSET),\
+ .datasheet_name = _name, \
+ }
+
+static const struct iio_chan_spec max77541_adc_channels[] = {
+ MAX77541_ADC_CHANNEL_V(MAX77541_ADC_VSYS_V, "vsys_v", IIO_VOLTAGE,
+ MAX77541_REG_ADC_DATA_CH1),
+ MAX77541_ADC_CHANNEL_V(MAX77541_ADC_VOUT1_V, "vout1_v", IIO_VOLTAGE,
+ MAX77541_REG_ADC_DATA_CH2),
+ MAX77541_ADC_CHANNEL_V(MAX77541_ADC_VOUT2_V, "vout2_v", IIO_VOLTAGE,
+ MAX77541_REG_ADC_DATA_CH3),
+ MAX77541_ADC_CHANNEL_TEMP(MAX77541_ADC_TEMP, "temp", IIO_TEMP,
+ MAX77541_REG_ADC_DATA_CH6),
+};
+
+static int max77541_adc_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_OFFSET:
+ return max77541_adc_offset(indio_dev, chan, val, val2);
+ case IIO_CHAN_INFO_SCALE:
+ return max77541_adc_scale(indio_dev, chan, val, val2);
+ case IIO_CHAN_INFO_RAW:
+ return max77541_adc_raw(indio_dev, chan, val);
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info max77541_adc_info = {
+ .read_raw = max77541_adc_read_raw,
+};
+
+static int max77541_adc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct iio_dev *indio_dev;
+ struct regmap **regmap;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*regmap));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ regmap = iio_priv(indio_dev);
+
+ *regmap = dev_get_regmap(dev->parent, NULL);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ indio_dev->name = "max77541";
+ indio_dev->info = &max77541_adc_info;
+ indio_dev->channels = max77541_adc_channels;
+ indio_dev->num_channels = ARRAY_SIZE(max77541_adc_channels);
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct platform_device_id max77541_adc_platform_id[] = {
+ { "max77541-adc" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, max77541_adc_platform_id);
+
+static struct platform_driver max77541_adc_driver = {
+ .driver = {
+ .name = "max77541-adc",
+ },
+ .probe = max77541_adc_probe,
+ .id_table = max77541_adc_platform_id,
+};
+module_platform_driver(max77541_adc_driver);
+
+MODULE_AUTHOR("Okan Sahin <Okan.Sahin@analog.com>");
+MODULE_DESCRIPTION("MAX77541 ADC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/max9611.c b/drivers/iio/adc/max9611.c
index cb7f4785423a..76e517b7b1e4 100644
--- a/drivers/iio/adc/max9611.c
+++ b/drivers/iio/adc/max9611.c
@@ -556,7 +556,7 @@ static struct i2c_driver max9611_driver = {
.name = DRIVER_NAME,
.of_match_table = max9611_of_table,
},
- .probe_new = max9611_probe,
+ .probe = max9611_probe,
};
module_i2c_driver(max9611_driver);
diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c
index ada844c3f7ec..0778a8fb6866 100644
--- a/drivers/iio/adc/mcp3422.c
+++ b/drivers/iio/adc/mcp3422.c
@@ -417,7 +417,7 @@ static struct i2c_driver mcp3422_driver = {
.name = "mcp3422",
.of_match_table = mcp3422_of_match,
},
- .probe_new = mcp3422_probe,
+ .probe = mcp3422_probe,
.id_table = mcp3422_id,
};
module_i2c_driver(mcp3422_driver);
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 18937a262af6..af6bfcc19075 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -72,7 +72,7 @@
#define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18)
#define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16)
#define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10
- #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5
+ #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 6
#define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8)
#define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0)
diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c
index c1261ecd400c..d9e1696df7ae 100644
--- a/drivers/iio/adc/nau7802.c
+++ b/drivers/iio/adc/nau7802.c
@@ -544,7 +544,7 @@ static const struct of_device_id nau7802_dt_ids[] = {
MODULE_DEVICE_TABLE(of, nau7802_dt_ids);
static struct i2c_driver nau7802_driver = {
- .probe_new = nau7802_probe,
+ .probe = nau7802_probe,
.id_table = nau7802_i2c_id,
.driver = {
.name = "nau7802",
diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c
index 7dfc9c927a23..27b2632c1037 100644
--- a/drivers/iio/adc/palmas_gpadc.c
+++ b/drivers/iio/adc/palmas_gpadc.c
@@ -14,7 +14,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/delay.h>
-#include <linux/i2c.h>
#include <linux/pm.h>
#include <linux/mfd/palmas.h>
#include <linux/completion.h>
diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c
index c2d5e06f137a..0a4fd3a46113 100644
--- a/drivers/iio/adc/qcom-spmi-adc5.c
+++ b/drivers/iio/adc/qcom-spmi-adc5.c
@@ -114,7 +114,7 @@ enum adc5_cal_val {
* that is an average of multiple measurements.
* @scale_fn_type: Represents the scaling function to convert voltage
* physical units desired by the client for the channel.
- * @datasheet_name: Channel name used in device tree.
+ * @channel_name: Channel name used in device tree.
*/
struct adc5_channel_prop {
unsigned int channel;
@@ -126,7 +126,7 @@ struct adc5_channel_prop {
unsigned int hw_settle_time;
unsigned int avg_samples;
enum vadc_scale_fn_type scale_fn_type;
- const char *datasheet_name;
+ const char *channel_name;
};
/**
@@ -657,8 +657,7 @@ static int adc5_get_fw_channel_data(struct adc5_chip *adc,
chan = chan & ADC_CHANNEL_MASK;
}
- if (chan > ADC5_PARALLEL_ISENSE_VBAT_IDATA ||
- !data->adc_chans[chan].datasheet_name) {
+ if (chan > ADC5_PARALLEL_ISENSE_VBAT_IDATA) {
dev_err(dev, "%s invalid channel number %d\n", name, chan);
return -EINVAL;
}
@@ -669,9 +668,9 @@ static int adc5_get_fw_channel_data(struct adc5_chip *adc,
ret = fwnode_property_read_string(fwnode, "label", &channel_name);
if (ret)
- channel_name = name;
+ channel_name = data->adc_chans[chan].datasheet_name;
- prop->datasheet_name = channel_name;
+ prop->channel_name = channel_name;
ret = fwnode_property_read_u32(fwnode, "qcom,decimation", &value);
if (!ret) {
@@ -861,8 +860,8 @@ static int adc5_get_fw_data(struct adc5_chip *adc)
adc_chan = &adc->data->adc_chans[prop.channel];
iio_chan->channel = prop.channel;
- iio_chan->datasheet_name = prop.datasheet_name;
- iio_chan->extend_name = prop.datasheet_name;
+ iio_chan->datasheet_name = adc_chan->datasheet_name;
+ iio_chan->extend_name = prop.channel_name;
iio_chan->info_mask_separate = adc_chan->info_mask;
iio_chan->type = adc_chan->type;
iio_chan->address = index;
diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c
index bcff0f62b70e..f5c6f1f27b2c 100644
--- a/drivers/iio/adc/qcom-spmi-vadc.c
+++ b/drivers/iio/adc/qcom-spmi-vadc.c
@@ -84,6 +84,7 @@
* that is an average of multiple measurements.
* @scale_fn_type: Represents the scaling function to convert voltage
* physical units desired by the client for the channel.
+ * @channel_name: Channel name used in device tree.
*/
struct vadc_channel_prop {
unsigned int channel;
@@ -93,6 +94,7 @@ struct vadc_channel_prop {
unsigned int hw_settle_time;
unsigned int avg_samples;
enum vadc_scale_fn_type scale_fn_type;
+ const char *channel_name;
};
/**
@@ -495,8 +497,18 @@ static int vadc_fwnode_xlate(struct iio_dev *indio_dev,
return -EINVAL;
}
+static int vadc_read_label(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, char *label)
+{
+ struct vadc_priv *vadc = iio_priv(indio_dev);
+ const char *name = vadc->chan_props[chan->address].channel_name;
+
+ return sysfs_emit(label, "%s\n", name);
+}
+
static const struct iio_info vadc_info = {
.read_raw = vadc_read_raw,
+ .read_label = vadc_read_label,
.fwnode_xlate = vadc_fwnode_xlate,
};
@@ -652,7 +664,7 @@ static int vadc_get_fw_channel_data(struct device *dev,
struct vadc_channel_prop *prop,
struct fwnode_handle *fwnode)
{
- const char *name = fwnode_get_name(fwnode);
+ const char *name = fwnode_get_name(fwnode), *label;
u32 chan, value, varr[2];
int ret;
@@ -667,6 +679,11 @@ static int vadc_get_fw_channel_data(struct device *dev,
return -EINVAL;
}
+ ret = fwnode_property_read_string(fwnode, "label", &label);
+ if (ret)
+ label = vadc_chans[chan].datasheet_name;
+ prop->channel_name = label;
+
/* the channel has DT description */
prop->channel = chan;
diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
index 79448c5ffc2a..4b011f7eddec 100644
--- a/drivers/iio/adc/rockchip_saradc.c
+++ b/drivers/iio/adc/rockchip_saradc.c
@@ -4,6 +4,7 @@
* Copyright (C) 2014 ROCKCHIP, Inc.
*/
+#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
@@ -38,10 +39,31 @@
#define SARADC_TIMEOUT msecs_to_jiffies(100)
#define SARADC_MAX_CHANNELS 8
+/* v2 registers */
+#define SARADC2_CONV_CON 0x000
+#define SARADC_T_PD_SOC 0x004
+#define SARADC_T_DAS_SOC 0x00c
+#define SARADC2_END_INT_EN 0x104
+#define SARADC2_ST_CON 0x108
+#define SARADC2_STATUS 0x10c
+#define SARADC2_END_INT_ST 0x110
+#define SARADC2_DATA_BASE 0x120
+
+#define SARADC2_EN_END_INT BIT(0)
+#define SARADC2_START BIT(4)
+#define SARADC2_SINGLE_MODE BIT(5)
+
+#define SARADC2_CONV_CHANNELS GENMASK(15, 0)
+
+struct rockchip_saradc;
+
struct rockchip_saradc_data {
const struct iio_chan_spec *channels;
int num_channels;
unsigned long clk_rate;
+ void (*start)(struct rockchip_saradc *info, int chn);
+ int (*read)(struct rockchip_saradc *info);
+ void (*power_down)(struct rockchip_saradc *info);
};
struct rockchip_saradc {
@@ -60,27 +82,81 @@ struct rockchip_saradc {
struct notifier_block nb;
};
-static void rockchip_saradc_power_down(struct rockchip_saradc *info)
+static void rockchip_saradc_reset_controller(struct reset_control *reset);
+
+static void rockchip_saradc_start_v1(struct rockchip_saradc *info, int chn)
+{
+ /* 8 clock periods as delay between power up and start cmd */
+ writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC);
+ /* Select the channel to be used and trigger conversion */
+ writel(SARADC_CTRL_POWER_CTRL | (chn & SARADC_CTRL_CHN_MASK) |
+ SARADC_CTRL_IRQ_ENABLE, info->regs + SARADC_CTRL);
+}
+
+static void rockchip_saradc_start_v2(struct rockchip_saradc *info, int chn)
+{
+ int val;
+
+ if (info->reset)
+ rockchip_saradc_reset_controller(info->reset);
+
+ writel_relaxed(0xc, info->regs + SARADC_T_DAS_SOC);
+ writel_relaxed(0x20, info->regs + SARADC_T_PD_SOC);
+ val = FIELD_PREP(SARADC2_EN_END_INT, 1);
+ val |= val << 16;
+ writel_relaxed(val, info->regs + SARADC2_END_INT_EN);
+ val = FIELD_PREP(SARADC2_START, 1) |
+ FIELD_PREP(SARADC2_SINGLE_MODE, 1) |
+ FIELD_PREP(SARADC2_CONV_CHANNELS, chn);
+ val |= val << 16;
+ writel(val, info->regs + SARADC2_CONV_CON);
+}
+
+static void rockchip_saradc_start(struct rockchip_saradc *info, int chn)
+{
+ info->data->start(info, chn);
+}
+
+static int rockchip_saradc_read_v1(struct rockchip_saradc *info)
+{
+ return readl_relaxed(info->regs + SARADC_DATA);
+}
+
+static int rockchip_saradc_read_v2(struct rockchip_saradc *info)
+{
+ int offset;
+
+ /* Clear irq */
+ writel_relaxed(0x1, info->regs + SARADC2_END_INT_ST);
+
+ offset = SARADC2_DATA_BASE + info->last_chan->channel * 0x4;
+
+ return readl_relaxed(info->regs + offset);
+}
+
+static int rockchip_saradc_read(struct rockchip_saradc *info)
+{
+ return info->data->read(info);
+}
+
+static void rockchip_saradc_power_down_v1(struct rockchip_saradc *info)
{
- /* Clear irq & power down adc */
writel_relaxed(0, info->regs + SARADC_CTRL);
}
+static void rockchip_saradc_power_down(struct rockchip_saradc *info)
+{
+ if (info->data->power_down)
+ info->data->power_down(info);
+}
+
static int rockchip_saradc_conversion(struct rockchip_saradc *info,
- struct iio_chan_spec const *chan)
+ struct iio_chan_spec const *chan)
{
reinit_completion(&info->completion);
- /* 8 clock periods as delay between power up and start cmd */
- writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC);
-
info->last_chan = chan;
-
- /* Select the channel to be used and trigger conversion */
- writel(SARADC_CTRL_POWER_CTRL
- | (chan->channel & SARADC_CTRL_CHN_MASK)
- | SARADC_CTRL_IRQ_ENABLE,
- info->regs + SARADC_CTRL);
+ rockchip_saradc_start(info, chan->channel);
if (!wait_for_completion_timeout(&info->completion, SARADC_TIMEOUT))
return -ETIMEDOUT;
@@ -123,7 +199,7 @@ static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id)
struct rockchip_saradc *info = dev_id;
/* Read value */
- info->last_val = readl_relaxed(info->regs + SARADC_DATA);
+ info->last_val = rockchip_saradc_read(info);
info->last_val &= GENMASK(info->last_chan->scan_type.realbits - 1, 0);
rockchip_saradc_power_down(info);
@@ -163,6 +239,9 @@ static const struct rockchip_saradc_data saradc_data = {
.channels = rockchip_saradc_iio_channels,
.num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels),
.clk_rate = 1000000,
+ .start = rockchip_saradc_start_v1,
+ .read = rockchip_saradc_read_v1,
+ .power_down = rockchip_saradc_power_down_v1,
};
static const struct iio_chan_spec rockchip_rk3066_tsadc_iio_channels[] = {
@@ -174,6 +253,9 @@ static const struct rockchip_saradc_data rk3066_tsadc_data = {
.channels = rockchip_rk3066_tsadc_iio_channels,
.num_channels = ARRAY_SIZE(rockchip_rk3066_tsadc_iio_channels),
.clk_rate = 50000,
+ .start = rockchip_saradc_start_v1,
+ .read = rockchip_saradc_read_v1,
+ .power_down = rockchip_saradc_power_down_v1,
};
static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = {
@@ -189,6 +271,9 @@ static const struct rockchip_saradc_data rk3399_saradc_data = {
.channels = rockchip_rk3399_saradc_iio_channels,
.num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels),
.clk_rate = 1000000,
+ .start = rockchip_saradc_start_v1,
+ .read = rockchip_saradc_read_v1,
+ .power_down = rockchip_saradc_power_down_v1,
};
static const struct iio_chan_spec rockchip_rk3568_saradc_iio_channels[] = {
@@ -206,6 +291,28 @@ static const struct rockchip_saradc_data rk3568_saradc_data = {
.channels = rockchip_rk3568_saradc_iio_channels,
.num_channels = ARRAY_SIZE(rockchip_rk3568_saradc_iio_channels),
.clk_rate = 1000000,
+ .start = rockchip_saradc_start_v1,
+ .read = rockchip_saradc_read_v1,
+ .power_down = rockchip_saradc_power_down_v1,
+};
+
+static const struct iio_chan_spec rockchip_rk3588_saradc_iio_channels[] = {
+ SARADC_CHANNEL(0, "adc0", 12),
+ SARADC_CHANNEL(1, "adc1", 12),
+ SARADC_CHANNEL(2, "adc2", 12),
+ SARADC_CHANNEL(3, "adc3", 12),
+ SARADC_CHANNEL(4, "adc4", 12),
+ SARADC_CHANNEL(5, "adc5", 12),
+ SARADC_CHANNEL(6, "adc6", 12),
+ SARADC_CHANNEL(7, "adc7", 12),
+};
+
+static const struct rockchip_saradc_data rk3588_saradc_data = {
+ .channels = rockchip_rk3588_saradc_iio_channels,
+ .num_channels = ARRAY_SIZE(rockchip_rk3588_saradc_iio_channels),
+ .clk_rate = 1000000,
+ .start = rockchip_saradc_start_v2,
+ .read = rockchip_saradc_read_v2,
};
static const struct of_device_id rockchip_saradc_match[] = {
@@ -221,6 +328,9 @@ static const struct of_device_id rockchip_saradc_match[] = {
}, {
.compatible = "rockchip,rk3568-saradc",
.data = &rk3568_saradc_data,
+ }, {
+ .compatible = "rockchip,rk3588-saradc",
+ .data = &rk3588_saradc_data,
},
{},
};
@@ -236,20 +346,6 @@ static void rockchip_saradc_reset_controller(struct reset_control *reset)
reset_control_deassert(reset);
}
-static void rockchip_saradc_clk_disable(void *data)
-{
- struct rockchip_saradc *info = data;
-
- clk_disable_unprepare(info->clk);
-}
-
-static void rockchip_saradc_pclk_disable(void *data)
-{
- struct rockchip_saradc *info = data;
-
- clk_disable_unprepare(info->pclk);
-}
-
static void rockchip_saradc_regulator_disable(void *data)
{
struct rockchip_saradc *info = data;
@@ -298,8 +394,7 @@ out:
}
static int rockchip_saradc_volt_notify(struct notifier_block *nb,
- unsigned long event,
- void *data)
+ unsigned long event, void *data)
{
struct rockchip_saradc *info =
container_of(nb, struct rockchip_saradc, nb);
@@ -319,10 +414,10 @@ static void rockchip_saradc_regulator_unreg_notifier(void *data)
static int rockchip_saradc_probe(struct platform_device *pdev)
{
+ const struct rockchip_saradc_data *match_data;
struct rockchip_saradc *info = NULL;
struct device_node *np = pdev->dev.of_node;
struct iio_dev *indio_dev = NULL;
- const struct of_device_id *match;
int ret;
int irq;
@@ -330,25 +425,23 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
return -ENODEV;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
- if (!indio_dev) {
- dev_err(&pdev->dev, "failed allocating iio device\n");
- return -ENOMEM;
- }
+ if (!indio_dev)
+ return dev_err_probe(&pdev->dev, -ENOMEM,
+ "failed allocating iio device\n");
+
info = iio_priv(indio_dev);
- match = of_match_device(rockchip_saradc_match, &pdev->dev);
- if (!match) {
- dev_err(&pdev->dev, "failed to match device\n");
- return -ENODEV;
- }
+ match_data = of_device_get_match_data(&pdev->dev);
+ if (!match_data)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "failed to match device\n");
- info->data = match->data;
+ info->data = match_data;
/* Sanity check for possible later IP variants with more channels */
- if (info->data->num_channels > SARADC_MAX_CHANNELS) {
- dev_err(&pdev->dev, "max channels exceeded");
- return -EINVAL;
- }
+ if (info->data->num_channels > SARADC_MAX_CHANNELS)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "max channels exceeded");
info->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(info->regs))
@@ -383,16 +476,6 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
return ret;
}
- info->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
- if (IS_ERR(info->pclk))
- return dev_err_probe(&pdev->dev, PTR_ERR(info->pclk),
- "failed to get pclk\n");
-
- info->clk = devm_clk_get(&pdev->dev, "saradc");
- if (IS_ERR(info->clk))
- return dev_err_probe(&pdev->dev, PTR_ERR(info->clk),
- "failed to get adc clock\n");
-
info->vref = devm_regulator_get(&pdev->dev, "vref");
if (IS_ERR(info->vref))
return dev_err_probe(&pdev->dev, PTR_ERR(info->vref),
@@ -406,23 +489,20 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
* This may become user-configurable in the future.
*/
ret = clk_set_rate(info->clk, info->data->clk_rate);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to set adc clk rate\n");
ret = regulator_enable(info->vref);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to enable vref regulator\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to enable vref regulator\n");
+
ret = devm_add_action_or_reset(&pdev->dev,
rockchip_saradc_regulator_disable, info);
- if (ret) {
- dev_err(&pdev->dev, "failed to register devm action, %d\n",
- ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to register devm action\n");
ret = regulator_get_voltage(info->vref);
if (ret < 0)
@@ -430,31 +510,15 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
info->uv_vref = ret;
- ret = clk_prepare_enable(info->pclk);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to enable pclk\n");
- return ret;
- }
- ret = devm_add_action_or_reset(&pdev->dev,
- rockchip_saradc_pclk_disable, info);
- if (ret) {
- dev_err(&pdev->dev, "failed to register devm action, %d\n",
- ret);
- return ret;
- }
+ info->pclk = devm_clk_get_enabled(&pdev->dev, "apb_pclk");
+ if (IS_ERR(info->pclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(info->pclk),
+ "failed to get pclk\n");
- ret = clk_prepare_enable(info->clk);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to enable converter clock\n");
- return ret;
- }
- ret = devm_add_action_or_reset(&pdev->dev,
- rockchip_saradc_clk_disable, info);
- if (ret) {
- dev_err(&pdev->dev, "failed to register devm action, %d\n",
- ret);
- return ret;
- }
+ info->clk = devm_clk_get_enabled(&pdev->dev, "saradc");
+ if (IS_ERR(info->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(info->clk),
+ "failed to get adc clock\n");
platform_set_drvdata(pdev, indio_dev);
diff --git a/drivers/iio/adc/rtq6056.c b/drivers/iio/adc/rtq6056.c
index c1b2e8dc9a26..ad4cea6839b2 100644
--- a/drivers/iio/adc/rtq6056.c
+++ b/drivers/iio/adc/rtq6056.c
@@ -652,7 +652,7 @@ static struct i2c_driver rtq6056_driver = {
.of_match_table = rtq6056_device_match,
.pm = pm_ptr(&rtq6056_pm_ops),
},
- .probe_new = rtq6056_probe,
+ .probe = rtq6056_probe,
};
module_i2c_driver(rtq6056_driver);
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index bd7e2408bf28..f7613efb870d 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -1993,6 +1993,8 @@ static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm
const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
int num_channels = 0, ret;
+ dev_dbg(&indio_dev->dev, "using legacy channel config\n");
+
ret = device_property_count_u32(dev, "st,adc-channels");
if (ret > adc_info->max_channels) {
dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c
index c663dc59d459..50c450e7a55f 100644
--- a/drivers/iio/adc/ti-adc081c.c
+++ b/drivers/iio/adc/ti-adc081c.c
@@ -235,7 +235,7 @@ static struct i2c_driver adc081c_driver = {
.of_match_table = adc081c_of_match,
.acpi_match_table = adc081c_acpi_match,
},
- .probe_new = adc081c_probe,
+ .probe = adc081c_probe,
.id_table = adc081c_id,
};
module_i2c_driver(adc081c_driver);
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index 56af5e148802..075c75a87544 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -1195,7 +1195,7 @@ static struct i2c_driver ads1015_driver = {
.of_match_table = ads1015_of_match,
.pm = &ads1015_pm_ops,
},
- .probe_new = ads1015_probe,
+ .probe = ads1015_probe,
.remove = ads1015_remove,
.id_table = ads1015_id,
};
diff --git a/drivers/iio/adc/ti-ads1100.c b/drivers/iio/adc/ti-ads1100.c
index 6b5aebb82455..1e46f07a9ca6 100644
--- a/drivers/iio/adc/ti-ads1100.c
+++ b/drivers/iio/adc/ti-ads1100.c
@@ -434,7 +434,7 @@ static struct i2c_driver ads1100_driver = {
.of_match_table = ads1100_of_match,
.pm = pm_ptr(&ads1100_pm_ops),
},
- .probe_new = ads1100_probe,
+ .probe = ads1100_probe,
.id_table = ads1100_id,
};
diff --git a/drivers/iio/adc/ti-ads7924.c b/drivers/iio/adc/ti-ads7924.c
index b02abb026966..afdbd04778a8 100644
--- a/drivers/iio/adc/ti-ads7924.c
+++ b/drivers/iio/adc/ti-ads7924.c
@@ -463,7 +463,7 @@ static struct i2c_driver ads7924_driver = {
.name = "ads7924",
.of_match_table = ads7924_of_match,
},
- .probe_new = ads7924_probe,
+ .probe = ads7924_probe,
.id_table = ads7924_id,
};
diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
index 34cf336b3490..f0b71a1220e0 100644
--- a/drivers/iio/adc/xilinx-ams.c
+++ b/drivers/iio/adc/xilinx-ams.c
@@ -1263,7 +1263,7 @@ static int ams_parse_firmware(struct iio_dev *indio_dev)
struct device *dev = indio_dev->dev.parent;
struct fwnode_handle *child = NULL;
struct fwnode_handle *fwnode = dev_fwnode(dev);
- size_t ams_size, dev_size;
+ size_t ams_size;
int ret, ch_cnt = 0, i, rising_off, falling_off;
unsigned int num_channels = 0;
@@ -1320,11 +1320,8 @@ static int ams_parse_firmware(struct iio_dev *indio_dev)
}
}
- dev_size = array_size(sizeof(*dev_channels), num_channels);
- if (dev_size == SIZE_MAX)
- return -ENOMEM;
-
- dev_channels = devm_krealloc(dev, ams_channels, dev_size, GFP_KERNEL);
+ dev_channels = devm_krealloc_array(dev, ams_channels, num_channels,
+ sizeof(*dev_channels), GFP_KERNEL);
if (!dev_channels)
return -ENOMEM;
diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
index 292f2892d223..dba73300f894 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -613,20 +613,17 @@ static int xadc_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *mask)
{
struct xadc *xadc = iio_priv(indio_dev);
- size_t new_size, n;
+ size_t n;
void *data;
n = bitmap_weight(mask, indio_dev->masklength);
- if (check_mul_overflow(n, sizeof(*xadc->data), &new_size))
- return -ENOMEM;
-
- data = devm_krealloc(indio_dev->dev.parent, xadc->data,
- new_size, GFP_KERNEL);
+ data = devm_krealloc_array(indio_dev->dev.parent, xadc->data,
+ n, sizeof(*xadc->data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- memset(data, 0, new_size);
+ memset(data, 0, n * sizeof(*xadc->data));
xadc->data = data;
return 0;
@@ -1281,9 +1278,9 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, unsigned int *conf, int irq)
}
indio_dev->num_channels = num_channels;
- indio_dev->channels = devm_krealloc(dev, channels,
- sizeof(*channels) * num_channels,
- GFP_KERNEL);
+ indio_dev->channels = devm_krealloc_array(dev, channels,
+ num_channels, sizeof(*channels),
+ GFP_KERNEL);
/* If we can't resize the channels array, just use the original */
if (!indio_dev->channels)
indio_dev->channels = channels;
diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c
index e3366cf5eb31..6b0e8218f150 100644
--- a/drivers/iio/addac/ad74413r.c
+++ b/drivers/iio/addac/ad74413r.c
@@ -1317,13 +1317,14 @@ static int ad74413r_setup_gpios(struct ad74413r_state *st)
}
if (config->func == CH_FUNC_DIGITAL_INPUT_LOGIC ||
- config->func == CH_FUNC_DIGITAL_INPUT_LOOP_POWER)
+ config->func == CH_FUNC_DIGITAL_INPUT_LOOP_POWER) {
st->comp_gpio_offsets[comp_gpio_i++] = i;
- strength = config->drive_strength;
- ret = ad74413r_set_comp_drive_strength(st, i, strength);
- if (ret)
- return ret;
+ strength = config->drive_strength;
+ ret = ad74413r_set_comp_drive_strength(st, i, strength);
+ if (ret)
+ return ret;
+ }
ret = ad74413r_set_gpo_config(st, i, gpo_config);
if (ret)
diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c
index f2c2ea79a07f..8d8c8ea94258 100644
--- a/drivers/iio/amplifiers/ad8366.c
+++ b/drivers/iio/amplifiers/ad8366.c
@@ -281,7 +281,7 @@ static int ad8366_probe(struct spi_device *spi)
indio_dev->info = &ad8366_info;
indio_dev->modes = INDIO_DIRECT_MODE;
- ret = ad8366_write(indio_dev, 0 , 0);
+ ret = ad8366_write(indio_dev, 0, 0);
if (ret < 0)
goto error_disable_reg;
diff --git a/drivers/iio/cdc/ad7150.c b/drivers/iio/cdc/ad7150.c
index 79aeb0aaea67..d656d2f12755 100644
--- a/drivers/iio/cdc/ad7150.c
+++ b/drivers/iio/cdc/ad7150.c
@@ -647,7 +647,7 @@ static struct i2c_driver ad7150_driver = {
.name = "ad7150",
.of_match_table = ad7150_of_match,
},
- .probe_new = ad7150_probe,
+ .probe = ad7150_probe,
.id_table = ad7150_id,
};
module_i2c_driver(ad7150_driver);
diff --git a/drivers/iio/cdc/ad7746.c b/drivers/iio/cdc/ad7746.c
index a1db5469f2d1..d11bc3496dda 100644
--- a/drivers/iio/cdc/ad7746.c
+++ b/drivers/iio/cdc/ad7746.c
@@ -809,7 +809,7 @@ static struct i2c_driver ad7746_driver = {
.name = KBUILD_MODNAME,
.of_match_table = ad7746_of_match,
},
- .probe_new = ad7746_probe,
+ .probe = ad7746_probe,
.id_table = ad7746_id,
};
module_i2c_driver(ad7746_driver);
diff --git a/drivers/iio/chemical/ams-iaq-core.c b/drivers/iio/chemical/ams-iaq-core.c
index 0a0fbcdd4469..164facac5db6 100644
--- a/drivers/iio/chemical/ams-iaq-core.c
+++ b/drivers/iio/chemical/ams-iaq-core.c
@@ -179,7 +179,7 @@ static struct i2c_driver ams_iaqcore_driver = {
.name = "ams-iaq-core",
.of_match_table = ams_iaqcore_dt_ids,
},
- .probe_new = ams_iaqcore_probe,
+ .probe = ams_iaqcore_probe,
.id_table = ams_iaqcore_id,
};
module_i2c_driver(ams_iaqcore_driver);
diff --git a/drivers/iio/chemical/atlas-ezo-sensor.c b/drivers/iio/chemical/atlas-ezo-sensor.c
index 307c3488f4bd..8fc926a2d33b 100644
--- a/drivers/iio/chemical/atlas-ezo-sensor.c
+++ b/drivers/iio/chemical/atlas-ezo-sensor.c
@@ -238,7 +238,7 @@ static struct i2c_driver atlas_ezo_driver = {
.name = ATLAS_EZO_DRV_NAME,
.of_match_table = atlas_ezo_dt_ids,
},
- .probe_new = atlas_ezo_probe,
+ .probe = atlas_ezo_probe,
.id_table = atlas_ezo_id,
};
module_i2c_driver(atlas_ezo_driver);
diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c
index 024657bc59e1..fb15bb216019 100644
--- a/drivers/iio/chemical/atlas-sensor.c
+++ b/drivers/iio/chemical/atlas-sensor.c
@@ -767,7 +767,7 @@ static struct i2c_driver atlas_driver = {
.of_match_table = atlas_dt_ids,
.pm = pm_ptr(&atlas_pm_ops),
},
- .probe_new = atlas_probe,
+ .probe = atlas_probe,
.remove = atlas_remove,
.id_table = atlas_id,
};
diff --git a/drivers/iio/chemical/bme680_i2c.c b/drivers/iio/chemical/bme680_i2c.c
index 61b12079858d..1c7076cf91ca 100644
--- a/drivers/iio/chemical/bme680_i2c.c
+++ b/drivers/iio/chemical/bme680_i2c.c
@@ -52,7 +52,7 @@ static struct i2c_driver bme680_i2c_driver = {
.name = "bme680_i2c",
.of_match_table = bme680_of_i2c_match,
},
- .probe_new = bme680_i2c_probe,
+ .probe = bme680_i2c_probe,
.id_table = bme680_i2c_id,
};
module_i2c_driver(bme680_i2c_driver);
diff --git a/drivers/iio/chemical/ccs811.c b/drivers/iio/chemical/ccs811.c
index 6ead80c08924..87741f155c32 100644
--- a/drivers/iio/chemical/ccs811.c
+++ b/drivers/iio/chemical/ccs811.c
@@ -567,7 +567,7 @@ static struct i2c_driver ccs811_driver = {
.name = "ccs811",
.of_match_table = ccs811_dt_ids,
},
- .probe_new = ccs811_probe,
+ .probe = ccs811_probe,
.remove = ccs811_remove,
.id_table = ccs811_id,
};
diff --git a/drivers/iio/chemical/scd30_i2c.c b/drivers/iio/chemical/scd30_i2c.c
index bae479a4721f..bd3b01ded246 100644
--- a/drivers/iio/chemical/scd30_i2c.c
+++ b/drivers/iio/chemical/scd30_i2c.c
@@ -130,7 +130,7 @@ static struct i2c_driver scd30_i2c_driver = {
.of_match_table = scd30_i2c_of_match,
.pm = pm_sleep_ptr(&scd30_pm_ops),
},
- .probe_new = scd30_i2c_probe,
+ .probe = scd30_i2c_probe,
};
module_i2c_driver(scd30_i2c_driver);
diff --git a/drivers/iio/chemical/scd4x.c b/drivers/iio/chemical/scd4x.c
index f7ed9455b3c8..a4f22d926400 100644
--- a/drivers/iio/chemical/scd4x.c
+++ b/drivers/iio/chemical/scd4x.c
@@ -690,7 +690,7 @@ static struct i2c_driver scd4x_i2c_driver = {
.of_match_table = scd4x_dt_ids,
.pm = pm_sleep_ptr(&scd4x_pm_ops),
},
- .probe_new = scd4x_probe,
+ .probe = scd4x_probe,
};
module_i2c_driver(scd4x_i2c_driver);
diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c
index 9d0c68485b63..b509cff9ce37 100644
--- a/drivers/iio/chemical/sgp30.c
+++ b/drivers/iio/chemical/sgp30.c
@@ -575,7 +575,7 @@ static struct i2c_driver sgp_driver = {
.name = "sgp30",
.of_match_table = sgp_dt_ids,
},
- .probe_new = sgp_probe,
+ .probe = sgp_probe,
.remove = sgp_remove,
.id_table = sgp_id,
};
diff --git a/drivers/iio/chemical/sgp40.c b/drivers/iio/chemical/sgp40.c
index c0ea01300908..7f0de14a1956 100644
--- a/drivers/iio/chemical/sgp40.c
+++ b/drivers/iio/chemical/sgp40.c
@@ -368,7 +368,7 @@ static struct i2c_driver sgp40_driver = {
.name = "sgp40",
.of_match_table = sgp40_dt_ids,
},
- .probe_new = sgp40_probe,
+ .probe = sgp40_probe,
.id_table = sgp40_id,
};
module_i2c_driver(sgp40_driver);
diff --git a/drivers/iio/chemical/sps30_i2c.c b/drivers/iio/chemical/sps30_i2c.c
index 0cb5d9b65d62..5c31299813ec 100644
--- a/drivers/iio/chemical/sps30_i2c.c
+++ b/drivers/iio/chemical/sps30_i2c.c
@@ -249,7 +249,7 @@ static struct i2c_driver sps30_i2c_driver = {
.of_match_table = sps30_i2c_of_match,
},
.id_table = sps30_i2c_id,
- .probe_new = sps30_i2c_probe,
+ .probe = sps30_i2c_probe,
};
module_i2c_driver(sps30_i2c_driver);
diff --git a/drivers/iio/chemical/sunrise_co2.c b/drivers/iio/chemical/sunrise_co2.c
index 8440dc0c77cf..cdb8696a4e81 100644
--- a/drivers/iio/chemical/sunrise_co2.c
+++ b/drivers/iio/chemical/sunrise_co2.c
@@ -528,7 +528,7 @@ static struct i2c_driver sunrise_driver = {
.name = DRIVER_NAME,
.of_match_table = sunrise_of_match,
},
- .probe_new = sunrise_probe,
+ .probe = sunrise_probe,
};
module_i2c_driver(sunrise_driver);
diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c
index d4604f7ccd1e..13555f4f401a 100644
--- a/drivers/iio/chemical/vz89x.c
+++ b/drivers/iio/chemical/vz89x.c
@@ -402,7 +402,7 @@ static struct i2c_driver vz89x_driver = {
.name = "vz89x",
.of_match_table = vz89x_dt_ids,
},
- .probe_new = vz89x_probe,
+ .probe = vz89x_probe,
.id_table = vz89x_id,
};
module_i2c_driver(vz89x_driver);
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c
index f01249c1ba93..7712dc6be608 100644
--- a/drivers/iio/dac/ad5064.c
+++ b/drivers/iio/dac/ad5064.c
@@ -1056,7 +1056,7 @@ static struct i2c_driver ad5064_i2c_driver = {
.driver = {
.name = "ad5064",
},
- .probe_new = ad5064_i2c_probe,
+ .probe = ad5064_i2c_probe,
.id_table = ad5064_i2c_ids,
};
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c
index 64b4519f8f5e..2e3e33f92bc0 100644
--- a/drivers/iio/dac/ad5380.c
+++ b/drivers/iio/dac/ad5380.c
@@ -589,7 +589,7 @@ static struct i2c_driver ad5380_i2c_driver = {
.driver = {
.name = "ad5380",
},
- .probe_new = ad5380_i2c_probe,
+ .probe = ad5380_i2c_probe,
.remove = ad5380_i2c_remove,
.id_table = ad5380_i2c_ids,
};
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index aa3130b33456..8103d2cd13f6 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -595,7 +595,7 @@ static struct i2c_driver ad5446_i2c_driver = {
.driver = {
.name = "ad5446",
},
- .probe_new = ad5446_i2c_probe,
+ .probe = ad5446_i2c_probe,
.remove = ad5446_i2c_remove,
.id_table = ad5446_i2c_ids,
};
diff --git a/drivers/iio/dac/ad5593r.c b/drivers/iio/dac/ad5593r.c
index d311567ab324..fae5e5a0e72f 100644
--- a/drivers/iio/dac/ad5593r.c
+++ b/drivers/iio/dac/ad5593r.c
@@ -138,7 +138,7 @@ static struct i2c_driver ad5593r_driver = {
.of_match_table = ad5593r_of_match,
.acpi_match_table = ad5593r_acpi_match,
},
- .probe_new = ad5593r_i2c_probe,
+ .probe = ad5593r_i2c_probe,
.remove = ad5593r_i2c_remove,
.id_table = ad5593r_i2c_ids,
};
diff --git a/drivers/iio/dac/ad5696-i2c.c b/drivers/iio/dac/ad5696-i2c.c
index 8a95f0278018..81541f755a3e 100644
--- a/drivers/iio/dac/ad5696-i2c.c
+++ b/drivers/iio/dac/ad5696-i2c.c
@@ -115,7 +115,7 @@ static struct i2c_driver ad5686_i2c_driver = {
.name = "ad5696",
.of_match_table = ad5686_of_match,
},
- .probe_new = ad5686_i2c_probe,
+ .probe = ad5686_i2c_probe,
.remove = ad5686_i2c_remove,
.id_table = ad5686_i2c_id,
};
diff --git a/drivers/iio/dac/ds4424.c b/drivers/iio/dac/ds4424.c
index a16a6a934d9d..e89e4c054653 100644
--- a/drivers/iio/dac/ds4424.c
+++ b/drivers/iio/dac/ds4424.c
@@ -312,7 +312,7 @@ static struct i2c_driver ds4424_driver = {
.of_match_table = ds4424_of_match,
.pm = pm_sleep_ptr(&ds4424_pm_ops),
},
- .probe_new = ds4424_probe,
+ .probe = ds4424_probe,
.remove = ds4424_remove,
.id_table = ds4424_id,
};
diff --git a/drivers/iio/dac/m62332.c b/drivers/iio/dac/m62332.c
index b692459b0f23..ae53baccec91 100644
--- a/drivers/iio/dac/m62332.c
+++ b/drivers/iio/dac/m62332.c
@@ -238,7 +238,7 @@ static struct i2c_driver m62332_driver = {
.name = "m62332",
.pm = pm_sleep_ptr(&m62332_pm_ops),
},
- .probe_new = m62332_probe,
+ .probe = m62332_probe,
.remove = m62332_remove,
.id_table = m62332_id,
};
diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c
index 25967c39365d..685980184d3c 100644
--- a/drivers/iio/dac/max517.c
+++ b/drivers/iio/dac/max517.c
@@ -203,7 +203,7 @@ static struct i2c_driver max517_driver = {
.name = MAX517_DRV_NAME,
.pm = pm_sleep_ptr(&max517_pm_ops),
},
- .probe_new = max517_probe,
+ .probe = max517_probe,
.id_table = max517_id,
};
module_i2c_driver(max517_driver);
diff --git a/drivers/iio/dac/max5821.c b/drivers/iio/dac/max5821.c
index 23da345b9250..18ba3eaaad75 100644
--- a/drivers/iio/dac/max5821.c
+++ b/drivers/iio/dac/max5821.c
@@ -377,7 +377,7 @@ static struct i2c_driver max5821_driver = {
.of_match_table = max5821_of_match,
.pm = pm_sleep_ptr(&max5821_pm_ops),
},
- .probe_new = max5821_probe,
+ .probe = max5821_probe,
.id_table = max5821_id,
};
module_i2c_driver(max5821_driver);
diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index 3f5661a3718f..f4a3124d29f2 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -536,7 +536,7 @@ static struct i2c_driver mcp4725_driver = {
.of_match_table = mcp4725_of_match,
.pm = pm_sleep_ptr(&mcp4725_pm_ops),
},
- .probe_new = mcp4725_probe,
+ .probe = mcp4725_probe,
.remove = mcp4725_remove,
.id_table = mcp4725_id,
};
diff --git a/drivers/iio/dac/ti-dac5571.c b/drivers/iio/dac/ti-dac5571.c
index 40191947fea3..bab11b9adc25 100644
--- a/drivers/iio/dac/ti-dac5571.c
+++ b/drivers/iio/dac/ti-dac5571.c
@@ -426,7 +426,7 @@ static struct i2c_driver dac5571_driver = {
.name = "ti-dac5571",
.of_match_table = dac5571_of_id,
},
- .probe_new = dac5571_probe,
+ .probe = dac5571_probe,
.remove = dac5571_remove,
.id_table = dac5571_id,
};
diff --git a/drivers/iio/gyro/bmg160_i2c.c b/drivers/iio/gyro/bmg160_i2c.c
index 2b019ee5b2eb..2f9675596138 100644
--- a/drivers/iio/gyro/bmg160_i2c.c
+++ b/drivers/iio/gyro/bmg160_i2c.c
@@ -70,7 +70,7 @@ static struct i2c_driver bmg160_i2c_driver = {
.of_match_table = bmg160_of_match,
.pm = &bmg160_pm_ops,
},
- .probe_new = bmg160_i2c_probe,
+ .probe = bmg160_i2c_probe,
.remove = bmg160_i2c_remove,
.id_table = bmg160_i2c_id,
};
diff --git a/drivers/iio/gyro/fxas21002c_i2c.c b/drivers/iio/gyro/fxas21002c_i2c.c
index 9e2d0f34a672..ee7f21b718e2 100644
--- a/drivers/iio/gyro/fxas21002c_i2c.c
+++ b/drivers/iio/gyro/fxas21002c_i2c.c
@@ -56,7 +56,7 @@ static struct i2c_driver fxas21002c_i2c_driver = {
.pm = pm_ptr(&fxas21002c_pm_ops),
.of_match_table = fxas21002c_i2c_of_match,
},
- .probe_new = fxas21002c_i2c_probe,
+ .probe = fxas21002c_i2c_probe,
.remove = fxas21002c_i2c_remove,
.id_table = fxas21002c_i2c_id,
};
diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c
index ceacd863d3ea..53fb92f0ac7e 100644
--- a/drivers/iio/gyro/itg3200_core.c
+++ b/drivers/iio/gyro/itg3200_core.c
@@ -405,7 +405,7 @@ static struct i2c_driver itg3200_driver = {
.pm = pm_sleep_ptr(&itg3200_pm_ops),
},
.id_table = itg3200_id,
- .probe_new = itg3200_probe,
+ .probe = itg3200_probe,
.remove = itg3200_remove,
};
diff --git a/drivers/iio/gyro/mpu3050-i2c.c b/drivers/iio/gyro/mpu3050-i2c.c
index 2116798226bf..52b6feed2637 100644
--- a/drivers/iio/gyro/mpu3050-i2c.c
+++ b/drivers/iio/gyro/mpu3050-i2c.c
@@ -108,7 +108,7 @@ static const struct of_device_id mpu3050_i2c_of_match[] = {
MODULE_DEVICE_TABLE(of, mpu3050_i2c_of_match);
static struct i2c_driver mpu3050_i2c_driver = {
- .probe_new = mpu3050_i2c_probe,
+ .probe = mpu3050_i2c_probe,
.remove = mpu3050_i2c_remove,
.id_table = mpu3050_i2c_id,
.driver = {
diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
index 797a1c6a0402..5a10a3556ab0 100644
--- a/drivers/iio/gyro/st_gyro_i2c.c
+++ b/drivers/iio/gyro/st_gyro_i2c.c
@@ -111,7 +111,7 @@ static struct i2c_driver st_gyro_driver = {
.name = "st-gyro-i2c",
.of_match_table = st_gyro_of_match,
},
- .probe_new = st_gyro_i2c_probe,
+ .probe = st_gyro_i2c_probe,
.id_table = st_gyro_id_table,
};
module_i2c_driver(st_gyro_driver);
diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c
index 21a6378b7052..ede1e8201311 100644
--- a/drivers/iio/health/afe4404.c
+++ b/drivers/iio/health/afe4404.c
@@ -609,7 +609,7 @@ static struct i2c_driver afe4404_i2c_driver = {
.of_match_table = afe4404_of_match,
.pm = pm_sleep_ptr(&afe4404_pm_ops),
},
- .probe_new = afe4404_probe,
+ .probe = afe4404_probe,
.remove = afe4404_remove,
.id_table = afe4404_ids,
};
diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c
index a80fa9852c22..6236b4d96137 100644
--- a/drivers/iio/health/max30100.c
+++ b/drivers/iio/health/max30100.c
@@ -499,7 +499,7 @@ static struct i2c_driver max30100_driver = {
.name = MAX30100_DRV_NAME,
.of_match_table = max30100_dt_ids,
},
- .probe_new = max30100_probe,
+ .probe = max30100_probe,
.remove = max30100_remove,
.id_table = max30100_id,
};
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 7edcf9e05687..37e619827e8a 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -631,7 +631,7 @@ static struct i2c_driver max30102_driver = {
.name = MAX30102_DRV_NAME,
.of_match_table = max30102_dt_ids,
},
- .probe_new = max30102_probe,
+ .probe = max30102_probe,
.remove = max30102_remove,
.id_table = max30102_id,
};
diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c
index f246516bd45e..37a35d1153d5 100644
--- a/drivers/iio/humidity/am2315.c
+++ b/drivers/iio/humidity/am2315.c
@@ -262,7 +262,7 @@ static struct i2c_driver am2315_driver = {
.driver = {
.name = "am2315",
},
- .probe_new = am2315_probe,
+ .probe = am2315_probe,
.id_table = am2315_i2c_id,
};
diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c
index 49a950d739e4..202014da2785 100644
--- a/drivers/iio/humidity/hdc100x.c
+++ b/drivers/iio/humidity/hdc100x.c
@@ -428,7 +428,7 @@ static struct i2c_driver hdc100x_driver = {
.of_match_table = hdc100x_dt_ids,
.acpi_match_table = hdc100x_acpi_match,
},
- .probe_new = hdc100x_probe,
+ .probe = hdc100x_probe,
.id_table = hdc100x_id,
};
module_i2c_driver(hdc100x_driver);
diff --git a/drivers/iio/humidity/hdc2010.c b/drivers/iio/humidity/hdc2010.c
index c8fddd612e06..f5867659e00f 100644
--- a/drivers/iio/humidity/hdc2010.c
+++ b/drivers/iio/humidity/hdc2010.c
@@ -338,7 +338,7 @@ static struct i2c_driver hdc2010_driver = {
.name = "hdc2010",
.of_match_table = hdc2010_dt_ids,
},
- .probe_new = hdc2010_probe,
+ .probe = hdc2010_probe,
.remove = hdc2010_remove,
.id_table = hdc2010_id,
};
diff --git a/drivers/iio/humidity/hts221_i2c.c b/drivers/iio/humidity/hts221_i2c.c
index d81869423cf0..30f2068ea156 100644
--- a/drivers/iio/humidity/hts221_i2c.c
+++ b/drivers/iio/humidity/hts221_i2c.c
@@ -65,7 +65,7 @@ static struct i2c_driver hts221_driver = {
.of_match_table = hts221_i2c_of_match,
.acpi_match_table = ACPI_PTR(hts221_acpi_match),
},
- .probe_new = hts221_i2c_probe,
+ .probe = hts221_i2c_probe,
.id_table = hts221_i2c_id_table,
};
module_i2c_driver(hts221_driver);
diff --git a/drivers/iio/humidity/htu21.c b/drivers/iio/humidity/htu21.c
index 8411a9f3e828..39e886075299 100644
--- a/drivers/iio/humidity/htu21.c
+++ b/drivers/iio/humidity/htu21.c
@@ -244,7 +244,7 @@ static const struct of_device_id htu21_of_match[] = {
MODULE_DEVICE_TABLE(of, htu21_of_match);
static struct i2c_driver htu21_driver = {
- .probe_new = htu21_probe,
+ .probe = htu21_probe,
.id_table = htu21_id,
.driver = {
.name = "htu21",
diff --git a/drivers/iio/humidity/si7005.c b/drivers/iio/humidity/si7005.c
index fa1faf168c8d..ebfb79bc9edc 100644
--- a/drivers/iio/humidity/si7005.c
+++ b/drivers/iio/humidity/si7005.c
@@ -173,7 +173,7 @@ static struct i2c_driver si7005_driver = {
.driver = {
.name = "si7005",
},
- .probe_new = si7005_probe,
+ .probe = si7005_probe,
.id_table = si7005_id,
};
module_i2c_driver(si7005_driver);
diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c
index 3e50592e8e68..fb1006649328 100644
--- a/drivers/iio/humidity/si7020.c
+++ b/drivers/iio/humidity/si7020.c
@@ -155,7 +155,7 @@ static struct i2c_driver si7020_driver = {
.name = "si7020",
.of_match_table = si7020_dt_ids,
},
- .probe_new = si7020_probe,
+ .probe = si7020_probe,
.id_table = si7020_id,
};
diff --git a/drivers/iio/imu/bmi160/bmi160_i2c.c b/drivers/iio/imu/bmi160/bmi160_i2c.c
index 2ca907d396a0..81652c08e644 100644
--- a/drivers/iio/imu/bmi160/bmi160_i2c.c
+++ b/drivers/iio/imu/bmi160/bmi160_i2c.c
@@ -60,7 +60,7 @@ static struct i2c_driver bmi160_i2c_driver = {
.acpi_match_table = bmi160_acpi_match,
.of_match_table = bmi160_of_match,
},
- .probe_new = bmi160_i2c_probe,
+ .probe = bmi160_i2c_probe,
.id_table = bmi160_i2c_id,
};
module_i2c_driver(bmi160_i2c_driver);
diff --git a/drivers/iio/imu/bno055/bno055_i2c.c b/drivers/iio/imu/bno055/bno055_i2c.c
index c1bbc0fe34f9..6ecd750c6b76 100644
--- a/drivers/iio/imu/bno055/bno055_i2c.c
+++ b/drivers/iio/imu/bno055/bno055_i2c.c
@@ -46,7 +46,7 @@ static struct i2c_driver bno055_driver = {
.name = "bno055-i2c",
.of_match_table = bno055_i2c_of_match,
},
- .probe_new = bno055_i2c_probe,
+ .probe = bno055_i2c_probe,
.id_table = bno055_i2c_id,
};
module_i2c_driver(bno055_driver);
diff --git a/drivers/iio/imu/fxos8700_i2c.c b/drivers/iio/imu/fxos8700_i2c.c
index a74a15fda8cb..2ace306d0f9a 100644
--- a/drivers/iio/imu/fxos8700_i2c.c
+++ b/drivers/iio/imu/fxos8700_i2c.c
@@ -60,7 +60,7 @@ static struct i2c_driver fxos8700_i2c_driver = {
.acpi_match_table = ACPI_PTR(fxos8700_acpi_match),
.of_match_table = fxos8700_of_match,
},
- .probe_new = fxos8700_i2c_probe,
+ .probe = fxos8700_i2c_probe,
.id_table = fxos8700_i2c_id,
};
module_i2c_driver(fxos8700_i2c_driver);
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
index eb2681ad375f..1af559403ba6 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
@@ -98,7 +98,7 @@ static struct i2c_driver inv_icm42600_driver = {
.of_match_table = inv_icm42600_of_matches,
.pm = pm_ptr(&inv_icm42600_pm_ops),
},
- .probe_new = inv_icm42600_probe,
+ .probe = inv_icm42600_probe,
};
module_i2c_driver(inv_icm42600_driver);
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c
index 7f2dc41f807b..37cbf08acb3a 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c
@@ -93,8 +93,8 @@ static bool inv_validate_period(uint32_t period, uint32_t mult)
return false;
}
-static bool inv_compute_chip_period(struct inv_icm42600_timestamp *ts,
- uint32_t mult, uint32_t period)
+static bool inv_update_chip_period(struct inv_icm42600_timestamp *ts,
+ uint32_t mult, uint32_t period)
{
uint32_t new_chip_period;
@@ -104,10 +104,31 @@ static bool inv_compute_chip_period(struct inv_icm42600_timestamp *ts,
/* update chip internal period estimation */
new_chip_period = period / mult;
inv_update_acc(&ts->chip_period, new_chip_period);
+ ts->period = ts->mult * ts->chip_period.val;
return true;
}
+static void inv_align_timestamp_it(struct inv_icm42600_timestamp *ts)
+{
+ int64_t delta, jitter;
+ int64_t adjust;
+
+ /* delta time between last sample and last interrupt */
+ delta = ts->it.lo - ts->timestamp;
+
+ /* adjust timestamp while respecting jitter */
+ jitter = div_s64((int64_t)ts->period * INV_ICM42600_TIMESTAMP_JITTER, 100);
+ if (delta > jitter)
+ adjust = jitter;
+ else if (delta < -jitter)
+ adjust = -jitter;
+ else
+ adjust = 0;
+
+ ts->timestamp += adjust;
+}
+
void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts,
uint32_t fifo_period, size_t fifo_nb,
size_t sensor_nb, int64_t timestamp)
@@ -116,7 +137,6 @@ void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts,
int64_t delta, interval;
const uint32_t fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD;
uint32_t period = ts->period;
- int32_t m;
bool valid = false;
if (fifo_nb == 0)
@@ -130,10 +150,7 @@ void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts,
if (it->lo != 0) {
/* compute period: delta time divided by number of samples */
period = div_s64(delta, fifo_nb);
- valid = inv_compute_chip_period(ts, fifo_mult, period);
- /* update sensor period if chip internal period is updated */
- if (valid)
- ts->period = ts->mult * ts->chip_period.val;
+ valid = inv_update_chip_period(ts, fifo_mult, period);
}
/* no previous data, compute theoritical value from interrupt */
@@ -145,22 +162,8 @@ void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts,
}
/* if interrupt interval is valid, sync with interrupt timestamp */
- if (valid) {
- /* compute measured fifo_period */
- fifo_period = fifo_mult * ts->chip_period.val;
- /* delta time between last sample and last interrupt */
- delta = it->lo - ts->timestamp;
- /* if there are multiple samples, go back to first one */
- while (delta >= (fifo_period * 3 / 2))
- delta -= fifo_period;
- /* compute maximal adjustment value */
- m = INV_ICM42600_TIMESTAMP_MAX_PERIOD(ts->period) - ts->period;
- if (delta > m)
- delta = m;
- else if (delta < -m)
- delta = -m;
- ts->timestamp += delta;
- }
+ if (valid)
+ inv_align_timestamp_it(ts);
}
void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts,
diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig
index 3636b1bc90f1..64dd73dcc4ba 100644
--- a/drivers/iio/imu/inv_mpu6050/Kconfig
+++ b/drivers/iio/imu/inv_mpu6050/Kconfig
@@ -16,7 +16,7 @@ config INV_MPU6050_I2C
select REGMAP_I2C
help
This driver supports the Invensense MPU6050/9150,
- MPU6500/6515/6880/9250/9255, ICM20608(D)/20609/20689, ICM20602/ICM20690
+ MPU6500/6515/6880/9250/9255, ICM20608(D)/20609/20689, ICM20600/20602/20690
and IAM20680 motion tracking devices over I2C.
This driver can be built as a module. The module will be called
inv-mpu6050-i2c.
@@ -28,7 +28,7 @@ config INV_MPU6050_SPI
select REGMAP_SPI
help
This driver supports the Invensense MPU6000,
- MPU6500/6515/6880/9250/9255, ICM20608(D)/20609/20689, ICM20602/ICM20690
+ MPU6500/6515/6880/9250/9255, ICM20608(D)/20609/20689, ICM20600/20602/20690
and IAM20680 motion tracking devices over SPI.
This driver can be built as a module. The module will be called
inv-mpu6050-spi.
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 8a129120b73d..592a6e60b413 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -245,6 +245,15 @@ static const struct inv_mpu6050_hw hw_info[] = {
.startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
{
+ .whoami = INV_ICM20600_WHOAMI_VALUE,
+ .name = "ICM20600",
+ .reg = &reg_set_icm20602,
+ .config = &chip_config_6500,
+ .fifo_size = 1008,
+ .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_ICM20602_GYRO_STARTUP_TIME, INV_ICM20602_ACCEL_STARTUP_TIME},
+ },
+ {
.whoami = INV_ICM20602_WHOAMI_VALUE,
.name = "ICM20602",
.reg = &reg_set_icm20602,
@@ -1597,6 +1606,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels);
indio_dev->available_scan_masks = inv_mpu9x50_scan_masks;
break;
+ case INV_ICM20600:
case INV_ICM20602:
indio_dev->channels = inv_mpu_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 2f2da4cb7321..410ea39fd495 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -32,6 +32,7 @@ static bool inv_mpu_i2c_aux_bus(struct device *dev)
case INV_ICM20608D:
case INV_ICM20609:
case INV_ICM20689:
+ case INV_ICM20600:
case INV_ICM20602:
case INV_IAM20680:
/* no i2c auxiliary bus on the chip */
@@ -183,6 +184,7 @@ static const struct i2c_device_id inv_mpu_id[] = {
{"icm20608d", INV_ICM20608D},
{"icm20609", INV_ICM20609},
{"icm20689", INV_ICM20689},
+ {"icm20600", INV_ICM20600},
{"icm20602", INV_ICM20602},
{"icm20690", INV_ICM20690},
{"iam20680", INV_IAM20680},
@@ -237,6 +239,10 @@ static const struct of_device_id inv_of_match[] = {
.data = (void *)INV_ICM20689
},
{
+ .compatible = "invensense,icm20600",
+ .data = (void *)INV_ICM20600
+ },
+ {
.compatible = "invensense,icm20602",
.data = (void *)INV_ICM20602
},
@@ -259,7 +265,7 @@ static const struct acpi_device_id inv_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, inv_acpi_match);
static struct i2c_driver inv_mpu_driver = {
- .probe_new = inv_mpu_probe,
+ .probe = inv_mpu_probe,
.remove = inv_mpu_remove,
.id_table = inv_mpu_id,
.driver = {
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index 94b54c501ec0..b4ab2c397d0f 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -79,6 +79,7 @@ enum inv_devices {
INV_ICM20608D,
INV_ICM20609,
INV_ICM20689,
+ INV_ICM20600,
INV_ICM20602,
INV_ICM20690,
INV_IAM20680,
@@ -398,6 +399,7 @@ struct inv_mpu6050_state {
#define INV_ICM20608D_WHOAMI_VALUE 0xAE
#define INV_ICM20609_WHOAMI_VALUE 0xA6
#define INV_ICM20689_WHOAMI_VALUE 0x98
+#define INV_ICM20600_WHOAMI_VALUE 0x11
#define INV_ICM20602_WHOAMI_VALUE 0x12
#define INV_ICM20690_WHOAMI_VALUE 0x20
#define INV_IAM20680_WHOAMI_VALUE 0xA9
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
index 89f46c2f213d..05451ca1580b 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
@@ -76,6 +76,7 @@ static const struct spi_device_id inv_mpu_id[] = {
{"icm20608d", INV_ICM20608D},
{"icm20609", INV_ICM20609},
{"icm20689", INV_ICM20689},
+ {"icm20600", INV_ICM20600},
{"icm20602", INV_ICM20602},
{"icm20690", INV_ICM20690},
{"iam20680", INV_IAM20680},
@@ -126,6 +127,10 @@ static const struct of_device_id inv_of_match[] = {
.data = (void *)INV_ICM20689
},
{
+ .compatible = "invensense,icm20600",
+ .data = (void *)INV_ICM20600
+ },
+ {
.compatible = "invensense,icm20602",
.data = (void *)INV_ICM20602
},
diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c
index 53ba020fa5d0..958167b31241 100644
--- a/drivers/iio/imu/kmx61.c
+++ b/drivers/iio/imu/kmx61.c
@@ -1517,7 +1517,7 @@ static struct i2c_driver kmx61_driver = {
.acpi_match_table = ACPI_PTR(kmx61_acpi_match),
.pm = pm_ptr(&kmx61_pm_ops),
},
- .probe_new = kmx61_probe,
+ .probe = kmx61_probe,
.remove = kmx61_remove,
.id_table = kmx61_id,
};
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
index 020717f92363..911444ec57c0 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
@@ -179,7 +179,7 @@ static struct i2c_driver st_lsm6dsx_driver = {
.of_match_table = st_lsm6dsx_i2c_of_match,
.acpi_match_table = st_lsm6dsx_i2c_acpi_match,
},
- .probe_new = st_lsm6dsx_i2c_probe,
+ .probe = st_lsm6dsx_i2c_probe,
.id_table = st_lsm6dsx_i2c_id_table,
};
module_i2c_driver(st_lsm6dsx_driver);
diff --git a/drivers/iio/imu/st_lsm9ds0/Kconfig b/drivers/iio/imu/st_lsm9ds0/Kconfig
index d29558edee60..7aef714b6ecb 100644
--- a/drivers/iio/imu/st_lsm9ds0/Kconfig
+++ b/drivers/iio/imu/st_lsm9ds0/Kconfig
@@ -10,7 +10,8 @@ config IIO_ST_LSM9DS0
help
Say yes here to build support for STMicroelectronics LSM9DS0 IMU
- sensor. Supported devices: accelerometer/magnetometer of lsm9ds0.
+ sensor. Supported devices: accelerometer/magnetometer of lsm9ds0
+ and lsm303d.
To compile this driver as a module, choose M here: the module
will be called st_lsm9ds0.
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
index a90138d8b06a..61d855083aa0 100644
--- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
@@ -19,6 +19,10 @@
static const struct of_device_id st_lsm9ds0_of_match[] = {
{
+ .compatible = "st,lsm303d-imu",
+ .data = LSM303D_IMU_DEV_NAME,
+ },
+ {
.compatible = "st,lsm9ds0-imu",
.data = LSM9DS0_IMU_DEV_NAME,
},
@@ -27,11 +31,18 @@ static const struct of_device_id st_lsm9ds0_of_match[] = {
MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match);
static const struct i2c_device_id st_lsm9ds0_id_table[] = {
+ { LSM303D_IMU_DEV_NAME },
{ LSM9DS0_IMU_DEV_NAME },
{}
};
MODULE_DEVICE_TABLE(i2c, st_lsm9ds0_id_table);
+static const struct acpi_device_id st_lsm9ds0_acpi_match[] = {
+ {"ACCL0001", (kernel_ulong_t)LSM303D_IMU_DEV_NAME},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, st_lsm9ds0_acpi_match);
+
static const struct regmap_config st_lsm9ds0_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -68,8 +79,9 @@ static struct i2c_driver st_lsm9ds0_driver = {
.driver = {
.name = "st-lsm9ds0-i2c",
.of_match_table = st_lsm9ds0_of_match,
+ .acpi_match_table = st_lsm9ds0_acpi_match,
},
- .probe_new = st_lsm9ds0_i2c_probe,
+ .probe = st_lsm9ds0_i2c_probe,
.id_table = st_lsm9ds0_id_table,
};
module_i2c_driver(st_lsm9ds0_driver);
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
index b743bf3546a7..8cc041d56cf7 100644
--- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
@@ -19,6 +19,10 @@
static const struct of_device_id st_lsm9ds0_of_match[] = {
{
+ .compatible = "st,lsm303d-imu",
+ .data = LSM303D_IMU_DEV_NAME,
+ },
+ {
.compatible = "st,lsm9ds0-imu",
.data = LSM9DS0_IMU_DEV_NAME,
},
@@ -27,6 +31,7 @@ static const struct of_device_id st_lsm9ds0_of_match[] = {
MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match);
static const struct spi_device_id st_lsm9ds0_id_table[] = {
+ { LSM303D_IMU_DEV_NAME },
{ LSM9DS0_IMU_DEV_NAME },
{}
};
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index a7a080bed180..176d31d9f9d8 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -194,7 +194,7 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
written = 0;
add_wait_queue(&rb->pollq, &wait);
do {
- if (indio_dev->info == NULL)
+ if (!indio_dev->info)
return -ENODEV;
if (!iio_buffer_space_available(rb)) {
@@ -210,7 +210,7 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
}
wait_woken(&wait, TASK_INTERRUPTIBLE,
- MAX_SCHEDULE_TIMEOUT);
+ MAX_SCHEDULE_TIMEOUT);
continue;
}
@@ -242,7 +242,7 @@ static __poll_t iio_buffer_poll(struct file *filp,
struct iio_buffer *rb = ib->buffer;
struct iio_dev *indio_dev = ib->indio_dev;
- if (!indio_dev->info || rb == NULL)
+ if (!indio_dev->info || !rb)
return 0;
poll_wait(filp, &rb->pollq, wait);
@@ -407,9 +407,9 @@ static ssize_t iio_scan_el_show(struct device *dev,
/* Note NULL used as error indicator as it doesn't make sense. */
static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
- unsigned int masklength,
- const unsigned long *mask,
- bool strict)
+ unsigned int masklength,
+ const unsigned long *mask,
+ bool strict)
{
if (bitmap_empty(mask, masklength))
return NULL;
@@ -427,7 +427,7 @@ static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
}
static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
- const unsigned long *mask)
+ const unsigned long *mask)
{
if (!indio_dev->setup_ops->validate_scan_mask)
return true;
@@ -446,7 +446,7 @@ static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
* individual buffers request is plausible.
*/
static int iio_scan_mask_set(struct iio_dev *indio_dev,
- struct iio_buffer *buffer, int bit)
+ struct iio_buffer *buffer, int bit)
{
const unsigned long *mask;
unsigned long *trialmask;
@@ -539,7 +539,6 @@ error_ret:
mutex_unlock(&iio_dev_opaque->mlock);
return ret < 0 ? ret : len;
-
}
static ssize_t iio_scan_el_ts_show(struct device *dev,
@@ -706,7 +705,7 @@ static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev)
}
static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
- const unsigned long *mask, bool timestamp)
+ const unsigned long *mask, bool timestamp)
{
unsigned int bytes = 0;
int length, i, largest = 0;
@@ -732,7 +731,7 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
}
static void iio_buffer_activate(struct iio_dev *indio_dev,
- struct iio_buffer *buffer)
+ struct iio_buffer *buffer)
{
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
@@ -753,12 +752,12 @@ static void iio_buffer_deactivate_all(struct iio_dev *indio_dev)
struct iio_buffer *buffer, *_buffer;
list_for_each_entry_safe(buffer, _buffer,
- &iio_dev_opaque->buffer_list, buffer_list)
+ &iio_dev_opaque->buffer_list, buffer_list)
iio_buffer_deactivate(buffer);
}
static int iio_buffer_enable(struct iio_buffer *buffer,
- struct iio_dev *indio_dev)
+ struct iio_dev *indio_dev)
{
if (!buffer->access->enable)
return 0;
@@ -766,7 +765,7 @@ static int iio_buffer_enable(struct iio_buffer *buffer,
}
static int iio_buffer_disable(struct iio_buffer *buffer,
- struct iio_dev *indio_dev)
+ struct iio_dev *indio_dev)
{
if (!buffer->access->disable)
return 0;
@@ -774,7 +773,7 @@ static int iio_buffer_disable(struct iio_buffer *buffer,
}
static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
- struct iio_buffer *buffer)
+ struct iio_buffer *buffer)
{
unsigned int bytes;
@@ -782,13 +781,13 @@ static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
return;
bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
- buffer->scan_timestamp);
+ buffer->scan_timestamp);
buffer->access->set_bytes_per_datum(buffer, bytes);
}
static int iio_buffer_request_update(struct iio_dev *indio_dev,
- struct iio_buffer *buffer)
+ struct iio_buffer *buffer)
{
int ret;
@@ -797,7 +796,7 @@ static int iio_buffer_request_update(struct iio_dev *indio_dev,
ret = buffer->access->request_update(buffer);
if (ret) {
dev_dbg(&indio_dev->dev,
- "Buffer not started: buffer parameter update failed (%d)\n",
+ "Buffer not started: buffer parameter update failed (%d)\n",
ret);
return ret;
}
@@ -807,7 +806,7 @@ static int iio_buffer_request_update(struct iio_dev *indio_dev,
}
static void iio_free_scan_mask(struct iio_dev *indio_dev,
- const unsigned long *mask)
+ const unsigned long *mask)
{
/* If the mask is dynamically allocated free it, otherwise do nothing */
if (!indio_dev->available_scan_masks)
@@ -823,8 +822,9 @@ struct iio_device_config {
};
static int iio_verify_update(struct iio_dev *indio_dev,
- struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer,
- struct iio_device_config *config)
+ struct iio_buffer *insert_buffer,
+ struct iio_buffer *remove_buffer,
+ struct iio_device_config *config)
{
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
unsigned long *compound_mask;
@@ -864,7 +864,7 @@ static int iio_verify_update(struct iio_dev *indio_dev,
if (insert_buffer) {
modes &= insert_buffer->access->modes;
config->watermark = min(config->watermark,
- insert_buffer->watermark);
+ insert_buffer->watermark);
}
/* Definitely possible for devices to support both of these. */
@@ -890,7 +890,7 @@ static int iio_verify_update(struct iio_dev *indio_dev,
/* What scan mask do we actually have? */
compound_mask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL);
- if (compound_mask == NULL)
+ if (!compound_mask)
return -ENOMEM;
scan_timestamp = false;
@@ -911,18 +911,18 @@ static int iio_verify_update(struct iio_dev *indio_dev,
if (indio_dev->available_scan_masks) {
scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks,
- indio_dev->masklength,
- compound_mask,
- strict_scanmask);
+ indio_dev->masklength,
+ compound_mask,
+ strict_scanmask);
bitmap_free(compound_mask);
- if (scan_mask == NULL)
+ if (!scan_mask)
return -EINVAL;
} else {
scan_mask = compound_mask;
}
config->scan_bytes = iio_compute_scan_bytes(indio_dev,
- scan_mask, scan_timestamp);
+ scan_mask, scan_timestamp);
config->scan_mask = scan_mask;
config->scan_timestamp = scan_timestamp;
@@ -954,16 +954,16 @@ static void iio_buffer_demux_free(struct iio_buffer *buffer)
}
static int iio_buffer_add_demux(struct iio_buffer *buffer,
- struct iio_demux_table **p, unsigned int in_loc, unsigned int out_loc,
- unsigned int length)
+ struct iio_demux_table **p, unsigned int in_loc,
+ unsigned int out_loc,
+ unsigned int length)
{
-
if (*p && (*p)->from + (*p)->length == in_loc &&
- (*p)->to + (*p)->length == out_loc) {
+ (*p)->to + (*p)->length == out_loc) {
(*p)->length += length;
} else {
*p = kmalloc(sizeof(**p), GFP_KERNEL);
- if (*p == NULL)
+ if (!(*p))
return -ENOMEM;
(*p)->from = in_loc;
(*p)->to = out_loc;
@@ -1027,7 +1027,7 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev,
out_loc += length;
}
buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
- if (buffer->demux_bounce == NULL) {
+ if (!buffer->demux_bounce) {
ret = -ENOMEM;
goto error_clear_mux_table;
}
@@ -1060,7 +1060,7 @@ error_clear_mux_table:
}
static int iio_enable_buffers(struct iio_dev *indio_dev,
- struct iio_device_config *config)
+ struct iio_device_config *config)
{
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
struct iio_buffer *buffer, *tmp = NULL;
@@ -1078,7 +1078,7 @@ static int iio_enable_buffers(struct iio_dev *indio_dev,
ret = indio_dev->setup_ops->preenable(indio_dev);
if (ret) {
dev_dbg(&indio_dev->dev,
- "Buffer not started: buffer preenable failed (%d)\n", ret);
+ "Buffer not started: buffer preenable failed (%d)\n", ret);
goto err_undo_config;
}
}
@@ -1118,7 +1118,7 @@ static int iio_enable_buffers(struct iio_dev *indio_dev,
ret = indio_dev->setup_ops->postenable(indio_dev);
if (ret) {
dev_dbg(&indio_dev->dev,
- "Buffer not started: postenable failed (%d)\n", ret);
+ "Buffer not started: postenable failed (%d)\n", ret);
goto err_detach_pollfunc;
}
}
@@ -1194,15 +1194,15 @@ static int iio_disable_buffers(struct iio_dev *indio_dev)
}
static int __iio_update_buffers(struct iio_dev *indio_dev,
- struct iio_buffer *insert_buffer,
- struct iio_buffer *remove_buffer)
+ struct iio_buffer *insert_buffer,
+ struct iio_buffer *remove_buffer)
{
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
struct iio_device_config new_config;
int ret;
ret = iio_verify_update(indio_dev, insert_buffer, remove_buffer,
- &new_config);
+ &new_config);
if (ret)
return ret;
@@ -1258,7 +1258,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
return 0;
if (insert_buffer &&
- (insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT))
+ insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT)
return -EINVAL;
mutex_lock(&iio_dev_opaque->info_exist_lock);
@@ -1275,7 +1275,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
goto out_unlock;
}
- if (indio_dev->info == NULL) {
+ if (!indio_dev->info) {
ret = -ENODEV;
goto out_unlock;
}
@@ -1615,7 +1615,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
buffer_attrcount = 0;
if (buffer->attrs) {
- while (buffer->attrs[buffer_attrcount] != NULL)
+ while (buffer->attrs[buffer_attrcount])
buffer_attrcount++;
}
buffer_attrcount += ARRAY_SIZE(iio_buffer_attrs);
@@ -1643,7 +1643,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
}
ret = iio_buffer_add_channel_sysfs(indio_dev, buffer,
- &channels[i]);
+ &channels[i]);
if (ret < 0)
goto error_cleanup_dynamic;
scan_el_attrcount += ret;
@@ -1651,10 +1651,10 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
iio_dev_opaque->scan_index_timestamp =
channels[i].scan_index;
}
- if (indio_dev->masklength && buffer->scan_mask == NULL) {
+ if (indio_dev->masklength && !buffer->scan_mask) {
buffer->scan_mask = bitmap_zalloc(indio_dev->masklength,
GFP_KERNEL);
- if (buffer->scan_mask == NULL) {
+ if (!buffer->scan_mask) {
ret = -ENOMEM;
goto error_cleanup_dynamic;
}
@@ -1771,7 +1771,7 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
goto error_unwind_sysfs_and_mask;
}
- sz = sizeof(*(iio_dev_opaque->buffer_ioctl_handler));
+ sz = sizeof(*iio_dev_opaque->buffer_ioctl_handler);
iio_dev_opaque->buffer_ioctl_handler = kzalloc(sz, GFP_KERNEL);
if (!iio_dev_opaque->buffer_ioctl_handler) {
ret = -ENOMEM;
@@ -1820,14 +1820,14 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev)
* a time.
*/
bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
- const unsigned long *mask)
+ const unsigned long *mask)
{
return bitmap_weight(mask, indio_dev->masklength) == 1;
}
EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot);
static const void *iio_demux(struct iio_buffer *buffer,
- const void *datain)
+ const void *datain)
{
struct iio_demux_table *t;
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index 784dc1e00310..f207e36b12cc 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -322,7 +322,7 @@ int iio_trigger_attach_poll_func(struct iio_trigger *trig,
* this is the case if the IIO device and the trigger device share the
* same parent device.
*/
- if (pf->indio_dev->dev.parent == trig->dev.parent)
+ if (iio_validate_own_trigger(pf->indio_dev, trig))
trig->attached_own_device = true;
return ret;
@@ -729,6 +729,26 @@ bool iio_trigger_using_own(struct iio_dev *indio_dev)
EXPORT_SYMBOL(iio_trigger_using_own);
/**
+ * iio_validate_own_trigger - Check if a trigger and IIO device belong to
+ * the same device
+ * @idev: the IIO device to check
+ * @trig: the IIO trigger to check
+ *
+ * This function can be used as the validate_trigger callback for triggers that
+ * can only be attached to their own device.
+ *
+ * Return: 0 if both the trigger and the IIO device belong to the same
+ * device, -EINVAL otherwise.
+ */
+int iio_validate_own_trigger(struct iio_dev *idev, struct iio_trigger *trig)
+{
+ if (idev->dev.parent != trig->dev.parent)
+ return -EINVAL;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(iio_validate_own_trigger);
+
+/**
* iio_trigger_validate_own_device - Check if a trigger and IIO device belong to
* the same device
* @trig: The IIO trigger to check
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 6fa31fcd71a1..45edba797e4c 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -289,6 +289,20 @@ config JSA1212
To compile this driver as a module, choose M here:
the module will be called jsa1212.
+config ROHM_BU27008
+ tristate "ROHM BU27008 color (RGB+C/IR) sensor"
+ depends on I2C
+ select REGMAP_I2C
+ select IIO_GTS_HELPER
+ help
+ Enable support for the ROHM BU27008 color sensor.
+ The ROHM BU27008 is a sensor with 5 photodiodes (red, green,
+ blue, clear and IR) with four configurable channels. Red and
+ green being always available and two out of the rest three
+ (blue, clear, IR) can be selected to be simultaneously measured.
+ Typical application is adjusting LCD backlight of TVs,
+ mobile phones and tablet PCs.
+
config ROHM_BU27034
tristate "ROHM BU27034 ambient light sensor"
depends on I2C
@@ -413,6 +427,17 @@ config OPT3001
If built as a dynamically linked module, it will be called
opt3001.
+config OPT4001
+ tristate "Texas Instruments OPT4001 Light Sensor"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ If you say Y or M here, you get support for Texas Instruments
+ OPT4001 Ambient Light Sensor.
+
+ If built as a dynamically linked module, it will be called
+ opt4001.
+
config PA12203001
tristate "TXC PA12203001 light and proximity sensor"
depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 985f6feaccd4..c0db4c4c36ec 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -37,7 +37,9 @@ obj-$(CONFIG_MAX44000) += max44000.o
obj-$(CONFIG_MAX44009) += max44009.o
obj-$(CONFIG_NOA1305) += noa1305.o
obj-$(CONFIG_OPT3001) += opt3001.o
+obj-$(CONFIG_OPT4001) += opt4001.o
obj-$(CONFIG_PA12203001) += pa12203001.o
+obj-$(CONFIG_ROHM_BU27008) += rohm-bu27008.o
obj-$(CONFIG_ROHM_BU27034) += rohm-bu27034.o
obj-$(CONFIG_RPR0521) += rpr0521.o
obj-$(CONFIG_SI1133) += si1133.o
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c
index 210a90f44c53..5fd775a20176 100644
--- a/drivers/iio/light/adjd_s311.c
+++ b/drivers/iio/light/adjd_s311.c
@@ -270,7 +270,7 @@ static struct i2c_driver adjd_s311_driver = {
.driver = {
.name = ADJD_S311_DRV_NAME,
},
- .probe_new = adjd_s311_probe,
+ .probe = adjd_s311_probe,
.id_table = adjd_s311_id,
};
module_i2c_driver(adjd_s311_driver);
diff --git a/drivers/iio/light/adux1020.c b/drivers/iio/light/adux1020.c
index 606075350d01..aa4a6c78f0aa 100644
--- a/drivers/iio/light/adux1020.c
+++ b/drivers/iio/light/adux1020.c
@@ -837,7 +837,7 @@ static struct i2c_driver adux1020_driver = {
.name = ADUX1020_DRV_NAME,
.of_match_table = adux1020_of_match,
},
- .probe_new = adux1020_probe,
+ .probe = adux1020_probe,
.id_table = adux1020_id,
};
module_i2c_driver(adux1020_driver);
diff --git a/drivers/iio/light/al3010.c b/drivers/iio/light/al3010.c
index 69cc723e2ac4..8f0119f392b7 100644
--- a/drivers/iio/light/al3010.c
+++ b/drivers/iio/light/al3010.c
@@ -229,7 +229,7 @@ static struct i2c_driver al3010_driver = {
.of_match_table = al3010_of_match,
.pm = pm_sleep_ptr(&al3010_pm_ops),
},
- .probe_new = al3010_probe,
+ .probe = al3010_probe,
.id_table = al3010_id,
};
module_i2c_driver(al3010_driver);
diff --git a/drivers/iio/light/al3320a.c b/drivers/iio/light/al3320a.c
index 9ff28bbf34bb..d5957d85c278 100644
--- a/drivers/iio/light/al3320a.c
+++ b/drivers/iio/light/al3320a.c
@@ -16,6 +16,7 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/mod_devicetable.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -247,13 +248,20 @@ static const struct of_device_id al3320a_of_match[] = {
};
MODULE_DEVICE_TABLE(of, al3320a_of_match);
+static const struct acpi_device_id al3320a_acpi_match[] = {
+ {"CALS0001"},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, al3320a_acpi_match);
+
static struct i2c_driver al3320a_driver = {
.driver = {
.name = AL3320A_DRV_NAME,
.of_match_table = al3320a_of_match,
.pm = pm_sleep_ptr(&al3320a_pm_ops),
+ .acpi_match_table = al3320a_acpi_match,
},
- .probe_new = al3320a_probe,
+ .probe = al3320a_probe,
.id_table = al3320a_id,
};
diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c
index 15dfb753734f..0f978b30a232 100644
--- a/drivers/iio/light/apds9300.c
+++ b/drivers/iio/light/apds9300.c
@@ -504,7 +504,7 @@ static struct i2c_driver apds9300_driver = {
.name = APDS9300_DRV_NAME,
.pm = pm_sleep_ptr(&apds9300_pm_ops),
},
- .probe_new = apds9300_probe,
+ .probe = apds9300_probe,
.remove = apds9300_remove,
.id_table = apds9300_id,
};
diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c
index cc5974a95bd3..1065a340b12b 100644
--- a/drivers/iio/light/apds9960.c
+++ b/drivers/iio/light/apds9960.c
@@ -1131,7 +1131,7 @@ static struct i2c_driver apds9960_driver = {
.pm = &apds9960_pm_ops,
.acpi_match_table = apds9960_acpi_match,
},
- .probe_new = apds9960_probe,
+ .probe = apds9960_probe,
.remove = apds9960_remove,
.id_table = apds9960_id,
};
diff --git a/drivers/iio/light/as73211.c b/drivers/iio/light/as73211.c
index 2307fc531752..ec97a3a46839 100644
--- a/drivers/iio/light/as73211.c
+++ b/drivers/iio/light/as73211.c
@@ -790,7 +790,7 @@ static struct i2c_driver as73211_driver = {
.of_match_table = as73211_of_match,
.pm = pm_sleep_ptr(&as73211_pm_ops),
},
- .probe_new = as73211_probe,
+ .probe = as73211_probe,
.id_table = as73211_id,
};
module_i2c_driver(as73211_driver);
diff --git a/drivers/iio/light/bh1750.c b/drivers/iio/light/bh1750.c
index 390c5b3ad4f6..4b869fa9e5b1 100644
--- a/drivers/iio/light/bh1750.c
+++ b/drivers/iio/light/bh1750.c
@@ -320,7 +320,7 @@ static struct i2c_driver bh1750_driver = {
.of_match_table = bh1750_of_match,
.pm = pm_sleep_ptr(&bh1750_pm_ops),
},
- .probe_new = bh1750_probe,
+ .probe = bh1750_probe,
.remove = bh1750_remove,
.id_table = bh1750_id,
diff --git a/drivers/iio/light/bh1780.c b/drivers/iio/light/bh1780.c
index da9039e5a839..b84166c5fa06 100644
--- a/drivers/iio/light/bh1780.c
+++ b/drivers/iio/light/bh1780.c
@@ -269,7 +269,7 @@ static const struct of_device_id of_bh1780_match[] = {
MODULE_DEVICE_TABLE(of, of_bh1780_match);
static struct i2c_driver bh1780_driver = {
- .probe_new = bh1780_probe,
+ .probe = bh1780_probe,
.remove = bh1780_remove,
.id_table = bh1780_id,
.driver = {
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index d4a34a3bf00d..9df85b3999fa 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -542,7 +542,7 @@ static struct i2c_driver cm32181_driver = {
.of_match_table = cm32181_of_match,
.pm = pm_sleep_ptr(&cm32181_pm_ops),
},
- .probe_new = cm32181_probe,
+ .probe = cm32181_probe,
};
module_i2c_driver(cm32181_driver);
diff --git a/drivers/iio/light/cm3232.c b/drivers/iio/light/cm3232.c
index 43e492f5051d..d48a70efca69 100644
--- a/drivers/iio/light/cm3232.c
+++ b/drivers/iio/light/cm3232.c
@@ -417,7 +417,7 @@ static struct i2c_driver cm3232_driver = {
.pm = pm_sleep_ptr(&cm3232_pm_ops),
},
.id_table = cm3232_id,
- .probe_new = cm3232_probe,
+ .probe = cm3232_probe,
.remove = cm3232_remove,
};
diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c
index e5ce7d0fd272..35d20207a648 100644
--- a/drivers/iio/light/cm3323.c
+++ b/drivers/iio/light/cm3323.c
@@ -266,7 +266,7 @@ static struct i2c_driver cm3323_driver = {
.name = CM3323_DRV_NAME,
.of_match_table = cm3323_of_match,
},
- .probe_new = cm3323_probe,
+ .probe = cm3323_probe,
.id_table = cm3323_id,
};
diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c
index 1707dbf2ce26..97e559acba2b 100644
--- a/drivers/iio/light/cm36651.c
+++ b/drivers/iio/light/cm36651.c
@@ -730,7 +730,7 @@ static struct i2c_driver cm36651_driver = {
.name = "cm36651",
.of_match_table = cm36651_of_match,
},
- .probe_new = cm36651_probe,
+ .probe = cm36651_probe,
.remove = cm36651_remove,
.id_table = cm36651_id,
};
diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c
index c0430db0038a..fec10d5e037e 100644
--- a/drivers/iio/light/gp2ap002.c
+++ b/drivers/iio/light/gp2ap002.c
@@ -710,7 +710,7 @@ static struct i2c_driver gp2ap002_driver = {
.of_match_table = gp2ap002_of_match,
.pm = pm_ptr(&gp2ap002_dev_pm_ops),
},
- .probe_new = gp2ap002_probe,
+ .probe = gp2ap002_probe,
.remove = gp2ap002_remove,
.id_table = gp2ap002_id_table,
};
diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c
index a5bf9da0d2f3..9f41724819b6 100644
--- a/drivers/iio/light/gp2ap020a00f.c
+++ b/drivers/iio/light/gp2ap020a00f.c
@@ -1609,7 +1609,7 @@ static struct i2c_driver gp2ap020a00f_driver = {
.name = GP2A_I2C_NAME,
.of_match_table = gp2ap020a00f_of_match,
},
- .probe_new = gp2ap020a00f_probe,
+ .probe = gp2ap020a00f_probe,
.remove = gp2ap020a00f_remove,
.id_table = gp2ap020a00f_id,
};
diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c
index 141845fb47f9..43484c18b101 100644
--- a/drivers/iio/light/isl29018.c
+++ b/drivers/iio/light/isl29018.c
@@ -865,7 +865,7 @@ static struct i2c_driver isl29018_driver = {
.pm = pm_sleep_ptr(&isl29018_pm_ops),
.of_match_table = isl29018_of_match,
},
- .probe_new = isl29018_probe,
+ .probe = isl29018_probe,
.id_table = isl29018_id,
};
module_i2c_driver(isl29018_driver);
diff --git a/drivers/iio/light/isl29028.c b/drivers/iio/light/isl29028.c
index bcf3a556e41a..5694683389be 100644
--- a/drivers/iio/light/isl29028.c
+++ b/drivers/iio/light/isl29028.c
@@ -698,7 +698,7 @@ static struct i2c_driver isl29028_driver = {
.pm = pm_ptr(&isl29028_pm_ops),
.of_match_table = isl29028_of_match,
},
- .probe_new = isl29028_probe,
+ .probe = isl29028_probe,
.remove = isl29028_remove,
.id_table = isl29028_id,
};
diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c
index b4bd656ca169..f1d3356d3369 100644
--- a/drivers/iio/light/isl29125.c
+++ b/drivers/iio/light/isl29125.c
@@ -337,7 +337,7 @@ static struct i2c_driver isl29125_driver = {
.name = ISL29125_DRV_NAME,
.pm = pm_sleep_ptr(&isl29125_pm_ops),
},
- .probe_new = isl29125_probe,
+ .probe = isl29125_probe,
.remove = isl29125_remove,
.id_table = isl29125_id,
};
diff --git a/drivers/iio/light/jsa1212.c b/drivers/iio/light/jsa1212.c
index d3834d0a0635..37e2807041a1 100644
--- a/drivers/iio/light/jsa1212.c
+++ b/drivers/iio/light/jsa1212.c
@@ -440,7 +440,7 @@ static struct i2c_driver jsa1212_driver = {
.pm = pm_sleep_ptr(&jsa1212_pm_ops),
.acpi_match_table = ACPI_PTR(jsa1212_acpi_match),
},
- .probe_new = jsa1212_probe,
+ .probe = jsa1212_probe,
.remove = jsa1212_remove,
.id_table = jsa1212_id,
};
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index bdbd918213e4..061c122fdc5e 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -1641,7 +1641,7 @@ static struct i2c_driver ltr501_driver = {
.pm = pm_sleep_ptr(&ltr501_pm_ops),
.acpi_match_table = ACPI_PTR(ltr_acpi_match),
},
- .probe_new = ltr501_probe,
+ .probe = ltr501_probe,
.remove = ltr501_remove,
.id_table = ltr501_id,
};
diff --git a/drivers/iio/light/ltrf216a.c b/drivers/iio/light/ltrf216a.c
index 4b8ef36b6912..8de4dd849936 100644
--- a/drivers/iio/light/ltrf216a.c
+++ b/drivers/iio/light/ltrf216a.c
@@ -539,7 +539,7 @@ static struct i2c_driver ltrf216a_driver = {
.pm = pm_ptr(&ltrf216a_pm_ops),
.of_match_table = ltrf216a_of_match,
},
- .probe_new = ltrf216a_probe,
+ .probe = ltrf216a_probe,
.id_table = ltrf216a_id,
};
module_i2c_driver(ltrf216a_driver);
diff --git a/drivers/iio/light/lv0104cs.c b/drivers/iio/light/lv0104cs.c
index c041fa0faa5d..a5445d58fddf 100644
--- a/drivers/iio/light/lv0104cs.c
+++ b/drivers/iio/light/lv0104cs.c
@@ -520,7 +520,7 @@ static struct i2c_driver lv0104cs_i2c_driver = {
.name = "lv0104cs",
},
.id_table = lv0104cs_id,
- .probe_new = lv0104cs_probe,
+ .probe = lv0104cs_probe,
};
module_i2c_driver(lv0104cs_i2c_driver);
diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c
index 5dcabc43a30e..db96c5b73100 100644
--- a/drivers/iio/light/max44000.c
+++ b/drivers/iio/light/max44000.c
@@ -616,7 +616,7 @@ static struct i2c_driver max44000_driver = {
.name = MAX44000_DRV_NAME,
.acpi_match_table = ACPI_PTR(max44000_acpi_match),
},
- .probe_new = max44000_probe,
+ .probe = max44000_probe,
.id_table = max44000_id,
};
diff --git a/drivers/iio/light/max44009.c b/drivers/iio/light/max44009.c
index 176dcad6e8e8..61ce276e86f7 100644
--- a/drivers/iio/light/max44009.c
+++ b/drivers/iio/light/max44009.c
@@ -544,7 +544,7 @@ static struct i2c_driver max44009_driver = {
.name = MAX44009_DRV_NAME,
.of_match_table = max44009_of_match,
},
- .probe_new = max44009_probe,
+ .probe = max44009_probe,
.id_table = max44009_id,
};
module_i2c_driver(max44009_driver);
diff --git a/drivers/iio/light/noa1305.c b/drivers/iio/light/noa1305.c
index eaf548d4649e..1574310020e3 100644
--- a/drivers/iio/light/noa1305.c
+++ b/drivers/iio/light/noa1305.c
@@ -278,7 +278,7 @@ static struct i2c_driver noa1305_driver = {
.name = NOA1305_DRIVER_NAME,
.of_match_table = noa1305_of_match,
},
- .probe_new = noa1305_probe,
+ .probe = noa1305_probe,
.id_table = noa1305_ids,
};
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index ec4f5c2369c4..cb41e5ee8ec1 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -834,7 +834,7 @@ static const struct of_device_id opt3001_of_match[] = {
MODULE_DEVICE_TABLE(of, opt3001_of_match);
static struct i2c_driver opt3001_driver = {
- .probe_new = opt3001_probe,
+ .probe = opt3001_probe,
.remove = opt3001_remove,
.id_table = opt3001_id,
diff --git a/drivers/iio/light/opt4001.c b/drivers/iio/light/opt4001.c
new file mode 100644
index 000000000000..502946bf9f94
--- /dev/null
+++ b/drivers/iio/light/opt4001.c
@@ -0,0 +1,467 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Axis Communications AB
+ *
+ * Datasheet: https://www.ti.com/lit/gpn/opt4001
+ *
+ * Device driver for the Texas Instruments OPT4001.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+/* OPT4001 register set */
+#define OPT4001_LIGHT1_MSB 0x00
+#define OPT4001_LIGHT1_LSB 0x01
+#define OPT4001_CTRL 0x0A
+#define OPT4001_DEVICE_ID 0x11
+
+/* OPT4001 register mask */
+#define OPT4001_EXPONENT_MASK GENMASK(15, 12)
+#define OPT4001_MSB_MASK GENMASK(11, 0)
+#define OPT4001_LSB_MASK GENMASK(15, 8)
+#define OPT4001_COUNTER_MASK GENMASK(7, 4)
+#define OPT4001_CRC_MASK GENMASK(3, 0)
+
+/* OPT4001 device id mask */
+#define OPT4001_DEVICE_ID_MASK GENMASK(11, 0)
+
+/* OPT4001 control registers mask */
+#define OPT4001_CTRL_QWAKE_MASK GENMASK(15, 15)
+#define OPT4001_CTRL_RANGE_MASK GENMASK(13, 10)
+#define OPT4001_CTRL_CONV_TIME_MASK GENMASK(9, 6)
+#define OPT4001_CTRL_OPER_MODE_MASK GENMASK(5, 4)
+#define OPT4001_CTRL_LATCH_MASK GENMASK(3, 3)
+#define OPT4001_CTRL_INT_POL_MASK GENMASK(2, 2)
+#define OPT4001_CTRL_FAULT_COUNT GENMASK(0, 1)
+
+/* OPT4001 constants */
+#define OPT4001_DEVICE_ID_VAL 0x121
+
+/* OPT4001 operating modes */
+#define OPT4001_CTRL_OPER_MODE_OFF 0x0
+#define OPT4001_CTRL_OPER_MODE_FORCED 0x1
+#define OPT4001_CTRL_OPER_MODE_ONE_SHOT 0x2
+#define OPT4001_CTRL_OPER_MODE_CONTINUOUS 0x3
+
+/* OPT4001 conversion control register definitions */
+#define OPT4001_CTRL_CONVERSION_0_6MS 0x0
+#define OPT4001_CTRL_CONVERSION_1MS 0x1
+#define OPT4001_CTRL_CONVERSION_1_8MS 0x2
+#define OPT4001_CTRL_CONVERSION_3_4MS 0x3
+#define OPT4001_CTRL_CONVERSION_6_5MS 0x4
+#define OPT4001_CTRL_CONVERSION_12_7MS 0x5
+#define OPT4001_CTRL_CONVERSION_25MS 0x6
+#define OPT4001_CTRL_CONVERSION_50MS 0x7
+#define OPT4001_CTRL_CONVERSION_100MS 0x8
+#define OPT4001_CTRL_CONVERSION_200MS 0x9
+#define OPT4001_CTRL_CONVERSION_400MS 0xa
+#define OPT4001_CTRL_CONVERSION_800MS 0xb
+
+/* OPT4001 scale light level range definitions */
+#define OPT4001_CTRL_LIGHT_SCALE_AUTO 12
+
+/* OPT4001 default values */
+#define OPT4001_DEFAULT_CONVERSION_TIME OPT4001_CTRL_CONVERSION_800MS
+
+/*
+ * The different packaging of OPT4001 has different constants used when calculating
+ * lux values.
+ */
+struct opt4001_chip_info {
+ int mul;
+ int div;
+ const char *name;
+};
+
+struct opt4001_chip {
+ struct regmap *regmap;
+ struct i2c_client *client;
+ u8 int_time;
+ const struct opt4001_chip_info *chip_info;
+};
+
+static const struct opt4001_chip_info opt4001_sot_5x3_info = {
+ .mul = 4375,
+ .div = 10000000,
+ .name = "opt4001-sot-5x3"
+};
+
+static const struct opt4001_chip_info opt4001_picostar_info = {
+ .mul = 3125,
+ .div = 10000000,
+ .name = "opt4001-picostar"
+};
+
+static const int opt4001_int_time_available[][2] = {
+ { 0, 600 },
+ { 0, 1000 },
+ { 0, 1800 },
+ { 0, 3400 },
+ { 0, 6500 },
+ { 0, 12700 },
+ { 0, 25000 },
+ { 0, 50000 },
+ { 0, 100000 },
+ { 0, 200000 },
+ { 0, 400000 },
+ { 0, 800000 },
+};
+
+/*
+ * Conversion time is integration time + time to set register
+ * this is used as integration time.
+ */
+static const int opt4001_int_time_reg[][2] = {
+ { 600, OPT4001_CTRL_CONVERSION_0_6MS },
+ { 1000, OPT4001_CTRL_CONVERSION_1MS },
+ { 1800, OPT4001_CTRL_CONVERSION_1_8MS },
+ { 3400, OPT4001_CTRL_CONVERSION_3_4MS },
+ { 6500, OPT4001_CTRL_CONVERSION_6_5MS },
+ { 12700, OPT4001_CTRL_CONVERSION_12_7MS },
+ { 25000, OPT4001_CTRL_CONVERSION_25MS },
+ { 50000, OPT4001_CTRL_CONVERSION_50MS },
+ { 100000, OPT4001_CTRL_CONVERSION_100MS },
+ { 200000, OPT4001_CTRL_CONVERSION_200MS },
+ { 400000, OPT4001_CTRL_CONVERSION_400MS },
+ { 800000, OPT4001_CTRL_CONVERSION_800MS },
+};
+
+static int opt4001_als_time_to_index(const u32 als_integration_time)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(opt4001_int_time_available); i++) {
+ if (als_integration_time == opt4001_int_time_available[i][1])
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+static u8 opt4001_calculate_crc(u8 exp, u32 mantissa, u8 count)
+{
+ u8 crc;
+
+ crc = (hweight32(mantissa) + hweight32(exp) + hweight32(count)) % 2;
+ crc |= ((hweight32(mantissa & 0xAAAAA) + hweight32(exp & 0xA)
+ + hweight32(count & 0xA)) % 2) << 1;
+ crc |= ((hweight32(mantissa & 0x88888) + hweight32(exp & 0x8)
+ + hweight32(count & 0x8)) % 2) << 2;
+ crc |= (hweight32(mantissa & 0x80808) % 2) << 3;
+
+ return crc;
+}
+
+static int opt4001_read_lux_value(struct iio_dev *indio_dev,
+ int *val, int *val2)
+{
+ struct opt4001_chip *chip = iio_priv(indio_dev);
+ struct device *dev = &chip->client->dev;
+ unsigned int light1;
+ unsigned int light2;
+ u16 msb;
+ u16 lsb;
+ u8 exp;
+ u8 count;
+ u8 crc;
+ u8 calc_crc;
+ u64 lux_raw;
+ int ret;
+
+ ret = regmap_read(chip->regmap, OPT4001_LIGHT1_MSB, &light1);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read data bytes");
+ return ret;
+ }
+
+ ret = regmap_read(chip->regmap, OPT4001_LIGHT1_LSB, &light2);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read data bytes");
+ return ret;
+ }
+
+ count = FIELD_GET(OPT4001_COUNTER_MASK, light2);
+ exp = FIELD_GET(OPT4001_EXPONENT_MASK, light1);
+ crc = FIELD_GET(OPT4001_CRC_MASK, light2);
+ msb = FIELD_GET(OPT4001_MSB_MASK, light1);
+ lsb = FIELD_GET(OPT4001_LSB_MASK, light2);
+ lux_raw = (msb << 8) + lsb;
+ calc_crc = opt4001_calculate_crc(exp, lux_raw, count);
+ if (calc_crc != crc)
+ return -EIO;
+
+ lux_raw = lux_raw << exp;
+ lux_raw = lux_raw * chip->chip_info->mul;
+ *val = div_u64_rem(lux_raw, chip->chip_info->div, val2);
+ *val2 = *val2 * 100;
+
+ return IIO_VAL_INT_PLUS_NANO;
+}
+
+static int opt4001_set_conf(struct opt4001_chip *chip)
+{
+ struct device *dev = &chip->client->dev;
+ u16 reg;
+ int ret;
+
+ reg = FIELD_PREP(OPT4001_CTRL_RANGE_MASK, OPT4001_CTRL_LIGHT_SCALE_AUTO);
+ reg |= FIELD_PREP(OPT4001_CTRL_CONV_TIME_MASK, chip->int_time);
+ reg |= FIELD_PREP(OPT4001_CTRL_OPER_MODE_MASK, OPT4001_CTRL_OPER_MODE_CONTINUOUS);
+
+ ret = regmap_write(chip->regmap, OPT4001_CTRL, reg);
+ if (ret)
+ dev_err(dev, "Failed to set configuration\n");
+
+ return ret;
+}
+
+static int opt4001_power_down(struct opt4001_chip *chip)
+{
+ struct device *dev = &chip->client->dev;
+ int ret;
+ unsigned int reg;
+
+ ret = regmap_read(chip->regmap, OPT4001_DEVICE_ID, &reg);
+ if (ret) {
+ dev_err(dev, "Failed to read configuration\n");
+ return ret;
+ }
+
+ /* MODE_OFF is 0x0 so just set bits to 0 */
+ reg &= ~OPT4001_CTRL_OPER_MODE_MASK;
+
+ ret = regmap_write(chip->regmap, OPT4001_CTRL, reg);
+ if (ret)
+ dev_err(dev, "Failed to set configuration to power down\n");
+
+ return ret;
+}
+
+static void opt4001_chip_off_action(void *data)
+{
+ struct opt4001_chip *chip = data;
+
+ opt4001_power_down(chip);
+}
+
+static const struct iio_chan_spec opt4001_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME)
+ },
+};
+
+static int opt4001_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct opt4001_chip *chip = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ return opt4001_read_lux_value(indio_dev, val, val2);
+ case IIO_CHAN_INFO_INT_TIME:
+ *val = 0;
+ *val2 = opt4001_int_time_reg[chip->int_time][0];
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int opt4001_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct opt4001_chip *chip = iio_priv(indio_dev);
+ int int_time;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ int_time = opt4001_als_time_to_index(val2);
+ if (int_time < 0)
+ return int_time;
+ chip->int_time = int_time;
+ return opt4001_set_conf(chip);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int opt4001_read_available(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ *length = ARRAY_SIZE(opt4001_int_time_available) * 2;
+ *vals = (const int *)opt4001_int_time_available;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info opt4001_info_no_irq = {
+ .read_raw = opt4001_read_raw,
+ .write_raw = opt4001_write_raw,
+ .read_avail = opt4001_read_available,
+};
+
+static int opt4001_load_defaults(struct opt4001_chip *chip)
+{
+ chip->int_time = OPT4001_DEFAULT_CONVERSION_TIME;
+
+ return opt4001_set_conf(chip);
+}
+
+static bool opt4001_readable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case OPT4001_LIGHT1_MSB:
+ case OPT4001_LIGHT1_LSB:
+ case OPT4001_CTRL:
+ case OPT4001_DEVICE_ID:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool opt4001_writable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case OPT4001_CTRL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool opt4001_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case OPT4001_LIGHT1_MSB:
+ case OPT4001_LIGHT1_LSB:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config opt4001_regmap_config = {
+ .name = "opt4001",
+ .reg_bits = 8,
+ .val_bits = 16,
+ .cache_type = REGCACHE_RBTREE,
+ .max_register = OPT4001_DEVICE_ID,
+ .readable_reg = opt4001_readable_reg,
+ .writeable_reg = opt4001_writable_reg,
+ .volatile_reg = opt4001_volatile_reg,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+};
+
+static int opt4001_probe(struct i2c_client *client)
+{
+ struct opt4001_chip *chip;
+ struct iio_dev *indio_dev;
+ int ret;
+ uint dev_id;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ chip = iio_priv(indio_dev);
+
+ ret = devm_regulator_get_enable(&client->dev, "vdd");
+ if (ret)
+ return dev_err_probe(&client->dev, ret, "Failed to enable vdd supply\n");
+
+ chip->regmap = devm_regmap_init_i2c(client, &opt4001_regmap_config);
+ if (IS_ERR(chip->regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(chip->regmap),
+ "regmap initialization failed\n");
+ chip->client = client;
+
+ indio_dev->info = &opt4001_info_no_irq;
+
+ ret = regmap_reinit_cache(chip->regmap, &opt4001_regmap_config);
+ if (ret)
+ return dev_err_probe(&client->dev, ret,
+ "failed to reinit regmap cache\n");
+
+ ret = regmap_read(chip->regmap, OPT4001_DEVICE_ID, &dev_id);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "Failed to read the device ID register\n");
+
+ dev_id = FIELD_GET(OPT4001_DEVICE_ID_MASK, dev_id);
+ if (dev_id != OPT4001_DEVICE_ID_VAL)
+ dev_warn(&client->dev, "Device ID: %#04x unknown\n", dev_id);
+
+ chip->chip_info = device_get_match_data(&client->dev);
+
+ indio_dev->channels = opt4001_channels;
+ indio_dev->num_channels = ARRAY_SIZE(opt4001_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = chip->chip_info->name;
+
+ ret = opt4001_load_defaults(chip);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "Failed to set sensor defaults\n");
+
+ ret = devm_add_action_or_reset(&client->dev,
+ opt4001_chip_off_action,
+ chip);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "Failed to setup power off action\n");
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+/*
+ * The compatible string determines which constants to use depending on
+ * opt4001 packaging
+ */
+static const struct i2c_device_id opt4001_id[] = {
+ { "opt4001-sot-5x3", (kernel_ulong_t)&opt4001_sot_5x3_info },
+ { "opt4001-picostar", (kernel_ulong_t)&opt4001_picostar_info },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, opt4001_id);
+
+static const struct of_device_id opt4001_of_match[] = {
+ { .compatible = "ti,opt4001-sot-5x3", .data = &opt4001_sot_5x3_info},
+ { .compatible = "ti,opt4001-picostar", .data = &opt4001_picostar_info},
+ {}
+};
+MODULE_DEVICE_TABLE(of, opt4001_of_match);
+
+static struct i2c_driver opt4001_driver = {
+ .driver = {
+ .name = "opt4001",
+ .of_match_table = opt4001_of_match,
+ },
+ .probe = opt4001_probe,
+ .id_table = opt4001_id,
+};
+module_i2c_driver(opt4001_driver);
+
+MODULE_AUTHOR("Stefan Windfeldt-Prytz <stefan.windfeldt-prytz@axis.com>");
+MODULE_DESCRIPTION("Texas Instruments opt4001 ambient light sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/pa12203001.c b/drivers/iio/light/pa12203001.c
index 15a666f15c27..ed241598aefb 100644
--- a/drivers/iio/light/pa12203001.c
+++ b/drivers/iio/light/pa12203001.c
@@ -474,7 +474,7 @@ static struct i2c_driver pa12203001_driver = {
.pm = &pa12203001_pm_ops,
.acpi_match_table = ACPI_PTR(pa12203001_acpi_match),
},
- .probe_new = pa12203001_probe,
+ .probe = pa12203001_probe,
.remove = pa12203001_remove,
.id_table = pa12203001_id,
diff --git a/drivers/iio/light/rohm-bu27008.c b/drivers/iio/light/rohm-bu27008.c
new file mode 100644
index 000000000000..489902bed7f0
--- /dev/null
+++ b/drivers/iio/light/rohm-bu27008.c
@@ -0,0 +1,1026 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * BU27008 ROHM Colour Sensor
+ *
+ * Copyright (c) 2023, ROHM Semiconductor.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/units.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/iio-gts-helper.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define BU27008_REG_SYSTEM_CONTROL 0x40
+#define BU27008_MASK_SW_RESET BIT(7)
+#define BU27008_MASK_PART_ID GENMASK(5, 0)
+#define BU27008_ID 0x1a
+#define BU27008_REG_MODE_CONTROL1 0x41
+#define BU27008_MASK_MEAS_MODE GENMASK(2, 0)
+#define BU27008_MASK_CHAN_SEL GENMASK(3, 2)
+
+#define BU27008_REG_MODE_CONTROL2 0x42
+#define BU27008_MASK_RGBC_GAIN GENMASK(7, 3)
+#define BU27008_MASK_IR_GAIN_LO GENMASK(2, 0)
+#define BU27008_SHIFT_IR_GAIN 3
+
+#define BU27008_REG_MODE_CONTROL3 0x43
+#define BU27008_MASK_VALID BIT(7)
+#define BU27008_MASK_INT_EN BIT(1)
+#define BU27008_INT_EN BU27008_MASK_INT_EN
+#define BU27008_INT_DIS 0
+#define BU27008_MASK_MEAS_EN BIT(0)
+#define BU27008_MEAS_EN BIT(0)
+#define BU27008_MEAS_DIS 0
+
+#define BU27008_REG_DATA0_LO 0x50
+#define BU27008_REG_DATA1_LO 0x52
+#define BU27008_REG_DATA2_LO 0x54
+#define BU27008_REG_DATA3_LO 0x56
+#define BU27008_REG_DATA3_HI 0x57
+#define BU27008_REG_MANUFACTURER_ID 0x92
+#define BU27008_REG_MAX BU27008_REG_MANUFACTURER_ID
+
+/**
+ * enum bu27008_chan_type - BU27008 channel types
+ * @BU27008_RED: Red channel. Always via data0.
+ * @BU27008_GREEN: Green channel. Always via data1.
+ * @BU27008_BLUE: Blue channel. Via data2 (when used).
+ * @BU27008_CLEAR: Clear channel. Via data2 or data3 (when used).
+ * @BU27008_IR: IR channel. Via data3 (when used).
+ * @BU27008_NUM_CHANS: Number of channel types.
+ */
+enum bu27008_chan_type {
+ BU27008_RED,
+ BU27008_GREEN,
+ BU27008_BLUE,
+ BU27008_CLEAR,
+ BU27008_IR,
+ BU27008_NUM_CHANS
+};
+
+/**
+ * enum bu27008_chan - BU27008 physical data channel
+ * @BU27008_DATA0: Always red.
+ * @BU27008_DATA1: Always green.
+ * @BU27008_DATA2: Blue or clear.
+ * @BU27008_DATA3: IR or clear.
+ * @BU27008_NUM_HW_CHANS: Number of physical channels
+ */
+enum bu27008_chan {
+ BU27008_DATA0,
+ BU27008_DATA1,
+ BU27008_DATA2,
+ BU27008_DATA3,
+ BU27008_NUM_HW_CHANS
+};
+
+/* We can always measure red and green at same time */
+#define ALWAYS_SCANNABLE (BIT(BU27008_RED) | BIT(BU27008_GREEN))
+
+/* We use these data channel configs. Ensure scan_masks below follow them too */
+#define BU27008_BLUE2_CLEAR3 0x0 /* buffer is R, G, B, C */
+#define BU27008_CLEAR2_IR3 0x1 /* buffer is R, G, C, IR */
+#define BU27008_BLUE2_IR3 0x2 /* buffer is R, G, B, IR */
+
+static const unsigned long bu27008_scan_masks[] = {
+ /* buffer is R, G, B, C */
+ ALWAYS_SCANNABLE | BIT(BU27008_BLUE) | BIT(BU27008_CLEAR),
+ /* buffer is R, G, C, IR */
+ ALWAYS_SCANNABLE | BIT(BU27008_CLEAR) | BIT(BU27008_IR),
+ /* buffer is R, G, B, IR */
+ ALWAYS_SCANNABLE | BIT(BU27008_BLUE) | BIT(BU27008_IR),
+ 0
+};
+
+/*
+ * Available scales with gain 1x - 1024x, timings 55, 100, 200, 400 mS
+ * Time impacts to gain: 1x, 2x, 4x, 8x.
+ *
+ * => Max total gain is HWGAIN * gain by integration time (8 * 1024) = 8192
+ *
+ * Max amplification is (HWGAIN * MAX integration-time multiplier) 1024 * 8
+ * = 8192. With NANO scale we get rid of accuracy loss when we start with the
+ * scale 16.0 for HWGAIN1, INT-TIME 55 mS. This way the nano scale for MAX
+ * total gain 8192 will be 1953125
+ */
+#define BU27008_SCALE_1X 16
+
+/* See the data sheet for the "Gain Setting" table */
+#define BU27008_GSEL_1X 0x00
+#define BU27008_GSEL_4X 0x08
+#define BU27008_GSEL_8X 0x09
+#define BU27008_GSEL_16X 0x0a
+#define BU27008_GSEL_32X 0x0b
+#define BU27008_GSEL_64X 0x0c
+#define BU27008_GSEL_256X 0x18
+#define BU27008_GSEL_512X 0x19
+#define BU27008_GSEL_1024X 0x1a
+
+static const struct iio_gain_sel_pair bu27008_gains[] = {
+ GAIN_SCALE_GAIN(1, BU27008_GSEL_1X),
+ GAIN_SCALE_GAIN(4, BU27008_GSEL_4X),
+ GAIN_SCALE_GAIN(8, BU27008_GSEL_8X),
+ GAIN_SCALE_GAIN(16, BU27008_GSEL_16X),
+ GAIN_SCALE_GAIN(32, BU27008_GSEL_32X),
+ GAIN_SCALE_GAIN(64, BU27008_GSEL_64X),
+ GAIN_SCALE_GAIN(256, BU27008_GSEL_256X),
+ GAIN_SCALE_GAIN(512, BU27008_GSEL_512X),
+ GAIN_SCALE_GAIN(1024, BU27008_GSEL_1024X),
+};
+
+static const struct iio_gain_sel_pair bu27008_gains_ir[] = {
+ GAIN_SCALE_GAIN(2, BU27008_GSEL_1X),
+ GAIN_SCALE_GAIN(4, BU27008_GSEL_4X),
+ GAIN_SCALE_GAIN(8, BU27008_GSEL_8X),
+ GAIN_SCALE_GAIN(16, BU27008_GSEL_16X),
+ GAIN_SCALE_GAIN(32, BU27008_GSEL_32X),
+ GAIN_SCALE_GAIN(64, BU27008_GSEL_64X),
+ GAIN_SCALE_GAIN(256, BU27008_GSEL_256X),
+ GAIN_SCALE_GAIN(512, BU27008_GSEL_512X),
+ GAIN_SCALE_GAIN(1024, BU27008_GSEL_1024X),
+};
+
+#define BU27008_MEAS_MODE_100MS 0x00
+#define BU27008_MEAS_MODE_55MS 0x01
+#define BU27008_MEAS_MODE_200MS 0x02
+#define BU27008_MEAS_MODE_400MS 0x04
+#define BU27008_MEAS_TIME_MAX_MS 400
+
+static const struct iio_itime_sel_mul bu27008_itimes[] = {
+ GAIN_SCALE_ITIME_US(400000, BU27008_MEAS_MODE_400MS, 8),
+ GAIN_SCALE_ITIME_US(200000, BU27008_MEAS_MODE_200MS, 4),
+ GAIN_SCALE_ITIME_US(100000, BU27008_MEAS_MODE_100MS, 2),
+ GAIN_SCALE_ITIME_US(55000, BU27008_MEAS_MODE_55MS, 1),
+};
+
+/*
+ * All the RGBC channels share the same gain.
+ * IR gain can be fine-tuned from the gain set for the RGBC by 2 bit, but this
+ * would yield quite complex gain setting. Especially since not all bit
+ * compinations are supported. And in any case setting GAIN for RGBC will
+ * always also change the IR-gain.
+ *
+ * On top of this, the selector '0' which corresponds to hw-gain 1X on RGBC,
+ * corresponds to gain 2X on IR. Rest of the selctors correspond to same gains
+ * though. This, however, makes it not possible to use shared gain for all
+ * RGBC and IR settings even though they are all changed at the one go.
+ */
+#define BU27008_CHAN(color, data, separate_avail) \
+{ \
+ .type = IIO_INTENSITY, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_LIGHT_##color, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_separate_available = (separate_avail), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), \
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), \
+ .address = BU27008_REG_##data##_LO, \
+ .scan_index = BU27008_##color, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ }, \
+}
+
+/* For raw reads we always configure DATA3 for CLEAR */
+static const struct iio_chan_spec bu27008_channels[] = {
+ BU27008_CHAN(RED, DATA0, BIT(IIO_CHAN_INFO_SCALE)),
+ BU27008_CHAN(GREEN, DATA1, BIT(IIO_CHAN_INFO_SCALE)),
+ BU27008_CHAN(BLUE, DATA2, BIT(IIO_CHAN_INFO_SCALE)),
+ BU27008_CHAN(CLEAR, DATA2, BIT(IIO_CHAN_INFO_SCALE)),
+ /*
+ * We don't allow setting scale for IR (because of shared gain bits).
+ * Hence we don't advertise available ones either.
+ */
+ BU27008_CHAN(IR, DATA3, 0),
+ IIO_CHAN_SOFT_TIMESTAMP(BU27008_NUM_CHANS),
+};
+
+struct bu27008_data {
+ struct regmap *regmap;
+ struct iio_trigger *trig;
+ struct device *dev;
+ struct iio_gts gts;
+ struct iio_gts gts_ir;
+ int irq;
+
+ /*
+ * Prevent changing gain/time config when scale is read/written.
+ * Similarly, protect the integration_time read/change sequence.
+ * Prevent changing gain/time when data is read.
+ */
+ struct mutex mutex;
+};
+
+static const struct regmap_range bu27008_volatile_ranges[] = {
+ {
+ .range_min = BU27008_REG_SYSTEM_CONTROL, /* SWRESET */
+ .range_max = BU27008_REG_SYSTEM_CONTROL,
+ }, {
+ .range_min = BU27008_REG_MODE_CONTROL3, /* VALID */
+ .range_max = BU27008_REG_MODE_CONTROL3,
+ }, {
+ .range_min = BU27008_REG_DATA0_LO, /* DATA */
+ .range_max = BU27008_REG_DATA3_HI,
+ },
+};
+
+static const struct regmap_access_table bu27008_volatile_regs = {
+ .yes_ranges = &bu27008_volatile_ranges[0],
+ .n_yes_ranges = ARRAY_SIZE(bu27008_volatile_ranges),
+};
+
+static const struct regmap_range bu27008_read_only_ranges[] = {
+ {
+ .range_min = BU27008_REG_DATA0_LO,
+ .range_max = BU27008_REG_DATA3_HI,
+ }, {
+ .range_min = BU27008_REG_MANUFACTURER_ID,
+ .range_max = BU27008_REG_MANUFACTURER_ID,
+ },
+};
+
+static const struct regmap_access_table bu27008_ro_regs = {
+ .no_ranges = &bu27008_read_only_ranges[0],
+ .n_no_ranges = ARRAY_SIZE(bu27008_read_only_ranges),
+};
+
+static const struct regmap_config bu27008_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = BU27008_REG_MAX,
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_table = &bu27008_volatile_regs,
+ .wr_table = &bu27008_ro_regs,
+ /*
+ * All register writes are serialized by the mutex which protects the
+ * scale setting/getting. This is needed because scale is combined by
+ * gain and integration time settings and we need to ensure those are
+ * not read / written when scale is being computed.
+ *
+ * As a result of this serializing, we don't need regmap locking. Note,
+ * this is not true if we add any configurations which are not
+ * serialized by the mutex and which may need for example a protected
+ * read-modify-write cycle (eg. regmap_update_bits()). Please, revise
+ * this when adding features to the driver.
+ */
+ .disable_locking = true,
+};
+
+#define BU27008_MAX_VALID_RESULT_WAIT_US 50000
+#define BU27008_VALID_RESULT_WAIT_QUANTA_US 1000
+
+static int bu27008_chan_read_data(struct bu27008_data *data, int reg, int *val)
+{
+ int ret, valid;
+ __le16 tmp;
+
+ ret = regmap_read_poll_timeout(data->regmap, BU27008_REG_MODE_CONTROL3,
+ valid, (valid & BU27008_MASK_VALID),
+ BU27008_VALID_RESULT_WAIT_QUANTA_US,
+ BU27008_MAX_VALID_RESULT_WAIT_US);
+ if (ret)
+ return ret;
+
+ ret = regmap_bulk_read(data->regmap, reg, &tmp, sizeof(tmp));
+ if (ret)
+ dev_err(data->dev, "Reading channel data failed\n");
+
+ *val = le16_to_cpu(tmp);
+
+ return ret;
+}
+
+static int bu27008_get_gain(struct bu27008_data *data, struct iio_gts *gts, int *gain)
+{
+ int ret, sel;
+
+ ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL2, &sel);
+ if (ret)
+ return ret;
+
+ sel = FIELD_GET(BU27008_MASK_RGBC_GAIN, sel);
+
+ ret = iio_gts_find_gain_by_sel(gts, sel);
+ if (ret < 0) {
+ dev_err(data->dev, "unknown gain value 0x%x\n", sel);
+ return ret;
+ }
+
+ *gain = ret;
+
+ return 0;
+}
+
+static int bu27008_write_gain_sel(struct bu27008_data *data, int sel)
+{
+ int regval;
+
+ regval = FIELD_PREP(BU27008_MASK_RGBC_GAIN, sel);
+
+ /*
+ * We do always set also the LOW bits of IR-gain because othervice we
+ * would risk resulting an invalid GAIN register value.
+ *
+ * We could allow setting separate gains for RGBC and IR when the
+ * values were such that HW could support both gain settings.
+ * Eg, when the shared bits were same for both gain values.
+ *
+ * This, however, has a negligible benefit compared to the increased
+ * software complexity when we would need to go through the gains
+ * for both channels separately when the integration time changes.
+ * This would end up with nasty logic for computing gain values for
+ * both channels - and rejecting them if shared bits changed.
+ *
+ * We should then build the logic by guessing what a user prefers.
+ * RGBC or IR gains correctly set while other jumps to odd value?
+ * Maybe look-up a value where both gains are somehow optimized
+ * <what this somehow is, is ATM unknown to us>. Or maybe user would
+ * expect us to reject changes when optimal gains can't be set to both
+ * channels w/given integration time. At best that would result
+ * solution that works well for a very specific subset of
+ * configurations but causes unexpected corner-cases.
+ *
+ * So, we keep it simple. Always set same selector to IR and RGBC.
+ * We disallow setting IR (as I expect that most of the users are
+ * interested in RGBC). This way we can show the user that the scales
+ * for RGBC and IR channels are different (1X Vs 2X with sel 0) while
+ * still keeping the operation deterministic.
+ */
+ regval |= FIELD_PREP(BU27008_MASK_IR_GAIN_LO, sel);
+
+ return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL2,
+ BU27008_MASK_RGBC_GAIN, regval);
+}
+
+static int bu27008_set_gain(struct bu27008_data *data, int gain)
+{
+ int ret;
+
+ ret = iio_gts_find_sel_by_gain(&data->gts, gain);
+ if (ret < 0)
+ return ret;
+
+ return bu27008_write_gain_sel(data, ret);
+}
+
+static int bu27008_get_int_time_sel(struct bu27008_data *data, int *sel)
+{
+ int ret, val;
+
+ ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL1, &val);
+ *sel = FIELD_GET(BU27008_MASK_MEAS_MODE, val);
+
+ return ret;
+}
+
+static int bu27008_set_int_time_sel(struct bu27008_data *data, int sel)
+{
+ return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL1,
+ BU27008_MASK_MEAS_MODE, sel);
+}
+
+static int bu27008_get_int_time_us(struct bu27008_data *data)
+{
+ int ret, sel;
+
+ ret = bu27008_get_int_time_sel(data, &sel);
+ if (ret)
+ return ret;
+
+ return iio_gts_find_int_time_by_sel(&data->gts, sel);
+}
+
+static int _bu27008_get_scale(struct bu27008_data *data, bool ir, int *val,
+ int *val2)
+{
+ struct iio_gts *gts;
+ int gain, ret;
+
+ if (ir)
+ gts = &data->gts_ir;
+ else
+ gts = &data->gts;
+
+ ret = bu27008_get_gain(data, gts, &gain);
+ if (ret)
+ return ret;
+
+ ret = bu27008_get_int_time_us(data);
+ if (ret < 0)
+ return ret;
+
+ return iio_gts_get_scale(gts, gain, ret, val, val2);
+}
+
+static int bu27008_get_scale(struct bu27008_data *data, bool ir, int *val,
+ int *val2)
+{
+ int ret;
+
+ mutex_lock(&data->mutex);
+ ret = _bu27008_get_scale(data, ir, val, val2);
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
+
+static int bu27008_set_int_time(struct bu27008_data *data, int time)
+{
+ int ret;
+
+ ret = iio_gts_find_sel_by_int_time(&data->gts, time);
+ if (ret < 0)
+ return ret;
+
+ return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL1,
+ BU27008_MASK_MEAS_MODE, ret);
+}
+
+/* Try to change the time so that the scale is maintained */
+static int bu27008_try_set_int_time(struct bu27008_data *data, int int_time_new)
+{
+ int ret, old_time_sel, new_time_sel, old_gain, new_gain;
+
+ mutex_lock(&data->mutex);
+
+ ret = bu27008_get_int_time_sel(data, &old_time_sel);
+ if (ret < 0)
+ goto unlock_out;
+
+ if (!iio_gts_valid_time(&data->gts, int_time_new)) {
+ dev_dbg(data->dev, "Unsupported integration time %u\n",
+ int_time_new);
+
+ ret = -EINVAL;
+ goto unlock_out;
+ }
+
+ /* If we already use requested time, then we're done */
+ new_time_sel = iio_gts_find_sel_by_int_time(&data->gts, int_time_new);
+ if (new_time_sel == old_time_sel)
+ goto unlock_out;
+
+ ret = bu27008_get_gain(data, &data->gts, &old_gain);
+ if (ret)
+ goto unlock_out;
+
+ ret = iio_gts_find_new_gain_sel_by_old_gain_time(&data->gts, old_gain,
+ old_time_sel, new_time_sel, &new_gain);
+ if (ret) {
+ int scale1, scale2;
+ bool ok;
+
+ _bu27008_get_scale(data, false, &scale1, &scale2);
+ dev_dbg(data->dev,
+ "Can't support time %u with current scale %u %u\n",
+ int_time_new, scale1, scale2);
+
+ if (new_gain < 0)
+ goto unlock_out;
+
+ /*
+ * If caller requests for integration time change and we
+ * can't support the scale - then the caller should be
+ * prepared to 'pick up the pieces and deal with the
+ * fact that the scale changed'.
+ */
+ ret = iio_find_closest_gain_low(&data->gts, new_gain, &ok);
+ if (!ok)
+ dev_dbg(data->dev, "optimal gain out of range\n");
+
+ if (ret < 0) {
+ dev_dbg(data->dev,
+ "Total gain increase. Risk of saturation");
+ ret = iio_gts_get_min_gain(&data->gts);
+ if (ret < 0)
+ goto unlock_out;
+ }
+ new_gain = ret;
+ dev_dbg(data->dev, "scale changed, new gain %u\n", new_gain);
+ }
+
+ ret = bu27008_set_gain(data, new_gain);
+ if (ret)
+ goto unlock_out;
+
+ ret = bu27008_set_int_time(data, int_time_new);
+
+unlock_out:
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
+
+static int bu27008_meas_set(struct bu27008_data *data, int state)
+{
+ return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3,
+ BU27008_MASK_MEAS_EN, state);
+}
+
+static int bu27008_chan_cfg(struct bu27008_data *data,
+ struct iio_chan_spec const *chan)
+{
+ int chan_sel;
+
+ if (chan->scan_index == BU27008_BLUE)
+ chan_sel = BU27008_BLUE2_CLEAR3;
+ else
+ chan_sel = BU27008_CLEAR2_IR3;
+
+ chan_sel = FIELD_PREP(BU27008_MASK_CHAN_SEL, chan_sel);
+
+ return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3,
+ BU27008_MASK_CHAN_SEL, chan_sel);
+}
+
+static int bu27008_read_one(struct bu27008_data *data, struct iio_dev *idev,
+ struct iio_chan_spec const *chan, int *val, int *val2)
+{
+ int ret, int_time;
+
+ ret = bu27008_chan_cfg(data, chan);
+ if (ret)
+ return ret;
+
+ ret = bu27008_meas_set(data, BU27008_MEAS_EN);
+ if (ret)
+ return ret;
+
+ ret = bu27008_get_int_time_us(data);
+ if (ret < 0)
+ int_time = BU27008_MEAS_TIME_MAX_MS;
+ else
+ int_time = ret / USEC_PER_MSEC;
+
+ msleep(int_time);
+
+ ret = bu27008_chan_read_data(data, chan->address, val);
+ if (!ret)
+ ret = IIO_VAL_INT;
+
+ if (bu27008_meas_set(data, BU27008_MEAS_DIS))
+ dev_warn(data->dev, "measurement disabling failed\n");
+
+ return ret;
+}
+
+static int bu27008_read_raw(struct iio_dev *idev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct bu27008_data *data = iio_priv(idev);
+ int busy, ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ busy = iio_device_claim_direct_mode(idev);
+ if (busy)
+ return -EBUSY;
+
+ mutex_lock(&data->mutex);
+ ret = bu27008_read_one(data, idev, chan, val, val2);
+ mutex_unlock(&data->mutex);
+
+ iio_device_release_direct_mode(idev);
+
+ return ret;
+
+ case IIO_CHAN_INFO_SCALE:
+ ret = bu27008_get_scale(data, chan->scan_index == BU27008_IR,
+ val, val2);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT_PLUS_NANO;
+
+ case IIO_CHAN_INFO_INT_TIME:
+ ret = bu27008_get_int_time_us(data);
+ if (ret < 0)
+ return ret;
+
+ *val = 0;
+ *val2 = ret;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+/* Called if the new scale could not be supported with existing int-time */
+static int bu27008_try_find_new_time_gain(struct bu27008_data *data, int val,
+ int val2, int *gain_sel)
+{
+ int i, ret, new_time_sel;
+
+ for (i = 0; i < data->gts.num_itime; i++) {
+ new_time_sel = data->gts.itime_table[i].sel;
+ ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts,
+ new_time_sel, val, val2 * 1000, gain_sel);
+ if (!ret)
+ break;
+ }
+ if (i == data->gts.num_itime) {
+ dev_err(data->dev, "Can't support scale %u %u\n", val, val2);
+
+ return -EINVAL;
+ }
+
+ return bu27008_set_int_time_sel(data, new_time_sel);
+}
+
+static int bu27008_set_scale(struct bu27008_data *data,
+ struct iio_chan_spec const *chan,
+ int val, int val2)
+{
+ int ret, gain_sel, time_sel;
+
+ if (chan->scan_index == BU27008_IR)
+ return -EINVAL;
+
+ mutex_lock(&data->mutex);
+
+ ret = bu27008_get_int_time_sel(data, &time_sel);
+ if (ret < 0)
+ goto unlock_out;
+
+ ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel,
+ val, val2 * 1000, &gain_sel);
+ if (ret) {
+ ret = bu27008_try_find_new_time_gain(data, val, val2, &gain_sel);
+ if (ret)
+ goto unlock_out;
+
+ }
+ ret = bu27008_write_gain_sel(data, gain_sel);
+
+unlock_out:
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
+
+static int bu27008_write_raw(struct iio_dev *idev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct bu27008_data *data = iio_priv(idev);
+ int ret;
+
+ /*
+ * Do not allow changing scale when measurement is ongoing as doing so
+ * could make values in the buffer inconsistent.
+ */
+ ret = iio_device_claim_direct_mode(idev);
+ if (ret)
+ return ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ ret = bu27008_set_scale(data, chan, val, val2);
+ break;
+ case IIO_CHAN_INFO_INT_TIME:
+ if (val) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = bu27008_try_set_int_time(data, val2);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ iio_device_release_direct_mode(idev);
+
+ return ret;
+}
+
+static int bu27008_read_avail(struct iio_dev *idev,
+ struct iio_chan_spec const *chan, const int **vals,
+ int *type, int *length, long mask)
+{
+ struct bu27008_data *data = iio_priv(idev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ return iio_gts_avail_times(&data->gts, vals, type, length);
+ case IIO_CHAN_INFO_SCALE:
+ if (chan->channel2 == IIO_MOD_LIGHT_IR)
+ return iio_gts_all_avail_scales(&data->gts_ir, vals,
+ type, length);
+ return iio_gts_all_avail_scales(&data->gts, vals, type, length);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int bu27008_update_scan_mode(struct iio_dev *idev,
+ const unsigned long *scan_mask)
+{
+ struct bu27008_data *data = iio_priv(idev);
+ int chan_sel;
+
+ /* Configure channel selection */
+ if (test_bit(BU27008_BLUE, idev->active_scan_mask)) {
+ if (test_bit(BU27008_CLEAR, idev->active_scan_mask))
+ chan_sel = BU27008_BLUE2_CLEAR3;
+ else
+ chan_sel = BU27008_BLUE2_IR3;
+ } else {
+ chan_sel = BU27008_CLEAR2_IR3;
+ }
+
+ chan_sel = FIELD_PREP(BU27008_MASK_CHAN_SEL, chan_sel);
+
+ return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3,
+ BU27008_MASK_CHAN_SEL, chan_sel);
+}
+
+static const struct iio_info bu27008_info = {
+ .read_raw = &bu27008_read_raw,
+ .write_raw = &bu27008_write_raw,
+ .read_avail = &bu27008_read_avail,
+ .update_scan_mode = bu27008_update_scan_mode,
+ .validate_trigger = iio_validate_own_trigger,
+};
+
+static int bu27008_chip_init(struct bu27008_data *data)
+{
+ int ret;
+
+ ret = regmap_write_bits(data->regmap, BU27008_REG_SYSTEM_CONTROL,
+ BU27008_MASK_SW_RESET, BU27008_MASK_SW_RESET);
+ if (ret)
+ return dev_err_probe(data->dev, ret, "Sensor reset failed\n");
+
+ /*
+ * The data-sheet does not tell how long performing the IC reset takes.
+ * However, the data-sheet says the minimum time it takes the IC to be
+ * able to take inputs after power is applied, is 100 uS. I'd assume
+ * > 1 mS is enough.
+ */
+ msleep(1);
+
+ ret = regmap_reinit_cache(data->regmap, &bu27008_regmap);
+ if (ret)
+ dev_err(data->dev, "Failed to reinit reg cache\n");
+
+ return ret;
+}
+
+static int bu27008_set_drdy_irq(struct bu27008_data *data, int state)
+{
+ return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3,
+ BU27008_MASK_INT_EN, state);
+}
+
+static int bu27008_trigger_set_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct bu27008_data *data = iio_trigger_get_drvdata(trig);
+ int ret;
+
+ if (state)
+ ret = bu27008_set_drdy_irq(data, BU27008_INT_EN);
+ else
+ ret = bu27008_set_drdy_irq(data, BU27008_INT_DIS);
+ if (ret)
+ dev_err(data->dev, "Failed to set trigger state\n");
+
+ return ret;
+}
+
+static void bu27008_trigger_reenable(struct iio_trigger *trig)
+{
+ struct bu27008_data *data = iio_trigger_get_drvdata(trig);
+
+ enable_irq(data->irq);
+}
+
+static const struct iio_trigger_ops bu27008_trigger_ops = {
+ .set_trigger_state = bu27008_trigger_set_state,
+ .reenable = bu27008_trigger_reenable,
+};
+
+static irqreturn_t bu27008_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *idev = pf->indio_dev;
+ struct bu27008_data *data = iio_priv(idev);
+ struct {
+ __le16 chan[BU27008_NUM_HW_CHANS];
+ s64 ts __aligned(8);
+ } raw;
+ int ret, dummy;
+
+ memset(&raw, 0, sizeof(raw));
+
+ /*
+ * After some measurements, it seems reading the
+ * BU27008_REG_MODE_CONTROL3 debounces the IRQ line
+ */
+ ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL3, &dummy);
+ if (ret < 0)
+ goto err_read;
+
+ ret = regmap_bulk_read(data->regmap, BU27008_REG_DATA0_LO, &raw.chan,
+ sizeof(raw.chan));
+ if (ret < 0)
+ goto err_read;
+
+ iio_push_to_buffers_with_timestamp(idev, &raw, pf->timestamp);
+err_read:
+ iio_trigger_notify_done(idev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int bu27008_buffer_preenable(struct iio_dev *idev)
+{
+ struct bu27008_data *data = iio_priv(idev);
+
+ return bu27008_meas_set(data, BU27008_MEAS_EN);
+}
+
+static int bu27008_buffer_postdisable(struct iio_dev *idev)
+{
+ struct bu27008_data *data = iio_priv(idev);
+
+ return bu27008_meas_set(data, BU27008_MEAS_DIS);
+}
+
+static const struct iio_buffer_setup_ops bu27008_buffer_ops = {
+ .preenable = bu27008_buffer_preenable,
+ .postdisable = bu27008_buffer_postdisable,
+};
+
+static irqreturn_t bu27008_data_rdy_poll(int irq, void *private)
+{
+ /*
+ * The BU27008 keeps IRQ asserted until we read the VALID bit from
+ * a register. We need to keep the IRQ disabled until then.
+ */
+ disable_irq_nosync(irq);
+ iio_trigger_poll(private);
+
+ return IRQ_HANDLED;
+}
+
+static int bu27008_setup_trigger(struct bu27008_data *data, struct iio_dev *idev)
+{
+ struct iio_trigger *itrig;
+ char *name;
+ int ret;
+
+ ret = devm_iio_triggered_buffer_setup(data->dev, idev,
+ &iio_pollfunc_store_time,
+ bu27008_trigger_handler,
+ &bu27008_buffer_ops);
+ if (ret)
+ return dev_err_probe(data->dev, ret,
+ "iio_triggered_buffer_setup_ext FAIL\n");
+
+ itrig = devm_iio_trigger_alloc(data->dev, "%sdata-rdy-dev%d",
+ idev->name, iio_device_id(idev));
+ if (!itrig)
+ return -ENOMEM;
+
+ data->trig = itrig;
+
+ itrig->ops = &bu27008_trigger_ops;
+ iio_trigger_set_drvdata(itrig, data);
+
+ name = devm_kasprintf(data->dev, GFP_KERNEL, "%s-bu27008",
+ dev_name(data->dev));
+
+ ret = devm_request_irq(data->dev, data->irq,
+ &bu27008_data_rdy_poll,
+ 0, name, itrig);
+ if (ret)
+ return dev_err_probe(data->dev, ret, "Could not request IRQ\n");
+
+ ret = devm_iio_trigger_register(data->dev, itrig);
+ if (ret)
+ return dev_err_probe(data->dev, ret,
+ "Trigger registration failed\n");
+
+ /* set default trigger */
+ idev->trig = iio_trigger_get(itrig);
+
+ return 0;
+}
+
+static int bu27008_probe(struct i2c_client *i2c)
+{
+ struct device *dev = &i2c->dev;
+ struct bu27008_data *data;
+ struct regmap *regmap;
+ unsigned int part_id, reg;
+ struct iio_dev *idev;
+ int ret;
+
+ regmap = devm_regmap_init_i2c(i2c, &bu27008_regmap);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to initialize Regmap\n");
+
+ idev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!idev)
+ return -ENOMEM;
+
+ ret = devm_regulator_get_enable(dev, "vdd");
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get regulator\n");
+
+ data = iio_priv(idev);
+
+ ret = regmap_read(regmap, BU27008_REG_SYSTEM_CONTROL, &reg);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to access sensor\n");
+
+ part_id = FIELD_GET(BU27008_MASK_PART_ID, reg);
+
+ if (part_id != BU27008_ID)
+ dev_warn(dev, "unknown device 0x%x\n", part_id);
+
+ ret = devm_iio_init_iio_gts(dev, BU27008_SCALE_1X, 0, bu27008_gains,
+ ARRAY_SIZE(bu27008_gains), bu27008_itimes,
+ ARRAY_SIZE(bu27008_itimes), &data->gts);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_init_iio_gts(dev, BU27008_SCALE_1X, 0, bu27008_gains_ir,
+ ARRAY_SIZE(bu27008_gains_ir), bu27008_itimes,
+ ARRAY_SIZE(bu27008_itimes), &data->gts_ir);
+ if (ret)
+ return ret;
+
+ mutex_init(&data->mutex);
+ data->regmap = regmap;
+ data->dev = dev;
+ data->irq = i2c->irq;
+
+ idev->channels = bu27008_channels;
+ idev->num_channels = ARRAY_SIZE(bu27008_channels);
+ idev->name = "bu27008";
+ idev->info = &bu27008_info;
+ idev->modes = INDIO_DIRECT_MODE;
+ idev->available_scan_masks = bu27008_scan_masks;
+
+ ret = bu27008_chip_init(data);
+ if (ret)
+ return ret;
+
+ if (i2c->irq) {
+ ret = bu27008_setup_trigger(data, idev);
+ if (ret)
+ return ret;
+ } else {
+ dev_info(dev, "No IRQ, buffered mode disabled\n");
+ }
+
+ ret = devm_iio_device_register(dev, idev);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Unable to register iio device\n");
+
+ return 0;
+}
+
+static const struct of_device_id bu27008_of_match[] = {
+ { .compatible = "rohm,bu27008" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, bu27008_of_match);
+
+static struct i2c_driver bu27008_i2c_driver = {
+ .driver = {
+ .name = "bu27008",
+ .of_match_table = bu27008_of_match,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+ .probe = bu27008_probe,
+};
+module_i2c_driver(bu27008_i2c_driver);
+
+MODULE_DESCRIPTION("ROHM BU27008 colour sensor driver");
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(IIO_GTS_HELPER);
diff --git a/drivers/iio/light/rohm-bu27034.c b/drivers/iio/light/rohm-bu27034.c
index f85194fda6b0..e63ef5789cde 100644
--- a/drivers/iio/light/rohm-bu27034.c
+++ b/drivers/iio/light/rohm-bu27034.c
@@ -1500,8 +1500,9 @@ static struct i2c_driver bu27034_i2c_driver = {
.driver = {
.name = "bu27034-als",
.of_match_table = bu27034_of_match,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = bu27034_probe,
+ .probe = bu27034_probe,
};
module_i2c_driver(bu27034_i2c_driver);
diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c
index 9d0218b7426e..bbb8581622f2 100644
--- a/drivers/iio/light/rpr0521.c
+++ b/drivers/iio/light/rpr0521.c
@@ -1121,7 +1121,7 @@ static struct i2c_driver rpr0521_driver = {
.pm = pm_ptr(&rpr0521_pm_ops),
.acpi_match_table = ACPI_PTR(rpr0521_acpi_match),
},
- .probe_new = rpr0521_probe,
+ .probe = rpr0521_probe,
.remove = rpr0521_remove,
.id_table = rpr0521_id,
};
diff --git a/drivers/iio/light/si1133.c b/drivers/iio/light/si1133.c
index a08fbc8f5adb..ea2c437199c0 100644
--- a/drivers/iio/light/si1133.c
+++ b/drivers/iio/light/si1133.c
@@ -1064,7 +1064,7 @@ static struct i2c_driver si1133_driver = {
.driver = {
.name = "si1133",
},
- .probe_new = si1133_probe,
+ .probe = si1133_probe,
.id_table = si1133_ids,
};
diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c
index f7126235f94c..77666b780a5c 100644
--- a/drivers/iio/light/si1145.c
+++ b/drivers/iio/light/si1145.c
@@ -1352,7 +1352,7 @@ static struct i2c_driver si1145_driver = {
.driver = {
.name = "si1145",
},
- .probe_new = si1145_probe,
+ .probe = si1145_probe,
.id_table = si1145_ids,
};
diff --git a/drivers/iio/light/st_uvis25_i2c.c b/drivers/iio/light/st_uvis25_i2c.c
index 2160e87bb498..6bc2ddfb77ca 100644
--- a/drivers/iio/light/st_uvis25_i2c.c
+++ b/drivers/iio/light/st_uvis25_i2c.c
@@ -57,7 +57,7 @@ static struct i2c_driver st_uvis25_driver = {
.pm = pm_sleep_ptr(&st_uvis25_pm_ops),
.of_match_table = st_uvis25_i2c_of_match,
},
- .probe_new = st_uvis25_i2c_probe,
+ .probe = st_uvis25_i2c_probe,
.id_table = st_uvis25_i2c_id_table,
};
module_i2c_driver(st_uvis25_driver);
diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c
index 48ae6ff0015e..72b08d870d33 100644
--- a/drivers/iio/light/stk3310.c
+++ b/drivers/iio/light/stk3310.c
@@ -714,7 +714,7 @@ static struct i2c_driver stk3310_driver = {
.pm = pm_sleep_ptr(&stk3310_pm_ops),
.acpi_match_table = ACPI_PTR(stk3310_acpi_id),
},
- .probe_new = stk3310_probe,
+ .probe = stk3310_probe,
.remove = stk3310_remove,
.id_table = stk3310_i2c_id,
};
diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c
index 5100732fbaf0..dcdd85b006be 100644
--- a/drivers/iio/light/tcs3414.c
+++ b/drivers/iio/light/tcs3414.c
@@ -373,7 +373,7 @@ static struct i2c_driver tcs3414_driver = {
.name = TCS3414_DRV_NAME,
.pm = pm_sleep_ptr(&tcs3414_pm_ops),
},
- .probe_new = tcs3414_probe,
+ .probe = tcs3414_probe,
.id_table = tcs3414_id,
};
module_i2c_driver(tcs3414_driver);
diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c
index 6187c5487916..75fcf2c93717 100644
--- a/drivers/iio/light/tcs3472.c
+++ b/drivers/iio/light/tcs3472.c
@@ -609,7 +609,7 @@ static struct i2c_driver tcs3472_driver = {
.name = TCS3472_DRV_NAME,
.pm = pm_sleep_ptr(&tcs3472_pm_ops),
},
- .probe_new = tcs3472_probe,
+ .probe = tcs3472_probe,
.remove = tcs3472_remove,
.id_table = tcs3472_id,
};
diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c
index f2f55239a072..1a6f514bced6 100644
--- a/drivers/iio/light/tsl2563.c
+++ b/drivers/iio/light/tsl2563.c
@@ -862,7 +862,7 @@ static struct i2c_driver tsl2563_i2c_driver = {
.of_match_table = tsl2563_of_match,
.pm = pm_sleep_ptr(&tsl2563_pm_ops),
},
- .probe_new = tsl2563_probe,
+ .probe = tsl2563_probe,
.remove = tsl2563_remove,
.id_table = tsl2563_id,
};
diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c
index a05f1c0453d1..02ad11611b9c 100644
--- a/drivers/iio/light/tsl2583.c
+++ b/drivers/iio/light/tsl2583.c
@@ -942,7 +942,7 @@ static struct i2c_driver tsl2583_driver = {
.of_match_table = tsl2583_of_match,
},
.id_table = tsl2583_idtable,
- .probe_new = tsl2583_probe,
+ .probe = tsl2583_probe,
.remove = tsl2583_remove,
};
module_i2c_driver(tsl2583_driver);
diff --git a/drivers/iio/light/tsl2591.c b/drivers/iio/light/tsl2591.c
index e485a556e6da..7bdbfe72f0f0 100644
--- a/drivers/iio/light/tsl2591.c
+++ b/drivers/iio/light/tsl2591.c
@@ -1214,7 +1214,7 @@ static struct i2c_driver tsl2591_driver = {
.pm = pm_ptr(&tsl2591_pm_ops),
.of_match_table = tsl2591_of_match,
},
- .probe_new = tsl2591_probe
+ .probe = tsl2591_probe
};
module_i2c_driver(tsl2591_driver);
diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c
index e823c145f679..cab468a82b61 100644
--- a/drivers/iio/light/tsl2772.c
+++ b/drivers/iio/light/tsl2772.c
@@ -1932,7 +1932,7 @@ static struct i2c_driver tsl2772_driver = {
.pm = &tsl2772_pm_ops,
},
.id_table = tsl2772_idtable,
- .probe_new = tsl2772_probe,
+ .probe = tsl2772_probe,
};
module_i2c_driver(tsl2772_driver);
diff --git a/drivers/iio/light/tsl4531.c b/drivers/iio/light/tsl4531.c
index d95397eb1526..4da7d78906d4 100644
--- a/drivers/iio/light/tsl4531.c
+++ b/drivers/iio/light/tsl4531.c
@@ -237,7 +237,7 @@ static struct i2c_driver tsl4531_driver = {
.name = TSL4531_DRV_NAME,
.pm = pm_sleep_ptr(&tsl4531_pm_ops),
},
- .probe_new = tsl4531_probe,
+ .probe = tsl4531_probe,
.remove = tsl4531_remove,
.id_table = tsl4531_id,
};
diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c
index 8b2a0c99c8e6..61b3b2aea626 100644
--- a/drivers/iio/light/us5182d.c
+++ b/drivers/iio/light/us5182d.c
@@ -974,7 +974,7 @@ static struct i2c_driver us5182d_driver = {
.of_match_table = us5182d_of_match,
.acpi_match_table = ACPI_PTR(us5182d_acpi_match),
},
- .probe_new = us5182d_probe,
+ .probe = us5182d_probe,
.remove = us5182d_remove,
.id_table = us5182d_id,
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 56d3963d3d66..7c7362e28821 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -1500,7 +1500,7 @@ static struct i2c_driver vcnl4000_driver = {
.pm = pm_ptr(&vcnl4000_pm_ops),
.of_match_table = vcnl_4000_of_match,
},
- .probe_new = vcnl4000_probe,
+ .probe = vcnl4000_probe,
.id_table = vcnl4000_id,
.remove = vcnl4000_remove,
};
diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c
index 94f5d611e98c..56bbefbc0ae6 100644
--- a/drivers/iio/light/vcnl4035.c
+++ b/drivers/iio/light/vcnl4035.c
@@ -670,7 +670,7 @@ static struct i2c_driver vcnl4035_driver = {
.pm = pm_ptr(&vcnl4035_pm_ops),
.of_match_table = vcnl4035_of_match,
},
- .probe_new = vcnl4035_probe,
+ .probe = vcnl4035_probe,
.remove = vcnl4035_remove,
.id_table = vcnl4035_id,
};
diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c
index e7d2d5d177d4..043f233d9bdb 100644
--- a/drivers/iio/light/veml6030.c
+++ b/drivers/iio/light/veml6030.c
@@ -892,7 +892,7 @@ static struct i2c_driver veml6030_driver = {
.of_match_table = veml6030_of_match,
.pm = pm_ptr(&veml6030_pm_ops),
},
- .probe_new = veml6030_probe,
+ .probe = veml6030_probe,
.id_table = veml6030_id,
};
module_i2c_driver(veml6030_driver);
diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c
index ee76a68deb24..d99bf3ae0fe8 100644
--- a/drivers/iio/light/veml6070.c
+++ b/drivers/iio/light/veml6070.c
@@ -198,7 +198,7 @@ static struct i2c_driver veml6070_driver = {
.driver = {
.name = VEML6070_DRV_NAME,
},
- .probe_new = veml6070_probe,
+ .probe = veml6070_probe,
.remove = veml6070_remove,
.id_table = veml6070_id,
};
diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c
index 8b56df26c59e..d4948dfc31ff 100644
--- a/drivers/iio/light/vl6180.c
+++ b/drivers/iio/light/vl6180.c
@@ -538,7 +538,7 @@ static struct i2c_driver vl6180_driver = {
.name = VL6180_DRV_NAME,
.of_match_table = vl6180_of_match,
},
- .probe_new = vl6180_probe,
+ .probe = vl6180_probe,
.id_table = vl6180_id,
};
diff --git a/drivers/iio/light/zopt2201.c b/drivers/iio/light/zopt2201.c
index e3bac8b56380..d370193a4742 100644
--- a/drivers/iio/light/zopt2201.c
+++ b/drivers/iio/light/zopt2201.c
@@ -554,7 +554,7 @@ static struct i2c_driver zopt2201_driver = {
.driver = {
.name = ZOPT2201_DRV_NAME,
},
- .probe_new = zopt2201_probe,
+ .probe = zopt2201_probe,
.id_table = zopt2201_id,
};
diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c
index 45abdcce6bc0..c74d11943ec7 100644
--- a/drivers/iio/magnetometer/ak8974.c
+++ b/drivers/iio/magnetometer/ak8974.c
@@ -1046,7 +1046,7 @@ static struct i2c_driver ak8974_driver = {
.pm = pm_ptr(&ak8974_dev_pm_ops),
.of_match_table = ak8974_of_match,
},
- .probe_new = ak8974_probe,
+ .probe = ak8974_probe,
.remove = ak8974_remove,
.id_table = ak8974_id,
};
diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
index 924b481a3034..eb706d0bf70b 100644
--- a/drivers/iio/magnetometer/ak8975.c
+++ b/drivers/iio/magnetometer/ak8975.c
@@ -1110,7 +1110,7 @@ static struct i2c_driver ak8975_driver = {
.of_match_table = ak8975_of_match,
.acpi_match_table = ak_acpi_match,
},
- .probe_new = ak8975_probe,
+ .probe = ak8975_probe,
.remove = ak8975_remove,
.id_table = ak8975_id,
};
diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c
index 44b8960eea17..281d1fa31c8e 100644
--- a/drivers/iio/magnetometer/bmc150_magn_i2c.c
+++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c
@@ -71,7 +71,7 @@ static struct i2c_driver bmc150_magn_driver = {
.acpi_match_table = ACPI_PTR(bmc150_magn_acpi_match),
.pm = &bmc150_magn_pm_ops,
},
- .probe_new = bmc150_magn_i2c_probe,
+ .probe = bmc150_magn_i2c_probe,
.remove = bmc150_magn_i2c_remove,
.id_table = bmc150_magn_i2c_id,
};
diff --git a/drivers/iio/magnetometer/hmc5843_i2c.c b/drivers/iio/magnetometer/hmc5843_i2c.c
index 7ef2b1d56289..bdd2784a9f86 100644
--- a/drivers/iio/magnetometer/hmc5843_i2c.c
+++ b/drivers/iio/magnetometer/hmc5843_i2c.c
@@ -95,7 +95,7 @@ static struct i2c_driver hmc5843_driver = {
.of_match_table = hmc5843_of_match,
},
.id_table = hmc5843_id,
- .probe_new = hmc5843_i2c_probe,
+ .probe = hmc5843_i2c_probe,
.remove = hmc5843_i2c_remove,
};
module_i2c_driver(hmc5843_driver);
diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c
index 661176a885ad..deffe3ca9004 100644
--- a/drivers/iio/magnetometer/mag3110.c
+++ b/drivers/iio/magnetometer/mag3110.c
@@ -641,7 +641,7 @@ static struct i2c_driver mag3110_driver = {
.of_match_table = mag3110_of_match,
.pm = pm_sleep_ptr(&mag3110_pm_ops),
},
- .probe_new = mag3110_probe,
+ .probe = mag3110_probe,
.remove = mag3110_remove,
.id_table = mag3110_id,
};
diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
index 756dadbad106..b495b8a63928 100644
--- a/drivers/iio/magnetometer/mmc35240.c
+++ b/drivers/iio/magnetometer/mmc35240.c
@@ -575,7 +575,7 @@ static struct i2c_driver mmc35240_driver = {
.pm = pm_sleep_ptr(&mmc35240_pm_ops),
.acpi_match_table = ACPI_PTR(mmc35240_acpi_match),
},
- .probe_new = mmc35240_probe,
+ .probe = mmc35240_probe,
.id_table = mmc35240_id,
};
diff --git a/drivers/iio/magnetometer/rm3100-i2c.c b/drivers/iio/magnetometer/rm3100-i2c.c
index ba669ab7113d..ac7276b3798c 100644
--- a/drivers/iio/magnetometer/rm3100-i2c.c
+++ b/drivers/iio/magnetometer/rm3100-i2c.c
@@ -45,7 +45,7 @@ static struct i2c_driver rm3100_driver = {
.name = "rm3100-i2c",
.of_match_table = rm3100_dt_match,
},
- .probe_new = rm3100_probe,
+ .probe = rm3100_probe,
};
module_i2c_driver(rm3100_driver);
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index 8faa7409d9e1..6cc0dfd31821 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -427,6 +427,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LSM9DS0_IMU_DEV_NAME,
+ [1] = LSM303D_IMU_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_magn_4_16bit_channels,
.odr = {
diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c
index cc0e0e94b129..950826dd20bf 100644
--- a/drivers/iio/magnetometer/st_magn_i2c.c
+++ b/drivers/iio/magnetometer/st_magn_i2c.c
@@ -111,7 +111,7 @@ static struct i2c_driver st_magn_driver = {
.name = "st-magn-i2c",
.of_match_table = st_magn_of_match,
},
- .probe_new = st_magn_i2c_probe,
+ .probe = st_magn_i2c_probe,
.id_table = st_magn_id_table,
};
module_i2c_driver(st_magn_driver);
diff --git a/drivers/iio/magnetometer/tmag5273.c b/drivers/iio/magnetometer/tmag5273.c
index e155a75b3cd2..c5e5c4ad681e 100644
--- a/drivers/iio/magnetometer/tmag5273.c
+++ b/drivers/iio/magnetometer/tmag5273.c
@@ -734,7 +734,7 @@ static struct i2c_driver tmag5273_driver = {
.of_match_table = tmag5273_of_match,
.pm = pm_ptr(&tmag5273_pm_ops),
},
- .probe_new = tmag5273_probe,
+ .probe = tmag5273_probe,
.id_table = tmag5273_id,
};
module_i2c_driver(tmag5273_driver);
diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c
index 753717158b07..c5e485bfc6fc 100644
--- a/drivers/iio/magnetometer/yamaha-yas530.c
+++ b/drivers/iio/magnetometer/yamaha-yas530.c
@@ -1605,7 +1605,7 @@ static struct i2c_driver yas5xx_driver = {
.of_match_table = yas5xx_of_match,
.pm = pm_ptr(&yas5xx_dev_pm_ops),
},
- .probe_new = yas5xx_probe,
+ .probe = yas5xx_probe,
.remove = yas5xx_remove,
.id_table = yas5xx_id,
};
diff --git a/drivers/iio/potentiometer/Kconfig b/drivers/iio/potentiometer/Kconfig
index 01dd3f858d99..e6a9a3c67845 100644
--- a/drivers/iio/potentiometer/Kconfig
+++ b/drivers/iio/potentiometer/Kconfig
@@ -136,4 +136,14 @@ config TPL0102
To compile this driver as a module, choose M here: the
module will be called tpl0102.
+config X9250
+ tristate "Renesas X9250 quad controlled potentiometers"
+ depends on SPI
+ help
+ Enable support for the Renesas X9250 quad controlled
+ potentiometers.
+
+ To compile this driver as a module, choose M here: the module
+ will be called x9250.
+
endmenu
diff --git a/drivers/iio/potentiometer/Makefile b/drivers/iio/potentiometer/Makefile
index 5ebb8e3bbd76..d11fb739176c 100644
--- a/drivers/iio/potentiometer/Makefile
+++ b/drivers/iio/potentiometer/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_MCP4131) += mcp4131.o
obj-$(CONFIG_MCP4531) += mcp4531.o
obj-$(CONFIG_MCP41010) += mcp41010.o
obj-$(CONFIG_TPL0102) += tpl0102.o
+obj-$(CONFIG_X9250) += x9250.o
diff --git a/drivers/iio/potentiometer/ad5110.c b/drivers/iio/potentiometer/ad5110.c
index 8fbcce482989..991e745c4f93 100644
--- a/drivers/iio/potentiometer/ad5110.c
+++ b/drivers/iio/potentiometer/ad5110.c
@@ -334,7 +334,7 @@ static struct i2c_driver ad5110_driver = {
.name = "ad5110",
.of_match_table = ad5110_of_match,
},
- .probe_new = ad5110_probe,
+ .probe = ad5110_probe,
.id_table = ad5110_id,
};
module_i2c_driver(ad5110_driver);
diff --git a/drivers/iio/potentiometer/ad5272.c b/drivers/iio/potentiometer/ad5272.c
index aa140d632101..b17941e4c2f7 100644
--- a/drivers/iio/potentiometer/ad5272.c
+++ b/drivers/iio/potentiometer/ad5272.c
@@ -218,7 +218,7 @@ static struct i2c_driver ad5272_driver = {
.name = "ad5272",
.of_match_table = ad5272_dt_ids,
},
- .probe_new = ad5272_probe,
+ .probe = ad5272_probe,
.id_table = ad5272_id,
};
diff --git a/drivers/iio/potentiometer/ds1803.c b/drivers/iio/potentiometer/ds1803.c
index 0b5e475807cb..fc183e0790da 100644
--- a/drivers/iio/potentiometer/ds1803.c
+++ b/drivers/iio/potentiometer/ds1803.c
@@ -252,7 +252,7 @@ static struct i2c_driver ds1803_driver = {
.name = "ds1803",
.of_match_table = ds1803_dt_ids,
},
- .probe_new = ds1803_probe,
+ .probe = ds1803_probe,
.id_table = ds1803_id,
};
diff --git a/drivers/iio/potentiometer/max5432.c b/drivers/iio/potentiometer/max5432.c
index 94ef27ef3fb5..c8e2481dadb5 100644
--- a/drivers/iio/potentiometer/max5432.c
+++ b/drivers/iio/potentiometer/max5432.c
@@ -123,7 +123,7 @@ static struct i2c_driver max5432_driver = {
.name = "max5432",
.of_match_table = max5432_dt_ids,
},
- .probe_new = max5432_probe,
+ .probe = max5432_probe,
};
module_i2c_driver(max5432_driver);
diff --git a/drivers/iio/potentiometer/mcp4018.c b/drivers/iio/potentiometer/mcp4018.c
index c0e171fec062..89daecc90305 100644
--- a/drivers/iio/potentiometer/mcp4018.c
+++ b/drivers/iio/potentiometer/mcp4018.c
@@ -174,7 +174,7 @@ static struct i2c_driver mcp4018_driver = {
.name = "mcp4018",
.of_match_table = mcp4018_of_match,
},
- .probe_new = mcp4018_probe,
+ .probe = mcp4018_probe,
.id_table = mcp4018_id,
};
diff --git a/drivers/iio/potentiometer/mcp4531.c b/drivers/iio/potentiometer/mcp4531.c
index c25f84b4a270..c513c00c8243 100644
--- a/drivers/iio/potentiometer/mcp4531.c
+++ b/drivers/iio/potentiometer/mcp4531.c
@@ -385,7 +385,7 @@ static struct i2c_driver mcp4531_driver = {
.name = "mcp4531",
.of_match_table = mcp4531_of_match,
},
- .probe_new = mcp4531_probe,
+ .probe = mcp4531_probe,
.id_table = mcp4531_id,
};
diff --git a/drivers/iio/potentiometer/tpl0102.c b/drivers/iio/potentiometer/tpl0102.c
index a3465b413b0c..8923ccb0fc4f 100644
--- a/drivers/iio/potentiometer/tpl0102.c
+++ b/drivers/iio/potentiometer/tpl0102.c
@@ -161,7 +161,7 @@ static struct i2c_driver tpl0102_driver = {
.driver = {
.name = "tpl0102",
},
- .probe_new = tpl0102_probe,
+ .probe = tpl0102_probe,
.id_table = tpl0102_id,
};
diff --git a/drivers/iio/potentiometer/x9250.c b/drivers/iio/potentiometer/x9250.c
new file mode 100644
index 000000000000..735348492699
--- /dev/null
+++ b/drivers/iio/potentiometer/x9250.c
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * x9250.c -- Renesas X9250 potentiometers IIO driver
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina <herve.codina@bootlin.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/iio.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+struct x9250_cfg {
+ const char *name;
+ int kohms;
+};
+
+struct x9250 {
+ struct spi_device *spi;
+ const struct x9250_cfg *cfg;
+ struct gpio_desc *wp_gpio;
+};
+
+#define X9250_ID 0x50
+#define X9250_CMD_RD_WCR(_p) (0x90 | (_p))
+#define X9250_CMD_WR_WCR(_p) (0xa0 | (_p))
+
+static int x9250_write8(struct x9250 *x9250, u8 cmd, u8 val)
+{
+ u8 txbuf[3];
+
+ txbuf[0] = X9250_ID;
+ txbuf[1] = cmd;
+ txbuf[2] = val;
+
+ return spi_write_then_read(x9250->spi, txbuf, ARRAY_SIZE(txbuf), NULL, 0);
+}
+
+static int x9250_read8(struct x9250 *x9250, u8 cmd, u8 *val)
+{
+ u8 txbuf[2];
+
+ txbuf[0] = X9250_ID;
+ txbuf[1] = cmd;
+
+ return spi_write_then_read(x9250->spi, txbuf, ARRAY_SIZE(txbuf), val, 1);
+}
+
+#define X9250_CHANNEL(ch) { \
+ .type = IIO_RESISTANCE, \
+ .indexed = 1, \
+ .output = 1, \
+ .channel = (ch), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_RAW), \
+}
+
+static const struct iio_chan_spec x9250_channels[] = {
+ X9250_CHANNEL(0),
+ X9250_CHANNEL(1),
+ X9250_CHANNEL(2),
+ X9250_CHANNEL(3),
+};
+
+static int x9250_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct x9250 *x9250 = iio_priv(indio_dev);
+ int ch = chan->channel;
+ int ret;
+ u8 v;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = x9250_read8(x9250, X9250_CMD_RD_WCR(ch), &v);
+ if (ret)
+ return ret;
+ *val = v;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ *val = 1000 * x9250->cfg->kohms;
+ *val2 = U8_MAX;
+ return IIO_VAL_FRACTIONAL;
+ }
+
+ return -EINVAL;
+}
+
+static int x9250_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length, long mask)
+{
+ static const int range[] = {0, 1, 255}; /* min, step, max */
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ *length = ARRAY_SIZE(range);
+ *vals = range;
+ *type = IIO_VAL_INT;
+ return IIO_AVAIL_RANGE;
+ }
+
+ return -EINVAL;
+}
+
+static int x9250_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct x9250 *x9250 = iio_priv(indio_dev);
+ int ch = chan->channel;
+ int ret;
+
+ if (mask != IIO_CHAN_INFO_RAW)
+ return -EINVAL;
+
+ if (val > U8_MAX || val < 0)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(x9250->wp_gpio, 0);
+ ret = x9250_write8(x9250, X9250_CMD_WR_WCR(ch), val);
+ gpiod_set_value_cansleep(x9250->wp_gpio, 1);
+
+ return ret;
+}
+
+static const struct iio_info x9250_info = {
+ .read_raw = x9250_read_raw,
+ .read_avail = x9250_read_avail,
+ .write_raw = x9250_write_raw,
+};
+
+enum x9250_type {
+ X9250T,
+ X9250U,
+};
+
+static const struct x9250_cfg x9250_cfg[] = {
+ [X9250T] = { .name = "x9250t", .kohms = 100, },
+ [X9250U] = { .name = "x9250u", .kohms = 50, },
+};
+
+static const char *const x9250_regulator_names[] = {
+ "vcc",
+ "avp",
+ "avn",
+};
+
+static int x9250_probe(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev;
+ struct x9250 *x9250;
+ int ret;
+
+ ret = devm_regulator_bulk_get_enable(&spi->dev, ARRAY_SIZE(x9250_regulator_names),
+ x9250_regulator_names);
+ if (ret)
+ return dev_err_probe(&spi->dev, ret, "Failed to get regulators\n");
+
+ /*
+ * The x9250 needs a 5ms maximum delay after the power-supplies are set
+ * before performing the first write (1ms for the first read).
+ */
+ usleep_range(5000, 6000);
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*x9250));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ x9250 = iio_priv(indio_dev);
+ x9250->spi = spi;
+ x9250->cfg = spi_get_device_match_data(spi);
+ x9250->wp_gpio = devm_gpiod_get_optional(&spi->dev, "wp", GPIOD_OUT_LOW);
+ if (IS_ERR(x9250->wp_gpio))
+ return dev_err_probe(&spi->dev, PTR_ERR(x9250->wp_gpio),
+ "failed to get wp gpio\n");
+
+ indio_dev->info = &x9250_info;
+ indio_dev->channels = x9250_channels;
+ indio_dev->num_channels = ARRAY_SIZE(x9250_channels);
+ indio_dev->name = x9250->cfg->name;
+
+ return devm_iio_device_register(&spi->dev, indio_dev);
+}
+
+static const struct of_device_id x9250_of_match[] = {
+ { .compatible = "renesas,x9250t", .data = &x9250_cfg[X9250T]},
+ { .compatible = "renesas,x9250u", .data = &x9250_cfg[X9250U]},
+ { }
+};
+MODULE_DEVICE_TABLE(of, x9250_of_match);
+
+static const struct spi_device_id x9250_id_table[] = {
+ { "x9250t", (kernel_ulong_t)&x9250_cfg[X9250T] },
+ { "x9250u", (kernel_ulong_t)&x9250_cfg[X9250U] },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, x9250_id_table);
+
+static struct spi_driver x9250_spi_driver = {
+ .driver = {
+ .name = "x9250",
+ .of_match_table = x9250_of_match,
+ },
+ .id_table = x9250_id_table,
+ .probe = x9250_probe,
+};
+
+module_spi_driver(x9250_spi_driver);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("X9250 ALSA SoC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c
index 0083e858c21e..bd0f2c3bf2f2 100644
--- a/drivers/iio/potentiostat/lmp91000.c
+++ b/drivers/iio/potentiostat/lmp91000.c
@@ -416,7 +416,7 @@ static struct i2c_driver lmp91000_driver = {
.name = LMP91000_DRV_NAME,
.of_match_table = lmp91000_of_match,
},
- .probe_new = lmp91000_probe,
+ .probe = lmp91000_probe,
.remove = lmp91000_remove,
.id_table = lmp91000_id,
};
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index 02b97e89de50..7b4c2af32852 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -148,6 +148,19 @@ config MPL3115
To compile this driver as a module, choose M here: the module
will be called mpl3115.
+config MPRLS0025PA
+ tristate "Honeywell MPRLS0025PA (MicroPressure sensors series)"
+ depends on I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say Y here to build support for the Honeywell MicroPressure pressure
+ sensor series. There are many different types with different pressure
+ range. These ranges can be set up in the device tree.
+
+ To compile this driver as a module, choose M here: the module will be
+ called mprls0025pa.
+
config MS5611
tristate "Measurement Specialties MS5611 pressure sensor driver"
select IIO_BUFFER
diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile
index 083ae87ff48f..c90f77210e94 100644
--- a/drivers/iio/pressure/Makefile
+++ b/drivers/iio/pressure/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_MPL115) += mpl115.o
obj-$(CONFIG_MPL115_I2C) += mpl115_i2c.o
obj-$(CONFIG_MPL115_SPI) += mpl115_spi.o
obj-$(CONFIG_MPL3115) += mpl3115.o
+obj-$(CONFIG_MPRLS0025PA) += mprls0025pa.o
obj-$(CONFIG_MS5611) += ms5611_core.o
obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o
obj-$(CONFIG_MS5611_SPI) += ms5611_spi.o
diff --git a/drivers/iio/pressure/abp060mg.c b/drivers/iio/pressure/abp060mg.c
index c0140779366a..752a63c06b44 100644
--- a/drivers/iio/pressure/abp060mg.c
+++ b/drivers/iio/pressure/abp060mg.c
@@ -255,7 +255,7 @@ static struct i2c_driver abp060mg_driver = {
.driver = {
.name = "abp060mg",
},
- .probe_new = abp060mg_probe,
+ .probe = abp060mg_probe,
.id_table = abp060mg_id_table,
};
module_i2c_driver(abp060mg_driver);
diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c
index 567b945e6427..dbe630ad05b5 100644
--- a/drivers/iio/pressure/bmp280-i2c.c
+++ b/drivers/iio/pressure/bmp280-i2c.c
@@ -56,7 +56,7 @@ static struct i2c_driver bmp280_i2c_driver = {
.of_match_table = bmp280_of_i2c_match,
.pm = pm_ptr(&bmp280_dev_pm_ops),
},
- .probe_new = bmp280_i2c_probe,
+ .probe = bmp280_i2c_probe,
.id_table = bmp280_i2c_id,
};
module_i2c_driver(bmp280_i2c_driver);
diff --git a/drivers/iio/pressure/dlhl60d.c b/drivers/iio/pressure/dlhl60d.c
index 43650b048d62..28c8269ba65d 100644
--- a/drivers/iio/pressure/dlhl60d.c
+++ b/drivers/iio/pressure/dlhl60d.c
@@ -362,7 +362,7 @@ static struct i2c_driver dlh_driver = {
.name = "dlhl60d",
.of_match_table = dlh_of_match,
},
- .probe_new = dlh_probe,
+ .probe = dlh_probe,
.id_table = dlh_id,
};
module_i2c_driver(dlh_driver);
diff --git a/drivers/iio/pressure/dps310.c b/drivers/iio/pressure/dps310.c
index 2af275a24ff9..b10dbf5cf494 100644
--- a/drivers/iio/pressure/dps310.c
+++ b/drivers/iio/pressure/dps310.c
@@ -887,7 +887,7 @@ static struct i2c_driver dps310_driver = {
.name = DPS310_DEV_NAME,
.acpi_match_table = dps310_acpi_match,
},
- .probe_new = dps310_probe,
+ .probe = dps310_probe,
.id_table = dps310_id,
};
module_i2c_driver(dps310_driver);
diff --git a/drivers/iio/pressure/hp03.c b/drivers/iio/pressure/hp03.c
index bd1f71a99cfa..8bdb279129fa 100644
--- a/drivers/iio/pressure/hp03.c
+++ b/drivers/iio/pressure/hp03.c
@@ -282,7 +282,7 @@ static struct i2c_driver hp03_driver = {
.name = "hp03",
.of_match_table = hp03_of_match,
},
- .probe_new = hp03_probe,
+ .probe = hp03_probe,
.id_table = hp03_id,
};
module_i2c_driver(hp03_driver);
diff --git a/drivers/iio/pressure/hp206c.c b/drivers/iio/pressure/hp206c.c
index b6d2ff464341..a072de6cb59c 100644
--- a/drivers/iio/pressure/hp206c.c
+++ b/drivers/iio/pressure/hp206c.c
@@ -409,7 +409,7 @@ MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match);
#endif
static struct i2c_driver hp206c_driver = {
- .probe_new = hp206c_probe,
+ .probe = hp206c_probe,
.id_table = hp206c_id,
.driver = {
.name = "hp206c",
diff --git a/drivers/iio/pressure/icp10100.c b/drivers/iio/pressure/icp10100.c
index 407cf25ea0e3..2086f3ef338f 100644
--- a/drivers/iio/pressure/icp10100.c
+++ b/drivers/iio/pressure/icp10100.c
@@ -648,7 +648,7 @@ static struct i2c_driver icp10100_driver = {
.pm = pm_ptr(&icp10100_pm),
.of_match_table = icp10100_of_match,
},
- .probe_new = icp10100_probe,
+ .probe = icp10100_probe,
.id_table = icp10100_id,
};
module_i2c_driver(icp10100_driver);
diff --git a/drivers/iio/pressure/mpl115_i2c.c b/drivers/iio/pressure/mpl115_i2c.c
index ade4dd854ddf..fcbdadf4a511 100644
--- a/drivers/iio/pressure/mpl115_i2c.c
+++ b/drivers/iio/pressure/mpl115_i2c.c
@@ -55,7 +55,7 @@ static struct i2c_driver mpl115_i2c_driver = {
.name = "mpl115",
.pm = pm_ptr(&mpl115_dev_pm_ops),
},
- .probe_new = mpl115_i2c_probe,
+ .probe = mpl115_i2c_probe,
.id_table = mpl115_i2c_id,
};
module_i2c_driver(mpl115_i2c_driver);
diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c
index 72e811a5c96e..7aa19584c340 100644
--- a/drivers/iio/pressure/mpl3115.c
+++ b/drivers/iio/pressure/mpl3115.c
@@ -335,7 +335,7 @@ static struct i2c_driver mpl3115_driver = {
.of_match_table = mpl3115_of_match,
.pm = pm_sleep_ptr(&mpl3115_pm_ops),
},
- .probe_new = mpl3115_probe,
+ .probe = mpl3115_probe,
.remove = mpl3115_remove,
.id_table = mpl3115_id,
};
diff --git a/drivers/iio/pressure/mprls0025pa.c b/drivers/iio/pressure/mprls0025pa.c
new file mode 100644
index 000000000000..30fb2de36821
--- /dev/null
+++ b/drivers/iio/pressure/mprls0025pa.c
@@ -0,0 +1,450 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MPRLS0025PA - Honeywell MicroPressure pressure sensor series driver
+ *
+ * Copyright (c) Andreas Klinger <ak@it-klinger.de>
+ *
+ * Data sheet:
+ * https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/
+ * products/sensors/pressure-sensors/board-mount-pressure-sensors/
+ * micropressure-mpr-series/documents/
+ * sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf
+ *
+ * 7-bit I2C default slave address: 0x18
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/math64.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/units.h>
+
+#include <linux/gpio/consumer.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#include <linux/regulator/consumer.h>
+
+#include <asm/unaligned.h>
+
+/* bits in i2c status byte */
+#define MPR_I2C_POWER BIT(6) /* device is powered */
+#define MPR_I2C_BUSY BIT(5) /* device is busy */
+#define MPR_I2C_MEMORY BIT(2) /* integrity test passed */
+#define MPR_I2C_MATH BIT(0) /* internal math saturation */
+
+/*
+ * support _RAW sysfs interface:
+ *
+ * Calculation formula from the datasheet:
+ * pressure = (press_cnt - outputmin) * scale + pmin
+ * with:
+ * * pressure - measured pressure in Pascal
+ * * press_cnt - raw value read from sensor
+ * * pmin - minimum pressure range value of sensor (data->pmin)
+ * * pmax - maximum pressure range value of sensor (data->pmax)
+ * * outputmin - minimum numerical range raw value delivered by sensor
+ * (mpr_func_spec.output_min)
+ * * outputmax - maximum numerical range raw value delivered by sensor
+ * (mpr_func_spec.output_max)
+ * * scale - (pmax - pmin) / (outputmax - outputmin)
+ *
+ * formula of the userspace:
+ * pressure = (raw + offset) * scale
+ *
+ * Values given to the userspace in sysfs interface:
+ * * raw - press_cnt
+ * * offset - (-1 * outputmin) - pmin / scale
+ * note: With all sensors from the datasheet pmin = 0
+ * which reduces the offset to (-1 * outputmin)
+ */
+
+/*
+ * transfer function A: 10% to 90% of 2^24
+ * transfer function B: 2.5% to 22.5% of 2^24
+ * transfer function C: 20% to 80% of 2^24
+ */
+enum mpr_func_id {
+ MPR_FUNCTION_A,
+ MPR_FUNCTION_B,
+ MPR_FUNCTION_C,
+};
+
+struct mpr_func_spec {
+ u32 output_min;
+ u32 output_max;
+};
+
+static const struct mpr_func_spec mpr_func_spec[] = {
+ [MPR_FUNCTION_A] = {.output_min = 1677722, .output_max = 15099494},
+ [MPR_FUNCTION_B] = {.output_min = 419430, .output_max = 3774874},
+ [MPR_FUNCTION_C] = {.output_min = 3355443, .output_max = 13421773},
+};
+
+struct mpr_chan {
+ s32 pres; /* pressure value */
+ s64 ts; /* timestamp */
+};
+
+struct mpr_data {
+ struct i2c_client *client;
+ struct mutex lock; /*
+ * access to device during read
+ */
+ u32 pmin; /* minimal pressure in pascal */
+ u32 pmax; /* maximal pressure in pascal */
+ enum mpr_func_id function; /* transfer function */
+ u32 outmin; /*
+ * minimal numerical range raw
+ * value from sensor
+ */
+ u32 outmax; /*
+ * maximal numerical range raw
+ * value from sensor
+ */
+ int scale; /* int part of scale */
+ int scale2; /* nano part of scale */
+ int offset; /* int part of offset */
+ int offset2; /* nano part of offset */
+ struct gpio_desc *gpiod_reset; /* reset */
+ int irq; /*
+ * end of conversion irq;
+ * used to distinguish between
+ * irq mode and reading in a
+ * loop until data is ready
+ */
+ struct completion completion; /* handshake from irq to read */
+ struct mpr_chan chan; /*
+ * channel values for buffered
+ * mode
+ */
+};
+
+static const struct iio_chan_spec mpr_channels[] = {
+ {
+ .type = IIO_PRESSURE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_OFFSET),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static void mpr_reset(struct mpr_data *data)
+{
+ if (data->gpiod_reset) {
+ gpiod_set_value(data->gpiod_reset, 0);
+ udelay(10);
+ gpiod_set_value(data->gpiod_reset, 1);
+ }
+}
+
+/**
+ * mpr_read_pressure() - Read pressure value from sensor via I2C
+ * @data: Pointer to private data struct.
+ * @press: Output value read from sensor.
+ *
+ * Reading from the sensor by sending and receiving I2C telegrams.
+ *
+ * If there is an end of conversion (EOC) interrupt registered the function
+ * waits for a maximum of one second for the interrupt.
+ *
+ * Context: The function can sleep and data->lock should be held when calling it
+ * Return:
+ * * 0 - OK, the pressure value could be read
+ * * -ETIMEDOUT - Timeout while waiting for the EOC interrupt or busy flag is
+ * still set after nloops attempts of reading
+ */
+static int mpr_read_pressure(struct mpr_data *data, s32 *press)
+{
+ struct device *dev = &data->client->dev;
+ int ret, i;
+ u8 wdata[] = {0xAA, 0x00, 0x00};
+ s32 status;
+ int nloops = 10;
+ u8 buf[4];
+
+ reinit_completion(&data->completion);
+
+ ret = i2c_master_send(data->client, wdata, sizeof(wdata));
+ if (ret < 0) {
+ dev_err(dev, "error while writing ret: %d\n", ret);
+ return ret;
+ }
+ if (ret != sizeof(wdata)) {
+ dev_err(dev, "received size doesn't fit - ret: %d / %u\n", ret,
+ (u32)sizeof(wdata));
+ return -EIO;
+ }
+
+ if (data->irq > 0) {
+ ret = wait_for_completion_timeout(&data->completion, HZ);
+ if (!ret) {
+ dev_err(dev, "timeout while waiting for eoc irq\n");
+ return -ETIMEDOUT;
+ }
+ } else {
+ /* wait until status indicates data is ready */
+ for (i = 0; i < nloops; i++) {
+ /*
+ * datasheet only says to wait at least 5 ms for the
+ * data but leave the maximum response time open
+ * --> let's try it nloops (10) times which seems to be
+ * quite long
+ */
+ usleep_range(5000, 10000);
+ status = i2c_smbus_read_byte(data->client);
+ if (status < 0) {
+ dev_err(dev,
+ "error while reading, status: %d\n",
+ status);
+ return status;
+ }
+ if (!(status & MPR_I2C_BUSY))
+ break;
+ }
+ if (i == nloops) {
+ dev_err(dev, "timeout while reading\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ ret = i2c_master_recv(data->client, buf, sizeof(buf));
+ if (ret < 0) {
+ dev_err(dev, "error in i2c_master_recv ret: %d\n", ret);
+ return ret;
+ }
+ if (ret != sizeof(buf)) {
+ dev_err(dev, "received size doesn't fit - ret: %d / %u\n", ret,
+ (u32)sizeof(buf));
+ return -EIO;
+ }
+
+ if (buf[0] & MPR_I2C_BUSY) {
+ /*
+ * it should never be the case that status still indicates
+ * business
+ */
+ dev_err(dev, "data still not ready: %08x\n", buf[0]);
+ return -ETIMEDOUT;
+ }
+
+ *press = get_unaligned_be24(&buf[1]);
+
+ dev_dbg(dev, "received: %*ph cnt: %d\n", ret, buf, *press);
+
+ return 0;
+}
+
+static irqreturn_t mpr_eoc_handler(int irq, void *p)
+{
+ struct mpr_data *data = p;
+
+ complete(&data->completion);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mpr_trigger_handler(int irq, void *p)
+{
+ int ret;
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct mpr_data *data = iio_priv(indio_dev);
+
+ mutex_lock(&data->lock);
+ ret = mpr_read_pressure(data, &data->chan.pres);
+ if (ret < 0)
+ goto err;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->chan,
+ iio_get_time_ns(indio_dev));
+
+err:
+ mutex_unlock(&data->lock);
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int mpr_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val, int *val2, long mask)
+{
+ int ret;
+ s32 pressure;
+ struct mpr_data *data = iio_priv(indio_dev);
+
+ if (chan->type != IIO_PRESSURE)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&data->lock);
+ ret = mpr_read_pressure(data, &pressure);
+ mutex_unlock(&data->lock);
+ if (ret < 0)
+ return ret;
+ *val = pressure;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = data->scale;
+ *val2 = data->scale2;
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_CHAN_INFO_OFFSET:
+ *val = data->offset;
+ *val2 = data->offset2;
+ return IIO_VAL_INT_PLUS_NANO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info mpr_info = {
+ .read_raw = &mpr_read_raw,
+};
+
+static int mpr_probe(struct i2c_client *client)
+{
+ int ret;
+ struct mpr_data *data;
+ struct iio_dev *indio_dev;
+ struct device *dev = &client->dev;
+ s64 scale, offset;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE))
+ return dev_err_probe(dev, -EOPNOTSUPP,
+ "I2C functionality not supported\n");
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return dev_err_probe(dev, -ENOMEM, "couldn't get iio_dev\n");
+
+ data = iio_priv(indio_dev);
+ data->client = client;
+ data->irq = client->irq;
+
+ mutex_init(&data->lock);
+ init_completion(&data->completion);
+
+ indio_dev->name = "mprls0025pa";
+ indio_dev->info = &mpr_info;
+ indio_dev->channels = mpr_channels;
+ indio_dev->num_channels = ARRAY_SIZE(mpr_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = devm_regulator_get_enable(dev, "vdd");
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "can't get and enable vdd supply\n");
+
+ if (dev_fwnode(dev)) {
+ ret = device_property_read_u32(dev, "honeywell,pmin-pascal",
+ &data->pmin);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "honeywell,pmin-pascal could not be read\n");
+ ret = device_property_read_u32(dev, "honeywell,pmax-pascal",
+ &data->pmax);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "honeywell,pmax-pascal could not be read\n");
+ ret = device_property_read_u32(dev,
+ "honeywell,transfer-function", &data->function);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "honeywell,transfer-function could not be read\n");
+ if (data->function > MPR_FUNCTION_C)
+ return dev_err_probe(dev, -EINVAL,
+ "honeywell,transfer-function %d invalid\n",
+ data->function);
+ } else {
+ /* when loaded as i2c device we need to use default values */
+ dev_notice(dev, "firmware node not found; using defaults\n");
+ data->pmin = 0;
+ data->pmax = 172369; /* 25 psi */
+ data->function = MPR_FUNCTION_A;
+ }
+
+ data->outmin = mpr_func_spec[data->function].output_min;
+ data->outmax = mpr_func_spec[data->function].output_max;
+
+ /* use 64 bit calculation for preserving a reasonable precision */
+ scale = div_s64(((s64)(data->pmax - data->pmin)) * NANO,
+ data->outmax - data->outmin);
+ data->scale = div_s64_rem(scale, NANO, &data->scale2);
+ /*
+ * multiply with NANO before dividing by scale and later divide by NANO
+ * again.
+ */
+ offset = ((-1LL) * (s64)data->outmin) * NANO -
+ div_s64(div_s64((s64)data->pmin * NANO, scale), NANO);
+ data->offset = div_s64_rem(offset, NANO, &data->offset2);
+
+ if (data->irq > 0) {
+ ret = devm_request_irq(dev, data->irq, mpr_eoc_handler,
+ IRQF_TRIGGER_RISING, client->name, data);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "request irq %d failed\n", data->irq);
+ }
+
+ data->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(data->gpiod_reset))
+ return dev_err_probe(dev, PTR_ERR(data->gpiod_reset),
+ "request reset-gpio failed\n");
+
+ mpr_reset(data);
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
+ mpr_trigger_handler, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "iio triggered buffer setup failed\n");
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "unable to register iio device\n");
+
+ return 0;
+}
+
+static const struct of_device_id mpr_matches[] = {
+ { .compatible = "honeywell,mprls0025pa" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mpr_matches);
+
+static const struct i2c_device_id mpr_id[] = {
+ { "mprls0025pa" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mpr_id);
+
+static struct i2c_driver mpr_driver = {
+ .probe = mpr_probe,
+ .id_table = mpr_id,
+ .driver = {
+ .name = "mprls0025pa",
+ .of_match_table = mpr_matches,
+ },
+};
+module_i2c_driver(mpr_driver);
+
+MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
+MODULE_DESCRIPTION("Honeywell MPRLS0025PA I2C driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c
index e3c68a3ed76a..9a0f52321fcb 100644
--- a/drivers/iio/pressure/ms5611_i2c.c
+++ b/drivers/iio/pressure/ms5611_i2c.c
@@ -125,7 +125,7 @@ static struct i2c_driver ms5611_driver = {
.of_match_table = ms5611_i2c_matches,
},
.id_table = ms5611_id,
- .probe_new = ms5611_i2c_probe,
+ .probe = ms5611_i2c_probe,
};
module_i2c_driver(ms5611_driver);
diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c
index c4981b29dccb..9b3abffb724b 100644
--- a/drivers/iio/pressure/ms5637.c
+++ b/drivers/iio/pressure/ms5637.c
@@ -238,7 +238,7 @@ static const struct of_device_id ms5637_of_match[] = {
MODULE_DEVICE_TABLE(of, ms5637_of_match);
static struct i2c_driver ms5637_driver = {
- .probe_new = ms5637_probe,
+ .probe = ms5637_probe,
.id_table = ms5637_id,
.driver = {
.name = "ms5637",
diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c
index f2c3bb568d16..5101552e3f38 100644
--- a/drivers/iio/pressure/st_pressure_i2c.c
+++ b/drivers/iio/pressure/st_pressure_i2c.c
@@ -116,7 +116,7 @@ static struct i2c_driver st_press_driver = {
.of_match_table = st_press_of_match,
.acpi_match_table = ACPI_PTR(st_press_acpi_match),
},
- .probe_new = st_press_i2c_probe,
+ .probe = st_press_i2c_probe,
.id_table = st_press_id_table,
};
module_i2c_driver(st_press_driver);
diff --git a/drivers/iio/pressure/t5403.c b/drivers/iio/pressure/t5403.c
index 2fbf14aff033..a6463c06975e 100644
--- a/drivers/iio/pressure/t5403.c
+++ b/drivers/iio/pressure/t5403.c
@@ -260,7 +260,7 @@ static struct i2c_driver t5403_driver = {
.driver = {
.name = "t5403",
},
- .probe_new = t5403_probe,
+ .probe = t5403_probe,
.id_table = t5403_id,
};
module_i2c_driver(t5403_driver);
diff --git a/drivers/iio/pressure/zpa2326_i2c.c b/drivers/iio/pressure/zpa2326_i2c.c
index ade465014be1..c7fffbe7c788 100644
--- a/drivers/iio/pressure/zpa2326_i2c.c
+++ b/drivers/iio/pressure/zpa2326_i2c.c
@@ -76,7 +76,7 @@ static struct i2c_driver zpa2326_i2c_driver = {
.of_match_table = zpa2326_i2c_matches,
.pm = ZPA2326_PM_OPS,
},
- .probe_new = zpa2326_probe_i2c,
+ .probe = zpa2326_probe_i2c,
.remove = zpa2326_remove_i2c,
.id_table = zpa2326_i2c_ids,
};
diff --git a/drivers/iio/proximity/isl29501.c b/drivers/iio/proximity/isl29501.c
index 7b8f40b7ccf3..fe45ca35a124 100644
--- a/drivers/iio/proximity/isl29501.c
+++ b/drivers/iio/proximity/isl29501.c
@@ -1008,7 +1008,7 @@ static struct i2c_driver isl29501_driver = {
.name = "isl29501",
},
.id_table = isl29501_id,
- .probe_new = isl29501_probe,
+ .probe = isl29501_probe,
};
module_i2c_driver(isl29501_driver);
diff --git a/drivers/iio/proximity/mb1232.c b/drivers/iio/proximity/mb1232.c
index e70cac8240af..fb1073c8d9f7 100644
--- a/drivers/iio/proximity/mb1232.c
+++ b/drivers/iio/proximity/mb1232.c
@@ -264,7 +264,7 @@ static struct i2c_driver mb1232_driver = {
.name = "maxbotix-mb1232",
.of_match_table = of_mb1232_match,
},
- .probe_new = mb1232_probe,
+ .probe = mb1232_probe,
.id_table = mb1232_id,
};
module_i2c_driver(mb1232_driver);
diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
index c9eead01a031..2913d5e0fe4f 100644
--- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
+++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
@@ -365,7 +365,7 @@ static struct i2c_driver lidar_driver = {
.of_match_table = lidar_dt_ids,
.pm = pm_ptr(&lidar_pm_ops),
},
- .probe_new = lidar_probe,
+ .probe = lidar_probe,
.remove = lidar_remove,
.id_table = lidar_id,
};
diff --git a/drivers/iio/proximity/rfd77402.c b/drivers/iio/proximity/rfd77402.c
index 44f72b78bd50..f02e83e3f15f 100644
--- a/drivers/iio/proximity/rfd77402.c
+++ b/drivers/iio/proximity/rfd77402.c
@@ -318,7 +318,7 @@ static struct i2c_driver rfd77402_driver = {
.name = RFD77402_DRV_NAME,
.pm = pm_sleep_ptr(&rfd77402_pm_ops),
},
- .probe_new = rfd77402_probe,
+ .probe = rfd77402_probe,
.id_table = rfd77402_id,
};
diff --git a/drivers/iio/proximity/srf08.c b/drivers/iio/proximity/srf08.c
index 61866d0440f7..a75ea5042876 100644
--- a/drivers/iio/proximity/srf08.c
+++ b/drivers/iio/proximity/srf08.c
@@ -549,7 +549,7 @@ static struct i2c_driver srf08_driver = {
.name = "srf08",
.of_match_table = of_srf08_match,
},
- .probe_new = srf08_probe,
+ .probe = srf08_probe,
.id_table = srf08_id,
};
module_i2c_driver(srf08_driver);
diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c
index 0e4747ccd3cf..d977aacb7491 100644
--- a/drivers/iio/proximity/sx9310.c
+++ b/drivers/iio/proximity/sx9310.c
@@ -1050,7 +1050,7 @@ static struct i2c_driver sx9310_driver = {
*/
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = sx9310_probe,
+ .probe = sx9310_probe,
.id_table = sx9310_id,
};
module_i2c_driver(sx9310_driver);
diff --git a/drivers/iio/proximity/sx9324.c b/drivers/iio/proximity/sx9324.c
index 9a40ca32bb1c..438f9c9aba6e 100644
--- a/drivers/iio/proximity/sx9324.c
+++ b/drivers/iio/proximity/sx9324.c
@@ -1152,7 +1152,7 @@ static struct i2c_driver sx9324_driver = {
*/
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = sx9324_probe,
+ .probe = sx9324_probe,
.id_table = sx9324_id,
};
module_i2c_driver(sx9324_driver);
diff --git a/drivers/iio/proximity/sx9360.c b/drivers/iio/proximity/sx9360.c
index a50d9176411a..2c4e14a4fe9f 100644
--- a/drivers/iio/proximity/sx9360.c
+++ b/drivers/iio/proximity/sx9360.c
@@ -896,7 +896,7 @@ static struct i2c_driver sx9360_driver = {
*/
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = sx9360_probe,
+ .probe = sx9360_probe,
.id_table = sx9360_id,
};
module_i2c_driver(sx9360_driver);
diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c
index 9b2cfcade6a4..550e7d3cd5ee 100644
--- a/drivers/iio/proximity/sx9500.c
+++ b/drivers/iio/proximity/sx9500.c
@@ -1055,7 +1055,7 @@ static struct i2c_driver sx9500_driver = {
.of_match_table = sx9500_of_match,
.pm = pm_sleep_ptr(&sx9500_pm_ops),
},
- .probe_new = sx9500_probe,
+ .probe = sx9500_probe,
.remove = sx9500_remove,
.id_table = sx9500_id,
};
diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c
index cbc8400c773c..d1ddf85f5383 100644
--- a/drivers/iio/proximity/vcnl3020.c
+++ b/drivers/iio/proximity/vcnl3020.c
@@ -662,7 +662,7 @@ static struct i2c_driver vcnl3020_driver = {
.name = "vcnl3020",
.of_match_table = vcnl3020_of_match,
},
- .probe_new = vcnl3020_probe,
+ .probe = vcnl3020_probe,
};
module_i2c_driver(vcnl3020_driver);
diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c
index c7c4d33d340f..2cea64bea909 100644
--- a/drivers/iio/proximity/vl53l0x-i2c.c
+++ b/drivers/iio/proximity/vl53l0x-i2c.c
@@ -294,7 +294,7 @@ static struct i2c_driver vl53l0x_driver = {
.name = "vl53l0x-i2c",
.of_match_table = st_vl53l0x_dt_match,
},
- .probe_new = vl53l0x_probe,
+ .probe = vl53l0x_probe,
.id_table = vl53l0x_id,
};
module_i2c_driver(vl53l0x_driver);
diff --git a/drivers/iio/temperature/max30208.c b/drivers/iio/temperature/max30208.c
index c85c21474711..48be03852cd8 100644
--- a/drivers/iio/temperature/max30208.c
+++ b/drivers/iio/temperature/max30208.c
@@ -242,7 +242,7 @@ static struct i2c_driver max30208_driver = {
.of_match_table = max30208_of_match,
.acpi_match_table = max30208_acpi_match,
},
- .probe_new = max30208_probe,
+ .probe = max30208_probe,
.id_table = max30208_id_table,
};
module_i2c_driver(max30208_driver);
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c
index 909fadb62349..676dc8701924 100644
--- a/drivers/iio/temperature/mlx90614.c
+++ b/drivers/iio/temperature/mlx90614.c
@@ -1,12 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * mlx90614.c - Support for Melexis MLX90614 contactless IR temperature sensor
+ * mlx90614.c - Support for Melexis MLX90614/MLX90615 contactless IR temperature sensor
*
* Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
* Copyright (c) 2015 Essensium NV
* Copyright (c) 2015 Melexis
*
- * Driver for the Melexis MLX90614 I2C 16-bit IR thermopile sensor
+ * Driver for the Melexis MLX90614/MLX90615 I2C 16-bit IR thermopile sensor
+ *
+ * MLX90614 - 17-bit ADC + MLX90302 DSP
+ * MLX90615 - 16-bit ADC + MLX90325 DSP
*
* (7-bit I2C slave address 0x5a, 100KHz bus speed only!)
*
@@ -19,12 +22,13 @@
* the "wakeup" GPIO is not given, power management will be disabled.
*/
+#include <linux/delay.h>
#include <linux/err.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/delay.h>
#include <linux/jiffies.h>
-#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
@@ -34,16 +38,9 @@
#define MLX90614_OP_EEPROM 0x20
#define MLX90614_OP_SLEEP 0xff
-/* RAM offsets with 16-bit data, MSB first */
-#define MLX90614_RAW1 (MLX90614_OP_RAM | 0x04) /* raw data IR channel 1 */
-#define MLX90614_RAW2 (MLX90614_OP_RAM | 0x05) /* raw data IR channel 2 */
-#define MLX90614_TA (MLX90614_OP_RAM | 0x06) /* ambient temperature */
-#define MLX90614_TOBJ1 (MLX90614_OP_RAM | 0x07) /* object 1 temperature */
-#define MLX90614_TOBJ2 (MLX90614_OP_RAM | 0x08) /* object 2 temperature */
-
-/* EEPROM offsets with 16-bit data, MSB first */
-#define MLX90614_EMISSIVITY (MLX90614_OP_EEPROM | 0x04) /* emissivity correction coefficient */
-#define MLX90614_CONFIG (MLX90614_OP_EEPROM | 0x05) /* configuration register */
+#define MLX90615_OP_EEPROM 0x10
+#define MLX90615_OP_RAM 0x20
+#define MLX90615_OP_SLEEP 0xc6
/* Control bits in configuration register */
#define MLX90614_CONFIG_IIR_SHIFT 0 /* IIR coefficient */
@@ -52,44 +49,61 @@
#define MLX90614_CONFIG_DUAL_MASK (1 << MLX90614_CONFIG_DUAL_SHIFT)
#define MLX90614_CONFIG_FIR_SHIFT 8 /* FIR coefficient */
#define MLX90614_CONFIG_FIR_MASK (0x7 << MLX90614_CONFIG_FIR_SHIFT)
-#define MLX90614_CONFIG_GAIN_SHIFT 11 /* gain */
-#define MLX90614_CONFIG_GAIN_MASK (0x7 << MLX90614_CONFIG_GAIN_SHIFT)
+
+#define MLX90615_CONFIG_IIR_SHIFT 12 /* IIR coefficient */
+#define MLX90615_CONFIG_IIR_MASK (0x7 << MLX90615_CONFIG_IIR_SHIFT)
/* Timings (in ms) */
#define MLX90614_TIMING_EEPROM 20 /* time for EEPROM write/erase to complete */
#define MLX90614_TIMING_WAKEUP 34 /* time to hold SDA low for wake-up */
#define MLX90614_TIMING_STARTUP 250 /* time before first data after wake-up */
+#define MLX90615_TIMING_WAKEUP 22 /* time to hold SCL low for wake-up */
+
#define MLX90614_AUTOSLEEP_DELAY 5000 /* default autosleep delay */
/* Magic constants */
#define MLX90614_CONST_OFFSET_DEC -13657 /* decimal part of the Kelvin offset */
#define MLX90614_CONST_OFFSET_REM 500000 /* remainder of offset (273.15*50) */
#define MLX90614_CONST_SCALE 20 /* Scale in milliKelvin (0.02 * 1000) */
-#define MLX90614_CONST_RAW_EMISSIVITY_MAX 65535 /* max value for emissivity */
-#define MLX90614_CONST_EMISSIVITY_RESOLUTION 15259 /* 1/65535 ~ 0.000015259 */
#define MLX90614_CONST_FIR 0x7 /* Fixed value for FIR part of low pass filter */
+/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
+
+struct mlx_chip_info {
+ /* EEPROM offsets with 16-bit data, MSB first */
+ /* emissivity correction coefficient */
+ u8 op_eeprom_emissivity;
+ u8 op_eeprom_config1;
+ /* RAM offsets with 16-bit data, MSB first */
+ /* ambient temperature */
+ u8 op_ram_ta;
+ /* object 1 temperature */
+ u8 op_ram_tobj1;
+ /* object 2 temperature */
+ u8 op_ram_tobj2;
+ u8 op_sleep;
+ /* support for two input channels (MLX90614 only) */
+ u8 dual_channel;
+ u8 wakeup_delay_ms;
+ u16 emissivity_max;
+ u16 fir_config_mask;
+ u16 iir_config_mask;
+ int iir_valid_offset;
+ u16 iir_values[8];
+ int iir_freqs[8][2];
+};
+
struct mlx90614_data {
struct i2c_client *client;
struct mutex lock; /* for EEPROM access only */
struct gpio_desc *wakeup_gpio; /* NULL to disable sleep/wake-up */
+ const struct mlx_chip_info *chip_info; /* Chip hardware details */
unsigned long ready_timestamp; /* in jiffies */
};
-/* Bandwidth values for IIR filtering */
-static const int mlx90614_iir_values[] = {77, 31, 20, 15, 723, 153, 110, 86};
-static const int mlx90614_freqs[][2] = {
- {0, 150000},
- {0, 200000},
- {0, 310000},
- {0, 770000},
- {0, 860000},
- {1, 100000},
- {1, 530000},
- {7, 230000}
-};
-
/*
* Erase an address and write word.
* The mutex must be locked before calling.
@@ -129,21 +143,26 @@ static s32 mlx90614_write_word(const struct i2c_client *client, u8 command,
}
/*
- * Find the IIR value inside mlx90614_iir_values array and return its position
+ * Find the IIR value inside iir_values array and return its position
* which is equivalent to the bit value in sensor register
*/
static inline s32 mlx90614_iir_search(const struct i2c_client *client,
int value)
{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct mlx90614_data *data = iio_priv(indio_dev);
+ const struct mlx_chip_info *chip_info = data->chip_info;
int i;
s32 ret;
- for (i = 0; i < ARRAY_SIZE(mlx90614_iir_values); ++i) {
- if (value == mlx90614_iir_values[i])
+ for (i = chip_info->iir_valid_offset;
+ i < ARRAY_SIZE(chip_info->iir_values);
+ i++) {
+ if (value == chip_info->iir_values[i])
break;
}
- if (i == ARRAY_SIZE(mlx90614_iir_values))
+ if (i == ARRAY_SIZE(chip_info->iir_values))
return -EINVAL;
/*
@@ -151,17 +170,21 @@ static inline s32 mlx90614_iir_search(const struct i2c_client *client,
* we must read them before we actually write
* changes
*/
- ret = i2c_smbus_read_word_data(client, MLX90614_CONFIG);
+ ret = i2c_smbus_read_word_data(client, chip_info->op_eeprom_config1);
if (ret < 0)
return ret;
- ret &= ~MLX90614_CONFIG_FIR_MASK;
- ret |= MLX90614_CONST_FIR << MLX90614_CONFIG_FIR_SHIFT;
- ret &= ~MLX90614_CONFIG_IIR_MASK;
- ret |= i << MLX90614_CONFIG_IIR_SHIFT;
+ /* Modify FIR on parts which have configurable FIR filter */
+ if (chip_info->fir_config_mask) {
+ ret &= ~chip_info->fir_config_mask;
+ ret |= field_prep(chip_info->fir_config_mask, MLX90614_CONST_FIR);
+ }
+
+ ret &= ~chip_info->iir_config_mask;
+ ret |= field_prep(chip_info->iir_config_mask, i);
/* Write changed values */
- ret = mlx90614_write_word(client, MLX90614_CONFIG, ret);
+ ret = mlx90614_write_word(client, chip_info->op_eeprom_config1, ret);
return ret;
}
@@ -221,22 +244,26 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
int *val2, long mask)
{
struct mlx90614_data *data = iio_priv(indio_dev);
- u8 cmd;
+ const struct mlx_chip_info *chip_info = data->chip_info;
+ u8 cmd, idx;
s32 ret;
switch (mask) {
case IIO_CHAN_INFO_RAW: /* 0.02K / LSB */
switch (channel->channel2) {
case IIO_MOD_TEMP_AMBIENT:
- cmd = MLX90614_TA;
+ cmd = chip_info->op_ram_ta;
break;
case IIO_MOD_TEMP_OBJECT:
+ if (chip_info->dual_channel && channel->channel)
+ return -EINVAL;
+
switch (channel->channel) {
case 0:
- cmd = MLX90614_TOBJ1;
+ cmd = chip_info->op_ram_tobj1;
break;
case 1:
- cmd = MLX90614_TOBJ2;
+ cmd = chip_info->op_ram_tobj2;
break;
default:
return -EINVAL;
@@ -268,45 +295,48 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
*val = MLX90614_CONST_SCALE;
return IIO_VAL_INT;
- case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
+ case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/emissivity_max / LSB */
ret = mlx90614_power_get(data, false);
if (ret < 0)
return ret;
mutex_lock(&data->lock);
ret = i2c_smbus_read_word_data(data->client,
- MLX90614_EMISSIVITY);
+ chip_info->op_eeprom_emissivity);
mutex_unlock(&data->lock);
mlx90614_power_put(data);
if (ret < 0)
return ret;
- if (ret == MLX90614_CONST_RAW_EMISSIVITY_MAX) {
+ if (ret == chip_info->emissivity_max) {
*val = 1;
*val2 = 0;
} else {
*val = 0;
- *val2 = ret * MLX90614_CONST_EMISSIVITY_RESOLUTION;
+ *val2 = ret * NSEC_PER_SEC / chip_info->emissivity_max;
}
return IIO_VAL_INT_PLUS_NANO;
- case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR setting with
- FIR = 1024 */
+ /* IIR setting with FIR=1024 (MLX90614) or FIR=65536 (MLX90615) */
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
ret = mlx90614_power_get(data, false);
if (ret < 0)
return ret;
mutex_lock(&data->lock);
- ret = i2c_smbus_read_word_data(data->client, MLX90614_CONFIG);
+ ret = i2c_smbus_read_word_data(data->client,
+ chip_info->op_eeprom_config1);
mutex_unlock(&data->lock);
mlx90614_power_put(data);
if (ret < 0)
return ret;
- *val = mlx90614_iir_values[ret & MLX90614_CONFIG_IIR_MASK] / 100;
- *val2 = (mlx90614_iir_values[ret & MLX90614_CONFIG_IIR_MASK] % 100) *
- 10000;
+ idx = field_get(chip_info->iir_config_mask, ret) -
+ chip_info->iir_valid_offset;
+
+ *val = chip_info->iir_values[idx] / 100;
+ *val2 = (chip_info->iir_values[idx] % 100) * 10000;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
@@ -318,22 +348,23 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev,
int val2, long mask)
{
struct mlx90614_data *data = iio_priv(indio_dev);
+ const struct mlx_chip_info *chip_info = data->chip_info;
s32 ret;
switch (mask) {
- case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
+ case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/emissivity_max / LSB */
if (val < 0 || val2 < 0 || val > 1 || (val == 1 && val2 != 0))
return -EINVAL;
- val = val * MLX90614_CONST_RAW_EMISSIVITY_MAX +
- val2 / MLX90614_CONST_EMISSIVITY_RESOLUTION;
+ val = val * chip_info->emissivity_max +
+ val2 * chip_info->emissivity_max / NSEC_PER_SEC;
ret = mlx90614_power_get(data, false);
if (ret < 0)
return ret;
mutex_lock(&data->lock);
- ret = mlx90614_write_word(data->client, MLX90614_EMISSIVITY,
- val);
+ ret = mlx90614_write_word(data->client,
+ chip_info->op_eeprom_emissivity, val);
mutex_unlock(&data->lock);
mlx90614_power_put(data);
@@ -377,11 +408,15 @@ static int mlx90614_read_avail(struct iio_dev *indio_dev,
const int **vals, int *type, int *length,
long mask)
{
+ struct mlx90614_data *data = iio_priv(indio_dev);
+ const struct mlx_chip_info *chip_info = data->chip_info;
+
switch (mask) {
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
- *vals = (int *)mlx90614_freqs;
+ *vals = (int *)chip_info->iir_freqs;
*type = IIO_VAL_INT_PLUS_MICRO;
- *length = 2 * ARRAY_SIZE(mlx90614_freqs);
+ *length = 2 * (ARRAY_SIZE(chip_info->iir_freqs) -
+ chip_info->iir_valid_offset);
return IIO_AVAIL_LIST;
default:
return -EINVAL;
@@ -435,6 +470,7 @@ static const struct iio_info mlx90614_info = {
#ifdef CONFIG_PM
static int mlx90614_sleep(struct mlx90614_data *data)
{
+ const struct mlx_chip_info *chip_info = data->chip_info;
s32 ret;
if (!data->wakeup_gpio) {
@@ -447,7 +483,7 @@ static int mlx90614_sleep(struct mlx90614_data *data)
mutex_lock(&data->lock);
ret = i2c_smbus_xfer(data->client->adapter, data->client->addr,
data->client->flags | I2C_CLIENT_PEC,
- I2C_SMBUS_WRITE, MLX90614_OP_SLEEP,
+ I2C_SMBUS_WRITE, chip_info->op_sleep,
I2C_SMBUS_BYTE, NULL);
mutex_unlock(&data->lock);
@@ -456,6 +492,8 @@ static int mlx90614_sleep(struct mlx90614_data *data)
static int mlx90614_wakeup(struct mlx90614_data *data)
{
+ const struct mlx_chip_info *chip_info = data->chip_info;
+
if (!data->wakeup_gpio) {
dev_dbg(&data->client->dev, "Wake-up disabled");
return -ENOSYS;
@@ -465,7 +503,7 @@ static int mlx90614_wakeup(struct mlx90614_data *data)
i2c_lock_bus(data->client->adapter, I2C_LOCK_ROOT_ADAPTER);
gpiod_direction_output(data->wakeup_gpio, 0);
- msleep(MLX90614_TIMING_WAKEUP);
+ msleep(chip_info->wakeup_delay_ms);
gpiod_direction_input(data->wakeup_gpio);
i2c_unlock_bus(data->client->adapter, I2C_LOCK_ROOT_ADAPTER);
@@ -478,7 +516,7 @@ static int mlx90614_wakeup(struct mlx90614_data *data)
* If the read fails, the controller will probably be reset so that
* further reads will work.
*/
- i2c_smbus_read_word_data(data->client, MLX90614_CONFIG);
+ i2c_smbus_read_word_data(data->client, chip_info->op_eeprom_config1);
return 0;
}
@@ -527,9 +565,15 @@ static inline struct gpio_desc *mlx90614_probe_wakeup(struct i2c_client *client)
/* Return 0 for single sensor, 1 for dual sensor, <0 on error. */
static int mlx90614_probe_num_ir_sensors(struct i2c_client *client)
{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct mlx90614_data *data = iio_priv(indio_dev);
+ const struct mlx_chip_info *chip_info = data->chip_info;
s32 ret;
- ret = i2c_smbus_read_word_data(client, MLX90614_CONFIG);
+ if (chip_info->dual_channel)
+ return 0;
+
+ ret = i2c_smbus_read_word_data(client, chip_info->op_eeprom_config1);
if (ret < 0)
return ret;
@@ -556,6 +600,7 @@ static int mlx90614_probe(struct i2c_client *client)
data->client = client;
mutex_init(&data->lock);
data->wakeup_gpio = mlx90614_probe_wakeup(client);
+ data->chip_info = device_get_match_data(&client->dev);
mlx90614_wakeup(data);
@@ -605,14 +650,68 @@ static void mlx90614_remove(struct i2c_client *client)
}
}
+static const struct mlx_chip_info mlx90614_chip_info = {
+ .op_eeprom_emissivity = MLX90614_OP_EEPROM | 0x04,
+ .op_eeprom_config1 = MLX90614_OP_EEPROM | 0x05,
+ .op_ram_ta = MLX90614_OP_RAM | 0x06,
+ .op_ram_tobj1 = MLX90614_OP_RAM | 0x07,
+ .op_ram_tobj2 = MLX90614_OP_RAM | 0x08,
+ .op_sleep = MLX90614_OP_SLEEP,
+ .dual_channel = true,
+ .wakeup_delay_ms = MLX90614_TIMING_WAKEUP,
+ .emissivity_max = 65535,
+ .fir_config_mask = MLX90614_CONFIG_FIR_MASK,
+ .iir_config_mask = MLX90614_CONFIG_IIR_MASK,
+ .iir_valid_offset = 0,
+ .iir_values = { 77, 31, 20, 15, 723, 153, 110, 86 },
+ .iir_freqs = {
+ { 0, 150000 }, /* 13% ~= 0.15 Hz */
+ { 0, 200000 }, /* 17% ~= 0.20 Hz */
+ { 0, 310000 }, /* 25% ~= 0.31 Hz */
+ { 0, 770000 }, /* 50% ~= 0.77 Hz */
+ { 0, 860000 }, /* 57% ~= 0.86 Hz */
+ { 1, 100000 }, /* 67% ~= 1.10 Hz */
+ { 1, 530000 }, /* 80% ~= 1.53 Hz */
+ { 7, 230000 } /* 100% ~= 7.23 Hz */
+ },
+};
+
+static const struct mlx_chip_info mlx90615_chip_info = {
+ .op_eeprom_emissivity = MLX90615_OP_EEPROM | 0x03,
+ .op_eeprom_config1 = MLX90615_OP_EEPROM | 0x02,
+ .op_ram_ta = MLX90615_OP_RAM | 0x06,
+ .op_ram_tobj1 = MLX90615_OP_RAM | 0x07,
+ .op_ram_tobj2 = MLX90615_OP_RAM | 0x08,
+ .op_sleep = MLX90615_OP_SLEEP,
+ .dual_channel = false,
+ .wakeup_delay_ms = MLX90615_TIMING_WAKEUP,
+ .emissivity_max = 16383,
+ .fir_config_mask = 0, /* MLX90615 FIR is fixed */
+ .iir_config_mask = MLX90615_CONFIG_IIR_MASK,
+ /* IIR value 0 is FORBIDDEN COMBINATION on MLX90615 */
+ .iir_valid_offset = 1,
+ .iir_values = { 500, 50, 30, 20, 15, 13, 10 },
+ .iir_freqs = {
+ { 0, 100000 }, /* 14% ~= 0.10 Hz */
+ { 0, 130000 }, /* 17% ~= 0.13 Hz */
+ { 0, 150000 }, /* 20% ~= 0.15 Hz */
+ { 0, 200000 }, /* 25% ~= 0.20 Hz */
+ { 0, 300000 }, /* 33% ~= 0.30 Hz */
+ { 0, 500000 }, /* 50% ~= 0.50 Hz */
+ { 5, 000000 }, /* 100% ~= 5.00 Hz */
+ },
+};
+
static const struct i2c_device_id mlx90614_id[] = {
- { "mlx90614", 0 },
+ { "mlx90614", .driver_data = (kernel_ulong_t)&mlx90614_chip_info },
+ { "mlx90615", .driver_data = (kernel_ulong_t)&mlx90615_chip_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, mlx90614_id);
static const struct of_device_id mlx90614_of_match[] = {
- { .compatible = "melexis,mlx90614" },
+ { .compatible = "melexis,mlx90614", .data = &mlx90614_chip_info },
+ { .compatible = "melexis,mlx90615", .data = &mlx90615_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, mlx90614_of_match);
@@ -675,7 +774,7 @@ static struct i2c_driver mlx90614_driver = {
.of_match_table = mlx90614_of_match,
.pm = pm_ptr(&mlx90614_pm_ops),
},
- .probe_new = mlx90614_probe,
+ .probe = mlx90614_probe,
.remove = mlx90614_remove,
.id_table = mlx90614_id,
};
diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c
index 753b7a4ccfdd..8a57be108620 100644
--- a/drivers/iio/temperature/mlx90632.c
+++ b/drivers/iio/temperature/mlx90632.c
@@ -1337,7 +1337,7 @@ static struct i2c_driver mlx90632_driver = {
.of_match_table = mlx90632_of_match,
.pm = pm_ptr(&mlx90632_pm_ops),
},
- .probe_new = mlx90632_probe,
+ .probe = mlx90632_probe,
.id_table = mlx90632_id,
};
module_i2c_driver(mlx90632_driver);
diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c
index cdf08477e63f..3a3904fe138c 100644
--- a/drivers/iio/temperature/tmp006.c
+++ b/drivers/iio/temperature/tmp006.c
@@ -15,6 +15,7 @@
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/pm.h>
#include <linux/bitops.h>
@@ -272,6 +273,12 @@ static int tmp006_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(tmp006_pm_ops, tmp006_suspend, tmp006_resume);
+static const struct of_device_id tmp006_of_match[] = {
+ { .compatible = "ti,tmp006" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, tmp006_of_match);
+
static const struct i2c_device_id tmp006_id[] = {
{ "tmp006", 0 },
{ }
@@ -281,9 +288,10 @@ MODULE_DEVICE_TABLE(i2c, tmp006_id);
static struct i2c_driver tmp006_driver = {
.driver = {
.name = "tmp006",
+ .of_match_table = tmp006_of_match,
.pm = pm_sleep_ptr(&tmp006_pm_ops),
},
- .probe_new = tmp006_probe,
+ .probe = tmp006_probe,
.id_table = tmp006_id,
};
module_i2c_driver(tmp006_driver);
diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c
index 8d27aa3bdd6d..decef6896362 100644
--- a/drivers/iio/temperature/tmp007.c
+++ b/drivers/iio/temperature/tmp007.c
@@ -574,7 +574,7 @@ static struct i2c_driver tmp007_driver = {
.of_match_table = tmp007_of_match,
.pm = pm_sleep_ptr(&tmp007_pm_ops),
},
- .probe_new = tmp007_probe,
+ .probe = tmp007_probe,
.id_table = tmp007_id,
};
module_i2c_driver(tmp007_driver);
diff --git a/drivers/iio/temperature/tmp117.c b/drivers/iio/temperature/tmp117.c
index 638e3a5bd6b8..fc02f491688b 100644
--- a/drivers/iio/temperature/tmp117.c
+++ b/drivers/iio/temperature/tmp117.c
@@ -217,7 +217,7 @@ static struct i2c_driver tmp117_driver = {
.name = "tmp117",
.of_match_table = tmp117_of_match,
},
- .probe_new = tmp117_probe,
+ .probe = tmp117_probe,
.id_table = tmp117_id,
};
module_i2c_driver(tmp117_driver);
diff --git a/drivers/iio/temperature/tsys01.c b/drivers/iio/temperature/tsys01.c
index 30b268ba82cc..53ef56fbfe1d 100644
--- a/drivers/iio/temperature/tsys01.c
+++ b/drivers/iio/temperature/tsys01.c
@@ -218,7 +218,7 @@ static const struct of_device_id tsys01_of_match[] = {
MODULE_DEVICE_TABLE(of, tsys01_of_match);
static struct i2c_driver tsys01_driver = {
- .probe_new = tsys01_i2c_probe,
+ .probe = tsys01_i2c_probe,
.id_table = tsys01_id,
.driver = {
.name = "tsys01",
diff --git a/drivers/iio/temperature/tsys02d.c b/drivers/iio/temperature/tsys02d.c
index cdefe046ab17..6191db92ef9a 100644
--- a/drivers/iio/temperature/tsys02d.c
+++ b/drivers/iio/temperature/tsys02d.c
@@ -174,7 +174,7 @@ static const struct i2c_device_id tsys02d_id[] = {
MODULE_DEVICE_TABLE(i2c, tsys02d_id);
static struct i2c_driver tsys02d_driver = {
- .probe_new = tsys02d_probe,
+ .probe = tsys02d_probe,
.id_table = tsys02d_id,
.driver = {
.name = "tsys02d",
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 6b3f4384e46a..1ee87c3aaeab 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -4805,8 +4805,7 @@ static void cma_make_mc_event(int status, struct rdma_id_private *id_priv,
event->param.ud.qkey = id_priv->qkey;
out:
- if (ndev)
- dev_put(ndev);
+ dev_put(ndev);
}
static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
diff --git a/drivers/infiniband/hw/bnxt_re/bnxt_re.h b/drivers/infiniband/hw/bnxt_re/bnxt_re.h
index 2c95e6f3d47a..ea81b2497511 100644
--- a/drivers/infiniband/hw/bnxt_re/bnxt_re.h
+++ b/drivers/infiniband/hw/bnxt_re/bnxt_re.h
@@ -39,6 +39,7 @@
#ifndef __BNXT_RE_H__
#define __BNXT_RE_H__
+#include <rdma/uverbs_ioctl.h>
#include "hw_counters.h"
#define ROCE_DRV_MODULE_NAME "bnxt_re"
@@ -179,10 +180,14 @@ struct bnxt_re_dev {
#define BNXT_RE_ROCEV2_IPV4_PACKET 2
#define BNXT_RE_ROCEV2_IPV6_PACKET 3
+#define BNXT_RE_CHECK_RC(x) ((x) && ((x) != -ETIMEDOUT))
+
static inline struct device *rdev_to_dev(struct bnxt_re_dev *rdev)
{
if (rdev)
return &rdev->ibdev.dev;
return NULL;
}
+
+extern const struct uapi_definition bnxt_re_uapi_defs[];
#endif
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 952811c40c54..abef0b8baa7c 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -61,6 +61,15 @@
#include "bnxt_re.h"
#include "ib_verbs.h"
+
+#include <rdma/uverbs_types.h>
+#include <rdma/uverbs_std_types.h>
+
+#include <rdma/ib_user_ioctl_cmds.h>
+
+#define UVERBS_MODULE_NAME bnxt_re
+#include <rdma/uverbs_named_ioctl.h>
+
#include <rdma/bnxt_re-abi.h>
static int __from_ib_access_flags(int iflags)
@@ -534,12 +543,57 @@ fail:
return rc;
}
+static struct bnxt_re_user_mmap_entry*
+bnxt_re_mmap_entry_insert(struct bnxt_re_ucontext *uctx, u64 mem_offset,
+ enum bnxt_re_mmap_flag mmap_flag, u64 *offset)
+{
+ struct bnxt_re_user_mmap_entry *entry;
+ int ret;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return NULL;
+
+ entry->mem_offset = mem_offset;
+ entry->mmap_flag = mmap_flag;
+ entry->uctx = uctx;
+
+ switch (mmap_flag) {
+ case BNXT_RE_MMAP_SH_PAGE:
+ ret = rdma_user_mmap_entry_insert_exact(&uctx->ib_uctx,
+ &entry->rdma_entry, PAGE_SIZE, 0);
+ break;
+ case BNXT_RE_MMAP_UC_DB:
+ case BNXT_RE_MMAP_WC_DB:
+ ret = rdma_user_mmap_entry_insert(&uctx->ib_uctx,
+ &entry->rdma_entry, PAGE_SIZE);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret) {
+ kfree(entry);
+ return NULL;
+ }
+ if (offset)
+ *offset = rdma_user_mmap_get_offset(&entry->rdma_entry);
+
+ return entry;
+}
+
/* Protection Domains */
int bnxt_re_dealloc_pd(struct ib_pd *ib_pd, struct ib_udata *udata)
{
struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
struct bnxt_re_dev *rdev = pd->rdev;
+ if (udata) {
+ rdma_user_mmap_entry_remove(pd->pd_db_mmap);
+ pd->pd_db_mmap = NULL;
+ }
+
bnxt_re_destroy_fence_mr(pd);
if (pd->qplib_pd.id) {
@@ -558,7 +612,8 @@ int bnxt_re_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
struct bnxt_re_ucontext *ucntx = rdma_udata_to_drv_context(
udata, struct bnxt_re_ucontext, ib_uctx);
struct bnxt_re_pd *pd = container_of(ibpd, struct bnxt_re_pd, ib_pd);
- int rc;
+ struct bnxt_re_user_mmap_entry *entry = NULL;
+ int rc = 0;
pd->rdev = rdev;
if (bnxt_qplib_alloc_pd(&rdev->qplib_res.pd_tbl, &pd->qplib_pd)) {
@@ -568,15 +623,15 @@ int bnxt_re_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
}
if (udata) {
- struct bnxt_re_pd_resp resp;
+ struct bnxt_re_pd_resp resp = {};
if (!ucntx->dpi.dbr) {
/* Allocate DPI in alloc_pd to avoid failing of
* ibv_devinfo and family of application when DPIs
* are depleted.
*/
- if (bnxt_qplib_alloc_dpi(&rdev->qplib_res.dpi_tbl,
- &ucntx->dpi, ucntx)) {
+ if (bnxt_qplib_alloc_dpi(&rdev->qplib_res,
+ &ucntx->dpi, ucntx, BNXT_QPLIB_DPI_TYPE_UC)) {
rc = -ENOMEM;
goto dbfail;
}
@@ -585,12 +640,21 @@ int bnxt_re_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
resp.pdid = pd->qplib_pd.id;
/* Still allow mapping this DBR to the new user PD. */
resp.dpi = ucntx->dpi.dpi;
- resp.dbr = (u64)ucntx->dpi.umdbr;
- rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
+ entry = bnxt_re_mmap_entry_insert(ucntx, (u64)ucntx->dpi.umdbr,
+ BNXT_RE_MMAP_UC_DB, &resp.dbr);
+
+ if (!entry) {
+ rc = -ENOMEM;
+ goto dbfail;
+ }
+
+ pd->pd_db_mmap = &entry->rdma_entry;
+
+ rc = ib_copy_to_udata(udata, &resp, min(sizeof(resp), udata->outlen));
if (rc) {
- ibdev_err(&rdev->ibdev,
- "Failed to copy user response\n");
+ rdma_user_mmap_entry_remove(pd->pd_db_mmap);
+ rc = -EFAULT;
goto dbfail;
}
}
@@ -614,12 +678,20 @@ int bnxt_re_destroy_ah(struct ib_ah *ib_ah, u32 flags)
{
struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ib_ah);
struct bnxt_re_dev *rdev = ah->rdev;
+ bool block = true;
+ int rc = 0;
- bnxt_qplib_destroy_ah(&rdev->qplib_res, &ah->qplib_ah,
- !(flags & RDMA_DESTROY_AH_SLEEPABLE));
+ block = !(flags & RDMA_DESTROY_AH_SLEEPABLE);
+ rc = bnxt_qplib_destroy_ah(&rdev->qplib_res, &ah->qplib_ah, block);
+ if (BNXT_RE_CHECK_RC(rc)) {
+ if (rc == -ETIMEDOUT)
+ rc = 0;
+ else
+ goto fail;
+ }
atomic_dec(&rdev->ah_count);
-
- return 0;
+fail:
+ return rc;
}
static u8 bnxt_re_stack_to_dev_nw_type(enum rdma_network_type ntype)
@@ -3955,6 +4027,7 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
container_of(ctx, struct bnxt_re_ucontext, ib_uctx);
struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
+ struct bnxt_re_user_mmap_entry *entry;
struct bnxt_re_uctx_resp resp = {};
u32 chip_met_rev_num = 0;
int rc;
@@ -3993,6 +4066,16 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
resp.comp_mask |= BNXT_RE_UCNTX_CMASK_HAVE_MODE;
resp.mode = rdev->chip_ctx->modes.wqe_mode;
+ if (rdev->chip_ctx->modes.db_push)
+ resp.comp_mask |= BNXT_RE_UCNTX_CMASK_WC_DPI_ENABLED;
+
+ entry = bnxt_re_mmap_entry_insert(uctx, 0, BNXT_RE_MMAP_SH_PAGE, NULL);
+ if (!entry) {
+ rc = -ENOMEM;
+ goto cfail;
+ }
+ uctx->shpage_mmap = &entry->rdma_entry;
+
rc = ib_copy_to_udata(udata, &resp, min(udata->outlen, sizeof(resp)));
if (rc) {
ibdev_err(ibdev, "Failed to copy user context");
@@ -4016,6 +4099,8 @@ void bnxt_re_dealloc_ucontext(struct ib_ucontext *ib_uctx)
struct bnxt_re_dev *rdev = uctx->rdev;
+ rdma_user_mmap_entry_remove(uctx->shpage_mmap);
+ uctx->shpage_mmap = NULL;
if (uctx->shpg)
free_page((unsigned long)uctx->shpg);
@@ -4023,8 +4108,7 @@ void bnxt_re_dealloc_ucontext(struct ib_ucontext *ib_uctx)
/* Free DPI only if this is the first PD allocated by the
* application and mark the context dpi as NULL
*/
- bnxt_qplib_dealloc_dpi(&rdev->qplib_res,
- &rdev->qplib_res.dpi_tbl, &uctx->dpi);
+ bnxt_qplib_dealloc_dpi(&rdev->qplib_res, &uctx->dpi);
uctx->dpi.dbr = NULL;
}
}
@@ -4035,27 +4119,177 @@ int bnxt_re_mmap(struct ib_ucontext *ib_uctx, struct vm_area_struct *vma)
struct bnxt_re_ucontext *uctx = container_of(ib_uctx,
struct bnxt_re_ucontext,
ib_uctx);
- struct bnxt_re_dev *rdev = uctx->rdev;
+ struct bnxt_re_user_mmap_entry *bnxt_entry;
+ struct rdma_user_mmap_entry *rdma_entry;
+ int ret = 0;
u64 pfn;
- if (vma->vm_end - vma->vm_start != PAGE_SIZE)
+ rdma_entry = rdma_user_mmap_entry_get(&uctx->ib_uctx, vma);
+ if (!rdma_entry)
return -EINVAL;
- if (vma->vm_pgoff) {
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- PAGE_SIZE, vma->vm_page_prot)) {
- ibdev_err(&rdev->ibdev, "Failed to map DPI");
- return -EAGAIN;
- }
- } else {
- pfn = virt_to_phys(uctx->shpg) >> PAGE_SHIFT;
- if (remap_pfn_range(vma, vma->vm_start,
- pfn, PAGE_SIZE, vma->vm_page_prot)) {
- ibdev_err(&rdev->ibdev, "Failed to map shared page");
- return -EAGAIN;
+ bnxt_entry = container_of(rdma_entry, struct bnxt_re_user_mmap_entry,
+ rdma_entry);
+
+ switch (bnxt_entry->mmap_flag) {
+ case BNXT_RE_MMAP_WC_DB:
+ pfn = bnxt_entry->mem_offset >> PAGE_SHIFT;
+ ret = rdma_user_mmap_io(ib_uctx, vma, pfn, PAGE_SIZE,
+ pgprot_writecombine(vma->vm_page_prot),
+ rdma_entry);
+ break;
+ case BNXT_RE_MMAP_UC_DB:
+ pfn = bnxt_entry->mem_offset >> PAGE_SHIFT;
+ ret = rdma_user_mmap_io(ib_uctx, vma, pfn, PAGE_SIZE,
+ pgprot_noncached(vma->vm_page_prot),
+ rdma_entry);
+ break;
+ case BNXT_RE_MMAP_SH_PAGE:
+ ret = vm_insert_page(vma, vma->vm_start, virt_to_page(uctx->shpg));
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ rdma_user_mmap_entry_put(rdma_entry);
+ return ret;
+}
+
+void bnxt_re_mmap_free(struct rdma_user_mmap_entry *rdma_entry)
+{
+ struct bnxt_re_user_mmap_entry *bnxt_entry;
+
+ bnxt_entry = container_of(rdma_entry, struct bnxt_re_user_mmap_entry,
+ rdma_entry);
+
+ kfree(bnxt_entry);
+}
+
+static int UVERBS_HANDLER(BNXT_RE_METHOD_ALLOC_PAGE)(struct uverbs_attr_bundle *attrs)
+{
+ struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, BNXT_RE_ALLOC_PAGE_HANDLE);
+ enum bnxt_re_alloc_page_type alloc_type;
+ struct bnxt_re_user_mmap_entry *entry;
+ enum bnxt_re_mmap_flag mmap_flag;
+ struct bnxt_qplib_chip_ctx *cctx;
+ struct bnxt_re_ucontext *uctx;
+ struct bnxt_re_dev *rdev;
+ u64 mmap_offset;
+ u32 length;
+ u32 dpi;
+ u64 dbr;
+ int err;
+
+ uctx = container_of(ib_uverbs_get_ucontext(attrs), struct bnxt_re_ucontext, ib_uctx);
+ if (IS_ERR(uctx))
+ return PTR_ERR(uctx);
+
+ err = uverbs_get_const(&alloc_type, attrs, BNXT_RE_ALLOC_PAGE_TYPE);
+ if (err)
+ return err;
+
+ rdev = uctx->rdev;
+ cctx = rdev->chip_ctx;
+
+ switch (alloc_type) {
+ case BNXT_RE_ALLOC_WC_PAGE:
+ if (cctx->modes.db_push) {
+ if (bnxt_qplib_alloc_dpi(&rdev->qplib_res, &uctx->wcdpi,
+ uctx, BNXT_QPLIB_DPI_TYPE_WC))
+ return -ENOMEM;
+ length = PAGE_SIZE;
+ dpi = uctx->wcdpi.dpi;
+ dbr = (u64)uctx->wcdpi.umdbr;
+ mmap_flag = BNXT_RE_MMAP_WC_DB;
+ } else {
+ return -EINVAL;
}
+
+ break;
+
+ default:
+ return -EOPNOTSUPP;
}
+ entry = bnxt_re_mmap_entry_insert(uctx, dbr, mmap_flag, &mmap_offset);
+ if (!entry)
+ return -ENOMEM;
+
+ uobj->object = entry;
+ uverbs_finalize_uobj_create(attrs, BNXT_RE_ALLOC_PAGE_HANDLE);
+ err = uverbs_copy_to(attrs, BNXT_RE_ALLOC_PAGE_MMAP_OFFSET,
+ &mmap_offset, sizeof(mmap_offset));
+ if (err)
+ return err;
+
+ err = uverbs_copy_to(attrs, BNXT_RE_ALLOC_PAGE_MMAP_LENGTH,
+ &length, sizeof(length));
+ if (err)
+ return err;
+
+ err = uverbs_copy_to(attrs, BNXT_RE_ALLOC_PAGE_DPI,
+ &dpi, sizeof(length));
+ if (err)
+ return err;
+
return 0;
}
+
+static int alloc_page_obj_cleanup(struct ib_uobject *uobject,
+ enum rdma_remove_reason why,
+ struct uverbs_attr_bundle *attrs)
+{
+ struct bnxt_re_user_mmap_entry *entry = uobject->object;
+ struct bnxt_re_ucontext *uctx = entry->uctx;
+
+ switch (entry->mmap_flag) {
+ case BNXT_RE_MMAP_WC_DB:
+ if (uctx && uctx->wcdpi.dbr) {
+ struct bnxt_re_dev *rdev = uctx->rdev;
+
+ bnxt_qplib_dealloc_dpi(&rdev->qplib_res, &uctx->wcdpi);
+ uctx->wcdpi.dbr = NULL;
+ }
+ break;
+ default:
+ goto exit;
+ }
+ rdma_user_mmap_entry_remove(&entry->rdma_entry);
+exit:
+ return 0;
+}
+
+DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_ALLOC_PAGE,
+ UVERBS_ATTR_IDR(BNXT_RE_ALLOC_PAGE_HANDLE,
+ BNXT_RE_OBJECT_ALLOC_PAGE,
+ UVERBS_ACCESS_NEW,
+ UA_MANDATORY),
+ UVERBS_ATTR_CONST_IN(BNXT_RE_ALLOC_PAGE_TYPE,
+ enum bnxt_re_alloc_page_type,
+ UA_MANDATORY),
+ UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_PAGE_MMAP_OFFSET,
+ UVERBS_ATTR_TYPE(u64),
+ UA_MANDATORY),
+ UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_PAGE_MMAP_LENGTH,
+ UVERBS_ATTR_TYPE(u32),
+ UA_MANDATORY),
+ UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_PAGE_DPI,
+ UVERBS_ATTR_TYPE(u32),
+ UA_MANDATORY));
+
+DECLARE_UVERBS_NAMED_METHOD_DESTROY(BNXT_RE_METHOD_DESTROY_PAGE,
+ UVERBS_ATTR_IDR(BNXT_RE_DESTROY_PAGE_HANDLE,
+ BNXT_RE_OBJECT_ALLOC_PAGE,
+ UVERBS_ACCESS_DESTROY,
+ UA_MANDATORY));
+
+DECLARE_UVERBS_NAMED_OBJECT(BNXT_RE_OBJECT_ALLOC_PAGE,
+ UVERBS_TYPE_ALLOC_IDR(alloc_page_obj_cleanup),
+ &UVERBS_METHOD(BNXT_RE_METHOD_ALLOC_PAGE),
+ &UVERBS_METHOD(BNXT_RE_METHOD_DESTROY_PAGE));
+
+const struct uapi_definition bnxt_re_uapi_defs[] = {
+ UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_ALLOC_PAGE),
+ {}
+};
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
index 31f7e34040f7..32d9e9d09791 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
@@ -60,6 +60,8 @@ struct bnxt_re_pd {
struct bnxt_re_dev *rdev;
struct bnxt_qplib_pd qplib_pd;
struct bnxt_re_fence_data fence;
+ struct rdma_user_mmap_entry *pd_db_mmap;
+ struct rdma_user_mmap_entry *pd_wcdb_mmap;
};
struct bnxt_re_ah {
@@ -134,8 +136,23 @@ struct bnxt_re_ucontext {
struct ib_ucontext ib_uctx;
struct bnxt_re_dev *rdev;
struct bnxt_qplib_dpi dpi;
+ struct bnxt_qplib_dpi wcdpi;
void *shpg;
spinlock_t sh_lock; /* protect shpg */
+ struct rdma_user_mmap_entry *shpage_mmap;
+};
+
+enum bnxt_re_mmap_flag {
+ BNXT_RE_MMAP_SH_PAGE,
+ BNXT_RE_MMAP_UC_DB,
+ BNXT_RE_MMAP_WC_DB,
+};
+
+struct bnxt_re_user_mmap_entry {
+ struct rdma_user_mmap_entry rdma_entry;
+ struct bnxt_re_ucontext *uctx;
+ u64 mem_offset;
+ u8 mmap_flag;
};
static inline u16 bnxt_re_get_swqe_size(int nsge)
@@ -213,6 +230,8 @@ struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata);
void bnxt_re_dealloc_ucontext(struct ib_ucontext *context);
int bnxt_re_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
+void bnxt_re_mmap_free(struct rdma_user_mmap_entry *rdma_entry);
+
unsigned long bnxt_re_lock_cqs(struct bnxt_re_qp *qp);
void bnxt_re_unlock_cqs(struct bnxt_re_qp *qp, unsigned long flags);
diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
index 3073398a2183..b42166fe7454 100644
--- a/drivers/infiniband/hw/bnxt_re/main.c
+++ b/drivers/infiniband/hw/bnxt_re/main.c
@@ -83,6 +83,45 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier,
unsigned long event, void *ptr);
static struct bnxt_re_dev *bnxt_re_from_netdev(struct net_device *netdev);
static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev);
+static int bnxt_re_hwrm_qcaps(struct bnxt_re_dev *rdev);
+
+static int bnxt_re_hwrm_qcfg(struct bnxt_re_dev *rdev, u32 *db_len,
+ u32 *offset);
+static void bnxt_re_set_db_offset(struct bnxt_re_dev *rdev)
+{
+ struct bnxt_qplib_chip_ctx *cctx;
+ struct bnxt_en_dev *en_dev;
+ struct bnxt_qplib_res *res;
+ u32 l2db_len = 0;
+ u32 offset = 0;
+ u32 barlen;
+ int rc;
+
+ res = &rdev->qplib_res;
+ en_dev = rdev->en_dev;
+ cctx = rdev->chip_ctx;
+
+ /* Issue qcfg */
+ rc = bnxt_re_hwrm_qcfg(rdev, &l2db_len, &offset);
+ if (rc)
+ dev_info(rdev_to_dev(rdev),
+ "Couldn't get DB bar size, Low latency framework is disabled\n");
+ /* set register offsets for both UC and WC */
+ res->dpi_tbl.ucreg.offset = res->is_vf ? BNXT_QPLIB_DBR_VF_DB_OFFSET :
+ BNXT_QPLIB_DBR_PF_DB_OFFSET;
+ res->dpi_tbl.wcreg.offset = res->dpi_tbl.ucreg.offset;
+
+ /* If WC mapping is disabled by L2 driver then en_dev->l2_db_size
+ * is equal to the DB-Bar actual size. This indicates that L2
+ * is mapping entire bar as UC-. RoCE driver can't enable WC mapping
+ * in such cases and DB-push will be disabled.
+ */
+ barlen = pci_resource_len(res->pdev, RCFW_DBR_PCI_BAR_REGION);
+ if (cctx->modes.db_push && l2db_len && en_dev->l2_db_size != barlen) {
+ res->dpi_tbl.wcreg.offset = en_dev->l2_db_size;
+ dev_info(rdev_to_dev(rdev), "Low latency framework is enabled\n");
+ }
+}
static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev, u8 mode)
{
@@ -91,6 +130,9 @@ static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev, u8 mode)
cctx = rdev->chip_ctx;
cctx->modes.wqe_mode = bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx) ?
mode : BNXT_QPLIB_WQE_MODE_STATIC;
+ if (bnxt_re_hwrm_qcaps(rdev))
+ dev_err(rdev_to_dev(rdev),
+ "Failed to query hwrm qcaps\n");
}
static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev)
@@ -112,6 +154,7 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode)
{
struct bnxt_qplib_chip_ctx *chip_ctx;
struct bnxt_en_dev *en_dev;
+ int rc;
en_dev = rdev->en_dev;
@@ -130,6 +173,12 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode)
rdev->qplib_res.is_vf = BNXT_EN_VF(en_dev);
bnxt_re_set_drv_mode(rdev, wqe_mode);
+
+ bnxt_re_set_db_offset(rdev);
+ rc = bnxt_qplib_map_db_bar(&rdev->qplib_res);
+ if (rc)
+ return rc;
+
if (bnxt_qplib_determine_atomics(en_dev->pdev))
ibdev_info(&rdev->ibdev,
"platform doesn't support global atomics.");
@@ -283,15 +332,21 @@ static void bnxt_re_start_irq(void *handle, struct bnxt_msix_entry *ent)
for (indx = 0; indx < rdev->num_msix; indx++)
rdev->en_dev->msix_entries[indx].vector = ent[indx].vector;
- bnxt_qplib_rcfw_start_irq(rcfw, msix_ent[BNXT_RE_AEQ_IDX].vector,
- false);
+ rc = bnxt_qplib_rcfw_start_irq(rcfw, msix_ent[BNXT_RE_AEQ_IDX].vector,
+ false);
+ if (rc) {
+ ibdev_warn(&rdev->ibdev, "Failed to reinit CREQ\n");
+ return;
+ }
for (indx = BNXT_RE_NQ_IDX ; indx < rdev->num_msix; indx++) {
nq = &rdev->nq[indx - 1];
rc = bnxt_qplib_nq_start_irq(nq, indx - 1,
msix_ent[indx].vector, false);
- if (rc)
+ if (rc) {
ibdev_warn(&rdev->ibdev, "Failed to reinit NQ index %d\n",
indx - 1);
+ return;
+ }
}
}
@@ -315,12 +370,11 @@ static int bnxt_re_register_netdev(struct bnxt_re_dev *rdev)
return rc;
}
-static void bnxt_re_init_hwrm_hdr(struct bnxt_re_dev *rdev, struct input *hdr,
- u16 opcd, u16 crid, u16 trid)
+static void bnxt_re_init_hwrm_hdr(struct input *hdr, u16 opcd)
{
hdr->req_type = cpu_to_le16(opcd);
- hdr->cmpl_ring = cpu_to_le16(crid);
- hdr->target_id = cpu_to_le16(trid);
+ hdr->cmpl_ring = cpu_to_le16(-1);
+ hdr->target_id = cpu_to_le16(-1);
}
static void bnxt_re_fill_fw_msg(struct bnxt_fw_msg *fw_msg, void *msg,
@@ -334,13 +388,60 @@ static void bnxt_re_fill_fw_msg(struct bnxt_fw_msg *fw_msg, void *msg,
fw_msg->timeout = timeout;
}
+/* Query device config using common hwrm */
+static int bnxt_re_hwrm_qcfg(struct bnxt_re_dev *rdev, u32 *db_len,
+ u32 *offset)
+{
+ struct bnxt_en_dev *en_dev = rdev->en_dev;
+ struct hwrm_func_qcfg_output resp = {0};
+ struct hwrm_func_qcfg_input req = {0};
+ struct bnxt_fw_msg fw_msg;
+ int rc;
+
+ memset(&fw_msg, 0, sizeof(fw_msg));
+ bnxt_re_init_hwrm_hdr((void *)&req, HWRM_FUNC_QCFG);
+ req.fid = cpu_to_le16(0xffff);
+ bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
+ sizeof(resp), DFLT_HWRM_CMD_TIMEOUT);
+ rc = bnxt_send_msg(en_dev, &fw_msg);
+ if (!rc) {
+ *db_len = PAGE_ALIGN(le16_to_cpu(resp.l2_doorbell_bar_size_kb) * 1024);
+ *offset = PAGE_ALIGN(le16_to_cpu(resp.legacy_l2_db_size_kb) * 1024);
+ }
+ return rc;
+}
+
+/* Query function capabilities using common hwrm */
+int bnxt_re_hwrm_qcaps(struct bnxt_re_dev *rdev)
+{
+ struct bnxt_en_dev *en_dev = rdev->en_dev;
+ struct hwrm_func_qcaps_output resp = {};
+ struct hwrm_func_qcaps_input req = {};
+ struct bnxt_qplib_chip_ctx *cctx;
+ struct bnxt_fw_msg fw_msg = {};
+ int rc;
+
+ cctx = rdev->chip_ctx;
+ bnxt_re_init_hwrm_hdr((void *)&req, HWRM_FUNC_QCAPS);
+ req.fid = cpu_to_le16(0xffff);
+ bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
+ sizeof(resp), DFLT_HWRM_CMD_TIMEOUT);
+
+ rc = bnxt_send_msg(en_dev, &fw_msg);
+ if (rc)
+ return rc;
+ cctx->modes.db_push = le32_to_cpu(resp.flags) & FUNC_QCAPS_RESP_FLAGS_WCB_PUSH_MODE;
+
+ return 0;
+}
+
static int bnxt_re_net_ring_free(struct bnxt_re_dev *rdev,
u16 fw_ring_id, int type)
{
struct bnxt_en_dev *en_dev;
- struct hwrm_ring_free_input req = {0};
+ struct hwrm_ring_free_input req = {};
struct hwrm_ring_free_output resp;
- struct bnxt_fw_msg fw_msg;
+ struct bnxt_fw_msg fw_msg = {};
int rc = -EINVAL;
if (!rdev)
@@ -354,9 +455,7 @@ static int bnxt_re_net_ring_free(struct bnxt_re_dev *rdev,
if (test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags))
return 0;
- memset(&fw_msg, 0, sizeof(fw_msg));
-
- bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_RING_FREE, -1, -1);
+ bnxt_re_init_hwrm_hdr((void *)&req, HWRM_RING_FREE);
req.ring_type = type;
req.ring_id = cpu_to_le16(fw_ring_id);
bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
@@ -373,16 +472,15 @@ static int bnxt_re_net_ring_alloc(struct bnxt_re_dev *rdev,
u16 *fw_ring_id)
{
struct bnxt_en_dev *en_dev = rdev->en_dev;
- struct hwrm_ring_alloc_input req = {0};
+ struct hwrm_ring_alloc_input req = {};
struct hwrm_ring_alloc_output resp;
- struct bnxt_fw_msg fw_msg;
+ struct bnxt_fw_msg fw_msg = {};
int rc = -EINVAL;
if (!en_dev)
return rc;
- memset(&fw_msg, 0, sizeof(fw_msg));
- bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_RING_ALLOC, -1, -1);
+ bnxt_re_init_hwrm_hdr((void *)&req, HWRM_RING_ALLOC);
req.enables = 0;
req.page_tbl_addr = cpu_to_le64(ring_attr->dma_arr[0]);
if (ring_attr->pages > 1) {
@@ -411,7 +509,7 @@ static int bnxt_re_net_stats_ctx_free(struct bnxt_re_dev *rdev,
struct bnxt_en_dev *en_dev = rdev->en_dev;
struct hwrm_stat_ctx_free_input req = {};
struct hwrm_stat_ctx_free_output resp = {};
- struct bnxt_fw_msg fw_msg;
+ struct bnxt_fw_msg fw_msg = {};
int rc = -EINVAL;
if (!en_dev)
@@ -420,9 +518,7 @@ static int bnxt_re_net_stats_ctx_free(struct bnxt_re_dev *rdev,
if (test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags))
return 0;
- memset(&fw_msg, 0, sizeof(fw_msg));
-
- bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_STAT_CTX_FREE, -1, -1);
+ bnxt_re_init_hwrm_hdr((void *)&req, HWRM_STAT_CTX_FREE);
req.stat_ctx_id = cpu_to_le32(fw_stats_ctx_id);
bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
sizeof(resp), DFLT_HWRM_CMD_TIMEOUT);
@@ -439,10 +535,10 @@ static int bnxt_re_net_stats_ctx_alloc(struct bnxt_re_dev *rdev,
u32 *fw_stats_ctx_id)
{
struct bnxt_qplib_chip_ctx *chip_ctx = rdev->chip_ctx;
- struct hwrm_stat_ctx_alloc_output resp = {0};
- struct hwrm_stat_ctx_alloc_input req = {0};
+ struct hwrm_stat_ctx_alloc_output resp = {};
+ struct hwrm_stat_ctx_alloc_input req = {};
struct bnxt_en_dev *en_dev = rdev->en_dev;
- struct bnxt_fw_msg fw_msg;
+ struct bnxt_fw_msg fw_msg = {};
int rc = -EINVAL;
*fw_stats_ctx_id = INVALID_STATS_CTX_ID;
@@ -450,9 +546,7 @@ static int bnxt_re_net_stats_ctx_alloc(struct bnxt_re_dev *rdev,
if (!en_dev)
return rc;
- memset(&fw_msg, 0, sizeof(fw_msg));
-
- bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_STAT_CTX_ALLOC, -1, -1);
+ bnxt_re_init_hwrm_hdr((void *)&req, HWRM_STAT_CTX_ALLOC);
req.update_period_ms = cpu_to_le32(1000);
req.stats_dma_addr = cpu_to_le64(dma_map);
req.stats_dma_length = cpu_to_le16(chip_ctx->hw_stats_size);
@@ -466,6 +560,10 @@ static int bnxt_re_net_stats_ctx_alloc(struct bnxt_re_dev *rdev,
return rc;
}
+static void bnxt_re_disassociate_ucontext(struct ib_ucontext *ibcontext)
+{
+}
+
/* Device */
static struct bnxt_re_dev *bnxt_re_from_netdev(struct net_device *netdev)
@@ -532,6 +630,7 @@ static const struct ib_device_ops bnxt_re_dev_ops = {
.destroy_qp = bnxt_re_destroy_qp,
.destroy_srq = bnxt_re_destroy_srq,
.device_group = &bnxt_re_dev_attr_group,
+ .disassociate_ucontext = bnxt_re_disassociate_ucontext,
.get_dev_fw_str = bnxt_re_query_fw_str,
.get_dma_mr = bnxt_re_get_dma_mr,
.get_hw_stats = bnxt_re_ib_get_hw_stats,
@@ -539,6 +638,7 @@ static const struct ib_device_ops bnxt_re_dev_ops = {
.get_port_immutable = bnxt_re_get_port_immutable,
.map_mr_sg = bnxt_re_map_mr_sg,
.mmap = bnxt_re_mmap,
+ .mmap_free = bnxt_re_mmap_free,
.modify_qp = bnxt_re_modify_qp,
.modify_srq = bnxt_re_modify_srq,
.poll_cq = bnxt_re_poll_cq,
@@ -579,6 +679,9 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev)
ibdev->dev.parent = &rdev->en_dev->pdev->dev;
ibdev->local_dma_lkey = BNXT_QPLIB_RSVD_LKEY;
+ if (IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS))
+ ibdev->driver_def = bnxt_re_uapi_defs;
+
ib_set_device_ops(ibdev, &bnxt_re_dev_ops);
ret = ib_device_set_netdev(&rdev->ibdev, rdev->netdev, 1);
if (ret)
@@ -822,7 +925,6 @@ static void bnxt_re_free_res(struct bnxt_re_dev *rdev)
if (rdev->qplib_res.dpi_tbl.max) {
bnxt_qplib_dealloc_dpi(&rdev->qplib_res,
- &rdev->qplib_res.dpi_tbl,
&rdev->dpi_privileged);
}
if (rdev->qplib_res.rcfw) {
@@ -850,9 +952,9 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
if (rc)
goto fail;
- rc = bnxt_qplib_alloc_dpi(&rdev->qplib_res.dpi_tbl,
+ rc = bnxt_qplib_alloc_dpi(&rdev->qplib_res,
&rdev->dpi_privileged,
- rdev);
+ rdev, BNXT_QPLIB_DPI_TYPE_KERNEL);
if (rc)
goto dealloc_res;
@@ -892,7 +994,6 @@ free_nq:
bnxt_qplib_free_nq(&rdev->nq[i]);
}
bnxt_qplib_dealloc_dpi(&rdev->qplib_res,
- &rdev->qplib_res.dpi_tbl,
&rdev->dpi_privileged);
dealloc_res:
bnxt_qplib_free_res(&rdev->qplib_res);
@@ -963,12 +1064,6 @@ static int bnxt_re_update_gid(struct bnxt_re_dev *rdev)
if (!ib_device_try_get(&rdev->ibdev))
return 0;
- if (!sgid_tbl) {
- ibdev_err(&rdev->ibdev, "QPLIB: SGID table not allocated");
- rc = -EINVAL;
- goto out;
- }
-
for (index = 0; index < sgid_tbl->active; index++) {
gid_idx = sgid_tbl->hw_id[index];
@@ -986,7 +1081,7 @@ static int bnxt_re_update_gid(struct bnxt_re_dev *rdev)
rc = bnxt_qplib_update_sgid(sgid_tbl, &gid, gid_idx,
rdev->qplib_res.netdev->dev_addr);
}
-out:
+
ib_device_put(&rdev->ibdev);
return rc;
}
@@ -1039,14 +1134,13 @@ static int bnxt_re_setup_qos(struct bnxt_re_dev *rdev)
static void bnxt_re_query_hwrm_intf_version(struct bnxt_re_dev *rdev)
{
struct bnxt_en_dev *en_dev = rdev->en_dev;
- struct hwrm_ver_get_output resp = {0};
- struct hwrm_ver_get_input req = {0};
- struct bnxt_fw_msg fw_msg;
+ struct hwrm_ver_get_output resp = {};
+ struct hwrm_ver_get_input req = {};
+ struct bnxt_qplib_chip_ctx *cctx;
+ struct bnxt_fw_msg fw_msg = {};
int rc = 0;
- memset(&fw_msg, 0, sizeof(fw_msg));
- bnxt_re_init_hwrm_hdr(rdev, (void *)&req,
- HWRM_VER_GET, -1, -1);
+ bnxt_re_init_hwrm_hdr((void *)&req, HWRM_VER_GET);
req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
req.hwrm_intf_min = HWRM_VERSION_MINOR;
req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
@@ -1058,11 +1152,18 @@ static void bnxt_re_query_hwrm_intf_version(struct bnxt_re_dev *rdev)
rc);
return;
}
- rdev->qplib_ctx.hwrm_intf_ver =
+
+ cctx = rdev->chip_ctx;
+ cctx->hwrm_intf_ver =
(u64)le16_to_cpu(resp.hwrm_intf_major) << 48 |
(u64)le16_to_cpu(resp.hwrm_intf_minor) << 32 |
(u64)le16_to_cpu(resp.hwrm_intf_build) << 16 |
le16_to_cpu(resp.hwrm_intf_patch);
+
+ cctx->hwrm_cmd_max_timeout = le16_to_cpu(resp.max_req_timeout);
+
+ if (!cctx->hwrm_cmd_max_timeout)
+ cctx->hwrm_cmd_max_timeout = RCFW_FW_STALL_MAX_TIMEOUT;
}
static int bnxt_re_ib_init(struct bnxt_re_dev *rdev)
@@ -1200,7 +1301,7 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode)
db_offt = bnxt_re_get_nqdb_offset(rdev, BNXT_RE_AEQ_IDX);
vid = rdev->en_dev->msix_entries[BNXT_RE_AEQ_IDX].vector;
rc = bnxt_qplib_enable_rcfw_channel(&rdev->rcfw,
- vid, db_offt, rdev->is_virtfn,
+ vid, db_offt,
&bnxt_re_aeq_handler);
if (rc) {
ibdev_err(&rdev->ibdev, "Failed to enable RCFW channel: %#x\n",
@@ -1497,6 +1598,7 @@ static int bnxt_re_suspend(struct auxiliary_device *adev, pm_message_t state)
*/
set_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags);
set_bit(ERR_DEVICE_DETACHED, &rdev->rcfw.cmdq.flags);
+ wake_up_all(&rdev->rcfw.cmdq.waitq);
mutex_unlock(&bnxt_re_mutex);
return 0;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
index 8974f6235cfa..91aed77ce40d 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
@@ -399,6 +399,9 @@ static irqreturn_t bnxt_qplib_nq_irq(int irq, void *dev_instance)
void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill)
{
+ if (!nq->requested)
+ return;
+
tasklet_disable(&nq->nq_tasklet);
/* Mask h/w interrupt */
bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, nq->res->cctx, false);
@@ -406,11 +409,12 @@ void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill)
synchronize_irq(nq->msix_vec);
if (kill)
tasklet_kill(&nq->nq_tasklet);
- if (nq->requested) {
- irq_set_affinity_hint(nq->msix_vec, NULL);
- free_irq(nq->msix_vec, nq);
- nq->requested = false;
- }
+
+ irq_set_affinity_hint(nq->msix_vec, NULL);
+ free_irq(nq->msix_vec, nq);
+ kfree(nq->name);
+ nq->name = NULL;
+ nq->requested = false;
}
void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq)
@@ -436,6 +440,7 @@ void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq)
int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx,
int msix_vector, bool need_init)
{
+ struct bnxt_qplib_res *res = nq->res;
int rc;
if (nq->requested)
@@ -447,10 +452,17 @@ int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx,
else
tasklet_enable(&nq->nq_tasklet);
- snprintf(nq->name, sizeof(nq->name), "bnxt_qplib_nq-%d", nq_indx);
+ nq->name = kasprintf(GFP_KERNEL, "bnxt_re-nq-%d@pci:%s",
+ nq_indx, pci_name(res->pdev));
+ if (!nq->name)
+ return -ENOMEM;
rc = request_irq(nq->msix_vec, bnxt_qplib_nq_irq, 0, nq->name, nq);
- if (rc)
+ if (rc) {
+ kfree(nq->name);
+ nq->name = NULL;
+ tasklet_disable(&nq->nq_tasklet);
return rc;
+ }
cpumask_clear(&nq->mask);
cpumask_set_cpu(nq_indx, &nq->mask);
@@ -461,7 +473,7 @@ int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx,
nq->msix_vec, nq_indx);
}
nq->requested = true;
- bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, nq->res->cctx, true);
+ bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, res->cctx, true);
return rc;
}
@@ -471,7 +483,6 @@ static int bnxt_qplib_map_nq_db(struct bnxt_qplib_nq *nq, u32 reg_offt)
resource_size_t reg_base;
struct bnxt_qplib_nq_db *nq_db;
struct pci_dev *pdev;
- int rc = 0;
pdev = nq->pdev;
nq_db = &nq->nq_db;
@@ -481,8 +492,7 @@ static int bnxt_qplib_map_nq_db(struct bnxt_qplib_nq *nq, u32 reg_offt)
if (!nq_db->reg.bar_base) {
dev_err(&pdev->dev, "QPLIB: NQ BAR region %d resc start is 0!",
nq_db->reg.bar_id);
- rc = -ENOMEM;
- goto fail;
+ return -ENOMEM;
}
reg_base = nq_db->reg.bar_base + reg_offt;
@@ -492,15 +502,14 @@ static int bnxt_qplib_map_nq_db(struct bnxt_qplib_nq *nq, u32 reg_offt)
if (!nq_db->reg.bar_reg) {
dev_err(&pdev->dev, "QPLIB: NQ BAR region %d mapping failed",
nq_db->reg.bar_id);
- rc = -ENOMEM;
- goto fail;
+ return -ENOMEM;
}
nq_db->dbinfo.db = nq_db->reg.bar_reg;
nq_db->dbinfo.hwq = &nq->hwq;
nq_db->dbinfo.xid = nq->ring_id;
-fail:
- return rc;
+
+ return 0;
}
int bnxt_qplib_enable_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq,
@@ -614,7 +623,7 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res,
hwq_attr.type = HWQ_TYPE_QUEUE;
rc = bnxt_qplib_alloc_init_hwq(&srq->hwq, &hwq_attr);
if (rc)
- goto exit;
+ return rc;
srq->swq = kcalloc(srq->hwq.max_elements, sizeof(*srq->swq),
GFP_KERNEL);
@@ -659,7 +668,7 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res,
srq->dbinfo.xid = srq->id;
srq->dbinfo.db = srq->dpi->dbr;
srq->dbinfo.max_slot = 1;
- srq->dbinfo.priv_db = res->dpi_tbl.dbr_bar_reg_iomem;
+ srq->dbinfo.priv_db = res->dpi_tbl.priv_db;
if (srq->threshold)
bnxt_qplib_armen_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ_ARMENA);
srq->arm_req = false;
@@ -668,7 +677,7 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res,
fail:
bnxt_qplib_free_hwq(res, &srq->hwq);
kfree(srq->swq);
-exit:
+
return rc;
}
@@ -732,15 +741,14 @@ int bnxt_qplib_post_srq_recv(struct bnxt_qplib_srq *srq,
struct rq_wqe *srqe;
struct sq_sge *hw_sge;
u32 sw_prod, sw_cons, count = 0;
- int i, rc = 0, next;
+ int i, next;
spin_lock(&srq_hwq->lock);
if (srq->start_idx == srq->last_idx) {
dev_err(&srq_hwq->pdev->dev,
"FP: SRQ (0x%x) is full!\n", srq->id);
- rc = -EINVAL;
spin_unlock(&srq_hwq->lock);
- goto done;
+ return -EINVAL;
}
next = srq->start_idx;
srq->start_idx = srq->swq[next].next_idx;
@@ -781,22 +789,19 @@ int bnxt_qplib_post_srq_recv(struct bnxt_qplib_srq *srq,
srq->arm_req = false;
bnxt_qplib_srq_arm_db(&srq->dbinfo, srq->threshold);
}
-done:
- return rc;
+
+ return 0;
}
/* QP */
static int bnxt_qplib_alloc_init_swq(struct bnxt_qplib_q *que)
{
- int rc = 0;
int indx;
que->swq = kcalloc(que->max_wqe, sizeof(*que->swq), GFP_KERNEL);
- if (!que->swq) {
- rc = -ENOMEM;
- goto out;
- }
+ if (!que->swq)
+ return -ENOMEM;
que->swq_start = 0;
que->swq_last = que->max_wqe - 1;
@@ -804,8 +809,8 @@ static int bnxt_qplib_alloc_init_swq(struct bnxt_qplib_q *que)
que->swq[indx].next_idx = indx + 1;
que->swq[que->swq_last].next_idx = 0; /* Make it circular */
que->swq_last = 0;
-out:
- return rc;
+
+ return 0;
}
int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
@@ -839,7 +844,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
hwq_attr.type = HWQ_TYPE_QUEUE;
rc = bnxt_qplib_alloc_init_hwq(&sq->hwq, &hwq_attr);
if (rc)
- goto exit;
+ return rc;
rc = bnxt_qplib_alloc_init_swq(sq);
if (rc)
@@ -927,7 +932,6 @@ sq_swq:
kfree(sq->swq);
fail_sq:
bnxt_qplib_free_hwq(res, &sq->hwq);
-exit:
return rc;
}
@@ -992,7 +996,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
hwq_attr.type = HWQ_TYPE_QUEUE;
rc = bnxt_qplib_alloc_init_hwq(&sq->hwq, &hwq_attr);
if (rc)
- goto exit;
+ return rc;
rc = bnxt_qplib_alloc_init_swq(sq);
if (rc)
@@ -1140,7 +1144,6 @@ sq_swq:
kfree(sq->swq);
fail_sq:
bnxt_qplib_free_hwq(res, &sq->hwq);
-exit:
return rc;
}
@@ -1614,7 +1617,7 @@ static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp,
il_src = (void *)wqe->sg_list[indx].addr;
t_len += len;
if (t_len > qp->max_inline_data)
- goto bad;
+ return -ENOMEM;
while (len) {
if (pull_dst) {
pull_dst = false;
@@ -1638,8 +1641,6 @@ static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp,
}
return t_len;
-bad:
- return -ENOMEM;
}
static u32 bnxt_qplib_put_sges(struct bnxt_qplib_hwq *hwq,
@@ -2069,7 +2070,7 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
hwq_attr.sginfo = &cq->sg_info;
rc = bnxt_qplib_alloc_init_hwq(&cq->hwq, &hwq_attr);
if (rc)
- goto exit;
+ return rc;
bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
CMDQ_BASE_OPCODE_CREATE_CQ,
@@ -2104,7 +2105,7 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
cq->dbinfo.hwq = &cq->hwq;
cq->dbinfo.xid = cq->id;
cq->dbinfo.db = cq->dpi->dbr;
- cq->dbinfo.priv_db = res->dpi_tbl.dbr_bar_reg_iomem;
+ cq->dbinfo.priv_db = res->dpi_tbl.priv_db;
bnxt_qplib_armen_db(&cq->dbinfo, DBC_DBC_TYPE_CQ_ARMENA);
@@ -2112,7 +2113,6 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
fail:
bnxt_qplib_free_hwq(res, &cq->hwq);
-exit:
return rc;
}
@@ -2505,7 +2505,6 @@ static int bnxt_qplib_cq_process_res_rc(struct bnxt_qplib_cq *cq,
struct bnxt_qplib_qp *qp;
struct bnxt_qplib_q *rq;
u32 wr_id_idx;
- int rc = 0;
qp = (struct bnxt_qplib_qp *)((unsigned long)
le64_to_cpu(hwcqe->qp_handle));
@@ -2516,7 +2515,7 @@ static int bnxt_qplib_cq_process_res_rc(struct bnxt_qplib_cq *cq,
if (qp->rq.flushed) {
dev_dbg(&cq->hwq.pdev->dev,
"%s: QP in Flush QP = %p\n", __func__, qp);
- goto done;
+ return 0;
}
cqe = *pcqe;
@@ -2572,8 +2571,7 @@ static int bnxt_qplib_cq_process_res_rc(struct bnxt_qplib_cq *cq,
}
}
-done:
- return rc;
+ return 0;
}
static int bnxt_qplib_cq_process_res_ud(struct bnxt_qplib_cq *cq,
@@ -2586,7 +2584,6 @@ static int bnxt_qplib_cq_process_res_ud(struct bnxt_qplib_cq *cq,
struct bnxt_qplib_qp *qp;
struct bnxt_qplib_q *rq;
u32 wr_id_idx;
- int rc = 0;
qp = (struct bnxt_qplib_qp *)((unsigned long)
le64_to_cpu(hwcqe->qp_handle));
@@ -2597,7 +2594,7 @@ static int bnxt_qplib_cq_process_res_ud(struct bnxt_qplib_cq *cq,
if (qp->rq.flushed) {
dev_dbg(&cq->hwq.pdev->dev,
"%s: QP in Flush QP = %p\n", __func__, qp);
- goto done;
+ return 0;
}
cqe = *pcqe;
cqe->opcode = hwcqe->cqe_type_toggle & CQ_BASE_CQE_TYPE_MASK;
@@ -2659,8 +2656,8 @@ static int bnxt_qplib_cq_process_res_ud(struct bnxt_qplib_cq *cq,
bnxt_qplib_add_flush_qp(qp);
}
}
-done:
- return rc;
+
+ return 0;
}
bool bnxt_qplib_is_cq_empty(struct bnxt_qplib_cq *cq)
@@ -2687,7 +2684,6 @@ static int bnxt_qplib_cq_process_res_raweth_qp1(struct bnxt_qplib_cq *cq,
struct bnxt_qplib_srq *srq;
struct bnxt_qplib_cqe *cqe;
u32 wr_id_idx;
- int rc = 0;
qp = (struct bnxt_qplib_qp *)((unsigned long)
le64_to_cpu(hwcqe->qp_handle));
@@ -2698,7 +2694,7 @@ static int bnxt_qplib_cq_process_res_raweth_qp1(struct bnxt_qplib_cq *cq,
if (qp->rq.flushed) {
dev_dbg(&cq->hwq.pdev->dev,
"%s: QP in Flush QP = %p\n", __func__, qp);
- goto done;
+ return 0;
}
cqe = *pcqe;
cqe->opcode = hwcqe->cqe_type_toggle & CQ_BASE_CQE_TYPE_MASK;
@@ -2767,8 +2763,7 @@ static int bnxt_qplib_cq_process_res_raweth_qp1(struct bnxt_qplib_cq *cq,
}
}
-done:
- return rc;
+ return 0;
}
static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq,
@@ -2790,11 +2785,8 @@ static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq,
qp = (struct bnxt_qplib_qp *)((unsigned long)
le64_to_cpu(hwcqe->qp_handle));
- if (!qp) {
- dev_err(&cq->hwq.pdev->dev,
- "FP: CQ Process terminal qp is NULL\n");
+ if (!qp)
return -EINVAL;
- }
/* Must block new posting of SQ and RQ */
qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
index d74d5ead2e32..a42820821c47 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
@@ -472,7 +472,7 @@ typedef int (*srqn_handler_t)(struct bnxt_qplib_nq *nq,
struct bnxt_qplib_nq {
struct pci_dev *pdev;
struct bnxt_qplib_res *res;
- char name[32];
+ char *name;
struct bnxt_qplib_hwq hwq;
struct bnxt_qplib_nq_db nq_db;
u16 ring_id;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
index de9069103177..b30e66b64827 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
@@ -53,112 +53,289 @@
static void bnxt_qplib_service_creq(struct tasklet_struct *t);
-/* Hardware communication channel */
+/**
+ * bnxt_qplib_map_rc - map return type based on opcode
+ * @opcode - roce slow path opcode
+ *
+ * case #1
+ * Firmware initiated error recovery is a safe state machine and
+ * driver can consider all the underlying rdma resources are free.
+ * In this state, it is safe to return success for opcodes related to
+ * destroying rdma resources (like destroy qp, destroy cq etc.).
+ *
+ * case #2
+ * If driver detect potential firmware stall, it is not safe state machine
+ * and the driver can not consider all the underlying rdma resources are
+ * freed.
+ * In this state, it is not safe to return success for opcodes related to
+ * destroying rdma resources (like destroy qp, destroy cq etc.).
+ *
+ * Scope of this helper function is only for case #1.
+ *
+ * Returns:
+ * 0 to communicate success to caller.
+ * Non zero error code to communicate failure to caller.
+ */
+static int bnxt_qplib_map_rc(u8 opcode)
+{
+ switch (opcode) {
+ case CMDQ_BASE_OPCODE_DESTROY_QP:
+ case CMDQ_BASE_OPCODE_DESTROY_SRQ:
+ case CMDQ_BASE_OPCODE_DESTROY_CQ:
+ case CMDQ_BASE_OPCODE_DEALLOCATE_KEY:
+ case CMDQ_BASE_OPCODE_DEREGISTER_MR:
+ case CMDQ_BASE_OPCODE_DELETE_GID:
+ case CMDQ_BASE_OPCODE_DESTROY_QP1:
+ case CMDQ_BASE_OPCODE_DESTROY_AH:
+ case CMDQ_BASE_OPCODE_DEINITIALIZE_FW:
+ case CMDQ_BASE_OPCODE_MODIFY_ROCE_CC:
+ case CMDQ_BASE_OPCODE_SET_LINK_AGGR_MODE:
+ return 0;
+ default:
+ return -ETIMEDOUT;
+ }
+}
+
+/**
+ * bnxt_re_is_fw_stalled - Check firmware health
+ * @rcfw - rcfw channel instance of rdev
+ * @cookie - cookie to track the command
+ *
+ * If firmware has not responded any rcfw command within
+ * rcfw->max_timeout, consider firmware as stalled.
+ *
+ * Returns:
+ * 0 if firmware is responding
+ * -ENODEV if firmware is not responding
+ */
+static int bnxt_re_is_fw_stalled(struct bnxt_qplib_rcfw *rcfw,
+ u16 cookie)
+{
+ struct bnxt_qplib_cmdq_ctx *cmdq;
+ struct bnxt_qplib_crsqe *crsqe;
+
+ crsqe = &rcfw->crsqe_tbl[cookie];
+ cmdq = &rcfw->cmdq;
+
+ if (time_after(jiffies, cmdq->last_seen +
+ (rcfw->max_timeout * HZ))) {
+ dev_warn_ratelimited(&rcfw->pdev->dev,
+ "%s: FW STALL Detected. cmdq[%#x]=%#x waited (%d > %d) msec active %d ",
+ __func__, cookie, crsqe->opcode,
+ jiffies_to_msecs(jiffies - cmdq->last_seen),
+ rcfw->max_timeout * 1000,
+ crsqe->is_in_used);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/**
+ * __wait_for_resp - Don't hold the cpu context and wait for response
+ * @rcfw - rcfw channel instance of rdev
+ * @cookie - cookie to track the command
+ *
+ * Wait for command completion in sleepable context.
+ *
+ * Returns:
+ * 0 if command is completed by firmware.
+ * Non zero error code for rest of the case.
+ */
static int __wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
{
struct bnxt_qplib_cmdq_ctx *cmdq;
- u16 cbit;
- int rc;
+ struct bnxt_qplib_crsqe *crsqe;
+ int ret;
cmdq = &rcfw->cmdq;
- cbit = cookie % rcfw->cmdq_depth;
- rc = wait_event_timeout(cmdq->waitq,
- !test_bit(cbit, cmdq->cmdq_bitmap),
- msecs_to_jiffies(RCFW_CMD_WAIT_TIME_MS));
- return rc ? 0 : -ETIMEDOUT;
+ crsqe = &rcfw->crsqe_tbl[cookie];
+
+ do {
+ if (test_bit(ERR_DEVICE_DETACHED, &cmdq->flags))
+ return bnxt_qplib_map_rc(crsqe->opcode);
+ if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags))
+ return -ETIMEDOUT;
+
+ wait_event_timeout(cmdq->waitq,
+ !crsqe->is_in_used ||
+ test_bit(ERR_DEVICE_DETACHED, &cmdq->flags),
+ msecs_to_jiffies(rcfw->max_timeout * 1000));
+
+ if (!crsqe->is_in_used)
+ return 0;
+
+ bnxt_qplib_service_creq(&rcfw->creq.creq_tasklet);
+
+ if (!crsqe->is_in_used)
+ return 0;
+
+ ret = bnxt_re_is_fw_stalled(rcfw, cookie);
+ if (ret)
+ return ret;
+
+ } while (true);
};
+/**
+ * __block_for_resp - hold the cpu context and wait for response
+ * @rcfw - rcfw channel instance of rdev
+ * @cookie - cookie to track the command
+ *
+ * This function will hold the cpu (non-sleepable context) and
+ * wait for command completion. Maximum holding interval is 8 second.
+ *
+ * Returns:
+ * -ETIMEOUT if command is not completed in specific time interval.
+ * 0 if command is completed by firmware.
+ */
static int __block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
{
- u32 count = RCFW_BLOCKED_CMD_WAIT_COUNT;
- struct bnxt_qplib_cmdq_ctx *cmdq;
- u16 cbit;
+ struct bnxt_qplib_cmdq_ctx *cmdq = &rcfw->cmdq;
+ struct bnxt_qplib_crsqe *crsqe;
+ unsigned long issue_time = 0;
+
+ issue_time = jiffies;
+ crsqe = &rcfw->crsqe_tbl[cookie];
- cmdq = &rcfw->cmdq;
- cbit = cookie % rcfw->cmdq_depth;
- if (!test_bit(cbit, cmdq->cmdq_bitmap))
- goto done;
do {
+ if (test_bit(ERR_DEVICE_DETACHED, &cmdq->flags))
+ return bnxt_qplib_map_rc(crsqe->opcode);
+ if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags))
+ return -ETIMEDOUT;
+
udelay(1);
+
bnxt_qplib_service_creq(&rcfw->creq.creq_tasklet);
- } while (test_bit(cbit, cmdq->cmdq_bitmap) && --count);
-done:
- return count ? 0 : -ETIMEDOUT;
+ if (!crsqe->is_in_used)
+ return 0;
+
+ } while (time_before(jiffies, issue_time + (8 * HZ)));
+
+ return -ETIMEDOUT;
};
-static int __send_message(struct bnxt_qplib_rcfw *rcfw,
- struct bnxt_qplib_cmdqmsg *msg)
+/* __send_message_no_waiter - get cookie and post the message.
+ * @rcfw - rcfw channel instance of rdev
+ * @msg - qplib message internal
+ *
+ * This function will just post and don't bother about completion.
+ * Current design of this function is -
+ * user must hold the completion queue hwq->lock.
+ * user must have used existing completion and free the resources.
+ * this function will not check queue full condition.
+ * this function will explicitly set is_waiter_alive=false.
+ * current use case is - send destroy_ah if create_ah is return
+ * after waiter of create_ah is lost. It can be extended for other
+ * use case as well.
+ *
+ * Returns: Nothing
+ *
+ */
+static void __send_message_no_waiter(struct bnxt_qplib_rcfw *rcfw,
+ struct bnxt_qplib_cmdqmsg *msg)
{
struct bnxt_qplib_cmdq_ctx *cmdq = &rcfw->cmdq;
struct bnxt_qplib_hwq *hwq = &cmdq->hwq;
struct bnxt_qplib_crsqe *crsqe;
struct bnxt_qplib_cmdqe *cmdqe;
u32 sw_prod, cmdq_prod;
- struct pci_dev *pdev;
- unsigned long flags;
- u32 bsize, opcode;
- u16 cookie, cbit;
+ u16 cookie;
+ u32 bsize;
u8 *preq;
- pdev = rcfw->pdev;
+ cookie = cmdq->seq_num & RCFW_MAX_COOKIE_VALUE;
+ __set_cmdq_base_cookie(msg->req, msg->req_sz, cpu_to_le16(cookie));
+ crsqe = &rcfw->crsqe_tbl[cookie];
- opcode = __get_cmdq_base_opcode(msg->req, msg->req_sz);
- if (!test_bit(FIRMWARE_INITIALIZED_FLAG, &cmdq->flags) &&
- (opcode != CMDQ_BASE_OPCODE_QUERY_FUNC &&
- opcode != CMDQ_BASE_OPCODE_INITIALIZE_FW &&
- opcode != CMDQ_BASE_OPCODE_QUERY_VERSION)) {
- dev_err(&pdev->dev,
- "RCFW not initialized, reject opcode 0x%x\n", opcode);
- return -EINVAL;
- }
+ /* Set cmd_size in terms of 16B slots in req. */
+ bsize = bnxt_qplib_set_cmd_slots(msg->req);
+ /* GET_CMD_SIZE would return number of slots in either case of tlv
+ * and non-tlv commands after call to bnxt_qplib_set_cmd_slots()
+ */
+ crsqe->is_internal_cmd = true;
+ crsqe->is_waiter_alive = false;
+ crsqe->is_in_used = true;
+ crsqe->req_size = __get_cmdq_base_cmd_size(msg->req, msg->req_sz);
- if (test_bit(FIRMWARE_INITIALIZED_FLAG, &cmdq->flags) &&
- opcode == CMDQ_BASE_OPCODE_INITIALIZE_FW) {
- dev_err(&pdev->dev, "RCFW already initialized!\n");
- return -EINVAL;
- }
+ preq = (u8 *)msg->req;
+ do {
+ /* Locate the next cmdq slot */
+ sw_prod = HWQ_CMP(hwq->prod, hwq);
+ cmdqe = bnxt_qplib_get_qe(hwq, sw_prod, NULL);
+ /* Copy a segment of the req cmd to the cmdq */
+ memset(cmdqe, 0, sizeof(*cmdqe));
+ memcpy(cmdqe, preq, min_t(u32, bsize, sizeof(*cmdqe)));
+ preq += min_t(u32, bsize, sizeof(*cmdqe));
+ bsize -= min_t(u32, bsize, sizeof(*cmdqe));
+ hwq->prod++;
+ } while (bsize > 0);
+ cmdq->seq_num++;
- if (test_bit(FIRMWARE_TIMED_OUT, &cmdq->flags))
- return -ETIMEDOUT;
+ cmdq_prod = hwq->prod;
+ atomic_inc(&rcfw->timeout_send);
+ /* ring CMDQ DB */
+ wmb();
+ writel(cmdq_prod, cmdq->cmdq_mbox.prod);
+ writel(RCFW_CMDQ_TRIG_VAL, cmdq->cmdq_mbox.db);
+}
+
+static int __send_message(struct bnxt_qplib_rcfw *rcfw,
+ struct bnxt_qplib_cmdqmsg *msg, u8 opcode)
+{
+ u32 bsize, free_slots, required_slots;
+ struct bnxt_qplib_cmdq_ctx *cmdq;
+ struct bnxt_qplib_crsqe *crsqe;
+ struct bnxt_qplib_cmdqe *cmdqe;
+ struct bnxt_qplib_hwq *hwq;
+ u32 sw_prod, cmdq_prod;
+ struct pci_dev *pdev;
+ unsigned long flags;
+ u16 cookie;
+ u8 *preq;
+
+ cmdq = &rcfw->cmdq;
+ hwq = &cmdq->hwq;
+ pdev = rcfw->pdev;
/* Cmdq are in 16-byte units, each request can consume 1 or more
* cmdqe
*/
spin_lock_irqsave(&hwq->lock, flags);
- if (msg->req->cmd_size >= HWQ_FREE_SLOTS(hwq)) {
- dev_err(&pdev->dev, "RCFW: CMDQ is full!\n");
+ required_slots = bnxt_qplib_get_cmd_slots(msg->req);
+ free_slots = HWQ_FREE_SLOTS(hwq);
+ cookie = cmdq->seq_num & RCFW_MAX_COOKIE_VALUE;
+ crsqe = &rcfw->crsqe_tbl[cookie];
+
+ if (required_slots >= free_slots) {
+ dev_info_ratelimited(&pdev->dev,
+ "CMDQ is full req/free %d/%d!",
+ required_slots, free_slots);
spin_unlock_irqrestore(&hwq->lock, flags);
return -EAGAIN;
}
-
-
- cookie = cmdq->seq_num & RCFW_MAX_COOKIE_VALUE;
- cbit = cookie % rcfw->cmdq_depth;
if (msg->block)
cookie |= RCFW_CMD_IS_BLOCKING;
-
- set_bit(cbit, cmdq->cmdq_bitmap);
__set_cmdq_base_cookie(msg->req, msg->req_sz, cpu_to_le16(cookie));
- crsqe = &rcfw->crsqe_tbl[cbit];
- if (crsqe->resp) {
- spin_unlock_irqrestore(&hwq->lock, flags);
- return -EBUSY;
- }
- /* change the cmd_size to the number of 16byte cmdq unit.
- * req->cmd_size is modified here
- */
bsize = bnxt_qplib_set_cmd_slots(msg->req);
-
- memset(msg->resp, 0, sizeof(*msg->resp));
+ crsqe->free_slots = free_slots;
crsqe->resp = (struct creq_qp_event *)msg->resp;
crsqe->resp->cookie = cpu_to_le16(cookie);
+ crsqe->is_internal_cmd = false;
+ crsqe->is_waiter_alive = true;
+ crsqe->is_in_used = true;
+ crsqe->opcode = opcode;
+
crsqe->req_size = __get_cmdq_base_cmd_size(msg->req, msg->req_sz);
if (__get_cmdq_base_resp_size(msg->req, msg->req_sz) && msg->sb) {
struct bnxt_qplib_rcfw_sbuf *sbuf = msg->sb;
- __set_cmdq_base_resp_addr(msg->req, msg->req_sz, cpu_to_le64(sbuf->dma_addr));
+
+ __set_cmdq_base_resp_addr(msg->req, msg->req_sz,
+ cpu_to_le64(sbuf->dma_addr));
__set_cmdq_base_resp_size(msg->req, msg->req_sz,
- ALIGN(sbuf->size, BNXT_QPLIB_CMDQE_UNITS));
+ ALIGN(sbuf->size,
+ BNXT_QPLIB_CMDQE_UNITS));
}
preq = (u8 *)msg->req;
@@ -166,11 +343,6 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw,
/* Locate the next cmdq slot */
sw_prod = HWQ_CMP(hwq->prod, hwq);
cmdqe = bnxt_qplib_get_qe(hwq, sw_prod, NULL);
- if (!cmdqe) {
- dev_err(&pdev->dev,
- "RCFW request failed with no cmdqe!\n");
- goto done;
- }
/* Copy a segment of the req cmd to the cmdq */
memset(cmdqe, 0, sizeof(*cmdqe));
memcpy(cmdqe, preq, min_t(u32, bsize, sizeof(*cmdqe)));
@@ -180,7 +352,7 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw,
} while (bsize > 0);
cmdq->seq_num++;
- cmdq_prod = hwq->prod;
+ cmdq_prod = hwq->prod & 0xFFFF;
if (test_bit(FIRMWARE_FIRST_FLAG, &cmdq->flags)) {
/* The very first doorbell write
* is required to set this flag
@@ -194,51 +366,158 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw,
wmb();
writel(cmdq_prod, cmdq->cmdq_mbox.prod);
writel(RCFW_CMDQ_TRIG_VAL, cmdq->cmdq_mbox.db);
-done:
spin_unlock_irqrestore(&hwq->lock, flags);
/* Return the CREQ response pointer */
return 0;
}
-int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
- struct bnxt_qplib_cmdqmsg *msg)
+/**
+ * __poll_for_resp - self poll completion for rcfw command
+ * @rcfw - rcfw channel instance of rdev
+ * @cookie - cookie to track the command
+ *
+ * It works same as __wait_for_resp except this function will
+ * do self polling in sort interval since interrupt is disabled.
+ * This function can not be called from non-sleepable context.
+ *
+ * Returns:
+ * -ETIMEOUT if command is not completed in specific time interval.
+ * 0 if command is completed by firmware.
+ */
+static int __poll_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
+{
+ struct bnxt_qplib_cmdq_ctx *cmdq = &rcfw->cmdq;
+ struct bnxt_qplib_crsqe *crsqe;
+ unsigned long issue_time;
+ int ret;
+
+ issue_time = jiffies;
+ crsqe = &rcfw->crsqe_tbl[cookie];
+
+ do {
+ if (test_bit(ERR_DEVICE_DETACHED, &cmdq->flags))
+ return bnxt_qplib_map_rc(crsqe->opcode);
+ if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags))
+ return -ETIMEDOUT;
+
+ usleep_range(1000, 1001);
+
+ bnxt_qplib_service_creq(&rcfw->creq.creq_tasklet);
+ if (!crsqe->is_in_used)
+ return 0;
+ if (jiffies_to_msecs(jiffies - issue_time) >
+ (rcfw->max_timeout * 1000)) {
+ ret = bnxt_re_is_fw_stalled(rcfw, cookie);
+ if (ret)
+ return ret;
+ }
+ } while (true);
+};
+
+static int __send_message_basic_sanity(struct bnxt_qplib_rcfw *rcfw,
+ struct bnxt_qplib_cmdqmsg *msg,
+ u8 opcode)
+{
+ struct bnxt_qplib_cmdq_ctx *cmdq;
+
+ cmdq = &rcfw->cmdq;
+
+ /* Prevent posting if f/w is not in a state to process */
+ if (test_bit(ERR_DEVICE_DETACHED, &rcfw->cmdq.flags))
+ return bnxt_qplib_map_rc(opcode);
+ if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags))
+ return -ETIMEDOUT;
+
+ if (test_bit(FIRMWARE_INITIALIZED_FLAG, &cmdq->flags) &&
+ opcode == CMDQ_BASE_OPCODE_INITIALIZE_FW) {
+ dev_err(&rcfw->pdev->dev, "QPLIB: RCFW already initialized!");
+ return -EINVAL;
+ }
+
+ if (!test_bit(FIRMWARE_INITIALIZED_FLAG, &cmdq->flags) &&
+ (opcode != CMDQ_BASE_OPCODE_QUERY_FUNC &&
+ opcode != CMDQ_BASE_OPCODE_INITIALIZE_FW &&
+ opcode != CMDQ_BASE_OPCODE_QUERY_VERSION)) {
+ dev_err(&rcfw->pdev->dev,
+ "QPLIB: RCFW not initialized, reject opcode 0x%x",
+ opcode);
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+/* This function will just post and do not bother about completion */
+static void __destroy_timedout_ah(struct bnxt_qplib_rcfw *rcfw,
+ struct creq_create_ah_resp *create_ah_resp)
+{
+ struct bnxt_qplib_cmdqmsg msg = {};
+ struct cmdq_destroy_ah req = {};
+
+ bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
+ CMDQ_BASE_OPCODE_DESTROY_AH,
+ sizeof(req));
+ req.ah_cid = create_ah_resp->xid;
+ msg.req = (struct cmdq_base *)&req;
+ msg.req_sz = sizeof(req);
+ __send_message_no_waiter(rcfw, &msg);
+ dev_info_ratelimited(&rcfw->pdev->dev,
+ "From %s: ah_cid = %d timeout_send %d\n",
+ __func__, req.ah_cid,
+ atomic_read(&rcfw->timeout_send));
+}
+
+/**
+ * __bnxt_qplib_rcfw_send_message - qplib interface to send
+ * and complete rcfw command.
+ * @rcfw - rcfw channel instance of rdev
+ * @msg - qplib message internal
+ *
+ * This function does not account shadow queue depth. It will send
+ * all the command unconditionally as long as send queue is not full.
+ *
+ * Returns:
+ * 0 if command completed by firmware.
+ * Non zero if the command is not completed by firmware.
+ */
+static int __bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
+ struct bnxt_qplib_cmdqmsg *msg)
{
struct creq_qp_event *evnt = (struct creq_qp_event *)msg->resp;
+ struct bnxt_qplib_crsqe *crsqe;
+ unsigned long flags;
u16 cookie;
- u8 opcode, retry_cnt = 0xFF;
int rc = 0;
+ u8 opcode;
- /* Prevent posting if f/w is not in a state to process */
- if (test_bit(ERR_DEVICE_DETACHED, &rcfw->cmdq.flags))
- return 0;
+ opcode = __get_cmdq_base_opcode(msg->req, msg->req_sz);
- do {
- opcode = __get_cmdq_base_opcode(msg->req, msg->req_sz);
- rc = __send_message(rcfw, msg);
- cookie = le16_to_cpu(__get_cmdq_base_cookie(msg->req, msg->req_sz)) &
- RCFW_MAX_COOKIE_VALUE;
- if (!rc)
- break;
- if (!retry_cnt || (rc != -EAGAIN && rc != -EBUSY)) {
- /* send failed */
- dev_err(&rcfw->pdev->dev, "cmdq[%#x]=%#x send failed\n",
- cookie, opcode);
- return rc;
- }
- msg->block ? mdelay(1) : usleep_range(500, 1000);
+ rc = __send_message_basic_sanity(rcfw, msg, opcode);
+ if (rc)
+ return rc;
- } while (retry_cnt--);
+ rc = __send_message(rcfw, msg, opcode);
+ if (rc)
+ return rc;
+
+ cookie = le16_to_cpu(__get_cmdq_base_cookie(msg->req, msg->req_sz))
+ & RCFW_MAX_COOKIE_VALUE;
if (msg->block)
rc = __block_for_resp(rcfw, cookie);
- else
+ else if (atomic_read(&rcfw->rcfw_intr_enabled))
rc = __wait_for_resp(rcfw, cookie);
+ else
+ rc = __poll_for_resp(rcfw, cookie);
+
if (rc) {
- /* timed out */
- dev_err(&rcfw->pdev->dev, "cmdq[%#x]=%#x timedout (%d)msec\n",
- cookie, opcode, RCFW_CMD_WAIT_TIME_MS);
- set_bit(FIRMWARE_TIMED_OUT, &rcfw->cmdq.flags);
- return rc;
+ spin_lock_irqsave(&rcfw->cmdq.hwq.lock, flags);
+ crsqe = &rcfw->crsqe_tbl[cookie];
+ crsqe->is_waiter_alive = false;
+ if (rc == -ENODEV)
+ set_bit(FIRMWARE_STALL_DETECTED, &rcfw->cmdq.flags);
+ spin_unlock_irqrestore(&rcfw->cmdq.hwq.lock, flags);
+ return -ETIMEDOUT;
}
if (evnt->status) {
@@ -250,6 +529,48 @@ int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
return rc;
}
+
+/**
+ * bnxt_qplib_rcfw_send_message - qplib interface to send
+ * and complete rcfw command.
+ * @rcfw - rcfw channel instance of rdev
+ * @msg - qplib message internal
+ *
+ * Driver interact with Firmware through rcfw channel/slow path in two ways.
+ * a. Blocking rcfw command send. In this path, driver cannot hold
+ * the context for longer period since it is holding cpu until
+ * command is not completed.
+ * b. Non-blocking rcfw command send. In this path, driver can hold the
+ * context for longer period. There may be many pending command waiting
+ * for completion because of non-blocking nature.
+ *
+ * Driver will use shadow queue depth. Current queue depth of 8K
+ * (due to size of rcfw message there can be actual ~4K rcfw outstanding)
+ * is not optimal for rcfw command processing in firmware.
+ *
+ * Restrict at max #RCFW_CMD_NON_BLOCKING_SHADOW_QD Non-Blocking rcfw commands.
+ * Allow all blocking commands until there is no queue full.
+ *
+ * Returns:
+ * 0 if command completed by firmware.
+ * Non zero if the command is not completed by firmware.
+ */
+int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
+ struct bnxt_qplib_cmdqmsg *msg)
+{
+ int ret;
+
+ if (!msg->block) {
+ down(&rcfw->rcfw_inflight);
+ ret = __bnxt_qplib_rcfw_send_message(rcfw, msg);
+ up(&rcfw->rcfw_inflight);
+ } else {
+ ret = __bnxt_qplib_rcfw_send_message(rcfw, msg);
+ }
+
+ return ret;
+}
+
/* Completions */
static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw,
struct creq_func_event *func_event)
@@ -295,19 +616,20 @@ static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw,
}
static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
- struct creq_qp_event *qp_event)
+ struct creq_qp_event *qp_event,
+ u32 *num_wait)
{
struct creq_qp_error_notification *err_event;
struct bnxt_qplib_hwq *hwq = &rcfw->cmdq.hwq;
struct bnxt_qplib_crsqe *crsqe;
+ u32 qp_id, tbl_indx, req_size;
struct bnxt_qplib_qp *qp;
- u16 cbit, blocked = 0;
+ u16 cookie, blocked = 0;
+ bool is_waiter_alive;
struct pci_dev *pdev;
unsigned long flags;
- __le16 mcookie;
- u16 cookie;
+ u32 wait_cmds = 0;
int rc = 0;
- u32 qp_id, tbl_indx;
pdev = rcfw->pdev;
switch (qp_event->event) {
@@ -339,33 +661,60 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
spin_lock_irqsave_nested(&hwq->lock, flags,
SINGLE_DEPTH_NESTING);
cookie = le16_to_cpu(qp_event->cookie);
- mcookie = qp_event->cookie;
blocked = cookie & RCFW_CMD_IS_BLOCKING;
cookie &= RCFW_MAX_COOKIE_VALUE;
- cbit = cookie % rcfw->cmdq_depth;
- crsqe = &rcfw->crsqe_tbl[cbit];
- if (crsqe->resp &&
- crsqe->resp->cookie == mcookie) {
- memcpy(crsqe->resp, qp_event, sizeof(*qp_event));
- crsqe->resp = NULL;
- } else {
- if (crsqe->resp && crsqe->resp->cookie)
- dev_err(&pdev->dev,
- "CMD %s cookie sent=%#x, recd=%#x\n",
- crsqe->resp ? "mismatch" : "collision",
- crsqe->resp ? crsqe->resp->cookie : 0,
- mcookie);
+ crsqe = &rcfw->crsqe_tbl[cookie];
+ crsqe->is_in_used = false;
+
+ if (WARN_ONCE(test_bit(FIRMWARE_STALL_DETECTED,
+ &rcfw->cmdq.flags),
+ "QPLIB: Unreponsive rcfw channel detected.!!")) {
+ dev_info(&pdev->dev,
+ "rcfw timedout: cookie = %#x, free_slots = %d",
+ cookie, crsqe->free_slots);
+ spin_unlock_irqrestore(&hwq->lock, flags);
+ return rc;
}
- if (!test_and_clear_bit(cbit, rcfw->cmdq.cmdq_bitmap))
- dev_warn(&pdev->dev,
- "CMD bit %d was not requested\n", cbit);
- hwq->cons += crsqe->req_size;
+
+ if (crsqe->is_internal_cmd && !qp_event->status)
+ atomic_dec(&rcfw->timeout_send);
+
+ if (crsqe->is_waiter_alive) {
+ if (crsqe->resp)
+ memcpy(crsqe->resp, qp_event, sizeof(*qp_event));
+ if (!blocked)
+ wait_cmds++;
+ }
+
+ req_size = crsqe->req_size;
+ is_waiter_alive = crsqe->is_waiter_alive;
+
crsqe->req_size = 0;
+ if (!is_waiter_alive)
+ crsqe->resp = NULL;
- if (!blocked)
- wake_up(&rcfw->cmdq.waitq);
+ hwq->cons += req_size;
+
+ /* This is a case to handle below scenario -
+ * Create AH is completed successfully by firmware,
+ * but completion took more time and driver already lost
+ * the context of create_ah from caller.
+ * We have already return failure for create_ah verbs,
+ * so let's destroy the same address vector since it is
+ * no more used in stack. We don't care about completion
+ * in __send_message_no_waiter.
+ * If destroy_ah is failued by firmware, there will be AH
+ * resource leak and relatively not critical + unlikely
+ * scenario. Current design is not to handle such case.
+ */
+ if (!is_waiter_alive && !qp_event->status &&
+ qp_event->event == CREQ_QP_EVENT_EVENT_CREATE_AH)
+ __destroy_timedout_ah(rcfw,
+ (struct creq_create_ah_resp *)
+ qp_event);
spin_unlock_irqrestore(&hwq->lock, flags);
}
+ *num_wait += wait_cmds;
return rc;
}
@@ -379,6 +728,7 @@ static void bnxt_qplib_service_creq(struct tasklet_struct *t)
struct creq_base *creqe;
u32 sw_cons, raw_cons;
unsigned long flags;
+ u32 num_wakeup = 0;
/* Service the CREQ until budget is over */
spin_lock_irqsave(&hwq->lock, flags);
@@ -392,12 +742,14 @@ static void bnxt_qplib_service_creq(struct tasklet_struct *t)
* reading any further.
*/
dma_rmb();
+ rcfw->cmdq.last_seen = jiffies;
type = creqe->type & CREQ_BASE_TYPE_MASK;
switch (type) {
case CREQ_BASE_TYPE_QP_EVENT:
bnxt_qplib_process_qp_event
- (rcfw, (struct creq_qp_event *)creqe);
+ (rcfw, (struct creq_qp_event *)creqe,
+ &num_wakeup);
creq->stats.creq_qp_event_processed++;
break;
case CREQ_BASE_TYPE_FUNC_EVENT:
@@ -425,6 +777,8 @@ static void bnxt_qplib_service_creq(struct tasklet_struct *t)
rcfw->res->cctx, true);
}
spin_unlock_irqrestore(&hwq->lock, flags);
+ if (num_wakeup)
+ wake_up_nr(&rcfw->cmdq.waitq, num_wakeup);
}
static irqreturn_t bnxt_qplib_creq_irq(int irq, void *dev_instance)
@@ -556,7 +910,6 @@ skip_ctx_setup:
void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)
{
- bitmap_free(rcfw->cmdq.cmdq_bitmap);
kfree(rcfw->qp_tbl);
kfree(rcfw->crsqe_tbl);
bnxt_qplib_free_hwq(rcfw->res, &rcfw->cmdq.hwq);
@@ -593,13 +946,11 @@ int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res,
"HW channel CREQ allocation failed\n");
goto fail;
}
- if (ctx->hwrm_intf_ver < HWRM_VERSION_RCFW_CMDQ_DEPTH_CHECK)
- rcfw->cmdq_depth = BNXT_QPLIB_CMDQE_MAX_CNT_256;
- else
- rcfw->cmdq_depth = BNXT_QPLIB_CMDQE_MAX_CNT_8192;
+
+ rcfw->cmdq_depth = BNXT_QPLIB_CMDQE_MAX_CNT;
sginfo.pgsize = bnxt_qplib_cmdqe_page_size(rcfw->cmdq_depth);
- hwq_attr.depth = rcfw->cmdq_depth;
+ hwq_attr.depth = rcfw->cmdq_depth & 0x7FFFFFFF;
hwq_attr.stride = BNXT_QPLIB_CMDQE_UNITS;
hwq_attr.type = HWQ_TYPE_CTX;
if (bnxt_qplib_alloc_init_hwq(&cmdq->hwq, &hwq_attr)) {
@@ -613,10 +964,6 @@ int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res,
if (!rcfw->crsqe_tbl)
goto fail;
- cmdq->cmdq_bitmap = bitmap_zalloc(rcfw->cmdq_depth, GFP_KERNEL);
- if (!cmdq->cmdq_bitmap)
- goto fail;
-
/* Allocate one extra to hold the QP1 entries */
rcfw->qp_tbl_size = qp_tbl_sz + 1;
rcfw->qp_tbl = kcalloc(rcfw->qp_tbl_size, sizeof(struct bnxt_qplib_qp_node),
@@ -624,6 +971,8 @@ int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res,
if (!rcfw->qp_tbl)
goto fail;
+ rcfw->max_timeout = res->cctx->hwrm_cmd_max_timeout;
+
return 0;
fail:
@@ -636,6 +985,10 @@ void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill)
struct bnxt_qplib_creq_ctx *creq;
creq = &rcfw->creq;
+
+ if (!creq->requested)
+ return;
+
tasklet_disable(&creq->creq_tasklet);
/* Mask h/w interrupts */
bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, rcfw->res->cctx, false);
@@ -644,17 +997,17 @@ void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill)
if (kill)
tasklet_kill(&creq->creq_tasklet);
- if (creq->requested) {
- free_irq(creq->msix_vec, rcfw);
- creq->requested = false;
- }
+ free_irq(creq->msix_vec, rcfw);
+ kfree(creq->irq_name);
+ creq->irq_name = NULL;
+ creq->requested = false;
+ atomic_set(&rcfw->rcfw_intr_enabled, 0);
}
void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)
{
struct bnxt_qplib_creq_ctx *creq;
struct bnxt_qplib_cmdq_ctx *cmdq;
- unsigned long indx;
creq = &rcfw->creq;
cmdq = &rcfw->cmdq;
@@ -664,11 +1017,6 @@ void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)
iounmap(cmdq->cmdq_mbox.reg.bar_reg);
iounmap(creq->creq_db.reg.bar_reg);
- indx = find_first_bit(cmdq->cmdq_bitmap, rcfw->cmdq_depth);
- if (indx != rcfw->cmdq_depth)
- dev_err(&rcfw->pdev->dev,
- "disabling RCFW with pending cmd-bit %lx\n", indx);
-
cmdq->cmdq_mbox.reg.bar_reg = NULL;
creq->creq_db.reg.bar_reg = NULL;
creq->aeq_handler = NULL;
@@ -679,9 +1027,11 @@ int bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector,
bool need_init)
{
struct bnxt_qplib_creq_ctx *creq;
+ struct bnxt_qplib_res *res;
int rc;
creq = &rcfw->creq;
+ res = rcfw->res;
if (creq->requested)
return -EFAULT;
@@ -691,24 +1041,32 @@ int bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector,
tasklet_setup(&creq->creq_tasklet, bnxt_qplib_service_creq);
else
tasklet_enable(&creq->creq_tasklet);
+
+ creq->irq_name = kasprintf(GFP_KERNEL, "bnxt_re-creq@pci:%s",
+ pci_name(res->pdev));
+ if (!creq->irq_name)
+ return -ENOMEM;
rc = request_irq(creq->msix_vec, bnxt_qplib_creq_irq, 0,
- "bnxt_qplib_creq", rcfw);
- if (rc)
+ creq->irq_name, rcfw);
+ if (rc) {
+ kfree(creq->irq_name);
+ creq->irq_name = NULL;
+ tasklet_disable(&creq->creq_tasklet);
return rc;
+ }
creq->requested = true;
- bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, rcfw->res->cctx, true);
+ bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, res->cctx, true);
+ atomic_inc(&rcfw->rcfw_intr_enabled);
return 0;
}
-static int bnxt_qplib_map_cmdq_mbox(struct bnxt_qplib_rcfw *rcfw, bool is_vf)
+static int bnxt_qplib_map_cmdq_mbox(struct bnxt_qplib_rcfw *rcfw)
{
struct bnxt_qplib_cmdq_mbox *mbox;
resource_size_t bar_reg;
struct pci_dev *pdev;
- u16 prod_offt;
- int rc = 0;
pdev = rcfw->pdev;
mbox = &rcfw->cmdq.cmdq_mbox;
@@ -733,11 +1091,10 @@ static int bnxt_qplib_map_cmdq_mbox(struct bnxt_qplib_rcfw *rcfw, bool is_vf)
return -ENOMEM;
}
- prod_offt = is_vf ? RCFW_VF_COMM_PROD_OFFSET :
- RCFW_PF_COMM_PROD_OFFSET;
- mbox->prod = (void __iomem *)(mbox->reg.bar_reg + prod_offt);
+ mbox->prod = (void __iomem *)(mbox->reg.bar_reg +
+ RCFW_PF_VF_COMM_PROD_OFFSET);
mbox->db = (void __iomem *)(mbox->reg.bar_reg + RCFW_COMM_TRIG_OFFSET);
- return rc;
+ return 0;
}
static int bnxt_qplib_map_creq_db(struct bnxt_qplib_rcfw *rcfw, u32 reg_offt)
@@ -798,7 +1155,7 @@ static void bnxt_qplib_start_rcfw(struct bnxt_qplib_rcfw *rcfw)
int bnxt_qplib_enable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw,
int msix_vector,
- int cp_bar_reg_off, int virt_fn,
+ int cp_bar_reg_off,
aeq_handler_t aeq_handler)
{
struct bnxt_qplib_cmdq_ctx *cmdq;
@@ -818,7 +1175,7 @@ int bnxt_qplib_enable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw,
creq->stats.creq_func_event_processed = 0;
creq->aeq_handler = aeq_handler;
- rc = bnxt_qplib_map_cmdq_mbox(rcfw, virt_fn);
+ rc = bnxt_qplib_map_cmdq_mbox(rcfw);
if (rc)
return rc;
@@ -834,6 +1191,7 @@ int bnxt_qplib_enable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw,
return rc;
}
+ sema_init(&rcfw->rcfw_inflight, RCFW_CMD_NON_BLOCKING_SHADOW_QD);
bnxt_qplib_start_rcfw(rcfw);
return 0;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
index dd5651478bbb..7b31bee3e000 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
@@ -45,13 +45,13 @@
#define RCFW_COMM_PCI_BAR_REGION 0
#define RCFW_COMM_CONS_PCI_BAR_REGION 2
#define RCFW_COMM_BASE_OFFSET 0x600
-#define RCFW_PF_COMM_PROD_OFFSET 0xc
-#define RCFW_VF_COMM_PROD_OFFSET 0xc
+#define RCFW_PF_VF_COMM_PROD_OFFSET 0xc
#define RCFW_COMM_TRIG_OFFSET 0x100
#define RCFW_COMM_SIZE 0x104
#define RCFW_DBR_PCI_BAR_REGION 2
#define RCFW_DBR_BASE_PAGE_SHIFT 12
+#define RCFW_FW_STALL_MAX_TIMEOUT 40
/* Cmdq contains a fix number of a 16-Byte slots */
struct bnxt_qplib_cmdqe {
@@ -67,11 +67,12 @@ static inline void bnxt_qplib_rcfw_cmd_prep(struct cmdq_base *req,
req->cmd_size = cmd_size;
}
+/* Shadow queue depth for non blocking command */
+#define RCFW_CMD_NON_BLOCKING_SHADOW_QD 64
#define RCFW_CMD_WAIT_TIME_MS 20000 /* 20 Seconds timeout */
/* CMDQ elements */
-#define BNXT_QPLIB_CMDQE_MAX_CNT_256 256
-#define BNXT_QPLIB_CMDQE_MAX_CNT_8192 8192
+#define BNXT_QPLIB_CMDQE_MAX_CNT 8192
#define BNXT_QPLIB_CMDQE_BYTES(depth) ((depth) * BNXT_QPLIB_CMDQE_UNITS)
static inline u32 bnxt_qplib_cmdqe_npages(u32 depth)
@@ -89,6 +90,26 @@ static inline u32 bnxt_qplib_cmdqe_page_size(u32 depth)
return (bnxt_qplib_cmdqe_npages(depth) * PAGE_SIZE);
}
+/* Get the number of command units required for the req. The
+ * function returns correct value only if called before
+ * setting using bnxt_qplib_set_cmd_slots
+ */
+static inline u32 bnxt_qplib_get_cmd_slots(struct cmdq_base *req)
+{
+ u32 cmd_units = 0;
+
+ if (HAS_TLV_HEADER(req)) {
+ struct roce_tlv *tlv_req = (struct roce_tlv *)req;
+
+ cmd_units = tlv_req->total_size;
+ } else {
+ cmd_units = (req->cmd_size + BNXT_QPLIB_CMDQE_UNITS - 1) /
+ BNXT_QPLIB_CMDQE_UNITS;
+ }
+
+ return cmd_units;
+}
+
static inline u32 bnxt_qplib_set_cmd_slots(struct cmdq_base *req)
{
u32 cmd_byte = 0;
@@ -106,11 +127,10 @@ static inline u32 bnxt_qplib_set_cmd_slots(struct cmdq_base *req)
return cmd_byte;
}
-#define RCFW_MAX_COOKIE_VALUE 0x7FFF
+#define RCFW_MAX_COOKIE_VALUE (BNXT_QPLIB_CMDQE_MAX_CNT - 1)
#define RCFW_CMD_IS_BLOCKING 0x8000
-#define RCFW_BLOCKED_CMD_WAIT_COUNT 20000000UL /* 20 sec */
-#define HWRM_VERSION_RCFW_CMDQ_DEPTH_CHECK 0x1000900020011ULL
+#define HWRM_VERSION_DEV_ATTR_MAX_DPI 0x1000A0000000DULL
/* Crsq buf is 1024-Byte */
struct bnxt_qplib_crsbe {
@@ -132,6 +152,12 @@ typedef int (*aeq_handler_t)(struct bnxt_qplib_rcfw *, void *, void *);
struct bnxt_qplib_crsqe {
struct creq_qp_event *resp;
u32 req_size;
+ /* Free slots at the time of submission */
+ u32 free_slots;
+ u8 opcode;
+ bool is_waiter_alive;
+ bool is_internal_cmd;
+ bool is_in_used;
};
struct bnxt_qplib_rcfw_sbuf {
@@ -149,7 +175,7 @@ struct bnxt_qplib_qp_node {
#define FIRMWARE_INITIALIZED_FLAG (0)
#define FIRMWARE_FIRST_FLAG (31)
-#define FIRMWARE_TIMED_OUT (3)
+#define FIRMWARE_STALL_DETECTED (3)
#define ERR_DEVICE_DETACHED (4)
struct bnxt_qplib_cmdq_mbox {
@@ -163,7 +189,7 @@ struct bnxt_qplib_cmdq_ctx {
struct bnxt_qplib_cmdq_mbox cmdq_mbox;
wait_queue_head_t waitq;
unsigned long flags;
- unsigned long *cmdq_bitmap;
+ unsigned long last_seen;
u32 seq_num;
};
@@ -186,6 +212,7 @@ struct bnxt_qplib_creq_ctx {
u16 ring_id;
int msix_vec;
bool requested; /*irq handler installed */
+ char *irq_name;
};
/* RCFW Communication Channels */
@@ -200,6 +227,11 @@ struct bnxt_qplib_rcfw {
u64 oos_prev;
u32 init_oos_stats;
u32 cmdq_depth;
+ atomic_t rcfw_intr_enabled;
+ struct semaphore rcfw_inflight;
+ atomic_t timeout_send;
+ /* cached from chip cctx for quick reference in slow path */
+ u16 max_timeout;
};
struct bnxt_qplib_cmdqmsg {
@@ -234,7 +266,7 @@ int bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector,
bool need_init);
int bnxt_qplib_enable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw,
int msix_vector,
- int cp_bar_reg_off, int virt_fn,
+ int cp_bar_reg_off,
aeq_handler_t aeq_handler);
struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c
index 81b0c5e879f9..5fd8f7c90bb0 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c
@@ -696,44 +696,76 @@ static int bnxt_qplib_alloc_pd_tbl(struct bnxt_qplib_res *res,
}
/* DPIs */
-int bnxt_qplib_alloc_dpi(struct bnxt_qplib_dpi_tbl *dpit,
- struct bnxt_qplib_dpi *dpi,
- void *app)
+int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res,
+ struct bnxt_qplib_dpi *dpi,
+ void *app, u8 type)
{
+ struct bnxt_qplib_dpi_tbl *dpit = &res->dpi_tbl;
+ struct bnxt_qplib_reg_desc *reg;
u32 bit_num;
+ u64 umaddr;
+
+ reg = &dpit->wcreg;
+ mutex_lock(&res->dpi_tbl_lock);
bit_num = find_first_bit(dpit->tbl, dpit->max);
- if (bit_num == dpit->max)
+ if (bit_num == dpit->max) {
+ mutex_unlock(&res->dpi_tbl_lock);
return -ENOMEM;
+ }
/* Found unused DPI */
clear_bit(bit_num, dpit->tbl);
dpit->app_tbl[bit_num] = app;
- dpi->dpi = bit_num;
- dpi->dbr = dpit->dbr_bar_reg_iomem + (bit_num * PAGE_SIZE);
- dpi->umdbr = dpit->unmapped_dbr + (bit_num * PAGE_SIZE);
+ dpi->bit = bit_num;
+ dpi->dpi = bit_num + (reg->offset - dpit->ucreg.offset) / PAGE_SIZE;
+
+ umaddr = reg->bar_base + reg->offset + bit_num * PAGE_SIZE;
+ dpi->umdbr = umaddr;
+
+ switch (type) {
+ case BNXT_QPLIB_DPI_TYPE_KERNEL:
+ /* privileged dbr was already mapped just initialize it. */
+ dpi->umdbr = dpit->ucreg.bar_base +
+ dpit->ucreg.offset + bit_num * PAGE_SIZE;
+ dpi->dbr = dpit->priv_db;
+ dpi->dpi = dpi->bit;
+ break;
+ case BNXT_QPLIB_DPI_TYPE_WC:
+ dpi->dbr = ioremap_wc(umaddr, PAGE_SIZE);
+ break;
+ default:
+ dpi->dbr = ioremap(umaddr, PAGE_SIZE);
+ break;
+ }
+ dpi->type = type;
+ mutex_unlock(&res->dpi_tbl_lock);
return 0;
+
}
int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res,
- struct bnxt_qplib_dpi_tbl *dpit,
- struct bnxt_qplib_dpi *dpi)
+ struct bnxt_qplib_dpi *dpi)
{
- if (dpi->dpi >= dpit->max) {
- dev_warn(&res->pdev->dev, "Invalid DPI? dpi = %d\n", dpi->dpi);
- return -EINVAL;
- }
- if (test_and_set_bit(dpi->dpi, dpit->tbl)) {
- dev_warn(&res->pdev->dev, "Freeing an unused DPI? dpi = %d\n",
- dpi->dpi);
+ struct bnxt_qplib_dpi_tbl *dpit = &res->dpi_tbl;
+
+ mutex_lock(&res->dpi_tbl_lock);
+ if (dpi->dpi && dpi->type != BNXT_QPLIB_DPI_TYPE_KERNEL)
+ pci_iounmap(res->pdev, dpi->dbr);
+
+ if (test_and_set_bit(dpi->bit, dpit->tbl)) {
+ dev_warn(&res->pdev->dev,
+ "Freeing an unused DPI? dpi = %d, bit = %d\n",
+ dpi->dpi, dpi->bit);
+ mutex_unlock(&res->dpi_tbl_lock);
return -EINVAL;
}
if (dpit->app_tbl)
- dpit->app_tbl[dpi->dpi] = NULL;
+ dpit->app_tbl[dpi->bit] = NULL;
memset(dpi, 0, sizeof(*dpi));
-
+ mutex_unlock(&res->dpi_tbl_lock);
return 0;
}
@@ -742,52 +774,38 @@ static void bnxt_qplib_free_dpi_tbl(struct bnxt_qplib_res *res,
{
kfree(dpit->tbl);
kfree(dpit->app_tbl);
- if (dpit->dbr_bar_reg_iomem)
- pci_iounmap(res->pdev, dpit->dbr_bar_reg_iomem);
- memset(dpit, 0, sizeof(*dpit));
+ dpit->tbl = NULL;
+ dpit->app_tbl = NULL;
+ dpit->max = 0;
}
-static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res,
- struct bnxt_qplib_dpi_tbl *dpit,
- u32 dbr_offset)
+static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res,
+ struct bnxt_qplib_dev_attr *dev_attr)
{
- u32 dbr_bar_reg = RCFW_DBR_PCI_BAR_REGION;
- resource_size_t bar_reg_base;
- u32 dbr_len, bytes;
-
- if (dpit->dbr_bar_reg_iomem) {
- dev_err(&res->pdev->dev, "DBR BAR region %d already mapped\n",
- dbr_bar_reg);
- return -EALREADY;
- }
-
- bar_reg_base = pci_resource_start(res->pdev, dbr_bar_reg);
- if (!bar_reg_base) {
- dev_err(&res->pdev->dev, "BAR region %d resc start failed\n",
- dbr_bar_reg);
- return -ENOMEM;
- }
+ struct bnxt_qplib_dpi_tbl *dpit;
+ struct bnxt_qplib_reg_desc *reg;
+ unsigned long bar_len;
+ u32 dbr_offset;
+ u32 bytes;
- dbr_len = pci_resource_len(res->pdev, dbr_bar_reg) - dbr_offset;
- if (!dbr_len || ((dbr_len & (PAGE_SIZE - 1)) != 0)) {
- dev_err(&res->pdev->dev, "Invalid DBR length %d\n", dbr_len);
- return -ENOMEM;
- }
+ dpit = &res->dpi_tbl;
+ reg = &dpit->wcreg;
- dpit->dbr_bar_reg_iomem = ioremap(bar_reg_base + dbr_offset,
- dbr_len);
- if (!dpit->dbr_bar_reg_iomem) {
- dev_err(&res->pdev->dev,
- "FP: DBR BAR region %d mapping failed\n", dbr_bar_reg);
- return -ENOMEM;
+ if (!bnxt_qplib_is_chip_gen_p5(res->cctx)) {
+ /* Offest should come from L2 driver */
+ dbr_offset = dev_attr->l2_db_size;
+ dpit->ucreg.offset = dbr_offset;
+ dpit->wcreg.offset = dbr_offset;
}
- dpit->unmapped_dbr = bar_reg_base + dbr_offset;
- dpit->max = dbr_len / PAGE_SIZE;
+ bar_len = pci_resource_len(res->pdev, reg->bar_id);
+ dpit->max = (bar_len - reg->offset) / PAGE_SIZE;
+ if (dev_attr->max_dpi)
+ dpit->max = min_t(u32, dpit->max, dev_attr->max_dpi);
- dpit->app_tbl = kcalloc(dpit->max, sizeof(void *), GFP_KERNEL);
+ dpit->app_tbl = kcalloc(dpit->max, sizeof(void *), GFP_KERNEL);
if (!dpit->app_tbl)
- goto unmap_io;
+ return -ENOMEM;
bytes = dpit->max >> 3;
if (!bytes)
@@ -797,17 +815,14 @@ static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res,
if (!dpit->tbl) {
kfree(dpit->app_tbl);
dpit->app_tbl = NULL;
- goto unmap_io;
+ return -ENOMEM;
}
memset((u8 *)dpit->tbl, 0xFF, bytes);
+ dpit->priv_db = dpit->ucreg.bar_reg + dpit->ucreg.offset;
return 0;
-unmap_io:
- pci_iounmap(res->pdev, dpit->dbr_bar_reg_iomem);
- dpit->dbr_bar_reg_iomem = NULL;
- return -ENOMEM;
}
/* Stats */
@@ -874,7 +889,7 @@ int bnxt_qplib_alloc_res(struct bnxt_qplib_res *res, struct pci_dev *pdev,
if (rc)
goto fail;
- rc = bnxt_qplib_alloc_dpi_tbl(res, &res->dpi_tbl, dev_attr->l2_db_size);
+ rc = bnxt_qplib_alloc_dpi_tbl(res, dev_attr);
if (rc)
goto fail;
@@ -884,6 +899,46 @@ fail:
return rc;
}
+void bnxt_qplib_unmap_db_bar(struct bnxt_qplib_res *res)
+{
+ struct bnxt_qplib_reg_desc *reg;
+
+ reg = &res->dpi_tbl.ucreg;
+ if (reg->bar_reg)
+ pci_iounmap(res->pdev, reg->bar_reg);
+ reg->bar_reg = NULL;
+ reg->bar_base = 0;
+ reg->len = 0;
+ reg->bar_id = 0;
+}
+
+int bnxt_qplib_map_db_bar(struct bnxt_qplib_res *res)
+{
+ struct bnxt_qplib_reg_desc *ucreg;
+ struct bnxt_qplib_reg_desc *wcreg;
+
+ wcreg = &res->dpi_tbl.wcreg;
+ wcreg->bar_id = RCFW_DBR_PCI_BAR_REGION;
+ wcreg->bar_base = pci_resource_start(res->pdev, wcreg->bar_id);
+
+ ucreg = &res->dpi_tbl.ucreg;
+ ucreg->bar_id = RCFW_DBR_PCI_BAR_REGION;
+ ucreg->bar_base = pci_resource_start(res->pdev, ucreg->bar_id);
+ ucreg->len = ucreg->offset + PAGE_SIZE;
+ if (!ucreg->len || ((ucreg->len & (PAGE_SIZE - 1)) != 0)) {
+ dev_err(&res->pdev->dev, "QPLIB: invalid dbr length %d",
+ (int)ucreg->len);
+ return -EINVAL;
+ }
+ ucreg->bar_reg = ioremap(ucreg->bar_base, ucreg->len);
+ if (!ucreg->bar_reg) {
+ dev_err(&res->pdev->dev, "privileged dpi map failed!");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
int bnxt_qplib_determine_atomics(struct pci_dev *dev)
{
int comp;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.h b/drivers/infiniband/hw/bnxt_re/qplib_res.h
index 982e2c96dac2..d850a553821e 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.h
@@ -47,7 +47,7 @@ extern const struct bnxt_qplib_gid bnxt_qplib_gid_zero;
struct bnxt_qplib_drv_modes {
u8 wqe_mode;
- /* Other modes to follow here */
+ bool db_push;
};
struct bnxt_qplib_chip_ctx {
@@ -55,9 +55,14 @@ struct bnxt_qplib_chip_ctx {
u8 chip_rev;
u8 chip_metal;
u16 hw_stats_size;
+ u16 hwrm_cmd_max_timeout;
struct bnxt_qplib_drv_modes modes;
+ u64 hwrm_intf_ver;
};
+#define BNXT_QPLIB_DBR_PF_DB_OFFSET 0x10000
+#define BNXT_QPLIB_DBR_VF_DB_OFFSET 0x4000
+
#define PTR_CNT_PER_PG (PAGE_SIZE / sizeof(void *))
#define PTR_MAX_IDX_PER_PG (PTR_CNT_PER_PG - 1)
#define PTR_PG(x) (((x) & ~PTR_MAX_IDX_PER_PG) / PTR_CNT_PER_PG)
@@ -109,6 +114,7 @@ enum bnxt_qplib_hwrm_pg_size {
struct bnxt_qplib_reg_desc {
u8 bar_id;
resource_size_t bar_base;
+ unsigned long offset;
void __iomem *bar_reg;
size_t len;
};
@@ -185,18 +191,27 @@ struct bnxt_qplib_sgid_tbl {
u8 *vlan;
};
+enum {
+ BNXT_QPLIB_DPI_TYPE_KERNEL = 0,
+ BNXT_QPLIB_DPI_TYPE_UC = 1,
+ BNXT_QPLIB_DPI_TYPE_WC = 2
+};
+
struct bnxt_qplib_dpi {
u32 dpi;
+ u32 bit;
void __iomem *dbr;
u64 umdbr;
+ u8 type;
};
struct bnxt_qplib_dpi_tbl {
void **app_tbl;
unsigned long *tbl;
u16 max;
- void __iomem *dbr_bar_reg_iomem;
- u64 unmapped_dbr;
+ struct bnxt_qplib_reg_desc ucreg; /* Hold entire DB bar. */
+ struct bnxt_qplib_reg_desc wcreg;
+ void __iomem *priv_db;
};
struct bnxt_qplib_stats {
@@ -241,7 +256,6 @@ struct bnxt_qplib_ctx {
struct bnxt_qplib_tqm_ctx tqm_ctx;
struct bnxt_qplib_stats stats;
struct bnxt_qplib_vf_res vf_res;
- u64 hwrm_intf_ver;
};
struct bnxt_qplib_res {
@@ -253,6 +267,8 @@ struct bnxt_qplib_res {
struct bnxt_qplib_pd_tbl pd_tbl;
struct bnxt_qplib_sgid_tbl sgid_tbl;
struct bnxt_qplib_dpi_tbl dpi_tbl;
+ /* To protect the dpi table bit map */
+ struct mutex dpi_tbl_lock;
bool prio;
bool is_vf;
};
@@ -344,11 +360,10 @@ int bnxt_qplib_alloc_pd(struct bnxt_qplib_pd_tbl *pd_tbl,
int bnxt_qplib_dealloc_pd(struct bnxt_qplib_res *res,
struct bnxt_qplib_pd_tbl *pd_tbl,
struct bnxt_qplib_pd *pd);
-int bnxt_qplib_alloc_dpi(struct bnxt_qplib_dpi_tbl *dpit,
- struct bnxt_qplib_dpi *dpi,
- void *app);
+int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res,
+ struct bnxt_qplib_dpi *dpi,
+ void *app, u8 type);
int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res,
- struct bnxt_qplib_dpi_tbl *dpi_tbl,
struct bnxt_qplib_dpi *dpi);
void bnxt_qplib_cleanup_res(struct bnxt_qplib_res *res);
int bnxt_qplib_init_res(struct bnxt_qplib_res *res);
@@ -361,6 +376,9 @@ void bnxt_qplib_free_ctx(struct bnxt_qplib_res *res,
int bnxt_qplib_alloc_ctx(struct bnxt_qplib_res *res,
struct bnxt_qplib_ctx *ctx,
bool virt_fn, bool is_p5);
+int bnxt_qplib_map_db_bar(struct bnxt_qplib_res *res);
+void bnxt_qplib_unmap_db_bar(struct bnxt_qplib_res *res);
+
int bnxt_qplib_determine_atomics(struct pci_dev *dev);
static inline void bnxt_qplib_hwq_incr_prod(struct bnxt_qplib_hwq *hwq, u32 cnt)
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
index b967a17a44be..ab45f9d4bb02 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
@@ -170,6 +170,9 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc);
}
+ if (rcfw->res->cctx->hwrm_intf_ver >= HWRM_VERSION_DEV_ATTR_MAX_DPI)
+ attr->max_dpi = le32_to_cpu(sb->max_dpi);
+
attr->is_atomic = bnxt_qplib_is_atomic_cap(rcfw);
bail:
bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf);
@@ -233,10 +236,6 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
int index;
- if (!sgid_tbl) {
- dev_err(&res->pdev->dev, "SGID table not allocated\n");
- return -EINVAL;
- }
/* Do we need a sgid_lock here? */
if (!sgid_tbl->active) {
dev_err(&res->pdev->dev, "SGID table has no active entries\n");
@@ -297,10 +296,6 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
int i, free_idx;
- if (!sgid_tbl) {
- dev_err(&res->pdev->dev, "SGID table not allocated\n");
- return -EINVAL;
- }
/* Do we need a sgid_lock here? */
if (sgid_tbl->active == sgid_tbl->max) {
dev_err(&res->pdev->dev, "SGID table is full\n");
@@ -468,13 +463,14 @@ int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
return 0;
}
-void bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
- bool block)
+int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
+ bool block)
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct creq_destroy_ah_resp resp = {};
struct bnxt_qplib_cmdqmsg msg = {};
struct cmdq_destroy_ah req = {};
+ int rc;
/* Clean up the AH table in the device */
bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
@@ -485,7 +481,8 @@ void bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req),
sizeof(resp), block);
- bnxt_qplib_rcfw_send_message(rcfw, &msg);
+ rc = bnxt_qplib_rcfw_send_message(rcfw, &msg);
+ return rc;
}
/* MRW */
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.h b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
index 5de874659cdf..264ef3cedc45 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
@@ -72,6 +72,7 @@ struct bnxt_qplib_dev_attr {
u8 tqm_alloc_reqs[MAX_TQM_ALLOC_REQ];
bool is_atomic;
u16 dev_cap_flags;
+ u32 max_dpi;
};
struct bnxt_qplib_pd {
@@ -327,8 +328,8 @@ int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res,
struct bnxt_qplib_ctx *ctx);
int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
bool block);
-void bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
- bool block);
+int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
+ bool block);
int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res,
struct bnxt_qplib_mrw *mrw);
int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw,
diff --git a/drivers/infiniband/hw/erdma/erdma.h b/drivers/infiniband/hw/erdma/erdma.h
index e819e4032490..f190111840e9 100644
--- a/drivers/infiniband/hw/erdma/erdma.h
+++ b/drivers/infiniband/hw/erdma/erdma.h
@@ -128,13 +128,8 @@ struct erdma_devattr {
int numa_node;
enum erdma_cc_alg cc;
- u32 grp_num;
u32 irq_num;
- bool disable_dwqe;
- u16 dwqe_pages;
- u16 dwqe_entries;
-
u32 max_qp;
u32 max_send_wr;
u32 max_recv_wr;
@@ -215,15 +210,6 @@ struct erdma_dev {
u32 next_alloc_qpn;
u32 next_alloc_cqn;
- spinlock_t db_bitmap_lock;
- /* We provide max 64 uContexts that each has one SQ doorbell Page. */
- DECLARE_BITMAP(sdb_page, ERDMA_DWQE_TYPE0_CNT);
- /*
- * We provide max 496 uContexts that each has one SQ normal Db,
- * and one directWQE db.
- */
- DECLARE_BITMAP(sdb_entry, ERDMA_DWQE_TYPE1_CNT);
-
atomic_t num_ctx;
struct list_head cep_list;
};
@@ -268,6 +254,8 @@ static inline u32 erdma_reg_read32_filed(struct erdma_dev *dev, u32 reg,
return FIELD_GET(filed_mask, val);
}
+#define ERDMA_GET(val, name) FIELD_GET(ERDMA_CMD_##name##_MASK, val)
+
int erdma_cmdq_init(struct erdma_dev *dev);
void erdma_finish_cmdq_init(struct erdma_dev *dev);
void erdma_cmdq_destroy(struct erdma_dev *dev);
diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
index 76ce2856be28..a882b57aa118 100644
--- a/drivers/infiniband/hw/erdma/erdma_hw.h
+++ b/drivers/infiniband/hw/erdma/erdma_hw.h
@@ -82,19 +82,6 @@
#define ERDMA_BAR_CQDB_SPACE_OFFSET \
(ERDMA_BAR_RQDB_SPACE_OFFSET + ERDMA_BAR_RQDB_SPACE_SIZE)
-/* Doorbell page resources related. */
-/*
- * Max # of parallelly issued directSQE is 3072 per device,
- * hardware organizes this into 24 group, per group has 128 credits.
- */
-#define ERDMA_DWQE_MAX_GRP_CNT 24
-#define ERDMA_DWQE_NUM_PER_GRP 128
-
-#define ERDMA_DWQE_TYPE0_CNT 64
-#define ERDMA_DWQE_TYPE1_CNT 496
-/* type1 DB contains 2 DBs, takes 256Byte. */
-#define ERDMA_DWQE_TYPE1_CNT_PER_PAGE 16
-
#define ERDMA_SDB_SHARED_PAGE_INDEX 95
/* Doorbell related. */
@@ -134,7 +121,7 @@
/* CMDQ related. */
#define ERDMA_CMDQ_MAX_OUTSTANDING 128
-#define ERDMA_CMDQ_SQE_SIZE 64
+#define ERDMA_CMDQ_SQE_SIZE 128
/* cmdq sub module definition. */
enum CMDQ_WQE_SUB_MOD {
@@ -159,6 +146,9 @@ enum CMDQ_COMMON_OPCODE {
CMDQ_OPCODE_DESTROY_EQ = 1,
CMDQ_OPCODE_QUERY_FW_INFO = 2,
CMDQ_OPCODE_CONF_MTU = 3,
+ CMDQ_OPCODE_CONF_DEVICE = 5,
+ CMDQ_OPCODE_ALLOC_DB = 8,
+ CMDQ_OPCODE_FREE_DB = 9,
};
/* cmdq-SQE HDR */
@@ -196,11 +186,41 @@ struct erdma_cmdq_destroy_eq_req {
u8 qtype;
};
+/* config device cfg */
+#define ERDMA_CMD_CONFIG_DEVICE_PS_EN_MASK BIT(31)
+#define ERDMA_CMD_CONFIG_DEVICE_PGSHIFT_MASK GENMASK(4, 0)
+
+struct erdma_cmdq_config_device_req {
+ u64 hdr;
+ u32 cfg;
+ u32 rsvd[5];
+};
+
struct erdma_cmdq_config_mtu_req {
u64 hdr;
u32 mtu;
};
+/* ext db requests(alloc and free) cfg */
+#define ERDMA_CMD_EXT_DB_CQ_EN_MASK BIT(2)
+#define ERDMA_CMD_EXT_DB_RQ_EN_MASK BIT(1)
+#define ERDMA_CMD_EXT_DB_SQ_EN_MASK BIT(0)
+
+struct erdma_cmdq_ext_db_req {
+ u64 hdr;
+ u32 cfg;
+ u16 rdb_off;
+ u16 sdb_off;
+ u16 rsvd0;
+ u16 cdb_off;
+ u32 rsvd1[3];
+};
+
+/* alloc db response qword 0 definition */
+#define ERDMA_CMD_ALLOC_DB_RESP_RDB_MASK GENMASK_ULL(63, 48)
+#define ERDMA_CMD_ALLOC_DB_RESP_CDB_MASK GENMASK_ULL(47, 32)
+#define ERDMA_CMD_ALLOC_DB_RESP_SDB_MASK GENMASK_ULL(15, 0)
+
/* create_cq cfg0 */
#define ERDMA_CMD_CREATE_CQ_DEPTH_MASK GENMASK(31, 24)
#define ERDMA_CMD_CREATE_CQ_PAGESIZE_MASK GENMASK(23, 20)
@@ -209,8 +229,12 @@ struct erdma_cmdq_config_mtu_req {
/* create_cq cfg1 */
#define ERDMA_CMD_CREATE_CQ_MTT_CNT_MASK GENMASK(31, 16)
#define ERDMA_CMD_CREATE_CQ_MTT_TYPE_MASK BIT(15)
+#define ERDMA_CMD_CREATE_CQ_MTT_DB_CFG_MASK BIT(11)
#define ERDMA_CMD_CREATE_CQ_EQN_MASK GENMASK(9, 0)
+/* create_cq cfg2 */
+#define ERDMA_CMD_CREATE_CQ_DB_CFG_MASK GENMASK(15, 0)
+
struct erdma_cmdq_create_cq_req {
u64 hdr;
u32 cfg0;
@@ -219,6 +243,7 @@ struct erdma_cmdq_create_cq_req {
u32 cfg1;
u64 cq_db_info_addr;
u32 first_page_offset;
+ u32 cfg2;
};
/* regmr/deregmr cfg0 */
@@ -278,6 +303,7 @@ struct erdma_cmdq_modify_qp_req {
/* create qp cqn_mtt_cfg */
#define ERDMA_CMD_CREATE_QP_PAGE_SIZE_MASK GENMASK(31, 28)
+#define ERDMA_CMD_CREATE_QP_DB_CFG_MASK BIT(25)
#define ERDMA_CMD_CREATE_QP_CQN_MASK GENMASK(23, 0)
/* create qp mtt_cfg */
@@ -285,6 +311,10 @@ struct erdma_cmdq_modify_qp_req {
#define ERDMA_CMD_CREATE_QP_MTT_CNT_MASK GENMASK(11, 1)
#define ERDMA_CMD_CREATE_QP_MTT_TYPE_MASK BIT(0)
+/* create qp db cfg */
+#define ERDMA_CMD_CREATE_QP_SQDB_CFG_MASK GENMASK(31, 16)
+#define ERDMA_CMD_CREATE_QP_RQDB_CFG_MASK GENMASK(15, 0)
+
#define ERDMA_CMDQ_CREATE_QP_RESP_COOKIE_MASK GENMASK_ULL(31, 0)
struct erdma_cmdq_create_qp_req {
@@ -299,6 +329,11 @@ struct erdma_cmdq_create_qp_req {
u32 rq_mtt_cfg;
u64 sq_db_info_dma_addr;
u64 rq_db_info_dma_addr;
+
+ u64 sq_mtt_entry[3];
+ u64 rq_mtt_entry[3];
+
+ u32 db_cfg;
};
struct erdma_cmdq_destroy_qp_req {
@@ -329,6 +364,7 @@ struct erdma_cmdq_reflush_req {
enum {
ERDMA_DEV_CAP_FLAGS_ATOMIC = 1 << 7,
+ ERDMA_DEV_CAP_FLAGS_EXTEND_DB = 1 << 3,
};
#define ERDMA_CMD_INFO0_FW_VER_MASK GENMASK_ULL(31, 0)
diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/infiniband/hw/erdma/erdma_main.c
index 7c74abeee864..0880c79a978c 100644
--- a/drivers/infiniband/hw/erdma/erdma_main.c
+++ b/drivers/infiniband/hw/erdma/erdma_main.c
@@ -130,33 +130,6 @@ static irqreturn_t erdma_comm_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
-static void erdma_dwqe_resource_init(struct erdma_dev *dev)
-{
- int total_pages, type0, type1;
-
- dev->attrs.grp_num = erdma_reg_read32(dev, ERDMA_REGS_GRP_NUM_REG);
-
- if (dev->attrs.grp_num < 4)
- dev->attrs.disable_dwqe = true;
- else
- dev->attrs.disable_dwqe = false;
-
- /* One page contains 4 goups. */
- total_pages = dev->attrs.grp_num * 4;
-
- if (dev->attrs.grp_num >= ERDMA_DWQE_MAX_GRP_CNT) {
- dev->attrs.grp_num = ERDMA_DWQE_MAX_GRP_CNT;
- type0 = ERDMA_DWQE_TYPE0_CNT;
- type1 = ERDMA_DWQE_TYPE1_CNT / ERDMA_DWQE_TYPE1_CNT_PER_PAGE;
- } else {
- type1 = total_pages / 3;
- type0 = total_pages - type1 - 1;
- }
-
- dev->attrs.dwqe_pages = type0;
- dev->attrs.dwqe_entries = type1 * ERDMA_DWQE_TYPE1_CNT_PER_PAGE;
-}
-
static int erdma_request_vectors(struct erdma_dev *dev)
{
int expect_irq_num = min(num_possible_cpus() + 1, ERDMA_NUM_MSIX_VEC);
@@ -199,8 +172,6 @@ static int erdma_device_init(struct erdma_dev *dev, struct pci_dev *pdev)
{
int ret;
- erdma_dwqe_resource_init(dev);
-
ret = dma_set_mask_and_coherent(&pdev->dev,
DMA_BIT_MASK(ERDMA_PCI_WIDTH));
if (ret)
@@ -426,6 +397,22 @@ static int erdma_dev_attrs_init(struct erdma_dev *dev)
return err;
}
+static int erdma_device_config(struct erdma_dev *dev)
+{
+ struct erdma_cmdq_config_device_req req = {};
+
+ if (!(dev->attrs.cap_flags & ERDMA_DEV_CAP_FLAGS_EXTEND_DB))
+ return 0;
+
+ erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_COMMON,
+ CMDQ_OPCODE_CONF_DEVICE);
+
+ req.cfg = FIELD_PREP(ERDMA_CMD_CONFIG_DEVICE_PGSHIFT_MASK, PAGE_SHIFT) |
+ FIELD_PREP(ERDMA_CMD_CONFIG_DEVICE_PS_EN_MASK, 1);
+
+ return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+}
+
static int erdma_res_cb_init(struct erdma_dev *dev)
{
int i, j;
@@ -512,6 +499,10 @@ static int erdma_ib_device_add(struct pci_dev *pdev)
if (ret)
return ret;
+ ret = erdma_device_config(dev);
+ if (ret)
+ return ret;
+
ibdev->node_type = RDMA_NODE_RNIC;
memcpy(ibdev->node_desc, ERDMA_NODE_DESC, sizeof(ERDMA_NODE_DESC));
@@ -537,10 +528,6 @@ static int erdma_ib_device_add(struct pci_dev *pdev)
if (ret)
return ret;
- spin_lock_init(&dev->db_bitmap_lock);
- bitmap_zero(dev->sdb_page, ERDMA_DWQE_TYPE0_CNT);
- bitmap_zero(dev->sdb_entry, ERDMA_DWQE_TYPE1_CNT);
-
atomic_set(&dev->num_ctx, 0);
mac = erdma_reg_read32(dev, ERDMA_REGS_NETDEV_MAC_L_REG);
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
index 83e1b0d55977..517676fbb8b1 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
@@ -19,10 +19,11 @@
#include "erdma_cm.h"
#include "erdma_verbs.h"
-static int create_qp_cmd(struct erdma_dev *dev, struct erdma_qp *qp)
+static int create_qp_cmd(struct erdma_ucontext *uctx, struct erdma_qp *qp)
{
- struct erdma_cmdq_create_qp_req req;
+ struct erdma_dev *dev = to_edev(qp->ibqp.device);
struct erdma_pd *pd = to_epd(qp->ibqp.pd);
+ struct erdma_cmdq_create_qp_req req;
struct erdma_uqp *user_qp;
u64 resp0, resp1;
int err;
@@ -93,6 +94,16 @@ static int create_qp_cmd(struct erdma_dev *dev, struct erdma_qp *qp)
req.sq_db_info_dma_addr = user_qp->sq_db_info_dma_addr;
req.rq_db_info_dma_addr = user_qp->rq_db_info_dma_addr;
+
+ if (uctx->ext_db.enable) {
+ req.sq_cqn_mtt_cfg |=
+ FIELD_PREP(ERDMA_CMD_CREATE_QP_DB_CFG_MASK, 1);
+ req.db_cfg =
+ FIELD_PREP(ERDMA_CMD_CREATE_QP_SQDB_CFG_MASK,
+ uctx->ext_db.sdb_off) |
+ FIELD_PREP(ERDMA_CMD_CREATE_QP_RQDB_CFG_MASK,
+ uctx->ext_db.rdb_off);
+ }
}
err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &resp0,
@@ -146,11 +157,12 @@ post_cmd:
return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
}
-static int create_cq_cmd(struct erdma_dev *dev, struct erdma_cq *cq)
+static int create_cq_cmd(struct erdma_ucontext *uctx, struct erdma_cq *cq)
{
+ struct erdma_dev *dev = to_edev(cq->ibcq.device);
struct erdma_cmdq_create_cq_req req;
- u32 page_size;
struct erdma_mem *mtt;
+ u32 page_size;
erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
CMDQ_OPCODE_CREATE_CQ);
@@ -192,6 +204,13 @@ static int create_cq_cmd(struct erdma_dev *dev, struct erdma_cq *cq)
req.first_page_offset = mtt->page_offset;
req.cq_db_info_addr = cq->user_cq.db_info_dma_addr;
+
+ if (uctx->ext_db.enable) {
+ req.cfg1 |= FIELD_PREP(
+ ERDMA_CMD_CREATE_CQ_MTT_DB_CFG_MASK, 1);
+ req.cfg2 = FIELD_PREP(ERDMA_CMD_CREATE_CQ_DB_CFG_MASK,
+ uctx->ext_db.cdb_off);
+ }
}
return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
@@ -753,7 +772,7 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
qp->attrs.state = ERDMA_QP_STATE_IDLE;
INIT_DELAYED_WORK(&qp->reflush_dwork, erdma_flush_worker);
- ret = create_qp_cmd(dev, qp);
+ ret = create_qp_cmd(uctx, qp);
if (ret)
goto err_out_cmd;
@@ -1130,62 +1149,73 @@ void erdma_mmap_free(struct rdma_user_mmap_entry *rdma_entry)
kfree(entry);
}
-#define ERDMA_SDB_PAGE 0
-#define ERDMA_SDB_ENTRY 1
-#define ERDMA_SDB_SHARED 2
-
-static void alloc_db_resources(struct erdma_dev *dev,
- struct erdma_ucontext *ctx)
+static int alloc_db_resources(struct erdma_dev *dev, struct erdma_ucontext *ctx,
+ bool ext_db_en)
{
- u32 bitmap_idx;
- struct erdma_devattr *attrs = &dev->attrs;
-
- if (attrs->disable_dwqe)
- goto alloc_normal_db;
-
- /* Try to alloc independent SDB page. */
- spin_lock(&dev->db_bitmap_lock);
- bitmap_idx = find_first_zero_bit(dev->sdb_page, attrs->dwqe_pages);
- if (bitmap_idx != attrs->dwqe_pages) {
- set_bit(bitmap_idx, dev->sdb_page);
- spin_unlock(&dev->db_bitmap_lock);
-
- ctx->sdb_type = ERDMA_SDB_PAGE;
- ctx->sdb_idx = bitmap_idx;
- ctx->sdb_page_idx = bitmap_idx;
- ctx->sdb = dev->func_bar_addr + ERDMA_BAR_SQDB_SPACE_OFFSET +
- (bitmap_idx << PAGE_SHIFT);
- ctx->sdb_page_off = 0;
+ struct erdma_cmdq_ext_db_req req = {};
+ u64 val0, val1;
+ int ret;
- return;
+ /*
+ * CAP_SYS_RAWIO is required if hardware does not support extend
+ * doorbell mechanism.
+ */
+ if (!ext_db_en && !capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ if (!ext_db_en) {
+ ctx->sdb = dev->func_bar_addr + ERDMA_BAR_SQDB_SPACE_OFFSET;
+ ctx->rdb = dev->func_bar_addr + ERDMA_BAR_RQDB_SPACE_OFFSET;
+ ctx->cdb = dev->func_bar_addr + ERDMA_BAR_CQDB_SPACE_OFFSET;
+ return 0;
}
- bitmap_idx = find_first_zero_bit(dev->sdb_entry, attrs->dwqe_entries);
- if (bitmap_idx != attrs->dwqe_entries) {
- set_bit(bitmap_idx, dev->sdb_entry);
- spin_unlock(&dev->db_bitmap_lock);
+ erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_COMMON,
+ CMDQ_OPCODE_ALLOC_DB);
+
+ req.cfg = FIELD_PREP(ERDMA_CMD_EXT_DB_CQ_EN_MASK, 1) |
+ FIELD_PREP(ERDMA_CMD_EXT_DB_RQ_EN_MASK, 1) |
+ FIELD_PREP(ERDMA_CMD_EXT_DB_SQ_EN_MASK, 1);
+
+ ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &val0, &val1);
+ if (ret)
+ return ret;
- ctx->sdb_type = ERDMA_SDB_ENTRY;
- ctx->sdb_idx = bitmap_idx;
- ctx->sdb_page_idx = attrs->dwqe_pages +
- bitmap_idx / ERDMA_DWQE_TYPE1_CNT_PER_PAGE;
- ctx->sdb_page_off = bitmap_idx % ERDMA_DWQE_TYPE1_CNT_PER_PAGE;
+ ctx->ext_db.enable = true;
+ ctx->ext_db.sdb_off = ERDMA_GET(val0, ALLOC_DB_RESP_SDB);
+ ctx->ext_db.rdb_off = ERDMA_GET(val0, ALLOC_DB_RESP_RDB);
+ ctx->ext_db.cdb_off = ERDMA_GET(val0, ALLOC_DB_RESP_CDB);
- ctx->sdb = dev->func_bar_addr + ERDMA_BAR_SQDB_SPACE_OFFSET +
- (ctx->sdb_page_idx << PAGE_SHIFT);
+ ctx->sdb = dev->func_bar_addr + (ctx->ext_db.sdb_off << PAGE_SHIFT);
+ ctx->cdb = dev->func_bar_addr + (ctx->ext_db.rdb_off << PAGE_SHIFT);
+ ctx->rdb = dev->func_bar_addr + (ctx->ext_db.cdb_off << PAGE_SHIFT);
+
+ return 0;
+}
+static void free_db_resources(struct erdma_dev *dev, struct erdma_ucontext *ctx)
+{
+ struct erdma_cmdq_ext_db_req req = {};
+ int ret;
+
+ if (!ctx->ext_db.enable)
return;
- }
- spin_unlock(&dev->db_bitmap_lock);
+ erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_COMMON,
+ CMDQ_OPCODE_FREE_DB);
+
+ req.cfg = FIELD_PREP(ERDMA_CMD_EXT_DB_CQ_EN_MASK, 1) |
+ FIELD_PREP(ERDMA_CMD_EXT_DB_RQ_EN_MASK, 1) |
+ FIELD_PREP(ERDMA_CMD_EXT_DB_SQ_EN_MASK, 1);
-alloc_normal_db:
- ctx->sdb_type = ERDMA_SDB_SHARED;
- ctx->sdb_idx = 0;
- ctx->sdb_page_idx = ERDMA_SDB_SHARED_PAGE_INDEX;
- ctx->sdb_page_off = 0;
+ req.sdb_off = ctx->ext_db.sdb_off;
+ req.rdb_off = ctx->ext_db.rdb_off;
+ req.cdb_off = ctx->ext_db.cdb_off;
- ctx->sdb = dev->func_bar_addr + (ctx->sdb_page_idx << PAGE_SHIFT);
+ ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+ if (ret)
+ ibdev_err_ratelimited(&dev->ibdev,
+ "free db resources failed %d", ret);
}
static void erdma_uctx_user_mmap_entries_remove(struct erdma_ucontext *uctx)
@@ -1207,71 +1237,67 @@ int erdma_alloc_ucontext(struct ib_ucontext *ibctx, struct ib_udata *udata)
goto err_out;
}
- INIT_LIST_HEAD(&ctx->dbrecords_page_list);
- mutex_init(&ctx->dbrecords_page_mutex);
-
- alloc_db_resources(dev, ctx);
-
- ctx->rdb = dev->func_bar_addr + ERDMA_BAR_RQDB_SPACE_OFFSET;
- ctx->cdb = dev->func_bar_addr + ERDMA_BAR_CQDB_SPACE_OFFSET;
-
if (udata->outlen < sizeof(uresp)) {
ret = -EINVAL;
goto err_out;
}
+ INIT_LIST_HEAD(&ctx->dbrecords_page_list);
+ mutex_init(&ctx->dbrecords_page_mutex);
+
+ ret = alloc_db_resources(dev, ctx,
+ !!(dev->attrs.cap_flags &
+ ERDMA_DEV_CAP_FLAGS_EXTEND_DB));
+ if (ret)
+ goto err_out;
+
ctx->sq_db_mmap_entry = erdma_user_mmap_entry_insert(
ctx, (void *)ctx->sdb, PAGE_SIZE, ERDMA_MMAP_IO_NC, &uresp.sdb);
if (!ctx->sq_db_mmap_entry) {
ret = -ENOMEM;
- goto err_out;
+ goto err_free_ext_db;
}
ctx->rq_db_mmap_entry = erdma_user_mmap_entry_insert(
ctx, (void *)ctx->rdb, PAGE_SIZE, ERDMA_MMAP_IO_NC, &uresp.rdb);
if (!ctx->rq_db_mmap_entry) {
ret = -EINVAL;
- goto err_out;
+ goto err_put_mmap_entries;
}
ctx->cq_db_mmap_entry = erdma_user_mmap_entry_insert(
ctx, (void *)ctx->cdb, PAGE_SIZE, ERDMA_MMAP_IO_NC, &uresp.cdb);
if (!ctx->cq_db_mmap_entry) {
ret = -EINVAL;
- goto err_out;
+ goto err_put_mmap_entries;
}
uresp.dev_id = dev->pdev->device;
- uresp.sdb_type = ctx->sdb_type;
- uresp.sdb_offset = ctx->sdb_page_off;
ret = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
if (ret)
- goto err_out;
+ goto err_put_mmap_entries;
return 0;
-err_out:
+err_put_mmap_entries:
erdma_uctx_user_mmap_entries_remove(ctx);
+
+err_free_ext_db:
+ free_db_resources(dev, ctx);
+
+err_out:
atomic_dec(&dev->num_ctx);
return ret;
}
void erdma_dealloc_ucontext(struct ib_ucontext *ibctx)
{
- struct erdma_ucontext *ctx = to_ectx(ibctx);
struct erdma_dev *dev = to_edev(ibctx->device);
-
- spin_lock(&dev->db_bitmap_lock);
- if (ctx->sdb_type == ERDMA_SDB_PAGE)
- clear_bit(ctx->sdb_idx, dev->sdb_page);
- else if (ctx->sdb_type == ERDMA_SDB_ENTRY)
- clear_bit(ctx->sdb_idx, dev->sdb_entry);
+ struct erdma_ucontext *ctx = to_ectx(ibctx);
erdma_uctx_user_mmap_entries_remove(ctx);
-
- spin_unlock(&dev->db_bitmap_lock);
-
+ free_db_resources(dev, ctx);
atomic_dec(&dev->num_ctx);
}
@@ -1438,7 +1464,7 @@ int erdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
goto err_out_xa;
}
- ret = create_cq_cmd(dev, cq);
+ ret = create_cq_cmd(ctx, cq);
if (ret)
goto err_free_res;
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h
index 131cf5f40982..429fc3063f98 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.h
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
@@ -31,13 +31,18 @@ struct erdma_user_mmap_entry {
u8 mmap_flag;
};
+struct erdma_ext_db_info {
+ bool enable;
+ u16 sdb_off;
+ u16 rdb_off;
+ u16 cdb_off;
+};
+
struct erdma_ucontext {
struct ib_ucontext ibucontext;
- u32 sdb_type;
- u32 sdb_idx;
- u32 sdb_page_idx;
- u32 sdb_page_off;
+ struct erdma_ext_db_info ext_db;
+
u64 sdb;
u64 rdb;
u64 cdb;
diff --git a/drivers/infiniband/hw/hfi1/ipoib_tx.c b/drivers/infiniband/hw/hfi1/ipoib_tx.c
index 8973a081d641..e7d831330278 100644
--- a/drivers/infiniband/hw/hfi1/ipoib_tx.c
+++ b/drivers/infiniband/hw/hfi1/ipoib_tx.c
@@ -215,11 +215,11 @@ static int hfi1_ipoib_build_ulp_payload(struct ipoib_txreq *tx,
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
ret = sdma_txadd_page(dd,
- NULL,
txreq,
skb_frag_page(frag),
frag->bv_offset,
- skb_frag_size(frag));
+ skb_frag_size(frag),
+ NULL, NULL, NULL);
if (unlikely(ret))
break;
}
diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.c b/drivers/infiniband/hw/hfi1/mmu_rb.c
index 1cea8b0c78e0..7a51f7d73b61 100644
--- a/drivers/infiniband/hw/hfi1/mmu_rb.c
+++ b/drivers/infiniband/hw/hfi1/mmu_rb.c
@@ -19,8 +19,7 @@ static int mmu_notifier_range_start(struct mmu_notifier *,
const struct mmu_notifier_range *);
static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *,
unsigned long, unsigned long);
-static void do_remove(struct mmu_rb_handler *handler,
- struct list_head *del_list);
+static void release_immediate(struct kref *refcount);
static void handle_remove(struct work_struct *work);
static const struct mmu_notifier_ops mn_opts = {
@@ -106,7 +105,11 @@ void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler)
}
spin_unlock_irqrestore(&handler->lock, flags);
- do_remove(handler, &del_list);
+ while (!list_empty(&del_list)) {
+ rbnode = list_first_entry(&del_list, struct mmu_rb_node, list);
+ list_del(&rbnode->list);
+ kref_put(&rbnode->refcount, release_immediate);
+ }
/* Now the mm may be freed. */
mmdrop(handler->mn.mm);
@@ -121,7 +124,7 @@ int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler,
unsigned long flags;
int ret = 0;
- trace_hfi1_mmu_rb_insert(mnode->addr, mnode->len);
+ trace_hfi1_mmu_rb_insert(mnode);
if (current->mm != handler->mn.mm)
return -EPERM;
@@ -134,12 +137,6 @@ int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler,
}
__mmu_int_rb_insert(mnode, &handler->root);
list_add_tail(&mnode->list, &handler->lru_list);
-
- ret = handler->ops->insert(handler->ops_arg, mnode);
- if (ret) {
- __mmu_int_rb_remove(mnode, &handler->root);
- list_del(&mnode->list); /* remove from LRU list */
- }
mnode->handler = handler;
unlock:
spin_unlock_irqrestore(&handler->lock, flags);
@@ -183,6 +180,49 @@ static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *handler,
return node;
}
+/*
+ * Must NOT call while holding mnode->handler->lock.
+ * mnode->handler->ops->remove() may sleep and mnode->handler->lock is a
+ * spinlock.
+ */
+static void release_immediate(struct kref *refcount)
+{
+ struct mmu_rb_node *mnode =
+ container_of(refcount, struct mmu_rb_node, refcount);
+ trace_hfi1_mmu_release_node(mnode);
+ mnode->handler->ops->remove(mnode->handler->ops_arg, mnode);
+}
+
+/* Caller must hold mnode->handler->lock */
+static void release_nolock(struct kref *refcount)
+{
+ struct mmu_rb_node *mnode =
+ container_of(refcount, struct mmu_rb_node, refcount);
+ list_move(&mnode->list, &mnode->handler->del_list);
+ queue_work(mnode->handler->wq, &mnode->handler->del_work);
+}
+
+/*
+ * struct mmu_rb_node->refcount kref_put() callback.
+ * Adds mmu_rb_node to mmu_rb_node->handler->del_list and queues
+ * handler->del_work on handler->wq.
+ * Does not remove mmu_rb_node from handler->lru_list or handler->rb_root.
+ * Acquires mmu_rb_node->handler->lock; do not call while already holding
+ * handler->lock.
+ */
+void hfi1_mmu_rb_release(struct kref *refcount)
+{
+ struct mmu_rb_node *mnode =
+ container_of(refcount, struct mmu_rb_node, refcount);
+ struct mmu_rb_handler *handler = mnode->handler;
+ unsigned long flags;
+
+ spin_lock_irqsave(&handler->lock, flags);
+ list_move(&mnode->list, &mnode->handler->del_list);
+ spin_unlock_irqrestore(&handler->lock, flags);
+ queue_work(handler->wq, &handler->del_work);
+}
+
void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg)
{
struct mmu_rb_node *rbnode, *ptr;
@@ -197,6 +237,10 @@ void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg)
spin_lock_irqsave(&handler->lock, flags);
list_for_each_entry_safe(rbnode, ptr, &handler->lru_list, list) {
+ /* refcount == 1 implies mmu_rb_handler has only rbnode ref */
+ if (kref_read(&rbnode->refcount) > 1)
+ continue;
+
if (handler->ops->evict(handler->ops_arg, rbnode, evict_arg,
&stop)) {
__mmu_int_rb_remove(rbnode, &handler->root);
@@ -209,7 +253,8 @@ void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg)
spin_unlock_irqrestore(&handler->lock, flags);
list_for_each_entry_safe(rbnode, ptr, &del_list, list) {
- handler->ops->remove(handler->ops_arg, rbnode);
+ trace_hfi1_mmu_rb_evict(rbnode);
+ kref_put(&rbnode->refcount, release_immediate);
}
}
@@ -221,7 +266,6 @@ static int mmu_notifier_range_start(struct mmu_notifier *mn,
struct rb_root_cached *root = &handler->root;
struct mmu_rb_node *node, *ptr = NULL;
unsigned long flags;
- bool added = false;
spin_lock_irqsave(&handler->lock, flags);
for (node = __mmu_int_rb_iter_first(root, range->start, range->end-1);
@@ -229,40 +273,18 @@ static int mmu_notifier_range_start(struct mmu_notifier *mn,
/* Guard against node removal. */
ptr = __mmu_int_rb_iter_next(node, range->start,
range->end - 1);
- trace_hfi1_mmu_mem_invalidate(node->addr, node->len);
- if (handler->ops->invalidate(handler->ops_arg, node)) {
- __mmu_int_rb_remove(node, root);
- /* move from LRU list to delete list */
- list_move(&node->list, &handler->del_list);
- added = true;
- }
+ trace_hfi1_mmu_mem_invalidate(node);
+ /* Remove from rb tree and lru_list. */
+ __mmu_int_rb_remove(node, root);
+ list_del_init(&node->list);
+ kref_put(&node->refcount, release_nolock);
}
spin_unlock_irqrestore(&handler->lock, flags);
- if (added)
- queue_work(handler->wq, &handler->del_work);
-
return 0;
}
/*
- * Call the remove function for the given handler and the list. This
- * is expected to be called with a delete list extracted from handler.
- * The caller should not be holding the handler lock.
- */
-static void do_remove(struct mmu_rb_handler *handler,
- struct list_head *del_list)
-{
- struct mmu_rb_node *node;
-
- while (!list_empty(del_list)) {
- node = list_first_entry(del_list, struct mmu_rb_node, list);
- list_del(&node->list);
- handler->ops->remove(handler->ops_arg, node);
- }
-}
-
-/*
* Work queue function to remove all nodes that have been queued up to
* be removed. The key feature is that mm->mmap_lock is not being held
* and the remove callback can sleep while taking it, if needed.
@@ -274,11 +296,17 @@ static void handle_remove(struct work_struct *work)
del_work);
struct list_head del_list;
unsigned long flags;
+ struct mmu_rb_node *node;
/* remove anything that is queued to get removed */
spin_lock_irqsave(&handler->lock, flags);
list_replace_init(&handler->del_list, &del_list);
spin_unlock_irqrestore(&handler->lock, flags);
- do_remove(handler, &del_list);
+ while (!list_empty(&del_list)) {
+ node = list_first_entry(&del_list, struct mmu_rb_node, list);
+ list_del(&node->list);
+ trace_hfi1_mmu_release_node(node);
+ handler->ops->remove(handler->ops_arg, node);
+ }
}
diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.h b/drivers/infiniband/hw/hfi1/mmu_rb.h
index c4da064188c9..751dc3fe1e02 100644
--- a/drivers/infiniband/hw/hfi1/mmu_rb.h
+++ b/drivers/infiniband/hw/hfi1/mmu_rb.h
@@ -16,18 +16,14 @@ struct mmu_rb_node {
struct rb_node node;
struct mmu_rb_handler *handler;
struct list_head list;
+ struct kref refcount;
};
-/*
- * NOTE: filter, insert, invalidate, and evict must not sleep. Only remove is
- * allowed to sleep.
- */
+/* filter and evict must not sleep. Only remove is allowed to sleep. */
struct mmu_rb_ops {
bool (*filter)(struct mmu_rb_node *node, unsigned long addr,
unsigned long len);
- int (*insert)(void *ops_arg, struct mmu_rb_node *mnode);
void (*remove)(void *ops_arg, struct mmu_rb_node *mnode);
- int (*invalidate)(void *ops_arg, struct mmu_rb_node *node);
int (*evict)(void *ops_arg, struct mmu_rb_node *mnode,
void *evict_arg, bool *stop);
};
@@ -61,6 +57,8 @@ int hfi1_mmu_rb_register(void *ops_arg,
void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler);
int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler,
struct mmu_rb_node *mnode);
+void hfi1_mmu_rb_release(struct kref *refcount);
+
void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg);
struct mmu_rb_node *hfi1_mmu_rb_get_first(struct mmu_rb_handler *handler,
unsigned long addr,
diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c
index bb2552dd29c1..26c62162759b 100644
--- a/drivers/infiniband/hw/hfi1/sdma.c
+++ b/drivers/infiniband/hw/hfi1/sdma.c
@@ -1593,7 +1593,20 @@ static inline void sdma_unmap_desc(
struct hfi1_devdata *dd,
struct sdma_desc *descp)
{
- system_descriptor_complete(dd, descp);
+ switch (sdma_mapping_type(descp)) {
+ case SDMA_MAP_SINGLE:
+ dma_unmap_single(&dd->pcidev->dev, sdma_mapping_addr(descp),
+ sdma_mapping_len(descp), DMA_TO_DEVICE);
+ break;
+ case SDMA_MAP_PAGE:
+ dma_unmap_page(&dd->pcidev->dev, sdma_mapping_addr(descp),
+ sdma_mapping_len(descp), DMA_TO_DEVICE);
+ break;
+ }
+
+ if (descp->pinning_ctx && descp->ctx_put)
+ descp->ctx_put(descp->pinning_ctx);
+ descp->pinning_ctx = NULL;
}
/*
@@ -3113,8 +3126,8 @@ int ext_coal_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx,
/* Add descriptor for coalesce buffer */
tx->desc_limit = MAX_DESC;
- return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, NULL, tx,
- addr, tx->tlen);
+ return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, tx,
+ addr, tx->tlen, NULL, NULL, NULL);
}
return 1;
@@ -3157,9 +3170,9 @@ int _pad_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx)
make_tx_sdma_desc(
tx,
SDMA_MAP_NONE,
- NULL,
dd->sdma_pad_phys,
- sizeof(u32) - (tx->packet_len & (sizeof(u32) - 1)));
+ sizeof(u32) - (tx->packet_len & (sizeof(u32) - 1)),
+ NULL, NULL, NULL);
tx->num_desc++;
_sdma_close_tx(dd, tx);
return rval;
diff --git a/drivers/infiniband/hw/hfi1/sdma.h b/drivers/infiniband/hw/hfi1/sdma.h
index 95aaec14c6c2..7fdebab202c4 100644
--- a/drivers/infiniband/hw/hfi1/sdma.h
+++ b/drivers/infiniband/hw/hfi1/sdma.h
@@ -594,9 +594,11 @@ static inline dma_addr_t sdma_mapping_addr(struct sdma_desc *d)
static inline void make_tx_sdma_desc(
struct sdma_txreq *tx,
int type,
- void *pinning_ctx,
dma_addr_t addr,
- size_t len)
+ size_t len,
+ void *pinning_ctx,
+ void (*ctx_get)(void *),
+ void (*ctx_put)(void *))
{
struct sdma_desc *desc = &tx->descp[tx->num_desc];
@@ -613,7 +615,11 @@ static inline void make_tx_sdma_desc(
<< SDMA_DESC0_PHY_ADDR_SHIFT) |
(((u64)len & SDMA_DESC0_BYTE_COUNT_MASK)
<< SDMA_DESC0_BYTE_COUNT_SHIFT);
+
desc->pinning_ctx = pinning_ctx;
+ desc->ctx_put = ctx_put;
+ if (pinning_ctx && ctx_get)
+ ctx_get(pinning_ctx);
}
/* helper to extend txreq */
@@ -645,18 +651,20 @@ static inline void _sdma_close_tx(struct hfi1_devdata *dd,
static inline int _sdma_txadd_daddr(
struct hfi1_devdata *dd,
int type,
- void *pinning_ctx,
struct sdma_txreq *tx,
dma_addr_t addr,
- u16 len)
+ u16 len,
+ void *pinning_ctx,
+ void (*ctx_get)(void *),
+ void (*ctx_put)(void *))
{
int rval = 0;
make_tx_sdma_desc(
tx,
type,
- pinning_ctx,
- addr, len);
+ addr, len,
+ pinning_ctx, ctx_get, ctx_put);
WARN_ON(len > tx->tlen);
tx->num_desc++;
tx->tlen -= len;
@@ -676,11 +684,18 @@ static inline int _sdma_txadd_daddr(
/**
* sdma_txadd_page() - add a page to the sdma_txreq
* @dd: the device to use for mapping
- * @pinning_ctx: context to be released at descriptor retirement
* @tx: tx request to which the page is added
* @page: page to map
* @offset: offset within the page
* @len: length in bytes
+ * @pinning_ctx: context to be stored on struct sdma_desc .pinning_ctx. Not
+ * added if coalesce buffer is used. E.g. pointer to pinned-page
+ * cache entry for the sdma_desc.
+ * @ctx_get: optional function to take reference to @pinning_ctx. Not called if
+ * @pinning_ctx is NULL.
+ * @ctx_put: optional function to release reference to @pinning_ctx after
+ * sdma_desc completes. May be called in interrupt context so must
+ * not sleep. Not called if @pinning_ctx is NULL.
*
* This is used to add a page/offset/length descriptor.
*
@@ -692,11 +707,13 @@ static inline int _sdma_txadd_daddr(
*/
static inline int sdma_txadd_page(
struct hfi1_devdata *dd,
- void *pinning_ctx,
struct sdma_txreq *tx,
struct page *page,
unsigned long offset,
- u16 len)
+ u16 len,
+ void *pinning_ctx,
+ void (*ctx_get)(void *),
+ void (*ctx_put)(void *))
{
dma_addr_t addr;
int rval;
@@ -720,7 +737,8 @@ static inline int sdma_txadd_page(
return -ENOSPC;
}
- return _sdma_txadd_daddr(dd, SDMA_MAP_PAGE, pinning_ctx, tx, addr, len);
+ return _sdma_txadd_daddr(dd, SDMA_MAP_PAGE, tx, addr, len,
+ pinning_ctx, ctx_get, ctx_put);
}
/**
@@ -754,8 +772,8 @@ static inline int sdma_txadd_daddr(
return rval;
}
- return _sdma_txadd_daddr(dd, SDMA_MAP_NONE, NULL, tx,
- addr, len);
+ return _sdma_txadd_daddr(dd, SDMA_MAP_NONE, tx, addr, len,
+ NULL, NULL, NULL);
}
/**
@@ -801,7 +819,8 @@ static inline int sdma_txadd_kvaddr(
return -ENOSPC;
}
- return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, NULL, tx, addr, len);
+ return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, tx, addr, len,
+ NULL, NULL, NULL);
}
struct iowait_work;
@@ -1034,6 +1053,4 @@ u16 sdma_get_descq_cnt(void);
extern uint mod_num_sdma;
void sdma_update_lmc(struct hfi1_devdata *dd, u64 mask, u32 lid);
-
-void system_descriptor_complete(struct hfi1_devdata *dd, struct sdma_desc *descp);
#endif
diff --git a/drivers/infiniband/hw/hfi1/sdma_txreq.h b/drivers/infiniband/hw/hfi1/sdma_txreq.h
index fad946cb5e0d..85ae7293c274 100644
--- a/drivers/infiniband/hw/hfi1/sdma_txreq.h
+++ b/drivers/infiniband/hw/hfi1/sdma_txreq.h
@@ -20,6 +20,8 @@ struct sdma_desc {
/* private: don't use directly */
u64 qw[2];
void *pinning_ctx;
+ /* Release reference to @pinning_ctx. May be called in interrupt context. Must not sleep. */
+ void (*ctx_put)(void *ctx);
};
/**
diff --git a/drivers/infiniband/hw/hfi1/trace_mmu.h b/drivers/infiniband/hw/hfi1/trace_mmu.h
index 57900ebb7702..82cc12aa3fb8 100644
--- a/drivers/infiniband/hw/hfi1/trace_mmu.h
+++ b/drivers/infiniband/hw/hfi1/trace_mmu.h
@@ -15,31 +15,53 @@
#define TRACE_SYSTEM hfi1_mmu
DECLARE_EVENT_CLASS(hfi1_mmu_rb_template,
- TP_PROTO(unsigned long addr, unsigned long len),
- TP_ARGS(addr, len),
+ TP_PROTO(struct mmu_rb_node *node),
+ TP_ARGS(node),
TP_STRUCT__entry(__field(unsigned long, addr)
__field(unsigned long, len)
+ __field(unsigned int, refcount)
),
- TP_fast_assign(__entry->addr = addr;
- __entry->len = len;
+ TP_fast_assign(__entry->addr = node->addr;
+ __entry->len = node->len;
+ __entry->refcount = kref_read(&node->refcount);
),
- TP_printk("MMU node addr 0x%lx, len %lu",
+ TP_printk("MMU node addr 0x%lx, len %lu, refcount %u",
__entry->addr,
- __entry->len
+ __entry->len,
+ __entry->refcount
)
);
DEFINE_EVENT(hfi1_mmu_rb_template, hfi1_mmu_rb_insert,
- TP_PROTO(unsigned long addr, unsigned long len),
- TP_ARGS(addr, len));
+ TP_PROTO(struct mmu_rb_node *node),
+ TP_ARGS(node));
-DEFINE_EVENT(hfi1_mmu_rb_template, hfi1_mmu_rb_search,
- TP_PROTO(unsigned long addr, unsigned long len),
- TP_ARGS(addr, len));
+TRACE_EVENT(hfi1_mmu_rb_search,
+ TP_PROTO(unsigned long addr, unsigned long len),
+ TP_ARGS(addr, len),
+ TP_STRUCT__entry(__field(unsigned long, addr)
+ __field(unsigned long, len)
+ ),
+ TP_fast_assign(__entry->addr = addr;
+ __entry->len = len;
+ ),
+ TP_printk("MMU node addr 0x%lx, len %lu",
+ __entry->addr,
+ __entry->len
+ )
+);
DEFINE_EVENT(hfi1_mmu_rb_template, hfi1_mmu_mem_invalidate,
- TP_PROTO(unsigned long addr, unsigned long len),
- TP_ARGS(addr, len));
+ TP_PROTO(struct mmu_rb_node *node),
+ TP_ARGS(node));
+
+DEFINE_EVENT(hfi1_mmu_rb_template, hfi1_mmu_rb_evict,
+ TP_PROTO(struct mmu_rb_node *node),
+ TP_ARGS(node));
+
+DEFINE_EVENT(hfi1_mmu_rb_template, hfi1_mmu_release_node,
+ TP_PROTO(struct mmu_rb_node *node),
+ TP_ARGS(node));
#endif /* __HFI1_TRACE_RC_H */
diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c
index ae58b48afe07..02bd62b857b7 100644
--- a/drivers/infiniband/hw/hfi1/user_sdma.c
+++ b/drivers/infiniband/hw/hfi1/user_sdma.c
@@ -62,18 +62,14 @@ static int defer_packet_queue(
static void activate_packet_queue(struct iowait *wait, int reason);
static bool sdma_rb_filter(struct mmu_rb_node *node, unsigned long addr,
unsigned long len);
-static int sdma_rb_insert(void *arg, struct mmu_rb_node *mnode);
static int sdma_rb_evict(void *arg, struct mmu_rb_node *mnode,
void *arg2, bool *stop);
static void sdma_rb_remove(void *arg, struct mmu_rb_node *mnode);
-static int sdma_rb_invalidate(void *arg, struct mmu_rb_node *mnode);
static struct mmu_rb_ops sdma_rb_ops = {
.filter = sdma_rb_filter,
- .insert = sdma_rb_insert,
.evict = sdma_rb_evict,
.remove = sdma_rb_remove,
- .invalidate = sdma_rb_invalidate
};
static int add_system_pages_to_sdma_packet(struct user_sdma_request *req,
@@ -247,14 +243,14 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd,
spin_unlock(&fd->pq_rcu_lock);
synchronize_srcu(&fd->pq_srcu);
/* at this point there can be no more new requests */
- if (pq->handler)
- hfi1_mmu_rb_unregister(pq->handler);
iowait_sdma_drain(&pq->busy);
/* Wait until all requests have been freed. */
wait_event_interruptible(
pq->wait,
!atomic_read(&pq->n_reqs));
kfree(pq->reqs);
+ if (pq->handler)
+ hfi1_mmu_rb_unregister(pq->handler);
bitmap_free(pq->req_in_use);
kmem_cache_destroy(pq->txreq_cache);
flush_pq_iowait(pq);
@@ -1275,25 +1271,17 @@ static void free_system_node(struct sdma_mmu_node *node)
kfree(node);
}
-static inline void acquire_node(struct sdma_mmu_node *node)
-{
- atomic_inc(&node->refcount);
- WARN_ON(atomic_read(&node->refcount) < 0);
-}
-
-static inline void release_node(struct mmu_rb_handler *handler,
- struct sdma_mmu_node *node)
-{
- atomic_dec(&node->refcount);
- WARN_ON(atomic_read(&node->refcount) < 0);
-}
-
+/*
+ * kref_get()'s an additional kref on the returned rb_node to prevent rb_node
+ * from being released until after rb_node is assigned to an SDMA descriptor
+ * (struct sdma_desc) under add_system_iovec_to_sdma_packet(), even if the
+ * virtual address range for rb_node is invalidated between now and then.
+ */
static struct sdma_mmu_node *find_system_node(struct mmu_rb_handler *handler,
unsigned long start,
unsigned long end)
{
struct mmu_rb_node *rb_node;
- struct sdma_mmu_node *node;
unsigned long flags;
spin_lock_irqsave(&handler->lock, flags);
@@ -1302,11 +1290,12 @@ static struct sdma_mmu_node *find_system_node(struct mmu_rb_handler *handler,
spin_unlock_irqrestore(&handler->lock, flags);
return NULL;
}
- node = container_of(rb_node, struct sdma_mmu_node, rb);
- acquire_node(node);
+
+ /* "safety" kref to prevent release before add_system_iovec_to_sdma_packet() */
+ kref_get(&rb_node->refcount);
spin_unlock_irqrestore(&handler->lock, flags);
- return node;
+ return container_of(rb_node, struct sdma_mmu_node, rb);
}
static int pin_system_pages(struct user_sdma_request *req,
@@ -1355,6 +1344,13 @@ retry:
return 0;
}
+/*
+ * kref refcount on *node_p will be 2 on successful addition: one kref from
+ * kref_init() for mmu_rb_handler and one kref to prevent *node_p from being
+ * released until after *node_p is assigned to an SDMA descriptor (struct
+ * sdma_desc) under add_system_iovec_to_sdma_packet(), even if the virtual
+ * address range for *node_p is invalidated between now and then.
+ */
static int add_system_pinning(struct user_sdma_request *req,
struct sdma_mmu_node **node_p,
unsigned long start, unsigned long len)
@@ -1368,6 +1364,12 @@ static int add_system_pinning(struct user_sdma_request *req,
if (!node)
return -ENOMEM;
+ /* First kref "moves" to mmu_rb_handler */
+ kref_init(&node->rb.refcount);
+
+ /* "safety" kref to prevent release before add_system_iovec_to_sdma_packet() */
+ kref_get(&node->rb.refcount);
+
node->pq = pq;
ret = pin_system_pages(req, start, len, node, PFN_DOWN(len));
if (ret == 0) {
@@ -1431,15 +1433,15 @@ static int get_system_cache_entry(struct user_sdma_request *req,
return 0;
}
- SDMA_DBG(req, "prepend: node->rb.addr %lx, node->refcount %d",
- node->rb.addr, atomic_read(&node->refcount));
+ SDMA_DBG(req, "prepend: node->rb.addr %lx, node->rb.refcount %d",
+ node->rb.addr, kref_read(&node->rb.refcount));
prepend_len = node->rb.addr - start;
/*
* This node will not be returned, instead a new node
* will be. So release the reference.
*/
- release_node(handler, node);
+ kref_put(&node->rb.refcount, hfi1_mmu_rb_release);
/* Prepend a node to cover the beginning of the allocation */
ret = add_system_pinning(req, node_p, start, prepend_len);
@@ -1451,6 +1453,20 @@ static int get_system_cache_entry(struct user_sdma_request *req,
}
}
+static void sdma_mmu_rb_node_get(void *ctx)
+{
+ struct mmu_rb_node *node = ctx;
+
+ kref_get(&node->refcount);
+}
+
+static void sdma_mmu_rb_node_put(void *ctx)
+{
+ struct sdma_mmu_node *node = ctx;
+
+ kref_put(&node->rb.refcount, hfi1_mmu_rb_release);
+}
+
static int add_mapping_to_sdma_packet(struct user_sdma_request *req,
struct user_sdma_txreq *tx,
struct sdma_mmu_node *cache_entry,
@@ -1494,9 +1510,12 @@ static int add_mapping_to_sdma_packet(struct user_sdma_request *req,
ctx = cache_entry;
}
- ret = sdma_txadd_page(pq->dd, ctx, &tx->txreq,
+ ret = sdma_txadd_page(pq->dd, &tx->txreq,
cache_entry->pages[page_index],
- page_offset, from_this_page);
+ page_offset, from_this_page,
+ ctx,
+ sdma_mmu_rb_node_get,
+ sdma_mmu_rb_node_put);
if (ret) {
/*
* When there's a failure, the entire request is freed by
@@ -1518,8 +1537,6 @@ static int add_system_iovec_to_sdma_packet(struct user_sdma_request *req,
struct user_sdma_iovec *iovec,
size_t from_this_iovec)
{
- struct mmu_rb_handler *handler = req->pq->handler;
-
while (from_this_iovec > 0) {
struct sdma_mmu_node *cache_entry;
size_t from_this_cache_entry;
@@ -1540,15 +1557,15 @@ static int add_system_iovec_to_sdma_packet(struct user_sdma_request *req,
ret = add_mapping_to_sdma_packet(req, tx, cache_entry, start,
from_this_cache_entry);
+
+ /*
+ * Done adding cache_entry to zero or more sdma_desc. Can
+ * kref_put() the "safety" kref taken under
+ * get_system_cache_entry().
+ */
+ kref_put(&cache_entry->rb.refcount, hfi1_mmu_rb_release);
+
if (ret) {
- /*
- * We're guaranteed that there will be no descriptor
- * completion callback that releases this node
- * because only the last descriptor referencing it
- * has a context attached, and a failure means the
- * last descriptor was never added.
- */
- release_node(handler, cache_entry);
SDMA_DBG(req, "add system segment failed %d", ret);
return ret;
}
@@ -1599,42 +1616,12 @@ static int add_system_pages_to_sdma_packet(struct user_sdma_request *req,
return 0;
}
-void system_descriptor_complete(struct hfi1_devdata *dd,
- struct sdma_desc *descp)
-{
- switch (sdma_mapping_type(descp)) {
- case SDMA_MAP_SINGLE:
- dma_unmap_single(&dd->pcidev->dev, sdma_mapping_addr(descp),
- sdma_mapping_len(descp), DMA_TO_DEVICE);
- break;
- case SDMA_MAP_PAGE:
- dma_unmap_page(&dd->pcidev->dev, sdma_mapping_addr(descp),
- sdma_mapping_len(descp), DMA_TO_DEVICE);
- break;
- }
-
- if (descp->pinning_ctx) {
- struct sdma_mmu_node *node = descp->pinning_ctx;
-
- release_node(node->rb.handler, node);
- }
-}
-
static bool sdma_rb_filter(struct mmu_rb_node *node, unsigned long addr,
unsigned long len)
{
return (bool)(node->addr == addr);
}
-static int sdma_rb_insert(void *arg, struct mmu_rb_node *mnode)
-{
- struct sdma_mmu_node *node =
- container_of(mnode, struct sdma_mmu_node, rb);
-
- atomic_inc(&node->refcount);
- return 0;
-}
-
/*
* Return 1 to remove the node from the rb tree and call the remove op.
*
@@ -1647,10 +1634,6 @@ static int sdma_rb_evict(void *arg, struct mmu_rb_node *mnode,
container_of(mnode, struct sdma_mmu_node, rb);
struct evict_data *evict_data = evict_arg;
- /* is this node still being used? */
- if (atomic_read(&node->refcount))
- return 0; /* keep this node */
-
/* this node will be evicted, add its pages to our count */
evict_data->cleared += node->npages;
@@ -1668,13 +1651,3 @@ static void sdma_rb_remove(void *arg, struct mmu_rb_node *mnode)
free_system_node(node);
}
-
-static int sdma_rb_invalidate(void *arg, struct mmu_rb_node *mnode)
-{
- struct sdma_mmu_node *node =
- container_of(mnode, struct sdma_mmu_node, rb);
-
- if (!atomic_read(&node->refcount))
- return 1;
- return 0;
-}
diff --git a/drivers/infiniband/hw/hfi1/user_sdma.h b/drivers/infiniband/hw/hfi1/user_sdma.h
index a241836371dc..548347d4c5bc 100644
--- a/drivers/infiniband/hw/hfi1/user_sdma.h
+++ b/drivers/infiniband/hw/hfi1/user_sdma.h
@@ -104,7 +104,6 @@ struct hfi1_user_sdma_comp_q {
struct sdma_mmu_node {
struct mmu_rb_node rb;
struct hfi1_user_sdma_pkt_q *pq;
- atomic_t refcount;
struct page **pages;
unsigned int npages;
};
diff --git a/drivers/infiniband/hw/hfi1/vnic_sdma.c b/drivers/infiniband/hw/hfi1/vnic_sdma.c
index 727eedfba332..cc6324d2d1dd 100644
--- a/drivers/infiniband/hw/hfi1/vnic_sdma.c
+++ b/drivers/infiniband/hw/hfi1/vnic_sdma.c
@@ -64,11 +64,11 @@ static noinline int build_vnic_ulp_payload(struct sdma_engine *sde,
/* combine physically continuous fragments later? */
ret = sdma_txadd_page(sde->dd,
- NULL,
&tx->txreq,
skb_frag_page(frag),
skb_frag_off(frag),
- skb_frag_size(frag));
+ skb_frag_size(frag),
+ NULL, NULL, NULL);
if (unlikely(ret))
goto bail_txadd;
}
diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c
index aa8a08d1c014..47c0efed1821 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hem.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hem.c
@@ -595,11 +595,12 @@ int hns_roce_table_get(struct hns_roce_dev *hr_dev,
}
/* Set HEM base address(128K/page, pa) to Hardware */
- if (hr_dev->hw->set_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT)) {
+ ret = hr_dev->hw->set_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT);
+ if (ret) {
hns_roce_free_hem(hr_dev, table->hem[i]);
table->hem[i] = NULL;
- ret = -ENODEV;
- dev_err(dev, "set HEM base address to HW failed.\n");
+ dev_err(dev, "set HEM base address to HW failed, ret = %d.\n",
+ ret);
goto out;
}
@@ -618,6 +619,7 @@ static void clear_mhop_hem(struct hns_roce_dev *hr_dev,
u32 hop_num = mhop->hop_num;
u32 chunk_ba_num;
u32 step_idx;
+ int ret;
index->inited = HEM_INDEX_BUF;
chunk_ba_num = mhop->bt_chunk_size / BA_BYTE_LEN;
@@ -641,16 +643,24 @@ static void clear_mhop_hem(struct hns_roce_dev *hr_dev,
else
step_idx = hop_num;
- if (hr_dev->hw->clear_hem(hr_dev, table, obj, step_idx))
- ibdev_warn(ibdev, "failed to clear hop%u HEM.\n", hop_num);
-
- if (index->inited & HEM_INDEX_L1)
- if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1))
- ibdev_warn(ibdev, "failed to clear HEM step 1.\n");
+ ret = hr_dev->hw->clear_hem(hr_dev, table, obj, step_idx);
+ if (ret)
+ ibdev_warn(ibdev, "failed to clear hop%u HEM, ret = %d.\n",
+ hop_num, ret);
+
+ if (index->inited & HEM_INDEX_L1) {
+ ret = hr_dev->hw->clear_hem(hr_dev, table, obj, 1);
+ if (ret)
+ ibdev_warn(ibdev, "failed to clear HEM step 1, ret = %d.\n",
+ ret);
+ }
- if (index->inited & HEM_INDEX_L0)
- if (hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
- ibdev_warn(ibdev, "failed to clear HEM step 0.\n");
+ if (index->inited & HEM_INDEX_L0) {
+ ret = hr_dev->hw->clear_hem(hr_dev, table, obj, 0);
+ if (ret)
+ ibdev_warn(ibdev, "failed to clear HEM step 0, ret = %d.\n",
+ ret);
+ }
}
}
@@ -687,6 +697,7 @@ void hns_roce_table_put(struct hns_roce_dev *hr_dev,
{
struct device *dev = hr_dev->dev;
unsigned long i;
+ int ret;
if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
hns_roce_table_mhop_put(hr_dev, table, obj, 1);
@@ -699,8 +710,10 @@ void hns_roce_table_put(struct hns_roce_dev *hr_dev,
&table->mutex))
return;
- if (hr_dev->hw->clear_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT))
- dev_warn(dev, "failed to clear HEM base address.\n");
+ ret = hr_dev->hw->clear_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT);
+ if (ret)
+ dev_warn(dev, "failed to clear HEM base address, ret = %d.\n",
+ ret);
hns_roce_free_hem(hr_dev, table->hem[i]);
table->hem[i] = NULL;
@@ -916,6 +929,8 @@ void hns_roce_cleanup_hem_table(struct hns_roce_dev *hr_dev,
{
struct device *dev = hr_dev->dev;
unsigned long i;
+ int obj;
+ int ret;
if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
hns_roce_cleanup_mhop_hem_table(hr_dev, table);
@@ -924,9 +939,11 @@ void hns_roce_cleanup_hem_table(struct hns_roce_dev *hr_dev,
for (i = 0; i < table->num_hem; ++i)
if (table->hem[i]) {
- if (hr_dev->hw->clear_hem(hr_dev, table,
- i * table->table_chunk_size / table->obj_size, 0))
- dev_err(dev, "clear HEM base address failed.\n");
+ obj = i * table->table_chunk_size / table->obj_size;
+ ret = hr_dev->hw->clear_hem(hr_dev, table, obj, 0);
+ if (ret)
+ dev_err(dev, "clear HEM base address failed, ret = %d.\n",
+ ret);
hns_roce_free_hem(hr_dev, table->hem[i]);
}
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index d4c6b9bc0a4e..8f7eb11066b4 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -373,17 +373,10 @@ static int check_send_valid(struct hns_roce_dev *hr_dev,
struct hns_roce_qp *hr_qp)
{
struct ib_device *ibdev = &hr_dev->ib_dev;
- struct ib_qp *ibqp = &hr_qp->ibqp;
- if (unlikely(ibqp->qp_type != IB_QPT_RC &&
- ibqp->qp_type != IB_QPT_GSI &&
- ibqp->qp_type != IB_QPT_UD)) {
- ibdev_err(ibdev, "not supported QP(0x%x)type!\n",
- ibqp->qp_type);
- return -EOPNOTSUPP;
- } else if (unlikely(hr_qp->state == IB_QPS_RESET ||
- hr_qp->state == IB_QPS_INIT ||
- hr_qp->state == IB_QPS_RTR)) {
+ if (unlikely(hr_qp->state == IB_QPS_RESET ||
+ hr_qp->state == IB_QPS_INIT ||
+ hr_qp->state == IB_QPS_RTR)) {
ibdev_err(ibdev, "failed to post WQE, QP state %u!\n",
hr_qp->state);
return -EINVAL;
@@ -771,17 +764,6 @@ out:
static int check_recv_valid(struct hns_roce_dev *hr_dev,
struct hns_roce_qp *hr_qp)
{
- struct ib_device *ibdev = &hr_dev->ib_dev;
- struct ib_qp *ibqp = &hr_qp->ibqp;
-
- if (unlikely(ibqp->qp_type != IB_QPT_RC &&
- ibqp->qp_type != IB_QPT_GSI &&
- ibqp->qp_type != IB_QPT_UD)) {
- ibdev_err(ibdev, "unsupported qp type, qp_type = %d.\n",
- ibqp->qp_type);
- return -EOPNOTSUPP;
- }
-
if (unlikely(hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN))
return -EIO;
diff --git a/drivers/infiniband/hw/irdma/uk.c b/drivers/infiniband/hw/irdma/uk.c
index 16183e894da7..dd428d915c17 100644
--- a/drivers/infiniband/hw/irdma/uk.c
+++ b/drivers/infiniband/hw/irdma/uk.c
@@ -93,16 +93,18 @@ static int irdma_nop_1(struct irdma_qp_uk *qp)
*/
void irdma_clr_wqes(struct irdma_qp_uk *qp, u32 qp_wqe_idx)
{
- __le64 *wqe;
+ struct irdma_qp_quanta *sq;
u32 wqe_idx;
if (!(qp_wqe_idx & 0x7F)) {
wqe_idx = (qp_wqe_idx + 128) % qp->sq_ring.size;
- wqe = qp->sq_base[wqe_idx].elem;
+ sq = qp->sq_base + wqe_idx;
if (wqe_idx)
- memset(wqe, qp->swqe_polarity ? 0 : 0xFF, 0x1000);
+ memset(sq, qp->swqe_polarity ? 0 : 0xFF,
+ 128 * sizeof(*sq));
else
- memset(wqe, qp->swqe_polarity ? 0xFF : 0, 0x1000);
+ memset(sq, qp->swqe_polarity ? 0xFF : 0,
+ 128 * sizeof(*sq));
}
}
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index eaa12c124598..9c4fe4fa9001 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -4452,8 +4452,16 @@ static const struct ib_device_ops irdma_roce_dev_ops = {
};
static const struct ib_device_ops irdma_iw_dev_ops = {
- .modify_qp = irdma_modify_qp,
.get_port_immutable = irdma_iw_port_immutable,
+ .iw_accept = irdma_accept,
+ .iw_add_ref = irdma_qp_add_ref,
+ .iw_connect = irdma_connect,
+ .iw_create_listen = irdma_create_listen,
+ .iw_destroy_listen = irdma_destroy_listen,
+ .iw_get_qp = irdma_get_qp,
+ .iw_reject = irdma_reject,
+ .iw_rem_ref = irdma_qp_rem_ref,
+ .modify_qp = irdma_modify_qp,
.query_gid = irdma_query_gid,
};
@@ -4517,50 +4525,35 @@ static void irdma_init_roce_device(struct irdma_device *iwdev)
* irdma_init_iw_device - initialization of iwarp rdma device
* @iwdev: irdma device
*/
-static int irdma_init_iw_device(struct irdma_device *iwdev)
+static void irdma_init_iw_device(struct irdma_device *iwdev)
{
struct net_device *netdev = iwdev->netdev;
iwdev->ibdev.node_type = RDMA_NODE_RNIC;
addrconf_addr_eui48((u8 *)&iwdev->ibdev.node_guid,
netdev->dev_addr);
- iwdev->ibdev.ops.iw_add_ref = irdma_qp_add_ref;
- iwdev->ibdev.ops.iw_rem_ref = irdma_qp_rem_ref;
- iwdev->ibdev.ops.iw_get_qp = irdma_get_qp;
- iwdev->ibdev.ops.iw_connect = irdma_connect;
- iwdev->ibdev.ops.iw_accept = irdma_accept;
- iwdev->ibdev.ops.iw_reject = irdma_reject;
- iwdev->ibdev.ops.iw_create_listen = irdma_create_listen;
- iwdev->ibdev.ops.iw_destroy_listen = irdma_destroy_listen;
memcpy(iwdev->ibdev.iw_ifname, netdev->name,
sizeof(iwdev->ibdev.iw_ifname));
ib_set_device_ops(&iwdev->ibdev, &irdma_iw_dev_ops);
-
- return 0;
}
/**
* irdma_init_rdma_device - initialization of rdma device
* @iwdev: irdma device
*/
-static int irdma_init_rdma_device(struct irdma_device *iwdev)
+static void irdma_init_rdma_device(struct irdma_device *iwdev)
{
struct pci_dev *pcidev = iwdev->rf->pcidev;
- int ret;
- if (iwdev->roce_mode) {
+ if (iwdev->roce_mode)
irdma_init_roce_device(iwdev);
- } else {
- ret = irdma_init_iw_device(iwdev);
- if (ret)
- return ret;
- }
+ else
+ irdma_init_iw_device(iwdev);
+
iwdev->ibdev.phys_port_cnt = 1;
iwdev->ibdev.num_comp_vectors = iwdev->rf->ceqs_count;
iwdev->ibdev.dev.parent = &pcidev->dev;
ib_set_device_ops(&iwdev->ibdev, &irdma_dev_ops);
-
- return 0;
}
/**
@@ -4598,9 +4591,7 @@ int irdma_ib_register_device(struct irdma_device *iwdev)
{
int ret;
- ret = irdma_init_rdma_device(iwdev);
- if (ret)
- return ret;
+ irdma_init_rdma_device(iwdev);
ret = ib_device_set_netdev(&iwdev->ibdev, iwdev->netdev, 1);
if (ret)
diff --git a/drivers/infiniband/hw/mana/qp.c b/drivers/infiniband/hw/mana/qp.c
index 54b61930a7fd..4b3b5b274e84 100644
--- a/drivers/infiniband/hw/mana/qp.c
+++ b/drivers/infiniband/hw/mana/qp.c
@@ -13,7 +13,7 @@ static int mana_ib_cfg_vport_steering(struct mana_ib_dev *dev,
u8 *rx_hash_key)
{
struct mana_port_context *mpc = netdev_priv(ndev);
- struct mana_cfg_rx_steer_req *req = NULL;
+ struct mana_cfg_rx_steer_req_v2 *req;
struct mana_cfg_rx_steer_resp resp = {};
mana_handle_t *req_indir_tab;
struct gdma_context *gc;
@@ -33,6 +33,8 @@ static int mana_ib_cfg_vport_steering(struct mana_ib_dev *dev,
mana_gd_init_req_hdr(&req->hdr, MANA_CONFIG_VPORT_RX, req_buf_size,
sizeof(resp));
+ req->hdr.req.msg_version = GDMA_MESSAGE_V2;
+
req->vport = mpc->port_handle;
req->rx_enable = 1;
req->update_default_rxobj = 1;
@@ -46,6 +48,7 @@ static int mana_ib_cfg_vport_steering(struct mana_ib_dev *dev,
req->num_indir_entries = MANA_INDIRECT_TABLE_SIZE;
req->indir_tab_offset = sizeof(*req);
req->update_indir_tab = true;
+ req->cqe_coalescing_enable = 1;
req_indir_tab = (mana_handle_t *)(req + 1);
/* The ind table passed to the hardware must have
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 2dfa6f49a6f4..9c33d960af3c 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -25,6 +25,7 @@
#include <rdma/mlx5_user_ioctl_verbs.h>
#include "srq.h"
+#include "qp.h"
#define mlx5_ib_dbg(_dev, format, arg...) \
dev_dbg(&(_dev)->ib_dev.dev, "%s:%d:(pid %d): " format, __func__, \
diff --git a/drivers/infiniband/hw/mlx5/qp.h b/drivers/infiniband/hw/mlx5/qp.h
index 77f9b4a54816..b6ee7c3ee1ca 100644
--- a/drivers/infiniband/hw/mlx5/qp.h
+++ b/drivers/infiniband/hw/mlx5/qp.h
@@ -6,7 +6,17 @@
#ifndef _MLX5_IB_QP_H
#define _MLX5_IB_QP_H
-#include "mlx5_ib.h"
+struct mlx5_ib_dev;
+
+struct mlx5_qp_table {
+ struct notifier_block nb;
+ struct xarray dct_xa;
+
+ /* protect radix tree
+ */
+ spinlock_t lock;
+ struct radix_tree_root tree;
+};
int mlx5_init_qp_table(struct mlx5_ib_dev *dev);
void mlx5_cleanup_qp_table(struct mlx5_ib_dev *dev);
diff --git a/drivers/infiniband/hw/mlx5/qpc.c b/drivers/infiniband/hw/mlx5/qpc.c
index bae0334d6e7f..d9cf6982d645 100644
--- a/drivers/infiniband/hw/mlx5/qpc.c
+++ b/drivers/infiniband/hw/mlx5/qpc.c
@@ -88,23 +88,35 @@ static bool is_event_type_allowed(int rsc_type, int event_type)
}
}
+static int dct_event_notifier(struct mlx5_ib_dev *dev, struct mlx5_eqe *eqe)
+{
+ struct mlx5_core_dct *dct;
+ unsigned long flags;
+ u32 qpn;
+
+ qpn = be32_to_cpu(eqe->data.dct.dctn) & 0xFFFFFF;
+ xa_lock_irqsave(&dev->qp_table.dct_xa, flags);
+ dct = xa_load(&dev->qp_table.dct_xa, qpn);
+ if (dct)
+ complete(&dct->drained);
+ xa_unlock_irqrestore(&dev->qp_table.dct_xa, flags);
+ return NOTIFY_OK;
+}
+
static int rsc_event_notifier(struct notifier_block *nb,
unsigned long type, void *data)
{
+ struct mlx5_ib_dev *dev =
+ container_of(nb, struct mlx5_ib_dev, qp_table.nb);
struct mlx5_core_rsc_common *common;
- struct mlx5_qp_table *table;
- struct mlx5_core_dct *dct;
+ struct mlx5_eqe *eqe = data;
u8 event_type = (u8)type;
struct mlx5_core_qp *qp;
- struct mlx5_eqe *eqe;
u32 rsn;
switch (event_type) {
case MLX5_EVENT_TYPE_DCT_DRAINED:
- eqe = data;
- rsn = be32_to_cpu(eqe->data.dct.dctn) & 0xffffff;
- rsn |= (MLX5_RES_DCT << MLX5_USER_INDEX_LEN);
- break;
+ return dct_event_notifier(dev, eqe);
case MLX5_EVENT_TYPE_PATH_MIG:
case MLX5_EVENT_TYPE_COMM_EST:
case MLX5_EVENT_TYPE_SQ_DRAINED:
@@ -113,7 +125,6 @@ static int rsc_event_notifier(struct notifier_block *nb,
case MLX5_EVENT_TYPE_PATH_MIG_FAILED:
case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR:
- eqe = data;
rsn = be32_to_cpu(eqe->data.qp_srq.qp_srq_n) & 0xffffff;
rsn |= (eqe->data.qp_srq.type << MLX5_USER_INDEX_LEN);
break;
@@ -121,8 +132,7 @@ static int rsc_event_notifier(struct notifier_block *nb,
return NOTIFY_DONE;
}
- table = container_of(nb, struct mlx5_qp_table, nb);
- common = mlx5_get_rsc(table, rsn);
+ common = mlx5_get_rsc(&dev->qp_table, rsn);
if (!common)
return NOTIFY_OK;
@@ -137,11 +147,6 @@ static int rsc_event_notifier(struct notifier_block *nb,
qp->event(qp, event_type);
/* Need to put resource in event handler */
return NOTIFY_OK;
- case MLX5_RES_DCT:
- dct = (struct mlx5_core_dct *)common;
- if (event_type == MLX5_EVENT_TYPE_DCT_DRAINED)
- complete(&dct->drained);
- break;
default:
break;
}
@@ -188,28 +193,15 @@ static void destroy_resource_common(struct mlx5_ib_dev *dev,
}
static int _mlx5_core_destroy_dct(struct mlx5_ib_dev *dev,
- struct mlx5_core_dct *dct, bool need_cleanup)
+ struct mlx5_core_dct *dct)
{
u32 in[MLX5_ST_SZ_DW(destroy_dct_in)] = {};
struct mlx5_core_qp *qp = &dct->mqp;
- int err;
- err = mlx5_core_drain_dct(dev, dct);
- if (err) {
- if (dev->mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
- goto destroy;
-
- return err;
- }
- wait_for_completion(&dct->drained);
-destroy:
- if (need_cleanup)
- destroy_resource_common(dev, &dct->mqp);
MLX5_SET(destroy_dct_in, in, opcode, MLX5_CMD_OP_DESTROY_DCT);
MLX5_SET(destroy_dct_in, in, dctn, qp->qpn);
MLX5_SET(destroy_dct_in, in, uid, qp->uid);
- err = mlx5_cmd_exec_in(dev->mdev, destroy_dct, in);
- return err;
+ return mlx5_cmd_exec_in(dev->mdev, destroy_dct, in);
}
int mlx5_core_create_dct(struct mlx5_ib_dev *dev, struct mlx5_core_dct *dct,
@@ -227,13 +219,13 @@ int mlx5_core_create_dct(struct mlx5_ib_dev *dev, struct mlx5_core_dct *dct,
qp->qpn = MLX5_GET(create_dct_out, out, dctn);
qp->uid = MLX5_GET(create_dct_in, in, uid);
- err = create_resource_common(dev, qp, MLX5_RES_DCT);
+ err = xa_err(xa_store_irq(&dev->qp_table.dct_xa, qp->qpn, dct, GFP_KERNEL));
if (err)
goto err_cmd;
return 0;
err_cmd:
- _mlx5_core_destroy_dct(dev, dct, false);
+ _mlx5_core_destroy_dct(dev, dct);
return err;
}
@@ -284,7 +276,31 @@ static int mlx5_core_drain_dct(struct mlx5_ib_dev *dev,
int mlx5_core_destroy_dct(struct mlx5_ib_dev *dev,
struct mlx5_core_dct *dct)
{
- return _mlx5_core_destroy_dct(dev, dct, true);
+ struct mlx5_qp_table *table = &dev->qp_table;
+ struct mlx5_core_dct *tmp;
+ int err;
+
+ err = mlx5_core_drain_dct(dev, dct);
+ if (err) {
+ if (dev->mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
+ goto destroy;
+
+ return err;
+ }
+ wait_for_completion(&dct->drained);
+
+destroy:
+ tmp = xa_cmpxchg_irq(&table->dct_xa, dct->mqp.qpn, dct, XA_ZERO_ENTRY, GFP_KERNEL);
+ if (WARN_ON(tmp != dct))
+ return xa_err(tmp) ?: -EINVAL;
+
+ err = _mlx5_core_destroy_dct(dev, dct);
+ if (err) {
+ xa_cmpxchg_irq(&table->dct_xa, dct->mqp.qpn, XA_ZERO_ENTRY, dct, 0);
+ return err;
+ }
+ xa_erase_irq(&table->dct_xa, dct->mqp.qpn);
+ return 0;
}
int mlx5_core_destroy_qp(struct mlx5_ib_dev *dev, struct mlx5_core_qp *qp)
@@ -298,8 +314,7 @@ int mlx5_core_destroy_qp(struct mlx5_ib_dev *dev, struct mlx5_core_qp *qp)
MLX5_SET(destroy_qp_in, in, opcode, MLX5_CMD_OP_DESTROY_QP);
MLX5_SET(destroy_qp_in, in, qpn, qp->qpn);
MLX5_SET(destroy_qp_in, in, uid, qp->uid);
- mlx5_cmd_exec_in(dev->mdev, destroy_qp, in);
- return 0;
+ return mlx5_cmd_exec_in(dev->mdev, destroy_qp, in);
}
int mlx5_core_set_delay_drop(struct mlx5_ib_dev *dev,
@@ -488,6 +503,7 @@ int mlx5_init_qp_table(struct mlx5_ib_dev *dev)
spin_lock_init(&table->lock);
INIT_RADIX_TREE(&table->tree, GFP_ATOMIC);
+ xa_init(&table->dct_xa);
mlx5_qp_debugfs_init(dev->mdev);
table->nb.notifier_call = rsc_event_notifier;
@@ -551,14 +567,14 @@ int mlx5_core_xrcd_dealloc(struct mlx5_ib_dev *dev, u32 xrcdn)
return mlx5_cmd_exec_in(dev->mdev, dealloc_xrcd, in);
}
-static void destroy_rq_tracked(struct mlx5_ib_dev *dev, u32 rqn, u16 uid)
+static int destroy_rq_tracked(struct mlx5_ib_dev *dev, u32 rqn, u16 uid)
{
u32 in[MLX5_ST_SZ_DW(destroy_rq_in)] = {};
MLX5_SET(destroy_rq_in, in, opcode, MLX5_CMD_OP_DESTROY_RQ);
MLX5_SET(destroy_rq_in, in, rqn, rqn);
MLX5_SET(destroy_rq_in, in, uid, uid);
- mlx5_cmd_exec_in(dev->mdev, destroy_rq, in);
+ return mlx5_cmd_exec_in(dev->mdev, destroy_rq, in);
}
int mlx5_core_create_rq_tracked(struct mlx5_ib_dev *dev, u32 *in, int inlen,
@@ -589,8 +605,7 @@ int mlx5_core_destroy_rq_tracked(struct mlx5_ib_dev *dev,
struct mlx5_core_qp *rq)
{
destroy_resource_common(dev, rq);
- destroy_rq_tracked(dev, rq->qpn, rq->uid);
- return 0;
+ return destroy_rq_tracked(dev, rq->qpn, rq->uid);
}
static void destroy_sq_tracked(struct mlx5_ib_dev *dev, u32 sqn, u16 uid)
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
index f83cd4a9d992..98b2a0090bf2 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
@@ -709,14 +709,6 @@ int pvrdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
goto out;
}
- if (unlikely(wr->opcode < 0)) {
- dev_warn_ratelimited(&dev->pdev->dev,
- "invalid send opcode\n");
- *bad_wr = wr;
- ret = -EINVAL;
- goto out;
- }
-
/*
* Only support UD, RC.
* Need to check opcode table for thorough checking.
diff --git a/drivers/infiniband/sw/rxe/rxe.c b/drivers/infiniband/sw/rxe/rxe.c
index 7a7e713de52d..54c723a6edda 100644
--- a/drivers/infiniband/sw/rxe/rxe.c
+++ b/drivers/infiniband/sw/rxe/rxe.c
@@ -212,10 +212,16 @@ static int __init rxe_module_init(void)
{
int err;
- err = rxe_net_init();
+ err = rxe_alloc_wq();
if (err)
return err;
+ err = rxe_net_init();
+ if (err) {
+ rxe_destroy_wq();
+ return err;
+ }
+
rdma_link_register(&rxe_link_ops);
pr_info("loaded\n");
return 0;
@@ -226,6 +232,7 @@ static void __exit rxe_module_exit(void)
rdma_link_unregister(&rxe_link_ops);
ib_unregister_driver(RDMA_DRIVER_RXE);
rxe_net_exit();
+ rxe_destroy_wq();
pr_info("unloaded\n");
}
diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
index f46c5a5fd0ae..5111735aafae 100644
--- a/drivers/infiniband/sw/rxe/rxe_comp.c
+++ b/drivers/infiniband/sw/rxe/rxe_comp.c
@@ -832,7 +832,7 @@ int rxe_completer(struct rxe_qp *qp)
}
/* A non-zero return value will cause rxe_do_task to
- * exit its loop and end the tasklet. A zero return
+ * exit its loop and end the work item. A zero return
* will continue looping and return to rxe_completer
*/
done:
diff --git a/drivers/infiniband/sw/rxe/rxe_cq.c b/drivers/infiniband/sw/rxe/rxe_cq.c
index 6ca2a05b6a2a..d5486cbb3f10 100644
--- a/drivers/infiniband/sw/rxe/rxe_cq.c
+++ b/drivers/infiniband/sw/rxe/rxe_cq.c
@@ -113,10 +113,9 @@ int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
queue_advance_producer(cq->queue, QUEUE_TYPE_TO_CLIENT);
- if ((cq->notify == IB_CQ_NEXT_COMP) ||
- (cq->notify == IB_CQ_SOLICITED && solicited)) {
+ if ((cq->notify & IB_CQ_NEXT_COMP) ||
+ (cq->notify & IB_CQ_SOLICITED && solicited)) {
cq->notify = 0;
-
cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
}
diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h
index 804b15e929dd..666e06a82bc9 100644
--- a/drivers/infiniband/sw/rxe/rxe_loc.h
+++ b/drivers/infiniband/sw/rxe/rxe_loc.h
@@ -31,8 +31,6 @@ int rxe_cq_resize_queue(struct rxe_cq *cq, int new_cqe,
int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited);
-void rxe_cq_disable(struct rxe_cq *cq);
-
void rxe_cq_cleanup(struct rxe_pool_elem *elem);
/* rxe_mcast.c */
diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c
index 0e538fafcc20..f54042e9aeb2 100644
--- a/drivers/infiniband/sw/rxe/rxe_mr.c
+++ b/drivers/infiniband/sw/rxe/rxe_mr.c
@@ -45,22 +45,17 @@ int mr_check_range(struct rxe_mr *mr, u64 iova, size_t length)
}
}
-#define IB_ACCESS_REMOTE (IB_ACCESS_REMOTE_READ \
- | IB_ACCESS_REMOTE_WRITE \
- | IB_ACCESS_REMOTE_ATOMIC)
-
static void rxe_mr_init(int access, struct rxe_mr *mr)
{
- u32 lkey = mr->elem.index << 8 | rxe_get_next_key(-1);
- u32 rkey = (access & IB_ACCESS_REMOTE) ? lkey : 0;
+ u32 key = mr->elem.index << 8 | rxe_get_next_key(-1);
/* set ibmr->l/rkey and also copy into private l/rkey
* for user MRs these will always be the same
* for cases where caller 'owns' the key portion
* they may be different until REG_MR WQE is executed.
*/
- mr->lkey = mr->ibmr.lkey = lkey;
- mr->rkey = mr->ibmr.rkey = rkey;
+ mr->lkey = mr->ibmr.lkey = key;
+ mr->rkey = mr->ibmr.rkey = key;
mr->access = access;
mr->ibmr.page_size = PAGE_SIZE;
@@ -195,7 +190,7 @@ int rxe_mr_init_fast(int max_pages, struct rxe_mr *mr)
int err;
/* always allow remote access for FMRs */
- rxe_mr_init(IB_ACCESS_REMOTE, mr);
+ rxe_mr_init(RXE_ACCESS_REMOTE, mr);
err = rxe_mr_alloc(mr, max_pages);
if (err)
@@ -644,6 +639,7 @@ int rxe_invalidate_mr(struct rxe_qp *qp, u32 key)
{
struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
struct rxe_mr *mr;
+ int remote;
int ret;
mr = rxe_pool_get_index(&rxe->mr_pool, key >> 8);
@@ -653,9 +649,10 @@ int rxe_invalidate_mr(struct rxe_qp *qp, u32 key)
goto err;
}
- if (mr->rkey ? (key != mr->rkey) : (key != mr->lkey)) {
+ remote = mr->access & RXE_ACCESS_REMOTE;
+ if (remote ? (key != mr->rkey) : (key != mr->lkey)) {
rxe_dbg_mr(mr, "wr key (%#x) doesn't match mr key (%#x)\n",
- key, (mr->rkey ? mr->rkey : mr->lkey));
+ key, (remote ? mr->rkey : mr->lkey));
ret = -EINVAL;
goto err_drop_ref;
}
@@ -715,7 +712,7 @@ int rxe_reg_fast_mr(struct rxe_qp *qp, struct rxe_send_wqe *wqe)
mr->access = access;
mr->lkey = key;
- mr->rkey = (access & IB_ACCESS_REMOTE) ? key : 0;
+ mr->rkey = key;
mr->ibmr.iova = wqe->wr.wr.reg.mr->iova;
mr->state = RXE_MR_STATE_VALID;
diff --git a/drivers/infiniband/sw/rxe/rxe_mw.c b/drivers/infiniband/sw/rxe/rxe_mw.c
index afa5ce1a7116..d8a43d87de93 100644
--- a/drivers/infiniband/sw/rxe/rxe_mw.c
+++ b/drivers/infiniband/sw/rxe/rxe_mw.c
@@ -48,7 +48,7 @@ int rxe_dealloc_mw(struct ib_mw *ibmw)
}
static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
- struct rxe_mw *mw, struct rxe_mr *mr)
+ struct rxe_mw *mw, struct rxe_mr *mr, int access)
{
if (mw->ibmw.type == IB_MW_TYPE_1) {
if (unlikely(mw->state != RXE_MW_STATE_VALID)) {
@@ -58,7 +58,7 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
}
/* o10-36.2.2 */
- if (unlikely((mw->access & IB_ZERO_BASED))) {
+ if (unlikely((access & IB_ZERO_BASED))) {
rxe_dbg_mw(mw, "attempt to bind a zero based type 1 MW\n");
return -EINVAL;
}
@@ -104,7 +104,7 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
}
/* C10-74 */
- if (unlikely((mw->access &
+ if (unlikely((access &
(IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_ATOMIC)) &&
!(mr->access & IB_ACCESS_LOCAL_WRITE))) {
rxe_dbg_mw(mw,
@@ -113,7 +113,7 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
}
/* C10-75 */
- if (mw->access & IB_ZERO_BASED) {
+ if (access & IB_ZERO_BASED) {
if (unlikely(wqe->wr.wr.mw.length > mr->ibmr.length)) {
rxe_dbg_mw(mw,
"attempt to bind a ZB MW outside of the MR\n");
@@ -133,12 +133,12 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
}
static void rxe_do_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
- struct rxe_mw *mw, struct rxe_mr *mr)
+ struct rxe_mw *mw, struct rxe_mr *mr, int access)
{
u32 key = wqe->wr.wr.mw.rkey & 0xff;
mw->rkey = (mw->rkey & ~0xff) | key;
- mw->access = wqe->wr.wr.mw.access;
+ mw->access = access;
mw->state = RXE_MW_STATE_VALID;
mw->addr = wqe->wr.wr.mw.addr;
mw->length = wqe->wr.wr.mw.length;
@@ -169,6 +169,7 @@ int rxe_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe)
struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
u32 mw_rkey = wqe->wr.wr.mw.mw_rkey;
u32 mr_lkey = wqe->wr.wr.mw.mr_lkey;
+ int access = wqe->wr.wr.mw.access;
mw = rxe_pool_get_index(&rxe->mw_pool, mw_rkey >> 8);
if (unlikely(!mw)) {
@@ -196,13 +197,18 @@ int rxe_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe)
mr = NULL;
}
+ if (access & ~RXE_ACCESS_SUPPORTED_MW) {
+ rxe_err_mw(mw, "access %#x not supported", access);
+ return -EOPNOTSUPP;
+ }
+
spin_lock_bh(&mw->lock);
- ret = rxe_check_bind_mw(qp, wqe, mw, mr);
+ ret = rxe_check_bind_mw(qp, wqe, mw, mr, access);
if (ret)
goto err_unlock;
- rxe_do_bind_mw(qp, wqe, mw, mr);
+ rxe_do_bind_mw(qp, wqe, mw, mr, access);
err_unlock:
spin_unlock_bh(&mw->lock);
err_drop_mr:
diff --git a/drivers/infiniband/sw/rxe/rxe_opcode.h b/drivers/infiniband/sw/rxe/rxe_opcode.h
index cea4e0a63919..5686b691d6b8 100644
--- a/drivers/infiniband/sw/rxe/rxe_opcode.h
+++ b/drivers/infiniband/sw/rxe/rxe_opcode.h
@@ -91,6 +91,9 @@ enum rxe_hdr_mask {
RXE_READ_OR_ATOMIC_MASK = (RXE_READ_MASK | RXE_ATOMIC_MASK),
RXE_WRITE_OR_SEND_MASK = (RXE_WRITE_MASK | RXE_SEND_MASK),
RXE_READ_OR_WRITE_MASK = (RXE_READ_MASK | RXE_WRITE_MASK),
+ RXE_RDMA_OP_MASK = (RXE_READ_MASK | RXE_WRITE_MASK |
+ RXE_ATOMIC_WRITE_MASK | RXE_FLUSH_MASK |
+ RXE_ATOMIC_MASK),
};
#define OPCODE_NONE (-1)
diff --git a/drivers/infiniband/sw/rxe/rxe_param.h b/drivers/infiniband/sw/rxe/rxe_param.h
index 7b41d79e72b2..d2f57ead78ad 100644
--- a/drivers/infiniband/sw/rxe/rxe_param.h
+++ b/drivers/infiniband/sw/rxe/rxe_param.h
@@ -112,7 +112,7 @@ enum rxe_device_param {
RXE_INFLIGHT_SKBS_PER_QP_HIGH = 64,
RXE_INFLIGHT_SKBS_PER_QP_LOW = 16,
- /* Max number of interations of each tasklet
+ /* Max number of interations of each work item
* before yielding the cpu to let other
* work make progress
*/
diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c
index a0f206431cf8..a569b111a9d2 100644
--- a/drivers/infiniband/sw/rxe/rxe_qp.c
+++ b/drivers/infiniband/sw/rxe/rxe_qp.c
@@ -392,6 +392,13 @@ int rxe_qp_chk_attr(struct rxe_dev *rxe, struct rxe_qp *qp,
if (mask & IB_QP_CAP && rxe_qp_chk_cap(rxe, &attr->cap, !!qp->srq))
goto err1;
+ if (mask & IB_QP_ACCESS_FLAGS) {
+ if (!(qp_type(qp) == IB_QPT_RC || qp_type(qp) == IB_QPT_UC))
+ goto err1;
+ if (attr->qp_access_flags & ~RXE_ACCESS_SUPPORTED_QP)
+ goto err1;
+ }
+
if (mask & IB_QP_AV && rxe_av_chk_attr(qp, &attr->ah_attr))
goto err1;
diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
index 5fe7cbae3031..2171f19494bc 100644
--- a/drivers/infiniband/sw/rxe/rxe_req.c
+++ b/drivers/infiniband/sw/rxe/rxe_req.c
@@ -857,7 +857,7 @@ int rxe_requester(struct rxe_qp *qp)
update_state(qp, &pkt);
/* A non-zero return value will cause rxe_do_task to
- * exit its loop and end the tasklet. A zero return
+ * exit its loop and end the work item. A zero return
* will continue looping and return to rxe_requester
*/
done:
diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
index ee68306555b9..64c64f5f36a8 100644
--- a/drivers/infiniband/sw/rxe/rxe_resp.c
+++ b/drivers/infiniband/sw/rxe/rxe_resp.c
@@ -387,7 +387,10 @@ static enum resp_states rxe_resp_check_length(struct rxe_qp *qp,
}
}
- return RESPST_CHK_RKEY;
+ if (pkt->mask & RXE_RDMA_OP_MASK)
+ return RESPST_CHK_RKEY;
+ else
+ return RESPST_EXECUTE;
}
/* if the reth length field is zero we can assume nothing
@@ -434,6 +437,10 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
enum resp_states state;
int access = 0;
+ /* parse RETH or ATMETH header for first/only packets
+ * for va, length, rkey, etc. or use current value for
+ * middle/last packets.
+ */
if (pkt->mask & (RXE_READ_OR_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) {
if (pkt->mask & RXE_RETH_MASK)
qp_resp_from_reth(qp, pkt);
@@ -454,7 +461,8 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
qp_resp_from_atmeth(qp, pkt);
access = IB_ACCESS_REMOTE_ATOMIC;
} else {
- return RESPST_EXECUTE;
+ /* shouldn't happen */
+ WARN_ON(1);
}
/* A zero-byte read or write op is not required to
@@ -1449,8 +1457,17 @@ static void flush_recv_queue(struct rxe_qp *qp, bool notify)
struct rxe_recv_wqe *wqe;
int err;
- if (qp->srq)
+ if (qp->srq) {
+ if (notify && qp->ibqp.event_handler) {
+ struct ib_event ev;
+
+ ev.device = qp->ibqp.device;
+ ev.element.qp = &qp->ibqp;
+ ev.event = IB_EVENT_QP_LAST_WQE_REACHED;
+ qp->ibqp.event_handler(&ev, qp->ibqp.qp_context);
+ }
return;
+ }
while ((wqe = queue_head(q, q->type))) {
if (notify) {
@@ -1657,7 +1674,7 @@ int rxe_responder(struct rxe_qp *qp)
}
/* A non-zero return value will cause rxe_do_task to
- * exit its loop and end the tasklet. A zero return
+ * exit its loop and end the work item. A zero return
* will continue looping and return to rxe_responder
*/
done:
diff --git a/drivers/infiniband/sw/rxe/rxe_task.c b/drivers/infiniband/sw/rxe/rxe_task.c
index fb9a6bc8e620..1501120d4f52 100644
--- a/drivers/infiniband/sw/rxe/rxe_task.c
+++ b/drivers/infiniband/sw/rxe/rxe_task.c
@@ -6,8 +6,24 @@
#include "rxe.h"
+static struct workqueue_struct *rxe_wq;
+
+int rxe_alloc_wq(void)
+{
+ rxe_wq = alloc_workqueue("rxe_wq", WQ_UNBOUND, WQ_MAX_ACTIVE);
+ if (!rxe_wq)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void rxe_destroy_wq(void)
+{
+ destroy_workqueue(rxe_wq);
+}
+
/* Check if task is idle i.e. not running, not scheduled in
- * tasklet queue and not draining. If so move to busy to
+ * work queue and not draining. If so move to busy to
* reserve a slot in do_task() by setting to busy and taking
* a qp reference to cover the gap from now until the task finishes.
* state will move out of busy if task returns a non zero value
@@ -21,9 +37,6 @@ static bool __reserve_if_idle(struct rxe_task *task)
{
WARN_ON(rxe_read(task->qp) <= 0);
- if (task->tasklet.state & BIT(TASKLET_STATE_SCHED))
- return false;
-
if (task->state == TASK_STATE_IDLE) {
rxe_get(task->qp);
task->state = TASK_STATE_BUSY;
@@ -38,7 +51,7 @@ static bool __reserve_if_idle(struct rxe_task *task)
}
/* check if task is idle or drained and not currently
- * scheduled in the tasklet queue. This routine is
+ * scheduled in the work queue. This routine is
* called by rxe_cleanup_task or rxe_disable_task to
* see if the queue is empty.
* Context: caller should hold task->lock.
@@ -46,7 +59,7 @@ static bool __reserve_if_idle(struct rxe_task *task)
*/
static bool __is_done(struct rxe_task *task)
{
- if (task->tasklet.state & BIT(TASKLET_STATE_SCHED))
+ if (work_pending(&task->work))
return false;
if (task->state == TASK_STATE_IDLE ||
@@ -77,23 +90,23 @@ static bool is_done(struct rxe_task *task)
* schedules the task. They must call __reserve_if_idle to
* move the task to busy before calling or scheduling.
* The task can also be moved to drained or invalid
- * by calls to rxe-cleanup_task or rxe_disable_task.
+ * by calls to rxe_cleanup_task or rxe_disable_task.
* In that case tasks which get here are not executed but
* just flushed. The tasks are designed to look to see if
- * there is work to do and do part of it before returning
+ * there is work to do and then do part of it before returning
* here with a return value of zero until all the work
- * has been consumed then it retuens a non-zero value.
+ * has been consumed then it returns a non-zero value.
* The number of times the task can be run is limited by
* max iterations so one task cannot hold the cpu forever.
+ * If the limit is hit and work remains the task is rescheduled.
*/
-static void do_task(struct tasklet_struct *t)
+static void do_task(struct rxe_task *task)
{
- int cont;
- int ret;
- struct rxe_task *task = from_tasklet(task, t, tasklet);
unsigned int iterations;
unsigned long flags;
int resched = 0;
+ int cont;
+ int ret;
WARN_ON(rxe_read(task->qp) <= 0);
@@ -115,25 +128,22 @@ static void do_task(struct tasklet_struct *t)
} while (ret == 0 && iterations-- > 0);
spin_lock_irqsave(&task->lock, flags);
+ /* we're not done yet but we ran out of iterations.
+ * yield the cpu and reschedule the task
+ */
+ if (!ret) {
+ task->state = TASK_STATE_IDLE;
+ resched = 1;
+ goto exit;
+ }
+
switch (task->state) {
case TASK_STATE_BUSY:
- if (ret) {
- task->state = TASK_STATE_IDLE;
- } else {
- /* This can happen if the client
- * can add work faster than the
- * tasklet can finish it.
- * Reschedule the tasklet and exit
- * the loop to give up the cpu
- */
- task->state = TASK_STATE_IDLE;
- resched = 1;
- }
+ task->state = TASK_STATE_IDLE;
break;
- /* someone tried to run the task since the last time we called
- * func, so we will call one more time regardless of the
- * return value
+ /* someone tried to schedule the task while we
+ * were running, keep going
*/
case TASK_STATE_ARMED:
task->state = TASK_STATE_BUSY;
@@ -141,22 +151,24 @@ static void do_task(struct tasklet_struct *t)
break;
case TASK_STATE_DRAINING:
- if (ret)
- task->state = TASK_STATE_DRAINED;
- else
- cont = 1;
+ task->state = TASK_STATE_DRAINED;
break;
default:
WARN_ON(1);
- rxe_info_qp(task->qp, "unexpected task state = %d", task->state);
+ rxe_dbg_qp(task->qp, "unexpected task state = %d",
+ task->state);
+ task->state = TASK_STATE_IDLE;
}
+exit:
if (!cont) {
task->num_done++;
if (WARN_ON(task->num_done != task->num_sched))
- rxe_err_qp(task->qp, "%ld tasks scheduled, %ld tasks done",
- task->num_sched, task->num_done);
+ rxe_dbg_qp(
+ task->qp,
+ "%ld tasks scheduled, %ld tasks done",
+ task->num_sched, task->num_done);
}
spin_unlock_irqrestore(&task->lock, flags);
} while (cont);
@@ -169,6 +181,12 @@ static void do_task(struct tasklet_struct *t)
rxe_put(task->qp);
}
+/* wrapper around do_task to fix argument for work queue */
+static void do_work(struct work_struct *work)
+{
+ do_task(container_of(work, struct rxe_task, work));
+}
+
int rxe_init_task(struct rxe_task *task, struct rxe_qp *qp,
int (*func)(struct rxe_qp *))
{
@@ -176,11 +194,9 @@ int rxe_init_task(struct rxe_task *task, struct rxe_qp *qp,
task->qp = qp;
task->func = func;
-
- tasklet_setup(&task->tasklet, do_task);
-
task->state = TASK_STATE_IDLE;
spin_lock_init(&task->lock);
+ INIT_WORK(&task->work, do_work);
return 0;
}
@@ -213,8 +229,6 @@ void rxe_cleanup_task(struct rxe_task *task)
while (!is_done(task))
cond_resched();
- tasklet_kill(&task->tasklet);
-
spin_lock_irqsave(&task->lock, flags);
task->state = TASK_STATE_INVALID;
spin_unlock_irqrestore(&task->lock, flags);
@@ -226,7 +240,7 @@ void rxe_cleanup_task(struct rxe_task *task)
void rxe_run_task(struct rxe_task *task)
{
unsigned long flags;
- int run;
+ bool run;
WARN_ON(rxe_read(task->qp) <= 0);
@@ -235,11 +249,11 @@ void rxe_run_task(struct rxe_task *task)
spin_unlock_irqrestore(&task->lock, flags);
if (run)
- do_task(&task->tasklet);
+ do_task(task);
}
-/* schedule the task to run later as a tasklet.
- * the tasklet)schedule call can be called holding
+/* schedule the task to run later as a work queue entry.
+ * the queue_work call can be called holding
* the lock.
*/
void rxe_sched_task(struct rxe_task *task)
@@ -250,7 +264,7 @@ void rxe_sched_task(struct rxe_task *task)
spin_lock_irqsave(&task->lock, flags);
if (__reserve_if_idle(task))
- tasklet_schedule(&task->tasklet);
+ queue_work(rxe_wq, &task->work);
spin_unlock_irqrestore(&task->lock, flags);
}
@@ -277,7 +291,9 @@ void rxe_disable_task(struct rxe_task *task)
while (!is_done(task))
cond_resched();
- tasklet_disable(&task->tasklet);
+ spin_lock_irqsave(&task->lock, flags);
+ task->state = TASK_STATE_DRAINED;
+ spin_unlock_irqrestore(&task->lock, flags);
}
void rxe_enable_task(struct rxe_task *task)
@@ -291,7 +307,7 @@ void rxe_enable_task(struct rxe_task *task)
spin_unlock_irqrestore(&task->lock, flags);
return;
}
+
task->state = TASK_STATE_IDLE;
- tasklet_enable(&task->tasklet);
spin_unlock_irqrestore(&task->lock, flags);
}
diff --git a/drivers/infiniband/sw/rxe/rxe_task.h b/drivers/infiniband/sw/rxe/rxe_task.h
index facb7c8e3729..a63e258b3d66 100644
--- a/drivers/infiniband/sw/rxe/rxe_task.h
+++ b/drivers/infiniband/sw/rxe/rxe_task.h
@@ -22,7 +22,7 @@ enum {
* called again.
*/
struct rxe_task {
- struct tasklet_struct tasklet;
+ struct work_struct work;
int state;
spinlock_t lock;
struct rxe_qp *qp;
@@ -32,6 +32,10 @@ struct rxe_task {
long num_done;
};
+int rxe_alloc_wq(void);
+
+void rxe_destroy_wq(void);
+
/*
* init rxe_task structure
* qp => parameter to pass to func
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index 83093e16b6c6..903f0b71447e 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -1182,9 +1182,7 @@ static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
unsigned long irq_flags;
spin_lock_irqsave(&cq->cq_lock, irq_flags);
- if (cq->notify != IB_CQ_NEXT_COMP)
- cq->notify = flags & IB_CQ_SOLICITED_MASK;
-
+ cq->notify |= flags & IB_CQ_SOLICITED_MASK;
empty = queue_empty(cq->queue, QUEUE_TYPE_TO_ULP);
if ((flags & IB_CQ_REPORT_MISSED_EVENTS) && !empty)
@@ -1261,6 +1259,12 @@ static struct ib_mr *rxe_reg_user_mr(struct ib_pd *ibpd, u64 start,
struct rxe_mr *mr;
int err, cleanup_err;
+ if (access & ~RXE_ACCESS_SUPPORTED_MR) {
+ rxe_err_pd(pd, "access = %#x not supported (%#x)", access,
+ RXE_ACCESS_SUPPORTED_MR);
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+
mr = kzalloc(sizeof(*mr), GFP_KERNEL);
if (!mr)
return ERR_PTR(-ENOMEM);
@@ -1294,6 +1298,40 @@ err_free:
return ERR_PTR(err);
}
+static struct ib_mr *rxe_rereg_user_mr(struct ib_mr *ibmr, int flags,
+ u64 start, u64 length, u64 iova,
+ int access, struct ib_pd *ibpd,
+ struct ib_udata *udata)
+{
+ struct rxe_mr *mr = to_rmr(ibmr);
+ struct rxe_pd *old_pd = to_rpd(ibmr->pd);
+ struct rxe_pd *pd = to_rpd(ibpd);
+
+ /* for now only support the two easy cases:
+ * rereg_pd and rereg_access
+ */
+ if (flags & ~RXE_MR_REREG_SUPPORTED) {
+ rxe_err_mr(mr, "flags = %#x not supported", flags);
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+
+ if (flags & IB_MR_REREG_PD) {
+ rxe_put(old_pd);
+ rxe_get(pd);
+ mr->ibmr.pd = ibpd;
+ }
+
+ if (flags & IB_MR_REREG_ACCESS) {
+ if (access & ~RXE_ACCESS_SUPPORTED_MR) {
+ rxe_err_mr(mr, "access = %#x not supported", access);
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+ mr->access = access;
+ }
+
+ return NULL;
+}
+
static struct ib_mr *rxe_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type mr_type,
u32 max_num_sg)
{
@@ -1446,6 +1484,7 @@ static const struct ib_device_ops rxe_dev_ops = {
.query_srq = rxe_query_srq,
.reg_user_mr = rxe_reg_user_mr,
.req_notify_cq = rxe_req_notify_cq,
+ .rereg_user_mr = rxe_rereg_user_mr,
.resize_cq = rxe_resize_cq,
INIT_RDMA_OBJ_SIZE(ib_ah, rxe_ah, ibah),
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h
index 26a20f088692..ccb9d19ffe8a 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.h
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.h
@@ -253,6 +253,22 @@ struct rxe_qp {
struct execute_work cleanup_work;
};
+enum {
+ RXE_ACCESS_REMOTE = IB_ACCESS_REMOTE_READ
+ | IB_ACCESS_REMOTE_WRITE
+ | IB_ACCESS_REMOTE_ATOMIC,
+ RXE_ACCESS_SUPPORTED_MR = RXE_ACCESS_REMOTE
+ | IB_ACCESS_LOCAL_WRITE
+ | IB_ACCESS_MW_BIND
+ | IB_ACCESS_ON_DEMAND
+ | IB_ACCESS_FLUSH_GLOBAL
+ | IB_ACCESS_FLUSH_PERSISTENT
+ | IB_ACCESS_OPTIONAL,
+ RXE_ACCESS_SUPPORTED_QP = RXE_ACCESS_SUPPORTED_MR,
+ RXE_ACCESS_SUPPORTED_MW = RXE_ACCESS_SUPPORTED_MR
+ | IB_ZERO_BASED,
+};
+
enum rxe_mr_state {
RXE_MR_STATE_INVALID,
RXE_MR_STATE_FREE,
@@ -269,6 +285,11 @@ enum rxe_mr_lookup_type {
RXE_LOOKUP_REMOTE,
};
+enum rxe_rereg {
+ RXE_MR_REREG_SUPPORTED = IB_MR_REREG_PD
+ | IB_MR_REREG_ACCESS,
+};
+
static inline int rkey_is_mw(u32 rkey)
{
u32 index = rkey >> 8;
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
index cfb50bfe53c3..b32941dd67cb 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
@@ -1710,7 +1710,6 @@ static int create_con_cq_qp(struct rtrs_clt_con *con)
return -ENOMEM;
con->queue_num = cq_num;
}
- cq_num = max_send_wr + max_recv_wr;
cq_vector = con->cpu % clt_path->s.dev->ib_dev->num_comp_vectors;
if (con->c.cid >= clt_path->s.irq_con_num)
err = rtrs_cq_qp_create(&clt_path->s, &con->c, max_send_sge,
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 735f90b74ee5..3bdbd34314b3 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -168,7 +168,7 @@ config INPUT_EVBUG
config INPUT_KUNIT_TEST
tristate "KUnit tests for Input" if !KUNIT_ALL_TESTS
- depends on INPUT && KUNIT=y
+ depends on INPUT && KUNIT
default KUNIT_ALL_TESTS
help
Say Y here if you want to build the KUnit tests for the input
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index db58a01b23d3..a1443320b419 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -11,6 +11,7 @@
#include <linux/stddef.h>
#include <linux/module.h>
+#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/gameport.h>
@@ -21,8 +22,6 @@
#include <linux/mutex.h>
#include <linux/timekeeping.h>
-/*#include <asm/io.h>*/
-
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Generic gameport layer");
MODULE_LICENSE("GPL");
@@ -518,6 +517,16 @@ void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
}
EXPORT_SYMBOL(gameport_set_phys);
+static void gameport_default_trigger(struct gameport *gameport)
+{
+ outb(0xff, gameport->io);
+}
+
+static unsigned char gameport_default_read(struct gameport *gameport)
+{
+ return inb(gameport->io);
+}
+
/*
* Prepare gameport port for registration.
*/
@@ -536,6 +545,11 @@ static void gameport_init_port(struct gameport *gameport)
if (gameport->parent)
gameport->dev.parent = &gameport->parent->dev;
+ if (!gameport->trigger)
+ gameport->trigger = gameport_default_trigger;
+ if (!gameport->read)
+ gameport->read = gameport_default_read;
+
INIT_LIST_HEAD(&gameport->node);
spin_lock_init(&gameport->timer_lock);
timer_setup(&gameport->poll_timer, gameport_run_poll_handler, 0);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 641eb86f276e..8c5fdb0f858a 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -190,6 +190,7 @@ static int input_handle_abs_event(struct input_dev *dev,
unsigned int code, int *pval)
{
struct input_mt *mt = dev->mt;
+ bool is_new_slot = false;
bool is_mt_event;
int *pold;
@@ -210,6 +211,7 @@ static int input_handle_abs_event(struct input_dev *dev,
pold = &dev->absinfo[code].value;
} else if (mt) {
pold = &mt->slots[mt->slot].abs[code - ABS_MT_FIRST];
+ is_new_slot = mt->slot != dev->absinfo[ABS_MT_SLOT].value;
} else {
/*
* Bypass filtering for multi-touch events when
@@ -228,8 +230,8 @@ static int input_handle_abs_event(struct input_dev *dev,
}
/* Flush pending "slot" event */
- if (is_mt_event && mt && mt->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
- input_abs_set_val(dev, ABS_MT_SLOT, mt->slot);
+ if (is_new_slot) {
+ dev->absinfo[ABS_MT_SLOT].value = mt->slot;
return INPUT_PASS_TO_HANDLERS | INPUT_SLOT;
}
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index 04ca3d1c2816..ac6925ce8366 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -292,33 +292,33 @@ config JOYSTICK_JOYDUMP
module will be called joydump.
config JOYSTICK_XPAD
- tristate "X-Box gamepad support"
+ tristate "Xbox gamepad support"
depends on USB_ARCH_HAS_HCD
select USB
help
- Say Y here if you want to use the X-Box pad with your computer.
+ Say Y here if you want to use Xbox pads with your computer.
Make sure to say Y to "Joystick support" (CONFIG_INPUT_JOYDEV)
and/or "Event interface support" (CONFIG_INPUT_EVDEV) as well.
- For information about how to connect the X-Box pad to USB, see
+ For information about how to connect the Xbox pad to USB, see
<file:Documentation/input/devices/xpad.rst>.
To compile this driver as a module, choose M here: the
module will be called xpad.
config JOYSTICK_XPAD_FF
- bool "X-Box gamepad rumble support"
+ bool "Xbox gamepad rumble support"
depends on JOYSTICK_XPAD && INPUT
select INPUT_FF_MEMLESS
help
- Say Y here if you want to take advantage of xbox 360 rumble features.
+ Say Y here if you want to take advantage of Xbox 360 rumble features.
config JOYSTICK_XPAD_LEDS
- bool "LED Support for Xbox360 controller 'BigX' LED"
+ bool "LED Support for the Xbox 360 controller Guide button"
depends on JOYSTICK_XPAD && (LEDS_CLASS=y || LEDS_CLASS=JOYSTICK_XPAD)
help
This option enables support for the LED which surrounds the Big X on
- XBox 360 controller.
+ Xbox 360 controllers.
config JOYSTICK_WALKERA0701
tristate "Walkera WK-0701 RC transmitter"
diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c
index 3b88f0b49e01..bf8b1cc0ea9c 100644
--- a/drivers/input/joystick/as5011.c
+++ b/drivers/input/joystick/as5011.c
@@ -348,7 +348,7 @@ static struct i2c_driver as5011_driver = {
.driver = {
.name = "as5011",
},
- .probe_new = as5011_probe,
+ .probe = as5011_probe,
.remove = as5011_remove,
.id_table = as5011_id,
};
diff --git a/drivers/input/joystick/qwiic-joystick.c b/drivers/input/joystick/qwiic-joystick.c
index d4da31c0616c..7d88d76b14d6 100644
--- a/drivers/input/joystick/qwiic-joystick.c
+++ b/drivers/input/joystick/qwiic-joystick.c
@@ -137,7 +137,7 @@ static struct i2c_driver qwiic_driver = {
.of_match_table = of_match_ptr(of_qwiic_match),
},
.id_table = qwiic_id_table,
- .probe_new = qwiic_probe,
+ .probe = qwiic_probe,
};
module_i2c_driver(qwiic_driver);
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index f33622fe946f..cdb193317c3b 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * X-Box gamepad driver
+ * Xbox gamepad driver
*
* Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de>
* 2004 Oliver Schwartz <Oliver.Schwartz@gmx.de>,
@@ -23,8 +23,8 @@
* - ITO Takayuki for providing essential xpad information on his website
* - Vojtech Pavlik - iforce driver / input subsystem
* - Greg Kroah-Hartman - usb-skeleton driver
- * - XBOX Linux project - extra USB id's
- * - Pekka Pöyry (quantus) - Xbox One controller reverse engineering
+ * - Xbox Linux project - extra USB IDs
+ * - Pekka Pöyry (quantus) - Xbox One controller reverse-engineering
*
* TODO:
* - fine tune axes (especially trigger axes)
@@ -52,7 +52,7 @@
* 2002-07-17 - 0.0.5 : simplified d-pad handling
*
* 2004-10-02 - 0.0.6 : DDR pad support
- * - borrowed from the XBOX linux kernel
+ * - borrowed from the Xbox Linux kernel
* - USB id's for commonly used dance pads are present
* - dance pads will map D-PAD to buttons, not axes
* - pass the module paramater 'dpad_to_buttons' to force
@@ -454,49 +454,49 @@ static const signed short xpad_btn_paddles[] = {
{ XPAD_XBOXONE_VENDOR_PROTOCOL((vend), 208) }
static const struct usb_device_id xpad_table[] = {
- { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
- XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 Controller */
+ { USB_INTERFACE_INFO('X', 'B', 0) }, /* Xbox USB-IF not-approved class */
+ XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 controller */
XPAD_XBOX360_VENDOR(0x03eb), /* Wooting Keyboards (Legacy) */
- XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster X-Box 360 controllers */
- XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */
- XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */
- XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */
+ XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster Xbox 360 controllers */
+ XPAD_XBOX360_VENDOR(0x045e), /* Microsoft Xbox 360 controllers */
+ XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft Xbox One controllers */
+ XPAD_XBOX360_VENDOR(0x046d), /* Logitech Xbox 360-style controllers */
XPAD_XBOX360_VENDOR(0x056e), /* Elecom JC-U3613M */
XPAD_XBOX360_VENDOR(0x06a3), /* Saitek P3600 */
- XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */
+ XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz Xbox 360 controllers */
{ USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
XPAD_XBOXONE_VENDOR(0x0738), /* Mad Catz FightStick TE 2 */
- XPAD_XBOX360_VENDOR(0x07ff), /* Mad Catz GamePad */
+ XPAD_XBOX360_VENDOR(0x07ff), /* Mad Catz Gamepad */
XPAD_XBOX360_VENDOR(0x0c12), /* Zeroplus X-Box 360 controllers */
- XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */
- XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */
- XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
- XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */
- XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries Controllers */
+ XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f Xbox 360 controllers */
+ XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f Xbox One controllers */
+ XPAD_XBOX360_VENDOR(0x0f0d), /* Hori controllers */
+ XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori controllers */
+ XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries controllers */
XPAD_XBOXONE_VENDOR(0x10f5), /* Turtle Beach Controllers */
XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */
XPAD_XBOX360_VENDOR(0x1209), /* Ardwiino Controllers */
- XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */
- XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
- XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */
+ XPAD_XBOX360_VENDOR(0x12ab), /* Xbox 360 dance pads */
+ XPAD_XBOX360_VENDOR(0x1430), /* RedOctane Xbox 360 controllers */
+ XPAD_XBOX360_VENDOR(0x146b), /* Bigben Interactive controllers */
XPAD_XBOX360_VENDOR(0x1532), /* Razer Sabertooth */
XPAD_XBOXONE_VENDOR(0x1532), /* Razer Wildcat */
- XPAD_XBOX360_VENDOR(0x15e4), /* Numark X-Box 360 controllers */
- XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */
+ XPAD_XBOX360_VENDOR(0x15e4), /* Numark Xbox 360 controllers */
+ XPAD_XBOX360_VENDOR(0x162e), /* Joytech Xbox 360 controllers */
XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */
XPAD_XBOX360_VENDOR(0x1949), /* Amazon controllers */
- XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */
- XPAD_XBOX360_VENDOR(0x20d6), /* PowerA Controllers */
- XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA Controllers */
- XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */
- XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA Controllers */
+ XPAD_XBOX360_VENDOR(0x1bad), /* Harmonix Rock Band guitar and drums */
+ XPAD_XBOX360_VENDOR(0x20d6), /* PowerA controllers */
+ XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA controllers */
+ XPAD_XBOX360_VENDOR(0x24c6), /* PowerA controllers */
+ XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA controllers */
XPAD_XBOX360_VENDOR(0x2563), /* OneXPlayer Gamepad */
XPAD_XBOX360_VENDOR(0x260d), /* Dareu H101 */
XPAD_XBOX360_VENDOR(0x2c22), /* Qanba Controllers */
XPAD_XBOX360_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller */
XPAD_XBOXONE_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller for Xbox */
- XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Duke X-Box One pad */
- XPAD_XBOX360_VENDOR(0x2f24), /* GameSir Controllers */
+ XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Duke Xbox One pad */
+ XPAD_XBOX360_VENDOR(0x2f24), /* GameSir controllers */
XPAD_XBOX360_VENDOR(0x31e3), /* Wooting Keyboards */
XPAD_XBOX360_VENDOR(0x3285), /* Nacon GC-100 */
{ }
@@ -724,7 +724,7 @@ static void xpad360w_poweroff_controller(struct usb_xpad *xpad);
* Completes a request by converting the data into events for the
* input subsystem.
*
- * The used report descriptor was taken from ITO Takayukis website:
+ * The used report descriptor was taken from ITO Takayuki's website:
* http://euc.jp/periphs/xbox-controller.ja.html
*/
static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
@@ -1569,7 +1569,7 @@ struct xpad_led {
};
/*
- * set the LEDs on Xbox360 / Wireless Controllers
+ * set the LEDs on Xbox 360 / Wireless Controllers
* @param command
* 0: off
* 1: all blink, then previous setting
@@ -2229,5 +2229,5 @@ static struct usb_driver xpad_driver = {
module_usb_driver(xpad_driver);
MODULE_AUTHOR("Marko Friedemann <mfr@bmx-chemnitz.de>");
-MODULE_DESCRIPTION("X-Box pad driver");
+MODULE_DESCRIPTION("Xbox pad driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index 72ae5ce72956..896a5a989ddc 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -866,7 +866,7 @@ static struct i2c_driver adp5588_driver = {
.of_match_table = adp5588_of_match,
.pm = pm_sleep_ptr(&adp5588_dev_pm_ops),
},
- .probe_new = adp5588_probe,
+ .probe = adp5588_probe,
.remove = adp5588_remove,
.id_table = adp5588_id,
};
diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c
index 38d7073863a8..8996e00cd63a 100644
--- a/drivers/input/keyboard/adp5589-keys.c
+++ b/drivers/input/keyboard/adp5589-keys.c
@@ -1054,7 +1054,7 @@ static struct i2c_driver adp5589_driver = {
.name = KBUILD_MODNAME,
.pm = pm_sleep_ptr(&adp5589_dev_pm_ops),
},
- .probe_new = adp5589_probe,
+ .probe = adp5589_probe,
.id_table = adp5589_id,
};
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 246958795f60..c92e544c792d 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -309,12 +309,19 @@ static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf)
return vivaldi_function_row_physmap_show(&atkbd->vdata, buf);
}
+static struct atkbd *atkbd_from_serio(struct serio *serio)
+{
+ struct ps2dev *ps2dev = serio_get_drvdata(serio);
+
+ return container_of(ps2dev, struct atkbd, ps2dev);
+}
+
static umode_t atkbd_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int i)
{
struct device *dev = kobj_to_dev(kobj);
struct serio *serio = to_serio_port(dev);
- struct atkbd *atkbd = serio_get_drvdata(serio);
+ struct atkbd *atkbd = atkbd_from_serio(serio);
if (attr == &atkbd_attr_function_row_physmap.attr &&
!atkbd->vdata.num_function_row_keys)
@@ -392,46 +399,60 @@ static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code
}
/*
- * atkbd_interrupt(). Here takes place processing of data received from
- * the keyboard into events.
+ * Tries to handle frame or parity error by requesting the keyboard controller
+ * to resend the last byte. This historically not done on x86 as controllers
+ * there typically do not implement this command.
*/
-
-static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
- unsigned int flags)
+static bool __maybe_unused atkbd_handle_frame_error(struct ps2dev *ps2dev,
+ u8 data, unsigned int flags)
{
- struct atkbd *atkbd = serio_get_drvdata(serio);
- struct input_dev *dev = atkbd->dev;
- unsigned int code = data;
- int scroll = 0, hscroll = 0, click = -1;
- int value;
- unsigned short keycode;
-
- dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags);
+ struct atkbd *atkbd = container_of(ps2dev, struct atkbd, ps2dev);
+ struct serio *serio = ps2dev->serio;
-#if !defined(__i386__) && !defined (__x86_64__)
- if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) {
+ if ((flags & (SERIO_FRAME | SERIO_PARITY)) &&
+ (~flags & SERIO_TIMEOUT) &&
+ !atkbd->resend && atkbd->write) {
dev_warn(&serio->dev, "Frame/parity error: %02x\n", flags);
serio_write(serio, ATKBD_CMD_RESEND);
atkbd->resend = true;
- goto out;
+ return true;
}
if (!flags && data == ATKBD_RET_ACK)
atkbd->resend = false;
+
+ return false;
+}
+
+static enum ps2_disposition atkbd_pre_receive_byte(struct ps2dev *ps2dev,
+ u8 data, unsigned int flags)
+{
+ struct serio *serio = ps2dev->serio;
+
+ dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags);
+
+#if !defined(__i386__) && !defined (__x86_64__)
+ if (atkbd_handle_frame_error(ps2dev, data, flags))
+ return PS2_IGNORE;
#endif
- if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK))
- if (ps2_handle_ack(&atkbd->ps2dev, data))
- goto out;
+ return PS2_PROCESS;
+}
- if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_CMD))
- if (ps2_handle_response(&atkbd->ps2dev, data))
- goto out;
+static void atkbd_receive_byte(struct ps2dev *ps2dev, u8 data)
+{
+ struct serio *serio = ps2dev->serio;
+ struct atkbd *atkbd = container_of(ps2dev, struct atkbd, ps2dev);
+ struct input_dev *dev = atkbd->dev;
+ unsigned int code = data;
+ int scroll = 0, hscroll = 0, click = -1;
+ int value;
+ unsigned short keycode;
pm_wakeup_event(&serio->dev, 0);
if (!atkbd->enabled)
- goto out;
+ return;
input_event(dev, EV_MSC, MSC_RAW, code);
@@ -453,16 +474,16 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
case ATKBD_RET_BAT:
atkbd->enabled = false;
serio_reconnect(atkbd->ps2dev.serio);
- goto out;
+ return;
case ATKBD_RET_EMUL0:
atkbd->emul = 1;
- goto out;
+ return;
case ATKBD_RET_EMUL1:
atkbd->emul = 2;
- goto out;
+ return;
case ATKBD_RET_RELEASE:
atkbd->release = true;
- goto out;
+ return;
case ATKBD_RET_ACK:
case ATKBD_RET_NAK:
if (printk_ratelimit())
@@ -470,18 +491,18 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
"Spurious %s on %s. "
"Some program might be trying to access hardware directly.\n",
data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
- goto out;
+ return;
case ATKBD_RET_ERR:
atkbd->err_count++;
dev_dbg(&serio->dev, "Keyboard on %s reports too many keys pressed.\n",
serio->phys);
- goto out;
+ return;
}
code = atkbd_compat_scancode(atkbd, code);
if (atkbd->emul && --atkbd->emul)
- goto out;
+ return;
keycode = atkbd->keycode[code];
@@ -557,8 +578,6 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
}
atkbd->release = false;
-out:
- return IRQ_HANDLED;
}
static int atkbd_set_repeat_rate(struct atkbd *atkbd)
@@ -909,7 +928,7 @@ static int atkbd_reset_state(struct atkbd *atkbd)
static void atkbd_cleanup(struct serio *serio)
{
- struct atkbd *atkbd = serio_get_drvdata(serio);
+ struct atkbd *atkbd = atkbd_from_serio(serio);
atkbd_disable(atkbd);
ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_DEF);
@@ -922,7 +941,7 @@ static void atkbd_cleanup(struct serio *serio)
static void atkbd_disconnect(struct serio *serio)
{
- struct atkbd *atkbd = serio_get_drvdata(serio);
+ struct atkbd *atkbd = atkbd_from_serio(serio);
atkbd_disable(atkbd);
@@ -1188,7 +1207,7 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd)
static void atkbd_parse_fwnode_data(struct serio *serio)
{
- struct atkbd *atkbd = serio_get_drvdata(serio);
+ struct atkbd *atkbd = atkbd_from_serio(serio);
struct device *dev = &serio->dev;
int n;
@@ -1222,7 +1241,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
goto fail1;
atkbd->dev = dev;
- ps2_init(&atkbd->ps2dev, serio);
+ ps2_init(&atkbd->ps2dev, serio,
+ atkbd_pre_receive_byte, atkbd_receive_byte);
INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
mutex_init(&atkbd->mutex);
@@ -1295,7 +1315,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
static int atkbd_reconnect(struct serio *serio)
{
- struct atkbd *atkbd = serio_get_drvdata(serio);
+ struct atkbd *atkbd = atkbd_from_serio(serio);
struct serio_driver *drv = serio->drv;
int retval = -1;
@@ -1378,7 +1398,7 @@ static struct serio_driver atkbd_drv = {
},
.description = DRIVER_DESC,
.id_table = atkbd_serio_ids,
- .interrupt = atkbd_interrupt,
+ .interrupt = ps2_interrupt,
.connect = atkbd_connect,
.reconnect = atkbd_reconnect,
.disconnect = atkbd_disconnect,
@@ -1389,7 +1409,7 @@ static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
ssize_t (*handler)(struct atkbd *, char *))
{
struct serio *serio = to_serio_port(dev);
- struct atkbd *atkbd = serio_get_drvdata(serio);
+ struct atkbd *atkbd = atkbd_from_serio(serio);
return handler(atkbd, buf);
}
@@ -1398,7 +1418,7 @@ static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t
ssize_t (*handler)(struct atkbd *, const char *, size_t))
{
struct serio *serio = to_serio_port(dev);
- struct atkbd *atkbd = serio_get_drvdata(serio);
+ struct atkbd *atkbd = atkbd_from_serio(serio);
int retval;
retval = mutex_lock_interruptible(&atkbd->mutex);
diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 040696d0e49c..1b4937dce672 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -518,7 +518,7 @@ static struct i2c_driver cap11xx_i2c_driver = {
.of_match_table = cap11xx_dt_ids,
},
.id_table = cap11xx_i2c_ids,
- .probe_new = cap11xx_i2c_probe,
+ .probe = cap11xx_i2c_probe,
};
module_i2c_driver(cap11xx_i2c_driver);
diff --git a/drivers/input/keyboard/cypress-sf.c b/drivers/input/keyboard/cypress-sf.c
index 686388f40317..2bacd9d80ecf 100644
--- a/drivers/input/keyboard/cypress-sf.c
+++ b/drivers/input/keyboard/cypress-sf.c
@@ -229,7 +229,7 @@ static struct i2c_driver cypress_sf_driver = {
.of_match_table = of_match_ptr(cypress_sf_of_match),
},
.id_table = cypress_sf_id_table,
- .probe_new = cypress_sf_probe,
+ .probe = cypress_sf_probe,
};
module_i2c_driver(cypress_sf_driver);
diff --git a/drivers/input/keyboard/dlink-dir685-touchkeys.c b/drivers/input/keyboard/dlink-dir685-touchkeys.c
index ddba2bc861da..6c065eff5a5a 100644
--- a/drivers/input/keyboard/dlink-dir685-touchkeys.c
+++ b/drivers/input/keyboard/dlink-dir685-touchkeys.c
@@ -145,7 +145,7 @@ static struct i2c_driver dir685_tk_i2c_driver = {
.name = "dlink-dir685-touchkeys",
.of_match_table = of_match_ptr(dir685_tk_of_match),
},
- .probe_new = dir685_tk_probe,
+ .probe = dir685_tk_probe,
.id_table = dir685_tk_id,
};
module_i2c_driver(dir685_tk_i2c_driver);
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index c42f86ad0766..c928829a8b0c 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -456,7 +456,7 @@ static enum hrtimer_restart gpio_keys_irq_timer(struct hrtimer *t)
struct input_dev *input = bdata->input;
if (bdata->key_pressed) {
- input_event(input, EV_KEY, *bdata->code, 0);
+ input_report_key(input, *bdata->code, 0);
input_sync(input);
bdata->key_pressed = false;
}
@@ -478,11 +478,11 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
if (bdata->button->wakeup)
pm_wakeup_event(bdata->input->dev.parent, 0);
- input_event(input, EV_KEY, *bdata->code, 1);
+ input_report_key(input, *bdata->code, 1);
input_sync(input);
if (!bdata->release_delay) {
- input_event(input, EV_KEY, *bdata->code, 0);
+ input_report_key(input, *bdata->code, 0);
input_sync(input);
goto out;
}
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index 5df4d5a7ed9e..3964f6e0f6af 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -826,7 +826,7 @@ static struct i2c_driver lm8323_i2c_driver = {
.name = "lm8323",
.pm = pm_sleep_ptr(&lm8323_pm_ops),
},
- .probe_new = lm8323_probe,
+ .probe = lm8323_probe,
.remove = lm8323_remove,
.id_table = lm8323_id,
};
diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c
index 7457c3220f90..c9f05764e36d 100644
--- a/drivers/input/keyboard/lm8333.c
+++ b/drivers/input/keyboard/lm8333.c
@@ -218,7 +218,7 @@ static struct i2c_driver lm8333_driver = {
.driver = {
.name = "lm8333",
},
- .probe_new = lm8333_probe,
+ .probe = lm8333_probe,
.remove = lm8333_remove,
.id_table = lm8333_id,
};
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c
index b363749d02e2..faab7691c219 100644
--- a/drivers/input/keyboard/max7359_keypad.c
+++ b/drivers/input/keyboard/max7359_keypad.c
@@ -280,7 +280,7 @@ static struct i2c_driver max7359_i2c_driver = {
.name = "max7359",
.pm = pm_sleep_ptr(&max7359_pm),
},
- .probe_new = max7359_probe,
+ .probe = max7359_probe,
.id_table = max7359_ids,
};
diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
index d414e19e4559..de312d8eb974 100644
--- a/drivers/input/keyboard/mcs_touchkey.c
+++ b/drivers/input/keyboard/mcs_touchkey.c
@@ -258,7 +258,7 @@ static struct i2c_driver mcs_touchkey_driver = {
.name = "mcs_touchkey",
.pm = pm_sleep_ptr(&mcs_touchkey_pm_ops),
},
- .probe_new = mcs_touchkey_probe,
+ .probe = mcs_touchkey_probe,
.remove = mcs_touchkey_remove,
.shutdown = mcs_touchkey_shutdown,
.id_table = mcs_touchkey_id,
diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index 74ad353462a3..d434753afab1 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -389,7 +389,7 @@ static struct i2c_driver mpr_touchkey_driver = {
.of_match_table = of_match_ptr(mpr121_touchkey_dt_match_table),
},
.id_table = mpr121_id,
- .probe_new = mpr_touchkey_probe,
+ .probe = mpr_touchkey_probe,
};
module_i2c_driver(mpr_touchkey_driver);
diff --git a/drivers/input/keyboard/pinephone-keyboard.c b/drivers/input/keyboard/pinephone-keyboard.c
index 5548699b8b38..038ff3549a7a 100644
--- a/drivers/input/keyboard/pinephone-keyboard.c
+++ b/drivers/input/keyboard/pinephone-keyboard.c
@@ -455,7 +455,7 @@ static const struct of_device_id ppkb_of_match[] = {
MODULE_DEVICE_TABLE(of, ppkb_of_match);
static struct i2c_driver ppkb_driver = {
- .probe_new = ppkb_probe,
+ .probe = ppkb_probe,
.driver = {
.name = DRV_NAME,
.of_match_table = ppkb_of_match,
diff --git a/drivers/input/keyboard/qt1050.c b/drivers/input/keyboard/qt1050.c
index 317fe2b1f827..6953097db445 100644
--- a/drivers/input/keyboard/qt1050.c
+++ b/drivers/input/keyboard/qt1050.c
@@ -588,7 +588,7 @@ static struct i2c_driver qt1050_driver = {
.of_match_table = of_match_ptr(qt1050_of_match),
.pm = pm_sleep_ptr(&qt1050_pm_ops),
},
- .probe_new = qt1050_probe,
+ .probe = qt1050_probe,
};
module_i2c_driver(qt1050_driver);
diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c
index fabb50bde844..91aaa9fc43a4 100644
--- a/drivers/input/keyboard/qt1070.c
+++ b/drivers/input/keyboard/qt1070.c
@@ -271,7 +271,7 @@ static struct i2c_driver qt1070_driver = {
.pm = pm_sleep_ptr(&qt1070_pm_ops),
},
.id_table = qt1070_id,
- .probe_new = qt1070_probe,
+ .probe = qt1070_probe,
.remove = qt1070_remove,
};
diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
index 04d2ee6ff577..599ea85cfd30 100644
--- a/drivers/input/keyboard/qt2160.c
+++ b/drivers/input/keyboard/qt2160.c
@@ -460,7 +460,7 @@ static struct i2c_driver qt2160_driver = {
},
.id_table = qt2160_idtable,
- .probe_new = qt2160_probe,
+ .probe = qt2160_probe,
.remove = qt2160_remove,
};
diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c
index 673b905af6fe..2f745cabf4f2 100644
--- a/drivers/input/keyboard/tca6416-keypad.c
+++ b/drivers/input/keyboard/tca6416-keypad.c
@@ -350,7 +350,7 @@ static struct i2c_driver tca6416_keypad_driver = {
.name = "tca6416-keypad",
.pm = pm_sleep_ptr(&tca6416_keypad_dev_pm_ops),
},
- .probe_new = tca6416_keypad_probe,
+ .probe = tca6416_keypad_probe,
.remove = tca6416_keypad_remove,
.id_table = tca6416_id,
};
diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c
index 3d7492f38337..76fc19ffe21d 100644
--- a/drivers/input/keyboard/tca8418_keypad.c
+++ b/drivers/input/keyboard/tca8418_keypad.c
@@ -370,7 +370,7 @@ static struct i2c_driver tca8418_keypad_driver = {
.name = "tca8418_keypad",
.of_match_table = tca8418_dt_ids,
},
- .probe_new = tca8418_keypad_probe,
+ .probe = tca8418_keypad_probe,
.id_table = tca8418_id,
};
diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c
index 4e20571cb4c3..75bd3ea51194 100644
--- a/drivers/input/keyboard/tm2-touchkey.c
+++ b/drivers/input/keyboard/tm2-touchkey.c
@@ -356,7 +356,7 @@ static struct i2c_driver tm2_touchkey_driver = {
.pm = pm_sleep_ptr(&tm2_touchkey_pm_ops),
.of_match_table = tm2_touchkey_of_match,
},
- .probe_new = tm2_touchkey_probe,
+ .probe = tm2_touchkey_probe,
.id_table = tm2_touchkey_id_table,
};
module_i2c_driver(tm2_touchkey_driver);
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
index d8e39f4a57ac..679fcfea942c 100644
--- a/drivers/input/misc/ad714x-i2c.c
+++ b/drivers/input/misc/ad714x-i2c.c
@@ -86,7 +86,7 @@ static struct i2c_driver ad714x_i2c_driver = {
.name = "ad714x_captouch",
.pm = pm_sleep_ptr(&ad714x_pm),
},
- .probe_new = ad714x_i2c_probe,
+ .probe = ad714x_i2c_probe,
.id_table = ad714x_id,
};
diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c
index 1c75d98c85a7..6b880e282d99 100644
--- a/drivers/input/misc/adxl34x-i2c.c
+++ b/drivers/input/misc/adxl34x-i2c.c
@@ -135,7 +135,7 @@ static struct i2c_driver adxl34x_driver = {
.pm = pm_sleep_ptr(&adxl34x_pm),
.of_match_table = adxl34x_of_id,
},
- .probe_new = adxl34x_i2c_probe,
+ .probe = adxl34x_i2c_probe,
.remove = adxl34x_i2c_remove,
.id_table = adxl34x_id,
};
diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c
index eecca671b588..a3f45e0ee0c7 100644
--- a/drivers/input/misc/adxl34x.c
+++ b/drivers/input/misc/adxl34x.c
@@ -817,8 +817,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
AC_WRITE(ac, POWER_CTL, 0);
err = request_threaded_irq(ac->irq, NULL, adxl34x_irq,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
- dev_name(dev), ac);
+ IRQF_ONESHOT, dev_name(dev), ac);
if (err) {
dev_err(dev, "irq %d busy?\n", ac->irq);
goto err_free_mem;
diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c
index f42d3219cdcc..b5219bbe856d 100644
--- a/drivers/input/misc/apanel.c
+++ b/drivers/input/misc/apanel.c
@@ -201,7 +201,7 @@ static struct i2c_driver apanel_driver = {
.driver = {
.name = APANEL,
},
- .probe_new = apanel_probe,
+ .probe = apanel_probe,
.shutdown = apanel_shutdown,
.id_table = apanel_id,
};
diff --git a/drivers/input/misc/atmel_captouch.c b/drivers/input/misc/atmel_captouch.c
index d9704b174d3a..b6a30044e814 100644
--- a/drivers/input/misc/atmel_captouch.c
+++ b/drivers/input/misc/atmel_captouch.c
@@ -263,7 +263,7 @@ static const struct i2c_device_id atmel_captouch_id[] = {
MODULE_DEVICE_TABLE(i2c, atmel_captouch_id);
static struct i2c_driver atmel_captouch_driver = {
- .probe_new = atmel_captouch_probe,
+ .probe = atmel_captouch_probe,
.id_table = atmel_captouch_id,
.driver = {
.name = "atmel_captouch",
diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
index 3f9da5c3cb53..0fb4cc628f29 100644
--- a/drivers/input/misc/bma150.c
+++ b/drivers/input/misc/bma150.c
@@ -551,7 +551,7 @@ static struct i2c_driver bma150_driver = {
},
.class = I2C_CLASS_HWMON,
.id_table = bma150_id,
- .probe_new = bma150_probe,
+ .probe = bma150_probe,
.remove = bma150_remove,
};
diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c
index 136eb3715870..a4dfb3052dc0 100644
--- a/drivers/input/misc/cma3000_d0x_i2c.c
+++ b/drivers/input/misc/cma3000_d0x_i2c.c
@@ -97,7 +97,7 @@ static const struct i2c_device_id cma3000_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, cma3000_i2c_id);
static struct i2c_driver cma3000_i2c_driver = {
- .probe_new = cma3000_i2c_probe,
+ .probe = cma3000_i2c_probe,
.remove = cma3000_i2c_remove,
.id_table = cma3000_i2c_id,
.driver = {
diff --git a/drivers/input/misc/da7280.c b/drivers/input/misc/da7280.c
index b85a19e3554f..ce82548916bb 100644
--- a/drivers/input/misc/da7280.c
+++ b/drivers/input/misc/da7280.c
@@ -1321,7 +1321,7 @@ static struct i2c_driver da7280_driver = {
.of_match_table = of_match_ptr(da7280_of_match),
.pm = pm_sleep_ptr(&da7280_pm_ops),
},
- .probe_new = da7280_probe,
+ .probe = da7280_probe,
.id_table = da7280_i2c_id,
};
module_i2c_driver(da7280_driver);
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index 8a9ebfc04a2d..6717e3c9549b 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -149,7 +149,7 @@
/* Control 3 Register */
#define DRV260X_LRA_OPEN_LOOP (1 << 0)
-#define DRV260X_ANANLOG_IN (1 << 1)
+#define DRV260X_ANALOG_IN (1 << 1)
#define DRV260X_LRA_DRV_MODE (1 << 2)
#define DRV260X_RTP_UNSIGNED_DATA (1 << 3)
#define DRV260X_SUPPLY_COMP_DIS (1 << 4)
@@ -186,51 +186,13 @@ struct drv260x_data {
struct work_struct work;
struct gpio_desc *enable_gpio;
struct regulator *regulator;
- u32 magnitude;
+ u8 magnitude;
u32 mode;
u32 library;
int rated_voltage;
int overdrive_voltage;
};
-static const struct reg_default drv260x_reg_defs[] = {
- { DRV260X_STATUS, 0xe0 },
- { DRV260X_MODE, 0x40 },
- { DRV260X_RT_PB_IN, 0x00 },
- { DRV260X_LIB_SEL, 0x00 },
- { DRV260X_WV_SEQ_1, 0x01 },
- { DRV260X_WV_SEQ_2, 0x00 },
- { DRV260X_WV_SEQ_3, 0x00 },
- { DRV260X_WV_SEQ_4, 0x00 },
- { DRV260X_WV_SEQ_5, 0x00 },
- { DRV260X_WV_SEQ_6, 0x00 },
- { DRV260X_WV_SEQ_7, 0x00 },
- { DRV260X_WV_SEQ_8, 0x00 },
- { DRV260X_GO, 0x00 },
- { DRV260X_OVERDRIVE_OFF, 0x00 },
- { DRV260X_SUSTAIN_P_OFF, 0x00 },
- { DRV260X_SUSTAIN_N_OFF, 0x00 },
- { DRV260X_BRAKE_OFF, 0x00 },
- { DRV260X_A_TO_V_CTRL, 0x05 },
- { DRV260X_A_TO_V_MIN_INPUT, 0x19 },
- { DRV260X_A_TO_V_MAX_INPUT, 0xff },
- { DRV260X_A_TO_V_MIN_OUT, 0x19 },
- { DRV260X_A_TO_V_MAX_OUT, 0xff },
- { DRV260X_RATED_VOLT, 0x3e },
- { DRV260X_OD_CLAMP_VOLT, 0x8c },
- { DRV260X_CAL_COMP, 0x0c },
- { DRV260X_CAL_BACK_EMF, 0x6c },
- { DRV260X_FEEDBACK_CTRL, 0x36 },
- { DRV260X_CTRL1, 0x93 },
- { DRV260X_CTRL2, 0xfa },
- { DRV260X_CTRL3, 0xa0 },
- { DRV260X_CTRL4, 0x20 },
- { DRV260X_CTRL5, 0x80 },
- { DRV260X_LRA_LOOP_PERIOD, 0x33 },
- { DRV260X_VBAT_MON, 0x00 },
- { DRV260X_LRA_RES_PERIOD, 0x00 },
-};
-
#define DRV260X_DEF_RATED_VOLT 0x90
#define DRV260X_DEF_OD_CLAMP_VOLT 0x90
@@ -275,10 +237,11 @@ static int drv260x_haptics_play(struct input_dev *input, void *data,
haptics->mode = DRV260X_LRA_NO_CAL_MODE;
+ /* Scale u16 magnitude into u8 register value */
if (effect->u.rumble.strong_magnitude > 0)
- haptics->magnitude = effect->u.rumble.strong_magnitude;
+ haptics->magnitude = effect->u.rumble.strong_magnitude >> 8;
else if (effect->u.rumble.weak_magnitude > 0)
- haptics->magnitude = effect->u.rumble.weak_magnitude;
+ haptics->magnitude = effect->u.rumble.weak_magnitude >> 8;
else
haptics->magnitude = 0;
@@ -304,7 +267,7 @@ static void drv260x_close(struct input_dev *input)
static const struct reg_sequence drv260x_lra_cal_regs[] = {
{ DRV260X_MODE, DRV260X_AUTO_CAL },
- { DRV260X_CTRL3, DRV260X_NG_THRESH_2 },
+ { DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_RTP_UNSIGNED_DATA },
{ DRV260X_FEEDBACK_CTRL, DRV260X_FB_REG_LRA_MODE |
DRV260X_BRAKE_FACTOR_4X | DRV260X_LOOP_GAIN_HIGH },
};
@@ -322,7 +285,7 @@ static const struct reg_sequence drv260x_lra_init_regs[] = {
DRV260X_BEMF_GAIN_3 },
{ DRV260X_CTRL1, DRV260X_STARTUP_BOOST },
{ DRV260X_CTRL2, DRV260X_SAMP_TIME_250 },
- { DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_ANANLOG_IN },
+ { DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_RTP_UNSIGNED_DATA | DRV260X_ANALOG_IN },
{ DRV260X_CTRL4, DRV260X_AUTOCAL_TIME_500MS },
};
@@ -337,7 +300,7 @@ static const struct reg_sequence drv260x_erm_cal_regs[] = {
{ DRV260X_CTRL1, DRV260X_STARTUP_BOOST },
{ DRV260X_CTRL2, DRV260X_SAMP_TIME_250 | DRV260X_BLANK_TIME_75 |
DRV260X_IDISS_TIME_75 },
- { DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_ERM_OPEN_LOOP },
+ { DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_RTP_UNSIGNED_DATA },
{ DRV260X_CTRL4, DRV260X_AUTOCAL_TIME_500MS },
};
@@ -435,6 +398,7 @@ static int drv260x_init(struct drv260x_data *haptics)
}
do {
+ usleep_range(15000, 15500);
error = regmap_read(haptics->regmap, DRV260X_GO, &cal_buf);
if (error) {
dev_err(&haptics->client->dev,
@@ -452,8 +416,6 @@ static const struct regmap_config drv260x_regmap_config = {
.val_bits = 8,
.max_register = DRV260X_MAX_REG,
- .reg_defaults = drv260x_reg_defs,
- .num_reg_defaults = ARRAY_SIZE(drv260x_reg_defs),
.cache_type = REGCACHE_NONE,
};
@@ -653,7 +615,7 @@ static const struct of_device_id drv260x_of_match[] = {
MODULE_DEVICE_TABLE(of, drv260x_of_match);
static struct i2c_driver drv260x_driver = {
- .probe_new = drv260x_probe,
+ .probe = drv260x_probe,
.driver = {
.name = "drv260x-haptics",
.of_match_table = drv260x_of_match,
diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c
index 9145096f80ea..de27e6079d84 100644
--- a/drivers/input/misc/drv2665.c
+++ b/drivers/input/misc/drv2665.c
@@ -297,7 +297,7 @@ MODULE_DEVICE_TABLE(of, drv2665_of_match);
#endif
static struct i2c_driver drv2665_driver = {
- .probe_new = drv2665_probe,
+ .probe = drv2665_probe,
.driver = {
.name = "drv2665-haptics",
.of_match_table = of_match_ptr(drv2665_of_match),
diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c
index 88b4dbe3e5b5..11c5855256e8 100644
--- a/drivers/input/misc/drv2667.c
+++ b/drivers/input/misc/drv2667.c
@@ -474,7 +474,7 @@ MODULE_DEVICE_TABLE(of, drv2667_of_match);
#endif
static struct i2c_driver drv2667_driver = {
- .probe_new = drv2667_probe,
+ .probe = drv2667_probe,
.driver = {
.name = "drv2667-haptics",
.of_match_table = of_match_ptr(drv2667_of_match),
diff --git a/drivers/input/misc/ibm-panel.c b/drivers/input/misc/ibm-panel.c
index 3969ffc1bc8d..867ac7aa10d2 100644
--- a/drivers/input/misc/ibm-panel.c
+++ b/drivers/input/misc/ibm-panel.c
@@ -189,7 +189,7 @@ static struct i2c_driver ibm_panel_driver = {
.name = DEVICE_NAME,
.of_match_table = ibm_panel_match,
},
- .probe_new = ibm_panel_probe,
+ .probe = ibm_panel_probe,
.remove = ibm_panel_remove,
};
module_i2c_driver(ibm_panel_driver);
diff --git a/drivers/input/misc/iqs269a.c b/drivers/input/misc/iqs269a.c
index f4c3aff3895b..1272ef7b5794 100644
--- a/drivers/input/misc/iqs269a.c
+++ b/drivers/input/misc/iqs269a.c
@@ -1746,7 +1746,7 @@ static struct i2c_driver iqs269_i2c_driver = {
.of_match_table = iqs269_of_match,
.pm = pm_sleep_ptr(&iqs269_pm),
},
- .probe_new = iqs269_probe,
+ .probe = iqs269_probe,
};
module_i2c_driver(iqs269_i2c_driver);
diff --git a/drivers/input/misc/iqs626a.c b/drivers/input/misc/iqs626a.c
index 90f997a905b5..50035c25c3f7 100644
--- a/drivers/input/misc/iqs626a.c
+++ b/drivers/input/misc/iqs626a.c
@@ -1822,7 +1822,7 @@ static struct i2c_driver iqs626_i2c_driver = {
.of_match_table = iqs626_of_match,
.pm = pm_sleep_ptr(&iqs626_pm),
},
- .probe_new = iqs626_probe,
+ .probe = iqs626_probe,
};
module_i2c_driver(iqs626_i2c_driver);
diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c
index e47ab6c1177f..096b0925f41b 100644
--- a/drivers/input/misc/iqs7222.c
+++ b/drivers/input/misc/iqs7222.c
@@ -2593,7 +2593,7 @@ static struct i2c_driver iqs7222_i2c_driver = {
.name = "iqs7222",
.of_match_table = iqs7222_of_match,
},
- .probe_new = iqs7222_probe,
+ .probe = iqs7222_probe,
};
module_i2c_driver(iqs7222_i2c_driver);
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index 4e806d56c55d..912e614d039d 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -538,7 +538,7 @@ static struct i2c_driver kxtj9_driver = {
.name = NAME,
.pm = pm_sleep_ptr(&kxtj9_pm_ops),
},
- .probe_new = kxtj9_probe,
+ .probe = kxtj9_probe,
.id_table = kxtj9_id,
};
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c
index b12152536976..76a190b2220b 100644
--- a/drivers/input/misc/mma8450.c
+++ b/drivers/input/misc/mma8450.c
@@ -202,7 +202,7 @@ static struct i2c_driver mma8450_driver = {
.name = MMA8450_DRV_NAME,
.of_match_table = mma8450_dt_ids,
},
- .probe_new = mma8450_probe,
+ .probe = mma8450_probe,
.id_table = mma8450_id,
};
diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c
index 6323c3d37ef7..536cedeb38e6 100644
--- a/drivers/input/misc/pcf8574_keypad.c
+++ b/drivers/input/misc/pcf8574_keypad.c
@@ -199,7 +199,7 @@ static struct i2c_driver pcf8574_kp_driver = {
.name = DRV_NAME,
.pm = pm_sleep_ptr(&pcf8574_kp_pm_ops),
},
- .probe_new = pcf8574_kp_probe,
+ .probe = pcf8574_kp_probe,
.remove = pcf8574_kp_remove,
.id_table = pcf8574_kp_id,
};
diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c
index b6a27ebae977..74d77d8aaeff 100644
--- a/drivers/input/misc/pm8941-pwrkey.c
+++ b/drivers/input/misc/pm8941-pwrkey.c
@@ -50,7 +50,10 @@
#define PON_RESIN_PULL_UP BIT(0)
#define PON_DBC_CTL 0x71
-#define PON_DBC_DELAY_MASK 0x7
+#define PON_DBC_DELAY_MASK_GEN1 0x7
+#define PON_DBC_DELAY_MASK_GEN2 0xf
+#define PON_DBC_SHIFT_GEN1 6
+#define PON_DBC_SHIFT_GEN2 14
struct pm8941_data {
unsigned int pull_up_bit;
@@ -247,7 +250,7 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
struct device *parent;
struct device_node *regmap_node;
const __be32 *addr;
- u32 req_delay;
+ u32 req_delay, mask, delay_shift;
int error;
if (of_property_read_u32(pdev->dev.of_node, "debounce", &req_delay))
@@ -336,12 +339,20 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
pwrkey->input->phys = pwrkey->data->phys;
if (pwrkey->data->supports_debounce_config) {
- req_delay = (req_delay << 6) / USEC_PER_SEC;
+ if (pwrkey->subtype >= PON_SUBTYPE_GEN2_PRIMARY) {
+ mask = PON_DBC_DELAY_MASK_GEN2;
+ delay_shift = PON_DBC_SHIFT_GEN2;
+ } else {
+ mask = PON_DBC_DELAY_MASK_GEN1;
+ delay_shift = PON_DBC_SHIFT_GEN1;
+ }
+
+ req_delay = (req_delay << delay_shift) / USEC_PER_SEC;
req_delay = ilog2(req_delay);
error = regmap_update_bits(pwrkey->regmap,
pwrkey->baseaddr + PON_DBC_CTL,
- PON_DBC_DELAY_MASK,
+ mask,
req_delay);
if (error) {
dev_err(&pdev->dev, "failed to set debounce: %d\n",
diff --git a/drivers/input/misc/pwm-vibra.c b/drivers/input/misc/pwm-vibra.c
index d0e58a7cdfa3..2ba035299db8 100644
--- a/drivers/input/misc/pwm-vibra.c
+++ b/drivers/input/misc/pwm-vibra.c
@@ -11,6 +11,7 @@
* Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
*/
+#include <linux/gpio/consumer.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -23,6 +24,7 @@
struct pwm_vibrator {
struct input_dev *input;
+ struct gpio_desc *enable_gpio;
struct pwm_device *pwm;
struct pwm_device *pwm_dir;
struct regulator *vcc;
@@ -42,19 +44,21 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
if (!vibrator->vcc_on) {
err = regulator_enable(vibrator->vcc);
if (err) {
- dev_err(pdev, "failed to enable regulator: %d", err);
+ dev_err(pdev, "failed to enable regulator: %d\n", err);
return err;
}
vibrator->vcc_on = true;
}
+ gpiod_set_value_cansleep(vibrator->enable_gpio, 1);
+
pwm_get_state(vibrator->pwm, &state);
pwm_set_relative_duty_cycle(&state, vibrator->level, 0xffff);
state.enabled = true;
err = pwm_apply_state(vibrator->pwm, &state);
if (err) {
- dev_err(pdev, "failed to apply pwm state: %d", err);
+ dev_err(pdev, "failed to apply pwm state: %d\n", err);
return err;
}
@@ -65,7 +69,7 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
err = pwm_apply_state(vibrator->pwm_dir, &state);
if (err) {
- dev_err(pdev, "failed to apply dir-pwm state: %d", err);
+ dev_err(pdev, "failed to apply dir-pwm state: %d\n", err);
pwm_disable(vibrator->pwm);
return err;
}
@@ -80,6 +84,8 @@ static void pwm_vibrator_stop(struct pwm_vibrator *vibrator)
pwm_disable(vibrator->pwm_dir);
pwm_disable(vibrator->pwm);
+ gpiod_set_value_cansleep(vibrator->enable_gpio, 0);
+
if (vibrator->vcc_on) {
regulator_disable(vibrator->vcc);
vibrator->vcc_on = false;
@@ -137,7 +143,17 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
err = PTR_ERR_OR_ZERO(vibrator->vcc);
if (err) {
if (err != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Failed to request regulator: %d",
+ dev_err(&pdev->dev, "Failed to request regulator: %d\n",
+ err);
+ return err;
+ }
+
+ vibrator->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
+ GPIOD_OUT_LOW);
+ err = PTR_ERR_OR_ZERO(vibrator->enable_gpio);
+ if (err) {
+ if (err != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to request enable gpio: %d\n",
err);
return err;
}
@@ -146,7 +162,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
err = PTR_ERR_OR_ZERO(vibrator->pwm);
if (err) {
if (err != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Failed to request main pwm: %d",
+ dev_err(&pdev->dev, "Failed to request main pwm: %d\n",
err);
return err;
}
@@ -158,7 +174,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
state.enabled = false;
err = pwm_apply_state(vibrator->pwm, &state);
if (err) {
- dev_err(&pdev->dev, "failed to apply initial PWM state: %d",
+ dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
err);
return err;
}
@@ -172,7 +188,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
state.enabled = false;
err = pwm_apply_state(vibrator->pwm_dir, &state);
if (err) {
- dev_err(&pdev->dev, "failed to apply initial PWM state: %d",
+ dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
err);
return err;
}
@@ -189,7 +205,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
break;
default:
- dev_err(&pdev->dev, "Failed to request direction pwm: %d", err);
+ dev_err(&pdev->dev, "Failed to request direction pwm: %d\n", err);
fallthrough;
case -EPROBE_DEFER:
@@ -207,13 +223,13 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
err = input_ff_create_memless(vibrator->input, NULL,
pwm_vibrator_play_effect);
if (err) {
- dev_err(&pdev->dev, "Couldn't create FF dev: %d", err);
+ dev_err(&pdev->dev, "Couldn't create FF dev: %d\n", err);
return err;
}
err = input_register_device(vibrator->input);
if (err) {
- dev_err(&pdev->dev, "Couldn't register input dev: %d", err);
+ dev_err(&pdev->dev, "Couldn't register input dev: %d\n", err);
return err;
}
diff --git a/drivers/input/misc/tps65219-pwrbutton.c b/drivers/input/misc/tps65219-pwrbutton.c
index 245134bdb59e..eeb9f2334ab4 100644
--- a/drivers/input/misc/tps65219-pwrbutton.c
+++ b/drivers/input/misc/tps65219-pwrbutton.c
@@ -117,14 +117,16 @@ static int tps65219_pb_probe(struct platform_device *pdev)
return 0;
}
-static int tps65219_pb_remove(struct platform_device *pdev)
+static void tps65219_pb_remove(struct platform_device *pdev)
{
struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent);
+ int ret;
/* Disable interrupt for the pushbutton */
- return regmap_update_bits(tps->regmap, TPS65219_REG_MASK_CONFIG,
- TPS65219_REG_MASK_INT_FOR_PB_MASK,
- TPS65219_REG_MASK_INT_FOR_PB_MASK);
+ ret = regmap_set_bits(tps->regmap, TPS65219_REG_MASK_CONFIG,
+ TPS65219_REG_MASK_INT_FOR_PB_MASK);
+ if (ret)
+ dev_warn(&pdev->dev, "Failed to disable irq (%pe)\n", ERR_PTR(ret));
}
static const struct platform_device_id tps65219_pwrbtn_id_table[] = {
@@ -135,7 +137,7 @@ MODULE_DEVICE_TABLE(platform, tps65219_pwrbtn_id_table);
static struct platform_driver tps65219_pb_driver = {
.probe = tps65219_pb_probe,
- .remove = tps65219_pb_remove,
+ .remove_new = tps65219_pb_remove,
.driver = {
.name = "tps65219_pwrbutton",
},
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index f2593133e524..d98212d55108 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -33,6 +33,7 @@
#define UINPUT_NAME "uinput"
#define UINPUT_BUFFER_SIZE 16
#define UINPUT_NUM_REQUESTS 16
+#define UINPUT_TIMESTAMP_ALLOWED_OFFSET_SECS 10
enum uinput_state { UIST_NEW_DEVICE, UIST_SETUP_COMPLETE, UIST_CREATED };
@@ -569,11 +570,40 @@ static int uinput_setup_device_legacy(struct uinput_device *udev,
return retval;
}
+/*
+ * Returns true if the given timestamp is valid (i.e., if all the following
+ * conditions are satisfied), false otherwise.
+ * 1) given timestamp is positive
+ * 2) it's within the allowed offset before the current time
+ * 3) it's not in the future
+ */
+static bool is_valid_timestamp(const ktime_t timestamp)
+{
+ ktime_t zero_time;
+ ktime_t current_time;
+ ktime_t min_time;
+ ktime_t offset;
+
+ zero_time = ktime_set(0, 0);
+ if (ktime_compare(zero_time, timestamp) >= 0)
+ return false;
+
+ current_time = ktime_get();
+ offset = ktime_set(UINPUT_TIMESTAMP_ALLOWED_OFFSET_SECS, 0);
+ min_time = ktime_sub(current_time, offset);
+
+ if (ktime_after(min_time, timestamp) || ktime_after(timestamp, current_time))
+ return false;
+
+ return true;
+}
+
static ssize_t uinput_inject_events(struct uinput_device *udev,
const char __user *buffer, size_t count)
{
struct input_event ev;
size_t bytes = 0;
+ ktime_t timestamp;
if (count != 0 && count < input_event_size())
return -EINVAL;
@@ -588,6 +618,10 @@ static ssize_t uinput_inject_events(struct uinput_device *udev,
if (input_event_from_user(buffer + bytes, &ev))
return -EFAULT;
+ timestamp = ktime_set(ev.input_event_sec, ev.input_event_usec * NSEC_PER_USEC);
+ if (is_valid_timestamp(timestamp))
+ input_set_timestamp(udev->dev, timestamp);
+
input_event(udev->dev, ev.type, ev.code, ev.value);
bytes += input_event_size();
cond_resched();
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index dd7b0d70d791..05851bc32541 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -1489,7 +1489,7 @@ static struct i2c_driver cyapa_driver = {
.of_match_table = of_match_ptr(cyapa_of_match),
},
- .probe_new = cyapa_probe,
+ .probe = cyapa_probe,
.id_table = cyapa_id_table,
};
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 5f0d75a45c80..0cff742302a9 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -1424,7 +1424,7 @@ static struct i2c_driver elan_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.dev_groups = elan_sysfs_groups,
},
- .probe_new = elan_probe,
+ .probe = elan_probe,
.id_table = elan_id,
};
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index c9a7e87b273e..a0aac76b1e41 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -116,6 +116,13 @@ static DEFINE_MUTEX(psmouse_mutex);
static struct workqueue_struct *kpsmoused_wq;
+struct psmouse *psmouse_from_serio(struct serio *serio)
+{
+ struct ps2dev *ps2dev = serio_get_drvdata(serio);
+
+ return container_of(ps2dev, struct psmouse, ps2dev);
+}
+
void psmouse_report_standard_buttons(struct input_dev *dev, u8 buttons)
{
input_report_key(dev, BTN_LEFT, buttons & BIT(0));
@@ -329,17 +336,14 @@ static void psmouse_handle_oob_data(struct psmouse *psmouse, u8 data)
}
}
-/*
- * psmouse_interrupt() handles incoming characters, either passing them
- * for normal processing or gathering them as command response.
- */
-static irqreturn_t psmouse_interrupt(struct serio *serio,
- u8 data, unsigned int flags)
+static enum ps2_disposition psmouse_pre_receive_byte(struct ps2dev *ps2dev,
+ u8 data,
+ unsigned int flags)
{
- struct psmouse *psmouse = serio_get_drvdata(serio);
+ struct psmouse *psmouse = container_of(ps2dev, struct psmouse, ps2dev);
if (psmouse->state == PSMOUSE_IGNORE)
- goto out;
+ return PS2_IGNORE;
if (unlikely((flags & SERIO_TIMEOUT) ||
((flags & SERIO_PARITY) &&
@@ -350,27 +354,25 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
"bad data from KBC -%s%s\n",
flags & SERIO_TIMEOUT ? " timeout" : "",
flags & SERIO_PARITY ? " bad parity" : "");
- ps2_cmd_aborted(&psmouse->ps2dev);
- goto out;
+ return PS2_ERROR;
}
if (flags & SERIO_OOB_DATA) {
psmouse_handle_oob_data(psmouse, data);
- goto out;
+ return PS2_IGNORE;
}
- if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_ACK))
- if (ps2_handle_ack(&psmouse->ps2dev, data))
- goto out;
+ return PS2_PROCESS;
+}
- if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_CMD))
- if (ps2_handle_response(&psmouse->ps2dev, data))
- goto out;
+static void psmouse_receive_byte(struct ps2dev *ps2dev, u8 data)
+{
+ struct psmouse *psmouse = container_of(ps2dev, struct psmouse, ps2dev);
- pm_wakeup_event(&serio->dev, 0);
+ pm_wakeup_event(&ps2dev->serio->dev, 0);
if (psmouse->state <= PSMOUSE_RESYNCING)
- goto out;
+ return;
if (psmouse->state == PSMOUSE_ACTIVATED &&
psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
@@ -379,7 +381,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
psmouse->badbyte = psmouse->packet[0];
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
- goto out;
+ return;
}
psmouse->packet[psmouse->pktcnt++] = data;
@@ -388,21 +390,21 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) {
if (psmouse->pktcnt == 1) {
psmouse->last = jiffies;
- goto out;
+ return;
}
if (psmouse->packet[1] == PSMOUSE_RET_ID ||
(psmouse->protocol->type == PSMOUSE_HGPK &&
psmouse->packet[1] == PSMOUSE_RET_BAT)) {
__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
- serio_reconnect(serio);
- goto out;
+ serio_reconnect(ps2dev->serio);
+ return;
}
/* Not a new device, try processing first byte normally */
psmouse->pktcnt = 1;
if (psmouse_handle_byte(psmouse))
- goto out;
+ return;
psmouse->packet[psmouse->pktcnt++] = data;
}
@@ -417,14 +419,11 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
psmouse->badbyte = psmouse->packet[0];
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
- goto out;
+ return;
}
psmouse->last = jiffies;
psmouse_handle_byte(psmouse);
-
- out:
- return IRQ_HANDLED;
}
/*
@@ -1344,7 +1343,7 @@ static void psmouse_resync(struct work_struct *work)
goto out;
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
- parent = serio_get_drvdata(serio->parent);
+ parent = psmouse_from_serio(serio->parent);
psmouse_deactivate(parent);
}
@@ -1428,13 +1427,13 @@ static void psmouse_resync(struct work_struct *work)
*/
static void psmouse_cleanup(struct serio *serio)
{
- struct psmouse *psmouse = serio_get_drvdata(serio);
+ struct psmouse *psmouse = psmouse_from_serio(serio);
struct psmouse *parent = NULL;
mutex_lock(&psmouse_mutex);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
- parent = serio_get_drvdata(serio->parent);
+ parent = psmouse_from_serio(serio->parent);
psmouse_deactivate(parent);
}
@@ -1476,7 +1475,7 @@ static void psmouse_cleanup(struct serio *serio)
*/
static void psmouse_disconnect(struct serio *serio)
{
- struct psmouse *psmouse = serio_get_drvdata(serio);
+ struct psmouse *psmouse = psmouse_from_serio(serio);
struct psmouse *parent = NULL;
mutex_lock(&psmouse_mutex);
@@ -1489,7 +1488,7 @@ static void psmouse_disconnect(struct serio *serio)
mutex_lock(&psmouse_mutex);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
- parent = serio_get_drvdata(serio->parent);
+ parent = psmouse_from_serio(serio->parent);
psmouse_deactivate(parent);
}
@@ -1588,7 +1587,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
* connected to this port can be successfully identified
*/
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
- parent = serio_get_drvdata(serio->parent);
+ parent = psmouse_from_serio(serio->parent);
psmouse_deactivate(parent);
}
@@ -1597,15 +1596,14 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
if (!psmouse || !input_dev)
goto err_free;
- ps2_init(&psmouse->ps2dev, serio);
+ ps2_init(&psmouse->ps2dev, serio,
+ psmouse_pre_receive_byte, psmouse_receive_byte);
INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync);
psmouse->dev = input_dev;
snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys);
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
- serio_set_drvdata(serio, psmouse);
-
error = serio_open(serio, drv);
if (error)
goto err_clear_drvdata;
@@ -1676,7 +1674,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
static int __psmouse_reconnect(struct serio *serio, bool fast_reconnect)
{
- struct psmouse *psmouse = serio_get_drvdata(serio);
+ struct psmouse *psmouse = psmouse_from_serio(serio);
struct psmouse *parent = NULL;
int (*reconnect_handler)(struct psmouse *);
enum psmouse_type type;
@@ -1695,7 +1693,7 @@ static int __psmouse_reconnect(struct serio *serio, bool fast_reconnect)
}
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
- parent = serio_get_drvdata(serio->parent);
+ parent = psmouse_from_serio(serio->parent);
psmouse_deactivate(parent);
}
@@ -1781,7 +1779,7 @@ static struct serio_driver psmouse_drv = {
},
.description = DRIVER_DESC,
.id_table = psmouse_serio_ids,
- .interrupt = psmouse_interrupt,
+ .interrupt = ps2_interrupt,
.connect = psmouse_connect,
.reconnect = psmouse_reconnect,
.fast_reconnect = psmouse_fast_reconnect,
@@ -1794,7 +1792,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de
{
struct serio *serio = to_serio_port(dev);
struct psmouse_attribute *attr = to_psmouse_attr(devattr);
- struct psmouse *psmouse = serio_get_drvdata(serio);
+ struct psmouse *psmouse = psmouse_from_serio(serio);
if (psmouse->protocol->smbus_companion &&
devattr != &psmouse_attr_protocol.dattr)
@@ -1815,7 +1813,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
if (retval)
goto out;
- psmouse = serio_get_drvdata(serio);
+ psmouse = psmouse_from_serio(serio);
if (psmouse->protocol->smbus_companion &&
devattr != &psmouse_attr_protocol.dattr) {
@@ -1830,7 +1828,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
}
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
- parent = serio_get_drvdata(serio->parent);
+ parent = psmouse_from_serio(serio->parent);
psmouse_deactivate(parent);
}
@@ -1925,7 +1923,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
}
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
- parent = serio_get_drvdata(serio->parent);
+ parent = psmouse_from_serio(serio->parent);
if (parent->pt_deactivate)
parent->pt_deactivate(parent);
}
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 64c3a5d3fb3e..4d8acfe0d82a 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -130,6 +130,8 @@ struct psmouse {
void (*pt_deactivate)(struct psmouse *psmouse);
};
+struct psmouse *psmouse_from_serio(struct serio *serio);
+
void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
unsigned long delay);
int psmouse_reset(struct psmouse *psmouse);
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index fa021af8506e..ada299ec5bba 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -628,7 +628,7 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
****************************************************************************/
static int synaptics_pt_write(struct serio *serio, u8 c)
{
- struct psmouse *parent = serio_get_drvdata(serio->parent);
+ struct psmouse *parent = psmouse_from_serio(serio->parent);
u8 rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
int error;
@@ -645,7 +645,7 @@ static int synaptics_pt_write(struct serio *serio, u8 c)
static int synaptics_pt_start(struct serio *serio)
{
- struct psmouse *parent = serio_get_drvdata(serio->parent);
+ struct psmouse *parent = psmouse_from_serio(serio->parent);
struct synaptics_data *priv = parent->private;
serio_pause_rx(parent->ps2dev.serio);
@@ -657,7 +657,7 @@ static int synaptics_pt_start(struct serio *serio)
static void synaptics_pt_stop(struct serio *serio)
{
- struct psmouse *parent = serio_get_drvdata(serio->parent);
+ struct psmouse *parent = psmouse_from_serio(serio->parent);
struct synaptics_data *priv = parent->private;
serio_pause_rx(parent->ps2dev.serio);
@@ -672,7 +672,7 @@ static int synaptics_is_pt_packet(u8 *buf)
static void synaptics_pass_pt_packet(struct serio *ptport, u8 *packet)
{
- struct psmouse *child = serio_get_drvdata(ptport);
+ struct psmouse *child = psmouse_from_serio(ptport);
if (child && child->state == PSMOUSE_ACTIVATED) {
serio_interrupt(ptport, packet[1], 0);
@@ -688,7 +688,7 @@ static void synaptics_pass_pt_packet(struct serio *ptport, u8 *packet)
static void synaptics_pt_activate(struct psmouse *psmouse)
{
struct synaptics_data *priv = psmouse->private;
- struct psmouse *child = serio_get_drvdata(priv->pt_port);
+ struct psmouse *child = psmouse_from_serio(priv->pt_port);
/* adjust the touchpad to child's choice of protocol */
if (child) {
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index 068692a8aba5..af5cc64c622d 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -650,7 +650,7 @@ static struct i2c_driver synaptics_i2c_driver = {
.pm = pm_sleep_ptr(&synaptics_i2c_pm),
},
- .probe_new = synaptics_i2c_probe,
+ .probe = synaptics_i2c_probe,
.remove = synaptics_i2c_remove,
.id_table = synaptics_i2c_id_table,
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index 4a86b3e31d3b..5f6643b69a2c 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -216,7 +216,7 @@ static umode_t trackpoint_is_attr_visible(struct kobject *kobj,
{
struct device *dev = kobj_to_dev(kobj);
struct serio *serio = to_serio_port(dev);
- struct psmouse *psmouse = serio_get_drvdata(serio);
+ struct psmouse *psmouse = psmouse_from_serio(serio);
return trackpoint_is_attr_available(psmouse, attr) ? attr->mode : 0;
}
diff --git a/drivers/input/rmi4/rmi_i2c.c b/drivers/input/rmi4/rmi_i2c.c
index d69569ce8d8d..091d4e23b629 100644
--- a/drivers/input/rmi4/rmi_i2c.c
+++ b/drivers/input/rmi4/rmi_i2c.c
@@ -377,7 +377,7 @@ static struct i2c_driver rmi_i2c_driver = {
.of_match_table = of_match_ptr(rmi_i2c_of_match),
},
.id_table = rmi_id,
- .probe_new = rmi_i2c_probe,
+ .probe = rmi_i2c_probe,
};
module_i2c_driver(rmi_i2c_driver);
diff --git a/drivers/input/rmi4/rmi_smbus.c b/drivers/input/rmi4/rmi_smbus.c
index 4bf0e1df6a4a..7059a2762aeb 100644
--- a/drivers/input/rmi4/rmi_smbus.c
+++ b/drivers/input/rmi4/rmi_smbus.c
@@ -418,7 +418,7 @@ static struct i2c_driver rmi_smb_driver = {
.pm = pm_ptr(&rmi_smb_pm),
},
.id_table = rmi_id,
- .probe_new = rmi_smb_probe,
+ .probe = rmi_smb_probe,
.remove = rmi_smb_remove,
};
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index f39b7b3f7942..17edc1597446 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -148,6 +148,7 @@ config HIL_MLC
config SERIO_PCIPS2
tristate "PCI PS/2 keyboard and PS/2 mouse controller"
depends on PCI
+ depends on HAS_IOPORT
help
Say Y here if you have a Mobility Docking station with PS/2
keyboard and mice ports.
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 3e19344eda93..6d78a1fe00c1 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -19,9 +19,26 @@
#define DRIVER_DESC "PS/2 driver library"
-MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
-MODULE_DESCRIPTION("PS/2 driver library");
-MODULE_LICENSE("GPL");
+#define PS2_CMD_SETSCALE11 0x00e6
+#define PS2_CMD_SETRES 0x10e8
+#define PS2_CMD_EX_SETLEDS 0x20eb
+#define PS2_CMD_SETLEDS 0x10ed
+#define PS2_CMD_GETID 0x02f2
+#define PS2_CMD_SETREP 0x10f3 /* Set repeat rate/set report rate */
+#define PS2_CMD_RESET_BAT 0x02ff
+
+#define PS2_RET_BAT 0xaa
+#define PS2_RET_ID 0x00
+#define PS2_RET_ACK 0xfa
+#define PS2_RET_NAK 0xfe
+#define PS2_RET_ERR 0xfc
+
+#define PS2_FLAG_ACK BIT(0) /* Waiting for ACK/NAK */
+#define PS2_FLAG_CMD BIT(1) /* Waiting for a command to finish */
+#define PS2_FLAG_CMD1 BIT(2) /* Waiting for the first byte of command response */
+#define PS2_FLAG_WAITID BIT(3) /* Command executing is GET ID */
+#define PS2_FLAG_NAK BIT(4) /* Last transmission was NAKed */
+#define PS2_FLAG_PASS_NOACK BIT(5) /* Pass non-ACK byte to receive handler */
static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte,
unsigned int timeout, unsigned int max_attempts)
@@ -76,14 +93,17 @@ static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte,
return error;
}
-/*
- * ps2_sendbyte() sends a byte to the device and waits for acknowledge.
- * It doesn't handle retransmission, the caller is expected to handle
+/**
+ * ps2_sendbyte - sends a byte to the device and wait for acknowledgement
+ * @ps2dev: a PS/2 device to send the data to
+ * @byte: data to be sent to the device
+ * @timeout: timeout for sending the data and receiving an acknowledge
+ *
+ * The function doesn't handle retransmission, the caller is expected to handle
* it when needed.
*
* ps2_sendbyte() can only be called from a process context.
*/
-
int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
{
int retval;
@@ -99,6 +119,13 @@ int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
}
EXPORT_SYMBOL(ps2_sendbyte);
+/**
+ * ps2_begin_command - mark beginning of execution of a complex command
+ * @ps2dev: a PS/2 device executing the command
+ *
+ * Serializes a complex/compound command. Once command is finished
+ * ps2_end_command() should be called.
+ */
void ps2_begin_command(struct ps2dev *ps2dev)
{
struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
@@ -107,6 +134,10 @@ void ps2_begin_command(struct ps2dev *ps2dev)
}
EXPORT_SYMBOL(ps2_begin_command);
+/**
+ * ps2_end_command - mark end of execution of a complex command
+ * @ps2dev: a PS/2 device executing the command
+ */
void ps2_end_command(struct ps2dev *ps2dev)
{
struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
@@ -115,11 +146,13 @@ void ps2_end_command(struct ps2dev *ps2dev)
}
EXPORT_SYMBOL(ps2_end_command);
-/*
- * ps2_drain() waits for device to transmit requested number of bytes
- * and discards them.
+/**
+ * ps2_drain - waits for device to transmit requested number of bytes
+ * and discards them
+ * @ps2dev: the PS/2 device that should be drained
+ * @maxbytes: maximum number of bytes to be drained
+ * @timeout: time to drain the device
*/
-
void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout)
{
if (maxbytes > sizeof(ps2dev->cmdbuf)) {
@@ -142,11 +175,11 @@ void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout)
}
EXPORT_SYMBOL(ps2_drain);
-/*
- * ps2_is_keyboard_id() checks received ID byte against the list of
- * known keyboard IDs.
+/**
+ * ps2_is_keyboard_id - checks received ID byte against the list of
+ * known keyboard IDs
+ * @id_byte: data byte that should be checked
*/
-
bool ps2_is_keyboard_id(u8 id_byte)
{
static const u8 keyboard_ids[] = {
@@ -167,7 +200,6 @@ EXPORT_SYMBOL(ps2_is_keyboard_id);
* response and tries to reduce remaining timeout to speed up command
* completion.
*/
-
static int ps2_adjust_timeout(struct ps2dev *ps2dev,
unsigned int command, unsigned int timeout)
{
@@ -217,13 +249,19 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev,
return timeout;
}
-/*
- * ps2_command() sends a command and its parameters to the mouse,
- * then waits for the response and puts it in the param array.
+/**
+ * __ps2_command - send a command to PS/2 device
+ * @ps2dev: the PS/2 device that should execute the command
+ * @param: a buffer containing parameters to be sent along with the command,
+ * or place where the results of the command execution will be deposited,
+ * or both
+ * @command: command word that encodes the command itself, as well as number of
+ * additional parameter bytes that should be sent to the device and expected
+ * length of the command response
*
- * ps2_command() can only be called from a process context
+ * Not serialized. Callers should use ps2_begin_command() and ps2_end_command()
+ * to ensure proper serialization for complex commands.
*/
-
int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
{
unsigned int timeout;
@@ -247,17 +285,38 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
serio_pause_rx(ps2dev->serio);
- ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0;
ps2dev->cmdcnt = receive;
- if (receive && param)
- for (i = 0; i < receive; i++)
- ps2dev->cmdbuf[(receive - 1) - i] = param[i];
- /* Signal that we are sending the command byte */
- ps2dev->flags |= PS2_FLAG_ACK_CMD;
+ switch (command) {
+ case PS2_CMD_GETID:
+ /*
+ * Some mice do not ACK the "get ID" command, prepare to
+ * handle this.
+ */
+ ps2dev->flags = PS2_FLAG_WAITID;
+ break;
+
+ case PS2_CMD_SETLEDS:
+ case PS2_CMD_EX_SETLEDS:
+ case PS2_CMD_SETREP:
+ ps2dev->flags = PS2_FLAG_PASS_NOACK;
+ break;
+
+ default:
+ ps2dev->flags = 0;
+ break;
+ }
+
+ if (receive) {
+ /* Indicate that we expect response to the command. */
+ ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1;
+ if (param)
+ for (i = 0; i < receive; i++)
+ ps2dev->cmdbuf[(receive - 1) - i] = param[i];
+ }
/*
- * Some devices (Synaptics) peform the reset before
+ * Some devices (Synaptics) perform the reset before
* ACKing the reset command, and so it can take a long
* time before the ACK arrives.
*/
@@ -267,9 +326,7 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
if (rc)
goto out_reset_flags;
- /* Now we are sending command parameters, if any */
- ps2dev->flags &= ~PS2_FLAG_ACK_CMD;
-
+ /* Send command parameters, if any. */
for (i = 0; i < send; i++) {
rc = ps2_do_sendbyte(ps2dev, param[i], 200, 2);
if (rc)
@@ -327,6 +384,20 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
}
EXPORT_SYMBOL(__ps2_command);
+/**
+ * ps2_command - send a command to PS/2 device
+ * @ps2dev: the PS/2 device that should execute the command
+ * @param: a buffer containing parameters to be sent along with the command,
+ * or place where the results of the command execution will be deposited,
+ * or both
+ * @command: command word that encodes the command itself, as well as number of
+ * additional parameter bytes that should be sent to the device and expected
+ * length of the command response
+ *
+ * Note: ps2_command() serializes the command execution so that only one
+ * command can be executed at a time for either individual port or the entire
+ * 8042 controller.
+ */
int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
{
int rc;
@@ -339,14 +410,16 @@ int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
}
EXPORT_SYMBOL(ps2_command);
-/*
- * ps2_sliced_command() sends an extended PS/2 command to the mouse
- * using sliced syntax, understood by advanced devices, such as Logitech
- * or Synaptics touchpads. The command is encoded as:
+/**
+ * ps2_sliced_command - sends an extended PS/2 command to a mouse
+ * @ps2dev: the PS/2 device that should execute the command
+ * @command: command byte
+ *
+ * The command is sent using "sliced" syntax understood by advanced devices,
+ * such as Logitech or Synaptics touchpads. The command is encoded as:
* 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu
* is the command.
*/
-
int ps2_sliced_command(struct ps2dev *ps2dev, u8 command)
{
int i;
@@ -372,25 +445,60 @@ out:
}
EXPORT_SYMBOL(ps2_sliced_command);
-/*
- * ps2_init() initializes ps2dev structure
+/**
+ * ps2_init - initializes ps2dev structure
+ * @ps2dev: structure to be initialized
+ * @serio: serio port associated with the PS/2 device
+ * @pre_receive_handler: validation handler to check basic communication state
+ * @receive_handler: main protocol handler
+ *
+ * Prepares ps2dev structure for use in drivers for PS/2 devices.
*/
-
-void ps2_init(struct ps2dev *ps2dev, struct serio *serio)
+void ps2_init(struct ps2dev *ps2dev, struct serio *serio,
+ ps2_pre_receive_handler_t pre_receive_handler,
+ ps2_receive_handler_t receive_handler)
{
+ ps2dev->pre_receive_handler = pre_receive_handler;
+ ps2dev->receive_handler = receive_handler;
+
mutex_init(&ps2dev->cmd_mutex);
lockdep_set_subclass(&ps2dev->cmd_mutex, serio->depth);
init_waitqueue_head(&ps2dev->wait);
ps2dev->serio = serio;
+ serio_set_drvdata(serio, ps2dev);
}
EXPORT_SYMBOL(ps2_init);
/*
- * ps2_handle_ack() is supposed to be used in interrupt handler
- * to properly process ACK/NAK of a command from a PS/2 device.
+ * ps2_handle_response() stores device's response to a command and notifies
+ * the process waiting for completion of the command. Note that there is a
+ * distinction between waiting for the first byte of the response, and
+ * waiting for subsequent bytes. It is done so that callers could shorten
+ * timeouts once first byte of response is received.
*/
+static void ps2_handle_response(struct ps2dev *ps2dev, u8 data)
+{
+ if (ps2dev->cmdcnt)
+ ps2dev->cmdbuf[--ps2dev->cmdcnt] = data;
+
+ if (ps2dev->flags & PS2_FLAG_CMD1) {
+ ps2dev->flags &= ~PS2_FLAG_CMD1;
+ if (ps2dev->cmdcnt)
+ wake_up(&ps2dev->wait);
+ }
+
+ if (!ps2dev->cmdcnt) {
+ ps2dev->flags &= ~PS2_FLAG_CMD;
+ wake_up(&ps2dev->wait);
+ }
+}
-bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
+/*
+ * ps2_handle_ack() processes ACK/NAK of a command from a PS/2 device,
+ * possibly applying workarounds for mice not acknowledging the "get ID"
+ * command.
+ */
+static void ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
{
switch (data) {
case PS2_RET_ACK:
@@ -427,68 +535,89 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
* Do not signal errors if we get unexpected reply while
* waiting for an ACK to the initial (first) command byte:
* the device might not be quiesced yet and continue
- * delivering data.
+ * delivering data. For certain commands (such as set leds and
+ * set repeat rate) that can be used during normal device
+ * operation, we even pass this data byte to the normal receive
+ * handler.
* Note that we reset PS2_FLAG_WAITID flag, so the workaround
* for mice not acknowledging the Get ID command only triggers
* on the 1st byte; if device spews data we really want to see
* a real ACK from it.
*/
dev_dbg(&ps2dev->serio->dev, "unexpected %#02x\n", data);
- ps2dev->flags &= ~PS2_FLAG_WAITID;
- return ps2dev->flags & PS2_FLAG_ACK_CMD;
+ if (ps2dev->flags & PS2_FLAG_PASS_NOACK)
+ ps2dev->receive_handler(ps2dev, data);
+ ps2dev->flags &= ~(PS2_FLAG_WAITID | PS2_FLAG_PASS_NOACK);
+ return;
}
- if (!ps2dev->nak) {
+ if (!ps2dev->nak)
ps2dev->flags &= ~PS2_FLAG_NAK;
- if (ps2dev->cmdcnt)
- ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1;
- }
ps2dev->flags &= ~PS2_FLAG_ACK;
- wake_up(&ps2dev->wait);
- if (data != PS2_RET_ACK)
+ if (!ps2dev->nak && data != PS2_RET_ACK)
ps2_handle_response(ps2dev, data);
-
- return true;
+ else
+ wake_up(&ps2dev->wait);
}
-EXPORT_SYMBOL(ps2_handle_ack);
/*
- * ps2_handle_response() is supposed to be used in interrupt handler
- * to properly store device's response to a command and notify process
- * waiting for completion of the command.
+ * Clears state of PS/2 device after communication error by resetting majority
+ * of flags and waking up waiters, if any.
*/
-
-bool ps2_handle_response(struct ps2dev *ps2dev, u8 data)
+static void ps2_cleanup(struct ps2dev *ps2dev)
{
- if (ps2dev->cmdcnt)
- ps2dev->cmdbuf[--ps2dev->cmdcnt] = data;
+ unsigned long old_flags = ps2dev->flags;
- if (ps2dev->flags & PS2_FLAG_CMD1) {
- ps2dev->flags &= ~PS2_FLAG_CMD1;
- if (ps2dev->cmdcnt)
- wake_up(&ps2dev->wait);
- }
+ /* reset all flags except last nak */
+ ps2dev->flags &= PS2_FLAG_NAK;
- if (!ps2dev->cmdcnt) {
- ps2dev->flags &= ~PS2_FLAG_CMD;
- wake_up(&ps2dev->wait);
- }
+ if (old_flags & PS2_FLAG_ACK)
+ ps2dev->nak = 1;
- return true;
+ if (old_flags & (PS2_FLAG_ACK | PS2_FLAG_CMD))
+ wake_up(&ps2dev->wait);
}
-EXPORT_SYMBOL(ps2_handle_response);
-void ps2_cmd_aborted(struct ps2dev *ps2dev)
-{
- if (ps2dev->flags & PS2_FLAG_ACK)
- ps2dev->nak = 1;
+/**
+ * ps2_interrupt - common interrupt handler for PS/2 devices
+ * @serio: serio port for the device
+ * @data: a data byte received from the device
+ * @flags: flags such as %SERIO_PARITY or %SERIO_TIMEOUT indicating state of
+ * the data transfer
+ *
+ * ps2_interrupt() invokes pre-receive handler, optionally handles command
+ * acknowledgement and response from the device, and finally passes the data
+ * to the main protocol handler for future processing.
+ */
+irqreturn_t ps2_interrupt(struct serio *serio, u8 data, unsigned int flags) {
+ struct ps2dev *ps2dev = serio_get_drvdata(serio);
+ enum ps2_disposition rc;
+
+ rc = ps2dev->pre_receive_handler(ps2dev, data, flags);
+ switch (rc) {
+ case PS2_ERROR:
+ ps2_cleanup(ps2dev);
+ break;
- if (ps2dev->flags & (PS2_FLAG_ACK | PS2_FLAG_CMD))
- wake_up(&ps2dev->wait);
+ case PS2_IGNORE:
+ break;
- /* reset all flags except last nack */
- ps2dev->flags &= PS2_FLAG_NAK;
+ case PS2_PROCESS:
+ if (ps2dev->flags & PS2_FLAG_ACK)
+ ps2_handle_ack(ps2dev, data);
+ else if (ps2dev->flags & PS2_FLAG_CMD)
+ ps2_handle_response(ps2dev, data);
+ else
+ ps2dev->receive_handler(ps2dev, data);
+ break;
+ }
+
+ return IRQ_HANDLED;
}
-EXPORT_SYMBOL(ps2_cmd_aborted);
+EXPORT_SYMBOL(ps2_interrupt);
+
+MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
+MODULE_DESCRIPTION("PS/2 driver library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/tests/input_test.c b/drivers/input/tests/input_test.c
index e5a6c1ad2167..2fa5b725ae0a 100644
--- a/drivers/input/tests/input_test.c
+++ b/drivers/input/tests/input_test.c
@@ -43,8 +43,8 @@ static void input_test_exit(struct kunit *test)
{
struct input_dev *input_dev = test->priv;
- input_unregister_device(input_dev);
- input_free_device(input_dev);
+ if (input_dev)
+ input_unregister_device(input_dev);
}
static void input_test_poll(struct input_dev *input) { }
@@ -87,7 +87,7 @@ static void input_test_timestamp(struct kunit *test)
static void input_test_match_device_id(struct kunit *test)
{
struct input_dev *input_dev = test->priv;
- struct input_device_id id;
+ struct input_device_id id = { 0 };
/*
* Must match when the input device bus, vendor, product, version
@@ -130,10 +130,42 @@ static void input_test_match_device_id(struct kunit *test)
KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id));
}
+static void input_test_grab(struct kunit *test)
+{
+ struct input_dev *input_dev = test->priv;
+ struct input_handle test_handle;
+ struct input_handler handler;
+ struct input_handle handle;
+ struct input_device_id id;
+ int res;
+
+ handler.name = "handler";
+ handler.id_table = &id;
+
+ handle.dev = input_get_device(input_dev);
+ handle.name = dev_name(&input_dev->dev);
+ handle.handler = &handler;
+ res = input_grab_device(&handle);
+ KUNIT_ASSERT_TRUE(test, res == 0);
+
+ test_handle.dev = input_get_device(input_dev);
+ test_handle.name = dev_name(&input_dev->dev);
+ test_handle.handler = &handler;
+ res = input_grab_device(&test_handle);
+ KUNIT_ASSERT_EQ(test, res, -EBUSY);
+
+ input_release_device(&handle);
+ input_put_device(input_dev);
+ res = input_grab_device(&test_handle);
+ KUNIT_ASSERT_TRUE(test, res == 0);
+ input_put_device(input_dev);
+}
+
static struct kunit_case input_tests[] = {
KUNIT_CASE(input_test_polling),
KUNIT_CASE(input_test_timestamp),
KUNIT_CASE(input_test_match_device_id),
+ KUNIT_CASE(input_test_grab),
{ /* sentinel */ }
};
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 143ff43c67ae..c2cbd332af1d 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -700,6 +700,7 @@ config TOUCHSCREEN_INEXIO
config TOUCHSCREEN_MK712
tristate "ICS MicroClock MK712 touchscreen"
+ depends on ISA
help
Say Y here if you have the ICS MicroClock MK712 touchscreen
controller chip in your system.
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c
index dd8f31737bb8..feaa6f8b01ed 100644
--- a/drivers/input/touchscreen/ad7879-i2c.c
+++ b/drivers/input/touchscreen/ad7879-i2c.c
@@ -62,7 +62,7 @@ static struct i2c_driver ad7879_i2c_driver = {
.pm = &ad7879_pm_ops,
.of_match_table = of_match_ptr(ad7879_i2c_dt_ids),
},
- .probe_new = ad7879_i2c_probe,
+ .probe = ad7879_i2c_probe,
.id_table = ad7879_id,
};
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index bb1058b1e7fd..faea40dd66d0 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -24,11 +24,8 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/pm.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/of_device.h>
+#include <linux/property.h>
#include <linux/gpio/consumer.h>
-#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <linux/regulator/consumer.h>
@@ -140,7 +137,7 @@ struct ads7846 {
int (*filter)(void *data, int data_idx, int *val);
void *filter_data;
int (*get_pendown_state)(void);
- int gpio_pendown;
+ struct gpio_desc *gpio_pendown;
void (*wait_for_sync)(void);
};
@@ -223,7 +220,7 @@ static int get_pendown_state(struct ads7846 *ts)
if (ts->get_pendown_state)
return ts->get_pendown_state();
- return !gpio_get_value(ts->gpio_pendown);
+ return gpiod_get_value(ts->gpio_pendown);
}
static void ads7846_report_pen_up(struct ads7846 *ts)
@@ -989,8 +986,6 @@ static int ads7846_setup_pendown(struct spi_device *spi,
struct ads7846 *ts,
const struct ads7846_platform_data *pdata)
{
- int err;
-
/*
* REVISIT when the irq can be triggered active-low, or if for some
* reason the touchscreen isn't hooked up, we don't need to access
@@ -999,25 +994,15 @@ static int ads7846_setup_pendown(struct spi_device *spi,
if (pdata->get_pendown_state) {
ts->get_pendown_state = pdata->get_pendown_state;
- } else if (gpio_is_valid(pdata->gpio_pendown)) {
-
- err = devm_gpio_request_one(&spi->dev, pdata->gpio_pendown,
- GPIOF_IN, "ads7846_pendown");
- if (err) {
- dev_err(&spi->dev,
- "failed to request/setup pendown GPIO%d: %d\n",
- pdata->gpio_pendown, err);
- return err;
+ } else {
+ ts->gpio_pendown = gpiod_get(&spi->dev, "pendown", GPIOD_IN);
+ if (IS_ERR(ts->gpio_pendown)) {
+ dev_err(&spi->dev, "failed to request pendown GPIO\n");
+ return PTR_ERR(ts->gpio_pendown);
}
-
- ts->gpio_pendown = pdata->gpio_pendown;
-
if (pdata->gpio_pendown_debounce)
- gpiod_set_debounce(gpio_to_desc(ts->gpio_pendown),
+ gpiod_set_debounce(ts->gpio_pendown,
pdata->gpio_pendown_debounce);
- } else {
- dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
- return -EINVAL;
}
return 0;
@@ -1119,7 +1104,6 @@ static int ads7846_setup_spi_msg(struct ads7846 *ts,
return 0;
}
-#ifdef CONFIG_OF
static const struct of_device_id ads7846_dt_ids[] = {
{ .compatible = "ti,tsc2046", .data = (void *) 7846 },
{ .compatible = "ti,ads7843", .data = (void *) 7843 },
@@ -1130,82 +1114,60 @@ static const struct of_device_id ads7846_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, ads7846_dt_ids);
-static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
+static const struct ads7846_platform_data *ads7846_get_props(struct device *dev)
{
struct ads7846_platform_data *pdata;
- struct device_node *node = dev->of_node;
- const struct of_device_id *match;
u32 value;
- if (!node) {
- dev_err(dev, "Device does not have associated DT data\n");
- return ERR_PTR(-EINVAL);
- }
-
- match = of_match_device(ads7846_dt_ids, dev);
- if (!match) {
- dev_err(dev, "Unknown device model\n");
- return ERR_PTR(-EINVAL);
- }
-
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
- pdata->model = (unsigned long)match->data;
+ pdata->model = (uintptr_t)device_get_match_data(dev);
- of_property_read_u16(node, "ti,vref-delay-usecs",
- &pdata->vref_delay_usecs);
- of_property_read_u16(node, "ti,vref-mv", &pdata->vref_mv);
- pdata->keep_vref_on = of_property_read_bool(node, "ti,keep-vref-on");
+ device_property_read_u16(dev, "ti,vref-delay-usecs",
+ &pdata->vref_delay_usecs);
+ device_property_read_u16(dev, "ti,vref-mv", &pdata->vref_mv);
+ pdata->keep_vref_on = device_property_read_bool(dev, "ti,keep-vref-on");
- pdata->swap_xy = of_property_read_bool(node, "ti,swap-xy");
+ pdata->swap_xy = device_property_read_bool(dev, "ti,swap-xy");
- of_property_read_u16(node, "ti,settle-delay-usec",
- &pdata->settle_delay_usecs);
- of_property_read_u16(node, "ti,penirq-recheck-delay-usecs",
- &pdata->penirq_recheck_delay_usecs);
+ device_property_read_u16(dev, "ti,settle-delay-usec",
+ &pdata->settle_delay_usecs);
+ device_property_read_u16(dev, "ti,penirq-recheck-delay-usecs",
+ &pdata->penirq_recheck_delay_usecs);
- of_property_read_u16(node, "ti,x-plate-ohms", &pdata->x_plate_ohms);
- of_property_read_u16(node, "ti,y-plate-ohms", &pdata->y_plate_ohms);
+ device_property_read_u16(dev, "ti,x-plate-ohms", &pdata->x_plate_ohms);
+ device_property_read_u16(dev, "ti,y-plate-ohms", &pdata->y_plate_ohms);
- of_property_read_u16(node, "ti,x-min", &pdata->x_min);
- of_property_read_u16(node, "ti,y-min", &pdata->y_min);
- of_property_read_u16(node, "ti,x-max", &pdata->x_max);
- of_property_read_u16(node, "ti,y-max", &pdata->y_max);
+ device_property_read_u16(dev, "ti,x-min", &pdata->x_min);
+ device_property_read_u16(dev, "ti,y-min", &pdata->y_min);
+ device_property_read_u16(dev, "ti,x-max", &pdata->x_max);
+ device_property_read_u16(dev, "ti,y-max", &pdata->y_max);
/*
* touchscreen-max-pressure gets parsed during
* touchscreen_parse_properties()
*/
- of_property_read_u16(node, "ti,pressure-min", &pdata->pressure_min);
- if (!of_property_read_u32(node, "touchscreen-min-pressure", &value))
+ device_property_read_u16(dev, "ti,pressure-min", &pdata->pressure_min);
+ if (!device_property_read_u32(dev, "touchscreen-min-pressure", &value))
pdata->pressure_min = (u16) value;
- of_property_read_u16(node, "ti,pressure-max", &pdata->pressure_max);
+ device_property_read_u16(dev, "ti,pressure-max", &pdata->pressure_max);
- of_property_read_u16(node, "ti,debounce-max", &pdata->debounce_max);
- if (!of_property_read_u32(node, "touchscreen-average-samples", &value))
+ device_property_read_u16(dev, "ti,debounce-max", &pdata->debounce_max);
+ if (!device_property_read_u32(dev, "touchscreen-average-samples", &value))
pdata->debounce_max = (u16) value;
- of_property_read_u16(node, "ti,debounce-tol", &pdata->debounce_tol);
- of_property_read_u16(node, "ti,debounce-rep", &pdata->debounce_rep);
+ device_property_read_u16(dev, "ti,debounce-tol", &pdata->debounce_tol);
+ device_property_read_u16(dev, "ti,debounce-rep", &pdata->debounce_rep);
- of_property_read_u32(node, "ti,pendown-gpio-debounce",
+ device_property_read_u32(dev, "ti,pendown-gpio-debounce",
&pdata->gpio_pendown_debounce);
- pdata->wakeup = of_property_read_bool(node, "wakeup-source") ||
- of_property_read_bool(node, "linux,wakeup");
-
- pdata->gpio_pendown = of_get_named_gpio(dev->of_node, "pendown-gpio", 0);
+ pdata->wakeup = device_property_read_bool(dev, "wakeup-source") ||
+ device_property_read_bool(dev, "linux,wakeup");
return pdata;
}
-#else
-static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
-{
- dev_err(dev, "no platform data defined\n");
- return ERR_PTR(-EINVAL);
-}
-#endif
static void ads7846_regulator_disable(void *regulator)
{
@@ -1269,7 +1231,7 @@ static int ads7846_probe(struct spi_device *spi)
pdata = dev_get_platdata(dev);
if (!pdata) {
- pdata = ads7846_probe_dt(dev);
+ pdata = ads7846_get_props(dev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
}
@@ -1426,7 +1388,7 @@ static struct spi_driver ads7846_driver = {
.driver = {
.name = "ads7846",
.pm = pm_sleep_ptr(&ads7846_pm),
- .of_match_table = of_match_ptr(ads7846_dt_ids),
+ .of_match_table = ads7846_dt_ids,
},
.probe = ads7846_probe,
.remove = ads7846_remove,
diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c
index 3a5b65cae360..64dfb749386f 100644
--- a/drivers/input/touchscreen/ar1021_i2c.c
+++ b/drivers/input/touchscreen/ar1021_i2c.c
@@ -182,7 +182,7 @@ static struct i2c_driver ar1021_i2c_driver = {
.of_match_table = ar1021_i2c_of_match,
},
- .probe_new = ar1021_i2c_probe,
+ .probe = ar1021_i2c_probe,
.id_table = ar1021_i2c_id,
};
module_i2c_driver(ar1021_i2c_driver);
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 996bf434e1cb..20094b9899f0 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -55,6 +55,7 @@
#define MXT_TOUCH_KEYARRAY_T15 15
#define MXT_TOUCH_PROXIMITY_T23 23
#define MXT_TOUCH_PROXKEY_T52 52
+#define MXT_TOUCH_PTC_KEYS_T97 97
#define MXT_PROCI_GRIPFACE_T20 20
#define MXT_PROCG_NOISE_T22 22
#define MXT_PROCI_ONETOUCH_T24 24
@@ -326,9 +327,13 @@ struct mxt_data {
u16 T71_address;
u8 T9_reportid_min;
u8 T9_reportid_max;
+ u8 T15_reportid_min;
+ u8 T15_reportid_max;
u16 T18_address;
u8 T19_reportid;
u16 T44_address;
+ u8 T97_reportid_min;
+ u8 T97_reportid_max;
u8 T100_reportid_min;
u8 T100_reportid_max;
@@ -344,6 +349,9 @@ struct mxt_data {
u32 *t19_keymap;
unsigned int t19_num_keys;
+ u32 *t15_keymap;
+ unsigned int t15_num_keys;
+
enum mxt_suspend_mode suspend_mode;
u32 wakeup_method;
@@ -375,6 +383,7 @@ static bool mxt_object_readable(unsigned int type)
case MXT_TOUCH_KEYARRAY_T15:
case MXT_TOUCH_PROXIMITY_T23:
case MXT_TOUCH_PROXKEY_T52:
+ case MXT_TOUCH_PTC_KEYS_T97:
case MXT_TOUCH_MULTITOUCHSCREEN_T100:
case MXT_PROCI_GRIPFACE_T20:
case MXT_PROCG_NOISE_T22:
@@ -891,6 +900,24 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message)
data->update_input = true;
}
+static void mxt_proc_t15_messages(struct mxt_data *data, u8 *message)
+{
+ struct input_dev *input_dev = data->input_dev;
+ unsigned long keystates = get_unaligned_le32(&message[2]);
+ int key;
+
+ for (key = 0; key < data->t15_num_keys; key++)
+ input_report_key(input_dev, data->t15_keymap[key],
+ keystates & BIT(key));
+
+ data->update_input = true;
+}
+
+static void mxt_proc_t97_messages(struct mxt_data *data, u8 *message)
+{
+ mxt_proc_t15_messages(data, message);
+}
+
static void mxt_proc_t100_message(struct mxt_data *data, u8 *message)
{
struct device *dev = &data->client->dev;
@@ -1017,6 +1044,12 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message)
} else if (report_id >= data->T9_reportid_min &&
report_id <= data->T9_reportid_max) {
mxt_proc_t9_message(data, message);
+ } else if (report_id >= data->T15_reportid_min &&
+ report_id <= data->T15_reportid_max) {
+ mxt_proc_t15_messages(data, message);
+ } else if (report_id >= data->T97_reportid_min &&
+ report_id <= data->T97_reportid_max) {
+ mxt_proc_t97_messages(data, message);
} else if (report_id >= data->T100_reportid_min &&
report_id <= data->T100_reportid_max) {
mxt_proc_t100_message(data, message);
@@ -1689,9 +1722,13 @@ static void mxt_free_object_table(struct mxt_data *data)
data->T71_address = 0;
data->T9_reportid_min = 0;
data->T9_reportid_max = 0;
+ data->T15_reportid_min = 0;
+ data->T15_reportid_max = 0;
data->T18_address = 0;
data->T19_reportid = 0;
data->T44_address = 0;
+ data->T97_reportid_min = 0;
+ data->T97_reportid_max = 0;
data->T100_reportid_min = 0;
data->T100_reportid_max = 0;
data->max_reportid = 0;
@@ -1764,6 +1801,10 @@ static int mxt_parse_object_table(struct mxt_data *data,
object->num_report_ids - 1;
data->num_touchids = object->num_report_ids;
break;
+ case MXT_TOUCH_KEYARRAY_T15:
+ data->T15_reportid_min = min_id;
+ data->T15_reportid_max = max_id;
+ break;
case MXT_SPT_COMMSCONFIG_T18:
data->T18_address = object->start_address;
break;
@@ -1773,6 +1814,10 @@ static int mxt_parse_object_table(struct mxt_data *data,
case MXT_SPT_GPIOPWM_T19:
data->T19_reportid = min_id;
break;
+ case MXT_TOUCH_PTC_KEYS_T97:
+ data->T97_reportid_min = min_id;
+ data->T97_reportid_max = max_id;
+ break;
case MXT_TOUCH_MULTITOUCHSCREEN_T100:
data->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100;
data->T100_reportid_min = min_id;
@@ -2050,6 +2095,7 @@ static int mxt_initialize_input_device(struct mxt_data *data)
int error;
unsigned int num_mt_slots;
unsigned int mt_flags = 0;
+ int i;
switch (data->multitouch) {
case MXT_TOUCH_MULTI_T9:
@@ -2095,6 +2141,10 @@ static int mxt_initialize_input_device(struct mxt_data *data)
input_dev->open = mxt_input_open;
input_dev->close = mxt_input_close;
+ input_dev->keycode = data->t15_keymap;
+ input_dev->keycodemax = data->t15_num_keys;
+ input_dev->keycodesize = sizeof(data->t15_keymap[0]);
+
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
/* For single touch */
@@ -2162,6 +2212,13 @@ static int mxt_initialize_input_device(struct mxt_data *data)
0, 255, 0, 0);
}
+ /* For T15 and T97 Key Array */
+ if (data->T15_reportid_min || data->T97_reportid_min) {
+ for (i = 0; i < data->t15_num_keys; i++)
+ input_set_capability(input_dev,
+ EV_KEY, data->t15_keymap[i]);
+ }
+
input_set_drvdata(input_dev, data);
error = input_register_device(input_dev);
@@ -3080,8 +3137,10 @@ static void mxt_input_close(struct input_dev *dev)
static int mxt_parse_device_properties(struct mxt_data *data)
{
static const char keymap_property[] = "linux,gpio-keymap";
+ static const char buttons_property[] = "linux,keycodes";
struct device *dev = &data->client->dev;
u32 *keymap;
+ u32 *buttonmap;
int n_keys;
int error;
@@ -3111,6 +3170,32 @@ static int mxt_parse_device_properties(struct mxt_data *data)
data->t19_num_keys = n_keys;
}
+ if (device_property_present(dev, buttons_property)) {
+ n_keys = device_property_count_u32(dev, buttons_property);
+ if (n_keys <= 0) {
+ error = n_keys < 0 ? n_keys : -EINVAL;
+ dev_err(dev, "invalid/malformed '%s' property: %d\n",
+ buttons_property, error);
+ return error;
+ }
+
+ buttonmap = devm_kmalloc_array(dev, n_keys, sizeof(*buttonmap),
+ GFP_KERNEL);
+ if (!buttonmap)
+ return -ENOMEM;
+
+ error = device_property_read_u32_array(dev, buttons_property,
+ buttonmap, n_keys);
+ if (error) {
+ dev_err(dev, "failed to parse '%s' property: %d\n",
+ buttons_property, error);
+ return error;
+ }
+
+ data->t15_keymap = buttonmap;
+ data->t15_num_keys = n_keys;
+ }
+
return 0;
}
@@ -3377,7 +3462,7 @@ static struct i2c_driver mxt_driver = {
.acpi_match_table = ACPI_PTR(mxt_acpi_id),
.pm = pm_sleep_ptr(&mxt_pm_ops),
},
- .probe_new = mxt_probe,
+ .probe = mxt_probe,
.remove = mxt_remove,
.id_table = mxt_id,
};
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index 5359efc80b2b..90c682e7407f 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -636,7 +636,7 @@ static struct i2c_driver auo_pixcir_driver = {
.pm = pm_sleep_ptr(&auo_pixcir_pm_ops),
.of_match_table = of_match_ptr(auo_pixcir_ts_dt_idtable),
},
- .probe_new = auo_pixcir_probe,
+ .probe = auo_pixcir_probe,
.id_table = auo_pixcir_idtable,
};
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
index c994ab6f4e58..85332cfaa29d 100644
--- a/drivers/input/touchscreen/bu21013_ts.c
+++ b/drivers/input/touchscreen/bu21013_ts.c
@@ -617,7 +617,7 @@ static struct i2c_driver bu21013_driver = {
.name = DRIVER_TP,
.pm = pm_sleep_ptr(&bu21013_dev_pm_ops),
},
- .probe_new = bu21013_probe,
+ .probe = bu21013_probe,
.remove = bu21013_remove,
.id_table = bu21013_id,
};
diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c
index 8f1442894ff9..c8126d2efe95 100644
--- a/drivers/input/touchscreen/bu21029_ts.c
+++ b/drivers/input/touchscreen/bu21029_ts.c
@@ -474,7 +474,7 @@ static struct i2c_driver bu21029_driver = {
.pm = pm_sleep_ptr(&bu21029_pm_ops),
},
.id_table = bu21029_ids,
- .probe_new = bu21029_probe,
+ .probe = bu21029_probe,
};
module_i2c_driver(bu21029_driver);
diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c
index 32b714a6ed2d..9fbeaf17f00b 100644
--- a/drivers/input/touchscreen/chipone_icn8318.c
+++ b/drivers/input/touchscreen/chipone_icn8318.c
@@ -264,7 +264,7 @@ static struct i2c_driver icn8318_driver = {
.pm = pm_sleep_ptr(&icn8318_pm_ops),
.of_match_table = icn8318_of_match,
},
- .probe_new = icn8318_probe,
+ .probe = icn8318_probe,
.id_table = icn8318_i2c_id,
};
diff --git a/drivers/input/touchscreen/chipone_icn8505.c b/drivers/input/touchscreen/chipone_icn8505.c
index 246bee0bee53..b56954830b33 100644
--- a/drivers/input/touchscreen/chipone_icn8505.c
+++ b/drivers/input/touchscreen/chipone_icn8505.c
@@ -498,7 +498,7 @@ static struct i2c_driver icn8505_driver = {
.pm = pm_sleep_ptr(&icn8505_pm_ops),
.acpi_match_table = icn8505_acpi_match,
},
- .probe_new = icn8505_probe,
+ .probe = icn8505_probe,
};
module_i2c_driver(icn8505_driver);
diff --git a/drivers/input/touchscreen/cy8ctma140.c b/drivers/input/touchscreen/cy8ctma140.c
index cd86477d971a..967ecde23e83 100644
--- a/drivers/input/touchscreen/cy8ctma140.c
+++ b/drivers/input/touchscreen/cy8ctma140.c
@@ -344,7 +344,7 @@ static struct i2c_driver cy8ctma140_driver = {
.of_match_table = cy8ctma140_of_match,
},
.id_table = cy8ctma140_idtable,
- .probe_new = cy8ctma140_probe,
+ .probe = cy8ctma140_probe,
};
module_i2c_driver(cy8ctma140_driver);
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c
index dcf50fbf6dc7..54d6c4869eb0 100644
--- a/drivers/input/touchscreen/cy8ctmg110_ts.c
+++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
@@ -279,7 +279,7 @@ static struct i2c_driver cy8ctmg110_driver = {
.pm = pm_sleep_ptr(&cy8ctmg110_pm),
},
.id_table = cy8ctmg110_idtable,
- .probe_new = cy8ctmg110_probe,
+ .probe = cy8ctmg110_probe,
};
module_i2c_driver(cy8ctmg110_driver);
diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c
index 0cd6f626adec..7cb26929dc73 100644
--- a/drivers/input/touchscreen/cyttsp4_core.c
+++ b/drivers/input/touchscreen/cyttsp4_core.c
@@ -1263,9 +1263,8 @@ static void cyttsp4_stop_wd_timer(struct cyttsp4 *cd)
* Ensure we wait until the watchdog timer
* running on a different CPU finishes
*/
- del_timer_sync(&cd->watchdog_timer);
+ timer_shutdown_sync(&cd->watchdog_timer);
cancel_work_sync(&cd->watchdog_work);
- del_timer_sync(&cd->watchdog_timer);
}
static void cyttsp4_watchdog_timer(struct timer_list *t)
diff --git a/drivers/input/touchscreen/cyttsp4_i2c.c b/drivers/input/touchscreen/cyttsp4_i2c.c
index ec7a4779f3fb..80a6890cd45a 100644
--- a/drivers/input/touchscreen/cyttsp4_i2c.c
+++ b/drivers/input/touchscreen/cyttsp4_i2c.c
@@ -60,7 +60,7 @@ static struct i2c_driver cyttsp4_i2c_driver = {
.name = CYTTSP4_I2C_NAME,
.pm = pm_ptr(&cyttsp4_pm_ops),
},
- .probe_new = cyttsp4_i2c_probe,
+ .probe = cyttsp4_i2c_probe,
.remove = cyttsp4_i2c_remove,
.id_table = cyttsp4_i2c_id,
};
diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c
index 3c9d07218f48..b461ded946fc 100644
--- a/drivers/input/touchscreen/cyttsp5.c
+++ b/drivers/input/touchscreen/cyttsp5.c
@@ -43,6 +43,7 @@
#define HID_DESC_REG 0x1
#define HID_INPUT_REG 0x3
#define HID_OUTPUT_REG 0x4
+#define HID_COMMAND_REG 0x5
#define REPORT_ID_TOUCH 0x1
#define REPORT_ID_BTN 0x3
@@ -68,6 +69,7 @@
#define HID_APP_OUTPUT_REPORT_ID 0x2F
#define HID_BL_RESPONSE_REPORT_ID 0x30
#define HID_BL_OUTPUT_REPORT_ID 0x40
+#define HID_RESPONSE_REPORT_ID 0xF0
#define HID_OUTPUT_RESPONSE_REPORT_OFFSET 2
#define HID_OUTPUT_RESPONSE_CMD_OFFSET 4
@@ -78,9 +80,15 @@
#define HID_SYSINFO_BTN_MASK GENMASK(7, 0)
#define HID_SYSINFO_MAX_BTN 8
+#define HID_CMD_SET_POWER 0x8
+
+#define HID_POWER_ON 0x0
+#define HID_POWER_SLEEP 0x1
+
#define CY_HID_OUTPUT_TIMEOUT_MS 200
#define CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT_MS 3000
#define CY_HID_GET_HID_DESCRIPTOR_TIMEOUT_MS 4000
+#define CY_HID_SET_POWER_TIMEOUT 500
/* maximum number of concurrent tracks */
#define TOUCH_REPORT_SIZE 10
@@ -100,6 +108,14 @@
#define TOUCH_REPORT_USAGE_PG_MIN 0xFF010063
#define TOUCH_COL_USAGE_PG 0x000D0022
+#define SET_CMD_LOW(byte, bits) \
+ ((byte) = (((byte) & 0xF0) | ((bits) & 0x0F)))
+#define SET_CMD_HIGH(byte, bits)\
+ ((byte) = (((byte) & 0x0F) | ((bits) & 0xF0)))
+#define SET_CMD_OPCODE(byte, opcode) SET_CMD_LOW(byte, opcode)
+#define SET_CMD_REPORT_TYPE(byte, type) SET_CMD_HIGH(byte, ((type) << 4))
+#define SET_CMD_REPORT_ID(byte, id) SET_CMD_LOW(byte, id)
+
/* System Information interface definitions */
struct cyttsp5_sensing_conf_data_dev {
u8 electrodes_x;
@@ -557,6 +573,40 @@ static int cyttsp5_hid_output_get_sysinfo(struct cyttsp5 *ts)
return cyttsp5_get_sysinfo_regs(ts);
}
+static int cyttsp5_power_control(struct cyttsp5 *ts, bool on)
+{
+ u8 state = on ? HID_POWER_ON : HID_POWER_SLEEP;
+ u8 cmd[2] = { 0 };
+ int rc;
+
+ SET_CMD_REPORT_TYPE(cmd[0], 0);
+ SET_CMD_REPORT_ID(cmd[0], HID_POWER_SLEEP);
+ SET_CMD_OPCODE(cmd[1], HID_CMD_SET_POWER);
+
+ rc = cyttsp5_write(ts, HID_COMMAND_REG, cmd, sizeof(cmd));
+ if (rc) {
+ dev_err(ts->dev, "Failed to write power command %d", rc);
+ return rc;
+ }
+
+ rc = wait_for_completion_interruptible_timeout(&ts->cmd_done,
+ msecs_to_jiffies(CY_HID_SET_POWER_TIMEOUT));
+ if (rc <= 0) {
+ dev_err(ts->dev, "HID power cmd execution timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ if (ts->response_buf[2] != HID_RESPONSE_REPORT_ID ||
+ (ts->response_buf[3] & 0x03) != state ||
+ (ts->response_buf[4] & 0x0f) != HID_CMD_SET_POWER) {
+ dev_err(ts->dev, "Validation of the %s response failed\n",
+ on ? "wakeup" : "sleep");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int cyttsp5_hid_output_bl_launch_app(struct cyttsp5 *ts)
{
int rc;
@@ -601,12 +651,7 @@ static int cyttsp5_get_hid_descriptor(struct cyttsp5 *ts,
struct cyttsp5_hid_desc *desc)
{
struct device *dev = ts->dev;
- __le16 hid_desc_register = cpu_to_le16(HID_DESC_REG);
int rc;
- u8 cmd[2];
-
- /* Set HID descriptor register */
- memcpy(cmd, &hid_desc_register, sizeof(hid_desc_register));
rc = cyttsp5_write(ts, HID_DESC_REG, NULL, 0);
if (rc) {
@@ -675,6 +720,10 @@ static irqreturn_t cyttsp5_handle_irq(int irq, void *handle)
case HID_BTN_REPORT_ID:
cyttsp5_btn_attention(ts->dev);
break;
+ case HID_RESPONSE_REPORT_ID:
+ memcpy(ts->response_buf, ts->input_buf, size);
+ complete(&ts->cmd_done);
+ break;
default:
/* It is not an input but a command response */
memcpy(ts->response_buf, ts->input_buf, size);
@@ -886,12 +935,35 @@ static const struct i2c_device_id cyttsp5_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id);
+static int __maybe_unused cyttsp5_suspend(struct device *dev)
+{
+ struct cyttsp5 *ts = dev_get_drvdata(dev);
+
+ if (!device_may_wakeup(dev))
+ cyttsp5_power_control(ts, false);
+
+ return 0;
+}
+
+static int __maybe_unused cyttsp5_resume(struct device *dev)
+{
+ struct cyttsp5 *ts = dev_get_drvdata(dev);
+
+ if (!device_may_wakeup(dev))
+ cyttsp5_power_control(ts, true);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(cyttsp5_pm, cyttsp5_suspend, cyttsp5_resume);
+
static struct i2c_driver cyttsp5_i2c_driver = {
.driver = {
.name = CYTTSP5_NAME,
.of_match_table = cyttsp5_of_match,
+ .pm = &cyttsp5_pm,
},
- .probe_new = cyttsp5_i2c_probe,
+ .probe = cyttsp5_i2c_probe,
.id_table = cyttsp5_i2c_id,
};
module_i2c_driver(cyttsp5_i2c_driver);
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
index 3f91cb43ec82..127a8fda1da4 100644
--- a/drivers/input/touchscreen/cyttsp_i2c.c
+++ b/drivers/input/touchscreen/cyttsp_i2c.c
@@ -66,7 +66,7 @@ static struct i2c_driver cyttsp_i2c_driver = {
.pm = pm_sleep_ptr(&cyttsp_pm_ops),
.of_match_table = cyttsp_of_i2c_match,
},
- .probe_new = cyttsp_i2c_probe,
+ .probe = cyttsp_i2c_probe,
.id_table = cyttsp_i2c_id,
};
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 24ab9e9f5b21..795c7dad22bf 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -1241,6 +1241,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
if (tsdata->wake_gpio) {
usleep_range(5000, 6000);
gpiod_set_value_cansleep(tsdata->wake_gpio, 1);
+ usleep_range(5000, 6000);
}
if (tsdata->reset_gpio) {
@@ -1510,7 +1511,7 @@ static struct i2c_driver edt_ft5x06_ts_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.id_table = edt_ft5x06_ts_id,
- .probe_new = edt_ft5x06_ts_probe,
+ .probe = edt_ft5x06_ts_probe,
.remove = edt_ft5x06_ts_remove,
};
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 56fa21688bdb..5e4167f6c63e 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -291,7 +291,7 @@ static struct i2c_driver eeti_ts_driver = {
.pm = pm_sleep_ptr(&eeti_ts_pm),
.of_match_table = of_match_ptr(of_eeti_ts_match),
},
- .probe_new = eeti_ts_probe,
+ .probe = eeti_ts_probe,
.id_table = eeti_ts_id,
};
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
index 1a9805938e6d..a7f7e7308267 100644
--- a/drivers/input/touchscreen/egalax_ts.c
+++ b/drivers/input/touchscreen/egalax_ts.c
@@ -264,7 +264,7 @@ static struct i2c_driver egalax_ts_driver = {
.of_match_table = egalax_ts_dt_ids,
},
.id_table = egalax_ts_id,
- .probe_new = egalax_ts_probe,
+ .probe = egalax_ts_probe,
};
module_i2c_driver(egalax_ts_driver);
diff --git a/drivers/input/touchscreen/ektf2127.c b/drivers/input/touchscreen/ektf2127.c
index e6f1e46d003d..fd8724a3c19f 100644
--- a/drivers/input/touchscreen/ektf2127.c
+++ b/drivers/input/touchscreen/ektf2127.c
@@ -351,7 +351,7 @@ static struct i2c_driver ektf2127_driver = {
.pm = pm_sleep_ptr(&ektf2127_pm_ops),
.of_match_table = of_match_ptr(ektf2127_of_match),
},
- .probe_new = ektf2127_probe,
+ .probe = ektf2127_probe,
.id_table = ektf2127_i2c_id,
};
module_i2c_driver(ektf2127_driver);
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index 8a16eb51481f..2da1db64126d 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -1673,7 +1673,7 @@ MODULE_DEVICE_TABLE(of, elants_of_match);
#endif
static struct i2c_driver elants_i2c_driver = {
- .probe_new = elants_i2c_probe,
+ .probe = elants_i2c_probe,
.id_table = elants_i2c_id,
.driver = {
.name = DEVICE_NAME,
diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c
index 69eae79e2087..4af4c1e5d0da 100644
--- a/drivers/input/touchscreen/exc3000.c
+++ b/drivers/input/touchscreen/exc3000.c
@@ -460,7 +460,7 @@ static struct i2c_driver exc3000_driver = {
.of_match_table = of_match_ptr(exc3000_of_match),
},
.id_table = exc3000_id,
- .probe_new = exc3000_probe,
+ .probe = exc3000_probe,
};
module_i2c_driver(exc3000_driver);
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index d77f116680a0..f5aa240739f9 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -1544,7 +1544,7 @@ MODULE_DEVICE_TABLE(of, goodix_of_match);
#endif
static struct i2c_driver goodix_ts_driver = {
- .probe_new = goodix_ts_probe,
+ .probe = goodix_ts_probe,
.remove = goodix_ts_remove,
.id_table = goodix_ts_id,
.driver = {
diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c
index 7c7020099b0f..404153338df7 100644
--- a/drivers/input/touchscreen/hideep.c
+++ b/drivers/input/touchscreen/hideep.c
@@ -1136,7 +1136,7 @@ static struct i2c_driver hideep_driver = {
.pm = pm_sleep_ptr(&hideep_pm_ops),
},
.id_table = hideep_i2c_id,
- .probe_new = hideep_probe,
+ .probe = hideep_probe,
};
module_i2c_driver(hideep_driver);
diff --git a/drivers/input/touchscreen/himax_hx83112b.c b/drivers/input/touchscreen/himax_hx83112b.c
index e96150d80a48..4f6609dcdef3 100644
--- a/drivers/input/touchscreen/himax_hx83112b.c
+++ b/drivers/input/touchscreen/himax_hx83112b.c
@@ -349,7 +349,7 @@ MODULE_DEVICE_TABLE(of, himax_of_match);
#endif
static struct i2c_driver himax_ts_driver = {
- .probe_new = himax_probe,
+ .probe = himax_probe,
.id_table = himax_ts_id,
.driver = {
.name = "Himax-hx83112b-TS",
diff --git a/drivers/input/touchscreen/hycon-hy46xx.c b/drivers/input/touchscreen/hycon-hy46xx.c
index 8f4989aba9a4..2450cfa14de9 100644
--- a/drivers/input/touchscreen/hycon-hy46xx.c
+++ b/drivers/input/touchscreen/hycon-hy46xx.c
@@ -580,7 +580,7 @@ static struct i2c_driver hycon_hy46xx_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.id_table = hycon_hy46xx_id,
- .probe_new = hycon_hy46xx_probe,
+ .probe = hycon_hy46xx_probe,
};
module_i2c_driver(hycon_hy46xx_driver);
diff --git a/drivers/input/touchscreen/hynitron_cstxxx.c b/drivers/input/touchscreen/hynitron_cstxxx.c
index e86c85addb38..05946fee4fd4 100644
--- a/drivers/input/touchscreen/hynitron_cstxxx.c
+++ b/drivers/input/touchscreen/hynitron_cstxxx.c
@@ -488,7 +488,7 @@ static struct i2c_driver hynitron_i2c_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.id_table = hyn_tpd_id,
- .probe_new = hyn_probe,
+ .probe = hyn_probe,
};
module_i2c_driver(hynitron_i2c_driver);
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index 4897fafa4204..f7cd773f7292 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -370,22 +370,33 @@ static int ili251x_firmware_update_resolution(struct device *dev)
/* The firmware update blob might have changed the resolution. */
error = priv->chip->read_reg(client, REG_PANEL_INFO, &rs, sizeof(rs));
- if (error)
- return error;
+ if (!error) {
+ resx = le16_to_cpup((__le16 *)rs);
+ resy = le16_to_cpup((__le16 *)(rs + 2));
- resx = le16_to_cpup((__le16 *)rs);
- resy = le16_to_cpup((__le16 *)(rs + 2));
+ /* The value reported by the firmware is invalid. */
+ if (!resx || resx == 0xffff || !resy || resy == 0xffff)
+ error = -EINVAL;
+ }
- /* The value reported by the firmware is invalid. */
- if (!resx || resx == 0xffff || !resy || resy == 0xffff)
- return -EINVAL;
+ /*
+ * In case of error, the firmware might be stuck in bootloader mode,
+ * e.g. after a failed firmware update. Set maximum resolution, but
+ * do not fail to probe, so the user can re-trigger the firmware
+ * update and recover the touch controller.
+ */
+ if (error) {
+ dev_warn(dev, "Invalid resolution reported by controller.\n");
+ resx = 16384;
+ resy = 16384;
+ }
input_abs_set_max(priv->input, ABS_X, resx - 1);
input_abs_set_max(priv->input, ABS_Y, resy - 1);
input_abs_set_max(priv->input, ABS_MT_POSITION_X, resx - 1);
input_abs_set_max(priv->input, ABS_MT_POSITION_Y, resy - 1);
- return 0;
+ return error;
}
static ssize_t ili251x_firmware_update_firmware_version(struct device *dev)
@@ -977,11 +988,10 @@ static int ili210x_i2c_probe(struct i2c_client *client)
if (priv->chip->has_pressure_reg)
input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xa, 0, 0);
error = ili251x_firmware_update_cached_state(dev);
- if (error) {
- dev_err(dev, "Unable to cache firmware information, err: %d\n",
- error);
- return error;
- }
+ if (error)
+ dev_warn(dev, "Unable to cache firmware information, err: %d\n",
+ error);
+
touchscreen_parse_properties(input, true, &priv->prop);
error = input_mt_init_slots(input, priv->chip->max_touches,
@@ -1043,7 +1053,7 @@ static struct i2c_driver ili210x_ts_driver = {
.of_match_table = ili210x_dt_ids,
},
.id_table = ili210x_i2c_id,
- .probe_new = ili210x_i2c_probe,
+ .probe = ili210x_i2c_probe,
};
module_i2c_driver(ili210x_ts_driver);
diff --git a/drivers/input/touchscreen/ilitek_ts_i2c.c b/drivers/input/touchscreen/ilitek_ts_i2c.c
index d69809338498..2f872e95fbba 100644
--- a/drivers/input/touchscreen/ilitek_ts_i2c.c
+++ b/drivers/input/touchscreen/ilitek_ts_i2c.c
@@ -679,7 +679,7 @@ static struct i2c_driver ilitek_ts_i2c_driver = {
.of_match_table = of_match_ptr(ilitek_ts_i2c_match),
.acpi_match_table = ACPI_PTR(ilitekts_acpi_id),
},
- .probe_new = ilitek_ts_i2c_probe,
+ .probe = ilitek_ts_i2c_probe,
.id_table = ilitek_ts_i2c_id,
};
module_i2c_driver(ilitek_ts_i2c_driver);
diff --git a/drivers/input/touchscreen/imagis.c b/drivers/input/touchscreen/imagis.c
index de1b16e94bb8..07111ca24455 100644
--- a/drivers/input/touchscreen/imagis.c
+++ b/drivers/input/touchscreen/imagis.c
@@ -357,7 +357,7 @@ static struct i2c_driver imagis_ts_driver = {
.pm = pm_sleep_ptr(&imagis_pm_ops),
.of_match_table = of_match_ptr(imagis_of_match),
},
- .probe_new = imagis_probe,
+ .probe = imagis_probe,
};
module_i2c_driver(imagis_ts_driver);
diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c
index c73e9c5c0077..0aa9d6492df8 100644
--- a/drivers/input/touchscreen/iqs5xx.c
+++ b/drivers/input/touchscreen/iqs5xx.c
@@ -1093,7 +1093,7 @@ static struct i2c_driver iqs5xx_i2c_driver = {
.pm = pm_sleep_ptr(&iqs5xx_pm),
},
.id_table = iqs5xx_id,
- .probe_new = iqs5xx_probe,
+ .probe = iqs5xx_probe,
};
module_i2c_driver(iqs5xx_i2c_driver);
diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c
index 461023fd6a09..8be6dade118c 100644
--- a/drivers/input/touchscreen/max11801_ts.c
+++ b/drivers/input/touchscreen/max11801_ts.c
@@ -230,7 +230,7 @@ static struct i2c_driver max11801_ts_driver = {
.of_match_table = max11801_ts_dt_ids,
},
.id_table = max11801_ts_id,
- .probe_new = max11801_ts_probe,
+ .probe = max11801_ts_probe,
};
module_i2c_driver(max11801_ts_driver);
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c
index 704e36087ca2..ac28019ba4c3 100644
--- a/drivers/input/touchscreen/mcs5000_ts.c
+++ b/drivers/input/touchscreen/mcs5000_ts.c
@@ -272,7 +272,7 @@ static const struct i2c_device_id mcs5000_ts_id[] = {
MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id);
static struct i2c_driver mcs5000_ts_driver = {
- .probe_new = mcs5000_ts_probe,
+ .probe = mcs5000_ts_probe,
.driver = {
.name = "mcs5000_ts",
.pm = pm_sleep_ptr(&mcs5000_ts_pm),
diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c
index 89b6020a9a61..32896e5085bd 100644
--- a/drivers/input/touchscreen/melfas_mip4.c
+++ b/drivers/input/touchscreen/melfas_mip4.c
@@ -1591,7 +1591,7 @@ MODULE_DEVICE_TABLE(i2c, mip4_i2c_ids);
static struct i2c_driver mip4_driver = {
.id_table = mip4_i2c_ids,
- .probe_new = mip4_probe,
+ .probe = mip4_probe,
.driver = {
.name = MIP4_DEVICE_NAME,
.of_match_table = of_match_ptr(mip4_of_match),
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c
index 69fcc88d4f80..2384ea69a3f8 100644
--- a/drivers/input/touchscreen/migor_ts.c
+++ b/drivers/input/touchscreen/migor_ts.c
@@ -221,7 +221,7 @@ static struct i2c_driver migor_ts_driver = {
.name = "migor_ts",
.pm = pm_sleep_ptr(&migor_ts_pm),
},
- .probe_new = migor_ts_probe,
+ .probe = migor_ts_probe,
.remove = migor_ts_remove,
.id_table = migor_ts_id,
};
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 4dbca1aad89d..ac12494c7930 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -638,7 +638,7 @@ static struct i2c_driver mms114_driver = {
.pm = pm_sleep_ptr(&mms114_pm_ops),
.of_match_table = of_match_ptr(mms114_dt_match),
},
- .probe_new = mms114_probe,
+ .probe = mms114_probe,
.id_table = mms114_id,
};
diff --git a/drivers/input/touchscreen/msg2638.c b/drivers/input/touchscreen/msg2638.c
index b23db689d995..a38af3fee34a 100644
--- a/drivers/input/touchscreen/msg2638.c
+++ b/drivers/input/touchscreen/msg2638.c
@@ -492,7 +492,7 @@ static const struct of_device_id msg2638_of_match[] = {
MODULE_DEVICE_TABLE(of, msg2638_of_match);
static struct i2c_driver msg2638_ts_driver = {
- .probe_new = msg2638_ts_probe,
+ .probe = msg2638_ts_probe,
.driver = {
.name = "MStar-TS",
.pm = pm_sleep_ptr(&msg2638_pm_ops),
diff --git a/drivers/input/touchscreen/novatek-nvt-ts.c b/drivers/input/touchscreen/novatek-nvt-ts.c
index 3e551f9d31d7..7f7d879aac6d 100644
--- a/drivers/input/touchscreen/novatek-nvt-ts.c
+++ b/drivers/input/touchscreen/novatek-nvt-ts.c
@@ -290,7 +290,7 @@ static struct i2c_driver nvt_ts_driver = {
.name = "novatek-nvt-ts",
.pm = pm_sleep_ptr(&nvt_ts_pm_ops),
},
- .probe_new = nvt_ts_probe,
+ .probe = nvt_ts_probe,
.id_table = nvt_ts_i2c_id,
};
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index f09f4831bad4..554e179c2e48 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -617,7 +617,7 @@ static struct i2c_driver pixcir_i2c_ts_driver = {
.pm = pm_sleep_ptr(&pixcir_dev_pm_ops),
.of_match_table = of_match_ptr(pixcir_of_match),
},
- .probe_new = pixcir_i2c_ts_probe,
+ .probe = pixcir_i2c_ts_probe,
.id_table = pixcir_i2c_ts_id,
};
diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c
index 49a06d3876cf..76e7d62d5870 100644
--- a/drivers/input/touchscreen/raydium_i2c_ts.c
+++ b/drivers/input/touchscreen/raydium_i2c_ts.c
@@ -1273,7 +1273,7 @@ MODULE_DEVICE_TABLE(of, raydium_of_match);
#endif
static struct i2c_driver raydium_i2c_driver = {
- .probe_new = raydium_i2c_probe,
+ .probe = raydium_i2c_probe,
.id_table = raydium_i2c_id,
.driver = {
.name = "raydium_ts",
diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c
index 833422e5fd6d..240424f06b98 100644
--- a/drivers/input/touchscreen/rohm_bu21023.c
+++ b/drivers/input/touchscreen/rohm_bu21023.c
@@ -1183,7 +1183,7 @@ static struct i2c_driver rohm_bu21023_i2c_driver = {
.driver = {
.name = BU21023_NAME,
},
- .probe_new = rohm_bu21023_i2c_probe,
+ .probe = rohm_bu21023_i2c_probe,
.id_table = rohm_bu21023_i2c_id,
};
module_i2c_driver(rohm_bu21023_i2c_driver);
diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c
index 371cf4848ad5..998d99d18911 100644
--- a/drivers/input/touchscreen/s6sy761.c
+++ b/drivers/input/touchscreen/s6sy761.c
@@ -538,7 +538,7 @@ static struct i2c_driver s6sy761_driver = {
.of_match_table = of_match_ptr(s6sy761_of_match),
.pm = pm_ptr(&s6sy761_pm_ops),
},
- .probe_new = s6sy761_probe,
+ .probe = s6sy761_probe,
.remove = s6sy761_remove,
.id_table = s6sy761_id,
};
diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
index a37fac089010..9e28f962e059 100644
--- a/drivers/input/touchscreen/silead.c
+++ b/drivers/input/touchscreen/silead.c
@@ -826,7 +826,7 @@ MODULE_DEVICE_TABLE(of, silead_ts_of_match);
#endif
static struct i2c_driver silead_ts_driver = {
- .probe_new = silead_ts_probe,
+ .probe = silead_ts_probe,
.id_table = silead_ts_id,
.driver = {
.name = SILEAD_TS_NAME,
diff --git a/drivers/input/touchscreen/sis_i2c.c b/drivers/input/touchscreen/sis_i2c.c
index 5a493b15b25d..426564d0fc39 100644
--- a/drivers/input/touchscreen/sis_i2c.c
+++ b/drivers/input/touchscreen/sis_i2c.c
@@ -393,7 +393,7 @@ static struct i2c_driver sis_ts_driver = {
.name = SIS_I2C_NAME,
.of_match_table = of_match_ptr(sis_ts_dt_ids),
},
- .probe_new = sis_ts_probe,
+ .probe = sis_ts_probe,
.id_table = sis_ts_id,
};
module_i2c_driver(sis_ts_driver);
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index f49566dc96f8..6475084aee1b 100644
--- a/drivers/input/touchscreen/st1232.c
+++ b/drivers/input/touchscreen/st1232.c
@@ -384,7 +384,7 @@ static const struct of_device_id st1232_ts_dt_ids[] = {
MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids);
static struct i2c_driver st1232_ts_driver = {
- .probe_new = st1232_ts_probe,
+ .probe = st1232_ts_probe,
.id_table = st1232_ts_id,
.driver = {
.name = ST1232_TS_NAME,
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index fdbf5e68943c..56e371fd88fa 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -808,7 +808,7 @@ static struct i2c_driver stmfts_driver = {
.pm = pm_ptr(&stmfts_pm_ops),
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
- .probe_new = stmfts_probe,
+ .probe = stmfts_probe,
.remove = stmfts_remove,
.id_table = stmfts_id,
};
diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c
index 52ae73035830..0293c493bc79 100644
--- a/drivers/input/touchscreen/sx8654.c
+++ b/drivers/input/touchscreen/sx8654.c
@@ -470,7 +470,7 @@ static struct i2c_driver sx8654_driver = {
.of_match_table = of_match_ptr(sx8654_of_match),
},
.id_table = sx8654_id_table,
- .probe_new = sx8654_probe,
+ .probe = sx8654_probe,
};
module_i2c_driver(sx8654_driver);
diff --git a/drivers/input/touchscreen/tsc2004.c b/drivers/input/touchscreen/tsc2004.c
index 45f39eb20638..b5e904c5b7c4 100644
--- a/drivers/input/touchscreen/tsc2004.c
+++ b/drivers/input/touchscreen/tsc2004.c
@@ -68,7 +68,7 @@ static struct i2c_driver tsc2004_driver = {
.pm = pm_sleep_ptr(&tsc200x_pm_ops),
},
.id_table = tsc2004_idtable,
- .probe_new = tsc2004_probe,
+ .probe = tsc2004_probe,
.remove = tsc2004_remove,
};
module_i2c_driver(tsc2004_driver);
diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c
index 21916a30fb76..b3655250d4a7 100644
--- a/drivers/input/touchscreen/tsc2007_core.c
+++ b/drivers/input/touchscreen/tsc2007_core.c
@@ -418,7 +418,7 @@ static struct i2c_driver tsc2007_driver = {
.of_match_table = tsc2007_of_match,
},
.id_table = tsc2007_idtable,
- .probe_new = tsc2007_probe,
+ .probe = tsc2007_probe,
};
module_i2c_driver(tsc2007_driver);
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
index a145b9105255..f389f9c004a9 100644
--- a/drivers/input/touchscreen/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom_i2c.c
@@ -264,7 +264,7 @@ static struct i2c_driver wacom_i2c_driver = {
.pm = pm_sleep_ptr(&wacom_i2c_pm),
},
- .probe_new = wacom_i2c_probe,
+ .probe = wacom_i2c_probe,
.id_table = wacom_i2c_id,
};
module_i2c_driver(wacom_i2c_driver);
diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c
index 771962af3d0a..cbc4750c53f9 100644
--- a/drivers/input/touchscreen/wdt87xx_i2c.c
+++ b/drivers/input/touchscreen/wdt87xx_i2c.c
@@ -1169,7 +1169,7 @@ static const struct acpi_device_id wdt87xx_acpi_id[] = {
MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id);
static struct i2c_driver wdt87xx_driver = {
- .probe_new = wdt87xx_ts_probe,
+ .probe = wdt87xx_ts_probe,
.id_table = wdt87xx_dev_id,
.driver = {
.name = WDT87XX_NAME,
diff --git a/drivers/input/touchscreen/zet6223.c b/drivers/input/touchscreen/zet6223.c
index bfa0c637d569..1a034471f103 100644
--- a/drivers/input/touchscreen/zet6223.c
+++ b/drivers/input/touchscreen/zet6223.c
@@ -248,7 +248,7 @@ static struct i2c_driver zet6223_driver = {
.name = "zet6223",
.of_match_table = zet6223_of_match,
},
- .probe_new = zet6223_probe,
+ .probe = zet6223_probe,
.id_table = zet6223_id
};
module_i2c_driver(zet6223_driver);
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c
index 76b194285e1c..5be5112845e1 100644
--- a/drivers/input/touchscreen/zforce_ts.c
+++ b/drivers/input/touchscreen/zforce_ts.c
@@ -944,7 +944,7 @@ static struct i2c_driver zforce_driver = {
.pm = pm_sleep_ptr(&zforce_pm_ops),
.of_match_table = of_match_ptr(zforce_dt_idtable),
},
- .probe_new = zforce_probe,
+ .probe = zforce_probe,
.id_table = zforce_idtable,
};
diff --git a/drivers/input/touchscreen/zinitix.c b/drivers/input/touchscreen/zinitix.c
index b6ece47151b8..1b4807ba4624 100644
--- a/drivers/input/touchscreen/zinitix.c
+++ b/drivers/input/touchscreen/zinitix.c
@@ -617,7 +617,7 @@ MODULE_DEVICE_TABLE(of, zinitix_of_match);
#endif
static struct i2c_driver zinitix_ts_driver = {
- .probe_new = zinitix_ts_probe,
+ .probe = zinitix_ts_probe,
.driver = {
.name = "Zinitix-TS",
.pm = pm_sleep_ptr(&zinitix_pm_ops),
diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig
index d637a89d4695..5faa8d2aecff 100644
--- a/drivers/interconnect/Kconfig
+++ b/drivers/interconnect/Kconfig
@@ -15,4 +15,10 @@ source "drivers/interconnect/imx/Kconfig"
source "drivers/interconnect/qcom/Kconfig"
source "drivers/interconnect/samsung/Kconfig"
+config INTERCONNECT_CLK
+ tristate
+ depends on COMMON_CLK
+ help
+ Support for wrapping clocks into the interconnect nodes.
+
endif
diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile
index 97d393fd638d..5604ce351a9f 100644
--- a/drivers/interconnect/Makefile
+++ b/drivers/interconnect/Makefile
@@ -7,3 +7,5 @@ obj-$(CONFIG_INTERCONNECT) += icc-core.o
obj-$(CONFIG_INTERCONNECT_IMX) += imx/
obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/
obj-$(CONFIG_INTERCONNECT_SAMSUNG) += samsung/
+
+obj-$(CONFIG_INTERCONNECT_CLK) += icc-clk.o
diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index ec46bcb16d5e..5fac448c28fd 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -587,7 +587,7 @@ EXPORT_SYMBOL_GPL(icc_set_tag);
/**
* icc_get_name() - Get name of the icc path
- * @path: reference to the path returned by icc_get()
+ * @path: interconnect path
*
* This function is used by an interconnect consumer to get the name of the icc
* path.
@@ -605,7 +605,7 @@ EXPORT_SYMBOL_GPL(icc_get_name);
/**
* icc_set_bw() - set bandwidth constraints on an interconnect path
- * @path: reference to the path returned by icc_get()
+ * @path: interconnect path
* @avg_bw: average bandwidth in kilobytes per second
* @peak_bw: peak bandwidth in kilobytes per second
*
@@ -705,54 +705,6 @@ int icc_disable(struct icc_path *path)
EXPORT_SYMBOL_GPL(icc_disable);
/**
- * icc_get() - return a handle for path between two endpoints
- * @dev: the device requesting the path
- * @src_id: source device port id
- * @dst_id: destination device port id
- *
- * This function will search for a path between two endpoints and return an
- * icc_path handle on success. Use icc_put() to release
- * constraints when they are not needed anymore.
- * If the interconnect API is disabled, NULL is returned and the consumer
- * drivers will still build. Drivers are free to handle this specifically,
- * but they don't have to.
- *
- * Return: icc_path pointer on success, ERR_PTR() on error or NULL if the
- * interconnect API is disabled.
- */
-struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id)
-{
- struct icc_node *src, *dst;
- struct icc_path *path = ERR_PTR(-EPROBE_DEFER);
-
- mutex_lock(&icc_lock);
-
- src = node_find(src_id);
- if (!src)
- goto out;
-
- dst = node_find(dst_id);
- if (!dst)
- goto out;
-
- path = path_find(dev, src, dst);
- if (IS_ERR(path)) {
- dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path));
- goto out;
- }
-
- path->name = kasprintf(GFP_KERNEL, "%s-%s", src->name, dst->name);
- if (!path->name) {
- kfree(path);
- path = ERR_PTR(-ENOMEM);
- }
-out:
- mutex_unlock(&icc_lock);
- return path;
-}
-EXPORT_SYMBOL_GPL(icc_get);
-
-/**
* icc_put() - release the reference to the icc_path
* @path: interconnect path
*
diff --git a/drivers/interconnect/icc-clk.c b/drivers/interconnect/icc-clk.c
new file mode 100644
index 000000000000..4d43ebff4257
--- /dev/null
+++ b/drivers/interconnect/icc-clk.c
@@ -0,0 +1,174 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023, Linaro Ltd.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/interconnect-clk.h>
+#include <linux/interconnect-provider.h>
+
+struct icc_clk_node {
+ struct clk *clk;
+ bool enabled;
+};
+
+struct icc_clk_provider {
+ struct icc_provider provider;
+ int num_clocks;
+ struct icc_clk_node clocks[];
+};
+
+#define to_icc_clk_provider(_provider) \
+ container_of(_provider, struct icc_clk_provider, provider)
+
+static int icc_clk_set(struct icc_node *src, struct icc_node *dst)
+{
+ struct icc_clk_node *qn = src->data;
+ int ret;
+
+ if (!qn || !qn->clk)
+ return 0;
+
+ if (!src->peak_bw) {
+ if (qn->enabled)
+ clk_disable_unprepare(qn->clk);
+ qn->enabled = false;
+
+ return 0;
+ }
+
+ if (!qn->enabled) {
+ ret = clk_prepare_enable(qn->clk);
+ if (ret)
+ return ret;
+ qn->enabled = true;
+ }
+
+ return clk_set_rate(qn->clk, icc_units_to_bps(src->peak_bw));
+}
+
+static int icc_clk_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
+{
+ struct icc_clk_node *qn = node->data;
+
+ if (!qn || !qn->clk)
+ *peak = INT_MAX;
+ else
+ *peak = Bps_to_icc(clk_get_rate(qn->clk));
+
+ return 0;
+}
+
+/**
+ * icc_clk_register() - register a new clk-based interconnect provider
+ * @dev: device supporting this provider
+ * @first_id: an ID of the first provider's node
+ * @num_clocks: number of instances of struct icc_clk_data
+ * @data: data for the provider
+ *
+ * Registers and returns a clk-based interconnect provider. It is a simple
+ * wrapper around COMMON_CLK framework, allowing other devices to vote on the
+ * clock rate.
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+struct icc_provider *icc_clk_register(struct device *dev,
+ unsigned int first_id,
+ unsigned int num_clocks,
+ const struct icc_clk_data *data)
+{
+ struct icc_clk_provider *qp;
+ struct icc_provider *provider;
+ struct icc_onecell_data *onecell;
+ struct icc_node *node;
+ int ret, i, j;
+
+ onecell = devm_kzalloc(dev, struct_size(onecell, nodes, 2 * num_clocks), GFP_KERNEL);
+ if (!onecell)
+ return ERR_PTR(-ENOMEM);
+
+ qp = devm_kzalloc(dev, struct_size(qp, clocks, num_clocks), GFP_KERNEL);
+ if (!qp)
+ return ERR_PTR(-ENOMEM);
+
+ qp->num_clocks = num_clocks;
+
+ provider = &qp->provider;
+ provider->dev = dev;
+ provider->get_bw = icc_clk_get_bw;
+ provider->set = icc_clk_set;
+ provider->aggregate = icc_std_aggregate;
+ provider->xlate = of_icc_xlate_onecell;
+ INIT_LIST_HEAD(&provider->nodes);
+ provider->data = onecell;
+
+ icc_provider_init(provider);
+
+ for (i = 0, j = 0; i < num_clocks; i++) {
+ qp->clocks[i].clk = data[i].clk;
+
+ node = icc_node_create(first_id + j);
+ if (IS_ERR(node)) {
+ ret = PTR_ERR(node);
+ goto err;
+ }
+
+ node->name = devm_kasprintf(dev, GFP_KERNEL, "%s_master", data[i].name);
+ node->data = &qp->clocks[i];
+ icc_node_add(node, provider);
+ /* link to the next node, slave */
+ icc_link_create(node, first_id + j + 1);
+ onecell->nodes[j++] = node;
+
+ node = icc_node_create(first_id + j);
+ if (IS_ERR(node)) {
+ ret = PTR_ERR(node);
+ goto err;
+ }
+
+ node->name = devm_kasprintf(dev, GFP_KERNEL, "%s_slave", data[i].name);
+ /* no data for slave node */
+ icc_node_add(node, provider);
+ onecell->nodes[j++] = node;
+ }
+
+ onecell->num_nodes = j;
+
+ ret = icc_provider_register(provider);
+ if (ret)
+ goto err;
+
+ return provider;
+
+err:
+ icc_nodes_remove(provider);
+
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(icc_clk_register);
+
+/**
+ * icc_clk_unregister() - unregister a previously registered clk interconnect provider
+ * @provider: provider returned by icc_clk_register()
+ */
+void icc_clk_unregister(struct icc_provider *provider)
+{
+ struct icc_clk_provider *qp = container_of(provider, struct icc_clk_provider, provider);
+ int i;
+
+ icc_provider_deregister(&qp->provider);
+ icc_nodes_remove(&qp->provider);
+
+ for (i = 0; i < qp->num_clocks; i++) {
+ struct icc_clk_node *qn = &qp->clocks[i];
+
+ if (qn->enabled)
+ clk_disable_unprepare(qn->clk);
+ }
+}
+EXPORT_SYMBOL_GPL(icc_clk_unregister);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Interconnect wrapper for clocks");
+MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>");
diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 5341fa169dbf..6acc7686ed38 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -50,7 +50,7 @@
#define NOC_QOS_MODE_FIXED_VAL 0x0
#define NOC_QOS_MODE_BYPASS_VAL 0x2
-static int qcom_icc_set_qnoc_qos(struct icc_node *src, u64 max_bw)
+static int qcom_icc_set_qnoc_qos(struct icc_node *src)
{
struct icc_provider *provider = src->provider;
struct qcom_icc_provider *qp = to_qcom_provider(provider);
@@ -95,7 +95,7 @@ static int qcom_icc_bimc_set_qos_health(struct qcom_icc_provider *qp,
mask, val);
}
-static int qcom_icc_set_bimc_qos(struct icc_node *src, u64 max_bw)
+static int qcom_icc_set_bimc_qos(struct icc_node *src)
{
struct qcom_icc_provider *qp;
struct qcom_icc_node *qn;
@@ -150,7 +150,7 @@ static int qcom_icc_noc_set_qos_priority(struct qcom_icc_provider *qp,
NOC_QOS_PRIORITY_P0_MASK, qos->prio_level);
}
-static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw)
+static int qcom_icc_set_noc_qos(struct icc_node *src)
{
struct qcom_icc_provider *qp;
struct qcom_icc_node *qn;
@@ -187,7 +187,7 @@ static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw)
NOC_QOS_MODEn_MASK, mode);
}
-static int qcom_icc_qos_set(struct icc_node *node, u64 sum_bw)
+static int qcom_icc_qos_set(struct icc_node *node)
{
struct qcom_icc_provider *qp = to_qcom_provider(node->provider);
struct qcom_icc_node *qn = node->data;
@@ -196,38 +196,41 @@ static int qcom_icc_qos_set(struct icc_node *node, u64 sum_bw)
switch (qp->type) {
case QCOM_ICC_BIMC:
- return qcom_icc_set_bimc_qos(node, sum_bw);
+ return qcom_icc_set_bimc_qos(node);
case QCOM_ICC_QNOC:
- return qcom_icc_set_qnoc_qos(node, sum_bw);
+ return qcom_icc_set_qnoc_qos(node);
default:
- return qcom_icc_set_noc_qos(node, sum_bw);
+ return qcom_icc_set_noc_qos(node);
}
}
-static int qcom_icc_rpm_set(int mas_rpm_id, int slv_rpm_id, u64 sum_bw)
+static int qcom_icc_rpm_set(struct qcom_icc_node *qn, u64 sum_bw)
{
int ret = 0;
- if (mas_rpm_id != -1) {
+ if (qn->qos.ap_owned)
+ return 0;
+
+ if (qn->mas_rpm_id != -1) {
ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE,
RPM_BUS_MASTER_REQ,
- mas_rpm_id,
+ qn->mas_rpm_id,
sum_bw);
if (ret) {
pr_err("qcom_icc_rpm_smd_send mas %d error %d\n",
- mas_rpm_id, ret);
+ qn->mas_rpm_id, ret);
return ret;
}
}
- if (slv_rpm_id != -1) {
+ if (qn->slv_rpm_id != -1) {
ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE,
RPM_BUS_SLAVE_REQ,
- slv_rpm_id,
+ qn->slv_rpm_id,
sum_bw);
if (ret) {
pr_err("qcom_icc_rpm_smd_send slv %d error %d\n",
- slv_rpm_id, ret);
+ qn->slv_rpm_id, ret);
return ret;
}
}
@@ -235,26 +238,6 @@ static int qcom_icc_rpm_set(int mas_rpm_id, int slv_rpm_id, u64 sum_bw)
return ret;
}
-static int __qcom_icc_set(struct icc_node *n, struct qcom_icc_node *qn,
- u64 sum_bw)
-{
- int ret;
-
- if (!qn->qos.ap_owned) {
- /* send bandwidth request message to the RPM processor */
- ret = qcom_icc_rpm_set(qn->mas_rpm_id, qn->slv_rpm_id, sum_bw);
- if (ret)
- return ret;
- } else if (qn->qos.qos_mode != NOC_QOS_MODE_INVALID) {
- /* set bandwidth directly from the AP */
- ret = qcom_icc_qos_set(n, sum_bw);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
/**
* qcom_icc_pre_bw_aggregate - cleans up values before re-aggregate requests
* @node: icc node to operate on
@@ -370,16 +353,17 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
sum_bw = icc_units_to_bps(max_agg_avg);
- ret = __qcom_icc_set(src, src_qn, sum_bw);
+ ret = qcom_icc_rpm_set(src_qn, sum_bw);
if (ret)
return ret;
+
if (dst_qn) {
- ret = __qcom_icc_set(dst, dst_qn, sum_bw);
+ ret = qcom_icc_rpm_set(dst_qn, sum_bw);
if (ret)
return ret;
}
- for (i = 0; i < qp->num_clks; i++) {
+ for (i = 0; i < qp->num_bus_clks; i++) {
/*
* Use WAKE bucket for active clock, otherwise, use SLEEP bucket
* for other clocks. If a platform doesn't set interconnect
@@ -425,7 +409,7 @@ int qnoc_probe(struct platform_device *pdev)
struct qcom_icc_provider *qp;
struct icc_node *node;
size_t num_nodes, i;
- const char * const *cds;
+ const char * const *cds = NULL;
int cd_num;
int ret;
@@ -440,21 +424,20 @@ int qnoc_probe(struct platform_device *pdev)
qnodes = desc->nodes;
num_nodes = desc->num_nodes;
- if (desc->num_clocks) {
- cds = desc->clocks;
- cd_num = desc->num_clocks;
+ if (desc->num_intf_clocks) {
+ cds = desc->intf_clocks;
+ cd_num = desc->num_intf_clocks;
} else {
- cds = bus_clocks;
- cd_num = ARRAY_SIZE(bus_clocks);
+ /* 0 intf clocks is perfectly fine */
+ cd_num = 0;
}
- qp = devm_kzalloc(dev, struct_size(qp, bus_clks, cd_num), GFP_KERNEL);
+ qp = devm_kzalloc(dev, sizeof(*qp), GFP_KERNEL);
if (!qp)
return -ENOMEM;
- qp->bus_clk_rate = devm_kcalloc(dev, cd_num, sizeof(*qp->bus_clk_rate),
- GFP_KERNEL);
- if (!qp->bus_clk_rate)
+ qp->intf_clks = devm_kcalloc(dev, cd_num, sizeof(*qp->intf_clks), GFP_KERNEL);
+ if (!qp->intf_clks)
return -ENOMEM;
data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
@@ -462,9 +445,13 @@ int qnoc_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
+ qp->num_intf_clks = cd_num;
for (i = 0; i < cd_num; i++)
- qp->bus_clks[i].id = cds[i];
- qp->num_clks = cd_num;
+ qp->intf_clks[i].id = cds[i];
+
+ qp->num_bus_clks = desc->no_clk_scaling ? 0 : NUM_BUS_CLKS;
+ for (i = 0; i < qp->num_bus_clks; i++)
+ qp->bus_clks[i].id = bus_clocks[i];
qp->type = desc->type;
qp->qos_offset = desc->qos_offset;
@@ -494,11 +481,15 @@ int qnoc_probe(struct platform_device *pdev)
}
regmap_done:
- ret = devm_clk_bulk_get_optional(dev, qp->num_clks, qp->bus_clks);
+ ret = devm_clk_bulk_get(dev, qp->num_bus_clks, qp->bus_clks);
+ if (ret)
+ return ret;
+
+ ret = clk_bulk_prepare_enable(qp->num_bus_clks, qp->bus_clks);
if (ret)
return ret;
- ret = clk_bulk_prepare_enable(qp->num_clks, qp->bus_clks);
+ ret = devm_clk_bulk_get(dev, qp->num_intf_clks, qp->intf_clks);
if (ret)
return ret;
@@ -512,6 +503,11 @@ regmap_done:
icc_provider_init(provider);
+ /* If this fails, bus accesses will crash the platform! */
+ ret = clk_bulk_prepare_enable(qp->num_intf_clks, qp->intf_clks);
+ if (ret)
+ return ret;
+
for (i = 0; i < num_nodes; i++) {
size_t j;
@@ -528,10 +524,20 @@ regmap_done:
for (j = 0; j < qnodes[i]->num_links; j++)
icc_link_create(node, qnodes[i]->links[j]);
+ /* Set QoS registers (we only need to do it once, generally) */
+ if (qnodes[i]->qos.ap_owned &&
+ qnodes[i]->qos.qos_mode != NOC_QOS_MODE_INVALID) {
+ ret = qcom_icc_qos_set(node);
+ if (ret)
+ return ret;
+ }
+
data->nodes[i] = node;
}
data->num_nodes = num_nodes;
+ clk_bulk_disable_unprepare(qp->num_intf_clks, qp->intf_clks);
+
ret = icc_provider_register(provider);
if (ret)
goto err_remove_nodes;
@@ -551,7 +557,7 @@ err_deregister_provider:
icc_provider_deregister(provider);
err_remove_nodes:
icc_nodes_remove(provider);
- clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
+ clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks);
return ret;
}
@@ -563,7 +569,7 @@ int qnoc_remove(struct platform_device *pdev)
icc_provider_deregister(&qp->provider);
icc_nodes_remove(&qp->provider);
- clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
+ clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks);
return 0;
}
diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index 22bdb1e4bb12..ee705edf19dd 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -20,24 +20,32 @@ enum qcom_icc_type {
QCOM_ICC_QNOC,
};
+#define NUM_BUS_CLKS 2
+
/**
* struct qcom_icc_provider - Qualcomm specific interconnect provider
* @provider: generic interconnect provider
- * @num_clks: the total number of clk_bulk_data entries
+ * @num_bus_clks: the total number of bus_clks clk_bulk_data entries (0 or 2)
+ * @num_intf_clks: the total number of intf_clks clk_bulk_data entries
* @type: the ICC provider type
* @regmap: regmap for QoS registers read/write access
* @qos_offset: offset to QoS registers
* @bus_clk_rate: bus clock rate in Hz
* @bus_clks: the clk_bulk_data table of bus clocks
+ * @intf_clks: a clk_bulk_data array of interface clocks
+ * @is_on: whether the bus is powered on
*/
struct qcom_icc_provider {
struct icc_provider provider;
- int num_clks;
+ int num_bus_clks;
+ int num_intf_clks;
enum qcom_icc_type type;
struct regmap *regmap;
unsigned int qos_offset;
- u64 *bus_clk_rate;
- struct clk_bulk_data bus_clks[];
+ u64 bus_clk_rate[NUM_BUS_CLKS];
+ struct clk_bulk_data bus_clks[NUM_BUS_CLKS];
+ struct clk_bulk_data *intf_clks;
+ bool is_on;
};
/**
@@ -91,8 +99,10 @@ struct qcom_icc_node {
struct qcom_icc_desc {
struct qcom_icc_node * const *nodes;
size_t num_nodes;
- const char * const *clocks;
- size_t num_clocks;
+ const char * const *bus_clocks;
+ const char * const *intf_clocks;
+ size_t num_intf_clocks;
+ bool no_clk_scaling;
enum qcom_icc_type type;
const struct regmap_config *regmap_cfg;
unsigned int qos_offset;
diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
index 14efd2761b7a..20340fb62fe6 100644
--- a/drivers/interconnect/qcom/msm8996.c
+++ b/drivers/interconnect/qcom/msm8996.c
@@ -21,21 +21,17 @@
#include "smd-rpm.h"
#include "msm8996.h"
-static const char * const bus_mm_clocks[] = {
- "bus",
- "bus_a",
+static const char * const mm_intf_clocks[] = {
"iface"
};
-static const char * const bus_a0noc_clocks[] = {
+static const char * const a0noc_intf_clocks[] = {
"aggre0_snoc_axi",
"aggre0_cnoc_ahb",
"aggre0_noc_mpu_cfg"
};
-static const char * const bus_a2noc_clocks[] = {
- "bus",
- "bus_a",
+static const char * const a2noc_intf_clocks[] = {
"aggre2_ufs_axi",
"ufs_axi"
};
@@ -1821,8 +1817,9 @@ static const struct qcom_icc_desc msm8996_a0noc = {
.type = QCOM_ICC_NOC,
.nodes = a0noc_nodes,
.num_nodes = ARRAY_SIZE(a0noc_nodes),
- .clocks = bus_a0noc_clocks,
- .num_clocks = ARRAY_SIZE(bus_a0noc_clocks),
+ .intf_clocks = a0noc_intf_clocks,
+ .num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
+ .no_clk_scaling = true,
.regmap_cfg = &msm8996_a0noc_regmap_config
};
@@ -1865,8 +1862,8 @@ static const struct qcom_icc_desc msm8996_a2noc = {
.type = QCOM_ICC_NOC,
.nodes = a2noc_nodes,
.num_nodes = ARRAY_SIZE(a2noc_nodes),
- .clocks = bus_a2noc_clocks,
- .num_clocks = ARRAY_SIZE(bus_a2noc_clocks),
+ .intf_clocks = a2noc_intf_clocks,
+ .num_intf_clocks = ARRAY_SIZE(a2noc_intf_clocks),
.regmap_cfg = &msm8996_a2noc_regmap_config
};
@@ -2004,8 +2001,8 @@ static const struct qcom_icc_desc msm8996_mnoc = {
.type = QCOM_ICC_NOC,
.nodes = mnoc_nodes,
.num_nodes = ARRAY_SIZE(mnoc_nodes),
- .clocks = bus_mm_clocks,
- .num_clocks = ARRAY_SIZE(bus_mm_clocks),
+ .intf_clocks = mm_intf_clocks,
+ .num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
.regmap_cfg = &msm8996_mnoc_regmap_config
};
@@ -2111,7 +2108,17 @@ static struct platform_driver qnoc_driver = {
.sync_state = icc_sync_state,
}
};
-module_platform_driver(qnoc_driver);
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+module_exit(qnoc_driver_exit);
MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
MODULE_DESCRIPTION("Qualcomm MSM8996 NoC driver");
diff --git a/drivers/interconnect/qcom/sdm660.c b/drivers/interconnect/qcom/sdm660.c
index 8d879b0bcabc..7ffaf70d62d3 100644
--- a/drivers/interconnect/qcom/sdm660.c
+++ b/drivers/interconnect/qcom/sdm660.c
@@ -127,15 +127,11 @@ enum {
SDM660_SNOC,
};
-static const char * const bus_mm_clocks[] = {
- "bus",
- "bus_a",
+static const char * const mm_intf_clocks[] = {
"iface",
};
-static const char * const bus_a2noc_clocks[] = {
- "bus",
- "bus_a",
+static const char * const a2noc_intf_clocks[] = {
"ipa",
"ufs_axi",
"aggre2_ufs_axi",
@@ -1516,8 +1512,8 @@ static const struct qcom_icc_desc sdm660_a2noc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_a2noc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_a2noc_nodes),
- .clocks = bus_a2noc_clocks,
- .num_clocks = ARRAY_SIZE(bus_a2noc_clocks),
+ .intf_clocks = a2noc_intf_clocks,
+ .num_intf_clocks = ARRAY_SIZE(a2noc_intf_clocks),
.regmap_cfg = &sdm660_a2noc_regmap_config,
};
@@ -1620,6 +1616,7 @@ static const struct qcom_icc_desc sdm660_gnoc = {
.nodes = sdm660_gnoc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_gnoc_nodes),
.regmap_cfg = &sdm660_gnoc_regmap_config,
+ .no_clk_scaling = true,
};
static struct qcom_icc_node * const sdm660_mnoc_nodes[] = {
@@ -1659,8 +1656,8 @@ static const struct qcom_icc_desc sdm660_mnoc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_mnoc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_mnoc_nodes),
- .clocks = bus_mm_clocks,
- .num_clocks = ARRAY_SIZE(bus_mm_clocks),
+ .intf_clocks = mm_intf_clocks,
+ .num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
.regmap_cfg = &sdm660_mnoc_regmap_config,
};
diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index 9beeceb9d825..0c35018239ce 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -11,12 +11,15 @@
#include "amd_iommu_types.h"
-extern irqreturn_t amd_iommu_int_thread(int irq, void *data);
-extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
-extern void amd_iommu_apply_erratum_63(struct amd_iommu *iommu, u16 devid);
-extern void amd_iommu_restart_event_logging(struct amd_iommu *iommu);
-extern void amd_iommu_restart_ga_log(struct amd_iommu *iommu);
-extern void amd_iommu_set_rlookup_table(struct amd_iommu *iommu, u16 devid);
+irqreturn_t amd_iommu_int_thread(int irq, void *data);
+irqreturn_t amd_iommu_int_handler(int irq, void *data);
+void amd_iommu_apply_erratum_63(struct amd_iommu *iommu, u16 devid);
+void amd_iommu_restart_event_logging(struct amd_iommu *iommu);
+void amd_iommu_restart_ga_log(struct amd_iommu *iommu);
+int amd_iommu_init_devices(void);
+void amd_iommu_uninit_devices(void);
+void amd_iommu_init_notifier(void);
+void amd_iommu_set_rlookup_table(struct amd_iommu *iommu, u16 devid);
#ifdef CONFIG_AMD_IOMMU_DEBUGFS
void amd_iommu_debugfs_setup(struct amd_iommu *iommu);
@@ -25,11 +28,11 @@ static inline void amd_iommu_debugfs_setup(struct amd_iommu *iommu) {}
#endif
/* Needed for interrupt remapping */
-extern int amd_iommu_prepare(void);
-extern int amd_iommu_enable(void);
-extern void amd_iommu_disable(void);
-extern int amd_iommu_reenable(int);
-extern int amd_iommu_enable_faulting(void);
+int amd_iommu_prepare(void);
+int amd_iommu_enable(void);
+void amd_iommu_disable(void);
+int amd_iommu_reenable(int mode);
+int amd_iommu_enable_faulting(void);
extern int amd_iommu_guest_ir;
extern enum io_pgtable_fmt amd_iommu_pgtable;
extern int amd_iommu_gpt_level;
@@ -37,33 +40,32 @@ extern int amd_iommu_gpt_level;
/* IOMMUv2 specific functions */
struct iommu_domain;
-extern bool amd_iommu_v2_supported(void);
-extern struct amd_iommu *get_amd_iommu(unsigned int idx);
-extern u8 amd_iommu_pc_get_max_banks(unsigned int idx);
-extern bool amd_iommu_pc_supported(void);
-extern u8 amd_iommu_pc_get_max_counters(unsigned int idx);
-extern int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
- u8 fxn, u64 *value);
-extern int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
- u8 fxn, u64 *value);
-
-extern int amd_iommu_register_ppr_notifier(struct notifier_block *nb);
-extern int amd_iommu_unregister_ppr_notifier(struct notifier_block *nb);
-extern void amd_iommu_domain_direct_map(struct iommu_domain *dom);
-extern int amd_iommu_domain_enable_v2(struct iommu_domain *dom, int pasids);
-extern int amd_iommu_flush_page(struct iommu_domain *dom, u32 pasid,
- u64 address);
-extern void amd_iommu_update_and_flush_device_table(struct protection_domain *domain);
-extern void amd_iommu_domain_update(struct protection_domain *domain);
-extern void amd_iommu_domain_flush_complete(struct protection_domain *domain);
-extern void amd_iommu_domain_flush_tlb_pde(struct protection_domain *domain);
-extern int amd_iommu_flush_tlb(struct iommu_domain *dom, u32 pasid);
-extern int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, u32 pasid,
- unsigned long cr3);
-extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, u32 pasid);
+bool amd_iommu_v2_supported(void);
+struct amd_iommu *get_amd_iommu(unsigned int idx);
+u8 amd_iommu_pc_get_max_banks(unsigned int idx);
+bool amd_iommu_pc_supported(void);
+u8 amd_iommu_pc_get_max_counters(unsigned int idx);
+int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
+ u8 fxn, u64 *value);
+int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
+ u8 fxn, u64 *value);
+
+int amd_iommu_register_ppr_notifier(struct notifier_block *nb);
+int amd_iommu_unregister_ppr_notifier(struct notifier_block *nb);
+void amd_iommu_domain_direct_map(struct iommu_domain *dom);
+int amd_iommu_domain_enable_v2(struct iommu_domain *dom, int pasids);
+int amd_iommu_flush_page(struct iommu_domain *dom, u32 pasid, u64 address);
+void amd_iommu_update_and_flush_device_table(struct protection_domain *domain);
+void amd_iommu_domain_update(struct protection_domain *domain);
+void amd_iommu_domain_flush_complete(struct protection_domain *domain);
+void amd_iommu_domain_flush_tlb_pde(struct protection_domain *domain);
+int amd_iommu_flush_tlb(struct iommu_domain *dom, u32 pasid);
+int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, u32 pasid,
+ unsigned long cr3);
+int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, u32 pasid);
#ifdef CONFIG_IRQ_REMAP
-extern int amd_iommu_create_irq_domain(struct amd_iommu *iommu);
+int amd_iommu_create_irq_domain(struct amd_iommu *iommu);
#else
static inline int amd_iommu_create_irq_domain(struct amd_iommu *iommu)
{
@@ -75,8 +77,8 @@ static inline int amd_iommu_create_irq_domain(struct amd_iommu *iommu)
#define PPR_INVALID 0x1
#define PPR_FAILURE 0xf
-extern int amd_iommu_complete_ppr(struct pci_dev *pdev, u32 pasid,
- int status, int tag);
+int amd_iommu_complete_ppr(struct pci_dev *pdev, u32 pasid,
+ int status, int tag);
static inline bool is_rd890_iommu(struct pci_dev *pdev)
{
@@ -129,10 +131,9 @@ static inline void *alloc_pgtable_page(int nid, gfp_t gfp)
return page ? page_address(page) : NULL;
}
-extern bool translation_pre_enabled(struct amd_iommu *iommu);
-extern bool amd_iommu_is_attach_deferred(struct device *dev);
-extern int __init add_special_device(u8 type, u8 id, u32 *devid,
- bool cmd_line);
+bool translation_pre_enabled(struct amd_iommu *iommu);
+bool amd_iommu_is_attach_deferred(struct device *dev);
+int __init add_special_device(u8 type, u8 id, u32 *devid, bool cmd_line);
#ifdef CONFIG_DMI
void amd_iommu_apply_ivrs_quirks(void);
@@ -140,9 +141,9 @@ void amd_iommu_apply_ivrs_quirks(void);
static inline void amd_iommu_apply_ivrs_quirks(void) { }
#endif
-extern void amd_iommu_domain_set_pgtable(struct protection_domain *domain,
- u64 *root, int mode);
-extern struct dev_table_entry *get_dev_table(struct amd_iommu *iommu);
+void amd_iommu_domain_set_pgtable(struct protection_domain *domain,
+ u64 *root, int mode);
+struct dev_table_entry *get_dev_table(struct amd_iommu *iommu);
extern u64 amd_iommu_efr;
extern u64 amd_iommu_efr2;
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index ab8aa8f77cc4..dc1db6167927 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -84,21 +84,21 @@
/* Extended Feature Bits */
-#define FEATURE_PREFETCH (1ULL<<0)
-#define FEATURE_PPR (1ULL<<1)
-#define FEATURE_X2APIC (1ULL<<2)
-#define FEATURE_NX (1ULL<<3)
-#define FEATURE_GT (1ULL<<4)
-#define FEATURE_IA (1ULL<<6)
-#define FEATURE_GA (1ULL<<7)
-#define FEATURE_HE (1ULL<<8)
-#define FEATURE_PC (1ULL<<9)
+#define FEATURE_PREFETCH BIT_ULL(0)
+#define FEATURE_PPR BIT_ULL(1)
+#define FEATURE_X2APIC BIT_ULL(2)
+#define FEATURE_NX BIT_ULL(3)
+#define FEATURE_GT BIT_ULL(4)
+#define FEATURE_IA BIT_ULL(6)
+#define FEATURE_GA BIT_ULL(7)
+#define FEATURE_HE BIT_ULL(8)
+#define FEATURE_PC BIT_ULL(9)
#define FEATURE_GATS_SHIFT (12)
#define FEATURE_GATS_MASK (3ULL)
-#define FEATURE_GAM_VAPIC (1ULL<<21)
-#define FEATURE_GIOSUP (1ULL<<48)
-#define FEATURE_EPHSUP (1ULL<<50)
-#define FEATURE_SNP (1ULL<<63)
+#define FEATURE_GAM_VAPIC BIT_ULL(21)
+#define FEATURE_GIOSUP BIT_ULL(48)
+#define FEATURE_EPHSUP BIT_ULL(50)
+#define FEATURE_SNP BIT_ULL(63)
#define FEATURE_PASID_SHIFT 32
#define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT)
@@ -120,13 +120,13 @@
#define PASID_MASK 0x0000ffff
/* MMIO status bits */
-#define MMIO_STATUS_EVT_OVERFLOW_INT_MASK (1 << 0)
-#define MMIO_STATUS_EVT_INT_MASK (1 << 1)
-#define MMIO_STATUS_COM_WAIT_INT_MASK (1 << 2)
-#define MMIO_STATUS_PPR_INT_MASK (1 << 6)
-#define MMIO_STATUS_GALOG_RUN_MASK (1 << 8)
-#define MMIO_STATUS_GALOG_OVERFLOW_MASK (1 << 9)
-#define MMIO_STATUS_GALOG_INT_MASK (1 << 10)
+#define MMIO_STATUS_EVT_OVERFLOW_INT_MASK BIT(0)
+#define MMIO_STATUS_EVT_INT_MASK BIT(1)
+#define MMIO_STATUS_COM_WAIT_INT_MASK BIT(2)
+#define MMIO_STATUS_PPR_INT_MASK BIT(6)
+#define MMIO_STATUS_GALOG_RUN_MASK BIT(8)
+#define MMIO_STATUS_GALOG_OVERFLOW_MASK BIT(9)
+#define MMIO_STATUS_GALOG_INT_MASK BIT(10)
/* event logging constants */
#define EVENT_ENTRY_SIZE 0x10
@@ -174,6 +174,7 @@
#define CONTROL_GAINT_EN 29
#define CONTROL_XT_EN 50
#define CONTROL_INTCAPXT_EN 51
+#define CONTROL_IRTCACHEDIS 59
#define CONTROL_SNPAVIC_EN 61
#define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT)
@@ -283,7 +284,7 @@
#define AMD_IOMMU_PGSIZES_V2 (PAGE_SIZE | (1ULL << 21) | (1ULL << 30))
/* Bit value definition for dte irq remapping fields*/
-#define DTE_IRQ_PHYS_ADDR_MASK (((1ULL << 45)-1) << 6)
+#define DTE_IRQ_PHYS_ADDR_MASK GENMASK_ULL(51, 6)
#define DTE_IRQ_REMAP_INTCTL_MASK (0x3ULL << 60)
#define DTE_IRQ_REMAP_INTCTL (2ULL << 60)
#define DTE_IRQ_REMAP_ENABLE 1ULL
@@ -369,23 +370,23 @@
/*
* Bit value definition for I/O PTE fields
*/
-#define IOMMU_PTE_PR (1ULL << 0)
-#define IOMMU_PTE_U (1ULL << 59)
-#define IOMMU_PTE_FC (1ULL << 60)
-#define IOMMU_PTE_IR (1ULL << 61)
-#define IOMMU_PTE_IW (1ULL << 62)
+#define IOMMU_PTE_PR BIT_ULL(0)
+#define IOMMU_PTE_U BIT_ULL(59)
+#define IOMMU_PTE_FC BIT_ULL(60)
+#define IOMMU_PTE_IR BIT_ULL(61)
+#define IOMMU_PTE_IW BIT_ULL(62)
/*
* Bit value definition for DTE fields
*/
-#define DTE_FLAG_V (1ULL << 0)
-#define DTE_FLAG_TV (1ULL << 1)
-#define DTE_FLAG_IR (1ULL << 61)
-#define DTE_FLAG_IW (1ULL << 62)
-
-#define DTE_FLAG_IOTLB (1ULL << 32)
-#define DTE_FLAG_GIOV (1ULL << 54)
-#define DTE_FLAG_GV (1ULL << 55)
+#define DTE_FLAG_V BIT_ULL(0)
+#define DTE_FLAG_TV BIT_ULL(1)
+#define DTE_FLAG_IR BIT_ULL(61)
+#define DTE_FLAG_IW BIT_ULL(62)
+
+#define DTE_FLAG_IOTLB BIT_ULL(32)
+#define DTE_FLAG_GIOV BIT_ULL(54)
+#define DTE_FLAG_GV BIT_ULL(55)
#define DTE_FLAG_MASK (0x3ffULL << 32)
#define DTE_GLX_SHIFT (56)
#define DTE_GLX_MASK (3)
@@ -439,13 +440,13 @@
#define MAX_DOMAIN_ID 65536
/* Protection domain flags */
-#define PD_DMA_OPS_MASK (1UL << 0) /* domain used for dma_ops */
-#define PD_DEFAULT_MASK (1UL << 1) /* domain is a default dma_ops
+#define PD_DMA_OPS_MASK BIT(0) /* domain used for dma_ops */
+#define PD_DEFAULT_MASK BIT(1) /* domain is a default dma_ops
domain for an IOMMU */
-#define PD_PASSTHROUGH_MASK (1UL << 2) /* domain has no page
+#define PD_PASSTHROUGH_MASK BIT(2) /* domain has no page
translation */
-#define PD_IOMMUV2_MASK (1UL << 3) /* domain has gcr3 table */
-#define PD_GIOV_MASK (1UL << 4) /* domain enable GIOV support */
+#define PD_IOMMUV2_MASK BIT(3) /* domain has gcr3 table */
+#define PD_GIOV_MASK BIT(4) /* domain enable GIOV support */
extern bool amd_iommu_dump;
#define DUMP_printk(format, arg...) \
@@ -716,6 +717,9 @@ struct amd_iommu {
/* if one, we need to send a completion wait command */
bool need_sync;
+ /* true if disable irte caching */
+ bool irtcachedis_enabled;
+
/* Handle for IOMMU core code */
struct iommu_device iommu;
@@ -748,7 +752,7 @@ struct amd_iommu {
u32 flags;
volatile u64 *cmd_sem;
- u64 cmd_sem_val;
+ atomic64_t cmd_sem_val;
#ifdef CONFIG_AMD_IOMMU_DEBUGFS
/* DebugFS Info */
@@ -882,7 +886,7 @@ extern int amd_iommu_max_glx_val;
* This function flushes all internal caches of
* the IOMMU used by this driver.
*/
-extern void iommu_flush_all_caches(struct amd_iommu *iommu);
+void iommu_flush_all_caches(struct amd_iommu *iommu);
static inline int get_ioapic_devid(int id)
{
@@ -1006,7 +1010,6 @@ struct amd_ir_data {
struct irq_2_irte irq_2_irte;
struct msi_msg msi_entry;
void *entry; /* Pointer to union irte or struct irte_ga */
- void *ref; /* Pointer to the actual irte */
/**
* Store information for activate/de-activate
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index c2d80a4e5fb0..ea0f1ab94178 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -162,6 +162,7 @@ static int amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
static bool amd_iommu_detected;
static bool amd_iommu_disabled __initdata;
static bool amd_iommu_force_enable __initdata;
+static bool amd_iommu_irtcachedis;
static int amd_iommu_target_ivhd_type;
/* Global EFR and EFR2 registers */
@@ -484,6 +485,9 @@ static void iommu_disable(struct amd_iommu *iommu)
/* Disable IOMMU hardware itself */
iommu_feature_disable(iommu, CONTROL_IOMMU_EN);
+
+ /* Clear IRTE cache disabling bit */
+ iommu_feature_disable(iommu, CONTROL_IRTCACHEDIS);
}
/*
@@ -1753,7 +1757,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h,
iommu->pci_seg = pci_seg;
raw_spin_lock_init(&iommu->lock);
- iommu->cmd_sem_val = 0;
+ atomic64_set(&iommu->cmd_sem_val, 0);
/* Add IOMMU to internal data structures */
list_add_tail(&iommu->list, &amd_iommu_list);
@@ -2710,6 +2714,33 @@ static void iommu_enable_ga(struct amd_iommu *iommu)
#endif
}
+static void iommu_disable_irtcachedis(struct amd_iommu *iommu)
+{
+ iommu_feature_disable(iommu, CONTROL_IRTCACHEDIS);
+}
+
+static void iommu_enable_irtcachedis(struct amd_iommu *iommu)
+{
+ u64 ctrl;
+
+ if (!amd_iommu_irtcachedis)
+ return;
+
+ /*
+ * Note:
+ * The support for IRTCacheDis feature is dertermined by
+ * checking if the bit is writable.
+ */
+ iommu_feature_enable(iommu, CONTROL_IRTCACHEDIS);
+ ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
+ ctrl &= (1ULL << CONTROL_IRTCACHEDIS);
+ if (ctrl)
+ iommu->irtcachedis_enabled = true;
+ pr_info("iommu%d (%#06x) : IRT cache is %s\n",
+ iommu->index, iommu->devid,
+ iommu->irtcachedis_enabled ? "disabled" : "enabled");
+}
+
static void early_enable_iommu(struct amd_iommu *iommu)
{
iommu_disable(iommu);
@@ -2720,6 +2751,7 @@ static void early_enable_iommu(struct amd_iommu *iommu)
iommu_set_exclusion_range(iommu);
iommu_enable_ga(iommu);
iommu_enable_xt(iommu);
+ iommu_enable_irtcachedis(iommu);
iommu_enable(iommu);
iommu_flush_all_caches(iommu);
}
@@ -2770,10 +2802,12 @@ static void early_enable_iommus(void)
for_each_iommu(iommu) {
iommu_disable_command_buffer(iommu);
iommu_disable_event_buffer(iommu);
+ iommu_disable_irtcachedis(iommu);
iommu_enable_command_buffer(iommu);
iommu_enable_event_buffer(iommu);
iommu_enable_ga(iommu);
iommu_enable_xt(iommu);
+ iommu_enable_irtcachedis(iommu);
iommu_set_device_table(iommu);
iommu_flush_all_caches(iommu);
}
@@ -3426,6 +3460,8 @@ static int __init parse_amd_iommu_options(char *str)
amd_iommu_pgtable = AMD_IOMMU_V1;
} else if (strncmp(str, "pgtbl_v2", 8) == 0) {
amd_iommu_pgtable = AMD_IOMMU_V2;
+ } else if (strncmp(str, "irtcachedis", 11) == 0) {
+ amd_iommu_irtcachedis = true;
} else {
pr_notice("Unknown option - '%s'\n", str);
}
diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
index 1b67116882be..2892aa1b4dc1 100644
--- a/drivers/iommu/amd/io_pgtable.c
+++ b/drivers/iommu/amd/io_pgtable.c
@@ -310,8 +310,8 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
return NULL;
/* Large PTE */
- if (PM_PTE_LEVEL(*pte) == 7 ||
- PM_PTE_LEVEL(*pte) == 0)
+ if (PM_PTE_LEVEL(*pte) == PAGE_MODE_7_LEVEL ||
+ PM_PTE_LEVEL(*pte) == PAGE_MODE_NONE)
break;
/* No level skipping support yet */
diff --git a/drivers/iommu/amd/io_pgtable_v2.c b/drivers/iommu/amd/io_pgtable_v2.c
index 27c3015947e6..e9ef2e0a62f6 100644
--- a/drivers/iommu/amd/io_pgtable_v2.c
+++ b/drivers/iommu/amd/io_pgtable_v2.c
@@ -2,7 +2,7 @@
/*
* CPU-agnostic AMD IO page table v2 allocator.
*
- * Copyright (C) 2022 Advanced Micro Devices, Inc.
+ * Copyright (C) 2022, 2023 Advanced Micro Devices, Inc.
* Author: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
* Author: Vasant Hegde <vasant.hegde@amd.com>
*/
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 9ea40960978b..c3b58a8389b9 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -1182,11 +1182,11 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
if (!iommu->need_sync)
return 0;
- raw_spin_lock_irqsave(&iommu->lock, flags);
-
- data = ++iommu->cmd_sem_val;
+ data = atomic64_add_return(1, &iommu->cmd_sem_val);
build_completion_wait(&cmd, iommu, data);
+ raw_spin_lock_irqsave(&iommu->lock, flags);
+
ret = __iommu_queue_command_sync(iommu, &cmd, false);
if (ret)
goto out_unlock;
@@ -1273,6 +1273,9 @@ static void amd_iommu_flush_irt_all(struct amd_iommu *iommu)
u32 devid;
u16 last_bdf = iommu->pci_seg->last_bdf;
+ if (iommu->irtcachedis_enabled)
+ return;
+
for (devid = 0; devid <= last_bdf; devid++)
iommu_flush_irt(iommu, devid);
@@ -2313,6 +2316,8 @@ static bool amd_iommu_capable(struct device *dev, enum iommu_cap cap)
return amdr_ivrs_remap_support;
case IOMMU_CAP_ENFORCE_CACHE_COHERENCY:
return true;
+ case IOMMU_CAP_DEFERRED_FLUSH:
+ return true;
default:
break;
}
@@ -2822,6 +2827,32 @@ EXPORT_SYMBOL(amd_iommu_device_info);
static struct irq_chip amd_ir_chip;
static DEFINE_SPINLOCK(iommu_table_lock);
+static void iommu_flush_irt_and_complete(struct amd_iommu *iommu, u16 devid)
+{
+ int ret;
+ u64 data;
+ unsigned long flags;
+ struct iommu_cmd cmd, cmd2;
+
+ if (iommu->irtcachedis_enabled)
+ return;
+
+ build_inv_irt(&cmd, devid);
+ data = atomic64_add_return(1, &iommu->cmd_sem_val);
+ build_completion_wait(&cmd2, iommu, data);
+
+ raw_spin_lock_irqsave(&iommu->lock, flags);
+ ret = __iommu_queue_command_sync(iommu, &cmd, true);
+ if (ret)
+ goto out;
+ ret = __iommu_queue_command_sync(iommu, &cmd2, false);
+ if (ret)
+ goto out;
+ wait_on_sem(iommu, data);
+out:
+ raw_spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
static void set_dte_irq_entry(struct amd_iommu *iommu, u16 devid,
struct irq_remap_table *table)
{
@@ -3021,7 +3052,7 @@ out:
}
static int modify_irte_ga(struct amd_iommu *iommu, u16 devid, int index,
- struct irte_ga *irte, struct amd_ir_data *data)
+ struct irte_ga *irte)
{
struct irq_remap_table *table;
struct irte_ga *entry;
@@ -3046,13 +3077,9 @@ static int modify_irte_ga(struct amd_iommu *iommu, u16 devid, int index,
old = entry->irte;
WARN_ON(!try_cmpxchg128(&entry->irte, &old, irte->irte));
- if (data)
- data->ref = entry;
-
raw_spin_unlock_irqrestore(&table->lock, flags);
- iommu_flush_irt(iommu, devid);
- iommu_completion_wait(iommu);
+ iommu_flush_irt_and_complete(iommu, devid);
return 0;
}
@@ -3071,8 +3098,7 @@ static int modify_irte(struct amd_iommu *iommu,
table->table[index] = irte->val;
raw_spin_unlock_irqrestore(&table->lock, flags);
- iommu_flush_irt(iommu, devid);
- iommu_completion_wait(iommu);
+ iommu_flush_irt_and_complete(iommu, devid);
return 0;
}
@@ -3090,8 +3116,7 @@ static void free_irte(struct amd_iommu *iommu, u16 devid, int index)
iommu->irte_ops->clear_allocated(table, index);
raw_spin_unlock_irqrestore(&table->lock, flags);
- iommu_flush_irt(iommu, devid);
- iommu_completion_wait(iommu);
+ iommu_flush_irt_and_complete(iommu, devid);
}
static void irte_prepare(void *entry,
@@ -3137,7 +3162,7 @@ static void irte_ga_activate(struct amd_iommu *iommu, void *entry, u16 devid, u1
struct irte_ga *irte = (struct irte_ga *) entry;
irte->lo.fields_remap.valid = 1;
- modify_irte_ga(iommu, devid, index, irte, NULL);
+ modify_irte_ga(iommu, devid, index, irte);
}
static void irte_deactivate(struct amd_iommu *iommu, void *entry, u16 devid, u16 index)
@@ -3153,7 +3178,7 @@ static void irte_ga_deactivate(struct amd_iommu *iommu, void *entry, u16 devid,
struct irte_ga *irte = (struct irte_ga *) entry;
irte->lo.fields_remap.valid = 0;
- modify_irte_ga(iommu, devid, index, irte, NULL);
+ modify_irte_ga(iommu, devid, index, irte);
}
static void irte_set_affinity(struct amd_iommu *iommu, void *entry, u16 devid, u16 index,
@@ -3177,7 +3202,7 @@ static void irte_ga_set_affinity(struct amd_iommu *iommu, void *entry, u16 devid
APICID_TO_IRTE_DEST_LO(dest_apicid);
irte->hi.fields.destination =
APICID_TO_IRTE_DEST_HI(dest_apicid);
- modify_irte_ga(iommu, devid, index, irte, NULL);
+ modify_irte_ga(iommu, devid, index, irte);
}
}
@@ -3527,7 +3552,7 @@ int amd_iommu_activate_guest_mode(void *data)
entry->lo.fields_vapic.ga_tag = ir_data->ga_tag;
return modify_irte_ga(ir_data->iommu, ir_data->irq_2_irte.devid,
- ir_data->irq_2_irte.index, entry, ir_data);
+ ir_data->irq_2_irte.index, entry);
}
EXPORT_SYMBOL(amd_iommu_activate_guest_mode);
@@ -3557,7 +3582,7 @@ int amd_iommu_deactivate_guest_mode(void *data)
APICID_TO_IRTE_DEST_HI(cfg->dest_apicid);
return modify_irte_ga(ir_data->iommu, ir_data->irq_2_irte.devid,
- ir_data->irq_2_irte.index, entry, ir_data);
+ ir_data->irq_2_irte.index, entry);
}
EXPORT_SYMBOL(amd_iommu_deactivate_guest_mode);
@@ -3719,44 +3744,26 @@ int amd_iommu_create_irq_domain(struct amd_iommu *iommu)
int amd_iommu_update_ga(int cpu, bool is_run, void *data)
{
- unsigned long flags;
- struct amd_iommu *iommu;
- struct irq_remap_table *table;
struct amd_ir_data *ir_data = (struct amd_ir_data *)data;
- int devid = ir_data->irq_2_irte.devid;
struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
- struct irte_ga *ref = (struct irte_ga *) ir_data->ref;
if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) ||
- !ref || !entry || !entry->lo.fields_vapic.guest_mode)
+ !entry || !entry->lo.fields_vapic.guest_mode)
return 0;
- iommu = ir_data->iommu;
- if (!iommu)
+ if (!ir_data->iommu)
return -ENODEV;
- table = get_irq_table(iommu, devid);
- if (!table)
- return -ENODEV;
-
- raw_spin_lock_irqsave(&table->lock, flags);
-
- if (ref->lo.fields_vapic.guest_mode) {
- if (cpu >= 0) {
- ref->lo.fields_vapic.destination =
- APICID_TO_IRTE_DEST_LO(cpu);
- ref->hi.fields.destination =
- APICID_TO_IRTE_DEST_HI(cpu);
- }
- ref->lo.fields_vapic.is_run = is_run;
- barrier();
+ if (cpu >= 0) {
+ entry->lo.fields_vapic.destination =
+ APICID_TO_IRTE_DEST_LO(cpu);
+ entry->hi.fields.destination =
+ APICID_TO_IRTE_DEST_HI(cpu);
}
+ entry->lo.fields_vapic.is_run = is_run;
- raw_spin_unlock_irqrestore(&table->lock, flags);
-
- iommu_flush_irt(iommu, devid);
- iommu_completion_wait(iommu);
- return 0;
+ return modify_irte_ga(ir_data->iommu, ir_data->irq_2_irte.devid,
+ ir_data->irq_2_irte.index, entry);
}
EXPORT_SYMBOL(amd_iommu_update_ga);
#endif
diff --git a/drivers/iommu/amd/iommu_v2.c b/drivers/iommu/amd/iommu_v2.c
index 864e4ffb6aa9..261352a23271 100644
--- a/drivers/iommu/amd/iommu_v2.c
+++ b/drivers/iommu/amd/iommu_v2.c
@@ -485,8 +485,8 @@ static void do_fault(struct work_struct *work)
flags |= FAULT_FLAG_REMOTE;
mmap_read_lock(mm);
- vma = find_extend_vma(mm, address);
- if (!vma || address < vma->vm_start)
+ vma = vma_lookup(mm, address);
+ if (!vma)
/* failed to get a vma in the right range */
goto out;
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 3fd83fb75722..9b0dc3505601 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -894,6 +894,12 @@ static void arm_smmu_cmdq_batch_add(struct arm_smmu_device *smmu,
{
int index;
+ if (cmds->num == CMDQ_BATCH_ENTRIES - 1 &&
+ (smmu->options & ARM_SMMU_OPT_CMDQ_FORCE_SYNC)) {
+ arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, true);
+ cmds->num = 0;
+ }
+
if (cmds->num == CMDQ_BATCH_ENTRIES) {
arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, false);
cmds->num = 0;
@@ -1892,8 +1898,13 @@ static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd,
/* Convert page size of 12,14,16 (log2) to 1,2,3 */
cmd->tlbi.tg = (tg - 10) / 2;
- /* Determine what level the granule is at */
- cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3));
+ /*
+ * Determine what level the granule is at. For non-leaf, io-pgtable
+ * assumes .tlb_flush_walk can invalidate multiple levels at once,
+ * so ignore the nominal last-level granule and leave TTL=0.
+ */
+ if (cmd->tlbi.leaf)
+ cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3));
num_pages = size >> tg;
}
@@ -2008,6 +2019,7 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
/* Assume that a coherent TCU implies coherent TBUs */
return master->smmu->features & ARM_SMMU_FEAT_COHERENCY;
case IOMMU_CAP_NOEXEC:
+ case IOMMU_CAP_DEFERRED_FLUSH:
return true;
default:
return false;
@@ -2023,7 +2035,6 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
if (type != IOMMU_DOMAIN_UNMANAGED &&
type != IOMMU_DOMAIN_DMA &&
- type != IOMMU_DOMAIN_DMA_FQ &&
type != IOMMU_DOMAIN_IDENTITY)
return NULL;
@@ -3429,6 +3440,44 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
return 0;
}
+#define IIDR_IMPLEMENTER_ARM 0x43b
+#define IIDR_PRODUCTID_ARM_MMU_600 0x483
+#define IIDR_PRODUCTID_ARM_MMU_700 0x487
+
+static void arm_smmu_device_iidr_probe(struct arm_smmu_device *smmu)
+{
+ u32 reg;
+ unsigned int implementer, productid, variant, revision;
+
+ reg = readl_relaxed(smmu->base + ARM_SMMU_IIDR);
+ implementer = FIELD_GET(IIDR_IMPLEMENTER, reg);
+ productid = FIELD_GET(IIDR_PRODUCTID, reg);
+ variant = FIELD_GET(IIDR_VARIANT, reg);
+ revision = FIELD_GET(IIDR_REVISION, reg);
+
+ switch (implementer) {
+ case IIDR_IMPLEMENTER_ARM:
+ switch (productid) {
+ case IIDR_PRODUCTID_ARM_MMU_600:
+ /* Arm erratum 1076982 */
+ if (variant == 0 && revision <= 2)
+ smmu->features &= ~ARM_SMMU_FEAT_SEV;
+ /* Arm erratum 1209401 */
+ if (variant < 2)
+ smmu->features &= ~ARM_SMMU_FEAT_NESTING;
+ break;
+ case IIDR_PRODUCTID_ARM_MMU_700:
+ /* Arm erratum 2812531 */
+ smmu->features &= ~ARM_SMMU_FEAT_BTM;
+ smmu->options |= ARM_SMMU_OPT_CMDQ_FORCE_SYNC;
+ /* Arm errata 2268618, 2812531 */
+ smmu->features &= ~ARM_SMMU_FEAT_NESTING;
+ break;
+ }
+ break;
+ }
+}
+
static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
{
u32 reg;
@@ -3635,6 +3684,12 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
smmu->ias = max(smmu->ias, smmu->oas);
+ if ((smmu->features & ARM_SMMU_FEAT_TRANS_S1) &&
+ (smmu->features & ARM_SMMU_FEAT_TRANS_S2))
+ smmu->features |= ARM_SMMU_FEAT_NESTING;
+
+ arm_smmu_device_iidr_probe(smmu);
+
if (arm_smmu_sva_supported(smmu))
smmu->features |= ARM_SMMU_FEAT_SVA;
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index b574c58a3487..dcab85698a4e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -69,6 +69,12 @@
#define IDR5_VAX GENMASK(11, 10)
#define IDR5_VAX_52_BIT 1
+#define ARM_SMMU_IIDR 0x18
+#define IIDR_PRODUCTID GENMASK(31, 20)
+#define IIDR_VARIANT GENMASK(19, 16)
+#define IIDR_REVISION GENMASK(15, 12)
+#define IIDR_IMPLEMENTER GENMASK(11, 0)
+
#define ARM_SMMU_CR0 0x20
#define CR0_ATSCHK (1 << 4)
#define CR0_CMDQEN (1 << 3)
@@ -639,11 +645,13 @@ struct arm_smmu_device {
#define ARM_SMMU_FEAT_BTM (1 << 16)
#define ARM_SMMU_FEAT_SVA (1 << 17)
#define ARM_SMMU_FEAT_E2H (1 << 18)
+#define ARM_SMMU_FEAT_NESTING (1 << 19)
u32 features;
#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
#define ARM_SMMU_OPT_PAGE0_REGS_ONLY (1 << 1)
#define ARM_SMMU_OPT_MSIPOLL (1 << 2)
+#define ARM_SMMU_OPT_CMDQ_FORCE_SYNC (1 << 3)
u32 options;
struct arm_smmu_cmdq cmdq;
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 6e0813b26fb6..a86acd76c1df 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -856,8 +856,7 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
struct arm_smmu_domain *smmu_domain;
if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_IDENTITY) {
- if (using_legacy_binding ||
- (type != IOMMU_DOMAIN_DMA && type != IOMMU_DOMAIN_DMA_FQ))
+ if (using_legacy_binding || type != IOMMU_DOMAIN_DMA)
return NULL;
}
/*
@@ -1325,6 +1324,7 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
return cfg->smmu->features & ARM_SMMU_FEAT_COHERENT_WALK ||
device_get_dma_attr(dev) == DEV_DMA_COHERENT;
case IOMMU_CAP_NOEXEC:
+ case IOMMU_CAP_DEFERRED_FLUSH:
return true;
default:
return false;
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index e86ae462cade..e57724163835 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -615,7 +615,8 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
goto done_unlock;
/* If the FQ fails we can simply fall back to strict mode */
- if (domain->type == IOMMU_DOMAIN_DMA_FQ && iommu_dma_init_fq(domain))
+ if (domain->type == IOMMU_DOMAIN_DMA_FQ &&
+ (!device_iommu_capable(dev, IOMMU_CAP_DEFERRED_FLUSH) || iommu_dma_init_fq(domain)))
domain->type = IOMMU_DOMAIN_DMA;
ret = iova_reserve_iommu_regions(dev, domain);
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index bce372297099..4ac0e247ec2b 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -334,17 +334,6 @@ int fsl_pamu_configure_l1_stash(struct iommu_domain *domain, u32 cpu)
return ret;
}
-static struct iommu_group *get_device_iommu_group(struct device *dev)
-{
- struct iommu_group *group;
-
- group = iommu_group_get(dev);
- if (!group)
- group = iommu_group_alloc();
-
- return group;
-}
-
static bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl)
{
u32 version;
@@ -356,94 +345,52 @@ static bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl)
return version >= 0x204;
}
-/* Get iommu group information from peer devices or devices on the parent bus */
-static struct iommu_group *get_shared_pci_device_group(struct pci_dev *pdev)
+static struct iommu_group *fsl_pamu_device_group(struct device *dev)
{
- struct pci_dev *tmp;
struct iommu_group *group;
- struct pci_bus *bus = pdev->bus;
+ struct pci_dev *pdev;
/*
- * Traverese the pci bus device list to get
- * the shared iommu group.
+ * For platform devices we allocate a separate group for each of the
+ * devices.
*/
- while (bus) {
- list_for_each_entry(tmp, &bus->devices, bus_list) {
- if (tmp == pdev)
- continue;
- group = iommu_group_get(&tmp->dev);
- if (group)
- return group;
- }
+ if (!dev_is_pci(dev))
+ return generic_device_group(dev);
- bus = bus->parent;
- }
-
- return NULL;
-}
-
-static struct iommu_group *get_pci_device_group(struct pci_dev *pdev)
-{
- struct pci_controller *pci_ctl;
- bool pci_endpt_partitioning;
- struct iommu_group *group = NULL;
-
- pci_ctl = pci_bus_to_host(pdev->bus);
- pci_endpt_partitioning = check_pci_ctl_endpt_part(pci_ctl);
- /* We can partition PCIe devices so assign device group to the device */
- if (pci_endpt_partitioning) {
- group = pci_device_group(&pdev->dev);
-
- /*
- * PCIe controller is not a paritionable entity
- * free the controller device iommu_group.
- */
- if (pci_ctl->parent->iommu_group)
- iommu_group_remove_device(pci_ctl->parent);
- } else {
- /*
- * All devices connected to the controller will share the
- * PCI controllers device group. If this is the first
- * device to be probed for the pci controller, copy the
- * device group information from the PCI controller device
- * node and remove the PCI controller iommu group.
- * For subsequent devices, the iommu group information can
- * be obtained from sibling devices (i.e. from the bus_devices
- * link list).
- */
- if (pci_ctl->parent->iommu_group) {
- group = get_device_iommu_group(pci_ctl->parent);
- iommu_group_remove_device(pci_ctl->parent);
- } else {
- group = get_shared_pci_device_group(pdev);
- }
- }
-
- if (!group)
- group = ERR_PTR(-ENODEV);
+ /*
+ * We can partition PCIe devices so assign device group to the device
+ */
+ pdev = to_pci_dev(dev);
+ if (check_pci_ctl_endpt_part(pci_bus_to_host(pdev->bus)))
+ return pci_device_group(&pdev->dev);
+ /*
+ * All devices connected to the controller will share the same device
+ * group.
+ *
+ * Due to ordering between fsl_pamu_init() and fsl_pci_init() it is
+ * guaranteed that the pci_ctl->parent platform_device will have the
+ * iommu driver bound and will already have a group set. So we just
+ * re-use this group as the group for every device in the hose.
+ */
+ group = iommu_group_get(pci_bus_to_host(pdev->bus)->parent);
+ if (WARN_ON(!group))
+ return ERR_PTR(-EINVAL);
return group;
}
-static struct iommu_group *fsl_pamu_device_group(struct device *dev)
+static struct iommu_device *fsl_pamu_probe_device(struct device *dev)
{
- struct iommu_group *group = ERR_PTR(-ENODEV);
int len;
/*
- * For platform devices we allocate a separate group for
- * each of the devices.
+ * uboot must fill the fsl,liodn for platform devices to be supported by
+ * the iommu.
*/
- if (dev_is_pci(dev))
- group = get_pci_device_group(to_pci_dev(dev));
- else if (of_get_property(dev->of_node, "fsl,liodn", &len))
- group = get_device_iommu_group(dev);
-
- return group;
-}
+ if (!dev_is_pci(dev) &&
+ !of_get_property(dev->of_node, "fsl,liodn", &len))
+ return ERR_PTR(-ENODEV);
-static struct iommu_device *fsl_pamu_probe_device(struct device *dev)
-{
return &pamu_iommu;
}
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index b871a6afd803..5c8c5cdc36cf 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -1185,7 +1185,7 @@ static int iommu_alloc_root_entry(struct intel_iommu *iommu)
{
struct root_entry *root;
- root = (struct root_entry *)alloc_pgtable_page(iommu->node, GFP_ATOMIC);
+ root = alloc_pgtable_page(iommu->node, GFP_ATOMIC);
if (!root) {
pr_err("Allocating root entry for %s failed\n",
iommu->name);
@@ -1312,15 +1312,7 @@ static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
iommu->name, type);
return;
}
- /* Note: set drain read/write */
-#if 0
- /*
- * This is probably to be super secure.. Looks like we can
- * ignore it without any impact.
- */
- if (cap_read_drain(iommu->cap))
- val |= DMA_TLB_READ_DRAIN;
-#endif
+
if (cap_write_drain(iommu->cap))
val |= DMA_TLB_WRITE_DRAIN;
@@ -1897,8 +1889,6 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
struct context_entry *context;
int ret;
- WARN_ON(did == 0);
-
if (hw_pass_through && domain_type_is_si(domain))
translation = CONTEXT_TT_PASS_THROUGH;
@@ -1944,8 +1934,6 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
if (sm_supported(iommu)) {
unsigned long pds;
- WARN_ON(!table);
-
/* Setup the PASID DIR pointer: */
pds = context_get_sm_pds(table);
context->lo = (u64)virt_to_phys(table->table) |
@@ -2967,10 +2955,15 @@ static int init_iommu_hw(void)
{
struct dmar_drhd_unit *drhd;
struct intel_iommu *iommu = NULL;
+ int ret;
- for_each_active_iommu(iommu, drhd)
- if (iommu->qi)
- dmar_reenable_qi(iommu);
+ for_each_active_iommu(iommu, drhd) {
+ if (iommu->qi) {
+ ret = dmar_reenable_qi(iommu);
+ if (ret)
+ return ret;
+ }
+ }
for_each_iommu(iommu, drhd) {
if (drhd->ignored) {
@@ -4064,7 +4057,6 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
case IOMMU_DOMAIN_BLOCKED:
return &blocking_domain;
case IOMMU_DOMAIN_DMA:
- case IOMMU_DOMAIN_DMA_FQ:
case IOMMU_DOMAIN_UNMANAGED:
dmar_domain = alloc_domain(type);
if (!dmar_domain) {
@@ -4369,6 +4361,7 @@ static bool intel_iommu_capable(struct device *dev, enum iommu_cap cap)
switch (cap) {
case IOMMU_CAP_CACHE_COHERENCY:
+ case IOMMU_CAP_DEFERRED_FLUSH:
return true;
case IOMMU_CAP_PRE_BOOT_PROTECTION:
return dmar_platform_optin();
diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
index 9821bc44f5ac..3ebd4b6586b3 100644
--- a/drivers/iommu/iommu-sva.c
+++ b/drivers/iommu/iommu-sva.c
@@ -175,7 +175,7 @@ iommu_sva_handle_iopf(struct iommu_fault *fault, void *data)
mmap_read_lock(mm);
- vma = find_extend_vma(mm, prm->addr);
+ vma = vma_lookup(mm, prm->addr);
if (!vma)
/* Unmapped area */
goto out_put_mm;
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index eb620552967b..da340f11c5f5 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -68,6 +68,10 @@ struct group_device {
char *name;
};
+/* Iterate over each struct group_device in a struct iommu_group */
+#define for_each_group_device(group, pos) \
+ list_for_each_entry(pos, &(group)->devices, list)
+
struct iommu_group_attribute {
struct attribute attr;
ssize_t (*show)(struct iommu_group *group, char *buf);
@@ -89,17 +93,39 @@ static const char * const iommu_group_resv_type_string[] = {
static int iommu_bus_notifier(struct notifier_block *nb,
unsigned long action, void *data);
static void iommu_release_device(struct device *dev);
-static int iommu_alloc_default_domain(struct iommu_group *group,
- struct device *dev);
static struct iommu_domain *__iommu_domain_alloc(const struct bus_type *bus,
unsigned type);
static int __iommu_attach_device(struct iommu_domain *domain,
struct device *dev);
static int __iommu_attach_group(struct iommu_domain *domain,
struct iommu_group *group);
+
+enum {
+ IOMMU_SET_DOMAIN_MUST_SUCCEED = 1 << 0,
+};
+
+static int __iommu_device_set_domain(struct iommu_group *group,
+ struct device *dev,
+ struct iommu_domain *new_domain,
+ unsigned int flags);
+static int __iommu_group_set_domain_internal(struct iommu_group *group,
+ struct iommu_domain *new_domain,
+ unsigned int flags);
static int __iommu_group_set_domain(struct iommu_group *group,
- struct iommu_domain *new_domain);
-static int iommu_create_device_direct_mappings(struct iommu_group *group,
+ struct iommu_domain *new_domain)
+{
+ return __iommu_group_set_domain_internal(group, new_domain, 0);
+}
+static void __iommu_group_set_domain_nofail(struct iommu_group *group,
+ struct iommu_domain *new_domain)
+{
+ WARN_ON(__iommu_group_set_domain_internal(
+ group, new_domain, IOMMU_SET_DOMAIN_MUST_SUCCEED));
+}
+
+static int iommu_setup_default_domain(struct iommu_group *group,
+ int target_type);
+static int iommu_create_device_direct_mappings(struct iommu_domain *domain,
struct device *dev);
static struct iommu_group *iommu_group_get_for_dev(struct device *dev);
static ssize_t iommu_group_store_type(struct iommu_group *group,
@@ -176,16 +202,16 @@ static int __init iommu_subsys_init(void)
if (!iommu_default_passthrough() && !iommu_dma_strict)
iommu_def_domain_type = IOMMU_DOMAIN_DMA_FQ;
- pr_info("Default domain type: %s %s\n",
+ pr_info("Default domain type: %s%s\n",
iommu_domain_type_str(iommu_def_domain_type),
(iommu_cmd_line & IOMMU_CMD_LINE_DMA_API) ?
- "(set via kernel command line)" : "");
+ " (set via kernel command line)" : "");
if (!iommu_default_passthrough())
- pr_info("DMA domain TLB invalidation policy: %s mode %s\n",
+ pr_info("DMA domain TLB invalidation policy: %s mode%s\n",
iommu_dma_strict ? "strict" : "lazy",
(iommu_cmd_line & IOMMU_CMD_LINE_STRICT) ?
- "(set via kernel command line)" : "");
+ " (set via kernel command line)" : "");
nb = kcalloc(ARRAY_SIZE(iommu_buses), sizeof(*nb), GFP_KERNEL);
if (!nb)
@@ -343,6 +369,8 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
dev->iommu->iommu_dev = iommu_dev;
dev->iommu->max_pasids = dev_iommu_get_max_pasids(dev);
+ if (ops->is_attach_deferred)
+ dev->iommu->attach_deferred = ops->is_attach_deferred(dev);
group = iommu_group_get_for_dev(dev);
if (IS_ERR(group)) {
@@ -377,30 +405,6 @@ err_unlock:
return ret;
}
-static bool iommu_is_attach_deferred(struct device *dev)
-{
- const struct iommu_ops *ops = dev_iommu_ops(dev);
-
- if (ops->is_attach_deferred)
- return ops->is_attach_deferred(dev);
-
- return false;
-}
-
-static int iommu_group_do_dma_first_attach(struct device *dev, void *data)
-{
- struct iommu_domain *domain = data;
-
- lockdep_assert_held(&dev->iommu_group->mutex);
-
- if (iommu_is_attach_deferred(dev)) {
- dev->iommu->attach_deferred = 1;
- return 0;
- }
-
- return __iommu_attach_device(domain, dev);
-}
-
int iommu_probe_device(struct device *dev)
{
const struct iommu_ops *ops;
@@ -417,29 +421,20 @@ int iommu_probe_device(struct device *dev)
goto err_release;
}
- /*
- * Try to allocate a default domain - needs support from the
- * IOMMU driver. There are still some drivers which don't
- * support default domains, so the return value is not yet
- * checked.
- */
mutex_lock(&group->mutex);
- iommu_alloc_default_domain(group, dev);
- /*
- * If device joined an existing group which has been claimed, don't
- * attach the default domain.
- */
- if (group->default_domain && !group->owner) {
- ret = iommu_group_do_dma_first_attach(dev, group->default_domain);
- if (ret) {
- mutex_unlock(&group->mutex);
- iommu_group_put(group);
- goto err_release;
- }
- }
+ if (group->default_domain)
+ iommu_create_device_direct_mappings(group->default_domain, dev);
- iommu_create_device_direct_mappings(group, dev);
+ if (group->domain) {
+ ret = __iommu_device_set_domain(group, dev, group->domain, 0);
+ if (ret)
+ goto err_unlock;
+ } else if (!group->default_domain) {
+ ret = iommu_setup_default_domain(group, 0);
+ if (ret)
+ goto err_unlock;
+ }
mutex_unlock(&group->mutex);
iommu_group_put(group);
@@ -450,6 +445,9 @@ int iommu_probe_device(struct device *dev)
return 0;
+err_unlock:
+ mutex_unlock(&group->mutex);
+ iommu_group_put(group);
err_release:
iommu_release_device(dev);
@@ -468,7 +466,7 @@ __iommu_group_remove_device(struct iommu_group *group, struct device *dev)
struct group_device *device;
lockdep_assert_held(&group->mutex);
- list_for_each_entry(device, &group->devices, list) {
+ for_each_group_device(group, device) {
if (device->dev == dev) {
list_del(&device->list);
return device;
@@ -707,7 +705,7 @@ int iommu_get_group_resv_regions(struct iommu_group *group,
int ret = 0;
mutex_lock(&group->mutex);
- list_for_each_entry(device, &group->devices, list) {
+ for_each_group_device(group, device) {
struct list_head dev_resv_regions;
/*
@@ -953,16 +951,15 @@ int iommu_group_set_name(struct iommu_group *group, const char *name)
}
EXPORT_SYMBOL_GPL(iommu_group_set_name);
-static int iommu_create_device_direct_mappings(struct iommu_group *group,
+static int iommu_create_device_direct_mappings(struct iommu_domain *domain,
struct device *dev)
{
- struct iommu_domain *domain = group->default_domain;
struct iommu_resv_region *entry;
struct list_head mappings;
unsigned long pg_size;
int ret = 0;
- if (!domain || !iommu_is_dma_domain(domain))
+ if (!iommu_is_dma_domain(domain))
return 0;
BUG_ON(!domain->pgsize_bitmap);
@@ -1069,25 +1066,13 @@ rename:
mutex_lock(&group->mutex);
list_add_tail(&device->list, &group->devices);
- if (group->domain)
- ret = iommu_group_do_dma_first_attach(dev, group->domain);
mutex_unlock(&group->mutex);
- if (ret)
- goto err_put_group;
-
trace_add_device_to_group(group->id, dev);
dev_info(dev, "Adding to iommu group %d\n", group->id);
return 0;
-err_put_group:
- mutex_lock(&group->mutex);
- list_del(&device->list);
- mutex_unlock(&group->mutex);
- dev->iommu_group = NULL;
- kobject_put(group->devices_kobj);
- sysfs_remove_link(group->devices_kobj, device->name);
err_free_name:
kfree(device->name);
err_remove_link:
@@ -1125,31 +1110,6 @@ void iommu_group_remove_device(struct device *dev)
}
EXPORT_SYMBOL_GPL(iommu_group_remove_device);
-static int iommu_group_device_count(struct iommu_group *group)
-{
- struct group_device *entry;
- int ret = 0;
-
- list_for_each_entry(entry, &group->devices, list)
- ret++;
-
- return ret;
-}
-
-static int __iommu_group_for_each_dev(struct iommu_group *group, void *data,
- int (*fn)(struct device *, void *))
-{
- struct group_device *device;
- int ret = 0;
-
- list_for_each_entry(device, &group->devices, list) {
- ret = fn(device->dev, data);
- if (ret)
- break;
- }
- return ret;
-}
-
/**
* iommu_group_for_each_dev - iterate over each device in the group
* @group: the group
@@ -1164,10 +1124,15 @@ static int __iommu_group_for_each_dev(struct iommu_group *group, void *data,
int iommu_group_for_each_dev(struct iommu_group *group, void *data,
int (*fn)(struct device *, void *))
{
- int ret;
+ struct group_device *device;
+ int ret = 0;
mutex_lock(&group->mutex);
- ret = __iommu_group_for_each_dev(group, data, fn);
+ for_each_group_device(group, device) {
+ ret = fn(device->dev, data);
+ if (ret)
+ break;
+ }
mutex_unlock(&group->mutex);
return ret;
@@ -1656,40 +1621,47 @@ static int iommu_get_def_domain_type(struct device *dev)
return 0;
}
-static int iommu_group_alloc_default_domain(const struct bus_type *bus,
- struct iommu_group *group,
- unsigned int type)
+static struct iommu_domain *
+__iommu_group_alloc_default_domain(const struct bus_type *bus,
+ struct iommu_group *group, int req_type)
{
- struct iommu_domain *dom;
-
- dom = __iommu_domain_alloc(bus, type);
- if (!dom && type != IOMMU_DOMAIN_DMA) {
- dom = __iommu_domain_alloc(bus, IOMMU_DOMAIN_DMA);
- if (dom)
- pr_warn("Failed to allocate default IOMMU domain of type %u for group %s - Falling back to IOMMU_DOMAIN_DMA",
- type, group->name);
- }
-
- if (!dom)
- return -ENOMEM;
-
- group->default_domain = dom;
- if (!group->domain)
- group->domain = dom;
- return 0;
+ if (group->default_domain && group->default_domain->type == req_type)
+ return group->default_domain;
+ return __iommu_domain_alloc(bus, req_type);
}
-static int iommu_alloc_default_domain(struct iommu_group *group,
- struct device *dev)
+/*
+ * req_type of 0 means "auto" which means to select a domain based on
+ * iommu_def_domain_type or what the driver actually supports.
+ */
+static struct iommu_domain *
+iommu_group_alloc_default_domain(struct iommu_group *group, int req_type)
{
- unsigned int type;
+ const struct bus_type *bus =
+ list_first_entry(&group->devices, struct group_device, list)
+ ->dev->bus;
+ struct iommu_domain *dom;
- if (group->default_domain)
- return 0;
+ lockdep_assert_held(&group->mutex);
+
+ if (req_type)
+ return __iommu_group_alloc_default_domain(bus, group, req_type);
- type = iommu_get_def_domain_type(dev) ? : iommu_def_domain_type;
+ /* The driver gave no guidance on what type to use, try the default */
+ dom = __iommu_group_alloc_default_domain(bus, group, iommu_def_domain_type);
+ if (dom)
+ return dom;
- return iommu_group_alloc_default_domain(dev->bus, group, type);
+ /* Otherwise IDENTITY and DMA_FQ defaults will try DMA */
+ if (iommu_def_domain_type == IOMMU_DOMAIN_DMA)
+ return NULL;
+ dom = __iommu_group_alloc_default_domain(bus, group, IOMMU_DOMAIN_DMA);
+ if (!dom)
+ return NULL;
+
+ pr_warn("Failed to allocate default IOMMU domain of type %u for group %s - Falling back to IOMMU_DOMAIN_DMA",
+ iommu_def_domain_type, group->name);
+ return dom;
}
/**
@@ -1774,87 +1746,48 @@ static int iommu_bus_notifier(struct notifier_block *nb,
return 0;
}
-struct __group_domain_type {
- struct device *dev;
- unsigned int type;
-};
-
-static int probe_get_default_domain_type(struct device *dev, void *data)
-{
- struct __group_domain_type *gtype = data;
- unsigned int type = iommu_get_def_domain_type(dev);
-
- if (type) {
- if (gtype->type && gtype->type != type) {
- dev_warn(dev, "Device needs domain type %s, but device %s in the same iommu group requires type %s - using default\n",
- iommu_domain_type_str(type),
- dev_name(gtype->dev),
- iommu_domain_type_str(gtype->type));
- gtype->type = 0;
- }
-
- if (!gtype->dev) {
- gtype->dev = dev;
- gtype->type = type;
- }
- }
-
- return 0;
-}
-
-static void probe_alloc_default_domain(const struct bus_type *bus,
- struct iommu_group *group)
+/* A target_type of 0 will select the best domain type and cannot fail */
+static int iommu_get_default_domain_type(struct iommu_group *group,
+ int target_type)
{
- struct __group_domain_type gtype;
+ int best_type = target_type;
+ struct group_device *gdev;
+ struct device *last_dev;
- memset(&gtype, 0, sizeof(gtype));
-
- /* Ask for default domain requirements of all devices in the group */
- __iommu_group_for_each_dev(group, &gtype,
- probe_get_default_domain_type);
-
- if (!gtype.type)
- gtype.type = iommu_def_domain_type;
+ lockdep_assert_held(&group->mutex);
- iommu_group_alloc_default_domain(bus, group, gtype.type);
+ for_each_group_device(group, gdev) {
+ unsigned int type = iommu_get_def_domain_type(gdev->dev);
-}
+ if (best_type && type && best_type != type) {
+ if (target_type) {
+ dev_err_ratelimited(
+ gdev->dev,
+ "Device cannot be in %s domain\n",
+ iommu_domain_type_str(target_type));
+ return -1;
+ }
-static int __iommu_group_dma_first_attach(struct iommu_group *group)
-{
- return __iommu_group_for_each_dev(group, group->default_domain,
- iommu_group_do_dma_first_attach);
+ dev_warn(
+ gdev->dev,
+ "Device needs domain type %s, but device %s in the same iommu group requires type %s - using default\n",
+ iommu_domain_type_str(type), dev_name(last_dev),
+ iommu_domain_type_str(best_type));
+ return 0;
+ }
+ if (!best_type)
+ best_type = type;
+ last_dev = gdev->dev;
+ }
+ return best_type;
}
-static int iommu_group_do_probe_finalize(struct device *dev, void *data)
+static void iommu_group_do_probe_finalize(struct device *dev)
{
const struct iommu_ops *ops = dev_iommu_ops(dev);
if (ops->probe_finalize)
ops->probe_finalize(dev);
-
- return 0;
-}
-
-static void __iommu_group_dma_finalize(struct iommu_group *group)
-{
- __iommu_group_for_each_dev(group, group->default_domain,
- iommu_group_do_probe_finalize);
-}
-
-static int iommu_do_create_direct_mappings(struct device *dev, void *data)
-{
- struct iommu_group *group = data;
-
- iommu_create_device_direct_mappings(group, dev);
-
- return 0;
-}
-
-static int iommu_group_create_direct_mappings(struct iommu_group *group)
-{
- return __iommu_group_for_each_dev(group, group,
- iommu_do_create_direct_mappings);
}
int bus_iommu_probe(const struct bus_type *bus)
@@ -1873,32 +1806,31 @@ int bus_iommu_probe(const struct bus_type *bus)
return ret;
list_for_each_entry_safe(group, next, &group_list, entry) {
+ struct group_device *gdev;
+
mutex_lock(&group->mutex);
/* Remove item from the list */
list_del_init(&group->entry);
- /* Try to allocate default domain */
- probe_alloc_default_domain(bus, group);
-
- if (!group->default_domain) {
+ ret = iommu_setup_default_domain(group, 0);
+ if (ret) {
mutex_unlock(&group->mutex);
- continue;
+ return ret;
}
-
- iommu_group_create_direct_mappings(group);
-
- ret = __iommu_group_dma_first_attach(group);
-
mutex_unlock(&group->mutex);
- if (ret)
- break;
-
- __iommu_group_dma_finalize(group);
+ /*
+ * FIXME: Mis-locked because the ops->probe_finalize() call-back
+ * of some IOMMU drivers calls arm_iommu_attach_device() which
+ * in-turn might call back into IOMMU core code, where it tries
+ * to take group->mutex, resulting in a deadlock.
+ */
+ for_each_group_device(group, gdev)
+ iommu_group_do_probe_finalize(gdev->dev);
}
- return ret;
+ return 0;
}
bool iommu_present(const struct bus_type *bus)
@@ -1946,7 +1878,7 @@ bool iommu_group_has_isolated_msi(struct iommu_group *group)
bool ret = true;
mutex_lock(&group->mutex);
- list_for_each_entry(group_dev, &group->devices, list)
+ for_each_group_device(group, group_dev)
ret &= msi_device_has_isolated_msi(group_dev->dev);
mutex_unlock(&group->mutex);
return ret;
@@ -1980,11 +1912,12 @@ static struct iommu_domain *__iommu_domain_alloc(const struct bus_type *bus,
unsigned type)
{
struct iommu_domain *domain;
+ unsigned int alloc_type = type & IOMMU_DOMAIN_ALLOC_FLAGS;
if (bus == NULL || bus->iommu_ops == NULL)
return NULL;
- domain = bus->iommu_ops->domain_alloc(type);
+ domain = bus->iommu_ops->domain_alloc(alloc_type);
if (!domain)
return NULL;
@@ -2028,15 +1961,13 @@ EXPORT_SYMBOL_GPL(iommu_domain_free);
static void __iommu_group_set_core_domain(struct iommu_group *group)
{
struct iommu_domain *new_domain;
- int ret;
if (group->owner)
new_domain = group->blocking_domain;
else
new_domain = group->default_domain;
- ret = __iommu_group_set_domain(group, new_domain);
- WARN(ret, "iommu driver failed to attach the default/blocking domain");
+ __iommu_group_set_domain_nofail(group, new_domain);
}
static int __iommu_attach_device(struct iommu_domain *domain,
@@ -2082,7 +2013,7 @@ int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
*/
mutex_lock(&group->mutex);
ret = -EINVAL;
- if (iommu_group_device_count(group) != 1)
+ if (list_count_nodes(&group->devices) != 1)
goto out_unlock;
ret = __iommu_attach_group(domain, group);
@@ -2113,7 +2044,7 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
mutex_lock(&group->mutex);
if (WARN_ON(domain != group->domain) ||
- WARN_ON(iommu_group_device_count(group) != 1))
+ WARN_ON(list_count_nodes(&group->devices) != 1))
goto out_unlock;
__iommu_group_set_core_domain(group);
@@ -2149,52 +2080,14 @@ struct iommu_domain *iommu_get_dma_domain(struct device *dev)
return dev->iommu_group->default_domain;
}
-/*
- * IOMMU groups are really the natural working unit of the IOMMU, but
- * the IOMMU API works on domains and devices. Bridge that gap by
- * iterating over the devices in a group. Ideally we'd have a single
- * device which represents the requestor ID of the group, but we also
- * allow IOMMU drivers to create policy defined minimum sets, where
- * the physical hardware may be able to distiguish members, but we
- * wish to group them at a higher level (ex. untrusted multi-function
- * PCI devices). Thus we attach each device.
- */
-static int iommu_group_do_attach_device(struct device *dev, void *data)
-{
- struct iommu_domain *domain = data;
-
- return __iommu_attach_device(domain, dev);
-}
-
static int __iommu_attach_group(struct iommu_domain *domain,
struct iommu_group *group)
{
- int ret;
-
if (group->domain && group->domain != group->default_domain &&
group->domain != group->blocking_domain)
return -EBUSY;
- ret = __iommu_group_for_each_dev(group, domain,
- iommu_group_do_attach_device);
- if (ret == 0) {
- group->domain = domain;
- } else {
- /*
- * To recover from the case when certain device within the
- * group fails to attach to the new domain, we need force
- * attaching all devices back to the old domain. The old
- * domain is compatible for all devices in the group,
- * hence the iommu driver should always return success.
- */
- struct iommu_domain *old_domain = group->domain;
-
- group->domain = NULL;
- WARN(__iommu_group_set_domain(group, old_domain),
- "iommu driver failed to attach a compatible domain");
- }
-
- return ret;
+ return __iommu_group_set_domain(group, domain);
}
/**
@@ -2221,21 +2114,61 @@ int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group)
}
EXPORT_SYMBOL_GPL(iommu_attach_group);
-static int iommu_group_do_set_platform_dma(struct device *dev, void *data)
+static int __iommu_device_set_domain(struct iommu_group *group,
+ struct device *dev,
+ struct iommu_domain *new_domain,
+ unsigned int flags)
{
- const struct iommu_ops *ops = dev_iommu_ops(dev);
+ int ret;
- if (!WARN_ON(!ops->set_platform_dma_ops))
- ops->set_platform_dma_ops(dev);
+ if (dev->iommu->attach_deferred) {
+ if (new_domain == group->default_domain)
+ return 0;
+ dev->iommu->attach_deferred = 0;
+ }
+ ret = __iommu_attach_device(new_domain, dev);
+ if (ret) {
+ /*
+ * If we have a blocking domain then try to attach that in hopes
+ * of avoiding a UAF. Modern drivers should implement blocking
+ * domains as global statics that cannot fail.
+ */
+ if ((flags & IOMMU_SET_DOMAIN_MUST_SUCCEED) &&
+ group->blocking_domain &&
+ group->blocking_domain != new_domain)
+ __iommu_attach_device(group->blocking_domain, dev);
+ return ret;
+ }
return 0;
}
-static int __iommu_group_set_domain(struct iommu_group *group,
- struct iommu_domain *new_domain)
+/*
+ * If 0 is returned the group's domain is new_domain. If an error is returned
+ * then the group's domain will be set back to the existing domain unless
+ * IOMMU_SET_DOMAIN_MUST_SUCCEED, otherwise an error is returned and the group's
+ * domains is left inconsistent. This is a driver bug to fail attach with a
+ * previously good domain. We try to avoid a kernel UAF because of this.
+ *
+ * IOMMU groups are really the natural working unit of the IOMMU, but the IOMMU
+ * API works on domains and devices. Bridge that gap by iterating over the
+ * devices in a group. Ideally we'd have a single device which represents the
+ * requestor ID of the group, but we also allow IOMMU drivers to create policy
+ * defined minimum sets, where the physical hardware may be able to distiguish
+ * members, but we wish to group them at a higher level (ex. untrusted
+ * multi-function PCI devices). Thus we attach each device.
+ */
+static int __iommu_group_set_domain_internal(struct iommu_group *group,
+ struct iommu_domain *new_domain,
+ unsigned int flags)
{
+ struct group_device *last_gdev;
+ struct group_device *gdev;
+ int result;
int ret;
+ lockdep_assert_held(&group->mutex);
+
if (group->domain == new_domain)
return 0;
@@ -2245,8 +2178,12 @@ static int __iommu_group_set_domain(struct iommu_group *group,
* platform specific behavior.
*/
if (!new_domain) {
- __iommu_group_for_each_dev(group, NULL,
- iommu_group_do_set_platform_dma);
+ for_each_group_device(group, gdev) {
+ const struct iommu_ops *ops = dev_iommu_ops(gdev->dev);
+
+ if (!WARN_ON(!ops->set_platform_dma_ops))
+ ops->set_platform_dma_ops(gdev->dev);
+ }
group->domain = NULL;
return 0;
}
@@ -2256,16 +2193,52 @@ static int __iommu_group_set_domain(struct iommu_group *group,
* domain. This switch does not have to be atomic and DMA can be
* discarded during the transition. DMA must only be able to access
* either new_domain or group->domain, never something else.
- *
- * Note that this is called in error unwind paths, attaching to a
- * domain that has already been attached cannot fail.
*/
- ret = __iommu_group_for_each_dev(group, new_domain,
- iommu_group_do_attach_device);
- if (ret)
- return ret;
+ result = 0;
+ for_each_group_device(group, gdev) {
+ ret = __iommu_device_set_domain(group, gdev->dev, new_domain,
+ flags);
+ if (ret) {
+ result = ret;
+ /*
+ * Keep trying the other devices in the group. If a
+ * driver fails attach to an otherwise good domain, and
+ * does not support blocking domains, it should at least
+ * drop its reference on the current domain so we don't
+ * UAF.
+ */
+ if (flags & IOMMU_SET_DOMAIN_MUST_SUCCEED)
+ continue;
+ goto err_revert;
+ }
+ }
group->domain = new_domain;
- return 0;
+ return result;
+
+err_revert:
+ /*
+ * This is called in error unwind paths. A well behaved driver should
+ * always allow us to attach to a domain that was already attached.
+ */
+ last_gdev = gdev;
+ for_each_group_device(group, gdev) {
+ const struct iommu_ops *ops = dev_iommu_ops(gdev->dev);
+
+ /*
+ * If set_platform_dma_ops is not present a NULL domain can
+ * happen only for first probe, in which case we leave
+ * group->domain as NULL and let release clean everything up.
+ */
+ if (group->domain)
+ WARN_ON(__iommu_device_set_domain(
+ group, gdev->dev, group->domain,
+ IOMMU_SET_DOMAIN_MUST_SUCCEED));
+ else if (ops->set_platform_dma_ops)
+ ops->set_platform_dma_ops(gdev->dev);
+ if (gdev == last_gdev)
+ break;
+ }
+ return ret;
}
void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group)
@@ -2846,78 +2819,112 @@ int iommu_dev_disable_feature(struct device *dev, enum iommu_dev_features feat)
}
EXPORT_SYMBOL_GPL(iommu_dev_disable_feature);
-/*
- * Changes the default domain of an iommu group
- *
- * @group: The group for which the default domain should be changed
- * @dev: The first device in the group
- * @type: The type of the new default domain that gets associated with the group
- *
- * Returns 0 on success and error code on failure
+/**
+ * iommu_setup_default_domain - Set the default_domain for the group
+ * @group: Group to change
+ * @target_type: Domain type to set as the default_domain
*
- * Note:
- * 1. Presently, this function is called only when user requests to change the
- * group's default domain type through /sys/kernel/iommu_groups/<grp_id>/type
- * Please take a closer look if intended to use for other purposes.
+ * Allocate a default domain and set it as the current domain on the group. If
+ * the group already has a default domain it will be changed to the target_type.
+ * When target_type is 0 the default domain is selected based on driver and
+ * system preferences.
*/
-static int iommu_change_dev_def_domain(struct iommu_group *group,
- struct device *dev, int type)
+static int iommu_setup_default_domain(struct iommu_group *group,
+ int target_type)
{
- struct __group_domain_type gtype = {NULL, 0};
- struct iommu_domain *prev_dom;
+ struct iommu_domain *old_dom = group->default_domain;
+ struct group_device *gdev;
+ struct iommu_domain *dom;
+ bool direct_failed;
+ int req_type;
int ret;
lockdep_assert_held(&group->mutex);
- prev_dom = group->default_domain;
- __iommu_group_for_each_dev(group, &gtype,
- probe_get_default_domain_type);
- if (!type) {
- /*
- * If the user hasn't requested any specific type of domain and
- * if the device supports both the domains, then default to the
- * domain the device was booted with
- */
- type = gtype.type ? : iommu_def_domain_type;
- } else if (gtype.type && type != gtype.type) {
- dev_err_ratelimited(dev, "Device cannot be in %s domain\n",
- iommu_domain_type_str(type));
+ req_type = iommu_get_default_domain_type(group, target_type);
+ if (req_type < 0)
return -EINVAL;
- }
/*
- * Switch to a new domain only if the requested domain type is different
- * from the existing default domain type
+ * There are still some drivers which don't support default domains, so
+ * we ignore the failure and leave group->default_domain NULL.
+ *
+ * We assume that the iommu driver starts up the device in
+ * 'set_platform_dma_ops' mode if it does not support default domains.
*/
- if (prev_dom->type == type)
+ dom = iommu_group_alloc_default_domain(group, req_type);
+ if (!dom) {
+ /* Once in default_domain mode we never leave */
+ if (group->default_domain)
+ return -ENODEV;
+ group->default_domain = NULL;
return 0;
+ }
- group->default_domain = NULL;
- group->domain = NULL;
-
- /* Sets group->default_domain to the newly allocated domain */
- ret = iommu_group_alloc_default_domain(dev->bus, group, type);
- if (ret)
- goto restore_old_domain;
-
- ret = iommu_group_create_direct_mappings(group);
- if (ret)
- goto free_new_domain;
-
- ret = __iommu_attach_group(group->default_domain, group);
- if (ret)
- goto free_new_domain;
+ if (group->default_domain == dom)
+ return 0;
- iommu_domain_free(prev_dom);
+ /*
+ * IOMMU_RESV_DIRECT and IOMMU_RESV_DIRECT_RELAXABLE regions must be
+ * mapped before their device is attached, in order to guarantee
+ * continuity with any FW activity
+ */
+ direct_failed = false;
+ for_each_group_device(group, gdev) {
+ if (iommu_create_device_direct_mappings(dom, gdev->dev)) {
+ direct_failed = true;
+ dev_warn_once(
+ gdev->dev->iommu->iommu_dev->dev,
+ "IOMMU driver was not able to establish FW requested direct mapping.");
+ }
+ }
- return 0;
+ /* We must set default_domain early for __iommu_device_set_domain */
+ group->default_domain = dom;
+ if (!group->domain) {
+ /*
+ * Drivers are not allowed to fail the first domain attach.
+ * The only way to recover from this is to fail attaching the
+ * iommu driver and call ops->release_device. Put the domain
+ * in group->default_domain so it is freed after.
+ */
+ ret = __iommu_group_set_domain_internal(
+ group, dom, IOMMU_SET_DOMAIN_MUST_SUCCEED);
+ if (WARN_ON(ret))
+ goto out_free;
+ } else {
+ ret = __iommu_group_set_domain(group, dom);
+ if (ret) {
+ iommu_domain_free(dom);
+ group->default_domain = old_dom;
+ return ret;
+ }
+ }
-free_new_domain:
- iommu_domain_free(group->default_domain);
-restore_old_domain:
- group->default_domain = prev_dom;
- group->domain = prev_dom;
+ /*
+ * Drivers are supposed to allow mappings to be installed in a domain
+ * before device attachment, but some don't. Hack around this defect by
+ * trying again after attaching. If this happens it means the device
+ * will not continuously have the IOMMU_RESV_DIRECT map.
+ */
+ if (direct_failed) {
+ for_each_group_device(group, gdev) {
+ ret = iommu_create_device_direct_mappings(dom, gdev->dev);
+ if (ret)
+ goto err_restore;
+ }
+ }
+err_restore:
+ if (old_dom) {
+ __iommu_group_set_domain_internal(
+ group, old_dom, IOMMU_SET_DOMAIN_MUST_SUCCEED);
+ iommu_domain_free(dom);
+ old_dom = NULL;
+ }
+out_free:
+ if (old_dom)
+ iommu_domain_free(old_dom);
return ret;
}
@@ -2933,8 +2940,7 @@ restore_old_domain:
static ssize_t iommu_group_store_type(struct iommu_group *group,
const char *buf, size_t count)
{
- struct group_device *grp_dev;
- struct device *dev;
+ struct group_device *gdev;
int ret, req_type;
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
@@ -2959,23 +2965,23 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
if (req_type == IOMMU_DOMAIN_DMA_FQ &&
group->default_domain->type == IOMMU_DOMAIN_DMA) {
ret = iommu_dma_init_fq(group->default_domain);
- if (!ret)
- group->default_domain->type = IOMMU_DOMAIN_DMA_FQ;
- mutex_unlock(&group->mutex);
+ if (ret)
+ goto out_unlock;
- return ret ?: count;
+ group->default_domain->type = IOMMU_DOMAIN_DMA_FQ;
+ ret = count;
+ goto out_unlock;
}
/* Otherwise, ensure that device exists and no driver is bound. */
if (list_empty(&group->devices) || group->owner_cnt) {
- mutex_unlock(&group->mutex);
- return -EPERM;
+ ret = -EPERM;
+ goto out_unlock;
}
- grp_dev = list_first_entry(&group->devices, struct group_device, list);
- dev = grp_dev->dev;
-
- ret = iommu_change_dev_def_domain(group, dev, req_type);
+ ret = iommu_setup_default_domain(group, req_type);
+ if (ret)
+ goto out_unlock;
/*
* Release the mutex here because ops->probe_finalize() call-back of
@@ -2986,9 +2992,12 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
mutex_unlock(&group->mutex);
/* Make sure dma_ops is appropriatley set */
- if (!ret)
- __iommu_group_dma_finalize(group);
+ for_each_group_device(group, gdev)
+ iommu_group_do_probe_finalize(gdev->dev);
+ return count;
+out_unlock:
+ mutex_unlock(&group->mutex);
return ret ?: count;
}
@@ -3182,16 +3191,13 @@ EXPORT_SYMBOL_GPL(iommu_device_claim_dma_owner);
static void __iommu_release_dma_ownership(struct iommu_group *group)
{
- int ret;
-
if (WARN_ON(!group->owner_cnt || !group->owner ||
!xa_empty(&group->pasid_array)))
return;
group->owner_cnt = 0;
group->owner = NULL;
- ret = __iommu_group_set_domain(group, group->default_domain);
- WARN(ret, "iommu driver failed to attach the default domain");
+ __iommu_group_set_domain_nofail(group, group->default_domain);
}
/**
@@ -3253,7 +3259,7 @@ static int __iommu_set_group_pasid(struct iommu_domain *domain,
struct group_device *device;
int ret = 0;
- list_for_each_entry(device, &group->devices, list) {
+ for_each_group_device(group, device) {
ret = domain->ops->set_dev_pasid(domain, device->dev, pasid);
if (ret)
break;
@@ -3268,7 +3274,7 @@ static void __iommu_remove_group_pasid(struct iommu_group *group,
struct group_device *device;
const struct iommu_ops *ops;
- list_for_each_entry(device, &group->devices, list) {
+ for_each_group_device(group, device) {
ops = dev_iommu_ops(device->dev);
ops->remove_dev_pasid(device->dev, pasid);
}
diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index 4f9b2142274c..29d05663d4d1 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -553,8 +553,8 @@ void iommufd_access_unpin_pages(struct iommufd_access *access,
iopt_area_iova_to_index(
area,
min(last_iova, iopt_area_last_iova(area))));
- up_read(&iopt->iova_rwsem);
WARN_ON(!iopt_area_contig_done(&iter));
+ up_read(&iopt->iova_rwsem);
}
EXPORT_SYMBOL_NS_GPL(iommufd_access_unpin_pages, IOMMUFD);
diff --git a/drivers/iommu/iommufd/io_pagetable.c b/drivers/iommu/iommufd/io_pagetable.c
index e0ae72b9e67f..724c4c574241 100644
--- a/drivers/iommu/iommufd/io_pagetable.c
+++ b/drivers/iommu/iommufd/io_pagetable.c
@@ -458,6 +458,7 @@ static int iopt_unmap_iova_range(struct io_pagetable *iopt, unsigned long start,
{
struct iopt_area *area;
unsigned long unmapped_bytes = 0;
+ unsigned int tries = 0;
int rc = -ENOENT;
/*
@@ -484,19 +485,26 @@ again:
goto out_unlock_iova;
}
+ if (area_first != start)
+ tries = 0;
+
/*
* num_accesses writers must hold the iova_rwsem too, so we can
* safely read it under the write side of the iovam_rwsem
* without the pages->mutex.
*/
if (area->num_accesses) {
+ size_t length = iopt_area_length(area);
+
start = area_first;
area->prevent_access = true;
up_write(&iopt->iova_rwsem);
up_read(&iopt->domains_rwsem);
- iommufd_access_notify_unmap(iopt, area_first,
- iopt_area_length(area));
- if (WARN_ON(READ_ONCE(area->num_accesses)))
+
+ iommufd_access_notify_unmap(iopt, area_first, length);
+ /* Something is not responding to unmap requests. */
+ tries++;
+ if (WARN_ON(tries > 100))
return -EDEADLOCK;
goto again;
}
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index fe452ce46642..10b964600948 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -647,7 +647,13 @@ struct iova_rcache {
static struct iova_magazine *iova_magazine_alloc(gfp_t flags)
{
- return kzalloc(sizeof(struct iova_magazine), flags);
+ struct iova_magazine *mag;
+
+ mag = kmalloc(sizeof(*mag), flags);
+ if (mag)
+ mag->size = 0;
+
+ return mag;
}
static void iova_magazine_free(struct iova_magazine *mag)
diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 5b8fe9bfa9a5..3551ed057774 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -788,6 +788,29 @@ static int viommu_attach_dev(struct iommu_domain *domain, struct device *dev)
return 0;
}
+static void viommu_detach_dev(struct viommu_endpoint *vdev)
+{
+ int i;
+ struct virtio_iommu_req_detach req;
+ struct viommu_domain *vdomain = vdev->vdomain;
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(vdev->dev);
+
+ if (!vdomain)
+ return;
+
+ req = (struct virtio_iommu_req_detach) {
+ .head.type = VIRTIO_IOMMU_T_DETACH,
+ .domain = cpu_to_le32(vdomain->id),
+ };
+
+ for (i = 0; i < fwspec->num_ids; i++) {
+ req.endpoint = cpu_to_le32(fwspec->ids[i]);
+ WARN_ON(viommu_send_req_sync(vdev->viommu, &req, sizeof(req)));
+ }
+ vdomain->nr_endpoints--;
+ vdev->vdomain = NULL;
+}
+
static int viommu_map_pages(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t pgsize, size_t pgcount,
int prot, gfp_t gfp, size_t *mapped)
@@ -810,25 +833,26 @@ static int viommu_map_pages(struct iommu_domain *domain, unsigned long iova,
if (ret)
return ret;
- map = (struct virtio_iommu_req_map) {
- .head.type = VIRTIO_IOMMU_T_MAP,
- .domain = cpu_to_le32(vdomain->id),
- .virt_start = cpu_to_le64(iova),
- .phys_start = cpu_to_le64(paddr),
- .virt_end = cpu_to_le64(end),
- .flags = cpu_to_le32(flags),
- };
-
- if (!vdomain->nr_endpoints)
- return 0;
+ if (vdomain->nr_endpoints) {
+ map = (struct virtio_iommu_req_map) {
+ .head.type = VIRTIO_IOMMU_T_MAP,
+ .domain = cpu_to_le32(vdomain->id),
+ .virt_start = cpu_to_le64(iova),
+ .phys_start = cpu_to_le64(paddr),
+ .virt_end = cpu_to_le64(end),
+ .flags = cpu_to_le32(flags),
+ };
- ret = viommu_send_req_sync(vdomain->viommu, &map, sizeof(map));
- if (ret)
- viommu_del_mappings(vdomain, iova, end);
- else if (mapped)
+ ret = viommu_send_req_sync(vdomain->viommu, &map, sizeof(map));
+ if (ret) {
+ viommu_del_mappings(vdomain, iova, end);
+ return ret;
+ }
+ }
+ if (mapped)
*mapped = size;
- return ret;
+ return 0;
}
static size_t viommu_unmap_pages(struct iommu_domain *domain, unsigned long iova,
@@ -990,6 +1014,7 @@ static void viommu_release_device(struct device *dev)
{
struct viommu_endpoint *vdev = dev_iommu_priv_get(dev);
+ viommu_detach_dev(vdev);
iommu_put_resv_regions(dev, &vdev->resv_regions);
kfree(vdev);
}
diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c
index f229e3e66387..4adeee1bc391 100644
--- a/drivers/irqchip/irq-riscv-intc.c
+++ b/drivers/irqchip/irq-riscv-intc.c
@@ -6,6 +6,7 @@
*/
#define pr_fmt(fmt) "riscv-intc: " fmt
+#include <linux/acpi.h>
#include <linux/atomic.h>
#include <linux/bits.h>
#include <linux/cpu.h>
@@ -112,6 +113,30 @@ static struct fwnode_handle *riscv_intc_hwnode(void)
return intc_domain->fwnode;
}
+static int __init riscv_intc_init_common(struct fwnode_handle *fn)
+{
+ int rc;
+
+ intc_domain = irq_domain_create_linear(fn, BITS_PER_LONG,
+ &riscv_intc_domain_ops, NULL);
+ if (!intc_domain) {
+ pr_err("unable to add IRQ domain\n");
+ return -ENXIO;
+ }
+
+ rc = set_handle_irq(&riscv_intc_irq);
+ if (rc) {
+ pr_err("failed to set irq handler\n");
+ return rc;
+ }
+
+ riscv_set_intc_hwnode_fn(riscv_intc_hwnode);
+
+ pr_info("%d local interrupts mapped\n", BITS_PER_LONG);
+
+ return 0;
+}
+
static int __init riscv_intc_init(struct device_node *node,
struct device_node *parent)
{
@@ -133,24 +158,39 @@ static int __init riscv_intc_init(struct device_node *node,
if (riscv_hartid_to_cpuid(hartid) != smp_processor_id())
return 0;
- intc_domain = irq_domain_add_linear(node, BITS_PER_LONG,
- &riscv_intc_domain_ops, NULL);
- if (!intc_domain) {
- pr_err("unable to add IRQ domain\n");
- return -ENXIO;
- }
+ return riscv_intc_init_common(of_node_to_fwnode(node));
+}
- rc = set_handle_irq(&riscv_intc_irq);
- if (rc) {
- pr_err("failed to set irq handler\n");
- return rc;
- }
+IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init);
- riscv_set_intc_hwnode_fn(riscv_intc_hwnode);
+#ifdef CONFIG_ACPI
- pr_info("%d local interrupts mapped\n", BITS_PER_LONG);
+static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
+ const unsigned long end)
+{
+ struct fwnode_handle *fn;
+ struct acpi_madt_rintc *rintc;
- return 0;
+ rintc = (struct acpi_madt_rintc *)header;
+
+ /*
+ * The ACPI MADT will have one INTC for each CPU (or HART)
+ * so riscv_intc_acpi_init() function will be called once
+ * for each INTC. We only do INTC initialization
+ * for the INTC belonging to the boot CPU (or boot HART).
+ */
+ if (riscv_hartid_to_cpuid(rintc->hart_id) != smp_processor_id())
+ return 0;
+
+ fn = irq_domain_alloc_named_fwnode("RISCV-INTC");
+ if (!fn) {
+ pr_err("unable to allocate INTC FW node\n");
+ return -ENOMEM;
+ }
+
+ return riscv_intc_init_common(fn);
}
-IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init);
+IRQCHIP_ACPI_DECLARE(riscv_intc, ACPI_MADT_TYPE_RINTC, NULL,
+ ACPI_MADT_RINTC_VERSION_V1, riscv_intc_acpi_init);
+#endif
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index 2690e2c5a158..6fd1b3f84a29 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -6,7 +6,6 @@
menuconfig ISDN
bool "ISDN support"
depends on NET && NETDEVICES
- depends on !S390 && !UML
help
ISDN ("Integrated Services Digital Network", called RNIS in France)
is a fully digital telephone service that can be used for voice and
diff --git a/drivers/isdn/hardware/mISDN/Kconfig b/drivers/isdn/hardware/mISDN/Kconfig
index 078eeadf707a..a35bff8a93f5 100644
--- a/drivers/isdn/hardware/mISDN/Kconfig
+++ b/drivers/isdn/hardware/mISDN/Kconfig
@@ -14,7 +14,7 @@ config MISDN_HFCPCI
config MISDN_HFCMULTI
tristate "Support for HFC multiport cards (HFC-4S/8S/E1)"
- depends on PCI || CPM1
+ depends on (PCI || CPM1) && HAS_IOPORT
depends on MISDN
help
Enable support for cards with Cologne Chip AG's HFC multiport
@@ -43,7 +43,7 @@ config MISDN_HFCUSB
config MISDN_AVMFRITZ
tristate "Support for AVM FRITZ!CARD PCI"
depends on MISDN
- depends on PCI
+ depends on PCI && HAS_IOPORT
select MISDN_IPAC
help
Enable support for AVMs FRITZ!CARD PCI cards
@@ -51,7 +51,7 @@ config MISDN_AVMFRITZ
config MISDN_SPEEDFAX
tristate "Support for Sedlbauer Speedfax+"
depends on MISDN
- depends on PCI
+ depends on PCI && HAS_IOPORT
select MISDN_IPAC
select MISDN_ISAR
help
@@ -60,7 +60,7 @@ config MISDN_SPEEDFAX
config MISDN_INFINEON
tristate "Support for cards with Infineon chipset"
depends on MISDN
- depends on PCI
+ depends on PCI && HAS_IOPORT
select MISDN_IPAC
help
Enable support for cards with ISAC + HSCX, IPAC or IPAC-SX
@@ -69,14 +69,14 @@ config MISDN_INFINEON
config MISDN_W6692
tristate "Support for cards with Winbond 6692"
depends on MISDN
- depends on PCI
+ depends on PCI && HAS_IOPORT
help
Enable support for Winbond 6692 PCI chip based cards.
config MISDN_NETJET
tristate "Support for NETJet cards"
depends on MISDN
- depends on PCI
+ depends on PCI && HAS_IOPORT
depends on TTY
select MISDN_IPAC
select MISDN_HDLC
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 2c5fdf848210..6046dfeca16f 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -94,6 +94,19 @@ config LEDS_ARIEL
Say Y to if your machine is a Dell Wyse 3020 thin client.
+config LEDS_AW200XX
+ tristate "LED support for Awinic AW20036/AW20054/AW20072"
+ depends on LEDS_CLASS
+ depends on I2C
+ help
+ This option enables support for the AW20036/AW20054/AW20072 LED driver.
+ It is a 3x12/6x9/6x12 matrix LED driver programmed via
+ an I2C interface, up to 36/54/72 LEDs or 12/18/24 RGBs,
+ 3 pattern controllers for auto breathing or group dimming control.
+
+ To compile this driver as a module, choose M here: the module
+ will be called leds-aw200xx.
+
config LEDS_AW2013
tristate "LED support for Awinic AW2013"
depends on LEDS_CLASS && I2C && OF
@@ -122,6 +135,17 @@ config LEDS_BCM6358
This option enables support for LEDs connected to the BCM6358
LED HW controller accessed via MMIO registers.
+config LEDS_CHT_WCOVE
+ tristate "LED support for Intel Cherry Trail Whiskey Cove PMIC"
+ depends on LEDS_CLASS
+ depends on INTEL_SOC_PMIC_CHTWC
+ help
+ This option enables support for charger and general purpose LEDs
+ connected to the Intel Cherrytrail Whiskey Cove PMIC.
+
+ To compile this driver as a module, choose M here: the module
+ will be called leds-cht-wcove.
+
config LEDS_CPCAP
tristate "LED Support for Motorola CPCAP"
depends on LEDS_CLASS
@@ -676,7 +700,7 @@ config LEDS_LM355x
config LEDS_OT200
tristate "LED support for the Bachmann OT200"
- depends on LEDS_CLASS && HAS_IOMEM && (X86_32 || COMPILE_TEST)
+ depends on LEDS_CLASS && HAS_IOPORT && (X86_32 || COMPILE_TEST)
help
This option enables support for the LEDs on the Bachmann OT200.
Say Y to enable LEDs on the Bachmann OT200.
@@ -807,8 +831,7 @@ config LEDS_SPI_BYTE
supported: Ubiquiti airCube ISP microcontroller based LED controller.
config LEDS_TI_LMU_COMMON
- tristate "LED driver for TI LMU"
- depends on LEDS_CLASS
+ tristate "LED driver for TI LMU" if COMPILE_TEST
select REGMAP
help
Say Y to enable the LED driver for TI LMU devices.
@@ -817,16 +840,16 @@ config LEDS_TI_LMU_COMMON
config LEDS_LM3697
tristate "LED driver for LM3697"
- depends on LEDS_TI_LMU_COMMON
- depends on I2C && OF
+ depends on LEDS_CLASS && I2C && OF
+ select LEDS_TI_LMU_COMMON
help
Say Y to enable the LM3697 LED driver for TI LMU devices.
This supports the LED device LM3697.
config LEDS_LM36274
tristate "LED driver for LM36274"
- depends on LEDS_TI_LMU_COMMON
- depends on MFD_TI_LMU
+ depends on LEDS_CLASS && MFD_TI_LMU
+ select LEDS_TI_LMU_COMMON
help
Say Y to enable the LM36274 LED driver for TI LMU devices.
This supports the LED device LM36274.
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index c07d1512c745..d71f1226540c 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -14,12 +14,14 @@ obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o
obj-$(CONFIG_LEDS_AN30259A) += leds-an30259a.o
obj-$(CONFIG_LEDS_APU) += leds-apu.o
obj-$(CONFIG_LEDS_ARIEL) += leds-ariel.o
+obj-$(CONFIG_LEDS_AW200XX) += leds-aw200xx.o
obj-$(CONFIG_LEDS_AW2013) += leds-aw2013.o
obj-$(CONFIG_LEDS_BCM6328) += leds-bcm6328.o
obj-$(CONFIG_LEDS_BCM6358) += leds-bcm6358.o
obj-$(CONFIG_LEDS_BD2606MVV) += leds-bd2606mvv.o
obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o
+obj-$(CONFIG_LEDS_CHT_WCOVE) += leds-cht-wcove.o
obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
diff --git a/drivers/leds/flash/leds-aat1290.c b/drivers/leds/flash/leds-aat1290.c
index 589484b22c79..f12ecb2c6580 100644
--- a/drivers/leds/flash/leds-aat1290.c
+++ b/drivers/leds/flash/leds-aat1290.c
@@ -425,7 +425,7 @@ static void aat1290_init_v4l2_flash_config(struct aat1290_led *led,
struct led_classdev *led_cdev = &led->fled_cdev.led_cdev;
struct led_flash_setting *s;
- strlcpy(v4l2_sd_cfg->dev_name, led_cdev->dev->kobj.name,
+ strscpy(v4l2_sd_cfg->dev_name, led_cdev->dev->kobj.name,
sizeof(v4l2_sd_cfg->dev_name));
s = &v4l2_sd_cfg->intensity;
diff --git a/drivers/leds/flash/leds-as3645a.c b/drivers/leds/flash/leds-as3645a.c
index bb2249771acb..12c2609c1137 100644
--- a/drivers/leds/flash/leds-as3645a.c
+++ b/drivers/leds/flash/leds-as3645a.c
@@ -651,8 +651,8 @@ static int as3645a_v4l2_setup(struct as3645a *flash)
},
};
- strlcpy(cfg.dev_name, led->dev->kobj.name, sizeof(cfg.dev_name));
- strlcpy(cfgind.dev_name, flash->iled_cdev.dev->kobj.name,
+ strscpy(cfg.dev_name, led->dev->kobj.name, sizeof(cfg.dev_name));
+ strscpy(cfgind.dev_name, flash->iled_cdev.dev->kobj.name,
sizeof(cfgind.dev_name));
flash->vf = v4l2_flash_init(
@@ -759,7 +759,7 @@ static struct i2c_driver as3645a_i2c_driver = {
.of_match_table = as3645a_of_table,
.name = AS_NAME,
},
- .probe_new = as3645a_probe,
+ .probe = as3645a_probe,
.remove = as3645a_remove,
.id_table = as3645a_id_table,
};
diff --git a/drivers/leds/flash/leds-lm3601x.c b/drivers/leds/flash/leds-lm3601x.c
index 78730e066a73..b6c524facf49 100644
--- a/drivers/leds/flash/leds-lm3601x.c
+++ b/drivers/leds/flash/leds-lm3601x.c
@@ -471,7 +471,7 @@ static struct i2c_driver lm3601x_i2c_driver = {
.name = "lm3601x",
.of_match_table = of_lm3601x_leds_match,
},
- .probe_new = lm3601x_probe,
+ .probe = lm3601x_probe,
.remove = lm3601x_remove,
.id_table = lm3601x_id,
};
diff --git a/drivers/leds/flash/leds-qcom-flash.c b/drivers/leds/flash/leds-qcom-flash.c
index 90a24fa25a49..b089ca1a1901 100644
--- a/drivers/leds/flash/leds-qcom-flash.c
+++ b/drivers/leds/flash/leds-qcom-flash.c
@@ -18,7 +18,8 @@
#define FLASH_TYPE_VAL 0x18
#define FLASH_SUBTYPE_REG 0x05
-#define FLASH_SUBTYPE_3CH_VAL 0x04
+#define FLASH_SUBTYPE_3CH_PM8150_VAL 0x04
+#define FLASH_SUBTYPE_3CH_PMI8998_VAL 0x03
#define FLASH_SUBTYPE_4CH_VAL 0x07
#define FLASH_STS_3CH_OTST1 BIT(0)
@@ -416,6 +417,14 @@ static int qcom_flash_led_brightness_set(struct led_classdev *led_cdev,
bool enable = !!brightness;
int rc;
+ rc = set_flash_strobe(led, SW_STROBE, false);
+ if (rc)
+ return rc;
+
+ rc = set_flash_module_en(led, false);
+ if (rc)
+ return rc;
+
rc = set_flash_current(led, current_ma, TORCH_MODE);
if (rc)
return rc;
@@ -529,9 +538,9 @@ static int qcom_flash_register_led_device(struct device *dev,
struct led_init_data init_data;
struct led_classdev_flash *flash = &led->flash;
struct led_flash_setting *brightness, *timeout;
- u32 count, current_ua, timeout_us;
+ u32 current_ua, timeout_us;
u32 channels[4];
- int i, rc;
+ int i, rc, count;
count = fwnode_property_count_u32(node, "led-sources");
if (count <= 0) {
@@ -682,7 +691,7 @@ static int qcom_flash_led_probe(struct platform_device *pdev)
return rc;
}
- if (val == FLASH_SUBTYPE_3CH_VAL) {
+ if (val == FLASH_SUBTYPE_3CH_PM8150_VAL || val == FLASH_SUBTYPE_3CH_PMI8998_VAL) {
flash_data->hw_type = QCOM_MVFLASH_3CH;
flash_data->max_channels = 3;
regs = mvflash_3ch_regs;
diff --git a/drivers/leds/flash/leds-rt4505.c b/drivers/leds/flash/leds-rt4505.c
index e404fe8b0314..1ae5b387f4a5 100644
--- a/drivers/leds/flash/leds-rt4505.c
+++ b/drivers/leds/flash/leds-rt4505.c
@@ -419,7 +419,7 @@ static struct i2c_driver rt4505_driver = {
.name = "rt4505",
.of_match_table = of_match_ptr(rt4505_leds_match),
},
- .probe_new = rt4505_probe,
+ .probe = rt4505_probe,
.remove = rt4505_remove,
.shutdown = rt4505_shutdown,
};
diff --git a/drivers/leds/flash/leds-sgm3140.c b/drivers/leds/flash/leds-sgm3140.c
index d3a30ad94ac4..d3f50dca5136 100644
--- a/drivers/leds/flash/leds-sgm3140.c
+++ b/drivers/leds/flash/leds-sgm3140.c
@@ -291,6 +291,7 @@ static int sgm3140_remove(struct platform_device *pdev)
static const struct of_device_id sgm3140_dt_match[] = {
{ .compatible = "ocs,ocp8110" },
+ { .compatible = "richtek,rt5033-led" },
{ .compatible = "sgmicro,sgm3140" },
{ /* sentinel */ }
};
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 9255bc11f99d..6dae56b914fe 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -409,7 +409,7 @@ static int led_classdev_next_name(const char *init_name, char *name,
int ret = 0;
struct device *dev;
- strlcpy(name, init_name, len);
+ strscpy(name, init_name, len);
while ((ret < len) &&
(dev = class_find_device_by_name(leds_class, name))) {
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 4a97cb745788..b9b1295833c9 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -114,21 +114,14 @@ static void led_timer_function(struct timer_list *t)
mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
}
-static void set_brightness_delayed(struct work_struct *ws)
+static void set_brightness_delayed_set_brightness(struct led_classdev *led_cdev,
+ unsigned int value)
{
- struct led_classdev *led_cdev =
- container_of(ws, struct led_classdev, set_brightness_work);
int ret = 0;
- if (test_and_clear_bit(LED_BLINK_DISABLE, &led_cdev->work_flags)) {
- led_cdev->delayed_set_value = LED_OFF;
- led_stop_software_blink(led_cdev);
- }
-
- ret = __led_set_brightness(led_cdev, led_cdev->delayed_set_value);
+ ret = __led_set_brightness(led_cdev, value);
if (ret == -ENOTSUPP)
- ret = __led_set_brightness_blocking(led_cdev,
- led_cdev->delayed_set_value);
+ ret = __led_set_brightness_blocking(led_cdev, value);
if (ret < 0 &&
/* LED HW might have been unplugged, therefore don't warn */
!(ret == -ENODEV && (led_cdev->flags & LED_UNREGISTERING) &&
@@ -137,6 +130,37 @@ static void set_brightness_delayed(struct work_struct *ws)
"Setting an LED's brightness failed (%d)\n", ret);
}
+static void set_brightness_delayed(struct work_struct *ws)
+{
+ struct led_classdev *led_cdev =
+ container_of(ws, struct led_classdev, set_brightness_work);
+
+ if (test_and_clear_bit(LED_BLINK_DISABLE, &led_cdev->work_flags)) {
+ led_stop_software_blink(led_cdev);
+ set_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags);
+ }
+
+ /*
+ * Triggers may call led_set_brightness(LED_OFF),
+ * led_set_brightness(LED_FULL) in quick succession to disable blinking
+ * and turn the LED on. Both actions may have been scheduled to run
+ * before this work item runs once. To make sure this works properly
+ * handle LED_SET_BRIGHTNESS_OFF first.
+ */
+ if (test_and_clear_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags))
+ set_brightness_delayed_set_brightness(led_cdev, LED_OFF);
+
+ if (test_and_clear_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags))
+ set_brightness_delayed_set_brightness(led_cdev, led_cdev->delayed_set_value);
+
+ if (test_and_clear_bit(LED_SET_BLINK, &led_cdev->work_flags)) {
+ unsigned long delay_on = led_cdev->delayed_delay_on;
+ unsigned long delay_off = led_cdev->delayed_delay_off;
+
+ led_blink_set(led_cdev, &delay_on, &delay_off);
+ }
+}
+
static void led_set_software_blink(struct led_classdev *led_cdev,
unsigned long delay_on,
unsigned long delay_off)
@@ -229,6 +253,22 @@ void led_blink_set_oneshot(struct led_classdev *led_cdev,
}
EXPORT_SYMBOL_GPL(led_blink_set_oneshot);
+void led_blink_set_nosleep(struct led_classdev *led_cdev, unsigned long delay_on,
+ unsigned long delay_off)
+{
+ /* If necessary delegate to a work queue task. */
+ if (led_cdev->blink_set && led_cdev->brightness_set_blocking) {
+ led_cdev->delayed_delay_on = delay_on;
+ led_cdev->delayed_delay_off = delay_off;
+ set_bit(LED_SET_BLINK, &led_cdev->work_flags);
+ schedule_work(&led_cdev->set_brightness_work);
+ return;
+ }
+
+ led_blink_set(led_cdev, &delay_on, &delay_off);
+}
+EXPORT_SYMBOL_GPL(led_blink_set_nosleep);
+
void led_stop_software_blink(struct led_classdev *led_cdev)
{
del_timer_sync(&led_cdev->blink_timer);
@@ -271,8 +311,23 @@ void led_set_brightness_nopm(struct led_classdev *led_cdev, unsigned int value)
if (!__led_set_brightness(led_cdev, value))
return;
- /* If brightness setting can sleep, delegate it to a work queue task */
- led_cdev->delayed_set_value = value;
+ /*
+ * Brightness setting can sleep, delegate it to a work queue task.
+ * value 0 / LED_OFF is special, since it also disables hw-blinking
+ * (sw-blink disable is handled in led_set_brightness()).
+ * To avoid a hw-blink-disable getting lost when a second brightness
+ * change is done immediately afterwards (before the work runs),
+ * it uses a separate work_flag.
+ */
+ if (value) {
+ led_cdev->delayed_set_value = value;
+ set_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags);
+ } else {
+ clear_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags);
+ clear_bit(LED_SET_BLINK, &led_cdev->work_flags);
+ set_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags);
+ }
+
schedule_work(&led_cdev->set_brightness_work);
}
EXPORT_SYMBOL_GPL(led_set_brightness_nopm);
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 072491d3e17b..6a5e1f41f9a4 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -185,6 +185,7 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
led_cdev->trigger = NULL;
led_cdev->trigger_data = NULL;
led_cdev->activated = false;
+ led_cdev->flags &= ~LED_INIT_DEFAULT_TRIGGER;
led_set_brightness(led_cdev, LED_OFF);
}
if (trig) {
@@ -393,8 +394,8 @@ void led_trigger_event(struct led_trigger *trig,
EXPORT_SYMBOL_GPL(led_trigger_event);
static void led_trigger_blink_setup(struct led_trigger *trig,
- unsigned long *delay_on,
- unsigned long *delay_off,
+ unsigned long delay_on,
+ unsigned long delay_off,
int oneshot,
int invert)
{
@@ -406,25 +407,25 @@ static void led_trigger_blink_setup(struct led_trigger *trig,
rcu_read_lock();
list_for_each_entry_rcu(led_cdev, &trig->led_cdevs, trig_list) {
if (oneshot)
- led_blink_set_oneshot(led_cdev, delay_on, delay_off,
+ led_blink_set_oneshot(led_cdev, &delay_on, &delay_off,
invert);
else
- led_blink_set(led_cdev, delay_on, delay_off);
+ led_blink_set_nosleep(led_cdev, delay_on, delay_off);
}
rcu_read_unlock();
}
void led_trigger_blink(struct led_trigger *trig,
- unsigned long *delay_on,
- unsigned long *delay_off)
+ unsigned long delay_on,
+ unsigned long delay_off)
{
led_trigger_blink_setup(trig, delay_on, delay_off, 0, 0);
}
EXPORT_SYMBOL_GPL(led_trigger_blink);
void led_trigger_blink_oneshot(struct led_trigger *trig,
- unsigned long *delay_on,
- unsigned long *delay_off,
+ unsigned long delay_on,
+ unsigned long delay_off,
int invert)
{
led_trigger_blink_setup(trig, delay_on, delay_off, 1, invert);
diff --git a/drivers/leds/leds-an30259a.c b/drivers/leds/leds-an30259a.c
index 89df267853a9..24b1041213c2 100644
--- a/drivers/leds/leds-an30259a.c
+++ b/drivers/leds/leds-an30259a.c
@@ -346,7 +346,7 @@ static struct i2c_driver an30259a_driver = {
.name = "leds-an30259a",
.of_match_table = of_match_ptr(an30259a_match_table),
},
- .probe_new = an30259a_probe,
+ .probe = an30259a_probe,
.remove = an30259a_remove,
.id_table = an30259a_id,
};
diff --git a/drivers/leds/leds-aw200xx.c b/drivers/leds/leds-aw200xx.c
new file mode 100644
index 000000000000..96979b8e09b7
--- /dev/null
+++ b/drivers/leds/leds-aw200xx.c
@@ -0,0 +1,594 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Awinic AW20036/AW20054/AW20072 LED driver
+ *
+ * Copyright (c) 2023, SberDevices. All Rights Reserved.
+ *
+ * Author: Martin Kurbanov <mmkurbanov@sberdevices.ru>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/container_of.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/time.h>
+#include <linux/units.h>
+
+#define AW200XX_DIM_MAX (BIT(6) - 1)
+#define AW200XX_FADE_MAX (BIT(8) - 1)
+#define AW200XX_IMAX_DEFAULT_uA 60000
+#define AW200XX_IMAX_MAX_uA 160000
+#define AW200XX_IMAX_MIN_uA 3300
+
+/* Page 0 */
+#define AW200XX_REG_PAGE0_BASE 0xc000
+
+/* Select page register */
+#define AW200XX_REG_PAGE 0xF0
+#define AW200XX_PAGE_MASK (GENMASK(7, 6) | GENMASK(2, 0))
+#define AW200XX_PAGE_SHIFT 0
+#define AW200XX_NUM_PAGES 6
+#define AW200XX_PAGE_SIZE 256
+#define AW200XX_REG(page, reg) \
+ (AW200XX_REG_PAGE0_BASE + (page) * AW200XX_PAGE_SIZE + (reg))
+#define AW200XX_REG_MAX \
+ AW200XX_REG(AW200XX_NUM_PAGES - 1, AW200XX_PAGE_SIZE - 1)
+#define AW200XX_PAGE0 0
+#define AW200XX_PAGE1 1
+#define AW200XX_PAGE2 2
+#define AW200XX_PAGE3 3
+#define AW200XX_PAGE4 4
+#define AW200XX_PAGE5 5
+
+/* Chip ID register */
+#define AW200XX_REG_IDR AW200XX_REG(AW200XX_PAGE0, 0x00)
+#define AW200XX_IDR_CHIPID 0x18
+
+/* Sleep mode register */
+#define AW200XX_REG_SLPCR AW200XX_REG(AW200XX_PAGE0, 0x01)
+#define AW200XX_SLPCR_ACTIVE 0x00
+
+/* Reset register */
+#define AW200XX_REG_RSTR AW200XX_REG(AW200XX_PAGE0, 0x02)
+#define AW200XX_RSTR_RESET 0x01
+
+/* Global current configuration register */
+#define AW200XX_REG_GCCR AW200XX_REG(AW200XX_PAGE0, 0x03)
+#define AW200XX_GCCR_IMAX_MASK GENMASK(7, 4)
+#define AW200XX_GCCR_IMAX(x) ((x) << 4)
+#define AW200XX_GCCR_ALLON BIT(3)
+
+/* Fast clear display control register */
+#define AW200XX_REG_FCD AW200XX_REG(AW200XX_PAGE0, 0x04)
+#define AW200XX_FCD_CLEAR 0x01
+
+/* Display size configuration */
+#define AW200XX_REG_DSIZE AW200XX_REG(AW200XX_PAGE0, 0x80)
+#define AW200XX_DSIZE_COLUMNS_MAX 12
+
+#define AW200XX_LED2REG(x, columns) \
+ ((x) + (((x) / (columns)) * (AW200XX_DSIZE_COLUMNS_MAX - (columns))))
+
+/*
+ * DIM current configuration register (page 4).
+ * The even address for current DIM configuration.
+ * The odd address for current FADE configuration
+ */
+#define AW200XX_REG_DIM(x, columns) \
+ AW200XX_REG(AW200XX_PAGE4, AW200XX_LED2REG(x, columns) * 2)
+#define AW200XX_REG_DIM2FADE(x) ((x) + 1)
+
+/*
+ * Duty ratio of display scan (see p.15 of datasheet for formula):
+ * duty = (592us / 600.5us) * (1 / (display_rows + 1))
+ *
+ * Multiply to 1000 (MILLI) to improve the accuracy of calculations.
+ */
+#define AW200XX_DUTY_RATIO(rows) \
+ (((592UL * USEC_PER_SEC) / 600500UL) * (MILLI / (rows)) / MILLI)
+
+struct aw200xx_chipdef {
+ u32 channels;
+ u32 display_size_rows_max;
+ u32 display_size_columns;
+};
+
+struct aw200xx_led {
+ struct led_classdev cdev;
+ struct aw200xx *chip;
+ int dim;
+ u32 num;
+};
+
+struct aw200xx {
+ const struct aw200xx_chipdef *cdef;
+ struct i2c_client *client;
+ struct regmap *regmap;
+ struct mutex mutex;
+ u32 num_leds;
+ u32 display_rows;
+ struct aw200xx_led leds[];
+};
+
+static ssize_t dim_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct led_classdev *cdev = dev_get_drvdata(dev);
+ struct aw200xx_led *led = container_of(cdev, struct aw200xx_led, cdev);
+ int dim = led->dim;
+
+ if (dim < 0)
+ return sysfs_emit(buf, "auto\n");
+
+ return sysfs_emit(buf, "%d\n", dim);
+}
+
+static ssize_t dim_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct led_classdev *cdev = dev_get_drvdata(dev);
+ struct aw200xx_led *led = container_of(cdev, struct aw200xx_led, cdev);
+ struct aw200xx *chip = led->chip;
+ u32 columns = chip->cdef->display_size_columns;
+ int dim;
+ ssize_t ret;
+
+ if (sysfs_streq(buf, "auto")) {
+ dim = -1;
+ } else {
+ ret = kstrtoint(buf, 0, &dim);
+ if (ret)
+ return ret;
+
+ if (dim > AW200XX_DIM_MAX)
+ return -EINVAL;
+ }
+
+ mutex_lock(&chip->mutex);
+
+ if (dim >= 0) {
+ ret = regmap_write(chip->regmap,
+ AW200XX_REG_DIM(led->num, columns), dim);
+ if (ret)
+ goto out_unlock;
+ }
+
+ led->dim = dim;
+ ret = count;
+
+out_unlock:
+ mutex_unlock(&chip->mutex);
+ return ret;
+}
+static DEVICE_ATTR_RW(dim);
+
+static struct attribute *dim_attrs[] = {
+ &dev_attr_dim.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(dim);
+
+static int aw200xx_brightness_set(struct led_classdev *cdev,
+ enum led_brightness brightness)
+{
+ struct aw200xx_led *led = container_of(cdev, struct aw200xx_led, cdev);
+ struct aw200xx *chip = led->chip;
+ int dim;
+ u32 reg;
+ int ret;
+
+ mutex_lock(&chip->mutex);
+
+ reg = AW200XX_REG_DIM(led->num, chip->cdef->display_size_columns);
+
+ dim = led->dim;
+ if (dim < 0)
+ dim = max_t(int,
+ brightness / (AW200XX_FADE_MAX / AW200XX_DIM_MAX),
+ 1);
+
+ ret = regmap_write(chip->regmap, reg, dim);
+ if (ret)
+ goto out_unlock;
+
+ ret = regmap_write(chip->regmap,
+ AW200XX_REG_DIM2FADE(reg), brightness);
+
+out_unlock:
+ mutex_unlock(&chip->mutex);
+
+ return ret;
+}
+
+static u32 aw200xx_imax_from_global(const struct aw200xx *const chip,
+ u32 global_imax_uA)
+{
+ u64 led_imax_uA;
+
+ /*
+ * The output current of each LED (see p.14 of datasheet for formula):
+ * Iled = Imax * (dim / 63) * ((fade + 1) / 256) * duty
+ *
+ * The value of duty is determined by the following formula:
+ * duty = (592us / 600.5us) * (1 / (display_rows + 1))
+ *
+ * Calculated for the maximum values of fade and dim.
+ * We divide by 1000 because we earlier multiplied by 1000 to improve
+ * accuracy when calculating the duty.
+ */
+ led_imax_uA = global_imax_uA * AW200XX_DUTY_RATIO(chip->display_rows);
+ do_div(led_imax_uA, MILLI);
+
+ return led_imax_uA;
+}
+
+static u32 aw200xx_imax_to_global(const struct aw200xx *const chip,
+ u32 led_imax_uA)
+{
+ u32 duty = AW200XX_DUTY_RATIO(chip->display_rows);
+
+ /* The output current of each LED (see p.14 of datasheet for formula) */
+ return (led_imax_uA * 1000U) / duty;
+}
+
+#define AW200XX_IMAX_MULTIPLIER1 10000
+#define AW200XX_IMAX_MULTIPLIER2 3333
+#define AW200XX_IMAX_BASE_VAL1 0
+#define AW200XX_IMAX_BASE_VAL2 8
+
+/*
+ * The AW200XX has a 4-bit register (GCCR) to configure the global current,
+ * which ranges from 3.3mA to 160mA. The following table indicates the values
+ * of the global current, divided into two parts:
+ *
+ * +-----------+-----------------+-----------+-----------------+
+ * | reg value | global max (mA) | reg value | global max (mA) |
+ * +-----------+-----------------+-----------+-----------------+
+ * | 0 | 10 | 8 | 3.3 |
+ * | 1 | 20 | 9 | 6.7 |
+ * | 2 | 30 | 10 | 10 |
+ * | 3 | 40 | 11 | 13.3 |
+ * | 4 | 60 | 12 | 20 |
+ * | 5 | 80 | 13 | 26.7 |
+ * | 6 | 120 | 14 | 40 |
+ * | 7 | 160 | 15 | 53.3 |
+ * +-----------+-----------------+-----------+-----------------+
+ *
+ * The left part with a multiplier of 10, and the right part with a multiplier
+ * of 3.3.
+ * So we have two formulas to calculate the global current:
+ * for the left part of the table:
+ * imax = coefficient * 10
+ *
+ * for the right part of the table:
+ * imax = coefficient * 3.3
+ *
+ * The coefficient table consists of the following values:
+ * 1, 2, 3, 4, 6, 8, 12, 16.
+ */
+static int aw200xx_set_imax(const struct aw200xx *const chip,
+ u32 led_imax_uA)
+{
+ u32 g_imax_uA = aw200xx_imax_to_global(chip, led_imax_uA);
+ u32 coeff_table[] = {1, 2, 3, 4, 6, 8, 12, 16};
+ u32 gccr_imax = UINT_MAX;
+ u32 cur_imax = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(coeff_table); i++) {
+ u32 imax;
+
+ /* select closest ones */
+ imax = coeff_table[i] * AW200XX_IMAX_MULTIPLIER1;
+ if (g_imax_uA >= imax && imax > cur_imax) {
+ cur_imax = imax;
+ gccr_imax = i + AW200XX_IMAX_BASE_VAL1;
+ }
+
+ imax = coeff_table[i] * AW200XX_IMAX_MULTIPLIER2;
+ imax = DIV_ROUND_CLOSEST(imax, 100) * 100;
+ if (g_imax_uA >= imax && imax > cur_imax) {
+ cur_imax = imax;
+ gccr_imax = i + AW200XX_IMAX_BASE_VAL2;
+ }
+ }
+
+ if (gccr_imax == UINT_MAX)
+ return -EINVAL;
+
+ return regmap_update_bits(chip->regmap, AW200XX_REG_GCCR,
+ AW200XX_GCCR_IMAX_MASK,
+ AW200XX_GCCR_IMAX(gccr_imax));
+}
+
+static int aw200xx_chip_reset(const struct aw200xx *const chip)
+{
+ int ret;
+
+ ret = regmap_write(chip->regmap, AW200XX_REG_RSTR, AW200XX_RSTR_RESET);
+ if (ret)
+ return ret;
+
+ regcache_mark_dirty(chip->regmap);
+ return regmap_write(chip->regmap, AW200XX_REG_FCD, AW200XX_FCD_CLEAR);
+}
+
+static int aw200xx_chip_init(const struct aw200xx *const chip)
+{
+ int ret;
+
+ ret = regmap_write(chip->regmap, AW200XX_REG_DSIZE,
+ chip->display_rows - 1);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(chip->regmap, AW200XX_REG_SLPCR,
+ AW200XX_SLPCR_ACTIVE);
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(chip->regmap, AW200XX_REG_GCCR,
+ AW200XX_GCCR_ALLON, AW200XX_GCCR_ALLON);
+}
+
+static int aw200xx_chip_check(const struct aw200xx *const chip)
+{
+ struct device *dev = &chip->client->dev;
+ u32 chipid;
+ int ret;
+
+ ret = regmap_read(chip->regmap, AW200XX_REG_IDR, &chipid);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read chip ID\n");
+
+ if (chipid != AW200XX_IDR_CHIPID)
+ return dev_err_probe(dev, -ENODEV,
+ "Chip reported wrong ID: %x\n", chipid);
+
+ return 0;
+}
+
+static int aw200xx_probe_fw(struct device *dev, struct aw200xx *chip)
+{
+ struct fwnode_handle *child;
+ u32 current_min, current_max, min_uA;
+ int ret;
+ int i;
+
+ ret = device_property_read_u32(dev, "awinic,display-rows",
+ &chip->display_rows);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to read 'display-rows' property\n");
+
+ if (!chip->display_rows ||
+ chip->display_rows > chip->cdef->display_size_rows_max) {
+ return dev_err_probe(dev, ret,
+ "Invalid leds display size %u\n",
+ chip->display_rows);
+ }
+
+ current_max = aw200xx_imax_from_global(chip, AW200XX_IMAX_MAX_uA);
+ current_min = aw200xx_imax_from_global(chip, AW200XX_IMAX_MIN_uA);
+ min_uA = UINT_MAX;
+ i = 0;
+
+ device_for_each_child_node(dev, child) {
+ struct led_init_data init_data = {};
+ struct aw200xx_led *led;
+ u32 source, imax;
+
+ ret = fwnode_property_read_u32(child, "reg", &source);
+ if (ret) {
+ dev_err(dev, "Missing reg property\n");
+ chip->num_leds--;
+ continue;
+ }
+
+ if (source >= chip->cdef->channels) {
+ dev_err(dev, "LED reg %u out of range (max %u)\n",
+ source, chip->cdef->channels);
+ chip->num_leds--;
+ continue;
+ }
+
+ ret = fwnode_property_read_u32(child, "led-max-microamp",
+ &imax);
+ if (ret) {
+ dev_info(&chip->client->dev,
+ "DT property led-max-microamp is missing\n");
+ } else if (imax < current_min || imax > current_max) {
+ dev_err(dev, "Invalid value %u for led-max-microamp\n",
+ imax);
+ chip->num_leds--;
+ continue;
+ } else {
+ min_uA = min(min_uA, imax);
+ }
+
+ led = &chip->leds[i];
+ led->dim = -1;
+ led->num = source;
+ led->chip = chip;
+ led->cdev.brightness_set_blocking = aw200xx_brightness_set;
+ led->cdev.groups = dim_groups;
+ init_data.fwnode = child;
+
+ ret = devm_led_classdev_register_ext(dev, &led->cdev,
+ &init_data);
+ if (ret) {
+ fwnode_handle_put(child);
+ break;
+ }
+
+ i++;
+ }
+
+ if (!chip->num_leds)
+ return -EINVAL;
+
+ if (min_uA == UINT_MAX) {
+ min_uA = aw200xx_imax_from_global(chip,
+ AW200XX_IMAX_DEFAULT_uA);
+ }
+
+ return aw200xx_set_imax(chip, min_uA);
+}
+
+static const struct regmap_range_cfg aw200xx_ranges[] = {
+ {
+ .name = "aw200xx",
+ .range_min = 0,
+ .range_max = AW200XX_REG_MAX,
+ .selector_reg = AW200XX_REG_PAGE,
+ .selector_mask = AW200XX_PAGE_MASK,
+ .selector_shift = AW200XX_PAGE_SHIFT,
+ .window_start = 0,
+ .window_len = AW200XX_PAGE_SIZE,
+ },
+};
+
+static const struct regmap_range aw200xx_writeonly_ranges[] = {
+ regmap_reg_range(AW200XX_REG(AW200XX_PAGE1, 0x00), AW200XX_REG_MAX),
+};
+
+static const struct regmap_access_table aw200xx_readable_table = {
+ .no_ranges = aw200xx_writeonly_ranges,
+ .n_no_ranges = ARRAY_SIZE(aw200xx_writeonly_ranges),
+};
+
+static const struct regmap_range aw200xx_readonly_ranges[] = {
+ regmap_reg_range(AW200XX_REG_IDR, AW200XX_REG_IDR),
+};
+
+static const struct regmap_access_table aw200xx_writeable_table = {
+ .no_ranges = aw200xx_readonly_ranges,
+ .n_no_ranges = ARRAY_SIZE(aw200xx_readonly_ranges),
+};
+
+static const struct regmap_config aw200xx_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = AW200XX_REG_MAX,
+ .ranges = aw200xx_ranges,
+ .num_ranges = ARRAY_SIZE(aw200xx_ranges),
+ .rd_table = &aw200xx_readable_table,
+ .wr_table = &aw200xx_writeable_table,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int aw200xx_probe(struct i2c_client *client)
+{
+ const struct aw200xx_chipdef *cdef;
+ struct aw200xx *chip;
+ int count;
+ int ret;
+
+ cdef = device_get_match_data(&client->dev);
+ if (!cdef)
+ return -ENODEV;
+
+ count = device_get_child_node_count(&client->dev);
+ if (!count || count > cdef->channels)
+ return dev_err_probe(&client->dev, -EINVAL,
+ "Incorrect number of leds (%d)", count);
+
+ chip = devm_kzalloc(&client->dev, struct_size(chip, leds, count),
+ GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->cdef = cdef;
+ chip->num_leds = count;
+ chip->client = client;
+ i2c_set_clientdata(client, chip);
+
+ chip->regmap = devm_regmap_init_i2c(client, &aw200xx_regmap_config);
+ if (IS_ERR(chip->regmap))
+ return PTR_ERR(chip->regmap);
+
+ ret = aw200xx_chip_check(chip);
+ if (ret)
+ return ret;
+
+ mutex_init(&chip->mutex);
+
+ /* Need a lock now since after call aw200xx_probe_fw, sysfs nodes created */
+ mutex_lock(&chip->mutex);
+
+ ret = aw200xx_chip_reset(chip);
+ if (ret)
+ goto out_unlock;
+
+ ret = aw200xx_probe_fw(&client->dev, chip);
+ if (ret)
+ goto out_unlock;
+
+ ret = aw200xx_chip_init(chip);
+
+out_unlock:
+ mutex_unlock(&chip->mutex);
+ return ret;
+}
+
+static void aw200xx_remove(struct i2c_client *client)
+{
+ struct aw200xx *chip = i2c_get_clientdata(client);
+
+ aw200xx_chip_reset(chip);
+ mutex_destroy(&chip->mutex);
+}
+
+static const struct aw200xx_chipdef aw20036_cdef = {
+ .channels = 36,
+ .display_size_rows_max = 3,
+ .display_size_columns = 12,
+};
+
+static const struct aw200xx_chipdef aw20054_cdef = {
+ .channels = 54,
+ .display_size_rows_max = 6,
+ .display_size_columns = 9,
+};
+
+static const struct aw200xx_chipdef aw20072_cdef = {
+ .channels = 72,
+ .display_size_rows_max = 6,
+ .display_size_columns = 12,
+};
+
+static const struct i2c_device_id aw200xx_id[] = {
+ { "aw20036" },
+ { "aw20054" },
+ { "aw20072" },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, aw200xx_id);
+
+static const struct of_device_id aw200xx_match_table[] = {
+ { .compatible = "awinic,aw20036", .data = &aw20036_cdef, },
+ { .compatible = "awinic,aw20054", .data = &aw20054_cdef, },
+ { .compatible = "awinic,aw20072", .data = &aw20072_cdef, },
+ {}
+};
+MODULE_DEVICE_TABLE(of, aw200xx_match_table);
+
+static struct i2c_driver aw200xx_driver = {
+ .driver = {
+ .name = "aw200xx",
+ .of_match_table = aw200xx_match_table,
+ },
+ .probe_new = aw200xx_probe,
+ .remove = aw200xx_remove,
+ .id_table = aw200xx_id,
+};
+module_i2c_driver(aw200xx_driver);
+
+MODULE_AUTHOR("Martin Kurbanov <mmkurbanov@sberdevices.ru>");
+MODULE_DESCRIPTION("AW200XX LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-aw2013.c b/drivers/leds/leds-aw2013.c
index 0b52fc9097c6..59765640b70f 100644
--- a/drivers/leds/leds-aw2013.c
+++ b/drivers/leds/leds-aw2013.c
@@ -422,7 +422,7 @@ static struct i2c_driver aw2013_driver = {
.name = "leds-aw2013",
.of_match_table = of_match_ptr(aw2013_match_table),
},
- .probe_new = aw2013_probe,
+ .probe = aw2013_probe,
.remove = aw2013_remove,
};
diff --git a/drivers/leds/leds-bd2606mvv.c b/drivers/leds/leds-bd2606mvv.c
index 76f9d4d70f9a..3fda712d2f80 100644
--- a/drivers/leds/leds-bd2606mvv.c
+++ b/drivers/leds/leds-bd2606mvv.c
@@ -150,7 +150,7 @@ static struct i2c_driver bd2606mvv_driver = {
.name = "leds-bd2606mvv",
.of_match_table = of_match_ptr(of_bd2606mvv_leds_match),
},
- .probe_new = bd2606mvv_probe,
+ .probe = bd2606mvv_probe,
};
module_i2c_driver(bd2606mvv_driver);
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c
index 601185ddabcc..0792ea126cea 100644
--- a/drivers/leds/leds-bd2802.c
+++ b/drivers/leds/leds-bd2802.c
@@ -786,7 +786,7 @@ static struct i2c_driver bd2802_i2c_driver = {
.name = "BD2802",
.pm = &bd2802_pm,
},
- .probe_new = bd2802_probe,
+ .probe = bd2802_probe,
.remove = bd2802_remove,
.id_table = bd2802_id,
};
diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c
index 37f2f32ae42d..2782da1a1930 100644
--- a/drivers/leds/leds-blinkm.c
+++ b/drivers/leds/leds-blinkm.c
@@ -561,7 +561,7 @@ static int blinkm_detect(struct i2c_client *client, struct i2c_board_info *info)
return -ENODEV;
}
- strlcpy(info->type, "blinkm", I2C_NAME_SIZE);
+ strscpy(info->type, "blinkm", I2C_NAME_SIZE);
return 0;
}
@@ -730,7 +730,7 @@ static struct i2c_driver blinkm_driver = {
.driver = {
.name = "blinkm",
},
- .probe_new = blinkm_probe,
+ .probe = blinkm_probe,
.remove = blinkm_remove,
.id_table = blinkm_id,
.detect = blinkm_detect,
diff --git a/drivers/leds/leds-cht-wcove.c b/drivers/leds/leds-cht-wcove.c
new file mode 100644
index 000000000000..b4998402b8c6
--- /dev/null
+++ b/drivers/leds/leds-cht-wcove.c
@@ -0,0 +1,476 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for LEDs connected to the Intel Cherry Trail Whiskey Cove PMIC
+ *
+ * Copyright 2019 Yauhen Kharuzhy <jekhor@gmail.com>
+ * Copyright 2023 Hans de Goede <hansg@kernel.org>
+ *
+ * Register info comes from the Lenovo Yoga Book Android opensource code
+ * available from Lenovo. File lenovo_yb1_x90f_l_osc_201803.7z path in the 7z:
+ * YB1_source_code/kernel/cht/drivers/misc/charger_gp_led.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/suspend.h>
+
+#define CHT_WC_LED1_CTRL 0x5e1f
+#define CHT_WC_LED1_FSM 0x5e20
+#define CHT_WC_LED1_PWM 0x5e21
+
+#define CHT_WC_LED2_CTRL 0x4fdf
+#define CHT_WC_LED2_FSM 0x4fe0
+#define CHT_WC_LED2_PWM 0x4fe1
+
+#define CHT_WC_LED1_SWCTL BIT(0) /* HW or SW control of charging led */
+#define CHT_WC_LED1_ON BIT(1)
+
+#define CHT_WC_LED2_ON BIT(0)
+#define CHT_WC_LED_I_MA2_5 (2 << 2) /* LED current limit */
+#define CHT_WC_LED_I_MASK GENMASK(3, 2) /* LED current limit mask */
+
+#define CHT_WC_LED_F_1_4_HZ (0 << 4)
+#define CHT_WC_LED_F_1_2_HZ (1 << 4)
+#define CHT_WC_LED_F_1_HZ (2 << 4)
+#define CHT_WC_LED_F_2_HZ (3 << 4)
+#define CHT_WC_LED_F_MASK GENMASK(5, 4)
+
+#define CHT_WC_LED_EFF_OFF (0 << 1)
+#define CHT_WC_LED_EFF_ON (1 << 1)
+#define CHT_WC_LED_EFF_BLINKING (2 << 1)
+#define CHT_WC_LED_EFF_BREATHING (3 << 1)
+#define CHT_WC_LED_EFF_MASK GENMASK(2, 1)
+
+#define CHT_WC_LED_COUNT 2
+
+struct cht_wc_led_regs {
+ /* Register addresses */
+ u16 ctrl;
+ u16 fsm;
+ u16 pwm;
+ /* Mask + values for turning the LED on/off */
+ u8 on_off_mask;
+ u8 on_val;
+ u8 off_val;
+};
+
+struct cht_wc_led_saved_regs {
+ unsigned int ctrl;
+ unsigned int fsm;
+ unsigned int pwm;
+};
+
+struct cht_wc_led {
+ struct led_classdev cdev;
+ const struct cht_wc_led_regs *regs;
+ struct regmap *regmap;
+ struct mutex mutex;
+ struct cht_wc_led_saved_regs saved_regs;
+};
+
+struct cht_wc_leds {
+ struct cht_wc_led leds[CHT_WC_LED_COUNT];
+ /* Saved LED1 initial register values */
+ struct cht_wc_led_saved_regs led1_initial_regs;
+};
+
+static const struct cht_wc_led_regs cht_wc_led_regs[CHT_WC_LED_COUNT] = {
+ {
+ .ctrl = CHT_WC_LED1_CTRL,
+ .fsm = CHT_WC_LED1_FSM,
+ .pwm = CHT_WC_LED1_PWM,
+ .on_off_mask = CHT_WC_LED1_SWCTL | CHT_WC_LED1_ON,
+ .on_val = CHT_WC_LED1_SWCTL | CHT_WC_LED1_ON,
+ .off_val = CHT_WC_LED1_SWCTL,
+ },
+ {
+ .ctrl = CHT_WC_LED2_CTRL,
+ .fsm = CHT_WC_LED2_FSM,
+ .pwm = CHT_WC_LED2_PWM,
+ .on_off_mask = CHT_WC_LED2_ON,
+ .on_val = CHT_WC_LED2_ON,
+ .off_val = 0,
+ },
+};
+
+static const char * const cht_wc_leds_names[CHT_WC_LED_COUNT] = {
+ "platform::" LED_FUNCTION_CHARGING,
+ "platform::" LED_FUNCTION_INDICATOR,
+};
+
+static int cht_wc_leds_brightness_set(struct led_classdev *cdev,
+ enum led_brightness value)
+{
+ struct cht_wc_led *led = container_of(cdev, struct cht_wc_led, cdev);
+ int ret;
+
+ mutex_lock(&led->mutex);
+
+ if (!value) {
+ ret = regmap_update_bits(led->regmap, led->regs->ctrl,
+ led->regs->on_off_mask, led->regs->off_val);
+ if (ret < 0) {
+ dev_err(cdev->dev, "Failed to turn off: %d\n", ret);
+ goto out;
+ }
+
+ /* Disable HW blinking */
+ ret = regmap_update_bits(led->regmap, led->regs->fsm,
+ CHT_WC_LED_EFF_MASK, CHT_WC_LED_EFF_ON);
+ if (ret < 0)
+ dev_err(cdev->dev, "Failed to update LED FSM reg: %d\n", ret);
+ } else {
+ ret = regmap_write(led->regmap, led->regs->pwm, value);
+ if (ret < 0) {
+ dev_err(cdev->dev, "Failed to set brightness: %d\n", ret);
+ goto out;
+ }
+
+ ret = regmap_update_bits(led->regmap, led->regs->ctrl,
+ led->regs->on_off_mask, led->regs->on_val);
+ if (ret < 0)
+ dev_err(cdev->dev, "Failed to turn on: %d\n", ret);
+ }
+out:
+ mutex_unlock(&led->mutex);
+ return ret;
+}
+
+static enum led_brightness cht_wc_leds_brightness_get(struct led_classdev *cdev)
+{
+ struct cht_wc_led *led = container_of(cdev, struct cht_wc_led, cdev);
+ unsigned int val;
+ int ret;
+
+ mutex_lock(&led->mutex);
+
+ ret = regmap_read(led->regmap, led->regs->ctrl, &val);
+ if (ret < 0) {
+ dev_err(cdev->dev, "Failed to read LED CTRL reg: %d\n", ret);
+ ret = 0;
+ goto done;
+ }
+
+ val &= led->regs->on_off_mask;
+ if (val != led->regs->on_val) {
+ ret = 0;
+ goto done;
+ }
+
+ ret = regmap_read(led->regmap, led->regs->pwm, &val);
+ if (ret < 0) {
+ dev_err(cdev->dev, "Failed to read LED PWM reg: %d\n", ret);
+ ret = 0;
+ goto done;
+ }
+
+ ret = val;
+done:
+ mutex_unlock(&led->mutex);
+
+ return ret;
+}
+
+/* Return blinking period for given CTRL reg value */
+static unsigned long cht_wc_leds_get_period(int ctrl)
+{
+ ctrl &= CHT_WC_LED_F_MASK;
+
+ switch (ctrl) {
+ case CHT_WC_LED_F_1_4_HZ:
+ return 1000 * 4;
+ case CHT_WC_LED_F_1_2_HZ:
+ return 1000 * 2;
+ case CHT_WC_LED_F_1_HZ:
+ return 1000;
+ case CHT_WC_LED_F_2_HZ:
+ return 1000 / 2;
+ }
+
+ return 0;
+}
+
+/*
+ * Find suitable hardware blink mode for given period.
+ * period < 750 ms - select 2 HZ
+ * 750 ms <= period < 1500 ms - select 1 HZ
+ * 1500 ms <= period < 3000 ms - select 1/2 HZ
+ * 3000 ms <= period < 5000 ms - select 1/4 HZ
+ * 5000 ms <= period - return -1
+ */
+static int cht_wc_leds_find_freq(unsigned long period)
+{
+ if (period < 750)
+ return CHT_WC_LED_F_2_HZ;
+ else if (period < 1500)
+ return CHT_WC_LED_F_1_HZ;
+ else if (period < 3000)
+ return CHT_WC_LED_F_1_2_HZ;
+ else if (period < 5000)
+ return CHT_WC_LED_F_1_4_HZ;
+ else
+ return -1;
+}
+
+static int cht_wc_leds_set_effect(struct led_classdev *cdev,
+ unsigned long *delay_on,
+ unsigned long *delay_off,
+ u8 effect)
+{
+ struct cht_wc_led *led = container_of(cdev, struct cht_wc_led, cdev);
+ int ctrl, ret;
+
+ mutex_lock(&led->mutex);
+
+ /* Blink with 1 Hz as default if nothing specified */
+ if (!*delay_on && !*delay_off)
+ *delay_on = *delay_off = 500;
+
+ ctrl = cht_wc_leds_find_freq(*delay_on + *delay_off);
+ if (ctrl < 0) {
+ /* Disable HW blinking */
+ ret = regmap_update_bits(led->regmap, led->regs->fsm,
+ CHT_WC_LED_EFF_MASK, CHT_WC_LED_EFF_ON);
+ if (ret < 0)
+ dev_err(cdev->dev, "Failed to update LED FSM reg: %d\n", ret);
+
+ /* Fallback to software timer */
+ *delay_on = *delay_off = 0;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = regmap_update_bits(led->regmap, led->regs->fsm,
+ CHT_WC_LED_EFF_MASK, effect);
+ if (ret < 0)
+ dev_err(cdev->dev, "Failed to update LED FSM reg: %d\n", ret);
+
+ /* Set the frequency and make sure the LED is on */
+ ret = regmap_update_bits(led->regmap, led->regs->ctrl,
+ CHT_WC_LED_F_MASK | led->regs->on_off_mask,
+ ctrl | led->regs->on_val);
+ if (ret < 0)
+ dev_err(cdev->dev, "Failed to update LED CTRL reg: %d\n", ret);
+
+ *delay_off = *delay_on = cht_wc_leds_get_period(ctrl) / 2;
+
+done:
+ mutex_unlock(&led->mutex);
+
+ return ret;
+}
+
+static int cht_wc_leds_blink_set(struct led_classdev *cdev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ u8 effect = CHT_WC_LED_EFF_BLINKING;
+
+ /*
+ * The desired default behavior of LED1 / the charge LED is breathing
+ * while charging and on/solid when full. Since triggers cannot select
+ * breathing, blink_set() gets called when charging. Use slow breathing
+ * when the default "charging-blink-full-solid" trigger is used to
+ * achieve the desired default behavior.
+ */
+ if (cdev->flags & LED_INIT_DEFAULT_TRIGGER) {
+ *delay_on = *delay_off = 1000;
+ effect = CHT_WC_LED_EFF_BREATHING;
+ }
+
+ return cht_wc_leds_set_effect(cdev, delay_on, delay_off, effect);
+}
+
+static int cht_wc_leds_pattern_set(struct led_classdev *cdev,
+ struct led_pattern *pattern,
+ u32 len, int repeat)
+{
+ unsigned long delay_off, delay_on;
+
+ if (repeat > 0 || len != 2 ||
+ pattern[0].brightness != 0 || pattern[1].brightness != 1 ||
+ pattern[0].delta_t != pattern[1].delta_t ||
+ (pattern[0].delta_t != 250 && pattern[0].delta_t != 500 &&
+ pattern[0].delta_t != 1000 && pattern[0].delta_t != 2000))
+ return -EINVAL;
+
+ delay_off = pattern[0].delta_t;
+ delay_on = pattern[1].delta_t;
+
+ return cht_wc_leds_set_effect(cdev, &delay_on, &delay_off, CHT_WC_LED_EFF_BREATHING);
+}
+
+static int cht_wc_leds_pattern_clear(struct led_classdev *cdev)
+{
+ return cht_wc_leds_brightness_set(cdev, 0);
+}
+
+static int cht_wc_led_save_regs(struct cht_wc_led *led,
+ struct cht_wc_led_saved_regs *saved_regs)
+{
+ int ret;
+
+ ret = regmap_read(led->regmap, led->regs->ctrl, &saved_regs->ctrl);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_read(led->regmap, led->regs->fsm, &saved_regs->fsm);
+ if (ret < 0)
+ return ret;
+
+ return regmap_read(led->regmap, led->regs->pwm, &saved_regs->pwm);
+}
+
+static void cht_wc_led_restore_regs(struct cht_wc_led *led,
+ const struct cht_wc_led_saved_regs *saved_regs)
+{
+ regmap_write(led->regmap, led->regs->ctrl, saved_regs->ctrl);
+ regmap_write(led->regmap, led->regs->fsm, saved_regs->fsm);
+ regmap_write(led->regmap, led->regs->pwm, saved_regs->pwm);
+}
+
+static int cht_wc_leds_probe(struct platform_device *pdev)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
+ struct cht_wc_leds *leds;
+ int ret;
+ int i;
+
+ /*
+ * On the Lenovo Yoga Tab 3 the LED1 driver output is actually
+ * connected to a haptic feedback motor rather then a LED.
+ * So do not register a LED classdev there (LED2 is unused).
+ */
+ if (pmic->cht_wc_model == INTEL_CHT_WC_LENOVO_YT3_X90)
+ return -ENODEV;
+
+ leds = devm_kzalloc(&pdev->dev, sizeof(*leds), GFP_KERNEL);
+ if (!leds)
+ return -ENOMEM;
+
+ /*
+ * LED1 might be in hw-controlled mode when this driver gets loaded; and
+ * since the PMIC is always powered by the battery any changes made are
+ * permanent. Save LED1 regs to restore them on remove() or shutdown().
+ */
+ leds->leds[0].regs = &cht_wc_led_regs[0];
+ leds->leds[0].regmap = pmic->regmap;
+ ret = cht_wc_led_save_regs(&leds->leds[0], &leds->led1_initial_regs);
+ if (ret < 0)
+ return ret;
+
+ /* Set LED1 default trigger based on machine model */
+ switch (pmic->cht_wc_model) {
+ case INTEL_CHT_WC_GPD_WIN_POCKET:
+ leds->leds[0].cdev.default_trigger = "max170xx_battery-charging-blink-full-solid";
+ break;
+ case INTEL_CHT_WC_XIAOMI_MIPAD2:
+ leds->leds[0].cdev.default_trigger = "bq27520-0-charging-blink-full-solid";
+ break;
+ case INTEL_CHT_WC_LENOVO_YOGABOOK1:
+ leds->leds[0].cdev.default_trigger = "bq27542-0-charging-blink-full-solid";
+ break;
+ default:
+ dev_warn(&pdev->dev, "Unknown model, no default charging trigger\n");
+ break;
+ }
+
+ for (i = 0; i < CHT_WC_LED_COUNT; i++) {
+ struct cht_wc_led *led = &leds->leds[i];
+
+ led->regs = &cht_wc_led_regs[i];
+ led->regmap = pmic->regmap;
+ mutex_init(&led->mutex);
+ led->cdev.name = cht_wc_leds_names[i];
+ led->cdev.brightness_set_blocking = cht_wc_leds_brightness_set;
+ led->cdev.brightness_get = cht_wc_leds_brightness_get;
+ led->cdev.blink_set = cht_wc_leds_blink_set;
+ led->cdev.pattern_set = cht_wc_leds_pattern_set;
+ led->cdev.pattern_clear = cht_wc_leds_pattern_clear;
+ led->cdev.max_brightness = 255;
+
+ ret = led_classdev_register(&pdev->dev, &led->cdev);
+ if (ret < 0)
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, leds);
+ return 0;
+}
+
+static void cht_wc_leds_remove(struct platform_device *pdev)
+{
+ struct cht_wc_leds *leds = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < CHT_WC_LED_COUNT; i++)
+ led_classdev_unregister(&leds->leds[i].cdev);
+
+ /* Restore LED1 regs if hw-control was active else leave LED1 off */
+ if (!(leds->led1_initial_regs.ctrl & CHT_WC_LED1_SWCTL))
+ cht_wc_led_restore_regs(&leds->leds[0], &leds->led1_initial_regs);
+}
+
+static void cht_wc_leds_disable(struct platform_device *pdev)
+{
+ struct cht_wc_leds *leds = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < CHT_WC_LED_COUNT; i++)
+ cht_wc_leds_brightness_set(&leds->leds[i].cdev, 0);
+
+ /* Restore LED1 regs if hw-control was active else leave LED1 off */
+ if (!(leds->led1_initial_regs.ctrl & CHT_WC_LED1_SWCTL))
+ cht_wc_led_restore_regs(&leds->leds[0], &leds->led1_initial_regs);
+}
+
+/* On suspend save current settings and turn LEDs off */
+static int cht_wc_leds_suspend(struct device *dev)
+{
+ struct cht_wc_leds *leds = dev_get_drvdata(dev);
+ int i, ret;
+
+ for (i = 0; i < CHT_WC_LED_COUNT; i++) {
+ ret = cht_wc_led_save_regs(&leds->leds[i], &leds->leds[i].saved_regs);
+ if (ret < 0)
+ return ret;
+ }
+
+ cht_wc_leds_disable(to_platform_device(dev));
+ return 0;
+}
+
+/* On resume restore the saved settings */
+static int cht_wc_leds_resume(struct device *dev)
+{
+ struct cht_wc_leds *leds = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < CHT_WC_LED_COUNT; i++)
+ cht_wc_led_restore_regs(&leds->leds[i], &leds->leds[i].saved_regs);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(cht_wc_leds_pm, cht_wc_leds_suspend, cht_wc_leds_resume);
+
+static struct platform_driver cht_wc_leds_driver = {
+ .probe = cht_wc_leds_probe,
+ .remove_new = cht_wc_leds_remove,
+ .shutdown = cht_wc_leds_disable,
+ .driver = {
+ .name = "cht_wcove_leds",
+ .pm = pm_sleep_ptr(&cht_wc_leds_pm),
+ },
+};
+module_platform_driver(cht_wc_leds_driver);
+
+MODULE_ALIAS("platform:cht_wcove_leds");
+MODULE_DESCRIPTION("Intel Cherry Trail Whiskey Cove PMIC LEDs driver");
+MODULE_AUTHOR("Yauhen Kharuzhy <jekhor@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index ce4e79939731..7bfe40a6bfdd 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -13,6 +13,7 @@
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
@@ -77,6 +78,7 @@ static int create_gpio_led(const struct gpio_led *template,
struct fwnode_handle *fwnode, gpio_blink_set_t blink_set)
{
struct led_init_data init_data = {};
+ struct pinctrl *pinctrl;
int ret, state;
led_dat->cdev.default_trigger = template->default_trigger;
@@ -119,6 +121,22 @@ static int create_gpio_led(const struct gpio_led *template,
&init_data);
}
+ if (ret)
+ return ret;
+
+ pinctrl = devm_pinctrl_get_select_default(led_dat->cdev.dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ if (ret != -ENODEV) {
+ dev_warn(led_dat->cdev.dev,
+ "Failed to select %pOF pinctrl: %d\n",
+ to_of_node(fwnode), ret);
+ } else {
+ /* pinctrl-%d not present, not an error */
+ ret = 0;
+ }
+ }
+
return ret;
}
diff --git a/drivers/leds/leds-is31fl319x.c b/drivers/leds/leds-is31fl319x.c
index 7c908414ac7e..66c65741202e 100644
--- a/drivers/leds/leds-is31fl319x.c
+++ b/drivers/leds/leds-is31fl319x.c
@@ -602,7 +602,7 @@ static struct i2c_driver is31fl319x_driver = {
.name = "leds-is31fl319x",
.of_match_table = of_is31fl319x_match,
},
- .probe_new = is31fl319x_probe,
+ .probe = is31fl319x_probe,
.id_table = is31fl319x_id,
};
diff --git a/drivers/leds/leds-is31fl32xx.c b/drivers/leds/leds-is31fl32xx.c
index 799191859ce0..72cb56d305c4 100644
--- a/drivers/leds/leds-is31fl32xx.c
+++ b/drivers/leds/leds-is31fl32xx.c
@@ -488,7 +488,7 @@ static struct i2c_driver is31fl32xx_driver = {
.name = "is31fl32xx",
.of_match_table = of_is31fl32xx_match,
},
- .probe_new = is31fl32xx_probe,
+ .probe = is31fl32xx_probe,
.remove = is31fl32xx_remove,
.id_table = is31fl32xx_id,
};
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index a9a2018592ff..a2feef8e4ac5 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -484,7 +484,7 @@ static const struct i2c_device_id lm3530_id[] = {
MODULE_DEVICE_TABLE(i2c, lm3530_id);
static struct i2c_driver lm3530_i2c_driver = {
- .probe_new = lm3530_probe,
+ .probe = lm3530_probe,
.remove = lm3530_remove,
.id_table = lm3530_id,
.driver = {
diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c
index a08c09129a68..13662a4aa1f2 100644
--- a/drivers/leds/leds-lm3532.c
+++ b/drivers/leds/leds-lm3532.c
@@ -726,7 +726,7 @@ static const struct i2c_device_id lm3532_id[] = {
MODULE_DEVICE_TABLE(i2c, lm3532_id);
static struct i2c_driver lm3532_i2c_driver = {
- .probe_new = lm3532_probe,
+ .probe = lm3532_probe,
.remove = lm3532_remove,
.id_table = lm3532_id,
.driver = {
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
index 612873070ca4..f68771b9eac6 100644
--- a/drivers/leds/leds-lm355x.c
+++ b/drivers/leds/leds-lm355x.c
@@ -516,7 +516,7 @@ static struct i2c_driver lm355x_i2c_driver = {
.name = LM355x_NAME,
.pm = NULL,
},
- .probe_new = lm355x_probe,
+ .probe = lm355x_probe,
.remove = lm355x_remove,
.id_table = lm355x_id,
};
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
index b75ee3546c2e..6eee52e211be 100644
--- a/drivers/leds/leds-lm3642.c
+++ b/drivers/leds/leds-lm3642.c
@@ -401,7 +401,7 @@ static struct i2c_driver lm3642_i2c_driver = {
.name = LM3642_NAME,
.pm = NULL,
},
- .probe_new = lm3642_probe,
+ .probe = lm3642_probe,
.remove = lm3642_remove,
.id_table = lm3642_id,
};
diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c
index 66126d0666f5..f8ad61e47a19 100644
--- a/drivers/leds/leds-lm3692x.c
+++ b/drivers/leds/leds-lm3692x.c
@@ -518,7 +518,7 @@ static struct i2c_driver lm3692x_driver = {
.name = "lm3692x",
.of_match_table = of_lm3692x_leds_match,
},
- .probe_new = lm3692x_probe,
+ .probe = lm3692x_probe,
.remove = lm3692x_remove,
.id_table = lm3692x_id,
};
diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c
index 10e904bf40a0..cfb8ac220db6 100644
--- a/drivers/leds/leds-lm3697.c
+++ b/drivers/leds/leds-lm3697.c
@@ -376,7 +376,7 @@ static struct i2c_driver lm3697_driver = {
.name = "lm3697",
.of_match_table = of_lm3697_leds_match,
},
- .probe_new = lm3697_probe,
+ .probe = lm3697_probe,
.remove = lm3697_remove,
.id_table = lm3697_id,
};
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
index be47c66b2e00..8ea746c499d1 100644
--- a/drivers/leds/leds-lp3944.c
+++ b/drivers/leds/leds-lp3944.c
@@ -427,7 +427,7 @@ static struct i2c_driver lp3944_driver = {
.driver = {
.name = "lp3944",
},
- .probe_new = lp3944_probe,
+ .probe = lp3944_probe,
.remove = lp3944_remove,
.id_table = lp3944_id,
};
diff --git a/drivers/leds/leds-lp3952.c b/drivers/leds/leds-lp3952.c
index 24b2e0f9080d..3bd55652a706 100644
--- a/drivers/leds/leds-lp3952.c
+++ b/drivers/leds/leds-lp3952.c
@@ -273,7 +273,7 @@ static struct i2c_driver lp3952_i2c_driver = {
.driver = {
.name = LP3952_NAME,
},
- .probe_new = lp3952_probe,
+ .probe = lp3952_probe,
.remove = lp3952_remove,
.id_table = lp3952_id,
};
diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c
index 28d6b39fa72d..68c4d9967d68 100644
--- a/drivers/leds/leds-lp50xx.c
+++ b/drivers/leds/leds-lp50xx.c
@@ -608,7 +608,7 @@ static struct i2c_driver lp50xx_driver = {
.name = "lp50xx",
.of_match_table = of_lp50xx_leds_match,
},
- .probe_new = lp50xx_probe,
+ .probe = lp50xx_probe,
.remove = lp50xx_remove,
.id_table = lp50xx_id,
};
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index a004af8e22c7..030c040fdf6d 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -58,14 +58,11 @@
/* CONFIG register */
#define LP5521_PWM_HF 0x40 /* PWM: 0 = 256Hz, 1 = 558Hz */
#define LP5521_PWRSAVE_EN 0x20 /* 1 = Power save mode */
-#define LP5521_CP_MODE_OFF 0 /* Charge pump (CP) off */
-#define LP5521_CP_MODE_BYPASS 8 /* CP forced to bypass mode */
-#define LP5521_CP_MODE_1X5 0x10 /* CP forced to 1.5x mode */
-#define LP5521_CP_MODE_AUTO 0x18 /* Automatic mode selection */
+#define LP5521_CP_MODE_MASK 0x18 /* Charge pump mode */
+#define LP5521_CP_MODE_SHIFT 3
#define LP5521_R_TO_BATT 0x04 /* R out: 0 = CP, 1 = Vbat */
#define LP5521_CLK_INT 0x01 /* Internal clock */
-#define LP5521_DEFAULT_CFG \
- (LP5521_PWM_HF | LP5521_PWRSAVE_EN | LP5521_CP_MODE_AUTO)
+#define LP5521_DEFAULT_CFG (LP5521_PWM_HF | LP5521_PWRSAVE_EN)
/* Status */
#define LP5521_EXT_CLK_USED 0x08
@@ -310,6 +307,8 @@ static int lp5521_post_init_device(struct lp55xx_chip *chip)
if (!lp55xx_is_extclk_used(chip))
val |= LP5521_CLK_INT;
+ val |= (chip->pdata->charge_pump_mode << LP5521_CP_MODE_SHIFT) & LP5521_CP_MODE_MASK;
+
ret = lp55xx_write(chip, LP5521_REG_CONFIG, val);
if (ret)
return ret;
@@ -608,7 +607,7 @@ static struct i2c_driver lp5521_driver = {
.name = "lp5521",
.of_match_table = of_match_ptr(of_lp5521_leds_match),
},
- .probe_new = lp5521_probe,
+ .probe = lp5521_probe,
.remove = lp5521_remove,
.id_table = lp5521_id,
};
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 55da914b8e5c..daa6a165fba6 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -57,8 +57,11 @@
#define LP5523_AUTO_INC 0x40
#define LP5523_PWR_SAVE 0x20
#define LP5523_PWM_PWR_SAVE 0x04
-#define LP5523_CP_AUTO 0x18
+#define LP5523_CP_MODE_MASK 0x18
+#define LP5523_CP_MODE_SHIFT 3
#define LP5523_AUTO_CLK 0x02
+#define LP5523_DEFAULT_CONFIG \
+ (LP5523_AUTO_INC | LP5523_PWR_SAVE | LP5523_AUTO_CLK | LP5523_PWM_PWR_SAVE)
#define LP5523_EN_LEDTEST 0x80
#define LP5523_LEDTEST_DONE 0x80
@@ -125,6 +128,7 @@ static void lp5523_set_led_current(struct lp55xx_led *led, u8 led_current)
static int lp5523_post_init_device(struct lp55xx_chip *chip)
{
int ret;
+ int val;
ret = lp55xx_write(chip, LP5523_REG_ENABLE, LP5523_ENABLE);
if (ret)
@@ -133,10 +137,10 @@ static int lp5523_post_init_device(struct lp55xx_chip *chip)
/* Chip startup time is 500 us, 1 - 2 ms gives some margin */
usleep_range(1000, 2000);
- ret = lp55xx_write(chip, LP5523_REG_CONFIG,
- LP5523_AUTO_INC | LP5523_PWR_SAVE |
- LP5523_CP_AUTO | LP5523_AUTO_CLK |
- LP5523_PWM_PWR_SAVE);
+ val = LP5523_DEFAULT_CONFIG;
+ val |= (chip->pdata->charge_pump_mode << LP5523_CP_MODE_SHIFT) & LP5523_CP_MODE_MASK;
+
+ ret = lp55xx_write(chip, LP5523_REG_CONFIG, val);
if (ret)
return ret;
@@ -983,7 +987,7 @@ static struct i2c_driver lp5523_driver = {
.name = "lp5523x",
.of_match_table = of_match_ptr(of_lp5523_leds_match),
},
- .probe_new = lp5523_probe,
+ .probe = lp5523_probe,
.remove = lp5523_remove,
.id_table = lp5523_id,
};
diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c
index b5d877faf6d7..4565cc12cea8 100644
--- a/drivers/leds/leds-lp5562.c
+++ b/drivers/leds/leds-lp5562.c
@@ -603,7 +603,7 @@ static struct i2c_driver lp5562_driver = {
.name = "lp5562",
.of_match_table = of_match_ptr(of_lp5562_leds_match),
},
- .probe_new = lp5562_probe,
+ .probe = lp5562_probe,
.remove = lp5562_remove,
.id_table = lp5562_id,
};
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index c1940964067a..77bb26906ea6 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -18,6 +18,7 @@
#include <linux/platform_data/leds-lp55xx.h>
#include <linux/slab.h>
#include <linux/gpio/consumer.h>
+#include <dt-bindings/leds/leds-lp55xx.h>
#include "leds-lp55xx-common.h"
@@ -691,6 +692,14 @@ struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,
i++;
}
+ if (of_property_read_u32(np, "ti,charge-pump-mode", &pdata->charge_pump_mode))
+ pdata->charge_pump_mode = LP55XX_CP_AUTO;
+
+ if (pdata->charge_pump_mode > LP55XX_CP_AUTO) {
+ dev_err(dev, "invalid charge pump mode %d\n", pdata->charge_pump_mode);
+ return ERR_PTR(-EINVAL);
+ }
+
of_property_read_string(np, "label", &pdata->label);
of_property_read_u8(np, "clock-mode", &pdata->clock_mode);
diff --git a/drivers/leds/leds-lp8501.c b/drivers/leds/leds-lp8501.c
index 165d6423a928..f11886aa8965 100644
--- a/drivers/leds/leds-lp8501.c
+++ b/drivers/leds/leds-lp8501.c
@@ -53,10 +53,10 @@
#define LP8501_PWM_PSAVE BIT(7)
#define LP8501_AUTO_INC BIT(6)
#define LP8501_PWR_SAVE BIT(5)
-#define LP8501_CP_AUTO 0x18
+#define LP8501_CP_MODE_MASK 0x18
+#define LP8501_CP_MODE_SHIFT 3
#define LP8501_INT_CLK BIT(0)
-#define LP8501_DEFAULT_CFG \
- (LP8501_PWM_PSAVE | LP8501_AUTO_INC | LP8501_PWR_SAVE | LP8501_CP_AUTO)
+#define LP8501_DEFAULT_CFG (LP8501_PWM_PSAVE | LP8501_AUTO_INC | LP8501_PWR_SAVE)
#define LP8501_REG_RESET 0x3D
#define LP8501_RESET 0xFF
@@ -102,6 +102,8 @@ static int lp8501_post_init_device(struct lp55xx_chip *chip)
if (chip->pdata->clock_mode != LP55XX_CLOCK_EXT)
val |= LP8501_INT_CLK;
+ val |= (chip->pdata->charge_pump_mode << LP8501_CP_MODE_SHIFT) & LP8501_CP_MODE_MASK;
+
ret = lp55xx_write(chip, LP8501_REG_CONFIG, val);
if (ret)
return ret;
@@ -392,7 +394,7 @@ static struct i2c_driver lp8501_driver = {
.name = "lp8501",
.of_match_table = of_match_ptr(of_lp8501_leds_match),
},
- .probe_new = lp8501_probe,
+ .probe = lp8501_probe,
.remove = lp8501_remove,
.id_table = lp8501_id,
};
diff --git a/drivers/leds/leds-lp8860.c b/drivers/leds/leds-lp8860.c
index 221b386443bc..19b621012e58 100644
--- a/drivers/leds/leds-lp8860.c
+++ b/drivers/leds/leds-lp8860.c
@@ -475,7 +475,7 @@ static struct i2c_driver lp8860_driver = {
.name = "lp8860",
.of_match_table = of_lp8860_leds_match,
},
- .probe_new = lp8860_probe,
+ .probe = lp8860_probe,
.remove = lp8860_remove,
.id_table = lp8860_id,
};
diff --git a/drivers/leds/leds-mt6323.c b/drivers/leds/leds-mt6323.c
index 17ee88043f52..24f35bdb55fb 100644
--- a/drivers/leds/leds-mt6323.c
+++ b/drivers/leds/leds-mt6323.c
@@ -14,61 +14,54 @@
#include <linux/regmap.h>
/*
- * Register field for MT6323_TOP_CKPDN0 to enable
+ * Register field for TOP_CKPDN0 to enable
* 32K clock common for LED device.
*/
-#define MT6323_RG_DRV_32K_CK_PDN BIT(11)
-#define MT6323_RG_DRV_32K_CK_PDN_MASK BIT(11)
+#define RG_DRV_32K_CK_PDN BIT(11)
+#define RG_DRV_32K_CK_PDN_MASK BIT(11)
+
+/* 32K/1M/6M clock common for WLED device */
+#define RG_VWLED_1M_CK_PDN BIT(0)
+#define RG_VWLED_32K_CK_PDN BIT(12)
+#define RG_VWLED_6M_CK_PDN BIT(13)
/*
- * Register field for MT6323_TOP_CKPDN2 to enable
+ * Register field for TOP_CKPDN2 to enable
* individual clock for LED device.
*/
-#define MT6323_RG_ISINK_CK_PDN(i) BIT(i)
-#define MT6323_RG_ISINK_CK_PDN_MASK(i) BIT(i)
+#define RG_ISINK_CK_PDN(i) BIT(i)
+#define RG_ISINK_CK_PDN_MASK(i) BIT(i)
/*
- * Register field for MT6323_TOP_CKCON1 to select
+ * Register field for TOP_CKCON1 to select
* clock source.
*/
-#define MT6323_RG_ISINK_CK_SEL_MASK(i) (BIT(10) << (i))
+#define RG_ISINK_CK_SEL_MASK(i) (BIT(10) << (i))
-/*
- * Register for MT6323_ISINK_CON0 to setup the
- * duty cycle of the blink.
- */
-#define MT6323_ISINK_CON0(i) (MT6323_ISINK0_CON0 + 0x8 * (i))
-#define MT6323_ISINK_DIM_DUTY_MASK (0x1f << 8)
-#define MT6323_ISINK_DIM_DUTY(i) (((i) << 8) & \
- MT6323_ISINK_DIM_DUTY_MASK)
-
-/* Register to setup the period of the blink. */
-#define MT6323_ISINK_CON1(i) (MT6323_ISINK0_CON1 + 0x8 * (i))
-#define MT6323_ISINK_DIM_FSEL_MASK (0xffff)
-#define MT6323_ISINK_DIM_FSEL(i) ((i) & MT6323_ISINK_DIM_FSEL_MASK)
-
-/* Register to control the brightness. */
-#define MT6323_ISINK_CON2(i) (MT6323_ISINK0_CON2 + 0x8 * (i))
-#define MT6323_ISINK_CH_STEP_SHIFT 12
-#define MT6323_ISINK_CH_STEP_MASK (0x7 << 12)
-#define MT6323_ISINK_CH_STEP(i) (((i) << 12) & \
- MT6323_ISINK_CH_STEP_MASK)
-#define MT6323_ISINK_SFSTR0_TC_MASK (0x3 << 1)
-#define MT6323_ISINK_SFSTR0_TC(i) (((i) << 1) & \
- MT6323_ISINK_SFSTR0_TC_MASK)
-#define MT6323_ISINK_SFSTR0_EN_MASK BIT(0)
-#define MT6323_ISINK_SFSTR0_EN BIT(0)
+#define ISINK_CON(r, i) (r + 0x8 * (i))
+
+/* ISINK_CON0: Register to setup the duty cycle of the blink. */
+#define ISINK_DIM_DUTY_MASK (0x1f << 8)
+#define ISINK_DIM_DUTY(i) (((i) << 8) & ISINK_DIM_DUTY_MASK)
+
+/* ISINK_CON1: Register to setup the period of the blink. */
+#define ISINK_DIM_FSEL_MASK (0xffff)
+#define ISINK_DIM_FSEL(i) ((i) & ISINK_DIM_FSEL_MASK)
+
+/* ISINK_CON2: Register to control the brightness. */
+#define ISINK_CH_STEP_SHIFT 12
+#define ISINK_CH_STEP_MASK (0x7 << 12)
+#define ISINK_CH_STEP(i) (((i) << 12) & ISINK_CH_STEP_MASK)
+#define ISINK_SFSTR0_TC_MASK (0x3 << 1)
+#define ISINK_SFSTR0_TC(i) (((i) << 1) & ISINK_SFSTR0_TC_MASK)
+#define ISINK_SFSTR0_EN_MASK BIT(0)
+#define ISINK_SFSTR0_EN BIT(0)
/* Register to LED channel enablement. */
-#define MT6323_ISINK_CH_EN_MASK(i) BIT(i)
-#define MT6323_ISINK_CH_EN(i) BIT(i)
+#define ISINK_CH_EN_MASK(i) BIT(i)
+#define ISINK_CH_EN(i) BIT(i)
-#define MT6323_MAX_PERIOD 10000
-#define MT6323_MAX_LEDS 4
-#define MT6323_MAX_BRIGHTNESS 6
-#define MT6323_UNIT_DUTY 3125
-#define MT6323_CAL_HW_DUTY(o, p) DIV_ROUND_CLOSEST((o) * 100000ul,\
- (p) * MT6323_UNIT_DUTY)
+#define MAX_SUPPORTED_LEDS 8
struct mt6323_leds;
@@ -87,11 +80,62 @@ struct mt6323_led {
};
/**
+ * struct mt6323_regs - register spec for the LED device
+ * @top_ckpdn: Offset to ISINK_CKPDN[0..x] registers
+ * @num_top_ckpdn: Number of ISINK_CKPDN registers
+ * @top_ckcon: Offset to ISINK_CKCON[0..x] registers
+ * @num_top_ckcon: Number of ISINK_CKCON registers
+ * @isink_con: Offset to ISINKx_CON[0..x] registers
+ * @num_isink_con: Number of ISINKx_CON registers
+ * @isink_max_regs: Number of ISINK[0..x] registers
+ * @isink_en_ctrl: Offset to ISINK_EN_CTRL register
+ * @iwled_en_ctrl: Offset to IWLED_EN_CTRL register
+ */
+struct mt6323_regs {
+ const u16 *top_ckpdn;
+ u8 num_top_ckpdn;
+ const u16 *top_ckcon;
+ u8 num_top_ckcon;
+ const u16 *isink_con;
+ u8 num_isink_con;
+ u8 isink_max_regs;
+ u16 isink_en_ctrl;
+ u16 iwled_en_ctrl;
+};
+
+/**
+ * struct mt6323_hwspec - hardware specific parameters
+ * @max_period: Maximum period for all LEDs
+ * @max_leds: Maximum number of supported LEDs
+ * @max_wleds: Maximum number of WLEDs
+ * @max_brightness: Maximum brightness for all LEDs
+ * @unit_duty: Steps of duty per period
+ */
+struct mt6323_hwspec {
+ u16 max_period;
+ u8 max_leds;
+ u8 max_wleds;
+ u16 max_brightness;
+ u16 unit_duty;
+};
+
+/**
+ * struct mt6323_data - device specific data
+ * @regs: Register spec for this device
+ * @spec: Hardware specific parameters
+ */
+struct mt6323_data {
+ const struct mt6323_regs *regs;
+ const struct mt6323_hwspec *spec;
+};
+
+/**
* struct mt6323_leds - state container for holding LED controller
* of the driver
* @dev: the device pointer
* @hw: the underlying hardware providing shared
* bus for the register operations
+ * @pdata: device specific data
* @lock: the lock among process context
* @led: the array that contains the state of individual
* LED device
@@ -99,9 +143,10 @@ struct mt6323_led {
struct mt6323_leds {
struct device *dev;
struct mt6397_chip *hw;
+ const struct mt6323_data *pdata;
/* protect among process context */
struct mutex lock;
- struct mt6323_led *led[MT6323_MAX_LEDS];
+ struct mt6323_led *led[MAX_SUPPORTED_LEDS];
};
static int mt6323_led_hw_brightness(struct led_classdev *cdev,
@@ -109,6 +154,7 @@ static int mt6323_led_hw_brightness(struct led_classdev *cdev,
{
struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
struct mt6323_leds *leds = led->parent;
+ const struct mt6323_regs *regs = leds->pdata->regs;
struct regmap *regmap = leds->hw->regmap;
u32 con2_mask = 0, con2_val = 0;
int ret;
@@ -117,14 +163,14 @@ static int mt6323_led_hw_brightness(struct led_classdev *cdev,
* Setup current output for the corresponding
* brightness level.
*/
- con2_mask |= MT6323_ISINK_CH_STEP_MASK |
- MT6323_ISINK_SFSTR0_TC_MASK |
- MT6323_ISINK_SFSTR0_EN_MASK;
- con2_val |= MT6323_ISINK_CH_STEP(brightness - 1) |
- MT6323_ISINK_SFSTR0_TC(2) |
- MT6323_ISINK_SFSTR0_EN;
-
- ret = regmap_update_bits(regmap, MT6323_ISINK_CON2(led->id),
+ con2_mask |= ISINK_CH_STEP_MASK |
+ ISINK_SFSTR0_TC_MASK |
+ ISINK_SFSTR0_EN_MASK;
+ con2_val |= ISINK_CH_STEP(brightness - 1) |
+ ISINK_SFSTR0_TC(2) |
+ ISINK_SFSTR0_EN;
+
+ ret = regmap_update_bits(regmap, ISINK_CON(regs->isink_con[2], led->id),
con2_mask, con2_val);
return ret;
}
@@ -133,20 +179,21 @@ static int mt6323_led_hw_off(struct led_classdev *cdev)
{
struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
struct mt6323_leds *leds = led->parent;
+ const struct mt6323_regs *regs = leds->pdata->regs;
struct regmap *regmap = leds->hw->regmap;
unsigned int status;
int ret;
- status = MT6323_ISINK_CH_EN(led->id);
- ret = regmap_update_bits(regmap, MT6323_ISINK_EN_CTRL,
- MT6323_ISINK_CH_EN_MASK(led->id), ~status);
+ status = ISINK_CH_EN(led->id);
+ ret = regmap_update_bits(regmap, regs->isink_en_ctrl,
+ ISINK_CH_EN_MASK(led->id), ~status);
if (ret < 0)
return ret;
usleep_range(100, 300);
- ret = regmap_update_bits(regmap, MT6323_TOP_CKPDN2,
- MT6323_RG_ISINK_CK_PDN_MASK(led->id),
- MT6323_RG_ISINK_CK_PDN(led->id));
+ ret = regmap_update_bits(regmap, regs->top_ckpdn[2],
+ RG_ISINK_CK_PDN_MASK(led->id),
+ RG_ISINK_CK_PDN(led->id));
if (ret < 0)
return ret;
@@ -158,30 +205,31 @@ mt6323_get_led_hw_brightness(struct led_classdev *cdev)
{
struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
struct mt6323_leds *leds = led->parent;
+ const struct mt6323_regs *regs = leds->pdata->regs;
struct regmap *regmap = leds->hw->regmap;
unsigned int status;
int ret;
- ret = regmap_read(regmap, MT6323_TOP_CKPDN2, &status);
+ ret = regmap_read(regmap, regs->top_ckpdn[2], &status);
if (ret < 0)
return ret;
- if (status & MT6323_RG_ISINK_CK_PDN_MASK(led->id))
+ if (status & RG_ISINK_CK_PDN_MASK(led->id))
return 0;
- ret = regmap_read(regmap, MT6323_ISINK_EN_CTRL, &status);
+ ret = regmap_read(regmap, regs->isink_en_ctrl, &status);
if (ret < 0)
return ret;
- if (!(status & MT6323_ISINK_CH_EN(led->id)))
+ if (!(status & ISINK_CH_EN(led->id)))
return 0;
- ret = regmap_read(regmap, MT6323_ISINK_CON2(led->id), &status);
+ ret = regmap_read(regmap, ISINK_CON(regs->isink_con[2], led->id), &status);
if (ret < 0)
return ret;
- return ((status & MT6323_ISINK_CH_STEP_MASK)
- >> MT6323_ISINK_CH_STEP_SHIFT) + 1;
+ return ((status & ISINK_CH_STEP_MASK)
+ >> ISINK_CH_STEP_SHIFT) + 1;
}
static int mt6323_led_hw_on(struct led_classdev *cdev,
@@ -189,6 +237,7 @@ static int mt6323_led_hw_on(struct led_classdev *cdev,
{
struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
struct mt6323_leds *leds = led->parent;
+ const struct mt6323_regs *regs = leds->pdata->regs;
struct regmap *regmap = leds->hw->regmap;
unsigned int status;
int ret;
@@ -198,23 +247,23 @@ static int mt6323_led_hw_on(struct led_classdev *cdev,
* clock and channel and let work with continuous blink as
* the default.
*/
- ret = regmap_update_bits(regmap, MT6323_TOP_CKCON1,
- MT6323_RG_ISINK_CK_SEL_MASK(led->id), 0);
+ ret = regmap_update_bits(regmap, regs->top_ckcon[1],
+ RG_ISINK_CK_SEL_MASK(led->id), 0);
if (ret < 0)
return ret;
- status = MT6323_RG_ISINK_CK_PDN(led->id);
- ret = regmap_update_bits(regmap, MT6323_TOP_CKPDN2,
- MT6323_RG_ISINK_CK_PDN_MASK(led->id),
+ status = RG_ISINK_CK_PDN(led->id);
+ ret = regmap_update_bits(regmap, regs->top_ckpdn[2],
+ RG_ISINK_CK_PDN_MASK(led->id),
~status);
if (ret < 0)
return ret;
usleep_range(100, 300);
- ret = regmap_update_bits(regmap, MT6323_ISINK_EN_CTRL,
- MT6323_ISINK_CH_EN_MASK(led->id),
- MT6323_ISINK_CH_EN(led->id));
+ ret = regmap_update_bits(regmap, regs->isink_en_ctrl,
+ ISINK_CH_EN_MASK(led->id),
+ ISINK_CH_EN(led->id));
if (ret < 0)
return ret;
@@ -222,15 +271,15 @@ static int mt6323_led_hw_on(struct led_classdev *cdev,
if (ret < 0)
return ret;
- ret = regmap_update_bits(regmap, MT6323_ISINK_CON0(led->id),
- MT6323_ISINK_DIM_DUTY_MASK,
- MT6323_ISINK_DIM_DUTY(31));
+ ret = regmap_update_bits(regmap, ISINK_CON(regs->isink_con[0], led->id),
+ ISINK_DIM_DUTY_MASK,
+ ISINK_DIM_DUTY(31));
if (ret < 0)
return ret;
- ret = regmap_update_bits(regmap, MT6323_ISINK_CON1(led->id),
- MT6323_ISINK_DIM_FSEL_MASK,
- MT6323_ISINK_DIM_FSEL(1000));
+ ret = regmap_update_bits(regmap, ISINK_CON(regs->isink_con[1], led->id),
+ ISINK_DIM_FSEL_MASK,
+ ISINK_DIM_FSEL(1000));
if (ret < 0)
return ret;
@@ -243,6 +292,8 @@ static int mt6323_led_set_blink(struct led_classdev *cdev,
{
struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
struct mt6323_leds *leds = led->parent;
+ const struct mt6323_regs *regs = leds->pdata->regs;
+ const struct mt6323_hwspec *spec = leds->pdata->spec;
struct regmap *regmap = leds->hw->regmap;
unsigned long period;
u8 duty_hw;
@@ -265,14 +316,14 @@ static int mt6323_led_set_blink(struct led_classdev *cdev,
*/
period = *delay_on + *delay_off;
- if (period > MT6323_MAX_PERIOD)
+ if (period > spec->max_period)
return -EINVAL;
/*
* Calculate duty_hw based on the percentage of period during
* which the led is ON.
*/
- duty_hw = MT6323_CAL_HW_DUTY(*delay_on, period);
+ duty_hw = DIV_ROUND_CLOSEST(*delay_on * 100000ul, period * spec->unit_duty);
/* hardware doesn't support zero duty cycle. */
if (!duty_hw)
@@ -290,15 +341,15 @@ static int mt6323_led_set_blink(struct led_classdev *cdev,
led->current_brightness = cdev->max_brightness;
}
- ret = regmap_update_bits(regmap, MT6323_ISINK_CON0(led->id),
- MT6323_ISINK_DIM_DUTY_MASK,
- MT6323_ISINK_DIM_DUTY(duty_hw - 1));
+ ret = regmap_update_bits(regmap, ISINK_CON(regs->isink_con[0], led->id),
+ ISINK_DIM_DUTY_MASK,
+ ISINK_DIM_DUTY(duty_hw - 1));
if (ret < 0)
goto out;
- ret = regmap_update_bits(regmap, MT6323_ISINK_CON1(led->id),
- MT6323_ISINK_DIM_FSEL_MASK,
- MT6323_ISINK_DIM_FSEL(period - 1));
+ ret = regmap_update_bits(regmap, ISINK_CON(regs->isink_con[1], led->id),
+ ISINK_DIM_FSEL_MASK,
+ ISINK_DIM_FSEL(period - 1));
out:
mutex_unlock(&leds->lock);
@@ -335,6 +386,117 @@ out:
return ret;
}
+static int mtk_wled_hw_on(struct led_classdev *cdev)
+{
+ struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
+ struct mt6323_leds *leds = led->parent;
+ const struct mt6323_regs *regs = leds->pdata->regs;
+ struct regmap *regmap = leds->hw->regmap;
+ int ret;
+
+ ret = regmap_clear_bits(regmap, regs->top_ckpdn[0], RG_VWLED_32K_CK_PDN);
+ if (ret)
+ return ret;
+
+ ret = regmap_clear_bits(regmap, regs->top_ckpdn[0], RG_VWLED_6M_CK_PDN);
+ if (ret)
+ return ret;
+
+ ret = regmap_clear_bits(regmap, regs->top_ckpdn[0], RG_VWLED_1M_CK_PDN);
+ if (ret)
+ return ret;
+
+ usleep_range(5000, 6000);
+
+ /* Enable WLED channel pair */
+ ret = regmap_set_bits(regmap, regs->iwled_en_ctrl, BIT(led->id));
+ if (ret)
+ return ret;
+
+ ret = regmap_set_bits(regmap, regs->iwled_en_ctrl, BIT(led->id + 1));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mtk_wled_hw_off(struct led_classdev *cdev)
+{
+ struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
+ struct mt6323_leds *leds = led->parent;
+ const struct mt6323_regs *regs = leds->pdata->regs;
+ struct regmap *regmap = leds->hw->regmap;
+ int ret;
+
+ ret = regmap_clear_bits(regmap, regs->iwled_en_ctrl, BIT(led->id + 1));
+ if (ret)
+ return ret;
+
+ ret = regmap_clear_bits(regmap, regs->iwled_en_ctrl, BIT(led->id));
+ if (ret)
+ return ret;
+
+ ret = regmap_set_bits(regmap, regs->top_ckpdn[0], RG_VWLED_32K_CK_PDN);
+ if (ret)
+ return ret;
+
+ ret = regmap_set_bits(regmap, regs->top_ckpdn[0], RG_VWLED_6M_CK_PDN);
+ if (ret)
+ return ret;
+
+ ret = regmap_set_bits(regmap, regs->top_ckpdn[0], RG_VWLED_1M_CK_PDN);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static enum led_brightness mt6323_get_wled_brightness(struct led_classdev *cdev)
+{
+ struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
+ struct mt6323_leds *leds = led->parent;
+ const struct mt6323_regs *regs = leds->pdata->regs;
+ struct regmap *regmap = leds->hw->regmap;
+ unsigned int status;
+ int ret;
+
+ ret = regmap_read(regmap, regs->iwled_en_ctrl, &status);
+ if (ret)
+ return 0;
+
+ /* Always two channels per WLED */
+ status &= BIT(led->id) | BIT(led->id + 1);
+
+ return status ? led->current_brightness : 0;
+}
+
+static int mt6323_wled_set_brightness(struct led_classdev *cdev,
+ enum led_brightness brightness)
+{
+ struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
+ struct mt6323_leds *leds = led->parent;
+ int ret = 0;
+
+ mutex_lock(&leds->lock);
+
+ if (brightness) {
+ if (!led->current_brightness)
+ ret = mtk_wled_hw_on(cdev);
+ if (ret)
+ goto out;
+ } else {
+ ret = mtk_wled_hw_off(cdev);
+ if (ret)
+ goto out;
+ }
+
+ led->current_brightness = brightness;
+out:
+ mutex_unlock(&leds->lock);
+
+ return ret;
+}
+
static int mt6323_led_set_dt_default(struct led_classdev *cdev,
struct device_node *np)
{
@@ -369,9 +531,12 @@ static int mt6323_led_probe(struct platform_device *pdev)
struct mt6397_chip *hw = dev_get_drvdata(dev->parent);
struct mt6323_leds *leds;
struct mt6323_led *led;
+ const struct mt6323_regs *regs;
+ const struct mt6323_hwspec *spec;
int ret;
unsigned int status;
u32 reg;
+ u8 max_leds;
leds = devm_kzalloc(dev, sizeof(*leds), GFP_KERNEL);
if (!leds)
@@ -379,6 +544,10 @@ static int mt6323_led_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, leds);
leds->dev = dev;
+ leds->pdata = device_get_match_data(dev);
+ regs = leds->pdata->regs;
+ spec = leds->pdata->spec;
+ max_leds = spec->max_leds + spec->max_wleds;
/*
* leds->hw points to the underlying bus for the register
@@ -387,17 +556,18 @@ static int mt6323_led_probe(struct platform_device *pdev)
leds->hw = hw;
mutex_init(&leds->lock);
- status = MT6323_RG_DRV_32K_CK_PDN;
- ret = regmap_update_bits(leds->hw->regmap, MT6323_TOP_CKPDN0,
- MT6323_RG_DRV_32K_CK_PDN_MASK, ~status);
+ status = RG_DRV_32K_CK_PDN;
+ ret = regmap_update_bits(leds->hw->regmap, regs->top_ckpdn[0],
+ RG_DRV_32K_CK_PDN_MASK, ~status);
if (ret < 0) {
dev_err(leds->dev,
- "Failed to update MT6323_TOP_CKPDN0 Register\n");
+ "Failed to update TOP_CKPDN0 Register\n");
return ret;
}
for_each_available_child_of_node(np, child) {
struct led_init_data init_data = {};
+ bool is_wled;
ret = of_property_read_u32(child, "reg", &reg);
if (ret) {
@@ -405,7 +575,8 @@ static int mt6323_led_probe(struct platform_device *pdev)
goto put_child_node;
}
- if (reg >= MT6323_MAX_LEDS || leds->led[reg]) {
+ if (reg >= max_leds || reg >= MAX_SUPPORTED_LEDS ||
+ leds->led[reg]) {
dev_err(dev, "Invalid led reg %u\n", reg);
ret = -EINVAL;
goto put_child_node;
@@ -417,14 +588,24 @@ static int mt6323_led_probe(struct platform_device *pdev)
goto put_child_node;
}
+ is_wled = of_property_read_bool(child, "mediatek,is-wled");
+
leds->led[reg] = led;
leds->led[reg]->id = reg;
- leds->led[reg]->cdev.max_brightness = MT6323_MAX_BRIGHTNESS;
- leds->led[reg]->cdev.brightness_set_blocking =
- mt6323_led_set_brightness;
- leds->led[reg]->cdev.blink_set = mt6323_led_set_blink;
- leds->led[reg]->cdev.brightness_get =
- mt6323_get_led_hw_brightness;
+ leds->led[reg]->cdev.max_brightness = spec->max_brightness;
+
+ if (is_wled) {
+ leds->led[reg]->cdev.brightness_set_blocking =
+ mt6323_wled_set_brightness;
+ leds->led[reg]->cdev.brightness_get =
+ mt6323_get_wled_brightness;
+ } else {
+ leds->led[reg]->cdev.brightness_set_blocking =
+ mt6323_led_set_brightness;
+ leds->led[reg]->cdev.blink_set = mt6323_led_set_blink;
+ leds->led[reg]->cdev.brightness_get =
+ mt6323_get_led_hw_brightness;
+ }
leds->led[reg]->parent = leds;
ret = mt6323_led_set_dt_default(&leds->led[reg]->cdev, child);
@@ -454,23 +635,88 @@ put_child_node:
static int mt6323_led_remove(struct platform_device *pdev)
{
struct mt6323_leds *leds = platform_get_drvdata(pdev);
+ const struct mt6323_regs *regs = leds->pdata->regs;
int i;
/* Turn the LEDs off on driver removal. */
for (i = 0 ; leds->led[i] ; i++)
mt6323_led_hw_off(&leds->led[i]->cdev);
- regmap_update_bits(leds->hw->regmap, MT6323_TOP_CKPDN0,
- MT6323_RG_DRV_32K_CK_PDN_MASK,
- MT6323_RG_DRV_32K_CK_PDN);
+ regmap_update_bits(leds->hw->regmap, regs->top_ckpdn[0],
+ RG_DRV_32K_CK_PDN_MASK,
+ RG_DRV_32K_CK_PDN);
mutex_destroy(&leds->lock);
return 0;
}
+static const struct mt6323_regs mt6323_registers = {
+ .top_ckpdn = (const u16[]){ 0x102, 0x106, 0x10e },
+ .num_top_ckpdn = 3,
+ .top_ckcon = (const u16[]){ 0x120, 0x126 },
+ .num_top_ckcon = 2,
+ .isink_con = (const u16[]){ 0x330, 0x332, 0x334 },
+ .num_isink_con = 3,
+ .isink_max_regs = 4, /* ISINK[0..3] */
+ .isink_en_ctrl = 0x356,
+};
+
+static const struct mt6323_regs mt6331_registers = {
+ .top_ckpdn = (const u16[]){ 0x138, 0x13e, 0x144 },
+ .num_top_ckpdn = 3,
+ .top_ckcon = (const u16[]){ 0x14c, 0x14a },
+ .num_top_ckcon = 2,
+ .isink_con = (const u16[]){ 0x40c, 0x40e, 0x410, 0x412, 0x414 },
+ .num_isink_con = 5,
+ .isink_max_regs = 4, /* ISINK[0..3] */
+ .isink_en_ctrl = 0x43a,
+};
+
+static const struct mt6323_regs mt6332_registers = {
+ .top_ckpdn = (const u16[]){ 0x8094, 0x809a, 0x80a0 },
+ .num_top_ckpdn = 3,
+ .top_ckcon = (const u16[]){ 0x80a6, 0x80ac },
+ .num_top_ckcon = 2,
+ .isink_con = (const u16[]){ 0x8cd4 },
+ .num_isink_con = 1,
+ .isink_max_regs = 12, /* IWLED[0..2, 3..9] */
+ .iwled_en_ctrl = 0x8cda,
+};
+
+static const struct mt6323_hwspec mt6323_spec = {
+ .max_period = 10000,
+ .max_leds = 4,
+ .max_brightness = 6,
+ .unit_duty = 3125,
+};
+
+static const struct mt6323_hwspec mt6332_spec = {
+ /* There are no LEDs in MT6332. Only WLEDs are present. */
+ .max_leds = 0,
+ .max_wleds = 1,
+ .max_brightness = 1024,
+};
+
+static const struct mt6323_data mt6323_pdata = {
+ .regs = &mt6323_registers,
+ .spec = &mt6323_spec,
+};
+
+static const struct mt6323_data mt6331_pdata = {
+ .regs = &mt6331_registers,
+ .spec = &mt6323_spec,
+};
+
+static const struct mt6323_data mt6332_pdata = {
+ .regs = &mt6332_registers,
+ .spec = &mt6332_spec,
+};
+
static const struct of_device_id mt6323_led_dt_match[] = {
- { .compatible = "mediatek,mt6323-led" },
+ { .compatible = "mediatek,mt6323-led", .data = &mt6323_pdata},
+ { .compatible = "mediatek,mt6331-led", .data = &mt6331_pdata },
+ { .compatible = "mediatek,mt6332-led", .data = &mt6332_pdata },
{},
};
MODULE_DEVICE_TABLE(of, mt6323_led_dt_match);
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
index 15b1acfa442e..8b5c62083e50 100644
--- a/drivers/leds/leds-pca9532.c
+++ b/drivers/leds/leds-pca9532.c
@@ -102,7 +102,7 @@ static struct i2c_driver pca9532_driver = {
.name = "leds-pca953x",
.of_match_table = of_match_ptr(of_pca9532_leds_match),
},
- .probe_new = pca9532_probe,
+ .probe = pca9532_probe,
.remove = pca9532_remove,
.id_table = pca9532_id,
};
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 1edd092e7894..b10e1ef38db0 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -668,7 +668,7 @@ static struct i2c_driver pca955x_driver = {
.name = "leds-pca955x",
.of_match_table = of_pca955x_match,
},
- .probe_new = pca955x_probe,
+ .probe = pca955x_probe,
.id_table = pca955x_id,
};
diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c
index 9cd476db601f..47223c850e4b 100644
--- a/drivers/leds/leds-pca963x.c
+++ b/drivers/leds/leds-pca963x.c
@@ -431,7 +431,7 @@ static struct i2c_driver pca963x_driver = {
.name = "leds-pca963x",
.of_match_table = of_pca963x_match,
},
- .probe_new = pca963x_probe,
+ .probe = pca963x_probe,
.id_table = pca963x_id,
};
diff --git a/drivers/leds/leds-spi-byte.c b/drivers/leds/leds-spi-byte.c
index 2bc5c99daf51..2c7ffc3c78e6 100644
--- a/drivers/leds/leds-spi-byte.c
+++ b/drivers/leds/leds-spi-byte.c
@@ -98,7 +98,7 @@ static int spi_byte_probe(struct spi_device *spi)
return -ENOMEM;
of_property_read_string(child, "label", &name);
- strlcpy(led->name, name, sizeof(led->name));
+ strscpy(led->name, name, sizeof(led->name));
led->spi = spi;
mutex_init(&led->mutex);
led->cdef = device_get_match_data(dev);
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
index 634cabd5bb79..aab861771210 100644
--- a/drivers/leds/leds-tca6507.c
+++ b/drivers/leds/leds-tca6507.c
@@ -808,7 +808,7 @@ static struct i2c_driver tca6507_driver = {
.name = "leds-tca6507",
.of_match_table = of_match_ptr(of_tca6507_leds_match),
},
- .probe_new = tca6507_probe,
+ .probe = tca6507_probe,
.remove = tca6507_remove,
.id_table = tca6507_id,
};
diff --git a/drivers/leds/leds-tlc591xx.c b/drivers/leds/leds-tlc591xx.c
index 7e31db50036f..dfc6fb2b3e52 100644
--- a/drivers/leds/leds-tlc591xx.c
+++ b/drivers/leds/leds-tlc591xx.c
@@ -230,7 +230,7 @@ static struct i2c_driver tlc591xx_driver = {
.name = "tlc591xx",
.of_match_table = of_match_ptr(of_tlc591xx_leds_match),
},
- .probe_new = tlc591xx_probe,
+ .probe = tlc591xx_probe,
.id_table = tlc591xx_id,
};
diff --git a/drivers/leds/leds-turris-omnia.c b/drivers/leds/leds-turris-omnia.c
index 013f551b32b2..64b2d7b6d3f3 100644
--- a/drivers/leds/leds-turris-omnia.c
+++ b/drivers/leds/leds-turris-omnia.c
@@ -271,7 +271,7 @@ static const struct i2c_device_id omnia_id[] = {
MODULE_DEVICE_TABLE(i2c, omnia_id);
static struct i2c_driver omnia_leds_driver = {
- .probe_new = omnia_leds_probe,
+ .probe = omnia_leds_probe,
.remove = omnia_leds_remove,
.id_table = omnia_id,
.driver = {
diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c
index 1c849814a491..59581b3e25ca 100644
--- a/drivers/leds/rgb/leds-qcom-lpg.c
+++ b/drivers/leds/rgb/leds-qcom-lpg.c
@@ -1173,8 +1173,10 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np)
i = 0;
for_each_available_child_of_node(np, child) {
ret = lpg_parse_channel(lpg, child, &led->channels[i]);
- if (ret < 0)
+ if (ret < 0) {
+ of_node_put(child);
return ret;
+ }
info[i].color_index = led->channels[i]->color;
info[i].intensity = 0;
@@ -1352,8 +1354,10 @@ static int lpg_probe(struct platform_device *pdev)
for_each_available_child_of_node(pdev->dev.of_node, np) {
ret = lpg_add_led(lpg, np);
- if (ret)
+ if (ret) {
+ of_node_put(np);
return ret;
+ }
}
for (i = 0; i < lpg->num_channels; i++)
@@ -1414,6 +1418,20 @@ static const struct lpg_data pm8994_lpg_data = {
},
};
+/* PMI632 uses SDAM instead of LUT for pattern */
+static const struct lpg_data pmi632_lpg_data = {
+ .triled_base = 0xd000,
+
+ .num_channels = 5,
+ .channels = (const struct lpg_channel_data[]) {
+ { .base = 0xb300, .triled_mask = BIT(7) },
+ { .base = 0xb400, .triled_mask = BIT(6) },
+ { .base = 0xb500, .triled_mask = BIT(5) },
+ { .base = 0xb600 },
+ { .base = 0xb700 },
+ },
+};
+
static const struct lpg_data pmi8994_lpg_data = {
.lut_base = 0xb000,
.lut_size = 24,
@@ -1505,6 +1523,7 @@ static const struct of_device_id lpg_of_table[] = {
{ .compatible = "qcom,pm8916-pwm", .data = &pm8916_pwm_data },
{ .compatible = "qcom,pm8941-lpg", .data = &pm8941_lpg_data },
{ .compatible = "qcom,pm8994-lpg", .data = &pm8994_lpg_data },
+ { .compatible = "qcom,pmi632-lpg", .data = &pmi632_lpg_data },
{ .compatible = "qcom,pmi8994-lpg", .data = &pmi8994_lpg_data },
{ .compatible = "qcom,pmi8998-lpg", .data = &pmi8998_lpg_data },
{ .compatible = "qcom,pmc8180c-lpg", .data = &pm8150l_lpg_data },
diff --git a/drivers/leds/simple/Kconfig b/drivers/leds/simple/Kconfig
index fd2b8225d926..44fa0f93cb3b 100644
--- a/drivers/leds/simple/Kconfig
+++ b/drivers/leds/simple/Kconfig
@@ -1,11 +1,36 @@
# SPDX-License-Identifier: GPL-2.0-only
config LEDS_SIEMENS_SIMATIC_IPC
tristate "LED driver for Siemens Simatic IPCs"
- depends on LEDS_GPIO
depends on SIEMENS_SIMATIC_IPC
help
This option enables support for the LEDs of several Industrial PCs
from Siemens.
- To compile this driver as a module, choose M here: the modules
- will be called simatic-ipc-leds and simatic-ipc-leds-gpio.
+ To compile this driver as a module, choose M here: the module
+ will be called simatic-ipc-leds.
+
+config LEDS_SIEMENS_SIMATIC_IPC_APOLLOLAKE
+ tristate "LED driver for Siemens Simatic IPCs based on Intel Apollo Lake GPIO"
+ depends on LEDS_GPIO
+ depends on PINCTRL_BROXTON
+ depends on SIEMENS_SIMATIC_IPC
+ default LEDS_SIEMENS_SIMATIC_IPC
+ help
+ This option enables support for the LEDs of several Industrial PCs
+ from Siemens based on Apollo Lake GPIO i.e. IPC127E.
+
+ To compile this driver as a module, choose M here: the module
+ will be called simatic-ipc-leds-gpio-apollolake.
+
+config LEDS_SIEMENS_SIMATIC_IPC_F7188X
+ tristate "LED driver for Siemens Simatic IPCs based on Nuvoton GPIO"
+ depends on LEDS_GPIO
+ depends on GPIO_F7188X
+ depends on SIEMENS_SIMATIC_IPC
+ default LEDS_SIEMENS_SIMATIC_IPC
+ help
+ This option enables support for the LEDs of several Industrial PCs
+ from Siemens based on Nuvoton GPIO i.e. IPC227G.
+
+ To compile this driver as a module, choose M here: the module
+ will be called simatic-ipc-leds-gpio-f7188x.
diff --git a/drivers/leds/simple/Makefile b/drivers/leds/simple/Makefile
index 1c7ef5e1324b..e3e840cea275 100644
--- a/drivers/leds/simple/Makefile
+++ b/drivers/leds/simple/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC) += simatic-ipc-leds.o
-obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC) += simatic-ipc-leds-gpio.o
+obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC) += simatic-ipc-leds.o
+obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC_APOLLOLAKE) += simatic-ipc-leds-gpio-core.o simatic-ipc-leds-gpio-apollolake.o
+obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC_F7188X) += simatic-ipc-leds-gpio-core.o simatic-ipc-leds-gpio-f7188x.o
diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c b/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c
new file mode 100644
index 000000000000..e1c712729dcf
--- /dev/null
+++ b/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Siemens SIMATIC IPC driver for GPIO based LEDs
+ *
+ * Copyright (c) Siemens AG, 2023
+ *
+ * Author:
+ * Henning Schild <henning.schild@siemens.com>
+ */
+
+#include <linux/gpio/machine.h>
+#include <linux/gpio/consumer.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/x86/simatic-ipc-base.h>
+
+#include "simatic-ipc-leds-gpio.h"
+
+static struct gpiod_lookup_table simatic_ipc_led_gpio_table = {
+ .dev_id = "leds-gpio",
+ .table = {
+ GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 52, NULL, 0, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 53, NULL, 1, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 57, NULL, 2, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 58, NULL, 3, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 60, NULL, 4, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 51, NULL, 5, GPIO_ACTIVE_LOW),
+ {} /* Terminating entry */
+ },
+};
+
+static struct gpiod_lookup_table simatic_ipc_led_gpio_table_extra = {
+ .dev_id = NULL, /* Filled during initialization */
+ .table = {
+ GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 56, NULL, 6, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 59, NULL, 7, GPIO_ACTIVE_HIGH),
+ {} /* Terminating entry */
+ },
+};
+
+static int simatic_ipc_leds_gpio_apollolake_probe(struct platform_device *pdev)
+{
+ return simatic_ipc_leds_gpio_probe(pdev, &simatic_ipc_led_gpio_table,
+ &simatic_ipc_led_gpio_table_extra);
+}
+
+static int simatic_ipc_leds_gpio_apollolake_remove(struct platform_device *pdev)
+{
+ return simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table,
+ &simatic_ipc_led_gpio_table_extra);
+}
+
+static struct platform_driver simatic_ipc_led_gpio_apollolake_driver = {
+ .probe = simatic_ipc_leds_gpio_apollolake_probe,
+ .remove = simatic_ipc_leds_gpio_apollolake_remove,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ },
+};
+module_platform_driver(simatic_ipc_led_gpio_apollolake_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" KBUILD_MODNAME);
+MODULE_SOFTDEP("pre: simatic-ipc-leds-gpio-core platform:apollolake-pinctrl");
+MODULE_AUTHOR("Henning Schild <henning.schild@siemens.com>");
diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-core.c b/drivers/leds/simple/simatic-ipc-leds-gpio-core.c
new file mode 100644
index 000000000000..2a21b663df87
--- /dev/null
+++ b/drivers/leds/simple/simatic-ipc-leds-gpio-core.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Siemens SIMATIC IPC driver for GPIO based LEDs
+ *
+ * Copyright (c) Siemens AG, 2023
+ *
+ * Author:
+ * Henning Schild <henning.schild@siemens.com>
+ */
+
+#include <linux/gpio/machine.h>
+#include <linux/gpio/consumer.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/x86/simatic-ipc-base.h>
+
+#include "simatic-ipc-leds-gpio.h"
+
+static struct platform_device *simatic_leds_pdev;
+
+static const struct gpio_led simatic_ipc_gpio_leds[] = {
+ { .name = "red:" LED_FUNCTION_STATUS "-1" },
+ { .name = "green:" LED_FUNCTION_STATUS "-1" },
+ { .name = "red:" LED_FUNCTION_STATUS "-2" },
+ { .name = "green:" LED_FUNCTION_STATUS "-2" },
+ { .name = "red:" LED_FUNCTION_STATUS "-3" },
+ { .name = "green:" LED_FUNCTION_STATUS "-3" },
+};
+
+static const struct gpio_led_platform_data simatic_ipc_gpio_leds_pdata = {
+ .num_leds = ARRAY_SIZE(simatic_ipc_gpio_leds),
+ .leds = simatic_ipc_gpio_leds,
+};
+
+int simatic_ipc_leds_gpio_remove(struct platform_device *pdev,
+ struct gpiod_lookup_table *table,
+ struct gpiod_lookup_table *table_extra)
+{
+ gpiod_remove_lookup_table(table);
+ gpiod_remove_lookup_table(table_extra);
+ platform_device_unregister(simatic_leds_pdev);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(simatic_ipc_leds_gpio_remove);
+
+int simatic_ipc_leds_gpio_probe(struct platform_device *pdev,
+ struct gpiod_lookup_table *table,
+ struct gpiod_lookup_table *table_extra)
+{
+ const struct simatic_ipc_platform *plat = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct gpio_desc *gpiod;
+ int err;
+
+ switch (plat->devmode) {
+ case SIMATIC_IPC_DEVICE_127E:
+ case SIMATIC_IPC_DEVICE_227G:
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ gpiod_add_lookup_table(table);
+ simatic_leds_pdev = platform_device_register_resndata(NULL,
+ "leds-gpio", PLATFORM_DEVID_NONE, NULL, 0,
+ &simatic_ipc_gpio_leds_pdata,
+ sizeof(simatic_ipc_gpio_leds_pdata));
+ if (IS_ERR(simatic_leds_pdev)) {
+ err = PTR_ERR(simatic_leds_pdev);
+ goto out;
+ }
+
+ table_extra->dev_id = dev_name(dev);
+ gpiod_add_lookup_table(table_extra);
+
+ /* PM_BIOS_BOOT_N */
+ gpiod = gpiod_get_index(dev, NULL, 6, GPIOD_OUT_LOW);
+ if (IS_ERR(gpiod)) {
+ err = PTR_ERR(gpiod);
+ goto out;
+ }
+ gpiod_put(gpiod);
+
+ /* PM_WDT_OUT */
+ gpiod = gpiod_get_index(dev, NULL, 7, GPIOD_OUT_LOW);
+ if (IS_ERR(gpiod)) {
+ err = PTR_ERR(gpiod);
+ goto out;
+ }
+ gpiod_put(gpiod);
+
+ return 0;
+out:
+ simatic_ipc_leds_gpio_remove(pdev, table, table_extra);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(simatic_ipc_leds_gpio_probe);
+
+MODULE_LICENSE("GPL v2");
+MODULE_SOFTDEP("pre: platform:leds-gpio");
+MODULE_AUTHOR("Henning Schild <henning.schild@siemens.com>");
diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c b/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c
new file mode 100644
index 000000000000..583a6b6c7c22
--- /dev/null
+++ b/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Siemens SIMATIC IPC driver for GPIO based LEDs
+ *
+ * Copyright (c) Siemens AG, 2023
+ *
+ * Author:
+ * Henning Schild <henning.schild@siemens.com>
+ */
+
+#include <linux/gpio/machine.h>
+#include <linux/gpio/consumer.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/x86/simatic-ipc-base.h>
+
+#include "simatic-ipc-leds-gpio.h"
+
+static struct gpiod_lookup_table simatic_ipc_led_gpio_table = {
+ .dev_id = "leds-gpio",
+ .table = {
+ GPIO_LOOKUP_IDX("gpio-f7188x-2", 0, NULL, 0, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("gpio-f7188x-2", 1, NULL, 1, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("gpio-f7188x-2", 2, NULL, 2, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("gpio-f7188x-2", 3, NULL, 3, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("gpio-f7188x-2", 4, NULL, 4, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("gpio-f7188x-2", 5, NULL, 5, GPIO_ACTIVE_LOW),
+ {} /* Terminating entry */
+ },
+};
+
+static struct gpiod_lookup_table simatic_ipc_led_gpio_table_extra = {
+ .dev_id = NULL, /* Filled during initialization */
+ .table = {
+ GPIO_LOOKUP_IDX("gpio-f7188x-3", 6, NULL, 6, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("gpio-f7188x-3", 7, NULL, 7, GPIO_ACTIVE_HIGH),
+ {} /* Terminating entry */
+ },
+};
+
+static int simatic_ipc_leds_gpio_f7188x_probe(struct platform_device *pdev)
+{
+ return simatic_ipc_leds_gpio_probe(pdev, &simatic_ipc_led_gpio_table,
+ &simatic_ipc_led_gpio_table_extra);
+}
+
+static int simatic_ipc_leds_gpio_f7188x_remove(struct platform_device *pdev)
+{
+ return simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table,
+ &simatic_ipc_led_gpio_table_extra);
+}
+
+static struct platform_driver simatic_ipc_led_gpio_driver = {
+ .probe = simatic_ipc_leds_gpio_f7188x_probe,
+ .remove = simatic_ipc_leds_gpio_f7188x_remove,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ },
+};
+module_platform_driver(simatic_ipc_led_gpio_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" KBUILD_MODNAME);
+MODULE_SOFTDEP("pre: simatic-ipc-leds-gpio-core gpio_f7188x");
+MODULE_AUTHOR("Henning Schild <henning.schild@siemens.com>");
diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio.c b/drivers/leds/simple/simatic-ipc-leds-gpio.c
deleted file mode 100644
index e8d329b5a68c..000000000000
--- a/drivers/leds/simple/simatic-ipc-leds-gpio.c
+++ /dev/null
@@ -1,139 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Siemens SIMATIC IPC driver for GPIO based LEDs
- *
- * Copyright (c) Siemens AG, 2022
- *
- * Authors:
- * Henning Schild <henning.schild@siemens.com>
- */
-
-#include <linux/gpio/machine.h>
-#include <linux/gpio/consumer.h>
-#include <linux/leds.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/x86/simatic-ipc-base.h>
-
-static struct gpiod_lookup_table *simatic_ipc_led_gpio_table;
-
-static struct gpiod_lookup_table simatic_ipc_led_gpio_table_127e = {
- .dev_id = "leds-gpio",
- .table = {
- GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 52, NULL, 0, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 53, NULL, 1, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 57, NULL, 2, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 58, NULL, 3, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 60, NULL, 4, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 51, NULL, 5, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 56, NULL, 6, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 59, NULL, 7, GPIO_ACTIVE_HIGH),
- },
-};
-
-static struct gpiod_lookup_table simatic_ipc_led_gpio_table_227g = {
- .dev_id = "leds-gpio",
- .table = {
- GPIO_LOOKUP_IDX("gpio-f7188x-2", 0, NULL, 0, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("gpio-f7188x-2", 1, NULL, 1, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("gpio-f7188x-2", 2, NULL, 2, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("gpio-f7188x-2", 3, NULL, 3, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("gpio-f7188x-2", 4, NULL, 4, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("gpio-f7188x-2", 5, NULL, 5, GPIO_ACTIVE_LOW),
- GPIO_LOOKUP_IDX("gpio-f7188x-3", 6, NULL, 6, GPIO_ACTIVE_HIGH),
- GPIO_LOOKUP_IDX("gpio-f7188x-3", 7, NULL, 7, GPIO_ACTIVE_HIGH),
- }
-};
-
-static const struct gpio_led simatic_ipc_gpio_leds[] = {
- { .name = "red:" LED_FUNCTION_STATUS "-1" },
- { .name = "green:" LED_FUNCTION_STATUS "-1" },
- { .name = "red:" LED_FUNCTION_STATUS "-2" },
- { .name = "green:" LED_FUNCTION_STATUS "-2" },
- { .name = "red:" LED_FUNCTION_STATUS "-3" },
- { .name = "green:" LED_FUNCTION_STATUS "-3" },
-};
-
-static const struct gpio_led_platform_data simatic_ipc_gpio_leds_pdata = {
- .num_leds = ARRAY_SIZE(simatic_ipc_gpio_leds),
- .leds = simatic_ipc_gpio_leds,
-};
-
-static struct platform_device *simatic_leds_pdev;
-
-static int simatic_ipc_leds_gpio_remove(struct platform_device *pdev)
-{
- gpiod_remove_lookup_table(simatic_ipc_led_gpio_table);
- platform_device_unregister(simatic_leds_pdev);
-
- return 0;
-}
-
-static int simatic_ipc_leds_gpio_probe(struct platform_device *pdev)
-{
- const struct simatic_ipc_platform *plat = pdev->dev.platform_data;
- struct gpio_desc *gpiod;
- int err;
-
- switch (plat->devmode) {
- case SIMATIC_IPC_DEVICE_127E:
- if (!IS_ENABLED(CONFIG_PINCTRL_BROXTON))
- return -ENODEV;
- simatic_ipc_led_gpio_table = &simatic_ipc_led_gpio_table_127e;
- break;
- case SIMATIC_IPC_DEVICE_227G:
- if (!IS_ENABLED(CONFIG_GPIO_F7188X))
- return -ENODEV;
- request_module("gpio-f7188x");
- simatic_ipc_led_gpio_table = &simatic_ipc_led_gpio_table_227g;
- break;
- default:
- return -ENODEV;
- }
-
- gpiod_add_lookup_table(simatic_ipc_led_gpio_table);
- simatic_leds_pdev = platform_device_register_resndata(NULL,
- "leds-gpio", PLATFORM_DEVID_NONE, NULL, 0,
- &simatic_ipc_gpio_leds_pdata,
- sizeof(simatic_ipc_gpio_leds_pdata));
- if (IS_ERR(simatic_leds_pdev)) {
- err = PTR_ERR(simatic_leds_pdev);
- goto out;
- }
-
- /* PM_BIOS_BOOT_N */
- gpiod = gpiod_get_index(&simatic_leds_pdev->dev, NULL, 6, GPIOD_OUT_LOW);
- if (IS_ERR(gpiod)) {
- err = PTR_ERR(gpiod);
- goto out;
- }
- gpiod_put(gpiod);
-
- /* PM_WDT_OUT */
- gpiod = gpiod_get_index(&simatic_leds_pdev->dev, NULL, 7, GPIOD_OUT_LOW);
- if (IS_ERR(gpiod)) {
- err = PTR_ERR(gpiod);
- goto out;
- }
- gpiod_put(gpiod);
-
- return 0;
-out:
- simatic_ipc_leds_gpio_remove(pdev);
-
- return err;
-}
-
-static struct platform_driver simatic_ipc_led_gpio_driver = {
- .probe = simatic_ipc_leds_gpio_probe,
- .remove = simatic_ipc_leds_gpio_remove,
- .driver = {
- .name = KBUILD_MODNAME,
- }
-};
-module_platform_driver(simatic_ipc_led_gpio_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" KBUILD_MODNAME);
-MODULE_SOFTDEP("pre: platform:leds-gpio");
-MODULE_AUTHOR("Henning Schild <henning.schild@siemens.com>");
diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio.h b/drivers/leds/simple/simatic-ipc-leds-gpio.h
new file mode 100644
index 000000000000..bf258c32f83d
--- /dev/null
+++ b/drivers/leds/simple/simatic-ipc-leds-gpio.h
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Siemens SIMATIC IPC driver for GPIO based LEDs
+ *
+ * Copyright (c) Siemens AG, 2023
+ *
+ * Author:
+ * Henning Schild <henning.schild@siemens.com>
+ */
+
+#ifndef _SIMATIC_IPC_LEDS_GPIO_H
+#define _SIMATIC_IPC_LEDS_GPIO_H
+
+int simatic_ipc_leds_gpio_probe(struct platform_device *pdev,
+ struct gpiod_lookup_table *table,
+ struct gpiod_lookup_table *table_extra);
+
+int simatic_ipc_leds_gpio_remove(struct platform_device *pdev,
+ struct gpiod_lookup_table *table,
+ struct gpiod_lookup_table *table_extra);
+
+#endif /* _SIMATIC_IPC_LEDS_GPIO_H */
diff --git a/drivers/leds/simple/simatic-ipc-leds.c b/drivers/leds/simple/simatic-ipc-leds.c
index 4894c228c165..2124f6d09930 100644
--- a/drivers/leds/simple/simatic-ipc-leds.c
+++ b/drivers/leds/simple/simatic-ipc-leds.c
@@ -126,7 +126,6 @@ static struct platform_driver simatic_ipc_led_driver = {
.name = KBUILD_MODNAME,
}
};
-
module_platform_driver(simatic_ipc_led_driver);
MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/trigger/ledtrig-disk.c b/drivers/leds/trigger/ledtrig-disk.c
index 0b7dfbd04273..e9b87ee944f2 100644
--- a/drivers/leds/trigger/ledtrig-disk.c
+++ b/drivers/leds/trigger/ledtrig-disk.c
@@ -19,16 +19,13 @@ DEFINE_LED_TRIGGER(ledtrig_disk_write);
void ledtrig_disk_activity(bool write)
{
- unsigned long blink_delay = BLINK_DELAY;
-
- led_trigger_blink_oneshot(ledtrig_disk,
- &blink_delay, &blink_delay, 0);
+ led_trigger_blink_oneshot(ledtrig_disk, BLINK_DELAY, BLINK_DELAY, 0);
if (write)
led_trigger_blink_oneshot(ledtrig_disk_write,
- &blink_delay, &blink_delay, 0);
+ BLINK_DELAY, BLINK_DELAY, 0);
else
led_trigger_blink_oneshot(ledtrig_disk_read,
- &blink_delay, &blink_delay, 0);
+ BLINK_DELAY, BLINK_DELAY, 0);
}
EXPORT_SYMBOL(ledtrig_disk_activity);
diff --git a/drivers/leds/trigger/ledtrig-mtd.c b/drivers/leds/trigger/ledtrig-mtd.c
index 8fa763c2269b..bbe6876a249d 100644
--- a/drivers/leds/trigger/ledtrig-mtd.c
+++ b/drivers/leds/trigger/ledtrig-mtd.c
@@ -22,12 +22,8 @@ DEFINE_LED_TRIGGER(ledtrig_nand);
void ledtrig_mtd_activity(void)
{
- unsigned long blink_delay = BLINK_DELAY;
-
- led_trigger_blink_oneshot(ledtrig_mtd,
- &blink_delay, &blink_delay, 0);
- led_trigger_blink_oneshot(ledtrig_nand,
- &blink_delay, &blink_delay, 0);
+ led_trigger_blink_oneshot(ledtrig_mtd, BLINK_DELAY, BLINK_DELAY, 0);
+ led_trigger_blink_oneshot(ledtrig_nand, BLINK_DELAY, BLINK_DELAY, 0);
}
EXPORT_SYMBOL(ledtrig_mtd_activity);
diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
index 32b66703068a..c9bc5a91ec83 100644
--- a/drivers/leds/trigger/ledtrig-netdev.c
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -462,8 +462,7 @@ static int netdev_trig_notify(struct notifier_block *nb,
get_device_state(trigger_data);
fallthrough;
case NETDEV_REGISTER:
- if (trigger_data->net_dev)
- dev_put(trigger_data->net_dev);
+ dev_put(trigger_data->net_dev);
dev_hold(dev);
trigger_data->net_dev = dev;
break;
@@ -594,8 +593,7 @@ static void netdev_trig_deactivate(struct led_classdev *led_cdev)
cancel_delayed_work_sync(&trigger_data->work);
- if (trigger_data->net_dev)
- dev_put(trigger_data->net_dev);
+ dev_put(trigger_data->net_dev);
kfree(trigger_data);
}
diff --git a/drivers/macintosh/ams/ams-i2c.c b/drivers/macintosh/ams/ams-i2c.c
index a4a1035eb412..f9bfe84b1c73 100644
--- a/drivers/macintosh/ams/ams-i2c.c
+++ b/drivers/macintosh/ams/ams-i2c.c
@@ -69,7 +69,7 @@ static struct i2c_driver ams_i2c_driver = {
.driver = {
.name = "ams",
},
- .probe_new = ams_i2c_probe,
+ .probe = ams_i2c_probe,
.remove = ams_i2c_remove,
.id_table = ams_id,
};
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index b495bfa77896..5183a00529f5 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -33,7 +33,8 @@
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
@@ -470,7 +471,7 @@ EXPORT_SYMBOL(smu_present);
int __init smu_init (void)
{
struct device_node *np;
- const u32 *data;
+ u64 data;
int ret = 0;
np = of_find_node_by_type(NULL, "smu");
@@ -514,8 +515,7 @@ int __init smu_init (void)
ret = -ENXIO;
goto fail_bootmem;
}
- data = of_get_property(smu->db_node, "reg", NULL);
- if (data == NULL) {
+ if (of_property_read_reg(smu->db_node, 0, &data, NULL)) {
printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n");
ret = -ENXIO;
goto fail_db_node;
@@ -525,7 +525,7 @@ int __init smu_init (void)
* and ack. GPIOs are at 0x50, best would be to find that out
* in the device-tree though.
*/
- smu->doorbell = *data;
+ smu->doorbell = data;
if (smu->doorbell < 0x50)
smu->doorbell += 0x50;
@@ -534,13 +534,12 @@ int __init smu_init (void)
smu->msg_node = of_find_node_by_name(NULL, "smu-interrupt");
if (smu->msg_node == NULL)
break;
- data = of_get_property(smu->msg_node, "reg", NULL);
- if (data == NULL) {
+ if (of_property_read_reg(smu->msg_node, 0, &data, NULL)) {
of_node_put(smu->msg_node);
smu->msg_node = NULL;
break;
}
- smu->msg = *data;
+ smu->msg = data;
if (smu->msg < 0x50)
smu->msg += 0x50;
} while(0);
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 384b87d661e1..53ea56b286f9 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -598,7 +598,7 @@ static struct i2c_driver thermostat_driver = {
.driver = {
.name = "therm_adt746x",
},
- .probe_new = probe_thermostat,
+ .probe = probe_thermostat,
.remove = remove_thermostat,
.id_table = therm_adt746x_id,
};
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 22b15efcc025..18a982454321 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -442,7 +442,7 @@ static struct i2c_driver g4fan_driver = {
.driver = {
.name = "therm_windtunnel",
},
- .probe_new = do_probe,
+ .probe = do_probe,
.remove = do_remove,
.id_table = therm_windtunnel_id,
};
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index 5071289063f0..f8dd1e831530 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -235,8 +235,7 @@ int __init find_via_cuda(void)
int __init find_via_cuda(void)
{
struct adb_request req;
- phys_addr_t taddr;
- const u32 *reg;
+ struct resource res;
int err;
if (vias)
@@ -245,17 +244,12 @@ int __init find_via_cuda(void)
if (!vias)
return 0;
- reg = of_get_property(vias, "reg", NULL);
- if (reg == NULL) {
- printk(KERN_ERR "via-cuda: No \"reg\" property !\n");
- goto fail;
- }
- taddr = of_translate_address(vias, reg);
- if (taddr == 0) {
- printk(KERN_ERR "via-cuda: Can't translate address !\n");
+ err = of_address_to_resource(vias, 0, &res);
+ if (err) {
+ printk(KERN_ERR "via-cuda: Error getting \"reg\" property !\n");
goto fail;
}
- via = ioremap(taddr, 0x2000);
+ via = ioremap(res.start, 0x2000);
if (via == NULL) {
printk(KERN_ERR "via-cuda: Can't map address !\n");
goto fail;
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index e0cb8daf4f08..9d5703b60937 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -286,8 +286,9 @@ static char *pbook_type[] = {
int __init find_via_pmu(void)
{
#ifdef CONFIG_PPC_PMAC
+ int err;
u64 taddr;
- const u32 *reg;
+ struct resource res;
if (pmu_state != uninitialized)
return 1;
@@ -295,16 +296,12 @@ int __init find_via_pmu(void)
if (vias == NULL)
return 0;
- reg = of_get_property(vias, "reg", NULL);
- if (reg == NULL) {
- printk(KERN_ERR "via-pmu: No \"reg\" property !\n");
- goto fail;
- }
- taddr = of_translate_address(vias, reg);
- if (taddr == OF_BAD_ADDR) {
- printk(KERN_ERR "via-pmu: Can't translate address !\n");
+ err = of_address_to_resource(vias, 0, &res);
+ if (err) {
+ printk(KERN_ERR "via-pmu: Error getting \"reg\" property !\n");
goto fail;
}
+ taddr = res.start;
pmu_has_adb = 1;
@@ -324,7 +321,6 @@ int __init find_via_pmu(void)
|| of_device_is_compatible(vias->parent, "K2-Keylargo")) {
struct device_node *gpiop;
struct device_node *adbp;
- u64 gaddr = OF_BAD_ADDR;
pmu_kind = PMU_KEYLARGO_BASED;
adbp = of_find_node_by_type(NULL, "adb");
@@ -338,11 +334,8 @@ int __init find_via_pmu(void)
gpiop = of_find_node_by_name(NULL, "gpio");
if (gpiop) {
- reg = of_get_property(gpiop, "reg", NULL);
- if (reg)
- gaddr = of_translate_address(gpiop, reg);
- if (gaddr != OF_BAD_ADDR)
- gpio_reg = ioremap(gaddr, 0x10);
+ if (!of_address_to_resource(gpiop, 0, &res))
+ gpio_reg = ioremap(res.start, 0x10);
of_node_put(gpiop);
}
if (gpio_reg == NULL) {
diff --git a/drivers/macintosh/windfarm_ad7417_sensor.c b/drivers/macintosh/windfarm_ad7417_sensor.c
index 33b4723d235e..49ce37fde930 100644
--- a/drivers/macintosh/windfarm_ad7417_sensor.c
+++ b/drivers/macintosh/windfarm_ad7417_sensor.c
@@ -320,7 +320,7 @@ static struct i2c_driver wf_ad7417_driver = {
.name = "wf_ad7417",
.of_match_table = wf_ad7417_of_id,
},
- .probe_new = wf_ad7417_probe,
+ .probe = wf_ad7417_probe,
.remove = wf_ad7417_remove,
.id_table = wf_ad7417_id,
};
diff --git a/drivers/macintosh/windfarm_fcu_controls.c b/drivers/macintosh/windfarm_fcu_controls.c
index e027d889d7e8..603ef6c600ba 100644
--- a/drivers/macintosh/windfarm_fcu_controls.c
+++ b/drivers/macintosh/windfarm_fcu_controls.c
@@ -589,7 +589,7 @@ static struct i2c_driver wf_fcu_driver = {
.name = "wf_fcu",
.of_match_table = wf_fcu_of_id,
},
- .probe_new = wf_fcu_probe,
+ .probe = wf_fcu_probe,
.remove = wf_fcu_remove,
.id_table = wf_fcu_id,
};
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index 9c6febce2376..48dbdb2bda15 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -177,7 +177,7 @@ static struct i2c_driver wf_lm75_driver = {
.name = "wf_lm75",
.of_match_table = wf_lm75_of_id,
},
- .probe_new = wf_lm75_probe,
+ .probe = wf_lm75_probe,
.remove = wf_lm75_remove,
.id_table = wf_lm75_id,
};
diff --git a/drivers/macintosh/windfarm_lm87_sensor.c b/drivers/macintosh/windfarm_lm87_sensor.c
index f37a32c2070c..975361c23a93 100644
--- a/drivers/macintosh/windfarm_lm87_sensor.c
+++ b/drivers/macintosh/windfarm_lm87_sensor.c
@@ -172,7 +172,7 @@ static struct i2c_driver wf_lm87_driver = {
.name = "wf_lm87",
.of_match_table = wf_lm87_of_id,
},
- .probe_new = wf_lm87_probe,
+ .probe = wf_lm87_probe,
.remove = wf_lm87_remove,
.id_table = wf_lm87_id,
};
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
index 6c5ab657b6b3..02856d1f0313 100644
--- a/drivers/macintosh/windfarm_max6690_sensor.c
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -128,7 +128,7 @@ static struct i2c_driver wf_max6690_driver = {
.name = "wf_max6690",
.of_match_table = wf_max6690_of_id,
},
- .probe_new = wf_max6690_probe,
+ .probe = wf_max6690_probe,
.remove = wf_max6690_remove,
.id_table = wf_max6690_id,
};
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index 089f2743a070..50baa062c9df 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -349,7 +349,7 @@ static struct i2c_driver wf_sat_driver = {
.name = "wf_smu_sat",
.of_match_table = wf_sat_of_id,
},
- .probe_new = wf_sat_probe,
+ .probe = wf_sat_probe,
.remove = wf_sat_remove,
.id_table = wf_sat_id,
};
diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index 573481e436f5..7f98e7436d94 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2016-2023, NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/delay.h>
@@ -97,6 +97,7 @@ struct tegra_hsp_soc {
const struct tegra_hsp_db_map *map;
bool has_per_mb_ie;
bool has_128_bit_mb;
+ unsigned int reg_stride;
};
struct tegra_hsp {
@@ -279,7 +280,7 @@ tegra_hsp_doorbell_create(struct tegra_hsp *hsp, const char *name,
return ERR_PTR(-ENOMEM);
offset = (1 + (hsp->num_sm / 2) + hsp->num_ss + hsp->num_as) * SZ_64K;
- offset += index * 0x100;
+ offset += index * hsp->soc->reg_stride;
db->channel.regs = hsp->regs + offset;
db->channel.hsp = hsp;
@@ -916,24 +917,35 @@ static const struct tegra_hsp_soc tegra186_hsp_soc = {
.map = tegra186_hsp_db_map,
.has_per_mb_ie = false,
.has_128_bit_mb = false,
+ .reg_stride = 0x100,
};
static const struct tegra_hsp_soc tegra194_hsp_soc = {
.map = tegra186_hsp_db_map,
.has_per_mb_ie = true,
.has_128_bit_mb = false,
+ .reg_stride = 0x100,
};
static const struct tegra_hsp_soc tegra234_hsp_soc = {
.map = tegra186_hsp_db_map,
.has_per_mb_ie = false,
.has_128_bit_mb = true,
+ .reg_stride = 0x100,
+};
+
+static const struct tegra_hsp_soc tegra264_hsp_soc = {
+ .map = tegra186_hsp_db_map,
+ .has_per_mb_ie = false,
+ .has_128_bit_mb = true,
+ .reg_stride = 0x1000,
};
static const struct of_device_id tegra_hsp_match[] = {
{ .compatible = "nvidia,tegra186-hsp", .data = &tegra186_hsp_soc },
{ .compatible = "nvidia,tegra194-hsp", .data = &tegra194_hsp_soc },
{ .compatible = "nvidia,tegra234-hsp", .data = &tegra234_hsp_soc },
+ { .compatible = "nvidia,tegra264-hsp", .data = &tegra264_hsp_soc },
{ }
};
diff --git a/drivers/mailbox/ti-msgmgr.c b/drivers/mailbox/ti-msgmgr.c
index ddac423ac1a9..03048cbda525 100644
--- a/drivers/mailbox/ti-msgmgr.c
+++ b/drivers/mailbox/ti-msgmgr.c
@@ -430,14 +430,20 @@ static int ti_msgmgr_send_data(struct mbox_chan *chan, void *data)
/* Ensure all unused data is 0 */
data_trail &= 0xFFFFFFFF >> (8 * (sizeof(u32) - trail_bytes));
writel(data_trail, data_reg);
- data_reg++;
+ data_reg += sizeof(u32);
}
+
/*
* 'data_reg' indicates next register to write. If we did not already
* write on tx complete reg(last reg), we must do so for transmit
+ * In addition, we also need to make sure all intermediate data
+ * registers(if any required), are reset to 0 for TISCI backward
+ * compatibility to be maintained.
*/
- if (data_reg <= qinst->queue_buff_end)
- writel(0, qinst->queue_buff_end);
+ while (data_reg <= qinst->queue_buff_end) {
+ writel(0, data_reg);
+ data_reg += sizeof(u32);
+ }
/* If we are in polled mode, wait for a response before proceeding */
if (ti_msgmgr_chan_has_polled_queue_rx(message->chan_rx))
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index e2a803683105..0ae2b3676293 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1369,7 +1369,7 @@ static void cached_dev_free(struct closure *cl)
put_page(virt_to_page(dc->sb_disk));
if (!IS_ERR_OR_NULL(dc->bdev))
- blkdev_put(dc->bdev, bcache_kobj);
+ blkdev_put(dc->bdev, dc);
wake_up(&unregister_wait);
@@ -1453,7 +1453,6 @@ static int register_bdev(struct cache_sb *sb, struct cache_sb_disk *sb_disk,
memcpy(&dc->sb, sb, sizeof(struct cache_sb));
dc->bdev = bdev;
- dc->bdev->bd_holder = dc;
dc->sb_disk = sb_disk;
if (cached_dev_init(dc, sb->block_size << 9))
@@ -2218,7 +2217,7 @@ void bch_cache_release(struct kobject *kobj)
put_page(virt_to_page(ca->sb_disk));
if (!IS_ERR_OR_NULL(ca->bdev))
- blkdev_put(ca->bdev, bcache_kobj);
+ blkdev_put(ca->bdev, ca);
kfree(ca);
module_put(THIS_MODULE);
@@ -2345,7 +2344,6 @@ static int register_cache(struct cache_sb *sb, struct cache_sb_disk *sb_disk,
memcpy(&ca->sb, sb, sizeof(struct cache_sb));
ca->bdev = bdev;
- ca->bdev->bd_holder = ca;
ca->sb_disk = sb_disk;
if (bdev_max_discard_sectors((bdev)))
@@ -2359,7 +2357,7 @@ static int register_cache(struct cache_sb *sb, struct cache_sb_disk *sb_disk,
* call blkdev_put() to bdev in bch_cache_release(). So we
* explicitly call blkdev_put() here.
*/
- blkdev_put(bdev, bcache_kobj);
+ blkdev_put(bdev, ca);
if (ret == -ENOMEM)
err = "cache_alloc(): -ENOMEM";
else if (ret == -EPERM)
@@ -2448,6 +2446,7 @@ struct async_reg_args {
struct cache_sb *sb;
struct cache_sb_disk *sb_disk;
struct block_device *bdev;
+ void *holder;
};
static void register_bdev_worker(struct work_struct *work)
@@ -2455,22 +2454,13 @@ static void register_bdev_worker(struct work_struct *work)
int fail = false;
struct async_reg_args *args =
container_of(work, struct async_reg_args, reg_work.work);
- struct cached_dev *dc;
-
- dc = kzalloc(sizeof(*dc), GFP_KERNEL);
- if (!dc) {
- fail = true;
- put_page(virt_to_page(args->sb_disk));
- blkdev_put(args->bdev, bcache_kobj);
- goto out;
- }
mutex_lock(&bch_register_lock);
- if (register_bdev(args->sb, args->sb_disk, args->bdev, dc) < 0)
+ if (register_bdev(args->sb, args->sb_disk, args->bdev, args->holder)
+ < 0)
fail = true;
mutex_unlock(&bch_register_lock);
-out:
if (fail)
pr_info("error %s: fail to register backing device\n",
args->path);
@@ -2485,21 +2475,11 @@ static void register_cache_worker(struct work_struct *work)
int fail = false;
struct async_reg_args *args =
container_of(work, struct async_reg_args, reg_work.work);
- struct cache *ca;
-
- ca = kzalloc(sizeof(*ca), GFP_KERNEL);
- if (!ca) {
- fail = true;
- put_page(virt_to_page(args->sb_disk));
- blkdev_put(args->bdev, bcache_kobj);
- goto out;
- }
/* blkdev_put() will be called in bch_cache_release() */
- if (register_cache(args->sb, args->sb_disk, args->bdev, ca) != 0)
+ if (register_cache(args->sb, args->sb_disk, args->bdev, args->holder))
fail = true;
-out:
if (fail)
pr_info("error %s: fail to register cache device\n",
args->path);
@@ -2520,6 +2500,13 @@ static void register_device_async(struct async_reg_args *args)
queue_delayed_work(system_wq, &args->reg_work, 10);
}
+static void *alloc_holder_object(struct cache_sb *sb)
+{
+ if (SB_IS_BDEV(sb))
+ return kzalloc(sizeof(struct cached_dev), GFP_KERNEL);
+ return kzalloc(sizeof(struct cache), GFP_KERNEL);
+}
+
static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
const char *buffer, size_t size)
{
@@ -2527,9 +2514,11 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
char *path = NULL;
struct cache_sb *sb;
struct cache_sb_disk *sb_disk;
- struct block_device *bdev;
+ struct block_device *bdev, *bdev2;
+ void *holder = NULL;
ssize_t ret;
bool async_registration = false;
+ bool quiet = false;
#ifdef CONFIG_BCACHE_ASYNC_REGISTRATION
async_registration = true;
@@ -2558,10 +2547,34 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
ret = -EINVAL;
err = "failed to open device";
- bdev = blkdev_get_by_path(strim(path), BLK_OPEN_READ | BLK_OPEN_WRITE,
- bcache_kobj, NULL);
+ bdev = blkdev_get_by_path(strim(path), BLK_OPEN_READ, NULL, NULL);
+ if (IS_ERR(bdev))
+ goto out_free_sb;
+
+ err = "failed to set blocksize";
+ if (set_blocksize(bdev, 4096))
+ goto out_blkdev_put;
+
+ err = read_super(sb, bdev, &sb_disk);
+ if (err)
+ goto out_blkdev_put;
+
+ holder = alloc_holder_object(sb);
+ if (!holder) {
+ ret = -ENOMEM;
+ err = "cannot allocate memory";
+ goto out_put_sb_page;
+ }
+
+ /* Now reopen in exclusive mode with proper holder */
+ bdev2 = blkdev_get_by_dev(bdev->bd_dev, BLK_OPEN_READ | BLK_OPEN_WRITE,
+ holder, NULL);
+ blkdev_put(bdev, NULL);
+ bdev = bdev2;
if (IS_ERR(bdev)) {
- if (bdev == ERR_PTR(-EBUSY)) {
+ ret = PTR_ERR(bdev);
+ bdev = NULL;
+ if (ret == -EBUSY) {
dev_t dev;
mutex_lock(&bch_register_lock);
@@ -2571,20 +2584,14 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
else
err = "device busy";
mutex_unlock(&bch_register_lock);
- if (attr == &ksysfs_register_quiet)
- goto done;
+ if (attr == &ksysfs_register_quiet) {
+ quiet = true;
+ ret = size;
+ }
}
- goto out_free_sb;
+ goto out_free_holder;
}
- err = "failed to set blocksize";
- if (set_blocksize(bdev, 4096))
- goto out_blkdev_put;
-
- err = read_super(sb, bdev, &sb_disk);
- if (err)
- goto out_blkdev_put;
-
err = "failed to register device";
if (async_registration) {
@@ -2595,59 +2602,46 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
if (!args) {
ret = -ENOMEM;
err = "cannot allocate memory";
- goto out_put_sb_page;
+ goto out_free_holder;
}
args->path = path;
args->sb = sb;
args->sb_disk = sb_disk;
args->bdev = bdev;
+ args->holder = holder;
register_device_async(args);
/* No wait and returns to user space */
goto async_done;
}
if (SB_IS_BDEV(sb)) {
- struct cached_dev *dc = kzalloc(sizeof(*dc), GFP_KERNEL);
-
- if (!dc) {
- ret = -ENOMEM;
- err = "cannot allocate memory";
- goto out_put_sb_page;
- }
-
mutex_lock(&bch_register_lock);
- ret = register_bdev(sb, sb_disk, bdev, dc);
+ ret = register_bdev(sb, sb_disk, bdev, holder);
mutex_unlock(&bch_register_lock);
/* blkdev_put() will be called in cached_dev_free() */
if (ret < 0)
goto out_free_sb;
} else {
- struct cache *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
-
- if (!ca) {
- ret = -ENOMEM;
- err = "cannot allocate memory";
- goto out_put_sb_page;
- }
-
/* blkdev_put() will be called in bch_cache_release() */
- ret = register_cache(sb, sb_disk, bdev, ca);
+ ret = register_cache(sb, sb_disk, bdev, holder);
if (ret)
goto out_free_sb;
}
-done:
kfree(sb);
kfree(path);
module_put(THIS_MODULE);
async_done:
return size;
+out_free_holder:
+ kfree(holder);
out_put_sb_page:
put_page(virt_to_page(sb_disk));
out_blkdev_put:
- blkdev_put(bdev, register_bcache);
+ if (bdev)
+ blkdev_put(bdev, holder);
out_free_sb:
kfree(sb);
out_free_path:
@@ -2656,7 +2650,8 @@ out_free_path:
out_module_put:
module_put(THIS_MODULE);
out:
- pr_info("error %s: %s\n", path?path:"", err);
+ if (!quiet)
+ pr_info("error %s: %s\n", path?path:"", err);
return ret;
}
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index eea977662e81..bc309e41d074 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -1157,23 +1157,6 @@ static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
*data_mode = DATA_MODE_VMALLOC;
- /*
- * __vmalloc allocates the data pages and auxiliary structures with
- * gfp_flags that were specified, but pagetables are always allocated
- * with GFP_KERNEL, no matter what was specified as gfp_mask.
- *
- * Consequently, we must set per-process flag PF_MEMALLOC_NOIO so that
- * all allocations done by this process (including pagetables) are done
- * as if GFP_NOIO was specified.
- */
- if (gfp_mask & __GFP_NORETRY) {
- unsigned int noio_flag = memalloc_noio_save();
- void *ptr = __vmalloc(c->block_size, gfp_mask);
-
- memalloc_noio_restore(noio_flag);
- return ptr;
- }
-
return __vmalloc(c->block_size, gfp_mask);
}
@@ -2592,6 +2575,13 @@ void dm_bufio_client_destroy(struct dm_bufio_client *c)
}
EXPORT_SYMBOL_GPL(dm_bufio_client_destroy);
+void dm_bufio_client_reset(struct dm_bufio_client *c)
+{
+ drop_buffers(c);
+ flush_work(&c->shrink_work);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_client_reset);
+
void dm_bufio_set_sector_offset(struct dm_bufio_client *c, sector_t start)
{
c->start = start;
diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h
index ce913ad91a52..0d93661f88d3 100644
--- a/drivers/md/dm-core.h
+++ b/drivers/md/dm-core.h
@@ -306,7 +306,8 @@ struct dm_io {
*/
enum {
DM_IO_ACCOUNTED,
- DM_IO_WAS_SPLIT
+ DM_IO_WAS_SPLIT,
+ DM_IO_BLK_STAT
};
static inline bool dm_io_flagged(struct dm_io *io, unsigned int bit)
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 15424bfea7ee..1dc6227d353e 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -31,10 +31,10 @@
#include <asm/unaligned.h>
#include <crypto/hash.h>
#include <crypto/md5.h>
-#include <crypto/algapi.h>
#include <crypto/skcipher.h>
#include <crypto/aead.h>
#include <crypto/authenc.h>
+#include <crypto/utils.h>
#include <linux/rtnetlink.h> /* for struct rtattr and RTA macros only */
#include <linux/key-type.h>
#include <keys/user-type.h>
@@ -745,16 +745,23 @@ static int crypt_iv_eboiv_ctr(struct crypt_config *cc, struct dm_target *ti,
static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv,
struct dm_crypt_request *dmreq)
{
- u8 buf[MAX_CIPHER_BLOCKSIZE] __aligned(__alignof__(__le64));
+ struct crypto_skcipher *tfm = any_tfm(cc);
struct skcipher_request *req;
struct scatterlist src, dst;
DECLARE_CRYPTO_WAIT(wait);
+ unsigned int reqsize;
int err;
+ u8 *buf;
- req = skcipher_request_alloc(any_tfm(cc), GFP_NOIO);
+ reqsize = ALIGN(crypto_skcipher_reqsize(tfm), __alignof__(__le64));
+
+ req = kmalloc(reqsize + cc->iv_size, GFP_NOIO);
if (!req)
return -ENOMEM;
+ skcipher_request_set_tfm(req, tfm);
+
+ buf = (u8 *)req + reqsize;
memset(buf, 0, cc->iv_size);
*(__le64 *)buf = cpu_to_le64(dmreq->iv_sector * cc->sector_size);
@@ -763,7 +770,7 @@ static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv,
skcipher_request_set_crypt(req, &src, &dst, cc->iv_size, buf);
skcipher_request_set_callback(req, 0, crypto_req_done, &wait);
err = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
- skcipher_request_free(req);
+ kfree_sensitive(req);
return err;
}
@@ -1661,6 +1668,9 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone);
* In order to not degrade performance with excessive locking, we try
* non-blocking allocations without a mutex first but on failure we fallback
* to blocking allocations with a mutex.
+ *
+ * In order to reduce allocation overhead, we try to allocate compound pages in
+ * the first pass. If they are not available, we fall back to the mempool.
*/
static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size)
{
@@ -1668,8 +1678,8 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size)
struct bio *clone;
unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
gfp_t gfp_mask = GFP_NOWAIT | __GFP_HIGHMEM;
- unsigned int i, len, remaining_size;
- struct page *page;
+ unsigned int remaining_size;
+ unsigned int order = MAX_ORDER - 1;
retry:
if (unlikely(gfp_mask & __GFP_DIRECT_RECLAIM))
@@ -1682,19 +1692,34 @@ retry:
remaining_size = size;
- for (i = 0; i < nr_iovecs; i++) {
- page = mempool_alloc(&cc->page_pool, gfp_mask);
- if (!page) {
+ while (remaining_size) {
+ struct page *pages;
+ unsigned size_to_add;
+ unsigned remaining_order = __fls((remaining_size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+ order = min(order, remaining_order);
+
+ while (order > 0) {
+ pages = alloc_pages(gfp_mask
+ | __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | __GFP_COMP,
+ order);
+ if (likely(pages != NULL))
+ goto have_pages;
+ order--;
+ }
+
+ pages = mempool_alloc(&cc->page_pool, gfp_mask);
+ if (!pages) {
crypt_free_buffer_pages(cc, clone);
bio_put(clone);
gfp_mask |= __GFP_DIRECT_RECLAIM;
+ order = 0;
goto retry;
}
- len = (remaining_size > PAGE_SIZE) ? PAGE_SIZE : remaining_size;
-
- __bio_add_page(clone, page, len, 0);
- remaining_size -= len;
+have_pages:
+ size_to_add = min((unsigned)PAGE_SIZE << order, remaining_size);
+ __bio_add_page(clone, pages, size_to_add, 0);
+ remaining_size -= size_to_add;
}
/* Allocate space for integrity tags */
@@ -1712,12 +1737,15 @@ retry:
static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone)
{
- struct bio_vec *bv;
- struct bvec_iter_all iter_all;
+ struct folio_iter fi;
- bio_for_each_segment_all(bv, clone, iter_all) {
- BUG_ON(!bv->bv_page);
- mempool_free(bv->bv_page, &cc->page_pool);
+ if (clone->bi_vcnt > 0) { /* bio_for_each_folio_all crashes with an empty bio */
+ bio_for_each_folio_all(fi, clone) {
+ if (folio_test_large(fi.folio))
+ folio_put(fi.folio);
+ else
+ mempool_free(&fi.folio->page, &cc->page_pool);
+ }
}
}
@@ -2887,7 +2915,7 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key
ret = crypt_ctr_auth_cipher(cc, cipher_api);
if (ret < 0) {
ti->error = "Invalid AEAD cipher spec";
- return -ENOMEM;
+ return ret;
}
}
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index bd80bcafbe50..120153e44ae0 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -16,6 +16,8 @@
#define DM_MSG_PREFIX "flakey"
+#define PROBABILITY_BASE 1000000000
+
#define all_corrupt_bio_flags_match(bio, fc) \
(((bio)->bi_opf & (fc)->corrupt_bio_flags) == (fc)->corrupt_bio_flags)
@@ -34,6 +36,8 @@ struct flakey_c {
unsigned int corrupt_bio_rw;
unsigned int corrupt_bio_value;
blk_opf_t corrupt_bio_flags;
+ unsigned int random_read_corrupt;
+ unsigned int random_write_corrupt;
};
enum feature_flag_bits {
@@ -54,10 +58,11 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
const char *arg_name;
static const struct dm_arg _args[] = {
- {0, 7, "Invalid number of feature args"},
+ {0, 11, "Invalid number of feature args"},
{1, UINT_MAX, "Invalid corrupt bio byte"},
{0, 255, "Invalid corrupt value to write into bio byte (0-255)"},
{0, UINT_MAX, "Invalid corrupt bio flags mask"},
+ {0, PROBABILITY_BASE, "Invalid random corrupt argument"},
};
/* No feature arguments supplied. */
@@ -170,6 +175,32 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
continue;
}
+ if (!strcasecmp(arg_name, "random_read_corrupt")) {
+ if (!argc) {
+ ti->error = "Feature random_read_corrupt requires a parameter";
+ return -EINVAL;
+ }
+ r = dm_read_arg(_args + 4, as, &fc->random_read_corrupt, &ti->error);
+ if (r)
+ return r;
+ argc--;
+
+ continue;
+ }
+
+ if (!strcasecmp(arg_name, "random_write_corrupt")) {
+ if (!argc) {
+ ti->error = "Feature random_write_corrupt requires a parameter";
+ return -EINVAL;
+ }
+ r = dm_read_arg(_args + 4, as, &fc->random_write_corrupt, &ti->error);
+ if (r)
+ return r;
+ argc--;
+
+ continue;
+ }
+
ti->error = "Unrecognised flakey feature requested";
return -EINVAL;
}
@@ -184,7 +215,8 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
}
if (!fc->corrupt_bio_byte && !test_bit(ERROR_READS, &fc->flags) &&
- !test_bit(DROP_WRITES, &fc->flags) && !test_bit(ERROR_WRITES, &fc->flags)) {
+ !test_bit(DROP_WRITES, &fc->flags) && !test_bit(ERROR_WRITES, &fc->flags) &&
+ !fc->random_read_corrupt && !fc->random_write_corrupt) {
set_bit(ERROR_WRITES, &fc->flags);
set_bit(ERROR_READS, &fc->flags);
}
@@ -306,40 +338,143 @@ static void flakey_map_bio(struct dm_target *ti, struct bio *bio)
bio->bi_iter.bi_sector = flakey_map_sector(ti, bio->bi_iter.bi_sector);
}
-static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc)
+static void corrupt_bio_common(struct bio *bio, unsigned int corrupt_bio_byte,
+ unsigned char corrupt_bio_value)
{
- unsigned int corrupt_bio_byte = fc->corrupt_bio_byte - 1;
-
struct bvec_iter iter;
struct bio_vec bvec;
- if (!bio_has_data(bio))
- return;
-
/*
* Overwrite the Nth byte of the bio's data, on whichever page
* it falls.
*/
bio_for_each_segment(bvec, bio, iter) {
if (bio_iter_len(bio, iter) > corrupt_bio_byte) {
- char *segment;
- struct page *page = bio_iter_page(bio, iter);
- if (unlikely(page == ZERO_PAGE(0)))
- break;
- segment = bvec_kmap_local(&bvec);
- segment[corrupt_bio_byte] = fc->corrupt_bio_value;
+ unsigned char *segment = bvec_kmap_local(&bvec);
+ segment[corrupt_bio_byte] = corrupt_bio_value;
kunmap_local(segment);
DMDEBUG("Corrupting data bio=%p by writing %u to byte %u "
"(rw=%c bi_opf=%u bi_sector=%llu size=%u)\n",
- bio, fc->corrupt_bio_value, fc->corrupt_bio_byte,
+ bio, corrupt_bio_value, corrupt_bio_byte,
(bio_data_dir(bio) == WRITE) ? 'w' : 'r', bio->bi_opf,
- (unsigned long long)bio->bi_iter.bi_sector, bio->bi_iter.bi_size);
+ (unsigned long long)bio->bi_iter.bi_sector,
+ bio->bi_iter.bi_size);
break;
}
corrupt_bio_byte -= bio_iter_len(bio, iter);
}
}
+static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc)
+{
+ unsigned int corrupt_bio_byte = fc->corrupt_bio_byte - 1;
+
+ if (!bio_has_data(bio))
+ return;
+
+ corrupt_bio_common(bio, corrupt_bio_byte, fc->corrupt_bio_value);
+}
+
+static void corrupt_bio_random(struct bio *bio)
+{
+ unsigned int corrupt_byte;
+ unsigned char corrupt_value;
+
+ if (!bio_has_data(bio))
+ return;
+
+ corrupt_byte = get_random_u32() % bio->bi_iter.bi_size;
+ corrupt_value = get_random_u8();
+
+ corrupt_bio_common(bio, corrupt_byte, corrupt_value);
+}
+
+static void clone_free(struct bio *clone)
+{
+ struct folio_iter fi;
+
+ if (clone->bi_vcnt > 0) { /* bio_for_each_folio_all crashes with an empty bio */
+ bio_for_each_folio_all(fi, clone)
+ folio_put(fi.folio);
+ }
+
+ bio_uninit(clone);
+ kfree(clone);
+}
+
+static void clone_endio(struct bio *clone)
+{
+ struct bio *bio = clone->bi_private;
+ bio->bi_status = clone->bi_status;
+ clone_free(clone);
+ bio_endio(bio);
+}
+
+static struct bio *clone_bio(struct dm_target *ti, struct flakey_c *fc, struct bio *bio)
+{
+ struct bio *clone;
+ unsigned size, remaining_size, nr_iovecs, order;
+ struct bvec_iter iter = bio->bi_iter;
+
+ if (unlikely(bio->bi_iter.bi_size > UIO_MAXIOV << PAGE_SHIFT))
+ dm_accept_partial_bio(bio, UIO_MAXIOV << PAGE_SHIFT >> SECTOR_SHIFT);
+
+ size = bio->bi_iter.bi_size;
+ nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ clone = bio_kmalloc(nr_iovecs, GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN);
+ if (!clone)
+ return NULL;
+
+ bio_init(clone, fc->dev->bdev, bio->bi_inline_vecs, nr_iovecs, bio->bi_opf);
+
+ clone->bi_iter.bi_sector = flakey_map_sector(ti, bio->bi_iter.bi_sector);
+ clone->bi_private = bio;
+ clone->bi_end_io = clone_endio;
+
+ remaining_size = size;
+
+ order = MAX_ORDER - 1;
+ while (remaining_size) {
+ struct page *pages;
+ unsigned size_to_add, to_copy;
+ unsigned char *virt;
+ unsigned remaining_order = __fls((remaining_size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+ order = min(order, remaining_order);
+
+retry_alloc_pages:
+ pages = alloc_pages(GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN | __GFP_COMP, order);
+ if (unlikely(!pages)) {
+ if (order) {
+ order--;
+ goto retry_alloc_pages;
+ }
+ clone_free(clone);
+ return NULL;
+ }
+ size_to_add = min((unsigned)PAGE_SIZE << order, remaining_size);
+
+ virt = page_to_virt(pages);
+ to_copy = size_to_add;
+ do {
+ struct bio_vec bvec = bvec_iter_bvec(bio->bi_io_vec, iter);
+ unsigned this_step = min(bvec.bv_len, to_copy);
+ void *map = bvec_kmap_local(&bvec);
+ memcpy(virt, map, this_step);
+ kunmap_local(map);
+
+ bvec_iter_advance(bio->bi_io_vec, &iter, this_step);
+ to_copy -= this_step;
+ virt += this_step;
+ } while (to_copy);
+
+ __bio_add_page(clone, pages, size_to_add, 0);
+ remaining_size -= size_to_add;
+ }
+
+ return clone;
+}
+
static int flakey_map(struct dm_target *ti, struct bio *bio)
{
struct flakey_c *fc = ti->private;
@@ -354,6 +489,7 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
/* Are we alive ? */
elapsed = (jiffies - fc->start_time) / HZ;
if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval) {
+ bool corrupt_fixed, corrupt_random;
/*
* Flag this bio as submitted while down.
*/
@@ -383,12 +519,28 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
/*
* Corrupt matching writes.
*/
- if (fc->corrupt_bio_byte) {
- if (fc->corrupt_bio_rw == WRITE) {
- if (all_corrupt_bio_flags_match(bio, fc))
- corrupt_bio_data(bio, fc);
+ corrupt_fixed = false;
+ corrupt_random = false;
+ if (fc->corrupt_bio_byte && fc->corrupt_bio_rw == WRITE) {
+ if (all_corrupt_bio_flags_match(bio, fc))
+ corrupt_fixed = true;
+ }
+ if (fc->random_write_corrupt) {
+ u64 rnd = get_random_u64();
+ u32 rem = do_div(rnd, PROBABILITY_BASE);
+ if (rem < fc->random_write_corrupt)
+ corrupt_random = true;
+ }
+ if (corrupt_fixed || corrupt_random) {
+ struct bio *clone = clone_bio(ti, fc, bio);
+ if (clone) {
+ if (corrupt_fixed)
+ corrupt_bio_data(clone, fc);
+ if (corrupt_random)
+ corrupt_bio_random(clone);
+ submit_bio(clone);
+ return DM_MAPIO_SUBMITTED;
}
- goto map_bio;
}
}
@@ -417,6 +569,12 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio,
corrupt_bio_data(bio, fc);
}
}
+ if (fc->random_read_corrupt) {
+ u64 rnd = get_random_u64();
+ u32 rem = do_div(rnd, PROBABILITY_BASE);
+ if (rem < fc->random_read_corrupt)
+ corrupt_bio_random(bio);
+ }
if (test_bit(ERROR_READS, &fc->flags)) {
/*
* Error read during the down_interval if drop_writes
@@ -449,7 +607,10 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
error_reads = test_bit(ERROR_READS, &fc->flags);
drop_writes = test_bit(DROP_WRITES, &fc->flags);
error_writes = test_bit(ERROR_WRITES, &fc->flags);
- DMEMIT(" %u", error_reads + drop_writes + error_writes + (fc->corrupt_bio_byte > 0) * 5);
+ DMEMIT(" %u", error_reads + drop_writes + error_writes +
+ (fc->corrupt_bio_byte > 0) * 5 +
+ (fc->random_read_corrupt > 0) * 2 +
+ (fc->random_write_corrupt > 0) * 2);
if (error_reads)
DMEMIT(" error_reads");
@@ -464,6 +625,11 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
(fc->corrupt_bio_rw == WRITE) ? 'w' : 'r',
fc->corrupt_bio_value, fc->corrupt_bio_flags);
+ if (fc->random_read_corrupt > 0)
+ DMEMIT(" random_read_corrupt %u", fc->random_read_corrupt);
+ if (fc->random_write_corrupt > 0)
+ DMEMIT(" random_write_corrupt %u", fc->random_write_corrupt);
+
break;
case STATUSTYPE_IMA:
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 63ec502fcb12..3d5c56e0a062 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -34,11 +34,11 @@
#define DEFAULT_BUFFER_SECTORS 128
#define DEFAULT_JOURNAL_WATERMARK 50
#define DEFAULT_SYNC_MSEC 10000
-#define DEFAULT_MAX_JOURNAL_SECTORS 131072
+#define DEFAULT_MAX_JOURNAL_SECTORS (IS_ENABLED(CONFIG_64BIT) ? 131072 : 8192)
#define MIN_LOG2_INTERLEAVE_SECTORS 3
#define MAX_LOG2_INTERLEAVE_SECTORS 31
#define METADATA_WORKQUEUE_MAX_ACTIVE 16
-#define RECALC_SECTORS 32768
+#define RECALC_SECTORS (IS_ENABLED(CONFIG_64BIT) ? 32768 : 2048)
#define RECALC_WRITE_SUPER 16
#define BITMAP_BLOCK_SIZE 4096 /* don't change it */
#define BITMAP_FLUSH_INTERVAL (10 * HZ)
@@ -251,8 +251,6 @@ struct dm_integrity_c {
struct workqueue_struct *recalc_wq;
struct work_struct recalc_work;
- u8 *recalc_buffer;
- u8 *recalc_tags;
struct bio_list flush_bio_list;
@@ -342,24 +340,9 @@ static struct kmem_cache *journal_io_cache;
#define JOURNAL_IO_MEMPOOL 32
#ifdef DEBUG_PRINT
-#define DEBUG_print(x, ...) printk(KERN_DEBUG x, ##__VA_ARGS__)
-static void __DEBUG_bytes(__u8 *bytes, size_t len, const char *msg, ...)
-{
- va_list args;
-
- va_start(args, msg);
- vprintk(msg, args);
- va_end(args);
- if (len)
- pr_cont(":");
- while (len) {
- pr_cont(" %02x", *bytes);
- bytes++;
- len--;
- }
- pr_cont("\n");
-}
-#define DEBUG_bytes(bytes, len, msg, ...) __DEBUG_bytes(bytes, len, KERN_DEBUG msg, ##__VA_ARGS__)
+#define DEBUG_print(x, ...) printk(KERN_DEBUG x, ##__VA_ARGS__)
+#define DEBUG_bytes(bytes, len, msg, ...) printk(KERN_DEBUG msg "%s%*ph\n", ##__VA_ARGS__, \
+ len ? ": " : "", len, bytes)
#else
#define DEBUG_print(x, ...) do { } while (0)
#define DEBUG_bytes(bytes, len, msg, ...) do { } while (0)
@@ -2661,6 +2644,9 @@ static void recalc_write_super(struct dm_integrity_c *ic)
static void integrity_recalc(struct work_struct *w)
{
struct dm_integrity_c *ic = container_of(w, struct dm_integrity_c, recalc_work);
+ size_t recalc_tags_size;
+ u8 *recalc_buffer = NULL;
+ u8 *recalc_tags = NULL;
struct dm_integrity_range range;
struct dm_io_request io_req;
struct dm_io_region io_loc;
@@ -2672,6 +2658,26 @@ static void integrity_recalc(struct work_struct *w)
unsigned int i;
int r;
unsigned int super_counter = 0;
+ unsigned recalc_sectors = RECALC_SECTORS;
+
+retry:
+ recalc_buffer = __vmalloc(recalc_sectors << SECTOR_SHIFT, GFP_NOIO);
+ if (!recalc_buffer) {
+oom:
+ recalc_sectors >>= 1;
+ if (recalc_sectors >= 1U << ic->sb->log2_sectors_per_block)
+ goto retry;
+ DMCRIT("out of memory for recalculate buffer - recalculation disabled");
+ goto free_ret;
+ }
+ recalc_tags_size = (recalc_sectors >> ic->sb->log2_sectors_per_block) * ic->tag_size;
+ if (crypto_shash_digestsize(ic->internal_hash) > ic->tag_size)
+ recalc_tags_size += crypto_shash_digestsize(ic->internal_hash) - ic->tag_size;
+ recalc_tags = kvmalloc(recalc_tags_size, GFP_NOIO);
+ if (!recalc_tags) {
+ vfree(recalc_buffer);
+ goto oom;
+ }
DEBUG_print("start recalculation... (position %llx)\n", le64_to_cpu(ic->sb->recalc_sector));
@@ -2693,7 +2699,7 @@ next_chunk:
}
get_area_and_offset(ic, range.logical_sector, &area, &offset);
- range.n_sectors = min((sector_t)RECALC_SECTORS, ic->provided_data_sectors - range.logical_sector);
+ range.n_sectors = min((sector_t)recalc_sectors, ic->provided_data_sectors - range.logical_sector);
if (!ic->meta_dev)
range.n_sectors = min(range.n_sectors, ((sector_t)1U << ic->sb->log2_interleave_sectors) - (unsigned int)offset);
@@ -2735,7 +2741,7 @@ next_chunk:
io_req.bi_opf = REQ_OP_READ;
io_req.mem.type = DM_IO_VMA;
- io_req.mem.ptr.addr = ic->recalc_buffer;
+ io_req.mem.ptr.addr = recalc_buffer;
io_req.notify.fn = NULL;
io_req.client = ic->io;
io_loc.bdev = ic->dev->bdev;
@@ -2748,15 +2754,15 @@ next_chunk:
goto err;
}
- t = ic->recalc_tags;
+ t = recalc_tags;
for (i = 0; i < n_sectors; i += ic->sectors_per_block) {
- integrity_sector_checksum(ic, logical_sector + i, ic->recalc_buffer + (i << SECTOR_SHIFT), t);
+ integrity_sector_checksum(ic, logical_sector + i, recalc_buffer + (i << SECTOR_SHIFT), t);
t += ic->tag_size;
}
metadata_block = get_metadata_sector_and_offset(ic, area, offset, &metadata_offset);
- r = dm_integrity_rw_tag(ic, ic->recalc_tags, &metadata_block, &metadata_offset, t - ic->recalc_tags, TAG_WRITE);
+ r = dm_integrity_rw_tag(ic, recalc_tags, &metadata_block, &metadata_offset, t - recalc_tags, TAG_WRITE);
if (unlikely(r)) {
dm_integrity_io_error(ic, "writing tags", r);
goto err;
@@ -2784,12 +2790,16 @@ advance_and_next:
err:
remove_range(ic, &range);
- return;
+ goto free_ret;
unlock_ret:
spin_unlock_irq(&ic->endio_wait.lock);
recalc_write_super(ic);
+
+free_ret:
+ vfree(recalc_buffer);
+ kvfree(recalc_tags);
}
static void bitmap_block_work(struct work_struct *w)
@@ -4454,8 +4464,6 @@ try_smaller_buffer:
}
if (ic->internal_hash) {
- size_t recalc_tags_size;
-
ic->recalc_wq = alloc_workqueue("dm-integrity-recalc", WQ_MEM_RECLAIM, 1);
if (!ic->recalc_wq) {
ti->error = "Cannot allocate workqueue";
@@ -4463,21 +4471,6 @@ try_smaller_buffer:
goto bad;
}
INIT_WORK(&ic->recalc_work, integrity_recalc);
- ic->recalc_buffer = vmalloc(RECALC_SECTORS << SECTOR_SHIFT);
- if (!ic->recalc_buffer) {
- ti->error = "Cannot allocate buffer for recalculating";
- r = -ENOMEM;
- goto bad;
- }
- recalc_tags_size = (RECALC_SECTORS >> ic->sb->log2_sectors_per_block) * ic->tag_size;
- if (crypto_shash_digestsize(ic->internal_hash) > ic->tag_size)
- recalc_tags_size += crypto_shash_digestsize(ic->internal_hash) - ic->tag_size;
- ic->recalc_tags = kvmalloc(recalc_tags_size, GFP_KERNEL);
- if (!ic->recalc_tags) {
- ti->error = "Cannot allocate tags for recalculating";
- r = -ENOMEM;
- goto bad;
- }
} else {
if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
ti->error = "Recalculate can only be specified with internal_hash";
@@ -4621,8 +4614,6 @@ static void dm_integrity_dtr(struct dm_target *ti)
destroy_workqueue(ic->writer_wq);
if (ic->recalc_wq)
destroy_workqueue(ic->recalc_wq);
- vfree(ic->recalc_buffer);
- kvfree(ic->recalc_tags);
kvfree(ic->bbs);
if (ic->bufio)
dm_bufio_client_destroy(ic->bufio);
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 6d301019e5e3..f5ed729a8e0c 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -767,7 +767,14 @@ static int get_target_version(struct file *filp, struct dm_ioctl *param, size_t
static int check_name(const char *name)
{
if (strchr(name, '/')) {
- DMERR("invalid device name");
+ DMERR("device name cannot contain '/'");
+ return -EINVAL;
+ }
+
+ if (strcmp(name, DM_CONTROL_NODE) == 0 ||
+ strcmp(name, ".") == 0 ||
+ strcmp(name, "..") == 0) {
+ DMERR("device name cannot be \"%s\", \".\", or \"..\"", DM_CONTROL_NODE);
return -EINVAL;
}
@@ -1388,16 +1395,38 @@ static inline blk_mode_t get_mode(struct dm_ioctl *param)
return mode;
}
-static int next_target(struct dm_target_spec *last, uint32_t next, void *end,
+static int next_target(struct dm_target_spec *last, uint32_t next, const char *end,
struct dm_target_spec **spec, char **target_params)
{
- *spec = (struct dm_target_spec *) ((unsigned char *) last + next);
- *target_params = (char *) (*spec + 1);
+ static_assert(__alignof__(struct dm_target_spec) <= 8,
+ "struct dm_target_spec must not require more than 8-byte alignment");
+
+ /*
+ * Number of bytes remaining, starting with last. This is always
+ * sizeof(struct dm_target_spec) or more, as otherwise *last was
+ * out of bounds already.
+ */
+ size_t remaining = end - (char *)last;
+
+ /*
+ * There must be room for both the next target spec and the
+ * NUL-terminator of the target itself.
+ */
+ if (remaining - sizeof(struct dm_target_spec) <= next) {
+ DMERR("Target spec extends beyond end of parameters");
+ return -EINVAL;
+ }
- if (*spec < (last + 1))
+ if (next % __alignof__(struct dm_target_spec)) {
+ DMERR("Next dm_target_spec (offset %u) is not %zu-byte aligned",
+ next, __alignof__(struct dm_target_spec));
return -EINVAL;
+ }
+
+ *spec = (struct dm_target_spec *) ((unsigned char *) last + next);
+ *target_params = (char *) (*spec + 1);
- return invalid_str(*target_params, end);
+ return 0;
}
static int populate_table(struct dm_table *table,
@@ -1407,8 +1436,9 @@ static int populate_table(struct dm_table *table,
unsigned int i = 0;
struct dm_target_spec *spec = (struct dm_target_spec *) param;
uint32_t next = param->data_start;
- void *end = (void *) param + param_size;
+ const char *const end = (const char *) param + param_size;
char *target_params;
+ size_t min_size = sizeof(struct dm_ioctl);
if (!param->target_count) {
DMERR("%s: no targets specified", __func__);
@@ -1416,6 +1446,13 @@ static int populate_table(struct dm_table *table,
}
for (i = 0; i < param->target_count; i++) {
+ const char *nul_terminator;
+
+ if (next < min_size) {
+ DMERR("%s: next target spec (offset %u) overlaps %s",
+ __func__, next, i ? "previous target" : "'struct dm_ioctl'");
+ return -EINVAL;
+ }
r = next_target(spec, next, end, &spec, &target_params);
if (r) {
@@ -1423,6 +1460,15 @@ static int populate_table(struct dm_table *table,
return r;
}
+ nul_terminator = memchr(target_params, 0, (size_t)(end - target_params));
+ if (nul_terminator == NULL) {
+ DMERR("%s: target parameters not NUL-terminated", __func__);
+ return -EINVAL;
+ }
+
+ /* Add 1 for NUL terminator */
+ min_size = (size_t)(nul_terminator - (const char *)spec) + 1;
+
r = dm_table_add_target(table, spec->target_type,
(sector_t) spec->sector_start,
(sector_t) spec->length,
@@ -1830,30 +1876,36 @@ static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags)
* As well as checking the version compatibility this always
* copies the kernel interface version out.
*/
-static int check_version(unsigned int cmd, struct dm_ioctl __user *user)
+static int check_version(unsigned int cmd, struct dm_ioctl __user *user,
+ struct dm_ioctl *kernel_params)
{
- uint32_t version[3];
int r = 0;
- if (copy_from_user(version, user->version, sizeof(version)))
+ /* Make certain version is first member of dm_ioctl struct */
+ BUILD_BUG_ON(offsetof(struct dm_ioctl, version) != 0);
+
+ if (copy_from_user(kernel_params->version, user->version, sizeof(kernel_params->version)))
return -EFAULT;
- if ((version[0] != DM_VERSION_MAJOR) ||
- (version[1] > DM_VERSION_MINOR)) {
+ if ((kernel_params->version[0] != DM_VERSION_MAJOR) ||
+ (kernel_params->version[1] > DM_VERSION_MINOR)) {
DMERR("ioctl interface mismatch: kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)",
DM_VERSION_MAJOR, DM_VERSION_MINOR,
DM_VERSION_PATCHLEVEL,
- version[0], version[1], version[2], cmd);
+ kernel_params->version[0],
+ kernel_params->version[1],
+ kernel_params->version[2],
+ cmd);
r = -EINVAL;
}
/*
* Fill in the kernel version.
*/
- version[0] = DM_VERSION_MAJOR;
- version[1] = DM_VERSION_MINOR;
- version[2] = DM_VERSION_PATCHLEVEL;
- if (copy_to_user(user->version, version, sizeof(version)))
+ kernel_params->version[0] = DM_VERSION_MAJOR;
+ kernel_params->version[1] = DM_VERSION_MINOR;
+ kernel_params->version[2] = DM_VERSION_PATCHLEVEL;
+ if (copy_to_user(user->version, kernel_params->version, sizeof(kernel_params->version)))
return -EFAULT;
return r;
@@ -1877,9 +1929,11 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
struct dm_ioctl *dmi;
int secure_data;
const size_t minimum_data_size = offsetof(struct dm_ioctl, data);
- unsigned int noio_flag;
- if (copy_from_user(param_kernel, user, minimum_data_size))
+ /* check_version() already copied version from userspace, avoid TOCTOU */
+ if (copy_from_user((char *)param_kernel + sizeof(param_kernel->version),
+ (char __user *)user + sizeof(param_kernel->version),
+ minimum_data_size - sizeof(param_kernel->version)))
return -EFAULT;
if (param_kernel->data_size < minimum_data_size) {
@@ -1904,9 +1958,7 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
* Use kmalloc() rather than vmalloc() when we can.
*/
dmi = NULL;
- noio_flag = memalloc_noio_save();
- dmi = kvmalloc(param_kernel->data_size, GFP_KERNEL | __GFP_HIGH);
- memalloc_noio_restore(noio_flag);
+ dmi = kvmalloc(param_kernel->data_size, GFP_NOIO | __GFP_HIGH);
if (!dmi) {
if (secure_data && clear_user(user, param_kernel->data_size))
@@ -1991,7 +2043,7 @@ static int ctl_ioctl(struct file *file, uint command, struct dm_ioctl __user *us
* Check the interface version passed in. This also
* writes out the kernel's interface version.
*/
- r = check_version(cmd, user);
+ r = check_version(cmd, user, &param_kernel);
if (r)
return r;
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 9dd0409848ab..6022189c1388 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -603,6 +603,8 @@ static int __format_metadata(struct dm_pool_metadata *pmd)
r = dm_tm_create_with_sm(pmd->bm, THIN_SUPERBLOCK_LOCATION,
&pmd->tm, &pmd->metadata_sm);
if (r < 0) {
+ pmd->tm = NULL;
+ pmd->metadata_sm = NULL;
DMERR("tm_create_with_sm failed");
return r;
}
@@ -611,6 +613,7 @@ static int __format_metadata(struct dm_pool_metadata *pmd)
if (IS_ERR(pmd->data_sm)) {
DMERR("sm_disk_create failed");
r = PTR_ERR(pmd->data_sm);
+ pmd->data_sm = NULL;
goto bad_cleanup_tm;
}
@@ -641,11 +644,15 @@ static int __format_metadata(struct dm_pool_metadata *pmd)
bad_cleanup_nb_tm:
dm_tm_destroy(pmd->nb_tm);
+ pmd->nb_tm = NULL;
bad_cleanup_data_sm:
dm_sm_destroy(pmd->data_sm);
+ pmd->data_sm = NULL;
bad_cleanup_tm:
dm_tm_destroy(pmd->tm);
+ pmd->tm = NULL;
dm_sm_destroy(pmd->metadata_sm);
+ pmd->metadata_sm = NULL;
return r;
}
@@ -711,6 +718,8 @@ static int __open_metadata(struct dm_pool_metadata *pmd)
sizeof(disk_super->metadata_space_map_root),
&pmd->tm, &pmd->metadata_sm);
if (r < 0) {
+ pmd->tm = NULL;
+ pmd->metadata_sm = NULL;
DMERR("tm_open_with_sm failed");
goto bad_unlock_sblock;
}
@@ -720,6 +729,7 @@ static int __open_metadata(struct dm_pool_metadata *pmd)
if (IS_ERR(pmd->data_sm)) {
DMERR("sm_disk_open failed");
r = PTR_ERR(pmd->data_sm);
+ pmd->data_sm = NULL;
goto bad_cleanup_tm;
}
@@ -746,9 +756,12 @@ static int __open_metadata(struct dm_pool_metadata *pmd)
bad_cleanup_data_sm:
dm_sm_destroy(pmd->data_sm);
+ pmd->data_sm = NULL;
bad_cleanup_tm:
dm_tm_destroy(pmd->tm);
+ pmd->tm = NULL;
dm_sm_destroy(pmd->metadata_sm);
+ pmd->metadata_sm = NULL;
bad_unlock_sblock:
dm_bm_unlock(sblock);
@@ -795,9 +808,13 @@ static void __destroy_persistent_data_objects(struct dm_pool_metadata *pmd,
bool destroy_bm)
{
dm_sm_destroy(pmd->data_sm);
+ pmd->data_sm = NULL;
dm_sm_destroy(pmd->metadata_sm);
+ pmd->metadata_sm = NULL;
dm_tm_destroy(pmd->nb_tm);
+ pmd->nb_tm = NULL;
dm_tm_destroy(pmd->tm);
+ pmd->tm = NULL;
if (destroy_bm)
dm_block_manager_destroy(pmd->bm);
}
@@ -1005,8 +1022,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
__func__, r);
}
pmd_write_unlock(pmd);
- if (!pmd->fail_io)
- __destroy_persistent_data_objects(pmd, true);
+ __destroy_persistent_data_objects(pmd, true);
kfree(pmd);
return 0;
@@ -1881,53 +1897,29 @@ static void __set_abort_with_changes_flags(struct dm_pool_metadata *pmd)
int dm_pool_abort_metadata(struct dm_pool_metadata *pmd)
{
int r = -EINVAL;
- struct dm_block_manager *old_bm = NULL, *new_bm = NULL;
/* fail_io is double-checked with pmd->root_lock held below */
if (unlikely(pmd->fail_io))
return r;
- /*
- * Replacement block manager (new_bm) is created and old_bm destroyed outside of
- * pmd root_lock to avoid ABBA deadlock that would result (due to life-cycle of
- * shrinker associated with the block manager's bufio client vs pmd root_lock).
- * - must take shrinker_rwsem without holding pmd->root_lock
- */
- new_bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
- THIN_MAX_CONCURRENT_LOCKS);
-
pmd_write_lock(pmd);
if (pmd->fail_io) {
pmd_write_unlock(pmd);
- goto out;
+ return r;
}
-
__set_abort_with_changes_flags(pmd);
+
+ /* destroy data_sm/metadata_sm/nb_tm/tm */
__destroy_persistent_data_objects(pmd, false);
- old_bm = pmd->bm;
- if (IS_ERR(new_bm)) {
- DMERR("could not create block manager during abort");
- pmd->bm = NULL;
- r = PTR_ERR(new_bm);
- goto out_unlock;
- }
- pmd->bm = new_bm;
+ /* reset bm */
+ dm_block_manager_reset(pmd->bm);
+
+ /* rebuild data_sm/metadata_sm/nb_tm/tm */
r = __open_or_format_metadata(pmd, false);
- if (r) {
- pmd->bm = NULL;
- goto out_unlock;
- }
- new_bm = NULL;
-out_unlock:
if (r)
pmd->fail_io = true;
pmd_write_unlock(pmd);
- dm_block_manager_destroy(old_bm);
-out:
- if (new_bm && !IS_ERR(new_bm))
- dm_block_manager_destroy(new_bm);
-
return r;
}
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index f1d0dcb9db22..07c7f9795b10 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -2527,16 +2527,11 @@ static void noflush_work(struct thin_c *tc, void (*fn)(struct work_struct *))
/*----------------------------------------------------------------*/
-static bool passdown_enabled(struct pool_c *pt)
-{
- return pt->adjusted_pf.discard_passdown;
-}
-
static void set_discard_callbacks(struct pool *pool)
{
struct pool_c *pt = pool->ti->private;
- if (passdown_enabled(pt)) {
+ if (pt->adjusted_pf.discard_passdown) {
pool->process_discard_cell = process_discard_cell_passdown;
pool->process_prepared_discard = process_prepared_discard_passdown_pt1;
pool->process_prepared_discard_pt2 = process_prepared_discard_passdown_pt2;
@@ -2845,7 +2840,7 @@ static bool is_factor(sector_t block_size, uint32_t n)
* If discard_passdown was enabled verify that the data device
* supports discards. Disable discard_passdown if not.
*/
-static void disable_passdown_if_not_supported(struct pool_c *pt)
+static void disable_discard_passdown_if_not_supported(struct pool_c *pt)
{
struct pool *pool = pt->pool;
struct block_device *data_bdev = pt->data_dev->bdev;
@@ -3446,7 +3441,6 @@ out_unlock:
static int pool_map(struct dm_target *ti, struct bio *bio)
{
- int r;
struct pool_c *pt = ti->private;
struct pool *pool = pt->pool;
@@ -3455,10 +3449,9 @@ static int pool_map(struct dm_target *ti, struct bio *bio)
*/
spin_lock_irq(&pool->lock);
bio_set_dev(bio, pt->data_dev->bdev);
- r = DM_MAPIO_REMAPPED;
spin_unlock_irq(&pool->lock);
- return r;
+ return DM_MAPIO_REMAPPED;
}
static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit)
@@ -4099,21 +4092,22 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
* They get transferred to the live pool in bind_control_target()
* called from pool_preresume().
*/
- if (!pt->adjusted_pf.discard_enabled) {
+
+ if (pt->adjusted_pf.discard_enabled) {
+ disable_discard_passdown_if_not_supported(pt);
+ if (!pt->adjusted_pf.discard_passdown)
+ limits->max_discard_sectors = 0;
+ /*
+ * The pool uses the same discard limits as the underlying data
+ * device. DM core has already set this up.
+ */
+ } else {
/*
* Must explicitly disallow stacking discard limits otherwise the
* block layer will stack them if pool's data device has support.
*/
limits->discard_granularity = 0;
- return;
}
-
- disable_passdown_if_not_supported(pt);
-
- /*
- * The pool uses the same discard limits as the underlying data
- * device. DM core has already set this up.
- */
}
static struct target_type pool_target = {
@@ -4497,11 +4491,10 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
struct thin_c *tc = ti->private;
struct pool *pool = tc->pool;
- if (!pool->pf.discard_enabled)
- return;
-
- limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
- limits->max_discard_sectors = pool->sectors_per_block * BIO_PRISON_MAX_RANGE;
+ if (pool->pf.discard_enabled) {
+ limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
+ limits->max_discard_sectors = pool->sectors_per_block * BIO_PRISON_MAX_RANGE;
+ }
}
static struct target_type thin_target = {
diff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c
index 4b82b7798ce4..eb9832b22b14 100644
--- a/drivers/md/dm-zone.c
+++ b/drivers/md/dm-zone.c
@@ -7,6 +7,7 @@
#include <linux/mm.h>
#include <linux/sched/mm.h>
#include <linux/slab.h>
+#include <linux/bitmap.h>
#include "dm-core.h"
@@ -140,9 +141,9 @@ bool dm_is_zone_write(struct mapped_device *md, struct bio *bio)
void dm_cleanup_zoned_dev(struct mapped_device *md)
{
if (md->disk) {
- kfree(md->disk->conv_zones_bitmap);
+ bitmap_free(md->disk->conv_zones_bitmap);
md->disk->conv_zones_bitmap = NULL;
- kfree(md->disk->seq_zones_wlock);
+ bitmap_free(md->disk->seq_zones_wlock);
md->disk->seq_zones_wlock = NULL;
}
@@ -182,9 +183,8 @@ static int dm_zone_revalidate_cb(struct blk_zone *zone, unsigned int idx,
switch (zone->type) {
case BLK_ZONE_TYPE_CONVENTIONAL:
if (!disk->conv_zones_bitmap) {
- disk->conv_zones_bitmap =
- kcalloc(BITS_TO_LONGS(disk->nr_zones),
- sizeof(unsigned long), GFP_NOIO);
+ disk->conv_zones_bitmap = bitmap_zalloc(disk->nr_zones,
+ GFP_NOIO);
if (!disk->conv_zones_bitmap)
return -ENOMEM;
}
@@ -193,9 +193,8 @@ static int dm_zone_revalidate_cb(struct blk_zone *zone, unsigned int idx,
case BLK_ZONE_TYPE_SEQWRITE_REQ:
case BLK_ZONE_TYPE_SEQWRITE_PREF:
if (!disk->seq_zones_wlock) {
- disk->seq_zones_wlock =
- kcalloc(BITS_TO_LONGS(disk->nr_zones),
- sizeof(unsigned long), GFP_NOIO);
+ disk->seq_zones_wlock = bitmap_zalloc(disk->nr_zones,
+ GFP_NOIO);
if (!disk->seq_zones_wlock)
return -ENOMEM;
}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index fe2d4750d9c7..f0f118ab20fa 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -487,48 +487,50 @@ u64 dm_start_time_ns_from_clone(struct bio *bio)
}
EXPORT_SYMBOL_GPL(dm_start_time_ns_from_clone);
-static bool bio_is_flush_with_data(struct bio *bio)
+static inline bool bio_is_flush_with_data(struct bio *bio)
{
return ((bio->bi_opf & REQ_PREFLUSH) && bio->bi_iter.bi_size);
}
-static void dm_io_acct(struct dm_io *io, bool end)
+static inline unsigned int dm_io_sectors(struct dm_io *io, struct bio *bio)
{
- struct dm_stats_aux *stats_aux = &io->stats_aux;
- unsigned long start_time = io->start_time;
- struct mapped_device *md = io->md;
- struct bio *bio = io->orig_bio;
- unsigned int sectors;
-
/*
* If REQ_PREFLUSH set, don't account payload, it will be
* submitted (and accounted) after this flush completes.
*/
if (bio_is_flush_with_data(bio))
- sectors = 0;
- else if (likely(!(dm_io_flagged(io, DM_IO_WAS_SPLIT))))
- sectors = bio_sectors(bio);
- else
- sectors = io->sectors;
+ return 0;
+ if (unlikely(dm_io_flagged(io, DM_IO_WAS_SPLIT)))
+ return io->sectors;
+ return bio_sectors(bio);
+}
- if (!end)
- bdev_start_io_acct(bio->bi_bdev, bio_op(bio), start_time);
- else
- bdev_end_io_acct(bio->bi_bdev, bio_op(bio), sectors,
- start_time);
+static void dm_io_acct(struct dm_io *io, bool end)
+{
+ struct bio *bio = io->orig_bio;
+
+ if (dm_io_flagged(io, DM_IO_BLK_STAT)) {
+ if (!end)
+ bdev_start_io_acct(bio->bi_bdev, bio_op(bio),
+ io->start_time);
+ else
+ bdev_end_io_acct(bio->bi_bdev, bio_op(bio),
+ dm_io_sectors(io, bio),
+ io->start_time);
+ }
if (static_branch_unlikely(&stats_enabled) &&
- unlikely(dm_stats_used(&md->stats))) {
+ unlikely(dm_stats_used(&io->md->stats))) {
sector_t sector;
- if (likely(!dm_io_flagged(io, DM_IO_WAS_SPLIT)))
- sector = bio->bi_iter.bi_sector;
- else
+ if (unlikely(dm_io_flagged(io, DM_IO_WAS_SPLIT)))
sector = bio_end_sector(bio) - io->sector_offset;
+ else
+ sector = bio->bi_iter.bi_sector;
- dm_stats_account_io(&md->stats, bio_data_dir(bio),
- sector, sectors,
- end, start_time, stats_aux);
+ dm_stats_account_io(&io->md->stats, bio_data_dir(bio),
+ sector, dm_io_sectors(io, bio),
+ end, io->start_time, &io->stats_aux);
}
}
@@ -592,8 +594,11 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio)
spin_lock_init(&io->lock);
io->start_time = jiffies;
io->flags = 0;
+ if (blk_queue_io_stat(md->queue))
+ dm_io_set_flag(io, DM_IO_BLK_STAT);
- if (static_branch_unlikely(&stats_enabled))
+ if (static_branch_unlikely(&stats_enabled) &&
+ unlikely(dm_stats_used(&md->stats)))
dm_stats_record_start(&md->stats, &io->stats_aux);
return io;
@@ -2348,6 +2353,7 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t)
break;
case DM_TYPE_BIO_BASED:
case DM_TYPE_DAX_BIO_BASED:
+ blk_queue_flag_set(QUEUE_FLAG_IO_STAT, md->queue);
break;
case DM_TYPE_NONE:
WARN_ON_ONCE(true);
@@ -3143,6 +3149,8 @@ struct dm_pr {
bool fail_early;
int ret;
enum pr_type type;
+ struct pr_keys *read_keys;
+ struct pr_held_reservation *rsv;
};
static int dm_call_pr(struct block_device *bdev, iterate_devices_callout_fn fn,
@@ -3375,12 +3383,79 @@ out:
return r;
}
+static int __dm_pr_read_keys(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+{
+ struct dm_pr *pr = data;
+ const struct pr_ops *ops = dev->bdev->bd_disk->fops->pr_ops;
+
+ if (!ops || !ops->pr_read_keys) {
+ pr->ret = -EOPNOTSUPP;
+ return -1;
+ }
+
+ pr->ret = ops->pr_read_keys(dev->bdev, pr->read_keys);
+ if (!pr->ret)
+ return -1;
+
+ return 0;
+}
+
+static int dm_pr_read_keys(struct block_device *bdev, struct pr_keys *keys)
+{
+ struct dm_pr pr = {
+ .read_keys = keys,
+ };
+ int ret;
+
+ ret = dm_call_pr(bdev, __dm_pr_read_keys, &pr);
+ if (ret)
+ return ret;
+
+ return pr.ret;
+}
+
+static int __dm_pr_read_reservation(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+{
+ struct dm_pr *pr = data;
+ const struct pr_ops *ops = dev->bdev->bd_disk->fops->pr_ops;
+
+ if (!ops || !ops->pr_read_reservation) {
+ pr->ret = -EOPNOTSUPP;
+ return -1;
+ }
+
+ pr->ret = ops->pr_read_reservation(dev->bdev, pr->rsv);
+ if (!pr->ret)
+ return -1;
+
+ return 0;
+}
+
+static int dm_pr_read_reservation(struct block_device *bdev,
+ struct pr_held_reservation *rsv)
+{
+ struct dm_pr pr = {
+ .rsv = rsv,
+ };
+ int ret;
+
+ ret = dm_call_pr(bdev, __dm_pr_read_reservation, &pr);
+ if (ret)
+ return ret;
+
+ return pr.ret;
+}
+
static const struct pr_ops dm_pr_ops = {
.pr_register = dm_pr_register,
.pr_reserve = dm_pr_reserve,
.pr_release = dm_pr_release,
.pr_preempt = dm_pr_preempt,
.pr_clear = dm_pr_clear,
+ .pr_read_keys = dm_pr_read_keys,
+ .pr_read_reservation = dm_pr_read_reservation,
};
static const struct block_device_operations dm_blk_dops = {
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 63d9010d8e61..f682295af91f 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -210,9 +210,6 @@ void dm_put_table_device(struct mapped_device *md, struct dm_dev *d);
int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
unsigned int cookie, bool need_resize_uevent);
-void dm_internal_suspend(struct mapped_device *md);
-void dm_internal_resume(struct mapped_device *md);
-
int dm_io_init(void);
void dm_io_exit(void);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index cf3733c90c47..2e38ef421d69 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -643,7 +643,6 @@ void mddev_init(struct mddev *mddev)
{
mutex_init(&mddev->open_mutex);
mutex_init(&mddev->reconfig_mutex);
- mutex_init(&mddev->delete_mutex);
mutex_init(&mddev->bitmap_info.mutex);
INIT_LIST_HEAD(&mddev->disks);
INIT_LIST_HEAD(&mddev->all_mddevs);
@@ -749,26 +748,15 @@ static void mddev_free(struct mddev *mddev)
static const struct attribute_group md_redundancy_group;
-static void md_free_rdev(struct mddev *mddev)
+void mddev_unlock(struct mddev *mddev)
{
struct md_rdev *rdev;
struct md_rdev *tmp;
+ LIST_HEAD(delete);
- mutex_lock(&mddev->delete_mutex);
- if (list_empty(&mddev->deleting))
- goto out;
-
- list_for_each_entry_safe(rdev, tmp, &mddev->deleting, same_set) {
- list_del_init(&rdev->same_set);
- kobject_del(&rdev->kobj);
- export_rdev(rdev, mddev);
- }
-out:
- mutex_unlock(&mddev->delete_mutex);
-}
+ if (!list_empty(&mddev->deleting))
+ list_splice_init(&mddev->deleting, &delete);
-void mddev_unlock(struct mddev *mddev)
-{
if (mddev->to_remove) {
/* These cannot be removed under reconfig_mutex as
* an access to the files will try to take reconfig_mutex
@@ -808,7 +796,11 @@ void mddev_unlock(struct mddev *mddev)
} else
mutex_unlock(&mddev->reconfig_mutex);
- md_free_rdev(mddev);
+ 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);
@@ -2458,7 +2450,7 @@ 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->major_version == -2 ? &claim_rdev : rdev);
+ blkdev_put(rdev->bdev, mddev->external ? &claim_rdev : rdev);
rdev->bdev = NULL;
kobject_put(&rdev->kobj);
}
@@ -2488,9 +2480,7 @@ static void md_kick_rdev_from_array(struct md_rdev *rdev)
* reconfig_mutex is held, hence it can't be called under
* reconfig_mutex and it's delayed to mddev_unlock().
*/
- mutex_lock(&mddev->delete_mutex);
list_add(&rdev->same_set, &mddev->deleting);
- mutex_unlock(&mddev->delete_mutex);
}
static void export_array(struct mddev *mddev)
@@ -6140,7 +6130,7 @@ static void md_clean(struct mddev *mddev)
mddev->resync_min = 0;
mddev->resync_max = MaxSector;
mddev->reshape_position = MaxSector;
- mddev->external = 0;
+ /* we still need mddev->external in export_rdev, do not clear it yet */
mddev->persistent = 0;
mddev->level = LEVEL_NONE;
mddev->clevel[0] = 0;
diff --git a/drivers/md/md.h b/drivers/md/md.h
index bfd2306bc750..1aef86bf3fc3 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -531,11 +531,9 @@ struct mddev {
/*
* Temporarily store rdev that will be finally removed when
- * reconfig_mutex is unlocked.
+ * reconfig_mutex is unlocked, protected by reconfig_mutex.
*/
struct list_head deleting;
- /* Protect the deleting list */
- struct mutex delete_mutex;
bool has_superblocks:1;
bool fail_last_dev:1;
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c
index 7bdfc23f758a..0e010e1204aa 100644
--- a/drivers/md/persistent-data/dm-block-manager.c
+++ b/drivers/md/persistent-data/dm-block-manager.c
@@ -421,6 +421,12 @@ void dm_block_manager_destroy(struct dm_block_manager *bm)
}
EXPORT_SYMBOL_GPL(dm_block_manager_destroy);
+void dm_block_manager_reset(struct dm_block_manager *bm)
+{
+ dm_bufio_client_reset(bm->bufio);
+}
+EXPORT_SYMBOL_GPL(dm_block_manager_reset);
+
unsigned int dm_bm_block_size(struct dm_block_manager *bm)
{
return dm_bufio_get_block_size(bm->bufio);
diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h
index 5746b0f82a03..f706d3de8d5a 100644
--- a/drivers/md/persistent-data/dm-block-manager.h
+++ b/drivers/md/persistent-data/dm-block-manager.h
@@ -36,6 +36,7 @@ struct dm_block_manager *dm_block_manager_create(
struct block_device *bdev, unsigned int block_size,
unsigned int max_held_per_thread);
void dm_block_manager_destroy(struct dm_block_manager *bm);
+void dm_block_manager_reset(struct dm_block_manager *bm);
unsigned int dm_bm_block_size(struct dm_block_manager *bm);
dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm);
diff --git a/drivers/md/persistent-data/dm-space-map.h b/drivers/md/persistent-data/dm-space-map.h
index dab490353781..6bf69922b5ad 100644
--- a/drivers/md/persistent-data/dm-space-map.h
+++ b/drivers/md/persistent-data/dm-space-map.h
@@ -77,7 +77,8 @@ struct dm_space_map {
static inline void dm_sm_destroy(struct dm_space_map *sm)
{
- sm->destroy(sm);
+ if (sm)
+ sm->destroy(sm);
}
static inline int dm_sm_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c
index 6dc016248baf..c88fa6266203 100644
--- a/drivers/md/persistent-data/dm-transaction-manager.c
+++ b/drivers/md/persistent-data/dm-transaction-manager.c
@@ -199,6 +199,9 @@ EXPORT_SYMBOL_GPL(dm_tm_create_non_blocking_clone);
void dm_tm_destroy(struct dm_transaction_manager *tm)
{
+ if (!tm)
+ return;
+
if (!tm->is_clone)
wipe_shadow_table(tm);
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index f8ee9a95e25d..d1ac73fcd852 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -270,6 +270,18 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
goto abort;
}
+ if (conf->layout == RAID0_ORIG_LAYOUT) {
+ for (i = 1; i < conf->nr_strip_zones; i++) {
+ sector_t first_sector = conf->strip_zone[i-1].zone_end;
+
+ sector_div(first_sector, mddev->chunk_sectors);
+ zone = conf->strip_zone + i;
+ /* disk_shift is first disk index used in the zone */
+ zone->disk_shift = sector_div(first_sector,
+ zone->nb_dev);
+ }
+ }
+
pr_debug("md/raid0:%s: done.\n", mdname(mddev));
*private_conf = conf;
@@ -431,6 +443,20 @@ exit_acct_set:
return ret;
}
+/*
+ * Convert disk_index to the disk order in which it is read/written.
+ * For example, if we have 4 disks, they are numbered 0,1,2,3. If we
+ * write the disks starting at disk 3, then the read/write order would
+ * be disk 3, then 0, then 1, and then disk 2 and we want map_disk_shift()
+ * to map the disks as follows 0,1,2,3 => 1,2,3,0. So disk 0 would map
+ * to 1, 1 to 2, 2 to 3, and 3 to 0. That way we can compare disks in
+ * that 'output' space to understand the read/write disk ordering.
+ */
+static int map_disk_shift(int disk_index, int num_disks, int disk_shift)
+{
+ return ((disk_index + num_disks - disk_shift) % num_disks);
+}
+
static void raid0_handle_discard(struct mddev *mddev, struct bio *bio)
{
struct r0conf *conf = mddev->private;
@@ -444,7 +470,9 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio)
sector_t end_disk_offset;
unsigned int end_disk_index;
unsigned int disk;
+ sector_t orig_start, orig_end;
+ orig_start = start;
zone = find_zone(conf, &start);
if (bio_end_sector(bio) > zone->zone_end) {
@@ -458,6 +486,7 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio)
} else
end = bio_end_sector(bio);
+ orig_end = end;
if (zone != conf->strip_zone)
end = end - zone[-1].zone_end;
@@ -469,13 +498,26 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio)
last_stripe_index = end;
sector_div(last_stripe_index, stripe_size);
- start_disk_index = (int)(start - first_stripe_index * stripe_size) /
- mddev->chunk_sectors;
+ /* In the first zone the original and alternate layouts are the same */
+ if ((conf->layout == RAID0_ORIG_LAYOUT) && (zone != conf->strip_zone)) {
+ sector_div(orig_start, mddev->chunk_sectors);
+ start_disk_index = sector_div(orig_start, zone->nb_dev);
+ start_disk_index = map_disk_shift(start_disk_index,
+ zone->nb_dev,
+ zone->disk_shift);
+ sector_div(orig_end, mddev->chunk_sectors);
+ end_disk_index = sector_div(orig_end, zone->nb_dev);
+ end_disk_index = map_disk_shift(end_disk_index,
+ zone->nb_dev, zone->disk_shift);
+ } else {
+ start_disk_index = (int)(start - first_stripe_index * stripe_size) /
+ mddev->chunk_sectors;
+ end_disk_index = (int)(end - last_stripe_index * stripe_size) /
+ mddev->chunk_sectors;
+ }
start_disk_offset = ((int)(start - first_stripe_index * stripe_size) %
mddev->chunk_sectors) +
first_stripe_index * mddev->chunk_sectors;
- end_disk_index = (int)(end - last_stripe_index * stripe_size) /
- mddev->chunk_sectors;
end_disk_offset = ((int)(end - last_stripe_index * stripe_size) %
mddev->chunk_sectors) +
last_stripe_index * mddev->chunk_sectors;
@@ -483,18 +525,22 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio)
for (disk = 0; disk < zone->nb_dev; disk++) {
sector_t dev_start, dev_end;
struct md_rdev *rdev;
+ int compare_disk;
+
+ compare_disk = map_disk_shift(disk, zone->nb_dev,
+ zone->disk_shift);
- if (disk < start_disk_index)
+ if (compare_disk < start_disk_index)
dev_start = (first_stripe_index + 1) *
mddev->chunk_sectors;
- else if (disk > start_disk_index)
+ else if (compare_disk > start_disk_index)
dev_start = first_stripe_index * mddev->chunk_sectors;
else
dev_start = start_disk_offset;
- if (disk < end_disk_index)
+ if (compare_disk < end_disk_index)
dev_end = (last_stripe_index + 1) * mddev->chunk_sectors;
- else if (disk > end_disk_index)
+ else if (compare_disk > end_disk_index)
dev_end = last_stripe_index * mddev->chunk_sectors;
else
dev_end = end_disk_offset;
diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h
index 3816e5477db1..8cc761ca7423 100644
--- a/drivers/md/raid0.h
+++ b/drivers/md/raid0.h
@@ -6,6 +6,7 @@ struct strip_zone {
sector_t zone_end; /* Start of the next zone (in sectors) */
sector_t dev_start; /* Zone offset in real dev (in sectors) */
int nb_dev; /* # of devices attached to the zone */
+ int disk_shift; /* start disk for the original layout */
};
/* Linux 3.14 (20d0189b101) made an unintended change to
diff --git a/drivers/md/raid1-10.c b/drivers/md/raid1-10.c
index 169ebe296f2d..3f22edec70e7 100644
--- a/drivers/md/raid1-10.c
+++ b/drivers/md/raid1-10.c
@@ -116,7 +116,7 @@ static void md_bio_reset_resync_pages(struct bio *bio, struct resync_pages *rp,
static inline void raid1_submit_write(struct bio *bio)
{
- struct md_rdev *rdev = (struct md_rdev *)bio->bi_bdev;
+ struct md_rdev *rdev = (void *)bio->bi_bdev;
bio->bi_next = NULL;
bio_set_dev(bio, rdev->bdev);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index d0de8c9fb3cf..5051149e27bb 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -325,7 +325,7 @@ static void raid_end_bio_io(struct r10bio *r10_bio)
if (!test_bit(R10BIO_Uptodate, &r10_bio->state))
bio->bi_status = BLK_STS_IOERR;
- if (blk_queue_io_stat(bio->bi_bdev->bd_disk->queue))
+ if (r10_bio->start_time)
bio_end_io_acct(bio, r10_bio->start_time);
bio_endio(bio);
/*
@@ -1118,7 +1118,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
spin_lock_irq(&conf->device_lock);
bio_list_merge(&conf->pending_bio_list, &plug->pending);
spin_unlock_irq(&conf->device_lock);
- wake_up(&conf->wait_barrier);
+ wake_up_barrier(conf);
md_wakeup_thread(mddev->thread);
kfree(plug);
return;
@@ -1127,7 +1127,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
/* we aren't scheduling, so we can do the write-out directly. */
bio = bio_list_get(&plug->pending);
raid1_prepare_flush_writes(mddev->bitmap);
- wake_up(&conf->wait_barrier);
+ wake_up_barrier(conf);
while (bio) { /* submit pending writes */
struct bio *next = bio->bi_next;
diff --git a/drivers/media/cec/i2c/Kconfig b/drivers/media/cec/i2c/Kconfig
index 70432a1d6918..d912d143fb31 100644
--- a/drivers/media/cec/i2c/Kconfig
+++ b/drivers/media/cec/i2c/Kconfig
@@ -5,6 +5,7 @@
config CEC_CH7322
tristate "Chrontel CH7322 CEC controller"
depends on I2C
+ select REGMAP
select REGMAP_I2C
select CEC_CORE
help
diff --git a/drivers/media/cec/i2c/ch7322.c b/drivers/media/cec/i2c/ch7322.c
index 34fad7123704..439c15bc9e44 100644
--- a/drivers/media/cec/i2c/ch7322.c
+++ b/drivers/media/cec/i2c/ch7322.c
@@ -591,7 +591,7 @@ static struct i2c_driver ch7322_i2c_driver = {
.name = "ch7322",
.of_match_table = of_match_ptr(ch7322_of_match),
},
- .probe_new = ch7322_probe,
+ .probe = ch7322_probe,
.remove = ch7322_remove,
};
diff --git a/drivers/media/common/saa7146/saa7146_core.c b/drivers/media/common/saa7146/saa7146_core.c
index bcb957883044..27c53eed8fe3 100644
--- a/drivers/media/common/saa7146/saa7146_core.c
+++ b/drivers/media/common/saa7146/saa7146_core.c
@@ -133,8 +133,8 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
****************************************************************************/
/* this is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c
- make sure virt has been allocated with vmalloc_32(), otherwise the BUG()
- may be triggered on highmem machines */
+ make sure virt has been allocated with vmalloc_32(), otherwise return NULL
+ on highmem machines */
static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
{
struct scatterlist *sglist;
@@ -150,7 +150,7 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
if (NULL == pg)
goto err;
if (WARN_ON(PageHighMem(pg)))
- return NULL;
+ goto err;
sg_set_page(&sglist[i], pg, PAGE_SIZE, 0);
}
return sglist;
diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
index a4b05e366ccc..305bb21d843c 100644
--- a/drivers/media/dvb-core/dvbdev.c
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -61,21 +61,21 @@ static const char * const dnames[] = {
#define DVB_MAX_IDS 4
static const u8 minor_type[] = {
- [DVB_DEVICE_VIDEO] = 0,
- [DVB_DEVICE_AUDIO] = 1,
- [DVB_DEVICE_SEC] = 2,
- [DVB_DEVICE_FRONTEND] = 3,
- [DVB_DEVICE_DEMUX] = 4,
- [DVB_DEVICE_DVR] = 5,
- [DVB_DEVICE_CA] = 6,
- [DVB_DEVICE_NET] = 7,
- [DVB_DEVICE_OSD] = 8,
+ [DVB_DEVICE_VIDEO] = 0,
+ [DVB_DEVICE_AUDIO] = 1,
+ [DVB_DEVICE_SEC] = 2,
+ [DVB_DEVICE_FRONTEND] = 3,
+ [DVB_DEVICE_DEMUX] = 4,
+ [DVB_DEVICE_DVR] = 5,
+ [DVB_DEVICE_CA] = 6,
+ [DVB_DEVICE_NET] = 7,
+ [DVB_DEVICE_OSD] = 8,
};
#define nums2minor(num, type, id) \
- (((num) << 6) | ((id) << 4) | minor_type[type])
+ (((num) << 6) | ((id) << 4) | minor_type[type])
-#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
+#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS * 64)
#endif
static struct class *dvb_class;
@@ -112,9 +112,7 @@ fail:
return -ENODEV;
}
-
-static const struct file_operations dvb_device_fops =
-{
+static const struct file_operations dvb_device_fops = {
.owner = THIS_MODULE,
.open = dvb_device_open,
.llseek = noop_llseek,
@@ -147,7 +145,6 @@ int dvb_generic_open(struct inode *inode, struct file *file)
}
EXPORT_SYMBOL(dvb_generic_open);
-
int dvb_generic_release(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
@@ -155,11 +152,10 @@ int dvb_generic_release(struct inode *inode, struct file *file)
if (!dvbdev)
return -ENODEV;
- if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+ if ((file->f_flags & O_ACCMODE) == O_RDONLY)
dvbdev->readers++;
- } else {
+ else
dvbdev->writers++;
- }
dvbdev->users++;
@@ -169,7 +165,6 @@ int dvb_generic_release(struct inode *inode, struct file *file)
}
EXPORT_SYMBOL(dvb_generic_release);
-
long dvb_generic_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -185,13 +180,13 @@ long dvb_generic_ioctl(struct file *file,
}
EXPORT_SYMBOL(dvb_generic_ioctl);
-
-static int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
+static int dvbdev_get_free_id(struct dvb_adapter *adap, int type)
{
u32 id = 0;
while (id < DVB_MAX_IDS) {
struct dvb_device *dev;
+
list_for_each_entry(dev, &adap->device_list, list_head)
if (dev->type == type && dev->id == id)
goto skip;
@@ -245,7 +240,7 @@ static void dvb_media_device_free(struct dvb_device *dvbdev)
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
static int dvb_create_tsout_entity(struct dvb_device *dvbdev,
- const char *name, int npads)
+ const char *name, int npads)
{
int i;
@@ -387,7 +382,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
static int dvb_register_media_device(struct dvb_device *dvbdev,
int type, int minor,
- unsigned demux_sink_pads)
+ unsigned int demux_sink_pads)
{
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
struct media_link *link;
@@ -462,7 +457,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
mutex_lock(&dvbdev_register_lock);
- if ((id = dvbdev_get_free_id (adap, type)) < 0) {
+ id = dvbdev_get_free_id(adap, type);
+ if (id < 0) {
mutex_unlock(&dvbdev_register_lock);
*pdvbdev = NULL;
pr_err("%s: couldn't find free device id\n", __func__);
@@ -470,7 +466,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
}
*pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL);
- if (!dvbdev){
+ if (!dvbdev) {
mutex_unlock(&dvbdev_register_lock);
return -ENOMEM;
}
@@ -482,14 +478,13 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
*/
list_for_each_entry(node, &dvbdevfops_list, list_head) {
if (node->fops->owner == adap->module &&
- node->type == type &&
- node->template == template) {
+ node->type == type && node->template == template) {
dvbdevfops = node->fops;
break;
}
}
- if (dvbdevfops == NULL) {
+ if (!dvbdevfops) {
dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
if (!dvbdevfops) {
kfree(dvbdev);
@@ -497,7 +492,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
return -ENOMEM;
}
- new_node = kzalloc(sizeof(struct dvbdevfops_node), GFP_KERNEL);
+ new_node = kzalloc(sizeof(*new_node), GFP_KERNEL);
if (!new_node) {
kfree(dvbdevfops);
kfree(dvbdev);
@@ -508,7 +503,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
new_node->fops = dvbdevfops;
new_node->type = type;
new_node->template = template;
- list_add_tail (&new_node->list_head, &dvbdevfops_list);
+ list_add_tail(&new_node->list_head, &dvbdevfops_list);
}
memcpy(dvbdev, template, sizeof(struct dvb_device));
@@ -518,21 +513,21 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
dvbdev->adapter = adap;
dvbdev->priv = priv;
dvbdev->fops = dvbdevfops;
- init_waitqueue_head (&dvbdev->wait_queue);
+ init_waitqueue_head(&dvbdev->wait_queue);
dvbdevfops->owner = adap->module;
- list_add_tail (&dvbdev->list_head, &adap->device_list);
+ list_add_tail(&dvbdev->list_head, &adap->device_list);
down_write(&minor_rwsem);
#ifdef CONFIG_DVB_DYNAMIC_MINORS
for (minor = 0; minor < MAX_DVB_MINORS; minor++)
- if (dvb_minors[minor] == NULL)
+ if (!dvb_minors[minor])
break;
if (minor == MAX_DVB_MINORS) {
if (new_node) {
- list_del (&new_node->list_head);
+ list_del(&new_node->list_head);
kfree(dvbdevfops);
kfree(new_node);
}
- list_del (&dvbdev->list_head);
+ list_del(&dvbdev->list_head);
kfree(dvbdev);
up_write(&minor_rwsem);
mutex_unlock(&dvbdev_register_lock);
@@ -547,14 +542,14 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
if (ret) {
pr_err("%s: dvb_register_media_device failed to create the mediagraph\n",
- __func__);
+ __func__);
if (new_node) {
- list_del (&new_node->list_head);
+ list_del(&new_node->list_head);
kfree(dvbdevfops);
kfree(new_node);
}
dvb_media_device_free(dvbdev);
- list_del (&dvbdev->list_head);
+ list_del(&dvbdev->list_head);
kfree(dvbdev);
mutex_unlock(&dvbdev_register_lock);
return ret;
@@ -567,12 +562,12 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
if (new_node) {
- list_del (&new_node->list_head);
+ list_del(&new_node->list_head);
kfree(dvbdevfops);
kfree(new_node);
}
dvb_media_device_free(dvbdev);
- list_del (&dvbdev->list_head);
+ list_del(&dvbdev->list_head);
kfree(dvbdev);
mutex_unlock(&dvbdev_register_lock);
return PTR_ERR(clsdev);
@@ -586,7 +581,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
}
EXPORT_SYMBOL(dvb_register_device);
-
void dvb_remove_device(struct dvb_device *dvbdev)
{
if (!dvbdev)
@@ -601,19 +595,17 @@ void dvb_remove_device(struct dvb_device *dvbdev)
device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
- list_del (&dvbdev->list_head);
+ list_del(&dvbdev->list_head);
}
EXPORT_SYMBOL(dvb_remove_device);
-
static void dvb_free_device(struct kref *ref)
{
struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
- kfree (dvbdev);
+ kfree(dvbdev);
}
-
struct dvb_device *dvb_device_get(struct dvb_device *dvbdev)
{
kref_get(&dvbdev->ref);
@@ -621,14 +613,12 @@ struct dvb_device *dvb_device_get(struct dvb_device *dvbdev)
}
EXPORT_SYMBOL(dvb_device_get);
-
void dvb_device_put(struct dvb_device *dvbdev)
{
if (dvbdev)
kref_put(&dvbdev->ref, dvb_free_device);
}
-
void dvb_unregister_device(struct dvb_device *dvbdev)
{
dvb_remove_device(dvbdev);
@@ -636,7 +626,6 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
}
EXPORT_SYMBOL(dvb_unregister_device);
-
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
static int dvb_create_io_intf_links(struct dvb_adapter *adap,
@@ -669,9 +658,9 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
struct media_entity *demux = NULL, *ca = NULL;
struct media_link *link;
struct media_interface *intf;
- unsigned demux_pad = 0;
- unsigned dvr_pad = 0;
- unsigned ntuner = 0, ndemod = 0;
+ unsigned int demux_pad = 0;
+ unsigned int dvr_pad = 0;
+ unsigned int ntuner = 0, ndemod = 0;
int ret, pad_source, pad_sink;
static const char *connector_name = "Television";
@@ -741,7 +730,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
MEDIA_LNK_FL_ENABLED,
false);
} else {
- pad_sink = media_get_pad_index(tuner, true,
+ pad_sink = media_get_pad_index(tuner, MEDIA_PAD_FL_SINK,
PAD_SIGNAL_ANALOG);
if (pad_sink < 0)
return -EINVAL;
@@ -759,7 +748,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
if (ntuner && ndemod) {
/* NOTE: first found tuner source pad presumed correct */
- pad_source = media_get_pad_index(tuner, false,
+ pad_source = media_get_pad_index(tuner, MEDIA_PAD_FL_SOURCE,
PAD_SIGNAL_ANALOG);
if (pad_source < 0)
return -EINVAL;
@@ -795,18 +784,18 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
media_device_for_each_entity(entity, mdev) {
if (entity->function == MEDIA_ENT_F_IO_DTV) {
if (!strncmp(entity->name, DVR_TSOUT,
- strlen(DVR_TSOUT))) {
+ strlen(DVR_TSOUT))) {
ret = media_create_pad_link(demux,
- ++dvr_pad,
- entity, 0, 0);
+ ++dvr_pad,
+ entity, 0, 0);
if (ret)
return ret;
}
if (!strncmp(entity->name, DEMUX_TSOUT,
- strlen(DEMUX_TSOUT))) {
+ strlen(DEMUX_TSOUT))) {
ret = media_create_pad_link(demux,
- ++demux_pad,
- entity, 0, 0);
+ ++demux_pad,
+ entity, 0, 0);
if (ret)
return ret;
}
@@ -864,8 +853,10 @@ EXPORT_SYMBOL_GPL(dvb_create_media_graph);
static int dvbdev_check_free_adapter_num(int num)
{
struct list_head *entry;
+
list_for_each(entry, &dvb_adapter_list) {
struct dvb_adapter *adap;
+
adap = list_entry(entry, struct dvb_adapter, list_head);
if (adap->num == num)
return 0;
@@ -873,7 +864,7 @@ static int dvbdev_check_free_adapter_num(int num)
return 1;
}
-static int dvbdev_get_free_adapter_num (void)
+static int dvbdev_get_free_adapter_num(void)
{
int num = 0;
@@ -886,7 +877,6 @@ static int dvbdev_get_free_adapter_num (void)
return -ENFILE;
}
-
int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
struct module *module, struct device *device,
short *adapter_nums)
@@ -913,8 +903,8 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
return -ENFILE;
}
- memset (adap, 0, sizeof(struct dvb_adapter));
- INIT_LIST_HEAD (&adap->device_list);
+ memset(adap, 0, sizeof(struct dvb_adapter));
+ INIT_LIST_HEAD(&adap->device_list);
pr_info("DVB: registering new adapter (%s)\n", name);
@@ -924,13 +914,13 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
adap->device = device;
adap->mfe_shared = 0;
adap->mfe_dvbdev = NULL;
- mutex_init (&adap->mfe_lock);
+ mutex_init(&adap->mfe_lock);
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
mutex_init(&adap->mdev_lock);
#endif
- list_add_tail (&adap->list_head, &dvb_adapter_list);
+ list_add_tail(&adap->list_head, &dvb_adapter_list);
mutex_unlock(&dvbdev_register_lock);
@@ -938,25 +928,26 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
}
EXPORT_SYMBOL(dvb_register_adapter);
-
int dvb_unregister_adapter(struct dvb_adapter *adap)
{
mutex_lock(&dvbdev_register_lock);
- list_del (&adap->list_head);
+ list_del(&adap->list_head);
mutex_unlock(&dvbdev_register_lock);
return 0;
}
EXPORT_SYMBOL(dvb_unregister_adapter);
-/* if the miracle happens and "generic_usercopy()" is included into
- the kernel, then this can vanish. please don't make the mistake and
- define this as video_usercopy(). this will introduce a dependency
- to the v4l "videodev.o" module, which is unnecessary for some
- cards (ie. the budget dvb-cards don't need the v4l module...) */
+/*
+ * if the miracle happens and "generic_usercopy()" is included into
+ * the kernel, then this can vanish. please don't make the mistake and
+ * define this as video_usercopy(). this will introduce a dependency
+ * to the v4l "videodev.o" module, which is unnecessary for some
+ * cards (ie. the budget dvb-cards don't need the v4l module...)
+ */
int dvb_usercopy(struct file *file,
- unsigned int cmd, unsigned long arg,
- int (*func)(struct file *file,
- unsigned int cmd, void *arg))
+ unsigned int cmd, unsigned long arg,
+ int (*func)(struct file *file,
+ unsigned int cmd, void *arg))
{
char sbuf[128];
void *mbuf = NULL;
@@ -970,7 +961,7 @@ int dvb_usercopy(struct file *file,
* For this command, the pointer is actually an integer
* argument.
*/
- parg = (void *) arg;
+ parg = (void *)arg;
break;
case _IOC_READ: /* some v4l ioctls are marked wrong ... */
case _IOC_WRITE:
@@ -980,7 +971,7 @@ int dvb_usercopy(struct file *file,
} else {
/* too big to allocate from stack */
mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
- if (NULL == mbuf)
+ if (!mbuf)
return -ENOMEM;
parg = mbuf;
}
@@ -992,15 +983,15 @@ int dvb_usercopy(struct file *file,
}
/* call driver */
- if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
+ err = func(file, cmd, parg);
+ if (err == -ENOIOCTLCMD)
err = -ENOTTY;
if (err < 0)
goto out;
/* Copy results into user buffer */
- switch (_IOC_DIR(cmd))
- {
+ switch (_IOC_DIR(cmd)) {
case _IOC_READ:
case (_IOC_WRITE | _IOC_READ):
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
@@ -1080,19 +1071,20 @@ static char *dvb_devnode(const struct device *dev, umode_t *mode)
dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
}
-
static int __init init_dvbdev(void)
{
int retval;
dev_t dev = MKDEV(DVB_MAJOR, 0);
- if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) {
+ retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB");
+ if (retval != 0) {
pr_err("dvb-core: unable to get major %d\n", DVB_MAJOR);
return retval;
}
cdev_init(&dvb_device_cdev, &dvb_device_fops);
- if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
+ retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS);
+ if (retval != 0) {
pr_err("dvb-core: unable register character device\n");
goto error;
}
@@ -1112,7 +1104,6 @@ error:
return retval;
}
-
static void __exit exit_dvbdev(void)
{
struct dvbdevfops_node *node, *next;
@@ -1122,7 +1113,7 @@ static void __exit exit_dvbdev(void)
unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
list_for_each_entry_safe(node, next, &dvbdevfops_list, list_head) {
- list_del (&node->list_head);
+ list_del(&node->list_head);
kfree(node->fops);
kfree(node);
}
diff --git a/drivers/media/dvb-frontends/a8293.c b/drivers/media/dvb-frontends/a8293.c
index cca7cbdd4c7c..f39887c04978 100644
--- a/drivers/media/dvb-frontends/a8293.c
+++ b/drivers/media/dvb-frontends/a8293.c
@@ -266,7 +266,7 @@ static struct i2c_driver a8293_driver = {
.name = "a8293",
.suppress_bind_attrs = true,
},
- .probe_new = a8293_probe,
+ .probe = a8293_probe,
.remove = a8293_remove,
.id_table = a8293_id_table,
};
diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c
index 206758a73ae2..a829c89792a4 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -1563,7 +1563,7 @@ static struct i2c_driver af9013_driver = {
.name = "af9013",
.suppress_bind_attrs = true,
},
- .probe_new = af9013_probe,
+ .probe = af9013_probe,
.remove = af9013_remove,
.id_table = af9013_id_table,
};
diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c
index a30773f62006..49b7b04a7899 100644
--- a/drivers/media/dvb-frontends/af9033.c
+++ b/drivers/media/dvb-frontends/af9033.c
@@ -1183,7 +1183,7 @@ static struct i2c_driver af9033_driver = {
.name = "af9033",
.suppress_bind_attrs = true,
},
- .probe_new = af9033_probe,
+ .probe = af9033_probe,
.remove = af9033_remove,
.id_table = af9033_id_table,
};
diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c
index 0f748cf46089..acc27376c246 100644
--- a/drivers/media/dvb-frontends/au8522_decoder.c
+++ b/drivers/media/dvb-frontends/au8522_decoder.c
@@ -776,7 +776,7 @@ static struct i2c_driver au8522_driver = {
.driver = {
.name = "au8522",
},
- .probe_new = au8522_probe,
+ .probe = au8522_probe,
.remove = au8522_remove,
.id_table = au8522_id,
};
diff --git a/drivers/media/dvb-frontends/cxd2099.c b/drivers/media/dvb-frontends/cxd2099.c
index c0967ad95220..3f3b85743666 100644
--- a/drivers/media/dvb-frontends/cxd2099.c
+++ b/drivers/media/dvb-frontends/cxd2099.c
@@ -681,7 +681,7 @@ static struct i2c_driver cxd2099_driver = {
.driver = {
.name = "cxd2099",
},
- .probe_new = cxd2099_probe,
+ .probe = cxd2099_probe,
.remove = cxd2099_remove,
.id_table = cxd2099_id,
};
diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c
index 47aa40967171..d7ee294c6833 100644
--- a/drivers/media/dvb-frontends/cxd2820r_core.c
+++ b/drivers/media/dvb-frontends/cxd2820r_core.c
@@ -733,7 +733,7 @@ static struct i2c_driver cxd2820r_driver = {
.name = "cxd2820r",
.suppress_bind_attrs = true,
},
- .probe_new = cxd2820r_probe,
+ .probe = cxd2820r_probe,
.remove = cxd2820r_remove,
.id_table = cxd2820r_id_table,
};
diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c
index e35e00db7dbb..90cb41eacf98 100644
--- a/drivers/media/dvb-frontends/dvb-pll.c
+++ b/drivers/media/dvb-frontends/dvb-pll.c
@@ -942,7 +942,7 @@ static struct i2c_driver dvb_pll_driver = {
.driver = {
.name = "dvb_pll",
},
- .probe_new = dvb_pll_probe,
+ .probe = dvb_pll_probe,
.remove = dvb_pll_remove,
.id_table = dvb_pll_id,
};
diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c
index e4bbf6a51a2b..68c1a3e0e2ba 100644
--- a/drivers/media/dvb-frontends/helene.c
+++ b/drivers/media/dvb-frontends/helene.c
@@ -1110,7 +1110,7 @@ static struct i2c_driver helene_driver = {
.driver = {
.name = "helene",
},
- .probe_new = helene_probe,
+ .probe = helene_probe,
.id_table = helene_id,
};
module_i2c_driver(helene_driver);
diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c
index 6bf723b5ffad..70258884126b 100644
--- a/drivers/media/dvb-frontends/lgdt3306a.c
+++ b/drivers/media/dvb-frontends/lgdt3306a.c
@@ -2249,7 +2249,7 @@ static struct i2c_driver lgdt3306a_driver = {
.name = "lgdt3306a",
.suppress_bind_attrs = true,
},
- .probe_new = lgdt3306a_probe,
+ .probe = lgdt3306a_probe,
.remove = lgdt3306a_remove,
.id_table = lgdt3306a_id_table,
};
diff --git a/drivers/media/dvb-frontends/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c
index 1d6932d8e497..83565209c3b1 100644
--- a/drivers/media/dvb-frontends/lgdt330x.c
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -993,7 +993,7 @@ static struct i2c_driver lgdt330x_driver = {
.name = "lgdt330x",
.suppress_bind_attrs = true,
},
- .probe_new = lgdt330x_probe,
+ .probe = lgdt330x_probe,
.remove = lgdt330x_remove,
.id_table = lgdt330x_id_table,
};
diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c
index f26508b217ee..cf49ac56a37e 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -1941,7 +1941,7 @@ static struct i2c_driver m88ds3103_driver = {
.name = "m88ds3103",
.suppress_bind_attrs = true,
},
- .probe_new = m88ds3103_probe,
+ .probe = m88ds3103_probe,
.remove = m88ds3103_remove,
.id_table = m88ds3103_id_table,
};
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c
index b74b9afed9a2..125fed4891ba 100644
--- a/drivers/media/dvb-frontends/mb86a20s.c
+++ b/drivers/media/dvb-frontends/mb86a20s.c
@@ -1569,7 +1569,7 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe, int status_nr)
u32 t_post_bit_error = 0, t_post_bit_count = 0;
u32 block_error = 0, block_count = 0;
u32 t_block_error = 0, t_block_count = 0;
- int active_layers = 0, pre_ber_layers = 0, post_ber_layers = 0;
+ int pre_ber_layers = 0, post_ber_layers = 0;
int per_layers = 0;
dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
@@ -1589,9 +1589,6 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe, int status_nr)
for (layer = 0; layer < NUM_LAYERS; layer++) {
if (c->isdbt_layer_enabled & (1 << layer)) {
- /* Layer is active and has rc segments */
- active_layers++;
-
/* Handle BER before vterbi */
rc = mb86a20s_get_pre_ber(fe, layer,
&bit_error, &bit_count);
diff --git a/drivers/media/dvb-frontends/mn88443x.c b/drivers/media/dvb-frontends/mn88443x.c
index 0782f8377eb2..2ce5692bc22c 100644
--- a/drivers/media/dvb-frontends/mn88443x.c
+++ b/drivers/media/dvb-frontends/mn88443x.c
@@ -800,7 +800,7 @@ static struct i2c_driver mn88443x_driver = {
.name = "mn88443x",
.of_match_table = mn88443x_of_match,
},
- .probe_new = mn88443x_probe,
+ .probe = mn88443x_probe,
.remove = mn88443x_remove,
.id_table = mn88443x_i2c_id,
};
diff --git a/drivers/media/dvb-frontends/mn88472.c b/drivers/media/dvb-frontends/mn88472.c
index 4a71f1c6371a..73d1e52de569 100644
--- a/drivers/media/dvb-frontends/mn88472.c
+++ b/drivers/media/dvb-frontends/mn88472.c
@@ -718,7 +718,7 @@ static struct i2c_driver mn88472_driver = {
.name = "mn88472",
.suppress_bind_attrs = true,
},
- .probe_new = mn88472_probe,
+ .probe = mn88472_probe,
.remove = mn88472_remove,
.id_table = mn88472_id_table,
};
diff --git a/drivers/media/dvb-frontends/mn88473.c b/drivers/media/dvb-frontends/mn88473.c
index 205b14ae584e..eb50591c0e7a 100644
--- a/drivers/media/dvb-frontends/mn88473.c
+++ b/drivers/media/dvb-frontends/mn88473.c
@@ -753,7 +753,7 @@ static struct i2c_driver mn88473_driver = {
.name = "mn88473",
.suppress_bind_attrs = true,
},
- .probe_new = mn88473_probe,
+ .probe = mn88473_probe,
.remove = mn88473_remove,
.id_table = mn88473_id_table,
};
diff --git a/drivers/media/dvb-frontends/mxl692.c b/drivers/media/dvb-frontends/mxl692.c
index 9858e11943a0..2a31bde2630f 100644
--- a/drivers/media/dvb-frontends/mxl692.c
+++ b/drivers/media/dvb-frontends/mxl692.c
@@ -1355,7 +1355,7 @@ static struct i2c_driver mxl692_driver = {
.driver = {
.name = "mxl692",
},
- .probe_new = mxl692_probe,
+ .probe = mxl692_probe,
.remove = mxl692_remove,
.id_table = mxl692_id_table,
};
diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c
index db3254950147..35c969fd2cb5 100644
--- a/drivers/media/dvb-frontends/rtl2830.c
+++ b/drivers/media/dvb-frontends/rtl2830.c
@@ -886,7 +886,7 @@ static struct i2c_driver rtl2830_driver = {
.name = "rtl2830",
.suppress_bind_attrs = true,
},
- .probe_new = rtl2830_probe,
+ .probe = rtl2830_probe,
.remove = rtl2830_remove,
.id_table = rtl2830_id_table,
};
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index 900d4db8b922..601cf45c3935 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -1135,7 +1135,7 @@ static struct i2c_driver rtl2832_driver = {
.name = "rtl2832",
.suppress_bind_attrs = true,
},
- .probe_new = rtl2832_probe,
+ .probe = rtl2832_probe,
.remove = rtl2832_remove,
.id_table = rtl2832_id_table,
};
diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c
index cc07e965c34c..72810efd1a96 100644
--- a/drivers/media/dvb-frontends/si2165.c
+++ b/drivers/media/dvb-frontends/si2165.c
@@ -1292,7 +1292,7 @@ static struct i2c_driver si2165_driver = {
.driver = {
.name = "si2165",
},
- .probe_new = si2165_probe,
+ .probe = si2165_probe,
.remove = si2165_remove,
.id_table = si2165_id_table,
};
diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c
index 2a0e108c5eb0..dae1f2153e8b 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -798,7 +798,7 @@ static struct i2c_driver si2168_driver = {
.name = "si2168",
.suppress_bind_attrs = true,
},
- .probe_new = si2168_probe,
+ .probe = si2168_probe,
.remove = si2168_remove,
.id_table = si2168_id_table,
};
diff --git a/drivers/media/dvb-frontends/sp2.c b/drivers/media/dvb-frontends/sp2.c
index 3395f6b5b948..4d7d0b8b51b4 100644
--- a/drivers/media/dvb-frontends/sp2.c
+++ b/drivers/media/dvb-frontends/sp2.c
@@ -416,7 +416,7 @@ static struct i2c_driver sp2_driver = {
.driver = {
.name = "sp2",
},
- .probe_new = sp2_probe,
+ .probe = sp2_probe,
.remove = sp2_remove,
.id_table = sp2_id,
};
diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c
index 9bde0ad6f26e..a07dc5fdeb3d 100644
--- a/drivers/media/dvb-frontends/stv090x.c
+++ b/drivers/media/dvb-frontends/stv090x.c
@@ -5084,7 +5084,7 @@ static struct i2c_driver stv090x_driver = {
.name = "stv090x",
.suppress_bind_attrs = true,
},
- .probe_new = stv090x_probe,
+ .probe = stv090x_probe,
.remove = stv090x_remove,
.id_table = stv090x_id_table,
};
diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c
index b2f456116c60..11653f846c12 100644
--- a/drivers/media/dvb-frontends/stv6110x.c
+++ b/drivers/media/dvb-frontends/stv6110x.c
@@ -480,7 +480,7 @@ static struct i2c_driver stv6110x_driver = {
.name = "stv6110x",
.suppress_bind_attrs = true,
},
- .probe_new = stv6110x_probe,
+ .probe = stv6110x_probe,
.remove = stv6110x_remove,
.id_table = stv6110x_id_table,
};
diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c
index 77a991bf4713..879f028f9682 100644
--- a/drivers/media/dvb-frontends/tc90522.c
+++ b/drivers/media/dvb-frontends/tc90522.c
@@ -840,7 +840,7 @@ static struct i2c_driver tc90522_driver = {
.driver = {
.name = "tc90522",
},
- .probe_new = tc90522_probe,
+ .probe = tc90522_probe,
.remove = tc90522_remove,
.id_table = tc90522_id,
};
diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c
index c8e5617d08c0..6640851d8bbc 100644
--- a/drivers/media/dvb-frontends/tda10071.c
+++ b/drivers/media/dvb-frontends/tda10071.c
@@ -1240,7 +1240,7 @@ static struct i2c_driver tda10071_driver = {
.name = "tda10071",
.suppress_bind_attrs = true,
},
- .probe_new = tda10071_probe,
+ .probe = tda10071_probe,
.remove = tda10071_remove,
.id_table = tda10071_id_table,
};
diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c
index c28fee7509cd..f5b60f827697 100644
--- a/drivers/media/dvb-frontends/ts2020.c
+++ b/drivers/media/dvb-frontends/ts2020.c
@@ -720,7 +720,7 @@ static struct i2c_driver ts2020_driver = {
.driver = {
.name = "ts2020",
},
- .probe_new = ts2020_probe,
+ .probe = ts2020_probe,
.remove = ts2020_remove,
.id_table = ts2020_id_table,
};
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 256d55bb2b1d..226454b6a90d 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -338,6 +338,19 @@ config VIDEO_OG01A1B
To compile this driver as a module, choose M here: the
module will be called og01a1b.
+config VIDEO_OV01A10
+ tristate "OmniVision OV01A10 sensor support"
+ depends on VIDEO_DEV && I2C
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
+ select V4L2_FWNODE
+ help
+ This is a Video4Linux2 sensor driver for the OmniVision
+ OV01A10 camera.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ov01a10.
+
config VIDEO_OV02A10
tristate "OmniVision OV02A10 sensor support"
depends on VIDEO_DEV && I2C
@@ -1292,6 +1305,7 @@ config VIDEO_TC358746
select VIDEO_V4L2_SUBDEV_API
select MEDIA_CONTROLLER
select V4L2_FWNODE
+ select GENERIC_PHY
select GENERIC_PHY_MIPI_DPHY
select REGMAP_I2C
help
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index b44dacf935f4..c743aeb5d1ad 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
obj-$(CONFIG_VIDEO_MT9V111) += mt9v111.o
obj-$(CONFIG_VIDEO_OG01A1B) += og01a1b.o
+obj-$(CONFIG_VIDEO_OV01A10) += ov01a10.o
obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o
obj-$(CONFIG_VIDEO_OV08D10) += ov08d10.o
obj-$(CONFIG_VIDEO_OV08X40) += ov08x40.o
diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
index 44c26af49071..5f605b9be3b1 100644
--- a/drivers/media/i2c/ad5820.c
+++ b/drivers/media/i2c/ad5820.c
@@ -370,7 +370,7 @@ static struct i2c_driver ad5820_i2c_driver = {
.pm = &ad5820_pm,
.of_match_table = ad5820_of_table,
},
- .probe_new = ad5820_probe,
+ .probe = ad5820_probe,
.remove = ad5820_remove,
.id_table = ad5820_id_table,
};
diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c
index a61a77de6eee..98ca417b8004 100644
--- a/drivers/media/i2c/adp1653.c
+++ b/drivers/media/i2c/adp1653.c
@@ -535,7 +535,7 @@ static struct i2c_driver adp1653_i2c_driver = {
.name = ADP1653_NAME,
.pm = &adp1653_pm_ops,
},
- .probe_new = adp1653_probe,
+ .probe = adp1653_probe,
.remove = adp1653_remove,
.id_table = adp1653_id_table,
};
diff --git a/drivers/media/i2c/adv7170.c b/drivers/media/i2c/adv7170.c
index aa0f80e299b3..4a2b9fd9e2da 100644
--- a/drivers/media/i2c/adv7170.c
+++ b/drivers/media/i2c/adv7170.c
@@ -387,7 +387,7 @@ static struct i2c_driver adv7170_driver = {
.driver = {
.name = "adv7170",
},
- .probe_new = adv7170_probe,
+ .probe = adv7170_probe,
.remove = adv7170_remove,
.id_table = adv7170_id,
};
diff --git a/drivers/media/i2c/adv7175.c b/drivers/media/i2c/adv7175.c
index d9bea2b9ec33..e454cba4b026 100644
--- a/drivers/media/i2c/adv7175.c
+++ b/drivers/media/i2c/adv7175.c
@@ -442,7 +442,7 @@ static struct i2c_driver adv7175_driver = {
.driver = {
.name = "adv7175",
},
- .probe_new = adv7175_probe,
+ .probe = adv7175_probe,
.remove = adv7175_remove,
.id_table = adv7175_id,
};
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index a22402b7acff..99ba925e8ec8 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -1610,7 +1610,7 @@ static struct i2c_driver adv7180_driver = {
.pm = ADV7180_PM_OPS,
.of_match_table = of_match_ptr(adv7180_of_id),
},
- .probe_new = adv7180_probe,
+ .probe = adv7180_probe,
.remove = adv7180_remove,
.id_table = adv7180_id,
};
diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c
index 98b63d79d33d..3659feafac69 100644
--- a/drivers/media/i2c/adv7183.c
+++ b/drivers/media/i2c/adv7183.c
@@ -631,7 +631,7 @@ static struct i2c_driver adv7183_driver = {
.driver = {
.name = "adv7183",
},
- .probe_new = adv7183_probe,
+ .probe = adv7183_probe,
.remove = adv7183_remove,
.id_table = adv7183_id,
};
diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c
index 7e84869d2434..ff21cd4744d3 100644
--- a/drivers/media/i2c/adv7343.c
+++ b/drivers/media/i2c/adv7343.c
@@ -521,7 +521,7 @@ static struct i2c_driver adv7343_driver = {
.of_match_table = of_match_ptr(adv7343_of_match),
.name = "adv7343",
},
- .probe_new = adv7343_probe,
+ .probe = adv7343_probe,
.remove = adv7343_remove,
.id_table = adv7343_id,
};
diff --git a/drivers/media/i2c/adv7393.c b/drivers/media/i2c/adv7393.c
index 61e916cbe651..7638af455cef 100644
--- a/drivers/media/i2c/adv7393.c
+++ b/drivers/media/i2c/adv7393.c
@@ -455,7 +455,7 @@ static struct i2c_driver adv7393_driver = {
.driver = {
.name = "adv7393",
},
- .probe_new = adv7393_probe,
+ .probe = adv7393_probe,
.remove = adv7393_remove,
.id_table = adv7393_id,
};
diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c
index 4498d78a2357..3eb6d5e8f082 100644
--- a/drivers/media/i2c/adv748x/adv748x-core.c
+++ b/drivers/media/i2c/adv748x/adv748x-core.c
@@ -847,7 +847,7 @@ static struct i2c_driver adv748x_driver = {
.of_match_table = adv748x_of_table,
.pm = &adv748x_pm_ops,
},
- .probe_new = adv748x_probe,
+ .probe = adv748x_probe,
.remove = adv748x_remove,
};
diff --git a/drivers/media/i2c/adv7511-v4l2.c b/drivers/media/i2c/adv7511-v4l2.c
index 3999fa524cab..a9183d9282fd 100644
--- a/drivers/media/i2c/adv7511-v4l2.c
+++ b/drivers/media/i2c/adv7511-v4l2.c
@@ -1957,7 +1957,7 @@ static struct i2c_driver adv7511_driver = {
.driver = {
.name = "adv7511-v4l2",
},
- .probe_new = adv7511_probe,
+ .probe = adv7511_probe,
.remove = adv7511_remove,
.id_table = adv7511_id,
};
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 3d0898c4175e..b202a85fbeaa 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -3689,7 +3689,7 @@ static struct i2c_driver adv76xx_driver = {
.name = "adv7604",
.of_match_table = of_match_ptr(adv76xx_of_id),
},
- .probe_new = adv76xx_probe,
+ .probe = adv76xx_probe,
.remove = adv76xx_remove,
.id_table = adv76xx_i2c_id,
};
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index cb8655574119..c1664a3620c8 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -3619,7 +3619,7 @@ static struct i2c_driver adv7842_driver = {
.driver = {
.name = "adv7842",
},
- .probe_new = adv7842_probe,
+ .probe = adv7842_probe,
.remove = adv7842_remove,
.id_table = adv7842_id,
};
diff --git a/drivers/media/i2c/ak7375.c b/drivers/media/i2c/ak7375.c
index e7cec45bc271..463b51d46320 100644
--- a/drivers/media/i2c/ak7375.c
+++ b/drivers/media/i2c/ak7375.c
@@ -306,7 +306,7 @@ static struct i2c_driver ak7375_i2c_driver = {
.pm = &ak7375_pm_ops,
.of_match_table = ak7375_of_table,
},
- .probe_new = ak7375_probe,
+ .probe = ak7375_probe,
.remove = ak7375_remove,
};
module_i2c_driver(ak7375_i2c_driver);
diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c
index 7c9ab76e2448..ce840adc2aa7 100644
--- a/drivers/media/i2c/ak881x.c
+++ b/drivers/media/i2c/ak881x.c
@@ -314,7 +314,7 @@ static struct i2c_driver ak881x_i2c_driver = {
.driver = {
.name = "ak881x",
},
- .probe_new = ak881x_probe,
+ .probe = ak881x_probe,
.remove = ak881x_remove,
.id_table = ak881x_id,
};
diff --git a/drivers/media/i2c/ar0521.c b/drivers/media/i2c/ar0521.c
index 77f597571167..a4e39871e8f7 100644
--- a/drivers/media/i2c/ar0521.c
+++ b/drivers/media/i2c/ar0521.c
@@ -1198,7 +1198,7 @@ static struct i2c_driver ar0521_i2c_driver = {
.pm = &ar0521_pm_ops,
.of_match_table = ar0521_dt_ids,
},
- .probe_new = ar0521_probe,
+ .probe = ar0521_probe,
.remove = ar0521_remove,
};
diff --git a/drivers/media/i2c/bt819.c b/drivers/media/i2c/bt819.c
index 39f8a5361166..b4a25cc996dc 100644
--- a/drivers/media/i2c/bt819.c
+++ b/drivers/media/i2c/bt819.c
@@ -468,7 +468,7 @@ static struct i2c_driver bt819_driver = {
.driver = {
.name = "bt819",
},
- .probe_new = bt819_probe,
+ .probe = bt819_probe,
.remove = bt819_remove,
.id_table = bt819_id,
};
diff --git a/drivers/media/i2c/bt856.c b/drivers/media/i2c/bt856.c
index d1d397b15b85..814acbd6a5a8 100644
--- a/drivers/media/i2c/bt856.c
+++ b/drivers/media/i2c/bt856.c
@@ -239,7 +239,7 @@ static struct i2c_driver bt856_driver = {
.driver = {
.name = "bt856",
},
- .probe_new = bt856_probe,
+ .probe = bt856_probe,
.remove = bt856_remove,
.id_table = bt856_id,
};
diff --git a/drivers/media/i2c/bt866.c b/drivers/media/i2c/bt866.c
index d632d9a07f04..dada059cbce4 100644
--- a/drivers/media/i2c/bt866.c
+++ b/drivers/media/i2c/bt866.c
@@ -206,7 +206,7 @@ static struct i2c_driver bt866_driver = {
.driver = {
.name = "bt866",
},
- .probe_new = bt866_probe,
+ .probe = bt866_probe,
.remove = bt866_remove,
.id_table = bt866_id,
};
diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c
index 559a415fd827..49e0d9a09530 100644
--- a/drivers/media/i2c/ccs/ccs-core.c
+++ b/drivers/media/i2c/ccs/ccs-core.c
@@ -3731,7 +3731,7 @@ static struct i2c_driver ccs_i2c_driver = {
.name = CCS_NAME,
.pm = &ccs_pm_ops,
},
- .probe_new = ccs_probe,
+ .probe = ccs_probe,
.remove = ccs_remove,
};
diff --git a/drivers/media/i2c/cs3308.c b/drivers/media/i2c/cs3308.c
index a0b66c04fe25..61afa3d799d2 100644
--- a/drivers/media/i2c/cs3308.c
+++ b/drivers/media/i2c/cs3308.c
@@ -118,7 +118,7 @@ static struct i2c_driver cs3308_driver = {
.driver = {
.name = "cs3308",
},
- .probe_new = cs3308_probe,
+ .probe = cs3308_probe,
.remove = cs3308_remove,
.id_table = cs3308_id,
};
diff --git a/drivers/media/i2c/cs5345.c b/drivers/media/i2c/cs5345.c
index ac4b5632fc46..3019a132e079 100644
--- a/drivers/media/i2c/cs5345.c
+++ b/drivers/media/i2c/cs5345.c
@@ -198,7 +198,7 @@ static struct i2c_driver cs5345_driver = {
.driver = {
.name = "cs5345",
},
- .probe_new = cs5345_probe,
+ .probe = cs5345_probe,
.remove = cs5345_remove,
.id_table = cs5345_id,
};
diff --git a/drivers/media/i2c/cs53l32a.c b/drivers/media/i2c/cs53l32a.c
index 670f89de32d4..82881b79e730 100644
--- a/drivers/media/i2c/cs53l32a.c
+++ b/drivers/media/i2c/cs53l32a.c
@@ -209,7 +209,7 @@ static struct i2c_driver cs53l32a_driver = {
.driver = {
.name = "cs53l32a",
},
- .probe_new = cs53l32a_probe,
+ .probe = cs53l32a_probe,
.remove = cs53l32a_remove,
.id_table = cs53l32a_id,
};
diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c
index 46cf422270b2..5aec25289062 100644
--- a/drivers/media/i2c/cx25840/cx25840-core.c
+++ b/drivers/media/i2c/cx25840/cx25840-core.c
@@ -6045,7 +6045,7 @@ static struct i2c_driver cx25840_driver = {
.driver = {
.name = "cx25840",
},
- .probe_new = cx25840_probe,
+ .probe = cx25840_probe,
.remove = cx25840_remove,
.id_table = cx25840_id,
};
diff --git a/drivers/media/i2c/dw9714.c b/drivers/media/i2c/dw9714.c
index af59687383aa..cc09b32ede60 100644
--- a/drivers/media/i2c/dw9714.c
+++ b/drivers/media/i2c/dw9714.c
@@ -299,7 +299,7 @@ static struct i2c_driver dw9714_i2c_driver = {
.pm = &dw9714_pm_ops,
.of_match_table = dw9714_of_table,
},
- .probe_new = dw9714_probe,
+ .probe = dw9714_probe,
.remove = dw9714_remove,
.id_table = dw9714_id_table,
};
diff --git a/drivers/media/i2c/dw9768.c b/drivers/media/i2c/dw9768.c
index 83a3ee275bbe..daabbece8c7e 100644
--- a/drivers/media/i2c/dw9768.c
+++ b/drivers/media/i2c/dw9768.c
@@ -549,7 +549,7 @@ static struct i2c_driver dw9768_i2c_driver = {
.pm = &dw9768_pm_ops,
.of_match_table = dw9768_of_table,
},
- .probe_new = dw9768_probe,
+ .probe = dw9768_probe,
.remove = dw9768_remove,
};
module_i2c_driver(dw9768_i2c_driver);
diff --git a/drivers/media/i2c/dw9807-vcm.c b/drivers/media/i2c/dw9807-vcm.c
index 3599720db7e9..4148009e0e01 100644
--- a/drivers/media/i2c/dw9807-vcm.c
+++ b/drivers/media/i2c/dw9807-vcm.c
@@ -310,7 +310,7 @@ static struct i2c_driver dw9807_i2c_driver = {
.pm = &dw9807_pm_ops,
.of_match_table = dw9807_of_table,
},
- .probe_new = dw9807_probe,
+ .probe = dw9807_probe,
.remove = dw9807_remove,
};
diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c
index ff9bb9fc97dd..d6fc843f9368 100644
--- a/drivers/media/i2c/et8ek8/et8ek8_driver.c
+++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c
@@ -1501,7 +1501,7 @@ static struct i2c_driver et8ek8_i2c_driver = {
.pm = &et8ek8_pm_ops,
.of_match_table = et8ek8_of_table,
},
- .probe_new = et8ek8_probe,
+ .probe = et8ek8_probe,
.remove = __exit_p(et8ek8_remove),
.id_table = et8ek8_id_table,
};
diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c
index 7daefab35cf0..50e78f5b058c 100644
--- a/drivers/media/i2c/hi556.c
+++ b/drivers/media/i2c/hi556.c
@@ -1350,7 +1350,7 @@ static struct i2c_driver hi556_i2c_driver = {
.pm = &hi556_pm_ops,
.acpi_match_table = ACPI_PTR(hi556_acpi_ids),
},
- .probe_new = hi556_probe,
+ .probe = hi556_probe,
.remove = hi556_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c
index 306dc35e925f..fa0038749a3b 100644
--- a/drivers/media/i2c/hi846.c
+++ b/drivers/media/i2c/hi846.c
@@ -1353,7 +1353,8 @@ static int hi846_set_ctrl(struct v4l2_ctrl *ctrl)
exposure_max);
}
- if (!pm_runtime_get_if_in_use(&client->dev))
+ ret = pm_runtime_get_if_in_use(&client->dev);
+ if (!ret || ret == -EAGAIN)
return 0;
switch (ctrl->id) {
@@ -2189,7 +2190,7 @@ static struct i2c_driver hi846_i2c_driver = {
.pm = &hi846_pm_ops,
.of_match_table = hi846_of_match,
},
- .probe_new = hi846_probe,
+ .probe = hi846_probe,
.remove = hi846_remove,
};
diff --git a/drivers/media/i2c/hi847.c b/drivers/media/i2c/hi847.c
index 5a82b15a9513..7cdce392e137 100644
--- a/drivers/media/i2c/hi847.c
+++ b/drivers/media/i2c/hi847.c
@@ -2999,7 +2999,7 @@ static struct i2c_driver hi847_i2c_driver = {
.pm = &hi847_pm_ops,
.acpi_match_table = ACPI_PTR(hi847_acpi_ids),
},
- .probe_new = hi847_probe,
+ .probe = hi847_probe,
.remove = hi847_remove,
};
diff --git a/drivers/media/i2c/imx208.c b/drivers/media/i2c/imx208.c
index 64c70ebf9869..3e870fa9ff79 100644
--- a/drivers/media/i2c/imx208.c
+++ b/drivers/media/i2c/imx208.c
@@ -1100,7 +1100,7 @@ static struct i2c_driver imx208_i2c_driver = {
.pm = &imx208_pm_ops,
.acpi_match_table = ACPI_PTR(imx208_acpi_ids),
},
- .probe_new = imx208_probe,
+ .probe = imx208_probe,
.remove = imx208_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c
index 710c9fb515fd..2f9c8582f940 100644
--- a/drivers/media/i2c/imx214.c
+++ b/drivers/media/i2c/imx214.c
@@ -1112,7 +1112,7 @@ static struct i2c_driver imx214_i2c_driver = {
.pm = &imx214_pm_ops,
.name = "imx214",
},
- .probe_new = imx214_probe,
+ .probe = imx214_probe,
.remove = imx214_remove,
};
diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index f9471c9e3a74..d737d5e9a4a6 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -1583,7 +1583,7 @@ static struct i2c_driver imx219_i2c_driver = {
.of_match_table = imx219_dt_ids,
.pm = &imx219_pm_ops,
},
- .probe_new = imx219_probe,
+ .probe = imx219_probe,
.remove = imx219_remove,
};
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 85d73b186111..e196565e846e 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -1395,7 +1395,7 @@ static struct i2c_driver imx258_i2c_driver = {
.acpi_match_table = ACPI_PTR(imx258_acpi_ids),
.of_match_table = imx258_dt_ids,
},
- .probe_new = imx258_probe,
+ .probe = imx258_probe,
.remove = imx258_remove,
};
diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c
index 9219f3c9594b..f33b692e6951 100644
--- a/drivers/media/i2c/imx274.c
+++ b/drivers/media/i2c/imx274.c
@@ -2168,7 +2168,7 @@ static struct i2c_driver imx274_i2c_driver = {
.pm = &imx274_pm_ops,
.of_match_table = imx274_of_id_table,
},
- .probe_new = imx274_probe,
+ .probe = imx274_probe,
.remove = imx274_remove,
.id_table = imx274_id,
};
diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 5ea25b7acc55..b3f832e9d7e1 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -1716,10 +1716,10 @@ static const struct of_device_id imx290_of_match[] = {
MODULE_DEVICE_TABLE(of, imx290_of_match);
static struct i2c_driver imx290_i2c_driver = {
- .probe_new = imx290_probe,
+ .probe = imx290_probe,
.remove = imx290_remove,
.driver = {
- .name = "imx290",
+ .name = "imx290",
.pm = pm_ptr(&imx290_pm_ops),
.of_match_table = imx290_of_match,
},
diff --git a/drivers/media/i2c/imx296.c b/drivers/media/i2c/imx296.c
index 4f22c0515ef8..c0b9a5349668 100644
--- a/drivers/media/i2c/imx296.c
+++ b/drivers/media/i2c/imx296.c
@@ -922,10 +922,12 @@ static int imx296_read_temperature(struct imx296 *sensor, int *temp)
if (ret < 0)
return ret;
- tmdout = imx296_read(sensor, IMX296_TMDOUT) & IMX296_TMDOUT_MASK;
+ tmdout = imx296_read(sensor, IMX296_TMDOUT);
if (tmdout < 0)
return tmdout;
+ tmdout &= IMX296_TMDOUT_MASK;
+
/* T(°C) = 246.312 - 0.304 * TMDOUT */;
*temp = 246312 - 304 * tmdout;
@@ -1152,7 +1154,7 @@ static struct i2c_driver imx296_i2c_driver = {
.name = "imx296",
.pm = &imx296_pm_ops
},
- .probe_new = imx296_probe,
+ .probe = imx296_probe,
.remove = imx296_remove,
};
diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c
index 45b1b61b2880..a2140848d0d6 100644
--- a/drivers/media/i2c/imx319.c
+++ b/drivers/media/i2c/imx319.c
@@ -2558,7 +2558,7 @@ static struct i2c_driver imx319_i2c_driver = {
.pm = &imx319_pm_ops,
.acpi_match_table = ACPI_PTR(imx319_acpi_ids),
},
- .probe_new = imx319_probe,
+ .probe = imx319_probe,
.remove = imx319_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
diff --git a/drivers/media/i2c/imx334.c b/drivers/media/i2c/imx334.c
index 309c706114d2..d722c9b7cd31 100644
--- a/drivers/media/i2c/imx334.c
+++ b/drivers/media/i2c/imx334.c
@@ -49,7 +49,8 @@
#define IMX334_INCLK_RATE 24000000
/* CSI2 HW configuration */
-#define IMX334_LINK_FREQ 891000000
+#define IMX334_LINK_FREQ_891M 891000000
+#define IMX334_LINK_FREQ_445M 445500000
#define IMX334_NUM_DATA_LANES 4
#define IMX334_REG_MIN 0x00
@@ -117,6 +118,7 @@ struct imx334_mode {
* @vblank: Vertical blanking in lines
* @cur_mode: Pointer to current selected sensor mode
* @mutex: Mutex for serializing sensor controls
+ * @menu_skip_mask: Menu skip mask for link_freq_ctrl
* @cur_code: current selected format code
* @streaming: Flag indicating streaming state
*/
@@ -139,12 +141,14 @@ struct imx334 {
u32 vblank;
const struct imx334_mode *cur_mode;
struct mutex mutex;
+ unsigned long menu_skip_mask;
u32 cur_code;
bool streaming;
};
static const s64 link_freq[] = {
- IMX334_LINK_FREQ,
+ IMX334_LINK_FREQ_891M,
+ IMX334_LINK_FREQ_445M,
};
/* Sensor mode registers for 1920x1080@30fps */
@@ -468,7 +472,7 @@ static const struct imx334_mode supported_modes[] = {
.vblank_min = 45,
.vblank_max = 132840,
.pclk = 297000000,
- .link_freq_idx = 0,
+ .link_freq_idx = 1,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1920x1080_regs),
.regs = mode_1920x1080_regs,
@@ -598,13 +602,22 @@ static int imx334_update_controls(struct imx334 *imx334,
if (ret)
return ret;
+ ret = __v4l2_ctrl_modify_range(imx334->pclk_ctrl, mode->pclk,
+ mode->pclk, 1, mode->pclk);
+ if (ret)
+ return ret;
+
ret = __v4l2_ctrl_modify_range(imx334->hblank_ctrl, mode->hblank,
mode->hblank, 1, mode->hblank);
if (ret)
return ret;
- return __v4l2_ctrl_modify_range(imx334->vblank_ctrl, mode->vblank_min,
+ ret = __v4l2_ctrl_modify_range(imx334->vblank_ctrl, mode->vblank_min,
mode->vblank_max, 1, mode->vblank);
+ if (ret)
+ return ret;
+
+ return __v4l2_ctrl_s_ctrl(imx334->vblank_ctrl, mode->vblank);
}
/**
@@ -698,6 +711,8 @@ static int imx334_set_ctrl(struct v4l2_ctrl *ctrl)
pm_runtime_put(imx334->dev);
break;
+ case V4L2_CID_PIXEL_RATE:
+ case V4L2_CID_LINK_FREQ:
case V4L2_CID_HBLANK:
ret = 0;
break;
@@ -885,7 +900,17 @@ static int imx334_init_pad_cfg(struct v4l2_subdev *sd,
struct v4l2_subdev_format fmt = { 0 };
fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
- imx334_fill_pad_format(imx334, &supported_modes[0], &fmt);
+
+ mutex_lock(&imx334->mutex);
+
+ imx334_fill_pad_format(imx334, imx334->cur_mode, &fmt);
+
+ __v4l2_ctrl_modify_range(imx334->link_freq_ctrl, 0,
+ __fls(imx334->menu_skip_mask),
+ ~(imx334->menu_skip_mask),
+ __ffs(imx334->menu_skip_mask));
+
+ mutex_unlock(&imx334->mutex);
return imx334_set_pad_format(sd, sd_state, &fmt);
}
@@ -1046,8 +1071,8 @@ static int imx334_parse_hw_config(struct imx334 *imx334)
};
struct fwnode_handle *ep;
unsigned long rate;
+ unsigned int i, j;
int ret;
- int i;
if (!fwnode)
return -ENXIO;
@@ -1097,11 +1122,20 @@ static int imx334_parse_hw_config(struct imx334 *imx334)
goto done_endpoint_free;
}
- for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++)
- if (bus_cfg.link_frequencies[i] == IMX334_LINK_FREQ)
+ for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) {
+ for (j = 0; j < ARRAY_SIZE(link_freq); j++) {
+ if (bus_cfg.link_frequencies[i] == link_freq[j]) {
+ set_bit(j, &imx334->menu_skip_mask);
+ break;
+ }
+ }
+
+ if (j == ARRAY_SIZE(link_freq)) {
+ ret = dev_err_probe(imx334->dev, -EINVAL,
+ "no supported link freq found\n");
goto done_endpoint_free;
-
- ret = -EINVAL;
+ }
+ }
done_endpoint_free:
v4l2_fwnode_endpoint_free(&bus_cfg);
@@ -1232,10 +1266,10 @@ static int imx334_init_controls(struct imx334 *imx334)
imx334->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr,
&imx334_ctrl_ops,
V4L2_CID_LINK_FREQ,
- ARRAY_SIZE(link_freq) -
- 1,
- mode->link_freq_idx,
+ __fls(imx334->menu_skip_mask),
+ __ffs(imx334->menu_skip_mask),
link_freq);
+
if (imx334->link_freq_ctrl)
imx334->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
@@ -1302,7 +1336,7 @@ static int imx334_probe(struct i2c_client *client)
}
/* Set default mode to max resolution */
- imx334->cur_mode = &supported_modes[0];
+ imx334->cur_mode = &supported_modes[__ffs(imx334->menu_skip_mask)];
imx334->cur_code = imx334_mbus_codes[0];
imx334->vblank = imx334->cur_mode->vblank;
@@ -1382,7 +1416,7 @@ static const struct of_device_id imx334_of_match[] = {
MODULE_DEVICE_TABLE(of, imx334_of_match);
static struct i2c_driver imx334_driver = {
- .probe_new = imx334_probe,
+ .probe = imx334_probe,
.remove = imx334_remove,
.driver = {
.name = "imx334",
diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c
index 078ede2b7a00..482a0b7f040a 100644
--- a/drivers/media/i2c/imx335.c
+++ b/drivers/media/i2c/imx335.c
@@ -1112,7 +1112,7 @@ static const struct of_device_id imx335_of_match[] = {
MODULE_DEVICE_TABLE(of, imx335_of_match);
static struct i2c_driver imx335_driver = {
- .probe_new = imx335_probe,
+ .probe = imx335_probe,
.remove = imx335_remove,
.driver = {
.name = "imx335",
diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c
index 25d4dbb6041e..6571a98b1e9e 100644
--- a/drivers/media/i2c/imx355.c
+++ b/drivers/media/i2c/imx355.c
@@ -1845,7 +1845,7 @@ static struct i2c_driver imx355_i2c_driver = {
.pm = &imx355_pm_ops,
.acpi_match_table = ACPI_PTR(imx355_acpi_ids),
},
- .probe_new = imx355_probe,
+ .probe = imx355_probe,
.remove = imx355_remove,
};
module_i2c_driver(imx355_i2c_driver);
diff --git a/drivers/media/i2c/imx412.c b/drivers/media/i2c/imx412.c
index e1e986dc8856..c7e862ae4040 100644
--- a/drivers/media/i2c/imx412.c
+++ b/drivers/media/i2c/imx412.c
@@ -1293,7 +1293,7 @@ static const struct of_device_id imx412_of_match[] = {
MODULE_DEVICE_TABLE(of, imx412_of_match);
static struct i2c_driver imx412_driver = {
- .probe_new = imx412_probe,
+ .probe = imx412_probe,
.remove = imx412_remove,
.driver = {
.name = "imx412",
diff --git a/drivers/media/i2c/imx415.c b/drivers/media/i2c/imx415.c
index d90392df98c7..4b5d1ee9cc6b 100644
--- a/drivers/media/i2c/imx415.c
+++ b/drivers/media/i2c/imx415.c
@@ -1283,7 +1283,7 @@ static const struct of_device_id imx415_of_match[] = {
MODULE_DEVICE_TABLE(of, imx415_of_match);
static struct i2c_driver imx415_driver = {
- .probe_new = imx415_probe,
+ .probe = imx415_probe,
.remove = imx415_remove,
.driver = {
.name = "imx415",
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 51921068931d..b37a2aaf8ac0 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -988,7 +988,7 @@ static struct i2c_driver ir_kbd_driver = {
.driver = {
.name = "ir-kbd-i2c",
},
- .probe_new = ir_probe,
+ .probe = ir_probe,
.remove = ir_remove,
.id_table = ir_kbd_id,
};
diff --git a/drivers/media/i2c/isl7998x.c b/drivers/media/i2c/isl7998x.c
index ae7af2cc94f5..92e49d95363d 100644
--- a/drivers/media/i2c/isl7998x.c
+++ b/drivers/media/i2c/isl7998x.c
@@ -1614,7 +1614,7 @@ static struct i2c_driver isl7998x_i2c_driver = {
.of_match_table = of_match_ptr(isl7998x_of_match),
.pm = &isl7998x_pm_ops,
},
- .probe_new = isl7998x_probe,
+ .probe = isl7998x_probe,
.remove = isl7998x_remove,
.id_table = isl7998x_id,
};
diff --git a/drivers/media/i2c/ks0127.c b/drivers/media/i2c/ks0127.c
index 0d86f2db7ad2..5c583f57e3f3 100644
--- a/drivers/media/i2c/ks0127.c
+++ b/drivers/media/i2c/ks0127.c
@@ -696,7 +696,7 @@ static struct i2c_driver ks0127_driver = {
.driver = {
.name = "ks0127",
},
- .probe_new = ks0127_probe,
+ .probe = ks0127_probe,
.remove = ks0127_remove,
.id_table = ks0127_id,
};
diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c
index 5ef613604be7..05283ac68f2d 100644
--- a/drivers/media/i2c/lm3560.c
+++ b/drivers/media/i2c/lm3560.c
@@ -467,7 +467,7 @@ static struct i2c_driver lm3560_i2c_driver = {
.name = LM3560_NAME,
.pm = NULL,
},
- .probe_new = lm3560_probe,
+ .probe = lm3560_probe,
.remove = lm3560_remove,
.id_table = lm3560_id_table,
};
diff --git a/drivers/media/i2c/lm3646.c b/drivers/media/i2c/lm3646.c
index 2a0cf74d2bed..fab3a7e05f92 100644
--- a/drivers/media/i2c/lm3646.c
+++ b/drivers/media/i2c/lm3646.c
@@ -396,7 +396,7 @@ static struct i2c_driver lm3646_i2c_driver = {
.driver = {
.name = LM3646_NAME,
},
- .probe_new = lm3646_probe,
+ .probe = lm3646_probe,
.remove = lm3646_remove,
.id_table = lm3646_id_table,
};
diff --git a/drivers/media/i2c/m52790.c b/drivers/media/i2c/m52790.c
index 0e6507ab7e08..f8a69142aae9 100644
--- a/drivers/media/i2c/m52790.c
+++ b/drivers/media/i2c/m52790.c
@@ -172,7 +172,7 @@ static struct i2c_driver m52790_driver = {
.driver = {
.name = "m52790",
},
- .probe_new = m52790_probe,
+ .probe = m52790_probe,
.remove = m52790_remove,
.id_table = m52790_id,
};
diff --git a/drivers/media/i2c/max2175.c b/drivers/media/i2c/max2175.c
index 1019020f3a37..70c2a2948fd4 100644
--- a/drivers/media/i2c/max2175.c
+++ b/drivers/media/i2c/max2175.c
@@ -1429,7 +1429,7 @@ static struct i2c_driver max2175_driver = {
.name = DRIVER_NAME,
.of_match_table = max2175_of_ids,
},
- .probe_new = max2175_probe,
+ .probe = max2175_probe,
.remove = max2175_remove,
.id_table = max2175_id,
};
diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
index 13a986b88588..88c58e0c49aa 100644
--- a/drivers/media/i2c/max9286.c
+++ b/drivers/media/i2c/max9286.c
@@ -1716,7 +1716,7 @@ static struct i2c_driver max9286_i2c_driver = {
.name = "max9286",
.of_match_table = of_match_ptr(max9286_dt_ids),
},
- .probe_new = max9286_probe,
+ .probe = max9286_probe,
.remove = max9286_remove,
};
diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c
index dbd2f0bd3651..5b72d4434224 100644
--- a/drivers/media/i2c/ml86v7667.c
+++ b/drivers/media/i2c/ml86v7667.c
@@ -433,7 +433,7 @@ static struct i2c_driver ml86v7667_i2c_driver = {
.driver = {
.name = DRV_NAME,
},
- .probe_new = ml86v7667_probe,
+ .probe = ml86v7667_probe,
.remove = ml86v7667_remove,
.id_table = ml86v7667_id,
};
diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c
index 12032e28b428..bec76801487a 100644
--- a/drivers/media/i2c/msp3400-driver.c
+++ b/drivers/media/i2c/msp3400-driver.c
@@ -892,7 +892,7 @@ static struct i2c_driver msp_driver = {
.name = "msp3400",
.pm = &msp3400_pm_ops,
},
- .probe_new = msp_probe,
+ .probe = msp_probe,
.remove = msp_remove,
.id_table = msp_id,
};
diff --git a/drivers/media/i2c/mt9m001.c b/drivers/media/i2c/mt9m001.c
index ebf9cf1e1bce..ce9568e8391c 100644
--- a/drivers/media/i2c/mt9m001.c
+++ b/drivers/media/i2c/mt9m001.c
@@ -877,7 +877,7 @@ static struct i2c_driver mt9m001_i2c_driver = {
.pm = &mt9m001_pm_ops,
.of_match_table = mt9m001_of_match,
},
- .probe_new = mt9m001_probe,
+ .probe = mt9m001_probe,
.remove = mt9m001_remove,
.id_table = mt9m001_id,
};
diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c
index f5fe272d1205..2878d328fc01 100644
--- a/drivers/media/i2c/mt9m111.c
+++ b/drivers/media/i2c/mt9m111.c
@@ -1384,7 +1384,7 @@ static struct i2c_driver mt9m111_i2c_driver = {
.name = "mt9m111",
.of_match_table = of_match_ptr(mt9m111_of_match),
},
- .probe_new = mt9m111_probe,
+ .probe = mt9m111_probe,
.remove = mt9m111_remove,
.id_table = mt9m111_id,
};
diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c
index 9e023a4b9bd1..348f1e1098fb 100644
--- a/drivers/media/i2c/mt9p031.c
+++ b/drivers/media/i2c/mt9p031.c
@@ -1248,7 +1248,7 @@ static struct i2c_driver mt9p031_i2c_driver = {
.of_match_table = of_match_ptr(mt9p031_of_match),
.name = "mt9p031",
},
- .probe_new = mt9p031_probe,
+ .probe = mt9p031_probe,
.remove = mt9p031_remove,
.id_table = mt9p031_id,
};
diff --git a/drivers/media/i2c/mt9t112.c b/drivers/media/i2c/mt9t112.c
index a82f056787b8..93f34b767027 100644
--- a/drivers/media/i2c/mt9t112.c
+++ b/drivers/media/i2c/mt9t112.c
@@ -1119,7 +1119,7 @@ static struct i2c_driver mt9t112_i2c_driver = {
.driver = {
.name = "mt9t112",
},
- .probe_new = mt9t112_probe,
+ .probe = mt9t112_probe,
.remove = mt9t112_remove,
.id_table = mt9t112_id,
};
diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c
index c54c7fbf0963..774861ba7747 100644
--- a/drivers/media/i2c/mt9v011.c
+++ b/drivers/media/i2c/mt9v011.c
@@ -585,7 +585,7 @@ static struct i2c_driver mt9v011_driver = {
.driver = {
.name = "mt9v011",
},
- .probe_new = mt9v011_probe,
+ .probe = mt9v011_probe,
.remove = mt9v011_remove,
.id_table = mt9v011_id,
};
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index 7cfd4ebdd2e6..00e7bc6e3235 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -1296,7 +1296,7 @@ static struct i2c_driver mt9v032_driver = {
.name = "mt9v032",
.of_match_table = of_match_ptr(mt9v032_of_match),
},
- .probe_new = mt9v032_probe,
+ .probe = mt9v032_probe,
.remove = mt9v032_remove,
.id_table = mt9v032_id,
};
diff --git a/drivers/media/i2c/mt9v111.c b/drivers/media/i2c/mt9v111.c
index 46d91cd0870c..1f7edc0f5b1a 100644
--- a/drivers/media/i2c/mt9v111.c
+++ b/drivers/media/i2c/mt9v111.c
@@ -1265,7 +1265,7 @@ static struct i2c_driver mt9v111_driver = {
.name = "mt9v111",
.of_match_table = mt9v111_of_match,
},
- .probe_new = mt9v111_probe,
+ .probe = mt9v111_probe,
.remove = mt9v111_remove,
};
diff --git a/drivers/media/i2c/og01a1b.c b/drivers/media/i2c/og01a1b.c
index 35663c10fcd9..b5948759342e 100644
--- a/drivers/media/i2c/og01a1b.c
+++ b/drivers/media/i2c/og01a1b.c
@@ -1115,7 +1115,7 @@ static struct i2c_driver og01a1b_i2c_driver = {
.pm = &og01a1b_pm_ops,
.acpi_match_table = ACPI_PTR(og01a1b_acpi_ids),
},
- .probe_new = og01a1b_probe,
+ .probe = og01a1b_probe,
.remove = og01a1b_remove,
};
diff --git a/drivers/media/i2c/ov01a10.c b/drivers/media/i2c/ov01a10.c
new file mode 100644
index 000000000000..de5bc19e715b
--- /dev/null
+++ b/drivers/media/i2c/ov01a10.c
@@ -0,0 +1,1004 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 Intel Corporation.
+ */
+
+#include <asm/unaligned.h>
+
+#include <linux/acpi.h>
+#include <linux/bitfield.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+
+#define OV01A10_LINK_FREQ_400MHZ 400000000ULL
+#define OV01A10_SCLK 40000000LL
+#define OV01A10_DATA_LANES 1
+
+#define OV01A10_REG_CHIP_ID 0x300a
+#define OV01A10_CHIP_ID 0x560141
+
+#define OV01A10_REG_MODE_SELECT 0x0100
+#define OV01A10_MODE_STANDBY 0x00
+#define OV01A10_MODE_STREAMING 0x01
+
+/* pixel array */
+#define OV01A10_PIXEL_ARRAY_WIDTH 1296
+#define OV01A10_PIXEL_ARRAY_HEIGHT 816
+#define OV01A10_ACITVE_WIDTH 1280
+#define OV01A10_ACITVE_HEIGHT 800
+
+/* vertical and horizontal timings */
+#define OV01A10_REG_VTS 0x380e
+#define OV01A10_VTS_DEF 0x0380
+#define OV01A10_VTS_MIN 0x0380
+#define OV01A10_VTS_MAX 0xffff
+#define OV01A10_HTS_DEF 1488
+
+/* exposure controls */
+#define OV01A10_REG_EXPOSURE 0x3501
+#define OV01A10_EXPOSURE_MIN 4
+#define OV01A10_EXPOSURE_MAX_MARGIN 8
+#define OV01A10_EXPOSURE_STEP 1
+
+/* analog gain controls */
+#define OV01A10_REG_ANALOG_GAIN 0x3508
+#define OV01A10_ANAL_GAIN_MIN 0x100
+#define OV01A10_ANAL_GAIN_MAX 0xffff
+#define OV01A10_ANAL_GAIN_STEP 1
+
+/* digital gain controls */
+#define OV01A10_REG_DIGITAL_GAIN_B 0x350a
+#define OV01A10_REG_DIGITAL_GAIN_GB 0x3510
+#define OV01A10_REG_DIGITAL_GAIN_GR 0x3513
+#define OV01A10_REG_DIGITAL_GAIN_R 0x3516
+#define OV01A10_DGTL_GAIN_MIN 0
+#define OV01A10_DGTL_GAIN_MAX 0x3ffff
+#define OV01A10_DGTL_GAIN_STEP 1
+#define OV01A10_DGTL_GAIN_DEFAULT 1024
+
+/* test pattern control */
+#define OV01A10_REG_TEST_PATTERN 0x4503
+#define OV01A10_TEST_PATTERN_ENABLE BIT(7)
+#define OV01A10_LINK_FREQ_400MHZ_INDEX 0
+
+/* flip and mirror control */
+#define OV01A10_REG_FORMAT1 0x3820
+#define OV01A10_VFLIP_MASK BIT(4)
+#define OV01A10_HFLIP_MASK BIT(3)
+
+/* window offset */
+#define OV01A10_REG_X_WIN 0x3811
+#define OV01A10_REG_Y_WIN 0x3813
+
+struct ov01a10_reg {
+ u16 address;
+ u8 val;
+};
+
+struct ov01a10_reg_list {
+ u32 num_of_regs;
+ const struct ov01a10_reg *regs;
+};
+
+struct ov01a10_link_freq_config {
+ const struct ov01a10_reg_list reg_list;
+};
+
+struct ov01a10_mode {
+ u32 width;
+ u32 height;
+ u32 hts;
+ u32 vts_def;
+ u32 vts_min;
+ u32 link_freq_index;
+
+ const struct ov01a10_reg_list reg_list;
+};
+
+static const struct ov01a10_reg mipi_data_rate_720mbps[] = {
+ {0x0103, 0x01},
+ {0x0302, 0x00},
+ {0x0303, 0x06},
+ {0x0304, 0x01},
+ {0x0305, 0xe0},
+ {0x0306, 0x00},
+ {0x0308, 0x01},
+ {0x0309, 0x00},
+ {0x030c, 0x01},
+ {0x0322, 0x01},
+ {0x0323, 0x06},
+ {0x0324, 0x01},
+ {0x0325, 0x68},
+};
+
+static const struct ov01a10_reg sensor_1280x800_setting[] = {
+ {0x3002, 0xa1},
+ {0x301e, 0xf0},
+ {0x3022, 0x01},
+ {0x3501, 0x03},
+ {0x3502, 0x78},
+ {0x3504, 0x0c},
+ {0x3508, 0x01},
+ {0x3509, 0x00},
+ {0x3601, 0xc0},
+ {0x3603, 0x71},
+ {0x3610, 0x68},
+ {0x3611, 0x86},
+ {0x3640, 0x10},
+ {0x3641, 0x80},
+ {0x3642, 0xdc},
+ {0x3646, 0x55},
+ {0x3647, 0x57},
+ {0x364b, 0x00},
+ {0x3653, 0x10},
+ {0x3655, 0x00},
+ {0x3656, 0x00},
+ {0x365f, 0x0f},
+ {0x3661, 0x45},
+ {0x3662, 0x24},
+ {0x3663, 0x11},
+ {0x3664, 0x07},
+ {0x3709, 0x34},
+ {0x370b, 0x6f},
+ {0x3714, 0x22},
+ {0x371b, 0x27},
+ {0x371c, 0x67},
+ {0x371d, 0xa7},
+ {0x371e, 0xe7},
+ {0x3730, 0x81},
+ {0x3733, 0x10},
+ {0x3734, 0x40},
+ {0x3737, 0x04},
+ {0x3739, 0x1c},
+ {0x3767, 0x00},
+ {0x376c, 0x81},
+ {0x3772, 0x14},
+ {0x37c2, 0x04},
+ {0x37d8, 0x03},
+ {0x37d9, 0x0c},
+ {0x37e0, 0x00},
+ {0x37e1, 0x08},
+ {0x37e2, 0x10},
+ {0x37e3, 0x04},
+ {0x37e4, 0x04},
+ {0x37e5, 0x03},
+ {0x37e6, 0x04},
+ {0x3800, 0x00},
+ {0x3801, 0x00},
+ {0x3802, 0x00},
+ {0x3803, 0x00},
+ {0x3804, 0x05},
+ {0x3805, 0x0f},
+ {0x3806, 0x03},
+ {0x3807, 0x2f},
+ {0x3808, 0x05},
+ {0x3809, 0x00},
+ {0x380a, 0x03},
+ {0x380b, 0x20},
+ {0x380c, 0x02},
+ {0x380d, 0xe8},
+ {0x380e, 0x03},
+ {0x380f, 0x80},
+ {0x3810, 0x00},
+ {0x3811, 0x08},
+ {0x3812, 0x00},
+ {0x3813, 0x08},
+ {0x3814, 0x01},
+ {0x3815, 0x01},
+ {0x3816, 0x01},
+ {0x3817, 0x01},
+ {0x3820, 0xa0},
+ {0x3822, 0x13},
+ {0x3832, 0x28},
+ {0x3833, 0x10},
+ {0x3b00, 0x00},
+ {0x3c80, 0x00},
+ {0x3c88, 0x02},
+ {0x3c8c, 0x07},
+ {0x3c8d, 0x40},
+ {0x3cc7, 0x80},
+ {0x4000, 0xc3},
+ {0x4001, 0xe0},
+ {0x4003, 0x40},
+ {0x4008, 0x02},
+ {0x4009, 0x19},
+ {0x400a, 0x01},
+ {0x400b, 0x6c},
+ {0x4011, 0x00},
+ {0x4041, 0x00},
+ {0x4300, 0xff},
+ {0x4301, 0x00},
+ {0x4302, 0x0f},
+ {0x4503, 0x00},
+ {0x4601, 0x50},
+ {0x4800, 0x64},
+ {0x481f, 0x34},
+ {0x4825, 0x33},
+ {0x4837, 0x11},
+ {0x4881, 0x40},
+ {0x4883, 0x01},
+ {0x4890, 0x00},
+ {0x4901, 0x00},
+ {0x4902, 0x00},
+ {0x4b00, 0x2a},
+ {0x4b0d, 0x00},
+ {0x450a, 0x04},
+ {0x450b, 0x00},
+ {0x5000, 0x65},
+ {0x5200, 0x18},
+ {0x5004, 0x00},
+ {0x5080, 0x40},
+ {0x0305, 0xf4},
+ {0x0325, 0xc2},
+};
+
+static const char * const ov01a10_test_pattern_menu[] = {
+ "Disabled",
+ "Color Bar",
+ "Top-Bottom Darker Color Bar",
+ "Right-Left Darker Color Bar",
+ "Color Bar type 4",
+};
+
+static const s64 link_freq_menu_items[] = {
+ OV01A10_LINK_FREQ_400MHZ,
+};
+
+static const struct ov01a10_link_freq_config link_freq_configs[] = {
+ [OV01A10_LINK_FREQ_400MHZ_INDEX] = {
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mipi_data_rate_720mbps),
+ .regs = mipi_data_rate_720mbps,
+ }
+ },
+};
+
+static const struct ov01a10_mode supported_modes[] = {
+ {
+ .width = OV01A10_ACITVE_WIDTH,
+ .height = OV01A10_ACITVE_HEIGHT,
+ .hts = OV01A10_HTS_DEF,
+ .vts_def = OV01A10_VTS_DEF,
+ .vts_min = OV01A10_VTS_MIN,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(sensor_1280x800_setting),
+ .regs = sensor_1280x800_setting,
+ },
+ .link_freq_index = OV01A10_LINK_FREQ_400MHZ_INDEX,
+ },
+};
+
+struct ov01a10 {
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+ struct v4l2_ctrl_handler ctrl_handler;
+
+ /* v4l2 controls */
+ struct v4l2_ctrl *link_freq;
+ struct v4l2_ctrl *pixel_rate;
+ struct v4l2_ctrl *vblank;
+ struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *exposure;
+
+ const struct ov01a10_mode *cur_mode;
+
+ /* streaming state */
+ bool streaming;
+};
+
+static inline struct ov01a10 *to_ov01a10(struct v4l2_subdev *subdev)
+{
+ return container_of(subdev, struct ov01a10, sd);
+}
+
+static int ov01a10_read_reg(struct ov01a10 *ov01a10, u16 reg, u16 len, u32 *val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ struct i2c_msg msgs[2];
+ u8 addr_buf[2];
+ u8 data_buf[4] = {0};
+ int ret = 0;
+
+ if (len > sizeof(data_buf))
+ return -EINVAL;
+
+ put_unaligned_be16(reg, addr_buf);
+ msgs[0].addr = client->addr;
+ msgs[0].flags = 0;
+ msgs[0].len = sizeof(addr_buf);
+ msgs[0].buf = addr_buf;
+ msgs[1].addr = client->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = len;
+ msgs[1].buf = &data_buf[sizeof(data_buf) - len];
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+
+ if (ret != ARRAY_SIZE(msgs))
+ return ret < 0 ? ret : -EIO;
+
+ *val = get_unaligned_be32(data_buf);
+
+ return 0;
+}
+
+static int ov01a10_write_reg(struct ov01a10 *ov01a10, u16 reg, u16 len, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ u8 buf[6];
+ int ret = 0;
+
+ if (len > 4)
+ return -EINVAL;
+
+ put_unaligned_be16(reg, buf);
+ put_unaligned_be32(val << 8 * (4 - len), buf + 2);
+
+ ret = i2c_master_send(client, buf, len + 2);
+ if (ret != len + 2)
+ return ret < 0 ? ret : -EIO;
+
+ return 0;
+}
+
+static int ov01a10_write_reg_list(struct ov01a10 *ov01a10,
+ const struct ov01a10_reg_list *r_list)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ unsigned int i;
+ int ret = 0;
+
+ for (i = 0; i < r_list->num_of_regs; i++) {
+ ret = ov01a10_write_reg(ov01a10, r_list->regs[i].address, 1,
+ r_list->regs[i].val);
+ if (ret) {
+ dev_err_ratelimited(&client->dev,
+ "write reg 0x%4.4x err = %d\n",
+ r_list->regs[i].address, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int ov01a10_update_digital_gain(struct ov01a10 *ov01a10, u32 d_gain)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ u32 real = d_gain << 6;
+ int ret = 0;
+
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_B, 3, real);
+ if (ret) {
+ dev_err(&client->dev, "failed to set DIGITAL_GAIN_B\n");
+ return ret;
+ }
+
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_GB, 3, real);
+ if (ret) {
+ dev_err(&client->dev, "failed to set DIGITAL_GAIN_GB\n");
+ return ret;
+ }
+
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_GR, 3, real);
+ if (ret) {
+ dev_err(&client->dev, "failed to set DIGITAL_GAIN_GR\n");
+ return ret;
+ }
+
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_R, 3, real);
+ if (ret)
+ dev_err(&client->dev, "failed to set DIGITAL_GAIN_R\n");
+
+ return ret;
+}
+
+static int ov01a10_test_pattern(struct ov01a10 *ov01a10, u32 pattern)
+{
+ if (!pattern)
+ return 0;
+
+ pattern = (pattern - 1) | OV01A10_TEST_PATTERN_ENABLE;
+
+ return ov01a10_write_reg(ov01a10, OV01A10_REG_TEST_PATTERN, 1, pattern);
+}
+
+/* for vflip and hflip, use 0x9 as window offset to keep the bayer */
+static int ov01a10_set_hflip(struct ov01a10 *ov01a10, u32 hflip)
+{
+ int ret;
+ u32 val, offset;
+
+ offset = hflip ? 0x9 : 0x8;
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_X_WIN, 1, offset);
+ if (ret)
+ return ret;
+
+ ret = ov01a10_read_reg(ov01a10, OV01A10_REG_FORMAT1, 1, &val);
+ if (ret)
+ return ret;
+
+ val = hflip ? val | FIELD_PREP(OV01A10_HFLIP_MASK, 0x1) :
+ val & ~OV01A10_HFLIP_MASK;
+
+ return ov01a10_write_reg(ov01a10, OV01A10_REG_FORMAT1, 1, val);
+}
+
+static int ov01a10_set_vflip(struct ov01a10 *ov01a10, u32 vflip)
+{
+ int ret;
+ u32 val, offset;
+
+ offset = vflip ? 0x9 : 0x8;
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_Y_WIN, 1, offset);
+ if (ret)
+ return ret;
+
+ ret = ov01a10_read_reg(ov01a10, OV01A10_REG_FORMAT1, 1, &val);
+ if (ret)
+ return ret;
+
+ val = vflip ? val | FIELD_PREP(OV01A10_VFLIP_MASK, 0x1) :
+ val & ~OV01A10_VFLIP_MASK;
+
+ return ov01a10_write_reg(ov01a10, OV01A10_REG_FORMAT1, 1, val);
+}
+
+static int ov01a10_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct ov01a10 *ov01a10 = container_of(ctrl->handler,
+ struct ov01a10, ctrl_handler);
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ s64 exposure_max;
+ int ret = 0;
+
+ if (ctrl->id == V4L2_CID_VBLANK) {
+ exposure_max = ov01a10->cur_mode->height + ctrl->val -
+ OV01A10_EXPOSURE_MAX_MARGIN;
+ __v4l2_ctrl_modify_range(ov01a10->exposure,
+ ov01a10->exposure->minimum,
+ exposure_max, ov01a10->exposure->step,
+ exposure_max);
+ }
+
+ if (!pm_runtime_get_if_in_use(&client->dev))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_ANALOGUE_GAIN:
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_ANALOG_GAIN, 2,
+ ctrl->val);
+ break;
+
+ case V4L2_CID_DIGITAL_GAIN:
+ ret = ov01a10_update_digital_gain(ov01a10, ctrl->val);
+ break;
+
+ case V4L2_CID_EXPOSURE:
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_EXPOSURE, 2,
+ ctrl->val);
+ break;
+
+ case V4L2_CID_VBLANK:
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_VTS, 2,
+ ov01a10->cur_mode->height + ctrl->val);
+ break;
+
+ case V4L2_CID_TEST_PATTERN:
+ ret = ov01a10_test_pattern(ov01a10, ctrl->val);
+ break;
+
+ case V4L2_CID_HFLIP:
+ ov01a10_set_hflip(ov01a10, ctrl->val);
+ break;
+
+ case V4L2_CID_VFLIP:
+ ov01a10_set_vflip(ov01a10, ctrl->val);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ pm_runtime_put(&client->dev);
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops ov01a10_ctrl_ops = {
+ .s_ctrl = ov01a10_set_ctrl,
+};
+
+static int ov01a10_init_controls(struct ov01a10 *ov01a10)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ struct v4l2_fwnode_device_properties props;
+ u32 vblank_min, vblank_max, vblank_default;
+ struct v4l2_ctrl_handler *ctrl_hdlr;
+ const struct ov01a10_mode *cur_mode;
+ s64 exposure_max, h_blank;
+ int ret = 0;
+ int size;
+
+ ret = v4l2_fwnode_device_parse(&client->dev, &props);
+ if (ret)
+ return ret;
+
+ ctrl_hdlr = &ov01a10->ctrl_handler;
+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
+ if (ret)
+ return ret;
+
+ cur_mode = ov01a10->cur_mode;
+ size = ARRAY_SIZE(link_freq_menu_items);
+
+ ov01a10->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
+ &ov01a10_ctrl_ops,
+ V4L2_CID_LINK_FREQ,
+ size - 1, 0,
+ link_freq_menu_items);
+ if (ov01a10->link_freq)
+ ov01a10->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ ov01a10->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops,
+ V4L2_CID_PIXEL_RATE, 0,
+ OV01A10_SCLK, 1, OV01A10_SCLK);
+
+ vblank_min = cur_mode->vts_min - cur_mode->height;
+ vblank_max = OV01A10_VTS_MAX - cur_mode->height;
+ vblank_default = cur_mode->vts_def - cur_mode->height;
+ ov01a10->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops,
+ V4L2_CID_VBLANK, vblank_min,
+ vblank_max, 1, vblank_default);
+
+ h_blank = cur_mode->hts - cur_mode->width;
+ ov01a10->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops,
+ V4L2_CID_HBLANK, h_blank, h_blank,
+ 1, h_blank);
+ if (ov01a10->hblank)
+ ov01a10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
+ OV01A10_ANAL_GAIN_MIN, OV01A10_ANAL_GAIN_MAX,
+ OV01A10_ANAL_GAIN_STEP, OV01A10_ANAL_GAIN_MIN);
+ v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
+ OV01A10_DGTL_GAIN_MIN, OV01A10_DGTL_GAIN_MAX,
+ OV01A10_DGTL_GAIN_STEP, OV01A10_DGTL_GAIN_DEFAULT);
+
+ exposure_max = cur_mode->vts_def - OV01A10_EXPOSURE_MAX_MARGIN;
+ ov01a10->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops,
+ V4L2_CID_EXPOSURE,
+ OV01A10_EXPOSURE_MIN,
+ exposure_max,
+ OV01A10_EXPOSURE_STEP,
+ exposure_max);
+
+ v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov01a10_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(ov01a10_test_pattern_menu) - 1,
+ 0, 0, ov01a10_test_pattern_menu);
+
+ v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_HFLIP,
+ 0, 1, 1, 0);
+ v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_VFLIP,
+ 0, 1, 1, 0);
+
+ ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov01a10_ctrl_ops,
+ &props);
+ if (ret)
+ goto fail;
+
+ if (ctrl_hdlr->error) {
+ ret = ctrl_hdlr->error;
+ goto fail;
+ }
+
+ ov01a10->sd.ctrl_handler = ctrl_hdlr;
+
+ return 0;
+fail:
+ v4l2_ctrl_handler_free(ctrl_hdlr);
+
+ return ret;
+}
+
+static void ov01a10_update_pad_format(const struct ov01a10_mode *mode,
+ struct v4l2_mbus_framefmt *fmt)
+{
+ fmt->width = mode->width;
+ fmt->height = mode->height;
+ fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->colorspace = V4L2_COLORSPACE_RAW;
+}
+
+static int ov01a10_start_streaming(struct ov01a10 *ov01a10)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ const struct ov01a10_reg_list *reg_list;
+ int link_freq_index;
+ int ret = 0;
+
+ link_freq_index = ov01a10->cur_mode->link_freq_index;
+ reg_list = &link_freq_configs[link_freq_index].reg_list;
+ ret = ov01a10_write_reg_list(ov01a10, reg_list);
+ if (ret) {
+ dev_err(&client->dev, "failed to set plls\n");
+ return ret;
+ }
+
+ reg_list = &ov01a10->cur_mode->reg_list;
+ ret = ov01a10_write_reg_list(ov01a10, reg_list);
+ if (ret) {
+ dev_err(&client->dev, "failed to set mode\n");
+ return ret;
+ }
+
+ ret = __v4l2_ctrl_handler_setup(ov01a10->sd.ctrl_handler);
+ if (ret)
+ return ret;
+
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_MODE_SELECT, 1,
+ OV01A10_MODE_STREAMING);
+ if (ret)
+ dev_err(&client->dev, "failed to start streaming\n");
+
+ return ret;
+}
+
+static void ov01a10_stop_streaming(struct ov01a10 *ov01a10)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ int ret = 0;
+
+ ret = ov01a10_write_reg(ov01a10, OV01A10_REG_MODE_SELECT, 1,
+ OV01A10_MODE_STANDBY);
+ if (ret)
+ dev_err(&client->dev, "failed to stop streaming\n");
+}
+
+static int ov01a10_set_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct ov01a10 *ov01a10 = to_ov01a10(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct v4l2_subdev_state *state;
+ int ret = 0;
+
+ state = v4l2_subdev_lock_and_get_active_state(sd);
+ if (ov01a10->streaming == enable)
+ goto unlock;
+
+ if (enable) {
+ ret = pm_runtime_resume_and_get(&client->dev);
+ if (ret < 0)
+ goto unlock;
+
+ ret = ov01a10_start_streaming(ov01a10);
+ if (ret) {
+ pm_runtime_put(&client->dev);
+ goto unlock;
+ }
+
+ goto done;
+ }
+
+ ov01a10_stop_streaming(ov01a10);
+ pm_runtime_put(&client->dev);
+done:
+ ov01a10->streaming = enable;
+unlock:
+ v4l2_subdev_unlock_state(state);
+
+ return ret;
+}
+
+static int __maybe_unused ov01a10_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct ov01a10 *ov01a10 = to_ov01a10(sd);
+ struct v4l2_subdev_state *state;
+
+ state = v4l2_subdev_lock_and_get_active_state(sd);
+ if (ov01a10->streaming)
+ ov01a10_stop_streaming(ov01a10);
+
+ v4l2_subdev_unlock_state(state);
+
+ return 0;
+}
+
+static int __maybe_unused ov01a10_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct ov01a10 *ov01a10 = to_ov01a10(sd);
+ struct v4l2_subdev_state *state;
+ int ret = 0;
+
+ state = v4l2_subdev_lock_and_get_active_state(sd);
+ if (!ov01a10->streaming)
+ goto exit;
+
+ ret = ov01a10_start_streaming(ov01a10);
+ if (ret) {
+ ov01a10->streaming = false;
+ ov01a10_stop_streaming(ov01a10);
+ }
+
+exit:
+ v4l2_subdev_unlock_state(state);
+
+ return ret;
+}
+
+static int ov01a10_set_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct ov01a10 *ov01a10 = to_ov01a10(sd);
+ const struct ov01a10_mode *mode;
+ struct v4l2_mbus_framefmt *format;
+ s32 vblank_def, h_blank;
+
+ mode = v4l2_find_nearest_size(supported_modes,
+ ARRAY_SIZE(supported_modes), width,
+ height, fmt->format.width,
+ fmt->format.height);
+
+ ov01a10_update_pad_format(mode, &fmt->format);
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+ ov01a10->cur_mode = mode;
+ __v4l2_ctrl_s_ctrl(ov01a10->link_freq, mode->link_freq_index);
+ __v4l2_ctrl_s_ctrl_int64(ov01a10->pixel_rate, OV01A10_SCLK);
+
+ vblank_def = mode->vts_def - mode->height;
+ __v4l2_ctrl_modify_range(ov01a10->vblank,
+ mode->vts_min - mode->height,
+ OV01A10_VTS_MAX - mode->height, 1,
+ vblank_def);
+ __v4l2_ctrl_s_ctrl(ov01a10->vblank, vblank_def);
+ h_blank = mode->hts - mode->width;
+ __v4l2_ctrl_modify_range(ov01a10->hblank, h_blank, h_blank, 1,
+ h_blank);
+ }
+
+ format = v4l2_subdev_get_pad_format(sd, sd_state, fmt->stream);
+ *format = fmt->format;
+
+ return 0;
+}
+
+static int ov01a10_init_cfg(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ .format = {
+ .width = OV01A10_ACITVE_WIDTH,
+ .height = OV01A10_ACITVE_HEIGHT,
+ },
+ };
+
+ ov01a10_set_format(sd, state, &fmt);
+
+ return 0;
+}
+
+static int ov01a10_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index > 0)
+ return -EINVAL;
+
+ code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+
+ return 0;
+}
+
+static int ov01a10_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (fse->index >= ARRAY_SIZE(supported_modes) ||
+ fse->code != MEDIA_BUS_FMT_SBGGR10_1X10)
+ return -EINVAL;
+
+ fse->min_width = supported_modes[fse->index].width;
+ fse->max_width = fse->min_width;
+ fse->min_height = supported_modes[fse->index].height;
+ fse->max_height = fse->min_height;
+
+ return 0;
+}
+
+static int ov01a10_get_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_selection *sel)
+{
+ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ switch (sel->target) {
+ case V4L2_SEL_TGT_NATIVE_SIZE:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = OV01A10_PIXEL_ARRAY_WIDTH;
+ sel->r.height = OV01A10_PIXEL_ARRAY_HEIGHT;
+ return 0;
+ case V4L2_SEL_TGT_CROP:
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ sel->r.top = (OV01A10_PIXEL_ARRAY_HEIGHT -
+ OV01A10_ACITVE_HEIGHT) / 2;
+ sel->r.left = (OV01A10_PIXEL_ARRAY_WIDTH -
+ OV01A10_ACITVE_WIDTH) / 2;
+ sel->r.width = OV01A10_ACITVE_WIDTH;
+ sel->r.height = OV01A10_ACITVE_HEIGHT;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static const struct v4l2_subdev_core_ops ov01a10_core_ops = {
+ .log_status = v4l2_ctrl_subdev_log_status,
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops ov01a10_video_ops = {
+ .s_stream = ov01a10_set_stream,
+};
+
+static const struct v4l2_subdev_pad_ops ov01a10_pad_ops = {
+ .init_cfg = ov01a10_init_cfg,
+ .set_fmt = ov01a10_set_format,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .get_selection = ov01a10_get_selection,
+ .enum_mbus_code = ov01a10_enum_mbus_code,
+ .enum_frame_size = ov01a10_enum_frame_size,
+};
+
+static const struct v4l2_subdev_ops ov01a10_subdev_ops = {
+ .core = &ov01a10_core_ops,
+ .video = &ov01a10_video_ops,
+ .pad = &ov01a10_pad_ops,
+};
+
+static const struct media_entity_operations ov01a10_subdev_entity_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+static int ov01a10_identify_module(struct ov01a10 *ov01a10)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd);
+ int ret;
+ u32 val;
+
+ ret = ov01a10_read_reg(ov01a10, OV01A10_REG_CHIP_ID, 3, &val);
+ if (ret)
+ return ret;
+
+ if (val != OV01A10_CHIP_ID) {
+ dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
+ OV01A10_CHIP_ID, val);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void ov01a10_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
+
+ pm_runtime_disable(&client->dev);
+}
+
+static int ov01a10_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct ov01a10 *ov01a10;
+ int ret = 0;
+
+ ov01a10 = devm_kzalloc(dev, sizeof(*ov01a10), GFP_KERNEL);
+ if (!ov01a10)
+ return -ENOMEM;
+
+ v4l2_i2c_subdev_init(&ov01a10->sd, client, &ov01a10_subdev_ops);
+
+ ret = ov01a10_identify_module(ov01a10);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to find sensor\n");
+
+ ov01a10->cur_mode = &supported_modes[0];
+
+ ret = ov01a10_init_controls(ov01a10);
+ if (ret) {
+ dev_err(dev, "failed to init controls: %d\n", ret);
+ return ret;
+ }
+
+ ov01a10->sd.state_lock = ov01a10->ctrl_handler.lock;
+ ov01a10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+ V4L2_SUBDEV_FL_HAS_EVENTS;
+ ov01a10->sd.entity.ops = &ov01a10_subdev_entity_ops;
+ ov01a10->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+ ov01a10->pad.flags = MEDIA_PAD_FL_SOURCE;
+
+ ret = media_entity_pads_init(&ov01a10->sd.entity, 1, &ov01a10->pad);
+ if (ret) {
+ dev_err(dev, "Failed to init entity pads: %d\n", ret);
+ goto err_handler_free;
+ }
+
+ ret = v4l2_subdev_init_finalize(&ov01a10->sd);
+ if (ret) {
+ dev_err(dev, "Failed to allocate subdev state: %d\n", ret);
+ goto err_media_entity_cleanup;
+ }
+
+ ret = v4l2_async_register_subdev_sensor(&ov01a10->sd);
+ if (ret < 0) {
+ dev_err(dev, "Failed to register subdev: %d\n", ret);
+ goto err_media_entity_cleanup;
+ }
+
+ pm_runtime_enable(dev);
+ pm_runtime_idle(dev);
+
+ return 0;
+
+err_media_entity_cleanup:
+ media_entity_cleanup(&ov01a10->sd.entity);
+
+err_handler_free:
+ v4l2_ctrl_handler_free(ov01a10->sd.ctrl_handler);
+
+ return ret;
+}
+
+static const struct dev_pm_ops ov01a10_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(ov01a10_suspend, ov01a10_resume)
+};
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id ov01a10_acpi_ids[] = {
+ { "OVTI01A0" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(acpi, ov01a10_acpi_ids);
+#endif
+
+static struct i2c_driver ov01a10_i2c_driver = {
+ .driver = {
+ .name = "ov01a10",
+ .pm = &ov01a10_pm_ops,
+ .acpi_match_table = ACPI_PTR(ov01a10_acpi_ids),
+ },
+ .probe_new = ov01a10_probe,
+ .remove = ov01a10_remove,
+};
+
+module_i2c_driver(ov01a10_i2c_driver);
+
+MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
+MODULE_AUTHOR("Wang Yating <yating.wang@intel.com>");
+MODULE_DESCRIPTION("OmniVision OV01A10 sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/ov02a10.c b/drivers/media/i2c/ov02a10.c
index 2c1eb724d8e5..741d977a76f3 100644
--- a/drivers/media/i2c/ov02a10.c
+++ b/drivers/media/i2c/ov02a10.c
@@ -1002,8 +1002,8 @@ static struct i2c_driver ov02a10_i2c_driver = {
.pm = &ov02a10_pm_ops,
.of_match_table = ov02a10_of_match,
},
- .probe_new = &ov02a10_probe,
- .remove = &ov02a10_remove,
+ .probe = ov02a10_probe,
+ .remove = ov02a10_remove,
};
module_i2c_driver(ov02a10_i2c_driver);
diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c
index a39e086a51c5..7d55d4ca24de 100644
--- a/drivers/media/i2c/ov08d10.c
+++ b/drivers/media/i2c/ov08d10.c
@@ -1520,7 +1520,7 @@ static struct i2c_driver ov08d10_i2c_driver = {
.pm = &ov08d10_pm_ops,
.acpi_match_table = ACPI_PTR(ov08d10_acpi_ids),
},
- .probe_new = ov08d10_probe,
+ .probe = ov08d10_probe,
.remove = ov08d10_remove,
};
diff --git a/drivers/media/i2c/ov08x40.c b/drivers/media/i2c/ov08x40.c
index 72ae7fba94eb..77bcdcd0824c 100644
--- a/drivers/media/i2c/ov08x40.c
+++ b/drivers/media/i2c/ov08x40.c
@@ -3313,7 +3313,7 @@ static struct i2c_driver ov08x40_i2c_driver = {
.pm = &ov08x40_pm_ops,
.acpi_match_table = ACPI_PTR(ov08x40_acpi_ids),
},
- .probe_new = ov08x40_probe,
+ .probe = ov08x40_probe,
.remove = ov08x40_remove,
};
diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c
index 69a7a2c590db..3db3e64fa3ff 100644
--- a/drivers/media/i2c/ov13858.c
+++ b/drivers/media/i2c/ov13858.c
@@ -1806,7 +1806,7 @@ static struct i2c_driver ov13858_i2c_driver = {
.pm = &ov13858_pm_ops,
.acpi_match_table = ACPI_PTR(ov13858_acpi_ids),
},
- .probe_new = ov13858_probe,
+ .probe = ov13858_probe,
.remove = ov13858_remove,
.id_table = ov13858_id_table,
};
diff --git a/drivers/media/i2c/ov13b10.c b/drivers/media/i2c/ov13b10.c
index c1430044fb1e..6110fb1e6bc6 100644
--- a/drivers/media/i2c/ov13b10.c
+++ b/drivers/media/i2c/ov13b10.c
@@ -1496,7 +1496,7 @@ static struct i2c_driver ov13b10_i2c_driver = {
.pm = &ov13b10_pm_ops,
.acpi_match_table = ACPI_PTR(ov13b10_acpi_ids),
},
- .probe_new = ov13b10_probe,
+ .probe = ov13b10_probe,
.remove = ov13b10_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
diff --git a/drivers/media/i2c/ov2640.c b/drivers/media/i2c/ov2640.c
index 39d56838a4ef..ec801a81c2d0 100644
--- a/drivers/media/i2c/ov2640.c
+++ b/drivers/media/i2c/ov2640.c
@@ -1298,7 +1298,7 @@ static struct i2c_driver ov2640_i2c_driver = {
.name = "ov2640",
.of_match_table = of_match_ptr(ov2640_of_match),
},
- .probe_new = ov2640_probe,
+ .probe = ov2640_probe,
.remove = ov2640_remove,
.id_table = ov2640_id,
};
diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c
index 42fc64ada08c..5429bd2eb053 100644
--- a/drivers/media/i2c/ov2659.c
+++ b/drivers/media/i2c/ov2659.c
@@ -1584,7 +1584,7 @@ static struct i2c_driver ov2659_i2c_driver = {
.pm = &ov2659_pm_ops,
.of_match_table = of_match_ptr(ov2659_of_match),
},
- .probe_new = ov2659_probe,
+ .probe = ov2659_probe,
.remove = ov2659_remove,
.id_table = ov2659_id,
};
diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c
index 54153bf66bdd..d06e9fc37f77 100644
--- a/drivers/media/i2c/ov2680.c
+++ b/drivers/media/i2c/ov2680.c
@@ -1158,7 +1158,7 @@ static struct i2c_driver ov2680_i2c_driver = {
.pm = &ov2680_pm_ops,
.of_match_table = of_match_ptr(ov2680_dt_ids),
},
- .probe_new = ov2680_probe,
+ .probe = ov2680_probe,
.remove = ov2680_remove,
};
module_i2c_driver(ov2680_i2c_driver);
diff --git a/drivers/media/i2c/ov2685.c b/drivers/media/i2c/ov2685.c
index f119a93e7c64..303793e1f97d 100644
--- a/drivers/media/i2c/ov2685.c
+++ b/drivers/media/i2c/ov2685.c
@@ -903,8 +903,8 @@ static struct i2c_driver ov2685_i2c_driver = {
.pm = &ov2685_pm_ops,
.of_match_table = of_match_ptr(ov2685_of_match),
},
- .probe_new = &ov2685_probe,
- .remove = &ov2685_remove,
+ .probe = ov2685_probe,
+ .remove = ov2685_remove,
};
module_i2c_driver(ov2685_i2c_driver);
diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index 89d126240c34..158d934733c3 100644
--- a/drivers/media/i2c/ov2740.c
+++ b/drivers/media/i2c/ov2740.c
@@ -1215,7 +1215,7 @@ static struct i2c_driver ov2740_i2c_driver = {
.pm = pm_sleep_ptr(&ov2740_pm_ops),
.acpi_match_table = ov2740_acpi_ids,
},
- .probe_new = ov2740_probe,
+ .probe = ov2740_probe,
.remove = ov2740_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c
index c602e507d42b..fda217d2cb10 100644
--- a/drivers/media/i2c/ov4689.c
+++ b/drivers/media/i2c/ov4689.c
@@ -1008,7 +1008,7 @@ static struct i2c_driver ov4689_i2c_driver = {
.pm = &ov4689_pm_ops,
.of_match_table = ov4689_of_match,
},
- .probe_new = ov4689_probe,
+ .probe = ov4689_probe,
.remove = ov4689_remove,
};
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 1536649b9e90..36b509714c8c 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -2815,7 +2815,6 @@ static int ov5640_get_fmt(struct v4l2_subdev *sd,
static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt,
- enum ov5640_frame_rate fr,
const struct ov5640_mode_info **new_mode)
{
struct ov5640_dev *sensor = to_ov5640_dev(sd);
@@ -2927,19 +2926,6 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor)
hblank, hblank, 1, hblank);
vblank = timings->vblank_def;
-
- if (sensor->current_fr != mode->def_fps) {
- /*
- * Compute the vertical blanking according to the framerate
- * configured with s_frame_interval.
- */
- int fie_num = sensor->frame_interval.numerator;
- int fie_denom = sensor->frame_interval.denominator;
-
- vblank = ((fie_num * pixel_rate / fie_denom) / timings->htot) -
- mode->height;
- }
-
__v4l2_ctrl_modify_range(sensor->ctrls.vblank, OV5640_MIN_VBLANK,
OV5640_MAX_VTS - mode->height, 1, vblank);
__v4l2_ctrl_s_ctrl(sensor->ctrls.vblank, vblank);
@@ -2975,8 +2961,7 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
goto out;
}
- ret = ov5640_try_fmt_internal(sd, mbus_fmt,
- sensor->current_fr, &new_mode);
+ ret = ov5640_try_fmt_internal(sd, mbus_fmt, &new_mode);
if (ret)
goto out;
@@ -3851,7 +3836,7 @@ static int ov5640_probe(struct i2c_client *client)
/*
* default init sequence initialize sensor to
- * YUV422 UYVY VGA@30fps
+ * YUV422 UYVY VGA(30FPS in parallel mode, 60 in MIPI CSI-2 mode)
*/
sensor->frame_interval.numerator = 1;
sensor->frame_interval.denominator = ov5640_framerates[OV5640_30_FPS];
@@ -4011,7 +3996,7 @@ static struct i2c_driver ov5640_i2c_driver = {
.pm = &ov5640_pm_ops,
},
.id_table = ov5640_id,
- .probe_new = ov5640_probe,
+ .probe = ov5640_probe,
.remove = ov5640_remove,
};
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index c8999fc4f26f..a70db7e601a4 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -1286,7 +1286,7 @@ static struct i2c_driver ov5645_i2c_driver = {
.name = "ov5645",
.pm = &ov5645_pm_ops,
},
- .probe_new = ov5645_probe,
+ .probe = ov5645_probe,
.remove = ov5645_remove,
.id_table = ov5645_id,
};
diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c
index 233576ee9503..8de398423b7c 100644
--- a/drivers/media/i2c/ov5647.c
+++ b/drivers/media/i2c/ov5647.c
@@ -1515,7 +1515,7 @@ static struct i2c_driver ov5647_driver = {
.name = "ov5647",
.pm = &ov5647_pm_ops,
},
- .probe_new = ov5647_probe,
+ .probe = ov5647_probe,
.remove = ov5647_remove,
.id_table = ov5647_id,
};
diff --git a/drivers/media/i2c/ov5648.c b/drivers/media/i2c/ov5648.c
index 17465fcf28e3..aa10eb4e3991 100644
--- a/drivers/media/i2c/ov5648.c
+++ b/drivers/media/i2c/ov5648.c
@@ -2616,8 +2616,8 @@ static struct i2c_driver ov5648_driver = {
.of_match_table = ov5648_of_match,
.pm = &ov5648_pm_ops,
},
- .probe_new = ov5648_probe,
- .remove = ov5648_remove,
+ .probe = ov5648_probe,
+ .remove = ov5648_remove,
};
module_i2c_driver(ov5648_driver);
diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c
index c026610d0f31..d722348b938b 100644
--- a/drivers/media/i2c/ov5670.c
+++ b/drivers/media/i2c/ov5670.c
@@ -2853,7 +2853,7 @@ static struct i2c_driver ov5670_i2c_driver = {
.acpi_match_table = ACPI_PTR(ov5670_acpi_ids),
.of_match_table = ov5670_of_ids,
},
- .probe_new = ov5670_probe,
+ .probe = ov5670_probe,
.remove = ov5670_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
diff --git a/drivers/media/i2c/ov5675.c b/drivers/media/i2c/ov5675.c
index d55180b3b7aa..700c4b69846f 100644
--- a/drivers/media/i2c/ov5675.c
+++ b/drivers/media/i2c/ov5675.c
@@ -1435,7 +1435,7 @@ static struct i2c_driver ov5675_i2c_driver = {
.acpi_match_table = ACPI_PTR(ov5675_acpi_ids),
.of_match_table = ov5675_of_match,
},
- .probe_new = ov5675_probe,
+ .probe = ov5675_probe,
.remove = ov5675_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
index e3c3bed69ad6..7f9212cce239 100644
--- a/drivers/media/i2c/ov5693.c
+++ b/drivers/media/i2c/ov5693.c
@@ -404,8 +404,8 @@ static int ov5693_read_reg(struct ov5693_device *ov5693, u32 addr, u32 *value)
ret = i2c_transfer(client->adapter, msg, 2);
if (ret < 0)
return dev_err_probe(&client->dev, ret,
- "Failed to read register 0x%04x: %d\n",
- addr & OV5693_REG_ADDR_MASK, ret);
+ "Failed to read register 0x%04x\n",
+ addr & OV5693_REG_ADDR_MASK);
*value = 0;
for (i = 0; i < len; ++i) {
@@ -1554,7 +1554,7 @@ static struct i2c_driver ov5693_driver = {
.of_match_table = ov5693_of_match,
.pm = &ov5693_pm_ops,
},
- .probe_new = ov5693_probe,
+ .probe = ov5693_probe,
.remove = ov5693_remove,
};
module_i2c_driver(ov5693_driver);
diff --git a/drivers/media/i2c/ov5695.c b/drivers/media/i2c/ov5695.c
index b287c28920a6..3023b7254167 100644
--- a/drivers/media/i2c/ov5695.c
+++ b/drivers/media/i2c/ov5695.c
@@ -1392,8 +1392,8 @@ static struct i2c_driver ov5695_i2c_driver = {
.pm = &ov5695_pm_ops,
.of_match_table = of_match_ptr(ov5695_of_match),
},
- .probe_new = &ov5695_probe,
- .remove = &ov5695_remove,
+ .probe = ov5695_probe,
+ .remove = ov5695_remove,
};
module_i2c_driver(ov5695_i2c_driver);
diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c
index 4c0ea2ae671b..1ad07935f046 100644
--- a/drivers/media/i2c/ov6650.c
+++ b/drivers/media/i2c/ov6650.c
@@ -1113,7 +1113,7 @@ static struct i2c_driver ov6650_i2c_driver = {
.driver = {
.name = "ov6650",
},
- .probe_new = ov6650_probe,
+ .probe = ov6650_probe,
.remove = ov6650_remove,
.id_table = ov6650_id,
};
diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c
index 88e987435285..675fb37a6fea 100644
--- a/drivers/media/i2c/ov7251.c
+++ b/drivers/media/i2c/ov7251.c
@@ -1806,7 +1806,7 @@ static struct i2c_driver ov7251_i2c_driver = {
.name = "ov7251",
.pm = &ov7251_pm_ops,
},
- .probe_new = ov7251_probe,
+ .probe = ov7251_probe,
.remove = ov7251_remove,
};
diff --git a/drivers/media/i2c/ov7640.c b/drivers/media/i2c/ov7640.c
index e6751d5cc64b..293f5f404358 100644
--- a/drivers/media/i2c/ov7640.c
+++ b/drivers/media/i2c/ov7640.c
@@ -86,7 +86,7 @@ static struct i2c_driver ov7640_driver = {
.driver = {
.name = "ov7640",
},
- .probe_new = ov7640_probe,
+ .probe = ov7640_probe,
.remove = ov7640_remove,
.id_table = ov7640_id,
};
diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c
index ecbded4f0765..2f55491ef571 100644
--- a/drivers/media/i2c/ov7670.c
+++ b/drivers/media/i2c/ov7670.c
@@ -2033,7 +2033,7 @@ static struct i2c_driver ov7670_driver = {
.name = "ov7670",
.of_match_table = of_match_ptr(ov7670_of_match),
},
- .probe_new = ov7670_probe,
+ .probe = ov7670_probe,
.remove = ov7670_remove,
.id_table = ov7670_id,
};
diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c
index a238e63425f8..386d69c8e074 100644
--- a/drivers/media/i2c/ov772x.c
+++ b/drivers/media/i2c/ov772x.c
@@ -1551,7 +1551,7 @@ static struct i2c_driver ov772x_i2c_driver = {
.name = "ov772x",
.of_match_table = ov772x_of_match,
},
- .probe_new = ov772x_probe,
+ .probe = ov772x_probe,
.remove = ov772x_remove,
.id_table = ov772x_id,
};
diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c
index c9fd9b0bc54a..10e47c7d4e0c 100644
--- a/drivers/media/i2c/ov7740.c
+++ b/drivers/media/i2c/ov7740.c
@@ -1212,7 +1212,7 @@ static struct i2c_driver ov7740_i2c_driver = {
.pm = &ov7740_pm_ops,
.of_match_table = of_match_ptr(ov7740_of_match),
},
- .probe_new = ov7740_probe,
+ .probe = ov7740_probe,
.remove = ov7740_remove,
.id_table = ov7740_id,
};
diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c
index b5c7881383ca..f053c3a7676a 100644
--- a/drivers/media/i2c/ov8856.c
+++ b/drivers/media/i2c/ov8856.c
@@ -2527,7 +2527,7 @@ static struct i2c_driver ov8856_i2c_driver = {
.acpi_match_table = ACPI_PTR(ov8856_acpi_ids),
.of_match_table = ov8856_of_match,
},
- .probe_new = ov8856_probe,
+ .probe = ov8856_probe,
.remove = ov8856_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
diff --git a/drivers/media/i2c/ov8858.c b/drivers/media/i2c/ov8858.c
index 9ca8a17bfbb9..3af6125a2eee 100644
--- a/drivers/media/i2c/ov8858.c
+++ b/drivers/media/i2c/ov8858.c
@@ -1998,8 +1998,8 @@ static struct i2c_driver ov8858_i2c_driver = {
.pm = &ov8858_pm_ops,
.of_match_table = ov8858_of_match,
},
- .probe_new = &ov8858_probe,
- .remove = &ov8858_remove,
+ .probe = ov8858_probe,
+ .remove = ov8858_remove,
};
module_i2c_driver(ov8858_i2c_driver);
diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c
index cae1866134a0..f2213c6158d3 100644
--- a/drivers/media/i2c/ov8865.c
+++ b/drivers/media/i2c/ov8865.c
@@ -3158,8 +3158,8 @@ static struct i2c_driver ov8865_driver = {
.acpi_match_table = ov8865_acpi_match,
.pm = &ov8865_pm_ops,
},
- .probe_new = ov8865_probe,
- .remove = ov8865_remove,
+ .probe = ov8865_probe,
+ .remove = ov8865_remove,
};
module_i2c_driver(ov8865_driver);
diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c
index 7f46cac38aab..068c7449f50e 100644
--- a/drivers/media/i2c/ov9282.c
+++ b/drivers/media/i2c/ov9282.c
@@ -1512,7 +1512,7 @@ static const struct of_device_id ov9282_of_match[] = {
MODULE_DEVICE_TABLE(of, ov9282_of_match);
static struct i2c_driver ov9282_driver = {
- .probe_new = ov9282_probe,
+ .probe = ov9282_probe,
.remove = ov9282_remove,
.driver = {
.name = "ov9282",
diff --git a/drivers/media/i2c/ov9640.c b/drivers/media/i2c/ov9640.c
index a80fa59bf2ae..cbaea049531d 100644
--- a/drivers/media/i2c/ov9640.c
+++ b/drivers/media/i2c/ov9640.c
@@ -762,7 +762,7 @@ static struct i2c_driver ov9640_i2c_driver = {
.driver = {
.name = "ov9640",
},
- .probe_new = ov9640_probe,
+ .probe = ov9640_probe,
.remove = ov9640_remove,
.id_table = ov9640_id,
};
diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c
index 7e7cb1e4520e..da1ab5135eaa 100644
--- a/drivers/media/i2c/ov9650.c
+++ b/drivers/media/i2c/ov9650.c
@@ -1571,7 +1571,7 @@ static struct i2c_driver ov965x_i2c_driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(ov965x_of_match),
},
- .probe_new = ov965x_probe,
+ .probe = ov965x_probe,
.remove = ov965x_remove,
.id_table = ov965x_id,
};
diff --git a/drivers/media/i2c/ov9734.c b/drivers/media/i2c/ov9734.c
index 8b0a158cb297..b6244772bc59 100644
--- a/drivers/media/i2c/ov9734.c
+++ b/drivers/media/i2c/ov9734.c
@@ -1028,7 +1028,7 @@ static struct i2c_driver ov9734_i2c_driver = {
.pm = &ov9734_pm_ops,
.acpi_match_table = ov9734_acpi_ids,
},
- .probe_new = ov9734_probe,
+ .probe = ov9734_probe,
.remove = ov9734_remove,
};
diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
index a2263fa825b5..01a2596282f0 100644
--- a/drivers/media/i2c/rdacm20.c
+++ b/drivers/media/i2c/rdacm20.c
@@ -676,7 +676,7 @@ static struct i2c_driver rdacm20_i2c_driver = {
.name = "rdacm20",
.of_match_table = rdacm20_of_ids,
},
- .probe_new = rdacm20_probe,
+ .probe = rdacm20_probe,
.remove = rdacm20_remove,
.shutdown = rdacm20_shutdown,
};
diff --git a/drivers/media/i2c/rdacm21.c b/drivers/media/i2c/rdacm21.c
index 9ccc56c30d3b..043fec778a5e 100644
--- a/drivers/media/i2c/rdacm21.c
+++ b/drivers/media/i2c/rdacm21.c
@@ -635,7 +635,7 @@ static struct i2c_driver rdacm21_i2c_driver = {
.name = "rdacm21",
.of_match_table = rdacm21_of_ids,
},
- .probe_new = rdacm21_probe,
+ .probe = rdacm21_probe,
.remove = rdacm21_remove,
};
diff --git a/drivers/media/i2c/rj54n1cb0c.c b/drivers/media/i2c/rj54n1cb0c.c
index 9db5473daba0..b430046f9e2a 100644
--- a/drivers/media/i2c/rj54n1cb0c.c
+++ b/drivers/media/i2c/rj54n1cb0c.c
@@ -1421,7 +1421,7 @@ static struct i2c_driver rj54n1_i2c_driver = {
.driver = {
.name = "rj54n1cb0c",
},
- .probe_new = rj54n1_probe,
+ .probe = rj54n1_probe,
.remove = rj54n1_remove,
.id_table = rj54n1_id,
};
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index 7938a3327d3e..ed5b10731a14 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -1729,7 +1729,7 @@ static struct i2c_driver s5c73m3_i2c_driver = {
.of_match_table = of_match_ptr(s5c73m3_of_match),
.name = DRIVER_NAME,
},
- .probe_new = s5c73m3_probe,
+ .probe = s5c73m3_probe,
.remove = s5c73m3_remove,
.id_table = s5c73m3_id,
};
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index 960fbf6428ea..67da2045f543 100644
--- a/drivers/media/i2c/s5k5baf.c
+++ b/drivers/media/i2c/s5k5baf.c
@@ -2021,7 +2021,7 @@ static struct i2c_driver s5k5baf_i2c_driver = {
.of_match_table = s5k5baf_of_match,
.name = S5K5BAF_DRIVER_NAME
},
- .probe_new = s5k5baf_probe,
+ .probe = s5k5baf_probe,
.remove = s5k5baf_remove,
.id_table = s5k5baf_id,
};
diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c
index ef6673b10580..b3560c8f8b41 100644
--- a/drivers/media/i2c/s5k6a3.c
+++ b/drivers/media/i2c/s5k6a3.c
@@ -373,7 +373,7 @@ static struct i2c_driver s5k6a3_driver = {
.of_match_table = of_match_ptr(s5k6a3_of_match),
.name = S5K6A3_DRV_NAME,
},
- .probe_new = s5k6a3_probe,
+ .probe = s5k6a3_probe,
.remove = s5k6a3_remove,
.id_table = s5k6a3_ids,
};
diff --git a/drivers/media/i2c/saa6588.c b/drivers/media/i2c/saa6588.c
index 8752f7cff611..dea9fc09356f 100644
--- a/drivers/media/i2c/saa6588.c
+++ b/drivers/media/i2c/saa6588.c
@@ -505,7 +505,7 @@ static struct i2c_driver saa6588_driver = {
.driver = {
.name = "saa6588",
},
- .probe_new = saa6588_probe,
+ .probe = saa6588_probe,
.remove = saa6588_remove,
.id_table = saa6588_id,
};
diff --git a/drivers/media/i2c/saa6752hs.c b/drivers/media/i2c/saa6752hs.c
index 892d64fe6e81..c106e7a7d1f4 100644
--- a/drivers/media/i2c/saa6752hs.c
+++ b/drivers/media/i2c/saa6752hs.c
@@ -781,7 +781,7 @@ static struct i2c_driver saa6752hs_driver = {
.driver = {
.name = "saa6752hs",
},
- .probe_new = saa6752hs_probe,
+ .probe = saa6752hs_probe,
.remove = saa6752hs_remove,
.id_table = saa6752hs_id,
};
diff --git a/drivers/media/i2c/saa7110.c b/drivers/media/i2c/saa7110.c
index b58e71517376..1520790338ce 100644
--- a/drivers/media/i2c/saa7110.c
+++ b/drivers/media/i2c/saa7110.c
@@ -448,7 +448,7 @@ static struct i2c_driver saa7110_driver = {
.driver = {
.name = "saa7110",
},
- .probe_new = saa7110_probe,
+ .probe = saa7110_probe,
.remove = saa7110_remove,
.id_table = saa7110_id,
};
diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c
index efeda3956f81..a1c71187e773 100644
--- a/drivers/media/i2c/saa7115.c
+++ b/drivers/media/i2c/saa7115.c
@@ -1951,7 +1951,7 @@ static struct i2c_driver saa711x_driver = {
.driver = {
.name = "saa7115",
},
- .probe_new = saa711x_probe,
+ .probe = saa711x_probe,
.remove = saa711x_remove,
.id_table = saa711x_id,
};
diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c
index f98f3a1c38a9..818ed19cf37b 100644
--- a/drivers/media/i2c/saa7127.c
+++ b/drivers/media/i2c/saa7127.c
@@ -810,7 +810,7 @@ static struct i2c_driver saa7127_driver = {
.driver = {
.name = "saa7127",
},
- .probe_new = saa7127_probe,
+ .probe = saa7127_probe,
.remove = saa7127_remove,
.id_table = saa7127_id,
};
diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c
index df01059076fa..933ec0171430 100644
--- a/drivers/media/i2c/saa717x.c
+++ b/drivers/media/i2c/saa717x.c
@@ -1343,7 +1343,7 @@ static struct i2c_driver saa717x_driver = {
.driver = {
.name = "saa717x",
},
- .probe_new = saa717x_probe,
+ .probe = saa717x_probe,
.remove = saa717x_remove,
.id_table = saa717x_id,
};
diff --git a/drivers/media/i2c/saa7185.c b/drivers/media/i2c/saa7185.c
index c78f2e95ba37..5535d71f4860 100644
--- a/drivers/media/i2c/saa7185.c
+++ b/drivers/media/i2c/saa7185.c
@@ -343,7 +343,7 @@ static struct i2c_driver saa7185_driver = {
.driver = {
.name = "saa7185",
},
- .probe_new = saa7185_probe,
+ .probe = saa7185_probe,
.remove = saa7185_remove,
.id_table = saa7185_id,
};
diff --git a/drivers/media/i2c/sony-btf-mpx.c b/drivers/media/i2c/sony-btf-mpx.c
index eef6c8a7c9c9..0f53834f3ae4 100644
--- a/drivers/media/i2c/sony-btf-mpx.c
+++ b/drivers/media/i2c/sony-btf-mpx.c
@@ -375,7 +375,7 @@ static struct i2c_driver sony_btf_mpx_driver = {
.driver = {
.name = "sony-btf-mpx",
},
- .probe_new = sony_btf_mpx_probe,
+ .probe = sony_btf_mpx_probe,
.remove = sony_btf_mpx_remove,
.id_table = sony_btf_mpx_id,
};
diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c
index 31b89aff0e86..906553a28676 100644
--- a/drivers/media/i2c/st-mipid02.c
+++ b/drivers/media/i2c/st-mipid02.c
@@ -736,8 +736,13 @@ static void mipid02_set_fmt_source(struct v4l2_subdev *sd,
{
struct mipid02_dev *bridge = to_mipid02_dev(sd);
- /* source pad mirror active sink pad */
- format->format = bridge->fmt;
+ /* source pad mirror sink pad */
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ format->format = bridge->fmt;
+ else
+ format->format = *v4l2_subdev_get_try_format(sd, sd_state,
+ MIPID02_SINK_0);
+
/* but code may need to be converted */
format->format.code = serial_to_parallel_code(format->format.code);
@@ -745,7 +750,8 @@ static void mipid02_set_fmt_source(struct v4l2_subdev *sd,
if (format->which != V4L2_SUBDEV_FORMAT_TRY)
return;
- *v4l2_subdev_get_try_format(sd, sd_state, format->pad) = format->format;
+ *v4l2_subdev_get_try_format(sd, sd_state, MIPID02_SOURCE) =
+ format->format;
}
static void mipid02_set_fmt_sink(struct v4l2_subdev *sd,
@@ -763,6 +769,9 @@ static void mipid02_set_fmt_sink(struct v4l2_subdev *sd,
fmt = &bridge->fmt;
*fmt = format->format;
+
+ /* Propagate the format change to the source pad */
+ mipid02_set_fmt_source(sd, sd_state, format);
}
static int mipid02_set_fmt(struct v4l2_subdev *sd,
@@ -1091,7 +1100,7 @@ static struct i2c_driver mipid02_i2c_driver = {
.name = "st-mipid02",
.of_match_table = mipid02_dt_ids,
},
- .probe_new = mipid02_probe,
+ .probe = mipid02_probe,
.remove = mipid02_remove,
};
diff --git a/drivers/media/i2c/st-vgxy61.c b/drivers/media/i2c/st-vgxy61.c
index adbd093ad190..30f82ca344c4 100644
--- a/drivers/media/i2c/st-vgxy61.c
+++ b/drivers/media/i2c/st-vgxy61.c
@@ -1951,7 +1951,7 @@ static struct i2c_driver vgxy61_i2c_driver = {
.of_match_table = vgxy61_dt_ids,
.pm = &vgxy61_pm_ops,
},
- .probe_new = vgxy61_probe,
+ .probe = vgxy61_probe,
.remove = vgxy61_remove,
};
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
index 9197fa0b1bc2..15f8163be9bf 100644
--- a/drivers/media/i2c/tc358743.c
+++ b/drivers/media/i2c/tc358743.c
@@ -2206,7 +2206,7 @@ static struct i2c_driver tc358743_driver = {
.name = "tc358743",
.of_match_table = of_match_ptr(tc358743_of_match),
},
- .probe_new = tc358743_probe,
+ .probe = tc358743_probe,
.remove = tc358743_remove,
.id_table = tc358743_id,
};
diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c
index ec1a193ba161..e9b2d906c177 100644
--- a/drivers/media/i2c/tc358746.c
+++ b/drivers/media/i2c/tc358746.c
@@ -1686,7 +1686,7 @@ static struct i2c_driver tc358746_driver = {
.pm = pm_ptr(&tc358746_pm_ops),
.of_match_table = tc358746_of_match,
},
- .probe_new = tc358746_probe,
+ .probe = tc358746_probe,
.remove = tc358746_remove,
};
diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c
index 27f6393dc327..325e99125941 100644
--- a/drivers/media/i2c/tda1997x.c
+++ b/drivers/media/i2c/tda1997x.c
@@ -2834,7 +2834,7 @@ static struct i2c_driver tda1997x_i2c_driver = {
.name = "tda1997x",
.of_match_table = of_match_ptr(tda1997x_of_id),
},
- .probe_new = tda1997x_probe,
+ .probe = tda1997x_probe,
.remove = tda1997x_remove,
.id_table = tda1997x_i2c_id,
};
diff --git a/drivers/media/i2c/tda7432.c b/drivers/media/i2c/tda7432.c
index bbceaac8e0b3..6ecdc8e2e0c6 100644
--- a/drivers/media/i2c/tda7432.c
+++ b/drivers/media/i2c/tda7432.c
@@ -409,7 +409,7 @@ static struct i2c_driver tda7432_driver = {
.driver = {
.name = "tda7432",
},
- .probe_new = tda7432_probe,
+ .probe = tda7432_probe,
.remove = tda7432_remove,
.id_table = tda7432_id,
};
diff --git a/drivers/media/i2c/tda9840.c b/drivers/media/i2c/tda9840.c
index 25fbd7e3950e..1911ef2126be 100644
--- a/drivers/media/i2c/tda9840.c
+++ b/drivers/media/i2c/tda9840.c
@@ -191,7 +191,7 @@ static struct i2c_driver tda9840_driver = {
.driver = {
.name = "tda9840",
},
- .probe_new = tda9840_probe,
+ .probe = tda9840_probe,
.remove = tda9840_remove,
.id_table = tda9840_id,
};
diff --git a/drivers/media/i2c/tea6415c.c b/drivers/media/i2c/tea6415c.c
index d375d2d24354..3ed6e441d515 100644
--- a/drivers/media/i2c/tea6415c.c
+++ b/drivers/media/i2c/tea6415c.c
@@ -150,7 +150,7 @@ static struct i2c_driver tea6415c_driver = {
.driver = {
.name = "tea6415c",
},
- .probe_new = tea6415c_probe,
+ .probe = tea6415c_probe,
.remove = tea6415c_remove,
.id_table = tea6415c_id,
};
diff --git a/drivers/media/i2c/tea6420.c b/drivers/media/i2c/tea6420.c
index 9da1f3b02c57..63f23784bb41 100644
--- a/drivers/media/i2c/tea6420.c
+++ b/drivers/media/i2c/tea6420.c
@@ -132,7 +132,7 @@ static struct i2c_driver tea6420_driver = {
.driver = {
.name = "tea6420",
},
- .probe_new = tea6420_probe,
+ .probe = tea6420_probe,
.remove = tea6420_remove,
.id_table = tea6420_id,
};
diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c
index 67de90cf696e..ea70c1c13872 100644
--- a/drivers/media/i2c/ths7303.c
+++ b/drivers/media/i2c/ths7303.c
@@ -376,7 +376,7 @@ static struct i2c_driver ths7303_driver = {
.driver = {
.name = "ths73x3",
},
- .probe_new = ths7303_probe,
+ .probe = ths7303_probe,
.remove = ths7303_remove,
.id_table = ths7303_id,
};
diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c
index 081ef5a4b950..0e0f676cd221 100644
--- a/drivers/media/i2c/ths8200.c
+++ b/drivers/media/i2c/ths8200.c
@@ -499,7 +499,7 @@ static struct i2c_driver ths8200_driver = {
.name = "ths8200",
.of_match_table = of_match_ptr(ths8200_of_match),
},
- .probe_new = ths8200_probe,
+ .probe = ths8200_probe,
.remove = ths8200_remove,
.id_table = ths8200_id,
};
diff --git a/drivers/media/i2c/tlv320aic23b.c b/drivers/media/i2c/tlv320aic23b.c
index 47198e803817..d800ff8af1ff 100644
--- a/drivers/media/i2c/tlv320aic23b.c
+++ b/drivers/media/i2c/tlv320aic23b.c
@@ -197,7 +197,7 @@ static struct i2c_driver tlv320aic23b_driver = {
.driver = {
.name = "tlv320aic23b",
},
- .probe_new = tlv320aic23b_probe,
+ .probe = tlv320aic23b_probe,
.remove = tlv320aic23b_remove,
.id_table = tlv320aic23b_id,
};
diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c
index a54c76d9e23b..ba20f35cafd5 100644
--- a/drivers/media/i2c/tvaudio.c
+++ b/drivers/media/i2c/tvaudio.c
@@ -2095,7 +2095,7 @@ static struct i2c_driver tvaudio_driver = {
.driver = {
.name = "tvaudio",
},
- .probe_new = tvaudio_probe,
+ .probe = tvaudio_probe,
.remove = tvaudio_remove,
.id_table = tvaudio_id,
};
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c
index f294cae72b01..aa6d4b67b6d5 100644
--- a/drivers/media/i2c/tvp514x.c
+++ b/drivers/media/i2c/tvp514x.c
@@ -1208,7 +1208,7 @@ static struct i2c_driver tvp514x_driver = {
.of_match_table = of_match_ptr(tvp514x_of_match),
.name = TVP514X_MODULE_NAME,
},
- .probe_new = tvp514x_probe,
+ .probe = tvp514x_probe,
.remove = tvp514x_remove,
.id_table = tvp514x_id,
};
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 859f1cb2fa74..c7fb35ee3f9d 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -2280,7 +2280,7 @@ static struct i2c_driver tvp5150_driver = {
.name = "tvp5150",
.pm = &tvp5150_pm_ops,
},
- .probe_new = tvp5150_probe,
+ .probe = tvp5150_probe,
.remove = tvp5150_remove,
.id_table = tvp5150_id,
};
diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
index 4ccd218f5584..a2d7bc799849 100644
--- a/drivers/media/i2c/tvp7002.c
+++ b/drivers/media/i2c/tvp7002.c
@@ -1079,7 +1079,7 @@ static struct i2c_driver tvp7002_driver = {
.of_match_table = of_match_ptr(tvp7002_of_match),
.name = TVP7002_MODULE_NAME,
},
- .probe_new = tvp7002_probe,
+ .probe = tvp7002_probe,
.remove = tvp7002_remove,
.id_table = tvp7002_id,
};
diff --git a/drivers/media/i2c/tw2804.c b/drivers/media/i2c/tw2804.c
index 710790ece11b..6a2521e3a25c 100644
--- a/drivers/media/i2c/tw2804.c
+++ b/drivers/media/i2c/tw2804.c
@@ -423,7 +423,7 @@ static struct i2c_driver tw2804_driver = {
.driver = {
.name = "tw2804",
},
- .probe_new = tw2804_probe,
+ .probe = tw2804_probe,
.remove = tw2804_remove,
.id_table = tw2804_id,
};
diff --git a/drivers/media/i2c/tw9903.c b/drivers/media/i2c/tw9903.c
index 428ee55787e1..996be3960af3 100644
--- a/drivers/media/i2c/tw9903.c
+++ b/drivers/media/i2c/tw9903.c
@@ -254,7 +254,7 @@ static struct i2c_driver tw9903_driver = {
.driver = {
.name = "tw9903",
},
- .probe_new = tw9903_probe,
+ .probe = tw9903_probe,
.remove = tw9903_remove,
.id_table = tw9903_id,
};
diff --git a/drivers/media/i2c/tw9906.c b/drivers/media/i2c/tw9906.c
index 7824ed9b04ed..25c625f6d6e4 100644
--- a/drivers/media/i2c/tw9906.c
+++ b/drivers/media/i2c/tw9906.c
@@ -222,7 +222,7 @@ static struct i2c_driver tw9906_driver = {
.driver = {
.name = "tw9906",
},
- .probe_new = tw9906_probe,
+ .probe = tw9906_probe,
.remove = tw9906_remove,
.id_table = tw9906_id,
};
diff --git a/drivers/media/i2c/tw9910.c b/drivers/media/i2c/tw9910.c
index 459fa22f4341..477a64d8f8ab 100644
--- a/drivers/media/i2c/tw9910.c
+++ b/drivers/media/i2c/tw9910.c
@@ -1012,7 +1012,7 @@ static struct i2c_driver tw9910_i2c_driver = {
.driver = {
.name = "tw9910",
},
- .probe_new = tw9910_probe,
+ .probe = tw9910_probe,
.remove = tw9910_remove,
.id_table = tw9910_id,
};
diff --git a/drivers/media/i2c/uda1342.c b/drivers/media/i2c/uda1342.c
index b6873d866272..da7bc4700bed 100644
--- a/drivers/media/i2c/uda1342.c
+++ b/drivers/media/i2c/uda1342.c
@@ -88,7 +88,7 @@ static struct i2c_driver uda1342_driver = {
.driver = {
.name = "uda1342",
},
- .probe_new = uda1342_probe,
+ .probe = uda1342_probe,
.remove = uda1342_remove,
.id_table = uda1342_id,
};
diff --git a/drivers/media/i2c/upd64031a.c b/drivers/media/i2c/upd64031a.c
index 47eed3aab060..54c2ba0ba375 100644
--- a/drivers/media/i2c/upd64031a.c
+++ b/drivers/media/i2c/upd64031a.c
@@ -228,7 +228,7 @@ static struct i2c_driver upd64031a_driver = {
.driver = {
.name = "upd64031a",
},
- .probe_new = upd64031a_probe,
+ .probe = upd64031a_probe,
.remove = upd64031a_remove,
.id_table = upd64031a_id,
};
diff --git a/drivers/media/i2c/upd64083.c b/drivers/media/i2c/upd64083.c
index 3f5a7d4853a1..2a820589a4cb 100644
--- a/drivers/media/i2c/upd64083.c
+++ b/drivers/media/i2c/upd64083.c
@@ -199,7 +199,7 @@ static struct i2c_driver upd64083_driver = {
.driver = {
.name = "upd64083",
},
- .probe_new = upd64083_probe,
+ .probe = upd64083_probe,
.remove = upd64083_remove,
.id_table = upd64083_id,
};
diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
index dddf9827b314..6f98abc7ccc1 100644
--- a/drivers/media/i2c/video-i2c.c
+++ b/drivers/media/i2c/video-i2c.c
@@ -274,7 +274,7 @@ static const struct hwmon_channel_info amg88xx_temp = {
.config = amg88xx_temp_config,
};
-static const struct hwmon_channel_info *amg88xx_info[] = {
+static const struct hwmon_channel_info * const amg88xx_info[] = {
&amg88xx_temp,
NULL
};
@@ -959,7 +959,7 @@ static struct i2c_driver video_i2c_driver = {
.of_match_table = video_i2c_of_match,
.pm = &video_i2c_pm_ops,
},
- .probe_new = video_i2c_probe,
+ .probe = video_i2c_probe,
.remove = video_i2c_remove,
.id_table = video_i2c_id_table,
};
diff --git a/drivers/media/i2c/vp27smpx.c b/drivers/media/i2c/vp27smpx.c
index ed1c58ea8ed3..0ba3c2b68037 100644
--- a/drivers/media/i2c/vp27smpx.c
+++ b/drivers/media/i2c/vp27smpx.c
@@ -181,7 +181,7 @@ static struct i2c_driver vp27smpx_driver = {
.driver = {
.name = "vp27smpx",
},
- .probe_new = vp27smpx_probe,
+ .probe = vp27smpx_probe,
.remove = vp27smpx_remove,
.id_table = vp27smpx_id,
};
diff --git a/drivers/media/i2c/vpx3220.c b/drivers/media/i2c/vpx3220.c
index aa73d5dcc3e7..1eaae886f217 100644
--- a/drivers/media/i2c/vpx3220.c
+++ b/drivers/media/i2c/vpx3220.c
@@ -546,7 +546,7 @@ static struct i2c_driver vpx3220_driver = {
.driver = {
.name = "vpx3220",
},
- .probe_new = vpx3220_probe,
+ .probe = vpx3220_probe,
.remove = vpx3220_remove,
.id_table = vpx3220_id,
};
diff --git a/drivers/media/i2c/wm8739.c b/drivers/media/i2c/wm8739.c
index 8b34a673ffd3..19bf7a00dff9 100644
--- a/drivers/media/i2c/wm8739.c
+++ b/drivers/media/i2c/wm8739.c
@@ -252,7 +252,7 @@ static struct i2c_driver wm8739_driver = {
.driver = {
.name = "wm8739",
},
- .probe_new = wm8739_probe,
+ .probe = wm8739_probe,
.remove = wm8739_remove,
.id_table = wm8739_id,
};
diff --git a/drivers/media/i2c/wm8775.c b/drivers/media/i2c/wm8775.c
index 56d98518f7eb..d1b716fd6f11 100644
--- a/drivers/media/i2c/wm8775.c
+++ b/drivers/media/i2c/wm8775.c
@@ -298,7 +298,7 @@ static struct i2c_driver wm8775_driver = {
.driver = {
.name = "wm8775",
},
- .probe_new = wm8775_probe,
+ .probe = wm8775_probe,
.remove = wm8775_remove,
.id_table = wm8775_id,
};
diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
index e7216a985ba6..83468d4a440b 100644
--- a/drivers/media/mc/mc-entity.c
+++ b/drivers/media/mc/mc-entity.c
@@ -1052,25 +1052,19 @@ static void __media_entity_remove_link(struct media_entity *entity,
kfree(link);
}
-int media_get_pad_index(struct media_entity *entity, bool is_sink,
+int media_get_pad_index(struct media_entity *entity, u32 pad_type,
enum media_pad_signal_type sig_type)
{
- int i;
- bool pad_is_sink;
+ unsigned int i;
if (!entity)
return -EINVAL;
for (i = 0; i < entity->num_pads; i++) {
- if (entity->pads[i].flags & MEDIA_PAD_FL_SINK)
- pad_is_sink = true;
- else if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE)
- pad_is_sink = false;
- else
- continue; /* This is an error! */
-
- if (pad_is_sink != is_sink)
+ if ((entity->pads[i].flags &
+ (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE)) != pad_type)
continue;
+
if (entity->pads[i].sig_type == sig_type)
return i;
}
@@ -1416,7 +1410,7 @@ struct media_pad *media_pad_remote_pad_unique(const struct media_pad *pad)
EXPORT_SYMBOL_GPL(media_pad_remote_pad_unique);
int media_entity_get_fwnode_pad(struct media_entity *entity,
- struct fwnode_handle *fwnode,
+ const struct fwnode_handle *fwnode,
unsigned long direction_flags)
{
struct fwnode_endpoint endpoint;
diff --git a/drivers/media/pci/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c
index 85fcdc59f0d1..d234a0f404d6 100644
--- a/drivers/media/pci/bt8xx/dst_ca.c
+++ b/drivers/media/pci/bt8xx/dst_ca.c
@@ -534,7 +534,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct
mutex_lock(&dst_ca_mutex);
dvbdev = file->private_data;
- state = (struct dst_state *)dvbdev->priv;
+ state = dvbdev->priv;
p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);
p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL);
diff --git a/drivers/media/pci/cx18/cx18-av-vbi.c b/drivers/media/pci/cx18/cx18-av-vbi.c
index a0d465924e75..65281d40c681 100644
--- a/drivers/media/pci/cx18/cx18-av-vbi.c
+++ b/drivers/media/pci/cx18/cx18-av-vbi.c
@@ -51,7 +51,7 @@ struct vbi_anc_data {
u8 sdid;
u8 data_count;
u8 idid[2];
- u8 payload[1]; /* data_count of payload */
+ u8 payload[]; /* data_count of payload */
/* u8 checksum; */
/* u8 fill[]; Variable number of fill bytes */
};
diff --git a/drivers/media/pci/cx18/cx18-dvb.c b/drivers/media/pci/cx18/cx18-dvb.c
index 33e5a5b5fab4..cf82360a503d 100644
--- a/drivers/media/pci/cx18/cx18-dvb.c
+++ b/drivers/media/pci/cx18/cx18-dvb.c
@@ -234,7 +234,7 @@ static int dvb_register(struct cx18_stream *stream);
static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
- struct cx18_stream *stream = (struct cx18_stream *) demux->priv;
+ struct cx18_stream *stream = demux->priv;
struct cx18 *cx;
int ret;
u32 v;
@@ -305,7 +305,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
- struct cx18_stream *stream = (struct cx18_stream *)demux->priv;
+ struct cx18_stream *stream = demux->priv;
struct cx18 *cx;
int ret = -EINVAL;
diff --git a/drivers/media/pci/dm1105/Kconfig b/drivers/media/pci/dm1105/Kconfig
index e0e3af67c99c..4498c37f4990 100644
--- a/drivers/media/pci/dm1105/Kconfig
+++ b/drivers/media/pci/dm1105/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DVB_DM1105
tristate "SDMC DM1105 based PCI cards"
- depends on DVB_CORE && PCI && I2C && I2C_ALGOBIT
+ depends on DVB_CORE && PCI && I2C && I2C_ALGOBIT && HAS_IOPORT
select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
index 3c84cb121632..34984a7474ed 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
@@ -1375,7 +1375,8 @@ struct sensor_async_subdev {
struct csi2_bus_info csi2;
};
-#define to_sensor_asd(asd) container_of(asd, struct sensor_async_subdev, asd)
+#define to_sensor_asd(__asd) \
+ container_of_const(__asd, struct sensor_async_subdev, asd)
/* The .bound() notifier callback when a match is found */
static int cio2_notifier_bound(struct v4l2_async_notifier *notifier,
@@ -1417,31 +1418,27 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
struct sensor_async_subdev *s_asd;
struct v4l2_async_subdev *asd;
struct cio2_queue *q;
- unsigned int pad;
int ret;
list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) {
s_asd = to_sensor_asd(asd);
q = &cio2->queue[s_asd->csi2.port];
- for (pad = 0; pad < q->sensor->entity.num_pads; pad++)
- if (q->sensor->entity.pads[pad].flags &
- MEDIA_PAD_FL_SOURCE)
- break;
-
- if (pad == q->sensor->entity.num_pads) {
- dev_err(dev, "failed to find src pad for %s\n",
- q->sensor->name);
- return -ENXIO;
+ ret = media_entity_get_fwnode_pad(&q->sensor->entity,
+ s_asd->asd.match.fwnode,
+ MEDIA_PAD_FL_SOURCE);
+ if (ret < 0) {
+ dev_err(dev, "no pad for endpoint %pfw (%d)\n",
+ s_asd->asd.match.fwnode, ret);
+ return ret;
}
- ret = media_create_pad_link(
- &q->sensor->entity, pad,
- &q->subdev.entity, CIO2_PAD_SINK,
- 0);
+ ret = media_create_pad_link(&q->sensor->entity, ret,
+ &q->subdev.entity, CIO2_PAD_SINK,
+ 0);
if (ret) {
- dev_err(dev, "failed to create link for %s\n",
- q->sensor->name);
+ dev_err(dev, "failed to create link for %s (endpoint %pfw, error %d)\n",
+ q->sensor->name, s_asd->asd.match.fwnode, ret);
return ret;
}
}
diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c
index 00ac94d4ab19..0aeb9daaee4c 100644
--- a/drivers/media/pci/ivtv/ivtvfb.c
+++ b/drivers/media/pci/ivtv/ivtvfb.c
@@ -378,8 +378,8 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
unsigned long dma_size;
u16 lead = 0, tail = 0;
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
+ if (!info->screen_base)
+ return -ENODEV;
total_size = info->screen_size;
diff --git a/drivers/media/pci/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c
index 24421c116b0b..3eb749db1ca7 100644
--- a/drivers/media/pci/saa7164/saa7164-dvb.c
+++ b/drivers/media/pci/saa7164/saa7164-dvb.c
@@ -280,7 +280,7 @@ out:
static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
- struct saa7164_port *port = (struct saa7164_port *) demux->priv;
+ struct saa7164_port *port = demux->priv;
struct saa7164_dvb *dvb = &port->dvb;
struct saa7164_dev *dev = port->dev;
int ret = 0;
@@ -307,7 +307,7 @@ static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
- struct saa7164_port *port = (struct saa7164_port *) demux->priv;
+ struct saa7164_port *port = demux->priv;
struct saa7164_dvb *dvb = &port->dvb;
struct saa7164_dev *dev = port->dev;
int ret = 0;
diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c
index 5d5796f24469..710595987522 100644
--- a/drivers/media/pci/ttpci/budget-core.c
+++ b/drivers/media/pci/ttpci/budget-core.c
@@ -308,7 +308,7 @@ int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr,
static int budget_start_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
- struct budget *budget = (struct budget *) demux->priv;
+ struct budget *budget = demux->priv;
int status = 0;
dprintk(2, "budget: %p\n", budget);
@@ -327,7 +327,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed)
static int budget_stop_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
- struct budget *budget = (struct budget *) demux->priv;
+ struct budget *budget = demux->priv;
int status = 0;
dprintk(2, "budget: %p\n", budget);
diff --git a/drivers/media/pci/tw686x/tw686x-audio.c b/drivers/media/pci/tw686x/tw686x-audio.c
index 74cba1368cfa..1ae3845b6743 100644
--- a/drivers/media/pci/tw686x/tw686x-audio.c
+++ b/drivers/media/pci/tw686x/tw686x-audio.c
@@ -59,7 +59,7 @@ void tw686x_audio_irq(struct tw686x_dev *dev, unsigned long requests,
}
spin_unlock_irqrestore(&ac->lock, flags);
- if (!done || !next)
+ if (!done)
continue;
/*
* Checking for a non-nil dma_desc[pb]->virt buffer is
diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform/amphion/vdec.c
index 3fa1a74a2e20..6515f3cdb7a7 100644
--- a/drivers/media/platform/amphion/vdec.c
+++ b/drivers/media/platform/amphion/vdec.c
@@ -279,6 +279,7 @@ static void vdec_handle_resolution_change(struct vpu_inst *inst)
vdec->source_change--;
vpu_notify_source_change(inst);
+ vpu_set_last_buffer_dequeued(inst, false);
}
static int vdec_update_state(struct vpu_inst *inst, enum vpu_codec_state state, u32 force)
@@ -314,7 +315,7 @@ static void vdec_set_last_buffer_dequeued(struct vpu_inst *inst)
return;
if (vdec->eos_received) {
- if (!vpu_set_last_buffer_dequeued(inst)) {
+ if (!vpu_set_last_buffer_dequeued(inst, true)) {
vdec->eos_received--;
vdec_update_state(inst, VPU_CODEC_STATE_DRAIN, 0);
}
@@ -569,7 +570,7 @@ static int vdec_drain(struct vpu_inst *inst)
return 0;
if (!vdec->params.frame_count) {
- vpu_set_last_buffer_dequeued(inst);
+ vpu_set_last_buffer_dequeued(inst, true);
return 0;
}
@@ -608,7 +609,7 @@ static int vdec_cmd_stop(struct vpu_inst *inst)
vpu_trace(inst->dev, "[%d]\n", inst->id);
if (inst->state == VPU_CODEC_STATE_DEINIT) {
- vpu_set_last_buffer_dequeued(inst);
+ vpu_set_last_buffer_dequeued(inst, true);
} else {
vdec->drain = 1;
vdec_drain(inst);
diff --git a/drivers/media/platform/amphion/venc.c b/drivers/media/platform/amphion/venc.c
index e6e8fe45fc7c..58480e2755ec 100644
--- a/drivers/media/platform/amphion/venc.c
+++ b/drivers/media/platform/amphion/venc.c
@@ -458,7 +458,7 @@ static int venc_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd
vpu_inst_lock(inst);
if (cmd->cmd == V4L2_ENC_CMD_STOP) {
if (inst->state == VPU_CODEC_STATE_DEINIT)
- vpu_set_last_buffer_dequeued(inst);
+ vpu_set_last_buffer_dequeued(inst, true);
else
venc_request_eos(inst);
}
@@ -878,7 +878,7 @@ static void venc_set_last_buffer_dequeued(struct vpu_inst *inst)
struct venc_t *venc = inst->priv;
if (venc->stopped && list_empty(&venc->frames))
- vpu_set_last_buffer_dequeued(inst);
+ vpu_set_last_buffer_dequeued(inst, true);
}
static void venc_stop_done(struct vpu_inst *inst)
diff --git a/drivers/media/platform/amphion/vpu_malone.c b/drivers/media/platform/amphion/vpu_malone.c
index ef44bff9fbaf..c1d6606ad7e5 100644
--- a/drivers/media/platform/amphion/vpu_malone.c
+++ b/drivers/media/platform/amphion/vpu_malone.c
@@ -1313,6 +1313,15 @@ static int vpu_malone_insert_scode_pic(struct malone_scode_t *scode, u32 codec_i
return sizeof(hdr);
}
+static int vpu_malone_insert_scode_vc1_g_seq(struct malone_scode_t *scode)
+{
+ if (!scode->inst->total_input_count)
+ return 0;
+ if (vpu_vb_is_codecconfig(to_vb2_v4l2_buffer(scode->vb)))
+ scode->need_data = 0;
+ return 0;
+}
+
static int vpu_malone_insert_scode_vc1_g_pic(struct malone_scode_t *scode)
{
struct vb2_v4l2_buffer *vbuf;
@@ -1344,6 +1353,8 @@ static int vpu_malone_insert_scode_vc1_l_seq(struct malone_scode_t *scode)
int size = 0;
u8 rcv_seqhdr[MALONE_VC1_RCV_SEQ_HEADER_LEN];
+ if (vpu_vb_is_codecconfig(to_vb2_v4l2_buffer(scode->vb)))
+ scode->need_data = 0;
if (scode->inst->total_input_count)
return 0;
scode->need_data = 0;
@@ -1458,6 +1469,7 @@ static const struct malone_scode_handler scode_handlers[] = {
},
{
.pixelformat = V4L2_PIX_FMT_VC1_ANNEX_G,
+ .insert_scode_seq = vpu_malone_insert_scode_vc1_g_seq,
.insert_scode_pic = vpu_malone_insert_scode_vc1_g_pic,
},
{
diff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c
index a48edb445eea..021235e1c144 100644
--- a/drivers/media/platform/amphion/vpu_v4l2.c
+++ b/drivers/media/platform/amphion/vpu_v4l2.c
@@ -100,7 +100,7 @@ int vpu_notify_source_change(struct vpu_inst *inst)
return 0;
}
-int vpu_set_last_buffer_dequeued(struct vpu_inst *inst)
+int vpu_set_last_buffer_dequeued(struct vpu_inst *inst, bool eos)
{
struct vb2_queue *q;
@@ -116,7 +116,8 @@ int vpu_set_last_buffer_dequeued(struct vpu_inst *inst)
vpu_trace(inst->dev, "last buffer dequeued\n");
q->last_buffer_dequeued = true;
wake_up(&q->done_wq);
- vpu_notify_eos(inst);
+ if (eos)
+ vpu_notify_eos(inst);
return 0;
}
diff --git a/drivers/media/platform/amphion/vpu_v4l2.h b/drivers/media/platform/amphion/vpu_v4l2.h
index ef5de6b66e47..60f43056a7a2 100644
--- a/drivers/media/platform/amphion/vpu_v4l2.h
+++ b/drivers/media/platform/amphion/vpu_v4l2.h
@@ -27,7 +27,7 @@ struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32
void vpu_v4l2_set_error(struct vpu_inst *inst);
int vpu_notify_eos(struct vpu_inst *inst);
int vpu_notify_source_change(struct vpu_inst *inst);
-int vpu_set_last_buffer_dequeued(struct vpu_inst *inst);
+int vpu_set_last_buffer_dequeued(struct vpu_inst *inst, bool eos);
void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state);
int vpu_get_num_buffers(struct vpu_inst *inst, u32 type);
bool vpu_is_source_empty(struct vpu_inst *inst);
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
index 0051f372a66c..4768156181c9 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
@@ -28,6 +28,7 @@
#include "mtk_jpeg_core.h"
#include "mtk_jpeg_dec_parse.h"
+#if defined(CONFIG_OF)
static struct mtk_jpeg_fmt mtk_jpeg_enc_formats[] = {
{
.fourcc = V4L2_PIX_FMT_JPEG,
@@ -101,6 +102,7 @@ static struct mtk_jpeg_fmt mtk_jpeg_dec_formats[] = {
.flags = MTK_JPEG_FMT_FLAG_CAPTURE,
},
};
+#endif
#define MTK_JPEG_ENC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_enc_formats)
#define MTK_JPEG_DEC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_dec_formats)
@@ -936,148 +938,6 @@ static int mtk_jpeg_set_dec_dst(struct mtk_jpeg_ctx *ctx,
return 0;
}
-static int mtk_jpegenc_get_hw(struct mtk_jpeg_ctx *ctx)
-{
- struct mtk_jpegenc_comp_dev *comp_jpeg;
- struct mtk_jpeg_dev *jpeg = ctx->jpeg;
- unsigned long flags;
- int hw_id = -1;
- int i;
-
- spin_lock_irqsave(&jpeg->hw_lock, flags);
- for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) {
- comp_jpeg = jpeg->enc_hw_dev[i];
- if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) {
- hw_id = i;
- comp_jpeg->hw_state = MTK_JPEG_HW_BUSY;
- break;
- }
- }
- spin_unlock_irqrestore(&jpeg->hw_lock, flags);
-
- return hw_id;
-}
-
-static int mtk_jpegenc_set_hw_param(struct mtk_jpeg_ctx *ctx,
- int hw_id,
- struct vb2_v4l2_buffer *src_buf,
- struct vb2_v4l2_buffer *dst_buf)
-{
- struct mtk_jpegenc_comp_dev *jpeg = ctx->jpeg->enc_hw_dev[hw_id];
-
- jpeg->hw_param.curr_ctx = ctx;
- jpeg->hw_param.src_buffer = src_buf;
- jpeg->hw_param.dst_buffer = dst_buf;
-
- return 0;
-}
-
-static int mtk_jpegenc_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&jpeg->hw_lock, flags);
- jpeg->enc_hw_dev[hw_id]->hw_state = MTK_JPEG_HW_IDLE;
- spin_unlock_irqrestore(&jpeg->hw_lock, flags);
-
- return 0;
-}
-
-static void mtk_jpegenc_worker(struct work_struct *work)
-{
- struct mtk_jpegenc_comp_dev *comp_jpeg[MTK_JPEGENC_HW_MAX];
- enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
- struct mtk_jpeg_src_buf *jpeg_dst_buf;
- struct vb2_v4l2_buffer *src_buf, *dst_buf;
- int ret, i, hw_id = 0;
- unsigned long flags;
-
- struct mtk_jpeg_ctx *ctx = container_of(work,
- struct mtk_jpeg_ctx,
- jpeg_work);
- struct mtk_jpeg_dev *jpeg = ctx->jpeg;
-
- for (i = 0; i < MTK_JPEGENC_HW_MAX; i++)
- comp_jpeg[i] = jpeg->enc_hw_dev[i];
- i = 0;
-
-retry_select:
- hw_id = mtk_jpegenc_get_hw(ctx);
- if (hw_id < 0) {
- ret = wait_event_interruptible(jpeg->hw_wq,
- atomic_read(&jpeg->hw_rdy) > 0);
- if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) {
- dev_err(jpeg->dev, "%s : %d, all HW are busy\n",
- __func__, __LINE__);
- v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
- return;
- }
-
- goto retry_select;
- }
-
- atomic_dec(&jpeg->hw_rdy);
- src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
- if (!src_buf)
- goto getbuf_fail;
-
- dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
- if (!dst_buf)
- goto getbuf_fail;
-
- v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true);
-
- mtk_jpegenc_set_hw_param(ctx, hw_id, src_buf, dst_buf);
- ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev);
- if (ret < 0) {
- dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n",
- __func__, __LINE__);
- goto enc_end;
- }
-
- ret = clk_prepare_enable(comp_jpeg[hw_id]->venc_clk.clks->clk);
- if (ret) {
- dev_err(jpeg->dev, "%s : %d, jpegenc clk_prepare_enable fail\n",
- __func__, __LINE__);
- goto enc_end;
- }
-
- v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-
- schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work,
- msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
-
- spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags);
- jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf);
- jpeg_dst_buf->curr_ctx = ctx;
- jpeg_dst_buf->frame_num = ctx->total_frame_num;
- ctx->total_frame_num++;
- mtk_jpeg_enc_reset(comp_jpeg[hw_id]->reg_base);
- mtk_jpeg_set_enc_dst(ctx,
- comp_jpeg[hw_id]->reg_base,
- &dst_buf->vb2_buf);
- mtk_jpeg_set_enc_src(ctx,
- comp_jpeg[hw_id]->reg_base,
- &src_buf->vb2_buf);
- mtk_jpeg_set_enc_params(ctx, comp_jpeg[hw_id]->reg_base);
- mtk_jpeg_enc_start(comp_jpeg[hw_id]->reg_base);
- v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
- spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags);
-
- return;
-
-enc_end:
- v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
- v4l2_m2m_buf_done(src_buf, buf_state);
- v4l2_m2m_buf_done(dst_buf, buf_state);
-getbuf_fail:
- atomic_inc(&jpeg->hw_rdy);
- mtk_jpegenc_put_hw(jpeg, hw_id);
- v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
-}
-
static void mtk_jpeg_enc_device_run(void *priv)
{
struct mtk_jpeg_ctx *ctx = priv;
@@ -1128,173 +988,6 @@ static void mtk_jpeg_multicore_enc_device_run(void *priv)
queue_work(jpeg->workqueue, &ctx->jpeg_work);
}
-static int mtk_jpegdec_get_hw(struct mtk_jpeg_ctx *ctx)
-{
- struct mtk_jpegdec_comp_dev *comp_jpeg;
- struct mtk_jpeg_dev *jpeg = ctx->jpeg;
- unsigned long flags;
- int hw_id = -1;
- int i;
-
- spin_lock_irqsave(&jpeg->hw_lock, flags);
- for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++) {
- comp_jpeg = jpeg->dec_hw_dev[i];
- if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) {
- hw_id = i;
- comp_jpeg->hw_state = MTK_JPEG_HW_BUSY;
- break;
- }
- }
- spin_unlock_irqrestore(&jpeg->hw_lock, flags);
-
- return hw_id;
-}
-
-static int mtk_jpegdec_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&jpeg->hw_lock, flags);
- jpeg->dec_hw_dev[hw_id]->hw_state =
- MTK_JPEG_HW_IDLE;
- spin_unlock_irqrestore(&jpeg->hw_lock, flags);
-
- return 0;
-}
-
-static int mtk_jpegdec_set_hw_param(struct mtk_jpeg_ctx *ctx,
- int hw_id,
- struct vb2_v4l2_buffer *src_buf,
- struct vb2_v4l2_buffer *dst_buf)
-{
- struct mtk_jpegdec_comp_dev *jpeg =
- ctx->jpeg->dec_hw_dev[hw_id];
-
- jpeg->hw_param.curr_ctx = ctx;
- jpeg->hw_param.src_buffer = src_buf;
- jpeg->hw_param.dst_buffer = dst_buf;
-
- return 0;
-}
-
-static void mtk_jpegdec_worker(struct work_struct *work)
-{
- struct mtk_jpeg_ctx *ctx = container_of(work, struct mtk_jpeg_ctx,
- jpeg_work);
- struct mtk_jpegdec_comp_dev *comp_jpeg[MTK_JPEGDEC_HW_MAX];
- enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
- struct mtk_jpeg_src_buf *jpeg_src_buf, *jpeg_dst_buf;
- struct vb2_v4l2_buffer *src_buf, *dst_buf;
- struct mtk_jpeg_dev *jpeg = ctx->jpeg;
- int ret, i, hw_id = 0;
- struct mtk_jpeg_bs bs;
- struct mtk_jpeg_fb fb;
- unsigned long flags;
-
- for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++)
- comp_jpeg[i] = jpeg->dec_hw_dev[i];
- i = 0;
-
-retry_select:
- hw_id = mtk_jpegdec_get_hw(ctx);
- if (hw_id < 0) {
- ret = wait_event_interruptible_timeout(jpeg->hw_wq,
- atomic_read(&jpeg->hw_rdy) > 0,
- MTK_JPEG_HW_TIMEOUT_MSEC);
- if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) {
- dev_err(jpeg->dev, "%s : %d, all HW are busy\n",
- __func__, __LINE__);
- v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
- return;
- }
-
- goto retry_select;
- }
-
- atomic_dec(&jpeg->hw_rdy);
- src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
- if (!src_buf)
- goto getbuf_fail;
-
- dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
- if (!dst_buf)
- goto getbuf_fail;
-
- v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true);
- jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
- jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf);
-
- if (mtk_jpeg_check_resolution_change(ctx,
- &jpeg_src_buf->dec_param)) {
- mtk_jpeg_queue_src_chg_event(ctx);
- ctx->state = MTK_JPEG_SOURCE_CHANGE;
- goto getbuf_fail;
- }
-
- jpeg_src_buf->curr_ctx = ctx;
- jpeg_src_buf->frame_num = ctx->total_frame_num;
- jpeg_dst_buf->curr_ctx = ctx;
- jpeg_dst_buf->frame_num = ctx->total_frame_num;
-
- mtk_jpegdec_set_hw_param(ctx, hw_id, src_buf, dst_buf);
- ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev);
- if (ret < 0) {
- dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n",
- __func__, __LINE__);
- goto dec_end;
- }
-
- ret = clk_prepare_enable(comp_jpeg[hw_id]->jdec_clk.clks->clk);
- if (ret) {
- dev_err(jpeg->dev, "%s : %d, jpegdec clk_prepare_enable fail\n",
- __func__, __LINE__);
- goto clk_end;
- }
-
- v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-
- schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work,
- msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
-
- mtk_jpeg_set_dec_src(ctx, &src_buf->vb2_buf, &bs);
- if (mtk_jpeg_set_dec_dst(ctx,
- &jpeg_src_buf->dec_param,
- &dst_buf->vb2_buf, &fb)) {
- dev_err(jpeg->dev, "%s : %d, mtk_jpeg_set_dec_dst fail\n",
- __func__, __LINE__);
- goto setdst_end;
- }
-
- spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags);
- ctx->total_frame_num++;
- mtk_jpeg_dec_reset(comp_jpeg[hw_id]->reg_base);
- mtk_jpeg_dec_set_config(comp_jpeg[hw_id]->reg_base,
- &jpeg_src_buf->dec_param,
- jpeg_src_buf->bs_size,
- &bs,
- &fb);
- mtk_jpeg_dec_start(comp_jpeg[hw_id]->reg_base);
- v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
- spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags);
-
- return;
-
-setdst_end:
- clk_disable_unprepare(comp_jpeg[hw_id]->jdec_clk.clks->clk);
-clk_end:
- pm_runtime_put(comp_jpeg[hw_id]->dev);
-dec_end:
- v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
- v4l2_m2m_buf_done(src_buf, buf_state);
- v4l2_m2m_buf_done(dst_buf, buf_state);
-getbuf_fail:
- atomic_inc(&jpeg->hw_rdy);
- mtk_jpegdec_put_hw(jpeg, hw_id);
- v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
-}
-
static void mtk_jpeg_multicore_dec_device_run(void *priv)
{
struct mtk_jpeg_ctx *ctx = priv;
@@ -1430,101 +1123,6 @@ static void mtk_jpeg_clk_off(struct mtk_jpeg_dev *jpeg)
jpeg->variant->clks);
}
-static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg)
-{
- struct mtk_jpeg_ctx *ctx;
- struct vb2_v4l2_buffer *src_buf, *dst_buf;
- enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
- u32 result_size;
-
- ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
- if (!ctx) {
- v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n");
- return IRQ_HANDLED;
- }
-
- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-
- result_size = mtk_jpeg_enc_get_file_size(jpeg->reg_base);
- vb2_set_plane_payload(&dst_buf->vb2_buf, 0, result_size);
-
- buf_state = VB2_BUF_STATE_DONE;
-
- v4l2_m2m_buf_done(src_buf, buf_state);
- v4l2_m2m_buf_done(dst_buf, buf_state);
- v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
- pm_runtime_put(ctx->jpeg->dev);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t mtk_jpeg_enc_irq(int irq, void *priv)
-{
- struct mtk_jpeg_dev *jpeg = priv;
- u32 irq_status;
- irqreturn_t ret = IRQ_NONE;
-
- cancel_delayed_work(&jpeg->job_timeout_work);
-
- irq_status = readl(jpeg->reg_base + JPEG_ENC_INT_STS) &
- JPEG_ENC_INT_STATUS_MASK_ALLIRQ;
- if (irq_status)
- writel(0, jpeg->reg_base + JPEG_ENC_INT_STS);
-
- if (!(irq_status & JPEG_ENC_INT_STATUS_DONE))
- return ret;
-
- ret = mtk_jpeg_enc_done(jpeg);
- return ret;
-}
-
-static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv)
-{
- struct mtk_jpeg_dev *jpeg = priv;
- struct mtk_jpeg_ctx *ctx;
- struct vb2_v4l2_buffer *src_buf, *dst_buf;
- struct mtk_jpeg_src_buf *jpeg_src_buf;
- enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
- u32 dec_irq_ret;
- u32 dec_ret;
- int i;
-
- cancel_delayed_work(&jpeg->job_timeout_work);
-
- dec_ret = mtk_jpeg_dec_get_int_status(jpeg->reg_base);
- dec_irq_ret = mtk_jpeg_dec_enum_result(dec_ret);
- ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
- if (!ctx) {
- v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n");
- return IRQ_HANDLED;
- }
-
- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
- jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
-
- if (dec_irq_ret >= MTK_JPEG_DEC_RESULT_UNDERFLOW)
- mtk_jpeg_dec_reset(jpeg->reg_base);
-
- if (dec_irq_ret != MTK_JPEG_DEC_RESULT_EOF_DONE) {
- dev_err(jpeg->dev, "decode failed\n");
- goto dec_end;
- }
-
- for (i = 0; i < dst_buf->vb2_buf.num_planes; i++)
- vb2_set_plane_payload(&dst_buf->vb2_buf, i,
- jpeg_src_buf->dec_param.comp_size[i]);
-
- buf_state = VB2_BUF_STATE_DONE;
-
-dec_end:
- v4l2_m2m_buf_done(src_buf, buf_state);
- v4l2_m2m_buf_done(dst_buf, buf_state);
- v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
- pm_runtime_put(ctx->jpeg->dev);
- return IRQ_HANDLED;
-}
-
static void mtk_jpeg_set_default_params(struct mtk_jpeg_ctx *ctx)
{
struct mtk_jpeg_q_data *q = &ctx->out_q;
@@ -1637,15 +1235,6 @@ static const struct v4l2_file_operations mtk_jpeg_fops = {
.mmap = v4l2_m2m_fop_mmap,
};
-static struct clk_bulk_data mt8173_jpeg_dec_clocks[] = {
- { .id = "jpgdec-smi" },
- { .id = "jpgdec" },
-};
-
-static struct clk_bulk_data mtk_jpeg_clocks[] = {
- { .id = "jpgenc" },
-};
-
static void mtk_jpeg_job_timeout_work(struct work_struct *work)
{
struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev,
@@ -1867,6 +1456,419 @@ static const struct dev_pm_ops mtk_jpeg_pm_ops = {
};
#if defined(CONFIG_OF)
+static int mtk_jpegenc_get_hw(struct mtk_jpeg_ctx *ctx)
+{
+ struct mtk_jpegenc_comp_dev *comp_jpeg;
+ struct mtk_jpeg_dev *jpeg = ctx->jpeg;
+ unsigned long flags;
+ int hw_id = -1;
+ int i;
+
+ spin_lock_irqsave(&jpeg->hw_lock, flags);
+ for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) {
+ comp_jpeg = jpeg->enc_hw_dev[i];
+ if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) {
+ hw_id = i;
+ comp_jpeg->hw_state = MTK_JPEG_HW_BUSY;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&jpeg->hw_lock, flags);
+
+ return hw_id;
+}
+
+static int mtk_jpegenc_set_hw_param(struct mtk_jpeg_ctx *ctx,
+ int hw_id,
+ struct vb2_v4l2_buffer *src_buf,
+ struct vb2_v4l2_buffer *dst_buf)
+{
+ struct mtk_jpegenc_comp_dev *jpeg = ctx->jpeg->enc_hw_dev[hw_id];
+
+ jpeg->hw_param.curr_ctx = ctx;
+ jpeg->hw_param.src_buffer = src_buf;
+ jpeg->hw_param.dst_buffer = dst_buf;
+
+ return 0;
+}
+
+static int mtk_jpegenc_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&jpeg->hw_lock, flags);
+ jpeg->enc_hw_dev[hw_id]->hw_state = MTK_JPEG_HW_IDLE;
+ spin_unlock_irqrestore(&jpeg->hw_lock, flags);
+
+ return 0;
+}
+
+static int mtk_jpegdec_get_hw(struct mtk_jpeg_ctx *ctx)
+{
+ struct mtk_jpegdec_comp_dev *comp_jpeg;
+ struct mtk_jpeg_dev *jpeg = ctx->jpeg;
+ unsigned long flags;
+ int hw_id = -1;
+ int i;
+
+ spin_lock_irqsave(&jpeg->hw_lock, flags);
+ for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++) {
+ comp_jpeg = jpeg->dec_hw_dev[i];
+ if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) {
+ hw_id = i;
+ comp_jpeg->hw_state = MTK_JPEG_HW_BUSY;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&jpeg->hw_lock, flags);
+
+ return hw_id;
+}
+
+static int mtk_jpegdec_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&jpeg->hw_lock, flags);
+ jpeg->dec_hw_dev[hw_id]->hw_state =
+ MTK_JPEG_HW_IDLE;
+ spin_unlock_irqrestore(&jpeg->hw_lock, flags);
+
+ return 0;
+}
+
+static int mtk_jpegdec_set_hw_param(struct mtk_jpeg_ctx *ctx,
+ int hw_id,
+ struct vb2_v4l2_buffer *src_buf,
+ struct vb2_v4l2_buffer *dst_buf)
+{
+ struct mtk_jpegdec_comp_dev *jpeg =
+ ctx->jpeg->dec_hw_dev[hw_id];
+
+ jpeg->hw_param.curr_ctx = ctx;
+ jpeg->hw_param.src_buffer = src_buf;
+ jpeg->hw_param.dst_buffer = dst_buf;
+
+ return 0;
+}
+
+static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg)
+{
+ struct mtk_jpeg_ctx *ctx;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
+ enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
+ u32 result_size;
+
+ ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+ if (!ctx) {
+ v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n");
+ return IRQ_HANDLED;
+ }
+
+ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+ result_size = mtk_jpeg_enc_get_file_size(jpeg->reg_base);
+ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, result_size);
+
+ buf_state = VB2_BUF_STATE_DONE;
+
+ v4l2_m2m_buf_done(src_buf, buf_state);
+ v4l2_m2m_buf_done(dst_buf, buf_state);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+ pm_runtime_put(ctx->jpeg->dev);
+ return IRQ_HANDLED;
+}
+
+static void mtk_jpegenc_worker(struct work_struct *work)
+{
+ struct mtk_jpegenc_comp_dev *comp_jpeg[MTK_JPEGENC_HW_MAX];
+ enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
+ struct mtk_jpeg_src_buf *jpeg_dst_buf;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
+ int ret, i, hw_id = 0;
+ unsigned long flags;
+
+ struct mtk_jpeg_ctx *ctx = container_of(work,
+ struct mtk_jpeg_ctx,
+ jpeg_work);
+ struct mtk_jpeg_dev *jpeg = ctx->jpeg;
+
+ for (i = 0; i < MTK_JPEGENC_HW_MAX; i++)
+ comp_jpeg[i] = jpeg->enc_hw_dev[i];
+ i = 0;
+
+retry_select:
+ hw_id = mtk_jpegenc_get_hw(ctx);
+ if (hw_id < 0) {
+ ret = wait_event_interruptible(jpeg->hw_wq,
+ atomic_read(&jpeg->hw_rdy) > 0);
+ if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) {
+ dev_err(jpeg->dev, "%s : %d, all HW are busy\n",
+ __func__, __LINE__);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+ return;
+ }
+
+ goto retry_select;
+ }
+
+ atomic_dec(&jpeg->hw_rdy);
+ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ if (!src_buf)
+ goto getbuf_fail;
+
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+ if (!dst_buf)
+ goto getbuf_fail;
+
+ v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true);
+
+ mtk_jpegenc_set_hw_param(ctx, hw_id, src_buf, dst_buf);
+ ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev);
+ if (ret < 0) {
+ dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n",
+ __func__, __LINE__);
+ goto enc_end;
+ }
+
+ ret = clk_prepare_enable(comp_jpeg[hw_id]->venc_clk.clks->clk);
+ if (ret) {
+ dev_err(jpeg->dev, "%s : %d, jpegenc clk_prepare_enable fail\n",
+ __func__, __LINE__);
+ goto enc_end;
+ }
+
+ v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+ schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work,
+ msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
+
+ spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags);
+ jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf);
+ jpeg_dst_buf->curr_ctx = ctx;
+ jpeg_dst_buf->frame_num = ctx->total_frame_num;
+ ctx->total_frame_num++;
+ mtk_jpeg_enc_reset(comp_jpeg[hw_id]->reg_base);
+ mtk_jpeg_set_enc_dst(ctx,
+ comp_jpeg[hw_id]->reg_base,
+ &dst_buf->vb2_buf);
+ mtk_jpeg_set_enc_src(ctx,
+ comp_jpeg[hw_id]->reg_base,
+ &src_buf->vb2_buf);
+ mtk_jpeg_set_enc_params(ctx, comp_jpeg[hw_id]->reg_base);
+ mtk_jpeg_enc_start(comp_jpeg[hw_id]->reg_base);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+ spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags);
+
+ return;
+
+enc_end:
+ v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+ v4l2_m2m_buf_done(src_buf, buf_state);
+ v4l2_m2m_buf_done(dst_buf, buf_state);
+getbuf_fail:
+ atomic_inc(&jpeg->hw_rdy);
+ mtk_jpegenc_put_hw(jpeg, hw_id);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+}
+
+static void mtk_jpegdec_worker(struct work_struct *work)
+{
+ struct mtk_jpeg_ctx *ctx = container_of(work, struct mtk_jpeg_ctx,
+ jpeg_work);
+ struct mtk_jpegdec_comp_dev *comp_jpeg[MTK_JPEGDEC_HW_MAX];
+ enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
+ struct mtk_jpeg_src_buf *jpeg_src_buf, *jpeg_dst_buf;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
+ struct mtk_jpeg_dev *jpeg = ctx->jpeg;
+ int ret, i, hw_id = 0;
+ struct mtk_jpeg_bs bs;
+ struct mtk_jpeg_fb fb;
+ unsigned long flags;
+
+ for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++)
+ comp_jpeg[i] = jpeg->dec_hw_dev[i];
+ i = 0;
+
+retry_select:
+ hw_id = mtk_jpegdec_get_hw(ctx);
+ if (hw_id < 0) {
+ ret = wait_event_interruptible_timeout(jpeg->hw_wq,
+ atomic_read(&jpeg->hw_rdy) > 0,
+ MTK_JPEG_HW_TIMEOUT_MSEC);
+ if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) {
+ dev_err(jpeg->dev, "%s : %d, all HW are busy\n",
+ __func__, __LINE__);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+ return;
+ }
+
+ goto retry_select;
+ }
+
+ atomic_dec(&jpeg->hw_rdy);
+ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ if (!src_buf)
+ goto getbuf_fail;
+
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+ if (!dst_buf)
+ goto getbuf_fail;
+
+ v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true);
+ jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
+ jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf);
+
+ if (mtk_jpeg_check_resolution_change(ctx,
+ &jpeg_src_buf->dec_param)) {
+ mtk_jpeg_queue_src_chg_event(ctx);
+ ctx->state = MTK_JPEG_SOURCE_CHANGE;
+ goto getbuf_fail;
+ }
+
+ jpeg_src_buf->curr_ctx = ctx;
+ jpeg_src_buf->frame_num = ctx->total_frame_num;
+ jpeg_dst_buf->curr_ctx = ctx;
+ jpeg_dst_buf->frame_num = ctx->total_frame_num;
+
+ mtk_jpegdec_set_hw_param(ctx, hw_id, src_buf, dst_buf);
+ ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev);
+ if (ret < 0) {
+ dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n",
+ __func__, __LINE__);
+ goto dec_end;
+ }
+
+ ret = clk_prepare_enable(comp_jpeg[hw_id]->jdec_clk.clks->clk);
+ if (ret) {
+ dev_err(jpeg->dev, "%s : %d, jpegdec clk_prepare_enable fail\n",
+ __func__, __LINE__);
+ goto clk_end;
+ }
+
+ v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+ schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work,
+ msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
+
+ mtk_jpeg_set_dec_src(ctx, &src_buf->vb2_buf, &bs);
+ if (mtk_jpeg_set_dec_dst(ctx,
+ &jpeg_src_buf->dec_param,
+ &dst_buf->vb2_buf, &fb)) {
+ dev_err(jpeg->dev, "%s : %d, mtk_jpeg_set_dec_dst fail\n",
+ __func__, __LINE__);
+ goto setdst_end;
+ }
+
+ spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags);
+ ctx->total_frame_num++;
+ mtk_jpeg_dec_reset(comp_jpeg[hw_id]->reg_base);
+ mtk_jpeg_dec_set_config(comp_jpeg[hw_id]->reg_base,
+ &jpeg_src_buf->dec_param,
+ jpeg_src_buf->bs_size,
+ &bs,
+ &fb);
+ mtk_jpeg_dec_start(comp_jpeg[hw_id]->reg_base);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+ spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags);
+
+ return;
+
+setdst_end:
+ clk_disable_unprepare(comp_jpeg[hw_id]->jdec_clk.clks->clk);
+clk_end:
+ pm_runtime_put(comp_jpeg[hw_id]->dev);
+dec_end:
+ v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+ v4l2_m2m_buf_done(src_buf, buf_state);
+ v4l2_m2m_buf_done(dst_buf, buf_state);
+getbuf_fail:
+ atomic_inc(&jpeg->hw_rdy);
+ mtk_jpegdec_put_hw(jpeg, hw_id);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+}
+
+static irqreturn_t mtk_jpeg_enc_irq(int irq, void *priv)
+{
+ struct mtk_jpeg_dev *jpeg = priv;
+ u32 irq_status;
+ irqreturn_t ret = IRQ_NONE;
+
+ cancel_delayed_work(&jpeg->job_timeout_work);
+
+ irq_status = readl(jpeg->reg_base + JPEG_ENC_INT_STS) &
+ JPEG_ENC_INT_STATUS_MASK_ALLIRQ;
+ if (irq_status)
+ writel(0, jpeg->reg_base + JPEG_ENC_INT_STS);
+
+ if (!(irq_status & JPEG_ENC_INT_STATUS_DONE))
+ return ret;
+
+ ret = mtk_jpeg_enc_done(jpeg);
+ return ret;
+}
+
+static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv)
+{
+ struct mtk_jpeg_dev *jpeg = priv;
+ struct mtk_jpeg_ctx *ctx;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
+ struct mtk_jpeg_src_buf *jpeg_src_buf;
+ enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
+ u32 dec_irq_ret;
+ u32 dec_ret;
+ int i;
+
+ cancel_delayed_work(&jpeg->job_timeout_work);
+
+ dec_ret = mtk_jpeg_dec_get_int_status(jpeg->reg_base);
+ dec_irq_ret = mtk_jpeg_dec_enum_result(dec_ret);
+ ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+ if (!ctx) {
+ v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n");
+ return IRQ_HANDLED;
+ }
+
+ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+ jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
+
+ if (dec_irq_ret >= MTK_JPEG_DEC_RESULT_UNDERFLOW)
+ mtk_jpeg_dec_reset(jpeg->reg_base);
+
+ if (dec_irq_ret != MTK_JPEG_DEC_RESULT_EOF_DONE) {
+ dev_err(jpeg->dev, "decode failed\n");
+ goto dec_end;
+ }
+
+ for (i = 0; i < dst_buf->vb2_buf.num_planes; i++)
+ vb2_set_plane_payload(&dst_buf->vb2_buf, i,
+ jpeg_src_buf->dec_param.comp_size[i]);
+
+ buf_state = VB2_BUF_STATE_DONE;
+
+dec_end:
+ v4l2_m2m_buf_done(src_buf, buf_state);
+ v4l2_m2m_buf_done(dst_buf, buf_state);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+ pm_runtime_put(ctx->jpeg->dev);
+ return IRQ_HANDLED;
+}
+
+static struct clk_bulk_data mtk_jpeg_clocks[] = {
+ { .id = "jpgenc" },
+};
+
+static struct clk_bulk_data mt8173_jpeg_dec_clocks[] = {
+ { .id = "jpgdec-smi" },
+ { .id = "jpgdec" },
+};
+
static const struct mtk_jpeg_variant mt8173_jpeg_drvdata = {
.clks = mt8173_jpeg_dec_clocks,
.num_clks = ARRAY_SIZE(mt8173_jpeg_dec_clocks),
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c
index b95c45791c29..bb9cdc9e0e90 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c
@@ -7,15 +7,10 @@
#include <linux/kernel.h>
#include <linux/videodev2.h>
+#include <media/jpeg.h>
#include "mtk_jpeg_dec_parse.h"
-#define TEM 0x01
-#define SOF0 0xc0
-#define RST 0xd0
-#define SOI 0xd8
-#define EOI 0xd9
-
struct mtk_jpeg_stream {
u8 *addr;
u32 size;
@@ -83,7 +78,7 @@ static bool mtk_jpeg_do_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va,
length = 0;
switch (byte) {
- case SOF0:
+ case JPEG_MARKER_SOF0:
/* length */
if (read_word_be(&stream, &word))
break;
@@ -123,10 +118,10 @@ static bool mtk_jpeg_do_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va,
notfound = !(i == param->comp_num);
break;
- case RST ... RST + 7:
- case SOI:
- case EOI:
- case TEM:
+ case JPEG_MARKER_RST ... JPEG_MARKER_RST + 7:
+ case JPEG_MARKER_SOI:
+ case JPEG_MARKER_EOI:
+ case JPEG_MARKER_TEM:
break;
default:
if (read_word_be(&stream, &word))
diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c
index 19a4a085f73a..a605e80c7dc3 100644
--- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c
+++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c
@@ -1035,6 +1035,7 @@ static int mdp_comp_sub_create(struct mdp_dev *mdp)
{
struct device *dev = &mdp->pdev->dev;
struct device_node *node, *parent;
+ int ret = 0;
parent = dev->of_node->parent;
@@ -1060,16 +1061,22 @@ static int mdp_comp_sub_create(struct mdp_dev *mdp)
dev_err(dev,
"Fail to get sub comp. id: type %d alias %d\n",
type, alias_id);
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_free_node;
}
mdp_comp_alias_id[type]++;
comp = mdp_comp_create(mdp, node, id);
- if (IS_ERR(comp))
- return PTR_ERR(comp);
+ if (IS_ERR(comp)) {
+ ret = PTR_ERR(comp);
+ goto err_free_node;
+ }
}
+ return ret;
- return 0;
+err_free_node:
+ of_node_put(node);
+ return ret;
}
void mdp_comp_destroy(struct mdp_dev *mdp)
diff --git a/drivers/media/platform/mediatek/vcodec/Makefile b/drivers/media/platform/mediatek/vcodec/Makefile
index 93e7a343b5b0..5f4c30fec85a 100644
--- a/drivers/media/platform/mediatek/vcodec/Makefile
+++ b/drivers/media/platform/mediatek/vcodec/Makefile
@@ -10,9 +10,11 @@ mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
vdec/vdec_vp8_req_if.o \
vdec/vdec_vp9_if.o \
vdec/vdec_vp9_req_lat_if.o \
+ vdec/vdec_av1_req_lat_if.o \
vdec/vdec_h264_req_if.o \
vdec/vdec_h264_req_common.o \
vdec/vdec_h264_req_multi_if.o \
+ vdec/vdec_hevc_req_multi_if.o \
mtk_vcodec_dec_drv.o \
vdec_drv_if.o \
vdec_vpu_if.o \
@@ -44,3 +46,9 @@ endif
ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_SCP),)
mtk-vcodec-common-y += mtk_vcodec_fw_scp.o
endif
+
+ifneq ($(CONFIG_DEBUG_FS),)
+obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dbgfs.o
+
+mtk-vcodec-dbgfs-y := mtk_vcodec_dbgfs.o
+endif \ No newline at end of file
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c
new file mode 100644
index 000000000000..b5cdbbfcc388
--- /dev/null
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Yunfei Dong <yunfei.dong@mediatek.com>
+ */
+
+#include <linux/debugfs.h>
+
+#include "mtk_vcodec_dbgfs.h"
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_util.h"
+
+static void mtk_vdec_dbgfs_get_format_type(struct mtk_vcodec_ctx *ctx, char *buf,
+ int *used, int total)
+{
+ int curr_len;
+
+ switch (ctx->current_codec) {
+ case V4L2_PIX_FMT_H264_SLICE:
+ curr_len = snprintf(buf + *used, total - *used,
+ "\toutput format: h264 slice\n");
+ break;
+ case V4L2_PIX_FMT_VP8_FRAME:
+ curr_len = snprintf(buf + *used, total - *used,
+ "\toutput format: vp8 slice\n");
+ break;
+ case V4L2_PIX_FMT_VP9_FRAME:
+ curr_len = snprintf(buf + *used, total - *used,
+ "\toutput format: vp9 slice\n");
+ break;
+ default:
+ curr_len = snprintf(buf + *used, total - *used,
+ "\tunsupported output format: 0x%x\n",
+ ctx->current_codec);
+ }
+ *used += curr_len;
+
+ switch (ctx->capture_fourcc) {
+ case V4L2_PIX_FMT_MM21:
+ curr_len = snprintf(buf + *used, total - *used,
+ "\tcapture format: MM21\n");
+ break;
+ case V4L2_PIX_FMT_MT21C:
+ curr_len = snprintf(buf + *used, total - *used,
+ "\tcapture format: MT21C\n");
+ break;
+ default:
+ curr_len = snprintf(buf + *used, total - *used,
+ "\tunsupported capture format: 0x%x\n",
+ ctx->capture_fourcc);
+ }
+ *used += curr_len;
+}
+
+static void mtk_vdec_dbgfs_get_help(char *buf, int *used, int total)
+{
+ int curr_len;
+
+ curr_len = snprintf(buf + *used, total - *used,
+ "help: (1: echo -'info' > vdec 2: cat vdec)\n");
+ *used += curr_len;
+
+ curr_len = snprintf(buf + *used, total - *used,
+ "\t-picinfo: get resolution\n");
+ *used += curr_len;
+
+ curr_len = snprintf(buf + *used, total - *used,
+ "\t-format: get output & capture queue format\n");
+ *used += curr_len;
+}
+
+static ssize_t mtk_vdec_dbgfs_write(struct file *filp, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct mtk_vcodec_dev *vcodec_dev = filp->private_data;
+ struct mtk_vcodec_dbgfs *dbgfs = &vcodec_dev->dbgfs;
+
+ mutex_lock(&dbgfs->dbgfs_lock);
+ dbgfs->buf_size = simple_write_to_buffer(dbgfs->dbgfs_buf, sizeof(dbgfs->dbgfs_buf),
+ ppos, ubuf, count);
+ mutex_unlock(&dbgfs->dbgfs_lock);
+ if (dbgfs->buf_size > 0)
+ return count;
+
+ return dbgfs->buf_size;
+}
+
+static ssize_t mtk_vdec_dbgfs_read(struct file *filp, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct mtk_vcodec_dev *vcodec_dev = filp->private_data;
+ struct mtk_vcodec_dbgfs *dbgfs = &vcodec_dev->dbgfs;
+ struct mtk_vcodec_dbgfs_inst *dbgfs_inst;
+ struct mtk_vcodec_ctx *ctx;
+ int total_len = 200 * (dbgfs->inst_count == 0 ? 1 : dbgfs->inst_count);
+ int used_len = 0, curr_len, ret;
+ bool dbgfs_index[MTK_VDEC_DBGFS_MAX] = {0};
+ char *buf = kmalloc(total_len, GFP_KERNEL);
+
+ if (!buf)
+ return -ENOMEM;
+
+ if (strstr(dbgfs->dbgfs_buf, "-help") || dbgfs->buf_size == 1) {
+ mtk_vdec_dbgfs_get_help(buf, &used_len, total_len);
+ goto read_buffer;
+ }
+
+ if (strstr(dbgfs->dbgfs_buf, "-picinfo"))
+ dbgfs_index[MTK_VDEC_DBGFS_PICINFO] = true;
+
+ if (strstr(dbgfs->dbgfs_buf, "-format"))
+ dbgfs_index[MTK_VDEC_DBGFS_FORMAT] = true;
+
+ mutex_lock(&dbgfs->dbgfs_lock);
+ list_for_each_entry(dbgfs_inst, &dbgfs->dbgfs_head, node) {
+ ctx = dbgfs_inst->vcodec_ctx;
+
+ curr_len = snprintf(buf + used_len, total_len - used_len,
+ "inst[%d]:\n ", ctx->id);
+ used_len += curr_len;
+
+ if (dbgfs_index[MTK_VDEC_DBGFS_PICINFO]) {
+ curr_len = snprintf(buf + used_len, total_len - used_len,
+ "\treal(%dx%d)=>align(%dx%d)\n",
+ ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+ ctx->picinfo.buf_w, ctx->picinfo.buf_h);
+ used_len += curr_len;
+ }
+
+ if (dbgfs_index[MTK_VDEC_DBGFS_FORMAT])
+ mtk_vdec_dbgfs_get_format_type(ctx, buf, &used_len, total_len);
+ }
+ mutex_unlock(&dbgfs->dbgfs_lock);
+read_buffer:
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, used_len);
+ kfree(buf);
+ return ret;
+}
+
+static const struct file_operations vdec_fops = {
+ .open = simple_open,
+ .write = mtk_vdec_dbgfs_write,
+ .read = mtk_vdec_dbgfs_read,
+};
+
+void mtk_vcodec_dbgfs_create(struct mtk_vcodec_ctx *ctx)
+{
+ struct mtk_vcodec_dbgfs_inst *dbgfs_inst;
+ struct mtk_vcodec_dev *vcodec_dev = ctx->dev;
+
+ dbgfs_inst = kzalloc(sizeof(*dbgfs_inst), GFP_KERNEL);
+ if (!dbgfs_inst)
+ return;
+
+ list_add_tail(&dbgfs_inst->node, &vcodec_dev->dbgfs.dbgfs_head);
+
+ vcodec_dev->dbgfs.inst_count++;
+
+ dbgfs_inst->inst_id = ctx->id;
+ dbgfs_inst->vcodec_ctx = ctx;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_create);
+
+void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dev *vcodec_dev, int ctx_id)
+{
+ struct mtk_vcodec_dbgfs_inst *dbgfs_inst;
+
+ list_for_each_entry(dbgfs_inst, &vcodec_dev->dbgfs.dbgfs_head, node) {
+ if (dbgfs_inst->inst_id == ctx_id) {
+ vcodec_dev->dbgfs.inst_count--;
+ break;
+ }
+ }
+
+ if (dbgfs_inst) {
+ list_del(&dbgfs_inst->node);
+ kfree(dbgfs_inst);
+ }
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_remove);
+
+void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev, bool is_encode)
+{
+ struct dentry *vcodec_root;
+
+ if (is_encode)
+ vcodec_dev->dbgfs.vcodec_root = debugfs_create_dir("vcodec-enc", NULL);
+ else
+ vcodec_dev->dbgfs.vcodec_root = debugfs_create_dir("vcodec-dec", NULL);
+ if (IS_ERR(vcodec_dev->dbgfs.vcodec_root))
+ dev_err(&vcodec_dev->plat_dev->dev, "create vcodec dir err:%d\n",
+ IS_ERR(vcodec_dev->dbgfs.vcodec_root));
+
+ vcodec_root = vcodec_dev->dbgfs.vcodec_root;
+ debugfs_create_x32("mtk_v4l2_dbg_level", 0644, vcodec_root, &mtk_v4l2_dbg_level);
+ debugfs_create_x32("mtk_vcodec_dbg", 0644, vcodec_root, &mtk_vcodec_dbg);
+
+ vcodec_dev->dbgfs.inst_count = 0;
+ if (is_encode)
+ return;
+
+ INIT_LIST_HEAD(&vcodec_dev->dbgfs.dbgfs_head);
+ debugfs_create_file("vdec", 0200, vcodec_root, vcodec_dev, &vdec_fops);
+ mutex_init(&vcodec_dev->dbgfs.dbgfs_lock);
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_init);
+
+void mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dev *vcodec_dev)
+{
+ debugfs_remove_recursive(vcodec_dev->dbgfs.vcodec_root);
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_deinit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Mediatek video codec driver");
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h
new file mode 100644
index 000000000000..241ff8197e73
--- /dev/null
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Yunfei Dong <yunfei.dong@mediatek.com>
+ */
+
+#ifndef __MTK_VCODEC_DBGFS_H__
+#define __MTK_VCODEC_DBGFS_H__
+
+struct mtk_vcodec_dev;
+struct mtk_vcodec_ctx;
+
+/*
+ * enum mtk_vdec_dbgfs_log_index - used to get different debug information
+ */
+enum mtk_vdec_dbgfs_log_index {
+ MTK_VDEC_DBGFS_PICINFO,
+ MTK_VDEC_DBGFS_FORMAT,
+ MTK_VDEC_DBGFS_MAX,
+};
+
+/**
+ * struct mtk_vcodec_dbgfs_inst - debugfs information for each inst
+ * @node: list node for each inst
+ * @vcodec_ctx: struct mtk_vcodec_ctx
+ * @inst_id: index of the context that the same with ctx->id
+ */
+struct mtk_vcodec_dbgfs_inst {
+ struct list_head node;
+ struct mtk_vcodec_ctx *vcodec_ctx;
+ int inst_id;
+};
+
+/**
+ * struct mtk_vcodec_dbgfs - dbgfs information
+ * @dbgfs_head: list head used to link each instance
+ * @vcodec_root: vcodec dbgfs entry
+ * @dbgfs_lock: dbgfs lock used to protect dbgfs_buf
+ * @dbgfs_buf: dbgfs buf used to store dbgfs cmd
+ * @buf_size: buffer size of dbgfs
+ * @inst_count: the count of total instance
+ */
+struct mtk_vcodec_dbgfs {
+ struct list_head dbgfs_head;
+ struct dentry *vcodec_root;
+ struct mutex dbgfs_lock;
+ char dbgfs_buf[1024];
+ int buf_size;
+ int inst_count;
+};
+
+#if defined(CONFIG_DEBUG_FS)
+void mtk_vcodec_dbgfs_create(struct mtk_vcodec_ctx *ctx);
+void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dev *vcodec_dev, int ctx_id);
+void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev, bool is_encode);
+void mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dev *vcodec_dev);
+#else
+static inline void mtk_vcodec_dbgfs_create(struct mtk_vcodec_ctx *ctx)
+{
+}
+
+static inline void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dev *vcodec_dev, int ctx_id)
+{
+}
+
+static inline void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev, bool is_encode)
+{
+}
+
+static inline void mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dev *vcodec_dev)
+{
+}
+#endif
+#endif
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c
index 9c652beb3f19..d41f2121b94f 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c
@@ -215,6 +215,7 @@ static int fops_vcodec_open(struct file *file)
ctx->dev->vdec_pdata->init_vdec_params(ctx);
list_add(&ctx->list, &dev->ctx_list);
+ mtk_vcodec_dbgfs_create(ctx);
mutex_unlock(&dev->dev_mutex);
mtk_v4l2_debug(0, "%s decoder [%d]", dev_name(&dev->plat_dev->dev),
@@ -256,6 +257,7 @@ static int fops_vcodec_release(struct file *file)
v4l2_fh_exit(&ctx->fh);
v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+ mtk_vcodec_dbgfs_remove(dev, ctx->id);
list_del_init(&ctx->list);
kfree(ctx);
mutex_unlock(&dev->dev_mutex);
@@ -310,7 +312,6 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
}
if (IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch)) {
- vdec_msg_queue_init_ctx(&dev->msg_queue_core_ctx, MTK_VDEC_CORE);
dev->core_workqueue =
alloc_ordered_workqueue("core-decoder",
WQ_MEM_RECLAIM | WQ_FREEZABLE);
@@ -423,6 +424,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
mtk_v4l2_debug(0, "media registered as /dev/media%d", vfd_dec->minor);
}
+ mtk_vcodec_dbgfs_init(dev, false);
mtk_v4l2_debug(0, "decoder registered as /dev/video%d", vfd_dec->minor);
return 0;
@@ -498,6 +500,7 @@ static void mtk_vcodec_dec_remove(struct platform_device *pdev)
if (dev->vfd_dec)
video_unregister_device(dev->vfd_dec);
+ mtk_vcodec_dbgfs_deinit(dev);
v4l2_device_unregister(&dev->v4l2_dev);
if (!dev->vdec_pdata->is_subdev_supported)
pm_runtime_disable(dev->pm.dev);
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c
index b753bf54ebd9..e1cb2f8dca33 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c
@@ -148,20 +148,21 @@ static int mtk_vdec_hw_probe(struct platform_device *pdev)
ret = mtk_vcodec_init_dec_clk(pdev, &subdev_dev->pm);
if (ret)
return ret;
- pm_runtime_enable(&pdev->dev);
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
of_id = of_match_device(mtk_vdec_hw_match, dev);
if (!of_id) {
dev_err(dev, "Can't get vdec subdev id.\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
hw_idx = (enum mtk_vdec_hw_id)(uintptr_t)of_id->data;
if (hw_idx >= MTK_VDEC_HW_MAX) {
dev_err(dev, "Hardware index %d not correct.\n", hw_idx);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
main_dev->subdev_dev[hw_idx] = subdev_dev;
@@ -173,14 +174,14 @@ static int mtk_vdec_hw_probe(struct platform_device *pdev)
if (IS_SUPPORT_VDEC_HW_IRQ(hw_idx)) {
ret = mtk_vdec_hw_init_irq(subdev_dev);
if (ret)
- goto err;
+ return ret;
}
subdev_dev->reg_base[VDEC_HW_MISC] =
devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR((__force void *)subdev_dev->reg_base[VDEC_HW_MISC])) {
ret = PTR_ERR((__force void *)subdev_dev->reg_base[VDEC_HW_MISC]);
- goto err;
+ return ret;
}
if (!main_dev->subdev_prob_done)
@@ -188,21 +189,10 @@ static int mtk_vdec_hw_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, subdev_dev);
return 0;
-err:
- pm_runtime_disable(subdev_dev->pm.dev);
- return ret;
-}
-
-static int mtk_vdec_hw_remove(struct platform_device *pdev)
-{
- pm_runtime_disable(&pdev->dev);
-
- return 0;
}
static struct platform_driver mtk_vdec_driver = {
.probe = mtk_vdec_hw_probe,
- .remove = mtk_vdec_hw_remove,
.driver = {
.name = "mtk-vdec-comp",
.of_match_table = mtk_vdec_hw_match,
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c
index 3000db975e5f..db1e14a1bd6c 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c
@@ -107,11 +107,103 @@ static const struct mtk_stateless_control mtk_stateless_controls[] = {
},
.codec_type = V4L2_PIX_FMT_VP9_FRAME,
},
+ {
+ .cfg = {
+ .id = V4L2_CID_STATELESS_HEVC_SPS,
+ },
+ .codec_type = V4L2_PIX_FMT_HEVC_SLICE,
+ },
+ {
+ .cfg = {
+ .id = V4L2_CID_STATELESS_HEVC_PPS,
+ },
+ .codec_type = V4L2_PIX_FMT_HEVC_SLICE,
+ },
+ {
+ .cfg = {
+ .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX,
+ },
+ .codec_type = V4L2_PIX_FMT_HEVC_SLICE,
+ },
+ {
+ .cfg = {
+ .id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS,
+ },
+ .codec_type = V4L2_PIX_FMT_HEVC_SLICE,
+ },
+ {
+ .cfg = {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
+ .def = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
+ .menu_skip_mask =
+ BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE),
+ },
+ .codec_type = V4L2_PIX_FMT_HEVC_SLICE,
+ },
+ {
+ .cfg = {
+ .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE,
+ .min = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED,
+ .def = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED,
+ .max = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED,
+ },
+ .codec_type = V4L2_PIX_FMT_HEVC_SLICE,
+ },
+ {
+ .cfg = {
+ .id = V4L2_CID_STATELESS_HEVC_START_CODE,
+ .min = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B,
+ .def = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B,
+ .max = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B,
+ },
+ .codec_type = V4L2_PIX_FMT_HEVC_SLICE,
+ },
+ {
+ .cfg = {
+ .id = V4L2_CID_STATELESS_AV1_SEQUENCE,
+
+ },
+ .codec_type = V4L2_PIX_FMT_AV1_FRAME,
+ },
+ {
+ .cfg = {
+ .id = V4L2_CID_STATELESS_AV1_FRAME,
+
+ },
+ .codec_type = V4L2_PIX_FMT_AV1_FRAME,
+ },
+ {
+ .cfg = {
+ .id = V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY,
+ .dims = { V4L2_AV1_MAX_TILE_COUNT },
+
+ },
+ .codec_type = V4L2_PIX_FMT_AV1_FRAME,
+ },
+ {
+ .cfg = {
+ .id = V4L2_CID_MPEG_VIDEO_AV1_PROFILE,
+ .min = V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN,
+ .def = V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN,
+ .max = V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN,
+ },
+ .codec_type = V4L2_PIX_FMT_AV1_FRAME,
+ },
+ {
+ .cfg = {
+ .id = V4L2_CID_MPEG_VIDEO_AV1_LEVEL,
+ .min = V4L2_MPEG_VIDEO_AV1_LEVEL_2_0,
+ .def = V4L2_MPEG_VIDEO_AV1_LEVEL_4_0,
+ .max = V4L2_MPEG_VIDEO_AV1_LEVEL_5_1,
+ },
+ .codec_type = V4L2_PIX_FMT_AV1_FRAME,
+ },
};
#define NUM_CTRLS ARRAY_SIZE(mtk_stateless_controls)
-static struct mtk_video_fmt mtk_video_formats[5];
+static struct mtk_video_fmt mtk_video_formats[7];
static struct mtk_video_fmt default_out_format;
static struct mtk_video_fmt default_cap_format;
@@ -240,7 +332,7 @@ static void mtk_vdec_worker(struct work_struct *work)
mtk_v4l2_err("vb2 buffer media request is NULL");
ret = vdec_if_decode(ctx, bs_src, NULL, &res_chg);
- if (ret) {
+ if (ret && ret != -EAGAIN) {
mtk_v4l2_err(" <===[%d], src_buf[%d] sz=0x%zx pts=%llu vdec_if_decode() ret=%d res_chg=%d===>",
ctx->id, vb2_src->index, bs_src->size,
vb2_src->timestamp, ret, res_chg);
@@ -356,6 +448,8 @@ static void mtk_vcodec_add_formats(unsigned int fourcc,
case V4L2_PIX_FMT_H264_SLICE:
case V4L2_PIX_FMT_VP8_FRAME:
case V4L2_PIX_FMT_VP9_FRAME:
+ case V4L2_PIX_FMT_HEVC_SLICE:
+ case V4L2_PIX_FMT_AV1_FRAME:
mtk_video_formats[count_formats].fourcc = fourcc;
mtk_video_formats[count_formats].type = MTK_FMT_DEC;
mtk_video_formats[count_formats].num_planes = 1;
@@ -412,6 +506,14 @@ static void mtk_vcodec_get_supported_formats(struct mtk_vcodec_ctx *ctx)
mtk_vcodec_add_formats(V4L2_PIX_FMT_VP9_FRAME, ctx);
out_format_count++;
}
+ if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_HEVC_FRAME) {
+ mtk_vcodec_add_formats(V4L2_PIX_FMT_HEVC_SLICE, ctx);
+ out_format_count++;
+ }
+ if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_AV1_FRAME) {
+ mtk_vcodec_add_formats(V4L2_PIX_FMT_AV1_FRAME, ctx);
+ out_format_count++;
+ }
if (cap_format_count)
default_cap_format = mtk_video_formats[cap_format_count - 1];
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h
index 9acab54fd650..f17d67e781c9 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h
@@ -16,6 +16,7 @@
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-core.h>
+#include "mtk_vcodec_dbgfs.h"
#include "mtk_vcodec_util.h"
#include "vdec_msg_queue.h"
@@ -347,6 +348,8 @@ enum mtk_vdec_format_types {
MTK_VDEC_FORMAT_H264_SLICE = 0x100,
MTK_VDEC_FORMAT_VP8_FRAME = 0x200,
MTK_VDEC_FORMAT_VP9_FRAME = 0x400,
+ MTK_VDEC_FORMAT_AV1_FRAME = 0x800,
+ MTK_VDEC_FORMAT_HEVC_FRAME = 0x1000,
MTK_VCODEC_INNER_RACING = 0x20000,
};
@@ -461,7 +464,6 @@ struct mtk_vcodec_enc_pdata {
* @enc_capability: used to identify encode capability
*
* @core_workqueue: queue used for core hardware decode
- * @msg_queue_core_ctx: msg queue context used for core workqueue
*
* @subdev_dev: subdev hardware device
* @subdev_prob_done: check whether all used hw device is prob done
@@ -470,6 +472,7 @@ struct mtk_vcodec_enc_pdata {
* @dec_active_cnt: used to mark whether need to record register value
* @vdec_racing_info: record register value
* @dec_racing_info_mutex: mutex lock used for inner racing mode
+ * @dbgfs: debug log related information
*/
struct mtk_vcodec_dev {
struct v4l2_device v4l2_dev;
@@ -510,7 +513,6 @@ struct mtk_vcodec_dev {
unsigned int enc_capability;
struct workqueue_struct *core_workqueue;
- struct vdec_msg_queue_ctx msg_queue_core_ctx;
void *subdev_dev[MTK_VDEC_HW_MAX];
int (*subdev_prob_done)(struct mtk_vcodec_dev *vdec_dev);
@@ -520,6 +522,8 @@ struct mtk_vcodec_dev {
u32 vdec_racing_info[132];
/* Protects access to vdec_racing_info data */
struct mutex dec_racing_info_mutex;
+
+ struct mtk_vcodec_dbgfs dbgfs;
};
static inline struct mtk_vcodec_ctx *fh_to_ctx(struct v4l2_fh *fh)
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c
index db65e77bd373..9ff439a50f53 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c
@@ -505,13 +505,13 @@ static int vidioc_venc_s_fmt_out(struct file *file, void *priv,
f->fmt.pix.pixelformat = fmt->fourcc;
}
- q_data->visible_width = f->fmt.pix_mp.width;
- q_data->visible_height = f->fmt.pix_mp.height;
- q_data->fmt = fmt;
- ret = vidioc_try_fmt_out(ctx, f, q_data->fmt);
+ ret = vidioc_try_fmt_out(ctx, f, fmt);
if (ret)
return ret;
+ q_data->fmt = fmt;
+ q_data->visible_width = f->fmt.pix_mp.width;
+ q_data->visible_height = f->fmt.pix_mp.height;
q_data->coded_width = f->fmt.pix_mp.width;
q_data->coded_height = f->fmt.pix_mp.height;
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c
index 168004a08888..5df0a22ff3b5 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c
@@ -358,6 +358,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
goto err_enc_reg;
}
+ mtk_vcodec_dbgfs_init(dev, true);
mtk_v4l2_debug(0, "encoder %d registered as /dev/video%d",
dev->venc_pdata->core_id, vfd_enc->num);
@@ -468,6 +469,7 @@ static void mtk_vcodec_enc_remove(struct platform_device *pdev)
if (dev->vfd_enc)
video_unregister_device(dev->vfd_enc);
+ mtk_vcodec_dbgfs_deinit(dev);
v4l2_device_unregister(&dev->v4l2_dev);
pm_runtime_disable(dev->pm.dev);
mtk_vcodec_fw_release(dev->fw_handler);
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c
index ace78c4b5b9e..f214e6f67005 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c
@@ -13,6 +13,14 @@
#include "mtk_vcodec_drv.h"
#include "mtk_vcodec_util.h"
+#if defined(CONFIG_DEBUG_FS)
+int mtk_vcodec_dbg;
+EXPORT_SYMBOL(mtk_vcodec_dbg);
+
+int mtk_v4l2_dbg_level;
+EXPORT_SYMBOL(mtk_v4l2_dbg_level);
+#endif
+
void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data,
unsigned int reg_idx)
{
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h
index 71956627a0e2..88d389b65f13 100644
--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h
+++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h
@@ -35,15 +35,35 @@ struct mtk_vcodec_dev;
pr_err("[MTK_VCODEC][ERROR][%d]: " fmt "\n", \
((struct mtk_vcodec_ctx *)(h)->ctx)->id, ##args)
+#if defined(CONFIG_DEBUG_FS)
+extern int mtk_v4l2_dbg_level;
+extern int mtk_vcodec_dbg;
-#define mtk_v4l2_debug(level, fmt, args...) pr_debug(fmt, ##args)
+#define mtk_v4l2_debug(level, fmt, args...) \
+ do { \
+ if (mtk_v4l2_dbg_level >= (level)) \
+ pr_debug("[MTK_V4L2] %s, %d: " fmt "\n", \
+ __func__, __LINE__, ##args); \
+ } while (0)
-#define mtk_v4l2_debug_enter() mtk_v4l2_debug(3, "+")
-#define mtk_v4l2_debug_leave() mtk_v4l2_debug(3, "-")
+#define mtk_vcodec_debug(h, fmt, args...) \
+ do { \
+ if (mtk_vcodec_dbg) \
+ dev_dbg(&(((struct mtk_vcodec_ctx *)(h)->ctx)->dev->plat_dev->dev), \
+ "[MTK_VCODEC][%d]: %s, %d " fmt "\n", \
+ ((struct mtk_vcodec_ctx *)(h)->ctx)->id, \
+ __func__, __LINE__, ##args); \
+ } while (0)
+#else
+#define mtk_v4l2_debug(level, fmt, args...) pr_debug(fmt, ##args)
#define mtk_vcodec_debug(h, fmt, args...) \
pr_debug("[MTK_VCODEC][%d]: " fmt "\n", \
((struct mtk_vcodec_ctx *)(h)->ctx)->id, ##args)
+#endif
+
+#define mtk_v4l2_debug_enter() mtk_v4l2_debug(3, "+")
+#define mtk_v4l2_debug_leave() mtk_v4l2_debug(3, "-")
#define mtk_vcodec_debug_enter(h) mtk_vcodec_debug(h, "+")
#define mtk_vcodec_debug_leave(h) mtk_vcodec_debug(h, "-")
diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c
new file mode 100644
index 000000000000..404a1a23fd40
--- /dev/null
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c
@@ -0,0 +1,2207 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Xiaoyong Lu <xiaoyong.lu@mediatek.com>
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "../mtk_vcodec_util.h"
+#include "../mtk_vcodec_dec.h"
+#include "../mtk_vcodec_intr.h"
+#include "../vdec_drv_base.h"
+#include "../vdec_drv_if.h"
+#include "../vdec_vpu_if.h"
+
+#define AV1_MAX_FRAME_BUF_COUNT (V4L2_AV1_TOTAL_REFS_PER_FRAME + 1)
+#define AV1_TILE_BUF_SIZE 64
+#define AV1_SCALE_SUBPEL_BITS 10
+#define AV1_REF_SCALE_SHIFT 14
+#define AV1_REF_NO_SCALE BIT(AV1_REF_SCALE_SHIFT)
+#define AV1_REF_INVALID_SCALE -1
+#define AV1_CDF_TABLE_BUFFER_SIZE 16384
+#define AV1_PRIMARY_REF_NONE 7
+
+#define AV1_INVALID_IDX -1
+
+#define AV1_DIV_ROUND_UP_POW2(value, n) \
+({ \
+ typeof(n) _n = n; \
+ typeof(value) _value = value; \
+ (_value + (BIT(_n) >> 1)) >> _n; \
+})
+
+#define AV1_DIV_ROUND_UP_POW2_SIGNED(value, n) \
+({ \
+ typeof(n) _n_ = n; \
+ typeof(value) _value_ = value; \
+ (((_value_) < 0) ? -AV1_DIV_ROUND_UP_POW2(-(_value_), (_n_)) \
+ : AV1_DIV_ROUND_UP_POW2((_value_), (_n_))); \
+})
+
+#define BIT_FLAG(x, bit) (!!((x)->flags & (bit)))
+#define SEGMENTATION_FLAG(x, name) (!!((x)->flags & V4L2_AV1_SEGMENTATION_FLAG_##name))
+#define QUANT_FLAG(x, name) (!!((x)->flags & V4L2_AV1_QUANTIZATION_FLAG_##name))
+#define SEQUENCE_FLAG(x, name) (!!((x)->flags & V4L2_AV1_SEQUENCE_FLAG_##name))
+#define FH_FLAG(x, name) (!!((x)->flags & V4L2_AV1_FRAME_FLAG_##name))
+
+#define MINQ 0
+#define MAXQ 255
+
+#define DIV_LUT_PREC_BITS 14
+#define DIV_LUT_BITS 8
+#define DIV_LUT_NUM BIT(DIV_LUT_BITS)
+#define WARP_PARAM_REDUCE_BITS 6
+#define WARPEDMODEL_PREC_BITS 16
+
+#define SEG_LVL_ALT_Q 0
+#define SECONDARY_FILTER_STRENGTH_NUM_BITS 2
+
+static const short div_lut[DIV_LUT_NUM + 1] = {
+ 16384, 16320, 16257, 16194, 16132, 16070, 16009, 15948, 15888, 15828, 15768,
+ 15709, 15650, 15592, 15534, 15477, 15420, 15364, 15308, 15252, 15197, 15142,
+ 15087, 15033, 14980, 14926, 14873, 14821, 14769, 14717, 14665, 14614, 14564,
+ 14513, 14463, 14413, 14364, 14315, 14266, 14218, 14170, 14122, 14075, 14028,
+ 13981, 13935, 13888, 13843, 13797, 13752, 13707, 13662, 13618, 13574, 13530,
+ 13487, 13443, 13400, 13358, 13315, 13273, 13231, 13190, 13148, 13107, 13066,
+ 13026, 12985, 12945, 12906, 12866, 12827, 12788, 12749, 12710, 12672, 12633,
+ 12596, 12558, 12520, 12483, 12446, 12409, 12373, 12336, 12300, 12264, 12228,
+ 12193, 12157, 12122, 12087, 12053, 12018, 11984, 11950, 11916, 11882, 11848,
+ 11815, 11782, 11749, 11716, 11683, 11651, 11619, 11586, 11555, 11523, 11491,
+ 11460, 11429, 11398, 11367, 11336, 11305, 11275, 11245, 11215, 11185, 11155,
+ 11125, 11096, 11067, 11038, 11009, 10980, 10951, 10923, 10894, 10866, 10838,
+ 10810, 10782, 10755, 10727, 10700, 10673, 10645, 10618, 10592, 10565, 10538,
+ 10512, 10486, 10460, 10434, 10408, 10382, 10356, 10331, 10305, 10280, 10255,
+ 10230, 10205, 10180, 10156, 10131, 10107, 10082, 10058, 10034, 10010, 9986,
+ 9963, 9939, 9916, 9892, 9869, 9846, 9823, 9800, 9777, 9754, 9732,
+ 9709, 9687, 9664, 9642, 9620, 9598, 9576, 9554, 9533, 9511, 9489,
+ 9468, 9447, 9425, 9404, 9383, 9362, 9341, 9321, 9300, 9279, 9259,
+ 9239, 9218, 9198, 9178, 9158, 9138, 9118, 9098, 9079, 9059, 9039,
+ 9020, 9001, 8981, 8962, 8943, 8924, 8905, 8886, 8867, 8849, 8830,
+ 8812, 8793, 8775, 8756, 8738, 8720, 8702, 8684, 8666, 8648, 8630,
+ 8613, 8595, 8577, 8560, 8542, 8525, 8508, 8490, 8473, 8456, 8439,
+ 8422, 8405, 8389, 8372, 8355, 8339, 8322, 8306, 8289, 8273, 8257,
+ 8240, 8224, 8208, 8192,
+};
+
+/**
+ * struct vdec_av1_slice_init_vsi - VSI used to initialize instance
+ * @architecture: architecture type
+ * @reserved: reserved
+ * @core_vsi: for core vsi
+ * @cdf_table_addr: cdf table addr
+ * @cdf_table_size: cdf table size
+ * @iq_table_addr: iq table addr
+ * @iq_table_size: iq table size
+ * @vsi_size: share vsi structure size
+ */
+struct vdec_av1_slice_init_vsi {
+ u32 architecture;
+ u32 reserved;
+ u64 core_vsi;
+ u64 cdf_table_addr;
+ u32 cdf_table_size;
+ u64 iq_table_addr;
+ u32 iq_table_size;
+ u32 vsi_size;
+};
+
+/**
+ * struct vdec_av1_slice_mem - memory address and size
+ * @buf: dma_addr padding
+ * @dma_addr: buffer address
+ * @size: buffer size
+ * @dma_addr_end: buffer end address
+ * @padding: for padding
+ */
+struct vdec_av1_slice_mem {
+ union {
+ u64 buf;
+ dma_addr_t dma_addr;
+ };
+ union {
+ size_t size;
+ dma_addr_t dma_addr_end;
+ u64 padding;
+ };
+};
+
+/**
+ * struct vdec_av1_slice_state - decoding state
+ * @err : err type for decode
+ * @full : transcoded buffer is full or not
+ * @timeout : decode timeout or not
+ * @perf : performance enable
+ * @crc : hw checksum
+ * @out_size : hw output size
+ */
+struct vdec_av1_slice_state {
+ int err;
+ u32 full;
+ u32 timeout;
+ u32 perf;
+ u32 crc[16];
+ u32 out_size;
+};
+
+/*
+ * enum vdec_av1_slice_resolution_level - resolution level
+ */
+enum vdec_av1_slice_resolution_level {
+ AV1_RES_NONE,
+ AV1_RES_FHD,
+ AV1_RES_4K,
+ AV1_RES_8K,
+};
+
+/*
+ * enum vdec_av1_slice_frame_type - av1 frame type
+ */
+enum vdec_av1_slice_frame_type {
+ AV1_KEY_FRAME = 0,
+ AV1_INTER_FRAME,
+ AV1_INTRA_ONLY_FRAME,
+ AV1_SWITCH_FRAME,
+ AV1_FRAME_TYPES,
+};
+
+/*
+ * enum vdec_av1_slice_reference_mode - reference mode type
+ */
+enum vdec_av1_slice_reference_mode {
+ AV1_SINGLE_REFERENCE = 0,
+ AV1_COMPOUND_REFERENCE,
+ AV1_REFERENCE_MODE_SELECT,
+ AV1_REFERENCE_MODES,
+};
+
+/**
+ * struct vdec_av1_slice_tile_group - info for each tile
+ * @num_tiles: tile number
+ * @tile_size: input size for each tile
+ * @tile_start_offset: tile offset to input buffer
+ */
+struct vdec_av1_slice_tile_group {
+ u32 num_tiles;
+ u32 tile_size[V4L2_AV1_MAX_TILE_COUNT];
+ u32 tile_start_offset[V4L2_AV1_MAX_TILE_COUNT];
+};
+
+/**
+ * struct vdec_av1_slice_scale_factors - scale info for each ref frame
+ * @is_scaled: frame is scaled or not
+ * @x_scale: frame width scale coefficient
+ * @y_scale: frame height scale coefficient
+ * @x_step: width step for x_scale
+ * @y_step: height step for y_scale
+ */
+struct vdec_av1_slice_scale_factors {
+ u8 is_scaled;
+ int x_scale;
+ int y_scale;
+ int x_step;
+ int y_step;
+};
+
+/**
+ * struct vdec_av1_slice_frame_refs - ref frame info
+ * @ref_fb_idx: ref slot index
+ * @ref_map_idx: ref frame index
+ * @scale_factors: scale factors for each ref frame
+ */
+struct vdec_av1_slice_frame_refs {
+ int ref_fb_idx;
+ int ref_map_idx;
+ struct vdec_av1_slice_scale_factors scale_factors;
+};
+
+/**
+ * struct vdec_av1_slice_gm - AV1 Global Motion parameters
+ * @wmtype: The type of global motion transform used
+ * @wmmat: gm_params
+ * @alpha: alpha info
+ * @beta: beta info
+ * @gamma: gamma info
+ * @delta: delta info
+ * @invalid: is invalid or not
+ */
+struct vdec_av1_slice_gm {
+ int wmtype;
+ int wmmat[8];
+ short alpha;
+ short beta;
+ short gamma;
+ short delta;
+ char invalid;
+};
+
+/**
+ * struct vdec_av1_slice_sm - AV1 Skip Mode parameters
+ * @skip_mode_allowed: Skip Mode is allowed or not
+ * @skip_mode_present: specified that the skip_mode will be present or not
+ * @skip_mode_frame: specifies the frames to use for compound prediction
+ */
+struct vdec_av1_slice_sm {
+ u8 skip_mode_allowed;
+ u8 skip_mode_present;
+ int skip_mode_frame[2];
+};
+
+/**
+ * struct vdec_av1_slice_seg - AV1 Segmentation params
+ * @segmentation_enabled: this frame makes use of the segmentation tool or not
+ * @segmentation_update_map: segmentation map are updated during the decoding frame
+ * @segmentation_temporal_update:segmentation map are coded relative the existing segmentaion map
+ * @segmentation_update_data: new parameters are about to be specified for each segment
+ * @feature_data: specifies the feature data for a segment feature
+ * @feature_enabled_mask: the corresponding feature value is coded or not.
+ * @segid_preskip: segment id will be read before the skip syntax element.
+ * @last_active_segid: the highest numbered segment id that has some enabled feature
+ */
+struct vdec_av1_slice_seg {
+ u8 segmentation_enabled;
+ u8 segmentation_update_map;
+ u8 segmentation_temporal_update;
+ u8 segmentation_update_data;
+ int feature_data[V4L2_AV1_MAX_SEGMENTS][V4L2_AV1_SEG_LVL_MAX];
+ u16 feature_enabled_mask[V4L2_AV1_MAX_SEGMENTS];
+ int segid_preskip;
+ int last_active_segid;
+};
+
+/**
+ * struct vdec_av1_slice_delta_q_lf - AV1 Loop Filter delta parameters
+ * @delta_q_present: specified whether quantizer index delta values are present
+ * @delta_q_res: specifies the left shift which should be applied to decoded quantizer index
+ * @delta_lf_present: specifies whether loop filter delta values are present
+ * @delta_lf_res: specifies the left shift which should be applied to decoded
+ * loop filter delta values
+ * @delta_lf_multi: specifies that separate loop filter deltas are sent for horizontal
+ * luma edges,vertical luma edges,the u edges, and the v edges.
+ */
+struct vdec_av1_slice_delta_q_lf {
+ u8 delta_q_present;
+ u8 delta_q_res;
+ u8 delta_lf_present;
+ u8 delta_lf_res;
+ u8 delta_lf_multi;
+};
+
+/**
+ * struct vdec_av1_slice_quantization - AV1 Quantization params
+ * @base_q_idx: indicates the base frame qindex. This is used for Y AC
+ * coefficients and as the base value for the other quantizers.
+ * @qindex: qindex
+ * @delta_qydc: indicates the Y DC quantizer relative to base_q_idx
+ * @delta_qudc: indicates the U DC quantizer relative to base_q_idx.
+ * @delta_quac: indicates the U AC quantizer relative to base_q_idx
+ * @delta_qvdc: indicates the V DC quantizer relative to base_q_idx
+ * @delta_qvac: indicates the V AC quantizer relative to base_q_idx
+ * @using_qmatrix: specifies that the quantizer matrix will be used to
+ * compute quantizers
+ * @qm_y: specifies the level in the quantizer matrix that should
+ * be used for luma plane decoding
+ * @qm_u: specifies the level in the quantizer matrix that should
+ * be used for chroma U plane decoding.
+ * @qm_v: specifies the level in the quantizer matrix that should be
+ * used for chroma V plane decoding
+ */
+struct vdec_av1_slice_quantization {
+ int base_q_idx;
+ int qindex[V4L2_AV1_MAX_SEGMENTS];
+ int delta_qydc;
+ int delta_qudc;
+ int delta_quac;
+ int delta_qvdc;
+ int delta_qvac;
+ u8 using_qmatrix;
+ u8 qm_y;
+ u8 qm_u;
+ u8 qm_v;
+};
+
+/**
+ * struct vdec_av1_slice_lr - AV1 Loop Restauration parameters
+ * @use_lr: whether to use loop restoration
+ * @use_chroma_lr: whether to use chroma loop restoration
+ * @frame_restoration_type: specifies the type of restoration used for each plane
+ * @loop_restoration_size: pecifies the size of loop restoration units in units
+ * of samples in the current plane
+ */
+struct vdec_av1_slice_lr {
+ u8 use_lr;
+ u8 use_chroma_lr;
+ u8 frame_restoration_type[V4L2_AV1_NUM_PLANES_MAX];
+ u32 loop_restoration_size[V4L2_AV1_NUM_PLANES_MAX];
+};
+
+/**
+ * struct vdec_av1_slice_loop_filter - AV1 Loop filter parameters
+ * @loop_filter_level: an array containing loop filter strength values.
+ * @loop_filter_ref_deltas: contains the adjustment needed for the filter
+ * level based on the chosen reference frame
+ * @loop_filter_mode_deltas: contains the adjustment needed for the filter
+ * level based on the chosen mode
+ * @loop_filter_sharpness: indicates the sharpness level. The loop_filter_level
+ * and loop_filter_sharpness together determine when
+ * a block edge is filtered, and by how much the
+ * filtering can change the sample values
+ * @loop_filter_delta_enabled: filetr level depends on the mode and reference
+ * frame used to predict a block
+ */
+struct vdec_av1_slice_loop_filter {
+ u8 loop_filter_level[4];
+ int loop_filter_ref_deltas[V4L2_AV1_TOTAL_REFS_PER_FRAME];
+ int loop_filter_mode_deltas[2];
+ u8 loop_filter_sharpness;
+ u8 loop_filter_delta_enabled;
+};
+
+/**
+ * struct vdec_av1_slice_cdef - AV1 CDEF parameters
+ * @cdef_damping: controls the amount of damping in the deringing filter
+ * @cdef_y_strength: specifies the strength of the primary filter and secondary filter
+ * @cdef_uv_strength: specifies the strength of the primary filter and secondary filter
+ * @cdef_bits: specifies the number of bits needed to specify which
+ * CDEF filter to apply
+ */
+struct vdec_av1_slice_cdef {
+ u8 cdef_damping;
+ u8 cdef_y_strength[8];
+ u8 cdef_uv_strength[8];
+ u8 cdef_bits;
+};
+
+/**
+ * struct vdec_av1_slice_mfmv - AV1 mfmv parameters
+ * @mfmv_valid_ref: mfmv_valid_ref
+ * @mfmv_dir: mfmv_dir
+ * @mfmv_ref_to_cur: mfmv_ref_to_cur
+ * @mfmv_ref_frame_idx: mfmv_ref_frame_idx
+ * @mfmv_count: mfmv_count
+ */
+struct vdec_av1_slice_mfmv {
+ u32 mfmv_valid_ref[3];
+ u32 mfmv_dir[3];
+ int mfmv_ref_to_cur[3];
+ int mfmv_ref_frame_idx[3];
+ int mfmv_count;
+};
+
+/**
+ * struct vdec_av1_slice_tile - AV1 Tile info
+ * @tile_cols: specifies the number of tiles across the frame
+ * @tile_rows: pecifies the number of tiles down the frame
+ * @mi_col_starts: an array specifying the start column
+ * @mi_row_starts: an array specifying the start row
+ * @context_update_tile_id: specifies which tile to use for the CDF update
+ * @uniform_tile_spacing_flag: tiles are uniformly spaced across the frame
+ * or the tile sizes are coded
+ */
+struct vdec_av1_slice_tile {
+ u8 tile_cols;
+ u8 tile_rows;
+ int mi_col_starts[V4L2_AV1_MAX_TILE_COLS + 1];
+ int mi_row_starts[V4L2_AV1_MAX_TILE_ROWS + 1];
+ u8 context_update_tile_id;
+ u8 uniform_tile_spacing_flag;
+};
+
+/**
+ * struct vdec_av1_slice_uncompressed_header - Represents an AV1 Frame Header OBU
+ * @use_ref_frame_mvs: use_ref_frame_mvs flag
+ * @order_hint: specifies OrderHintBits least significant bits of the expected
+ * @gm: global motion param
+ * @upscaled_width: the upscaled width
+ * @frame_width: frame's width
+ * @frame_height: frame's height
+ * @reduced_tx_set: frame is restricted to a reduced subset of the full
+ * set of transform types
+ * @tx_mode: specifies how the transform size is determined
+ * @uniform_tile_spacing_flag: tiles are uniformly spaced across the frame
+ * or the tile sizes are coded
+ * @interpolation_filter: specifies the filter selection used for performing inter prediction
+ * @allow_warped_motion: motion_mode may be present or not
+ * @is_motion_mode_switchable : euqlt to 0 specifies that only the SIMPLE motion mode will be used
+ * @reference_mode : frame reference mode selected
+ * @allow_high_precision_mv: specifies that motion vectors are specified to
+ * quarter pel precision or to eighth pel precision
+ * @allow_intra_bc: ubducates that intra block copy may be used in this frame
+ * @force_integer_mv: specifies motion vectors will always be integers or
+ * can contain fractional bits
+ * @allow_screen_content_tools: intra blocks may use palette encoding
+ * @error_resilient_mode: error resislent mode is enable/disable
+ * @frame_type: specifies the AV1 frame type
+ * @primary_ref_frame: specifies which reference frame contains the CDF values
+ * and other state that should be loaded at the start of the frame
+ * slots will be updated with the current frame after it is decoded
+ * @disable_frame_end_update_cdf:indicates the end of frame CDF update is disable or enable
+ * @disable_cdf_update: specified whether the CDF update in the symbol
+ * decoding process should be disables
+ * @skip_mode: av1 skip mode parameters
+ * @seg: av1 segmentaon parameters
+ * @delta_q_lf: av1 delta loop fileter
+ * @quant: av1 Quantization params
+ * @lr: av1 Loop Restauration parameters
+ * @superres_denom: the denominator for the upscaling ratio
+ * @loop_filter: av1 Loop filter parameters
+ * @cdef: av1 CDEF parameters
+ * @mfmv: av1 mfmv parameters
+ * @tile: av1 Tile info
+ * @frame_is_intra: intra frame
+ * @loss_less_array: loss less array
+ * @coded_loss_less: coded lsss less
+ * @mi_rows: size of mi unit in rows
+ * @mi_cols: size of mi unit in cols
+ */
+struct vdec_av1_slice_uncompressed_header {
+ u8 use_ref_frame_mvs;
+ int order_hint;
+ struct vdec_av1_slice_gm gm[V4L2_AV1_TOTAL_REFS_PER_FRAME];
+ u32 upscaled_width;
+ u32 frame_width;
+ u32 frame_height;
+ u8 reduced_tx_set;
+ u8 tx_mode;
+ u8 uniform_tile_spacing_flag;
+ u8 interpolation_filter;
+ u8 allow_warped_motion;
+ u8 is_motion_mode_switchable;
+ u8 reference_mode;
+ u8 allow_high_precision_mv;
+ u8 allow_intra_bc;
+ u8 force_integer_mv;
+ u8 allow_screen_content_tools;
+ u8 error_resilient_mode;
+ u8 frame_type;
+ u8 primary_ref_frame;
+ u8 disable_frame_end_update_cdf;
+ u32 disable_cdf_update;
+ struct vdec_av1_slice_sm skip_mode;
+ struct vdec_av1_slice_seg seg;
+ struct vdec_av1_slice_delta_q_lf delta_q_lf;
+ struct vdec_av1_slice_quantization quant;
+ struct vdec_av1_slice_lr lr;
+ u32 superres_denom;
+ struct vdec_av1_slice_loop_filter loop_filter;
+ struct vdec_av1_slice_cdef cdef;
+ struct vdec_av1_slice_mfmv mfmv;
+ struct vdec_av1_slice_tile tile;
+ u8 frame_is_intra;
+ u8 loss_less_array[V4L2_AV1_MAX_SEGMENTS];
+ u8 coded_loss_less;
+ u32 mi_rows;
+ u32 mi_cols;
+};
+
+/**
+ * struct vdec_av1_slice_seq_header - Represents an AV1 Sequence OBU
+ * @bitdepth: the bitdepth to use for the sequence
+ * @enable_superres: specifies whether the use_superres syntax element may be present
+ * @enable_filter_intra: specifies the use_filter_intra syntax element may be present
+ * @enable_intra_edge_filter: whether the intra edge filtering process should be enabled
+ * @enable_interintra_compound: specifies the mode info fo rinter blocks may
+ * contain the syntax element interintra
+ * @enable_masked_compound: specifies the mode info fo rinter blocks may
+ * contain the syntax element compound_type
+ * @enable_dual_filter: the inter prediction filter type may be specified independently
+ * @enable_jnt_comp: distance weights process may be used for inter prediction
+ * @mono_chrome: indicates the video does not contain U and V color planes
+ * @enable_order_hint: tools based on the values of order hints may be used
+ * @order_hint_bits: the number of bits used for the order_hint field at each frame
+ * @use_128x128_superblock: indicates superblocks contain 128*128 luma samples
+ * @subsampling_x: the chroma subsamling format
+ * @subsampling_y: the chroma subsamling format
+ * @max_frame_width: the maximum frame width for the frames represented by sequence
+ * @max_frame_height: the maximum frame height for the frames represented by sequence
+ */
+struct vdec_av1_slice_seq_header {
+ u8 bitdepth;
+ u8 enable_superres;
+ u8 enable_filter_intra;
+ u8 enable_intra_edge_filter;
+ u8 enable_interintra_compound;
+ u8 enable_masked_compound;
+ u8 enable_dual_filter;
+ u8 enable_jnt_comp;
+ u8 mono_chrome;
+ u8 enable_order_hint;
+ u8 order_hint_bits;
+ u8 use_128x128_superblock;
+ u8 subsampling_x;
+ u8 subsampling_y;
+ u32 max_frame_width;
+ u32 max_frame_height;
+};
+
+/**
+ * struct vdec_av1_slice_frame - Represents current Frame info
+ * @uh: uncompressed header info
+ * @seq: sequence header info
+ * @large_scale_tile: is large scale mode
+ * @cur_ts: current frame timestamp
+ * @prev_fb_idx: prev slot id
+ * @ref_frame_sign_bias: arrays for ref_frame sign bias
+ * @order_hints: arrays for ref_frame order hint
+ * @ref_frame_valid: arrays for valid ref_frame
+ * @ref_frame_map: map to slot frame info
+ * @frame_refs: ref_frame info
+ */
+struct vdec_av1_slice_frame {
+ struct vdec_av1_slice_uncompressed_header uh;
+ struct vdec_av1_slice_seq_header seq;
+ u8 large_scale_tile;
+ u64 cur_ts;
+ int prev_fb_idx;
+ u8 ref_frame_sign_bias[V4L2_AV1_TOTAL_REFS_PER_FRAME];
+ u32 order_hints[V4L2_AV1_REFS_PER_FRAME];
+ u32 ref_frame_valid[V4L2_AV1_REFS_PER_FRAME];
+ int ref_frame_map[V4L2_AV1_TOTAL_REFS_PER_FRAME];
+ struct vdec_av1_slice_frame_refs frame_refs[V4L2_AV1_REFS_PER_FRAME];
+};
+
+/**
+ * struct vdec_av1_slice_work_buffer - work buffer for lat
+ * @mv_addr: mv buffer memory info
+ * @cdf_addr: cdf buffer memory info
+ * @segid_addr: segid buffer memory info
+ */
+struct vdec_av1_slice_work_buffer {
+ struct vdec_av1_slice_mem mv_addr;
+ struct vdec_av1_slice_mem cdf_addr;
+ struct vdec_av1_slice_mem segid_addr;
+};
+
+/**
+ * struct vdec_av1_slice_frame_info - frame info for each slot
+ * @frame_type: frame type
+ * @frame_is_intra: is intra frame
+ * @order_hint: order hint
+ * @order_hints: referece frame order hint
+ * @upscaled_width: upscale width
+ * @pic_pitch: buffer pitch
+ * @frame_width: frane width
+ * @frame_height: frame height
+ * @mi_rows: rows in mode info
+ * @mi_cols: cols in mode info
+ * @ref_count: mark to reference frame counts
+ */
+struct vdec_av1_slice_frame_info {
+ u8 frame_type;
+ u8 frame_is_intra;
+ int order_hint;
+ u32 order_hints[V4L2_AV1_REFS_PER_FRAME];
+ u32 upscaled_width;
+ u32 pic_pitch;
+ u32 frame_width;
+ u32 frame_height;
+ u32 mi_rows;
+ u32 mi_cols;
+ int ref_count;
+};
+
+/**
+ * struct vdec_av1_slice_slot - slot info that needs to be saved in the global instance
+ * @frame_info: frame info for each slot
+ * @timestamp: time stamp info
+ */
+struct vdec_av1_slice_slot {
+ struct vdec_av1_slice_frame_info frame_info[AV1_MAX_FRAME_BUF_COUNT];
+ u64 timestamp[AV1_MAX_FRAME_BUF_COUNT];
+};
+
+/**
+ * struct vdec_av1_slice_fb - frame buffer for decoding
+ * @y: current y buffer address info
+ * @c: current c buffer address info
+ */
+struct vdec_av1_slice_fb {
+ struct vdec_av1_slice_mem y;
+ struct vdec_av1_slice_mem c;
+};
+
+/**
+ * struct vdec_av1_slice_vsi - exchange frame information between Main CPU and MicroP
+ * @bs: input buffer info
+ * @work_buffer: working buffe for hw
+ * @cdf_table: cdf_table buffer
+ * @cdf_tmp: cdf temp buffer
+ * @rd_mv: mv buffer for lat output , core input
+ * @ube: ube buffer
+ * @trans: transcoded buffer
+ * @err_map: err map buffer
+ * @row_info: row info buffer
+ * @fb: current y/c buffer
+ * @ref: ref y/c buffer
+ * @iq_table: iq table buffer
+ * @tile: tile buffer
+ * @slots: slots info for each frame
+ * @slot_id: current frame slot id
+ * @frame: current frame info
+ * @state: status after decode done
+ * @cur_lst_tile_id: tile id for large scale
+ */
+struct vdec_av1_slice_vsi {
+ /* lat */
+ struct vdec_av1_slice_mem bs;
+ struct vdec_av1_slice_work_buffer work_buffer[AV1_MAX_FRAME_BUF_COUNT];
+ struct vdec_av1_slice_mem cdf_table;
+ struct vdec_av1_slice_mem cdf_tmp;
+ /* LAT stage's output, Core stage's input */
+ struct vdec_av1_slice_mem rd_mv;
+ struct vdec_av1_slice_mem ube;
+ struct vdec_av1_slice_mem trans;
+ struct vdec_av1_slice_mem err_map;
+ struct vdec_av1_slice_mem row_info;
+ /* core */
+ struct vdec_av1_slice_fb fb;
+ struct vdec_av1_slice_fb ref[V4L2_AV1_REFS_PER_FRAME];
+ struct vdec_av1_slice_mem iq_table;
+ /* lat and core share*/
+ struct vdec_av1_slice_mem tile;
+ struct vdec_av1_slice_slot slots;
+ s8 slot_id;
+ struct vdec_av1_slice_frame frame;
+ struct vdec_av1_slice_state state;
+ u32 cur_lst_tile_id;
+};
+
+/**
+ * struct vdec_av1_slice_pfc - per-frame context that contains a local vsi.
+ * pass it from lat to core
+ * @vsi: local vsi. copy to/from remote vsi before/after decoding
+ * @ref_idx: reference buffer timestamp
+ * @seq: picture sequence
+ */
+struct vdec_av1_slice_pfc {
+ struct vdec_av1_slice_vsi vsi;
+ u64 ref_idx[V4L2_AV1_REFS_PER_FRAME];
+ int seq;
+};
+
+/**
+ * struct vdec_av1_slice_instance - represent one av1 instance
+ * @ctx: pointer to codec's context
+ * @vpu: VPU instance
+ * @iq_table: iq table buffer
+ * @cdf_table: cdf table buffer
+ * @mv: mv working buffer
+ * @cdf: cdf working buffer
+ * @seg: segmentation working buffer
+ * @cdf_temp: cdf temp buffer
+ * @tile: tile buffer
+ * @slots: slots info
+ * @tile_group: tile_group entry
+ * @level: level of current resolution
+ * @width: width of last picture
+ * @height: height of last picture
+ * @frame_type: frame_type of last picture
+ * @irq_enabled: irq to Main CPU or MicroP
+ * @inneracing_mode: is inneracing mode
+ * @init_vsi: vsi used for initialized AV1 instance
+ * @vsi: vsi used for decoding/flush ...
+ * @core_vsi: vsi used for Core stage
+ * @seq: global picture sequence
+ */
+struct vdec_av1_slice_instance {
+ struct mtk_vcodec_ctx *ctx;
+ struct vdec_vpu_inst vpu;
+
+ struct mtk_vcodec_mem iq_table;
+ struct mtk_vcodec_mem cdf_table;
+
+ struct mtk_vcodec_mem mv[AV1_MAX_FRAME_BUF_COUNT];
+ struct mtk_vcodec_mem cdf[AV1_MAX_FRAME_BUF_COUNT];
+ struct mtk_vcodec_mem seg[AV1_MAX_FRAME_BUF_COUNT];
+ struct mtk_vcodec_mem cdf_temp;
+ struct mtk_vcodec_mem tile;
+ struct vdec_av1_slice_slot slots;
+ struct vdec_av1_slice_tile_group tile_group;
+
+ /* for resolution change and get_pic_info */
+ enum vdec_av1_slice_resolution_level level;
+ u32 width;
+ u32 height;
+
+ u32 frame_type;
+ u32 irq_enabled;
+ u32 inneracing_mode;
+
+ /* MicroP vsi */
+ union {
+ struct vdec_av1_slice_init_vsi *init_vsi;
+ struct vdec_av1_slice_vsi *vsi;
+ };
+ struct vdec_av1_slice_vsi *core_vsi;
+ int seq;
+};
+
+static int vdec_av1_slice_core_decode(struct vdec_lat_buf *lat_buf);
+
+static inline int vdec_av1_slice_get_msb(u32 n)
+{
+ if (n == 0)
+ return 0;
+ return 31 ^ __builtin_clz(n);
+}
+
+static inline bool vdec_av1_slice_need_scale(u32 ref_width, u32 ref_height,
+ u32 this_width, u32 this_height)
+{
+ return ((this_width << 1) >= ref_width) &&
+ ((this_height << 1) >= ref_height) &&
+ (this_width <= (ref_width << 4)) &&
+ (this_height <= (ref_height << 4));
+}
+
+static void *vdec_av1_get_ctrl_ptr(struct mtk_vcodec_ctx *ctx, int id)
+{
+ struct v4l2_ctrl *ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, id);
+
+ if (!ctrl)
+ return ERR_PTR(-EINVAL);
+
+ return ctrl->p_cur.p;
+}
+
+static int vdec_av1_slice_init_cdf_table(struct vdec_av1_slice_instance *instance)
+{
+ u8 *remote_cdf_table;
+ struct mtk_vcodec_ctx *ctx;
+ struct vdec_av1_slice_init_vsi *vsi;
+ int ret;
+
+ ctx = instance->ctx;
+ vsi = instance->vpu.vsi;
+ remote_cdf_table = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
+ (u32)vsi->cdf_table_addr);
+ if (IS_ERR(remote_cdf_table)) {
+ mtk_vcodec_err(instance, "failed to map cdf table\n");
+ return PTR_ERR(remote_cdf_table);
+ }
+
+ mtk_vcodec_debug(instance, "map cdf table to 0x%p\n",
+ remote_cdf_table);
+
+ if (instance->cdf_table.va)
+ mtk_vcodec_mem_free(ctx, &instance->cdf_table);
+ instance->cdf_table.size = vsi->cdf_table_size;
+
+ ret = mtk_vcodec_mem_alloc(ctx, &instance->cdf_table);
+ if (ret)
+ return ret;
+
+ memcpy(instance->cdf_table.va, remote_cdf_table, vsi->cdf_table_size);
+
+ return 0;
+}
+
+static int vdec_av1_slice_init_iq_table(struct vdec_av1_slice_instance *instance)
+{
+ u8 *remote_iq_table;
+ struct mtk_vcodec_ctx *ctx;
+ struct vdec_av1_slice_init_vsi *vsi;
+ int ret;
+
+ ctx = instance->ctx;
+ vsi = instance->vpu.vsi;
+ remote_iq_table = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
+ (u32)vsi->iq_table_addr);
+ if (IS_ERR(remote_iq_table)) {
+ mtk_vcodec_err(instance, "failed to map iq table\n");
+ return PTR_ERR(remote_iq_table);
+ }
+
+ mtk_vcodec_debug(instance, "map iq table to 0x%p\n", remote_iq_table);
+
+ if (instance->iq_table.va)
+ mtk_vcodec_mem_free(ctx, &instance->iq_table);
+ instance->iq_table.size = vsi->iq_table_size;
+
+ ret = mtk_vcodec_mem_alloc(ctx, &instance->iq_table);
+ if (ret)
+ return ret;
+
+ memcpy(instance->iq_table.va, remote_iq_table, vsi->iq_table_size);
+
+ return 0;
+}
+
+static int vdec_av1_slice_get_new_slot(struct vdec_av1_slice_vsi *vsi)
+{
+ struct vdec_av1_slice_slot *slots = &vsi->slots;
+ int new_slot_idx = AV1_INVALID_IDX;
+ int i;
+
+ for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) {
+ if (slots->frame_info[i].ref_count == 0) {
+ new_slot_idx = i;
+ break;
+ }
+ }
+
+ if (new_slot_idx != AV1_INVALID_IDX) {
+ slots->frame_info[new_slot_idx].ref_count++;
+ slots->timestamp[new_slot_idx] = vsi->frame.cur_ts;
+ }
+
+ return new_slot_idx;
+}
+
+static inline void vdec_av1_slice_clear_fb(struct vdec_av1_slice_frame_info *frame_info)
+{
+ memset((void *)frame_info, 0, sizeof(struct vdec_av1_slice_frame_info));
+}
+
+static void vdec_av1_slice_decrease_ref_count(struct vdec_av1_slice_slot *slots, int fb_idx)
+{
+ struct vdec_av1_slice_frame_info *frame_info = slots->frame_info;
+
+ frame_info[fb_idx].ref_count--;
+ if (frame_info[fb_idx].ref_count < 0) {
+ frame_info[fb_idx].ref_count = 0;
+ mtk_v4l2_err("av1_error: %s() fb_idx %d decrease ref_count error\n",
+ __func__, fb_idx);
+ }
+
+ vdec_av1_slice_clear_fb(&frame_info[fb_idx]);
+}
+
+static void vdec_av1_slice_cleanup_slots(struct vdec_av1_slice_slot *slots,
+ struct vdec_av1_slice_frame *frame,
+ struct v4l2_ctrl_av1_frame *ctrl_fh)
+{
+ int slot_id, ref_id;
+
+ for (ref_id = 0; ref_id < V4L2_AV1_TOTAL_REFS_PER_FRAME; ref_id++)
+ frame->ref_frame_map[ref_id] = AV1_INVALID_IDX;
+
+ for (slot_id = 0; slot_id < AV1_MAX_FRAME_BUF_COUNT; slot_id++) {
+ u64 timestamp = slots->timestamp[slot_id];
+ bool ref_used = false;
+
+ /* ignored unused slots */
+ if (slots->frame_info[slot_id].ref_count == 0)
+ continue;
+
+ for (ref_id = 0; ref_id < V4L2_AV1_TOTAL_REFS_PER_FRAME; ref_id++) {
+ if (ctrl_fh->reference_frame_ts[ref_id] == timestamp) {
+ frame->ref_frame_map[ref_id] = slot_id;
+ ref_used = true;
+ }
+ }
+
+ if (!ref_used)
+ vdec_av1_slice_decrease_ref_count(slots, slot_id);
+ }
+}
+
+static void vdec_av1_slice_setup_slot(struct vdec_av1_slice_instance *instance,
+ struct vdec_av1_slice_vsi *vsi,
+ struct v4l2_ctrl_av1_frame *ctrl_fh)
+{
+ struct vdec_av1_slice_frame_info *cur_frame_info;
+ struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh;
+ int ref_id;
+
+ memcpy(&vsi->slots, &instance->slots, sizeof(instance->slots));
+ vdec_av1_slice_cleanup_slots(&vsi->slots, &vsi->frame, ctrl_fh);
+ vsi->slot_id = vdec_av1_slice_get_new_slot(vsi);
+
+ if (vsi->slot_id == AV1_INVALID_IDX) {
+ mtk_v4l2_err("warning:av1 get invalid index slot\n");
+ vsi->slot_id = 0;
+ }
+ cur_frame_info = &vsi->slots.frame_info[vsi->slot_id];
+ cur_frame_info->frame_type = uh->frame_type;
+ cur_frame_info->frame_is_intra = ((uh->frame_type == AV1_INTRA_ONLY_FRAME) ||
+ (uh->frame_type == AV1_KEY_FRAME));
+ cur_frame_info->order_hint = uh->order_hint;
+ cur_frame_info->upscaled_width = uh->upscaled_width;
+ cur_frame_info->pic_pitch = 0;
+ cur_frame_info->frame_width = uh->frame_width;
+ cur_frame_info->frame_height = uh->frame_height;
+ cur_frame_info->mi_cols = ((uh->frame_width + 7) >> 3) << 1;
+ cur_frame_info->mi_rows = ((uh->frame_height + 7) >> 3) << 1;
+
+ /* ensure current frame is properly mapped if referenced */
+ for (ref_id = 0; ref_id < V4L2_AV1_TOTAL_REFS_PER_FRAME; ref_id++) {
+ u64 timestamp = vsi->slots.timestamp[vsi->slot_id];
+
+ if (ctrl_fh->reference_frame_ts[ref_id] == timestamp)
+ vsi->frame.ref_frame_map[ref_id] = vsi->slot_id;
+ }
+}
+
+static int vdec_av1_slice_alloc_working_buffer(struct vdec_av1_slice_instance *instance,
+ struct vdec_av1_slice_vsi *vsi)
+{
+ struct mtk_vcodec_ctx *ctx = instance->ctx;
+ enum vdec_av1_slice_resolution_level level;
+ u32 max_sb_w, max_sb_h, max_w, max_h, w, h;
+ int i, ret;
+
+ w = vsi->frame.uh.frame_width;
+ h = vsi->frame.uh.frame_height;
+
+ if (w > VCODEC_DEC_4K_CODED_WIDTH || h > VCODEC_DEC_4K_CODED_HEIGHT)
+ /* 8K */
+ return -EINVAL;
+
+ if (w > MTK_VDEC_MAX_W || h > MTK_VDEC_MAX_H) {
+ /* 4K */
+ level = AV1_RES_4K;
+ max_w = VCODEC_DEC_4K_CODED_WIDTH;
+ max_h = VCODEC_DEC_4K_CODED_HEIGHT;
+ } else {
+ /* FHD */
+ level = AV1_RES_FHD;
+ max_w = MTK_VDEC_MAX_W;
+ max_h = MTK_VDEC_MAX_H;
+ }
+
+ if (level == instance->level)
+ return 0;
+
+ mtk_vcodec_debug(instance, "resolution level changed from %u to %u, %ux%u",
+ instance->level, level, w, h);
+
+ max_sb_w = DIV_ROUND_UP(max_w, 128);
+ max_sb_h = DIV_ROUND_UP(max_h, 128);
+
+ for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) {
+ if (instance->mv[i].va)
+ mtk_vcodec_mem_free(ctx, &instance->mv[i]);
+ instance->mv[i].size = max_sb_w * max_sb_h * SZ_1K;
+ ret = mtk_vcodec_mem_alloc(ctx, &instance->mv[i]);
+ if (ret)
+ goto err;
+
+ if (instance->seg[i].va)
+ mtk_vcodec_mem_free(ctx, &instance->seg[i]);
+ instance->seg[i].size = max_sb_w * max_sb_h * 512;
+ ret = mtk_vcodec_mem_alloc(ctx, &instance->seg[i]);
+ if (ret)
+ goto err;
+
+ if (instance->cdf[i].va)
+ mtk_vcodec_mem_free(ctx, &instance->cdf[i]);
+ instance->cdf[i].size = AV1_CDF_TABLE_BUFFER_SIZE;
+ ret = mtk_vcodec_mem_alloc(ctx, &instance->cdf[i]);
+ if (ret)
+ goto err;
+ }
+
+ if (!instance->cdf_temp.va) {
+ instance->cdf_temp.size = (SZ_1K * 16 * 100);
+ ret = mtk_vcodec_mem_alloc(ctx, &instance->cdf_temp);
+ if (ret)
+ goto err;
+ vsi->cdf_tmp.buf = instance->cdf_temp.dma_addr;
+ vsi->cdf_tmp.size = instance->cdf_temp.size;
+ }
+
+ if (instance->tile.va)
+ mtk_vcodec_mem_free(ctx, &instance->tile);
+
+ instance->tile.size = AV1_TILE_BUF_SIZE * V4L2_AV1_MAX_TILE_COUNT;
+ ret = mtk_vcodec_mem_alloc(ctx, &instance->tile);
+ if (ret)
+ goto err;
+
+ instance->level = level;
+ return 0;
+
+err:
+ instance->level = AV1_RES_NONE;
+ return ret;
+}
+
+static void vdec_av1_slice_free_working_buffer(struct vdec_av1_slice_instance *instance)
+{
+ struct mtk_vcodec_ctx *ctx = instance->ctx;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(instance->mv); i++)
+ mtk_vcodec_mem_free(ctx, &instance->mv[i]);
+
+ for (i = 0; i < ARRAY_SIZE(instance->seg); i++)
+ mtk_vcodec_mem_free(ctx, &instance->seg[i]);
+
+ for (i = 0; i < ARRAY_SIZE(instance->cdf); i++)
+ mtk_vcodec_mem_free(ctx, &instance->cdf[i]);
+
+ mtk_vcodec_mem_free(ctx, &instance->tile);
+ mtk_vcodec_mem_free(ctx, &instance->cdf_temp);
+ mtk_vcodec_mem_free(ctx, &instance->cdf_table);
+ mtk_vcodec_mem_free(ctx, &instance->iq_table);
+
+ instance->level = AV1_RES_NONE;
+}
+
+static inline void vdec_av1_slice_vsi_from_remote(struct vdec_av1_slice_vsi *vsi,
+ struct vdec_av1_slice_vsi *remote_vsi)
+{
+ memcpy(&vsi->trans, &remote_vsi->trans, sizeof(vsi->trans));
+ memcpy(&vsi->state, &remote_vsi->state, sizeof(vsi->state));
+}
+
+static inline void vdec_av1_slice_vsi_to_remote(struct vdec_av1_slice_vsi *vsi,
+ struct vdec_av1_slice_vsi *remote_vsi)
+{
+ memcpy(remote_vsi, vsi, sizeof(*vsi));
+}
+
+static int vdec_av1_slice_setup_lat_from_src_buf(struct vdec_av1_slice_instance *instance,
+ struct vdec_av1_slice_vsi *vsi,
+ struct vdec_lat_buf *lat_buf)
+{
+ struct vb2_v4l2_buffer *src;
+ struct vb2_v4l2_buffer *dst;
+
+ src = v4l2_m2m_next_src_buf(instance->ctx->m2m_ctx);
+ if (!src)
+ return -EINVAL;
+
+ lat_buf->src_buf_req = src->vb2_buf.req_obj.req;
+ dst = &lat_buf->ts_info;
+ v4l2_m2m_buf_copy_metadata(src, dst, true);
+ vsi->frame.cur_ts = dst->vb2_buf.timestamp;
+
+ return 0;
+}
+
+static short vdec_av1_slice_resolve_divisor_32(u32 D, short *shift)
+{
+ int f;
+ int e;
+
+ *shift = vdec_av1_slice_get_msb(D);
+ /* e is obtained from D after resetting the most significant 1 bit. */
+ e = D - ((u32)1 << *shift);
+ /* Get the most significant DIV_LUT_BITS (8) bits of e into f */
+ if (*shift > DIV_LUT_BITS)
+ f = AV1_DIV_ROUND_UP_POW2(e, *shift - DIV_LUT_BITS);
+ else
+ f = e << (DIV_LUT_BITS - *shift);
+ if (f > DIV_LUT_NUM)
+ return -1;
+ *shift += DIV_LUT_PREC_BITS;
+ /* Use f as lookup into the precomputed table of multipliers */
+ return div_lut[f];
+}
+
+static void vdec_av1_slice_get_shear_params(struct vdec_av1_slice_gm *gm_params)
+{
+ const int *mat = gm_params->wmmat;
+ short shift;
+ short y;
+ long long gv, dv;
+
+ if (gm_params->wmmat[2] <= 0)
+ return;
+
+ gm_params->alpha = clamp_val(mat[2] - (1 << WARPEDMODEL_PREC_BITS), S16_MIN, S16_MAX);
+ gm_params->beta = clamp_val(mat[3], S16_MIN, S16_MAX);
+
+ y = vdec_av1_slice_resolve_divisor_32(abs(mat[2]), &shift) * (mat[2] < 0 ? -1 : 1);
+
+ gv = ((long long)mat[4] * (1 << WARPEDMODEL_PREC_BITS)) * y;
+ gm_params->gamma = clamp_val((int)AV1_DIV_ROUND_UP_POW2_SIGNED(gv, shift),
+ S16_MIN, S16_MAX);
+
+ dv = ((long long)mat[3] * mat[4]) * y;
+ gm_params->delta = clamp_val(mat[5] - (int)AV1_DIV_ROUND_UP_POW2_SIGNED(dv, shift) -
+ (1 << WARPEDMODEL_PREC_BITS), S16_MIN, S16_MAX);
+
+ gm_params->alpha = AV1_DIV_ROUND_UP_POW2_SIGNED(gm_params->alpha, WARP_PARAM_REDUCE_BITS) *
+ (1 << WARP_PARAM_REDUCE_BITS);
+ gm_params->beta = AV1_DIV_ROUND_UP_POW2_SIGNED(gm_params->beta, WARP_PARAM_REDUCE_BITS) *
+ (1 << WARP_PARAM_REDUCE_BITS);
+ gm_params->gamma = AV1_DIV_ROUND_UP_POW2_SIGNED(gm_params->gamma, WARP_PARAM_REDUCE_BITS) *
+ (1 << WARP_PARAM_REDUCE_BITS);
+ gm_params->delta = AV1_DIV_ROUND_UP_POW2_SIGNED(gm_params->delta, WARP_PARAM_REDUCE_BITS) *
+ (1 << WARP_PARAM_REDUCE_BITS);
+}
+
+static void vdec_av1_slice_setup_gm(struct vdec_av1_slice_gm *gm,
+ struct v4l2_av1_global_motion *ctrl_gm)
+{
+ u32 i, j;
+
+ for (i = 0; i < V4L2_AV1_TOTAL_REFS_PER_FRAME; i++) {
+ gm[i].wmtype = ctrl_gm->type[i];
+ for (j = 0; j < 6; j++)
+ gm[i].wmmat[j] = ctrl_gm->params[i][j];
+
+ gm[i].invalid = !!(ctrl_gm->invalid & BIT(i));
+ gm[i].alpha = 0;
+ gm[i].beta = 0;
+ gm[i].gamma = 0;
+ gm[i].delta = 0;
+ if (gm[i].wmtype <= V4L2_AV1_WARP_MODEL_AFFINE)
+ vdec_av1_slice_get_shear_params(&gm[i]);
+ }
+}
+
+static void vdec_av1_slice_setup_seg(struct vdec_av1_slice_seg *seg,
+ struct v4l2_av1_segmentation *ctrl_seg)
+{
+ u32 i, j;
+
+ seg->segmentation_enabled = SEGMENTATION_FLAG(ctrl_seg, ENABLED);
+ seg->segmentation_update_map = SEGMENTATION_FLAG(ctrl_seg, UPDATE_MAP);
+ seg->segmentation_temporal_update = SEGMENTATION_FLAG(ctrl_seg, TEMPORAL_UPDATE);
+ seg->segmentation_update_data = SEGMENTATION_FLAG(ctrl_seg, UPDATE_DATA);
+ seg->segid_preskip = SEGMENTATION_FLAG(ctrl_seg, SEG_ID_PRE_SKIP);
+ seg->last_active_segid = ctrl_seg->last_active_seg_id;
+
+ for (i = 0; i < V4L2_AV1_MAX_SEGMENTS; i++) {
+ seg->feature_enabled_mask[i] = ctrl_seg->feature_enabled[i];
+ for (j = 0; j < V4L2_AV1_SEG_LVL_MAX; j++)
+ seg->feature_data[i][j] = ctrl_seg->feature_data[i][j];
+ }
+}
+
+static void vdec_av1_slice_setup_quant(struct vdec_av1_slice_quantization *quant,
+ struct v4l2_av1_quantization *ctrl_quant)
+{
+ quant->base_q_idx = ctrl_quant->base_q_idx;
+ quant->delta_qydc = ctrl_quant->delta_q_y_dc;
+ quant->delta_qudc = ctrl_quant->delta_q_u_dc;
+ quant->delta_quac = ctrl_quant->delta_q_u_ac;
+ quant->delta_qvdc = ctrl_quant->delta_q_v_dc;
+ quant->delta_qvac = ctrl_quant->delta_q_v_ac;
+ quant->qm_y = ctrl_quant->qm_y;
+ quant->qm_u = ctrl_quant->qm_u;
+ quant->qm_v = ctrl_quant->qm_v;
+ quant->using_qmatrix = QUANT_FLAG(ctrl_quant, USING_QMATRIX);
+}
+
+static int vdec_av1_slice_get_qindex(struct vdec_av1_slice_uncompressed_header *uh,
+ int segmentation_id)
+{
+ struct vdec_av1_slice_seg *seg = &uh->seg;
+ struct vdec_av1_slice_quantization *quant = &uh->quant;
+ int data = 0, qindex = 0;
+
+ if (seg->segmentation_enabled &&
+ (seg->feature_enabled_mask[segmentation_id] & BIT(SEG_LVL_ALT_Q))) {
+ data = seg->feature_data[segmentation_id][SEG_LVL_ALT_Q];
+ qindex = quant->base_q_idx + data;
+ return clamp_val(qindex, 0, MAXQ);
+ }
+
+ return quant->base_q_idx;
+}
+
+static void vdec_av1_slice_setup_lr(struct vdec_av1_slice_lr *lr,
+ struct v4l2_av1_loop_restoration *ctrl_lr)
+{
+ int i;
+
+ lr->use_lr = 0;
+ lr->use_chroma_lr = 0;
+ for (i = 0; i < V4L2_AV1_NUM_PLANES_MAX; i++) {
+ lr->frame_restoration_type[i] = ctrl_lr->frame_restoration_type[i];
+ lr->loop_restoration_size[i] = ctrl_lr->loop_restoration_size[i];
+ if (lr->frame_restoration_type[i]) {
+ lr->use_lr = 1;
+ if (i > 0)
+ lr->use_chroma_lr = 1;
+ }
+ }
+}
+
+static void vdec_av1_slice_setup_lf(struct vdec_av1_slice_loop_filter *lf,
+ struct v4l2_av1_loop_filter *ctrl_lf)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(lf->loop_filter_level); i++)
+ lf->loop_filter_level[i] = ctrl_lf->level[i];
+
+ for (i = 0; i < V4L2_AV1_TOTAL_REFS_PER_FRAME; i++)
+ lf->loop_filter_ref_deltas[i] = ctrl_lf->ref_deltas[i];
+
+ for (i = 0; i < ARRAY_SIZE(lf->loop_filter_mode_deltas); i++)
+ lf->loop_filter_mode_deltas[i] = ctrl_lf->mode_deltas[i];
+
+ lf->loop_filter_sharpness = ctrl_lf->sharpness;
+ lf->loop_filter_delta_enabled =
+ BIT_FLAG(ctrl_lf, V4L2_AV1_LOOP_FILTER_FLAG_DELTA_ENABLED);
+}
+
+static void vdec_av1_slice_setup_cdef(struct vdec_av1_slice_cdef *cdef,
+ struct v4l2_av1_cdef *ctrl_cdef)
+{
+ int i;
+
+ cdef->cdef_damping = ctrl_cdef->damping_minus_3 + 3;
+ cdef->cdef_bits = ctrl_cdef->bits;
+
+ for (i = 0; i < V4L2_AV1_CDEF_MAX; i++) {
+ if (ctrl_cdef->y_sec_strength[i] == 4)
+ ctrl_cdef->y_sec_strength[i] -= 1;
+
+ if (ctrl_cdef->uv_sec_strength[i] == 4)
+ ctrl_cdef->uv_sec_strength[i] -= 1;
+
+ cdef->cdef_y_strength[i] =
+ ctrl_cdef->y_pri_strength[i] << SECONDARY_FILTER_STRENGTH_NUM_BITS |
+ ctrl_cdef->y_sec_strength[i];
+ cdef->cdef_uv_strength[i] =
+ ctrl_cdef->uv_pri_strength[i] << SECONDARY_FILTER_STRENGTH_NUM_BITS |
+ ctrl_cdef->uv_sec_strength[i];
+ }
+}
+
+static void vdec_av1_slice_setup_seq(struct vdec_av1_slice_seq_header *seq,
+ struct v4l2_ctrl_av1_sequence *ctrl_seq)
+{
+ seq->bitdepth = ctrl_seq->bit_depth;
+ seq->max_frame_width = ctrl_seq->max_frame_width_minus_1 + 1;
+ seq->max_frame_height = ctrl_seq->max_frame_height_minus_1 + 1;
+ seq->enable_superres = SEQUENCE_FLAG(ctrl_seq, ENABLE_SUPERRES);
+ seq->enable_filter_intra = SEQUENCE_FLAG(ctrl_seq, ENABLE_FILTER_INTRA);
+ seq->enable_intra_edge_filter = SEQUENCE_FLAG(ctrl_seq, ENABLE_INTRA_EDGE_FILTER);
+ seq->enable_interintra_compound = SEQUENCE_FLAG(ctrl_seq, ENABLE_INTERINTRA_COMPOUND);
+ seq->enable_masked_compound = SEQUENCE_FLAG(ctrl_seq, ENABLE_MASKED_COMPOUND);
+ seq->enable_dual_filter = SEQUENCE_FLAG(ctrl_seq, ENABLE_DUAL_FILTER);
+ seq->enable_jnt_comp = SEQUENCE_FLAG(ctrl_seq, ENABLE_JNT_COMP);
+ seq->mono_chrome = SEQUENCE_FLAG(ctrl_seq, MONO_CHROME);
+ seq->enable_order_hint = SEQUENCE_FLAG(ctrl_seq, ENABLE_ORDER_HINT);
+ seq->order_hint_bits = ctrl_seq->order_hint_bits;
+ seq->use_128x128_superblock = SEQUENCE_FLAG(ctrl_seq, USE_128X128_SUPERBLOCK);
+ seq->subsampling_x = SEQUENCE_FLAG(ctrl_seq, SUBSAMPLING_X);
+ seq->subsampling_y = SEQUENCE_FLAG(ctrl_seq, SUBSAMPLING_Y);
+}
+
+static void vdec_av1_slice_setup_tile(struct vdec_av1_slice_frame *frame,
+ struct v4l2_av1_tile_info *ctrl_tile)
+{
+ struct vdec_av1_slice_seq_header *seq = &frame->seq;
+ struct vdec_av1_slice_tile *tile = &frame->uh.tile;
+ u32 mib_size_log2 = seq->use_128x128_superblock ? 5 : 4;
+ int i;
+
+ tile->tile_cols = ctrl_tile->tile_cols;
+ tile->tile_rows = ctrl_tile->tile_rows;
+ tile->context_update_tile_id = ctrl_tile->context_update_tile_id;
+ tile->uniform_tile_spacing_flag =
+ BIT_FLAG(ctrl_tile, V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING);
+
+ for (i = 0; i < tile->tile_cols + 1; i++)
+ tile->mi_col_starts[i] =
+ ALIGN(ctrl_tile->mi_col_starts[i], BIT(mib_size_log2)) >> mib_size_log2;
+
+ for (i = 0; i < tile->tile_rows + 1; i++)
+ tile->mi_row_starts[i] =
+ ALIGN(ctrl_tile->mi_row_starts[i], BIT(mib_size_log2)) >> mib_size_log2;
+}
+
+static void vdec_av1_slice_setup_uh(struct vdec_av1_slice_instance *instance,
+ struct vdec_av1_slice_frame *frame,
+ struct v4l2_ctrl_av1_frame *ctrl_fh)
+{
+ struct vdec_av1_slice_uncompressed_header *uh = &frame->uh;
+ int i;
+
+ uh->use_ref_frame_mvs = FH_FLAG(ctrl_fh, USE_REF_FRAME_MVS);
+ uh->order_hint = ctrl_fh->order_hint;
+ vdec_av1_slice_setup_gm(uh->gm, &ctrl_fh->global_motion);
+ uh->upscaled_width = ctrl_fh->upscaled_width;
+ uh->frame_width = ctrl_fh->frame_width_minus_1 + 1;
+ uh->frame_height = ctrl_fh->frame_height_minus_1 + 1;
+ uh->mi_cols = ((uh->frame_width + 7) >> 3) << 1;
+ uh->mi_rows = ((uh->frame_height + 7) >> 3) << 1;
+ uh->reduced_tx_set = FH_FLAG(ctrl_fh, REDUCED_TX_SET);
+ uh->tx_mode = ctrl_fh->tx_mode;
+ uh->uniform_tile_spacing_flag =
+ BIT_FLAG(&ctrl_fh->tile_info, V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING);
+ uh->interpolation_filter = ctrl_fh->interpolation_filter;
+ uh->allow_warped_motion = FH_FLAG(ctrl_fh, ALLOW_WARPED_MOTION);
+ uh->is_motion_mode_switchable = FH_FLAG(ctrl_fh, IS_MOTION_MODE_SWITCHABLE);
+ uh->frame_type = ctrl_fh->frame_type;
+ uh->frame_is_intra = (uh->frame_type == V4L2_AV1_INTRA_ONLY_FRAME ||
+ uh->frame_type == V4L2_AV1_KEY_FRAME);
+
+ if (!uh->frame_is_intra && FH_FLAG(ctrl_fh, REFERENCE_SELECT))
+ uh->reference_mode = AV1_REFERENCE_MODE_SELECT;
+ else
+ uh->reference_mode = AV1_SINGLE_REFERENCE;
+
+ uh->allow_high_precision_mv = FH_FLAG(ctrl_fh, ALLOW_HIGH_PRECISION_MV);
+ uh->allow_intra_bc = FH_FLAG(ctrl_fh, ALLOW_INTRABC);
+ uh->force_integer_mv = FH_FLAG(ctrl_fh, FORCE_INTEGER_MV);
+ uh->allow_screen_content_tools = FH_FLAG(ctrl_fh, ALLOW_SCREEN_CONTENT_TOOLS);
+ uh->error_resilient_mode = FH_FLAG(ctrl_fh, ERROR_RESILIENT_MODE);
+ uh->primary_ref_frame = ctrl_fh->primary_ref_frame;
+ uh->disable_frame_end_update_cdf =
+ FH_FLAG(ctrl_fh, DISABLE_FRAME_END_UPDATE_CDF);
+ uh->disable_cdf_update = FH_FLAG(ctrl_fh, DISABLE_CDF_UPDATE);
+ uh->skip_mode.skip_mode_present = FH_FLAG(ctrl_fh, SKIP_MODE_PRESENT);
+ uh->skip_mode.skip_mode_frame[0] =
+ ctrl_fh->skip_mode_frame[0] - V4L2_AV1_REF_LAST_FRAME;
+ uh->skip_mode.skip_mode_frame[1] =
+ ctrl_fh->skip_mode_frame[1] - V4L2_AV1_REF_LAST_FRAME;
+ uh->skip_mode.skip_mode_allowed = ctrl_fh->skip_mode_frame[0] ? 1 : 0;
+
+ vdec_av1_slice_setup_seg(&uh->seg, &ctrl_fh->segmentation);
+ uh->delta_q_lf.delta_q_present = QUANT_FLAG(&ctrl_fh->quantization, DELTA_Q_PRESENT);
+ uh->delta_q_lf.delta_q_res = 1 << ctrl_fh->quantization.delta_q_res;
+ uh->delta_q_lf.delta_lf_present =
+ BIT_FLAG(&ctrl_fh->loop_filter, V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_PRESENT);
+ uh->delta_q_lf.delta_lf_res = ctrl_fh->loop_filter.delta_lf_res;
+ uh->delta_q_lf.delta_lf_multi =
+ BIT_FLAG(&ctrl_fh->loop_filter, V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_MULTI);
+ vdec_av1_slice_setup_quant(&uh->quant, &ctrl_fh->quantization);
+
+ uh->coded_loss_less = 1;
+ for (i = 0; i < V4L2_AV1_MAX_SEGMENTS; i++) {
+ uh->quant.qindex[i] = vdec_av1_slice_get_qindex(uh, i);
+ uh->loss_less_array[i] =
+ (uh->quant.qindex[i] == 0 && uh->quant.delta_qydc == 0 &&
+ uh->quant.delta_quac == 0 && uh->quant.delta_qudc == 0 &&
+ uh->quant.delta_qvac == 0 && uh->quant.delta_qvdc == 0);
+
+ if (!uh->loss_less_array[i])
+ uh->coded_loss_less = 0;
+ }
+
+ vdec_av1_slice_setup_lr(&uh->lr, &ctrl_fh->loop_restoration);
+ uh->superres_denom = ctrl_fh->superres_denom;
+ vdec_av1_slice_setup_lf(&uh->loop_filter, &ctrl_fh->loop_filter);
+ vdec_av1_slice_setup_cdef(&uh->cdef, &ctrl_fh->cdef);
+ vdec_av1_slice_setup_tile(frame, &ctrl_fh->tile_info);
+}
+
+static int vdec_av1_slice_setup_tile_group(struct vdec_av1_slice_instance *instance,
+ struct vdec_av1_slice_vsi *vsi)
+{
+ struct v4l2_ctrl_av1_tile_group_entry *ctrl_tge;
+ struct vdec_av1_slice_tile_group *tile_group = &instance->tile_group;
+ struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh;
+ struct vdec_av1_slice_tile *tile = &uh->tile;
+ struct v4l2_ctrl *ctrl;
+ u32 tge_size;
+ int i;
+
+ ctrl = v4l2_ctrl_find(&instance->ctx->ctrl_hdl, V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY);
+ if (!ctrl)
+ return -EINVAL;
+
+ tge_size = ctrl->elems;
+ ctrl_tge = (struct v4l2_ctrl_av1_tile_group_entry *)ctrl->p_cur.p;
+
+ tile_group->num_tiles = tile->tile_cols * tile->tile_rows;
+
+ if (tile_group->num_tiles != tge_size ||
+ tile_group->num_tiles > V4L2_AV1_MAX_TILE_COUNT) {
+ mtk_vcodec_err(instance, "invalid tge_size %d, tile_num:%d\n",
+ tge_size, tile_group->num_tiles);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < tge_size; i++) {
+ if (i != ctrl_tge[i].tile_row * vsi->frame.uh.tile.tile_cols +
+ ctrl_tge[i].tile_col) {
+ mtk_vcodec_err(instance, "invalid tge info %d, %d %d %d\n",
+ i, ctrl_tge[i].tile_row, ctrl_tge[i].tile_col,
+ vsi->frame.uh.tile.tile_rows);
+ return -EINVAL;
+ }
+ tile_group->tile_size[i] = ctrl_tge[i].tile_size;
+ tile_group->tile_start_offset[i] = ctrl_tge[i].tile_offset;
+ }
+
+ return 0;
+}
+
+static inline void vdec_av1_slice_setup_state(struct vdec_av1_slice_vsi *vsi)
+{
+ memset(&vsi->state, 0, sizeof(vsi->state));
+}
+
+static void vdec_av1_slice_setup_scale_factors(struct vdec_av1_slice_frame_refs *frame_ref,
+ struct vdec_av1_slice_frame_info *ref_frame_info,
+ struct vdec_av1_slice_uncompressed_header *uh)
+{
+ struct vdec_av1_slice_scale_factors *scale_factors = &frame_ref->scale_factors;
+ u32 ref_upscaled_width = ref_frame_info->upscaled_width;
+ u32 ref_frame_height = ref_frame_info->frame_height;
+ u32 frame_width = uh->frame_width;
+ u32 frame_height = uh->frame_height;
+
+ if (!vdec_av1_slice_need_scale(ref_upscaled_width, ref_frame_height,
+ frame_width, frame_height)) {
+ scale_factors->x_scale = -1;
+ scale_factors->y_scale = -1;
+ scale_factors->is_scaled = 0;
+ return;
+ }
+
+ scale_factors->x_scale =
+ ((ref_upscaled_width << AV1_REF_SCALE_SHIFT) + (frame_width >> 1)) / frame_width;
+ scale_factors->y_scale =
+ ((ref_frame_height << AV1_REF_SCALE_SHIFT) + (frame_height >> 1)) / frame_height;
+ scale_factors->is_scaled =
+ (scale_factors->x_scale != AV1_REF_INVALID_SCALE) &&
+ (scale_factors->y_scale != AV1_REF_INVALID_SCALE) &&
+ (scale_factors->x_scale != AV1_REF_NO_SCALE ||
+ scale_factors->y_scale != AV1_REF_NO_SCALE);
+ scale_factors->x_step =
+ AV1_DIV_ROUND_UP_POW2(scale_factors->x_scale,
+ AV1_REF_SCALE_SHIFT - AV1_SCALE_SUBPEL_BITS);
+ scale_factors->y_step =
+ AV1_DIV_ROUND_UP_POW2(scale_factors->y_scale,
+ AV1_REF_SCALE_SHIFT - AV1_SCALE_SUBPEL_BITS);
+}
+
+static unsigned char vdec_av1_slice_get_sign_bias(int a,
+ int b,
+ u8 enable_order_hint,
+ u8 order_hint_bits)
+{
+ int diff = 0;
+ int m = 0;
+ unsigned char result = 0;
+
+ if (!enable_order_hint)
+ return 0;
+
+ diff = a - b;
+ m = 1 << (order_hint_bits - 1);
+ diff = (diff & (m - 1)) - (diff & m);
+
+ if (diff > 0)
+ result = 1;
+
+ return result;
+}
+
+static void vdec_av1_slice_setup_ref(struct vdec_av1_slice_pfc *pfc,
+ struct v4l2_ctrl_av1_frame *ctrl_fh)
+{
+ struct vdec_av1_slice_vsi *vsi = &pfc->vsi;
+ struct vdec_av1_slice_frame *frame = &vsi->frame;
+ struct vdec_av1_slice_slot *slots = &vsi->slots;
+ struct vdec_av1_slice_uncompressed_header *uh = &frame->uh;
+ struct vdec_av1_slice_seq_header *seq = &frame->seq;
+ struct vdec_av1_slice_frame_info *cur_frame_info =
+ &slots->frame_info[vsi->slot_id];
+ struct vdec_av1_slice_frame_info *frame_info;
+ int i, slot_id;
+
+ if (uh->frame_is_intra)
+ return;
+
+ for (i = 0; i < V4L2_AV1_REFS_PER_FRAME; i++) {
+ int ref_idx = ctrl_fh->ref_frame_idx[i];
+
+ pfc->ref_idx[i] = ctrl_fh->reference_frame_ts[ref_idx];
+ slot_id = frame->ref_frame_map[ref_idx];
+ frame_info = &slots->frame_info[slot_id];
+ if (slot_id == AV1_INVALID_IDX) {
+ mtk_v4l2_err("cannot match reference[%d] 0x%llx\n", i,
+ ctrl_fh->reference_frame_ts[ref_idx]);
+ frame->order_hints[i] = 0;
+ frame->ref_frame_valid[i] = 0;
+ continue;
+ }
+
+ frame->frame_refs[i].ref_fb_idx = slot_id;
+ vdec_av1_slice_setup_scale_factors(&frame->frame_refs[i],
+ frame_info, uh);
+ if (!seq->enable_order_hint)
+ frame->ref_frame_sign_bias[i + 1] = 0;
+ else
+ frame->ref_frame_sign_bias[i + 1] =
+ vdec_av1_slice_get_sign_bias(frame_info->order_hint,
+ uh->order_hint,
+ seq->enable_order_hint,
+ seq->order_hint_bits);
+
+ frame->order_hints[i] = ctrl_fh->order_hints[i + 1];
+ cur_frame_info->order_hints[i] = frame->order_hints[i];
+ frame->ref_frame_valid[i] = 1;
+ }
+}
+
+static void vdec_av1_slice_get_previous(struct vdec_av1_slice_vsi *vsi)
+{
+ struct vdec_av1_slice_frame *frame = &vsi->frame;
+
+ if (frame->uh.primary_ref_frame == AV1_PRIMARY_REF_NONE)
+ frame->prev_fb_idx = AV1_INVALID_IDX;
+ else
+ frame->prev_fb_idx = frame->frame_refs[frame->uh.primary_ref_frame].ref_fb_idx;
+}
+
+static inline void vdec_av1_slice_setup_operating_mode(struct vdec_av1_slice_instance *instance,
+ struct vdec_av1_slice_frame *frame)
+{
+ frame->large_scale_tile = 0;
+}
+
+static int vdec_av1_slice_setup_pfc(struct vdec_av1_slice_instance *instance,
+ struct vdec_av1_slice_pfc *pfc)
+{
+ struct v4l2_ctrl_av1_frame *ctrl_fh;
+ struct v4l2_ctrl_av1_sequence *ctrl_seq;
+ struct vdec_av1_slice_vsi *vsi = &pfc->vsi;
+ int ret = 0;
+
+ /* frame header */
+ ctrl_fh = (struct v4l2_ctrl_av1_frame *)
+ vdec_av1_get_ctrl_ptr(instance->ctx,
+ V4L2_CID_STATELESS_AV1_FRAME);
+ if (IS_ERR(ctrl_fh))
+ return PTR_ERR(ctrl_fh);
+
+ ctrl_seq = (struct v4l2_ctrl_av1_sequence *)
+ vdec_av1_get_ctrl_ptr(instance->ctx,
+ V4L2_CID_STATELESS_AV1_SEQUENCE);
+ if (IS_ERR(ctrl_seq))
+ return PTR_ERR(ctrl_seq);
+
+ /* setup vsi information */
+ vdec_av1_slice_setup_seq(&vsi->frame.seq, ctrl_seq);
+ vdec_av1_slice_setup_uh(instance, &vsi->frame, ctrl_fh);
+ vdec_av1_slice_setup_operating_mode(instance, &vsi->frame);
+
+ vdec_av1_slice_setup_state(vsi);
+ vdec_av1_slice_setup_slot(instance, vsi, ctrl_fh);
+ vdec_av1_slice_setup_ref(pfc, ctrl_fh);
+ vdec_av1_slice_get_previous(vsi);
+
+ pfc->seq = instance->seq;
+ instance->seq++;
+
+ return ret;
+}
+
+static void vdec_av1_slice_setup_lat_buffer(struct vdec_av1_slice_instance *instance,
+ struct vdec_av1_slice_vsi *vsi,
+ struct mtk_vcodec_mem *bs,
+ struct vdec_lat_buf *lat_buf)
+{
+ struct vdec_av1_slice_work_buffer *work_buffer;
+ int i;
+
+ vsi->bs.dma_addr = bs->dma_addr;
+ vsi->bs.size = bs->size;
+
+ vsi->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
+ vsi->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size;
+ vsi->trans.dma_addr = lat_buf->ctx->msg_queue.wdma_wptr_addr;
+ /* used to store trans end */
+ vsi->trans.dma_addr_end = lat_buf->ctx->msg_queue.wdma_rptr_addr;
+ vsi->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr;
+ vsi->err_map.size = lat_buf->wdma_err_addr.size;
+ vsi->rd_mv.dma_addr = lat_buf->rd_mv_addr.dma_addr;
+ vsi->rd_mv.size = lat_buf->rd_mv_addr.size;
+
+ vsi->row_info.buf = 0;
+ vsi->row_info.size = 0;
+
+ work_buffer = vsi->work_buffer;
+
+ for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) {
+ work_buffer[i].mv_addr.buf = instance->mv[i].dma_addr;
+ work_buffer[i].mv_addr.size = instance->mv[i].size;
+ work_buffer[i].segid_addr.buf = instance->seg[i].dma_addr;
+ work_buffer[i].segid_addr.size = instance->seg[i].size;
+ work_buffer[i].cdf_addr.buf = instance->cdf[i].dma_addr;
+ work_buffer[i].cdf_addr.size = instance->cdf[i].size;
+ }
+
+ vsi->cdf_tmp.buf = instance->cdf_temp.dma_addr;
+ vsi->cdf_tmp.size = instance->cdf_temp.size;
+
+ vsi->tile.buf = instance->tile.dma_addr;
+ vsi->tile.size = instance->tile.size;
+ memcpy(lat_buf->tile_addr.va, instance->tile.va, 64 * instance->tile_group.num_tiles);
+
+ vsi->cdf_table.buf = instance->cdf_table.dma_addr;
+ vsi->cdf_table.size = instance->cdf_table.size;
+ vsi->iq_table.buf = instance->iq_table.dma_addr;
+ vsi->iq_table.size = instance->iq_table.size;
+}
+
+static void vdec_av1_slice_setup_seg_buffer(struct vdec_av1_slice_instance *instance,
+ struct vdec_av1_slice_vsi *vsi)
+{
+ struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh;
+ struct mtk_vcodec_mem *buf;
+
+ /* reset segment buffer */
+ if (uh->primary_ref_frame == AV1_PRIMARY_REF_NONE || !uh->seg.segmentation_enabled) {
+ mtk_vcodec_debug(instance, "reset seg %d\n", vsi->slot_id);
+ if (vsi->slot_id != AV1_INVALID_IDX) {
+ buf = &instance->seg[vsi->slot_id];
+ memset(buf->va, 0, buf->size);
+ }
+ }
+}
+
+static void vdec_av1_slice_setup_tile_buffer(struct vdec_av1_slice_instance *instance,
+ struct vdec_av1_slice_vsi *vsi,
+ struct mtk_vcodec_mem *bs)
+{
+ struct vdec_av1_slice_tile_group *tile_group = &instance->tile_group;
+ struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh;
+ struct vdec_av1_slice_tile *tile = &uh->tile;
+ u32 tile_num, tile_row, tile_col;
+ u32 allow_update_cdf = 0;
+ u32 sb_boundary_x_m1 = 0, sb_boundary_y_m1 = 0;
+ int tile_info_base;
+ u32 tile_buf_pa;
+ u32 *tile_info_buf = instance->tile.va;
+ u32 pa = (u32)bs->dma_addr;
+
+ if (uh->disable_cdf_update == 0)
+ allow_update_cdf = 1;
+
+ for (tile_num = 0; tile_num < tile_group->num_tiles; tile_num++) {
+ /* each uint32 takes place of 4 bytes */
+ tile_info_base = (AV1_TILE_BUF_SIZE * tile_num) >> 2;
+ tile_row = tile_num / tile->tile_cols;
+ tile_col = tile_num % tile->tile_cols;
+ tile_info_buf[tile_info_base + 0] = (tile_group->tile_size[tile_num] << 3);
+ tile_buf_pa = pa + tile_group->tile_start_offset[tile_num];
+
+ tile_info_buf[tile_info_base + 1] = (tile_buf_pa >> 4) << 4;
+ tile_info_buf[tile_info_base + 2] = (tile_buf_pa % 16) << 3;
+
+ sb_boundary_x_m1 =
+ (tile->mi_col_starts[tile_col + 1] - tile->mi_col_starts[tile_col] - 1) &
+ 0x3f;
+ sb_boundary_y_m1 =
+ (tile->mi_row_starts[tile_row + 1] - tile->mi_row_starts[tile_row] - 1) &
+ 0x1ff;
+
+ tile_info_buf[tile_info_base + 3] = (sb_boundary_y_m1 << 7) | sb_boundary_x_m1;
+ tile_info_buf[tile_info_base + 4] = ((allow_update_cdf << 18) | (1 << 16));
+
+ if (tile_num == tile->context_update_tile_id &&
+ uh->disable_frame_end_update_cdf == 0)
+ tile_info_buf[tile_info_base + 4] |= (1 << 17);
+
+ mtk_vcodec_debug(instance, "// tile buf %d pos(%dx%d) offset 0x%x\n",
+ tile_num, tile_row, tile_col, tile_info_base);
+ mtk_vcodec_debug(instance, "// %08x %08x %08x %08x\n",
+ tile_info_buf[tile_info_base + 0],
+ tile_info_buf[tile_info_base + 1],
+ tile_info_buf[tile_info_base + 2],
+ tile_info_buf[tile_info_base + 3]);
+ mtk_vcodec_debug(instance, "// %08x %08x %08x %08x\n",
+ tile_info_buf[tile_info_base + 4],
+ tile_info_buf[tile_info_base + 5],
+ tile_info_buf[tile_info_base + 6],
+ tile_info_buf[tile_info_base + 7]);
+ }
+}
+
+static int vdec_av1_slice_setup_lat(struct vdec_av1_slice_instance *instance,
+ struct mtk_vcodec_mem *bs,
+ struct vdec_lat_buf *lat_buf,
+ struct vdec_av1_slice_pfc *pfc)
+{
+ struct vdec_av1_slice_vsi *vsi = &pfc->vsi;
+ int ret;
+
+ ret = vdec_av1_slice_setup_lat_from_src_buf(instance, vsi, lat_buf);
+ if (ret)
+ return ret;
+
+ ret = vdec_av1_slice_setup_pfc(instance, pfc);
+ if (ret)
+ return ret;
+
+ ret = vdec_av1_slice_setup_tile_group(instance, vsi);
+ if (ret)
+ return ret;
+
+ ret = vdec_av1_slice_alloc_working_buffer(instance, vsi);
+ if (ret)
+ return ret;
+
+ vdec_av1_slice_setup_seg_buffer(instance, vsi);
+ vdec_av1_slice_setup_tile_buffer(instance, vsi, bs);
+ vdec_av1_slice_setup_lat_buffer(instance, vsi, bs, lat_buf);
+
+ return 0;
+}
+
+static int vdec_av1_slice_update_lat(struct vdec_av1_slice_instance *instance,
+ struct vdec_lat_buf *lat_buf,
+ struct vdec_av1_slice_pfc *pfc)
+{
+ struct vdec_av1_slice_vsi *vsi;
+
+ vsi = &pfc->vsi;
+ mtk_vcodec_debug(instance, "frame %u LAT CRC 0x%08x, output size is %d\n",
+ pfc->seq, vsi->state.crc[0], vsi->state.out_size);
+
+ /* buffer full, need to re-decode */
+ if (vsi->state.full) {
+ /* buffer not enough */
+ if (vsi->trans.dma_addr_end - vsi->trans.dma_addr == vsi->ube.size)
+ return -ENOMEM;
+ return -EAGAIN;
+ }
+
+ instance->width = vsi->frame.uh.upscaled_width;
+ instance->height = vsi->frame.uh.frame_height;
+ instance->frame_type = vsi->frame.uh.frame_type;
+
+ return 0;
+}
+
+static int vdec_av1_slice_setup_core_to_dst_buf(struct vdec_av1_slice_instance *instance,
+ struct vdec_lat_buf *lat_buf)
+{
+ struct vb2_v4l2_buffer *dst;
+
+ dst = v4l2_m2m_next_dst_buf(instance->ctx->m2m_ctx);
+ if (!dst)
+ return -EINVAL;
+
+ v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, dst, true);
+
+ return 0;
+}
+
+static int vdec_av1_slice_setup_core_buffer(struct vdec_av1_slice_instance *instance,
+ struct vdec_av1_slice_pfc *pfc,
+ struct vdec_av1_slice_vsi *vsi,
+ struct vdec_fb *fb,
+ struct vdec_lat_buf *lat_buf)
+{
+ struct vb2_buffer *vb;
+ struct vb2_queue *vq;
+ int w, h, plane, size;
+ int i;
+
+ plane = instance->ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes;
+ w = vsi->frame.uh.upscaled_width;
+ h = vsi->frame.uh.frame_height;
+ size = ALIGN(w, VCODEC_DEC_ALIGNED_64) * ALIGN(h, VCODEC_DEC_ALIGNED_64);
+
+ /* frame buffer */
+ vsi->fb.y.dma_addr = fb->base_y.dma_addr;
+ if (plane == 1)
+ vsi->fb.c.dma_addr = fb->base_y.dma_addr + size;
+ else
+ vsi->fb.c.dma_addr = fb->base_c.dma_addr;
+
+ /* reference buffers */
+ vq = v4l2_m2m_get_vq(instance->ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ if (!vq)
+ return -EINVAL;
+
+ /* get current output buffer */
+ vb = &v4l2_m2m_next_dst_buf(instance->ctx->m2m_ctx)->vb2_buf;
+ if (!vb)
+ return -EINVAL;
+
+ /* get buffer address from vb2buf */
+ for (i = 0; i < V4L2_AV1_REFS_PER_FRAME; i++) {
+ struct vdec_av1_slice_fb *vref = &vsi->ref[i];
+
+ vb = vb2_find_buffer(vq, pfc->ref_idx[i]);
+ if (!vb) {
+ memset(vref, 0, sizeof(*vref));
+ continue;
+ }
+
+ vref->y.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ if (plane == 1)
+ vref->c.dma_addr = vref->y.dma_addr + size;
+ else
+ vref->c.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 1);
+ }
+ vsi->tile.dma_addr = lat_buf->tile_addr.dma_addr;
+ vsi->tile.size = lat_buf->tile_addr.size;
+
+ return 0;
+}
+
+static int vdec_av1_slice_setup_core(struct vdec_av1_slice_instance *instance,
+ struct vdec_fb *fb,
+ struct vdec_lat_buf *lat_buf,
+ struct vdec_av1_slice_pfc *pfc)
+{
+ struct vdec_av1_slice_vsi *vsi = &pfc->vsi;
+ int ret;
+
+ ret = vdec_av1_slice_setup_core_to_dst_buf(instance, lat_buf);
+ if (ret)
+ return ret;
+
+ ret = vdec_av1_slice_setup_core_buffer(instance, pfc, vsi, fb, lat_buf);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int vdec_av1_slice_update_core(struct vdec_av1_slice_instance *instance,
+ struct vdec_lat_buf *lat_buf,
+ struct vdec_av1_slice_pfc *pfc)
+{
+ struct vdec_av1_slice_vsi *vsi = instance->core_vsi;
+
+ mtk_vcodec_debug(instance, "frame %u Y_CRC %08x %08x %08x %08x\n",
+ pfc->seq, vsi->state.crc[0], vsi->state.crc[1],
+ vsi->state.crc[2], vsi->state.crc[3]);
+ mtk_vcodec_debug(instance, "frame %u C_CRC %08x %08x %08x %08x\n",
+ pfc->seq, vsi->state.crc[8], vsi->state.crc[9],
+ vsi->state.crc[10], vsi->state.crc[11]);
+
+ return 0;
+}
+
+static int vdec_av1_slice_init(struct mtk_vcodec_ctx *ctx)
+{
+ struct vdec_av1_slice_instance *instance;
+ struct vdec_av1_slice_init_vsi *vsi;
+ int ret;
+
+ instance = kzalloc(sizeof(*instance), GFP_KERNEL);
+ if (!instance)
+ return -ENOMEM;
+
+ instance->ctx = ctx;
+ instance->vpu.id = SCP_IPI_VDEC_LAT;
+ instance->vpu.core_id = SCP_IPI_VDEC_CORE;
+ instance->vpu.ctx = ctx;
+ instance->vpu.codec_type = ctx->current_codec;
+
+ ret = vpu_dec_init(&instance->vpu);
+ if (ret) {
+ mtk_vcodec_err(instance, "failed to init vpu dec, ret %d\n", ret);
+ goto error_vpu_init;
+ }
+
+ /* init vsi and global flags */
+ vsi = instance->vpu.vsi;
+ if (!vsi) {
+ mtk_vcodec_err(instance, "failed to get AV1 vsi\n");
+ ret = -EINVAL;
+ goto error_vsi;
+ }
+ instance->init_vsi = vsi;
+ instance->core_vsi = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler, (u32)vsi->core_vsi);
+
+ if (!instance->core_vsi) {
+ mtk_vcodec_err(instance, "failed to get AV1 core vsi\n");
+ ret = -EINVAL;
+ goto error_vsi;
+ }
+
+ if (vsi->vsi_size != sizeof(struct vdec_av1_slice_vsi))
+ mtk_vcodec_err(instance, "remote vsi size 0x%x mismatch! expected: 0x%zx\n",
+ vsi->vsi_size, sizeof(struct vdec_av1_slice_vsi));
+
+ instance->irq_enabled = 1;
+ instance->inneracing_mode = IS_VDEC_INNER_RACING(instance->ctx->dev->dec_capability);
+
+ mtk_vcodec_debug(instance, "vsi 0x%p core_vsi 0x%llx 0x%p, inneracing_mode %d\n",
+ vsi, vsi->core_vsi, instance->core_vsi, instance->inneracing_mode);
+
+ ret = vdec_av1_slice_init_cdf_table(instance);
+ if (ret)
+ goto error_vsi;
+
+ ret = vdec_av1_slice_init_iq_table(instance);
+ if (ret)
+ goto error_vsi;
+
+ ctx->drv_handle = instance;
+
+ return 0;
+error_vsi:
+ vpu_dec_deinit(&instance->vpu);
+error_vpu_init:
+ kfree(instance);
+
+ return ret;
+}
+
+static void vdec_av1_slice_deinit(void *h_vdec)
+{
+ struct vdec_av1_slice_instance *instance = h_vdec;
+
+ if (!instance)
+ return;
+ mtk_vcodec_debug(instance, "h_vdec 0x%p\n", h_vdec);
+ vpu_dec_deinit(&instance->vpu);
+ vdec_av1_slice_free_working_buffer(instance);
+ vdec_msg_queue_deinit(&instance->ctx->msg_queue, instance->ctx);
+ kfree(instance);
+}
+
+static int vdec_av1_slice_flush(void *h_vdec, struct mtk_vcodec_mem *bs,
+ struct vdec_fb *fb, bool *res_chg)
+{
+ struct vdec_av1_slice_instance *instance = h_vdec;
+ int i;
+
+ mtk_vcodec_debug(instance, "flush ...\n");
+
+ vdec_msg_queue_wait_lat_buf_full(&instance->ctx->msg_queue);
+
+ for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++)
+ vdec_av1_slice_clear_fb(&instance->slots.frame_info[i]);
+
+ return vpu_dec_reset(&instance->vpu);
+}
+
+static void vdec_av1_slice_get_pic_info(struct vdec_av1_slice_instance *instance)
+{
+ struct mtk_vcodec_ctx *ctx = instance->ctx;
+ u32 data[3];
+
+ mtk_vcodec_debug(instance, "w %u h %u\n", ctx->picinfo.pic_w, ctx->picinfo.pic_h);
+
+ data[0] = ctx->picinfo.pic_w;
+ data[1] = ctx->picinfo.pic_h;
+ data[2] = ctx->capture_fourcc;
+ vpu_dec_get_param(&instance->vpu, data, 3, GET_PARAM_PIC_INFO);
+
+ ctx->picinfo.buf_w = ALIGN(ctx->picinfo.pic_w, VCODEC_DEC_ALIGNED_64);
+ ctx->picinfo.buf_h = ALIGN(ctx->picinfo.pic_h, VCODEC_DEC_ALIGNED_64);
+ ctx->picinfo.fb_sz[0] = instance->vpu.fb_sz[0];
+ ctx->picinfo.fb_sz[1] = instance->vpu.fb_sz[1];
+}
+
+static inline void vdec_av1_slice_get_dpb_size(struct vdec_av1_slice_instance *instance,
+ u32 *dpb_sz)
+{
+ /* refer av1 specification */
+ *dpb_sz = V4L2_AV1_TOTAL_REFS_PER_FRAME + 1;
+}
+
+static void vdec_av1_slice_get_crop_info(struct vdec_av1_slice_instance *instance,
+ struct v4l2_rect *cr)
+{
+ struct mtk_vcodec_ctx *ctx = instance->ctx;
+
+ cr->left = 0;
+ cr->top = 0;
+ cr->width = ctx->picinfo.pic_w;
+ cr->height = ctx->picinfo.pic_h;
+
+ mtk_vcodec_debug(instance, "l=%d, t=%d, w=%d, h=%d\n",
+ cr->left, cr->top, cr->width, cr->height);
+}
+
+static int vdec_av1_slice_get_param(void *h_vdec, enum vdec_get_param_type type, void *out)
+{
+ struct vdec_av1_slice_instance *instance = h_vdec;
+
+ switch (type) {
+ case GET_PARAM_PIC_INFO:
+ vdec_av1_slice_get_pic_info(instance);
+ break;
+ case GET_PARAM_DPB_SIZE:
+ vdec_av1_slice_get_dpb_size(instance, out);
+ break;
+ case GET_PARAM_CROP_INFO:
+ vdec_av1_slice_get_crop_info(instance, out);
+ break;
+ default:
+ mtk_vcodec_err(instance, "invalid get parameter type=%d\n", type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vdec_av1_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
+ struct vdec_fb *fb, bool *res_chg)
+{
+ struct vdec_av1_slice_instance *instance = h_vdec;
+ struct vdec_lat_buf *lat_buf;
+ struct vdec_av1_slice_pfc *pfc;
+ struct vdec_av1_slice_vsi *vsi;
+ struct mtk_vcodec_ctx *ctx;
+ int ret;
+
+ if (!instance || !instance->ctx)
+ return -EINVAL;
+
+ ctx = instance->ctx;
+ /* init msgQ for the first time */
+ if (vdec_msg_queue_init(&ctx->msg_queue, ctx,
+ vdec_av1_slice_core_decode, sizeof(*pfc))) {
+ mtk_vcodec_err(instance, "failed to init AV1 msg queue\n");
+ return -ENOMEM;
+ }
+
+ /* bs NULL means flush decoder */
+ if (!bs)
+ return vdec_av1_slice_flush(h_vdec, bs, fb, res_chg);
+
+ lat_buf = vdec_msg_queue_dqbuf(&ctx->msg_queue.lat_ctx);
+ if (!lat_buf) {
+ mtk_vcodec_err(instance, "failed to get AV1 lat buf\n");
+ return -EAGAIN;
+ }
+ pfc = (struct vdec_av1_slice_pfc *)lat_buf->private_data;
+ if (!pfc) {
+ ret = -EINVAL;
+ goto err_free_fb_out;
+ }
+ vsi = &pfc->vsi;
+
+ ret = vdec_av1_slice_setup_lat(instance, bs, lat_buf, pfc);
+ if (ret) {
+ mtk_vcodec_err(instance, "failed to setup AV1 lat ret %d\n", ret);
+ goto err_free_fb_out;
+ }
+
+ vdec_av1_slice_vsi_to_remote(vsi, instance->vsi);
+ ret = vpu_dec_start(&instance->vpu, NULL, 0);
+ if (ret) {
+ mtk_vcodec_err(instance, "failed to dec AV1 ret %d\n", ret);
+ goto err_free_fb_out;
+ }
+ if (instance->inneracing_mode)
+ vdec_msg_queue_qbuf(&ctx->msg_queue.core_ctx, lat_buf);
+
+ if (instance->irq_enabled) {
+ ret = mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED,
+ WAIT_INTR_TIMEOUT_MS,
+ MTK_VDEC_LAT0);
+ /* update remote vsi if decode timeout */
+ if (ret) {
+ mtk_vcodec_err(instance, "AV1 Frame %d decode timeout %d\n", pfc->seq, ret);
+ WRITE_ONCE(instance->vsi->state.timeout, 1);
+ }
+ vpu_dec_end(&instance->vpu);
+ }
+
+ vdec_av1_slice_vsi_from_remote(vsi, instance->vsi);
+ ret = vdec_av1_slice_update_lat(instance, lat_buf, pfc);
+
+ /* LAT trans full, re-decode */
+ if (ret == -EAGAIN) {
+ mtk_vcodec_err(instance, "AV1 Frame %d trans full\n", pfc->seq);
+ if (!instance->inneracing_mode)
+ vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf);
+ return 0;
+ }
+
+ /* LAT trans full, no more UBE or decode timeout */
+ if (ret == -ENOMEM || vsi->state.timeout) {
+ mtk_vcodec_err(instance, "AV1 Frame %d insufficient buffer or timeout\n", pfc->seq);
+ if (!instance->inneracing_mode)
+ vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf);
+ return -EBUSY;
+ }
+ vsi->trans.dma_addr_end += ctx->msg_queue.wdma_addr.dma_addr;
+ mtk_vcodec_debug(instance, "lat dma 1 0x%pad 0x%pad\n",
+ &pfc->vsi.trans.dma_addr, &pfc->vsi.trans.dma_addr_end);
+
+ vdec_msg_queue_update_ube_wptr(&ctx->msg_queue, vsi->trans.dma_addr_end);
+
+ if (!instance->inneracing_mode)
+ vdec_msg_queue_qbuf(&ctx->msg_queue.core_ctx, lat_buf);
+ memcpy(&instance->slots, &vsi->slots, sizeof(instance->slots));
+
+ return 0;
+
+err_free_fb_out:
+ vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf);
+
+ if (pfc)
+ mtk_vcodec_err(instance, "slice dec number: %d err: %d", pfc->seq, ret);
+
+ return ret;
+}
+
+static int vdec_av1_slice_core_decode(struct vdec_lat_buf *lat_buf)
+{
+ struct vdec_av1_slice_instance *instance;
+ struct vdec_av1_slice_pfc *pfc;
+ struct mtk_vcodec_ctx *ctx = NULL;
+ struct vdec_fb *fb = NULL;
+ int ret = -EINVAL;
+
+ if (!lat_buf)
+ return -EINVAL;
+
+ pfc = lat_buf->private_data;
+ ctx = lat_buf->ctx;
+ if (!pfc || !ctx)
+ return -EINVAL;
+
+ instance = ctx->drv_handle;
+ if (!instance)
+ goto err;
+
+ fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx);
+ if (!fb) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ ret = vdec_av1_slice_setup_core(instance, fb, lat_buf, pfc);
+ if (ret) {
+ mtk_vcodec_err(instance, "vdec_av1_slice_setup_core\n");
+ goto err;
+ }
+ vdec_av1_slice_vsi_to_remote(&pfc->vsi, instance->core_vsi);
+ ret = vpu_dec_core(&instance->vpu);
+ if (ret) {
+ mtk_vcodec_err(instance, "vpu_dec_core\n");
+ goto err;
+ }
+
+ if (instance->irq_enabled) {
+ ret = mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED,
+ WAIT_INTR_TIMEOUT_MS,
+ MTK_VDEC_CORE);
+ /* update remote vsi if decode timeout */
+ if (ret) {
+ mtk_vcodec_err(instance, "AV1 frame %d core timeout\n", pfc->seq);
+ WRITE_ONCE(instance->vsi->state.timeout, 1);
+ }
+ vpu_dec_core_end(&instance->vpu);
+ }
+
+ ret = vdec_av1_slice_update_core(instance, lat_buf, pfc);
+ if (ret) {
+ mtk_vcodec_err(instance, "vdec_av1_slice_update_core\n");
+ goto err;
+ }
+
+ mtk_vcodec_debug(instance, "core dma_addr_end 0x%pad\n",
+ &instance->core_vsi->trans.dma_addr_end);
+ vdec_msg_queue_update_ube_rptr(&ctx->msg_queue, instance->core_vsi->trans.dma_addr_end);
+
+ ctx->dev->vdec_pdata->cap_to_disp(ctx, 0, lat_buf->src_buf_req);
+
+ return 0;
+
+err:
+ /* always update read pointer */
+ vdec_msg_queue_update_ube_rptr(&ctx->msg_queue, pfc->vsi.trans.dma_addr_end);
+
+ if (fb)
+ ctx->dev->vdec_pdata->cap_to_disp(ctx, 1, lat_buf->src_buf_req);
+
+ return ret;
+}
+
+const struct vdec_common_if vdec_av1_slice_lat_if = {
+ .init = vdec_av1_slice_init,
+ .decode = vdec_av1_slice_lat_decode,
+ .get_param = vdec_av1_slice_get_param,
+ .deinit = vdec_av1_slice_deinit,
+};
diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c
index 999ce7ee5fdc..a7e8e3257b7f 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c
@@ -596,7 +596,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
lat_buf = vdec_msg_queue_dqbuf(&inst->ctx->msg_queue.lat_ctx);
if (!lat_buf) {
- mtk_vcodec_err(inst, "failed to get lat buffer");
+ mtk_vcodec_debug(inst, "failed to get lat buffer");
return -EAGAIN;
}
share_info = lat_buf->private_data;
@@ -672,7 +672,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
memcpy(&share_info->h264_slice_params, &inst->vsi->h264_slice_params,
sizeof(share_info->h264_slice_params));
- vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf);
+ vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
}
/* wait decoder done interrupt */
@@ -698,7 +698,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
memcpy(&share_info->h264_slice_params, &inst->vsi->h264_slice_params,
sizeof(share_info->h264_slice_params));
- vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf);
+ vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
}
mtk_vcodec_debug(inst, "dec num: %d lat crc: 0x%x 0x%x 0x%x", inst->slice_dec_num,
inst->vsi->dec.crc[0], inst->vsi->dec.crc[1], inst->vsi->dec.crc[2]);
diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c
new file mode 100644
index 000000000000..1e6ab138b0bb
--- /dev/null
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c
@@ -0,0 +1,1097 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Yunfei Dong <yunfei.dong@mediatek.com>
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "../mtk_vcodec_util.h"
+#include "../mtk_vcodec_dec.h"
+#include "../mtk_vcodec_intr.h"
+#include "../vdec_drv_base.h"
+#include "../vdec_drv_if.h"
+#include "../vdec_vpu_if.h"
+
+/* the size used to store hevc wrap information */
+#define VDEC_HEVC_WRAP_SZ (532 * SZ_1K)
+
+#define HEVC_MAX_MV_NUM 32
+
+/* get used parameters for sps/pps */
+#define GET_HEVC_VDEC_FLAG(cond, flag) \
+ { dst_param->cond = ((src_param->flags & (flag)) ? (1) : (0)); }
+#define GET_HEVC_VDEC_PARAM(param) \
+ { dst_param->param = src_param->param; }
+
+/**
+ * enum vdec_hevc_core_dec_err_type - core decode error type
+ *
+ * @TRANS_BUFFER_FULL: trans buffer is full
+ * @SLICE_HEADER_FULL: slice header buffer is full
+ */
+enum vdec_hevc_core_dec_err_type {
+ TRANS_BUFFER_FULL = 1,
+ SLICE_HEADER_FULL,
+};
+
+/**
+ * struct mtk_hevc_dpb_info - hevc dpb information
+ *
+ * @y_dma_addr: Y plane physical address
+ * @c_dma_addr: CbCr plane physical address
+ * @reference_flag: reference picture flag (short/long term reference picture)
+ * @field: field picture flag
+ */
+struct mtk_hevc_dpb_info {
+ dma_addr_t y_dma_addr;
+ dma_addr_t c_dma_addr;
+ int reference_flag;
+ int field;
+};
+
+/*
+ * struct mtk_hevc_sps_param - parameters for sps
+ */
+struct mtk_hevc_sps_param {
+ unsigned char video_parameter_set_id;
+ unsigned char seq_parameter_set_id;
+ unsigned short pic_width_in_luma_samples;
+ unsigned short pic_height_in_luma_samples;
+ unsigned char bit_depth_luma_minus8;
+ unsigned char bit_depth_chroma_minus8;
+ unsigned char log2_max_pic_order_cnt_lsb_minus4;
+ unsigned char sps_max_dec_pic_buffering_minus1;
+ unsigned char sps_max_num_reorder_pics;
+ unsigned char sps_max_latency_increase_plus1;
+ unsigned char log2_min_luma_coding_block_size_minus3;
+ unsigned char log2_diff_max_min_luma_coding_block_size;
+ unsigned char log2_min_luma_transform_block_size_minus2;
+ unsigned char log2_diff_max_min_luma_transform_block_size;
+ unsigned char max_transform_hierarchy_depth_inter;
+ unsigned char max_transform_hierarchy_depth_intra;
+ unsigned char pcm_sample_bit_depth_luma_minus1;
+ unsigned char pcm_sample_bit_depth_chroma_minus1;
+ unsigned char log2_min_pcm_luma_coding_block_size_minus3;
+ unsigned char log2_diff_max_min_pcm_luma_coding_block_size;
+ unsigned char num_short_term_ref_pic_sets;
+ unsigned char num_long_term_ref_pics_sps;
+ unsigned char chroma_format_idc;
+ unsigned char sps_max_sub_layers_minus1;
+ unsigned char separate_colour_plane;
+ unsigned char scaling_list_enabled;
+ unsigned char amp_enabled;
+ unsigned char sample_adaptive_offset;
+ unsigned char pcm_enabled;
+ unsigned char pcm_loop_filter_disabled;
+ unsigned char long_term_ref_pics_enabled;
+ unsigned char sps_temporal_mvp_enabled;
+ unsigned char strong_intra_smoothing_enabled;
+ unsigned char reserved[5];
+};
+
+/*
+ * struct mtk_hevc_pps_param - parameters for pps
+ */
+struct mtk_hevc_pps_param {
+ unsigned char pic_parameter_set_id;
+ unsigned char num_extra_slice_header_bits;
+ unsigned char num_ref_idx_l0_default_active_minus1;
+ unsigned char num_ref_idx_l1_default_active_minus1;
+ char init_qp_minus26;
+ unsigned char diff_cu_qp_delta_depth;
+ char pps_cb_qp_offset;
+ char pps_cr_qp_offset;
+ unsigned char num_tile_columns_minus1;
+ unsigned char num_tile_rows_minus1;
+ unsigned char column_width_minus1[20];
+ unsigned char row_height_minus1[22];
+ char pps_beta_offset_div2;
+ char pps_tc_offset_div2;
+ unsigned char log2_parallel_merge_level_minus2;
+ char dependent_slice_segment_enabled;
+ char output_flag_present;
+ char sign_data_hiding_enabled;
+ char cabac_init_present;
+ char constrained_intra_pred;
+ char transform_skip_enabled;
+ char cu_qp_delta_enabled;
+ char pps_slice_chroma_qp_offsets_present;
+ char weighted_pred;
+ char weighted_bipred;
+ char transquant_bypass_enabled;
+ char pps_flag_tiles_enabled;
+ char entropy_coding_sync_enabled;
+ char loop_filter_across_tiles_enabled;
+ char pps_loop_filter_across_slices_enabled;
+ char deblocking_filter_override_enabled;
+ char pps_disable_deflocking_filter;
+ char lists_modification_present;
+ char slice_segment_header_extersion_present;
+ char deblocking_filter_control_present;
+ char uniform_spacing;
+ char reserved[6];
+};
+
+/*
+ * struct mtk_hevc_slice_header_param - parameters for slice header
+ */
+struct mtk_hevc_slice_header_param {
+ unsigned int slice_type;
+ unsigned int num_active_ref_layer_pics;
+ int slice_qp;
+ int slice_qp_delta_cb;
+ int slice_qp_delta_cr;
+ int num_ref_idx[3];
+ unsigned int col_ref_idx;
+ unsigned int five_minus_max_num_merge_cand;
+ int slice_deblocking_filter_beta_offset_div2;
+ int slice_deblocking_filter_tc_offset_div2;
+ unsigned char sao_enable_flag;
+ unsigned char sao_enable_flag_chroma;
+ unsigned char cabac_init_flag;
+ unsigned char slice_tmvp_flags_present;
+ unsigned char col_from_l0_flag;
+ unsigned char mvd_l1_zero_flag;
+ unsigned char slice_loop_filter_across_slices_enabled_flag;
+ unsigned char deblocking_filter_disable_flag;
+ unsigned int slice_reg0;
+ unsigned int slice_reg1;
+ unsigned int slice_reg2;
+ unsigned int num_rps_curr_temp_list;
+ unsigned int ref_list_mode;
+ int str_num_delta_pocs;
+ int str_num_negtive_pos_pics;
+ int num_long_term;
+ int num_long_term_sps;
+ unsigned int max_cu_width;
+ unsigned int max_cu_height;
+ unsigned int num_entry_point_offsets;
+ unsigned int last_lcu_x_in_tile[17];
+ unsigned int last_lcu_y_in_tile[17];
+ unsigned char nal_unit_type;
+};
+
+/*
+ * struct slice_api_hevc_scaling_matrix - parameters for scaling list
+ */
+struct slice_api_hevc_scaling_matrix {
+ unsigned char scaling_list_4x4[6][16];
+ unsigned char scaling_list_8x8[6][64];
+ unsigned char scaling_list_16x16[6][64];
+ unsigned char scaling_list_32x32[2][64];
+ unsigned char scaling_list_dc_coef_16x16[6];
+ unsigned char scaling_list_dc_coef_32x32[2];
+};
+
+/*
+ * struct slice_hevc_dpb_entry - each dpb information
+ */
+struct slice_hevc_dpb_entry {
+ u64 timestamp;
+ unsigned char flags;
+ unsigned char field_pic;
+ int pic_order_cnt_val;
+};
+
+/*
+ * struct slice_api_hevc_decode_param - parameters for decode.
+ */
+struct slice_api_hevc_decode_param {
+ struct slice_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ int pic_order_cnt_val;
+ unsigned short short_term_ref_pic_set_size;
+ unsigned short long_term_ref_pic_set_size;
+ unsigned char num_active_dpb_entries;
+ unsigned char num_poc_st_curr_before;
+ unsigned char num_poc_st_curr_after;
+ unsigned char num_poc_lt_curr;
+ unsigned char poc_st_curr_before[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ unsigned char poc_st_curr_after[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ unsigned char poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ unsigned char num_delta_pocs_of_ref_rps_idx;
+ int flags;
+};
+
+/**
+ * struct hevc_fb - hevc decode frame buffer information
+ *
+ * @vdec_fb_va: virtual address of struct vdec_fb
+ * @y_fb_dma: dma address of Y frame buffer (luma)
+ * @c_fb_dma: dma address of C frame buffer (chroma)
+ * @poc: picture order count of frame buffer
+ * @reserved: for 8 bytes alignment
+ */
+struct hevc_fb {
+ u64 vdec_fb_va;
+ u64 y_fb_dma;
+ u64 c_fb_dma;
+ s32 poc;
+ u32 reserved;
+};
+
+/**
+ * struct vdec_hevc_slice_lat_dec_param - parameters for decode current frame
+ *
+ * @sps: hevc sps syntax parameters
+ * @pps: hevc pps syntax parameters
+ * @slice_header: hevc slice header syntax parameters
+ * @scaling_matrix: hevc scaling list parameters
+ * @decode_params: decoder parameters of each frame used for hardware decode
+ * @hevc_dpb_info: dpb reference list
+ */
+struct vdec_hevc_slice_lat_dec_param {
+ struct mtk_hevc_sps_param sps;
+ struct mtk_hevc_pps_param pps;
+ struct mtk_hevc_slice_header_param slice_header;
+ struct slice_api_hevc_scaling_matrix scaling_matrix;
+ struct slice_api_hevc_decode_param decode_params;
+ struct mtk_hevc_dpb_info hevc_dpb_info[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+};
+
+/**
+ * struct vdec_hevc_slice_info - decode information
+ *
+ * @wdma_end_addr_offset: wdma end address offset
+ * @timeout: Decode timeout: 1 timeout, 0 no timeount
+ * @vdec_fb_va: VDEC frame buffer struct virtual address
+ * @crc: Used to check whether hardware's status is right
+ */
+struct vdec_hevc_slice_info {
+ u64 wdma_end_addr_offset;
+ u64 timeout;
+ u64 vdec_fb_va;
+ u32 crc[8];
+};
+
+/*
+ * struct vdec_hevc_slice_mem - memory address and size
+ */
+struct vdec_hevc_slice_mem {
+ union {
+ u64 buf;
+ dma_addr_t dma_addr;
+ };
+ union {
+ size_t size;
+ dma_addr_t dma_addr_end;
+ u64 padding;
+ };
+};
+
+/**
+ * struct vdec_hevc_slice_fb - frame buffer for decoding
+ * @y: current y buffer address info
+ * @c: current c buffer address info
+ */
+struct vdec_hevc_slice_fb {
+ struct vdec_hevc_slice_mem y;
+ struct vdec_hevc_slice_mem c;
+};
+
+/**
+ * struct vdec_hevc_slice_vsi - shared memory for decode information exchange
+ * between SCP and Host.
+ *
+ * @bs: input buffer info
+ *
+ * @ube: ube buffer
+ * @trans: transcoded buffer
+ * @err_map: err map buffer
+ * @slice_bc: slice bc buffer
+ * @wrap: temp buffer
+ *
+ * @fb: current y/c buffer
+ * @mv_buf_dma: HW working motion vector buffer
+ * @dec: decode information (AP-R, VPU-W)
+ * @hevc_slice_params: decode parameters for hw used
+ */
+struct vdec_hevc_slice_vsi {
+ /* used in LAT stage */
+ struct vdec_hevc_slice_mem bs;
+
+ struct vdec_hevc_slice_mem ube;
+ struct vdec_hevc_slice_mem trans;
+ struct vdec_hevc_slice_mem err_map;
+ struct vdec_hevc_slice_mem slice_bc;
+ struct vdec_hevc_slice_mem wrap;
+
+ struct vdec_hevc_slice_fb fb;
+ struct vdec_hevc_slice_mem mv_buf_dma[HEVC_MAX_MV_NUM];
+ struct vdec_hevc_slice_info dec;
+ struct vdec_hevc_slice_lat_dec_param hevc_slice_params;
+};
+
+/**
+ * struct vdec_hevc_slice_share_info - shared information used to exchange
+ * message between lat and core
+ *
+ * @sps: sequence header information from user space
+ * @dec_params: decoder params from user space
+ * @hevc_slice_params: decoder params used for hardware
+ * @trans: trans buffer dma address
+ */
+struct vdec_hevc_slice_share_info {
+ struct v4l2_ctrl_hevc_sps sps;
+ struct v4l2_ctrl_hevc_decode_params dec_params;
+ struct vdec_hevc_slice_lat_dec_param hevc_slice_params;
+ struct vdec_hevc_slice_mem trans;
+};
+
+/**
+ * struct vdec_hevc_slice_inst - hevc decoder instance
+ *
+ * @slice_dec_num: how many picture be decoded
+ * @ctx: point to mtk_vcodec_ctx
+ * @mv_buf: HW working motion vector buffer
+ * @vpu: VPU instance
+ * @vsi: vsi used for lat
+ * @vsi_core: vsi used for core
+ * @wrap_addr: wrap address used for hevc
+ *
+ * @hevc_slice_param: the parameters that hardware use to decode
+ *
+ * @resolution_changed: resolution changed
+ * @realloc_mv_buf: reallocate mv buffer
+ * @cap_num_planes: number of capture queue plane
+ */
+struct vdec_hevc_slice_inst {
+ unsigned int slice_dec_num;
+ struct mtk_vcodec_ctx *ctx;
+ struct mtk_vcodec_mem mv_buf[HEVC_MAX_MV_NUM];
+ struct vdec_vpu_inst vpu;
+ struct vdec_hevc_slice_vsi *vsi;
+ struct vdec_hevc_slice_vsi *vsi_core;
+ struct mtk_vcodec_mem wrap_addr;
+
+ struct vdec_hevc_slice_lat_dec_param hevc_slice_param;
+
+ unsigned int resolution_changed;
+ unsigned int realloc_mv_buf;
+ unsigned int cap_num_planes;
+};
+
+static unsigned int vdec_hevc_get_mv_buf_size(unsigned int width, unsigned int height)
+{
+ const unsigned int unit_size = (width / 16) * (height / 16) + 8;
+
+ return 64 * unit_size;
+}
+
+static void *vdec_hevc_get_ctrl_ptr(struct mtk_vcodec_ctx *ctx, int id)
+{
+ struct v4l2_ctrl *ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, id);
+
+ if (!ctrl)
+ return ERR_PTR(-EINVAL);
+
+ return ctrl->p_cur.p;
+}
+
+static void vdec_hevc_fill_dpb_info(struct mtk_vcodec_ctx *ctx,
+ struct slice_api_hevc_decode_param *decode_params,
+ struct mtk_hevc_dpb_info *hevc_dpb_info)
+{
+ const struct slice_hevc_dpb_entry *dpb;
+ struct vb2_queue *vq;
+ struct vb2_buffer *vb;
+ int index;
+
+ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ for (index = 0; index < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; index++) {
+ dpb = &decode_params->dpb[index];
+ if (index >= decode_params->num_active_dpb_entries)
+ continue;
+
+ vb = vb2_find_buffer(vq, dpb->timestamp);
+ if (!vb) {
+ dev_err(&ctx->dev->plat_dev->dev,
+ "Reference invalid: dpb_index(%d) timestamp(%lld)",
+ index, dpb->timestamp);
+ continue;
+ }
+
+ hevc_dpb_info[index].field = dpb->field_pic;
+
+ hevc_dpb_info[index].y_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2)
+ hevc_dpb_info[index].c_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 1);
+ else
+ hevc_dpb_info[index].c_dma_addr =
+ hevc_dpb_info[index].y_dma_addr + ctx->picinfo.fb_sz[0];
+ }
+}
+
+static void vdec_hevc_copy_sps_params(struct mtk_hevc_sps_param *dst_param,
+ const struct v4l2_ctrl_hevc_sps *src_param)
+{
+ GET_HEVC_VDEC_PARAM(video_parameter_set_id);
+ GET_HEVC_VDEC_PARAM(seq_parameter_set_id);
+ GET_HEVC_VDEC_PARAM(pic_width_in_luma_samples);
+ GET_HEVC_VDEC_PARAM(pic_height_in_luma_samples);
+ GET_HEVC_VDEC_PARAM(bit_depth_luma_minus8);
+ GET_HEVC_VDEC_PARAM(bit_depth_chroma_minus8);
+ GET_HEVC_VDEC_PARAM(log2_max_pic_order_cnt_lsb_minus4);
+ GET_HEVC_VDEC_PARAM(sps_max_dec_pic_buffering_minus1);
+ GET_HEVC_VDEC_PARAM(sps_max_num_reorder_pics);
+ GET_HEVC_VDEC_PARAM(sps_max_latency_increase_plus1);
+ GET_HEVC_VDEC_PARAM(log2_min_luma_coding_block_size_minus3);
+ GET_HEVC_VDEC_PARAM(log2_diff_max_min_luma_coding_block_size);
+ GET_HEVC_VDEC_PARAM(log2_min_luma_transform_block_size_minus2);
+ GET_HEVC_VDEC_PARAM(log2_diff_max_min_luma_transform_block_size);
+ GET_HEVC_VDEC_PARAM(max_transform_hierarchy_depth_inter);
+ GET_HEVC_VDEC_PARAM(max_transform_hierarchy_depth_intra);
+ GET_HEVC_VDEC_PARAM(pcm_sample_bit_depth_luma_minus1);
+ GET_HEVC_VDEC_PARAM(pcm_sample_bit_depth_chroma_minus1);
+ GET_HEVC_VDEC_PARAM(log2_min_pcm_luma_coding_block_size_minus3);
+ GET_HEVC_VDEC_PARAM(log2_diff_max_min_pcm_luma_coding_block_size);
+ GET_HEVC_VDEC_PARAM(num_short_term_ref_pic_sets);
+ GET_HEVC_VDEC_PARAM(num_long_term_ref_pics_sps);
+ GET_HEVC_VDEC_PARAM(chroma_format_idc);
+ GET_HEVC_VDEC_PARAM(sps_max_sub_layers_minus1);
+
+ GET_HEVC_VDEC_FLAG(separate_colour_plane,
+ V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE);
+ GET_HEVC_VDEC_FLAG(scaling_list_enabled,
+ V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED);
+ GET_HEVC_VDEC_FLAG(amp_enabled,
+ V4L2_HEVC_SPS_FLAG_AMP_ENABLED);
+ GET_HEVC_VDEC_FLAG(sample_adaptive_offset,
+ V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET);
+ GET_HEVC_VDEC_FLAG(pcm_enabled,
+ V4L2_HEVC_SPS_FLAG_PCM_ENABLED);
+ GET_HEVC_VDEC_FLAG(pcm_loop_filter_disabled,
+ V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED);
+ GET_HEVC_VDEC_FLAG(long_term_ref_pics_enabled,
+ V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT);
+ GET_HEVC_VDEC_FLAG(sps_temporal_mvp_enabled,
+ V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED);
+ GET_HEVC_VDEC_FLAG(strong_intra_smoothing_enabled,
+ V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED);
+}
+
+static void vdec_hevc_copy_pps_params(struct mtk_hevc_pps_param *dst_param,
+ const struct v4l2_ctrl_hevc_pps *src_param)
+{
+ int i;
+
+ GET_HEVC_VDEC_PARAM(pic_parameter_set_id);
+ GET_HEVC_VDEC_PARAM(num_extra_slice_header_bits);
+ GET_HEVC_VDEC_PARAM(num_ref_idx_l0_default_active_minus1);
+ GET_HEVC_VDEC_PARAM(num_ref_idx_l1_default_active_minus1);
+ GET_HEVC_VDEC_PARAM(init_qp_minus26);
+ GET_HEVC_VDEC_PARAM(diff_cu_qp_delta_depth);
+ GET_HEVC_VDEC_PARAM(pps_cb_qp_offset);
+ GET_HEVC_VDEC_PARAM(pps_cr_qp_offset);
+ GET_HEVC_VDEC_PARAM(num_tile_columns_minus1);
+ GET_HEVC_VDEC_PARAM(num_tile_rows_minus1);
+ GET_HEVC_VDEC_PARAM(init_qp_minus26);
+ GET_HEVC_VDEC_PARAM(diff_cu_qp_delta_depth);
+ GET_HEVC_VDEC_PARAM(pic_parameter_set_id);
+ GET_HEVC_VDEC_PARAM(num_extra_slice_header_bits);
+ GET_HEVC_VDEC_PARAM(num_ref_idx_l0_default_active_minus1);
+ GET_HEVC_VDEC_PARAM(num_ref_idx_l1_default_active_minus1);
+ GET_HEVC_VDEC_PARAM(pps_beta_offset_div2);
+ GET_HEVC_VDEC_PARAM(pps_tc_offset_div2);
+ GET_HEVC_VDEC_PARAM(log2_parallel_merge_level_minus2);
+
+ for (i = 0; i < ARRAY_SIZE(src_param->column_width_minus1); i++)
+ GET_HEVC_VDEC_PARAM(column_width_minus1[i]);
+ for (i = 0; i < ARRAY_SIZE(src_param->row_height_minus1); i++)
+ GET_HEVC_VDEC_PARAM(row_height_minus1[i]);
+
+ GET_HEVC_VDEC_FLAG(dependent_slice_segment_enabled,
+ V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED);
+ GET_HEVC_VDEC_FLAG(output_flag_present,
+ V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT);
+ GET_HEVC_VDEC_FLAG(sign_data_hiding_enabled,
+ V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED);
+ GET_HEVC_VDEC_FLAG(cabac_init_present,
+ V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT);
+ GET_HEVC_VDEC_FLAG(constrained_intra_pred,
+ V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED);
+ GET_HEVC_VDEC_FLAG(transform_skip_enabled,
+ V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED);
+ GET_HEVC_VDEC_FLAG(cu_qp_delta_enabled,
+ V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED);
+ GET_HEVC_VDEC_FLAG(pps_slice_chroma_qp_offsets_present,
+ V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT);
+ GET_HEVC_VDEC_FLAG(weighted_pred,
+ V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED);
+ GET_HEVC_VDEC_FLAG(weighted_bipred,
+ V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED);
+ GET_HEVC_VDEC_FLAG(transquant_bypass_enabled,
+ V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED);
+ GET_HEVC_VDEC_FLAG(pps_flag_tiles_enabled,
+ V4L2_HEVC_PPS_FLAG_TILES_ENABLED);
+ GET_HEVC_VDEC_FLAG(entropy_coding_sync_enabled,
+ V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED);
+ GET_HEVC_VDEC_FLAG(loop_filter_across_tiles_enabled,
+ V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED);
+ GET_HEVC_VDEC_FLAG(pps_loop_filter_across_slices_enabled,
+ V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED);
+ GET_HEVC_VDEC_FLAG(deblocking_filter_override_enabled,
+ V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED);
+ GET_HEVC_VDEC_FLAG(pps_disable_deflocking_filter,
+ V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER);
+ GET_HEVC_VDEC_FLAG(lists_modification_present,
+ V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT);
+ GET_HEVC_VDEC_FLAG(slice_segment_header_extersion_present,
+ V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT);
+ GET_HEVC_VDEC_FLAG(deblocking_filter_control_present,
+ V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT);
+ GET_HEVC_VDEC_FLAG(uniform_spacing,
+ V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING);
+}
+
+static void vdec_hevc_copy_scaling_matrix(struct slice_api_hevc_scaling_matrix *dst_matrix,
+ const struct v4l2_ctrl_hevc_scaling_matrix *src_matrix)
+{
+ memcpy(dst_matrix, src_matrix, sizeof(*src_matrix));
+}
+
+static void
+vdec_hevc_copy_decode_params(struct slice_api_hevc_decode_param *dst_param,
+ const struct v4l2_ctrl_hevc_decode_params *src_param,
+ const struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX])
+{
+ struct slice_hevc_dpb_entry *dst_entry;
+ const struct v4l2_hevc_dpb_entry *src_entry;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dst_param->dpb); i++) {
+ dst_entry = &dst_param->dpb[i];
+ src_entry = &dpb[i];
+
+ dst_entry->timestamp = src_entry->timestamp;
+ dst_entry->flags = src_entry->flags;
+ dst_entry->field_pic = src_entry->field_pic;
+ dst_entry->pic_order_cnt_val = src_entry->pic_order_cnt_val;
+
+ GET_HEVC_VDEC_PARAM(poc_st_curr_before[i]);
+ GET_HEVC_VDEC_PARAM(poc_st_curr_after[i]);
+ GET_HEVC_VDEC_PARAM(poc_lt_curr[i]);
+ }
+
+ GET_HEVC_VDEC_PARAM(pic_order_cnt_val);
+ GET_HEVC_VDEC_PARAM(short_term_ref_pic_set_size);
+ GET_HEVC_VDEC_PARAM(long_term_ref_pic_set_size);
+ GET_HEVC_VDEC_PARAM(num_active_dpb_entries);
+ GET_HEVC_VDEC_PARAM(num_poc_st_curr_before);
+ GET_HEVC_VDEC_PARAM(num_poc_st_curr_after);
+ GET_HEVC_VDEC_PARAM(num_delta_pocs_of_ref_rps_idx);
+ GET_HEVC_VDEC_PARAM(num_poc_lt_curr);
+ GET_HEVC_VDEC_PARAM(flags);
+}
+
+static int vdec_hevc_slice_fill_decode_parameters(struct vdec_hevc_slice_inst *inst,
+ struct vdec_hevc_slice_share_info *share_info)
+{
+ struct vdec_hevc_slice_lat_dec_param *slice_param = &inst->vsi->hevc_slice_params;
+ const struct v4l2_ctrl_hevc_decode_params *dec_params;
+ const struct v4l2_ctrl_hevc_scaling_matrix *src_matrix;
+ const struct v4l2_ctrl_hevc_sps *sps;
+ const struct v4l2_ctrl_hevc_pps *pps;
+
+ dec_params =
+ vdec_hevc_get_ctrl_ptr(inst->ctx, V4L2_CID_STATELESS_HEVC_DECODE_PARAMS);
+ if (IS_ERR(dec_params))
+ return PTR_ERR(dec_params);
+
+ src_matrix =
+ vdec_hevc_get_ctrl_ptr(inst->ctx, V4L2_CID_STATELESS_HEVC_SCALING_MATRIX);
+ if (IS_ERR(src_matrix))
+ return PTR_ERR(src_matrix);
+
+ sps = vdec_hevc_get_ctrl_ptr(inst->ctx, V4L2_CID_STATELESS_HEVC_SPS);
+ if (IS_ERR(sps))
+ return PTR_ERR(sps);
+
+ pps = vdec_hevc_get_ctrl_ptr(inst->ctx, V4L2_CID_STATELESS_HEVC_PPS);
+ if (IS_ERR(pps))
+ return PTR_ERR(pps);
+
+ vdec_hevc_copy_sps_params(&slice_param->sps, sps);
+ vdec_hevc_copy_pps_params(&slice_param->pps, pps);
+ vdec_hevc_copy_scaling_matrix(&slice_param->scaling_matrix, src_matrix);
+
+ memcpy(&share_info->sps, sps, sizeof(*sps));
+ memcpy(&share_info->dec_params, dec_params, sizeof(*dec_params));
+
+ slice_param->decode_params.num_poc_st_curr_before = dec_params->num_poc_st_curr_before;
+ slice_param->decode_params.num_poc_st_curr_after = dec_params->num_poc_st_curr_after;
+ slice_param->decode_params.num_poc_lt_curr = dec_params->num_poc_lt_curr;
+ slice_param->decode_params.num_delta_pocs_of_ref_rps_idx =
+ dec_params->num_delta_pocs_of_ref_rps_idx;
+
+ return 0;
+}
+
+static void vdec_hevc_slice_fill_decode_reflist(struct vdec_hevc_slice_inst *inst,
+ struct vdec_hevc_slice_lat_dec_param *slice_param,
+ struct vdec_hevc_slice_share_info *share_info)
+{
+ struct v4l2_ctrl_hevc_decode_params *dec_params = &share_info->dec_params;
+
+ vdec_hevc_copy_decode_params(&slice_param->decode_params, dec_params,
+ share_info->dec_params.dpb);
+
+ vdec_hevc_fill_dpb_info(inst->ctx, &slice_param->decode_params,
+ slice_param->hevc_dpb_info);
+}
+
+static int vdec_hevc_slice_alloc_mv_buf(struct vdec_hevc_slice_inst *inst,
+ struct vdec_pic_info *pic)
+{
+ unsigned int buf_sz = vdec_hevc_get_mv_buf_size(pic->buf_w, pic->buf_h);
+ struct mtk_vcodec_mem *mem;
+ int i, err;
+
+ mtk_v4l2_debug(3, "allocate mv buffer size = 0x%x", buf_sz);
+ for (i = 0; i < HEVC_MAX_MV_NUM; i++) {
+ mem = &inst->mv_buf[i];
+ if (mem->va)
+ mtk_vcodec_mem_free(inst->ctx, mem);
+ mem->size = buf_sz;
+ err = mtk_vcodec_mem_alloc(inst->ctx, mem);
+ if (err) {
+ mtk_vcodec_err(inst, "failed to allocate mv buf");
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static void vdec_hevc_slice_free_mv_buf(struct vdec_hevc_slice_inst *inst)
+{
+ int i;
+ struct mtk_vcodec_mem *mem;
+
+ for (i = 0; i < HEVC_MAX_MV_NUM; i++) {
+ mem = &inst->mv_buf[i];
+ if (mem->va)
+ mtk_vcodec_mem_free(inst->ctx, mem);
+ }
+}
+
+static void vdec_hevc_slice_get_pic_info(struct vdec_hevc_slice_inst *inst)
+{
+ struct mtk_vcodec_ctx *ctx = inst->ctx;
+ u32 data[3];
+
+ data[0] = ctx->picinfo.pic_w;
+ data[1] = ctx->picinfo.pic_h;
+ data[2] = ctx->capture_fourcc;
+ vpu_dec_get_param(&inst->vpu, data, 3, GET_PARAM_PIC_INFO);
+
+ ctx->picinfo.buf_w = ALIGN(ctx->picinfo.pic_w, VCODEC_DEC_ALIGNED_64);
+ ctx->picinfo.buf_h = ALIGN(ctx->picinfo.pic_h, VCODEC_DEC_ALIGNED_64);
+ ctx->picinfo.fb_sz[0] = inst->vpu.fb_sz[0];
+ ctx->picinfo.fb_sz[1] = inst->vpu.fb_sz[1];
+ inst->cap_num_planes =
+ ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes;
+
+ mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
+ ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+ ctx->picinfo.buf_w, ctx->picinfo.buf_h);
+ mtk_vcodec_debug(inst, "Y/C(%d, %d)", ctx->picinfo.fb_sz[0],
+ ctx->picinfo.fb_sz[1]);
+
+ if (ctx->last_decoded_picinfo.pic_w != ctx->picinfo.pic_w ||
+ ctx->last_decoded_picinfo.pic_h != ctx->picinfo.pic_h) {
+ inst->resolution_changed = true;
+ if (ctx->last_decoded_picinfo.buf_w != ctx->picinfo.buf_w ||
+ ctx->last_decoded_picinfo.buf_h != ctx->picinfo.buf_h)
+ inst->realloc_mv_buf = true;
+
+ mtk_v4l2_debug(1, "resChg: (%d %d) : old(%d, %d) -> new(%d, %d)",
+ inst->resolution_changed,
+ inst->realloc_mv_buf,
+ ctx->last_decoded_picinfo.pic_w,
+ ctx->last_decoded_picinfo.pic_h,
+ ctx->picinfo.pic_w, ctx->picinfo.pic_h);
+ }
+}
+
+static void vdec_hevc_slice_get_crop_info(struct vdec_hevc_slice_inst *inst,
+ struct v4l2_rect *cr)
+{
+ cr->left = 0;
+ cr->top = 0;
+ cr->width = inst->ctx->picinfo.pic_w;
+ cr->height = inst->ctx->picinfo.pic_h;
+
+ mtk_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d",
+ cr->left, cr->top, cr->width, cr->height);
+}
+
+static int vdec_hevc_slice_setup_lat_buffer(struct vdec_hevc_slice_inst *inst,
+ struct mtk_vcodec_mem *bs,
+ struct vdec_lat_buf *lat_buf,
+ bool *res_chg)
+{
+ struct mtk_vcodec_mem *mem;
+ struct mtk_video_dec_buf *src_buf_info;
+ struct vdec_hevc_slice_share_info *share_info;
+ int i, err;
+
+ inst->vsi->bs.dma_addr = (u64)bs->dma_addr;
+ inst->vsi->bs.size = bs->size;
+
+ src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer);
+ lat_buf->src_buf_req = src_buf_info->m2m_buf.vb.vb2_buf.req_obj.req;
+ v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb, &lat_buf->ts_info, true);
+
+ *res_chg = inst->resolution_changed;
+ if (inst->resolution_changed) {
+ mtk_vcodec_debug(inst, "- resolution changed -");
+ if (inst->realloc_mv_buf) {
+ err = vdec_hevc_slice_alloc_mv_buf(inst, &inst->ctx->picinfo);
+ inst->realloc_mv_buf = false;
+ if (err)
+ return err;
+ }
+ inst->resolution_changed = false;
+ }
+
+ for (i = 0; i < HEVC_MAX_MV_NUM; i++) {
+ mem = &inst->mv_buf[i];
+ inst->vsi->mv_buf_dma[i].dma_addr = mem->dma_addr;
+ inst->vsi->mv_buf_dma[i].size = mem->size;
+ }
+
+ inst->vsi->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
+ inst->vsi->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size;
+
+ inst->vsi->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr;
+ inst->vsi->err_map.size = lat_buf->wdma_err_addr.size;
+
+ inst->vsi->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr;
+ inst->vsi->slice_bc.size = lat_buf->slice_bc_addr.size;
+
+ inst->vsi->trans.dma_addr_end = inst->ctx->msg_queue.wdma_rptr_addr;
+ inst->vsi->trans.dma_addr = inst->ctx->msg_queue.wdma_wptr_addr;
+
+ share_info = lat_buf->private_data;
+ share_info->trans.dma_addr = inst->vsi->trans.dma_addr;
+ share_info->trans.dma_addr_end = inst->vsi->trans.dma_addr_end;
+
+ mtk_vcodec_debug(inst, "lat: ube addr/size(0x%llx 0x%llx) err:0x%llx",
+ inst->vsi->ube.buf,
+ inst->vsi->ube.padding,
+ inst->vsi->err_map.buf);
+
+ mtk_vcodec_debug(inst, "slice addr/size(0x%llx 0x%llx) trans start/end((0x%llx 0x%llx))",
+ inst->vsi->slice_bc.buf,
+ inst->vsi->slice_bc.padding,
+ inst->vsi->trans.buf,
+ inst->vsi->trans.padding);
+
+ return 0;
+}
+
+static int vdec_hevc_slice_setup_core_buffer(struct vdec_hevc_slice_inst *inst,
+ struct vdec_hevc_slice_share_info *share_info,
+ struct vdec_lat_buf *lat_buf)
+{
+ struct mtk_vcodec_mem *mem;
+ struct mtk_vcodec_ctx *ctx = inst->ctx;
+ struct vb2_v4l2_buffer *vb2_v4l2;
+ struct vdec_fb *fb;
+ u64 y_fb_dma, c_fb_dma;
+ int i;
+
+ fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx);
+ if (!fb) {
+ mtk_vcodec_err(inst, "fb buffer is NULL");
+ return -EBUSY;
+ }
+
+ y_fb_dma = (u64)fb->base_y.dma_addr;
+ if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1)
+ c_fb_dma =
+ y_fb_dma + inst->ctx->picinfo.buf_w * inst->ctx->picinfo.buf_h;
+ else
+ c_fb_dma = (u64)fb->base_c.dma_addr;
+
+ mtk_vcodec_debug(inst, "[hevc-core] y/c addr = 0x%llx 0x%llx", y_fb_dma,
+ c_fb_dma);
+
+ inst->vsi_core->fb.y.dma_addr = y_fb_dma;
+ inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[0];
+ inst->vsi_core->fb.c.dma_addr = c_fb_dma;
+ inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[1];
+
+ inst->vsi_core->dec.vdec_fb_va = (unsigned long)fb;
+
+ inst->vsi_core->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
+ inst->vsi_core->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size;
+
+ inst->vsi_core->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr;
+ inst->vsi_core->err_map.size = lat_buf->wdma_err_addr.size;
+
+ inst->vsi_core->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr;
+ inst->vsi_core->slice_bc.size = lat_buf->slice_bc_addr.size;
+
+ inst->vsi_core->trans.dma_addr = share_info->trans.dma_addr;
+ inst->vsi_core->trans.dma_addr_end = share_info->trans.dma_addr_end;
+
+ inst->vsi_core->wrap.dma_addr = inst->wrap_addr.dma_addr;
+ inst->vsi_core->wrap.size = inst->wrap_addr.size;
+
+ for (i = 0; i < HEVC_MAX_MV_NUM; i++) {
+ mem = &inst->mv_buf[i];
+ inst->vsi_core->mv_buf_dma[i].dma_addr = mem->dma_addr;
+ inst->vsi_core->mv_buf_dma[i].size = mem->size;
+ }
+
+ vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, vb2_v4l2, true);
+
+ return 0;
+}
+
+static int vdec_hevc_slice_init(struct mtk_vcodec_ctx *ctx)
+{
+ struct vdec_hevc_slice_inst *inst;
+ int err, vsi_size;
+
+ inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+ if (!inst)
+ return -ENOMEM;
+
+ inst->ctx = ctx;
+
+ inst->vpu.id = SCP_IPI_VDEC_LAT;
+ inst->vpu.core_id = SCP_IPI_VDEC_CORE;
+ inst->vpu.ctx = ctx;
+ inst->vpu.codec_type = ctx->current_codec;
+ inst->vpu.capture_type = ctx->capture_fourcc;
+
+ ctx->drv_handle = inst;
+ err = vpu_dec_init(&inst->vpu);
+ if (err) {
+ mtk_vcodec_err(inst, "vdec_hevc init err=%d", err);
+ goto error_free_inst;
+ }
+
+ vsi_size = round_up(sizeof(struct vdec_hevc_slice_vsi), VCODEC_DEC_ALIGNED_64);
+ inst->vsi = inst->vpu.vsi;
+ inst->vsi_core =
+ (struct vdec_hevc_slice_vsi *)(((char *)inst->vpu.vsi) + vsi_size);
+
+ inst->resolution_changed = true;
+ inst->realloc_mv_buf = true;
+
+ inst->wrap_addr.size = VDEC_HEVC_WRAP_SZ;
+ err = mtk_vcodec_mem_alloc(ctx, &inst->wrap_addr);
+ if (err)
+ goto error_free_inst;
+
+ mtk_vcodec_debug(inst, "lat struct size = %d,%d,%d,%d vsi: %d\n",
+ (int)sizeof(struct mtk_hevc_sps_param),
+ (int)sizeof(struct mtk_hevc_pps_param),
+ (int)sizeof(struct vdec_hevc_slice_lat_dec_param),
+ (int)sizeof(struct mtk_hevc_dpb_info),
+ vsi_size);
+ mtk_vcodec_debug(inst, "lat hevc instance >> %p, codec_type = 0x%x",
+ inst, inst->vpu.codec_type);
+
+ return 0;
+error_free_inst:
+ kfree(inst);
+ return err;
+}
+
+static void vdec_hevc_slice_deinit(void *h_vdec)
+{
+ struct vdec_hevc_slice_inst *inst = h_vdec;
+ struct mtk_vcodec_mem *mem;
+
+ mtk_vcodec_debug_enter(inst);
+
+ vpu_dec_deinit(&inst->vpu);
+ vdec_hevc_slice_free_mv_buf(inst);
+
+ mem = &inst->wrap_addr;
+ if (mem->va)
+ mtk_vcodec_mem_free(inst->ctx, mem);
+
+ vdec_msg_queue_deinit(&inst->ctx->msg_queue, inst->ctx);
+ kfree(inst);
+}
+
+static int vdec_hevc_slice_core_decode(struct vdec_lat_buf *lat_buf)
+{
+ int err, timeout;
+ struct mtk_vcodec_ctx *ctx = lat_buf->ctx;
+ struct vdec_hevc_slice_inst *inst = ctx->drv_handle;
+ struct vdec_hevc_slice_share_info *share_info = lat_buf->private_data;
+ struct vdec_vpu_inst *vpu = &inst->vpu;
+
+ mtk_vcodec_debug(inst, "[hevc-core] vdec_hevc core decode");
+ memcpy(&inst->vsi_core->hevc_slice_params, &share_info->hevc_slice_params,
+ sizeof(share_info->hevc_slice_params));
+
+ err = vdec_hevc_slice_setup_core_buffer(inst, share_info, lat_buf);
+ if (err)
+ goto vdec_dec_end;
+
+ vdec_hevc_slice_fill_decode_reflist(inst, &inst->vsi_core->hevc_slice_params,
+ share_info);
+ err = vpu_dec_core(vpu);
+ if (err) {
+ mtk_vcodec_err(inst, "core decode err=%d", err);
+ goto vdec_dec_end;
+ }
+
+ /* wait decoder done interrupt */
+ timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
+ WAIT_INTR_TIMEOUT_MS, MTK_VDEC_CORE);
+ if (timeout)
+ mtk_vcodec_err(inst, "core decode timeout: pic_%d",
+ ctx->decoded_frame_cnt);
+ inst->vsi_core->dec.timeout = !!timeout;
+
+ vpu_dec_core_end(vpu);
+ mtk_vcodec_debug(inst, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ ctx->decoded_frame_cnt,
+ inst->vsi_core->dec.crc[0], inst->vsi_core->dec.crc[1],
+ inst->vsi_core->dec.crc[2], inst->vsi_core->dec.crc[3],
+ inst->vsi_core->dec.crc[4], inst->vsi_core->dec.crc[5],
+ inst->vsi_core->dec.crc[6], inst->vsi_core->dec.crc[7]);
+
+vdec_dec_end:
+ vdec_msg_queue_update_ube_rptr(&lat_buf->ctx->msg_queue, share_info->trans.dma_addr_end);
+ ctx->dev->vdec_pdata->cap_to_disp(ctx, !!err, lat_buf->src_buf_req);
+ mtk_vcodec_debug(inst, "core decode done err=%d", err);
+ ctx->decoded_frame_cnt++;
+ return 0;
+}
+
+static int vdec_hevc_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
+ struct vdec_fb *fb, bool *res_chg)
+{
+ struct vdec_hevc_slice_inst *inst = h_vdec;
+ struct vdec_vpu_inst *vpu = &inst->vpu;
+ int err, timeout = 0;
+ unsigned int data[2];
+ struct vdec_lat_buf *lat_buf;
+ struct vdec_hevc_slice_share_info *share_info;
+
+ if (vdec_msg_queue_init(&inst->ctx->msg_queue, inst->ctx,
+ vdec_hevc_slice_core_decode,
+ sizeof(*share_info)))
+ return -ENOMEM;
+
+ /* bs NULL means flush decoder */
+ if (!bs) {
+ vdec_msg_queue_wait_lat_buf_full(&inst->ctx->msg_queue);
+ return vpu_dec_reset(vpu);
+ }
+
+ lat_buf = vdec_msg_queue_dqbuf(&inst->ctx->msg_queue.lat_ctx);
+ if (!lat_buf) {
+ mtk_vcodec_debug(inst, "failed to get lat buffer");
+ return -EAGAIN;
+ }
+
+ share_info = lat_buf->private_data;
+ err = vdec_hevc_slice_fill_decode_parameters(inst, share_info);
+ if (err)
+ goto err_free_fb_out;
+
+ err = vdec_hevc_slice_setup_lat_buffer(inst, bs, lat_buf, res_chg);
+ if (err)
+ goto err_free_fb_out;
+
+ err = vpu_dec_start(vpu, data, 2);
+ if (err) {
+ mtk_vcodec_debug(inst, "lat decode err: %d", err);
+ goto err_free_fb_out;
+ }
+
+ if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
+ memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params,
+ sizeof(share_info->hevc_slice_params));
+ vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
+ }
+
+ /* wait decoder done interrupt */
+ timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
+ WAIT_INTR_TIMEOUT_MS, MTK_VDEC_LAT0);
+ if (timeout)
+ mtk_vcodec_err(inst, "lat decode timeout: pic_%d", inst->slice_dec_num);
+ inst->vsi->dec.timeout = !!timeout;
+
+ err = vpu_dec_end(vpu);
+ if (err == SLICE_HEADER_FULL || err == TRANS_BUFFER_FULL) {
+ if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability))
+ vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf);
+ inst->slice_dec_num++;
+ mtk_vcodec_err(inst, "lat dec fail: pic_%d err:%d", inst->slice_dec_num, err);
+ return -EINVAL;
+ }
+
+ share_info->trans.dma_addr_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
+ inst->vsi->dec.wdma_end_addr_offset;
+ vdec_msg_queue_update_ube_wptr(&lat_buf->ctx->msg_queue, share_info->trans.dma_addr_end);
+
+ if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
+ memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params,
+ sizeof(share_info->hevc_slice_params));
+ vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
+ }
+ mtk_vcodec_debug(inst, "dec num: %d lat crc: 0x%x 0x%x 0x%x", inst->slice_dec_num,
+ inst->vsi->dec.crc[0], inst->vsi->dec.crc[1], inst->vsi->dec.crc[2]);
+
+ inst->slice_dec_num++;
+ return 0;
+err_free_fb_out:
+ vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf);
+ mtk_vcodec_err(inst, "slice dec number: %d err: %d", inst->slice_dec_num, err);
+ return err;
+}
+
+static int vdec_hevc_slice_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
+ struct vdec_fb *unused, bool *res_chg)
+{
+ struct vdec_hevc_slice_inst *inst = h_vdec;
+
+ if (!h_vdec || inst->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_PURE_SINGLE_CORE)
+ return -EINVAL;
+
+ return vdec_hevc_slice_lat_decode(h_vdec, bs, unused, res_chg);
+}
+
+static int vdec_hevc_slice_get_param(void *h_vdec, enum vdec_get_param_type type,
+ void *out)
+{
+ struct vdec_hevc_slice_inst *inst = h_vdec;
+
+ switch (type) {
+ case GET_PARAM_PIC_INFO:
+ vdec_hevc_slice_get_pic_info(inst);
+ break;
+ case GET_PARAM_DPB_SIZE:
+ *(unsigned int *)out = 6;
+ break;
+ case GET_PARAM_CROP_INFO:
+ vdec_hevc_slice_get_crop_info(inst, out);
+ break;
+ default:
+ mtk_vcodec_err(inst, "invalid get parameter type=%d", type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+const struct vdec_common_if vdec_hevc_slice_multi_if = {
+ .init = vdec_hevc_slice_init,
+ .decode = vdec_hevc_slice_decode,
+ .get_param = vdec_hevc_slice_get_param,
+ .deinit = vdec_hevc_slice_deinit,
+};
diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
index cf16cf2807f0..c2f90848f498 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
@@ -2069,7 +2069,7 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
lat_buf = vdec_msg_queue_dqbuf(&instance->ctx->msg_queue.lat_ctx);
if (!lat_buf) {
- mtk_vcodec_err(instance, "Failed to get VP9 lat buf\n");
+ mtk_vcodec_debug(instance, "Failed to get VP9 lat buf\n");
return -EAGAIN;
}
pfc = (struct vdec_vp9_slice_pfc *)lat_buf->private_data;
@@ -2119,7 +2119,7 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
vdec_msg_queue_update_ube_wptr(&ctx->msg_queue,
vsi->trans.dma_addr_end +
ctx->msg_queue.wdma_addr.dma_addr);
- vdec_msg_queue_qbuf(&ctx->dev->msg_queue_core_ctx, lat_buf);
+ vdec_msg_queue_qbuf(&ctx->msg_queue.core_ctx, lat_buf);
return 0;
err_free_fb_out:
diff --git a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c
index f3807f03d880..06d393174cc2 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c
@@ -49,6 +49,14 @@ int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
ctx->dec_if = &vdec_vp9_slice_lat_if;
ctx->hw_id = IS_VDEC_LAT_ARCH(hw_arch) ? MTK_VDEC_LAT0 : MTK_VDEC_CORE;
break;
+ case V4L2_PIX_FMT_HEVC_SLICE:
+ ctx->dec_if = &vdec_hevc_slice_multi_if;
+ ctx->hw_id = MTK_VDEC_LAT0;
+ break;
+ case V4L2_PIX_FMT_AV1_FRAME:
+ ctx->dec_if = &vdec_av1_slice_lat_if;
+ ctx->hw_id = MTK_VDEC_LAT0;
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h
index 076306ff2dd4..a8da6a59a6a5 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h
+++ b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h
@@ -61,6 +61,8 @@ extern const struct vdec_common_if vdec_vp8_if;
extern const struct vdec_common_if vdec_vp8_slice_if;
extern const struct vdec_common_if vdec_vp9_if;
extern const struct vdec_common_if vdec_vp9_slice_lat_if;
+extern const struct vdec_common_if vdec_hevc_slice_multi_if;
+extern const struct vdec_common_if vdec_av1_slice_lat_if;
/**
* vdec_if_init() - initialize decode driver
diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
index f3073d1e7f42..f555341ae708 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
@@ -20,6 +20,9 @@
/* the size used to store avc error information */
#define VDEC_ERR_MAP_SZ_AVC (17 * SZ_1K)
+#define VDEC_RD_MV_BUFFER_SZ (((SZ_4K * 2304 >> 4) + SZ_1K) << 1)
+#define VDEC_LAT_TILE_SZ (64 * V4L2_AV1_MAX_TILE_COUNT)
+
/* core will read the trans buffer which decoded by lat to decode again.
* The trans buffer size of FHD and 4K bitstreams are different.
*/
@@ -71,7 +74,6 @@ static void vdec_msg_queue_dec(struct vdec_msg_queue *msg_queue, int hardware_in
int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf *buf)
{
struct list_head *head;
- int status;
head = vdec_get_buf_list(msg_ctx->hardware_index, buf);
if (!head) {
@@ -87,12 +89,9 @@ int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf
if (msg_ctx->hardware_index != MTK_VDEC_CORE) {
wake_up_all(&msg_ctx->ready_to_use);
} else {
- if (buf->ctx->msg_queue.core_work_cnt <
- atomic_read(&buf->ctx->msg_queue.core_list_cnt)) {
- status = queue_work(buf->ctx->dev->core_workqueue,
- &buf->ctx->msg_queue.core_work);
- if (status)
- buf->ctx->msg_queue.core_work_cnt++;
+ if (!(buf->ctx->msg_queue.status & CONTEXT_LIST_QUEUED)) {
+ queue_work(buf->ctx->dev->core_workqueue, &buf->ctx->msg_queue.core_work);
+ buf->ctx->msg_queue.status |= CONTEXT_LIST_QUEUED;
}
}
@@ -181,49 +180,23 @@ void vdec_msg_queue_update_ube_wptr(struct vdec_msg_queue *msg_queue, uint64_t u
bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
{
- struct vdec_lat_buf *buf, *tmp;
- struct list_head *list_core[3];
- struct vdec_msg_queue_ctx *core_ctx;
- int ret, i, in_core_count = 0, count = 0;
- long timeout_jiff;
-
- core_ctx = &msg_queue->ctx->dev->msg_queue_core_ctx;
- spin_lock(&core_ctx->ready_lock);
- list_for_each_entry_safe(buf, tmp, &core_ctx->ready_queue, core_list) {
- if (buf && buf->ctx == msg_queue->ctx) {
- list_core[in_core_count++] = &buf->core_list;
- list_del(&buf->core_list);
- }
- }
-
- for (i = 0; i < in_core_count; i++) {
- list_add(list_core[in_core_count - (1 + i)], &core_ctx->ready_queue);
- queue_work(msg_queue->ctx->dev->core_workqueue, &msg_queue->core_work);
- }
- spin_unlock(&core_ctx->ready_lock);
-
- timeout_jiff = msecs_to_jiffies(1000 * (NUM_BUFFER_COUNT + 2));
- ret = wait_event_timeout(msg_queue->ctx->msg_queue.core_dec_done,
- msg_queue->lat_ctx.ready_num == NUM_BUFFER_COUNT,
- timeout_jiff);
- if (ret) {
- mtk_v4l2_debug(3, "success to get lat buf: %d",
- msg_queue->lat_ctx.ready_num);
+ if (atomic_read(&msg_queue->lat_list_cnt) == NUM_BUFFER_COUNT) {
+ mtk_v4l2_debug(3, "wait buf full: list(%d %d) ready_num:%d status:%d",
+ atomic_read(&msg_queue->lat_list_cnt),
+ atomic_read(&msg_queue->core_list_cnt),
+ msg_queue->lat_ctx.ready_num,
+ msg_queue->status);
return true;
}
- spin_lock(&core_ctx->ready_lock);
- list_for_each_entry_safe(buf, tmp, &core_ctx->ready_queue, core_list) {
- if (buf && buf->ctx == msg_queue->ctx) {
- count++;
- list_del(&buf->core_list);
- }
- }
- spin_unlock(&core_ctx->ready_lock);
+ msg_queue->flush_done = false;
+ vdec_msg_queue_qbuf(&msg_queue->core_ctx, &msg_queue->empty_lat_buf);
+ wait_event(msg_queue->core_dec_done, msg_queue->flush_done);
- mtk_v4l2_err("failed with lat buf isn't full: list(%d %d) count:%d",
- atomic_read(&msg_queue->lat_list_cnt),
- atomic_read(&msg_queue->core_list_cnt), count);
+ mtk_v4l2_debug(3, "flush done => ready_num:%d status:%d list(%d %d)",
+ msg_queue->lat_ctx.ready_num, msg_queue->status,
+ atomic_read(&msg_queue->lat_list_cnt),
+ atomic_read(&msg_queue->core_list_cnt));
return false;
}
@@ -249,8 +222,18 @@ void vdec_msg_queue_deinit(struct vdec_msg_queue *msg_queue,
if (mem->va)
mtk_vcodec_mem_free(ctx, mem);
+ mem = &lat_buf->rd_mv_addr;
+ if (mem->va)
+ mtk_vcodec_mem_free(ctx, mem);
+
+ mem = &lat_buf->tile_addr;
+ if (mem->va)
+ mtk_vcodec_mem_free(ctx, mem);
+
kfree(lat_buf->private_data);
}
+
+ cancel_work_sync(&msg_queue->core_work);
}
static void vdec_msg_queue_core_work(struct work_struct *work)
@@ -261,12 +244,23 @@ static void vdec_msg_queue_core_work(struct work_struct *work)
container_of(msg_queue, struct mtk_vcodec_ctx, msg_queue);
struct mtk_vcodec_dev *dev = ctx->dev;
struct vdec_lat_buf *lat_buf;
- int status;
- lat_buf = vdec_msg_queue_dqbuf(&dev->msg_queue_core_ctx);
+ spin_lock(&msg_queue->core_ctx.ready_lock);
+ ctx->msg_queue.status &= ~CONTEXT_LIST_QUEUED;
+ spin_unlock(&msg_queue->core_ctx.ready_lock);
+
+ lat_buf = vdec_msg_queue_dqbuf(&msg_queue->core_ctx);
if (!lat_buf)
return;
+ if (lat_buf->is_last_frame) {
+ ctx->msg_queue.status = CONTEXT_LIST_DEC_DONE;
+ msg_queue->flush_done = true;
+ wake_up(&ctx->msg_queue.core_dec_done);
+
+ return;
+ }
+
ctx = lat_buf->ctx;
mtk_vcodec_dec_enable_hardware(ctx, MTK_VDEC_CORE);
mtk_vcodec_set_curr_ctx(dev, ctx, MTK_VDEC_CORE);
@@ -277,18 +271,13 @@ static void vdec_msg_queue_core_work(struct work_struct *work)
mtk_vcodec_dec_disable_hardware(ctx, MTK_VDEC_CORE);
vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf);
- wake_up_all(&ctx->msg_queue.core_dec_done);
- spin_lock(&dev->msg_queue_core_ctx.ready_lock);
- lat_buf->ctx->msg_queue.core_work_cnt--;
-
- if (lat_buf->ctx->msg_queue.core_work_cnt <
- atomic_read(&lat_buf->ctx->msg_queue.core_list_cnt)) {
- status = queue_work(lat_buf->ctx->dev->core_workqueue,
- &lat_buf->ctx->msg_queue.core_work);
- if (status)
- lat_buf->ctx->msg_queue.core_work_cnt++;
+ if (!(ctx->msg_queue.status & CONTEXT_LIST_QUEUED) &&
+ atomic_read(&msg_queue->core_list_cnt)) {
+ spin_lock(&msg_queue->core_ctx.ready_lock);
+ ctx->msg_queue.status |= CONTEXT_LIST_QUEUED;
+ spin_unlock(&msg_queue->core_ctx.ready_lock);
+ queue_work(ctx->dev->core_workqueue, &msg_queue->core_work);
}
- spin_unlock(&dev->msg_queue_core_ctx.ready_lock);
}
int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
@@ -302,14 +291,14 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
if (msg_queue->wdma_addr.size)
return 0;
- msg_queue->ctx = ctx;
- msg_queue->core_work_cnt = 0;
vdec_msg_queue_init_ctx(&msg_queue->lat_ctx, MTK_VDEC_LAT0);
+ vdec_msg_queue_init_ctx(&msg_queue->core_ctx, MTK_VDEC_CORE);
INIT_WORK(&msg_queue->core_work, vdec_msg_queue_core_work);
atomic_set(&msg_queue->lat_list_cnt, 0);
atomic_set(&msg_queue->core_list_cnt, 0);
init_waitqueue_head(&msg_queue->core_dec_done);
+ msg_queue->status = CONTEXT_LIST_EMPTY;
msg_queue->wdma_addr.size =
vde_msg_queue_get_trans_size(ctx->picinfo.buf_w,
@@ -322,6 +311,10 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
msg_queue->wdma_rptr_addr = msg_queue->wdma_addr.dma_addr;
msg_queue->wdma_wptr_addr = msg_queue->wdma_addr.dma_addr;
+ msg_queue->empty_lat_buf.ctx = ctx;
+ msg_queue->empty_lat_buf.core_decode = NULL;
+ msg_queue->empty_lat_buf.is_last_frame = true;
+
for (i = 0; i < NUM_BUFFER_COUNT; i++) {
lat_buf = &msg_queue->lat_buf[i];
@@ -339,6 +332,22 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
goto mem_alloc_err;
}
+ if (ctx->current_codec == V4L2_PIX_FMT_AV1_FRAME) {
+ lat_buf->rd_mv_addr.size = VDEC_RD_MV_BUFFER_SZ;
+ err = mtk_vcodec_mem_alloc(ctx, &lat_buf->rd_mv_addr);
+ if (err) {
+ mtk_v4l2_err("failed to allocate rd_mv_addr buf[%d]", i);
+ return -ENOMEM;
+ }
+
+ lat_buf->tile_addr.size = VDEC_LAT_TILE_SZ;
+ err = mtk_vcodec_mem_alloc(ctx, &lat_buf->tile_addr);
+ if (err) {
+ mtk_v4l2_err("failed to allocate tile_addr buf[%d]", i);
+ return -ENOMEM;
+ }
+ }
+
lat_buf->private_data = kzalloc(private_size, GFP_KERNEL);
if (!lat_buf->private_data) {
err = -ENOMEM;
@@ -347,6 +356,7 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
lat_buf->ctx = ctx;
lat_buf->core_decode = core_decode;
+ lat_buf->is_last_frame = false;
err = vdec_msg_queue_qbuf(&msg_queue->lat_ctx, lat_buf);
if (err) {
mtk_v4l2_err("failed to qbuf buf[%d]", i);
diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
index a5d44bc97c16..2a745e902ad1 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
+++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
@@ -22,6 +22,18 @@ struct mtk_vcodec_dev;
typedef int (*core_decode_cb_t)(struct vdec_lat_buf *lat_buf);
/**
+ * enum core_ctx_status - Context decode status for core hardwre.
+ * @CONTEXT_LIST_EMPTY: No buffer queued on core hardware(must always be 0)
+ * @CONTEXT_LIST_QUEUED: Buffer queued to core work list
+ * @CONTEXT_LIST_DEC_DONE: context decode done
+ */
+enum core_ctx_status {
+ CONTEXT_LIST_EMPTY = 0,
+ CONTEXT_LIST_QUEUED,
+ CONTEXT_LIST_DEC_DONE,
+};
+
+/**
* struct vdec_msg_queue_ctx - represents a queue for buffers ready to be processed
* @ready_to_use: ready used queue used to signalize when get a job queue
* @ready_queue: list of ready lat buffer queues
@@ -42,6 +54,8 @@ struct vdec_msg_queue_ctx {
* struct vdec_lat_buf - lat buffer message used to store lat info for core decode
* @wdma_err_addr: wdma error address used for lat hardware
* @slice_bc_addr: slice bc address used for lat hardware
+ * @rd_mv_addr: mv addr for av1 lat hardware output, core hardware input
+ * @tile_addr: tile buffer for av1 core input
* @ts_info: need to set timestamp from output to capture
* @src_buf_req: output buffer media request object
*
@@ -50,10 +64,14 @@ struct vdec_msg_queue_ctx {
* @core_decode: different codec use different decode callback function
* @lat_list: add lat buffer to lat head list
* @core_list: add lat buffer to core head list
+ *
+ * @is_last_frame: meaning this buffer is the last frame
*/
struct vdec_lat_buf {
struct mtk_vcodec_mem wdma_err_addr;
struct mtk_vcodec_mem slice_bc_addr;
+ struct mtk_vcodec_mem rd_mv_addr;
+ struct mtk_vcodec_mem tile_addr;
struct vb2_v4l2_buffer ts_info;
struct media_request *src_buf_req;
@@ -62,6 +80,8 @@ struct vdec_lat_buf {
core_decode_cb_t core_decode;
struct list_head lat_list;
struct list_head core_list;
+
+ bool is_last_frame;
};
/**
@@ -72,12 +92,14 @@ struct vdec_lat_buf {
* @wdma_wptr_addr: ube write point
* @core_work: core hardware work
* @lat_ctx: used to store lat buffer list
- * @ctx: point to mtk_vcodec_ctx
+ * @core_ctx: used to store core buffer list
*
* @lat_list_cnt: used to record each instance lat list count
* @core_list_cnt: used to record each instance core list count
+ * @flush_done: core flush done status
+ * @empty_lat_buf: the last lat buf used to flush decode
* @core_dec_done: core work queue decode done event
- * @core_work_cnt: the number of core work in work queue
+ * @status: current context decode status for core hardware
*/
struct vdec_msg_queue {
struct vdec_lat_buf lat_buf[NUM_BUFFER_COUNT];
@@ -88,12 +110,14 @@ struct vdec_msg_queue {
struct work_struct core_work;
struct vdec_msg_queue_ctx lat_ctx;
- struct mtk_vcodec_ctx *ctx;
+ struct vdec_msg_queue_ctx core_ctx;
atomic_t lat_list_cnt;
atomic_t core_list_cnt;
+ bool flush_done;
+ struct vdec_lat_buf empty_lat_buf;
wait_queue_head_t core_dec_done;
- int core_work_cnt;
+ int status;
};
/**
diff --git a/drivers/media/platform/mediatek/vpu/mtk_vpu.c b/drivers/media/platform/mediatek/vpu/mtk_vpu.c
index 5e2bc286f168..4c8f5296d120 100644
--- a/drivers/media/platform/mediatek/vpu/mtk_vpu.c
+++ b/drivers/media/platform/mediatek/vpu/mtk_vpu.c
@@ -562,15 +562,17 @@ static int load_requested_vpu(struct mtk_vpu *vpu,
int vpu_load_firmware(struct platform_device *pdev)
{
struct mtk_vpu *vpu;
- struct device *dev = &pdev->dev;
+ struct device *dev;
struct vpu_run *run;
int ret;
if (!pdev) {
- dev_err(dev, "VPU platform device is invalid\n");
+ pr_err("VPU platform device is invalid\n");
return -EINVAL;
}
+ dev = &pdev->dev;
+
vpu = platform_get_drvdata(pdev);
run = &vpu->run;
@@ -1016,6 +1018,7 @@ static int mtk_vpu_resume(struct device *dev)
clk_prepare(vpu->clk);
ret = vpu_clock_enable(vpu);
if (ret) {
+ clk_unprepare(vpu->clk);
dev_err(dev, "failed to enable vpu clock\n");
return ret;
}
diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c
index b701e823436a..0bd2613b9320 100644
--- a/drivers/media/platform/nxp/imx7-media-csi.c
+++ b/drivers/media/platform/nxp/imx7-media-csi.c
@@ -1014,39 +1014,6 @@ static int imx7_csi_enum_mbus_formats(u32 *code, u32 index)
return -EINVAL;
}
-static int imx7_csi_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
- const struct v4l2_mbus_framefmt *mbus,
- const struct imx7_csi_pixfmt *cc)
-{
- u32 width;
- u32 stride;
-
- if (!cc) {
- cc = imx7_csi_find_mbus_format(mbus->code);
- if (!cc)
- return -EINVAL;
- }
-
- /* Round up width for minimum burst size */
- width = round_up(mbus->width, 8);
-
- /* Round up stride for IDMAC line start address alignment */
- stride = round_up((width * cc->bpp) >> 3, 8);
-
- pix->width = width;
- pix->height = mbus->height;
- pix->pixelformat = cc->fourcc;
- pix->colorspace = mbus->colorspace;
- pix->xfer_func = mbus->xfer_func;
- pix->ycbcr_enc = mbus->ycbcr_enc;
- pix->quantization = mbus->quantization;
- pix->field = mbus->field;
- pix->bytesperline = stride;
- pix->sizeimage = stride * pix->height;
-
- return 0;
-}
-
/* -----------------------------------------------------------------------------
* Video Capture Device - IOCTLs
*/
@@ -1145,8 +1112,13 @@ static const struct imx7_csi_pixfmt *
__imx7_csi_video_try_fmt(struct v4l2_pix_format *pixfmt,
struct v4l2_rect *compose)
{
- struct v4l2_mbus_framefmt fmt_src;
const struct imx7_csi_pixfmt *cc;
+ u32 walign;
+
+ if (compose) {
+ compose->width = pixfmt->width;
+ compose->height = pixfmt->height;
+ }
/*
* Find the pixel format, default to the first supported format if not
@@ -1158,27 +1130,19 @@ __imx7_csi_video_try_fmt(struct v4l2_pix_format *pixfmt,
cc = imx7_csi_find_pixel_format(pixfmt->pixelformat);
}
- /* Allow IDMAC interweave but enforce field order from source. */
- if (V4L2_FIELD_IS_INTERLACED(pixfmt->field)) {
- switch (pixfmt->field) {
- case V4L2_FIELD_SEQ_TB:
- pixfmt->field = V4L2_FIELD_INTERLACED_TB;
- break;
- case V4L2_FIELD_SEQ_BT:
- pixfmt->field = V4L2_FIELD_INTERLACED_BT;
- break;
- default:
- break;
- }
- }
+ /*
+ * The width alignment is 8 bytes as indicated by the
+ * CSI_IMAG_PARA.IMAGE_WIDTH documentation. Convert it to pixels.
+ *
+ * TODO: Implement configurable stride support.
+ */
+ walign = 8 * 8 / cc->bpp;
+ v4l_bound_align_image(&pixfmt->width, 1, 0xffff, walign,
+ &pixfmt->height, 1, 0xffff, 1, 0);
- v4l2_fill_mbus_format(&fmt_src, pixfmt, 0);
- imx7_csi_mbus_fmt_to_pix_fmt(pixfmt, &fmt_src, cc);
-
- if (compose) {
- compose->width = fmt_src.width;
- compose->height = fmt_src.height;
- }
+ pixfmt->bytesperline = pixfmt->width * cc->bpp / 8;
+ pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
+ pixfmt->field = V4L2_FIELD_NONE;
return cc;
}
@@ -1606,22 +1570,14 @@ static struct imx7_csi_vb2_buffer *imx7_csi_video_next_buf(struct imx7_csi *csi)
return buf;
}
-static int imx7_csi_video_init_format(struct imx7_csi *csi)
+static void imx7_csi_video_init_format(struct imx7_csi *csi)
{
- struct v4l2_mbus_framefmt format = { };
-
- format.code = IMX7_CSI_DEF_MBUS_CODE;
- format.width = IMX7_CSI_DEF_PIX_WIDTH;
- format.height = IMX7_CSI_DEF_PIX_HEIGHT;
- format.field = V4L2_FIELD_NONE;
-
- imx7_csi_mbus_fmt_to_pix_fmt(&csi->vdev_fmt, &format, NULL);
- csi->vdev_compose.width = format.width;
- csi->vdev_compose.height = format.height;
+ struct v4l2_pix_format *pixfmt = &csi->vdev_fmt;
- csi->vdev_cc = imx7_csi_find_pixel_format(csi->vdev_fmt.pixelformat);
+ pixfmt->width = IMX7_CSI_DEF_PIX_WIDTH;
+ pixfmt->height = IMX7_CSI_DEF_PIX_HEIGHT;
- return 0;
+ csi->vdev_cc = __imx7_csi_video_try_fmt(pixfmt, &csi->vdev_compose);
}
static int imx7_csi_video_register(struct imx7_csi *csi)
@@ -1634,9 +1590,7 @@ static int imx7_csi_video_register(struct imx7_csi *csi)
vdev->v4l2_dev = v4l2_dev;
/* Initialize the default format and compose rectangle. */
- ret = imx7_csi_video_init_format(csi);
- if (ret < 0)
- return ret;
+ imx7_csi_video_init_format(csi);
/* Register the video device. */
ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c
index b5ffde46f31b..f7447b2f4d77 100644
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c
@@ -223,7 +223,7 @@ static int mxc_isi_crossbar_init_cfg(struct v4l2_subdev *sd,
route->sink_pad = i;
route->source_pad = i + xbar->num_sinks;
route->flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE;
- };
+ }
routing.num_routes = xbar->num_sources;
routing.routes = routes;
diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
index e0832f3f4f25..06c95568e5af 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe.c
@@ -1541,7 +1541,11 @@ int msm_vfe_register_entities(struct vfe_device *vfe,
}
video_out->ops = &vfe->video_ops;
- video_out->bpl_alignment = 8;
+ if (vfe->camss->version == CAMSS_845 ||
+ vfe->camss->version == CAMSS_8250)
+ video_out->bpl_alignment = 16;
+ else
+ video_out->bpl_alignment = 8;
video_out->line_based = 0;
if (i == VFE_LINE_PIX) {
video_out->bpl_alignment = 16;
diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
index 4f81669986ba..320bde0f83cb 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -83,6 +83,23 @@ struct venus_resources {
const char *fwname;
};
+enum venus_fmt {
+ VENUS_FMT_NV12 = 0,
+ VENUS_FMT_QC08C = 1,
+ VENUS_FMT_QC10C = 2,
+ VENUS_FMT_P010 = 3,
+ VENUS_FMT_H264 = 4,
+ VENUS_FMT_VP8 = 5,
+ VENUS_FMT_VP9 = 6,
+ VENUS_FMT_HEVC = 7,
+ VENUS_FMT_VC1_ANNEX_G = 8,
+ VENUS_FMT_VC1_ANNEX_L = 9,
+ VENUS_FMT_MPEG4 = 10,
+ VENUS_FMT_MPEG2 = 11,
+ VENUS_FMT_H263 = 12,
+ VENUS_FMT_XVID = 13,
+};
+
struct venus_format {
u32 pixfmt;
unsigned int num_planes;
@@ -201,6 +218,11 @@ struct venus_core {
unsigned int core0_usage_count;
unsigned int core1_usage_count;
struct dentry *root;
+ struct venus_img_version {
+ u32 major;
+ u32 minor;
+ u32 rev;
+ } venus_ver;
};
struct vdec_controls {
@@ -389,6 +411,7 @@ enum venus_inst_modes {
* @sequence_out: a sequence counter for output queue
* @m2m_dev: a reference to m2m device structure
* @m2m_ctx: a reference to m2m context structure
+ * @ctx_q_lock: a lock to serialize video device ioctl calls
* @state: current state of the instance
* @done: a completion for sync HFI operation
* @error: an error returned during last HFI sync operation
@@ -460,6 +483,7 @@ struct venus_inst {
u32 sequence_out;
struct v4l2_m2m_dev *m2m_dev;
struct v4l2_m2m_ctx *m2m_ctx;
+ struct mutex ctx_q_lock;
unsigned int state;
struct completion done;
unsigned int error;
@@ -508,4 +532,19 @@ venus_caps_by_codec(struct venus_core *core, u32 codec, u32 domain)
return NULL;
}
+static inline bool
+is_fw_rev_or_newer(struct venus_core *core, u32 vmajor, u32 vminor, u32 vrev)
+{
+ return ((core)->venus_ver.major == vmajor &&
+ (core)->venus_ver.minor == vminor &&
+ (core)->venus_ver.rev >= vrev);
+}
+
+static inline bool
+is_fw_rev_or_older(struct venus_core *core, u32 vmajor, u32 vminor, u32 vrev)
+{
+ return ((core)->venus_ver.major == vmajor &&
+ (core)->venus_ver.minor == vminor &&
+ (core)->venus_ver.rev <= vrev);
+}
#endif
diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c
index a2ceab7f9ddb..1822e85ab6bf 100644
--- a/drivers/media/platform/qcom/venus/helpers.c
+++ b/drivers/media/platform/qcom/venus/helpers.c
@@ -502,7 +502,6 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
struct vb2_buffer *vb = &vbuf->vb2_buf;
unsigned int type = vb->type;
struct hfi_frame_data fdata;
- int ret;
memset(&fdata, 0, sizeof(fdata));
fdata.alloc_len = buf->size;
@@ -533,11 +532,7 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
fdata.offset = 0;
}
- ret = hfi_session_process_buf(inst, &fdata);
- if (ret)
- return ret;
-
- return 0;
+ return hfi_session_process_buf(inst, &fdata);
}
static bool is_dynamic_bufmode(struct venus_inst *inst)
@@ -612,6 +607,8 @@ static u32 to_hfi_raw_fmt(u32 v4l2_fmt)
return HFI_COLOR_FORMAT_NV12_UBWC;
case V4L2_PIX_FMT_QC10C:
return HFI_COLOR_FORMAT_YUV420_TP10_UBWC;
+ case V4L2_PIX_FMT_P010:
+ return HFI_COLOR_FORMAT_P010;
default:
break;
}
@@ -639,12 +636,16 @@ static int platform_get_bufreq(struct venus_inst *inst, u32 buftype,
if (is_dec) {
params.width = inst->width;
params.height = inst->height;
+ params.out_width = inst->out_width;
+ params.out_height = inst->out_height;
params.codec = inst->fmt_out->pixfmt;
params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_cap->pixfmt);
params.dec.max_mbs_per_frame = mbs_per_frame_max(inst);
params.dec.buffer_size_limit = 0;
params.dec.is_secondary_output =
inst->opb_buftype == HFI_BUFFER_OUTPUT2;
+ if (params.dec.is_secondary_output)
+ params.hfi_dpb_color_fmt = inst->dpb_fmt;
params.dec.is_interlaced =
inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE;
} else {
@@ -1036,8 +1037,8 @@ static u32 get_framesize_raw_yuv420_tp10_ubwc(u32 width, u32 height)
u32 extradata = SZ_16K;
u32 size;
- y_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256);
- uv_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256);
+ y_stride = ALIGN(width * 4 / 3, 256);
+ uv_stride = ALIGN(width * 4 / 3, 256);
y_sclines = ALIGN(height, 16);
uv_sclines = ALIGN((height + 1) >> 1, 16);
@@ -1764,6 +1765,22 @@ int venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt,
if (!caps)
return -EINVAL;
+ if (inst->bit_depth == VIDC_BITDEPTH_10 && inst->session_type == VIDC_SESSION_TYPE_DEC) {
+ found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,
+ HFI_COLOR_FORMAT_YUV420_TP10_UBWC);
+ found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);
+ if (found_ubwc && found) {
+ /*
+ * Hard-code DPB buffers to be 10bit UBWC
+ * until V4L2 is able to expose compressed/tiled
+ * formats to applications.
+ */
+ *out_fmt = HFI_COLOR_FORMAT_YUV420_TP10_UBWC;
+ *out2_fmt = fmt;
+ return 0;
+ }
+ }
+
if (ubwc) {
ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE;
found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,
diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c
index bc3f8ff05840..7f0802a5518c 100644
--- a/drivers/media/platform/qcom/venus/hfi_cmds.c
+++ b/drivers/media/platform/qcom/venus/hfi_cmds.c
@@ -83,7 +83,7 @@ int pkt_sys_set_resource(struct hfi_sys_set_resource_pkt *pkt, u32 id, u32 size,
res->size = size;
res->mem = addr;
pkt->resource_type = HFI_RESOURCE_OCMEM;
- pkt->hdr.size += sizeof(*res) - sizeof(u32);
+ pkt->hdr.size += sizeof(*res);
break;
}
case VIDC_RESOURCE_NONE:
@@ -200,8 +200,8 @@ int pkt_session_set_buffers(struct hfi_session_set_buffers_pkt *pkt,
struct hfi_buffer_info *bi;
pkt->extradata_size = bd->extradata_size;
- pkt->shdr.hdr.size = sizeof(*pkt) - sizeof(u32) +
- (bd->num_buffers * sizeof(*bi));
+ pkt->shdr.hdr.size = sizeof(*pkt) +
+ bd->num_buffers * sizeof(*bi);
bi = (struct hfi_buffer_info *)pkt->buffer_info;
for (i = 0; i < pkt->num_buffers; i++) {
bi->buffer_addr = bd->device_addr;
@@ -209,8 +209,8 @@ int pkt_session_set_buffers(struct hfi_session_set_buffers_pkt *pkt,
}
} else {
pkt->extradata_size = 0;
- pkt->shdr.hdr.size = sizeof(*pkt) +
- ((bd->num_buffers - 1) * sizeof(u32));
+ pkt->shdr.hdr.size = struct_size(pkt, buffer_info,
+ bd->num_buffers);
for (i = 0; i < pkt->num_buffers; i++)
pkt->buffer_info[i] = bd->device_addr;
}
@@ -243,16 +243,16 @@ int pkt_session_unset_buffers(struct hfi_session_release_buffer_pkt *pkt,
bi->extradata_addr = bd->extradata_addr;
}
pkt->shdr.hdr.size =
- sizeof(struct hfi_session_set_buffers_pkt) -
- sizeof(u32) + (bd->num_buffers * sizeof(*bi));
+ sizeof(struct hfi_session_set_buffers_pkt) +
+ bd->num_buffers * sizeof(*bi);
} else {
for (i = 0; i < pkt->num_buffers; i++)
pkt->buffer_info[i] = bd->device_addr;
pkt->extradata_size = 0;
pkt->shdr.hdr.size =
- sizeof(struct hfi_session_set_buffers_pkt) +
- ((bd->num_buffers - 1) * sizeof(u32));
+ struct_size((struct hfi_session_set_buffers_pkt *)0,
+ buffer_info, bd->num_buffers);
}
pkt->response_req = bd->response_required;
@@ -521,6 +521,7 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt,
pkt->shdr.hdr.size += sizeof(u32) + sizeof(*en);
break;
}
+ case HFI_PROPERTY_PARAM_VDEC_ENABLE_SUFFICIENT_SEQCHANGE_EVENT:
case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER: {
struct hfi_enable *in = pdata;
struct hfi_enable *en = prop_data;
diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.h b/drivers/media/platform/qcom/venus/hfi_cmds.h
index 99bc0b6db67c..dd9c5066442d 100644
--- a/drivers/media/platform/qcom/venus/hfi_cmds.h
+++ b/drivers/media/platform/qcom/venus/hfi_cmds.h
@@ -56,7 +56,7 @@ struct hfi_sys_set_resource_pkt {
struct hfi_pkt_hdr hdr;
u32 resource_handle;
u32 resource_type;
- u32 resource_data[1];
+ u32 resource_data[];
};
struct hfi_sys_release_resource_pkt {
@@ -117,7 +117,7 @@ struct hfi_session_set_buffers_pkt {
u32 extradata_size;
u32 min_buffer_size;
u32 num_buffers;
- u32 buffer_info[1];
+ u32 buffer_info[];
};
struct hfi_session_get_sequence_header_pkt {
diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h
index 105792a68060..0abbc50c5864 100644
--- a/drivers/media/platform/qcom/venus/hfi_helper.h
+++ b/drivers/media/platform/qcom/venus/hfi_helper.h
@@ -469,6 +469,8 @@
#define HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH 0x1003007
#define HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT 0x1003009
#define HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE 0x100300a
+#define HFI_PROPERTY_PARAM_VDEC_ENABLE_SUFFICIENT_SEQCHANGE_EVENT \
+ 0x100300b
/*
* HFI_PROPERTY_CONFIG_VDEC_COMMON_START
diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c
index df96db3761a7..3d5dadfa1900 100644
--- a/drivers/media/platform/qcom/venus/hfi_msgs.c
+++ b/drivers/media/platform/qcom/venus/hfi_msgs.c
@@ -233,7 +233,7 @@ static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst,
goto done;
}
- rem_bytes = pkt->hdr.size - sizeof(*pkt) + sizeof(u32);
+ rem_bytes = pkt->hdr.size - sizeof(*pkt);
if (rem_bytes <= 0) {
/* missing property data */
error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
@@ -248,13 +248,15 @@ done:
}
static void
-sys_get_prop_image_version(struct device *dev,
+sys_get_prop_image_version(struct venus_core *core,
struct hfi_msg_sys_property_info_pkt *pkt)
{
+ struct device *dev = core->dev;
u8 *smem_tbl_ptr;
u8 *img_ver;
int req_bytes;
size_t smem_blk_sz;
+ int ret;
req_bytes = pkt->hdr.size - sizeof(*pkt);
@@ -263,8 +265,30 @@ sys_get_prop_image_version(struct device *dev,
return;
img_ver = pkt->data;
+ if (!img_ver)
+ return;
+
+ ret = sscanf(img_ver, "14:video-firmware.%u.%u-%u",
+ &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
+ if (ret)
+ goto done;
+
+ ret = sscanf(img_ver, "14:VIDEO.VPU.%u.%u-%u",
+ &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
+ if (ret)
+ goto done;
+
+ ret = sscanf(img_ver, "14:VIDEO.VE.%u.%u-%u",
+ &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
+ if (ret)
+ goto done;
- dev_dbg(dev, VDBGL "F/W version: %s\n", img_ver);
+ dev_err(dev, VDBGL "error reading F/W version\n");
+ return;
+
+done:
+ dev_dbg(dev, VDBGL "F/W version: %s, major %u, minor %u, revision %u\n",
+ img_ver, core->venus_ver.major, core->venus_ver.minor, core->venus_ver.rev);
smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY,
SMEM_IMG_VER_TBL, &smem_blk_sz);
@@ -286,7 +310,7 @@ static void hfi_sys_property_info(struct venus_core *core,
switch (pkt->property) {
case HFI_PROPERTY_SYS_IMAGE_VERSION:
- sys_get_prop_image_version(dev, pkt);
+ sys_get_prop_image_version(core, pkt);
break;
default:
dev_dbg(dev, VDBGL "unknown property data\n");
@@ -434,7 +458,7 @@ static void hfi_session_init_done(struct venus_core *core,
if (!IS_V1(core))
goto done;
- rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt) + sizeof(u32);
+ rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
if (rem_bytes <= 0) {
error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
goto done;
diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.h b/drivers/media/platform/qcom/venus/hfi_msgs.h
index 510513697335..8c2e17b0d36f 100644
--- a/drivers/media/platform/qcom/venus/hfi_msgs.h
+++ b/drivers/media/platform/qcom/venus/hfi_msgs.h
@@ -50,7 +50,7 @@ struct hfi_msg_event_notify_pkt {
u32 event_id;
u32 event_data1;
u32 event_data2;
- u32 ext_event_data[1];
+ u32 ext_event_data[];
};
struct hfi_msg_event_release_buffer_ref_pkt {
@@ -63,7 +63,7 @@ struct hfi_msg_sys_init_done_pkt {
struct hfi_pkt_hdr hdr;
u32 error_type;
u32 num_properties;
- u32 data[1];
+ u32 data[];
};
struct hfi_msg_sys_pc_prep_done_pkt {
@@ -81,7 +81,7 @@ struct hfi_msg_session_init_done_pkt {
struct hfi_session_hdr_pkt shdr;
u32 error_type;
u32 num_properties;
- u32 data[1];
+ u32 data[];
};
struct hfi_msg_session_end_done_pkt {
@@ -228,7 +228,7 @@ struct hfi_msg_session_parse_sequence_header_done_pkt {
struct hfi_session_hdr_pkt shdr;
u32 error_type;
u32 num_properties;
- u32 data[1];
+ u32 data[];
};
struct hfi_msg_session_property_info_pkt {
@@ -247,7 +247,7 @@ struct hfi_msg_session_release_buffers_done_pkt {
struct hfi_session_hdr_pkt shdr;
u32 error_type;
u32 num_buffers;
- u32 buffer_info[1];
+ u32 buffer_info[];
};
struct hfi_msg_sys_debug_pkt {
@@ -256,7 +256,7 @@ struct hfi_msg_sys_debug_pkt {
u32 msg_size;
u32 time_stamp_hi;
u32 time_stamp_lo;
- u8 msg_data[1];
+ u8 msg_data[];
};
struct hfi_msg_sys_coverage_pkt {
@@ -264,7 +264,7 @@ struct hfi_msg_sys_coverage_pkt {
u32 msg_size;
u32 time_stamp_hi;
u32 time_stamp_lo;
- u8 msg_data[1];
+ u8 msg_data[];
};
struct venus_core;
diff --git a/drivers/media/platform/qcom/venus/hfi_plat_bufs.h b/drivers/media/platform/qcom/venus/hfi_plat_bufs.h
index 52a51a3b964a..25e607452096 100644
--- a/drivers/media/platform/qcom/venus/hfi_plat_bufs.h
+++ b/drivers/media/platform/qcom/venus/hfi_plat_bufs.h
@@ -12,8 +12,11 @@
struct hfi_plat_buffers_params {
u32 width;
u32 height;
+ u32 out_width;
+ u32 out_height;
u32 codec;
u32 hfi_color_fmt;
+ u32 hfi_dpb_color_fmt;
enum hfi_version version;
u32 num_vpp_pipes;
union {
diff --git a/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c b/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c
index a9be31ec6927..e97ff8cf6d64 100644
--- a/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c
+++ b/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c
@@ -1185,6 +1185,7 @@ static int bufreq_dec(struct hfi_plat_buffers_params *params, u32 buftype,
enum hfi_version version = params->version;
u32 codec = params->codec;
u32 width = params->width, height = params->height, out_min_count;
+ u32 out_width = params->out_width, out_height = params->out_height;
struct dec_bufsize_ops *dec_ops;
bool is_secondary_output = params->dec.is_secondary_output;
bool is_interlaced = params->dec.is_interlaced;
@@ -1230,12 +1231,16 @@ static int bufreq_dec(struct hfi_plat_buffers_params *params, u32 buftype,
calculate_dec_input_frame_size(width, height, codec,
max_mbs_per_frame,
buffer_size_limit);
- } else if (buftype == HFI_BUFFER_OUTPUT ||
- buftype == HFI_BUFFER_OUTPUT2) {
+ } else if (buftype == HFI_BUFFER_OUTPUT || buftype == HFI_BUFFER_OUTPUT2) {
bufreq->count_min = out_min_count;
bufreq->size =
venus_helper_get_framesz_raw(params->hfi_color_fmt,
- width, height);
+ out_width, out_height);
+ if (buftype == HFI_BUFFER_OUTPUT &&
+ params->dec.is_secondary_output)
+ bufreq->size =
+ venus_helper_get_framesz_raw(params->hfi_dpb_color_fmt,
+ out_width, out_height);
} else if (buftype == HFI_BUFFER_INTERNAL_SCRATCH(version)) {
bufreq->size = dec_ops->scratch(width, height, is_interlaced);
} else if (buftype == HFI_BUFFER_INTERNAL_SCRATCH_1(version)) {
diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c
index 2ad40b3945b0..f0b46389e8d5 100644
--- a/drivers/media/platform/qcom/venus/hfi_venus.c
+++ b/drivers/media/platform/qcom/venus/hfi_venus.c
@@ -835,34 +835,24 @@ static int venus_sys_set_debug(struct venus_hfi_device *hdev, u32 debug)
{
struct hfi_sys_set_property_pkt *pkt;
u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
- int ret;
pkt = (struct hfi_sys_set_property_pkt *)packet;
pkt_sys_debug_config(pkt, HFI_DEBUG_MODE_QUEUE, debug);
- ret = venus_iface_cmdq_write(hdev, pkt, false);
- if (ret)
- return ret;
-
- return 0;
+ return venus_iface_cmdq_write(hdev, pkt, false);
}
static int venus_sys_set_coverage(struct venus_hfi_device *hdev, u32 mode)
{
struct hfi_sys_set_property_pkt *pkt;
u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
- int ret;
pkt = (struct hfi_sys_set_property_pkt *)packet;
pkt_sys_coverage_config(pkt, mode);
- ret = venus_iface_cmdq_write(hdev, pkt, false);
- if (ret)
- return ret;
-
- return 0;
+ return venus_iface_cmdq_write(hdev, pkt, false);
}
static int venus_sys_set_idle_message(struct venus_hfi_device *hdev,
@@ -870,7 +860,6 @@ static int venus_sys_set_idle_message(struct venus_hfi_device *hdev,
{
struct hfi_sys_set_property_pkt *pkt;
u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
- int ret;
if (!enable)
return 0;
@@ -879,11 +868,7 @@ static int venus_sys_set_idle_message(struct venus_hfi_device *hdev,
pkt_sys_idle_indicator(pkt, enable);
- ret = venus_iface_cmdq_write(hdev, pkt, false);
- if (ret)
- return ret;
-
- return 0;
+ return venus_iface_cmdq_write(hdev, pkt, false);
}
static int venus_sys_set_power_control(struct venus_hfi_device *hdev,
@@ -891,17 +876,12 @@ static int venus_sys_set_power_control(struct venus_hfi_device *hdev,
{
struct hfi_sys_set_property_pkt *pkt;
u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
- int ret;
pkt = (struct hfi_sys_set_property_pkt *)packet;
pkt_sys_power_control(pkt, enable);
- ret = venus_iface_cmdq_write(hdev, pkt, false);
- if (ret)
- return ret;
-
- return 0;
+ return venus_iface_cmdq_write(hdev, pkt, false);
}
static int venus_sys_set_ubwc_config(struct venus_hfi_device *hdev)
diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c
index 51a53bf82bd3..f5676440dd36 100644
--- a/drivers/media/platform/qcom/venus/vdec.c
+++ b/drivers/media/platform/qcom/venus/vdec.c
@@ -30,69 +30,87 @@
* - future firmware versions could add support for >1 planes
*/
static const struct venus_format vdec_formats[] = {
- {
+ [VENUS_FMT_NV12] = {
.pixfmt = V4L2_PIX_FMT_NV12,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
+ },
+ [VENUS_FMT_QC08C] = {
.pixfmt = V4L2_PIX_FMT_QC08C,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
+ },
+ [VENUS_FMT_QC10C] = {
.pixfmt = V4L2_PIX_FMT_QC10C,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
- .pixfmt = V4L2_PIX_FMT_MPEG4,
+ },
+ [VENUS_FMT_P010] = {
+ .pixfmt = V4L2_PIX_FMT_P010,
+ .num_planes = 1,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ },
+ [VENUS_FMT_H264] = {
+ .pixfmt = V4L2_PIX_FMT_H264,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_MPEG2,
+ },
+ [VENUS_FMT_VP8] = {
+ .pixfmt = V4L2_PIX_FMT_VP8,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_H263,
+ },
+ [VENUS_FMT_VP9] = {
+ .pixfmt = V4L2_PIX_FMT_VP9,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G,
+ },
+ [VENUS_FMT_HEVC] = {
+ .pixfmt = V4L2_PIX_FMT_HEVC,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L,
+ },
+ [VENUS_FMT_VC1_ANNEX_G] = {
+ .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_H264,
+ },
+ [VENUS_FMT_VC1_ANNEX_L] = {
+ .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_VP8,
+ },
+ [VENUS_FMT_MPEG4] = {
+ .pixfmt = V4L2_PIX_FMT_MPEG4,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_VP9,
+ },
+ [VENUS_FMT_MPEG2] = {
+ .pixfmt = V4L2_PIX_FMT_MPEG2,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_XVID,
+ },
+ [VENUS_FMT_H263] = {
+ .pixfmt = V4L2_PIX_FMT_H263,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_HEVC,
+ },
+ [VENUS_FMT_XVID] = {
+ .pixfmt = V4L2_PIX_FMT_XVID,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
},
+
};
static const struct venus_format *
@@ -551,7 +569,7 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
fdata.buffer_type = HFI_BUFFER_INPUT;
fdata.flags |= HFI_BUFFERFLAG_EOS;
- if (IS_V6(inst->core))
+ if (IS_V6(inst->core) && is_fw_rev_or_older(inst->core, 1, 0, 87))
fdata.device_addr = 0;
else
fdata.device_addr = 0xdeadb000;
@@ -684,6 +702,14 @@ static int vdec_set_properties(struct venus_inst *inst)
return ret;
}
+ /* Enabling sufficient sequence change support for VP9 */
+ if (is_fw_rev_or_newer(inst->core, 5, 4, 51)) {
+ ptype = HFI_PROPERTY_PARAM_VDEC_ENABLE_SUFFICIENT_SEQCHANGE_EVENT;
+ ret = hfi_session_set_property(inst, ptype, &en);
+ if (ret)
+ return ret;
+ }
+
ptype = HFI_PROPERTY_PARAM_VDEC_CONCEAL_COLOR;
conceal = ctr->conceal_color & 0xffff;
conceal |= ((ctr->conceal_color >> 16) & 0xffff) << 10;
@@ -710,6 +736,9 @@ static int vdec_set_work_route(struct venus_inst *inst)
}
#define is_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_UBWC_BASE))
+#define is_10bit_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_10_BIT_BASE & \
+ HFI_COLOR_FORMAT_UBWC_BASE))
+
static int vdec_output_conf(struct venus_inst *inst)
{
@@ -757,7 +786,7 @@ static int vdec_output_conf(struct venus_inst *inst)
inst->opb_fmt = out2_fmt;
inst->dpb_buftype = HFI_BUFFER_OUTPUT;
inst->dpb_fmt = out_fmt;
- } else if (is_ubwc_fmt(out2_fmt)) {
+ } else if (is_ubwc_fmt(out2_fmt) || is_10bit_ubwc_fmt(out_fmt)) {
inst->opb_buftype = HFI_BUFFER_OUTPUT;
inst->opb_fmt = out_fmt;
inst->dpb_buftype = HFI_BUFFER_OUTPUT2;
@@ -1474,8 +1503,13 @@ static void vdec_event_change(struct venus_inst *inst,
inst->out_width = ev_data->width;
inst->out_height = ev_data->height;
- if (inst->bit_depth != ev_data->bit_depth)
+ if (inst->bit_depth != ev_data->bit_depth) {
inst->bit_depth = ev_data->bit_depth;
+ if (inst->bit_depth == VIDC_BITDEPTH_10)
+ inst->fmt_cap = &vdec_formats[VENUS_FMT_P010];
+ else
+ inst->fmt_cap = &vdec_formats[VENUS_FMT_NV12];
+ }
if (inst->pic_struct != ev_data->pic_struct)
inst->pic_struct = ev_data->pic_struct;
@@ -1567,8 +1601,8 @@ static const struct hfi_inst_ops vdec_hfi_ops = {
static void vdec_inst_init(struct venus_inst *inst)
{
inst->hfi_codec = HFI_VIDEO_CODEC_H264;
- inst->fmt_out = &vdec_formats[8];
- inst->fmt_cap = &vdec_formats[0];
+ inst->fmt_out = &vdec_formats[VENUS_FMT_H264];
+ inst->fmt_cap = &vdec_formats[VENUS_FMT_NV12];
inst->width = frame_width_min(inst);
inst->height = ALIGN(frame_height_min(inst), 32);
inst->crop.left = 0;
@@ -1609,6 +1643,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->allow_zero_bytesused = 1;
src_vq->min_buffers_needed = 0;
src_vq->dev = inst->core->dev;
+ src_vq->lock = &inst->ctx_q_lock;
ret = vb2_queue_init(src_vq);
if (ret)
return ret;
@@ -1623,6 +1658,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->allow_zero_bytesused = 1;
dst_vq->min_buffers_needed = 0;
dst_vq->dev = inst->core->dev;
+ dst_vq->lock = &inst->ctx_q_lock;
return vb2_queue_init(dst_vq);
}
@@ -1641,6 +1677,7 @@ static int vdec_open(struct file *file)
INIT_LIST_HEAD(&inst->internalbufs);
INIT_LIST_HEAD(&inst->list);
mutex_init(&inst->lock);
+ mutex_init(&inst->ctx_q_lock);
inst->core = core;
inst->session_type = VIDC_SESSION_TYPE_DEC;
@@ -1716,6 +1753,7 @@ static int vdec_close(struct file *file)
ida_destroy(&inst->dpb_ids);
hfi_session_destroy(inst);
mutex_destroy(&inst->lock);
+ mutex_destroy(&inst->ctx_q_lock);
v4l2_fh_del(&inst->fh);
v4l2_fh_exit(&inst->fh);
diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index 4666f42feea3..6d773b000e8a 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -32,28 +32,33 @@
* - future firmware versions could add support for >1 planes
*/
static const struct venus_format venc_formats[] = {
- {
+ [VENUS_FMT_NV12] = {
.pixfmt = V4L2_PIX_FMT_NV12,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
- }, {
- .pixfmt = V4L2_PIX_FMT_MPEG4,
+ },
+ [VENUS_FMT_H264] = {
+ .pixfmt = V4L2_PIX_FMT_H264,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
- .pixfmt = V4L2_PIX_FMT_H263,
+ },
+ [VENUS_FMT_VP8] = {
+ .pixfmt = V4L2_PIX_FMT_VP8,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
- .pixfmt = V4L2_PIX_FMT_H264,
+ },
+ [VENUS_FMT_HEVC] = {
+ .pixfmt = V4L2_PIX_FMT_HEVC,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
- .pixfmt = V4L2_PIX_FMT_VP8,
+ },
+ [VENUS_FMT_MPEG4] = {
+ .pixfmt = V4L2_PIX_FMT_MPEG4,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
- .pixfmt = V4L2_PIX_FMT_HEVC,
+ },
+ [VENUS_FMT_H263] = {
+ .pixfmt = V4L2_PIX_FMT_H263,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
},
@@ -1395,6 +1400,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->allow_zero_bytesused = 1;
src_vq->min_buffers_needed = 1;
src_vq->dev = inst->core->dev;
+ src_vq->lock = &inst->ctx_q_lock;
if (inst->core->res->hfi_version == HFI_VERSION_1XX)
src_vq->bidirectional = 1;
ret = vb2_queue_init(src_vq);
@@ -1411,13 +1417,14 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->allow_zero_bytesused = 1;
dst_vq->min_buffers_needed = 1;
dst_vq->dev = inst->core->dev;
+ dst_vq->lock = &inst->ctx_q_lock;
return vb2_queue_init(dst_vq);
}
static void venc_inst_init(struct venus_inst *inst)
{
- inst->fmt_cap = &venc_formats[3];
- inst->fmt_out = &venc_formats[0];
+ inst->fmt_cap = &venc_formats[VENUS_FMT_H264];
+ inst->fmt_out = &venc_formats[VENUS_FMT_NV12];
inst->width = 1280;
inst->height = ALIGN(720, 32);
inst->out_width = 1280;
@@ -1443,6 +1450,7 @@ static int venc_open(struct file *file)
INIT_LIST_HEAD(&inst->internalbufs);
INIT_LIST_HEAD(&inst->list);
mutex_init(&inst->lock);
+ mutex_init(&inst->ctx_q_lock);
inst->core = core;
inst->session_type = VIDC_SESSION_TYPE_ENC;
@@ -1512,6 +1520,7 @@ static int venc_close(struct file *file)
venc_ctrl_deinit(inst);
hfi_session_destroy(inst);
mutex_destroy(&inst->lock);
+ mutex_destroy(&inst->ctx_q_lock);
v4l2_fh_del(&inst->fh);
v4l2_fh_exit(&inst->fh);
diff --git a/drivers/media/platform/renesas/rcar-isp.c b/drivers/media/platform/renesas/rcar-isp.c
index f666b621338d..fee1a066f56b 100644
--- a/drivers/media/platform/renesas/rcar-isp.c
+++ b/drivers/media/platform/renesas/rcar-isp.c
@@ -430,6 +430,7 @@ static int risp_probe_resources(struct rcar_isp *isp,
static const struct of_device_id risp_of_id_table[] = {
{ .compatible = "renesas,r8a779a0-isp" },
+ { .compatible = "renesas,r8a779g0-isp" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, risp_of_id_table);
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
index ff4bde9cc0e3..3c4f5eb93be1 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
@@ -1284,6 +1284,15 @@ static const struct rvin_info rcar_info_r8a779a0 = {
.max_height = 4096,
};
+static const struct rvin_info rcar_info_r8a779g0 = {
+ .model = RCAR_GEN3,
+ .use_mc = true,
+ .use_isp = true,
+ .nv12 = true,
+ .max_width = 4096,
+ .max_height = 4096,
+};
+
static const struct of_device_id rvin_of_id_table[] = {
{
.compatible = "renesas,vin-r8a774a1",
@@ -1349,6 +1358,10 @@ static const struct of_device_id rvin_of_id_table[] = {
.compatible = "renesas,vin-r8a779a0",
.data = &rcar_info_r8a779a0,
},
+ {
+ .compatible = "renesas,vin-r8a779g0",
+ .data = &rcar_info_r8a779g0,
+ },
{ /* Sentinel */ },
};
MODULE_DEVICE_TABLE(of, rvin_of_id_table);
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
index e34060c2b039..7a134c0eff57 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
@@ -483,11 +483,15 @@ enum rcar_csi2_pads {
struct rcar_csi2_info {
int (*init_phtw)(struct rcar_csi2 *priv, unsigned int mbps);
int (*phy_post_init)(struct rcar_csi2 *priv);
+ int (*start_receiver)(struct rcar_csi2 *priv);
+ void (*enter_standby)(struct rcar_csi2 *priv);
const struct rcsi2_mbps_reg *hsfreqrange;
unsigned int csi0clkfreqrange;
unsigned int num_channels;
bool clear_ulps;
bool use_isp;
+ bool support_dphy;
+ bool support_cphy;
};
struct rcar_csi2 {
@@ -509,6 +513,7 @@ struct rcar_csi2 {
struct v4l2_mbus_framefmt mf;
int stream_count;
+ bool cphy;
unsigned short lanes;
unsigned char lane_swap[4];
};
@@ -533,10 +538,17 @@ static void rcsi2_write(struct rcar_csi2 *priv, unsigned int reg, u32 data)
iowrite32(data, priv->base + reg);
}
-static void rcsi2_enter_standby(struct rcar_csi2 *priv)
+static void rcsi2_enter_standby_gen3(struct rcar_csi2 *priv)
{
rcsi2_write(priv, PHYCNT_REG, 0);
rcsi2_write(priv, PHTC_REG, PHTC_TESTCLR);
+}
+
+static void rcsi2_enter_standby(struct rcar_csi2 *priv)
+{
+ if (priv->info->enter_standby)
+ priv->info->enter_standby(priv);
+
reset_control_assert(priv->rstc);
usleep_range(100, 150);
pm_runtime_put(priv->dev);
@@ -656,7 +668,16 @@ static int rcsi2_get_active_lanes(struct rcar_csi2 *priv,
return ret;
}
- if (mbus_config.type != V4L2_MBUS_CSI2_DPHY) {
+ switch (mbus_config.type) {
+ case V4L2_MBUS_CSI2_CPHY:
+ if (!priv->cphy)
+ return -EINVAL;
+ break;
+ case V4L2_MBUS_CSI2_DPHY:
+ if (priv->cphy)
+ return -EINVAL;
+ break;
+ default:
dev_err(priv->dev, "Unsupported media bus type %u\n",
mbus_config.type);
return -EINVAL;
@@ -674,7 +695,7 @@ static int rcsi2_get_active_lanes(struct rcar_csi2 *priv,
return 0;
}
-static int rcsi2_start_receiver(struct rcar_csi2 *priv)
+static int rcsi2_start_receiver_gen3(struct rcar_csi2 *priv)
{
const struct rcar_csi2_format *format;
u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0;
@@ -821,7 +842,7 @@ static int rcsi2_start(struct rcar_csi2 *priv)
if (ret < 0)
return ret;
- ret = rcsi2_start_receiver(priv);
+ ret = priv->info->start_receiver(priv);
if (ret) {
rcsi2_enter_standby(priv);
return ret;
@@ -1016,15 +1037,41 @@ static int rcsi2_parse_v4l2(struct rcar_csi2 *priv,
if (vep->base.port || vep->base.id)
return -ENOTCONN;
- if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) {
- dev_err(priv->dev, "Unsupported bus: %u\n", vep->bus_type);
- return -EINVAL;
- }
-
priv->lanes = vep->bus.mipi_csi2.num_data_lanes;
- if (priv->lanes != 1 && priv->lanes != 2 && priv->lanes != 4) {
- dev_err(priv->dev, "Unsupported number of data-lanes: %u\n",
- priv->lanes);
+
+ switch (vep->bus_type) {
+ case V4L2_MBUS_CSI2_DPHY:
+ if (!priv->info->support_dphy) {
+ dev_err(priv->dev, "D-PHY not supported\n");
+ return -EINVAL;
+ }
+
+ if (priv->lanes != 1 && priv->lanes != 2 && priv->lanes != 4) {
+ dev_err(priv->dev,
+ "Unsupported number of data-lanes for D-PHY: %u\n",
+ priv->lanes);
+ return -EINVAL;
+ }
+
+ priv->cphy = false;
+ break;
+ case V4L2_MBUS_CSI2_CPHY:
+ if (!priv->info->support_cphy) {
+ dev_err(priv->dev, "C-PHY not supported\n");
+ return -EINVAL;
+ }
+
+ if (priv->lanes != 3) {
+ dev_err(priv->dev,
+ "Unsupported number of data-lanes for C-PHY: %u\n",
+ priv->lanes);
+ return -EINVAL;
+ }
+
+ priv->cphy = true;
+ break;
+ default:
+ dev_err(priv->dev, "Unsupported bus: %u\n", vep->bus_type);
return -EINVAL;
}
@@ -1048,7 +1095,7 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv)
struct fwnode_handle *fwnode;
struct fwnode_handle *ep;
struct v4l2_fwnode_endpoint v4l2_ep = {
- .bus_type = V4L2_MBUS_CSI2_DPHY
+ .bus_type = V4L2_MBUS_UNKNOWN,
};
int ret;
@@ -1363,63 +1410,90 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
static const struct rcar_csi2_info rcar_csi2_info_r8a7795 = {
.init_phtw = rcsi2_init_phtw_h3_v3h_m3n,
+ .start_receiver = rcsi2_start_receiver_gen3,
+ .enter_standby = rcsi2_enter_standby_gen3,
.hsfreqrange = hsfreqrange_h3_v3h_m3n,
.csi0clkfreqrange = 0x20,
.num_channels = 4,
.clear_ulps = true,
+ .support_dphy = true,
};
static const struct rcar_csi2_info rcar_csi2_info_r8a7795es2 = {
.init_phtw = rcsi2_init_phtw_h3es2,
+ .start_receiver = rcsi2_start_receiver_gen3,
+ .enter_standby = rcsi2_enter_standby_gen3,
.hsfreqrange = hsfreqrange_h3_v3h_m3n,
.csi0clkfreqrange = 0x20,
.num_channels = 4,
.clear_ulps = true,
+ .support_dphy = true,
};
static const struct rcar_csi2_info rcar_csi2_info_r8a7796 = {
+ .start_receiver = rcsi2_start_receiver_gen3,
+ .enter_standby = rcsi2_enter_standby_gen3,
.hsfreqrange = hsfreqrange_m3w,
.num_channels = 4,
+ .support_dphy = true,
};
static const struct rcar_csi2_info rcar_csi2_info_r8a77961 = {
+ .start_receiver = rcsi2_start_receiver_gen3,
+ .enter_standby = rcsi2_enter_standby_gen3,
.hsfreqrange = hsfreqrange_m3w,
.num_channels = 4,
+ .support_dphy = true,
};
static const struct rcar_csi2_info rcar_csi2_info_r8a77965 = {
.init_phtw = rcsi2_init_phtw_h3_v3h_m3n,
+ .start_receiver = rcsi2_start_receiver_gen3,
+ .enter_standby = rcsi2_enter_standby_gen3,
.hsfreqrange = hsfreqrange_h3_v3h_m3n,
.csi0clkfreqrange = 0x20,
.num_channels = 4,
.clear_ulps = true,
+ .support_dphy = true,
};
static const struct rcar_csi2_info rcar_csi2_info_r8a77970 = {
.init_phtw = rcsi2_init_phtw_v3m_e3,
.phy_post_init = rcsi2_phy_post_init_v3m_e3,
+ .start_receiver = rcsi2_start_receiver_gen3,
+ .enter_standby = rcsi2_enter_standby_gen3,
.num_channels = 4,
+ .support_dphy = true,
};
static const struct rcar_csi2_info rcar_csi2_info_r8a77980 = {
.init_phtw = rcsi2_init_phtw_h3_v3h_m3n,
+ .start_receiver = rcsi2_start_receiver_gen3,
+ .enter_standby = rcsi2_enter_standby_gen3,
.hsfreqrange = hsfreqrange_h3_v3h_m3n,
.csi0clkfreqrange = 0x20,
.clear_ulps = true,
+ .support_dphy = true,
};
static const struct rcar_csi2_info rcar_csi2_info_r8a77990 = {
.init_phtw = rcsi2_init_phtw_v3m_e3,
.phy_post_init = rcsi2_phy_post_init_v3m_e3,
+ .start_receiver = rcsi2_start_receiver_gen3,
+ .enter_standby = rcsi2_enter_standby_gen3,
.num_channels = 2,
+ .support_dphy = true,
};
static const struct rcar_csi2_info rcar_csi2_info_r8a779a0 = {
.init_phtw = rcsi2_init_phtw_v3u,
+ .start_receiver = rcsi2_start_receiver_gen3,
+ .enter_standby = rcsi2_enter_standby_gen3,
.hsfreqrange = hsfreqrange_v3u,
.csi0clkfreqrange = 0x20,
.clear_ulps = true,
.use_isp = true,
+ .support_dphy = true,
};
static const struct of_device_id rcar_csi2_of_table[] = {
diff --git a/drivers/media/platform/renesas/rcar_fdp1.c b/drivers/media/platform/renesas/rcar_fdp1.c
index f43e458590b8..ab39cd2201c8 100644
--- a/drivers/media/platform/renesas/rcar_fdp1.c
+++ b/drivers/media/platform/renesas/rcar_fdp1.c
@@ -254,6 +254,8 @@ MODULE_PARM_DESC(debug, "activate debug info");
/* Internal Data (HW Version) */
#define FD1_IP_INTDATA 0x0800
+/* R-Car Gen2 HW manual says zero, but actual value matches R-Car H3 ES1.x */
+#define FD1_IP_GEN2 0x02010101
#define FD1_IP_M3W 0x02010202
#define FD1_IP_H3 0x02010203
#define FD1_IP_M3N 0x02010204
@@ -2360,6 +2362,9 @@ static int fdp1_probe(struct platform_device *pdev)
hw_version = fdp1_read(fdp1, FD1_IP_INTDATA);
switch (hw_version) {
+ case FD1_IP_GEN2:
+ dprintk(fdp1, "FDP1 Version R-Car Gen2\n");
+ break;
case FD1_IP_M3W:
dprintk(fdp1, "FDP1 Version R-Car M3-W\n");
break;
diff --git a/drivers/media/platform/renesas/rcar_jpu.c b/drivers/media/platform/renesas/rcar_jpu.c
index e7f604807825..2b8cb50f54de 100644
--- a/drivers/media/platform/renesas/rcar_jpu.c
+++ b/drivers/media/platform/renesas/rcar_jpu.c
@@ -28,6 +28,7 @@
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/videodev2.h>
+#include <media/jpeg.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
@@ -71,19 +72,6 @@
#define JPU_JPEG_DEFAULT_422_PIX_FMT V4L2_PIX_FMT_NV16M
#define JPU_JPEG_DEFAULT_420_PIX_FMT V4L2_PIX_FMT_NV12M
-/* JPEG markers */
-#define TEM 0x01
-#define SOF0 0xc0
-#define RST 0xd0
-#define SOI 0xd8
-#define EOI 0xd9
-#define DHP 0xde
-#define DHT 0xc4
-#define COM 0xfe
-#define DQT 0xdb
-#define DRI 0xdd
-#define APP0 0xe0
-
#define JPU_RESET_TIMEOUT 100 /* ms */
#define JPU_JOB_TIMEOUT 300 /* ms */
#define JPU_MAX_QUALITY 4
@@ -330,26 +318,32 @@ static const u8 zigzag[] = {
* Huffman tables; Padding with 0xff (33.3.27 R01UH0501EJ0100 Rev.1.00)
*/
#define JPU_JPEG_HDR_BLOB { \
- 0xff, SOI, 0xff, DQT, 0x00, JPU_JPEG_QTBL_SIZE + 0x3, JPU_JPEG_LUM, \
- [JPU_JPEG_QTBL_LUM_OFFSET ... \
+ 0xff, JPEG_MARKER_SOI, 0xff, JPEG_MARKER_DQT, 0x00, \
+ JPU_JPEG_QTBL_SIZE + 0x3, JPU_JPEG_LUM, \
+ [JPU_JPEG_QTBL_LUM_OFFSET ... \
JPU_JPEG_QTBL_LUM_OFFSET + JPU_JPEG_QTBL_SIZE - 1] = 0x00, \
- 0xff, DQT, 0x00, JPU_JPEG_QTBL_SIZE + 0x3, JPU_JPEG_CHR, \
+ 0xff, JPEG_MARKER_DQT, 0x00, JPU_JPEG_QTBL_SIZE + 0x3, JPU_JPEG_CHR, \
[JPU_JPEG_QTBL_CHR_OFFSET ... JPU_JPEG_QTBL_CHR_OFFSET + \
- JPU_JPEG_QTBL_SIZE - 1] = 0x00, 0xff, SOF0, 0x00, 0x11, 0x08, \
+ JPU_JPEG_QTBL_SIZE - 1] = 0x00, \
+ 0xff, JPEG_MARKER_SOF0, 0x00, 0x11, 0x08, \
[JPU_JPEG_HEIGHT_OFFSET ... JPU_JPEG_HEIGHT_OFFSET + 1] = 0x00, \
[JPU_JPEG_WIDTH_OFFSET ... JPU_JPEG_WIDTH_OFFSET + 1] = 0x00, \
0x03, 0x01, [JPU_JPEG_SUBS_OFFSET] = 0x00, JPU_JPEG_LUM, \
0x02, 0x11, JPU_JPEG_CHR, 0x03, 0x11, JPU_JPEG_CHR, \
- 0xff, DHT, 0x00, JPU_JPEG_HDCTBL_SIZE + 0x3, JPU_JPEG_LUM|JPU_JPEG_DC, \
+ 0xff, JPEG_MARKER_DHT, 0x00, JPU_JPEG_HDCTBL_SIZE + 0x3, \
+ JPU_JPEG_LUM | JPU_JPEG_DC, \
[JPU_JPEG_HDCTBL_LUM_OFFSET ... \
JPU_JPEG_HDCTBL_LUM_OFFSET + JPU_JPEG_HDCTBL_SIZE - 1] = 0x00, \
- 0xff, DHT, 0x00, JPU_JPEG_HACTBL_SIZE + 0x3, JPU_JPEG_LUM|JPU_JPEG_AC, \
+ 0xff, JPEG_MARKER_DHT, 0x00, JPU_JPEG_HACTBL_SIZE + 0x3, \
+ JPU_JPEG_LUM | JPU_JPEG_AC, \
[JPU_JPEG_HACTBL_LUM_OFFSET ... \
JPU_JPEG_HACTBL_LUM_OFFSET + JPU_JPEG_HACTBL_SIZE - 1] = 0x00, \
- 0xff, DHT, 0x00, JPU_JPEG_HDCTBL_SIZE + 0x3, JPU_JPEG_CHR|JPU_JPEG_DC, \
+ 0xff, JPEG_MARKER_DHT, 0x00, JPU_JPEG_HDCTBL_SIZE + 0x3, \
+ JPU_JPEG_CHR | JPU_JPEG_DC, \
[JPU_JPEG_HDCTBL_CHR_OFFSET ... \
JPU_JPEG_HDCTBL_CHR_OFFSET + JPU_JPEG_HDCTBL_SIZE - 1] = 0x00, \
- 0xff, DHT, 0x00, JPU_JPEG_HACTBL_SIZE + 0x3, JPU_JPEG_CHR|JPU_JPEG_AC, \
+ 0xff, JPEG_MARKER_DHT, 0x00, JPU_JPEG_HACTBL_SIZE + 0x3, \
+ JPU_JPEG_CHR | JPU_JPEG_AC, \
[JPU_JPEG_HACTBL_CHR_OFFSET ... \
JPU_JPEG_HACTBL_CHR_OFFSET + JPU_JPEG_HACTBL_SIZE - 1] = 0x00, \
[JPU_JPEG_PADDING_OFFSET ... JPU_JPEG_HDR_SIZE - 1] = 0xff \
@@ -613,7 +607,8 @@ static u8 jpu_parse_hdr(void *buffer, unsigned long size, unsigned int *width,
* basic size check and EOI - we don't want to let JPU cross
* buffer bounds in any case. Hope it's stopping by EOI.
*/
- if (size < JPU_JPEG_MIN_SIZE || *(u8 *)(buffer + size - 1) != EOI)
+ if (size < JPU_JPEG_MIN_SIZE ||
+ *(u8 *)(buffer + size - 1) != JPEG_MARKER_EOI)
return 0;
for (;;) {
@@ -624,14 +619,14 @@ static u8 jpu_parse_hdr(void *buffer, unsigned long size, unsigned int *width,
c = get_byte(&jpeg_buffer);
while (c == 0xff || c == 0);
- if (!soi && c == SOI) {
+ if (!soi && c == JPEG_MARKER_SOI) {
soi = true;
continue;
- } else if (soi != (c != SOI))
+ } else if (soi != (c != JPEG_MARKER_SOI))
return 0;
switch (c) {
- case SOF0: /* SOF0: baseline JPEG */
+ case JPEG_MARKER_SOF0: /* SOF0: baseline JPEG */
skip(&jpeg_buffer, 3); /* segment length and bpp */
if (get_word_be(&jpeg_buffer, height) ||
get_word_be(&jpeg_buffer, width) ||
@@ -640,11 +635,11 @@ static u8 jpu_parse_hdr(void *buffer, unsigned long size, unsigned int *width,
skip(&jpeg_buffer, 1);
return get_byte(&jpeg_buffer);
- case DHT:
- case DQT:
- case COM:
- case DRI:
- case APP0 ... APP0 + 0x0f:
+ case JPEG_MARKER_DHT:
+ case JPEG_MARKER_DQT:
+ case JPEG_MARKER_COM:
+ case JPEG_MARKER_DRI:
+ case JPEG_MARKER_APP0 ... JPEG_MARKER_APP0 + 0x0f:
if (get_word_be(&jpeg_buffer, &word))
return 0;
skip(&jpeg_buffer, (long)word - 2);
diff --git a/drivers/media/platform/renesas/renesas-ceu.c b/drivers/media/platform/renesas/renesas-ceu.c
index 56b9c59cfda8..5c9e27f8c94b 100644
--- a/drivers/media/platform/renesas/renesas-ceu.c
+++ b/drivers/media/platform/renesas/renesas-ceu.c
@@ -702,12 +702,6 @@ static int ceu_start_streaming(struct vb2_queue *vq, unsigned int count)
/* Grab the first available buffer and trigger the first capture. */
buf = list_first_entry(&ceudev->capture, struct ceu_buffer,
queue);
- if (!buf) {
- spin_unlock_irqrestore(&ceudev->lock, irqflags);
- dev_dbg(ceudev->dev,
- "No buffer available for capture.\n");
- goto error_stop_sensor;
- }
list_del(&buf->queue);
ceudev->active = &buf->vb;
@@ -722,9 +716,6 @@ static int ceu_start_streaming(struct vb2_queue *vq, unsigned int count)
return 0;
-error_stop_sensor:
- v4l2_subdev_call(v4l2_sd, video, s_stream, 0);
-
error_return_bufs:
spin_lock_irqsave(&ceudev->lock, irqflags);
list_for_each_entry(buf, &ceudev->capture, queue)
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
index 30dad7383654..d6489c62b081 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
@@ -81,10 +81,10 @@
#define CSIDPHYSKW0_UTIL_DL1_SKW_ADJ(x) (((x) & 0x3) << 4)
#define CSIDPHYSKW0_UTIL_DL2_SKW_ADJ(x) (((x) & 0x3) << 8)
#define CSIDPHYSKW0_UTIL_DL3_SKW_ADJ(x) (((x) & 0x3) << 12)
-#define CSIDPHYSKW0_DEFAULT_SKW CSIDPHYSKW0_UTIL_DL0_SKW_ADJ(1) | \
- CSIDPHYSKW0_UTIL_DL1_SKW_ADJ(1) | \
- CSIDPHYSKW0_UTIL_DL2_SKW_ADJ(1) | \
- CSIDPHYSKW0_UTIL_DL3_SKW_ADJ(1)
+#define CSIDPHYSKW0_DEFAULT_SKW (CSIDPHYSKW0_UTIL_DL0_SKW_ADJ(1) | \
+ CSIDPHYSKW0_UTIL_DL1_SKW_ADJ(1) | \
+ CSIDPHYSKW0_UTIL_DL2_SKW_ADJ(1) | \
+ CSIDPHYSKW0_UTIL_DL3_SKW_ADJ(1))
#define VSRSTS_RETRIES 20
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index 67dcf22e5ba3..f1c532a5802a 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -76,10 +76,7 @@ static irqreturn_t rga_isr(int irq, void *prv)
WARN_ON(!src);
WARN_ON(!dst);
- dst->timecode = src->timecode;
- dst->vb2_buf.timestamp = src->vb2_buf.timestamp;
- dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst->flags |= src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+ v4l2_m2m_buf_copy_metadata(src, dst, true);
v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
@@ -726,10 +723,10 @@ static int rga_enable_clocks(struct rockchip_rga *rga)
return 0;
-err_disable_sclk:
- clk_disable_unprepare(rga->sclk);
err_disable_aclk:
clk_disable_unprepare(rga->aclk);
+err_disable_sclk:
+ clk_disable_unprepare(rga->sclk);
return ret;
}
diff --git a/drivers/media/platform/samsung/exynos4-is/Kconfig b/drivers/media/platform/samsung/exynos4-is/Kconfig
index da33faa7132e..7f9ba053dd8e 100644
--- a/drivers/media/platform/samsung/exynos4-is/Kconfig
+++ b/drivers/media/platform/samsung/exynos4-is/Kconfig
@@ -47,7 +47,7 @@ config VIDEO_S5P_MIPI_CSIS
config VIDEO_EXYNOS_FIMC_LITE
tristate "EXYNOS FIMC-LITE camera interface driver"
depends on I2C
- depends on SOC_EXYNOS4412 || SOC_EXYNOS5250 || COMPILE_TEST
+ depends on SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250 || COMPILE_TEST
depends on HAS_DMA
select VIDEOBUF2_DMA_CONTIG
select VIDEO_EXYNOS4_IS_COMMON
diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-core.c b/drivers/media/platform/samsung/exynos4-is/fimc-core.c
index a2034ade8b9e..976b4f747ad4 100644
--- a/drivers/media/platform/samsung/exynos4-is/fimc-core.c
+++ b/drivers/media/platform/samsung/exynos4-is/fimc-core.c
@@ -1128,7 +1128,7 @@ static const struct fimc_drvdata fimc_drvdata_exynos4210 = {
.out_buf_count = 32,
};
-/* EXYNOS4412 */
+/* EXYNOS4212, EXYNOS4412 */
static const struct fimc_drvdata fimc_drvdata_exynos4x12 = {
.num_entities = 4,
.lclk_frequency = 166000000UL,
diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-lite.c b/drivers/media/platform/samsung/exynos4-is/fimc-lite.c
index 24b3dda26714..c3146ae08447 100644
--- a/drivers/media/platform/samsung/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/samsung/exynos4-is/fimc-lite.c
@@ -1621,7 +1621,7 @@ static const struct dev_pm_ops fimc_lite_pm_ops = {
NULL)
};
-/* EXYNOS4412 */
+/* EXYNOS4212, EXYNOS4412 */
static struct flite_drvdata fimc_lite_drvdata_exynos4 = {
.max_width = 8192,
.max_height = 8192,
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h
index 5570c79f122f..4b665a3b630f 100644
--- a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h
+++ b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h
@@ -11,6 +11,7 @@
#define JPEG_CORE_H_
#include <linux/interrupt.h>
+#include <media/jpeg.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-ctrls.h>
@@ -36,17 +37,6 @@
#define EXYNOS3250_IRQ_TIMEOUT 0x10000000
-/* a selection of JPEG markers */
-#define JPEG_MARKER_TEM 0x01
-#define JPEG_MARKER_SOF0 0xc0
-#define JPEG_MARKER_DHT 0xc4
-#define JPEG_MARKER_RST 0xd0
-#define JPEG_MARKER_SOI 0xd8
-#define JPEG_MARKER_EOI 0xd9
-#define JPEG_MARKER_SOS 0xda
-#define JPEG_MARKER_DQT 0xdb
-#define JPEG_MARKER_DHP 0xde
-
/* Flags that indicate a format can be used for capture/output */
#define SJPEG_FMT_FLAG_ENC_CAPTURE (1 << 0)
#define SJPEG_FMT_FLAG_ENC_OUTPUT (1 << 1)
diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c
index 45ade7210d26..5dc1f908b49b 100644
--- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c
+++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c
@@ -16,8 +16,10 @@
#include <linux/dma-mapping.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
+#include <linux/err.h>
#include <linux/errno.h>
#include <linux/firmware.h>
+#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -135,7 +137,7 @@ static void channel_swdemux_tsklet(struct tasklet_struct *t)
static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_demux *demux = dvbdmxfeed->demux;
- struct stdemux *stdemux = (struct stdemux *)demux->priv;
+ struct stdemux *stdemux = demux->priv;
struct c8sectpfei *fei = stdemux->c8sectpfei;
struct channel_info *channel;
u32 tmp;
@@ -256,7 +258,7 @@ static int c8sectpfe_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_demux *demux = dvbdmxfeed->demux;
- struct stdemux *stdemux = (struct stdemux *)demux->priv;
+ struct stdemux *stdemux = demux->priv;
struct c8sectpfei *fei = stdemux->c8sectpfei;
struct channel_info *channel;
int idlereq;
@@ -812,30 +814,23 @@ static int c8sectpfe_probe(struct platform_device *pdev)
}
of_node_put(i2c_bus);
- tsin->rst_gpio = of_get_named_gpio(child, "reset-gpios", 0);
-
- ret = gpio_is_valid(tsin->rst_gpio);
- if (!ret) {
- dev_err(dev,
- "reset gpio for tsin%d not valid (gpio=%d)\n",
- tsin->tsin_id, tsin->rst_gpio);
- ret = -EINVAL;
- goto err_node_put;
- }
-
- ret = devm_gpio_request_one(dev, tsin->rst_gpio,
- GPIOF_OUT_INIT_LOW, "NIM reset");
+ /* Acquire reset GPIO and activate it */
+ tsin->rst_gpio = devm_fwnode_gpiod_get(dev,
+ of_fwnode_handle(child),
+ "reset", GPIOD_OUT_HIGH,
+ "NIM reset");
+ ret = PTR_ERR_OR_ZERO(tsin->rst_gpio);
if (ret && ret != -EBUSY) {
- dev_err(dev, "Can't request tsin%d reset gpio\n"
- , fei->channel_data[index]->tsin_id);
+ dev_err(dev, "Can't request tsin%d reset gpio\n",
+ fei->channel_data[index]->tsin_id);
goto err_node_put;
}
if (!ret) {
- /* toggle reset lines */
- gpio_direction_output(tsin->rst_gpio, 0);
+ /* wait for the chip to reset */
usleep_range(3500, 5000);
- gpio_direction_output(tsin->rst_gpio, 1);
+ /* release the reset line */
+ gpiod_set_value_cansleep(tsin->rst_gpio, 0);
usleep_range(3000, 5000);
}
@@ -1173,7 +1168,7 @@ MODULE_DEVICE_TABLE(of, c8sectpfe_match);
static struct platform_driver c8sectpfe_driver = {
.driver = {
.name = "c8sectpfe",
- .of_match_table = of_match_ptr(c8sectpfe_match),
+ .of_match_table = c8sectpfe_match,
},
.probe = c8sectpfe_probe,
.remove_new = c8sectpfe_remove,
diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h
index c9d6021904cd..bf377cc82225 100644
--- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h
+++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h
@@ -16,6 +16,8 @@
#define C8SECTPFE_MAX_TSIN_CHAN 8
+struct gpio_desc;
+
struct channel_info {
int tsin_id;
@@ -25,7 +27,7 @@ struct channel_info {
int i2c;
int dvb_card;
- int rst_gpio;
+ struct gpio_desc *rst_gpio;
struct i2c_adapter *i2c_adapter;
struct i2c_adapter *tuner_i2c;
diff --git a/drivers/media/platform/st/sti/hva/hva-h264.c b/drivers/media/platform/st/sti/hva/hva-h264.c
index 98cb00d2d868..196e631fa4b8 100644
--- a/drivers/media/platform/st/sti/hva/hva-h264.c
+++ b/drivers/media/platform/st/sti/hva/hva-h264.c
@@ -591,7 +591,7 @@ static int hva_h264_prepare_task(struct hva_ctx *pctx,
{
struct hva_dev *hva = ctx_to_hdev(pctx);
struct device *dev = ctx_to_dev(pctx);
- struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv;
+ struct hva_h264_ctx *ctx = pctx->priv;
struct hva_buffer *seq_info = ctx->seq_info;
struct hva_buffer *fwd_ref_frame = ctx->ref_frame;
struct hva_buffer *loc_rec_frame = ctx->rec_frame;
@@ -984,7 +984,7 @@ err:
static int hva_h264_close(struct hva_ctx *pctx)
{
- struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv;
+ struct hva_h264_ctx *ctx = pctx->priv;
struct device *dev = ctx_to_dev(pctx);
if (ctx->seq_info)
@@ -1007,8 +1007,8 @@ static int hva_h264_close(struct hva_ctx *pctx)
static int hva_h264_encode(struct hva_ctx *pctx, struct hva_frame *frame,
struct hva_stream *stream)
{
- struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv;
- struct hva_h264_task *task = (struct hva_h264_task *)ctx->task->vaddr;
+ struct hva_h264_ctx *ctx = pctx->priv;
+ struct hva_h264_task *task = ctx->task->vaddr;
u32 stuffing_bytes = 0;
int ret = 0;
diff --git a/drivers/media/platform/verisilicon/Makefile b/drivers/media/platform/verisilicon/Makefile
index ebd5ede7bef7..6ad2ef885920 100644
--- a/drivers/media/platform/verisilicon/Makefile
+++ b/drivers/media/platform/verisilicon/Makefile
@@ -18,6 +18,9 @@ hantro-vpu-y += \
rockchip_vpu2_hw_h264_dec.o \
rockchip_vpu2_hw_mpeg2_dec.o \
rockchip_vpu2_hw_vp8_dec.o \
+ rockchip_vpu981_hw_av1_dec.o \
+ rockchip_av1_filmgrain.o \
+ rockchip_av1_entropymode.o \
hantro_jpeg.o \
hantro_h264.o \
hantro_hevc.o \
diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h
index 2989ebc631cc..6523ffb74881 100644
--- a/drivers/media/platform/verisilicon/hantro.h
+++ b/drivers/media/platform/verisilicon/hantro.h
@@ -38,6 +38,7 @@ struct hantro_postproc_ops;
#define HANTRO_H264_DECODER BIT(18)
#define HANTRO_HEVC_DECODER BIT(19)
#define HANTRO_VP9_DECODER BIT(20)
+#define HANTRO_AV1_DECODER BIT(21)
#define HANTRO_DECODERS 0xffff0000
/**
@@ -111,6 +112,7 @@ struct hantro_variant {
* @HANTRO_MODE_VP8_DEC: VP8 decoder.
* @HANTRO_MODE_HEVC_DEC: HEVC decoder.
* @HANTRO_MODE_VP9_DEC: VP9 decoder.
+ * @HANTRO_MODE_AV1_DEC: AV1 decoder
*/
enum hantro_codec_mode {
HANTRO_MODE_NONE = -1,
@@ -120,6 +122,7 @@ enum hantro_codec_mode {
HANTRO_MODE_VP8_DEC,
HANTRO_MODE_HEVC_DEC,
HANTRO_MODE_VP9_DEC,
+ HANTRO_MODE_AV1_DEC,
};
/*
@@ -228,6 +231,8 @@ struct hantro_dev {
* @ctrl_handler: Control handler used to register controls.
* @jpeg_quality: User-specified JPEG compression quality.
* @bit_depth: Bit depth of current frame
+ * @need_postproc: Set to true if the bitstream features require to
+ * use the post-processor.
*
* @codec_ops: Set of operations related to codec mode.
* @postproc: Post-processing context.
@@ -237,6 +242,7 @@ struct hantro_dev {
* @vp8_dec: VP8-decoding context.
* @hevc_dec: HEVC-decoding context.
* @vp9_dec: VP9-decoding context.
+ * @av1_dec: AV1-decoding context.
*/
struct hantro_ctx {
struct hantro_dev *dev;
@@ -257,6 +263,7 @@ struct hantro_ctx {
const struct hantro_codec_ops *codec_ops;
struct hantro_postproc_ctx postproc;
+ bool need_postproc;
/* Specific for particular codec modes. */
union {
@@ -265,6 +272,7 @@ struct hantro_ctx {
struct hantro_vp8_dec_hw_ctx vp8_dec;
struct hantro_hevc_dec_hw_ctx hevc_dec;
struct hantro_vp9_dec_hw_ctx vp9_dec;
+ struct hantro_av1_dec_hw_ctx av1_dec;
};
};
diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
index 09c74a573ddb..c0a368bacf88 100644
--- a/drivers/media/platform/verisilicon/hantro_drv.c
+++ b/drivers/media/platform/verisilicon/hantro_drv.c
@@ -275,7 +275,13 @@ static int hantro_try_ctrl(struct v4l2_ctrl *ctrl)
/* We only support profile 0 */
if (dec_params->profile != 0)
return -EINVAL;
+ } else if (ctrl->id == V4L2_CID_STATELESS_AV1_SEQUENCE) {
+ const struct v4l2_ctrl_av1_sequence *sequence = ctrl->p_new.p_av1_sequence;
+
+ if (sequence->bit_depth != 8 && sequence->bit_depth != 10)
+ return -EINVAL;
}
+
return 0;
}
@@ -313,7 +319,7 @@ static int hantro_vp9_s_ctrl(struct v4l2_ctrl *ctrl)
if (ctx->bit_depth == bit_depth)
return 0;
- return hantro_reset_raw_fmt(ctx, bit_depth);
+ return hantro_reset_raw_fmt(ctx, bit_depth, HANTRO_AUTO_POSTPROC);
}
default:
return -EINVAL;
@@ -337,7 +343,37 @@ static int hantro_hevc_s_ctrl(struct v4l2_ctrl *ctrl)
if (ctx->bit_depth == bit_depth)
return 0;
- return hantro_reset_raw_fmt(ctx, bit_depth);
+ return hantro_reset_raw_fmt(ctx, bit_depth, HANTRO_AUTO_POSTPROC);
+ }
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hantro_av1_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct hantro_ctx *ctx;
+
+ ctx = container_of(ctrl->handler,
+ struct hantro_ctx, ctrl_handler);
+
+ switch (ctrl->id) {
+ case V4L2_CID_STATELESS_AV1_SEQUENCE:
+ {
+ int bit_depth = ctrl->p_new.p_av1_sequence->bit_depth;
+ bool need_postproc = HANTRO_AUTO_POSTPROC;
+
+ if (ctrl->p_new.p_av1_sequence->flags
+ & V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT)
+ need_postproc = HANTRO_FORCE_POSTPROC;
+
+ if (ctx->bit_depth == bit_depth &&
+ ctx->need_postproc == need_postproc)
+ return 0;
+
+ return hantro_reset_raw_fmt(ctx, bit_depth, need_postproc);
}
default:
return -EINVAL;
@@ -363,6 +399,11 @@ static const struct v4l2_ctrl_ops hantro_hevc_ctrl_ops = {
.s_ctrl = hantro_hevc_s_ctrl,
};
+static const struct v4l2_ctrl_ops hantro_av1_ctrl_ops = {
+ .try_ctrl = hantro_try_ctrl,
+ .s_ctrl = hantro_av1_s_ctrl,
+};
+
#define HANTRO_JPEG_ACTIVE_MARKERS (V4L2_JPEG_ACTIVE_MARKER_APP0 | \
V4L2_JPEG_ACTIVE_MARKER_COM | \
V4L2_JPEG_ACTIVE_MARKER_DQT | \
@@ -525,6 +566,28 @@ static const struct hantro_ctrl controls[] = {
.cfg = {
.id = V4L2_CID_STATELESS_VP9_COMPRESSED_HDR,
},
+ }, {
+ .codec = HANTRO_AV1_DECODER,
+ .cfg = {
+ .id = V4L2_CID_STATELESS_AV1_FRAME,
+ },
+ }, {
+ .codec = HANTRO_AV1_DECODER,
+ .cfg = {
+ .id = V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY,
+ .dims = { V4L2_AV1_MAX_TILE_COUNT },
+ },
+ }, {
+ .codec = HANTRO_AV1_DECODER,
+ .cfg = {
+ .id = V4L2_CID_STATELESS_AV1_SEQUENCE,
+ .ops = &hantro_av1_ctrl_ops,
+ },
+ }, {
+ .codec = HANTRO_AV1_DECODER,
+ .cfg = {
+ .id = V4L2_CID_STATELESS_AV1_FILM_GRAIN,
+ },
},
};
@@ -656,6 +719,7 @@ static const struct of_device_id of_hantro_match[] = {
{ .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, },
{ .compatible = "rockchip,rk3568-vepu", .data = &rk3568_vepu_variant, },
{ .compatible = "rockchip,rk3568-vpu", .data = &rk3568_vpu_variant, },
+ { .compatible = "rockchip,rk3588-av1-vpu", .data = &rk3588_vpu981_variant, },
#endif
#ifdef CONFIG_VIDEO_HANTRO_IMX8M
{ .compatible = "nxp,imx8mm-vpu-g1", .data = &imx8mm_vpu_g1_variant, },
diff --git a/drivers/media/platform/verisilicon/hantro_hevc.c b/drivers/media/platform/verisilicon/hantro_hevc.c
index 9383fb7081f6..2c14330bc562 100644
--- a/drivers/media/platform/verisilicon/hantro_hevc.c
+++ b/drivers/media/platform/verisilicon/hantro_hevc.c
@@ -109,7 +109,7 @@ static int tile_buffer_reallocate(struct hantro_ctx *ctx)
&hevc_dec->tile_filter.dma,
GFP_KERNEL);
if (!hevc_dec->tile_filter.cpu)
- goto err_free_tile_buffers;
+ return -ENOMEM;
hevc_dec->tile_filter.size = size;
size = (VERT_SAO_RAM_SIZE * height64 * (num_tile_cols - 1) * ctx->bit_depth) / 8;
@@ -125,31 +125,26 @@ static int tile_buffer_reallocate(struct hantro_ctx *ctx)
&hevc_dec->tile_bsd.dma,
GFP_KERNEL);
if (!hevc_dec->tile_bsd.cpu)
- goto err_free_tile_buffers;
+ goto err_free_sao_buffers;
hevc_dec->tile_bsd.size = size;
hevc_dec->num_tile_cols_allocated = num_tile_cols;
return 0;
-err_free_tile_buffers:
- if (hevc_dec->tile_filter.cpu)
- dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size,
- hevc_dec->tile_filter.cpu,
- hevc_dec->tile_filter.dma);
- hevc_dec->tile_filter.cpu = NULL;
-
+err_free_sao_buffers:
if (hevc_dec->tile_sao.cpu)
dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size,
hevc_dec->tile_sao.cpu,
hevc_dec->tile_sao.dma);
hevc_dec->tile_sao.cpu = NULL;
- if (hevc_dec->tile_bsd.cpu)
- dma_free_coherent(vpu->dev, hevc_dec->tile_bsd.size,
- hevc_dec->tile_bsd.cpu,
- hevc_dec->tile_bsd.dma);
- hevc_dec->tile_bsd.cpu = NULL;
+err_free_tile_buffers:
+ if (hevc_dec->tile_filter.cpu)
+ dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size,
+ hevc_dec->tile_filter.cpu,
+ hevc_dec->tile_filter.dma);
+ hevc_dec->tile_filter.cpu = NULL;
return -ENOMEM;
}
diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h
index e83f0c523a30..7f33f7b07ce4 100644
--- a/drivers/media/platform/verisilicon/hantro_hw.h
+++ b/drivers/media/platform/verisilicon/hantro_hw.h
@@ -15,6 +15,9 @@
#include <media/v4l2-vp9.h>
#include <media/videobuf2-core.h>
+#include "rockchip_av1_entropymode.h"
+#include "rockchip_av1_filmgrain.h"
+
#define DEC_8190_ALIGN_MASK 0x07U
#define MB_DIM 16
@@ -35,6 +38,8 @@
#define NUM_REF_PICTURES (V4L2_HEVC_DPB_ENTRIES_NUM_MAX + 1)
+#define AV1_MAX_FRAME_BUF_COUNT (V4L2_AV1_TOTAL_REFS_PER_FRAME + 1)
+
struct hantro_dev;
struct hantro_ctx;
struct hantro_buf;
@@ -248,6 +253,84 @@ struct hantro_vp9_dec_hw_ctx {
};
/**
+ * struct hantro_av1_dec_ctrls
+ * @sequence: AV1 Sequence
+ * @tile_group_entry: AV1 Tile Group entry
+ * @frame: AV1 Frame Header OBU
+ * @film_grain: AV1 Film Grain
+ */
+struct hantro_av1_dec_ctrls {
+ const struct v4l2_ctrl_av1_sequence *sequence;
+ const struct v4l2_ctrl_av1_tile_group_entry *tile_group_entry;
+ const struct v4l2_ctrl_av1_frame *frame;
+ const struct v4l2_ctrl_av1_film_grain *film_grain;
+};
+
+struct hantro_av1_frame_ref {
+ int width;
+ int height;
+ int mi_cols;
+ int mi_rows;
+ u64 timestamp;
+ enum v4l2_av1_frame_type frame_type;
+ bool used;
+ u32 order_hint;
+ u32 order_hints[V4L2_AV1_TOTAL_REFS_PER_FRAME];
+ struct vb2_v4l2_buffer *vb2_ref;
+};
+
+/**
+ * struct hantro_av1_dec_hw_ctx
+ * @db_data_col: db tile col data buffer
+ * @db_ctrl_col: db tile col ctrl buffer
+ * @cdef_col: cdef tile col buffer
+ * @sr_col: sr tile col buffer
+ * @lr_col: lr tile col buffer
+ * @global_model: global model buffer
+ * @tile_info: tile info buffer
+ * @segment: segmentation info buffer
+ * @film_grain: film grain buffer
+ * @prob_tbl: probability table
+ * @prob_tbl_out: probability table output
+ * @tile_buf: tile buffer
+ * @ctrls: V4L2 controls attached to a run
+ * @frame_refs: reference frames info slots
+ * @ref_frame_sign_bias: array of sign bias
+ * @num_tile_cols_allocated: number of allocated tiles
+ * @cdfs: current probabilities structure
+ * @cdfs_ndvc: current mv probabilities structure
+ * @default_cdfs: default probabilities structure
+ * @default_cdfs_ndvc: default mv probabilties structure
+ * @cdfs_last: stored probabilities structures
+ * @cdfs_last_ndvc: stored mv probabilities structures
+ * @current_frame_index: index of the current in frame_refs array
+ */
+struct hantro_av1_dec_hw_ctx {
+ struct hantro_aux_buf db_data_col;
+ struct hantro_aux_buf db_ctrl_col;
+ struct hantro_aux_buf cdef_col;
+ struct hantro_aux_buf sr_col;
+ struct hantro_aux_buf lr_col;
+ struct hantro_aux_buf global_model;
+ struct hantro_aux_buf tile_info;
+ struct hantro_aux_buf segment;
+ struct hantro_aux_buf film_grain;
+ struct hantro_aux_buf prob_tbl;
+ struct hantro_aux_buf prob_tbl_out;
+ struct hantro_aux_buf tile_buf;
+ struct hantro_av1_dec_ctrls ctrls;
+ struct hantro_av1_frame_ref frame_refs[AV1_MAX_FRAME_BUF_COUNT];
+ u32 ref_frame_sign_bias[V4L2_AV1_TOTAL_REFS_PER_FRAME];
+ unsigned int num_tile_cols_allocated;
+ struct av1cdfs *cdfs;
+ struct mvcdfs *cdfs_ndvc;
+ struct av1cdfs default_cdfs;
+ struct mvcdfs default_cdfs_ndvc;
+ struct av1cdfs cdfs_last[NUM_REF_FRAMES];
+ struct mvcdfs cdfs_last_ndvc[NUM_REF_FRAMES];
+ int current_frame_index;
+};
+/**
* struct hantro_postproc_ctx
*
* @dec_q: References buffers, in decoder format.
@@ -320,11 +403,13 @@ extern const struct hantro_variant rk3328_vpu_variant;
extern const struct hantro_variant rk3399_vpu_variant;
extern const struct hantro_variant rk3568_vepu_variant;
extern const struct hantro_variant rk3568_vpu_variant;
+extern const struct hantro_variant rk3588_vpu981_variant;
extern const struct hantro_variant sama5d4_vdec_variant;
extern const struct hantro_variant sunxi_vpu_variant;
extern const struct hantro_postproc_ops hantro_g1_postproc_ops;
extern const struct hantro_postproc_ops hantro_g2_postproc_ops;
+extern const struct hantro_postproc_ops rockchip_vpu981_postproc_ops;
extern const u32 hantro_vp8_dec_mc_filter[8][6];
@@ -361,6 +446,10 @@ void hantro_hevc_ref_init(struct hantro_ctx *ctx);
dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx, s32 poc);
int hantro_hevc_add_ref_buf(struct hantro_ctx *ctx, int poc, dma_addr_t addr);
+int rockchip_vpu981_av1_dec_init(struct hantro_ctx *ctx);
+void rockchip_vpu981_av1_dec_exit(struct hantro_ctx *ctx);
+int rockchip_vpu981_av1_dec_run(struct hantro_ctx *ctx);
+void rockchip_vpu981_av1_dec_done(struct hantro_ctx *ctx);
static inline unsigned short hantro_vp9_num_sbs(unsigned short dimension)
{
@@ -417,6 +506,19 @@ hantro_hevc_mv_size(unsigned int width, unsigned int height)
return width * height / 16;
}
+static inline unsigned short hantro_av1_num_sbs(unsigned short dimension)
+{
+ return DIV_ROUND_UP(dimension, 64);
+}
+
+static inline size_t
+hantro_av1_mv_size(unsigned int width, unsigned int height)
+{
+ size_t num_sbs = hantro_av1_num_sbs(width) * hantro_av1_num_sbs(height);
+
+ return ALIGN(num_sbs * 384, 16) * 2 + 512;
+}
+
int hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx);
int rockchip_vpu2_mpeg2_dec_run(struct hantro_ctx *ctx);
void hantro_mpeg2_dec_copy_qtable(u8 *qtable,
diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c
index 6437423ccf3a..c977d64105b1 100644
--- a/drivers/media/platform/verisilicon/hantro_postproc.c
+++ b/drivers/media/platform/verisilicon/hantro_postproc.c
@@ -57,6 +57,10 @@ bool hantro_needs_postproc(const struct hantro_ctx *ctx,
{
if (ctx->is_encoder)
return false;
+
+ if (ctx->need_postproc)
+ return true;
+
return fmt->postprocessed;
}
@@ -197,7 +201,7 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx)
unsigned int i, buf_size;
/* this should always pick native format */
- fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth);
+ fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth, HANTRO_AUTO_POSTPROC);
if (!fmt)
return -EINVAL;
v4l2_fill_pixfmt_mp(&pix_mp, fmt->fourcc, ctx->src_fmt.width,
@@ -213,6 +217,9 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx)
else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_HEVC_SLICE)
buf_size += hantro_hevc_mv_size(pix_mp.width,
pix_mp.height);
+ else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_AV1_FRAME)
+ buf_size += hantro_av1_mv_size(pix_mp.width,
+ pix_mp.height);
for (i = 0; i < num_buffers; ++i) {
struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i];
diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
index 61cfaaf4e927..e871c078dd59 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.c
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
@@ -31,15 +31,21 @@
#define HANTRO_DEFAULT_BIT_DEPTH 8
static int hantro_set_fmt_out(struct hantro_ctx *ctx,
- struct v4l2_pix_format_mplane *pix_mp);
+ struct v4l2_pix_format_mplane *pix_mp,
+ bool need_postproc);
static int hantro_set_fmt_cap(struct hantro_ctx *ctx,
struct v4l2_pix_format_mplane *pix_mp);
static const struct hantro_fmt *
-hantro_get_formats(const struct hantro_ctx *ctx, unsigned int *num_fmts)
+hantro_get_formats(const struct hantro_ctx *ctx, unsigned int *num_fmts, bool need_postproc)
{
const struct hantro_fmt *formats;
+ if (need_postproc) {
+ *num_fmts = 0;
+ return NULL;
+ }
+
if (ctx->is_encoder) {
formats = ctx->dev->variant->enc_fmts;
*num_fmts = ctx->dev->variant->num_enc_fmts;
@@ -71,6 +77,7 @@ int hantro_get_format_depth(u32 fourcc)
switch (fourcc) {
case V4L2_PIX_FMT_P010:
case V4L2_PIX_FMT_P010_4L4:
+ case V4L2_PIX_FMT_NV15_4L4:
return 10;
default:
return 8;
@@ -85,6 +92,10 @@ hantro_check_depth_match(const struct hantro_fmt *fmt, int bit_depth)
if (!fmt->match_depth && !fmt->postprocessed)
return true;
+ /* 0 means default depth, which is 8 */
+ if (!bit_depth)
+ bit_depth = HANTRO_DEFAULT_BIT_DEPTH;
+
fmt_depth = hantro_get_format_depth(fmt->fourcc);
/*
@@ -103,7 +114,7 @@ hantro_find_format(const struct hantro_ctx *ctx, u32 fourcc)
const struct hantro_fmt *formats;
unsigned int i, num_fmts;
- formats = hantro_get_formats(ctx, &num_fmts);
+ formats = hantro_get_formats(ctx, &num_fmts, HANTRO_AUTO_POSTPROC);
for (i = 0; i < num_fmts; i++)
if (formats[i].fourcc == fourcc)
return &formats[i];
@@ -116,18 +127,28 @@ hantro_find_format(const struct hantro_ctx *ctx, u32 fourcc)
}
const struct hantro_fmt *
-hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream, int bit_depth)
+hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream,
+ int bit_depth, bool need_postproc)
{
const struct hantro_fmt *formats;
unsigned int i, num_fmts;
- formats = hantro_get_formats(ctx, &num_fmts);
+ formats = hantro_get_formats(ctx, &num_fmts, need_postproc);
+ for (i = 0; i < num_fmts; i++) {
+ if (bitstream == (formats[i].codec_mode !=
+ HANTRO_MODE_NONE) &&
+ hantro_check_depth_match(&formats[i], bit_depth))
+ return &formats[i];
+ }
+
+ formats = hantro_get_postproc_formats(ctx, &num_fmts);
for (i = 0; i < num_fmts; i++) {
if (bitstream == (formats[i].codec_mode !=
HANTRO_MODE_NONE) &&
hantro_check_depth_match(&formats[i], bit_depth))
return &formats[i];
}
+
return NULL;
}
@@ -194,7 +215,7 @@ static int vidioc_enum_fmt(struct file *file, void *priv,
*/
skip_mode_none = capture == ctx->is_encoder;
- formats = hantro_get_formats(ctx, &num_fmts);
+ formats = hantro_get_formats(ctx, &num_fmts, HANTRO_AUTO_POSTPROC);
for (i = 0; i < num_fmts; i++) {
bool mode_none = formats[i].codec_mode == HANTRO_MODE_NONE;
fmt = &formats[i];
@@ -289,7 +310,7 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx,
fmt = hantro_find_format(ctx, pix_mp->pixelformat);
if (!fmt) {
- fmt = hantro_get_default_fmt(ctx, coded, HANTRO_DEFAULT_BIT_DEPTH);
+ fmt = hantro_get_default_fmt(ctx, coded, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC);
pix_mp->pixelformat = fmt->fourcc;
}
@@ -328,6 +349,11 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx,
pix_mp->plane_fmt[0].sizeimage +=
hantro_hevc_mv_size(pix_mp->width,
pix_mp->height);
+ else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_AV1_FRAME &&
+ !hantro_needs_postproc(ctx, fmt))
+ pix_mp->plane_fmt[0].sizeimage +=
+ hantro_av1_mv_size(pix_mp->width,
+ pix_mp->height);
} else if (!pix_mp->plane_fmt[0].sizeimage) {
/*
* For coded formats the application can specify
@@ -373,7 +399,7 @@ hantro_reset_encoded_fmt(struct hantro_ctx *ctx)
const struct hantro_fmt *vpu_fmt;
struct v4l2_pix_format_mplane fmt;
- vpu_fmt = hantro_get_default_fmt(ctx, true, HANTRO_DEFAULT_BIT_DEPTH);
+ vpu_fmt = hantro_get_default_fmt(ctx, true, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC);
if (!vpu_fmt)
return;
@@ -383,17 +409,17 @@ hantro_reset_encoded_fmt(struct hantro_ctx *ctx)
if (ctx->is_encoder)
hantro_set_fmt_cap(ctx, &fmt);
else
- hantro_set_fmt_out(ctx, &fmt);
+ hantro_set_fmt_out(ctx, &fmt, HANTRO_AUTO_POSTPROC);
}
int
-hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth)
+hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth, bool need_postproc)
{
const struct hantro_fmt *raw_vpu_fmt;
struct v4l2_pix_format_mplane raw_fmt, *encoded_fmt;
int ret;
- raw_vpu_fmt = hantro_get_default_fmt(ctx, false, bit_depth);
+ raw_vpu_fmt = hantro_get_default_fmt(ctx, false, bit_depth, need_postproc);
if (!raw_vpu_fmt)
return -EINVAL;
@@ -408,12 +434,14 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth)
raw_fmt.width = encoded_fmt->width;
raw_fmt.height = encoded_fmt->height;
if (ctx->is_encoder)
- ret = hantro_set_fmt_out(ctx, &raw_fmt);
+ ret = hantro_set_fmt_out(ctx, &raw_fmt, need_postproc);
else
ret = hantro_set_fmt_cap(ctx, &raw_fmt);
- if (!ret)
+ if (!ret) {
ctx->bit_depth = bit_depth;
+ ctx->need_postproc = need_postproc;
+ }
return ret;
}
@@ -421,7 +449,7 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth)
void hantro_reset_fmts(struct hantro_ctx *ctx)
{
hantro_reset_encoded_fmt(ctx);
- hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH);
+ hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC);
}
static void
@@ -468,7 +496,8 @@ hantro_update_requires_hold_capture_buf(struct hantro_ctx *ctx, u32 fourcc)
}
static int hantro_set_fmt_out(struct hantro_ctx *ctx,
- struct v4l2_pix_format_mplane *pix_mp)
+ struct v4l2_pix_format_mplane *pix_mp,
+ bool need_postproc)
{
struct vb2_queue *vq;
int ret;
@@ -521,7 +550,9 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx,
* changes to the raw format.
*/
if (!ctx->is_encoder)
- hantro_reset_raw_fmt(ctx, hantro_get_format_depth(pix_mp->pixelformat));
+ hantro_reset_raw_fmt(ctx,
+ hantro_get_format_depth(pix_mp->pixelformat),
+ need_postproc);
/* Colorimetry information are always propagated. */
ctx->dst_fmt.colorspace = pix_mp->colorspace;
@@ -584,7 +615,7 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx,
* changes to the raw format.
*/
if (ctx->is_encoder)
- hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH);
+ hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC);
/* Colorimetry information are always propagated. */
ctx->src_fmt.colorspace = pix_mp->colorspace;
@@ -604,7 +635,7 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx,
static int
vidioc_s_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f)
{
- return hantro_set_fmt_out(fh_to_ctx(priv), &f->fmt.pix_mp);
+ return hantro_set_fmt_out(fh_to_ctx(priv), &f->fmt.pix_mp, HANTRO_AUTO_POSTPROC);
}
static int
diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.h b/drivers/media/platform/verisilicon/hantro_v4l2.h
index 9ea2fef57dcd..fca7e3a690e5 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.h
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.h
@@ -18,13 +18,17 @@
#include "hantro.h"
+#define HANTRO_FORCE_POSTPROC true
+#define HANTRO_AUTO_POSTPROC false
+
extern const struct v4l2_ioctl_ops hantro_ioctl_ops;
extern const struct vb2_ops hantro_queue_ops;
-int hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth);
+int hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth, bool need_postproc);
void hantro_reset_fmts(struct hantro_ctx *ctx);
int hantro_get_format_depth(u32 fourcc);
const struct hantro_fmt *
-hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream, int bit_depth);
+hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream,
+ int bit_depth, bool need_postproc);
#endif /* HANTRO_V4L2_H_ */
diff --git a/drivers/media/platform/verisilicon/rockchip_av1_entropymode.c b/drivers/media/platform/verisilicon/rockchip_av1_entropymode.c
new file mode 100644
index 000000000000..b1ae72ad675e
--- /dev/null
+++ b/drivers/media/platform/verisilicon/rockchip_av1_entropymode.c
@@ -0,0 +1,4424 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2016, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+
+#include "hantro.h"
+#include "rockchip_av1_entropymode.h"
+
+#define AOM_ICDF ICDF
+#define AOM_CDF2(a0) AOM_ICDF(a0)
+#define AOM_CDF3(a0, a1) \
+ AOM_ICDF(a0), AOM_ICDF(a1)
+#define AOM_CDF4(a0, a1, a2) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2)
+#define AOM_CDF5(a0, a1, a2, a3) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3)
+#define AOM_CDF6(a0, a1, a2, a3, a4) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4)
+#define AOM_CDF7(a0, a1, a2, a3, a4, a5) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), \
+ AOM_ICDF(a3), AOM_ICDF(a4), AOM_ICDF(a5)
+#define AOM_CDF8(a0, a1, a2, a3, a4, a5, a6) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), \
+ AOM_ICDF(a3), AOM_ICDF(a4), AOM_ICDF(a5), AOM_ICDF(a6)
+#define AOM_CDF9(a0, a1, a2, a3, a4, a5, a6, a7) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), \
+ AOM_ICDF(a4), AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7)
+#define AOM_CDF10(a0, a1, a2, a3, a4, a5, a6, a7, a8) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), \
+ AOM_ICDF(a4), AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8)
+#define AOM_CDF11(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), \
+ AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9)
+#define AOM_CDF12(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), AOM_ICDF(a5), \
+ AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), AOM_ICDF(a10)
+#define AOM_CDF13(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), AOM_ICDF(a5), \
+ AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), AOM_ICDF(a10), AOM_ICDF(a11)
+#define AOM_CDF14(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), \
+ AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), \
+ AOM_ICDF(a10), AOM_ICDF(a11), AOM_ICDF(a12)
+#define AOM_CDF15(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), \
+ AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), \
+ AOM_ICDF(a10), AOM_ICDF(a11), AOM_ICDF(a12), AOM_ICDF(a13)
+#define AOM_CDF16(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) \
+ AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), \
+ AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), \
+ AOM_ICDF(a10), AOM_ICDF(a11), AOM_ICDF(a12), AOM_ICDF(a13), AOM_ICDF(a14)
+
+static const u16 default_kf_y_mode_cdf
+ [KF_MODE_CONTEXTS][KF_MODE_CONTEXTS][CDF_SIZE(AV1_INTRA_MODES)] = {
+ {
+ {
+ AOM_CDF13(15588, 17027, 19338, 20218, 20682, 21110,
+ 21825, 23244, 24189, 28165, 29093, 30466)
+ },
+ {
+ AOM_CDF13(12016, 18066, 19516, 20303, 20719, 21444,
+ 21888, 23032, 24434, 28658, 30172, 31409)
+ },
+ {
+ AOM_CDF13(10052, 10771, 22296, 22788, 23055, 23239,
+ 24133, 25620, 26160, 29336, 29929, 31567)
+ },
+ {
+ AOM_CDF13(14091, 15406, 16442, 18808, 19136, 19546,
+ 19998, 22096, 24746, 29585, 30958, 32462)
+ },
+ {
+ AOM_CDF13(12122, 13265, 15603, 16501, 18609, 20033,
+ 22391, 25583, 26437, 30261, 31073, 32475)
+ }
+ },
+ {
+ {
+ AOM_CDF13(10023, 19585, 20848, 21440, 21832, 22760,
+ 23089, 24023, 25381, 29014, 30482, 31436)
+ },
+ {
+ AOM_CDF13(5983, 24099, 24560, 24886, 25066, 25795,
+ 25913, 26423, 27610, 29905, 31276, 31794)
+ },
+ {
+ AOM_CDF13(7444, 12781, 20177, 20728, 21077, 21607,
+ 22170, 23405, 24469, 27915, 29090, 30492)
+ },
+ {
+ AOM_CDF13(8537, 14689, 15432, 17087, 17408, 18172,
+ 18408, 19825, 24649, 29153, 31096, 32210)
+ },
+ {
+ AOM_CDF13(7543, 14231, 15496, 16195, 17905, 20717,
+ 21984, 24516, 26001, 29675, 30981, 31994)
+ }
+ },
+ {
+ {
+ AOM_CDF13(12613, 13591, 21383, 22004, 22312, 22577,
+ 23401, 25055, 25729, 29538, 30305, 32077)
+ },
+ {
+ AOM_CDF13(9687, 13470, 18506, 19230, 19604, 20147,
+ 20695, 22062, 23219, 27743, 29211, 30907)
+ },
+ {
+ AOM_CDF13(6183, 6505, 26024, 26252, 26366, 26434,
+ 27082, 28354, 28555, 30467, 30794, 32086)
+ },
+ {
+ AOM_CDF13(10718, 11734, 14954, 17224, 17565, 17924,
+ 18561, 21523, 23878, 28975, 30287, 32252)
+ },
+ {
+ AOM_CDF13(9194, 9858, 16501, 17263, 18424, 19171,
+ 21563, 25961, 26561, 30072, 30737, 32463)
+ }
+ },
+ {
+ {
+ AOM_CDF13(12602, 14399, 15488, 18381, 18778, 19315,
+ 19724, 21419, 25060, 29696, 30917, 32409)
+ },
+ {
+ AOM_CDF13(8203, 13821, 14524, 17105, 17439, 18131,
+ 18404, 19468, 25225, 29485, 31158, 32342)
+ },
+ {
+ AOM_CDF13(8451, 9731, 15004, 17643, 18012, 18425,
+ 19070, 21538, 24605, 29118, 30078, 32018)
+ },
+ {
+ AOM_CDF13(7714, 9048, 9516, 16667, 16817, 16994,
+ 17153, 18767, 26743, 30389, 31536, 32528)
+ },
+ {
+ AOM_CDF13(8843, 10280, 11496, 15317, 16652, 17943,
+ 19108, 22718, 25769, 29953, 30983, 32485)
+ }
+ },
+ {
+ {
+ AOM_CDF13(12578, 13671, 15979, 16834, 19075, 20913,
+ 22989, 25449, 26219, 30214, 31150, 32477)
+ },
+ {
+ AOM_CDF13(9563, 13626, 15080, 15892, 17756, 20863,
+ 22207, 24236, 25380, 29653, 31143, 32277)
+ },
+ {
+ AOM_CDF13(8356, 8901, 17616, 18256, 19350, 20106,
+ 22598, 25947, 26466, 29900, 30523, 32261)
+ },
+ {
+ AOM_CDF13(10835, 11815, 13124, 16042, 17018, 18039,
+ 18947, 22753, 24615, 29489, 30883, 32482)
+ },
+ {
+ AOM_CDF13(7618, 8288, 9859, 10509, 15386, 18657,
+ 22903, 28776, 29180, 31355, 31802, 32593)
+ }
+ }
+};
+
+static const u16 default_angle_delta_cdf[DIRECTIONAL_MODES]
+ [CDF_SIZE(2 * MAX_ANGLE_DELTA + 1)] = {
+ { AOM_CDF7(2180, 5032, 7567, 22776, 26989, 30217) },
+ { AOM_CDF7(2301, 5608, 8801, 23487, 26974, 30330) },
+ { AOM_CDF7(3780, 11018, 13699, 19354, 23083, 31286) },
+ { AOM_CDF7(4581, 11226, 15147, 17138, 21834, 28397) },
+ { AOM_CDF7(1737, 10927, 14509, 19588, 22745, 28823) },
+ { AOM_CDF7(2664, 10176, 12485, 17650, 21600, 30495) },
+ { AOM_CDF7(2240, 11096, 15453, 20341, 22561, 28917) },
+ { AOM_CDF7(3605, 10428, 12459, 17676, 21244, 30655) }
+};
+
+static const u16 default_if_y_mode_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(AV1_INTRA_MODES)] = {
+ {
+ AOM_CDF13(22801, 23489, 24293, 24756, 25601, 26123,
+ 26606, 27418, 27945, 29228, 29685, 30349)
+ },
+ {
+ AOM_CDF13(18673, 19845, 22631, 23318, 23950, 24649,
+ 25527, 27364, 28152, 29701, 29984, 30852)
+ },
+ {
+ AOM_CDF13(19770, 20979, 23396, 23939, 24241, 24654,
+ 25136, 27073, 27830, 29360, 29730, 30659)
+ },
+ {
+ AOM_CDF13(20155, 21301, 22838, 23178, 23261, 23533,
+ 23703, 24804, 25352, 26575, 27016, 28049)
+ }
+};
+
+static const u16 default_uv_mode_cdf[CFL_ALLOWED_TYPES]
+ [AV1_INTRA_MODES][CDF_SIZE(UV_INTRA_MODES)] = {
+ {
+ {
+ AOM_CDF13(22631, 24152, 25378, 25661, 25986, 26520,
+ 27055, 27923, 28244, 30059, 30941, 31961)
+ },
+ {
+ AOM_CDF13(9513, 26881, 26973, 27046, 27118, 27664,
+ 27739, 27824, 28359, 29505, 29800, 31796)
+ },
+ {
+ AOM_CDF13(9845, 9915, 28663, 28704, 28757, 28780,
+ 29198, 29822, 29854, 30764, 31777, 32029)
+ },
+ {
+ AOM_CDF13(13639, 13897, 14171, 25331, 25606, 25727,
+ 25953, 27148, 28577, 30612, 31355, 32493)
+ },
+ {
+ AOM_CDF13(9764, 9835, 9930, 9954, 25386, 27053,
+ 27958, 28148, 28243, 31101, 31744, 32363)
+ },
+ {
+ AOM_CDF13(11825, 13589, 13677, 13720, 15048, 29213,
+ 29301, 29458, 29711, 31161, 31441, 32550)
+ },
+ {
+ AOM_CDF13(14175, 14399, 16608, 16821, 17718, 17775,
+ 28551, 30200, 30245, 31837, 32342, 32667)
+ },
+ {
+ AOM_CDF13(12885, 13038, 14978, 15590, 15673, 15748,
+ 16176, 29128, 29267, 30643, 31961, 32461)
+ },
+ {
+ AOM_CDF13(12026, 13661, 13874, 15305, 15490, 15726,
+ 15995, 16273, 28443, 30388, 30767, 32416)
+ },
+ {
+ AOM_CDF13(19052, 19840, 20579, 20916, 21150, 21467,
+ 21885, 22719, 23174, 28861, 30379, 32175)
+ },
+ {
+ AOM_CDF13(18627, 19649, 20974, 21219, 21492, 21816,
+ 22199, 23119, 23527, 27053, 31397, 32148)
+ },
+ {
+ AOM_CDF13(17026, 19004, 19997, 20339, 20586, 21103,
+ 21349, 21907, 22482, 25896, 26541, 31819)
+ },
+ {
+ AOM_CDF13(12124, 13759, 14959, 14992, 15007, 15051,
+ 15078, 15166, 15255, 15753, 16039, 16606)
+ }
+ },
+ {
+ {
+ AOM_CDF14(10407, 11208, 12900, 13181, 13823, 14175,
+ 14899, 15656, 15986, 20086, 20995, 22455,
+ 24212)
+ },
+ {
+ AOM_CDF14(4532, 19780, 20057, 20215, 20428, 21071,
+ 21199, 21451, 22099, 24228, 24693, 27032,
+ 29472)
+ },
+ {
+ AOM_CDF14(5273, 5379, 20177, 20270, 20385, 20439,
+ 20949, 21695, 21774, 23138, 24256, 24703,
+ 26679)
+ },
+ {
+ AOM_CDF14(6740, 7167, 7662, 14152, 14536, 14785,
+ 15034, 16741, 18371, 21520, 22206, 23389,
+ 24182)
+ },
+ {
+ AOM_CDF14(4987, 5368, 5928, 6068, 19114, 20315, 21857,
+ 22253, 22411, 24911, 25380, 26027, 26376)
+ },
+ {
+ AOM_CDF14(5370, 6889, 7247, 7393, 9498, 21114, 21402,
+ 21753, 21981, 24780, 25386, 26517, 27176)
+ },
+ {
+ AOM_CDF14(4816, 4961, 7204, 7326, 8765, 8930, 20169,
+ 20682, 20803, 23188, 23763, 24455, 24940)
+ },
+ {
+ AOM_CDF14(6608, 6740, 8529, 9049, 9257, 9356, 9735,
+ 18827, 19059, 22336, 23204, 23964, 24793)
+ },
+ {
+ AOM_CDF14(5998, 7419, 7781, 8933, 9255, 9549, 9753,
+ 10417, 18898, 22494, 23139, 24764, 25989)
+ },
+ {
+ AOM_CDF14(10660, 11298, 12550, 12957, 13322, 13624,
+ 14040, 15004, 15534, 20714, 21789, 23443,
+ 24861)
+ },
+ {
+ AOM_CDF14(10522, 11530, 12552, 12963, 13378, 13779,
+ 14245, 15235, 15902, 20102, 22696, 23774,
+ 25838)
+ },
+ {
+ AOM_CDF14(10099, 10691, 12639, 13049, 13386, 13665,
+ 14125, 15163, 15636, 19676, 20474, 23519,
+ 25208)
+ },
+ {
+ AOM_CDF14(3144, 5087, 7382, 7504, 7593, 7690, 7801,
+ 8064, 8232, 9248, 9875, 10521, 29048)
+ }
+ }
+};
+
+static const u16 default_partition_cdf[13][16] = {
+ {
+ AOM_CDF4(19132, 25510, 30392), AOM_CDF4(13928, 19855, 28540),
+ AOM_CDF4(12522, 23679, 28629), AOM_CDF4(9896, 18783, 25853),
+ AOM_CDF2(11570), AOM_CDF2(16855), AOM_CDF3(9413, 22581)
+ },
+ {
+ AOM_CDF10(15597, 20929, 24571, 26706, 27664, 28821, 29601, 30571, 31902)
+ },
+ {
+ AOM_CDF10(7925, 11043, 16785, 22470, 23971, 25043, 26651, 28701, 29834)
+ },
+ {
+ AOM_CDF10(5414, 13269, 15111, 20488, 22360, 24500, 25537, 26336, 32117)
+ },
+ {
+ AOM_CDF10(2662, 6362, 8614, 20860, 23053, 24778, 26436, 27829, 31171)
+ },
+ {
+ AOM_CDF10(18462, 20920, 23124, 27647, 28227, 29049, 29519, 30178, 31544)
+ },
+ {
+ AOM_CDF10(7689, 9060, 12056, 24992, 25660, 26182, 26951, 28041, 29052)
+ },
+ {
+ AOM_CDF10(6015, 9009, 10062, 24544, 25409, 26545, 27071, 27526, 32047)
+ },
+ {
+ AOM_CDF10(1394, 2208, 2796, 28614, 29061, 29466, 29840, 30185, 31899)
+ },
+ {
+ AOM_CDF10(20137, 21547, 23078, 29566, 29837, 30261, 30524, 30892, 31724),
+ AOM_CDF8(27899, 28219, 28529, 32484, 32539, 32619, 32639)
+ },
+ {
+ AOM_CDF10(6732, 7490, 9497, 27944, 28250, 28515, 28969, 29630, 30104),
+ AOM_CDF8(6607, 6990, 8268, 32060, 32219, 32338, 32371)
+ },
+ {
+ AOM_CDF10(5945, 7663, 8348, 28683, 29117, 29749, 30064, 30298, 32238),
+ AOM_CDF8(5429, 6676, 7122, 32027, 32227, 32531, 32582)
+ },
+ {
+ AOM_CDF10(870, 1212, 1487, 31198, 31394, 31574, 31743, 31881, 32332),
+ AOM_CDF8(711, 966, 1172, 32448, 32538, 32617, 32664)
+ },
+};
+
+static const u16 default_intra_ext_tx0_cdf[EXTTX_SIZES][AV1_INTRA_MODES][8] = {
+ {
+ { AOM_CDF7(1535, 8035, 9461, 12751, 23467, 27825)},
+ { AOM_CDF7(564, 3335, 9709, 10870, 18143, 28094)},
+ { AOM_CDF7(672, 3247, 3676, 11982, 19415, 23127)},
+ { AOM_CDF7(5279, 13885, 15487, 18044, 23527, 30252)},
+ { AOM_CDF7(4423, 6074, 7985, 10416, 25693, 29298)},
+ { AOM_CDF7(1486, 4241, 9460, 10662, 16456, 27694)},
+ { AOM_CDF7(439, 2838, 3522, 6737, 18058, 23754)},
+ { AOM_CDF7(1190, 4233, 4855, 11670, 20281, 24377)},
+ { AOM_CDF7(1045, 4312, 8647, 10159, 18644, 29335)},
+ { AOM_CDF7(202, 3734, 4747, 7298, 17127, 24016)},
+ { AOM_CDF7(447, 4312, 6819, 8884, 16010, 23858)},
+ { AOM_CDF7(277, 4369, 5255, 8905, 16465, 22271)},
+ { AOM_CDF7(3409, 5436, 10599, 15599, 19687, 24040)},
+ },
+ {
+ { AOM_CDF7(1870, 13742, 14530, 16498, 23770, 27698)},
+ { AOM_CDF7(326, 8796, 14632, 15079, 19272, 27486)},
+ { AOM_CDF7(484, 7576, 7712, 14443, 19159, 22591)},
+ { AOM_CDF7(1126, 15340, 15895, 17023, 20896, 30279)},
+ { AOM_CDF7(655, 4854, 5249, 5913, 22099, 27138)},
+ { AOM_CDF7(1299, 6458, 8885, 9290, 14851, 25497)},
+ { AOM_CDF7(311, 5295, 5552, 6885, 16107, 22672)},
+ { AOM_CDF7(883, 8059, 8270, 11258, 17289, 21549)},
+ { AOM_CDF7(741, 7580, 9318, 10345, 16688, 29046)},
+ { AOM_CDF7(110, 7406, 7915, 9195, 16041, 23329)},
+ { AOM_CDF7(363, 7974, 9357, 10673, 15629, 24474)},
+ { AOM_CDF7(153, 7647, 8112, 9936, 15307, 19996)},
+ { AOM_CDF7(3511, 6332, 11165, 15335, 19323, 23594)},
+ },
+ {
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ },
+ {
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)},
+ },
+};
+
+static const u16 default_intra_ext_tx1_cdf[EXTTX_SIZES][AV1_INTRA_MODES][4] = {
+ {
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ },
+ {
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ },
+ {
+ { AOM_CDF5(1127, 12814, 22772, 27483)},
+ { AOM_CDF5(145, 6761, 11980, 26667)},
+ { AOM_CDF5(362, 5887, 11678, 16725)},
+ { AOM_CDF5(385, 15213, 18587, 30693)},
+ { AOM_CDF5(25, 2914, 23134, 27903)},
+ { AOM_CDF5(60, 4470, 11749, 23991)},
+ { AOM_CDF5(37, 3332, 14511, 21448)},
+ { AOM_CDF5(157, 6320, 13036, 17439)},
+ { AOM_CDF5(119, 6719, 12906, 29396)},
+ { AOM_CDF5(47, 5537, 12576, 21499)},
+ { AOM_CDF5(269, 6076, 11258, 23115)},
+ { AOM_CDF5(83, 5615, 12001, 17228)},
+ { AOM_CDF5(1968, 5556, 12023, 18547)},
+ },
+ {
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ { AOM_CDF5(6554, 13107, 19661, 26214)},
+ },
+};
+
+static const u16 default_inter_ext_tx_cdf[2][EXTTX_SIZES][EXT_TX_TYPES] = {
+ {
+ {
+ AOM_CDF16(4458, 5560, 7695, 9709, 13330, 14789, 17537, 20266,
+ 21504, 22848, 23934, 25474, 27727, 28915, 30631)
+ },
+ {
+ AOM_CDF16(1645, 2573, 4778, 5711, 7807, 8622, 10522, 15357, 17674,
+ 20408, 22517, 25010, 27116, 28856, 30749)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
+ 18432, 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
+ 18432, 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ },
+ {
+ {
+ AOM_CDF12(2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845,
+ 24576, 27307, 30037),
+ AOM_CDF2(16384)
+ },
+ {
+ AOM_CDF12(2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845,
+ 24576, 27307, 30037),
+ AOM_CDF2(4167)
+ },
+ {
+ AOM_CDF12(770, 2421, 5225, 12907, 15819, 18927, 21561, 24089,
+ 26595, 28526, 30529),
+ AOM_CDF2(1998)
+ },
+ {
+ AOM_CDF12(2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845,
+ 24576, 27307, 30037),
+ AOM_CDF2(748)
+ },
+ }
+};
+
+static const u16 default_cfl_sign_cdf[CDF_SIZE(CFL_JOINT_SIGNS)] = {
+ AOM_CDF8(1418, 2123, 13340, 18405, 26972, 28343, 32294)
+};
+
+static const u16 default_cfl_alpha_cdf[CFL_ALPHA_CONTEXTS][CDF_SIZE(CFL_ALPHABET_SIZE)] = {
+ {
+ AOM_CDF16(7637, 20719, 31401, 32481, 32657, 32688, 32692, 32696, 32700,
+ 32704, 32708, 32712, 32716, 32720, 32724)
+ },
+ {
+ AOM_CDF16(14365, 23603, 28135, 31168, 32167, 32395, 32487, 32573,
+ 32620, 32647, 32668, 32672, 32676, 32680, 32684)
+ },
+ {
+ AOM_CDF16(11532, 22380, 28445, 31360, 32349, 32523, 32584, 32649,
+ 32673, 32677, 32681, 32685, 32689, 32693, 32697)
+ },
+ {
+ AOM_CDF16(26990, 31402, 32282, 32571, 32692, 32696, 32700, 32704,
+ 32708, 32712, 32716, 32720, 32724, 32728, 32732)
+ },
+ {
+ AOM_CDF16(17248, 26058, 28904, 30608, 31305, 31877, 32126, 32321,
+ 32394, 32464, 32516, 32560, 32576, 32593, 32622)
+ },
+ {
+ AOM_CDF16(14738, 21678, 25779, 27901, 29024, 30302, 30980, 31843,
+ 32144, 32413, 32520, 32594, 32622, 32656, 32660)
+ }
+};
+
+static const u16 default_switchable_interp_cdf[SWITCHABLE_FILTER_CONTEXTS]
+ [CDF_SIZE(AV1_SWITCHABLE_FILTERS)] = {
+ { AOM_CDF3(31935, 32720) }, { AOM_CDF3(5568, 32719) },
+ { AOM_CDF3(422, 2938) }, { AOM_CDF3(28244, 32608) },
+ { AOM_CDF3(31206, 31953) }, { AOM_CDF3(4862, 32121) },
+ { AOM_CDF3(770, 1152) }, { AOM_CDF3(20889, 25637) },
+ { AOM_CDF3(31910, 32724) }, { AOM_CDF3(4120, 32712) },
+ { AOM_CDF3(305, 2247) }, { AOM_CDF3(27403, 32636) },
+ { AOM_CDF3(31022, 32009) }, { AOM_CDF3(2963, 32093) },
+ { AOM_CDF3(601, 943) }, { AOM_CDF3(14969, 21398) }
+};
+
+static const u16 default_newmv_cdf[NEWMV_MODE_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(24035) }, { AOM_CDF2(16630) }, { AOM_CDF2(15339) },
+ { AOM_CDF2(8386) }, { AOM_CDF2(12222) }, { AOM_CDF2(4676) }
+};
+
+static const u16 default_zeromv_cdf[GLOBALMV_MODE_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(2175) }, { AOM_CDF2(1054) }
+};
+
+static const u16 default_refmv_cdf[REFMV_MODE_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(23974) }, { AOM_CDF2(24188) }, { AOM_CDF2(17848) },
+ { AOM_CDF2(28622) }, { AOM_CDF2(24312) }, { AOM_CDF2(19923) }
+};
+
+static const u16 default_drl_cdf[DRL_MODE_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(13104) }, { AOM_CDF2(24560) }, { AOM_CDF2(18945) }
+};
+
+static const u16 default_inter_compound_mode_cdf[AV1_INTER_MODE_CONTEXTS]
+ [CDF_SIZE(INTER_COMPOUND_MODES)] = {
+ { AOM_CDF8(7760, 13823, 15808, 17641, 19156, 20666, 26891) },
+ { AOM_CDF8(10730, 19452, 21145, 22749, 24039, 25131, 28724) },
+ { AOM_CDF8(10664, 20221, 21588, 22906, 24295, 25387, 28436) },
+ { AOM_CDF8(13298, 16984, 20471, 24182, 25067, 25736, 26422) },
+ { AOM_CDF8(18904, 23325, 25242, 27432, 27898, 28258, 30758) },
+ { AOM_CDF8(10725, 17454, 20124, 22820, 24195, 25168, 26046) },
+ { AOM_CDF8(17125, 24273, 25814, 27492, 28214, 28704, 30592) },
+ { AOM_CDF8(13046, 23214, 24505, 25942, 27435, 28442, 29330) }
+};
+
+static const u16 default_interintra_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(2)] = {
+ { AOM_CDF2(16384) }, { AOM_CDF2(26887) }, { AOM_CDF2(27597) },
+ { AOM_CDF2(30237) }
+};
+
+static const u16 default_interintra_mode_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(INTERINTRA_MODES)] = {
+ { AOM_CDF4(8192, 16384, 24576) },
+ { AOM_CDF4(1875, 11082, 27332) },
+ { AOM_CDF4(2473, 9996, 26388) },
+ { AOM_CDF4(4238, 11537, 25926) }
+};
+
+static const u16 default_wedge_interintra_cdf[BLOCK_SIZES_ALL][CDF_SIZE(2)] = {
+ { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) },
+ { AOM_CDF2(20036) }, { AOM_CDF2(24957) }, { AOM_CDF2(26704) },
+ { AOM_CDF2(27530) }, { AOM_CDF2(29564) }, { AOM_CDF2(29444) },
+ { AOM_CDF2(26872) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) },
+ { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) },
+ { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) },
+ { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) },
+ { AOM_CDF2(16384) }
+};
+
+static const u16 default_compound_type_cdf[BLOCK_SIZES_ALL][CDF_SIZE(COMPOUND_TYPES - 1)] = {
+ { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) },
+ { AOM_CDF2(23431) },
+ { AOM_CDF2(13171) }, { AOM_CDF2(11470) }, { AOM_CDF2(9770) },
+ { AOM_CDF2(9100) },
+ { AOM_CDF2(8233) }, { AOM_CDF2(6172) }, { AOM_CDF2(16384) },
+ { AOM_CDF2(16384) },
+ { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) },
+ { AOM_CDF2(16384) },
+ { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(11820) },
+ { AOM_CDF2(7701) },
+ { AOM_CDF2(16384) }, { AOM_CDF2(16384) }
+};
+
+static const u16 default_wedge_idx_cdf[BLOCK_SIZES_ALL][CDF_SIZE(16)] = {
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
+ 18432, 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
+ 18432, 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384,
+ 18432, 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(2438, 4440, 6599, 8663, 11005, 12874, 15751, 18094,
+ 20359, 22362, 24127, 25702, 27752, 29450, 31171)
+ },
+ {
+ AOM_CDF16(806, 3266, 6005, 6738, 7218, 7367, 7771, 14588, 16323,
+ 17367, 18452, 19422, 22839, 26127, 29629)
+ },
+ {
+ AOM_CDF16(2779, 3738, 4683, 7213, 7775, 8017, 8655, 14357, 17939,
+ 21332, 24520, 27470, 29456, 30529, 31656)
+ },
+ {
+ AOM_CDF16(1684, 3625, 5675, 7108, 9302, 11274, 14429, 17144, 19163,
+ 20961, 22884, 24471, 26719, 28714, 30877)
+ },
+ {
+ AOM_CDF16(1142, 3491, 6277, 7314, 8089, 8355, 9023, 13624, 15369,
+ 16730, 18114, 19313, 22521, 26012, 29550)
+ },
+ {
+ AOM_CDF16(2742, 4195, 5727, 8035, 8980, 9336, 10146, 14124, 17270,
+ 20533, 23434, 25972, 27944, 29570, 31416)
+ },
+ {
+ AOM_CDF16(1727, 3948, 6101, 7796, 9841, 12344, 15766, 18944, 20638,
+ 22038, 23963, 25311, 26988, 28766, 31012)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
+ 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
+ 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
+ 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
+ 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
+ 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
+ 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
+ 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
+ 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(154, 987, 1925, 2051, 2088, 2111, 2151, 23033, 23703, 24284,
+ 24985, 25684, 27259, 28883, 30911)
+ },
+ {
+ AOM_CDF16(1135, 1322, 1493, 2635, 2696, 2737, 2770, 21016, 22935,
+ 25057, 27251, 29173, 30089, 30960, 31933)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
+ 20480, 22528, 24576, 26624, 28672, 30720)
+ },
+ {
+ AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432,
+ 20480, 22528, 24576, 26624, 28672, 30720)
+ }
+};
+
+static const u16 default_motion_mode_cdf[BLOCK_SIZES_ALL][CDF_SIZE(MOTION_MODES)] = {
+ { AOM_CDF3(10923, 21845) }, { AOM_CDF3(10923, 21845) },
+ { AOM_CDF3(10923, 21845) }, { AOM_CDF3(7651, 24760) },
+ { AOM_CDF3(4738, 24765) }, { AOM_CDF3(5391, 25528) },
+ { AOM_CDF3(19419, 26810) }, { AOM_CDF3(5123, 23606) },
+ { AOM_CDF3(11606, 24308) }, { AOM_CDF3(26260, 29116) },
+ { AOM_CDF3(20360, 28062) }, { AOM_CDF3(21679, 26830) },
+ { AOM_CDF3(29516, 30701) }, { AOM_CDF3(28898, 30397) },
+ { AOM_CDF3(30878, 31335) }, { AOM_CDF3(32507, 32558) },
+ { AOM_CDF3(10923, 21845) }, { AOM_CDF3(10923, 21845) },
+ { AOM_CDF3(28799, 31390) }, { AOM_CDF3(26431, 30774) },
+ { AOM_CDF3(28973, 31594) }, { AOM_CDF3(29742, 31203) }
+};
+
+static const u16 default_obmc_cdf[BLOCK_SIZES_ALL][CDF_SIZE(2)] = {
+ { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) },
+ { AOM_CDF2(10437) },
+ { AOM_CDF2(9371) }, { AOM_CDF2(9301) }, { AOM_CDF2(17432) },
+ { AOM_CDF2(14423) },
+ { AOM_CDF2(15142) }, { AOM_CDF2(25817) }, { AOM_CDF2(22823) },
+ { AOM_CDF2(22083) },
+ { AOM_CDF2(30128) }, { AOM_CDF2(31014) }, { AOM_CDF2(31560) },
+ { AOM_CDF2(32638) },
+ { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(23664) },
+ { AOM_CDF2(20901) },
+ { AOM_CDF2(24008) }, { AOM_CDF2(26879) }
+};
+
+static const u16 default_intra_inter_cdf[INTRA_INTER_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(806) },
+ { AOM_CDF2(16662) },
+ { AOM_CDF2(20186) },
+ { AOM_CDF2(26538) }
+};
+
+static const u16 default_comp_inter_cdf[COMP_INTER_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(26828) },
+ { AOM_CDF2(24035) },
+ { AOM_CDF2(12031) },
+ { AOM_CDF2(10640) },
+ { AOM_CDF2(2901) }
+};
+
+static const u16 default_comp_ref_type_cdf[COMP_REF_TYPE_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(1198) },
+ { AOM_CDF2(2070) },
+ { AOM_CDF2(9166) },
+ { AOM_CDF2(7499) },
+ { AOM_CDF2(22475) }
+};
+
+static const u16 default_uni_comp_ref_cdf[UNI_COMP_REF_CONTEXTS]
+ [UNIDIR_COMP_REFS - 1][CDF_SIZE(2)] = {
+ { { AOM_CDF2(5284)}, { AOM_CDF2(3865)}, { AOM_CDF2(3128)} },
+ { { AOM_CDF2(23152)}, { AOM_CDF2(14173)}, { AOM_CDF2(15270)} },
+ { { AOM_CDF2(31774)}, { AOM_CDF2(25120)}, { AOM_CDF2(26710)} }
+};
+
+static const u16 default_single_ref_cdf[REF_CONTEXTS][SINGLE_REFS - 1][CDF_SIZE(2)] = {
+ {
+ { AOM_CDF2(4897)},
+ { AOM_CDF2(1555)},
+ { AOM_CDF2(4236)},
+ { AOM_CDF2(8650)},
+ { AOM_CDF2(904)},
+ { AOM_CDF2(1444)}
+ },
+ {
+ { AOM_CDF2(16973)},
+ { AOM_CDF2(16751)},
+ { AOM_CDF2(19647)},
+ { AOM_CDF2(24773)},
+ { AOM_CDF2(11014)},
+ { AOM_CDF2(15087)}
+ },
+ {
+ { AOM_CDF2(29744)},
+ { AOM_CDF2(30279)},
+ { AOM_CDF2(31194)},
+ { AOM_CDF2(31895)},
+ { AOM_CDF2(26875)},
+ { AOM_CDF2(30304)}
+ }
+};
+
+static const u16 default_comp_ref_cdf[REF_CONTEXTS][FWD_REFS - 1][CDF_SIZE(2)] = {
+ { { AOM_CDF2(4946)}, { AOM_CDF2(9468)}, { AOM_CDF2(1503)} },
+ { { AOM_CDF2(19891)}, { AOM_CDF2(22441)}, { AOM_CDF2(15160)} },
+ { { AOM_CDF2(30731)}, { AOM_CDF2(31059)}, { AOM_CDF2(27544)} }
+};
+
+static const u16 default_comp_bwdref_cdf[REF_CONTEXTS][BWD_REFS - 1][CDF_SIZE(2)] = {
+ { { AOM_CDF2(2235)}, { AOM_CDF2(1423)} },
+ { { AOM_CDF2(17182)}, { AOM_CDF2(15175)} },
+ { { AOM_CDF2(30606)}, { AOM_CDF2(30489)} }
+};
+
+static const u16 default_palette_y_size_cdf[PALETTE_BLOCK_SIZES][CDF_SIZE(PALETTE_SIZES)] = {
+ { AOM_CDF7(7952, 13000, 18149, 21478, 25527, 29241) },
+ { AOM_CDF7(7139, 11421, 16195, 19544, 23666, 28073) },
+ { AOM_CDF7(7788, 12741, 17325, 20500, 24315, 28530) },
+ { AOM_CDF7(8271, 14064, 18246, 21564, 25071, 28533) },
+ { AOM_CDF7(12725, 19180, 21863, 24839, 27535, 30120) },
+ { AOM_CDF7(9711, 14888, 16923, 21052, 25661, 27875) },
+ { AOM_CDF7(14940, 20797, 21678, 24186, 27033, 28999) }
+};
+
+static const u16 default_palette_uv_size_cdf[PALETTE_BLOCK_SIZES][CDF_SIZE(PALETTE_SIZES)] = {
+ { AOM_CDF7(8713, 19979, 27128, 29609, 31331, 32272) },
+ { AOM_CDF7(5839, 15573, 23581, 26947, 29848, 31700) },
+ { AOM_CDF7(4426, 11260, 17999, 21483, 25863, 29430) },
+ { AOM_CDF7(3228, 9464, 14993, 18089, 22523, 27420) },
+ { AOM_CDF7(3768, 8886, 13091, 17852, 22495, 27207) },
+ { AOM_CDF7(2464, 8451, 12861, 21632, 25525, 28555) },
+ { AOM_CDF7(1269, 5435, 10433, 18963, 21700, 25865) }
+};
+
+static const u16 default_palette_y_mode_cdf[PALETTE_BLOCK_SIZES]
+ [PALETTE_Y_MODE_CONTEXTS][CDF_SIZE(2)] = {
+ { { AOM_CDF2(31676)}, { AOM_CDF2(3419)}, { AOM_CDF2(1261)} },
+ { { AOM_CDF2(31912)}, { AOM_CDF2(2859)}, { AOM_CDF2(980)} },
+ { { AOM_CDF2(31823)}, { AOM_CDF2(3400)}, { AOM_CDF2(781)} },
+ { { AOM_CDF2(32030)}, { AOM_CDF2(3561)}, { AOM_CDF2(904)} },
+ { { AOM_CDF2(32309)}, { AOM_CDF2(7337)}, { AOM_CDF2(1462)} },
+ { { AOM_CDF2(32265)}, { AOM_CDF2(4015)}, { AOM_CDF2(1521)} },
+ { { AOM_CDF2(32450)}, { AOM_CDF2(7946)}, { AOM_CDF2(129)} }
+};
+
+static const u16 default_palette_uv_mode_cdf[PALETTE_UV_MODE_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(32461) }, { AOM_CDF2(21488) }
+};
+
+static const u16 default_palette_y_color_index_cdf[PALETTE_IDX_CONTEXTS][8] = {
+ // Palette sizes 2 & 8
+ {
+ AOM_CDF2(28710),
+ AOM_CDF8(21689, 23883, 25163, 26352, 27506, 28827, 30195)
+ },
+ {
+ AOM_CDF2(16384),
+ AOM_CDF8(6892, 15385, 17840, 21606, 24287, 26753, 29204)
+ },
+ {
+ AOM_CDF2(10553),
+ AOM_CDF8(5651, 23182, 25042, 26518, 27982, 29392, 30900)
+ },
+ {
+ AOM_CDF2(27036),
+ AOM_CDF8(19349, 22578, 24418, 25994, 27524, 29031, 30448)
+ },
+ {
+ AOM_CDF2(31603),
+ AOM_CDF8(31028, 31270, 31504, 31705, 31927, 32153, 32392)
+ },
+ // Palette sizes 3 & 7
+ {
+ AOM_CDF3(27877, 30490),
+ AOM_CDF7(23105, 25199, 26464, 27684, 28931, 30318)
+ },
+ {
+ AOM_CDF3(11532, 25697),
+ AOM_CDF7(6950, 15447, 18952, 22681, 25567, 28563)
+ },
+ {
+ AOM_CDF3(6544, 30234),
+ AOM_CDF7(7560, 23474, 25490, 27203, 28921, 30708)
+ },
+ {
+ AOM_CDF3(23018, 28072),
+ AOM_CDF7(18544, 22373, 24457, 26195, 28119, 30045)
+ },
+ {
+ AOM_CDF3(31915, 32385),
+ AOM_CDF7(31198, 31451, 31670, 31882, 32123, 32391)
+ },
+ // Palette sizes 4 & 6
+ {
+ AOM_CDF4(25572, 28046, 30045),
+ AOM_CDF6(23132, 25407, 26970, 28435, 30073)
+ },
+ {
+ AOM_CDF4(9478, 21590, 27256),
+ AOM_CDF6(7443, 17242, 20717, 24762, 27982)
+ },
+ {
+ AOM_CDF4(7248, 26837, 29824),
+ AOM_CDF6(6300, 24862, 26944, 28784, 30671)
+ },
+ {
+ AOM_CDF4(19167, 24486, 28349),
+ AOM_CDF6(18916, 22895, 25267, 27435, 29652)
+ },
+ {
+ AOM_CDF4(31400, 31825, 32250),
+ AOM_CDF6(31270, 31550, 31808, 32059, 32353)
+ },
+ // Palette size 5
+ {
+ AOM_CDF5(24779, 26955, 28576, 30282),
+ AOM_CDF5(8669, 20364, 24073, 28093)
+ },
+ {
+ AOM_CDF5(4255, 27565, 29377, 31067),
+ AOM_CDF5(19864, 23674, 26716, 29530)
+ },
+ {
+ AOM_CDF5(31646, 31893, 32147, 32426),
+ 0, 0, 0, 0
+ }
+};
+
+static const u16 default_palette_uv_color_index_cdf[PALETTE_IDX_CONTEXTS][8] = {
+ // Palette sizes 2 & 8
+ {
+ AOM_CDF2(29089),
+ AOM_CDF8(21442, 23288, 24758, 26246, 27649, 28980, 30563)
+ },
+ {
+ AOM_CDF2(16384),
+ AOM_CDF8(5863, 14933, 17552, 20668, 23683, 26411, 29273)
+ },
+ {
+ AOM_CDF2(8713),
+ AOM_CDF8(3415, 25810, 26877, 27990, 29223, 30394, 31618)
+ },
+ {
+ AOM_CDF2(29257),
+ AOM_CDF8(17965, 20084, 22232, 23974, 26274, 28402, 30390)
+ },
+ {
+ AOM_CDF2(31610),
+ AOM_CDF8(31190, 31329, 31516, 31679, 31825, 32026, 32322)
+ },
+ // Palette sizes 3 & 7
+ {
+ AOM_CDF3(25257, 29145),
+ AOM_CDF7(21239, 23168, 25044, 26962, 28705, 30506)
+ },
+ {
+ AOM_CDF3(12287, 27293),
+ AOM_CDF7(6545, 15012, 18004, 21817, 25503, 28701)
+ },
+ {
+ AOM_CDF3(7033, 27960),
+ AOM_CDF7(3448, 26295, 27437, 28704, 30126, 31442)
+ },
+ {
+ AOM_CDF3(20145, 25405),
+ AOM_CDF7(15889, 18323, 21704, 24698, 26976, 29690)
+ },
+ {
+ AOM_CDF3(30608, 31639),
+ AOM_CDF7(30988, 31204, 31479, 31734, 31983, 32325)
+ },
+ // Palette sizes 4 & 6
+ {
+ AOM_CDF4(24210, 27175, 29903),
+ AOM_CDF6(22217, 24567, 26637, 28683, 30548)
+ },
+ {
+ AOM_CDF4(9888, 22386, 27214),
+ AOM_CDF6(7307, 16406, 19636, 24632, 28424)
+ },
+ {
+ AOM_CDF4(5901, 26053, 29293),
+ AOM_CDF6(4441, 25064, 26879, 28942, 30919)
+ },
+ {
+ AOM_CDF4(18318, 22152, 28333),
+ AOM_CDF6(17210, 20528, 23319, 26750, 29582)
+ },
+ {
+ AOM_CDF4(30459, 31136, 31926),
+ AOM_CDF6(30674, 30953, 31396, 31735, 32207)
+ },
+ // Palette size 5
+ {
+ AOM_CDF5(22980, 25479, 27781, 29986),
+ AOM_CDF5(8413, 21408, 24859, 28874)
+ },
+ {
+ AOM_CDF5(2257, 29449, 30594, 31598),
+ AOM_CDF5(19189, 21202, 25915, 28620)
+ },
+ {
+ AOM_CDF5(31844, 32044, 32281, 32518),
+ 0, 0, 0, 0
+ }
+};
+
+static const u16 default_txfm_partition_cdf[TXFM_PARTITION_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(28581) }, { AOM_CDF2(23846) }, { AOM_CDF2(20847) },
+ { AOM_CDF2(24315) }, { AOM_CDF2(18196) }, { AOM_CDF2(12133) },
+ { AOM_CDF2(18791) }, { AOM_CDF2(10887) }, { AOM_CDF2(11005) },
+ { AOM_CDF2(27179) }, { AOM_CDF2(20004) }, { AOM_CDF2(11281) },
+ { AOM_CDF2(26549) }, { AOM_CDF2(19308) }, { AOM_CDF2(14224) },
+ { AOM_CDF2(28015) }, { AOM_CDF2(21546) }, { AOM_CDF2(14400) },
+ { AOM_CDF2(28165) }, { AOM_CDF2(22401) }, { AOM_CDF2(16088) }
+};
+
+static const u16 default_skip_cdfs[SKIP_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(31671) }, { AOM_CDF2(16515) }, { AOM_CDF2(4576) }
+};
+
+static const u16 default_skip_mode_cdfs[SKIP_MODE_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(32621) }, { AOM_CDF2(20708) }, { AOM_CDF2(8127) }
+};
+
+static const u16 default_compound_idx_cdfs[COMP_INDEX_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(18244) }, { AOM_CDF2(12865) }, { AOM_CDF2(7053) },
+ { AOM_CDF2(13259) }, { AOM_CDF2(9334) }, { AOM_CDF2(4644) }
+};
+
+static const u16 default_comp_group_idx_cdfs[COMP_GROUP_IDX_CONTEXTS][CDF_SIZE(2)] = {
+ { AOM_CDF2(26607) }, { AOM_CDF2(22891) }, { AOM_CDF2(18840) },
+ { AOM_CDF2(24594) }, { AOM_CDF2(19934) }, { AOM_CDF2(22674) }
+};
+
+static const u16 default_intrabc_cdf[CDF_SIZE(2)] = { AOM_CDF2(30531) };
+
+static const u16 default_filter_intra_mode_cdf[CDF_SIZE(FILTER_INTRA_MODES)] = {
+ AOM_CDF5(8949, 12776, 17211, 29558)
+};
+
+static const u16 default_filter_intra_cdfs[BLOCK_SIZES_ALL][CDF_SIZE(2)] = {
+ { AOM_CDF2(4621) }, { AOM_CDF2(6743) }, { AOM_CDF2(5893) }, { AOM_CDF2(7866) },
+ { AOM_CDF2(12551) }, { AOM_CDF2(9394) }, { AOM_CDF2(12408) }, { AOM_CDF2(14301) },
+ { AOM_CDF2(12756) }, { AOM_CDF2(22343) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) },
+ { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) },
+ { AOM_CDF2(12770) }, { AOM_CDF2(10368) }, { AOM_CDF2(20229) }, { AOM_CDF2(18101) },
+ { AOM_CDF2(16384) }, { AOM_CDF2(16384) }
+};
+
+static const u16 default_delta_q_cdf[CDF_SIZE(DELTA_Q_PROBS + 1)] = {
+ AOM_CDF4(28160, 32120, 32677)
+};
+
+static const u16 default_delta_lf_multi_cdf[FRAME_LF_COUNT][CDF_SIZE(DELTA_LF_PROBS + 1)] = {
+ { AOM_CDF4(28160, 32120, 32677) },
+ { AOM_CDF4(28160, 32120, 32677) },
+ { AOM_CDF4(28160, 32120, 32677) },
+ { AOM_CDF4(28160, 32120, 32677) }
+};
+
+static const u16 default_delta_lf_cdf[CDF_SIZE(DELTA_LF_PROBS + 1)] = {
+ AOM_CDF4(28160, 32120, 32677)
+};
+
+static const u16 default_segment_pred_cdf[SEG_TEMPORAL_PRED_CTXS][CDF_SIZE(2)] = {
+ { AOM_CDF2(128 * 128) },
+ { AOM_CDF2(128 * 128) },
+ { AOM_CDF2(128 * 128) }
+};
+
+static const u16 default_spatial_pred_seg_tree_cdf[SPATIAL_PREDICTION_PROBS]
+ [CDF_SIZE(MAX_SEGMENTS)] = {
+ {
+ AOM_CDF8(5622, 7893, 16093, 18233, 27809, 28373, 32533),
+ },
+ {
+ AOM_CDF8(14274, 18230, 22557, 24935, 29980, 30851, 32344),
+ },
+ {
+ AOM_CDF8(27527, 28487, 28723, 28890, 32397, 32647, 32679),
+ },
+};
+
+static const u16 default_tx_size_cdf[MAX_TX_CATS]
+ [AV1_TX_SIZE_CONTEXTS][CDF_SIZE(MAX_TX_DEPTH + 1)] = {
+ {
+ { AOM_CDF2(19968)},
+ { AOM_CDF2(19968)},
+ { AOM_CDF2(24320)}
+ },
+ {
+ { AOM_CDF3(12272, 30172)},
+ { AOM_CDF3(12272, 30172)},
+ { AOM_CDF3(18677, 30848)}
+ },
+ {
+ { AOM_CDF3(12986, 15180)},
+ { AOM_CDF3(12986, 15180)},
+ { AOM_CDF3(24302, 25602)}
+ },
+ {
+ { AOM_CDF3(5782, 11475)},
+ { AOM_CDF3(5782, 11475)},
+ { AOM_CDF3(16803, 22759)}
+ },
+};
+
+static const u16 av1_default_dc_sign_cdfs[TOKEN_CDF_Q_CTXS]
+ [PLANE_TYPES][DC_SIGN_CONTEXTS][CDF_SIZE(2)] = {
+ {
+ {
+ { AOM_CDF2(128 * 125)},
+ { AOM_CDF2(128 * 102)},
+ { AOM_CDF2(128 * 147)},
+ },
+ {
+ { AOM_CDF2(128 * 119)},
+ { AOM_CDF2(128 * 101)},
+ { AOM_CDF2(128 * 135)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(128 * 125)},
+ { AOM_CDF2(128 * 102)},
+ { AOM_CDF2(128 * 147)},
+ },
+ {
+ { AOM_CDF2(128 * 119)},
+ { AOM_CDF2(128 * 101)},
+ { AOM_CDF2(128 * 135)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(128 * 125)},
+ { AOM_CDF2(128 * 102)},
+ { AOM_CDF2(128 * 147)},
+ },
+ {
+ { AOM_CDF2(128 * 119)},
+ { AOM_CDF2(128 * 101)},
+ { AOM_CDF2(128 * 135)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(128 * 125)},
+ { AOM_CDF2(128 * 102)},
+ { AOM_CDF2(128 * 147)},
+ },
+ {
+ { AOM_CDF2(128 * 119)},
+ { AOM_CDF2(128 * 101)},
+ { AOM_CDF2(128 * 135)},
+ }
+ },
+};
+
+static const u16 av1_default_txb_skip_cdfs[TOKEN_CDF_Q_CTXS]
+ [TX_SIZES][TXB_SKIP_CONTEXTS][CDF_SIZE(2)] = {
+ {
+ {
+ { AOM_CDF2(31849)},
+ { AOM_CDF2(5892)},
+ { AOM_CDF2(12112)},
+ { AOM_CDF2(21935)},
+ { AOM_CDF2(20289)},
+ { AOM_CDF2(27473)},
+ { AOM_CDF2(32487)},
+ { AOM_CDF2(7654)},
+ { AOM_CDF2(19473)},
+ { AOM_CDF2(29984)},
+ { AOM_CDF2(9961)},
+ { AOM_CDF2(30242)},
+ { AOM_CDF2(32117)}
+ },
+ {
+ { AOM_CDF2(31548)},
+ { AOM_CDF2(1549)},
+ { AOM_CDF2(10130)},
+ { AOM_CDF2(16656)},
+ { AOM_CDF2(18591)},
+ { AOM_CDF2(26308)},
+ { AOM_CDF2(32537)},
+ { AOM_CDF2(5403)},
+ { AOM_CDF2(18096)},
+ { AOM_CDF2(30003)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ },
+ {
+ { AOM_CDF2(29957)},
+ { AOM_CDF2(5391)},
+ { AOM_CDF2(18039)},
+ { AOM_CDF2(23566)},
+ { AOM_CDF2(22431)},
+ { AOM_CDF2(25822)},
+ { AOM_CDF2(32197)},
+ { AOM_CDF2(3778)},
+ { AOM_CDF2(15336)},
+ { AOM_CDF2(28981)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ },
+ {
+ { AOM_CDF2(17920)},
+ { AOM_CDF2(1818)},
+ { AOM_CDF2(7282)},
+ { AOM_CDF2(25273)},
+ { AOM_CDF2(10923)},
+ { AOM_CDF2(31554)},
+ { AOM_CDF2(32624)},
+ { AOM_CDF2(1366)},
+ { AOM_CDF2(15628)},
+ { AOM_CDF2(30462)},
+ { AOM_CDF2(146)},
+ { AOM_CDF2(5132)},
+ { AOM_CDF2(31657)}
+ },
+ {
+ { AOM_CDF2(6308)},
+ { AOM_CDF2(117)},
+ { AOM_CDF2(1638)},
+ { AOM_CDF2(2161)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(10923)},
+ { AOM_CDF2(30247)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ }
+ },
+ {
+ {
+ { AOM_CDF2(30371)},
+ { AOM_CDF2(7570)},
+ { AOM_CDF2(13155)},
+ { AOM_CDF2(20751)},
+ { AOM_CDF2(20969)},
+ { AOM_CDF2(27067)},
+ { AOM_CDF2(32013)},
+ { AOM_CDF2(5495)},
+ { AOM_CDF2(17942)},
+ { AOM_CDF2(28280)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ },
+ {
+ { AOM_CDF2(31782)},
+ { AOM_CDF2(1836)},
+ { AOM_CDF2(10689)},
+ { AOM_CDF2(17604)},
+ { AOM_CDF2(21622)},
+ { AOM_CDF2(27518)},
+ { AOM_CDF2(32399)},
+ { AOM_CDF2(4419)},
+ { AOM_CDF2(16294)},
+ { AOM_CDF2(28345)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ },
+ {
+ { AOM_CDF2(31901)},
+ { AOM_CDF2(10311)},
+ { AOM_CDF2(18047)},
+ { AOM_CDF2(24806)},
+ { AOM_CDF2(23288)},
+ { AOM_CDF2(27914)},
+ { AOM_CDF2(32296)},
+ { AOM_CDF2(4215)},
+ { AOM_CDF2(15756)},
+ { AOM_CDF2(28341)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ },
+ {
+ { AOM_CDF2(26726)},
+ { AOM_CDF2(1045)},
+ { AOM_CDF2(11703)},
+ { AOM_CDF2(20590)},
+ { AOM_CDF2(18554)},
+ { AOM_CDF2(25970)},
+ { AOM_CDF2(31938)},
+ { AOM_CDF2(5583)},
+ { AOM_CDF2(21313)},
+ { AOM_CDF2(29390)},
+ { AOM_CDF2(641)},
+ { AOM_CDF2(22265)},
+ { AOM_CDF2(31452)}
+ },
+ {
+ { AOM_CDF2(26584)},
+ { AOM_CDF2(188)},
+ { AOM_CDF2(8847)},
+ { AOM_CDF2(24519)},
+ { AOM_CDF2(22938)},
+ { AOM_CDF2(30583)},
+ { AOM_CDF2(32608)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ }
+ },
+ {
+ {
+ { AOM_CDF2(29614)},
+ { AOM_CDF2(9068)},
+ { AOM_CDF2(12924)},
+ { AOM_CDF2(19538)},
+ { AOM_CDF2(17737)},
+ { AOM_CDF2(24619)},
+ { AOM_CDF2(30642)},
+ { AOM_CDF2(4119)},
+ { AOM_CDF2(16026)},
+ { AOM_CDF2(25657)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ },
+ {
+ { AOM_CDF2(31957)},
+ { AOM_CDF2(3230)},
+ { AOM_CDF2(11153)},
+ { AOM_CDF2(18123)},
+ { AOM_CDF2(20143)},
+ { AOM_CDF2(26536)},
+ { AOM_CDF2(31986)},
+ { AOM_CDF2(3050)},
+ { AOM_CDF2(14603)},
+ { AOM_CDF2(25155)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ },
+ {
+ { AOM_CDF2(32363)},
+ { AOM_CDF2(10692)},
+ { AOM_CDF2(19090)},
+ { AOM_CDF2(24357)},
+ { AOM_CDF2(24442)},
+ { AOM_CDF2(28312)},
+ { AOM_CDF2(32169)},
+ { AOM_CDF2(3648)},
+ { AOM_CDF2(15690)},
+ { AOM_CDF2(26815)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ },
+ {
+ { AOM_CDF2(30669)},
+ { AOM_CDF2(3832)},
+ { AOM_CDF2(11663)},
+ { AOM_CDF2(18889)},
+ { AOM_CDF2(19782)},
+ { AOM_CDF2(23313)},
+ { AOM_CDF2(31330)},
+ { AOM_CDF2(5124)},
+ { AOM_CDF2(18719)},
+ { AOM_CDF2(28468)},
+ { AOM_CDF2(3082)},
+ { AOM_CDF2(20982)},
+ { AOM_CDF2(29443)}
+ },
+ {
+ { AOM_CDF2(28573)},
+ { AOM_CDF2(3183)},
+ { AOM_CDF2(17802)},
+ { AOM_CDF2(25977)},
+ { AOM_CDF2(26677)},
+ { AOM_CDF2(27832)},
+ { AOM_CDF2(32387)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ }
+ },
+ {
+ {
+ { AOM_CDF2(26887)},
+ { AOM_CDF2(6729)},
+ { AOM_CDF2(10361)},
+ { AOM_CDF2(17442)},
+ { AOM_CDF2(15045)},
+ { AOM_CDF2(22478)},
+ { AOM_CDF2(29072)},
+ { AOM_CDF2(2713)},
+ { AOM_CDF2(11861)},
+ { AOM_CDF2(20773)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ },
+ {
+ { AOM_CDF2(31903)},
+ { AOM_CDF2(2044)},
+ { AOM_CDF2(7528)},
+ { AOM_CDF2(14618)},
+ { AOM_CDF2(16182)},
+ { AOM_CDF2(24168)},
+ { AOM_CDF2(31037)},
+ { AOM_CDF2(2786)},
+ { AOM_CDF2(11194)},
+ { AOM_CDF2(20155)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ },
+ {
+ { AOM_CDF2(32510)},
+ { AOM_CDF2(8430)},
+ { AOM_CDF2(17318)},
+ { AOM_CDF2(24154)},
+ { AOM_CDF2(23674)},
+ { AOM_CDF2(28789)},
+ { AOM_CDF2(32139)},
+ { AOM_CDF2(3440)},
+ { AOM_CDF2(13117)},
+ { AOM_CDF2(22702)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ },
+ {
+ { AOM_CDF2(31671)},
+ { AOM_CDF2(2056)},
+ { AOM_CDF2(11746)},
+ { AOM_CDF2(16852)},
+ { AOM_CDF2(18635)},
+ { AOM_CDF2(24715)},
+ { AOM_CDF2(31484)},
+ { AOM_CDF2(4656)},
+ { AOM_CDF2(16074)},
+ { AOM_CDF2(24704)},
+ { AOM_CDF2(1806)},
+ { AOM_CDF2(14645)},
+ { AOM_CDF2(25336)}
+ },
+ {
+ { AOM_CDF2(31539)},
+ { AOM_CDF2(8433)},
+ { AOM_CDF2(20576)},
+ { AOM_CDF2(27904)},
+ { AOM_CDF2(27852)},
+ { AOM_CDF2(30026)},
+ { AOM_CDF2(32441)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)}
+ }
+ }
+};
+
+static const u16 av1_default_eob_extra_cdfs[TOKEN_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES]
+ [EOB_COEF_CONTEXTS][CDF_SIZE(2)] = {
+ {
+ {
+ {
+ { AOM_CDF2(16961)},
+ { AOM_CDF2(17223)},
+ { AOM_CDF2(7621)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ },
+ {
+ { AOM_CDF2(19069)},
+ { AOM_CDF2(22525)},
+ { AOM_CDF2(13377)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(20401)},
+ { AOM_CDF2(17025)},
+ { AOM_CDF2(12845)},
+ { AOM_CDF2(12873)},
+ { AOM_CDF2(14094)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ },
+ {
+ { AOM_CDF2(20681)},
+ { AOM_CDF2(20701)},
+ { AOM_CDF2(15250)},
+ { AOM_CDF2(15017)},
+ { AOM_CDF2(14928)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(23905)},
+ { AOM_CDF2(17194)},
+ { AOM_CDF2(16170)},
+ { AOM_CDF2(17695)},
+ { AOM_CDF2(13826)},
+ { AOM_CDF2(15810)},
+ { AOM_CDF2(12036)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ },
+ {
+ { AOM_CDF2(23959)},
+ { AOM_CDF2(20799)},
+ { AOM_CDF2(19021)},
+ { AOM_CDF2(16203)},
+ { AOM_CDF2(17886)},
+ { AOM_CDF2(14144)},
+ { AOM_CDF2(12010)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(27399)},
+ { AOM_CDF2(16327)},
+ { AOM_CDF2(18071)},
+ { AOM_CDF2(19584)},
+ { AOM_CDF2(20721)},
+ { AOM_CDF2(18432)},
+ { AOM_CDF2(19560)},
+ { AOM_CDF2(10150)},
+ { AOM_CDF2(8805)},
+ },
+ {
+ { AOM_CDF2(24932)},
+ { AOM_CDF2(20833)},
+ { AOM_CDF2(12027)},
+ { AOM_CDF2(16670)},
+ { AOM_CDF2(19914)},
+ { AOM_CDF2(15106)},
+ { AOM_CDF2(17662)},
+ { AOM_CDF2(13783)},
+ { AOM_CDF2(28756)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(23406)},
+ { AOM_CDF2(21845)},
+ { AOM_CDF2(18432)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(17096)},
+ { AOM_CDF2(12561)},
+ { AOM_CDF2(17320)},
+ { AOM_CDF2(22395)},
+ { AOM_CDF2(21370)},
+ },
+ {
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ }
+ },
+ {
+ {
+ {
+ { AOM_CDF2(17471)},
+ { AOM_CDF2(20223)},
+ { AOM_CDF2(11357)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ },
+ {
+ { AOM_CDF2(20335)},
+ { AOM_CDF2(21667)},
+ { AOM_CDF2(14818)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(20430)},
+ { AOM_CDF2(20662)},
+ { AOM_CDF2(15367)},
+ { AOM_CDF2(16970)},
+ { AOM_CDF2(14657)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ },
+ {
+ { AOM_CDF2(22117)},
+ { AOM_CDF2(22028)},
+ { AOM_CDF2(18650)},
+ { AOM_CDF2(16042)},
+ { AOM_CDF2(15885)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(22409)},
+ { AOM_CDF2(21012)},
+ { AOM_CDF2(15650)},
+ { AOM_CDF2(17395)},
+ { AOM_CDF2(15469)},
+ { AOM_CDF2(20205)},
+ { AOM_CDF2(19511)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ },
+ {
+ { AOM_CDF2(24220)},
+ { AOM_CDF2(22480)},
+ { AOM_CDF2(17737)},
+ { AOM_CDF2(18916)},
+ { AOM_CDF2(19268)},
+ { AOM_CDF2(18412)},
+ { AOM_CDF2(18844)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(25991)},
+ { AOM_CDF2(20314)},
+ { AOM_CDF2(17731)},
+ { AOM_CDF2(19678)},
+ { AOM_CDF2(18649)},
+ { AOM_CDF2(17307)},
+ { AOM_CDF2(21798)},
+ { AOM_CDF2(17549)},
+ { AOM_CDF2(15630)},
+ },
+ {
+ { AOM_CDF2(26585)},
+ { AOM_CDF2(21469)},
+ { AOM_CDF2(20432)},
+ { AOM_CDF2(17735)},
+ { AOM_CDF2(19280)},
+ { AOM_CDF2(15235)},
+ { AOM_CDF2(20297)},
+ { AOM_CDF2(22471)},
+ { AOM_CDF2(28997)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(26605)},
+ { AOM_CDF2(11304)},
+ { AOM_CDF2(16726)},
+ { AOM_CDF2(16560)},
+ { AOM_CDF2(20866)},
+ { AOM_CDF2(23524)},
+ { AOM_CDF2(19878)},
+ { AOM_CDF2(13469)},
+ { AOM_CDF2(23084)},
+ },
+ {
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ }
+ },
+ {
+ {
+ {
+ { AOM_CDF2(18983)},
+ { AOM_CDF2(20512)},
+ { AOM_CDF2(14885)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ },
+ {
+ { AOM_CDF2(20090)},
+ { AOM_CDF2(19444)},
+ { AOM_CDF2(17286)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(19139)},
+ { AOM_CDF2(21487)},
+ { AOM_CDF2(18959)},
+ { AOM_CDF2(20910)},
+ { AOM_CDF2(19089)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ },
+ {
+ { AOM_CDF2(20536)},
+ { AOM_CDF2(20664)},
+ { AOM_CDF2(20625)},
+ { AOM_CDF2(19123)},
+ { AOM_CDF2(14862)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(19833)},
+ { AOM_CDF2(21502)},
+ { AOM_CDF2(17485)},
+ { AOM_CDF2(20267)},
+ { AOM_CDF2(18353)},
+ { AOM_CDF2(23329)},
+ { AOM_CDF2(21478)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ },
+ {
+ { AOM_CDF2(22041)},
+ { AOM_CDF2(23434)},
+ { AOM_CDF2(20001)},
+ { AOM_CDF2(20554)},
+ { AOM_CDF2(20951)},
+ { AOM_CDF2(20145)},
+ { AOM_CDF2(15562)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(23312)},
+ { AOM_CDF2(21607)},
+ { AOM_CDF2(16526)},
+ { AOM_CDF2(18957)},
+ { AOM_CDF2(18034)},
+ { AOM_CDF2(18934)},
+ { AOM_CDF2(24247)},
+ { AOM_CDF2(16921)},
+ { AOM_CDF2(17080)},
+ },
+ {
+ { AOM_CDF2(26579)},
+ { AOM_CDF2(24910)},
+ { AOM_CDF2(18637)},
+ { AOM_CDF2(19800)},
+ { AOM_CDF2(20388)},
+ { AOM_CDF2(9887)},
+ { AOM_CDF2(15642)},
+ { AOM_CDF2(30198)},
+ { AOM_CDF2(24721)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(26998)},
+ { AOM_CDF2(16737)},
+ { AOM_CDF2(17838)},
+ { AOM_CDF2(18922)},
+ { AOM_CDF2(19515)},
+ { AOM_CDF2(18636)},
+ { AOM_CDF2(17333)},
+ { AOM_CDF2(15776)},
+ { AOM_CDF2(22658)},
+ },
+ {
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ }
+ },
+ {
+ {
+ {
+ { AOM_CDF2(20177)},
+ { AOM_CDF2(20789)},
+ { AOM_CDF2(20262)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ },
+ {
+ { AOM_CDF2(21416)},
+ { AOM_CDF2(20855)},
+ { AOM_CDF2(23410)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(20238)},
+ { AOM_CDF2(21057)},
+ { AOM_CDF2(19159)},
+ { AOM_CDF2(22337)},
+ { AOM_CDF2(20159)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ },
+ {
+ { AOM_CDF2(20125)},
+ { AOM_CDF2(20559)},
+ { AOM_CDF2(21707)},
+ { AOM_CDF2(22296)},
+ { AOM_CDF2(17333)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(19941)},
+ { AOM_CDF2(20527)},
+ { AOM_CDF2(21470)},
+ { AOM_CDF2(22487)},
+ { AOM_CDF2(19558)},
+ { AOM_CDF2(22354)},
+ { AOM_CDF2(20331)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ },
+ {
+ { AOM_CDF2(22752)},
+ { AOM_CDF2(25006)},
+ { AOM_CDF2(22075)},
+ { AOM_CDF2(21576)},
+ { AOM_CDF2(17740)},
+ { AOM_CDF2(21690)},
+ { AOM_CDF2(19211)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(21442)},
+ { AOM_CDF2(22358)},
+ { AOM_CDF2(18503)},
+ { AOM_CDF2(20291)},
+ { AOM_CDF2(19945)},
+ { AOM_CDF2(21294)},
+ { AOM_CDF2(21178)},
+ { AOM_CDF2(19400)},
+ { AOM_CDF2(10556)},
+ },
+ {
+ { AOM_CDF2(24648)},
+ { AOM_CDF2(24949)},
+ { AOM_CDF2(20708)},
+ { AOM_CDF2(23905)},
+ { AOM_CDF2(20501)},
+ { AOM_CDF2(9558)},
+ { AOM_CDF2(9423)},
+ { AOM_CDF2(30365)},
+ { AOM_CDF2(19253)},
+ }
+ },
+ {
+ {
+ { AOM_CDF2(26064)},
+ { AOM_CDF2(22098)},
+ { AOM_CDF2(19613)},
+ { AOM_CDF2(20525)},
+ { AOM_CDF2(17595)},
+ { AOM_CDF2(16618)},
+ { AOM_CDF2(20497)},
+ { AOM_CDF2(18989)},
+ { AOM_CDF2(15513)},
+ },
+ {
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ { AOM_CDF2(16384)},
+ }
+ }
+ }
+};
+
+static const u16 av1_default_eob_multi16_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][4] = {
+ {
+ {
+ { AOM_CDF5(840, 1039, 1980, 4895)},
+ { AOM_CDF5(370, 671, 1883, 4471)}
+ },
+ {
+ { AOM_CDF5(3247, 4950, 9688, 14563)},
+ { AOM_CDF5(1904, 3354, 7763, 14647)}
+ }
+ },
+ {
+ {
+ { AOM_CDF5(2125, 2551, 5165, 8946)},
+ { AOM_CDF5(513, 765, 1859, 6339)}
+ },
+ {
+ { AOM_CDF5(7637, 9498, 14259, 19108)},
+ { AOM_CDF5(2497, 4096, 8866, 16993)}
+ }
+ },
+ {
+ {
+ { AOM_CDF5(4016, 4897, 8881, 14968)},
+ { AOM_CDF5(716, 1105, 2646, 10056)}
+ },
+ {
+ { AOM_CDF5(11139, 13270, 18241, 23566)},
+ { AOM_CDF5(3192, 5032, 10297, 19755)}
+ }
+ },
+ {
+ {
+ { AOM_CDF5(6708, 8958, 14746, 22133)},
+ { AOM_CDF5(1222, 2074, 4783, 15410)}
+ },
+ {
+ { AOM_CDF5(19575, 21766, 26044, 29709)},
+ { AOM_CDF5(7297, 10767, 19273, 28194)}
+ }
+ }
+};
+
+static const u16 av1_default_eob_multi32_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8] = {
+ {
+ {
+ { AOM_CDF6(400, 520, 977, 2102, 6542)},
+ { AOM_CDF6(210, 405, 1315, 3326, 7537)}
+ },
+ {
+ { AOM_CDF6(2636, 4273, 7588, 11794, 20401)},
+ { AOM_CDF6(1786, 3179, 6902, 11357, 19054)}
+ }
+ },
+ {
+ {
+ { AOM_CDF6(989, 1249, 2019, 4151, 10785)},
+ { AOM_CDF6(313, 441, 1099, 2917, 8562)}
+ },
+ {
+ { AOM_CDF6(8394, 10352, 13932, 18855, 26014)},
+ { AOM_CDF6(2578, 4124, 8181, 13670, 24234)}
+ }
+ },
+ {
+ {
+ { AOM_CDF6(2515, 3003, 4452, 8162, 16041)},
+ { AOM_CDF6(574, 821, 1836, 5089, 13128)}
+ },
+ {
+ { AOM_CDF6(13468, 16303, 20361, 25105, 29281)},
+ { AOM_CDF6(3542, 5502, 10415, 16760, 25644)}
+ }
+ },
+ {
+ {
+ { AOM_CDF6(4617, 5709, 8446, 13584, 23135)},
+ { AOM_CDF6(1156, 1702, 3675, 9274, 20539)}
+ },
+ {
+ { AOM_CDF6(22086, 24282, 27010, 29770, 31743)},
+ { AOM_CDF6(7699, 10897, 20891, 26926, 31628)}
+ }
+ }
+};
+
+static const u16 av1_default_eob_multi64_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8] = {
+ {
+ {
+ { AOM_CDF7(329, 498, 1101, 1784, 3265, 7758)},
+ { AOM_CDF7(335, 730, 1459, 5494, 8755, 12997)}
+ },
+ {
+ { AOM_CDF7(3505, 5304, 10086, 13814, 17684, 23370)},
+ { AOM_CDF7(1563, 2700, 4876, 10911, 14706, 22480)}
+ }
+ },
+ {
+ {
+ { AOM_CDF7(1260, 1446, 2253, 3712, 6652, 13369)},
+ { AOM_CDF7(401, 605, 1029, 2563, 5845, 12626)}
+ },
+ {
+ { AOM_CDF7(8609, 10612, 14624, 18714, 22614, 29024)},
+ { AOM_CDF7(1923, 3127, 5867, 9703, 14277, 27100)}
+ }
+ },
+ {
+ {
+ { AOM_CDF7(2374, 2772, 4583, 7276, 12288, 19706)},
+ { AOM_CDF7(497, 810, 1315, 3000, 7004, 15641)}
+ },
+ {
+ { AOM_CDF7(15050, 17126, 21410, 24886, 28156, 30726)},
+ { AOM_CDF7(4034, 6290, 10235, 14982, 21214, 28491)}
+ }
+ },
+ {
+ {
+ { AOM_CDF7(6307, 7541, 12060, 16358, 22553, 27865)},
+ { AOM_CDF7(1289, 2320, 3971, 7926, 14153, 24291)}
+ },
+ {
+ { AOM_CDF7(24212, 25708, 28268, 30035, 31307, 32049)},
+ { AOM_CDF7(8726, 12378, 19409, 26450, 30038, 32462)}
+ }
+ }
+};
+
+static const u16 av1_default_eob_multi128_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8] = {
+ {
+ {
+ { AOM_CDF8(219, 482, 1140, 2091, 3680, 6028, 12586)},
+ { AOM_CDF8(371, 699, 1254, 4830, 9479, 12562, 17497)}
+ },
+ {
+ { AOM_CDF8(5245, 7456, 12880, 15852, 20033, 23932, 27608)},
+ { AOM_CDF8(2054, 3472, 5869, 14232, 18242, 20590, 26752)}
+ }
+ },
+ {
+ {
+ { AOM_CDF8(685, 933, 1488, 2714, 4766, 8562, 19254)},
+ { AOM_CDF8(217, 352, 618, 2303, 5261, 9969, 17472)}
+ },
+ {
+ { AOM_CDF8(8045, 11200, 15497, 19595, 23948, 27408, 30938)},
+ { AOM_CDF8(2310, 4160, 7471, 14997, 17931, 20768, 30240)}
+ }
+ },
+ {
+ {
+ { AOM_CDF8(1366, 1738, 2527, 5016, 9355, 15797, 24643)},
+ { AOM_CDF8(354, 558, 944, 2760, 7287, 14037, 21779)}
+ },
+ {
+ { AOM_CDF8(13627, 16246, 20173, 24429, 27948, 30415, 31863)},
+ { AOM_CDF8(6275, 9889, 14769, 23164, 27988, 30493, 32272)}
+ }
+ },
+ {
+ {
+ { AOM_CDF8(3472, 4885, 7489, 12481, 18517, 24536, 29635)},
+ { AOM_CDF8(886, 1731, 3271, 8469, 15569, 22126, 28383)}
+ },
+ {
+ { AOM_CDF8(24313, 26062, 28385, 30107, 31217, 31898, 32345)},
+ { AOM_CDF8(9165, 13282, 21150, 30286, 31894, 32571, 32712)}
+ }
+ }
+};
+
+static const u16 av1_default_eob_multi256_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8] = {
+ {
+ {
+ { AOM_CDF9(310, 584, 1887, 3589, 6168, 8611, 11352, 15652)},
+ { AOM_CDF9(998, 1850, 2998, 5604, 17341, 19888, 22899, 25583)}
+ },
+ {
+ { AOM_CDF9(2520, 3240, 5952, 8870, 12577, 17558, 19954, 24168)},
+ { AOM_CDF9(2203, 4130, 7435, 10739, 20652, 23681, 25609, 27261)}
+ }
+ },
+ {
+ {
+ { AOM_CDF9(1448, 2109, 4151, 6263, 9329, 13260, 17944, 23300)},
+ { AOM_CDF9(399, 1019, 1749, 3038, 10444, 15546, 22739, 27294)}
+ },
+ {
+ { AOM_CDF9(6402, 8148, 12623, 15072, 18728, 22847, 26447, 29377)},
+ { AOM_CDF9(1674, 3252, 5734, 10159, 22397, 23802, 24821, 30940)}
+ }
+ },
+ {
+ {
+ { AOM_CDF9(3089, 3920, 6038, 9460, 14266, 19881, 25766, 29176)},
+ { AOM_CDF9(1084, 2358, 3488, 5122, 11483, 18103, 26023, 29799)}
+ },
+ {
+ { AOM_CDF9(11514, 13794, 17480, 20754, 24361, 27378, 29492, 31277)},
+ { AOM_CDF9(6571, 9610, 15516, 21826, 29092, 30829, 31842, 32708)}
+ }
+ },
+ {
+ {
+ { AOM_CDF9(5348, 7113, 11820, 15924, 22106, 26777, 30334, 31757)},
+ { AOM_CDF9(2453, 4474, 6307, 8777, 16474, 22975, 29000, 31547)}
+ },
+ {
+ { AOM_CDF9(23110, 24597, 27140, 28894, 30167, 30927, 31392, 32094)},
+ { AOM_CDF9(9998, 17661, 25178, 28097, 31308, 32038, 32403, 32695)}
+ }
+ }
+};
+
+static const u16 av1_default_eob_multi512_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][16] = {
+ {
+ {
+ { AOM_CDF10(641, 983, 3707, 5430, 10234, 14958, 18788, 23412, 26061)},
+ { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)}
+ },
+ {
+ { AOM_CDF10(5095, 6446, 9996, 13354, 16017, 17986, 20919, 26129, 29140)},
+ { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)}
+ }
+ },
+ {
+ {
+ { AOM_CDF10(1230, 2278, 5035, 7776, 11871, 15346, 19590, 24584, 28749)},
+ { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)}
+ },
+ {
+ { AOM_CDF10(7265, 9979, 15819, 19250, 21780, 23846, 26478, 28396, 31811)},
+ { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)}
+ }
+ },
+ {
+ {
+ { AOM_CDF10(2624, 3936, 6480, 9686, 13979, 17726, 23267, 28410, 31078)},
+ { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)}
+ },
+ {
+ { AOM_CDF10(12015, 14769, 19588, 22052, 24222, 25812, 27300, 29219, 32114)},
+ { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)}
+ }
+ },
+ {
+ {
+ { AOM_CDF10(5927, 7809, 10923, 14597, 19439, 24135, 28456, 31142, 32060)},
+ { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)}
+ },
+ {
+ { AOM_CDF10(21093, 23043, 25742, 27658, 29097, 29716, 30073, 30820, 31956)},
+ { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)}
+ }
+ }
+};
+
+static const u16 av1_default_eob_multi1024_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][16] = {
+ {
+ {
+ { AOM_CDF11(393, 421, 751, 1623, 3160,
+ 6352, 13345, 18047, 22571, 25830)},
+ { AOM_CDF11(2979, 5958, 8937, 11916, 14895,
+ 17873, 20852, 23831, 26810, 29789)}
+ },
+ {
+ { AOM_CDF11(1865, 1988, 2930, 4242, 10533,
+ 16538, 21354, 27255, 28546, 31784)},
+ { AOM_CDF11(2979, 5958, 8937, 11916, 14895,
+ 17873, 20852, 23831, 26810, 29789)}
+ }
+ },
+ {
+ {
+ { AOM_CDF11(696, 948, 3145, 5702, 9706,
+ 13217, 17851, 21856, 25692, 28034)},
+ { AOM_CDF11(2979, 5958, 8937, 11916, 14895,
+ 17873, 20852, 23831, 26810, 29789)}
+ },
+ {
+ { AOM_CDF11(2672, 3591, 9330, 17084, 22725,
+ 24284, 26527, 28027, 28377, 30876)},
+ { AOM_CDF11(2979, 5958, 8937, 11916, 14895,
+ 17873, 20852, 23831, 26810, 29789)}
+ }
+ },
+ {
+ {
+ { AOM_CDF11(2784, 3831, 7041, 10521, 14847,
+ 18844, 23155, 26682, 29229, 31045)},
+ { AOM_CDF11(2979, 5958, 8937, 11916, 14895,
+ 17873, 20852, 23831, 26810, 29789)}
+ },
+ {
+ { AOM_CDF11(9577, 12466, 17739, 20750, 22061,
+ 23215, 24601, 25483, 25843, 32056)},
+ { AOM_CDF11(2979, 5958, 8937, 11916, 14895,
+ 17873, 20852, 23831, 26810, 29789)}
+ }
+ },
+ {
+ {
+ { AOM_CDF11(6698, 8334, 11961, 15762, 20186,
+ 23862, 27434, 29326, 31082, 32050)},
+ { AOM_CDF11(2979, 5958, 8937, 11916, 14895,
+ 17873, 20852, 23831, 26810, 29789)}
+ },
+ {
+ { AOM_CDF11(20569, 22426, 25569, 26859, 28053,
+ 28913, 29486, 29724, 29807, 32570)},
+ { AOM_CDF11(2979, 5958, 8937, 11916, 14895,
+ 17873, 20852, 23831, 26810, 29789)}
+ }
+ }
+};
+
+static const u16 av1_default_coeff_lps_multi_cdfs[TOKEN_CDF_Q_CTXS]
+ [TX_SIZES][PLANE_TYPES][LEVEL_CONTEXTS][CDF_SIZE(BR_CDF_SIZE) + 1] = {
+ {
+ {
+ {
+ { AOM_CDF4(14298, 20718, 24174)}, { AOM_CDF4(12536, 19601, 23789)},
+ { AOM_CDF4(8712, 15051, 19503)}, { AOM_CDF4(6170, 11327, 15434)},
+ { AOM_CDF4(4742, 8926, 12538)}, { AOM_CDF4(3803, 7317, 10546)},
+ { AOM_CDF4(1696, 3317, 4871)}, { AOM_CDF4(14392, 19951, 22756)},
+ { AOM_CDF4(15978, 23218, 26818)}, { AOM_CDF4(12187, 19474, 23889)},
+ { AOM_CDF4(9176, 15640, 20259)}, { AOM_CDF4(7068, 12655, 17028)},
+ { AOM_CDF4(5656, 10442, 14472)}, { AOM_CDF4(2580, 4992, 7244)},
+ { AOM_CDF4(12136, 18049, 21426)}, { AOM_CDF4(13784, 20721, 24481)},
+ { AOM_CDF4(10836, 17621, 21900)}, { AOM_CDF4(8372, 14444, 18847)},
+ { AOM_CDF4(6523, 11779, 16000)}, { AOM_CDF4(5337, 9898, 13760)},
+ { AOM_CDF4(3034, 5860, 8462)}
+ },
+ {
+ { AOM_CDF4(15967, 22905, 26286)}, { AOM_CDF4(13534, 20654, 24579)},
+ { AOM_CDF4(9504, 16092, 20535)}, { AOM_CDF4(6975, 12568, 16903)},
+ { AOM_CDF4(5364, 10091, 14020)}, { AOM_CDF4(4357, 8370, 11857)},
+ { AOM_CDF4(2506, 4934, 7218)}, { AOM_CDF4(23032, 28815, 30936)},
+ { AOM_CDF4(19540, 26704, 29719)}, { AOM_CDF4(15158, 22969, 27097)},
+ { AOM_CDF4(11408, 18865, 23650)}, { AOM_CDF4(8885, 15448, 20250)},
+ { AOM_CDF4(7108, 12853, 17416)}, { AOM_CDF4(4231, 8041, 11480)},
+ { AOM_CDF4(19823, 26490, 29156)}, { AOM_CDF4(18890, 25929, 28932)},
+ { AOM_CDF4(15660, 23491, 27433)}, { AOM_CDF4(12147, 19776, 24488)},
+ { AOM_CDF4(9728, 16774, 21649)}, { AOM_CDF4(7919, 14277, 19066)},
+ { AOM_CDF4(5440, 10170, 14185)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(14406, 20862, 24414)}, { AOM_CDF4(11824, 18907, 23109)},
+ { AOM_CDF4(8257, 14393, 18803)}, { AOM_CDF4(5860, 10747, 14778)},
+ { AOM_CDF4(4475, 8486, 11984)}, { AOM_CDF4(3606, 6954, 10043)},
+ { AOM_CDF4(1736, 3410, 5048)}, { AOM_CDF4(14430, 20046, 22882)},
+ { AOM_CDF4(15593, 22899, 26709)}, { AOM_CDF4(12102, 19368, 23811)},
+ { AOM_CDF4(9059, 15584, 20262)}, { AOM_CDF4(6999, 12603, 17048)},
+ { AOM_CDF4(5684, 10497, 14553)}, { AOM_CDF4(2822, 5438, 7862)},
+ { AOM_CDF4(15785, 21585, 24359)}, { AOM_CDF4(18347, 25229, 28266)},
+ { AOM_CDF4(14974, 22487, 26389)}, { AOM_CDF4(11423, 18681, 23271)},
+ { AOM_CDF4(8863, 15350, 20008)}, { AOM_CDF4(7153, 12852, 17278)},
+ { AOM_CDF4(3707, 7036, 9982)}
+ },
+ {
+ { AOM_CDF4(15460, 21696, 25469)}, { AOM_CDF4(12170, 19249, 23191)},
+ { AOM_CDF4(8723, 15027, 19332)}, { AOM_CDF4(6428, 11704, 15874)},
+ { AOM_CDF4(4922, 9292, 13052)}, { AOM_CDF4(4139, 7695, 11010)},
+ { AOM_CDF4(2291, 4508, 6598)}, { AOM_CDF4(19856, 26920, 29828)},
+ { AOM_CDF4(17923, 25289, 28792)}, { AOM_CDF4(14278, 21968, 26297)},
+ { AOM_CDF4(10910, 18136, 22950)}, { AOM_CDF4(8423, 14815, 19627)},
+ { AOM_CDF4(6771, 12283, 16774)}, { AOM_CDF4(4074, 7750, 11081)},
+ { AOM_CDF4(19852, 26074, 28672)}, { AOM_CDF4(19371, 26110, 28989)},
+ { AOM_CDF4(16265, 23873, 27663)}, { AOM_CDF4(12758, 20378, 24952)},
+ { AOM_CDF4(10095, 17098, 21961)}, { AOM_CDF4(8250, 14628, 19451)},
+ { AOM_CDF4(5205, 9745, 13622)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(10563, 16233, 19763)}, { AOM_CDF4(9794, 16022, 19804)},
+ { AOM_CDF4(6750, 11945, 15759)}, { AOM_CDF4(4963, 9186, 12752)},
+ { AOM_CDF4(3845, 7435, 10627)}, { AOM_CDF4(3051, 6085, 8834)},
+ { AOM_CDF4(1311, 2596, 3830)}, { AOM_CDF4(11246, 16404, 19689)},
+ { AOM_CDF4(12315, 18911, 22731)}, { AOM_CDF4(10557, 17095, 21289)},
+ { AOM_CDF4(8136, 14006, 18249)}, { AOM_CDF4(6348, 11474, 15565)},
+ { AOM_CDF4(5196, 9655, 13400)}, { AOM_CDF4(2349, 4526, 6587)},
+ { AOM_CDF4(13337, 18730, 21569)}, { AOM_CDF4(19306, 26071, 28882)},
+ { AOM_CDF4(15952, 23540, 27254)}, { AOM_CDF4(12409, 19934, 24430)},
+ { AOM_CDF4(9760, 16706, 21389)}, { AOM_CDF4(8004, 14220, 18818)},
+ { AOM_CDF4(4138, 7794, 10961)}
+ },
+ {
+ { AOM_CDF4(10870, 16684, 20949)}, { AOM_CDF4(9664, 15230, 18680)},
+ { AOM_CDF4(6886, 12109, 15408)}, { AOM_CDF4(4825, 8900, 12305)},
+ { AOM_CDF4(3630, 7162, 10314)}, { AOM_CDF4(3036, 6429, 9387)},
+ { AOM_CDF4(1671, 3296, 4940)}, { AOM_CDF4(13819, 19159, 23026)},
+ { AOM_CDF4(11984, 19108, 23120)}, { AOM_CDF4(10690, 17210, 21663)},
+ { AOM_CDF4(7984, 14154, 18333)}, { AOM_CDF4(6868, 12294, 16124)},
+ { AOM_CDF4(5274, 8994, 12868)}, { AOM_CDF4(2988, 5771, 8424)},
+ { AOM_CDF4(19736, 26647, 29141)}, { AOM_CDF4(18933, 26070, 28984)},
+ { AOM_CDF4(15779, 23048, 27200)}, { AOM_CDF4(12638, 20061, 24532)},
+ { AOM_CDF4(10692, 17545, 22220)}, { AOM_CDF4(9217, 15251, 20054)},
+ { AOM_CDF4(5078, 9284, 12594)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(2331, 3662, 5244)}, { AOM_CDF4(2891, 4771, 6145)},
+ { AOM_CDF4(4598, 7623, 9729)}, { AOM_CDF4(3520, 6845, 9199)},
+ { AOM_CDF4(3417, 6119, 9324)}, { AOM_CDF4(2601, 5412, 7385)},
+ { AOM_CDF4(600, 1173, 1744)}, { AOM_CDF4(7672, 13286, 17469)},
+ { AOM_CDF4(4232, 7792, 10793)}, { AOM_CDF4(2915, 5317, 7397)},
+ { AOM_CDF4(2318, 4356, 6152)}, { AOM_CDF4(2127, 4000, 5554)},
+ { AOM_CDF4(1850, 3478, 5275)}, { AOM_CDF4(977, 1933, 2843)},
+ { AOM_CDF4(18280, 24387, 27989)}, { AOM_CDF4(15852, 22671, 26185)},
+ { AOM_CDF4(13845, 20951, 24789)}, { AOM_CDF4(11055, 17966, 22129)},
+ { AOM_CDF4(9138, 15422, 19801)}, { AOM_CDF4(7454, 13145, 17456)},
+ { AOM_CDF4(3370, 6393, 9013)}
+ },
+ {
+ { AOM_CDF4(5842, 9229, 10838)}, { AOM_CDF4(2313, 3491, 4276)},
+ { AOM_CDF4(2998, 6104, 7496)}, { AOM_CDF4(2420, 7447, 9868)},
+ { AOM_CDF4(3034, 8495, 10923)}, { AOM_CDF4(4076, 8937, 10975)},
+ { AOM_CDF4(1086, 2370, 3299)}, { AOM_CDF4(9714, 17254, 20444)},
+ { AOM_CDF4(8543, 13698, 17123)}, { AOM_CDF4(4918, 9007, 11910)},
+ { AOM_CDF4(4129, 7532, 10553)}, { AOM_CDF4(2364, 5533, 8058)},
+ { AOM_CDF4(1834, 3546, 5563)}, { AOM_CDF4(1473, 2908, 4133)},
+ { AOM_CDF4(15405, 21193, 25619)}, { AOM_CDF4(15691, 21952, 26561)},
+ { AOM_CDF4(12962, 19194, 24165)}, { AOM_CDF4(10272, 17855, 22129)},
+ { AOM_CDF4(8588, 15270, 20718)}, { AOM_CDF4(8682, 14669, 19500)},
+ { AOM_CDF4(4870, 9636, 13205)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}
+ }
+ }
+ },
+ {
+ {
+ {
+ { AOM_CDF4(14995, 21341, 24749)}, { AOM_CDF4(13158, 20289, 24601)},
+ { AOM_CDF4(8941, 15326, 19876)}, { AOM_CDF4(6297, 11541, 15807)},
+ { AOM_CDF4(4817, 9029, 12776)}, { AOM_CDF4(3731, 7273, 10627)},
+ { AOM_CDF4(1847, 3617, 5354)}, { AOM_CDF4(14472, 19659, 22343)},
+ { AOM_CDF4(16806, 24162, 27533)}, { AOM_CDF4(12900, 20404, 24713)},
+ { AOM_CDF4(9411, 16112, 20797)}, { AOM_CDF4(7056, 12697, 17148)},
+ { AOM_CDF4(5544, 10339, 14460)}, { AOM_CDF4(2954, 5704, 8319)},
+ { AOM_CDF4(12464, 18071, 21354)}, { AOM_CDF4(15482, 22528, 26034)},
+ { AOM_CDF4(12070, 19269, 23624)}, { AOM_CDF4(8953, 15406, 20106)},
+ { AOM_CDF4(7027, 12730, 17220)}, { AOM_CDF4(5887, 10913, 15140)},
+ { AOM_CDF4(3793, 7278, 10447)}
+ },
+ {
+ { AOM_CDF4(15571, 22232, 25749)}, { AOM_CDF4(14506, 21575, 25374)},
+ { AOM_CDF4(10189, 17089, 21569)}, { AOM_CDF4(7316, 13301, 17915)},
+ { AOM_CDF4(5783, 10912, 15190)}, { AOM_CDF4(4760, 9155, 13088)},
+ { AOM_CDF4(2993, 5966, 8774)}, { AOM_CDF4(23424, 28903, 30778)},
+ { AOM_CDF4(20775, 27666, 30290)}, { AOM_CDF4(16474, 24410, 28299)},
+ { AOM_CDF4(12471, 20180, 24987)}, { AOM_CDF4(9410, 16487, 21439)},
+ { AOM_CDF4(7536, 13614, 18529)}, { AOM_CDF4(5048, 9586, 13549)},
+ { AOM_CDF4(21090, 27290, 29756)}, { AOM_CDF4(20796, 27402, 30026)},
+ { AOM_CDF4(17819, 25485, 28969)}, { AOM_CDF4(13860, 21909, 26462)},
+ { AOM_CDF4(11002, 18494, 23529)}, { AOM_CDF4(8953, 15929, 20897)},
+ { AOM_CDF4(6448, 11918, 16454)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(15999, 22208, 25449)}, { AOM_CDF4(13050, 19988, 24122)},
+ { AOM_CDF4(8594, 14864, 19378)}, { AOM_CDF4(6033, 11079, 15238)},
+ { AOM_CDF4(4554, 8683, 12347)}, { AOM_CDF4(3672, 7139, 10337)},
+ { AOM_CDF4(1900, 3771, 5576)}, { AOM_CDF4(15788, 21340, 23949)},
+ { AOM_CDF4(16825, 24235, 27758)}, { AOM_CDF4(12873, 20402, 24810)},
+ { AOM_CDF4(9590, 16363, 21094)}, { AOM_CDF4(7352, 13209, 17733)},
+ { AOM_CDF4(5960, 10989, 15184)}, { AOM_CDF4(3232, 6234, 9007)},
+ { AOM_CDF4(15761, 20716, 23224)}, { AOM_CDF4(19318, 25989, 28759)},
+ { AOM_CDF4(15529, 23094, 26929)}, { AOM_CDF4(11662, 18989, 23641)},
+ { AOM_CDF4(8955, 15568, 20366)}, { AOM_CDF4(7281, 13106, 17708)},
+ { AOM_CDF4(4248, 8059, 11440)}
+ },
+ {
+ { AOM_CDF4(14899, 21217, 24503)}, { AOM_CDF4(13519, 20283, 24047)},
+ { AOM_CDF4(9429, 15966, 20365)}, { AOM_CDF4(6700, 12355, 16652)},
+ { AOM_CDF4(5088, 9704, 13716)}, { AOM_CDF4(4243, 8154, 11731)},
+ { AOM_CDF4(2702, 5364, 7861)}, { AOM_CDF4(22745, 28388, 30454)},
+ { AOM_CDF4(20235, 27146, 29922)}, { AOM_CDF4(15896, 23715, 27637)},
+ { AOM_CDF4(11840, 19350, 24131)}, { AOM_CDF4(9122, 15932, 20880)},
+ { AOM_CDF4(7488, 13581, 18362)}, { AOM_CDF4(5114, 9568, 13370)},
+ { AOM_CDF4(20845, 26553, 28932)}, { AOM_CDF4(20981, 27372, 29884)},
+ { AOM_CDF4(17781, 25335, 28785)}, { AOM_CDF4(13760, 21708, 26297)},
+ { AOM_CDF4(10975, 18415, 23365)}, { AOM_CDF4(9045, 15789, 20686)},
+ { AOM_CDF4(6130, 11199, 15423)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(13549, 19724, 23158)}, { AOM_CDF4(11844, 18382, 22246)},
+ { AOM_CDF4(7919, 13619, 17773)}, { AOM_CDF4(5486, 10143, 13946)},
+ { AOM_CDF4(4166, 7983, 11324)}, { AOM_CDF4(3364, 6506, 9427)},
+ { AOM_CDF4(1598, 3160, 4674)}, { AOM_CDF4(15281, 20979, 23781)},
+ { AOM_CDF4(14939, 22119, 25952)}, { AOM_CDF4(11363, 18407, 22812)},
+ { AOM_CDF4(8609, 14857, 19370)}, { AOM_CDF4(6737, 12184, 16480)},
+ { AOM_CDF4(5506, 10263, 14262)}, { AOM_CDF4(2990, 5786, 8380)},
+ { AOM_CDF4(20249, 25253, 27417)}, { AOM_CDF4(21070, 27518, 30001)},
+ { AOM_CDF4(16854, 24469, 28074)}, { AOM_CDF4(12864, 20486, 25000)},
+ { AOM_CDF4(9962, 16978, 21778)}, { AOM_CDF4(8074, 14338, 19048)},
+ { AOM_CDF4(4494, 8479, 11906)}
+ },
+ {
+ { AOM_CDF4(13960, 19617, 22829)}, { AOM_CDF4(11150, 17341, 21228)},
+ { AOM_CDF4(7150, 12964, 17190)}, { AOM_CDF4(5331, 10002, 13867)},
+ { AOM_CDF4(4167, 7744, 11057)}, { AOM_CDF4(3480, 6629, 9646)},
+ { AOM_CDF4(1883, 3784, 5686)}, { AOM_CDF4(18752, 25660, 28912)},
+ { AOM_CDF4(16968, 24586, 28030)}, { AOM_CDF4(13520, 21055, 25313)},
+ { AOM_CDF4(10453, 17626, 22280)}, { AOM_CDF4(8386, 14505, 19116)},
+ { AOM_CDF4(6742, 12595, 17008)}, { AOM_CDF4(4273, 8140, 11499)},
+ { AOM_CDF4(22120, 27827, 30233)}, { AOM_CDF4(20563, 27358, 29895)},
+ { AOM_CDF4(17076, 24644, 28153)}, { AOM_CDF4(13362, 20942, 25309)},
+ { AOM_CDF4(10794, 17965, 22695)}, { AOM_CDF4(9014, 15652, 20319)},
+ { AOM_CDF4(5708, 10512, 14497)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(5705, 10930, 15725)}, { AOM_CDF4(7946, 12765, 16115)},
+ { AOM_CDF4(6801, 12123, 16226)}, { AOM_CDF4(5462, 10135, 14200)},
+ { AOM_CDF4(4189, 8011, 11507)}, { AOM_CDF4(3191, 6229, 9408)},
+ { AOM_CDF4(1057, 2137, 3212)}, { AOM_CDF4(10018, 17067, 21491)},
+ { AOM_CDF4(7380, 12582, 16453)}, { AOM_CDF4(6068, 10845, 14339)},
+ { AOM_CDF4(5098, 9198, 12555)}, { AOM_CDF4(4312, 8010, 11119)},
+ { AOM_CDF4(3700, 6966, 9781)}, { AOM_CDF4(1693, 3326, 4887)},
+ { AOM_CDF4(18757, 24930, 27774)}, { AOM_CDF4(17648, 24596, 27817)},
+ { AOM_CDF4(14707, 22052, 26026)}, { AOM_CDF4(11720, 18852, 23292)},
+ { AOM_CDF4(9357, 15952, 20525)}, { AOM_CDF4(7810, 13753, 18210)},
+ { AOM_CDF4(3879, 7333, 10328)}
+ },
+ {
+ { AOM_CDF4(8278, 13242, 15922)}, { AOM_CDF4(10547, 15867, 18919)},
+ { AOM_CDF4(9106, 15842, 20609)}, { AOM_CDF4(6833, 13007, 17218)},
+ { AOM_CDF4(4811, 9712, 13923)}, { AOM_CDF4(3985, 7352, 11128)},
+ { AOM_CDF4(1688, 3458, 5262)}, { AOM_CDF4(12951, 21861, 26510)},
+ { AOM_CDF4(9788, 16044, 20276)}, { AOM_CDF4(6309, 11244, 14870)},
+ { AOM_CDF4(5183, 9349, 12566)}, { AOM_CDF4(4389, 8229, 11492)},
+ { AOM_CDF4(3633, 6945, 10620)}, { AOM_CDF4(3600, 6847, 9907)},
+ { AOM_CDF4(21748, 28137, 30255)}, { AOM_CDF4(19436, 26581, 29560)},
+ { AOM_CDF4(16359, 24201, 27953)}, { AOM_CDF4(13961, 21693, 25871)},
+ { AOM_CDF4(11544, 18686, 23322)}, { AOM_CDF4(9372, 16462, 20952)},
+ { AOM_CDF4(6138, 11210, 15390)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}
+ }
+ }
+ },
+ {
+ {
+ {
+ { AOM_CDF4(16138, 22223, 25509)}, { AOM_CDF4(15347, 22430, 26332)},
+ { AOM_CDF4(9614, 16736, 21332)}, { AOM_CDF4(6600, 12275, 16907)},
+ { AOM_CDF4(4811, 9424, 13547)}, { AOM_CDF4(3748, 7809, 11420)},
+ { AOM_CDF4(2254, 4587, 6890)}, { AOM_CDF4(15196, 20284, 23177)},
+ { AOM_CDF4(18317, 25469, 28451)}, { AOM_CDF4(13918, 21651, 25842)},
+ { AOM_CDF4(10052, 17150, 21995)}, { AOM_CDF4(7499, 13630, 18587)},
+ { AOM_CDF4(6158, 11417, 16003)}, { AOM_CDF4(4014, 7785, 11252)},
+ { AOM_CDF4(15048, 21067, 24384)}, { AOM_CDF4(18202, 25346, 28553)},
+ { AOM_CDF4(14302, 22019, 26356)}, { AOM_CDF4(10839, 18139, 23166)},
+ { AOM_CDF4(8715, 15744, 20806)}, { AOM_CDF4(7536, 13576, 18544)},
+ { AOM_CDF4(5413, 10335, 14498)}
+ },
+ {
+ { AOM_CDF4(17394, 24501, 27895)}, { AOM_CDF4(15889, 23420, 27185)},
+ { AOM_CDF4(11561, 19133, 23870)}, { AOM_CDF4(8285, 14812, 19844)},
+ { AOM_CDF4(6496, 12043, 16550)}, { AOM_CDF4(4771, 9574, 13677)},
+ { AOM_CDF4(3603, 6830, 10144)}, { AOM_CDF4(21656, 27704, 30200)},
+ { AOM_CDF4(21324, 27915, 30511)}, { AOM_CDF4(17327, 25336, 28997)},
+ { AOM_CDF4(13417, 21381, 26033)}, { AOM_CDF4(10132, 17425, 22338)},
+ { AOM_CDF4(8580, 15016, 19633)}, { AOM_CDF4(5694, 11477, 16411)},
+ { AOM_CDF4(24116, 29780, 31450)}, { AOM_CDF4(23853, 29695, 31591)},
+ { AOM_CDF4(20085, 27614, 30428)}, { AOM_CDF4(15326, 24335, 28575)},
+ { AOM_CDF4(11814, 19472, 24810)}, { AOM_CDF4(10221, 18611, 24767)},
+ { AOM_CDF4(7689, 14558, 20321)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(16214, 22380, 25770)}, { AOM_CDF4(14213, 21304, 25295)},
+ { AOM_CDF4(9213, 15823, 20455)}, { AOM_CDF4(6395, 11758, 16139)},
+ { AOM_CDF4(4779, 9187, 13066)}, { AOM_CDF4(3821, 7501, 10953)},
+ { AOM_CDF4(2293, 4567, 6795)}, { AOM_CDF4(15859, 21283, 23820)},
+ { AOM_CDF4(18404, 25602, 28726)}, { AOM_CDF4(14325, 21980, 26206)},
+ { AOM_CDF4(10669, 17937, 22720)}, { AOM_CDF4(8297, 14642, 19447)},
+ { AOM_CDF4(6746, 12389, 16893)}, { AOM_CDF4(4324, 8251, 11770)},
+ { AOM_CDF4(16532, 21631, 24475)}, { AOM_CDF4(20667, 27150, 29668)},
+ { AOM_CDF4(16728, 24510, 28175)}, { AOM_CDF4(12861, 20645, 25332)},
+ { AOM_CDF4(10076, 17361, 22417)}, { AOM_CDF4(8395, 14940, 19963)},
+ { AOM_CDF4(5731, 10683, 14912)}
+ },
+ {
+ { AOM_CDF4(14433, 21155, 24938)}, { AOM_CDF4(14658, 21716, 25545)},
+ { AOM_CDF4(9923, 16824, 21557)}, { AOM_CDF4(6982, 13052, 17721)},
+ { AOM_CDF4(5419, 10503, 15050)}, { AOM_CDF4(4852, 9162, 13014)},
+ { AOM_CDF4(3271, 6395, 9630)}, { AOM_CDF4(22210, 27833, 30109)},
+ { AOM_CDF4(20750, 27368, 29821)}, { AOM_CDF4(16894, 24828, 28573)},
+ { AOM_CDF4(13247, 21276, 25757)}, { AOM_CDF4(10038, 17265, 22563)},
+ { AOM_CDF4(8587, 14947, 20327)}, { AOM_CDF4(5645, 11371, 15252)},
+ { AOM_CDF4(22027, 27526, 29714)}, { AOM_CDF4(23098, 29146, 31221)},
+ { AOM_CDF4(19886, 27341, 30272)}, { AOM_CDF4(15609, 23747, 28046)},
+ { AOM_CDF4(11993, 20065, 24939)}, { AOM_CDF4(9637, 18267, 23671)},
+ { AOM_CDF4(7625, 13801, 19144)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(14438, 20798, 24089)}, { AOM_CDF4(12621, 19203, 23097)},
+ { AOM_CDF4(8177, 14125, 18402)}, { AOM_CDF4(5674, 10501, 14456)},
+ { AOM_CDF4(4236, 8239, 11733)}, { AOM_CDF4(3447, 6750, 9806)},
+ { AOM_CDF4(1986, 3950, 5864)}, { AOM_CDF4(16208, 22099, 24930)},
+ { AOM_CDF4(16537, 24025, 27585)}, { AOM_CDF4(12780, 20381, 24867)},
+ { AOM_CDF4(9767, 16612, 21416)}, { AOM_CDF4(7686, 13738, 18398)},
+ { AOM_CDF4(6333, 11614, 15964)}, { AOM_CDF4(3941, 7571, 10836)},
+ { AOM_CDF4(22819, 27422, 29202)}, { AOM_CDF4(22224, 28514, 30721)},
+ { AOM_CDF4(17660, 25433, 28913)}, { AOM_CDF4(13574, 21482, 26002)},
+ { AOM_CDF4(10629, 17977, 22938)}, { AOM_CDF4(8612, 15298, 20265)},
+ { AOM_CDF4(5607, 10491, 14596)}
+ },
+ {
+ { AOM_CDF4(13569, 19800, 23206)}, { AOM_CDF4(13128, 19924, 23869)},
+ { AOM_CDF4(8329, 14841, 19403)}, { AOM_CDF4(6130, 10976, 15057)},
+ { AOM_CDF4(4682, 8839, 12518)}, { AOM_CDF4(3656, 7409, 10588)},
+ { AOM_CDF4(2577, 5099, 7412)}, { AOM_CDF4(22427, 28684, 30585)},
+ { AOM_CDF4(20913, 27750, 30139)}, { AOM_CDF4(15840, 24109, 27834)},
+ { AOM_CDF4(12308, 20029, 24569)}, { AOM_CDF4(10216, 16785, 21458)},
+ { AOM_CDF4(8309, 14203, 19113)}, { AOM_CDF4(6043, 11168, 15307)},
+ { AOM_CDF4(23166, 28901, 30998)}, { AOM_CDF4(21899, 28405, 30751)},
+ { AOM_CDF4(18413, 26091, 29443)}, { AOM_CDF4(15233, 23114, 27352)},
+ { AOM_CDF4(12683, 20472, 25288)}, { AOM_CDF4(10702, 18259, 23409)},
+ { AOM_CDF4(8125, 14464, 19226)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(9040, 14786, 18360)}, { AOM_CDF4(9979, 15718, 19415)},
+ { AOM_CDF4(7913, 13918, 18311)}, { AOM_CDF4(5859, 10889, 15184)},
+ { AOM_CDF4(4593, 8677, 12510)}, { AOM_CDF4(3820, 7396, 10791)},
+ { AOM_CDF4(1730, 3471, 5192)}, { AOM_CDF4(11803, 18365, 22709)},
+ { AOM_CDF4(11419, 18058, 22225)}, { AOM_CDF4(9418, 15774, 20243)},
+ { AOM_CDF4(7539, 13325, 17657)}, { AOM_CDF4(6233, 11317, 15384)},
+ { AOM_CDF4(5137, 9656, 13545)}, { AOM_CDF4(2977, 5774, 8349)},
+ { AOM_CDF4(21207, 27246, 29640)}, { AOM_CDF4(19547, 26578, 29497)},
+ { AOM_CDF4(16169, 23871, 27690)}, { AOM_CDF4(12820, 20458, 25018)},
+ { AOM_CDF4(10224, 17332, 22214)}, { AOM_CDF4(8526, 15048, 19884)},
+ { AOM_CDF4(5037, 9410, 13118)}
+ },
+ {
+ { AOM_CDF4(12339, 17329, 20140)}, { AOM_CDF4(13505, 19895, 23225)},
+ { AOM_CDF4(9847, 16944, 21564)}, { AOM_CDF4(7280, 13256, 18348)},
+ { AOM_CDF4(4712, 10009, 14454)}, { AOM_CDF4(4361, 7914, 12477)},
+ { AOM_CDF4(2870, 5628, 7995)}, { AOM_CDF4(20061, 25504, 28526)},
+ { AOM_CDF4(15235, 22878, 26145)}, { AOM_CDF4(12985, 19958, 24155)},
+ { AOM_CDF4(9782, 16641, 21403)}, { AOM_CDF4(9456, 16360, 20760)},
+ { AOM_CDF4(6855, 12940, 18557)}, { AOM_CDF4(5661, 10564, 15002)},
+ { AOM_CDF4(25656, 30602, 31894)}, { AOM_CDF4(22570, 29107, 31092)},
+ { AOM_CDF4(18917, 26423, 29541)}, { AOM_CDF4(15940, 23649, 27754)},
+ { AOM_CDF4(12803, 20581, 25219)}, { AOM_CDF4(11082, 18695, 23376)},
+ { AOM_CDF4(7939, 14373, 19005)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}
+ }
+ }
+ },
+ {
+ {
+ {
+ { AOM_CDF4(18315, 24289, 27551)}, { AOM_CDF4(16854, 24068, 27835)},
+ { AOM_CDF4(10140, 17927, 23173)}, { AOM_CDF4(6722, 12982, 18267)},
+ { AOM_CDF4(4661, 9826, 14706)}, { AOM_CDF4(3832, 8165, 12294)},
+ { AOM_CDF4(2795, 6098, 9245)}, { AOM_CDF4(17145, 23326, 26672)},
+ { AOM_CDF4(20733, 27680, 30308)}, { AOM_CDF4(16032, 24461, 28546)},
+ { AOM_CDF4(11653, 20093, 25081)}, { AOM_CDF4(9290, 16429, 22086)},
+ { AOM_CDF4(7796, 14598, 19982)}, { AOM_CDF4(6502, 12378, 17441)},
+ { AOM_CDF4(21681, 27732, 30320)}, { AOM_CDF4(22389, 29044, 31261)},
+ { AOM_CDF4(19027, 26731, 30087)}, { AOM_CDF4(14739, 23755, 28624)},
+ { AOM_CDF4(11358, 20778, 25511)}, { AOM_CDF4(10995, 18073, 24190)},
+ { AOM_CDF4(9162, 14990, 20617)}
+ },
+ {
+ { AOM_CDF4(21425, 27952, 30388)}, { AOM_CDF4(18062, 25838, 29034)},
+ { AOM_CDF4(11956, 19881, 24808)}, { AOM_CDF4(7718, 15000, 20980)},
+ { AOM_CDF4(5702, 11254, 16143)}, { AOM_CDF4(4898, 9088, 16864)},
+ { AOM_CDF4(3679, 6776, 11907)}, { AOM_CDF4(23294, 30160, 31663)},
+ { AOM_CDF4(24397, 29896, 31836)}, { AOM_CDF4(19245, 27128, 30593)},
+ { AOM_CDF4(13202, 19825, 26404)}, { AOM_CDF4(11578, 19297, 23957)},
+ { AOM_CDF4(8073, 13297, 21370)}, { AOM_CDF4(5461, 10923, 19745)},
+ { AOM_CDF4(27367, 30521, 31934)}, { AOM_CDF4(24904, 30671, 31940)},
+ { AOM_CDF4(23075, 28460, 31299)}, { AOM_CDF4(14400, 23658, 30417)},
+ { AOM_CDF4(13885, 23882, 28325)}, { AOM_CDF4(14746, 22938, 27853)},
+ { AOM_CDF4(5461, 16384, 27307)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(18274, 24813, 27890)}, { AOM_CDF4(15537, 23149, 27003)},
+ { AOM_CDF4(9449, 16740, 21827)}, { AOM_CDF4(6700, 12498, 17261)},
+ { AOM_CDF4(4988, 9866, 14198)}, { AOM_CDF4(4236, 8147, 11902)},
+ { AOM_CDF4(2867, 5860, 8654)}, { AOM_CDF4(17124, 23171, 26101)},
+ { AOM_CDF4(20396, 27477, 30148)}, { AOM_CDF4(16573, 24629, 28492)},
+ { AOM_CDF4(12749, 20846, 25674)}, { AOM_CDF4(10233, 17878, 22818)},
+ { AOM_CDF4(8525, 15332, 20363)}, { AOM_CDF4(6283, 11632, 16255)},
+ { AOM_CDF4(20466, 26511, 29286)}, { AOM_CDF4(23059, 29174, 31191)},
+ { AOM_CDF4(19481, 27263, 30241)}, { AOM_CDF4(15458, 23631, 28137)},
+ { AOM_CDF4(12416, 20608, 25693)}, { AOM_CDF4(10261, 18011, 23261)},
+ { AOM_CDF4(8016, 14655, 19666)}
+ },
+ {
+ { AOM_CDF4(17616, 24586, 28112)}, { AOM_CDF4(15809, 23299, 27155)},
+ { AOM_CDF4(10767, 18890, 23793)}, { AOM_CDF4(7727, 14255, 18865)},
+ { AOM_CDF4(6129, 11926, 16882)}, { AOM_CDF4(4482, 9704, 14861)},
+ { AOM_CDF4(3277, 7452, 11522)}, { AOM_CDF4(22956, 28551, 30730)},
+ { AOM_CDF4(22724, 28937, 30961)}, { AOM_CDF4(18467, 26324, 29580)},
+ { AOM_CDF4(13234, 20713, 25649)}, { AOM_CDF4(11181, 17592, 22481)},
+ { AOM_CDF4(8291, 18358, 24576)}, { AOM_CDF4(7568, 11881, 14984)},
+ { AOM_CDF4(24948, 29001, 31147)}, { AOM_CDF4(25674, 30619, 32151)},
+ { AOM_CDF4(20841, 26793, 29603)}, { AOM_CDF4(14669, 24356, 28666)},
+ { AOM_CDF4(11334, 23593, 28219)}, { AOM_CDF4(8922, 14762, 22873)},
+ { AOM_CDF4(8301, 13544, 20535)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(17113, 23733, 27081)}, { AOM_CDF4(14139, 21406, 25452)},
+ { AOM_CDF4(8552, 15002, 19776)}, { AOM_CDF4(5871, 11120, 15378)},
+ { AOM_CDF4(4455, 8616, 12253)}, { AOM_CDF4(3469, 6910, 10386)},
+ { AOM_CDF4(2255, 4553, 6782)}, { AOM_CDF4(18224, 24376, 27053)},
+ { AOM_CDF4(19290, 26710, 29614)}, { AOM_CDF4(14936, 22991, 27184)},
+ { AOM_CDF4(11238, 18951, 23762)}, { AOM_CDF4(8786, 15617, 20588)},
+ { AOM_CDF4(7317, 13228, 18003)}, { AOM_CDF4(5101, 9512, 13493)},
+ { AOM_CDF4(22639, 28222, 30210)}, { AOM_CDF4(23216, 29331, 31307)},
+ { AOM_CDF4(19075, 26762, 29895)}, { AOM_CDF4(15014, 23113, 27457)},
+ { AOM_CDF4(11938, 19857, 24752)}, { AOM_CDF4(9942, 17280, 22282)},
+ { AOM_CDF4(7167, 13144, 17752)}
+ },
+ {
+ { AOM_CDF4(15820, 22738, 26488)}, { AOM_CDF4(13530, 20885, 25216)},
+ { AOM_CDF4(8395, 15530, 20452)}, { AOM_CDF4(6574, 12321, 16380)},
+ { AOM_CDF4(5353, 10419, 14568)}, { AOM_CDF4(4613, 8446, 12381)},
+ { AOM_CDF4(3440, 7158, 9903)}, { AOM_CDF4(24247, 29051, 31224)},
+ { AOM_CDF4(22118, 28058, 30369)}, { AOM_CDF4(16498, 24768, 28389)},
+ { AOM_CDF4(12920, 21175, 26137)}, { AOM_CDF4(10730, 18619, 25352)},
+ { AOM_CDF4(10187, 16279, 22791)}, { AOM_CDF4(9310, 14631, 22127)},
+ { AOM_CDF4(24970, 30558, 32057)}, { AOM_CDF4(24801, 29942, 31698)},
+ { AOM_CDF4(22432, 28453, 30855)}, { AOM_CDF4(19054, 25680, 29580)},
+ { AOM_CDF4(14392, 23036, 28109)}, { AOM_CDF4(12495, 20947, 26650)},
+ { AOM_CDF4(12442, 20326, 26214)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(12162, 18785, 22648)}, { AOM_CDF4(12749, 19697, 23806)},
+ { AOM_CDF4(8580, 15297, 20346)}, { AOM_CDF4(6169, 11749, 16543)},
+ { AOM_CDF4(4836, 9391, 13448)}, { AOM_CDF4(3821, 7711, 11613)},
+ { AOM_CDF4(2228, 4601, 7070)}, { AOM_CDF4(16319, 24725, 28280)},
+ { AOM_CDF4(15698, 23277, 27168)}, { AOM_CDF4(12726, 20368, 25047)},
+ { AOM_CDF4(9912, 17015, 21976)}, { AOM_CDF4(7888, 14220, 19179)},
+ { AOM_CDF4(6777, 12284, 17018)}, { AOM_CDF4(4492, 8590, 12252)},
+ { AOM_CDF4(23249, 28904, 30947)}, { AOM_CDF4(21050, 27908, 30512)},
+ { AOM_CDF4(17440, 25340, 28949)}, { AOM_CDF4(14059, 22018, 26541)},
+ { AOM_CDF4(11288, 18903, 23898)}, { AOM_CDF4(9411, 16342, 21428)},
+ { AOM_CDF4(6278, 11588, 15944)}
+ },
+ {
+ { AOM_CDF4(13981, 20067, 23226)}, { AOM_CDF4(16922, 23580, 26783)},
+ { AOM_CDF4(11005, 19039, 24487)}, { AOM_CDF4(7389, 14218, 19798)},
+ { AOM_CDF4(5598, 11505, 17206)}, { AOM_CDF4(6090, 11213, 15659)},
+ { AOM_CDF4(3820, 7371, 10119)}, { AOM_CDF4(21082, 26925, 29675)},
+ { AOM_CDF4(21262, 28627, 31128)}, { AOM_CDF4(18392, 26454, 30437)},
+ { AOM_CDF4(14870, 22910, 27096)}, { AOM_CDF4(12620, 19484, 24908)},
+ { AOM_CDF4(9290, 16553, 22802)}, { AOM_CDF4(6668, 14288, 20004)},
+ { AOM_CDF4(27704, 31055, 31949)}, { AOM_CDF4(24709, 29978, 31788)},
+ { AOM_CDF4(21668, 29264, 31657)}, { AOM_CDF4(18295, 26968, 30074)},
+ { AOM_CDF4(16399, 24422, 29313)}, { AOM_CDF4(14347, 23026, 28104)},
+ { AOM_CDF4(12370, 19806, 24477)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}
+ }
+ }
+ }
+};
+
+static const u16 av1_default_coeff_base_multi_cdfs
+ [TOKEN_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES]
+ [SIG_COEF_CONTEXTS][CDF_SIZE(NUM_BASE_LEVELS + 2) + 1] = {
+ {
+ {
+ {
+ { AOM_CDF4(4034, 8930, 12727)}, { AOM_CDF4(18082, 29741, 31877)},
+ { AOM_CDF4(12596, 26124, 30493)}, { AOM_CDF4(9446, 21118, 27005)},
+ { AOM_CDF4(6308, 15141, 21279)}, { AOM_CDF4(2463, 6357, 9783)},
+ { AOM_CDF4(20667, 30546, 31929)}, { AOM_CDF4(13043, 26123, 30134)},
+ { AOM_CDF4(8151, 18757, 24778)}, { AOM_CDF4(5255, 12839, 18632)},
+ { AOM_CDF4(2820, 7206, 11161)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(15736, 27553, 30604)},
+ { AOM_CDF4(11210, 23794, 28787)}, { AOM_CDF4(5947, 13874, 19701)},
+ { AOM_CDF4(4215, 9323, 13891)}, { AOM_CDF4(2833, 6462, 10059)},
+ { AOM_CDF4(19605, 30393, 31582)}, { AOM_CDF4(13523, 26252, 30248)},
+ { AOM_CDF4(8446, 18622, 24512)}, { AOM_CDF4(3818, 10343, 15974)},
+ { AOM_CDF4(1481, 4117, 6796)}, { AOM_CDF4(22649, 31302, 32190)},
+ { AOM_CDF4(14829, 27127, 30449)}, { AOM_CDF4(8313, 17702, 23304)},
+ { AOM_CDF4(3022, 8301, 12786)}, { AOM_CDF4(1536, 4412, 7184)},
+ { AOM_CDF4(22354, 29774, 31372)}, { AOM_CDF4(14723, 25472, 29214)},
+ { AOM_CDF4(6673, 13745, 18662)}, { AOM_CDF4(2068, 5766, 9322)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(6302, 16444, 21761)}, { AOM_CDF4(23040, 31538, 32475)},
+ { AOM_CDF4(15196, 28452, 31496)}, { AOM_CDF4(10020, 22946, 28514)},
+ { AOM_CDF4(6533, 16862, 23501)}, { AOM_CDF4(3538, 9816, 15076)},
+ { AOM_CDF4(24444, 31875, 32525)}, { AOM_CDF4(15881, 28924, 31635)},
+ { AOM_CDF4(9922, 22873, 28466)}, { AOM_CDF4(6527, 16966, 23691)},
+ { AOM_CDF4(4114, 11303, 17220)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(20201, 30770, 32209)},
+ { AOM_CDF4(14754, 28071, 31258)}, { AOM_CDF4(8378, 20186, 26517)},
+ { AOM_CDF4(5916, 15299, 21978)}, { AOM_CDF4(4268, 11583, 17901)},
+ { AOM_CDF4(24361, 32025, 32581)}, { AOM_CDF4(18673, 30105, 31943)},
+ { AOM_CDF4(10196, 22244, 27576)}, { AOM_CDF4(5495, 14349, 20417)},
+ { AOM_CDF4(2676, 7415, 11498)}, { AOM_CDF4(24678, 31958, 32585)},
+ { AOM_CDF4(18629, 29906, 31831)}, { AOM_CDF4(9364, 20724, 26315)},
+ { AOM_CDF4(4641, 12318, 18094)}, { AOM_CDF4(2758, 7387, 11579)},
+ { AOM_CDF4(25433, 31842, 32469)}, { AOM_CDF4(18795, 29289, 31411)},
+ { AOM_CDF4(7644, 17584, 23592)}, { AOM_CDF4(3408, 9014, 15047)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(4536, 10072, 14001)}, { AOM_CDF4(25459, 31416, 32206)},
+ { AOM_CDF4(16605, 28048, 30818)}, { AOM_CDF4(11008, 22857, 27719)},
+ { AOM_CDF4(6915, 16268, 22315)}, { AOM_CDF4(2625, 6812, 10537)},
+ { AOM_CDF4(24257, 31788, 32499)}, { AOM_CDF4(16880, 29454, 31879)},
+ { AOM_CDF4(11958, 25054, 29778)}, { AOM_CDF4(7916, 18718, 25084)},
+ { AOM_CDF4(3383, 8777, 13446)}, { AOM_CDF4(22720, 31603, 32393)},
+ { AOM_CDF4(14960, 28125, 31335)}, { AOM_CDF4(9731, 22210, 27928)},
+ { AOM_CDF4(6304, 15832, 22277)}, { AOM_CDF4(2910, 7818, 12166)},
+ { AOM_CDF4(20375, 30627, 32131)}, { AOM_CDF4(13904, 27284, 30887)},
+ { AOM_CDF4(9368, 21558, 27144)}, { AOM_CDF4(5937, 14966, 21119)},
+ { AOM_CDF4(2667, 7225, 11319)}, { AOM_CDF4(23970, 31470, 32378)},
+ { AOM_CDF4(17173, 29734, 32018)}, { AOM_CDF4(12795, 25441, 29965)},
+ { AOM_CDF4(8981, 19680, 25893)}, { AOM_CDF4(4728, 11372, 16902)},
+ { AOM_CDF4(24287, 31797, 32439)}, { AOM_CDF4(16703, 29145, 31696)},
+ { AOM_CDF4(10833, 23554, 28725)}, { AOM_CDF4(6468, 16566, 23057)},
+ { AOM_CDF4(2415, 6562, 10278)}, { AOM_CDF4(26610, 32395, 32659)},
+ { AOM_CDF4(18590, 30498, 32117)}, { AOM_CDF4(12420, 25756, 29950)},
+ { AOM_CDF4(7639, 18746, 24710)}, { AOM_CDF4(3001, 8086, 12347)},
+ { AOM_CDF4(25076, 32064, 32580)}, { AOM_CDF4(17946, 30128, 32028)},
+ { AOM_CDF4(12024, 24985, 29378)}, { AOM_CDF4(7517, 18390, 24304)},
+ { AOM_CDF4(3243, 8781, 13331)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(6037, 16771, 21957)}, { AOM_CDF4(24774, 31704, 32426)},
+ { AOM_CDF4(16830, 28589, 31056)}, { AOM_CDF4(10602, 22828, 27760)},
+ { AOM_CDF4(6733, 16829, 23071)}, { AOM_CDF4(3250, 8914, 13556)},
+ { AOM_CDF4(25582, 32220, 32668)}, { AOM_CDF4(18659, 30342, 32223)},
+ { AOM_CDF4(12546, 26149, 30515)}, { AOM_CDF4(8420, 20451, 26801)},
+ { AOM_CDF4(4636, 12420, 18344)}, { AOM_CDF4(27581, 32362, 32639)},
+ { AOM_CDF4(18987, 30083, 31978)}, { AOM_CDF4(11327, 24248, 29084)},
+ { AOM_CDF4(7264, 17719, 24120)}, { AOM_CDF4(3995, 10768, 16169)},
+ { AOM_CDF4(25893, 31831, 32487)}, { AOM_CDF4(16577, 28587, 31379)},
+ { AOM_CDF4(10189, 22748, 28182)}, { AOM_CDF4(6832, 17094, 23556)},
+ { AOM_CDF4(3708, 10110, 15334)}, { AOM_CDF4(25904, 32282, 32656)},
+ { AOM_CDF4(19721, 30792, 32276)}, { AOM_CDF4(12819, 26243, 30411)},
+ { AOM_CDF4(8572, 20614, 26891)}, { AOM_CDF4(5364, 14059, 20467)},
+ { AOM_CDF4(26580, 32438, 32677)}, { AOM_CDF4(20852, 31225, 32340)},
+ { AOM_CDF4(12435, 25700, 29967)}, { AOM_CDF4(8691, 20825, 26976)},
+ { AOM_CDF4(4446, 12209, 17269)}, { AOM_CDF4(27350, 32429, 32696)},
+ { AOM_CDF4(21372, 30977, 32272)}, { AOM_CDF4(12673, 25270, 29853)},
+ { AOM_CDF4(9208, 20925, 26640)}, { AOM_CDF4(5018, 13351, 18732)},
+ { AOM_CDF4(27351, 32479, 32713)}, { AOM_CDF4(21398, 31209, 32387)},
+ { AOM_CDF4(12162, 25047, 29842)}, { AOM_CDF4(7896, 18691, 25319)},
+ { AOM_CDF4(4670, 12882, 18881)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(5487, 10460, 13708)}, { AOM_CDF4(21597, 28303, 30674)},
+ { AOM_CDF4(11037, 21953, 26476)}, { AOM_CDF4(8147, 17962, 22952)},
+ { AOM_CDF4(5242, 13061, 18532)}, { AOM_CDF4(1889, 5208, 8182)},
+ { AOM_CDF4(26774, 32133, 32590)}, { AOM_CDF4(17844, 29564, 31767)},
+ { AOM_CDF4(11690, 24438, 29171)}, { AOM_CDF4(7542, 18215, 24459)},
+ { AOM_CDF4(2993, 8050, 12319)}, { AOM_CDF4(28023, 32328, 32591)},
+ { AOM_CDF4(18651, 30126, 31954)}, { AOM_CDF4(12164, 25146, 29589)},
+ { AOM_CDF4(7762, 18530, 24771)}, { AOM_CDF4(3492, 9183, 13920)},
+ { AOM_CDF4(27591, 32008, 32491)}, { AOM_CDF4(17149, 28853, 31510)},
+ { AOM_CDF4(11485, 24003, 28860)}, { AOM_CDF4(7697, 18086, 24210)},
+ { AOM_CDF4(3075, 7999, 12218)}, { AOM_CDF4(28268, 32482, 32654)},
+ { AOM_CDF4(19631, 31051, 32404)}, { AOM_CDF4(13860, 27260, 31020)},
+ { AOM_CDF4(9605, 21613, 27594)}, { AOM_CDF4(4876, 12162, 17908)},
+ { AOM_CDF4(27248, 32316, 32576)}, { AOM_CDF4(18955, 30457, 32075)},
+ { AOM_CDF4(11824, 23997, 28795)}, { AOM_CDF4(7346, 18196, 24647)},
+ { AOM_CDF4(3403, 9247, 14111)}, { AOM_CDF4(29711, 32655, 32735)},
+ { AOM_CDF4(21169, 31394, 32417)}, { AOM_CDF4(13487, 27198, 30957)},
+ { AOM_CDF4(8828, 21683, 27614)}, { AOM_CDF4(4270, 11451, 17038)},
+ { AOM_CDF4(28708, 32578, 32731)}, { AOM_CDF4(20120, 31241, 32482)},
+ { AOM_CDF4(13692, 27550, 31321)}, { AOM_CDF4(9418, 22514, 28439)},
+ { AOM_CDF4(4999, 13283, 19462)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(5673, 14302, 19711)}, { AOM_CDF4(26251, 30701, 31834)},
+ { AOM_CDF4(12782, 23783, 27803)}, { AOM_CDF4(9127, 20657, 25808)},
+ { AOM_CDF4(6368, 16208, 21462)}, { AOM_CDF4(2465, 7177, 10822)},
+ { AOM_CDF4(29961, 32563, 32719)}, { AOM_CDF4(18318, 29891, 31949)},
+ { AOM_CDF4(11361, 24514, 29357)}, { AOM_CDF4(7900, 19603, 25607)},
+ { AOM_CDF4(4002, 10590, 15546)}, { AOM_CDF4(29637, 32310, 32595)},
+ { AOM_CDF4(18296, 29913, 31809)}, { AOM_CDF4(10144, 21515, 26871)},
+ { AOM_CDF4(5358, 14322, 20394)}, { AOM_CDF4(3067, 8362, 13346)},
+ { AOM_CDF4(28652, 32470, 32676)}, { AOM_CDF4(17538, 30771, 32209)},
+ { AOM_CDF4(13924, 26882, 30494)}, { AOM_CDF4(10496, 22837, 27869)},
+ { AOM_CDF4(7236, 16396, 21621)}, { AOM_CDF4(30743, 32687, 32746)},
+ { AOM_CDF4(23006, 31676, 32489)}, { AOM_CDF4(14494, 27828, 31120)},
+ { AOM_CDF4(10174, 22801, 28352)}, { AOM_CDF4(6242, 15281, 21043)},
+ { AOM_CDF4(25817, 32243, 32720)}, { AOM_CDF4(18618, 31367, 32325)},
+ { AOM_CDF4(13997, 28318, 31878)}, { AOM_CDF4(12255, 26534, 31383)},
+ { AOM_CDF4(9561, 21588, 28450)}, { AOM_CDF4(28188, 32635, 32724)},
+ { AOM_CDF4(22060, 32365, 32728)}, { AOM_CDF4(18102, 30690, 32528)},
+ { AOM_CDF4(14196, 28864, 31999)}, { AOM_CDF4(12262, 25792, 30865)},
+ { AOM_CDF4(24176, 32109, 32628)}, { AOM_CDF4(18280, 29681, 31963)},
+ { AOM_CDF4(10205, 23703, 29664)}, { AOM_CDF4(7889, 20025, 27676)},
+ { AOM_CDF4(6060, 16743, 23970)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(5141, 7096, 8260)}, { AOM_CDF4(27186, 29022, 29789)},
+ { AOM_CDF4(6668, 12568, 15682)}, { AOM_CDF4(2172, 6181, 8638)},
+ { AOM_CDF4(1126, 3379, 4531)}, { AOM_CDF4(443, 1361, 2254)},
+ { AOM_CDF4(26083, 31153, 32436)}, { AOM_CDF4(13486, 24603, 28483)},
+ { AOM_CDF4(6508, 14840, 19910)}, { AOM_CDF4(3386, 8800, 13286)},
+ { AOM_CDF4(1530, 4322, 7054)}, { AOM_CDF4(29639, 32080, 32548)},
+ { AOM_CDF4(15897, 27552, 30290)}, { AOM_CDF4(8588, 20047, 25383)},
+ { AOM_CDF4(4889, 13339, 19269)}, { AOM_CDF4(2240, 6871, 10498)},
+ { AOM_CDF4(28165, 32197, 32517)}, { AOM_CDF4(20735, 30427, 31568)},
+ { AOM_CDF4(14325, 24671, 27692)}, { AOM_CDF4(5119, 12554, 17805)},
+ { AOM_CDF4(1810, 5441, 8261)}, { AOM_CDF4(31212, 32724, 32748)},
+ { AOM_CDF4(23352, 31766, 32545)}, { AOM_CDF4(14669, 27570, 31059)},
+ { AOM_CDF4(8492, 20894, 27272)}, { AOM_CDF4(3644, 10194, 15204)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(2461, 7013, 9371)}, { AOM_CDF4(24749, 29600, 30986)},
+ { AOM_CDF4(9466, 19037, 22417)}, { AOM_CDF4(3584, 9280, 14400)},
+ { AOM_CDF4(1505, 3929, 5433)}, { AOM_CDF4(677, 1500, 2736)},
+ { AOM_CDF4(23987, 30702, 32117)}, { AOM_CDF4(13554, 24571, 29263)},
+ { AOM_CDF4(6211, 14556, 21155)}, { AOM_CDF4(3135, 10972, 15625)},
+ { AOM_CDF4(2435, 7127, 11427)}, { AOM_CDF4(31300, 32532, 32550)},
+ { AOM_CDF4(14757, 30365, 31954)}, { AOM_CDF4(4405, 11612, 18553)},
+ { AOM_CDF4(580, 4132, 7322)}, { AOM_CDF4(1695, 10169, 14124)},
+ { AOM_CDF4(30008, 32282, 32591)}, { AOM_CDF4(19244, 30108, 31748)},
+ { AOM_CDF4(11180, 24158, 29555)}, { AOM_CDF4(5650, 14972, 19209)},
+ { AOM_CDF4(2114, 5109, 8456)}, { AOM_CDF4(31856, 32716, 32748)},
+ { AOM_CDF4(23012, 31664, 32572)}, { AOM_CDF4(13694, 26656, 30636)},
+ { AOM_CDF4(8142, 19508, 26093)}, { AOM_CDF4(4253, 10955, 16724)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(601, 983, 1311)}, { AOM_CDF4(18725, 23406, 28087)},
+ { AOM_CDF4(5461, 8192, 10923)}, { AOM_CDF4(3781, 15124, 21425)},
+ { AOM_CDF4(2587, 7761, 12072)}, { AOM_CDF4(106, 458, 810)},
+ { AOM_CDF4(22282, 29710, 31894)}, { AOM_CDF4(8508, 20926, 25984)},
+ { AOM_CDF4(3726, 12713, 18083)}, { AOM_CDF4(1620, 7112, 10893)},
+ { AOM_CDF4(729, 2236, 3495)}, { AOM_CDF4(30163, 32474, 32684)},
+ { AOM_CDF4(18304, 30464, 32000)}, { AOM_CDF4(11443, 26526, 29647)},
+ { AOM_CDF4(6007, 15292, 21299)}, { AOM_CDF4(2234, 6703, 8937)},
+ { AOM_CDF4(30954, 32177, 32571)}, { AOM_CDF4(17363, 29562, 31076)},
+ { AOM_CDF4(9686, 22464, 27410)}, { AOM_CDF4(8192, 16384, 21390)},
+ { AOM_CDF4(1755, 8046, 11264)}, { AOM_CDF4(31168, 32734, 32748)},
+ { AOM_CDF4(22486, 31441, 32471)}, { AOM_CDF4(12833, 25627, 29738)},
+ { AOM_CDF4(6980, 17379, 23122)}, { AOM_CDF4(3111, 8887, 13479)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ }
+ },
+ {
+ {
+ {
+ { AOM_CDF4(6041, 11854, 15927)}, { AOM_CDF4(20326, 30905, 32251)},
+ { AOM_CDF4(14164, 26831, 30725)}, { AOM_CDF4(9760, 20647, 26585)},
+ { AOM_CDF4(6416, 14953, 21219)}, { AOM_CDF4(2966, 7151, 10891)},
+ { AOM_CDF4(23567, 31374, 32254)}, { AOM_CDF4(14978, 27416, 30946)},
+ { AOM_CDF4(9434, 20225, 26254)}, { AOM_CDF4(6658, 14558, 20535)},
+ { AOM_CDF4(3916, 8677, 12989)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(18088, 29545, 31587)},
+ { AOM_CDF4(13062, 25843, 30073)}, { AOM_CDF4(8940, 16827, 22251)},
+ { AOM_CDF4(7654, 13220, 17973)}, { AOM_CDF4(5733, 10316, 14456)},
+ { AOM_CDF4(22879, 31388, 32114)}, { AOM_CDF4(15215, 27993, 30955)},
+ { AOM_CDF4(9397, 19445, 24978)}, { AOM_CDF4(3442, 9813, 15344)},
+ { AOM_CDF4(1368, 3936, 6532)}, { AOM_CDF4(25494, 32033, 32406)},
+ { AOM_CDF4(16772, 27963, 30718)}, { AOM_CDF4(9419, 18165, 23260)},
+ { AOM_CDF4(2677, 7501, 11797)}, { AOM_CDF4(1516, 4344, 7170)},
+ { AOM_CDF4(26556, 31454, 32101)}, { AOM_CDF4(17128, 27035, 30108)},
+ { AOM_CDF4(8324, 15344, 20249)}, { AOM_CDF4(1903, 5696, 9469)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(8455, 19003, 24368)}, { AOM_CDF4(23563, 32021, 32604)},
+ { AOM_CDF4(16237, 29446, 31935)}, { AOM_CDF4(10724, 23999, 29358)},
+ { AOM_CDF4(6725, 17528, 24416)}, { AOM_CDF4(3927, 10927, 16825)},
+ { AOM_CDF4(26313, 32288, 32634)}, { AOM_CDF4(17430, 30095, 32095)},
+ { AOM_CDF4(11116, 24606, 29679)}, { AOM_CDF4(7195, 18384, 25269)},
+ { AOM_CDF4(4726, 12852, 19315)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(22822, 31648, 32483)},
+ { AOM_CDF4(16724, 29633, 31929)}, { AOM_CDF4(10261, 23033, 28725)},
+ { AOM_CDF4(7029, 17840, 24528)}, { AOM_CDF4(4867, 13886, 21502)},
+ { AOM_CDF4(25298, 31892, 32491)}, { AOM_CDF4(17809, 29330, 31512)},
+ { AOM_CDF4(9668, 21329, 26579)}, { AOM_CDF4(4774, 12956, 18976)},
+ { AOM_CDF4(2322, 7030, 11540)}, { AOM_CDF4(25472, 31920, 32543)},
+ { AOM_CDF4(17957, 29387, 31632)}, { AOM_CDF4(9196, 20593, 26400)},
+ { AOM_CDF4(4680, 12705, 19202)}, { AOM_CDF4(2917, 8456, 13436)},
+ { AOM_CDF4(26471, 32059, 32574)}, { AOM_CDF4(18458, 29783, 31909)},
+ { AOM_CDF4(8400, 19464, 25956)}, { AOM_CDF4(3812, 10973, 17206)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(6779, 13743, 17678)}, { AOM_CDF4(24806, 31797, 32457)},
+ { AOM_CDF4(17616, 29047, 31372)}, { AOM_CDF4(11063, 23175, 28003)},
+ { AOM_CDF4(6521, 16110, 22324)}, { AOM_CDF4(2764, 7504, 11654)},
+ { AOM_CDF4(25266, 32367, 32637)}, { AOM_CDF4(19054, 30553, 32175)},
+ { AOM_CDF4(12139, 25212, 29807)}, { AOM_CDF4(7311, 18162, 24704)},
+ { AOM_CDF4(3397, 9164, 14074)}, { AOM_CDF4(25988, 32208, 32522)},
+ { AOM_CDF4(16253, 28912, 31526)}, { AOM_CDF4(9151, 21387, 27372)},
+ { AOM_CDF4(5688, 14915, 21496)}, { AOM_CDF4(2717, 7627, 12004)},
+ { AOM_CDF4(23144, 31855, 32443)}, { AOM_CDF4(16070, 28491, 31325)},
+ { AOM_CDF4(8702, 20467, 26517)}, { AOM_CDF4(5243, 13956, 20367)},
+ { AOM_CDF4(2621, 7335, 11567)}, { AOM_CDF4(26636, 32340, 32630)},
+ { AOM_CDF4(19990, 31050, 32341)}, { AOM_CDF4(13243, 26105, 30315)},
+ { AOM_CDF4(8588, 19521, 25918)}, { AOM_CDF4(4717, 11585, 17304)},
+ { AOM_CDF4(25844, 32292, 32582)}, { AOM_CDF4(19090, 30635, 32097)},
+ { AOM_CDF4(11963, 24546, 28939)}, { AOM_CDF4(6218, 16087, 22354)},
+ { AOM_CDF4(2340, 6608, 10426)}, { AOM_CDF4(28046, 32576, 32694)},
+ { AOM_CDF4(21178, 31313, 32296)}, { AOM_CDF4(13486, 26184, 29870)},
+ { AOM_CDF4(7149, 17871, 23723)}, { AOM_CDF4(2833, 7958, 12259)},
+ { AOM_CDF4(27710, 32528, 32686)}, { AOM_CDF4(20674, 31076, 32268)},
+ { AOM_CDF4(12413, 24955, 29243)}, { AOM_CDF4(6676, 16927, 23097)},
+ { AOM_CDF4(2966, 8333, 12919)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(8639, 19339, 24429)}, { AOM_CDF4(24404, 31837, 32525)},
+ { AOM_CDF4(16997, 29425, 31784)}, { AOM_CDF4(11253, 24234, 29149)},
+ { AOM_CDF4(6751, 17394, 24028)}, { AOM_CDF4(3490, 9830, 15191)},
+ { AOM_CDF4(26283, 32471, 32714)}, { AOM_CDF4(19599, 31168, 32442)},
+ { AOM_CDF4(13146, 26954, 30893)}, { AOM_CDF4(8214, 20588, 26890)},
+ { AOM_CDF4(4699, 13081, 19300)}, { AOM_CDF4(28212, 32458, 32669)},
+ { AOM_CDF4(18594, 30316, 32100)}, { AOM_CDF4(11219, 24408, 29234)},
+ { AOM_CDF4(6865, 17656, 24149)}, { AOM_CDF4(3678, 10362, 16006)},
+ { AOM_CDF4(25825, 32136, 32616)}, { AOM_CDF4(17313, 29853, 32021)},
+ { AOM_CDF4(11197, 24471, 29472)}, { AOM_CDF4(6947, 17781, 24405)},
+ { AOM_CDF4(3768, 10660, 16261)}, { AOM_CDF4(27352, 32500, 32706)},
+ { AOM_CDF4(20850, 31468, 32469)}, { AOM_CDF4(14021, 27707, 31133)},
+ { AOM_CDF4(8964, 21748, 27838)}, { AOM_CDF4(5437, 14665, 21187)},
+ { AOM_CDF4(26304, 32492, 32698)}, { AOM_CDF4(20409, 31380, 32385)},
+ { AOM_CDF4(13682, 27222, 30632)}, { AOM_CDF4(8974, 21236, 26685)},
+ { AOM_CDF4(4234, 11665, 16934)}, { AOM_CDF4(26273, 32357, 32711)},
+ { AOM_CDF4(20672, 31242, 32441)}, { AOM_CDF4(14172, 27254, 30902)},
+ { AOM_CDF4(9870, 21898, 27275)}, { AOM_CDF4(5164, 13506, 19270)},
+ { AOM_CDF4(26725, 32459, 32728)}, { AOM_CDF4(20991, 31442, 32527)},
+ { AOM_CDF4(13071, 26434, 30811)}, { AOM_CDF4(8184, 20090, 26742)},
+ { AOM_CDF4(4803, 13255, 19895)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(7555, 14942, 18501)}, { AOM_CDF4(24410, 31178, 32287)},
+ { AOM_CDF4(14394, 26738, 30253)}, { AOM_CDF4(8413, 19554, 25195)},
+ { AOM_CDF4(4766, 12924, 18785)}, { AOM_CDF4(2029, 5806, 9207)},
+ { AOM_CDF4(26776, 32364, 32663)}, { AOM_CDF4(18732, 29967, 31931)},
+ { AOM_CDF4(11005, 23786, 28852)}, { AOM_CDF4(6466, 16909, 23510)},
+ { AOM_CDF4(3044, 8638, 13419)}, { AOM_CDF4(29208, 32582, 32704)},
+ { AOM_CDF4(20068, 30857, 32208)}, { AOM_CDF4(12003, 25085, 29595)},
+ { AOM_CDF4(6947, 17750, 24189)}, { AOM_CDF4(3245, 9103, 14007)},
+ { AOM_CDF4(27359, 32465, 32669)}, { AOM_CDF4(19421, 30614, 32174)},
+ { AOM_CDF4(11915, 25010, 29579)}, { AOM_CDF4(6950, 17676, 24074)},
+ { AOM_CDF4(3007, 8473, 13096)}, { AOM_CDF4(29002, 32676, 32735)},
+ { AOM_CDF4(22102, 31849, 32576)}, { AOM_CDF4(14408, 28009, 31405)},
+ { AOM_CDF4(9027, 21679, 27931)}, { AOM_CDF4(4694, 12678, 18748)},
+ { AOM_CDF4(28216, 32528, 32682)}, { AOM_CDF4(20849, 31264, 32318)},
+ { AOM_CDF4(12756, 25815, 29751)}, { AOM_CDF4(7565, 18801, 24923)},
+ { AOM_CDF4(3509, 9533, 14477)}, { AOM_CDF4(30133, 32687, 32739)},
+ { AOM_CDF4(23063, 31910, 32515)}, { AOM_CDF4(14588, 28051, 31132)},
+ { AOM_CDF4(9085, 21649, 27457)}, { AOM_CDF4(4261, 11654, 17264)},
+ { AOM_CDF4(29518, 32691, 32748)}, { AOM_CDF4(22451, 31959, 32613)},
+ { AOM_CDF4(14864, 28722, 31700)}, { AOM_CDF4(9695, 22964, 28716)},
+ { AOM_CDF4(4932, 13358, 19502)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(6465, 16958, 21688)}, { AOM_CDF4(25199, 31514, 32360)},
+ { AOM_CDF4(14774, 27149, 30607)}, { AOM_CDF4(9257, 21438, 26972)},
+ { AOM_CDF4(5723, 15183, 21882)}, { AOM_CDF4(3150, 8879, 13731)},
+ { AOM_CDF4(26989, 32262, 32682)}, { AOM_CDF4(17396, 29937, 32085)},
+ { AOM_CDF4(11387, 24901, 29784)}, { AOM_CDF4(7289, 18821, 25548)},
+ { AOM_CDF4(3734, 10577, 16086)}, { AOM_CDF4(29728, 32501, 32695)},
+ { AOM_CDF4(17431, 29701, 31903)}, { AOM_CDF4(9921, 22826, 28300)},
+ { AOM_CDF4(5896, 15434, 22068)}, { AOM_CDF4(3430, 9646, 14757)},
+ { AOM_CDF4(28614, 32511, 32705)}, { AOM_CDF4(19364, 30638, 32263)},
+ { AOM_CDF4(13129, 26254, 30402)}, { AOM_CDF4(8754, 20484, 26440)},
+ { AOM_CDF4(4378, 11607, 17110)}, { AOM_CDF4(30292, 32671, 32744)},
+ { AOM_CDF4(21780, 31603, 32501)}, { AOM_CDF4(14314, 27829, 31291)},
+ { AOM_CDF4(9611, 22327, 28263)}, { AOM_CDF4(4890, 13087, 19065)},
+ { AOM_CDF4(25862, 32567, 32733)}, { AOM_CDF4(20794, 32050, 32567)},
+ { AOM_CDF4(17243, 30625, 32254)}, { AOM_CDF4(13283, 27628, 31474)},
+ { AOM_CDF4(9669, 22532, 28918)}, { AOM_CDF4(27435, 32697, 32748)},
+ { AOM_CDF4(24922, 32390, 32714)}, { AOM_CDF4(21449, 31504, 32536)},
+ { AOM_CDF4(16392, 29729, 31832)}, { AOM_CDF4(11692, 24884, 29076)},
+ { AOM_CDF4(24193, 32290, 32735)}, { AOM_CDF4(18909, 31104, 32563)},
+ { AOM_CDF4(12236, 26841, 31403)}, { AOM_CDF4(8171, 21840, 29082)},
+ { AOM_CDF4(7224, 17280, 25275)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(3078, 6839, 9890)}, { AOM_CDF4(13837, 20450, 24479)},
+ { AOM_CDF4(5914, 14222, 19328)}, { AOM_CDF4(3866, 10267, 14762)},
+ { AOM_CDF4(2612, 7208, 11042)}, { AOM_CDF4(1067, 2991, 4776)},
+ { AOM_CDF4(25817, 31646, 32529)}, { AOM_CDF4(13708, 26338, 30385)},
+ { AOM_CDF4(7328, 18585, 24870)}, { AOM_CDF4(4691, 13080, 19276)},
+ { AOM_CDF4(1825, 5253, 8352)}, { AOM_CDF4(29386, 32315, 32624)},
+ { AOM_CDF4(17160, 29001, 31360)}, { AOM_CDF4(9602, 21862, 27396)},
+ { AOM_CDF4(5915, 15772, 22148)}, { AOM_CDF4(2786, 7779, 12047)},
+ { AOM_CDF4(29246, 32450, 32663)}, { AOM_CDF4(18696, 29929, 31818)},
+ { AOM_CDF4(10510, 23369, 28560)}, { AOM_CDF4(6229, 16499, 23125)},
+ { AOM_CDF4(2608, 7448, 11705)}, { AOM_CDF4(30753, 32710, 32748)},
+ { AOM_CDF4(21638, 31487, 32503)}, { AOM_CDF4(12937, 26854, 30870)},
+ { AOM_CDF4(8182, 20596, 26970)}, { AOM_CDF4(3637, 10269, 15497)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(5244, 12150, 16906)}, { AOM_CDF4(20486, 26858, 29701)},
+ { AOM_CDF4(7756, 18317, 23735)}, { AOM_CDF4(3452, 9256, 13146)},
+ { AOM_CDF4(2020, 5206, 8229)}, { AOM_CDF4(1801, 4993, 7903)},
+ { AOM_CDF4(27051, 31858, 32531)}, { AOM_CDF4(15988, 27531, 30619)},
+ { AOM_CDF4(9188, 21484, 26719)}, { AOM_CDF4(6273, 17186, 23800)},
+ { AOM_CDF4(3108, 9355, 14764)}, { AOM_CDF4(31076, 32520, 32680)},
+ { AOM_CDF4(18119, 30037, 31850)}, { AOM_CDF4(10244, 22969, 27472)},
+ { AOM_CDF4(4692, 14077, 19273)}, { AOM_CDF4(3694, 11677, 17556)},
+ { AOM_CDF4(30060, 32581, 32720)}, { AOM_CDF4(21011, 30775, 32120)},
+ { AOM_CDF4(11931, 24820, 29289)}, { AOM_CDF4(7119, 17662, 24356)},
+ { AOM_CDF4(3833, 10706, 16304)}, { AOM_CDF4(31954, 32731, 32748)},
+ { AOM_CDF4(23913, 31724, 32489)}, { AOM_CDF4(15520, 28060, 31286)},
+ { AOM_CDF4(11517, 23008, 28571)}, { AOM_CDF4(6193, 14508, 20629)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(1035, 2807, 4156)}, { AOM_CDF4(13162, 18138, 20939)},
+ { AOM_CDF4(2696, 6633, 8755)}, { AOM_CDF4(1373, 4161, 6853)},
+ { AOM_CDF4(1099, 2746, 4716)}, { AOM_CDF4(340, 1021, 1599)},
+ { AOM_CDF4(22826, 30419, 32135)}, { AOM_CDF4(10395, 21762, 26942)},
+ { AOM_CDF4(4726, 12407, 17361)}, { AOM_CDF4(2447, 7080, 10593)},
+ { AOM_CDF4(1227, 3717, 6011)}, { AOM_CDF4(28156, 31424, 31934)},
+ { AOM_CDF4(16915, 27754, 30373)}, { AOM_CDF4(9148, 20990, 26431)},
+ { AOM_CDF4(5950, 15515, 21148)}, { AOM_CDF4(2492, 7327, 11526)},
+ { AOM_CDF4(30602, 32477, 32670)}, { AOM_CDF4(20026, 29955, 31568)},
+ { AOM_CDF4(11220, 23628, 28105)}, { AOM_CDF4(6652, 17019, 22973)},
+ { AOM_CDF4(3064, 8536, 13043)}, { AOM_CDF4(31769, 32724, 32748)},
+ { AOM_CDF4(22230, 30887, 32373)}, { AOM_CDF4(12234, 25079, 29731)},
+ { AOM_CDF4(7326, 18816, 25353)}, { AOM_CDF4(3933, 10907, 16616)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ }
+ },
+ {
+ {
+ {
+ { AOM_CDF4(8896, 16227, 20630)}, { AOM_CDF4(23629, 31782, 32527)},
+ { AOM_CDF4(15173, 27755, 31321)}, { AOM_CDF4(10158, 21233, 27382)},
+ { AOM_CDF4(6420, 14857, 21558)}, { AOM_CDF4(3269, 8155, 12646)},
+ { AOM_CDF4(24835, 32009, 32496)}, { AOM_CDF4(16509, 28421, 31579)},
+ { AOM_CDF4(10957, 21514, 27418)}, { AOM_CDF4(7881, 15930, 22096)},
+ { AOM_CDF4(5388, 10960, 15918)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(20745, 30773, 32093)},
+ { AOM_CDF4(15200, 27221, 30861)}, { AOM_CDF4(13032, 20873, 25667)},
+ { AOM_CDF4(12285, 18663, 23494)}, { AOM_CDF4(11563, 17481, 21489)},
+ { AOM_CDF4(26260, 31982, 32320)}, { AOM_CDF4(15397, 28083, 31100)},
+ { AOM_CDF4(9742, 19217, 24824)}, { AOM_CDF4(3261, 9629, 15362)},
+ { AOM_CDF4(1480, 4322, 7499)}, { AOM_CDF4(27599, 32256, 32460)},
+ { AOM_CDF4(16857, 27659, 30774)}, { AOM_CDF4(9551, 18290, 23748)},
+ { AOM_CDF4(3052, 8933, 14103)}, { AOM_CDF4(2021, 5910, 9787)},
+ { AOM_CDF4(29005, 32015, 32392)}, { AOM_CDF4(17677, 27694, 30863)},
+ { AOM_CDF4(9204, 17356, 23219)}, { AOM_CDF4(2403, 7516, 12814)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(10808, 22056, 26896)}, { AOM_CDF4(25739, 32313, 32676)},
+ { AOM_CDF4(17288, 30203, 32221)}, { AOM_CDF4(11359, 24878, 29896)},
+ { AOM_CDF4(6949, 17767, 24893)}, { AOM_CDF4(4287, 11796, 18071)},
+ { AOM_CDF4(27880, 32521, 32705)}, { AOM_CDF4(19038, 31004, 32414)},
+ { AOM_CDF4(12564, 26345, 30768)}, { AOM_CDF4(8269, 19947, 26779)},
+ { AOM_CDF4(5674, 14657, 21674)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(25742, 32319, 32671)},
+ { AOM_CDF4(19557, 31164, 32454)}, { AOM_CDF4(13381, 26381, 30755)},
+ { AOM_CDF4(10101, 21466, 26722)}, { AOM_CDF4(9209, 19650, 26825)},
+ { AOM_CDF4(27107, 31917, 32432)}, { AOM_CDF4(18056, 28893, 31203)},
+ { AOM_CDF4(10200, 21434, 26764)}, { AOM_CDF4(4660, 12913, 19502)},
+ { AOM_CDF4(2368, 6930, 12504)}, { AOM_CDF4(26960, 32158, 32613)},
+ { AOM_CDF4(18628, 30005, 32031)}, { AOM_CDF4(10233, 22442, 28232)},
+ { AOM_CDF4(5471, 14630, 21516)}, { AOM_CDF4(3235, 10767, 17109)},
+ { AOM_CDF4(27696, 32440, 32692)}, { AOM_CDF4(20032, 31167, 32438)},
+ { AOM_CDF4(8700, 21341, 28442)}, { AOM_CDF4(5662, 14831, 21795)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(9704, 17294, 21132)}, { AOM_CDF4(26762, 32278, 32633)},
+ { AOM_CDF4(18382, 29620, 31819)}, { AOM_CDF4(10891, 23475, 28723)},
+ { AOM_CDF4(6358, 16583, 23309)}, { AOM_CDF4(3248, 9118, 14141)},
+ { AOM_CDF4(27204, 32573, 32699)}, { AOM_CDF4(19818, 30824, 32329)},
+ { AOM_CDF4(11772, 25120, 30041)}, { AOM_CDF4(6995, 18033, 25039)},
+ { AOM_CDF4(3752, 10442, 16098)}, { AOM_CDF4(27222, 32256, 32559)},
+ { AOM_CDF4(15356, 28399, 31475)}, { AOM_CDF4(8821, 20635, 27057)},
+ { AOM_CDF4(5511, 14404, 21239)}, { AOM_CDF4(2935, 8222, 13051)},
+ { AOM_CDF4(24875, 32120, 32529)}, { AOM_CDF4(15233, 28265, 31445)},
+ { AOM_CDF4(8605, 20570, 26932)}, { AOM_CDF4(5431, 14413, 21196)},
+ { AOM_CDF4(2994, 8341, 13223)}, { AOM_CDF4(28201, 32604, 32700)},
+ { AOM_CDF4(21041, 31446, 32456)}, { AOM_CDF4(13221, 26213, 30475)},
+ { AOM_CDF4(8255, 19385, 26037)}, { AOM_CDF4(4930, 12585, 18830)},
+ { AOM_CDF4(28768, 32448, 32627)}, { AOM_CDF4(19705, 30561, 32021)},
+ { AOM_CDF4(11572, 23589, 28220)}, { AOM_CDF4(5532, 15034, 21446)},
+ { AOM_CDF4(2460, 7150, 11456)}, { AOM_CDF4(29874, 32619, 32699)},
+ { AOM_CDF4(21621, 31071, 32201)}, { AOM_CDF4(12511, 24747, 28992)},
+ { AOM_CDF4(6281, 16395, 22748)}, { AOM_CDF4(3246, 9278, 14497)},
+ { AOM_CDF4(29715, 32625, 32712)}, { AOM_CDF4(20958, 31011, 32283)},
+ { AOM_CDF4(11233, 23671, 28806)}, { AOM_CDF4(6012, 16128, 22868)},
+ { AOM_CDF4(3427, 9851, 15414)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(11016, 22111, 26794)}, { AOM_CDF4(25946, 32357, 32677)},
+ { AOM_CDF4(17890, 30452, 32252)}, { AOM_CDF4(11678, 25142, 29816)},
+ { AOM_CDF4(6720, 17534, 24584)}, { AOM_CDF4(4230, 11665, 17820)},
+ { AOM_CDF4(28400, 32623, 32747)}, { AOM_CDF4(21164, 31668, 32575)},
+ { AOM_CDF4(13572, 27388, 31182)}, { AOM_CDF4(8234, 20750, 27358)},
+ { AOM_CDF4(5065, 14055, 20897)}, { AOM_CDF4(28981, 32547, 32705)},
+ { AOM_CDF4(18681, 30543, 32239)}, { AOM_CDF4(10919, 24075, 29286)},
+ { AOM_CDF4(6431, 17199, 24077)}, { AOM_CDF4(3819, 10464, 16618)},
+ { AOM_CDF4(26870, 32467, 32693)}, { AOM_CDF4(19041, 30831, 32347)},
+ { AOM_CDF4(11794, 25211, 30016)}, { AOM_CDF4(6888, 18019, 24970)},
+ { AOM_CDF4(4370, 12363, 18992)}, { AOM_CDF4(29578, 32670, 32744)},
+ { AOM_CDF4(23159, 32007, 32613)}, { AOM_CDF4(15315, 28669, 31676)},
+ { AOM_CDF4(9298, 22607, 28782)}, { AOM_CDF4(6144, 15913, 22968)},
+ { AOM_CDF4(28110, 32499, 32669)}, { AOM_CDF4(21574, 30937, 32015)},
+ { AOM_CDF4(12759, 24818, 28727)}, { AOM_CDF4(6545, 16761, 23042)},
+ { AOM_CDF4(3649, 10597, 16833)}, { AOM_CDF4(28163, 32552, 32728)},
+ { AOM_CDF4(22101, 31469, 32464)}, { AOM_CDF4(13160, 25472, 30143)},
+ { AOM_CDF4(7303, 18684, 25468)}, { AOM_CDF4(5241, 13975, 20955)},
+ { AOM_CDF4(28400, 32631, 32744)}, { AOM_CDF4(22104, 31793, 32603)},
+ { AOM_CDF4(13557, 26571, 30846)}, { AOM_CDF4(7749, 19861, 26675)},
+ { AOM_CDF4(4873, 14030, 21234)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(9800, 17635, 21073)}, { AOM_CDF4(26153, 31885, 32527)},
+ { AOM_CDF4(15038, 27852, 31006)}, { AOM_CDF4(8718, 20564, 26486)},
+ { AOM_CDF4(5128, 14076, 20514)}, { AOM_CDF4(2636, 7566, 11925)},
+ { AOM_CDF4(27551, 32504, 32701)}, { AOM_CDF4(18310, 30054, 32100)},
+ { AOM_CDF4(10211, 23420, 29082)}, { AOM_CDF4(6222, 16876, 23916)},
+ { AOM_CDF4(3462, 9954, 15498)}, { AOM_CDF4(29991, 32633, 32721)},
+ { AOM_CDF4(19883, 30751, 32201)}, { AOM_CDF4(11141, 24184, 29285)},
+ { AOM_CDF4(6420, 16940, 23774)}, { AOM_CDF4(3392, 9753, 15118)},
+ { AOM_CDF4(28465, 32616, 32712)}, { AOM_CDF4(19850, 30702, 32244)},
+ { AOM_CDF4(10983, 24024, 29223)}, { AOM_CDF4(6294, 16770, 23582)},
+ { AOM_CDF4(3244, 9283, 14509)}, { AOM_CDF4(30023, 32717, 32748)},
+ { AOM_CDF4(22940, 32032, 32626)}, { AOM_CDF4(14282, 27928, 31473)},
+ { AOM_CDF4(8562, 21327, 27914)}, { AOM_CDF4(4846, 13393, 19919)},
+ { AOM_CDF4(29981, 32590, 32695)}, { AOM_CDF4(20465, 30963, 32166)},
+ { AOM_CDF4(11479, 23579, 28195)}, { AOM_CDF4(5916, 15648, 22073)},
+ { AOM_CDF4(3031, 8605, 13398)}, { AOM_CDF4(31146, 32691, 32739)},
+ { AOM_CDF4(23106, 31724, 32444)}, { AOM_CDF4(13783, 26738, 30439)},
+ { AOM_CDF4(7852, 19468, 25807)}, { AOM_CDF4(3860, 11124, 16853)},
+ { AOM_CDF4(31014, 32724, 32748)}, { AOM_CDF4(23629, 32109, 32628)},
+ { AOM_CDF4(14747, 28115, 31403)}, { AOM_CDF4(8545, 21242, 27478)},
+ { AOM_CDF4(4574, 12781, 19067)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(9185, 19694, 24688)}, { AOM_CDF4(26081, 31985, 32621)},
+ { AOM_CDF4(16015, 29000, 31787)}, { AOM_CDF4(10542, 23690, 29206)},
+ { AOM_CDF4(6732, 17945, 24677)}, { AOM_CDF4(3916, 11039, 16722)},
+ { AOM_CDF4(28224, 32566, 32744)}, { AOM_CDF4(19100, 31138, 32485)},
+ { AOM_CDF4(12528, 26620, 30879)}, { AOM_CDF4(7741, 20277, 26885)},
+ { AOM_CDF4(4566, 12845, 18990)}, { AOM_CDF4(29933, 32593, 32718)},
+ { AOM_CDF4(17670, 30333, 32155)}, { AOM_CDF4(10385, 23600, 28909)},
+ { AOM_CDF4(6243, 16236, 22407)}, { AOM_CDF4(3976, 10389, 16017)},
+ { AOM_CDF4(28377, 32561, 32738)}, { AOM_CDF4(19366, 31175, 32482)},
+ { AOM_CDF4(13327, 27175, 31094)}, { AOM_CDF4(8258, 20769, 27143)},
+ { AOM_CDF4(4703, 13198, 19527)}, { AOM_CDF4(31086, 32706, 32748)},
+ { AOM_CDF4(22853, 31902, 32583)}, { AOM_CDF4(14759, 28186, 31419)},
+ { AOM_CDF4(9284, 22382, 28348)}, { AOM_CDF4(5585, 15192, 21868)},
+ { AOM_CDF4(28291, 32652, 32746)}, { AOM_CDF4(19849, 32107, 32571)},
+ { AOM_CDF4(14834, 26818, 29214)}, { AOM_CDF4(10306, 22594, 28672)},
+ { AOM_CDF4(6615, 17384, 23384)}, { AOM_CDF4(28947, 32604, 32745)},
+ { AOM_CDF4(25625, 32289, 32646)}, { AOM_CDF4(18758, 28672, 31403)},
+ { AOM_CDF4(10017, 23430, 28523)}, { AOM_CDF4(6862, 15269, 22131)},
+ { AOM_CDF4(23933, 32509, 32739)}, { AOM_CDF4(19927, 31495, 32631)},
+ { AOM_CDF4(11903, 26023, 30621)}, { AOM_CDF4(7026, 20094, 27252)},
+ { AOM_CDF4(5998, 18106, 24437)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(4456, 11274, 15533)}, { AOM_CDF4(21219, 29079, 31616)},
+ { AOM_CDF4(11173, 23774, 28567)}, { AOM_CDF4(7282, 18293, 24263)},
+ { AOM_CDF4(4890, 13286, 19115)}, { AOM_CDF4(1890, 5508, 8659)},
+ { AOM_CDF4(26651, 32136, 32647)}, { AOM_CDF4(14630, 28254, 31455)},
+ { AOM_CDF4(8716, 21287, 27395)}, { AOM_CDF4(5615, 15331, 22008)},
+ { AOM_CDF4(2675, 7700, 12150)}, { AOM_CDF4(29954, 32526, 32690)},
+ { AOM_CDF4(16126, 28982, 31633)}, { AOM_CDF4(9030, 21361, 27352)},
+ { AOM_CDF4(5411, 14793, 21271)}, { AOM_CDF4(2943, 8422, 13163)},
+ { AOM_CDF4(29539, 32601, 32730)}, { AOM_CDF4(18125, 30385, 32201)},
+ { AOM_CDF4(10422, 24090, 29468)}, { AOM_CDF4(6468, 17487, 24438)},
+ { AOM_CDF4(2970, 8653, 13531)}, { AOM_CDF4(30912, 32715, 32748)},
+ { AOM_CDF4(20666, 31373, 32497)}, { AOM_CDF4(12509, 26640, 30917)},
+ { AOM_CDF4(8058, 20629, 27290)}, { AOM_CDF4(4231, 12006, 18052)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(10202, 20633, 25484)}, { AOM_CDF4(27336, 31445, 32352)},
+ { AOM_CDF4(12420, 24384, 28552)}, { AOM_CDF4(7648, 18115, 23856)},
+ { AOM_CDF4(5662, 14341, 19902)}, { AOM_CDF4(3611, 10328, 15390)},
+ { AOM_CDF4(30945, 32616, 32736)}, { AOM_CDF4(18682, 30505, 32253)},
+ { AOM_CDF4(11513, 25336, 30203)}, { AOM_CDF4(7449, 19452, 26148)},
+ { AOM_CDF4(4482, 13051, 18886)}, { AOM_CDF4(32022, 32690, 32747)},
+ { AOM_CDF4(18578, 30501, 32146)}, { AOM_CDF4(11249, 23368, 28631)},
+ { AOM_CDF4(5645, 16958, 22158)}, { AOM_CDF4(5009, 11444, 16637)},
+ { AOM_CDF4(31357, 32710, 32748)}, { AOM_CDF4(21552, 31494, 32504)},
+ { AOM_CDF4(13891, 27677, 31340)}, { AOM_CDF4(9051, 22098, 28172)},
+ { AOM_CDF4(5190, 13377, 19486)}, { AOM_CDF4(32364, 32740, 32748)},
+ { AOM_CDF4(24839, 31907, 32551)}, { AOM_CDF4(17160, 28779, 31696)},
+ { AOM_CDF4(12452, 24137, 29602)}, { AOM_CDF4(6165, 15389, 22477)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(2575, 7281, 11077)}, { AOM_CDF4(14002, 20866, 25402)},
+ { AOM_CDF4(6343, 15056, 19658)}, { AOM_CDF4(4474, 11858, 17041)},
+ { AOM_CDF4(2865, 8299, 12534)}, { AOM_CDF4(1344, 3949, 6391)},
+ { AOM_CDF4(24720, 31239, 32459)}, { AOM_CDF4(12585, 25356, 29968)},
+ { AOM_CDF4(7181, 18246, 24444)}, { AOM_CDF4(5025, 13667, 19885)},
+ { AOM_CDF4(2521, 7304, 11605)}, { AOM_CDF4(29908, 32252, 32584)},
+ { AOM_CDF4(17421, 29156, 31575)}, { AOM_CDF4(9889, 22188, 27782)},
+ { AOM_CDF4(5878, 15647, 22123)}, { AOM_CDF4(2814, 8665, 13323)},
+ { AOM_CDF4(30183, 32568, 32713)}, { AOM_CDF4(18528, 30195, 32049)},
+ { AOM_CDF4(10982, 24606, 29657)}, { AOM_CDF4(6957, 18165, 25231)},
+ { AOM_CDF4(3508, 10118, 15468)}, { AOM_CDF4(31761, 32736, 32748)},
+ { AOM_CDF4(21041, 31328, 32546)}, { AOM_CDF4(12568, 26732, 31166)},
+ { AOM_CDF4(8052, 20720, 27733)}, { AOM_CDF4(4336, 12192, 18396)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ }
+ },
+ {
+ {
+ {
+ { AOM_CDF4(7062, 16472, 22319)}, { AOM_CDF4(24538, 32261, 32674)},
+ { AOM_CDF4(13675, 28041, 31779)}, { AOM_CDF4(8590, 20674, 27631)},
+ { AOM_CDF4(5685, 14675, 22013)}, { AOM_CDF4(3655, 9898, 15731)},
+ { AOM_CDF4(26493, 32418, 32658)}, { AOM_CDF4(16376, 29342, 32090)},
+ { AOM_CDF4(10594, 22649, 28970)}, { AOM_CDF4(8176, 17170, 24303)},
+ { AOM_CDF4(5605, 12694, 19139)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(23888, 31902, 32542)},
+ { AOM_CDF4(18612, 29687, 31987)}, { AOM_CDF4(16245, 24852, 29249)},
+ { AOM_CDF4(15765, 22608, 27559)}, { AOM_CDF4(19895, 24699, 27510)},
+ { AOM_CDF4(28401, 32212, 32457)}, { AOM_CDF4(15274, 27825, 30980)},
+ { AOM_CDF4(9364, 18128, 24332)}, { AOM_CDF4(2283, 8193, 15082)},
+ { AOM_CDF4(1228, 3972, 7881)}, { AOM_CDF4(29455, 32469, 32620)},
+ { AOM_CDF4(17981, 28245, 31388)}, { AOM_CDF4(10921, 20098, 26240)},
+ { AOM_CDF4(3743, 11829, 18657)}, { AOM_CDF4(2374, 9593, 15715)},
+ { AOM_CDF4(31068, 32466, 32635)}, { AOM_CDF4(20321, 29572, 31971)},
+ { AOM_CDF4(10771, 20255, 27119)}, { AOM_CDF4(2795, 10410, 17361)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(9320, 22102, 27840)}, { AOM_CDF4(27057, 32464, 32724)},
+ { AOM_CDF4(16331, 30268, 32309)}, { AOM_CDF4(10319, 23935, 29720)},
+ { AOM_CDF4(6189, 16448, 24106)}, { AOM_CDF4(3589, 10884, 18808)},
+ { AOM_CDF4(29026, 32624, 32748)}, { AOM_CDF4(19226, 31507, 32587)},
+ { AOM_CDF4(12692, 26921, 31203)}, { AOM_CDF4(7049, 19532, 27635)},
+ { AOM_CDF4(7727, 15669, 23252)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(28056, 32625, 32748)},
+ { AOM_CDF4(22383, 32075, 32669)}, { AOM_CDF4(15417, 27098, 31749)},
+ { AOM_CDF4(18127, 26493, 27190)}, { AOM_CDF4(5461, 16384, 21845)},
+ { AOM_CDF4(27982, 32091, 32584)}, { AOM_CDF4(19045, 29868, 31972)},
+ { AOM_CDF4(10397, 22266, 27932)}, { AOM_CDF4(5990, 13697, 21500)},
+ { AOM_CDF4(1792, 6912, 15104)}, { AOM_CDF4(28198, 32501, 32718)},
+ { AOM_CDF4(21534, 31521, 32569)}, { AOM_CDF4(11109, 25217, 30017)},
+ { AOM_CDF4(5671, 15124, 26151)}, { AOM_CDF4(4681, 14043, 18725)},
+ { AOM_CDF4(28688, 32580, 32741)}, { AOM_CDF4(22576, 32079, 32661)},
+ { AOM_CDF4(10627, 22141, 28340)}, { AOM_CDF4(9362, 14043, 28087)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(7754, 16948, 22142)}, { AOM_CDF4(25670, 32330, 32691)},
+ { AOM_CDF4(15663, 29225, 31994)}, { AOM_CDF4(9878, 23288, 29158)},
+ { AOM_CDF4(6419, 17088, 24336)}, { AOM_CDF4(3859, 11003, 17039)},
+ { AOM_CDF4(27562, 32595, 32725)}, { AOM_CDF4(17575, 30588, 32399)},
+ { AOM_CDF4(10819, 24838, 30309)}, { AOM_CDF4(7124, 18686, 25916)},
+ { AOM_CDF4(4479, 12688, 19340)}, { AOM_CDF4(28385, 32476, 32673)},
+ { AOM_CDF4(15306, 29005, 31938)}, { AOM_CDF4(8937, 21615, 28322)},
+ { AOM_CDF4(5982, 15603, 22786)}, { AOM_CDF4(3620, 10267, 16136)},
+ { AOM_CDF4(27280, 32464, 32667)}, { AOM_CDF4(15607, 29160, 32004)},
+ { AOM_CDF4(9091, 22135, 28740)}, { AOM_CDF4(6232, 16632, 24020)},
+ { AOM_CDF4(4047, 11377, 17672)}, { AOM_CDF4(29220, 32630, 32718)},
+ { AOM_CDF4(19650, 31220, 32462)}, { AOM_CDF4(13050, 26312, 30827)},
+ { AOM_CDF4(9228, 20870, 27468)}, { AOM_CDF4(6146, 15149, 21971)},
+ { AOM_CDF4(30169, 32481, 32623)}, { AOM_CDF4(17212, 29311, 31554)},
+ { AOM_CDF4(9911, 21311, 26882)}, { AOM_CDF4(4487, 13314, 20372)},
+ { AOM_CDF4(2570, 7772, 12889)}, { AOM_CDF4(30924, 32613, 32708)},
+ { AOM_CDF4(19490, 30206, 32107)}, { AOM_CDF4(11232, 23998, 29276)},
+ { AOM_CDF4(6769, 17955, 25035)}, { AOM_CDF4(4398, 12623, 19214)},
+ { AOM_CDF4(30609, 32627, 32722)}, { AOM_CDF4(19370, 30582, 32287)},
+ { AOM_CDF4(10457, 23619, 29409)}, { AOM_CDF4(6443, 17637, 24834)},
+ { AOM_CDF4(4645, 13236, 20106)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(8626, 20271, 26216)}, { AOM_CDF4(26707, 32406, 32711)},
+ { AOM_CDF4(16999, 30329, 32286)}, { AOM_CDF4(11445, 25123, 30286)},
+ { AOM_CDF4(6411, 18828, 25601)}, { AOM_CDF4(6801, 12458, 20248)},
+ { AOM_CDF4(29918, 32682, 32748)}, { AOM_CDF4(20649, 31739, 32618)},
+ { AOM_CDF4(12879, 27773, 31581)}, { AOM_CDF4(7896, 21751, 28244)},
+ { AOM_CDF4(5260, 14870, 23698)}, { AOM_CDF4(29252, 32593, 32731)},
+ { AOM_CDF4(17072, 30460, 32294)}, { AOM_CDF4(10653, 24143, 29365)},
+ { AOM_CDF4(6536, 17490, 23983)}, { AOM_CDF4(4929, 13170, 20085)},
+ { AOM_CDF4(28137, 32518, 32715)}, { AOM_CDF4(18171, 30784, 32407)},
+ { AOM_CDF4(11437, 25436, 30459)}, { AOM_CDF4(7252, 18534, 26176)},
+ { AOM_CDF4(4126, 13353, 20978)}, { AOM_CDF4(31162, 32726, 32748)},
+ { AOM_CDF4(23017, 32222, 32701)}, { AOM_CDF4(15629, 29233, 32046)},
+ { AOM_CDF4(9387, 22621, 29480)}, { AOM_CDF4(6922, 17616, 25010)},
+ { AOM_CDF4(28838, 32265, 32614)}, { AOM_CDF4(19701, 30206, 31920)},
+ { AOM_CDF4(11214, 22410, 27933)}, { AOM_CDF4(5320, 14177, 23034)},
+ { AOM_CDF4(5049, 12881, 17827)}, { AOM_CDF4(27484, 32471, 32734)},
+ { AOM_CDF4(21076, 31526, 32561)}, { AOM_CDF4(12707, 26303, 31211)},
+ { AOM_CDF4(8169, 21722, 28219)}, { AOM_CDF4(6045, 19406, 27042)},
+ { AOM_CDF4(27753, 32572, 32745)}, { AOM_CDF4(20832, 31878, 32653)},
+ { AOM_CDF4(13250, 27356, 31674)}, { AOM_CDF4(7718, 21508, 29858)},
+ { AOM_CDF4(7209, 18350, 25559)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(7876, 16901, 21741)}, { AOM_CDF4(24001, 31898, 32625)},
+ { AOM_CDF4(14529, 27959, 31451)}, { AOM_CDF4(8273, 20818, 27258)},
+ { AOM_CDF4(5278, 14673, 21510)}, { AOM_CDF4(2983, 8843, 14039)},
+ { AOM_CDF4(28016, 32574, 32732)}, { AOM_CDF4(17471, 30306, 32301)},
+ { AOM_CDF4(10224, 24063, 29728)}, { AOM_CDF4(6602, 17954, 25052)},
+ { AOM_CDF4(4002, 11585, 17759)}, { AOM_CDF4(30190, 32634, 32739)},
+ { AOM_CDF4(17497, 30282, 32270)}, { AOM_CDF4(10229, 23729, 29538)},
+ { AOM_CDF4(6344, 17211, 24440)}, { AOM_CDF4(3849, 11189, 17108)},
+ { AOM_CDF4(28570, 32583, 32726)}, { AOM_CDF4(17521, 30161, 32238)},
+ { AOM_CDF4(10153, 23565, 29378)}, { AOM_CDF4(6455, 17341, 24443)},
+ { AOM_CDF4(3907, 11042, 17024)}, { AOM_CDF4(30689, 32715, 32748)},
+ { AOM_CDF4(21546, 31840, 32610)}, { AOM_CDF4(13547, 27581, 31459)},
+ { AOM_CDF4(8912, 21757, 28309)}, { AOM_CDF4(5548, 15080, 22046)},
+ { AOM_CDF4(30783, 32540, 32685)}, { AOM_CDF4(17540, 29528, 31668)},
+ { AOM_CDF4(10160, 21468, 26783)}, { AOM_CDF4(4724, 13393, 20054)},
+ { AOM_CDF4(2702, 8174, 13102)}, { AOM_CDF4(31648, 32686, 32742)},
+ { AOM_CDF4(20954, 31094, 32337)}, { AOM_CDF4(12420, 25698, 30179)},
+ { AOM_CDF4(7304, 19320, 26248)}, { AOM_CDF4(4366, 12261, 18864)},
+ { AOM_CDF4(31581, 32723, 32748)}, { AOM_CDF4(21373, 31586, 32525)},
+ { AOM_CDF4(12744, 26625, 30885)}, { AOM_CDF4(7431, 20322, 26950)},
+ { AOM_CDF4(4692, 13323, 20111)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(7833, 18369, 24095)}, { AOM_CDF4(26650, 32273, 32702)},
+ { AOM_CDF4(16371, 29961, 32191)}, { AOM_CDF4(11055, 24082, 29629)},
+ { AOM_CDF4(6892, 18644, 25400)}, { AOM_CDF4(5006, 13057, 19240)},
+ { AOM_CDF4(29834, 32666, 32748)}, { AOM_CDF4(19577, 31335, 32570)},
+ { AOM_CDF4(12253, 26509, 31122)}, { AOM_CDF4(7991, 20772, 27711)},
+ { AOM_CDF4(5677, 15910, 23059)}, { AOM_CDF4(30109, 32532, 32720)},
+ { AOM_CDF4(16747, 30166, 32252)}, { AOM_CDF4(10134, 23542, 29184)},
+ { AOM_CDF4(5791, 16176, 23556)}, { AOM_CDF4(4362, 10414, 17284)},
+ { AOM_CDF4(29492, 32626, 32748)}, { AOM_CDF4(19894, 31402, 32525)},
+ { AOM_CDF4(12942, 27071, 30869)}, { AOM_CDF4(8346, 21216, 27405)},
+ { AOM_CDF4(6572, 17087, 23859)}, { AOM_CDF4(32035, 32735, 32748)},
+ { AOM_CDF4(22957, 31838, 32618)}, { AOM_CDF4(14724, 28572, 31772)},
+ { AOM_CDF4(10364, 23999, 29553)}, { AOM_CDF4(7004, 18433, 25655)},
+ { AOM_CDF4(27528, 32277, 32681)}, { AOM_CDF4(16959, 31171, 32096)},
+ { AOM_CDF4(10486, 23593, 27962)}, { AOM_CDF4(8192, 16384, 23211)},
+ { AOM_CDF4(8937, 17873, 20852)}, { AOM_CDF4(27715, 32002, 32615)},
+ { AOM_CDF4(15073, 29491, 31676)}, { AOM_CDF4(11264, 24576, 28672)},
+ { AOM_CDF4(2341, 18725, 23406)}, { AOM_CDF4(7282, 18204, 25486)},
+ { AOM_CDF4(28547, 32213, 32657)}, { AOM_CDF4(20788, 29773, 32239)},
+ { AOM_CDF4(6780, 21469, 30508)}, { AOM_CDF4(5958, 14895, 23831)},
+ { AOM_CDF4(16384, 21845, 27307)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(5992, 14304, 19765)}, { AOM_CDF4(22612, 31238, 32456)},
+ { AOM_CDF4(13456, 27162, 31087)}, { AOM_CDF4(8001, 20062, 26504)},
+ { AOM_CDF4(5168, 14105, 20764)}, { AOM_CDF4(2632, 7771, 12385)},
+ { AOM_CDF4(27034, 32344, 32709)}, { AOM_CDF4(15850, 29415, 31997)},
+ { AOM_CDF4(9494, 22776, 28841)}, { AOM_CDF4(6151, 16830, 23969)},
+ { AOM_CDF4(3461, 10039, 15722)}, { AOM_CDF4(30134, 32569, 32731)},
+ { AOM_CDF4(15638, 29422, 31945)}, { AOM_CDF4(9150, 21865, 28218)},
+ { AOM_CDF4(5647, 15719, 22676)}, { AOM_CDF4(3402, 9772, 15477)},
+ { AOM_CDF4(28530, 32586, 32735)}, { AOM_CDF4(17139, 30298, 32292)},
+ { AOM_CDF4(10200, 24039, 29685)}, { AOM_CDF4(6419, 17674, 24786)},
+ { AOM_CDF4(3544, 10225, 15824)}, { AOM_CDF4(31333, 32726, 32748)},
+ { AOM_CDF4(20618, 31487, 32544)}, { AOM_CDF4(12901, 27217, 31232)},
+ { AOM_CDF4(8624, 21734, 28171)}, { AOM_CDF4(5104, 14191, 20748)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(11206, 21090, 26561)}, { AOM_CDF4(28759, 32279, 32671)},
+ { AOM_CDF4(14171, 27952, 31569)}, { AOM_CDF4(9743, 22907, 29141)},
+ { AOM_CDF4(6871, 17886, 24868)}, { AOM_CDF4(4960, 13152, 19315)},
+ { AOM_CDF4(31077, 32661, 32748)}, { AOM_CDF4(19400, 31195, 32515)},
+ { AOM_CDF4(12752, 26858, 31040)}, { AOM_CDF4(8370, 22098, 28591)},
+ { AOM_CDF4(5457, 15373, 22298)}, { AOM_CDF4(31697, 32706, 32748)},
+ { AOM_CDF4(17860, 30657, 32333)}, { AOM_CDF4(12510, 24812, 29261)},
+ { AOM_CDF4(6180, 19124, 24722)}, { AOM_CDF4(5041, 13548, 17959)},
+ { AOM_CDF4(31552, 32716, 32748)}, { AOM_CDF4(21908, 31769, 32623)},
+ { AOM_CDF4(14470, 28201, 31565)}, { AOM_CDF4(9493, 22982, 28608)},
+ { AOM_CDF4(6858, 17240, 24137)}, { AOM_CDF4(32543, 32752, 32756)},
+ { AOM_CDF4(24286, 32097, 32666)}, { AOM_CDF4(15958, 29217, 32024)},
+ { AOM_CDF4(10207, 24234, 29958)}, { AOM_CDF4(6929, 18305, 25652)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ },
+ {
+ {
+ { AOM_CDF4(4137, 10847, 15682)}, { AOM_CDF4(17824, 27001, 30058)},
+ { AOM_CDF4(10204, 22796, 28291)}, { AOM_CDF4(6076, 15935, 22125)},
+ { AOM_CDF4(3852, 10937, 16816)}, { AOM_CDF4(2252, 6324, 10131)},
+ { AOM_CDF4(25840, 32016, 32662)}, { AOM_CDF4(15109, 28268, 31531)},
+ { AOM_CDF4(9385, 22231, 28340)}, { AOM_CDF4(6082, 16672, 23479)},
+ { AOM_CDF4(3318, 9427, 14681)}, { AOM_CDF4(30594, 32574, 32718)},
+ { AOM_CDF4(16836, 29552, 31859)}, { AOM_CDF4(9556, 22542, 28356)},
+ { AOM_CDF4(6305, 16725, 23540)}, { AOM_CDF4(3376, 9895, 15184)},
+ { AOM_CDF4(29383, 32617, 32745)}, { AOM_CDF4(18891, 30809, 32401)},
+ { AOM_CDF4(11688, 25942, 30687)}, { AOM_CDF4(7468, 19469, 26651)},
+ { AOM_CDF4(3909, 11358, 17012)}, { AOM_CDF4(31564, 32736, 32748)},
+ { AOM_CDF4(20906, 31611, 32600)}, { AOM_CDF4(13191, 27621, 31537)},
+ { AOM_CDF4(8768, 22029, 28676)}, { AOM_CDF4(5079, 14109, 20906)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ },
+ {
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)},
+ { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}
+ }
+ }
+ }
+};
+
+static const u16 av1_default_coeff_base_eob_multi_cdfs[TOKEN_CDF_Q_CTXS][TX_SIZES]
+ [PLANE_TYPES][SIG_COEF_CONTEXTS_EOB][CDF_SIZE(NUM_BASE_LEVELS + 1)] = {
+ {
+ {
+ {
+ { AOM_CDF3(17837, 29055)},
+ { AOM_CDF3(29600, 31446)},
+ { AOM_CDF3(30844, 31878)},
+ { AOM_CDF3(24926, 28948)}
+ },
+ {
+ { AOM_CDF3(21365, 30026)},
+ { AOM_CDF3(30512, 32423)},
+ { AOM_CDF3(31658, 32621)},
+ { AOM_CDF3(29630, 31881)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(5717, 26477)},
+ { AOM_CDF3(30491, 31703)},
+ { AOM_CDF3(31550, 32158)},
+ { AOM_CDF3(29648, 31491)}
+ },
+ {
+ { AOM_CDF3(12608, 27820)},
+ { AOM_CDF3(30680, 32225)},
+ { AOM_CDF3(30809, 32335)},
+ { AOM_CDF3(31299, 32423)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(1786, 12612)},
+ { AOM_CDF3(30663, 31625)},
+ { AOM_CDF3(32339, 32468)},
+ { AOM_CDF3(31148, 31833)}
+ },
+ {
+ { AOM_CDF3(18857, 23865)},
+ { AOM_CDF3(31428, 32428)},
+ { AOM_CDF3(31744, 32373)},
+ { AOM_CDF3(31775, 32526)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(1787, 2532)},
+ { AOM_CDF3(30832, 31662)},
+ { AOM_CDF3(31824, 32682)},
+ { AOM_CDF3(32133, 32569)}
+ },
+ {
+ { AOM_CDF3(13751, 22235)},
+ { AOM_CDF3(32089, 32409)},
+ { AOM_CDF3(27084, 27920)},
+ { AOM_CDF3(29291, 32594)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(1725, 3449)},
+ { AOM_CDF3(31102, 31935)},
+ { AOM_CDF3(32457, 32613)},
+ { AOM_CDF3(32412, 32649)}
+ },
+ {
+ { AOM_CDF3(10923, 21845)},
+ { AOM_CDF3(10923, 21845)},
+ { AOM_CDF3(10923, 21845)},
+ { AOM_CDF3(10923, 21845)}
+ }
+ }
+ },
+ {
+ {
+ {
+ { AOM_CDF3(17560, 29888)},
+ { AOM_CDF3(29671, 31549)},
+ { AOM_CDF3(31007, 32056)},
+ { AOM_CDF3(27286, 30006)}
+ },
+ {
+ { AOM_CDF3(26594, 31212)},
+ { AOM_CDF3(31208, 32582)},
+ { AOM_CDF3(31835, 32637)},
+ { AOM_CDF3(30595, 32206)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(15239, 29932)},
+ { AOM_CDF3(31315, 32095)},
+ { AOM_CDF3(32130, 32434)},
+ { AOM_CDF3(30864, 31996)}
+ },
+ {
+ { AOM_CDF3(26279, 30968)},
+ { AOM_CDF3(31142, 32495)},
+ { AOM_CDF3(31713, 32540)},
+ { AOM_CDF3(31929, 32594)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(2644, 25198)},
+ { AOM_CDF3(32038, 32451)},
+ { AOM_CDF3(32639, 32695)},
+ { AOM_CDF3(32166, 32518)}
+ },
+ {
+ { AOM_CDF3(17187, 27668)},
+ { AOM_CDF3(31714, 32550)},
+ { AOM_CDF3(32283, 32678)},
+ { AOM_CDF3(31930, 32563)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(1044, 2257)},
+ { AOM_CDF3(30755, 31923)},
+ { AOM_CDF3(32208, 32693)},
+ { AOM_CDF3(32244, 32615)}
+ },
+ {
+ { AOM_CDF3(21317, 26207)},
+ { AOM_CDF3(29133, 30868)},
+ { AOM_CDF3(29311, 31231)},
+ { AOM_CDF3(29657, 31087)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(478, 1834)},
+ { AOM_CDF3(31005, 31987)},
+ { AOM_CDF3(32317, 32724)},
+ { AOM_CDF3(30865, 32648)}
+ },
+ {
+ { AOM_CDF3(10923, 21845)},
+ { AOM_CDF3(10923, 21845)},
+ { AOM_CDF3(10923, 21845)},
+ { AOM_CDF3(10923, 21845)}
+ }
+ }
+ },
+ {
+ {
+ {
+ { AOM_CDF3(20092, 30774)},
+ { AOM_CDF3(30695, 32020)},
+ { AOM_CDF3(31131, 32103)},
+ { AOM_CDF3(28666, 30870)}
+ },
+ {
+ { AOM_CDF3(27258, 31095)},
+ { AOM_CDF3(31804, 32623)},
+ { AOM_CDF3(31763, 32528)},
+ { AOM_CDF3(31438, 32506)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(18049, 30489)},
+ { AOM_CDF3(31706, 32286)},
+ { AOM_CDF3(32163, 32473)},
+ { AOM_CDF3(31550, 32184)}
+ },
+ {
+ { AOM_CDF3(27116, 30842)},
+ { AOM_CDF3(31971, 32598)},
+ { AOM_CDF3(32088, 32576)},
+ { AOM_CDF3(32067, 32664)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(12854, 29093)},
+ { AOM_CDF3(32272, 32558)},
+ { AOM_CDF3(32667, 32729)},
+ { AOM_CDF3(32306, 32585)}
+ },
+ {
+ { AOM_CDF3(25476, 30366)},
+ { AOM_CDF3(32169, 32687)},
+ { AOM_CDF3(32479, 32689)},
+ { AOM_CDF3(31673, 32634)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(2809, 19301)},
+ { AOM_CDF3(32205, 32622)},
+ { AOM_CDF3(32338, 32730)},
+ { AOM_CDF3(31786, 32616)}
+ },
+ {
+ { AOM_CDF3(22737, 29105)},
+ { AOM_CDF3(30810, 32362)},
+ { AOM_CDF3(30014, 32627)},
+ { AOM_CDF3(30528, 32574)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(935, 3382)},
+ { AOM_CDF3(30789, 31909)},
+ { AOM_CDF3(32466, 32756)},
+ { AOM_CDF3(30860, 32513)}
+ },
+ {
+ { AOM_CDF3(10923, 21845)},
+ { AOM_CDF3(10923, 21845)},
+ { AOM_CDF3(10923, 21845)},
+ { AOM_CDF3(10923, 21845)}
+ }
+ }
+ },
+ {
+ {
+ {
+ { AOM_CDF3(22497, 31198)},
+ { AOM_CDF3(31715, 32495)},
+ { AOM_CDF3(31606, 32337)},
+ { AOM_CDF3(30388, 31990)}
+ },
+ {
+ { AOM_CDF3(27877, 31584)},
+ { AOM_CDF3(32170, 32728)},
+ { AOM_CDF3(32155, 32688)},
+ { AOM_CDF3(32219, 32702)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(21457, 31043)},
+ { AOM_CDF3(31951, 32483)},
+ { AOM_CDF3(32153, 32562)},
+ { AOM_CDF3(31473, 32215)}
+ },
+ {
+ { AOM_CDF3(27558, 31151)},
+ { AOM_CDF3(32020, 32640)},
+ { AOM_CDF3(32097, 32575)},
+ { AOM_CDF3(32242, 32719)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(19980, 30591)},
+ { AOM_CDF3(32219, 32597)},
+ { AOM_CDF3(32581, 32706)},
+ { AOM_CDF3(31803, 32287)}
+ },
+ {
+ { AOM_CDF3(26473, 30507)},
+ { AOM_CDF3(32431, 32723)},
+ { AOM_CDF3(32196, 32611)},
+ { AOM_CDF3(31588, 32528)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(24647, 30463)},
+ { AOM_CDF3(32412, 32695)},
+ { AOM_CDF3(32468, 32720)},
+ { AOM_CDF3(31269, 32523)}
+ },
+ {
+ { AOM_CDF3(28482, 31505)},
+ { AOM_CDF3(32152, 32701)},
+ { AOM_CDF3(31732, 32598)},
+ { AOM_CDF3(31767, 32712)}
+ }
+ },
+ {
+ {
+ { AOM_CDF3(12358, 24977)},
+ { AOM_CDF3(31331, 32385)},
+ { AOM_CDF3(32634, 32756)},
+ { AOM_CDF3(30411, 32548)}
+ },
+ {
+ { AOM_CDF3(10923, 21845)},
+ { AOM_CDF3(10923, 21845)},
+ { AOM_CDF3(10923, 21845)},
+ { AOM_CDF3(10923, 21845)}
+ }
+ }
+ }
+};
+
+static const u16 default_joint_cdf[] = { ICDF(4096), ICDF(11264), ICDF(19328)};
+static const u16 default_clsss_cdf[][10] = {
+ // Vertical component
+ {
+ ICDF(28672), ICDF(30976), ICDF(31858), ICDF(32320), ICDF(32551),
+ ICDF(32656), ICDF(32740), ICDF(32757), ICDF(32762), ICDF(32767)
+ },
+ // Horizontal component
+ {
+ ICDF(28672), ICDF(30976), ICDF(31858), ICDF(32320), ICDF(32551),
+ ICDF(32656), ICDF(32740), ICDF(32757), ICDF(32762), ICDF(32767)
+ }
+};
+
+static const u16 default_clsss0_fp_cdf[][2][3] = {
+ // Vertical component
+ {
+ { ICDF(16384), ICDF(24576), ICDF(26624)},
+ { ICDF(12288), ICDF(21248), ICDF(24128)}
+ },
+ // Horizontal component
+ {
+ { ICDF(16384), ICDF(24576), ICDF(26624)},
+ { ICDF(12288), ICDF(21248), ICDF(24128)}
+ }
+};
+
+static const u16 default_fp_cdf[][3] = {
+ // Vertical component
+ {
+ ICDF(8192), ICDF(17408), ICDF(21248)
+ },
+ // Horizontal component
+ {
+ ICDF(8192), ICDF(17408), ICDF(21248)
+ }
+};
+
+static const u16 default_sign_cdf[] = { ICDF(128 * 128), ICDF(128 * 128)};
+static const u16 default_class0_hp_cdf[] = { ICDF(160 * 128), ICDF(160 * 128)};
+static const u16 default_hp_cdf[] = { ICDF(128 * 128), ICDF(128 * 128)};
+static const u16 default_class0_cdf[] = { ICDF(216 * 128), ICDF(216 * 128)};
+static const u16 default_bits_cdf[][10] = {
+ {
+ ICDF(128 * 136), ICDF(128 * 140), ICDF(128 * 148), ICDF(128 * 160),
+ ICDF(128 * 176), ICDF(128 * 192), ICDF(128 * 224), ICDF(128 * 234),
+ ICDF(128 * 234), ICDF(128 * 240)
+ },
+ {
+ ICDF(128 * 136), ICDF(128 * 140), ICDF(128 * 148), ICDF(128 * 160),
+ ICDF(128 * 176), ICDF(128 * 192), ICDF(128 * 224), ICDF(128 * 234),
+ ICDF(128 * 234), ICDF(128 * 240)
+ }
+};
+
+static int rockchip_av1_get_q_ctx(int q)
+{
+ if (q <= 20)
+ return 0;
+ if (q <= 60)
+ return 1;
+ if (q <= 120)
+ return 2;
+ return 3;
+}
+
+void rockchip_av1_default_coeff_probs(u32 base_qindex, void *ptr)
+{
+ struct av1cdfs *cdfs = (struct av1cdfs *)ptr;
+ const int index = rockchip_av1_get_q_ctx(base_qindex);
+
+ memcpy(cdfs->txb_skip_cdf, av1_default_txb_skip_cdfs[index],
+ sizeof(av1_default_txb_skip_cdfs[0]));
+ memcpy(cdfs->eob_extra_cdf, av1_default_eob_extra_cdfs[index],
+ sizeof(av1_default_eob_extra_cdfs[0]));
+ memcpy(cdfs->dc_sign_cdf, av1_default_dc_sign_cdfs[index],
+ sizeof(av1_default_dc_sign_cdfs[0]));
+ memcpy(cdfs->coeff_br_cdf, av1_default_coeff_lps_multi_cdfs[index],
+ sizeof(av1_default_coeff_lps_multi_cdfs[0]));
+ memcpy(cdfs->coeff_base_cdf, av1_default_coeff_base_multi_cdfs[index],
+ sizeof(av1_default_coeff_base_multi_cdfs[0]));
+ memcpy(cdfs->coeff_base_eob_cdf,
+ av1_default_coeff_base_eob_multi_cdfs[index],
+ sizeof(av1_default_coeff_base_eob_multi_cdfs[0]));
+ memcpy(cdfs->eob_flag_cdf16, av1_default_eob_multi16_cdfs[index],
+ sizeof(av1_default_eob_multi16_cdfs[0]));
+ memcpy(cdfs->eob_flag_cdf32, av1_default_eob_multi32_cdfs[index],
+ sizeof(av1_default_eob_multi32_cdfs[0]));
+ memcpy(cdfs->eob_flag_cdf64, av1_default_eob_multi64_cdfs[index],
+ sizeof(av1_default_eob_multi64_cdfs[0]));
+ memcpy(cdfs->eob_flag_cdf128, av1_default_eob_multi128_cdfs[index],
+ sizeof(av1_default_eob_multi128_cdfs[0]));
+ memcpy(cdfs->eob_flag_cdf256, av1_default_eob_multi256_cdfs[index],
+ sizeof(av1_default_eob_multi256_cdfs[0]));
+ memcpy(cdfs->eob_flag_cdf512, av1_default_eob_multi512_cdfs[index],
+ sizeof(av1_default_eob_multi512_cdfs[0]));
+ memcpy(cdfs->eob_flag_cdf1024, av1_default_eob_multi1024_cdfs[index],
+ sizeof(av1_default_eob_multi1024_cdfs[0]));
+}
+
+void rockchip_av1_set_default_cdfs(struct av1cdfs *cdfs,
+ struct mvcdfs *cdfs_ndvc)
+{
+ memcpy(cdfs->partition_cdf, default_partition_cdf,
+ sizeof(cdfs->partition_cdf));
+
+ memcpy(cdfs->tx_type_intra0_cdf, default_intra_ext_tx0_cdf,
+ sizeof(cdfs->tx_type_intra0_cdf));
+ memcpy(cdfs->tx_type_intra1_cdf, default_intra_ext_tx1_cdf,
+ sizeof(cdfs->tx_type_intra1_cdf));
+ memcpy(cdfs->tx_type_inter_cdf, default_inter_ext_tx_cdf,
+ sizeof(cdfs->tx_type_inter_cdf));
+
+ memcpy(cdfs->vartx_part_cdf, default_txfm_partition_cdf,
+ sizeof(cdfs->vartx_part_cdf));
+ memcpy(cdfs->mbskip_cdf, default_skip_cdfs, sizeof(cdfs->mbskip_cdf));
+ memcpy(cdfs->delta_q_cdf, default_delta_q_cdf,
+ sizeof(cdfs->delta_q_cdf));
+ memcpy(cdfs->delta_lf_multi_cdf, default_delta_lf_multi_cdf,
+ sizeof(cdfs->delta_lf_multi_cdf));
+ memcpy(cdfs->delta_lf_cdf, default_delta_lf_cdf,
+ sizeof(cdfs->delta_lf_cdf));
+
+ memcpy(cdfs->segment_pred_cdf, default_segment_pred_cdf,
+ sizeof(cdfs->segment_pred_cdf));
+
+ memcpy(cdfs->spatial_pred_seg_tree_cdf,
+ default_spatial_pred_seg_tree_cdf,
+ sizeof(cdfs->spatial_pred_seg_tree_cdf));
+
+ memcpy(cdfs->skip_mode_cdf, default_skip_mode_cdfs,
+ sizeof(cdfs->skip_mode_cdf));
+
+ memcpy(cdfs->tx_size_cdf, default_tx_size_cdf,
+ sizeof(cdfs->tx_size_cdf));
+
+ memcpy(cdfs->kf_ymode_cdf, default_kf_y_mode_cdf,
+ sizeof(cdfs->kf_ymode_cdf));
+ memcpy(cdfs->uv_mode_cdf, default_uv_mode_cdf,
+ sizeof(cdfs->uv_mode_cdf));
+ memcpy(cdfs->if_ymode_cdf, default_if_y_mode_cdf,
+ sizeof(cdfs->if_ymode_cdf));
+
+ memcpy(cdfs->intra_inter_cdf, default_intra_inter_cdf,
+ sizeof(cdfs->intra_inter_cdf));
+
+ memcpy(cdfs->comp_ref_cdf, default_comp_ref_cdf,
+ sizeof(cdfs->comp_ref_cdf));
+ memcpy(cdfs->comp_bwdref_cdf, default_comp_bwdref_cdf,
+ sizeof(cdfs->comp_bwdref_cdf));
+
+ memcpy(cdfs->comp_inter_cdf, default_comp_inter_cdf,
+ sizeof(cdfs->comp_inter_cdf));
+
+ memcpy(cdfs->single_ref_cdf, default_single_ref_cdf,
+ sizeof(cdfs->single_ref_cdf));
+ memcpy(cdfs->comp_ref_type_cdf, default_comp_ref_type_cdf,
+ sizeof(cdfs->comp_ref_type_cdf));
+ memcpy(cdfs->uni_comp_ref_cdf, default_uni_comp_ref_cdf,
+ sizeof(cdfs->uni_comp_ref_cdf));
+
+ memcpy(cdfs->newmv_cdf, default_newmv_cdf, sizeof(cdfs->newmv_cdf));
+ memcpy(cdfs->zeromv_cdf, default_zeromv_cdf, sizeof(cdfs->zeromv_cdf));
+ memcpy(cdfs->refmv_cdf, default_refmv_cdf, sizeof(cdfs->refmv_cdf));
+ memcpy(cdfs->drl_cdf, default_drl_cdf, sizeof(cdfs->drl_cdf));
+
+ memcpy(cdfs->interp_filter_cdf, default_switchable_interp_cdf,
+ sizeof(cdfs->interp_filter_cdf));
+
+ // Regular MV cdfs
+ memcpy(cdfs->mv_cdf.joint_cdf, default_joint_cdf,
+ sizeof(cdfs->mv_cdf.joint_cdf));
+ memcpy(cdfs->mv_cdf.sign_cdf, default_sign_cdf,
+ sizeof(cdfs->mv_cdf.sign_cdf));
+ memcpy(cdfs->mv_cdf.clsss_cdf, default_clsss_cdf,
+ sizeof(cdfs->mv_cdf.clsss_cdf));
+ memcpy(cdfs->mv_cdf.clsss0_fp_cdf, default_clsss0_fp_cdf,
+ sizeof(cdfs->mv_cdf.clsss0_fp_cdf));
+ memcpy(cdfs->mv_cdf.fp_cdf, default_fp_cdf,
+ sizeof(cdfs->mv_cdf.fp_cdf));
+ memcpy(cdfs->mv_cdf.class0_hp_cdf, default_class0_hp_cdf,
+ sizeof(cdfs->mv_cdf.class0_hp_cdf));
+ memcpy(cdfs->mv_cdf.hp_cdf, default_hp_cdf,
+ sizeof(cdfs->mv_cdf.hp_cdf));
+ memcpy(cdfs->mv_cdf.class0_cdf, default_class0_cdf,
+ sizeof(cdfs->mv_cdf.class0_cdf));
+ memcpy(cdfs->mv_cdf.bits_cdf, default_bits_cdf,
+ sizeof(cdfs->mv_cdf.bits_cdf));
+
+ // Intrabc cdfs
+ memcpy(cdfs_ndvc->joint_cdf, default_joint_cdf,
+ sizeof(cdfs_ndvc->joint_cdf));
+ memcpy(cdfs_ndvc->sign_cdf, default_sign_cdf,
+ sizeof(cdfs_ndvc->sign_cdf));
+ memcpy(cdfs_ndvc->clsss_cdf, default_clsss_cdf,
+ sizeof(cdfs_ndvc->clsss_cdf));
+ memcpy(cdfs_ndvc->clsss0_fp_cdf, default_clsss0_fp_cdf,
+ sizeof(cdfs_ndvc->clsss0_fp_cdf));
+ memcpy(cdfs_ndvc->fp_cdf, default_fp_cdf, sizeof(cdfs_ndvc->fp_cdf));
+ memcpy(cdfs_ndvc->class0_hp_cdf, default_class0_hp_cdf,
+ sizeof(cdfs_ndvc->class0_hp_cdf));
+ memcpy(cdfs_ndvc->hp_cdf, default_hp_cdf, sizeof(cdfs_ndvc->hp_cdf));
+ memcpy(cdfs_ndvc->class0_cdf, default_class0_cdf,
+ sizeof(cdfs_ndvc->class0_cdf));
+ memcpy(cdfs_ndvc->bits_cdf, default_bits_cdf,
+ sizeof(cdfs_ndvc->bits_cdf));
+
+ memcpy(cdfs->obmc_cdf, default_obmc_cdf, sizeof(cdfs->obmc_cdf));
+ memcpy(cdfs->motion_mode_cdf, default_motion_mode_cdf,
+ sizeof(cdfs->motion_mode_cdf));
+
+ memcpy(cdfs->inter_compound_mode_cdf, default_inter_compound_mode_cdf,
+ sizeof(cdfs->inter_compound_mode_cdf));
+ memcpy(cdfs->compound_type_cdf, default_compound_type_cdf,
+ sizeof(cdfs->compound_type_cdf));
+ memcpy(cdfs->interintra_cdf, default_interintra_cdf,
+ sizeof(cdfs->interintra_cdf));
+ memcpy(cdfs->interintra_mode_cdf, default_interintra_mode_cdf,
+ sizeof(cdfs->interintra_mode_cdf));
+ memcpy(cdfs->wedge_interintra_cdf, default_wedge_interintra_cdf,
+ sizeof(cdfs->wedge_interintra_cdf));
+ memcpy(cdfs->wedge_idx_cdf, default_wedge_idx_cdf,
+ sizeof(cdfs->wedge_idx_cdf));
+
+ memcpy(cdfs->palette_y_mode_cdf, default_palette_y_mode_cdf,
+ sizeof(cdfs->palette_y_mode_cdf));
+ memcpy(cdfs->palette_uv_mode_cdf, default_palette_uv_mode_cdf,
+ sizeof(cdfs->palette_uv_mode_cdf));
+ memcpy(cdfs->palette_y_size_cdf, default_palette_y_size_cdf,
+ sizeof(cdfs->palette_y_size_cdf));
+ memcpy(cdfs->palette_uv_size_cdf, default_palette_uv_size_cdf,
+ sizeof(cdfs->palette_uv_size_cdf));
+ memcpy(cdfs->palette_y_color_index_cdf,
+ default_palette_y_color_index_cdf,
+ sizeof(cdfs->palette_y_color_index_cdf));
+ memcpy(cdfs->palette_uv_color_index_cdf,
+ default_palette_uv_color_index_cdf,
+ sizeof(cdfs->palette_uv_color_index_cdf));
+
+ memcpy(cdfs->cfl_sign_cdf, default_cfl_sign_cdf,
+ sizeof(cdfs->cfl_sign_cdf));
+ memcpy(cdfs->cfl_alpha_cdf, default_cfl_alpha_cdf,
+ sizeof(cdfs->cfl_alpha_cdf));
+
+ memcpy(cdfs->intrabc_cdf, default_intrabc_cdf,
+ sizeof(cdfs->intrabc_cdf));
+ memcpy(cdfs->angle_delta_cdf, default_angle_delta_cdf,
+ sizeof(cdfs->angle_delta_cdf));
+ memcpy(cdfs->filter_intra_mode_cdf, default_filter_intra_mode_cdf,
+ sizeof(cdfs->filter_intra_mode_cdf));
+ memcpy(cdfs->filter_intra_cdf, default_filter_intra_cdfs,
+ sizeof(cdfs->filter_intra_cdf));
+ memcpy(cdfs->comp_group_idx_cdf, default_comp_group_idx_cdfs,
+ sizeof(cdfs->comp_group_idx_cdf));
+ memcpy(cdfs->compound_idx_cdf, default_compound_idx_cdfs,
+ sizeof(cdfs->compound_idx_cdf));
+}
+
+void rockchip_av1_get_cdfs(struct hantro_ctx *ctx, u32 ref_idx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+
+ av1_dec->cdfs = &av1_dec->cdfs_last[ref_idx];
+ av1_dec->cdfs_ndvc = &av1_dec->cdfs_last_ndvc[ref_idx];
+}
+
+void rockchip_av1_store_cdfs(struct hantro_ctx *ctx,
+ u32 refresh_frame_flags)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ int i;
+
+ for (i = 0; i < NUM_REF_FRAMES; i++) {
+ if (refresh_frame_flags & (1 << i)) {
+ if (&av1_dec->cdfs_last[i] != av1_dec->cdfs) {
+ av1_dec->cdfs_last[i] = *av1_dec->cdfs;
+ av1_dec->cdfs_last_ndvc[i] =
+ *av1_dec->cdfs_ndvc;
+ }
+ }
+ }
+}
diff --git a/drivers/media/platform/verisilicon/rockchip_av1_entropymode.h b/drivers/media/platform/verisilicon/rockchip_av1_entropymode.h
new file mode 100644
index 000000000000..bbf8424c7d2c
--- /dev/null
+++ b/drivers/media/platform/verisilicon/rockchip_av1_entropymode.h
@@ -0,0 +1,272 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _ROCKCHIP_AV1_ENTROPYMODE_H_
+#define _ROCKCHIP_AV1_ENTROPYMODE_H_
+
+#include <linux/types.h>
+
+struct hantro_ctx;
+
+#define AV1_INTER_MODE_CONTEXTS 15
+#define AV1_INTRA_MODES 13
+#define AV1_REF_CONTEXTS 3
+#define AV1_SWITCHABLE_FILTERS 3 /* number of switchable filters */
+#define AV1_TX_SIZE_CONTEXTS 3
+#define BLOCK_SIZE_GROUPS 4
+#define BR_CDF_SIZE 4
+#define BWD_REFS 3
+#define CFL_ALLOWED_TYPES 2
+#define CFL_ALPHA_CONTEXTS 6
+#define CFL_ALPHABET_SIZE 16
+#define CFL_JOINT_SIGNS 8
+#define CDF_SIZE(x) ((x) - 1)
+#define COMP_GROUP_IDX_CONTEXTS 7
+#define COMP_INDEX_CONTEXTS 6
+#define COMP_INTER_CONTEXTS 5
+#define COMP_REF_TYPE_CONTEXTS 5
+#define COMPOUND_TYPES 3
+#define DC_SIGN_CONTEXTS 3
+#define DELTA_LF_PROBS 3
+#define DELTA_Q_PROBS 3
+#define DIRECTIONAL_MODES 8
+#define DRL_MODE_CONTEXTS 3
+#define EOB_COEF_CONTEXTS 9
+#define EXT_TX_SIZES 3
+#define EXT_TX_TYPES 16
+#define EXTTX_SIZES 4
+#define FRAME_LF_COUNT 4
+#define FWD_REFS 4
+#define GLOBALMV_MODE_CONTEXTS 2
+#define ICDF(x) (32768U - (x))
+#define INTER_COMPOUND_MODES 8
+#define INTERINTRA_MODES 4
+#define INTRA_INTER_CONTEXTS 4
+#define KF_MODE_CONTEXTS 5
+#define LEVEL_CONTEXTS 21
+#define MAX_ANGLE_DELTA 3
+#define MAX_MB_SEGMENTS 8
+#define MAX_SEGMENTS 8
+#define MAX_TX_CATS 4
+#define MAX_TX_DEPTH 2
+#define MBSKIP_CONTEXTS 3
+#define MOTION_MODES 3
+#define MOTION_MODE_CONTEXTS 10
+#define NEWMV_MODE_CONTEXTS 6
+#define NUM_BASE_LEVELS 2
+#define NUM_REF_FRAMES 8
+#define PALETTE_BLOCK_SIZES 7
+#define PALETTE_IDX_CONTEXTS 18
+#define PALETTE_SIZES 7
+#define PALETTE_UV_MODE_CONTEXTS 2
+#define PALETTE_Y_MODE_CONTEXTS 3
+#define PARTITION_PLOFFSET 4
+#define NUM_PARTITION_CONTEXTS (4 * PARTITION_PLOFFSET)
+#define PLANE_TYPES 2
+#define PREDICTION_PROBS 3
+#define REF_CONTEXTS 5
+#define REFMV_MODE_CONTEXTS 9
+#define SEG_TEMPORAL_PRED_CTXS 3
+#define SIG_COEF_CONTEXTS 42
+#define SIG_COEF_CONTEXTS_EOB 4
+#define SINGLE_REFS 7
+#define SKIP_CONTEXTS 3
+#define SKIP_MODE_CONTEXTS 3
+#define SPATIAL_PREDICTION_PROBS 3
+#define SWITCHABLE_FILTER_CONTEXTS ((AV1_SWITCHABLE_FILTERS + 1) * 4)
+#define TOKEN_CDF_Q_CTXS 4
+#define TX_SIZES 5
+#define TX_SIZE_CONTEXTS 2
+#define TX_TYPES 4
+#define TXB_SKIP_CONTEXTS 13
+#define TXFM_PARTITION_CONTEXTS 22
+#define UNI_COMP_REF_CONTEXTS 3
+#define UNIDIR_COMP_REFS 4
+#define UV_INTRA_MODES 14
+#define VARTX_PART_CONTEXTS 22
+#define ZEROMV_MODE_CONTEXTS 2
+
+enum blocksizetype {
+ BLOCK_SIZE_AB4X4,
+ BLOCK_SIZE_SB4X8,
+ BLOCK_SIZE_SB8X4,
+ BLOCK_SIZE_SB8X8,
+ BLOCK_SIZE_SB8X16,
+ BLOCK_SIZE_SB16X8,
+ BLOCK_SIZE_MB16X16,
+ BLOCK_SIZE_SB16X32,
+ BLOCK_SIZE_SB32X16,
+ BLOCK_SIZE_SB32X32,
+ BLOCK_SIZE_SB32X64,
+ BLOCK_SIZE_SB64X32,
+ BLOCK_SIZE_SB64X64,
+ BLOCK_SIZE_SB64X128,
+ BLOCK_SIZE_SB128X64,
+ BLOCK_SIZE_SB128X128,
+ BLOCK_SIZE_SB4X16,
+ BLOCK_SIZE_SB16X4,
+ BLOCK_SIZE_SB8X32,
+ BLOCK_SIZE_SB32X8,
+ BLOCK_SIZE_SB16X64,
+ BLOCK_SIZE_SB64X16,
+ BLOCK_SIZE_TYPES,
+ BLOCK_SIZES_ALL = BLOCK_SIZE_TYPES
+};
+
+enum filterintramodetype {
+ FILTER_DC_PRED,
+ FILTER_V_PRED,
+ FILTER_H_PRED,
+ FILTER_D153_PRED,
+ FILTER_PAETH_PRED,
+ FILTER_INTRA_MODES,
+ FILTER_INTRA_UNUSED = 7
+};
+
+enum frametype {
+ KEY_FRAME = 0,
+ INTER_FRAME = 1,
+ NUM_FRAME_TYPES,
+};
+
+enum txsize {
+ TX_4X4 = 0,
+ TX_8X8 = 1,
+ TX_16X16 = 2,
+ TX_32X32 = 3,
+ TX_SIZE_MAX_SB,
+};
+
+enum { SIMPLE_TRANSLATION, OBMC_CAUSAL, MOTION_MODE_COUNT };
+
+enum mb_prediction_mode {
+ DC_PRED, /* average of above and left pixels */
+ V_PRED, /* vertical prediction */
+ H_PRED, /* horizontal prediction */
+ D45_PRED, /* Directional 45 deg prediction [anti-clockwise from 0 deg hor] */
+ D135_PRED, /* Directional 135 deg prediction [anti-clockwise from 0 deg hor] */
+ D117_PRED, /* Directional 112 deg prediction [anti-clockwise from 0 deg hor] */
+ D153_PRED, /* Directional 157 deg prediction [anti-clockwise from 0 deg hor] */
+ D27_PRED, /* Directional 22 deg prediction [anti-clockwise from 0 deg hor] */
+ D63_PRED, /* Directional 67 deg prediction [anti-clockwise from 0 deg hor] */
+ SMOOTH_PRED,
+ TM_PRED_AV1 = SMOOTH_PRED,
+ SMOOTH_V_PRED, // Vertical interpolation
+ SMOOTH_H_PRED, // Horizontal interpolation
+ TM_PRED, /* Truemotion prediction */
+ PAETH_PRED = TM_PRED,
+ NEARESTMV,
+ NEARMV,
+ ZEROMV,
+ NEWMV,
+ NEAREST_NEARESTMV,
+ NEAR_NEARMV,
+ NEAREST_NEWMV,
+ NEW_NEARESTMV,
+ NEAR_NEWMV,
+ NEW_NEARMV,
+ ZERO_ZEROMV,
+ NEW_NEWMV,
+ SPLITMV,
+ MB_MODE_COUNT
+};
+
+enum partitiontype {
+ PARTITION_NONE,
+ PARTITION_HORZ,
+ PARTITION_VERT,
+ PARTITION_SPLIT,
+ PARTITION_TYPES
+};
+
+struct mvcdfs {
+ u16 joint_cdf[3];
+ u16 sign_cdf[2];
+ u16 clsss_cdf[2][10];
+ u16 clsss0_fp_cdf[2][2][3];
+ u16 fp_cdf[2][3];
+ u16 class0_hp_cdf[2];
+ u16 hp_cdf[2];
+ u16 class0_cdf[2];
+ u16 bits_cdf[2][10];
+};
+
+struct av1cdfs {
+ u16 partition_cdf[13][16];
+ u16 kf_ymode_cdf[KF_MODE_CONTEXTS][KF_MODE_CONTEXTS][AV1_INTRA_MODES - 1];
+ u16 segment_pred_cdf[PREDICTION_PROBS];
+ u16 spatial_pred_seg_tree_cdf[SPATIAL_PREDICTION_PROBS][MAX_MB_SEGMENTS - 1];
+ u16 mbskip_cdf[MBSKIP_CONTEXTS];
+ u16 delta_q_cdf[DELTA_Q_PROBS];
+ u16 delta_lf_multi_cdf[FRAME_LF_COUNT][DELTA_LF_PROBS];
+ u16 delta_lf_cdf[DELTA_LF_PROBS];
+ u16 skip_mode_cdf[SKIP_MODE_CONTEXTS];
+ u16 vartx_part_cdf[VARTX_PART_CONTEXTS][1];
+ u16 tx_size_cdf[MAX_TX_CATS][AV1_TX_SIZE_CONTEXTS][MAX_TX_DEPTH];
+ u16 if_ymode_cdf[BLOCK_SIZE_GROUPS][AV1_INTRA_MODES - 1];
+ u16 uv_mode_cdf[2][AV1_INTRA_MODES][AV1_INTRA_MODES - 1 + 1];
+ u16 intra_inter_cdf[INTRA_INTER_CONTEXTS];
+ u16 comp_inter_cdf[COMP_INTER_CONTEXTS];
+ u16 single_ref_cdf[AV1_REF_CONTEXTS][SINGLE_REFS - 1];
+ u16 comp_ref_type_cdf[COMP_REF_TYPE_CONTEXTS][1];
+ u16 uni_comp_ref_cdf[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1][1];
+ u16 comp_ref_cdf[AV1_REF_CONTEXTS][FWD_REFS - 1];
+ u16 comp_bwdref_cdf[AV1_REF_CONTEXTS][BWD_REFS - 1];
+ u16 newmv_cdf[NEWMV_MODE_CONTEXTS];
+ u16 zeromv_cdf[ZEROMV_MODE_CONTEXTS];
+ u16 refmv_cdf[REFMV_MODE_CONTEXTS];
+ u16 drl_cdf[DRL_MODE_CONTEXTS];
+ u16 interp_filter_cdf[SWITCHABLE_FILTER_CONTEXTS][AV1_SWITCHABLE_FILTERS - 1];
+ struct mvcdfs mv_cdf;
+ u16 obmc_cdf[BLOCK_SIZE_TYPES];
+ u16 motion_mode_cdf[BLOCK_SIZE_TYPES][2];
+ u16 inter_compound_mode_cdf[AV1_INTER_MODE_CONTEXTS][INTER_COMPOUND_MODES - 1];
+ u16 compound_type_cdf[BLOCK_SIZE_TYPES][CDF_SIZE(COMPOUND_TYPES - 1)];
+ u16 interintra_cdf[BLOCK_SIZE_GROUPS];
+ u16 interintra_mode_cdf[BLOCK_SIZE_GROUPS][INTERINTRA_MODES - 1];
+ u16 wedge_interintra_cdf[BLOCK_SIZE_TYPES];
+ u16 wedge_idx_cdf[BLOCK_SIZE_TYPES][CDF_SIZE(16)];
+ u16 palette_y_mode_cdf[PALETTE_BLOCK_SIZES][PALETTE_Y_MODE_CONTEXTS][1];
+ u16 palette_uv_mode_cdf[PALETTE_UV_MODE_CONTEXTS][1];
+ u16 palette_y_size_cdf[PALETTE_BLOCK_SIZES][PALETTE_SIZES - 1];
+ u16 palette_uv_size_cdf[PALETTE_BLOCK_SIZES][PALETTE_SIZES - 1];
+ u16 cfl_sign_cdf[CFL_JOINT_SIGNS - 1];
+ u16 cfl_alpha_cdf[CFL_ALPHA_CONTEXTS][CFL_ALPHABET_SIZE - 1];
+ u16 intrabc_cdf[1];
+ u16 angle_delta_cdf[DIRECTIONAL_MODES][6];
+ u16 filter_intra_mode_cdf[FILTER_INTRA_MODES - 1];
+ u16 filter_intra_cdf[BLOCK_SIZES_ALL];
+ u16 comp_group_idx_cdf[COMP_GROUP_IDX_CONTEXTS][CDF_SIZE(2)];
+ u16 compound_idx_cdf[COMP_INDEX_CONTEXTS][CDF_SIZE(2)];
+ u16 dummy0[14];
+ // Palette index contexts; sizes 1/7, 2/6, 3/5 packed together
+ u16 palette_y_color_index_cdf[PALETTE_IDX_CONTEXTS][8];
+ u16 palette_uv_color_index_cdf[PALETTE_IDX_CONTEXTS][8];
+ u16 tx_type_intra0_cdf[EXTTX_SIZES][AV1_INTRA_MODES][8];
+ u16 tx_type_intra1_cdf[EXTTX_SIZES][AV1_INTRA_MODES][4];
+ u16 tx_type_inter_cdf[2][EXTTX_SIZES][EXT_TX_TYPES];
+ u16 txb_skip_cdf[TX_SIZES][TXB_SKIP_CONTEXTS][CDF_SIZE(2)];
+ u16 eob_extra_cdf[TX_SIZES][PLANE_TYPES][EOB_COEF_CONTEXTS][CDF_SIZE(2)];
+ u16 dummy1[5];
+ u16 eob_flag_cdf16[PLANE_TYPES][2][4];
+ u16 eob_flag_cdf32[PLANE_TYPES][2][8];
+ u16 eob_flag_cdf64[PLANE_TYPES][2][8];
+ u16 eob_flag_cdf128[PLANE_TYPES][2][8];
+ u16 eob_flag_cdf256[PLANE_TYPES][2][8];
+ u16 eob_flag_cdf512[PLANE_TYPES][2][16];
+ u16 eob_flag_cdf1024[PLANE_TYPES][2][16];
+ u16 coeff_base_eob_cdf[TX_SIZES][PLANE_TYPES][SIG_COEF_CONTEXTS_EOB][CDF_SIZE(3)];
+ u16 coeff_base_cdf[TX_SIZES][PLANE_TYPES][SIG_COEF_CONTEXTS][CDF_SIZE(4) + 1];
+ u16 dc_sign_cdf[PLANE_TYPES][DC_SIGN_CONTEXTS][CDF_SIZE(2)];
+ u16 dummy2[2];
+ u16 coeff_br_cdf[TX_SIZES][PLANE_TYPES][LEVEL_CONTEXTS][CDF_SIZE(BR_CDF_SIZE) + 1];
+ u16 dummy3[16];
+};
+
+void rockchip_av1_store_cdfs(struct hantro_ctx *ctx,
+ u32 refresh_frame_flags);
+void rockchip_av1_get_cdfs(struct hantro_ctx *ctx, u32 ref_idx);
+void rockchip_av1_set_default_cdfs(struct av1cdfs *cdfs,
+ struct mvcdfs *cdfs_ndvc);
+void rockchip_av1_default_coeff_probs(u32 base_qindex, void *ptr);
+
+#endif /* _ROCKCHIP_AV1_ENTROPYMODE_H_ */
diff --git a/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.c b/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.c
new file mode 100644
index 000000000000..f2ae84f0b436
--- /dev/null
+++ b/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.c
@@ -0,0 +1,401 @@
+// SPDX-License-Identifier: GPL-2.0-only or Apache-2.0
+
+#include "rockchip_av1_filmgrain.h"
+
+static const s32 gaussian_sequence[2048] = {
+ 56, 568, -180, 172, 124, -84, 172, -64, -900, 24, 820,
+ 224, 1248, 996, 272, -8, -916, -388, -732, -104, -188, 800,
+ 112, -652, -320, -376, 140, -252, 492, -168, 44, -788, 588,
+ -584, 500, -228, 12, 680, 272, -476, 972, -100, 652, 368,
+ 432, -196, -720, -192, 1000, -332, 652, -136, -552, -604, -4,
+ 192, -220, -136, 1000, -52, 372, -96, -624, 124, -24, 396,
+ 540, -12, -104, 640, 464, 244, -208, -84, 368, -528, -740,
+ 248, -968, -848, 608, 376, -60, -292, -40, -156, 252, -292,
+ 248, 224, -280, 400, -244, 244, -60, 76, -80, 212, 532,
+ 340, 128, -36, 824, -352, -60, -264, -96, -612, 416, -704,
+ 220, -204, 640, -160, 1220, -408, 900, 336, 20, -336, -96,
+ -792, 304, 48, -28, -1232, -1172, -448, 104, -292, -520, 244,
+ 60, -948, 0, -708, 268, 108, 356, -548, 488, -344, -136,
+ 488, -196, -224, 656, -236, -1128, 60, 4, 140, 276, -676,
+ -376, 168, -108, 464, 8, 564, 64, 240, 308, -300, -400,
+ -456, -136, 56, 120, -408, -116, 436, 504, -232, 328, 844,
+ -164, -84, 784, -168, 232, -224, 348, -376, 128, 568, 96,
+ -1244, -288, 276, 848, 832, -360, 656, 464, -384, -332, -356,
+ 728, -388, 160, -192, 468, 296, 224, 140, -776, -100, 280,
+ 4, 196, 44, -36, -648, 932, 16, 1428, 28, 528, 808,
+ 772, 20, 268, 88, -332, -284, 124, -384, -448, 208, -228,
+ -1044, -328, 660, 380, -148, -300, 588, 240, 540, 28, 136,
+ -88, -436, 256, 296, -1000, 1400, 0, -48, 1056, -136, 264,
+ -528, -1108, 632, -484, -592, -344, 796, 124, -668, -768, 388,
+ 1296, -232, -188, -200, -288, -4, 308, 100, -168, 256, -500,
+ 204, -508, 648, -136, 372, -272, -120, -1004, -552, -548, -384,
+ 548, -296, 428, -108, -8, -912, -324, -224, -88, -112, -220,
+ -100, 996, -796, 548, 360, -216, 180, 428, -200, -212, 148,
+ 96, 148, 284, 216, -412, -320, 120, -300, -384, -604, -572,
+ -332, -8, -180, -176, 696, 116, -88, 628, 76, 44, -516,
+ 240, -208, -40, 100, -592, 344, -308, -452, -228, 20, 916,
+ -1752, -136, -340, -804, 140, 40, 512, 340, 248, 184, -492,
+ 896, -156, 932, -628, 328, -688, -448, -616, -752, -100, 560,
+ -1020, 180, -800, -64, 76, 576, 1068, 396, 660, 552, -108,
+ -28, 320, -628, 312, -92, -92, -472, 268, 16, 560, 516,
+ -672, -52, 492, -100, 260, 384, 284, 292, 304, -148, 88,
+ -152, 1012, 1064, -228, 164, -376, -684, 592, -392, 156, 196,
+ -524, -64, -884, 160, -176, 636, 648, 404, -396, -436, 864,
+ 424, -728, 988, -604, 904, -592, 296, -224, 536, -176, -920,
+ 436, -48, 1176, -884, 416, -776, -824, -884, 524, -548, -564,
+ -68, -164, -96, 692, 364, -692, -1012, -68, 260, -480, 876,
+ -1116, 452, -332, -352, 892, -1088, 1220, -676, 12, -292, 244,
+ 496, 372, -32, 280, 200, 112, -440, -96, 24, -644, -184,
+ 56, -432, 224, -980, 272, -260, 144, -436, 420, 356, 364,
+ -528, 76, 172, -744, -368, 404, -752, -416, 684, -688, 72,
+ 540, 416, 92, 444, 480, -72, -1416, 164, -1172, -68, 24,
+ 424, 264, 1040, 128, -912, -524, -356, 64, 876, -12, 4,
+ -88, 532, 272, -524, 320, 276, -508, 940, 24, -400, -120,
+ 756, 60, 236, -412, 100, 376, -484, 400, -100, -740, -108,
+ -260, 328, -268, 224, -200, -416, 184, -604, -564, -20, 296,
+ 60, 892, -888, 60, 164, 68, -760, 216, -296, 904, -336,
+ -28, 404, -356, -568, -208, -1480, -512, 296, 328, -360, -164,
+ -1560, -776, 1156, -428, 164, -504, -112, 120, -216, -148, -264,
+ 308, 32, 64, -72, 72, 116, 176, -64, -272, 460, -536,
+ -784, -280, 348, 108, -752, -132, 524, -540, -776, 116, -296,
+ -1196, -288, -560, 1040, -472, 116, -848, -1116, 116, 636, 696,
+ 284, -176, 1016, 204, -864, -648, -248, 356, 972, -584, -204,
+ 264, 880, 528, -24, -184, 116, 448, -144, 828, 524, 212,
+ -212, 52, 12, 200, 268, -488, -404, -880, 824, -672, -40,
+ 908, -248, 500, 716, -576, 492, -576, 16, 720, -108, 384,
+ 124, 344, 280, 576, -500, 252, 104, -308, 196, -188, -8,
+ 1268, 296, 1032, -1196, 436, 316, 372, -432, -200, -660, 704,
+ -224, 596, -132, 268, 32, -452, 884, 104, -1008, 424, -1348,
+ -280, 4, -1168, 368, 476, 696, 300, -8, 24, 180, -592,
+ -196, 388, 304, 500, 724, -160, 244, -84, 272, -256, -420,
+ 320, 208, -144, -156, 156, 364, 452, 28, 540, 316, 220,
+ -644, -248, 464, 72, 360, 32, -388, 496, -680, -48, 208,
+ -116, -408, 60, -604, -392, 548, -840, 784, -460, 656, -544,
+ -388, -264, 908, -800, -628, -612, -568, 572, -220, 164, 288,
+ -16, -308, 308, -112, -636, -760, 280, -668, 432, 364, 240,
+ -196, 604, 340, 384, 196, 592, -44, -500, 432, -580, -132,
+ 636, -76, 392, 4, -412, 540, 508, 328, -356, -36, 16,
+ -220, -64, -248, -60, 24, -192, 368, 1040, 92, -24, -1044,
+ -32, 40, 104, 148, 192, -136, -520, 56, -816, -224, 732,
+ 392, 356, 212, -80, -424, -1008, -324, 588, -1496, 576, 460,
+ -816, -848, 56, -580, -92, -1372, -112, -496, 200, 364, 52,
+ -140, 48, -48, -60, 84, 72, 40, 132, -356, -268, -104,
+ -284, -404, 732, -520, 164, -304, -540, 120, 328, -76, -460,
+ 756, 388, 588, 236, -436, -72, -176, -404, -316, -148, 716,
+ -604, 404, -72, -88, -888, -68, 944, 88, -220, -344, 960,
+ 472, 460, -232, 704, 120, 832, -228, 692, -508, 132, -476,
+ 844, -748, -364, -44, 1116, -1104, -1056, 76, 428, 552, -692,
+ 60, 356, 96, -384, -188, -612, -576, 736, 508, 892, 352,
+ -1132, 504, -24, -352, 324, 332, -600, -312, 292, 508, -144,
+ -8, 484, 48, 284, -260, -240, 256, -100, -292, -204, -44,
+ 472, -204, 908, -188, -1000, -256, 92, 1164, -392, 564, 356,
+ 652, -28, -884, 256, 484, -192, 760, -176, 376, -524, -452,
+ -436, 860, -736, 212, 124, 504, -476, 468, 76, -472, 552,
+ -692, -944, -620, 740, -240, 400, 132, 20, 192, -196, 264,
+ -668, -1012, -60, 296, -316, -828, 76, -156, 284, -768, -448,
+ -832, 148, 248, 652, 616, 1236, 288, -328, -400, -124, 588,
+ 220, 520, -696, 1032, 768, -740, -92, -272, 296, 448, -464,
+ 412, -200, 392, 440, -200, 264, -152, -260, 320, 1032, 216,
+ 320, -8, -64, 156, -1016, 1084, 1172, 536, 484, -432, 132,
+ 372, -52, -256, 84, 116, -352, 48, 116, 304, -384, 412,
+ 924, -300, 528, 628, 180, 648, 44, -980, -220, 1320, 48,
+ 332, 748, 524, -268, -720, 540, -276, 564, -344, -208, -196,
+ 436, 896, 88, -392, 132, 80, -964, -288, 568, 56, -48,
+ -456, 888, 8, 552, -156, -292, 948, 288, 128, -716, -292,
+ 1192, -152, 876, 352, -600, -260, -812, -468, -28, -120, -32,
+ -44, 1284, 496, 192, 464, 312, -76, -516, -380, -456, -1012,
+ -48, 308, -156, 36, 492, -156, -808, 188, 1652, 68, -120,
+ -116, 316, 160, -140, 352, 808, -416, 592, 316, -480, 56,
+ 528, -204, -568, 372, -232, 752, -344, 744, -4, 324, -416,
+ -600, 768, 268, -248, -88, -132, -420, -432, 80, -288, 404,
+ -316, -1216, -588, 520, -108, 92, -320, 368, -480, -216, -92,
+ 1688, -300, 180, 1020, -176, 820, -68, -228, -260, 436, -904,
+ 20, 40, -508, 440, -736, 312, 332, 204, 760, -372, 728,
+ 96, -20, -632, -520, -560, 336, 1076, -64, -532, 776, 584,
+ 192, 396, -728, -520, 276, -188, 80, -52, -612, -252, -48,
+ 648, 212, -688, 228, -52, -260, 428, -412, -272, -404, 180,
+ 816, -796, 48, 152, 484, -88, -216, 988, 696, 188, -528,
+ 648, -116, -180, 316, 476, 12, -564, 96, 476, -252, -364,
+ -376, -392, 556, -256, -576, 260, -352, 120, -16, -136, -260,
+ -492, 72, 556, 660, 580, 616, 772, 436, 424, -32, -324,
+ -1268, 416, -324, -80, 920, 160, 228, 724, 32, -516, 64,
+ 384, 68, -128, 136, 240, 248, -204, -68, 252, -932, -120,
+ -480, -628, -84, 192, 852, -404, -288, -132, 204, 100, 168,
+ -68, -196, -868, 460, 1080, 380, -80, 244, 0, 484, -888,
+ 64, 184, 352, 600, 460, 164, 604, -196, 320, -64, 588,
+ -184, 228, 12, 372, 48, -848, -344, 224, 208, -200, 484,
+ 128, -20, 272, -468, -840, 384, 256, -720, -520, -464, -580,
+ 112, -120, 644, -356, -208, -608, -528, 704, 560, -424, 392,
+ 828, 40, 84, 200, -152, 0, -144, 584, 280, -120, 80,
+ -556, -972, -196, -472, 724, 80, 168, -32, 88, 160, -688,
+ 0, 160, 356, 372, -776, 740, -128, 676, -248, -480, 4,
+ -364, 96, 544, 232, -1032, 956, 236, 356, 20, -40, 300,
+ 24, -676, -596, 132, 1120, -104, 532, -1096, 568, 648, 444,
+ 508, 380, 188, -376, -604, 1488, 424, 24, 756, -220, -192,
+ 716, 120, 920, 688, 168, 44, -460, 568, 284, 1144, 1160,
+ 600, 424, 888, 656, -356, -320, 220, 316, -176, -724, -188,
+ -816, -628, -348, -228, -380, 1012, -452, -660, 736, 928, 404,
+ -696, -72, -268, -892, 128, 184, -344, -780, 360, 336, 400,
+ 344, 428, 548, -112, 136, -228, -216, -820, -516, 340, 92,
+ -136, 116, -300, 376, -244, 100, -316, -520, -284, -12, 824,
+ 164, -548, -180, -128, 116, -924, -828, 268, -368, -580, 620,
+ 192, 160, 0, -1676, 1068, 424, -56, -360, 468, -156, 720,
+ 288, -528, 556, -364, 548, -148, 504, 316, 152, -648, -620,
+ -684, -24, -376, -384, -108, -920, -1032, 768, 180, -264, -508,
+ -1268, -260, -60, 300, -240, 988, 724, -376, -576, -212, -736,
+ 556, 192, 1092, -620, -880, 376, -56, -4, -216, -32, 836,
+ 268, 396, 1332, 864, -600, 100, 56, -412, -92, 356, 180,
+ 884, -468, -436, 292, -388, -804, -704, -840, 368, -348, 140,
+ -724, 1536, 940, 372, 112, -372, 436, -480, 1136, 296, -32,
+ -228, 132, -48, -220, 868, -1016, -60, -1044, -464, 328, 916,
+ 244, 12, -736, -296, 360, 468, -376, -108, -92, 788, 368,
+ -56, 544, 400, -672, -420, 728, 16, 320, 44, -284, -380,
+ -796, 488, 132, 204, -596, -372, 88, -152, -908, -636, -572,
+ -624, -116, -692, -200, -56, 276, -88, 484, -324, 948, 864,
+ 1000, -456, -184, -276, 292, -296, 156, 676, 320, 160, 908,
+ -84, -1236, -288, -116, 260, -372, -644, 732, -756, -96, 84,
+ 344, -520, 348, -688, 240, -84, 216, -1044, -136, -676, -396,
+ -1500, 960, -40, 176, 168, 1516, 420, -504, -344, -364, -360,
+ 1216, -940, -380, -212, 252, -660, -708, 484, -444, -152, 928,
+ -120, 1112, 476, -260, 560, -148, -344, 108, -196, 228, -288,
+ 504, 560, -328, -88, 288, -1008, 460, -228, 468, -836, -196,
+ 76, 388, 232, 412, -1168, -716, -644, 756, -172, -356, -504,
+ 116, 432, 528, 48, 476, -168, -608, 448, 160, -532, -272,
+ 28, -676, -12, 828, 980, 456, 520, 104, -104, 256, -344,
+ -4, -28, -368, -52, -524, -572, -556, -200, 768, 1124, -208,
+ -512, 176, 232, 248, -148, -888, 604, -600, -304, 804, -156,
+ -212, 488, -192, -804, -256, 368, -360, -916, -328, 228, -240,
+ -448, -472, 856, -556, -364, 572, -12, -156, -368, -340, 432,
+ 252, -752, -152, 288, 268, -580, -848, -592, 108, -76, 244,
+ 312, -716, 592, -80, 436, 360, 4, -248, 160, 516, 584,
+ 732, 44, -468, -280, -292, -156, -588, 28, 308, 912, 24,
+ 124, 156, 180, -252, 944, -924, -772, -520, -428, -624, 300,
+ -212, -1144, 32, -724, 800, -1128, -212, -1288, -848, 180, -416,
+ 440, 192, -576, -792, -76, -1080, 80, -532, -352, -132, 380,
+ -820, 148, 1112, 128, 164, 456, 700, -924, 144, -668, -384,
+ 648, -832, 508, 552, -52, -100, -656, 208, -568, 748, -88,
+ 680, 232, 300, 192, -408, -1012, -152, -252, -268, 272, -876,
+ -664, -648, -332, -136, 16, 12, 1152, -28, 332, -536, 320,
+ -672, -460, -316, 532, -260, 228, -40, 1052, -816, 180, 88,
+ -496, -556, -672, -368, 428, 92, 356, 404, -408, 252, 196,
+ -176, -556, 792, 268, 32, 372, 40, 96, -332, 328, 120,
+ 372, -900, -40, 472, -264, -592, 952, 128, 656, 112, 664,
+ -232, 420, 4, -344, -464, 556, 244, -416, -32, 252, 0,
+ -412, 188, -696, 508, -476, 324, -1096, 656, -312, 560, 264,
+ -136, 304, 160, -64, -580, 248, 336, -720, 560, -348, -288,
+ -276, -196, -500, 852, -544, -236, -1128, -992, -776, 116, 56,
+ 52, 860, 884, 212, -12, 168, 1020, 512, -552, 924, -148,
+ 716, 188, 164, -340, -520, -184, 880, -152, -680, -208, -1156,
+ -300, -528, -472, 364, 100, -744, -1056, -32, 540, 280, 144,
+ -676, -32, -232, -280, -224, 96, 568, -76, 172, 148, 148,
+ 104, 32, -296, -32, 788, -80, 32, -16, 280, 288, 944,
+ 428, -484
+};
+
+static inline s32 clamp(s32 value, s32 low, s32 high)
+{
+ return value < low ? low : (value > high ? high : value);
+}
+
+static inline s32 round_power_of_two(const s32 val, s32 n)
+{
+ const s32 a = (s32)1 << (n - 1);
+
+ return (val + a) >> n;
+}
+
+static void rockchip_av1_init_random_generator(u8 luma_num, u16 seed,
+ u16 *random_register)
+{
+ u16 random_reg = seed;
+
+ random_reg ^= ((luma_num * 37 + 178) & 255) << 8;
+ random_reg ^= ((luma_num * 173 + 105) & 255);
+ *random_register = random_reg;
+}
+
+static inline void rockchip_av1_update_random_register(u16 *random_register)
+{
+ u16 bit;
+ u16 random_reg = *random_register;
+
+ bit = ((random_reg >> 0) ^ (random_reg >> 1) ^ (random_reg >> 3) ^
+ (random_reg >> 12)) & 1;
+ *random_register = (random_reg >> 1) | (bit << 15);
+}
+
+static inline s32 rockchip_av1_get_random_number(u16 random_register)
+{
+ return (random_register >> 5) & ((1 << 11) - 1);
+}
+
+void rockchip_av1_generate_luma_grain_block(s32 (*luma_grain_block)[73][82],
+ s32 bitdepth,
+ u8 num_y_points,
+ s32 grain_scale_shift,
+ s32 ar_coeff_lag,
+ s32 (*ar_coeffs_y)[24],
+ s32 ar_coeff_shift,
+ s32 grain_min,
+ s32 grain_max,
+ u16 random_seed)
+{
+ s32 gauss_sec_shift = 12 - bitdepth + grain_scale_shift;
+ u16 grain_random_register = random_seed;
+ s32 i, j;
+
+ for (i = 0; i < 73; i++) {
+ for (j = 0; j < 82; j++) {
+ if (num_y_points > 0) {
+ rockchip_av1_update_random_register
+ (&grain_random_register);
+ (*luma_grain_block)[i][j] =
+ round_power_of_two(gaussian_sequence
+ [rockchip_av1_get_random_number
+ (grain_random_register)],
+ gauss_sec_shift);
+ } else {
+ (*luma_grain_block)[i][j] = 0;
+ }
+ }
+ }
+
+ for (i = 3; i < 73; i++)
+ for (j = 3; j < 82 - 3; j++) {
+ s32 pos = 0;
+ s32 wsum = 0;
+ s32 deltarow, deltacol;
+
+ for (deltarow = -ar_coeff_lag; deltarow <= 0;
+ deltarow++) {
+ for (deltacol = -ar_coeff_lag;
+ deltacol <= ar_coeff_lag; deltacol++) {
+ if (deltarow == 0 && deltacol == 0)
+ break;
+ wsum = wsum + (*ar_coeffs_y)[pos] *
+ (*luma_grain_block)[i + deltarow][j + deltacol];
+ ++pos;
+ }
+ }
+ (*luma_grain_block)[i][j] =
+ clamp((*luma_grain_block)[i][j] +
+ round_power_of_two(wsum, ar_coeff_shift),
+ grain_min, grain_max);
+ }
+}
+
+// Calculate chroma grain noise once per frame
+void rockchip_av1_generate_chroma_grain_block(s32 (*luma_grain_block)[73][82],
+ s32 (*cb_grain_block)[38][44],
+ s32 (*cr_grain_block)[38][44],
+ s32 bitdepth,
+ u8 num_y_points,
+ u8 num_cb_points,
+ u8 num_cr_points,
+ s32 grain_scale_shift,
+ s32 ar_coeff_lag,
+ s32 (*ar_coeffs_cb)[25],
+ s32 (*ar_coeffs_cr)[25],
+ s32 ar_coeff_shift,
+ s32 grain_min,
+ s32 grain_max,
+ u8 chroma_scaling_from_luma,
+ u16 random_seed)
+{
+ s32 gauss_sec_shift = 12 - bitdepth + grain_scale_shift;
+ u16 grain_random_register = 0;
+ s32 i, j;
+
+ rockchip_av1_init_random_generator(7, random_seed,
+ &grain_random_register);
+ for (i = 0; i < 38; i++) {
+ for (j = 0; j < 44; j++) {
+ if (num_cb_points || chroma_scaling_from_luma) {
+ rockchip_av1_update_random_register
+ (&grain_random_register);
+ (*cb_grain_block)[i][j] =
+ round_power_of_two(gaussian_sequence
+ [rockchip_av1_get_random_number
+ (grain_random_register)],
+ gauss_sec_shift);
+ } else {
+ (*cb_grain_block)[i][j] = 0;
+ }
+ }
+ }
+
+ rockchip_av1_init_random_generator(11, random_seed,
+ &grain_random_register);
+ for (i = 0; i < 38; i++) {
+ for (j = 0; j < 44; j++) {
+ if (num_cr_points || chroma_scaling_from_luma) {
+ rockchip_av1_update_random_register
+ (&grain_random_register);
+ (*cr_grain_block)[i][j] =
+ round_power_of_two(gaussian_sequence
+ [rockchip_av1_get_random_number
+ (grain_random_register)],
+ gauss_sec_shift);
+ } else {
+ (*cr_grain_block)[i][j] = 0;
+ }
+ }
+ }
+
+ for (i = 3; i < 38; i++) {
+ for (j = 3; j < 44 - 3; j++) {
+ s32 wsum_cb = 0;
+ s32 wsum_cr = 0;
+ s32 pos = 0;
+ s32 deltarow, deltacol;
+
+ for (deltarow = -ar_coeff_lag; deltarow <= 0;
+ deltarow++) {
+ for (deltacol = -ar_coeff_lag;
+ deltacol <= ar_coeff_lag; deltacol++) {
+ if (deltarow == 0 && deltacol == 0)
+ break;
+ wsum_cb = wsum_cb + (*ar_coeffs_cb)[pos] *
+ (*cb_grain_block)[i + deltarow][j + deltacol];
+ wsum_cr =
+ wsum_cr +
+ (*ar_coeffs_cr)[pos] *
+ (*cr_grain_block)[i + deltarow][j + deltacol];
+ ++pos;
+ }
+ }
+
+ if (num_y_points > 0) {
+ s32 av_luma = 0;
+ s32 luma_coord_y = (i << 1) - 3;
+ s32 luma_coord_x = (j << 1) - 3;
+
+ av_luma +=
+ (*luma_grain_block)[luma_coord_y][luma_coord_x];
+ av_luma +=
+ (*luma_grain_block)[luma_coord_y][luma_coord_x + 1];
+ av_luma +=
+ (*luma_grain_block)[luma_coord_y + 1][luma_coord_x];
+ av_luma +=
+ (*luma_grain_block)[(luma_coord_y + 1)][luma_coord_x + 1];
+ av_luma = round_power_of_two(av_luma, 2);
+
+ wsum_cb = wsum_cb + (*ar_coeffs_cb)[pos] * av_luma;
+ wsum_cr = wsum_cr + (*ar_coeffs_cr)[pos] * av_luma;
+ }
+
+ if (num_cb_points || chroma_scaling_from_luma) {
+ (*cb_grain_block)[i][j] =
+ clamp((*cb_grain_block)[i][j] +
+ round_power_of_two(wsum_cb, ar_coeff_shift),
+ grain_min, grain_max);
+ }
+ if (num_cr_points || chroma_scaling_from_luma) {
+ (*cr_grain_block)[i][j] =
+ clamp((*cr_grain_block)[i][j] +
+ round_power_of_two(wsum_cr, ar_coeff_shift),
+ grain_min, grain_max);
+ }
+ }
+ }
+}
diff --git a/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.h b/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.h
new file mode 100644
index 000000000000..31a8b7920c31
--- /dev/null
+++ b/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _ROCKCHIP_AV1_FILMGRAIN_H_
+#define _ROCKCHIP_AV1_FILMGRAIN_H_
+
+#include <linux/types.h>
+
+void rockchip_av1_generate_luma_grain_block(s32 (*luma_grain_block)[73][82],
+ s32 bitdepth,
+ u8 num_y_points,
+ s32 grain_scale_shift,
+ s32 ar_coeff_lag,
+ s32 (*ar_coeffs_y)[24],
+ s32 ar_coeff_shift,
+ s32 grain_min,
+ s32 grain_max,
+ u16 random_seed);
+
+void rockchip_av1_generate_chroma_grain_block(s32 (*luma_grain_block)[73][82],
+ s32 (*cb_grain_block)[38][44],
+ s32 (*cr_grain_block)[38][44],
+ s32 bitdepth,
+ u8 num_y_points,
+ u8 num_cb_points,
+ u8 num_cr_points,
+ s32 grain_scale_shift,
+ s32 ar_coeff_lag,
+ s32 (*ar_coeffs_cb)[25],
+ s32 (*ar_coeffs_cr)[25],
+ s32 ar_coeff_shift,
+ s32 grain_min,
+ s32 grain_max,
+ u8 chroma_scaling_from_luma,
+ u16 random_seed);
+
+#endif
diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
new file mode 100644
index 000000000000..cc4483857489
--- /dev/null
+++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
@@ -0,0 +1,2232 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, Collabora
+ *
+ * Author: Benjamin Gaignard <benjamin.gaignard@collabora.com>
+ */
+
+#include <media/v4l2-mem2mem.h>
+#include "hantro.h"
+#include "hantro_v4l2.h"
+#include "rockchip_vpu981_regs.h"
+
+#define AV1_DEC_MODE 17
+#define GM_GLOBAL_MODELS_PER_FRAME 7
+#define GLOBAL_MODEL_TOTAL_SIZE (6 * 4 + 4 * 2)
+#define GLOBAL_MODEL_SIZE ALIGN(GM_GLOBAL_MODELS_PER_FRAME * GLOBAL_MODEL_TOTAL_SIZE, 2048)
+#define AV1_MAX_TILES 128
+#define AV1_TILE_INFO_SIZE (AV1_MAX_TILES * 16)
+#define AV1DEC_MAX_PIC_BUFFERS 24
+#define AV1_REF_SCALE_SHIFT 14
+#define AV1_INVALID_IDX -1
+#define MAX_FRAME_DISTANCE 31
+#define AV1_PRIMARY_REF_NONE 7
+#define AV1_TILE_SIZE ALIGN(32 * 128, 4096)
+/*
+ * These 3 values aren't defined enum v4l2_av1_segment_feature because
+ * they are not part of the specification
+ */
+#define V4L2_AV1_SEG_LVL_ALT_LF_Y_H 2
+#define V4L2_AV1_SEG_LVL_ALT_LF_U 3
+#define V4L2_AV1_SEG_LVL_ALT_LF_V 4
+
+#define SUPERRES_SCALE_BITS 3
+#define SCALE_NUMERATOR 8
+#define SUPERRES_SCALE_DENOMINATOR_MIN (SCALE_NUMERATOR + 1)
+
+#define RS_SUBPEL_BITS 6
+#define RS_SUBPEL_MASK ((1 << RS_SUBPEL_BITS) - 1)
+#define RS_SCALE_SUBPEL_BITS 14
+#define RS_SCALE_SUBPEL_MASK ((1 << RS_SCALE_SUBPEL_BITS) - 1)
+#define RS_SCALE_EXTRA_BITS (RS_SCALE_SUBPEL_BITS - RS_SUBPEL_BITS)
+#define RS_SCALE_EXTRA_OFF (1 << (RS_SCALE_EXTRA_BITS - 1))
+
+#define IS_INTRA(type) ((type == V4L2_AV1_KEY_FRAME) || (type == V4L2_AV1_INTRA_ONLY_FRAME))
+
+#define LST_BUF_IDX (V4L2_AV1_REF_LAST_FRAME - V4L2_AV1_REF_LAST_FRAME)
+#define LST2_BUF_IDX (V4L2_AV1_REF_LAST2_FRAME - V4L2_AV1_REF_LAST_FRAME)
+#define LST3_BUF_IDX (V4L2_AV1_REF_LAST3_FRAME - V4L2_AV1_REF_LAST_FRAME)
+#define GLD_BUF_IDX (V4L2_AV1_REF_GOLDEN_FRAME - V4L2_AV1_REF_LAST_FRAME)
+#define BWD_BUF_IDX (V4L2_AV1_REF_BWDREF_FRAME - V4L2_AV1_REF_LAST_FRAME)
+#define ALT2_BUF_IDX (V4L2_AV1_REF_ALTREF2_FRAME - V4L2_AV1_REF_LAST_FRAME)
+#define ALT_BUF_IDX (V4L2_AV1_REF_ALTREF_FRAME - V4L2_AV1_REF_LAST_FRAME)
+
+#define DIV_LUT_PREC_BITS 14
+#define DIV_LUT_BITS 8
+#define DIV_LUT_NUM BIT(DIV_LUT_BITS)
+#define WARP_PARAM_REDUCE_BITS 6
+#define WARPEDMODEL_PREC_BITS 16
+
+#define AV1_DIV_ROUND_UP_POW2(value, n) \
+({ \
+ typeof(n) _n = n; \
+ typeof(value) _value = value; \
+ (_value + (BIT(_n) >> 1)) >> _n; \
+})
+
+#define AV1_DIV_ROUND_UP_POW2_SIGNED(value, n) \
+({ \
+ typeof(n) _n_ = n; \
+ typeof(value) _value_ = value; \
+ (((_value_) < 0) ? -AV1_DIV_ROUND_UP_POW2(-(_value_), (_n_)) \
+ : AV1_DIV_ROUND_UP_POW2((_value_), (_n_))); \
+})
+
+struct rockchip_av1_film_grain {
+ u8 scaling_lut_y[256];
+ u8 scaling_lut_cb[256];
+ u8 scaling_lut_cr[256];
+ s16 cropped_luma_grain_block[4096];
+ s16 cropped_chroma_grain_block[1024 * 2];
+};
+
+static const short div_lut[DIV_LUT_NUM + 1] = {
+ 16384, 16320, 16257, 16194, 16132, 16070, 16009, 15948, 15888, 15828, 15768,
+ 15709, 15650, 15592, 15534, 15477, 15420, 15364, 15308, 15252, 15197, 15142,
+ 15087, 15033, 14980, 14926, 14873, 14821, 14769, 14717, 14665, 14614, 14564,
+ 14513, 14463, 14413, 14364, 14315, 14266, 14218, 14170, 14122, 14075, 14028,
+ 13981, 13935, 13888, 13843, 13797, 13752, 13707, 13662, 13618, 13574, 13530,
+ 13487, 13443, 13400, 13358, 13315, 13273, 13231, 13190, 13148, 13107, 13066,
+ 13026, 12985, 12945, 12906, 12866, 12827, 12788, 12749, 12710, 12672, 12633,
+ 12596, 12558, 12520, 12483, 12446, 12409, 12373, 12336, 12300, 12264, 12228,
+ 12193, 12157, 12122, 12087, 12053, 12018, 11984, 11950, 11916, 11882, 11848,
+ 11815, 11782, 11749, 11716, 11683, 11651, 11619, 11586, 11555, 11523, 11491,
+ 11460, 11429, 11398, 11367, 11336, 11305, 11275, 11245, 11215, 11185, 11155,
+ 11125, 11096, 11067, 11038, 11009, 10980, 10951, 10923, 10894, 10866, 10838,
+ 10810, 10782, 10755, 10727, 10700, 10673, 10645, 10618, 10592, 10565, 10538,
+ 10512, 10486, 10460, 10434, 10408, 10382, 10356, 10331, 10305, 10280, 10255,
+ 10230, 10205, 10180, 10156, 10131, 10107, 10082, 10058, 10034, 10010, 9986,
+ 9963, 9939, 9916, 9892, 9869, 9846, 9823, 9800, 9777, 9754, 9732,
+ 9709, 9687, 9664, 9642, 9620, 9598, 9576, 9554, 9533, 9511, 9489,
+ 9468, 9447, 9425, 9404, 9383, 9362, 9341, 9321, 9300, 9279, 9259,
+ 9239, 9218, 9198, 9178, 9158, 9138, 9118, 9098, 9079, 9059, 9039,
+ 9020, 9001, 8981, 8962, 8943, 8924, 8905, 8886, 8867, 8849, 8830,
+ 8812, 8793, 8775, 8756, 8738, 8720, 8702, 8684, 8666, 8648, 8630,
+ 8613, 8595, 8577, 8560, 8542, 8525, 8508, 8490, 8473, 8456, 8439,
+ 8422, 8405, 8389, 8372, 8355, 8339, 8322, 8306, 8289, 8273, 8257,
+ 8240, 8224, 8208, 8192,
+};
+
+static int rockchip_vpu981_get_frame_index(struct hantro_ctx *ctx, int ref)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ u64 timestamp;
+ int i, idx = frame->ref_frame_idx[ref];
+
+ if (idx >= V4L2_AV1_TOTAL_REFS_PER_FRAME || idx < 0)
+ return AV1_INVALID_IDX;
+
+ timestamp = frame->reference_frame_ts[idx];
+ for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) {
+ if (!av1_dec->frame_refs[i].used)
+ continue;
+ if (av1_dec->frame_refs[i].timestamp == timestamp)
+ return i;
+ }
+
+ return AV1_INVALID_IDX;
+}
+
+static int rockchip_vpu981_get_order_hint(struct hantro_ctx *ctx, int ref)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ int idx = rockchip_vpu981_get_frame_index(ctx, ref);
+
+ if (idx != AV1_INVALID_IDX)
+ return av1_dec->frame_refs[idx].order_hint;
+
+ return 0;
+}
+
+static int rockchip_vpu981_av1_dec_frame_ref(struct hantro_ctx *ctx,
+ u64 timestamp)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ int i;
+
+ for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) {
+ int j;
+
+ if (av1_dec->frame_refs[i].used)
+ continue;
+
+ av1_dec->frame_refs[i].width = frame->frame_width_minus_1 + 1;
+ av1_dec->frame_refs[i].height = frame->frame_height_minus_1 + 1;
+ av1_dec->frame_refs[i].mi_cols = DIV_ROUND_UP(frame->frame_width_minus_1 + 1, 8);
+ av1_dec->frame_refs[i].mi_rows = DIV_ROUND_UP(frame->frame_height_minus_1 + 1, 8);
+ av1_dec->frame_refs[i].timestamp = timestamp;
+ av1_dec->frame_refs[i].frame_type = frame->frame_type;
+ av1_dec->frame_refs[i].order_hint = frame->order_hint;
+ if (!av1_dec->frame_refs[i].vb2_ref)
+ av1_dec->frame_refs[i].vb2_ref = hantro_get_dst_buf(ctx);
+
+ for (j = 0; j < V4L2_AV1_TOTAL_REFS_PER_FRAME; j++)
+ av1_dec->frame_refs[i].order_hints[j] = frame->order_hints[j];
+ av1_dec->frame_refs[i].used = true;
+ av1_dec->current_frame_index = i;
+
+ return i;
+ }
+
+ return AV1_INVALID_IDX;
+}
+
+static void rockchip_vpu981_av1_dec_frame_unref(struct hantro_ctx *ctx, int idx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+
+ if (idx >= 0)
+ av1_dec->frame_refs[idx].used = false;
+}
+
+static void rockchip_vpu981_av1_dec_clean_refs(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+
+ int ref, idx;
+
+ for (idx = 0; idx < AV1_MAX_FRAME_BUF_COUNT; idx++) {
+ u64 timestamp = av1_dec->frame_refs[idx].timestamp;
+ bool used = false;
+
+ if (!av1_dec->frame_refs[idx].used)
+ continue;
+
+ for (ref = 0; ref < V4L2_AV1_TOTAL_REFS_PER_FRAME; ref++) {
+ if (ctrls->frame->reference_frame_ts[ref] == timestamp)
+ used = true;
+ }
+
+ if (!used)
+ rockchip_vpu981_av1_dec_frame_unref(ctx, idx);
+ }
+}
+
+static size_t rockchip_vpu981_av1_dec_luma_size(struct hantro_ctx *ctx)
+{
+ return ctx->dst_fmt.width * ctx->dst_fmt.height * ctx->bit_depth / 8;
+}
+
+static size_t rockchip_vpu981_av1_dec_chroma_size(struct hantro_ctx *ctx)
+{
+ size_t cr_offset = rockchip_vpu981_av1_dec_luma_size(ctx);
+
+ return ALIGN((cr_offset * 3) / 2, 64);
+}
+
+static void rockchip_vpu981_av1_dec_tiles_free(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+
+ if (av1_dec->db_data_col.cpu)
+ dma_free_coherent(vpu->dev, av1_dec->db_data_col.size,
+ av1_dec->db_data_col.cpu,
+ av1_dec->db_data_col.dma);
+ av1_dec->db_data_col.cpu = NULL;
+
+ if (av1_dec->db_ctrl_col.cpu)
+ dma_free_coherent(vpu->dev, av1_dec->db_ctrl_col.size,
+ av1_dec->db_ctrl_col.cpu,
+ av1_dec->db_ctrl_col.dma);
+ av1_dec->db_ctrl_col.cpu = NULL;
+
+ if (av1_dec->cdef_col.cpu)
+ dma_free_coherent(vpu->dev, av1_dec->cdef_col.size,
+ av1_dec->cdef_col.cpu, av1_dec->cdef_col.dma);
+ av1_dec->cdef_col.cpu = NULL;
+
+ if (av1_dec->sr_col.cpu)
+ dma_free_coherent(vpu->dev, av1_dec->sr_col.size,
+ av1_dec->sr_col.cpu, av1_dec->sr_col.dma);
+ av1_dec->sr_col.cpu = NULL;
+
+ if (av1_dec->lr_col.cpu)
+ dma_free_coherent(vpu->dev, av1_dec->lr_col.size,
+ av1_dec->lr_col.cpu, av1_dec->lr_col.dma);
+ av1_dec->lr_col.cpu = NULL;
+}
+
+static int rockchip_vpu981_av1_dec_tiles_reallocate(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ unsigned int num_tile_cols = 1 << ctrls->tile_group_entry->tile_col;
+ unsigned int height = ALIGN(ctrls->frame->frame_height_minus_1 + 1, 64);
+ unsigned int height_in_sb = height / 64;
+ unsigned int stripe_num = ((height + 8) + 63) / 64;
+ size_t size;
+
+ if (av1_dec->db_data_col.size >=
+ ALIGN(height * 12 * ctx->bit_depth / 8, 128) * num_tile_cols)
+ return 0;
+
+ rockchip_vpu981_av1_dec_tiles_free(ctx);
+
+ size = ALIGN(height * 12 * ctx->bit_depth / 8, 128) * num_tile_cols;
+ av1_dec->db_data_col.cpu = dma_alloc_coherent(vpu->dev, size,
+ &av1_dec->db_data_col.dma,
+ GFP_KERNEL);
+ if (!av1_dec->db_data_col.cpu)
+ goto buffer_allocation_error;
+ av1_dec->db_data_col.size = size;
+
+ size = ALIGN(height * 2 * 16 / 4, 128) * num_tile_cols;
+ av1_dec->db_ctrl_col.cpu = dma_alloc_coherent(vpu->dev, size,
+ &av1_dec->db_ctrl_col.dma,
+ GFP_KERNEL);
+ if (!av1_dec->db_ctrl_col.cpu)
+ goto buffer_allocation_error;
+ av1_dec->db_ctrl_col.size = size;
+
+ size = ALIGN(height_in_sb * 44 * ctx->bit_depth * 16 / 8, 128) * num_tile_cols;
+ av1_dec->cdef_col.cpu = dma_alloc_coherent(vpu->dev, size,
+ &av1_dec->cdef_col.dma,
+ GFP_KERNEL);
+ if (!av1_dec->cdef_col.cpu)
+ goto buffer_allocation_error;
+ av1_dec->cdef_col.size = size;
+
+ size = ALIGN(height_in_sb * (3040 + 1280), 128) * num_tile_cols;
+ av1_dec->sr_col.cpu = dma_alloc_coherent(vpu->dev, size,
+ &av1_dec->sr_col.dma,
+ GFP_KERNEL);
+ if (!av1_dec->sr_col.cpu)
+ goto buffer_allocation_error;
+ av1_dec->sr_col.size = size;
+
+ size = ALIGN(stripe_num * 1536 * ctx->bit_depth / 8, 128) * num_tile_cols;
+ av1_dec->lr_col.cpu = dma_alloc_coherent(vpu->dev, size,
+ &av1_dec->lr_col.dma,
+ GFP_KERNEL);
+ if (!av1_dec->lr_col.cpu)
+ goto buffer_allocation_error;
+ av1_dec->lr_col.size = size;
+
+ av1_dec->num_tile_cols_allocated = num_tile_cols;
+ return 0;
+
+buffer_allocation_error:
+ rockchip_vpu981_av1_dec_tiles_free(ctx);
+ return -ENOMEM;
+}
+
+void rockchip_vpu981_av1_dec_exit(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+
+ if (av1_dec->global_model.cpu)
+ dma_free_coherent(vpu->dev, av1_dec->global_model.size,
+ av1_dec->global_model.cpu,
+ av1_dec->global_model.dma);
+ av1_dec->global_model.cpu = NULL;
+
+ if (av1_dec->tile_info.cpu)
+ dma_free_coherent(vpu->dev, av1_dec->tile_info.size,
+ av1_dec->tile_info.cpu,
+ av1_dec->tile_info.dma);
+ av1_dec->tile_info.cpu = NULL;
+
+ if (av1_dec->film_grain.cpu)
+ dma_free_coherent(vpu->dev, av1_dec->film_grain.size,
+ av1_dec->film_grain.cpu,
+ av1_dec->film_grain.dma);
+ av1_dec->film_grain.cpu = NULL;
+
+ if (av1_dec->prob_tbl.cpu)
+ dma_free_coherent(vpu->dev, av1_dec->prob_tbl.size,
+ av1_dec->prob_tbl.cpu, av1_dec->prob_tbl.dma);
+ av1_dec->prob_tbl.cpu = NULL;
+
+ if (av1_dec->prob_tbl_out.cpu)
+ dma_free_coherent(vpu->dev, av1_dec->prob_tbl_out.size,
+ av1_dec->prob_tbl_out.cpu,
+ av1_dec->prob_tbl_out.dma);
+ av1_dec->prob_tbl_out.cpu = NULL;
+
+ if (av1_dec->tile_buf.cpu)
+ dma_free_coherent(vpu->dev, av1_dec->tile_buf.size,
+ av1_dec->tile_buf.cpu, av1_dec->tile_buf.dma);
+ av1_dec->tile_buf.cpu = NULL;
+
+ rockchip_vpu981_av1_dec_tiles_free(ctx);
+}
+
+int rockchip_vpu981_av1_dec_init(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+
+ memset(av1_dec, 0, sizeof(*av1_dec));
+
+ av1_dec->global_model.cpu = dma_alloc_coherent(vpu->dev, GLOBAL_MODEL_SIZE,
+ &av1_dec->global_model.dma,
+ GFP_KERNEL);
+ if (!av1_dec->global_model.cpu)
+ return -ENOMEM;
+ av1_dec->global_model.size = GLOBAL_MODEL_SIZE;
+
+ av1_dec->tile_info.cpu = dma_alloc_coherent(vpu->dev, AV1_MAX_TILES,
+ &av1_dec->tile_info.dma,
+ GFP_KERNEL);
+ if (!av1_dec->tile_info.cpu)
+ return -ENOMEM;
+ av1_dec->tile_info.size = AV1_MAX_TILES;
+
+ av1_dec->film_grain.cpu = dma_alloc_coherent(vpu->dev,
+ ALIGN(sizeof(struct rockchip_av1_film_grain), 2048),
+ &av1_dec->film_grain.dma,
+ GFP_KERNEL);
+ if (!av1_dec->film_grain.cpu)
+ return -ENOMEM;
+ av1_dec->film_grain.size = ALIGN(sizeof(struct rockchip_av1_film_grain), 2048);
+
+ av1_dec->prob_tbl.cpu = dma_alloc_coherent(vpu->dev,
+ ALIGN(sizeof(struct av1cdfs), 2048),
+ &av1_dec->prob_tbl.dma,
+ GFP_KERNEL);
+ if (!av1_dec->prob_tbl.cpu)
+ return -ENOMEM;
+ av1_dec->prob_tbl.size = ALIGN(sizeof(struct av1cdfs), 2048);
+
+ av1_dec->prob_tbl_out.cpu = dma_alloc_coherent(vpu->dev,
+ ALIGN(sizeof(struct av1cdfs), 2048),
+ &av1_dec->prob_tbl_out.dma,
+ GFP_KERNEL);
+ if (!av1_dec->prob_tbl_out.cpu)
+ return -ENOMEM;
+ av1_dec->prob_tbl_out.size = ALIGN(sizeof(struct av1cdfs), 2048);
+ av1_dec->cdfs = &av1_dec->default_cdfs;
+ av1_dec->cdfs_ndvc = &av1_dec->default_cdfs_ndvc;
+
+ rockchip_av1_set_default_cdfs(av1_dec->cdfs, av1_dec->cdfs_ndvc);
+
+ av1_dec->tile_buf.cpu = dma_alloc_coherent(vpu->dev,
+ AV1_TILE_SIZE,
+ &av1_dec->tile_buf.dma,
+ GFP_KERNEL);
+ if (!av1_dec->tile_buf.cpu)
+ return -ENOMEM;
+ av1_dec->tile_buf.size = AV1_TILE_SIZE;
+
+ return 0;
+}
+
+static int rockchip_vpu981_av1_dec_prepare_run(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+
+ ctrls->sequence = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_SEQUENCE);
+ if (WARN_ON(!ctrls->sequence))
+ return -EINVAL;
+
+ ctrls->tile_group_entry =
+ hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY);
+ if (WARN_ON(!ctrls->tile_group_entry))
+ return -EINVAL;
+
+ ctrls->frame = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_FRAME);
+ if (WARN_ON(!ctrls->frame))
+ return -EINVAL;
+
+ ctrls->film_grain =
+ hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_FILM_GRAIN);
+
+ return rockchip_vpu981_av1_dec_tiles_reallocate(ctx);
+}
+
+static inline int rockchip_vpu981_av1_dec_get_msb(u32 n)
+{
+ if (n == 0)
+ return 0;
+ return 31 ^ __builtin_clz(n);
+}
+
+static short rockchip_vpu981_av1_dec_resolve_divisor_32(u32 d, short *shift)
+{
+ int f;
+ u64 e;
+
+ *shift = rockchip_vpu981_av1_dec_get_msb(d);
+ /* e is obtained from D after resetting the most significant 1 bit. */
+ e = d - ((u32)1 << *shift);
+ /* Get the most significant DIV_LUT_BITS (8) bits of e into f */
+ if (*shift > DIV_LUT_BITS)
+ f = AV1_DIV_ROUND_UP_POW2(e, *shift - DIV_LUT_BITS);
+ else
+ f = e << (DIV_LUT_BITS - *shift);
+ if (f > DIV_LUT_NUM)
+ return -1;
+ *shift += DIV_LUT_PREC_BITS;
+ /* Use f as lookup into the precomputed table of multipliers */
+ return div_lut[f];
+}
+
+static void
+rockchip_vpu981_av1_dec_get_shear_params(const u32 *params, s64 *alpha,
+ s64 *beta, s64 *gamma, s64 *delta)
+{
+ const int *mat = params;
+ short shift;
+ short y;
+ long long gv, dv;
+
+ if (mat[2] <= 0)
+ return;
+
+ *alpha = clamp_val(mat[2] - (1 << WARPEDMODEL_PREC_BITS), S16_MIN, S16_MAX);
+ *beta = clamp_val(mat[3], S16_MIN, S16_MAX);
+
+ y = rockchip_vpu981_av1_dec_resolve_divisor_32(abs(mat[2]), &shift) * (mat[2] < 0 ? -1 : 1);
+
+ gv = ((long long)mat[4] * (1 << WARPEDMODEL_PREC_BITS)) * y;
+
+ *gamma = clamp_val((int)AV1_DIV_ROUND_UP_POW2_SIGNED(gv, shift), S16_MIN, S16_MAX);
+
+ dv = ((long long)mat[3] * mat[4]) * y;
+ *delta = clamp_val(mat[5] -
+ (int)AV1_DIV_ROUND_UP_POW2_SIGNED(dv, shift) - (1 << WARPEDMODEL_PREC_BITS),
+ S16_MIN, S16_MAX);
+
+ *alpha = AV1_DIV_ROUND_UP_POW2_SIGNED(*alpha, WARP_PARAM_REDUCE_BITS)
+ * (1 << WARP_PARAM_REDUCE_BITS);
+ *beta = AV1_DIV_ROUND_UP_POW2_SIGNED(*beta, WARP_PARAM_REDUCE_BITS)
+ * (1 << WARP_PARAM_REDUCE_BITS);
+ *gamma = AV1_DIV_ROUND_UP_POW2_SIGNED(*gamma, WARP_PARAM_REDUCE_BITS)
+ * (1 << WARP_PARAM_REDUCE_BITS);
+ *delta = AV1_DIV_ROUND_UP_POW2_SIGNED(*delta, WARP_PARAM_REDUCE_BITS)
+ * (1 << WARP_PARAM_REDUCE_BITS);
+}
+
+static void rockchip_vpu981_av1_dec_set_global_model(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ const struct v4l2_av1_global_motion *gm = &frame->global_motion;
+ u8 *dst = av1_dec->global_model.cpu;
+ struct hantro_dev *vpu = ctx->dev;
+ int ref_frame, i;
+
+ memset(dst, 0, GLOBAL_MODEL_SIZE);
+ for (ref_frame = 0; ref_frame < V4L2_AV1_REFS_PER_FRAME; ++ref_frame) {
+ s64 alpha = 0, beta = 0, gamma = 0, delta = 0;
+
+ for (i = 0; i < 6; ++i) {
+ if (i == 2)
+ *(s32 *)dst =
+ gm->params[V4L2_AV1_REF_LAST_FRAME + ref_frame][3];
+ else if (i == 3)
+ *(s32 *)dst =
+ gm->params[V4L2_AV1_REF_LAST_FRAME + ref_frame][2];
+ else
+ *(s32 *)dst =
+ gm->params[V4L2_AV1_REF_LAST_FRAME + ref_frame][i];
+ dst += 4;
+ }
+
+ if (gm->type[V4L2_AV1_REF_LAST_FRAME + ref_frame] <= V4L2_AV1_WARP_MODEL_AFFINE)
+ rockchip_vpu981_av1_dec_get_shear_params(&gm->params[V4L2_AV1_REF_LAST_FRAME + ref_frame][0],
+ &alpha, &beta, &gamma, &delta);
+
+ *(s16 *)dst = alpha;
+ dst += 2;
+ *(s16 *)dst = beta;
+ dst += 2;
+ *(s16 *)dst = gamma;
+ dst += 2;
+ *(s16 *)dst = delta;
+ dst += 2;
+ }
+
+ hantro_write_addr(vpu, AV1_GLOBAL_MODEL, av1_dec->global_model.dma);
+}
+
+static int rockchip_vpu981_av1_tile_log2(int target)
+{
+ int k;
+
+ /*
+ * returns the smallest value for k such that 1 << k is greater
+ * than or equal to target
+ */
+ for (k = 0; (1 << k) < target; k++);
+
+ return k;
+}
+
+static void rockchip_vpu981_av1_dec_set_tile_info(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_av1_tile_info *tile_info = &ctrls->frame->tile_info;
+ const struct v4l2_ctrl_av1_tile_group_entry *group_entry =
+ ctrls->tile_group_entry;
+ int context_update_y =
+ tile_info->context_update_tile_id / tile_info->tile_cols;
+ int context_update_x =
+ tile_info->context_update_tile_id % tile_info->tile_cols;
+ int context_update_tile_id =
+ context_update_x * tile_info->tile_rows + context_update_y;
+ u8 *dst = av1_dec->tile_info.cpu;
+ struct hantro_dev *vpu = ctx->dev;
+ int tile0, tile1;
+
+ memset(dst, 0, av1_dec->tile_info.size);
+
+ for (tile0 = 0; tile0 < tile_info->tile_cols; tile0++) {
+ for (tile1 = 0; tile1 < tile_info->tile_rows; tile1++) {
+ int tile_id = tile1 * tile_info->tile_cols + tile0;
+ u32 start, end;
+ u32 y0 =
+ tile_info->height_in_sbs_minus_1[tile1] + 1;
+ u32 x0 = tile_info->width_in_sbs_minus_1[tile0] + 1;
+
+ /* tile size in SB units (width,height) */
+ *dst++ = x0;
+ *dst++ = 0;
+ *dst++ = 0;
+ *dst++ = 0;
+ *dst++ = y0;
+ *dst++ = 0;
+ *dst++ = 0;
+ *dst++ = 0;
+
+ /* tile start position */
+ start = group_entry[tile_id].tile_offset - group_entry[0].tile_offset;
+ *dst++ = start & 255;
+ *dst++ = (start >> 8) & 255;
+ *dst++ = (start >> 16) & 255;
+ *dst++ = (start >> 24) & 255;
+
+ /* number of bytes in tile data */
+ end = start + group_entry[tile_id].tile_size;
+ *dst++ = end & 255;
+ *dst++ = (end >> 8) & 255;
+ *dst++ = (end >> 16) & 255;
+ *dst++ = (end >> 24) & 255;
+ }
+ }
+
+ hantro_reg_write(vpu, &av1_multicore_expect_context_update, !!(context_update_x == 0));
+ hantro_reg_write(vpu, &av1_tile_enable,
+ !!((tile_info->tile_cols > 1) || (tile_info->tile_rows > 1)));
+ hantro_reg_write(vpu, &av1_num_tile_cols_8k, tile_info->tile_cols);
+ hantro_reg_write(vpu, &av1_num_tile_rows_8k, tile_info->tile_rows);
+ hantro_reg_write(vpu, &av1_context_update_tile_id, context_update_tile_id);
+ hantro_reg_write(vpu, &av1_tile_transpose, 1);
+ if (rockchip_vpu981_av1_tile_log2(tile_info->tile_cols) ||
+ rockchip_vpu981_av1_tile_log2(tile_info->tile_rows))
+ hantro_reg_write(vpu, &av1_dec_tile_size_mag, tile_info->tile_size_bytes - 1);
+ else
+ hantro_reg_write(vpu, &av1_dec_tile_size_mag, 3);
+
+ hantro_write_addr(vpu, AV1_TILE_BASE, av1_dec->tile_info.dma);
+}
+
+static int rockchip_vpu981_av1_dec_get_dist(struct hantro_ctx *ctx,
+ int a, int b)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ int bits = ctrls->sequence->order_hint_bits - 1;
+ int diff, m;
+
+ if (!ctrls->sequence->order_hint_bits)
+ return 0;
+
+ diff = a - b;
+ m = 1 << bits;
+ diff = (diff & (m - 1)) - (diff & m);
+
+ return diff;
+}
+
+static void rockchip_vpu981_av1_dec_set_frame_sign_bias(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ const struct v4l2_ctrl_av1_sequence *sequence = ctrls->sequence;
+ int i;
+
+ if (!sequence->order_hint_bits || IS_INTRA(frame->frame_type)) {
+ for (i = 0; i < V4L2_AV1_TOTAL_REFS_PER_FRAME; i++)
+ av1_dec->ref_frame_sign_bias[i] = 0;
+
+ return;
+ }
+ // Identify the nearest forward and backward references.
+ for (i = 0; i < V4L2_AV1_TOTAL_REFS_PER_FRAME - 1; i++) {
+ if (rockchip_vpu981_get_frame_index(ctx, i) >= 0) {
+ int rel_off =
+ rockchip_vpu981_av1_dec_get_dist(ctx,
+ rockchip_vpu981_get_order_hint(ctx, i),
+ frame->order_hint);
+ av1_dec->ref_frame_sign_bias[i + 1] = (rel_off <= 0) ? 0 : 1;
+ }
+ }
+}
+
+static bool
+rockchip_vpu981_av1_dec_set_ref(struct hantro_ctx *ctx, int ref, int idx,
+ int width, int height)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ struct hantro_dev *vpu = ctx->dev;
+ struct hantro_decoded_buffer *dst;
+ dma_addr_t luma_addr, chroma_addr, mv_addr = 0;
+ size_t cr_offset = rockchip_vpu981_av1_dec_luma_size(ctx);
+ size_t mv_offset = rockchip_vpu981_av1_dec_chroma_size(ctx);
+ int cur_width = frame->frame_width_minus_1 + 1;
+ int cur_height = frame->frame_height_minus_1 + 1;
+ int scale_width =
+ ((width << AV1_REF_SCALE_SHIFT) + cur_width / 2) / cur_width;
+ int scale_height =
+ ((height << AV1_REF_SCALE_SHIFT) + cur_height / 2) / cur_height;
+
+ switch (ref) {
+ case 0:
+ hantro_reg_write(vpu, &av1_ref0_height, height);
+ hantro_reg_write(vpu, &av1_ref0_width, width);
+ hantro_reg_write(vpu, &av1_ref0_ver_scale, scale_width);
+ hantro_reg_write(vpu, &av1_ref0_hor_scale, scale_height);
+ break;
+ case 1:
+ hantro_reg_write(vpu, &av1_ref1_height, height);
+ hantro_reg_write(vpu, &av1_ref1_width, width);
+ hantro_reg_write(vpu, &av1_ref1_ver_scale, scale_width);
+ hantro_reg_write(vpu, &av1_ref1_hor_scale, scale_height);
+ break;
+ case 2:
+ hantro_reg_write(vpu, &av1_ref2_height, height);
+ hantro_reg_write(vpu, &av1_ref2_width, width);
+ hantro_reg_write(vpu, &av1_ref2_ver_scale, scale_width);
+ hantro_reg_write(vpu, &av1_ref2_hor_scale, scale_height);
+ break;
+ case 3:
+ hantro_reg_write(vpu, &av1_ref3_height, height);
+ hantro_reg_write(vpu, &av1_ref3_width, width);
+ hantro_reg_write(vpu, &av1_ref3_ver_scale, scale_width);
+ hantro_reg_write(vpu, &av1_ref3_hor_scale, scale_height);
+ break;
+ case 4:
+ hantro_reg_write(vpu, &av1_ref4_height, height);
+ hantro_reg_write(vpu, &av1_ref4_width, width);
+ hantro_reg_write(vpu, &av1_ref4_ver_scale, scale_width);
+ hantro_reg_write(vpu, &av1_ref4_hor_scale, scale_height);
+ break;
+ case 5:
+ hantro_reg_write(vpu, &av1_ref5_height, height);
+ hantro_reg_write(vpu, &av1_ref5_width, width);
+ hantro_reg_write(vpu, &av1_ref5_ver_scale, scale_width);
+ hantro_reg_write(vpu, &av1_ref5_hor_scale, scale_height);
+ break;
+ case 6:
+ hantro_reg_write(vpu, &av1_ref6_height, height);
+ hantro_reg_write(vpu, &av1_ref6_width, width);
+ hantro_reg_write(vpu, &av1_ref6_ver_scale, scale_width);
+ hantro_reg_write(vpu, &av1_ref6_hor_scale, scale_height);
+ break;
+ default:
+ pr_warn("AV1 invalid reference frame index\n");
+ }
+
+ dst = vb2_to_hantro_decoded_buf(&av1_dec->frame_refs[idx].vb2_ref->vb2_buf);
+ luma_addr = hantro_get_dec_buf_addr(ctx, &dst->base.vb.vb2_buf);
+ chroma_addr = luma_addr + cr_offset;
+ mv_addr = luma_addr + mv_offset;
+
+ hantro_write_addr(vpu, AV1_REFERENCE_Y(ref), luma_addr);
+ hantro_write_addr(vpu, AV1_REFERENCE_CB(ref), chroma_addr);
+ hantro_write_addr(vpu, AV1_REFERENCE_MV(ref), mv_addr);
+
+ return (scale_width != (1 << AV1_REF_SCALE_SHIFT)) ||
+ (scale_height != (1 << AV1_REF_SCALE_SHIFT));
+}
+
+static void rockchip_vpu981_av1_dec_set_sign_bias(struct hantro_ctx *ctx,
+ int ref, int val)
+{
+ struct hantro_dev *vpu = ctx->dev;
+
+ switch (ref) {
+ case 0:
+ hantro_reg_write(vpu, &av1_ref0_sign_bias, val);
+ break;
+ case 1:
+ hantro_reg_write(vpu, &av1_ref1_sign_bias, val);
+ break;
+ case 2:
+ hantro_reg_write(vpu, &av1_ref2_sign_bias, val);
+ break;
+ case 3:
+ hantro_reg_write(vpu, &av1_ref3_sign_bias, val);
+ break;
+ case 4:
+ hantro_reg_write(vpu, &av1_ref4_sign_bias, val);
+ break;
+ case 5:
+ hantro_reg_write(vpu, &av1_ref5_sign_bias, val);
+ break;
+ case 6:
+ hantro_reg_write(vpu, &av1_ref6_sign_bias, val);
+ break;
+ default:
+ pr_warn("AV1 invalid sign bias index\n");
+ break;
+ }
+}
+
+static void rockchip_vpu981_av1_dec_set_segmentation(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ const struct v4l2_av1_segmentation *seg = &frame->segmentation;
+ u32 segval[V4L2_AV1_MAX_SEGMENTS][V4L2_AV1_SEG_LVL_MAX] = { 0 };
+ struct hantro_dev *vpu = ctx->dev;
+ u8 segsign = 0, preskip_segid = 0, last_active_seg = 0, i, j;
+
+ if (!!(seg->flags & V4L2_AV1_SEGMENTATION_FLAG_ENABLED) &&
+ frame->primary_ref_frame < V4L2_AV1_REFS_PER_FRAME) {
+ int idx = rockchip_vpu981_get_frame_index(ctx, frame->primary_ref_frame);
+
+ if (idx >= 0) {
+ dma_addr_t luma_addr, mv_addr = 0;
+ struct hantro_decoded_buffer *seg;
+ size_t mv_offset = rockchip_vpu981_av1_dec_chroma_size(ctx);
+
+ seg = vb2_to_hantro_decoded_buf(&av1_dec->frame_refs[idx].vb2_ref->vb2_buf);
+ luma_addr = hantro_get_dec_buf_addr(ctx, &seg->base.vb.vb2_buf);
+ mv_addr = luma_addr + mv_offset;
+
+ hantro_write_addr(vpu, AV1_SEGMENTATION, mv_addr);
+ hantro_reg_write(vpu, &av1_use_temporal3_mvs, 1);
+ }
+ }
+
+ hantro_reg_write(vpu, &av1_segment_temp_upd_e,
+ !!(seg->flags & V4L2_AV1_SEGMENTATION_FLAG_TEMPORAL_UPDATE));
+ hantro_reg_write(vpu, &av1_segment_upd_e,
+ !!(seg->flags & V4L2_AV1_SEGMENTATION_FLAG_UPDATE_MAP));
+ hantro_reg_write(vpu, &av1_segment_e,
+ !!(seg->flags & V4L2_AV1_SEGMENTATION_FLAG_ENABLED));
+
+ hantro_reg_write(vpu, &av1_error_resilient,
+ !!(frame->flags & V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE));
+
+ if (IS_INTRA(frame->frame_type) ||
+ !!(frame->flags & V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE)) {
+ hantro_reg_write(vpu, &av1_use_temporal3_mvs, 0);
+ }
+
+ if (seg->flags & V4L2_AV1_SEGMENTATION_FLAG_ENABLED) {
+ int s;
+
+ for (s = 0; s < V4L2_AV1_MAX_SEGMENTS; s++) {
+ if (seg->feature_enabled[s] &
+ V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_Q)) {
+ segval[s][V4L2_AV1_SEG_LVL_ALT_Q] =
+ clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_Q]),
+ 0, 255);
+ segsign |=
+ (seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_Q] < 0) << s;
+ }
+
+ if (seg->feature_enabled[s] &
+ V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_LF_Y_V))
+ segval[s][V4L2_AV1_SEG_LVL_ALT_LF_Y_V] =
+ clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]),
+ -63, 63);
+
+ if (seg->feature_enabled[s] &
+ V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_LF_Y_H))
+ segval[s][V4L2_AV1_SEG_LVL_ALT_LF_Y_H] =
+ clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]),
+ -63, 63);
+
+ if (seg->feature_enabled[s] &
+ V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_LF_U))
+ segval[s][V4L2_AV1_SEG_LVL_ALT_LF_U] =
+ clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_LF_U]),
+ -63, 63);
+
+ if (seg->feature_enabled[s] &
+ V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_LF_V))
+ segval[s][V4L2_AV1_SEG_LVL_ALT_LF_V] =
+ clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_LF_V]),
+ -63, 63);
+
+ if (frame->frame_type && seg->feature_enabled[s] &
+ V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_REF_FRAME))
+ segval[s][V4L2_AV1_SEG_LVL_REF_FRAME]++;
+
+ if (seg->feature_enabled[s] &
+ V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_REF_SKIP))
+ segval[s][V4L2_AV1_SEG_LVL_REF_SKIP] = 1;
+
+ if (seg->feature_enabled[s] &
+ V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_REF_GLOBALMV))
+ segval[s][V4L2_AV1_SEG_LVL_REF_GLOBALMV] = 1;
+ }
+ }
+
+ for (i = 0; i < V4L2_AV1_MAX_SEGMENTS; i++) {
+ for (j = 0; j < V4L2_AV1_SEG_LVL_MAX; j++) {
+ if (seg->feature_enabled[i]
+ & V4L2_AV1_SEGMENT_FEATURE_ENABLED(j)) {
+ preskip_segid |= (j >= V4L2_AV1_SEG_LVL_REF_FRAME);
+ last_active_seg = max(i, last_active_seg);
+ }
+ }
+ }
+
+ hantro_reg_write(vpu, &av1_last_active_seg, last_active_seg);
+ hantro_reg_write(vpu, &av1_preskip_segid, preskip_segid);
+
+ hantro_reg_write(vpu, &av1_seg_quant_sign, segsign);
+
+ /* Write QP, filter level, ref frame and skip for every segment */
+ hantro_reg_write(vpu, &av1_quant_seg0,
+ segval[0][V4L2_AV1_SEG_LVL_ALT_Q]);
+ hantro_reg_write(vpu, &av1_filt_level_delta0_seg0,
+ segval[0][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]);
+ hantro_reg_write(vpu, &av1_filt_level_delta1_seg0,
+ segval[0][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]);
+ hantro_reg_write(vpu, &av1_filt_level_delta2_seg0,
+ segval[0][V4L2_AV1_SEG_LVL_ALT_LF_U]);
+ hantro_reg_write(vpu, &av1_filt_level_delta3_seg0,
+ segval[0][V4L2_AV1_SEG_LVL_ALT_LF_V]);
+ hantro_reg_write(vpu, &av1_refpic_seg0,
+ segval[0][V4L2_AV1_SEG_LVL_REF_FRAME]);
+ hantro_reg_write(vpu, &av1_skip_seg0,
+ segval[0][V4L2_AV1_SEG_LVL_REF_SKIP]);
+ hantro_reg_write(vpu, &av1_global_mv_seg0,
+ segval[0][V4L2_AV1_SEG_LVL_REF_GLOBALMV]);
+
+ hantro_reg_write(vpu, &av1_quant_seg1,
+ segval[1][V4L2_AV1_SEG_LVL_ALT_Q]);
+ hantro_reg_write(vpu, &av1_filt_level_delta0_seg1,
+ segval[1][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]);
+ hantro_reg_write(vpu, &av1_filt_level_delta1_seg1,
+ segval[1][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]);
+ hantro_reg_write(vpu, &av1_filt_level_delta2_seg1,
+ segval[1][V4L2_AV1_SEG_LVL_ALT_LF_U]);
+ hantro_reg_write(vpu, &av1_filt_level_delta3_seg1,
+ segval[1][V4L2_AV1_SEG_LVL_ALT_LF_V]);
+ hantro_reg_write(vpu, &av1_refpic_seg1,
+ segval[1][V4L2_AV1_SEG_LVL_REF_FRAME]);
+ hantro_reg_write(vpu, &av1_skip_seg1,
+ segval[1][V4L2_AV1_SEG_LVL_REF_SKIP]);
+ hantro_reg_write(vpu, &av1_global_mv_seg1,
+ segval[1][V4L2_AV1_SEG_LVL_REF_GLOBALMV]);
+
+ hantro_reg_write(vpu, &av1_quant_seg2,
+ segval[2][V4L2_AV1_SEG_LVL_ALT_Q]);
+ hantro_reg_write(vpu, &av1_filt_level_delta0_seg2,
+ segval[2][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]);
+ hantro_reg_write(vpu, &av1_filt_level_delta1_seg2,
+ segval[2][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]);
+ hantro_reg_write(vpu, &av1_filt_level_delta2_seg2,
+ segval[2][V4L2_AV1_SEG_LVL_ALT_LF_U]);
+ hantro_reg_write(vpu, &av1_filt_level_delta3_seg2,
+ segval[2][V4L2_AV1_SEG_LVL_ALT_LF_V]);
+ hantro_reg_write(vpu, &av1_refpic_seg2,
+ segval[2][V4L2_AV1_SEG_LVL_REF_FRAME]);
+ hantro_reg_write(vpu, &av1_skip_seg2,
+ segval[2][V4L2_AV1_SEG_LVL_REF_SKIP]);
+ hantro_reg_write(vpu, &av1_global_mv_seg2,
+ segval[2][V4L2_AV1_SEG_LVL_REF_GLOBALMV]);
+
+ hantro_reg_write(vpu, &av1_quant_seg3,
+ segval[3][V4L2_AV1_SEG_LVL_ALT_Q]);
+ hantro_reg_write(vpu, &av1_filt_level_delta0_seg3,
+ segval[3][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]);
+ hantro_reg_write(vpu, &av1_filt_level_delta1_seg3,
+ segval[3][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]);
+ hantro_reg_write(vpu, &av1_filt_level_delta2_seg3,
+ segval[3][V4L2_AV1_SEG_LVL_ALT_LF_U]);
+ hantro_reg_write(vpu, &av1_filt_level_delta3_seg3,
+ segval[3][V4L2_AV1_SEG_LVL_ALT_LF_V]);
+ hantro_reg_write(vpu, &av1_refpic_seg3,
+ segval[3][V4L2_AV1_SEG_LVL_REF_FRAME]);
+ hantro_reg_write(vpu, &av1_skip_seg3,
+ segval[3][V4L2_AV1_SEG_LVL_REF_SKIP]);
+ hantro_reg_write(vpu, &av1_global_mv_seg3,
+ segval[3][V4L2_AV1_SEG_LVL_REF_GLOBALMV]);
+
+ hantro_reg_write(vpu, &av1_quant_seg4,
+ segval[4][V4L2_AV1_SEG_LVL_ALT_Q]);
+ hantro_reg_write(vpu, &av1_filt_level_delta0_seg4,
+ segval[4][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]);
+ hantro_reg_write(vpu, &av1_filt_level_delta1_seg4,
+ segval[4][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]);
+ hantro_reg_write(vpu, &av1_filt_level_delta2_seg4,
+ segval[4][V4L2_AV1_SEG_LVL_ALT_LF_U]);
+ hantro_reg_write(vpu, &av1_filt_level_delta3_seg4,
+ segval[4][V4L2_AV1_SEG_LVL_ALT_LF_V]);
+ hantro_reg_write(vpu, &av1_refpic_seg4,
+ segval[4][V4L2_AV1_SEG_LVL_REF_FRAME]);
+ hantro_reg_write(vpu, &av1_skip_seg4,
+ segval[4][V4L2_AV1_SEG_LVL_REF_SKIP]);
+ hantro_reg_write(vpu, &av1_global_mv_seg4,
+ segval[4][V4L2_AV1_SEG_LVL_REF_GLOBALMV]);
+
+ hantro_reg_write(vpu, &av1_quant_seg5,
+ segval[5][V4L2_AV1_SEG_LVL_ALT_Q]);
+ hantro_reg_write(vpu, &av1_filt_level_delta0_seg5,
+ segval[5][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]);
+ hantro_reg_write(vpu, &av1_filt_level_delta1_seg5,
+ segval[5][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]);
+ hantro_reg_write(vpu, &av1_filt_level_delta2_seg5,
+ segval[5][V4L2_AV1_SEG_LVL_ALT_LF_U]);
+ hantro_reg_write(vpu, &av1_filt_level_delta3_seg5,
+ segval[5][V4L2_AV1_SEG_LVL_ALT_LF_V]);
+ hantro_reg_write(vpu, &av1_refpic_seg5,
+ segval[5][V4L2_AV1_SEG_LVL_REF_FRAME]);
+ hantro_reg_write(vpu, &av1_skip_seg5,
+ segval[5][V4L2_AV1_SEG_LVL_REF_SKIP]);
+ hantro_reg_write(vpu, &av1_global_mv_seg5,
+ segval[5][V4L2_AV1_SEG_LVL_REF_GLOBALMV]);
+
+ hantro_reg_write(vpu, &av1_quant_seg6,
+ segval[6][V4L2_AV1_SEG_LVL_ALT_Q]);
+ hantro_reg_write(vpu, &av1_filt_level_delta0_seg6,
+ segval[6][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]);
+ hantro_reg_write(vpu, &av1_filt_level_delta1_seg6,
+ segval[6][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]);
+ hantro_reg_write(vpu, &av1_filt_level_delta2_seg6,
+ segval[6][V4L2_AV1_SEG_LVL_ALT_LF_U]);
+ hantro_reg_write(vpu, &av1_filt_level_delta3_seg6,
+ segval[6][V4L2_AV1_SEG_LVL_ALT_LF_V]);
+ hantro_reg_write(vpu, &av1_refpic_seg6,
+ segval[6][V4L2_AV1_SEG_LVL_REF_FRAME]);
+ hantro_reg_write(vpu, &av1_skip_seg6,
+ segval[6][V4L2_AV1_SEG_LVL_REF_SKIP]);
+ hantro_reg_write(vpu, &av1_global_mv_seg6,
+ segval[6][V4L2_AV1_SEG_LVL_REF_GLOBALMV]);
+
+ hantro_reg_write(vpu, &av1_quant_seg7,
+ segval[7][V4L2_AV1_SEG_LVL_ALT_Q]);
+ hantro_reg_write(vpu, &av1_filt_level_delta0_seg7,
+ segval[7][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]);
+ hantro_reg_write(vpu, &av1_filt_level_delta1_seg7,
+ segval[7][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]);
+ hantro_reg_write(vpu, &av1_filt_level_delta2_seg7,
+ segval[7][V4L2_AV1_SEG_LVL_ALT_LF_U]);
+ hantro_reg_write(vpu, &av1_filt_level_delta3_seg7,
+ segval[7][V4L2_AV1_SEG_LVL_ALT_LF_V]);
+ hantro_reg_write(vpu, &av1_refpic_seg7,
+ segval[7][V4L2_AV1_SEG_LVL_REF_FRAME]);
+ hantro_reg_write(vpu, &av1_skip_seg7,
+ segval[7][V4L2_AV1_SEG_LVL_REF_SKIP]);
+ hantro_reg_write(vpu, &av1_global_mv_seg7,
+ segval[7][V4L2_AV1_SEG_LVL_REF_GLOBALMV]);
+}
+
+static bool rockchip_vpu981_av1_dec_is_lossless(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ const struct v4l2_av1_segmentation *segmentation = &frame->segmentation;
+ const struct v4l2_av1_quantization *quantization = &frame->quantization;
+ int i;
+
+ for (i = 0; i < V4L2_AV1_MAX_SEGMENTS; i++) {
+ int qindex = quantization->base_q_idx;
+
+ if (segmentation->feature_enabled[i] &
+ V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_Q)) {
+ qindex += segmentation->feature_data[i][V4L2_AV1_SEG_LVL_ALT_Q];
+ }
+ qindex = clamp(qindex, 0, 255);
+
+ if (qindex ||
+ quantization->delta_q_y_dc ||
+ quantization->delta_q_u_dc ||
+ quantization->delta_q_u_ac ||
+ quantization->delta_q_v_dc ||
+ quantization->delta_q_v_ac)
+ return false;
+ }
+ return true;
+}
+
+static void rockchip_vpu981_av1_dec_set_loopfilter(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ const struct v4l2_av1_loop_filter *loop_filter = &frame->loop_filter;
+ bool filtering_dis = (loop_filter->level[0] == 0) && (loop_filter->level[1] == 0);
+ struct hantro_dev *vpu = ctx->dev;
+
+ hantro_reg_write(vpu, &av1_filtering_dis, filtering_dis);
+ hantro_reg_write(vpu, &av1_filt_level_base_gt32, loop_filter->level[0] > 32);
+ hantro_reg_write(vpu, &av1_filt_sharpness, loop_filter->sharpness);
+
+ hantro_reg_write(vpu, &av1_filt_level0, loop_filter->level[0]);
+ hantro_reg_write(vpu, &av1_filt_level1, loop_filter->level[1]);
+ hantro_reg_write(vpu, &av1_filt_level2, loop_filter->level[2]);
+ hantro_reg_write(vpu, &av1_filt_level3, loop_filter->level[3]);
+
+ if (loop_filter->flags & V4L2_AV1_LOOP_FILTER_FLAG_DELTA_ENABLED &&
+ !rockchip_vpu981_av1_dec_is_lossless(ctx) &&
+ !(frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC)) {
+ hantro_reg_write(vpu, &av1_filt_ref_adj_0,
+ loop_filter->ref_deltas[0]);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_1,
+ loop_filter->ref_deltas[1]);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_2,
+ loop_filter->ref_deltas[2]);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_3,
+ loop_filter->ref_deltas[3]);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_4,
+ loop_filter->ref_deltas[4]);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_5,
+ loop_filter->ref_deltas[5]);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_6,
+ loop_filter->ref_deltas[6]);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_7,
+ loop_filter->ref_deltas[7]);
+ hantro_reg_write(vpu, &av1_filt_mb_adj_0,
+ loop_filter->mode_deltas[0]);
+ hantro_reg_write(vpu, &av1_filt_mb_adj_1,
+ loop_filter->mode_deltas[1]);
+ } else {
+ hantro_reg_write(vpu, &av1_filt_ref_adj_0, 0);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_1, 0);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_2, 0);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_3, 0);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_4, 0);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_5, 0);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_6, 0);
+ hantro_reg_write(vpu, &av1_filt_ref_adj_7, 0);
+ hantro_reg_write(vpu, &av1_filt_mb_adj_0, 0);
+ hantro_reg_write(vpu, &av1_filt_mb_adj_1, 0);
+ }
+
+ hantro_write_addr(vpu, AV1_DB_DATA_COL, av1_dec->db_data_col.dma);
+ hantro_write_addr(vpu, AV1_DB_CTRL_COL, av1_dec->db_ctrl_col.dma);
+}
+
+static void rockchip_vpu981_av1_dec_update_prob(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ bool frame_is_intra = IS_INTRA(frame->frame_type);
+ struct av1cdfs *out_cdfs = (struct av1cdfs *)av1_dec->prob_tbl_out.cpu;
+ int i;
+
+ if (frame->flags & V4L2_AV1_FRAME_FLAG_DISABLE_FRAME_END_UPDATE_CDF)
+ return;
+
+ for (i = 0; i < NUM_REF_FRAMES; i++) {
+ if (frame->refresh_frame_flags & BIT(i)) {
+ struct mvcdfs stored_mv_cdf;
+
+ rockchip_av1_get_cdfs(ctx, i);
+ stored_mv_cdf = av1_dec->cdfs->mv_cdf;
+ *av1_dec->cdfs = *out_cdfs;
+ if (frame_is_intra) {
+ av1_dec->cdfs->mv_cdf = stored_mv_cdf;
+ *av1_dec->cdfs_ndvc = out_cdfs->mv_cdf;
+ }
+ rockchip_av1_store_cdfs(ctx,
+ frame->refresh_frame_flags);
+ break;
+ }
+ }
+}
+
+void rockchip_vpu981_av1_dec_done(struct hantro_ctx *ctx)
+{
+ rockchip_vpu981_av1_dec_update_prob(ctx);
+}
+
+static void rockchip_vpu981_av1_dec_set_prob(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ const struct v4l2_av1_quantization *quantization = &frame->quantization;
+ struct hantro_dev *vpu = ctx->dev;
+ bool error_resilient_mode =
+ !!(frame->flags & V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE);
+ bool frame_is_intra = IS_INTRA(frame->frame_type);
+
+ if (error_resilient_mode || frame_is_intra ||
+ frame->primary_ref_frame == AV1_PRIMARY_REF_NONE) {
+ av1_dec->cdfs = &av1_dec->default_cdfs;
+ av1_dec->cdfs_ndvc = &av1_dec->default_cdfs_ndvc;
+ rockchip_av1_default_coeff_probs(quantization->base_q_idx,
+ av1_dec->cdfs);
+ } else {
+ rockchip_av1_get_cdfs(ctx, frame->ref_frame_idx[frame->primary_ref_frame]);
+ }
+ rockchip_av1_store_cdfs(ctx, frame->refresh_frame_flags);
+
+ memcpy(av1_dec->prob_tbl.cpu, av1_dec->cdfs, sizeof(struct av1cdfs));
+
+ if (frame_is_intra) {
+ int mv_offset = offsetof(struct av1cdfs, mv_cdf);
+ /* Overwrite MV context area with intrabc MV context */
+ memcpy(av1_dec->prob_tbl.cpu + mv_offset, av1_dec->cdfs_ndvc,
+ sizeof(struct mvcdfs));
+ }
+
+ hantro_write_addr(vpu, AV1_PROP_TABLE_OUT, av1_dec->prob_tbl_out.dma);
+ hantro_write_addr(vpu, AV1_PROP_TABLE, av1_dec->prob_tbl.dma);
+}
+
+static void
+rockchip_vpu981_av1_dec_init_scaling_function(const u8 *values, const u8 *scaling,
+ u8 num_points, u8 *scaling_lut)
+{
+ int i, point;
+
+ if (num_points == 0) {
+ memset(scaling_lut, 0, 256);
+ return;
+ }
+
+ for (point = 0; point < num_points - 1; point++) {
+ int x;
+ s32 delta_y = scaling[point + 1] - scaling[point];
+ s32 delta_x = values[point + 1] - values[point];
+ s64 delta =
+ delta_x ? delta_y * ((65536 + (delta_x >> 1)) /
+ delta_x) : 0;
+
+ for (x = 0; x < delta_x; x++) {
+ scaling_lut[values[point] + x] =
+ scaling[point] +
+ (s32)((x * delta + 32768) >> 16);
+ }
+ }
+
+ for (i = values[num_points - 1]; i < 256; i++)
+ scaling_lut[i] = scaling[num_points - 1];
+}
+
+static void rockchip_vpu981_av1_dec_set_fgs(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_film_grain *film_grain = ctrls->film_grain;
+ struct rockchip_av1_film_grain *fgmem = av1_dec->film_grain.cpu;
+ struct hantro_dev *vpu = ctx->dev;
+ bool scaling_from_luma =
+ !!(film_grain->flags & V4L2_AV1_FILM_GRAIN_FLAG_CHROMA_SCALING_FROM_LUMA);
+ s32 (*ar_coeffs_y)[24];
+ s32 (*ar_coeffs_cb)[25];
+ s32 (*ar_coeffs_cr)[25];
+ s32 (*luma_grain_block)[73][82];
+ s32 (*cb_grain_block)[38][44];
+ s32 (*cr_grain_block)[38][44];
+ s32 ar_coeff_lag, ar_coeff_shift;
+ s32 grain_scale_shift, bitdepth;
+ s32 grain_center, grain_min, grain_max;
+ int i, j;
+
+ hantro_reg_write(vpu, &av1_apply_grain, 0);
+
+ if (!(film_grain->flags & V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN)) {
+ hantro_reg_write(vpu, &av1_num_y_points_b, 0);
+ hantro_reg_write(vpu, &av1_num_cb_points_b, 0);
+ hantro_reg_write(vpu, &av1_num_cr_points_b, 0);
+ hantro_reg_write(vpu, &av1_scaling_shift, 0);
+ hantro_reg_write(vpu, &av1_cb_mult, 0);
+ hantro_reg_write(vpu, &av1_cb_luma_mult, 0);
+ hantro_reg_write(vpu, &av1_cb_offset, 0);
+ hantro_reg_write(vpu, &av1_cr_mult, 0);
+ hantro_reg_write(vpu, &av1_cr_luma_mult, 0);
+ hantro_reg_write(vpu, &av1_cr_offset, 0);
+ hantro_reg_write(vpu, &av1_overlap_flag, 0);
+ hantro_reg_write(vpu, &av1_clip_to_restricted_range, 0);
+ hantro_reg_write(vpu, &av1_chroma_scaling_from_luma, 0);
+ hantro_reg_write(vpu, &av1_random_seed, 0);
+ hantro_write_addr(vpu, AV1_FILM_GRAIN, 0);
+ return;
+ }
+
+ ar_coeffs_y = kzalloc(sizeof(int32_t) * 24, GFP_KERNEL);
+ ar_coeffs_cb = kzalloc(sizeof(int32_t) * 25, GFP_KERNEL);
+ ar_coeffs_cr = kzalloc(sizeof(int32_t) * 25, GFP_KERNEL);
+ luma_grain_block = kzalloc(sizeof(int32_t) * 73 * 82, GFP_KERNEL);
+ cb_grain_block = kzalloc(sizeof(int32_t) * 38 * 44, GFP_KERNEL);
+ cr_grain_block = kzalloc(sizeof(int32_t) * 38 * 44, GFP_KERNEL);
+
+ if (!ar_coeffs_y || !ar_coeffs_cb || !ar_coeffs_cr ||
+ !luma_grain_block || !cb_grain_block || !cr_grain_block) {
+ pr_warn("Fail allocating memory for film grain parameters\n");
+ goto alloc_fail;
+ }
+
+ hantro_reg_write(vpu, &av1_apply_grain, 1);
+
+ hantro_reg_write(vpu, &av1_num_y_points_b,
+ film_grain->num_y_points > 0);
+ hantro_reg_write(vpu, &av1_num_cb_points_b,
+ film_grain->num_cb_points > 0);
+ hantro_reg_write(vpu, &av1_num_cr_points_b,
+ film_grain->num_cr_points > 0);
+ hantro_reg_write(vpu, &av1_scaling_shift,
+ film_grain->grain_scaling_minus_8 + 8);
+
+ if (!scaling_from_luma) {
+ hantro_reg_write(vpu, &av1_cb_mult, film_grain->cb_mult - 128);
+ hantro_reg_write(vpu, &av1_cb_luma_mult, film_grain->cb_luma_mult - 128);
+ hantro_reg_write(vpu, &av1_cb_offset, film_grain->cb_offset - 256);
+ hantro_reg_write(vpu, &av1_cr_mult, film_grain->cr_mult - 128);
+ hantro_reg_write(vpu, &av1_cr_luma_mult, film_grain->cr_luma_mult - 128);
+ hantro_reg_write(vpu, &av1_cr_offset, film_grain->cr_offset - 256);
+ } else {
+ hantro_reg_write(vpu, &av1_cb_mult, 0);
+ hantro_reg_write(vpu, &av1_cb_luma_mult, 0);
+ hantro_reg_write(vpu, &av1_cb_offset, 0);
+ hantro_reg_write(vpu, &av1_cr_mult, 0);
+ hantro_reg_write(vpu, &av1_cr_luma_mult, 0);
+ hantro_reg_write(vpu, &av1_cr_offset, 0);
+ }
+
+ hantro_reg_write(vpu, &av1_overlap_flag,
+ !!(film_grain->flags & V4L2_AV1_FILM_GRAIN_FLAG_OVERLAP));
+ hantro_reg_write(vpu, &av1_clip_to_restricted_range,
+ !!(film_grain->flags & V4L2_AV1_FILM_GRAIN_FLAG_CLIP_TO_RESTRICTED_RANGE));
+ hantro_reg_write(vpu, &av1_chroma_scaling_from_luma, scaling_from_luma);
+ hantro_reg_write(vpu, &av1_random_seed, film_grain->grain_seed);
+
+ rockchip_vpu981_av1_dec_init_scaling_function(film_grain->point_y_value,
+ film_grain->point_y_scaling,
+ film_grain->num_y_points,
+ fgmem->scaling_lut_y);
+
+ if (film_grain->flags &
+ V4L2_AV1_FILM_GRAIN_FLAG_CHROMA_SCALING_FROM_LUMA) {
+ memcpy(fgmem->scaling_lut_cb, fgmem->scaling_lut_y,
+ sizeof(*fgmem->scaling_lut_y) * 256);
+ memcpy(fgmem->scaling_lut_cr, fgmem->scaling_lut_y,
+ sizeof(*fgmem->scaling_lut_y) * 256);
+ } else {
+ rockchip_vpu981_av1_dec_init_scaling_function
+ (film_grain->point_cb_value, film_grain->point_cb_scaling,
+ film_grain->num_cb_points, fgmem->scaling_lut_cb);
+ rockchip_vpu981_av1_dec_init_scaling_function
+ (film_grain->point_cr_value, film_grain->point_cr_scaling,
+ film_grain->num_cr_points, fgmem->scaling_lut_cr);
+ }
+
+ for (i = 0; i < V4L2_AV1_AR_COEFFS_SIZE; i++) {
+ if (i < 24)
+ (*ar_coeffs_y)[i] = film_grain->ar_coeffs_y_plus_128[i] - 128;
+ (*ar_coeffs_cb)[i] = film_grain->ar_coeffs_cb_plus_128[i] - 128;
+ (*ar_coeffs_cr)[i] = film_grain->ar_coeffs_cr_plus_128[i] - 128;
+ }
+
+ ar_coeff_lag = film_grain->ar_coeff_lag;
+ ar_coeff_shift = film_grain->ar_coeff_shift_minus_6 + 6;
+ grain_scale_shift = film_grain->grain_scale_shift;
+ bitdepth = ctx->bit_depth;
+ grain_center = 128 << (bitdepth - 8);
+ grain_min = 0 - grain_center;
+ grain_max = (256 << (bitdepth - 8)) - 1 - grain_center;
+
+ rockchip_av1_generate_luma_grain_block(luma_grain_block, bitdepth,
+ film_grain->num_y_points, grain_scale_shift,
+ ar_coeff_lag, ar_coeffs_y, ar_coeff_shift,
+ grain_min, grain_max, film_grain->grain_seed);
+
+ rockchip_av1_generate_chroma_grain_block(luma_grain_block, cb_grain_block,
+ cr_grain_block, bitdepth,
+ film_grain->num_y_points,
+ film_grain->num_cb_points,
+ film_grain->num_cr_points,
+ grain_scale_shift, ar_coeff_lag, ar_coeffs_cb,
+ ar_coeffs_cr, ar_coeff_shift, grain_min,
+ grain_max,
+ scaling_from_luma,
+ film_grain->grain_seed);
+
+ for (i = 0; i < 64; i++) {
+ for (j = 0; j < 64; j++)
+ fgmem->cropped_luma_grain_block[i * 64 + j] =
+ (*luma_grain_block)[i + 9][j + 9];
+ }
+
+ for (i = 0; i < 32; i++) {
+ for (j = 0; j < 32; j++) {
+ fgmem->cropped_chroma_grain_block[i * 64 + 2 * j] =
+ (*cb_grain_block)[i + 6][j + 6];
+ fgmem->cropped_chroma_grain_block[i * 64 + 2 * j + 1] =
+ (*cr_grain_block)[i + 6][j + 6];
+ }
+ }
+
+ hantro_write_addr(vpu, AV1_FILM_GRAIN, av1_dec->film_grain.dma);
+
+alloc_fail:
+ kfree(ar_coeffs_y);
+ kfree(ar_coeffs_cb);
+ kfree(ar_coeffs_cr);
+ kfree(luma_grain_block);
+ kfree(cb_grain_block);
+ kfree(cr_grain_block);
+}
+
+static void rockchip_vpu981_av1_dec_set_cdef(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ const struct v4l2_av1_cdef *cdef = &frame->cdef;
+ struct hantro_dev *vpu = ctx->dev;
+ u32 luma_pri_strength = 0;
+ u16 luma_sec_strength = 0;
+ u32 chroma_pri_strength = 0;
+ u16 chroma_sec_strength = 0;
+ int i;
+
+ hantro_reg_write(vpu, &av1_cdef_bits, cdef->bits);
+ hantro_reg_write(vpu, &av1_cdef_damping, cdef->damping_minus_3);
+
+ for (i = 0; i < BIT(cdef->bits); i++) {
+ luma_pri_strength |= cdef->y_pri_strength[i] << (i * 4);
+ if (cdef->y_sec_strength[i] == 4)
+ luma_sec_strength |= 3 << (i * 2);
+ else
+ luma_sec_strength |= cdef->y_sec_strength[i] << (i * 2);
+
+ chroma_pri_strength |= cdef->uv_pri_strength[i] << (i * 4);
+ if (cdef->uv_sec_strength[i] == 4)
+ chroma_sec_strength |= 3 << (i * 2);
+ else
+ chroma_sec_strength |= cdef->uv_sec_strength[i] << (i * 2);
+ }
+
+ hantro_reg_write(vpu, &av1_cdef_luma_primary_strength,
+ luma_pri_strength);
+ hantro_reg_write(vpu, &av1_cdef_luma_secondary_strength,
+ luma_sec_strength);
+ hantro_reg_write(vpu, &av1_cdef_chroma_primary_strength,
+ chroma_pri_strength);
+ hantro_reg_write(vpu, &av1_cdef_chroma_secondary_strength,
+ chroma_sec_strength);
+
+ hantro_write_addr(vpu, AV1_CDEF_COL, av1_dec->cdef_col.dma);
+}
+
+static void rockchip_vpu981_av1_dec_set_lr(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ const struct v4l2_av1_loop_restoration *loop_restoration =
+ &frame->loop_restoration;
+ struct hantro_dev *vpu = ctx->dev;
+ u16 lr_type = 0, lr_unit_size = 0;
+ u8 restoration_unit_size[V4L2_AV1_NUM_PLANES_MAX] = { 3, 3, 3 };
+ int i;
+
+ if (loop_restoration->flags & V4L2_AV1_LOOP_RESTORATION_FLAG_USES_LR) {
+ restoration_unit_size[0] = 1 + loop_restoration->lr_unit_shift;
+ restoration_unit_size[1] =
+ 1 + loop_restoration->lr_unit_shift - loop_restoration->lr_uv_shift;
+ restoration_unit_size[2] =
+ 1 + loop_restoration->lr_unit_shift - loop_restoration->lr_uv_shift;
+ }
+
+ for (i = 0; i < V4L2_AV1_NUM_PLANES_MAX; i++) {
+ lr_type |=
+ loop_restoration->frame_restoration_type[i] << (i * 2);
+ lr_unit_size |= restoration_unit_size[i] << (i * 2);
+ }
+
+ hantro_reg_write(vpu, &av1_lr_type, lr_type);
+ hantro_reg_write(vpu, &av1_lr_unit_size, lr_unit_size);
+ hantro_write_addr(vpu, AV1_LR_COL, av1_dec->lr_col.dma);
+}
+
+static void rockchip_vpu981_av1_dec_set_superres_params(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ struct hantro_dev *vpu = ctx->dev;
+ u8 superres_scale_denominator = SCALE_NUMERATOR;
+ int superres_luma_step = RS_SCALE_SUBPEL_BITS;
+ int superres_chroma_step = RS_SCALE_SUBPEL_BITS;
+ int superres_luma_step_invra = RS_SCALE_SUBPEL_BITS;
+ int superres_chroma_step_invra = RS_SCALE_SUBPEL_BITS;
+ int superres_init_luma_subpel_x = 0;
+ int superres_init_chroma_subpel_x = 0;
+ int superres_is_scaled = 0;
+ int min_w = min_t(uint32_t, 16, frame->upscaled_width);
+ int upscaled_luma, downscaled_luma;
+ int downscaled_chroma, upscaled_chroma;
+ int step_luma, step_chroma;
+ int err_luma, err_chroma;
+ int initial_luma, initial_chroma;
+ int width = 0;
+
+ if (frame->flags & V4L2_AV1_FRAME_FLAG_USE_SUPERRES)
+ superres_scale_denominator = frame->superres_denom;
+
+ if (superres_scale_denominator <= SCALE_NUMERATOR)
+ goto set_regs;
+
+ width = (frame->upscaled_width * SCALE_NUMERATOR +
+ (superres_scale_denominator / 2)) / superres_scale_denominator;
+
+ if (width < min_w)
+ width = min_w;
+
+ if (width == frame->upscaled_width)
+ goto set_regs;
+
+ superres_is_scaled = 1;
+ upscaled_luma = frame->upscaled_width;
+ downscaled_luma = width;
+ downscaled_chroma = (downscaled_luma + 1) >> 1;
+ upscaled_chroma = (upscaled_luma + 1) >> 1;
+ step_luma =
+ ((downscaled_luma << RS_SCALE_SUBPEL_BITS) +
+ (upscaled_luma / 2)) / upscaled_luma;
+ step_chroma =
+ ((downscaled_chroma << RS_SCALE_SUBPEL_BITS) +
+ (upscaled_chroma / 2)) / upscaled_chroma;
+ err_luma =
+ (upscaled_luma * step_luma)
+ - (downscaled_luma << RS_SCALE_SUBPEL_BITS);
+ err_chroma =
+ (upscaled_chroma * step_chroma)
+ - (downscaled_chroma << RS_SCALE_SUBPEL_BITS);
+ initial_luma =
+ ((-((upscaled_luma - downscaled_luma) << (RS_SCALE_SUBPEL_BITS - 1))
+ + upscaled_luma / 2)
+ / upscaled_luma + (1 << (RS_SCALE_EXTRA_BITS - 1)) - err_luma / 2)
+ & RS_SCALE_SUBPEL_MASK;
+ initial_chroma =
+ ((-((upscaled_chroma - downscaled_chroma) << (RS_SCALE_SUBPEL_BITS - 1))
+ + upscaled_chroma / 2)
+ / upscaled_chroma + (1 << (RS_SCALE_EXTRA_BITS - 1)) - err_chroma / 2)
+ & RS_SCALE_SUBPEL_MASK;
+ superres_luma_step = step_luma;
+ superres_chroma_step = step_chroma;
+ superres_luma_step_invra =
+ ((upscaled_luma << RS_SCALE_SUBPEL_BITS) + (downscaled_luma / 2))
+ / downscaled_luma;
+ superres_chroma_step_invra =
+ ((upscaled_chroma << RS_SCALE_SUBPEL_BITS) + (downscaled_chroma / 2))
+ / downscaled_chroma;
+ superres_init_luma_subpel_x = initial_luma;
+ superres_init_chroma_subpel_x = initial_chroma;
+
+set_regs:
+ hantro_reg_write(vpu, &av1_superres_pic_width, frame->upscaled_width);
+
+ if (frame->flags & V4L2_AV1_FRAME_FLAG_USE_SUPERRES)
+ hantro_reg_write(vpu, &av1_scale_denom_minus9,
+ frame->superres_denom - SUPERRES_SCALE_DENOMINATOR_MIN);
+ else
+ hantro_reg_write(vpu, &av1_scale_denom_minus9, frame->superres_denom);
+
+ hantro_reg_write(vpu, &av1_superres_luma_step, superres_luma_step);
+ hantro_reg_write(vpu, &av1_superres_chroma_step, superres_chroma_step);
+ hantro_reg_write(vpu, &av1_superres_luma_step_invra,
+ superres_luma_step_invra);
+ hantro_reg_write(vpu, &av1_superres_chroma_step_invra,
+ superres_chroma_step_invra);
+ hantro_reg_write(vpu, &av1_superres_init_luma_subpel_x,
+ superres_init_luma_subpel_x);
+ hantro_reg_write(vpu, &av1_superres_init_chroma_subpel_x,
+ superres_init_chroma_subpel_x);
+ hantro_reg_write(vpu, &av1_superres_is_scaled, superres_is_scaled);
+
+ hantro_write_addr(vpu, AV1_SR_COL, av1_dec->sr_col.dma);
+}
+
+static void rockchip_vpu981_av1_dec_set_picture_dimensions(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ struct hantro_dev *vpu = ctx->dev;
+ int pic_width_in_cbs = DIV_ROUND_UP(frame->frame_width_minus_1 + 1, 8);
+ int pic_height_in_cbs = DIV_ROUND_UP(frame->frame_height_minus_1 + 1, 8);
+ int pic_width_pad = ALIGN(frame->frame_width_minus_1 + 1, 8)
+ - (frame->frame_width_minus_1 + 1);
+ int pic_height_pad = ALIGN(frame->frame_height_minus_1 + 1, 8)
+ - (frame->frame_height_minus_1 + 1);
+
+ hantro_reg_write(vpu, &av1_pic_width_in_cbs, pic_width_in_cbs);
+ hantro_reg_write(vpu, &av1_pic_height_in_cbs, pic_height_in_cbs);
+ hantro_reg_write(vpu, &av1_pic_width_pad, pic_width_pad);
+ hantro_reg_write(vpu, &av1_pic_height_pad, pic_height_pad);
+
+ rockchip_vpu981_av1_dec_set_superres_params(ctx);
+}
+
+static void rockchip_vpu981_av1_dec_set_other_frames(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ struct hantro_dev *vpu = ctx->dev;
+ bool use_ref_frame_mvs =
+ !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS);
+ int cur_frame_offset = frame->order_hint;
+ int alt_frame_offset = 0;
+ int gld_frame_offset = 0;
+ int bwd_frame_offset = 0;
+ int alt2_frame_offset = 0;
+ int refs_selected[3] = { 0, 0, 0 };
+ int cur_mi_cols = DIV_ROUND_UP(frame->frame_width_minus_1 + 1, 8);
+ int cur_mi_rows = DIV_ROUND_UP(frame->frame_height_minus_1 + 1, 8);
+ int cur_offset[V4L2_AV1_TOTAL_REFS_PER_FRAME - 1];
+ int cur_roffset[V4L2_AV1_TOTAL_REFS_PER_FRAME - 1];
+ int mf_types[3] = { 0, 0, 0 };
+ int ref_stamp = 2;
+ int ref_ind = 0;
+ int rf, idx;
+
+ alt_frame_offset = rockchip_vpu981_get_order_hint(ctx, ALT_BUF_IDX);
+ gld_frame_offset = rockchip_vpu981_get_order_hint(ctx, GLD_BUF_IDX);
+ bwd_frame_offset = rockchip_vpu981_get_order_hint(ctx, BWD_BUF_IDX);
+ alt2_frame_offset = rockchip_vpu981_get_order_hint(ctx, ALT2_BUF_IDX);
+
+ idx = rockchip_vpu981_get_frame_index(ctx, LST_BUF_IDX);
+ if (idx >= 0) {
+ int alt_frame_offset_in_lst =
+ av1_dec->frame_refs[idx].order_hints[V4L2_AV1_REF_ALTREF_FRAME];
+ bool is_lst_overlay =
+ (alt_frame_offset_in_lst == gld_frame_offset);
+
+ if (!is_lst_overlay) {
+ int lst_mi_cols = av1_dec->frame_refs[idx].mi_cols;
+ int lst_mi_rows = av1_dec->frame_refs[idx].mi_rows;
+ bool lst_intra_only =
+ IS_INTRA(av1_dec->frame_refs[idx].frame_type);
+
+ if (lst_mi_cols == cur_mi_cols &&
+ lst_mi_rows == cur_mi_rows && !lst_intra_only) {
+ mf_types[ref_ind] = V4L2_AV1_REF_LAST_FRAME;
+ refs_selected[ref_ind++] = LST_BUF_IDX;
+ }
+ }
+ ref_stamp--;
+ }
+
+ idx = rockchip_vpu981_get_frame_index(ctx, BWD_BUF_IDX);
+ if (rockchip_vpu981_av1_dec_get_dist(ctx, bwd_frame_offset, cur_frame_offset) > 0) {
+ int bwd_mi_cols = av1_dec->frame_refs[idx].mi_cols;
+ int bwd_mi_rows = av1_dec->frame_refs[idx].mi_rows;
+ bool bwd_intra_only =
+ IS_INTRA(av1_dec->frame_refs[idx].frame_type);
+
+ if (bwd_mi_cols == cur_mi_cols && bwd_mi_rows == cur_mi_rows &&
+ !bwd_intra_only) {
+ mf_types[ref_ind] = V4L2_AV1_REF_BWDREF_FRAME;
+ refs_selected[ref_ind++] = BWD_BUF_IDX;
+ ref_stamp--;
+ }
+ }
+
+ idx = rockchip_vpu981_get_frame_index(ctx, ALT2_BUF_IDX);
+ if (rockchip_vpu981_av1_dec_get_dist(ctx, alt2_frame_offset, cur_frame_offset) > 0) {
+ int alt2_mi_cols = av1_dec->frame_refs[idx].mi_cols;
+ int alt2_mi_rows = av1_dec->frame_refs[idx].mi_rows;
+ bool alt2_intra_only =
+ IS_INTRA(av1_dec->frame_refs[idx].frame_type);
+
+ if (alt2_mi_cols == cur_mi_cols && alt2_mi_rows == cur_mi_rows &&
+ !alt2_intra_only) {
+ mf_types[ref_ind] = V4L2_AV1_REF_ALTREF2_FRAME;
+ refs_selected[ref_ind++] = ALT2_BUF_IDX;
+ ref_stamp--;
+ }
+ }
+
+ idx = rockchip_vpu981_get_frame_index(ctx, ALT_BUF_IDX);
+ if (rockchip_vpu981_av1_dec_get_dist(ctx, alt_frame_offset, cur_frame_offset) > 0 &&
+ ref_stamp >= 0) {
+ int alt_mi_cols = av1_dec->frame_refs[idx].mi_cols;
+ int alt_mi_rows = av1_dec->frame_refs[idx].mi_rows;
+ bool alt_intra_only =
+ IS_INTRA(av1_dec->frame_refs[idx].frame_type);
+
+ if (alt_mi_cols == cur_mi_cols && alt_mi_rows == cur_mi_rows &&
+ !alt_intra_only) {
+ mf_types[ref_ind] = V4L2_AV1_REF_ALTREF_FRAME;
+ refs_selected[ref_ind++] = ALT_BUF_IDX;
+ ref_stamp--;
+ }
+ }
+
+ idx = rockchip_vpu981_get_frame_index(ctx, LST2_BUF_IDX);
+ if (idx >= 0 && ref_stamp >= 0) {
+ int lst2_mi_cols = av1_dec->frame_refs[idx].mi_cols;
+ int lst2_mi_rows = av1_dec->frame_refs[idx].mi_rows;
+ bool lst2_intra_only =
+ IS_INTRA(av1_dec->frame_refs[idx].frame_type);
+
+ if (lst2_mi_cols == cur_mi_cols && lst2_mi_rows == cur_mi_rows &&
+ !lst2_intra_only) {
+ mf_types[ref_ind] = V4L2_AV1_REF_LAST2_FRAME;
+ refs_selected[ref_ind++] = LST2_BUF_IDX;
+ ref_stamp--;
+ }
+ }
+
+ for (rf = 0; rf < V4L2_AV1_TOTAL_REFS_PER_FRAME - 1; ++rf) {
+ idx = rockchip_vpu981_get_frame_index(ctx, rf);
+ if (idx >= 0) {
+ int rf_order_hint = rockchip_vpu981_get_order_hint(ctx, rf);
+
+ cur_offset[rf] =
+ rockchip_vpu981_av1_dec_get_dist(ctx, cur_frame_offset, rf_order_hint);
+ cur_roffset[rf] =
+ rockchip_vpu981_av1_dec_get_dist(ctx, rf_order_hint, cur_frame_offset);
+ } else {
+ cur_offset[rf] = 0;
+ cur_roffset[rf] = 0;
+ }
+ }
+
+ hantro_reg_write(vpu, &av1_use_temporal0_mvs, 0);
+ hantro_reg_write(vpu, &av1_use_temporal1_mvs, 0);
+ hantro_reg_write(vpu, &av1_use_temporal2_mvs, 0);
+ hantro_reg_write(vpu, &av1_use_temporal3_mvs, 0);
+
+ hantro_reg_write(vpu, &av1_mf1_last_offset, 0);
+ hantro_reg_write(vpu, &av1_mf1_last2_offset, 0);
+ hantro_reg_write(vpu, &av1_mf1_last3_offset, 0);
+ hantro_reg_write(vpu, &av1_mf1_golden_offset, 0);
+ hantro_reg_write(vpu, &av1_mf1_bwdref_offset, 0);
+ hantro_reg_write(vpu, &av1_mf1_altref2_offset, 0);
+ hantro_reg_write(vpu, &av1_mf1_altref_offset, 0);
+
+ if (use_ref_frame_mvs && ref_ind > 0 &&
+ cur_offset[mf_types[0] - V4L2_AV1_REF_LAST_FRAME] <= MAX_FRAME_DISTANCE &&
+ cur_offset[mf_types[0] - V4L2_AV1_REF_LAST_FRAME] >= -MAX_FRAME_DISTANCE) {
+ int rf = rockchip_vpu981_get_order_hint(ctx, refs_selected[0]);
+ int idx = rockchip_vpu981_get_frame_index(ctx, refs_selected[0]);
+ u32 *oh = av1_dec->frame_refs[idx].order_hints;
+ int val;
+
+ hantro_reg_write(vpu, &av1_use_temporal0_mvs, 1);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST_FRAME]);
+ hantro_reg_write(vpu, &av1_mf1_last_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST2_FRAME]);
+ hantro_reg_write(vpu, &av1_mf1_last2_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST3_FRAME]);
+ hantro_reg_write(vpu, &av1_mf1_last3_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_GOLDEN_FRAME]);
+ hantro_reg_write(vpu, &av1_mf1_golden_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_BWDREF_FRAME]);
+ hantro_reg_write(vpu, &av1_mf1_bwdref_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF2_FRAME]);
+ hantro_reg_write(vpu, &av1_mf1_altref2_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF_FRAME]);
+ hantro_reg_write(vpu, &av1_mf1_altref_offset, val);
+ }
+
+ hantro_reg_write(vpu, &av1_mf2_last_offset, 0);
+ hantro_reg_write(vpu, &av1_mf2_last2_offset, 0);
+ hantro_reg_write(vpu, &av1_mf2_last3_offset, 0);
+ hantro_reg_write(vpu, &av1_mf2_golden_offset, 0);
+ hantro_reg_write(vpu, &av1_mf2_bwdref_offset, 0);
+ hantro_reg_write(vpu, &av1_mf2_altref2_offset, 0);
+ hantro_reg_write(vpu, &av1_mf2_altref_offset, 0);
+
+ if (use_ref_frame_mvs && ref_ind > 1 &&
+ cur_offset[mf_types[1] - V4L2_AV1_REF_LAST_FRAME] <= MAX_FRAME_DISTANCE &&
+ cur_offset[mf_types[1] - V4L2_AV1_REF_LAST_FRAME] >= -MAX_FRAME_DISTANCE) {
+ int rf = rockchip_vpu981_get_order_hint(ctx, refs_selected[1]);
+ int idx = rockchip_vpu981_get_frame_index(ctx, refs_selected[1]);
+ u32 *oh = av1_dec->frame_refs[idx].order_hints;
+ int val;
+
+ hantro_reg_write(vpu, &av1_use_temporal1_mvs, 1);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST_FRAME]);
+ hantro_reg_write(vpu, &av1_mf2_last_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST2_FRAME]);
+ hantro_reg_write(vpu, &av1_mf2_last2_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST3_FRAME]);
+ hantro_reg_write(vpu, &av1_mf2_last3_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_GOLDEN_FRAME]);
+ hantro_reg_write(vpu, &av1_mf2_golden_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_BWDREF_FRAME]);
+ hantro_reg_write(vpu, &av1_mf2_bwdref_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF2_FRAME]);
+ hantro_reg_write(vpu, &av1_mf2_altref2_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF_FRAME]);
+ hantro_reg_write(vpu, &av1_mf2_altref_offset, val);
+ }
+
+ hantro_reg_write(vpu, &av1_mf3_last_offset, 0);
+ hantro_reg_write(vpu, &av1_mf3_last2_offset, 0);
+ hantro_reg_write(vpu, &av1_mf3_last3_offset, 0);
+ hantro_reg_write(vpu, &av1_mf3_golden_offset, 0);
+ hantro_reg_write(vpu, &av1_mf3_bwdref_offset, 0);
+ hantro_reg_write(vpu, &av1_mf3_altref2_offset, 0);
+ hantro_reg_write(vpu, &av1_mf3_altref_offset, 0);
+
+ if (use_ref_frame_mvs && ref_ind > 2 &&
+ cur_offset[mf_types[2] - V4L2_AV1_REF_LAST_FRAME] <= MAX_FRAME_DISTANCE &&
+ cur_offset[mf_types[2] - V4L2_AV1_REF_LAST_FRAME] >= -MAX_FRAME_DISTANCE) {
+ int rf = rockchip_vpu981_get_order_hint(ctx, refs_selected[2]);
+ int idx = rockchip_vpu981_get_frame_index(ctx, refs_selected[2]);
+ u32 *oh = av1_dec->frame_refs[idx].order_hints;
+ int val;
+
+ hantro_reg_write(vpu, &av1_use_temporal2_mvs, 1);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST_FRAME]);
+ hantro_reg_write(vpu, &av1_mf3_last_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST2_FRAME]);
+ hantro_reg_write(vpu, &av1_mf3_last2_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST3_FRAME]);
+ hantro_reg_write(vpu, &av1_mf3_last3_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_GOLDEN_FRAME]);
+ hantro_reg_write(vpu, &av1_mf3_golden_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_BWDREF_FRAME]);
+ hantro_reg_write(vpu, &av1_mf3_bwdref_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF2_FRAME]);
+ hantro_reg_write(vpu, &av1_mf3_altref2_offset, val);
+
+ val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF_FRAME]);
+ hantro_reg_write(vpu, &av1_mf3_altref_offset, val);
+ }
+
+ hantro_reg_write(vpu, &av1_cur_last_offset, cur_offset[0]);
+ hantro_reg_write(vpu, &av1_cur_last2_offset, cur_offset[1]);
+ hantro_reg_write(vpu, &av1_cur_last3_offset, cur_offset[2]);
+ hantro_reg_write(vpu, &av1_cur_golden_offset, cur_offset[3]);
+ hantro_reg_write(vpu, &av1_cur_bwdref_offset, cur_offset[4]);
+ hantro_reg_write(vpu, &av1_cur_altref2_offset, cur_offset[5]);
+ hantro_reg_write(vpu, &av1_cur_altref_offset, cur_offset[6]);
+
+ hantro_reg_write(vpu, &av1_cur_last_roffset, cur_roffset[0]);
+ hantro_reg_write(vpu, &av1_cur_last2_roffset, cur_roffset[1]);
+ hantro_reg_write(vpu, &av1_cur_last3_roffset, cur_roffset[2]);
+ hantro_reg_write(vpu, &av1_cur_golden_roffset, cur_roffset[3]);
+ hantro_reg_write(vpu, &av1_cur_bwdref_roffset, cur_roffset[4]);
+ hantro_reg_write(vpu, &av1_cur_altref2_roffset, cur_roffset[5]);
+ hantro_reg_write(vpu, &av1_cur_altref_roffset, cur_roffset[6]);
+
+ hantro_reg_write(vpu, &av1_mf1_type, mf_types[0] - V4L2_AV1_REF_LAST_FRAME);
+ hantro_reg_write(vpu, &av1_mf2_type, mf_types[1] - V4L2_AV1_REF_LAST_FRAME);
+ hantro_reg_write(vpu, &av1_mf3_type, mf_types[2] - V4L2_AV1_REF_LAST_FRAME);
+}
+
+static void rockchip_vpu981_av1_dec_set_reference_frames(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_frame *frame = ctrls->frame;
+ int frame_type = frame->frame_type;
+ bool allow_intrabc = !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC);
+ int ref_count[AV1DEC_MAX_PIC_BUFFERS] = { 0 };
+ struct hantro_dev *vpu = ctx->dev;
+ int i, ref_frames = 0;
+ bool scale_enable = false;
+
+ if (IS_INTRA(frame_type) && !allow_intrabc)
+ return;
+
+ if (!allow_intrabc) {
+ for (i = 0; i < V4L2_AV1_REFS_PER_FRAME; i++) {
+ int idx = rockchip_vpu981_get_frame_index(ctx, i);
+
+ if (idx >= 0)
+ ref_count[idx]++;
+ }
+
+ for (i = 0; i < AV1DEC_MAX_PIC_BUFFERS; i++) {
+ if (ref_count[i])
+ ref_frames++;
+ }
+ } else {
+ ref_frames = 1;
+ }
+ hantro_reg_write(vpu, &av1_ref_frames, ref_frames);
+
+ rockchip_vpu981_av1_dec_set_frame_sign_bias(ctx);
+
+ for (i = V4L2_AV1_REF_LAST_FRAME; i < V4L2_AV1_TOTAL_REFS_PER_FRAME; i++) {
+ u32 ref = i - 1;
+ int idx = 0;
+ int width, height;
+
+ if (allow_intrabc) {
+ idx = av1_dec->current_frame_index;
+ width = frame->frame_width_minus_1 + 1;
+ height = frame->frame_height_minus_1 + 1;
+ } else {
+ if (rockchip_vpu981_get_frame_index(ctx, ref) > 0)
+ idx = rockchip_vpu981_get_frame_index(ctx, ref);
+ width = av1_dec->frame_refs[idx].width;
+ height = av1_dec->frame_refs[idx].height;
+ }
+
+ scale_enable |=
+ rockchip_vpu981_av1_dec_set_ref(ctx, ref, idx, width,
+ height);
+
+ rockchip_vpu981_av1_dec_set_sign_bias(ctx, ref,
+ av1_dec->ref_frame_sign_bias[i]);
+ }
+ hantro_reg_write(vpu, &av1_ref_scaling_enable, scale_enable);
+
+ hantro_reg_write(vpu, &av1_ref0_gm_mode,
+ frame->global_motion.type[V4L2_AV1_REF_LAST_FRAME]);
+ hantro_reg_write(vpu, &av1_ref1_gm_mode,
+ frame->global_motion.type[V4L2_AV1_REF_LAST2_FRAME]);
+ hantro_reg_write(vpu, &av1_ref2_gm_mode,
+ frame->global_motion.type[V4L2_AV1_REF_LAST3_FRAME]);
+ hantro_reg_write(vpu, &av1_ref3_gm_mode,
+ frame->global_motion.type[V4L2_AV1_REF_GOLDEN_FRAME]);
+ hantro_reg_write(vpu, &av1_ref4_gm_mode,
+ frame->global_motion.type[V4L2_AV1_REF_BWDREF_FRAME]);
+ hantro_reg_write(vpu, &av1_ref5_gm_mode,
+ frame->global_motion.type[V4L2_AV1_REF_ALTREF2_FRAME]);
+ hantro_reg_write(vpu, &av1_ref6_gm_mode,
+ frame->global_motion.type[V4L2_AV1_REF_ALTREF_FRAME]);
+
+ rockchip_vpu981_av1_dec_set_other_frames(ctx);
+}
+
+static void rockchip_vpu981_av1_dec_set_parameters(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+
+ hantro_reg_write(vpu, &av1_skip_mode,
+ !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT));
+ hantro_reg_write(vpu, &av1_tempor_mvp_e,
+ !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS));
+ hantro_reg_write(vpu, &av1_delta_lf_res_log,
+ ctrls->frame->loop_filter.delta_lf_res);
+ hantro_reg_write(vpu, &av1_delta_lf_multi,
+ !!(ctrls->frame->loop_filter.flags
+ & V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_MULTI));
+ hantro_reg_write(vpu, &av1_delta_lf_present,
+ !!(ctrls->frame->loop_filter.flags
+ & V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_PRESENT));
+ hantro_reg_write(vpu, &av1_disable_cdf_update,
+ !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_DISABLE_CDF_UPDATE));
+ hantro_reg_write(vpu, &av1_allow_warp,
+ !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_WARPED_MOTION));
+ hantro_reg_write(vpu, &av1_show_frame,
+ !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_SHOW_FRAME));
+ hantro_reg_write(vpu, &av1_switchable_motion_mode,
+ !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE));
+ hantro_reg_write(vpu, &av1_enable_cdef,
+ !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF));
+ hantro_reg_write(vpu, &av1_allow_masked_compound,
+ !!(ctrls->sequence->flags
+ & V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND));
+ hantro_reg_write(vpu, &av1_allow_interintra,
+ !!(ctrls->sequence->flags
+ & V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND));
+ hantro_reg_write(vpu, &av1_enable_intra_edge_filter,
+ !!(ctrls->sequence->flags
+ & V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER));
+ hantro_reg_write(vpu, &av1_allow_filter_intra,
+ !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA));
+ hantro_reg_write(vpu, &av1_enable_jnt_comp,
+ !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP));
+ hantro_reg_write(vpu, &av1_enable_dual_filter,
+ !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER));
+ hantro_reg_write(vpu, &av1_reduced_tx_set_used,
+ !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_REDUCED_TX_SET));
+ hantro_reg_write(vpu, &av1_allow_screen_content_tools,
+ !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS));
+ hantro_reg_write(vpu, &av1_allow_intrabc,
+ !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC));
+
+ if (!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS))
+ hantro_reg_write(vpu, &av1_force_interger_mv, 0);
+ else
+ hantro_reg_write(vpu, &av1_force_interger_mv,
+ !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_FORCE_INTEGER_MV));
+
+ hantro_reg_write(vpu, &av1_blackwhite_e, 0);
+ hantro_reg_write(vpu, &av1_delta_q_res_log, ctrls->frame->quantization.delta_q_res);
+ hantro_reg_write(vpu, &av1_delta_q_present,
+ !!(ctrls->frame->quantization.flags
+ & V4L2_AV1_QUANTIZATION_FLAG_DELTA_Q_PRESENT));
+
+ hantro_reg_write(vpu, &av1_idr_pic_e, !ctrls->frame->frame_type);
+ hantro_reg_write(vpu, &av1_quant_base_qindex, ctrls->frame->quantization.base_q_idx);
+ hantro_reg_write(vpu, &av1_bit_depth_y_minus8, ctx->bit_depth - 8);
+ hantro_reg_write(vpu, &av1_bit_depth_c_minus8, ctx->bit_depth - 8);
+
+ hantro_reg_write(vpu, &av1_mcomp_filt_type, ctrls->frame->interpolation_filter);
+ hantro_reg_write(vpu, &av1_high_prec_mv_e,
+ !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV));
+ hantro_reg_write(vpu, &av1_comp_pred_mode,
+ (ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT) ? 2 : 0);
+ hantro_reg_write(vpu, &av1_transform_mode, (ctrls->frame->tx_mode == 1) ? 3 : 4);
+ hantro_reg_write(vpu, &av1_max_cb_size,
+ (ctrls->sequence->flags
+ & V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK) ? 7 : 6);
+ hantro_reg_write(vpu, &av1_min_cb_size, 3);
+
+ hantro_reg_write(vpu, &av1_comp_pred_fixed_ref, 0);
+ hantro_reg_write(vpu, &av1_comp_pred_var_ref0_av1, 0);
+ hantro_reg_write(vpu, &av1_comp_pred_var_ref1_av1, 0);
+ hantro_reg_write(vpu, &av1_filt_level_seg0, 0);
+ hantro_reg_write(vpu, &av1_filt_level_seg1, 0);
+ hantro_reg_write(vpu, &av1_filt_level_seg2, 0);
+ hantro_reg_write(vpu, &av1_filt_level_seg3, 0);
+ hantro_reg_write(vpu, &av1_filt_level_seg4, 0);
+ hantro_reg_write(vpu, &av1_filt_level_seg5, 0);
+ hantro_reg_write(vpu, &av1_filt_level_seg6, 0);
+ hantro_reg_write(vpu, &av1_filt_level_seg7, 0);
+
+ hantro_reg_write(vpu, &av1_qp_delta_y_dc_av1, ctrls->frame->quantization.delta_q_y_dc);
+ hantro_reg_write(vpu, &av1_qp_delta_ch_dc_av1, ctrls->frame->quantization.delta_q_u_dc);
+ hantro_reg_write(vpu, &av1_qp_delta_ch_ac_av1, ctrls->frame->quantization.delta_q_u_ac);
+ if (ctrls->frame->quantization.flags & V4L2_AV1_QUANTIZATION_FLAG_USING_QMATRIX) {
+ hantro_reg_write(vpu, &av1_qmlevel_y, ctrls->frame->quantization.qm_y);
+ hantro_reg_write(vpu, &av1_qmlevel_u, ctrls->frame->quantization.qm_u);
+ hantro_reg_write(vpu, &av1_qmlevel_v, ctrls->frame->quantization.qm_v);
+ } else {
+ hantro_reg_write(vpu, &av1_qmlevel_y, 0xff);
+ hantro_reg_write(vpu, &av1_qmlevel_u, 0xff);
+ hantro_reg_write(vpu, &av1_qmlevel_v, 0xff);
+ }
+
+ hantro_reg_write(vpu, &av1_lossless_e, rockchip_vpu981_av1_dec_is_lossless(ctx));
+ hantro_reg_write(vpu, &av1_quant_delta_v_dc, ctrls->frame->quantization.delta_q_v_dc);
+ hantro_reg_write(vpu, &av1_quant_delta_v_ac, ctrls->frame->quantization.delta_q_v_ac);
+
+ hantro_reg_write(vpu, &av1_skip_ref0,
+ (ctrls->frame->skip_mode_frame[0]) ? ctrls->frame->skip_mode_frame[0] : 1);
+ hantro_reg_write(vpu, &av1_skip_ref1,
+ (ctrls->frame->skip_mode_frame[1]) ? ctrls->frame->skip_mode_frame[1] : 1);
+
+ hantro_write_addr(vpu, AV1_MC_SYNC_CURR, av1_dec->tile_buf.dma);
+ hantro_write_addr(vpu, AV1_MC_SYNC_LEFT, av1_dec->tile_buf.dma);
+}
+
+static void
+rockchip_vpu981_av1_dec_set_input_buffer(struct hantro_ctx *ctx,
+ struct vb2_v4l2_buffer *vb2_src)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_ctrl_av1_tile_group_entry *group_entry =
+ ctrls->tile_group_entry;
+ struct hantro_dev *vpu = ctx->dev;
+ dma_addr_t src_dma;
+ u32 src_len, src_buf_len;
+ int start_bit, offset;
+
+ src_dma = vb2_dma_contig_plane_dma_addr(&vb2_src->vb2_buf, 0);
+ src_len = vb2_get_plane_payload(&vb2_src->vb2_buf, 0);
+ src_buf_len = vb2_plane_size(&vb2_src->vb2_buf, 0);
+
+ start_bit = (group_entry[0].tile_offset & 0xf) * 8;
+ offset = group_entry[0].tile_offset & ~0xf;
+
+ hantro_reg_write(vpu, &av1_strm_buffer_len, src_buf_len);
+ hantro_reg_write(vpu, &av1_strm_start_bit, start_bit);
+ hantro_reg_write(vpu, &av1_stream_len, src_len);
+ hantro_reg_write(vpu, &av1_strm_start_offset, 0);
+ hantro_write_addr(vpu, AV1_INPUT_STREAM, src_dma + offset);
+}
+
+static void
+rockchip_vpu981_av1_dec_set_output_buffer(struct hantro_ctx *ctx)
+{
+ struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
+ struct hantro_dev *vpu = ctx->dev;
+ struct hantro_decoded_buffer *dst;
+ struct vb2_v4l2_buffer *vb2_dst;
+ dma_addr_t luma_addr, chroma_addr, mv_addr = 0;
+ size_t cr_offset = rockchip_vpu981_av1_dec_luma_size(ctx);
+ size_t mv_offset = rockchip_vpu981_av1_dec_chroma_size(ctx);
+
+ vb2_dst = av1_dec->frame_refs[av1_dec->current_frame_index].vb2_ref;
+ dst = vb2_to_hantro_decoded_buf(&vb2_dst->vb2_buf);
+ luma_addr = hantro_get_dec_buf_addr(ctx, &dst->base.vb.vb2_buf);
+ chroma_addr = luma_addr + cr_offset;
+ mv_addr = luma_addr + mv_offset;
+
+ hantro_write_addr(vpu, AV1_TILE_OUT_LU, luma_addr);
+ hantro_write_addr(vpu, AV1_TILE_OUT_CH, chroma_addr);
+ hantro_write_addr(vpu, AV1_TILE_OUT_MV, mv_addr);
+}
+
+int rockchip_vpu981_av1_dec_run(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ struct vb2_v4l2_buffer *vb2_src;
+ int ret;
+
+ hantro_start_prepare_run(ctx);
+
+ ret = rockchip_vpu981_av1_dec_prepare_run(ctx);
+ if (ret)
+ goto prepare_error;
+
+ vb2_src = hantro_get_src_buf(ctx);
+ if (!vb2_src) {
+ ret = -EINVAL;
+ goto prepare_error;
+ }
+
+ rockchip_vpu981_av1_dec_clean_refs(ctx);
+ rockchip_vpu981_av1_dec_frame_ref(ctx, vb2_src->vb2_buf.timestamp);
+
+ rockchip_vpu981_av1_dec_set_parameters(ctx);
+ rockchip_vpu981_av1_dec_set_global_model(ctx);
+ rockchip_vpu981_av1_dec_set_tile_info(ctx);
+ rockchip_vpu981_av1_dec_set_reference_frames(ctx);
+ rockchip_vpu981_av1_dec_set_segmentation(ctx);
+ rockchip_vpu981_av1_dec_set_loopfilter(ctx);
+ rockchip_vpu981_av1_dec_set_picture_dimensions(ctx);
+ rockchip_vpu981_av1_dec_set_cdef(ctx);
+ rockchip_vpu981_av1_dec_set_lr(ctx);
+ rockchip_vpu981_av1_dec_set_fgs(ctx);
+ rockchip_vpu981_av1_dec_set_prob(ctx);
+
+ hantro_reg_write(vpu, &av1_dec_mode, AV1_DEC_MODE);
+ hantro_reg_write(vpu, &av1_dec_out_ec_byte_word, 0);
+ hantro_reg_write(vpu, &av1_write_mvs_e, 1);
+ hantro_reg_write(vpu, &av1_dec_out_ec_bypass, 1);
+ hantro_reg_write(vpu, &av1_dec_clk_gate_e, 1);
+
+ hantro_reg_write(vpu, &av1_dec_abort_e, 0);
+ hantro_reg_write(vpu, &av1_dec_tile_int_e, 0);
+
+ hantro_reg_write(vpu, &av1_dec_alignment, 64);
+ hantro_reg_write(vpu, &av1_apf_disable, 0);
+ hantro_reg_write(vpu, &av1_apf_threshold, 8);
+ hantro_reg_write(vpu, &av1_dec_buswidth, 2);
+ hantro_reg_write(vpu, &av1_dec_max_burst, 16);
+ hantro_reg_write(vpu, &av1_error_conceal_e, 0);
+ hantro_reg_write(vpu, &av1_axi_rd_ostd_threshold, 64);
+ hantro_reg_write(vpu, &av1_axi_wr_ostd_threshold, 64);
+
+ hantro_reg_write(vpu, &av1_ext_timeout_cycles, 0xfffffff);
+ hantro_reg_write(vpu, &av1_ext_timeout_override_e, 1);
+ hantro_reg_write(vpu, &av1_timeout_cycles, 0xfffffff);
+ hantro_reg_write(vpu, &av1_timeout_override_e, 1);
+
+ rockchip_vpu981_av1_dec_set_output_buffer(ctx);
+ rockchip_vpu981_av1_dec_set_input_buffer(ctx, vb2_src);
+
+ hantro_end_prepare_run(ctx);
+
+ hantro_reg_write(vpu, &av1_dec_e, 1);
+
+ return 0;
+
+prepare_error:
+ hantro_end_prepare_run(ctx);
+ hantro_irq_done(vpu, VB2_BUF_STATE_ERROR);
+ return ret;
+}
+
+static void rockchip_vpu981_postproc_enable(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+ int width = ctx->dst_fmt.width;
+ int height = ctx->dst_fmt.height;
+ struct vb2_v4l2_buffer *vb2_dst;
+ size_t chroma_offset;
+ dma_addr_t dst_dma;
+
+ vb2_dst = hantro_get_dst_buf(ctx);
+
+ dst_dma = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0);
+ chroma_offset = ctx->dst_fmt.plane_fmt[0].bytesperline *
+ ctx->dst_fmt.height;
+
+ /* enable post processor */
+ hantro_reg_write(vpu, &av1_pp_out_e, 1);
+ hantro_reg_write(vpu, &av1_pp_in_format, 0);
+ hantro_reg_write(vpu, &av1_pp0_dup_hor, 1);
+ hantro_reg_write(vpu, &av1_pp0_dup_ver, 1);
+
+ hantro_reg_write(vpu, &av1_pp_in_height, height / 2);
+ hantro_reg_write(vpu, &av1_pp_in_width, width / 2);
+ hantro_reg_write(vpu, &av1_pp_out_height, height);
+ hantro_reg_write(vpu, &av1_pp_out_width, width);
+ hantro_reg_write(vpu, &av1_pp_out_y_stride,
+ ctx->dst_fmt.plane_fmt[0].bytesperline);
+ hantro_reg_write(vpu, &av1_pp_out_c_stride,
+ ctx->dst_fmt.plane_fmt[0].bytesperline);
+ switch (ctx->dst_fmt.pixelformat) {
+ case V4L2_PIX_FMT_P010:
+ hantro_reg_write(vpu, &av1_pp_out_format, 1);
+ break;
+ case V4L2_PIX_FMT_NV12:
+ hantro_reg_write(vpu, &av1_pp_out_format, 3);
+ break;
+ default:
+ hantro_reg_write(vpu, &av1_pp_out_format, 0);
+ }
+
+ hantro_reg_write(vpu, &av1_ppd_blend_exist, 0);
+ hantro_reg_write(vpu, &av1_ppd_dith_exist, 0);
+ hantro_reg_write(vpu, &av1_ablend_crop_e, 0);
+ hantro_reg_write(vpu, &av1_pp_format_customer1_e, 0);
+ hantro_reg_write(vpu, &av1_pp_crop_exist, 0);
+ hantro_reg_write(vpu, &av1_pp_up_level, 0);
+ hantro_reg_write(vpu, &av1_pp_down_level, 0);
+ hantro_reg_write(vpu, &av1_pp_exist, 0);
+
+ hantro_write_addr(vpu, AV1_PP_OUT_LU, dst_dma);
+ hantro_write_addr(vpu, AV1_PP_OUT_CH, dst_dma + chroma_offset);
+}
+
+static void rockchip_vpu981_postproc_disable(struct hantro_ctx *ctx)
+{
+ struct hantro_dev *vpu = ctx->dev;
+
+ /* disable post processor */
+ hantro_reg_write(vpu, &av1_pp_out_e, 0);
+}
+
+const struct hantro_postproc_ops rockchip_vpu981_postproc_ops = {
+ .enable = rockchip_vpu981_postproc_enable,
+ .disable = rockchip_vpu981_postproc_disable,
+};
diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h b/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h
new file mode 100644
index 000000000000..182e6c830ff6
--- /dev/null
+++ b/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h
@@ -0,0 +1,477 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022, Collabora
+ *
+ * Author: Benjamin Gaignard <benjamin.gaignard@collabora.com>
+ */
+
+#ifndef _ROCKCHIP_VPU981_REGS_H_
+#define _ROCKCHIP_VPU981_REGS_H_
+
+#include "hantro.h"
+
+#define AV1_SWREG(nr) ((nr) * 4)
+
+#define AV1_DEC_REG(b, s, m) \
+ ((const struct hantro_reg) { \
+ .base = AV1_SWREG(b), \
+ .shift = s, \
+ .mask = m, \
+ })
+
+#define AV1_REG_INTERRUPT AV1_SWREG(1)
+#define AV1_REG_INTERRUPT_DEC_RDY_INT BIT(12)
+
+#define AV1_REG_CONFIG AV1_SWREG(2)
+#define AV1_REG_CONFIG_DEC_CLK_GATE_E BIT(10)
+
+#define av1_dec_e AV1_DEC_REG(1, 0, 0x1)
+#define av1_dec_abort_e AV1_DEC_REG(1, 5, 0x1)
+#define av1_dec_tile_int_e AV1_DEC_REG(1, 7, 0x1)
+
+#define av1_dec_clk_gate_e AV1_DEC_REG(2, 10, 0x1)
+
+#define av1_dec_out_ec_bypass AV1_DEC_REG(3, 8, 0x1)
+#define av1_write_mvs_e AV1_DEC_REG(3, 12, 0x1)
+#define av1_filtering_dis AV1_DEC_REG(3, 14, 0x1)
+#define av1_dec_out_dis AV1_DEC_REG(3, 15, 0x1)
+#define av1_dec_out_ec_byte_word AV1_DEC_REG(3, 16, 0x1)
+#define av1_skip_mode AV1_DEC_REG(3, 26, 0x1)
+#define av1_dec_mode AV1_DEC_REG(3, 27, 0x1f)
+
+#define av1_ref_frames AV1_DEC_REG(4, 0, 0xf)
+#define av1_pic_height_in_cbs AV1_DEC_REG(4, 6, 0x1fff)
+#define av1_pic_width_in_cbs AV1_DEC_REG(4, 19, 0x1fff)
+
+#define av1_ref_scaling_enable AV1_DEC_REG(5, 0, 0x1)
+#define av1_filt_level_base_gt32 AV1_DEC_REG(5, 1, 0x1)
+#define av1_error_resilient AV1_DEC_REG(5, 2, 0x1)
+#define av1_force_interger_mv AV1_DEC_REG(5, 3, 0x1)
+#define av1_allow_intrabc AV1_DEC_REG(5, 4, 0x1)
+#define av1_allow_screen_content_tools AV1_DEC_REG(5, 5, 0x1)
+#define av1_reduced_tx_set_used AV1_DEC_REG(5, 6, 0x1)
+#define av1_enable_dual_filter AV1_DEC_REG(5, 7, 0x1)
+#define av1_enable_jnt_comp AV1_DEC_REG(5, 8, 0x1)
+#define av1_allow_filter_intra AV1_DEC_REG(5, 9, 0x1)
+#define av1_enable_intra_edge_filter AV1_DEC_REG(5, 10, 0x1)
+#define av1_tempor_mvp_e AV1_DEC_REG(5, 11, 0x1)
+#define av1_allow_interintra AV1_DEC_REG(5, 12, 0x1)
+#define av1_allow_masked_compound AV1_DEC_REG(5, 13, 0x1)
+#define av1_enable_cdef AV1_DEC_REG(5, 14, 0x1)
+#define av1_switchable_motion_mode AV1_DEC_REG(5, 15, 0x1)
+#define av1_show_frame AV1_DEC_REG(5, 16, 0x1)
+#define av1_superres_is_scaled AV1_DEC_REG(5, 17, 0x1)
+#define av1_allow_warp AV1_DEC_REG(5, 18, 0x1)
+#define av1_disable_cdf_update AV1_DEC_REG(5, 19, 0x1)
+#define av1_preskip_segid AV1_DEC_REG(5, 20, 0x1)
+#define av1_delta_lf_present AV1_DEC_REG(5, 21, 0x1)
+#define av1_delta_lf_multi AV1_DEC_REG(5, 22, 0x1)
+#define av1_delta_lf_res_log AV1_DEC_REG(5, 23, 0x3)
+#define av1_strm_start_bit AV1_DEC_REG(5, 25, 0x7f)
+
+#define av1_stream_len AV1_DEC_REG(6, 0, 0xffffffff)
+
+#define av1_delta_q_present AV1_DEC_REG(7, 0, 0x1)
+#define av1_delta_q_res_log AV1_DEC_REG(7, 1, 0x3)
+#define av1_cdef_damping AV1_DEC_REG(7, 3, 0x3)
+#define av1_cdef_bits AV1_DEC_REG(7, 5, 0x3)
+#define av1_apply_grain AV1_DEC_REG(7, 7, 0x1)
+#define av1_num_y_points_b AV1_DEC_REG(7, 8, 0x1)
+#define av1_num_cb_points_b AV1_DEC_REG(7, 9, 0x1)
+#define av1_num_cr_points_b AV1_DEC_REG(7, 10, 0x1)
+#define av1_overlap_flag AV1_DEC_REG(7, 11, 0x1)
+#define av1_clip_to_restricted_range AV1_DEC_REG(7, 12, 0x1)
+#define av1_chroma_scaling_from_luma AV1_DEC_REG(7, 13, 0x1)
+#define av1_random_seed AV1_DEC_REG(7, 14, 0xffff)
+#define av1_blackwhite_e AV1_DEC_REG(7, 30, 0x1)
+
+#define av1_scaling_shift AV1_DEC_REG(8, 0, 0xf)
+#define av1_bit_depth_c_minus8 AV1_DEC_REG(8, 4, 0x3)
+#define av1_bit_depth_y_minus8 AV1_DEC_REG(8, 6, 0x3)
+#define av1_quant_base_qindex AV1_DEC_REG(8, 8, 0xff)
+#define av1_idr_pic_e AV1_DEC_REG(8, 16, 0x1)
+#define av1_superres_pic_width AV1_DEC_REG(8, 17, 0x7fff)
+
+#define av1_ref4_sign_bias AV1_DEC_REG(9, 2, 0x1)
+#define av1_ref5_sign_bias AV1_DEC_REG(9, 3, 0x1)
+#define av1_ref6_sign_bias AV1_DEC_REG(9, 4, 0x1)
+#define av1_mf1_type AV1_DEC_REG(9, 5, 0x7)
+#define av1_mf2_type AV1_DEC_REG(9, 8, 0x7)
+#define av1_mf3_type AV1_DEC_REG(9, 11, 0x7)
+#define av1_scale_denom_minus9 AV1_DEC_REG(9, 14, 0x7)
+#define av1_last_active_seg AV1_DEC_REG(9, 17, 0x7)
+#define av1_context_update_tile_id AV1_DEC_REG(9, 20, 0xfff)
+
+#define av1_tile_transpose AV1_DEC_REG(10, 0, 0x1)
+#define av1_tile_enable AV1_DEC_REG(10, 1, 0x1)
+#define av1_multicore_full_width AV1_DEC_REG(10, 2, 0xff)
+#define av1_num_tile_rows_8k AV1_DEC_REG(10, 10, 0x7f)
+#define av1_num_tile_cols_8k AV1_DEC_REG(10, 17, 0x7f)
+#define av1_multicore_tile_start_x AV1_DEC_REG(10, 24, 0xff)
+
+#define av1_use_temporal3_mvs AV1_DEC_REG(11, 0, 0x1)
+#define av1_use_temporal2_mvs AV1_DEC_REG(11, 1, 0x1)
+#define av1_use_temporal1_mvs AV1_DEC_REG(11, 2, 0x1)
+#define av1_use_temporal0_mvs AV1_DEC_REG(11, 3, 0x1)
+#define av1_comp_pred_mode AV1_DEC_REG(11, 4, 0x3)
+#define av1_high_prec_mv_e AV1_DEC_REG(11, 7, 0x1)
+#define av1_mcomp_filt_type AV1_DEC_REG(11, 8, 0x7)
+#define av1_multicore_expect_context_update AV1_DEC_REG(11, 11, 0x1)
+#define av1_multicore_sbx_offset AV1_DEC_REG(11, 12, 0x7f)
+#define av1_ulticore_tile_col AV1_DEC_REG(11, 19, 0x7f)
+#define av1_transform_mode AV1_DEC_REG(11, 27, 0x7)
+#define av1_dec_tile_size_mag AV1_DEC_REG(11, 30, 0x3)
+
+#define av1_seg_quant_sign AV1_DEC_REG(12, 2, 0xff)
+#define av1_max_cb_size AV1_DEC_REG(12, 10, 0x7)
+#define av1_min_cb_size AV1_DEC_REG(12, 13, 0x7)
+#define av1_comp_pred_fixed_ref AV1_DEC_REG(12, 16, 0x7)
+#define av1_multicore_tile_width AV1_DEC_REG(12, 19, 0x7f)
+#define av1_pic_height_pad AV1_DEC_REG(12, 26, 0x7)
+#define av1_pic_width_pad AV1_DEC_REG(12, 29, 0x7)
+
+#define av1_segment_e AV1_DEC_REG(13, 0, 0x1)
+#define av1_segment_upd_e AV1_DEC_REG(13, 1, 0x1)
+#define av1_segment_temp_upd_e AV1_DEC_REG(13, 2, 0x1)
+#define av1_comp_pred_var_ref0_av1 AV1_DEC_REG(13, 3, 0x7)
+#define av1_comp_pred_var_ref1_av1 AV1_DEC_REG(13, 6, 0x7)
+#define av1_lossless_e AV1_DEC_REG(13, 9, 0x1)
+#define av1_qp_delta_ch_ac_av1 AV1_DEC_REG(13, 11, 0x7f)
+#define av1_qp_delta_ch_dc_av1 AV1_DEC_REG(13, 18, 0x7f)
+#define av1_qp_delta_y_dc_av1 AV1_DEC_REG(13, 25, 0x7f)
+
+#define av1_quant_seg0 AV1_DEC_REG(14, 0, 0xff)
+#define av1_filt_level_seg0 AV1_DEC_REG(14, 8, 0x3f)
+#define av1_skip_seg0 AV1_DEC_REG(14, 14, 0x1)
+#define av1_refpic_seg0 AV1_DEC_REG(14, 15, 0xf)
+#define av1_filt_level_delta0_seg0 AV1_DEC_REG(14, 19, 0x7f)
+#define av1_filt_level0 AV1_DEC_REG(14, 26, 0x3f)
+
+#define av1_quant_seg1 AV1_DEC_REG(15, 0, 0xff)
+#define av1_filt_level_seg1 AV1_DEC_REG(15, 8, 0x3f)
+#define av1_skip_seg1 AV1_DEC_REG(15, 14, 0x1)
+#define av1_refpic_seg1 AV1_DEC_REG(15, 15, 0xf)
+#define av1_filt_level_delta0_seg1 AV1_DEC_REG(15, 19, 0x7f)
+#define av1_filt_level1 AV1_DEC_REG(15, 26, 0x3f)
+
+#define av1_quant_seg2 AV1_DEC_REG(16, 0, 0xff)
+#define av1_filt_level_seg2 AV1_DEC_REG(16, 8, 0x3f)
+#define av1_skip_seg2 AV1_DEC_REG(16, 14, 0x1)
+#define av1_refpic_seg2 AV1_DEC_REG(16, 15, 0xf)
+#define av1_filt_level_delta0_seg2 AV1_DEC_REG(16, 19, 0x7f)
+#define av1_filt_level2 AV1_DEC_REG(16, 26, 0x3f)
+
+#define av1_quant_seg3 AV1_DEC_REG(17, 0, 0xff)
+#define av1_filt_level_seg3 AV1_DEC_REG(17, 8, 0x3f)
+#define av1_skip_seg3 AV1_DEC_REG(17, 14, 0x1)
+#define av1_refpic_seg3 AV1_DEC_REG(17, 15, 0xf)
+#define av1_filt_level_delta0_seg3 AV1_DEC_REG(17, 19, 0x7f)
+#define av1_filt_level3 AV1_DEC_REG(17, 26, 0x3f)
+
+#define av1_quant_seg4 AV1_DEC_REG(18, 0, 0xff)
+#define av1_filt_level_seg4 AV1_DEC_REG(18, 8, 0x3f)
+#define av1_skip_seg4 AV1_DEC_REG(18, 14, 0x1)
+#define av1_refpic_seg4 AV1_DEC_REG(18, 15, 0xf)
+#define av1_filt_level_delta0_seg4 AV1_DEC_REG(18, 19, 0x7f)
+#define av1_lr_type AV1_DEC_REG(18, 26, 0x3f)
+
+#define av1_quant_seg5 AV1_DEC_REG(19, 0, 0xff)
+#define av1_filt_level_seg5 AV1_DEC_REG(19, 8, 0x3f)
+#define av1_skip_seg5 AV1_DEC_REG(19, 14, 0x1)
+#define av1_refpic_seg5 AV1_DEC_REG(19, 15, 0xf)
+#define av1_filt_level_delta0_seg5 AV1_DEC_REG(19, 19, 0x7f)
+#define av1_lr_unit_size AV1_DEC_REG(19, 26, 0x3f)
+
+#define av1_filt_level_delta1_seg0 AV1_DEC_REG(20, 0, 0x7f)
+#define av1_filt_level_delta2_seg0 AV1_DEC_REG(20, 7, 0x7f)
+#define av1_filt_level_delta3_seg0 AV1_DEC_REG(20, 14, 0x7f)
+#define av1_global_mv_seg0 AV1_DEC_REG(20, 21, 0x1)
+#define av1_mf1_last_offset AV1_DEC_REG(20, 22, 0x1ff)
+
+#define av1_filt_level_delta1_seg1 AV1_DEC_REG(21, 0, 0x7f)
+#define av1_filt_level_delta2_seg1 AV1_DEC_REG(21, 7, 0x7f)
+#define av1_filt_level_delta3_seg1 AV1_DEC_REG(21, 14, 0x7f)
+#define av1_global_mv_seg1 AV1_DEC_REG(21, 21, 0x1)
+#define av1_mf1_last2_offset AV1_DEC_REG(21, 22, 0x1ff)
+
+#define av1_filt_level_delta1_seg2 AV1_DEC_REG(22, 0, 0x7f)
+#define av1_filt_level_delta2_seg2 AV1_DEC_REG(22, 7, 0x7f)
+#define av1_filt_level_delta3_seg2 AV1_DEC_REG(22, 14, 0x7f)
+#define av1_global_mv_seg2 AV1_DEC_REG(22, 21, 0x1)
+#define av1_mf1_last3_offset AV1_DEC_REG(22, 22, 0x1ff)
+
+#define av1_filt_level_delta1_seg3 AV1_DEC_REG(23, 0, 0x7f)
+#define av1_filt_level_delta2_seg3 AV1_DEC_REG(23, 7, 0x7f)
+#define av1_filt_level_delta3_seg3 AV1_DEC_REG(23, 14, 0x7f)
+#define av1_global_mv_seg3 AV1_DEC_REG(23, 21, 0x1)
+#define av1_mf1_golden_offset AV1_DEC_REG(23, 22, 0x1ff)
+
+#define av1_filt_level_delta1_seg4 AV1_DEC_REG(24, 0, 0x7f)
+#define av1_filt_level_delta2_seg4 AV1_DEC_REG(24, 7, 0x7f)
+#define av1_filt_level_delta3_seg4 AV1_DEC_REG(24, 14, 0x7f)
+#define av1_global_mv_seg4 AV1_DEC_REG(24, 21, 0x1)
+#define av1_mf1_bwdref_offset AV1_DEC_REG(24, 22, 0x1ff)
+
+#define av1_filt_level_delta1_seg5 AV1_DEC_REG(25, 0, 0x7f)
+#define av1_filt_level_delta2_seg5 AV1_DEC_REG(25, 7, 0x7f)
+#define av1_filt_level_delta3_seg5 AV1_DEC_REG(25, 14, 0x7f)
+#define av1_global_mv_seg5 AV1_DEC_REG(25, 21, 0x1)
+#define av1_mf1_altref2_offset AV1_DEC_REG(25, 22, 0x1ff)
+
+#define av1_filt_level_delta1_seg6 AV1_DEC_REG(26, 0, 0x7f)
+#define av1_filt_level_delta2_seg6 AV1_DEC_REG(26, 7, 0x7f)
+#define av1_filt_level_delta3_seg6 AV1_DEC_REG(26, 14, 0x7f)
+#define av1_global_mv_seg6 AV1_DEC_REG(26, 21, 0x1)
+#define av1_mf1_altref_offset AV1_DEC_REG(26, 22, 0x1ff)
+
+#define av1_filt_level_delta1_seg7 AV1_DEC_REG(27, 0, 0x7f)
+#define av1_filt_level_delta2_seg7 AV1_DEC_REG(27, 7, 0x7f)
+#define av1_filt_level_delta3_seg7 AV1_DEC_REG(27, 14, 0x7f)
+#define av1_global_mv_seg7 AV1_DEC_REG(27, 21, 0x1)
+#define av1_mf2_last_offset AV1_DEC_REG(27, 22, 0x1ff)
+
+#define av1_cb_offset AV1_DEC_REG(28, 0, 0x1ff)
+#define av1_cb_luma_mult AV1_DEC_REG(28, 9, 0xff)
+#define av1_cb_mult AV1_DEC_REG(28, 17, 0xff)
+#define av1_quant_delta_v_dc AV1_DEC_REG(28, 25, 0x7f)
+
+#define av1_cr_offset AV1_DEC_REG(29, 0, 0x1ff)
+#define av1_cr_luma_mult AV1_DEC_REG(29, 9, 0xff)
+#define av1_cr_mult AV1_DEC_REG(29, 17, 0xff)
+#define av1_quant_delta_v_ac AV1_DEC_REG(29, 25, 0x7f)
+
+#define av1_filt_ref_adj_5 AV1_DEC_REG(30, 0, 0x7f)
+#define av1_filt_ref_adj_4 AV1_DEC_REG(30, 7, 0x7f)
+#define av1_filt_mb_adj_1 AV1_DEC_REG(30, 14, 0x7f)
+#define av1_filt_mb_adj_0 AV1_DEC_REG(30, 21, 0x7f)
+#define av1_filt_sharpness AV1_DEC_REG(30, 28, 0x7)
+
+#define av1_quant_seg6 AV1_DEC_REG(31, 0, 0xff)
+#define av1_filt_level_seg6 AV1_DEC_REG(31, 8, 0x3f)
+#define av1_skip_seg6 AV1_DEC_REG(31, 14, 0x1)
+#define av1_refpic_seg6 AV1_DEC_REG(31, 15, 0xf)
+#define av1_filt_level_delta0_seg6 AV1_DEC_REG(31, 19, 0x7f)
+#define av1_skip_ref0 AV1_DEC_REG(31, 26, 0xf)
+
+#define av1_quant_seg7 AV1_DEC_REG(32, 0, 0xff)
+#define av1_filt_level_seg7 AV1_DEC_REG(32, 8, 0x3f)
+#define av1_skip_seg7 AV1_DEC_REG(32, 14, 0x1)
+#define av1_refpic_seg7 AV1_DEC_REG(32, 15, 0xf)
+#define av1_filt_level_delta0_seg7 AV1_DEC_REG(32, 19, 0x7f)
+#define av1_skip_ref1 AV1_DEC_REG(32, 26, 0xf)
+
+#define av1_ref0_height AV1_DEC_REG(33, 0, 0xffff)
+#define av1_ref0_width AV1_DEC_REG(33, 16, 0xffff)
+
+#define av1_ref1_height AV1_DEC_REG(34, 0, 0xffff)
+#define av1_ref1_width AV1_DEC_REG(34, 16, 0xffff)
+
+#define av1_ref2_height AV1_DEC_REG(35, 0, 0xffff)
+#define av1_ref2_width AV1_DEC_REG(35, 16, 0xffff)
+
+#define av1_ref0_ver_scale AV1_DEC_REG(36, 0, 0xffff)
+#define av1_ref0_hor_scale AV1_DEC_REG(36, 16, 0xffff)
+
+#define av1_ref1_ver_scale AV1_DEC_REG(37, 0, 0xffff)
+#define av1_ref1_hor_scale AV1_DEC_REG(37, 16, 0xffff)
+
+#define av1_ref2_ver_scale AV1_DEC_REG(38, 0, 0xffff)
+#define av1_ref2_hor_scale AV1_DEC_REG(38, 16, 0xffff)
+
+#define av1_ref3_ver_scale AV1_DEC_REG(39, 0, 0xffff)
+#define av1_ref3_hor_scale AV1_DEC_REG(39, 16, 0xffff)
+
+#define av1_ref4_ver_scale AV1_DEC_REG(40, 0, 0xffff)
+#define av1_ref4_hor_scale AV1_DEC_REG(40, 16, 0xffff)
+
+#define av1_ref5_ver_scale AV1_DEC_REG(41, 0, 0xffff)
+#define av1_ref5_hor_scale AV1_DEC_REG(41, 16, 0xffff)
+
+#define av1_ref6_ver_scale AV1_DEC_REG(42, 0, 0xffff)
+#define av1_ref6_hor_scale AV1_DEC_REG(42, 16, 0xffff)
+
+#define av1_ref3_height AV1_DEC_REG(43, 0, 0xffff)
+#define av1_ref3_width AV1_DEC_REG(43, 16, 0xffff)
+
+#define av1_ref4_height AV1_DEC_REG(44, 0, 0xffff)
+#define av1_ref4_width AV1_DEC_REG(44, 16, 0xffff)
+
+#define av1_ref5_height AV1_DEC_REG(45, 0, 0xffff)
+#define av1_ref5_width AV1_DEC_REG(45, 16, 0xffff)
+
+#define av1_ref6_height AV1_DEC_REG(46, 0, 0xffff)
+#define av1_ref6_width AV1_DEC_REG(46, 16, 0xffff)
+
+#define av1_mf2_last2_offset AV1_DEC_REG(47, 0, 0x1ff)
+#define av1_mf2_last3_offset AV1_DEC_REG(47, 9, 0x1ff)
+#define av1_mf2_golden_offset AV1_DEC_REG(47, 18, 0x1ff)
+#define av1_qmlevel_y AV1_DEC_REG(47, 27, 0xf)
+
+#define av1_mf2_bwdref_offset AV1_DEC_REG(48, 0, 0x1ff)
+#define av1_mf2_altref2_offset AV1_DEC_REG(48, 9, 0x1ff)
+#define av1_mf2_altref_offset AV1_DEC_REG(48, 18, 0x1ff)
+#define av1_qmlevel_u AV1_DEC_REG(48, 27, 0xf)
+
+#define av1_filt_ref_adj_6 AV1_DEC_REG(49, 0, 0x7f)
+#define av1_filt_ref_adj_7 AV1_DEC_REG(49, 7, 0x7f)
+#define av1_qmlevel_v AV1_DEC_REG(49, 14, 0xf)
+
+#define av1_superres_chroma_step AV1_DEC_REG(51, 0, 0x3fff)
+#define av1_superres_luma_step AV1_DEC_REG(51, 14, 0x3fff)
+
+#define av1_superres_init_chroma_subpel_x AV1_DEC_REG(52, 0, 0x3fff)
+#define av1_superres_init_luma_subpel_x AV1_DEC_REG(52, 14, 0x3fff)
+
+#define av1_cdef_chroma_secondary_strength AV1_DEC_REG(53, 0, 0xffff)
+#define av1_cdef_luma_secondary_strength AV1_DEC_REG(53, 16, 0xffff)
+
+#define av1_apf_threshold AV1_DEC_REG(55, 0, 0xffff)
+#define av1_apf_single_pu_mode AV1_DEC_REG(55, 30, 0x1)
+#define av1_apf_disable AV1_DEC_REG(55, 30, 0x1)
+
+#define av1_dec_max_burst AV1_DEC_REG(58, 0, 0xff)
+#define av1_dec_buswidth AV1_DEC_REG(58, 8, 0x7)
+#define av1_dec_multicore_mode AV1_DEC_REG(58, 11, 0x3)
+#define av1_dec_axi_wd_id_e AV1_DEC_REG(58, 13, 0x1)
+#define av1_dec_axi_rd_id_e AV1_DEC_REG(58, 14, 0x1)
+#define av1_dec_mc_polltime AV1_DEC_REG(58, 17, 0x3ff)
+#define av1_dec_mc_pollmode AV1_DEC_REG(58, 27, 0x3)
+
+#define av1_filt_ref_adj_3 AV1_DEC_REG(59, 0, 0x3f)
+#define av1_filt_ref_adj_2 AV1_DEC_REG(59, 7, 0x3f)
+#define av1_filt_ref_adj_1 AV1_DEC_REG(59, 14, 0x3f)
+#define av1_filt_ref_adj_0 AV1_DEC_REG(59, 21, 0x3f)
+#define av1_ref0_sign_bias AV1_DEC_REG(59, 28, 0x1)
+#define av1_ref1_sign_bias AV1_DEC_REG(59, 29, 0x1)
+#define av1_ref2_sign_bias AV1_DEC_REG(59, 30, 0x1)
+#define av1_ref3_sign_bias AV1_DEC_REG(59, 31, 0x1)
+
+#define av1_cur_last_roffset AV1_DEC_REG(184, 0, 0x1ff)
+#define av1_cur_last_offset AV1_DEC_REG(184, 9, 0x1ff)
+#define av1_mf3_last_offset AV1_DEC_REG(184, 18, 0x1ff)
+#define av1_ref0_gm_mode AV1_DEC_REG(184, 27, 0x3)
+
+#define av1_cur_last2_roffset AV1_DEC_REG(185, 0, 0x1ff)
+#define av1_cur_last2_offset AV1_DEC_REG(185, 9, 0x1ff)
+#define av1_mf3_last2_offset AV1_DEC_REG(185, 18, 0x1ff)
+#define av1_ref1_gm_mode AV1_DEC_REG(185, 27, 0x3)
+
+#define av1_cur_last3_roffset AV1_DEC_REG(186, 0, 0x1ff)
+#define av1_cur_last3_offset AV1_DEC_REG(186, 9, 0x1ff)
+#define av1_mf3_last3_offset AV1_DEC_REG(186, 18, 0x1ff)
+#define av1_ref2_gm_mode AV1_DEC_REG(186, 27, 0x3)
+
+#define av1_cur_golden_roffset AV1_DEC_REG(187, 0, 0x1ff)
+#define av1_cur_golden_offset AV1_DEC_REG(187, 9, 0x1ff)
+#define av1_mf3_golden_offset AV1_DEC_REG(187, 18, 0x1ff)
+#define av1_ref3_gm_mode AV1_DEC_REG(187, 27, 0x3)
+
+#define av1_cur_bwdref_roffset AV1_DEC_REG(188, 0, 0x1ff)
+#define av1_cur_bwdref_offset AV1_DEC_REG(188, 9, 0x1ff)
+#define av1_mf3_bwdref_offset AV1_DEC_REG(188, 18, 0x1ff)
+#define av1_ref4_gm_mode AV1_DEC_REG(188, 27, 0x3)
+
+#define av1_cur_altref2_roffset AV1_DEC_REG(257, 0, 0x1ff)
+#define av1_cur_altref2_offset AV1_DEC_REG(257, 9, 0x1ff)
+#define av1_mf3_altref2_offset AV1_DEC_REG(257, 18, 0x1ff)
+#define av1_ref5_gm_mode AV1_DEC_REG(257, 27, 0x3)
+
+#define av1_strm_buffer_len AV1_DEC_REG(258, 0, 0xffffffff)
+
+#define av1_strm_start_offset AV1_DEC_REG(259, 0, 0xffffffff)
+
+#define av1_ppd_blend_exist AV1_DEC_REG(260, 21, 0x1)
+#define av1_ppd_dith_exist AV1_DEC_REG(260, 23, 0x1)
+#define av1_ablend_crop_e AV1_DEC_REG(260, 24, 0x1)
+#define av1_pp_format_p010_e AV1_DEC_REG(260, 25, 0x1)
+#define av1_pp_format_customer1_e AV1_DEC_REG(260, 26, 0x1)
+#define av1_pp_crop_exist AV1_DEC_REG(260, 27, 0x1)
+#define av1_pp_up_level AV1_DEC_REG(260, 28, 0x1)
+#define av1_pp_down_level AV1_DEC_REG(260, 29, 0x3)
+#define av1_pp_exist AV1_DEC_REG(260, 31, 0x1)
+
+#define av1_cur_altref_roffset AV1_DEC_REG(262, 0, 0x1ff)
+#define av1_cur_altref_offset AV1_DEC_REG(262, 9, 0x1ff)
+#define av1_mf3_altref_offset AV1_DEC_REG(262, 18, 0x1ff)
+#define av1_ref6_gm_mode AV1_DEC_REG(262, 27, 0x3)
+
+#define av1_cdef_luma_primary_strength AV1_DEC_REG(263, 0, 0xffffffff)
+
+#define av1_cdef_chroma_primary_strength AV1_DEC_REG(264, 0, 0xffffffff)
+
+#define av1_axi_arqos AV1_DEC_REG(265, 0, 0xf)
+#define av1_axi_awqos AV1_DEC_REG(265, 4, 0xf)
+#define av1_axi_wr_ostd_threshold AV1_DEC_REG(265, 8, 0x3ff)
+#define av1_axi_rd_ostd_threshold AV1_DEC_REG(265, 18, 0x3ff)
+#define av1_axi_wr_4k_dis AV1_DEC_REG(265, 31, 0x1)
+
+#define av1_128bit_mode AV1_DEC_REG(266, 5, 0x1)
+#define av1_wr_shaper_bypass AV1_DEC_REG(266, 10, 0x1)
+#define av1_error_conceal_e AV1_DEC_REG(266, 30, 0x1)
+
+#define av1_superres_chroma_step_invra AV1_DEC_REG(298, 0, 0xffff)
+#define av1_superres_luma_step_invra AV1_DEC_REG(298, 16, 0xffff)
+
+#define av1_dec_alignment AV1_DEC_REG(314, 0, 0xffff)
+
+#define av1_ext_timeout_cycles AV1_DEC_REG(318, 0, 0x7fffffff)
+#define av1_ext_timeout_override_e AV1_DEC_REG(318, 31, 0x1)
+
+#define av1_timeout_cycles AV1_DEC_REG(319, 0, 0x7fffffff)
+#define av1_timeout_override_e AV1_DEC_REG(319, 31, 0x1)
+
+#define av1_pp_out_e AV1_DEC_REG(320, 0, 0x1)
+#define av1_pp_cr_first AV1_DEC_REG(320, 1, 0x1)
+#define av1_pp_out_mode AV1_DEC_REG(320, 2, 0x1)
+#define av1_pp_out_tile_e AV1_DEC_REG(320, 3, 0x1)
+#define av1_pp_status AV1_DEC_REG(320, 4, 0xf)
+#define av1_pp_in_blk_size AV1_DEC_REG(320, 8, 0x7)
+#define av1_pp_out_p010_fmt AV1_DEC_REG(320, 11, 0x3)
+#define av1_pp_out_rgb_fmt AV1_DEC_REG(320, 13, 0x1f)
+#define av1_rgb_range_max AV1_DEC_REG(320, 18, 0xfff)
+#define av1_pp_rgb_planar AV1_DEC_REG(320, 30, 0x1)
+
+#define av1_scale_hratio AV1_DEC_REG(322, 0, 0x3ffff)
+#define av1_pp_out_format AV1_DEC_REG(322, 18, 0x1f)
+#define av1_ver_scale_mode AV1_DEC_REG(322, 23, 0x3)
+#define av1_hor_scale_mode AV1_DEC_REG(322, 25, 0x3)
+#define av1_pp_in_format AV1_DEC_REG(322, 27, 0x1f)
+
+#define av1_pp_out_c_stride AV1_DEC_REG(329, 0, 0xffff)
+#define av1_pp_out_y_stride AV1_DEC_REG(329, 16, 0xffff)
+
+#define av1_pp_in_height AV1_DEC_REG(331, 0, 0xffff)
+#define av1_pp_in_width AV1_DEC_REG(331, 16, 0xffff)
+
+#define av1_pp_out_height AV1_DEC_REG(332, 0, 0xffff)
+#define av1_pp_out_width AV1_DEC_REG(332, 16, 0xffff)
+
+#define av1_pp1_dup_ver AV1_DEC_REG(394, 0, 0xff)
+#define av1_pp1_dup_hor AV1_DEC_REG(394, 8, 0xff)
+#define av1_pp0_dup_ver AV1_DEC_REG(394, 16, 0xff)
+#define av1_pp0_dup_hor AV1_DEC_REG(394, 24, 0xff)
+
+#define AV1_TILE_OUT_LU (AV1_SWREG(65))
+#define AV1_REFERENCE_Y(i) (AV1_SWREG(67) + ((i) * 0x8))
+#define AV1_SEGMENTATION (AV1_SWREG(81))
+#define AV1_GLOBAL_MODEL (AV1_SWREG(83))
+#define AV1_CDEF_COL (AV1_SWREG(85))
+#define AV1_SR_COL (AV1_SWREG(89))
+#define AV1_LR_COL (AV1_SWREG(91))
+#define AV1_FILM_GRAIN (AV1_SWREG(95))
+#define AV1_TILE_OUT_CH (AV1_SWREG(99))
+#define AV1_REFERENCE_CB(i) (AV1_SWREG(101) + ((i) * 0x8))
+#define AV1_TILE_OUT_MV (AV1_SWREG(133))
+#define AV1_REFERENCE_MV(i) (AV1_SWREG(135) + ((i) * 0x8))
+#define AV1_TILE_BASE (AV1_SWREG(167))
+#define AV1_INPUT_STREAM (AV1_SWREG(169))
+#define AV1_PROP_TABLE_OUT (AV1_SWREG(171))
+#define AV1_PROP_TABLE (AV1_SWREG(173))
+#define AV1_MC_SYNC_CURR (AV1_SWREG(175))
+#define AV1_MC_SYNC_LEFT (AV1_SWREG(177))
+#define AV1_DB_DATA_COL (AV1_SWREG(179))
+#define AV1_DB_CTRL_COL (AV1_SWREG(183))
+#define AV1_PP_OUT_LU (AV1_SWREG(326))
+#define AV1_PP_OUT_CH (AV1_SWREG(328))
+
+#endif /* _ROCKCHIP_VPU981_REGS_H_ */
diff --git a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c
index 8de6fd2e8eef..816ffa905a4b 100644
--- a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c
+++ b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c
@@ -13,9 +13,13 @@
#include "hantro_g1_regs.h"
#include "hantro_h1_regs.h"
#include "rockchip_vpu2_regs.h"
+#include "rockchip_vpu981_regs.h"
#define RK3066_ACLK_MAX_FREQ (300 * 1000 * 1000)
#define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000)
+#define RK3588_ACLK_MAX_FREQ (300 * 1000 * 1000)
+
+#define ROCKCHIP_VPU981_MIN_SIZE 64
/*
* Supported formats.
@@ -74,6 +78,37 @@ static const struct hantro_fmt rockchip_vpu1_postproc_fmts[] = {
},
};
+static const struct hantro_fmt rockchip_vpu981_postproc_fmts[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .codec_mode = HANTRO_MODE_NONE,
+ .match_depth = true,
+ .postprocessed = true,
+ .frmsize = {
+ .min_width = ROCKCHIP_VPU981_MIN_SIZE,
+ .max_width = FMT_UHD_WIDTH,
+ .step_width = MB_DIM,
+ .min_height = ROCKCHIP_VPU981_MIN_SIZE,
+ .max_height = FMT_UHD_HEIGHT,
+ .step_height = MB_DIM,
+ },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_P010,
+ .codec_mode = HANTRO_MODE_NONE,
+ .match_depth = true,
+ .postprocessed = true,
+ .frmsize = {
+ .min_width = ROCKCHIP_VPU981_MIN_SIZE,
+ .max_width = FMT_UHD_WIDTH,
+ .step_width = MB_DIM,
+ .min_height = ROCKCHIP_VPU981_MIN_SIZE,
+ .max_height = FMT_UHD_HEIGHT,
+ .step_height = MB_DIM,
+ },
+ },
+};
+
static const struct hantro_fmt rk3066_vpu_dec_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
@@ -277,6 +312,48 @@ static const struct hantro_fmt rk3399_vpu_dec_fmts[] = {
},
};
+static const struct hantro_fmt rockchip_vpu981_dec_fmts[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_NV12_4L4,
+ .codec_mode = HANTRO_MODE_NONE,
+ .match_depth = true,
+ .frmsize = {
+ .min_width = ROCKCHIP_VPU981_MIN_SIZE,
+ .max_width = FMT_UHD_WIDTH,
+ .step_width = MB_DIM,
+ .min_height = ROCKCHIP_VPU981_MIN_SIZE,
+ .max_height = FMT_UHD_HEIGHT,
+ .step_height = MB_DIM,
+ },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV15_4L4,
+ .codec_mode = HANTRO_MODE_NONE,
+ .match_depth = true,
+ .frmsize = {
+ .min_width = ROCKCHIP_VPU981_MIN_SIZE,
+ .max_width = FMT_UHD_WIDTH,
+ .step_width = MB_DIM,
+ .min_height = ROCKCHIP_VPU981_MIN_SIZE,
+ .max_height = FMT_UHD_HEIGHT,
+ .step_height = MB_DIM,
+ },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_AV1_FRAME,
+ .codec_mode = HANTRO_MODE_AV1_DEC,
+ .max_depth = 2,
+ .frmsize = {
+ .min_width = ROCKCHIP_VPU981_MIN_SIZE,
+ .max_width = FMT_UHD_WIDTH,
+ .step_width = MB_DIM,
+ .min_height = ROCKCHIP_VPU981_MIN_SIZE,
+ .max_height = FMT_UHD_HEIGHT,
+ .step_height = MB_DIM,
+ },
+ },
+};
+
static irqreturn_t rockchip_vpu1_vepu_irq(int irq, void *dev_id)
{
struct hantro_dev *vpu = dev_id;
@@ -331,6 +408,24 @@ static irqreturn_t rockchip_vpu2_vepu_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static irqreturn_t rk3588_vpu981_irq(int irq, void *dev_id)
+{
+ struct hantro_dev *vpu = dev_id;
+ enum vb2_buffer_state state;
+ u32 status;
+
+ status = vdpu_read(vpu, AV1_REG_INTERRUPT);
+ state = (status & AV1_REG_INTERRUPT_DEC_RDY_INT) ?
+ VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
+
+ vdpu_write(vpu, 0, AV1_REG_INTERRUPT);
+ vdpu_write(vpu, AV1_REG_CONFIG_DEC_CLK_GATE_E, AV1_REG_CONFIG);
+
+ hantro_irq_done(vpu, state);
+
+ return IRQ_HANDLED;
+}
+
static int rk3036_vpu_hw_init(struct hantro_dev *vpu)
{
/* Bump ACLK to max. possible freq. to improve performance. */
@@ -346,6 +441,13 @@ static int rk3066_vpu_hw_init(struct hantro_dev *vpu)
return 0;
}
+static int rk3588_vpu981_hw_init(struct hantro_dev *vpu)
+{
+ /* Bump ACLKs to max. possible freq. to improve performance. */
+ clk_set_rate(vpu->clocks[0].clk, RK3588_ACLK_MAX_FREQ);
+ return 0;
+}
+
static int rockchip_vpu_hw_init(struct hantro_dev *vpu)
{
/* Bump ACLK to max. possible freq. to improve performance. */
@@ -498,6 +600,14 @@ static const struct hantro_codec_ops rk3568_vepu_codec_ops[] = {
},
};
+static const struct hantro_codec_ops rk3588_vpu981_codec_ops[] = {
+ [HANTRO_MODE_AV1_DEC] = {
+ .run = rockchip_vpu981_av1_dec_run,
+ .init = rockchip_vpu981_av1_dec_init,
+ .exit = rockchip_vpu981_av1_dec_exit,
+ .done = rockchip_vpu981_av1_dec_done,
+ },
+};
/*
* VPU variant.
*/
@@ -529,10 +639,18 @@ static const char * const rk3066_vpu_clk_names[] = {
"aclk_vepu", "hclk_vepu"
};
+static const struct hantro_irq rk3588_vpu981_irqs[] = {
+ { "vdpu", rk3588_vpu981_irq },
+};
+
static const char * const rockchip_vpu_clk_names[] = {
"aclk", "hclk"
};
+static const char * const rk3588_vpu981_vpu_clk_names[] = {
+ "aclk", "hclk", "aclk_vdpu_root", "hclk_vdpu_root"
+};
+
/* VDPU1/VEPU1 */
const struct hantro_variant rk3036_vpu_variant = {
@@ -678,3 +796,19 @@ const struct hantro_variant px30_vpu_variant = {
.clk_names = rockchip_vpu_clk_names,
.num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
};
+
+const struct hantro_variant rk3588_vpu981_variant = {
+ .dec_offset = 0x0,
+ .dec_fmts = rockchip_vpu981_dec_fmts,
+ .num_dec_fmts = ARRAY_SIZE(rockchip_vpu981_dec_fmts),
+ .postproc_fmts = rockchip_vpu981_postproc_fmts,
+ .num_postproc_fmts = ARRAY_SIZE(rockchip_vpu981_postproc_fmts),
+ .postproc_ops = &rockchip_vpu981_postproc_ops,
+ .codec = HANTRO_AV1_DECODER,
+ .codec_ops = rk3588_vpu981_codec_ops,
+ .irqs = rk3588_vpu981_irqs,
+ .num_irqs = ARRAY_SIZE(rk3588_vpu981_irqs),
+ .init = rk3588_vpu981_hw_init,
+ .clk_names = rk3588_vpu981_vpu_clk_names,
+ .num_clocks = ARRAY_SIZE(rk3588_vpu981_vpu_clk_names)
+};
diff --git a/drivers/media/platform/via/via-camera.c b/drivers/media/platform/via/via-camera.c
index 450254403fa8..4cb8f29e2f14 100644
--- a/drivers/media/platform/via/via-camera.c
+++ b/drivers/media/platform/via/via-camera.c
@@ -11,7 +11,7 @@
#include <linux/device.h>
#include <linux/list.h>
#include <linux/pci.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/videodev2.h>
@@ -26,7 +26,6 @@
#include <linux/dma-mapping.h>
#include <linux/pm_qos.h>
#include <linux/via-core.h>
-#include <linux/via-gpio.h>
#include <linux/via_i2c.h>
#ifdef CONFIG_X86
@@ -71,8 +70,8 @@ struct via_camera {
/*
* GPIO info for power/reset management
*/
- int power_gpio;
- int reset_gpio;
+ struct gpio_desc *power_gpio;
+ struct gpio_desc *reset_gpio;
/*
* I/O memory stuff.
*/
@@ -180,27 +179,19 @@ static struct via_format *via_find_format(u32 pixelformat)
*/
static int via_sensor_power_setup(struct via_camera *cam)
{
- int ret;
+ struct device *dev = &cam->platdev->dev;
+
+ cam->power_gpio = devm_gpiod_get(dev, "VGPIO3", GPIOD_OUT_LOW);
+ if (IS_ERR(cam->power_gpio))
+ return dev_err_probe(dev, PTR_ERR(cam->power_gpio),
+ "failed to get power GPIO");
+
+ /* Request the reset line asserted */
+ cam->reset_gpio = devm_gpiod_get(dev, "VGPIO2", GPIOD_OUT_HIGH);
+ if (IS_ERR(cam->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(cam->reset_gpio),
+ "failed to get reset GPIO");
- cam->power_gpio = viafb_gpio_lookup("VGPIO3");
- cam->reset_gpio = viafb_gpio_lookup("VGPIO2");
- if (!gpio_is_valid(cam->power_gpio) || !gpio_is_valid(cam->reset_gpio)) {
- dev_err(&cam->platdev->dev, "Unable to find GPIO lines\n");
- return -EINVAL;
- }
- ret = gpio_request(cam->power_gpio, "viafb-camera");
- if (ret) {
- dev_err(&cam->platdev->dev, "Unable to request power GPIO\n");
- return ret;
- }
- ret = gpio_request(cam->reset_gpio, "viafb-camera");
- if (ret) {
- dev_err(&cam->platdev->dev, "Unable to request reset GPIO\n");
- gpio_free(cam->power_gpio);
- return ret;
- }
- gpio_direction_output(cam->power_gpio, 0);
- gpio_direction_output(cam->reset_gpio, 0);
return 0;
}
@@ -209,25 +200,23 @@ static int via_sensor_power_setup(struct via_camera *cam)
*/
static void via_sensor_power_up(struct via_camera *cam)
{
- gpio_set_value(cam->power_gpio, 1);
- gpio_set_value(cam->reset_gpio, 0);
+ gpiod_set_value(cam->power_gpio, 1);
+ gpiod_set_value(cam->reset_gpio, 1);
msleep(20); /* Probably excessive */
- gpio_set_value(cam->reset_gpio, 1);
+ gpiod_set_value(cam->reset_gpio, 0);
msleep(20);
}
static void via_sensor_power_down(struct via_camera *cam)
{
- gpio_set_value(cam->power_gpio, 0);
- gpio_set_value(cam->reset_gpio, 0);
+ gpiod_set_value(cam->power_gpio, 0);
+ gpiod_set_value(cam->reset_gpio, 1);
}
static void via_sensor_power_release(struct via_camera *cam)
{
via_sensor_power_down(cam);
- gpio_free(cam->power_gpio);
- gpio_free(cam->reset_gpio);
}
/* --------------------------------------------------------------------------*/
diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
index 1d9f32e5a917..6d273abfe16c 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -24,7 +24,6 @@ struct video_mux {
struct v4l2_subdev subdev;
struct v4l2_async_notifier notifier;
struct media_pad *pads;
- struct v4l2_mbus_framefmt *format_mbus;
struct mux_control *mux;
struct mutex lock;
int active;
@@ -71,6 +70,9 @@ static int video_mux_link_setup(struct media_entity *entity,
mutex_lock(&vmux->lock);
if (flags & MEDIA_LNK_FL_ENABLED) {
+ struct v4l2_subdev_state *sd_state;
+ struct v4l2_mbus_framefmt *source_mbusformat;
+
if (vmux->active == local->index)
goto out;
@@ -86,7 +88,12 @@ static int video_mux_link_setup(struct media_entity *entity,
vmux->active = local->index;
/* Propagate the active format to the source */
- vmux->format_mbus[source_pad] = vmux->format_mbus[vmux->active];
+ sd_state = v4l2_subdev_lock_and_get_active_state(sd);
+ source_mbusformat = v4l2_subdev_get_pad_format(sd, sd_state,
+ source_pad);
+ *source_mbusformat = *v4l2_subdev_get_pad_format(sd, sd_state,
+ vmux->active);
+ v4l2_subdev_unlock_state(sd_state);
} else {
if (vmux->active != local->index)
goto out;
@@ -138,40 +145,6 @@ static const struct v4l2_subdev_video_ops video_mux_subdev_video_ops = {
.s_stream = video_mux_s_stream,
};
-static struct v4l2_mbus_framefmt *
-__video_mux_get_pad_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- unsigned int pad, u32 which)
-{
- struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
-
- switch (which) {
- case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_format(sd, sd_state, pad);
- case V4L2_SUBDEV_FORMAT_ACTIVE:
- return &vmux->format_mbus[pad];
- default:
- return NULL;
- }
-}
-
-static int video_mux_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_format *sdformat)
-{
- struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
-
- mutex_lock(&vmux->lock);
-
- sdformat->format = *__video_mux_get_pad_format(sd, sd_state,
- sdformat->pad,
- sdformat->which);
-
- mutex_unlock(&vmux->lock);
-
- return 0;
-}
-
static int video_mux_set_format(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
@@ -181,14 +154,11 @@ static int video_mux_set_format(struct v4l2_subdev *sd,
struct media_pad *pad = &vmux->pads[sdformat->pad];
u16 source_pad = sd->entity.num_pads - 1;
- mbusformat = __video_mux_get_pad_format(sd, sd_state, sdformat->pad,
- sdformat->which);
+ mbusformat = v4l2_subdev_get_pad_format(sd, sd_state, sdformat->pad);
if (!mbusformat)
return -EINVAL;
- source_mbusformat = __video_mux_get_pad_format(sd, sd_state,
- source_pad,
- sdformat->which);
+ source_mbusformat = v4l2_subdev_get_pad_format(sd, sd_state, source_pad);
if (!source_mbusformat)
return -EINVAL;
@@ -298,7 +268,8 @@ static int video_mux_set_format(struct v4l2_subdev *sd,
/* Source pad mirrors active sink pad, no limitations on sink pads */
if ((pad->flags & MEDIA_PAD_FL_SOURCE) && vmux->active >= 0)
- sdformat->format = vmux->format_mbus[vmux->active];
+ sdformat->format = *v4l2_subdev_get_pad_format(sd, sd_state,
+ vmux->active);
*mbusformat = sdformat->format;
@@ -321,7 +292,7 @@ static int video_mux_init_cfg(struct v4l2_subdev *sd,
mutex_lock(&vmux->lock);
for (i = 0; i < sd->entity.num_pads; i++) {
- mbusformat = v4l2_subdev_get_try_format(sd, sd_state, i);
+ mbusformat = v4l2_subdev_get_pad_format(sd, sd_state, i);
*mbusformat = video_mux_format_mbus_default;
}
@@ -332,7 +303,7 @@ static int video_mux_init_cfg(struct v4l2_subdev *sd,
static const struct v4l2_subdev_pad_ops video_mux_pad_ops = {
.init_cfg = video_mux_init_cfg,
- .get_fmt = video_mux_get_format,
+ .get_fmt = v4l2_subdev_get_fmt,
.set_fmt = video_mux_set_format,
};
@@ -389,7 +360,7 @@ static int video_mux_async_register(struct video_mux *vmux,
ret = PTR_ERR(asd);
/* OK if asd already exists */
if (ret != -EEXIST)
- return ret;
+ goto err_nf_cleanup;
}
}
@@ -397,9 +368,19 @@ static int video_mux_async_register(struct video_mux *vmux,
ret = v4l2_async_subdev_nf_register(&vmux->subdev, &vmux->notifier);
if (ret)
- return ret;
+ goto err_nf_cleanup;
+
+ ret = v4l2_async_register_subdev(&vmux->subdev);
+ if (ret)
+ goto err_nf_unregister;
- return v4l2_async_register_subdev(&vmux->subdev);
+ return 0;
+
+err_nf_unregister:
+ v4l2_async_nf_unregister(&vmux->notifier);
+err_nf_cleanup:
+ v4l2_async_nf_cleanup(&vmux->notifier);
+ return ret;
}
static int video_mux_probe(struct platform_device *pdev)
@@ -452,17 +433,9 @@ static int video_mux_probe(struct platform_device *pdev)
if (!vmux->pads)
return -ENOMEM;
- vmux->format_mbus = devm_kcalloc(dev, num_pads,
- sizeof(*vmux->format_mbus),
- GFP_KERNEL);
- if (!vmux->format_mbus)
- return -ENOMEM;
-
- for (i = 0; i < num_pads; i++) {
+ for (i = 0; i < num_pads; i++)
vmux->pads[i].flags = (i < num_pads - 1) ? MEDIA_PAD_FL_SINK
: MEDIA_PAD_FL_SOURCE;
- vmux->format_mbus[i] = video_mux_format_mbus_default;
- }
vmux->subdev.entity.function = MEDIA_ENT_F_VID_MUX;
ret = media_entity_pads_init(&vmux->subdev.entity, num_pads,
@@ -472,12 +445,20 @@ static int video_mux_probe(struct platform_device *pdev)
vmux->subdev.entity.ops = &video_mux_ops;
+ ret = v4l2_subdev_init_finalize(&vmux->subdev);
+ if (ret < 0)
+ goto err_entity_cleanup;
+
ret = video_mux_async_register(vmux, num_pads - 1);
- if (ret) {
- v4l2_async_nf_unregister(&vmux->notifier);
- v4l2_async_nf_cleanup(&vmux->notifier);
- }
+ if (ret)
+ goto err_subdev_cleanup;
+
+ return 0;
+err_subdev_cleanup:
+ v4l2_subdev_cleanup(&vmux->subdev);
+err_entity_cleanup:
+ media_entity_cleanup(&vmux->subdev.entity);
return ret;
}
@@ -489,6 +470,7 @@ static void video_mux_remove(struct platform_device *pdev)
v4l2_async_nf_unregister(&vmux->notifier);
v4l2_async_nf_cleanup(&vmux->notifier);
v4l2_async_unregister_subdev(sd);
+ v4l2_subdev_cleanup(sd);
media_entity_cleanup(&sd->entity);
}
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 616a38feb641..d52eccdc7eb9 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -15,7 +15,7 @@ if RADIO_ADAPTERS
config RADIO_MAXIRADIO
tristate "Guillemot MAXI Radio FM 2000 radio"
- depends on PCI
+ depends on PCI && HAS_IOPORT
select RADIO_TEA575X
help
Choose Y here if you have this radio card. This card may also be
@@ -232,6 +232,7 @@ source "drivers/media/radio/wl128x/Kconfig"
menuconfig V4L_RADIO_ISA_DRIVERS
bool "ISA radio devices"
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
help
Say Y here to enable support for these ISA drivers.
@@ -240,6 +241,7 @@ if V4L_RADIO_ISA_DRIVERS
config RADIO_AZTECH
tristate "Aztech/Packard Bell Radio"
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
select RADIO_ISA
help
Choose Y here if you have one of these FM radio cards, and then fill
@@ -260,6 +262,7 @@ config RADIO_AZTECH_PORT
config RADIO_CADET
tristate "ADS Cadet AM/FM Tuner"
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
help
Choose Y here if you have one of these AM/FM radio cards, and then
fill in the port address below.
@@ -270,6 +273,7 @@ config RADIO_CADET
config RADIO_GEMTEK
tristate "GemTek Radio card (or compatible) support"
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
select RADIO_ISA
help
Choose Y here if you have this FM radio card, and then fill in the
@@ -309,6 +313,7 @@ config RADIO_GEMTEK_PROBE
config RADIO_ISA
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
tristate
config RADIO_MIROPCM20
@@ -329,6 +334,7 @@ config RADIO_MIROPCM20
config RADIO_RTRACK
tristate "AIMSlab RadioTrack (aka RadioReveal) support"
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
select RADIO_ISA
help
Choose Y here if you have one of these FM radio cards, and then fill
@@ -383,6 +389,7 @@ config RADIO_RTRACK_PORT
config RADIO_SF16FMI
tristate "SF16-FMI/SF16-FMP/SF16-FMD Radio"
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
help
Choose Y here if you have one of these FM radio cards.
@@ -392,6 +399,7 @@ config RADIO_SF16FMI
config RADIO_SF16FMR2
tristate "SF16-FMR2/SF16-FMD2 Radio"
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
select RADIO_TEA575X
help
Choose Y here if you have one of these FM radio cards.
@@ -402,6 +410,7 @@ config RADIO_SF16FMR2
config RADIO_TERRATEC
tristate "TerraTec ActiveRadio ISA Standalone"
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
select RADIO_ISA
help
Choose Y here if you have this FM radio card.
@@ -416,6 +425,7 @@ config RADIO_TERRATEC
config RADIO_TRUST
tristate "Trust FM radio card"
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
select RADIO_ISA
help
This is a driver for the Trust FM radio cards. Say Y if you have
@@ -439,6 +449,7 @@ config RADIO_TRUST_PORT
config RADIO_TYPHOON
tristate "Typhoon Radio (a.k.a. EcoRadio)"
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
select RADIO_ISA
help
Choose Y here if you have one of these FM radio cards, and then fill
@@ -473,6 +484,7 @@ config RADIO_TYPHOON_PORT
config RADIO_ZOLTRIX
tristate "Zoltrix Radio"
depends on ISA || COMPILE_TEST
+ depends on HAS_IOPORT
select RADIO_ISA
help
Choose Y here if you have one of these FM radio cards, and then fill
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index 2cb74afba49c..14e7dd3889ff 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -511,7 +511,7 @@ static struct i2c_driver tea5764_i2c_driver = {
.driver = {
.name = "radio-tea5764",
},
- .probe_new = tea5764_i2c_probe,
+ .probe = tea5764_i2c_probe,
.remove = tea5764_i2c_remove,
.id_table = tea5764_id,
};
diff --git a/drivers/media/radio/saa7706h.c b/drivers/media/radio/saa7706h.c
index 3c758a983344..91345198bbf1 100644
--- a/drivers/media/radio/saa7706h.c
+++ b/drivers/media/radio/saa7706h.c
@@ -405,7 +405,7 @@ static struct i2c_driver saa7706h_driver = {
.driver = {
.name = DRIVER_NAME,
},
- .probe_new = saa7706h_probe,
+ .probe = saa7706h_probe,
.remove = saa7706h_remove,
.id_table = saa7706h_id,
};
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c
index a6ad926c2b4e..fd449e42c191 100644
--- a/drivers/media/radio/si470x/radio-si470x-i2c.c
+++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
@@ -532,7 +532,7 @@ static struct i2c_driver si470x_i2c_driver = {
.pm = &si470x_i2c_pm,
#endif
},
- .probe_new = si470x_i2c_probe,
+ .probe = si470x_i2c_probe,
.remove = si470x_i2c_remove,
.id_table = si470x_i2c_id,
};
diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c
index 93d847c294e8..ddaf7a60b7d0 100644
--- a/drivers/media/radio/si4713/si4713.c
+++ b/drivers/media/radio/si4713/si4713.c
@@ -1657,7 +1657,7 @@ static struct i2c_driver si4713_i2c_driver = {
.name = "si4713",
.of_match_table = of_match_ptr(si4713_of_match),
},
- .probe_new = si4713_probe,
+ .probe = si4713_probe,
.remove = si4713_remove,
.id_table = si4713_id,
};
diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c
index d14c97d79e83..215168aa1588 100644
--- a/drivers/media/radio/tef6862.c
+++ b/drivers/media/radio/tef6862.c
@@ -183,7 +183,7 @@ static struct i2c_driver tef6862_driver = {
.driver = {
.name = DRIVER_NAME,
},
- .probe_new = tef6862_probe,
+ .probe = tef6862_probe,
.remove = tef6862_remove,
.id_table = tef6862_id,
};
diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c
index cbd49dff6d74..b31b7ed60bbe 100644
--- a/drivers/media/radio/wl128x/fmdrv_common.c
+++ b/drivers/media/radio/wl128x/fmdrv_common.c
@@ -1234,9 +1234,8 @@ static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name)
struct bts_action *action;
struct bts_action_delay *delay;
u8 *fw_data;
- int ret, fw_len, cmd_cnt;
+ int ret, fw_len;
- cmd_cnt = 0;
set_bit(FM_FW_DW_INPROGRESS, &fmdev->flag);
ret = request_firmware(&fw_entry, fw_name,
@@ -1272,7 +1271,6 @@ static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name)
if (ret)
goto rel_fw;
- cmd_cnt++;
break;
case ACTION_DELAY: /* Delay */
@@ -1284,7 +1282,7 @@ static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name)
fw_data += (sizeof(struct bts_action) + (action->size));
fw_len -= (sizeof(struct bts_action) + (action->size));
}
- fmdbg("Firmware commands(%d) loaded to chip\n", cmd_cnt);
+ fmdbg("Transfered only %d of %d bytes of the firmware to chip\n", fw_entry->size - fw_len, fw_entry->size);
rel_fw:
release_firmware(fw_entry);
clear_bit(FM_FW_DW_INPROGRESS, &fmdev->flag);
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index ac4172feb6f9..922c790b577e 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -148,6 +148,7 @@ if RC_DEVICES
config IR_ENE
tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)"
depends on PNP || COMPILE_TEST
+ depends on HAS_IOPORT
help
Say Y here to enable support for integrated infrared receiver
/transceiver made by ENE.
@@ -161,6 +162,7 @@ config IR_ENE
config IR_FINTEK
tristate "Fintek Consumer Infrared Transceiver"
depends on PNP || COMPILE_TEST
+ depends on HAS_IOPORT
help
Say Y here to enable support for integrated infrared receiver
/transceiver made by Fintek. This chip is found on assorted
@@ -249,6 +251,7 @@ config IR_IMON_RAW
config IR_ITE_CIR
tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver"
depends on PNP || COMPILE_TEST
+ depends on HAS_IOPORT
help
Say Y here to enable support for integrated infrared receivers
/transceivers made by ITE Tech Inc. These are found in
@@ -301,6 +304,7 @@ config IR_MTK
config IR_NUVOTON
tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
depends on PNP || COMPILE_TEST
+ depends on HAS_IOPORT
help
Say Y here to enable support for integrated infrared receiver
/transceiver made by Nuvoton (formerly Winbond). This chip is
@@ -345,6 +349,7 @@ config IR_RX51
config IR_SERIAL
tristate "Homebrew Serial Port Receiver"
+ depends on HAS_IOPORT
help
Say Y if you want to use Homebrew Serial Port Receivers and
Transceivers.
@@ -412,6 +417,7 @@ config IR_TTUSBIR
config IR_WINBOND_CIR
tristate "Winbond IR remote control"
depends on (X86 && PNP) || COMPILE_TEST
+ depends on HAS_IOPORT
select NEW_LEDS
select LEDS_CLASS
select BITREVERSE
diff --git a/drivers/media/test-drivers/vidtv/vidtv_demod.c b/drivers/media/test-drivers/vidtv/vidtv_demod.c
index b878db798686..7a0cd9601917 100644
--- a/drivers/media/test-drivers/vidtv/vidtv_demod.c
+++ b/drivers/media/test-drivers/vidtv/vidtv_demod.c
@@ -449,7 +449,7 @@ static struct i2c_driver vidtv_demod_i2c_driver = {
.name = "dvb_vidtv_demod",
.suppress_bind_attrs = true,
},
- .probe_new = vidtv_demod_i2c_probe,
+ .probe = vidtv_demod_i2c_probe,
.remove = vidtv_demod_i2c_remove,
.id_table = vidtv_demod_i2c_id_table,
};
diff --git a/drivers/media/test-drivers/vidtv/vidtv_tuner.c b/drivers/media/test-drivers/vidtv/vidtv_tuner.c
index 55a4387f3854..a748737d47f3 100644
--- a/drivers/media/test-drivers/vidtv/vidtv_tuner.c
+++ b/drivers/media/test-drivers/vidtv/vidtv_tuner.c
@@ -425,7 +425,7 @@ static struct i2c_driver vidtv_tuner_i2c_driver = {
.name = "dvb_vidtv_tuner",
.suppress_bind_attrs = true,
},
- .probe_new = vidtv_tuner_i2c_probe,
+ .probe = vidtv_tuner_i2c_probe,
.remove = vidtv_tuner_i2c_remove,
.id_table = vidtv_tuner_i2c_id_table,
};
diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c
index 801286dc1448..3a06df35a2d7 100644
--- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c
+++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c
@@ -21,13 +21,8 @@
#include "vivid-kthread-cap.h"
#include "vivid-vid-cap.h"
-/* The number of discrete webcam framesizes */
-#define VIVID_WEBCAM_SIZES 6
-/* The number of discrete webcam frameintervals */
-#define VIVID_WEBCAM_IVALS (VIVID_WEBCAM_SIZES * 2)
-
/* Sizes must be in increasing order */
-static const struct v4l2_frmsize_discrete webcam_sizes[VIVID_WEBCAM_SIZES] = {
+static const struct v4l2_frmsize_discrete webcam_sizes[] = {
{ 320, 180 },
{ 640, 360 },
{ 640, 480 },
@@ -40,21 +35,43 @@ static const struct v4l2_frmsize_discrete webcam_sizes[VIVID_WEBCAM_SIZES] = {
* Intervals must be in increasing order and there must be twice as many
* elements in this array as there are in webcam_sizes.
*/
-static const struct v4l2_fract webcam_intervals[VIVID_WEBCAM_IVALS] = {
+static const struct v4l2_fract webcam_intervals[] = {
{ 1, 1 },
{ 1, 2 },
{ 1, 4 },
{ 1, 5 },
{ 1, 10 },
{ 2, 25 },
- { 1, 15 },
+ { 1, 15 }, /* 7 - maximum for 2160p */
{ 1, 25 },
- { 1, 30 },
+ { 1, 30 }, /* 9 - maximum for 1080p */
{ 1, 40 },
{ 1, 50 },
- { 1, 60 },
+ { 1, 60 }, /* 12 - maximum for 720p */
+ { 1, 120 },
};
+/* Limit maximum FPS rates for high resolutions */
+#define IVAL_COUNT_720P 12 /* 720p and up is limited to 60 fps */
+#define IVAL_COUNT_1080P 9 /* 1080p and up is limited to 30 fps */
+#define IVAL_COUNT_2160P 7 /* 2160p and up is limited to 15 fps */
+
+static inline unsigned int webcam_ival_count(const struct vivid_dev *dev,
+ unsigned int frmsize_idx)
+{
+ if (webcam_sizes[frmsize_idx].height >= 2160)
+ return IVAL_COUNT_2160P;
+
+ if (webcam_sizes[frmsize_idx].height >= 1080)
+ return IVAL_COUNT_1080P;
+
+ if (webcam_sizes[frmsize_idx].height >= 720)
+ return IVAL_COUNT_720P;
+
+ /* For low resolutions, allow all FPS rates */
+ return ARRAY_SIZE(webcam_intervals);
+}
+
static int vid_cap_queue_setup(struct vb2_queue *vq,
unsigned *nbuffers, unsigned *nplanes,
unsigned sizes[], struct device *alloc_devs[])
@@ -560,7 +577,7 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
if (vivid_is_webcam(dev)) {
const struct v4l2_frmsize_discrete *sz =
v4l2_find_nearest_size(webcam_sizes,
- VIVID_WEBCAM_SIZES, width,
+ ARRAY_SIZE(webcam_sizes), width,
height, mp->width, mp->height);
w = sz->width;
@@ -736,14 +753,16 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
compose->height /= factor;
}
} else if (vivid_is_webcam(dev)) {
+ unsigned int ival_sz = webcam_ival_count(dev, dev->webcam_size_idx);
+
/* Guaranteed to be a match */
for (i = 0; i < ARRAY_SIZE(webcam_sizes); i++)
if (webcam_sizes[i].width == mp->width &&
webcam_sizes[i].height == mp->height)
break;
dev->webcam_size_idx = i;
- if (dev->webcam_ival_idx >= 2 * (VIVID_WEBCAM_SIZES - i))
- dev->webcam_ival_idx = 2 * (VIVID_WEBCAM_SIZES - i) - 1;
+ if (dev->webcam_ival_idx >= ival_sz)
+ dev->webcam_ival_idx = ival_sz - 1;
vivid_update_format_cap(dev, false);
} else {
struct v4l2_rect r = { 0, 0, mp->width, mp->height };
@@ -1636,7 +1655,7 @@ int vidioc_enum_frameintervals(struct file *file, void *priv,
break;
if (i == ARRAY_SIZE(webcam_sizes))
return -EINVAL;
- if (fival->index >= 2 * (VIVID_WEBCAM_SIZES - i))
+ if (fival->index >= webcam_ival_count(dev, i))
return -EINVAL;
fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
fival->discrete = webcam_intervals[fival->index];
@@ -1663,7 +1682,7 @@ int vivid_vid_cap_s_parm(struct file *file, void *priv,
struct v4l2_streamparm *parm)
{
struct vivid_dev *dev = video_drvdata(file);
- unsigned ival_sz = 2 * (VIVID_WEBCAM_SIZES - dev->webcam_size_idx);
+ unsigned int ival_sz = webcam_ival_count(dev, dev->webcam_size_idx);
struct v4l2_fract tpf;
unsigned i;
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index 7c269f3159ef..3893a00c18ce 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -729,7 +729,7 @@ static struct i2c_driver e4000_driver = {
.name = "e4000",
.suppress_bind_attrs = true,
},
- .probe_new = e4000_probe,
+ .probe = e4000_probe,
.remove = e4000_remove,
.id_table = e4000_id_table,
};
diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c
index 3cd8279f4f2e..f6613dcf40a3 100644
--- a/drivers/media/tuners/fc2580.c
+++ b/drivers/media/tuners/fc2580.c
@@ -610,7 +610,7 @@ static struct i2c_driver fc2580_driver = {
.name = "fc2580",
.suppress_bind_attrs = true,
},
- .probe_new = fc2580_probe,
+ .probe = fc2580_probe,
.remove = fc2580_remove,
.id_table = fc2580_id_table,
};
diff --git a/drivers/media/tuners/m88rs6000t.c b/drivers/media/tuners/m88rs6000t.c
index 7d172a5a66d9..2cd7f0e0c70d 100644
--- a/drivers/media/tuners/m88rs6000t.c
+++ b/drivers/media/tuners/m88rs6000t.c
@@ -718,7 +718,7 @@ static struct i2c_driver m88rs6000t_driver = {
.driver = {
.name = "m88rs6000t",
},
- .probe_new = m88rs6000t_probe,
+ .probe = m88rs6000t_probe,
.remove = m88rs6000t_remove,
.id_table = m88rs6000t_id,
};
diff --git a/drivers/media/tuners/mt2060.c b/drivers/media/tuners/mt2060.c
index e5d86874adb3..0278a9f0aeef 100644
--- a/drivers/media/tuners/mt2060.c
+++ b/drivers/media/tuners/mt2060.c
@@ -524,7 +524,7 @@ static struct i2c_driver mt2060_driver = {
.name = "mt2060",
.suppress_bind_attrs = true,
},
- .probe_new = mt2060_probe,
+ .probe = mt2060_probe,
.remove = mt2060_remove,
.id_table = mt2060_id_table,
};
diff --git a/drivers/media/tuners/mxl301rf.c b/drivers/media/tuners/mxl301rf.c
index c35442a77ae5..9b2b237745ae 100644
--- a/drivers/media/tuners/mxl301rf.c
+++ b/drivers/media/tuners/mxl301rf.c
@@ -326,7 +326,7 @@ static struct i2c_driver mxl301rf_driver = {
.driver = {
.name = "mxl301rf",
},
- .probe_new = mxl301rf_probe,
+ .probe = mxl301rf_probe,
.remove = mxl301rf_remove,
.id_table = mxl301rf_id,
};
diff --git a/drivers/media/tuners/qm1d1b0004.c b/drivers/media/tuners/qm1d1b0004.c
index 0b6f750c54ad..af2d3618b9d5 100644
--- a/drivers/media/tuners/qm1d1b0004.c
+++ b/drivers/media/tuners/qm1d1b0004.c
@@ -253,7 +253,7 @@ static struct i2c_driver qm1d1b0004_driver = {
.driver = {
.name = "qm1d1b0004",
},
- .probe_new = qm1d1b0004_probe,
+ .probe = qm1d1b0004_probe,
.remove = qm1d1b0004_remove,
.id_table = qm1d1b0004_id,
};
diff --git a/drivers/media/tuners/qm1d1c0042.c b/drivers/media/tuners/qm1d1c0042.c
index f9be7a721d2c..ce7223315b0c 100644
--- a/drivers/media/tuners/qm1d1c0042.c
+++ b/drivers/media/tuners/qm1d1c0042.c
@@ -443,7 +443,7 @@ static struct i2c_driver qm1d1c0042_driver = {
.driver = {
.name = "qm1d1c0042",
},
- .probe_new = qm1d1c0042_probe,
+ .probe = qm1d1c0042_probe,
.remove = qm1d1c0042_remove,
.id_table = qm1d1c0042_id,
};
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 3fa3dcda917a..def06c262ea2 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -990,7 +990,7 @@ static struct i2c_driver si2157_driver = {
.name = "si2157",
.suppress_bind_attrs = true,
},
- .probe_new = si2157_probe,
+ .probe = si2157_probe,
.remove = si2157_remove,
.id_table = si2157_id_table,
};
diff --git a/drivers/media/tuners/tda18212.c b/drivers/media/tuners/tda18212.c
index 5fdf05a97415..8d742bd61df0 100644
--- a/drivers/media/tuners/tda18212.c
+++ b/drivers/media/tuners/tda18212.c
@@ -263,7 +263,7 @@ static struct i2c_driver tda18212_driver = {
.driver = {
.name = "tda18212",
},
- .probe_new = tda18212_probe,
+ .probe = tda18212_probe,
.remove = tda18212_remove,
.id_table = tda18212_id,
};
diff --git a/drivers/media/tuners/tda18250.c b/drivers/media/tuners/tda18250.c
index 66ff2d035de7..32ea473f3f49 100644
--- a/drivers/media/tuners/tda18250.c
+++ b/drivers/media/tuners/tda18250.c
@@ -877,7 +877,7 @@ static struct i2c_driver tda18250_driver = {
.driver = {
.name = "tda18250",
},
- .probe_new = tda18250_probe,
+ .probe = tda18250_probe,
.remove = tda18250_remove,
.id_table = tda18250_id_table,
};
diff --git a/drivers/media/tuners/tua9001.c b/drivers/media/tuners/tua9001.c
index ac38afd3441a..03a3a022b0a8 100644
--- a/drivers/media/tuners/tua9001.c
+++ b/drivers/media/tuners/tua9001.c
@@ -255,7 +255,7 @@ static struct i2c_driver tua9001_driver = {
.name = "tua9001",
.suppress_bind_attrs = true,
},
- .probe_new = tua9001_probe,
+ .probe = tua9001_probe,
.remove = tua9001_remove,
.id_table = tua9001_id_table,
};
diff --git a/drivers/media/usb/as102/as102_usb_drv.c b/drivers/media/usb/as102/as102_usb_drv.c
index 50419e8ae56c..6b380144d6c2 100644
--- a/drivers/media/usb/as102/as102_usb_drv.c
+++ b/drivers/media/usb/as102/as102_usb_drv.c
@@ -303,10 +303,8 @@ static void as102_usb_release(struct kref *kref)
struct as102_dev_t *as102_dev;
as102_dev = container_of(kref, struct as102_dev_t, kref);
- if (as102_dev != NULL) {
- usb_put_dev(as102_dev->bus_adap.usb_dev);
- kfree(as102_dev);
- }
+ usb_put_dev(as102_dev->bus_adap.usb_dev);
+ kfree(as102_dev);
}
static void as102_usb_disconnect(struct usb_interface *intf)
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index b3a09d3ac7d2..1e246b47766d 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -250,7 +250,7 @@ static void au0828_media_graph_notify(struct media_entity *new,
create_link:
if (decoder && mixer) {
- ret = media_get_pad_index(decoder, false,
+ ret = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE,
PAD_SIGNAL_AUDIO);
if (ret >= 0)
ret = media_create_pad_link(decoder, ret,
diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c
index 62ee09f28a0b..2dcbb49d66da 100644
--- a/drivers/media/usb/dvb-usb-v2/az6007.c
+++ b/drivers/media/usb/dvb-usb-v2/az6007.c
@@ -202,7 +202,8 @@ static int az6007_rc_query(struct dvb_usb_device *d)
unsigned code;
enum rc_proto proto;
- az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10);
+ if (az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10) < 0)
+ return -EIO;
if (st->data[1] == 0x44)
return 0;
@@ -248,7 +249,7 @@ static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
int slot,
int address)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct dvb_usb_device *d = ca->data;
struct az6007_device_state *state = d_to_priv(d);
int ret;
@@ -290,7 +291,7 @@ static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
int address,
u8 value)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct dvb_usb_device *d = ca->data;
struct az6007_device_state *state = d_to_priv(d);
int ret;
@@ -321,7 +322,7 @@ static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca,
int slot,
u8 address)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct dvb_usb_device *d = ca->data;
struct az6007_device_state *state = d_to_priv(d);
int ret;
@@ -367,7 +368,7 @@ static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca,
u8 address,
u8 value)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct dvb_usb_device *d = ca->data;
struct az6007_device_state *state = d_to_priv(d);
int ret;
@@ -398,7 +399,7 @@ failed:
static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct dvb_usb_device *d = ca->data;
int ret;
u8 req;
@@ -429,7 +430,7 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct dvb_usb_device *d = ca->data;
struct az6007_device_state *state = d_to_priv(d);
int ret, i;
@@ -485,7 +486,7 @@ static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct dvb_usb_device *d = ca->data;
struct az6007_device_state *state = d_to_priv(d);
int ret;
@@ -514,7 +515,7 @@ failed:
static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct dvb_usb_device *d = ca->data;
struct az6007_device_state *state = d_to_priv(d);
int ret;
u8 req;
diff --git a/drivers/media/usb/dvb-usb/af9005-fe.c b/drivers/media/usb/dvb-usb/af9005-fe.c
index 9d6fa0556d7b..404e56b32145 100644
--- a/drivers/media/usb/dvb-usb/af9005-fe.c
+++ b/drivers/media/usb/dvb-usb/af9005-fe.c
@@ -1412,8 +1412,7 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
static void af9005_fe_release(struct dvb_frontend *fe)
{
- struct af9005_fe_state *state =
- (struct af9005_fe_state *)fe->demodulator_priv;
+ struct af9005_fe_state *state = fe->demodulator_priv;
kfree(state);
}
diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c
index a31c6f82f4e9..2bc27710427d 100644
--- a/drivers/media/usb/dvb-usb/az6027.c
+++ b/drivers/media/usb/dvb-usb/az6027.c
@@ -407,8 +407,8 @@ static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
int slot,
int address)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+ struct dvb_usb_device *d = ca->data;
+ struct az6027_device_state *state = d->priv;
int ret;
u8 req;
@@ -449,8 +449,8 @@ static int az6027_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
int address,
u8 value)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+ struct dvb_usb_device *d = ca->data;
+ struct az6027_device_state *state = d->priv;
int ret;
u8 req;
@@ -480,8 +480,8 @@ static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca,
int slot,
u8 address)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+ struct dvb_usb_device *d = ca->data;
+ struct az6027_device_state *state = d->priv;
int ret;
u8 req;
@@ -526,8 +526,8 @@ static int az6027_ci_write_cam_control(struct dvb_ca_en50221 *ca,
u8 address,
u8 value)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+ struct dvb_usb_device *d = ca->data;
+ struct az6027_device_state *state = d->priv;
int ret;
u8 req;
@@ -557,7 +557,7 @@ failed:
static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct dvb_usb_device *d = ca->data;
int ret;
u8 req;
@@ -588,8 +588,8 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
static int az6027_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+ struct dvb_usb_device *d = ca->data;
+ struct az6027_device_state *state = d->priv;
int ret, i;
u8 req;
@@ -644,8 +644,8 @@ static int az6027_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+ struct dvb_usb_device *d = ca->data;
+ struct az6027_device_state *state = d->priv;
int ret;
u8 req;
@@ -673,8 +673,8 @@ failed:
static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+ struct dvb_usb_device *d = ca->data;
+ struct az6027_device_state *state = d->priv;
int ret;
u8 req;
u16 value;
@@ -719,7 +719,7 @@ static void az6027_ci_uninit(struct dvb_usb_device *d)
if (NULL == d)
return;
- state = (struct az6027_device_state *)d->priv;
+ state = d->priv;
if (NULL == state)
return;
@@ -735,7 +735,7 @@ static void az6027_ci_uninit(struct dvb_usb_device *d)
static int az6027_ci_init(struct dvb_usb_adapter *a)
{
struct dvb_usb_device *d = a->dev;
- struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+ struct az6027_device_state *state = d->priv;
int ret;
deb_info("%s", __func__);
diff --git a/drivers/media/usb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c
index 9f83560ba63d..586afe22d817 100644
--- a/drivers/media/usb/dvb-usb/dtt200u-fe.c
+++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c
@@ -195,7 +195,7 @@ static int dtt200u_fe_get_frontend(struct dvb_frontend* fe,
static void dtt200u_fe_release(struct dvb_frontend* fe)
{
- struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
+ struct dtt200u_fe_state *state = fe->demodulator_priv;
kfree(state);
}
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
index 8747960e6146..970b84c3f0b5 100644
--- a/drivers/media/usb/dvb-usb/dw2102.c
+++ b/drivers/media/usb/dvb-usb/dw2102.c
@@ -830,7 +830,7 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
for (i = 0; i < 256; i++) {
if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) {
err("read eeprom failed.");
- return -1;
+ return -EIO;
} else {
eepromline[i%16] = ibuf[0];
eeprom[i] = ibuf[0];
@@ -869,7 +869,7 @@ static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2);
if (ret != 2) {
err("read eeprom failed.");
- return -1;
+ return -EIO;
} else {
eepromline[i % 16] = ibuf[0];
eeprom[i] = ibuf[0];
@@ -903,7 +903,7 @@ static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
static int su3000_power_ctrl(struct dvb_usb_device *d, int i)
{
- struct dw2102_state *state = (struct dw2102_state *)d->priv;
+ struct dw2102_state *state = d->priv;
int ret = 0;
info("%s: %d, initialized %d", __func__, i, state->initialized);
@@ -946,7 +946,7 @@ static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
for (i = 0; i < 6; i++) {
obuf[1] = 0xf0 + i;
if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
- return -1;
+ return -EIO;
else
mac[i] = ibuf[0];
}
@@ -978,8 +978,7 @@ static int dw210x_set_voltage(struct dvb_frontend *fe,
.len = 2,
};
- struct dvb_usb_adapter *udev_adap =
- (struct dvb_usb_adapter *)(fe->dvb->priv);
+ struct dvb_usb_adapter *udev_adap = fe->dvb->priv;
if (voltage == SEC_VOLTAGE_18)
msg.buf = command_18v;
else if (voltage == SEC_VOLTAGE_13)
@@ -993,9 +992,8 @@ static int dw210x_set_voltage(struct dvb_frontend *fe,
static int s660_set_voltage(struct dvb_frontend *fe,
enum fe_sec_voltage voltage)
{
- struct dvb_usb_adapter *d =
- (struct dvb_usb_adapter *)(fe->dvb->priv);
- struct dw2102_state *st = (struct dw2102_state *)d->dev->priv;
+ struct dvb_usb_adapter *d = fe->dvb->priv;
+ struct dw2102_state *st = d->dev->priv;
dw210x_set_voltage(fe, voltage);
if (st->old_set_voltage)
@@ -1014,8 +1012,7 @@ static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon)
.buf = led_off,
.len = 1
};
- struct dvb_usb_adapter *udev_adap =
- (struct dvb_usb_adapter *)(fe->dvb->priv);
+ struct dvb_usb_adapter *udev_adap = fe->dvb->priv;
if (offon)
msg.buf = led_on;
@@ -1025,9 +1022,8 @@ static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon)
static int tt_s2_4600_read_status(struct dvb_frontend *fe,
enum fe_status *status)
{
- struct dvb_usb_adapter *d =
- (struct dvb_usb_adapter *)(fe->dvb->priv);
- struct dw2102_state *st = (struct dw2102_state *)d->dev->priv;
+ struct dvb_usb_adapter *d = fe->dvb->priv;
+ struct dw2102_state *st = d->dev->priv;
int ret;
ret = st->fe_read_status(fe, status);
@@ -2576,7 +2572,7 @@ static int dw2102_probe(struct usb_interface *intf,
static void dw2102_disconnect(struct usb_interface *intf)
{
struct dvb_usb_device *d = usb_get_intfdata(intf);
- struct dw2102_state *st = (struct dw2102_state *)d->priv;
+ struct dw2102_state *st = d->priv;
struct i2c_client *client;
/* remove I2C client for tuner */
diff --git a/drivers/media/usb/dvb-usb/opera1.c b/drivers/media/usb/dvb-usb/opera1.c
index 0da86f58aff6..98b2177667d2 100644
--- a/drivers/media/usb/dvb-usb/opera1.c
+++ b/drivers/media/usb/dvb-usb/opera1.c
@@ -172,8 +172,7 @@ static int opera1_set_voltage(struct dvb_frontend *fe,
struct i2c_msg msg[] = {
{.addr = ADDR_B600_VOLTAGE_13V,.flags = 0,.buf = command_13v,.len = 1},
};
- struct dvb_usb_adapter *udev_adap =
- (struct dvb_usb_adapter *)(fe->dvb->priv);
+ struct dvb_usb_adapter *udev_adap = fe->dvb->priv;
if (voltage == SEC_VOLTAGE_18) {
msg[0].addr = ADDR_B601_VOLTAGE_18V;
msg[0].buf = command_18v;
diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c
index da42c989e071..2aab49003493 100644
--- a/drivers/media/usb/dvb-usb/pctv452e.c
+++ b/drivers/media/usb/dvb-usb/pctv452e.c
@@ -108,7 +108,7 @@ struct pctv452e_state {
static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
unsigned int write_len, unsigned int read_len)
{
- struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ struct pctv452e_state *state = d->priv;
u8 *buf;
u8 id;
unsigned int rlen;
@@ -159,8 +159,8 @@ static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca,
u8 cmd, u8 *data, unsigned int write_len,
unsigned int read_len)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ struct dvb_usb_device *d = ca->data;
+ struct pctv452e_state *state = d->priv;
int ret;
mutex_lock(&state->ca_mutex);
@@ -292,8 +292,8 @@ static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
- struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
- struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ struct dvb_usb_device *d = ca->data;
+ struct pctv452e_state *state = d->priv;
u8 buf[1];
int ret;
@@ -361,7 +361,7 @@ static void tt3650_ci_uninit(struct dvb_usb_device *d)
if (NULL == d)
return;
- state = (struct pctv452e_state *)d->priv;
+ state = d->priv;
if (NULL == state)
return;
@@ -379,7 +379,7 @@ static void tt3650_ci_uninit(struct dvb_usb_device *d)
static int tt3650_ci_init(struct dvb_usb_adapter *a)
{
struct dvb_usb_device *d = a->dev;
- struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ struct pctv452e_state *state = d->priv;
int ret;
ci_dbg("%s", __func__);
@@ -417,7 +417,7 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,
const u8 *snd_buf, u8 snd_len,
u8 *rcv_buf, u8 rcv_len)
{
- struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ struct pctv452e_state *state = d->priv;
u8 *buf;
u8 id;
int ret;
@@ -516,7 +516,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter)
static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
{
- struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ struct pctv452e_state *state = d->priv;
u8 *b0, *rx;
int ret;
@@ -567,7 +567,7 @@ ret:
static int pctv452e_rc_query(struct dvb_usb_device *d)
{
- struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ struct pctv452e_state *state = d->priv;
u8 *b, *rx;
int ret, i;
u8 id;
diff --git a/drivers/media/usb/go7007/s2250-board.c b/drivers/media/usb/go7007/s2250-board.c
index 29dfcc6d0b0a..db1fab96d529 100644
--- a/drivers/media/usb/go7007/s2250-board.c
+++ b/drivers/media/usb/go7007/s2250-board.c
@@ -620,7 +620,7 @@ static struct i2c_driver s2250_driver = {
.driver = {
.name = "s2250",
},
- .probe_new = s2250_probe,
+ .probe = s2250_probe,
.remove = s2250_remove,
.id_table = s2250_id,
};
diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c
index 6f443c542c6d..640737d3b8ae 100644
--- a/drivers/media/usb/siano/smsusb.c
+++ b/drivers/media/usb/siano/smsusb.c
@@ -179,7 +179,8 @@ static void smsusb_stop_streaming(struct smsusb_device_t *dev)
for (i = 0; i < MAX_URBS; i++) {
usb_kill_urb(&dev->surbs[i].urb);
- cancel_work_sync(&dev->surbs[i].wq);
+ if (dev->surbs[i].wq.func)
+ cancel_work_sync(&dev->surbs[i].wq);
if (dev->surbs[i].cb) {
smscore_putbuffer(dev->coredev, dev->surbs[i].cb);
diff --git a/drivers/media/usb/stk1160/Kconfig b/drivers/media/usb/stk1160/Kconfig
index 4f50fb7db7b9..bf7c16baa9f8 100644
--- a/drivers/media/usb/stk1160/Kconfig
+++ b/drivers/media/usb/stk1160/Kconfig
@@ -1,8 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-only
-config VIDEO_STK1160_COMMON
+config VIDEO_STK1160
tristate "STK1160 USB video capture support"
depends on VIDEO_DEV && I2C
-
+ select VIDEOBUF2_VMALLOC
+ select VIDEO_SAA711X
help
This is a video4linux driver for STK1160 based video capture devices.
@@ -12,10 +13,3 @@ config VIDEO_STK1160_COMMON
This driver only provides support for video capture. For audio
capture, you need to select the snd-usb-audio driver (i.e.
CONFIG_SND_USB_AUDIO).
-
-config VIDEO_STK1160
- tristate
- depends on VIDEO_STK1160_COMMON
- default y
- select VIDEOBUF2_VMALLOC
- select VIDEO_SAA711X
diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c
index c4474d4c44e2..79faa2560613 100644
--- a/drivers/media/usb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c
@@ -1128,7 +1128,7 @@ static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct ttusb_dec *dec = dvbdmxfeed->demux->priv;
u8 b0[] = { 0x00, 0x00 };
- struct filter_info *finfo = (struct filter_info *)dvbdmxfeed->priv;
+ struct filter_info *finfo = dvbdmxfeed->priv;
unsigned long flags;
b0[1] = finfo->stream_id;
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index d631ce4f9f7b..08fcd2ffa727 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -184,7 +184,7 @@ static void uvc_stream_delete(struct uvc_streaming *stream)
usb_put_intf(stream->intf);
- kfree(stream->format);
+ kfree(stream->formats);
kfree(stream->header.bmaControls);
kfree(stream);
}
@@ -221,7 +221,8 @@ static struct uvc_streaming *uvc_stream_new(struct uvc_device *dev,
static int uvc_parse_format(struct uvc_device *dev,
struct uvc_streaming *streaming, struct uvc_format *format,
- u32 **intervals, unsigned char *buffer, int buflen)
+ struct uvc_frame *frames, u32 **intervals, const unsigned char *buffer,
+ int buflen)
{
struct usb_interface *intf = streaming->intf;
struct usb_host_interface *alts = intf->cur_altsetting;
@@ -235,6 +236,7 @@ static int uvc_parse_format(struct uvc_device *dev,
format->type = buffer[2];
format->index = buffer[3];
+ format->frames = frames;
switch (buffer[2]) {
case UVC_VS_FORMAT_UNCOMPRESSED:
@@ -339,8 +341,8 @@ static int uvc_parse_format(struct uvc_device *dev,
ftype = 0;
/* Create a dummy frame descriptor. */
- frame = &format->frame[0];
- memset(&format->frame[0], 0, sizeof(format->frame[0]));
+ frame = &frames[0];
+ memset(frame, 0, sizeof(*frame));
frame->bFrameIntervalType = 1;
frame->dwDefaultFrameInterval = 1;
frame->dwFrameInterval = *intervals;
@@ -370,7 +372,9 @@ static int uvc_parse_format(struct uvc_device *dev,
*/
while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
buffer[2] == ftype) {
- frame = &format->frame[format->nframes];
+ unsigned int maxIntervalIndex;
+
+ frame = &frames[format->nframes];
if (ftype != UVC_VS_FRAME_FRAME_BASED)
n = buflen > 25 ? buffer[25] : 0;
else
@@ -405,8 +409,27 @@ static int uvc_parse_format(struct uvc_device *dev,
get_unaligned_le32(&buffer[17]);
frame->bFrameIntervalType = buffer[21];
}
+
+ /*
+ * Copy the frame intervals.
+ *
+ * Some bogus devices report dwMinFrameInterval equal to
+ * dwMaxFrameInterval and have dwFrameIntervalStep set to
+ * zero. Setting all null intervals to 1 fixes the problem and
+ * some other divisions by zero that could happen.
+ */
frame->dwFrameInterval = *intervals;
+ for (i = 0; i < n; ++i) {
+ interval = get_unaligned_le32(&buffer[26+4*i]);
+ (*intervals)[i] = interval ? interval : 1;
+ }
+
+ /*
+ * Apply more fixes, quirks and workarounds to handle incorrect
+ * or broken descriptors.
+ */
+
/*
* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
* completely. Observed behaviours range from setting the
@@ -421,30 +444,25 @@ static int uvc_parse_format(struct uvc_device *dev,
* frame->wWidth * frame->wHeight / 8;
/*
- * Some bogus devices report dwMinFrameInterval equal to
- * dwMaxFrameInterval and have dwFrameIntervalStep set to
- * zero. Setting all null intervals to 1 fixes the problem and
- * some other divisions by zero that could happen.
+ * Clamp the default frame interval to the boundaries. A zero
+ * bFrameIntervalType value indicates a continuous frame
+ * interval range, with dwFrameInterval[0] storing the minimum
+ * value and dwFrameInterval[1] storing the maximum value.
*/
- for (i = 0; i < n; ++i) {
- interval = get_unaligned_le32(&buffer[26+4*i]);
- *(*intervals)++ = interval ? interval : 1;
- }
+ maxIntervalIndex = frame->bFrameIntervalType ? n - 1 : 1;
+ frame->dwDefaultFrameInterval =
+ clamp(frame->dwDefaultFrameInterval,
+ frame->dwFrameInterval[0],
+ frame->dwFrameInterval[maxIntervalIndex]);
/*
- * Make sure that the default frame interval stays between
- * the boundaries.
+ * Some devices report frame intervals that are not functional.
+ * If the corresponding quirk is set, restrict operation to the
+ * first interval only.
*/
- n -= frame->bFrameIntervalType ? 1 : 2;
- frame->dwDefaultFrameInterval =
- min(frame->dwFrameInterval[n],
- max(frame->dwFrameInterval[0],
- frame->dwDefaultFrameInterval));
-
if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) {
frame->bFrameIntervalType = 1;
- frame->dwFrameInterval[0] =
- frame->dwDefaultFrameInterval;
+ (*intervals)[0] = frame->dwDefaultFrameInterval;
}
uvc_dbg(dev, DESCR, "- %ux%u (%u.%u fps)\n",
@@ -453,6 +471,8 @@ static int uvc_parse_format(struct uvc_device *dev,
(100000000 / frame->dwDefaultFrameInterval) % 10);
format->nframes++;
+ *intervals += n;
+
buflen -= buffer[0];
buffer += buffer[0];
}
@@ -493,7 +513,7 @@ static int uvc_parse_streaming(struct uvc_device *dev,
struct uvc_format *format;
struct uvc_frame *frame;
struct usb_host_interface *alts = &intf->altsetting[0];
- unsigned char *_buffer, *buffer = alts->extra;
+ const unsigned char *_buffer, *buffer = alts->extra;
int _buflen, buflen = alts->extralen;
unsigned int nformats = 0, nframes = 0, nintervals = 0;
unsigned int size, i, n, p;
@@ -677,7 +697,7 @@ static int uvc_parse_streaming(struct uvc_device *dev,
frame = (struct uvc_frame *)&format[nformats];
interval = (u32 *)&frame[nframes];
- streaming->format = format;
+ streaming->formats = format;
streaming->nformats = 0;
/* Parse the format descriptors. */
@@ -687,8 +707,7 @@ static int uvc_parse_streaming(struct uvc_device *dev,
case UVC_VS_FORMAT_MJPEG:
case UVC_VS_FORMAT_DV:
case UVC_VS_FORMAT_FRAME_BASED:
- format->frame = frame;
- ret = uvc_parse_format(dev, streaming, format,
+ ret = uvc_parse_format(dev, streaming, format, frame,
&interval, buffer, buflen);
if (ret < 0)
goto error;
@@ -1147,7 +1166,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
static int uvc_parse_control(struct uvc_device *dev)
{
struct usb_host_interface *alts = dev->intf->cur_altsetting;
- unsigned char *buffer = alts->extra;
+ const unsigned char *buffer = alts->extra;
int buflen = alts->extralen;
int ret;
@@ -3011,15 +3030,33 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = (kernel_ulong_t)&uvc_ctrl_power_line_limited },
- /* Acer EasyCamera */
+ /* Intel D410/ASR depth camera */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x5986,
- .idProduct = 0x1180,
+ .idVendor = 0x8086,
+ .idProduct = 0x0ad2,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
- .driver_info = (kernel_ulong_t)&uvc_ctrl_power_line_limited },
+ .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
+ /* Intel D415/ASRC depth camera */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x8086,
+ .idProduct = 0x0ad3,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
+ /* Intel D430/AWG depth camera */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x8086,
+ .idProduct = 0x0ad4,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
/* Intel RealSense D4M */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -3029,6 +3066,42 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
+ /* Intel D435/AWGC depth camera */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x8086,
+ .idProduct = 0x0b07,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
+ /* Intel D435i depth camera */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x8086,
+ .idProduct = 0x0b3a,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
+ /* Intel D405 Depth Camera */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x8086,
+ .idProduct = 0x0b5b,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
+ /* Intel D455 Depth Camera */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x8086,
+ .idProduct = 0x0b5c,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
/* Generic USB Video Class */
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) },
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) },
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 35453f81c1d9..5ac2a424b13d 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -161,7 +161,7 @@ free_map:
* the Video Probe and Commit negotiation, but some hardware don't implement
* that feature.
*/
-static u32 uvc_try_frame_interval(struct uvc_frame *frame, u32 interval)
+static u32 uvc_try_frame_interval(const struct uvc_frame *frame, u32 interval)
{
unsigned int i;
@@ -210,10 +210,11 @@ static u32 uvc_v4l2_get_bytesperline(const struct uvc_format *format,
static int uvc_v4l2_try_format(struct uvc_streaming *stream,
struct v4l2_format *fmt, struct uvc_streaming_control *probe,
- struct uvc_format **uvc_format, struct uvc_frame **uvc_frame)
+ const struct uvc_format **uvc_format,
+ const struct uvc_frame **uvc_frame)
{
- struct uvc_format *format = NULL;
- struct uvc_frame *frame = NULL;
+ const struct uvc_format *format = NULL;
+ const struct uvc_frame *frame = NULL;
u16 rw, rh;
unsigned int d, maxd;
unsigned int i;
@@ -235,7 +236,7 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
* format otherwise.
*/
for (i = 0; i < stream->nformats; ++i) {
- format = &stream->format[i];
+ format = &stream->formats[i];
if (format->fcc == fmt->fmt.pix.pixelformat)
break;
}
@@ -255,14 +256,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
maxd = (unsigned int)-1;
for (i = 0; i < format->nframes; ++i) {
- u16 w = format->frame[i].wWidth;
- u16 h = format->frame[i].wHeight;
+ u16 w = format->frames[i].wWidth;
+ u16 h = format->frames[i].wHeight;
d = min(w, rw) * min(h, rh);
d = w*h + rw*rh - 2*d;
if (d < maxd) {
maxd = d;
- frame = &format->frame[i];
+ frame = &format->frames[i];
}
if (maxd == 0)
@@ -319,8 +320,8 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
* accepted the requested format as-is.
*/
for (i = 0; i < stream->nformats; ++i) {
- if (probe->bFormatIndex == stream->format[i].index) {
- format = &stream->format[i];
+ if (probe->bFormatIndex == stream->formats[i].index) {
+ format = &stream->formats[i];
break;
}
}
@@ -331,8 +332,8 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
probe->bFormatIndex);
for (i = 0; i < format->nframes; ++i) {
- if (probe->bFrameIndex == format->frame[i].bFrameIndex) {
- frame = &format->frame[i];
+ if (probe->bFrameIndex == format->frames[i].bFrameIndex) {
+ frame = &format->frames[i];
break;
}
}
@@ -363,8 +364,8 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
static int uvc_v4l2_get_format(struct uvc_streaming *stream,
struct v4l2_format *fmt)
{
- struct uvc_format *format;
- struct uvc_frame *frame;
+ const struct uvc_format *format;
+ const struct uvc_frame *frame;
int ret = 0;
if (fmt->type != stream->type)
@@ -398,8 +399,8 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,
struct v4l2_format *fmt)
{
struct uvc_streaming_control probe;
- struct uvc_format *format;
- struct uvc_frame *frame;
+ const struct uvc_format *format;
+ const struct uvc_frame *frame;
int ret;
if (fmt->type != stream->type)
@@ -465,8 +466,8 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
{
struct uvc_streaming_control probe;
struct v4l2_fract timeperframe;
- struct uvc_format *format;
- struct uvc_frame *frame;
+ const struct uvc_format *format;
+ const struct uvc_frame *frame;
u32 interval, maxd;
unsigned int i;
int ret;
@@ -501,19 +502,19 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
for (i = 0; i < format->nframes && maxd != 0; i++) {
u32 d, ival;
- if (&format->frame[i] == stream->cur_frame)
+ if (&format->frames[i] == stream->cur_frame)
continue;
- if (format->frame[i].wWidth != stream->cur_frame->wWidth ||
- format->frame[i].wHeight != stream->cur_frame->wHeight)
+ if (format->frames[i].wWidth != stream->cur_frame->wWidth ||
+ format->frames[i].wHeight != stream->cur_frame->wHeight)
continue;
- ival = uvc_try_frame_interval(&format->frame[i], interval);
+ ival = uvc_try_frame_interval(&format->frames[i], interval);
d = abs((s32)ival - interval);
if (d >= maxd)
continue;
- frame = &format->frame[i];
+ frame = &format->frames[i];
probe.bFrameIndex = frame->bFrameIndex;
probe.dwFrameInterval = ival;
maxd = d;
@@ -697,7 +698,7 @@ static int uvc_ioctl_querycap(struct file *file, void *fh,
static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream,
struct v4l2_fmtdesc *fmt)
{
- struct uvc_format *format;
+ const struct uvc_format *format;
enum v4l2_buf_type type = fmt->type;
u32 index = fmt->index;
@@ -708,7 +709,7 @@ static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream,
fmt->index = index;
fmt->type = type;
- format = &stream->format[fmt->index];
+ format = &stream->formats[fmt->index];
fmt->flags = 0;
if (format->flags & UVC_FMT_FLAG_COMPRESSED)
fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
@@ -1249,15 +1250,15 @@ static int uvc_ioctl_enum_framesizes(struct file *file, void *fh,
{
struct uvc_fh *handle = fh;
struct uvc_streaming *stream = handle->stream;
- struct uvc_format *format = NULL;
- struct uvc_frame *frame = NULL;
+ const struct uvc_format *format = NULL;
+ const struct uvc_frame *frame = NULL;
unsigned int index;
unsigned int i;
/* Look for the given pixel format */
for (i = 0; i < stream->nformats; i++) {
- if (stream->format[i].fcc == fsize->pixel_format) {
- format = &stream->format[i];
+ if (stream->formats[i].fcc == fsize->pixel_format) {
+ format = &stream->formats[i];
break;
}
}
@@ -1266,10 +1267,10 @@ static int uvc_ioctl_enum_framesizes(struct file *file, void *fh,
/* Skip duplicate frame sizes */
for (i = 0, index = 0; i < format->nframes; i++) {
- if (frame && frame->wWidth == format->frame[i].wWidth &&
- frame->wHeight == format->frame[i].wHeight)
+ if (frame && frame->wWidth == format->frames[i].wWidth &&
+ frame->wHeight == format->frames[i].wHeight)
continue;
- frame = &format->frame[i];
+ frame = &format->frames[i];
if (index == fsize->index)
break;
index++;
@@ -1289,16 +1290,16 @@ static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh,
{
struct uvc_fh *handle = fh;
struct uvc_streaming *stream = handle->stream;
- struct uvc_format *format = NULL;
- struct uvc_frame *frame = NULL;
+ const struct uvc_format *format = NULL;
+ const struct uvc_frame *frame = NULL;
unsigned int nintervals;
unsigned int index;
unsigned int i;
/* Look for the given pixel format and frame size */
for (i = 0; i < stream->nformats; i++) {
- if (stream->format[i].fcc == fival->pixel_format) {
- format = &stream->format[i];
+ if (stream->formats[i].fcc == fival->pixel_format) {
+ format = &stream->formats[i];
break;
}
}
@@ -1307,9 +1308,9 @@ static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh,
index = fival->index;
for (i = 0; i < format->nframes; i++) {
- if (format->frame[i].wWidth == fival->width &&
- format->frame[i].wHeight == fival->height) {
- frame = &format->frame[i];
+ if (format->frames[i].wWidth == fival->width &&
+ format->frames[i].wHeight == fival->height) {
+ frame = &format->frames[i];
nintervals = frame->bFrameIntervalType ?: 1;
if (index < nintervals)
break;
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index d4b023d4de7c..28dde08ec6c5 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -137,8 +137,8 @@ static const struct usb_device_id elgato_cam_link_4k = {
static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
struct uvc_streaming_control *ctrl)
{
- struct uvc_format *format = NULL;
- struct uvc_frame *frame = NULL;
+ const struct uvc_format *format = NULL;
+ const struct uvc_frame *frame = NULL;
unsigned int i;
/*
@@ -166,8 +166,8 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
}
for (i = 0; i < stream->nformats; ++i) {
- if (stream->format[i].index == ctrl->bFormatIndex) {
- format = &stream->format[i];
+ if (stream->formats[i].index == ctrl->bFormatIndex) {
+ format = &stream->formats[i];
break;
}
}
@@ -176,8 +176,8 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
return;
for (i = 0; i < format->nframes; ++i) {
- if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) {
- frame = &format->frame[i];
+ if (format->frames[i].bFrameIndex == ctrl->bFrameIndex) {
+ frame = &format->frames[i];
break;
}
}
@@ -2100,8 +2100,8 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset)
int uvc_video_init(struct uvc_streaming *stream)
{
struct uvc_streaming_control *probe = &stream->ctrl;
- struct uvc_format *format = NULL;
- struct uvc_frame *frame = NULL;
+ const struct uvc_format *format = NULL;
+ const struct uvc_frame *frame = NULL;
struct uvc_urb *uvc_urb;
unsigned int i;
int ret;
@@ -2161,7 +2161,7 @@ int uvc_video_init(struct uvc_streaming *stream)
* available format otherwise.
*/
for (i = stream->nformats; i > 0; --i) {
- format = &stream->format[i-1];
+ format = &stream->formats[i-1];
if (format->index == probe->bFormatIndex)
break;
}
@@ -2179,7 +2179,7 @@ int uvc_video_init(struct uvc_streaming *stream)
* descriptor is not found, use the first available frame.
*/
for (i = format->nframes; i > 0; --i) {
- frame = &format->frame[i-1];
+ frame = &format->frames[i-1];
if (frame->bFrameIndex == probe->bFrameIndex)
break;
}
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 9a596c8d894a..6fb0a78b1b00 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -251,7 +251,7 @@ struct uvc_frame {
u32 dwMaxVideoFrameBufferSize;
u8 bFrameIntervalType;
u32 dwDefaultFrameInterval;
- u32 *dwFrameInterval;
+ const u32 *dwFrameInterval;
};
struct uvc_format {
@@ -265,7 +265,7 @@ struct uvc_format {
u32 flags;
unsigned int nframes;
- struct uvc_frame *frame;
+ const struct uvc_frame *frames;
};
struct uvc_streaming_header {
@@ -438,12 +438,12 @@ struct uvc_streaming {
enum v4l2_buf_type type;
unsigned int nformats;
- struct uvc_format *format;
+ const struct uvc_format *formats;
struct uvc_streaming_control ctrl;
- struct uvc_format *def_format;
- struct uvc_format *cur_format;
- struct uvc_frame *cur_frame;
+ const struct uvc_format *def_format;
+ const struct uvc_format *cur_format;
+ const struct uvc_frame *cur_frame;
/*
* Protect access to ctrl, cur_format, cur_frame and hardware video
diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index 1c0d23c52203..5687089bea6e 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -1411,7 +1411,7 @@ static struct i2c_driver tuner_driver = {
.name = "tuner",
.pm = &tuner_pm_ops,
},
- .probe_new = tuner_probe,
+ .probe = tuner_probe,
.remove = tuner_remove,
.command = tuner_command,
.id_table = tuner_id,
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 3c5ab5ecd678..bee1535b04d3 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -235,91 +235,93 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
{
static const struct v4l2_format_info formats[] = {
/* RGB formats */
- { .format = V4L2_PIX_FMT_BGR24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_RGB24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_HSV24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_BGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_XBGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_BGRX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_RGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_XRGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_RGBX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_HSV32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_ARGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_RGBA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_ABGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_BGRA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_RGB565, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_RGB555, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_BGR666, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_BGR48_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_ABGR64_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_BGR24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_RGB24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_HSV24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_BGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_XBGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_BGRX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_RGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_XRGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_RGBX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_HSV32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_ARGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_RGBA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_ABGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_BGRA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_RGB565, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_RGB555, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_BGR666, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_BGR48_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_ABGR64_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
/* YUV packed formats */
- { .format = V4L2_PIX_FMT_YUYV, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_YVYU, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_UYVY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_VYUY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_Y212, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_YUYV, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_YVYU, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_UYVY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_VYUY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_Y212, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
/* YUV planar formats */
- { .format = V4L2_PIX_FMT_NV12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
- { .format = V4L2_PIX_FMT_NV21, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
- { .format = V4L2_PIX_FMT_NV16, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_NV61, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_NV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_NV42, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_P010, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_P012, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .hdiv = 2, .vdiv = 2 },
-
- { .format = V4L2_PIX_FMT_YUV410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 },
- { .format = V4L2_PIX_FMT_YVU410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 },
- { .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_YUV420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 },
- { .format = V4L2_PIX_FMT_YVU420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 },
- { .format = V4L2_PIX_FMT_YUV422P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_GREY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_NV12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_NV21, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_NV16, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_NV61, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_NV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_NV42, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_P010, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_P012, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
+
+ { .format = V4L2_PIX_FMT_YUV410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 4 },
+ { .format = V4L2_PIX_FMT_YVU410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 4 },
+ { .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_YUV420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_YVU420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_YUV422P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_GREY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
/* Tiled YUV formats */
- { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
- { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_NV15_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
+ .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 }},
+ { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
/* YUV planar formats, non contiguous variant */
- { .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 },
- { .format = V4L2_PIX_FMT_YVU420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 },
- { .format = V4L2_PIX_FMT_YUV422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_YVU422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_YUV444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_YVU444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 },
-
- { .format = V4L2_PIX_FMT_NV12M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
- { .format = V4L2_PIX_FMT_NV21M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
- { .format = V4L2_PIX_FMT_NV16M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_NV61M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_P012M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_YVU420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_YUV422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_YVU422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_YUV444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_YVU444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+
+ { .format = V4L2_PIX_FMT_NV12M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_NV21M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_NV16M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_NV61M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_P012M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
/* Bayer RGB formats */
- { .format = V4L2_PIX_FMT_SBGGR8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SGBRG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SGRBG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SRGGB8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SBGGR10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SGBRG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SGRBG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SRGGB10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SBGGR10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SGBRG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SGRBG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SRGGB10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SBGGR10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SGBRG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SGRBG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SRGGB10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SBGGR12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SGBRG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SGRBG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
- { .format = V4L2_PIX_FMT_SRGGB12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SBGGR8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SGBRG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SGRBG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SRGGB8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SBGGR10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SGBRG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SGRBG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SRGGB10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SBGGR10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SGBRG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SGRBG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SRGGB10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SBGGR10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SGBRG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SGRBG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SRGGB10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SBGGR12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SGBRG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SGRBG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_SRGGB12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
};
unsigned int i;
@@ -379,7 +381,7 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt,
if (info->mem_planes == 1) {
plane = &pixfmt->plane_fmt[0];
- plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0];
+ plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0] / info->bpp_div[0];
plane->sizeimage = 0;
for (i = 0; i < info->comp_planes; i++) {
@@ -393,7 +395,7 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt,
plane->sizeimage += info->bpp[i] *
DIV_ROUND_UP(aligned_width, hdiv) *
- DIV_ROUND_UP(aligned_height, vdiv);
+ DIV_ROUND_UP(aligned_height, vdiv) / info->bpp_div[i];
}
} else {
for (i = 0; i < info->comp_planes; i++) {
@@ -407,7 +409,7 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt,
plane = &pixfmt->plane_fmt[i];
plane->bytesperline =
- info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv);
+ info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv) / info->bpp_div[i];
plane->sizeimage =
plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv);
}
@@ -433,7 +435,7 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat,
pixfmt->width = width;
pixfmt->height = height;
pixfmt->pixelformat = pixelformat;
- pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0];
+ pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0] / info->bpp_div[0];
pixfmt->sizeimage = 0;
for (i = 0; i < info->comp_planes; i++) {
@@ -447,7 +449,7 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat,
pixfmt->sizeimage += info->bpp[i] *
DIV_ROUND_UP(aligned_width, hdiv) *
- DIV_ROUND_UP(aligned_height, vdiv);
+ DIV_ROUND_UP(aligned_height, vdiv) / info->bpp_div[i];
}
return 0;
}
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
index 29169170880a..a662fb60f73f 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
@@ -111,6 +111,7 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx,
struct v4l2_ctrl_vp9_frame *p_vp9_frame;
struct v4l2_ctrl_fwht_params *p_fwht_params;
struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix;
+ struct v4l2_ctrl_av1_sequence *p_av1_sequence;
void *p = ptr.p + idx * ctrl->elem_size;
if (ctrl->p_def.p_const)
@@ -157,6 +158,10 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx,
p_vp9_frame->flags |= V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING |
V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING;
break;
+ case V4L2_CTRL_TYPE_AV1_SEQUENCE:
+ p_av1_sequence = p;
+ p_av1_sequence->bit_depth = 8;
+ break;
case V4L2_CTRL_TYPE_FWHT_PARAMS:
p_fwht_params = p;
p_fwht_params->version = V4L2_FWHT_VERSION;
@@ -350,6 +355,19 @@ void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl)
case V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS:
pr_cont("HEVC_DECODE_PARAMS");
break;
+ case V4L2_CTRL_TYPE_AV1_SEQUENCE:
+ pr_cont("AV1_SEQUENCE");
+ break;
+ case V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY:
+ pr_cont("AV1_TILE_GROUP_ENTRY");
+ break;
+ case V4L2_CTRL_TYPE_AV1_FRAME:
+ pr_cont("AV1_FRAME");
+ break;
+ case V4L2_CTRL_TYPE_AV1_FILM_GRAIN:
+ pr_cont("AV1_FILM_GRAIN");
+ break;
+
default:
pr_cont("unknown type %d", ctrl->type);
break;
@@ -547,6 +565,231 @@ validate_vp9_frame(struct v4l2_ctrl_vp9_frame *frame)
return 0;
}
+static int validate_av1_quantization(struct v4l2_av1_quantization *q)
+{
+ if (q->flags > GENMASK(2, 0))
+ return -EINVAL;
+
+ if (q->delta_q_y_dc < -64 || q->delta_q_y_dc > 63 ||
+ q->delta_q_u_dc < -64 || q->delta_q_u_dc > 63 ||
+ q->delta_q_v_dc < -64 || q->delta_q_v_dc > 63 ||
+ q->delta_q_u_ac < -64 || q->delta_q_u_ac > 63 ||
+ q->delta_q_v_ac < -64 || q->delta_q_v_ac > 63 ||
+ q->delta_q_res > GENMASK(1, 0))
+ return -EINVAL;
+
+ if (q->qm_y > GENMASK(3, 0) ||
+ q->qm_u > GENMASK(3, 0) ||
+ q->qm_v > GENMASK(3, 0))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int validate_av1_segmentation(struct v4l2_av1_segmentation *s)
+{
+ u32 i;
+ u32 j;
+
+ if (s->flags > GENMASK(4, 0))
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(s->feature_data); i++) {
+ static const int segmentation_feature_signed[] = { 1, 1, 1, 1, 1, 0, 0, 0 };
+ static const int segmentation_feature_max[] = { 255, 63, 63, 63, 63, 7, 0, 0};
+
+ for (j = 0; j < ARRAY_SIZE(s->feature_data[j]); j++) {
+ s32 limit = segmentation_feature_max[j];
+
+ if (segmentation_feature_signed[j]) {
+ if (s->feature_data[i][j] < -limit ||
+ s->feature_data[i][j] > limit)
+ return -EINVAL;
+ } else {
+ if (s->feature_data[i][j] < 0 || s->feature_data[i][j] > limit)
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int validate_av1_loop_filter(struct v4l2_av1_loop_filter *lf)
+{
+ u32 i;
+
+ if (lf->flags > GENMASK(3, 0))
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(lf->level); i++) {
+ if (lf->level[i] > GENMASK(5, 0))
+ return -EINVAL;
+ }
+
+ if (lf->sharpness > GENMASK(2, 0))
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) {
+ if (lf->ref_deltas[i] < -64 || lf->ref_deltas[i] > 63)
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) {
+ if (lf->mode_deltas[i] < -64 || lf->mode_deltas[i] > 63)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int validate_av1_cdef(struct v4l2_av1_cdef *cdef)
+{
+ u32 i;
+
+ if (cdef->damping_minus_3 > GENMASK(1, 0) ||
+ cdef->bits > GENMASK(1, 0))
+ return -EINVAL;
+
+ for (i = 0; i < 1 << cdef->bits; i++) {
+ if (cdef->y_pri_strength[i] > GENMASK(3, 0) ||
+ cdef->y_sec_strength[i] > 4 ||
+ cdef->uv_pri_strength[i] > GENMASK(3, 0) ||
+ cdef->uv_sec_strength[i] > 4)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int validate_av1_loop_restauration(struct v4l2_av1_loop_restoration *lr)
+{
+ if (lr->lr_unit_shift > 3 || lr->lr_uv_shift > 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int validate_av1_film_grain(struct v4l2_ctrl_av1_film_grain *fg)
+{
+ u32 i;
+
+ if (fg->flags > GENMASK(4, 0))
+ return -EINVAL;
+
+ if (fg->film_grain_params_ref_idx > GENMASK(2, 0) ||
+ fg->num_y_points > 14 ||
+ fg->num_cb_points > 10 ||
+ fg->num_cr_points > GENMASK(3, 0) ||
+ fg->grain_scaling_minus_8 > GENMASK(1, 0) ||
+ fg->ar_coeff_lag > GENMASK(1, 0) ||
+ fg->ar_coeff_shift_minus_6 > GENMASK(1, 0) ||
+ fg->grain_scale_shift > GENMASK(1, 0))
+ return -EINVAL;
+
+ if (!(fg->flags & V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN))
+ return 0;
+
+ for (i = 1; i < fg->num_y_points; i++)
+ if (fg->point_y_value[i] <= fg->point_y_value[i - 1])
+ return -EINVAL;
+
+ for (i = 1; i < fg->num_cb_points; i++)
+ if (fg->point_cb_value[i] <= fg->point_cb_value[i - 1])
+ return -EINVAL;
+
+ for (i = 1; i < fg->num_cr_points; i++)
+ if (fg->point_cr_value[i] <= fg->point_cr_value[i - 1])
+ return -EINVAL;
+
+ return 0;
+}
+
+static int validate_av1_frame(struct v4l2_ctrl_av1_frame *f)
+{
+ int ret = 0;
+
+ ret = validate_av1_quantization(&f->quantization);
+ if (ret)
+ return ret;
+ ret = validate_av1_segmentation(&f->segmentation);
+ if (ret)
+ return ret;
+ ret = validate_av1_loop_filter(&f->loop_filter);
+ if (ret)
+ return ret;
+ ret = validate_av1_cdef(&f->cdef);
+ if (ret)
+ return ret;
+ ret = validate_av1_loop_restauration(&f->loop_restoration);
+ if (ret)
+ return ret;
+
+ if (f->flags &
+ ~(V4L2_AV1_FRAME_FLAG_SHOW_FRAME |
+ V4L2_AV1_FRAME_FLAG_SHOWABLE_FRAME |
+ V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE |
+ V4L2_AV1_FRAME_FLAG_DISABLE_CDF_UPDATE |
+ V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS |
+ V4L2_AV1_FRAME_FLAG_FORCE_INTEGER_MV |
+ V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC |
+ V4L2_AV1_FRAME_FLAG_USE_SUPERRES |
+ V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV |
+ V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE |
+ V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS |
+ V4L2_AV1_FRAME_FLAG_DISABLE_FRAME_END_UPDATE_CDF |
+ V4L2_AV1_FRAME_FLAG_ALLOW_WARPED_MOTION |
+ V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT |
+ V4L2_AV1_FRAME_FLAG_REDUCED_TX_SET |
+ V4L2_AV1_FRAME_FLAG_SKIP_MODE_ALLOWED |
+ V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT |
+ V4L2_AV1_FRAME_FLAG_FRAME_SIZE_OVERRIDE |
+ V4L2_AV1_FRAME_FLAG_BUFFER_REMOVAL_TIME_PRESENT |
+ V4L2_AV1_FRAME_FLAG_FRAME_REFS_SHORT_SIGNALING))
+ return -EINVAL;
+
+ if (f->superres_denom > GENMASK(2, 0) + 9)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int validate_av1_sequence(struct v4l2_ctrl_av1_sequence *s)
+{
+ if (s->flags &
+ ~(V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE |
+ V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK |
+ V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA |
+ V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER |
+ V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND |
+ V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND |
+ V4L2_AV1_SEQUENCE_FLAG_ENABLE_WARPED_MOTION |
+ V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER |
+ V4L2_AV1_SEQUENCE_FLAG_ENABLE_ORDER_HINT |
+ V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP |
+ V4L2_AV1_SEQUENCE_FLAG_ENABLE_REF_FRAME_MVS |
+ V4L2_AV1_SEQUENCE_FLAG_ENABLE_SUPERRES |
+ V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF |
+ V4L2_AV1_SEQUENCE_FLAG_ENABLE_RESTORATION |
+ V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME |
+ V4L2_AV1_SEQUENCE_FLAG_COLOR_RANGE |
+ V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_X |
+ V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_Y |
+ V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT |
+ V4L2_AV1_SEQUENCE_FLAG_SEPARATE_UV_DELTA_Q))
+ return -EINVAL;
+
+ if (s->seq_profile == 1 && s->flags & V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME)
+ return -EINVAL;
+
+ /* reserved */
+ if (s->seq_profile > 2)
+ return -EINVAL;
+
+ /* TODO: PROFILES */
+ return 0;
+}
+
/*
* Compound controls validation requires setting unused fields/flags to zero
* in order to properly detect unchanged controls with v4l2_ctrl_type_op_equal's
@@ -911,6 +1154,14 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
case V4L2_CTRL_TYPE_VP9_FRAME:
return validate_vp9_frame(p);
+ case V4L2_CTRL_TYPE_AV1_FRAME:
+ return validate_av1_frame(p);
+ case V4L2_CTRL_TYPE_AV1_SEQUENCE:
+ return validate_av1_sequence(p);
+ case V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY:
+ break;
+ case V4L2_CTRL_TYPE_AV1_FILM_GRAIN:
+ return validate_av1_film_grain(p);
case V4L2_CTRL_TYPE_AREA:
area = p;
@@ -1602,6 +1853,18 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
case V4L2_CTRL_TYPE_VP9_FRAME:
elem_size = sizeof(struct v4l2_ctrl_vp9_frame);
break;
+ case V4L2_CTRL_TYPE_AV1_SEQUENCE:
+ elem_size = sizeof(struct v4l2_ctrl_av1_sequence);
+ break;
+ case V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY:
+ elem_size = sizeof(struct v4l2_ctrl_av1_tile_group_entry);
+ break;
+ case V4L2_CTRL_TYPE_AV1_FRAME:
+ elem_size = sizeof(struct v4l2_ctrl_av1_frame);
+ break;
+ case V4L2_CTRL_TYPE_AV1_FILM_GRAIN:
+ elem_size = sizeof(struct v4l2_ctrl_av1_film_grain);
+ break;
case V4L2_CTRL_TYPE_AREA:
elem_size = sizeof(struct v4l2_area);
break;
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
index 564fedee2c88..8696eb1cdd61 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
@@ -499,6 +499,40 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
NULL,
};
+ static const char * const av1_profile[] = {
+ "Main",
+ "High",
+ "Professional",
+ NULL,
+ };
+ static const char * const av1_level[] = {
+ "2.0",
+ "2.1",
+ "2.2",
+ "2.3",
+ "3.0",
+ "3.1",
+ "3.2",
+ "3.3",
+ "4.0",
+ "4.1",
+ "4.2",
+ "4.3",
+ "5.0",
+ "5.1",
+ "5.2",
+ "5.3",
+ "6.0",
+ "6.1",
+ "6.2",
+ "6.3",
+ "7.0",
+ "7.1",
+ "7.2",
+ "7.3",
+ NULL,
+ };
+
static const char * const hevc_profile[] = {
"Main",
"Main Still Picture",
@@ -704,6 +738,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
return hevc_tier;
case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE:
return hevc_loop_filter_mode;
+ case V4L2_CID_MPEG_VIDEO_AV1_PROFILE:
+ return av1_profile;
+ case V4L2_CID_MPEG_VIDEO_AV1_LEVEL:
+ return av1_level;
case V4L2_CID_STATELESS_HEVC_DECODE_MODE:
return hevc_decode_mode;
case V4L2_CID_STATELESS_HEVC_START_CODE:
@@ -1004,6 +1042,10 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES: return "Reference Frames for a P-Frame";
case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR: return "Prepend SPS and PPS to IDR";
+ /* AV1 controls */
+ case V4L2_CID_MPEG_VIDEO_AV1_PROFILE: return "AV1 Profile";
+ case V4L2_CID_MPEG_VIDEO_AV1_LEVEL: return "AV1 Level";
+
/* CAMERA controls */
/* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_CAMERA_CLASS: return "Camera Controls";
@@ -1190,6 +1232,10 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_STATELESS_HEVC_DECODE_MODE: return "HEVC Decode Mode";
case V4L2_CID_STATELESS_HEVC_START_CODE: return "HEVC Start Code";
case V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS: return "HEVC Entry Point Offsets";
+ case V4L2_CID_STATELESS_AV1_SEQUENCE: return "AV1 Sequence Parameters";
+ case V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY: return "AV1 Tile Group Entry";
+ case V4L2_CID_STATELESS_AV1_FRAME: return "AV1 Frame Parameters";
+ case V4L2_CID_STATELESS_AV1_FILM_GRAIN: return "AV1 Film Grain";
/* Colorimetry controls */
/* Keep the order of the 'case's the same as in v4l2-controls.h! */
@@ -1365,6 +1411,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD:
case V4L2_CID_MPEG_VIDEO_HEVC_TIER:
case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE:
+ case V4L2_CID_MPEG_VIDEO_AV1_PROFILE:
+ case V4L2_CID_MPEG_VIDEO_AV1_LEVEL:
case V4L2_CID_STATELESS_HEVC_DECODE_MODE:
case V4L2_CID_STATELESS_HEVC_START_CODE:
case V4L2_CID_STATELESS_H264_DECODE_MODE:
@@ -1531,6 +1579,19 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_STATELESS_VP9_FRAME:
*type = V4L2_CTRL_TYPE_VP9_FRAME;
break;
+ case V4L2_CID_STATELESS_AV1_SEQUENCE:
+ *type = V4L2_CTRL_TYPE_AV1_SEQUENCE;
+ break;
+ case V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY:
+ *type = V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY;
+ *flags |= V4L2_CTRL_FLAG_DYNAMIC_ARRAY;
+ break;
+ case V4L2_CID_STATELESS_AV1_FRAME:
+ *type = V4L2_CTRL_TYPE_AV1_FRAME;
+ break;
+ case V4L2_CID_STATELESS_AV1_FILM_GRAIN:
+ *type = V4L2_CTRL_TYPE_AV1_FILM_GRAIN;
+ break;
case V4L2_CID_UNIT_CELL_SIZE:
*type = V4L2_CTRL_TYPE_AREA;
*flags |= V4L2_CTRL_FLAG_READ_ONLY;
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index a858acea6547..01ba27f2ef87 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1356,6 +1356,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_NV12_4L4: descr = "Y/UV 4:2:0 (4x4 Linear)"; break;
case V4L2_PIX_FMT_NV12_16L16: descr = "Y/UV 4:2:0 (16x16 Linear)"; break;
case V4L2_PIX_FMT_NV12_32L32: descr = "Y/UV 4:2:0 (32x32 Linear)"; break;
+ case V4L2_PIX_FMT_NV15_4L4: descr = "10-bit Y/UV 4:2:0 (4x4 Linear)"; break;
case V4L2_PIX_FMT_P010_4L4: descr = "10-bit Y/UV 4:2:0 (4x4 Linear)"; break;
case V4L2_PIX_FMT_NV12M: descr = "Y/UV 4:2:0 (N-C)"; break;
case V4L2_PIX_FMT_NV21M: descr = "Y/VU 4:2:0 (N-C)"; break;
@@ -1506,6 +1507,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_QC08C: descr = "QCOM Compressed 8-bit Format"; break;
case V4L2_PIX_FMT_QC10C: descr = "QCOM Compressed 10-bit Format"; break;
case V4L2_PIX_FMT_AJPG: descr = "Aspeed JPEG"; break;
+ case V4L2_PIX_FMT_AV1_FRAME: descr = "AV1 Frame"; break;
default:
if (fmt->description[0])
return;
diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
index 22fe08fce0a9..52d349e72b8c 100644
--- a/drivers/media/v4l2-core/v4l2-mc.c
+++ b/drivers/media/v4l2-core/v4l2-mc.c
@@ -105,9 +105,11 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
/* Link the tuner and IF video output pads */
if (tuner) {
if (if_vid) {
- pad_source = media_get_pad_index(tuner, false,
+ pad_source = media_get_pad_index(tuner,
+ MEDIA_PAD_FL_SOURCE,
PAD_SIGNAL_ANALOG);
- pad_sink = media_get_pad_index(if_vid, true,
+ pad_sink = media_get_pad_index(if_vid,
+ MEDIA_PAD_FL_SINK,
PAD_SIGNAL_ANALOG);
if (pad_source < 0 || pad_sink < 0) {
dev_warn(mdev->dev, "Couldn't get tuner and/or PLL pad(s): (%d, %d)\n",
@@ -122,9 +124,11 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
return ret;
}
- pad_source = media_get_pad_index(if_vid, false,
+ pad_source = media_get_pad_index(if_vid,
+ MEDIA_PAD_FL_SOURCE,
PAD_SIGNAL_ANALOG);
- pad_sink = media_get_pad_index(decoder, true,
+ pad_sink = media_get_pad_index(decoder,
+ MEDIA_PAD_FL_SINK,
PAD_SIGNAL_ANALOG);
if (pad_source < 0 || pad_sink < 0) {
dev_warn(mdev->dev, "get decoder and/or PLL pad(s): (%d, %d)\n",
@@ -139,9 +143,11 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
return ret;
}
} else {
- pad_source = media_get_pad_index(tuner, false,
+ pad_source = media_get_pad_index(tuner,
+ MEDIA_PAD_FL_SOURCE,
PAD_SIGNAL_ANALOG);
- pad_sink = media_get_pad_index(decoder, true,
+ pad_sink = media_get_pad_index(decoder,
+ MEDIA_PAD_FL_SINK,
PAD_SIGNAL_ANALOG);
if (pad_source < 0 || pad_sink < 0) {
dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s): (%d, %d)\n",
@@ -156,9 +162,11 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
}
if (if_aud) {
- pad_source = media_get_pad_index(tuner, false,
+ pad_source = media_get_pad_index(tuner,
+ MEDIA_PAD_FL_SOURCE,
PAD_SIGNAL_AUDIO);
- pad_sink = media_get_pad_index(if_aud, true,
+ pad_sink = media_get_pad_index(if_aud,
+ MEDIA_PAD_FL_SINK,
PAD_SIGNAL_AUDIO);
if (pad_source < 0 || pad_sink < 0) {
dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s) for audio: (%d, %d)\n",
@@ -180,7 +188,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
/* Create demod to V4L, VBI and SDR radio links */
if (io_v4l) {
- pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
+ pad_source = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE,
+ PAD_SIGNAL_DV);
if (pad_source < 0) {
dev_warn(mdev->dev, "couldn't get decoder output pad for V4L I/O\n");
return -EINVAL;
@@ -195,7 +204,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
}
if (io_swradio) {
- pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
+ pad_source = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE,
+ PAD_SIGNAL_DV);
if (pad_source < 0) {
dev_warn(mdev->dev, "couldn't get decoder output pad for SDR\n");
return -EINVAL;
@@ -210,7 +220,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
}
if (io_vbi) {
- pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
+ pad_source = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE,
+ PAD_SIGNAL_DV);
if (pad_source < 0) {
dev_warn(mdev->dev, "couldn't get decoder output pad for VBI\n");
return -EINVAL;
@@ -231,7 +242,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
case MEDIA_ENT_F_CONN_RF:
if (!tuner)
continue;
- pad_sink = media_get_pad_index(tuner, true,
+ pad_sink = media_get_pad_index(tuner, MEDIA_PAD_FL_SINK,
PAD_SIGNAL_ANALOG);
if (pad_sink < 0) {
dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n");
@@ -243,7 +254,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
break;
case MEDIA_ENT_F_CONN_SVIDEO:
case MEDIA_ENT_F_CONN_COMPOSITE:
- pad_sink = media_get_pad_index(decoder, true,
+ pad_sink = media_get_pad_index(decoder,
+ MEDIA_PAD_FL_SINK,
PAD_SIGNAL_ANALOG);
if (pad_sink < 0) {
dev_warn(mdev->dev, "couldn't get decoder analog pad sink\n");
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 91774e6ee624..8efdd1f97139 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -30,17 +30,6 @@ config ARM_PL172_MPMC
If you have an embedded system with an AMBA bus and a PL172
controller, say Y or M here.
-config ATMEL_SDRAMC
- bool "Atmel (Multi-port DDR-)SDRAM Controller"
- default y if ARCH_AT91
- depends on ARCH_AT91 || COMPILE_TEST
- depends on OF
- help
- This driver is for Atmel SDRAM Controller or Atmel Multi-port
- DDR-SDRAM Controller available on Atmel AT91SAM9 and SAMA5 SoCs.
- Starting with the at91sam9g45, this controller supports SDR, DDR and
- LP-DDR memories.
-
config ATMEL_EBI
bool "Atmel EBI driver"
default y if ARCH_AT91
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index ae14ded464a8..d2e6ca9abbe0 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -8,7 +8,6 @@ ifeq ($(CONFIG_DDR),y)
obj-$(CONFIG_OF) += of_memory.o
endif
obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o
-obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o
obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o
obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o
obj-$(CONFIG_BRCMSTB_MEMC) += brcmstb_memc.o
diff --git a/drivers/memory/atmel-sdramc.c b/drivers/memory/atmel-sdramc.c
deleted file mode 100644
index ea6e9e1eaf04..000000000000
--- a/drivers/memory/atmel-sdramc.c
+++ /dev/null
@@ -1,74 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Atmel (Multi-port DDR-)SDRAM Controller driver
- *
- * Author: Alexandre Belloni <alexandre.belloni@free-electrons.com>
- *
- * Copyright (C) 2014 Atmel
- */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-
-struct at91_ramc_caps {
- bool has_ddrck;
- bool has_mpddr_clk;
-};
-
-static const struct at91_ramc_caps at91rm9200_caps = { };
-
-static const struct at91_ramc_caps at91sam9g45_caps = {
- .has_ddrck = 1,
- .has_mpddr_clk = 0,
-};
-
-static const struct at91_ramc_caps sama5d3_caps = {
- .has_ddrck = 1,
- .has_mpddr_clk = 1,
-};
-
-static const struct of_device_id atmel_ramc_of_match[] = {
- { .compatible = "atmel,at91rm9200-sdramc", .data = &at91rm9200_caps, },
- { .compatible = "atmel,at91sam9260-sdramc", .data = &at91rm9200_caps, },
- { .compatible = "atmel,at91sam9g45-ddramc", .data = &at91sam9g45_caps, },
- { .compatible = "atmel,sama5d3-ddramc", .data = &sama5d3_caps, },
- {},
-};
-
-static int atmel_ramc_probe(struct platform_device *pdev)
-{
- const struct at91_ramc_caps *caps;
- struct clk *clk;
-
- caps = of_device_get_match_data(&pdev->dev);
-
- if (caps->has_ddrck) {
- clk = devm_clk_get_enabled(&pdev->dev, "ddrck");
- if (IS_ERR(clk))
- return PTR_ERR(clk);
- }
-
- if (caps->has_mpddr_clk) {
- clk = devm_clk_get_enabled(&pdev->dev, "mpddr");
- if (IS_ERR(clk)) {
- pr_err("AT91 RAMC: couldn't get mpddr clock\n");
- return PTR_ERR(clk);
- }
- }
-
- return 0;
-}
-
-static struct platform_driver atmel_ramc_driver = {
- .probe = atmel_ramc_probe,
- .driver = {
- .name = "atmel-ramc",
- .of_match_table = atmel_ramc_of_match,
- },
-};
-
-builtin_platform_driver(atmel_ramc_driver);
diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c
index 76c82e9c8fce..9339f80b21c5 100644
--- a/drivers/memory/brcmstb_dpfe.c
+++ b/drivers/memory/brcmstb_dpfe.c
@@ -434,15 +434,17 @@ static void __finalize_command(struct brcmstb_dpfe_priv *priv)
static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd,
u32 result[])
{
- const u32 *msg = priv->dpfe_api->command[cmd];
void __iomem *regs = priv->regs;
unsigned int i, chksum, chksum_idx;
+ const u32 *msg;
int ret = 0;
u32 resp;
if (cmd >= DPFE_CMD_MAX)
return -1;
+ msg = priv->dpfe_api->command[cmd];
+
mutex_lock(&priv->lock);
/* Wait for DCPU to become ready */
diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c
index 025bb628aaf3..75fcba45ec1b 100644
--- a/drivers/memory/renesas-rpc-if.c
+++ b/drivers/memory/renesas-rpc-if.c
@@ -7,6 +7,7 @@
* Copyright (C) 2019-2020 Cogent Embedded, Inc.
*/
+#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -163,6 +164,11 @@ static const struct regmap_access_table rpcif_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(rpcif_volatile_ranges),
};
+struct rpcif_info {
+ enum rpcif_type type;
+ u8 strtim;
+};
+
struct rpcif_priv {
struct device *dev;
void __iomem *base;
@@ -171,7 +177,7 @@ struct rpcif_priv {
struct reset_control *rstc;
struct platform_device *vdev;
size_t size;
- enum rpcif_type type;
+ const struct rpcif_info *info;
enum rpcif_data_dir dir;
u8 bus_size;
u8 xfer_size;
@@ -186,6 +192,26 @@ struct rpcif_priv {
u32 ddr; /* DRDRENR or SMDRENR */
};
+static const struct rpcif_info rpcif_info_r8a7796 = {
+ .type = RPCIF_RCAR_GEN3,
+ .strtim = 6,
+};
+
+static const struct rpcif_info rpcif_info_gen3 = {
+ .type = RPCIF_RCAR_GEN3,
+ .strtim = 7,
+};
+
+static const struct rpcif_info rpcif_info_rz_g2l = {
+ .type = RPCIF_RZ_G2L,
+ .strtim = 7,
+};
+
+static const struct rpcif_info rpcif_info_gen4 = {
+ .type = RPCIF_RCAR_GEN4,
+ .strtim = 15,
+};
+
/*
* Custom accessor functions to ensure SM[RW]DR[01] are always accessed with
* proper width. Requires rpcif_priv.xfer_size to be correctly set before!
@@ -310,7 +336,7 @@ int rpcif_hw_init(struct device *dev, bool hyperflash)
if (ret)
return ret;
- if (rpc->type == RPCIF_RZ_G2L) {
+ if (rpc->info->type == RPCIF_RZ_G2L) {
ret = reset_control_reset(rpc->rstc);
if (ret)
return ret;
@@ -324,12 +350,10 @@ int rpcif_hw_init(struct device *dev, bool hyperflash)
/* DMA Transfer is not supported */
regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_HS, 0);
- if (rpc->type == RPCIF_RCAR_GEN3)
- regmap_update_bits(rpc->regmap, RPCIF_PHYCNT,
- RPCIF_PHYCNT_STRTIM(7), RPCIF_PHYCNT_STRTIM(7));
- else if (rpc->type == RPCIF_RCAR_GEN4)
- regmap_update_bits(rpc->regmap, RPCIF_PHYCNT,
- RPCIF_PHYCNT_STRTIM(15), RPCIF_PHYCNT_STRTIM(15));
+ regmap_update_bits(rpc->regmap, RPCIF_PHYCNT,
+ /* create mask with all affected bits set */
+ RPCIF_PHYCNT_STRTIM(BIT(fls(rpc->info->strtim)) - 1),
+ RPCIF_PHYCNT_STRTIM(rpc->info->strtim));
regmap_update_bits(rpc->regmap, RPCIF_PHYOFFSET1, RPCIF_PHYOFFSET1_DDRTMG(3),
RPCIF_PHYOFFSET1_DDRTMG(3));
@@ -340,7 +364,7 @@ int rpcif_hw_init(struct device *dev, bool hyperflash)
regmap_update_bits(rpc->regmap, RPCIF_PHYINT,
RPCIF_PHYINT_WPVAL, 0);
- if (rpc->type == RPCIF_RZ_G2L)
+ if (rpc->info->type == RPCIF_RZ_G2L)
regmap_update_bits(rpc->regmap, RPCIF_CMNCR,
RPCIF_CMNCR_MOIIO(3) | RPCIF_CMNCR_IOFV(3) |
RPCIF_CMNCR_BSZ(3),
@@ -729,9 +753,9 @@ static int rpcif_probe(struct platform_device *pdev)
rpc->dirmap = devm_ioremap_resource(dev, res);
if (IS_ERR(rpc->dirmap))
return PTR_ERR(rpc->dirmap);
- rpc->size = resource_size(res);
- rpc->type = (uintptr_t)of_device_get_match_data(dev);
+ rpc->size = resource_size(res);
+ rpc->info = of_device_get_match_data(dev);
rpc->rstc = devm_reset_control_get_exclusive(dev, NULL);
if (IS_ERR(rpc->rstc))
return PTR_ERR(rpc->rstc);
@@ -764,9 +788,10 @@ static int rpcif_remove(struct platform_device *pdev)
}
static const struct of_device_id rpcif_of_match[] = {
- { .compatible = "renesas,rcar-gen3-rpc-if", .data = (void *)RPCIF_RCAR_GEN3 },
- { .compatible = "renesas,rcar-gen4-rpc-if", .data = (void *)RPCIF_RCAR_GEN4 },
- { .compatible = "renesas,rzg2l-rpc-if", .data = (void *)RPCIF_RZ_G2L },
+ { .compatible = "renesas,r8a7796-rpc-if", .data = &rpcif_info_r8a7796 },
+ { .compatible = "renesas,rcar-gen3-rpc-if", .data = &rpcif_info_gen3 },
+ { .compatible = "renesas,rcar-gen4-rpc-if", .data = &rpcif_info_gen4 },
+ { .compatible = "renesas,rzg2l-rpc-if", .data = &rpcif_info_rz_g2l },
{},
};
MODULE_DEVICE_TABLE(of, rpcif_of_match);
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index 9082b6c3763d..4a750da1c12a 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sort.h>
+#include <linux/tegra-icc.h>
#include <soc/tegra/fuse.h>
@@ -792,6 +793,8 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc)
mc->provider.data = &mc->provider;
mc->provider.set = mc->soc->icc_ops->set;
mc->provider.aggregate = mc->soc->icc_ops->aggregate;
+ mc->provider.get_bw = mc->soc->icc_ops->get_bw;
+ mc->provider.xlate = mc->soc->icc_ops->xlate;
mc->provider.xlate_extended = mc->soc->icc_ops->xlate_extended;
icc_provider_init(&mc->provider);
@@ -824,6 +827,8 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc)
err = icc_link_create(node, TEGRA_ICC_MC);
if (err)
goto remove_nodes;
+
+ node->data = (struct tegra_mc_client *)&(mc->soc->clients[i]);
}
err = icc_provider_register(&mc->provider);
@@ -838,6 +843,23 @@ remove_nodes:
return err;
}
+static void tegra_mc_num_channel_enabled(struct tegra_mc *mc)
+{
+ unsigned int i;
+ u32 value;
+
+ value = mc_ch_readl(mc, 0, MC_EMEM_ADR_CFG_CHANNEL_ENABLE);
+ if (value <= 0) {
+ mc->num_channels = mc->soc->num_channels;
+ return;
+ }
+
+ for (i = 0; i < 32; i++) {
+ if (value & BIT(i))
+ mc->num_channels++;
+ }
+}
+
static int tegra_mc_probe(struct platform_device *pdev)
{
struct tegra_mc *mc;
@@ -876,6 +898,8 @@ static int tegra_mc_probe(struct platform_device *pdev)
return err;
}
+ tegra_mc_num_channel_enabled(mc);
+
if (mc->soc->ops && mc->soc->ops->handle_irq) {
mc->irq = platform_get_irq(pdev, 0);
if (mc->irq < 0)
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
index bc01586b6560..c3f6655bec60 100644
--- a/drivers/memory/tegra/mc.h
+++ b/drivers/memory/tegra/mc.h
@@ -53,6 +53,7 @@
#define MC_ERR_ROUTE_SANITY_ADR 0x9c4
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00
#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04
+#define MC_EMEM_ADR_CFG_CHANNEL_ENABLE 0xdf8
#define MC_GLOBAL_INTSTATUS 0xf24
#define MC_ERR_ADR_HI 0x11fc
diff --git a/drivers/memory/tegra/tegra186-emc.c b/drivers/memory/tegra/tegra186-emc.c
index e935ad4e95b6..6ad8a4023dd7 100644
--- a/drivers/memory/tegra/tegra186-emc.c
+++ b/drivers/memory/tegra/tegra186-emc.c
@@ -7,9 +7,11 @@
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <soc/tegra/bpmp.h>
+#include "mc.h"
struct tegra186_emc_dvfs {
unsigned long latency;
@@ -29,8 +31,15 @@ struct tegra186_emc {
unsigned long min_rate;
unsigned long max_rate;
} debugfs;
+
+ struct icc_provider provider;
};
+static inline struct tegra186_emc *to_tegra186_emc(struct icc_provider *provider)
+{
+ return container_of(provider, struct tegra186_emc, provider);
+}
+
/*
* debugfs interface
*
@@ -146,8 +155,102 @@ DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_max_rate_fops,
tegra186_emc_debug_max_rate_get,
tegra186_emc_debug_max_rate_set, "%llu\n");
+/*
+ * tegra_emc_icc_set_bw() - Set BW api for EMC provider
+ * @src: ICC node for External Memory Controller (EMC)
+ * @dst: ICC node for External Memory (DRAM)
+ *
+ * Do nothing here as info to BPMP-FW is now passed in the BW set function
+ * of the MC driver. BPMP-FW sets the final Freq based on the passed values.
+ */
+static int tegra_emc_icc_set_bw(struct icc_node *src, struct icc_node *dst)
+{
+ return 0;
+}
+
+static struct icc_node *
+tegra_emc_of_icc_xlate(struct of_phandle_args *spec, void *data)
+{
+ struct icc_provider *provider = data;
+ struct icc_node *node;
+
+ /* External Memory is the only possible ICC route */
+ list_for_each_entry(node, &provider->nodes, node_list) {
+ if (node->id != TEGRA_ICC_EMEM)
+ continue;
+
+ return node;
+ }
+
+ return ERR_PTR(-EPROBE_DEFER);
+}
+
+static int tegra_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
+{
+ *avg = 0;
+ *peak = 0;
+
+ return 0;
+}
+
+static int tegra_emc_interconnect_init(struct tegra186_emc *emc)
+{
+ struct tegra_mc *mc = dev_get_drvdata(emc->dev->parent);
+ const struct tegra_mc_soc *soc = mc->soc;
+ struct icc_node *node;
+ int err;
+
+ emc->provider.dev = emc->dev;
+ emc->provider.set = tegra_emc_icc_set_bw;
+ emc->provider.data = &emc->provider;
+ emc->provider.aggregate = soc->icc_ops->aggregate;
+ emc->provider.xlate = tegra_emc_of_icc_xlate;
+ emc->provider.get_bw = tegra_emc_icc_get_init_bw;
+
+ icc_provider_init(&emc->provider);
+
+ /* create External Memory Controller node */
+ node = icc_node_create(TEGRA_ICC_EMC);
+ if (IS_ERR(node)) {
+ err = PTR_ERR(node);
+ goto err_msg;
+ }
+
+ node->name = "External Memory Controller";
+ icc_node_add(node, &emc->provider);
+
+ /* link External Memory Controller to External Memory (DRAM) */
+ err = icc_link_create(node, TEGRA_ICC_EMEM);
+ if (err)
+ goto remove_nodes;
+
+ /* create External Memory node */
+ node = icc_node_create(TEGRA_ICC_EMEM);
+ if (IS_ERR(node)) {
+ err = PTR_ERR(node);
+ goto remove_nodes;
+ }
+
+ node->name = "External Memory (DRAM)";
+ icc_node_add(node, &emc->provider);
+
+ err = icc_provider_register(&emc->provider);
+ if (err)
+ goto remove_nodes;
+
+ return 0;
+
+remove_nodes:
+ icc_nodes_remove(&emc->provider);
+err_msg:
+ dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
+
+ return err;
+}
+
static int tegra186_emc_probe(struct platform_device *pdev)
{
+ struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent);
struct mrq_emc_dvfs_latency_response response;
struct tegra_bpmp_message msg;
struct tegra186_emc *emc;
@@ -236,6 +339,32 @@ static int tegra186_emc_probe(struct platform_device *pdev)
debugfs_create_file("max_rate", S_IRUGO | S_IWUSR, emc->debugfs.root,
emc, &tegra186_emc_debug_max_rate_fops);
+ if (mc && mc->soc->icc_ops) {
+ if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_BWMGR_INT)) {
+ mc->bwmgr_mrq_supported = true;
+
+ /*
+ * MC driver probe can't get BPMP reference as it gets probed
+ * earlier than BPMP. So, save the BPMP ref got from the EMC
+ * DT node in the mc->bpmp and use it in MC's icc_set hook.
+ */
+ mc->bpmp = emc->bpmp;
+ barrier();
+ }
+
+ /*
+ * Initialize the ICC even if BPMP-FW doesn't support 'MRQ_BWMGR_INT'.
+ * Use the flag 'mc->bwmgr_mrq_supported' within MC driver and return
+ * EINVAL instead of passing the request to BPMP-FW later when the BW
+ * request is made by client with 'icc_set_bw()' call.
+ */
+ err = tegra_emc_interconnect_init(emc);
+ if (err) {
+ mc->bpmp = NULL;
+ goto put_bpmp;
+ }
+ }
+
return 0;
put_bpmp:
@@ -245,9 +374,12 @@ put_bpmp:
static int tegra186_emc_remove(struct platform_device *pdev)
{
+ struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent);
struct tegra186_emc *emc = platform_get_drvdata(pdev);
debugfs_remove_recursive(emc->debugfs.root);
+
+ mc->bpmp = NULL;
tegra_bpmp_put(emc->bpmp);
return 0;
@@ -272,6 +404,7 @@ static struct platform_driver tegra186_emc_driver = {
.name = "tegra186-emc",
.of_match_table = tegra186_emc_of_match,
.suppress_bind_attrs = true,
+ .sync_state = icc_sync_state,
},
.probe = tegra186_emc_probe,
.remove = tegra186_emc_remove,
diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c
index 02dcc5748bba..8e873a7bc34f 100644
--- a/drivers/memory/tegra/tegra234.c
+++ b/drivers/memory/tegra/tegra234.c
@@ -1,18 +1,47 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (C) 2021-2022, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (C) 2022-2023, NVIDIA CORPORATION. All rights reserved.
*/
#include <soc/tegra/mc.h>
#include <dt-bindings/memory/tegra234-mc.h>
+#include <linux/interconnect.h>
+#include <linux/tegra-icc.h>
+#include <soc/tegra/bpmp.h>
#include "mc.h"
static const struct tegra_mc_client tegra234_mc_clients[] = {
{
+ .id = TEGRA234_MEMORY_CLIENT_HDAR,
+ .name = "hdar",
+ .bpmp_id = TEGRA_ICC_BPMP_HDA,
+ .type = TEGRA_ICC_ISO_AUDIO,
+ .sid = TEGRA234_SID_HDA,
+ .regs = {
+ .sid = {
+ .override = 0xa8,
+ .security = 0xac,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_HDAW,
+ .name = "hdaw",
+ .bpmp_id = TEGRA_ICC_BPMP_HDA,
+ .type = TEGRA_ICC_ISO_AUDIO,
+ .sid = TEGRA234_SID_HDA,
+ .regs = {
+ .sid = {
+ .override = 0x1a8,
+ .security = 0x1ac,
+ },
+ },
+ }, {
.id = TEGRA234_MEMORY_CLIENT_MGBEARD,
.name = "mgbeard",
+ .bpmp_id = TEGRA_ICC_BPMP_EQOS,
+ .type = TEGRA_ICC_NISO,
.sid = TEGRA234_SID_MGBE,
.regs = {
.sid = {
@@ -23,6 +52,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBEBRD,
.name = "mgbebrd",
+ .bpmp_id = TEGRA_ICC_BPMP_EQOS,
+ .type = TEGRA_ICC_NISO,
.sid = TEGRA234_SID_MGBE_VF1,
.regs = {
.sid = {
@@ -33,6 +64,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBECRD,
.name = "mgbecrd",
+ .bpmp_id = TEGRA_ICC_BPMP_EQOS,
+ .type = TEGRA_ICC_NISO,
.sid = TEGRA234_SID_MGBE_VF2,
.regs = {
.sid = {
@@ -43,6 +76,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBEDRD,
.name = "mgbedrd",
+ .bpmp_id = TEGRA_ICC_BPMP_EQOS,
+ .type = TEGRA_ICC_NISO,
.sid = TEGRA234_SID_MGBE_VF3,
.regs = {
.sid = {
@@ -52,6 +87,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
},
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBEAWR,
+ .bpmp_id = TEGRA_ICC_BPMP_EQOS,
+ .type = TEGRA_ICC_NISO,
.name = "mgbeawr",
.sid = TEGRA234_SID_MGBE,
.regs = {
@@ -63,6 +100,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBEBWR,
.name = "mgbebwr",
+ .bpmp_id = TEGRA_ICC_BPMP_EQOS,
+ .type = TEGRA_ICC_NISO,
.sid = TEGRA234_SID_MGBE_VF1,
.regs = {
.sid = {
@@ -73,6 +112,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBECWR,
.name = "mgbecwr",
+ .bpmp_id = TEGRA_ICC_BPMP_EQOS,
+ .type = TEGRA_ICC_NISO,
.sid = TEGRA234_SID_MGBE_VF2,
.regs = {
.sid = {
@@ -83,6 +124,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
}, {
.id = TEGRA234_MEMORY_CLIENT_SDMMCRAB,
.name = "sdmmcrab",
+ .bpmp_id = TEGRA_ICC_BPMP_SDMMC_4,
+ .type = TEGRA_ICC_NISO,
.sid = TEGRA234_SID_SDMMC4,
.regs = {
.sid = {
@@ -93,6 +136,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
}, {
.id = TEGRA234_MEMORY_CLIENT_MGBEDWR,
.name = "mgbedwr",
+ .bpmp_id = TEGRA_ICC_BPMP_EQOS,
+ .type = TEGRA_ICC_NISO,
.sid = TEGRA234_SID_MGBE_VF3,
.regs = {
.sid = {
@@ -103,6 +148,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
}, {
.id = TEGRA234_MEMORY_CLIENT_SDMMCWAB,
.name = "sdmmcwab",
+ .bpmp_id = TEGRA_ICC_BPMP_SDMMC_4,
+ .type = TEGRA_ICC_NISO,
.sid = TEGRA234_SID_SDMMC4,
.regs = {
.sid = {
@@ -111,6 +158,90 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
},
},
}, {
+ .id = TEGRA234_MEMORY_CLIENT_VI2W,
+ .name = "vi2w",
+ .bpmp_id = TEGRA_ICC_BPMP_VI2,
+ .type = TEGRA_ICC_ISO_VI,
+ .sid = TEGRA234_SID_ISO_VI2,
+ .regs = {
+ .sid = {
+ .override = 0x380,
+ .security = 0x384,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_VI2FALR,
+ .name = "vi2falr",
+ .bpmp_id = TEGRA_ICC_BPMP_VI2FAL,
+ .type = TEGRA_ICC_ISO_VIFAL,
+ .sid = TEGRA234_SID_ISO_VI2FALC,
+ .regs = {
+ .sid = {
+ .override = 0x388,
+ .security = 0x38c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_VI2FALW,
+ .name = "vi2falw",
+ .bpmp_id = TEGRA_ICC_BPMP_VI2FAL,
+ .type = TEGRA_ICC_ISO_VIFAL,
+ .sid = TEGRA234_SID_ISO_VI2FALC,
+ .regs = {
+ .sid = {
+ .override = 0x3e0,
+ .security = 0x3e4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_APER,
+ .name = "aper",
+ .bpmp_id = TEGRA_ICC_BPMP_APE,
+ .type = TEGRA_ICC_ISO_AUDIO,
+ .sid = TEGRA234_SID_APE,
+ .regs = {
+ .sid = {
+ .override = 0x3d0,
+ .security = 0x3d4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_APEW,
+ .name = "apew",
+ .bpmp_id = TEGRA_ICC_BPMP_APE,
+ .type = TEGRA_ICC_ISO_AUDIO,
+ .sid = TEGRA234_SID_APE,
+ .regs = {
+ .sid = {
+ .override = 0x3d8,
+ .security = 0x3dc,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_NVDISPLAYR,
+ .name = "nvdisplayr",
+ .bpmp_id = TEGRA_ICC_BPMP_DISPLAY,
+ .type = TEGRA_ICC_ISO_DISPLAY,
+ .sid = TEGRA234_SID_ISO_NVDISPLAY,
+ .regs = {
+ .sid = {
+ .override = 0x490,
+ .security = 0x494,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_NVDISPLAYR1,
+ .name = "nvdisplayr1",
+ .bpmp_id = TEGRA_ICC_BPMP_DISPLAY,
+ .type = TEGRA_ICC_ISO_DISPLAY,
+ .sid = TEGRA234_SID_ISO_NVDISPLAY,
+ .regs = {
+ .sid = {
+ .override = 0x508,
+ .security = 0x50c,
+ },
+ },
+ }, {
.id = TEGRA234_MEMORY_CLIENT_BPMPR,
.name = "bpmpr",
.sid = TEGRA234_SID_BPMP,
@@ -153,6 +284,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
}, {
.id = TEGRA234_MEMORY_CLIENT_APEDMAR,
.name = "apedmar",
+ .bpmp_id = TEGRA_ICC_BPMP_APEDMA,
+ .type = TEGRA_ICC_ISO_AUDIO,
.sid = TEGRA234_SID_APE,
.regs = {
.sid = {
@@ -163,6 +296,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
}, {
.id = TEGRA234_MEMORY_CLIENT_APEDMAW,
.name = "apedmaw",
+ .bpmp_id = TEGRA_ICC_BPMP_APEDMA,
+ .type = TEGRA_ICC_ISO_AUDIO,
.sid = TEGRA234_SID_APE,
.regs = {
.sid = {
@@ -330,9 +465,466 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
.security = 0x37c,
},
},
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE0R,
+ .name = "pcie0r",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_0,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE0,
+ .regs = {
+ .sid = {
+ .override = 0x6c0,
+ .security = 0x6c4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE0W,
+ .name = "pcie0w",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_0,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE0,
+ .regs = {
+ .sid = {
+ .override = 0x6c8,
+ .security = 0x6cc,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE1R,
+ .name = "pcie1r",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_1,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE1,
+ .regs = {
+ .sid = {
+ .override = 0x6d0,
+ .security = 0x6d4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE1W,
+ .name = "pcie1w",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_1,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE1,
+ .regs = {
+ .sid = {
+ .override = 0x6d8,
+ .security = 0x6dc,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE2AR,
+ .name = "pcie2ar",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_2,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE2,
+ .regs = {
+ .sid = {
+ .override = 0x6e0,
+ .security = 0x6e4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE2AW,
+ .name = "pcie2aw",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_2,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE2,
+ .regs = {
+ .sid = {
+ .override = 0x6e8,
+ .security = 0x6ec,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE3R,
+ .name = "pcie3r",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_3,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE3,
+ .regs = {
+ .sid = {
+ .override = 0x6f0,
+ .security = 0x6f4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE3W,
+ .name = "pcie3w",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_3,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE3,
+ .regs = {
+ .sid = {
+ .override = 0x6f8,
+ .security = 0x6fc,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE4R,
+ .name = "pcie4r",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_4,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE4,
+ .regs = {
+ .sid = {
+ .override = 0x700,
+ .security = 0x704,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE4W,
+ .name = "pcie4w",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_4,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE4,
+ .regs = {
+ .sid = {
+ .override = 0x708,
+ .security = 0x70c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE5R,
+ .name = "pcie5r",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_5,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE5,
+ .regs = {
+ .sid = {
+ .override = 0x710,
+ .security = 0x714,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE5W,
+ .name = "pcie5w",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_5,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE5,
+ .regs = {
+ .sid = {
+ .override = 0x718,
+ .security = 0x71c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE5R1,
+ .name = "pcie5r1",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_5,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE5,
+ .regs = {
+ .sid = {
+ .override = 0x778,
+ .security = 0x77c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE6AR,
+ .name = "pcie6ar",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_6,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE6,
+ .regs = {
+ .sid = {
+ .override = 0x140,
+ .security = 0x144,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE6AW,
+ .name = "pcie6aw",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_6,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE6,
+ .regs = {
+ .sid = {
+ .override = 0x148,
+ .security = 0x14c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE6AR1,
+ .name = "pcie6ar1",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_6,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE6,
+ .regs = {
+ .sid = {
+ .override = 0x1e8,
+ .security = 0x1ec,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE7AR,
+ .name = "pcie7ar",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_7,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE7,
+ .regs = {
+ .sid = {
+ .override = 0x150,
+ .security = 0x154,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE7AW,
+ .name = "pcie7aw",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_7,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE7,
+ .regs = {
+ .sid = {
+ .override = 0x180,
+ .security = 0x184,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE7AR1,
+ .name = "pcie7ar1",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_7,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE7,
+ .regs = {
+ .sid = {
+ .override = 0x248,
+ .security = 0x24c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE8AR,
+ .name = "pcie8ar",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_8,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE8,
+ .regs = {
+ .sid = {
+ .override = 0x190,
+ .security = 0x194,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE8AW,
+ .name = "pcie8aw",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_8,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE8,
+ .regs = {
+ .sid = {
+ .override = 0x1d8,
+ .security = 0x1dc,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE9AR,
+ .name = "pcie9ar",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_9,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE9,
+ .regs = {
+ .sid = {
+ .override = 0x1e0,
+ .security = 0x1e4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE9AW,
+ .name = "pcie9aw",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_9,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE9,
+ .regs = {
+ .sid = {
+ .override = 0x1f0,
+ .security = 0x1f4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE10AR,
+ .name = "pcie10ar",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_10,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE10,
+ .regs = {
+ .sid = {
+ .override = 0x1f8,
+ .security = 0x1fc,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE10AW,
+ .name = "pcie10aw",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_10,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE10,
+ .regs = {
+ .sid = {
+ .override = 0x200,
+ .security = 0x204,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_PCIE10AR1,
+ .name = "pcie10ar1",
+ .bpmp_id = TEGRA_ICC_BPMP_PCIE_10,
+ .type = TEGRA_ICC_NISO,
+ .sid = TEGRA234_SID_PCIE10,
+ .regs = {
+ .sid = {
+ .override = 0x240,
+ .security = 0x244,
+ },
+ },
+ }, {
+ .id = TEGRA_ICC_MC_CPU_CLUSTER0,
+ .name = "sw_cluster0",
+ .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER0,
+ .type = TEGRA_ICC_NISO,
+ }, {
+ .id = TEGRA_ICC_MC_CPU_CLUSTER1,
+ .name = "sw_cluster1",
+ .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER1,
+ .type = TEGRA_ICC_NISO,
+ }, {
+ .id = TEGRA_ICC_MC_CPU_CLUSTER2,
+ .name = "sw_cluster2",
+ .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER2,
+ .type = TEGRA_ICC_NISO,
},
};
+/*
+ * tegra234_mc_icc_set() - Pass MC client info to the BPMP-FW
+ * @src: ICC node for Memory Controller's (MC) Client
+ * @dst: ICC node for Memory Controller (MC)
+ *
+ * Passing the current request info from the MC to the BPMP-FW where
+ * LA and PTSA registers are accessed and the final EMC freq is set
+ * based on client_id, type, latency and bandwidth.
+ * icc_set_bw() makes set_bw calls for both MC and EMC providers in
+ * sequence. Both the calls are protected by 'mutex_lock(&icc_lock)'.
+ * So, the data passed won't be updated by concurrent set calls from
+ * other clients.
+ */
+static int tegra234_mc_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+ struct tegra_mc *mc = icc_provider_to_tegra_mc(dst->provider);
+ struct mrq_bwmgr_int_request bwmgr_req = { 0 };
+ struct mrq_bwmgr_int_response bwmgr_resp = { 0 };
+ const struct tegra_mc_client *pclient = src->data;
+ struct tegra_bpmp_message msg;
+ int ret;
+
+ /*
+ * Same Src and Dst node will happen during boot from icc_node_add().
+ * This can be used to pre-initialize and set bandwidth for all clients
+ * before their drivers are loaded. We are skipping this case as for us,
+ * the pre-initialization already happened in Bootloader(MB2) and BPMP-FW.
+ */
+ if (src->id == dst->id)
+ return 0;
+
+ if (!mc->bwmgr_mrq_supported)
+ return -EINVAL;
+
+ if (!mc->bpmp) {
+ dev_err(mc->dev, "BPMP reference NULL\n");
+ return -ENOENT;
+ }
+
+ if (pclient->type == TEGRA_ICC_NISO)
+ bwmgr_req.bwmgr_calc_set_req.niso_bw = src->avg_bw;
+ else
+ bwmgr_req.bwmgr_calc_set_req.iso_bw = src->avg_bw;
+
+ bwmgr_req.bwmgr_calc_set_req.client_id = pclient->bpmp_id;
+
+ bwmgr_req.cmd = CMD_BWMGR_INT_CALC_AND_SET;
+ bwmgr_req.bwmgr_calc_set_req.mc_floor = src->peak_bw;
+ bwmgr_req.bwmgr_calc_set_req.floor_unit = BWMGR_INT_UNIT_KBPS;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.mrq = MRQ_BWMGR_INT;
+ msg.tx.data = &bwmgr_req;
+ msg.tx.size = sizeof(bwmgr_req);
+ msg.rx.data = &bwmgr_resp;
+ msg.rx.size = sizeof(bwmgr_resp);
+
+ ret = tegra_bpmp_transfer(mc->bpmp, &msg);
+ if (ret < 0) {
+ dev_err(mc->dev, "BPMP transfer failed: %d\n", ret);
+ goto error;
+ }
+ if (msg.rx.ret < 0) {
+ pr_err("failed to set bandwidth for %u: %d\n",
+ bwmgr_req.bwmgr_calc_set_req.client_id, msg.rx.ret);
+ ret = -EINVAL;
+ }
+
+error:
+ return ret;
+}
+
+static int tegra234_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
+ u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
+{
+ struct icc_provider *p = node->provider;
+ struct tegra_mc *mc = icc_provider_to_tegra_mc(p);
+
+ if (!mc->bwmgr_mrq_supported)
+ return -EINVAL;
+
+ if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 ||
+ node->id == TEGRA_ICC_MC_CPU_CLUSTER1 ||
+ node->id == TEGRA_ICC_MC_CPU_CLUSTER2) {
+ if (mc)
+ peak_bw = peak_bw * mc->num_channels;
+ }
+
+ *agg_avg += avg_bw;
+ *agg_peak = max(*agg_peak, peak_bw);
+
+ return 0;
+}
+
+static struct icc_node*
+tegra234_mc_of_icc_xlate(struct of_phandle_args *spec, void *data)
+{
+ struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
+ unsigned int cl_id = spec->args[0];
+ struct icc_node *node;
+
+ list_for_each_entry(node, &mc->provider.nodes, node_list) {
+ if (node->id != cl_id)
+ continue;
+
+ return node;
+ }
+
+ /*
+ * If a client driver calls devm_of_icc_get() before the MC driver
+ * is probed, then return EPROBE_DEFER to the client driver.
+ */
+ return ERR_PTR(-EPROBE_DEFER);
+}
+
+static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
+{
+ *avg = 0;
+ *peak = 0;
+
+ return 0;
+}
+
+static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = {
+ .xlate = tegra234_mc_of_icc_xlate,
+ .aggregate = tegra234_mc_icc_aggregate,
+ .get_bw = tegra234_mc_icc_get_init_bw,
+ .set = tegra234_mc_icc_set,
+};
+
const struct tegra_mc_soc tegra234_mc_soc = {
.num_clients = ARRAY_SIZE(tegra234_mc_clients),
.clients = tegra234_mc_clients,
@@ -345,6 +937,7 @@ const struct tegra_mc_soc tegra234_mc_soc = {
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
.has_addr_hi_reg = true,
.ops = &tegra186_mc_ops,
+ .icc_ops = &tegra234_mc_icc_ops,
.ch_intmask = 0x0000ff00,
.global_intstatus_channel_shift = 8,
/*
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index a3d0288fd0e2..88a6e506a942 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -2,7 +2,7 @@
menuconfig FUSION
bool "Fusion MPT device support"
- depends on PCI
+ depends on PCI && HAS_IOPORT
help
Say Y here to get to see options for Fusion Message
Passing Technology (MPT) drivers.
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 4f0afce8428d..4bf669c55649 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -712,7 +712,7 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass, char *func_name)
MptDriverClass[cb_idx] = dclass;
MptEvHandlers[cb_idx] = NULL;
last_drv_idx = cb_idx;
- strlcpy(MptCallbacksName[cb_idx], func_name,
+ strscpy(MptCallbacksName[cb_idx], func_name,
MPT_MAX_CALLBACKNAME_LEN+1);
break;
}
@@ -7666,7 +7666,7 @@ mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)
break;
}
if (ds)
- strlcpy(evStr, ds, EVENT_DESCR_STR_SZ);
+ strscpy(evStr, ds, EVENT_DESCR_STR_SZ);
devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 1decd09a08d8..dd028df4b283 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -2408,7 +2408,7 @@ mptctl_hp_hostinfo(MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
if (mpt_config(ioc, &cfg) == 0) {
ManufacturingPage0_t *pdata = (ManufacturingPage0_t *) pbuf;
if (strlen(pdata->BoardTracerNumber) > 1) {
- strlcpy(karg.serial_number,
+ strscpy(karg.serial_number,
pdata->BoardTracerNumber, 24);
}
}
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index 4d9b61b92754..300caa067335 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -597,7 +597,7 @@ static struct i2c_driver pm800_driver = {
.name = "88PM800",
.pm = pm_sleep_ptr(&pm80x_pm_ops),
},
- .probe_new = pm800_probe,
+ .probe = pm800_probe,
.remove = pm800_remove,
.id_table = pm80x_id_table,
};
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 352f13cb1481..68417c3c4f5a 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -253,7 +253,7 @@ static struct i2c_driver pm805_driver = {
.name = "88PM805",
.pm = pm_sleep_ptr(&pm80x_pm_ops),
},
- .probe_new = pm805_probe,
+ .probe = pm805_probe,
.remove = pm805_remove,
.id_table = pm80x_id_table,
};
diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c
index ac4f08565f29..bbc1a87f0c8f 100644
--- a/drivers/mfd/88pm80x.c
+++ b/drivers/mfd/88pm80x.c
@@ -74,7 +74,6 @@ int pm80x_init(struct i2c_client *client)
chip->irq = client->irq;
chip->dev = &client->dev;
- dev_set_drvdata(chip->dev, chip);
i2c_set_clientdata(chip->client, chip);
ret = regmap_read(chip->regmap, PM80X_CHIP_ID, &val);
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index aabac37c3502..151bf03e772d 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -1166,7 +1166,6 @@ static int pm860x_probe(struct i2c_client *client)
chip->client = client;
i2c_set_clientdata(client, chip);
chip->dev = &client->dev;
- dev_set_drvdata(chip->dev, chip);
/*
* Both client and companion client shares same platform driver.
@@ -1251,7 +1250,7 @@ static struct i2c_driver pm860x_driver = {
.pm = pm_sleep_ptr(&pm860x_pm_ops),
.of_match_table = pm860x_dt_ids,
},
- .probe_new = pm860x_probe,
+ .probe = pm860x_probe,
.remove = pm860x_remove,
.id_table = pm860x_id_table,
};
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index f89f455c130a..6f5b259a6d6a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -266,8 +266,8 @@ config MFD_MADERA_SPI
Support for the Cirrus Logic Madera platform audio SoC
core functionality controlled via SPI.
-config MFD_MAX597X
- tristate "Maxim 597x power switch and monitor"
+config MFD_MAX5970
+ tristate "Maxim 5970/5978 power switch and monitor"
depends on (I2C && OF)
select MFD_SIMPLE_MFD_I2C
help
@@ -784,6 +784,19 @@ config MFD_MAX14577
additional drivers must be enabled in order to use the functionality
of the device.
+config MFD_MAX77541
+ tristate "Analog Devices MAX77541/77540 PMIC Support"
+ depends on I2C=y
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ help
+ Say yes here to add support for Analog Devices MAX77541 and
+ MAX77540 Power Management ICs. This driver provides
+ common support for accessing the device; additional drivers
+ must be enabled in order to use the functionality of the device.
+ There are regulators and adc.
+
config MFD_MAX77620
bool "Maxim Semiconductor MAX77620 and MAX20024 PMIC Support"
depends on I2C=y
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 39c461536181..f3d1f1dc73b5 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -154,6 +154,7 @@ obj-$(CONFIG_MFD_DA9063) += da9063.o
obj-$(CONFIG_MFD_DA9150) += da9150-core.o
obj-$(CONFIG_MFD_MAX14577) += max14577.o
+obj-$(CONFIG_MFD_MAX77541) += max77541.o
obj-$(CONFIG_MFD_MAX77620) += max77620.o
obj-$(CONFIG_MFD_MAX77650) += max77650.o
obj-$(CONFIG_MFD_MAX77686) += max77686.o
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c
index f253da5b246b..2fee62f1016c 100644
--- a/drivers/mfd/aat2870-core.c
+++ b/drivers/mfd/aat2870-core.c
@@ -345,8 +345,6 @@ static int aat2870_i2c_probe(struct i2c_client *client)
return -ENOMEM;
aat2870->dev = &client->dev;
- dev_set_drvdata(aat2870->dev, aat2870);
-
aat2870->client = client;
i2c_set_clientdata(client, aat2870);
@@ -451,7 +449,7 @@ static struct i2c_driver aat2870_i2c_driver = {
.pm = pm_sleep_ptr(&aat2870_pm_ops),
.suppress_bind_attrs = true,
},
- .probe_new = aat2870_i2c_probe,
+ .probe = aat2870_i2c_probe,
.id_table = aat2870_i2c_id_table,
};
diff --git a/drivers/mfd/acer-ec-a500.c b/drivers/mfd/acer-ec-a500.c
index 7fd8b9988075..feb757e90dc3 100644
--- a/drivers/mfd/acer-ec-a500.c
+++ b/drivers/mfd/acer-ec-a500.c
@@ -190,7 +190,7 @@ static struct i2c_driver a500_ec_driver = {
.name = "acer-a500-embedded-controller",
.of_match_table = a500_ec_match,
},
- .probe_new = a500_ec_probe,
+ .probe = a500_ec_probe,
.remove = a500_ec_remove,
};
module_i2c_driver(a500_ec_driver);
diff --git a/drivers/mfd/act8945a.c b/drivers/mfd/act8945a.c
index bcf0fda15f0c..2406fcdff5f9 100644
--- a/drivers/mfd/act8945a.c
+++ b/drivers/mfd/act8945a.c
@@ -70,7 +70,7 @@ static struct i2c_driver act8945a_i2c_driver = {
.name = "act8945a",
.of_match_table = of_match_ptr(act8945a_of_match),
},
- .probe_new = act8945a_i2c_probe,
+ .probe = act8945a_i2c_probe,
.id_table = act8945a_i2c_id,
};
diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c
index cb168efdbafe..bd6f4965ebc8 100644
--- a/drivers/mfd/adp5520.c
+++ b/drivers/mfd/adp5520.c
@@ -340,7 +340,7 @@ static struct i2c_driver adp5520_driver = {
.pm = pm_sleep_ptr(&adp5520_pm),
.suppress_bind_attrs = true,
},
- .probe_new = adp5520_probe,
+ .probe = adp5520_probe,
.id_table = adp5520_id,
};
builtin_i2c_driver(adp5520_driver);
diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
index 43e393c8608d..9b7183ffc928 100644
--- a/drivers/mfd/arizona-i2c.c
+++ b/drivers/mfd/arizona-i2c.c
@@ -121,7 +121,7 @@ static struct i2c_driver arizona_i2c_driver = {
.pm = pm_ptr(&arizona_pm_ops),
.of_match_table = of_match_ptr(arizona_i2c_of_match),
},
- .probe_new = arizona_i2c_probe,
+ .probe = arizona_i2c_probe,
.remove = arizona_i2c_remove,
.id_table = arizona_i2c_id,
};
diff --git a/drivers/mfd/as3711.c b/drivers/mfd/as3711.c
index 3facfdd28e81..c7e85ff38013 100644
--- a/drivers/mfd/as3711.c
+++ b/drivers/mfd/as3711.c
@@ -201,7 +201,7 @@ static struct i2c_driver as3711_i2c_driver = {
.name = "as3711",
.of_match_table = of_match_ptr(as3711_of_match),
},
- .probe_new = as3711_i2c_probe,
+ .probe = as3711_i2c_probe,
.id_table = as3711_i2c_id,
};
diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c
index b6dda0eb8645..a2bf68afc131 100644
--- a/drivers/mfd/as3722.c
+++ b/drivers/mfd/as3722.c
@@ -445,7 +445,7 @@ static struct i2c_driver as3722_i2c_driver = {
.of_match_table = as3722_of_match,
.pm = &as3722_pm_ops,
},
- .probe_new = as3722_i2c_probe,
+ .probe = as3722_i2c_probe,
.id_table = as3722_i2c_id,
};
diff --git a/drivers/mfd/atc260x-i2c.c b/drivers/mfd/atc260x-i2c.c
index 8e1491167160..fb53b0432a31 100644
--- a/drivers/mfd/atc260x-i2c.c
+++ b/drivers/mfd/atc260x-i2c.c
@@ -53,7 +53,7 @@ static struct i2c_driver atc260x_i2c_driver = {
.name = "atc260x",
.of_match_table = atc260x_i2c_of_match,
},
- .probe_new = atc260x_i2c_probe,
+ .probe = atc260x_i2c_probe,
};
module_i2c_driver(atc260x_i2c_driver);
diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c
index a49e5e217554..68d3560cfe4a 100644
--- a/drivers/mfd/axp20x-i2c.c
+++ b/drivers/mfd/axp20x-i2c.c
@@ -59,6 +59,7 @@ static void axp20x_i2c_remove(struct i2c_client *i2c)
#ifdef CONFIG_OF
static const struct of_device_id axp20x_i2c_of_match[] = {
{ .compatible = "x-powers,axp152", .data = (void *)AXP152_ID },
+ { .compatible = "x-powers,axp192", .data = (void *)AXP192_ID },
{ .compatible = "x-powers,axp202", .data = (void *)AXP202_ID },
{ .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
{ .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
@@ -74,6 +75,7 @@ MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
static const struct i2c_device_id axp20x_i2c_id[] = {
{ "axp152", 0 },
+ { "axp192", 0 },
{ "axp202", 0 },
{ "axp209", 0 },
{ "axp221", 0 },
@@ -103,7 +105,7 @@ static struct i2c_driver axp20x_i2c_driver = {
.of_match_table = of_match_ptr(axp20x_i2c_of_match),
.acpi_match_table = ACPI_PTR(axp20x_i2c_acpi_match),
},
- .probe_new = axp20x_i2c_probe,
+ .probe = axp20x_i2c_probe,
.remove = axp20x_i2c_remove,
.id_table = axp20x_i2c_id,
};
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 07a846ecbf18..c03bc5cda080 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -34,6 +34,7 @@
static const char * const axp20x_model_names[] = {
"AXP152",
+ "AXP192",
"AXP202",
"AXP209",
"AXP221",
@@ -94,6 +95,35 @@ static const struct regmap_access_table axp20x_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges),
};
+static const struct regmap_range axp192_writeable_ranges[] = {
+ regmap_reg_range(AXP192_DATACACHE(0), AXP192_DATACACHE(5)),
+ regmap_reg_range(AXP192_PWR_OUT_CTRL, AXP192_IRQ5_STATE),
+ regmap_reg_range(AXP20X_DCDC_MODE, AXP192_N_RSTO_CTRL),
+ regmap_reg_range(AXP20X_CC_CTRL, AXP20X_CC_CTRL),
+};
+
+static const struct regmap_range axp192_volatile_ranges[] = {
+ regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP192_USB_OTG_STATUS),
+ regmap_reg_range(AXP192_IRQ1_STATE, AXP192_IRQ4_STATE),
+ regmap_reg_range(AXP192_IRQ5_STATE, AXP192_IRQ5_STATE),
+ regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
+ regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
+ regmap_reg_range(AXP192_GPIO2_0_STATE, AXP192_GPIO2_0_STATE),
+ regmap_reg_range(AXP192_GPIO4_3_STATE, AXP192_GPIO4_3_STATE),
+ regmap_reg_range(AXP192_N_RSTO_CTRL, AXP192_N_RSTO_CTRL),
+ regmap_reg_range(AXP20X_CHRG_CC_31_24, AXP20X_CC_CTRL),
+};
+
+static const struct regmap_access_table axp192_writeable_table = {
+ .yes_ranges = axp192_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp192_writeable_ranges),
+};
+
+static const struct regmap_access_table axp192_volatile_table = {
+ .yes_ranges = axp192_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp192_volatile_ranges),
+};
+
/* AXP22x ranges are shared with the AXP809, as they cover the same range */
static const struct regmap_range axp22x_writeable_ranges[] = {
regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
@@ -220,6 +250,19 @@ static const struct resource axp152_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
+static const struct resource axp192_ac_power_supply_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"),
+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"),
+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_OVER_V, "ACIN_OVER_V"),
+};
+
+static const struct resource axp192_usb_power_supply_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_VALID, "VBUS_VALID"),
+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"),
+};
+
static const struct resource axp20x_ac_power_supply_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"),
@@ -302,6 +345,15 @@ static const struct regmap_config axp152_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
+static const struct regmap_config axp192_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .wr_table = &axp192_writeable_table,
+ .volatile_table = &axp192_volatile_table,
+ .max_register = AXP20X_CC_CTRL,
+ .cache_type = REGCACHE_RBTREE,
+};
+
static const struct regmap_config axp20x_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -379,6 +431,42 @@ static const struct regmap_irq axp152_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT, 2, 0),
};
+static const struct regmap_irq axp192_regmap_irqs[] = {
+ INIT_REGMAP_IRQ(AXP192, ACIN_OVER_V, 0, 7),
+ INIT_REGMAP_IRQ(AXP192, ACIN_PLUGIN, 0, 6),
+ INIT_REGMAP_IRQ(AXP192, ACIN_REMOVAL, 0, 5),
+ INIT_REGMAP_IRQ(AXP192, VBUS_OVER_V, 0, 4),
+ INIT_REGMAP_IRQ(AXP192, VBUS_PLUGIN, 0, 3),
+ INIT_REGMAP_IRQ(AXP192, VBUS_REMOVAL, 0, 2),
+ INIT_REGMAP_IRQ(AXP192, VBUS_V_LOW, 0, 1),
+ INIT_REGMAP_IRQ(AXP192, BATT_PLUGIN, 1, 7),
+ INIT_REGMAP_IRQ(AXP192, BATT_REMOVAL, 1, 6),
+ INIT_REGMAP_IRQ(AXP192, BATT_ENT_ACT_MODE, 1, 5),
+ INIT_REGMAP_IRQ(AXP192, BATT_EXIT_ACT_MODE, 1, 4),
+ INIT_REGMAP_IRQ(AXP192, CHARG, 1, 3),
+ INIT_REGMAP_IRQ(AXP192, CHARG_DONE, 1, 2),
+ INIT_REGMAP_IRQ(AXP192, BATT_TEMP_HIGH, 1, 1),
+ INIT_REGMAP_IRQ(AXP192, BATT_TEMP_LOW, 1, 0),
+ INIT_REGMAP_IRQ(AXP192, DIE_TEMP_HIGH, 2, 7),
+ INIT_REGMAP_IRQ(AXP192, CHARG_I_LOW, 2, 6),
+ INIT_REGMAP_IRQ(AXP192, DCDC1_V_LONG, 2, 5),
+ INIT_REGMAP_IRQ(AXP192, DCDC2_V_LONG, 2, 4),
+ INIT_REGMAP_IRQ(AXP192, DCDC3_V_LONG, 2, 3),
+ INIT_REGMAP_IRQ(AXP192, PEK_SHORT, 2, 1),
+ INIT_REGMAP_IRQ(AXP192, PEK_LONG, 2, 0),
+ INIT_REGMAP_IRQ(AXP192, N_OE_PWR_ON, 3, 7),
+ INIT_REGMAP_IRQ(AXP192, N_OE_PWR_OFF, 3, 6),
+ INIT_REGMAP_IRQ(AXP192, VBUS_VALID, 3, 5),
+ INIT_REGMAP_IRQ(AXP192, VBUS_NOT_VALID, 3, 4),
+ INIT_REGMAP_IRQ(AXP192, VBUS_SESS_VALID, 3, 3),
+ INIT_REGMAP_IRQ(AXP192, VBUS_SESS_END, 3, 2),
+ INIT_REGMAP_IRQ(AXP192, LOW_PWR_LVL, 3, 0),
+ INIT_REGMAP_IRQ(AXP192, TIMER, 4, 7),
+ INIT_REGMAP_IRQ(AXP192, GPIO2_INPUT, 4, 2),
+ INIT_REGMAP_IRQ(AXP192, GPIO1_INPUT, 4, 1),
+ INIT_REGMAP_IRQ(AXP192, GPIO0_INPUT, 4, 0),
+};
+
static const struct regmap_irq axp20x_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V, 0, 7),
INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN, 0, 6),
@@ -615,6 +703,32 @@ static const struct regmap_irq_chip axp152_regmap_irq_chip = {
.num_regs = 3,
};
+static unsigned int axp192_get_irq_reg(struct regmap_irq_chip_data *data,
+ unsigned int base, int index)
+{
+ /* linear mapping for IRQ1 to IRQ4 */
+ if (index < 4)
+ return base + index;
+
+ /* handle IRQ5 separately */
+ if (base == AXP192_IRQ1_EN)
+ return AXP192_IRQ5_EN;
+
+ return AXP192_IRQ5_STATE;
+}
+
+static const struct regmap_irq_chip axp192_regmap_irq_chip = {
+ .name = "axp192_irq_chip",
+ .status_base = AXP192_IRQ1_STATE,
+ .ack_base = AXP192_IRQ1_STATE,
+ .unmask_base = AXP192_IRQ1_EN,
+ .init_ack_masked = true,
+ .irqs = axp192_regmap_irqs,
+ .num_irqs = ARRAY_SIZE(axp192_regmap_irqs),
+ .num_regs = 5,
+ .get_irq_reg = axp192_get_irq_reg,
+};
+
static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
.name = "axp20x_irq_chip",
.status_base = AXP20X_IRQ1_STATE,
@@ -705,6 +819,27 @@ static const struct regmap_irq_chip axp15060_regmap_irq_chip = {
.num_regs = 2,
};
+static const struct mfd_cell axp192_cells[] = {
+ {
+ .name = "axp192-adc",
+ .of_compatible = "x-powers,axp192-adc",
+ }, {
+ .name = "axp20x-battery-power-supply",
+ .of_compatible = "x-powers,axp192-battery-power-supply",
+ }, {
+ .name = "axp20x-ac-power-supply",
+ .of_compatible = "x-powers,axp202-ac-power-supply",
+ .num_resources = ARRAY_SIZE(axp192_ac_power_supply_resources),
+ .resources = axp192_ac_power_supply_resources,
+ }, {
+ .name = "axp20x-usb-power-supply",
+ .of_compatible = "x-powers,axp192-usb-power-supply",
+ .num_resources = ARRAY_SIZE(axp192_usb_power_supply_resources),
+ .resources = axp192_usb_power_supply_resources,
+ },
+ { .name = "axp20x-regulator" },
+};
+
static const struct mfd_cell axp20x_cells[] = {
{
.name = "axp20x-gpio",
@@ -1022,6 +1157,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_cfg = &axp152_regmap_config;
axp20x->regmap_irq_chip = &axp152_regmap_irq_chip;
break;
+ case AXP192_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp192_cells);
+ axp20x->cells = axp192_cells;
+ axp20x->regmap_cfg = &axp192_regmap_config;
+ axp20x->regmap_irq_chip = &axp192_regmap_irq_chip;
+ break;
case AXP202_ID:
case AXP209_ID:
axp20x->nr_cells = ARRAY_SIZE(axp20x_cells);
diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
index 251d515478d5..9f39b46b87f4 100644
--- a/drivers/mfd/bcm590xx.c
+++ b/drivers/mfd/bcm590xx.c
@@ -108,7 +108,7 @@ static struct i2c_driver bcm590xx_i2c_driver = {
.name = "bcm590xx",
.of_match_table = bcm590xx_of_match,
},
- .probe_new = bcm590xx_i2c_probe,
+ .probe = bcm590xx_i2c_probe,
.id_table = bcm590xx_i2c_id,
};
module_i2c_driver(bcm590xx_i2c_driver);
diff --git a/drivers/mfd/bd9571mwv.c b/drivers/mfd/bd9571mwv.c
index 60dc858c8117..819d09e4d100 100644
--- a/drivers/mfd/bd9571mwv.c
+++ b/drivers/mfd/bd9571mwv.c
@@ -278,7 +278,7 @@ static struct i2c_driver bd9571mwv_driver = {
.name = "bd9571mwv",
.of_match_table = bd9571mwv_of_match_table,
},
- .probe_new = bd9571mwv_probe,
+ .probe = bd9571mwv_probe,
.id_table = bd9571mwv_id_table,
};
module_i2c_driver(bd9571mwv_driver);
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index 6570b33a5a77..e86b39de3303 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -543,7 +543,7 @@ static struct i2c_driver da903x_driver = {
.driver = {
.name = "da903x",
},
- .probe_new = da903x_probe,
+ .probe = da903x_probe,
.remove = da903x_remove,
.id_table = da903x_id_table,
};
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
index 03db7a2ccf7a..541e2d47677e 100644
--- a/drivers/mfd/da9052-i2c.c
+++ b/drivers/mfd/da9052-i2c.c
@@ -176,7 +176,7 @@ static void da9052_i2c_remove(struct i2c_client *client)
}
static struct i2c_driver da9052_i2c_driver = {
- .probe_new = da9052_i2c_probe,
+ .probe = da9052_i2c_probe,
.remove = da9052_i2c_remove,
.id_table = da9052_i2c_id,
.driver = {
diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c
index 537fd5de3e6d..bbaf4f07f274 100644
--- a/drivers/mfd/da9055-i2c.c
+++ b/drivers/mfd/da9055-i2c.c
@@ -66,7 +66,7 @@ static const struct of_device_id da9055_of_match[] = {
};
static struct i2c_driver da9055_i2c_driver = {
- .probe_new = da9055_i2c_probe,
+ .probe = da9055_i2c_probe,
.remove = da9055_i2c_remove,
.id_table = da9055_i2c_id,
.driver = {
diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c
index d073d5f106ec..48f58b6f5629 100644
--- a/drivers/mfd/da9062-core.c
+++ b/drivers/mfd/da9062-core.c
@@ -726,7 +726,7 @@ static struct i2c_driver da9062_i2c_driver = {
.name = "da9062",
.of_match_table = da9062_dt_ids,
},
- .probe_new = da9062_i2c_probe,
+ .probe = da9062_i2c_probe,
.remove = da9062_i2c_remove,
.id_table = da9062_i2c_id,
};
diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c
index 03f8f95a1d62..d715cf9a9e68 100644
--- a/drivers/mfd/da9063-i2c.c
+++ b/drivers/mfd/da9063-i2c.c
@@ -469,7 +469,7 @@ static struct i2c_driver da9063_i2c_driver = {
.name = "da9063",
.of_match_table = da9063_dt_ids,
},
- .probe_new = da9063_i2c_probe,
+ .probe = da9063_i2c_probe,
.id_table = da9063_i2c_id,
};
diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c
index d2c954103b2f..94d621e20635 100644
--- a/drivers/mfd/da9150-core.c
+++ b/drivers/mfd/da9150-core.c
@@ -510,7 +510,7 @@ static struct i2c_driver da9150_driver = {
.name = "da9150",
.of_match_table = da9150_of_match,
},
- .probe_new = da9150_probe,
+ .probe = da9150_probe,
.remove = da9150_remove,
.shutdown = da9150_shutdown,
.id_table = da9150_i2c_id,
diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
index c3149729cec2..c7510434380a 100644
--- a/drivers/mfd/dln2.c
+++ b/drivers/mfd/dln2.c
@@ -14,7 +14,6 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/usb.h>
-#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
diff --git a/drivers/mfd/ene-kb3930.c b/drivers/mfd/ene-kb3930.c
index 3eff98e26bea..fa0ad2f14a39 100644
--- a/drivers/mfd/ene-kb3930.c
+++ b/drivers/mfd/ene-kb3930.c
@@ -196,7 +196,7 @@ static const struct of_device_id kb3930_dt_ids[] = {
MODULE_DEVICE_TABLE(of, kb3930_dt_ids);
static struct i2c_driver kb3930_driver = {
- .probe_new = kb3930_probe,
+ .probe = kb3930_probe,
.remove = kb3930_remove,
.driver = {
.name = "ene-kb3930",
diff --git a/drivers/mfd/gateworks-gsc.c b/drivers/mfd/gateworks-gsc.c
index c954ed265de8..b02bfdc871e9 100644
--- a/drivers/mfd/gateworks-gsc.c
+++ b/drivers/mfd/gateworks-gsc.c
@@ -264,7 +264,7 @@ static struct i2c_driver gsc_driver = {
.name = "gateworks-gsc",
.of_match_table = gsc_of_match,
},
- .probe_new = gsc_probe,
+ .probe = gsc_probe,
.remove = gsc_remove,
};
module_i2c_driver(gsc_driver);
diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c
index a143c8dca2d9..212818aef93e 100644
--- a/drivers/mfd/intel-lpss-acpi.c
+++ b/drivers/mfd/intel-lpss-acpi.c
@@ -183,6 +183,9 @@ static int intel_lpss_acpi_probe(struct platform_device *pdev)
return -ENOMEM;
info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!info->mem)
+ return -ENODEV;
+
info->irq = platform_get_irq(pdev, 0);
ret = intel_lpss_probe(&pdev->dev, info);
diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c
index cfbee2cfba6b..9591b354072a 100644
--- a/drivers/mfd/intel-lpss.c
+++ b/drivers/mfd/intel-lpss.c
@@ -460,6 +460,7 @@ void intel_lpss_remove(struct device *dev)
}
EXPORT_SYMBOL_GPL(intel_lpss_remove);
+#ifdef CONFIG_PM
static int resume_lpss_device(struct device *dev, void *data)
{
if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND))
@@ -514,6 +515,7 @@ int intel_lpss_resume(struct device *dev)
return 0;
}
EXPORT_SYMBOL_GPL(intel_lpss_resume);
+#endif
static int __init intel_lpss_init(void)
{
diff --git a/drivers/mfd/intel-m10-bmc-core.c b/drivers/mfd/intel-m10-bmc-core.c
index dac9cf7bcb4a..8ad5b3821584 100644
--- a/drivers/mfd/intel-m10-bmc-core.c
+++ b/drivers/mfd/intel-m10-bmc-core.c
@@ -12,6 +12,91 @@
#include <linux/mfd/intel-m10-bmc.h>
#include <linux/module.h>
+void m10bmc_fw_state_set(struct intel_m10bmc *m10bmc, enum m10bmc_fw_state new_state)
+{
+ /* bmcfw_state is only needed if handshake_sys_reg_nranges > 0 */
+ if (!m10bmc->info->handshake_sys_reg_nranges)
+ return;
+
+ down_write(&m10bmc->bmcfw_lock);
+ m10bmc->bmcfw_state = new_state;
+ up_write(&m10bmc->bmcfw_lock);
+}
+EXPORT_SYMBOL_NS_GPL(m10bmc_fw_state_set, INTEL_M10_BMC_CORE);
+
+/*
+ * For some Intel FPGA devices, the BMC firmware is not available to service
+ * handshake registers during a secure update.
+ */
+static bool m10bmc_reg_always_available(struct intel_m10bmc *m10bmc, unsigned int offset)
+{
+ if (!m10bmc->info->handshake_sys_reg_nranges)
+ return true;
+
+ return !regmap_reg_in_ranges(offset, m10bmc->info->handshake_sys_reg_ranges,
+ m10bmc->info->handshake_sys_reg_nranges);
+}
+
+/*
+ * m10bmc_handshake_reg_unavailable - Checks if reg access collides with secure update state
+ * @m10bmc: M10 BMC structure
+ *
+ * For some Intel FPGA devices, the BMC firmware is not available to service
+ * handshake registers during a secure update erase and write phases.
+ *
+ * Context: @m10bmc->bmcfw_lock must be held.
+ */
+static bool m10bmc_handshake_reg_unavailable(struct intel_m10bmc *m10bmc)
+{
+ return m10bmc->bmcfw_state == M10BMC_FW_STATE_SEC_UPDATE_PREPARE ||
+ m10bmc->bmcfw_state == M10BMC_FW_STATE_SEC_UPDATE_WRITE;
+}
+
+/*
+ * This function helps to simplify the accessing of the system registers.
+ *
+ * The base of the system registers is configured through the struct
+ * csr_map.
+ */
+int m10bmc_sys_read(struct intel_m10bmc *m10bmc, unsigned int offset, unsigned int *val)
+{
+ const struct m10bmc_csr_map *csr_map = m10bmc->info->csr_map;
+ int ret;
+
+ if (m10bmc_reg_always_available(m10bmc, offset))
+ return m10bmc_raw_read(m10bmc, csr_map->base + offset, val);
+
+ down_read(&m10bmc->bmcfw_lock);
+ if (m10bmc_handshake_reg_unavailable(m10bmc))
+ ret = -EBUSY; /* Reg not available during secure update */
+ else
+ ret = m10bmc_raw_read(m10bmc, csr_map->base + offset, val);
+ up_read(&m10bmc->bmcfw_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(m10bmc_sys_read, INTEL_M10_BMC_CORE);
+
+int m10bmc_sys_update_bits(struct intel_m10bmc *m10bmc, unsigned int offset,
+ unsigned int msk, unsigned int val)
+{
+ const struct m10bmc_csr_map *csr_map = m10bmc->info->csr_map;
+ int ret;
+
+ if (m10bmc_reg_always_available(m10bmc, offset))
+ return regmap_update_bits(m10bmc->regmap, csr_map->base + offset, msk, val);
+
+ down_read(&m10bmc->bmcfw_lock);
+ if (m10bmc_handshake_reg_unavailable(m10bmc))
+ ret = -EBUSY; /* Reg not available during secure update */
+ else
+ ret = regmap_update_bits(m10bmc->regmap, csr_map->base + offset, msk, val);
+ up_read(&m10bmc->bmcfw_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(m10bmc_sys_update_bits, INTEL_M10_BMC_CORE);
+
static ssize_t bmc_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -98,7 +183,7 @@ const struct attribute_group *m10bmc_dev_groups[] = {
&m10bmc_group,
NULL,
};
-EXPORT_SYMBOL_GPL(m10bmc_dev_groups);
+EXPORT_SYMBOL_NS_GPL(m10bmc_dev_groups, INTEL_M10_BMC_CORE);
int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platform_info *info)
{
@@ -106,6 +191,7 @@ int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platf
m10bmc->info = info;
dev_set_drvdata(m10bmc->dev, m10bmc);
+ init_rwsem(&m10bmc->bmcfw_lock);
ret = devm_mfd_add_devices(m10bmc->dev, PLATFORM_DEVID_AUTO,
info->cells, info->n_cells,
@@ -115,7 +201,7 @@ int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platf
return ret;
}
-EXPORT_SYMBOL_GPL(m10bmc_dev_init);
+EXPORT_SYMBOL_NS_GPL(m10bmc_dev_init, INTEL_M10_BMC_CORE);
MODULE_DESCRIPTION("Intel MAX 10 BMC core driver");
MODULE_AUTHOR("Intel Corporation");
diff --git a/drivers/mfd/intel-m10-bmc-pmci.c b/drivers/mfd/intel-m10-bmc-pmci.c
index 8821f1876dd6..0392ef8b57d8 100644
--- a/drivers/mfd/intel-m10-bmc-pmci.c
+++ b/drivers/mfd/intel-m10-bmc-pmci.c
@@ -453,3 +453,4 @@ module_dfl_driver(m10bmc_pmci_driver);
MODULE_DESCRIPTION("MAX10 BMC PMCI-based interface");
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(INTEL_M10_BMC_CORE);
diff --git a/drivers/mfd/intel-m10-bmc-spi.c b/drivers/mfd/intel-m10-bmc-spi.c
index 957200e17fed..cbeb7de9e041 100644
--- a/drivers/mfd/intel-m10-bmc-spi.c
+++ b/drivers/mfd/intel-m10-bmc-spi.c
@@ -116,12 +116,20 @@ static struct mfd_cell m10bmc_d5005_subdevs[] = {
{ .name = "d5005bmc-sec-update" },
};
+static const struct regmap_range m10bmc_d5005_fw_handshake_regs[] = {
+ regmap_reg_range(M10BMC_N3000_TELEM_START, M10BMC_D5005_TELEM_END),
+};
+
static struct mfd_cell m10bmc_pacn3000_subdevs[] = {
{ .name = "n3000bmc-hwmon" },
{ .name = "n3000bmc-retimer" },
{ .name = "n3000bmc-sec-update" },
};
+static const struct regmap_range m10bmc_n3000_fw_handshake_regs[] = {
+ regmap_reg_range(M10BMC_N3000_TELEM_START, M10BMC_N3000_TELEM_END),
+};
+
static struct mfd_cell m10bmc_n5010_subdevs[] = {
{ .name = "n5010bmc-hwmon" },
};
@@ -129,18 +137,24 @@ static struct mfd_cell m10bmc_n5010_subdevs[] = {
static const struct intel_m10bmc_platform_info m10bmc_spi_n3000 = {
.cells = m10bmc_pacn3000_subdevs,
.n_cells = ARRAY_SIZE(m10bmc_pacn3000_subdevs),
+ .handshake_sys_reg_ranges = m10bmc_n3000_fw_handshake_regs,
+ .handshake_sys_reg_nranges = ARRAY_SIZE(m10bmc_n3000_fw_handshake_regs),
.csr_map = &m10bmc_n3000_csr_map,
};
static const struct intel_m10bmc_platform_info m10bmc_spi_d5005 = {
.cells = m10bmc_d5005_subdevs,
.n_cells = ARRAY_SIZE(m10bmc_d5005_subdevs),
+ .handshake_sys_reg_ranges = m10bmc_d5005_fw_handshake_regs,
+ .handshake_sys_reg_nranges = ARRAY_SIZE(m10bmc_d5005_fw_handshake_regs),
.csr_map = &m10bmc_n3000_csr_map,
};
static const struct intel_m10bmc_platform_info m10bmc_spi_n5010 = {
.cells = m10bmc_n5010_subdevs,
.n_cells = ARRAY_SIZE(m10bmc_n5010_subdevs),
+ .handshake_sys_reg_ranges = m10bmc_n3000_fw_handshake_regs,
+ .handshake_sys_reg_nranges = ARRAY_SIZE(m10bmc_n3000_fw_handshake_regs),
.csr_map = &m10bmc_n3000_csr_map,
};
@@ -166,3 +180,4 @@ MODULE_DESCRIPTION("Intel MAX 10 BMC SPI bus interface");
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:intel-m10-bmc");
+MODULE_IMPORT_NS(INTEL_M10_BMC_CORE);
diff --git a/drivers/mfd/intel_soc_pmic_chtdc_ti.c b/drivers/mfd/intel_soc_pmic_chtdc_ti.c
index 282b8fd08009..992855bfda3e 100644
--- a/drivers/mfd/intel_soc_pmic_chtdc_ti.c
+++ b/drivers/mfd/intel_soc_pmic_chtdc_ti.c
@@ -172,7 +172,7 @@ static struct i2c_driver chtdc_ti_i2c_driver = {
.pm = pm_sleep_ptr(&chtdc_ti_pm_ops),
.acpi_match_table = chtdc_ti_acpi_ids,
},
- .probe_new = chtdc_ti_probe,
+ .probe = chtdc_ti_probe,
.shutdown = chtdc_ti_shutdown,
};
module_i2c_driver(chtdc_ti_i2c_driver);
diff --git a/drivers/mfd/intel_soc_pmic_chtwc.c b/drivers/mfd/intel_soc_pmic_chtwc.c
index 871776d511e3..7fce3ef7ab45 100644
--- a/drivers/mfd/intel_soc_pmic_chtwc.c
+++ b/drivers/mfd/intel_soc_pmic_chtwc.c
@@ -272,7 +272,7 @@ static struct i2c_driver cht_wc_driver = {
.pm = pm_sleep_ptr(&cht_wc_pm_ops),
.acpi_match_table = cht_wc_acpi_ids,
},
- .probe_new = cht_wc_probe,
+ .probe = cht_wc_probe,
.shutdown = cht_wc_shutdown,
.id_table = cht_wc_i2c_id,
};
diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c
index b745ace46e5b..581f81cbaa24 100644
--- a/drivers/mfd/intel_soc_pmic_crc.c
+++ b/drivers/mfd/intel_soc_pmic_crc.c
@@ -263,7 +263,7 @@ static struct i2c_driver crystal_cove_i2c_driver = {
.pm = pm_sleep_ptr(&crystal_cove_pm_ops),
.acpi_match_table = crystal_cove_acpi_match,
},
- .probe_new = crystal_cove_i2c_probe,
+ .probe = crystal_cove_i2c_probe,
.remove = crystal_cove_i2c_remove,
.shutdown = crystal_cove_shutdown,
};
diff --git a/drivers/mfd/iqs62x.c b/drivers/mfd/iqs62x.c
index 1895fce25b06..dfe9cb79e6a1 100644
--- a/drivers/mfd/iqs62x.c
+++ b/drivers/mfd/iqs62x.c
@@ -1069,7 +1069,7 @@ static struct i2c_driver iqs62x_i2c_driver = {
.of_match_table = iqs62x_of_match,
.pm = &iqs62x_pm,
},
- .probe_new = iqs62x_probe,
+ .probe = iqs62x_probe,
.remove = iqs62x_remove,
};
module_i2c_driver(iqs62x_i2c_driver);
diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
index 1c807c0e6d25..61396d824f16 100644
--- a/drivers/mfd/khadas-mcu.c
+++ b/drivers/mfd/khadas-mcu.c
@@ -134,7 +134,7 @@ static struct i2c_driver khadas_mcu_driver = {
.name = "khadas-mcu-core",
.of_match_table = of_match_ptr(khadas_mcu_of_match),
},
- .probe_new = khadas_mcu_probe,
+ .probe = khadas_mcu_probe,
};
module_i2c_driver(khadas_mcu_driver);
diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c
index 946f94f3a3c3..c211183cecb2 100644
--- a/drivers/mfd/lm3533-core.c
+++ b/drivers/mfd/lm3533-core.c
@@ -485,8 +485,6 @@ static int lm3533_device_init(struct lm3533 *lm3533)
lm3533->gpio_hwen = pdata->gpio_hwen;
- dev_set_drvdata(lm3533->dev, lm3533);
-
if (gpio_is_valid(lm3533->gpio_hwen)) {
ret = devm_gpio_request_one(lm3533->dev, lm3533->gpio_hwen,
GPIOF_OUT_INIT_LOW, "lm3533-hwen");
@@ -626,7 +624,7 @@ static struct i2c_driver lm3533_i2c_driver = {
.name = "lm3533",
},
.id_table = lm3533_i2c_ids,
- .probe_new = lm3533_i2c_probe,
+ .probe = lm3533_i2c_probe,
.remove = lm3533_i2c_remove,
};
diff --git a/drivers/mfd/lochnagar-i2c.c b/drivers/mfd/lochnagar-i2c.c
index 3a65d9938902..3c8843117080 100644
--- a/drivers/mfd/lochnagar-i2c.c
+++ b/drivers/mfd/lochnagar-i2c.c
@@ -382,7 +382,7 @@ static struct i2c_driver lochnagar_i2c_driver = {
.of_match_table = of_match_ptr(lochnagar_of_match),
.suppress_bind_attrs = true,
},
- .probe_new = lochnagar_i2c_probe,
+ .probe = lochnagar_i2c_probe,
};
static int __init lochnagar_i2c_init(void)
diff --git a/drivers/mfd/lp3943.c b/drivers/mfd/lp3943.c
index f9f39b53d030..7f749a23dca8 100644
--- a/drivers/mfd/lp3943.c
+++ b/drivers/mfd/lp3943.c
@@ -140,7 +140,7 @@ MODULE_DEVICE_TABLE(of, lp3943_of_match);
#endif
static struct i2c_driver lp3943_driver = {
- .probe_new = lp3943_probe,
+ .probe = lp3943_probe,
.driver = {
.name = "lp3943",
.of_match_table = of_match_ptr(lp3943_of_match),
diff --git a/drivers/mfd/lp873x.c b/drivers/mfd/lp873x.c
index c81c5c9ad748..6639f0fad4ea 100644
--- a/drivers/mfd/lp873x.c
+++ b/drivers/mfd/lp873x.c
@@ -78,7 +78,7 @@ static struct i2c_driver lp873x_driver = {
.name = "lp873x",
.of_match_table = of_lp873x_match_table,
},
- .probe_new = lp873x_probe,
+ .probe = lp873x_probe,
.id_table = lp873x_id_table,
};
module_i2c_driver(lp873x_driver);
diff --git a/drivers/mfd/lp87565.c b/drivers/mfd/lp87565.c
index 568f0f01ea0d..88ce4d7c50a7 100644
--- a/drivers/mfd/lp87565.c
+++ b/drivers/mfd/lp87565.c
@@ -119,7 +119,7 @@ static struct i2c_driver lp87565_driver = {
.name = "lp87565",
.of_match_table = of_lp87565_match_table,
},
- .probe_new = lp87565_probe,
+ .probe = lp87565_probe,
.shutdown = lp87565_shutdown,
.id_table = lp87565_id_table,
};
diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c
index 18583addaae2..f371eeb042e0 100644
--- a/drivers/mfd/lp8788.c
+++ b/drivers/mfd/lp8788.c
@@ -225,7 +225,7 @@ static struct i2c_driver lp8788_driver = {
.driver = {
.name = "lp8788",
},
- .probe_new = lp8788_probe,
+ .probe = lp8788_probe,
.remove = lp8788_remove,
.id_table = lp8788_ids,
};
diff --git a/drivers/mfd/madera-i2c.c b/drivers/mfd/madera-i2c.c
index 47e65d88feb0..0968aa9733ac 100644
--- a/drivers/mfd/madera-i2c.c
+++ b/drivers/mfd/madera-i2c.c
@@ -139,7 +139,7 @@ static struct i2c_driver madera_i2c_driver = {
.pm = &madera_pm_ops,
.of_match_table = of_match_ptr(madera_of_match),
},
- .probe_new = madera_i2c_probe,
+ .probe = madera_i2c_probe,
.remove = madera_i2c_remove,
.id_table = madera_i2c_id,
};
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c
index 0e3731e9e9b5..25ed8846b7fb 100644
--- a/drivers/mfd/max14577.c
+++ b/drivers/mfd/max14577.c
@@ -518,7 +518,7 @@ static struct i2c_driver max14577_i2c_driver = {
.pm = pm_sleep_ptr(&max14577_pm),
.of_match_table = max14577_dt_match,
},
- .probe_new = max14577_i2c_probe,
+ .probe = max14577_i2c_probe,
.remove = max14577_i2c_remove,
.id_table = max14577_i2c_id,
};
diff --git a/drivers/mfd/max77541.c b/drivers/mfd/max77541.c
new file mode 100644
index 000000000000..e147e949c2b3
--- /dev/null
+++ b/drivers/mfd/max77541.c
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022 Analog Devices, Inc.
+ * Driver for the MAX77540 and MAX77541
+ */
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max77541.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+
+static const struct regmap_config max77541_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static const struct regmap_irq max77541_src_irqs[] = {
+ { .mask = MAX77541_BIT_INT_SRC_TOPSYS },
+ { .mask = MAX77541_BIT_INT_SRC_BUCK },
+};
+
+static const struct regmap_irq_chip max77541_src_irq_chip = {
+ .name = "max77541-src",
+ .status_base = MAX77541_REG_INT_SRC,
+ .mask_base = MAX77541_REG_INT_SRC_M,
+ .num_regs = 1,
+ .irqs = max77541_src_irqs,
+ .num_irqs = ARRAY_SIZE(max77541_src_irqs),
+};
+
+static const struct regmap_irq max77541_topsys_irqs[] = {
+ { .mask = MAX77541_BIT_TOPSYS_INT_TJ_120C },
+ { .mask = MAX77541_BIT_TOPSYS_INT_TJ_140C },
+ { .mask = MAX77541_BIT_TOPSYS_INT_TSHDN },
+ { .mask = MAX77541_BIT_TOPSYS_INT_UVLO },
+ { .mask = MAX77541_BIT_TOPSYS_INT_ALT_SWO },
+ { .mask = MAX77541_BIT_TOPSYS_INT_EXT_FREQ_DET },
+};
+
+static const struct regmap_irq_chip max77541_topsys_irq_chip = {
+ .name = "max77541-topsys",
+ .status_base = MAX77541_REG_TOPSYS_INT,
+ .mask_base = MAX77541_REG_TOPSYS_INT_M,
+ .num_regs = 1,
+ .irqs = max77541_topsys_irqs,
+ .num_irqs = ARRAY_SIZE(max77541_topsys_irqs),
+};
+
+static const struct regmap_irq max77541_buck_irqs[] = {
+ { .mask = MAX77541_BIT_BUCK_INT_M1_POK_FLT },
+ { .mask = MAX77541_BIT_BUCK_INT_M2_POK_FLT },
+ { .mask = MAX77541_BIT_BUCK_INT_M1_SCFLT },
+ { .mask = MAX77541_BIT_BUCK_INT_M2_SCFLT },
+};
+
+static const struct regmap_irq_chip max77541_buck_irq_chip = {
+ .name = "max77541-buck",
+ .status_base = MAX77541_REG_BUCK_INT,
+ .mask_base = MAX77541_REG_BUCK_INT_M,
+ .num_regs = 1,
+ .irqs = max77541_buck_irqs,
+ .num_irqs = ARRAY_SIZE(max77541_buck_irqs),
+};
+
+static const struct regmap_irq max77541_adc_irqs[] = {
+ { .mask = MAX77541_BIT_ADC_INT_CH1_I },
+ { .mask = MAX77541_BIT_ADC_INT_CH2_I },
+ { .mask = MAX77541_BIT_ADC_INT_CH3_I },
+ { .mask = MAX77541_BIT_ADC_INT_CH6_I },
+};
+
+static const struct regmap_irq_chip max77541_adc_irq_chip = {
+ .name = "max77541-adc",
+ .status_base = MAX77541_REG_ADC_INT,
+ .mask_base = MAX77541_REG_ADC_INT_M,
+ .num_regs = 1,
+ .irqs = max77541_adc_irqs,
+ .num_irqs = ARRAY_SIZE(max77541_adc_irqs),
+};
+
+static const struct mfd_cell max77540_devs[] = {
+ MFD_CELL_OF("max77540-regulator", NULL, NULL, 0, 0, NULL),
+};
+
+static const struct mfd_cell max77541_devs[] = {
+ MFD_CELL_OF("max77541-regulator", NULL, NULL, 0, 0, NULL),
+ MFD_CELL_OF("max77541-adc", NULL, NULL, 0, 0, NULL),
+};
+
+static int max77541_pmic_irq_init(struct device *dev)
+{
+ struct max77541 *max77541 = dev_get_drvdata(dev);
+ int irq = max77541->i2c->irq;
+ int ret;
+
+ ret = devm_regmap_add_irq_chip(dev, max77541->regmap, irq,
+ IRQF_ONESHOT | IRQF_SHARED, 0,
+ &max77541_src_irq_chip,
+ &max77541->irq_data);
+ if (ret)
+ return ret;
+
+ ret = devm_regmap_add_irq_chip(dev, max77541->regmap, irq,
+ IRQF_ONESHOT | IRQF_SHARED, 0,
+ &max77541_topsys_irq_chip,
+ &max77541->irq_topsys);
+ if (ret)
+ return ret;
+
+ ret = devm_regmap_add_irq_chip(dev, max77541->regmap, irq,
+ IRQF_ONESHOT | IRQF_SHARED, 0,
+ &max77541_buck_irq_chip,
+ &max77541->irq_buck);
+ if (ret)
+ return ret;
+
+ if (max77541->id == MAX77541) {
+ ret = devm_regmap_add_irq_chip(dev, max77541->regmap, irq,
+ IRQF_ONESHOT | IRQF_SHARED, 0,
+ &max77541_adc_irq_chip,
+ &max77541->irq_adc);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int max77541_pmic_setup(struct device *dev)
+{
+ struct max77541 *max77541 = dev_get_drvdata(dev);
+ const struct mfd_cell *cells;
+ int n_devs;
+ int ret;
+
+ switch (max77541->id) {
+ case MAX77540:
+ cells = max77540_devs;
+ n_devs = ARRAY_SIZE(max77540_devs);
+ break;
+ case MAX77541:
+ cells = max77541_devs;
+ n_devs = ARRAY_SIZE(max77541_devs);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = max77541_pmic_irq_init(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to initialize IRQ\n");
+
+ ret = device_init_wakeup(dev, true);
+ if (ret)
+ return dev_err_probe(dev, ret, "Unable to init wakeup\n");
+
+ return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+ cells, n_devs, NULL, 0, NULL);
+}
+
+static int max77541_probe(struct i2c_client *client)
+{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
+ struct device *dev = &client->dev;
+ struct max77541 *max77541;
+
+ max77541 = devm_kzalloc(dev, sizeof(*max77541), GFP_KERNEL);
+ if (!max77541)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, max77541);
+ max77541->i2c = client;
+
+ max77541->id = (enum max7754x_ids)device_get_match_data(dev);
+ if (!max77541->id)
+ max77541->id = (enum max7754x_ids)id->driver_data;
+
+ if (!max77541->id)
+ return -EINVAL;
+
+ max77541->regmap = devm_regmap_init_i2c(client,
+ &max77541_regmap_config);
+ if (IS_ERR(max77541->regmap))
+ return dev_err_probe(dev, PTR_ERR(max77541->regmap),
+ "Failed to allocate register map\n");
+
+ return max77541_pmic_setup(dev);
+}
+
+static const struct of_device_id max77541_of_id[] = {
+ {
+ .compatible = "adi,max77540",
+ .data = (void *)MAX77540,
+ },
+ {
+ .compatible = "adi,max77541",
+ .data = (void *)MAX77541,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max77541_of_id);
+
+static const struct i2c_device_id max77541_id[] = {
+ { "max77540", MAX77540 },
+ { "max77541", MAX77541 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max77541_id);
+
+static struct i2c_driver max77541_driver = {
+ .driver = {
+ .name = "max77541",
+ .of_match_table = max77541_of_id,
+ },
+ .probe = max77541_probe,
+ .id_table = max77541_id,
+};
+module_i2c_driver(max77541_driver);
+
+MODULE_DESCRIPTION("MAX7740/MAX7741 Driver");
+MODULE_AUTHOR("Okan Sahin <okan.sahin@analog.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c
index cbd2297126f0..5811ed8f4840 100644
--- a/drivers/mfd/max77620.c
+++ b/drivers/mfd/max77620.c
@@ -698,7 +698,7 @@ static struct i2c_driver max77620_driver = {
.name = "max77620",
.pm = pm_sleep_ptr(&max77620_pm_ops),
},
- .probe_new = max77620_probe,
+ .probe = max77620_probe,
.id_table = max77620_id,
};
builtin_i2c_driver(max77620_driver);
diff --git a/drivers/mfd/max77650.c b/drivers/mfd/max77650.c
index 3c07fcdd9d07..75b5dc44e38c 100644
--- a/drivers/mfd/max77650.c
+++ b/drivers/mfd/max77650.c
@@ -222,7 +222,7 @@ static struct i2c_driver max77650_i2c_driver = {
.name = "max77650",
.of_match_table = max77650_of_match,
},
- .probe_new = max77650_i2c_probe,
+ .probe = max77650_i2c_probe,
};
module_i2c_driver(max77650_i2c_driver);
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index f8e863f3fc95..01833086ca7d 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -269,7 +269,7 @@ static struct i2c_driver max77686_i2c_driver = {
.pm = pm_sleep_ptr(&max77686_pm),
.of_match_table = max77686_pmic_dt_match,
},
- .probe_new = max77686_i2c_probe,
+ .probe = max77686_i2c_probe,
};
module_i2c_driver(max77686_i2c_driver);
diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index 3995e8769f49..1c485a4c3dcf 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -356,7 +356,7 @@ static struct i2c_driver max77693_i2c_driver = {
.pm = &max77693_pm,
.of_match_table = of_match_ptr(max77693_dt_match),
},
- .probe_new = max77693_i2c_probe,
+ .probe = max77693_i2c_probe,
.remove = max77693_i2c_remove,
.id_table = max77693_i2c_id,
};
diff --git a/drivers/mfd/max77714.c b/drivers/mfd/max77714.c
index 143a432ea343..c618605a3fb2 100644
--- a/drivers/mfd/max77714.c
+++ b/drivers/mfd/max77714.c
@@ -143,7 +143,7 @@ static struct i2c_driver max77714_driver = {
.name = "max77714",
.of_match_table = max77714_dt_match,
},
- .probe_new = max77714_probe,
+ .probe = max77714_probe,
};
module_i2c_driver(max77714_driver);
diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c
index 8ff0723808c8..b3689c13a14d 100644
--- a/drivers/mfd/max77843.c
+++ b/drivers/mfd/max77843.c
@@ -207,7 +207,7 @@ static struct i2c_driver max77843_i2c_driver = {
.of_match_table = max77843_dt_match,
.suppress_bind_attrs = true,
},
- .probe_new = max77843_probe,
+ .probe = max77843_probe,
.id_table = max77843_id,
};
diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c
index a69b865c6eac..78b5ee688dec 100644
--- a/drivers/mfd/max8907.c
+++ b/drivers/mfd/max8907.c
@@ -201,8 +201,6 @@ static int max8907_i2c_probe(struct i2c_client *i2c)
}
max8907->dev = &i2c->dev;
- dev_set_drvdata(max8907->dev, max8907);
-
max8907->i2c_gen = i2c;
i2c_set_clientdata(i2c, max8907);
max8907->regmap_gen = devm_regmap_init_i2c(i2c,
@@ -313,7 +311,7 @@ static struct i2c_driver max8907_i2c_driver = {
.name = "max8907",
.of_match_table = of_match_ptr(max8907_of_match),
},
- .probe_new = max8907_i2c_probe,
+ .probe = max8907_i2c_probe,
.remove = max8907_i2c_remove,
.id_table = max8907_i2c_id,
};
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index 4057fd15c29e..7608000488f9 100644
--- a/drivers/mfd/max8925-i2c.c
+++ b/drivers/mfd/max8925-i2c.c
@@ -172,7 +172,6 @@ static int max8925_probe(struct i2c_client *client)
chip->i2c = client;
chip->dev = &client->dev;
i2c_set_clientdata(client, chip);
- dev_set_drvdata(chip->dev, chip);
mutex_init(&chip->io_lock);
chip->rtc = i2c_new_dummy_device(chip->i2c->adapter, RTC_I2C_ADDR);
@@ -240,7 +239,7 @@ static struct i2c_driver max8925_driver = {
.pm = pm_sleep_ptr(&max8925_pm_ops),
.of_match_table = max8925_dt_ids,
},
- .probe_new = max8925_probe,
+ .probe = max8925_probe,
.remove = max8925_remove,
.id_table = max8925_id_table,
};
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 79d551b86150..94c09a5eab32 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -478,7 +478,7 @@ static struct i2c_driver max8997_i2c_driver = {
.suppress_bind_attrs = true,
.of_match_table = of_match_ptr(max8997_pmic_dt_match),
},
- .probe_new = max8997_i2c_probe,
+ .probe = max8997_i2c_probe,
.id_table = max8997_i2c_id,
};
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c
index 122f7b931f5a..33a3ec5464fb 100644
--- a/drivers/mfd/max8998.c
+++ b/drivers/mfd/max8998.c
@@ -348,7 +348,7 @@ static struct i2c_driver max8998_i2c_driver = {
.suppress_bind_attrs = true,
.of_match_table = of_match_ptr(max8998_dt_match),
},
- .probe_new = max8998_i2c_probe,
+ .probe = max8998_i2c_probe,
.id_table = max8998_i2c_id,
};
diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c
index 633b973a5ba7..de59b498c925 100644
--- a/drivers/mfd/mc13xxx-i2c.c
+++ b/drivers/mfd/mc13xxx-i2c.c
@@ -95,7 +95,7 @@ static struct i2c_driver mc13xxx_i2c_driver = {
.name = "mc13xxx",
.of_match_table = mc13xxx_dt_ids,
},
- .probe_new = mc13xxx_i2c_probe,
+ .probe = mc13xxx_i2c_probe,
.remove = mc13xxx_i2c_remove,
};
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c
index c2866a11c1d2..662604ea97f2 100644
--- a/drivers/mfd/menelaus.c
+++ b/drivers/mfd/menelaus.c
@@ -1240,7 +1240,7 @@ static struct i2c_driver menelaus_i2c_driver = {
.driver = {
.name = DRIVER_NAME,
},
- .probe_new = menelaus_probe,
+ .probe = menelaus_probe,
.remove = menelaus_remove,
.id_table = menelaus_id,
};
diff --git a/drivers/mfd/menf21bmc.c b/drivers/mfd/menf21bmc.c
index 9092fac46e35..1d36095155e0 100644
--- a/drivers/mfd/menf21bmc.c
+++ b/drivers/mfd/menf21bmc.c
@@ -111,7 +111,7 @@ MODULE_DEVICE_TABLE(i2c, menf21bmc_id_table);
static struct i2c_driver menf21bmc_driver = {
.driver.name = "menf21bmc",
.id_table = menf21bmc_id_table,
- .probe_new = menf21bmc_probe,
+ .probe = menf21bmc_probe,
};
module_i2c_driver(menf21bmc_driver);
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 695d50b3bac6..0ed7c0d7784e 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -102,7 +102,6 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev,
{
#if IS_ENABLED(CONFIG_OF)
struct mfd_of_node_entry *of_entry;
- const __be32 *reg;
u64 of_node_addr;
/* Skip if OF node has previously been allocated to a device */
@@ -115,13 +114,10 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev,
goto allocate_of_node;
/* We only care about each node's first defined address */
- reg = of_get_address(np, 0, NULL, NULL);
- if (!reg)
+ if (of_property_read_reg(np, 0, &of_node_addr, NULL))
/* OF node does not contatin a 'reg' property to match to */
return -EAGAIN;
- of_node_addr = of_read_number(reg, of_n_addr_cells(np));
-
if (cell->of_reg != of_node_addr)
/* No match */
return -EAGAIN;
diff --git a/drivers/mfd/mp2629.c b/drivers/mfd/mp2629.c
index 16840ec5fd1c..717b704c3c6b 100644
--- a/drivers/mfd/mp2629.c
+++ b/drivers/mfd/mp2629.c
@@ -70,7 +70,7 @@ static struct i2c_driver mp2629_driver = {
.name = "mp2629",
.of_match_table = mp2629_of_match,
},
- .probe_new = mp2629_probe,
+ .probe = mp2629_probe,
};
module_i2c_driver(mp2629_driver);
diff --git a/drivers/mfd/mt6360-core.c b/drivers/mfd/mt6360-core.c
index d3b32eb79837..2685efa5c9e2 100644
--- a/drivers/mfd/mt6360-core.c
+++ b/drivers/mfd/mt6360-core.c
@@ -623,7 +623,7 @@ static struct i2c_driver mt6360_driver = {
.pm = &mt6360_pm_ops,
.of_match_table = of_match_ptr(mt6360_of_id),
},
- .probe_new = mt6360_probe,
+ .probe = mt6360_probe,
};
module_i2c_driver(mt6360_driver);
diff --git a/drivers/mfd/mt6370.c b/drivers/mfd/mt6370.c
index cf19cce2fdc0..c126ccb25d66 100644
--- a/drivers/mfd/mt6370.c
+++ b/drivers/mfd/mt6370.c
@@ -303,7 +303,7 @@ static struct i2c_driver mt6370_driver = {
.name = "mt6370",
.of_match_table = mt6370_match_table,
},
- .probe_new = mt6370_probe,
+ .probe = mt6370_probe,
};
module_i2c_driver(mt6370_driver);
diff --git a/drivers/mfd/ntxec.c b/drivers/mfd/ntxec.c
index b02785b10d48..4416cd37e539 100644
--- a/drivers/mfd/ntxec.c
+++ b/drivers/mfd/ntxec.c
@@ -260,7 +260,7 @@ static struct i2c_driver ntxec_driver = {
.name = "ntxec",
.of_match_table = of_ntxec_match_table,
},
- .probe_new = ntxec_probe,
+ .probe = ntxec_probe,
.remove = ntxec_remove,
};
module_i2c_driver(ntxec_driver);
diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
index b8383c6cba3f..a36f12402987 100644
--- a/drivers/mfd/palmas.c
+++ b/drivers/mfd/palmas.c
@@ -725,7 +725,7 @@ static struct i2c_driver palmas_i2c_driver = {
.name = "palmas",
.of_match_table = of_palmas_match_tbl,
},
- .probe_new = palmas_i2c_probe,
+ .probe = palmas_i2c_probe,
.remove = palmas_i2c_remove,
.id_table = palmas_i2c_id,
};
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 0e4fc99e9f49..014a68711b18 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -282,7 +282,7 @@ static struct i2c_driver pcf50633_driver = {
.pm = pm_sleep_ptr(&pcf50633_pm),
},
.id_table = pcf50633_id_table,
- .probe_new = pcf50633_probe,
+ .probe = pcf50633_probe,
.remove = pcf50633_remove,
};
diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c
index 837246aab4ac..94a8cca1d955 100644
--- a/drivers/mfd/qcom-pm8008.c
+++ b/drivers/mfd/qcom-pm8008.c
@@ -199,15 +199,15 @@ static const struct of_device_id pm8008_match[] = {
{ .compatible = "qcom,pm8008", },
{ },
};
+MODULE_DEVICE_TABLE(of, pm8008_match);
static struct i2c_driver pm8008_mfd_driver = {
.driver = {
.name = "pm8008",
.of_match_table = pm8008_match,
},
- .probe_new = pm8008_probe,
+ .probe = pm8008_probe,
};
module_i2c_driver(pm8008_mfd_driver);
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("i2c:qcom-pm8008");
diff --git a/drivers/mfd/rc5t583-irq.c b/drivers/mfd/rc5t583-irq.c
index 621ea61fa7c6..97f52b671520 100644
--- a/drivers/mfd/rc5t583-irq.c
+++ b/drivers/mfd/rc5t583-irq.c
@@ -8,9 +8,9 @@
* based on code
* Copyright (C) 2011 RICOH COMPANY,LTD
*/
+#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/i2c.h>
#include <linux/mfd/rc5t583.h>
enum int_type {
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
index df83cc399315..5e81f011363f 100644
--- a/drivers/mfd/rc5t583.c
+++ b/drivers/mfd/rc5t583.c
@@ -288,7 +288,7 @@ static struct i2c_driver rc5t583_i2c_driver = {
.driver = {
.name = "rc5t583",
},
- .probe_new = rc5t583_i2c_probe,
+ .probe = rc5t583_i2c_probe,
.id_table = rc5t583_i2c_id,
};
diff --git a/drivers/mfd/retu-mfd.c b/drivers/mfd/retu-mfd.c
index d71483859e2e..b50cfa7f4b8f 100644
--- a/drivers/mfd/retu-mfd.c
+++ b/drivers/mfd/retu-mfd.c
@@ -318,7 +318,7 @@ static struct i2c_driver retu_driver = {
.name = "retu-mfd",
.of_match_table = retu_of_match,
},
- .probe_new = retu_probe,
+ .probe = retu_probe,
.remove = retu_remove,
.id_table = retu_id,
};
diff --git a/drivers/mfd/rk8xx-i2c.c b/drivers/mfd/rk8xx-i2c.c
index 2822bfa8a04a..1a98feea97e2 100644
--- a/drivers/mfd/rk8xx-i2c.c
+++ b/drivers/mfd/rk8xx-i2c.c
@@ -173,7 +173,7 @@ static struct i2c_driver rk8xx_i2c_driver = {
.of_match_table = rk8xx_i2c_of_match,
.pm = &rk8xx_i2c_pm_ops,
},
- .probe_new = rk8xx_i2c_probe,
+ .probe = rk8xx_i2c_probe,
.shutdown = rk8xx_i2c_shutdown,
};
module_i2c_driver(rk8xx_i2c_driver);
diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c
index 2f59230749cd..333fef8729a5 100644
--- a/drivers/mfd/rn5t618.c
+++ b/drivers/mfd/rn5t618.c
@@ -280,7 +280,7 @@ static struct i2c_driver rn5t618_i2c_driver = {
.of_match_table = of_match_ptr(rn5t618_of_match),
.pm = &rn5t618_i2c_dev_pm_ops,
},
- .probe_new = rn5t618_i2c_probe,
+ .probe = rn5t618_i2c_probe,
.remove = rn5t618_i2c_remove,
};
diff --git a/drivers/mfd/rohm-bd71828.c b/drivers/mfd/rohm-bd71828.c
index 7eb920633ee9..93d80a79b901 100644
--- a/drivers/mfd/rohm-bd71828.c
+++ b/drivers/mfd/rohm-bd71828.c
@@ -564,7 +564,7 @@ static struct i2c_driver bd71828_drv = {
.name = "rohm-bd71828",
.of_match_table = bd71828_of_match,
},
- .probe_new = &bd71828_i2c_probe,
+ .probe = bd71828_i2c_probe,
};
module_i2c_driver(bd71828_drv);
diff --git a/drivers/mfd/rohm-bd718x7.c b/drivers/mfd/rohm-bd718x7.c
index 378eb1a692e4..0b58ecc78334 100644
--- a/drivers/mfd/rohm-bd718x7.c
+++ b/drivers/mfd/rohm-bd718x7.c
@@ -208,7 +208,7 @@ static struct i2c_driver bd718xx_i2c_driver = {
.name = "rohm-bd718x7",
.of_match_table = bd718xx_of_match,
},
- .probe_new = bd718xx_i2c_probe,
+ .probe = bd718xx_i2c_probe,
};
static int __init bd718xx_i2c_init(void)
diff --git a/drivers/mfd/rohm-bd9576.c b/drivers/mfd/rohm-bd9576.c
index 6491e385d980..645673322ec0 100644
--- a/drivers/mfd/rohm-bd9576.c
+++ b/drivers/mfd/rohm-bd9576.c
@@ -178,7 +178,7 @@ static struct i2c_driver bd957x_drv = {
.name = "rohm-bd957x",
.of_match_table = bd957x_of_match,
},
- .probe_new = &bd957x_i2c_probe,
+ .probe = bd957x_i2c_probe,
};
module_i2c_driver(bd957x_drv);
diff --git a/drivers/mfd/rsmu_i2c.c b/drivers/mfd/rsmu_i2c.c
index 807c32101460..26972a5aff45 100644
--- a/drivers/mfd/rsmu_i2c.c
+++ b/drivers/mfd/rsmu_i2c.c
@@ -279,7 +279,7 @@ static struct i2c_driver rsmu_i2c_driver = {
.name = "rsmu-i2c",
.of_match_table = of_match_ptr(rsmu_i2c_of_match),
},
- .probe_new = rsmu_i2c_probe,
+ .probe = rsmu_i2c_probe,
.remove = rsmu_i2c_remove,
.id_table = rsmu_i2c_id,
};
diff --git a/drivers/mfd/rt4831.c b/drivers/mfd/rt4831.c
index c6d34dc2b520..f8d6dc55b558 100644
--- a/drivers/mfd/rt4831.c
+++ b/drivers/mfd/rt4831.c
@@ -109,7 +109,7 @@ static struct i2c_driver rt4831_driver = {
.name = "rt4831",
.of_match_table = rt4831_of_match,
},
- .probe_new = rt4831_probe,
+ .probe = rt4831_probe,
.remove = rt4831_remove,
};
module_i2c_driver(rt4831_driver);
diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c
index a5e520fe50a1..67b0a228db24 100644
--- a/drivers/mfd/rt5033.c
+++ b/drivers/mfd/rt5033.c
@@ -41,9 +41,6 @@ static const struct mfd_cell rt5033_devs[] = {
.name = "rt5033-charger",
.of_compatible = "richtek,rt5033-charger",
}, {
- .name = "rt5033-battery",
- .of_compatible = "richtek,rt5033-battery",
- }, {
.name = "rt5033-led",
.of_compatible = "richtek,rt5033-led",
},
@@ -58,7 +55,7 @@ static const struct regmap_config rt5033_regmap_config = {
static int rt5033_i2c_probe(struct i2c_client *i2c)
{
struct rt5033_dev *rt5033;
- unsigned int dev_id;
+ unsigned int dev_id, chip_rev;
int ret;
rt5033 = devm_kzalloc(&i2c->dev, sizeof(*rt5033), GFP_KERNEL);
@@ -81,7 +78,8 @@ static int rt5033_i2c_probe(struct i2c_client *i2c)
dev_err(&i2c->dev, "Device not found\n");
return -ENODEV;
}
- dev_info(&i2c->dev, "Device found Device ID: %04x\n", dev_id);
+ chip_rev = dev_id & RT5033_CHIP_REV_MASK;
+ dev_info(&i2c->dev, "Device found (rev. %d)\n", chip_rev);
ret = regmap_add_irq_chip(rt5033->regmap, rt5033->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
@@ -122,7 +120,7 @@ static struct i2c_driver rt5033_driver = {
.name = "rt5033",
.of_match_table = rt5033_dt_match,
},
- .probe_new = rt5033_i2c_probe,
+ .probe = rt5033_i2c_probe,
.id_table = rt5033_i2c_id,
};
module_i2c_driver(rt5033_driver);
diff --git a/drivers/mfd/rt5120.c b/drivers/mfd/rt5120.c
index 829b7a0a0781..58d9a124d795 100644
--- a/drivers/mfd/rt5120.c
+++ b/drivers/mfd/rt5120.c
@@ -114,7 +114,7 @@ static struct i2c_driver rt5120_driver = {
.name = "rt5120",
.of_match_table = rt5120_device_match_table,
},
- .probe_new = rt5120_probe,
+ .probe = rt5120_probe,
};
module_i2c_driver(rt5120_driver);
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index c2d0ed496959..d2f631901886 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -450,7 +450,7 @@ static struct i2c_driver sec_pmic_driver = {
.pm = pm_sleep_ptr(&sec_pmic_pm_ops),
.of_match_table = sec_dt_match,
},
- .probe_new = sec_pmic_probe,
+ .probe = sec_pmic_probe,
.shutdown = sec_pmic_shutdown,
};
module_i2c_driver(sec_pmic_driver);
diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c
index 22131cf85e3f..899c0b5ea3aa 100644
--- a/drivers/mfd/si476x-i2c.c
+++ b/drivers/mfd/si476x-i2c.c
@@ -866,7 +866,7 @@ static struct i2c_driver si476x_core_driver = {
.driver = {
.name = "si476x-core",
},
- .probe_new = si476x_core_probe,
+ .probe = si476x_core_probe,
.remove = si476x_core_remove,
.id_table = si476x_id,
};
diff --git a/drivers/mfd/simple-mfd-i2c.c b/drivers/mfd/simple-mfd-i2c.c
index 20782b4dd172..6eda79533208 100644
--- a/drivers/mfd/simple-mfd-i2c.c
+++ b/drivers/mfd/simple-mfd-i2c.c
@@ -72,28 +72,28 @@ static const struct simple_mfd_data silergy_sy7636a = {
.mfd_cell_size = ARRAY_SIZE(sy7636a_cells),
};
-static const struct mfd_cell max597x_cells[] = {
- { .name = "max597x-regulator", },
- { .name = "max597x-iio", },
- { .name = "max597x-led", },
+static const struct mfd_cell max5970_cells[] = {
+ { .name = "max5970-regulator", },
+ { .name = "max5970-iio", },
+ { .name = "max5970-led", },
};
-static const struct simple_mfd_data maxim_max597x = {
- .mfd_cell = max597x_cells,
- .mfd_cell_size = ARRAY_SIZE(max597x_cells),
+static const struct simple_mfd_data maxim_max5970 = {
+ .mfd_cell = max5970_cells,
+ .mfd_cell_size = ARRAY_SIZE(max5970_cells),
};
static const struct of_device_id simple_mfd_i2c_of_match[] = {
{ .compatible = "kontron,sl28cpld" },
{ .compatible = "silergy,sy7636a", .data = &silergy_sy7636a},
- { .compatible = "maxim,max5970", .data = &maxim_max597x},
- { .compatible = "maxim,max5978", .data = &maxim_max597x},
+ { .compatible = "maxim,max5970", .data = &maxim_max5970},
+ { .compatible = "maxim,max5978", .data = &maxim_max5970},
{}
};
MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match);
static struct i2c_driver simple_mfd_i2c_driver = {
- .probe_new = simple_mfd_i2c_probe,
+ .probe = simple_mfd_i2c_probe,
.driver = {
.name = "simple-mfd-i2c",
.of_match_table = simple_mfd_i2c_of_match,
diff --git a/drivers/mfd/sky81452.c b/drivers/mfd/sky81452.c
index 2515ecae1d3f..771b62a5c70f 100644
--- a/drivers/mfd/sky81452.c
+++ b/drivers/mfd/sky81452.c
@@ -77,7 +77,7 @@ static struct i2c_driver sky81452_driver = {
.name = "sky81452",
.of_match_table = of_match_ptr(sky81452_of_match),
},
- .probe_new = sky81452_probe,
+ .probe = sky81452_probe,
.id_table = sky81452_ids,
};
diff --git a/drivers/mfd/smpro-core.c b/drivers/mfd/smpro-core.c
index d7729cf70378..59d31590c69b 100644
--- a/drivers/mfd/smpro-core.c
+++ b/drivers/mfd/smpro-core.c
@@ -125,7 +125,7 @@ static const struct of_device_id smpro_core_of_match[] = {
MODULE_DEVICE_TABLE(of, smpro_core_of_match);
static struct i2c_driver smpro_core_driver = {
- .probe_new = smpro_core_probe,
+ .probe = smpro_core_probe,
.driver = {
.name = "smpro-core",
.of_match_table = smpro_core_of_match,
diff --git a/drivers/mfd/stmfx.c b/drivers/mfd/stmfx.c
index e281971ba54e..c02cbd9c2f5d 100644
--- a/drivers/mfd/stmfx.c
+++ b/drivers/mfd/stmfx.c
@@ -330,9 +330,8 @@ static int stmfx_chip_init(struct i2c_client *client)
stmfx->vdd = devm_regulator_get_optional(&client->dev, "vdd");
ret = PTR_ERR_OR_ZERO(stmfx->vdd);
if (ret) {
- if (ret == -ENODEV)
- stmfx->vdd = NULL;
- else
+ stmfx->vdd = NULL;
+ if (ret != -ENODEV)
return dev_err_probe(&client->dev, ret, "Failed to get VDD regulator\n");
}
@@ -387,7 +386,7 @@ static int stmfx_chip_init(struct i2c_client *client)
err:
if (stmfx->vdd)
- return regulator_disable(stmfx->vdd);
+ regulator_disable(stmfx->vdd);
return ret;
}
@@ -553,7 +552,7 @@ static struct i2c_driver stmfx_driver = {
.of_match_table = stmfx_of_match,
.pm = pm_sleep_ptr(&stmfx_dev_pm_ops),
},
- .probe_new = stmfx_probe,
+ .probe = stmfx_probe,
.remove = stmfx_remove,
};
module_i2c_driver(stmfx_driver);
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
index 7998e0db1e15..1d7b401776d1 100644
--- a/drivers/mfd/stmpe-i2c.c
+++ b/drivers/mfd/stmpe-i2c.c
@@ -118,7 +118,7 @@ static struct i2c_driver stmpe_i2c_driver = {
.pm = pm_sleep_ptr(&stmpe_dev_pm_ops),
.of_match_table = stmpe_of_match,
},
- .probe_new = stmpe_i2c_probe,
+ .probe = stmpe_i2c_probe,
.remove = stmpe_i2c_remove,
.id_table = stmpe_i2c_id,
};
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index a92301dfc712..9c3cf58457a7 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -1485,9 +1485,9 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
void stmpe_remove(struct stmpe *stmpe)
{
- if (!IS_ERR(stmpe->vio))
+ if (!IS_ERR(stmpe->vio) && regulator_is_enabled(stmpe->vio))
regulator_disable(stmpe->vio);
- if (!IS_ERR(stmpe->vcc))
+ if (!IS_ERR(stmpe->vcc) && regulator_is_enabled(stmpe->vcc))
regulator_disable(stmpe->vcc);
__stmpe_disable(stmpe, STMPE_BLOCK_ADC);
diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c
index 8db1530d9bac..3cc7492f828f 100644
--- a/drivers/mfd/stpmic1.c
+++ b/drivers/mfd/stpmic1.c
@@ -7,6 +7,7 @@
#include <linux/mfd/core.h>
#include <linux/mfd/stpmic1.h>
#include <linux/module.h>
+#include <linux/reboot.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
@@ -19,7 +20,7 @@
static const struct regmap_range stpmic1_readable_ranges[] = {
regmap_reg_range(TURN_ON_SR, VERSION_SR),
- regmap_reg_range(SWOFF_PWRCTRL_CR, LDO6_STDBY_CR),
+ regmap_reg_range(MAIN_CR, LDO6_STDBY_CR),
regmap_reg_range(BST_SW_CR, BST_SW_CR),
regmap_reg_range(INT_PENDING_R1, INT_PENDING_R4),
regmap_reg_range(INT_CLEAR_R1, INT_CLEAR_R4),
@@ -30,7 +31,7 @@ static const struct regmap_range stpmic1_readable_ranges[] = {
};
static const struct regmap_range stpmic1_writeable_ranges[] = {
- regmap_reg_range(SWOFF_PWRCTRL_CR, LDO6_STDBY_CR),
+ regmap_reg_range(MAIN_CR, LDO6_STDBY_CR),
regmap_reg_range(BST_SW_CR, BST_SW_CR),
regmap_reg_range(INT_CLEAR_R1, INT_CLEAR_R4),
regmap_reg_range(INT_SET_MASK_R1, INT_SET_MASK_R4),
@@ -117,6 +118,16 @@ static const struct regmap_irq_chip stpmic1_regmap_irq_chip = {
.num_irqs = ARRAY_SIZE(stpmic1_irqs),
};
+static int stpmic1_power_off(struct sys_off_data *data)
+{
+ struct stpmic1 *ddata = data->cb_data;
+
+ regmap_update_bits(ddata->regmap, MAIN_CR,
+ SOFTWARE_SWITCH_OFF, SOFTWARE_SWITCH_OFF);
+
+ return NOTIFY_DONE;
+}
+
static int stpmic1_probe(struct i2c_client *i2c)
{
struct stpmic1 *ddata;
@@ -159,6 +170,16 @@ static int stpmic1_probe(struct i2c_client *i2c)
return ret;
}
+ ret = devm_register_sys_off_handler(ddata->dev,
+ SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_DEFAULT,
+ stpmic1_power_off,
+ ddata);
+ if (ret) {
+ dev_err(ddata->dev, "failed to register sys-off handler: %d\n", ret);
+ return ret;
+ }
+
return devm_of_platform_populate(dev);
}
@@ -201,7 +222,7 @@ static struct i2c_driver stpmic1_driver = {
.of_match_table = of_match_ptr(stpmic1_of_match),
.pm = pm_sleep_ptr(&stpmic1_pm),
},
- .probe_new = stpmic1_probe,
+ .probe = stpmic1_probe,
};
module_i2c_driver(stpmic1_driver);
diff --git a/drivers/mfd/stw481x.c b/drivers/mfd/stw481x.c
index 2a8fc9d1c806..f35c3af680dd 100644
--- a/drivers/mfd/stw481x.c
+++ b/drivers/mfd/stw481x.c
@@ -239,7 +239,7 @@ static struct i2c_driver stw481x_driver = {
.name = "stw481x",
.of_match_table = stw481x_match,
},
- .probe_new = stw481x_probe,
+ .probe = stw481x_probe,
.id_table = stw481x_id,
};
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
index cbfe19d1b145..16df64e3c0be 100644
--- a/drivers/mfd/tc3589x.c
+++ b/drivers/mfd/tc3589x.c
@@ -485,7 +485,7 @@ static struct i2c_driver tc3589x_driver = {
.pm = pm_sleep_ptr(&tc3589x_dev_pm_ops),
.of_match_table = of_match_ptr(tc3589x_match),
},
- .probe_new = tc3589x_probe,
+ .probe = tc3589x_probe,
.remove = tc3589x_remove,
.id_table = tc3589x_id,
};
diff --git a/drivers/mfd/ti-lmu.c b/drivers/mfd/ti-lmu.c
index 9921320be255..4f06adad7b5e 100644
--- a/drivers/mfd/ti-lmu.c
+++ b/drivers/mfd/ti-lmu.c
@@ -217,7 +217,7 @@ static const struct i2c_device_id ti_lmu_ids[] = {
MODULE_DEVICE_TABLE(i2c, ti_lmu_ids);
static struct i2c_driver ti_lmu_driver = {
- .probe_new = ti_lmu_probe,
+ .probe = ti_lmu_probe,
.driver = {
.name = "ti-lmu",
.of_match_table = ti_lmu_of_match,
diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
index a66cb911998d..5601f6d0d874 100644
--- a/drivers/mfd/tps6105x.c
+++ b/drivers/mfd/tps6105x.c
@@ -209,7 +209,7 @@ static struct i2c_driver tps6105x_driver = {
.name = "tps6105x",
.of_match_table = tps6105x_of_match,
},
- .probe_new = tps6105x_probe,
+ .probe = tps6105x_probe,
.remove = tps6105x_remove,
.id_table = tps6105x_id,
};
diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c
index fb733288cca3..2b9105295f30 100644
--- a/drivers/mfd/tps65010.c
+++ b/drivers/mfd/tps65010.c
@@ -506,12 +506,8 @@ static void tps65010_remove(struct i2c_client *client)
struct tps65010 *tps = i2c_get_clientdata(client);
struct tps65010_board *board = dev_get_platdata(&client->dev);
- if (board && board->teardown) {
- int status = board->teardown(client, board->context);
- if (status < 0)
- dev_dbg(&client->dev, "board %s %s err %d\n",
- "teardown", client->name, status);
- }
+ if (board && board->teardown)
+ board->teardown(client, &tps->chip);
if (client->irq > 0)
free_irq(client->irq, tps);
cancel_delayed_work_sync(&tps->work);
@@ -619,7 +615,7 @@ static int tps65010_probe(struct i2c_client *client)
tps, DEBUG_FOPS);
/* optionally register GPIOs */
- if (board && board->base != 0) {
+ if (board) {
tps->outmask = board->outmask;
tps->chip.label = client->name;
@@ -632,7 +628,7 @@ static int tps65010_probe(struct i2c_client *client)
/* NOTE: only partial support for inputs; nyet IRQs */
tps->chip.get = tps65010_gpio_get;
- tps->chip.base = board->base;
+ tps->chip.base = -1;
tps->chip.ngpio = 7;
tps->chip.can_sleep = 1;
@@ -641,7 +637,7 @@ static int tps65010_probe(struct i2c_client *client)
dev_err(&client->dev, "can't add gpiochip, err %d\n",
status);
else if (board->setup) {
- status = board->setup(client, board->context);
+ status = board->setup(client, &tps->chip);
if (status < 0) {
dev_dbg(&client->dev,
"board %s %s err %d\n",
@@ -668,7 +664,7 @@ static struct i2c_driver tps65010_driver = {
.driver = {
.name = "tps65010",
},
- .probe_new = tps65010_probe,
+ .probe = tps65010_probe,
.remove = tps65010_remove,
.id_table = tps65010_id,
};
diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c
index 500b594de316..9716bf703c7a 100644
--- a/drivers/mfd/tps6507x.c
+++ b/drivers/mfd/tps6507x.c
@@ -122,7 +122,7 @@ static struct i2c_driver tps6507x_i2c_driver = {
.name = "tps6507x",
.of_match_table = of_match_ptr(tps6507x_of_match),
},
- .probe_new = tps6507x_i2c_probe,
+ .probe = tps6507x_i2c_probe,
.id_table = tps6507x_i2c_id,
};
diff --git a/drivers/mfd/tps65086.c b/drivers/mfd/tps65086.c
index 9494c1d71b86..6a21000aad4a 100644
--- a/drivers/mfd/tps65086.c
+++ b/drivers/mfd/tps65086.c
@@ -129,7 +129,7 @@ static struct i2c_driver tps65086_driver = {
.name = "tps65086",
.of_match_table = tps65086_of_match_table,
},
- .probe_new = tps65086_probe,
+ .probe = tps65086_probe,
.remove = tps65086_remove,
.id_table = tps65086_id_table,
};
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
index af718a9c58b3..a35ad70755fb 100644
--- a/drivers/mfd/tps65090.c
+++ b/drivers/mfd/tps65090.c
@@ -236,7 +236,7 @@ static struct i2c_driver tps65090_driver = {
.suppress_bind_attrs = true,
.of_match_table = of_match_ptr(tps65090_of_match),
},
- .probe_new = tps65090_i2c_probe,
+ .probe = tps65090_i2c_probe,
.id_table = tps65090_id_table,
};
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
index eebd60601b01..60599291b315 100644
--- a/drivers/mfd/tps65217.c
+++ b/drivers/mfd/tps65217.c
@@ -402,7 +402,7 @@ static struct i2c_driver tps65217_driver = {
.of_match_table = tps65217_of_match,
},
.id_table = tps65217_id_table,
- .probe_new = tps65217_probe,
+ .probe = tps65217_probe,
.remove = tps65217_remove,
};
diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c
index ea69dcef91ec..619bf7adb20c 100644
--- a/drivers/mfd/tps65218.c
+++ b/drivers/mfd/tps65218.c
@@ -347,7 +347,7 @@ static struct i2c_driver tps65218_driver = {
.name = "tps65218",
.of_match_table = of_tps65218_match_table,
},
- .probe_new = tps65218_probe,
+ .probe = tps65218_probe,
.id_table = tps65218_id_table,
};
diff --git a/drivers/mfd/tps65219.c b/drivers/mfd/tps65219.c
index 0e402fda206b..0e0c42e4fdfc 100644
--- a/drivers/mfd/tps65219.c
+++ b/drivers/mfd/tps65219.c
@@ -25,13 +25,21 @@ static int tps65219_cold_reset(struct tps65219 *tps)
TPS65219_MFP_COLD_RESET_I2C_CTRL_MASK);
}
-static int tps65219_restart(struct notifier_block *this,
- unsigned long reboot_mode, void *cmd)
+static int tps65219_soft_shutdown(struct tps65219 *tps)
{
- struct tps65219 *tps;
+ return regmap_update_bits(tps->regmap, TPS65219_REG_MFP_CTRL,
+ TPS65219_MFP_I2C_OFF_REQ_MASK,
+ TPS65219_MFP_I2C_OFF_REQ_MASK);
+}
- tps = container_of(this, struct tps65219, nb);
+static int tps65219_power_off_handler(struct sys_off_data *data)
+{
+ tps65219_soft_shutdown(data->cb_data);
+ return NOTIFY_DONE;
+}
+static int tps65219_restart(struct tps65219 *tps, unsigned long reboot_mode)
+{
if (reboot_mode == REBOOT_WARM)
tps65219_warm_reset(tps);
else
@@ -40,10 +48,11 @@ static int tps65219_restart(struct notifier_block *this,
return NOTIFY_DONE;
}
-static struct notifier_block pmic_rst_restart_nb = {
- .notifier_call = tps65219_restart,
- .priority = 200,
-};
+static int tps65219_restart_handler(struct sys_off_data *data)
+{
+ tps65219_restart(data->cb_data, data->mode);
+ return NOTIFY_DONE;
+}
static const struct resource tps65219_pwrbutton_resources[] = {
DEFINE_RES_IRQ_NAMED(TPS65219_INT_PB_FALLING_EDGE_DETECT, "falling"),
@@ -106,7 +115,7 @@ static const struct mfd_cell tps65219_cells[] = {
.resources = tps65219_regulator_resources,
.num_resources = ARRAY_SIZE(tps65219_regulator_resources),
},
- { .name = "tps65219-gpios", },
+ { .name = "tps65219-gpio", },
};
static const struct mfd_cell tps65219_pwrbutton_cell = {
@@ -269,13 +278,22 @@ static int tps65219_probe(struct i2c_client *client)
}
}
- tps->nb = pmic_rst_restart_nb;
- ret = register_restart_handler(&tps->nb);
+ ret = devm_register_restart_handler(tps->dev,
+ tps65219_restart_handler,
+ tps);
+
if (ret) {
dev_err(tps->dev, "cannot register restart handler, %d\n", ret);
return ret;
}
+ ret = devm_register_power_off_handler(tps->dev,
+ tps65219_power_off_handler,
+ tps);
+ if (ret) {
+ dev_err(tps->dev, "failed to register power-off handler: %d\n", ret);
+ return ret;
+ }
return 0;
}
@@ -290,7 +308,7 @@ static struct i2c_driver tps65219_driver = {
.name = "tps65219",
.of_match_table = of_tps65219_match_table,
},
- .probe_new = tps65219_probe,
+ .probe = tps65219_probe,
};
module_i2c_driver(tps65219_driver);
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 90e23232b6b0..55675ceedcd3 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -619,7 +619,7 @@ static struct i2c_driver tps6586x_driver = {
.of_match_table = of_match_ptr(tps6586x_of_match),
.pm = &tps6586x_pm_ops,
},
- .probe_new = tps6586x_i2c_probe,
+ .probe = tps6586x_i2c_probe,
.remove = tps6586x_i2c_remove,
.id_table = tps6586x_id_table,
};
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 821c0277a2ed..41408df1712f 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -535,7 +535,7 @@ static struct i2c_driver tps65910_i2c_driver = {
.name = "tps65910",
.of_match_table = of_match_ptr(tps65910_of_match),
},
- .probe_new = tps65910_i2c_probe,
+ .probe = tps65910_i2c_probe,
.id_table = tps65910_i2c_id,
};
diff --git a/drivers/mfd/tps65912-i2c.c b/drivers/mfd/tps65912-i2c.c
index 1bf945966bf7..3c5ac781b6c1 100644
--- a/drivers/mfd/tps65912-i2c.c
+++ b/drivers/mfd/tps65912-i2c.c
@@ -60,7 +60,7 @@ static struct i2c_driver tps65912_i2c_driver = {
.name = "tps65912",
.of_match_table = tps65912_i2c_of_match_table,
},
- .probe_new = tps65912_i2c_probe,
+ .probe = tps65912_i2c_probe,
.remove = tps65912_i2c_remove,
.id_table = tps65912_i2c_id_table,
};
diff --git a/drivers/mfd/tps6594-i2c.c b/drivers/mfd/tps6594-i2c.c
index 449d5c61bc9f..899c88c0fe77 100644
--- a/drivers/mfd/tps6594-i2c.c
+++ b/drivers/mfd/tps6594-i2c.c
@@ -222,7 +222,7 @@ static int tps6594_i2c_probe(struct i2c_client *client)
match = of_match_device(tps6594_i2c_of_match_table, dev);
if (!match)
- return dev_err_probe(dev, PTR_ERR(match), "Failed to find matching chip ID\n");
+ return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n");
tps->chip_id = (unsigned long)match->data;
crc8_populate_msb(tps6594_i2c_crc_table, TPS6594_CRC8_POLYNOMIAL);
@@ -235,7 +235,7 @@ static struct i2c_driver tps6594_i2c_driver = {
.name = "tps6594",
.of_match_table = tps6594_i2c_of_match_table,
},
- .probe_new = tps6594_i2c_probe,
+ .probe = tps6594_i2c_probe,
};
module_i2c_driver(tps6594_i2c_driver);
diff --git a/drivers/mfd/tps6594-spi.c b/drivers/mfd/tps6594-spi.c
index a938a191744f..f4b4f37f957f 100644
--- a/drivers/mfd/tps6594-spi.c
+++ b/drivers/mfd/tps6594-spi.c
@@ -107,7 +107,7 @@ static int tps6594_spi_probe(struct spi_device *spi)
match = of_match_device(tps6594_spi_of_match_table, dev);
if (!match)
- return dev_err_probe(dev, PTR_ERR(match), "Failed to find matching chip ID\n");
+ return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n");
tps->chip_id = (unsigned long)match->data;
crc8_populate_msb(tps6594_spi_crc_table, TPS6594_CRC8_POLYNOMIAL);
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index e801b7ce010f..ce01a87f8dc3 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -890,7 +890,7 @@ static struct i2c_driver twl_driver = {
.driver.name = DRIVER_NAME,
.driver.pm = &twl_dev_pm_ops,
.id_table = twl_ids,
- .probe_new = twl_probe,
+ .probe = twl_probe,
.remove = twl_remove,
};
builtin_i2c_driver(twl_driver);
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index e982119bbefa..d85675a4d9a8 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -608,7 +608,7 @@ static const struct regmap_config twl6040_regmap_config = {
.volatile_reg = twl6040_volatile_reg,
.writeable_reg = twl6040_writeable_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.use_single_read = true,
.use_single_write = true,
};
@@ -829,7 +829,7 @@ static struct i2c_driver twl6040_driver = {
.driver = {
.name = "twl6040",
},
- .probe_new = twl6040_probe,
+ .probe = twl6040_probe,
.remove = twl6040_remove,
.id_table = twl6040_i2c_id,
};
diff --git a/drivers/mfd/wcd934x.c b/drivers/mfd/wcd934x.c
index 07e884087f2c..6b942d5270c1 100644
--- a/drivers/mfd/wcd934x.c
+++ b/drivers/mfd/wcd934x.c
@@ -227,10 +227,9 @@ static int wcd934x_slim_probe(struct slim_device *sdev)
"Failed to get IRQ\n");
ddata->extclk = devm_clk_get(dev, "extclk");
- if (IS_ERR(ddata->extclk)) {
- dev_err(dev, "Failed to get extclk");
- return PTR_ERR(ddata->extclk);
- }
+ if (IS_ERR(ddata->extclk))
+ return dev_err_probe(dev, PTR_ERR(ddata->extclk),
+ "Failed to get extclk");
ddata->supplies[0].supply = "vdd-buck";
ddata->supplies[1].supply = "vdd-buck-sido";
@@ -239,16 +238,12 @@ static int wcd934x_slim_probe(struct slim_device *sdev)
ddata->supplies[4].supply = "vdd-io";
ret = regulator_bulk_get(dev, WCD934X_MAX_SUPPLY, ddata->supplies);
- if (ret) {
- dev_err(dev, "Failed to get supplies: err = %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get supplies\n");
ret = regulator_bulk_enable(WCD934X_MAX_SUPPLY, ddata->supplies);
- if (ret) {
- dev_err(dev, "Failed to enable supplies: err = %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable supplies\n");
/*
* For WCD934X, it takes about 600us for the Vout_A and
@@ -258,8 +253,9 @@ static int wcd934x_slim_probe(struct slim_device *sdev)
usleep_range(600, 650);
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(reset_gpio)) {
- return dev_err_probe(dev, PTR_ERR(reset_gpio),
- "Failed to get reset gpio: err = %ld\n", PTR_ERR(reset_gpio));
+ ret = dev_err_probe(dev, PTR_ERR(reset_gpio),
+ "Failed to get reset gpio\n");
+ goto err_disable_regulators;
}
msleep(20);
gpiod_set_value(reset_gpio, 1);
@@ -269,6 +265,10 @@ static int wcd934x_slim_probe(struct slim_device *sdev)
dev_set_drvdata(dev, ddata);
return 0;
+
+err_disable_regulators:
+ regulator_bulk_disable(WCD934X_MAX_SUPPLY, ddata->supplies);
+ return ret;
}
static void wcd934x_slim_remove(struct slim_device *sdev)
diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c
index a5d6128fc67d..e2a7fccaed01 100644
--- a/drivers/mfd/wl1273-core.c
+++ b/drivers/mfd/wl1273-core.c
@@ -232,7 +232,7 @@ static struct i2c_driver wl1273_core_driver = {
.driver = {
.name = WL1273_FM_DRIVER_NAME,
},
- .probe_new = wl1273_core_probe,
+ .probe = wl1273_core_probe,
.id_table = wl1273_driver_id_table,
};
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index d2f444d2ae78..e86b6a4896a6 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -1430,7 +1430,7 @@ struct regmap_config wm831x_regmap_config = {
.reg_bits = 16,
.val_bits = 16,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = WM831X_DBE_CHECK_DATA,
.readable_reg = wm831x_reg_readable,
diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c
index 9dbe96e2d46a..997837f13180 100644
--- a/drivers/mfd/wm831x-i2c.c
+++ b/drivers/mfd/wm831x-i2c.c
@@ -102,7 +102,7 @@ static struct i2c_driver wm831x_i2c_driver = {
.of_match_table = of_match_ptr(wm831x_of_match),
.suppress_bind_attrs = true,
},
- .probe_new = wm831x_i2c_probe,
+ .probe = wm831x_i2c_probe,
.id_table = wm831x_i2c_id,
};
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
index 1fa1dfbc9e31..c2a7d7069975 100644
--- a/drivers/mfd/wm8350-i2c.c
+++ b/drivers/mfd/wm8350-i2c.c
@@ -52,7 +52,7 @@ static struct i2c_driver wm8350_i2c_driver = {
.name = "wm8350",
.suppress_bind_attrs = true,
},
- .probe_new = wm8350_i2c_probe,
+ .probe = wm8350_i2c_probe,
.id_table = wm8350_i2c_id,
};
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index 5e1599ac9abc..75483c9be0c4 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -54,8 +54,6 @@ static int wm8400_init(struct wm8400 *wm8400,
unsigned int reg;
int ret;
- dev_set_drvdata(wm8400->dev, wm8400);
-
/* Check that this is actually a WM8400 */
ret = regmap_read(wm8400->regmap, WM8400_RESET_ID, &reg);
if (ret != 0) {
@@ -145,7 +143,7 @@ static struct i2c_driver wm8400_i2c_driver = {
.driver = {
.name = "WM8400",
},
- .probe_new = wm8400_i2c_probe,
+ .probe = wm8400_i2c_probe,
.id_table = wm8400_i2c_id,
};
#endif
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index c419ab0c0eae..1e4f1694f065 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -320,8 +320,6 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
if (ret != 0)
return ret;
- dev_set_drvdata(wm8994->dev, wm8994);
-
/* Add the on-chip regulators first for bootstrapping */
ret = mfd_add_devices(wm8994->dev, 0,
wm8994_regulator_devs,
@@ -672,7 +670,7 @@ static struct i2c_driver wm8994_i2c_driver = {
.pm = pm_ptr(&wm8994_pm_ops),
.of_match_table = wm8994_of_match,
},
- .probe_new = wm8994_i2c_probe,
+ .probe = wm8994_i2c_probe,
.remove = wm8994_i2c_remove,
.id_table = wm8994_i2c_id,
};
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 433aa4197785..75e427f124b2 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -538,6 +538,29 @@ config TMR_INJECT
Say N here unless you know what you are doing.
+config TPS6594_ESM
+ tristate "TI TPS6594 Error Signal Monitor support"
+ depends on MFD_TPS6594
+ default MFD_TPS6594
+ help
+ Support ESM (Error Signal Monitor) on TPS6594 PMIC devices.
+ ESM is used typically to reboot the board in error condition.
+
+ This driver can also be built as a module. If so, the module
+ will be called tps6594-esm.
+
+config TPS6594_PFSM
+ tristate "TI TPS6594 Pre-configurable Finite State Machine support"
+ depends on MFD_TPS6594
+ default MFD_TPS6594
+ help
+ Support PFSM (Pre-configurable Finite State Machine) on TPS6594 PMIC devices.
+ These devices integrate a finite state machine engine, which manages the state
+ of the device during operating state transition.
+
+ This driver can also be built as a module. If so, the module
+ will be called tps6594-pfsm.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 56de43943cd5..f2a4d1ff65d4 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -65,3 +65,5 @@ obj-$(CONFIG_GP_PCI1XXXX) += mchp_pci1xxxx/
obj-$(CONFIG_VCPU_STALL_DETECTOR) += vcpu_stall_detector.o
obj-$(CONFIG_TMR_MANAGER) += xilinx_tmr_manager.o
obj-$(CONFIG_TMR_INJECT) += xilinx_tmr_inject.o
+obj-$(CONFIG_TPS6594_ESM) += tps6594-esm.o
+obj-$(CONFIG_TPS6594_PFSM) += tps6594-pfsm.o
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
index 3856d5c04c5f..469478f7a1d3 100644
--- a/drivers/misc/ad525x_dpot-i2c.c
+++ b/drivers/misc/ad525x_dpot-i2c.c
@@ -106,7 +106,7 @@ static struct i2c_driver ad_dpot_i2c_driver = {
.driver = {
.name = "ad_dpot",
},
- .probe_new = ad_dpot_i2c_probe,
+ .probe = ad_dpot_i2c_probe,
.remove = ad_dpot_i2c_remove,
.id_table = ad_dpot_id,
};
diff --git a/drivers/misc/altera-stapl/Makefile b/drivers/misc/altera-stapl/Makefile
index dd0f8189666b..90f18e7bf9b0 100644
--- a/drivers/misc/altera-stapl/Makefile
+++ b/drivers/misc/altera-stapl/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
-altera-stapl-objs = altera-lpt.o altera-jtag.o altera-comp.o altera.o
+altera-stapl-y = altera-jtag.o altera-comp.o altera.o
+altera-stapl-$(CONFIG_HAS_IOPORT) += altera-lpt.o
obj-$(CONFIG_ALTERA_STAPL) += altera-stapl.o
diff --git a/drivers/misc/altera-stapl/altera.c b/drivers/misc/altera-stapl/altera.c
index a58b7cb81d98..587427b73914 100644
--- a/drivers/misc/altera-stapl/altera.c
+++ b/drivers/misc/altera-stapl/altera.c
@@ -2407,6 +2407,10 @@ int altera_init(struct altera_config *config, const struct firmware *fw)
astate->config = config;
if (!astate->config->jtag_io) {
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT)) {
+ retval = -ENODEV;
+ goto free_state;
+ }
dprintk("%s: using byteblaster!\n", __func__);
astate->config->jtag_io = netup_jtag_io_lpt;
}
@@ -2481,7 +2485,7 @@ int altera_init(struct altera_config *config, const struct firmware *fw)
} else if (exec_result)
printk(KERN_ERR "%s: error %d\n", __func__, exec_result);
-
+free_state:
kfree(astate);
free_value:
kfree(value);
diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c
index 0526c55d5cd5..693f0e539f37 100644
--- a/drivers/misc/apds9802als.c
+++ b/drivers/misc/apds9802als.c
@@ -296,7 +296,7 @@ static struct i2c_driver apds9802als_driver = {
.name = DRIVER_NAME,
.pm = APDS9802ALS_PM_OPS,
},
- .probe_new = apds9802als_probe,
+ .probe = apds9802als_probe,
.remove = apds9802als_remove,
.id_table = apds9802als_id,
};
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
index 0024503ea6db..92b92be91d60 100644
--- a/drivers/misc/apds990x.c
+++ b/drivers/misc/apds990x.c
@@ -1267,11 +1267,11 @@ static const struct dev_pm_ops apds990x_pm_ops = {
};
static struct i2c_driver apds990x_driver = {
- .driver = {
+ .driver = {
.name = "apds990x",
.pm = &apds990x_pm_ops,
},
- .probe_new = apds990x_probe,
+ .probe = apds990x_probe,
.remove = apds990x_remove,
.id_table = apds990x_id,
};
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
index bedbe0efb330..1629b62fd052 100644
--- a/drivers/misc/bh1770glc.c
+++ b/drivers/misc/bh1770glc.c
@@ -1374,11 +1374,11 @@ static const struct dev_pm_ops bh1770_pm_ops = {
};
static struct i2c_driver bh1770_driver = {
- .driver = {
+ .driver = {
.name = "bh1770glc",
.pm = &bh1770_pm_ops,
},
- .probe_new = bh1770_probe,
+ .probe = bh1770_probe,
.remove = bh1770_remove,
.id_table = bh1770_id,
};
diff --git a/drivers/misc/ds1682.c b/drivers/misc/ds1682.c
index d517eed32971..21fc5bc85c5c 100644
--- a/drivers/misc/ds1682.c
+++ b/drivers/misc/ds1682.c
@@ -250,7 +250,7 @@ static struct i2c_driver ds1682_driver = {
.name = "ds1682",
.of_match_table = ds1682_of_match,
},
- .probe_new = ds1682_probe,
+ .probe = ds1682_probe,
.remove = ds1682_remove,
.id_table = ds1682_id,
};
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 938c4f41b98c..dbbf7db4ff2f 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -761,7 +761,8 @@ static int at24_probe(struct i2c_client *client)
pm_runtime_disable(dev);
if (!pm_runtime_status_suspended(dev))
regulator_disable(at24->vcc_reg);
- return PTR_ERR(at24->nvmem);
+ return dev_err_probe(dev, PTR_ERR(at24->nvmem),
+ "failed to register nvmem\n");
}
/*
@@ -832,7 +833,7 @@ static struct i2c_driver at24_driver = {
.of_match_table = at24_of_match,
.acpi_match_table = ACPI_PTR(at24_acpi_ids),
},
- .probe_new = at24_probe,
+ .probe = at24_probe,
.remove = at24_remove,
.id_table = at24_ids,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c
index c8c6deb7ed89..a1acd77130f2 100644
--- a/drivers/misc/eeprom/ee1004.c
+++ b/drivers/misc/eeprom/ee1004.c
@@ -234,7 +234,7 @@ static struct i2c_driver ee1004_driver = {
.name = "ee1004",
.dev_groups = ee1004_groups,
},
- .probe_new = ee1004_probe,
+ .probe = ee1004_probe,
.remove = ee1004_remove,
.id_table = ee1004_ids,
};
diff --git a/drivers/misc/eeprom/eeprom.c b/drivers/misc/eeprom/eeprom.c
index 32611100d5cd..ccb7c2f7ee2f 100644
--- a/drivers/misc/eeprom/eeprom.c
+++ b/drivers/misc/eeprom/eeprom.c
@@ -196,7 +196,7 @@ static struct i2c_driver eeprom_driver = {
.driver = {
.name = "eeprom",
},
- .probe_new = eeprom_probe,
+ .probe = eeprom_probe,
.remove = eeprom_remove,
.id_table = eeprom_id,
diff --git a/drivers/misc/eeprom/idt_89hpesx.c b/drivers/misc/eeprom/idt_89hpesx.c
index 7075d0b37881..740c06382b83 100644
--- a/drivers/misc/eeprom/idt_89hpesx.c
+++ b/drivers/misc/eeprom/idt_89hpesx.c
@@ -1556,7 +1556,7 @@ static struct i2c_driver idt_driver = {
.name = IDT_NAME,
.of_match_table = idt_of_match,
},
- .probe_new = idt_probe,
+ .probe = idt_probe,
.remove = idt_remove,
.id_table = idt_ids,
};
diff --git a/drivers/misc/eeprom/max6875.c b/drivers/misc/eeprom/max6875.c
index 79cf8afcef2e..cb6b1efeafe0 100644
--- a/drivers/misc/eeprom/max6875.c
+++ b/drivers/misc/eeprom/max6875.c
@@ -192,7 +192,7 @@ static struct i2c_driver max6875_driver = {
.driver = {
.name = "max6875",
},
- .probe_new = max6875_probe,
+ .probe = max6875_probe,
.remove = max6875_remove,
.id_table = max6875_id,
};
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 30d4d0476248..9666d28037e1 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -1437,7 +1437,7 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl,
sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE, 4, 0);
if (init.attrs)
- sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 6, 0);
+ sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 4, 0);
err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
sc, args);
@@ -2225,6 +2225,9 @@ static int fastrpc_device_register(struct device *dev, struct fastrpc_channel_ct
fdev->miscdev.fops = &fastrpc_fops;
fdev->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "fastrpc-%s%s",
domain, is_secured ? "-secure" : "");
+ if (!fdev->miscdev.name)
+ return -ENOMEM;
+
err = misc_register(&fdev->miscdev);
if (!err) {
if (is_secured)
diff --git a/drivers/misc/hmc6352.c b/drivers/misc/hmc6352.c
index 8967940ecd1e..759eaeb64307 100644
--- a/drivers/misc/hmc6352.c
+++ b/drivers/misc/hmc6352.c
@@ -131,7 +131,7 @@ static struct i2c_driver hmc6352_driver = {
.driver = {
.name = "hmc6352",
},
- .probe_new = hmc6352_probe,
+ .probe = hmc6352_probe,
.remove = hmc6352_remove,
.id_table = hmc6352_id,
};
diff --git a/drivers/misc/ics932s401.c b/drivers/misc/ics932s401.c
index 12108a7b9b40..ee6296b98078 100644
--- a/drivers/misc/ics932s401.c
+++ b/drivers/misc/ics932s401.c
@@ -105,7 +105,7 @@ static struct i2c_driver ics932s401_driver = {
.driver = {
.name = "ics932s401",
},
- .probe_new = ics932s401_probe,
+ .probe = ics932s401_probe,
.remove = ics932s401_remove,
.id_table = ics932s401_id,
.detect = ics932s401_detect,
diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c
index 147b58f7968d..ebf0635aee64 100644
--- a/drivers/misc/isl29003.c
+++ b/drivers/misc/isl29003.c
@@ -459,7 +459,7 @@ static struct i2c_driver isl29003_driver = {
.name = ISL29003_DRV_NAME,
.pm = ISL29003_PM_OPS,
},
- .probe_new = isl29003_probe,
+ .probe = isl29003_probe,
.remove = isl29003_remove,
.id_table = isl29003_id,
};
diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c
index 3be02093368c..c5976fa8c825 100644
--- a/drivers/misc/isl29020.c
+++ b/drivers/misc/isl29020.c
@@ -214,7 +214,7 @@ static struct i2c_driver isl29020_driver = {
.name = "isl29020",
.pm = ISL29020_PM_OPS,
},
- .probe_new = isl29020_probe,
+ .probe = isl29020_probe,
.remove = isl29020_remove,
.id_table = isl29020_id,
};
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
index 7071412d6bf6..3882e97e96a7 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
@@ -262,7 +262,7 @@ static struct i2c_driver lis3lv02d_i2c_driver = {
.pm = &lis3_pm_ops,
.of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids),
},
- .probe_new = lis3lv02d_i2c_probe,
+ .probe = lis3lv02d_i2c_probe,
.remove = lis3lv02d_i2c_remove,
.id_table = lis3lv02d_id,
};
diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c
index b4712ff196b4..0772e4a4757e 100644
--- a/drivers/misc/lkdtm/core.c
+++ b/drivers/misc/lkdtm/core.c
@@ -79,7 +79,7 @@ static struct crashpoint crashpoints[] = {
CRASHPOINT("INT_HARDWARE_ENTRY", "do_IRQ"),
CRASHPOINT("INT_HW_IRQ_EN", "handle_irq_event"),
CRASHPOINT("INT_TASKLET_ENTRY", "tasklet_action"),
- CRASHPOINT("FS_DEVRW", "ll_rw_block"),
+ CRASHPOINT("FS_SUBMIT_BH", "submit_bh"),
CRASHPOINT("MEM_SWAPOUT", "shrink_inactive_list"),
CRASHPOINT("TIMERADD", "hrtimer_start"),
CRASHPOINT("SCSI_QUEUE_RQ", "scsi_queue_rq"),
diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index d21486d69df2..37db142de413 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -62,4 +62,4 @@ config INTEL_MEI_GSC
source "drivers/misc/mei/hdcp/Kconfig"
source "drivers/misc/mei/pxp/Kconfig"
-
+source "drivers/misc/mei/gsc_proxy/Kconfig"
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index fb740d754900..14aee253ae48 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -30,3 +30,4 @@ CFLAGS_mei-trace.o = -I$(src)
obj-$(CONFIG_INTEL_MEI_HDCP) += hdcp/
obj-$(CONFIG_INTEL_MEI_PXP) += pxp/
+obj-$(CONFIG_INTEL_MEI_GSC_PROXY) += gsc_proxy/
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 31e3c74ca1f1..b8b716faf192 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -108,7 +108,7 @@ struct mkhi_fw_ver {
static int mei_osver(struct mei_cl_device *cldev)
{
const size_t size = MKHI_OSVER_BUF_LEN;
- char buf[MKHI_OSVER_BUF_LEN];
+ u8 buf[MKHI_OSVER_BUF_LEN];
struct mkhi_msg *req;
struct mkhi_fwcaps *fwcaps;
struct mei_os_ver *os_ver;
@@ -137,7 +137,7 @@ static int mei_osver(struct mei_cl_device *cldev)
sizeof(struct mkhi_fw_ver_block) * (__num))
static int mei_fwver(struct mei_cl_device *cldev)
{
- char buf[MKHI_FWVER_BUF_LEN];
+ u8 buf[MKHI_FWVER_BUF_LEN];
struct mkhi_msg req;
struct mkhi_msg *rsp;
struct mkhi_fw_ver *fwver;
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 5d7a68674d9b..33ec6424dfee 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -1046,9 +1046,6 @@ static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
const struct mei_cl_driver *cldrv = to_mei_cl_driver(drv);
const struct mei_cl_device_id *found_id;
- if (!cldev)
- return 0;
-
if (!cldev->do_match)
return 0;
@@ -1079,9 +1076,6 @@ static int mei_cl_device_probe(struct device *dev)
cldev = to_mei_cl_device(dev);
cldrv = to_mei_cl_driver(dev->driver);
- if (!cldev)
- return 0;
-
if (!cldrv || !cldrv->probe)
return -ENODEV;
@@ -1276,9 +1270,6 @@ static void mei_cl_bus_dev_release(struct device *dev)
{
struct mei_cl_device *cldev = to_mei_cl_device(dev);
- if (!cldev)
- return;
-
mei_cl_flush_queues(cldev->cl, NULL);
mei_me_cl_put(cldev->me_cl);
mei_dev_bus_put(cldev->bus);
diff --git a/drivers/misc/mei/gsc_proxy/Kconfig b/drivers/misc/mei/gsc_proxy/Kconfig
new file mode 100644
index 000000000000..5f68d9f3d691
--- /dev/null
+++ b/drivers/misc/mei/gsc_proxy/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2022-2023, Intel Corporation. All rights reserved.
+#
+config INTEL_MEI_GSC_PROXY
+ tristate "Intel GSC Proxy services of ME Interface"
+ select INTEL_MEI_ME
+ depends on DRM_I915
+ help
+ MEI Support for GSC Proxy Services on Intel platforms.
+
+ MEI GSC proxy enables messaging between GSC service on
+ Intel graphics card and services on CSE (MEI) firmware
+ residing SoC or PCH.
+
diff --git a/drivers/misc/mei/gsc_proxy/Makefile b/drivers/misc/mei/gsc_proxy/Makefile
new file mode 100644
index 000000000000..358847e9aaa9
--- /dev/null
+++ b/drivers/misc/mei/gsc_proxy/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2022-2023, Intel Corporation. All rights reserved.
+#
+# Makefile - GSC Proxy client driver for Intel MEI Bus Driver.
+
+obj-$(CONFIG_INTEL_MEI_GSC_PROXY) += mei_gsc_proxy.o
diff --git a/drivers/misc/mei/gsc_proxy/mei_gsc_proxy.c b/drivers/misc/mei/gsc_proxy/mei_gsc_proxy.c
new file mode 100644
index 000000000000..be52b113aea9
--- /dev/null
+++ b/drivers/misc/mei/gsc_proxy/mei_gsc_proxy.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022-2023 Intel Corporation
+ */
+
+/**
+ * DOC: MEI_GSC_PROXY Client Driver
+ *
+ * The mei_gsc_proxy driver acts as a translation layer between
+ * proxy user (I915) and ME FW by proxying messages to ME FW
+ */
+
+#include <linux/component.h>
+#include <linux/mei_cl_bus.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/uuid.h>
+#include <drm/drm_connector.h>
+#include <drm/i915_component.h>
+#include <drm/i915_gsc_proxy_mei_interface.h>
+
+/**
+ * mei_gsc_proxy_send - Sends a proxy message to ME FW.
+ * @dev: device corresponding to the mei_cl_device
+ * @buf: a message buffer to send
+ * @size: size of the message
+ * Return: bytes sent on Success, <0 on Failure
+ */
+static int mei_gsc_proxy_send(struct device *dev, const void *buf, size_t size)
+{
+ ssize_t ret;
+
+ if (!dev || !buf)
+ return -EINVAL;
+
+ ret = mei_cldev_send(to_mei_cl_device(dev), buf, size);
+ if (ret < 0)
+ dev_dbg(dev, "mei_cldev_send failed. %zd\n", ret);
+
+ return ret;
+}
+
+/**
+ * mei_gsc_proxy_recv - Receives a proxy message from ME FW.
+ * @dev: device corresponding to the mei_cl_device
+ * @buf: a message buffer to contain the received message
+ * @size: size of the buffer
+ * Return: bytes received on Success, <0 on Failure
+ */
+static int mei_gsc_proxy_recv(struct device *dev, void *buf, size_t size)
+{
+ ssize_t ret;
+
+ if (!dev || !buf)
+ return -EINVAL;
+
+ ret = mei_cldev_recv(to_mei_cl_device(dev), buf, size);
+ if (ret < 0)
+ dev_dbg(dev, "mei_cldev_recv failed. %zd\n", ret);
+
+ return ret;
+}
+
+static const struct i915_gsc_proxy_component_ops mei_gsc_proxy_ops = {
+ .owner = THIS_MODULE,
+ .send = mei_gsc_proxy_send,
+ .recv = mei_gsc_proxy_recv,
+};
+
+static int mei_component_master_bind(struct device *dev)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ struct i915_gsc_proxy_component *comp_master = mei_cldev_get_drvdata(cldev);
+
+ comp_master->ops = &mei_gsc_proxy_ops;
+ comp_master->mei_dev = dev;
+ return component_bind_all(dev, comp_master);
+}
+
+static void mei_component_master_unbind(struct device *dev)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ struct i915_gsc_proxy_component *comp_master = mei_cldev_get_drvdata(cldev);
+
+ component_unbind_all(dev, comp_master);
+}
+
+static const struct component_master_ops mei_component_master_ops = {
+ .bind = mei_component_master_bind,
+ .unbind = mei_component_master_unbind,
+};
+
+/**
+ * mei_gsc_proxy_component_match - compare function for matching mei.
+ *
+ * The function checks if the device is pci device and
+ * Intel VGA adapter, the subcomponent is SW Proxy
+ * and the parent of MEI PCI and the parent of VGA are the same PCH device.
+ *
+ * @dev: master device
+ * @subcomponent: subcomponent to match (I915_COMPONENT_SWPROXY)
+ * @data: compare data (mei pci parent)
+ *
+ * Return:
+ * * 1 - if components match
+ * * 0 - otherwise
+ */
+static int mei_gsc_proxy_component_match(struct device *dev, int subcomponent,
+ void *data)
+{
+ struct pci_dev *pdev;
+
+ if (!dev_is_pci(dev))
+ return 0;
+
+ pdev = to_pci_dev(dev);
+
+ if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8) ||
+ pdev->vendor != PCI_VENDOR_ID_INTEL)
+ return 0;
+
+ if (subcomponent != I915_COMPONENT_GSC_PROXY)
+ return 0;
+
+ return component_compare_dev(dev->parent, ((struct device *)data)->parent);
+}
+
+static int mei_gsc_proxy_probe(struct mei_cl_device *cldev,
+ const struct mei_cl_device_id *id)
+{
+ struct i915_gsc_proxy_component *comp_master;
+ struct component_match *master_match = NULL;
+ int ret;
+
+ ret = mei_cldev_enable(cldev);
+ if (ret < 0) {
+ dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
+ goto enable_err_exit;
+ }
+
+ comp_master = kzalloc(sizeof(*comp_master), GFP_KERNEL);
+ if (!comp_master) {
+ ret = -ENOMEM;
+ goto err_exit;
+ }
+
+ component_match_add_typed(&cldev->dev, &master_match,
+ mei_gsc_proxy_component_match, cldev->dev.parent);
+ if (IS_ERR_OR_NULL(master_match)) {
+ ret = -ENOMEM;
+ goto err_exit;
+ }
+
+ mei_cldev_set_drvdata(cldev, comp_master);
+ ret = component_master_add_with_match(&cldev->dev,
+ &mei_component_master_ops,
+ master_match);
+ if (ret < 0) {
+ dev_err(&cldev->dev, "Master comp add failed %d\n", ret);
+ goto err_exit;
+ }
+
+ return 0;
+
+err_exit:
+ mei_cldev_set_drvdata(cldev, NULL);
+ kfree(comp_master);
+ mei_cldev_disable(cldev);
+enable_err_exit:
+ return ret;
+}
+
+static void mei_gsc_proxy_remove(struct mei_cl_device *cldev)
+{
+ struct i915_gsc_proxy_component *comp_master = mei_cldev_get_drvdata(cldev);
+ int ret;
+
+ component_master_del(&cldev->dev, &mei_component_master_ops);
+ kfree(comp_master);
+ mei_cldev_set_drvdata(cldev, NULL);
+
+ ret = mei_cldev_disable(cldev);
+ if (ret)
+ dev_warn(&cldev->dev, "mei_cldev_disable() failed %d\n", ret);
+}
+
+#define MEI_UUID_GSC_PROXY UUID_LE(0xf73db04, 0x97ab, 0x4125, \
+ 0xb8, 0x93, 0xe9, 0x4, 0xad, 0xd, 0x54, 0x64)
+
+static struct mei_cl_device_id mei_gsc_proxy_tbl[] = {
+ { .uuid = MEI_UUID_GSC_PROXY, .version = MEI_CL_VERSION_ANY },
+ { }
+};
+MODULE_DEVICE_TABLE(mei, mei_gsc_proxy_tbl);
+
+static struct mei_cl_driver mei_gsc_proxy_driver = {
+ .id_table = mei_gsc_proxy_tbl,
+ .name = KBUILD_MODNAME,
+ .probe = mei_gsc_proxy_probe,
+ .remove = mei_gsc_proxy_remove,
+};
+
+module_mei_cl_driver(mei_gsc_proxy_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MEI GSC PROXY");
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 85cbfc3413ee..51359cc5ece9 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -735,13 +735,13 @@ static const struct i915_hdcp_ops mei_hdcp_ops = {
static int mei_component_master_bind(struct device *dev)
{
struct mei_cl_device *cldev = to_mei_cl_device(dev);
- struct i915_hdcp_master *comp_master = mei_cldev_get_drvdata(cldev);
+ struct i915_hdcp_arbiter *comp_arbiter = mei_cldev_get_drvdata(cldev);
int ret;
dev_dbg(dev, "%s\n", __func__);
- comp_master->ops = &mei_hdcp_ops;
- comp_master->hdcp_dev = dev;
- ret = component_bind_all(dev, comp_master);
+ comp_arbiter->ops = &mei_hdcp_ops;
+ comp_arbiter->hdcp_dev = dev;
+ ret = component_bind_all(dev, comp_arbiter);
if (ret < 0)
return ret;
@@ -751,10 +751,10 @@ static int mei_component_master_bind(struct device *dev)
static void mei_component_master_unbind(struct device *dev)
{
struct mei_cl_device *cldev = to_mei_cl_device(dev);
- struct i915_hdcp_master *comp_master = mei_cldev_get_drvdata(cldev);
+ struct i915_hdcp_arbiter *comp_arbiter = mei_cldev_get_drvdata(cldev);
dev_dbg(dev, "%s\n", __func__);
- component_unbind_all(dev, comp_master);
+ component_unbind_all(dev, comp_arbiter);
}
static const struct component_master_ops mei_component_master_ops = {
@@ -799,7 +799,7 @@ static int mei_hdcp_component_match(struct device *dev, int subcomponent,
static int mei_hdcp_probe(struct mei_cl_device *cldev,
const struct mei_cl_device_id *id)
{
- struct i915_hdcp_master *comp_master;
+ struct i915_hdcp_arbiter *comp_arbiter;
struct component_match *master_match;
int ret;
@@ -809,8 +809,8 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev,
goto enable_err_exit;
}
- comp_master = kzalloc(sizeof(*comp_master), GFP_KERNEL);
- if (!comp_master) {
+ comp_arbiter = kzalloc(sizeof(*comp_arbiter), GFP_KERNEL);
+ if (!comp_arbiter) {
ret = -ENOMEM;
goto err_exit;
}
@@ -823,7 +823,7 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev,
goto err_exit;
}
- mei_cldev_set_drvdata(cldev, comp_master);
+ mei_cldev_set_drvdata(cldev, comp_arbiter);
ret = component_master_add_with_match(&cldev->dev,
&mei_component_master_ops,
master_match);
@@ -836,7 +836,7 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev,
err_exit:
mei_cldev_set_drvdata(cldev, NULL);
- kfree(comp_master);
+ kfree(comp_arbiter);
mei_cldev_disable(cldev);
enable_err_exit:
return ret;
@@ -844,11 +844,11 @@ enable_err_exit:
static void mei_hdcp_remove(struct mei_cl_device *cldev)
{
- struct i915_hdcp_master *comp_master = mei_cldev_get_drvdata(cldev);
+ struct i915_hdcp_arbiter *comp_arbiter = mei_cldev_get_drvdata(cldev);
int ret;
component_master_del(&cldev->dev, &mei_component_master_ops);
- kfree(comp_master);
+ kfree(comp_arbiter);
mei_cldev_set_drvdata(cldev, NULL);
ret = mei_cldev_disable(cldev);
diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index a7244de081ec..ed4d0ef5e5c3 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -159,10 +159,7 @@ static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id)
if (reg & STATUS_IRQ_RAISED) {
test->last_irq = irq;
complete(&test->irq_raised);
- reg &= ~STATUS_IRQ_RAISED;
}
- pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS,
- reg);
return IRQ_HANDLED;
}
@@ -316,21 +313,17 @@ static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
struct pci_dev *pdev = test->pdev;
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE,
- msix == false ? IRQ_TYPE_MSI :
- IRQ_TYPE_MSIX);
+ msix ? IRQ_TYPE_MSIX : IRQ_TYPE_MSI);
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, msi_num);
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
- msix == false ? COMMAND_RAISE_MSI_IRQ :
- COMMAND_RAISE_MSIX_IRQ);
+ msix ? COMMAND_RAISE_MSIX_IRQ :
+ COMMAND_RAISE_MSI_IRQ);
val = wait_for_completion_timeout(&test->irq_raised,
msecs_to_jiffies(1000));
if (!val)
return false;
- if (pci_irq_vector(pdev, msi_num - 1) == test->last_irq)
- return true;
-
- return false;
+ return pci_irq_vector(pdev, msi_num - 1) == test->last_irq;
}
static int pci_endpoint_test_validate_xfer_params(struct device *dev,
@@ -729,6 +722,10 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
struct pci_dev *pdev = test->pdev;
mutex_lock(&test->mutex);
+
+ reinit_completion(&test->irq_raised);
+ test->last_irq = -ENODATA;
+
switch (cmd) {
case PCITEST_BAR:
bar = arg;
@@ -938,6 +935,9 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev)
if (id < 0)
return;
+ pci_endpoint_test_release_irq(test);
+ pci_endpoint_test_free_irq_vectors(test);
+
misc_deregister(&test->miscdev);
kfree(misc_device->name);
kfree(test->name);
@@ -947,9 +947,6 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev)
pci_iounmap(pdev, test->bar[bar]);
}
- pci_endpoint_test_release_irq(test);
- pci_endpoint_test_free_irq_vectors(test);
-
pci_release_regions(pdev);
pci_disable_device(pdev);
}
diff --git a/drivers/misc/smpro-errmon.c b/drivers/misc/smpro-errmon.c
index a1f0b2c77fac..c12035a46585 100644
--- a/drivers/misc/smpro-errmon.c
+++ b/drivers/misc/smpro-errmon.c
@@ -6,7 +6,6 @@
*
*/
-#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index 99413310956b..5757adf418b1 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -235,10 +235,11 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
goto err_chunks;
}
if (!label)
- label = child->name;
-
- block->label = devm_kstrdup(sram->dev,
- label, GFP_KERNEL);
+ block->label = devm_kasprintf(sram->dev, GFP_KERNEL,
+ "%s", dev_name(sram->dev));
+ else
+ block->label = devm_kstrdup(sram->dev,
+ label, GFP_KERNEL);
if (!block->label) {
ret = -ENOMEM;
goto err_chunks;
diff --git a/drivers/misc/tps6594-esm.c b/drivers/misc/tps6594-esm.c
new file mode 100644
index 000000000000..b488f704f104
--- /dev/null
+++ b/drivers/misc/tps6594-esm.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ESM (Error Signal Monitor) driver for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/tps6594.h>
+
+static irqreturn_t tps6594_esm_isr(int irq, void *dev_id)
+{
+ struct platform_device *pdev = dev_id;
+ int i;
+
+ for (i = 0 ; i < pdev->num_resources ; i++) {
+ if (irq == platform_get_irq_byname(pdev, pdev->resource[i].name)) {
+ dev_err(pdev->dev.parent, "%s error detected\n", pdev->resource[i].name);
+ return IRQ_HANDLED;
+ }
+ }
+
+ return IRQ_NONE;
+}
+
+static int tps6594_esm_probe(struct platform_device *pdev)
+{
+ struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+ struct device *dev = &pdev->dev;
+ int irq;
+ int ret;
+ int i;
+
+ for (i = 0 ; i < pdev->num_resources ; i++) {
+ irq = platform_get_irq_byname(pdev, pdev->resource[i].name);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "Failed to get %s irq\n",
+ pdev->resource[i].name);
+
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ tps6594_esm_isr, IRQF_ONESHOT,
+ pdev->resource[i].name, pdev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to request irq\n");
+ }
+
+ ret = regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_MODE_CFG,
+ TPS6594_BIT_ESM_SOC_EN | TPS6594_BIT_ESM_SOC_ENDRV);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to configure ESM\n");
+
+ ret = regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
+ TPS6594_BIT_ESM_SOC_START);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to start ESM\n");
+
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+
+ return 0;
+}
+
+static int tps6594_esm_remove(struct platform_device *pdev)
+{
+ struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
+ TPS6594_BIT_ESM_SOC_START);
+ if (ret) {
+ dev_err(dev, "Failed to stop ESM\n");
+ goto out;
+ }
+
+ ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_MODE_CFG,
+ TPS6594_BIT_ESM_SOC_EN | TPS6594_BIT_ESM_SOC_ENDRV);
+ if (ret)
+ dev_err(dev, "Failed to unconfigure ESM\n");
+
+out:
+ pm_runtime_put_sync(dev);
+ pm_runtime_disable(dev);
+
+ return ret;
+}
+
+static int tps6594_esm_suspend(struct device *dev)
+{
+ struct tps6594 *tps = dev_get_drvdata(dev->parent);
+ int ret;
+
+ ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
+ TPS6594_BIT_ESM_SOC_START);
+
+ pm_runtime_put_sync(dev);
+
+ return ret;
+}
+
+static int tps6594_esm_resume(struct device *dev)
+{
+ struct tps6594 *tps = dev_get_drvdata(dev->parent);
+
+ pm_runtime_get_sync(dev);
+
+ return regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
+ TPS6594_BIT_ESM_SOC_START);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(tps6594_esm_pm_ops, tps6594_esm_suspend, tps6594_esm_resume);
+
+static struct platform_driver tps6594_esm_driver = {
+ .driver = {
+ .name = "tps6594-esm",
+ .pm = pm_sleep_ptr(&tps6594_esm_pm_ops),
+ },
+ .probe = tps6594_esm_probe,
+ .remove = tps6594_esm_remove,
+};
+
+module_platform_driver(tps6594_esm_driver);
+
+MODULE_ALIAS("platform:tps6594-esm");
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 Error Signal Monitor Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/tps6594-pfsm.c b/drivers/misc/tps6594-pfsm.c
new file mode 100644
index 000000000000..5223d1580807
--- /dev/null
+++ b/drivers/misc/tps6594-pfsm.c
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PFSM (Pre-configurable Finite State Machine) driver for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/tps6594.h>
+
+#include <linux/tps6594_pfsm.h>
+
+#define TPS6594_STARTUP_DEST_MCU_ONLY_VAL 2
+#define TPS6594_STARTUP_DEST_ACTIVE_VAL 3
+#define TPS6594_STARTUP_DEST_SHIFT 5
+#define TPS6594_STARTUP_DEST_MCU_ONLY (TPS6594_STARTUP_DEST_MCU_ONLY_VAL \
+ << TPS6594_STARTUP_DEST_SHIFT)
+#define TPS6594_STARTUP_DEST_ACTIVE (TPS6594_STARTUP_DEST_ACTIVE_VAL \
+ << TPS6594_STARTUP_DEST_SHIFT)
+
+/*
+ * To update the PMIC firmware, the user must be able to access
+ * page 0 (user registers) and page 1 (NVM control and configuration).
+ */
+#define TPS6594_PMIC_MAX_POS 0x200
+
+#define TPS6594_FILE_TO_PFSM(f) container_of((f)->private_data, struct tps6594_pfsm, miscdev)
+
+/**
+ * struct tps6594_pfsm - device private data structure
+ *
+ * @miscdev: misc device infos
+ * @regmap: regmap for accessing the device registers
+ */
+struct tps6594_pfsm {
+ struct miscdevice miscdev;
+ struct regmap *regmap;
+};
+
+static ssize_t tps6594_pfsm_read(struct file *f, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f);
+ loff_t pos = *ppos;
+ unsigned int val;
+ int ret;
+ int i;
+
+ if (pos < 0)
+ return -EINVAL;
+ if (pos >= TPS6594_PMIC_MAX_POS)
+ return 0;
+ if (count > TPS6594_PMIC_MAX_POS - pos)
+ count = TPS6594_PMIC_MAX_POS - pos;
+
+ for (i = 0 ; i < count ; i++) {
+ ret = regmap_read(pfsm->regmap, pos + i, &val);
+ if (ret)
+ return ret;
+
+ if (put_user(val, buf + i))
+ return -EFAULT;
+ }
+
+ *ppos = pos + count;
+
+ return count;
+}
+
+static ssize_t tps6594_pfsm_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f);
+ loff_t pos = *ppos;
+ char val;
+ int ret;
+ int i;
+
+ if (pos < 0)
+ return -EINVAL;
+ if (pos >= TPS6594_PMIC_MAX_POS || !count)
+ return 0;
+ if (count > TPS6594_PMIC_MAX_POS - pos)
+ count = TPS6594_PMIC_MAX_POS - pos;
+
+ for (i = 0 ; i < count ; i++) {
+ if (get_user(val, buf + i))
+ return -EFAULT;
+
+ ret = regmap_write(pfsm->regmap, pos + i, val);
+ if (ret)
+ return ret;
+ }
+
+ *ppos = pos + count;
+
+ return count;
+}
+
+static int tps6594_pfsm_configure_ret_trig(struct regmap *regmap, u8 gpio_ret, u8 ddr_ret)
+{
+ int ret;
+
+ if (gpio_ret)
+ ret = regmap_set_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+ TPS6594_BIT_TRIGGER_I2C(5) | TPS6594_BIT_TRIGGER_I2C(6));
+ else
+ ret = regmap_clear_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+ TPS6594_BIT_TRIGGER_I2C(5) | TPS6594_BIT_TRIGGER_I2C(6));
+ if (ret)
+ return ret;
+
+ if (ddr_ret)
+ ret = regmap_set_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+ TPS6594_BIT_TRIGGER_I2C(7));
+ else
+ ret = regmap_clear_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+ TPS6594_BIT_TRIGGER_I2C(7));
+
+ return ret;
+}
+
+static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+ struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f);
+ struct pmic_state_opt state_opt;
+ void __user *argp = (void __user *)arg;
+ int ret = -ENOIOCTLCMD;
+
+ switch (cmd) {
+ case PMIC_GOTO_STANDBY:
+ /* Disable LP mode */
+ ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+ TPS6594_BIT_LP_STANDBY_SEL);
+ if (ret)
+ return ret;
+
+ /* Force trigger */
+ ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+ TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0));
+ break;
+ case PMIC_GOTO_LP_STANDBY:
+ /* Enable LP mode */
+ ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+ TPS6594_BIT_LP_STANDBY_SEL);
+ if (ret)
+ return ret;
+
+ /* Force trigger */
+ ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+ TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0));
+ break;
+ case PMIC_UPDATE_PGM:
+ /* Force trigger */
+ ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+ TPS6594_BIT_TRIGGER_I2C(3), TPS6594_BIT_TRIGGER_I2C(3));
+ break;
+ case PMIC_SET_ACTIVE_STATE:
+ /* Modify NSLEEP1-2 bits */
+ ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+ TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B);
+ break;
+ case PMIC_SET_MCU_ONLY_STATE:
+ if (copy_from_user(&state_opt, argp, sizeof(state_opt)))
+ return -EFAULT;
+
+ /* Configure retention triggers */
+ ret = tps6594_pfsm_configure_ret_trig(pfsm->regmap, state_opt.gpio_retention,
+ state_opt.ddr_retention);
+ if (ret)
+ return ret;
+
+ /* Modify NSLEEP1-2 bits */
+ ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+ TPS6594_BIT_NSLEEP1B);
+ if (ret)
+ return ret;
+
+ ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+ TPS6594_BIT_NSLEEP2B);
+ break;
+ case PMIC_SET_RETENTION_STATE:
+ if (copy_from_user(&state_opt, argp, sizeof(state_opt)))
+ return -EFAULT;
+
+ /* Configure wake-up destination */
+ if (state_opt.mcu_only_startup_dest)
+ ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+ TPS6594_MASK_STARTUP_DEST,
+ TPS6594_STARTUP_DEST_MCU_ONLY);
+ else
+ ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+ TPS6594_MASK_STARTUP_DEST,
+ TPS6594_STARTUP_DEST_ACTIVE);
+ if (ret)
+ return ret;
+
+ /* Configure retention triggers */
+ ret = tps6594_pfsm_configure_ret_trig(pfsm->regmap, state_opt.gpio_retention,
+ state_opt.ddr_retention);
+ if (ret)
+ return ret;
+
+ /* Modify NSLEEP1-2 bits */
+ ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+ TPS6594_BIT_NSLEEP2B);
+ break;
+ }
+
+ return ret;
+}
+
+static const struct file_operations tps6594_pfsm_fops = {
+ .owner = THIS_MODULE,
+ .llseek = generic_file_llseek,
+ .read = tps6594_pfsm_read,
+ .write = tps6594_pfsm_write,
+ .unlocked_ioctl = tps6594_pfsm_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
+};
+
+static irqreturn_t tps6594_pfsm_isr(int irq, void *dev_id)
+{
+ struct platform_device *pdev = dev_id;
+ int i;
+
+ for (i = 0 ; i < pdev->num_resources ; i++) {
+ if (irq == platform_get_irq_byname(pdev, pdev->resource[i].name)) {
+ dev_err(pdev->dev.parent, "%s event detected\n", pdev->resource[i].name);
+ return IRQ_HANDLED;
+ }
+ }
+
+ return IRQ_NONE;
+}
+
+static int tps6594_pfsm_probe(struct platform_device *pdev)
+{
+ struct tps6594_pfsm *pfsm;
+ struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+ struct device *dev = &pdev->dev;
+ int irq;
+ int ret;
+ int i;
+
+ pfsm = devm_kzalloc(dev, sizeof(struct tps6594_pfsm), GFP_KERNEL);
+ if (!pfsm)
+ return -ENOMEM;
+
+ pfsm->regmap = tps->regmap;
+
+ pfsm->miscdev.minor = MISC_DYNAMIC_MINOR;
+ pfsm->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "pfsm-%ld-0x%02x",
+ tps->chip_id, tps->reg);
+ pfsm->miscdev.fops = &tps6594_pfsm_fops;
+ pfsm->miscdev.parent = dev->parent;
+
+ for (i = 0 ; i < pdev->num_resources ; i++) {
+ irq = platform_get_irq_byname(pdev, pdev->resource[i].name);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "Failed to get %s irq\n",
+ pdev->resource[i].name);
+
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ tps6594_pfsm_isr, IRQF_ONESHOT,
+ pdev->resource[i].name, pdev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to request irq\n");
+ }
+
+ platform_set_drvdata(pdev, pfsm);
+
+ return misc_register(&pfsm->miscdev);
+}
+
+static int tps6594_pfsm_remove(struct platform_device *pdev)
+{
+ struct tps6594_pfsm *pfsm = platform_get_drvdata(pdev);
+
+ misc_deregister(&pfsm->miscdev);
+
+ return 0;
+}
+
+static struct platform_driver tps6594_pfsm_driver = {
+ .driver = {
+ .name = "tps6594-pfsm",
+ },
+ .probe = tps6594_pfsm_probe,
+ .remove = tps6594_pfsm_remove,
+};
+
+module_platform_driver(tps6594_pfsm_driver);
+
+MODULE_ALIAS("platform:tps6594-pfsm");
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 Pre-configurable Finite State Machine Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c
index 6c62b94e0acd..a3bc2823143e 100644
--- a/drivers/misc/tsl2550.c
+++ b/drivers/misc/tsl2550.c
@@ -437,7 +437,7 @@ static struct i2c_driver tsl2550_driver = {
.of_match_table = tsl2550_of_match,
.pm = TSL2550_PM_OPS,
},
- .probe_new = tsl2550_probe,
+ .probe = tsl2550_probe,
.remove = tsl2550_remove,
.id_table = tsl2550_id,
};
diff --git a/drivers/misc/uacce/uacce.c b/drivers/misc/uacce/uacce.c
index 346bd7cf2e94..930c252753a0 100644
--- a/drivers/misc/uacce/uacce.c
+++ b/drivers/misc/uacce/uacce.c
@@ -166,8 +166,8 @@ static int uacce_fops_open(struct inode *inode, struct file *filep)
init_waitqueue_head(&q->wait);
filep->private_data = q;
- uacce->inode = inode;
q->state = UACCE_Q_INIT;
+ q->mapping = filep->f_mapping;
mutex_init(&q->mutex);
list_add(&q->list, &uacce->queues);
mutex_unlock(&uacce->mutex);
@@ -200,12 +200,15 @@ static int uacce_fops_release(struct inode *inode, struct file *filep)
static void uacce_vma_close(struct vm_area_struct *vma)
{
struct uacce_queue *q = vma->vm_private_data;
- struct uacce_qfile_region *qfr = NULL;
- if (vma->vm_pgoff < UACCE_MAX_REGION)
- qfr = q->qfrs[vma->vm_pgoff];
+ if (vma->vm_pgoff < UACCE_MAX_REGION) {
+ struct uacce_qfile_region *qfr = q->qfrs[vma->vm_pgoff];
- kfree(qfr);
+ mutex_lock(&q->mutex);
+ q->qfrs[vma->vm_pgoff] = NULL;
+ mutex_unlock(&q->mutex);
+ kfree(qfr);
+ }
}
static const struct vm_operations_struct uacce_vm_ops = {
@@ -574,12 +577,6 @@ void uacce_remove(struct uacce_device *uacce)
if (!uacce)
return;
- /*
- * unmap remaining mapping from user space, preventing user still
- * access the mmaped area while parent device is already removed
- */
- if (uacce->inode)
- unmap_mapping_range(uacce->inode->i_mapping, 0, 0, 1);
/*
* uacce_fops_open() may be running concurrently, even after we remove
@@ -597,6 +594,12 @@ void uacce_remove(struct uacce_device *uacce)
uacce_put_queue(q);
mutex_unlock(&q->mutex);
uacce_unbind_queue(q);
+
+ /*
+ * unmap remaining mapping from user space, preventing user still
+ * access the mmaped area while parent device is already removed
+ */
+ unmap_mapping_range(q->mapping, 0, 0, 1);
}
/* disable sva now since no opened queues */
diff --git a/drivers/misc/xilinx_sdfec.c b/drivers/misc/xilinx_sdfec.c
index cb9506f9cbd0..270ff4c5971a 100644
--- a/drivers/misc/xilinx_sdfec.c
+++ b/drivers/misc/xilinx_sdfec.c
@@ -855,16 +855,6 @@ static int xsdfec_cfg_axi_streams(struct xsdfec_dev *xsdfec)
return 0;
}
-static int xsdfec_dev_open(struct inode *iptr, struct file *fptr)
-{
- return 0;
-}
-
-static int xsdfec_dev_release(struct inode *iptr, struct file *fptr)
-{
- return 0;
-}
-
static int xsdfec_start(struct xsdfec_dev *xsdfec)
{
u32 regread;
@@ -1030,8 +1020,6 @@ static __poll_t xsdfec_poll(struct file *file, poll_table *wait)
static const struct file_operations xsdfec_fops = {
.owner = THIS_MODULE,
- .open = xsdfec_dev_open,
- .release = xsdfec_dev_release,
.unlocked_ioctl = xsdfec_dev_ioctl,
.poll = xsdfec_poll,
.compat_ioctl = compat_ptr_ioctl,
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 86454f1182bb..6a259563690d 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -26,6 +26,7 @@
#include <linux/clk.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
+#include <linux/gpio/consumer.h>
#include <linux/platform_data/mmc-omap.h>
@@ -111,6 +112,9 @@ struct mmc_omap_slot {
struct mmc_request *mrq;
struct mmc_omap_host *host;
struct mmc_host *mmc;
+ struct gpio_desc *vsd;
+ struct gpio_desc *vio;
+ struct gpio_desc *cover;
struct omap_mmc_slot_data *pdata;
};
@@ -133,6 +137,7 @@ struct mmc_omap_host {
int irq;
unsigned char bus_mode;
unsigned int reg_shift;
+ struct gpio_desc *slot_switch;
struct work_struct cmd_abort_work;
unsigned abort:1;
@@ -216,8 +221,13 @@ no_claim:
if (host->current_slot != slot) {
OMAP_MMC_WRITE(host, CON, slot->saved_con & 0xFC00);
- if (host->pdata->switch_slot != NULL)
- host->pdata->switch_slot(mmc_dev(slot->mmc), slot->id);
+ if (host->slot_switch)
+ /*
+ * With two slots and a simple GPIO switch, setting
+ * the GPIO to 0 selects slot ID 0, setting it to 1
+ * selects slot ID 1.
+ */
+ gpiod_set_value(host->slot_switch, slot->id);
host->current_slot = slot;
}
@@ -297,6 +307,9 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled)
static inline
int mmc_omap_cover_is_open(struct mmc_omap_slot *slot)
{
+ /* If we have a GPIO then use that */
+ if (slot->cover)
+ return gpiod_get_value(slot->cover);
if (slot->pdata->get_cover_state)
return slot->pdata->get_cover_state(mmc_dev(slot->mmc),
slot->id);
@@ -1106,6 +1119,11 @@ static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on,
host = slot->host;
+ if (slot->vsd)
+ gpiod_set_value(slot->vsd, power_on);
+ if (slot->vio)
+ gpiod_set_value(slot->vio, power_on);
+
if (slot->pdata->set_power != NULL)
slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on,
vdd);
@@ -1240,6 +1258,23 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
slot->power_mode = MMC_POWER_UNDEFINED;
slot->pdata = &host->pdata->slots[id];
+ /* Check for some optional GPIO controls */
+ slot->vsd = gpiod_get_index_optional(host->dev, "vsd",
+ id, GPIOD_OUT_LOW);
+ if (IS_ERR(slot->vsd))
+ return dev_err_probe(host->dev, PTR_ERR(slot->vsd),
+ "error looking up VSD GPIO\n");
+ slot->vio = gpiod_get_index_optional(host->dev, "vio",
+ id, GPIOD_OUT_LOW);
+ if (IS_ERR(slot->vio))
+ return dev_err_probe(host->dev, PTR_ERR(slot->vio),
+ "error looking up VIO GPIO\n");
+ slot->cover = gpiod_get_index_optional(host->dev, "cover",
+ id, GPIOD_IN);
+ if (IS_ERR(slot->cover))
+ return dev_err_probe(host->dev, PTR_ERR(slot->cover),
+ "error looking up cover switch GPIO\n");
+
host->slots[id] = slot;
mmc->caps = 0;
@@ -1349,6 +1384,13 @@ static int mmc_omap_probe(struct platform_device *pdev)
if (IS_ERR(host->virt_base))
return PTR_ERR(host->virt_base);
+ host->slot_switch = gpiod_get_optional(host->dev, "switch",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(host->slot_switch))
+ return dev_err_probe(host->dev, PTR_ERR(host->slot_switch),
+ "error looking up slot switch GPIO\n");
+
+
INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work);
INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work);
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index e5c571fd232c..80f015cf6e54 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -47,7 +47,7 @@ config MUX_GPIO
config MUX_MMIO
tristate "MMIO/Regmap register bitfield-controlled Multiplexer"
- depends on OF || COMPILE_TEST
+ depends on OF
help
MMIO/Regmap register bitfield-controlled Multiplexer controller.
diff --git a/drivers/mux/adg792a.c b/drivers/mux/adg792a.c
index e8fc2fc1ab09..4da5aecb9fc6 100644
--- a/drivers/mux/adg792a.c
+++ b/drivers/mux/adg792a.c
@@ -143,7 +143,7 @@ static struct i2c_driver adg792a_driver = {
.name = "adg792a",
.of_match_table = of_match_ptr(adg792a_of_match),
},
- .probe_new = adg792a_probe,
+ .probe = adg792a_probe,
.id_table = adg792a_id,
};
module_i2c_driver(adg792a_driver);
diff --git a/drivers/mux/mmio.c b/drivers/mux/mmio.c
index 44a7a0e885b8..245bc07eee4b 100644
--- a/drivers/mux/mmio.c
+++ b/drivers/mux/mmio.c
@@ -131,7 +131,7 @@ static int mux_mmio_probe(struct platform_device *pdev)
static struct platform_driver mux_mmio_driver = {
.driver = {
.name = "mmio-mux",
- .of_match_table = of_match_ptr(mux_mmio_dt_ids),
+ .of_match_table = mux_mmio_dt_ids,
},
.probe = mux_mmio_probe,
};
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 1bad1866ae46..99265667538c 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -196,13 +196,10 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum,
void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event)
{
struct arcnet_local *lp = netdev_priv(dev);
- unsigned long led_delay = 350;
- unsigned long tx_delay = 50;
switch (event) {
case ARCNET_LED_EVENT_RECON:
- led_trigger_blink_oneshot(lp->recon_led_trig,
- &led_delay, &led_delay, 0);
+ led_trigger_blink_oneshot(lp->recon_led_trig, 350, 350, 0);
break;
case ARCNET_LED_EVENT_OPEN:
led_trigger_event(lp->tx_led_trig, LED_OFF);
@@ -213,8 +210,7 @@ void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event)
led_trigger_event(lp->recon_led_trig, LED_OFF);
break;
case ARCNET_LED_EVENT_TX:
- led_trigger_blink_oneshot(lp->tx_led_trig,
- &tx_delay, &tx_delay, 0);
+ led_trigger_blink_oneshot(lp->tx_led_trig, 50, 50, 0);
break;
}
}
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index a62cffaf6ff1..a9676d0dece8 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -5025,7 +5025,7 @@ err_wq_alloc:
return err;
}
-static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
+static void dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
{
struct device *dev;
struct net_device *net_dev;
@@ -5073,8 +5073,6 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
dev_dbg(net_dev->dev.parent, "Removed interface %s\n", net_dev->name);
free_netdev(net_dev);
-
- return 0;
}
static const struct fsl_mc_device_id dpaa2_eth_match_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
index 90d23ab1ce9d..4497e3c0456d 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
@@ -219,7 +219,7 @@ err_exit:
return err;
}
-static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
+static void dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
{
struct device *dev = &mc_dev->dev;
struct ptp_qoriq *ptp_qoriq;
@@ -232,8 +232,6 @@ static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
fsl_mc_free_irqs(mc_dev);
dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
fsl_mc_portal_free(mc_dev->mc_io);
-
- return 0;
}
static const struct fsl_mc_device_id dpaa2_ptp_match_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
index f4ae4289c41a..21cc4e52425a 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
@@ -3221,7 +3221,7 @@ static void dpaa2_switch_teardown(struct fsl_mc_device *sw_dev)
dev_warn(dev, "dpsw_close err %d\n", err);
}
-static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
+static void dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
{
struct ethsw_port_priv *port_priv;
struct ethsw_core *ethsw;
@@ -3252,8 +3252,6 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
kfree(ethsw);
dev_set_drvdata(dev, NULL);
-
- return 0;
}
static int dpaa2_switch_probe_port(struct ethsw_core *ethsw,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
index fc13b41cc9b2..2138f28a2931 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
@@ -514,11 +514,11 @@ EXPORT_SYMBOL(mlx5_debug_qp_add);
void mlx5_debug_qp_remove(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp)
{
- if (!mlx5_debugfs_root)
+ if (!mlx5_debugfs_root || !qp->dbg)
return;
- if (qp->dbg)
- rem_res_tree(qp->dbg);
+ rem_res_tree(qp->dbg);
+ qp->dbg = NULL;
}
EXPORT_SYMBOL(mlx5_debug_qp_remove);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
index fb7874da3caa..4804990b7f22 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
@@ -368,7 +368,6 @@ static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev)
struct pci_dev *sdev;
u16 reg16, dev_id;
int cap, err;
- u32 reg32;
err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id);
if (err)
@@ -399,11 +398,8 @@ static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev)
return err;
/* Check link */
- err = pci_read_config_dword(bridge, cap + PCI_EXP_LNKCAP, &reg32);
- if (err)
- return err;
- if (!(reg32 & PCI_EXP_LNKCAP_DLLLARC)) {
- mlx5_core_warn(dev, "No PCI link reporting capability (0x%08x)\n", reg32);
+ if (!bridge->link_active_reporting) {
+ mlx5_core_warn(dev, "No PCI link reporting capability\n");
msleep(1000);
goto restore;
}
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index cd4d5ceb9f2d..a499e460594b 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -980,7 +980,7 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
bool update_tab)
{
u16 num_entries = MANA_INDIRECT_TABLE_SIZE;
- struct mana_cfg_rx_steer_req *req = NULL;
+ struct mana_cfg_rx_steer_req_v2 *req;
struct mana_cfg_rx_steer_resp resp = {};
struct net_device *ndev = apc->ndev;
mana_handle_t *req_indir_tab;
@@ -995,6 +995,8 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
mana_gd_init_req_hdr(&req->hdr, MANA_CONFIG_VPORT_RX, req_buf_size,
sizeof(resp));
+ req->hdr.req.msg_version = GDMA_MESSAGE_V2;
+
req->vport = apc->port_handle;
req->num_indir_entries = num_entries;
req->indir_tab_offset = sizeof(*req);
@@ -1004,6 +1006,7 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
req->update_hashkey = update_key;
req->update_indir_tab = update_tab;
req->default_rxobj = apc->default_rxobj;
+ req->cqe_coalescing_enable = 0;
if (update_key)
memcpy(&req->hashkey, apc->hashkey, MANA_HASH_KEY_SIZE);
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 954dbc105fc8..5852fe290523 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -25,7 +25,7 @@
int nvdimm_major;
static int nvdimm_bus_major;
-struct class *nd_class;
+static struct class *nd_class;
static DEFINE_IDA(nd_ida);
static int to_nd_device_type(const struct device *dev)
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 957f7c3d17ba..1273873582be 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -349,8 +349,8 @@ static ssize_t available_slots_show(struct device *dev,
}
static DEVICE_ATTR_RO(available_slots);
-ssize_t security_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t security_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct nvdimm *nvdimm = to_nvdimm(dev);
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index ceea55f621cc..46e094e56159 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -260,7 +260,7 @@ __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff,
long actual_nr;
if (mode != DAX_RECOVERY_WRITE)
- return -EIO;
+ return -EHWPOISON;
/*
* Set the recovery stride is set to kernel page size because
diff --git a/drivers/nvme/host/Makefile b/drivers/nvme/host/Makefile
index d3fc5063e4be..c7c3cf202d12 100644
--- a/drivers/nvme/host/Makefile
+++ b/drivers/nvme/host/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_NVME_FC) += nvme-fc.o
obj-$(CONFIG_NVME_TCP) += nvme-tcp.o
obj-$(CONFIG_NVME_APPLE) += nvme-apple.o
-nvme-core-y += core.o ioctl.o sysfs.o
+nvme-core-y += core.o ioctl.o sysfs.o pr.o
nvme-core-$(CONFIG_NVME_VERBOSE_ERRORS) += constants.o
nvme-core-$(CONFIG_TRACING) += trace.o
nvme-core-$(CONFIG_NVME_MULTIPATH) += multipath.o
diff --git a/drivers/nvme/host/constants.c b/drivers/nvme/host/constants.c
index 5e4f8848dce0..20f46c230885 100644
--- a/drivers/nvme/host/constants.c
+++ b/drivers/nvme/host/constants.c
@@ -12,7 +12,7 @@ static const char * const nvme_ops[] = {
[nvme_cmd_read] = "Read",
[nvme_cmd_write_uncor] = "Write Uncorrectable",
[nvme_cmd_compare] = "Compare",
- [nvme_cmd_write_zeroes] = "Write Zeros",
+ [nvme_cmd_write_zeroes] = "Write Zeroes",
[nvme_cmd_dsm] = "Dataset Management",
[nvme_cmd_verify] = "Verify",
[nvme_cmd_resv_register] = "Reservation Register",
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index fdfcf2781c85..47d7ba2827ff 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -279,7 +279,7 @@ static blk_status_t nvme_error_status(u16 status)
case NVME_SC_INVALID_PI:
return BLK_STS_PROTECTION;
case NVME_SC_RESERVATION_CONFLICT:
- return BLK_STS_NEXUS;
+ return BLK_STS_RESV_CONFLICT;
case NVME_SC_HOST_PATH_ERROR:
return BLK_STS_TRANSPORT;
case NVME_SC_ZONE_TOO_MANY_ACTIVE:
@@ -1134,8 +1134,11 @@ void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects,
mutex_unlock(&ctrl->scan_lock);
}
if (effects & NVME_CMD_EFFECTS_CCC) {
- dev_info(ctrl->device,
+ if (!test_and_set_bit(NVME_CTRL_DIRTY_CAPABILITY,
+ &ctrl->flags)) {
+ dev_info(ctrl->device,
"controller capabilities changed, reset may be required to take effect.\n");
+ }
}
if (effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC)) {
nvme_queue_scan(ctrl);
@@ -2105,153 +2108,6 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_ns_info *info)
}
}
-static char nvme_pr_type(enum pr_type type)
-{
- switch (type) {
- case PR_WRITE_EXCLUSIVE:
- return 1;
- case PR_EXCLUSIVE_ACCESS:
- return 2;
- case PR_WRITE_EXCLUSIVE_REG_ONLY:
- return 3;
- case PR_EXCLUSIVE_ACCESS_REG_ONLY:
- return 4;
- case PR_WRITE_EXCLUSIVE_ALL_REGS:
- return 5;
- case PR_EXCLUSIVE_ACCESS_ALL_REGS:
- return 6;
- default:
- return 0;
- }
-}
-
-static int nvme_send_ns_head_pr_command(struct block_device *bdev,
- struct nvme_command *c, u8 data[16])
-{
- struct nvme_ns_head *head = bdev->bd_disk->private_data;
- int srcu_idx = srcu_read_lock(&head->srcu);
- struct nvme_ns *ns = nvme_find_path(head);
- int ret = -EWOULDBLOCK;
-
- if (ns) {
- c->common.nsid = cpu_to_le32(ns->head->ns_id);
- ret = nvme_submit_sync_cmd(ns->queue, c, data, 16);
- }
- srcu_read_unlock(&head->srcu, srcu_idx);
- return ret;
-}
-
-static int nvme_send_ns_pr_command(struct nvme_ns *ns, struct nvme_command *c,
- u8 data[16])
-{
- c->common.nsid = cpu_to_le32(ns->head->ns_id);
- return nvme_submit_sync_cmd(ns->queue, c, data, 16);
-}
-
-static int nvme_sc_to_pr_err(int nvme_sc)
-{
- if (nvme_is_path_error(nvme_sc))
- return PR_STS_PATH_FAILED;
-
- switch (nvme_sc) {
- case NVME_SC_SUCCESS:
- return PR_STS_SUCCESS;
- case NVME_SC_RESERVATION_CONFLICT:
- return PR_STS_RESERVATION_CONFLICT;
- case NVME_SC_ONCS_NOT_SUPPORTED:
- return -EOPNOTSUPP;
- case NVME_SC_BAD_ATTRIBUTES:
- case NVME_SC_INVALID_OPCODE:
- case NVME_SC_INVALID_FIELD:
- case NVME_SC_INVALID_NS:
- return -EINVAL;
- default:
- return PR_STS_IOERR;
- }
-}
-
-static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
- u64 key, u64 sa_key, u8 op)
-{
- struct nvme_command c = { };
- u8 data[16] = { 0, };
- int ret;
-
- put_unaligned_le64(key, &data[0]);
- put_unaligned_le64(sa_key, &data[8]);
-
- c.common.opcode = op;
- c.common.cdw10 = cpu_to_le32(cdw10);
-
- if (IS_ENABLED(CONFIG_NVME_MULTIPATH) &&
- bdev->bd_disk->fops == &nvme_ns_head_ops)
- ret = nvme_send_ns_head_pr_command(bdev, &c, data);
- else
- ret = nvme_send_ns_pr_command(bdev->bd_disk->private_data, &c,
- data);
- if (ret < 0)
- return ret;
-
- return nvme_sc_to_pr_err(ret);
-}
-
-static int nvme_pr_register(struct block_device *bdev, u64 old,
- u64 new, unsigned flags)
-{
- u32 cdw10;
-
- if (flags & ~PR_FL_IGNORE_KEY)
- return -EOPNOTSUPP;
-
- cdw10 = old ? 2 : 0;
- cdw10 |= (flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0;
- cdw10 |= (1 << 30) | (1 << 31); /* PTPL=1 */
- return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_register);
-}
-
-static int nvme_pr_reserve(struct block_device *bdev, u64 key,
- enum pr_type type, unsigned flags)
-{
- u32 cdw10;
-
- if (flags & ~PR_FL_IGNORE_KEY)
- return -EOPNOTSUPP;
-
- cdw10 = nvme_pr_type(type) << 8;
- cdw10 |= ((flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_acquire);
-}
-
-static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new,
- enum pr_type type, bool abort)
-{
- u32 cdw10 = nvme_pr_type(type) << 8 | (abort ? 2 : 1);
-
- return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire);
-}
-
-static int nvme_pr_clear(struct block_device *bdev, u64 key)
-{
- u32 cdw10 = 1 | (key ? 0 : 1 << 3);
-
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
-}
-
-static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
-{
- u32 cdw10 = nvme_pr_type(type) << 8 | (key ? 0 : 1 << 3);
-
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
-}
-
-const struct pr_ops nvme_pr_ops = {
- .pr_register = nvme_pr_register,
- .pr_reserve = nvme_pr_reserve,
- .pr_release = nvme_pr_release,
- .pr_preempt = nvme_pr_preempt,
- .pr_clear = nvme_pr_clear,
-};
-
#ifdef CONFIG_BLK_SED_OPAL
static int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t len,
bool send)
@@ -3324,6 +3180,7 @@ int nvme_init_ctrl_finish(struct nvme_ctrl *ctrl, bool was_suspended)
return ret;
}
+ clear_bit(NVME_CTRL_DIRTY_CAPABILITY, &ctrl->flags);
ctrl->identified = true;
return 0;
diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index 2130ad65b58c..5c3250f36ce7 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -505,7 +505,6 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
{
struct io_uring_cmd *ioucmd = req->end_io_data;
struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
- void *cookie = READ_ONCE(ioucmd->cookie);
req->bio = pdu->bio;
if (nvme_req(req)->flags & NVME_REQ_CANCELLED)
@@ -518,10 +517,12 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
* For iopoll, complete it directly.
* Otherwise, move the completion to task work.
*/
- if (cookie != NULL && blk_rq_is_poll(req))
+ if (blk_rq_is_poll(req)) {
+ WRITE_ONCE(ioucmd->cookie, NULL);
nvme_uring_task_cb(ioucmd, IO_URING_F_UNLOCKED);
- else
+ } else {
io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_cb);
+ }
return RQ_END_IO_FREE;
}
@@ -531,7 +532,6 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io_meta(struct request *req,
{
struct io_uring_cmd *ioucmd = req->end_io_data;
struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
- void *cookie = READ_ONCE(ioucmd->cookie);
req->bio = pdu->bio;
pdu->req = req;
@@ -540,10 +540,12 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io_meta(struct request *req,
* For iopoll, complete it directly.
* Otherwise, move the completion to task work.
*/
- if (cookie != NULL && blk_rq_is_poll(req))
+ if (blk_rq_is_poll(req)) {
+ WRITE_ONCE(ioucmd->cookie, NULL);
nvme_uring_task_meta_cb(ioucmd, IO_URING_F_UNLOCKED);
- else
+ } else {
io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_meta_cb);
+ }
return RQ_END_IO_NONE;
}
@@ -599,7 +601,6 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
if (issue_flags & IO_URING_F_IOPOLL)
rq_flags |= REQ_POLLED;
-retry:
req = nvme_alloc_user_request(q, &c, rq_flags, blk_flags);
if (IS_ERR(req))
return PTR_ERR(req);
@@ -613,17 +614,11 @@ retry:
return ret;
}
- if (issue_flags & IO_URING_F_IOPOLL && rq_flags & REQ_POLLED) {
- if (unlikely(!req->bio)) {
- /* we can't poll this, so alloc regular req instead */
- blk_mq_free_request(req);
- rq_flags &= ~REQ_POLLED;
- goto retry;
- } else {
- WRITE_ONCE(ioucmd->cookie, req->bio);
- req->bio->bi_opf |= REQ_POLLED;
- }
+ if (blk_rq_is_poll(req)) {
+ ioucmd->flags |= IORING_URING_CMD_POLLED;
+ WRITE_ONCE(ioucmd->cookie, req);
}
+
/* to free bio on completion, as req->bio will be null at that time */
pdu->bio = req->bio;
pdu->meta_len = d.metadata_len;
@@ -785,18 +780,16 @@ int nvme_ns_chr_uring_cmd_iopoll(struct io_uring_cmd *ioucmd,
struct io_comp_batch *iob,
unsigned int poll_flags)
{
- struct bio *bio;
+ struct request *req;
int ret = 0;
- struct nvme_ns *ns;
- struct request_queue *q;
+
+ if (!(ioucmd->flags & IORING_URING_CMD_POLLED))
+ return 0;
rcu_read_lock();
- bio = READ_ONCE(ioucmd->cookie);
- ns = container_of(file_inode(ioucmd->file)->i_cdev,
- struct nvme_ns, cdev);
- q = ns->queue;
- if (test_bit(QUEUE_FLAG_POLL, &q->queue_flags) && bio && bio->bi_bdev)
- ret = bio_poll(bio, iob, poll_flags);
+ req = READ_ONCE(ioucmd->cookie);
+ if (req && blk_rq_is_poll(req))
+ ret = blk_rq_poll(req, iob, poll_flags);
rcu_read_unlock();
return ret;
}
@@ -890,31 +883,6 @@ int nvme_ns_head_chr_uring_cmd(struct io_uring_cmd *ioucmd,
srcu_read_unlock(&head->srcu, srcu_idx);
return ret;
}
-
-int nvme_ns_head_chr_uring_cmd_iopoll(struct io_uring_cmd *ioucmd,
- struct io_comp_batch *iob,
- unsigned int poll_flags)
-{
- struct cdev *cdev = file_inode(ioucmd->file)->i_cdev;
- struct nvme_ns_head *head = container_of(cdev, struct nvme_ns_head, cdev);
- int srcu_idx = srcu_read_lock(&head->srcu);
- struct nvme_ns *ns = nvme_find_path(head);
- struct bio *bio;
- int ret = 0;
- struct request_queue *q;
-
- if (ns) {
- rcu_read_lock();
- bio = READ_ONCE(ioucmd->cookie);
- q = ns->queue;
- if (test_bit(QUEUE_FLAG_POLL, &q->queue_flags) && bio
- && bio->bi_bdev)
- ret = bio_poll(bio, iob, poll_flags);
- rcu_read_unlock();
- }
- srcu_read_unlock(&head->srcu, srcu_idx);
- return ret;
-}
#endif /* CONFIG_NVME_MULTIPATH */
int nvme_dev_uring_cmd(struct io_uring_cmd *ioucmd, unsigned int issue_flags)
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index 98001eebd275..0a88d7bdc5e3 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -106,6 +106,14 @@ void nvme_failover_req(struct request *req)
bio->bi_opf &= ~REQ_POLLED;
bio->bi_cookie = BLK_QC_T_NONE;
}
+ /*
+ * The alternate request queue that we may end up submitting
+ * the bio to may be frozen temporarily, in this case REQ_NOWAIT
+ * will fail the I/O immediately with EAGAIN to the issuer.
+ * We are not in the issuer context which cannot block. Clear
+ * the flag to avoid spurious EAGAIN I/O failures.
+ */
+ bio->bi_opf &= ~REQ_NOWAIT;
}
blk_steal_bios(&ns->head->requeue_list, req);
spin_unlock_irqrestore(&ns->head->requeue_lock, flags);
@@ -470,7 +478,7 @@ static const struct file_operations nvme_ns_head_chr_fops = {
.unlocked_ioctl = nvme_ns_head_chr_ioctl,
.compat_ioctl = compat_ptr_ioctl,
.uring_cmd = nvme_ns_head_chr_uring_cmd,
- .uring_cmd_iopoll = nvme_ns_head_chr_uring_cmd_iopoll,
+ .uring_cmd_iopoll = nvme_ns_chr_uring_cmd_iopoll,
};
static int nvme_add_ns_head_cdev(struct nvme_ns_head *head)
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 9a98c14c552a..f35647c470af 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -19,6 +19,8 @@
#include <trace/events/block.h>
+extern const struct pr_ops nvme_pr_ops;
+
extern unsigned int nvme_io_timeout;
#define NVME_IO_TIMEOUT (nvme_io_timeout * HZ)
@@ -248,6 +250,7 @@ enum nvme_ctrl_flags {
NVME_CTRL_STARTED_ONCE = 2,
NVME_CTRL_STOPPED = 3,
NVME_CTRL_SKIP_ID_CNS_CS = 4,
+ NVME_CTRL_DIRTY_CAPABILITY = 5,
};
struct nvme_ctrl {
@@ -854,8 +857,6 @@ long nvme_dev_ioctl(struct file *file, unsigned int cmd,
unsigned long arg);
int nvme_ns_chr_uring_cmd_iopoll(struct io_uring_cmd *ioucmd,
struct io_comp_batch *iob, unsigned int poll_flags);
-int nvme_ns_head_chr_uring_cmd_iopoll(struct io_uring_cmd *ioucmd,
- struct io_comp_batch *iob, unsigned int poll_flags);
int nvme_ns_chr_uring_cmd(struct io_uring_cmd *ioucmd,
unsigned int issue_flags);
int nvme_ns_head_chr_uring_cmd(struct io_uring_cmd *ioucmd,
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 48c60f7fda0b..72725729cb6c 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -2690,7 +2690,8 @@ static void nvme_reset_work(struct work_struct *work)
if (dev->ctrl.state != NVME_CTRL_RESETTING) {
dev_warn(dev->ctrl.device, "ctrl state %d is not RESETTING\n",
dev->ctrl.state);
- return;
+ result = -ENODEV;
+ goto out;
}
/*
@@ -2777,7 +2778,9 @@ static void nvme_reset_work(struct work_struct *work)
result);
nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING);
nvme_dev_disable(dev, true);
+ nvme_sync_queues(&dev->ctrl);
nvme_mark_namespaces_dead(&dev->ctrl);
+ nvme_unquiesce_io_queues(&dev->ctrl);
nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DEAD);
}
diff --git a/drivers/nvme/host/pr.c b/drivers/nvme/host/pr.c
new file mode 100644
index 000000000000..391b1465ebfd
--- /dev/null
+++ b/drivers/nvme/host/pr.c
@@ -0,0 +1,315 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2015 Intel Corporation
+ * Keith Busch <kbusch@kernel.org>
+ */
+#include <linux/blkdev.h>
+#include <linux/pr.h>
+#include <asm/unaligned.h>
+
+#include "nvme.h"
+
+static enum nvme_pr_type nvme_pr_type_from_blk(enum pr_type type)
+{
+ switch (type) {
+ case PR_WRITE_EXCLUSIVE:
+ return NVME_PR_WRITE_EXCLUSIVE;
+ case PR_EXCLUSIVE_ACCESS:
+ return NVME_PR_EXCLUSIVE_ACCESS;
+ case PR_WRITE_EXCLUSIVE_REG_ONLY:
+ return NVME_PR_WRITE_EXCLUSIVE_REG_ONLY;
+ case PR_EXCLUSIVE_ACCESS_REG_ONLY:
+ return NVME_PR_EXCLUSIVE_ACCESS_REG_ONLY;
+ case PR_WRITE_EXCLUSIVE_ALL_REGS:
+ return NVME_PR_WRITE_EXCLUSIVE_ALL_REGS;
+ case PR_EXCLUSIVE_ACCESS_ALL_REGS:
+ return NVME_PR_EXCLUSIVE_ACCESS_ALL_REGS;
+ }
+
+ return 0;
+}
+
+static enum pr_type block_pr_type_from_nvme(enum nvme_pr_type type)
+{
+ switch (type) {
+ case NVME_PR_WRITE_EXCLUSIVE:
+ return PR_WRITE_EXCLUSIVE;
+ case NVME_PR_EXCLUSIVE_ACCESS:
+ return PR_EXCLUSIVE_ACCESS;
+ case NVME_PR_WRITE_EXCLUSIVE_REG_ONLY:
+ return PR_WRITE_EXCLUSIVE_REG_ONLY;
+ case NVME_PR_EXCLUSIVE_ACCESS_REG_ONLY:
+ return PR_EXCLUSIVE_ACCESS_REG_ONLY;
+ case NVME_PR_WRITE_EXCLUSIVE_ALL_REGS:
+ return PR_WRITE_EXCLUSIVE_ALL_REGS;
+ case NVME_PR_EXCLUSIVE_ACCESS_ALL_REGS:
+ return PR_EXCLUSIVE_ACCESS_ALL_REGS;
+ }
+
+ return 0;
+}
+
+static int nvme_send_ns_head_pr_command(struct block_device *bdev,
+ struct nvme_command *c, void *data, unsigned int data_len)
+{
+ struct nvme_ns_head *head = bdev->bd_disk->private_data;
+ int srcu_idx = srcu_read_lock(&head->srcu);
+ struct nvme_ns *ns = nvme_find_path(head);
+ int ret = -EWOULDBLOCK;
+
+ if (ns) {
+ c->common.nsid = cpu_to_le32(ns->head->ns_id);
+ ret = nvme_submit_sync_cmd(ns->queue, c, data, data_len);
+ }
+ srcu_read_unlock(&head->srcu, srcu_idx);
+ return ret;
+}
+
+static int nvme_send_ns_pr_command(struct nvme_ns *ns, struct nvme_command *c,
+ void *data, unsigned int data_len)
+{
+ c->common.nsid = cpu_to_le32(ns->head->ns_id);
+ return nvme_submit_sync_cmd(ns->queue, c, data, data_len);
+}
+
+static int nvme_sc_to_pr_err(int nvme_sc)
+{
+ if (nvme_is_path_error(nvme_sc))
+ return PR_STS_PATH_FAILED;
+
+ switch (nvme_sc) {
+ case NVME_SC_SUCCESS:
+ return PR_STS_SUCCESS;
+ case NVME_SC_RESERVATION_CONFLICT:
+ return PR_STS_RESERVATION_CONFLICT;
+ case NVME_SC_ONCS_NOT_SUPPORTED:
+ return -EOPNOTSUPP;
+ case NVME_SC_BAD_ATTRIBUTES:
+ case NVME_SC_INVALID_OPCODE:
+ case NVME_SC_INVALID_FIELD:
+ case NVME_SC_INVALID_NS:
+ return -EINVAL;
+ default:
+ return PR_STS_IOERR;
+ }
+}
+
+static int nvme_send_pr_command(struct block_device *bdev,
+ struct nvme_command *c, void *data, unsigned int data_len)
+{
+ if (IS_ENABLED(CONFIG_NVME_MULTIPATH) &&
+ bdev->bd_disk->fops == &nvme_ns_head_ops)
+ return nvme_send_ns_head_pr_command(bdev, c, data, data_len);
+
+ return nvme_send_ns_pr_command(bdev->bd_disk->private_data, c, data,
+ data_len);
+}
+
+static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
+ u64 key, u64 sa_key, u8 op)
+{
+ struct nvme_command c = { };
+ u8 data[16] = { 0, };
+ int ret;
+
+ put_unaligned_le64(key, &data[0]);
+ put_unaligned_le64(sa_key, &data[8]);
+
+ c.common.opcode = op;
+ c.common.cdw10 = cpu_to_le32(cdw10);
+
+ ret = nvme_send_pr_command(bdev, &c, data, sizeof(data));
+ if (ret < 0)
+ return ret;
+
+ return nvme_sc_to_pr_err(ret);
+}
+
+static int nvme_pr_register(struct block_device *bdev, u64 old,
+ u64 new, unsigned flags)
+{
+ u32 cdw10;
+
+ if (flags & ~PR_FL_IGNORE_KEY)
+ return -EOPNOTSUPP;
+
+ cdw10 = old ? 2 : 0;
+ cdw10 |= (flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0;
+ cdw10 |= (1 << 30) | (1 << 31); /* PTPL=1 */
+ return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_register);
+}
+
+static int nvme_pr_reserve(struct block_device *bdev, u64 key,
+ enum pr_type type, unsigned flags)
+{
+ u32 cdw10;
+
+ if (flags & ~PR_FL_IGNORE_KEY)
+ return -EOPNOTSUPP;
+
+ cdw10 = nvme_pr_type_from_blk(type) << 8;
+ cdw10 |= ((flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0);
+ return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_acquire);
+}
+
+static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new,
+ enum pr_type type, bool abort)
+{
+ u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (abort ? 2 : 1);
+
+ return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire);
+}
+
+static int nvme_pr_clear(struct block_device *bdev, u64 key)
+{
+ u32 cdw10 = 1 | (key ? 0 : 1 << 3);
+
+ return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+}
+
+static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
+{
+ u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (key ? 0 : 1 << 3);
+
+ return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+}
+
+static int nvme_pr_resv_report(struct block_device *bdev, void *data,
+ u32 data_len, bool *eds)
+{
+ struct nvme_command c = { };
+ int ret;
+
+ c.common.opcode = nvme_cmd_resv_report;
+ c.common.cdw10 = cpu_to_le32(nvme_bytes_to_numd(data_len));
+ c.common.cdw11 = cpu_to_le32(NVME_EXTENDED_DATA_STRUCT);
+ *eds = true;
+
+retry:
+ ret = nvme_send_pr_command(bdev, &c, data, data_len);
+ if (ret == NVME_SC_HOST_ID_INCONSIST &&
+ c.common.cdw11 == cpu_to_le32(NVME_EXTENDED_DATA_STRUCT)) {
+ c.common.cdw11 = 0;
+ *eds = false;
+ goto retry;
+ }
+
+ if (ret < 0)
+ return ret;
+
+ return nvme_sc_to_pr_err(ret);
+}
+
+static int nvme_pr_read_keys(struct block_device *bdev,
+ struct pr_keys *keys_info)
+{
+ u32 rse_len, num_keys = keys_info->num_keys;
+ struct nvme_reservation_status_ext *rse;
+ int ret, i;
+ bool eds;
+
+ /*
+ * Assume we are using 128-bit host IDs and allocate a buffer large
+ * enough to get enough keys to fill the return keys buffer.
+ */
+ rse_len = struct_size(rse, regctl_eds, num_keys);
+ rse = kzalloc(rse_len, GFP_KERNEL);
+ if (!rse)
+ return -ENOMEM;
+
+ ret = nvme_pr_resv_report(bdev, rse, rse_len, &eds);
+ if (ret)
+ goto free_rse;
+
+ keys_info->generation = le32_to_cpu(rse->gen);
+ keys_info->num_keys = get_unaligned_le16(&rse->regctl);
+
+ num_keys = min(num_keys, keys_info->num_keys);
+ for (i = 0; i < num_keys; i++) {
+ if (eds) {
+ keys_info->keys[i] =
+ le64_to_cpu(rse->regctl_eds[i].rkey);
+ } else {
+ struct nvme_reservation_status *rs;
+
+ rs = (struct nvme_reservation_status *)rse;
+ keys_info->keys[i] = le64_to_cpu(rs->regctl_ds[i].rkey);
+ }
+ }
+
+free_rse:
+ kfree(rse);
+ return ret;
+}
+
+static int nvme_pr_read_reservation(struct block_device *bdev,
+ struct pr_held_reservation *resv)
+{
+ struct nvme_reservation_status_ext tmp_rse, *rse;
+ int ret, i, num_regs;
+ u32 rse_len;
+ bool eds;
+
+get_num_regs:
+ /*
+ * Get the number of registrations so we know how big to allocate
+ * the response buffer.
+ */
+ ret = nvme_pr_resv_report(bdev, &tmp_rse, sizeof(tmp_rse), &eds);
+ if (ret)
+ return ret;
+
+ num_regs = get_unaligned_le16(&tmp_rse.regctl);
+ if (!num_regs) {
+ resv->generation = le32_to_cpu(tmp_rse.gen);
+ return 0;
+ }
+
+ rse_len = struct_size(rse, regctl_eds, num_regs);
+ rse = kzalloc(rse_len, GFP_KERNEL);
+ if (!rse)
+ return -ENOMEM;
+
+ ret = nvme_pr_resv_report(bdev, rse, rse_len, &eds);
+ if (ret)
+ goto free_rse;
+
+ if (num_regs != get_unaligned_le16(&rse->regctl)) {
+ kfree(rse);
+ goto get_num_regs;
+ }
+
+ resv->generation = le32_to_cpu(rse->gen);
+ resv->type = block_pr_type_from_nvme(rse->rtype);
+
+ for (i = 0; i < num_regs; i++) {
+ if (eds) {
+ if (rse->regctl_eds[i].rcsts) {
+ resv->key = le64_to_cpu(rse->regctl_eds[i].rkey);
+ break;
+ }
+ } else {
+ struct nvme_reservation_status *rs;
+
+ rs = (struct nvme_reservation_status *)rse;
+ if (rs->regctl_ds[i].rcsts) {
+ resv->key = le64_to_cpu(rs->regctl_ds[i].rkey);
+ break;
+ }
+ }
+ }
+
+free_rse:
+ kfree(rse);
+ return ret;
+}
+
+const struct pr_ops nvme_pr_ops = {
+ .pr_register = nvme_pr_register,
+ .pr_reserve = nvme_pr_reserve,
+ .pr_release = nvme_pr_release,
+ .pr_preempt = nvme_pr_preempt,
+ .pr_clear = nvme_pr_clear,
+ .pr_read_keys = nvme_pr_read_keys,
+ .pr_read_reservation = nvme_pr_read_reservation,
+};
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 6cf723bc664e..8cfd60f3b564 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -79,8 +79,8 @@ struct nvmet_ns {
struct completion disable_done;
mempool_t *bvec_pool;
- int use_p2pmem;
struct pci_dev *p2p_dev;
+ int use_p2pmem;
int pi_type;
int metadata_size;
u8 csi;
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index b291b27048c7..da9befa3d6c4 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -55,6 +55,7 @@ config NVMEM_BRCM_NVRAM
tristate "Broadcom's NVRAM support"
depends on ARCH_BCM_5301X || COMPILE_TEST
depends on HAS_IOMEM
+ select GENERIC_NET_UTILS
help
This driver provides support for Broadcom's NVRAM that can be accessed
using I/O mapping.
@@ -82,6 +83,15 @@ config NVMEM_IMX_OCOTP
This driver can also be built as a module. If so, the module
will be called nvmem-imx-ocotp.
+config NVMEM_IMX_OCOTP_ELE
+ tristate "i.MX On-Chip OTP Controller support"
+ depends on ARCH_MXC || COMPILE_TEST
+ depends on HAS_IOMEM
+ depends on OF
+ help
+ This is a driver for the On-Chip OTP Controller (OCOTP)
+ available on i.MX SoCs which has ELE.
+
config NVMEM_IMX_OCOTP_SCU
tristate "i.MX8 SCU On-Chip OTP Controller support"
depends on IMX_SCU
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index f82431ec8aef..cc23ce4ffb1f 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -18,6 +18,8 @@ obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-imx-iim.o
nvmem-imx-iim-y := imx-iim.o
obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o
nvmem-imx-ocotp-y := imx-ocotp.o
+obj-$(CONFIG_NVMEM_IMX_OCOTP_ELE) += nvmem-imx-ocotp-ele.o
+nvmem-imx-ocotp-ele-y := imx-ocotp-ele.o
obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o
nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o
diff --git a/drivers/nvmem/brcm_nvram.c b/drivers/nvmem/brcm_nvram.c
index 39aa27942f28..4567c597c87f 100644
--- a/drivers/nvmem/brcm_nvram.c
+++ b/drivers/nvmem/brcm_nvram.c
@@ -4,6 +4,8 @@
*/
#include <linux/bcm47xx_nvram.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
#include <linux/io.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
@@ -42,6 +44,25 @@ static int brcm_nvram_read(void *context, unsigned int offset, void *val,
return 0;
}
+static int brcm_nvram_read_post_process_macaddr(void *context, const char *id, int index,
+ unsigned int offset, void *buf, size_t bytes)
+{
+ u8 mac[ETH_ALEN];
+
+ if (bytes != 3 * ETH_ALEN - 1)
+ return -EINVAL;
+
+ if (!mac_pton(buf, mac))
+ return -EINVAL;
+
+ if (index)
+ eth_addr_add(mac, index);
+
+ ether_addr_copy(buf, mac);
+
+ return 0;
+}
+
static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data,
size_t len)
{
@@ -75,6 +96,13 @@ static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data,
priv->cells[idx].offset = value - (char *)data;
priv->cells[idx].bytes = strlen(value);
priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
+ if (!strcmp(var, "et0macaddr") ||
+ !strcmp(var, "et1macaddr") ||
+ !strcmp(var, "et2macaddr")) {
+ priv->cells[idx].raw_len = strlen(value);
+ priv->cells[idx].bytes = ETH_ALEN;
+ priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr;
+ }
}
return 0;
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 342cd380b420..3f8c7718412b 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -696,7 +696,7 @@ static int nvmem_validate_keepouts(struct nvmem_device *nvmem)
return 0;
}
-static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
+static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np)
{
struct nvmem_layout *layout = nvmem->layout;
struct device *dev = &nvmem->dev;
@@ -704,7 +704,7 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
const __be32 *addr;
int len, ret;
- for_each_child_of_node(dev->of_node, child) {
+ for_each_child_of_node(np, child) {
struct nvmem_cell_info info = {0};
addr = of_get_property(child, "reg", &len);
@@ -742,6 +742,28 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
return 0;
}
+static int nvmem_add_cells_from_legacy_of(struct nvmem_device *nvmem)
+{
+ return nvmem_add_cells_from_dt(nvmem, nvmem->dev.of_node);
+}
+
+static int nvmem_add_cells_from_fixed_layout(struct nvmem_device *nvmem)
+{
+ struct device_node *layout_np;
+ int err = 0;
+
+ layout_np = of_nvmem_layout_get_container(nvmem);
+ if (!layout_np)
+ return 0;
+
+ if (of_device_is_compatible(layout_np, "fixed-layout"))
+ err = nvmem_add_cells_from_dt(nvmem, layout_np);
+
+ of_node_put(layout_np);
+
+ return err;
+}
+
int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner)
{
layout->owner = owner;
@@ -972,7 +994,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
if (rval)
goto err_remove_cells;
- rval = nvmem_add_cells_from_of(nvmem);
+ rval = nvmem_add_cells_from_legacy_of(nvmem);
if (rval)
goto err_remove_cells;
@@ -982,6 +1004,10 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
if (rval)
goto err_remove_cells;
+ rval = nvmem_add_cells_from_fixed_layout(nvmem);
+ if (rval)
+ goto err_remove_cells;
+
rval = nvmem_add_cells_from_layout(nvmem);
if (rval)
goto err_remove_cells;
diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c
new file mode 100644
index 000000000000..f1cbbc9afeb8
--- /dev/null
+++ b/drivers/nvmem/imx-ocotp-ele.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * i.MX9 OCOTP fusebox driver
+ *
+ * Copyright 2023 NXP
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+enum fuse_type {
+ FUSE_FSB = 1,
+ FUSE_ELE = 2,
+ FUSE_INVALID = -1
+};
+
+struct ocotp_map_entry {
+ u32 start; /* start word */
+ u32 num; /* num words */
+ enum fuse_type type;
+};
+
+struct ocotp_devtype_data {
+ u32 reg_off;
+ char *name;
+ u32 size;
+ u32 num_entry;
+ u32 flag;
+ nvmem_reg_read_t reg_read;
+ struct ocotp_map_entry entry[];
+};
+
+struct imx_ocotp_priv {
+ struct device *dev;
+ void __iomem *base;
+ struct nvmem_config config;
+ struct mutex lock;
+ const struct ocotp_devtype_data *data;
+};
+
+static enum fuse_type imx_ocotp_fuse_type(void *context, u32 index)
+{
+ struct imx_ocotp_priv *priv = context;
+ const struct ocotp_devtype_data *data = priv->data;
+ u32 start, end;
+ int i;
+
+ for (i = 0; i < data->num_entry; i++) {
+ start = data->entry[i].start;
+ end = data->entry[i].start + data->entry[i].num;
+
+ if (index >= start && index < end)
+ return data->entry[i].type;
+ }
+
+ return FUSE_INVALID;
+}
+
+static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, size_t bytes)
+{
+ struct imx_ocotp_priv *priv = context;
+ void __iomem *reg = priv->base + priv->data->reg_off;
+ u32 count, index, num_bytes;
+ enum fuse_type type;
+ u32 *buf;
+ void *p;
+ int i;
+
+ index = offset;
+ num_bytes = round_up(bytes, 4);
+ count = num_bytes >> 2;
+
+ if (count > ((priv->data->size >> 2) - index))
+ count = (priv->data->size >> 2) - index;
+
+ p = kzalloc(num_bytes, GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ mutex_lock(&priv->lock);
+
+ buf = p;
+
+ for (i = index; i < (index + count); i++) {
+ type = imx_ocotp_fuse_type(context, i);
+ if (type == FUSE_INVALID || type == FUSE_ELE) {
+ *buf++ = 0;
+ continue;
+ }
+
+ *buf++ = readl_relaxed(reg + (i << 2));
+ }
+
+ memcpy(val, (u8 *)p, bytes);
+
+ mutex_unlock(&priv->lock);
+
+ kfree(p);
+
+ return 0;
+};
+
+static int imx_ele_ocotp_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct imx_ocotp_priv *priv;
+ struct nvmem_device *nvmem;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->data = of_device_get_match_data(dev);
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ priv->config.dev = dev;
+ priv->config.name = "ELE-OCOTP";
+ priv->config.id = NVMEM_DEVID_AUTO;
+ priv->config.owner = THIS_MODULE;
+ priv->config.size = priv->data->size;
+ priv->config.reg_read = priv->data->reg_read;
+ priv->config.word_size = 4;
+ priv->config.stride = 1;
+ priv->config.priv = priv;
+ priv->config.read_only = true;
+ mutex_init(&priv->lock);
+
+ nvmem = devm_nvmem_register(dev, &priv->config);
+ if (IS_ERR(nvmem))
+ return PTR_ERR(nvmem);
+
+ return 0;
+}
+
+static const struct ocotp_devtype_data imx93_ocotp_data = {
+ .reg_off = 0x8000,
+ .reg_read = imx_ocotp_reg_read,
+ .size = 2048,
+ .num_entry = 6,
+ .entry = {
+ { 0, 52, FUSE_FSB },
+ { 63, 1, FUSE_ELE},
+ { 128, 16, FUSE_ELE },
+ { 182, 1, FUSE_ELE },
+ { 188, 1, FUSE_ELE },
+ { 312, 200, FUSE_FSB }
+ },
+};
+
+static const struct of_device_id imx_ele_ocotp_dt_ids[] = {
+ { .compatible = "fsl,imx93-ocotp", .data = &imx93_ocotp_data, },
+ {},
+};
+MODULE_DEVICE_TABLE(of, imx_ele_ocotp_dt_ids);
+
+static struct platform_driver imx_ele_ocotp_driver = {
+ .driver = {
+ .name = "imx_ele_ocotp",
+ .of_match_table = imx_ele_ocotp_dt_ids,
+ },
+ .probe = imx_ele_ocotp_probe,
+};
+module_platform_driver(imx_ele_ocotp_driver);
+
+MODULE_DESCRIPTION("i.MX OCOTP/ELE driver");
+MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c
index ac0edb6398f1..ab556c011f3e 100644
--- a/drivers/nvmem/imx-ocotp.c
+++ b/drivers/nvmem/imx-ocotp.c
@@ -97,7 +97,6 @@ struct ocotp_params {
unsigned int bank_address_words;
void (*set_timing)(struct ocotp_priv *priv);
struct ocotp_ctrl_reg ctrl;
- bool reverse_mac_address;
};
static int imx_ocotp_wait_for_busy(struct ocotp_priv *priv, u32 flags)
@@ -545,7 +544,6 @@ static const struct ocotp_params imx8mq_params = {
.bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
- .reverse_mac_address = true,
};
static const struct ocotp_params imx8mm_params = {
@@ -553,7 +551,6 @@ static const struct ocotp_params imx8mm_params = {
.bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
- .reverse_mac_address = true,
};
static const struct ocotp_params imx8mn_params = {
@@ -561,7 +558,6 @@ static const struct ocotp_params imx8mn_params = {
.bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
- .reverse_mac_address = true,
};
static const struct ocotp_params imx8mp_params = {
@@ -569,7 +565,6 @@ static const struct ocotp_params imx8mp_params = {
.bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_8MP,
- .reverse_mac_address = true,
};
static const struct of_device_id imx_ocotp_dt_ids[] = {
@@ -596,7 +591,7 @@ static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem,
cell->read_post_process = imx_ocotp_cell_pp;
}
-struct nvmem_layout imx_ocotp_layout = {
+static struct nvmem_layout imx_ocotp_layout = {
.fixup_cell_info = imx_ocotp_fixup_cell_info,
};
@@ -624,8 +619,7 @@ static int imx_ocotp_probe(struct platform_device *pdev)
imx_ocotp_nvmem_config.size = 4 * priv->params->nregs;
imx_ocotp_nvmem_config.dev = dev;
imx_ocotp_nvmem_config.priv = priv;
- if (priv->params->reverse_mac_address)
- imx_ocotp_nvmem_config.layout = &imx_ocotp_layout;
+ imx_ocotp_nvmem_config.layout = &imx_ocotp_layout;
priv->config = &imx_ocotp_nvmem_config;
diff --git a/drivers/nvmem/rmem.c b/drivers/nvmem/rmem.c
index 80cb187f1481..752d0bf4445e 100644
--- a/drivers/nvmem/rmem.c
+++ b/drivers/nvmem/rmem.c
@@ -71,6 +71,7 @@ static int rmem_probe(struct platform_device *pdev)
config.dev = dev;
config.priv = priv;
config.name = "rmem";
+ config.id = NVMEM_DEVID_AUTO;
config.size = mem->size;
config.reg_read = rmem_read;
diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
index 9f53bcce2f87..cb9aa5428350 100644
--- a/drivers/nvmem/rockchip-otp.c
+++ b/drivers/nvmem/rockchip-otp.c
@@ -54,21 +54,32 @@
#define OTPC_TIMEOUT 10000
+/* RK3588 Register */
+#define RK3588_OTPC_AUTO_CTRL 0x04
+#define RK3588_OTPC_AUTO_EN 0x08
+#define RK3588_OTPC_INT_ST 0x84
+#define RK3588_OTPC_DOUT0 0x20
+#define RK3588_NO_SECURE_OFFSET 0x300
+#define RK3588_NBYTES 4
+#define RK3588_BURST_NUM 1
+#define RK3588_BURST_SHIFT 8
+#define RK3588_ADDR_SHIFT 16
+#define RK3588_AUTO_EN BIT(0)
+#define RK3588_RD_DONE BIT(1)
+
+struct rockchip_data {
+ int size;
+ const char * const *clks;
+ int num_clks;
+ nvmem_reg_read_t reg_read;
+};
+
struct rockchip_otp {
struct device *dev;
void __iomem *base;
- struct clk_bulk_data *clks;
- int num_clks;
+ struct clk_bulk_data *clks;
struct reset_control *rst;
-};
-
-/* list of required clocks */
-static const char * const rockchip_otp_clocks[] = {
- "otp", "apb_pclk", "phy",
-};
-
-struct rockchip_data {
- int size;
+ const struct rockchip_data *data;
};
static int rockchip_otp_reset(struct rockchip_otp *otp)
@@ -92,18 +103,19 @@ static int rockchip_otp_reset(struct rockchip_otp *otp)
return 0;
}
-static int rockchip_otp_wait_status(struct rockchip_otp *otp, u32 flag)
+static int rockchip_otp_wait_status(struct rockchip_otp *otp,
+ unsigned int reg, u32 flag)
{
u32 status = 0;
int ret;
- ret = readl_poll_timeout_atomic(otp->base + OTPC_INT_STATUS, status,
+ ret = readl_poll_timeout_atomic(otp->base + reg, status,
(status & flag), 1, OTPC_TIMEOUT);
if (ret)
return ret;
/* clean int status */
- writel(flag, otp->base + OTPC_INT_STATUS);
+ writel(flag, otp->base + reg);
return 0;
}
@@ -125,36 +137,30 @@ static int rockchip_otp_ecc_enable(struct rockchip_otp *otp, bool enable)
writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
- ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
+ ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_SBPI_DONE);
if (ret < 0)
dev_err(otp->dev, "timeout during ecc_enable\n");
return ret;
}
-static int rockchip_otp_read(void *context, unsigned int offset,
- void *val, size_t bytes)
+static int px30_otp_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
{
struct rockchip_otp *otp = context;
u8 *buf = val;
- int ret = 0;
-
- ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks);
- if (ret < 0) {
- dev_err(otp->dev, "failed to prepare/enable clks\n");
- return ret;
- }
+ int ret;
ret = rockchip_otp_reset(otp);
if (ret) {
dev_err(otp->dev, "failed to reset otp phy\n");
- goto disable_clks;
+ return ret;
}
ret = rockchip_otp_ecc_enable(otp, false);
if (ret < 0) {
dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
- goto disable_clks;
+ return ret;
}
writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
@@ -164,7 +170,7 @@ static int rockchip_otp_read(void *context, unsigned int offset,
otp->base + OTPC_USER_ADDR);
writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
otp->base + OTPC_USER_ENABLE);
- ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
+ ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_USER_DONE);
if (ret < 0) {
dev_err(otp->dev, "timeout during read setup\n");
goto read_end;
@@ -174,8 +180,74 @@ static int rockchip_otp_read(void *context, unsigned int offset,
read_end:
writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
-disable_clks:
- clk_bulk_disable_unprepare(otp->num_clks, otp->clks);
+
+ return ret;
+}
+
+static int rk3588_otp_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+ struct rockchip_otp *otp = context;
+ unsigned int addr_start, addr_end, addr_len;
+ int ret, i = 0;
+ u32 data;
+ u8 *buf;
+
+ addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES;
+ addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES;
+ addr_len = addr_end - addr_start;
+ addr_start += RK3588_NO_SECURE_OFFSET;
+
+ buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ while (addr_len--) {
+ writel((addr_start << RK3588_ADDR_SHIFT) |
+ (RK3588_BURST_NUM << RK3588_BURST_SHIFT),
+ otp->base + RK3588_OTPC_AUTO_CTRL);
+ writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN);
+
+ ret = rockchip_otp_wait_status(otp, RK3588_OTPC_INT_ST,
+ RK3588_RD_DONE);
+ if (ret < 0) {
+ dev_err(otp->dev, "timeout during read setup\n");
+ goto read_end;
+ }
+
+ data = readl(otp->base + RK3588_OTPC_DOUT0);
+ memcpy(&buf[i], &data, RK3588_NBYTES);
+
+ i += RK3588_NBYTES;
+ addr_start++;
+ }
+
+ memcpy(val, buf + offset % RK3588_NBYTES, bytes);
+
+read_end:
+ kfree(buf);
+
+ return ret;
+}
+
+static int rockchip_otp_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+ struct rockchip_otp *otp = context;
+ int ret;
+
+ if (!otp->data || !otp->data->reg_read)
+ return -EINVAL;
+
+ ret = clk_bulk_prepare_enable(otp->data->num_clks, otp->clks);
+ if (ret < 0) {
+ dev_err(otp->dev, "failed to prepare/enable clks\n");
+ return ret;
+ }
+
+ ret = otp->data->reg_read(context, offset, val, bytes);
+
+ clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks);
return ret;
}
@@ -189,18 +261,40 @@ static struct nvmem_config otp_config = {
.reg_read = rockchip_otp_read,
};
+static const char * const px30_otp_clocks[] = {
+ "otp", "apb_pclk", "phy",
+};
+
static const struct rockchip_data px30_data = {
.size = 0x40,
+ .clks = px30_otp_clocks,
+ .num_clks = ARRAY_SIZE(px30_otp_clocks),
+ .reg_read = px30_otp_read,
+};
+
+static const char * const rk3588_otp_clocks[] = {
+ "otp", "apb_pclk", "phy", "arb",
+};
+
+static const struct rockchip_data rk3588_data = {
+ .size = 0x400,
+ .clks = rk3588_otp_clocks,
+ .num_clks = ARRAY_SIZE(rk3588_otp_clocks),
+ .reg_read = rk3588_otp_read,
};
static const struct of_device_id rockchip_otp_match[] = {
{
.compatible = "rockchip,px30-otp",
- .data = (void *)&px30_data,
+ .data = &px30_data,
},
{
.compatible = "rockchip,rk3308-otp",
- .data = (void *)&px30_data,
+ .data = &px30_data,
+ },
+ {
+ .compatible = "rockchip,rk3588-otp",
+ .data = &rk3588_data,
},
{ /* sentinel */ },
};
@@ -215,44 +309,47 @@ static int rockchip_otp_probe(struct platform_device *pdev)
int ret, i;
data = of_device_get_match_data(dev);
- if (!data) {
- dev_err(dev, "failed to get match data\n");
- return -EINVAL;
- }
+ if (!data)
+ return dev_err_probe(dev, -EINVAL, "failed to get match data\n");
otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp),
GFP_KERNEL);
if (!otp)
return -ENOMEM;
+ otp->data = data;
otp->dev = dev;
otp->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(otp->base))
- return PTR_ERR(otp->base);
+ return dev_err_probe(dev, PTR_ERR(otp->base),
+ "failed to ioremap resource\n");
- otp->num_clks = ARRAY_SIZE(rockchip_otp_clocks);
- otp->clks = devm_kcalloc(dev, otp->num_clks,
- sizeof(*otp->clks), GFP_KERNEL);
+ otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks),
+ GFP_KERNEL);
if (!otp->clks)
return -ENOMEM;
- for (i = 0; i < otp->num_clks; ++i)
- otp->clks[i].id = rockchip_otp_clocks[i];
+ for (i = 0; i < data->num_clks; ++i)
+ otp->clks[i].id = data->clks[i];
- ret = devm_clk_bulk_get(dev, otp->num_clks, otp->clks);
+ ret = devm_clk_bulk_get(dev, data->num_clks, otp->clks);
if (ret)
- return ret;
+ return dev_err_probe(dev, ret, "failed to get clocks\n");
- otp->rst = devm_reset_control_get(dev, "phy");
+ otp->rst = devm_reset_control_array_get_exclusive(dev);
if (IS_ERR(otp->rst))
- return PTR_ERR(otp->rst);
+ return dev_err_probe(dev, PTR_ERR(otp->rst),
+ "failed to get resets\n");
otp_config.size = data->size;
otp_config.priv = otp;
otp_config.dev = dev;
- nvmem = devm_nvmem_register(dev, &otp_config);
- return PTR_ERR_OR_ZERO(nvmem);
+ nvmem = devm_nvmem_register(dev, &otp_config);
+ if (IS_ERR(nvmem))
+ return dev_err_probe(dev, PTR_ERR(nvmem),
+ "failed to register nvmem device\n");
+ return 0;
}
static struct platform_driver rockchip_otp_driver = {
diff --git a/drivers/nvmem/sunplus-ocotp.c b/drivers/nvmem/sunplus-ocotp.c
index 52b928a7a6d5..f85350b17d67 100644
--- a/drivers/nvmem/sunplus-ocotp.c
+++ b/drivers/nvmem/sunplus-ocotp.c
@@ -192,9 +192,11 @@ static int sp_ocotp_probe(struct platform_device *pdev)
sp_ocotp_nvmem_config.dev = dev;
nvmem = devm_nvmem_register(dev, &sp_ocotp_nvmem_config);
- if (IS_ERR(nvmem))
- return dev_err_probe(&pdev->dev, PTR_ERR(nvmem),
+ if (IS_ERR(nvmem)) {
+ ret = dev_err_probe(&pdev->dev, PTR_ERR(nvmem),
"register nvmem device fail\n");
+ goto err;
+ }
platform_set_drvdata(pdev, nvmem);
@@ -203,6 +205,9 @@ static int sp_ocotp_probe(struct platform_device *pdev)
(int)OTP_WORD_SIZE, (int)QAC628_OTP_SIZE);
return 0;
+err:
+ clk_unprepare(otp->clk);
+ return ret;
}
static const struct of_device_id sp_ocotp_dt_ids[] = {
diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c
index e28d7b133e11..f49bb9a26d05 100644
--- a/drivers/nvmem/zynqmp_nvmem.c
+++ b/drivers/nvmem/zynqmp_nvmem.c
@@ -76,6 +76,6 @@ static struct platform_driver zynqmp_nvmem_driver = {
module_platform_driver(zynqmp_nvmem_driver);
-MODULE_AUTHOR("Michal Simek <michal.simek@xilinx.com>, Nava kishore Manne <navam@xilinx.com>");
+MODULE_AUTHOR("Michal Simek <michal.simek@amd.com>, Nava kishore Manne <nava.kishore.manne@amd.com>");
MODULE_DESCRIPTION("ZynqMP NVMEM driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 948efa9f99e3..7ec94cfcbddb 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -78,6 +78,57 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
}
/*
+ * __reserved_mem_alloc_in_range() - allocate reserved memory described with
+ * 'alloc-ranges'. Choose bottom-up/top-down depending on nearby existing
+ * reserved regions to keep the reserved memory contiguous if possible.
+ */
+static int __init __reserved_mem_alloc_in_range(phys_addr_t size,
+ phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
+ phys_addr_t *res_base)
+{
+ bool prev_bottom_up = memblock_bottom_up();
+ bool bottom_up = false, top_down = false;
+ int ret, i;
+
+ for (i = 0; i < reserved_mem_count; i++) {
+ struct reserved_mem *rmem = &reserved_mem[i];
+
+ /* Skip regions that were not reserved yet */
+ if (rmem->size == 0)
+ continue;
+
+ /*
+ * If range starts next to an existing reservation, use bottom-up:
+ * |....RRRR................RRRRRRRR..............|
+ * --RRRR------
+ */
+ if (start >= rmem->base && start <= (rmem->base + rmem->size))
+ bottom_up = true;
+
+ /*
+ * If range ends next to an existing reservation, use top-down:
+ * |....RRRR................RRRRRRRR..............|
+ * -------RRRR-----
+ */
+ if (end >= rmem->base && end <= (rmem->base + rmem->size))
+ top_down = true;
+ }
+
+ /* Change setting only if either bottom-up or top-down was selected */
+ if (bottom_up != top_down)
+ memblock_set_bottom_up(bottom_up);
+
+ ret = early_init_dt_alloc_reserved_memory_arch(size, align,
+ start, end, nomap, res_base);
+
+ /* Restore old setting if needed */
+ if (bottom_up != top_down)
+ memblock_set_bottom_up(prev_bottom_up);
+
+ return ret;
+}
+
+/*
* __reserved_mem_alloc_size() - allocate reserved memory described by
* 'size', 'alignment' and 'alloc-ranges' properties.
*/
@@ -137,8 +188,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
end = start + dt_mem_next_cell(dt_root_size_cells,
&prop);
- ret = early_init_dt_alloc_reserved_memory_arch(size,
- align, start, end, nomap, &base);
+ ret = __reserved_mem_alloc_in_range(size, align,
+ start, end, nomap, &base);
if (ret == 0) {
pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n",
uname, &base,
@@ -217,6 +268,11 @@ static int __init __rmem_cmp(const void *a, const void *b)
if (ra->size > rb->size)
return 1;
+ if (ra->fdt_node < rb->fdt_node)
+ return -1;
+ if (ra->fdt_node > rb->fdt_node)
+ return 1;
+
return 0;
}
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 78ae84187449..051e29b7ad2b 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -140,8 +140,8 @@ struct platform_device *of_device_alloc(struct device_node *np,
}
}
- dev->dev.of_node = of_node_get(np);
- dev->dev.fwnode = &np->fwnode;
+ /* setup generic device info */
+ device_set_node(&dev->dev, of_fwnode_handle(np));
dev->dev.parent = parent ? : &platform_bus;
if (bus_id)
@@ -239,8 +239,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
/* setup generic device info */
- dev->dev.of_node = of_node_get(node);
- dev->dev.fwnode = &node->fwnode;
+ device_set_node(&dev->dev, of_fwnode_handle(node));
dev->dev.parent = parent ? : &platform_bus;
dev->dev.platform_data = platform_data;
if (bus_id)
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 2191c0136531..a406a12eb208 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -1844,26 +1844,10 @@ static void __init of_unittest_overlay_gpio(void)
unittest(overlay_data_apply("overlay_gpio_02b", NULL),
"Adding overlay 'overlay_gpio_02b' failed\n");
- /*
- * messages are the result of the probes, after the
- * driver is registered
- */
-
- EXPECT_BEGIN(KERN_INFO,
- "gpio-<<int>> (line-B-input): hogged as input\n");
-
- EXPECT_BEGIN(KERN_INFO,
- "gpio-<<int>> (line-A-input): hogged as input\n");
-
ret = platform_driver_register(&unittest_gpio_driver);
if (unittest(ret == 0, "could not register unittest gpio driver\n"))
return;
- EXPECT_END(KERN_INFO,
- "gpio-<<int>> (line-A-input): hogged as input\n");
- EXPECT_END(KERN_INFO,
- "gpio-<<int>> (line-B-input): hogged as input\n");
-
unittest(probe_pass_count + 2 == unittest_gpio_probe_pass_count,
"unittest_gpio_probe() failed or not called\n");
@@ -1888,17 +1872,11 @@ static void __init of_unittest_overlay_gpio(void)
probe_pass_count = unittest_gpio_probe_pass_count;
chip_request_count = unittest_gpio_chip_request_count;
- EXPECT_BEGIN(KERN_INFO,
- "gpio-<<int>> (line-D-input): hogged as input\n");
-
/* overlay_gpio_03 contains gpio node and child gpio hog node */
unittest(overlay_data_apply("overlay_gpio_03", NULL),
"Adding overlay 'overlay_gpio_03' failed\n");
- EXPECT_END(KERN_INFO,
- "gpio-<<int>> (line-D-input): hogged as input\n");
-
unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count,
"unittest_gpio_probe() failed or not called\n");
@@ -1935,17 +1913,11 @@ static void __init of_unittest_overlay_gpio(void)
* - processing gpio for overlay_gpio_04b
*/
- EXPECT_BEGIN(KERN_INFO,
- "gpio-<<int>> (line-C-input): hogged as input\n");
-
/* overlay_gpio_04b contains child gpio hog node */
unittest(overlay_data_apply("overlay_gpio_04b", NULL),
"Adding overlay 'overlay_gpio_04b' failed\n");
- EXPECT_END(KERN_INFO,
- "gpio-<<int>> (line-C-input): hogged as input\n");
-
unittest(chip_request_count + 1 == unittest_gpio_chip_request_count,
"unittest_gpio_chip_request() called %d times (expected 1 time)\n",
unittest_gpio_chip_request_count - chip_request_count);
@@ -2686,7 +2658,7 @@ static struct i2c_driver unittest_i2c_dev_driver = {
.driver = {
.name = "unittest-i2c-dev",
},
- .probe_new = unittest_i2c_dev_probe,
+ .probe = unittest_i2c_dev_probe,
.remove = unittest_i2c_dev_remove,
.id_table = unittest_i2c_dev_id,
};
@@ -2763,7 +2735,7 @@ static struct i2c_driver unittest_i2c_mux_driver = {
.driver = {
.name = "unittest-i2c-mux",
},
- .probe_new = unittest_i2c_mux_probe,
+ .probe = unittest_i2c_mux_probe,
.remove = unittest_i2c_mux_remove,
.id_table = unittest_i2c_mux_id,
};
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 954c94865cf5..3f46e499d615 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -29,9 +29,6 @@
*/
LIST_HEAD(opp_tables);
-/* OPP tables with uninitialized required OPPs */
-LIST_HEAD(lazy_opp_tables);
-
/* Lock to allow exclusive modification to the device and opp lists */
DEFINE_MUTEX(opp_table_lock);
/* Flag indicating that opp_tables list is being updated at the moment */
@@ -230,17 +227,25 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_level);
unsigned int dev_pm_opp_get_required_pstate(struct dev_pm_opp *opp,
unsigned int index)
{
+ struct opp_table *opp_table = opp->opp_table;
+
if (IS_ERR_OR_NULL(opp) || !opp->available ||
- index >= opp->opp_table->required_opp_count) {
+ index >= opp_table->required_opp_count) {
pr_err("%s: Invalid parameters\n", __func__);
return 0;
}
/* required-opps not fully initialized yet */
- if (lazy_linking_pending(opp->opp_table))
+ if (lazy_linking_pending(opp_table))
return 0;
- return opp->required_opps[index]->pstate;
+ /* The required OPP table must belong to a genpd */
+ if (unlikely(!opp_table->required_opp_tables[index]->is_genpd)) {
+ pr_err("%s: Performance state is only valid for genpds.\n", __func__);
+ return 0;
+ }
+
+ return opp->required_opps[index]->level;
}
EXPORT_SYMBOL_GPL(dev_pm_opp_get_required_pstate);
@@ -938,7 +943,7 @@ static int _set_opp_bw(const struct opp_table *opp_table,
static int _set_performance_state(struct device *dev, struct device *pd_dev,
struct dev_pm_opp *opp, int i)
{
- unsigned int pstate = likely(opp) ? opp->required_opps[i]->pstate : 0;
+ unsigned int pstate = likely(opp) ? opp->required_opps[i]->level: 0;
int ret;
if (!pd_dev)
@@ -1091,7 +1096,7 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
/* Return early if nothing to do */
if (!forced && old_opp == opp && opp_table->enabled) {
- dev_dbg(dev, "%s: OPPs are same, nothing to do\n", __func__);
+ dev_dbg_ratelimited(dev, "%s: OPPs are same, nothing to do\n", __func__);
return 0;
}
@@ -1358,7 +1363,10 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
return opp_table;
remove_opp_dev:
+ _of_clear_opp_table(opp_table);
_remove_opp_dev(opp_dev, opp_table);
+ mutex_destroy(&opp_table->genpd_virt_dev_lock);
+ mutex_destroy(&opp_table->lock);
err:
kfree(opp_table);
return ERR_PTR(ret);
@@ -1522,16 +1530,8 @@ static void _opp_table_kref_release(struct kref *kref)
WARN_ON(!list_empty(&opp_table->opp_list));
- list_for_each_entry_safe(opp_dev, temp, &opp_table->dev_list, node) {
- /*
- * The OPP table is getting removed, drop the performance state
- * constraints.
- */
- if (opp_table->genpd_performance_state)
- dev_pm_genpd_set_performance_state((struct device *)(opp_dev->dev), 0);
-
+ list_for_each_entry_safe(opp_dev, temp, &opp_table->dev_list, node)
_remove_opp_dev(opp_dev, opp_table);
- }
mutex_destroy(&opp_table->genpd_virt_dev_lock);
mutex_destroy(&opp_table->lock);
@@ -2704,6 +2704,12 @@ int dev_pm_opp_xlate_performance_state(struct opp_table *src_table,
if (!src_table || !src_table->required_opp_count)
return pstate;
+ /* Both OPP tables must belong to genpds */
+ if (unlikely(!src_table->is_genpd || !dst_table->is_genpd)) {
+ pr_err("%s: Performance state is only valid for genpds.\n", __func__);
+ return -EINVAL;
+ }
+
/* required-opps not fully initialized yet */
if (lazy_linking_pending(src_table))
return -EBUSY;
@@ -2722,8 +2728,8 @@ int dev_pm_opp_xlate_performance_state(struct opp_table *src_table,
mutex_lock(&src_table->lock);
list_for_each_entry(opp, &src_table->opp_list, node) {
- if (opp->pstate == pstate) {
- dest_pstate = opp->required_opps[i]->pstate;
+ if (opp->level == pstate) {
+ dest_pstate = opp->required_opps[i]->level;
goto unlock;
}
}
diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c
index 2c7fb683441e..17543c0aa5b6 100644
--- a/drivers/opp/debugfs.c
+++ b/drivers/opp/debugfs.c
@@ -152,7 +152,6 @@ void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
debugfs_create_bool("dynamic", S_IRUGO, d, &opp->dynamic);
debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo);
debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend);
- debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate);
debugfs_create_u32("level", S_IRUGO, d, &opp->level);
debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
&opp->clock_latency_ns);
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 8246e9b7afe7..ada4963c7cfa 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -21,6 +21,9 @@
#include "opp.h"
+/* OPP tables with uninitialized required OPPs, protected by opp_table_lock */
+static LIST_HEAD(lazy_opp_tables);
+
/*
* Returns opp descriptor node for a device node, caller must
* do of_node_put().
@@ -145,7 +148,10 @@ static void _opp_table_free_required_tables(struct opp_table *opp_table)
opp_table->required_opp_count = 0;
opp_table->required_opp_tables = NULL;
+
+ mutex_lock(&opp_table_lock);
list_del(&opp_table->lazy);
+ mutex_unlock(&opp_table_lock);
}
/*
@@ -194,8 +200,15 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table,
}
/* Let's do the linking later on */
- if (lazy)
+ if (lazy) {
+ /*
+ * The OPP table is not held while allocating the table, take it
+ * now to avoid corruption to the lazy_opp_tables list.
+ */
+ mutex_lock(&opp_table_lock);
list_add(&opp_table->lazy, &lazy_opp_tables);
+ mutex_unlock(&opp_table_lock);
+ }
else
_update_set_required_opps(opp_table);
@@ -500,11 +513,7 @@ int dev_pm_opp_of_find_icc_paths(struct device *dev,
for (i = 0; i < num_paths; i++) {
paths[i] = of_icc_get_by_index(dev, i);
if (IS_ERR(paths[i])) {
- ret = PTR_ERR(paths[i]);
- if (ret != -EPROBE_DEFER) {
- dev_err(dev, "%s: Unable to get path%d: %d\n",
- __func__, i, ret);
- }
+ ret = dev_err_probe(dev, PTR_ERR(paths[i]), "%s: Unable to get path%d\n", __func__, i);
goto err;
}
}
@@ -932,9 +941,6 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
if (ret)
goto free_required_opps;
- if (opp_table->is_genpd)
- new_opp->pstate = pm_genpd_opp_to_performance_state(dev, new_opp);
-
ret = _opp_add(dev, new_opp, opp_table);
if (ret) {
/* Don't return error for duplicate OPPs */
@@ -1021,14 +1027,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
goto remove_static_opp;
}
- list_for_each_entry(opp, &opp_table->opp_list, node) {
- /* Any non-zero performance state would enable the feature */
- if (opp->pstate) {
- opp_table->genpd_performance_state = true;
- break;
- }
- }
-
lazy_link_required_opp_table(opp_table);
return 0;
@@ -1387,9 +1385,15 @@ int of_get_required_opp_performance_state(struct device_node *np, int index)
goto put_required_np;
}
+ /* The OPP tables must belong to a genpd */
+ if (unlikely(!opp_table->is_genpd)) {
+ pr_err("%s: Performance state is only valid for genpds.\n", __func__);
+ goto put_required_np;
+ }
+
opp = _find_opp_of_np(opp_table, required_np);
if (opp) {
- pstate = opp->pstate;
+ pstate = opp->level;
dev_pm_opp_put(opp);
}
diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
index 2a057c42ddf4..8a5ea38f3a3d 100644
--- a/drivers/opp/opp.h
+++ b/drivers/opp/opp.h
@@ -26,7 +26,7 @@ struct regulator;
/* Lock to allow exclusive modification to the device and opp lists */
extern struct mutex opp_table_lock;
-extern struct list_head opp_tables, lazy_opp_tables;
+extern struct list_head opp_tables;
/* OPP Config flags */
#define OPP_CONFIG_CLK BIT(0)
@@ -78,7 +78,6 @@ struct opp_config_data {
* @turbo: true if turbo (boost) OPP
* @suspend: true if suspend OPP
* @removed: flag indicating that OPP's reference is dropped by OPP core.
- * @pstate: Device's power domain's performance state.
* @rates: Frequencies in hertz
* @level: Performance level
* @supplies: Power supplies voltage/current values
@@ -101,7 +100,6 @@ struct dev_pm_opp {
bool turbo;
bool suspend;
bool removed;
- unsigned int pstate;
unsigned long *rates;
unsigned int level;
@@ -182,7 +180,6 @@ enum opp_table_access {
* @paths: Interconnect path handles
* @path_count: Number of interconnect paths
* @enabled: Set to true if the device's resources are enabled/configured.
- * @genpd_performance_state: Device's power domain support performance state.
* @is_genpd: Marks if the OPP table belongs to a genpd.
* @set_required_opps: Helper responsible to set required OPPs.
* @dentry: debugfs dentry pointer of the real device directory (not links).
@@ -233,7 +230,6 @@ struct opp_table {
struct icc_path **paths;
unsigned int path_count;
bool enabled;
- bool genpd_performance_state;
bool is_genpd;
int (*set_required_opps)(struct device *dev,
struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down);
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index a66386043aa6..9bf652bd002c 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -97,7 +97,6 @@
#define DBG_RUN_SG(x...)
#endif
-#define CCIO_INLINE inline
#define WRITE_U32(value, addr) __raw_writel(value, addr)
#define READ_U32(addr) __raw_readl(addr)
@@ -330,7 +329,8 @@ static int ioc_count;
/**
* ccio_alloc_range - Allocate pages in the ioc's resource map.
* @ioc: The I/O Controller.
- * @pages_needed: The requested number of pages to be mapped into the
+ * @dev: The PCI device.
+ * @size: The requested number of bytes to be mapped into the
* I/O Pdir...
*
* This function searches the resource map of the ioc to locate a range
@@ -552,7 +552,7 @@ static u32 hint_lookup[] = {
* (Load Coherence Index) instruction. The 8 bits used for the virtual
* index are bits 12:19 of the value returned by LCI.
*/
-static void CCIO_INLINE
+static void
ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
unsigned long hints)
{
@@ -623,7 +623,7 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
*
* FIXME: Can we change the byte_cnt to pages_mapped?
*/
-static CCIO_INLINE void
+static void
ccio_clear_io_tlb(struct ioc *ioc, dma_addr_t iovp, size_t byte_cnt)
{
u32 chain_size = 1 << ioc->chainid_shift;
@@ -656,7 +656,7 @@ ccio_clear_io_tlb(struct ioc *ioc, dma_addr_t iovp, size_t byte_cnt)
*
* FIXME: Can we change byte_cnt to pages_mapped?
*/
-static CCIO_INLINE void
+static void
ccio_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
{
u32 iovp = (u32)CCIO_IOVP(iova);
@@ -795,9 +795,10 @@ ccio_map_page(struct device *dev, struct page *page, unsigned long offset,
/**
* ccio_unmap_page - Unmap an address range from the IOMMU.
* @dev: The PCI device.
- * @addr: The start address of the DMA region.
+ * @iova: The start address of the DMA region.
* @size: The length of the DMA region.
* @direction: The direction of the DMA transaction (to/from device).
+ * @attrs: attributes
*/
static void
ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
@@ -838,6 +839,8 @@ ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
* @dev: The PCI device.
* @size: The length of the DMA region.
* @dma_handle: The DMA address handed back to the device (not the cpu).
+ * @flag: allocation flags
+ * @attrs: attributes
*
* This function implements the pci_alloc_consistent function.
*/
@@ -872,6 +875,7 @@ ccio_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag,
* @size: The length of the DMA region.
* @cpu_addr: The cpu address returned from the ccio_alloc_consistent.
* @dma_handle: The device address returned from the ccio_alloc_consistent.
+ * @attrs: attributes
*
* This function implements the pci_free_consistent function.
*/
@@ -901,6 +905,7 @@ ccio_free(struct device *dev, size_t size, void *cpu_addr,
* @sglist: The scatter/gather list to be mapped in the IOMMU.
* @nents: The number of entries in the scatter/gather list.
* @direction: The direction of the DMA transaction (to/from device).
+ * @attrs: attributes
*
* This function implements the pci_map_sg function.
*/
@@ -980,6 +985,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
* @sglist: The scatter/gather list to be unmapped from the IOMMU.
* @nents: The number of entries in the scatter/gather list.
* @direction: The direction of the DMA transaction (to/from device).
+ * @attrs: attributes
*
* This function implements the pci_unmap_sg function.
*/
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index e33036281327..f89f9fb4c84b 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -924,8 +924,6 @@ static const char cujo_vers[][4] = {
"2.0"
};
-void ccio_cujo20_fixup(struct parisc_device *dev, u32 iovp);
-
/*
** Determine if dino should claim this chip (return 0) or not (return 1).
** If so, initialize the chip appropriately (card-mode vs bridge mode).
@@ -1086,9 +1084,8 @@ static struct parisc_driver dino_driver __refdata = {
* This is the only routine which is NOT static.
* Must be called exactly once before pci_init().
*/
-int __init dino_init(void)
+void __init dino_init(void)
{
register_parisc_driver(&dino_driver);
- return 0;
}
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index f96e5eaee87e..45e487388c6e 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -400,7 +400,7 @@ static struct parisc_driver eisa_driver __refdata = {
.probe = eisa_probe,
};
-void __init eisa_init(void)
+void __init parisc_eisa_init(void)
{
register_parisc_driver(&eisa_driver);
}
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index afc6e66ddc31..702bfd64e6e1 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -404,7 +404,7 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int
static void
lba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
{
- int error = 0;
+ int error __maybe_unused = 0;
u32 arb_mask = 0;
u32 error_config = 0;
u32 status_control = 0;
@@ -1018,7 +1018,7 @@ static void
lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
{
unsigned long bytecnt;
- long io_count;
+ long io_count __maybe_unused;
long status; /* PDC return status */
long pa_count;
pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; /* PA_VIEW */
@@ -1164,10 +1164,6 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
#endif /* CONFIG_64BIT */
-extern void sba_distributed_lmmio(struct parisc_device *, struct resource *);
-extern void sba_directed_lmmio(struct parisc_device *, struct resource *);
-
-
static void
lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
{
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 2a18f7ba2398..633266447e2f 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -509,6 +509,8 @@ static struct pdcspath_entry *pdcspath_entries[] = {
/**
* pdcs_size_read - Stable Storage size output.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The output buffer to write to.
*/
static ssize_t pdcs_size_read(struct kobject *kobj,
@@ -528,6 +530,8 @@ static ssize_t pdcs_size_read(struct kobject *kobj,
/**
* pdcs_auto_read - Stable Storage autoboot/search flag output.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The output buffer to write to.
* @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag
*/
@@ -554,6 +558,8 @@ static ssize_t pdcs_auto_read(struct kobject *kobj,
/**
* pdcs_autoboot_read - Stable Storage autoboot flag output.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The output buffer to write to.
*/
static ssize_t pdcs_autoboot_read(struct kobject *kobj,
@@ -564,6 +570,8 @@ static ssize_t pdcs_autoboot_read(struct kobject *kobj,
/**
* pdcs_autosearch_read - Stable Storage autoboot flag output.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The output buffer to write to.
*/
static ssize_t pdcs_autosearch_read(struct kobject *kobj,
@@ -574,6 +582,8 @@ static ssize_t pdcs_autosearch_read(struct kobject *kobj,
/**
* pdcs_timer_read - Stable Storage timer count output (in seconds).
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The output buffer to write to.
*
* The value of the timer field correponds to a number of seconds in powers of 2.
@@ -601,6 +611,8 @@ static ssize_t pdcs_timer_read(struct kobject *kobj,
/**
* pdcs_osid_read - Stable Storage OS ID register output.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The output buffer to write to.
*/
static ssize_t pdcs_osid_read(struct kobject *kobj,
@@ -619,6 +631,8 @@ static ssize_t pdcs_osid_read(struct kobject *kobj,
/**
* pdcs_osdep1_read - Stable Storage OS-Dependent data area 1 output.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The output buffer to write to.
*
* This can hold 16 bytes of OS-Dependent data.
@@ -645,6 +659,8 @@ static ssize_t pdcs_osdep1_read(struct kobject *kobj,
/**
* pdcs_diagnostic_read - Stable Storage Diagnostic register output.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The output buffer to write to.
*
* I have NFC how to interpret the content of that register ;-).
@@ -669,6 +685,8 @@ static ssize_t pdcs_diagnostic_read(struct kobject *kobj,
/**
* pdcs_fastsize_read - Stable Storage FastSize register output.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The output buffer to write to.
*
* This register holds the amount of system RAM to be tested during boot sequence.
@@ -697,6 +715,8 @@ static ssize_t pdcs_fastsize_read(struct kobject *kobj,
/**
* pdcs_osdep2_read - Stable Storage OS-Dependent data area 2 output.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The output buffer to write to.
*
* This can hold pdcs_size - 224 bytes of OS-Dependent data, when available.
@@ -729,6 +749,8 @@ static ssize_t pdcs_osdep2_read(struct kobject *kobj,
/**
* pdcs_auto_write - This function handles autoboot/search flag modifying.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The input buffer to read from.
* @count: The number of bytes to be read.
* @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag
@@ -801,6 +823,8 @@ parse_error:
/**
* pdcs_autoboot_write - This function handles autoboot flag modifying.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The input buffer to read from.
* @count: The number of bytes to be read.
*
@@ -817,6 +841,8 @@ static ssize_t pdcs_autoboot_write(struct kobject *kobj,
/**
* pdcs_autosearch_write - This function handles autosearch flag modifying.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The input buffer to read from.
* @count: The number of bytes to be read.
*
@@ -833,6 +859,8 @@ static ssize_t pdcs_autosearch_write(struct kobject *kobj,
/**
* pdcs_osdep1_write - Stable Storage OS-Dependent data area 1 input.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The input buffer to read from.
* @count: The number of bytes to be read.
*
@@ -870,6 +898,8 @@ static ssize_t pdcs_osdep1_write(struct kobject *kobj,
/**
* pdcs_osdep2_write - Stable Storage OS-Dependent data area 2 input.
+ * @kobj: The kobject used to share data with userspace.
+ * @attr: The kobject attributes.
* @buf: The input buffer to read from.
* @count: The number of bytes to be read.
*
@@ -1023,7 +1053,7 @@ pdcs_unregister_pathentries(void)
static int __init
pdc_stable_init(void)
{
- int rc = 0, error = 0;
+ int rc = 0, error;
u32 result;
/* find the size of the stable storage */
@@ -1052,6 +1082,10 @@ pdc_stable_init(void)
/* Don't forget the root entries */
error = sysfs_create_group(stable_kobj, &pdcs_attr_group);
+ if (error) {
+ rc = -ENOMEM;
+ goto fail_ksetreg;
+ }
/* register the paths kset as a child of the stable kset */
paths_kset = kset_create_and_add("paths", NULL, stable_kobj);
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index ecd870087a3d..bf3405f4289e 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -95,8 +95,6 @@
#define DBG_RES(x...)
#endif
-#define SBA_INLINE __inline__
-
#define DEFAULT_DMA_HINT_REG 0
struct sba_device *sba_list;
@@ -332,13 +330,14 @@ static unsigned long ptr_to_pide(struct ioc *ioc, unsigned long *res_ptr,
/**
* sba_search_bitmap - find free space in IO PDIR resource bitmap
* @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @dev: device to query the bitmap for
* @bits_wanted: number of entries we need.
*
* Find consecutive free bits in resource bitmap.
* Each bit represents one entry in the IO Pdir.
* Cool perf optimization: search for log2(size) bits at a time.
*/
-static SBA_INLINE unsigned long
+static unsigned long
sba_search_bitmap(struct ioc *ioc, struct device *dev,
unsigned long bits_wanted)
{
@@ -431,6 +430,7 @@ sba_search_bitmap(struct ioc *ioc, struct device *dev,
/**
* sba_alloc_range - find free bits and mark them in IO PDIR resource bitmap
* @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @dev: device for which pages should be alloced
* @size: number of bytes to create a mapping for
*
* Given a size, find consecutive unmarked and then mark those bits in the
@@ -490,7 +490,7 @@ sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
*
* clear bits in the ioc's resource map
*/
-static SBA_INLINE void
+static void
sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size)
{
unsigned long iovp = SBA_IOVP(ioc, iova);
@@ -568,7 +568,7 @@ typedef unsigned long space_t;
* IOMMU uses little endian for the pdir.
*/
-static void SBA_INLINE
+static void
sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
unsigned long hint)
{
@@ -609,7 +609,7 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
* must be a power of 2. The "Cool perf optimization" in the
* allocation routine helps keep that true.
*/
-static SBA_INLINE void
+static void
sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
{
u32 iovp = (u32) SBA_IOVP(ioc,iova);
@@ -793,6 +793,7 @@ sba_map_page(struct device *dev, struct page *page, unsigned long offset,
* @iova: IOVA of driver buffer previously mapped.
* @size: number of bytes mapped in driver buffer.
* @direction: R/W or both.
+ * @attrs: attributes
*
* See Documentation/core-api/dma-api-howto.rst
*/
@@ -872,6 +873,8 @@ sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
* @hwdev: instance of PCI owned by the driver that's asking.
* @size: number of bytes mapped in driver buffer.
* @dma_handle: IOVA of new buffer.
+ * @gfp: allocation flags
+ * @attrs: attributes
*
* See Documentation/core-api/dma-api-howto.rst
*/
@@ -902,7 +905,8 @@ static void *sba_alloc(struct device *hwdev, size_t size, dma_addr_t *dma_handle
* @hwdev: instance of PCI owned by the driver that's asking.
* @size: number of bytes mapped in driver buffer.
* @vaddr: virtual address IOVA of "consistent" buffer.
- * @dma_handler: IO virtual address of "consistent" buffer.
+ * @dma_handle: IO virtual address of "consistent" buffer.
+ * @attrs: attributes
*
* See Documentation/core-api/dma-api-howto.rst
*/
@@ -938,6 +942,7 @@ int dump_run_sg = 0;
* @sglist: array of buffer/length pairs
* @nents: number of entries in list
* @direction: R/W or both.
+ * @attrs: attributes
*
* See Documentation/core-api/dma-api-howto.rst
*/
@@ -946,7 +951,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
enum dma_data_direction direction, unsigned long attrs)
{
struct ioc *ioc;
- int coalesced, filled = 0;
+ int filled = 0;
unsigned long flags;
DBG_RUN_SG("%s() START %d entries\n", __func__, nents);
@@ -985,7 +990,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
** w/o this association, we wouldn't have coherent DMA!
** Access to the virtual address is what forces a two pass algorithm.
*/
- coalesced = iommu_coalesce_chunks(ioc, dev, sglist, nents, sba_alloc_range);
+ iommu_coalesce_chunks(ioc, dev, sglist, nents, sba_alloc_range);
/*
** Program the I/O Pdir
@@ -1022,6 +1027,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
* @sglist: array of buffer/length pairs
* @nents: number of entries in list
* @direction: R/W or both.
+ * @attrs: attributes
*
* See Documentation/core-api/dma-api-howto.rst
*/
@@ -1229,8 +1235,6 @@ struct ibase_data_struct {
static int setup_ibase_imask_callback(struct device *dev, void *data)
{
- /* lba_set_iregs() is in drivers/parisc/lba_pci.c */
- extern void lba_set_iregs(struct parisc_device *, u32, u32);
struct parisc_device *lba = to_parisc_device(dev);
struct ibase_data_struct *ibd = data;
int rope_num = (lba->hpa.start >> 13) & 0xf;
@@ -1992,7 +1996,7 @@ void __init sba_init(void)
/**
* sba_get_iommu - Assign the iommu pointer for the pci bus controller.
- * @dev: The parisc device.
+ * @pci_hba: The parisc device.
*
* Returns the appropriate IOMMU data for the given parisc PCI controller.
* This is cached and used later for PCI DMA Mapping.
@@ -2012,7 +2016,7 @@ void * sba_get_iommu(struct parisc_device *pci_hba)
/**
* sba_directed_lmmio - return first directed LMMIO range routed to rope
- * @pa_dev: The parisc device.
+ * @pci_hba: The parisc device.
* @r: resource PCI host controller wants start/end fields assigned.
*
* For the given parisc PCI controller, determine if any direct ranges
@@ -2054,7 +2058,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r)
/**
* sba_distributed_lmmio - return portion of distributed LMMIO range
- * @pa_dev: The parisc device.
+ * @pci_hba: The parisc device.
* @r: resource PCI host controller wants start/end fields assigned.
*
* For the given parisc PCI controller, return portion of distributed LMMIO
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 5561362224e2..631c193fe42c 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -42,7 +42,8 @@ if PARPORT
config PARPORT_PC
tristate "PC-style hardware"
- depends on ARCH_MIGHT_HAVE_PC_PARPORT || (PCI && !S390)
+ depends on ARCH_MIGHT_HAVE_PC_PARPORT || PCI
+ depends on HAS_IOPORT
help
You should say Y here if you have a PC-style parallel port. All
IBM PC compatible computers and some Alphas have PC-style
diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c
index cc83a8925ce0..e70213c9060a 100644
--- a/drivers/pci/controller/cadence/pci-j721e.c
+++ b/drivers/pci/controller/cadence/pci-j721e.c
@@ -542,7 +542,7 @@ err_get_sync:
return ret;
}
-static int j721e_pcie_remove(struct platform_device *pdev)
+static void j721e_pcie_remove(struct platform_device *pdev)
{
struct j721e_pcie *pcie = platform_get_drvdata(pdev);
struct cdns_pcie *cdns_pcie = pcie->cdns_pcie;
@@ -552,13 +552,11 @@ static int j721e_pcie_remove(struct platform_device *pdev)
cdns_pcie_disable_phy(cdns_pcie);
pm_runtime_put(dev);
pm_runtime_disable(dev);
-
- return 0;
}
static struct platform_driver j721e_pcie_driver = {
.probe = j721e_pcie_probe,
- .remove = j721e_pcie_remove,
+ .remove_new = j721e_pcie_remove,
.driver = {
.name = "j721e-pcie",
.of_match_table = of_j721e_pcie_match,
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c
index 940c7dd701d6..5b14f7ee3c79 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host.c
@@ -12,6 +12,8 @@
#include "pcie-cadence.h"
+#define LINK_RETRAIN_TIMEOUT HZ
+
static u64 bar_max_size[] = {
[RP_BAR0] = _ULL(128 * SZ_2G),
[RP_BAR1] = SZ_2G,
@@ -77,6 +79,27 @@ static struct pci_ops cdns_pcie_host_ops = {
.write = pci_generic_config_write,
};
+static int cdns_pcie_host_training_complete(struct cdns_pcie *pcie)
+{
+ u32 pcie_cap_off = CDNS_PCIE_RP_CAP_OFFSET;
+ unsigned long end_jiffies;
+ u16 lnk_stat;
+
+ /* Wait for link training to complete. Exit after timeout. */
+ end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT;
+ do {
+ lnk_stat = cdns_pcie_rp_readw(pcie, pcie_cap_off + PCI_EXP_LNKSTA);
+ if (!(lnk_stat & PCI_EXP_LNKSTA_LT))
+ break;
+ usleep_range(0, 1000);
+ } while (time_before(jiffies, end_jiffies));
+
+ if (!(lnk_stat & PCI_EXP_LNKSTA_LT))
+ return 0;
+
+ return -ETIMEDOUT;
+}
+
static int cdns_pcie_host_wait_for_link(struct cdns_pcie *pcie)
{
struct device *dev = pcie->dev;
@@ -118,6 +141,10 @@ static int cdns_pcie_retrain(struct cdns_pcie *pcie)
cdns_pcie_rp_writew(pcie, pcie_cap_off + PCI_EXP_LNKCTL,
lnk_ctl);
+ ret = cdns_pcie_host_training_complete(pcie);
+ if (ret)
+ return ret;
+
ret = cdns_pcie_host_wait_for_link(pcie);
}
return ret;
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 52906f999f2b..27aaa2a6bf39 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -80,6 +80,7 @@ struct imx6_pcie {
struct clk *pcie;
struct clk *pcie_aux;
struct regmap *iomuxc_gpr;
+ u16 msi_ctrl;
u32 controller_id;
struct reset_control *pciephy_reset;
struct reset_control *apps_reset;
@@ -1178,6 +1179,26 @@ pm_turnoff_sleep:
usleep_range(1000, 10000);
}
+static void imx6_pcie_msi_save_restore(struct imx6_pcie *imx6_pcie, bool save)
+{
+ u8 offset;
+ u16 val;
+ struct dw_pcie *pci = imx6_pcie->pci;
+
+ if (pci_msi_enabled()) {
+ offset = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI);
+ if (save) {
+ val = dw_pcie_readw_dbi(pci, offset + PCI_MSI_FLAGS);
+ imx6_pcie->msi_ctrl = val;
+ } else {
+ dw_pcie_dbi_ro_wr_en(pci);
+ val = imx6_pcie->msi_ctrl;
+ dw_pcie_writew_dbi(pci, offset + PCI_MSI_FLAGS, val);
+ dw_pcie_dbi_ro_wr_dis(pci);
+ }
+ }
+}
+
static int imx6_pcie_suspend_noirq(struct device *dev)
{
struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
@@ -1186,6 +1207,7 @@ static int imx6_pcie_suspend_noirq(struct device *dev)
if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND))
return 0;
+ imx6_pcie_msi_save_restore(imx6_pcie, true);
imx6_pcie_pm_turnoff(imx6_pcie);
imx6_pcie_stop_link(imx6_pcie->pci);
imx6_pcie_host_exit(pp);
@@ -1205,6 +1227,7 @@ static int imx6_pcie_resume_noirq(struct device *dev)
ret = imx6_pcie_host_init(pp);
if (ret)
return ret;
+ imx6_pcie_msi_save_restore(imx6_pcie, false);
dw_pcie_setup_rc(pp);
if (imx6_pcie->link_is_up)
diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index c640db60edc6..de4c1758a6c3 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -18,6 +18,20 @@
#include "pcie-designware.h"
+#define PEX_PF0_CONFIG 0xC0014
+#define PEX_PF0_CFG_READY BIT(0)
+
+/* PEX PFa PCIE PME and message interrupt registers*/
+#define PEX_PF0_PME_MES_DR 0xC0020
+#define PEX_PF0_PME_MES_DR_LUD BIT(7)
+#define PEX_PF0_PME_MES_DR_LDD BIT(9)
+#define PEX_PF0_PME_MES_DR_HRD BIT(10)
+
+#define PEX_PF0_PME_MES_IER 0xC0028
+#define PEX_PF0_PME_MES_IER_LUDIE BIT(7)
+#define PEX_PF0_PME_MES_IER_LDDIE BIT(9)
+#define PEX_PF0_PME_MES_IER_HRDIE BIT(10)
+
#define to_ls_pcie_ep(x) dev_get_drvdata((x)->dev)
struct ls_pcie_ep_drvdata {
@@ -30,8 +44,84 @@ struct ls_pcie_ep {
struct dw_pcie *pci;
struct pci_epc_features *ls_epc;
const struct ls_pcie_ep_drvdata *drvdata;
+ int irq;
+ bool big_endian;
};
+static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
+{
+ struct dw_pcie *pci = pcie->pci;
+
+ if (pcie->big_endian)
+ return ioread32be(pci->dbi_base + offset);
+ else
+ return ioread32(pci->dbi_base + offset);
+}
+
+static void ls_lut_writel(struct ls_pcie_ep *pcie, u32 offset, u32 value)
+{
+ struct dw_pcie *pci = pcie->pci;
+
+ if (pcie->big_endian)
+ iowrite32be(value, pci->dbi_base + offset);
+ else
+ iowrite32(value, pci->dbi_base + offset);
+}
+
+static irqreturn_t ls_pcie_ep_event_handler(int irq, void *dev_id)
+{
+ struct ls_pcie_ep *pcie = dev_id;
+ struct dw_pcie *pci = pcie->pci;
+ u32 val, cfg;
+
+ val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
+ ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
+
+ if (!val)
+ return IRQ_NONE;
+
+ if (val & PEX_PF0_PME_MES_DR_LUD) {
+ cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
+ cfg |= PEX_PF0_CFG_READY;
+ ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
+ dw_pcie_ep_linkup(&pci->ep);
+
+ dev_dbg(pci->dev, "Link up\n");
+ } else if (val & PEX_PF0_PME_MES_DR_LDD) {
+ dev_dbg(pci->dev, "Link down\n");
+ } else if (val & PEX_PF0_PME_MES_DR_HRD) {
+ dev_dbg(pci->dev, "Hot reset\n");
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep *pcie,
+ struct platform_device *pdev)
+{
+ u32 val;
+ int ret;
+
+ pcie->irq = platform_get_irq_byname(pdev, "pme");
+ if (pcie->irq < 0)
+ return pcie->irq;
+
+ ret = devm_request_irq(&pdev->dev, pcie->irq, ls_pcie_ep_event_handler,
+ IRQF_SHARED, pdev->name, pcie);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't register PCIe IRQ\n");
+ return ret;
+ }
+
+ /* Enable interrupts */
+ val = ls_lut_readl(pcie, PEX_PF0_PME_MES_IER);
+ val |= PEX_PF0_PME_MES_IER_LDDIE | PEX_PF0_PME_MES_IER_HRDIE |
+ PEX_PF0_PME_MES_IER_LUDIE;
+ ls_lut_writel(pcie, PEX_PF0_PME_MES_IER, val);
+
+ return 0;
+}
+
static const struct pci_epc_features*
ls_pcie_ep_get_features(struct dw_pcie_ep *ep)
{
@@ -125,6 +215,7 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)
struct ls_pcie_ep *pcie;
struct pci_epc_features *ls_epc;
struct resource *dbi_base;
+ int ret;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
@@ -144,6 +235,7 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)
pci->ops = pcie->drvdata->dw_pcie_ops;
ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4);
+ ls_epc->linkup_notifier = true;
pcie->pci = pci;
pcie->ls_epc = ls_epc;
@@ -155,9 +247,15 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)
pci->ep.ops = &ls_pcie_ep_ops;
+ pcie->big_endian = of_property_read_bool(dev->of_node, "big-endian");
+
platform_set_drvdata(pdev, pcie);
- return dw_pcie_ep_init(&pci->ep);
+ ret = dw_pcie_ep_init(&pci->ep);
+ if (ret)
+ return ret;
+
+ return ls_pcie_ep_interrupt_init(pcie, pdev);
}
static struct platform_driver ls_pcie_ep_driver = {
diff --git a/drivers/pci/controller/dwc/pcie-bt1.c b/drivers/pci/controller/dwc/pcie-bt1.c
index 95a723a6fd46..17e696797ff5 100644
--- a/drivers/pci/controller/dwc/pcie-bt1.c
+++ b/drivers/pci/controller/dwc/pcie-bt1.c
@@ -617,13 +617,11 @@ static int bt1_pcie_probe(struct platform_device *pdev)
return bt1_pcie_add_port(btpci);
}
-static int bt1_pcie_remove(struct platform_device *pdev)
+static void bt1_pcie_remove(struct platform_device *pdev)
{
struct bt1_pcie *btpci = platform_get_drvdata(pdev);
bt1_pcie_del_port(btpci);
-
- return 0;
}
static const struct of_device_id bt1_pcie_of_match[] = {
@@ -634,7 +632,7 @@ MODULE_DEVICE_TABLE(of, bt1_pcie_of_match);
static struct platform_driver bt1_pcie_driver = {
.probe = bt1_pcie_probe,
- .remove = bt1_pcie_remove,
+ .remove_new = bt1_pcie_remove,
.driver = {
.name = "bt1-pcie",
.of_match_table = bt1_pcie_of_match,
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 9952057c8819..cf61733bf78d 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -485,14 +485,19 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
if (ret)
goto err_remove_edma;
- if (!dw_pcie_link_up(pci)) {
+ if (dw_pcie_link_up(pci)) {
+ dw_pcie_print_link_status(pci);
+ } else {
ret = dw_pcie_start_link(pci);
if (ret)
goto err_remove_edma;
- }
- /* Ignore errors, the link may come up later */
- dw_pcie_wait_for_link(pci);
+ if (pci->ops && pci->ops->start_link) {
+ ret = dw_pcie_wait_for_link(pci);
+ if (ret)
+ goto err_stop_link;
+ }
+ }
bridge->sysdata = pp;
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 8e33e6e59e68..df092229e97d 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -644,9 +644,20 @@ void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index)
dw_pcie_writel_atu(pci, dir, index, PCIE_ATU_REGION_CTRL2, 0);
}
-int dw_pcie_wait_for_link(struct dw_pcie *pci)
+void dw_pcie_print_link_status(struct dw_pcie *pci)
{
u32 offset, val;
+
+ offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+ val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
+
+ dev_info(pci->dev, "PCIe Gen.%u x%u link up\n",
+ FIELD_GET(PCI_EXP_LNKSTA_CLS, val),
+ FIELD_GET(PCI_EXP_LNKSTA_NLW, val));
+}
+
+int dw_pcie_wait_for_link(struct dw_pcie *pci)
+{
int retries;
/* Check if the link is up or not */
@@ -662,12 +673,7 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci)
return -ETIMEDOUT;
}
- offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
- val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
-
- dev_info(pci->dev, "PCIe Gen.%u x%u link up\n",
- FIELD_GET(PCI_EXP_LNKSTA_CLS, val),
- FIELD_GET(PCI_EXP_LNKSTA_NLW, val));
+ dw_pcie_print_link_status(pci);
return 0;
}
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 79713ce075cc..615660640801 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -429,6 +429,7 @@ void dw_pcie_setup(struct dw_pcie *pci);
void dw_pcie_iatu_detect(struct dw_pcie *pci);
int dw_pcie_edma_detect(struct dw_pcie *pci);
void dw_pcie_edma_remove(struct dw_pcie *pci);
+void dw_pcie_print_link_status(struct dw_pcie *pci);
static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
{
diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c
index 927ae05dc920..fd484cc7c481 100644
--- a/drivers/pci/controller/dwc/pcie-histb.c
+++ b/drivers/pci/controller/dwc/pcie-histb.c
@@ -421,7 +421,7 @@ static int histb_pcie_probe(struct platform_device *pdev)
return 0;
}
-static int histb_pcie_remove(struct platform_device *pdev)
+static void histb_pcie_remove(struct platform_device *pdev)
{
struct histb_pcie *hipcie = platform_get_drvdata(pdev);
@@ -429,8 +429,6 @@ static int histb_pcie_remove(struct platform_device *pdev)
if (hipcie->phy)
phy_exit(hipcie->phy);
-
- return 0;
}
static const struct of_device_id histb_pcie_of_match[] = {
@@ -441,7 +439,7 @@ MODULE_DEVICE_TABLE(of, histb_pcie_of_match);
static struct platform_driver histb_pcie_platform_driver = {
.probe = histb_pcie_probe,
- .remove = histb_pcie_remove,
+ .remove_new = histb_pcie_remove,
.driver = {
.name = "histb-pcie",
.of_match_table = histb_pcie_of_match,
diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c
index 333c33d98a70..9c7caed9e706 100644
--- a/drivers/pci/controller/dwc/pcie-intel-gw.c
+++ b/drivers/pci/controller/dwc/pcie-intel-gw.c
@@ -340,15 +340,13 @@ static void __intel_pcie_remove(struct intel_pcie *pcie)
phy_exit(pcie->phy);
}
-static int intel_pcie_remove(struct platform_device *pdev)
+static void intel_pcie_remove(struct platform_device *pdev)
{
struct intel_pcie *pcie = platform_get_drvdata(pdev);
struct dw_pcie_rp *pp = &pcie->pci.pp;
dw_pcie_host_deinit(pp);
__intel_pcie_remove(pcie);
-
- return 0;
}
static int intel_pcie_suspend_noirq(struct device *dev)
@@ -443,7 +441,7 @@ static const struct of_device_id of_intel_pcie_match[] = {
static struct platform_driver intel_pcie_driver = {
.probe = intel_pcie_probe,
- .remove = intel_pcie_remove,
+ .remove_new = intel_pcie_remove,
.driver = {
.name = "intel-gw-pcie",
.of_match_table = of_intel_pcie_match,
diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c
index 19b32839ea26..0fe7f06f2102 100644
--- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
+++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c
@@ -569,9 +569,11 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data)
if (FIELD_GET(PARF_INT_ALL_LINK_DOWN, status)) {
dev_dbg(dev, "Received Linkdown event\n");
pcie_ep->link_status = QCOM_PCIE_EP_LINK_DOWN;
+ pci_epc_linkdown(pci->ep.epc);
} else if (FIELD_GET(PARF_INT_ALL_BME, status)) {
dev_dbg(dev, "Received BME event. Link is enabled!\n");
pcie_ep->link_status = QCOM_PCIE_EP_LINK_ENABLED;
+ pci_epc_bme_notify(pci->ep.epc);
} else if (FIELD_GET(PARF_INT_ALL_PM_TURNOFF, status)) {
dev_dbg(dev, "Received PM Turn-off event! Entering L23\n");
val = readl_relaxed(pcie_ep->parf + PARF_PM_CTRL);
@@ -784,7 +786,7 @@ err_disable_resources:
return ret;
}
-static int qcom_pcie_ep_remove(struct platform_device *pdev)
+static void qcom_pcie_ep_remove(struct platform_device *pdev)
{
struct qcom_pcie_ep *pcie_ep = platform_get_drvdata(pdev);
@@ -794,11 +796,9 @@ static int qcom_pcie_ep_remove(struct platform_device *pdev)
debugfs_remove_recursive(pcie_ep->debugfs);
if (pcie_ep->link_status == QCOM_PCIE_EP_LINK_DISABLED)
- return 0;
+ return;
qcom_pcie_disable_resources(pcie_ep);
-
- return 0;
}
static const struct of_device_id qcom_pcie_ep_match[] = {
@@ -810,7 +810,7 @@ MODULE_DEVICE_TABLE(of, qcom_pcie_ep_match);
static struct platform_driver qcom_pcie_ep_driver = {
.probe = qcom_pcie_ep_probe,
- .remove = qcom_pcie_ep_remove,
+ .remove_new = qcom_pcie_ep_remove,
.driver = {
.name = "qcom-pcie-ep",
.of_match_table = qcom_pcie_ep_match,
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index 4ab30892f6ef..7a87a47eb7ed 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -61,7 +61,6 @@
/* DBI registers */
#define AXI_MSTR_RESP_COMP_CTRL0 0x818
#define AXI_MSTR_RESP_COMP_CTRL1 0x81c
-#define MISC_CONTROL_1_REG 0x8bc
/* MHI registers */
#define PARF_DEBUG_CNT_PM_LINKST_IN_L2 0xc04
@@ -132,9 +131,6 @@
/* AXI_MSTR_RESP_COMP_CTRL1 register fields */
#define CFG_BRIDGE_SB_INIT BIT(0)
-/* MISC_CONTROL_1_REG register fields */
-#define DBI_RO_WR_EN 1
-
/* PCI_EXP_SLTCAP register fields */
#define PCIE_CAP_SLOT_POWER_LIMIT_VAL FIELD_PREP(PCI_EXP_SLTCAP_SPLV, 250)
#define PCIE_CAP_SLOT_POWER_LIMIT_SCALE FIELD_PREP(PCI_EXP_SLTCAP_SPLS, 1)
@@ -144,7 +140,6 @@
PCI_EXP_SLTCAP_AIP | \
PCI_EXP_SLTCAP_PIP | \
PCI_EXP_SLTCAP_HPS | \
- PCI_EXP_SLTCAP_HPC | \
PCI_EXP_SLTCAP_EIP | \
PCIE_CAP_SLOT_POWER_LIMIT_VAL | \
PCIE_CAP_SLOT_POWER_LIMIT_SCALE)
@@ -274,6 +269,20 @@ static int qcom_pcie_start_link(struct dw_pcie *pci)
return 0;
}
+static void qcom_pcie_clear_hpc(struct dw_pcie *pci)
+{
+ u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+ u32 val;
+
+ dw_pcie_dbi_ro_wr_en(pci);
+
+ val = readl(pci->dbi_base + offset + PCI_EXP_SLTCAP);
+ val &= ~PCI_EXP_SLTCAP_HPC;
+ writel(val, pci->dbi_base + offset + PCI_EXP_SLTCAP);
+
+ dw_pcie_dbi_ro_wr_dis(pci);
+}
+
static void qcom_pcie_2_1_0_ltssm_enable(struct qcom_pcie *pcie)
{
u32 val;
@@ -429,6 +438,8 @@ static int qcom_pcie_post_init_2_1_0(struct qcom_pcie *pcie)
writel(CFG_BRIDGE_SB_INIT,
pci->dbi_base + AXI_MSTR_RESP_COMP_CTRL1);
+ qcom_pcie_clear_hpc(pcie->pci);
+
return 0;
}
@@ -512,6 +523,8 @@ static int qcom_pcie_post_init_1_0_0(struct qcom_pcie *pcie)
writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT);
}
+ qcom_pcie_clear_hpc(pcie->pci);
+
return 0;
}
@@ -607,6 +620,8 @@ static int qcom_pcie_post_init_2_3_2(struct qcom_pcie *pcie)
val |= EN;
writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
+ qcom_pcie_clear_hpc(pcie->pci);
+
return 0;
}
@@ -692,34 +707,6 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie)
return 0;
}
-static int qcom_pcie_post_init_2_4_0(struct qcom_pcie *pcie)
-{
- u32 val;
-
- /* enable PCIe clocks and resets */
- val = readl(pcie->parf + PARF_PHY_CTRL);
- val &= ~PHY_TEST_PWR_DOWN;
- writel(val, pcie->parf + PARF_PHY_CTRL);
-
- /* change DBI base address */
- writel(0, pcie->parf + PARF_DBI_BASE_ADDR);
-
- /* MAC PHY_POWERDOWN MUX DISABLE */
- val = readl(pcie->parf + PARF_SYS_CTRL);
- val &= ~MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN;
- writel(val, pcie->parf + PARF_SYS_CTRL);
-
- val = readl(pcie->parf + PARF_MHI_CLOCK_RESET_CTRL);
- val |= BYPASS;
- writel(val, pcie->parf + PARF_MHI_CLOCK_RESET_CTRL);
-
- val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
- val |= EN;
- writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
-
- return 0;
-}
-
static int qcom_pcie_get_resources_2_3_3(struct qcom_pcie *pcie)
{
struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3;
@@ -826,7 +813,9 @@ static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie)
writel(0, pcie->parf + PARF_Q2A_FLUSH);
writel(PCI_COMMAND_MASTER, pci->dbi_base + PCI_COMMAND);
- writel(DBI_RO_WR_EN, pci->dbi_base + MISC_CONTROL_1_REG);
+
+ dw_pcie_dbi_ro_wr_en(pci);
+
writel(PCIE_CAP_SLOT_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP);
val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP);
@@ -836,6 +825,8 @@ static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie)
writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + offset +
PCI_EXP_DEVCTL2);
+ dw_pcie_dbi_ro_wr_dis(pci);
+
return 0;
}
@@ -966,6 +957,13 @@ err_disable_regulators:
return ret;
}
+static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)
+{
+ qcom_pcie_clear_hpc(pcie->pci);
+
+ return 0;
+}
+
static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie)
{
struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
@@ -1136,6 +1134,7 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie)
writel(0, pcie->parf + PARF_Q2A_FLUSH);
dw_pcie_dbi_ro_wr_en(pci);
+
writel(PCIE_CAP_SLOT_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP);
val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP);
@@ -1145,6 +1144,8 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie)
writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + offset +
PCI_EXP_DEVCTL2);
+ dw_pcie_dbi_ro_wr_dis(pci);
+
for (i = 0; i < 256; i++)
writel(0, pcie->parf + PARF_BDF_TO_SID_TABLE_N + (4 * i));
@@ -1251,7 +1252,7 @@ static const struct qcom_pcie_ops ops_2_3_2 = {
static const struct qcom_pcie_ops ops_2_4_0 = {
.get_resources = qcom_pcie_get_resources_2_4_0,
.init = qcom_pcie_init_2_4_0,
- .post_init = qcom_pcie_post_init_2_4_0,
+ .post_init = qcom_pcie_post_init_2_3_2,
.deinit = qcom_pcie_deinit_2_4_0,
.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
};
@@ -1269,6 +1270,7 @@ static const struct qcom_pcie_ops ops_2_3_3 = {
static const struct qcom_pcie_ops ops_2_7_0 = {
.get_resources = qcom_pcie_get_resources_2_7_0,
.init = qcom_pcie_init_2_7_0,
+ .post_init = qcom_pcie_post_init_2_7_0,
.deinit = qcom_pcie_deinit_2_7_0,
.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
};
@@ -1277,6 +1279,7 @@ static const struct qcom_pcie_ops ops_2_7_0 = {
static const struct qcom_pcie_ops ops_1_9_0 = {
.get_resources = qcom_pcie_get_resources_2_7_0,
.init = qcom_pcie_init_2_7_0,
+ .post_init = qcom_pcie_post_init_2_7_0,
.deinit = qcom_pcie_deinit_2_7_0,
.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
.config_sid = qcom_pcie_config_sid_1_9_0,
diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 09825b4a075e..e1db909f53ec 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -14,6 +14,7 @@
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
+#include <linux/interconnect.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
@@ -223,6 +224,7 @@
#define EP_STATE_ENABLED 1
static const unsigned int pcie_gen_freq[] = {
+ GEN1_CORE_CLK_FREQ, /* PCI_EXP_LNKSTA_CLS == 0; undefined */
GEN1_CORE_CLK_FREQ,
GEN2_CORE_CLK_FREQ,
GEN3_CORE_CLK_FREQ,
@@ -287,6 +289,7 @@ struct tegra_pcie_dw {
unsigned int pex_rst_irq;
int ep_state;
long link_status;
+ struct icc_path *icc_path;
};
static inline struct tegra_pcie_dw *to_tegra_pcie(struct dw_pcie *pci)
@@ -309,6 +312,27 @@ struct tegra_pcie_soc {
enum dw_pcie_device_mode mode;
};
+static void tegra_pcie_icc_set(struct tegra_pcie_dw *pcie)
+{
+ struct dw_pcie *pci = &pcie->pci;
+ u32 val, speed, width;
+
+ val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA);
+
+ speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, val);
+ width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val);
+
+ val = width * (PCIE_SPEED2MBS_ENC(pcie_link_speed[speed]) / BITS_PER_BYTE);
+
+ if (icc_set_bw(pcie->icc_path, MBps_to_icc(val), 0))
+ dev_err(pcie->dev, "can't set bw[%u]\n", val);
+
+ if (speed >= ARRAY_SIZE(pcie_gen_freq))
+ speed = 0;
+
+ clk_set_rate(pcie->core_clk, pcie_gen_freq[speed]);
+}
+
static void apply_bad_link_workaround(struct dw_pcie_rp *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -452,14 +476,12 @@ static irqreturn_t tegra_pcie_ep_irq_thread(int irq, void *arg)
struct tegra_pcie_dw *pcie = arg;
struct dw_pcie_ep *ep = &pcie->pci.ep;
struct dw_pcie *pci = &pcie->pci;
- u32 val, speed;
+ u32 val;
if (test_and_clear_bit(0, &pcie->link_status))
dw_pcie_ep_linkup(ep);
- speed = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA) &
- PCI_EXP_LNKSTA_CLS;
- clk_set_rate(pcie->core_clk, pcie_gen_freq[speed - 1]);
+ tegra_pcie_icc_set(pcie);
if (pcie->of_data->has_ltr_req_fix)
return IRQ_HANDLED;
@@ -945,9 +967,9 @@ static int tegra_pcie_dw_host_init(struct dw_pcie_rp *pp)
static int tegra_pcie_dw_start_link(struct dw_pcie *pci)
{
- u32 val, offset, speed, tmp;
struct tegra_pcie_dw *pcie = to_tegra_pcie(pci);
struct dw_pcie_rp *pp = &pci->pp;
+ u32 val, offset, tmp;
bool retry = true;
if (pcie->of_data->mode == DW_PCIE_EP_TYPE) {
@@ -1018,9 +1040,7 @@ retry_link:
goto retry_link;
}
- speed = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA) &
- PCI_EXP_LNKSTA_CLS;
- clk_set_rate(pcie->core_clk, pcie_gen_freq[speed - 1]);
+ tegra_pcie_icc_set(pcie);
tegra_pcie_enable_interrupts(pp);
@@ -2224,6 +2244,14 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pcie);
+ pcie->icc_path = devm_of_icc_get(&pdev->dev, "write");
+ ret = PTR_ERR_OR_ZERO(pcie->icc_path);
+ if (ret) {
+ tegra_bpmp_put(pcie->bpmp);
+ dev_err_probe(&pdev->dev, ret, "failed to get write interconnect\n");
+ return ret;
+ }
+
switch (pcie->of_data->mode) {
case DW_PCIE_RC_TYPE:
ret = devm_request_irq(dev, pp->irq, tegra_pcie_rp_irq_handler,
@@ -2268,13 +2296,13 @@ fail:
return ret;
}
-static int tegra_pcie_dw_remove(struct platform_device *pdev)
+static void tegra_pcie_dw_remove(struct platform_device *pdev)
{
struct tegra_pcie_dw *pcie = platform_get_drvdata(pdev);
if (pcie->of_data->mode == DW_PCIE_RC_TYPE) {
if (!pcie->link_state)
- return 0;
+ return;
debugfs_remove_recursive(pcie->debugfs);
tegra_pcie_deinit_controller(pcie);
@@ -2288,8 +2316,6 @@ static int tegra_pcie_dw_remove(struct platform_device *pdev)
tegra_bpmp_put(pcie->bpmp);
if (pcie->pex_refclk_sel_gpiod)
gpiod_set_value(pcie->pex_refclk_sel_gpiod, 0);
-
- return 0;
}
static int tegra_pcie_dw_suspend_late(struct device *dev)
@@ -2483,7 +2509,7 @@ static const struct dev_pm_ops tegra_pcie_dw_pm_ops = {
static struct platform_driver tegra_pcie_dw_driver = {
.probe = tegra_pcie_dw_probe,
- .remove = tegra_pcie_dw_remove,
+ .remove_new = tegra_pcie_dw_remove,
.shutdown = tegra_pcie_dw_shutdown,
.driver = {
.name = "tegra194-pcie",
diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
index 513d8edf3a5c..71ecd7ddcc8a 100644
--- a/drivers/pci/controller/pci-aardvark.c
+++ b/drivers/pci/controller/pci-aardvark.c
@@ -1927,7 +1927,7 @@ static int advk_pcie_probe(struct platform_device *pdev)
return 0;
}
-static int advk_pcie_remove(struct platform_device *pdev)
+static void advk_pcie_remove(struct platform_device *pdev)
{
struct advk_pcie *pcie = platform_get_drvdata(pdev);
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
@@ -1989,8 +1989,6 @@ static int advk_pcie_remove(struct platform_device *pdev)
/* Disable phy */
advk_pcie_disable_phy(pcie);
-
- return 0;
}
static const struct of_device_id advk_pcie_of_match_table[] = {
@@ -2005,7 +2003,7 @@ static struct platform_driver advk_pcie_driver = {
.of_match_table = advk_pcie_of_match_table,
},
.probe = advk_pcie_probe,
- .remove = advk_pcie_remove,
+ .remove_new = advk_pcie_remove,
};
module_platform_driver(advk_pcie_driver);
diff --git a/drivers/pci/controller/pci-ftpci100.c b/drivers/pci/controller/pci-ftpci100.c
index ecd3009df586..6e7981d2ed5e 100644
--- a/drivers/pci/controller/pci-ftpci100.c
+++ b/drivers/pci/controller/pci-ftpci100.c
@@ -429,22 +429,12 @@ static int faraday_pci_probe(struct platform_device *pdev)
p->dev = dev;
/* Retrieve and enable optional clocks */
- clk = devm_clk_get(dev, "PCLK");
+ clk = devm_clk_get_enabled(dev, "PCLK");
if (IS_ERR(clk))
return PTR_ERR(clk);
- ret = clk_prepare_enable(clk);
- if (ret) {
- dev_err(dev, "could not prepare PCLK\n");
- return ret;
- }
- p->bus_clk = devm_clk_get(dev, "PCICLK");
+ p->bus_clk = devm_clk_get_enabled(dev, "PCICLK");
if (IS_ERR(p->bus_clk))
return PTR_ERR(p->bus_clk);
- ret = clk_prepare_enable(p->bus_clk);
- if (ret) {
- dev_err(dev, "could not prepare PCICLK\n");
- return ret;
- }
p->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(p->base))
diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 1dc209f6f53a..c931b1b07b1d 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -1649,7 +1649,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
return pci_host_probe(bridge);
}
-static int mvebu_pcie_remove(struct platform_device *pdev)
+static void mvebu_pcie_remove(struct platform_device *pdev)
{
struct mvebu_pcie *pcie = platform_get_drvdata(pdev);
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
@@ -1707,8 +1707,6 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
/* Power down card and disable clocks. Must be the last step. */
mvebu_pcie_powerdown(port);
}
-
- return 0;
}
static const struct of_device_id mvebu_pcie_of_match_table[] = {
@@ -1730,7 +1728,7 @@ static struct platform_driver mvebu_pcie_driver = {
.pm = &mvebu_pcie_pm_ops,
},
.probe = mvebu_pcie_probe,
- .remove = mvebu_pcie_remove,
+ .remove_new = mvebu_pcie_remove,
};
module_platform_driver(mvebu_pcie_driver);
diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c
index 79630885b9c8..038d974a318e 100644
--- a/drivers/pci/controller/pci-tegra.c
+++ b/drivers/pci/controller/pci-tegra.c
@@ -2680,7 +2680,7 @@ put_resources:
return err;
}
-static int tegra_pcie_remove(struct platform_device *pdev)
+static void tegra_pcie_remove(struct platform_device *pdev)
{
struct tegra_pcie *pcie = platform_get_drvdata(pdev);
struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
@@ -2701,8 +2701,6 @@ static int tegra_pcie_remove(struct platform_device *pdev)
list_for_each_entry_safe(port, tmp, &pcie->ports, list)
tegra_pcie_port_free(port);
-
- return 0;
}
static int tegra_pcie_pm_suspend(struct device *dev)
@@ -2808,6 +2806,6 @@ static struct platform_driver tegra_pcie_driver = {
.pm = &tegra_pcie_pm_ops,
},
.probe = tegra_pcie_probe,
- .remove = tegra_pcie_remove,
+ .remove_new = tegra_pcie_remove,
};
module_platform_driver(tegra_pcie_driver);
diff --git a/drivers/pci/controller/pci-xgene-msi.c b/drivers/pci/controller/pci-xgene-msi.c
index d7987b281f79..0234e528b9a5 100644
--- a/drivers/pci/controller/pci-xgene-msi.c
+++ b/drivers/pci/controller/pci-xgene-msi.c
@@ -348,7 +348,7 @@ static void xgene_msi_isr(struct irq_desc *desc)
static enum cpuhp_state pci_xgene_online;
-static int xgene_msi_remove(struct platform_device *pdev)
+static void xgene_msi_remove(struct platform_device *pdev)
{
struct xgene_msi *msi = platform_get_drvdata(pdev);
@@ -362,8 +362,6 @@ static int xgene_msi_remove(struct platform_device *pdev)
msi->bitmap = NULL;
xgene_free_domains(msi);
-
- return 0;
}
static int xgene_msi_hwirq_alloc(unsigned int cpu)
@@ -521,7 +519,7 @@ static struct platform_driver xgene_msi_driver = {
.of_match_table = xgene_msi_match_table,
},
.probe = xgene_msi_probe,
- .remove = xgene_msi_remove,
+ .remove_new = xgene_msi_remove,
};
static int __init xgene_pcie_msi_init(void)
diff --git a/drivers/pci/controller/pcie-altera-msi.c b/drivers/pci/controller/pcie-altera-msi.c
index 65e8a20cc442..6ad5427490b5 100644
--- a/drivers/pci/controller/pcie-altera-msi.c
+++ b/drivers/pci/controller/pcie-altera-msi.c
@@ -197,7 +197,7 @@ static void altera_free_domains(struct altera_msi *msi)
irq_domain_remove(msi->inner_domain);
}
-static int altera_msi_remove(struct platform_device *pdev)
+static void altera_msi_remove(struct platform_device *pdev)
{
struct altera_msi *msi = platform_get_drvdata(pdev);
@@ -207,7 +207,6 @@ static int altera_msi_remove(struct platform_device *pdev)
altera_free_domains(msi);
platform_set_drvdata(pdev, NULL);
- return 0;
}
static int altera_msi_probe(struct platform_device *pdev)
@@ -275,7 +274,7 @@ static struct platform_driver altera_msi_driver = {
.of_match_table = altera_msi_of_match,
},
.probe = altera_msi_probe,
- .remove = altera_msi_remove,
+ .remove_new = altera_msi_remove,
};
static int __init altera_msi_init(void)
diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c
index 18b2361d6462..c95a29fff8bf 100644
--- a/drivers/pci/controller/pcie-altera.c
+++ b/drivers/pci/controller/pcie-altera.c
@@ -806,7 +806,7 @@ static int altera_pcie_probe(struct platform_device *pdev)
return pci_host_probe(bridge);
}
-static int altera_pcie_remove(struct platform_device *pdev)
+static void altera_pcie_remove(struct platform_device *pdev)
{
struct altera_pcie *pcie = platform_get_drvdata(pdev);
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
@@ -814,13 +814,11 @@ static int altera_pcie_remove(struct platform_device *pdev)
pci_stop_root_bus(bridge->bus);
pci_remove_root_bus(bridge->bus);
altera_pcie_irq_teardown(pcie);
-
- return 0;
}
static struct platform_driver altera_pcie_driver = {
.probe = altera_pcie_probe,
- .remove = altera_pcie_remove,
+ .remove_new = altera_pcie_remove,
.driver = {
.name = "altera-pcie",
.of_match_table = altera_pcie_of_match,
diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
index edf283e2b5dd..f593a422bd63 100644
--- a/drivers/pci/controller/pcie-brcmstb.c
+++ b/drivers/pci/controller/pcie-brcmstb.c
@@ -1396,7 +1396,7 @@ static void __brcm_pcie_remove(struct brcm_pcie *pcie)
clk_disable_unprepare(pcie->clk);
}
-static int brcm_pcie_remove(struct platform_device *pdev)
+static void brcm_pcie_remove(struct platform_device *pdev)
{
struct brcm_pcie *pcie = platform_get_drvdata(pdev);
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
@@ -1404,8 +1404,6 @@ static int brcm_pcie_remove(struct platform_device *pdev)
pci_stop_root_bus(bridge->bus);
pci_remove_root_bus(bridge->bus);
__brcm_pcie_remove(pcie);
-
- return 0;
}
static const int pcie_offsets[] = {
@@ -1612,7 +1610,7 @@ static const struct dev_pm_ops brcm_pcie_pm_ops = {
static struct platform_driver brcm_pcie_driver = {
.probe = brcm_pcie_probe,
- .remove = brcm_pcie_remove,
+ .remove_new = brcm_pcie_remove,
.driver = {
.name = "brcm-pcie",
.of_match_table = brcm_pcie_match,
diff --git a/drivers/pci/controller/pcie-hisi-error.c b/drivers/pci/controller/pcie-hisi-error.c
index 7d88eb696b06..ad9d5ffcd9e3 100644
--- a/drivers/pci/controller/pcie-hisi-error.c
+++ b/drivers/pci/controller/pcie-hisi-error.c
@@ -299,13 +299,11 @@ static int hisi_pcie_error_handler_probe(struct platform_device *pdev)
return 0;
}
-static int hisi_pcie_error_handler_remove(struct platform_device *pdev)
+static void hisi_pcie_error_handler_remove(struct platform_device *pdev)
{
struct hisi_pcie_error_private *priv = platform_get_drvdata(pdev);
ghes_unregister_vendor_record_notifier(&priv->nb);
-
- return 0;
}
static const struct acpi_device_id hisi_pcie_acpi_match[] = {
@@ -319,7 +317,7 @@ static struct platform_driver hisi_pcie_error_handler_driver = {
.acpi_match_table = hisi_pcie_acpi_match,
},
.probe = hisi_pcie_error_handler_probe,
- .remove = hisi_pcie_error_handler_remove,
+ .remove_new = hisi_pcie_error_handler_remove,
};
module_platform_driver(hisi_pcie_error_handler_driver);
diff --git a/drivers/pci/controller/pcie-iproc-platform.c b/drivers/pci/controller/pcie-iproc-platform.c
index 4142a73e611d..acdc583d2980 100644
--- a/drivers/pci/controller/pcie-iproc-platform.c
+++ b/drivers/pci/controller/pcie-iproc-platform.c
@@ -114,11 +114,11 @@ static int iproc_pltfm_pcie_probe(struct platform_device *pdev)
return 0;
}
-static int iproc_pltfm_pcie_remove(struct platform_device *pdev)
+static void iproc_pltfm_pcie_remove(struct platform_device *pdev)
{
struct iproc_pcie *pcie = platform_get_drvdata(pdev);
- return iproc_pcie_remove(pcie);
+ iproc_pcie_remove(pcie);
}
static void iproc_pltfm_pcie_shutdown(struct platform_device *pdev)
@@ -134,7 +134,7 @@ static struct platform_driver iproc_pltfm_pcie_driver = {
.of_match_table = of_match_ptr(iproc_pcie_of_match_table),
},
.probe = iproc_pltfm_pcie_probe,
- .remove = iproc_pltfm_pcie_remove,
+ .remove_new = iproc_pltfm_pcie_remove,
.shutdown = iproc_pltfm_pcie_shutdown,
};
module_platform_driver(iproc_pltfm_pcie_driver);
diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
index 83029bdfd884..bd1c98b68851 100644
--- a/drivers/pci/controller/pcie-iproc.c
+++ b/drivers/pci/controller/pcie-iproc.c
@@ -1537,7 +1537,7 @@ err_exit_phy:
}
EXPORT_SYMBOL(iproc_pcie_setup);
-int iproc_pcie_remove(struct iproc_pcie *pcie)
+void iproc_pcie_remove(struct iproc_pcie *pcie)
{
struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
@@ -1548,8 +1548,6 @@ int iproc_pcie_remove(struct iproc_pcie *pcie)
phy_power_off(pcie->phy);
phy_exit(pcie->phy);
-
- return 0;
}
EXPORT_SYMBOL(iproc_pcie_remove);
diff --git a/drivers/pci/controller/pcie-iproc.h b/drivers/pci/controller/pcie-iproc.h
index dcca315897c8..969ded03b8c2 100644
--- a/drivers/pci/controller/pcie-iproc.h
+++ b/drivers/pci/controller/pcie-iproc.h
@@ -111,7 +111,7 @@ struct iproc_pcie {
};
int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res);
-int iproc_pcie_remove(struct iproc_pcie *pcie);
+void iproc_pcie_remove(struct iproc_pcie *pcie);
int iproc_pcie_shutdown(struct iproc_pcie *pcie);
#ifdef CONFIG_PCIE_IPROC_MSI
diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c
index b8612ce5f4d0..e0e27645fdf4 100644
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -943,7 +943,7 @@ static int mtk_pcie_probe(struct platform_device *pdev)
return 0;
}
-static int mtk_pcie_remove(struct platform_device *pdev)
+static void mtk_pcie_remove(struct platform_device *pdev)
{
struct mtk_gen3_pcie *pcie = platform_get_drvdata(pdev);
struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
@@ -955,8 +955,6 @@ static int mtk_pcie_remove(struct platform_device *pdev)
mtk_pcie_irq_teardown(pcie);
mtk_pcie_power_down(pcie);
-
- return 0;
}
static void mtk_pcie_irq_save(struct mtk_gen3_pcie *pcie)
@@ -1069,7 +1067,7 @@ MODULE_DEVICE_TABLE(of, mtk_pcie_of_match);
static struct platform_driver mtk_pcie_driver = {
.probe = mtk_pcie_probe,
- .remove = mtk_pcie_remove,
+ .remove_new = mtk_pcie_remove,
.driver = {
.name = "mtk-pcie-gen3",
.of_match_table = mtk_pcie_of_match,
diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
index 31de7a29192c..66a8f73296fc 100644
--- a/drivers/pci/controller/pcie-mediatek.c
+++ b/drivers/pci/controller/pcie-mediatek.c
@@ -1134,7 +1134,7 @@ static void mtk_pcie_free_resources(struct mtk_pcie *pcie)
pci_free_resource_list(windows);
}
-static int mtk_pcie_remove(struct platform_device *pdev)
+static void mtk_pcie_remove(struct platform_device *pdev)
{
struct mtk_pcie *pcie = platform_get_drvdata(pdev);
struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
@@ -1146,8 +1146,6 @@ static int mtk_pcie_remove(struct platform_device *pdev)
mtk_pcie_irq_teardown(pcie);
mtk_pcie_put_resources(pcie);
-
- return 0;
}
static int mtk_pcie_suspend_noirq(struct device *dev)
@@ -1239,7 +1237,7 @@ MODULE_DEVICE_TABLE(of, mtk_pcie_ids);
static struct platform_driver mtk_pcie_driver = {
.probe = mtk_pcie_probe,
- .remove = mtk_pcie_remove,
+ .remove_new = mtk_pcie_remove,
.driver = {
.name = "mtk-pcie",
.of_match_table = mtk_pcie_ids,
diff --git a/drivers/pci/controller/pcie-mt7621.c b/drivers/pci/controller/pcie-mt7621.c
index a445ec314375..79e225edb42a 100644
--- a/drivers/pci/controller/pcie-mt7621.c
+++ b/drivers/pci/controller/pcie-mt7621.c
@@ -524,15 +524,13 @@ remove_resets:
return err;
}
-static int mt7621_pcie_remove(struct platform_device *pdev)
+static void mt7621_pcie_remove(struct platform_device *pdev)
{
struct mt7621_pcie *pcie = platform_get_drvdata(pdev);
struct mt7621_pcie_port *port;
list_for_each_entry(port, &pcie->ports, list)
reset_control_put(port->pcie_rst);
-
- return 0;
}
static const struct of_device_id mt7621_pcie_ids[] = {
@@ -543,7 +541,7 @@ MODULE_DEVICE_TABLE(of, mt7621_pcie_ids);
static struct platform_driver mt7621_pcie_driver = {
.probe = mt7621_pcie_probe,
- .remove = mt7621_pcie_remove,
+ .remove_new = mt7621_pcie_remove,
.driver = {
.name = "mt7621-pci",
.of_match_table = mt7621_pcie_ids,
diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c
index e80e56b2a842..88975e40ee2f 100644
--- a/drivers/pci/controller/pcie-rcar-host.c
+++ b/drivers/pci/controller/pcie-rcar-host.c
@@ -41,21 +41,6 @@ struct rcar_msi {
int irq2;
};
-#ifdef CONFIG_ARM
-/*
- * Here we keep a static copy of the remapped PCIe controller address.
- * This is only used on aarch32 systems, all of which have one single
- * PCIe controller, to provide quick access to the PCIe controller in
- * the L1 link state fixup function, called from the ARM fault handler.
- */
-static void __iomem *pcie_base;
-/*
- * Static copy of PCIe device pointer, so we can check whether the
- * device is runtime suspended or not.
- */
-static struct device *pcie_dev;
-#endif
-
/* Structure representing the PCIe interface */
struct rcar_pcie_host {
struct rcar_pcie pcie;
@@ -684,7 +669,7 @@ static void rcar_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
}
static struct irq_chip rcar_msi_bottom_chip = {
- .name = "Rcar MSI",
+ .name = "R-Car MSI",
.irq_ack = rcar_msi_irq_ack,
.irq_mask = rcar_msi_irq_mask,
.irq_unmask = rcar_msi_irq_unmask,
@@ -813,7 +798,7 @@ static int rcar_pcie_enable_msi(struct rcar_pcie_host *host)
/*
* Setup MSI data target using RC base address address, which
- * is guaranteed to be in the low 32bit range on any RCar HW.
+ * is guaranteed to be in the low 32bit range on any R-Car HW.
*/
rcar_pci_write_reg(pcie, lower_32_bits(res.start) | MSIFE, PCIEMSIALR);
rcar_pci_write_reg(pcie, upper_32_bits(res.start), PCIEMSIAUR);
@@ -879,12 +864,6 @@ static int rcar_pcie_get_resources(struct rcar_pcie_host *host)
}
host->msi.irq2 = i;
-#ifdef CONFIG_ARM
- /* Cache static copy for L1 link state fixup hook on aarch32 */
- pcie_base = pcie->base;
- pcie_dev = pcie->dev;
-#endif
-
return 0;
err_irq2:
diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c
index d1a200b93b2b..0af0e965fb57 100644
--- a/drivers/pci/controller/pcie-rockchip-ep.c
+++ b/drivers/pci/controller/pcie-rockchip-ep.c
@@ -61,70 +61,38 @@ static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip,
ROCKCHIP_PCIE_AT_OB_REGION_DESC0(region));
rockchip_pcie_write(rockchip, 0,
ROCKCHIP_PCIE_AT_OB_REGION_DESC1(region));
- rockchip_pcie_write(rockchip, 0,
- ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(region));
- rockchip_pcie_write(rockchip, 0,
- ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(region));
}
static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn,
- u32 r, u32 type, u64 cpu_addr,
- u64 pci_addr, size_t size)
+ u32 r, u64 cpu_addr, u64 pci_addr,
+ size_t size)
{
- u64 sz = 1ULL << fls64(size - 1);
- int num_pass_bits = ilog2(sz);
- u32 addr0, addr1, desc0, desc1;
- bool is_nor_msg = (type == AXI_WRAPPER_NOR_MSG);
+ int num_pass_bits = fls64(size - 1);
+ u32 addr0, addr1, desc0;
- /* The minimal region size is 1MB */
if (num_pass_bits < 8)
num_pass_bits = 8;
- cpu_addr -= rockchip->mem_res->start;
- addr0 = ((is_nor_msg ? 0x10 : (num_pass_bits - 1)) &
- PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) |
- (lower_32_bits(cpu_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR);
- addr1 = upper_32_bits(is_nor_msg ? cpu_addr : pci_addr);
- desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | type;
- desc1 = 0;
-
- if (is_nor_msg) {
- rockchip_pcie_write(rockchip, 0,
- ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r));
- rockchip_pcie_write(rockchip, 0,
- ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r));
- rockchip_pcie_write(rockchip, desc0,
- ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r));
- rockchip_pcie_write(rockchip, desc1,
- ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r));
- } else {
- /* PCI bus address region */
- rockchip_pcie_write(rockchip, addr0,
- ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r));
- rockchip_pcie_write(rockchip, addr1,
- ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r));
- rockchip_pcie_write(rockchip, desc0,
- ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r));
- rockchip_pcie_write(rockchip, desc1,
- ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r));
-
- addr0 =
- ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) |
- (lower_32_bits(cpu_addr) &
- PCIE_CORE_OB_REGION_ADDR0_LO_ADDR);
- addr1 = upper_32_bits(cpu_addr);
- }
+ addr0 = ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) |
+ (lower_32_bits(pci_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR);
+ addr1 = upper_32_bits(pci_addr);
+ desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | AXI_WRAPPER_MEM_WRITE;
- /* CPU bus address region */
+ /* PCI bus address region */
rockchip_pcie_write(rockchip, addr0,
- ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r));
+ ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r));
rockchip_pcie_write(rockchip, addr1,
- ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r));
+ ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r));
+ rockchip_pcie_write(rockchip, desc0,
+ ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r));
+ rockchip_pcie_write(rockchip, 0,
+ ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r));
}
static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn,
struct pci_epf_header *hdr)
{
+ u32 reg;
struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
struct rockchip_pcie *rockchip = &ep->rockchip;
@@ -137,8 +105,9 @@ static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn,
PCIE_CORE_CONFIG_VENDOR);
}
- rockchip_pcie_write(rockchip, hdr->deviceid << 16,
- ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + PCI_VENDOR_ID);
+ reg = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_DID_VID);
+ reg = (reg & 0xFFFF) | (hdr->deviceid << 16);
+ rockchip_pcie_write(rockchip, reg, PCIE_EP_CONFIG_DID_VID);
rockchip_pcie_write(rockchip,
hdr->revid |
@@ -256,26 +225,20 @@ static void rockchip_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn, u8 vfn,
ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar));
}
+static inline u32 rockchip_ob_region(phys_addr_t addr)
+{
+ return (addr >> ilog2(SZ_1M)) & 0x1f;
+}
+
static int rockchip_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, u8 vfn,
phys_addr_t addr, u64 pci_addr,
size_t size)
{
struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
struct rockchip_pcie *pcie = &ep->rockchip;
- u32 r;
-
- r = find_first_zero_bit(&ep->ob_region_map, BITS_PER_LONG);
- /*
- * Region 0 is reserved for configuration space and shouldn't
- * be used elsewhere per TRM, so leave it out.
- */
- if (r >= ep->max_regions - 1) {
- dev_err(&epc->dev, "no free outbound region\n");
- return -EINVAL;
- }
+ u32 r = rockchip_ob_region(addr);
- rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, AXI_WRAPPER_MEM_WRITE, addr,
- pci_addr, size);
+ rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, addr, pci_addr, size);
set_bit(r, &ep->ob_region_map);
ep->ob_addr[r] = addr;
@@ -290,15 +253,11 @@ static void rockchip_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn,
struct rockchip_pcie *rockchip = &ep->rockchip;
u32 r;
- for (r = 0; r < ep->max_regions - 1; r++)
+ for (r = 0; r < ep->max_regions; r++)
if (ep->ob_addr[r] == addr)
break;
- /*
- * Region 0 is reserved for configuration space and shouldn't
- * be used elsewhere per TRM, so leave it out.
- */
- if (r == ep->max_regions - 1)
+ if (r == ep->max_regions)
return;
rockchip_pcie_clear_ep_ob_atu(rockchip, r);
@@ -312,15 +271,15 @@ static int rockchip_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn,
{
struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
struct rockchip_pcie *rockchip = &ep->rockchip;
- u16 flags;
+ u32 flags;
flags = rockchip_pcie_read(rockchip,
ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
ROCKCHIP_PCIE_EP_MSI_CTRL_REG);
flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK;
flags |=
- ((multi_msg_cap << 1) << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) |
- PCI_MSI_FLAGS_64BIT;
+ (multi_msg_cap << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) |
+ (PCI_MSI_FLAGS_64BIT << ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET);
flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP;
rockchip_pcie_write(rockchip, flags,
ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
@@ -332,7 +291,7 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn)
{
struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
struct rockchip_pcie *rockchip = &ep->rockchip;
- u16 flags;
+ u32 flags;
flags = rockchip_pcie_read(rockchip,
ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
@@ -345,48 +304,25 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn)
}
static void rockchip_pcie_ep_assert_intx(struct rockchip_pcie_ep *ep, u8 fn,
- u8 intx, bool is_asserted)
+ u8 intx, bool do_assert)
{
struct rockchip_pcie *rockchip = &ep->rockchip;
- u32 r = ep->max_regions - 1;
- u32 offset;
- u32 status;
- u8 msg_code;
-
- if (unlikely(ep->irq_pci_addr != ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR ||
- ep->irq_pci_fn != fn)) {
- rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r,
- AXI_WRAPPER_NOR_MSG,
- ep->irq_phys_addr, 0, 0);
- ep->irq_pci_addr = ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR;
- ep->irq_pci_fn = fn;
- }
intx &= 3;
- if (is_asserted) {
+
+ if (do_assert) {
ep->irq_pending |= BIT(intx);
- msg_code = ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTA + intx;
+ rockchip_pcie_write(rockchip,
+ PCIE_CLIENT_INT_IN_ASSERT |
+ PCIE_CLIENT_INT_PEND_ST_PEND,
+ PCIE_CLIENT_LEGACY_INT_CTRL);
} else {
ep->irq_pending &= ~BIT(intx);
- msg_code = ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTA + intx;
+ rockchip_pcie_write(rockchip,
+ PCIE_CLIENT_INT_IN_DEASSERT |
+ PCIE_CLIENT_INT_PEND_ST_NORMAL,
+ PCIE_CLIENT_LEGACY_INT_CTRL);
}
-
- status = rockchip_pcie_read(rockchip,
- ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
- ROCKCHIP_PCIE_EP_CMD_STATUS);
- status &= ROCKCHIP_PCIE_EP_CMD_STATUS_IS;
-
- if ((status != 0) ^ (ep->irq_pending != 0)) {
- status ^= ROCKCHIP_PCIE_EP_CMD_STATUS_IS;
- rockchip_pcie_write(rockchip, status,
- ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
- ROCKCHIP_PCIE_EP_CMD_STATUS);
- }
-
- offset =
- ROCKCHIP_PCIE_MSG_ROUTING(ROCKCHIP_PCIE_MSG_ROUTING_LOCAL_INTX) |
- ROCKCHIP_PCIE_MSG_CODE(msg_code) | ROCKCHIP_PCIE_MSG_NO_DATA;
- writel(0, ep->irq_cpu_addr + offset);
}
static int rockchip_pcie_ep_send_legacy_irq(struct rockchip_pcie_ep *ep, u8 fn,
@@ -416,9 +352,10 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn,
u8 interrupt_num)
{
struct rockchip_pcie *rockchip = &ep->rockchip;
- u16 flags, mme, data, data_mask;
+ u32 flags, mme, data, data_mask;
u8 msi_count;
- u64 pci_addr, pci_addr_mask = 0xff;
+ u64 pci_addr;
+ u32 r;
/* Check MSI enable bit */
flags = rockchip_pcie_read(&ep->rockchip,
@@ -452,21 +389,20 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn,
ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
ROCKCHIP_PCIE_EP_MSI_CTRL_REG +
PCI_MSI_ADDRESS_LO);
- pci_addr &= GENMASK_ULL(63, 2);
/* Set the outbound region if needed. */
- if (unlikely(ep->irq_pci_addr != (pci_addr & ~pci_addr_mask) ||
+ if (unlikely(ep->irq_pci_addr != (pci_addr & PCIE_ADDR_MASK) ||
ep->irq_pci_fn != fn)) {
- rockchip_pcie_prog_ep_ob_atu(rockchip, fn, ep->max_regions - 1,
- AXI_WRAPPER_MEM_WRITE,
+ r = rockchip_ob_region(ep->irq_phys_addr);
+ rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r,
ep->irq_phys_addr,
- pci_addr & ~pci_addr_mask,
- pci_addr_mask + 1);
- ep->irq_pci_addr = (pci_addr & ~pci_addr_mask);
+ pci_addr & PCIE_ADDR_MASK,
+ ~PCIE_ADDR_MASK + 1);
+ ep->irq_pci_addr = (pci_addr & PCIE_ADDR_MASK);
ep->irq_pci_fn = fn;
}
- writew(data, ep->irq_cpu_addr + (pci_addr & pci_addr_mask));
+ writew(data, ep->irq_cpu_addr + (pci_addr & ~PCIE_ADDR_MASK));
return 0;
}
@@ -506,6 +442,7 @@ static const struct pci_epc_features rockchip_pcie_epc_features = {
.linkup_notifier = false,
.msi_capable = true,
.msix_capable = false,
+ .align = 256,
};
static const struct pci_epc_features*
@@ -547,6 +484,8 @@ static int rockchip_pcie_parse_ep_dt(struct rockchip_pcie *rockchip,
if (err < 0 || ep->max_regions > MAX_REGION_LIMIT)
ep->max_regions = MAX_REGION_LIMIT;
+ ep->ob_region_map = 0;
+
err = of_property_read_u8(dev->of_node, "max-functions",
&ep->epc->max_functions);
if (err < 0)
@@ -567,7 +506,9 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
struct rockchip_pcie *rockchip;
struct pci_epc *epc;
size_t max_regions;
- int err;
+ struct pci_epc_mem_window *windows = NULL;
+ int err, i;
+ u32 cfg_msi, cfg_msix_cp;
ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL);
if (!ep)
@@ -614,15 +555,27 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
/* Only enable function 0 by default */
rockchip_pcie_write(rockchip, BIT(0), PCIE_CORE_PHY_FUNC_CFG);
- err = pci_epc_mem_init(epc, rockchip->mem_res->start,
- resource_size(rockchip->mem_res), PAGE_SIZE);
+ windows = devm_kcalloc(dev, ep->max_regions,
+ sizeof(struct pci_epc_mem_window), GFP_KERNEL);
+ if (!windows) {
+ err = -ENOMEM;
+ goto err_uninit_port;
+ }
+ for (i = 0; i < ep->max_regions; i++) {
+ windows[i].phys_base = rockchip->mem_res->start + (SZ_1M * i);
+ windows[i].size = SZ_1M;
+ windows[i].page_size = SZ_1M;
+ }
+ err = pci_epc_multi_mem_init(epc, windows, ep->max_regions);
+ devm_kfree(dev, windows);
+
if (err < 0) {
dev_err(dev, "failed to initialize the memory space\n");
goto err_uninit_port;
}
ep->irq_cpu_addr = pci_epc_mem_alloc_addr(epc, &ep->irq_phys_addr,
- SZ_128K);
+ SZ_1M);
if (!ep->irq_cpu_addr) {
dev_err(dev, "failed to reserve memory space for MSI\n");
err = -ENOMEM;
@@ -631,6 +584,32 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
ep->irq_pci_addr = ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR;
+ /*
+ * MSI-X is not supported but the controller still advertises the MSI-X
+ * capability by default, which can lead to the Root Complex side
+ * allocating MSI-X vectors which cannot be used. Avoid this by skipping
+ * the MSI-X capability entry in the PCIe capabilities linked-list: get
+ * the next pointer from the MSI-X entry and set that in the MSI
+ * capability entry (which is the previous entry). This way the MSI-X
+ * entry is skipped (left out of the linked-list) and not advertised.
+ */
+ cfg_msi = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE +
+ ROCKCHIP_PCIE_EP_MSI_CTRL_REG);
+
+ cfg_msi &= ~ROCKCHIP_PCIE_EP_MSI_CP1_MASK;
+
+ cfg_msix_cp = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE +
+ ROCKCHIP_PCIE_EP_MSIX_CAP_REG) &
+ ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK;
+
+ cfg_msi |= cfg_msix_cp;
+
+ rockchip_pcie_write(rockchip, cfg_msi,
+ PCIE_EP_CONFIG_BASE + ROCKCHIP_PCIE_EP_MSI_CTRL_REG);
+
+ rockchip_pcie_write(rockchip, PCIE_CLIENT_CONF_ENABLE,
+ PCIE_CLIENT_CONFIG);
+
return 0;
err_epc_mem_exit:
pci_epc_mem_exit(epc);
diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c
index c96c0f454570..2438bc9b3a1a 100644
--- a/drivers/pci/controller/pcie-rockchip-host.c
+++ b/drivers/pci/controller/pcie-rockchip-host.c
@@ -1009,7 +1009,7 @@ err_set_vpcie:
return err;
}
-static int rockchip_pcie_remove(struct platform_device *pdev)
+static void rockchip_pcie_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rockchip_pcie *rockchip = dev_get_drvdata(dev);
@@ -1029,8 +1029,6 @@ static int rockchip_pcie_remove(struct platform_device *pdev)
regulator_disable(rockchip->vpcie3v3);
regulator_disable(rockchip->vpcie1v8);
regulator_disable(rockchip->vpcie0v9);
-
- return 0;
}
static const struct dev_pm_ops rockchip_pcie_pm_ops = {
@@ -1051,7 +1049,7 @@ static struct platform_driver rockchip_pcie_driver = {
.pm = &rockchip_pcie_pm_ops,
},
.probe = rockchip_pcie_probe,
- .remove = rockchip_pcie_remove,
+ .remove_new = rockchip_pcie_remove,
};
module_platform_driver(rockchip_pcie_driver);
diff --git a/drivers/pci/controller/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c
index 990a00e08bc5..1aa84035a8bc 100644
--- a/drivers/pci/controller/pcie-rockchip.c
+++ b/drivers/pci/controller/pcie-rockchip.c
@@ -14,6 +14,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
+#include <linux/iopoll.h>
#include <linux/of_pci.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
@@ -153,6 +154,12 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip)
}
EXPORT_SYMBOL_GPL(rockchip_pcie_parse_dt);
+#define rockchip_pcie_read_addr(addr) rockchip_pcie_read(rockchip, addr)
+/* 100 ms max wait time for PHY PLLs to lock */
+#define RK_PHY_PLL_LOCK_TIMEOUT_US 100000
+/* Sleep should be less than 20ms */
+#define RK_PHY_PLL_LOCK_SLEEP_US 1000
+
int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
{
struct device *dev = rockchip->dev;
@@ -254,6 +261,16 @@ int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
}
}
+ err = readx_poll_timeout(rockchip_pcie_read_addr,
+ PCIE_CLIENT_SIDE_BAND_STATUS,
+ regs, !(regs & PCIE_CLIENT_PHY_ST),
+ RK_PHY_PLL_LOCK_SLEEP_US,
+ RK_PHY_PLL_LOCK_TIMEOUT_US);
+ if (err) {
+ dev_err(dev, "PHY PLLs could not lock, %d\n", err);
+ goto err_power_off_phy;
+ }
+
/*
* Please don't reorder the deassert sequence of the following
* four reset pins.
diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h
index 32c3a859c26b..fe0333778fd9 100644
--- a/drivers/pci/controller/pcie-rockchip.h
+++ b/drivers/pci/controller/pcie-rockchip.h
@@ -38,6 +38,13 @@
#define PCIE_CLIENT_MODE_EP HIWORD_UPDATE(0x0040, 0)
#define PCIE_CLIENT_GEN_SEL_1 HIWORD_UPDATE(0x0080, 0)
#define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080)
+#define PCIE_CLIENT_LEGACY_INT_CTRL (PCIE_CLIENT_BASE + 0x0c)
+#define PCIE_CLIENT_INT_IN_ASSERT HIWORD_UPDATE_BIT(0x0002)
+#define PCIE_CLIENT_INT_IN_DEASSERT HIWORD_UPDATE(0x0002, 0)
+#define PCIE_CLIENT_INT_PEND_ST_PEND HIWORD_UPDATE_BIT(0x0001)
+#define PCIE_CLIENT_INT_PEND_ST_NORMAL HIWORD_UPDATE(0x0001, 0)
+#define PCIE_CLIENT_SIDE_BAND_STATUS (PCIE_CLIENT_BASE + 0x20)
+#define PCIE_CLIENT_PHY_ST BIT(12)
#define PCIE_CLIENT_DEBUG_OUT_0 (PCIE_CLIENT_BASE + 0x3c)
#define PCIE_CLIENT_DEBUG_LTSSM_MASK GENMASK(5, 0)
#define PCIE_CLIENT_DEBUG_LTSSM_L1 0x18
@@ -132,7 +139,10 @@
#define PCIE_RC_RP_ATS_BASE 0x400000
#define PCIE_RC_CONFIG_NORMAL_BASE 0x800000
+#define PCIE_EP_PF_CONFIG_REGS_BASE 0x800000
#define PCIE_RC_CONFIG_BASE 0xa00000
+#define PCIE_EP_CONFIG_BASE 0xa00000
+#define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00)
#define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08)
#define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4)
#define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18
@@ -148,10 +158,11 @@
#define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274)
#define PCIE_RC_CONFIG_THP_CAP_NEXT_MASK GENMASK(31, 20)
+#define PCIE_ADDR_MASK 0xffffff00
#define PCIE_CORE_AXI_CONF_BASE 0xc00000
#define PCIE_CORE_OB_REGION_ADDR0 (PCIE_CORE_AXI_CONF_BASE + 0x0)
#define PCIE_CORE_OB_REGION_ADDR0_NUM_BITS 0x3f
-#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR 0xffffff00
+#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR PCIE_ADDR_MASK
#define PCIE_CORE_OB_REGION_ADDR1 (PCIE_CORE_AXI_CONF_BASE + 0x4)
#define PCIE_CORE_OB_REGION_DESC0 (PCIE_CORE_AXI_CONF_BASE + 0x8)
#define PCIE_CORE_OB_REGION_DESC1 (PCIE_CORE_AXI_CONF_BASE + 0xc)
@@ -159,7 +170,7 @@
#define PCIE_CORE_AXI_INBOUND_BASE 0xc00800
#define PCIE_RP_IB_ADDR0 (PCIE_CORE_AXI_INBOUND_BASE + 0x0)
#define PCIE_CORE_IB_REGION_ADDR0_NUM_BITS 0x3f
-#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR 0xffffff00
+#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR PCIE_ADDR_MASK
#define PCIE_RP_IB_ADDR1 (PCIE_CORE_AXI_INBOUND_BASE + 0x4)
/* Size of one AXI Region (not Region 0) */
@@ -216,21 +227,28 @@
#define ROCKCHIP_PCIE_EP_CMD_STATUS 0x4
#define ROCKCHIP_PCIE_EP_CMD_STATUS_IS BIT(19)
#define ROCKCHIP_PCIE_EP_MSI_CTRL_REG 0x90
+#define ROCKCHIP_PCIE_EP_MSI_CP1_OFFSET 8
+#define ROCKCHIP_PCIE_EP_MSI_CP1_MASK GENMASK(15, 8)
+#define ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET 16
#define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET 17
#define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK GENMASK(19, 17)
#define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET 20
#define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_MASK GENMASK(22, 20)
#define ROCKCHIP_PCIE_EP_MSI_CTRL_ME BIT(16)
#define ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP BIT(24)
+#define ROCKCHIP_PCIE_EP_MSIX_CAP_REG 0xb0
+#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_OFFSET 8
+#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK GENMASK(15, 8)
#define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1
#define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3
-#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) (((fn) << 12) & GENMASK(19, 12))
+#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) \
+ (PCIE_EP_PF_CONFIG_REGS_BASE + (((fn) << 12) & GENMASK(19, 12)))
+#define ROCKCHIP_PCIE_EP_VIRT_FUNC_BASE(fn) \
+ (PCIE_EP_PF_CONFIG_REGS_BASE + 0x10000 + (((fn) << 12) & GENMASK(19, 12)))
#define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \
- (PCIE_RC_RP_ATS_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008)
+ (PCIE_CORE_AXI_CONF_BASE + 0x0828 + (fn) * 0x0040 + (bar) * 0x0008)
#define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar) \
- (PCIE_RC_RP_ATS_BASE + 0x0844 + (fn) * 0x0040 + (bar) * 0x0008)
-#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \
- (PCIE_RC_RP_ATS_BASE + 0x0000 + ((r) & 0x1f) * 0x0020)
+ (PCIE_CORE_AXI_CONF_BASE + 0x082c + (fn) * 0x0040 + (bar) * 0x0008)
#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN_MASK GENMASK(19, 12)
#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) \
(((devfn) << 12) & \
@@ -238,20 +256,21 @@
#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK GENMASK(27, 20)
#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(bus) \
(((bus) << 20) & ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK)
+#define PCIE_RC_EP_ATR_OB_REGIONS_1_32 (PCIE_CORE_AXI_CONF_BASE + 0x0020)
+#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \
+ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0000 + ((r) & 0x1f) * 0x0020)
#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r) \
- (PCIE_RC_RP_ATS_BASE + 0x0004 + ((r) & 0x1f) * 0x0020)
+ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0004 + ((r) & 0x1f) * 0x0020)
#define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID BIT(23)
#define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK GENMASK(31, 24)
#define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(devfn) \
(((devfn) << 24) & ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK)
#define ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r) \
- (PCIE_RC_RP_ATS_BASE + 0x0008 + ((r) & 0x1f) * 0x0020)
-#define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \
- (PCIE_RC_RP_ATS_BASE + 0x000c + ((r) & 0x1f) * 0x0020)
-#define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r) \
- (PCIE_RC_RP_ATS_BASE + 0x0018 + ((r) & 0x1f) * 0x0020)
-#define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r) \
- (PCIE_RC_RP_ATS_BASE + 0x001c + ((r) & 0x1f) * 0x0020)
+ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0008 + ((r) & 0x1f) * 0x0020)
+#define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \
+ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x000c + ((r) & 0x1f) * 0x0020)
+#define ROCKCHIP_PCIE_AT_OB_REGION_DESC2(r) \
+ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0010 + ((r) & 0x1f) * 0x0020)
#define ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG0(fn) \
(PCIE_CORE_CTRL_MGMT_BASE + 0x0240 + (fn) * 0x0008)
diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
index 990630ec57c6..e718a816d481 100644
--- a/drivers/pci/controller/vmd.c
+++ b/drivers/pci/controller/vmd.c
@@ -927,7 +927,8 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
if (!list_empty(&child->devices)) {
dev = list_first_entry(&child->devices,
struct pci_dev, bus_list);
- if (pci_reset_bus(dev))
+ ret = pci_reset_bus(dev);
+ if (ret)
pci_warn(dev, "can't reset device: %d\n", ret);
break;
@@ -1036,6 +1037,13 @@ static void vmd_remove(struct pci_dev *dev)
ida_simple_remove(&vmd_instance_ida, vmd->instance);
}
+static void vmd_shutdown(struct pci_dev *dev)
+{
+ struct vmd_dev *vmd = pci_get_drvdata(dev);
+
+ vmd_remove_irq_domain(vmd);
+}
+
#ifdef CONFIG_PM_SLEEP
static int vmd_suspend(struct device *dev)
{
@@ -1101,6 +1109,7 @@ static struct pci_driver vmd_drv = {
.id_table = vmd_ids,
.probe = vmd_probe,
.remove = vmd_remove,
+ .shutdown = vmd_shutdown,
.driver = {
.pm = &vmd_dev_pm_ops,
},
diff --git a/drivers/pci/endpoint/functions/Kconfig b/drivers/pci/endpoint/functions/Kconfig
index 9fd560886871..0c9cea0698d7 100644
--- a/drivers/pci/endpoint/functions/Kconfig
+++ b/drivers/pci/endpoint/functions/Kconfig
@@ -27,7 +27,7 @@ config PCI_EPF_NTB
If in doubt, say "N" to disable Endpoint NTB driver.
config PCI_EPF_VNTB
- tristate "PCI Endpoint NTB driver"
+ tristate "PCI Endpoint Virtual NTB driver"
depends on PCI_ENDPOINT
depends on NTB
select CONFIGFS_FS
@@ -37,3 +37,13 @@ config PCI_EPF_VNTB
between PCI Root Port and PCIe Endpoint.
If in doubt, say "N" to disable Endpoint NTB driver.
+
+config PCI_EPF_MHI
+ tristate "PCI Endpoint driver for MHI bus"
+ depends on PCI_ENDPOINT && MHI_BUS_EP
+ help
+ Enable this configuration option to enable the PCI Endpoint
+ driver for Modem Host Interface (MHI) bus in Qualcomm Endpoint
+ devices such as SDX55.
+
+ If in doubt, say "N" to disable Endpoint driver for MHI bus.
diff --git a/drivers/pci/endpoint/functions/Makefile b/drivers/pci/endpoint/functions/Makefile
index 5c13001deaba..696473fce50e 100644
--- a/drivers/pci/endpoint/functions/Makefile
+++ b/drivers/pci/endpoint/functions/Makefile
@@ -6,3 +6,4 @@
obj-$(CONFIG_PCI_EPF_TEST) += pci-epf-test.o
obj-$(CONFIG_PCI_EPF_NTB) += pci-epf-ntb.o
obj-$(CONFIG_PCI_EPF_VNTB) += pci-epf-vntb.o
+obj-$(CONFIG_PCI_EPF_MHI) += pci-epf-mhi.o
diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c
new file mode 100644
index 000000000000..9c1f5a154fbd
--- /dev/null
+++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c
@@ -0,0 +1,458 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCI EPF driver for MHI Endpoint devices
+ *
+ * Copyright (C) 2023 Linaro Ltd.
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ */
+
+#include <linux/mhi_ep.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+
+#define MHI_VERSION_1_0 0x01000000
+
+#define to_epf_mhi(cntrl) container_of(cntrl, struct pci_epf_mhi, cntrl)
+
+struct pci_epf_mhi_ep_info {
+ const struct mhi_ep_cntrl_config *config;
+ struct pci_epf_header *epf_header;
+ enum pci_barno bar_num;
+ u32 epf_flags;
+ u32 msi_count;
+ u32 mru;
+};
+
+#define MHI_EP_CHANNEL_CONFIG(ch_num, ch_name, direction) \
+ { \
+ .num = ch_num, \
+ .name = ch_name, \
+ .dir = direction, \
+ }
+
+#define MHI_EP_CHANNEL_CONFIG_UL(ch_num, ch_name) \
+ MHI_EP_CHANNEL_CONFIG(ch_num, ch_name, DMA_TO_DEVICE)
+
+#define MHI_EP_CHANNEL_CONFIG_DL(ch_num, ch_name) \
+ MHI_EP_CHANNEL_CONFIG(ch_num, ch_name, DMA_FROM_DEVICE)
+
+static const struct mhi_ep_channel_config mhi_v1_channels[] = {
+ MHI_EP_CHANNEL_CONFIG_UL(0, "LOOPBACK"),
+ MHI_EP_CHANNEL_CONFIG_DL(1, "LOOPBACK"),
+ MHI_EP_CHANNEL_CONFIG_UL(2, "SAHARA"),
+ MHI_EP_CHANNEL_CONFIG_DL(3, "SAHARA"),
+ MHI_EP_CHANNEL_CONFIG_UL(4, "DIAG"),
+ MHI_EP_CHANNEL_CONFIG_DL(5, "DIAG"),
+ MHI_EP_CHANNEL_CONFIG_UL(6, "SSR"),
+ MHI_EP_CHANNEL_CONFIG_DL(7, "SSR"),
+ MHI_EP_CHANNEL_CONFIG_UL(8, "QDSS"),
+ MHI_EP_CHANNEL_CONFIG_DL(9, "QDSS"),
+ MHI_EP_CHANNEL_CONFIG_UL(10, "EFS"),
+ MHI_EP_CHANNEL_CONFIG_DL(11, "EFS"),
+ MHI_EP_CHANNEL_CONFIG_UL(12, "MBIM"),
+ MHI_EP_CHANNEL_CONFIG_DL(13, "MBIM"),
+ MHI_EP_CHANNEL_CONFIG_UL(14, "QMI"),
+ MHI_EP_CHANNEL_CONFIG_DL(15, "QMI"),
+ MHI_EP_CHANNEL_CONFIG_UL(16, "QMI"),
+ MHI_EP_CHANNEL_CONFIG_DL(17, "QMI"),
+ MHI_EP_CHANNEL_CONFIG_UL(18, "IP-CTRL-1"),
+ MHI_EP_CHANNEL_CONFIG_DL(19, "IP-CTRL-1"),
+ MHI_EP_CHANNEL_CONFIG_UL(20, "IPCR"),
+ MHI_EP_CHANNEL_CONFIG_DL(21, "IPCR"),
+ MHI_EP_CHANNEL_CONFIG_UL(32, "DUN"),
+ MHI_EP_CHANNEL_CONFIG_DL(33, "DUN"),
+ MHI_EP_CHANNEL_CONFIG_UL(46, "IP_SW0"),
+ MHI_EP_CHANNEL_CONFIG_DL(47, "IP_SW0"),
+};
+
+static const struct mhi_ep_cntrl_config mhi_v1_config = {
+ .max_channels = 128,
+ .num_channels = ARRAY_SIZE(mhi_v1_channels),
+ .ch_cfg = mhi_v1_channels,
+ .mhi_version = MHI_VERSION_1_0,
+};
+
+static struct pci_epf_header sdx55_header = {
+ .vendorid = PCI_VENDOR_ID_QCOM,
+ .deviceid = 0x0306,
+ .baseclass_code = PCI_BASE_CLASS_COMMUNICATION,
+ .subclass_code = PCI_CLASS_COMMUNICATION_MODEM & 0xff,
+ .interrupt_pin = PCI_INTERRUPT_INTA,
+};
+
+static const struct pci_epf_mhi_ep_info sdx55_info = {
+ .config = &mhi_v1_config,
+ .epf_header = &sdx55_header,
+ .bar_num = BAR_0,
+ .epf_flags = PCI_BASE_ADDRESS_MEM_TYPE_32,
+ .msi_count = 32,
+ .mru = 0x8000,
+};
+
+struct pci_epf_mhi {
+ const struct pci_epf_mhi_ep_info *info;
+ struct mhi_ep_cntrl mhi_cntrl;
+ struct pci_epf *epf;
+ struct mutex lock;
+ void __iomem *mmio;
+ resource_size_t mmio_phys;
+ u32 mmio_size;
+ int irq;
+};
+
+static int __pci_epf_mhi_alloc_map(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr,
+ phys_addr_t *paddr, void __iomem **vaddr,
+ size_t offset, size_t size)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ struct pci_epf *epf = epf_mhi->epf;
+ struct pci_epc *epc = epf->epc;
+ int ret;
+
+ *vaddr = pci_epc_mem_alloc_addr(epc, paddr, size + offset);
+ if (!*vaddr)
+ return -ENOMEM;
+
+ ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, *paddr,
+ pci_addr - offset, size + offset);
+ if (ret) {
+ pci_epc_mem_free_addr(epc, *paddr, *vaddr, size + offset);
+ return ret;
+ }
+
+ *paddr = *paddr + offset;
+ *vaddr = *vaddr + offset;
+
+ return 0;
+}
+
+static int pci_epf_mhi_alloc_map(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr,
+ phys_addr_t *paddr, void __iomem **vaddr,
+ size_t size)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ struct pci_epc *epc = epf_mhi->epf->epc;
+ size_t offset = pci_addr & (epc->mem->window.page_size - 1);
+
+ return __pci_epf_mhi_alloc_map(mhi_cntrl, pci_addr, paddr, vaddr,
+ offset, size);
+}
+
+static void __pci_epf_mhi_unmap_free(struct mhi_ep_cntrl *mhi_cntrl,
+ u64 pci_addr, phys_addr_t paddr,
+ void __iomem *vaddr, size_t offset,
+ size_t size)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ struct pci_epf *epf = epf_mhi->epf;
+ struct pci_epc *epc = epf->epc;
+
+ pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, paddr - offset);
+ pci_epc_mem_free_addr(epc, paddr - offset, vaddr - offset,
+ size + offset);
+}
+
+static void pci_epf_mhi_unmap_free(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr,
+ phys_addr_t paddr, void __iomem *vaddr,
+ size_t size)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ struct pci_epf *epf = epf_mhi->epf;
+ struct pci_epc *epc = epf->epc;
+ size_t offset = pci_addr & (epc->mem->window.page_size - 1);
+
+ __pci_epf_mhi_unmap_free(mhi_cntrl, pci_addr, paddr, vaddr, offset,
+ size);
+}
+
+static void pci_epf_mhi_raise_irq(struct mhi_ep_cntrl *mhi_cntrl, u32 vector)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ struct pci_epf *epf = epf_mhi->epf;
+ struct pci_epc *epc = epf->epc;
+
+ /*
+ * MHI supplies 0 based MSI vectors but the API expects the vector
+ * number to start from 1, so we need to increment the vector by 1.
+ */
+ pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, PCI_EPC_IRQ_MSI,
+ vector + 1);
+}
+
+static int pci_epf_mhi_read_from_host(struct mhi_ep_cntrl *mhi_cntrl, u64 from,
+ void *to, size_t size)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ size_t offset = from % SZ_4K;
+ void __iomem *tre_buf;
+ phys_addr_t tre_phys;
+ int ret;
+
+ mutex_lock(&epf_mhi->lock);
+
+ ret = __pci_epf_mhi_alloc_map(mhi_cntrl, from, &tre_phys, &tre_buf,
+ offset, size);
+ if (ret) {
+ mutex_unlock(&epf_mhi->lock);
+ return ret;
+ }
+
+ memcpy_fromio(to, tre_buf, size);
+
+ __pci_epf_mhi_unmap_free(mhi_cntrl, from, tre_phys, tre_buf, offset,
+ size);
+
+ mutex_unlock(&epf_mhi->lock);
+
+ return 0;
+}
+
+static int pci_epf_mhi_write_to_host(struct mhi_ep_cntrl *mhi_cntrl,
+ void *from, u64 to, size_t size)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ size_t offset = to % SZ_4K;
+ void __iomem *tre_buf;
+ phys_addr_t tre_phys;
+ int ret;
+
+ mutex_lock(&epf_mhi->lock);
+
+ ret = __pci_epf_mhi_alloc_map(mhi_cntrl, to, &tre_phys, &tre_buf,
+ offset, size);
+ if (ret) {
+ mutex_unlock(&epf_mhi->lock);
+ return ret;
+ }
+
+ memcpy_toio(tre_buf, from, size);
+
+ __pci_epf_mhi_unmap_free(mhi_cntrl, to, tre_phys, tre_buf, offset,
+ size);
+
+ mutex_unlock(&epf_mhi->lock);
+
+ return 0;
+}
+
+static int pci_epf_mhi_core_init(struct pci_epf *epf)
+{
+ struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
+ const struct pci_epf_mhi_ep_info *info = epf_mhi->info;
+ struct pci_epf_bar *epf_bar = &epf->bar[info->bar_num];
+ struct pci_epc *epc = epf->epc;
+ struct device *dev = &epf->dev;
+ int ret;
+
+ epf_bar->phys_addr = epf_mhi->mmio_phys;
+ epf_bar->size = epf_mhi->mmio_size;
+ epf_bar->barno = info->bar_num;
+ epf_bar->flags = info->epf_flags;
+ ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no, epf_bar);
+ if (ret) {
+ dev_err(dev, "Failed to set BAR: %d\n", ret);
+ return ret;
+ }
+
+ ret = pci_epc_set_msi(epc, epf->func_no, epf->vfunc_no,
+ order_base_2(info->msi_count));
+ if (ret) {
+ dev_err(dev, "Failed to set MSI configuration: %d\n", ret);
+ return ret;
+ }
+
+ ret = pci_epc_write_header(epc, epf->func_no, epf->vfunc_no,
+ epf->header);
+ if (ret) {
+ dev_err(dev, "Failed to set Configuration header: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pci_epf_mhi_link_up(struct pci_epf *epf)
+{
+ struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
+ const struct pci_epf_mhi_ep_info *info = epf_mhi->info;
+ struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl;
+ struct pci_epc *epc = epf->epc;
+ struct device *dev = &epf->dev;
+ int ret;
+
+ mhi_cntrl->mmio = epf_mhi->mmio;
+ mhi_cntrl->irq = epf_mhi->irq;
+ mhi_cntrl->mru = info->mru;
+
+ /* Assign the struct dev of PCI EP as MHI controller device */
+ mhi_cntrl->cntrl_dev = epc->dev.parent;
+ mhi_cntrl->raise_irq = pci_epf_mhi_raise_irq;
+ mhi_cntrl->alloc_map = pci_epf_mhi_alloc_map;
+ mhi_cntrl->unmap_free = pci_epf_mhi_unmap_free;
+ mhi_cntrl->read_from_host = pci_epf_mhi_read_from_host;
+ mhi_cntrl->write_to_host = pci_epf_mhi_write_to_host;
+
+ /* Register the MHI EP controller */
+ ret = mhi_ep_register_controller(mhi_cntrl, info->config);
+ if (ret) {
+ dev_err(dev, "Failed to register MHI EP controller: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pci_epf_mhi_link_down(struct pci_epf *epf)
+{
+ struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
+ struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl;
+
+ if (mhi_cntrl->mhi_dev) {
+ mhi_ep_power_down(mhi_cntrl);
+ mhi_ep_unregister_controller(mhi_cntrl);
+ }
+
+ return 0;
+}
+
+static int pci_epf_mhi_bme(struct pci_epf *epf)
+{
+ struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
+ struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl;
+ struct device *dev = &epf->dev;
+ int ret;
+
+ /*
+ * Power up the MHI EP stack if link is up and stack is in power down
+ * state.
+ */
+ if (!mhi_cntrl->enabled && mhi_cntrl->mhi_dev) {
+ ret = mhi_ep_power_up(mhi_cntrl);
+ if (ret) {
+ dev_err(dev, "Failed to power up MHI EP: %d\n", ret);
+ mhi_ep_unregister_controller(mhi_cntrl);
+ }
+ }
+
+ return 0;
+}
+
+static int pci_epf_mhi_bind(struct pci_epf *epf)
+{
+ struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
+ struct pci_epc *epc = epf->epc;
+ struct platform_device *pdev = to_platform_device(epc->dev.parent);
+ struct resource *res;
+ int ret;
+
+ /* Get MMIO base address from Endpoint controller */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mmio");
+ epf_mhi->mmio_phys = res->start;
+ epf_mhi->mmio_size = resource_size(res);
+
+ epf_mhi->mmio = ioremap(epf_mhi->mmio_phys, epf_mhi->mmio_size);
+ if (!epf_mhi->mmio)
+ return -ENOMEM;
+
+ ret = platform_get_irq_byname(pdev, "doorbell");
+ if (ret < 0) {
+ iounmap(epf_mhi->mmio);
+ return ret;
+ }
+
+ epf_mhi->irq = ret;
+
+ return 0;
+}
+
+static void pci_epf_mhi_unbind(struct pci_epf *epf)
+{
+ struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
+ const struct pci_epf_mhi_ep_info *info = epf_mhi->info;
+ struct pci_epf_bar *epf_bar = &epf->bar[info->bar_num];
+ struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl;
+ struct pci_epc *epc = epf->epc;
+
+ /*
+ * Forcefully power down the MHI EP stack. Only way to bring the MHI EP
+ * stack back to working state after successive bind is by getting BME
+ * from host.
+ */
+ if (mhi_cntrl->mhi_dev) {
+ mhi_ep_power_down(mhi_cntrl);
+ mhi_ep_unregister_controller(mhi_cntrl);
+ }
+
+ iounmap(epf_mhi->mmio);
+ pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no, epf_bar);
+}
+
+static struct pci_epc_event_ops pci_epf_mhi_event_ops = {
+ .core_init = pci_epf_mhi_core_init,
+ .link_up = pci_epf_mhi_link_up,
+ .link_down = pci_epf_mhi_link_down,
+ .bme = pci_epf_mhi_bme,
+};
+
+static int pci_epf_mhi_probe(struct pci_epf *epf,
+ const struct pci_epf_device_id *id)
+{
+ struct pci_epf_mhi_ep_info *info =
+ (struct pci_epf_mhi_ep_info *)id->driver_data;
+ struct pci_epf_mhi *epf_mhi;
+ struct device *dev = &epf->dev;
+
+ epf_mhi = devm_kzalloc(dev, sizeof(*epf_mhi), GFP_KERNEL);
+ if (!epf_mhi)
+ return -ENOMEM;
+
+ epf->header = info->epf_header;
+ epf_mhi->info = info;
+ epf_mhi->epf = epf;
+
+ epf->event_ops = &pci_epf_mhi_event_ops;
+
+ mutex_init(&epf_mhi->lock);
+
+ epf_set_drvdata(epf, epf_mhi);
+
+ return 0;
+}
+
+static const struct pci_epf_device_id pci_epf_mhi_ids[] = {
+ {
+ .name = "sdx55", .driver_data = (kernel_ulong_t)&sdx55_info,
+ },
+ {},
+};
+
+static struct pci_epf_ops pci_epf_mhi_ops = {
+ .unbind = pci_epf_mhi_unbind,
+ .bind = pci_epf_mhi_bind,
+};
+
+static struct pci_epf_driver pci_epf_mhi_driver = {
+ .driver.name = "pci_epf_mhi",
+ .probe = pci_epf_mhi_probe,
+ .id_table = pci_epf_mhi_ids,
+ .ops = &pci_epf_mhi_ops,
+ .owner = THIS_MODULE,
+};
+
+static int __init pci_epf_mhi_init(void)
+{
+ return pci_epf_register_driver(&pci_epf_mhi_driver);
+}
+module_init(pci_epf_mhi_init);
+
+static void __exit pci_epf_mhi_exit(void)
+{
+ pci_epf_unregister_driver(&pci_epf_mhi_driver);
+}
+module_exit(pci_epf_mhi_exit);
+
+MODULE_DESCRIPTION("PCI EPF driver for MHI Endpoint devices");
+MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pci/endpoint/functions/pci-epf-ntb.c b/drivers/pci/endpoint/functions/pci-epf-ntb.c
index 9a00448c7e61..9aac2c6f3bb9 100644
--- a/drivers/pci/endpoint/functions/pci-epf-ntb.c
+++ b/drivers/pci/endpoint/functions/pci-epf-ntb.c
@@ -2075,11 +2075,13 @@ static struct config_group *epf_ntb_add_cfs(struct pci_epf *epf,
/**
* epf_ntb_probe() - Probe NTB function driver
* @epf: NTB endpoint function device
+ * @id: NTB endpoint function device ID
*
* Probe NTB function driver when endpoint function bus detects a NTB
* endpoint function.
*/
-static int epf_ntb_probe(struct pci_epf *epf)
+static int epf_ntb_probe(struct pci_epf *epf,
+ const struct pci_epf_device_id *id)
{
struct epf_ntb *ntb;
struct device *dev;
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
index 0f9d2ec822ac..1f0d2b84296a 100644
--- a/drivers/pci/endpoint/functions/pci-epf-test.c
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -54,6 +54,9 @@ struct pci_epf_test {
struct delayed_work cmd_handler;
struct dma_chan *dma_chan_tx;
struct dma_chan *dma_chan_rx;
+ struct dma_chan *transfer_chan;
+ dma_cookie_t transfer_cookie;
+ enum dma_status transfer_status;
struct completion transfer_complete;
bool dma_supported;
bool dma_private;
@@ -85,8 +88,14 @@ static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
static void pci_epf_test_dma_callback(void *param)
{
struct pci_epf_test *epf_test = param;
-
- complete(&epf_test->transfer_complete);
+ struct dma_tx_state state;
+
+ epf_test->transfer_status =
+ dmaengine_tx_status(epf_test->transfer_chan,
+ epf_test->transfer_cookie, &state);
+ if (epf_test->transfer_status == DMA_COMPLETE ||
+ epf_test->transfer_status == DMA_ERROR)
+ complete(&epf_test->transfer_complete);
}
/**
@@ -112,7 +121,7 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test,
size_t len, dma_addr_t dma_remote,
enum dma_transfer_direction dir)
{
- struct dma_chan *chan = (dir == DMA_DEV_TO_MEM) ?
+ struct dma_chan *chan = (dir == DMA_MEM_TO_DEV) ?
epf_test->dma_chan_tx : epf_test->dma_chan_rx;
dma_addr_t dma_local = (dir == DMA_MEM_TO_DEV) ? dma_src : dma_dst;
enum dma_ctrl_flags flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
@@ -120,7 +129,6 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test,
struct dma_async_tx_descriptor *tx;
struct dma_slave_config sconf = {};
struct device *dev = &epf->dev;
- dma_cookie_t cookie;
int ret;
if (IS_ERR_OR_NULL(chan)) {
@@ -151,26 +159,34 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test,
return -EIO;
}
+ reinit_completion(&epf_test->transfer_complete);
+ epf_test->transfer_chan = chan;
tx->callback = pci_epf_test_dma_callback;
tx->callback_param = epf_test;
- cookie = tx->tx_submit(tx);
- reinit_completion(&epf_test->transfer_complete);
+ epf_test->transfer_cookie = dmaengine_submit(tx);
- ret = dma_submit_error(cookie);
+ ret = dma_submit_error(epf_test->transfer_cookie);
if (ret) {
- dev_err(dev, "Failed to do DMA tx_submit %d\n", cookie);
- return -EIO;
+ dev_err(dev, "Failed to do DMA tx_submit %d\n", ret);
+ goto terminate;
}
dma_async_issue_pending(chan);
ret = wait_for_completion_interruptible(&epf_test->transfer_complete);
if (ret < 0) {
- dmaengine_terminate_sync(chan);
- dev_err(dev, "DMA wait_for_completion_timeout\n");
- return -ETIMEDOUT;
+ dev_err(dev, "DMA wait_for_completion interrupted\n");
+ goto terminate;
}
- return 0;
+ if (epf_test->transfer_status == DMA_ERROR) {
+ dev_err(dev, "DMA transfer failed\n");
+ ret = -EIO;
+ }
+
+terminate:
+ dmaengine_terminate_sync(chan);
+
+ return ret;
}
struct epf_dma_filter {
@@ -279,40 +295,29 @@ static void pci_epf_test_clean_dma_chan(struct pci_epf_test *epf_test)
return;
}
-static void pci_epf_test_print_rate(const char *ops, u64 size,
+static void pci_epf_test_print_rate(struct pci_epf_test *epf_test,
+ const char *op, u64 size,
struct timespec64 *start,
struct timespec64 *end, bool dma)
{
- struct timespec64 ts;
- u64 rate, ns;
-
- ts = timespec64_sub(*end, *start);
-
- /* convert both size (stored in 'rate') and time in terms of 'ns' */
- ns = timespec64_to_ns(&ts);
- rate = size * NSEC_PER_SEC;
-
- /* Divide both size (stored in 'rate') and ns by a common factor */
- while (ns > UINT_MAX) {
- rate >>= 1;
- ns >>= 1;
- }
-
- if (!ns)
- return;
+ struct timespec64 ts = timespec64_sub(*end, *start);
+ u64 rate = 0, ns;
/* calculate the rate */
- do_div(rate, (uint32_t)ns);
+ ns = timespec64_to_ns(&ts);
+ if (ns)
+ rate = div64_u64(size * NSEC_PER_SEC, ns * 1000);
- pr_info("\n%s => Size: %llu bytes\t DMA: %s\t Time: %llu.%09u seconds\t"
- "Rate: %llu KB/s\n", ops, size, dma ? "YES" : "NO",
- (u64)ts.tv_sec, (u32)ts.tv_nsec, rate / 1024);
+ dev_info(&epf_test->epf->dev,
+ "%s => Size: %llu B, DMA: %s, Time: %llu.%09u s, Rate: %llu KB/s\n",
+ op, size, dma ? "YES" : "NO",
+ (u64)ts.tv_sec, (u32)ts.tv_nsec, rate);
}
-static int pci_epf_test_copy(struct pci_epf_test *epf_test)
+static void pci_epf_test_copy(struct pci_epf_test *epf_test,
+ struct pci_epf_test_reg *reg)
{
int ret;
- bool use_dma;
void __iomem *src_addr;
void __iomem *dst_addr;
phys_addr_t src_phys_addr;
@@ -321,8 +326,6 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)
struct pci_epf *epf = epf_test->epf;
struct device *dev = &epf->dev;
struct pci_epc *epc = epf->epc;
- enum pci_barno test_reg_bar = epf_test->test_reg_bar;
- struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
src_addr = pci_epc_mem_alloc_addr(epc, &src_phys_addr, reg->size);
if (!src_addr) {
@@ -357,14 +360,7 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)
}
ktime_get_ts64(&start);
- use_dma = !!(reg->flags & FLAG_USE_DMA);
- if (use_dma) {
- if (!epf_test->dma_supported) {
- dev_err(dev, "Cannot transfer data using DMA\n");
- ret = -EINVAL;
- goto err_map_addr;
- }
-
+ if (reg->flags & FLAG_USE_DMA) {
if (epf_test->dma_private) {
dev_err(dev, "Cannot transfer data using DMA\n");
ret = -EINVAL;
@@ -390,7 +386,8 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)
kfree(buf);
}
ktime_get_ts64(&end);
- pci_epf_test_print_rate("COPY", reg->size, &start, &end, use_dma);
+ pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start, &end,
+ reg->flags & FLAG_USE_DMA);
err_map_addr:
pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr);
@@ -405,16 +402,19 @@ err_src_addr:
pci_epc_mem_free_addr(epc, src_phys_addr, src_addr, reg->size);
err:
- return ret;
+ if (!ret)
+ reg->status |= STATUS_COPY_SUCCESS;
+ else
+ reg->status |= STATUS_COPY_FAIL;
}
-static int pci_epf_test_read(struct pci_epf_test *epf_test)
+static void pci_epf_test_read(struct pci_epf_test *epf_test,
+ struct pci_epf_test_reg *reg)
{
int ret;
void __iomem *src_addr;
void *buf;
u32 crc32;
- bool use_dma;
phys_addr_t phys_addr;
phys_addr_t dst_phys_addr;
struct timespec64 start, end;
@@ -422,8 +422,6 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test)
struct device *dev = &epf->dev;
struct pci_epc *epc = epf->epc;
struct device *dma_dev = epf->epc->dev.parent;
- enum pci_barno test_reg_bar = epf_test->test_reg_bar;
- struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
src_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
if (!src_addr) {
@@ -447,14 +445,7 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test)
goto err_map_addr;
}
- use_dma = !!(reg->flags & FLAG_USE_DMA);
- if (use_dma) {
- if (!epf_test->dma_supported) {
- dev_err(dev, "Cannot transfer data using DMA\n");
- ret = -EINVAL;
- goto err_dma_map;
- }
-
+ if (reg->flags & FLAG_USE_DMA) {
dst_phys_addr = dma_map_single(dma_dev, buf, reg->size,
DMA_FROM_DEVICE);
if (dma_mapping_error(dma_dev, dst_phys_addr)) {
@@ -479,7 +470,8 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test)
ktime_get_ts64(&end);
}
- pci_epf_test_print_rate("READ", reg->size, &start, &end, use_dma);
+ pci_epf_test_print_rate(epf_test, "READ", reg->size, &start, &end,
+ reg->flags & FLAG_USE_DMA);
crc32 = crc32_le(~0, buf, reg->size);
if (crc32 != reg->checksum)
@@ -495,15 +487,18 @@ err_addr:
pci_epc_mem_free_addr(epc, phys_addr, src_addr, reg->size);
err:
- return ret;
+ if (!ret)
+ reg->status |= STATUS_READ_SUCCESS;
+ else
+ reg->status |= STATUS_READ_FAIL;
}
-static int pci_epf_test_write(struct pci_epf_test *epf_test)
+static void pci_epf_test_write(struct pci_epf_test *epf_test,
+ struct pci_epf_test_reg *reg)
{
int ret;
void __iomem *dst_addr;
void *buf;
- bool use_dma;
phys_addr_t phys_addr;
phys_addr_t src_phys_addr;
struct timespec64 start, end;
@@ -511,8 +506,6 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test)
struct device *dev = &epf->dev;
struct pci_epc *epc = epf->epc;
struct device *dma_dev = epf->epc->dev.parent;
- enum pci_barno test_reg_bar = epf_test->test_reg_bar;
- struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
dst_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
if (!dst_addr) {
@@ -539,14 +532,7 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test)
get_random_bytes(buf, reg->size);
reg->checksum = crc32_le(~0, buf, reg->size);
- use_dma = !!(reg->flags & FLAG_USE_DMA);
- if (use_dma) {
- if (!epf_test->dma_supported) {
- dev_err(dev, "Cannot transfer data using DMA\n");
- ret = -EINVAL;
- goto err_dma_map;
- }
-
+ if (reg->flags & FLAG_USE_DMA) {
src_phys_addr = dma_map_single(dma_dev, buf, reg->size,
DMA_TO_DEVICE);
if (dma_mapping_error(dma_dev, src_phys_addr)) {
@@ -573,7 +559,8 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test)
ktime_get_ts64(&end);
}
- pci_epf_test_print_rate("WRITE", reg->size, &start, &end, use_dma);
+ pci_epf_test_print_rate(epf_test, "WRITE", reg->size, &start, &end,
+ reg->flags & FLAG_USE_DMA);
/*
* wait 1ms inorder for the write to complete. Without this delay L3
@@ -591,32 +578,51 @@ err_addr:
pci_epc_mem_free_addr(epc, phys_addr, dst_addr, reg->size);
err:
- return ret;
+ if (!ret)
+ reg->status |= STATUS_WRITE_SUCCESS;
+ else
+ reg->status |= STATUS_WRITE_FAIL;
}
-static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, u8 irq_type,
- u16 irq)
+static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test,
+ struct pci_epf_test_reg *reg)
{
struct pci_epf *epf = epf_test->epf;
struct device *dev = &epf->dev;
struct pci_epc *epc = epf->epc;
- enum pci_barno test_reg_bar = epf_test->test_reg_bar;
- struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
+ u32 status = reg->status | STATUS_IRQ_RAISED;
+ int count;
- reg->status |= STATUS_IRQ_RAISED;
+ /*
+ * Set the status before raising the IRQ to ensure that the host sees
+ * the updated value when it gets the IRQ.
+ */
+ WRITE_ONCE(reg->status, status);
- switch (irq_type) {
+ switch (reg->irq_type) {
case IRQ_TYPE_LEGACY:
pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no,
PCI_EPC_IRQ_LEGACY, 0);
break;
case IRQ_TYPE_MSI:
+ count = pci_epc_get_msi(epc, epf->func_no, epf->vfunc_no);
+ if (reg->irq_number > count || count <= 0) {
+ dev_err(dev, "Invalid MSI IRQ number %d / %d\n",
+ reg->irq_number, count);
+ return;
+ }
pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no,
- PCI_EPC_IRQ_MSI, irq);
+ PCI_EPC_IRQ_MSI, reg->irq_number);
break;
case IRQ_TYPE_MSIX:
+ count = pci_epc_get_msix(epc, epf->func_no, epf->vfunc_no);
+ if (reg->irq_number > count || count <= 0) {
+ dev_err(dev, "Invalid MSIX IRQ number %d / %d\n",
+ reg->irq_number, count);
+ return;
+ }
pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no,
- PCI_EPC_IRQ_MSIX, irq);
+ PCI_EPC_IRQ_MSIX, reg->irq_number);
break;
default:
dev_err(dev, "Failed to raise IRQ, unknown type\n");
@@ -626,87 +632,53 @@ static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, u8 irq_type,
static void pci_epf_test_cmd_handler(struct work_struct *work)
{
- int ret;
- int count;
u32 command;
struct pci_epf_test *epf_test = container_of(work, struct pci_epf_test,
cmd_handler.work);
struct pci_epf *epf = epf_test->epf;
struct device *dev = &epf->dev;
- struct pci_epc *epc = epf->epc;
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
- command = reg->command;
+ command = READ_ONCE(reg->command);
if (!command)
goto reset_handler;
- reg->command = 0;
- reg->status = 0;
+ WRITE_ONCE(reg->command, 0);
+ WRITE_ONCE(reg->status, 0);
- if (reg->irq_type > IRQ_TYPE_MSIX) {
- dev_err(dev, "Failed to detect IRQ type\n");
+ if ((READ_ONCE(reg->flags) & FLAG_USE_DMA) &&
+ !epf_test->dma_supported) {
+ dev_err(dev, "Cannot transfer data using DMA\n");
goto reset_handler;
}
- if (command & COMMAND_RAISE_LEGACY_IRQ) {
- reg->status = STATUS_IRQ_RAISED;
- pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no,
- PCI_EPC_IRQ_LEGACY, 0);
- goto reset_handler;
- }
-
- if (command & COMMAND_WRITE) {
- ret = pci_epf_test_write(epf_test);
- if (ret)
- reg->status |= STATUS_WRITE_FAIL;
- else
- reg->status |= STATUS_WRITE_SUCCESS;
- pci_epf_test_raise_irq(epf_test, reg->irq_type,
- reg->irq_number);
- goto reset_handler;
- }
-
- if (command & COMMAND_READ) {
- ret = pci_epf_test_read(epf_test);
- if (!ret)
- reg->status |= STATUS_READ_SUCCESS;
- else
- reg->status |= STATUS_READ_FAIL;
- pci_epf_test_raise_irq(epf_test, reg->irq_type,
- reg->irq_number);
- goto reset_handler;
- }
-
- if (command & COMMAND_COPY) {
- ret = pci_epf_test_copy(epf_test);
- if (!ret)
- reg->status |= STATUS_COPY_SUCCESS;
- else
- reg->status |= STATUS_COPY_FAIL;
- pci_epf_test_raise_irq(epf_test, reg->irq_type,
- reg->irq_number);
- goto reset_handler;
- }
-
- if (command & COMMAND_RAISE_MSI_IRQ) {
- count = pci_epc_get_msi(epc, epf->func_no, epf->vfunc_no);
- if (reg->irq_number > count || count <= 0)
- goto reset_handler;
- reg->status = STATUS_IRQ_RAISED;
- pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no,
- PCI_EPC_IRQ_MSI, reg->irq_number);
+ if (reg->irq_type > IRQ_TYPE_MSIX) {
+ dev_err(dev, "Failed to detect IRQ type\n");
goto reset_handler;
}
- if (command & COMMAND_RAISE_MSIX_IRQ) {
- count = pci_epc_get_msix(epc, epf->func_no, epf->vfunc_no);
- if (reg->irq_number > count || count <= 0)
- goto reset_handler;
- reg->status = STATUS_IRQ_RAISED;
- pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no,
- PCI_EPC_IRQ_MSIX, reg->irq_number);
- goto reset_handler;
+ switch (command) {
+ case COMMAND_RAISE_LEGACY_IRQ:
+ case COMMAND_RAISE_MSI_IRQ:
+ case COMMAND_RAISE_MSIX_IRQ:
+ pci_epf_test_raise_irq(epf_test, reg);
+ break;
+ case COMMAND_WRITE:
+ pci_epf_test_write(epf_test, reg);
+ pci_epf_test_raise_irq(epf_test, reg);
+ break;
+ case COMMAND_READ:
+ pci_epf_test_read(epf_test, reg);
+ pci_epf_test_raise_irq(epf_test, reg);
+ break;
+ case COMMAND_COPY:
+ pci_epf_test_copy(epf_test, reg);
+ pci_epf_test_raise_irq(epf_test, reg);
+ break;
+ default:
+ dev_err(dev, "Invalid command 0x%x\n", command);
+ break;
}
reset_handler:
@@ -980,7 +952,8 @@ static const struct pci_epf_device_id pci_epf_test_ids[] = {
{},
};
-static int pci_epf_test_probe(struct pci_epf *epf)
+static int pci_epf_test_probe(struct pci_epf *epf,
+ const struct pci_epf_device_id *id)
{
struct pci_epf_test *epf_test;
struct device *dev = &epf->dev;
diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
index b7c7a8af99f4..0f5c8f8be847 100644
--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
+++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
@@ -84,15 +84,15 @@ enum epf_ntb_bar {
* | |
* | |
* | |
- * +-----------------------+--------------------------+ Base+span_offset
+ * +-----------------------+--------------------------+ Base+spad_offset
* | | |
- * | Peer Span Space | Span Space |
+ * | Peer Spad Space | Spad Space |
* | | |
* | | |
- * +-----------------------+--------------------------+ Base+span_offset
- * | | | +span_count * 4
+ * +-----------------------+--------------------------+ Base+spad_offset
+ * | | | +spad_count * 4
* | | |
- * | Span Space | Peer Span Space |
+ * | Spad Space | Peer Spad Space |
* | | |
* +-----------------------+--------------------------+
* Virtual PCI PCIe Endpoint
@@ -1395,13 +1395,15 @@ static struct pci_epf_ops epf_ntb_ops = {
/**
* epf_ntb_probe() - Probe NTB function driver
* @epf: NTB endpoint function device
+ * @id: NTB endpoint function device ID
*
* Probe NTB function driver when endpoint function bus detects a NTB
* endpoint function.
*
* Returns: Zero for success, or an error code in case of failure
*/
-static int epf_ntb_probe(struct pci_epf *epf)
+static int epf_ntb_probe(struct pci_epf *epf,
+ const struct pci_epf_device_id *id)
{
struct epf_ntb *ntb;
struct device *dev;
diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c
index 4b8ac0ac84d5..0ea64e24ed61 100644
--- a/drivers/pci/endpoint/pci-ep-cfs.c
+++ b/drivers/pci/endpoint/pci-ep-cfs.c
@@ -23,6 +23,7 @@ struct pci_epf_group {
struct config_group group;
struct config_group primary_epc_group;
struct config_group secondary_epc_group;
+ struct config_group *type_group;
struct delayed_work cfs_work;
struct pci_epf *epf;
int index;
@@ -178,6 +179,9 @@ static ssize_t pci_epc_start_store(struct config_item *item, const char *page,
if (kstrtobool(page, &start) < 0)
return -EINVAL;
+ if (start == epc_group->start)
+ return -EALREADY;
+
if (!start) {
pci_epc_stop(epc);
epc_group->start = 0;
@@ -502,33 +506,64 @@ static struct configfs_item_operations pci_epf_ops = {
.release = pci_epf_release,
};
-static struct config_group *pci_epf_type_make(struct config_group *group,
- const char *name)
+static const struct config_item_type pci_epf_type = {
+ .ct_item_ops = &pci_epf_ops,
+ .ct_attrs = pci_epf_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+/**
+ * pci_epf_type_add_cfs() - Help function drivers to expose function specific
+ * attributes in configfs
+ * @epf: the EPF device that has to be configured using configfs
+ * @group: the parent configfs group (corresponding to entries in
+ * pci_epf_device_id)
+ *
+ * Invoke to expose function specific attributes in configfs.
+ *
+ * Return: A pointer to a config_group structure or NULL if the function driver
+ * does not have anything to expose (attributes configured by user) or if
+ * the function driver does not implement the add_cfs() method.
+ *
+ * Returns an error pointer if this function is called for an unbound EPF device
+ * or if the EPF driver add_cfs() method fails.
+ */
+static struct config_group *pci_epf_type_add_cfs(struct pci_epf *epf,
+ struct config_group *group)
{
- struct pci_epf_group *epf_group = to_pci_epf_group(&group->cg_item);
struct config_group *epf_type_group;
- epf_type_group = pci_epf_type_add_cfs(epf_group->epf, group);
+ if (!epf->driver) {
+ dev_err(&epf->dev, "epf device not bound to driver\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ if (!epf->driver->ops->add_cfs)
+ return NULL;
+
+ mutex_lock(&epf->lock);
+ epf_type_group = epf->driver->ops->add_cfs(epf, group);
+ mutex_unlock(&epf->lock);
+
return epf_type_group;
}
-static void pci_epf_type_drop(struct config_group *group,
- struct config_item *item)
+static void pci_ep_cfs_add_type_group(struct pci_epf_group *epf_group)
{
- config_item_put(item);
-}
+ struct config_group *group;
-static struct configfs_group_operations pci_epf_type_group_ops = {
- .make_group = &pci_epf_type_make,
- .drop_item = &pci_epf_type_drop,
-};
+ group = pci_epf_type_add_cfs(epf_group->epf, &epf_group->group);
+ if (!group)
+ return;
-static const struct config_item_type pci_epf_type = {
- .ct_group_ops = &pci_epf_type_group_ops,
- .ct_item_ops = &pci_epf_ops,
- .ct_attrs = pci_epf_attrs,
- .ct_owner = THIS_MODULE,
-};
+ if (IS_ERR(group)) {
+ dev_err(&epf_group->epf->dev,
+ "failed to create epf type specific attributes\n");
+ return;
+ }
+
+ configfs_register_group(&epf_group->group, group);
+}
static void pci_epf_cfs_work(struct work_struct *work)
{
@@ -547,6 +582,8 @@ static void pci_epf_cfs_work(struct work_struct *work)
pr_err("failed to create 'secondary' EPC interface\n");
return;
}
+
+ pci_ep_cfs_add_type_group(epf_group);
}
static struct config_group *pci_epf_make(struct config_group *group,
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
index 46c9a5c3ca14..6c54fa5684d2 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -213,7 +213,7 @@ EXPORT_SYMBOL_GPL(pci_epc_start);
* @func_no: the physical endpoint function number in the EPC device
* @vfunc_no: the virtual endpoint function number in the physical function
* @type: specify the type of interrupt; legacy, MSI or MSI-X
- * @interrupt_num: the MSI or MSI-X interrupt number
+ * @interrupt_num: the MSI or MSI-X interrupt number with range (1-N)
*
* Invoke to raise an legacy, MSI or MSI-X interrupt
*/
@@ -246,7 +246,7 @@ EXPORT_SYMBOL_GPL(pci_epc_raise_irq);
* @func_no: the physical endpoint function number in the EPC device
* @vfunc_no: the virtual endpoint function number in the physical function
* @phys_addr: the physical address of the outbound region
- * @interrupt_num: the MSI interrupt number
+ * @interrupt_num: the MSI interrupt number with range (1-N)
* @entry_size: Size of Outbound address region for each interrupt
* @msi_data: the data that should be written in order to raise MSI interrupt
* with interrupt number as 'interrupt num'
@@ -707,6 +707,32 @@ void pci_epc_linkup(struct pci_epc *epc)
EXPORT_SYMBOL_GPL(pci_epc_linkup);
/**
+ * pci_epc_linkdown() - Notify the EPF device that EPC device has dropped the
+ * connection with the Root Complex.
+ * @epc: the EPC device which has dropped the link with the host
+ *
+ * Invoke to Notify the EPF device that the EPC device has dropped the
+ * connection with the Root Complex.
+ */
+void pci_epc_linkdown(struct pci_epc *epc)
+{
+ struct pci_epf *epf;
+
+ if (!epc || IS_ERR(epc))
+ return;
+
+ mutex_lock(&epc->list_lock);
+ list_for_each_entry(epf, &epc->pci_epf, list) {
+ mutex_lock(&epf->lock);
+ if (epf->event_ops && epf->event_ops->link_down)
+ epf->event_ops->link_down(epf);
+ mutex_unlock(&epf->lock);
+ }
+ mutex_unlock(&epc->list_lock);
+}
+EXPORT_SYMBOL_GPL(pci_epc_linkdown);
+
+/**
* pci_epc_init_notify() - Notify the EPF device that EPC device's core
* initialization is completed.
* @epc: the EPC device whose core initialization is completed
@@ -733,6 +759,32 @@ void pci_epc_init_notify(struct pci_epc *epc)
EXPORT_SYMBOL_GPL(pci_epc_init_notify);
/**
+ * pci_epc_bme_notify() - Notify the EPF device that the EPC device has received
+ * the BME event from the Root complex
+ * @epc: the EPC device that received the BME event
+ *
+ * Invoke to Notify the EPF device that the EPC device has received the Bus
+ * Master Enable (BME) event from the Root complex
+ */
+void pci_epc_bme_notify(struct pci_epc *epc)
+{
+ struct pci_epf *epf;
+
+ if (!epc || IS_ERR(epc))
+ return;
+
+ mutex_lock(&epc->list_lock);
+ list_for_each_entry(epf, &epc->pci_epf, list) {
+ mutex_lock(&epf->lock);
+ if (epf->event_ops && epf->event_ops->bme)
+ epf->event_ops->bme(epf);
+ mutex_unlock(&epf->lock);
+ }
+ mutex_unlock(&epc->list_lock);
+}
+EXPORT_SYMBOL_GPL(pci_epc_bme_notify);
+
+/**
* pci_epc_destroy() - destroy the EPC device
* @epc: the EPC device that has to be destroyed
*
diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c
index 2036e38be093..2c32de667937 100644
--- a/drivers/pci/endpoint/pci-epf-core.c
+++ b/drivers/pci/endpoint/pci-epf-core.c
@@ -21,38 +21,6 @@ static struct bus_type pci_epf_bus_type;
static const struct device_type pci_epf_type;
/**
- * pci_epf_type_add_cfs() - Help function drivers to expose function specific
- * attributes in configfs
- * @epf: the EPF device that has to be configured using configfs
- * @group: the parent configfs group (corresponding to entries in
- * pci_epf_device_id)
- *
- * Invoke to expose function specific attributes in configfs. If the function
- * driver does not have anything to expose (attributes configured by user),
- * return NULL.
- */
-struct config_group *pci_epf_type_add_cfs(struct pci_epf *epf,
- struct config_group *group)
-{
- struct config_group *epf_type_group;
-
- if (!epf->driver) {
- dev_err(&epf->dev, "epf device not bound to driver\n");
- return NULL;
- }
-
- if (!epf->driver->ops->add_cfs)
- return NULL;
-
- mutex_lock(&epf->lock);
- epf_type_group = epf->driver->ops->add_cfs(epf, group);
- mutex_unlock(&epf->lock);
-
- return epf_type_group;
-}
-EXPORT_SYMBOL_GPL(pci_epf_type_add_cfs);
-
-/**
* pci_epf_unbind() - Notify the function driver that the binding between the
* EPF device and EPC device has been lost
* @epf: the EPF device which has lost the binding with the EPC device
@@ -493,16 +461,16 @@ static const struct device_type pci_epf_type = {
.release = pci_epf_dev_release,
};
-static int
+static const struct pci_epf_device_id *
pci_epf_match_id(const struct pci_epf_device_id *id, const struct pci_epf *epf)
{
while (id->name[0]) {
if (strcmp(epf->name, id->name) == 0)
- return true;
+ return id;
id++;
}
- return false;
+ return NULL;
}
static int pci_epf_device_match(struct device *dev, struct device_driver *drv)
@@ -511,7 +479,7 @@ static int pci_epf_device_match(struct device *dev, struct device_driver *drv)
struct pci_epf_driver *driver = to_pci_epf_driver(drv);
if (driver->id_table)
- return pci_epf_match_id(driver->id_table, epf);
+ return !!pci_epf_match_id(driver->id_table, epf);
return !strcmp(epf->name, drv->name);
}
@@ -526,7 +494,7 @@ static int pci_epf_device_probe(struct device *dev)
epf->driver = driver;
- return driver->probe(epf);
+ return driver->probe(epf, pci_epf_match_id(driver->id_table, epf));
}
static void pci_epf_device_remove(struct device *dev)
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 5b1f271c6034..328d1e416014 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -498,7 +498,6 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge)
acpiphp_native_scan_bridge(dev);
}
} else {
- LIST_HEAD(add_list);
int max, pass;
acpiphp_rescan_slot(slot);
@@ -512,12 +511,10 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge)
if (pass && dev->subordinate) {
check_hotplug_bridge(slot, dev);
pcibios_resource_survey_bus(dev->subordinate);
- __pci_bus_size_bridges(dev->subordinate,
- &add_list);
}
}
}
- __pci_bus_assign_resources(bus, &add_list, NULL);
+ pci_assign_unassigned_bridge_resources(bus->self);
}
acpiphp_sanitize_bus(bus);
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 529c34808440..dcdbfcf404dd 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -166,11 +166,11 @@ void pciehp_handle_button_press(struct controller *ctrl)
case ON_STATE:
if (ctrl->state == ON_STATE) {
ctrl->state = BLINKINGOFF_STATE;
- ctrl_info(ctrl, "Slot(%s): Powering off due to button press\n",
+ ctrl_info(ctrl, "Slot(%s): Button press: will power off in 5 sec\n",
slot_name(ctrl));
} else {
ctrl->state = BLINKINGON_STATE;
- ctrl_info(ctrl, "Slot(%s) Powering on due to button press\n",
+ ctrl_info(ctrl, "Slot(%s): Button press: will power on in 5 sec\n",
slot_name(ctrl));
}
/* blink power indicator and turn off attention */
@@ -185,22 +185,23 @@ void pciehp_handle_button_press(struct controller *ctrl)
* press the attention again before the 5 sec. limit
* expires to cancel hot-add or hot-remove
*/
- ctrl_info(ctrl, "Slot(%s): Button cancel\n", slot_name(ctrl));
cancel_delayed_work(&ctrl->button_work);
if (ctrl->state == BLINKINGOFF_STATE) {
ctrl->state = ON_STATE;
pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON,
PCI_EXP_SLTCTL_ATTN_IND_OFF);
+ ctrl_info(ctrl, "Slot(%s): Button press: canceling request to power off\n",
+ slot_name(ctrl));
} else {
ctrl->state = OFF_STATE;
pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
PCI_EXP_SLTCTL_ATTN_IND_OFF);
+ ctrl_info(ctrl, "Slot(%s): Button press: canceling request to power on\n",
+ slot_name(ctrl));
}
- ctrl_info(ctrl, "Slot(%s): Action canceled due to button press\n",
- slot_name(ctrl));
break;
default:
- ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n",
+ ctrl_err(ctrl, "Slot(%s): Button press: ignoring invalid state %#x\n",
slot_name(ctrl), ctrl->state);
break;
}
@@ -256,6 +257,14 @@ void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events)
present = pciehp_card_present(ctrl);
link_active = pciehp_check_link_active(ctrl);
if (present <= 0 && link_active <= 0) {
+ if (ctrl->state == BLINKINGON_STATE) {
+ ctrl->state = OFF_STATE;
+ cancel_delayed_work(&ctrl->button_work);
+ pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
+ INDICATOR_NOOP);
+ ctrl_info(ctrl, "Slot(%s): Card not present\n",
+ slot_name(ctrl));
+ }
mutex_unlock(&ctrl->state_lock);
return;
}
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index f8c70115b691..8711325605f0 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -722,11 +722,8 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id)
}
/* Check Attention Button Pressed */
- if (events & PCI_EXP_SLTSTA_ABP) {
- ctrl_info(ctrl, "Slot(%s): Attention button pressed\n",
- slot_name(ctrl));
+ if (events & PCI_EXP_SLTSTA_ABP)
pciehp_handle_button_press(ctrl);
- }
/* Check Power Fault Detected */
if (events & PCI_EXP_SLTSTA_PFD) {
@@ -984,7 +981,7 @@ static inline int pcie_hotplug_depth(struct pci_dev *dev)
struct controller *pcie_init(struct pcie_device *dev)
{
struct controller *ctrl;
- u32 slot_cap, slot_cap2, link_cap;
+ u32 slot_cap, slot_cap2;
u8 poweron;
struct pci_dev *pdev = dev->port;
struct pci_bus *subordinate = pdev->subordinate;
@@ -1030,9 +1027,6 @@ struct controller *pcie_init(struct pcie_device *dev)
if (dmi_first_match(inband_presence_disabled_dmi_table))
ctrl->inband_presence_disabled = 1;
- /* Check if Data Link Layer Link Active Reporting is implemented */
- pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap);
-
/* Clear all remaining event bits in Slot Status register. */
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
@@ -1051,7 +1045,7 @@ struct controller *pcie_init(struct pcie_device *dev)
FLAG(slot_cap, PCI_EXP_SLTCAP_EIP),
FLAG(slot_cap, PCI_EXP_SLTCAP_NCCS),
FLAG(slot_cap2, PCI_EXP_SLTCAP2_IBPD),
- FLAG(link_cap, PCI_EXP_LNKCAP_DLLLARC),
+ FLAG(pdev->link_active_reporting, true),
pdev->broken_cmd_compl ? " (with Cmd Compl erratum)" : "");
/*
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index 2c25f4fa0225..e51219f9f523 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -39,16 +39,14 @@ int pci_set_of_node(struct pci_dev *dev)
return -ENODEV;
}
- dev->dev.of_node = node;
- dev->dev.fwnode = &node->fwnode;
+ device_set_node(&dev->dev, of_fwnode_handle(node));
return 0;
}
void pci_release_of_node(struct pci_dev *dev)
{
of_node_put(dev->dev.of_node);
- dev->dev.of_node = NULL;
- dev->dev.fwnode = NULL;
+ device_set_node(&dev->dev, NULL);
}
void pci_set_bus_of_node(struct pci_bus *bus)
@@ -63,17 +61,13 @@ void pci_set_bus_of_node(struct pci_bus *bus)
bus->self->external_facing = true;
}
- bus->dev.of_node = node;
-
- if (bus->dev.of_node)
- bus->dev.fwnode = &bus->dev.of_node->fwnode;
+ device_set_node(&bus->dev, of_fwnode_handle(node));
}
void pci_release_bus_of_node(struct pci_bus *bus)
{
of_node_put(bus->dev.of_node);
- bus->dev.of_node = NULL;
- bus->dev.fwnode = NULL;
+ device_set_node(&bus->dev, NULL);
}
struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 052a611081ec..a05350a4e49c 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -1043,6 +1043,16 @@ bool acpi_pci_bridge_d3(struct pci_dev *dev)
return false;
}
+static void acpi_pci_config_space_access(struct pci_dev *dev, bool enable)
+{
+ int val = enable ? ACPI_REG_CONNECT : ACPI_REG_DISCONNECT;
+ int ret = acpi_evaluate_reg(ACPI_HANDLE(&dev->dev),
+ ACPI_ADR_SPACE_PCI_CONFIG, val);
+ if (ret)
+ pci_dbg(dev, "ACPI _REG %s evaluation failed (%d)\n",
+ enable ? "connect" : "disconnect", ret);
+}
+
int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
{
struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
@@ -1053,32 +1063,49 @@ int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
[PCI_D3hot] = ACPI_STATE_D3_HOT,
[PCI_D3cold] = ACPI_STATE_D3_COLD,
};
- int error = -EINVAL;
+ int error;
/* If the ACPI device has _EJ0, ignore the device */
if (!adev || acpi_has_method(adev->handle, "_EJ0"))
return -ENODEV;
switch (state) {
- case PCI_D3cold:
- if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
- PM_QOS_FLAGS_ALL) {
- error = -EBUSY;
- break;
- }
- fallthrough;
case PCI_D0:
case PCI_D1:
case PCI_D2:
case PCI_D3hot:
- error = acpi_device_set_power(adev, state_conv[state]);
+ case PCI_D3cold:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (state == PCI_D3cold) {
+ if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
+ PM_QOS_FLAGS_ALL)
+ return -EBUSY;
+
+ /* Notify AML lack of PCI config space availability */
+ acpi_pci_config_space_access(dev, false);
}
- if (!error)
- pci_dbg(dev, "power state changed by ACPI to %s\n",
- acpi_power_state_string(adev->power.state));
+ error = acpi_device_set_power(adev, state_conv[state]);
+ if (error)
+ return error;
- return error;
+ pci_dbg(dev, "power state changed by ACPI to %s\n",
+ acpi_power_state_string(adev->power.state));
+
+ /*
+ * Notify AML of PCI config space availability. Config space is
+ * accessible in all states except D3cold; the only transitions
+ * that change availability are transitions to D3cold and from
+ * D3cold to D0.
+ */
+ if (state == PCI_D0)
+ acpi_pci_config_space_access(dev, true);
+
+ return 0;
}
pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 5ede93222bc1..60230da957e0 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -65,6 +65,13 @@ struct pci_pme_device {
#define PME_TIMEOUT 1000 /* How long between PME checks */
/*
+ * Following exit from Conventional Reset, devices must be ready within 1 sec
+ * (PCIe r6.0 sec 6.6.1). A D3cold to D0 transition implies a Conventional
+ * Reset (PCIe r6.0 sec 5.8).
+ */
+#define PCI_RESET_WAIT 1000 /* msec */
+
+/*
* Devices may extend the 1 sec period through Request Retry Status
* completions (PCIe r6.0 sec 2.3.1). The spec does not provide an upper
* limit, but 60 sec ought to be enough for any device to become
@@ -1156,7 +1163,14 @@ void pci_resume_bus(struct pci_bus *bus)
static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
{
int delay = 1;
- u32 id;
+ bool retrain = false;
+ struct pci_dev *bridge;
+
+ if (pci_is_pcie(dev)) {
+ bridge = pci_upstream_bridge(dev);
+ if (bridge)
+ retrain = true;
+ }
/*
* After reset, the device should not silently discard config
@@ -1170,21 +1184,33 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
* Command register instead of Vendor ID so we don't have to
* contend with the CRS SV value.
*/
- pci_read_config_dword(dev, PCI_COMMAND, &id);
- while (PCI_POSSIBLE_ERROR(id)) {
+ for (;;) {
+ u32 id;
+
+ pci_read_config_dword(dev, PCI_COMMAND, &id);
+ if (!PCI_POSSIBLE_ERROR(id))
+ break;
+
if (delay > timeout) {
pci_warn(dev, "not ready %dms after %s; giving up\n",
delay - 1, reset_type);
return -ENOTTY;
}
- if (delay > PCI_RESET_WAIT)
+ if (delay > PCI_RESET_WAIT) {
+ if (retrain) {
+ retrain = false;
+ if (pcie_failed_link_retrain(bridge)) {
+ delay = 1;
+ continue;
+ }
+ }
pci_info(dev, "not ready %dms after %s; waiting\n",
delay - 1, reset_type);
+ }
msleep(delay);
delay *= 2;
- pci_read_config_dword(dev, PCI_COMMAND, &id);
}
if (delay > PCI_RESET_WAIT)
@@ -2949,13 +2975,13 @@ static const struct dmi_system_id bridge_d3_blacklist[] = {
{
/*
* Downstream device is not accessible after putting a root port
- * into D3cold and back into D0 on Elo i2.
+ * into D3cold and back into D0 on Elo Continental Z2 board
*/
- .ident = "Elo i2",
+ .ident = "Elo Continental Z2",
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Elo Touch Solutions"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Elo i2"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "RevB"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "Elo Touch Solutions"),
+ DMI_MATCH(DMI_BOARD_NAME, "Geminilake"),
+ DMI_MATCH(DMI_BOARD_VERSION, "Continental Z2"),
},
},
#endif
@@ -4857,6 +4883,79 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe)
}
/**
+ * pcie_wait_for_link_status - Wait for link status change
+ * @pdev: Device whose link to wait for.
+ * @use_lt: Use the LT bit if TRUE, or the DLLLA bit if FALSE.
+ * @active: Waiting for active or inactive?
+ *
+ * Return 0 if successful, or -ETIMEDOUT if status has not changed within
+ * PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds.
+ */
+static int pcie_wait_for_link_status(struct pci_dev *pdev,
+ bool use_lt, bool active)
+{
+ u16 lnksta_mask, lnksta_match;
+ unsigned long end_jiffies;
+ u16 lnksta;
+
+ lnksta_mask = use_lt ? PCI_EXP_LNKSTA_LT : PCI_EXP_LNKSTA_DLLLA;
+ lnksta_match = active ? lnksta_mask : 0;
+
+ end_jiffies = jiffies + msecs_to_jiffies(PCIE_LINK_RETRAIN_TIMEOUT_MS);
+ do {
+ pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta);
+ if ((lnksta & lnksta_mask) == lnksta_match)
+ return 0;
+ msleep(1);
+ } while (time_before(jiffies, end_jiffies));
+
+ return -ETIMEDOUT;
+}
+
+/**
+ * pcie_retrain_link - Request a link retrain and wait for it to complete
+ * @pdev: Device whose link to retrain.
+ * @use_lt: Use the LT bit if TRUE, or the DLLLA bit if FALSE, for status.
+ *
+ * Retrain completion status is retrieved from the Link Status Register
+ * according to @use_lt. It is not verified whether the use of the DLLLA
+ * bit is valid.
+ *
+ * Return 0 if successful, or -ETIMEDOUT if training has not completed
+ * within PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds.
+ */
+int pcie_retrain_link(struct pci_dev *pdev, bool use_lt)
+{
+ int rc;
+ u16 lnkctl;
+
+ /*
+ * Ensure the updated LNKCTL parameters are used during link
+ * training by checking that there is no ongoing link training to
+ * avoid LTSSM race as recommended in Implementation Note at the
+ * end of PCIe r6.0.1 sec 7.5.3.7.
+ */
+ rc = pcie_wait_for_link_status(pdev, use_lt, !use_lt);
+ if (rc)
+ return rc;
+
+ pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnkctl);
+ lnkctl |= PCI_EXP_LNKCTL_RL;
+ pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl);
+ if (pdev->clear_retrain_link) {
+ /*
+ * Due to an erratum in some devices the Retrain Link bit
+ * needs to be cleared again manually to allow the link
+ * training to succeed.
+ */
+ lnkctl &= ~PCI_EXP_LNKCTL_RL;
+ pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl);
+ }
+
+ return pcie_wait_for_link_status(pdev, use_lt, !use_lt);
+}
+
+/**
* pcie_wait_for_link_delay - Wait until link is active or inactive
* @pdev: Bridge device
* @active: waiting for active or inactive?
@@ -4867,16 +4966,14 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe)
static bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active,
int delay)
{
- int timeout = 1000;
- bool ret;
- u16 lnk_status;
+ int rc;
/*
* Some controllers might not implement link active reporting. In this
* case, we wait for 1000 ms + any delay requested by the caller.
*/
if (!pdev->link_active_reporting) {
- msleep(timeout + delay);
+ msleep(PCIE_LINK_RETRAIN_TIMEOUT_MS + delay);
return true;
}
@@ -4891,20 +4988,21 @@ static bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active,
*/
if (active)
msleep(20);
- for (;;) {
- pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
- ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
- if (ret == active)
- break;
- if (timeout <= 0)
- break;
- msleep(10);
- timeout -= 10;
- }
- if (active && ret)
+ rc = pcie_wait_for_link_status(pdev, false, active);
+ if (active) {
+ if (rc)
+ rc = pcie_failed_link_retrain(pdev);
+ if (rc)
+ return false;
+
msleep(delay);
+ return true;
+ }
+
+ if (rc)
+ return false;
- return ret == active;
+ return true;
}
/**
@@ -5011,11 +5109,9 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
*
* However, 100 ms is the minimum and the PCIe spec says the
* software must allow at least 1s before it can determine that the
- * device that did not respond is a broken device. There is
- * evidence that 100 ms is not always enough, for example certain
- * Titan Ridge xHCI controller does not always respond to
- * configuration requests if we only wait for 100 ms (see
- * https://bugzilla.kernel.org/show_bug.cgi?id=203885).
+ * device that did not respond is a broken device. Also device can
+ * take longer than that to respond if it indicates so through Request
+ * Retry Status completions.
*
* Therefore we wait for 100 ms and check for the device presence
* until the timeout expires.
@@ -5024,16 +5120,36 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
return 0;
if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) {
+ u16 status;
+
pci_dbg(dev, "waiting %d ms for downstream link\n", delay);
msleep(delay);
- } else {
- pci_dbg(dev, "waiting %d ms for downstream link, after activation\n",
- delay);
- if (!pcie_wait_for_link_delay(dev, true, delay)) {
- /* Did not train, no need to wait any further */
- pci_info(dev, "Data Link Layer Link Active not set in 1000 msec\n");
+
+ if (!pci_dev_wait(child, reset_type, PCI_RESET_WAIT - delay))
+ return 0;
+
+ /*
+ * If the port supports active link reporting we now check
+ * whether the link is active and if not bail out early with
+ * the assumption that the device is not present anymore.
+ */
+ if (!dev->link_active_reporting)
return -ENOTTY;
- }
+
+ pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &status);
+ if (!(status & PCI_EXP_LNKSTA_DLLLA))
+ return -ENOTTY;
+
+ return pci_dev_wait(child, reset_type,
+ PCIE_RESET_READY_POLL_MS - PCI_RESET_WAIT);
+ }
+
+ pci_dbg(dev, "waiting %d ms for downstream link, after activation\n",
+ delay);
+ if (!pcie_wait_for_link_delay(dev, true, delay)) {
+ /* Did not train, no need to wait any further */
+ pci_info(dev, "Data Link Layer Link Active not set in 1000 msec\n");
+ return -ENOTTY;
}
return pci_dev_wait(child, reset_type,
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 2475098f6518..a4c397434057 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -11,6 +11,8 @@
#define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */
+#define PCIE_LINK_RETRAIN_TIMEOUT_MS 1000
+
extern const unsigned char pcie_link_speed[];
extern bool pci_early_dump;
@@ -64,13 +66,6 @@ struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev,
#define PCI_PM_D3HOT_WAIT 10 /* msec */
#define PCI_PM_D3COLD_WAIT 100 /* msec */
-/*
- * Following exit from Conventional Reset, devices must be ready within 1 sec
- * (PCIe r6.0 sec 6.6.1). A D3cold to D0 transition implies a Conventional
- * Reset (PCIe r6.0 sec 5.8).
- */
-#define PCI_RESET_WAIT 1000 /* msec */
-
void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
void pci_refresh_power_state(struct pci_dev *dev);
int pci_power_up(struct pci_dev *dev);
@@ -541,6 +536,7 @@ void pci_acs_init(struct pci_dev *dev);
int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags);
int pci_dev_specific_enable_acs(struct pci_dev *dev);
int pci_dev_specific_disable_acs_redir(struct pci_dev *dev);
+bool pcie_failed_link_retrain(struct pci_dev *dev);
#else
static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev,
u16 acs_flags)
@@ -555,6 +551,10 @@ static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev)
{
return -ENOTTY;
}
+static inline bool pcie_failed_link_retrain(struct pci_dev *dev)
+{
+ return false;
+}
#endif
/* PCI error reporting and recovery */
@@ -563,6 +563,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev));
bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
+int pcie_retrain_link(struct pci_dev *pdev, bool use_lt);
#ifdef CONFIG_PCIEASPM
void pcie_aspm_init_link_state(struct pci_dev *pdev);
void pcie_aspm_exit_link_state(struct pci_dev *pdev);
@@ -686,6 +687,8 @@ extern const struct attribute_group aer_stats_attr_group;
void pci_aer_clear_fatal_status(struct pci_dev *dev);
int pci_aer_clear_status(struct pci_dev *dev);
int pci_aer_raw_clear_status(struct pci_dev *dev);
+void pci_save_aer_state(struct pci_dev *dev);
+void pci_restore_aer_state(struct pci_dev *dev);
#else
static inline void pci_no_aer(void) { }
static inline void pci_aer_init(struct pci_dev *d) { }
@@ -693,6 +696,8 @@ static inline void pci_aer_exit(struct pci_dev *d) { }
static inline void pci_aer_clear_fatal_status(struct pci_dev *dev) { }
static inline int pci_aer_clear_status(struct pci_dev *dev) { return -EINVAL; }
static inline int pci_aer_raw_clear_status(struct pci_dev *dev) { return -EINVAL; }
+static inline void pci_save_aer_state(struct pci_dev *dev) { }
+static inline void pci_restore_aer_state(struct pci_dev *dev) { }
#endif
#ifdef CONFIG_ACPI
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 66d7514ca111..3dafba0b5f41 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -90,8 +90,6 @@ static const char *policy_str[] = {
[POLICY_POWER_SUPERSAVE] = "powersupersave"
};
-#define LINK_RETRAIN_TIMEOUT HZ
-
/*
* The L1 PM substate capability is only implemented in function 0 in a
* multi function device.
@@ -193,36 +191,6 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
link->clkpm_disable = blacklist ? 1 : 0;
}
-static bool pcie_retrain_link(struct pcie_link_state *link)
-{
- struct pci_dev *parent = link->pdev;
- unsigned long end_jiffies;
- u16 reg16;
-
- pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &reg16);
- reg16 |= PCI_EXP_LNKCTL_RL;
- pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
- if (parent->clear_retrain_link) {
- /*
- * Due to an erratum in some devices the Retrain Link bit
- * needs to be cleared again manually to allow the link
- * training to succeed.
- */
- reg16 &= ~PCI_EXP_LNKCTL_RL;
- pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
- }
-
- /* Wait for link training end. Break out after waiting for timeout */
- end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT;
- do {
- pcie_capability_read_word(parent, PCI_EXP_LNKSTA, &reg16);
- if (!(reg16 & PCI_EXP_LNKSTA_LT))
- break;
- msleep(1);
- } while (time_before(jiffies, end_jiffies));
- return !(reg16 & PCI_EXP_LNKSTA_LT);
-}
-
/*
* pcie_aspm_configure_common_clock: check if the 2 ends of a link
* could use common clock. If they are, configure them to use the
@@ -289,15 +257,15 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
reg16 &= ~PCI_EXP_LNKCTL_CCC;
pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
- if (pcie_retrain_link(link))
- return;
+ if (pcie_retrain_link(link->pdev, true)) {
- /* Training failed. Restore common clock configurations */
- pci_err(parent, "ASPM: Could not configure common clock\n");
- list_for_each_entry(child, &linkbus->devices, bus_list)
- pcie_capability_write_word(child, PCI_EXP_LNKCTL,
+ /* Training failed. Restore common clock configurations */
+ pci_err(parent, "ASPM: Could not configure common clock\n");
+ list_for_each_entry(child, &linkbus->devices, bus_list)
+ pcie_capability_write_word(child, PCI_EXP_LNKCTL,
child_reg[PCI_FUNC(child->devfn)]);
- pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg);
+ pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg);
+ }
}
/* Convert L0s latency encoding to ns */
@@ -337,7 +305,7 @@ static u32 calc_l1_acceptable(u32 encoding)
}
/* Convert L1SS T_pwr encoding to usec */
-static u32 calc_l1ss_pwron(struct pci_dev *pdev, u32 scale, u32 val)
+static u32 calc_l12_pwron(struct pci_dev *pdev, u32 scale, u32 val)
{
switch (scale) {
case 0:
@@ -471,7 +439,7 @@ static void pci_clear_and_set_dword(struct pci_dev *pdev, int pos,
}
/* Calculate L1.2 PM substate timing parameters */
-static void aspm_calc_l1ss_info(struct pcie_link_state *link,
+static void aspm_calc_l12_info(struct pcie_link_state *link,
u32 parent_l1ss_cap, u32 child_l1ss_cap)
{
struct pci_dev *child = link->downstream, *parent = link->pdev;
@@ -481,9 +449,6 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link,
u32 pctl1, pctl2, cctl1, cctl2;
u32 pl1_2_enables, cl1_2_enables;
- if (!(link->aspm_support & ASPM_STATE_L1_2_MASK))
- return;
-
/* Choose the greater of the two Port Common_Mode_Restore_Times */
val1 = (parent_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8;
val2 = (child_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8;
@@ -495,13 +460,13 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link,
val2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19;
scale2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16;
- if (calc_l1ss_pwron(parent, scale1, val1) >
- calc_l1ss_pwron(child, scale2, val2)) {
+ if (calc_l12_pwron(parent, scale1, val1) >
+ calc_l12_pwron(child, scale2, val2)) {
ctl2 |= scale1 | (val1 << 3);
- t_power_on = calc_l1ss_pwron(parent, scale1, val1);
+ t_power_on = calc_l12_pwron(parent, scale1, val1);
} else {
ctl2 |= scale2 | (val2 << 3);
- t_power_on = calc_l1ss_pwron(child, scale2, val2);
+ t_power_on = calc_l12_pwron(child, scale2, val2);
}
/*
@@ -616,8 +581,8 @@ static void aspm_l1ss_init(struct pcie_link_state *link)
if (parent_l1ss_ctl1 & child_l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_2)
link->aspm_enabled |= ASPM_STATE_L1_2_PCIPM;
- if (link->aspm_support & ASPM_STATE_L1SS)
- aspm_calc_l1ss_info(link, parent_l1ss_cap, child_l1ss_cap);
+ if (link->aspm_support & ASPM_STATE_L1_2_MASK)
+ aspm_calc_l12_info(link, parent_l1ss_cap, child_l1ss_cap);
}
static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
@@ -1010,21 +975,24 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
down_read(&pci_bus_sem);
mutex_lock(&aspm_lock);
- /*
- * All PCIe functions are in one slot, remove one function will remove
- * the whole slot, so just wait until we are the last function left.
- */
- if (!list_empty(&parent->subordinate->devices))
- goto out;
link = parent->link_state;
root = link->root;
parent_link = link->parent;
- /* All functions are removed, so just disable ASPM for the link */
+ /*
+ * link->downstream is a pointer to the pci_dev of function 0. If
+ * we remove that function, the pci_dev is about to be deallocated,
+ * so we can't use link->downstream again. Free the link state to
+ * avoid this.
+ *
+ * If we're removing a non-0 function, it's possible we could
+ * retain the link state, but PCIe r6.0, sec 7.5.3.7, recommends
+ * programming the same ASPM Control value for all functions of
+ * multi-function devices, so disable ASPM for all of them.
+ */
pcie_config_aspm_link(link, 0);
list_del(&link->sibling);
- /* Clock PM is for endpoint device */
free_link_state(link);
/* Recheck latencies and configure upstream links */
@@ -1032,7 +1000,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
pcie_update_aspm_capable(root);
pcie_config_aspm_path(parent_link);
}
-out:
+
mutex_unlock(&aspm_lock);
up_read(&pci_bus_sem);
}
@@ -1095,8 +1063,7 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
if (state & PCIE_LINK_STATE_L0S)
link->aspm_disable |= ASPM_STATE_L0S;
if (state & PCIE_LINK_STATE_L1)
- /* L1 PM substates require L1 */
- link->aspm_disable |= ASPM_STATE_L1 | ASPM_STATE_L1SS;
+ link->aspm_disable |= ASPM_STATE_L1;
if (state & PCIE_LINK_STATE_L1_1)
link->aspm_disable |= ASPM_STATE_L1_1;
if (state & PCIE_LINK_STATE_L1_2)
@@ -1171,16 +1138,16 @@ int pci_enable_link_state(struct pci_dev *pdev, int state)
if (state & PCIE_LINK_STATE_L0S)
link->aspm_default |= ASPM_STATE_L0S;
if (state & PCIE_LINK_STATE_L1)
- /* L1 PM substates require L1 */
- link->aspm_default |= ASPM_STATE_L1 | ASPM_STATE_L1SS;
+ link->aspm_default |= ASPM_STATE_L1;
+ /* L1 PM substates require L1 */
if (state & PCIE_LINK_STATE_L1_1)
- link->aspm_default |= ASPM_STATE_L1_1;
+ link->aspm_default |= ASPM_STATE_L1_1 | ASPM_STATE_L1;
if (state & PCIE_LINK_STATE_L1_2)
- link->aspm_default |= ASPM_STATE_L1_2;
+ link->aspm_default |= ASPM_STATE_L1_2 | ASPM_STATE_L1;
if (state & PCIE_LINK_STATE_L1_1_PCIPM)
- link->aspm_default |= ASPM_STATE_L1_1_PCIPM;
+ link->aspm_default |= ASPM_STATE_L1_1_PCIPM | ASPM_STATE_L1;
if (state & PCIE_LINK_STATE_L1_2_PCIPM)
- link->aspm_default |= ASPM_STATE_L1_2_PCIPM;
+ link->aspm_default |= ASPM_STATE_L1_2_PCIPM | ASPM_STATE_L1;
pcie_config_aspm_link(link, policy_to_aspm_state(link));
link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 0b2826c4a832..8bac3ce02609 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -820,7 +820,6 @@ static void pci_set_bus_speed(struct pci_bus *bus)
pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap);
bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS];
- bridge->link_active_reporting = !!(linkcap & PCI_EXP_LNKCAP_DLLLARC);
pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta);
pcie_update_link_speed(bus, linksta);
@@ -997,8 +996,10 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
resource_list_for_each_entry_safe(window, n, &resources) {
offset = window->offset;
res = window->res;
- if (!res->flags && !res->start && !res->end)
+ if (!res->flags && !res->start && !res->end) {
+ release_resource(res);
continue;
+ }
list_move_tail(&window->node, &bridge->windows);
@@ -1527,6 +1528,7 @@ void set_pcie_port_type(struct pci_dev *pdev)
{
int pos;
u16 reg16;
+ u32 reg32;
int type;
struct pci_dev *parent;
@@ -1540,6 +1542,10 @@ void set_pcie_port_type(struct pci_dev *pdev)
pci_read_config_dword(pdev, pos + PCI_EXP_DEVCAP, &pdev->devcap);
pdev->pcie_mpss = FIELD_GET(PCI_EXP_DEVCAP_PAYLOAD, pdev->devcap);
+ pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &reg32);
+ if (reg32 & PCI_EXP_LNKCAP_DLLLARC)
+ pdev->link_active_reporting = 1;
+
parent = pci_upstream_bridge(pdev);
if (!parent)
return;
@@ -2546,6 +2552,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
dma_set_max_seg_size(&dev->dev, 65536);
dma_set_seg_boundary(&dev->dev, 0xffffffff);
+ pcie_failed_link_retrain(dev);
+
/* Fix up broken headers */
pci_fixup_device(pci_fixup_header, dev);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index c525867760bf..321156ca273d 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -33,6 +33,99 @@
#include <linux/switchtec.h>
#include "pci.h"
+/*
+ * Retrain the link of a downstream PCIe port by hand if necessary.
+ *
+ * This is needed at least where a downstream port of the ASMedia ASM2824
+ * Gen 3 switch is wired to the upstream port of the Pericom PI7C9X2G304
+ * Gen 2 switch, and observed with the Delock Riser Card PCI Express x1 >
+ * 2 x PCIe x1 device, P/N 41433, plugged into the SiFive HiFive Unmatched
+ * board.
+ *
+ * In such a configuration the switches are supposed to negotiate the link
+ * speed of preferably 5.0GT/s, falling back to 2.5GT/s. However the link
+ * continues switching between the two speeds indefinitely and the data
+ * link layer never reaches the active state, with link training reported
+ * repeatedly active ~84% of the time. Forcing the target link speed to
+ * 2.5GT/s with the upstream ASM2824 device makes the two switches talk to
+ * each other correctly however. And more interestingly retraining with a
+ * higher target link speed afterwards lets the two successfully negotiate
+ * 5.0GT/s.
+ *
+ * With the ASM2824 we can rely on the otherwise optional Data Link Layer
+ * Link Active status bit and in the failed link training scenario it will
+ * be off along with the Link Bandwidth Management Status indicating that
+ * hardware has changed the link speed or width in an attempt to correct
+ * unreliable link operation. For a port that has been left unconnected
+ * both bits will be clear. So use this information to detect the problem
+ * rather than polling the Link Training bit and watching out for flips or
+ * at least the active status.
+ *
+ * Since the exact nature of the problem isn't known and in principle this
+ * could trigger where an ASM2824 device is downstream rather upstream,
+ * apply this erratum workaround to any downstream ports as long as they
+ * support Link Active reporting and have the Link Control 2 register.
+ * Restrict the speed to 2.5GT/s then with the Target Link Speed field,
+ * request a retrain and wait 200ms for the data link to go up.
+ *
+ * If this turns out successful and we know by the Vendor:Device ID it is
+ * safe to do so, then lift the restriction, letting the devices negotiate
+ * a higher speed. Also check for a similar 2.5GT/s speed restriction the
+ * firmware may have already arranged and lift it with ports that already
+ * report their data link being up.
+ *
+ * Return TRUE if the link has been successfully retrained, otherwise FALSE.
+ */
+bool pcie_failed_link_retrain(struct pci_dev *dev)
+{
+ static const struct pci_device_id ids[] = {
+ { PCI_VDEVICE(ASMEDIA, 0x2824) }, /* ASMedia ASM2824 */
+ {}
+ };
+ u16 lnksta, lnkctl2;
+
+ if (!pci_is_pcie(dev) || !pcie_downstream_port(dev) ||
+ !pcie_cap_has_lnkctl2(dev) || !dev->link_active_reporting)
+ return false;
+
+ pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2);
+ pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
+ if ((lnksta & (PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_DLLLA)) ==
+ PCI_EXP_LNKSTA_LBMS) {
+ pci_info(dev, "broken device, retraining non-functional downstream link at 2.5GT/s\n");
+
+ lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS;
+ lnkctl2 |= PCI_EXP_LNKCTL2_TLS_2_5GT;
+ pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, lnkctl2);
+
+ if (pcie_retrain_link(dev, false)) {
+ pci_info(dev, "retraining failed\n");
+ return false;
+ }
+
+ pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
+ }
+
+ if ((lnksta & PCI_EXP_LNKSTA_DLLLA) &&
+ (lnkctl2 & PCI_EXP_LNKCTL2_TLS) == PCI_EXP_LNKCTL2_TLS_2_5GT &&
+ pci_match_id(ids, dev)) {
+ u32 lnkcap;
+
+ pci_info(dev, "removing 2.5GT/s downstream link speed restriction\n");
+ pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
+ lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS;
+ lnkctl2 |= lnkcap & PCI_EXP_LNKCAP_SLS;
+ pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, lnkctl2);
+
+ if (pcie_retrain_link(dev, false)) {
+ pci_info(dev, "retraining failed\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
static ktime_t fixup_debug_start(struct pci_dev *dev,
void (*fn)(struct pci_dev *dev))
{
@@ -2420,9 +2513,9 @@ static void quirk_enable_clear_retrain_link(struct pci_dev *dev)
dev->clear_retrain_link = 1;
pci_info(dev, "Enable PCIe Retrain Link quirk\n");
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, 0xe110, quirk_enable_clear_retrain_link);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, 0xe111, quirk_enable_clear_retrain_link);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, 0xe130, quirk_enable_clear_retrain_link);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PERICOM, 0xe110, quirk_enable_clear_retrain_link);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PERICOM, 0xe111, quirk_enable_clear_retrain_link);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PERICOM, 0xe130, quirk_enable_clear_retrain_link);
static void fixup_rev1_53c810(struct pci_dev *dev)
{
@@ -3993,10 +4086,11 @@ static int nvme_disable_and_flr(struct pci_dev *dev, bool probe)
}
/*
- * Intel DC P3700 NVMe controller will timeout waiting for ready status
- * to change after NVMe enable if the driver starts interacting with the
- * device too soon after FLR. A 250ms delay after FLR has heuristically
- * proven to produce reliably working results for device assignment cases.
+ * Some NVMe controllers such as Intel DC P3700 and Solidigm P44 Pro will
+ * timeout waiting for ready status to change after NVMe enable if the driver
+ * starts interacting with the device too soon after FLR. A 250ms delay after
+ * FLR has heuristically proven to produce reliably working results for device
+ * assignment cases.
*/
static int delay_250ms_after_flr(struct pci_dev *dev, bool probe)
{
@@ -4083,6 +4177,7 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
{ PCI_VENDOR_ID_SAMSUNG, 0xa804, nvme_disable_and_flr },
{ PCI_VENDOR_ID_INTEL, 0x0953, delay_250ms_after_flr },
{ PCI_VENDOR_ID_INTEL, 0x0a54, delay_250ms_after_flr },
+ { PCI_VENDOR_ID_SOLIDIGM, 0xf1ac, delay_250ms_after_flr },
{ PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
reset_chelsio_generic_dev },
{ PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_HINIC_VF,
@@ -4174,6 +4269,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9220,
/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c49 */
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9230,
quirk_dma_func1_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9235,
+ quirk_dma_func1_alias);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0642,
quirk_dma_func1_alias);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0645,
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 44c16508ef14..e72419d7e72e 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -5,7 +5,6 @@
menuconfig PCCARD
tristate "PCCard (PCMCIA/CardBus) support"
- depends on !UML
help
Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
computer. These are credit-card size devices such as network cards,
@@ -113,7 +112,7 @@ config YENTA_TOSHIBA
config PD6729
tristate "Cirrus PD6729 compatible bridge support"
- depends on PCMCIA && PCI
+ depends on PCMCIA && PCI && HAS_IOPORT
select PCCARD_NONSTATIC
help
This provides support for the Cirrus PD6729 PCI-to-PCMCIA bridge
@@ -121,7 +120,7 @@ config PD6729
config I82092
tristate "i82092 compatible bridge support"
- depends on PCMCIA && PCI
+ depends on PCMCIA && PCI && HAS_IOPORT
select PCCARD_NONSTATIC
help
This provides support for the Intel I82092AA PCI-to-PCMCIA bridge device,
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 471e0c5815f3..bf9d070a4496 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -1053,6 +1053,8 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
q = p->next;
kfree(p);
}
+
+ kfree(data);
}
diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 4c07d71cab0b..f4572a5cca72 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -221,4 +221,17 @@ source "drivers/perf/arm_cspmu/Kconfig"
source "drivers/perf/amlogic/Kconfig"
+config CXL_PMU
+ tristate "CXL Performance Monitoring Unit"
+ depends on CXL_BUS
+ help
+ Support performance monitoring as defined in CXL rev 3.0
+ section 13.2: Performance Monitoring. CXL components may have
+ one or more CXL Performance Monitoring Units (CPMUs).
+
+ Say 'y/m' to enable a driver that will attach to performance
+ monitoring units and provide standard perf based interfaces.
+
+ If unsure say 'm'.
+
endmenu
diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile
index 5cfe8954c250..16b3ec4db916 100644
--- a/drivers/perf/Makefile
+++ b/drivers/perf/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_APPLE_M1_CPU_PMU) += apple_m1_cpu_pmu.o
obj-$(CONFIG_ALIBABA_UNCORE_DRW_PMU) += alibaba_uncore_drw_pmu.o
obj-$(CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU) += arm_cspmu/
obj-$(CONFIG_MESON_DDR_PMU) += amlogic/
+obj-$(CONFIG_CXL_PMU) += cxl_pmu.o
diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c
new file mode 100644
index 000000000000..0a8f597e695b
--- /dev/null
+++ b/drivers/perf/cxl_pmu.c
@@ -0,0 +1,990 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright(c) 2023 Huawei
+ *
+ * The CXL 3.0 specification includes a standard Performance Monitoring Unit,
+ * called the CXL PMU, or CPMU. In order to allow a high degree of
+ * implementation flexibility the specification provides a wide range of
+ * options all of which are self describing.
+ *
+ * Details in CXL rev 3.0 section 8.2.7 CPMU Register Interface
+ */
+
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/perf_event.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/bits.h>
+#include <linux/list.h>
+#include <linux/bug.h>
+#include <linux/pci.h>
+
+#include "../cxl/cxlpci.h"
+#include "../cxl/cxl.h"
+#include "../cxl/pmu.h"
+
+#define CXL_PMU_CAP_REG 0x0
+#define CXL_PMU_CAP_NUM_COUNTERS_MSK GENMASK_ULL(4, 0)
+#define CXL_PMU_CAP_COUNTER_WIDTH_MSK GENMASK_ULL(15, 8)
+#define CXL_PMU_CAP_NUM_EVN_CAP_REG_SUP_MSK GENMASK_ULL(24, 20)
+#define CXL_PMU_CAP_FILTERS_SUP_MSK GENMASK_ULL(39, 32)
+#define CXL_PMU_FILTER_HDM BIT(0)
+#define CXL_PMU_FILTER_CHAN_RANK_BANK BIT(1)
+#define CXL_PMU_CAP_MSI_N_MSK GENMASK_ULL(47, 44)
+#define CXL_PMU_CAP_WRITEABLE_WHEN_FROZEN BIT_ULL(48)
+#define CXL_PMU_CAP_FREEZE BIT_ULL(49)
+#define CXL_PMU_CAP_INT BIT_ULL(50)
+#define CXL_PMU_CAP_VERSION_MSK GENMASK_ULL(63, 60)
+
+#define CXL_PMU_OVERFLOW_REG 0x10
+#define CXL_PMU_FREEZE_REG 0x18
+#define CXL_PMU_EVENT_CAP_REG(n) (0x100 + 8 * (n))
+#define CXL_PMU_EVENT_CAP_SUPPORTED_EVENTS_MSK GENMASK_ULL(31, 0)
+#define CXL_PMU_EVENT_CAP_GROUP_ID_MSK GENMASK_ULL(47, 32)
+#define CXL_PMU_EVENT_CAP_VENDOR_ID_MSK GENMASK_ULL(63, 48)
+
+#define CXL_PMU_COUNTER_CFG_REG(n) (0x200 + 8 * (n))
+#define CXL_PMU_COUNTER_CFG_TYPE_MSK GENMASK_ULL(1, 0)
+#define CXL_PMU_COUNTER_CFG_TYPE_FREE_RUN 0
+#define CXL_PMU_COUNTER_CFG_TYPE_FIXED_FUN 1
+#define CXL_PMU_COUNTER_CFG_TYPE_CONFIGURABLE 2
+#define CXL_PMU_COUNTER_CFG_ENABLE BIT_ULL(8)
+#define CXL_PMU_COUNTER_CFG_INT_ON_OVRFLW BIT_ULL(9)
+#define CXL_PMU_COUNTER_CFG_FREEZE_ON_OVRFLW BIT_ULL(10)
+#define CXL_PMU_COUNTER_CFG_EDGE BIT_ULL(11)
+#define CXL_PMU_COUNTER_CFG_INVERT BIT_ULL(12)
+#define CXL_PMU_COUNTER_CFG_THRESHOLD_MSK GENMASK_ULL(23, 16)
+#define CXL_PMU_COUNTER_CFG_EVENTS_MSK GENMASK_ULL(55, 24)
+#define CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK GENMASK_ULL(63, 59)
+
+#define CXL_PMU_FILTER_CFG_REG(n, f) (0x400 + 4 * ((f) + (n) * 8))
+#define CXL_PMU_FILTER_CFG_VALUE_MSK GENMASK(15, 0)
+
+#define CXL_PMU_COUNTER_REG(n) (0xc00 + 8 * (n))
+
+/* CXL rev 3.0 Table 13-5 Events under CXL Vendor ID */
+#define CXL_PMU_GID_CLOCK_TICKS 0x00
+#define CXL_PMU_GID_D2H_REQ 0x0010
+#define CXL_PMU_GID_D2H_RSP 0x0011
+#define CXL_PMU_GID_H2D_REQ 0x0012
+#define CXL_PMU_GID_H2D_RSP 0x0013
+#define CXL_PMU_GID_CACHE_DATA 0x0014
+#define CXL_PMU_GID_M2S_REQ 0x0020
+#define CXL_PMU_GID_M2S_RWD 0x0021
+#define CXL_PMU_GID_M2S_BIRSP 0x0022
+#define CXL_PMU_GID_S2M_BISNP 0x0023
+#define CXL_PMU_GID_S2M_NDR 0x0024
+#define CXL_PMU_GID_S2M_DRS 0x0025
+#define CXL_PMU_GID_DDR 0x8000
+
+static int cxl_pmu_cpuhp_state_num;
+
+struct cxl_pmu_ev_cap {
+ u16 vid;
+ u16 gid;
+ u32 msk;
+ union {
+ int counter_idx; /* fixed counters */
+ int event_idx; /* configurable counters */
+ };
+ struct list_head node;
+};
+
+#define CXL_PMU_MAX_COUNTERS 64
+struct cxl_pmu_info {
+ struct pmu pmu;
+ void __iomem *base;
+ struct perf_event **hw_events;
+ struct list_head event_caps_configurable;
+ struct list_head event_caps_fixed;
+ DECLARE_BITMAP(used_counter_bm, CXL_PMU_MAX_COUNTERS);
+ DECLARE_BITMAP(conf_counter_bm, CXL_PMU_MAX_COUNTERS);
+ u16 counter_width;
+ u8 num_counters;
+ u8 num_event_capabilities;
+ int on_cpu;
+ struct hlist_node node;
+ bool filter_hdm;
+ int irq;
+};
+
+#define pmu_to_cxl_pmu_info(_pmu) container_of(_pmu, struct cxl_pmu_info, pmu)
+
+/*
+ * All CPMU counters are discoverable via the Event Capabilities Registers.
+ * Each Event Capability register contains a a VID / GroupID.
+ * A counter may then count any combination (by summing) of events in
+ * that group which are in the Supported Events Bitmask.
+ * However, there are some complexities to the scheme.
+ * - Fixed function counters refer to an Event Capabilities register.
+ * That event capability register is not then used for Configurable
+ * counters.
+ */
+static int cxl_pmu_parse_caps(struct device *dev, struct cxl_pmu_info *info)
+{
+ unsigned long fixed_counter_event_cap_bm = 0;
+ void __iomem *base = info->base;
+ bool freeze_for_enable;
+ u64 val, eval;
+ int i;
+
+ val = readq(base + CXL_PMU_CAP_REG);
+ freeze_for_enable = FIELD_GET(CXL_PMU_CAP_WRITEABLE_WHEN_FROZEN, val) &&
+ FIELD_GET(CXL_PMU_CAP_FREEZE, val);
+ if (!freeze_for_enable) {
+ dev_err(dev, "Counters not writable while frozen\n");
+ return -ENODEV;
+ }
+
+ info->num_counters = FIELD_GET(CXL_PMU_CAP_NUM_COUNTERS_MSK, val) + 1;
+ info->counter_width = FIELD_GET(CXL_PMU_CAP_COUNTER_WIDTH_MSK, val);
+ info->num_event_capabilities = FIELD_GET(CXL_PMU_CAP_NUM_EVN_CAP_REG_SUP_MSK, val) + 1;
+
+ info->filter_hdm = FIELD_GET(CXL_PMU_CAP_FILTERS_SUP_MSK, val) & CXL_PMU_FILTER_HDM;
+ if (FIELD_GET(CXL_PMU_CAP_INT, val))
+ info->irq = FIELD_GET(CXL_PMU_CAP_MSI_N_MSK, val);
+ else
+ info->irq = -1;
+
+ /* First handle fixed function counters; note if configurable counters found */
+ for (i = 0; i < info->num_counters; i++) {
+ struct cxl_pmu_ev_cap *pmu_ev;
+ u32 events_msk;
+ u8 group_idx;
+
+ val = readq(base + CXL_PMU_COUNTER_CFG_REG(i));
+
+ if (FIELD_GET(CXL_PMU_COUNTER_CFG_TYPE_MSK, val) ==
+ CXL_PMU_COUNTER_CFG_TYPE_CONFIGURABLE) {
+ set_bit(i, info->conf_counter_bm);
+ }
+
+ if (FIELD_GET(CXL_PMU_COUNTER_CFG_TYPE_MSK, val) !=
+ CXL_PMU_COUNTER_CFG_TYPE_FIXED_FUN)
+ continue;
+
+ /* In this case we know which fields are const */
+ group_idx = FIELD_GET(CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK, val);
+ events_msk = FIELD_GET(CXL_PMU_COUNTER_CFG_EVENTS_MSK, val);
+ eval = readq(base + CXL_PMU_EVENT_CAP_REG(group_idx));
+ pmu_ev = devm_kzalloc(dev, sizeof(*pmu_ev), GFP_KERNEL);
+ if (!pmu_ev)
+ return -ENOMEM;
+
+ pmu_ev->vid = FIELD_GET(CXL_PMU_EVENT_CAP_VENDOR_ID_MSK, eval);
+ pmu_ev->gid = FIELD_GET(CXL_PMU_EVENT_CAP_GROUP_ID_MSK, eval);
+ /* For a fixed purpose counter use the events mask from the counter CFG */
+ pmu_ev->msk = events_msk;
+ pmu_ev->counter_idx = i;
+ /* This list add is never unwound as all entries deleted on remove */
+ list_add(&pmu_ev->node, &info->event_caps_fixed);
+ /*
+ * Configurable counters must not use an Event Capability registers that
+ * is in use for a Fixed counter
+ */
+ set_bit(group_idx, &fixed_counter_event_cap_bm);
+ }
+
+ if (!bitmap_empty(info->conf_counter_bm, CXL_PMU_MAX_COUNTERS)) {
+ struct cxl_pmu_ev_cap *pmu_ev;
+ int j;
+ /* Walk event capabilities unused by fixed counters */
+ for_each_clear_bit(j, &fixed_counter_event_cap_bm,
+ info->num_event_capabilities) {
+ pmu_ev = devm_kzalloc(dev, sizeof(*pmu_ev), GFP_KERNEL);
+ if (!pmu_ev)
+ return -ENOMEM;
+
+ eval = readq(base + CXL_PMU_EVENT_CAP_REG(j));
+ pmu_ev->vid = FIELD_GET(CXL_PMU_EVENT_CAP_VENDOR_ID_MSK, eval);
+ pmu_ev->gid = FIELD_GET(CXL_PMU_EVENT_CAP_GROUP_ID_MSK, eval);
+ pmu_ev->msk = FIELD_GET(CXL_PMU_EVENT_CAP_SUPPORTED_EVENTS_MSK, eval);
+ pmu_ev->event_idx = j;
+ list_add(&pmu_ev->node, &info->event_caps_configurable);
+ }
+ }
+
+ return 0;
+}
+
+static ssize_t cxl_pmu_format_sysfs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dev_ext_attribute *eattr;
+
+ eattr = container_of(attr, struct dev_ext_attribute, attr);
+
+ return sysfs_emit(buf, "%s\n", (char *)eattr->var);
+}
+
+#define CXL_PMU_FORMAT_ATTR(_name, _format)\
+ (&((struct dev_ext_attribute[]) { \
+ { \
+ .attr = __ATTR(_name, 0444, \
+ cxl_pmu_format_sysfs_show, NULL), \
+ .var = (void *)_format \
+ } \
+ })[0].attr.attr)
+
+enum {
+ cxl_pmu_mask_attr,
+ cxl_pmu_gid_attr,
+ cxl_pmu_vid_attr,
+ cxl_pmu_threshold_attr,
+ cxl_pmu_invert_attr,
+ cxl_pmu_edge_attr,
+ cxl_pmu_hdm_filter_en_attr,
+ cxl_pmu_hdm_attr,
+};
+
+static struct attribute *cxl_pmu_format_attr[] = {
+ [cxl_pmu_mask_attr] = CXL_PMU_FORMAT_ATTR(mask, "config:0-31"),
+ [cxl_pmu_gid_attr] = CXL_PMU_FORMAT_ATTR(gid, "config:32-47"),
+ [cxl_pmu_vid_attr] = CXL_PMU_FORMAT_ATTR(vid, "config:48-63"),
+ [cxl_pmu_threshold_attr] = CXL_PMU_FORMAT_ATTR(threshold, "config1:0-15"),
+ [cxl_pmu_invert_attr] = CXL_PMU_FORMAT_ATTR(invert, "config1:16"),
+ [cxl_pmu_edge_attr] = CXL_PMU_FORMAT_ATTR(edge, "config1:17"),
+ [cxl_pmu_hdm_filter_en_attr] = CXL_PMU_FORMAT_ATTR(hdm_filter_en, "config1:18"),
+ [cxl_pmu_hdm_attr] = CXL_PMU_FORMAT_ATTR(hdm, "config2:0-15"),
+ NULL
+};
+
+#define CXL_PMU_ATTR_CONFIG_MASK_MSK GENMASK_ULL(31, 0)
+#define CXL_PMU_ATTR_CONFIG_GID_MSK GENMASK_ULL(47, 32)
+#define CXL_PMU_ATTR_CONFIG_VID_MSK GENMASK_ULL(63, 48)
+#define CXL_PMU_ATTR_CONFIG1_THRESHOLD_MSK GENMASK_ULL(15, 0)
+#define CXL_PMU_ATTR_CONFIG1_INVERT_MSK BIT(16)
+#define CXL_PMU_ATTR_CONFIG1_EDGE_MSK BIT(17)
+#define CXL_PMU_ATTR_CONFIG1_FILTER_EN_MSK BIT(18)
+#define CXL_PMU_ATTR_CONFIG2_HDM_MSK GENMASK(15, 0)
+
+static umode_t cxl_pmu_format_is_visible(struct kobject *kobj,
+ struct attribute *attr, int a)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct cxl_pmu_info *info = dev_get_drvdata(dev);
+
+ /*
+ * Filter capability at the CPMU level, so hide the attributes if the particular
+ * filter is not supported.
+ */
+ if (!info->filter_hdm &&
+ (attr == cxl_pmu_format_attr[cxl_pmu_hdm_filter_en_attr] ||
+ attr == cxl_pmu_format_attr[cxl_pmu_hdm_attr]))
+ return 0;
+
+ return attr->mode;
+}
+
+static const struct attribute_group cxl_pmu_format_group = {
+ .name = "format",
+ .attrs = cxl_pmu_format_attr,
+ .is_visible = cxl_pmu_format_is_visible,
+};
+
+static u32 cxl_pmu_config_get_mask(struct perf_event *event)
+{
+ return FIELD_GET(CXL_PMU_ATTR_CONFIG_MASK_MSK, event->attr.config);
+}
+
+static u16 cxl_pmu_config_get_gid(struct perf_event *event)
+{
+ return FIELD_GET(CXL_PMU_ATTR_CONFIG_GID_MSK, event->attr.config);
+}
+
+static u16 cxl_pmu_config_get_vid(struct perf_event *event)
+{
+ return FIELD_GET(CXL_PMU_ATTR_CONFIG_VID_MSK, event->attr.config);
+}
+
+static u8 cxl_pmu_config1_get_threshold(struct perf_event *event)
+{
+ return FIELD_GET(CXL_PMU_ATTR_CONFIG1_THRESHOLD_MSK, event->attr.config1);
+}
+
+static bool cxl_pmu_config1_get_invert(struct perf_event *event)
+{
+ return FIELD_GET(CXL_PMU_ATTR_CONFIG1_INVERT_MSK, event->attr.config1);
+}
+
+static bool cxl_pmu_config1_get_edge(struct perf_event *event)
+{
+ return FIELD_GET(CXL_PMU_ATTR_CONFIG1_EDGE_MSK, event->attr.config1);
+}
+
+/*
+ * CPMU specification allows for 8 filters, each with a 16 bit value...
+ * So we need to find 8x16bits to store it in.
+ * As the value used for disable is 0xffff, a separate enable switch
+ * is needed.
+ */
+
+static bool cxl_pmu_config1_hdm_filter_en(struct perf_event *event)
+{
+ return FIELD_GET(CXL_PMU_ATTR_CONFIG1_FILTER_EN_MSK, event->attr.config1);
+}
+
+static u16 cxl_pmu_config2_get_hdm_decoder(struct perf_event *event)
+{
+ return FIELD_GET(CXL_PMU_ATTR_CONFIG2_HDM_MSK, event->attr.config2);
+}
+
+static ssize_t cxl_pmu_event_sysfs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct perf_pmu_events_attr *pmu_attr =
+ container_of(attr, struct perf_pmu_events_attr, attr);
+
+ return sysfs_emit(buf, "config=%#llx\n", pmu_attr->id);
+}
+
+#define CXL_PMU_EVENT_ATTR(_name, _vid, _gid, _msk) \
+ PMU_EVENT_ATTR_ID(_name, cxl_pmu_event_sysfs_show, \
+ ((u64)(_vid) << 48) | ((u64)(_gid) << 32) | (u64)(_msk))
+
+/* For CXL spec defined events */
+#define CXL_PMU_EVENT_CXL_ATTR(_name, _gid, _msk) \
+ CXL_PMU_EVENT_ATTR(_name, PCI_DVSEC_VENDOR_ID_CXL, _gid, _msk)
+
+static struct attribute *cxl_pmu_event_attrs[] = {
+ CXL_PMU_EVENT_CXL_ATTR(clock_ticks, CXL_PMU_GID_CLOCK_TICKS, BIT(0)),
+ /* CXL rev 3.0 Table 3-17 - Device to Host Requests */
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdcurr, CXL_PMU_GID_D2H_REQ, BIT(1)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdown, CXL_PMU_GID_D2H_REQ, BIT(2)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdshared, CXL_PMU_GID_D2H_REQ, BIT(3)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdany, CXL_PMU_GID_D2H_REQ, BIT(4)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdownnodata, CXL_PMU_GID_D2H_REQ, BIT(5)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_itomwr, CXL_PMU_GID_D2H_REQ, BIT(6)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_wrcurr, CXL_PMU_GID_D2H_REQ, BIT(7)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_clflush, CXL_PMU_GID_D2H_REQ, BIT(8)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_cleanevict, CXL_PMU_GID_D2H_REQ, BIT(9)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_dirtyevict, CXL_PMU_GID_D2H_REQ, BIT(10)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_cleanevictnodata, CXL_PMU_GID_D2H_REQ, BIT(11)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_wowrinv, CXL_PMU_GID_D2H_REQ, BIT(12)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_wowrinvf, CXL_PMU_GID_D2H_REQ, BIT(13)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_wrinv, CXL_PMU_GID_D2H_REQ, BIT(14)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_req_cacheflushed, CXL_PMU_GID_D2H_REQ, BIT(16)),
+ /* CXL rev 3.0 Table 3-20 - D2H Repsonse Encodings */
+ CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspihiti, CXL_PMU_GID_D2H_RSP, BIT(4)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspvhitv, CXL_PMU_GID_D2H_RSP, BIT(6)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspihitse, CXL_PMU_GID_D2H_RSP, BIT(5)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspshitse, CXL_PMU_GID_D2H_RSP, BIT(1)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspsfwdm, CXL_PMU_GID_D2H_RSP, BIT(7)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspifwdm, CXL_PMU_GID_D2H_RSP, BIT(15)),
+ CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspvfwdv, CXL_PMU_GID_D2H_RSP, BIT(22)),
+ /* CXL rev 3.0 Table 3-21 - CXL.cache - Mapping of H2D Requests to D2H Responses */
+ CXL_PMU_EVENT_CXL_ATTR(h2d_req_snpdata, CXL_PMU_GID_H2D_REQ, BIT(1)),
+ CXL_PMU_EVENT_CXL_ATTR(h2d_req_snpinv, CXL_PMU_GID_H2D_REQ, BIT(2)),
+ CXL_PMU_EVENT_CXL_ATTR(h2d_req_snpcur, CXL_PMU_GID_H2D_REQ, BIT(3)),
+ /* CXL rev 3.0 Table 3-22 - H2D Response Opcode Encodings */
+ CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_writepull, CXL_PMU_GID_H2D_RSP, BIT(1)),
+ CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_go, CXL_PMU_GID_H2D_RSP, BIT(4)),
+ CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_gowritepull, CXL_PMU_GID_H2D_RSP, BIT(5)),
+ CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_extcmp, CXL_PMU_GID_H2D_RSP, BIT(6)),
+ CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_gowritepulldrop, CXL_PMU_GID_H2D_RSP, BIT(8)),
+ CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_fastgowritepull, CXL_PMU_GID_H2D_RSP, BIT(13)),
+ CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_goerrwritepull, CXL_PMU_GID_H2D_RSP, BIT(15)),
+ /* CXL rev 3.0 Table 13-5 directly lists these */
+ CXL_PMU_EVENT_CXL_ATTR(cachedata_d2h_data, CXL_PMU_GID_CACHE_DATA, BIT(0)),
+ CXL_PMU_EVENT_CXL_ATTR(cachedata_h2d_data, CXL_PMU_GID_CACHE_DATA, BIT(1)),
+ /* CXL rev 3.0 Table 3-29 M2S Req Memory Opcodes */
+ CXL_PMU_EVENT_CXL_ATTR(m2s_req_meminv, CXL_PMU_GID_M2S_REQ, BIT(0)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrd, CXL_PMU_GID_M2S_REQ, BIT(1)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrddata, CXL_PMU_GID_M2S_REQ, BIT(2)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrdfwd, CXL_PMU_GID_M2S_REQ, BIT(3)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_req_memwrfwd, CXL_PMU_GID_M2S_REQ, BIT(4)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_req_memspecrd, CXL_PMU_GID_M2S_REQ, BIT(8)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_req_meminvnt, CXL_PMU_GID_M2S_REQ, BIT(9)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_req_memcleanevict, CXL_PMU_GID_M2S_REQ, BIT(10)),
+ /* CXL rev 3.0 Table 3-35 M2S RwD Memory Opcodes */
+ CXL_PMU_EVENT_CXL_ATTR(m2s_rwd_memwr, CXL_PMU_GID_M2S_RWD, BIT(1)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_rwd_memwrptl, CXL_PMU_GID_M2S_RWD, BIT(2)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_rwd_biconflict, CXL_PMU_GID_M2S_RWD, BIT(4)),
+ /* CXL rev 3.0 Table 3-38 M2S BIRsp Memory Opcodes */
+ CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_i, CXL_PMU_GID_M2S_BIRSP, BIT(0)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_s, CXL_PMU_GID_M2S_BIRSP, BIT(1)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_e, CXL_PMU_GID_M2S_BIRSP, BIT(2)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_iblk, CXL_PMU_GID_M2S_BIRSP, BIT(4)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_sblk, CXL_PMU_GID_M2S_BIRSP, BIT(5)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_eblk, CXL_PMU_GID_M2S_BIRSP, BIT(6)),
+ /* CXL rev 3.0 Table 3-40 S2M BISnp Opcodes */
+ CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_cur, CXL_PMU_GID_S2M_BISNP, BIT(0)),
+ CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_data, CXL_PMU_GID_S2M_BISNP, BIT(1)),
+ CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_inv, CXL_PMU_GID_S2M_BISNP, BIT(2)),
+ CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_curblk, CXL_PMU_GID_S2M_BISNP, BIT(4)),
+ CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_datblk, CXL_PMU_GID_S2M_BISNP, BIT(5)),
+ CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_invblk, CXL_PMU_GID_S2M_BISNP, BIT(6)),
+ /* CXL rev 3.0 Table 3-43 S2M NDR Opcopdes */
+ CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmp, CXL_PMU_GID_S2M_NDR, BIT(0)),
+ CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmps, CXL_PMU_GID_S2M_NDR, BIT(1)),
+ CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmpe, CXL_PMU_GID_S2M_NDR, BIT(2)),
+ CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_biconflictack, CXL_PMU_GID_S2M_NDR, BIT(3)),
+ /* CXL rev 3.0 Table 3-46 S2M DRS opcodes */
+ CXL_PMU_EVENT_CXL_ATTR(s2m_drs_memdata, CXL_PMU_GID_S2M_DRS, BIT(0)),
+ CXL_PMU_EVENT_CXL_ATTR(s2m_drs_memdatanxm, CXL_PMU_GID_S2M_DRS, BIT(1)),
+ /* CXL rev 3.0 Table 13-5 directly lists these */
+ CXL_PMU_EVENT_CXL_ATTR(ddr_act, CXL_PMU_GID_DDR, BIT(0)),
+ CXL_PMU_EVENT_CXL_ATTR(ddr_pre, CXL_PMU_GID_DDR, BIT(1)),
+ CXL_PMU_EVENT_CXL_ATTR(ddr_casrd, CXL_PMU_GID_DDR, BIT(2)),
+ CXL_PMU_EVENT_CXL_ATTR(ddr_caswr, CXL_PMU_GID_DDR, BIT(3)),
+ CXL_PMU_EVENT_CXL_ATTR(ddr_refresh, CXL_PMU_GID_DDR, BIT(4)),
+ CXL_PMU_EVENT_CXL_ATTR(ddr_selfrefreshent, CXL_PMU_GID_DDR, BIT(5)),
+ CXL_PMU_EVENT_CXL_ATTR(ddr_rfm, CXL_PMU_GID_DDR, BIT(6)),
+ NULL
+};
+
+static struct cxl_pmu_ev_cap *cxl_pmu_find_fixed_counter_ev_cap(struct cxl_pmu_info *info,
+ int vid, int gid, int msk)
+{
+ struct cxl_pmu_ev_cap *pmu_ev;
+
+ list_for_each_entry(pmu_ev, &info->event_caps_fixed, node) {
+ if (vid != pmu_ev->vid || gid != pmu_ev->gid)
+ continue;
+
+ /* Precise match for fixed counter */
+ if (msk == pmu_ev->msk)
+ return pmu_ev;
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+static struct cxl_pmu_ev_cap *cxl_pmu_find_config_counter_ev_cap(struct cxl_pmu_info *info,
+ int vid, int gid, int msk)
+{
+ struct cxl_pmu_ev_cap *pmu_ev;
+
+ list_for_each_entry(pmu_ev, &info->event_caps_configurable, node) {
+ if (vid != pmu_ev->vid || gid != pmu_ev->gid)
+ continue;
+
+ /* Request mask must be subset of supported */
+ if (msk & ~pmu_ev->msk)
+ continue;
+
+ return pmu_ev;
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+static umode_t cxl_pmu_event_is_visible(struct kobject *kobj, struct attribute *attr, int a)
+{
+ struct device_attribute *dev_attr = container_of(attr, struct device_attribute, attr);
+ struct perf_pmu_events_attr *pmu_attr =
+ container_of(dev_attr, struct perf_pmu_events_attr, attr);
+ struct device *dev = kobj_to_dev(kobj);
+ struct cxl_pmu_info *info = dev_get_drvdata(dev);
+ int vid = FIELD_GET(CXL_PMU_ATTR_CONFIG_VID_MSK, pmu_attr->id);
+ int gid = FIELD_GET(CXL_PMU_ATTR_CONFIG_GID_MSK, pmu_attr->id);
+ int msk = FIELD_GET(CXL_PMU_ATTR_CONFIG_MASK_MSK, pmu_attr->id);
+
+ if (!IS_ERR(cxl_pmu_find_fixed_counter_ev_cap(info, vid, gid, msk)))
+ return attr->mode;
+
+ if (!IS_ERR(cxl_pmu_find_config_counter_ev_cap(info, vid, gid, msk)))
+ return attr->mode;
+
+ return 0;
+}
+
+static const struct attribute_group cxl_pmu_events = {
+ .name = "events",
+ .attrs = cxl_pmu_event_attrs,
+ .is_visible = cxl_pmu_event_is_visible,
+};
+
+static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct cxl_pmu_info *info = dev_get_drvdata(dev);
+
+ return cpumap_print_to_pagebuf(true, buf, cpumask_of(info->on_cpu));
+}
+static DEVICE_ATTR_RO(cpumask);
+
+static struct attribute *cxl_pmu_cpumask_attrs[] = {
+ &dev_attr_cpumask.attr,
+ NULL
+};
+
+static const struct attribute_group cxl_pmu_cpumask_group = {
+ .attrs = cxl_pmu_cpumask_attrs,
+};
+
+static const struct attribute_group *cxl_pmu_attr_groups[] = {
+ &cxl_pmu_events,
+ &cxl_pmu_format_group,
+ &cxl_pmu_cpumask_group,
+ NULL
+};
+
+/* If counter_idx == NULL, don't try to allocate a counter. */
+static int cxl_pmu_get_event_idx(struct perf_event *event, int *counter_idx,
+ int *event_idx)
+{
+ struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu);
+ DECLARE_BITMAP(configurable_and_free, CXL_PMU_MAX_COUNTERS);
+ struct cxl_pmu_ev_cap *pmu_ev;
+ u32 mask;
+ u16 gid, vid;
+ int i;
+
+ vid = cxl_pmu_config_get_vid(event);
+ gid = cxl_pmu_config_get_gid(event);
+ mask = cxl_pmu_config_get_mask(event);
+
+ pmu_ev = cxl_pmu_find_fixed_counter_ev_cap(info, vid, gid, mask);
+ if (!IS_ERR(pmu_ev)) {
+ if (!counter_idx)
+ return 0;
+ if (!test_bit(pmu_ev->counter_idx, info->used_counter_bm)) {
+ *counter_idx = pmu_ev->counter_idx;
+ return 0;
+ }
+ /* Fixed counter is in use, but maybe a configurable one? */
+ }
+
+ pmu_ev = cxl_pmu_find_config_counter_ev_cap(info, vid, gid, mask);
+ if (!IS_ERR(pmu_ev)) {
+ if (!counter_idx)
+ return 0;
+
+ bitmap_andnot(configurable_and_free, info->conf_counter_bm,
+ info->used_counter_bm, CXL_PMU_MAX_COUNTERS);
+
+ i = find_first_bit(configurable_and_free, CXL_PMU_MAX_COUNTERS);
+ if (i == CXL_PMU_MAX_COUNTERS)
+ return -EINVAL;
+
+ *counter_idx = i;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int cxl_pmu_event_init(struct perf_event *event)
+{
+ struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu);
+ int rc;
+
+ /* Top level type sanity check - is this a Hardware Event being requested */
+ if (event->attr.type != event->pmu->type)
+ return -ENOENT;
+
+ if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
+ return -EOPNOTSUPP;
+ /* TODO: Validation of any filter */
+
+ /*
+ * Verify that it is possible to count what was requested. Either must
+ * be a fixed counter that is a precise match or a configurable counter
+ * where this is a subset.
+ */
+ rc = cxl_pmu_get_event_idx(event, NULL, NULL);
+ if (rc < 0)
+ return rc;
+
+ event->cpu = info->on_cpu;
+
+ return 0;
+}
+
+static void cxl_pmu_enable(struct pmu *pmu)
+{
+ struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(pmu);
+ void __iomem *base = info->base;
+
+ /* Can assume frozen at this stage */
+ writeq(0, base + CXL_PMU_FREEZE_REG);
+}
+
+static void cxl_pmu_disable(struct pmu *pmu)
+{
+ struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(pmu);
+ void __iomem *base = info->base;
+
+ /*
+ * Whilst bits above number of counters are RsvdZ
+ * they are unlikely to be repurposed given
+ * number of counters is allowed to be 64 leaving
+ * no reserved bits. Hence this is only slightly
+ * naughty.
+ */
+ writeq(GENMASK_ULL(63, 0), base + CXL_PMU_FREEZE_REG);
+}
+
+static void cxl_pmu_event_start(struct perf_event *event, int flags)
+{
+ struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ void __iomem *base = info->base;
+ u64 cfg;
+
+ /*
+ * All paths to here should either set these flags directly or
+ * call cxl_pmu_event_stop() which will ensure the correct state.
+ */
+ if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
+ return;
+
+ WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+ hwc->state = 0;
+
+ /*
+ * Currently only hdm filter control is implemnted, this code will
+ * want generalizing when more filters are added.
+ */
+ if (info->filter_hdm) {
+ if (cxl_pmu_config1_hdm_filter_en(event))
+ cfg = cxl_pmu_config2_get_hdm_decoder(event);
+ else
+ cfg = GENMASK(15, 0); /* No filtering if 0xFFFF_FFFF */
+ writeq(cfg, base + CXL_PMU_FILTER_CFG_REG(hwc->idx, 0));
+ }
+
+ cfg = readq(base + CXL_PMU_COUNTER_CFG_REG(hwc->idx));
+ cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_INT_ON_OVRFLW, 1);
+ cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_FREEZE_ON_OVRFLW, 1);
+ cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_ENABLE, 1);
+ cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EDGE,
+ cxl_pmu_config1_get_edge(event) ? 1 : 0);
+ cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_INVERT,
+ cxl_pmu_config1_get_invert(event) ? 1 : 0);
+
+ /* Fixed purpose counters have next two fields RO */
+ if (test_bit(hwc->idx, info->conf_counter_bm)) {
+ cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK,
+ hwc->event_base);
+ cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EVENTS_MSK,
+ cxl_pmu_config_get_mask(event));
+ }
+ cfg &= ~CXL_PMU_COUNTER_CFG_THRESHOLD_MSK;
+ /*
+ * For events that generate only 1 count per clock the CXL 3.0 spec
+ * states the threshold shall be set to 1 but if set to 0 it will
+ * count the raw value anwyay?
+ * There is no definition of what events will count multiple per cycle
+ * and hence to which non 1 values of threshold can apply.
+ * (CXL 3.0 8.2.7.2.1 Counter Configuration - threshold field definition)
+ */
+ cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_THRESHOLD_MSK,
+ cxl_pmu_config1_get_threshold(event));
+ writeq(cfg, base + CXL_PMU_COUNTER_CFG_REG(hwc->idx));
+
+ local64_set(&hwc->prev_count, 0);
+ writeq(0, base + CXL_PMU_COUNTER_REG(hwc->idx));
+
+ perf_event_update_userpage(event);
+}
+
+static u64 cxl_pmu_read_counter(struct perf_event *event)
+{
+ struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu);
+ void __iomem *base = info->base;
+
+ return readq(base + CXL_PMU_COUNTER_REG(event->hw.idx));
+}
+
+static void __cxl_pmu_read(struct perf_event *event, bool overflow)
+{
+ struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ u64 new_cnt, prev_cnt, delta;
+
+ do {
+ prev_cnt = local64_read(&hwc->prev_count);
+ new_cnt = cxl_pmu_read_counter(event);
+ } while (local64_cmpxchg(&hwc->prev_count, prev_cnt, new_cnt) != prev_cnt);
+
+ /*
+ * If we know an overflow occur then take that into account.
+ * Note counter is not reset as that would lose events
+ */
+ delta = (new_cnt - prev_cnt) & GENMASK_ULL(info->counter_width - 1, 0);
+ if (overflow && delta < GENMASK_ULL(info->counter_width - 1, 0))
+ delta += (1UL << info->counter_width);
+
+ local64_add(delta, &event->count);
+}
+
+static void cxl_pmu_read(struct perf_event *event)
+{
+ __cxl_pmu_read(event, false);
+}
+
+static void cxl_pmu_event_stop(struct perf_event *event, int flags)
+{
+ struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu);
+ void __iomem *base = info->base;
+ struct hw_perf_event *hwc = &event->hw;
+ u64 cfg;
+
+ cxl_pmu_read(event);
+ WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+ hwc->state |= PERF_HES_STOPPED;
+
+ cfg = readq(base + CXL_PMU_COUNTER_CFG_REG(hwc->idx));
+ cfg &= ~(FIELD_PREP(CXL_PMU_COUNTER_CFG_INT_ON_OVRFLW, 1) |
+ FIELD_PREP(CXL_PMU_COUNTER_CFG_ENABLE, 1));
+ writeq(cfg, base + CXL_PMU_COUNTER_CFG_REG(hwc->idx));
+
+ hwc->state |= PERF_HES_UPTODATE;
+}
+
+static int cxl_pmu_event_add(struct perf_event *event, int flags)
+{
+ struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ int idx, rc;
+ int event_idx = 0;
+
+ hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+
+ rc = cxl_pmu_get_event_idx(event, &idx, &event_idx);
+ if (rc < 0)
+ return rc;
+
+ hwc->idx = idx;
+
+ /* Only set for configurable counters */
+ hwc->event_base = event_idx;
+ info->hw_events[idx] = event;
+ set_bit(idx, info->used_counter_bm);
+
+ if (flags & PERF_EF_START)
+ cxl_pmu_event_start(event, PERF_EF_RELOAD);
+
+ return 0;
+}
+
+static void cxl_pmu_event_del(struct perf_event *event, int flags)
+{
+ struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+
+ cxl_pmu_event_stop(event, PERF_EF_UPDATE);
+ clear_bit(hwc->idx, info->used_counter_bm);
+ info->hw_events[hwc->idx] = NULL;
+ perf_event_update_userpage(event);
+}
+
+static irqreturn_t cxl_pmu_irq(int irq, void *data)
+{
+ struct cxl_pmu_info *info = data;
+ void __iomem *base = info->base;
+ u64 overflowed;
+ DECLARE_BITMAP(overflowedbm, 64);
+ int i;
+
+ overflowed = readq(base + CXL_PMU_OVERFLOW_REG);
+
+ /* Interrupt may be shared, so maybe it isn't ours */
+ if (!overflowed)
+ return IRQ_NONE;
+
+ bitmap_from_arr64(overflowedbm, &overflowed, 64);
+ for_each_set_bit(i, overflowedbm, info->num_counters) {
+ struct perf_event *event = info->hw_events[i];
+
+ if (!event) {
+ dev_dbg(info->pmu.dev,
+ "overflow but on non enabled counter %d\n", i);
+ continue;
+ }
+
+ __cxl_pmu_read(event, true);
+ }
+
+ writeq(overflowed, base + CXL_PMU_OVERFLOW_REG);
+
+ return IRQ_HANDLED;
+}
+
+static void cxl_pmu_perf_unregister(void *_info)
+{
+ struct cxl_pmu_info *info = _info;
+
+ perf_pmu_unregister(&info->pmu);
+}
+
+static void cxl_pmu_cpuhp_remove(void *_info)
+{
+ struct cxl_pmu_info *info = _info;
+
+ cpuhp_state_remove_instance_nocalls(cxl_pmu_cpuhp_state_num, &info->node);
+}
+
+static int cxl_pmu_probe(struct device *dev)
+{
+ struct cxl_pmu *pmu = to_cxl_pmu(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->parent);
+ struct cxl_pmu_info *info;
+ char *irq_name;
+ char *dev_name;
+ int rc, irq;
+
+ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, info);
+ INIT_LIST_HEAD(&info->event_caps_fixed);
+ INIT_LIST_HEAD(&info->event_caps_configurable);
+
+ info->base = pmu->base;
+
+ info->on_cpu = -1;
+ rc = cxl_pmu_parse_caps(dev, info);
+ if (rc)
+ return rc;
+
+ info->hw_events = devm_kcalloc(dev, sizeof(*info->hw_events),
+ info->num_counters, GFP_KERNEL);
+ if (!info->hw_events)
+ return -ENOMEM;
+
+ switch (pmu->type) {
+ case CXL_PMU_MEMDEV:
+ dev_name = devm_kasprintf(dev, GFP_KERNEL, "cxl_pmu_mem%d.%d",
+ pmu->assoc_id, pmu->index);
+ break;
+ }
+ if (!dev_name)
+ return -ENOMEM;
+
+ info->pmu = (struct pmu) {
+ .name = dev_name,
+ .parent = dev,
+ .module = THIS_MODULE,
+ .event_init = cxl_pmu_event_init,
+ .pmu_enable = cxl_pmu_enable,
+ .pmu_disable = cxl_pmu_disable,
+ .add = cxl_pmu_event_add,
+ .del = cxl_pmu_event_del,
+ .start = cxl_pmu_event_start,
+ .stop = cxl_pmu_event_stop,
+ .read = cxl_pmu_read,
+ .task_ctx_nr = perf_invalid_context,
+ .attr_groups = cxl_pmu_attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
+ };
+
+ if (info->irq <= 0)
+ return -EINVAL;
+
+ rc = pci_irq_vector(pdev, info->irq);
+ if (rc < 0)
+ return rc;
+ irq = rc;
+
+ irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_overflow\n", dev_name);
+ if (!irq_name)
+ return -ENOMEM;
+
+ rc = devm_request_irq(dev, irq, cxl_pmu_irq, IRQF_SHARED | IRQF_ONESHOT,
+ irq_name, info);
+ if (rc)
+ return rc;
+ info->irq = irq;
+
+ rc = cpuhp_state_add_instance(cxl_pmu_cpuhp_state_num, &info->node);
+ if (rc)
+ return rc;
+
+ rc = devm_add_action_or_reset(dev, cxl_pmu_cpuhp_remove, info);
+ if (rc)
+ return rc;
+
+ rc = perf_pmu_register(&info->pmu, info->pmu.name, -1);
+ if (rc)
+ return rc;
+
+ rc = devm_add_action_or_reset(dev, cxl_pmu_perf_unregister, info);
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+static struct cxl_driver cxl_pmu_driver = {
+ .name = "cxl_pmu",
+ .probe = cxl_pmu_probe,
+ .id = CXL_DEVICE_PMU,
+};
+
+static int cxl_pmu_online_cpu(unsigned int cpu, struct hlist_node *node)
+{
+ struct cxl_pmu_info *info = hlist_entry_safe(node, struct cxl_pmu_info, node);
+
+ if (info->on_cpu != -1)
+ return 0;
+
+ info->on_cpu = cpu;
+ /*
+ * CPU HP lock is held so we should be guaranteed that the CPU hasn't yet
+ * gone away again.
+ */
+ WARN_ON(irq_set_affinity(info->irq, cpumask_of(cpu)));
+
+ return 0;
+}
+
+static int cxl_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
+{
+ struct cxl_pmu_info *info = hlist_entry_safe(node, struct cxl_pmu_info, node);
+ unsigned int target;
+
+ if (info->on_cpu != cpu)
+ return 0;
+
+ info->on_cpu = -1;
+ target = cpumask_any_but(cpu_online_mask, cpu);
+ if (target >= nr_cpu_ids) {
+ dev_err(info->pmu.dev, "Unable to find a suitable CPU\n");
+ return 0;
+ }
+
+ perf_pmu_migrate_context(&info->pmu, cpu, target);
+ info->on_cpu = target;
+ /*
+ * CPU HP lock is held so we should be guaranteed that this CPU hasn't yet
+ * gone away.
+ */
+ WARN_ON(irq_set_affinity(info->irq, cpumask_of(target)));
+
+ return 0;
+}
+
+static __init int cxl_pmu_init(void)
+{
+ int rc;
+
+ rc = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
+ "AP_PERF_CXL_PMU_ONLINE",
+ cxl_pmu_online_cpu, cxl_pmu_offline_cpu);
+ if (rc < 0)
+ return rc;
+ cxl_pmu_cpuhp_state_num = rc;
+
+ rc = cxl_driver_register(&cxl_pmu_driver);
+ if (rc)
+ cpuhp_remove_multi_state(cxl_pmu_cpuhp_state_num);
+
+ return rc;
+}
+
+static __exit void cxl_pmu_exit(void)
+{
+ cxl_driver_unregister(&cxl_pmu_driver);
+ cpuhp_remove_multi_state(cxl_pmu_cpuhp_state_num);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(CXL);
+module_init(cxl_pmu_init);
+module_exit(cxl_pmu_exit);
+MODULE_ALIAS_CXL(CXL_DEVICE_PMU);
diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
index 4f3ac296b3e2..4163ff517471 100644
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -739,7 +739,6 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde
{
int ret;
struct cpu_hw_events __percpu *hw_events = pmu->hw_events;
- struct device_node *cpu, *child;
struct irq_domain *domain = NULL;
if (riscv_isa_extension_available(NULL, SSCOFPMF)) {
@@ -756,20 +755,8 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde
if (!riscv_pmu_use_irq)
return -EOPNOTSUPP;
- for_each_of_cpu_node(cpu) {
- child = of_get_compatible_child(cpu, "riscv,cpu-intc");
- if (!child) {
- pr_err("Failed to find INTC node\n");
- of_node_put(cpu);
- return -ENODEV;
- }
- domain = irq_find_host(child);
- of_node_put(child);
- if (domain) {
- of_node_put(cpu);
- break;
- }
- }
+ domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(),
+ DOMAIN_BUS_ANY);
if (!domain) {
pr_err("Failed to find INTC IRQ root domain\n");
return -ENODEV;
@@ -868,6 +855,12 @@ static int pmu_sbi_device_probe(struct platform_device *pdev)
goto out_free;
}
+ /* It is possible to get from SBI more than max number of counters */
+ if (num_counters > RISCV_MAX_COUNTERS) {
+ num_counters = RISCV_MAX_COUNTERS;
+ pr_info("SBI returned more than maximum number of counters. Limiting the number of counters to %d\n", num_counters);
+ }
+
/* cache all the information about counters now */
if (pmu_sbi_get_ctrinfo(num_counters, &cmask))
goto out_free;
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index f46e3148d286..8dba9596408f 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -18,6 +18,7 @@ config GENERIC_PHY
config GENERIC_PHY_MIPI_DPHY
bool
+ depends on GENERIC_PHY
help
Generic MIPI D-PHY support.
diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c
index 13fcd3a65fe9..7df9c79a772a 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -720,6 +720,7 @@ static int cdns_sierra_pll_mux_set_parent(struct clk_hw *hw, u8 index)
}
static const struct clk_ops cdns_sierra_pll_mux_ops = {
+ .determine_rate = __clk_mux_determine_rate,
.set_parent = cdns_sierra_pll_mux_set_parent,
.get_parent = cdns_sierra_pll_mux_get_parent,
};
diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c
index 3831f596d50c..62e59d1bb9c3 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -1861,6 +1861,7 @@ static const struct clk_ops cdns_torrent_refclk_driver_ops = {
.enable = cdns_torrent_refclk_driver_enable,
.disable = cdns_torrent_refclk_driver_disable,
.is_enabled = cdns_torrent_refclk_driver_is_enabled,
+ .determine_rate = __clk_mux_determine_rate,
.set_parent = cdns_torrent_refclk_driver_set_parent,
.get_parent = cdns_torrent_refclk_driver_get_parent,
};
diff --git a/drivers/phy/ti/phy-am654-serdes.c b/drivers/phy/ti/phy-am654-serdes.c
index 4ed2d951d3df..3f1d43e8b7ad 100644
--- a/drivers/phy/ti/phy-am654-serdes.c
+++ b/drivers/phy/ti/phy-am654-serdes.c
@@ -634,6 +634,7 @@ static int serdes_am654_clk_mux_set_parent(struct clk_hw *hw, u8 index)
}
static const struct clk_ops serdes_am654_clk_mux_ops = {
+ .determine_rate = __clk_mux_determine_rate,
.set_parent = serdes_am654_clk_mux_set_parent,
.get_parent = serdes_am654_clk_mux_get_parent,
};
diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index d91923799df2..fc3cd98c60ff 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -801,6 +801,7 @@ static int wiz_clk_mux_set_parent(struct clk_hw *hw, u8 index)
}
static const struct clk_ops wiz_clk_mux_ops = {
+ .determine_rate = __clk_mux_determine_rate,
.set_parent = wiz_clk_mux_set_parent,
.get_parent = wiz_clk_mux_get_parent,
};
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 77ff9a641aeb..57d57af1f624 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -510,7 +510,6 @@ config PINCTRL_MLXBF3
select PINMUX
select GPIOLIB
select GPIOLIB_IRQCHIP
- select GPIO_MLXBF3
help
Say Y to select the pinctrl driver for BlueField-3 SoCs.
This pin controller allows selecting the mux function for
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index e196c6e324ad..482b391b5deb 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -66,7 +66,7 @@ obj-y += nomadik/
obj-y += nuvoton/
obj-y += nxp/
obj-$(CONFIG_PINCTRL_PXA) += pxa/
-obj-$(CONFIG_ARCH_QCOM) += qcom/
+obj-y += qcom/
obj-$(CONFIG_PINCTRL_RENESAS) += renesas/
obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/
obj-$(CONFIG_PINCTRL_SPEAR) += spear/
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index 7435173e10f4..1489191a213f 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -376,10 +376,8 @@ static int bcm2835_add_pin_ranges_fallback(struct gpio_chip *gc)
if (!pctldev)
return 0;
- gpiochip_add_pin_range(gc, pinctrl_dev_get_devname(pctldev), 0, 0,
- gc->ngpio);
-
- return 0;
+ return gpiochip_add_pin_range(gc, pinctrl_dev_get_devname(pctldev), 0, 0,
+ gc->ngpio);
}
static const struct gpio_chip bcm2835_gpio_chip = {
diff --git a/drivers/pinctrl/freescale/pinctrl-scu.c b/drivers/pinctrl/freescale/pinctrl-scu.c
index ea261b6e7458..3b252d684d72 100644
--- a/drivers/pinctrl/freescale/pinctrl-scu.c
+++ b/drivers/pinctrl/freescale/pinctrl-scu.c
@@ -90,7 +90,7 @@ int imx_pinconf_set_scu(struct pinctrl_dev *pctldev, unsigned pin_id,
struct imx_sc_msg_req_pad_set msg;
struct imx_sc_rpc_msg *hdr = &msg.hdr;
unsigned int mux = configs[0];
- unsigned int conf = configs[1];
+ unsigned int conf;
unsigned int val;
int ret;
@@ -115,6 +115,7 @@ int imx_pinconf_set_scu(struct pinctrl_dev *pctldev, unsigned pin_id,
* Set mux and conf together in one IPC call
*/
WARN_ON(num_configs != 2);
+ conf = configs[1];
val = conf | BM_PAD_CTL_IFMUX_ENABLE | BM_PAD_CTL_GP_ENABLE;
val |= mux << BP_PAD_CTL_IFMUX;
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index 770a2723ef81..27aef62fc7c0 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -18,6 +18,7 @@
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/seq_file.h>
+#include <linux/string_helpers.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
@@ -52,10 +53,9 @@
#define BYT_PULL_STR_10K (1 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_20K (2 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_40K (3 << BYT_PULL_STR_SHIFT)
-#define BYT_PULL_ASSIGN_SHIFT 7
#define BYT_PULL_ASSIGN_MASK GENMASK(8, 7)
-#define BYT_PULL_ASSIGN_UP (1 << BYT_PULL_ASSIGN_SHIFT)
-#define BYT_PULL_ASSIGN_DOWN (2 << BYT_PULL_ASSIGN_SHIFT)
+#define BYT_PULL_ASSIGN_DOWN BIT(8)
+#define BYT_PULL_ASSIGN_UP BIT(7)
#define BYT_PIN_MUX GENMASK(2, 0)
/* BYT_VAL_REG register bits */
@@ -668,8 +668,7 @@ static void byt_set_group_simple_mux(struct intel_pinctrl *vg,
padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG);
if (!padcfg0) {
- dev_warn(vg->dev,
- "Group %s, pin %i not muxed (no padcfg0)\n",
+ dev_warn(vg->dev, "Group %s, pin %i not muxed (can't retrieve CONF0)\n",
group.grp.name, i);
continue;
}
@@ -698,8 +697,7 @@ static void byt_set_group_mixed_mux(struct intel_pinctrl *vg,
padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG);
if (!padcfg0) {
- dev_warn(vg->dev,
- "Group %s, pin %i not muxed (no padcfg0)\n",
+ dev_warn(vg->dev, "Group %s, pin %i not muxed (can't retrieve CONF0)\n",
group.grp.name, i);
continue;
}
@@ -755,9 +753,7 @@ static void byt_gpio_clear_triggering(struct intel_pinctrl *vg, unsigned int off
value = readl(reg);
/* Do not clear direct-irq enabled IRQs (from gpio_disable_free) */
- if (value & BYT_DIRECT_IRQ_EN)
- /* nothing to do */ ;
- else
+ if (!(value & BYT_DIRECT_IRQ_EN))
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
writel(value, reg);
@@ -791,7 +787,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
value |= gpio_mux;
writel(value, reg);
- dev_warn(vg->dev, FW_BUG "pin %u forcibly re-configured as GPIO\n", offset);
+ dev_warn(vg->dev, FW_BUG "Pin %i: forcibly re-configured as GPIO\n", offset);
}
raw_spin_unlock_irqrestore(&byt_lock, flags);
@@ -823,7 +819,9 @@ static void byt_gpio_direct_irq_check(struct intel_pinctrl *vg,
* themselves in the foot.
*/
if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
- dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
+ dev_info_once(vg->dev,
+ "Potential Error: Pin %i: forcibly set GPIO with DIRECT_IRQ_EN to output\n",
+ offset);
}
static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
@@ -1026,9 +1024,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
if (val & BYT_INPUT_EN) {
val &= ~BYT_INPUT_EN;
writel(val, val_reg);
- dev_warn(vg->dev,
- "pin %u forcibly set to input mode\n",
- offset);
+ dev_warn(vg->dev, "Pin %i: forcibly set to input mode\n", offset);
}
conf &= ~BYT_PULL_ASSIGN_MASK;
@@ -1048,9 +1044,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
if (val & BYT_INPUT_EN) {
val &= ~BYT_INPUT_EN;
writel(val, val_reg);
- dev_warn(vg->dev,
- "pin %u forcibly set to input mode\n",
- offset);
+ dev_warn(vg->dev, "Pin %i: forcibly set to input mode\n", offset);
}
conf &= ~BYT_PULL_ASSIGN_MASK;
@@ -1245,39 +1239,35 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
for (i = 0; i < vg->soc->npins; i++) {
const struct intel_community *comm;
+ void __iomem *conf_reg, *val_reg;
const char *pull_str = NULL;
const char *pull = NULL;
- void __iomem *reg;
unsigned long flags;
const char *label;
unsigned int pin;
- raw_spin_lock_irqsave(&byt_lock, flags);
pin = vg->soc->pins[i].number;
- reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
- if (!reg) {
- seq_printf(s,
- "Could not retrieve pin %i conf0 reg\n",
- pin);
- raw_spin_unlock_irqrestore(&byt_lock, flags);
+
+ conf_reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
+ if (!conf_reg) {
+ seq_printf(s, "Pin %i: can't retrieve CONF0\n", pin);
continue;
}
- conf0 = readl(reg);
- reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
- if (!reg) {
- seq_printf(s,
- "Could not retrieve pin %i val reg\n", pin);
- raw_spin_unlock_irqrestore(&byt_lock, flags);
+ val_reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
+ if (!val_reg) {
+ seq_printf(s, "Pin %i: can't retrieve VAL\n", pin);
continue;
}
- val = readl(reg);
+
+ raw_spin_lock_irqsave(&byt_lock, flags);
+ conf0 = readl(conf_reg);
+ val = readl(val_reg);
raw_spin_unlock_irqrestore(&byt_lock, flags);
comm = byt_get_community(vg, pin);
if (!comm) {
- seq_printf(s,
- "Could not get community for pin %i\n", pin);
+ seq_printf(s, "Pin %i: can't retrieve community\n", pin);
continue;
}
label = gpiochip_is_requested(chip, i);
@@ -1314,7 +1304,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
label,
val & BYT_INPUT_EN ? " " : "in",
val & BYT_OUTPUT_EN ? " " : "out",
- val & BYT_LEVEL ? "hi" : "lo",
+ str_hi_lo(val & BYT_LEVEL),
comm->pad_map[i], comm->pad_map[i] * 16,
conf0 & 0x7,
conf0 & BYT_TRIG_NEG ? " fall" : " ",
@@ -1429,7 +1419,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
value = readl(reg);
WARN(value & BYT_DIRECT_IRQ_EN,
- "Bad pad config for io mode, force direct_irq_en bit clearing");
+ "Bad pad config for IO mode, force DIRECT_IRQ_EN bit clearing");
/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
* are used to indicate high and low level triggering
@@ -1476,9 +1466,7 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
if (!reg) {
- dev_warn(vg->dev,
- "Pin %i: could not retrieve interrupt status register\n",
- base);
+ dev_warn(vg->dev, "Pin %i: can't retrieve INT_STAT%u\n", base / 32, base);
continue;
}
@@ -1501,7 +1489,7 @@ static bool byt_direct_irq_sanity_check(struct intel_pinctrl *vg, int pin, u32 c
sizeof(direct_irq_mux));
match = memchr(direct_irq_mux, pin, sizeof(direct_irq_mux));
if (!match) {
- dev_warn(vg->dev, FW_BUG "pin %i: direct_irq_en set but no IRQ assigned, clearing\n", pin);
+ dev_warn(vg->dev, FW_BUG "Pin %i: DIRECT_IRQ_EN set but no IRQ assigned, clearing\n", pin);
return false;
}
@@ -1528,7 +1516,8 @@ static bool byt_direct_irq_sanity_check(struct intel_pinctrl *vg, int pin, u32 c
trig = conf0 & BYT_TRIG_MASK;
if (trig != (BYT_TRIG_POS | BYT_TRIG_LVL) &&
trig != (BYT_TRIG_NEG | BYT_TRIG_LVL)) {
- dev_warn(vg->dev, FW_BUG "pin %i: direct_irq_en set without trigger (conf0: %xh), clearing\n",
+ dev_warn(vg->dev,
+ FW_BUG "Pin %i: DIRECT_IRQ_EN set without trigger (CONF0: %#08x), clearing\n",
pin, conf0);
return false;
}
@@ -1555,9 +1544,7 @@ static void byt_init_irq_valid_mask(struct gpio_chip *chip,
reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
if (!reg) {
- dev_warn(vg->dev,
- "Pin %i: could not retrieve conf0 register\n",
- i);
+ dev_warn(vg->dev, "Pin %i: could not retrieve CONF0\n", i);
continue;
}
@@ -1588,9 +1575,7 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
if (!reg) {
- dev_warn(vg->dev,
- "Pin %i: could not retrieve irq status reg\n",
- base);
+ dev_warn(vg->dev, "Pin %i: can't retrieve INT_STAT%u\n", base / 32, base);
continue;
}
@@ -1600,7 +1585,7 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
value = readl(reg);
if (value)
dev_err(vg->dev,
- "GPIO interrupt error, pins misconfigured. INT_STAT%u: 0x%08x\n",
+ "GPIO interrupt error, pins misconfigured. INT_STAT%u: %#08x\n",
base / 32, value);
}
@@ -1764,15 +1749,17 @@ static int byt_gpio_suspend(struct device *dev)
reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
if (!reg) {
- dev_warn(vg->dev,
- "Pin %i: could not retrieve conf0 register\n",
- i);
+ dev_warn(vg->dev, "Pin %i: can't retrieve CONF0\n", i);
continue;
}
value = readl(reg) & BYT_CONF0_RESTORE_MASK;
vg->context.pads[i].conf0 = value;
reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
+ if (!reg) {
+ dev_warn(vg->dev, "Pin %i: can't retrieve VAL\n", i);
+ continue;
+ }
value = readl(reg) & BYT_VAL_RESTORE_MASK;
vg->context.pads[i].val = value;
}
@@ -1796,9 +1783,7 @@ static int byt_gpio_resume(struct device *dev)
reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
if (!reg) {
- dev_warn(vg->dev,
- "Pin %i: could not retrieve conf0 register\n",
- i);
+ dev_warn(vg->dev, "Pin %i: can't retrieve CONF0\n", i);
continue;
}
value = readl(reg);
@@ -1807,10 +1792,14 @@ static int byt_gpio_resume(struct device *dev)
value &= ~BYT_CONF0_RESTORE_MASK;
value |= vg->context.pads[i].conf0;
writel(value, reg);
- dev_info(dev, "restored pin %d conf0 %#08x", i, value);
+ dev_info(dev, "restored pin %d CONF0 %#08x", i, value);
}
reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
+ if (!reg) {
+ dev_warn(vg->dev, "Pin %i: can't retrieve VAL\n", i);
+ continue;
+ }
value = readl(reg);
if ((value & BYT_VAL_RESTORE_MASK) !=
vg->context.pads[i].val) {
@@ -1820,8 +1809,7 @@ static int byt_gpio_resume(struct device *dev)
v |= vg->context.pads[i].val;
if (v != value) {
writel(v, reg);
- dev_dbg(dev, "restored pin %d val %#08x\n",
- i, v);
+ dev_dbg(dev, "restored pin %d VAL %#08x\n", i, v);
}
}
}
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 722990e27836..eee0f9bc3d32 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -75,7 +75,7 @@ struct intel_pad_context {
u32 padctrl1;
};
-#define CHV_INVALID_HWIRQ ((unsigned int)INVALID_HWIRQ)
+#define CHV_INVALID_HWIRQ (~0U)
/**
* struct intel_community_context - community context for Cherryview
@@ -949,11 +949,6 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
break;
- case PIN_CONFIG_DRIVE_OPEN_DRAIN:
- if (!(ctrl1 & CHV_PADCTRL1_ODEN))
- return -EINVAL;
- break;
-
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: {
u32 cfg;
@@ -963,6 +958,16 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
return -EINVAL;
break;
+
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ if (ctrl1 & CHV_PADCTRL1_ODEN)
+ return -EINVAL;
+ break;
+
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ if (!(ctrl1 & CHV_PADCTRL1_ODEN))
+ return -EINVAL;
+ break;
}
default:
@@ -1408,8 +1413,10 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type)
raw_spin_lock_irqsave(&chv_lock, flags);
ret = chv_gpio_set_intr_line(pctrl, hwirq);
- if (ret)
- goto out_unlock;
+ if (ret) {
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
+ return ret;
+ }
/*
* Pins which can be used as shared interrupt are configured in
@@ -1450,10 +1457,9 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type)
else if (type & IRQ_TYPE_LEVEL_MASK)
irq_set_handler_locked(d, handle_level_irq);
-out_unlock:
raw_spin_unlock_irqrestore(&chv_lock, flags);
- return ret;
+ return 0;
}
static const struct irq_chip chv_gpio_irq_chip = {
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index c7a71c49df0a..64c3e62b4348 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -55,12 +55,11 @@
/* Offset from pad_regs */
#define PADCFG0 0x000
-#define PADCFG0_RXEVCFG_SHIFT 25
#define PADCFG0_RXEVCFG_MASK GENMASK(26, 25)
-#define PADCFG0_RXEVCFG_LEVEL 0
-#define PADCFG0_RXEVCFG_EDGE 1
-#define PADCFG0_RXEVCFG_DISABLED 2
-#define PADCFG0_RXEVCFG_EDGE_BOTH 3
+#define PADCFG0_RXEVCFG_LEVEL (0 << 25)
+#define PADCFG0_RXEVCFG_EDGE (1 << 25)
+#define PADCFG0_RXEVCFG_DISABLED (2 << 25)
+#define PADCFG0_RXEVCFG_EDGE_BOTH (3 << 25)
#define PADCFG0_PREGFRXSEL BIT(24)
#define PADCFG0_RXINV BIT(23)
#define PADCFG0_GPIROUTIOXAPIC BIT(20)
@@ -411,18 +410,19 @@ static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev,
/* Now enable the mux setting for each pin in the group */
for (i = 0; i < grp->grp.npins; i++) {
void __iomem *padcfg0;
- u32 value;
+ u32 value, pmode;
padcfg0 = intel_get_padcfg(pctrl, grp->grp.pins[i], PADCFG0);
- value = readl(padcfg0);
+ value = readl(padcfg0);
value &= ~PADCFG0_PMODE_MASK;
if (grp->modes)
- value |= grp->modes[i] << PADCFG0_PMODE_SHIFT;
+ pmode = grp->modes[i];
else
- value |= grp->mode << PADCFG0_PMODE_SHIFT;
+ pmode = grp->mode;
+ value |= pmode << PADCFG0_PMODE_SHIFT;
writel(value, padcfg0);
}
@@ -1126,9 +1126,9 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
unsigned int pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
+ u32 rxevcfg, rxinv, value;
unsigned long flags;
void __iomem *reg;
- u32 value;
reg = intel_get_padcfg(pctrl, pin, PADCFG0);
if (!reg)
@@ -1144,28 +1144,32 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type)
return -EPERM;
}
- raw_spin_lock_irqsave(&pctrl->lock, flags);
-
- intel_gpio_set_gpio_mode(reg);
-
- value = readl(reg);
-
- value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV);
-
if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
- value |= PADCFG0_RXEVCFG_EDGE_BOTH << PADCFG0_RXEVCFG_SHIFT;
+ rxevcfg = PADCFG0_RXEVCFG_EDGE_BOTH;
} else if (type & IRQ_TYPE_EDGE_FALLING) {
- value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT;
- value |= PADCFG0_RXINV;
+ rxevcfg = PADCFG0_RXEVCFG_EDGE;
} else if (type & IRQ_TYPE_EDGE_RISING) {
- value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT;
+ rxevcfg = PADCFG0_RXEVCFG_EDGE;
} else if (type & IRQ_TYPE_LEVEL_MASK) {
- if (type & IRQ_TYPE_LEVEL_LOW)
- value |= PADCFG0_RXINV;
+ rxevcfg = PADCFG0_RXEVCFG_LEVEL;
} else {
- value |= PADCFG0_RXEVCFG_DISABLED << PADCFG0_RXEVCFG_SHIFT;
+ rxevcfg = PADCFG0_RXEVCFG_DISABLED;
}
+ if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW)
+ rxinv = PADCFG0_RXINV;
+ else
+ rxinv = 0;
+
+ raw_spin_lock_irqsave(&pctrl->lock, flags);
+
+ intel_gpio_set_gpio_mode(reg);
+
+ value = readl(reg);
+
+ value = (value & ~PADCFG0_RXEVCFG_MASK) | rxevcfg;
+ value = (value & ~PADCFG0_RXINV) | rxinv;
+
writel(value, reg);
if (type & IRQ_TYPE_EDGE_BOTH)
diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c
index 365c391c97a3..fb6de38b1c50 100644
--- a/drivers/pinctrl/intel/pinctrl-merrifield.c
+++ b/drivers/pinctrl/intel/pinctrl-merrifield.c
@@ -549,7 +549,7 @@ static void mrfld_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
}
mode = (value & BUFCFG_PINMODE_MASK) >> BUFCFG_PINMODE_SHIFT;
- if (!mode)
+ if (mode == BUFCFG_PINMODE_GPIO)
seq_puts(s, "GPIO ");
else
seq_printf(s, "mode %d ", mode);
@@ -710,6 +710,11 @@ static int mrfld_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
break;
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ if (value & BUFCFG_OD_EN)
+ return -EINVAL;
+ break;
+
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
if (!(value & BUFCFG_OD_EN))
return -EINVAL;
@@ -791,10 +796,14 @@ static int mrfld_config_set_pin(struct mrfld_pinctrl *mp, unsigned int pin,
break;
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ mask |= BUFCFG_OD_EN;
+ bits &= ~BUFCFG_OD_EN;
+ break;
+
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
mask |= BUFCFG_OD_EN;
- if (arg)
- bits |= BUFCFG_OD_EN;
+ bits |= BUFCFG_OD_EN;
break;
case PIN_CONFIG_SLEW_RATE:
@@ -826,6 +835,7 @@ static int mrfld_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
case PIN_CONFIG_SLEW_RATE:
ret = mrfld_config_set_pin(mp, pin, configs[i]);
diff --git a/drivers/pinctrl/intel/pinctrl-meteorlake.c b/drivers/pinctrl/intel/pinctrl-meteorlake.c
index a82f6754c45b..9a11f729bec8 100644
--- a/drivers/pinctrl/intel/pinctrl-meteorlake.c
+++ b/drivers/pinctrl/intel/pinctrl-meteorlake.c
@@ -20,6 +20,12 @@
#define MTL_P_GPI_IS 0x200
#define MTL_P_GPI_IE 0x210
+#define MTL_S_PAD_OWN 0x0b0
+#define MTL_S_PADCFGLOCK 0x0f0
+#define MTL_S_HOSTSW_OWN 0x110
+#define MTL_S_GPI_IS 0x200
+#define MTL_S_GPI_IE 0x210
+
#define MTL_GPP(r, s, e, g) \
{ \
.reg_num = (r), \
@@ -28,9 +34,12 @@
.gpio_base = (g), \
}
-#define MTL_COMMUNITY(b, s, e, g) \
+#define MTL_P_COMMUNITY(b, s, e, g) \
INTEL_COMMUNITY_GPPS(b, s, e, g, MTL_P)
+#define MTL_S_COMMUNITY(b, s, e, g) \
+ INTEL_COMMUNITY_GPPS(b, s, e, g, MTL_S)
+
/* Meteor Lake-P */
static const struct pinctrl_pin_desc mtlp_pins[] = {
/* CPU */
@@ -369,11 +378,11 @@ static const struct intel_padgroup mtlp_community5_gpps[] = {
};
static const struct intel_community mtlp_communities[] = {
- MTL_COMMUNITY(0, 0, 52, mtlp_community0_gpps),
- MTL_COMMUNITY(1, 53, 102, mtlp_community1_gpps),
- MTL_COMMUNITY(2, 103, 183, mtlp_community3_gpps),
- MTL_COMMUNITY(3, 184, 203, mtlp_community4_gpps),
- MTL_COMMUNITY(4, 204, 288, mtlp_community5_gpps),
+ MTL_P_COMMUNITY(0, 0, 52, mtlp_community0_gpps),
+ MTL_P_COMMUNITY(1, 53, 102, mtlp_community1_gpps),
+ MTL_P_COMMUNITY(2, 103, 183, mtlp_community3_gpps),
+ MTL_P_COMMUNITY(3, 184, 203, mtlp_community4_gpps),
+ MTL_P_COMMUNITY(4, 204, 288, mtlp_community5_gpps),
};
static const struct intel_pinctrl_soc_data mtlp_soc_data = {
@@ -383,8 +392,199 @@ static const struct intel_pinctrl_soc_data mtlp_soc_data = {
.ncommunities = ARRAY_SIZE(mtlp_communities),
};
+/* Meteor Lake-S */
+static const struct pinctrl_pin_desc mtls_pins[] = {
+ /* GPP_A */
+ PINCTRL_PIN(0, "DIR_ESPI_IO_0"),
+ PINCTRL_PIN(1, "DIR_ESPI_IO_1"),
+ PINCTRL_PIN(2, "DIR_ESPI_IO_2"),
+ PINCTRL_PIN(3, "DIR_ESPI_IO_3"),
+ PINCTRL_PIN(4, "DIR_ESPI_CS0_B"),
+ PINCTRL_PIN(5, "DIR_ESPI_CLK"),
+ PINCTRL_PIN(6, "DIR_ESPI_RCLK"),
+ PINCTRL_PIN(7, "DIR_ESPI_RESET_B"),
+ PINCTRL_PIN(8, "SLP_S0_B"),
+ PINCTRL_PIN(9, "DMI_PERSTB"),
+ PINCTRL_PIN(10, "CATERR_B"),
+ PINCTRL_PIN(11, "THERMTRIP_B"),
+ PINCTRL_PIN(12, "CPU_C10_GATE_B"),
+ PINCTRL_PIN(13, "PS_ONB"),
+ PINCTRL_PIN(14, "GPP_SA_14"),
+ PINCTRL_PIN(15, "GPP_SA_15"),
+ PINCTRL_PIN(16, "GPP_SA_16"),
+ PINCTRL_PIN(17, "GPP_SA_17"),
+ PINCTRL_PIN(18, "GPP_SA_18"),
+ PINCTRL_PIN(19, "GPP_SA_19"),
+ PINCTRL_PIN(20, "GPP_SA_20"),
+ PINCTRL_PIN(21, "GPP_SA_21"),
+ PINCTRL_PIN(22, "FUSA_DIAGTEST_EN"),
+ PINCTRL_PIN(23, "FUSA_DIAGTEST_MODE"),
+ PINCTRL_PIN(24, "RTCCLKIN"),
+ PINCTRL_PIN(25, "RESET_SYNC_B"),
+ PINCTRL_PIN(26, "PCH_PWROK"),
+ PINCTRL_PIN(27, "DIR_ESPI_CLK_LOOPBACK"),
+ /* vGPIO_0 */
+ PINCTRL_PIN(28, "LPC_ME_FTPM_ENABLE"),
+ PINCTRL_PIN(29, "LPC_DTFUS_CORE_SPITPM_DIS"),
+ PINCTRL_PIN(30, "LPC_SPI_STRAP_TOS"),
+ PINCTRL_PIN(31, "ITSS_KU1_SHTDWN"),
+ PINCTRL_PIN(32, "LPC_PRR_TS_OVR"),
+ PINCTRL_PIN(33, "ESPI_PMC_EC_SCI"),
+ PINCTRL_PIN(34, "ESPI_PMC_EC_SCI1"),
+ PINCTRL_PIN(35, "vGPIO_SPARE0"),
+ PINCTRL_PIN(36, "vGPIO_SPARE1"),
+ PINCTRL_PIN(37, "vGPIO_SPARE2"),
+ PINCTRL_PIN(38, "vGPIO_SPARE3"),
+ PINCTRL_PIN(39, "vGPIO_SPARE8"),
+ PINCTRL_PIN(40, "vGPIO_SPARE9"),
+ PINCTRL_PIN(41, "vGPIO_SPARE10"),
+ PINCTRL_PIN(42, "vGPIO_SPARE11"),
+ PINCTRL_PIN(43, "vGPIO_SPARE12"),
+ PINCTRL_PIN(44, "vGPIO_SPARE13"),
+ PINCTRL_PIN(45, "vGPIO_SPARE14"),
+ PINCTRL_PIN(46, "vGPIO_SPARE15"),
+ /* GPP_C */
+ PINCTRL_PIN(47, "GPP_SC_0"),
+ PINCTRL_PIN(48, "GPP_SC_1"),
+ PINCTRL_PIN(49, "GPP_SC_2"),
+ PINCTRL_PIN(50, "GPP_SC_3"),
+ PINCTRL_PIN(51, "GPP_SC_4"),
+ PINCTRL_PIN(52, "GPP_SC_5"),
+ PINCTRL_PIN(53, "GPP_SC_6"),
+ PINCTRL_PIN(54, "GPP_SC_7"),
+ PINCTRL_PIN(55, "GPP_SC_8"),
+ PINCTRL_PIN(56, "GPP_SC_9"),
+ PINCTRL_PIN(57, "GPP_SC_10"),
+ PINCTRL_PIN(58, "GPP_SC_11"),
+ PINCTRL_PIN(59, "GPP_SC_12"),
+ PINCTRL_PIN(60, "GPP_SC_13"),
+ PINCTRL_PIN(61, "GPP_SC_14"),
+ PINCTRL_PIN(62, "GPP_SC_15"),
+ PINCTRL_PIN(63, "GPP_SC_16"),
+ PINCTRL_PIN(64, "GPP_SC_17"),
+ PINCTRL_PIN(65, "GPP_SC_18"),
+ PINCTRL_PIN(66, "GPP_SC_19"),
+ PINCTRL_PIN(67, "GPP_SC_20"),
+ PINCTRL_PIN(68, "GPP_SC_21"),
+ PINCTRL_PIN(69, "GPP_SC_22"),
+ PINCTRL_PIN(70, "GPP_SC_23"),
+ PINCTRL_PIN(71, "GPP_SC_24"),
+ PINCTRL_PIN(72, "GPP_SC_25"),
+ PINCTRL_PIN(73, "GPP_SC_26"),
+ /* GPP_B */
+ PINCTRL_PIN(74, "GPP_SB_0"),
+ PINCTRL_PIN(75, "GPP_SB_1"),
+ PINCTRL_PIN(76, "GPP_SB_2"),
+ PINCTRL_PIN(77, "GPP_SB_3"),
+ PINCTRL_PIN(78, "GPP_SB_4"),
+ PINCTRL_PIN(79, "GPP_SB_5"),
+ PINCTRL_PIN(80, "GPP_SB_6"),
+ PINCTRL_PIN(81, "GPP_SB_7"),
+ PINCTRL_PIN(82, "GPP_SB_8"),
+ PINCTRL_PIN(83, "GPP_SB_9"),
+ PINCTRL_PIN(84, "GPP_SB_10"),
+ PINCTRL_PIN(85, "GPP_SB_11"),
+ PINCTRL_PIN(86, "GPP_SB_12"),
+ PINCTRL_PIN(87, "GPP_SB_13"),
+ PINCTRL_PIN(88, "GPP_SB_14"),
+ PINCTRL_PIN(89, "GPP_SB_15"),
+ PINCTRL_PIN(90, "GPP_SB_16"),
+ PINCTRL_PIN(91, "PROCHOT_B"),
+ PINCTRL_PIN(92, "BPKI3C_SDA"),
+ PINCTRL_PIN(93, "BPKI3C_SCL"),
+ /* vGPIO_3 */
+ PINCTRL_PIN(94, "TS0_IN_INT"),
+ PINCTRL_PIN(95, "TS1_IN_INT"),
+ /* GPP_D */
+ PINCTRL_PIN(96, "TIME_SYNC_0"),
+ PINCTRL_PIN(97, "TIME_SYNC_1"),
+ PINCTRL_PIN(98, "DSI_DE_TE_2_GENLOCK_REF"),
+ PINCTRL_PIN(99, "DSI_DE_TE_1_DISP_UTILS"),
+ PINCTRL_PIN(100, "DSI_GENLOCK_2"),
+ PINCTRL_PIN(101, "DSI_GENLOCK_3"),
+ PINCTRL_PIN(102, "SRCCLKREQ2_B"),
+ PINCTRL_PIN(103, "SRCCLKREQ3_B"),
+ PINCTRL_PIN(104, "GPP_SD_8"),
+ PINCTRL_PIN(105, "GPP_SD_9"),
+ PINCTRL_PIN(106, "GPP_SD_10"),
+ PINCTRL_PIN(107, "GPP_SD_11"),
+ PINCTRL_PIN(108, "GPP_SD_12"),
+ PINCTRL_PIN(109, "GPP_SD_13"),
+ PINCTRL_PIN(110, "GPP_SD_14"),
+ PINCTRL_PIN(111, "GPP_SD_15"),
+ PINCTRL_PIN(112, "GPP_SD_16"),
+ PINCTRL_PIN(113, "GPP_SD_17"),
+ PINCTRL_PIN(114, "BOOTHALT_B"),
+ PINCTRL_PIN(115, "GPP_SD_19"),
+ PINCTRL_PIN(116, "GPP_SD_20"),
+ PINCTRL_PIN(117, "AUDCLK"),
+ PINCTRL_PIN(118, "AUDIN"),
+ PINCTRL_PIN(119, "AUDOUT"),
+ /* JTAG_CPU */
+ PINCTRL_PIN(120, "PECI"),
+ PINCTRL_PIN(121, "VIDSOUT"),
+ PINCTRL_PIN(122, "VIDSCK"),
+ PINCTRL_PIN(123, "VIDALERT_B"),
+ PINCTRL_PIN(124, "JTAG_MBPB0"),
+ PINCTRL_PIN(125, "JTAG_MBPB1"),
+ PINCTRL_PIN(126, "JTAG_MBPB2"),
+ PINCTRL_PIN(127, "JTAG_MBPB3"),
+ PINCTRL_PIN(128, "JTAG_TDO"),
+ PINCTRL_PIN(129, "PRDY_B"),
+ PINCTRL_PIN(130, "PREQ_B"),
+ PINCTRL_PIN(131, "JTAG_TDI"),
+ PINCTRL_PIN(132, "JTAG_TMS"),
+ PINCTRL_PIN(133, "JTAG_TCK"),
+ PINCTRL_PIN(134, "DBG_PMODE"),
+ PINCTRL_PIN(135, "JTAG_TRST_B"),
+ /* vGPIO_4 */
+ PINCTRL_PIN(136, "ISCLK_ESPI_XTAL_CLKREQ"),
+ PINCTRL_PIN(137, "ESPI_ISCLK_XTAL_CLKACK"),
+ PINCTRL_PIN(138, "vGPIO_SPARE4"),
+ PINCTRL_PIN(139, "vGPIO_SPARE5"),
+ PINCTRL_PIN(140, "vGPIO_SPARE6"),
+ PINCTRL_PIN(141, "vGPIO_SPARE7"),
+ PINCTRL_PIN(142, "vGPIO_SPARE16"),
+ PINCTRL_PIN(143, "vGPIO_SPARE17"),
+ PINCTRL_PIN(144, "vGPIO_SPARE18"),
+ PINCTRL_PIN(145, "vGPIO_SPARE19"),
+ PINCTRL_PIN(146, "vGPIO_SPARE20"),
+ PINCTRL_PIN(147, "vGPIO_SPARE21"),
+};
+
+static const struct intel_padgroup mtls_community0_gpps[] = {
+ MTL_GPP(0, 0, 27, 0), /* GPP_A */
+ MTL_GPP(1, 28, 46, 32), /* vGPIO_0 */
+ MTL_GPP(2, 47, 73, 64), /* GPP_C */
+};
+
+static const struct intel_padgroup mtls_community1_gpps[] = {
+ MTL_GPP(0, 74, 93, 96), /* GPP_B */
+ MTL_GPP(1, 94, 95, 128), /* vGPIO_3 */
+ MTL_GPP(2, 96, 119, 160), /* GPP_D */
+};
+
+static const struct intel_padgroup mtls_community3_gpps[] = {
+ MTL_GPP(0, 120, 135, 192), /* JTAG_CPU */
+ MTL_GPP(1, 136, 147, 224), /* vGPIO_4 */
+};
+
+static const struct intel_community mtls_communities[] = {
+ MTL_S_COMMUNITY(0, 0, 73, mtls_community0_gpps),
+ MTL_S_COMMUNITY(1, 74, 119, mtls_community1_gpps),
+ MTL_S_COMMUNITY(2, 120, 147, mtls_community3_gpps),
+};
+
+static const struct intel_pinctrl_soc_data mtls_soc_data = {
+ .pins = mtls_pins,
+ .npins = ARRAY_SIZE(mtls_pins),
+ .communities = mtls_communities,
+ .ncommunities = ARRAY_SIZE(mtls_communities),
+};
+
static const struct acpi_device_id mtl_pinctrl_acpi_match[] = {
{ "INTC1083", (kernel_ulong_t)&mtlp_soc_data },
+ { "INTC1082", (kernel_ulong_t)&mtls_soc_data },
{ }
};
MODULE_DEVICE_TABLE(acpi, mtl_pinctrl_acpi_match);
diff --git a/drivers/pinctrl/intel/pinctrl-moorefield.c b/drivers/pinctrl/intel/pinctrl-moorefield.c
index 3c9a8484b442..2d38d953f360 100644
--- a/drivers/pinctrl/intel/pinctrl-moorefield.c
+++ b/drivers/pinctrl/intel/pinctrl-moorefield.c
@@ -504,7 +504,7 @@ static void mofld_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
}
mode = (value & BUFCFG_PINMODE_MASK) >> BUFCFG_PINMODE_SHIFT;
- if (!mode)
+ if (mode == BUFCFG_PINMODE_GPIO)
seq_puts(s, "GPIO ");
else
seq_printf(s, "mode %d ", mode);
@@ -661,6 +661,11 @@ static int mofld_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
break;
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ if (value & BUFCFG_OD_EN)
+ return -EINVAL;
+ break;
+
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
if (!(value & BUFCFG_OD_EN))
return -EINVAL;
@@ -734,10 +739,14 @@ static int mofld_config_set_pin(struct mofld_pinctrl *mp, unsigned int pin,
break;
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ mask |= BUFCFG_OD_EN;
+ bits &= ~BUFCFG_OD_EN;
+ break;
+
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
mask |= BUFCFG_OD_EN;
- if (arg)
- bits |= BUFCFG_OD_EN;
+ bits |= BUFCFG_OD_EN;
break;
case PIN_CONFIG_SLEW_RATE:
@@ -769,6 +778,7 @@ static int mofld_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
case PIN_CONFIG_SLEW_RATE:
ret = mofld_config_set_pin(mp, pin, configs[i]);
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
index 21e61c2a3798..843ffcd96877 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
@@ -1884,6 +1884,8 @@ static int npcm7xx_gpio_of(struct npcm7xx_pinctrl *pctrl)
}
pctrl->gpio_bank[id].base = ioremap(res.start, resource_size(&res));
+ if (!pctrl->gpio_bank[id].base)
+ return -EINVAL;
ret = bgpio_init(&pctrl->gpio_bank[id].gc, dev, 4,
pctrl->gpio_bank[id].base + NPCM7XX_GP_N_DIN,
diff --git a/drivers/pinctrl/nxp/pinctrl-s32.h b/drivers/pinctrl/nxp/pinctrl-s32.h
index 2f7aecd462e4..add3c77ddfed 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32.h
+++ b/drivers/pinctrl/nxp/pinctrl-s32.h
@@ -34,24 +34,28 @@ struct s32_pin_range {
unsigned int end;
};
-struct s32_pinctrl_soc_info {
- struct device *dev;
+struct s32_pinctrl_soc_data {
const struct pinctrl_pin_desc *pins;
unsigned int npins;
+ const struct s32_pin_range *mem_pin_ranges;
+ unsigned int mem_regions;
+};
+
+struct s32_pinctrl_soc_info {
+ struct device *dev;
+ const struct s32_pinctrl_soc_data *soc_data;
struct s32_pin_group *groups;
unsigned int ngroups;
struct pinfunction *functions;
unsigned int nfunctions;
unsigned int grp_index;
- const struct s32_pin_range *mem_pin_ranges;
- unsigned int mem_regions;
};
#define S32_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
#define S32_PIN_RANGE(_start, _end) { .start = _start, .end = _end }
int s32_pinctrl_probe(struct platform_device *pdev,
- struct s32_pinctrl_soc_info *info);
+ const struct s32_pinctrl_soc_data *soc_data);
int s32_pinctrl_resume(struct device *dev);
int s32_pinctrl_suspend(struct device *dev);
#endif /* __DRIVERS_PINCTRL_S32_H */
diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index 8373468719b6..3ae043b27463 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
@@ -106,7 +106,7 @@ s32_get_region(struct pinctrl_dev *pctldev, unsigned int pin)
{
struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32_pin_range *pin_range;
- unsigned int mem_regions = ipctl->info->mem_regions;
+ unsigned int mem_regions = ipctl->info->soc_data->mem_regions;
unsigned int i;
for (i = 0; i < mem_regions; i++) {
@@ -279,8 +279,10 @@ static int s32_dt_node_to_map(struct pinctrl_dev *pctldev,
ret = s32_dt_group_node_to_map(pctldev, np, map,
&reserved_maps, num_maps,
np_config->name);
- if (ret < 0)
+ if (ret < 0) {
+ of_node_put(np);
break;
+ }
}
if (ret)
@@ -688,8 +690,8 @@ int s32_pinctrl_suspend(struct device *dev)
int ret;
unsigned int config;
- for (i = 0; i < info->npins; i++) {
- pin = &info->pins[i];
+ for (i = 0; i < info->soc_data->npins; i++) {
+ pin = &info->soc_data->pins[i];
if (!s32_pinctrl_should_save(ipctl, pin->number))
continue;
@@ -713,8 +715,8 @@ int s32_pinctrl_resume(struct device *dev)
struct s32_pinctrl_context *saved_context = &ipctl->saved_context;
int ret, i;
- for (i = 0; i < info->npins; i++) {
- pin = &info->pins[i];
+ for (i = 0; i < info->soc_data->npins; i++) {
+ pin = &info->soc_data->pins[i];
if (!s32_pinctrl_should_save(ipctl, pin->number))
continue;
@@ -812,8 +814,10 @@ static int s32_pinctrl_parse_functions(struct device_node *np,
groups[i] = child->name;
grp = &info->groups[info->grp_index++];
ret = s32_pinctrl_parse_groups(child, grp, info);
- if (ret)
+ if (ret) {
+ of_node_put(child);
return ret;
+ }
i++;
}
@@ -831,7 +835,7 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
struct resource *res;
struct regmap *map;
void __iomem *base;
- int mem_regions = info->mem_regions;
+ unsigned int mem_regions = info->soc_data->mem_regions;
int ret;
u32 nfuncs = 0;
u32 i = 0;
@@ -869,7 +873,7 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
}
ipctl->regions[i].map = map;
- ipctl->regions[i].pin_range = &info->mem_pin_ranges[i];
+ ipctl->regions[i].pin_range = &info->soc_data->mem_pin_ranges[i];
}
nfuncs = of_get_child_count(np);
@@ -896,28 +900,36 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
i = 0;
for_each_child_of_node(np, child) {
ret = s32_pinctrl_parse_functions(child, info, i++);
- if (ret)
+ if (ret) {
+ of_node_put(child);
return ret;
+ }
}
return 0;
}
int s32_pinctrl_probe(struct platform_device *pdev,
- struct s32_pinctrl_soc_info *info)
+ const struct s32_pinctrl_soc_data *soc_data)
{
struct s32_pinctrl *ipctl;
int ret;
struct pinctrl_desc *s32_pinctrl_desc;
+ struct s32_pinctrl_soc_info *info;
#ifdef CONFIG_PM_SLEEP
struct s32_pinctrl_context *saved_context;
#endif
- if (!info || !info->pins || !info->npins) {
+ if (!soc_data || !soc_data->pins || !soc_data->npins) {
dev_err(&pdev->dev, "wrong pinctrl info\n");
return -EINVAL;
}
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->soc_data = soc_data;
info->dev = &pdev->dev;
/* Create state holders etc for this driver */
@@ -938,8 +950,8 @@ int s32_pinctrl_probe(struct platform_device *pdev,
return -ENOMEM;
s32_pinctrl_desc->name = dev_name(&pdev->dev);
- s32_pinctrl_desc->pins = info->pins;
- s32_pinctrl_desc->npins = info->npins;
+ s32_pinctrl_desc->pins = info->soc_data->pins;
+ s32_pinctrl_desc->npins = info->soc_data->npins;
s32_pinctrl_desc->pctlops = &s32_pctrl_ops;
s32_pinctrl_desc->pmxops = &s32_pmx_ops;
s32_pinctrl_desc->confops = &s32_pinconf_ops;
@@ -960,7 +972,7 @@ int s32_pinctrl_probe(struct platform_device *pdev,
#ifdef CONFIG_PM_SLEEP
saved_context = &ipctl->saved_context;
saved_context->pads =
- devm_kcalloc(&pdev->dev, info->npins,
+ devm_kcalloc(&pdev->dev, info->soc_data->npins,
sizeof(*saved_context->pads),
GFP_KERNEL);
if (!saved_context->pads)
diff --git a/drivers/pinctrl/nxp/pinctrl-s32g2.c b/drivers/pinctrl/nxp/pinctrl-s32g2.c
index d9f3ff6794ea..224a12ce70ed 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32g2.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32g2.c
@@ -721,7 +721,7 @@ static const struct s32_pin_range s32_pin_ranges_siul2[] = {
S32_PIN_RANGE(942, 1007),
};
-static struct s32_pinctrl_soc_info s32_pinctrl_info = {
+static const struct s32_pinctrl_soc_data s32_pinctrl_data = {
.pins = s32_pinctrl_pads_siul2,
.npins = ARRAY_SIZE(s32_pinctrl_pads_siul2),
.mem_pin_ranges = s32_pin_ranges_siul2,
@@ -730,9 +730,8 @@ static struct s32_pinctrl_soc_info s32_pinctrl_info = {
static const struct of_device_id s32_pinctrl_of_match[] = {
{
-
.compatible = "nxp,s32g2-siul2-pinctrl",
- .data = (void *) &s32_pinctrl_info,
+ .data = &s32_pinctrl_data,
},
{ /* sentinel */ }
};
@@ -740,14 +739,11 @@ MODULE_DEVICE_TABLE(of, s32_pinctrl_of_match);
static int s32g_pinctrl_probe(struct platform_device *pdev)
{
- const struct of_device_id *of_id =
- of_match_device(s32_pinctrl_of_match, &pdev->dev);
+ const struct s32_pinctrl_soc_data *soc_data;
- if (!of_id)
- return -ENODEV;
+ soc_data = of_device_get_match_data(&pdev->dev);
- return s32_pinctrl_probe
- (pdev, (struct s32_pinctrl_soc_info *) of_id->data);
+ return s32_pinctrl_probe(pdev, soc_data);
}
static const struct dev_pm_ops s32g_pinctrl_pm_ops = {
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 43d3530bab48..3c4220be30ec 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -126,6 +126,12 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+
+ /* Use special handling for Pin0 debounce */
+ pin_reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
+ if (pin_reg & INTERNAL_GPIO0_DEBOUNCE)
+ debounce = 0;
+
pin_reg = readl(gpio_dev->base + offset * 4);
if (debounce) {
@@ -220,6 +226,7 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
char *debounce_enable;
char *wake_cntrlz;
+ seq_printf(s, "WAKE_INT_MASTER_REG: 0x%08x\n", readl(gpio_dev->base + WAKE_INT_MASTER_REG));
for (bank = 0; bank < gpio_dev->hwbank_num; bank++) {
unsigned int time = 0;
unsigned int unit = 0;
@@ -653,21 +660,21 @@ static bool do_amd_gpio_irq_handler(int irq, void *dev_id)
* We must read the pin register again, in case the
* value was changed while executing
* generic_handle_domain_irq() above.
- * If we didn't find a mapping for the interrupt,
- * disable it in order to avoid a system hang caused
- * by an interrupt storm.
+ * If the line is not an irq, disable it in order to
+ * avoid a system hang caused by an interrupt storm.
*/
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
regval = readl(regs + i);
- if (irq == 0) {
- regval &= ~BIT(INTERRUPT_ENABLE_OFF);
+ if (!gpiochip_line_is_irq(gc, irqnr + i)) {
+ regval &= ~BIT(INTERRUPT_MASK_OFF);
dev_dbg(&gpio_dev->pdev->dev,
"Disabling spurious GPIO IRQ %d\n",
irqnr + i);
+ } else {
+ ret = true;
}
writel(regval, regs + i);
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
- ret = true;
}
}
/* did not cause wake on resume context for shared IRQ */
@@ -870,34 +877,6 @@ static const struct pinconf_ops amd_pinconf_ops = {
.pin_config_group_set = amd_pinconf_group_set,
};
-static void amd_gpio_irq_init(struct amd_gpio *gpio_dev)
-{
- struct pinctrl_desc *desc = gpio_dev->pctrl->desc;
- unsigned long flags;
- u32 pin_reg, mask;
- int i;
-
- mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3) |
- BIT(INTERRUPT_MASK_OFF) | BIT(INTERRUPT_ENABLE_OFF) |
- BIT(WAKE_CNTRL_OFF_S4);
-
- for (i = 0; i < desc->npins; i++) {
- int pin = desc->pins[i].number;
- const struct pin_desc *pd = pin_desc_get(gpio_dev->pctrl, pin);
-
- if (!pd)
- continue;
-
- raw_spin_lock_irqsave(&gpio_dev->lock, flags);
-
- pin_reg = readl(gpio_dev->base + i * 4);
- pin_reg &= ~mask;
- writel(pin_reg, gpio_dev->base + i * 4);
-
- raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
- }
-}
-
#ifdef CONFIG_PM_SLEEP
static bool amd_gpio_should_save(struct amd_gpio *gpio_dev, unsigned int pin)
{
@@ -1135,9 +1114,6 @@ static int amd_gpio_probe(struct platform_device *pdev)
return PTR_ERR(gpio_dev->pctrl);
}
- /* Disable and mask interrupts */
- amd_gpio_irq_init(gpio_dev);
-
girq = &gpio_dev->gc.irq;
gpio_irq_chip_set_chip(girq, &amd_gpio_irqchip);
/* This will let us handle the parent IRQ in the driver */
diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h
index 81ae8319a1f0..1cf2d06bbd8c 100644
--- a/drivers/pinctrl/pinctrl-amd.h
+++ b/drivers/pinctrl/pinctrl-amd.h
@@ -17,6 +17,7 @@
#define AMD_GPIO_PINS_BANK3 32
#define WAKE_INT_MASTER_REG 0xfc
+#define INTERNAL_GPIO0_DEBOUNCE (1 << 15)
#define EOI_MASK (1 << 29)
#define WAKE_INT_STATUS_REG0 0x2f8
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index 2fe40acb6a3e..5d360ba3abc2 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -762,6 +762,11 @@ static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev,
return -EINVAL;
arg = 1;
break;
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ if (res & ATMEL_PIO_OPD_MASK)
+ return -EINVAL;
+ arg = 1;
+ break;
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
if (!(res & ATMEL_PIO_SCHMITT_MASK))
return -EINVAL;
@@ -827,10 +832,10 @@ static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
conf &= (~ATMEL_PIO_PUEN_MASK);
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
- if (arg == 0)
- conf &= (~ATMEL_PIO_OPD_MASK);
- else
- conf |= ATMEL_PIO_OPD_MASK;
+ conf |= ATMEL_PIO_OPD_MASK;
+ break;
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ conf &= ~ATMEL_PIO_OPD_MASK;
break;
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
if (arg == 0)
@@ -948,6 +953,8 @@ static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev,
seq_printf(s, "%s ", "debounce");
if (conf & ATMEL_PIO_OPD_MASK)
seq_printf(s, "%s ", "open-drain");
+ else
+ seq_printf(s, "%s ", "push-pull");
if (conf & ATMEL_PIO_SCHMITT_MASK)
seq_printf(s, "%s ", "schmitt");
if (atmel_pioctrl->slew_rate_support && (conf & ATMEL_PIO_SR_MASK))
@@ -1146,6 +1153,8 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
/* Pin naming convention: P(bank_name)(bank_pin_number). */
pin_desc[i].name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "P%c%u",
bank + 'A', line);
+ if (!pin_desc[i].name)
+ return -ENOMEM;
group->name = group_names[i] = pin_desc[i].name;
group->pin = pin_desc[i].number;
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 871209c24153..39956d821ad7 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -1389,8 +1389,8 @@ static int at91_pinctrl_probe(struct platform_device *pdev)
char **names;
names = devm_kasprintf_strarray(dev, "pio", MAX_NB_GPIO_PER_BANK);
- if (!names)
- return -ENOMEM;
+ if (IS_ERR(names))
+ return PTR_ERR(names);
for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) {
char *name = names[j];
@@ -1870,8 +1870,8 @@ static int at91_gpio_probe(struct platform_device *pdev)
}
names = devm_kasprintf_strarray(dev, "pio", chip->ngpio);
- if (!names)
- return -ENOMEM;
+ if (IS_ERR(names))
+ return PTR_ERR(names);
for (i = 0; i < chip->ngpio; i++)
strreplace(names[i], '-', alias_idx + 'A');
diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c
index 0bc1b381a2b8..b3ba25435c34 100644
--- a/drivers/pinctrl/pinctrl-axp209.c
+++ b/drivers/pinctrl/pinctrl-axp209.c
@@ -30,6 +30,11 @@
#define AXP20X_GPIO_FUNCTION_OUT_HIGH 1
#define AXP20X_GPIO_FUNCTION_INPUT 2
+#define AXP20X_GPIO3_FUNCTIONS GENMASK(2, 1)
+#define AXP20X_GPIO3_FUNCTION_OUT_LOW 0
+#define AXP20X_GPIO3_FUNCTION_OUT_HIGH 2
+#define AXP20X_GPIO3_FUNCTION_INPUT 4
+
#define AXP20X_FUNC_GPIO_OUT 0
#define AXP20X_FUNC_GPIO_IN 1
#define AXP20X_FUNC_LDO 2
@@ -73,6 +78,7 @@ static const struct pinctrl_pin_desc axp209_pins[] = {
PINCTRL_PIN(0, "GPIO0"),
PINCTRL_PIN(1, "GPIO1"),
PINCTRL_PIN(2, "GPIO2"),
+ PINCTRL_PIN(3, "GPIO3"),
};
static const struct pinctrl_pin_desc axp22x_pins[] = {
@@ -130,6 +136,14 @@ static int axp20x_gpio_get(struct gpio_chip *chip, unsigned int offset)
unsigned int val;
int ret;
+ /* AXP209 has GPIO3 status sharing the settings register */
+ if (offset == 3) {
+ ret = regmap_read(pctl->regmap, AXP20X_GPIO3_CTRL, &val);
+ if (ret)
+ return ret;
+ return !!(val & BIT(0));
+ }
+
ret = regmap_read(pctl->regmap, AXP20X_GPIO20_SS, &val);
if (ret)
return ret;
@@ -144,6 +158,17 @@ static int axp20x_gpio_get_direction(struct gpio_chip *chip,
unsigned int val;
int reg, ret;
+ /* AXP209 GPIO3 settings have a different layout */
+ if (offset == 3) {
+ ret = regmap_read(pctl->regmap, AXP20X_GPIO3_CTRL, &val);
+ if (ret)
+ return ret;
+ if (val & AXP20X_GPIO3_FUNCTION_INPUT)
+ return GPIO_LINE_DIRECTION_IN;
+
+ return GPIO_LINE_DIRECTION_OUT;
+ }
+
reg = axp20x_gpio_get_reg(offset);
if (reg < 0)
return reg;
@@ -184,6 +209,15 @@ static void axp20x_gpio_set(struct gpio_chip *chip, unsigned int offset,
struct axp20x_pctl *pctl = gpiochip_get_data(chip);
int reg;
+ /* AXP209 has GPIO3 status sharing the settings register */
+ if (offset == 3) {
+ regmap_update_bits(pctl->regmap, AXP20X_GPIO3_CTRL,
+ AXP20X_GPIO3_FUNCTIONS,
+ value ? AXP20X_GPIO3_FUNCTION_OUT_HIGH :
+ AXP20X_GPIO3_FUNCTION_OUT_LOW);
+ return;
+ }
+
reg = axp20x_gpio_get_reg(offset);
if (reg < 0)
return;
@@ -200,6 +234,14 @@ static int axp20x_pmx_set(struct pinctrl_dev *pctldev, unsigned int offset,
struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
int reg;
+ /* AXP209 GPIO3 settings have a different layout */
+ if (offset == 3) {
+ return regmap_update_bits(pctl->regmap, AXP20X_GPIO3_CTRL,
+ AXP20X_GPIO3_FUNCTIONS,
+ config == AXP20X_MUX_GPIO_OUT ? AXP20X_GPIO3_FUNCTION_OUT_LOW :
+ AXP20X_GPIO3_FUNCTION_INPUT);
+ }
+
reg = axp20x_gpio_get_reg(offset);
if (reg < 0)
return reg;
diff --git a/drivers/pinctrl/pinctrl-cy8c95x0.c b/drivers/pinctrl/pinctrl-cy8c95x0.c
index 564fbaabcdb8..2ecc96691c55 100644
--- a/drivers/pinctrl/pinctrl-cy8c95x0.c
+++ b/drivers/pinctrl/pinctrl-cy8c95x0.c
@@ -1442,7 +1442,7 @@ static struct i2c_driver cy8c95x0_driver = {
.of_match_table = cy8c95x0_dt_ids,
.acpi_match_table = cy8c95x0_acpi_ids,
},
- .probe_new = cy8c95x0_probe,
+ .probe = cy8c95x0_probe,
.remove = cy8c95x0_remove,
.id_table = cy8c95x0_id,
.detect = cy8c95x0_detect,
diff --git a/drivers/pinctrl/pinctrl-falcon.c b/drivers/pinctrl/pinctrl-falcon.c
index 2eab14f86fa3..0bf9ffbcc79f 100644
--- a/drivers/pinctrl/pinctrl-falcon.c
+++ b/drivers/pinctrl/pinctrl-falcon.c
@@ -14,7 +14,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
-#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/seq_file.h>
diff --git a/drivers/pinctrl/pinctrl-mcp23s08_i2c.c b/drivers/pinctrl/pinctrl-mcp23s08_i2c.c
index b635c5737e0c..3dd1bd8e73eb 100644
--- a/drivers/pinctrl/pinctrl-mcp23s08_i2c.c
+++ b/drivers/pinctrl/pinctrl-mcp23s08_i2c.c
@@ -101,7 +101,7 @@ static struct i2c_driver mcp230xx_driver = {
.name = "mcp230xx",
.of_match_table = mcp23s08_i2c_of_match,
},
- .probe_new = mcp230xx_probe,
+ .probe = mcp230xx_probe,
.id_table = mcp230xx_id,
};
diff --git a/drivers/pinctrl/pinctrl-microchip-sgpio.c b/drivers/pinctrl/pinctrl-microchip-sgpio.c
index 4794602316e7..a60db93b61b1 100644
--- a/drivers/pinctrl/pinctrl-microchip-sgpio.c
+++ b/drivers/pinctrl/pinctrl-microchip-sgpio.c
@@ -719,8 +719,6 @@ static void microchip_sgpio_irq_ack(struct irq_data *data)
static int microchip_sgpio_irq_set_type(struct irq_data *data, unsigned int type)
{
- type &= IRQ_TYPE_SENSE_MASK;
-
switch (type) {
case IRQ_TYPE_EDGE_BOTH:
irq_set_handler_locked(data, handle_edge_irq);
@@ -818,6 +816,9 @@ static int microchip_sgpio_register_bank(struct device *dev,
pctl_desc->name = devm_kasprintf(dev, GFP_KERNEL, "%s-%sput",
dev_name(dev),
bank->is_input ? "in" : "out");
+ if (!pctl_desc->name)
+ return -ENOMEM;
+
pctl_desc->pctlops = &sgpio_pctl_ops;
pctl_desc->pmxops = &sgpio_pmx_ops;
pctl_desc->confops = &sgpio_confops;
diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c
index 7632ffc3946f..35faea8dfb0b 100644
--- a/drivers/pinctrl/pinctrl-sx150x.c
+++ b/drivers/pinctrl/pinctrl-sx150x.c
@@ -1262,7 +1262,7 @@ static struct i2c_driver sx150x_driver = {
.name = "sx150x-pinctrl",
.of_match_table = sx150x_of_match,
},
- .probe_new = sx150x_probe,
+ .probe = sx150x_probe,
.id_table = sx150x_id,
};
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
index 858abb23b337..cf0383f575d9 100644
--- a/drivers/pinctrl/pinctrl-xway.c
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -8,11 +8,11 @@
*/
#include <linux/err.h>
+#include <linux/gpio/driver.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
-#include <linux/of_gpio.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/device.h>
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 021382632608..82c750a31952 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -677,7 +677,6 @@ void pinmux_show_setting(struct seq_file *s,
DEFINE_SHOW_ATTRIBUTE(pinmux_functions);
DEFINE_SHOW_ATTRIBUTE(pinmux_pins);
-#define PINMUX_SELECT_MAX 128
static ssize_t pinmux_select(struct file *file, const char __user *user_buf,
size_t len, loff_t *ppos)
{
@@ -689,17 +688,9 @@ static ssize_t pinmux_select(struct file *file, const char __user *user_buf,
unsigned int num_groups;
int fsel, gsel, ret;
- if (len > PINMUX_SELECT_MAX)
- return -ENOMEM;
-
- buf = kzalloc(PINMUX_SELECT_MAX, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- ret = strncpy_from_user(buf, user_buf, PINMUX_SELECT_MAX);
- if (ret < 0)
- goto exit_free_buf;
- buf[len-1] = '\0';
+ buf = memdup_user_nul(user_buf, len);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
/* remove leading and trailing spaces of input buffer */
gname = strstrip(buf);
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index e52cfab8d5ae..634c75336983 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -4,6 +4,8 @@ if (ARCH_QCOM || COMPILE_TEST)
config PINCTRL_MSM
tristate "Qualcomm core pin controller driver"
depends on GPIOLIB
+ # OF for pinconf_generic_dt_node_to_map_group() from GENERIC_PINCONF
+ depends on OF
select QCOM_SCM
select PINMUX
select PINCONF
@@ -12,231 +14,7 @@ config PINCTRL_MSM
select IRQ_DOMAIN_HIERARCHY
select IRQ_FASTEOI_HIERARCHY_HANDLERS
-config PINCTRL_APQ8064
- tristate "Qualcomm APQ8064 pin controller driver"
- depends on OF
- depends on ARM || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm APQ8064 platform.
-
-config PINCTRL_APQ8084
- tristate "Qualcomm APQ8084 pin controller driver"
- depends on OF
- depends on ARM || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm APQ8084 platform.
-
-config PINCTRL_IPQ4019
- tristate "Qualcomm IPQ4019 pin controller driver"
- depends on OF
- depends on ARM || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm IPQ4019 platform.
-
-config PINCTRL_IPQ8064
- tristate "Qualcomm IPQ8064 pin controller driver"
- depends on OF
- depends on ARM || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm IPQ8064 platform.
-
-config PINCTRL_IPQ5332
- tristate "Qualcomm Technologies Inc IPQ5332 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc IPQ5332 platform.
-
-config PINCTRL_IPQ8074
- tristate "Qualcomm Technologies, Inc. IPQ8074 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for
- the Qualcomm Technologies Inc. TLMM block found on the
- Qualcomm Technologies Inc. IPQ8074 platform. Select this for
- IPQ8074.
-
-config PINCTRL_IPQ6018
- tristate "Qualcomm Technologies, Inc. IPQ6018 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for
- the Qualcomm Technologies Inc. TLMM block found on the
- Qualcomm Technologies Inc. IPQ6018 platform. Select this for
- IPQ6018.
-
-config PINCTRL_IPQ9574
- tristate "Qualcomm Technologies, Inc. IPQ9574 pin controller driver"
- depends on OF || COMPILE_TEST
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for
- the Qualcomm Technologies Inc. TLMM block found on the
- Qualcomm Technologies Inc. IPQ9574 platform. Select this for
- IPQ9574.
-
-config PINCTRL_MSM8226
- tristate "Qualcomm 8226 pin controller driver"
- depends on OF
- depends on ARM || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc MSM8226 platform.
-
-config PINCTRL_MSM8660
- tristate "Qualcomm 8660 pin controller driver"
- depends on OF
- depends on ARM || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm 8660 platform.
-
-config PINCTRL_MSM8960
- tristate "Qualcomm 8960 pin controller driver"
- depends on OF
- depends on ARM || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm 8960 platform.
-
-config PINCTRL_MDM9607
- tristate "Qualcomm 9607 pin controller driver"
- depends on GPIOLIB && OF
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm 9607 platform.
-
-config PINCTRL_MDM9615
- tristate "Qualcomm 9615 pin controller driver"
- depends on OF
- depends on ARM || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm 9615 platform.
-
-config PINCTRL_MSM8X74
- tristate "Qualcomm 8x74 pin controller driver"
- depends on OF
- depends on ARM || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm 8974 platform.
-
-config PINCTRL_MSM8909
- tristate "Qualcomm 8909 pin controller driver"
- depends on OF
- depends on ARM || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found on the Qualcomm MSM8909 platform.
-
-config PINCTRL_MSM8916
- tristate "Qualcomm 8916 pin controller driver"
- depends on OF
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found on the Qualcomm 8916 platform.
-
-config PINCTRL_MSM8953
- tristate "Qualcomm 8953 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found on the Qualcomm MSM8953 platform.
- The Qualcomm APQ8053, SDM450, SDM632 platforms are also
- supported by this driver.
-
-config PINCTRL_MSM8976
- tristate "Qualcomm 8976 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found on the Qualcomm MSM8976 platform.
- The Qualcomm MSM8956, APQ8056, APQ8076 platforms are also
- supported by this driver.
-
-config PINCTRL_MSM8994
- tristate "Qualcomm 8994 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm 8994 platform. The
- Qualcomm 8992 platform is also supported by this driver.
-
-config PINCTRL_MSM8996
- tristate "Qualcomm MSM8996 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm MSM8996 platform.
-
-config PINCTRL_MSM8998
- tristate "Qualcomm MSM8998 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm MSM8998 platform.
-
-config PINCTRL_QCM2290
- tristate "Qualcomm QCM2290 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- TLMM block found in the Qualcomm QCM2290 platform.
-
-config PINCTRL_QCS404
- tristate "Qualcomm QCS404 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- TLMM block found in the Qualcomm QCS404 platform.
-
-config PINCTRL_QDF2XXX
- tristate "Qualcomm Technologies QDF2xxx pin controller driver"
- depends on ACPI
- depends on PINCTRL_MSM
- help
- This is the GPIO driver for the TLMM block found on the
- Qualcomm Technologies QDF2xxx SOCs.
+source "drivers/pinctrl/qcom/Kconfig.msm"
config PINCTRL_QCOM_SPMI_PMIC
tristate "Qualcomm SPMI PMIC pin controller driver"
@@ -245,7 +23,7 @@ config PINCTRL_QCOM_SPMI_PMIC
select PINMUX
select PINCONF
select GENERIC_PINCONF
- select GPIOLIB
+ select GPIOLIB
select GPIOLIB_IRQCHIP
select IRQ_DOMAIN_HIERARCHY
help
@@ -260,7 +38,7 @@ config PINCTRL_QCOM_SSBI_PMIC
select PINMUX
select PINCONF
select GENERIC_PINCONF
- select GPIOLIB
+ select GPIOLIB
select GPIOLIB_IRQCHIP
select IRQ_DOMAIN_HIERARCHY
help
@@ -269,48 +47,20 @@ config PINCTRL_QCOM_SSBI_PMIC
which are using SSBI for communication with SoC. Example PMIC's
devices are pm8058 and pm8921.
-config PINCTRL_QDU1000
- tristate "Qualcomm Tehcnologies Inc QDU1000/QRU1000 pin controller driver"
- depends on GPIOLIB && OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf, and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc QDU1000 and QRU1000 platforms.
-
-config PINCTRL_SA8775P
- tristate "Qualcomm Technologies Inc SA8775P pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux and pinconf driver for the Qualcomm
- TLMM block found on the Qualcomm SA8775P platforms.
-
-config PINCTRL_SC7180
- tristate "Qualcomm Technologies Inc SC7180 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SC7180 platform.
-
-config PINCTRL_SC7280
- tristate "Qualcomm Technologies Inc SC7280 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
+config PINCTRL_LPASS_LPI
+ tristate "Qualcomm Technologies Inc LPASS LPI pin controller driver"
+ select PINMUX
+ select PINCONF
+ select GENERIC_PINCONF
+ select GENERIC_PINCTRL_GROUPS
+ depends on GPIOLIB
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SC7280 platform.
+ Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI
+ (Low Power Island) found on the Qualcomm Technologies Inc SoCs.
config PINCTRL_SC7280_LPASS_LPI
tristate "Qualcomm Technologies Inc SC7280 LPASS LPI pin controller driver"
- depends on GPIOLIB
depends on ARM64 || COMPILE_TEST
depends on PINCTRL_LPASS_LPI
help
@@ -318,149 +68,8 @@ config PINCTRL_SC7280_LPASS_LPI
Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI
(Low Power Island) found on the Qualcomm Technologies Inc SC7280 platform.
-config PINCTRL_SC8180X
- tristate "Qualcomm Technologies Inc SC8180x pin controller driver"
- depends on (OF || ACPI)
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SC8180x platform.
-
-config PINCTRL_SC8280XP
- tristate "Qualcomm Technologies Inc SC8280xp pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SC8280xp platform.
-
-config PINCTRL_SDM660
- tristate "Qualcomm Technologies Inc SDM660 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SDM660 platform.
-
-config PINCTRL_SDM670
- tristate "Qualcomm Technologies Inc SDM670 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SDM670 platform.
-
-config PINCTRL_SDM845
- tristate "Qualcomm Technologies Inc SDM845 pin controller driver"
- depends on (OF || ACPI)
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SDM845 platform.
-
-config PINCTRL_SDX55
- tristate "Qualcomm Technologies Inc SDX55 pin controller driver"
- depends on OF
- depends on ARM || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SDX55 platform.
-
-config PINCTRL_SM6115
- tristate "Qualcomm Technologies Inc SM6115,SM4250 pin controller driver"
- depends on GPIOLIB && OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SM6115 and SM4250 platforms.
-
-config PINCTRL_SM6125
- tristate "Qualcomm Technologies Inc SM6125 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SM6125 platform.
-
-config PINCTRL_SM6350
- tristate "Qualcomm Technologies Inc SM6350 pin controller driver"
- depends on GPIOLIB && OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SM6350 platform.
-
-config PINCTRL_SM6375
- tristate "Qualcomm Technologies Inc SM6375 pin controller driver"
- depends on GPIOLIB && OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SM6375 platform.
-
-config PINCTRL_SDX65
- tristate "Qualcomm Technologies Inc SDX65 pin controller driver"
- depends on GPIOLIB && OF
- depends on ARM || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SDX65 platform.
-
-config PINCTRL_SM7150
- tristate "Qualcomm Technologies Inc SM7150 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SM7150 platform.
-
-config PINCTRL_SM8150
- tristate "Qualcomm Technologies Inc SM8150 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SM8150 platform.
-
-config PINCTRL_SM8250
- tristate "Qualcomm Technologies Inc SM8250 pin controller driver"
- depends on OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SM8250 platform.
-
config PINCTRL_SM8250_LPASS_LPI
tristate "Qualcomm Technologies Inc SM8250 LPASS LPI pin controller driver"
- depends on GPIOLIB
depends on ARM64 || COMPILE_TEST
depends on PINCTRL_LPASS_LPI
help
@@ -468,28 +77,8 @@ config PINCTRL_SM8250_LPASS_LPI
Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI
(Low Power Island) found on the Qualcomm Technologies Inc SM8250 platform.
-config PINCTRL_SM8350
- tristate "Qualcomm Technologies Inc SM8350 pin controller driver"
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SM8350 platform.
-
-config PINCTRL_SM8450
- tristate "Qualcomm Technologies Inc SM8450 pin controller driver"
- depends on GPIOLIB && OF
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SM8450 platform.
-
config PINCTRL_SM8450_LPASS_LPI
tristate "Qualcomm Technologies Inc SM8450 LPASS LPI pin controller driver"
- depends on GPIOLIB
depends on ARM64 || COMPILE_TEST
depends on PINCTRL_LPASS_LPI
help
@@ -499,7 +88,6 @@ config PINCTRL_SM8450_LPASS_LPI
config PINCTRL_SC8280XP_LPASS_LPI
tristate "Qualcomm Technologies Inc SC8280XP LPASS LPI pin controller driver"
- depends on GPIOLIB
depends on ARM64 || COMPILE_TEST
depends on PINCTRL_LPASS_LPI
help
@@ -507,19 +95,8 @@ config PINCTRL_SC8280XP_LPASS_LPI
Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI
(Low Power Island) found on the Qualcomm Technologies Inc SC8280XP platform.
-config PINCTRL_SM8550
- tristate "Qualcomm Technologies Inc SM8550 pin controller driver"
- depends on GPIOLIB
- depends on ARM64 || COMPILE_TEST
- depends on PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc TLMM block found on the Qualcomm
- Technologies Inc SM8550 platform.
-
config PINCTRL_SM8550_LPASS_LPI
tristate "Qualcomm Technologies Inc SM8550 LPASS LPI pin controller driver"
- depends on GPIOLIB
depends on ARM64 || COMPILE_TEST
depends on PINCTRL_LPASS_LPI
help
@@ -528,16 +105,4 @@ config PINCTRL_SM8550_LPASS_LPI
(Low Power Island) found on the Qualcomm Technologies Inc SM8550
platform.
-config PINCTRL_LPASS_LPI
- tristate "Qualcomm Technologies Inc LPASS LPI pin controller driver"
- select PINMUX
- select PINCONF
- select GENERIC_PINCONF
- select GENERIC_PINCTRL_GROUPS
- depends on GPIOLIB
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI
- (Low Power Island) found on the Qualcomm Technologies Inc SoCs.
-
endif
diff --git a/drivers/pinctrl/qcom/Kconfig.msm b/drivers/pinctrl/qcom/Kconfig.msm
new file mode 100644
index 000000000000..01dd7b134354
--- /dev/null
+++ b/drivers/pinctrl/qcom/Kconfig.msm
@@ -0,0 +1,369 @@
+# SPDX-License-Identifier: GPL-2.0-only
+if PINCTRL_MSM
+
+config PINCTRL_APQ8064
+ tristate "Qualcomm APQ8064 pin controller driver"
+ depends on ARM || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm APQ8064 platform.
+
+config PINCTRL_APQ8084
+ tristate "Qualcomm APQ8084 pin controller driver"
+ depends on ARM || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm APQ8084 platform.
+
+config PINCTRL_IPQ4019
+ tristate "Qualcomm IPQ4019 pin controller driver"
+ depends on ARM || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm IPQ4019 platform.
+
+config PINCTRL_IPQ5018
+ tristate "Qualcomm Technologies, Inc. IPQ5018 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for
+ the Qualcomm Technologies Inc. TLMM block found on the
+ Qualcomm Technologies Inc. IPQ5018 platform. Select this for
+ IPQ5018.
+
+config PINCTRL_IPQ8064
+ tristate "Qualcomm IPQ8064 pin controller driver"
+ depends on ARM || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm IPQ8064 platform.
+
+config PINCTRL_IPQ5332
+ tristate "Qualcomm Technologies Inc IPQ5332 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc IPQ5332 platform.
+
+config PINCTRL_IPQ8074
+ tristate "Qualcomm Technologies, Inc. IPQ8074 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for
+ the Qualcomm Technologies Inc. TLMM block found on the
+ Qualcomm Technologies Inc. IPQ8074 platform. Select this for
+ IPQ8074.
+
+config PINCTRL_IPQ6018
+ tristate "Qualcomm Technologies, Inc. IPQ6018 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for
+ the Qualcomm Technologies Inc. TLMM block found on the
+ Qualcomm Technologies Inc. IPQ6018 platform. Select this for
+ IPQ6018.
+
+config PINCTRL_IPQ9574
+ tristate "Qualcomm Technologies, Inc. IPQ9574 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for
+ the Qualcomm Technologies Inc. TLMM block found on the
+ Qualcomm Technologies Inc. IPQ9574 platform. Select this for
+ IPQ9574.
+
+config PINCTRL_MSM8226
+ tristate "Qualcomm 8226 pin controller driver"
+ depends on ARM || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc MSM8226 platform.
+
+config PINCTRL_MSM8660
+ tristate "Qualcomm 8660 pin controller driver"
+ depends on ARM || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm 8660 platform.
+
+config PINCTRL_MSM8960
+ tristate "Qualcomm 8960 pin controller driver"
+ depends on ARM || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm 8960 platform.
+
+config PINCTRL_MDM9607
+ tristate "Qualcomm 9607 pin controller driver"
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm 9607 platform.
+
+config PINCTRL_MDM9615
+ tristate "Qualcomm 9615 pin controller driver"
+ depends on ARM || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm 9615 platform.
+
+config PINCTRL_MSM8X74
+ tristate "Qualcomm 8x74 pin controller driver"
+ depends on ARM || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm 8974 platform.
+
+config PINCTRL_MSM8909
+ tristate "Qualcomm 8909 pin controller driver"
+ depends on ARM || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found on the Qualcomm MSM8909 platform.
+
+config PINCTRL_MSM8916
+ tristate "Qualcomm 8916 pin controller driver"
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found on the Qualcomm 8916 platform.
+
+config PINCTRL_MSM8953
+ tristate "Qualcomm 8953 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found on the Qualcomm MSM8953 platform.
+ The Qualcomm APQ8053, SDM450, SDM632 platforms are also
+ supported by this driver.
+
+config PINCTRL_MSM8976
+ tristate "Qualcomm 8976 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found on the Qualcomm MSM8976 platform.
+ The Qualcomm MSM8956, APQ8056, APQ8076 platforms are also
+ supported by this driver.
+
+config PINCTRL_MSM8994
+ tristate "Qualcomm 8994 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm 8994 platform. The
+ Qualcomm 8992 platform is also supported by this driver.
+
+config PINCTRL_MSM8996
+ tristate "Qualcomm MSM8996 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm MSM8996 platform.
+
+config PINCTRL_MSM8998
+ tristate "Qualcomm MSM8998 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm MSM8998 platform.
+
+config PINCTRL_QCM2290
+ tristate "Qualcomm QCM2290 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ TLMM block found in the Qualcomm QCM2290 platform.
+
+config PINCTRL_QCS404
+ tristate "Qualcomm QCS404 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ TLMM block found in the Qualcomm QCS404 platform.
+
+config PINCTRL_QDF2XXX
+ tristate "Qualcomm Technologies QDF2xxx pin controller driver"
+ depends on ACPI
+ help
+ This is the GPIO driver for the TLMM block found on the
+ Qualcomm Technologies QDF2xxx SOCs.
+
+config PINCTRL_QDU1000
+ tristate "Qualcomm Technologies Inc QDU1000/QRU1000 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf, and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc QDU1000 and QRU1000 platforms.
+
+config PINCTRL_SA8775P
+ tristate "Qualcomm Technologies Inc SA8775P pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux and pinconf driver for the Qualcomm
+ TLMM block found on the Qualcomm SA8775P platforms.
+
+config PINCTRL_SC7180
+ tristate "Qualcomm Technologies Inc SC7180 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SC7180 platform.
+
+config PINCTRL_SC7280
+ tristate "Qualcomm Technologies Inc SC7280 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SC7280 platform.
+
+config PINCTRL_SC8180X
+ tristate "Qualcomm Technologies Inc SC8180x pin controller driver"
+ depends on (OF || ACPI)
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SC8180x platform.
+
+config PINCTRL_SC8280XP
+ tristate "Qualcomm Technologies Inc SC8280xp pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SC8280xp platform.
+
+config PINCTRL_SDM660
+ tristate "Qualcomm Technologies Inc SDM660 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SDM660 platform.
+
+config PINCTRL_SDM670
+ tristate "Qualcomm Technologies Inc SDM670 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SDM670 platform.
+
+config PINCTRL_SDM845
+ tristate "Qualcomm Technologies Inc SDM845 pin controller driver"
+ depends on (OF || ACPI)
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SDM845 platform.
+
+config PINCTRL_SDX55
+ tristate "Qualcomm Technologies Inc SDX55 pin controller driver"
+ depends on ARM || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SDX55 platform.
+
+config PINCTRL_SDX65
+ tristate "Qualcomm Technologies Inc SDX65 pin controller driver"
+ depends on ARM || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SDX65 platform.
+
+config PINCTRL_SDX75
+ tristate "Qualcomm Technologies Inc SDX75 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SDX75 platform.
+
+config PINCTRL_SM6115
+ tristate "Qualcomm Technologies Inc SM6115,SM4250 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM6115 and SM4250 platforms.
+
+config PINCTRL_SM6125
+ tristate "Qualcomm Technologies Inc SM6125 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM6125 platform.
+
+config PINCTRL_SM6350
+ tristate "Qualcomm Technologies Inc SM6350 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM6350 platform.
+
+config PINCTRL_SM6375
+ tristate "Qualcomm Technologies Inc SM6375 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM6375 platform.
+
+config PINCTRL_SM7150
+ tristate "Qualcomm Technologies Inc SM7150 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM7150 platform.
+
+config PINCTRL_SM8150
+ tristate "Qualcomm Technologies Inc SM8150 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM8150 platform.
+
+config PINCTRL_SM8250
+ tristate "Qualcomm Technologies Inc SM8250 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM8250 platform.
+
+config PINCTRL_SM8350
+ tristate "Qualcomm Technologies Inc SM8350 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM8350 platform.
+
+config PINCTRL_SM8450
+ tristate "Qualcomm Technologies Inc SM8450 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM8450 platform.
+
+config PINCTRL_SM8550
+ tristate "Qualcomm Technologies Inc SM8550 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM8550 platform.
+
+endif
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 521b021b74ba..426ddbf35f32 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o
obj-$(CONFIG_PINCTRL_APQ8064) += pinctrl-apq8064.o
obj-$(CONFIG_PINCTRL_APQ8084) += pinctrl-apq8084.o
obj-$(CONFIG_PINCTRL_IPQ4019) += pinctrl-ipq4019.o
+obj-$(CONFIG_PINCTRL_IPQ5018) += pinctrl-ipq5018.o
obj-$(CONFIG_PINCTRL_IPQ8064) += pinctrl-ipq8064.o
obj-$(CONFIG_PINCTRL_IPQ5332) += pinctrl-ipq5332.o
obj-$(CONFIG_PINCTRL_IPQ8074) += pinctrl-ipq8074.o
@@ -40,11 +41,12 @@ obj-$(CONFIG_PINCTRL_SDM660) += pinctrl-sdm660.o
obj-$(CONFIG_PINCTRL_SDM670) += pinctrl-sdm670.o
obj-$(CONFIG_PINCTRL_SDM845) += pinctrl-sdm845.o
obj-$(CONFIG_PINCTRL_SDX55) += pinctrl-sdx55.o
+obj-$(CONFIG_PINCTRL_SDX65) += pinctrl-sdx65.o
+obj-$(CONFIG_PINCTRL_SDX75) += pinctrl-sdx75.o
obj-$(CONFIG_PINCTRL_SM6115) += pinctrl-sm6115.o
obj-$(CONFIG_PINCTRL_SM6125) += pinctrl-sm6125.o
obj-$(CONFIG_PINCTRL_SM6350) += pinctrl-sm6350.o
obj-$(CONFIG_PINCTRL_SM6375) += pinctrl-sm6375.o
-obj-$(CONFIG_PINCTRL_SDX65) += pinctrl-sdx65.o
obj-$(CONFIG_PINCTRL_SM7150) += pinctrl-sm7150.o
obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o
obj-$(CONFIG_PINCTRL_SM8250) += pinctrl-sm8250.o
diff --git a/drivers/pinctrl/qcom/pinctrl-apq8064.c b/drivers/pinctrl/qcom/pinctrl-apq8064.c
index d40ad4ea3819..20c3b9025044 100644
--- a/drivers/pinctrl/qcom/pinctrl-apq8064.c
+++ b/drivers/pinctrl/qcom/pinctrl-apq8064.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -209,18 +208,11 @@ static const unsigned int sdc3_clk_pins[] = { 93 };
static const unsigned int sdc3_cmd_pins[] = { 94 };
static const unsigned int sdc3_data_pins[] = { 95 };
-#define FUNCTION(fname) \
- [APQ_MUX_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
APQ_MUX_gpio, \
APQ_MUX_##f1, \
@@ -259,9 +251,9 @@ static const unsigned int sdc3_data_pins[] = { 95 };
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -464,48 +456,48 @@ static const char * const usb2_hsic_groups[] = {
"gpio88", "gpio89"
};
-static const struct msm_function apq8064_functions[] = {
- FUNCTION(cam_mclk),
- FUNCTION(codec_mic_i2s),
- FUNCTION(codec_spkr_i2s),
- FUNCTION(gp_clk_0a),
- FUNCTION(gp_clk_0b),
- FUNCTION(gp_clk_1a),
- FUNCTION(gp_clk_1b),
- FUNCTION(gp_clk_2a),
- FUNCTION(gp_clk_2b),
- FUNCTION(gpio),
- FUNCTION(gsbi1),
- FUNCTION(gsbi2),
- FUNCTION(gsbi3),
- FUNCTION(gsbi4),
- FUNCTION(gsbi4_cam_i2c),
- FUNCTION(gsbi5),
- FUNCTION(gsbi5_spi_cs1),
- FUNCTION(gsbi5_spi_cs2),
- FUNCTION(gsbi5_spi_cs3),
- FUNCTION(gsbi6),
- FUNCTION(gsbi6_spi_cs1),
- FUNCTION(gsbi6_spi_cs2),
- FUNCTION(gsbi6_spi_cs3),
- FUNCTION(gsbi7),
- FUNCTION(gsbi7_spi_cs1),
- FUNCTION(gsbi7_spi_cs2),
- FUNCTION(gsbi7_spi_cs3),
- FUNCTION(gsbi_cam_i2c),
- FUNCTION(hdmi),
- FUNCTION(mi2s),
- FUNCTION(riva_bt),
- FUNCTION(riva_fm),
- FUNCTION(riva_wlan),
- FUNCTION(sdc2),
- FUNCTION(sdc4),
- FUNCTION(slimbus),
- FUNCTION(spkr_i2s),
- FUNCTION(tsif1),
- FUNCTION(tsif2),
- FUNCTION(usb2_hsic),
- FUNCTION(ps_hold),
+static const struct pinfunction apq8064_functions[] = {
+ APQ_PIN_FUNCTION(cam_mclk),
+ APQ_PIN_FUNCTION(codec_mic_i2s),
+ APQ_PIN_FUNCTION(codec_spkr_i2s),
+ APQ_PIN_FUNCTION(gp_clk_0a),
+ APQ_PIN_FUNCTION(gp_clk_0b),
+ APQ_PIN_FUNCTION(gp_clk_1a),
+ APQ_PIN_FUNCTION(gp_clk_1b),
+ APQ_PIN_FUNCTION(gp_clk_2a),
+ APQ_PIN_FUNCTION(gp_clk_2b),
+ APQ_PIN_FUNCTION(gpio),
+ APQ_PIN_FUNCTION(gsbi1),
+ APQ_PIN_FUNCTION(gsbi2),
+ APQ_PIN_FUNCTION(gsbi3),
+ APQ_PIN_FUNCTION(gsbi4),
+ APQ_PIN_FUNCTION(gsbi4_cam_i2c),
+ APQ_PIN_FUNCTION(gsbi5),
+ APQ_PIN_FUNCTION(gsbi5_spi_cs1),
+ APQ_PIN_FUNCTION(gsbi5_spi_cs2),
+ APQ_PIN_FUNCTION(gsbi5_spi_cs3),
+ APQ_PIN_FUNCTION(gsbi6),
+ APQ_PIN_FUNCTION(gsbi6_spi_cs1),
+ APQ_PIN_FUNCTION(gsbi6_spi_cs2),
+ APQ_PIN_FUNCTION(gsbi6_spi_cs3),
+ APQ_PIN_FUNCTION(gsbi7),
+ APQ_PIN_FUNCTION(gsbi7_spi_cs1),
+ APQ_PIN_FUNCTION(gsbi7_spi_cs2),
+ APQ_PIN_FUNCTION(gsbi7_spi_cs3),
+ APQ_PIN_FUNCTION(gsbi_cam_i2c),
+ APQ_PIN_FUNCTION(hdmi),
+ APQ_PIN_FUNCTION(mi2s),
+ APQ_PIN_FUNCTION(riva_bt),
+ APQ_PIN_FUNCTION(riva_fm),
+ APQ_PIN_FUNCTION(riva_wlan),
+ APQ_PIN_FUNCTION(sdc2),
+ APQ_PIN_FUNCTION(sdc4),
+ APQ_PIN_FUNCTION(slimbus),
+ APQ_PIN_FUNCTION(spkr_i2s),
+ APQ_PIN_FUNCTION(tsif1),
+ APQ_PIN_FUNCTION(tsif2),
+ APQ_PIN_FUNCTION(usb2_hsic),
+ APQ_PIN_FUNCTION(ps_hold),
};
static const struct msm_pingroup apq8064_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-apq8084.c b/drivers/pinctrl/qcom/pinctrl-apq8084.c
index f83153a1d622..3fc0a40762b6 100644
--- a/drivers/pinctrl/qcom/pinctrl-apq8084.c
+++ b/drivers/pinctrl/qcom/pinctrl-apq8084.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -324,18 +323,11 @@ static const unsigned int sdc2_clk_pins[] = { 150 };
static const unsigned int sdc2_cmd_pins[] = { 151 };
static const unsigned int sdc2_data_pins[] = { 152 };
-#define FUNCTION(fname) \
- [APQ_MUX_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
APQ_MUX_gpio, \
APQ_MUX_##f1, \
@@ -371,9 +363,9 @@ static const unsigned int sdc2_data_pins[] = { 152 };
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -906,128 +898,128 @@ static const char * const uim_groups[] = {
static const char * const uim_batt_alarm_groups[] = {
"gpio102"
};
-static const struct msm_function apq8084_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(audio_ref),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_i2c5),
- FUNCTION(blsp_i2c6),
- FUNCTION(blsp_i2c7),
- FUNCTION(blsp_i2c8),
- FUNCTION(blsp_i2c9),
- FUNCTION(blsp_i2c10),
- FUNCTION(blsp_i2c11),
- FUNCTION(blsp_i2c12),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi1_cs1),
- FUNCTION(blsp_spi1_cs2),
- FUNCTION(blsp_spi1_cs3),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi3_cs1),
- FUNCTION(blsp_spi3_cs2),
- FUNCTION(blsp_spi3_cs3),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_spi5),
- FUNCTION(blsp_spi6),
- FUNCTION(blsp_spi7),
- FUNCTION(blsp_spi8),
- FUNCTION(blsp_spi9),
- FUNCTION(blsp_spi10),
- FUNCTION(blsp_spi10_cs1),
- FUNCTION(blsp_spi10_cs2),
- FUNCTION(blsp_spi10_cs3),
- FUNCTION(blsp_spi11),
- FUNCTION(blsp_spi12),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_uart3),
- FUNCTION(blsp_uart4),
- FUNCTION(blsp_uart5),
- FUNCTION(blsp_uart6),
- FUNCTION(blsp_uart7),
- FUNCTION(blsp_uart8),
- FUNCTION(blsp_uart9),
- FUNCTION(blsp_uart10),
- FUNCTION(blsp_uart11),
- FUNCTION(blsp_uart12),
- FUNCTION(blsp_uim1),
- FUNCTION(blsp_uim2),
- FUNCTION(blsp_uim3),
- FUNCTION(blsp_uim4),
- FUNCTION(blsp_uim5),
- FUNCTION(blsp_uim6),
- FUNCTION(blsp_uim7),
- FUNCTION(blsp_uim8),
- FUNCTION(blsp_uim9),
- FUNCTION(blsp_uim10),
- FUNCTION(blsp_uim11),
- FUNCTION(blsp_uim12),
- FUNCTION(cam_mclk0),
- FUNCTION(cam_mclk1),
- FUNCTION(cam_mclk2),
- FUNCTION(cam_mclk3),
- FUNCTION(cci_async),
- FUNCTION(cci_async_in0),
- FUNCTION(cci_i2c0),
- FUNCTION(cci_i2c1),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(edp_hpd),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gcc_obt),
- FUNCTION(gcc_vtt),
- FUNCTION(gp_mn),
- FUNCTION(gp_pdm0),
- FUNCTION(gp_pdm1),
- FUNCTION(gp_pdm2),
- FUNCTION(gp0_clk),
- FUNCTION(gp1_clk),
- FUNCTION(gpio),
- FUNCTION(hdmi_cec),
- FUNCTION(hdmi_ddc),
- FUNCTION(hdmi_dtest),
- FUNCTION(hdmi_hpd),
- FUNCTION(hdmi_rcv),
- FUNCTION(hsic),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(mdp_vsync),
- FUNCTION(pci_e0),
- FUNCTION(pci_e0_n),
- FUNCTION(pci_e0_rst),
- FUNCTION(pci_e1),
- FUNCTION(pci_e1_rst),
- FUNCTION(pci_e1_rst_n),
- FUNCTION(pci_e1_clkreq_n),
- FUNCTION(pri_mi2s),
- FUNCTION(qua_mi2s),
- FUNCTION(sata_act),
- FUNCTION(sata_devsleep),
- FUNCTION(sata_devsleep_n),
- FUNCTION(sd_write),
- FUNCTION(sdc_emmc_mode),
- FUNCTION(sdc3),
- FUNCTION(sdc4),
- FUNCTION(sec_mi2s),
- FUNCTION(slimbus),
- FUNCTION(spdif_tx),
- FUNCTION(spkr_i2s),
- FUNCTION(spkr_i2s_ws),
- FUNCTION(spss_geni),
- FUNCTION(ter_mi2s),
- FUNCTION(tsif1),
- FUNCTION(tsif2),
- FUNCTION(uim),
- FUNCTION(uim_batt_alarm),
+static const struct pinfunction apq8084_functions[] = {
+ APQ_PIN_FUNCTION(adsp_ext),
+ APQ_PIN_FUNCTION(audio_ref),
+ APQ_PIN_FUNCTION(blsp_i2c1),
+ APQ_PIN_FUNCTION(blsp_i2c2),
+ APQ_PIN_FUNCTION(blsp_i2c3),
+ APQ_PIN_FUNCTION(blsp_i2c4),
+ APQ_PIN_FUNCTION(blsp_i2c5),
+ APQ_PIN_FUNCTION(blsp_i2c6),
+ APQ_PIN_FUNCTION(blsp_i2c7),
+ APQ_PIN_FUNCTION(blsp_i2c8),
+ APQ_PIN_FUNCTION(blsp_i2c9),
+ APQ_PIN_FUNCTION(blsp_i2c10),
+ APQ_PIN_FUNCTION(blsp_i2c11),
+ APQ_PIN_FUNCTION(blsp_i2c12),
+ APQ_PIN_FUNCTION(blsp_spi1),
+ APQ_PIN_FUNCTION(blsp_spi1_cs1),
+ APQ_PIN_FUNCTION(blsp_spi1_cs2),
+ APQ_PIN_FUNCTION(blsp_spi1_cs3),
+ APQ_PIN_FUNCTION(blsp_spi2),
+ APQ_PIN_FUNCTION(blsp_spi3),
+ APQ_PIN_FUNCTION(blsp_spi3_cs1),
+ APQ_PIN_FUNCTION(blsp_spi3_cs2),
+ APQ_PIN_FUNCTION(blsp_spi3_cs3),
+ APQ_PIN_FUNCTION(blsp_spi4),
+ APQ_PIN_FUNCTION(blsp_spi5),
+ APQ_PIN_FUNCTION(blsp_spi6),
+ APQ_PIN_FUNCTION(blsp_spi7),
+ APQ_PIN_FUNCTION(blsp_spi8),
+ APQ_PIN_FUNCTION(blsp_spi9),
+ APQ_PIN_FUNCTION(blsp_spi10),
+ APQ_PIN_FUNCTION(blsp_spi10_cs1),
+ APQ_PIN_FUNCTION(blsp_spi10_cs2),
+ APQ_PIN_FUNCTION(blsp_spi10_cs3),
+ APQ_PIN_FUNCTION(blsp_spi11),
+ APQ_PIN_FUNCTION(blsp_spi12),
+ APQ_PIN_FUNCTION(blsp_uart1),
+ APQ_PIN_FUNCTION(blsp_uart2),
+ APQ_PIN_FUNCTION(blsp_uart3),
+ APQ_PIN_FUNCTION(blsp_uart4),
+ APQ_PIN_FUNCTION(blsp_uart5),
+ APQ_PIN_FUNCTION(blsp_uart6),
+ APQ_PIN_FUNCTION(blsp_uart7),
+ APQ_PIN_FUNCTION(blsp_uart8),
+ APQ_PIN_FUNCTION(blsp_uart9),
+ APQ_PIN_FUNCTION(blsp_uart10),
+ APQ_PIN_FUNCTION(blsp_uart11),
+ APQ_PIN_FUNCTION(blsp_uart12),
+ APQ_PIN_FUNCTION(blsp_uim1),
+ APQ_PIN_FUNCTION(blsp_uim2),
+ APQ_PIN_FUNCTION(blsp_uim3),
+ APQ_PIN_FUNCTION(blsp_uim4),
+ APQ_PIN_FUNCTION(blsp_uim5),
+ APQ_PIN_FUNCTION(blsp_uim6),
+ APQ_PIN_FUNCTION(blsp_uim7),
+ APQ_PIN_FUNCTION(blsp_uim8),
+ APQ_PIN_FUNCTION(blsp_uim9),
+ APQ_PIN_FUNCTION(blsp_uim10),
+ APQ_PIN_FUNCTION(blsp_uim11),
+ APQ_PIN_FUNCTION(blsp_uim12),
+ APQ_PIN_FUNCTION(cam_mclk0),
+ APQ_PIN_FUNCTION(cam_mclk1),
+ APQ_PIN_FUNCTION(cam_mclk2),
+ APQ_PIN_FUNCTION(cam_mclk3),
+ APQ_PIN_FUNCTION(cci_async),
+ APQ_PIN_FUNCTION(cci_async_in0),
+ APQ_PIN_FUNCTION(cci_i2c0),
+ APQ_PIN_FUNCTION(cci_i2c1),
+ APQ_PIN_FUNCTION(cci_timer0),
+ APQ_PIN_FUNCTION(cci_timer1),
+ APQ_PIN_FUNCTION(cci_timer2),
+ APQ_PIN_FUNCTION(cci_timer3),
+ APQ_PIN_FUNCTION(cci_timer4),
+ APQ_PIN_FUNCTION(edp_hpd),
+ APQ_PIN_FUNCTION(gcc_gp1),
+ APQ_PIN_FUNCTION(gcc_gp2),
+ APQ_PIN_FUNCTION(gcc_gp3),
+ APQ_PIN_FUNCTION(gcc_obt),
+ APQ_PIN_FUNCTION(gcc_vtt),
+ APQ_PIN_FUNCTION(gp_mn),
+ APQ_PIN_FUNCTION(gp_pdm0),
+ APQ_PIN_FUNCTION(gp_pdm1),
+ APQ_PIN_FUNCTION(gp_pdm2),
+ APQ_PIN_FUNCTION(gp0_clk),
+ APQ_PIN_FUNCTION(gp1_clk),
+ APQ_PIN_FUNCTION(gpio),
+ APQ_PIN_FUNCTION(hdmi_cec),
+ APQ_PIN_FUNCTION(hdmi_ddc),
+ APQ_PIN_FUNCTION(hdmi_dtest),
+ APQ_PIN_FUNCTION(hdmi_hpd),
+ APQ_PIN_FUNCTION(hdmi_rcv),
+ APQ_PIN_FUNCTION(hsic),
+ APQ_PIN_FUNCTION(ldo_en),
+ APQ_PIN_FUNCTION(ldo_update),
+ APQ_PIN_FUNCTION(mdp_vsync),
+ APQ_PIN_FUNCTION(pci_e0),
+ APQ_PIN_FUNCTION(pci_e0_n),
+ APQ_PIN_FUNCTION(pci_e0_rst),
+ APQ_PIN_FUNCTION(pci_e1),
+ APQ_PIN_FUNCTION(pci_e1_rst),
+ APQ_PIN_FUNCTION(pci_e1_rst_n),
+ APQ_PIN_FUNCTION(pci_e1_clkreq_n),
+ APQ_PIN_FUNCTION(pri_mi2s),
+ APQ_PIN_FUNCTION(qua_mi2s),
+ APQ_PIN_FUNCTION(sata_act),
+ APQ_PIN_FUNCTION(sata_devsleep),
+ APQ_PIN_FUNCTION(sata_devsleep_n),
+ APQ_PIN_FUNCTION(sd_write),
+ APQ_PIN_FUNCTION(sdc_emmc_mode),
+ APQ_PIN_FUNCTION(sdc3),
+ APQ_PIN_FUNCTION(sdc4),
+ APQ_PIN_FUNCTION(sec_mi2s),
+ APQ_PIN_FUNCTION(slimbus),
+ APQ_PIN_FUNCTION(spdif_tx),
+ APQ_PIN_FUNCTION(spkr_i2s),
+ APQ_PIN_FUNCTION(spkr_i2s_ws),
+ APQ_PIN_FUNCTION(spss_geni),
+ APQ_PIN_FUNCTION(ter_mi2s),
+ APQ_PIN_FUNCTION(tsif1),
+ APQ_PIN_FUNCTION(tsif2),
+ APQ_PIN_FUNCTION(uim),
+ APQ_PIN_FUNCTION(uim_batt_alarm),
};
static const struct msm_pingroup apq8084_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c
index 63915cb210ff..1f7944dd829d 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -216,18 +215,11 @@ DECLARE_QCA_GPIO_PINS(97);
DECLARE_QCA_GPIO_PINS(98);
DECLARE_QCA_GPIO_PINS(99);
-#define FUNCTION(fname) \
- [qca_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
qca_mux_gpio, /* gpio mode */ \
qca_mux_##f1, \
@@ -478,51 +470,51 @@ static const char * const wifi1_groups[] = {
"gpio53", "gpio56", "gpio57", "gpio58", "gpio98",
};
-static const struct msm_function ipq4019_functions[] = {
- FUNCTION(aud_pin),
- FUNCTION(audio_pwm),
- FUNCTION(blsp_i2c0),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_spi0),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_uart0),
- FUNCTION(blsp_uart1),
- FUNCTION(chip_rst),
- FUNCTION(gpio),
- FUNCTION(i2s_rx),
- FUNCTION(i2s_spdif_in),
- FUNCTION(i2s_spdif_out),
- FUNCTION(i2s_td),
- FUNCTION(i2s_tx),
- FUNCTION(jtag),
- FUNCTION(led0),
- FUNCTION(led1),
- FUNCTION(led2),
- FUNCTION(led3),
- FUNCTION(led4),
- FUNCTION(led5),
- FUNCTION(led6),
- FUNCTION(led7),
- FUNCTION(led8),
- FUNCTION(led9),
- FUNCTION(led10),
- FUNCTION(led11),
- FUNCTION(mdc),
- FUNCTION(mdio),
- FUNCTION(pcie),
- FUNCTION(pmu),
- FUNCTION(prng_rosc),
- FUNCTION(qpic),
- FUNCTION(rgmii),
- FUNCTION(rmii),
- FUNCTION(sdio),
- FUNCTION(smart0),
- FUNCTION(smart1),
- FUNCTION(smart2),
- FUNCTION(smart3),
- FUNCTION(tm),
- FUNCTION(wifi0),
- FUNCTION(wifi1),
+static const struct pinfunction ipq4019_functions[] = {
+ QCA_PIN_FUNCTION(aud_pin),
+ QCA_PIN_FUNCTION(audio_pwm),
+ QCA_PIN_FUNCTION(blsp_i2c0),
+ QCA_PIN_FUNCTION(blsp_i2c1),
+ QCA_PIN_FUNCTION(blsp_spi0),
+ QCA_PIN_FUNCTION(blsp_spi1),
+ QCA_PIN_FUNCTION(blsp_uart0),
+ QCA_PIN_FUNCTION(blsp_uart1),
+ QCA_PIN_FUNCTION(chip_rst),
+ QCA_PIN_FUNCTION(gpio),
+ QCA_PIN_FUNCTION(i2s_rx),
+ QCA_PIN_FUNCTION(i2s_spdif_in),
+ QCA_PIN_FUNCTION(i2s_spdif_out),
+ QCA_PIN_FUNCTION(i2s_td),
+ QCA_PIN_FUNCTION(i2s_tx),
+ QCA_PIN_FUNCTION(jtag),
+ QCA_PIN_FUNCTION(led0),
+ QCA_PIN_FUNCTION(led1),
+ QCA_PIN_FUNCTION(led2),
+ QCA_PIN_FUNCTION(led3),
+ QCA_PIN_FUNCTION(led4),
+ QCA_PIN_FUNCTION(led5),
+ QCA_PIN_FUNCTION(led6),
+ QCA_PIN_FUNCTION(led7),
+ QCA_PIN_FUNCTION(led8),
+ QCA_PIN_FUNCTION(led9),
+ QCA_PIN_FUNCTION(led10),
+ QCA_PIN_FUNCTION(led11),
+ QCA_PIN_FUNCTION(mdc),
+ QCA_PIN_FUNCTION(mdio),
+ QCA_PIN_FUNCTION(pcie),
+ QCA_PIN_FUNCTION(pmu),
+ QCA_PIN_FUNCTION(prng_rosc),
+ QCA_PIN_FUNCTION(qpic),
+ QCA_PIN_FUNCTION(rgmii),
+ QCA_PIN_FUNCTION(rmii),
+ QCA_PIN_FUNCTION(sdio),
+ QCA_PIN_FUNCTION(smart0),
+ QCA_PIN_FUNCTION(smart1),
+ QCA_PIN_FUNCTION(smart2),
+ QCA_PIN_FUNCTION(smart3),
+ QCA_PIN_FUNCTION(tm),
+ QCA_PIN_FUNCTION(wifi0),
+ QCA_PIN_FUNCTION(wifi1),
};
static const struct msm_pingroup ipq4019_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5018.c b/drivers/pinctrl/qcom/pinctrl-ipq5018.c
new file mode 100644
index 000000000000..ed58f750f1eb
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-ipq5018.c
@@ -0,0 +1,783 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019-2021, 2023 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-msm.h"
+
+#define REG_SIZE 0x1000
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+ { \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9 \
+ }, \
+ .nfuncs = 10, \
+ .ctl_reg = REG_SIZE * id, \
+ .io_reg = 0x4 + REG_SIZE * id, \
+ .intr_cfg_reg = 0x8 + REG_SIZE * id, \
+ .intr_status_reg = 0xc + REG_SIZE * id, \
+ .intr_target_reg = 0x8 + REG_SIZE * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 3, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+static const struct pinctrl_pin_desc ipq5018_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+
+enum ipq5018_functions {
+ msm_mux_atest_char,
+ msm_mux_audio_pdm0,
+ msm_mux_audio_pdm1,
+ msm_mux_audio_rxbclk,
+ msm_mux_audio_rxd,
+ msm_mux_audio_rxfsync,
+ msm_mux_audio_rxmclk,
+ msm_mux_audio_txbclk,
+ msm_mux_audio_txd,
+ msm_mux_audio_txfsync,
+ msm_mux_audio_txmclk,
+ msm_mux_blsp0_i2c,
+ msm_mux_blsp0_spi,
+ msm_mux_blsp0_uart0,
+ msm_mux_blsp0_uart1,
+ msm_mux_blsp1_i2c0,
+ msm_mux_blsp1_i2c1,
+ msm_mux_blsp1_spi0,
+ msm_mux_blsp1_spi1,
+ msm_mux_blsp1_uart0,
+ msm_mux_blsp1_uart1,
+ msm_mux_blsp1_uart2,
+ msm_mux_blsp2_i2c0,
+ msm_mux_blsp2_i2c1,
+ msm_mux_blsp2_spi,
+ msm_mux_blsp2_spi0,
+ msm_mux_blsp2_spi1,
+ msm_mux_btss,
+ msm_mux_burn0,
+ msm_mux_burn1,
+ msm_mux_cri_trng,
+ msm_mux_cri_trng0,
+ msm_mux_cri_trng1,
+ msm_mux_cxc_clk,
+ msm_mux_cxc_data,
+ msm_mux_dbg_out,
+ msm_mux_eud_gpio,
+ msm_mux_gcc_plltest,
+ msm_mux_gcc_tlmm,
+ msm_mux_gpio,
+ msm_mux_led0,
+ msm_mux_led2,
+ msm_mux_mac0,
+ msm_mux_mac1,
+ msm_mux_mdc,
+ msm_mux_mdio,
+ msm_mux_pcie0_clk,
+ msm_mux_pcie0_wake,
+ msm_mux_pcie1_clk,
+ msm_mux_pcie1_wake,
+ msm_mux_pll_test,
+ msm_mux_prng_rosc,
+ msm_mux_pwm0,
+ msm_mux_pwm1,
+ msm_mux_pwm2,
+ msm_mux_pwm3,
+ msm_mux_qdss_cti_trig_in_a0,
+ msm_mux_qdss_cti_trig_in_a1,
+ msm_mux_qdss_cti_trig_in_b0,
+ msm_mux_qdss_cti_trig_in_b1,
+ msm_mux_qdss_cti_trig_out_a0,
+ msm_mux_qdss_cti_trig_out_a1,
+ msm_mux_qdss_cti_trig_out_b0,
+ msm_mux_qdss_cti_trig_out_b1,
+ msm_mux_qdss_traceclk_a,
+ msm_mux_qdss_traceclk_b,
+ msm_mux_qdss_tracectl_a,
+ msm_mux_qdss_tracectl_b,
+ msm_mux_qdss_tracedata_a,
+ msm_mux_qdss_tracedata_b,
+ msm_mux_qspi_clk,
+ msm_mux_qspi_cs,
+ msm_mux_qspi_data,
+ msm_mux_reset_out,
+ msm_mux_sdc1_clk,
+ msm_mux_sdc1_cmd,
+ msm_mux_sdc1_data,
+ msm_mux_wci_txd,
+ msm_mux_wci_rxd,
+ msm_mux_wsa_swrm,
+ msm_mux_wsi_clk3,
+ msm_mux_wsi_data3,
+ msm_mux_wsis_reset,
+ msm_mux_xfem,
+ msm_mux__,
+};
+
+static const char * const atest_char_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio37",
+};
+
+static const char * const _groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46",
+};
+
+static const char * const wci_txd_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+ "gpio42", "gpio43", "gpio44", "gpio45",
+};
+
+static const char * const wci_rxd_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+ "gpio42", "gpio43", "gpio44", "gpio45",
+};
+
+static const char * const xfem_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+ "gpio42", "gpio43", "gpio44", "gpio45",
+};
+
+static const char * const qdss_cti_trig_out_a0_groups[] = {
+ "gpio0",
+};
+
+static const char * const qdss_cti_trig_in_a0_groups[] = {
+ "gpio1",
+};
+
+static const char * const qdss_cti_trig_out_a1_groups[] = {
+ "gpio2",
+};
+
+static const char * const qdss_cti_trig_in_a1_groups[] = {
+ "gpio3",
+};
+
+static const char * const sdc1_data_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+
+static const char * const qspi_data_groups[] = {
+ "gpio4",
+ "gpio5",
+ "gpio6",
+ "gpio7",
+};
+
+static const char * const blsp1_spi1_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+
+static const char * const btss_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7", "gpio8", "gpio17", "gpio18",
+ "gpio19", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+};
+
+static const char * const dbg_out_groups[] = {
+ "gpio4",
+};
+
+static const char * const qdss_traceclk_a_groups[] = {
+ "gpio4",
+};
+
+static const char * const burn0_groups[] = {
+ "gpio4",
+};
+
+static const char * const cxc_clk_groups[] = {
+ "gpio5",
+};
+
+static const char * const blsp1_i2c1_groups[] = {
+ "gpio5", "gpio6",
+};
+
+static const char * const qdss_tracectl_a_groups[] = {
+ "gpio5",
+};
+
+static const char * const burn1_groups[] = {
+ "gpio5",
+};
+
+static const char * const cxc_data_groups[] = {
+ "gpio6",
+};
+
+static const char * const qdss_tracedata_a_groups[] = {
+ "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", "gpio12",
+ "gpio13", "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19",
+ "gpio20", "gpio21",
+};
+
+static const char * const mac0_groups[] = {
+ "gpio7",
+};
+
+static const char * const sdc1_cmd_groups[] = {
+ "gpio8",
+};
+
+static const char * const qspi_cs_groups[] = {
+ "gpio8",
+};
+
+static const char * const mac1_groups[] = {
+ "gpio8",
+};
+
+static const char * const sdc1_clk_groups[] = {
+ "gpio9",
+};
+
+static const char * const qspi_clk_groups[] = {
+ "gpio9",
+};
+
+static const char * const blsp0_spi_groups[] = {
+ "gpio10", "gpio11", "gpio12", "gpio13",
+};
+
+static const char * const blsp1_uart0_groups[] = {
+ "gpio10", "gpio11", "gpio12", "gpio13",
+};
+
+static const char * const gcc_plltest_groups[] = {
+ "gpio10", "gpio12",
+};
+
+static const char * const gcc_tlmm_groups[] = {
+ "gpio11",
+};
+
+static const char * const blsp0_i2c_groups[] = {
+ "gpio12", "gpio13",
+};
+
+static const char * const pcie0_clk_groups[] = {
+ "gpio14",
+};
+
+static const char * const cri_trng0_groups[] = {
+ "gpio14",
+};
+
+static const char * const cri_trng1_groups[] = {
+ "gpio15",
+};
+
+static const char * const pcie0_wake_groups[] = {
+ "gpio16",
+};
+
+static const char * const cri_trng_groups[] = {
+ "gpio16",
+};
+
+static const char * const pcie1_clk_groups[] = {
+ "gpio17",
+};
+
+static const char * const prng_rosc_groups[] = {
+ "gpio17",
+};
+
+static const char * const blsp1_spi0_groups[] = {
+ "gpio18", "gpio19", "gpio20", "gpio21",
+};
+
+static const char * const pcie1_wake_groups[] = {
+ "gpio19",
+};
+
+static const char * const blsp1_i2c0_groups[] = {
+ "gpio19", "gpio20",
+};
+
+static const char * const blsp0_uart0_groups[] = {
+ "gpio20", "gpio21",
+};
+
+static const char * const pll_test_groups[] = {
+ "gpio22",
+};
+
+static const char * const eud_gpio_groups[] = {
+ "gpio22", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+};
+
+static const char * const audio_rxmclk_groups[] = {
+ "gpio23", "gpio23",
+};
+
+static const char * const audio_pdm0_groups[] = {
+ "gpio23", "gpio24",
+};
+
+static const char * const blsp2_spi1_groups[] = {
+ "gpio23", "gpio24", "gpio25", "gpio26",
+};
+
+static const char * const blsp1_uart2_groups[] = {
+ "gpio23", "gpio24", "gpio25", "gpio26",
+};
+
+static const char * const qdss_tracedata_b_groups[] = {
+ "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29",
+ "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36",
+ "gpio37", "gpio38",
+};
+
+static const char * const audio_rxbclk_groups[] = {
+ "gpio24",
+};
+
+static const char * const audio_rxfsync_groups[] = {
+ "gpio25",
+};
+
+static const char * const audio_pdm1_groups[] = {
+ "gpio25", "gpio26",
+};
+
+static const char * const blsp2_i2c1_groups[] = {
+ "gpio25", "gpio26",
+};
+
+static const char * const audio_rxd_groups[] = {
+ "gpio26",
+};
+
+static const char * const audio_txmclk_groups[] = {
+ "gpio27", "gpio27",
+};
+
+static const char * const wsa_swrm_groups[] = {
+ "gpio27", "gpio28",
+};
+
+static const char * const blsp2_spi_groups[] = {
+ "gpio27",
+};
+
+static const char * const audio_txbclk_groups[] = {
+ "gpio28",
+};
+
+static const char * const blsp0_uart1_groups[] = {
+ "gpio28", "gpio29",
+};
+
+static const char * const audio_txfsync_groups[] = {
+ "gpio29",
+};
+
+static const char * const audio_txd_groups[] = {
+ "gpio30",
+};
+
+static const char * const wsis_reset_groups[] = {
+ "gpio30",
+};
+
+static const char * const blsp2_spi0_groups[] = {
+ "gpio31", "gpio32", "gpio33", "gpio34",
+};
+
+static const char * const blsp1_uart1_groups[] = {
+ "gpio31", "gpio32", "gpio33", "gpio34",
+};
+
+static const char * const blsp2_i2c0_groups[] = {
+ "gpio33", "gpio34",
+};
+
+static const char * const mdc_groups[] = {
+ "gpio36",
+};
+
+static const char * const wsi_clk3_groups[] = {
+ "gpio36",
+};
+
+static const char * const mdio_groups[] = {
+ "gpio37",
+};
+
+static const char * const wsi_data3_groups[] = {
+ "gpio37",
+};
+
+static const char * const qdss_traceclk_b_groups[] = {
+ "gpio39",
+};
+
+static const char * const reset_out_groups[] = {
+ "gpio40",
+};
+
+static const char * const qdss_tracectl_b_groups[] = {
+ "gpio40",
+};
+
+static const char * const pwm0_groups[] = {
+ "gpio42",
+};
+
+static const char * const qdss_cti_trig_out_b0_groups[] = {
+ "gpio42",
+};
+
+static const char * const pwm1_groups[] = {
+ "gpio43",
+};
+
+static const char * const qdss_cti_trig_in_b0_groups[] = {
+ "gpio43",
+};
+
+static const char * const pwm2_groups[] = {
+ "gpio44",
+};
+
+static const char * const qdss_cti_trig_out_b1_groups[] = {
+ "gpio44",
+};
+
+static const char * const pwm3_groups[] = {
+ "gpio45",
+};
+
+static const char * const qdss_cti_trig_in_b1_groups[] = {
+ "gpio45",
+};
+
+static const char * const led0_groups[] = {
+ "gpio46", "gpio30", "gpio10",
+};
+
+static const char * const led2_groups[] = {
+ "gpio30",
+};
+
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46",
+};
+
+static const struct pinfunction ipq5018_functions[] = {
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(audio_pdm0),
+ MSM_PIN_FUNCTION(audio_pdm1),
+ MSM_PIN_FUNCTION(audio_rxbclk),
+ MSM_PIN_FUNCTION(audio_rxd),
+ MSM_PIN_FUNCTION(audio_rxfsync),
+ MSM_PIN_FUNCTION(audio_rxmclk),
+ MSM_PIN_FUNCTION(audio_txbclk),
+ MSM_PIN_FUNCTION(audio_txd),
+ MSM_PIN_FUNCTION(audio_txfsync),
+ MSM_PIN_FUNCTION(audio_txmclk),
+ MSM_PIN_FUNCTION(blsp0_i2c),
+ MSM_PIN_FUNCTION(blsp0_spi),
+ MSM_PIN_FUNCTION(blsp0_uart0),
+ MSM_PIN_FUNCTION(blsp0_uart1),
+ MSM_PIN_FUNCTION(blsp1_i2c0),
+ MSM_PIN_FUNCTION(blsp1_i2c1),
+ MSM_PIN_FUNCTION(blsp1_spi0),
+ MSM_PIN_FUNCTION(blsp1_spi1),
+ MSM_PIN_FUNCTION(blsp1_uart0),
+ MSM_PIN_FUNCTION(blsp1_uart1),
+ MSM_PIN_FUNCTION(blsp1_uart2),
+ MSM_PIN_FUNCTION(blsp2_i2c0),
+ MSM_PIN_FUNCTION(blsp2_i2c1),
+ MSM_PIN_FUNCTION(blsp2_spi),
+ MSM_PIN_FUNCTION(blsp2_spi0),
+ MSM_PIN_FUNCTION(blsp2_spi1),
+ MSM_PIN_FUNCTION(btss),
+ MSM_PIN_FUNCTION(burn0),
+ MSM_PIN_FUNCTION(burn1),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(cxc_clk),
+ MSM_PIN_FUNCTION(cxc_data),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(eud_gpio),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gcc_tlmm),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(led0),
+ MSM_PIN_FUNCTION(led2),
+ MSM_PIN_FUNCTION(mac0),
+ MSM_PIN_FUNCTION(mac1),
+ MSM_PIN_FUNCTION(mdc),
+ MSM_PIN_FUNCTION(mdio),
+ MSM_PIN_FUNCTION(pcie0_clk),
+ MSM_PIN_FUNCTION(pcie0_wake),
+ MSM_PIN_FUNCTION(pcie1_clk),
+ MSM_PIN_FUNCTION(pcie1_wake),
+ MSM_PIN_FUNCTION(pll_test),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(pwm0),
+ MSM_PIN_FUNCTION(pwm1),
+ MSM_PIN_FUNCTION(pwm2),
+ MSM_PIN_FUNCTION(pwm3),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b1),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_traceclk_b),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_b),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qspi_data),
+ MSM_PIN_FUNCTION(reset_out),
+ MSM_PIN_FUNCTION(sdc1_clk),
+ MSM_PIN_FUNCTION(sdc1_cmd),
+ MSM_PIN_FUNCTION(sdc1_data),
+ MSM_PIN_FUNCTION(wci_txd),
+ MSM_PIN_FUNCTION(wci_rxd),
+ MSM_PIN_FUNCTION(wsa_swrm),
+ MSM_PIN_FUNCTION(wsi_clk3),
+ MSM_PIN_FUNCTION(wsi_data3),
+ MSM_PIN_FUNCTION(wsis_reset),
+ MSM_PIN_FUNCTION(xfem),
+};
+
+static const struct msm_pingroup ipq5018_groups[] = {
+ PINGROUP(0, atest_char, _, qdss_cti_trig_out_a0, wci_txd, wci_rxd, xfem, _, _, _),
+ PINGROUP(1, atest_char, _, qdss_cti_trig_in_a0, wci_txd, wci_rxd, xfem, _, _, _),
+ PINGROUP(2, atest_char, _, qdss_cti_trig_out_a1, wci_txd, wci_rxd, xfem, _, _, _),
+ PINGROUP(3, atest_char, _, qdss_cti_trig_in_a1, wci_txd, wci_rxd, xfem, _, _, _),
+ PINGROUP(4, sdc1_data, qspi_data, blsp1_spi1, btss, dbg_out, qdss_traceclk_a, _, burn0, _),
+ PINGROUP(5, sdc1_data, qspi_data, cxc_clk, blsp1_spi1, blsp1_i2c1, btss, _, qdss_tracectl_a, _),
+ PINGROUP(6, sdc1_data, qspi_data, cxc_data, blsp1_spi1, blsp1_i2c1, btss, _, qdss_tracedata_a, _),
+ PINGROUP(7, sdc1_data, qspi_data, mac0, blsp1_spi1, btss, _, qdss_tracedata_a, _, _),
+ PINGROUP(8, sdc1_cmd, qspi_cs, mac1, btss, _, qdss_tracedata_a, _, _, _),
+ PINGROUP(9, sdc1_clk, qspi_clk, _, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(10, blsp0_spi, blsp1_uart0, led0, gcc_plltest, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(11, blsp0_spi, blsp1_uart0, _, gcc_tlmm, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(12, blsp0_spi, blsp0_i2c, blsp1_uart0, _, gcc_plltest, qdss_tracedata_a, _, _, _),
+ PINGROUP(13, blsp0_spi, blsp0_i2c, blsp1_uart0, _, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(14, pcie0_clk, _, _, cri_trng0, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(15, _, _, cri_trng1, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(16, pcie0_wake, _, _, cri_trng, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(17, pcie1_clk, btss, _, prng_rosc, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(18, blsp1_spi0, btss, _, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(19, pcie1_wake, blsp1_spi0, blsp1_i2c0, btss, _, qdss_tracedata_a, _, _, _),
+ PINGROUP(20, blsp0_uart0, blsp1_spi0, blsp1_i2c0, _, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(21, blsp0_uart0, blsp1_spi0, _, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(22, _, pll_test, eud_gpio, _, _, _, _, _, _),
+ PINGROUP(23, audio_rxmclk, audio_pdm0, audio_rxmclk, blsp2_spi1, blsp1_uart2, btss, _, qdss_tracedata_b, _),
+ PINGROUP(24, audio_rxbclk, audio_pdm0, blsp2_spi1, blsp1_uart2, btss, _, qdss_tracedata_b, _, _),
+ PINGROUP(25, audio_rxfsync, audio_pdm1, blsp2_i2c1, blsp2_spi1, blsp1_uart2, btss, _, qdss_tracedata_b, _),
+ PINGROUP(26, audio_rxd, audio_pdm1, blsp2_i2c1, blsp2_spi1, blsp1_uart2, btss, _, qdss_tracedata_b, _),
+ PINGROUP(27, audio_txmclk, wsa_swrm, audio_txmclk, blsp2_spi, btss, _, qdss_tracedata_b, _, _),
+ PINGROUP(28, audio_txbclk, wsa_swrm, blsp0_uart1, btss, qdss_tracedata_b, _, _, _, _),
+ PINGROUP(29, audio_txfsync, _, blsp0_uart1, _, qdss_tracedata_b, _, _, _, _),
+ PINGROUP(30, audio_txd, led2, led0, _, _, _, _, _, _),
+ PINGROUP(31, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _, _),
+ PINGROUP(32, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _, _),
+ PINGROUP(33, blsp2_i2c0, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _),
+ PINGROUP(34, blsp2_i2c0, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _),
+ PINGROUP(35, _, qdss_tracedata_b, eud_gpio, _, _, _, _, _, _),
+ PINGROUP(36, mdc, qdss_tracedata_b, _, wsi_clk3, _, _, _, _, _),
+ PINGROUP(37, mdio, atest_char, qdss_tracedata_b, _, wsi_data3, _, _, _, _),
+ PINGROUP(38, qdss_tracedata_b, _, _, _, _, _, _, _, _),
+ PINGROUP(39, qdss_traceclk_b, _, _, _, _, _, _, _, _),
+ PINGROUP(40, reset_out, qdss_tracectl_b, _, _, _, _, _, _, _),
+ PINGROUP(41, _, _, _, _, _, _, _, _, _),
+ PINGROUP(42, pwm0, qdss_cti_trig_out_b0, wci_txd, wci_rxd, xfem, _, _, _, _),
+ PINGROUP(43, pwm1, qdss_cti_trig_in_b0, wci_txd, wci_rxd, xfem, _, _, _, _),
+ PINGROUP(44, pwm2, qdss_cti_trig_out_b1, wci_txd, wci_rxd, xfem, _, _, _, _),
+ PINGROUP(45, pwm3, qdss_cti_trig_in_b1, wci_txd, wci_rxd, xfem, _, _, _, _),
+ PINGROUP(46, led0, _, _, _, _, _, _, _, _),
+};
+
+static const struct msm_pinctrl_soc_data ipq5018_pinctrl = {
+ .pins = ipq5018_pins,
+ .npins = ARRAY_SIZE(ipq5018_pins),
+ .functions = ipq5018_functions,
+ .nfunctions = ARRAY_SIZE(ipq5018_functions),
+ .groups = ipq5018_groups,
+ .ngroups = ARRAY_SIZE(ipq5018_groups),
+ .ngpios = 47,
+};
+
+static int ipq5018_pinctrl_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &ipq5018_pinctrl);
+}
+
+static const struct of_device_id ipq5018_pinctrl_of_match[] = {
+ { .compatible = "qcom,ipq5018-tlmm", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ipq5018_pinctrl_of_match);
+
+static struct platform_driver ipq5018_pinctrl_driver = {
+ .driver = {
+ .name = "ipq5018-tlmm",
+ .of_match_table = ipq5018_pinctrl_of_match,
+ },
+ .probe = ipq5018_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init ipq5018_pinctrl_init(void)
+{
+ return platform_driver_register(&ipq5018_pinctrl_driver);
+}
+arch_initcall(ipq5018_pinctrl_init);
+
+static void __exit ipq5018_pinctrl_exit(void)
+{
+ platform_driver_unregister(&ipq5018_pinctrl_driver);
+}
+module_exit(ipq5018_pinctrl_exit);
+
+MODULE_DESCRIPTION("Qualcomm Technologies Inc ipq5018 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5332.c b/drivers/pinctrl/qcom/pinctrl-ipq5332.c
index e78d11292f42..625f8014051f 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq5332.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq5332.c
@@ -6,23 +6,15 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -661,102 +653,102 @@ static const char * const xfem_groups[] = {
"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
};
-static const struct msm_function ipq5332_functions[] = {
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(atest_tic),
- FUNCTION(audio_pri),
- FUNCTION(audio_pri0),
- FUNCTION(audio_pri1),
- FUNCTION(audio_sec),
- FUNCTION(audio_sec0),
- FUNCTION(audio_sec1),
- FUNCTION(blsp0_i2c),
- FUNCTION(blsp0_spi),
- FUNCTION(blsp0_uart0),
- FUNCTION(blsp0_uart1),
- FUNCTION(blsp1_i2c0),
- FUNCTION(blsp1_i2c1),
- FUNCTION(blsp1_spi0),
- FUNCTION(blsp1_spi1),
- FUNCTION(blsp1_uart0),
- FUNCTION(blsp1_uart1),
- FUNCTION(blsp1_uart2),
- FUNCTION(blsp2_i2c0),
- FUNCTION(blsp2_i2c1),
- FUNCTION(blsp2_spi),
- FUNCTION(blsp2_spi0),
- FUNCTION(blsp2_spi1),
- FUNCTION(core_voltage),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(cri_trng2),
- FUNCTION(cri_trng3),
- FUNCTION(cxc_clk),
- FUNCTION(cxc_data),
- FUNCTION(dbg_out),
- FUNCTION(gcc_plltest),
- FUNCTION(gcc_tlmm),
- FUNCTION(gpio),
- FUNCTION(lock_det),
- FUNCTION(mac0),
- FUNCTION(mac1),
- FUNCTION(mdc0),
- FUNCTION(mdc1),
- FUNCTION(mdio0),
- FUNCTION(mdio1),
- FUNCTION(pc),
- FUNCTION(pcie0_clk),
- FUNCTION(pcie0_wake),
- FUNCTION(pcie1_clk),
- FUNCTION(pcie1_wake),
- FUNCTION(pcie2_clk),
- FUNCTION(pcie2_wake),
- FUNCTION(pll_test),
- FUNCTION(prng_rosc0),
- FUNCTION(prng_rosc1),
- FUNCTION(prng_rosc2),
- FUNCTION(prng_rosc3),
- FUNCTION(pta),
- FUNCTION(pwm0),
- FUNCTION(pwm1),
- FUNCTION(pwm2),
- FUNCTION(pwm3),
- FUNCTION(qdss_cti_trig_in_a0),
- FUNCTION(qdss_cti_trig_in_a1),
- FUNCTION(qdss_cti_trig_in_b0),
- FUNCTION(qdss_cti_trig_in_b1),
- FUNCTION(qdss_cti_trig_out_a0),
- FUNCTION(qdss_cti_trig_out_a1),
- FUNCTION(qdss_cti_trig_out_b0),
- FUNCTION(qdss_cti_trig_out_b1),
- FUNCTION(qdss_traceclk_a),
- FUNCTION(qdss_traceclk_b),
- FUNCTION(qdss_tracectl_a),
- FUNCTION(qdss_tracectl_b),
- FUNCTION(qdss_tracedata_a),
- FUNCTION(qdss_tracedata_b),
- FUNCTION(qspi_data),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(resout),
- FUNCTION(rx0),
- FUNCTION(rx1),
- FUNCTION(sdc_data),
- FUNCTION(sdc_clk),
- FUNCTION(sdc_cmd),
- FUNCTION(tsens_max),
- FUNCTION(wci_txd),
- FUNCTION(wci_rxd),
- FUNCTION(wsi_clk),
- FUNCTION(wsi_clk3),
- FUNCTION(wsi_data),
- FUNCTION(wsi_data3),
- FUNCTION(wsis_reset),
- FUNCTION(xfem),
+static const struct pinfunction ipq5332_functions[] = {
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_tic),
+ MSM_PIN_FUNCTION(audio_pri),
+ MSM_PIN_FUNCTION(audio_pri0),
+ MSM_PIN_FUNCTION(audio_pri1),
+ MSM_PIN_FUNCTION(audio_sec),
+ MSM_PIN_FUNCTION(audio_sec0),
+ MSM_PIN_FUNCTION(audio_sec1),
+ MSM_PIN_FUNCTION(blsp0_i2c),
+ MSM_PIN_FUNCTION(blsp0_spi),
+ MSM_PIN_FUNCTION(blsp0_uart0),
+ MSM_PIN_FUNCTION(blsp0_uart1),
+ MSM_PIN_FUNCTION(blsp1_i2c0),
+ MSM_PIN_FUNCTION(blsp1_i2c1),
+ MSM_PIN_FUNCTION(blsp1_spi0),
+ MSM_PIN_FUNCTION(blsp1_spi1),
+ MSM_PIN_FUNCTION(blsp1_uart0),
+ MSM_PIN_FUNCTION(blsp1_uart1),
+ MSM_PIN_FUNCTION(blsp1_uart2),
+ MSM_PIN_FUNCTION(blsp2_i2c0),
+ MSM_PIN_FUNCTION(blsp2_i2c1),
+ MSM_PIN_FUNCTION(blsp2_spi),
+ MSM_PIN_FUNCTION(blsp2_spi0),
+ MSM_PIN_FUNCTION(blsp2_spi1),
+ MSM_PIN_FUNCTION(core_voltage),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(cri_trng2),
+ MSM_PIN_FUNCTION(cri_trng3),
+ MSM_PIN_FUNCTION(cxc_clk),
+ MSM_PIN_FUNCTION(cxc_data),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gcc_tlmm),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(lock_det),
+ MSM_PIN_FUNCTION(mac0),
+ MSM_PIN_FUNCTION(mac1),
+ MSM_PIN_FUNCTION(mdc0),
+ MSM_PIN_FUNCTION(mdc1),
+ MSM_PIN_FUNCTION(mdio0),
+ MSM_PIN_FUNCTION(mdio1),
+ MSM_PIN_FUNCTION(pc),
+ MSM_PIN_FUNCTION(pcie0_clk),
+ MSM_PIN_FUNCTION(pcie0_wake),
+ MSM_PIN_FUNCTION(pcie1_clk),
+ MSM_PIN_FUNCTION(pcie1_wake),
+ MSM_PIN_FUNCTION(pcie2_clk),
+ MSM_PIN_FUNCTION(pcie2_wake),
+ MSM_PIN_FUNCTION(pll_test),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(prng_rosc2),
+ MSM_PIN_FUNCTION(prng_rosc3),
+ MSM_PIN_FUNCTION(pta),
+ MSM_PIN_FUNCTION(pwm0),
+ MSM_PIN_FUNCTION(pwm1),
+ MSM_PIN_FUNCTION(pwm2),
+ MSM_PIN_FUNCTION(pwm3),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b1),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_traceclk_b),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_b),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(qspi_data),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(resout),
+ MSM_PIN_FUNCTION(rx0),
+ MSM_PIN_FUNCTION(rx1),
+ MSM_PIN_FUNCTION(sdc_data),
+ MSM_PIN_FUNCTION(sdc_clk),
+ MSM_PIN_FUNCTION(sdc_cmd),
+ MSM_PIN_FUNCTION(tsens_max),
+ MSM_PIN_FUNCTION(wci_txd),
+ MSM_PIN_FUNCTION(wci_rxd),
+ MSM_PIN_FUNCTION(wsi_clk),
+ MSM_PIN_FUNCTION(wsi_clk3),
+ MSM_PIN_FUNCTION(wsi_data),
+ MSM_PIN_FUNCTION(wsi_data3),
+ MSM_PIN_FUNCTION(wsis_reset),
+ MSM_PIN_FUNCTION(xfem),
};
static const struct msm_pingroup ipq5332_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq6018.c b/drivers/pinctrl/qcom/pinctrl-ipq6018.c
index ec50a3b4bd16..0ad08647dbcd 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq6018.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq6018.c
@@ -6,23 +6,15 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -854,129 +846,129 @@ static const char * const gpio_groups[] = {
"gpio78", "gpio79",
};
-static const struct msm_function ipq6018_functions[] = {
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(audio0),
- FUNCTION(audio1),
- FUNCTION(audio2),
- FUNCTION(audio3),
- FUNCTION(audio_rxbclk),
- FUNCTION(audio_rxfsync),
- FUNCTION(audio_rxmclk),
- FUNCTION(audio_rxmclkin),
- FUNCTION(audio_txbclk),
- FUNCTION(audio_txfsync),
- FUNCTION(audio_txmclk),
- FUNCTION(audio_txmclkin),
- FUNCTION(blsp0_i2c),
- FUNCTION(blsp0_spi),
- FUNCTION(blsp0_uart),
- FUNCTION(blsp1_i2c),
- FUNCTION(blsp1_spi),
- FUNCTION(blsp1_uart),
- FUNCTION(blsp2_i2c),
- FUNCTION(blsp2_spi),
- FUNCTION(blsp2_uart),
- FUNCTION(blsp3_i2c),
- FUNCTION(blsp3_spi),
- FUNCTION(blsp3_uart),
- FUNCTION(blsp4_i2c),
- FUNCTION(blsp4_spi),
- FUNCTION(blsp4_uart),
- FUNCTION(blsp5_i2c),
- FUNCTION(blsp5_uart),
- FUNCTION(burn0),
- FUNCTION(burn1),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(cxc0),
- FUNCTION(cxc1),
- FUNCTION(dbg_out),
- FUNCTION(gcc_plltest),
- FUNCTION(gcc_tlmm),
- FUNCTION(gpio),
- FUNCTION(lpass_aud),
- FUNCTION(lpass_aud0),
- FUNCTION(lpass_aud1),
- FUNCTION(lpass_aud2),
- FUNCTION(lpass_pcm),
- FUNCTION(lpass_pdm),
- FUNCTION(mac00),
- FUNCTION(mac01),
- FUNCTION(mac10),
- FUNCTION(mac11),
- FUNCTION(mac12),
- FUNCTION(mac13),
- FUNCTION(mac20),
- FUNCTION(mac21),
- FUNCTION(mdc),
- FUNCTION(mdio),
- FUNCTION(pcie0_clk),
- FUNCTION(pcie0_rst),
- FUNCTION(pcie0_wake),
- FUNCTION(prng_rosc),
- FUNCTION(pta1_0),
- FUNCTION(pta1_1),
- FUNCTION(pta1_2),
- FUNCTION(pta2_0),
- FUNCTION(pta2_1),
- FUNCTION(pta2_2),
- FUNCTION(pwm00),
- FUNCTION(pwm01),
- FUNCTION(pwm02),
- FUNCTION(pwm03),
- FUNCTION(pwm04),
- FUNCTION(pwm10),
- FUNCTION(pwm11),
- FUNCTION(pwm12),
- FUNCTION(pwm13),
- FUNCTION(pwm14),
- FUNCTION(pwm20),
- FUNCTION(pwm21),
- FUNCTION(pwm22),
- FUNCTION(pwm23),
- FUNCTION(pwm24),
- FUNCTION(pwm30),
- FUNCTION(pwm31),
- FUNCTION(pwm32),
- FUNCTION(pwm33),
- FUNCTION(qdss_cti_trig_in_a0),
- FUNCTION(qdss_cti_trig_in_a1),
- FUNCTION(qdss_cti_trig_out_a0),
- FUNCTION(qdss_cti_trig_out_a1),
- FUNCTION(qdss_cti_trig_in_b0),
- FUNCTION(qdss_cti_trig_in_b1),
- FUNCTION(qdss_cti_trig_out_b0),
- FUNCTION(qdss_cti_trig_out_b1),
- FUNCTION(qdss_traceclk_a),
- FUNCTION(qdss_tracectl_a),
- FUNCTION(qdss_tracedata_a),
- FUNCTION(qdss_traceclk_b),
- FUNCTION(qdss_tracectl_b),
- FUNCTION(qdss_tracedata_b),
- FUNCTION(qpic_pad),
- FUNCTION(rx0),
- FUNCTION(rx1),
- FUNCTION(rx_swrm),
- FUNCTION(rx_swrm0),
- FUNCTION(rx_swrm1),
- FUNCTION(sd_card),
- FUNCTION(sd_write),
- FUNCTION(tsens_max),
- FUNCTION(tx_swrm),
- FUNCTION(tx_swrm0),
- FUNCTION(tx_swrm1),
- FUNCTION(tx_swrm2),
- FUNCTION(wci20),
- FUNCTION(wci21),
- FUNCTION(wci22),
- FUNCTION(wci23),
- FUNCTION(wsa_swrm),
+static const struct pinfunction ipq6018_functions[] = {
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(audio0),
+ MSM_PIN_FUNCTION(audio1),
+ MSM_PIN_FUNCTION(audio2),
+ MSM_PIN_FUNCTION(audio3),
+ MSM_PIN_FUNCTION(audio_rxbclk),
+ MSM_PIN_FUNCTION(audio_rxfsync),
+ MSM_PIN_FUNCTION(audio_rxmclk),
+ MSM_PIN_FUNCTION(audio_rxmclkin),
+ MSM_PIN_FUNCTION(audio_txbclk),
+ MSM_PIN_FUNCTION(audio_txfsync),
+ MSM_PIN_FUNCTION(audio_txmclk),
+ MSM_PIN_FUNCTION(audio_txmclkin),
+ MSM_PIN_FUNCTION(blsp0_i2c),
+ MSM_PIN_FUNCTION(blsp0_spi),
+ MSM_PIN_FUNCTION(blsp0_uart),
+ MSM_PIN_FUNCTION(blsp1_i2c),
+ MSM_PIN_FUNCTION(blsp1_spi),
+ MSM_PIN_FUNCTION(blsp1_uart),
+ MSM_PIN_FUNCTION(blsp2_i2c),
+ MSM_PIN_FUNCTION(blsp2_spi),
+ MSM_PIN_FUNCTION(blsp2_uart),
+ MSM_PIN_FUNCTION(blsp3_i2c),
+ MSM_PIN_FUNCTION(blsp3_spi),
+ MSM_PIN_FUNCTION(blsp3_uart),
+ MSM_PIN_FUNCTION(blsp4_i2c),
+ MSM_PIN_FUNCTION(blsp4_spi),
+ MSM_PIN_FUNCTION(blsp4_uart),
+ MSM_PIN_FUNCTION(blsp5_i2c),
+ MSM_PIN_FUNCTION(blsp5_uart),
+ MSM_PIN_FUNCTION(burn0),
+ MSM_PIN_FUNCTION(burn1),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(cxc0),
+ MSM_PIN_FUNCTION(cxc1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gcc_tlmm),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(lpass_aud),
+ MSM_PIN_FUNCTION(lpass_aud0),
+ MSM_PIN_FUNCTION(lpass_aud1),
+ MSM_PIN_FUNCTION(lpass_aud2),
+ MSM_PIN_FUNCTION(lpass_pcm),
+ MSM_PIN_FUNCTION(lpass_pdm),
+ MSM_PIN_FUNCTION(mac00),
+ MSM_PIN_FUNCTION(mac01),
+ MSM_PIN_FUNCTION(mac10),
+ MSM_PIN_FUNCTION(mac11),
+ MSM_PIN_FUNCTION(mac12),
+ MSM_PIN_FUNCTION(mac13),
+ MSM_PIN_FUNCTION(mac20),
+ MSM_PIN_FUNCTION(mac21),
+ MSM_PIN_FUNCTION(mdc),
+ MSM_PIN_FUNCTION(mdio),
+ MSM_PIN_FUNCTION(pcie0_clk),
+ MSM_PIN_FUNCTION(pcie0_rst),
+ MSM_PIN_FUNCTION(pcie0_wake),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(pta1_0),
+ MSM_PIN_FUNCTION(pta1_1),
+ MSM_PIN_FUNCTION(pta1_2),
+ MSM_PIN_FUNCTION(pta2_0),
+ MSM_PIN_FUNCTION(pta2_1),
+ MSM_PIN_FUNCTION(pta2_2),
+ MSM_PIN_FUNCTION(pwm00),
+ MSM_PIN_FUNCTION(pwm01),
+ MSM_PIN_FUNCTION(pwm02),
+ MSM_PIN_FUNCTION(pwm03),
+ MSM_PIN_FUNCTION(pwm04),
+ MSM_PIN_FUNCTION(pwm10),
+ MSM_PIN_FUNCTION(pwm11),
+ MSM_PIN_FUNCTION(pwm12),
+ MSM_PIN_FUNCTION(pwm13),
+ MSM_PIN_FUNCTION(pwm14),
+ MSM_PIN_FUNCTION(pwm20),
+ MSM_PIN_FUNCTION(pwm21),
+ MSM_PIN_FUNCTION(pwm22),
+ MSM_PIN_FUNCTION(pwm23),
+ MSM_PIN_FUNCTION(pwm24),
+ MSM_PIN_FUNCTION(pwm30),
+ MSM_PIN_FUNCTION(pwm31),
+ MSM_PIN_FUNCTION(pwm32),
+ MSM_PIN_FUNCTION(pwm33),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b1),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qdss_traceclk_b),
+ MSM_PIN_FUNCTION(qdss_tracectl_b),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(qpic_pad),
+ MSM_PIN_FUNCTION(rx0),
+ MSM_PIN_FUNCTION(rx1),
+ MSM_PIN_FUNCTION(rx_swrm),
+ MSM_PIN_FUNCTION(rx_swrm0),
+ MSM_PIN_FUNCTION(rx_swrm1),
+ MSM_PIN_FUNCTION(sd_card),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(tsens_max),
+ MSM_PIN_FUNCTION(tx_swrm),
+ MSM_PIN_FUNCTION(tx_swrm0),
+ MSM_PIN_FUNCTION(tx_swrm1),
+ MSM_PIN_FUNCTION(tx_swrm2),
+ MSM_PIN_FUNCTION(wci20),
+ MSM_PIN_FUNCTION(wci21),
+ MSM_PIN_FUNCTION(wci22),
+ MSM_PIN_FUNCTION(wci23),
+ MSM_PIN_FUNCTION(wsa_swrm),
};
static const struct msm_pingroup ipq6018_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
index ac717ee38416..e2bb94e86aef 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -161,18 +160,11 @@ static const unsigned int sdc3_clk_pins[] = { 69 };
static const unsigned int sdc3_cmd_pins[] = { 70 };
static const unsigned int sdc3_data_pins[] = { 71 };
-#define FUNCTION(fname) \
- [IPQ_MUX_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
IPQ_MUX_gpio, \
IPQ_MUX_##f1, \
@@ -211,9 +203,9 @@ static const unsigned int sdc3_data_pins[] = { 71 };
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -487,53 +479,53 @@ static const char * const ps_hold_groups[] = {
"gpio26",
};
-static const struct msm_function ipq8064_functions[] = {
- FUNCTION(gpio),
- FUNCTION(mdio),
- FUNCTION(ssbi),
- FUNCTION(spmi),
- FUNCTION(mi2s),
- FUNCTION(pdm),
- FUNCTION(audio_pcm),
- FUNCTION(gsbi1),
- FUNCTION(gsbi2),
- FUNCTION(gsbi4),
- FUNCTION(gsbi5),
- FUNCTION(gsbi5_spi_cs1),
- FUNCTION(gsbi5_spi_cs2),
- FUNCTION(gsbi5_spi_cs3),
- FUNCTION(gsbi6),
- FUNCTION(gsbi7),
- FUNCTION(nss_spi),
- FUNCTION(sdc1),
- FUNCTION(spdif),
- FUNCTION(nand),
- FUNCTION(tsif1),
- FUNCTION(tsif2),
- FUNCTION(usb_fs_n),
- FUNCTION(usb_fs),
- FUNCTION(usb2_hsic),
- FUNCTION(rgmii2),
- FUNCTION(sata),
- FUNCTION(pcie1_rst),
- FUNCTION(pcie1_prsnt),
- FUNCTION(pcie1_pwren_n),
- FUNCTION(pcie1_pwren),
- FUNCTION(pcie1_pwrflt),
- FUNCTION(pcie1_clk_req),
- FUNCTION(pcie2_rst),
- FUNCTION(pcie2_prsnt),
- FUNCTION(pcie2_pwren_n),
- FUNCTION(pcie2_pwren),
- FUNCTION(pcie2_pwrflt),
- FUNCTION(pcie2_clk_req),
- FUNCTION(pcie3_rst),
- FUNCTION(pcie3_prsnt),
- FUNCTION(pcie3_pwren_n),
- FUNCTION(pcie3_pwren),
- FUNCTION(pcie3_pwrflt),
- FUNCTION(pcie3_clk_req),
- FUNCTION(ps_hold),
+static const struct pinfunction ipq8064_functions[] = {
+ IPQ_PIN_FUNCTION(gpio),
+ IPQ_PIN_FUNCTION(mdio),
+ IPQ_PIN_FUNCTION(ssbi),
+ IPQ_PIN_FUNCTION(spmi),
+ IPQ_PIN_FUNCTION(mi2s),
+ IPQ_PIN_FUNCTION(pdm),
+ IPQ_PIN_FUNCTION(audio_pcm),
+ IPQ_PIN_FUNCTION(gsbi1),
+ IPQ_PIN_FUNCTION(gsbi2),
+ IPQ_PIN_FUNCTION(gsbi4),
+ IPQ_PIN_FUNCTION(gsbi5),
+ IPQ_PIN_FUNCTION(gsbi5_spi_cs1),
+ IPQ_PIN_FUNCTION(gsbi5_spi_cs2),
+ IPQ_PIN_FUNCTION(gsbi5_spi_cs3),
+ IPQ_PIN_FUNCTION(gsbi6),
+ IPQ_PIN_FUNCTION(gsbi7),
+ IPQ_PIN_FUNCTION(nss_spi),
+ IPQ_PIN_FUNCTION(sdc1),
+ IPQ_PIN_FUNCTION(spdif),
+ IPQ_PIN_FUNCTION(nand),
+ IPQ_PIN_FUNCTION(tsif1),
+ IPQ_PIN_FUNCTION(tsif2),
+ IPQ_PIN_FUNCTION(usb_fs_n),
+ IPQ_PIN_FUNCTION(usb_fs),
+ IPQ_PIN_FUNCTION(usb2_hsic),
+ IPQ_PIN_FUNCTION(rgmii2),
+ IPQ_PIN_FUNCTION(sata),
+ IPQ_PIN_FUNCTION(pcie1_rst),
+ IPQ_PIN_FUNCTION(pcie1_prsnt),
+ IPQ_PIN_FUNCTION(pcie1_pwren_n),
+ IPQ_PIN_FUNCTION(pcie1_pwren),
+ IPQ_PIN_FUNCTION(pcie1_pwrflt),
+ IPQ_PIN_FUNCTION(pcie1_clk_req),
+ IPQ_PIN_FUNCTION(pcie2_rst),
+ IPQ_PIN_FUNCTION(pcie2_prsnt),
+ IPQ_PIN_FUNCTION(pcie2_pwren_n),
+ IPQ_PIN_FUNCTION(pcie2_pwren),
+ IPQ_PIN_FUNCTION(pcie2_pwrflt),
+ IPQ_PIN_FUNCTION(pcie2_clk_req),
+ IPQ_PIN_FUNCTION(pcie3_rst),
+ IPQ_PIN_FUNCTION(pcie3_prsnt),
+ IPQ_PIN_FUNCTION(pcie3_pwren_n),
+ IPQ_PIN_FUNCTION(pcie3_pwren),
+ IPQ_PIN_FUNCTION(pcie3_pwrflt),
+ IPQ_PIN_FUNCTION(pcie3_clk_req),
+ IPQ_PIN_FUNCTION(ps_hold),
};
static const struct msm_pingroup ipq8064_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8074.c b/drivers/pinctrl/qcom/pinctrl-ipq8074.c
index aec68b1c9f53..337f3a1c92c1 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq8074.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq8074.c
@@ -6,23 +6,15 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -797,119 +789,119 @@ static const char * const gpio_groups[] = {
"gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69",
};
-static const struct msm_function ipq8074_functions[] = {
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(audio_rxbclk),
- FUNCTION(audio_rxd),
- FUNCTION(audio_rxfsync),
- FUNCTION(audio_rxmclk),
- FUNCTION(audio_txbclk),
- FUNCTION(audio_txd),
- FUNCTION(audio_txfsync),
- FUNCTION(audio_txmclk),
- FUNCTION(blsp0_i2c),
- FUNCTION(blsp0_spi),
- FUNCTION(blsp0_uart),
- FUNCTION(blsp1_i2c),
- FUNCTION(blsp1_spi),
- FUNCTION(blsp1_uart),
- FUNCTION(blsp2_i2c),
- FUNCTION(blsp2_spi),
- FUNCTION(blsp2_uart),
- FUNCTION(blsp3_i2c),
- FUNCTION(blsp3_spi),
- FUNCTION(blsp3_spi0),
- FUNCTION(blsp3_spi1),
- FUNCTION(blsp3_spi2),
- FUNCTION(blsp3_spi3),
- FUNCTION(blsp3_uart),
- FUNCTION(blsp4_i2c0),
- FUNCTION(blsp4_i2c1),
- FUNCTION(blsp4_spi0),
- FUNCTION(blsp4_spi1),
- FUNCTION(blsp4_uart0),
- FUNCTION(blsp4_uart1),
- FUNCTION(blsp5_i2c),
- FUNCTION(blsp5_spi),
- FUNCTION(blsp5_uart),
- FUNCTION(burn0),
- FUNCTION(burn1),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(cxc0),
- FUNCTION(cxc1),
- FUNCTION(dbg_out),
- FUNCTION(gcc_plltest),
- FUNCTION(gcc_tlmm),
- FUNCTION(gpio),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(led0),
- FUNCTION(led1),
- FUNCTION(led2),
- FUNCTION(mac0_sa0),
- FUNCTION(mac0_sa1),
- FUNCTION(mac1_sa0),
- FUNCTION(mac1_sa1),
- FUNCTION(mac1_sa2),
- FUNCTION(mac1_sa3),
- FUNCTION(mac2_sa0),
- FUNCTION(mac2_sa1),
- FUNCTION(mdc),
- FUNCTION(mdio),
- FUNCTION(pcie0_clk),
- FUNCTION(pcie0_rst),
- FUNCTION(pcie0_wake),
- FUNCTION(pcie1_clk),
- FUNCTION(pcie1_rst),
- FUNCTION(pcie1_wake),
- FUNCTION(pcm_drx),
- FUNCTION(pcm_dtx),
- FUNCTION(pcm_fsync),
- FUNCTION(pcm_pclk),
- FUNCTION(pcm_zsi0),
- FUNCTION(pcm_zsi1),
- FUNCTION(prng_rosc),
- FUNCTION(pta1_0),
- FUNCTION(pta1_1),
- FUNCTION(pta1_2),
- FUNCTION(pta2_0),
- FUNCTION(pta2_1),
- FUNCTION(pta2_2),
- FUNCTION(pwm0),
- FUNCTION(pwm1),
- FUNCTION(pwm2),
- FUNCTION(pwm3),
- FUNCTION(qdss_cti_trig_in_a0),
- FUNCTION(qdss_cti_trig_in_a1),
- FUNCTION(qdss_cti_trig_in_b0),
- FUNCTION(qdss_cti_trig_in_b1),
- FUNCTION(qdss_cti_trig_out_a0),
- FUNCTION(qdss_cti_trig_out_a1),
- FUNCTION(qdss_cti_trig_out_b0),
- FUNCTION(qdss_cti_trig_out_b1),
- FUNCTION(qdss_traceclk_a),
- FUNCTION(qdss_traceclk_b),
- FUNCTION(qdss_tracectl_a),
- FUNCTION(qdss_tracectl_b),
- FUNCTION(qdss_tracedata_a),
- FUNCTION(qdss_tracedata_b),
- FUNCTION(qpic),
- FUNCTION(rx0),
- FUNCTION(rx1),
- FUNCTION(rx2),
- FUNCTION(sd_card),
- FUNCTION(sd_write),
- FUNCTION(tsens_max),
- FUNCTION(wci2a),
- FUNCTION(wci2b),
- FUNCTION(wci2c),
- FUNCTION(wci2d),
+static const struct pinfunction ipq8074_functions[] = {
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(audio_rxbclk),
+ MSM_PIN_FUNCTION(audio_rxd),
+ MSM_PIN_FUNCTION(audio_rxfsync),
+ MSM_PIN_FUNCTION(audio_rxmclk),
+ MSM_PIN_FUNCTION(audio_txbclk),
+ MSM_PIN_FUNCTION(audio_txd),
+ MSM_PIN_FUNCTION(audio_txfsync),
+ MSM_PIN_FUNCTION(audio_txmclk),
+ MSM_PIN_FUNCTION(blsp0_i2c),
+ MSM_PIN_FUNCTION(blsp0_spi),
+ MSM_PIN_FUNCTION(blsp0_uart),
+ MSM_PIN_FUNCTION(blsp1_i2c),
+ MSM_PIN_FUNCTION(blsp1_spi),
+ MSM_PIN_FUNCTION(blsp1_uart),
+ MSM_PIN_FUNCTION(blsp2_i2c),
+ MSM_PIN_FUNCTION(blsp2_spi),
+ MSM_PIN_FUNCTION(blsp2_uart),
+ MSM_PIN_FUNCTION(blsp3_i2c),
+ MSM_PIN_FUNCTION(blsp3_spi),
+ MSM_PIN_FUNCTION(blsp3_spi0),
+ MSM_PIN_FUNCTION(blsp3_spi1),
+ MSM_PIN_FUNCTION(blsp3_spi2),
+ MSM_PIN_FUNCTION(blsp3_spi3),
+ MSM_PIN_FUNCTION(blsp3_uart),
+ MSM_PIN_FUNCTION(blsp4_i2c0),
+ MSM_PIN_FUNCTION(blsp4_i2c1),
+ MSM_PIN_FUNCTION(blsp4_spi0),
+ MSM_PIN_FUNCTION(blsp4_spi1),
+ MSM_PIN_FUNCTION(blsp4_uart0),
+ MSM_PIN_FUNCTION(blsp4_uart1),
+ MSM_PIN_FUNCTION(blsp5_i2c),
+ MSM_PIN_FUNCTION(blsp5_spi),
+ MSM_PIN_FUNCTION(blsp5_uart),
+ MSM_PIN_FUNCTION(burn0),
+ MSM_PIN_FUNCTION(burn1),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(cxc0),
+ MSM_PIN_FUNCTION(cxc1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gcc_tlmm),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(led0),
+ MSM_PIN_FUNCTION(led1),
+ MSM_PIN_FUNCTION(led2),
+ MSM_PIN_FUNCTION(mac0_sa0),
+ MSM_PIN_FUNCTION(mac0_sa1),
+ MSM_PIN_FUNCTION(mac1_sa0),
+ MSM_PIN_FUNCTION(mac1_sa1),
+ MSM_PIN_FUNCTION(mac1_sa2),
+ MSM_PIN_FUNCTION(mac1_sa3),
+ MSM_PIN_FUNCTION(mac2_sa0),
+ MSM_PIN_FUNCTION(mac2_sa1),
+ MSM_PIN_FUNCTION(mdc),
+ MSM_PIN_FUNCTION(mdio),
+ MSM_PIN_FUNCTION(pcie0_clk),
+ MSM_PIN_FUNCTION(pcie0_rst),
+ MSM_PIN_FUNCTION(pcie0_wake),
+ MSM_PIN_FUNCTION(pcie1_clk),
+ MSM_PIN_FUNCTION(pcie1_rst),
+ MSM_PIN_FUNCTION(pcie1_wake),
+ MSM_PIN_FUNCTION(pcm_drx),
+ MSM_PIN_FUNCTION(pcm_dtx),
+ MSM_PIN_FUNCTION(pcm_fsync),
+ MSM_PIN_FUNCTION(pcm_pclk),
+ MSM_PIN_FUNCTION(pcm_zsi0),
+ MSM_PIN_FUNCTION(pcm_zsi1),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(pta1_0),
+ MSM_PIN_FUNCTION(pta1_1),
+ MSM_PIN_FUNCTION(pta1_2),
+ MSM_PIN_FUNCTION(pta2_0),
+ MSM_PIN_FUNCTION(pta2_1),
+ MSM_PIN_FUNCTION(pta2_2),
+ MSM_PIN_FUNCTION(pwm0),
+ MSM_PIN_FUNCTION(pwm1),
+ MSM_PIN_FUNCTION(pwm2),
+ MSM_PIN_FUNCTION(pwm3),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b1),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_traceclk_b),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_b),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(qpic),
+ MSM_PIN_FUNCTION(rx0),
+ MSM_PIN_FUNCTION(rx1),
+ MSM_PIN_FUNCTION(rx2),
+ MSM_PIN_FUNCTION(sd_card),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(tsens_max),
+ MSM_PIN_FUNCTION(wci2a),
+ MSM_PIN_FUNCTION(wci2b),
+ MSM_PIN_FUNCTION(wci2c),
+ MSM_PIN_FUNCTION(wci2d),
};
static const struct msm_pingroup ipq8074_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq9574.c b/drivers/pinctrl/qcom/pinctrl-ipq9574.c
index 7f057b62475f..e2491617b236 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq9574.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq9574.c
@@ -6,23 +6,15 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -623,87 +615,87 @@ static const char * const tsens_max_groups[] = {
"gpio64",
};
-static const struct msm_function ipq9574_functions[] = {
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(audio_pdm0),
- FUNCTION(audio_pdm1),
- FUNCTION(audio_pri),
- FUNCTION(audio_sec),
- FUNCTION(blsp0_spi),
- FUNCTION(blsp0_uart),
- FUNCTION(blsp1_i2c),
- FUNCTION(blsp1_spi),
- FUNCTION(blsp1_uart),
- FUNCTION(blsp2_i2c),
- FUNCTION(blsp2_spi),
- FUNCTION(blsp2_uart),
- FUNCTION(blsp3_i2c),
- FUNCTION(blsp3_spi),
- FUNCTION(blsp3_uart),
- FUNCTION(blsp4_i2c),
- FUNCTION(blsp4_spi),
- FUNCTION(blsp4_uart),
- FUNCTION(blsp5_i2c),
- FUNCTION(blsp5_uart),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(cri_trng2),
- FUNCTION(cri_trng3),
- FUNCTION(cxc0),
- FUNCTION(cxc1),
- FUNCTION(dbg_out),
- FUNCTION(dwc_ddrphy),
- FUNCTION(gcc_plltest),
- FUNCTION(gcc_tlmm),
- FUNCTION(gpio),
- FUNCTION(mac),
- FUNCTION(mdc),
- FUNCTION(mdio),
- FUNCTION(pcie0_clk),
- FUNCTION(pcie0_wake),
- FUNCTION(pcie1_clk),
- FUNCTION(pcie1_wake),
- FUNCTION(pcie2_clk),
- FUNCTION(pcie2_wake),
- FUNCTION(pcie3_clk),
- FUNCTION(pcie3_wake),
- FUNCTION(prng_rosc0),
- FUNCTION(prng_rosc1),
- FUNCTION(prng_rosc2),
- FUNCTION(prng_rosc3),
- FUNCTION(pta),
- FUNCTION(pwm),
- FUNCTION(qdss_cti_trig_in_a0),
- FUNCTION(qdss_cti_trig_in_a1),
- FUNCTION(qdss_cti_trig_in_b0),
- FUNCTION(qdss_cti_trig_in_b1),
- FUNCTION(qdss_cti_trig_out_a0),
- FUNCTION(qdss_cti_trig_out_a1),
- FUNCTION(qdss_cti_trig_out_b0),
- FUNCTION(qdss_cti_trig_out_b1),
- FUNCTION(qdss_traceclk_a),
- FUNCTION(qdss_traceclk_b),
- FUNCTION(qdss_tracectl_a),
- FUNCTION(qdss_tracectl_b),
- FUNCTION(qdss_tracedata_a),
- FUNCTION(qdss_tracedata_b),
- FUNCTION(qspi_data),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(rx0),
- FUNCTION(rx1),
- FUNCTION(sdc_data),
- FUNCTION(sdc_clk),
- FUNCTION(sdc_cmd),
- FUNCTION(sdc_rclk),
- FUNCTION(tsens_max),
- FUNCTION(wci20),
- FUNCTION(wci21),
- FUNCTION(wsa_swrm),
+static const struct pinfunction ipq9574_functions[] = {
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(audio_pdm0),
+ MSM_PIN_FUNCTION(audio_pdm1),
+ MSM_PIN_FUNCTION(audio_pri),
+ MSM_PIN_FUNCTION(audio_sec),
+ MSM_PIN_FUNCTION(blsp0_spi),
+ MSM_PIN_FUNCTION(blsp0_uart),
+ MSM_PIN_FUNCTION(blsp1_i2c),
+ MSM_PIN_FUNCTION(blsp1_spi),
+ MSM_PIN_FUNCTION(blsp1_uart),
+ MSM_PIN_FUNCTION(blsp2_i2c),
+ MSM_PIN_FUNCTION(blsp2_spi),
+ MSM_PIN_FUNCTION(blsp2_uart),
+ MSM_PIN_FUNCTION(blsp3_i2c),
+ MSM_PIN_FUNCTION(blsp3_spi),
+ MSM_PIN_FUNCTION(blsp3_uart),
+ MSM_PIN_FUNCTION(blsp4_i2c),
+ MSM_PIN_FUNCTION(blsp4_spi),
+ MSM_PIN_FUNCTION(blsp4_uart),
+ MSM_PIN_FUNCTION(blsp5_i2c),
+ MSM_PIN_FUNCTION(blsp5_uart),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(cri_trng2),
+ MSM_PIN_FUNCTION(cri_trng3),
+ MSM_PIN_FUNCTION(cxc0),
+ MSM_PIN_FUNCTION(cxc1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(dwc_ddrphy),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gcc_tlmm),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(mac),
+ MSM_PIN_FUNCTION(mdc),
+ MSM_PIN_FUNCTION(mdio),
+ MSM_PIN_FUNCTION(pcie0_clk),
+ MSM_PIN_FUNCTION(pcie0_wake),
+ MSM_PIN_FUNCTION(pcie1_clk),
+ MSM_PIN_FUNCTION(pcie1_wake),
+ MSM_PIN_FUNCTION(pcie2_clk),
+ MSM_PIN_FUNCTION(pcie2_wake),
+ MSM_PIN_FUNCTION(pcie3_clk),
+ MSM_PIN_FUNCTION(pcie3_wake),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(prng_rosc2),
+ MSM_PIN_FUNCTION(prng_rosc3),
+ MSM_PIN_FUNCTION(pta),
+ MSM_PIN_FUNCTION(pwm),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b1),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_traceclk_b),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_b),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(qspi_data),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(rx0),
+ MSM_PIN_FUNCTION(rx1),
+ MSM_PIN_FUNCTION(sdc_data),
+ MSM_PIN_FUNCTION(sdc_clk),
+ MSM_PIN_FUNCTION(sdc_cmd),
+ MSM_PIN_FUNCTION(sdc_rclk),
+ MSM_PIN_FUNCTION(tsens_max),
+ MSM_PIN_FUNCTION(wci20),
+ MSM_PIN_FUNCTION(wci21),
+ MSM_PIN_FUNCTION(wsa_swrm),
};
static const struct msm_pingroup ipq9574_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9607.c b/drivers/pinctrl/qcom/pinctrl-mdm9607.c
index d622b3df0fe7..e7cd3ef1cf3e 100644
--- a/drivers/pinctrl/qcom/pinctrl-mdm9607.c
+++ b/drivers/pinctrl/qcom/pinctrl-mdm9607.c
@@ -8,7 +8,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -204,18 +203,11 @@ static const unsigned int qdsd_data1_pins[] = { 89 };
static const unsigned int qdsd_data2_pins[] = { 90 };
static const unsigned int qdsd_data3_pins[] = { 91 };
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, \
msm_mux_##f1, \
@@ -252,9 +244,9 @@ static const unsigned int qdsd_data3_pins[] = { 91 };
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -806,134 +798,134 @@ static const char * const pwr_crypto_enabled_b_groups[] = {
"gpio79",
};
-static const struct msm_function mdm9607_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(atest_bbrx0),
- FUNCTION(atest_bbrx1),
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(atest_combodac_to_gpio_native),
- FUNCTION(atest_gpsadc_dtest0_native),
- FUNCTION(atest_gpsadc_dtest1_native),
- FUNCTION(atest_tsens),
- FUNCTION(backlight_en_b),
- FUNCTION(bimc_dte0),
- FUNCTION(bimc_dte1),
- FUNCTION(blsp1_spi),
- FUNCTION(blsp2_spi),
- FUNCTION(blsp3_spi),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_i2c5),
- FUNCTION(blsp_i2c6),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_spi5),
- FUNCTION(blsp_spi6),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_uart3),
- FUNCTION(blsp_uart4),
- FUNCTION(blsp_uart5),
- FUNCTION(blsp_uart6),
- FUNCTION(blsp_uim1),
- FUNCTION(blsp_uim2),
- FUNCTION(codec_int),
- FUNCTION(codec_rst),
- FUNCTION(coex_uart),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ebi0_wrcdc),
- FUNCTION(ebi2_a),
- FUNCTION(ebi2_a_d_8_b),
- FUNCTION(ebi2_lcd),
- FUNCTION(ebi2_lcd_cs_n_b),
- FUNCTION(ebi2_lcd_te_b),
- FUNCTION(eth_irq),
- FUNCTION(eth_rst),
- FUNCTION(gcc_gp1_clk_a),
- FUNCTION(gcc_gp1_clk_b),
- FUNCTION(gcc_gp2_clk_a),
- FUNCTION(gcc_gp2_clk_b),
- FUNCTION(gcc_gp3_clk_a),
- FUNCTION(gcc_gp3_clk_b),
- FUNCTION(gcc_plltest),
- FUNCTION(gcc_tlmm),
- FUNCTION(gmac_mdio),
- FUNCTION(gpio),
- FUNCTION(gsm0_tx),
- FUNCTION(lcd_rst),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(m_voc),
- FUNCTION(modem_tsync),
- FUNCTION(nav_ptp_pps_in_a),
- FUNCTION(nav_ptp_pps_in_b),
- FUNCTION(nav_tsync_out_a),
- FUNCTION(nav_tsync_out_b),
- FUNCTION(pa_indicator),
- FUNCTION(pbs0),
- FUNCTION(pbs1),
- FUNCTION(pbs2),
- FUNCTION(pri_mi2s_data0_a),
- FUNCTION(pri_mi2s_data1_a),
- FUNCTION(pri_mi2s_mclk_a),
- FUNCTION(pri_mi2s_sck_a),
- FUNCTION(pri_mi2s_ws_a),
- FUNCTION(prng_rosc),
- FUNCTION(ptp_pps_out_a),
- FUNCTION(ptp_pps_out_b),
- FUNCTION(pwr_crypto_enabled_a),
- FUNCTION(pwr_crypto_enabled_b),
- FUNCTION(pwr_modem_enabled_a),
- FUNCTION(pwr_modem_enabled_b),
- FUNCTION(pwr_nav_enabled_a),
- FUNCTION(pwr_nav_enabled_b),
- FUNCTION(qdss_cti_trig_in_a0),
- FUNCTION(qdss_cti_trig_in_a1),
- FUNCTION(qdss_cti_trig_in_b0),
- FUNCTION(qdss_cti_trig_in_b1),
- FUNCTION(qdss_cti_trig_out_a0),
- FUNCTION(qdss_cti_trig_out_a1),
- FUNCTION(qdss_cti_trig_out_b0),
- FUNCTION(qdss_cti_trig_out_b1),
- FUNCTION(qdss_traceclk_a),
- FUNCTION(qdss_traceclk_b),
- FUNCTION(qdss_tracectl_a),
- FUNCTION(qdss_tracectl_b),
- FUNCTION(qdss_tracedata_a),
- FUNCTION(qdss_tracedata_b),
- FUNCTION(rcm_marker1),
- FUNCTION(rcm_marker2),
- FUNCTION(sd_write),
- FUNCTION(sec_mi2s),
- FUNCTION(sensor_en),
- FUNCTION(sensor_int2),
- FUNCTION(sensor_int3),
- FUNCTION(sensor_rst),
- FUNCTION(ssbi1),
- FUNCTION(ssbi2),
- FUNCTION(touch_rst),
- FUNCTION(ts_int),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(uim_batt),
- FUNCTION(wlan_en1)
+static const struct pinfunction mdm9607_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(atest_bbrx0),
+ MSM_PIN_FUNCTION(atest_bbrx1),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_combodac_to_gpio_native),
+ MSM_PIN_FUNCTION(atest_gpsadc_dtest0_native),
+ MSM_PIN_FUNCTION(atest_gpsadc_dtest1_native),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(backlight_en_b),
+ MSM_PIN_FUNCTION(bimc_dte0),
+ MSM_PIN_FUNCTION(bimc_dte1),
+ MSM_PIN_FUNCTION(blsp1_spi),
+ MSM_PIN_FUNCTION(blsp2_spi),
+ MSM_PIN_FUNCTION(blsp3_spi),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_i2c5),
+ MSM_PIN_FUNCTION(blsp_i2c6),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(blsp_spi5),
+ MSM_PIN_FUNCTION(blsp_spi6),
+ MSM_PIN_FUNCTION(blsp_uart1),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(blsp_uart3),
+ MSM_PIN_FUNCTION(blsp_uart4),
+ MSM_PIN_FUNCTION(blsp_uart5),
+ MSM_PIN_FUNCTION(blsp_uart6),
+ MSM_PIN_FUNCTION(blsp_uim1),
+ MSM_PIN_FUNCTION(blsp_uim2),
+ MSM_PIN_FUNCTION(codec_int),
+ MSM_PIN_FUNCTION(codec_rst),
+ MSM_PIN_FUNCTION(coex_uart),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ebi0_wrcdc),
+ MSM_PIN_FUNCTION(ebi2_a),
+ MSM_PIN_FUNCTION(ebi2_a_d_8_b),
+ MSM_PIN_FUNCTION(ebi2_lcd),
+ MSM_PIN_FUNCTION(ebi2_lcd_cs_n_b),
+ MSM_PIN_FUNCTION(ebi2_lcd_te_b),
+ MSM_PIN_FUNCTION(eth_irq),
+ MSM_PIN_FUNCTION(eth_rst),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_b),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gcc_tlmm),
+ MSM_PIN_FUNCTION(gmac_mdio),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gsm0_tx),
+ MSM_PIN_FUNCTION(lcd_rst),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(modem_tsync),
+ MSM_PIN_FUNCTION(nav_ptp_pps_in_a),
+ MSM_PIN_FUNCTION(nav_ptp_pps_in_b),
+ MSM_PIN_FUNCTION(nav_tsync_out_a),
+ MSM_PIN_FUNCTION(nav_tsync_out_b),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pbs0),
+ MSM_PIN_FUNCTION(pbs1),
+ MSM_PIN_FUNCTION(pbs2),
+ MSM_PIN_FUNCTION(pri_mi2s_data0_a),
+ MSM_PIN_FUNCTION(pri_mi2s_data1_a),
+ MSM_PIN_FUNCTION(pri_mi2s_mclk_a),
+ MSM_PIN_FUNCTION(pri_mi2s_sck_a),
+ MSM_PIN_FUNCTION(pri_mi2s_ws_a),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(ptp_pps_out_a),
+ MSM_PIN_FUNCTION(ptp_pps_out_b),
+ MSM_PIN_FUNCTION(pwr_crypto_enabled_a),
+ MSM_PIN_FUNCTION(pwr_crypto_enabled_b),
+ MSM_PIN_FUNCTION(pwr_modem_enabled_a),
+ MSM_PIN_FUNCTION(pwr_modem_enabled_b),
+ MSM_PIN_FUNCTION(pwr_nav_enabled_a),
+ MSM_PIN_FUNCTION(pwr_nav_enabled_b),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b1),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_traceclk_b),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_b),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(rcm_marker1),
+ MSM_PIN_FUNCTION(rcm_marker2),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(sensor_en),
+ MSM_PIN_FUNCTION(sensor_int2),
+ MSM_PIN_FUNCTION(sensor_int3),
+ MSM_PIN_FUNCTION(sensor_rst),
+ MSM_PIN_FUNCTION(ssbi1),
+ MSM_PIN_FUNCTION(ssbi2),
+ MSM_PIN_FUNCTION(touch_rst),
+ MSM_PIN_FUNCTION(ts_int),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(wlan_en1)
};
static const struct msm_pingroup mdm9607_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9615.c b/drivers/pinctrl/qcom/pinctrl-mdm9615.c
index 24a4e439edd4..0a2ae383d3d5 100644
--- a/drivers/pinctrl/qcom/pinctrl-mdm9615.c
+++ b/drivers/pinctrl/qcom/pinctrl-mdm9615.c
@@ -8,7 +8,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include "pinctrl-msm.h"
@@ -195,31 +194,24 @@ DECLARE_MSM_GPIO_PINS(85);
DECLARE_MSM_GPIO_PINS(86);
DECLARE_MSM_GPIO_PINS(87);
-#define FUNCTION(fname) \
- [MSM_MUX_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
- MSM_MUX_gpio, \
- MSM_MUX_##f1, \
- MSM_MUX_##f2, \
- MSM_MUX_##f3, \
- MSM_MUX_##f4, \
- MSM_MUX_##f5, \
- MSM_MUX_##f6, \
- MSM_MUX_##f7, \
- MSM_MUX_##f8, \
- MSM_MUX_##f9, \
- MSM_MUX_##f10, \
- MSM_MUX_##f11 \
+ msm_mux_gpio, \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9, \
+ msm_mux_##f10, \
+ msm_mux_##f11 \
}, \
.nfuncs = 12, \
.ctl_reg = 0x1000 + 0x10 * id, \
@@ -245,19 +237,19 @@ DECLARE_MSM_GPIO_PINS(87);
}
enum mdm9615_functions {
- MSM_MUX_gpio,
- MSM_MUX_gsbi2_i2c,
- MSM_MUX_gsbi3,
- MSM_MUX_gsbi4,
- MSM_MUX_gsbi5_i2c,
- MSM_MUX_gsbi5_uart,
- MSM_MUX_sdc2,
- MSM_MUX_ebi2_lcdc,
- MSM_MUX_ps_hold,
- MSM_MUX_prim_audio,
- MSM_MUX_sec_audio,
- MSM_MUX_cdc_mclk,
- MSM_MUX_NA,
+ msm_mux_gpio,
+ msm_mux_gsbi2_i2c,
+ msm_mux_gsbi3,
+ msm_mux_gsbi4,
+ msm_mux_gsbi5_i2c,
+ msm_mux_gsbi5_uart,
+ msm_mux_sdc2,
+ msm_mux_ebi2_lcdc,
+ msm_mux_ps_hold,
+ msm_mux_prim_audio,
+ msm_mux_sec_audio,
+ msm_mux_cdc_mclk,
+ msm_mux_NA,
};
static const char * const gpio_groups[] = {
@@ -320,19 +312,19 @@ static const char * const cdc_mclk_groups[] = {
"gpio24",
};
-static const struct msm_function mdm9615_functions[] = {
- FUNCTION(gpio),
- FUNCTION(gsbi2_i2c),
- FUNCTION(gsbi3),
- FUNCTION(gsbi4),
- FUNCTION(gsbi5_i2c),
- FUNCTION(gsbi5_uart),
- FUNCTION(sdc2),
- FUNCTION(ebi2_lcdc),
- FUNCTION(ps_hold),
- FUNCTION(prim_audio),
- FUNCTION(sec_audio),
- FUNCTION(cdc_mclk),
+static const struct pinfunction mdm9615_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gsbi2_i2c),
+ MSM_PIN_FUNCTION(gsbi3),
+ MSM_PIN_FUNCTION(gsbi4),
+ MSM_PIN_FUNCTION(gsbi5_i2c),
+ MSM_PIN_FUNCTION(gsbi5_uart),
+ MSM_PIN_FUNCTION(sdc2),
+ MSM_PIN_FUNCTION(ebi2_lcdc),
+ MSM_PIN_FUNCTION(ps_hold),
+ MSM_PIN_FUNCTION(prim_audio),
+ MSM_PIN_FUNCTION(sec_audio),
+ MSM_PIN_FUNCTION(cdc_mclk),
};
static const struct msm_pingroup mdm9615_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index c5f52d4f7781..2585ef2b2793 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -23,7 +23,6 @@
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
-#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/soc/qcom/irq.h>
@@ -121,7 +120,7 @@ static const char *msm_get_group_name(struct pinctrl_dev *pctldev,
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
- return pctrl->soc->groups[group].name;
+ return pctrl->soc->groups[group].grp.name;
}
static int msm_get_group_pins(struct pinctrl_dev *pctldev,
@@ -131,8 +130,8 @@ static int msm_get_group_pins(struct pinctrl_dev *pctldev,
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
- *pins = pctrl->soc->groups[group].pins;
- *num_pins = pctrl->soc->groups[group].npins;
+ *pins = pctrl->soc->groups[group].grp.pins;
+ *num_pins = pctrl->soc->groups[group].grp.npins;
return 0;
}
@@ -706,11 +705,11 @@ static void msm_gpio_dbg_show_one(struct seq_file *s,
val = !!(io_reg & BIT(g->in_bit));
if (egpio_enable) {
- seq_printf(s, " %-8s: egpio\n", g->name);
+ seq_printf(s, " %-8s: egpio\n", g->grp.name);
return;
}
- seq_printf(s, " %-8s: %-3s", g->name, is_out ? "out" : "in");
+ seq_printf(s, " %-8s: %-3s", g->grp.name, is_out ? "out" : "in");
seq_printf(s, " %-4s func%d", val ? "high" : "low", func);
seq_printf(s, " %dmA", msm_regval_to_drive(drive));
if (pctrl->soc->pull_no_keeper)
@@ -1442,7 +1441,7 @@ static void msm_ps_hold_poweroff(void)
static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl)
{
int i;
- const struct msm_function *func = pctrl->soc->functions;
+ const struct pinfunction *func = pctrl->soc->functions;
for (i = 0; i < pctrl->soc->nfunctions; i++)
if (!strcmp(func[i].name, "ps_hold")) {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
index 985eceda2517..5e4410bed823 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.h
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
@@ -8,27 +8,35 @@
#include <linux/pm.h>
#include <linux/types.h>
+#include <linux/pinctrl/pinctrl.h>
+
struct platform_device;
struct pinctrl_pin_desc;
-/**
- * struct msm_function - a pinmux function
- * @name: Name of the pinmux function.
- * @groups: List of pingroups for this function.
- * @ngroups: Number of entries in @groups.
- */
-struct msm_function {
- const char *name;
- const char * const *groups;
- unsigned ngroups;
-};
+#define APQ_PIN_FUNCTION(fname) \
+ [APQ_MUX_##fname] = PINCTRL_PINFUNCTION(#fname, \
+ fname##_groups, \
+ ARRAY_SIZE(fname##_groups))
+
+#define IPQ_PIN_FUNCTION(fname) \
+ [IPQ_MUX_##fname] = PINCTRL_PINFUNCTION(#fname, \
+ fname##_groups, \
+ ARRAY_SIZE(fname##_groups))
+
+#define MSM_PIN_FUNCTION(fname) \
+ [msm_mux_##fname] = PINCTRL_PINFUNCTION(#fname, \
+ fname##_groups, \
+ ARRAY_SIZE(fname##_groups))
+
+#define QCA_PIN_FUNCTION(fname) \
+ [qca_mux_##fname] = PINCTRL_PINFUNCTION(#fname, \
+ fname##_groups, \
+ ARRAY_SIZE(fname##_groups))
/**
* struct msm_pingroup - Qualcomm pingroup definition
- * @name: Name of the pingroup.
- * @pins: A list of pins assigned to this pingroup.
- * @npins: Number of entries in @pins.
+ * @grp: Generic data of the pin group (name and pins)
* @funcs: A list of pinmux functions that can be selected for
* this group. The index of the selected function is used
* for programming the function selector.
@@ -61,9 +69,7 @@ struct msm_function {
* otherwise 1.
*/
struct msm_pingroup {
- const char *name;
- const unsigned *pins;
- unsigned npins;
+ struct pingroup grp;
unsigned *funcs;
unsigned nfuncs;
@@ -138,7 +144,7 @@ struct msm_gpio_wakeirq_map {
struct msm_pinctrl_soc_data {
const struct pinctrl_pin_desc *pins;
unsigned npins;
- const struct msm_function *functions;
+ const struct pinfunction *functions;
unsigned nfunctions;
const struct msm_pingroup *groups;
unsigned ngroups;
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8226.c b/drivers/pinctrl/qcom/pinctrl-msm8226.c
index 0f05725e0a21..994619840a70 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8226.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8226.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -263,27 +262,20 @@ static const unsigned int sdc2_clk_pins[] = { 120 };
static const unsigned int sdc2_cmd_pins[] = { 121 };
static const unsigned int sdc2_data_pins[] = { 122 };
-#define FUNCTION(fname) \
- [MSM_MUX_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
- MSM_MUX_gpio, \
- MSM_MUX_##f1, \
- MSM_MUX_##f2, \
- MSM_MUX_##f3, \
- MSM_MUX_##f4, \
- MSM_MUX_##f5, \
- MSM_MUX_##f6, \
- MSM_MUX_##f7 \
+ msm_mux_gpio, \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7 \
}, \
.nfuncs = 8, \
.ctl_reg = 0x1000 + 0x10 * id, \
@@ -309,9 +301,9 @@ static const unsigned int sdc2_data_pins[] = { 122 };
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -338,36 +330,36 @@ static const unsigned int sdc2_data_pins[] = { 122 };
* the pingroup table below.
*/
enum msm8226_functions {
- MSM_MUX_audio_pcm,
- MSM_MUX_blsp_i2c1,
- MSM_MUX_blsp_i2c2,
- MSM_MUX_blsp_i2c3,
- MSM_MUX_blsp_i2c4,
- MSM_MUX_blsp_i2c5,
- MSM_MUX_blsp_spi1,
- MSM_MUX_blsp_spi2,
- MSM_MUX_blsp_spi3,
- MSM_MUX_blsp_spi4,
- MSM_MUX_blsp_spi5,
- MSM_MUX_blsp_uart1,
- MSM_MUX_blsp_uart2,
- MSM_MUX_blsp_uart3,
- MSM_MUX_blsp_uart4,
- MSM_MUX_blsp_uart5,
- MSM_MUX_blsp_uim1,
- MSM_MUX_blsp_uim2,
- MSM_MUX_blsp_uim3,
- MSM_MUX_blsp_uim4,
- MSM_MUX_blsp_uim5,
- MSM_MUX_cam_mclk0,
- MSM_MUX_cam_mclk1,
- MSM_MUX_cci_i2c0,
- MSM_MUX_gp0_clk,
- MSM_MUX_gp1_clk,
- MSM_MUX_gpio,
- MSM_MUX_sdc3,
- MSM_MUX_wlan,
- MSM_MUX_NA,
+ msm_mux_audio_pcm,
+ msm_mux_blsp_i2c1,
+ msm_mux_blsp_i2c2,
+ msm_mux_blsp_i2c3,
+ msm_mux_blsp_i2c4,
+ msm_mux_blsp_i2c5,
+ msm_mux_blsp_spi1,
+ msm_mux_blsp_spi2,
+ msm_mux_blsp_spi3,
+ msm_mux_blsp_spi4,
+ msm_mux_blsp_spi5,
+ msm_mux_blsp_uart1,
+ msm_mux_blsp_uart2,
+ msm_mux_blsp_uart3,
+ msm_mux_blsp_uart4,
+ msm_mux_blsp_uart5,
+ msm_mux_blsp_uim1,
+ msm_mux_blsp_uim2,
+ msm_mux_blsp_uim3,
+ msm_mux_blsp_uim4,
+ msm_mux_blsp_uim5,
+ msm_mux_cam_mclk0,
+ msm_mux_cam_mclk1,
+ msm_mux_cci_i2c0,
+ msm_mux_gp0_clk,
+ msm_mux_gp1_clk,
+ msm_mux_gpio,
+ msm_mux_sdc3,
+ msm_mux_wlan,
+ msm_mux_NA,
};
static const char * const gpio_groups[] = {
@@ -460,36 +452,36 @@ static const char * const wlan_groups[] = {
"gpio40", "gpio41", "gpio42", "gpio43", "gpio44"
};
-static const struct msm_function msm8226_functions[] = {
- FUNCTION(audio_pcm),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_i2c5),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_spi5),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_uart3),
- FUNCTION(blsp_uart4),
- FUNCTION(blsp_uart5),
- FUNCTION(blsp_uim1),
- FUNCTION(blsp_uim2),
- FUNCTION(blsp_uim3),
- FUNCTION(blsp_uim4),
- FUNCTION(blsp_uim5),
- FUNCTION(cam_mclk0),
- FUNCTION(cam_mclk1),
- FUNCTION(cci_i2c0),
- FUNCTION(gp0_clk),
- FUNCTION(gp1_clk),
- FUNCTION(gpio),
- FUNCTION(sdc3),
- FUNCTION(wlan),
+static const struct pinfunction msm8226_functions[] = {
+ MSM_PIN_FUNCTION(audio_pcm),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_i2c5),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(blsp_spi5),
+ MSM_PIN_FUNCTION(blsp_uart1),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(blsp_uart3),
+ MSM_PIN_FUNCTION(blsp_uart4),
+ MSM_PIN_FUNCTION(blsp_uart5),
+ MSM_PIN_FUNCTION(blsp_uim1),
+ MSM_PIN_FUNCTION(blsp_uim2),
+ MSM_PIN_FUNCTION(blsp_uim3),
+ MSM_PIN_FUNCTION(blsp_uim4),
+ MSM_PIN_FUNCTION(blsp_uim5),
+ MSM_PIN_FUNCTION(cam_mclk0),
+ MSM_PIN_FUNCTION(cam_mclk1),
+ MSM_PIN_FUNCTION(cci_i2c0),
+ MSM_PIN_FUNCTION(gp0_clk),
+ MSM_PIN_FUNCTION(gp1_clk),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(sdc3),
+ MSM_PIN_FUNCTION(wlan),
};
static const struct msm_pingroup msm8226_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8660.c b/drivers/pinctrl/qcom/pinctrl-msm8660.c
index 16e562eaad17..999a5f867eb5 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8660.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8660.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -375,27 +374,20 @@ static const unsigned int sdc3_clk_pins[] = { 176 };
static const unsigned int sdc3_cmd_pins[] = { 177 };
static const unsigned int sdc3_data_pins[] = { 178 };
-#define FUNCTION(fname) \
- [MSM_MUX_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
- MSM_MUX_gpio, \
- MSM_MUX_##f1, \
- MSM_MUX_##f2, \
- MSM_MUX_##f3, \
- MSM_MUX_##f4, \
- MSM_MUX_##f5, \
- MSM_MUX_##f6, \
- MSM_MUX_##f7, \
+ msm_mux_gpio, \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
}, \
.nfuncs = 8, \
.ctl_reg = 0x1000 + 0x10 * id, \
@@ -422,9 +414,9 @@ static const unsigned int sdc3_data_pins[] = { 178 };
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -447,60 +439,60 @@ static const unsigned int sdc3_data_pins[] = { 178 };
}
enum msm8660_functions {
- MSM_MUX_gpio,
- MSM_MUX_cam_mclk,
- MSM_MUX_dsub,
- MSM_MUX_ext_gps,
- MSM_MUX_gp_clk_0a,
- MSM_MUX_gp_clk_0b,
- MSM_MUX_gp_clk_1a,
- MSM_MUX_gp_clk_1b,
- MSM_MUX_gp_clk_2a,
- MSM_MUX_gp_clk_2b,
- MSM_MUX_gp_mn,
- MSM_MUX_gsbi1,
- MSM_MUX_gsbi1_spi_cs1_n,
- MSM_MUX_gsbi1_spi_cs2a_n,
- MSM_MUX_gsbi1_spi_cs2b_n,
- MSM_MUX_gsbi1_spi_cs3_n,
- MSM_MUX_gsbi2,
- MSM_MUX_gsbi2_spi_cs1_n,
- MSM_MUX_gsbi2_spi_cs2_n,
- MSM_MUX_gsbi2_spi_cs3_n,
- MSM_MUX_gsbi3,
- MSM_MUX_gsbi3_spi_cs1_n,
- MSM_MUX_gsbi3_spi_cs2_n,
- MSM_MUX_gsbi3_spi_cs3_n,
- MSM_MUX_gsbi4,
- MSM_MUX_gsbi5,
- MSM_MUX_gsbi6,
- MSM_MUX_gsbi7,
- MSM_MUX_gsbi8,
- MSM_MUX_gsbi9,
- MSM_MUX_gsbi10,
- MSM_MUX_gsbi11,
- MSM_MUX_gsbi12,
- MSM_MUX_hdmi,
- MSM_MUX_i2s,
- MSM_MUX_lcdc,
- MSM_MUX_mdp_vsync,
- MSM_MUX_mi2s,
- MSM_MUX_pcm,
- MSM_MUX_ps_hold,
- MSM_MUX_sdc1,
- MSM_MUX_sdc2,
- MSM_MUX_sdc5,
- MSM_MUX_tsif1,
- MSM_MUX_tsif2,
- MSM_MUX_usb_fs1,
- MSM_MUX_usb_fs1_oe_n,
- MSM_MUX_usb_fs2,
- MSM_MUX_usb_fs2_oe_n,
- MSM_MUX_vfe,
- MSM_MUX_vsens_alarm,
- MSM_MUX_ebi2cs,
- MSM_MUX_ebi2,
- MSM_MUX__,
+ msm_mux_gpio,
+ msm_mux_cam_mclk,
+ msm_mux_dsub,
+ msm_mux_ext_gps,
+ msm_mux_gp_clk_0a,
+ msm_mux_gp_clk_0b,
+ msm_mux_gp_clk_1a,
+ msm_mux_gp_clk_1b,
+ msm_mux_gp_clk_2a,
+ msm_mux_gp_clk_2b,
+ msm_mux_gp_mn,
+ msm_mux_gsbi1,
+ msm_mux_gsbi1_spi_cs1_n,
+ msm_mux_gsbi1_spi_cs2a_n,
+ msm_mux_gsbi1_spi_cs2b_n,
+ msm_mux_gsbi1_spi_cs3_n,
+ msm_mux_gsbi2,
+ msm_mux_gsbi2_spi_cs1_n,
+ msm_mux_gsbi2_spi_cs2_n,
+ msm_mux_gsbi2_spi_cs3_n,
+ msm_mux_gsbi3,
+ msm_mux_gsbi3_spi_cs1_n,
+ msm_mux_gsbi3_spi_cs2_n,
+ msm_mux_gsbi3_spi_cs3_n,
+ msm_mux_gsbi4,
+ msm_mux_gsbi5,
+ msm_mux_gsbi6,
+ msm_mux_gsbi7,
+ msm_mux_gsbi8,
+ msm_mux_gsbi9,
+ msm_mux_gsbi10,
+ msm_mux_gsbi11,
+ msm_mux_gsbi12,
+ msm_mux_hdmi,
+ msm_mux_i2s,
+ msm_mux_lcdc,
+ msm_mux_mdp_vsync,
+ msm_mux_mi2s,
+ msm_mux_pcm,
+ msm_mux_ps_hold,
+ msm_mux_sdc1,
+ msm_mux_sdc2,
+ msm_mux_sdc5,
+ msm_mux_tsif1,
+ msm_mux_tsif2,
+ msm_mux_usb_fs1,
+ msm_mux_usb_fs1_oe_n,
+ msm_mux_usb_fs2,
+ msm_mux_usb_fs2_oe_n,
+ msm_mux_vfe,
+ msm_mux_vsens_alarm,
+ msm_mux_ebi2cs,
+ msm_mux_ebi2,
+ msm_mux__,
};
static const char * const gpio_groups[] = {
@@ -721,60 +713,60 @@ static const char * const ebi2_groups[] = {
"gpio158", /* busy */
};
-static const struct msm_function msm8660_functions[] = {
- FUNCTION(gpio),
- FUNCTION(cam_mclk),
- FUNCTION(dsub),
- FUNCTION(ext_gps),
- FUNCTION(gp_clk_0a),
- FUNCTION(gp_clk_0b),
- FUNCTION(gp_clk_1a),
- FUNCTION(gp_clk_1b),
- FUNCTION(gp_clk_2a),
- FUNCTION(gp_clk_2b),
- FUNCTION(gp_mn),
- FUNCTION(gsbi1),
- FUNCTION(gsbi1_spi_cs1_n),
- FUNCTION(gsbi1_spi_cs2a_n),
- FUNCTION(gsbi1_spi_cs2b_n),
- FUNCTION(gsbi1_spi_cs3_n),
- FUNCTION(gsbi2),
- FUNCTION(gsbi2_spi_cs1_n),
- FUNCTION(gsbi2_spi_cs2_n),
- FUNCTION(gsbi2_spi_cs3_n),
- FUNCTION(gsbi3),
- FUNCTION(gsbi3_spi_cs1_n),
- FUNCTION(gsbi3_spi_cs2_n),
- FUNCTION(gsbi3_spi_cs3_n),
- FUNCTION(gsbi4),
- FUNCTION(gsbi5),
- FUNCTION(gsbi6),
- FUNCTION(gsbi7),
- FUNCTION(gsbi8),
- FUNCTION(gsbi9),
- FUNCTION(gsbi10),
- FUNCTION(gsbi11),
- FUNCTION(gsbi12),
- FUNCTION(hdmi),
- FUNCTION(i2s),
- FUNCTION(lcdc),
- FUNCTION(mdp_vsync),
- FUNCTION(mi2s),
- FUNCTION(pcm),
- FUNCTION(ps_hold),
- FUNCTION(sdc1),
- FUNCTION(sdc2),
- FUNCTION(sdc5),
- FUNCTION(tsif1),
- FUNCTION(tsif2),
- FUNCTION(usb_fs1),
- FUNCTION(usb_fs1_oe_n),
- FUNCTION(usb_fs2),
- FUNCTION(usb_fs2_oe_n),
- FUNCTION(vfe),
- FUNCTION(vsens_alarm),
- FUNCTION(ebi2cs), /* for EBI2 chip selects */
- FUNCTION(ebi2), /* for general EBI2 pins */
+static const struct pinfunction msm8660_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(dsub),
+ MSM_PIN_FUNCTION(ext_gps),
+ MSM_PIN_FUNCTION(gp_clk_0a),
+ MSM_PIN_FUNCTION(gp_clk_0b),
+ MSM_PIN_FUNCTION(gp_clk_1a),
+ MSM_PIN_FUNCTION(gp_clk_1b),
+ MSM_PIN_FUNCTION(gp_clk_2a),
+ MSM_PIN_FUNCTION(gp_clk_2b),
+ MSM_PIN_FUNCTION(gp_mn),
+ MSM_PIN_FUNCTION(gsbi1),
+ MSM_PIN_FUNCTION(gsbi1_spi_cs1_n),
+ MSM_PIN_FUNCTION(gsbi1_spi_cs2a_n),
+ MSM_PIN_FUNCTION(gsbi1_spi_cs2b_n),
+ MSM_PIN_FUNCTION(gsbi1_spi_cs3_n),
+ MSM_PIN_FUNCTION(gsbi2),
+ MSM_PIN_FUNCTION(gsbi2_spi_cs1_n),
+ MSM_PIN_FUNCTION(gsbi2_spi_cs2_n),
+ MSM_PIN_FUNCTION(gsbi2_spi_cs3_n),
+ MSM_PIN_FUNCTION(gsbi3),
+ MSM_PIN_FUNCTION(gsbi3_spi_cs1_n),
+ MSM_PIN_FUNCTION(gsbi3_spi_cs2_n),
+ MSM_PIN_FUNCTION(gsbi3_spi_cs3_n),
+ MSM_PIN_FUNCTION(gsbi4),
+ MSM_PIN_FUNCTION(gsbi5),
+ MSM_PIN_FUNCTION(gsbi6),
+ MSM_PIN_FUNCTION(gsbi7),
+ MSM_PIN_FUNCTION(gsbi8),
+ MSM_PIN_FUNCTION(gsbi9),
+ MSM_PIN_FUNCTION(gsbi10),
+ MSM_PIN_FUNCTION(gsbi11),
+ MSM_PIN_FUNCTION(gsbi12),
+ MSM_PIN_FUNCTION(hdmi),
+ MSM_PIN_FUNCTION(i2s),
+ MSM_PIN_FUNCTION(lcdc),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mi2s),
+ MSM_PIN_FUNCTION(pcm),
+ MSM_PIN_FUNCTION(ps_hold),
+ MSM_PIN_FUNCTION(sdc1),
+ MSM_PIN_FUNCTION(sdc2),
+ MSM_PIN_FUNCTION(sdc5),
+ MSM_PIN_FUNCTION(tsif1),
+ MSM_PIN_FUNCTION(tsif2),
+ MSM_PIN_FUNCTION(usb_fs1),
+ MSM_PIN_FUNCTION(usb_fs1_oe_n),
+ MSM_PIN_FUNCTION(usb_fs2),
+ MSM_PIN_FUNCTION(usb_fs2_oe_n),
+ MSM_PIN_FUNCTION(vfe),
+ MSM_PIN_FUNCTION(vsens_alarm),
+ MSM_PIN_FUNCTION(ebi2cs), /* for EBI2 chip selects */
+ MSM_PIN_FUNCTION(ebi2), /* for general EBI2 pins */
};
static const struct msm_pingroup msm8660_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8909.c b/drivers/pinctrl/qcom/pinctrl-msm8909.c
index 6dd15b910632..756856d20d6b 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8909.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8909.c
@@ -7,23 +7,15 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, \
msm_mux_##f1, \
@@ -60,9 +52,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -643,130 +635,130 @@ static const char * const wcss_wlan_groups[] = {
"gpio40", "gpio41", "gpio42", "gpio43", "gpio44"
};
-static const struct msm_function msm8909_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(atest_bbrx0),
- FUNCTION(atest_bbrx1),
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(atest_combodac),
- FUNCTION(atest_gpsadc0),
- FUNCTION(atest_gpsadc1),
- FUNCTION(atest_wlan0),
- FUNCTION(atest_wlan1),
- FUNCTION(bimc_dte0),
- FUNCTION(bimc_dte1),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_i2c5),
- FUNCTION(blsp_i2c6),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi1_cs1),
- FUNCTION(blsp_spi1_cs2),
- FUNCTION(blsp_spi1_cs3),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi2_cs1),
- FUNCTION(blsp_spi2_cs2),
- FUNCTION(blsp_spi2_cs3),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi3_cs1),
- FUNCTION(blsp_spi3_cs2),
- FUNCTION(blsp_spi3_cs3),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_spi5),
- FUNCTION(blsp_spi6),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_uim1),
- FUNCTION(blsp_uim2),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cdc_pdm0),
- FUNCTION(dbg_out),
- FUNCTION(dmic0_clk),
- FUNCTION(dmic0_data),
- FUNCTION(ebi0_wrcdc),
- FUNCTION(ebi2_a),
- FUNCTION(ebi2_lcd),
- FUNCTION(ext_lpass),
- FUNCTION(gcc_gp1_clk_a),
- FUNCTION(gcc_gp1_clk_b),
- FUNCTION(gcc_gp2_clk_a),
- FUNCTION(gcc_gp2_clk_b),
- FUNCTION(gcc_gp3_clk_a),
- FUNCTION(gcc_gp3_clk_b),
- FUNCTION(gcc_plltest),
- FUNCTION(gpio),
- FUNCTION(gsm0_tx),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(m_voc),
- FUNCTION(mdp_vsync),
- FUNCTION(modem_tsync),
- FUNCTION(nav_pps),
- FUNCTION(nav_tsync),
- FUNCTION(pa_indicator),
- FUNCTION(pbs0),
- FUNCTION(pbs1),
- FUNCTION(pbs2),
- FUNCTION(pri_mi2s_data0_a),
- FUNCTION(pri_mi2s_data0_b),
- FUNCTION(pri_mi2s_data1_a),
- FUNCTION(pri_mi2s_data1_b),
- FUNCTION(pri_mi2s_mclk_a),
- FUNCTION(pri_mi2s_mclk_b),
- FUNCTION(pri_mi2s_sck_a),
- FUNCTION(pri_mi2s_sck_b),
- FUNCTION(pri_mi2s_ws_a),
- FUNCTION(pri_mi2s_ws_b),
- FUNCTION(prng_rosc),
- FUNCTION(pwr_crypto_enabled_a),
- FUNCTION(pwr_crypto_enabled_b),
- FUNCTION(pwr_modem_enabled_a),
- FUNCTION(pwr_modem_enabled_b),
- FUNCTION(pwr_nav_enabled_a),
- FUNCTION(pwr_nav_enabled_b),
- FUNCTION(qdss_cti_trig_in_a0),
- FUNCTION(qdss_cti_trig_in_a1),
- FUNCTION(qdss_cti_trig_in_b0),
- FUNCTION(qdss_cti_trig_in_b1),
- FUNCTION(qdss_cti_trig_out_a0),
- FUNCTION(qdss_cti_trig_out_a1),
- FUNCTION(qdss_cti_trig_out_b0),
- FUNCTION(qdss_cti_trig_out_b1),
- FUNCTION(qdss_traceclk_a),
- FUNCTION(qdss_tracectl_a),
- FUNCTION(qdss_tracedata_a),
- FUNCTION(qdss_tracedata_b),
- FUNCTION(sd_write),
- FUNCTION(sec_mi2s),
- FUNCTION(smb_int),
- FUNCTION(ssbi0),
- FUNCTION(ssbi1),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(uim3_clk),
- FUNCTION(uim3_data),
- FUNCTION(uim3_present),
- FUNCTION(uim3_reset),
- FUNCTION(uim_batt),
- FUNCTION(wcss_bt),
- FUNCTION(wcss_fm),
- FUNCTION(wcss_wlan),
+static const struct pinfunction msm8909_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(atest_bbrx0),
+ MSM_PIN_FUNCTION(atest_bbrx1),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_combodac),
+ MSM_PIN_FUNCTION(atest_gpsadc0),
+ MSM_PIN_FUNCTION(atest_gpsadc1),
+ MSM_PIN_FUNCTION(atest_wlan0),
+ MSM_PIN_FUNCTION(atest_wlan1),
+ MSM_PIN_FUNCTION(bimc_dte0),
+ MSM_PIN_FUNCTION(bimc_dte1),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_i2c5),
+ MSM_PIN_FUNCTION(blsp_i2c6),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(blsp_spi1_cs1),
+ MSM_PIN_FUNCTION(blsp_spi1_cs2),
+ MSM_PIN_FUNCTION(blsp_spi1_cs3),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_spi2_cs1),
+ MSM_PIN_FUNCTION(blsp_spi2_cs2),
+ MSM_PIN_FUNCTION(blsp_spi2_cs3),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(blsp_spi3_cs1),
+ MSM_PIN_FUNCTION(blsp_spi3_cs2),
+ MSM_PIN_FUNCTION(blsp_spi3_cs3),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(blsp_spi5),
+ MSM_PIN_FUNCTION(blsp_spi6),
+ MSM_PIN_FUNCTION(blsp_uart1),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(blsp_uim1),
+ MSM_PIN_FUNCTION(blsp_uim2),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cdc_pdm0),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(dmic0_clk),
+ MSM_PIN_FUNCTION(dmic0_data),
+ MSM_PIN_FUNCTION(ebi0_wrcdc),
+ MSM_PIN_FUNCTION(ebi2_a),
+ MSM_PIN_FUNCTION(ebi2_lcd),
+ MSM_PIN_FUNCTION(ext_lpass),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_b),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gsm0_tx),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(modem_tsync),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(nav_tsync),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pbs0),
+ MSM_PIN_FUNCTION(pbs1),
+ MSM_PIN_FUNCTION(pbs2),
+ MSM_PIN_FUNCTION(pri_mi2s_data0_a),
+ MSM_PIN_FUNCTION(pri_mi2s_data0_b),
+ MSM_PIN_FUNCTION(pri_mi2s_data1_a),
+ MSM_PIN_FUNCTION(pri_mi2s_data1_b),
+ MSM_PIN_FUNCTION(pri_mi2s_mclk_a),
+ MSM_PIN_FUNCTION(pri_mi2s_mclk_b),
+ MSM_PIN_FUNCTION(pri_mi2s_sck_a),
+ MSM_PIN_FUNCTION(pri_mi2s_sck_b),
+ MSM_PIN_FUNCTION(pri_mi2s_ws_a),
+ MSM_PIN_FUNCTION(pri_mi2s_ws_b),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(pwr_crypto_enabled_a),
+ MSM_PIN_FUNCTION(pwr_crypto_enabled_b),
+ MSM_PIN_FUNCTION(pwr_modem_enabled_a),
+ MSM_PIN_FUNCTION(pwr_modem_enabled_b),
+ MSM_PIN_FUNCTION(pwr_nav_enabled_a),
+ MSM_PIN_FUNCTION(pwr_nav_enabled_b),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b1),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(smb_int),
+ MSM_PIN_FUNCTION(ssbi0),
+ MSM_PIN_FUNCTION(ssbi1),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(uim3_clk),
+ MSM_PIN_FUNCTION(uim3_data),
+ MSM_PIN_FUNCTION(uim3_present),
+ MSM_PIN_FUNCTION(uim3_reset),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(wcss_bt),
+ MSM_PIN_FUNCTION(wcss_fm),
+ MSM_PIN_FUNCTION(wcss_wlan),
};
static const struct msm_pingroup msm8909_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8916.c b/drivers/pinctrl/qcom/pinctrl-msm8916.c
index bf68913ba821..cea5c54f92fe 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8916.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8916.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -286,29 +285,22 @@ static const unsigned int qdsd_data1_pins[] = { 131 };
static const unsigned int qdsd_data2_pins[] = { 132 };
static const unsigned int qdsd_data3_pins[] = { 133 };
-#define FUNCTION(fname) \
- [MSM_MUX_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
- MSM_MUX_gpio, \
- MSM_MUX_##f1, \
- MSM_MUX_##f2, \
- MSM_MUX_##f3, \
- MSM_MUX_##f4, \
- MSM_MUX_##f5, \
- MSM_MUX_##f6, \
- MSM_MUX_##f7, \
- MSM_MUX_##f8, \
- MSM_MUX_##f9 \
+ msm_mux_gpio, \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9 \
}, \
.nfuncs = 10, \
.ctl_reg = 0x1000 * id, \
@@ -334,9 +326,9 @@ static const unsigned int qdsd_data3_pins[] = { 133 };
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -359,135 +351,135 @@ static const unsigned int qdsd_data3_pins[] = { 133 };
}
enum msm8916_functions {
- MSM_MUX_adsp_ext,
- MSM_MUX_alsp_int,
- MSM_MUX_atest_bbrx0,
- MSM_MUX_atest_bbrx1,
- MSM_MUX_atest_char,
- MSM_MUX_atest_char0,
- MSM_MUX_atest_char1,
- MSM_MUX_atest_char2,
- MSM_MUX_atest_char3,
- MSM_MUX_atest_combodac,
- MSM_MUX_atest_gpsadc0,
- MSM_MUX_atest_gpsadc1,
- MSM_MUX_atest_tsens,
- MSM_MUX_atest_wlan0,
- MSM_MUX_atest_wlan1,
- MSM_MUX_backlight_en,
- MSM_MUX_bimc_dte0,
- MSM_MUX_bimc_dte1,
- MSM_MUX_blsp_i2c1,
- MSM_MUX_blsp_i2c2,
- MSM_MUX_blsp_i2c3,
- MSM_MUX_blsp_i2c4,
- MSM_MUX_blsp_i2c5,
- MSM_MUX_blsp_i2c6,
- MSM_MUX_blsp_spi1,
- MSM_MUX_blsp_spi1_cs1,
- MSM_MUX_blsp_spi1_cs2,
- MSM_MUX_blsp_spi1_cs3,
- MSM_MUX_blsp_spi2,
- MSM_MUX_blsp_spi2_cs1,
- MSM_MUX_blsp_spi2_cs2,
- MSM_MUX_blsp_spi2_cs3,
- MSM_MUX_blsp_spi3,
- MSM_MUX_blsp_spi3_cs1,
- MSM_MUX_blsp_spi3_cs2,
- MSM_MUX_blsp_spi3_cs3,
- MSM_MUX_blsp_spi4,
- MSM_MUX_blsp_spi5,
- MSM_MUX_blsp_spi6,
- MSM_MUX_blsp_uart1,
- MSM_MUX_blsp_uart2,
- MSM_MUX_blsp_uim1,
- MSM_MUX_blsp_uim2,
- MSM_MUX_cam1_rst,
- MSM_MUX_cam1_standby,
- MSM_MUX_cam_mclk0,
- MSM_MUX_cam_mclk1,
- MSM_MUX_cci_async,
- MSM_MUX_cci_i2c,
- MSM_MUX_cci_timer0,
- MSM_MUX_cci_timer1,
- MSM_MUX_cci_timer2,
- MSM_MUX_cdc_pdm0,
- MSM_MUX_codec_mad,
- MSM_MUX_dbg_out,
- MSM_MUX_display_5v,
- MSM_MUX_dmic0_clk,
- MSM_MUX_dmic0_data,
- MSM_MUX_dsi_rst,
- MSM_MUX_ebi0_wrcdc,
- MSM_MUX_euro_us,
- MSM_MUX_ext_lpass,
- MSM_MUX_flash_strobe,
- MSM_MUX_gcc_gp1_clk_a,
- MSM_MUX_gcc_gp1_clk_b,
- MSM_MUX_gcc_gp2_clk_a,
- MSM_MUX_gcc_gp2_clk_b,
- MSM_MUX_gcc_gp3_clk_a,
- MSM_MUX_gcc_gp3_clk_b,
- MSM_MUX_gpio,
- MSM_MUX_gsm0_tx0,
- MSM_MUX_gsm0_tx1,
- MSM_MUX_gsm1_tx0,
- MSM_MUX_gsm1_tx1,
- MSM_MUX_gyro_accl,
- MSM_MUX_kpsns0,
- MSM_MUX_kpsns1,
- MSM_MUX_kpsns2,
- MSM_MUX_ldo_en,
- MSM_MUX_ldo_update,
- MSM_MUX_mag_int,
- MSM_MUX_mdp_vsync,
- MSM_MUX_modem_tsync,
- MSM_MUX_m_voc,
- MSM_MUX_nav_pps,
- MSM_MUX_nav_tsync,
- MSM_MUX_pa_indicator,
- MSM_MUX_pbs0,
- MSM_MUX_pbs1,
- MSM_MUX_pbs2,
- MSM_MUX_pri_mi2s,
- MSM_MUX_pri_mi2s_ws,
- MSM_MUX_prng_rosc,
- MSM_MUX_pwr_crypto_enabled_a,
- MSM_MUX_pwr_crypto_enabled_b,
- MSM_MUX_pwr_modem_enabled_a,
- MSM_MUX_pwr_modem_enabled_b,
- MSM_MUX_pwr_nav_enabled_a,
- MSM_MUX_pwr_nav_enabled_b,
- MSM_MUX_qdss_ctitrig_in_a0,
- MSM_MUX_qdss_ctitrig_in_a1,
- MSM_MUX_qdss_ctitrig_in_b0,
- MSM_MUX_qdss_ctitrig_in_b1,
- MSM_MUX_qdss_ctitrig_out_a0,
- MSM_MUX_qdss_ctitrig_out_a1,
- MSM_MUX_qdss_ctitrig_out_b0,
- MSM_MUX_qdss_ctitrig_out_b1,
- MSM_MUX_qdss_traceclk_a,
- MSM_MUX_qdss_traceclk_b,
- MSM_MUX_qdss_tracectl_a,
- MSM_MUX_qdss_tracectl_b,
- MSM_MUX_qdss_tracedata_a,
- MSM_MUX_qdss_tracedata_b,
- MSM_MUX_reset_n,
- MSM_MUX_sd_card,
- MSM_MUX_sd_write,
- MSM_MUX_sec_mi2s,
- MSM_MUX_smb_int,
- MSM_MUX_ssbi_wtr0,
- MSM_MUX_ssbi_wtr1,
- MSM_MUX_uim1,
- MSM_MUX_uim2,
- MSM_MUX_uim3,
- MSM_MUX_uim_batt,
- MSM_MUX_wcss_bt,
- MSM_MUX_wcss_fm,
- MSM_MUX_wcss_wlan,
- MSM_MUX_webcam1_rst,
- MSM_MUX_NA,
+ msm_mux_adsp_ext,
+ msm_mux_alsp_int,
+ msm_mux_atest_bbrx0,
+ msm_mux_atest_bbrx1,
+ msm_mux_atest_char,
+ msm_mux_atest_char0,
+ msm_mux_atest_char1,
+ msm_mux_atest_char2,
+ msm_mux_atest_char3,
+ msm_mux_atest_combodac,
+ msm_mux_atest_gpsadc0,
+ msm_mux_atest_gpsadc1,
+ msm_mux_atest_tsens,
+ msm_mux_atest_wlan0,
+ msm_mux_atest_wlan1,
+ msm_mux_backlight_en,
+ msm_mux_bimc_dte0,
+ msm_mux_bimc_dte1,
+ msm_mux_blsp_i2c1,
+ msm_mux_blsp_i2c2,
+ msm_mux_blsp_i2c3,
+ msm_mux_blsp_i2c4,
+ msm_mux_blsp_i2c5,
+ msm_mux_blsp_i2c6,
+ msm_mux_blsp_spi1,
+ msm_mux_blsp_spi1_cs1,
+ msm_mux_blsp_spi1_cs2,
+ msm_mux_blsp_spi1_cs3,
+ msm_mux_blsp_spi2,
+ msm_mux_blsp_spi2_cs1,
+ msm_mux_blsp_spi2_cs2,
+ msm_mux_blsp_spi2_cs3,
+ msm_mux_blsp_spi3,
+ msm_mux_blsp_spi3_cs1,
+ msm_mux_blsp_spi3_cs2,
+ msm_mux_blsp_spi3_cs3,
+ msm_mux_blsp_spi4,
+ msm_mux_blsp_spi5,
+ msm_mux_blsp_spi6,
+ msm_mux_blsp_uart1,
+ msm_mux_blsp_uart2,
+ msm_mux_blsp_uim1,
+ msm_mux_blsp_uim2,
+ msm_mux_cam1_rst,
+ msm_mux_cam1_standby,
+ msm_mux_cam_mclk0,
+ msm_mux_cam_mclk1,
+ msm_mux_cci_async,
+ msm_mux_cci_i2c,
+ msm_mux_cci_timer0,
+ msm_mux_cci_timer1,
+ msm_mux_cci_timer2,
+ msm_mux_cdc_pdm0,
+ msm_mux_codec_mad,
+ msm_mux_dbg_out,
+ msm_mux_display_5v,
+ msm_mux_dmic0_clk,
+ msm_mux_dmic0_data,
+ msm_mux_dsi_rst,
+ msm_mux_ebi0_wrcdc,
+ msm_mux_euro_us,
+ msm_mux_ext_lpass,
+ msm_mux_flash_strobe,
+ msm_mux_gcc_gp1_clk_a,
+ msm_mux_gcc_gp1_clk_b,
+ msm_mux_gcc_gp2_clk_a,
+ msm_mux_gcc_gp2_clk_b,
+ msm_mux_gcc_gp3_clk_a,
+ msm_mux_gcc_gp3_clk_b,
+ msm_mux_gpio,
+ msm_mux_gsm0_tx0,
+ msm_mux_gsm0_tx1,
+ msm_mux_gsm1_tx0,
+ msm_mux_gsm1_tx1,
+ msm_mux_gyro_accl,
+ msm_mux_kpsns0,
+ msm_mux_kpsns1,
+ msm_mux_kpsns2,
+ msm_mux_ldo_en,
+ msm_mux_ldo_update,
+ msm_mux_mag_int,
+ msm_mux_mdp_vsync,
+ msm_mux_modem_tsync,
+ msm_mux_m_voc,
+ msm_mux_nav_pps,
+ msm_mux_nav_tsync,
+ msm_mux_pa_indicator,
+ msm_mux_pbs0,
+ msm_mux_pbs1,
+ msm_mux_pbs2,
+ msm_mux_pri_mi2s,
+ msm_mux_pri_mi2s_ws,
+ msm_mux_prng_rosc,
+ msm_mux_pwr_crypto_enabled_a,
+ msm_mux_pwr_crypto_enabled_b,
+ msm_mux_pwr_modem_enabled_a,
+ msm_mux_pwr_modem_enabled_b,
+ msm_mux_pwr_nav_enabled_a,
+ msm_mux_pwr_nav_enabled_b,
+ msm_mux_qdss_ctitrig_in_a0,
+ msm_mux_qdss_ctitrig_in_a1,
+ msm_mux_qdss_ctitrig_in_b0,
+ msm_mux_qdss_ctitrig_in_b1,
+ msm_mux_qdss_ctitrig_out_a0,
+ msm_mux_qdss_ctitrig_out_a1,
+ msm_mux_qdss_ctitrig_out_b0,
+ msm_mux_qdss_ctitrig_out_b1,
+ msm_mux_qdss_traceclk_a,
+ msm_mux_qdss_traceclk_b,
+ msm_mux_qdss_tracectl_a,
+ msm_mux_qdss_tracectl_b,
+ msm_mux_qdss_tracedata_a,
+ msm_mux_qdss_tracedata_b,
+ msm_mux_reset_n,
+ msm_mux_sd_card,
+ msm_mux_sd_write,
+ msm_mux_sec_mi2s,
+ msm_mux_smb_int,
+ msm_mux_ssbi_wtr0,
+ msm_mux_ssbi_wtr1,
+ msm_mux_uim1,
+ msm_mux_uim2,
+ msm_mux_uim3,
+ msm_mux_uim_batt,
+ msm_mux_wcss_bt,
+ msm_mux_wcss_fm,
+ msm_mux_wcss_wlan,
+ msm_mux_webcam1_rst,
+ msm_mux_NA,
};
static const char * const gpio_groups[] = {
@@ -681,135 +673,135 @@ static const char * const wcss_wlan_groups[] = {
};
static const char * const webcam1_rst_groups[] = { "gpio28" };
-static const struct msm_function msm8916_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(alsp_int),
- FUNCTION(atest_bbrx0),
- FUNCTION(atest_bbrx1),
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(atest_combodac),
- FUNCTION(atest_gpsadc0),
- FUNCTION(atest_gpsadc1),
- FUNCTION(atest_tsens),
- FUNCTION(atest_wlan0),
- FUNCTION(atest_wlan1),
- FUNCTION(backlight_en),
- FUNCTION(bimc_dte0),
- FUNCTION(bimc_dte1),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_i2c5),
- FUNCTION(blsp_i2c6),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi1_cs1),
- FUNCTION(blsp_spi1_cs2),
- FUNCTION(blsp_spi1_cs3),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi2_cs1),
- FUNCTION(blsp_spi2_cs2),
- FUNCTION(blsp_spi2_cs3),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi3_cs1),
- FUNCTION(blsp_spi3_cs2),
- FUNCTION(blsp_spi3_cs3),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_spi5),
- FUNCTION(blsp_spi6),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_uim1),
- FUNCTION(blsp_uim2),
- FUNCTION(cam1_rst),
- FUNCTION(cam1_standby),
- FUNCTION(cam_mclk0),
- FUNCTION(cam_mclk1),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cdc_pdm0),
- FUNCTION(codec_mad),
- FUNCTION(dbg_out),
- FUNCTION(display_5v),
- FUNCTION(dmic0_clk),
- FUNCTION(dmic0_data),
- FUNCTION(dsi_rst),
- FUNCTION(ebi0_wrcdc),
- FUNCTION(euro_us),
- FUNCTION(ext_lpass),
- FUNCTION(flash_strobe),
- FUNCTION(gcc_gp1_clk_a),
- FUNCTION(gcc_gp1_clk_b),
- FUNCTION(gcc_gp2_clk_a),
- FUNCTION(gcc_gp2_clk_b),
- FUNCTION(gcc_gp3_clk_a),
- FUNCTION(gcc_gp3_clk_b),
- FUNCTION(gpio),
- FUNCTION(gsm0_tx0),
- FUNCTION(gsm0_tx1),
- FUNCTION(gsm1_tx0),
- FUNCTION(gsm1_tx1),
- FUNCTION(gyro_accl),
- FUNCTION(kpsns0),
- FUNCTION(kpsns1),
- FUNCTION(kpsns2),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(mag_int),
- FUNCTION(mdp_vsync),
- FUNCTION(modem_tsync),
- FUNCTION(m_voc),
- FUNCTION(nav_pps),
- FUNCTION(nav_tsync),
- FUNCTION(pa_indicator),
- FUNCTION(pbs0),
- FUNCTION(pbs1),
- FUNCTION(pbs2),
- FUNCTION(pri_mi2s),
- FUNCTION(pri_mi2s_ws),
- FUNCTION(prng_rosc),
- FUNCTION(pwr_crypto_enabled_a),
- FUNCTION(pwr_crypto_enabled_b),
- FUNCTION(pwr_modem_enabled_a),
- FUNCTION(pwr_modem_enabled_b),
- FUNCTION(pwr_nav_enabled_a),
- FUNCTION(pwr_nav_enabled_b),
- FUNCTION(qdss_ctitrig_in_a0),
- FUNCTION(qdss_ctitrig_in_a1),
- FUNCTION(qdss_ctitrig_in_b0),
- FUNCTION(qdss_ctitrig_in_b1),
- FUNCTION(qdss_ctitrig_out_a0),
- FUNCTION(qdss_ctitrig_out_a1),
- FUNCTION(qdss_ctitrig_out_b0),
- FUNCTION(qdss_ctitrig_out_b1),
- FUNCTION(qdss_traceclk_a),
- FUNCTION(qdss_traceclk_b),
- FUNCTION(qdss_tracectl_a),
- FUNCTION(qdss_tracectl_b),
- FUNCTION(qdss_tracedata_a),
- FUNCTION(qdss_tracedata_b),
- FUNCTION(reset_n),
- FUNCTION(sd_card),
- FUNCTION(sd_write),
- FUNCTION(sec_mi2s),
- FUNCTION(smb_int),
- FUNCTION(ssbi_wtr0),
- FUNCTION(ssbi_wtr1),
- FUNCTION(uim1),
- FUNCTION(uim2),
- FUNCTION(uim3),
- FUNCTION(uim_batt),
- FUNCTION(wcss_bt),
- FUNCTION(wcss_fm),
- FUNCTION(wcss_wlan),
- FUNCTION(webcam1_rst)
+static const struct pinfunction msm8916_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(alsp_int),
+ MSM_PIN_FUNCTION(atest_bbrx0),
+ MSM_PIN_FUNCTION(atest_bbrx1),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_combodac),
+ MSM_PIN_FUNCTION(atest_gpsadc0),
+ MSM_PIN_FUNCTION(atest_gpsadc1),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_wlan0),
+ MSM_PIN_FUNCTION(atest_wlan1),
+ MSM_PIN_FUNCTION(backlight_en),
+ MSM_PIN_FUNCTION(bimc_dte0),
+ MSM_PIN_FUNCTION(bimc_dte1),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_i2c5),
+ MSM_PIN_FUNCTION(blsp_i2c6),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(blsp_spi1_cs1),
+ MSM_PIN_FUNCTION(blsp_spi1_cs2),
+ MSM_PIN_FUNCTION(blsp_spi1_cs3),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_spi2_cs1),
+ MSM_PIN_FUNCTION(blsp_spi2_cs2),
+ MSM_PIN_FUNCTION(blsp_spi2_cs3),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(blsp_spi3_cs1),
+ MSM_PIN_FUNCTION(blsp_spi3_cs2),
+ MSM_PIN_FUNCTION(blsp_spi3_cs3),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(blsp_spi5),
+ MSM_PIN_FUNCTION(blsp_spi6),
+ MSM_PIN_FUNCTION(blsp_uart1),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(blsp_uim1),
+ MSM_PIN_FUNCTION(blsp_uim2),
+ MSM_PIN_FUNCTION(cam1_rst),
+ MSM_PIN_FUNCTION(cam1_standby),
+ MSM_PIN_FUNCTION(cam_mclk0),
+ MSM_PIN_FUNCTION(cam_mclk1),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cdc_pdm0),
+ MSM_PIN_FUNCTION(codec_mad),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(display_5v),
+ MSM_PIN_FUNCTION(dmic0_clk),
+ MSM_PIN_FUNCTION(dmic0_data),
+ MSM_PIN_FUNCTION(dsi_rst),
+ MSM_PIN_FUNCTION(ebi0_wrcdc),
+ MSM_PIN_FUNCTION(euro_us),
+ MSM_PIN_FUNCTION(ext_lpass),
+ MSM_PIN_FUNCTION(flash_strobe),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_b),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gsm0_tx0),
+ MSM_PIN_FUNCTION(gsm0_tx1),
+ MSM_PIN_FUNCTION(gsm1_tx0),
+ MSM_PIN_FUNCTION(gsm1_tx1),
+ MSM_PIN_FUNCTION(gyro_accl),
+ MSM_PIN_FUNCTION(kpsns0),
+ MSM_PIN_FUNCTION(kpsns1),
+ MSM_PIN_FUNCTION(kpsns2),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(mag_int),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(modem_tsync),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(nav_tsync),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pbs0),
+ MSM_PIN_FUNCTION(pbs1),
+ MSM_PIN_FUNCTION(pbs2),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(pri_mi2s_ws),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(pwr_crypto_enabled_a),
+ MSM_PIN_FUNCTION(pwr_crypto_enabled_b),
+ MSM_PIN_FUNCTION(pwr_modem_enabled_a),
+ MSM_PIN_FUNCTION(pwr_modem_enabled_b),
+ MSM_PIN_FUNCTION(pwr_nav_enabled_a),
+ MSM_PIN_FUNCTION(pwr_nav_enabled_b),
+ MSM_PIN_FUNCTION(qdss_ctitrig_in_a0),
+ MSM_PIN_FUNCTION(qdss_ctitrig_in_a1),
+ MSM_PIN_FUNCTION(qdss_ctitrig_in_b0),
+ MSM_PIN_FUNCTION(qdss_ctitrig_in_b1),
+ MSM_PIN_FUNCTION(qdss_ctitrig_out_a0),
+ MSM_PIN_FUNCTION(qdss_ctitrig_out_a1),
+ MSM_PIN_FUNCTION(qdss_ctitrig_out_b0),
+ MSM_PIN_FUNCTION(qdss_ctitrig_out_b1),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_traceclk_b),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_b),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(reset_n),
+ MSM_PIN_FUNCTION(sd_card),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(smb_int),
+ MSM_PIN_FUNCTION(ssbi_wtr0),
+ MSM_PIN_FUNCTION(ssbi_wtr1),
+ MSM_PIN_FUNCTION(uim1),
+ MSM_PIN_FUNCTION(uim2),
+ MSM_PIN_FUNCTION(uim3),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(wcss_bt),
+ MSM_PIN_FUNCTION(wcss_fm),
+ MSM_PIN_FUNCTION(wcss_wlan),
+ MSM_PIN_FUNCTION(webcam1_rst)
};
static const struct msm_pingroup msm8916_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8953.c b/drivers/pinctrl/qcom/pinctrl-msm8953.c
index e0c939ff3d54..998351bdfee1 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8953.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8953.c
@@ -4,22 +4,14 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -56,9 +48,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -1431,208 +1423,208 @@ static const char * const wsa_irq_groups[] = {
"gpio97",
};
-static const struct msm_function msm8953_functions[] = {
- FUNCTION(accel_int),
- FUNCTION(adsp_ext),
- FUNCTION(alsp_int),
- FUNCTION(atest_bbrx0),
- FUNCTION(atest_bbrx1),
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(atest_gpsadc_dtest0_native),
- FUNCTION(atest_gpsadc_dtest1_native),
- FUNCTION(atest_tsens),
- FUNCTION(atest_wlan0),
- FUNCTION(atest_wlan1),
- FUNCTION(bimc_dte0),
- FUNCTION(bimc_dte1),
- FUNCTION(blsp1_spi),
- FUNCTION(blsp3_spi),
- FUNCTION(blsp6_spi),
- FUNCTION(blsp7_spi),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_i2c5),
- FUNCTION(blsp_i2c6),
- FUNCTION(blsp_i2c7),
- FUNCTION(blsp_i2c8),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_spi5),
- FUNCTION(blsp_spi6),
- FUNCTION(blsp_spi7),
- FUNCTION(blsp_spi8),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_uart4),
- FUNCTION(blsp_uart5),
- FUNCTION(blsp_uart6),
- FUNCTION(cam0_ldo),
- FUNCTION(cam1_ldo),
- FUNCTION(cam1_rst),
- FUNCTION(cam1_standby),
- FUNCTION(cam2_rst),
- FUNCTION(cam2_standby),
- FUNCTION(cam3_rst),
- FUNCTION(cam3_standby),
- FUNCTION(cam_irq),
- FUNCTION(cam_mclk),
- FUNCTION(cap_int),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cdc_pdm0),
- FUNCTION(codec_int1),
- FUNCTION(codec_int2),
- FUNCTION(codec_reset),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dac_calib0),
- FUNCTION(dac_calib1),
- FUNCTION(dac_calib10),
- FUNCTION(dac_calib11),
- FUNCTION(dac_calib12),
- FUNCTION(dac_calib13),
- FUNCTION(dac_calib14),
- FUNCTION(dac_calib15),
- FUNCTION(dac_calib16),
- FUNCTION(dac_calib17),
- FUNCTION(dac_calib18),
- FUNCTION(dac_calib19),
- FUNCTION(dac_calib2),
- FUNCTION(dac_calib20),
- FUNCTION(dac_calib21),
- FUNCTION(dac_calib22),
- FUNCTION(dac_calib23),
- FUNCTION(dac_calib24),
- FUNCTION(dac_calib25),
- FUNCTION(dac_calib3),
- FUNCTION(dac_calib4),
- FUNCTION(dac_calib5),
- FUNCTION(dac_calib6),
- FUNCTION(dac_calib7),
- FUNCTION(dac_calib8),
- FUNCTION(dac_calib9),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(dmic0_clk),
- FUNCTION(dmic0_data),
- FUNCTION(ebi_cdc),
- FUNCTION(ebi_ch0),
- FUNCTION(ext_lpass),
- FUNCTION(flash_strobe),
- FUNCTION(fp_int),
- FUNCTION(gcc_gp1_clk_a),
- FUNCTION(gcc_gp1_clk_b),
- FUNCTION(gcc_gp2_clk_a),
- FUNCTION(gcc_gp2_clk_b),
- FUNCTION(gcc_gp3_clk_a),
- FUNCTION(gcc_gp3_clk_b),
- FUNCTION(gcc_plltest),
- FUNCTION(gcc_tlmm),
- FUNCTION(gpio),
- FUNCTION(gsm0_tx),
- FUNCTION(gsm1_tx),
- FUNCTION(gyro_int),
- FUNCTION(hall_int),
- FUNCTION(hdmi_int),
- FUNCTION(key_focus),
- FUNCTION(key_home),
- FUNCTION(key_snapshot),
- FUNCTION(key_volp),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(lpass_slimbus),
- FUNCTION(lpass_slimbus0),
- FUNCTION(lpass_slimbus1),
- FUNCTION(m_voc),
- FUNCTION(mag_int),
- FUNCTION(mdp_vsync),
- FUNCTION(mipi_dsi0),
- FUNCTION(modem_tsync),
- FUNCTION(mss_lte),
- FUNCTION(nav_pps),
- FUNCTION(nav_pps_in_a),
- FUNCTION(nav_pps_in_b),
- FUNCTION(nav_tsync),
- FUNCTION(nfc_disable),
- FUNCTION(nfc_dwl),
- FUNCTION(nfc_irq),
- FUNCTION(ois_sync),
- FUNCTION(pa_indicator),
- FUNCTION(pbs0),
- FUNCTION(pbs1),
- FUNCTION(pbs2),
- FUNCTION(pressure_int),
- FUNCTION(pri_mi2s),
- FUNCTION(pri_mi2s_mclk_a),
- FUNCTION(pri_mi2s_mclk_b),
- FUNCTION(pri_mi2s_ws),
- FUNCTION(prng_rosc),
- FUNCTION(pwr_crypto_enabled_a),
- FUNCTION(pwr_crypto_enabled_b),
- FUNCTION(pwr_down),
- FUNCTION(pwr_modem_enabled_a),
- FUNCTION(pwr_modem_enabled_b),
- FUNCTION(pwr_nav_enabled_a),
- FUNCTION(pwr_nav_enabled_b),
- FUNCTION(qdss_cti_trig_in_a0),
- FUNCTION(qdss_cti_trig_in_a1),
- FUNCTION(qdss_cti_trig_in_b0),
- FUNCTION(qdss_cti_trig_in_b1),
- FUNCTION(qdss_cti_trig_out_a0),
- FUNCTION(qdss_cti_trig_out_a1),
- FUNCTION(qdss_cti_trig_out_b0),
- FUNCTION(qdss_cti_trig_out_b1),
- FUNCTION(qdss_traceclk_a),
- FUNCTION(qdss_traceclk_b),
- FUNCTION(qdss_tracectl_a),
- FUNCTION(qdss_tracectl_b),
- FUNCTION(qdss_tracedata_a),
- FUNCTION(qdss_tracedata_b),
- FUNCTION(sd_write),
- FUNCTION(sdcard_det),
- FUNCTION(sec_mi2s),
- FUNCTION(sec_mi2s_mclk_a),
- FUNCTION(sec_mi2s_mclk_b),
- FUNCTION(smb_int),
- FUNCTION(ss_switch),
- FUNCTION(ssbi_wtr1),
- FUNCTION(ts_resout),
- FUNCTION(ts_sample),
- FUNCTION(ts_xvdd),
- FUNCTION(tsens_max),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(uim_batt),
- FUNCTION(us_emitter),
- FUNCTION(us_euro),
- FUNCTION(wcss_bt),
- FUNCTION(wcss_fm),
- FUNCTION(wcss_wlan),
- FUNCTION(wcss_wlan0),
- FUNCTION(wcss_wlan1),
- FUNCTION(wcss_wlan2),
- FUNCTION(wsa_en),
- FUNCTION(wsa_io),
- FUNCTION(wsa_irq),
+static const struct pinfunction msm8953_functions[] = {
+ MSM_PIN_FUNCTION(accel_int),
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(alsp_int),
+ MSM_PIN_FUNCTION(atest_bbrx0),
+ MSM_PIN_FUNCTION(atest_bbrx1),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_gpsadc_dtest0_native),
+ MSM_PIN_FUNCTION(atest_gpsadc_dtest1_native),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_wlan0),
+ MSM_PIN_FUNCTION(atest_wlan1),
+ MSM_PIN_FUNCTION(bimc_dte0),
+ MSM_PIN_FUNCTION(bimc_dte1),
+ MSM_PIN_FUNCTION(blsp1_spi),
+ MSM_PIN_FUNCTION(blsp3_spi),
+ MSM_PIN_FUNCTION(blsp6_spi),
+ MSM_PIN_FUNCTION(blsp7_spi),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_i2c5),
+ MSM_PIN_FUNCTION(blsp_i2c6),
+ MSM_PIN_FUNCTION(blsp_i2c7),
+ MSM_PIN_FUNCTION(blsp_i2c8),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(blsp_spi5),
+ MSM_PIN_FUNCTION(blsp_spi6),
+ MSM_PIN_FUNCTION(blsp_spi7),
+ MSM_PIN_FUNCTION(blsp_spi8),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(blsp_uart4),
+ MSM_PIN_FUNCTION(blsp_uart5),
+ MSM_PIN_FUNCTION(blsp_uart6),
+ MSM_PIN_FUNCTION(cam0_ldo),
+ MSM_PIN_FUNCTION(cam1_ldo),
+ MSM_PIN_FUNCTION(cam1_rst),
+ MSM_PIN_FUNCTION(cam1_standby),
+ MSM_PIN_FUNCTION(cam2_rst),
+ MSM_PIN_FUNCTION(cam2_standby),
+ MSM_PIN_FUNCTION(cam3_rst),
+ MSM_PIN_FUNCTION(cam3_standby),
+ MSM_PIN_FUNCTION(cam_irq),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cap_int),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cdc_pdm0),
+ MSM_PIN_FUNCTION(codec_int1),
+ MSM_PIN_FUNCTION(codec_int2),
+ MSM_PIN_FUNCTION(codec_reset),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dac_calib0),
+ MSM_PIN_FUNCTION(dac_calib1),
+ MSM_PIN_FUNCTION(dac_calib10),
+ MSM_PIN_FUNCTION(dac_calib11),
+ MSM_PIN_FUNCTION(dac_calib12),
+ MSM_PIN_FUNCTION(dac_calib13),
+ MSM_PIN_FUNCTION(dac_calib14),
+ MSM_PIN_FUNCTION(dac_calib15),
+ MSM_PIN_FUNCTION(dac_calib16),
+ MSM_PIN_FUNCTION(dac_calib17),
+ MSM_PIN_FUNCTION(dac_calib18),
+ MSM_PIN_FUNCTION(dac_calib19),
+ MSM_PIN_FUNCTION(dac_calib2),
+ MSM_PIN_FUNCTION(dac_calib20),
+ MSM_PIN_FUNCTION(dac_calib21),
+ MSM_PIN_FUNCTION(dac_calib22),
+ MSM_PIN_FUNCTION(dac_calib23),
+ MSM_PIN_FUNCTION(dac_calib24),
+ MSM_PIN_FUNCTION(dac_calib25),
+ MSM_PIN_FUNCTION(dac_calib3),
+ MSM_PIN_FUNCTION(dac_calib4),
+ MSM_PIN_FUNCTION(dac_calib5),
+ MSM_PIN_FUNCTION(dac_calib6),
+ MSM_PIN_FUNCTION(dac_calib7),
+ MSM_PIN_FUNCTION(dac_calib8),
+ MSM_PIN_FUNCTION(dac_calib9),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(dmic0_clk),
+ MSM_PIN_FUNCTION(dmic0_data),
+ MSM_PIN_FUNCTION(ebi_cdc),
+ MSM_PIN_FUNCTION(ebi_ch0),
+ MSM_PIN_FUNCTION(ext_lpass),
+ MSM_PIN_FUNCTION(flash_strobe),
+ MSM_PIN_FUNCTION(fp_int),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_b),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gcc_tlmm),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gsm0_tx),
+ MSM_PIN_FUNCTION(gsm1_tx),
+ MSM_PIN_FUNCTION(gyro_int),
+ MSM_PIN_FUNCTION(hall_int),
+ MSM_PIN_FUNCTION(hdmi_int),
+ MSM_PIN_FUNCTION(key_focus),
+ MSM_PIN_FUNCTION(key_home),
+ MSM_PIN_FUNCTION(key_snapshot),
+ MSM_PIN_FUNCTION(key_volp),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(lpass_slimbus),
+ MSM_PIN_FUNCTION(lpass_slimbus0),
+ MSM_PIN_FUNCTION(lpass_slimbus1),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mag_int),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mipi_dsi0),
+ MSM_PIN_FUNCTION(modem_tsync),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(nav_pps_in_a),
+ MSM_PIN_FUNCTION(nav_pps_in_b),
+ MSM_PIN_FUNCTION(nav_tsync),
+ MSM_PIN_FUNCTION(nfc_disable),
+ MSM_PIN_FUNCTION(nfc_dwl),
+ MSM_PIN_FUNCTION(nfc_irq),
+ MSM_PIN_FUNCTION(ois_sync),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pbs0),
+ MSM_PIN_FUNCTION(pbs1),
+ MSM_PIN_FUNCTION(pbs2),
+ MSM_PIN_FUNCTION(pressure_int),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(pri_mi2s_mclk_a),
+ MSM_PIN_FUNCTION(pri_mi2s_mclk_b),
+ MSM_PIN_FUNCTION(pri_mi2s_ws),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(pwr_crypto_enabled_a),
+ MSM_PIN_FUNCTION(pwr_crypto_enabled_b),
+ MSM_PIN_FUNCTION(pwr_down),
+ MSM_PIN_FUNCTION(pwr_modem_enabled_a),
+ MSM_PIN_FUNCTION(pwr_modem_enabled_b),
+ MSM_PIN_FUNCTION(pwr_nav_enabled_a),
+ MSM_PIN_FUNCTION(pwr_nav_enabled_b),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b1),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_traceclk_b),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_b),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sdcard_det),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(sec_mi2s_mclk_a),
+ MSM_PIN_FUNCTION(sec_mi2s_mclk_b),
+ MSM_PIN_FUNCTION(smb_int),
+ MSM_PIN_FUNCTION(ss_switch),
+ MSM_PIN_FUNCTION(ssbi_wtr1),
+ MSM_PIN_FUNCTION(ts_resout),
+ MSM_PIN_FUNCTION(ts_sample),
+ MSM_PIN_FUNCTION(ts_xvdd),
+ MSM_PIN_FUNCTION(tsens_max),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(us_emitter),
+ MSM_PIN_FUNCTION(us_euro),
+ MSM_PIN_FUNCTION(wcss_bt),
+ MSM_PIN_FUNCTION(wcss_fm),
+ MSM_PIN_FUNCTION(wcss_wlan),
+ MSM_PIN_FUNCTION(wcss_wlan0),
+ MSM_PIN_FUNCTION(wcss_wlan1),
+ MSM_PIN_FUNCTION(wcss_wlan2),
+ MSM_PIN_FUNCTION(wsa_en),
+ MSM_PIN_FUNCTION(wsa_io),
+ MSM_PIN_FUNCTION(wsa_irq),
};
static const struct msm_pingroup msm8953_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8960.c b/drivers/pinctrl/qcom/pinctrl-msm8960.c
index e3928f5f8d5b..ebe230b3b437 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8960.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8960.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include "pinctrl-msm.h"
@@ -334,31 +333,24 @@ static const unsigned int sdc3_clk_pins[] = { 155 };
static const unsigned int sdc3_cmd_pins[] = { 156 };
static const unsigned int sdc3_data_pins[] = { 157 };
-#define FUNCTION(fname) \
- [MSM_MUX_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
- MSM_MUX_gpio, \
- MSM_MUX_##f1, \
- MSM_MUX_##f2, \
- MSM_MUX_##f3, \
- MSM_MUX_##f4, \
- MSM_MUX_##f5, \
- MSM_MUX_##f6, \
- MSM_MUX_##f7, \
- MSM_MUX_##f8, \
- MSM_MUX_##f9, \
- MSM_MUX_##f10, \
- MSM_MUX_##f11 \
+ msm_mux_gpio, \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9, \
+ msm_mux_##f10, \
+ msm_mux_##f11 \
}, \
.nfuncs = 12, \
.ctl_reg = 0x1000 + 0x10 * id, \
@@ -385,9 +377,9 @@ static const unsigned int sdc3_data_pins[] = { 157 };
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -410,111 +402,111 @@ static const unsigned int sdc3_data_pins[] = { 157 };
}
enum msm8960_functions {
- MSM_MUX_audio_pcm,
- MSM_MUX_bt,
- MSM_MUX_cam_mclk0,
- MSM_MUX_cam_mclk1,
- MSM_MUX_cam_mclk2,
- MSM_MUX_codec_mic_i2s,
- MSM_MUX_codec_spkr_i2s,
- MSM_MUX_ext_gps,
- MSM_MUX_fm,
- MSM_MUX_gps_blanking,
- MSM_MUX_gps_pps_in,
- MSM_MUX_gps_pps_out,
- MSM_MUX_gp_clk_0a,
- MSM_MUX_gp_clk_0b,
- MSM_MUX_gp_clk_1a,
- MSM_MUX_gp_clk_1b,
- MSM_MUX_gp_clk_2a,
- MSM_MUX_gp_clk_2b,
- MSM_MUX_gp_mn,
- MSM_MUX_gp_pdm_0a,
- MSM_MUX_gp_pdm_0b,
- MSM_MUX_gp_pdm_1a,
- MSM_MUX_gp_pdm_1b,
- MSM_MUX_gp_pdm_2a,
- MSM_MUX_gp_pdm_2b,
- MSM_MUX_gpio,
- MSM_MUX_gsbi1,
- MSM_MUX_gsbi1_spi_cs1_n,
- MSM_MUX_gsbi1_spi_cs2a_n,
- MSM_MUX_gsbi1_spi_cs2b_n,
- MSM_MUX_gsbi1_spi_cs3_n,
- MSM_MUX_gsbi2,
- MSM_MUX_gsbi2_spi_cs1_n,
- MSM_MUX_gsbi2_spi_cs2_n,
- MSM_MUX_gsbi2_spi_cs3_n,
- MSM_MUX_gsbi3,
- MSM_MUX_gsbi4,
- MSM_MUX_gsbi4_3d_cam_i2c_l,
- MSM_MUX_gsbi4_3d_cam_i2c_r,
- MSM_MUX_gsbi5,
- MSM_MUX_gsbi5_3d_cam_i2c_l,
- MSM_MUX_gsbi5_3d_cam_i2c_r,
- MSM_MUX_gsbi6,
- MSM_MUX_gsbi7,
- MSM_MUX_gsbi8,
- MSM_MUX_gsbi9,
- MSM_MUX_gsbi10,
- MSM_MUX_gsbi11,
- MSM_MUX_gsbi11_spi_cs1a_n,
- MSM_MUX_gsbi11_spi_cs1b_n,
- MSM_MUX_gsbi11_spi_cs2a_n,
- MSM_MUX_gsbi11_spi_cs2b_n,
- MSM_MUX_gsbi11_spi_cs3_n,
- MSM_MUX_gsbi12,
- MSM_MUX_hdmi_cec,
- MSM_MUX_hdmi_ddc_clock,
- MSM_MUX_hdmi_ddc_data,
- MSM_MUX_hdmi_hot_plug_detect,
- MSM_MUX_hsic,
- MSM_MUX_mdp_vsync,
- MSM_MUX_mi2s,
- MSM_MUX_mic_i2s,
- MSM_MUX_pmb_clk,
- MSM_MUX_pmb_ext_ctrl,
- MSM_MUX_ps_hold,
- MSM_MUX_rpm_wdog,
- MSM_MUX_sdc2,
- MSM_MUX_sdc4,
- MSM_MUX_sdc5,
- MSM_MUX_slimbus1,
- MSM_MUX_slimbus2,
- MSM_MUX_spkr_i2s,
- MSM_MUX_ssbi1,
- MSM_MUX_ssbi2,
- MSM_MUX_ssbi_ext_gps,
- MSM_MUX_ssbi_pmic2,
- MSM_MUX_ssbi_qpa1,
- MSM_MUX_ssbi_ts,
- MSM_MUX_tsif1,
- MSM_MUX_tsif2,
- MSM_MUX_ts_eoc,
- MSM_MUX_usb_fs1,
- MSM_MUX_usb_fs1_oe,
- MSM_MUX_usb_fs1_oe_n,
- MSM_MUX_usb_fs2,
- MSM_MUX_usb_fs2_oe,
- MSM_MUX_usb_fs2_oe_n,
- MSM_MUX_vfe_camif_timer1_a,
- MSM_MUX_vfe_camif_timer1_b,
- MSM_MUX_vfe_camif_timer2,
- MSM_MUX_vfe_camif_timer3_a,
- MSM_MUX_vfe_camif_timer3_b,
- MSM_MUX_vfe_camif_timer4_a,
- MSM_MUX_vfe_camif_timer4_b,
- MSM_MUX_vfe_camif_timer4_c,
- MSM_MUX_vfe_camif_timer5_a,
- MSM_MUX_vfe_camif_timer5_b,
- MSM_MUX_vfe_camif_timer6_a,
- MSM_MUX_vfe_camif_timer6_b,
- MSM_MUX_vfe_camif_timer6_c,
- MSM_MUX_vfe_camif_timer7_a,
- MSM_MUX_vfe_camif_timer7_b,
- MSM_MUX_vfe_camif_timer7_c,
- MSM_MUX_wlan,
- MSM_MUX_NA,
+ msm_mux_audio_pcm,
+ msm_mux_bt,
+ msm_mux_cam_mclk0,
+ msm_mux_cam_mclk1,
+ msm_mux_cam_mclk2,
+ msm_mux_codec_mic_i2s,
+ msm_mux_codec_spkr_i2s,
+ msm_mux_ext_gps,
+ msm_mux_fm,
+ msm_mux_gps_blanking,
+ msm_mux_gps_pps_in,
+ msm_mux_gps_pps_out,
+ msm_mux_gp_clk_0a,
+ msm_mux_gp_clk_0b,
+ msm_mux_gp_clk_1a,
+ msm_mux_gp_clk_1b,
+ msm_mux_gp_clk_2a,
+ msm_mux_gp_clk_2b,
+ msm_mux_gp_mn,
+ msm_mux_gp_pdm_0a,
+ msm_mux_gp_pdm_0b,
+ msm_mux_gp_pdm_1a,
+ msm_mux_gp_pdm_1b,
+ msm_mux_gp_pdm_2a,
+ msm_mux_gp_pdm_2b,
+ msm_mux_gpio,
+ msm_mux_gsbi1,
+ msm_mux_gsbi1_spi_cs1_n,
+ msm_mux_gsbi1_spi_cs2a_n,
+ msm_mux_gsbi1_spi_cs2b_n,
+ msm_mux_gsbi1_spi_cs3_n,
+ msm_mux_gsbi2,
+ msm_mux_gsbi2_spi_cs1_n,
+ msm_mux_gsbi2_spi_cs2_n,
+ msm_mux_gsbi2_spi_cs3_n,
+ msm_mux_gsbi3,
+ msm_mux_gsbi4,
+ msm_mux_gsbi4_3d_cam_i2c_l,
+ msm_mux_gsbi4_3d_cam_i2c_r,
+ msm_mux_gsbi5,
+ msm_mux_gsbi5_3d_cam_i2c_l,
+ msm_mux_gsbi5_3d_cam_i2c_r,
+ msm_mux_gsbi6,
+ msm_mux_gsbi7,
+ msm_mux_gsbi8,
+ msm_mux_gsbi9,
+ msm_mux_gsbi10,
+ msm_mux_gsbi11,
+ msm_mux_gsbi11_spi_cs1a_n,
+ msm_mux_gsbi11_spi_cs1b_n,
+ msm_mux_gsbi11_spi_cs2a_n,
+ msm_mux_gsbi11_spi_cs2b_n,
+ msm_mux_gsbi11_spi_cs3_n,
+ msm_mux_gsbi12,
+ msm_mux_hdmi_cec,
+ msm_mux_hdmi_ddc_clock,
+ msm_mux_hdmi_ddc_data,
+ msm_mux_hdmi_hot_plug_detect,
+ msm_mux_hsic,
+ msm_mux_mdp_vsync,
+ msm_mux_mi2s,
+ msm_mux_mic_i2s,
+ msm_mux_pmb_clk,
+ msm_mux_pmb_ext_ctrl,
+ msm_mux_ps_hold,
+ msm_mux_rpm_wdog,
+ msm_mux_sdc2,
+ msm_mux_sdc4,
+ msm_mux_sdc5,
+ msm_mux_slimbus1,
+ msm_mux_slimbus2,
+ msm_mux_spkr_i2s,
+ msm_mux_ssbi1,
+ msm_mux_ssbi2,
+ msm_mux_ssbi_ext_gps,
+ msm_mux_ssbi_pmic2,
+ msm_mux_ssbi_qpa1,
+ msm_mux_ssbi_ts,
+ msm_mux_tsif1,
+ msm_mux_tsif2,
+ msm_mux_ts_eoc,
+ msm_mux_usb_fs1,
+ msm_mux_usb_fs1_oe,
+ msm_mux_usb_fs1_oe_n,
+ msm_mux_usb_fs2,
+ msm_mux_usb_fs2_oe,
+ msm_mux_usb_fs2_oe_n,
+ msm_mux_vfe_camif_timer1_a,
+ msm_mux_vfe_camif_timer1_b,
+ msm_mux_vfe_camif_timer2,
+ msm_mux_vfe_camif_timer3_a,
+ msm_mux_vfe_camif_timer3_b,
+ msm_mux_vfe_camif_timer4_a,
+ msm_mux_vfe_camif_timer4_b,
+ msm_mux_vfe_camif_timer4_c,
+ msm_mux_vfe_camif_timer5_a,
+ msm_mux_vfe_camif_timer5_b,
+ msm_mux_vfe_camif_timer6_a,
+ msm_mux_vfe_camif_timer6_b,
+ msm_mux_vfe_camif_timer6_c,
+ msm_mux_vfe_camif_timer7_a,
+ msm_mux_vfe_camif_timer7_b,
+ msm_mux_vfe_camif_timer7_c,
+ msm_mux_wlan,
+ msm_mux_NA,
};
static const char * const audio_pcm_groups[] = {
@@ -956,111 +948,111 @@ static const char * const wlan_groups[] = {
"gpio84", "gpio85", "gpio86", "gpio87", "gpio88"
};
-static const struct msm_function msm8960_functions[] = {
- FUNCTION(audio_pcm),
- FUNCTION(bt),
- FUNCTION(cam_mclk0),
- FUNCTION(cam_mclk1),
- FUNCTION(cam_mclk2),
- FUNCTION(codec_mic_i2s),
- FUNCTION(codec_spkr_i2s),
- FUNCTION(ext_gps),
- FUNCTION(fm),
- FUNCTION(gps_blanking),
- FUNCTION(gps_pps_in),
- FUNCTION(gps_pps_out),
- FUNCTION(gp_clk_0a),
- FUNCTION(gp_clk_0b),
- FUNCTION(gp_clk_1a),
- FUNCTION(gp_clk_1b),
- FUNCTION(gp_clk_2a),
- FUNCTION(gp_clk_2b),
- FUNCTION(gp_mn),
- FUNCTION(gp_pdm_0a),
- FUNCTION(gp_pdm_0b),
- FUNCTION(gp_pdm_1a),
- FUNCTION(gp_pdm_1b),
- FUNCTION(gp_pdm_2a),
- FUNCTION(gp_pdm_2b),
- FUNCTION(gpio),
- FUNCTION(gsbi1),
- FUNCTION(gsbi1_spi_cs1_n),
- FUNCTION(gsbi1_spi_cs2a_n),
- FUNCTION(gsbi1_spi_cs2b_n),
- FUNCTION(gsbi1_spi_cs3_n),
- FUNCTION(gsbi2),
- FUNCTION(gsbi2_spi_cs1_n),
- FUNCTION(gsbi2_spi_cs2_n),
- FUNCTION(gsbi2_spi_cs3_n),
- FUNCTION(gsbi3),
- FUNCTION(gsbi4),
- FUNCTION(gsbi4_3d_cam_i2c_l),
- FUNCTION(gsbi4_3d_cam_i2c_r),
- FUNCTION(gsbi5),
- FUNCTION(gsbi5_3d_cam_i2c_l),
- FUNCTION(gsbi5_3d_cam_i2c_r),
- FUNCTION(gsbi6),
- FUNCTION(gsbi7),
- FUNCTION(gsbi8),
- FUNCTION(gsbi9),
- FUNCTION(gsbi10),
- FUNCTION(gsbi11),
- FUNCTION(gsbi11_spi_cs1a_n),
- FUNCTION(gsbi11_spi_cs1b_n),
- FUNCTION(gsbi11_spi_cs2a_n),
- FUNCTION(gsbi11_spi_cs2b_n),
- FUNCTION(gsbi11_spi_cs3_n),
- FUNCTION(gsbi12),
- FUNCTION(hdmi_cec),
- FUNCTION(hdmi_ddc_clock),
- FUNCTION(hdmi_ddc_data),
- FUNCTION(hdmi_hot_plug_detect),
- FUNCTION(hsic),
- FUNCTION(mdp_vsync),
- FUNCTION(mi2s),
- FUNCTION(mic_i2s),
- FUNCTION(pmb_clk),
- FUNCTION(pmb_ext_ctrl),
- FUNCTION(ps_hold),
- FUNCTION(rpm_wdog),
- FUNCTION(sdc2),
- FUNCTION(sdc4),
- FUNCTION(sdc5),
- FUNCTION(slimbus1),
- FUNCTION(slimbus2),
- FUNCTION(spkr_i2s),
- FUNCTION(ssbi1),
- FUNCTION(ssbi2),
- FUNCTION(ssbi_ext_gps),
- FUNCTION(ssbi_pmic2),
- FUNCTION(ssbi_qpa1),
- FUNCTION(ssbi_ts),
- FUNCTION(tsif1),
- FUNCTION(tsif2),
- FUNCTION(ts_eoc),
- FUNCTION(usb_fs1),
- FUNCTION(usb_fs1_oe),
- FUNCTION(usb_fs1_oe_n),
- FUNCTION(usb_fs2),
- FUNCTION(usb_fs2_oe),
- FUNCTION(usb_fs2_oe_n),
- FUNCTION(vfe_camif_timer1_a),
- FUNCTION(vfe_camif_timer1_b),
- FUNCTION(vfe_camif_timer2),
- FUNCTION(vfe_camif_timer3_a),
- FUNCTION(vfe_camif_timer3_b),
- FUNCTION(vfe_camif_timer4_a),
- FUNCTION(vfe_camif_timer4_b),
- FUNCTION(vfe_camif_timer4_c),
- FUNCTION(vfe_camif_timer5_a),
- FUNCTION(vfe_camif_timer5_b),
- FUNCTION(vfe_camif_timer6_a),
- FUNCTION(vfe_camif_timer6_b),
- FUNCTION(vfe_camif_timer6_c),
- FUNCTION(vfe_camif_timer7_a),
- FUNCTION(vfe_camif_timer7_b),
- FUNCTION(vfe_camif_timer7_c),
- FUNCTION(wlan),
+static const struct pinfunction msm8960_functions[] = {
+ MSM_PIN_FUNCTION(audio_pcm),
+ MSM_PIN_FUNCTION(bt),
+ MSM_PIN_FUNCTION(cam_mclk0),
+ MSM_PIN_FUNCTION(cam_mclk1),
+ MSM_PIN_FUNCTION(cam_mclk2),
+ MSM_PIN_FUNCTION(codec_mic_i2s),
+ MSM_PIN_FUNCTION(codec_spkr_i2s),
+ MSM_PIN_FUNCTION(ext_gps),
+ MSM_PIN_FUNCTION(fm),
+ MSM_PIN_FUNCTION(gps_blanking),
+ MSM_PIN_FUNCTION(gps_pps_in),
+ MSM_PIN_FUNCTION(gps_pps_out),
+ MSM_PIN_FUNCTION(gp_clk_0a),
+ MSM_PIN_FUNCTION(gp_clk_0b),
+ MSM_PIN_FUNCTION(gp_clk_1a),
+ MSM_PIN_FUNCTION(gp_clk_1b),
+ MSM_PIN_FUNCTION(gp_clk_2a),
+ MSM_PIN_FUNCTION(gp_clk_2b),
+ MSM_PIN_FUNCTION(gp_mn),
+ MSM_PIN_FUNCTION(gp_pdm_0a),
+ MSM_PIN_FUNCTION(gp_pdm_0b),
+ MSM_PIN_FUNCTION(gp_pdm_1a),
+ MSM_PIN_FUNCTION(gp_pdm_1b),
+ MSM_PIN_FUNCTION(gp_pdm_2a),
+ MSM_PIN_FUNCTION(gp_pdm_2b),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gsbi1),
+ MSM_PIN_FUNCTION(gsbi1_spi_cs1_n),
+ MSM_PIN_FUNCTION(gsbi1_spi_cs2a_n),
+ MSM_PIN_FUNCTION(gsbi1_spi_cs2b_n),
+ MSM_PIN_FUNCTION(gsbi1_spi_cs3_n),
+ MSM_PIN_FUNCTION(gsbi2),
+ MSM_PIN_FUNCTION(gsbi2_spi_cs1_n),
+ MSM_PIN_FUNCTION(gsbi2_spi_cs2_n),
+ MSM_PIN_FUNCTION(gsbi2_spi_cs3_n),
+ MSM_PIN_FUNCTION(gsbi3),
+ MSM_PIN_FUNCTION(gsbi4),
+ MSM_PIN_FUNCTION(gsbi4_3d_cam_i2c_l),
+ MSM_PIN_FUNCTION(gsbi4_3d_cam_i2c_r),
+ MSM_PIN_FUNCTION(gsbi5),
+ MSM_PIN_FUNCTION(gsbi5_3d_cam_i2c_l),
+ MSM_PIN_FUNCTION(gsbi5_3d_cam_i2c_r),
+ MSM_PIN_FUNCTION(gsbi6),
+ MSM_PIN_FUNCTION(gsbi7),
+ MSM_PIN_FUNCTION(gsbi8),
+ MSM_PIN_FUNCTION(gsbi9),
+ MSM_PIN_FUNCTION(gsbi10),
+ MSM_PIN_FUNCTION(gsbi11),
+ MSM_PIN_FUNCTION(gsbi11_spi_cs1a_n),
+ MSM_PIN_FUNCTION(gsbi11_spi_cs1b_n),
+ MSM_PIN_FUNCTION(gsbi11_spi_cs2a_n),
+ MSM_PIN_FUNCTION(gsbi11_spi_cs2b_n),
+ MSM_PIN_FUNCTION(gsbi11_spi_cs3_n),
+ MSM_PIN_FUNCTION(gsbi12),
+ MSM_PIN_FUNCTION(hdmi_cec),
+ MSM_PIN_FUNCTION(hdmi_ddc_clock),
+ MSM_PIN_FUNCTION(hdmi_ddc_data),
+ MSM_PIN_FUNCTION(hdmi_hot_plug_detect),
+ MSM_PIN_FUNCTION(hsic),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mi2s),
+ MSM_PIN_FUNCTION(mic_i2s),
+ MSM_PIN_FUNCTION(pmb_clk),
+ MSM_PIN_FUNCTION(pmb_ext_ctrl),
+ MSM_PIN_FUNCTION(ps_hold),
+ MSM_PIN_FUNCTION(rpm_wdog),
+ MSM_PIN_FUNCTION(sdc2),
+ MSM_PIN_FUNCTION(sdc4),
+ MSM_PIN_FUNCTION(sdc5),
+ MSM_PIN_FUNCTION(slimbus1),
+ MSM_PIN_FUNCTION(slimbus2),
+ MSM_PIN_FUNCTION(spkr_i2s),
+ MSM_PIN_FUNCTION(ssbi1),
+ MSM_PIN_FUNCTION(ssbi2),
+ MSM_PIN_FUNCTION(ssbi_ext_gps),
+ MSM_PIN_FUNCTION(ssbi_pmic2),
+ MSM_PIN_FUNCTION(ssbi_qpa1),
+ MSM_PIN_FUNCTION(ssbi_ts),
+ MSM_PIN_FUNCTION(tsif1),
+ MSM_PIN_FUNCTION(tsif2),
+ MSM_PIN_FUNCTION(ts_eoc),
+ MSM_PIN_FUNCTION(usb_fs1),
+ MSM_PIN_FUNCTION(usb_fs1_oe),
+ MSM_PIN_FUNCTION(usb_fs1_oe_n),
+ MSM_PIN_FUNCTION(usb_fs2),
+ MSM_PIN_FUNCTION(usb_fs2_oe),
+ MSM_PIN_FUNCTION(usb_fs2_oe_n),
+ MSM_PIN_FUNCTION(vfe_camif_timer1_a),
+ MSM_PIN_FUNCTION(vfe_camif_timer1_b),
+ MSM_PIN_FUNCTION(vfe_camif_timer2),
+ MSM_PIN_FUNCTION(vfe_camif_timer3_a),
+ MSM_PIN_FUNCTION(vfe_camif_timer3_b),
+ MSM_PIN_FUNCTION(vfe_camif_timer4_a),
+ MSM_PIN_FUNCTION(vfe_camif_timer4_b),
+ MSM_PIN_FUNCTION(vfe_camif_timer4_c),
+ MSM_PIN_FUNCTION(vfe_camif_timer5_a),
+ MSM_PIN_FUNCTION(vfe_camif_timer5_b),
+ MSM_PIN_FUNCTION(vfe_camif_timer6_a),
+ MSM_PIN_FUNCTION(vfe_camif_timer6_b),
+ MSM_PIN_FUNCTION(vfe_camif_timer6_c),
+ MSM_PIN_FUNCTION(vfe_camif_timer7_a),
+ MSM_PIN_FUNCTION(vfe_camif_timer7_b),
+ MSM_PIN_FUNCTION(vfe_camif_timer7_c),
+ MSM_PIN_FUNCTION(wlan),
};
static const struct msm_pingroup msm8960_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8976.c b/drivers/pinctrl/qcom/pinctrl-msm8976.c
index e11d84584719..c30d80e4e98c 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8976.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8976.c
@@ -8,24 +8,16 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_BASE 0x0
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -62,9 +54,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -819,102 +811,102 @@ static const char * const ss_switch_groups[] = {
"gpio139",
};
-static const struct msm_function msm8976_functions[] = {
- FUNCTION(gpio),
- FUNCTION(blsp_spi1),
- FUNCTION(smb_int),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_i2c2),
- FUNCTION(gcc_gp1_clk_b),
- FUNCTION(blsp_spi3),
- FUNCTION(qdss_tracedata_b),
- FUNCTION(blsp_i2c3),
- FUNCTION(gcc_gp2_clk_b),
- FUNCTION(gcc_gp3_clk_b),
- FUNCTION(blsp_spi4),
- FUNCTION(cap_int),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_spi5),
- FUNCTION(blsp_uart5),
- FUNCTION(qdss_traceclk_a),
- FUNCTION(m_voc),
- FUNCTION(blsp_i2c5),
- FUNCTION(qdss_tracectl_a),
- FUNCTION(qdss_tracedata_a),
- FUNCTION(blsp_spi6),
- FUNCTION(blsp_uart6),
- FUNCTION(qdss_tracectl_b),
- FUNCTION(blsp_i2c6),
- FUNCTION(qdss_traceclk_b),
- FUNCTION(mdp_vsync),
- FUNCTION(pri_mi2s_mclk_a),
- FUNCTION(sec_mi2s_mclk_a),
- FUNCTION(cam_mclk),
- FUNCTION(cci0_i2c),
- FUNCTION(cci1_i2c),
- FUNCTION(blsp1_spi),
- FUNCTION(blsp3_spi),
- FUNCTION(gcc_gp1_clk_a),
- FUNCTION(gcc_gp2_clk_a),
- FUNCTION(gcc_gp3_clk_a),
- FUNCTION(uim_batt),
- FUNCTION(sd_write),
- FUNCTION(uim1_data),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_reset),
- FUNCTION(uim1_present),
- FUNCTION(uim2_data),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_reset),
- FUNCTION(uim2_present),
- FUNCTION(ts_xvdd),
- FUNCTION(mipi_dsi0),
- FUNCTION(us_euro),
- FUNCTION(ts_resout),
- FUNCTION(ts_sample),
- FUNCTION(sec_mi2s_mclk_b),
- FUNCTION(pri_mi2s),
- FUNCTION(codec_reset),
- FUNCTION(cdc_pdm0),
- FUNCTION(us_emitter),
- FUNCTION(pri_mi2s_mclk_b),
- FUNCTION(pri_mi2s_mclk_c),
- FUNCTION(lpass_slimbus),
- FUNCTION(lpass_slimbus0),
- FUNCTION(lpass_slimbus1),
- FUNCTION(codec_int1),
- FUNCTION(codec_int2),
- FUNCTION(wcss_bt),
- FUNCTION(sdc3),
- FUNCTION(wcss_wlan2),
- FUNCTION(wcss_wlan1),
- FUNCTION(wcss_wlan0),
- FUNCTION(wcss_wlan),
- FUNCTION(wcss_fm),
- FUNCTION(key_volp),
- FUNCTION(key_snapshot),
- FUNCTION(key_focus),
- FUNCTION(key_home),
- FUNCTION(pwr_down),
- FUNCTION(dmic0_clk),
- FUNCTION(hdmi_int),
- FUNCTION(dmic0_data),
- FUNCTION(wsa_vi),
- FUNCTION(wsa_en),
- FUNCTION(blsp_spi8),
- FUNCTION(wsa_irq),
- FUNCTION(blsp_i2c8),
- FUNCTION(pa_indicator),
- FUNCTION(modem_tsync),
- FUNCTION(ssbi_wtr1),
- FUNCTION(gsm1_tx),
- FUNCTION(gsm0_tx),
- FUNCTION(sdcard_det),
- FUNCTION(sec_mi2s),
- FUNCTION(ss_switch),
+static const struct pinfunction msm8976_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(smb_int),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_uart1),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_b),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_b),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(cap_int),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_spi5),
+ MSM_PIN_FUNCTION(blsp_uart5),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(blsp_i2c5),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(blsp_spi6),
+ MSM_PIN_FUNCTION(blsp_uart6),
+ MSM_PIN_FUNCTION(qdss_tracectl_b),
+ MSM_PIN_FUNCTION(blsp_i2c6),
+ MSM_PIN_FUNCTION(qdss_traceclk_b),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(pri_mi2s_mclk_a),
+ MSM_PIN_FUNCTION(sec_mi2s_mclk_a),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci0_i2c),
+ MSM_PIN_FUNCTION(cci1_i2c),
+ MSM_PIN_FUNCTION(blsp1_spi),
+ MSM_PIN_FUNCTION(blsp3_spi),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_a),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(ts_xvdd),
+ MSM_PIN_FUNCTION(mipi_dsi0),
+ MSM_PIN_FUNCTION(us_euro),
+ MSM_PIN_FUNCTION(ts_resout),
+ MSM_PIN_FUNCTION(ts_sample),
+ MSM_PIN_FUNCTION(sec_mi2s_mclk_b),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(codec_reset),
+ MSM_PIN_FUNCTION(cdc_pdm0),
+ MSM_PIN_FUNCTION(us_emitter),
+ MSM_PIN_FUNCTION(pri_mi2s_mclk_b),
+ MSM_PIN_FUNCTION(pri_mi2s_mclk_c),
+ MSM_PIN_FUNCTION(lpass_slimbus),
+ MSM_PIN_FUNCTION(lpass_slimbus0),
+ MSM_PIN_FUNCTION(lpass_slimbus1),
+ MSM_PIN_FUNCTION(codec_int1),
+ MSM_PIN_FUNCTION(codec_int2),
+ MSM_PIN_FUNCTION(wcss_bt),
+ MSM_PIN_FUNCTION(sdc3),
+ MSM_PIN_FUNCTION(wcss_wlan2),
+ MSM_PIN_FUNCTION(wcss_wlan1),
+ MSM_PIN_FUNCTION(wcss_wlan0),
+ MSM_PIN_FUNCTION(wcss_wlan),
+ MSM_PIN_FUNCTION(wcss_fm),
+ MSM_PIN_FUNCTION(key_volp),
+ MSM_PIN_FUNCTION(key_snapshot),
+ MSM_PIN_FUNCTION(key_focus),
+ MSM_PIN_FUNCTION(key_home),
+ MSM_PIN_FUNCTION(pwr_down),
+ MSM_PIN_FUNCTION(dmic0_clk),
+ MSM_PIN_FUNCTION(hdmi_int),
+ MSM_PIN_FUNCTION(dmic0_data),
+ MSM_PIN_FUNCTION(wsa_vi),
+ MSM_PIN_FUNCTION(wsa_en),
+ MSM_PIN_FUNCTION(blsp_spi8),
+ MSM_PIN_FUNCTION(wsa_irq),
+ MSM_PIN_FUNCTION(blsp_i2c8),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(modem_tsync),
+ MSM_PIN_FUNCTION(ssbi_wtr1),
+ MSM_PIN_FUNCTION(gsm1_tx),
+ MSM_PIN_FUNCTION(gsm0_tx),
+ MSM_PIN_FUNCTION(sdcard_det),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(ss_switch),
};
static const struct msm_pingroup msm8976_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8994.c b/drivers/pinctrl/qcom/pinctrl-msm8994.c
index 0ec886563f45..b1a6759ab4a5 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8994.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8994.c
@@ -6,35 +6,27 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [MSM_MUX_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
- MSM_MUX_gpio, \
- MSM_MUX_##f1, \
- MSM_MUX_##f2, \
- MSM_MUX_##f3, \
- MSM_MUX_##f4, \
- MSM_MUX_##f5, \
- MSM_MUX_##f6, \
- MSM_MUX_##f7, \
- MSM_MUX_##f8, \
- MSM_MUX_##f9, \
- MSM_MUX_##f10, \
- MSM_MUX_##f11 \
+ msm_mux_gpio, \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9, \
+ msm_mux_##f10, \
+ msm_mux_##f11 \
}, \
.nfuncs = 12, \
.ctl_reg = 0x1000 + 0x10 * id, \
@@ -60,9 +52,9 @@
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -403,136 +395,136 @@ static const unsigned int sdc3_cmd_pins[] = { 154 };
static const unsigned int sdc3_data_pins[] = { 155 };
enum msm8994_functions {
- MSM_MUX_audio_ref_clk,
- MSM_MUX_blsp_i2c1,
- MSM_MUX_blsp_i2c2,
- MSM_MUX_blsp_i2c3,
- MSM_MUX_blsp_i2c4,
- MSM_MUX_blsp_i2c5,
- MSM_MUX_blsp_i2c6,
- MSM_MUX_blsp_i2c7,
- MSM_MUX_blsp_i2c8,
- MSM_MUX_blsp_i2c9,
- MSM_MUX_blsp_i2c10,
- MSM_MUX_blsp_i2c11,
- MSM_MUX_blsp_i2c12,
- MSM_MUX_blsp_spi1,
- MSM_MUX_blsp_spi1_cs1,
- MSM_MUX_blsp_spi1_cs2,
- MSM_MUX_blsp_spi1_cs3,
- MSM_MUX_blsp_spi2,
- MSM_MUX_blsp_spi2_cs1,
- MSM_MUX_blsp_spi2_cs2,
- MSM_MUX_blsp_spi2_cs3,
- MSM_MUX_blsp_spi3,
- MSM_MUX_blsp_spi4,
- MSM_MUX_blsp_spi5,
- MSM_MUX_blsp_spi6,
- MSM_MUX_blsp_spi7,
- MSM_MUX_blsp_spi8,
- MSM_MUX_blsp_spi9,
- MSM_MUX_blsp_spi10,
- MSM_MUX_blsp_spi10_cs1,
- MSM_MUX_blsp_spi10_cs2,
- MSM_MUX_blsp_spi10_cs3,
- MSM_MUX_blsp_spi11,
- MSM_MUX_blsp_spi12,
- MSM_MUX_blsp_uart1,
- MSM_MUX_blsp_uart2,
- MSM_MUX_blsp_uart3,
- MSM_MUX_blsp_uart4,
- MSM_MUX_blsp_uart5,
- MSM_MUX_blsp_uart6,
- MSM_MUX_blsp_uart7,
- MSM_MUX_blsp_uart8,
- MSM_MUX_blsp_uart9,
- MSM_MUX_blsp_uart10,
- MSM_MUX_blsp_uart11,
- MSM_MUX_blsp_uart12,
- MSM_MUX_blsp_uim1,
- MSM_MUX_blsp_uim2,
- MSM_MUX_blsp_uim3,
- MSM_MUX_blsp_uim4,
- MSM_MUX_blsp_uim5,
- MSM_MUX_blsp_uim6,
- MSM_MUX_blsp_uim7,
- MSM_MUX_blsp_uim8,
- MSM_MUX_blsp_uim9,
- MSM_MUX_blsp_uim10,
- MSM_MUX_blsp_uim11,
- MSM_MUX_blsp_uim12,
- MSM_MUX_blsp11_i2c_scl_b,
- MSM_MUX_blsp11_i2c_sda_b,
- MSM_MUX_blsp11_uart_rx_b,
- MSM_MUX_blsp11_uart_tx_b,
- MSM_MUX_cam_mclk0,
- MSM_MUX_cam_mclk1,
- MSM_MUX_cam_mclk2,
- MSM_MUX_cam_mclk3,
- MSM_MUX_cci_async_in0,
- MSM_MUX_cci_async_in1,
- MSM_MUX_cci_async_in2,
- MSM_MUX_cci_i2c0,
- MSM_MUX_cci_i2c1,
- MSM_MUX_cci_timer0,
- MSM_MUX_cci_timer1,
- MSM_MUX_cci_timer2,
- MSM_MUX_cci_timer3,
- MSM_MUX_cci_timer4,
- MSM_MUX_gcc_gp1_clk_a,
- MSM_MUX_gcc_gp1_clk_b,
- MSM_MUX_gcc_gp2_clk_a,
- MSM_MUX_gcc_gp2_clk_b,
- MSM_MUX_gcc_gp3_clk_a,
- MSM_MUX_gcc_gp3_clk_b,
- MSM_MUX_gp_mn,
- MSM_MUX_gp_pdm0,
- MSM_MUX_gp_pdm1,
- MSM_MUX_gp_pdm2,
- MSM_MUX_gp0_clk,
- MSM_MUX_gp1_clk,
- MSM_MUX_gps_tx,
- MSM_MUX_gsm_tx,
- MSM_MUX_hdmi_cec,
- MSM_MUX_hdmi_ddc,
- MSM_MUX_hdmi_hpd,
- MSM_MUX_hdmi_rcv,
- MSM_MUX_mdp_vsync,
- MSM_MUX_mss_lte,
- MSM_MUX_nav_pps,
- MSM_MUX_nav_tsync,
- MSM_MUX_qdss_cti_trig_in_a,
- MSM_MUX_qdss_cti_trig_in_b,
- MSM_MUX_qdss_cti_trig_in_c,
- MSM_MUX_qdss_cti_trig_in_d,
- MSM_MUX_qdss_cti_trig_out_a,
- MSM_MUX_qdss_cti_trig_out_b,
- MSM_MUX_qdss_cti_trig_out_c,
- MSM_MUX_qdss_cti_trig_out_d,
- MSM_MUX_qdss_traceclk_a,
- MSM_MUX_qdss_traceclk_b,
- MSM_MUX_qdss_tracectl_a,
- MSM_MUX_qdss_tracectl_b,
- MSM_MUX_qdss_tracedata_a,
- MSM_MUX_qdss_tracedata_b,
- MSM_MUX_qua_mi2s,
- MSM_MUX_pci_e0,
- MSM_MUX_pci_e1,
- MSM_MUX_pri_mi2s,
- MSM_MUX_sdc4,
- MSM_MUX_sec_mi2s,
- MSM_MUX_slimbus,
- MSM_MUX_spkr_i2s,
- MSM_MUX_ter_mi2s,
- MSM_MUX_tsif1,
- MSM_MUX_tsif2,
- MSM_MUX_uim1,
- MSM_MUX_uim2,
- MSM_MUX_uim3,
- MSM_MUX_uim4,
- MSM_MUX_uim_batt_alarm,
- MSM_MUX_gpio,
- MSM_MUX_NA,
+ msm_mux_audio_ref_clk,
+ msm_mux_blsp_i2c1,
+ msm_mux_blsp_i2c2,
+ msm_mux_blsp_i2c3,
+ msm_mux_blsp_i2c4,
+ msm_mux_blsp_i2c5,
+ msm_mux_blsp_i2c6,
+ msm_mux_blsp_i2c7,
+ msm_mux_blsp_i2c8,
+ msm_mux_blsp_i2c9,
+ msm_mux_blsp_i2c10,
+ msm_mux_blsp_i2c11,
+ msm_mux_blsp_i2c12,
+ msm_mux_blsp_spi1,
+ msm_mux_blsp_spi1_cs1,
+ msm_mux_blsp_spi1_cs2,
+ msm_mux_blsp_spi1_cs3,
+ msm_mux_blsp_spi2,
+ msm_mux_blsp_spi2_cs1,
+ msm_mux_blsp_spi2_cs2,
+ msm_mux_blsp_spi2_cs3,
+ msm_mux_blsp_spi3,
+ msm_mux_blsp_spi4,
+ msm_mux_blsp_spi5,
+ msm_mux_blsp_spi6,
+ msm_mux_blsp_spi7,
+ msm_mux_blsp_spi8,
+ msm_mux_blsp_spi9,
+ msm_mux_blsp_spi10,
+ msm_mux_blsp_spi10_cs1,
+ msm_mux_blsp_spi10_cs2,
+ msm_mux_blsp_spi10_cs3,
+ msm_mux_blsp_spi11,
+ msm_mux_blsp_spi12,
+ msm_mux_blsp_uart1,
+ msm_mux_blsp_uart2,
+ msm_mux_blsp_uart3,
+ msm_mux_blsp_uart4,
+ msm_mux_blsp_uart5,
+ msm_mux_blsp_uart6,
+ msm_mux_blsp_uart7,
+ msm_mux_blsp_uart8,
+ msm_mux_blsp_uart9,
+ msm_mux_blsp_uart10,
+ msm_mux_blsp_uart11,
+ msm_mux_blsp_uart12,
+ msm_mux_blsp_uim1,
+ msm_mux_blsp_uim2,
+ msm_mux_blsp_uim3,
+ msm_mux_blsp_uim4,
+ msm_mux_blsp_uim5,
+ msm_mux_blsp_uim6,
+ msm_mux_blsp_uim7,
+ msm_mux_blsp_uim8,
+ msm_mux_blsp_uim9,
+ msm_mux_blsp_uim10,
+ msm_mux_blsp_uim11,
+ msm_mux_blsp_uim12,
+ msm_mux_blsp11_i2c_scl_b,
+ msm_mux_blsp11_i2c_sda_b,
+ msm_mux_blsp11_uart_rx_b,
+ msm_mux_blsp11_uart_tx_b,
+ msm_mux_cam_mclk0,
+ msm_mux_cam_mclk1,
+ msm_mux_cam_mclk2,
+ msm_mux_cam_mclk3,
+ msm_mux_cci_async_in0,
+ msm_mux_cci_async_in1,
+ msm_mux_cci_async_in2,
+ msm_mux_cci_i2c0,
+ msm_mux_cci_i2c1,
+ msm_mux_cci_timer0,
+ msm_mux_cci_timer1,
+ msm_mux_cci_timer2,
+ msm_mux_cci_timer3,
+ msm_mux_cci_timer4,
+ msm_mux_gcc_gp1_clk_a,
+ msm_mux_gcc_gp1_clk_b,
+ msm_mux_gcc_gp2_clk_a,
+ msm_mux_gcc_gp2_clk_b,
+ msm_mux_gcc_gp3_clk_a,
+ msm_mux_gcc_gp3_clk_b,
+ msm_mux_gp_mn,
+ msm_mux_gp_pdm0,
+ msm_mux_gp_pdm1,
+ msm_mux_gp_pdm2,
+ msm_mux_gp0_clk,
+ msm_mux_gp1_clk,
+ msm_mux_gps_tx,
+ msm_mux_gsm_tx,
+ msm_mux_hdmi_cec,
+ msm_mux_hdmi_ddc,
+ msm_mux_hdmi_hpd,
+ msm_mux_hdmi_rcv,
+ msm_mux_mdp_vsync,
+ msm_mux_mss_lte,
+ msm_mux_nav_pps,
+ msm_mux_nav_tsync,
+ msm_mux_qdss_cti_trig_in_a,
+ msm_mux_qdss_cti_trig_in_b,
+ msm_mux_qdss_cti_trig_in_c,
+ msm_mux_qdss_cti_trig_in_d,
+ msm_mux_qdss_cti_trig_out_a,
+ msm_mux_qdss_cti_trig_out_b,
+ msm_mux_qdss_cti_trig_out_c,
+ msm_mux_qdss_cti_trig_out_d,
+ msm_mux_qdss_traceclk_a,
+ msm_mux_qdss_traceclk_b,
+ msm_mux_qdss_tracectl_a,
+ msm_mux_qdss_tracectl_b,
+ msm_mux_qdss_tracedata_a,
+ msm_mux_qdss_tracedata_b,
+ msm_mux_qua_mi2s,
+ msm_mux_pci_e0,
+ msm_mux_pci_e1,
+ msm_mux_pri_mi2s,
+ msm_mux_sdc4,
+ msm_mux_sec_mi2s,
+ msm_mux_slimbus,
+ msm_mux_spkr_i2s,
+ msm_mux_ter_mi2s,
+ msm_mux_tsif1,
+ msm_mux_tsif2,
+ msm_mux_uim1,
+ msm_mux_uim2,
+ msm_mux_uim3,
+ msm_mux_uim4,
+ msm_mux_uim_batt_alarm,
+ msm_mux_gpio,
+ msm_mux_NA,
};
static const char * const gpio_groups[] = {
@@ -950,136 +942,136 @@ static const char * const mss_lte_groups[] = {
"gpio134", "gpio135"
};
-static const struct msm_function msm8994_functions[] = {
- FUNCTION(audio_ref_clk),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_i2c5),
- FUNCTION(blsp_i2c6),
- FUNCTION(blsp_i2c7),
- FUNCTION(blsp_i2c8),
- FUNCTION(blsp_i2c9),
- FUNCTION(blsp_i2c10),
- FUNCTION(blsp_i2c11),
- FUNCTION(blsp_i2c12),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi1_cs1),
- FUNCTION(blsp_spi1_cs2),
- FUNCTION(blsp_spi1_cs3),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi2_cs1),
- FUNCTION(blsp_spi2_cs2),
- FUNCTION(blsp_spi2_cs3),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_spi5),
- FUNCTION(blsp_spi6),
- FUNCTION(blsp_spi7),
- FUNCTION(blsp_spi8),
- FUNCTION(blsp_spi9),
- FUNCTION(blsp_spi10),
- FUNCTION(blsp_spi10_cs1),
- FUNCTION(blsp_spi10_cs2),
- FUNCTION(blsp_spi10_cs3),
- FUNCTION(blsp_spi11),
- FUNCTION(blsp_spi12),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_uart3),
- FUNCTION(blsp_uart4),
- FUNCTION(blsp_uart5),
- FUNCTION(blsp_uart6),
- FUNCTION(blsp_uart7),
- FUNCTION(blsp_uart8),
- FUNCTION(blsp_uart9),
- FUNCTION(blsp_uart10),
- FUNCTION(blsp_uart11),
- FUNCTION(blsp_uart12),
- FUNCTION(blsp_uim1),
- FUNCTION(blsp_uim2),
- FUNCTION(blsp_uim3),
- FUNCTION(blsp_uim4),
- FUNCTION(blsp_uim5),
- FUNCTION(blsp_uim6),
- FUNCTION(blsp_uim7),
- FUNCTION(blsp_uim8),
- FUNCTION(blsp_uim9),
- FUNCTION(blsp_uim10),
- FUNCTION(blsp_uim11),
- FUNCTION(blsp_uim12),
- FUNCTION(blsp11_i2c_scl_b),
- FUNCTION(blsp11_i2c_sda_b),
- FUNCTION(blsp11_uart_rx_b),
- FUNCTION(blsp11_uart_tx_b),
- FUNCTION(cam_mclk0),
- FUNCTION(cam_mclk1),
- FUNCTION(cam_mclk2),
- FUNCTION(cam_mclk3),
- FUNCTION(cci_async_in0),
- FUNCTION(cci_async_in1),
- FUNCTION(cci_async_in2),
- FUNCTION(cci_i2c0),
- FUNCTION(cci_i2c1),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(gcc_gp1_clk_a),
- FUNCTION(gcc_gp1_clk_b),
- FUNCTION(gcc_gp2_clk_a),
- FUNCTION(gcc_gp2_clk_b),
- FUNCTION(gcc_gp3_clk_a),
- FUNCTION(gcc_gp3_clk_b),
- FUNCTION(gp_mn),
- FUNCTION(gp_pdm0),
- FUNCTION(gp_pdm1),
- FUNCTION(gp_pdm2),
- FUNCTION(gp0_clk),
- FUNCTION(gp1_clk),
- FUNCTION(gps_tx),
- FUNCTION(gsm_tx),
- FUNCTION(hdmi_cec),
- FUNCTION(hdmi_ddc),
- FUNCTION(hdmi_hpd),
- FUNCTION(hdmi_rcv),
- FUNCTION(mdp_vsync),
- FUNCTION(mss_lte),
- FUNCTION(nav_pps),
- FUNCTION(nav_tsync),
- FUNCTION(qdss_cti_trig_in_a),
- FUNCTION(qdss_cti_trig_in_b),
- FUNCTION(qdss_cti_trig_in_c),
- FUNCTION(qdss_cti_trig_in_d),
- FUNCTION(qdss_cti_trig_out_a),
- FUNCTION(qdss_cti_trig_out_b),
- FUNCTION(qdss_cti_trig_out_c),
- FUNCTION(qdss_cti_trig_out_d),
- FUNCTION(qdss_traceclk_a),
- FUNCTION(qdss_traceclk_b),
- FUNCTION(qdss_tracectl_a),
- FUNCTION(qdss_tracectl_b),
- FUNCTION(qdss_tracedata_a),
- FUNCTION(qdss_tracedata_b),
- FUNCTION(qua_mi2s),
- FUNCTION(pci_e0),
- FUNCTION(pci_e1),
- FUNCTION(pri_mi2s),
- FUNCTION(sdc4),
- FUNCTION(sec_mi2s),
- FUNCTION(slimbus),
- FUNCTION(spkr_i2s),
- FUNCTION(ter_mi2s),
- FUNCTION(tsif1),
- FUNCTION(tsif2),
- FUNCTION(uim_batt_alarm),
- FUNCTION(uim1),
- FUNCTION(uim2),
- FUNCTION(uim3),
- FUNCTION(uim4),
- FUNCTION(gpio),
+static const struct pinfunction msm8994_functions[] = {
+ MSM_PIN_FUNCTION(audio_ref_clk),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_i2c5),
+ MSM_PIN_FUNCTION(blsp_i2c6),
+ MSM_PIN_FUNCTION(blsp_i2c7),
+ MSM_PIN_FUNCTION(blsp_i2c8),
+ MSM_PIN_FUNCTION(blsp_i2c9),
+ MSM_PIN_FUNCTION(blsp_i2c10),
+ MSM_PIN_FUNCTION(blsp_i2c11),
+ MSM_PIN_FUNCTION(blsp_i2c12),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(blsp_spi1_cs1),
+ MSM_PIN_FUNCTION(blsp_spi1_cs2),
+ MSM_PIN_FUNCTION(blsp_spi1_cs3),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_spi2_cs1),
+ MSM_PIN_FUNCTION(blsp_spi2_cs2),
+ MSM_PIN_FUNCTION(blsp_spi2_cs3),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(blsp_spi5),
+ MSM_PIN_FUNCTION(blsp_spi6),
+ MSM_PIN_FUNCTION(blsp_spi7),
+ MSM_PIN_FUNCTION(blsp_spi8),
+ MSM_PIN_FUNCTION(blsp_spi9),
+ MSM_PIN_FUNCTION(blsp_spi10),
+ MSM_PIN_FUNCTION(blsp_spi10_cs1),
+ MSM_PIN_FUNCTION(blsp_spi10_cs2),
+ MSM_PIN_FUNCTION(blsp_spi10_cs3),
+ MSM_PIN_FUNCTION(blsp_spi11),
+ MSM_PIN_FUNCTION(blsp_spi12),
+ MSM_PIN_FUNCTION(blsp_uart1),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(blsp_uart3),
+ MSM_PIN_FUNCTION(blsp_uart4),
+ MSM_PIN_FUNCTION(blsp_uart5),
+ MSM_PIN_FUNCTION(blsp_uart6),
+ MSM_PIN_FUNCTION(blsp_uart7),
+ MSM_PIN_FUNCTION(blsp_uart8),
+ MSM_PIN_FUNCTION(blsp_uart9),
+ MSM_PIN_FUNCTION(blsp_uart10),
+ MSM_PIN_FUNCTION(blsp_uart11),
+ MSM_PIN_FUNCTION(blsp_uart12),
+ MSM_PIN_FUNCTION(blsp_uim1),
+ MSM_PIN_FUNCTION(blsp_uim2),
+ MSM_PIN_FUNCTION(blsp_uim3),
+ MSM_PIN_FUNCTION(blsp_uim4),
+ MSM_PIN_FUNCTION(blsp_uim5),
+ MSM_PIN_FUNCTION(blsp_uim6),
+ MSM_PIN_FUNCTION(blsp_uim7),
+ MSM_PIN_FUNCTION(blsp_uim8),
+ MSM_PIN_FUNCTION(blsp_uim9),
+ MSM_PIN_FUNCTION(blsp_uim10),
+ MSM_PIN_FUNCTION(blsp_uim11),
+ MSM_PIN_FUNCTION(blsp_uim12),
+ MSM_PIN_FUNCTION(blsp11_i2c_scl_b),
+ MSM_PIN_FUNCTION(blsp11_i2c_sda_b),
+ MSM_PIN_FUNCTION(blsp11_uart_rx_b),
+ MSM_PIN_FUNCTION(blsp11_uart_tx_b),
+ MSM_PIN_FUNCTION(cam_mclk0),
+ MSM_PIN_FUNCTION(cam_mclk1),
+ MSM_PIN_FUNCTION(cam_mclk2),
+ MSM_PIN_FUNCTION(cam_mclk3),
+ MSM_PIN_FUNCTION(cci_async_in0),
+ MSM_PIN_FUNCTION(cci_async_in1),
+ MSM_PIN_FUNCTION(cci_async_in2),
+ MSM_PIN_FUNCTION(cci_i2c0),
+ MSM_PIN_FUNCTION(cci_i2c1),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_b),
+ MSM_PIN_FUNCTION(gp_mn),
+ MSM_PIN_FUNCTION(gp_pdm0),
+ MSM_PIN_FUNCTION(gp_pdm1),
+ MSM_PIN_FUNCTION(gp_pdm2),
+ MSM_PIN_FUNCTION(gp0_clk),
+ MSM_PIN_FUNCTION(gp1_clk),
+ MSM_PIN_FUNCTION(gps_tx),
+ MSM_PIN_FUNCTION(gsm_tx),
+ MSM_PIN_FUNCTION(hdmi_cec),
+ MSM_PIN_FUNCTION(hdmi_ddc),
+ MSM_PIN_FUNCTION(hdmi_hpd),
+ MSM_PIN_FUNCTION(hdmi_rcv),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(nav_tsync),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_c),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_d),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_c),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_d),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_traceclk_b),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_b),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(qua_mi2s),
+ MSM_PIN_FUNCTION(pci_e0),
+ MSM_PIN_FUNCTION(pci_e1),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(sdc4),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(slimbus),
+ MSM_PIN_FUNCTION(spkr_i2s),
+ MSM_PIN_FUNCTION(ter_mi2s),
+ MSM_PIN_FUNCTION(tsif1),
+ MSM_PIN_FUNCTION(tsif2),
+ MSM_PIN_FUNCTION(uim_batt_alarm),
+ MSM_PIN_FUNCTION(uim1),
+ MSM_PIN_FUNCTION(uim2),
+ MSM_PIN_FUNCTION(uim3),
+ MSM_PIN_FUNCTION(uim4),
+ MSM_PIN_FUNCTION(gpio),
};
static const struct msm_pingroup msm8994_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8996.c b/drivers/pinctrl/qcom/pinctrl-msm8996.c
index 05812dfdb368..46cc0b49dbab 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8996.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8996.c
@@ -6,24 +6,16 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_BASE 0x0
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -60,9 +52,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -1409,250 +1401,250 @@ static const char * const qspi3_groups[] = {
"gpio149",
};
-static const struct msm_function msm8996_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(atest_bbrx0),
- FUNCTION(atest_bbrx1),
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(atest_gpsadc0),
- FUNCTION(atest_gpsadc1),
- FUNCTION(atest_tsens),
- FUNCTION(atest_tsens2),
- FUNCTION(atest_usb1),
- FUNCTION(atest_usb10),
- FUNCTION(atest_usb11),
- FUNCTION(atest_usb12),
- FUNCTION(atest_usb13),
- FUNCTION(atest_usb2),
- FUNCTION(atest_usb20),
- FUNCTION(atest_usb21),
- FUNCTION(atest_usb22),
- FUNCTION(atest_usb23),
- FUNCTION(audio_ref),
- FUNCTION(bimc_dte0),
- FUNCTION(bimc_dte1),
- FUNCTION(blsp10_spi),
- FUNCTION(blsp11_i2c_scl_b),
- FUNCTION(blsp11_i2c_sda_b),
- FUNCTION(blsp11_uart_rx_b),
- FUNCTION(blsp11_uart_tx_b),
- FUNCTION(blsp1_spi),
- FUNCTION(blsp2_spi),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c10),
- FUNCTION(blsp_i2c11),
- FUNCTION(blsp_i2c12),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_i2c5),
- FUNCTION(blsp_i2c6),
- FUNCTION(blsp_i2c7),
- FUNCTION(blsp_i2c8),
- FUNCTION(blsp_i2c9),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi10),
- FUNCTION(blsp_spi11),
- FUNCTION(blsp_spi12),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_spi5),
- FUNCTION(blsp_spi6),
- FUNCTION(blsp_spi7),
- FUNCTION(blsp_spi8),
- FUNCTION(blsp_spi9),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_uart10),
- FUNCTION(blsp_uart11),
- FUNCTION(blsp_uart12),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_uart3),
- FUNCTION(blsp_uart4),
- FUNCTION(blsp_uart5),
- FUNCTION(blsp_uart6),
- FUNCTION(blsp_uart7),
- FUNCTION(blsp_uart8),
- FUNCTION(blsp_uart9),
- FUNCTION(blsp_uim1),
- FUNCTION(blsp_uim10),
- FUNCTION(blsp_uim11),
- FUNCTION(blsp_uim12),
- FUNCTION(blsp_uim2),
- FUNCTION(blsp_uim3),
- FUNCTION(blsp_uim4),
- FUNCTION(blsp_uim5),
- FUNCTION(blsp_uim6),
- FUNCTION(blsp_uim7),
- FUNCTION(blsp_uim8),
- FUNCTION(blsp_uim9),
- FUNCTION(btfm_slimbus),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dac_calib0),
- FUNCTION(dac_calib1),
- FUNCTION(dac_calib10),
- FUNCTION(dac_calib11),
- FUNCTION(dac_calib12),
- FUNCTION(dac_calib13),
- FUNCTION(dac_calib14),
- FUNCTION(dac_calib15),
- FUNCTION(dac_calib16),
- FUNCTION(dac_calib17),
- FUNCTION(dac_calib18),
- FUNCTION(dac_calib19),
- FUNCTION(dac_calib2),
- FUNCTION(dac_calib20),
- FUNCTION(dac_calib21),
- FUNCTION(dac_calib22),
- FUNCTION(dac_calib23),
- FUNCTION(dac_calib24),
- FUNCTION(dac_calib25),
- FUNCTION(dac_calib26),
- FUNCTION(dac_calib3),
- FUNCTION(dac_calib4),
- FUNCTION(dac_calib5),
- FUNCTION(dac_calib6),
- FUNCTION(dac_calib7),
- FUNCTION(dac_calib8),
- FUNCTION(dac_calib9),
- FUNCTION(dac_gpio),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(edp_hot),
- FUNCTION(edp_lcd),
- FUNCTION(gcc_gp1_clk_a),
- FUNCTION(gcc_gp1_clk_b),
- FUNCTION(gcc_gp2_clk_a),
- FUNCTION(gcc_gp2_clk_b),
- FUNCTION(gcc_gp3_clk_a),
- FUNCTION(gcc_gp3_clk_b),
- FUNCTION(gpio),
- FUNCTION(gsm_tx),
- FUNCTION(hdmi_cec),
- FUNCTION(hdmi_ddc),
- FUNCTION(hdmi_hot),
- FUNCTION(hdmi_rcv),
- FUNCTION(isense_dbg),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(lpass_slimbus),
- FUNCTION(m_voc),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync_p_b),
- FUNCTION(mdp_vsync_s_b),
- FUNCTION(modem_tsync),
- FUNCTION(mss_lte),
- FUNCTION(nav_dr),
- FUNCTION(nav_pps),
- FUNCTION(pa_indicator),
- FUNCTION(pci_e0),
- FUNCTION(pci_e1),
- FUNCTION(pci_e2),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_reset),
- FUNCTION(pri_mi2s),
- FUNCTION(prng_rosc),
- FUNCTION(pwr_crypto),
- FUNCTION(pwr_modem),
- FUNCTION(pwr_nav),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_cti_trig_in_a),
- FUNCTION(qdss_cti_trig_in_b),
- FUNCTION(qdss_cti_trig_out_a),
- FUNCTION(qdss_cti_trig_out_b),
- FUNCTION(qdss_stm0),
- FUNCTION(qdss_stm1),
- FUNCTION(qdss_stm10),
- FUNCTION(qdss_stm11),
- FUNCTION(qdss_stm12),
- FUNCTION(qdss_stm13),
- FUNCTION(qdss_stm14),
- FUNCTION(qdss_stm15),
- FUNCTION(qdss_stm16),
- FUNCTION(qdss_stm17),
- FUNCTION(qdss_stm18),
- FUNCTION(qdss_stm19),
- FUNCTION(qdss_stm2),
- FUNCTION(qdss_stm20),
- FUNCTION(qdss_stm21),
- FUNCTION(qdss_stm22),
- FUNCTION(qdss_stm23),
- FUNCTION(qdss_stm24),
- FUNCTION(qdss_stm25),
- FUNCTION(qdss_stm26),
- FUNCTION(qdss_stm27),
- FUNCTION(qdss_stm28),
- FUNCTION(qdss_stm29),
- FUNCTION(qdss_stm3),
- FUNCTION(qdss_stm30),
- FUNCTION(qdss_stm31),
- FUNCTION(qdss_stm4),
- FUNCTION(qdss_stm5),
- FUNCTION(qdss_stm6),
- FUNCTION(qdss_stm7),
- FUNCTION(qdss_stm8),
- FUNCTION(qdss_stm9),
- FUNCTION(qdss_traceclk_a),
- FUNCTION(qdss_traceclk_b),
- FUNCTION(qdss_tracectl_a),
- FUNCTION(qdss_tracectl_b),
- FUNCTION(qdss_tracedata_11),
- FUNCTION(qdss_tracedata_12),
- FUNCTION(qdss_tracedata_a),
- FUNCTION(qdss_tracedata_b),
- FUNCTION(qspi0),
- FUNCTION(qspi1),
- FUNCTION(qspi2),
- FUNCTION(qspi3),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(qua_mi2s),
- FUNCTION(sd_card),
- FUNCTION(sd_write),
- FUNCTION(sdc40),
- FUNCTION(sdc41),
- FUNCTION(sdc42),
- FUNCTION(sdc43),
- FUNCTION(sdc4_clk),
- FUNCTION(sdc4_cmd),
- FUNCTION(sec_mi2s),
- FUNCTION(spkr_i2s),
- FUNCTION(ssbi1),
- FUNCTION(ssbi2),
- FUNCTION(ssc_irq),
- FUNCTION(ter_mi2s),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(tsif1_clk),
- FUNCTION(tsif1_data),
- FUNCTION(tsif1_en),
- FUNCTION(tsif1_error),
- FUNCTION(tsif1_sync),
- FUNCTION(tsif2_clk),
- FUNCTION(tsif2_data),
- FUNCTION(tsif2_en),
- FUNCTION(tsif2_error),
- FUNCTION(tsif2_sync),
- FUNCTION(uim1),
- FUNCTION(uim2),
- FUNCTION(uim3),
- FUNCTION(uim4),
- FUNCTION(uim_batt),
- FUNCTION(vfr_1),
+static const struct pinfunction msm8996_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(atest_bbrx0),
+ MSM_PIN_FUNCTION(atest_bbrx1),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_gpsadc0),
+ MSM_PIN_FUNCTION(atest_gpsadc1),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_tsens2),
+ MSM_PIN_FUNCTION(atest_usb1),
+ MSM_PIN_FUNCTION(atest_usb10),
+ MSM_PIN_FUNCTION(atest_usb11),
+ MSM_PIN_FUNCTION(atest_usb12),
+ MSM_PIN_FUNCTION(atest_usb13),
+ MSM_PIN_FUNCTION(atest_usb2),
+ MSM_PIN_FUNCTION(atest_usb20),
+ MSM_PIN_FUNCTION(atest_usb21),
+ MSM_PIN_FUNCTION(atest_usb22),
+ MSM_PIN_FUNCTION(atest_usb23),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(bimc_dte0),
+ MSM_PIN_FUNCTION(bimc_dte1),
+ MSM_PIN_FUNCTION(blsp10_spi),
+ MSM_PIN_FUNCTION(blsp11_i2c_scl_b),
+ MSM_PIN_FUNCTION(blsp11_i2c_sda_b),
+ MSM_PIN_FUNCTION(blsp11_uart_rx_b),
+ MSM_PIN_FUNCTION(blsp11_uart_tx_b),
+ MSM_PIN_FUNCTION(blsp1_spi),
+ MSM_PIN_FUNCTION(blsp2_spi),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_i2c10),
+ MSM_PIN_FUNCTION(blsp_i2c11),
+ MSM_PIN_FUNCTION(blsp_i2c12),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_i2c5),
+ MSM_PIN_FUNCTION(blsp_i2c6),
+ MSM_PIN_FUNCTION(blsp_i2c7),
+ MSM_PIN_FUNCTION(blsp_i2c8),
+ MSM_PIN_FUNCTION(blsp_i2c9),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(blsp_spi10),
+ MSM_PIN_FUNCTION(blsp_spi11),
+ MSM_PIN_FUNCTION(blsp_spi12),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(blsp_spi5),
+ MSM_PIN_FUNCTION(blsp_spi6),
+ MSM_PIN_FUNCTION(blsp_spi7),
+ MSM_PIN_FUNCTION(blsp_spi8),
+ MSM_PIN_FUNCTION(blsp_spi9),
+ MSM_PIN_FUNCTION(blsp_uart1),
+ MSM_PIN_FUNCTION(blsp_uart10),
+ MSM_PIN_FUNCTION(blsp_uart11),
+ MSM_PIN_FUNCTION(blsp_uart12),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(blsp_uart3),
+ MSM_PIN_FUNCTION(blsp_uart4),
+ MSM_PIN_FUNCTION(blsp_uart5),
+ MSM_PIN_FUNCTION(blsp_uart6),
+ MSM_PIN_FUNCTION(blsp_uart7),
+ MSM_PIN_FUNCTION(blsp_uart8),
+ MSM_PIN_FUNCTION(blsp_uart9),
+ MSM_PIN_FUNCTION(blsp_uim1),
+ MSM_PIN_FUNCTION(blsp_uim10),
+ MSM_PIN_FUNCTION(blsp_uim11),
+ MSM_PIN_FUNCTION(blsp_uim12),
+ MSM_PIN_FUNCTION(blsp_uim2),
+ MSM_PIN_FUNCTION(blsp_uim3),
+ MSM_PIN_FUNCTION(blsp_uim4),
+ MSM_PIN_FUNCTION(blsp_uim5),
+ MSM_PIN_FUNCTION(blsp_uim6),
+ MSM_PIN_FUNCTION(blsp_uim7),
+ MSM_PIN_FUNCTION(blsp_uim8),
+ MSM_PIN_FUNCTION(blsp_uim9),
+ MSM_PIN_FUNCTION(btfm_slimbus),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dac_calib0),
+ MSM_PIN_FUNCTION(dac_calib1),
+ MSM_PIN_FUNCTION(dac_calib10),
+ MSM_PIN_FUNCTION(dac_calib11),
+ MSM_PIN_FUNCTION(dac_calib12),
+ MSM_PIN_FUNCTION(dac_calib13),
+ MSM_PIN_FUNCTION(dac_calib14),
+ MSM_PIN_FUNCTION(dac_calib15),
+ MSM_PIN_FUNCTION(dac_calib16),
+ MSM_PIN_FUNCTION(dac_calib17),
+ MSM_PIN_FUNCTION(dac_calib18),
+ MSM_PIN_FUNCTION(dac_calib19),
+ MSM_PIN_FUNCTION(dac_calib2),
+ MSM_PIN_FUNCTION(dac_calib20),
+ MSM_PIN_FUNCTION(dac_calib21),
+ MSM_PIN_FUNCTION(dac_calib22),
+ MSM_PIN_FUNCTION(dac_calib23),
+ MSM_PIN_FUNCTION(dac_calib24),
+ MSM_PIN_FUNCTION(dac_calib25),
+ MSM_PIN_FUNCTION(dac_calib26),
+ MSM_PIN_FUNCTION(dac_calib3),
+ MSM_PIN_FUNCTION(dac_calib4),
+ MSM_PIN_FUNCTION(dac_calib5),
+ MSM_PIN_FUNCTION(dac_calib6),
+ MSM_PIN_FUNCTION(dac_calib7),
+ MSM_PIN_FUNCTION(dac_calib8),
+ MSM_PIN_FUNCTION(dac_calib9),
+ MSM_PIN_FUNCTION(dac_gpio),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(edp_hot),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_b),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_a),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_b),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gsm_tx),
+ MSM_PIN_FUNCTION(hdmi_cec),
+ MSM_PIN_FUNCTION(hdmi_ddc),
+ MSM_PIN_FUNCTION(hdmi_hot),
+ MSM_PIN_FUNCTION(hdmi_rcv),
+ MSM_PIN_FUNCTION(isense_dbg),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(lpass_slimbus),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync_p_b),
+ MSM_PIN_FUNCTION(mdp_vsync_s_b),
+ MSM_PIN_FUNCTION(modem_tsync),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(nav_dr),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pci_e0),
+ MSM_PIN_FUNCTION(pci_e1),
+ MSM_PIN_FUNCTION(pci_e2),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(pwr_crypto),
+ MSM_PIN_FUNCTION(pwr_modem),
+ MSM_PIN_FUNCTION(pwr_nav),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b),
+ MSM_PIN_FUNCTION(qdss_stm0),
+ MSM_PIN_FUNCTION(qdss_stm1),
+ MSM_PIN_FUNCTION(qdss_stm10),
+ MSM_PIN_FUNCTION(qdss_stm11),
+ MSM_PIN_FUNCTION(qdss_stm12),
+ MSM_PIN_FUNCTION(qdss_stm13),
+ MSM_PIN_FUNCTION(qdss_stm14),
+ MSM_PIN_FUNCTION(qdss_stm15),
+ MSM_PIN_FUNCTION(qdss_stm16),
+ MSM_PIN_FUNCTION(qdss_stm17),
+ MSM_PIN_FUNCTION(qdss_stm18),
+ MSM_PIN_FUNCTION(qdss_stm19),
+ MSM_PIN_FUNCTION(qdss_stm2),
+ MSM_PIN_FUNCTION(qdss_stm20),
+ MSM_PIN_FUNCTION(qdss_stm21),
+ MSM_PIN_FUNCTION(qdss_stm22),
+ MSM_PIN_FUNCTION(qdss_stm23),
+ MSM_PIN_FUNCTION(qdss_stm24),
+ MSM_PIN_FUNCTION(qdss_stm25),
+ MSM_PIN_FUNCTION(qdss_stm26),
+ MSM_PIN_FUNCTION(qdss_stm27),
+ MSM_PIN_FUNCTION(qdss_stm28),
+ MSM_PIN_FUNCTION(qdss_stm29),
+ MSM_PIN_FUNCTION(qdss_stm3),
+ MSM_PIN_FUNCTION(qdss_stm30),
+ MSM_PIN_FUNCTION(qdss_stm31),
+ MSM_PIN_FUNCTION(qdss_stm4),
+ MSM_PIN_FUNCTION(qdss_stm5),
+ MSM_PIN_FUNCTION(qdss_stm6),
+ MSM_PIN_FUNCTION(qdss_stm7),
+ MSM_PIN_FUNCTION(qdss_stm8),
+ MSM_PIN_FUNCTION(qdss_stm9),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_traceclk_b),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_b),
+ MSM_PIN_FUNCTION(qdss_tracedata_11),
+ MSM_PIN_FUNCTION(qdss_tracedata_12),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(qspi0),
+ MSM_PIN_FUNCTION(qspi1),
+ MSM_PIN_FUNCTION(qspi2),
+ MSM_PIN_FUNCTION(qspi3),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qua_mi2s),
+ MSM_PIN_FUNCTION(sd_card),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sdc40),
+ MSM_PIN_FUNCTION(sdc41),
+ MSM_PIN_FUNCTION(sdc42),
+ MSM_PIN_FUNCTION(sdc43),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(spkr_i2s),
+ MSM_PIN_FUNCTION(ssbi1),
+ MSM_PIN_FUNCTION(ssbi2),
+ MSM_PIN_FUNCTION(ssc_irq),
+ MSM_PIN_FUNCTION(ter_mi2s),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(tsif1_clk),
+ MSM_PIN_FUNCTION(tsif1_data),
+ MSM_PIN_FUNCTION(tsif1_en),
+ MSM_PIN_FUNCTION(tsif1_error),
+ MSM_PIN_FUNCTION(tsif1_sync),
+ MSM_PIN_FUNCTION(tsif2_clk),
+ MSM_PIN_FUNCTION(tsif2_data),
+ MSM_PIN_FUNCTION(tsif2_en),
+ MSM_PIN_FUNCTION(tsif2_error),
+ MSM_PIN_FUNCTION(tsif2_sync),
+ MSM_PIN_FUNCTION(uim1),
+ MSM_PIN_FUNCTION(uim2),
+ MSM_PIN_FUNCTION(uim3),
+ MSM_PIN_FUNCTION(uim4),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(vfr_1),
};
static const struct msm_pingroup msm8996_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8998.c b/drivers/pinctrl/qcom/pinctrl-msm8998.c
index 1a061bc9b8fa..b7cbf32b3125 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8998.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8998.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -14,18 +13,11 @@
#define WEST 0x100000
#define EAST 0x900000
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -62,9 +54,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -87,9 +79,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -1167,183 +1159,183 @@ static const char * const mss_lte_groups[] = {
"gpio144", "gpio145",
};
-static const struct msm_function msm8998_functions[] = {
- FUNCTION(gpio),
- FUNCTION(adsp_ext),
- FUNCTION(agera_pll),
- FUNCTION(atest_char),
- FUNCTION(atest_gpsadc0),
- FUNCTION(atest_gpsadc1),
- FUNCTION(atest_tsens),
- FUNCTION(atest_tsens2),
- FUNCTION(atest_usb1),
- FUNCTION(atest_usb10),
- FUNCTION(atest_usb11),
- FUNCTION(atest_usb12),
- FUNCTION(atest_usb13),
- FUNCTION(audio_ref),
- FUNCTION(bimc_dte0),
- FUNCTION(bimc_dte1),
- FUNCTION(blsp10_spi),
- FUNCTION(blsp10_spi_a),
- FUNCTION(blsp10_spi_b),
- FUNCTION(blsp11_i2c),
- FUNCTION(blsp1_spi),
- FUNCTION(blsp1_spi_a),
- FUNCTION(blsp1_spi_b),
- FUNCTION(blsp2_spi),
- FUNCTION(blsp9_spi),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_i2c5),
- FUNCTION(blsp_i2c6),
- FUNCTION(blsp_i2c7),
- FUNCTION(blsp_i2c8),
- FUNCTION(blsp_i2c9),
- FUNCTION(blsp_i2c10),
- FUNCTION(blsp_i2c11),
- FUNCTION(blsp_i2c12),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_spi5),
- FUNCTION(blsp_spi6),
- FUNCTION(blsp_spi7),
- FUNCTION(blsp_spi8),
- FUNCTION(blsp_spi9),
- FUNCTION(blsp_spi10),
- FUNCTION(blsp_spi11),
- FUNCTION(blsp_spi12),
- FUNCTION(blsp_uart1_a),
- FUNCTION(blsp_uart1_b),
- FUNCTION(blsp_uart2_a),
- FUNCTION(blsp_uart2_b),
- FUNCTION(blsp_uart3_a),
- FUNCTION(blsp_uart3_b),
- FUNCTION(blsp_uart7_a),
- FUNCTION(blsp_uart7_b),
- FUNCTION(blsp_uart8),
- FUNCTION(blsp_uart8_a),
- FUNCTION(blsp_uart8_b),
- FUNCTION(blsp_uart9_a),
- FUNCTION(blsp_uart9_b),
- FUNCTION(blsp_uim1_a),
- FUNCTION(blsp_uim1_b),
- FUNCTION(blsp_uim2_a),
- FUNCTION(blsp_uim2_b),
- FUNCTION(blsp_uim3_a),
- FUNCTION(blsp_uim3_b),
- FUNCTION(blsp_uim7_a),
- FUNCTION(blsp_uim7_b),
- FUNCTION(blsp_uim8_a),
- FUNCTION(blsp_uim8_b),
- FUNCTION(blsp_uim9_a),
- FUNCTION(blsp_uim9_b),
- FUNCTION(bt_reset),
- FUNCTION(btfm_slimbus),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(edp_hot),
- FUNCTION(edp_lcd),
- FUNCTION(gcc_gp1_a),
- FUNCTION(gcc_gp1_b),
- FUNCTION(gcc_gp2_a),
- FUNCTION(gcc_gp2_b),
- FUNCTION(gcc_gp3_a),
- FUNCTION(gcc_gp3_b),
- FUNCTION(hdmi_cec),
- FUNCTION(hdmi_ddc),
- FUNCTION(hdmi_hot),
- FUNCTION(hdmi_rcv),
- FUNCTION(isense_dbg),
- FUNCTION(jitter_bist),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(lpass_slimbus),
- FUNCTION(m_voc),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mdp_vsync_a),
- FUNCTION(mdp_vsync_b),
- FUNCTION(modem_tsync),
- FUNCTION(mss_lte),
- FUNCTION(nav_dr),
- FUNCTION(nav_pps),
- FUNCTION(pa_indicator),
- FUNCTION(pci_e0),
- FUNCTION(phase_flag),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_reset),
- FUNCTION(pri_mi2s),
- FUNCTION(pri_mi2s_ws),
- FUNCTION(prng_rosc),
- FUNCTION(pwr_crypto),
- FUNCTION(pwr_modem),
- FUNCTION(pwr_nav),
- FUNCTION(qdss_cti0_a),
- FUNCTION(qdss_cti0_b),
- FUNCTION(qdss_cti1_a),
- FUNCTION(qdss_cti1_b),
- FUNCTION(qdss),
- FUNCTION(qlink_enable),
- FUNCTION(qlink_request),
- FUNCTION(qua_mi2s),
- FUNCTION(sd_card),
- FUNCTION(sd_write),
- FUNCTION(sdc40),
- FUNCTION(sdc41),
- FUNCTION(sdc42),
- FUNCTION(sdc43),
- FUNCTION(sdc4_clk),
- FUNCTION(sdc4_cmd),
- FUNCTION(sec_mi2s),
- FUNCTION(sp_cmu),
- FUNCTION(spkr_i2s),
- FUNCTION(ssbi1),
- FUNCTION(ssc_irq),
- FUNCTION(ter_mi2s),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(tsif0),
- FUNCTION(tsif1),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(uim_batt),
- FUNCTION(usb_phy),
- FUNCTION(vfr_1),
- FUNCTION(vsense_clkout),
- FUNCTION(vsense_data0),
- FUNCTION(vsense_data1),
- FUNCTION(vsense_mode),
- FUNCTION(wlan1_adc0),
- FUNCTION(wlan1_adc1),
- FUNCTION(wlan2_adc0),
- FUNCTION(wlan2_adc1),
+static const struct pinfunction msm8998_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_gpsadc0),
+ MSM_PIN_FUNCTION(atest_gpsadc1),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_tsens2),
+ MSM_PIN_FUNCTION(atest_usb1),
+ MSM_PIN_FUNCTION(atest_usb10),
+ MSM_PIN_FUNCTION(atest_usb11),
+ MSM_PIN_FUNCTION(atest_usb12),
+ MSM_PIN_FUNCTION(atest_usb13),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(bimc_dte0),
+ MSM_PIN_FUNCTION(bimc_dte1),
+ MSM_PIN_FUNCTION(blsp10_spi),
+ MSM_PIN_FUNCTION(blsp10_spi_a),
+ MSM_PIN_FUNCTION(blsp10_spi_b),
+ MSM_PIN_FUNCTION(blsp11_i2c),
+ MSM_PIN_FUNCTION(blsp1_spi),
+ MSM_PIN_FUNCTION(blsp1_spi_a),
+ MSM_PIN_FUNCTION(blsp1_spi_b),
+ MSM_PIN_FUNCTION(blsp2_spi),
+ MSM_PIN_FUNCTION(blsp9_spi),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_i2c5),
+ MSM_PIN_FUNCTION(blsp_i2c6),
+ MSM_PIN_FUNCTION(blsp_i2c7),
+ MSM_PIN_FUNCTION(blsp_i2c8),
+ MSM_PIN_FUNCTION(blsp_i2c9),
+ MSM_PIN_FUNCTION(blsp_i2c10),
+ MSM_PIN_FUNCTION(blsp_i2c11),
+ MSM_PIN_FUNCTION(blsp_i2c12),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(blsp_spi5),
+ MSM_PIN_FUNCTION(blsp_spi6),
+ MSM_PIN_FUNCTION(blsp_spi7),
+ MSM_PIN_FUNCTION(blsp_spi8),
+ MSM_PIN_FUNCTION(blsp_spi9),
+ MSM_PIN_FUNCTION(blsp_spi10),
+ MSM_PIN_FUNCTION(blsp_spi11),
+ MSM_PIN_FUNCTION(blsp_spi12),
+ MSM_PIN_FUNCTION(blsp_uart1_a),
+ MSM_PIN_FUNCTION(blsp_uart1_b),
+ MSM_PIN_FUNCTION(blsp_uart2_a),
+ MSM_PIN_FUNCTION(blsp_uart2_b),
+ MSM_PIN_FUNCTION(blsp_uart3_a),
+ MSM_PIN_FUNCTION(blsp_uart3_b),
+ MSM_PIN_FUNCTION(blsp_uart7_a),
+ MSM_PIN_FUNCTION(blsp_uart7_b),
+ MSM_PIN_FUNCTION(blsp_uart8),
+ MSM_PIN_FUNCTION(blsp_uart8_a),
+ MSM_PIN_FUNCTION(blsp_uart8_b),
+ MSM_PIN_FUNCTION(blsp_uart9_a),
+ MSM_PIN_FUNCTION(blsp_uart9_b),
+ MSM_PIN_FUNCTION(blsp_uim1_a),
+ MSM_PIN_FUNCTION(blsp_uim1_b),
+ MSM_PIN_FUNCTION(blsp_uim2_a),
+ MSM_PIN_FUNCTION(blsp_uim2_b),
+ MSM_PIN_FUNCTION(blsp_uim3_a),
+ MSM_PIN_FUNCTION(blsp_uim3_b),
+ MSM_PIN_FUNCTION(blsp_uim7_a),
+ MSM_PIN_FUNCTION(blsp_uim7_b),
+ MSM_PIN_FUNCTION(blsp_uim8_a),
+ MSM_PIN_FUNCTION(blsp_uim8_b),
+ MSM_PIN_FUNCTION(blsp_uim9_a),
+ MSM_PIN_FUNCTION(blsp_uim9_b),
+ MSM_PIN_FUNCTION(bt_reset),
+ MSM_PIN_FUNCTION(btfm_slimbus),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(edp_hot),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(gcc_gp1_a),
+ MSM_PIN_FUNCTION(gcc_gp1_b),
+ MSM_PIN_FUNCTION(gcc_gp2_a),
+ MSM_PIN_FUNCTION(gcc_gp2_b),
+ MSM_PIN_FUNCTION(gcc_gp3_a),
+ MSM_PIN_FUNCTION(gcc_gp3_b),
+ MSM_PIN_FUNCTION(hdmi_cec),
+ MSM_PIN_FUNCTION(hdmi_ddc),
+ MSM_PIN_FUNCTION(hdmi_hot),
+ MSM_PIN_FUNCTION(hdmi_rcv),
+ MSM_PIN_FUNCTION(isense_dbg),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(lpass_slimbus),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mdp_vsync_a),
+ MSM_PIN_FUNCTION(mdp_vsync_b),
+ MSM_PIN_FUNCTION(modem_tsync),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(nav_dr),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pci_e0),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(pri_mi2s_ws),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(pwr_crypto),
+ MSM_PIN_FUNCTION(pwr_modem),
+ MSM_PIN_FUNCTION(pwr_nav),
+ MSM_PIN_FUNCTION(qdss_cti0_a),
+ MSM_PIN_FUNCTION(qdss_cti0_b),
+ MSM_PIN_FUNCTION(qdss_cti1_a),
+ MSM_PIN_FUNCTION(qdss_cti1_b),
+ MSM_PIN_FUNCTION(qdss),
+ MSM_PIN_FUNCTION(qlink_enable),
+ MSM_PIN_FUNCTION(qlink_request),
+ MSM_PIN_FUNCTION(qua_mi2s),
+ MSM_PIN_FUNCTION(sd_card),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sdc40),
+ MSM_PIN_FUNCTION(sdc41),
+ MSM_PIN_FUNCTION(sdc42),
+ MSM_PIN_FUNCTION(sdc43),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(sp_cmu),
+ MSM_PIN_FUNCTION(spkr_i2s),
+ MSM_PIN_FUNCTION(ssbi1),
+ MSM_PIN_FUNCTION(ssc_irq),
+ MSM_PIN_FUNCTION(ter_mi2s),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(tsif0),
+ MSM_PIN_FUNCTION(tsif1),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_clkout),
+ MSM_PIN_FUNCTION(vsense_data0),
+ MSM_PIN_FUNCTION(vsense_data1),
+ MSM_PIN_FUNCTION(vsense_mode),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(wlan1_adc1),
+ MSM_PIN_FUNCTION(wlan2_adc0),
+ MSM_PIN_FUNCTION(wlan2_adc1),
};
static const struct msm_pingroup msm8998_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8x74.c b/drivers/pinctrl/qcom/pinctrl-msm8x74.c
index 3d193acee6a3..d5fe62992849 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8x74.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8x74.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -325,27 +324,20 @@ static const unsigned int sdc2_data_pins[] = { 151 };
static const unsigned int hsic_strobe_pins[] = { 152 };
static const unsigned int hsic_data_pins[] = { 153 };
-#define FUNCTION(fname) \
- [MSM_MUX_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
- MSM_MUX_gpio, \
- MSM_MUX_##f1, \
- MSM_MUX_##f2, \
- MSM_MUX_##f3, \
- MSM_MUX_##f4, \
- MSM_MUX_##f5, \
- MSM_MUX_##f6, \
- MSM_MUX_##f7 \
+ msm_mux_gpio, \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7 \
}, \
.nfuncs = 8, \
.ctl_reg = 0x1000 + 0x10 * id, \
@@ -371,9 +363,9 @@ static const unsigned int hsic_data_pins[] = { 153 };
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -397,12 +389,12 @@ static const unsigned int hsic_data_pins[] = { 153 };
#define HSIC_PINGROUP(pg_name, ctl) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.funcs = (int[]){ \
- MSM_MUX_gpio, \
- MSM_MUX_hsic_ctl, \
+ msm_mux_gpio, \
+ msm_mux_hsic_ctl, \
}, \
.nfuncs = 2, \
.ctl_reg = ctl, \
@@ -431,113 +423,113 @@ static const unsigned int hsic_data_pins[] = { 153 };
* the pingroup table below.
*/
enum msm8x74_functions {
- MSM_MUX_gpio,
- MSM_MUX_cci_i2c0,
- MSM_MUX_cci_i2c1,
- MSM_MUX_blsp_i2c1,
- MSM_MUX_blsp_i2c2,
- MSM_MUX_blsp_i2c3,
- MSM_MUX_blsp_i2c4,
- MSM_MUX_blsp_i2c5,
- MSM_MUX_blsp_i2c6,
- MSM_MUX_blsp_i2c7,
- MSM_MUX_blsp_i2c8,
- MSM_MUX_blsp_i2c9,
- MSM_MUX_blsp_i2c10,
- MSM_MUX_blsp_i2c11,
- MSM_MUX_blsp_i2c12,
- MSM_MUX_blsp_spi1,
- MSM_MUX_blsp_spi1_cs1,
- MSM_MUX_blsp_spi1_cs2,
- MSM_MUX_blsp_spi1_cs3,
- MSM_MUX_blsp_spi2,
- MSM_MUX_blsp_spi2_cs1,
- MSM_MUX_blsp_spi2_cs2,
- MSM_MUX_blsp_spi2_cs3,
- MSM_MUX_blsp_spi3,
- MSM_MUX_blsp_spi4,
- MSM_MUX_blsp_spi5,
- MSM_MUX_blsp_spi6,
- MSM_MUX_blsp_spi7,
- MSM_MUX_blsp_spi8,
- MSM_MUX_blsp_spi9,
- MSM_MUX_blsp_spi10,
- MSM_MUX_blsp_spi10_cs1,
- MSM_MUX_blsp_spi10_cs2,
- MSM_MUX_blsp_spi10_cs3,
- MSM_MUX_blsp_spi11,
- MSM_MUX_blsp_spi12,
- MSM_MUX_blsp_uart1,
- MSM_MUX_blsp_uart2,
- MSM_MUX_blsp_uart3,
- MSM_MUX_blsp_uart4,
- MSM_MUX_blsp_uart5,
- MSM_MUX_blsp_uart6,
- MSM_MUX_blsp_uart7,
- MSM_MUX_blsp_uart8,
- MSM_MUX_blsp_uart9,
- MSM_MUX_blsp_uart10,
- MSM_MUX_blsp_uart11,
- MSM_MUX_blsp_uart12,
- MSM_MUX_blsp_uim1,
- MSM_MUX_blsp_uim2,
- MSM_MUX_blsp_uim3,
- MSM_MUX_blsp_uim4,
- MSM_MUX_blsp_uim5,
- MSM_MUX_blsp_uim6,
- MSM_MUX_blsp_uim7,
- MSM_MUX_blsp_uim8,
- MSM_MUX_blsp_uim9,
- MSM_MUX_blsp_uim10,
- MSM_MUX_blsp_uim11,
- MSM_MUX_blsp_uim12,
- MSM_MUX_uim1,
- MSM_MUX_uim2,
- MSM_MUX_uim_batt_alarm,
- MSM_MUX_sdc3,
- MSM_MUX_sdc4,
- MSM_MUX_gcc_gp_clk1,
- MSM_MUX_gcc_gp_clk2,
- MSM_MUX_gcc_gp_clk3,
- MSM_MUX_qua_mi2s,
- MSM_MUX_pri_mi2s,
- MSM_MUX_spkr_mi2s,
- MSM_MUX_ter_mi2s,
- MSM_MUX_sec_mi2s,
- MSM_MUX_hdmi_cec,
- MSM_MUX_hdmi_ddc,
- MSM_MUX_hdmi_hpd,
- MSM_MUX_edp_hpd,
- MSM_MUX_mdp_vsync,
- MSM_MUX_cam_mclk0,
- MSM_MUX_cam_mclk1,
- MSM_MUX_cam_mclk2,
- MSM_MUX_cam_mclk3,
- MSM_MUX_cci_timer0,
- MSM_MUX_cci_timer1,
- MSM_MUX_cci_timer2,
- MSM_MUX_cci_timer3,
- MSM_MUX_cci_timer4,
- MSM_MUX_cci_async_in0,
- MSM_MUX_cci_async_in1,
- MSM_MUX_cci_async_in2,
- MSM_MUX_gp_pdm0,
- MSM_MUX_gp_pdm1,
- MSM_MUX_gp_pdm2,
- MSM_MUX_gp0_clk,
- MSM_MUX_gp1_clk,
- MSM_MUX_gp_mn,
- MSM_MUX_tsif1,
- MSM_MUX_tsif2,
- MSM_MUX_hsic,
- MSM_MUX_grfc,
- MSM_MUX_audio_ref_clk,
- MSM_MUX_bt,
- MSM_MUX_fm,
- MSM_MUX_wlan,
- MSM_MUX_slimbus,
- MSM_MUX_hsic_ctl,
- MSM_MUX_NA,
+ msm_mux_gpio,
+ msm_mux_cci_i2c0,
+ msm_mux_cci_i2c1,
+ msm_mux_blsp_i2c1,
+ msm_mux_blsp_i2c2,
+ msm_mux_blsp_i2c3,
+ msm_mux_blsp_i2c4,
+ msm_mux_blsp_i2c5,
+ msm_mux_blsp_i2c6,
+ msm_mux_blsp_i2c7,
+ msm_mux_blsp_i2c8,
+ msm_mux_blsp_i2c9,
+ msm_mux_blsp_i2c10,
+ msm_mux_blsp_i2c11,
+ msm_mux_blsp_i2c12,
+ msm_mux_blsp_spi1,
+ msm_mux_blsp_spi1_cs1,
+ msm_mux_blsp_spi1_cs2,
+ msm_mux_blsp_spi1_cs3,
+ msm_mux_blsp_spi2,
+ msm_mux_blsp_spi2_cs1,
+ msm_mux_blsp_spi2_cs2,
+ msm_mux_blsp_spi2_cs3,
+ msm_mux_blsp_spi3,
+ msm_mux_blsp_spi4,
+ msm_mux_blsp_spi5,
+ msm_mux_blsp_spi6,
+ msm_mux_blsp_spi7,
+ msm_mux_blsp_spi8,
+ msm_mux_blsp_spi9,
+ msm_mux_blsp_spi10,
+ msm_mux_blsp_spi10_cs1,
+ msm_mux_blsp_spi10_cs2,
+ msm_mux_blsp_spi10_cs3,
+ msm_mux_blsp_spi11,
+ msm_mux_blsp_spi12,
+ msm_mux_blsp_uart1,
+ msm_mux_blsp_uart2,
+ msm_mux_blsp_uart3,
+ msm_mux_blsp_uart4,
+ msm_mux_blsp_uart5,
+ msm_mux_blsp_uart6,
+ msm_mux_blsp_uart7,
+ msm_mux_blsp_uart8,
+ msm_mux_blsp_uart9,
+ msm_mux_blsp_uart10,
+ msm_mux_blsp_uart11,
+ msm_mux_blsp_uart12,
+ msm_mux_blsp_uim1,
+ msm_mux_blsp_uim2,
+ msm_mux_blsp_uim3,
+ msm_mux_blsp_uim4,
+ msm_mux_blsp_uim5,
+ msm_mux_blsp_uim6,
+ msm_mux_blsp_uim7,
+ msm_mux_blsp_uim8,
+ msm_mux_blsp_uim9,
+ msm_mux_blsp_uim10,
+ msm_mux_blsp_uim11,
+ msm_mux_blsp_uim12,
+ msm_mux_uim1,
+ msm_mux_uim2,
+ msm_mux_uim_batt_alarm,
+ msm_mux_sdc3,
+ msm_mux_sdc4,
+ msm_mux_gcc_gp_clk1,
+ msm_mux_gcc_gp_clk2,
+ msm_mux_gcc_gp_clk3,
+ msm_mux_qua_mi2s,
+ msm_mux_pri_mi2s,
+ msm_mux_spkr_mi2s,
+ msm_mux_ter_mi2s,
+ msm_mux_sec_mi2s,
+ msm_mux_hdmi_cec,
+ msm_mux_hdmi_ddc,
+ msm_mux_hdmi_hpd,
+ msm_mux_edp_hpd,
+ msm_mux_mdp_vsync,
+ msm_mux_cam_mclk0,
+ msm_mux_cam_mclk1,
+ msm_mux_cam_mclk2,
+ msm_mux_cam_mclk3,
+ msm_mux_cci_timer0,
+ msm_mux_cci_timer1,
+ msm_mux_cci_timer2,
+ msm_mux_cci_timer3,
+ msm_mux_cci_timer4,
+ msm_mux_cci_async_in0,
+ msm_mux_cci_async_in1,
+ msm_mux_cci_async_in2,
+ msm_mux_gp_pdm0,
+ msm_mux_gp_pdm1,
+ msm_mux_gp_pdm2,
+ msm_mux_gp0_clk,
+ msm_mux_gp1_clk,
+ msm_mux_gp_mn,
+ msm_mux_tsif1,
+ msm_mux_tsif2,
+ msm_mux_hsic,
+ msm_mux_grfc,
+ msm_mux_audio_ref_clk,
+ msm_mux_bt,
+ msm_mux_fm,
+ msm_mux_wlan,
+ msm_mux_slimbus,
+ msm_mux_hsic_ctl,
+ msm_mux_NA,
};
static const char * const gpio_groups[] = {
@@ -785,113 +777,113 @@ static const char * const wlan_groups[] = {
static const char * const slimbus_groups[] = { "gpio70", "gpio71" };
static const char * const hsic_ctl_groups[] = { "hsic_strobe", "hsic_data" };
-static const struct msm_function msm8x74_functions[] = {
- FUNCTION(gpio),
- FUNCTION(cci_i2c0),
- FUNCTION(cci_i2c1),
- FUNCTION(uim1),
- FUNCTION(uim2),
- FUNCTION(uim_batt_alarm),
- FUNCTION(blsp_uim1),
- FUNCTION(blsp_uim2),
- FUNCTION(blsp_uim3),
- FUNCTION(blsp_uim4),
- FUNCTION(blsp_uim5),
- FUNCTION(blsp_uim6),
- FUNCTION(blsp_uim7),
- FUNCTION(blsp_uim8),
- FUNCTION(blsp_uim9),
- FUNCTION(blsp_uim10),
- FUNCTION(blsp_uim11),
- FUNCTION(blsp_uim12),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_i2c5),
- FUNCTION(blsp_i2c6),
- FUNCTION(blsp_i2c7),
- FUNCTION(blsp_i2c8),
- FUNCTION(blsp_i2c9),
- FUNCTION(blsp_i2c10),
- FUNCTION(blsp_i2c11),
- FUNCTION(blsp_i2c12),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi1_cs1),
- FUNCTION(blsp_spi1_cs2),
- FUNCTION(blsp_spi1_cs3),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi2_cs1),
- FUNCTION(blsp_spi2_cs2),
- FUNCTION(blsp_spi2_cs3),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_spi5),
- FUNCTION(blsp_spi6),
- FUNCTION(blsp_spi7),
- FUNCTION(blsp_spi8),
- FUNCTION(blsp_spi9),
- FUNCTION(blsp_spi10),
- FUNCTION(blsp_spi10_cs1),
- FUNCTION(blsp_spi10_cs2),
- FUNCTION(blsp_spi10_cs3),
- FUNCTION(blsp_spi11),
- FUNCTION(blsp_spi12),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_uart3),
- FUNCTION(blsp_uart4),
- FUNCTION(blsp_uart5),
- FUNCTION(blsp_uart6),
- FUNCTION(blsp_uart7),
- FUNCTION(blsp_uart8),
- FUNCTION(blsp_uart9),
- FUNCTION(blsp_uart10),
- FUNCTION(blsp_uart11),
- FUNCTION(blsp_uart12),
- FUNCTION(sdc3),
- FUNCTION(sdc4),
- FUNCTION(gcc_gp_clk1),
- FUNCTION(gcc_gp_clk2),
- FUNCTION(gcc_gp_clk3),
- FUNCTION(qua_mi2s),
- FUNCTION(pri_mi2s),
- FUNCTION(spkr_mi2s),
- FUNCTION(ter_mi2s),
- FUNCTION(sec_mi2s),
- FUNCTION(mdp_vsync),
- FUNCTION(cam_mclk0),
- FUNCTION(cam_mclk1),
- FUNCTION(cam_mclk2),
- FUNCTION(cam_mclk3),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cci_async_in0),
- FUNCTION(cci_async_in1),
- FUNCTION(cci_async_in2),
- FUNCTION(hdmi_cec),
- FUNCTION(hdmi_ddc),
- FUNCTION(hdmi_hpd),
- FUNCTION(edp_hpd),
- FUNCTION(gp_pdm0),
- FUNCTION(gp_pdm1),
- FUNCTION(gp_pdm2),
- FUNCTION(gp0_clk),
- FUNCTION(gp1_clk),
- FUNCTION(gp_mn),
- FUNCTION(tsif1),
- FUNCTION(tsif2),
- FUNCTION(hsic),
- FUNCTION(grfc),
- FUNCTION(audio_ref_clk),
- FUNCTION(bt),
- FUNCTION(fm),
- FUNCTION(wlan),
- FUNCTION(slimbus),
- FUNCTION(hsic_ctl),
+static const struct pinfunction msm8x74_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(cci_i2c0),
+ MSM_PIN_FUNCTION(cci_i2c1),
+ MSM_PIN_FUNCTION(uim1),
+ MSM_PIN_FUNCTION(uim2),
+ MSM_PIN_FUNCTION(uim_batt_alarm),
+ MSM_PIN_FUNCTION(blsp_uim1),
+ MSM_PIN_FUNCTION(blsp_uim2),
+ MSM_PIN_FUNCTION(blsp_uim3),
+ MSM_PIN_FUNCTION(blsp_uim4),
+ MSM_PIN_FUNCTION(blsp_uim5),
+ MSM_PIN_FUNCTION(blsp_uim6),
+ MSM_PIN_FUNCTION(blsp_uim7),
+ MSM_PIN_FUNCTION(blsp_uim8),
+ MSM_PIN_FUNCTION(blsp_uim9),
+ MSM_PIN_FUNCTION(blsp_uim10),
+ MSM_PIN_FUNCTION(blsp_uim11),
+ MSM_PIN_FUNCTION(blsp_uim12),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_i2c5),
+ MSM_PIN_FUNCTION(blsp_i2c6),
+ MSM_PIN_FUNCTION(blsp_i2c7),
+ MSM_PIN_FUNCTION(blsp_i2c8),
+ MSM_PIN_FUNCTION(blsp_i2c9),
+ MSM_PIN_FUNCTION(blsp_i2c10),
+ MSM_PIN_FUNCTION(blsp_i2c11),
+ MSM_PIN_FUNCTION(blsp_i2c12),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(blsp_spi1_cs1),
+ MSM_PIN_FUNCTION(blsp_spi1_cs2),
+ MSM_PIN_FUNCTION(blsp_spi1_cs3),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_spi2_cs1),
+ MSM_PIN_FUNCTION(blsp_spi2_cs2),
+ MSM_PIN_FUNCTION(blsp_spi2_cs3),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(blsp_spi5),
+ MSM_PIN_FUNCTION(blsp_spi6),
+ MSM_PIN_FUNCTION(blsp_spi7),
+ MSM_PIN_FUNCTION(blsp_spi8),
+ MSM_PIN_FUNCTION(blsp_spi9),
+ MSM_PIN_FUNCTION(blsp_spi10),
+ MSM_PIN_FUNCTION(blsp_spi10_cs1),
+ MSM_PIN_FUNCTION(blsp_spi10_cs2),
+ MSM_PIN_FUNCTION(blsp_spi10_cs3),
+ MSM_PIN_FUNCTION(blsp_spi11),
+ MSM_PIN_FUNCTION(blsp_spi12),
+ MSM_PIN_FUNCTION(blsp_uart1),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(blsp_uart3),
+ MSM_PIN_FUNCTION(blsp_uart4),
+ MSM_PIN_FUNCTION(blsp_uart5),
+ MSM_PIN_FUNCTION(blsp_uart6),
+ MSM_PIN_FUNCTION(blsp_uart7),
+ MSM_PIN_FUNCTION(blsp_uart8),
+ MSM_PIN_FUNCTION(blsp_uart9),
+ MSM_PIN_FUNCTION(blsp_uart10),
+ MSM_PIN_FUNCTION(blsp_uart11),
+ MSM_PIN_FUNCTION(blsp_uart12),
+ MSM_PIN_FUNCTION(sdc3),
+ MSM_PIN_FUNCTION(sdc4),
+ MSM_PIN_FUNCTION(gcc_gp_clk1),
+ MSM_PIN_FUNCTION(gcc_gp_clk2),
+ MSM_PIN_FUNCTION(gcc_gp_clk3),
+ MSM_PIN_FUNCTION(qua_mi2s),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(spkr_mi2s),
+ MSM_PIN_FUNCTION(ter_mi2s),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(cam_mclk0),
+ MSM_PIN_FUNCTION(cam_mclk1),
+ MSM_PIN_FUNCTION(cam_mclk2),
+ MSM_PIN_FUNCTION(cam_mclk3),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cci_async_in0),
+ MSM_PIN_FUNCTION(cci_async_in1),
+ MSM_PIN_FUNCTION(cci_async_in2),
+ MSM_PIN_FUNCTION(hdmi_cec),
+ MSM_PIN_FUNCTION(hdmi_ddc),
+ MSM_PIN_FUNCTION(hdmi_hpd),
+ MSM_PIN_FUNCTION(edp_hpd),
+ MSM_PIN_FUNCTION(gp_pdm0),
+ MSM_PIN_FUNCTION(gp_pdm1),
+ MSM_PIN_FUNCTION(gp_pdm2),
+ MSM_PIN_FUNCTION(gp0_clk),
+ MSM_PIN_FUNCTION(gp1_clk),
+ MSM_PIN_FUNCTION(gp_mn),
+ MSM_PIN_FUNCTION(tsif1),
+ MSM_PIN_FUNCTION(tsif2),
+ MSM_PIN_FUNCTION(hsic),
+ MSM_PIN_FUNCTION(grfc),
+ MSM_PIN_FUNCTION(audio_ref_clk),
+ MSM_PIN_FUNCTION(bt),
+ MSM_PIN_FUNCTION(fm),
+ MSM_PIN_FUNCTION(wlan),
+ MSM_PIN_FUNCTION(slimbus),
+ MSM_PIN_FUNCTION(hsic_ctl),
};
static const struct msm_pingroup msm8x74_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-qcm2290.c b/drivers/pinctrl/qcom/pinctrl-qcm2290.c
index aa9325f333fb..ba699eac9ee8 100644
--- a/drivers/pinctrl/qcom/pinctrl-qcm2290.c
+++ b/drivers/pinctrl/qcom/pinctrl-qcm2290.c
@@ -6,24 +6,16 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -60,9 +52,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -85,9 +77,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -837,108 +829,108 @@ static const char * const pwm_9_groups[] = {
"gpio115",
};
-static const struct msm_function qcm2290_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(agera_pll),
- FUNCTION(atest),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(char_exec),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dac_calib),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gpio),
- FUNCTION(gp_pdm0),
- FUNCTION(gp_pdm1),
- FUNCTION(gp_pdm2),
- FUNCTION(gsm0_tx),
- FUNCTION(gsm1_tx),
- FUNCTION(jitter_bist),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync_out_0),
- FUNCTION(mdp_vsync_out_1),
- FUNCTION(mpm_pwr),
- FUNCTION(mss_lte),
- FUNCTION(m_voc),
- FUNCTION(nav_gpio),
- FUNCTION(pa_indicator),
- FUNCTION(pbs0),
- FUNCTION(pbs1),
- FUNCTION(pbs2),
- FUNCTION(pbs3),
- FUNCTION(pbs4),
- FUNCTION(pbs5),
- FUNCTION(pbs6),
- FUNCTION(pbs7),
- FUNCTION(pbs8),
- FUNCTION(pbs9),
- FUNCTION(pbs10),
- FUNCTION(pbs11),
- FUNCTION(pbs12),
- FUNCTION(pbs13),
- FUNCTION(pbs14),
- FUNCTION(pbs15),
- FUNCTION(pbs_out),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_reset),
- FUNCTION(prng_rosc),
- FUNCTION(pwm_0),
- FUNCTION(pwm_1),
- FUNCTION(pwm_2),
- FUNCTION(pwm_3),
- FUNCTION(pwm_4),
- FUNCTION(pwm_5),
- FUNCTION(pwm_6),
- FUNCTION(pwm_7),
- FUNCTION(pwm_8),
- FUNCTION(pwm_9),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qup0),
- FUNCTION(qup1),
- FUNCTION(qup2),
- FUNCTION(qup3),
- FUNCTION(qup4),
- FUNCTION(qup5),
- FUNCTION(sdc1_tb),
- FUNCTION(sdc2_tb),
- FUNCTION(sd_write),
- FUNCTION(ssbi_wtr1),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tsense_pwm),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(usb_phy),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
- FUNCTION(wlan1_adc0),
- FUNCTION(wlan1_adc1),
+static const struct pinfunction qcm2290_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(atest),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(char_exec),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dac_calib),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gp_pdm0),
+ MSM_PIN_FUNCTION(gp_pdm1),
+ MSM_PIN_FUNCTION(gp_pdm2),
+ MSM_PIN_FUNCTION(gsm0_tx),
+ MSM_PIN_FUNCTION(gsm1_tx),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync_out_0),
+ MSM_PIN_FUNCTION(mdp_vsync_out_1),
+ MSM_PIN_FUNCTION(mpm_pwr),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(nav_gpio),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pbs0),
+ MSM_PIN_FUNCTION(pbs1),
+ MSM_PIN_FUNCTION(pbs2),
+ MSM_PIN_FUNCTION(pbs3),
+ MSM_PIN_FUNCTION(pbs4),
+ MSM_PIN_FUNCTION(pbs5),
+ MSM_PIN_FUNCTION(pbs6),
+ MSM_PIN_FUNCTION(pbs7),
+ MSM_PIN_FUNCTION(pbs8),
+ MSM_PIN_FUNCTION(pbs9),
+ MSM_PIN_FUNCTION(pbs10),
+ MSM_PIN_FUNCTION(pbs11),
+ MSM_PIN_FUNCTION(pbs12),
+ MSM_PIN_FUNCTION(pbs13),
+ MSM_PIN_FUNCTION(pbs14),
+ MSM_PIN_FUNCTION(pbs15),
+ MSM_PIN_FUNCTION(pbs_out),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(pwm_0),
+ MSM_PIN_FUNCTION(pwm_1),
+ MSM_PIN_FUNCTION(pwm_2),
+ MSM_PIN_FUNCTION(pwm_3),
+ MSM_PIN_FUNCTION(pwm_4),
+ MSM_PIN_FUNCTION(pwm_5),
+ MSM_PIN_FUNCTION(pwm_6),
+ MSM_PIN_FUNCTION(pwm_7),
+ MSM_PIN_FUNCTION(pwm_8),
+ MSM_PIN_FUNCTION(pwm_9),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qup0),
+ MSM_PIN_FUNCTION(qup1),
+ MSM_PIN_FUNCTION(qup2),
+ MSM_PIN_FUNCTION(qup3),
+ MSM_PIN_FUNCTION(qup4),
+ MSM_PIN_FUNCTION(qup5),
+ MSM_PIN_FUNCTION(sdc1_tb),
+ MSM_PIN_FUNCTION(sdc2_tb),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(ssbi_wtr1),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tsense_pwm),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(wlan1_adc1),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c
index 1c6ba978c69f..ae7224012f8a 100644
--- a/drivers/pinctrl/qcom/pinctrl-qcs404.c
+++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -22,18 +21,11 @@ enum {
EAST
};
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -71,9 +63,9 @@ enum {
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -1303,190 +1295,190 @@ static const char * const i2s_3_ws_a_groups[] = {
"gpio105",
};
-static const struct msm_function qcs404_functions[] = {
- FUNCTION(gpio),
- FUNCTION(hdmi_tx),
- FUNCTION(hdmi_ddc),
- FUNCTION(blsp_uart_tx_a2),
- FUNCTION(blsp_spi2),
- FUNCTION(m_voc),
- FUNCTION(qdss_cti_trig_in_a0),
- FUNCTION(blsp_uart_rx_a2),
- FUNCTION(qdss_tracectl_a),
- FUNCTION(blsp_uart2),
- FUNCTION(aud_cdc),
- FUNCTION(blsp_i2c_sda_a2),
- FUNCTION(qdss_tracedata_a),
- FUNCTION(blsp_i2c_scl_a2),
- FUNCTION(qdss_tracectl_b),
- FUNCTION(qdss_cti_trig_in_b0),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_spi_mosi_a1),
- FUNCTION(blsp_spi_miso_a1),
- FUNCTION(qdss_tracedata_b),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_spi_cs_n_a1),
- FUNCTION(gcc_plltest),
- FUNCTION(blsp_spi_clk_a1),
- FUNCTION(rgb_data0),
- FUNCTION(blsp_uart5),
- FUNCTION(blsp_spi5),
- FUNCTION(adsp_ext),
- FUNCTION(rgb_data1),
- FUNCTION(prng_rosc),
- FUNCTION(rgb_data2),
- FUNCTION(blsp_i2c5),
- FUNCTION(gcc_gp1_clk_b),
- FUNCTION(rgb_data3),
- FUNCTION(gcc_gp2_clk_b),
- FUNCTION(blsp_spi0),
- FUNCTION(blsp_uart0),
- FUNCTION(gcc_gp3_clk_b),
- FUNCTION(blsp_i2c0),
- FUNCTION(qdss_traceclk_b),
- FUNCTION(pcie_clk),
- FUNCTION(nfc_irq),
- FUNCTION(blsp_spi4),
- FUNCTION(nfc_dwl),
- FUNCTION(audio_ts),
- FUNCTION(rgb_data4),
- FUNCTION(spi_lcd),
- FUNCTION(blsp_uart_tx_b2),
- FUNCTION(gcc_gp3_clk_a),
- FUNCTION(rgb_data5),
- FUNCTION(blsp_uart_rx_b2),
- FUNCTION(blsp_i2c_sda_b2),
- FUNCTION(blsp_i2c_scl_b2),
- FUNCTION(pwm_led11),
- FUNCTION(i2s_3_data0_a),
- FUNCTION(ebi2_lcd),
- FUNCTION(i2s_3_data1_a),
- FUNCTION(i2s_3_data2_a),
- FUNCTION(atest_char),
- FUNCTION(pwm_led3),
- FUNCTION(i2s_3_data3_a),
- FUNCTION(pwm_led4),
- FUNCTION(i2s_4),
- FUNCTION(ebi2_a),
- FUNCTION(dsd_clk_b),
- FUNCTION(pwm_led5),
- FUNCTION(pwm_led6),
- FUNCTION(pwm_led7),
- FUNCTION(pwm_led8),
- FUNCTION(pwm_led24),
- FUNCTION(spkr_dac0),
- FUNCTION(blsp_i2c4),
- FUNCTION(pwm_led9),
- FUNCTION(pwm_led10),
- FUNCTION(spdifrx_opt),
- FUNCTION(pwm_led12),
- FUNCTION(pwm_led13),
- FUNCTION(pwm_led14),
- FUNCTION(wlan1_adc1),
- FUNCTION(rgb_data_b0),
- FUNCTION(pwm_led15),
- FUNCTION(blsp_spi_mosi_b1),
- FUNCTION(wlan1_adc0),
- FUNCTION(rgb_data_b1),
- FUNCTION(pwm_led16),
- FUNCTION(blsp_spi_miso_b1),
- FUNCTION(qdss_cti_trig_out_b0),
- FUNCTION(wlan2_adc1),
- FUNCTION(rgb_data_b2),
- FUNCTION(pwm_led17),
- FUNCTION(blsp_spi_cs_n_b1),
- FUNCTION(wlan2_adc0),
- FUNCTION(rgb_data_b3),
- FUNCTION(pwm_led18),
- FUNCTION(blsp_spi_clk_b1),
- FUNCTION(rgb_data_b4),
- FUNCTION(pwm_led19),
- FUNCTION(ext_mclk1_b),
- FUNCTION(qdss_traceclk_a),
- FUNCTION(rgb_data_b5),
- FUNCTION(pwm_led20),
- FUNCTION(atest_char3),
- FUNCTION(i2s_3_sck_b),
- FUNCTION(ldo_update),
- FUNCTION(bimc_dte0),
- FUNCTION(rgb_hsync),
- FUNCTION(pwm_led21),
- FUNCTION(i2s_3_ws_b),
- FUNCTION(dbg_out),
- FUNCTION(rgb_vsync),
- FUNCTION(i2s_3_data0_b),
- FUNCTION(ldo_en),
- FUNCTION(hdmi_dtest),
- FUNCTION(rgb_de),
- FUNCTION(i2s_3_data1_b),
- FUNCTION(hdmi_lbk9),
- FUNCTION(rgb_clk),
- FUNCTION(atest_char1),
- FUNCTION(i2s_3_data2_b),
- FUNCTION(ebi_cdc),
- FUNCTION(hdmi_lbk8),
- FUNCTION(rgb_mdp),
- FUNCTION(atest_char0),
- FUNCTION(i2s_3_data3_b),
- FUNCTION(hdmi_lbk7),
- FUNCTION(rgb_data_b6),
- FUNCTION(rgb_data_b7),
- FUNCTION(hdmi_lbk6),
- FUNCTION(rgmii_int),
- FUNCTION(cri_trng1),
- FUNCTION(rgmii_wol),
- FUNCTION(cri_trng0),
- FUNCTION(gcc_tlmm),
- FUNCTION(rgmii_ck),
- FUNCTION(rgmii_tx),
- FUNCTION(hdmi_lbk5),
- FUNCTION(hdmi_pixel),
- FUNCTION(hdmi_rcv),
- FUNCTION(hdmi_lbk4),
- FUNCTION(rgmii_ctl),
- FUNCTION(ext_lpass),
- FUNCTION(rgmii_rx),
- FUNCTION(cri_trng),
- FUNCTION(hdmi_lbk3),
- FUNCTION(hdmi_lbk2),
- FUNCTION(qdss_cti_trig_out_b1),
- FUNCTION(rgmii_mdio),
- FUNCTION(hdmi_lbk1),
- FUNCTION(rgmii_mdc),
- FUNCTION(hdmi_lbk0),
- FUNCTION(ir_in),
- FUNCTION(wsa_en),
- FUNCTION(rgb_data6),
- FUNCTION(rgb_data7),
- FUNCTION(atest_char2),
- FUNCTION(ebi_ch0),
- FUNCTION(blsp_uart3),
- FUNCTION(blsp_spi3),
- FUNCTION(sd_write),
- FUNCTION(blsp_i2c3),
- FUNCTION(gcc_gp1_clk_a),
- FUNCTION(qdss_cti_trig_in_b1),
- FUNCTION(gcc_gp2_clk_a),
- FUNCTION(ext_mclk0),
- FUNCTION(mclk_in1),
- FUNCTION(i2s_1),
- FUNCTION(dsd_clk_a),
- FUNCTION(qdss_cti_trig_in_a1),
- FUNCTION(rgmi_dll1),
- FUNCTION(pwm_led22),
- FUNCTION(pwm_led23),
- FUNCTION(qdss_cti_trig_out_a0),
- FUNCTION(rgmi_dll2),
- FUNCTION(pwm_led1),
- FUNCTION(qdss_cti_trig_out_a1),
- FUNCTION(pwm_led2),
- FUNCTION(i2s_2),
- FUNCTION(pll_bist),
- FUNCTION(ext_mclk1_a),
- FUNCTION(mclk_in2),
- FUNCTION(bimc_dte1),
- FUNCTION(i2s_3_sck_a),
- FUNCTION(i2s_3_ws_a),
+static const struct pinfunction qcs404_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(hdmi_tx),
+ MSM_PIN_FUNCTION(hdmi_ddc),
+ MSM_PIN_FUNCTION(blsp_uart_tx_a2),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a0),
+ MSM_PIN_FUNCTION(blsp_uart_rx_a2),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(aud_cdc),
+ MSM_PIN_FUNCTION(blsp_i2c_sda_a2),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(blsp_i2c_scl_a2),
+ MSM_PIN_FUNCTION(qdss_tracectl_b),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b0),
+ MSM_PIN_FUNCTION(blsp_uart1),
+ MSM_PIN_FUNCTION(blsp_spi_mosi_a1),
+ MSM_PIN_FUNCTION(blsp_spi_miso_a1),
+ MSM_PIN_FUNCTION(qdss_tracedata_b),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_spi_cs_n_a1),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(blsp_spi_clk_a1),
+ MSM_PIN_FUNCTION(rgb_data0),
+ MSM_PIN_FUNCTION(blsp_uart5),
+ MSM_PIN_FUNCTION(blsp_spi5),
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(rgb_data1),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(rgb_data2),
+ MSM_PIN_FUNCTION(blsp_i2c5),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_b),
+ MSM_PIN_FUNCTION(rgb_data3),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_b),
+ MSM_PIN_FUNCTION(blsp_spi0),
+ MSM_PIN_FUNCTION(blsp_uart0),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_b),
+ MSM_PIN_FUNCTION(blsp_i2c0),
+ MSM_PIN_FUNCTION(qdss_traceclk_b),
+ MSM_PIN_FUNCTION(pcie_clk),
+ MSM_PIN_FUNCTION(nfc_irq),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(nfc_dwl),
+ MSM_PIN_FUNCTION(audio_ts),
+ MSM_PIN_FUNCTION(rgb_data4),
+ MSM_PIN_FUNCTION(spi_lcd),
+ MSM_PIN_FUNCTION(blsp_uart_tx_b2),
+ MSM_PIN_FUNCTION(gcc_gp3_clk_a),
+ MSM_PIN_FUNCTION(rgb_data5),
+ MSM_PIN_FUNCTION(blsp_uart_rx_b2),
+ MSM_PIN_FUNCTION(blsp_i2c_sda_b2),
+ MSM_PIN_FUNCTION(blsp_i2c_scl_b2),
+ MSM_PIN_FUNCTION(pwm_led11),
+ MSM_PIN_FUNCTION(i2s_3_data0_a),
+ MSM_PIN_FUNCTION(ebi2_lcd),
+ MSM_PIN_FUNCTION(i2s_3_data1_a),
+ MSM_PIN_FUNCTION(i2s_3_data2_a),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(pwm_led3),
+ MSM_PIN_FUNCTION(i2s_3_data3_a),
+ MSM_PIN_FUNCTION(pwm_led4),
+ MSM_PIN_FUNCTION(i2s_4),
+ MSM_PIN_FUNCTION(ebi2_a),
+ MSM_PIN_FUNCTION(dsd_clk_b),
+ MSM_PIN_FUNCTION(pwm_led5),
+ MSM_PIN_FUNCTION(pwm_led6),
+ MSM_PIN_FUNCTION(pwm_led7),
+ MSM_PIN_FUNCTION(pwm_led8),
+ MSM_PIN_FUNCTION(pwm_led24),
+ MSM_PIN_FUNCTION(spkr_dac0),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(pwm_led9),
+ MSM_PIN_FUNCTION(pwm_led10),
+ MSM_PIN_FUNCTION(spdifrx_opt),
+ MSM_PIN_FUNCTION(pwm_led12),
+ MSM_PIN_FUNCTION(pwm_led13),
+ MSM_PIN_FUNCTION(pwm_led14),
+ MSM_PIN_FUNCTION(wlan1_adc1),
+ MSM_PIN_FUNCTION(rgb_data_b0),
+ MSM_PIN_FUNCTION(pwm_led15),
+ MSM_PIN_FUNCTION(blsp_spi_mosi_b1),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(rgb_data_b1),
+ MSM_PIN_FUNCTION(pwm_led16),
+ MSM_PIN_FUNCTION(blsp_spi_miso_b1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b0),
+ MSM_PIN_FUNCTION(wlan2_adc1),
+ MSM_PIN_FUNCTION(rgb_data_b2),
+ MSM_PIN_FUNCTION(pwm_led17),
+ MSM_PIN_FUNCTION(blsp_spi_cs_n_b1),
+ MSM_PIN_FUNCTION(wlan2_adc0),
+ MSM_PIN_FUNCTION(rgb_data_b3),
+ MSM_PIN_FUNCTION(pwm_led18),
+ MSM_PIN_FUNCTION(blsp_spi_clk_b1),
+ MSM_PIN_FUNCTION(rgb_data_b4),
+ MSM_PIN_FUNCTION(pwm_led19),
+ MSM_PIN_FUNCTION(ext_mclk1_b),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(rgb_data_b5),
+ MSM_PIN_FUNCTION(pwm_led20),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(i2s_3_sck_b),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(bimc_dte0),
+ MSM_PIN_FUNCTION(rgb_hsync),
+ MSM_PIN_FUNCTION(pwm_led21),
+ MSM_PIN_FUNCTION(i2s_3_ws_b),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(rgb_vsync),
+ MSM_PIN_FUNCTION(i2s_3_data0_b),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(hdmi_dtest),
+ MSM_PIN_FUNCTION(rgb_de),
+ MSM_PIN_FUNCTION(i2s_3_data1_b),
+ MSM_PIN_FUNCTION(hdmi_lbk9),
+ MSM_PIN_FUNCTION(rgb_clk),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(i2s_3_data2_b),
+ MSM_PIN_FUNCTION(ebi_cdc),
+ MSM_PIN_FUNCTION(hdmi_lbk8),
+ MSM_PIN_FUNCTION(rgb_mdp),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(i2s_3_data3_b),
+ MSM_PIN_FUNCTION(hdmi_lbk7),
+ MSM_PIN_FUNCTION(rgb_data_b6),
+ MSM_PIN_FUNCTION(rgb_data_b7),
+ MSM_PIN_FUNCTION(hdmi_lbk6),
+ MSM_PIN_FUNCTION(rgmii_int),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(rgmii_wol),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(gcc_tlmm),
+ MSM_PIN_FUNCTION(rgmii_ck),
+ MSM_PIN_FUNCTION(rgmii_tx),
+ MSM_PIN_FUNCTION(hdmi_lbk5),
+ MSM_PIN_FUNCTION(hdmi_pixel),
+ MSM_PIN_FUNCTION(hdmi_rcv),
+ MSM_PIN_FUNCTION(hdmi_lbk4),
+ MSM_PIN_FUNCTION(rgmii_ctl),
+ MSM_PIN_FUNCTION(ext_lpass),
+ MSM_PIN_FUNCTION(rgmii_rx),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(hdmi_lbk3),
+ MSM_PIN_FUNCTION(hdmi_lbk2),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b1),
+ MSM_PIN_FUNCTION(rgmii_mdio),
+ MSM_PIN_FUNCTION(hdmi_lbk1),
+ MSM_PIN_FUNCTION(rgmii_mdc),
+ MSM_PIN_FUNCTION(hdmi_lbk0),
+ MSM_PIN_FUNCTION(ir_in),
+ MSM_PIN_FUNCTION(wsa_en),
+ MSM_PIN_FUNCTION(rgb_data6),
+ MSM_PIN_FUNCTION(rgb_data7),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(ebi_ch0),
+ MSM_PIN_FUNCTION(blsp_uart3),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(gcc_gp1_clk_a),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b1),
+ MSM_PIN_FUNCTION(gcc_gp2_clk_a),
+ MSM_PIN_FUNCTION(ext_mclk0),
+ MSM_PIN_FUNCTION(mclk_in1),
+ MSM_PIN_FUNCTION(i2s_1),
+ MSM_PIN_FUNCTION(dsd_clk_a),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a1),
+ MSM_PIN_FUNCTION(rgmi_dll1),
+ MSM_PIN_FUNCTION(pwm_led22),
+ MSM_PIN_FUNCTION(pwm_led23),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a0),
+ MSM_PIN_FUNCTION(rgmi_dll2),
+ MSM_PIN_FUNCTION(pwm_led1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a1),
+ MSM_PIN_FUNCTION(pwm_led2),
+ MSM_PIN_FUNCTION(i2s_2),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(ext_mclk1_a),
+ MSM_PIN_FUNCTION(mclk_in2),
+ MSM_PIN_FUNCTION(bimc_dte1),
+ MSM_PIN_FUNCTION(i2s_3_sck_a),
+ MSM_PIN_FUNCTION(i2s_3_ws_a),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
diff --git a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c
index 43bd15f16377..b5808fcfb13c 100644
--- a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c
+++ b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c
@@ -90,17 +90,17 @@ static int qdf2xxx_pinctrl_probe(struct platform_device *pdev)
*/
for (i = 0; i < num_gpios; i++) {
pins[i].number = i;
- groups[i].pins = &pins[i].number;
+ groups[i].grp.pins = &pins[i].number;
}
/* Populate the entries that are meant to be exposed as GPIOs. */
for (i = 0; i < avail_gpios; i++) {
unsigned int gpio = gpios[i];
- groups[gpio].npins = 1;
+ groups[gpio].grp.npins = 1;
snprintf(names[i], NAME_SIZE, "gpio%u", gpio);
pins[gpio].name = names[i];
- groups[gpio].name = names[i];
+ groups[gpio].grp.name = names[i];
groups[gpio].ctl_reg = 0x10000 * gpio;
groups[gpio].io_reg = 0x04 + 0x10000 * gpio;
@@ -142,7 +142,7 @@ MODULE_DEVICE_TABLE(acpi, qdf2xxx_acpi_ids);
static struct platform_driver qdf2xxx_pinctrl_driver = {
.driver = {
.name = "qdf2xxx-pinctrl",
- .acpi_match_table = ACPI_PTR(qdf2xxx_acpi_ids),
+ .acpi_match_table = qdf2xxx_acpi_ids,
},
.probe = qdf2xxx_pinctrl_probe,
.remove = msm_pinctrl_remove,
diff --git a/drivers/pinctrl/qcom/pinctrl-qdu1000.c b/drivers/pinctrl/qcom/pinctrl-qdu1000.c
index b1d7674a2bec..47bc529ef550 100644
--- a/drivers/pinctrl/qcom/pinctrl-qdu1000.c
+++ b/drivers/pinctrl/qcom/pinctrl-qdu1000.c
@@ -7,24 +7,17 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_BASE 0x100000
#define REG_SIZE 0x1000
+
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -61,9 +54,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = REG_BASE + ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -86,9 +79,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -910,117 +903,117 @@ static const char * const vsense_trigger_groups[] = {
"gpio135",
};
-static const struct msm_function qdu1000_functions[] = {
- FUNCTION(gpio),
- FUNCTION(cmo_pri),
- FUNCTION(si5518_int),
- FUNCTION(atest_char),
- FUNCTION(atest_usb),
- FUNCTION(char_exec),
- FUNCTION(cmu_rng),
- FUNCTION(dbg_out_clk),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(ddr_pxi4),
- FUNCTION(ddr_pxi5),
- FUNCTION(ddr_pxi6),
- FUNCTION(ddr_pxi7),
- FUNCTION(eth012_int_n),
- FUNCTION(eth345_int_n),
- FUNCTION(eth6_int_n),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gps_pps_in),
- FUNCTION(hardsync_pps_in),
- FUNCTION(intr_c),
- FUNCTION(jitter_bist_ref),
- FUNCTION(pcie_clkreqn),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_clk),
- FUNCTION(prng_rosc),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qlink0_enable),
- FUNCTION(qlink0_request),
- FUNCTION(qlink0_wmss),
- FUNCTION(qlink1_enable),
- FUNCTION(qlink1_request),
- FUNCTION(qlink1_wmss),
- FUNCTION(qlink2_enable),
- FUNCTION(qlink2_request),
- FUNCTION(qlink2_wmss),
- FUNCTION(qlink3_enable),
- FUNCTION(qlink3_request),
- FUNCTION(qlink3_wmss),
- FUNCTION(qlink4_enable),
- FUNCTION(qlink4_request),
- FUNCTION(qlink4_wmss),
- FUNCTION(qlink5_enable),
- FUNCTION(qlink5_request),
- FUNCTION(qlink5_wmss),
- FUNCTION(qlink6_enable),
- FUNCTION(qlink6_request),
- FUNCTION(qlink6_wmss),
- FUNCTION(qlink7_enable),
- FUNCTION(qlink7_request),
- FUNCTION(qlink7_wmss),
- FUNCTION(qspi0),
- FUNCTION(qspi1),
- FUNCTION(qspi2),
- FUNCTION(qspi3),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(qup00),
- FUNCTION(qup01),
- FUNCTION(qup02),
- FUNCTION(qup03),
- FUNCTION(qup04),
- FUNCTION(qup05),
- FUNCTION(qup06),
- FUNCTION(qup07),
- FUNCTION(qup08),
- FUNCTION(qup10),
- FUNCTION(qup11),
- FUNCTION(qup12),
- FUNCTION(qup13),
- FUNCTION(qup14),
- FUNCTION(qup15),
- FUNCTION(qup16),
- FUNCTION(qup17),
- FUNCTION(qup20),
- FUNCTION(qup21),
- FUNCTION(qup22),
- FUNCTION(smb_alert),
- FUNCTION(smb_clk),
- FUNCTION(smb_dat),
- FUNCTION(tb_trig),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tgu_ch4),
- FUNCTION(tgu_ch5),
- FUNCTION(tgu_ch6),
- FUNCTION(tgu_ch7),
- FUNCTION(tmess_prng0),
- FUNCTION(tmess_prng1),
- FUNCTION(tmess_prng2),
- FUNCTION(tmess_prng3),
- FUNCTION(tod_pps_in),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(usb2phy_ac),
- FUNCTION(usb_con_det),
- FUNCTION(usb_dfp_en),
- FUNCTION(usb_phy),
- FUNCTION(vfr_0),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
+static const struct pinfunction qdu1000_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(cmo_pri),
+ MSM_PIN_FUNCTION(si5518_int),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_usb),
+ MSM_PIN_FUNCTION(char_exec),
+ MSM_PIN_FUNCTION(cmu_rng),
+ MSM_PIN_FUNCTION(dbg_out_clk),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(ddr_pxi4),
+ MSM_PIN_FUNCTION(ddr_pxi5),
+ MSM_PIN_FUNCTION(ddr_pxi6),
+ MSM_PIN_FUNCTION(ddr_pxi7),
+ MSM_PIN_FUNCTION(eth012_int_n),
+ MSM_PIN_FUNCTION(eth345_int_n),
+ MSM_PIN_FUNCTION(eth6_int_n),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gps_pps_in),
+ MSM_PIN_FUNCTION(hardsync_pps_in),
+ MSM_PIN_FUNCTION(intr_c),
+ MSM_PIN_FUNCTION(jitter_bist_ref),
+ MSM_PIN_FUNCTION(pcie_clkreqn),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_clk),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qlink0_enable),
+ MSM_PIN_FUNCTION(qlink0_request),
+ MSM_PIN_FUNCTION(qlink0_wmss),
+ MSM_PIN_FUNCTION(qlink1_enable),
+ MSM_PIN_FUNCTION(qlink1_request),
+ MSM_PIN_FUNCTION(qlink1_wmss),
+ MSM_PIN_FUNCTION(qlink2_enable),
+ MSM_PIN_FUNCTION(qlink2_request),
+ MSM_PIN_FUNCTION(qlink2_wmss),
+ MSM_PIN_FUNCTION(qlink3_enable),
+ MSM_PIN_FUNCTION(qlink3_request),
+ MSM_PIN_FUNCTION(qlink3_wmss),
+ MSM_PIN_FUNCTION(qlink4_enable),
+ MSM_PIN_FUNCTION(qlink4_request),
+ MSM_PIN_FUNCTION(qlink4_wmss),
+ MSM_PIN_FUNCTION(qlink5_enable),
+ MSM_PIN_FUNCTION(qlink5_request),
+ MSM_PIN_FUNCTION(qlink5_wmss),
+ MSM_PIN_FUNCTION(qlink6_enable),
+ MSM_PIN_FUNCTION(qlink6_request),
+ MSM_PIN_FUNCTION(qlink6_wmss),
+ MSM_PIN_FUNCTION(qlink7_enable),
+ MSM_PIN_FUNCTION(qlink7_request),
+ MSM_PIN_FUNCTION(qlink7_wmss),
+ MSM_PIN_FUNCTION(qspi0),
+ MSM_PIN_FUNCTION(qspi1),
+ MSM_PIN_FUNCTION(qspi2),
+ MSM_PIN_FUNCTION(qspi3),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qup00),
+ MSM_PIN_FUNCTION(qup01),
+ MSM_PIN_FUNCTION(qup02),
+ MSM_PIN_FUNCTION(qup03),
+ MSM_PIN_FUNCTION(qup04),
+ MSM_PIN_FUNCTION(qup05),
+ MSM_PIN_FUNCTION(qup06),
+ MSM_PIN_FUNCTION(qup07),
+ MSM_PIN_FUNCTION(qup08),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(qup15),
+ MSM_PIN_FUNCTION(qup16),
+ MSM_PIN_FUNCTION(qup17),
+ MSM_PIN_FUNCTION(qup20),
+ MSM_PIN_FUNCTION(qup21),
+ MSM_PIN_FUNCTION(qup22),
+ MSM_PIN_FUNCTION(smb_alert),
+ MSM_PIN_FUNCTION(smb_clk),
+ MSM_PIN_FUNCTION(smb_dat),
+ MSM_PIN_FUNCTION(tb_trig),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tgu_ch4),
+ MSM_PIN_FUNCTION(tgu_ch5),
+ MSM_PIN_FUNCTION(tgu_ch6),
+ MSM_PIN_FUNCTION(tgu_ch7),
+ MSM_PIN_FUNCTION(tmess_prng0),
+ MSM_PIN_FUNCTION(tmess_prng1),
+ MSM_PIN_FUNCTION(tmess_prng2),
+ MSM_PIN_FUNCTION(tmess_prng3),
+ MSM_PIN_FUNCTION(tod_pps_in),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(usb_con_det),
+ MSM_PIN_FUNCTION(usb_dfp_en),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_0),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
};
/*
diff --git a/drivers/pinctrl/qcom/pinctrl-sa8775p.c b/drivers/pinctrl/qcom/pinctrl-sa8775p.c
index 2ae7cdca65d3..8a5cd15512b9 100644
--- a/drivers/pinctrl/qcom/pinctrl-sa8775p.c
+++ b/drivers/pinctrl/qcom/pinctrl-sa8775p.c
@@ -7,24 +7,16 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_BASE 0x100000
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9)\
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -63,9 +55,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -88,9 +80,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -1179,147 +1171,147 @@ static const char * const vsense_trigger_groups[] = {
"gpio111",
};
-static const struct msm_function sa8775p_functions[] = {
- FUNCTION(gpio),
- FUNCTION(atest_char),
- FUNCTION(atest_usb2),
- FUNCTION(audio_ref),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cci_timer5),
- FUNCTION(cci_timer6),
- FUNCTION(cci_timer7),
- FUNCTION(cci_timer8),
- FUNCTION(cci_timer9),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(ddr_pxi4),
- FUNCTION(ddr_pxi5),
- FUNCTION(edp0_hot),
- FUNCTION(edp0_lcd),
- FUNCTION(edp1_hot),
- FUNCTION(edp1_lcd),
- FUNCTION(edp2_hot),
- FUNCTION(edp2_lcd),
- FUNCTION(edp3_hot),
- FUNCTION(edp3_lcd),
- FUNCTION(emac0_mcg0),
- FUNCTION(emac0_mcg1),
- FUNCTION(emac0_mcg2),
- FUNCTION(emac0_mcg3),
- FUNCTION(emac0_mdc),
- FUNCTION(emac0_mdio),
- FUNCTION(emac0_ptp_aux),
- FUNCTION(emac0_ptp_pps),
- FUNCTION(emac1_mcg0),
- FUNCTION(emac1_mcg1),
- FUNCTION(emac1_mcg2),
- FUNCTION(emac1_mcg3),
- FUNCTION(emac1_mdc),
- FUNCTION(emac1_mdio),
- FUNCTION(emac1_ptp_aux),
- FUNCTION(emac1_ptp_pps),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gcc_gp4),
- FUNCTION(gcc_gp5),
- FUNCTION(hs0_mi2s),
- FUNCTION(hs1_mi2s),
- FUNCTION(hs2_mi2s),
- FUNCTION(ibi_i3c),
- FUNCTION(jitter_bist),
- FUNCTION(mdp0_vsync0),
- FUNCTION(mdp0_vsync1),
- FUNCTION(mdp0_vsync2),
- FUNCTION(mdp0_vsync3),
- FUNCTION(mdp0_vsync4),
- FUNCTION(mdp0_vsync5),
- FUNCTION(mdp0_vsync6),
- FUNCTION(mdp0_vsync7),
- FUNCTION(mdp0_vsync8),
- FUNCTION(mdp1_vsync0),
- FUNCTION(mdp1_vsync1),
- FUNCTION(mdp1_vsync2),
- FUNCTION(mdp1_vsync3),
- FUNCTION(mdp1_vsync4),
- FUNCTION(mdp1_vsync5),
- FUNCTION(mdp1_vsync6),
- FUNCTION(mdp1_vsync7),
- FUNCTION(mdp1_vsync8),
- FUNCTION(mdp_vsync),
- FUNCTION(mi2s1_data0),
- FUNCTION(mi2s1_data1),
- FUNCTION(mi2s1_sck),
- FUNCTION(mi2s1_ws),
- FUNCTION(mi2s2_data0),
- FUNCTION(mi2s2_data1),
- FUNCTION(mi2s2_sck),
- FUNCTION(mi2s2_ws),
- FUNCTION(mi2s_mclk0),
- FUNCTION(mi2s_mclk1),
- FUNCTION(pcie0_clkreq),
- FUNCTION(pcie1_clkreq),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_clk),
- FUNCTION(prng_rosc0),
- FUNCTION(prng_rosc1),
- FUNCTION(prng_rosc2),
- FUNCTION(prng_rosc3),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qup0_se0),
- FUNCTION(qup0_se1),
- FUNCTION(qup0_se2),
- FUNCTION(qup0_se3),
- FUNCTION(qup0_se4),
- FUNCTION(qup0_se5),
- FUNCTION(qup1_se0),
- FUNCTION(qup1_se1),
- FUNCTION(qup1_se2),
- FUNCTION(qup1_se3),
- FUNCTION(qup1_se4),
- FUNCTION(qup1_se5),
- FUNCTION(qup1_se6),
- FUNCTION(qup2_se0),
- FUNCTION(qup2_se1),
- FUNCTION(qup2_se2),
- FUNCTION(qup2_se3),
- FUNCTION(qup2_se4),
- FUNCTION(qup2_se5),
- FUNCTION(qup2_se6),
- FUNCTION(qup3_se0),
- FUNCTION(sail_top),
- FUNCTION(sailss_emac0),
- FUNCTION(sailss_ospi),
- FUNCTION(sgmii_phy),
- FUNCTION(tb_trig),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tgu_ch4),
- FUNCTION(tgu_ch5),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(tsense_pwm3),
- FUNCTION(tsense_pwm4),
- FUNCTION(usb2phy_ac),
- FUNCTION(vsense_trigger),
+static const struct pinfunction sa8775p_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_usb2),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cci_timer5),
+ MSM_PIN_FUNCTION(cci_timer6),
+ MSM_PIN_FUNCTION(cci_timer7),
+ MSM_PIN_FUNCTION(cci_timer8),
+ MSM_PIN_FUNCTION(cci_timer9),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(ddr_pxi4),
+ MSM_PIN_FUNCTION(ddr_pxi5),
+ MSM_PIN_FUNCTION(edp0_hot),
+ MSM_PIN_FUNCTION(edp0_lcd),
+ MSM_PIN_FUNCTION(edp1_hot),
+ MSM_PIN_FUNCTION(edp1_lcd),
+ MSM_PIN_FUNCTION(edp2_hot),
+ MSM_PIN_FUNCTION(edp2_lcd),
+ MSM_PIN_FUNCTION(edp3_hot),
+ MSM_PIN_FUNCTION(edp3_lcd),
+ MSM_PIN_FUNCTION(emac0_mcg0),
+ MSM_PIN_FUNCTION(emac0_mcg1),
+ MSM_PIN_FUNCTION(emac0_mcg2),
+ MSM_PIN_FUNCTION(emac0_mcg3),
+ MSM_PIN_FUNCTION(emac0_mdc),
+ MSM_PIN_FUNCTION(emac0_mdio),
+ MSM_PIN_FUNCTION(emac0_ptp_aux),
+ MSM_PIN_FUNCTION(emac0_ptp_pps),
+ MSM_PIN_FUNCTION(emac1_mcg0),
+ MSM_PIN_FUNCTION(emac1_mcg1),
+ MSM_PIN_FUNCTION(emac1_mcg2),
+ MSM_PIN_FUNCTION(emac1_mcg3),
+ MSM_PIN_FUNCTION(emac1_mdc),
+ MSM_PIN_FUNCTION(emac1_mdio),
+ MSM_PIN_FUNCTION(emac1_ptp_aux),
+ MSM_PIN_FUNCTION(emac1_ptp_pps),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gcc_gp4),
+ MSM_PIN_FUNCTION(gcc_gp5),
+ MSM_PIN_FUNCTION(hs0_mi2s),
+ MSM_PIN_FUNCTION(hs1_mi2s),
+ MSM_PIN_FUNCTION(hs2_mi2s),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(mdp0_vsync0),
+ MSM_PIN_FUNCTION(mdp0_vsync1),
+ MSM_PIN_FUNCTION(mdp0_vsync2),
+ MSM_PIN_FUNCTION(mdp0_vsync3),
+ MSM_PIN_FUNCTION(mdp0_vsync4),
+ MSM_PIN_FUNCTION(mdp0_vsync5),
+ MSM_PIN_FUNCTION(mdp0_vsync6),
+ MSM_PIN_FUNCTION(mdp0_vsync7),
+ MSM_PIN_FUNCTION(mdp0_vsync8),
+ MSM_PIN_FUNCTION(mdp1_vsync0),
+ MSM_PIN_FUNCTION(mdp1_vsync1),
+ MSM_PIN_FUNCTION(mdp1_vsync2),
+ MSM_PIN_FUNCTION(mdp1_vsync3),
+ MSM_PIN_FUNCTION(mdp1_vsync4),
+ MSM_PIN_FUNCTION(mdp1_vsync5),
+ MSM_PIN_FUNCTION(mdp1_vsync6),
+ MSM_PIN_FUNCTION(mdp1_vsync7),
+ MSM_PIN_FUNCTION(mdp1_vsync8),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mi2s1_data0),
+ MSM_PIN_FUNCTION(mi2s1_data1),
+ MSM_PIN_FUNCTION(mi2s1_sck),
+ MSM_PIN_FUNCTION(mi2s1_ws),
+ MSM_PIN_FUNCTION(mi2s2_data0),
+ MSM_PIN_FUNCTION(mi2s2_data1),
+ MSM_PIN_FUNCTION(mi2s2_sck),
+ MSM_PIN_FUNCTION(mi2s2_ws),
+ MSM_PIN_FUNCTION(mi2s_mclk0),
+ MSM_PIN_FUNCTION(mi2s_mclk1),
+ MSM_PIN_FUNCTION(pcie0_clkreq),
+ MSM_PIN_FUNCTION(pcie1_clkreq),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_clk),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(prng_rosc2),
+ MSM_PIN_FUNCTION(prng_rosc3),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qup0_se0),
+ MSM_PIN_FUNCTION(qup0_se1),
+ MSM_PIN_FUNCTION(qup0_se2),
+ MSM_PIN_FUNCTION(qup0_se3),
+ MSM_PIN_FUNCTION(qup0_se4),
+ MSM_PIN_FUNCTION(qup0_se5),
+ MSM_PIN_FUNCTION(qup1_se0),
+ MSM_PIN_FUNCTION(qup1_se1),
+ MSM_PIN_FUNCTION(qup1_se2),
+ MSM_PIN_FUNCTION(qup1_se3),
+ MSM_PIN_FUNCTION(qup1_se4),
+ MSM_PIN_FUNCTION(qup1_se5),
+ MSM_PIN_FUNCTION(qup1_se6),
+ MSM_PIN_FUNCTION(qup2_se0),
+ MSM_PIN_FUNCTION(qup2_se1),
+ MSM_PIN_FUNCTION(qup2_se2),
+ MSM_PIN_FUNCTION(qup2_se3),
+ MSM_PIN_FUNCTION(qup2_se4),
+ MSM_PIN_FUNCTION(qup2_se5),
+ MSM_PIN_FUNCTION(qup2_se6),
+ MSM_PIN_FUNCTION(qup3_se0),
+ MSM_PIN_FUNCTION(sail_top),
+ MSM_PIN_FUNCTION(sailss_emac0),
+ MSM_PIN_FUNCTION(sailss_ospi),
+ MSM_PIN_FUNCTION(sgmii_phy),
+ MSM_PIN_FUNCTION(tb_trig),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tgu_ch4),
+ MSM_PIN_FUNCTION(tgu_ch5),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(tsense_pwm3),
+ MSM_PIN_FUNCTION(tsense_pwm4),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(vsense_trigger),
};
/*
@@ -1491,6 +1483,23 @@ static const struct msm_pingroup sa8775p_groups[] = {
[153] = SDC_QDSD_PINGROUP(sdc1_data, 0x199000, 9, 0),
};
+static const struct msm_gpio_wakeirq_map sa8775p_pdc_map[] = {
+ { 0, 169 }, { 1, 174 }, { 2, 170 }, { 3, 175 }, { 4, 171 }, { 5, 173 },
+ { 6, 172 }, { 7, 182 }, { 10, 220 }, { 11, 213 }, { 12, 221 },
+ { 16, 230 }, { 19, 231 }, { 20, 232 }, { 23, 233 }, { 24, 234 },
+ { 26, 223 }, { 27, 235 }, { 28, 209 }, { 29, 176 }, { 30, 200 },
+ { 31, 201 }, { 32, 212 }, { 35, 177 }, { 36, 178 }, { 39, 184 },
+ { 40, 185 }, { 41, 227 }, { 42, 186 }, { 43, 228 }, { 45, 187 },
+ { 47, 188 }, { 48, 194 }, { 51, 195 }, { 52, 196 }, { 55, 197 },
+ { 56, 198 }, { 57, 236 }, { 58, 192 }, { 59, 193 }, { 72, 179 },
+ { 73, 180 }, { 74, 181 }, { 75, 202 }, { 76, 183 }, { 77, 189 },
+ { 78, 190 }, { 79, 191 }, { 80, 199 }, { 83, 204 }, { 84, 205 },
+ { 85, 229 }, { 86, 206 }, { 89, 207 }, { 91, 208 }, { 94, 214 },
+ { 95, 215 }, { 96, 237 }, { 97, 216 }, { 98, 238 }, { 99, 217 },
+ { 100, 239 }, { 105, 219 }, { 106, 210 }, { 107, 211 }, { 108, 222 },
+ { 109, 203 }, { 145, 225 }, { 146, 226 },
+};
+
static const struct msm_pinctrl_soc_data sa8775p_pinctrl = {
.pins = sa8775p_pins,
.npins = ARRAY_SIZE(sa8775p_pins),
@@ -1499,6 +1508,8 @@ static const struct msm_pinctrl_soc_data sa8775p_pinctrl = {
.groups = sa8775p_groups,
.ngroups = ARRAY_SIZE(sa8775p_groups),
.ngpios = 150,
+ .wakeirq_map = sa8775p_pdc_map,
+ .nwakeirq_map = ARRAY_SIZE(sa8775p_pdc_map),
};
static int sa8775p_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/qcom/pinctrl-sc7180.c b/drivers/pinctrl/qcom/pinctrl-sc7180.c
index 1d9acad3c1ce..6eb0c73791c0 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc7180.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc7180.c
@@ -4,7 +4,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -20,18 +19,11 @@ enum {
WEST
};
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -69,9 +61,9 @@ enum {
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -95,9 +87,9 @@ enum {
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -868,120 +860,120 @@ static const char * const qup04_uart_groups[] = {
"gpio115", "gpio116",
};
-static const struct msm_function sc7180_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(agera_pll),
- FUNCTION(aoss_cti),
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(atest_tsens),
- FUNCTION(atest_tsens2),
- FUNCTION(atest_usb1),
- FUNCTION(atest_usb2),
- FUNCTION(atest_usb10),
- FUNCTION(atest_usb11),
- FUNCTION(atest_usb12),
- FUNCTION(atest_usb13),
- FUNCTION(atest_usb20),
- FUNCTION(atest_usb21),
- FUNCTION(atest_usb22),
- FUNCTION(atest_usb23),
- FUNCTION(audio_ref),
- FUNCTION(btfm_slimbus),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cri_trng),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(dp_hot),
- FUNCTION(edp_lcd),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gpio),
- FUNCTION(gp_pdm0),
- FUNCTION(gp_pdm1),
- FUNCTION(gp_pdm2),
- FUNCTION(gps_tx),
- FUNCTION(jitter_bist),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(lpass_ext),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mi2s_0),
- FUNCTION(mi2s_1),
- FUNCTION(mi2s_2),
- FUNCTION(mss_lte),
- FUNCTION(m_voc),
- FUNCTION(pa_indicator),
- FUNCTION(phase_flag),
- FUNCTION(PLL_BIST),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_reset),
- FUNCTION(prng_rosc),
- FUNCTION(qdss),
- FUNCTION(qdss_cti),
- FUNCTION(qlink_enable),
- FUNCTION(qlink_request),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(qspi_data),
- FUNCTION(qup00),
- FUNCTION(qup01),
- FUNCTION(qup02_i2c),
- FUNCTION(qup02_uart),
- FUNCTION(qup03),
- FUNCTION(qup04_i2c),
- FUNCTION(qup04_uart),
- FUNCTION(qup05),
- FUNCTION(qup10),
- FUNCTION(qup11_i2c),
- FUNCTION(qup11_uart),
- FUNCTION(qup12),
- FUNCTION(qup13_i2c),
- FUNCTION(qup13_uart),
- FUNCTION(qup14),
- FUNCTION(qup15),
- FUNCTION(sdc1_tb),
- FUNCTION(sdc2_tb),
- FUNCTION(sd_write),
- FUNCTION(sp_cmu),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(uim1),
- FUNCTION(uim2),
- FUNCTION(uim_batt),
- FUNCTION(usb_phy),
- FUNCTION(vfr_1),
- FUNCTION(_V_GPIO),
- FUNCTION(_V_PPS_IN),
- FUNCTION(_V_PPS_OUT),
- FUNCTION(vsense_trigger),
- FUNCTION(wlan1_adc0),
- FUNCTION(wlan1_adc1),
- FUNCTION(wlan2_adc0),
- FUNCTION(wlan2_adc1),
+static const struct pinfunction sc7180_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_tsens2),
+ MSM_PIN_FUNCTION(atest_usb1),
+ MSM_PIN_FUNCTION(atest_usb2),
+ MSM_PIN_FUNCTION(atest_usb10),
+ MSM_PIN_FUNCTION(atest_usb11),
+ MSM_PIN_FUNCTION(atest_usb12),
+ MSM_PIN_FUNCTION(atest_usb13),
+ MSM_PIN_FUNCTION(atest_usb20),
+ MSM_PIN_FUNCTION(atest_usb21),
+ MSM_PIN_FUNCTION(atest_usb22),
+ MSM_PIN_FUNCTION(atest_usb23),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(btfm_slimbus),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gp_pdm0),
+ MSM_PIN_FUNCTION(gp_pdm1),
+ MSM_PIN_FUNCTION(gp_pdm2),
+ MSM_PIN_FUNCTION(gps_tx),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(lpass_ext),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mi2s_0),
+ MSM_PIN_FUNCTION(mi2s_1),
+ MSM_PIN_FUNCTION(mi2s_2),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(PLL_BIST),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qlink_enable),
+ MSM_PIN_FUNCTION(qlink_request),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qspi_data),
+ MSM_PIN_FUNCTION(qup00),
+ MSM_PIN_FUNCTION(qup01),
+ MSM_PIN_FUNCTION(qup02_i2c),
+ MSM_PIN_FUNCTION(qup02_uart),
+ MSM_PIN_FUNCTION(qup03),
+ MSM_PIN_FUNCTION(qup04_i2c),
+ MSM_PIN_FUNCTION(qup04_uart),
+ MSM_PIN_FUNCTION(qup05),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11_i2c),
+ MSM_PIN_FUNCTION(qup11_uart),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13_i2c),
+ MSM_PIN_FUNCTION(qup13_uart),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(qup15),
+ MSM_PIN_FUNCTION(sdc1_tb),
+ MSM_PIN_FUNCTION(sdc2_tb),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sp_cmu),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(uim1),
+ MSM_PIN_FUNCTION(uim2),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(_V_GPIO),
+ MSM_PIN_FUNCTION(_V_PPS_IN),
+ MSM_PIN_FUNCTION(_V_PPS_OUT),
+ MSM_PIN_FUNCTION(vsense_trigger),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(wlan1_adc1),
+ MSM_PIN_FUNCTION(wlan2_adc0),
+ MSM_PIN_FUNCTION(wlan2_adc1),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280.c b/drivers/pinctrl/qcom/pinctrl-sc7280.c
index 31df55c79cb3..0c10eeb60b55 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc7280.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc7280.c
@@ -6,22 +6,14 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -60,9 +52,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -85,9 +77,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -1120,154 +1112,154 @@ static const char * const vsense_trigger_groups[] = {
"gpio100",
};
-static const struct msm_function sc7280_functions[] = {
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(atest_usb0),
- FUNCTION(atest_usb00),
- FUNCTION(atest_usb01),
- FUNCTION(atest_usb02),
- FUNCTION(atest_usb03),
- FUNCTION(atest_usb1),
- FUNCTION(atest_usb10),
- FUNCTION(atest_usb11),
- FUNCTION(atest_usb12),
- FUNCTION(atest_usb13),
- FUNCTION(audio_ref),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cmu_rng0),
- FUNCTION(cmu_rng1),
- FUNCTION(cmu_rng2),
- FUNCTION(cmu_rng3),
- FUNCTION(coex_uart1),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(dp_hot),
- FUNCTION(dp_lcd),
- FUNCTION(edp_hot),
- FUNCTION(edp_lcd),
- FUNCTION(egpio),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gpio),
- FUNCTION(host2wlan_sol),
- FUNCTION(ibi_i3c),
- FUNCTION(jitter_bist),
- FUNCTION(lpass_slimbus),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mdp_vsync4),
- FUNCTION(mdp_vsync5),
- FUNCTION(mi2s0_data0),
- FUNCTION(mi2s0_data1),
- FUNCTION(mi2s0_sck),
- FUNCTION(mi2s0_ws),
- FUNCTION(mi2s1_data0),
- FUNCTION(mi2s1_data1),
- FUNCTION(mi2s1_sck),
- FUNCTION(mi2s1_ws),
- FUNCTION(mi2s2_data0),
- FUNCTION(mi2s2_data1),
- FUNCTION(mi2s2_sck),
- FUNCTION(mi2s2_ws),
- FUNCTION(mss_grfc0),
- FUNCTION(mss_grfc1),
- FUNCTION(mss_grfc10),
- FUNCTION(mss_grfc11),
- FUNCTION(mss_grfc12),
- FUNCTION(mss_grfc2),
- FUNCTION(mss_grfc3),
- FUNCTION(mss_grfc4),
- FUNCTION(mss_grfc5),
- FUNCTION(mss_grfc6),
- FUNCTION(mss_grfc7),
- FUNCTION(mss_grfc8),
- FUNCTION(mss_grfc9),
- FUNCTION(nav_gpio0),
- FUNCTION(nav_gpio1),
- FUNCTION(nav_gpio2),
- FUNCTION(pa_indicator),
- FUNCTION(pcie0_clkreqn),
- FUNCTION(pcie1_clkreqn),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_clk),
- FUNCTION(pll_reset),
- FUNCTION(pri_mi2s),
- FUNCTION(prng_rosc),
- FUNCTION(qdss),
- FUNCTION(qdss_cti),
- FUNCTION(qlink0_enable),
- FUNCTION(qlink0_request),
- FUNCTION(qlink0_wmss),
- FUNCTION(qlink1_enable),
- FUNCTION(qlink1_request),
- FUNCTION(qlink1_wmss),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(qspi_data),
- FUNCTION(qup00),
- FUNCTION(qup01),
- FUNCTION(qup02),
- FUNCTION(qup03),
- FUNCTION(qup04),
- FUNCTION(qup05),
- FUNCTION(qup06),
- FUNCTION(qup07),
- FUNCTION(qup10),
- FUNCTION(qup11),
- FUNCTION(qup12),
- FUNCTION(qup13),
- FUNCTION(qup14),
- FUNCTION(qup15),
- FUNCTION(qup16),
- FUNCTION(qup17),
- FUNCTION(sdc40),
- FUNCTION(sdc41),
- FUNCTION(sdc42),
- FUNCTION(sdc43),
- FUNCTION(sdc4_clk),
- FUNCTION(sdc4_cmd),
- FUNCTION(sd_write),
- FUNCTION(sec_mi2s),
- FUNCTION(tb_trig),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(uim0_clk),
- FUNCTION(uim0_data),
- FUNCTION(uim0_present),
- FUNCTION(uim0_reset),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(usb2phy_ac),
- FUNCTION(usb_phy),
- FUNCTION(vfr_0),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
+static const struct pinfunction sc7280_functions[] = {
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_usb0),
+ MSM_PIN_FUNCTION(atest_usb00),
+ MSM_PIN_FUNCTION(atest_usb01),
+ MSM_PIN_FUNCTION(atest_usb02),
+ MSM_PIN_FUNCTION(atest_usb03),
+ MSM_PIN_FUNCTION(atest_usb1),
+ MSM_PIN_FUNCTION(atest_usb10),
+ MSM_PIN_FUNCTION(atest_usb11),
+ MSM_PIN_FUNCTION(atest_usb12),
+ MSM_PIN_FUNCTION(atest_usb13),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cmu_rng0),
+ MSM_PIN_FUNCTION(cmu_rng1),
+ MSM_PIN_FUNCTION(cmu_rng2),
+ MSM_PIN_FUNCTION(cmu_rng3),
+ MSM_PIN_FUNCTION(coex_uart1),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(dp_lcd),
+ MSM_PIN_FUNCTION(edp_hot),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(egpio),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(host2wlan_sol),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(lpass_slimbus),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mdp_vsync4),
+ MSM_PIN_FUNCTION(mdp_vsync5),
+ MSM_PIN_FUNCTION(mi2s0_data0),
+ MSM_PIN_FUNCTION(mi2s0_data1),
+ MSM_PIN_FUNCTION(mi2s0_sck),
+ MSM_PIN_FUNCTION(mi2s0_ws),
+ MSM_PIN_FUNCTION(mi2s1_data0),
+ MSM_PIN_FUNCTION(mi2s1_data1),
+ MSM_PIN_FUNCTION(mi2s1_sck),
+ MSM_PIN_FUNCTION(mi2s1_ws),
+ MSM_PIN_FUNCTION(mi2s2_data0),
+ MSM_PIN_FUNCTION(mi2s2_data1),
+ MSM_PIN_FUNCTION(mi2s2_sck),
+ MSM_PIN_FUNCTION(mi2s2_ws),
+ MSM_PIN_FUNCTION(mss_grfc0),
+ MSM_PIN_FUNCTION(mss_grfc1),
+ MSM_PIN_FUNCTION(mss_grfc10),
+ MSM_PIN_FUNCTION(mss_grfc11),
+ MSM_PIN_FUNCTION(mss_grfc12),
+ MSM_PIN_FUNCTION(mss_grfc2),
+ MSM_PIN_FUNCTION(mss_grfc3),
+ MSM_PIN_FUNCTION(mss_grfc4),
+ MSM_PIN_FUNCTION(mss_grfc5),
+ MSM_PIN_FUNCTION(mss_grfc6),
+ MSM_PIN_FUNCTION(mss_grfc7),
+ MSM_PIN_FUNCTION(mss_grfc8),
+ MSM_PIN_FUNCTION(mss_grfc9),
+ MSM_PIN_FUNCTION(nav_gpio0),
+ MSM_PIN_FUNCTION(nav_gpio1),
+ MSM_PIN_FUNCTION(nav_gpio2),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pcie0_clkreqn),
+ MSM_PIN_FUNCTION(pcie1_clkreqn),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_clk),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qlink0_enable),
+ MSM_PIN_FUNCTION(qlink0_request),
+ MSM_PIN_FUNCTION(qlink0_wmss),
+ MSM_PIN_FUNCTION(qlink1_enable),
+ MSM_PIN_FUNCTION(qlink1_request),
+ MSM_PIN_FUNCTION(qlink1_wmss),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qspi_data),
+ MSM_PIN_FUNCTION(qup00),
+ MSM_PIN_FUNCTION(qup01),
+ MSM_PIN_FUNCTION(qup02),
+ MSM_PIN_FUNCTION(qup03),
+ MSM_PIN_FUNCTION(qup04),
+ MSM_PIN_FUNCTION(qup05),
+ MSM_PIN_FUNCTION(qup06),
+ MSM_PIN_FUNCTION(qup07),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(qup15),
+ MSM_PIN_FUNCTION(qup16),
+ MSM_PIN_FUNCTION(qup17),
+ MSM_PIN_FUNCTION(sdc40),
+ MSM_PIN_FUNCTION(sdc41),
+ MSM_PIN_FUNCTION(sdc42),
+ MSM_PIN_FUNCTION(sdc43),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(tb_trig),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(uim0_clk),
+ MSM_PIN_FUNCTION(uim0_data),
+ MSM_PIN_FUNCTION(uim0_present),
+ MSM_PIN_FUNCTION(uim0_reset),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_0),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
diff --git a/drivers/pinctrl/qcom/pinctrl-sc8180x.c b/drivers/pinctrl/qcom/pinctrl-sc8180x.c
index 704a99d2f93c..d6a79ad41a40 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc8180x.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc8180x.c
@@ -7,7 +7,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -38,19 +37,12 @@ static const struct tile_info sc8180x_tile_info[] = {
{ 0x00100000, 0x00300000, },
};
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP_OFFSET(id, _tile, offset, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -91,9 +83,9 @@ static const struct tile_info sc8180x_tile_info[] = {
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -117,9 +109,9 @@ static const struct tile_info sc8180x_tile_info[] = {
#define UFS_RESET(pg_name) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = 0xb6000, \
.io_reg = 0xb6004, \
.intr_cfg_reg = 0, \
@@ -1238,136 +1230,136 @@ static const char * const wmss_reset_groups[] = {
"gpio63",
};
-static const struct msm_function sc8180x_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(agera_pll),
- FUNCTION(aoss_cti),
- FUNCTION(atest_char),
- FUNCTION(atest_tsens),
- FUNCTION(atest_tsens2),
- FUNCTION(atest_usb0),
- FUNCTION(atest_usb1),
- FUNCTION(atest_usb2),
- FUNCTION(atest_usb3),
- FUNCTION(atest_usb4),
- FUNCTION(audio_ref),
- FUNCTION(btfm_slimbus),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cci_timer5),
- FUNCTION(cci_timer6),
- FUNCTION(cci_timer7),
- FUNCTION(cci_timer8),
- FUNCTION(cci_timer9),
- FUNCTION(cri_trng),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi),
- FUNCTION(debug_hot),
- FUNCTION(dp_hot),
- FUNCTION(edp_hot),
- FUNCTION(edp_lcd),
- FUNCTION(emac_phy),
- FUNCTION(emac_pps),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gcc_gp4),
- FUNCTION(gcc_gp5),
- FUNCTION(gpio),
- FUNCTION(gps),
- FUNCTION(grfc),
- FUNCTION(hs1_mi2s),
- FUNCTION(hs2_mi2s),
- FUNCTION(hs3_mi2s),
- FUNCTION(jitter_bist),
- FUNCTION(lpass_slimbus),
- FUNCTION(m_voc),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mdp_vsync4),
- FUNCTION(mdp_vsync5),
- FUNCTION(mss_lte),
- FUNCTION(nav_pps),
- FUNCTION(pa_indicator),
- FUNCTION(pci_e0),
- FUNCTION(pci_e1),
- FUNCTION(pci_e2),
- FUNCTION(pci_e3),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_reset),
- FUNCTION(pri_mi2s),
- FUNCTION(pri_mi2s_ws),
- FUNCTION(prng_rosc),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qlink),
- FUNCTION(qspi0),
- FUNCTION(qspi0_clk),
- FUNCTION(qspi0_cs),
- FUNCTION(qspi1),
- FUNCTION(qspi1_clk),
- FUNCTION(qspi1_cs),
- FUNCTION(qua_mi2s),
- FUNCTION(qup0),
- FUNCTION(qup1),
- FUNCTION(qup2),
- FUNCTION(qup3),
- FUNCTION(qup4),
- FUNCTION(qup5),
- FUNCTION(qup6),
- FUNCTION(qup7),
- FUNCTION(qup8),
- FUNCTION(qup9),
- FUNCTION(qup10),
- FUNCTION(qup11),
- FUNCTION(qup12),
- FUNCTION(qup13),
- FUNCTION(qup14),
- FUNCTION(qup15),
- FUNCTION(qup16),
- FUNCTION(qup17),
- FUNCTION(qup18),
- FUNCTION(qup19),
- FUNCTION(qup_l4),
- FUNCTION(qup_l5),
- FUNCTION(qup_l6),
- FUNCTION(rgmii),
- FUNCTION(sd_write),
- FUNCTION(sdc4),
- FUNCTION(sdc4_clk),
- FUNCTION(sdc4_cmd),
- FUNCTION(sec_mi2s),
- FUNCTION(sp_cmu),
- FUNCTION(spkr_i2s),
- FUNCTION(ter_mi2s),
- FUNCTION(tgu),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(tsif1),
- FUNCTION(tsif2),
- FUNCTION(uim1),
- FUNCTION(uim2),
- FUNCTION(uim_batt),
- FUNCTION(usb0_phy),
- FUNCTION(usb1_phy),
- FUNCTION(usb2phy_ac),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
- FUNCTION(wlan1_adc),
- FUNCTION(wlan2_adc),
- FUNCTION(wmss_reset),
+static const struct pinfunction sc8180x_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_tsens2),
+ MSM_PIN_FUNCTION(atest_usb0),
+ MSM_PIN_FUNCTION(atest_usb1),
+ MSM_PIN_FUNCTION(atest_usb2),
+ MSM_PIN_FUNCTION(atest_usb3),
+ MSM_PIN_FUNCTION(atest_usb4),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(btfm_slimbus),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cci_timer5),
+ MSM_PIN_FUNCTION(cci_timer6),
+ MSM_PIN_FUNCTION(cci_timer7),
+ MSM_PIN_FUNCTION(cci_timer8),
+ MSM_PIN_FUNCTION(cci_timer9),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi),
+ MSM_PIN_FUNCTION(debug_hot),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(edp_hot),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(emac_phy),
+ MSM_PIN_FUNCTION(emac_pps),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gcc_gp4),
+ MSM_PIN_FUNCTION(gcc_gp5),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gps),
+ MSM_PIN_FUNCTION(grfc),
+ MSM_PIN_FUNCTION(hs1_mi2s),
+ MSM_PIN_FUNCTION(hs2_mi2s),
+ MSM_PIN_FUNCTION(hs3_mi2s),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(lpass_slimbus),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mdp_vsync4),
+ MSM_PIN_FUNCTION(mdp_vsync5),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pci_e0),
+ MSM_PIN_FUNCTION(pci_e1),
+ MSM_PIN_FUNCTION(pci_e2),
+ MSM_PIN_FUNCTION(pci_e3),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(pri_mi2s_ws),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qlink),
+ MSM_PIN_FUNCTION(qspi0),
+ MSM_PIN_FUNCTION(qspi0_clk),
+ MSM_PIN_FUNCTION(qspi0_cs),
+ MSM_PIN_FUNCTION(qspi1),
+ MSM_PIN_FUNCTION(qspi1_clk),
+ MSM_PIN_FUNCTION(qspi1_cs),
+ MSM_PIN_FUNCTION(qua_mi2s),
+ MSM_PIN_FUNCTION(qup0),
+ MSM_PIN_FUNCTION(qup1),
+ MSM_PIN_FUNCTION(qup2),
+ MSM_PIN_FUNCTION(qup3),
+ MSM_PIN_FUNCTION(qup4),
+ MSM_PIN_FUNCTION(qup5),
+ MSM_PIN_FUNCTION(qup6),
+ MSM_PIN_FUNCTION(qup7),
+ MSM_PIN_FUNCTION(qup8),
+ MSM_PIN_FUNCTION(qup9),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(qup15),
+ MSM_PIN_FUNCTION(qup16),
+ MSM_PIN_FUNCTION(qup17),
+ MSM_PIN_FUNCTION(qup18),
+ MSM_PIN_FUNCTION(qup19),
+ MSM_PIN_FUNCTION(qup_l4),
+ MSM_PIN_FUNCTION(qup_l5),
+ MSM_PIN_FUNCTION(qup_l6),
+ MSM_PIN_FUNCTION(rgmii),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sdc4),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(sp_cmu),
+ MSM_PIN_FUNCTION(spkr_i2s),
+ MSM_PIN_FUNCTION(ter_mi2s),
+ MSM_PIN_FUNCTION(tgu),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(tsif1),
+ MSM_PIN_FUNCTION(tsif2),
+ MSM_PIN_FUNCTION(uim1),
+ MSM_PIN_FUNCTION(uim2),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(usb0_phy),
+ MSM_PIN_FUNCTION(usb1_phy),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
+ MSM_PIN_FUNCTION(wlan1_adc),
+ MSM_PIN_FUNCTION(wlan2_adc),
+ MSM_PIN_FUNCTION(wmss_reset),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
@@ -1630,7 +1622,8 @@ static const struct msm_pinctrl_soc_data sc8180x_acpi_pinctrl = {
static int sc8180x_pinctrl_add_tile_resources(struct platform_device *pdev)
{
int nres_num = pdev->num_resources + ARRAY_SIZE(sc8180x_tiles) - 1;
- struct resource *mres, *nres, *res;
+ struct resource *mres = NULL;
+ struct resource *nres, *res;
int i, ret;
/*
@@ -1657,6 +1650,9 @@ static int sc8180x_pinctrl_add_tile_resources(struct platform_device *pdev)
*res++ = *r;
}
+ if (!mres)
+ return -EINVAL;
+
/* Append tile memory resources */
for (i = 0; i < ARRAY_SIZE(sc8180x_tiles); i++, res++) {
const struct tile_info *info = &sc8180x_tile_info[i];
diff --git a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c
index e96c00686a25..96f4fb5a5d29 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c
@@ -7,23 +7,15 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -60,9 +52,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -85,9 +77,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -1476,172 +1468,172 @@ static const char * const vsense_trigger_groups[] = {
"gpio81",
};
-static const struct msm_function sc8280xp_functions[] = {
- FUNCTION(atest_char),
- FUNCTION(atest_usb),
- FUNCTION(audio_ref),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cci_timer5),
- FUNCTION(cci_timer6),
- FUNCTION(cci_timer7),
- FUNCTION(cci_timer8),
- FUNCTION(cci_timer9),
- FUNCTION(cmu_rng),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(ddr_pxi4),
- FUNCTION(ddr_pxi5),
- FUNCTION(ddr_pxi6),
- FUNCTION(ddr_pxi7),
- FUNCTION(dp2_hot),
- FUNCTION(dp3_hot),
- FUNCTION(edp0_lcd),
- FUNCTION(edp1_lcd),
- FUNCTION(edp2_lcd),
- FUNCTION(edp3_lcd),
- FUNCTION(edp_hot),
- FUNCTION(egpio),
- FUNCTION(emac0_dll),
- FUNCTION(emac0_mcg0),
- FUNCTION(emac0_mcg1),
- FUNCTION(emac0_mcg2),
- FUNCTION(emac0_mcg3),
- FUNCTION(emac0_phy),
- FUNCTION(emac0_ptp),
- FUNCTION(emac1_dll0),
- FUNCTION(emac1_dll1),
- FUNCTION(emac1_mcg0),
- FUNCTION(emac1_mcg1),
- FUNCTION(emac1_mcg2),
- FUNCTION(emac1_mcg3),
- FUNCTION(emac1_phy),
- FUNCTION(emac1_ptp),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gcc_gp4),
- FUNCTION(gcc_gp5),
- FUNCTION(gpio),
- FUNCTION(hs1_mi2s),
- FUNCTION(hs2_mi2s),
- FUNCTION(hs3_mi2s),
- FUNCTION(ibi_i3c),
- FUNCTION(jitter_bist),
- FUNCTION(lpass_slimbus),
- FUNCTION(mdp0_vsync0),
- FUNCTION(mdp0_vsync1),
- FUNCTION(mdp0_vsync2),
- FUNCTION(mdp0_vsync3),
- FUNCTION(mdp0_vsync4),
- FUNCTION(mdp0_vsync5),
- FUNCTION(mdp0_vsync6),
- FUNCTION(mdp0_vsync7),
- FUNCTION(mdp0_vsync8),
- FUNCTION(mdp1_vsync0),
- FUNCTION(mdp1_vsync1),
- FUNCTION(mdp1_vsync2),
- FUNCTION(mdp1_vsync3),
- FUNCTION(mdp1_vsync4),
- FUNCTION(mdp1_vsync5),
- FUNCTION(mdp1_vsync6),
- FUNCTION(mdp1_vsync7),
- FUNCTION(mdp1_vsync8),
- FUNCTION(mdp_vsync),
- FUNCTION(mi2s0_data0),
- FUNCTION(mi2s0_data1),
- FUNCTION(mi2s0_sck),
- FUNCTION(mi2s0_ws),
- FUNCTION(mi2s1_data0),
- FUNCTION(mi2s1_data1),
- FUNCTION(mi2s1_sck),
- FUNCTION(mi2s1_ws),
- FUNCTION(mi2s2_data0),
- FUNCTION(mi2s2_data1),
- FUNCTION(mi2s2_sck),
- FUNCTION(mi2s2_ws),
- FUNCTION(mi2s_mclk1),
- FUNCTION(mi2s_mclk2),
- FUNCTION(pcie2a_clkreq),
- FUNCTION(pcie2b_clkreq),
- FUNCTION(pcie3a_clkreq),
- FUNCTION(pcie3b_clkreq),
- FUNCTION(pcie4_clkreq),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_clk),
- FUNCTION(prng_rosc0),
- FUNCTION(prng_rosc1),
- FUNCTION(prng_rosc2),
- FUNCTION(prng_rosc3),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qspi),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(qup0),
- FUNCTION(qup1),
- FUNCTION(qup2),
- FUNCTION(qup3),
- FUNCTION(qup4),
- FUNCTION(qup5),
- FUNCTION(qup6),
- FUNCTION(qup7),
- FUNCTION(qup8),
- FUNCTION(qup9),
- FUNCTION(qup10),
- FUNCTION(qup11),
- FUNCTION(qup12),
- FUNCTION(qup13),
- FUNCTION(qup14),
- FUNCTION(qup15),
- FUNCTION(qup16),
- FUNCTION(qup17),
- FUNCTION(qup18),
- FUNCTION(qup19),
- FUNCTION(qup20),
- FUNCTION(qup21),
- FUNCTION(qup22),
- FUNCTION(qup23),
- FUNCTION(rgmii_0),
- FUNCTION(rgmii_1),
- FUNCTION(sd_write),
- FUNCTION(sdc40),
- FUNCTION(sdc42),
- FUNCTION(sdc43),
- FUNCTION(sdc4_clk),
- FUNCTION(sdc4_cmd),
- FUNCTION(tb_trig),
- FUNCTION(tgu),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(tsense_pwm3),
- FUNCTION(tsense_pwm4),
- FUNCTION(usb0_dp),
- FUNCTION(usb0_phy),
- FUNCTION(usb0_sbrx),
- FUNCTION(usb0_sbtx),
- FUNCTION(usb0_usb4),
- FUNCTION(usb1_dp),
- FUNCTION(usb1_phy),
- FUNCTION(usb1_sbrx),
- FUNCTION(usb1_sbtx),
- FUNCTION(usb1_usb4),
- FUNCTION(usb2phy_ac),
- FUNCTION(vsense_trigger),
+static const struct pinfunction sc8280xp_functions[] = {
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_usb),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cci_timer5),
+ MSM_PIN_FUNCTION(cci_timer6),
+ MSM_PIN_FUNCTION(cci_timer7),
+ MSM_PIN_FUNCTION(cci_timer8),
+ MSM_PIN_FUNCTION(cci_timer9),
+ MSM_PIN_FUNCTION(cmu_rng),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(ddr_pxi4),
+ MSM_PIN_FUNCTION(ddr_pxi5),
+ MSM_PIN_FUNCTION(ddr_pxi6),
+ MSM_PIN_FUNCTION(ddr_pxi7),
+ MSM_PIN_FUNCTION(dp2_hot),
+ MSM_PIN_FUNCTION(dp3_hot),
+ MSM_PIN_FUNCTION(edp0_lcd),
+ MSM_PIN_FUNCTION(edp1_lcd),
+ MSM_PIN_FUNCTION(edp2_lcd),
+ MSM_PIN_FUNCTION(edp3_lcd),
+ MSM_PIN_FUNCTION(edp_hot),
+ MSM_PIN_FUNCTION(egpio),
+ MSM_PIN_FUNCTION(emac0_dll),
+ MSM_PIN_FUNCTION(emac0_mcg0),
+ MSM_PIN_FUNCTION(emac0_mcg1),
+ MSM_PIN_FUNCTION(emac0_mcg2),
+ MSM_PIN_FUNCTION(emac0_mcg3),
+ MSM_PIN_FUNCTION(emac0_phy),
+ MSM_PIN_FUNCTION(emac0_ptp),
+ MSM_PIN_FUNCTION(emac1_dll0),
+ MSM_PIN_FUNCTION(emac1_dll1),
+ MSM_PIN_FUNCTION(emac1_mcg0),
+ MSM_PIN_FUNCTION(emac1_mcg1),
+ MSM_PIN_FUNCTION(emac1_mcg2),
+ MSM_PIN_FUNCTION(emac1_mcg3),
+ MSM_PIN_FUNCTION(emac1_phy),
+ MSM_PIN_FUNCTION(emac1_ptp),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gcc_gp4),
+ MSM_PIN_FUNCTION(gcc_gp5),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(hs1_mi2s),
+ MSM_PIN_FUNCTION(hs2_mi2s),
+ MSM_PIN_FUNCTION(hs3_mi2s),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(lpass_slimbus),
+ MSM_PIN_FUNCTION(mdp0_vsync0),
+ MSM_PIN_FUNCTION(mdp0_vsync1),
+ MSM_PIN_FUNCTION(mdp0_vsync2),
+ MSM_PIN_FUNCTION(mdp0_vsync3),
+ MSM_PIN_FUNCTION(mdp0_vsync4),
+ MSM_PIN_FUNCTION(mdp0_vsync5),
+ MSM_PIN_FUNCTION(mdp0_vsync6),
+ MSM_PIN_FUNCTION(mdp0_vsync7),
+ MSM_PIN_FUNCTION(mdp0_vsync8),
+ MSM_PIN_FUNCTION(mdp1_vsync0),
+ MSM_PIN_FUNCTION(mdp1_vsync1),
+ MSM_PIN_FUNCTION(mdp1_vsync2),
+ MSM_PIN_FUNCTION(mdp1_vsync3),
+ MSM_PIN_FUNCTION(mdp1_vsync4),
+ MSM_PIN_FUNCTION(mdp1_vsync5),
+ MSM_PIN_FUNCTION(mdp1_vsync6),
+ MSM_PIN_FUNCTION(mdp1_vsync7),
+ MSM_PIN_FUNCTION(mdp1_vsync8),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mi2s0_data0),
+ MSM_PIN_FUNCTION(mi2s0_data1),
+ MSM_PIN_FUNCTION(mi2s0_sck),
+ MSM_PIN_FUNCTION(mi2s0_ws),
+ MSM_PIN_FUNCTION(mi2s1_data0),
+ MSM_PIN_FUNCTION(mi2s1_data1),
+ MSM_PIN_FUNCTION(mi2s1_sck),
+ MSM_PIN_FUNCTION(mi2s1_ws),
+ MSM_PIN_FUNCTION(mi2s2_data0),
+ MSM_PIN_FUNCTION(mi2s2_data1),
+ MSM_PIN_FUNCTION(mi2s2_sck),
+ MSM_PIN_FUNCTION(mi2s2_ws),
+ MSM_PIN_FUNCTION(mi2s_mclk1),
+ MSM_PIN_FUNCTION(mi2s_mclk2),
+ MSM_PIN_FUNCTION(pcie2a_clkreq),
+ MSM_PIN_FUNCTION(pcie2b_clkreq),
+ MSM_PIN_FUNCTION(pcie3a_clkreq),
+ MSM_PIN_FUNCTION(pcie3b_clkreq),
+ MSM_PIN_FUNCTION(pcie4_clkreq),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_clk),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(prng_rosc2),
+ MSM_PIN_FUNCTION(prng_rosc3),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qspi),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qup0),
+ MSM_PIN_FUNCTION(qup1),
+ MSM_PIN_FUNCTION(qup2),
+ MSM_PIN_FUNCTION(qup3),
+ MSM_PIN_FUNCTION(qup4),
+ MSM_PIN_FUNCTION(qup5),
+ MSM_PIN_FUNCTION(qup6),
+ MSM_PIN_FUNCTION(qup7),
+ MSM_PIN_FUNCTION(qup8),
+ MSM_PIN_FUNCTION(qup9),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(qup15),
+ MSM_PIN_FUNCTION(qup16),
+ MSM_PIN_FUNCTION(qup17),
+ MSM_PIN_FUNCTION(qup18),
+ MSM_PIN_FUNCTION(qup19),
+ MSM_PIN_FUNCTION(qup20),
+ MSM_PIN_FUNCTION(qup21),
+ MSM_PIN_FUNCTION(qup22),
+ MSM_PIN_FUNCTION(qup23),
+ MSM_PIN_FUNCTION(rgmii_0),
+ MSM_PIN_FUNCTION(rgmii_1),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sdc40),
+ MSM_PIN_FUNCTION(sdc42),
+ MSM_PIN_FUNCTION(sdc43),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(tb_trig),
+ MSM_PIN_FUNCTION(tgu),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(tsense_pwm3),
+ MSM_PIN_FUNCTION(tsense_pwm4),
+ MSM_PIN_FUNCTION(usb0_dp),
+ MSM_PIN_FUNCTION(usb0_phy),
+ MSM_PIN_FUNCTION(usb0_sbrx),
+ MSM_PIN_FUNCTION(usb0_sbtx),
+ MSM_PIN_FUNCTION(usb0_usb4),
+ MSM_PIN_FUNCTION(usb1_dp),
+ MSM_PIN_FUNCTION(usb1_phy),
+ MSM_PIN_FUNCTION(usb1_sbrx),
+ MSM_PIN_FUNCTION(usb1_sbtx),
+ MSM_PIN_FUNCTION(usb1_usb4),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(vsense_trigger),
};
static const struct msm_pingroup sc8280xp_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm660.c b/drivers/pinctrl/qcom/pinctrl-sdm660.c
index 1bfb0ae6b387..c2e0d5c034ac 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm660.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm660.c
@@ -7,7 +7,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -25,19 +24,11 @@ enum {
#define REG_SIZE 0x1000
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
-
#define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -75,9 +66,9 @@ enum {
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -1099,189 +1090,189 @@ static const char * const wlan2_adc1_groups[] = {
"gpio10",
};
-static const struct msm_function sdm660_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(agera_pll),
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(atest_gpsadc0),
- FUNCTION(atest_gpsadc1),
- FUNCTION(atest_tsens),
- FUNCTION(atest_tsens2),
- FUNCTION(atest_usb1),
- FUNCTION(atest_usb10),
- FUNCTION(atest_usb11),
- FUNCTION(atest_usb12),
- FUNCTION(atest_usb13),
- FUNCTION(atest_usb2),
- FUNCTION(atest_usb20),
- FUNCTION(atest_usb21),
- FUNCTION(atest_usb22),
- FUNCTION(atest_usb23),
- FUNCTION(audio_ref),
- FUNCTION(bimc_dte0),
- FUNCTION(bimc_dte1),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_i2c5),
- FUNCTION(blsp_i2c6),
- FUNCTION(blsp_i2c7),
- FUNCTION(blsp_i2c8_a),
- FUNCTION(blsp_i2c8_b),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi3_cs1),
- FUNCTION(blsp_spi3_cs2),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_spi5),
- FUNCTION(blsp_spi6),
- FUNCTION(blsp_spi7),
- FUNCTION(blsp_spi8_a),
- FUNCTION(blsp_spi8_b),
- FUNCTION(blsp_spi8_cs1),
- FUNCTION(blsp_spi8_cs2),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_uart5),
- FUNCTION(blsp_uart6_a),
- FUNCTION(blsp_uart6_b),
- FUNCTION(blsp_uim1),
- FUNCTION(blsp_uim2),
- FUNCTION(blsp_uim5),
- FUNCTION(blsp_uim6),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gpio),
- FUNCTION(gps_tx_a),
- FUNCTION(gps_tx_b),
- FUNCTION(gps_tx_c),
- FUNCTION(isense_dbg),
- FUNCTION(jitter_bist),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(m_voc),
- FUNCTION(mdp_vsync),
- FUNCTION(mdss_vsync0),
- FUNCTION(mdss_vsync1),
- FUNCTION(mdss_vsync2),
- FUNCTION(mdss_vsync3),
- FUNCTION(mss_lte),
- FUNCTION(nav_pps_a),
- FUNCTION(nav_pps_b),
- FUNCTION(nav_pps_c),
- FUNCTION(pa_indicator),
- FUNCTION(phase_flag0),
- FUNCTION(phase_flag1),
- FUNCTION(phase_flag2),
- FUNCTION(phase_flag3),
- FUNCTION(phase_flag4),
- FUNCTION(phase_flag5),
- FUNCTION(phase_flag6),
- FUNCTION(phase_flag7),
- FUNCTION(phase_flag8),
- FUNCTION(phase_flag9),
- FUNCTION(phase_flag10),
- FUNCTION(phase_flag11),
- FUNCTION(phase_flag12),
- FUNCTION(phase_flag13),
- FUNCTION(phase_flag14),
- FUNCTION(phase_flag15),
- FUNCTION(phase_flag16),
- FUNCTION(phase_flag17),
- FUNCTION(phase_flag18),
- FUNCTION(phase_flag19),
- FUNCTION(phase_flag20),
- FUNCTION(phase_flag21),
- FUNCTION(phase_flag22),
- FUNCTION(phase_flag23),
- FUNCTION(phase_flag24),
- FUNCTION(phase_flag25),
- FUNCTION(phase_flag26),
- FUNCTION(phase_flag27),
- FUNCTION(phase_flag28),
- FUNCTION(phase_flag29),
- FUNCTION(phase_flag30),
- FUNCTION(phase_flag31),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_reset),
- FUNCTION(pri_mi2s),
- FUNCTION(pri_mi2s_ws),
- FUNCTION(prng_rosc),
- FUNCTION(pwr_crypto),
- FUNCTION(pwr_modem),
- FUNCTION(pwr_nav),
- FUNCTION(qdss_cti0_a),
- FUNCTION(qdss_cti0_b),
- FUNCTION(qdss_cti1_a),
- FUNCTION(qdss_cti1_b),
- FUNCTION(qdss_gpio),
- FUNCTION(qdss_gpio0),
- FUNCTION(qdss_gpio1),
- FUNCTION(qdss_gpio10),
- FUNCTION(qdss_gpio11),
- FUNCTION(qdss_gpio12),
- FUNCTION(qdss_gpio13),
- FUNCTION(qdss_gpio14),
- FUNCTION(qdss_gpio15),
- FUNCTION(qdss_gpio2),
- FUNCTION(qdss_gpio3),
- FUNCTION(qdss_gpio4),
- FUNCTION(qdss_gpio5),
- FUNCTION(qdss_gpio6),
- FUNCTION(qdss_gpio7),
- FUNCTION(qdss_gpio8),
- FUNCTION(qdss_gpio9),
- FUNCTION(qlink_enable),
- FUNCTION(qlink_request),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(qspi_data0),
- FUNCTION(qspi_data1),
- FUNCTION(qspi_data2),
- FUNCTION(qspi_data3),
- FUNCTION(qspi_resetn),
- FUNCTION(sec_mi2s),
- FUNCTION(sndwire_clk),
- FUNCTION(sndwire_data),
- FUNCTION(sp_cmu),
- FUNCTION(ssc_irq),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(uim_batt),
- FUNCTION(vfr_1),
- FUNCTION(vsense_clkout),
- FUNCTION(vsense_data0),
- FUNCTION(vsense_data1),
- FUNCTION(vsense_mode),
- FUNCTION(wlan1_adc0),
- FUNCTION(wlan1_adc1),
- FUNCTION(wlan2_adc0),
- FUNCTION(wlan2_adc1),
+static const struct pinfunction sdm660_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_gpsadc0),
+ MSM_PIN_FUNCTION(atest_gpsadc1),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_tsens2),
+ MSM_PIN_FUNCTION(atest_usb1),
+ MSM_PIN_FUNCTION(atest_usb10),
+ MSM_PIN_FUNCTION(atest_usb11),
+ MSM_PIN_FUNCTION(atest_usb12),
+ MSM_PIN_FUNCTION(atest_usb13),
+ MSM_PIN_FUNCTION(atest_usb2),
+ MSM_PIN_FUNCTION(atest_usb20),
+ MSM_PIN_FUNCTION(atest_usb21),
+ MSM_PIN_FUNCTION(atest_usb22),
+ MSM_PIN_FUNCTION(atest_usb23),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(bimc_dte0),
+ MSM_PIN_FUNCTION(bimc_dte1),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_i2c5),
+ MSM_PIN_FUNCTION(blsp_i2c6),
+ MSM_PIN_FUNCTION(blsp_i2c7),
+ MSM_PIN_FUNCTION(blsp_i2c8_a),
+ MSM_PIN_FUNCTION(blsp_i2c8_b),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(blsp_spi3_cs1),
+ MSM_PIN_FUNCTION(blsp_spi3_cs2),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(blsp_spi5),
+ MSM_PIN_FUNCTION(blsp_spi6),
+ MSM_PIN_FUNCTION(blsp_spi7),
+ MSM_PIN_FUNCTION(blsp_spi8_a),
+ MSM_PIN_FUNCTION(blsp_spi8_b),
+ MSM_PIN_FUNCTION(blsp_spi8_cs1),
+ MSM_PIN_FUNCTION(blsp_spi8_cs2),
+ MSM_PIN_FUNCTION(blsp_uart1),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(blsp_uart5),
+ MSM_PIN_FUNCTION(blsp_uart6_a),
+ MSM_PIN_FUNCTION(blsp_uart6_b),
+ MSM_PIN_FUNCTION(blsp_uim1),
+ MSM_PIN_FUNCTION(blsp_uim2),
+ MSM_PIN_FUNCTION(blsp_uim5),
+ MSM_PIN_FUNCTION(blsp_uim6),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gps_tx_a),
+ MSM_PIN_FUNCTION(gps_tx_b),
+ MSM_PIN_FUNCTION(gps_tx_c),
+ MSM_PIN_FUNCTION(isense_dbg),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdss_vsync0),
+ MSM_PIN_FUNCTION(mdss_vsync1),
+ MSM_PIN_FUNCTION(mdss_vsync2),
+ MSM_PIN_FUNCTION(mdss_vsync3),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(nav_pps_a),
+ MSM_PIN_FUNCTION(nav_pps_b),
+ MSM_PIN_FUNCTION(nav_pps_c),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(phase_flag0),
+ MSM_PIN_FUNCTION(phase_flag1),
+ MSM_PIN_FUNCTION(phase_flag2),
+ MSM_PIN_FUNCTION(phase_flag3),
+ MSM_PIN_FUNCTION(phase_flag4),
+ MSM_PIN_FUNCTION(phase_flag5),
+ MSM_PIN_FUNCTION(phase_flag6),
+ MSM_PIN_FUNCTION(phase_flag7),
+ MSM_PIN_FUNCTION(phase_flag8),
+ MSM_PIN_FUNCTION(phase_flag9),
+ MSM_PIN_FUNCTION(phase_flag10),
+ MSM_PIN_FUNCTION(phase_flag11),
+ MSM_PIN_FUNCTION(phase_flag12),
+ MSM_PIN_FUNCTION(phase_flag13),
+ MSM_PIN_FUNCTION(phase_flag14),
+ MSM_PIN_FUNCTION(phase_flag15),
+ MSM_PIN_FUNCTION(phase_flag16),
+ MSM_PIN_FUNCTION(phase_flag17),
+ MSM_PIN_FUNCTION(phase_flag18),
+ MSM_PIN_FUNCTION(phase_flag19),
+ MSM_PIN_FUNCTION(phase_flag20),
+ MSM_PIN_FUNCTION(phase_flag21),
+ MSM_PIN_FUNCTION(phase_flag22),
+ MSM_PIN_FUNCTION(phase_flag23),
+ MSM_PIN_FUNCTION(phase_flag24),
+ MSM_PIN_FUNCTION(phase_flag25),
+ MSM_PIN_FUNCTION(phase_flag26),
+ MSM_PIN_FUNCTION(phase_flag27),
+ MSM_PIN_FUNCTION(phase_flag28),
+ MSM_PIN_FUNCTION(phase_flag29),
+ MSM_PIN_FUNCTION(phase_flag30),
+ MSM_PIN_FUNCTION(phase_flag31),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(pri_mi2s_ws),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(pwr_crypto),
+ MSM_PIN_FUNCTION(pwr_modem),
+ MSM_PIN_FUNCTION(pwr_nav),
+ MSM_PIN_FUNCTION(qdss_cti0_a),
+ MSM_PIN_FUNCTION(qdss_cti0_b),
+ MSM_PIN_FUNCTION(qdss_cti1_a),
+ MSM_PIN_FUNCTION(qdss_cti1_b),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qdss_gpio0),
+ MSM_PIN_FUNCTION(qdss_gpio1),
+ MSM_PIN_FUNCTION(qdss_gpio10),
+ MSM_PIN_FUNCTION(qdss_gpio11),
+ MSM_PIN_FUNCTION(qdss_gpio12),
+ MSM_PIN_FUNCTION(qdss_gpio13),
+ MSM_PIN_FUNCTION(qdss_gpio14),
+ MSM_PIN_FUNCTION(qdss_gpio15),
+ MSM_PIN_FUNCTION(qdss_gpio2),
+ MSM_PIN_FUNCTION(qdss_gpio3),
+ MSM_PIN_FUNCTION(qdss_gpio4),
+ MSM_PIN_FUNCTION(qdss_gpio5),
+ MSM_PIN_FUNCTION(qdss_gpio6),
+ MSM_PIN_FUNCTION(qdss_gpio7),
+ MSM_PIN_FUNCTION(qdss_gpio8),
+ MSM_PIN_FUNCTION(qdss_gpio9),
+ MSM_PIN_FUNCTION(qlink_enable),
+ MSM_PIN_FUNCTION(qlink_request),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qspi_data0),
+ MSM_PIN_FUNCTION(qspi_data1),
+ MSM_PIN_FUNCTION(qspi_data2),
+ MSM_PIN_FUNCTION(qspi_data3),
+ MSM_PIN_FUNCTION(qspi_resetn),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(sndwire_clk),
+ MSM_PIN_FUNCTION(sndwire_data),
+ MSM_PIN_FUNCTION(sp_cmu),
+ MSM_PIN_FUNCTION(ssc_irq),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_clkout),
+ MSM_PIN_FUNCTION(vsense_data0),
+ MSM_PIN_FUNCTION(vsense_data1),
+ MSM_PIN_FUNCTION(vsense_mode),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(wlan1_adc1),
+ MSM_PIN_FUNCTION(wlan2_adc0),
+ MSM_PIN_FUNCTION(wlan2_adc1),
};
static const struct msm_pingroup sdm660_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm670.c b/drivers/pinctrl/qcom/pinctrl-sdm670.c
index b888bca7ecd7..cc3cce077de4 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm670.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm670.c
@@ -7,17 +7,9 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define NORTH 0x00500000
#define SOUTH 0x00900000
#define WEST 0x00100000
@@ -25,9 +17,9 @@
#define REG_SIZE 0x1000
#define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -68,9 +60,9 @@
*/
#define PINGROUP_DUMMY(id) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.ctl_reg = 0, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -93,9 +85,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -118,9 +110,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -998,132 +990,132 @@ static const char * const mss_lte_groups[] = {
"gpio144", "gpio145",
};
-static const struct msm_function sdm670_functions[] = {
- FUNCTION(gpio),
- FUNCTION(adsp_ext),
- FUNCTION(agera_pll),
- FUNCTION(atest_char),
- FUNCTION(atest_tsens),
- FUNCTION(atest_tsens2),
- FUNCTION(atest_usb1),
- FUNCTION(atest_usb10),
- FUNCTION(atest_usb11),
- FUNCTION(atest_usb12),
- FUNCTION(atest_usb13),
- FUNCTION(atest_usb2),
- FUNCTION(atest_usb20),
- FUNCTION(atest_usb21),
- FUNCTION(atest_usb22),
- FUNCTION(atest_usb23),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(copy_gp),
- FUNCTION(copy_phase),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(edp_hot),
- FUNCTION(edp_lcd),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gp_pdm0),
- FUNCTION(gp_pdm1),
- FUNCTION(gp_pdm2),
- FUNCTION(gps_tx),
- FUNCTION(jitter_bist),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(lpass_slimbus),
- FUNCTION(m_voc),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mss_lte),
- FUNCTION(nav_pps),
- FUNCTION(pa_indicator),
- FUNCTION(pci_e0),
- FUNCTION(pci_e1),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_reset),
- FUNCTION(pri_mi2s),
- FUNCTION(pri_mi2s_ws),
- FUNCTION(prng_rosc),
- FUNCTION(qdss_cti),
- FUNCTION(qdss),
- FUNCTION(qlink_enable),
- FUNCTION(qlink_request),
- FUNCTION(qua_mi2s),
- FUNCTION(qup0),
- FUNCTION(qup1),
- FUNCTION(qup10),
- FUNCTION(qup11),
- FUNCTION(qup12),
- FUNCTION(qup13),
- FUNCTION(qup14),
- FUNCTION(qup15),
- FUNCTION(qup2),
- FUNCTION(qup3),
- FUNCTION(qup4),
- FUNCTION(qup5),
- FUNCTION(qup6),
- FUNCTION(qup7),
- FUNCTION(qup8),
- FUNCTION(qup9),
- FUNCTION(qup_l4),
- FUNCTION(qup_l5),
- FUNCTION(qup_l6),
- FUNCTION(sdc4_clk),
- FUNCTION(sdc4_cmd),
- FUNCTION(sdc4_data),
- FUNCTION(sd_write),
- FUNCTION(sec_mi2s),
- FUNCTION(ter_mi2s),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tsif1_clk),
- FUNCTION(tsif1_data),
- FUNCTION(tsif1_en),
- FUNCTION(tsif1_error),
- FUNCTION(tsif1_sync),
- FUNCTION(tsif2_clk),
- FUNCTION(tsif2_data),
- FUNCTION(tsif2_en),
- FUNCTION(tsif2_error),
- FUNCTION(tsif2_sync),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(uim_batt),
- FUNCTION(usb_phy),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
- FUNCTION(wlan1_adc0),
- FUNCTION(wlan1_adc1),
- FUNCTION(wlan2_adc0),
- FUNCTION(wlan2_adc1),
- FUNCTION(wsa_clk),
- FUNCTION(wsa_data),
+static const struct pinfunction sdm670_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_tsens2),
+ MSM_PIN_FUNCTION(atest_usb1),
+ MSM_PIN_FUNCTION(atest_usb10),
+ MSM_PIN_FUNCTION(atest_usb11),
+ MSM_PIN_FUNCTION(atest_usb12),
+ MSM_PIN_FUNCTION(atest_usb13),
+ MSM_PIN_FUNCTION(atest_usb2),
+ MSM_PIN_FUNCTION(atest_usb20),
+ MSM_PIN_FUNCTION(atest_usb21),
+ MSM_PIN_FUNCTION(atest_usb22),
+ MSM_PIN_FUNCTION(atest_usb23),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(copy_gp),
+ MSM_PIN_FUNCTION(copy_phase),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(edp_hot),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gp_pdm0),
+ MSM_PIN_FUNCTION(gp_pdm1),
+ MSM_PIN_FUNCTION(gp_pdm2),
+ MSM_PIN_FUNCTION(gps_tx),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(lpass_slimbus),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pci_e0),
+ MSM_PIN_FUNCTION(pci_e1),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(pri_mi2s_ws),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss),
+ MSM_PIN_FUNCTION(qlink_enable),
+ MSM_PIN_FUNCTION(qlink_request),
+ MSM_PIN_FUNCTION(qua_mi2s),
+ MSM_PIN_FUNCTION(qup0),
+ MSM_PIN_FUNCTION(qup1),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(qup15),
+ MSM_PIN_FUNCTION(qup2),
+ MSM_PIN_FUNCTION(qup3),
+ MSM_PIN_FUNCTION(qup4),
+ MSM_PIN_FUNCTION(qup5),
+ MSM_PIN_FUNCTION(qup6),
+ MSM_PIN_FUNCTION(qup7),
+ MSM_PIN_FUNCTION(qup8),
+ MSM_PIN_FUNCTION(qup9),
+ MSM_PIN_FUNCTION(qup_l4),
+ MSM_PIN_FUNCTION(qup_l5),
+ MSM_PIN_FUNCTION(qup_l6),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sdc4_data),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(ter_mi2s),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tsif1_clk),
+ MSM_PIN_FUNCTION(tsif1_data),
+ MSM_PIN_FUNCTION(tsif1_en),
+ MSM_PIN_FUNCTION(tsif1_error),
+ MSM_PIN_FUNCTION(tsif1_sync),
+ MSM_PIN_FUNCTION(tsif2_clk),
+ MSM_PIN_FUNCTION(tsif2_data),
+ MSM_PIN_FUNCTION(tsif2_en),
+ MSM_PIN_FUNCTION(tsif2_error),
+ MSM_PIN_FUNCTION(tsif2_sync),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(wlan1_adc1),
+ MSM_PIN_FUNCTION(wlan2_adc0),
+ MSM_PIN_FUNCTION(wlan2_adc1),
+ MSM_PIN_FUNCTION(wsa_clk),
+ MSM_PIN_FUNCTION(wsa_data),
};
/*
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c
index fdfd7b8f3a76..cc05c415ed15 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm845.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c
@@ -7,26 +7,18 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define NORTH 0x00500000
#define SOUTH 0x00900000
#define EAST 0x00100000
#define REG_SIZE 0x1000
#define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -64,9 +56,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -89,9 +81,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -983,136 +975,136 @@ static const char * const tsif1_sync_groups[] = {
"gpio12",
};
-static const struct msm_function sdm845_functions[] = {
- FUNCTION(gpio),
- FUNCTION(adsp_ext),
- FUNCTION(agera_pll),
- FUNCTION(atest_char),
- FUNCTION(atest_tsens),
- FUNCTION(atest_tsens2),
- FUNCTION(atest_usb1),
- FUNCTION(atest_usb10),
- FUNCTION(atest_usb11),
- FUNCTION(atest_usb12),
- FUNCTION(atest_usb13),
- FUNCTION(atest_usb2),
- FUNCTION(atest_usb20),
- FUNCTION(atest_usb21),
- FUNCTION(atest_usb22),
- FUNCTION(atest_usb23),
- FUNCTION(audio_ref),
- FUNCTION(btfm_slimbus),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(edp_hot),
- FUNCTION(edp_lcd),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(jitter_bist),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(lpass_slimbus),
- FUNCTION(m_voc),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mss_lte),
- FUNCTION(nav_pps),
- FUNCTION(pa_indicator),
- FUNCTION(pci_e0),
- FUNCTION(pci_e1),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_reset),
- FUNCTION(pri_mi2s),
- FUNCTION(pri_mi2s_ws),
- FUNCTION(prng_rosc),
- FUNCTION(qdss_cti),
- FUNCTION(qdss),
- FUNCTION(qlink_enable),
- FUNCTION(qlink_request),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(qspi_data),
- FUNCTION(qua_mi2s),
- FUNCTION(qup0),
- FUNCTION(qup1),
- FUNCTION(qup10),
- FUNCTION(qup11),
- FUNCTION(qup12),
- FUNCTION(qup13),
- FUNCTION(qup14),
- FUNCTION(qup15),
- FUNCTION(qup2),
- FUNCTION(qup3),
- FUNCTION(qup4),
- FUNCTION(qup5),
- FUNCTION(qup6),
- FUNCTION(qup7),
- FUNCTION(qup8),
- FUNCTION(qup9),
- FUNCTION(qup_l4),
- FUNCTION(qup_l5),
- FUNCTION(qup_l6),
- FUNCTION(sd_write),
- FUNCTION(sdc4_clk),
- FUNCTION(sdc4_cmd),
- FUNCTION(sdc4_data),
- FUNCTION(sec_mi2s),
- FUNCTION(sp_cmu),
- FUNCTION(spkr_i2s),
- FUNCTION(ter_mi2s),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(tsif1_clk),
- FUNCTION(tsif1_data),
- FUNCTION(tsif1_en),
- FUNCTION(tsif1_error),
- FUNCTION(tsif1_sync),
- FUNCTION(tsif2_clk),
- FUNCTION(tsif2_data),
- FUNCTION(tsif2_en),
- FUNCTION(tsif2_error),
- FUNCTION(tsif2_sync),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(uim_batt),
- FUNCTION(usb_phy),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
- FUNCTION(wlan1_adc0),
- FUNCTION(wlan1_adc1),
- FUNCTION(wlan2_adc0),
- FUNCTION(wlan2_adc1),
+static const struct pinfunction sdm845_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_tsens2),
+ MSM_PIN_FUNCTION(atest_usb1),
+ MSM_PIN_FUNCTION(atest_usb10),
+ MSM_PIN_FUNCTION(atest_usb11),
+ MSM_PIN_FUNCTION(atest_usb12),
+ MSM_PIN_FUNCTION(atest_usb13),
+ MSM_PIN_FUNCTION(atest_usb2),
+ MSM_PIN_FUNCTION(atest_usb20),
+ MSM_PIN_FUNCTION(atest_usb21),
+ MSM_PIN_FUNCTION(atest_usb22),
+ MSM_PIN_FUNCTION(atest_usb23),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(btfm_slimbus),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(edp_hot),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(lpass_slimbus),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pci_e0),
+ MSM_PIN_FUNCTION(pci_e1),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(pri_mi2s_ws),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss),
+ MSM_PIN_FUNCTION(qlink_enable),
+ MSM_PIN_FUNCTION(qlink_request),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qspi_data),
+ MSM_PIN_FUNCTION(qua_mi2s),
+ MSM_PIN_FUNCTION(qup0),
+ MSM_PIN_FUNCTION(qup1),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(qup15),
+ MSM_PIN_FUNCTION(qup2),
+ MSM_PIN_FUNCTION(qup3),
+ MSM_PIN_FUNCTION(qup4),
+ MSM_PIN_FUNCTION(qup5),
+ MSM_PIN_FUNCTION(qup6),
+ MSM_PIN_FUNCTION(qup7),
+ MSM_PIN_FUNCTION(qup8),
+ MSM_PIN_FUNCTION(qup9),
+ MSM_PIN_FUNCTION(qup_l4),
+ MSM_PIN_FUNCTION(qup_l5),
+ MSM_PIN_FUNCTION(qup_l6),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sdc4_data),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(sp_cmu),
+ MSM_PIN_FUNCTION(spkr_i2s),
+ MSM_PIN_FUNCTION(ter_mi2s),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(tsif1_clk),
+ MSM_PIN_FUNCTION(tsif1_data),
+ MSM_PIN_FUNCTION(tsif1_en),
+ MSM_PIN_FUNCTION(tsif1_error),
+ MSM_PIN_FUNCTION(tsif1_sync),
+ MSM_PIN_FUNCTION(tsif2_clk),
+ MSM_PIN_FUNCTION(tsif2_data),
+ MSM_PIN_FUNCTION(tsif2_en),
+ MSM_PIN_FUNCTION(tsif2_error),
+ MSM_PIN_FUNCTION(tsif2_sync),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(wlan1_adc1),
+ MSM_PIN_FUNCTION(wlan2_adc0),
+ MSM_PIN_FUNCTION(wlan2_adc1),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
diff --git a/drivers/pinctrl/qcom/pinctrl-sdx55.c b/drivers/pinctrl/qcom/pinctrl-sdx55.c
index 0bb4931cec59..8826db9d21d0 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdx55.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdx55.c
@@ -6,24 +6,16 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -60,9 +52,9 @@
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -765,91 +757,91 @@ static const char * const spmi_coex_groups[] = {
"gpio44", "gpio45",
};
-static const struct msm_function sdx55_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(atest),
- FUNCTION(audio_ref),
- FUNCTION(bimc_dte0),
- FUNCTION(bimc_dte1),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_uart3),
- FUNCTION(blsp_uart4),
- FUNCTION(char_exec),
- FUNCTION(coex_uart),
- FUNCTION(coex_uart2),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ebi0_wrcdc),
- FUNCTION(ebi2_a),
- FUNCTION(ebi2_lcd),
- FUNCTION(emac_gcc0),
- FUNCTION(emac_gcc1),
- FUNCTION(emac_pps0),
- FUNCTION(emac_pps1),
- FUNCTION(ext_dbg),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gcc_plltest),
- FUNCTION(gpio),
- FUNCTION(i2s_mclk),
- FUNCTION(jitter_bist),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(mgpi_clk),
- FUNCTION(m_voc),
- FUNCTION(native_char),
- FUNCTION(native_char0),
- FUNCTION(native_char1),
- FUNCTION(native_char2),
- FUNCTION(native_char3),
- FUNCTION(native_tsens),
- FUNCTION(native_tsense),
- FUNCTION(nav_gpio),
- FUNCTION(pa_indicator),
- FUNCTION(pcie_clkreq),
- FUNCTION(pci_e),
- FUNCTION(pll_bist),
- FUNCTION(pll_ref),
- FUNCTION(pll_test),
- FUNCTION(pri_mi2s),
- FUNCTION(prng_rosc),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qdss_stm),
- FUNCTION(qlink0_en),
- FUNCTION(qlink0_req),
- FUNCTION(qlink0_wmss),
- FUNCTION(qlink1_en),
- FUNCTION(qlink1_req),
- FUNCTION(qlink1_wmss),
- FUNCTION(spmi_coex),
- FUNCTION(sec_mi2s),
- FUNCTION(spmi_vgi),
- FUNCTION(tgu_ch0),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(usb2phy_ac),
- FUNCTION(vsense_trigger),
+static const struct pinfunction sdx55_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(atest),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(bimc_dte0),
+ MSM_PIN_FUNCTION(bimc_dte1),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(blsp_uart1),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(blsp_uart3),
+ MSM_PIN_FUNCTION(blsp_uart4),
+ MSM_PIN_FUNCTION(char_exec),
+ MSM_PIN_FUNCTION(coex_uart),
+ MSM_PIN_FUNCTION(coex_uart2),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ebi0_wrcdc),
+ MSM_PIN_FUNCTION(ebi2_a),
+ MSM_PIN_FUNCTION(ebi2_lcd),
+ MSM_PIN_FUNCTION(emac_gcc0),
+ MSM_PIN_FUNCTION(emac_gcc1),
+ MSM_PIN_FUNCTION(emac_pps0),
+ MSM_PIN_FUNCTION(emac_pps1),
+ MSM_PIN_FUNCTION(ext_dbg),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(i2s_mclk),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(mgpi_clk),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(native_char),
+ MSM_PIN_FUNCTION(native_char0),
+ MSM_PIN_FUNCTION(native_char1),
+ MSM_PIN_FUNCTION(native_char2),
+ MSM_PIN_FUNCTION(native_char3),
+ MSM_PIN_FUNCTION(native_tsens),
+ MSM_PIN_FUNCTION(native_tsense),
+ MSM_PIN_FUNCTION(nav_gpio),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pcie_clkreq),
+ MSM_PIN_FUNCTION(pci_e),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_ref),
+ MSM_PIN_FUNCTION(pll_test),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qdss_stm),
+ MSM_PIN_FUNCTION(qlink0_en),
+ MSM_PIN_FUNCTION(qlink0_req),
+ MSM_PIN_FUNCTION(qlink0_wmss),
+ MSM_PIN_FUNCTION(qlink1_en),
+ MSM_PIN_FUNCTION(qlink1_req),
+ MSM_PIN_FUNCTION(qlink1_wmss),
+ MSM_PIN_FUNCTION(spmi_coex),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(spmi_vgi),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(vsense_trigger),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
diff --git a/drivers/pinctrl/qcom/pinctrl-sdx65.c b/drivers/pinctrl/qcom/pinctrl-sdx65.c
index e793ea713965..f6f319c997fc 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdx65.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdx65.c
@@ -6,24 +6,16 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_BASE 0x0
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -60,9 +52,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -85,9 +77,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -700,90 +692,90 @@ static const char * const sdc1_tb_groups[] = {
"gpio106",
};
-static const struct msm_function sdx65_functions[] = {
- FUNCTION(qlink0_wmss),
- FUNCTION(adsp_ext),
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(audio_ref),
- FUNCTION(bimc_dte0),
- FUNCTION(bimc_dte1),
- FUNCTION(blsp_i2c1),
- FUNCTION(blsp_i2c2),
- FUNCTION(blsp_i2c3),
- FUNCTION(blsp_i2c4),
- FUNCTION(blsp_spi1),
- FUNCTION(blsp_spi2),
- FUNCTION(blsp_spi3),
- FUNCTION(blsp_spi4),
- FUNCTION(blsp_uart1),
- FUNCTION(blsp_uart2),
- FUNCTION(blsp_uart3),
- FUNCTION(blsp_uart4),
- FUNCTION(char_exec),
- FUNCTION(coex_uart),
- FUNCTION(coex_uart2),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ebi0_wrcdc),
- FUNCTION(ebi2_a),
- FUNCTION(ebi2_lcd),
- FUNCTION(ext_dbg),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gcc_plltest),
- FUNCTION(gpio),
- FUNCTION(i2s_mclk),
- FUNCTION(jitter_bist),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(m_voc),
- FUNCTION(mgpi_clk),
- FUNCTION(native_char),
- FUNCTION(native_tsens),
- FUNCTION(native_tsense),
- FUNCTION(nav_gpio),
- FUNCTION(pa_indicator),
- FUNCTION(pci_e),
- FUNCTION(pcie_clkreq),
- FUNCTION(pll_bist),
- FUNCTION(pll_ref),
- FUNCTION(pri_mi2s),
- FUNCTION(pri_mi2s_ws),
- FUNCTION(prng_rosc),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qlink0_en),
- FUNCTION(qlink0_req),
- FUNCTION(qlink1_en),
- FUNCTION(qlink1_req),
- FUNCTION(qlink1_wmss),
- FUNCTION(qlink2_en),
- FUNCTION(qlink2_req),
- FUNCTION(qlink2_wmss),
- FUNCTION(sdc1_tb),
- FUNCTION(sec_mi2s),
- FUNCTION(spmi_coex),
- FUNCTION(spmi_vgi),
- FUNCTION(tgu_ch0),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(usb2phy_ac),
- FUNCTION(vsense_trigger),
+static const struct pinfunction sdx65_functions[] = {
+ MSM_PIN_FUNCTION(qlink0_wmss),
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(bimc_dte0),
+ MSM_PIN_FUNCTION(bimc_dte1),
+ MSM_PIN_FUNCTION(blsp_i2c1),
+ MSM_PIN_FUNCTION(blsp_i2c2),
+ MSM_PIN_FUNCTION(blsp_i2c3),
+ MSM_PIN_FUNCTION(blsp_i2c4),
+ MSM_PIN_FUNCTION(blsp_spi1),
+ MSM_PIN_FUNCTION(blsp_spi2),
+ MSM_PIN_FUNCTION(blsp_spi3),
+ MSM_PIN_FUNCTION(blsp_spi4),
+ MSM_PIN_FUNCTION(blsp_uart1),
+ MSM_PIN_FUNCTION(blsp_uart2),
+ MSM_PIN_FUNCTION(blsp_uart3),
+ MSM_PIN_FUNCTION(blsp_uart4),
+ MSM_PIN_FUNCTION(char_exec),
+ MSM_PIN_FUNCTION(coex_uart),
+ MSM_PIN_FUNCTION(coex_uart2),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ebi0_wrcdc),
+ MSM_PIN_FUNCTION(ebi2_a),
+ MSM_PIN_FUNCTION(ebi2_lcd),
+ MSM_PIN_FUNCTION(ext_dbg),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(i2s_mclk),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mgpi_clk),
+ MSM_PIN_FUNCTION(native_char),
+ MSM_PIN_FUNCTION(native_tsens),
+ MSM_PIN_FUNCTION(native_tsense),
+ MSM_PIN_FUNCTION(nav_gpio),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pci_e),
+ MSM_PIN_FUNCTION(pcie_clkreq),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_ref),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(pri_mi2s_ws),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qlink0_en),
+ MSM_PIN_FUNCTION(qlink0_req),
+ MSM_PIN_FUNCTION(qlink1_en),
+ MSM_PIN_FUNCTION(qlink1_req),
+ MSM_PIN_FUNCTION(qlink1_wmss),
+ MSM_PIN_FUNCTION(qlink2_en),
+ MSM_PIN_FUNCTION(qlink2_req),
+ MSM_PIN_FUNCTION(qlink2_wmss),
+ MSM_PIN_FUNCTION(sdc1_tb),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(spmi_coex),
+ MSM_PIN_FUNCTION(spmi_vgi),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(vsense_trigger),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
diff --git a/drivers/pinctrl/qcom/pinctrl-sdx75.c b/drivers/pinctrl/qcom/pinctrl-sdx75.c
new file mode 100644
index 000000000000..2ade7866dbc5
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-sdx75.c
@@ -0,0 +1,1144 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "pinctrl-msm.h"
+
+#define REG_BASE 0x100000
+#define REG_SIZE 0x1000
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \
+ { \
+ .grp = PINCTRL_PINGROUP("gpio"#id, gpio##id##_pins, \
+ (unsigned int)ARRAY_SIZE(gpio##id##_pins)), \
+ .ctl_reg = REG_BASE + REG_SIZE * id, \
+ .io_reg = REG_BASE + 0x4 + REG_SIZE * id, \
+ .intr_cfg_reg = REG_BASE + 0x8 + REG_SIZE * id, \
+ .intr_status_reg = REG_BASE + 0xc + REG_SIZE * id, \
+ .intr_target_reg = REG_BASE + 0x8 + REG_SIZE * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .egpio_enable = 12, \
+ .egpio_present = 11, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 3, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9, \
+ msm_mux_##f10 \
+ }, \
+ .nfuncs = 11, \
+ }
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
+ { \
+ .grp = PINCTRL_PINGROUP(#pg_name, pg_name##_pins, \
+ (unsigned int)ARRAY_SIZE(pg_name##_pins)), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+static const struct pinctrl_pin_desc sdx75_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+ PINCTRL_PIN(128, "GPIO_128"),
+ PINCTRL_PIN(129, "GPIO_129"),
+ PINCTRL_PIN(130, "GPIO_130"),
+ PINCTRL_PIN(131, "GPIO_131"),
+ PINCTRL_PIN(132, "GPIO_132"),
+ PINCTRL_PIN(133, "SDC1_RCLK"),
+ PINCTRL_PIN(134, "SDC1_CLK"),
+ PINCTRL_PIN(135, "SDC1_CMD"),
+ PINCTRL_PIN(136, "SDC1_DATA"),
+ PINCTRL_PIN(137, "SDC2_CLK"),
+ PINCTRL_PIN(138, "SDC2_CMD"),
+ PINCTRL_PIN(139, "SDC2_DATA"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = {pin}
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+
+static const unsigned int sdc1_rclk_pins[] = {133};
+static const unsigned int sdc1_clk_pins[] = {134};
+static const unsigned int sdc1_cmd_pins[] = {135};
+static const unsigned int sdc1_data_pins[] = {136};
+static const unsigned int sdc2_clk_pins[] = {137};
+static const unsigned int sdc2_cmd_pins[] = {138};
+static const unsigned int sdc2_data_pins[] = {139};
+
+enum sdx75_functions {
+ msm_mux_adsp_ext,
+ msm_mux_atest_char,
+ msm_mux_audio_ref_clk,
+ msm_mux_bimc_dte,
+ msm_mux_char_exec,
+ msm_mux_coex_uart2,
+ msm_mux_coex_uart,
+ msm_mux_cri_trng,
+ msm_mux_cri_trng0,
+ msm_mux_cri_trng1,
+ msm_mux_dbg_out_clk,
+ msm_mux_ddr_bist,
+ msm_mux_ddr_pxi0,
+ msm_mux_ebi0_wrcdc,
+ msm_mux_ebi2_a,
+ msm_mux_ebi2_lcd,
+ msm_mux_ebi2_lcd_te,
+ msm_mux_emac0_mcg,
+ msm_mux_emac0_ptp,
+ msm_mux_emac1_mcg,
+ msm_mux_emac1_ptp,
+ msm_mux_emac_cdc,
+ msm_mux_emac_pps_in,
+ msm_mux_eth0_mdc,
+ msm_mux_eth0_mdio,
+ msm_mux_eth1_mdc,
+ msm_mux_eth1_mdio,
+ msm_mux_ext_dbg,
+ msm_mux_gcc_125_clk,
+ msm_mux_gcc_gp1_clk,
+ msm_mux_gcc_gp2_clk,
+ msm_mux_gcc_gp3_clk,
+ msm_mux_gcc_plltest,
+ msm_mux_gpio,
+ msm_mux_i2s_mclk,
+ msm_mux_jitter_bist,
+ msm_mux_ldo_en,
+ msm_mux_ldo_update,
+ msm_mux_m_voc,
+ msm_mux_mgpi_clk,
+ msm_mux_native_char,
+ msm_mux_native_tsens,
+ msm_mux_native_tsense,
+ msm_mux_nav_dr_sync,
+ msm_mux_nav_gpio,
+ msm_mux_pa_indicator,
+ msm_mux_pci_e,
+ msm_mux_pcie0_clkreq_n,
+ msm_mux_pcie1_clkreq_n,
+ msm_mux_pcie2_clkreq_n,
+ msm_mux_pll_bist_sync,
+ msm_mux_pll_clk_aux,
+ msm_mux_pll_ref_clk,
+ msm_mux_pri_mi2s,
+ msm_mux_prng_rosc,
+ msm_mux_qdss_cti,
+ msm_mux_qdss_gpio,
+ msm_mux_qlink0_b_en,
+ msm_mux_qlink0_b_req,
+ msm_mux_qlink0_l_en,
+ msm_mux_qlink0_l_req,
+ msm_mux_qlink0_wmss,
+ msm_mux_qlink1_l_en,
+ msm_mux_qlink1_l_req,
+ msm_mux_qlink1_wmss,
+ msm_mux_qup_se0,
+ msm_mux_qup_se1_l2_mira,
+ msm_mux_qup_se1_l2_mirb,
+ msm_mux_qup_se1_l3_mira,
+ msm_mux_qup_se1_l3_mirb,
+ msm_mux_qup_se2,
+ msm_mux_qup_se3,
+ msm_mux_qup_se4,
+ msm_mux_qup_se5,
+ msm_mux_qup_se6,
+ msm_mux_qup_se7,
+ msm_mux_qup_se8,
+ msm_mux_rgmii_rx_ctl,
+ msm_mux_rgmii_rxc,
+ msm_mux_rgmii_rxd,
+ msm_mux_rgmii_tx_ctl,
+ msm_mux_rgmii_txc,
+ msm_mux_rgmii_txd,
+ msm_mux_sd_card,
+ msm_mux_sdc1_tb,
+ msm_mux_sdc2_tb_trig,
+ msm_mux_sec_mi2s,
+ msm_mux_sgmii_phy_intr0_n,
+ msm_mux_sgmii_phy_intr1_n,
+ msm_mux_spmi_coex,
+ msm_mux_spmi_vgi,
+ msm_mux_tgu_ch0_trigout,
+ msm_mux_tmess_prng0,
+ msm_mux_tmess_prng1,
+ msm_mux_tmess_prng2,
+ msm_mux_tmess_prng3,
+ msm_mux_tri_mi2s,
+ msm_mux_uim1_clk,
+ msm_mux_uim1_data,
+ msm_mux_uim1_present,
+ msm_mux_uim1_reset,
+ msm_mux_uim2_clk,
+ msm_mux_uim2_data,
+ msm_mux_uim2_present,
+ msm_mux_uim2_reset,
+ msm_mux_usb2phy_ac_en,
+ msm_mux_vsense_trigger_mirnat,
+ msm_mux__,
+};
+
+static const char *const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6",
+ "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13",
+ "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20",
+ "gpio21", "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27",
+ "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34",
+ "gpio35", "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41",
+ "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48",
+ "gpio49", "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55",
+ "gpio56", "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62",
+ "gpio63", "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69",
+ "gpio70", "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76",
+ "gpio77", "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83",
+ "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90",
+ "gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97",
+ "gpio98", "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+ "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110", "gpio111",
+ "gpio112", "gpio113", "gpio114", "gpio115", "gpio116", "gpio117", "gpio118",
+ "gpio119", "gpio120", "gpio121", "gpio122", "gpio123", "gpio124", "gpio125",
+ "gpio126", "gpio127", "gpio128", "gpio129", "gpio130", "gpio131", "gpio132",
+};
+static const char *const adsp_ext_groups[] = {
+ "gpio59", "gpio68",
+};
+static const char *const atest_char_groups[] = {
+ "gpio24", "gpio25", "gpio26", "gpio41", "gpio63",
+};
+static const char *const audio_ref_clk_groups[] = {
+ "gpio126",
+};
+static const char *const bimc_dte_groups[] = {
+ "gpio14", "gpio15", "gpio61", "gpio59",
+};
+static const char *const char_exec_groups[] = {
+ "gpio6", "gpio7",
+};
+static const char *const coex_uart2_groups[] = {
+ "gpio48", "gpio49", "gpio90", "gpio91",
+};
+static const char *const coex_uart_groups[] = {
+ "gpio46", "gpio47",
+};
+static const char *const cri_trng_groups[] = {
+ "gpio36",
+};
+static const char *const cri_trng0_groups[] = {
+ "gpio31",
+};
+static const char *const cri_trng1_groups[] = {
+ "gpio32",
+};
+static const char *const dbg_out_clk_groups[] = {
+ "gpio26",
+};
+static const char *const ddr_bist_groups[] = {
+ "gpio46", "gpio47", "gpio48", "gpio49",
+};
+static const char *const ddr_pxi0_groups[] = {
+ "gpio45", "gpio46",
+};
+static const char *const ebi0_wrcdc_groups[] = {
+ "gpio0", "gpio2",
+};
+static const char *const ebi2_a_groups[] = {
+ "gpio100",
+};
+static const char *const ebi2_lcd_groups[] = {
+ "gpio99", "gpio101",
+};
+static const char *const ebi2_lcd_te_groups[] = {
+ "gpio98",
+};
+static const char *const emac0_mcg_groups[] = {
+ "gpio83", "gpio84", "gpio85", "gpio89",
+};
+static const char *const emac0_ptp_groups[] = {
+ "gpio35", "gpio83", "gpio84", "gpio85", "gpio89", "gpio119", "gpio123",
+};
+static const char *const emac1_mcg_groups[] = {
+ "gpio90", "gpio92", "gpio93", "gpio122",
+};
+static const char *const emac1_ptp_groups[] = {
+ "gpio112", "gpio113", "gpio114", "gpio115",
+};
+static const char *const emac_cdc_groups[] = {
+ "gpio38", "gpio39",
+};
+static const char *const emac_pps_in_groups[] = {
+ "gpio127",
+};
+static const char *const eth0_mdc_groups[] = {
+ "gpio94",
+};
+static const char *const eth0_mdio_groups[] = {
+ "gpio95",
+};
+static const char *const eth1_mdc_groups[] = {
+ "gpio106",
+};
+static const char *const eth1_mdio_groups[] = {
+ "gpio107",
+};
+static const char *const ext_dbg_groups[] = {
+ "gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char *const gcc_125_clk_groups[] = {
+ "gpio25",
+};
+static const char *const gcc_gp1_clk_groups[] = {
+ "gpio39",
+};
+static const char *const gcc_gp2_clk_groups[] = {
+ "gpio40",
+};
+static const char *const gcc_gp3_clk_groups[] = {
+ "gpio41",
+};
+static const char *const gcc_plltest_groups[] = {
+ "gpio81", "gpio82",
+};
+static const char *const i2s_mclk_groups[] = {
+ "gpio74",
+};
+static const char *const jitter_bist_groups[] = {
+ "gpio41",
+};
+static const char *const ldo_en_groups[] = {
+ "gpio8",
+};
+static const char *const ldo_update_groups[] = {
+ "gpio62",
+};
+static const char *const m_voc_groups[] = {
+ "gpio62", "gpio63", "gpio64", "gpio65", "gpio71",
+};
+static const char *const mgpi_clk_groups[] = {
+ "gpio39", "gpio40",
+};
+static const char *const native_char_groups[] = {
+ "gpio29", "gpio33", "gpio57", "gpio66", "gpio67",
+};
+static const char *const native_tsens_groups[] = {
+ "gpio38",
+};
+static const char *const native_tsense_groups[] = {
+ "gpio64", "gpio76",
+};
+static const char *const nav_dr_sync_groups[] = {
+ "gpio36",
+};
+static const char *const nav_gpio_groups[] = {
+ "gpio35", "gpio36", "gpio104",
+};
+static const char *const pa_indicator_groups[] = {
+ "gpio58",
+};
+static const char *const pci_e_groups[] = {
+ "gpio42",
+};
+static const char *const pcie0_clkreq_n_groups[] = {
+ "gpio43",
+};
+static const char *const pcie1_clkreq_n_groups[] = {
+ "gpio124",
+};
+static const char *const pcie2_clkreq_n_groups[] = {
+ "gpio121",
+};
+static const char *const pll_bist_sync_groups[] = {
+ "gpio38",
+};
+static const char *const pll_clk_aux_groups[] = {
+ "gpio40",
+};
+static const char *const pll_ref_clk_groups[] = {
+ "gpio37",
+};
+static const char *const pri_mi2s_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19",
+};
+static const char *const prng_rosc_groups[] = {
+ "gpio27", "gpio36", "gpio37", "gpio38",
+};
+static const char *const qdss_cti_groups[] = {
+ "gpio16", "gpio17", "gpio52", "gpio53", "gpio56",
+ "gpio57", "gpio59", "gpio60", "gpio78", "gpio79",
+};
+static const char *const qdss_gpio_groups[] = {
+ "gpio82", "gpio83", "gpio84", "gpio85", "gpio94",
+ "gpio95", "gpio96", "gpio97", "gpio110", "gpio111",
+ "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+ "gpio117", "gpio118", "gpio119",
+};
+static const char *const qlink0_b_en_groups[] = {
+ "gpio40",
+};
+static const char *const qlink0_b_req_groups[] = {
+ "gpio41",
+};
+static const char *const qlink0_l_en_groups[] = {
+ "gpio37",
+};
+static const char *const qlink0_l_req_groups[] = {
+ "gpio38",
+};
+static const char *const qlink0_wmss_groups[] = {
+ "gpio39",
+};
+static const char *const qlink1_l_en_groups[] = {
+ "gpio26",
+};
+static const char *const qlink1_l_req_groups[] = {
+ "gpio27",
+};
+static const char *const qlink1_wmss_groups[] = {
+ "gpio28",
+};
+static const char *const qup_se0_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char *const qup_se1_l2_mira_groups[] = {
+ "gpio12",
+};
+static const char *const qup_se1_l2_mirb_groups[] = {
+ "gpio16",
+};
+static const char *const qup_se1_l3_mira_groups[] = {
+ "gpio13",
+};
+static const char *const qup_se1_l3_mirb_groups[] = {
+ "gpio17",
+};
+static const char *const qup_se2_groups[] = {
+ "gpio14", "gpio15", "gpio16", "gpio17",
+};
+static const char *const qup_se3_groups[] = {
+ "gpio52", "gpio53", "gpio54", "gpio55",
+};
+static const char *const qup_se4_groups[] = {
+ "gpio64", "gpio65",
+};
+static const char *const qup_se5_groups[] = {
+ "gpio110", "gpio111",
+};
+static const char *const qup_se6_groups[] = {
+ "gpio112", "gpio113", "gpio114", "gpio115",
+};
+static const char *const qup_se7_groups[] = {
+ "gpio116", "gpio117", "gpio118", "gpio119",
+};
+static const char *const qup_se8_groups[] = {
+ "gpio124", "gpio125",
+};
+static const char *const rgmii_rx_ctl_groups[] = {
+ "gpio93",
+};
+static const char *const rgmii_rxc_groups[] = {
+ "gpio88",
+};
+static const char *const rgmii_rxd_groups[] = {
+ "gpio89", "gpio90", "gpio91", "gpio92",
+};
+static const char *const rgmii_tx_ctl_groups[] = {
+ "gpio87",
+};
+static const char *const rgmii_txc_groups[] = {
+ "gpio82",
+};
+static const char *const rgmii_txd_groups[] = {
+ "gpio83", "gpio84", "gpio85", "gpio86",
+};
+static const char *const sd_card_groups[] = {
+ "gpio105",
+};
+static const char *const sdc1_tb_groups[] = {
+ "gpio84", "gpio130",
+};
+static const char *const sdc2_tb_trig_groups[] = {
+ "gpio129",
+};
+static const char *const sec_mi2s_groups[] = {
+ "gpio20", "gpio21", "gpio22", "gpio23",
+};
+static const char *const sgmii_phy_intr0_n_groups[] = {
+ "gpio97",
+};
+static const char *const sgmii_phy_intr1_n_groups[] = {
+ "gpio109",
+};
+static const char *const spmi_coex_groups[] = {
+ "gpio48", "gpio49",
+};
+static const char *const spmi_vgi_groups[] = {
+ "gpio50", "gpio51",
+};
+static const char *const tgu_ch0_trigout_groups[] = {
+ "gpio55",
+};
+static const char *const tmess_prng0_groups[] = {
+ "gpio28",
+};
+static const char *const tmess_prng1_groups[] = {
+ "gpio29",
+};
+static const char *const tmess_prng2_groups[] = {
+ "gpio30",
+};
+static const char *const tmess_prng3_groups[] = {
+ "gpio31",
+};
+static const char *const tri_mi2s_groups[] = {
+ "gpio98", "gpio99", "gpio100", "gpio101",
+};
+static const char *const uim1_clk_groups[] = {
+ "gpio7",
+};
+static const char *const uim1_data_groups[] = {
+ "gpio4",
+};
+static const char *const uim1_present_groups[] = {
+ "gpio5",
+};
+static const char *const uim1_reset_groups[] = {
+ "gpio6",
+};
+static const char *const uim2_clk_groups[] = {
+ "gpio3",
+};
+static const char *const uim2_data_groups[] = {
+ "gpio0",
+};
+static const char *const uim2_present_groups[] = {
+ "gpio1",
+};
+static const char *const uim2_reset_groups[] = {
+ "gpio2",
+};
+static const char *const usb2phy_ac_en_groups[] = {
+ "gpio80",
+};
+static const char *const vsense_trigger_mirnat_groups[] = {
+ "gpio37",
+};
+
+static const struct pinfunction sdx75_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(audio_ref_clk),
+ MSM_PIN_FUNCTION(bimc_dte),
+ MSM_PIN_FUNCTION(char_exec),
+ MSM_PIN_FUNCTION(coex_uart2),
+ MSM_PIN_FUNCTION(coex_uart),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out_clk),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ebi0_wrcdc),
+ MSM_PIN_FUNCTION(ebi2_a),
+ MSM_PIN_FUNCTION(ebi2_lcd),
+ MSM_PIN_FUNCTION(ebi2_lcd_te),
+ MSM_PIN_FUNCTION(emac0_mcg),
+ MSM_PIN_FUNCTION(emac0_ptp),
+ MSM_PIN_FUNCTION(emac1_mcg),
+ MSM_PIN_FUNCTION(emac1_ptp),
+ MSM_PIN_FUNCTION(emac_cdc),
+ MSM_PIN_FUNCTION(emac_pps_in),
+ MSM_PIN_FUNCTION(eth0_mdc),
+ MSM_PIN_FUNCTION(eth0_mdio),
+ MSM_PIN_FUNCTION(eth1_mdc),
+ MSM_PIN_FUNCTION(eth1_mdio),
+ MSM_PIN_FUNCTION(ext_dbg),
+ MSM_PIN_FUNCTION(gcc_125_clk),
+ MSM_PIN_FUNCTION(gcc_gp1_clk),
+ MSM_PIN_FUNCTION(gcc_gp2_clk),
+ MSM_PIN_FUNCTION(gcc_gp3_clk),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(i2s_mclk),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mgpi_clk),
+ MSM_PIN_FUNCTION(native_char),
+ MSM_PIN_FUNCTION(native_tsens),
+ MSM_PIN_FUNCTION(native_tsense),
+ MSM_PIN_FUNCTION(nav_dr_sync),
+ MSM_PIN_FUNCTION(nav_gpio),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pci_e),
+ MSM_PIN_FUNCTION(pcie0_clkreq_n),
+ MSM_PIN_FUNCTION(pcie1_clkreq_n),
+ MSM_PIN_FUNCTION(pcie2_clkreq_n),
+ MSM_PIN_FUNCTION(pll_bist_sync),
+ MSM_PIN_FUNCTION(pll_clk_aux),
+ MSM_PIN_FUNCTION(pll_ref_clk),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qlink0_b_en),
+ MSM_PIN_FUNCTION(qlink0_b_req),
+ MSM_PIN_FUNCTION(qlink0_l_en),
+ MSM_PIN_FUNCTION(qlink0_l_req),
+ MSM_PIN_FUNCTION(qlink1_l_en),
+ MSM_PIN_FUNCTION(qlink1_l_req),
+ MSM_PIN_FUNCTION(qlink0_wmss),
+ MSM_PIN_FUNCTION(qlink1_wmss),
+ MSM_PIN_FUNCTION(qup_se0),
+ MSM_PIN_FUNCTION(qup_se1_l2_mira),
+ MSM_PIN_FUNCTION(qup_se1_l2_mirb),
+ MSM_PIN_FUNCTION(qup_se1_l3_mira),
+ MSM_PIN_FUNCTION(qup_se1_l3_mirb),
+ MSM_PIN_FUNCTION(qup_se2),
+ MSM_PIN_FUNCTION(qup_se3),
+ MSM_PIN_FUNCTION(qup_se4),
+ MSM_PIN_FUNCTION(qup_se5),
+ MSM_PIN_FUNCTION(qup_se6),
+ MSM_PIN_FUNCTION(qup_se7),
+ MSM_PIN_FUNCTION(qup_se8),
+ MSM_PIN_FUNCTION(rgmii_rx_ctl),
+ MSM_PIN_FUNCTION(rgmii_rxc),
+ MSM_PIN_FUNCTION(rgmii_rxd),
+ MSM_PIN_FUNCTION(rgmii_tx_ctl),
+ MSM_PIN_FUNCTION(rgmii_txc),
+ MSM_PIN_FUNCTION(rgmii_txd),
+ MSM_PIN_FUNCTION(sd_card),
+ MSM_PIN_FUNCTION(sdc1_tb),
+ MSM_PIN_FUNCTION(sdc2_tb_trig),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(sgmii_phy_intr0_n),
+ MSM_PIN_FUNCTION(sgmii_phy_intr1_n),
+ MSM_PIN_FUNCTION(spmi_coex),
+ MSM_PIN_FUNCTION(spmi_vgi),
+ MSM_PIN_FUNCTION(tgu_ch0_trigout),
+ MSM_PIN_FUNCTION(tmess_prng0),
+ MSM_PIN_FUNCTION(tmess_prng1),
+ MSM_PIN_FUNCTION(tmess_prng2),
+ MSM_PIN_FUNCTION(tmess_prng3),
+ MSM_PIN_FUNCTION(tri_mi2s),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(usb2phy_ac_en),
+ MSM_PIN_FUNCTION(vsense_trigger_mirnat),
+};
+
+static const struct msm_pingroup sdx75_groups[] = {
+ [0] = PINGROUP(0, uim2_data, ebi0_wrcdc, _, _, _, _, _, _, _, _),
+ [1] = PINGROUP(1, uim2_present, _, _, _, _, _, _, _, _, _),
+ [2] = PINGROUP(2, uim2_reset, ebi0_wrcdc, _, _, _, _, _, _, _, _),
+ [3] = PINGROUP(3, uim2_clk, _, _, _, _, _, _, _, _, _),
+ [4] = PINGROUP(4, uim1_data, _, _, _, _, _, _, _, _, _),
+ [5] = PINGROUP(5, uim1_present, _, _, _, _, _, _, _, _, _),
+ [6] = PINGROUP(6, uim1_reset, char_exec, _, _, _, _, _, _, _, _),
+ [7] = PINGROUP(7, uim1_clk, char_exec, _, _, _, _, _, _, _, _),
+ [8] = PINGROUP(8, qup_se0, ldo_en, _, _, _, _, _, _, _, _),
+ [9] = PINGROUP(9, qup_se0, _, _, _, _, _, _, _, _, _),
+ [10] = PINGROUP(10, qup_se0, _, _, _, _, _, _, _, _, _),
+ [11] = PINGROUP(11, qup_se0, _, _, _, _, _, _, _, _, _),
+ [12] = PINGROUP(12, qup_se1_l2_mira, ext_dbg, _, _, _, _, _, _, _, _),
+ [13] = PINGROUP(13, qup_se1_l3_mira, ext_dbg, _, _, _, _, _, _, _, _),
+ [14] = PINGROUP(14, qup_se2, ext_dbg, bimc_dte, _, _, _, _, _, _, _),
+ [15] = PINGROUP(15, qup_se2, ext_dbg, bimc_dte, _, _, _, _, _, _, _),
+ [16] = PINGROUP(16, pri_mi2s, qup_se2, qup_se1_l2_mirb, qdss_cti, qdss_cti, _, _, _, _, _),
+ [17] = PINGROUP(17, pri_mi2s, qup_se2, qup_se1_l3_mirb, qdss_cti, qdss_cti, _, _, _, _, _),
+ [18] = PINGROUP(18, pri_mi2s, _, _, _, _, _, _, _, _, _),
+ [19] = PINGROUP(19, pri_mi2s, _, _, _, _, _, _, _, _, _),
+ [20] = PINGROUP(20, sec_mi2s, _, _, _, _, _, _, _, _, _),
+ [21] = PINGROUP(21, sec_mi2s, _, _, _, _, _, _, _, _, _),
+ [22] = PINGROUP(22, sec_mi2s, _, _, _, _, _, _, _, _, _),
+ [23] = PINGROUP(23, sec_mi2s, _, _, _, _, _, _, _, _, _),
+ [24] = PINGROUP(24, _, atest_char, _, _, _, _, _, _, _, _),
+ [25] = PINGROUP(25, gcc_125_clk, _, atest_char, _, _, _, _, _, _, _),
+ [26] = PINGROUP(26, _, _, qlink1_l_en, dbg_out_clk, atest_char, _, _, _, _, _),
+ [27] = PINGROUP(27, _, _, qlink1_l_req, prng_rosc, _, _, _, _, _, _),
+ [28] = PINGROUP(28, _, qlink1_wmss, tmess_prng0, _, _, _, _, _, _, _),
+ [29] = PINGROUP(29, _, _, _, native_char, tmess_prng1, _, _, _, _, _),
+ [30] = PINGROUP(30, _, _, _, tmess_prng2, _, _, _, _, _, _),
+ [31] = PINGROUP(31, _, _, cri_trng0, _, tmess_prng3, _, _, _, _, _),
+ [32] = PINGROUP(32, _, _, cri_trng1, _, _, _, _, _, _, _),
+ [33] = PINGROUP(33, _, _, native_char, _, _, _, _, _, _, _),
+ [34] = PINGROUP(34, _, _, _, _, _, _, _, _, _, _),
+ [35] = PINGROUP(35, nav_gpio, emac0_ptp, emac0_ptp, _, _, _, _, _, _, _),
+ [36] = PINGROUP(36, nav_gpio, nav_dr_sync, nav_gpio, cri_trng, prng_rosc, _, _, _, _, _),
+ [37] = PINGROUP(37, qlink0_l_en, _, pll_ref_clk, prng_rosc, vsense_trigger_mirnat, _, _, _, _, _),
+ [38] = PINGROUP(38, qlink0_l_req, _, pll_bist_sync, prng_rosc, _, emac_cdc, _, native_tsens, _, _),
+ [39] = PINGROUP(39, qlink0_wmss, _, mgpi_clk, gcc_gp1_clk, _, emac_cdc, _, _, _, _),
+ [40] = PINGROUP(40, qlink0_b_en, _, mgpi_clk, pll_clk_aux, gcc_gp2_clk, _, _, _, _, _),
+ [41] = PINGROUP(41, qlink0_b_req, _, jitter_bist, gcc_gp3_clk, _, _, atest_char, _, _, _),
+ [42] = PINGROUP(42, pci_e, _, _, _, _, _, _, _, _, _),
+ [43] = PINGROUP(43, pcie0_clkreq_n, _, _, _, _, _, _, _, _, _),
+ [44] = PINGROUP(44, _, _, _, _, _, _, _, _, _, _),
+ [45] = PINGROUP(45, ddr_pxi0, _, _, _, _, _, _, _, _, _),
+ [46] = PINGROUP(46, coex_uart, ddr_bist, ddr_pxi0, _, _, _, _, _, _, _),
+ [47] = PINGROUP(47, coex_uart, ddr_bist, _, _, _, _, _, _, _, _),
+ [48] = PINGROUP(48, coex_uart2, spmi_coex, ddr_bist, _, _, _, _, _, _, _),
+ [49] = PINGROUP(49, coex_uart2, spmi_coex, ddr_bist, _, _, _, _, _, _, _),
+ [50] = PINGROUP(50, spmi_vgi, _, _, _, _, _, _, _, _, _),
+ [51] = PINGROUP(51, spmi_vgi, _, _, _, _, _, _, _, _, _),
+ [52] = PINGROUP(52, qup_se3, qdss_cti, qdss_cti, _, _, _, _, _, _, _),
+ [53] = PINGROUP(53, qup_se3, qdss_cti, qdss_cti, _, _, _, _, _, _, _),
+ [54] = PINGROUP(54, qup_se3, _, _, _, _, _, _, _, _, _),
+ [55] = PINGROUP(55, qup_se3, tgu_ch0_trigout, _, _, _, _, _, _, _, _),
+ [56] = PINGROUP(56, qdss_cti, qdss_cti, _, _, _, _, _, _, _, _),
+ [57] = PINGROUP(57, qdss_cti, qdss_cti, _, native_char, _, _, _, _, _, _),
+ [58] = PINGROUP(58, _, pa_indicator, _, _, _, _, _, _, _, _),
+ [59] = PINGROUP(59, adsp_ext, qdss_cti, _, bimc_dte, _, _, _, _, _, _),
+ [60] = PINGROUP(60, qdss_cti, _, _, _, _, _, _, _, _, _),
+ [61] = PINGROUP(61, _, bimc_dte, _, _, _, _, _, _, _, _),
+ [62] = PINGROUP(62, m_voc, ldo_update, _, _, _, _, _, _, _, _),
+ [63] = PINGROUP(63, m_voc, _, atest_char, _, _, _, _, _, _, _),
+ [64] = PINGROUP(64, qup_se4, m_voc, _, native_tsense, _, _, _, _, _, _),
+ [65] = PINGROUP(65, qup_se4, m_voc, _, _, _, _, _, _, _, _),
+ [66] = PINGROUP(66, _, native_char, _, _, _, _, _, _, _, _),
+ [67] = PINGROUP(67, _, native_char, _, _, _, _, _, _, _, _),
+ [68] = PINGROUP(68, adsp_ext, _, _, _, _, _, _, _, _, _),
+ [69] = PINGROUP(69, _, _, _, _, _, _, _, _, _, _),
+ [70] = PINGROUP(70, _, _, _, _, _, _, _, _, _, _),
+ [71] = PINGROUP(71, m_voc, _, _, _, _, _, _, _, _, _),
+ [72] = PINGROUP(72, _, _, _, _, _, _, _, _, _, _),
+ [73] = PINGROUP(73, _, _, _, _, _, _, _, _, _, _),
+ [74] = PINGROUP(74, i2s_mclk, _, _, _, _, _, _, _, _, _),
+ [75] = PINGROUP(75, _, _, _, _, _, _, _, _, _, _),
+ [76] = PINGROUP(76, native_tsense, _, _, _, _, _, _, _, _, _),
+ [77] = PINGROUP(77, _, _, _, _, _, _, _, _, _, _),
+ [78] = PINGROUP(78, qdss_cti, qdss_cti, _, _, _, _, _, _, _, _),
+ [79] = PINGROUP(79, qdss_cti, qdss_cti, _, _, _, _, _, _, _, _),
+ [80] = PINGROUP(80, usb2phy_ac_en, _, _, _, _, _, _, _, _, _),
+ [81] = PINGROUP(81, gcc_plltest, _, _, _, _, _, _, _, _, _),
+ [82] = PINGROUP(82, rgmii_txc, gcc_plltest, qdss_gpio, _, _, _, _, _, _, _),
+ [83] = PINGROUP(83, rgmii_txd, emac0_ptp, emac0_ptp, emac0_mcg, qdss_gpio, _, _, _, _, _),
+ [84] = PINGROUP(84, rgmii_txd, emac0_ptp, emac0_mcg, qdss_gpio, _, sdc1_tb, _, _, _, _),
+ [85] = PINGROUP(85, rgmii_txd, emac0_ptp, emac0_mcg, qdss_gpio, _, _, _, _, _, _),
+ [86] = PINGROUP(86, rgmii_txd, _, _, _, _, _, _, _, _, _),
+ [87] = PINGROUP(87, rgmii_tx_ctl, _, _, _, _, _, _, _, _, _),
+ [88] = PINGROUP(88, rgmii_rxc, _, _, _, _, _, _, _, _, _),
+ [89] = PINGROUP(89, rgmii_rxd, emac0_ptp, emac0_ptp, emac0_mcg, _, _, _, _, _, _),
+ [90] = PINGROUP(90, rgmii_rxd, coex_uart2, emac1_mcg, _, _, _, _, _, _, _),
+ [91] = PINGROUP(91, rgmii_rxd, coex_uart2, _, _, _, _, _, _, _, _),
+ [92] = PINGROUP(92, rgmii_rxd, emac1_mcg, _, _, _, _, _, _, _, _),
+ [93] = PINGROUP(93, rgmii_rx_ctl, emac1_mcg, _, _, _, _, _, _, _, _),
+ [94] = PINGROUP(94, eth0_mdc, qdss_gpio, _, _, _, _, _, _, _, _),
+ [95] = PINGROUP(95, eth0_mdio, qdss_gpio, _, _, _, _, _, _, _, _),
+ [96] = PINGROUP(96, qdss_gpio, _, _, _, _, _, _, _, _, _),
+ [97] = PINGROUP(97, sgmii_phy_intr0_n, _, qdss_gpio, _, _, _, _, _, _, _),
+ [98] = PINGROUP(98, tri_mi2s, ebi2_lcd_te, _, _, _, _, _, _, _, _),
+ [99] = PINGROUP(99, tri_mi2s, ebi2_lcd, _, _, _, _, _, _, _, _),
+ [100] = PINGROUP(100, tri_mi2s, ebi2_a, _, _, _, _, _, _, _, _),
+ [101] = PINGROUP(101, tri_mi2s, ebi2_lcd, _, _, _, _, _, _, _, _),
+ [102] = PINGROUP(102, _, _, _, _, _, _, _, _, _, _),
+ [103] = PINGROUP(103, _, _, _, _, _, _, _, _, _, _),
+ [104] = PINGROUP(104, nav_gpio, _, _, _, _, _, _, _, _, _),
+ [105] = PINGROUP(105, sd_card, _, _, _, _, _, _, _, _, _),
+ [106] = PINGROUP(106, eth1_mdc, _, _, _, _, _, _, _, _, _),
+ [107] = PINGROUP(107, eth1_mdio, _, _, _, _, _, _, _, _, _),
+ [108] = PINGROUP(108, _, _, _, _, _, _, _, _, _, _),
+ [109] = PINGROUP(109, sgmii_phy_intr1_n, _, _, _, _, _, _, _, _, _),
+ [110] = PINGROUP(110, qup_se5, qdss_gpio, _, _, _, _, _, _, _, _),
+ [111] = PINGROUP(111, qup_se5, qdss_gpio, _, _, _, _, _, _, _, _),
+ [112] = PINGROUP(112, qup_se6, emac1_ptp, emac1_ptp, qdss_gpio, _, _, _, _, _, _),
+ [113] = PINGROUP(113, qup_se6, emac1_ptp, emac1_ptp, qdss_gpio, _, _, _, _, _, _),
+ [114] = PINGROUP(114, qup_se6, emac1_ptp, emac1_ptp, qdss_gpio, _, _, _, _, _, _),
+ [115] = PINGROUP(115, qup_se6, emac1_ptp, emac1_ptp, qdss_gpio, _, _, _, _, _, _),
+ [116] = PINGROUP(116, qup_se7, qdss_gpio, _, _, _, _, _, _, _, _),
+ [117] = PINGROUP(117, qup_se7, qdss_gpio, _, _, _, _, _, _, _, _),
+ [118] = PINGROUP(118, qup_se7, qdss_gpio, _, _, _, _, _, _, _, _),
+ [119] = PINGROUP(119, qup_se7, emac0_ptp, qdss_gpio, _, _, _, _, _, _, _),
+ [120] = PINGROUP(120, _, _, _, _, _, _, _, _, _, _),
+ [121] = PINGROUP(121, pcie2_clkreq_n, _, _, _, _, _, _, _, _, _),
+ [122] = PINGROUP(122, emac1_mcg, _, _, _, _, _, _, _, _, _),
+ [123] = PINGROUP(123, emac0_ptp, emac0_ptp, emac0_ptp, emac0_ptp, _, _, _, _, _, _),
+ [124] = PINGROUP(124, pcie1_clkreq_n, qup_se8, _, _, _, _, _, _, _, _),
+ [125] = PINGROUP(125, qup_se8, _, _, _, _, _, _, _, _, _),
+ [126] = PINGROUP(126, audio_ref_clk, _, _, _, _, _, _, _, _, _),
+ [127] = PINGROUP(127, emac_pps_in, _, _, _, _, _, _, _, _, _),
+ [128] = PINGROUP(128, _, _, _, _, _, _, _, _, _, _),
+ [129] = PINGROUP(129, sdc2_tb_trig, _, _, _, _, _, _, _, _, _),
+ [130] = PINGROUP(130, sdc1_tb, _, _, _, _, _, _, _, _, _),
+ [131] = PINGROUP(131, _, _, _, _, _, _, _, _, _, _),
+ [132] = PINGROUP(132, _, _, _, _, _, _, _, _, _, _),
+ [133] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x19a000, 16, 0),
+ [134] = SDC_QDSD_PINGROUP(sdc1_clk, 0x19a000, 14, 6),
+ [135] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x19a000, 11, 3),
+ [136] = SDC_QDSD_PINGROUP(sdc1_data, 0x19a000, 9, 0),
+ [137] = SDC_QDSD_PINGROUP(sdc2_clk, 0x19b000, 14, 6),
+ [138] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x19b000, 11, 3),
+ [139] = SDC_QDSD_PINGROUP(sdc2_data, 0x19b000, 9, 0),
+};
+
+static const struct msm_gpio_wakeirq_map sdx75_pdc_map[] = {
+ { 1, 57 }, { 2, 91 }, {5, 52 }, { 6, 109 }, { 9, 129 }, { 11, 62 },
+ { 13, 84 }, { 15, 87 }, { 17, 88 }, { 18, 89 }, { 19, 90 }, { 20, 92 },
+ { 21, 93 }, { 22, 94 }, { 23, 95 }, { 25, 96 }, { 27, 97 }, { 35, 58 },
+ { 36, 53 }, { 38, 98 }, { 39, 99 }, { 40, 100 }, { 41, 101 }, { 42, 54 },
+ { 43, 56 }, { 44, 71 }, { 46, 60 }, { 47, 61 }, { 49, 47 }, { 50, 126 },
+ { 51, 55 }, { 52, 102 }, { 53, 141 }, { 54, 104 }, { 55, 105 }, { 56, 106 },
+ { 57, 107 }, { 59, 108 }, { 60, 110 }, { 62, 111 }, { 63, 112 }, { 64, 113 },
+ { 65, 114 }, { 67, 115 }, { 68, 116 }, { 69, 117 }, { 70, 118 }, { 71, 119 },
+ { 72, 120 }, { 75, 121 }, { 76, 122 }, { 78, 123 }, { 79, 124 }, { 80, 125 },
+ { 81, 50 }, { 85, 127 }, { 87, 128 }, { 91, 130 }, { 92, 131 }, { 93, 132 },
+ { 94, 133 }, { 95, 134 }, { 97, 135 }, { 98, 136 }, { 101, 64 }, { 103, 51 },
+ { 105, 65 }, { 106, 66 }, { 107, 67 }, { 108, 68 }, { 109, 69 }, { 111, 70 },
+ { 113, 59 }, { 115, 72 }, { 116, 73 }, { 117, 74 }, { 118, 75 }, { 119, 76 },
+ { 120, 77 }, { 121, 78 }, { 123, 79 }, { 124, 80 }, { 125, 63 }, { 127, 81 },
+ { 128, 82 }, { 129, 83 }, { 130, 85 }, { 132, 86 },
+};
+
+static const struct msm_pinctrl_soc_data sdx75_pinctrl = {
+ .pins = sdx75_pins,
+ .npins = ARRAY_SIZE(sdx75_pins),
+ .functions = sdx75_functions,
+ .nfunctions = ARRAY_SIZE(sdx75_functions),
+ .groups = sdx75_groups,
+ .ngroups = ARRAY_SIZE(sdx75_groups),
+ .ngpios = 133,
+ .wakeirq_map = sdx75_pdc_map,
+ .nwakeirq_map = ARRAY_SIZE(sdx75_pdc_map),
+};
+
+static const struct of_device_id sdx75_pinctrl_of_match[] = {
+ { .compatible = "qcom,sdx75-tlmm", .data = &sdx75_pinctrl },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sdx75_pinctrl_of_match);
+
+static int sdx75_pinctrl_probe(struct platform_device *pdev)
+{
+ const struct msm_pinctrl_soc_data *pinctrl_data;
+
+ pinctrl_data = of_device_get_match_data(&pdev->dev);
+ if (!pinctrl_data)
+ return -EINVAL;
+
+ return msm_pinctrl_probe(pdev, pinctrl_data);
+}
+
+static struct platform_driver sdx75_pinctrl_driver = {
+ .driver = {
+ .name = "sdx75-tlmm",
+ .of_match_table = sdx75_pinctrl_of_match,
+ },
+ .probe = sdx75_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init sdx75_pinctrl_init(void)
+{
+ return platform_driver_register(&sdx75_pinctrl_driver);
+}
+arch_initcall(sdx75_pinctrl_init);
+
+static void __exit sdx75_pinctrl_exit(void)
+{
+ platform_driver_unregister(&sdx75_pinctrl_driver);
+}
+module_exit(sdx75_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI sdx75 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/qcom/pinctrl-sm6115.c b/drivers/pinctrl/qcom/pinctrl-sm6115.c
index b3a0161ca377..2a06025f4885 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm6115.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm6115.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -22,18 +21,11 @@ enum {
WEST
};
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -71,9 +63,9 @@ enum {
#define SDC_QDSD_PINGROUP(pg_name, _tile, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -97,9 +89,9 @@ enum {
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -676,74 +668,74 @@ static const char * const ddr_pxi3_groups[] = {
"gpio104", "gpio105",
};
-static const struct msm_function sm6115_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(agera_pll),
- FUNCTION(atest),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer),
- FUNCTION(cri_trng),
- FUNCTION(dac_calib),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gpio),
- FUNCTION(gp_pdm0),
- FUNCTION(gp_pdm1),
- FUNCTION(gp_pdm2),
- FUNCTION(gsm0_tx),
- FUNCTION(gsm1_tx),
- FUNCTION(jitter_bist),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync_out_0),
- FUNCTION(mdp_vsync_out_1),
- FUNCTION(mpm_pwr),
- FUNCTION(mss_lte),
- FUNCTION(m_voc),
- FUNCTION(nav_gpio),
- FUNCTION(pa_indicator),
- FUNCTION(pbs),
- FUNCTION(pbs_out),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_reset),
- FUNCTION(prng_rosc),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qup0),
- FUNCTION(qup1),
- FUNCTION(qup2),
- FUNCTION(qup3),
- FUNCTION(qup4),
- FUNCTION(qup5),
- FUNCTION(sdc1_tb),
- FUNCTION(sdc2_tb),
- FUNCTION(sd_write),
- FUNCTION(ssbi_wtr1),
- FUNCTION(tgu),
- FUNCTION(tsense_pwm),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(usb_phy),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
- FUNCTION(wlan1_adc0),
- FUNCTION(wlan1_adc1),
+static const struct pinfunction sm6115_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(atest),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(dac_calib),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gp_pdm0),
+ MSM_PIN_FUNCTION(gp_pdm1),
+ MSM_PIN_FUNCTION(gp_pdm2),
+ MSM_PIN_FUNCTION(gsm0_tx),
+ MSM_PIN_FUNCTION(gsm1_tx),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync_out_0),
+ MSM_PIN_FUNCTION(mdp_vsync_out_1),
+ MSM_PIN_FUNCTION(mpm_pwr),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(nav_gpio),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pbs),
+ MSM_PIN_FUNCTION(pbs_out),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qup0),
+ MSM_PIN_FUNCTION(qup1),
+ MSM_PIN_FUNCTION(qup2),
+ MSM_PIN_FUNCTION(qup3),
+ MSM_PIN_FUNCTION(qup4),
+ MSM_PIN_FUNCTION(qup5),
+ MSM_PIN_FUNCTION(sdc1_tb),
+ MSM_PIN_FUNCTION(sdc2_tb),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(ssbi_wtr1),
+ MSM_PIN_FUNCTION(tgu),
+ MSM_PIN_FUNCTION(tsense_pwm),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(wlan1_adc1),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
diff --git a/drivers/pinctrl/qcom/pinctrl-sm6125.c b/drivers/pinctrl/qcom/pinctrl-sm6125.c
index 170d4ffbb919..d5e2b896954c 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm6125.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm6125.c
@@ -3,7 +3,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -19,18 +18,11 @@ enum {
WEST
};
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -68,9 +60,9 @@ enum {
#define SDC_QDSD_PINGROUP(pg_name, _tile, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -94,9 +86,9 @@ enum {
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -949,134 +941,134 @@ static const char * const dmic1_data_groups[] = {
"gpio128",
};
-static const struct msm_function sm6125_functions[] = {
- FUNCTION(qup00),
- FUNCTION(gpio),
- FUNCTION(qdss),
- FUNCTION(qup01),
- FUNCTION(qup02),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_bist),
- FUNCTION(atest_tsens2),
- FUNCTION(vsense_trigger),
- FUNCTION(atest_usb1),
- FUNCTION(gp_pdm1),
- FUNCTION(phase_flag),
- FUNCTION(dbg_out),
- FUNCTION(qup14),
- FUNCTION(atest_usb11),
- FUNCTION(ddr_pxi2),
- FUNCTION(atest_usb10),
- FUNCTION(jitter_bist),
- FUNCTION(ddr_pxi3),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_bist),
- FUNCTION(qup03),
- FUNCTION(pll_reset),
- FUNCTION(agera_pll),
- FUNCTION(qdss_cti),
- FUNCTION(qup04),
- FUNCTION(wlan2_adc1),
- FUNCTION(wlan2_adc0),
- FUNCTION(wsa_clk),
- FUNCTION(qup13),
- FUNCTION(ter_mi2s),
- FUNCTION(wsa_data),
- FUNCTION(qup10),
- FUNCTION(gcc_gp3),
- FUNCTION(qup12),
- FUNCTION(sd_write),
- FUNCTION(qup11),
- FUNCTION(cam_mclk),
- FUNCTION(atest_tsens),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer1),
- FUNCTION(gcc_gp2),
- FUNCTION(cci_async),
- FUNCTION(cci_timer4),
- FUNCTION(cci_timer0),
- FUNCTION(gcc_gp1),
- FUNCTION(cci_timer3),
- FUNCTION(wlan1_adc1),
- FUNCTION(wlan1_adc0),
- FUNCTION(qlink_request),
- FUNCTION(qlink_enable),
- FUNCTION(pa_indicator),
- FUNCTION(nav_pps),
- FUNCTION(gps_tx),
- FUNCTION(gp_pdm0),
- FUNCTION(atest_usb13),
- FUNCTION(ddr_pxi1),
- FUNCTION(atest_usb12),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng1),
- FUNCTION(gp_pdm2),
- FUNCTION(sp_cmu),
- FUNCTION(atest_usb2),
- FUNCTION(atest_usb23),
- FUNCTION(uim2_data),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_reset),
- FUNCTION(atest_usb22),
- FUNCTION(uim2_present),
- FUNCTION(atest_usb21),
- FUNCTION(uim1_data),
- FUNCTION(atest_usb20),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_reset),
- FUNCTION(uim1_present),
- FUNCTION(mdp_vsync),
- FUNCTION(copy_gp),
- FUNCTION(tsense_pwm),
- FUNCTION(mpm_pwr),
- FUNCTION(tgu_ch3),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mdp_vsync4),
- FUNCTION(mdp_vsync5),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(atest_char1),
- FUNCTION(vfr_1),
- FUNCTION(tgu_ch2),
- FUNCTION(atest_char0),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(prng_rosc),
- FUNCTION(dp_hot),
- FUNCTION(debug_hot),
- FUNCTION(copy_phase),
- FUNCTION(usb_phy),
- FUNCTION(atest_char),
- FUNCTION(unused1),
- FUNCTION(qua_mi2s),
- FUNCTION(mss_lte),
- FUNCTION(swr_tx),
- FUNCTION(aud_sb),
- FUNCTION(unused2),
- FUNCTION(swr_rx),
- FUNCTION(edp_hot),
- FUNCTION(audio_ref),
- FUNCTION(pri_mi2s),
- FUNCTION(pri_mi2s_ws),
- FUNCTION(adsp_ext),
- FUNCTION(edp_lcd),
- FUNCTION(mclk2),
- FUNCTION(m_voc),
- FUNCTION(mclk1),
- FUNCTION(qca_sb),
- FUNCTION(qui_mi2s),
- FUNCTION(dmic0_clk),
- FUNCTION(sec_mi2s),
- FUNCTION(dmic0_data),
- FUNCTION(dmic1_clk),
- FUNCTION(dmic1_data),
+static const struct pinfunction sm6125_functions[] = {
+ MSM_PIN_FUNCTION(qup00),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(qdss),
+ MSM_PIN_FUNCTION(qup01),
+ MSM_PIN_FUNCTION(qup02),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(atest_tsens2),
+ MSM_PIN_FUNCTION(vsense_trigger),
+ MSM_PIN_FUNCTION(atest_usb1),
+ MSM_PIN_FUNCTION(gp_pdm1),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(atest_usb11),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(atest_usb10),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(qup03),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qup04),
+ MSM_PIN_FUNCTION(wlan2_adc1),
+ MSM_PIN_FUNCTION(wlan2_adc0),
+ MSM_PIN_FUNCTION(wsa_clk),
+ MSM_PIN_FUNCTION(qup13),
+ MSM_PIN_FUNCTION(ter_mi2s),
+ MSM_PIN_FUNCTION(wsa_data),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(wlan1_adc1),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(qlink_request),
+ MSM_PIN_FUNCTION(qlink_enable),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(gps_tx),
+ MSM_PIN_FUNCTION(gp_pdm0),
+ MSM_PIN_FUNCTION(atest_usb13),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(atest_usb12),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(gp_pdm2),
+ MSM_PIN_FUNCTION(sp_cmu),
+ MSM_PIN_FUNCTION(atest_usb2),
+ MSM_PIN_FUNCTION(atest_usb23),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(atest_usb22),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(atest_usb21),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(atest_usb20),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(copy_gp),
+ MSM_PIN_FUNCTION(tsense_pwm),
+ MSM_PIN_FUNCTION(mpm_pwr),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mdp_vsync4),
+ MSM_PIN_FUNCTION(mdp_vsync5),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(debug_hot),
+ MSM_PIN_FUNCTION(copy_phase),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(unused1),
+ MSM_PIN_FUNCTION(qua_mi2s),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(swr_tx),
+ MSM_PIN_FUNCTION(aud_sb),
+ MSM_PIN_FUNCTION(unused2),
+ MSM_PIN_FUNCTION(swr_rx),
+ MSM_PIN_FUNCTION(edp_hot),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(pri_mi2s_ws),
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(mclk2),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mclk1),
+ MSM_PIN_FUNCTION(qca_sb),
+ MSM_PIN_FUNCTION(qui_mi2s),
+ MSM_PIN_FUNCTION(dmic0_clk),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(dmic0_data),
+ MSM_PIN_FUNCTION(dmic1_clk),
+ MSM_PIN_FUNCTION(dmic1_data),
};
/*
diff --git a/drivers/pinctrl/qcom/pinctrl-sm6350.c b/drivers/pinctrl/qcom/pinctrl-sm6350.c
index a91a86628f2f..f3828c07b134 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm6350.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm6350.c
@@ -7,23 +7,15 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -60,9 +52,9 @@
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -85,9 +77,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -1016,141 +1008,141 @@ static const char * const usb_phy_groups[] = {
"gpio124",
};
-static const struct msm_function sm6350_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(agera_pll),
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(atest_tsens),
- FUNCTION(atest_tsens2),
- FUNCTION(atest_usb),
- FUNCTION(audio_ref),
- FUNCTION(btfm_slimbus),
- FUNCTION(cam_mclk0),
- FUNCTION(cam_mclk1),
- FUNCTION(cam_mclk2),
- FUNCTION(cam_mclk3),
- FUNCTION(cam_mclk4),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cri_trng),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(dp_hot),
- FUNCTION(edp_lcd),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gp_pdm0),
- FUNCTION(gp_pdm1),
- FUNCTION(gp_pdm2),
- FUNCTION(gpio),
- FUNCTION(gps_tx),
- FUNCTION(ibi_i3c),
- FUNCTION(jitter_bist),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(lpass_ext),
- FUNCTION(m_voc),
- FUNCTION(mclk),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mi2s_0),
- FUNCTION(mi2s_1),
- FUNCTION(mi2s_2),
- FUNCTION(mss_lte),
- FUNCTION(nav_gpio),
- FUNCTION(nav_pps),
- FUNCTION(pa_indicator),
- FUNCTION(pcie0_clk),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_reset),
- FUNCTION(prng_rosc),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qdss_gpio0),
- FUNCTION(qdss_gpio1),
- FUNCTION(qdss_gpio10),
- FUNCTION(qdss_gpio11),
- FUNCTION(qdss_gpio12),
- FUNCTION(qdss_gpio13),
- FUNCTION(qdss_gpio14),
- FUNCTION(qdss_gpio15),
- FUNCTION(qdss_gpio2),
- FUNCTION(qdss_gpio3),
- FUNCTION(qdss_gpio4),
- FUNCTION(qdss_gpio5),
- FUNCTION(qdss_gpio6),
- FUNCTION(qdss_gpio7),
- FUNCTION(qdss_gpio8),
- FUNCTION(qdss_gpio9),
- FUNCTION(qlink0_enable),
- FUNCTION(qlink0_request),
- FUNCTION(qlink0_wmss),
- FUNCTION(qlink1_enable),
- FUNCTION(qlink1_request),
- FUNCTION(qlink1_wmss),
- FUNCTION(qup00),
- FUNCTION(qup01),
- FUNCTION(qup02),
- FUNCTION(qup10),
- FUNCTION(qup11),
- FUNCTION(qup12),
- FUNCTION(qup13_f1),
- FUNCTION(qup13_f2),
- FUNCTION(qup14),
- FUNCTION(rffe0_clk),
- FUNCTION(rffe0_data),
- FUNCTION(rffe1_clk),
- FUNCTION(rffe1_data),
- FUNCTION(rffe2_clk),
- FUNCTION(rffe2_data),
- FUNCTION(rffe3_clk),
- FUNCTION(rffe3_data),
- FUNCTION(rffe4_clk),
- FUNCTION(rffe4_data),
- FUNCTION(sd_write),
- FUNCTION(sdc1_tb),
- FUNCTION(sdc2_tb),
- FUNCTION(sp_cmu),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(usb_phy),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
- FUNCTION(wlan1_adc0),
- FUNCTION(wlan1_adc1),
- FUNCTION(wlan2_adc0),
- FUNCTION(wlan2_adc1),
+static const struct pinfunction sm6350_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_tsens2),
+ MSM_PIN_FUNCTION(atest_usb),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(btfm_slimbus),
+ MSM_PIN_FUNCTION(cam_mclk0),
+ MSM_PIN_FUNCTION(cam_mclk1),
+ MSM_PIN_FUNCTION(cam_mclk2),
+ MSM_PIN_FUNCTION(cam_mclk3),
+ MSM_PIN_FUNCTION(cam_mclk4),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gp_pdm0),
+ MSM_PIN_FUNCTION(gp_pdm1),
+ MSM_PIN_FUNCTION(gp_pdm2),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gps_tx),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(lpass_ext),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mclk),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mi2s_0),
+ MSM_PIN_FUNCTION(mi2s_1),
+ MSM_PIN_FUNCTION(mi2s_2),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(nav_gpio),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pcie0_clk),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qdss_gpio0),
+ MSM_PIN_FUNCTION(qdss_gpio1),
+ MSM_PIN_FUNCTION(qdss_gpio10),
+ MSM_PIN_FUNCTION(qdss_gpio11),
+ MSM_PIN_FUNCTION(qdss_gpio12),
+ MSM_PIN_FUNCTION(qdss_gpio13),
+ MSM_PIN_FUNCTION(qdss_gpio14),
+ MSM_PIN_FUNCTION(qdss_gpio15),
+ MSM_PIN_FUNCTION(qdss_gpio2),
+ MSM_PIN_FUNCTION(qdss_gpio3),
+ MSM_PIN_FUNCTION(qdss_gpio4),
+ MSM_PIN_FUNCTION(qdss_gpio5),
+ MSM_PIN_FUNCTION(qdss_gpio6),
+ MSM_PIN_FUNCTION(qdss_gpio7),
+ MSM_PIN_FUNCTION(qdss_gpio8),
+ MSM_PIN_FUNCTION(qdss_gpio9),
+ MSM_PIN_FUNCTION(qlink0_enable),
+ MSM_PIN_FUNCTION(qlink0_request),
+ MSM_PIN_FUNCTION(qlink0_wmss),
+ MSM_PIN_FUNCTION(qlink1_enable),
+ MSM_PIN_FUNCTION(qlink1_request),
+ MSM_PIN_FUNCTION(qlink1_wmss),
+ MSM_PIN_FUNCTION(qup00),
+ MSM_PIN_FUNCTION(qup01),
+ MSM_PIN_FUNCTION(qup02),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13_f1),
+ MSM_PIN_FUNCTION(qup13_f2),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(rffe0_clk),
+ MSM_PIN_FUNCTION(rffe0_data),
+ MSM_PIN_FUNCTION(rffe1_clk),
+ MSM_PIN_FUNCTION(rffe1_data),
+ MSM_PIN_FUNCTION(rffe2_clk),
+ MSM_PIN_FUNCTION(rffe2_data),
+ MSM_PIN_FUNCTION(rffe3_clk),
+ MSM_PIN_FUNCTION(rffe3_data),
+ MSM_PIN_FUNCTION(rffe4_clk),
+ MSM_PIN_FUNCTION(rffe4_data),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sdc1_tb),
+ MSM_PIN_FUNCTION(sdc2_tb),
+ MSM_PIN_FUNCTION(sp_cmu),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(wlan1_adc1),
+ MSM_PIN_FUNCTION(wlan2_adc0),
+ MSM_PIN_FUNCTION(wlan2_adc1),
};
/*
diff --git a/drivers/pinctrl/qcom/pinctrl-sm6375.c b/drivers/pinctrl/qcom/pinctrl-sm6375.c
index 1138e683e6f4..c82c8516932e 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm6375.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm6375.c
@@ -7,24 +7,16 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_BASE 0x100000
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -63,9 +55,9 @@
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -88,9 +80,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -1135,172 +1127,172 @@ static const char * const wlan2_adc1_groups[] = {
"gpio93",
};
-static const struct msm_function sm6375_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(agera_pll),
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(atest_tsens),
- FUNCTION(atest_tsens2),
- FUNCTION(atest_usb1),
- FUNCTION(atest_usb10),
- FUNCTION(atest_usb11),
- FUNCTION(atest_usb12),
- FUNCTION(atest_usb13),
- FUNCTION(atest_usb2),
- FUNCTION(atest_usb20),
- FUNCTION(atest_usb21),
- FUNCTION(atest_usb22),
- FUNCTION(atest_usb23),
- FUNCTION(audio_ref),
- FUNCTION(btfm_slimbus),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cri_trng),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(dp_hot),
- FUNCTION(edp_lcd),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gp_pdm0),
- FUNCTION(gp_pdm1),
- FUNCTION(gp_pdm2),
- FUNCTION(gpio),
- FUNCTION(gps_tx),
- FUNCTION(ibi_i3c),
- FUNCTION(jitter_bist),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(lpass_ext),
- FUNCTION(m_voc),
- FUNCTION(mclk),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mi2s_0),
- FUNCTION(mi2s_1),
- FUNCTION(mi2s_2),
- FUNCTION(mss_lte),
- FUNCTION(nav_gpio),
- FUNCTION(nav_pps),
- FUNCTION(pa_indicator),
- FUNCTION(phase_flag0),
- FUNCTION(phase_flag1),
- FUNCTION(phase_flag10),
- FUNCTION(phase_flag11),
- FUNCTION(phase_flag12),
- FUNCTION(phase_flag13),
- FUNCTION(phase_flag14),
- FUNCTION(phase_flag15),
- FUNCTION(phase_flag16),
- FUNCTION(phase_flag17),
- FUNCTION(phase_flag18),
- FUNCTION(phase_flag19),
- FUNCTION(phase_flag2),
- FUNCTION(phase_flag20),
- FUNCTION(phase_flag21),
- FUNCTION(phase_flag22),
- FUNCTION(phase_flag23),
- FUNCTION(phase_flag24),
- FUNCTION(phase_flag25),
- FUNCTION(phase_flag26),
- FUNCTION(phase_flag27),
- FUNCTION(phase_flag28),
- FUNCTION(phase_flag29),
- FUNCTION(phase_flag3),
- FUNCTION(phase_flag30),
- FUNCTION(phase_flag31),
- FUNCTION(phase_flag4),
- FUNCTION(phase_flag5),
- FUNCTION(phase_flag6),
- FUNCTION(phase_flag7),
- FUNCTION(phase_flag8),
- FUNCTION(phase_flag9),
- FUNCTION(pll_bist),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_clk),
- FUNCTION(pll_reset),
- FUNCTION(prng_rosc0),
- FUNCTION(prng_rosc1),
- FUNCTION(prng_rosc2),
- FUNCTION(prng_rosc3),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qdss_gpio0),
- FUNCTION(qdss_gpio1),
- FUNCTION(qdss_gpio10),
- FUNCTION(qdss_gpio11),
- FUNCTION(qdss_gpio12),
- FUNCTION(qdss_gpio13),
- FUNCTION(qdss_gpio14),
- FUNCTION(qdss_gpio15),
- FUNCTION(qdss_gpio2),
- FUNCTION(qdss_gpio3),
- FUNCTION(qdss_gpio4),
- FUNCTION(qdss_gpio5),
- FUNCTION(qdss_gpio6),
- FUNCTION(qdss_gpio7),
- FUNCTION(qdss_gpio8),
- FUNCTION(qdss_gpio9),
- FUNCTION(qlink0_enable),
- FUNCTION(qlink0_request),
- FUNCTION(qlink0_wmss),
- FUNCTION(qlink1_enable),
- FUNCTION(qlink1_request),
- FUNCTION(qlink1_wmss),
- FUNCTION(qup00),
- FUNCTION(qup01),
- FUNCTION(qup02),
- FUNCTION(qup10),
- FUNCTION(qup11_f1),
- FUNCTION(qup11_f2),
- FUNCTION(qup12),
- FUNCTION(qup13_f1),
- FUNCTION(qup13_f2),
- FUNCTION(qup14),
- FUNCTION(sd_write),
- FUNCTION(sdc1_tb),
- FUNCTION(sdc2_tb),
- FUNCTION(sp_cmu),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(usb2phy_ac),
- FUNCTION(usb_phy),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
- FUNCTION(wlan1_adc0),
- FUNCTION(wlan1_adc1),
- FUNCTION(wlan2_adc0),
- FUNCTION(wlan2_adc1),
+static const struct pinfunction sm6375_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_tsens2),
+ MSM_PIN_FUNCTION(atest_usb1),
+ MSM_PIN_FUNCTION(atest_usb10),
+ MSM_PIN_FUNCTION(atest_usb11),
+ MSM_PIN_FUNCTION(atest_usb12),
+ MSM_PIN_FUNCTION(atest_usb13),
+ MSM_PIN_FUNCTION(atest_usb2),
+ MSM_PIN_FUNCTION(atest_usb20),
+ MSM_PIN_FUNCTION(atest_usb21),
+ MSM_PIN_FUNCTION(atest_usb22),
+ MSM_PIN_FUNCTION(atest_usb23),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(btfm_slimbus),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gp_pdm0),
+ MSM_PIN_FUNCTION(gp_pdm1),
+ MSM_PIN_FUNCTION(gp_pdm2),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(gps_tx),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(lpass_ext),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mclk),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mi2s_0),
+ MSM_PIN_FUNCTION(mi2s_1),
+ MSM_PIN_FUNCTION(mi2s_2),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(nav_gpio),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(phase_flag0),
+ MSM_PIN_FUNCTION(phase_flag1),
+ MSM_PIN_FUNCTION(phase_flag10),
+ MSM_PIN_FUNCTION(phase_flag11),
+ MSM_PIN_FUNCTION(phase_flag12),
+ MSM_PIN_FUNCTION(phase_flag13),
+ MSM_PIN_FUNCTION(phase_flag14),
+ MSM_PIN_FUNCTION(phase_flag15),
+ MSM_PIN_FUNCTION(phase_flag16),
+ MSM_PIN_FUNCTION(phase_flag17),
+ MSM_PIN_FUNCTION(phase_flag18),
+ MSM_PIN_FUNCTION(phase_flag19),
+ MSM_PIN_FUNCTION(phase_flag2),
+ MSM_PIN_FUNCTION(phase_flag20),
+ MSM_PIN_FUNCTION(phase_flag21),
+ MSM_PIN_FUNCTION(phase_flag22),
+ MSM_PIN_FUNCTION(phase_flag23),
+ MSM_PIN_FUNCTION(phase_flag24),
+ MSM_PIN_FUNCTION(phase_flag25),
+ MSM_PIN_FUNCTION(phase_flag26),
+ MSM_PIN_FUNCTION(phase_flag27),
+ MSM_PIN_FUNCTION(phase_flag28),
+ MSM_PIN_FUNCTION(phase_flag29),
+ MSM_PIN_FUNCTION(phase_flag3),
+ MSM_PIN_FUNCTION(phase_flag30),
+ MSM_PIN_FUNCTION(phase_flag31),
+ MSM_PIN_FUNCTION(phase_flag4),
+ MSM_PIN_FUNCTION(phase_flag5),
+ MSM_PIN_FUNCTION(phase_flag6),
+ MSM_PIN_FUNCTION(phase_flag7),
+ MSM_PIN_FUNCTION(phase_flag8),
+ MSM_PIN_FUNCTION(phase_flag9),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_clk),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(prng_rosc2),
+ MSM_PIN_FUNCTION(prng_rosc3),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qdss_gpio0),
+ MSM_PIN_FUNCTION(qdss_gpio1),
+ MSM_PIN_FUNCTION(qdss_gpio10),
+ MSM_PIN_FUNCTION(qdss_gpio11),
+ MSM_PIN_FUNCTION(qdss_gpio12),
+ MSM_PIN_FUNCTION(qdss_gpio13),
+ MSM_PIN_FUNCTION(qdss_gpio14),
+ MSM_PIN_FUNCTION(qdss_gpio15),
+ MSM_PIN_FUNCTION(qdss_gpio2),
+ MSM_PIN_FUNCTION(qdss_gpio3),
+ MSM_PIN_FUNCTION(qdss_gpio4),
+ MSM_PIN_FUNCTION(qdss_gpio5),
+ MSM_PIN_FUNCTION(qdss_gpio6),
+ MSM_PIN_FUNCTION(qdss_gpio7),
+ MSM_PIN_FUNCTION(qdss_gpio8),
+ MSM_PIN_FUNCTION(qdss_gpio9),
+ MSM_PIN_FUNCTION(qlink0_enable),
+ MSM_PIN_FUNCTION(qlink0_request),
+ MSM_PIN_FUNCTION(qlink0_wmss),
+ MSM_PIN_FUNCTION(qlink1_enable),
+ MSM_PIN_FUNCTION(qlink1_request),
+ MSM_PIN_FUNCTION(qlink1_wmss),
+ MSM_PIN_FUNCTION(qup00),
+ MSM_PIN_FUNCTION(qup01),
+ MSM_PIN_FUNCTION(qup02),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11_f1),
+ MSM_PIN_FUNCTION(qup11_f2),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13_f1),
+ MSM_PIN_FUNCTION(qup13_f2),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sdc1_tb),
+ MSM_PIN_FUNCTION(sdc2_tb),
+ MSM_PIN_FUNCTION(sp_cmu),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(wlan1_adc1),
+ MSM_PIN_FUNCTION(wlan2_adc0),
+ MSM_PIN_FUNCTION(wlan2_adc1),
};
/*
diff --git a/drivers/pinctrl/qcom/pinctrl-sm7150.c b/drivers/pinctrl/qcom/pinctrl-sm7150.c
index 2a87e3f144fd..33657cf98fb9 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm7150.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm7150.c
@@ -23,20 +23,13 @@ enum {
WEST
};
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -74,9 +67,9 @@ enum {
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -100,9 +93,9 @@ enum {
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -966,117 +959,117 @@ static const char * const wsa_data_groups[] = {
"gpio50",
};
-static const struct msm_function sm7150_functions[] = {
- FUNCTION(gpio),
- FUNCTION(adsp_ext),
- FUNCTION(agera_pll),
- FUNCTION(aoss_cti),
- FUNCTION(atest_char),
- FUNCTION(atest_tsens),
- FUNCTION(atest_tsens2),
- FUNCTION(atest_usb1),
- FUNCTION(atest_usb2),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(edp_hot),
- FUNCTION(edp_lcd),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gp_pdm0),
- FUNCTION(gp_pdm1),
- FUNCTION(gp_pdm2),
- FUNCTION(gps_tx),
- FUNCTION(jitter_bist),
- FUNCTION(ldo_en),
- FUNCTION(ldo_update),
- FUNCTION(m_voc),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mss_lte),
- FUNCTION(nav_pps_in),
- FUNCTION(nav_pps_out),
- FUNCTION(pa_indicator),
- FUNCTION(pci_e),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_reset),
- FUNCTION(pri_mi2s),
- FUNCTION(pri_mi2s_ws),
- FUNCTION(prng_rosc),
- FUNCTION(qdss_cti),
- FUNCTION(qdss),
- FUNCTION(qlink_enable),
- FUNCTION(qlink_request),
- FUNCTION(qua_mi2s),
- FUNCTION(qup00),
- FUNCTION(qup01),
- FUNCTION(qup02),
- FUNCTION(qup03),
- FUNCTION(qup04),
- FUNCTION(qup10),
- FUNCTION(qup11),
- FUNCTION(qup12),
- FUNCTION(qup13),
- FUNCTION(qup14),
- FUNCTION(qup15),
- FUNCTION(sd_write),
- FUNCTION(sdc40),
- FUNCTION(sdc41),
- FUNCTION(sdc42),
- FUNCTION(sdc43),
- FUNCTION(sdc4_clk),
- FUNCTION(sdc4_cmd),
- FUNCTION(sec_mi2s),
- FUNCTION(ter_mi2s),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tsif1_clk),
- FUNCTION(tsif1_data),
- FUNCTION(tsif1_en),
- FUNCTION(tsif1_error),
- FUNCTION(tsif1_sync),
- FUNCTION(tsif2_clk),
- FUNCTION(tsif2_data),
- FUNCTION(tsif2_en),
- FUNCTION(tsif2_error),
- FUNCTION(tsif2_sync),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(uim2_clk),
- FUNCTION(uim2_data),
- FUNCTION(uim2_present),
- FUNCTION(uim2_reset),
- FUNCTION(uim_batt),
- FUNCTION(usb_phy),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
- FUNCTION(wlan1_adc0),
- FUNCTION(wlan1_adc1),
- FUNCTION(wlan2_adc0),
- FUNCTION(wlan2_adc1),
- FUNCTION(wsa_clk),
- FUNCTION(wsa_data),
+static const struct pinfunction sm7150_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_tsens2),
+ MSM_PIN_FUNCTION(atest_usb1),
+ MSM_PIN_FUNCTION(atest_usb2),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(edp_hot),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gp_pdm0),
+ MSM_PIN_FUNCTION(gp_pdm1),
+ MSM_PIN_FUNCTION(gp_pdm2),
+ MSM_PIN_FUNCTION(gps_tx),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(nav_pps_in),
+ MSM_PIN_FUNCTION(nav_pps_out),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pci_e),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(pri_mi2s_ws),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss),
+ MSM_PIN_FUNCTION(qlink_enable),
+ MSM_PIN_FUNCTION(qlink_request),
+ MSM_PIN_FUNCTION(qua_mi2s),
+ MSM_PIN_FUNCTION(qup00),
+ MSM_PIN_FUNCTION(qup01),
+ MSM_PIN_FUNCTION(qup02),
+ MSM_PIN_FUNCTION(qup03),
+ MSM_PIN_FUNCTION(qup04),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(qup15),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sdc40),
+ MSM_PIN_FUNCTION(sdc41),
+ MSM_PIN_FUNCTION(sdc42),
+ MSM_PIN_FUNCTION(sdc43),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(ter_mi2s),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tsif1_clk),
+ MSM_PIN_FUNCTION(tsif1_data),
+ MSM_PIN_FUNCTION(tsif1_en),
+ MSM_PIN_FUNCTION(tsif1_error),
+ MSM_PIN_FUNCTION(tsif1_sync),
+ MSM_PIN_FUNCTION(tsif2_clk),
+ MSM_PIN_FUNCTION(tsif2_data),
+ MSM_PIN_FUNCTION(tsif2_en),
+ MSM_PIN_FUNCTION(tsif2_error),
+ MSM_PIN_FUNCTION(tsif2_sync),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(uim2_clk),
+ MSM_PIN_FUNCTION(uim2_data),
+ MSM_PIN_FUNCTION(uim2_present),
+ MSM_PIN_FUNCTION(uim2_reset),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(wlan1_adc1),
+ MSM_PIN_FUNCTION(wlan2_adc0),
+ MSM_PIN_FUNCTION(wlan2_adc1),
+ MSM_PIN_FUNCTION(wsa_clk),
+ MSM_PIN_FUNCTION(wsa_data),
};
/*
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c b/drivers/pinctrl/qcom/pinctrl-sm8150.c
index 1cc622694553..01aea9c70b7a 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8150.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c
@@ -4,7 +4,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -22,18 +21,11 @@ enum {
WEST
};
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -71,9 +63,9 @@ enum {
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -97,9 +89,9 @@ enum {
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -1180,136 +1172,136 @@ static const char * const mss_lte_groups[] = {
"gpio69", "gpio70",
};
-static const struct msm_function sm8150_functions[] = {
- FUNCTION(adsp_ext),
- FUNCTION(agera_pll),
- FUNCTION(aoss_cti),
- FUNCTION(ddr_pxi2),
- FUNCTION(atest_char),
- FUNCTION(atest_char0),
- FUNCTION(atest_char1),
- FUNCTION(atest_char2),
- FUNCTION(atest_char3),
- FUNCTION(audio_ref),
- FUNCTION(atest_usb1),
- FUNCTION(atest_usb2),
- FUNCTION(atest_usb10),
- FUNCTION(atest_usb11),
- FUNCTION(atest_usb12),
- FUNCTION(atest_usb13),
- FUNCTION(atest_usb20),
- FUNCTION(atest_usb21),
- FUNCTION(atest_usb22),
- FUNCTION(atest_usb23),
- FUNCTION(btfm_slimbus),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi3),
- FUNCTION(edp_hot),
- FUNCTION(edp_lcd),
- FUNCTION(emac_phy),
- FUNCTION(emac_pps),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gpio),
- FUNCTION(hs1_mi2s),
- FUNCTION(hs2_mi2s),
- FUNCTION(hs3_mi2s),
- FUNCTION(jitter_bist),
- FUNCTION(lpass_slimbus),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mss_lte),
- FUNCTION(m_voc),
- FUNCTION(nav_pps),
- FUNCTION(pa_indicator),
- FUNCTION(pci_e0),
- FUNCTION(phase_flag),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_bist),
- FUNCTION(pci_e1),
- FUNCTION(pll_reset),
- FUNCTION(pri_mi2s),
- FUNCTION(pri_mi2s_ws),
- FUNCTION(prng_rosc),
- FUNCTION(qdss),
- FUNCTION(qdss_cti),
- FUNCTION(qlink_request),
- FUNCTION(qlink_enable),
- FUNCTION(qspi0),
- FUNCTION(qspi1),
- FUNCTION(qspi2),
- FUNCTION(qspi3),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(qua_mi2s),
- FUNCTION(qup0),
- FUNCTION(qup1),
- FUNCTION(qup2),
- FUNCTION(qup3),
- FUNCTION(qup4),
- FUNCTION(qup5),
- FUNCTION(qup6),
- FUNCTION(qup7),
- FUNCTION(qup8),
- FUNCTION(qup9),
- FUNCTION(qup10),
- FUNCTION(qup11),
- FUNCTION(qup12),
- FUNCTION(qup13),
- FUNCTION(qup14),
- FUNCTION(qup15),
- FUNCTION(qup16),
- FUNCTION(qup17),
- FUNCTION(qup18),
- FUNCTION(qup19),
- FUNCTION(qup_l4),
- FUNCTION(qup_l5),
- FUNCTION(qup_l6),
- FUNCTION(rgmii),
- FUNCTION(sdc4),
- FUNCTION(sd_write),
- FUNCTION(sec_mi2s),
- FUNCTION(spkr_i2s),
- FUNCTION(sp_cmu),
- FUNCTION(ter_mi2s),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(tsif1),
- FUNCTION(tsif2),
- FUNCTION(uim1),
- FUNCTION(uim2),
- FUNCTION(uim_batt),
- FUNCTION(usb2phy_ac),
- FUNCTION(usb_phy),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
- FUNCTION(wlan1_adc0),
- FUNCTION(wlan1_adc1),
- FUNCTION(wlan2_adc0),
- FUNCTION(wlan2_adc1),
- FUNCTION(wmss_reset),
+static const struct pinfunction sm8150_functions[] = {
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(atest_usb1),
+ MSM_PIN_FUNCTION(atest_usb2),
+ MSM_PIN_FUNCTION(atest_usb10),
+ MSM_PIN_FUNCTION(atest_usb11),
+ MSM_PIN_FUNCTION(atest_usb12),
+ MSM_PIN_FUNCTION(atest_usb13),
+ MSM_PIN_FUNCTION(atest_usb20),
+ MSM_PIN_FUNCTION(atest_usb21),
+ MSM_PIN_FUNCTION(atest_usb22),
+ MSM_PIN_FUNCTION(atest_usb23),
+ MSM_PIN_FUNCTION(btfm_slimbus),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(edp_hot),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(emac_phy),
+ MSM_PIN_FUNCTION(emac_pps),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(hs1_mi2s),
+ MSM_PIN_FUNCTION(hs2_mi2s),
+ MSM_PIN_FUNCTION(hs3_mi2s),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(lpass_slimbus),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(nav_pps),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pci_e0),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pci_e1),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(pri_mi2s_ws),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qlink_request),
+ MSM_PIN_FUNCTION(qlink_enable),
+ MSM_PIN_FUNCTION(qspi0),
+ MSM_PIN_FUNCTION(qspi1),
+ MSM_PIN_FUNCTION(qspi2),
+ MSM_PIN_FUNCTION(qspi3),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qua_mi2s),
+ MSM_PIN_FUNCTION(qup0),
+ MSM_PIN_FUNCTION(qup1),
+ MSM_PIN_FUNCTION(qup2),
+ MSM_PIN_FUNCTION(qup3),
+ MSM_PIN_FUNCTION(qup4),
+ MSM_PIN_FUNCTION(qup5),
+ MSM_PIN_FUNCTION(qup6),
+ MSM_PIN_FUNCTION(qup7),
+ MSM_PIN_FUNCTION(qup8),
+ MSM_PIN_FUNCTION(qup9),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(qup15),
+ MSM_PIN_FUNCTION(qup16),
+ MSM_PIN_FUNCTION(qup17),
+ MSM_PIN_FUNCTION(qup18),
+ MSM_PIN_FUNCTION(qup19),
+ MSM_PIN_FUNCTION(qup_l4),
+ MSM_PIN_FUNCTION(qup_l5),
+ MSM_PIN_FUNCTION(qup_l6),
+ MSM_PIN_FUNCTION(rgmii),
+ MSM_PIN_FUNCTION(sdc4),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(spkr_i2s),
+ MSM_PIN_FUNCTION(sp_cmu),
+ MSM_PIN_FUNCTION(ter_mi2s),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(tsif1),
+ MSM_PIN_FUNCTION(tsif2),
+ MSM_PIN_FUNCTION(uim1),
+ MSM_PIN_FUNCTION(uim2),
+ MSM_PIN_FUNCTION(uim_batt),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
+ MSM_PIN_FUNCTION(wlan1_adc0),
+ MSM_PIN_FUNCTION(wlan1_adc1),
+ MSM_PIN_FUNCTION(wlan2_adc0),
+ MSM_PIN_FUNCTION(wlan2_adc1),
+ MSM_PIN_FUNCTION(wmss_reset),
};
/*
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c b/drivers/pinctrl/qcom/pinctrl-sm8250.c
index 3bd7f9fedcc3..e9961a49ff98 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8250.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
@@ -22,19 +21,12 @@ enum {
NORTH,
};
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -72,9 +64,9 @@ enum {
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -98,9 +90,9 @@ enum {
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -1003,122 +995,122 @@ static const char * const sdc42_groups[] = {
"gpio74",
};
-static const struct msm_function sm8250_functions[] = {
- FUNCTION(aoss_cti),
- FUNCTION(atest),
- FUNCTION(audio_ref),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer0),
- FUNCTION(cci_timer1),
- FUNCTION(cci_timer2),
- FUNCTION(cci_timer3),
- FUNCTION(cci_timer4),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(dp_hot),
- FUNCTION(dp_lcd),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gpio),
- FUNCTION(ibi_i3c),
- FUNCTION(jitter_bist),
- FUNCTION(lpass_slimbus),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mi2s0_data0),
- FUNCTION(mi2s0_data1),
- FUNCTION(mi2s0_sck),
- FUNCTION(mi2s0_ws),
- FUNCTION(mi2s1_data0),
- FUNCTION(mi2s1_data1),
- FUNCTION(mi2s1_sck),
- FUNCTION(mi2s1_ws),
- FUNCTION(mi2s2_data0),
- FUNCTION(mi2s2_data1),
- FUNCTION(mi2s2_sck),
- FUNCTION(mi2s2_ws),
- FUNCTION(pci_e0),
- FUNCTION(pci_e1),
- FUNCTION(pci_e2),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_bypassnl),
- FUNCTION(pll_clk),
- FUNCTION(pll_reset),
- FUNCTION(pri_mi2s),
- FUNCTION(prng_rosc),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qspi0),
- FUNCTION(qspi1),
- FUNCTION(qspi2),
- FUNCTION(qspi3),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(qup0),
- FUNCTION(qup1),
- FUNCTION(qup10),
- FUNCTION(qup11),
- FUNCTION(qup12),
- FUNCTION(qup13),
- FUNCTION(qup14),
- FUNCTION(qup15),
- FUNCTION(qup16),
- FUNCTION(qup17),
- FUNCTION(qup18),
- FUNCTION(qup19),
- FUNCTION(qup2),
- FUNCTION(qup3),
- FUNCTION(qup4),
- FUNCTION(qup5),
- FUNCTION(qup6),
- FUNCTION(qup7),
- FUNCTION(qup8),
- FUNCTION(qup9),
- FUNCTION(qup_l4),
- FUNCTION(qup_l5),
- FUNCTION(qup_l6),
- FUNCTION(sd_write),
- FUNCTION(sdc40),
- FUNCTION(sdc41),
- FUNCTION(sdc42),
- FUNCTION(sdc43),
- FUNCTION(sdc4_clk),
- FUNCTION(sdc4_cmd),
- FUNCTION(sec_mi2s),
- FUNCTION(sp_cmu),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(tsif0_clk),
- FUNCTION(tsif0_data),
- FUNCTION(tsif0_en),
- FUNCTION(tsif0_error),
- FUNCTION(tsif0_sync),
- FUNCTION(tsif1_clk),
- FUNCTION(tsif1_data),
- FUNCTION(tsif1_en),
- FUNCTION(tsif1_error),
- FUNCTION(tsif1_sync),
- FUNCTION(usb2phy_ac),
- FUNCTION(usb_phy),
- FUNCTION(vsense_trigger),
+static const struct pinfunction sm8250_functions[] = {
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(atest),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(dp_lcd),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(lpass_slimbus),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mi2s0_data0),
+ MSM_PIN_FUNCTION(mi2s0_data1),
+ MSM_PIN_FUNCTION(mi2s0_sck),
+ MSM_PIN_FUNCTION(mi2s0_ws),
+ MSM_PIN_FUNCTION(mi2s1_data0),
+ MSM_PIN_FUNCTION(mi2s1_data1),
+ MSM_PIN_FUNCTION(mi2s1_sck),
+ MSM_PIN_FUNCTION(mi2s1_ws),
+ MSM_PIN_FUNCTION(mi2s2_data0),
+ MSM_PIN_FUNCTION(mi2s2_data1),
+ MSM_PIN_FUNCTION(mi2s2_sck),
+ MSM_PIN_FUNCTION(mi2s2_ws),
+ MSM_PIN_FUNCTION(pci_e0),
+ MSM_PIN_FUNCTION(pci_e1),
+ MSM_PIN_FUNCTION(pci_e2),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_clk),
+ MSM_PIN_FUNCTION(pll_reset),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qspi0),
+ MSM_PIN_FUNCTION(qspi1),
+ MSM_PIN_FUNCTION(qspi2),
+ MSM_PIN_FUNCTION(qspi3),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qup0),
+ MSM_PIN_FUNCTION(qup1),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(qup15),
+ MSM_PIN_FUNCTION(qup16),
+ MSM_PIN_FUNCTION(qup17),
+ MSM_PIN_FUNCTION(qup18),
+ MSM_PIN_FUNCTION(qup19),
+ MSM_PIN_FUNCTION(qup2),
+ MSM_PIN_FUNCTION(qup3),
+ MSM_PIN_FUNCTION(qup4),
+ MSM_PIN_FUNCTION(qup5),
+ MSM_PIN_FUNCTION(qup6),
+ MSM_PIN_FUNCTION(qup7),
+ MSM_PIN_FUNCTION(qup8),
+ MSM_PIN_FUNCTION(qup9),
+ MSM_PIN_FUNCTION(qup_l4),
+ MSM_PIN_FUNCTION(qup_l5),
+ MSM_PIN_FUNCTION(qup_l6),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sdc40),
+ MSM_PIN_FUNCTION(sdc41),
+ MSM_PIN_FUNCTION(sdc42),
+ MSM_PIN_FUNCTION(sdc43),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(sp_cmu),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(tsif0_clk),
+ MSM_PIN_FUNCTION(tsif0_data),
+ MSM_PIN_FUNCTION(tsif0_en),
+ MSM_PIN_FUNCTION(tsif0_error),
+ MSM_PIN_FUNCTION(tsif0_sync),
+ MSM_PIN_FUNCTION(tsif1_clk),
+ MSM_PIN_FUNCTION(tsif1_data),
+ MSM_PIN_FUNCTION(tsif1_en),
+ MSM_PIN_FUNCTION(tsif1_error),
+ MSM_PIN_FUNCTION(tsif1_sync),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vsense_trigger),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8350.c b/drivers/pinctrl/qcom/pinctrl-sm8350.c
index 1c042d39380c..9c69458bd910 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8350.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8350.c
@@ -7,24 +7,16 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -61,9 +53,9 @@
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -86,9 +78,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -1250,142 +1242,142 @@ static const char * const vsense_trigger_groups[] = {
"gpio78",
};
-static const struct msm_function sm8350_functions[] = {
- FUNCTION(atest_char),
- FUNCTION(atest_usb),
- FUNCTION(audio_ref),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer),
- FUNCTION(cmu_rng),
- FUNCTION(coex_uart1),
- FUNCTION(coex_uart2),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(dp_hot),
- FUNCTION(dp_lcd),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(gpio),
- FUNCTION(ibi_i3c),
- FUNCTION(jitter_bist),
- FUNCTION(lpass_slimbus),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mi2s0_data0),
- FUNCTION(mi2s0_data1),
- FUNCTION(mi2s0_sck),
- FUNCTION(mi2s0_ws),
- FUNCTION(mi2s1_data0),
- FUNCTION(mi2s1_data1),
- FUNCTION(mi2s1_sck),
- FUNCTION(mi2s1_ws),
- FUNCTION(mi2s2_data0),
- FUNCTION(mi2s2_data1),
- FUNCTION(mi2s2_sck),
- FUNCTION(mi2s2_ws),
- FUNCTION(mss_grfc0),
- FUNCTION(mss_grfc1),
- FUNCTION(mss_grfc10),
- FUNCTION(mss_grfc11),
- FUNCTION(mss_grfc12),
- FUNCTION(mss_grfc2),
- FUNCTION(mss_grfc3),
- FUNCTION(mss_grfc4),
- FUNCTION(mss_grfc5),
- FUNCTION(mss_grfc6),
- FUNCTION(mss_grfc7),
- FUNCTION(mss_grfc8),
- FUNCTION(mss_grfc9),
- FUNCTION(nav_gpio),
- FUNCTION(pa_indicator),
- FUNCTION(pcie0_clkreqn),
- FUNCTION(pcie1_clkreqn),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_clk),
- FUNCTION(pri_mi2s),
- FUNCTION(prng_rosc),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qlink0_enable),
- FUNCTION(qlink0_request),
- FUNCTION(qlink0_wmss),
- FUNCTION(qlink1_enable),
- FUNCTION(qlink1_request),
- FUNCTION(qlink1_wmss),
- FUNCTION(qlink2_enable),
- FUNCTION(qlink2_request),
- FUNCTION(qlink2_wmss),
- FUNCTION(qspi0),
- FUNCTION(qspi1),
- FUNCTION(qspi2),
- FUNCTION(qspi3),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(qup0),
- FUNCTION(qup1),
- FUNCTION(qup10),
- FUNCTION(qup11),
- FUNCTION(qup12),
- FUNCTION(qup13),
- FUNCTION(qup14),
- FUNCTION(qup15),
- FUNCTION(qup16),
- FUNCTION(qup17),
- FUNCTION(qup18),
- FUNCTION(qup19),
- FUNCTION(qup2),
- FUNCTION(qup3),
- FUNCTION(qup4),
- FUNCTION(qup5),
- FUNCTION(qup6),
- FUNCTION(qup7),
- FUNCTION(qup8),
- FUNCTION(qup9),
- FUNCTION(qup_l4),
- FUNCTION(qup_l5),
- FUNCTION(qup_l6),
- FUNCTION(sd_write),
- FUNCTION(sdc40),
- FUNCTION(sdc41),
- FUNCTION(sdc42),
- FUNCTION(sdc43),
- FUNCTION(sdc4_clk),
- FUNCTION(sdc4_cmd),
- FUNCTION(sec_mi2s),
- FUNCTION(tb_trig),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(uim0_clk),
- FUNCTION(uim0_data),
- FUNCTION(uim0_present),
- FUNCTION(uim0_reset),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(usb2phy_ac),
- FUNCTION(usb_phy),
- FUNCTION(vfr_0),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
+static const struct pinfunction sm8350_functions[] = {
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_usb),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer),
+ MSM_PIN_FUNCTION(cmu_rng),
+ MSM_PIN_FUNCTION(coex_uart1),
+ MSM_PIN_FUNCTION(coex_uart2),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(dp_lcd),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(lpass_slimbus),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mi2s0_data0),
+ MSM_PIN_FUNCTION(mi2s0_data1),
+ MSM_PIN_FUNCTION(mi2s0_sck),
+ MSM_PIN_FUNCTION(mi2s0_ws),
+ MSM_PIN_FUNCTION(mi2s1_data0),
+ MSM_PIN_FUNCTION(mi2s1_data1),
+ MSM_PIN_FUNCTION(mi2s1_sck),
+ MSM_PIN_FUNCTION(mi2s1_ws),
+ MSM_PIN_FUNCTION(mi2s2_data0),
+ MSM_PIN_FUNCTION(mi2s2_data1),
+ MSM_PIN_FUNCTION(mi2s2_sck),
+ MSM_PIN_FUNCTION(mi2s2_ws),
+ MSM_PIN_FUNCTION(mss_grfc0),
+ MSM_PIN_FUNCTION(mss_grfc1),
+ MSM_PIN_FUNCTION(mss_grfc10),
+ MSM_PIN_FUNCTION(mss_grfc11),
+ MSM_PIN_FUNCTION(mss_grfc12),
+ MSM_PIN_FUNCTION(mss_grfc2),
+ MSM_PIN_FUNCTION(mss_grfc3),
+ MSM_PIN_FUNCTION(mss_grfc4),
+ MSM_PIN_FUNCTION(mss_grfc5),
+ MSM_PIN_FUNCTION(mss_grfc6),
+ MSM_PIN_FUNCTION(mss_grfc7),
+ MSM_PIN_FUNCTION(mss_grfc8),
+ MSM_PIN_FUNCTION(mss_grfc9),
+ MSM_PIN_FUNCTION(nav_gpio),
+ MSM_PIN_FUNCTION(pa_indicator),
+ MSM_PIN_FUNCTION(pcie0_clkreqn),
+ MSM_PIN_FUNCTION(pcie1_clkreqn),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_clk),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qlink0_enable),
+ MSM_PIN_FUNCTION(qlink0_request),
+ MSM_PIN_FUNCTION(qlink0_wmss),
+ MSM_PIN_FUNCTION(qlink1_enable),
+ MSM_PIN_FUNCTION(qlink1_request),
+ MSM_PIN_FUNCTION(qlink1_wmss),
+ MSM_PIN_FUNCTION(qlink2_enable),
+ MSM_PIN_FUNCTION(qlink2_request),
+ MSM_PIN_FUNCTION(qlink2_wmss),
+ MSM_PIN_FUNCTION(qspi0),
+ MSM_PIN_FUNCTION(qspi1),
+ MSM_PIN_FUNCTION(qspi2),
+ MSM_PIN_FUNCTION(qspi3),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qup0),
+ MSM_PIN_FUNCTION(qup1),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(qup15),
+ MSM_PIN_FUNCTION(qup16),
+ MSM_PIN_FUNCTION(qup17),
+ MSM_PIN_FUNCTION(qup18),
+ MSM_PIN_FUNCTION(qup19),
+ MSM_PIN_FUNCTION(qup2),
+ MSM_PIN_FUNCTION(qup3),
+ MSM_PIN_FUNCTION(qup4),
+ MSM_PIN_FUNCTION(qup5),
+ MSM_PIN_FUNCTION(qup6),
+ MSM_PIN_FUNCTION(qup7),
+ MSM_PIN_FUNCTION(qup8),
+ MSM_PIN_FUNCTION(qup9),
+ MSM_PIN_FUNCTION(qup_l4),
+ MSM_PIN_FUNCTION(qup_l5),
+ MSM_PIN_FUNCTION(qup_l6),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sdc40),
+ MSM_PIN_FUNCTION(sdc41),
+ MSM_PIN_FUNCTION(sdc42),
+ MSM_PIN_FUNCTION(sdc43),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(tb_trig),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(uim0_clk),
+ MSM_PIN_FUNCTION(uim0_data),
+ MSM_PIN_FUNCTION(uim0_present),
+ MSM_PIN_FUNCTION(uim0_reset),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_0),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8450.c b/drivers/pinctrl/qcom/pinctrl-sm8450.c
index 3110d7bf5698..d11bb1ee9e3d 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8450.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8450.c
@@ -7,24 +7,16 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -63,9 +55,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -88,9 +80,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -1276,143 +1268,143 @@ static const char * const vsense_trigger_groups[] = {
"gpio18",
};
-static const struct msm_function sm8450_functions[] = {
- FUNCTION(gpio),
- FUNCTION(aon_cam),
- FUNCTION(atest_char),
- FUNCTION(atest_usb),
- FUNCTION(audio_ref),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async),
- FUNCTION(cci_i2c),
- FUNCTION(cci_timer),
- FUNCTION(cmu_rng),
- FUNCTION(coex_uart1),
- FUNCTION(coex_uart2),
- FUNCTION(cri_trng),
- FUNCTION(cri_trng0),
- FUNCTION(cri_trng1),
- FUNCTION(dbg_out),
- FUNCTION(ddr_bist),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(dp_hot),
- FUNCTION(egpio),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(ibi_i3c),
- FUNCTION(jitter_bist),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0),
- FUNCTION(mdp_vsync1),
- FUNCTION(mdp_vsync2),
- FUNCTION(mdp_vsync3),
- FUNCTION(mi2s0_data0),
- FUNCTION(mi2s0_data1),
- FUNCTION(mi2s0_sck),
- FUNCTION(mi2s0_ws),
- FUNCTION(mi2s2_data0),
- FUNCTION(mi2s2_data1),
- FUNCTION(mi2s2_sck),
- FUNCTION(mi2s2_ws),
- FUNCTION(mss_grfc0),
- FUNCTION(mss_grfc1),
- FUNCTION(mss_grfc10),
- FUNCTION(mss_grfc11),
- FUNCTION(mss_grfc12),
- FUNCTION(mss_grfc2),
- FUNCTION(mss_grfc3),
- FUNCTION(mss_grfc4),
- FUNCTION(mss_grfc5),
- FUNCTION(mss_grfc6),
- FUNCTION(mss_grfc7),
- FUNCTION(mss_grfc8),
- FUNCTION(mss_grfc9),
- FUNCTION(nav),
- FUNCTION(pcie0_clkreqn),
- FUNCTION(pcie1_clkreqn),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist),
- FUNCTION(pll_clk),
- FUNCTION(pri_mi2s),
- FUNCTION(prng_rosc),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qlink0_enable),
- FUNCTION(qlink0_request),
- FUNCTION(qlink0_wmss),
- FUNCTION(qlink1_enable),
- FUNCTION(qlink1_request),
- FUNCTION(qlink1_wmss),
- FUNCTION(qlink2_enable),
- FUNCTION(qlink2_request),
- FUNCTION(qlink2_wmss),
- FUNCTION(qspi0),
- FUNCTION(qspi1),
- FUNCTION(qspi2),
- FUNCTION(qspi3),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(qup0),
- FUNCTION(qup1),
- FUNCTION(qup10),
- FUNCTION(qup11),
- FUNCTION(qup12),
- FUNCTION(qup13),
- FUNCTION(qup14),
- FUNCTION(qup15),
- FUNCTION(qup16),
- FUNCTION(qup17),
- FUNCTION(qup18),
- FUNCTION(qup19),
- FUNCTION(qup2),
- FUNCTION(qup20),
- FUNCTION(qup21),
- FUNCTION(qup3),
- FUNCTION(qup4),
- FUNCTION(qup5),
- FUNCTION(qup6),
- FUNCTION(qup7),
- FUNCTION(qup8),
- FUNCTION(qup9),
- FUNCTION(qup_l4),
- FUNCTION(qup_l5),
- FUNCTION(qup_l6),
- FUNCTION(sd_write),
- FUNCTION(sdc40),
- FUNCTION(sdc41),
- FUNCTION(sdc42),
- FUNCTION(sdc43),
- FUNCTION(sdc4_clk),
- FUNCTION(sdc4_cmd),
- FUNCTION(sec_mi2s),
- FUNCTION(tb_trig),
- FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
- FUNCTION(tgu_ch2),
- FUNCTION(tgu_ch3),
- FUNCTION(tmess_prng0),
- FUNCTION(tmess_prng1),
- FUNCTION(tmess_prng2),
- FUNCTION(tmess_prng3),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(uim0_clk),
- FUNCTION(uim0_data),
- FUNCTION(uim0_present),
- FUNCTION(uim0_reset),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(usb2phy_ac),
- FUNCTION(usb_phy),
- FUNCTION(vfr_0),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger),
+static const struct pinfunction sm8450_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(aon_cam),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_usb),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer),
+ MSM_PIN_FUNCTION(cmu_rng),
+ MSM_PIN_FUNCTION(coex_uart1),
+ MSM_PIN_FUNCTION(coex_uart2),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(egpio),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(mi2s0_data0),
+ MSM_PIN_FUNCTION(mi2s0_data1),
+ MSM_PIN_FUNCTION(mi2s0_sck),
+ MSM_PIN_FUNCTION(mi2s0_ws),
+ MSM_PIN_FUNCTION(mi2s2_data0),
+ MSM_PIN_FUNCTION(mi2s2_data1),
+ MSM_PIN_FUNCTION(mi2s2_sck),
+ MSM_PIN_FUNCTION(mi2s2_ws),
+ MSM_PIN_FUNCTION(mss_grfc0),
+ MSM_PIN_FUNCTION(mss_grfc1),
+ MSM_PIN_FUNCTION(mss_grfc10),
+ MSM_PIN_FUNCTION(mss_grfc11),
+ MSM_PIN_FUNCTION(mss_grfc12),
+ MSM_PIN_FUNCTION(mss_grfc2),
+ MSM_PIN_FUNCTION(mss_grfc3),
+ MSM_PIN_FUNCTION(mss_grfc4),
+ MSM_PIN_FUNCTION(mss_grfc5),
+ MSM_PIN_FUNCTION(mss_grfc6),
+ MSM_PIN_FUNCTION(mss_grfc7),
+ MSM_PIN_FUNCTION(mss_grfc8),
+ MSM_PIN_FUNCTION(mss_grfc9),
+ MSM_PIN_FUNCTION(nav),
+ MSM_PIN_FUNCTION(pcie0_clkreqn),
+ MSM_PIN_FUNCTION(pcie1_clkreqn),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_clk),
+ MSM_PIN_FUNCTION(pri_mi2s),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qlink0_enable),
+ MSM_PIN_FUNCTION(qlink0_request),
+ MSM_PIN_FUNCTION(qlink0_wmss),
+ MSM_PIN_FUNCTION(qlink1_enable),
+ MSM_PIN_FUNCTION(qlink1_request),
+ MSM_PIN_FUNCTION(qlink1_wmss),
+ MSM_PIN_FUNCTION(qlink2_enable),
+ MSM_PIN_FUNCTION(qlink2_request),
+ MSM_PIN_FUNCTION(qlink2_wmss),
+ MSM_PIN_FUNCTION(qspi0),
+ MSM_PIN_FUNCTION(qspi1),
+ MSM_PIN_FUNCTION(qspi2),
+ MSM_PIN_FUNCTION(qspi3),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qup0),
+ MSM_PIN_FUNCTION(qup1),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup12),
+ MSM_PIN_FUNCTION(qup13),
+ MSM_PIN_FUNCTION(qup14),
+ MSM_PIN_FUNCTION(qup15),
+ MSM_PIN_FUNCTION(qup16),
+ MSM_PIN_FUNCTION(qup17),
+ MSM_PIN_FUNCTION(qup18),
+ MSM_PIN_FUNCTION(qup19),
+ MSM_PIN_FUNCTION(qup2),
+ MSM_PIN_FUNCTION(qup20),
+ MSM_PIN_FUNCTION(qup21),
+ MSM_PIN_FUNCTION(qup3),
+ MSM_PIN_FUNCTION(qup4),
+ MSM_PIN_FUNCTION(qup5),
+ MSM_PIN_FUNCTION(qup6),
+ MSM_PIN_FUNCTION(qup7),
+ MSM_PIN_FUNCTION(qup8),
+ MSM_PIN_FUNCTION(qup9),
+ MSM_PIN_FUNCTION(qup_l4),
+ MSM_PIN_FUNCTION(qup_l5),
+ MSM_PIN_FUNCTION(qup_l6),
+ MSM_PIN_FUNCTION(sd_write),
+ MSM_PIN_FUNCTION(sdc40),
+ MSM_PIN_FUNCTION(sdc41),
+ MSM_PIN_FUNCTION(sdc42),
+ MSM_PIN_FUNCTION(sdc43),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sec_mi2s),
+ MSM_PIN_FUNCTION(tb_trig),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tmess_prng0),
+ MSM_PIN_FUNCTION(tmess_prng1),
+ MSM_PIN_FUNCTION(tmess_prng2),
+ MSM_PIN_FUNCTION(tmess_prng3),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(uim0_clk),
+ MSM_PIN_FUNCTION(uim0_data),
+ MSM_PIN_FUNCTION(uim0_present),
+ MSM_PIN_FUNCTION(uim0_reset),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_0),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8550.c b/drivers/pinctrl/qcom/pinctrl-sm8550.c
index c9d038098f2c..3c847d9cb5d9 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8550.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8550.c
@@ -8,24 +8,16 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-msm.h"
-#define FUNCTION(fname) \
- [msm_mux_##fname] = { \
- .name = #fname, \
- .groups = fname##_groups, \
- .ngroups = ARRAY_SIZE(fname##_groups), \
- }
-
#define REG_SIZE 0x1000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
- .name = "gpio" #id, \
- .pins = gpio##id##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
.funcs = (int[]){ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
@@ -65,9 +57,9 @@
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = ctl, \
.io_reg = 0, \
.intr_cfg_reg = 0, \
@@ -90,9 +82,9 @@
#define UFS_RESET(pg_name, offset) \
{ \
- .name = #pg_name, \
- .pins = pg_name##_pins, \
- .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.intr_cfg_reg = 0, \
@@ -1347,153 +1339,153 @@ static const char *const vsense_trigger_mirnat_groups[] = {
"gpio24",
};
-static const struct msm_function sm8550_functions[] = {
- FUNCTION(gpio),
- FUNCTION(aon_cci),
- FUNCTION(aoss_cti),
- FUNCTION(atest_char),
- FUNCTION(atest_usb),
- FUNCTION(audio_ext_mclk0),
- FUNCTION(audio_ext_mclk1),
- FUNCTION(audio_ref_clk),
- FUNCTION(cam_aon_mclk4),
- FUNCTION(cam_mclk),
- FUNCTION(cci_async_in),
- FUNCTION(cci_i2c_scl),
- FUNCTION(cci_i2c_sda),
- FUNCTION(cci_timer),
- FUNCTION(cmu_rng),
- FUNCTION(coex_uart1_rx),
- FUNCTION(coex_uart1_tx),
- FUNCTION(coex_uart2_rx),
- FUNCTION(coex_uart2_tx),
- FUNCTION(cri_trng),
- FUNCTION(dbg_out_clk),
- FUNCTION(ddr_bist_complete),
- FUNCTION(ddr_bist_fail),
- FUNCTION(ddr_bist_start),
- FUNCTION(ddr_bist_stop),
- FUNCTION(ddr_pxi0),
- FUNCTION(ddr_pxi1),
- FUNCTION(ddr_pxi2),
- FUNCTION(ddr_pxi3),
- FUNCTION(dp_hot),
- FUNCTION(gcc_gp1),
- FUNCTION(gcc_gp2),
- FUNCTION(gcc_gp3),
- FUNCTION(i2chub0_se0),
- FUNCTION(i2chub0_se1),
- FUNCTION(i2chub0_se2),
- FUNCTION(i2chub0_se3),
- FUNCTION(i2chub0_se4),
- FUNCTION(i2chub0_se5),
- FUNCTION(i2chub0_se6),
- FUNCTION(i2chub0_se7),
- FUNCTION(i2chub0_se8),
- FUNCTION(i2chub0_se9),
- FUNCTION(i2s0_data0),
- FUNCTION(i2s0_data1),
- FUNCTION(i2s0_sck),
- FUNCTION(i2s0_ws),
- FUNCTION(i2s1_data0),
- FUNCTION(i2s1_data1),
- FUNCTION(i2s1_sck),
- FUNCTION(i2s1_ws),
- FUNCTION(ibi_i3c),
- FUNCTION(jitter_bist),
- FUNCTION(mdp_vsync),
- FUNCTION(mdp_vsync0_out),
- FUNCTION(mdp_vsync1_out),
- FUNCTION(mdp_vsync2_out),
- FUNCTION(mdp_vsync3_out),
- FUNCTION(mdp_vsync_e),
- FUNCTION(nav_gpio0),
- FUNCTION(nav_gpio1),
- FUNCTION(nav_gpio2),
- FUNCTION(pcie0_clk_req_n),
- FUNCTION(pcie1_clk_req_n),
- FUNCTION(phase_flag),
- FUNCTION(pll_bist_sync),
- FUNCTION(pll_clk_aux),
- FUNCTION(prng_rosc0),
- FUNCTION(prng_rosc1),
- FUNCTION(prng_rosc2),
- FUNCTION(prng_rosc3),
- FUNCTION(qdss_cti),
- FUNCTION(qdss_gpio),
- FUNCTION(qlink0_enable),
- FUNCTION(qlink0_request),
- FUNCTION(qlink0_wmss),
- FUNCTION(qlink1_enable),
- FUNCTION(qlink1_request),
- FUNCTION(qlink1_wmss),
- FUNCTION(qlink2_enable),
- FUNCTION(qlink2_request),
- FUNCTION(qlink2_wmss),
- FUNCTION(qspi0),
- FUNCTION(qspi1),
- FUNCTION(qspi2),
- FUNCTION(qspi3),
- FUNCTION(qspi_clk),
- FUNCTION(qspi_cs),
- FUNCTION(qup1_se0),
- FUNCTION(qup1_se1),
- FUNCTION(qup1_se2),
- FUNCTION(qup1_se3),
- FUNCTION(qup1_se4),
- FUNCTION(qup1_se5),
- FUNCTION(qup1_se6),
- FUNCTION(qup1_se7),
- FUNCTION(qup2_se0),
- FUNCTION(qup2_se0_l0_mira),
- FUNCTION(qup2_se0_l0_mirb),
- FUNCTION(qup2_se0_l1_mira),
- FUNCTION(qup2_se0_l1_mirb),
- FUNCTION(qup2_se0_l2_mira),
- FUNCTION(qup2_se0_l2_mirb),
- FUNCTION(qup2_se0_l3_mira),
- FUNCTION(qup2_se0_l3_mirb),
- FUNCTION(qup2_se1),
- FUNCTION(qup2_se2),
- FUNCTION(qup2_se3),
- FUNCTION(qup2_se4),
- FUNCTION(qup2_se5),
- FUNCTION(qup2_se6),
- FUNCTION(qup2_se7),
- FUNCTION(resout_n),
- FUNCTION(sd_write_protect),
- FUNCTION(sdc40),
- FUNCTION(sdc41),
- FUNCTION(sdc42),
- FUNCTION(sdc43),
- FUNCTION(sdc4_clk),
- FUNCTION(sdc4_cmd),
- FUNCTION(tb_trig_sdc2),
- FUNCTION(tb_trig_sdc4),
- FUNCTION(tgu_ch0_trigout),
- FUNCTION(tgu_ch1_trigout),
- FUNCTION(tgu_ch2_trigout),
- FUNCTION(tgu_ch3_trigout),
- FUNCTION(tmess_prng0),
- FUNCTION(tmess_prng1),
- FUNCTION(tmess_prng2),
- FUNCTION(tmess_prng3),
- FUNCTION(tsense_pwm1),
- FUNCTION(tsense_pwm2),
- FUNCTION(tsense_pwm3),
- FUNCTION(uim0_clk),
- FUNCTION(uim0_data),
- FUNCTION(uim0_present),
- FUNCTION(uim0_reset),
- FUNCTION(uim1_clk),
- FUNCTION(uim1_data),
- FUNCTION(uim1_present),
- FUNCTION(uim1_reset),
- FUNCTION(usb1_hs),
- FUNCTION(usb_phy),
- FUNCTION(vfr_0),
- FUNCTION(vfr_1),
- FUNCTION(vsense_trigger_mirnat),
+static const struct pinfunction sm8550_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(aon_cci),
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_usb),
+ MSM_PIN_FUNCTION(audio_ext_mclk0),
+ MSM_PIN_FUNCTION(audio_ext_mclk1),
+ MSM_PIN_FUNCTION(audio_ref_clk),
+ MSM_PIN_FUNCTION(cam_aon_mclk4),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async_in),
+ MSM_PIN_FUNCTION(cci_i2c_scl),
+ MSM_PIN_FUNCTION(cci_i2c_sda),
+ MSM_PIN_FUNCTION(cci_timer),
+ MSM_PIN_FUNCTION(cmu_rng),
+ MSM_PIN_FUNCTION(coex_uart1_rx),
+ MSM_PIN_FUNCTION(coex_uart1_tx),
+ MSM_PIN_FUNCTION(coex_uart2_rx),
+ MSM_PIN_FUNCTION(coex_uart2_tx),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(dbg_out_clk),
+ MSM_PIN_FUNCTION(ddr_bist_complete),
+ MSM_PIN_FUNCTION(ddr_bist_fail),
+ MSM_PIN_FUNCTION(ddr_bist_start),
+ MSM_PIN_FUNCTION(ddr_bist_stop),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(i2chub0_se0),
+ MSM_PIN_FUNCTION(i2chub0_se1),
+ MSM_PIN_FUNCTION(i2chub0_se2),
+ MSM_PIN_FUNCTION(i2chub0_se3),
+ MSM_PIN_FUNCTION(i2chub0_se4),
+ MSM_PIN_FUNCTION(i2chub0_se5),
+ MSM_PIN_FUNCTION(i2chub0_se6),
+ MSM_PIN_FUNCTION(i2chub0_se7),
+ MSM_PIN_FUNCTION(i2chub0_se8),
+ MSM_PIN_FUNCTION(i2chub0_se9),
+ MSM_PIN_FUNCTION(i2s0_data0),
+ MSM_PIN_FUNCTION(i2s0_data1),
+ MSM_PIN_FUNCTION(i2s0_sck),
+ MSM_PIN_FUNCTION(i2s0_ws),
+ MSM_PIN_FUNCTION(i2s1_data0),
+ MSM_PIN_FUNCTION(i2s1_data1),
+ MSM_PIN_FUNCTION(i2s1_sck),
+ MSM_PIN_FUNCTION(i2s1_ws),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0_out),
+ MSM_PIN_FUNCTION(mdp_vsync1_out),
+ MSM_PIN_FUNCTION(mdp_vsync2_out),
+ MSM_PIN_FUNCTION(mdp_vsync3_out),
+ MSM_PIN_FUNCTION(mdp_vsync_e),
+ MSM_PIN_FUNCTION(nav_gpio0),
+ MSM_PIN_FUNCTION(nav_gpio1),
+ MSM_PIN_FUNCTION(nav_gpio2),
+ MSM_PIN_FUNCTION(pcie0_clk_req_n),
+ MSM_PIN_FUNCTION(pcie1_clk_req_n),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist_sync),
+ MSM_PIN_FUNCTION(pll_clk_aux),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(prng_rosc2),
+ MSM_PIN_FUNCTION(prng_rosc3),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qlink0_enable),
+ MSM_PIN_FUNCTION(qlink0_request),
+ MSM_PIN_FUNCTION(qlink0_wmss),
+ MSM_PIN_FUNCTION(qlink1_enable),
+ MSM_PIN_FUNCTION(qlink1_request),
+ MSM_PIN_FUNCTION(qlink1_wmss),
+ MSM_PIN_FUNCTION(qlink2_enable),
+ MSM_PIN_FUNCTION(qlink2_request),
+ MSM_PIN_FUNCTION(qlink2_wmss),
+ MSM_PIN_FUNCTION(qspi0),
+ MSM_PIN_FUNCTION(qspi1),
+ MSM_PIN_FUNCTION(qspi2),
+ MSM_PIN_FUNCTION(qspi3),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qup1_se0),
+ MSM_PIN_FUNCTION(qup1_se1),
+ MSM_PIN_FUNCTION(qup1_se2),
+ MSM_PIN_FUNCTION(qup1_se3),
+ MSM_PIN_FUNCTION(qup1_se4),
+ MSM_PIN_FUNCTION(qup1_se5),
+ MSM_PIN_FUNCTION(qup1_se6),
+ MSM_PIN_FUNCTION(qup1_se7),
+ MSM_PIN_FUNCTION(qup2_se0),
+ MSM_PIN_FUNCTION(qup2_se0_l0_mira),
+ MSM_PIN_FUNCTION(qup2_se0_l0_mirb),
+ MSM_PIN_FUNCTION(qup2_se0_l1_mira),
+ MSM_PIN_FUNCTION(qup2_se0_l1_mirb),
+ MSM_PIN_FUNCTION(qup2_se0_l2_mira),
+ MSM_PIN_FUNCTION(qup2_se0_l2_mirb),
+ MSM_PIN_FUNCTION(qup2_se0_l3_mira),
+ MSM_PIN_FUNCTION(qup2_se0_l3_mirb),
+ MSM_PIN_FUNCTION(qup2_se1),
+ MSM_PIN_FUNCTION(qup2_se2),
+ MSM_PIN_FUNCTION(qup2_se3),
+ MSM_PIN_FUNCTION(qup2_se4),
+ MSM_PIN_FUNCTION(qup2_se5),
+ MSM_PIN_FUNCTION(qup2_se6),
+ MSM_PIN_FUNCTION(qup2_se7),
+ MSM_PIN_FUNCTION(resout_n),
+ MSM_PIN_FUNCTION(sd_write_protect),
+ MSM_PIN_FUNCTION(sdc40),
+ MSM_PIN_FUNCTION(sdc41),
+ MSM_PIN_FUNCTION(sdc42),
+ MSM_PIN_FUNCTION(sdc43),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(tb_trig_sdc2),
+ MSM_PIN_FUNCTION(tb_trig_sdc4),
+ MSM_PIN_FUNCTION(tgu_ch0_trigout),
+ MSM_PIN_FUNCTION(tgu_ch1_trigout),
+ MSM_PIN_FUNCTION(tgu_ch2_trigout),
+ MSM_PIN_FUNCTION(tgu_ch3_trigout),
+ MSM_PIN_FUNCTION(tmess_prng0),
+ MSM_PIN_FUNCTION(tmess_prng1),
+ MSM_PIN_FUNCTION(tmess_prng2),
+ MSM_PIN_FUNCTION(tmess_prng3),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(tsense_pwm3),
+ MSM_PIN_FUNCTION(uim0_clk),
+ MSM_PIN_FUNCTION(uim0_data),
+ MSM_PIN_FUNCTION(uim0_present),
+ MSM_PIN_FUNCTION(uim0_reset),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(usb1_hs),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_0),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger_mirnat),
};
/*
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
index 43c7857c06a5..b4cd66886f29 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
@@ -1229,6 +1229,8 @@ static const struct of_device_id pmic_gpio_of_match[] = {
{ .compatible = "qcom,pm8941-gpio", .data = (void *) 36 },
/* pm8950 has 8 GPIOs with holes on 3 */
{ .compatible = "qcom,pm8950-gpio", .data = (void *) 8 },
+ /* pm8953 has 8 GPIOs with holes on 3 and 6 */
+ { .compatible = "qcom,pm8953-gpio", .data = (void *) 8 },
{ .compatible = "qcom,pm8994-gpio", .data = (void *) 22 },
{ .compatible = "qcom,pm8998-gpio", .data = (void *) 26 },
{ .compatible = "qcom,pma8084-gpio", .data = (void *) 22 },
diff --git a/drivers/pinctrl/renesas/pfc-r8a77970.c b/drivers/pinctrl/renesas/pfc-r8a77970.c
index 5b66d7b1af95..e1b3e3b38ec3 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77970.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77970.c
@@ -171,7 +171,7 @@
#define IP0_31_28 FM(DU_DG3) FM(MSIOF3_SS2) F_(0, 0) FM(A7) FM(PWMFSW0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP1_3_0 FM(DU_DG4) F_(0, 0) F_(0, 0) FM(A8) FM(FSO_CFE_0_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP1_7_4 FM(DU_DG5) F_(0, 0) F_(0, 0) FM(A9) FM(FSO_CFE_1_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP1_11_8 FM(DU_DG6) F_(0, 0) F_(0, 0) FM(A10) FM(FSO_TOE_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP1_11_8 FM(DU_DG6) F_(0, 0) F_(0, 0) FM(A10) FM(FSO_TOE_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP1_15_12 FM(DU_DG7) F_(0, 0) F_(0, 0) FM(A11) FM(IRQ1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP1_19_16 FM(DU_DB2) F_(0, 0) F_(0, 0) FM(A12) FM(IRQ2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP1_23_20 FM(DU_DB3) F_(0, 0) F_(0, 0) FM(A13) FM(FXR_CLKOUT1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
diff --git a/drivers/pinctrl/renesas/pfc-r8a77980.c b/drivers/pinctrl/renesas/pfc-r8a77980.c
index 384faa0d6937..877134d78c7e 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77980.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77980.c
@@ -99,7 +99,7 @@
#define GPSR1_0 F_(IRQ0, IP2_27_24)
/* GPSR2 */
-#define GPSR2_29 F_(FSO_TOE_N, IP10_19_16)
+#define GPSR2_29 F_(FSO_TOE_N, IP10_19_16)
#define GPSR2_28 F_(FSO_CFE_1_N, IP10_15_12)
#define GPSR2_27 F_(FSO_CFE_0_N, IP10_11_8)
#define GPSR2_26 F_(SDA3, IP10_7_4)
@@ -264,11 +264,11 @@
#define IP8_11_8 FM(CANFD0_RX_A) FM(RXDA_EXTFXR) FM(PWM1_B) FM(DU_CDE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP8_15_12 FM(CANFD1_TX) FM(FXR_TXDB) FM(PWM2_B) FM(TCLK1_B) FM(TX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP8_19_16 FM(CANFD1_RX) FM(RXDB_EXTFXR) FM(PWM3_B) FM(TCLK2_B) FM(RX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP8_23_20 FM(CANFD_CLK_A) FM(CLK_EXTFXR) FM(PWM4_B) FM(SPEEDIN_B) FM(SCIF_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP8_23_20 FM(CANFD_CLK_A) FM(CLK_EXTFXR) FM(PWM4_B) FM(SPEEDIN_B) FM(SCIF_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP8_27_24 FM(DIGRF_CLKIN) FM(DIGRF_CLKEN_IN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP8_31_28 FM(DIGRF_CLKOUT) FM(DIGRF_CLKEN_OUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP9_3_0 FM(IRQ4) F_(0, 0) F_(0, 0) FM(VI0_DATA12) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP9_7_4 FM(IRQ5) F_(0, 0) F_(0, 0) FM(VI0_DATA13) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP9_7_4 FM(IRQ5) F_(0, 0) F_(0, 0) FM(VI0_DATA13) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP9_11_8 FM(MSIOF0_RXD) FM(DU_DR0) F_(0, 0) FM(VI0_DATA14) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP9_15_12 FM(MSIOF0_TXD) FM(DU_DR1) F_(0, 0) FM(VI0_DATA15) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
#define IP9_19_16 FM(MSIOF0_SCK) FM(DU_DG0) F_(0, 0) FM(VI0_DATA16) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index 18de2e70ea50..b8caaa5a2d4e 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -18,7 +18,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
-#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
diff --git a/drivers/pinctrl/stm32/Kconfig b/drivers/pinctrl/stm32/Kconfig
index d532f3c6f670..2656d3d3ae40 100644
--- a/drivers/pinctrl/stm32/Kconfig
+++ b/drivers/pinctrl/stm32/Kconfig
@@ -51,4 +51,10 @@ config PINCTRL_STM32MP157
depends on OF && HAS_IOMEM
default MACH_STM32MP157
select PINCTRL_STM32
+
+config PINCTRL_STM32MP257
+ bool "STMicroelectronics STM32MP257 pin control" if COMPILE_TEST && !MACH_STM32MP25
+ depends on OF && HAS_IOMEM
+ default MACH_STM32MP25
+ select PINCTRL_STM32
endif
diff --git a/drivers/pinctrl/stm32/Makefile b/drivers/pinctrl/stm32/Makefile
index 619629ee9944..7b17464d8de1 100644
--- a/drivers/pinctrl/stm32/Makefile
+++ b/drivers/pinctrl/stm32/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_PINCTRL_STM32F769) += pinctrl-stm32f769.o
obj-$(CONFIG_PINCTRL_STM32H743) += pinctrl-stm32h743.o
obj-$(CONFIG_PINCTRL_STM32MP135) += pinctrl-stm32mp135.o
obj-$(CONFIG_PINCTRL_STM32MP157) += pinctrl-stm32mp157.o
+obj-$(CONFIG_PINCTRL_STM32MP257) += pinctrl-stm32mp257.o
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h
index e0c31c4c8bca..5e5de92ddd58 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.h
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.h
@@ -24,6 +24,9 @@
#define STM32MP_PKG_AB BIT(1)
#define STM32MP_PKG_AC BIT(2)
#define STM32MP_PKG_AD BIT(3)
+#define STM32MP_PKG_AI BIT(8)
+#define STM32MP_PKG_AK BIT(10)
+#define STM32MP_PKG_AL BIT(11)
struct stm32_desc_function {
const char *name;
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp257.c b/drivers/pinctrl/stm32/pinctrl-stm32mp257.c
new file mode 100644
index 000000000000..73f091cd827e
--- /dev/null
+++ b/drivers/pinctrl/stm32/pinctrl-stm32mp257.c
@@ -0,0 +1,2581 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-stm32.h"
+
+static const struct stm32_desc_pin stm32mp257_pins[] = {
+ STM32_PIN_PKG(
+ PINCTRL_PIN(0, "PA0"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA0"),
+ STM32_FUNCTION(2, "LPTIM1_CH2"),
+ STM32_FUNCTION(3, "SPI5_RDY"),
+ STM32_FUNCTION(4, "UART8_CTS"),
+ STM32_FUNCTION(5, "SAI2_MCLK_B"),
+ STM32_FUNCTION(6, "UART5_TX"),
+ STM32_FUNCTION(7, "USART3_TX"),
+ STM32_FUNCTION(8, "TIM3_ETR"),
+ STM32_FUNCTION(9, "TIM5_CH2"),
+ STM32_FUNCTION(11, "ETH2_MII_RXD2 ETH2_RGMII_RXD2"),
+ STM32_FUNCTION(13, "FMC_NL"),
+ STM32_FUNCTION(15, "DCMI_D9 PSSI_D9 DCMIPP_D9"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(1, "PA1"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA1"),
+ STM32_FUNCTION(3, "SPI6_MISO"),
+ STM32_FUNCTION(5, "SAI3_SD_A"),
+ STM32_FUNCTION(6, "USART1_RTS"),
+ STM32_FUNCTION(7, "USART6_CK"),
+ STM32_FUNCTION(8, "TIM4_CH2"),
+ STM32_FUNCTION(9, "I2C4_SDA"),
+ STM32_FUNCTION(10, "I2C6_SDA"),
+ STM32_FUNCTION(12, "LCD_R3"),
+ STM32_FUNCTION(14, "DCMI_D5 PSSI_D5 DCMIPP_D5"),
+ STM32_FUNCTION(15, "ETH3_PHY_INTN"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(2, "PA2"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA2"),
+ STM32_FUNCTION(2, "LPTIM2_IN1"),
+ STM32_FUNCTION(3, "SPI7_MISO"),
+ STM32_FUNCTION(6, "MDF1_SDI7"),
+ STM32_FUNCTION(7, "USART1_RX"),
+ STM32_FUNCTION(9, "I3C1_SDA"),
+ STM32_FUNCTION(11, "I2C1_SDA"),
+ STM32_FUNCTION(12, "LCD_B0"),
+ STM32_FUNCTION(14, "DCMI_D3 PSSI_D3 DCMIPP_D3"),
+ STM32_FUNCTION(15, "ETH3_RGMII_RX_CTL ETH3_RMII_CRS_DV"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(3, "PA3"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA3"),
+ STM32_FUNCTION(2, "LPTIM2_ETR"),
+ STM32_FUNCTION(3, "SPI7_MOSI"),
+ STM32_FUNCTION(6, "MDF1_CKI7"),
+ STM32_FUNCTION(7, "USART1_TX"),
+ STM32_FUNCTION(9, "I3C1_SCL"),
+ STM32_FUNCTION(10, "I2C7_SMBA"),
+ STM32_FUNCTION(11, "I2C1_SCL"),
+ STM32_FUNCTION(12, "LCD_B1"),
+ STM32_FUNCTION(14, "DCMI_D2 PSSI_D2 DCMIPP_D2"),
+ STM32_FUNCTION(15, "ETH3_RGMII_TX_CTL ETH3_RMII_TX_EN"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(4, "PA4"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA4"),
+ STM32_FUNCTION(7, "USART2_TX"),
+ STM32_FUNCTION(8, "FDCAN2_TX"),
+ STM32_FUNCTION(9, "TIM2_CH1"),
+ STM32_FUNCTION(11, "LCD_R1"),
+ STM32_FUNCTION(14, "ETH1_PTP_AUX_TS"),
+ STM32_FUNCTION(15, "ETH3_PPS_OUT"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(5, "PA5"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA5"),
+ STM32_FUNCTION(4, "SPI4_MOSI"),
+ STM32_FUNCTION(5, "SAI2_MCLK_B"),
+ STM32_FUNCTION(6, "SAI2_SD_B"),
+ STM32_FUNCTION(7, "USART2_RTS"),
+ STM32_FUNCTION(8, "FDCAN2_RX"),
+ STM32_FUNCTION(9, "TIM2_CH4"),
+ STM32_FUNCTION(11, "LCD_G0"),
+ STM32_FUNCTION(13, "FMC_A0"),
+ STM32_FUNCTION(14, "DCMI_D13 PSSI_D13 DCMIPP_D13"),
+ STM32_FUNCTION(15, "ETH3_RGMII_RX_CLK ETH3_RMII_REF_CLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(6, "PA6"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA6"),
+ STM32_FUNCTION(4, "SPI4_SCK"),
+ STM32_FUNCTION(5, "SAI2_FS_B"),
+ STM32_FUNCTION(6, "MDF1_SDI6"),
+ STM32_FUNCTION(7, "USART2_CK"),
+ STM32_FUNCTION(8, "TIM13_CH1"),
+ STM32_FUNCTION(9, "TIM2_ETR"),
+ STM32_FUNCTION(11, "LCD_G4"),
+ STM32_FUNCTION(13, "FMC_NE1"),
+ STM32_FUNCTION(14, "DCMI_D12 PSSI_D12 DCMIPP_D12"),
+ STM32_FUNCTION(15, "ETH3_RGMII_TXD0 ETH3_RMII_TXD0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(7, "PA7"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA7"),
+ STM32_FUNCTION(3, "AUDIOCLK"),
+ STM32_FUNCTION(4, "SPI6_RDY"),
+ STM32_FUNCTION(5, "PCIE_CLKREQN"),
+ STM32_FUNCTION(6, "MDF1_CCK0"),
+ STM32_FUNCTION(7, "USART1_CTS"),
+ STM32_FUNCTION(8, "TIM4_ETR"),
+ STM32_FUNCTION(9, "I2C2_SMBA"),
+ STM32_FUNCTION(10, "I2C6_SMBA"),
+ STM32_FUNCTION(11, "LCD_B5"),
+ STM32_FUNCTION(12, "I2C3_SMBA"),
+ STM32_FUNCTION(13, "I2C4_SMBA"),
+ STM32_FUNCTION(14, "DCMI_D6 PSSI_D6 DCMIPP_D6"),
+ STM32_FUNCTION(15, "ETH3_RGMII_TXD1 ETH3_RMII_TXD1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(8, "PA8"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA8"),
+ STM32_FUNCTION(2, "LPTIM2_CH2"),
+ STM32_FUNCTION(3, "SPI7_NSS"),
+ STM32_FUNCTION(5, "SAI1_FS_B"),
+ STM32_FUNCTION(7, "USART1_CK"),
+ STM32_FUNCTION(9, "USART2_RX"),
+ STM32_FUNCTION(10, "I2C5_SCL"),
+ STM32_FUNCTION(13, "LCD_B2"),
+ STM32_FUNCTION(14, "DCMI_D4 PSSI_D4 DCMIPP_D4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(9, "PA9"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA9"),
+ STM32_FUNCTION(4, "SPI4_NSS"),
+ STM32_FUNCTION(5, "SAI2_SCK_B"),
+ STM32_FUNCTION(7, "USART2_CTS"),
+ STM32_FUNCTION(8, "LPTIM5_ETR"),
+ STM32_FUNCTION(9, "TIM2_CH3"),
+ STM32_FUNCTION(11, "ETH1_MDC"),
+ STM32_FUNCTION(13, "LCD_G7"),
+ STM32_FUNCTION(14, "PSSI_D14 DCMIPP_D14"),
+ STM32_FUNCTION(15, "ETH3_RGMII_RXD0 ETH3_RMII_RXD0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(10, "PA10"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA10"),
+ STM32_FUNCTION(4, "SPI4_MISO"),
+ STM32_FUNCTION(5, "SAI2_SD_B"),
+ STM32_FUNCTION(7, "USART2_RX"),
+ STM32_FUNCTION(8, "LPTIM5_IN1"),
+ STM32_FUNCTION(9, "TIM2_CH2"),
+ STM32_FUNCTION(11, "ETH1_MDIO"),
+ STM32_FUNCTION(13, "LCD_R6"),
+ STM32_FUNCTION(14, "PSSI_D15 DCMIPP_D15"),
+ STM32_FUNCTION(15, "ETH3_RGMII_RXD1 ETH3_RMII_RXD1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(11, "PA11"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA11"),
+ STM32_FUNCTION(2, "SPI8_SCK"),
+ STM32_FUNCTION(3, "LPTIM2_CH1"),
+ STM32_FUNCTION(5, "SAI4_SD_B"),
+ STM32_FUNCTION(6, "MDF1_SDI4"),
+ STM32_FUNCTION(11, "ETH1_MII_RX_DV ETH1_RGMII_RX_CTL ETH1_RMII_CRS_DV"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(12, "PA12"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA12"),
+ STM32_FUNCTION(3, "SPI6_MOSI"),
+ STM32_FUNCTION(5, "SAI3_FS_A"),
+ STM32_FUNCTION(8, "TIM4_CH1"),
+ STM32_FUNCTION(9, "I2C4_SCL"),
+ STM32_FUNCTION(10, "I2C6_SCL"),
+ STM32_FUNCTION(11, "ETH1_PHY_INTN"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(13, "PA13"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA13"),
+ STM32_FUNCTION(2, "SPI8_RDY"),
+ STM32_FUNCTION(3, "I2S3_MCK"),
+ STM32_FUNCTION(4, "LPTIM2_ETR"),
+ STM32_FUNCTION(6, "MDF1_CKI3"),
+ STM32_FUNCTION(7, "USART2_CTS"),
+ STM32_FUNCTION(10, "I2C7_SMBA"),
+ STM32_FUNCTION(11, "ETH1_MII_TX_EN ETH1_RGMII_TX_CTL ETH1_RMII_TX_EN"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(14, "PA14"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA14"),
+ STM32_FUNCTION(2, "SPI8_NSS"),
+ STM32_FUNCTION(3, "LPTIM2_CH2"),
+ STM32_FUNCTION(5, "SAI4_FS_B"),
+ STM32_FUNCTION(6, "MDF1_CCK1"),
+ STM32_FUNCTION(11, "ETH1_MII_RX_CLK ETH1_RGMII_RX_CLK ETH1_RMII_REF_CLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(15, "PA15"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOA15"),
+ STM32_FUNCTION(3, "SPI3_MISO I2S3_SDI"),
+ STM32_FUNCTION(7, "USART2_RX"),
+ STM32_FUNCTION(10, "I2C7_SDA"),
+ STM32_FUNCTION(11, "ETH1_MII_TXD0 ETH1_RGMII_TXD0 ETH1_RMII_TXD0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(16, "PB0"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB0"),
+ STM32_FUNCTION(3, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(7, "USART1_CK"),
+ STM32_FUNCTION(8, "TIM16_CH1"),
+ STM32_FUNCTION(9, "TIM20_CH4N"),
+ STM32_FUNCTION(11, "OCTOSPIM_P2_IO0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(17, "PB1"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB1"),
+ STM32_FUNCTION(2, "SPI3_NSS I2S3_WS"),
+ STM32_FUNCTION(8, "TIM16_CH1N"),
+ STM32_FUNCTION(9, "TIM20_CH3N"),
+ STM32_FUNCTION(11, "OCTOSPIM_P2_IO1"),
+ STM32_FUNCTION(13, "FMC_NCE4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(18, "PB2"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB2"),
+ STM32_FUNCTION(3, "SPI2_MOSI I2S2_SDO"),
+ STM32_FUNCTION(6, "MDF1_CKI3"),
+ STM32_FUNCTION(7, "TIM17_BKIN"),
+ STM32_FUNCTION(8, "TIM16_BKIN"),
+ STM32_FUNCTION(9, "TIM20_CH2N"),
+ STM32_FUNCTION(11, "OCTOSPIM_P2_IO2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(19, "PB3"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB3"),
+ STM32_FUNCTION(3, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(6, "MDF1_SDI3"),
+ STM32_FUNCTION(9, "TIM20_CH3"),
+ STM32_FUNCTION(11, "OCTOSPIM_P2_IO3"),
+ STM32_FUNCTION(13, "FMC_NCE3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(20, "PB4"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB4"),
+ STM32_FUNCTION(3, "SPI2_RDY"),
+ STM32_FUNCTION(4, "UART4_CTS"),
+ STM32_FUNCTION(5, "SAI4_FS_B"),
+ STM32_FUNCTION(6, "MDF1_SDI4"),
+ STM32_FUNCTION(7, "TIM14_CH1"),
+ STM32_FUNCTION(9, "TIM20_CH2"),
+ STM32_FUNCTION(10, "I2C2_SDA"),
+ STM32_FUNCTION(11, "OCTOSPIM_P2_IO4"),
+ STM32_FUNCTION(14, "I3C2_SDA"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(21, "PB5"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB5"),
+ STM32_FUNCTION(3, "I2S2_MCK"),
+ STM32_FUNCTION(4, "UART4_RTS"),
+ STM32_FUNCTION(5, "SAI4_SD_B"),
+ STM32_FUNCTION(6, "MDF1_CKI4"),
+ STM32_FUNCTION(9, "TIM20_CH1"),
+ STM32_FUNCTION(10, "I2C2_SCL"),
+ STM32_FUNCTION(11, "OCTOSPIM_P2_IO5"),
+ STM32_FUNCTION(13, "FMC_AD8 FMC_D8"),
+ STM32_FUNCTION(14, "I3C2_SCL"),
+ STM32_FUNCTION(15, "SDMMC3_D123DIR"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(22, "PB6"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB6"),
+ STM32_FUNCTION(3, "SPI2_MISO I2S2_SDI"),
+ STM32_FUNCTION(4, "UART4_RX"),
+ STM32_FUNCTION(5, "SAI4_SCK_B"),
+ STM32_FUNCTION(9, "TIM20_CH1N"),
+ STM32_FUNCTION(11, "OCTOSPIM_P2_IO6"),
+ STM32_FUNCTION(13, "FMC_AD9 FMC_D9"),
+ STM32_FUNCTION(15, "SDMMC3_D0DIR"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(23, "PB7"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB7"),
+ STM32_FUNCTION(2, "SPI3_SCK I2S3_CK"),
+ STM32_FUNCTION(4, "UART4_TX"),
+ STM32_FUNCTION(5, "SAI4_MCLK_B"),
+ STM32_FUNCTION(9, "TIM20_ETR"),
+ STM32_FUNCTION(10, "TIM12_CH1"),
+ STM32_FUNCTION(11, "OCTOSPIM_P2_IO7"),
+ STM32_FUNCTION(13, "FMC_AD10 FMC_D10"),
+ STM32_FUNCTION(15, "SDMMC3_CDIR"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(24, "PB8"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB8"),
+ STM32_FUNCTION(2, "SPI3_MOSI I2S3_SDO"),
+ STM32_FUNCTION(5, "PCIE_CLKREQN"),
+ STM32_FUNCTION(7, "USART1_TX"),
+ STM32_FUNCTION(8, "TIM17_CH1"),
+ STM32_FUNCTION(9, "TIM20_CH4"),
+ STM32_FUNCTION(11, "OCTOSPIM_P2_NCS1"),
+ STM32_FUNCTION(13, "FMC_AD12 FMC_D12"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(25, "PB9"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB9"),
+ STM32_FUNCTION(2, "SPI3_RDY"),
+ STM32_FUNCTION(7, "USART1_RTS"),
+ STM32_FUNCTION(8, "FDCAN1_TX"),
+ STM32_FUNCTION(9, "TIM20_BKIN"),
+ STM32_FUNCTION(10, "TIM10_CH1"),
+ STM32_FUNCTION(11, "OCTOSPIM_P2_DQS"),
+ STM32_FUNCTION(12, "OCTOSPIM_P2_NCS2"),
+ STM32_FUNCTION(13, "FMC_AD13 FMC_D13"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(26, "PB10"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB10"),
+ STM32_FUNCTION(2, "SPI3_MISO I2S3_SDI"),
+ STM32_FUNCTION(7, "USART1_RX"),
+ STM32_FUNCTION(8, "TIM17_CH1N"),
+ STM32_FUNCTION(11, "OCTOSPIM_P2_CLK"),
+ STM32_FUNCTION(13, "FMC_AD15 FMC_D15"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(27, "PB11"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB11"),
+ STM32_FUNCTION(2, "I2S3_MCK"),
+ STM32_FUNCTION(7, "USART1_CTS"),
+ STM32_FUNCTION(8, "FDCAN1_RX"),
+ STM32_FUNCTION(9, "TIM20_BKIN2"),
+ STM32_FUNCTION(10, "TIM12_CH2"),
+ STM32_FUNCTION(11, "OCTOSPIM_P2_NCLK"),
+ STM32_FUNCTION(12, "OCTOSPIM_P2_NCS2"),
+ STM32_FUNCTION(13, "FMC_AD14 FMC_D14"),
+ STM32_FUNCTION(14, "OCTOSPIM_P1_NCS2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(28, "PB12"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB12"),
+ STM32_FUNCTION(6, "UART8_CTS"),
+ STM32_FUNCTION(8, "TIM13_CH1"),
+ STM32_FUNCTION(10, "DSI_TE"),
+ STM32_FUNCTION(11, "SDMMC3_D2"),
+ STM32_FUNCTION(12, "FMC_NWAIT"),
+ STM32_FUNCTION(15, "DCMI_D12 PSSI_D12 DCMIPP_D12"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(29, "PB13"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB13"),
+ STM32_FUNCTION(3, "SPI7_SCK"),
+ STM32_FUNCTION(5, "SAI1_SD_B"),
+ STM32_FUNCTION(6, "UART8_RX"),
+ STM32_FUNCTION(11, "SDMMC3_CK"),
+ STM32_FUNCTION(12, "FMC_AD5 FMC_D5"),
+ STM32_FUNCTION(13, "FMC_AD0 FMC_D0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(30, "PB14"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB14"),
+ STM32_FUNCTION(3, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(6, "MDF1_CKI7"),
+ STM32_FUNCTION(7, "UART9_RX"),
+ STM32_FUNCTION(10, "TIM4_CH2"),
+ STM32_FUNCTION(11, "SDMMC3_D0"),
+ STM32_FUNCTION(12, "FMC_AD7 FMC_D7"),
+ STM32_FUNCTION(13, "FMC_AD2 FMC_D2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(31, "PB15"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOB15"),
+ STM32_FUNCTION(2, "LPTIM1_IN2"),
+ STM32_FUNCTION(3, "SPI5_SCK"),
+ STM32_FUNCTION(4, "UART8_RTS"),
+ STM32_FUNCTION(5, "SAI2_SD_B"),
+ STM32_FUNCTION(6, "UART5_RX"),
+ STM32_FUNCTION(8, "TIM3_CH2"),
+ STM32_FUNCTION(9, "TIM5_CH1"),
+ STM32_FUNCTION(11, "ETH1_PPS_OUT"),
+ STM32_FUNCTION(13, "FMC_A18"),
+ STM32_FUNCTION(14, "LCD_R4"),
+ STM32_FUNCTION(15, "DCMI_D8 PSSI_D8 DCMIPP_D8"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(32, "PC0"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC0"),
+ STM32_FUNCTION(2, "LPTIM1_CH1"),
+ STM32_FUNCTION(4, "SPI6_SCK"),
+ STM32_FUNCTION(5, "SAI3_MCLK_B"),
+ STM32_FUNCTION(6, "USART6_TX"),
+ STM32_FUNCTION(10, "DCMI_D0 PSSI_D0 DCMIPP_D0"),
+ STM32_FUNCTION(11, "ETH2_MII_RX_CLK ETH2_RGMII_RX_CLK ETH2_RMII_REF_CLK"),
+ STM32_FUNCTION(12, "ETH1_MII_TX_CLK"),
+ STM32_FUNCTION(13, "ETH1_RGMII_GTX_CLK"),
+ STM32_FUNCTION(14, "LCD_G7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(33, "PC1"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC1"),
+ STM32_FUNCTION(3, "SPI3_MOSI I2S3_SDO"),
+ STM32_FUNCTION(7, "USART2_TX"),
+ STM32_FUNCTION(10, "I2C7_SCL"),
+ STM32_FUNCTION(11, "ETH1_MII_TXD1 ETH1_RGMII_TXD1 ETH1_RMII_TXD1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(34, "PC2"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC2"),
+ STM32_FUNCTION(2, "SPI8_MOSI"),
+ STM32_FUNCTION(3, "LPTIM2_IN1"),
+ STM32_FUNCTION(5, "SAI4_MCLK_B"),
+ STM32_FUNCTION(6, "MDF1_SDI3"),
+ STM32_FUNCTION(7, "USART2_RTS"),
+ STM32_FUNCTION(11, "ETH1_MII_RXD1 ETH1_RGMII_RXD1 ETH1_RMII_RXD1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(35, "PC3"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC3"),
+ STM32_FUNCTION(2, "LPTIM1_IN2"),
+ STM32_FUNCTION(3, "SPI3_NSS I2S3_WS"),
+ STM32_FUNCTION(4, "SPI6_RDY"),
+ STM32_FUNCTION(7, "USART6_RTS"),
+ STM32_FUNCTION(8, "FDCAN2_TX"),
+ STM32_FUNCTION(11, "ETH2_MII_RX_DV ETH2_RGMII_RX_CTL ETH2_RMII_CRS_DV"),
+ STM32_FUNCTION(12, "ETH1_MII_RX_ER"),
+ STM32_FUNCTION(14, "LCD_G6"),
+ STM32_FUNCTION(15, "DCMI_D3 PSSI_D3 DCMIPP_D3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(36, "PC4"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC4"),
+ STM32_FUNCTION(4, "SPI6_MISO"),
+ STM32_FUNCTION(5, "SAI3_FS_B"),
+ STM32_FUNCTION(11, "ETH2_MII_TX_EN ETH2_RGMII_TX_CTL ETH2_RMII_TX_EN"),
+ STM32_FUNCTION(13, "ETH1_RGMII_CLK125"),
+ STM32_FUNCTION(14, "LCD_R0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(37, "PC5"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC5"),
+ STM32_FUNCTION(3, "SPDIFRX1_IN1"),
+ STM32_FUNCTION(6, "MDF1_SDI1"),
+ STM32_FUNCTION(9, "TIM8_CH1N"),
+ STM32_FUNCTION(10, "I2C4_SDA"),
+ STM32_FUNCTION(11, "ETH2_MDIO"),
+ STM32_FUNCTION(12, "ETH1_MII_COL"),
+ STM32_FUNCTION(13, "FMC_A25"),
+ STM32_FUNCTION(14, "ETH1_PPS_OUT"),
+ STM32_FUNCTION(15, "LCD_DE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(38, "PC6"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC6"),
+ STM32_FUNCTION(2, "RTC_REFIN"),
+ STM32_FUNCTION(3, "SPDIFRX1_IN0"),
+ STM32_FUNCTION(6, "MDF1_CKI1"),
+ STM32_FUNCTION(9, "TIM8_CH1"),
+ STM32_FUNCTION(10, "I2C4_SCL"),
+ STM32_FUNCTION(11, "ETH2_MDC"),
+ STM32_FUNCTION(12, "ETH1_MII_CRS"),
+ STM32_FUNCTION(13, "FMC_A24"),
+ STM32_FUNCTION(14, "ETH1_PHY_INTN"),
+ STM32_FUNCTION(15, "LCD_CLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(39, "PC7"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC7"),
+ STM32_FUNCTION(4, "SPI6_MOSI"),
+ STM32_FUNCTION(5, "SAI3_SD_B"),
+ STM32_FUNCTION(9, "TIM8_CH2N"),
+ STM32_FUNCTION(11, "ETH2_MII_TXD0 ETH2_RGMII_TXD0 ETH2_RMII_TXD0"),
+ STM32_FUNCTION(12, "ETH1_MII_TXD2 ETH1_RGMII_TXD2"),
+ STM32_FUNCTION(14, "LCD_B4"),
+ STM32_FUNCTION(15, "DCMI_D1 PSSI_D1 DCMIPP_D1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(40, "PC8"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC8"),
+ STM32_FUNCTION(2, "LPTIM1_ETR"),
+ STM32_FUNCTION(4, "SPI6_NSS"),
+ STM32_FUNCTION(5, "SAI3_SCK_B"),
+ STM32_FUNCTION(7, "USART6_CTS"),
+ STM32_FUNCTION(9, "TIM8_CH2"),
+ STM32_FUNCTION(11, "ETH2_MII_TXD1 ETH2_RGMII_TXD1 ETH2_RMII_TXD1"),
+ STM32_FUNCTION(12, "ETH1_MII_TXD3 ETH1_RGMII_TXD3"),
+ STM32_FUNCTION(14, "LCD_B3"),
+ STM32_FUNCTION(15, "DCMI_D2 PSSI_D2 DCMIPP_D2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(41, "PC9"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC9"),
+ STM32_FUNCTION(2, "MCO1"),
+ STM32_FUNCTION(3, "SPI3_MISO I2S3_SDI"),
+ STM32_FUNCTION(5, "SAI2_SCK_A"),
+ STM32_FUNCTION(8, "TIM13_CH1"),
+ STM32_FUNCTION(9, "TIM8_CH4N"),
+ STM32_FUNCTION(10, "USBH_HS_OVRCUR"),
+ STM32_FUNCTION(11, "ETH2_MII_TXD2 ETH2_RGMII_TXD2"),
+ STM32_FUNCTION(12, "USB3DR_OVRCUR"),
+ STM32_FUNCTION(13, "FMC_A22"),
+ STM32_FUNCTION(14, "LCD_G2"),
+ STM32_FUNCTION(15, "DCMI_D7 PSSI_D7 DCMIPP_D7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(42, "PC10"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC10"),
+ STM32_FUNCTION(3, "SPI3_MOSI I2S3_SDO"),
+ STM32_FUNCTION(8, "LPTIM4_ETR"),
+ STM32_FUNCTION(9, "TIM8_CH4"),
+ STM32_FUNCTION(10, "USBH_HS_VBUSEN"),
+ STM32_FUNCTION(11, "ETH2_MII_TXD3 ETH2_RGMII_TXD3"),
+ STM32_FUNCTION(12, "USB3DR_VBUSEN"),
+ STM32_FUNCTION(13, "FMC_A23"),
+ STM32_FUNCTION(14, "LCD_G3"),
+ STM32_FUNCTION(15, "DCMI_D6 PSSI_D6 DCMIPP_D6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(43, "PC11"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC11"),
+ STM32_FUNCTION(2, "LPTIM1_CH1"),
+ STM32_FUNCTION(3, "SPI5_NSS"),
+ STM32_FUNCTION(5, "SAI2_MCLK_A"),
+ STM32_FUNCTION(6, "UART5_RTS"),
+ STM32_FUNCTION(7, "USART3_RTS"),
+ STM32_FUNCTION(8, "TIM3_CH1"),
+ STM32_FUNCTION(9, "TIM5_ETR"),
+ STM32_FUNCTION(11, "ETH2_MII_RXD3 ETH2_RGMII_RXD3"),
+ STM32_FUNCTION(13, "FMC_NBL1"),
+ STM32_FUNCTION(14, "LCD_R2"),
+ STM32_FUNCTION(15, "DCMI_D10 PSSI_D10 DCMIPP_D10"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(44, "PC12"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC12"),
+ STM32_FUNCTION(2, "LPTIM1_CH2"),
+ STM32_FUNCTION(4, "I3C3_SCL"),
+ STM32_FUNCTION(6, "MDF1_CKI2"),
+ STM32_FUNCTION(9, "TIM8_CH3"),
+ STM32_FUNCTION(10, "I2C3_SCL"),
+ STM32_FUNCTION(11, "ETH2_MII_RXD1 ETH2_RGMII_RXD1 ETH2_RMII_RXD1"),
+ STM32_FUNCTION(12, "ETH1_MII_RXD3 ETH1_RGMII_RXD3"),
+ STM32_FUNCTION(14, "LCD_G1"),
+ STM32_FUNCTION(15, "DCMI_D5 PSSI_D5 DCMIPP_D5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(45, "PC13"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOC13"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(48, "PD0"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD0"),
+ STM32_FUNCTION(1, "TRACECLK"),
+ STM32_FUNCTION(2, "HDP0"),
+ STM32_FUNCTION(3, "SPI7_RDY"),
+ STM32_FUNCTION(4, "SAI1_D2"),
+ STM32_FUNCTION(6, "SAI4_FS_A"),
+ STM32_FUNCTION(7, "UART7_RX"),
+ STM32_FUNCTION(8, "TIM15_CH2"),
+ STM32_FUNCTION(10, "SDVSEL1"),
+ STM32_FUNCTION(11, "OCTOSPIM_P1_CLK"),
+ STM32_FUNCTION(14, "DCMI_PIXCLK PSSI_PDCK DCMIPP_PIXCLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(49, "PD1"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD1"),
+ STM32_FUNCTION(2, "HDP1"),
+ STM32_FUNCTION(3, "SPI1_MISO I2S1_SDI"),
+ STM32_FUNCTION(4, "SAI1_CK2"),
+ STM32_FUNCTION(6, "SAI4_SD_A"),
+ STM32_FUNCTION(7, "UART7_RTS"),
+ STM32_FUNCTION(8, "TIM15_CH1"),
+ STM32_FUNCTION(9, "TIM1_BKIN"),
+ STM32_FUNCTION(10, "FDCAN3_RX"),
+ STM32_FUNCTION(11, "OCTOSPIM_P1_NCLK"),
+ STM32_FUNCTION(12, "OCTOSPIM_P1_NCS2"),
+ STM32_FUNCTION(13, "OCTOSPIM_P2_NCS2"),
+ STM32_FUNCTION(14, "DCMI_HSYNC PSSI_DE DCMIPP_HSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(50, "PD2"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD2"),
+ STM32_FUNCTION(2, "HDP2"),
+ STM32_FUNCTION(3, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(4, "SAI1_CK1"),
+ STM32_FUNCTION(6, "SAI4_SCK_A"),
+ STM32_FUNCTION(7, "UART7_CTS"),
+ STM32_FUNCTION(8, "TIM15_BKIN"),
+ STM32_FUNCTION(9, "TIM1_ETR"),
+ STM32_FUNCTION(10, "FDCAN3_TX"),
+ STM32_FUNCTION(11, "OCTOSPIM_P1_DQS"),
+ STM32_FUNCTION(12, "OCTOSPIM_P1_NCS2"),
+ STM32_FUNCTION(14, "DCMI_VSYNC PSSI_RDY DCMIPP_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(51, "PD3"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD3"),
+ STM32_FUNCTION(2, "SAI1_MCLK_A"),
+ STM32_FUNCTION(3, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(4, "SAI1_D1"),
+ STM32_FUNCTION(6, "SAI4_MCLK_A"),
+ STM32_FUNCTION(7, "UART7_TX"),
+ STM32_FUNCTION(8, "TIM15_CH1N"),
+ STM32_FUNCTION(9, "TIM1_BKIN2"),
+ STM32_FUNCTION(10, "SDVSEL2"),
+ STM32_FUNCTION(11, "OCTOSPIM_P1_NCS1"),
+ STM32_FUNCTION(14, "PSSI_D15 DCMIPP_D15"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(52, "PD4"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD4"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(2, "SPI4_MISO"),
+ STM32_FUNCTION(3, "HDP3"),
+ STM32_FUNCTION(4, "SAI1_D3"),
+ STM32_FUNCTION(5, "SAI1_SD_B"),
+ STM32_FUNCTION(9, "TIM1_CH4N"),
+ STM32_FUNCTION(10, "TIM4_CH1"),
+ STM32_FUNCTION(11, "OCTOSPIM_P1_IO0"),
+ STM32_FUNCTION(14, "PSSI_D14 DCMIPP_D14"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(53, "PD5"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD5"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(2, "SPI4_NSS"),
+ STM32_FUNCTION(3, "HDP4"),
+ STM32_FUNCTION(4, "SAI1_D4"),
+ STM32_FUNCTION(5, "SAI1_FS_B"),
+ STM32_FUNCTION(9, "TIM1_CH3N"),
+ STM32_FUNCTION(10, "TIM4_CH2"),
+ STM32_FUNCTION(11, "OCTOSPIM_P1_IO1"),
+ STM32_FUNCTION(14, "DCMI_D13 PSSI_D13 DCMIPP_D13"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(54, "PD6"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD6"),
+ STM32_FUNCTION(1, "TRACED2"),
+ STM32_FUNCTION(2, "SPI4_MOSI"),
+ STM32_FUNCTION(3, "HDP5"),
+ STM32_FUNCTION(5, "SAI1_SCK_B"),
+ STM32_FUNCTION(6, "MDF1_SDI2"),
+ STM32_FUNCTION(9, "TIM1_CH2N"),
+ STM32_FUNCTION(10, "TIM4_CH3"),
+ STM32_FUNCTION(11, "OCTOSPIM_P1_IO2"),
+ STM32_FUNCTION(14, "DCMI_D12 PSSI_D12 DCMIPP_D12"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(55, "PD7"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD7"),
+ STM32_FUNCTION(1, "TRACED3"),
+ STM32_FUNCTION(2, "SPI4_SCK"),
+ STM32_FUNCTION(3, "SPI1_RDY"),
+ STM32_FUNCTION(5, "SAI1_MCLK_B"),
+ STM32_FUNCTION(6, "MDF1_CKI2"),
+ STM32_FUNCTION(9, "TIM1_CH1N"),
+ STM32_FUNCTION(10, "TIM4_CH4"),
+ STM32_FUNCTION(11, "OCTOSPIM_P1_IO3"),
+ STM32_FUNCTION(14, "DCMI_D11 PSSI_D11 DCMIPP_D11"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(56, "PD8"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD8"),
+ STM32_FUNCTION(1, "TRACED4"),
+ STM32_FUNCTION(2, "SPI4_RDY"),
+ STM32_FUNCTION(3, "I2S1_MCK"),
+ STM32_FUNCTION(4, "SAI1_FS_A"),
+ STM32_FUNCTION(5, "UART4_CTS"),
+ STM32_FUNCTION(6, "MDF1_SDI1"),
+ STM32_FUNCTION(9, "TIM1_CH4"),
+ STM32_FUNCTION(10, "TIM4_ETR"),
+ STM32_FUNCTION(11, "OCTOSPIM_P1_IO4"),
+ STM32_FUNCTION(12, "SDMMC1_D7"),
+ STM32_FUNCTION(13, "SDMMC1_D123DIR"),
+ STM32_FUNCTION(14, "DCMI_D10 PSSI_D10 DCMIPP_D10"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(57, "PD9"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD9"),
+ STM32_FUNCTION(1, "TRACED5"),
+ STM32_FUNCTION(2, "HDP6"),
+ STM32_FUNCTION(3, "SPI1_MOSI I2S1_SDO"),
+ STM32_FUNCTION(4, "SAI1_SD_A"),
+ STM32_FUNCTION(5, "UART4_RTS"),
+ STM32_FUNCTION(6, "MDF1_CKI1"),
+ STM32_FUNCTION(9, "TIM1_CH3"),
+ STM32_FUNCTION(11, "OCTOSPIM_P1_IO5"),
+ STM32_FUNCTION(12, "SDMMC1_D6"),
+ STM32_FUNCTION(13, "SDMMC1_D0DIR"),
+ STM32_FUNCTION(14, "DCMI_D9 PSSI_D9 DCMIPP_D9"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(58, "PD10"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD10"),
+ STM32_FUNCTION(1, "TRACED6"),
+ STM32_FUNCTION(2, "HDP7"),
+ STM32_FUNCTION(4, "SAI1_SCK_A"),
+ STM32_FUNCTION(5, "UART4_RX"),
+ STM32_FUNCTION(6, "MDF1_SDI0"),
+ STM32_FUNCTION(7, "I2C4_SDA"),
+ STM32_FUNCTION(9, "TIM1_CH2"),
+ STM32_FUNCTION(10, "TIM14_CH1"),
+ STM32_FUNCTION(11, "OCTOSPIM_P1_IO6"),
+ STM32_FUNCTION(12, "SDMMC1_D5"),
+ STM32_FUNCTION(13, "SDMMC1_CDIR"),
+ STM32_FUNCTION(14, "DCMI_D8 PSSI_D8 DCMIPP_D8"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(59, "PD11"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD11"),
+ STM32_FUNCTION(1, "TRACED7"),
+ STM32_FUNCTION(3, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(4, "SAI1_MCLK_A"),
+ STM32_FUNCTION(5, "UART4_TX"),
+ STM32_FUNCTION(6, "MDF1_CKI0"),
+ STM32_FUNCTION(7, "I2C4_SCL"),
+ STM32_FUNCTION(9, "TIM1_CH1"),
+ STM32_FUNCTION(10, "SDVSEL1"),
+ STM32_FUNCTION(11, "OCTOSPIM_P1_IO7"),
+ STM32_FUNCTION(12, "SDMMC1_D4"),
+ STM32_FUNCTION(13, "SDMMC1_CKIN"),
+ STM32_FUNCTION(14, "DCMI_D7 PSSI_D7 DCMIPP_D7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(60, "PD12"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD12"),
+ STM32_FUNCTION(2, "SPI7_MISO"),
+ STM32_FUNCTION(3, "SPI2_MISO I2S2_SDI"),
+ STM32_FUNCTION(4, "SPDIFRX1_IN2"),
+ STM32_FUNCTION(6, "UART8_RTS"),
+ STM32_FUNCTION(10, "TIM4_ETR"),
+ STM32_FUNCTION(11, "SDMMC3_CMD"),
+ STM32_FUNCTION(12, "FMC_AD6 FMC_D6"),
+ STM32_FUNCTION(13, "FMC_AD1 FMC_D1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(61, "PD13"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD13"),
+ STM32_FUNCTION(3, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(6, "MDF1_SDI7"),
+ STM32_FUNCTION(7, "UART9_TX"),
+ STM32_FUNCTION(10, "TIM4_CH4"),
+ STM32_FUNCTION(11, "SDMMC3_D1"),
+ STM32_FUNCTION(12, "FMC_AD11 FMC_D11"),
+ STM32_FUNCTION(13, "FMC_NWE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(62, "PD14"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD14"),
+ STM32_FUNCTION(3, "I2S1_MCK"),
+ STM32_FUNCTION(8, "FDCAN1_RX"),
+ STM32_FUNCTION(9, "TIM11_CH1"),
+ STM32_FUNCTION(11, "I2C7_SDA"),
+ STM32_FUNCTION(12, "FMC_AD4 FMC_D4"),
+ STM32_FUNCTION(13, "SDMMC3_D3"),
+ STM32_FUNCTION(14, "DCMI_D1 PSSI_D1 DCMIPP_D1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(63, "PD15"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOD15"),
+ STM32_FUNCTION(2, "SPI1_RDY"),
+ STM32_FUNCTION(6, "DSI_TE"),
+ STM32_FUNCTION(7, "I2C5_SDA"),
+ STM32_FUNCTION(8, "FDCAN1_TX"),
+ STM32_FUNCTION(9, "TIM1_BKIN2"),
+ STM32_FUNCTION(10, "TIM5_ETR"),
+ STM32_FUNCTION(11, "I2C7_SCL"),
+ STM32_FUNCTION(12, "FMC_AD3 FMC_D3"),
+ STM32_FUNCTION(13, "SDMMC3_CKIN"),
+ STM32_FUNCTION(14, "DCMI_D0 PSSI_D0 DCMIPP_D0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(64, "PE0"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE0"),
+ STM32_FUNCTION(1, "TRACED2"),
+ STM32_FUNCTION(2, "LPTIM2_CH1"),
+ STM32_FUNCTION(3, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(4, "SPI3_RDY"),
+ STM32_FUNCTION(7, "USART3_CK"),
+ STM32_FUNCTION(11, "SDMMC1_D2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(65, "PE1"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE1"),
+ STM32_FUNCTION(1, "TRACED3"),
+ STM32_FUNCTION(2, "LPTIM2_CH2"),
+ STM32_FUNCTION(3, "I2S1_MCK"),
+ STM32_FUNCTION(4, "I2S3_MCK"),
+ STM32_FUNCTION(7, "USART3_RX"),
+ STM32_FUNCTION(11, "SDMMC1_D3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(66, "PE2"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE2"),
+ STM32_FUNCTION(2, "LPTIM2_ETR"),
+ STM32_FUNCTION(3, "SPI1_MISO I2S1_SDI"),
+ STM32_FUNCTION(4, "SPI3_MOSI I2S3_SDO"),
+ STM32_FUNCTION(5, "SAI1_SCK_B"),
+ STM32_FUNCTION(9, "TIM10_CH1"),
+ STM32_FUNCTION(11, "SDMMC1_CMD"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(67, "PE3"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE3"),
+ STM32_FUNCTION(1, "TRACECLK"),
+ STM32_FUNCTION(3, "SPI1_RDY"),
+ STM32_FUNCTION(4, "SPI3_SCK I2S3_CK"),
+ STM32_FUNCTION(5, "SAI1_MCLK_B"),
+ STM32_FUNCTION(7, "USART3_TX"),
+ STM32_FUNCTION(9, "TIM11_CH1"),
+ STM32_FUNCTION(11, "SDMMC1_CK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(68, "PE4"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE4"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(2, "LPTIM2_IN1"),
+ STM32_FUNCTION(3, "SPI1_MOSI I2S1_SDO"),
+ STM32_FUNCTION(4, "SPI3_MISO I2S3_SDI"),
+ STM32_FUNCTION(5, "SAI1_SD_B"),
+ STM32_FUNCTION(7, "USART3_CTS"),
+ STM32_FUNCTION(8, "FDCAN1_TX"),
+ STM32_FUNCTION(11, "SDMMC1_D0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(69, "PE5"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE5"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(2, "LPTIM2_IN2"),
+ STM32_FUNCTION(3, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(4, "SPI3_NSS I2S3_WS"),
+ STM32_FUNCTION(5, "SAI1_FS_B"),
+ STM32_FUNCTION(7, "USART3_RTS"),
+ STM32_FUNCTION(8, "FDCAN1_RX"),
+ STM32_FUNCTION(11, "SDMMC1_D1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(70, "PE6"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE6"),
+ STM32_FUNCTION(2, "SPI4_RDY"),
+ STM32_FUNCTION(5, "SPDIFRX1_IN2"),
+ STM32_FUNCTION(7, "USART1_TX"),
+ STM32_FUNCTION(9, "TIM1_ETR"),
+ STM32_FUNCTION(12, "FMC_AD1 FMC_D1"),
+ STM32_FUNCTION(13, "SDMMC2_D6"),
+ STM32_FUNCTION(14, "SDMMC2_D0DIR"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(71, "PE7"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE7"),
+ STM32_FUNCTION(4, "SAI4_D4"),
+ STM32_FUNCTION(5, "SPDIFRX1_IN3"),
+ STM32_FUNCTION(7, "USART1_RX"),
+ STM32_FUNCTION(9, "TIM1_CH4N"),
+ STM32_FUNCTION(11, "TIM14_CH1"),
+ STM32_FUNCTION(12, "FMC_AD2 FMC_D2"),
+ STM32_FUNCTION(13, "SDMMC2_D7"),
+ STM32_FUNCTION(14, "SDMMC2_D123DIR"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(72, "PE8"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE8"),
+ STM32_FUNCTION(2, "SPI4_MOSI"),
+ STM32_FUNCTION(4, "SAI4_CK1"),
+ STM32_FUNCTION(5, "SAI4_MCLK_A"),
+ STM32_FUNCTION(6, "MDF1_CKI0"),
+ STM32_FUNCTION(9, "TIM1_CH1"),
+ STM32_FUNCTION(12, "FMC_A17 FMC_ALE"),
+ STM32_FUNCTION(13, "SDMMC2_D2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(73, "PE9"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE9"),
+ STM32_FUNCTION(2, "SPI4_MISO"),
+ STM32_FUNCTION(4, "SAI4_D2"),
+ STM32_FUNCTION(5, "SAI4_FS_A"),
+ STM32_FUNCTION(7, "USART1_CK"),
+ STM32_FUNCTION(9, "TIM1_CH4"),
+ STM32_FUNCTION(12, "FMC_AD0 FMC_D0"),
+ STM32_FUNCTION(13, "SDMMC2_D5"),
+ STM32_FUNCTION(14, "SDMMC2_CDIR"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(74, "PE10"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE10"),
+ STM32_FUNCTION(2, "SPI4_SCK"),
+ STM32_FUNCTION(4, "SAI4_D1"),
+ STM32_FUNCTION(5, "SAI4_SD_A"),
+ STM32_FUNCTION(7, "USART1_CTS"),
+ STM32_FUNCTION(9, "TIM1_CH3"),
+ STM32_FUNCTION(11, "FMC_NE3"),
+ STM32_FUNCTION(12, "FMC_NCE2"),
+ STM32_FUNCTION(13, "SDMMC2_D4"),
+ STM32_FUNCTION(14, "SDMMC2_CKIN"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(75, "PE11"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE11"),
+ STM32_FUNCTION(3, "SPI7_SCK"),
+ STM32_FUNCTION(4, "SAI4_D3"),
+ STM32_FUNCTION(5, "SAI1_FS_A"),
+ STM32_FUNCTION(8, "TIM15_CH2"),
+ STM32_FUNCTION(9, "TIM1_CH3N"),
+ STM32_FUNCTION(12, "FMC_A16 FMC_CLE"),
+ STM32_FUNCTION(13, "SDMMC2_D1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(76, "PE12"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE12"),
+ STM32_FUNCTION(2, "SPI4_NSS"),
+ STM32_FUNCTION(4, "SAI4_CK2"),
+ STM32_FUNCTION(5, "SAI4_SCK_A"),
+ STM32_FUNCTION(6, "MDF1_SDI0"),
+ STM32_FUNCTION(7, "USART1_RTS"),
+ STM32_FUNCTION(9, "TIM1_CH2"),
+ STM32_FUNCTION(11, "FMC_NE2"),
+ STM32_FUNCTION(12, "FMC_NCE1"),
+ STM32_FUNCTION(13, "SDMMC2_D3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(77, "PE13"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE13"),
+ STM32_FUNCTION(3, "SPI7_MISO"),
+ STM32_FUNCTION(5, "SAI1_SD_A"),
+ STM32_FUNCTION(8, "TIM15_CH1"),
+ STM32_FUNCTION(9, "TIM1_CH2N"),
+ STM32_FUNCTION(12, "FMC_RNB"),
+ STM32_FUNCTION(13, "SDMMC2_D0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(78, "PE14"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE14"),
+ STM32_FUNCTION(3, "SPI7_NSS"),
+ STM32_FUNCTION(5, "SAI1_MCLK_A"),
+ STM32_FUNCTION(6, "MDF1_CKI6"),
+ STM32_FUNCTION(8, "TIM15_BKIN"),
+ STM32_FUNCTION(9, "TIM1_BKIN"),
+ STM32_FUNCTION(12, "FMC_NWE"),
+ STM32_FUNCTION(13, "SDMMC2_CK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(79, "PE15"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOE15"),
+ STM32_FUNCTION(3, "SPI7_MOSI"),
+ STM32_FUNCTION(5, "SAI1_SCK_A"),
+ STM32_FUNCTION(6, "MDF1_SDI6"),
+ STM32_FUNCTION(8, "TIM15_CH1N"),
+ STM32_FUNCTION(9, "TIM1_CH1N"),
+ STM32_FUNCTION(12, "FMC_NOE"),
+ STM32_FUNCTION(13, "SDMMC2_CMD"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(80, "PF0"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF0"),
+ STM32_FUNCTION(3, "SPI3_SCK I2S3_CK"),
+ STM32_FUNCTION(8, "FDCAN2_RX"),
+ STM32_FUNCTION(9, "TIM12_CH2"),
+ STM32_FUNCTION(10, "I2C2_SDA"),
+ STM32_FUNCTION(11, "ETH1_MDC"),
+ STM32_FUNCTION(12, "ETH2_MII_CRS"),
+ STM32_FUNCTION(14, "I3C2_SDA"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(81, "PF1"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF1"),
+ STM32_FUNCTION(2, "SPI8_MISO"),
+ STM32_FUNCTION(3, "LPTIM2_IN2"),
+ STM32_FUNCTION(5, "SAI4_SCK_B"),
+ STM32_FUNCTION(6, "MDF1_CKI4"),
+ STM32_FUNCTION(7, "USART2_CK"),
+ STM32_FUNCTION(11, "ETH1_MII_RXD0 ETH1_RGMII_RXD0 ETH1_RMII_RXD0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(82, "PF2"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF2"),
+ STM32_FUNCTION(3, "SPI3_RDY"),
+ STM32_FUNCTION(7, "I2C4_SMBA"),
+ STM32_FUNCTION(9, "TIM12_CH1"),
+ STM32_FUNCTION(10, "I2C2_SCL"),
+ STM32_FUNCTION(11, "ETH1_MDIO"),
+ STM32_FUNCTION(12, "ETH2_MII_COL"),
+ STM32_FUNCTION(13, "FMC_NE4"),
+ STM32_FUNCTION(14, "I3C2_SCL"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(83, "PF3"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF3"),
+ STM32_FUNCTION(4, "UART8_RX"),
+ STM32_FUNCTION(5, "SAI2_SCK_B"),
+ STM32_FUNCTION(6, "MDF1_CCK0"),
+ STM32_FUNCTION(8, "TIM3_CH4"),
+ STM32_FUNCTION(9, "TIM8_BKIN2"),
+ STM32_FUNCTION(10, "ETH1_CLK"),
+ STM32_FUNCTION(11, "ETH2_PPS_OUT"),
+ STM32_FUNCTION(13, "FMC_A20"),
+ STM32_FUNCTION(14, "LCD_R6"),
+ STM32_FUNCTION(15, "DCMI_HSYNC PSSI_DE DCMIPP_HSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(84, "PF4"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF4"),
+ STM32_FUNCTION(2, "RTC_OUT2"),
+ STM32_FUNCTION(3, "SPI6_NSS"),
+ STM32_FUNCTION(5, "SAI3_SCK_A"),
+ STM32_FUNCTION(7, "USART6_RX"),
+ STM32_FUNCTION(8, "TIM4_CH4"),
+ STM32_FUNCTION(9, "ETH1_MDC"),
+ STM32_FUNCTION(10, "ETH2_CLK"),
+ STM32_FUNCTION(11, "ETH2_PPS_OUT"),
+ STM32_FUNCTION(12, "ETH1_PPS_OUT"),
+ STM32_FUNCTION(14, "LCD_B7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(85, "PF5"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF5"),
+ STM32_FUNCTION(3, "SPI6_SCK"),
+ STM32_FUNCTION(5, "SAI3_MCLK_A"),
+ STM32_FUNCTION(7, "USART6_TX"),
+ STM32_FUNCTION(8, "TIM4_CH3"),
+ STM32_FUNCTION(9, "ETH1_MDIO"),
+ STM32_FUNCTION(10, "ETH1_CLK"),
+ STM32_FUNCTION(11, "ETH2_PHY_INTN"),
+ STM32_FUNCTION(12, "ETH1_PHY_INTN"),
+ STM32_FUNCTION(14, "LCD_B6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(86, "PF6"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF6"),
+ STM32_FUNCTION(2, "RTC_OUT2"),
+ STM32_FUNCTION(4, "SAI3_MCLK_B"),
+ STM32_FUNCTION(7, "USART6_CK"),
+ STM32_FUNCTION(8, "TIM12_CH1"),
+ STM32_FUNCTION(10, "I2C3_SMBA"),
+ STM32_FUNCTION(11, "ETH2_MII_RX_CLK ETH2_RGMII_RX_CLK ETH2_RMII_REF_CLK"),
+ STM32_FUNCTION(14, "LCD_B0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(87, "PF7"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF7"),
+ STM32_FUNCTION(3, "SPDIFRX1_IN1"),
+ STM32_FUNCTION(4, "SPI6_SCK"),
+ STM32_FUNCTION(5, "SAI3_SD_A"),
+ STM32_FUNCTION(8, "TIM2_ETR"),
+ STM32_FUNCTION(11, "ETH2_RGMII_GTX_CLK"),
+ STM32_FUNCTION(12, "ETH2_MII_TX_CLK"),
+ STM32_FUNCTION(14, "LCD_R1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(88, "PF8"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF8"),
+ STM32_FUNCTION(2, "RTC_REFIN"),
+ STM32_FUNCTION(4, "SAI3_SCK_B"),
+ STM32_FUNCTION(7, "USART3_RX"),
+ STM32_FUNCTION(8, "TIM12_CH2"),
+ STM32_FUNCTION(10, "ETH1_CLK"),
+ STM32_FUNCTION(11, "ETH2_RGMII_CLK125"),
+ STM32_FUNCTION(12, "ETH2_MII_RX_ER"),
+ STM32_FUNCTION(13, "ETH2_MII_RX_DV ETH2_RGMII_RX_CTL ETH2_RMII_CRS_DV"),
+ STM32_FUNCTION(14, "LCD_G0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(89, "PF9"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF9"),
+ STM32_FUNCTION(4, "SAI3_SD_B"),
+ STM32_FUNCTION(5, "SAI2_SD_A"),
+ STM32_FUNCTION(6, "MDF1_SDI5"),
+ STM32_FUNCTION(7, "UART8_RTS"),
+ STM32_FUNCTION(8, "TIM2_CH2"),
+ STM32_FUNCTION(11, "ETH2_MII_RXD2 ETH2_RGMII_RXD2"),
+ STM32_FUNCTION(12, "ETH2_MDIO"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(90, "PF10"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF10"),
+ STM32_FUNCTION(2, "MCO2"),
+ STM32_FUNCTION(3, "SPI3_RDY"),
+ STM32_FUNCTION(5, "SAI2_MCLK_A"),
+ STM32_FUNCTION(6, "MDF1_CKI6"),
+ STM32_FUNCTION(7, "UART8_TX"),
+ STM32_FUNCTION(8, "TIM2_CH3"),
+ STM32_FUNCTION(11, "ETH2_MII_TXD2 ETH2_RGMII_TXD2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(91, "PF11"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF11"),
+ STM32_FUNCTION(2, "MCO1"),
+ STM32_FUNCTION(3, "SPDIFRX1_IN0"),
+ STM32_FUNCTION(4, "SPI6_RDY"),
+ STM32_FUNCTION(5, "SAI2_SCK_A"),
+ STM32_FUNCTION(6, "MDF1_SDI6"),
+ STM32_FUNCTION(7, "UART8_RX"),
+ STM32_FUNCTION(8, "TIM2_CH4"),
+ STM32_FUNCTION(11, "ETH2_MII_TXD3 ETH2_RGMII_TXD3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(92, "PF12"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF12"),
+ STM32_FUNCTION(1, "TRACECLK"),
+ STM32_FUNCTION(3, "SPI5_MISO"),
+ STM32_FUNCTION(4, "SPI1_MISO I2S1_SDI"),
+ STM32_FUNCTION(7, "UART9_RTS"),
+ STM32_FUNCTION(9, "TIM5_CH1"),
+ STM32_FUNCTION(14, "LCD_CLK"),
+ STM32_FUNCTION(15, "DCMI_D0 PSSI_D0 DCMIPP_D0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(93, "PF13"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF13"),
+ STM32_FUNCTION(1, "TRACED0"),
+ STM32_FUNCTION(2, "HDP0"),
+ STM32_FUNCTION(3, "AUDIOCLK"),
+ STM32_FUNCTION(4, "USART6_TX"),
+ STM32_FUNCTION(5, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(6, "MDF1_CKI7"),
+ STM32_FUNCTION(7, "USART3_CTS"),
+ STM32_FUNCTION(8, "FDCAN3_TX"),
+ STM32_FUNCTION(9, "TIM3_CH3"),
+ STM32_FUNCTION(14, "LCD_R2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(94, "PF14"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF14"),
+ STM32_FUNCTION(1, "TRACED1"),
+ STM32_FUNCTION(2, "HDP1"),
+ STM32_FUNCTION(4, "USART6_RX"),
+ STM32_FUNCTION(6, "MDF1_SDI7"),
+ STM32_FUNCTION(7, "USART3_RTS"),
+ STM32_FUNCTION(8, "FDCAN3_RX"),
+ STM32_FUNCTION(9, "TIM3_CH4"),
+ STM32_FUNCTION(14, "LCD_R3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(95, "PF15"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOF15"),
+ STM32_FUNCTION(1, "TRACED2"),
+ STM32_FUNCTION(2, "HDP2"),
+ STM32_FUNCTION(3, "SPI2_RDY"),
+ STM32_FUNCTION(4, "USART6_CTS"),
+ STM32_FUNCTION(5, "SPI2_SCK I2S2_CK"),
+ STM32_FUNCTION(7, "USART3_CK"),
+ STM32_FUNCTION(8, "TIM2_CH2"),
+ STM32_FUNCTION(9, "TIM3_ETR"),
+ STM32_FUNCTION(10, "I2C6_SMBA"),
+ STM32_FUNCTION(14, "LCD_R4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(96, "PG0"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG0"),
+ STM32_FUNCTION(2, "LPTIM1_IN1"),
+ STM32_FUNCTION(4, "I3C3_SDA"),
+ STM32_FUNCTION(6, "MDF1_SDI2"),
+ STM32_FUNCTION(9, "TIM8_CH3N"),
+ STM32_FUNCTION(10, "I2C3_SDA"),
+ STM32_FUNCTION(11, "ETH2_MII_RXD0 ETH2_RGMII_RXD0 ETH2_RMII_RXD0"),
+ STM32_FUNCTION(12, "ETH1_MII_RXD2 ETH1_RGMII_RXD2"),
+ STM32_FUNCTION(14, "LCD_G5"),
+ STM32_FUNCTION(15, "DCMI_D4 PSSI_D4 DCMIPP_D4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(97, "PG1"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG1"),
+ STM32_FUNCTION(2, "LPTIM1_IN1"),
+ STM32_FUNCTION(3, "I2S3_MCK"),
+ STM32_FUNCTION(4, "I3C3_SCL"),
+ STM32_FUNCTION(5, "SAI2_SD_A"),
+ STM32_FUNCTION(6, "UART5_CTS"),
+ STM32_FUNCTION(7, "USART3_CTS"),
+ STM32_FUNCTION(9, "TIM5_CH4"),
+ STM32_FUNCTION(10, "I2C3_SCL"),
+ STM32_FUNCTION(11, "ETH2_MII_RX_ER"),
+ STM32_FUNCTION(12, "ETH2_MII_RXD3 ETH2_RGMII_RXD3"),
+ STM32_FUNCTION(13, "FMC_NBL0"),
+ STM32_FUNCTION(14, "LCD_VSYNC"),
+ STM32_FUNCTION(15, "DCMI_D11 PSSI_D11 DCMIPP_D11"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(98, "PG2"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG2"),
+ STM32_FUNCTION(2, "RTC_REFIN"),
+ STM32_FUNCTION(3, "I2S3_MCK"),
+ STM32_FUNCTION(4, "I3C3_SDA"),
+ STM32_FUNCTION(5, "SAI2_FS_A"),
+ STM32_FUNCTION(7, "USART3_CK"),
+ STM32_FUNCTION(9, "TIM5_CH3"),
+ STM32_FUNCTION(10, "I2C3_SDA"),
+ STM32_FUNCTION(11, "ETH2_MII_TX_CLK"),
+ STM32_FUNCTION(12, "ETH2_RGMII_CLK125"),
+ STM32_FUNCTION(13, "FMC_CLK"),
+ STM32_FUNCTION(14, "LCD_HSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(99, "PG3"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG3"),
+ STM32_FUNCTION(2, "LPTIM1_ETR"),
+ STM32_FUNCTION(3, "SPI5_MOSI"),
+ STM32_FUNCTION(4, "UART8_TX"),
+ STM32_FUNCTION(5, "SAI2_FS_B"),
+ STM32_FUNCTION(8, "TIM3_CH3"),
+ STM32_FUNCTION(9, "TIM8_ETR"),
+ STM32_FUNCTION(10, "ETH2_CLK"),
+ STM32_FUNCTION(11, "ETH2_PHY_INTN"),
+ STM32_FUNCTION(13, "FMC_A19"),
+ STM32_FUNCTION(14, "LCD_R5"),
+ STM32_FUNCTION(15, "DCMI_PIXCLK PSSI_PDCK DCMIPP_PIXCLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(100, "PG4"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG4"),
+ STM32_FUNCTION(3, "SPI5_MISO"),
+ STM32_FUNCTION(4, "SAI3_FS_B"),
+ STM32_FUNCTION(8, "LPTIM4_IN1"),
+ STM32_FUNCTION(9, "TIM8_BKIN"),
+ STM32_FUNCTION(11, "ETH2_PPS_OUT"),
+ STM32_FUNCTION(12, "ETH2_MDC"),
+ STM32_FUNCTION(13, "FMC_A21"),
+ STM32_FUNCTION(14, "LCD_R7"),
+ STM32_FUNCTION(15, "DCMI_VSYNC PSSI_RDY DCMIPP_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(101, "PG5"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG5"),
+ STM32_FUNCTION(1, "TRACED3"),
+ STM32_FUNCTION(2, "HDP3"),
+ STM32_FUNCTION(4, "USART6_RTS"),
+ STM32_FUNCTION(8, "TIM2_CH3"),
+ STM32_FUNCTION(10, "I2C6_SDA"),
+ STM32_FUNCTION(14, "LCD_R5"),
+ STM32_FUNCTION(15, "DCMI_PIXCLK PSSI_PDCK DCMIPP_PIXCLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(102, "PG6"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG6"),
+ STM32_FUNCTION(1, "TRACED4"),
+ STM32_FUNCTION(2, "HDP4"),
+ STM32_FUNCTION(3, "SPI5_SCK"),
+ STM32_FUNCTION(4, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(8, "TIM2_CH4"),
+ STM32_FUNCTION(10, "I2C6_SCL"),
+ STM32_FUNCTION(14, "LCD_R6"),
+ STM32_FUNCTION(15, "DCMI_HSYNC PSSI_DE DCMIPP_HSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(103, "PG7"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG7"),
+ STM32_FUNCTION(1, "TRACED5"),
+ STM32_FUNCTION(2, "HDP5"),
+ STM32_FUNCTION(3, "SPI5_NSS"),
+ STM32_FUNCTION(4, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(7, "UART9_CTS"),
+ STM32_FUNCTION(9, "TIM5_ETR"),
+ STM32_FUNCTION(14, "LCD_R7"),
+ STM32_FUNCTION(15, "DCMI_VSYNC PSSI_RDY DCMIPP_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(104, "PG8"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG8"),
+ STM32_FUNCTION(1, "TRACED6"),
+ STM32_FUNCTION(2, "HDP6"),
+ STM32_FUNCTION(3, "SPI5_RDY"),
+ STM32_FUNCTION(4, "SPI1_RDY"),
+ STM32_FUNCTION(5, "USART6_CK"),
+ STM32_FUNCTION(6, "UART5_RTS"),
+ STM32_FUNCTION(7, "UART9_TX"),
+ STM32_FUNCTION(9, "TIM5_CH3"),
+ STM32_FUNCTION(14, "LCD_G2"),
+ STM32_FUNCTION(15, "DCMI_D2 PSSI_D2 DCMIPP_D2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(105, "PG9"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG9"),
+ STM32_FUNCTION(1, "TRACED7"),
+ STM32_FUNCTION(6, "UART5_TX"),
+ STM32_FUNCTION(9, "TIM5_CH4"),
+ STM32_FUNCTION(14, "LCD_G3"),
+ STM32_FUNCTION(15, "DCMI_D3 PSSI_D3 DCMIPP_D3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(106, "PG10"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG10"),
+ STM32_FUNCTION(1, "TRACED8"),
+ STM32_FUNCTION(2, "HDP0"),
+ STM32_FUNCTION(6, "UART5_RX"),
+ STM32_FUNCTION(9, "TIM8_CH4N"),
+ STM32_FUNCTION(14, "LCD_G4"),
+ STM32_FUNCTION(15, "DCMI_D4 PSSI_D4 DCMIPP_D4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(107, "PG11"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG11"),
+ STM32_FUNCTION(1, "TRACED9"),
+ STM32_FUNCTION(2, "HDP1"),
+ STM32_FUNCTION(3, "SPI7_MOSI"),
+ STM32_FUNCTION(8, "FDCAN1_TX"),
+ STM32_FUNCTION(9, "TIM8_CH4"),
+ STM32_FUNCTION(14, "LCD_G5"),
+ STM32_FUNCTION(15, "DCMI_D5 PSSI_D5 DCMIPP_D5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(108, "PG12"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG12"),
+ STM32_FUNCTION(1, "TRACED10"),
+ STM32_FUNCTION(2, "HDP2"),
+ STM32_FUNCTION(3, "SPI7_MISO"),
+ STM32_FUNCTION(8, "FDCAN1_RX"),
+ STM32_FUNCTION(9, "TIM8_CH1N"),
+ STM32_FUNCTION(14, "LCD_G6"),
+ STM32_FUNCTION(15, "DCMI_D6 PSSI_D6 DCMIPP_D6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(109, "PG13"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG13"),
+ STM32_FUNCTION(1, "TRACED11"),
+ STM32_FUNCTION(2, "HDP3"),
+ STM32_FUNCTION(3, "SPI7_SCK"),
+ STM32_FUNCTION(6, "MDF1_CKI6"),
+ STM32_FUNCTION(9, "TIM8_CH2N"),
+ STM32_FUNCTION(10, "I2C1_SCL"),
+ STM32_FUNCTION(11, "I3C1_SCL"),
+ STM32_FUNCTION(14, "LCD_G7"),
+ STM32_FUNCTION(15, "DCMI_D7 PSSI_D7 DCMIPP_D7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(110, "PG14"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG14"),
+ STM32_FUNCTION(1, "TRACED12"),
+ STM32_FUNCTION(2, "HDP4"),
+ STM32_FUNCTION(3, "SPI7_RDY"),
+ STM32_FUNCTION(6, "MDF1_CKI5"),
+ STM32_FUNCTION(7, "USART1_TX"),
+ STM32_FUNCTION(9, "TIM8_BKIN2"),
+ STM32_FUNCTION(14, "LCD_B1"),
+ STM32_FUNCTION(15, "DCMI_D9 PSSI_D9 DCMIPP_D9"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(111, "PG15"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOG15"),
+ STM32_FUNCTION(1, "TRACED13"),
+ STM32_FUNCTION(2, "HDP5"),
+ STM32_FUNCTION(4, "LPTIM1_CH2"),
+ STM32_FUNCTION(6, "MDF1_SDI5"),
+ STM32_FUNCTION(7, "USART1_RX"),
+ STM32_FUNCTION(9, "TIM8_ETR"),
+ STM32_FUNCTION(14, "LCD_B2"),
+ STM32_FUNCTION(15, "DCMI_D10 PSSI_D10 DCMIPP_D10"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(114, "PH2"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOH2"),
+ STM32_FUNCTION(2, "LPTIM2_CH1"),
+ STM32_FUNCTION(3, "SPI7_RDY"),
+ STM32_FUNCTION(4, "SPDIFRX1_IN3"),
+ STM32_FUNCTION(5, "SAI1_SCK_B"),
+ STM32_FUNCTION(6, "I3C3_SDA"),
+ STM32_FUNCTION(8, "TIM16_CH1"),
+ STM32_FUNCTION(9, "I2C5_SDA"),
+ STM32_FUNCTION(10, "I2C3_SDA"),
+ STM32_FUNCTION(15, "ETH3_RGMII_GTX_CLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(115, "PH3"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOH3"),
+ STM32_FUNCTION(3, "SPI1_NSS I2S1_WS"),
+ STM32_FUNCTION(7, "UART7_RX"),
+ STM32_FUNCTION(8, "TIM17_CH1N"),
+ STM32_FUNCTION(10, "TIM5_CH3"),
+ STM32_FUNCTION(11, "I2C7_SCL"),
+ STM32_FUNCTION(15, "ETH3_RGMII_TXD3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(116, "PH4"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOH4"),
+ STM32_FUNCTION(7, "UART7_TX"),
+ STM32_FUNCTION(8, "TIM17_BKIN"),
+ STM32_FUNCTION(10, "TIM5_CH2"),
+ STM32_FUNCTION(11, "LCD_R0"),
+ STM32_FUNCTION(12, "USB3DR_OVRCUR"),
+ STM32_FUNCTION(13, "USBH_HS_OVRCUR"),
+ STM32_FUNCTION(14, "ETH1_PTP_AUX_TS"),
+ STM32_FUNCTION(15, "ETH3_PPS_OUT"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(117, "PH5"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOH5"),
+ STM32_FUNCTION(5, "SAI2_FS_A"),
+ STM32_FUNCTION(7, "UART8_CTS"),
+ STM32_FUNCTION(8, "TIM2_CH1"),
+ STM32_FUNCTION(9, "UART7_RX"),
+ STM32_FUNCTION(11, "LCD_G1"),
+ STM32_FUNCTION(12, "USB3DR_VBUSEN"),
+ STM32_FUNCTION(13, "USBH_HS_VBUSEN"),
+ STM32_FUNCTION(14, "ETH2_PTP_AUX_TS"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(118, "PH6"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOH6"),
+ STM32_FUNCTION(2, "LPTIM2_IN2"),
+ STM32_FUNCTION(5, "SAI1_MCLK_B"),
+ STM32_FUNCTION(6, "I3C3_SCL"),
+ STM32_FUNCTION(8, "TIM16_CH1N"),
+ STM32_FUNCTION(9, "I2C5_SCL"),
+ STM32_FUNCTION(10, "I2C3_SCL"),
+ STM32_FUNCTION(11, "I2C1_SMBA"),
+ STM32_FUNCTION(15, "ETH3_RGMII_TXD2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(119, "PH7"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOH7"),
+ STM32_FUNCTION(3, "SPI1_MOSI I2S1_SDO"),
+ STM32_FUNCTION(5, "UART4_TX"),
+ STM32_FUNCTION(7, "UART7_RTS"),
+ STM32_FUNCTION(8, "TIM17_CH1"),
+ STM32_FUNCTION(10, "TIM5_CH4"),
+ STM32_FUNCTION(11, "I2C7_SDA"),
+ STM32_FUNCTION(15, "ETH3_RGMII_RXD2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(120, "PH8"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOH8"),
+ STM32_FUNCTION(3, "SPI1_MISO I2S1_SDI"),
+ STM32_FUNCTION(4, "SPDIFRX1_IN3"),
+ STM32_FUNCTION(5, "UART4_RX"),
+ STM32_FUNCTION(7, "UART7_CTS"),
+ STM32_FUNCTION(10, "TIM5_CH1"),
+ STM32_FUNCTION(11, "I2C3_SMBA"),
+ STM32_FUNCTION(12, "I2C5_SMBA"),
+ STM32_FUNCTION(15, "ETH3_RGMII_RXD3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(121, "PH9"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOH9"),
+ STM32_FUNCTION(4, "SPI6_NSS"),
+ STM32_FUNCTION(5, "SAI3_MCLK_A"),
+ STM32_FUNCTION(7, "USART6_RX"),
+ STM32_FUNCTION(8, "TIM15_CH1N"),
+ STM32_FUNCTION(11, "ETH1_RGMII_CLK125"),
+ STM32_FUNCTION(12, "ETH1_MII_RX_ER"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(122, "PH10"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOH10"),
+ STM32_FUNCTION(3, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(4, "SPI6_MOSI"),
+ STM32_FUNCTION(5, "SAI3_SCK_A"),
+ STM32_FUNCTION(8, "TIM15_CH1"),
+ STM32_FUNCTION(10, "ETH2_MDC"),
+ STM32_FUNCTION(11, "ETH1_MII_TXD2 ETH1_RGMII_TXD2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(123, "PH11"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOH11"),
+ STM32_FUNCTION(4, "SPI6_MISO"),
+ STM32_FUNCTION(5, "SAI3_FS_A"),
+ STM32_FUNCTION(8, "TIM15_CH2"),
+ STM32_FUNCTION(10, "ETH2_MDIO"),
+ STM32_FUNCTION(11, "ETH1_MII_TXD3 ETH1_RGMII_TXD3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(124, "PH12"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOH12"),
+ STM32_FUNCTION(3, "SPI3_NSS I2S3_WS"),
+ STM32_FUNCTION(4, "SPI6_MISO"),
+ STM32_FUNCTION(9, "TIM10_CH1"),
+ STM32_FUNCTION(11, "ETH1_MII_RXD2 ETH1_RGMII_RXD2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(125, "PH13"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOH13"),
+ STM32_FUNCTION(3, "SPI3_SCK I2S3_CK"),
+ STM32_FUNCTION(4, "SPI6_MOSI"),
+ STM32_FUNCTION(8, "TIM15_BKIN"),
+ STM32_FUNCTION(9, "TIM11_CH1"),
+ STM32_FUNCTION(11, "ETH1_MII_RXD3 ETH1_RGMII_RXD3"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(128, "PI0"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOI0"),
+ STM32_FUNCTION(1, "TRACED14"),
+ STM32_FUNCTION(2, "HDP6"),
+ STM32_FUNCTION(4, "LPTIM1_IN1"),
+ STM32_FUNCTION(5, "SAI4_MCLK_B"),
+ STM32_FUNCTION(7, "USART1_CK"),
+ STM32_FUNCTION(9, "TIM8_BKIN"),
+ STM32_FUNCTION(14, "LCD_B3"),
+ STM32_FUNCTION(15, "DCMI_D11 PSSI_D11 DCMIPP_D11"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(129, "PI1"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOI1"),
+ STM32_FUNCTION(1, "TRACED15"),
+ STM32_FUNCTION(2, "HDP7"),
+ STM32_FUNCTION(3, "SPI7_NSS"),
+ STM32_FUNCTION(6, "MDF1_SDI6"),
+ STM32_FUNCTION(9, "TIM8_CH3N"),
+ STM32_FUNCTION(10, "I2C1_SDA"),
+ STM32_FUNCTION(11, "I3C1_SDA"),
+ STM32_FUNCTION(14, "LCD_B4"),
+ STM32_FUNCTION(15, "DCMI_D8 PSSI_D8 DCMIPP_D8"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(130, "PI2"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOI2"),
+ STM32_FUNCTION(4, "LPTIM1_ETR"),
+ STM32_FUNCTION(5, "SAI4_SCK_B"),
+ STM32_FUNCTION(7, "USART1_RTS"),
+ STM32_FUNCTION(9, "TIM8_CH1"),
+ STM32_FUNCTION(14, "LCD_B5"),
+ STM32_FUNCTION(15, "DCMI_D13 PSSI_D13 DCMIPP_D13"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(131, "PI3"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOI3"),
+ STM32_FUNCTION(4, "LPTIM1_IN2"),
+ STM32_FUNCTION(5, "SAI4_SD_B"),
+ STM32_FUNCTION(7, "USART1_CTS"),
+ STM32_FUNCTION(9, "TIM8_CH2"),
+ STM32_FUNCTION(14, "LCD_B6"),
+ STM32_FUNCTION(15, "PSSI_D14 DCMIPP_D14"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(132, "PI4"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOI4"),
+ STM32_FUNCTION(4, "LPTIM1_CH1"),
+ STM32_FUNCTION(5, "SAI4_FS_B"),
+ STM32_FUNCTION(9, "TIM8_CH3"),
+ STM32_FUNCTION(14, "LCD_B7"),
+ STM32_FUNCTION(15, "PSSI_D15 DCMIPP_D15"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(133, "PI5"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOI5"),
+ STM32_FUNCTION(3, "SPI5_MOSI"),
+ STM32_FUNCTION(4, "SPI1_MOSI I2S1_SDO"),
+ STM32_FUNCTION(6, "UART5_CTS"),
+ STM32_FUNCTION(7, "UART9_RX"),
+ STM32_FUNCTION(9, "TIM5_CH2"),
+ STM32_FUNCTION(14, "LCD_DE"),
+ STM32_FUNCTION(15, "DCMI_D1 PSSI_D1 DCMIPP_D1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(134, "PI6"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOI6"),
+ STM32_FUNCTION(2, "MCO1"),
+ STM32_FUNCTION(7, "USART3_TX"),
+ STM32_FUNCTION(8, "TIM2_ETR"),
+ STM32_FUNCTION(9, "TIM3_CH1"),
+ STM32_FUNCTION(14, "LCD_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(135, "PI7"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOI7"),
+ STM32_FUNCTION(7, "USART3_RX"),
+ STM32_FUNCTION(8, "TIM2_CH1"),
+ STM32_FUNCTION(9, "TIM3_CH2"),
+ STM32_FUNCTION(14, "LCD_HSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(136, "PI8"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOI8"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(137, "PI9"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOI9"),
+ STM32_FUNCTION(2, "SPI7_MOSI"),
+ STM32_FUNCTION(3, "SPI2_MOSI I2S2_SDO"),
+ STM32_FUNCTION(5, "FDCAN2_TX"),
+ STM32_FUNCTION(7, "UART9_CTS"),
+ STM32_FUNCTION(9, "TIM16_BKIN"),
+ STM32_FUNCTION(10, "SDVSEL2"),
+ STM32_FUNCTION(11, "FMC_NWAIT"),
+ STM32_FUNCTION(13, "DSI_TE"),
+ STM32_FUNCTION(14, "LCD_B0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(138, "PI10"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOI10"),
+ STM32_FUNCTION(2, "SAI1_SCK_A"),
+ STM32_FUNCTION(3, "SPI1_SCK I2S1_CK"),
+ STM32_FUNCTION(4, "SPDIFRX1_IN0"),
+ STM32_FUNCTION(5, "FDCAN2_RX"),
+ STM32_FUNCTION(6, "MDF1_CCK0"),
+ STM32_FUNCTION(9, "TIM4_CH1"),
+ STM32_FUNCTION(10, "SDVSEL1"),
+ STM32_FUNCTION(13, "FMC_AD12 FMC_D12"),
+ STM32_FUNCTION(14, "DSI_TE"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(139, "PI11"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOI11"),
+ STM32_FUNCTION(3, "I2S2_MCK"),
+ STM32_FUNCTION(6, "UART8_TX"),
+ STM32_FUNCTION(7, "UART9_RTS"),
+ STM32_FUNCTION(10, "TIM4_CH3"),
+ STM32_FUNCTION(11, "SDMMC3_D3"),
+ STM32_FUNCTION(12, "FMC_AD15 FMC_D15"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(140, "PI12"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOI12"),
+ STM32_FUNCTION(3, "SPI4_NSS"),
+ STM32_FUNCTION(8, "FDCAN3_RX"),
+ STM32_FUNCTION(9, "TIM11_CH1"),
+ STM32_FUNCTION(13, "FMC_A2"),
+ STM32_FUNCTION(14, "LCD_G0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(141, "PI13"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOI13"),
+ STM32_FUNCTION(3, "SPI4_MOSI"),
+ STM32_FUNCTION(5, "FDCAN2_RX"),
+ STM32_FUNCTION(9, "TIM10_CH1"),
+ STM32_FUNCTION(13, "FMC_A3"),
+ STM32_FUNCTION(14, "LCD_G1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(142, "PI14"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOI14"),
+ STM32_FUNCTION(3, "SPI2_NSS I2S2_WS"),
+ STM32_FUNCTION(6, "MDF1_SDI1"),
+ STM32_FUNCTION(8, "TIM20_CH3"),
+ STM32_FUNCTION(9, "TIM1_CH3N"),
+ STM32_FUNCTION(11, "FMC_NWAIT"),
+ STM32_FUNCTION(13, "FMC_AD10 FMC_D10"),
+ STM32_FUNCTION(14, "DCMI_D4 PSSI_D4 DCMIPP_D4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(143, "PI15"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOI15"),
+ STM32_FUNCTION(3, "I2S2_MCK"),
+ STM32_FUNCTION(4, "UART4_RX"),
+ STM32_FUNCTION(6, "MDF1_CKI2"),
+ STM32_FUNCTION(8, "TIM20_BKIN2"),
+ STM32_FUNCTION(9, "TIM1_BKIN2"),
+ STM32_FUNCTION(10, "SDVSEL1"),
+ STM32_FUNCTION(11, "SDMMC3_CDIR"),
+ STM32_FUNCTION(14, "DCMI_D9 PSSI_D9 DCMIPP_D9"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(144, "PJ0"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ0"),
+ STM32_FUNCTION(3, "SPI5_MOSI"),
+ STM32_FUNCTION(5, "PCIE_CLKREQN"),
+ STM32_FUNCTION(6, "SAI4_D2"),
+ STM32_FUNCTION(7, "USART6_CTS"),
+ STM32_FUNCTION(10, "USBH_HS_VBUSEN"),
+ STM32_FUNCTION(12, "ETH2_PTP_AUX_TS"),
+ STM32_FUNCTION(13, "FMC_A11"),
+ STM32_FUNCTION(14, "ETH3_PPS_OUT"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(145, "PJ1"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ1"),
+ STM32_FUNCTION(7, "USART6_RX"),
+ STM32_FUNCTION(9, "TIM8_CH1N"),
+ STM32_FUNCTION(10, "I2C1_SCL"),
+ STM32_FUNCTION(11, "I3C1_SCL"),
+ STM32_FUNCTION(13, "FMC_A7"),
+ STM32_FUNCTION(15, "DCMI_VSYNC PSSI_RDY DCMIPP_VSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(146, "PJ2"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ2"),
+ STM32_FUNCTION(5, "SAI2_SD_B"),
+ STM32_FUNCTION(7, "UART9_RTS"),
+ STM32_FUNCTION(9, "TIM8_CH4N"),
+ STM32_FUNCTION(10, "USBH_HS_OVRCUR"),
+ STM32_FUNCTION(13, "FMC_A14"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(147, "PJ3"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ3"),
+ STM32_FUNCTION(3, "SPI5_NSS"),
+ STM32_FUNCTION(4, "SAI2_FS_A"),
+ STM32_FUNCTION(6, "SAI4_D1"),
+ STM32_FUNCTION(7, "USART6_RTS"),
+ STM32_FUNCTION(9, "TIM8_CH3"),
+ STM32_FUNCTION(13, "FMC_A10"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(148, "PJ4"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ4"),
+ STM32_FUNCTION(4, "SAI2_FS_B"),
+ STM32_FUNCTION(6, "MDF1_CCK1"),
+ STM32_FUNCTION(7, "USART6_CK"),
+ STM32_FUNCTION(9, "TIM8_CH4"),
+ STM32_FUNCTION(10, "I2C2_SMBA"),
+ STM32_FUNCTION(11, "I2C5_SMBA"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(149, "PJ5"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ5"),
+ STM32_FUNCTION(3, "SPI5_MISO"),
+ STM32_FUNCTION(4, "SAI2_SCK_B"),
+ STM32_FUNCTION(6, "SAI4_CK1"),
+ STM32_FUNCTION(7, "USART6_TX"),
+ STM32_FUNCTION(9, "TIM8_CH1"),
+ STM32_FUNCTION(13, "FMC_A8"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(150, "PJ6"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ6"),
+ STM32_FUNCTION(3, "SPI7_MOSI"),
+ STM32_FUNCTION(5, "SAI4_SD_A"),
+ STM32_FUNCTION(7, "USART2_CK"),
+ STM32_FUNCTION(8, "TIM20_CH1N"),
+ STM32_FUNCTION(9, "TIM1_CH1"),
+ STM32_FUNCTION(10, "I2C6_SMBA"),
+ STM32_FUNCTION(14, "DCMI_D7 PSSI_D7 DCMIPP_D7"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(151, "PJ7"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ7"),
+ STM32_FUNCTION(3, "SPI5_MISO"),
+ STM32_FUNCTION(5, "SAI2_MCLK_B"),
+ STM32_FUNCTION(6, "SAI4_D3"),
+ STM32_FUNCTION(7, "USART6_CK"),
+ STM32_FUNCTION(9, "TIM8_CH2N"),
+ STM32_FUNCTION(10, "I2C1_SMBA"),
+ STM32_FUNCTION(13, "FMC_A12"),
+ STM32_FUNCTION(15, "DCMI_D0 PSSI_D0 DCMIPP_D0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(152, "PJ8"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ8"),
+ STM32_FUNCTION(3, "SPI5_SCK"),
+ STM32_FUNCTION(6, "SAI4_CK2"),
+ STM32_FUNCTION(7, "USART6_RX"),
+ STM32_FUNCTION(9, "TIM8_CH2"),
+ STM32_FUNCTION(13, "FMC_A9"),
+ STM32_FUNCTION(15, "PSSI_D14 DCMIPP_D14"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(153, "PJ9"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ9"),
+ STM32_FUNCTION(3, "SPI4_RDY"),
+ STM32_FUNCTION(8, "TIM12_CH1"),
+ STM32_FUNCTION(9, "TIM8_BKIN"),
+ STM32_FUNCTION(13, "FMC_A5"),
+ STM32_FUNCTION(15, "DCMI_PIXCLK PSSI_PDCK DCMIPP_PIXCLK"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(154, "PJ10"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ10"),
+ STM32_FUNCTION(8, "TIM12_CH2"),
+ STM32_FUNCTION(9, "TIM8_ETR"),
+ STM32_FUNCTION(10, "I2C1_SDA"),
+ STM32_FUNCTION(11, "I3C1_SDA"),
+ STM32_FUNCTION(13, "FMC_A6"),
+ STM32_FUNCTION(15, "DCMI_HSYNC PSSI_DE DCMIPP_HSYNC"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(155, "PJ11"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ11"),
+ STM32_FUNCTION(3, "SPI5_RDY"),
+ STM32_FUNCTION(4, "SAI2_SCK_A"),
+ STM32_FUNCTION(6, "SAI4_D4"),
+ STM32_FUNCTION(7, "UART9_CTS"),
+ STM32_FUNCTION(9, "TIM8_CH3N"),
+ STM32_FUNCTION(13, "FMC_A13"),
+ STM32_FUNCTION(15, "DCMI_D12 PSSI_D12 DCMIPP_D12"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(156, "PJ12"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ12"),
+ STM32_FUNCTION(4, "SAI2_SD_A"),
+ STM32_FUNCTION(7, "UART9_RX"),
+ STM32_FUNCTION(8, "FDCAN1_TX"),
+ STM32_FUNCTION(9, "TIM8_BKIN2"),
+ STM32_FUNCTION(10, "I2C2_SCL"),
+ STM32_FUNCTION(11, "I3C2_SCL"),
+ STM32_FUNCTION(13, "FMC_A15"),
+ STM32_FUNCTION(15, "DCMI_D13 PSSI_D13 DCMIPP_D13"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(157, "PJ13"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ13"),
+ STM32_FUNCTION(4, "SAI2_MCLK_A"),
+ STM32_FUNCTION(7, "UART9_TX"),
+ STM32_FUNCTION(8, "FDCAN1_RX"),
+ STM32_FUNCTION(9, "TIM10_CH1"),
+ STM32_FUNCTION(10, "I2C2_SDA"),
+ STM32_FUNCTION(11, "I3C2_SDA"),
+ STM32_FUNCTION(15, "PSSI_D15 DCMIPP_D15"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(158, "PJ14"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ14"),
+ STM32_FUNCTION(3, "SPI4_SCK"),
+ STM32_FUNCTION(8, "FDCAN3_TX"),
+ STM32_FUNCTION(13, "FMC_A1"),
+ STM32_FUNCTION(14, "LCD_R0"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(159, "PJ15"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOJ15"),
+ STM32_FUNCTION(1, "TRACED7"),
+ STM32_FUNCTION(2, "HDP7"),
+ STM32_FUNCTION(3, "SPI4_MISO"),
+ STM32_FUNCTION(5, "FDCAN2_TX"),
+ STM32_FUNCTION(9, "TIM11_CH1"),
+ STM32_FUNCTION(13, "FMC_A4"),
+ STM32_FUNCTION(14, "LCD_R1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(160, "PK0"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOK0"),
+ STM32_FUNCTION(3, "SPI2_MISO I2S2_SDI"),
+ STM32_FUNCTION(4, "SPDIFRX1_IN2"),
+ STM32_FUNCTION(6, "MDF1_CCK0"),
+ STM32_FUNCTION(8, "TIM20_ETR"),
+ STM32_FUNCTION(9, "TIM1_ETR"),
+ STM32_FUNCTION(11, "SDMMC3_D123DIR"),
+ STM32_FUNCTION(13, "FMC_AD11 FMC_D11"),
+ STM32_FUNCTION(14, "DCMI_D11 PSSI_D11 DCMIPP_D11"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(161, "PK1"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOK1"),
+ STM32_FUNCTION(3, "SPI2_MOSI I2S2_SDO"),
+ STM32_FUNCTION(6, "MDF1_SDI2"),
+ STM32_FUNCTION(8, "TIM20_BKIN"),
+ STM32_FUNCTION(9, "TIM1_BKIN"),
+ STM32_FUNCTION(10, "SDVSEL2"),
+ STM32_FUNCTION(11, "SDMMC3_D0DIR"),
+ STM32_FUNCTION(13, "FMC_AD13 FMC_D13"),
+ STM32_FUNCTION(14, "DCMI_D10 PSSI_D10 DCMIPP_D10"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(162, "PK2"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOK2"),
+ STM32_FUNCTION(3, "SPI7_NSS"),
+ STM32_FUNCTION(5, "SAI4_SCK_A"),
+ STM32_FUNCTION(7, "USART1_RTS"),
+ STM32_FUNCTION(8, "TIM20_CH2"),
+ STM32_FUNCTION(9, "TIM1_CH2N"),
+ STM32_FUNCTION(10, "I2C6_SDA"),
+ STM32_FUNCTION(13, "FMC_NCE3"),
+ STM32_FUNCTION(14, "DCMI_D6 PSSI_D6 DCMIPP_D6"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(163, "PK3"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOK3"),
+ STM32_FUNCTION(3, "SPI7_RDY"),
+ STM32_FUNCTION(6, "MDF1_CKI1"),
+ STM32_FUNCTION(8, "TIM20_CH3N"),
+ STM32_FUNCTION(9, "TIM1_CH3"),
+ STM32_FUNCTION(13, "FMC_AD8 FMC_D8"),
+ STM32_FUNCTION(14, "DCMI_D3 PSSI_D3 DCMIPP_D3"),
+ STM32_FUNCTION(15, "FMC_NCE4"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(164, "PK4"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOK4"),
+ STM32_FUNCTION(3, "SPI7_MISO"),
+ STM32_FUNCTION(4, "UART4_TX"),
+ STM32_FUNCTION(5, "SAI4_FS_A"),
+ STM32_FUNCTION(8, "TIM20_CH1"),
+ STM32_FUNCTION(9, "TIM1_CH1N"),
+ STM32_FUNCTION(11, "SDMMC3_CKIN"),
+ STM32_FUNCTION(13, "FMC_AD9 FMC_D9"),
+ STM32_FUNCTION(14, "DCMI_D8 PSSI_D8 DCMIPP_D8"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(165, "PK5"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOK5"),
+ STM32_FUNCTION(3, "SPI2_RDY"),
+ STM32_FUNCTION(6, "MDF1_CKI0"),
+ STM32_FUNCTION(7, "USART1_TX"),
+ STM32_FUNCTION(8, "TIM20_CH4N"),
+ STM32_FUNCTION(9, "TIM1_CH4"),
+ STM32_FUNCTION(11, "I2C5_SCL"),
+ STM32_FUNCTION(13, "FMC_AD5 FMC_D5"),
+ STM32_FUNCTION(14, "DCMI_D1 PSSI_D1 DCMIPP_D1"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(166, "PK6"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOK6"),
+ STM32_FUNCTION(3, "SPI7_SCK"),
+ STM32_FUNCTION(5, "SAI4_MCLK_A"),
+ STM32_FUNCTION(7, "USART1_CTS"),
+ STM32_FUNCTION(8, "TIM20_CH2N"),
+ STM32_FUNCTION(9, "TIM1_CH2"),
+ STM32_FUNCTION(10, "I2C6_SCL"),
+ STM32_FUNCTION(12, "FMC_AD14 FMC_D14"),
+ STM32_FUNCTION(13, "FMC_AD7 FMC_D7"),
+ STM32_FUNCTION(14, "DCMI_D5 PSSI_D5 DCMIPP_D5"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(167, "PK7"),
+ STM32MP_PKG_AI,
+ STM32_FUNCTION(0, "GPIOK7"),
+ STM32_FUNCTION(6, "MDF1_SDI0"),
+ STM32_FUNCTION(7, "USART1_RX"),
+ STM32_FUNCTION(8, "TIM20_CH4"),
+ STM32_FUNCTION(9, "TIM1_CH4N"),
+ STM32_FUNCTION(11, "I2C5_SDA"),
+ STM32_FUNCTION(12, "FMC_NCE4"),
+ STM32_FUNCTION(13, "FMC_AD6 FMC_D6"),
+ STM32_FUNCTION(14, "DCMI_D2 PSSI_D2 DCMIPP_D2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+};
+
+static const struct stm32_desc_pin stm32mp257_z_pins[] = {
+ STM32_PIN_PKG(
+ PINCTRL_PIN(400, "PZ0"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOZ0"),
+ STM32_FUNCTION(3, "LPTIM3_IN1"),
+ STM32_FUNCTION(4, "SPI8_MOSI"),
+ STM32_FUNCTION(5, "TIM8_CH1"),
+ STM32_FUNCTION(7, "LPUART1_TX"),
+ STM32_FUNCTION(8, "LPTIM5_OUT"),
+ STM32_FUNCTION(9, "I2C8_SDA"),
+ STM32_FUNCTION(11, "LPTIM3_CH2"),
+ STM32_FUNCTION(12, "I3C4_SDA"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(401, "PZ1"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOZ1"),
+ STM32_FUNCTION(3, "LPTIM3_CH1"),
+ STM32_FUNCTION(4, "SPI8_MISO"),
+ STM32_FUNCTION(5, "TIM8_CH2"),
+ STM32_FUNCTION(7, "LPUART1_RX"),
+ STM32_FUNCTION(8, "LPTIM5_ETR"),
+ STM32_FUNCTION(9, "I2C8_SCL"),
+ STM32_FUNCTION(10, "I2C8_SMBA"),
+ STM32_FUNCTION(12, "I3C4_SCL"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(402, "PZ2"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOZ2"),
+ STM32_FUNCTION(3, "LPTIM3_CH1"),
+ STM32_FUNCTION(4, "SPI8_SCK"),
+ STM32_FUNCTION(6, "ADF1_CCK0"),
+ STM32_FUNCTION(7, "LPUART1_RTS"),
+ STM32_FUNCTION(8, "LPTIM4_ETR"),
+ STM32_FUNCTION(9, "I2C8_SCL"),
+ STM32_FUNCTION(12, "I3C4_SCL"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(403, "PZ3"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOZ3"),
+ STM32_FUNCTION(1, "DBTRGI"),
+ STM32_FUNCTION(2, "DBTRGO"),
+ STM32_FUNCTION(3, "LPTIM3_ETR"),
+ STM32_FUNCTION(4, "SPI8_NSS"),
+ STM32_FUNCTION(5, "MDF1_SDI5"),
+ STM32_FUNCTION(6, "ADF1_SDI0"),
+ STM32_FUNCTION(7, "LPUART1_CTS"),
+ STM32_FUNCTION(8, "LPTIM4_IN1"),
+ STM32_FUNCTION(9, "I2C8_SDA"),
+ STM32_FUNCTION(11, "LPTIM4_CH2"),
+ STM32_FUNCTION(12, "I3C4_SDA"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(404, "PZ4"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOZ4"),
+ STM32_FUNCTION(1, "DBTRGI"),
+ STM32_FUNCTION(2, "DBTRGO"),
+ STM32_FUNCTION(3, "MCO2"),
+ STM32_FUNCTION(4, "SPI8_RDY"),
+ STM32_FUNCTION(5, "MDF1_CCK1"),
+ STM32_FUNCTION(6, "ADF1_CCK1"),
+ STM32_FUNCTION(7, "LPUART1_RX"),
+ STM32_FUNCTION(8, "LPTIM4_CH1"),
+ STM32_FUNCTION(9, "I2C8_SCL"),
+ STM32_FUNCTION(12, "I3C4_SCL"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(405, "PZ5"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOZ5"),
+ STM32_FUNCTION(2, "MCO1"),
+ STM32_FUNCTION(3, "LPTIM3_ETR"),
+ STM32_FUNCTION(4, "SPI8_SCK"),
+ STM32_FUNCTION(6, "ADF1_CCK0"),
+ STM32_FUNCTION(7, "LPUART1_RTS"),
+ STM32_FUNCTION(8, "LPTIM5_IN1"),
+ STM32_FUNCTION(11, "LPTIM4_CH2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(406, "PZ6"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOZ6"),
+ STM32_FUNCTION(1, "DBTRGI"),
+ STM32_FUNCTION(2, "DBTRGO"),
+ STM32_FUNCTION(4, "SPI8_NSS"),
+ STM32_FUNCTION(5, "TIM8_CH3"),
+ STM32_FUNCTION(6, "ADF1_SDI0"),
+ STM32_FUNCTION(7, "LPUART1_CTS"),
+ STM32_FUNCTION(8, "LPTIM5_OUT"),
+ STM32_FUNCTION(11, "LPTIM4_CH2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(407, "PZ7"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOZ7"),
+ STM32_FUNCTION(4, "SPI8_MOSI"),
+ STM32_FUNCTION(5, "MDF1_CCK1"),
+ STM32_FUNCTION(6, "ADF1_CCK1"),
+ STM32_FUNCTION(7, "LPUART1_TX"),
+ STM32_FUNCTION(8, "LPTIM5_IN1"),
+ STM32_FUNCTION(11, "LPTIM3_CH2"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(408, "PZ8"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOZ8"),
+ STM32_FUNCTION(3, "LPTIM3_IN1"),
+ STM32_FUNCTION(4, "SPI8_MISO"),
+ STM32_FUNCTION(5, "MDF1_SDI5"),
+ STM32_FUNCTION(6, "ADF1_SDI0"),
+ STM32_FUNCTION(7, "LPUART1_RX"),
+ STM32_FUNCTION(8, "LPTIM4_CH1"),
+ STM32_FUNCTION(9, "I2C8_SMBA"),
+ STM32_FUNCTION(10, "LPTIM5_ETR"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+ STM32_PIN_PKG(
+ PINCTRL_PIN(409, "PZ9"),
+ STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL,
+ STM32_FUNCTION(0, "GPIOZ9"),
+ STM32_FUNCTION(2, "MCO2"),
+ STM32_FUNCTION(4, "SPI8_RDY"),
+ STM32_FUNCTION(5, "MDF1_CKI5"),
+ STM32_FUNCTION(7, "LPUART1_TX"),
+ STM32_FUNCTION(8, "LPTIM4_ETR"),
+ STM32_FUNCTION(9, "I2C8_SDA"),
+ STM32_FUNCTION(11, "LPTIM3_CH2"),
+ STM32_FUNCTION(12, "I3C4_SDA"),
+ STM32_FUNCTION(16, "EVENTOUT"),
+ STM32_FUNCTION(17, "ANALOG")
+ ),
+};
+
+static struct stm32_pinctrl_match_data stm32mp257_match_data = {
+ .pins = stm32mp257_pins,
+ .npins = ARRAY_SIZE(stm32mp257_pins),
+};
+
+static struct stm32_pinctrl_match_data stm32mp257_z_match_data = {
+ .pins = stm32mp257_z_pins,
+ .npins = ARRAY_SIZE(stm32mp257_z_pins),
+};
+
+static const struct of_device_id stm32mp257_pctrl_match[] = {
+ {
+ .compatible = "st,stm32mp257-pinctrl",
+ .data = &stm32mp257_match_data,
+ },
+ {
+ .compatible = "st,stm32mp257-z-pinctrl",
+ .data = &stm32mp257_z_match_data,
+ },
+ { }
+};
+
+static const struct dev_pm_ops stm32_pinctrl_dev_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, stm32_pinctrl_resume)
+};
+
+static struct platform_driver stm32mp257_pinctrl_driver = {
+ .probe = stm32_pctl_probe,
+ .driver = {
+ .name = "stm32mp257-pinctrl",
+ .of_match_table = stm32mp257_pctrl_match,
+ .pm = &stm32_pinctrl_dev_pm_ops,
+ },
+};
+
+static int __init stm32mp257_pinctrl_init(void)
+{
+ return platform_driver_register(&stm32mp257_pinctrl_driver);
+}
+arch_initcall(stm32mp257_pinctrl_init);
diff --git a/drivers/pinctrl/sunplus/sppctl.c b/drivers/pinctrl/sunplus/sppctl.c
index 6bbbab3a6fdf..150996949ede 100644
--- a/drivers/pinctrl/sunplus/sppctl.c
+++ b/drivers/pinctrl/sunplus/sppctl.c
@@ -834,11 +834,6 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node
int i, size = 0;
list = of_get_property(np_config, "sunplus,pins", &size);
-
- if (nmG <= 0)
- nmG = 0;
-
- parent = of_get_parent(np_config);
*num_maps = size / sizeof(*list);
/*
@@ -866,10 +861,14 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node
}
}
+ if (nmG <= 0)
+ nmG = 0;
+
*map = kcalloc(*num_maps + nmG, sizeof(**map), GFP_KERNEL);
- if (*map == NULL)
+ if (!(*map))
return -ENOMEM;
+ parent = of_get_parent(np_config);
for (i = 0; i < (*num_maps); i++) {
dt_pin = be32_to_cpu(list[i]);
pin_num = FIELD_GET(GENMASK(31, 24), dt_pin);
@@ -883,6 +882,8 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node
(*map)[i].data.configs.num_configs = 1;
(*map)[i].data.configs.group_or_pin = pin_get_name(pctldev, pin_num);
configs = kmalloc(sizeof(*configs), GFP_KERNEL);
+ if (!configs)
+ goto sppctl_map_err;
*configs = FIELD_GET(GENMASK(7, 0), dt_pin);
(*map)[i].data.configs.configs = configs;
@@ -896,6 +897,8 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node
(*map)[i].data.configs.num_configs = 1;
(*map)[i].data.configs.group_or_pin = pin_get_name(pctldev, pin_num);
configs = kmalloc(sizeof(*configs), GFP_KERNEL);
+ if (!configs)
+ goto sppctl_map_err;
*configs = SPPCTL_IOP_CONFIGS;
(*map)[i].data.configs.configs = configs;
@@ -965,6 +968,14 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node
of_node_put(parent);
dev_dbg(pctldev->dev, "%d pins mapped\n", *num_maps);
return 0;
+
+sppctl_map_err:
+ for (i = 0; i < (*num_maps); i++)
+ if ((*map)[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
+ kfree((*map)[i].data.configs.configs);
+ kfree(*map);
+ of_node_put(parent);
+ return -ENOMEM;
}
static const struct pinctrl_ops sppctl_pctl_ops = {
diff --git a/drivers/pinctrl/tegra/Kconfig b/drivers/pinctrl/tegra/Kconfig
index a67d0d9ae8cd..4e87d19323ba 100644
--- a/drivers/pinctrl/tegra/Kconfig
+++ b/drivers/pinctrl/tegra/Kconfig
@@ -28,6 +28,10 @@ config PINCTRL_TEGRA194
bool
select PINCTRL_TEGRA
+config PINCTRL_TEGRA234
+ bool
+ select PINCTRL_TEGRA
+
config PINCTRL_TEGRA_XUSB
def_bool y if ARCH_TEGRA
select GENERIC_PHY
diff --git a/drivers/pinctrl/tegra/Makefile b/drivers/pinctrl/tegra/Makefile
index ead4e10097d0..a93973701d4c 100644
--- a/drivers/pinctrl/tegra/Makefile
+++ b/drivers/pinctrl/tegra/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o
obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o
obj-$(CONFIG_PINCTRL_TEGRA210) += pinctrl-tegra210.o
obj-$(CONFIG_PINCTRL_TEGRA194) += pinctrl-tegra194.o
+obj-$(CONFIG_PINCTRL_TEGRA234) += pinctrl-tegra234.o
obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
index 1729b7ddfa94..4547cf66d03b 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
@@ -232,7 +232,7 @@ static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- return pmx->soc->functions[function].name;
+ return pmx->functions[function].name;
}
static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
@@ -242,8 +242,8 @@ static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- *groups = pmx->soc->functions[function].groups;
- *num_groups = pmx->soc->functions[function].ngroups;
+ *groups = pmx->functions[function].groups;
+ *num_groups = pmx->functions[function].ngroups;
return 0;
}
@@ -789,20 +789,26 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
* Each mux group will appear in 4 functions' list of groups.
* This over-allocates slightly, since not all groups are mux groups.
*/
- pmx->group_pins = devm_kcalloc(&pdev->dev,
- soc_data->ngroups * 4, sizeof(*pmx->group_pins),
- GFP_KERNEL);
+ pmx->group_pins = devm_kcalloc(&pdev->dev, pmx->soc->ngroups * 4,
+ sizeof(*pmx->group_pins), GFP_KERNEL);
if (!pmx->group_pins)
return -ENOMEM;
+ pmx->functions = devm_kcalloc(&pdev->dev, pmx->soc->nfunctions,
+ sizeof(*pmx->functions), GFP_KERNEL);
+ if (!pmx->functions)
+ return -ENOMEM;
+
group_pins = pmx->group_pins;
- for (fn = 0; fn < soc_data->nfunctions; fn++) {
- struct tegra_function *func = &soc_data->functions[fn];
+ for (fn = 0; fn < pmx->soc->nfunctions; fn++) {
+ struct tegra_function *func = &pmx->functions[fn];
+
+ func->name = pmx->soc->functions[fn];
func->groups = group_pins;
- for (gn = 0; gn < soc_data->ngroups; gn++) {
- const struct tegra_pingroup *g = &soc_data->groups[gn];
+ for (gn = 0; gn < pmx->soc->ngroups; gn++) {
+ const struct tegra_pingroup *g = &pmx->soc->groups[gn];
if (g->mux_reg == -1)
continue;
@@ -814,7 +820,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
continue;
BUG_ON(group_pins - pmx->group_pins >=
- soc_data->ngroups * 4);
+ pmx->soc->ngroups * 4);
*group_pins++ = g->name;
func->ngroups++;
}
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h
index 6130cba7cce5..b3289bdf727d 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra.h
+++ b/drivers/pinctrl/tegra/pinctrl-tegra.h
@@ -13,6 +13,7 @@ struct tegra_pmx {
struct pinctrl_dev *pctl;
const struct tegra_pinctrl_soc_data *soc;
+ struct tegra_function *functions;
const char **group_pins;
struct pinctrl_gpio_range gpio_range;
@@ -191,7 +192,7 @@ struct tegra_pinctrl_soc_data {
const char *gpio_compatible;
const struct pinctrl_pin_desc *pins;
unsigned npins;
- struct tegra_function *functions;
+ const char * const *functions;
unsigned nfunctions;
const struct tegra_pingroup *groups;
unsigned ngroups;
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra114.c b/drivers/pinctrl/tegra/pinctrl-tegra114.c
index e72ab1eb2398..3d425b2018e7 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra114.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra114.c
@@ -1452,12 +1452,9 @@ enum tegra_mux {
TEGRA_MUX_VI_ALT3,
};
-#define FUNCTION(fname) \
- { \
- .name = #fname, \
- }
+#define FUNCTION(fname) #fname
-static struct tegra_function tegra114_functions[] = {
+static const char * const tegra114_functions[] = {
FUNCTION(blink),
FUNCTION(cec),
FUNCTION(cldvfs),
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra124.c b/drivers/pinctrl/tegra/pinctrl-tegra124.c
index 26096c6b967e..2a50c5c7516c 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra124.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra124.c
@@ -1611,12 +1611,9 @@ enum tegra_mux {
TEGRA_MUX_VIMCLK2_ALT,
};
-#define FUNCTION(fname) \
- { \
- .name = #fname, \
- }
+#define FUNCTION(fname) #fname
-static struct tegra_function tegra124_functions[] = {
+static const char * const tegra124_functions[] = {
FUNCTION(blink),
FUNCTION(ccla),
FUNCTION(cec),
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra194.c b/drivers/pinctrl/tegra/pinctrl-tegra194.c
index 277973c88434..69f58df62897 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra194.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra194.c
@@ -1189,12 +1189,9 @@ enum tegra_mux_dt {
};
/* Make list of each function name */
-#define TEGRA_PIN_FUNCTION(lid) \
- { \
- .name = #lid, \
- }
+#define TEGRA_PIN_FUNCTION(lid) #lid
-static struct tegra_function tegra194_functions[] = {
+static const char * const tegra194_functions[] = {
TEGRA_PIN_FUNCTION(rsvd0),
TEGRA_PIN_FUNCTION(rsvd1),
TEGRA_PIN_FUNCTION(rsvd2),
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra20.c b/drivers/pinctrl/tegra/pinctrl-tegra20.c
index 0dc2cf0d05b1..737fc2000f66 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra20.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra20.c
@@ -1889,12 +1889,9 @@ enum tegra_mux {
TEGRA_MUX_XIO,
};
-#define FUNCTION(fname) \
- { \
- .name = #fname, \
- }
+#define FUNCTION(fname) #fname
-static struct tegra_function tegra20_functions[] = {
+static const char * const tegra20_functions[] = {
FUNCTION(ahb_clk),
FUNCTION(apb_clk),
FUNCTION(audio_sync),
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra210.c b/drivers/pinctrl/tegra/pinctrl-tegra210.c
index b480f607fa16..9bb29146dfff 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra210.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra210.c
@@ -1185,12 +1185,9 @@ enum tegra_mux {
TEGRA_MUX_VIMCLK2,
};
-#define FUNCTION(fname) \
- { \
- .name = #fname, \
- }
+#define FUNCTION(fname) #fname
-static struct tegra_function tegra210_functions[] = {
+static const char * const tegra210_functions[] = {
FUNCTION(aud),
FUNCTION(bcl),
FUNCTION(blink),
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra234.c b/drivers/pinctrl/tegra/pinctrl-tegra234.c
new file mode 100644
index 000000000000..86c2b84e792d
--- /dev/null
+++ b/drivers/pinctrl/tegra/pinctrl-tegra234.c
@@ -0,0 +1,1960 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Pinctrl data for the NVIDIA Tegra234 pinmux
+ *
+ * Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved.
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-tegra.h"
+
+/* Define unique ID for each pins */
+enum {
+ TEGRA_PIN_DAP6_SCLK_PA0,
+ TEGRA_PIN_DAP6_DOUT_PA1,
+ TEGRA_PIN_DAP6_DIN_PA2,
+ TEGRA_PIN_DAP6_FS_PA3,
+ TEGRA_PIN_DAP4_SCLK_PA4,
+ TEGRA_PIN_DAP4_DOUT_PA5,
+ TEGRA_PIN_DAP4_DIN_PA6,
+ TEGRA_PIN_DAP4_FS_PA7,
+ TEGRA_PIN_SOC_GPIO08_PB0,
+ TEGRA_PIN_QSPI0_SCK_PC0,
+ TEGRA_PIN_QSPI0_CS_N_PC1,
+ TEGRA_PIN_QSPI0_IO0_PC2,
+ TEGRA_PIN_QSPI0_IO1_PC3,
+ TEGRA_PIN_QSPI0_IO2_PC4,
+ TEGRA_PIN_QSPI0_IO3_PC5,
+ TEGRA_PIN_QSPI1_SCK_PC6,
+ TEGRA_PIN_QSPI1_CS_N_PC7,
+ TEGRA_PIN_QSPI1_IO0_PD0,
+ TEGRA_PIN_QSPI1_IO1_PD1,
+ TEGRA_PIN_QSPI1_IO2_PD2,
+ TEGRA_PIN_QSPI1_IO3_PD3,
+ TEGRA_PIN_EQOS_TXC_PE0,
+ TEGRA_PIN_EQOS_TD0_PE1,
+ TEGRA_PIN_EQOS_TD1_PE2,
+ TEGRA_PIN_EQOS_TD2_PE3,
+ TEGRA_PIN_EQOS_TD3_PE4,
+ TEGRA_PIN_EQOS_TX_CTL_PE5,
+ TEGRA_PIN_EQOS_RD0_PE6,
+ TEGRA_PIN_EQOS_RD1_PE7,
+ TEGRA_PIN_EQOS_RD2_PF0,
+ TEGRA_PIN_EQOS_RD3_PF1,
+ TEGRA_PIN_EQOS_RX_CTL_PF2,
+ TEGRA_PIN_EQOS_RXC_PF3,
+ TEGRA_PIN_EQOS_SMA_MDIO_PF4,
+ TEGRA_PIN_EQOS_SMA_MDC_PF5,
+ TEGRA_PIN_SOC_GPIO13_PG0,
+ TEGRA_PIN_SOC_GPIO14_PG1,
+ TEGRA_PIN_SOC_GPIO15_PG2,
+ TEGRA_PIN_SOC_GPIO16_PG3,
+ TEGRA_PIN_SOC_GPIO17_PG4,
+ TEGRA_PIN_SOC_GPIO18_PG5,
+ TEGRA_PIN_SOC_GPIO19_PG6,
+ TEGRA_PIN_SOC_GPIO20_PG7,
+ TEGRA_PIN_SOC_GPIO21_PH0,
+ TEGRA_PIN_SOC_GPIO22_PH1,
+ TEGRA_PIN_SOC_GPIO06_PH2,
+ TEGRA_PIN_UART4_TX_PH3,
+ TEGRA_PIN_UART4_RX_PH4,
+ TEGRA_PIN_UART4_RTS_PH5,
+ TEGRA_PIN_UART4_CTS_PH6,
+ TEGRA_PIN_SOC_GPIO41_PH7,
+ TEGRA_PIN_SOC_GPIO42_PI0,
+ TEGRA_PIN_SOC_GPIO43_PI1,
+ TEGRA_PIN_SOC_GPIO44_PI2,
+ TEGRA_PIN_GEN1_I2C_SCL_PI3,
+ TEGRA_PIN_GEN1_I2C_SDA_PI4,
+ TEGRA_PIN_CPU_PWR_REQ_PI5,
+ TEGRA_PIN_SOC_GPIO07_PI6,
+ TEGRA_PIN_SDMMC1_CLK_PJ0,
+ TEGRA_PIN_SDMMC1_CMD_PJ1,
+ TEGRA_PIN_SDMMC1_DAT0_PJ2,
+ TEGRA_PIN_SDMMC1_DAT1_PJ3,
+ TEGRA_PIN_SDMMC1_DAT2_PJ4,
+ TEGRA_PIN_SDMMC1_DAT3_PJ5,
+ TEGRA_PIN_PEX_L0_CLKREQ_N_PK0,
+ TEGRA_PIN_PEX_L0_RST_N_PK1,
+ TEGRA_PIN_PEX_L1_CLKREQ_N_PK2,
+ TEGRA_PIN_PEX_L1_RST_N_PK3,
+ TEGRA_PIN_PEX_L2_CLKREQ_N_PK4,
+ TEGRA_PIN_PEX_L2_RST_N_PK5,
+ TEGRA_PIN_PEX_L3_CLKREQ_N_PK6,
+ TEGRA_PIN_PEX_L3_RST_N_PK7,
+ TEGRA_PIN_PEX_L4_CLKREQ_N_PL0,
+ TEGRA_PIN_PEX_L4_RST_N_PL1,
+ TEGRA_PIN_PEX_WAKE_N_PL2,
+ TEGRA_PIN_SOC_GPIO34_PL3,
+ TEGRA_PIN_DP_AUX_CH0_HPD_PM0,
+ TEGRA_PIN_DP_AUX_CH1_HPD_PM1,
+ TEGRA_PIN_DP_AUX_CH2_HPD_PM2,
+ TEGRA_PIN_DP_AUX_CH3_HPD_PM3,
+ TEGRA_PIN_SOC_GPIO55_PM4,
+ TEGRA_PIN_SOC_GPIO36_PM5,
+ TEGRA_PIN_SOC_GPIO53_PM6,
+ TEGRA_PIN_SOC_GPIO38_PM7,
+ TEGRA_PIN_DP_AUX_CH3_N_PN0,
+ TEGRA_PIN_SOC_GPIO39_PN1,
+ TEGRA_PIN_SOC_GPIO40_PN2,
+ TEGRA_PIN_DP_AUX_CH1_P_PN3,
+ TEGRA_PIN_DP_AUX_CH1_N_PN4,
+ TEGRA_PIN_DP_AUX_CH2_P_PN5,
+ TEGRA_PIN_DP_AUX_CH2_N_PN6,
+ TEGRA_PIN_DP_AUX_CH3_P_PN7,
+ TEGRA_PIN_EXTPERIPH1_CLK_PP0,
+ TEGRA_PIN_EXTPERIPH2_CLK_PP1,
+ TEGRA_PIN_CAM_I2C_SCL_PP2,
+ TEGRA_PIN_CAM_I2C_SDA_PP3,
+ TEGRA_PIN_SOC_GPIO23_PP4,
+ TEGRA_PIN_SOC_GPIO24_PP5,
+ TEGRA_PIN_SOC_GPIO25_PP6,
+ TEGRA_PIN_PWR_I2C_SCL_PP7,
+ TEGRA_PIN_PWR_I2C_SDA_PQ0,
+ TEGRA_PIN_SOC_GPIO28_PQ1,
+ TEGRA_PIN_SOC_GPIO29_PQ2,
+ TEGRA_PIN_SOC_GPIO30_PQ3,
+ TEGRA_PIN_SOC_GPIO31_PQ4,
+ TEGRA_PIN_SOC_GPIO32_PQ5,
+ TEGRA_PIN_SOC_GPIO33_PQ6,
+ TEGRA_PIN_SOC_GPIO35_PQ7,
+ TEGRA_PIN_SOC_GPIO37_PR0,
+ TEGRA_PIN_SOC_GPIO56_PR1,
+ TEGRA_PIN_UART1_TX_PR2,
+ TEGRA_PIN_UART1_RX_PR3,
+ TEGRA_PIN_UART1_RTS_PR4,
+ TEGRA_PIN_UART1_CTS_PR5,
+ TEGRA_PIN_GPU_PWR_REQ_PX0,
+ TEGRA_PIN_CV_PWR_REQ_PX1,
+ TEGRA_PIN_GP_PWM2_PX2,
+ TEGRA_PIN_GP_PWM3_PX3,
+ TEGRA_PIN_UART2_TX_PX4,
+ TEGRA_PIN_UART2_RX_PX5,
+ TEGRA_PIN_UART2_RTS_PX6,
+ TEGRA_PIN_UART2_CTS_PX7,
+ TEGRA_PIN_SPI3_SCK_PY0,
+ TEGRA_PIN_SPI3_MISO_PY1,
+ TEGRA_PIN_SPI3_MOSI_PY2,
+ TEGRA_PIN_SPI3_CS0_PY3,
+ TEGRA_PIN_SPI3_CS1_PY4,
+ TEGRA_PIN_UART5_TX_PY5,
+ TEGRA_PIN_UART5_RX_PY6,
+ TEGRA_PIN_UART5_RTS_PY7,
+ TEGRA_PIN_UART5_CTS_PZ0,
+ TEGRA_PIN_USB_VBUS_EN0_PZ1,
+ TEGRA_PIN_USB_VBUS_EN1_PZ2,
+ TEGRA_PIN_SPI1_SCK_PZ3,
+ TEGRA_PIN_SPI1_MISO_PZ4,
+ TEGRA_PIN_SPI1_MOSI_PZ5,
+ TEGRA_PIN_SPI1_CS0_PZ6,
+ TEGRA_PIN_SPI1_CS1_PZ7,
+ TEGRA_PIN_SPI5_SCK_PAC0,
+ TEGRA_PIN_SPI5_MISO_PAC1,
+ TEGRA_PIN_SPI5_MOSI_PAC2,
+ TEGRA_PIN_SPI5_CS0_PAC3,
+ TEGRA_PIN_SOC_GPIO57_PAC4,
+ TEGRA_PIN_SOC_GPIO58_PAC5,
+ TEGRA_PIN_SOC_GPIO59_PAC6,
+ TEGRA_PIN_SOC_GPIO60_PAC7,
+ TEGRA_PIN_SOC_GPIO45_PAD0,
+ TEGRA_PIN_SOC_GPIO46_PAD1,
+ TEGRA_PIN_SOC_GPIO47_PAD2,
+ TEGRA_PIN_SOC_GPIO48_PAD3,
+ TEGRA_PIN_UFS0_REF_CLK_PAE0,
+ TEGRA_PIN_UFS0_RST_N_PAE1,
+ TEGRA_PIN_PEX_L5_CLKREQ_N_PAF0,
+ TEGRA_PIN_PEX_L5_RST_N_PAF1,
+ TEGRA_PIN_PEX_L6_CLKREQ_N_PAF2,
+ TEGRA_PIN_PEX_L6_RST_N_PAF3,
+ TEGRA_PIN_PEX_L7_CLKREQ_N_PAG0,
+ TEGRA_PIN_PEX_L7_RST_N_PAG1,
+ TEGRA_PIN_PEX_L8_CLKREQ_N_PAG2,
+ TEGRA_PIN_PEX_L8_RST_N_PAG3,
+ TEGRA_PIN_PEX_L9_CLKREQ_N_PAG4,
+ TEGRA_PIN_PEX_L9_RST_N_PAG5,
+ TEGRA_PIN_PEX_L10_CLKREQ_N_PAG6,
+ TEGRA_PIN_PEX_L10_RST_N_PAG7,
+ TEGRA_PIN_EQOS_COMP,
+ TEGRA_PIN_QSPI_COMP,
+ TEGRA_PIN_SDMMC1_COMP,
+};
+
+enum {
+ TEGRA_PIN_CAN0_DOUT_PAA0,
+ TEGRA_PIN_CAN0_DIN_PAA1,
+ TEGRA_PIN_CAN1_DOUT_PAA2,
+ TEGRA_PIN_CAN1_DIN_PAA3,
+ TEGRA_PIN_CAN0_STB_PAA4,
+ TEGRA_PIN_CAN0_EN_PAA5,
+ TEGRA_PIN_SOC_GPIO49_PAA6,
+ TEGRA_PIN_CAN0_ERR_PAA7,
+ TEGRA_PIN_CAN1_STB_PBB0,
+ TEGRA_PIN_CAN1_EN_PBB1,
+ TEGRA_PIN_SOC_GPIO50_PBB2,
+ TEGRA_PIN_CAN1_ERR_PBB3,
+ TEGRA_PIN_SPI2_SCK_PCC0,
+ TEGRA_PIN_SPI2_MISO_PCC1,
+ TEGRA_PIN_SPI2_MOSI_PCC2,
+ TEGRA_PIN_SPI2_CS0_PCC3,
+ TEGRA_PIN_TOUCH_CLK_PCC4,
+ TEGRA_PIN_UART3_TX_PCC5,
+ TEGRA_PIN_UART3_RX_PCC6,
+ TEGRA_PIN_GEN2_I2C_SCL_PCC7,
+ TEGRA_PIN_GEN2_I2C_SDA_PDD0,
+ TEGRA_PIN_GEN8_I2C_SCL_PDD1,
+ TEGRA_PIN_GEN8_I2C_SDA_PDD2,
+ TEGRA_PIN_SCE_ERROR_PEE0,
+ TEGRA_PIN_VCOMP_ALERT_PEE1,
+ TEGRA_PIN_AO_RETENTION_N_PEE2,
+ TEGRA_PIN_BATT_OC_PEE3,
+ TEGRA_PIN_POWER_ON_PEE4,
+ TEGRA_PIN_SOC_GPIO26_PEE5,
+ TEGRA_PIN_SOC_GPIO27_PEE6,
+ TEGRA_PIN_BOOTV_CTL_N_PEE7,
+ TEGRA_PIN_HDMI_CEC_PGG0,
+};
+
+/* Table for pin descriptor */
+static const struct pinctrl_pin_desc tegra234_pins[] = {
+ PINCTRL_PIN(TEGRA_PIN_DAP6_SCLK_PA0, "DAP6_SCLK_PA0"),
+ PINCTRL_PIN(TEGRA_PIN_DAP6_DOUT_PA1, "DAP6_DOUT_PA1"),
+ PINCTRL_PIN(TEGRA_PIN_DAP6_DIN_PA2, "DAP6_DIN_PA2"),
+ PINCTRL_PIN(TEGRA_PIN_DAP6_FS_PA3, "DAP6_FS_PA3"),
+ PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PA4, "DAP4_SCLK_PA4"),
+ PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PA5, "DAP4_DOUT_PA5"),
+ PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PA6, "DAP4_DIN_PA6"),
+ PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PA7, "DAP4_FS_PA7"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO08_PB0, "SOC_GPIO08_PB0"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI0_SCK_PC0, "QSPI0_SCK_PC0"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI0_CS_N_PC1, "QSPI0_CS_N_PC1"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI0_IO0_PC2, "QSPI0_IO0_PC2"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI0_IO1_PC3, "QSPI0_IO1_PC3"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI0_IO2_PC4, "QSPI0_IO2_PC4"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI0_IO3_PC5, "QSPI0_IO3_PC5"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI1_SCK_PC6, "QSPI1_SCK_PC6"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI1_CS_N_PC7, "QSPI1_CS_N_PC7"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI1_IO0_PD0, "QSPI1_IO0_PD0"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI1_IO1_PD1, "QSPI1_IO1_PD1"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI1_IO2_PD2, "QSPI1_IO2_PD2"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI1_IO3_PD3, "QSPI1_IO3_PD3"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_TXC_PE0, "EQOS_TXC_PE0"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_TD0_PE1, "EQOS_TD0_PE1"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_TD1_PE2, "EQOS_TD1_PE2"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_TD2_PE3, "EQOS_TD2_PE3"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_TD3_PE4, "EQOS_TD3_PE4"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_TX_CTL_PE5, "EQOS_TX_CTL_PE5"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_RD0_PE6, "EQOS_RD0_PE6"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_RD1_PE7, "EQOS_RD1_PE7"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_RD2_PF0, "EQOS_RD2_PF0"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_RD3_PF1, "EQOS_RD3_PF1"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_RX_CTL_PF2, "EQOS_RX_CTL_PF2"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_RXC_PF3, "EQOS_RXC_PF3"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_SMA_MDIO_PF4, "EQOS_SMA_MDIO_PF4"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_SMA_MDC_PF5, "EQOS_SMA_MDC_PF5"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO13_PG0, "SOC_GPIO13_PG0"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO14_PG1, "SOC_GPIO14_PG1"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO15_PG2, "SOC_GPIO15_PG2"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO16_PG3, "SOC_GPIO16_PG3"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO17_PG4, "SOC_GPIO17_PG4"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO18_PG5, "SOC_GPIO18_PG5"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO19_PG6, "SOC_GPIO19_PG6"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO20_PG7, "SOC_GPIO20_PG7"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO21_PH0, "SOC_GPIO21_PH0"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO22_PH1, "SOC_GPIO22_PH1"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO06_PH2, "SOC_GPIO06_PH2"),
+ PINCTRL_PIN(TEGRA_PIN_UART4_TX_PH3, "UART4_TX_PH3"),
+ PINCTRL_PIN(TEGRA_PIN_UART4_RX_PH4, "UART4_RX_PH4"),
+ PINCTRL_PIN(TEGRA_PIN_UART4_RTS_PH5, "UART4_RTS_PH5"),
+ PINCTRL_PIN(TEGRA_PIN_UART4_CTS_PH6, "UART4_CTS_PH6"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO41_PH7, "SOC_GPIO41_PH7"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO42_PI0, "SOC_GPIO42_PI0"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO43_PI1, "SOC_GPIO43_PI1"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO44_PI2, "SOC_GPIO44_PI2"),
+ PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PI3, "GEN1_I2C_SCL_PI3"),
+ PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PI4, "GEN1_I2C_SDA_PI4"),
+ PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ_PI5, "CPU_PWR_REQ_PI5"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO07_PI6, "SOC_GPIO07_PI6"),
+ PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PJ0, "SDMMC1_CLK_PJ0"),
+ PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PJ1, "SDMMC1_CMD_PJ1"),
+ PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PJ2, "SDMMC1_DAT0_PJ2"),
+ PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PJ3, "SDMMC1_DAT1_PJ3"),
+ PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PJ4, "SDMMC1_DAT2_PJ4"),
+ PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PJ5, "SDMMC1_DAT3_PJ5"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PK0, "PEX_L0_CLKREQ_N_PK0"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PK1, "PEX_L0_RST_N_PK1"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PK2, "PEX_L1_CLKREQ_N_PK2"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PK3, "PEX_L1_RST_N_PK3"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L2_CLKREQ_N_PK4, "PEX_L2_CLKREQ_N_PK4"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L2_RST_N_PK5, "PEX_L2_RST_N_PK5"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L3_CLKREQ_N_PK6, "PEX_L3_CLKREQ_N_PK6"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L3_RST_N_PK7, "PEX_L3_RST_N_PK7"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L4_CLKREQ_N_PL0, "PEX_L4_CLKREQ_N_PL0"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L4_RST_N_PL1, "PEX_L4_RST_N_PL1"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PL2, "PEX_WAKE_N_PL2"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO34_PL3, "SOC_GPIO34_PL3"),
+ PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH0_HPD_PM0, "DP_AUX_CH0_HPD_PM0"),
+ PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH1_HPD_PM1, "DP_AUX_CH1_HPD_PM1"),
+ PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH2_HPD_PM2, "DP_AUX_CH2_HPD_PM2"),
+ PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH3_HPD_PM3, "DP_AUX_CH3_HPD_PM3"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO55_PM4, "SOC_GPIO55_PM4"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO36_PM5, "SOC_GPIO36_PM5"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO53_PM6, "SOC_GPIO53_PM6"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO38_PM7, "SOC_GPIO38_PM7"),
+ PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH3_N_PN0, "DP_AUX_CH3_N_PN0"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO39_PN1, "SOC_GPIO39_PN1"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO40_PN2, "SOC_GPIO40_PN2"),
+ PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH1_P_PN3, "DP_AUX_CH1_P_PN3"),
+ PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH1_N_PN4, "DP_AUX_CH1_N_PN4"),
+ PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH2_P_PN5, "DP_AUX_CH2_P_PN5"),
+ PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH2_N_PN6, "DP_AUX_CH2_N_PN6"),
+ PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH3_P_PN7, "DP_AUX_CH3_P_PN7"),
+ PINCTRL_PIN(TEGRA_PIN_EXTPERIPH1_CLK_PP0, "EXTPERIPH1_CLK_PP0"),
+ PINCTRL_PIN(TEGRA_PIN_EXTPERIPH2_CLK_PP1, "EXTPERIPH2_CLK_PP1"),
+ PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PP2, "CAM_I2C_SCL_PP2"),
+ PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PP3, "CAM_I2C_SDA_PP3"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO23_PP4, "SOC_GPIO23_PP4"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO24_PP5, "SOC_GPIO24_PP5"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO25_PP6, "SOC_GPIO25_PP6"),
+ PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PP7, "PWR_I2C_SCL_PP7"),
+ PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PQ0, "PWR_I2C_SDA_PQ0"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO28_PQ1, "SOC_GPIO28_PQ1"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO29_PQ2, "SOC_GPIO29_PQ2"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO30_PQ3, "SOC_GPIO30_PQ3"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO31_PQ4, "SOC_GPIO31_PQ4"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO32_PQ5, "SOC_GPIO32_PQ5"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO33_PQ6, "SOC_GPIO33_PQ6"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO35_PQ7, "SOC_GPIO35_PQ7"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO37_PR0, "SOC_GPIO37_PR0"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO56_PR1, "SOC_GPIO56_PR1"),
+ PINCTRL_PIN(TEGRA_PIN_UART1_TX_PR2, "UART1_TX_PR2"),
+ PINCTRL_PIN(TEGRA_PIN_UART1_RX_PR3, "UART1_RX_PR3"),
+ PINCTRL_PIN(TEGRA_PIN_UART1_RTS_PR4, "UART1_RTS_PR4"),
+ PINCTRL_PIN(TEGRA_PIN_UART1_CTS_PR5, "UART1_CTS_PR5"),
+ PINCTRL_PIN(TEGRA_PIN_GPU_PWR_REQ_PX0, "GPU_PWR_REQ_PX0"),
+ PINCTRL_PIN(TEGRA_PIN_CV_PWR_REQ_PX1, "CV_PWR_REQ_PX1"),
+ PINCTRL_PIN(TEGRA_PIN_GP_PWM2_PX2, "GP_PWM2_PX2"),
+ PINCTRL_PIN(TEGRA_PIN_GP_PWM3_PX3, "GP_PWM3_PX3"),
+ PINCTRL_PIN(TEGRA_PIN_UART2_TX_PX4, "UART2_TX_PX4"),
+ PINCTRL_PIN(TEGRA_PIN_UART2_RX_PX5, "UART2_RX_PX5"),
+ PINCTRL_PIN(TEGRA_PIN_UART2_RTS_PX6, "UART2_RTS_PX6"),
+ PINCTRL_PIN(TEGRA_PIN_UART2_CTS_PX7, "UART2_CTS_PX7"),
+ PINCTRL_PIN(TEGRA_PIN_SPI3_SCK_PY0, "SPI3_SCK_PY0"),
+ PINCTRL_PIN(TEGRA_PIN_SPI3_MISO_PY1, "SPI3_MISO_PY1"),
+ PINCTRL_PIN(TEGRA_PIN_SPI3_MOSI_PY2, "SPI3_MOSI_PY2"),
+ PINCTRL_PIN(TEGRA_PIN_SPI3_CS0_PY3, "SPI3_CS0_PY3"),
+ PINCTRL_PIN(TEGRA_PIN_SPI3_CS1_PY4, "SPI3_CS1_PY4"),
+ PINCTRL_PIN(TEGRA_PIN_UART5_TX_PY5, "UART5_TX_PY5"),
+ PINCTRL_PIN(TEGRA_PIN_UART5_RX_PY6, "UART5_RX_PY6"),
+ PINCTRL_PIN(TEGRA_PIN_UART5_RTS_PY7, "UART5_RTS_PY7"),
+ PINCTRL_PIN(TEGRA_PIN_UART5_CTS_PZ0, "UART5_CTS_PZ0"),
+ PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PZ1, "USB_VBUS_EN0_PZ1"),
+ PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PZ2, "USB_VBUS_EN1_PZ2"),
+ PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PZ3, "SPI1_SCK_PZ3"),
+ PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PZ4, "SPI1_MISO_PZ4"),
+ PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PZ5, "SPI1_MOSI_PZ5"),
+ PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_PZ6, "SPI1_CS0_PZ6"),
+ PINCTRL_PIN(TEGRA_PIN_SPI1_CS1_PZ7, "SPI1_CS1_PZ7"),
+ PINCTRL_PIN(TEGRA_PIN_SPI5_SCK_PAC0, "SPI5_SCK_PAC0"),
+ PINCTRL_PIN(TEGRA_PIN_SPI5_MISO_PAC1, "SPI5_MISO_PAC1"),
+ PINCTRL_PIN(TEGRA_PIN_SPI5_MOSI_PAC2, "SPI5_MOSI_PAC2"),
+ PINCTRL_PIN(TEGRA_PIN_SPI5_CS0_PAC3, "SPI5_CS0_PAC3"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO57_PAC4, "SOC_GPIO57_PAC4"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO58_PAC5, "SOC_GPIO58_PAC5"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO59_PAC6, "SOC_GPIO59_PAC6"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO60_PAC7, "SOC_GPIO60_PAC7"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO45_PAD0, "SOC_GPIO45_PAD0"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO46_PAD1, "SOC_GPIO46_PAD1"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO47_PAD2, "SOC_GPIO47_PAD2"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO48_PAD3, "SOC_GPIO48_PAD3"),
+ PINCTRL_PIN(TEGRA_PIN_UFS0_REF_CLK_PAE0, "UFS0_REF_CLK_PAE0"),
+ PINCTRL_PIN(TEGRA_PIN_UFS0_RST_N_PAE1, "UFS0_RST_N_PAE1"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L5_CLKREQ_N_PAF0, "PEX_L5_CLKREQ_N_PAF0"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L5_RST_N_PAF1, "PEX_L5_RST_N_PAF1"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L6_CLKREQ_N_PAF2, "PEX_L6_CLKREQ_N_PAF2"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L6_RST_N_PAF3, "PEX_L6_RST_N_PAF3"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L7_CLKREQ_N_PAG0, "PEX_L7_CLKREQ_N_PAG0"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L7_RST_N_PAG1, "PEX_L7_RST_N_PAG1"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L8_CLKREQ_N_PAG2, "PEX_L8_CLKREQ_N_PAG2"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L8_RST_N_PAG3, "PEX_L8_RST_N_PAG3"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L9_CLKREQ_N_PAG4, "PEX_L9_CLKREQ_N_PAG4"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L9_RST_N_PAG5, "PEX_L9_RST_N_PAG5"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L10_CLKREQ_N_PAG6, "PEX_L10_CLKREQ_N_PAG6"),
+ PINCTRL_PIN(TEGRA_PIN_PEX_L10_RST_N_PAG7, "PEX_L10_RST_N_PAG7"),
+ PINCTRL_PIN(TEGRA_PIN_EQOS_COMP, "EQOS_COMP"),
+ PINCTRL_PIN(TEGRA_PIN_QSPI_COMP, "QSPI_COMP"),
+ PINCTRL_PIN(TEGRA_PIN_SDMMC1_COMP, "SDMMC1_COMP"),
+};
+
+static const unsigned int dap6_sclk_pa0_pins[] = {
+ TEGRA_PIN_DAP6_SCLK_PA0,
+};
+
+static const unsigned int dap6_dout_pa1_pins[] = {
+ TEGRA_PIN_DAP6_DOUT_PA1,
+};
+
+static const unsigned int dap6_din_pa2_pins[] = {
+ TEGRA_PIN_DAP6_DIN_PA2,
+};
+
+static const unsigned int dap6_fs_pa3_pins[] = {
+ TEGRA_PIN_DAP6_FS_PA3,
+};
+
+static const unsigned int dap4_sclk_pa4_pins[] = {
+ TEGRA_PIN_DAP4_SCLK_PA4,
+};
+
+static const unsigned int dap4_dout_pa5_pins[] = {
+ TEGRA_PIN_DAP4_DOUT_PA5,
+};
+
+static const unsigned int dap4_din_pa6_pins[] = {
+ TEGRA_PIN_DAP4_DIN_PA6,
+};
+
+static const unsigned int dap4_fs_pa7_pins[] = {
+ TEGRA_PIN_DAP4_FS_PA7,
+};
+
+static const unsigned int soc_gpio08_pb0_pins[] = {
+ TEGRA_PIN_SOC_GPIO08_PB0,
+};
+
+static const unsigned int qspi0_sck_pc0_pins[] = {
+ TEGRA_PIN_QSPI0_SCK_PC0,
+};
+
+static const unsigned int qspi0_cs_n_pc1_pins[] = {
+ TEGRA_PIN_QSPI0_CS_N_PC1,
+};
+
+static const unsigned int qspi0_io0_pc2_pins[] = {
+ TEGRA_PIN_QSPI0_IO0_PC2,
+};
+
+static const unsigned int qspi0_io1_pc3_pins[] = {
+ TEGRA_PIN_QSPI0_IO1_PC3,
+};
+
+static const unsigned int qspi0_io2_pc4_pins[] = {
+ TEGRA_PIN_QSPI0_IO2_PC4,
+};
+
+static const unsigned int qspi0_io3_pc5_pins[] = {
+ TEGRA_PIN_QSPI0_IO3_PC5,
+};
+
+static const unsigned int qspi1_sck_pc6_pins[] = {
+ TEGRA_PIN_QSPI1_SCK_PC6,
+};
+
+static const unsigned int qspi1_cs_n_pc7_pins[] = {
+ TEGRA_PIN_QSPI1_CS_N_PC7,
+};
+
+static const unsigned int qspi1_io0_pd0_pins[] = {
+ TEGRA_PIN_QSPI1_IO0_PD0,
+};
+
+static const unsigned int qspi1_io1_pd1_pins[] = {
+ TEGRA_PIN_QSPI1_IO1_PD1,
+};
+
+static const unsigned int qspi1_io2_pd2_pins[] = {
+ TEGRA_PIN_QSPI1_IO2_PD2,
+};
+
+static const unsigned int qspi1_io3_pd3_pins[] = {
+ TEGRA_PIN_QSPI1_IO3_PD3,
+};
+
+static const unsigned int eqos_txc_pe0_pins[] = {
+ TEGRA_PIN_EQOS_TXC_PE0,
+};
+
+static const unsigned int eqos_td0_pe1_pins[] = {
+ TEGRA_PIN_EQOS_TD0_PE1,
+};
+
+static const unsigned int eqos_td1_pe2_pins[] = {
+ TEGRA_PIN_EQOS_TD1_PE2,
+};
+
+static const unsigned int eqos_td2_pe3_pins[] = {
+ TEGRA_PIN_EQOS_TD2_PE3,
+};
+
+static const unsigned int eqos_td3_pe4_pins[] = {
+ TEGRA_PIN_EQOS_TD3_PE4,
+};
+
+static const unsigned int eqos_tx_ctl_pe5_pins[] = {
+ TEGRA_PIN_EQOS_TX_CTL_PE5,
+};
+
+static const unsigned int eqos_rd0_pe6_pins[] = {
+ TEGRA_PIN_EQOS_RD0_PE6,
+};
+
+static const unsigned int eqos_rd1_pe7_pins[] = {
+ TEGRA_PIN_EQOS_RD1_PE7,
+};
+
+static const unsigned int eqos_rd2_pf0_pins[] = {
+ TEGRA_PIN_EQOS_RD2_PF0,
+};
+
+static const unsigned int eqos_rd3_pf1_pins[] = {
+ TEGRA_PIN_EQOS_RD3_PF1,
+};
+
+static const unsigned int eqos_rx_ctl_pf2_pins[] = {
+ TEGRA_PIN_EQOS_RX_CTL_PF2,
+};
+
+static const unsigned int eqos_rxc_pf3_pins[] = {
+ TEGRA_PIN_EQOS_RXC_PF3,
+};
+
+static const unsigned int eqos_sma_mdio_pf4_pins[] = {
+ TEGRA_PIN_EQOS_SMA_MDIO_PF4,
+};
+
+static const unsigned int eqos_sma_mdc_pf5_pins[] = {
+ TEGRA_PIN_EQOS_SMA_MDC_PF5,
+};
+
+static const unsigned int soc_gpio13_pg0_pins[] = {
+ TEGRA_PIN_SOC_GPIO13_PG0,
+};
+
+static const unsigned int soc_gpio14_pg1_pins[] = {
+ TEGRA_PIN_SOC_GPIO14_PG1,
+};
+
+static const unsigned int soc_gpio15_pg2_pins[] = {
+ TEGRA_PIN_SOC_GPIO15_PG2,
+};
+
+static const unsigned int soc_gpio16_pg3_pins[] = {
+ TEGRA_PIN_SOC_GPIO16_PG3,
+};
+
+static const unsigned int soc_gpio17_pg4_pins[] = {
+ TEGRA_PIN_SOC_GPIO17_PG4,
+};
+
+static const unsigned int soc_gpio18_pg5_pins[] = {
+ TEGRA_PIN_SOC_GPIO18_PG5,
+};
+
+static const unsigned int soc_gpio19_pg6_pins[] = {
+ TEGRA_PIN_SOC_GPIO19_PG6,
+};
+
+static const unsigned int soc_gpio20_pg7_pins[] = {
+ TEGRA_PIN_SOC_GPIO20_PG7,
+};
+
+static const unsigned int soc_gpio21_ph0_pins[] = {
+ TEGRA_PIN_SOC_GPIO21_PH0,
+};
+
+static const unsigned int soc_gpio22_ph1_pins[] = {
+ TEGRA_PIN_SOC_GPIO22_PH1,
+};
+
+static const unsigned int soc_gpio06_ph2_pins[] = {
+ TEGRA_PIN_SOC_GPIO06_PH2,
+};
+
+static const unsigned int uart4_tx_ph3_pins[] = {
+ TEGRA_PIN_UART4_TX_PH3,
+};
+
+static const unsigned int uart4_rx_ph4_pins[] = {
+ TEGRA_PIN_UART4_RX_PH4,
+};
+
+static const unsigned int uart4_rts_ph5_pins[] = {
+ TEGRA_PIN_UART4_RTS_PH5,
+};
+
+static const unsigned int uart4_cts_ph6_pins[] = {
+ TEGRA_PIN_UART4_CTS_PH6,
+};
+
+static const unsigned int soc_gpio41_ph7_pins[] = {
+ TEGRA_PIN_SOC_GPIO41_PH7,
+};
+
+static const unsigned int soc_gpio42_pi0_pins[] = {
+ TEGRA_PIN_SOC_GPIO42_PI0,
+};
+
+static const unsigned int soc_gpio43_pi1_pins[] = {
+ TEGRA_PIN_SOC_GPIO43_PI1,
+};
+
+static const unsigned int soc_gpio44_pi2_pins[] = {
+ TEGRA_PIN_SOC_GPIO44_PI2,
+};
+
+static const unsigned int gen1_i2c_scl_pi3_pins[] = {
+ TEGRA_PIN_GEN1_I2C_SCL_PI3,
+};
+
+static const unsigned int gen1_i2c_sda_pi4_pins[] = {
+ TEGRA_PIN_GEN1_I2C_SDA_PI4,
+};
+
+static const unsigned int cpu_pwr_req_pi5_pins[] = {
+ TEGRA_PIN_CPU_PWR_REQ_PI5,
+};
+
+static const unsigned int soc_gpio07_pi6_pins[] = {
+ TEGRA_PIN_SOC_GPIO07_PI6,
+};
+
+static const unsigned int sdmmc1_clk_pj0_pins[] = {
+ TEGRA_PIN_SDMMC1_CLK_PJ0,
+};
+
+static const unsigned int sdmmc1_cmd_pj1_pins[] = {
+ TEGRA_PIN_SDMMC1_CMD_PJ1,
+};
+
+static const unsigned int sdmmc1_dat0_pj2_pins[] = {
+ TEGRA_PIN_SDMMC1_DAT0_PJ2,
+};
+
+static const unsigned int sdmmc1_dat1_pj3_pins[] = {
+ TEGRA_PIN_SDMMC1_DAT1_PJ3,
+};
+
+static const unsigned int sdmmc1_dat2_pj4_pins[] = {
+ TEGRA_PIN_SDMMC1_DAT2_PJ4,
+};
+
+static const unsigned int sdmmc1_dat3_pj5_pins[] = {
+ TEGRA_PIN_SDMMC1_DAT3_PJ5,
+};
+
+static const unsigned int pex_l0_clkreq_n_pk0_pins[] = {
+ TEGRA_PIN_PEX_L0_CLKREQ_N_PK0,
+};
+
+static const unsigned int pex_l0_rst_n_pk1_pins[] = {
+ TEGRA_PIN_PEX_L0_RST_N_PK1,
+};
+
+static const unsigned int pex_l1_clkreq_n_pk2_pins[] = {
+ TEGRA_PIN_PEX_L1_CLKREQ_N_PK2,
+};
+
+static const unsigned int pex_l1_rst_n_pk3_pins[] = {
+ TEGRA_PIN_PEX_L1_RST_N_PK3,
+};
+
+static const unsigned int pex_l2_clkreq_n_pk4_pins[] = {
+ TEGRA_PIN_PEX_L2_CLKREQ_N_PK4,
+};
+
+static const unsigned int pex_l2_rst_n_pk5_pins[] = {
+ TEGRA_PIN_PEX_L2_RST_N_PK5,
+};
+
+static const unsigned int pex_l3_clkreq_n_pk6_pins[] = {
+ TEGRA_PIN_PEX_L3_CLKREQ_N_PK6,
+};
+
+static const unsigned int pex_l3_rst_n_pk7_pins[] = {
+ TEGRA_PIN_PEX_L3_RST_N_PK7,
+};
+
+static const unsigned int pex_l4_clkreq_n_pl0_pins[] = {
+ TEGRA_PIN_PEX_L4_CLKREQ_N_PL0,
+};
+
+static const unsigned int pex_l4_rst_n_pl1_pins[] = {
+ TEGRA_PIN_PEX_L4_RST_N_PL1,
+};
+
+static const unsigned int pex_wake_n_pl2_pins[] = {
+ TEGRA_PIN_PEX_WAKE_N_PL2,
+};
+
+static const unsigned int soc_gpio34_pl3_pins[] = {
+ TEGRA_PIN_SOC_GPIO34_PL3,
+};
+
+static const unsigned int dp_aux_ch0_hpd_pm0_pins[] = {
+ TEGRA_PIN_DP_AUX_CH0_HPD_PM0,
+};
+
+static const unsigned int dp_aux_ch1_hpd_pm1_pins[] = {
+ TEGRA_PIN_DP_AUX_CH1_HPD_PM1,
+};
+
+static const unsigned int dp_aux_ch2_hpd_pm2_pins[] = {
+ TEGRA_PIN_DP_AUX_CH2_HPD_PM2,
+};
+
+static const unsigned int dp_aux_ch3_hpd_pm3_pins[] = {
+ TEGRA_PIN_DP_AUX_CH3_HPD_PM3,
+};
+
+static const unsigned int soc_gpio55_pm4_pins[] = {
+ TEGRA_PIN_SOC_GPIO55_PM4,
+};
+
+static const unsigned int soc_gpio36_pm5_pins[] = {
+ TEGRA_PIN_SOC_GPIO36_PM5,
+};
+
+static const unsigned int soc_gpio53_pm6_pins[] = {
+ TEGRA_PIN_SOC_GPIO53_PM6,
+};
+
+static const unsigned int soc_gpio38_pm7_pins[] = {
+ TEGRA_PIN_SOC_GPIO38_PM7,
+};
+
+static const unsigned int dp_aux_ch3_n_pn0_pins[] = {
+ TEGRA_PIN_DP_AUX_CH3_N_PN0,
+};
+
+static const unsigned int soc_gpio39_pn1_pins[] = {
+ TEGRA_PIN_SOC_GPIO39_PN1,
+};
+
+static const unsigned int soc_gpio40_pn2_pins[] = {
+ TEGRA_PIN_SOC_GPIO40_PN2,
+};
+
+static const unsigned int dp_aux_ch1_p_pn3_pins[] = {
+ TEGRA_PIN_DP_AUX_CH1_P_PN3,
+};
+
+static const unsigned int dp_aux_ch1_n_pn4_pins[] = {
+ TEGRA_PIN_DP_AUX_CH1_N_PN4,
+};
+
+static const unsigned int dp_aux_ch2_p_pn5_pins[] = {
+ TEGRA_PIN_DP_AUX_CH2_P_PN5,
+};
+
+static const unsigned int dp_aux_ch2_n_pn6_pins[] = {
+ TEGRA_PIN_DP_AUX_CH2_N_PN6,
+};
+
+static const unsigned int dp_aux_ch3_p_pn7_pins[] = {
+ TEGRA_PIN_DP_AUX_CH3_P_PN7,
+};
+
+static const unsigned int extperiph1_clk_pp0_pins[] = {
+ TEGRA_PIN_EXTPERIPH1_CLK_PP0,
+};
+
+static const unsigned int extperiph2_clk_pp1_pins[] = {
+ TEGRA_PIN_EXTPERIPH2_CLK_PP1,
+};
+
+static const unsigned int cam_i2c_scl_pp2_pins[] = {
+ TEGRA_PIN_CAM_I2C_SCL_PP2,
+};
+
+static const unsigned int cam_i2c_sda_pp3_pins[] = {
+ TEGRA_PIN_CAM_I2C_SDA_PP3,
+};
+
+static const unsigned int soc_gpio23_pp4_pins[] = {
+ TEGRA_PIN_SOC_GPIO23_PP4,
+};
+
+static const unsigned int soc_gpio24_pp5_pins[] = {
+ TEGRA_PIN_SOC_GPIO24_PP5,
+};
+
+static const unsigned int soc_gpio25_pp6_pins[] = {
+ TEGRA_PIN_SOC_GPIO25_PP6,
+};
+
+static const unsigned int pwr_i2c_scl_pp7_pins[] = {
+ TEGRA_PIN_PWR_I2C_SCL_PP7,
+};
+
+static const unsigned int pwr_i2c_sda_pq0_pins[] = {
+ TEGRA_PIN_PWR_I2C_SDA_PQ0,
+};
+
+static const unsigned int soc_gpio28_pq1_pins[] = {
+ TEGRA_PIN_SOC_GPIO28_PQ1,
+};
+
+static const unsigned int soc_gpio29_pq2_pins[] = {
+ TEGRA_PIN_SOC_GPIO29_PQ2,
+};
+
+static const unsigned int soc_gpio30_pq3_pins[] = {
+ TEGRA_PIN_SOC_GPIO30_PQ3,
+};
+
+static const unsigned int soc_gpio31_pq4_pins[] = {
+ TEGRA_PIN_SOC_GPIO31_PQ4,
+};
+
+static const unsigned int soc_gpio32_pq5_pins[] = {
+ TEGRA_PIN_SOC_GPIO32_PQ5,
+};
+
+static const unsigned int soc_gpio33_pq6_pins[] = {
+ TEGRA_PIN_SOC_GPIO33_PQ6,
+};
+
+static const unsigned int soc_gpio35_pq7_pins[] = {
+ TEGRA_PIN_SOC_GPIO35_PQ7,
+};
+
+static const unsigned int soc_gpio37_pr0_pins[] = {
+ TEGRA_PIN_SOC_GPIO37_PR0,
+};
+
+static const unsigned int soc_gpio56_pr1_pins[] = {
+ TEGRA_PIN_SOC_GPIO56_PR1,
+};
+
+static const unsigned int uart1_tx_pr2_pins[] = {
+ TEGRA_PIN_UART1_TX_PR2,
+};
+
+static const unsigned int uart1_rx_pr3_pins[] = {
+ TEGRA_PIN_UART1_RX_PR3,
+};
+
+static const unsigned int uart1_rts_pr4_pins[] = {
+ TEGRA_PIN_UART1_RTS_PR4,
+};
+
+static const unsigned int uart1_cts_pr5_pins[] = {
+ TEGRA_PIN_UART1_CTS_PR5,
+};
+
+static const unsigned int gpu_pwr_req_px0_pins[] = {
+ TEGRA_PIN_GPU_PWR_REQ_PX0,
+};
+
+static const unsigned int cv_pwr_req_px1_pins[] = {
+ TEGRA_PIN_CV_PWR_REQ_PX1,
+};
+
+static const unsigned int gp_pwm2_px2_pins[] = {
+ TEGRA_PIN_GP_PWM2_PX2,
+};
+
+static const unsigned int gp_pwm3_px3_pins[] = {
+ TEGRA_PIN_GP_PWM3_PX3,
+};
+
+static const unsigned int uart2_tx_px4_pins[] = {
+ TEGRA_PIN_UART2_TX_PX4,
+};
+
+static const unsigned int uart2_rx_px5_pins[] = {
+ TEGRA_PIN_UART2_RX_PX5,
+};
+
+static const unsigned int uart2_rts_px6_pins[] = {
+ TEGRA_PIN_UART2_RTS_PX6,
+};
+
+static const unsigned int uart2_cts_px7_pins[] = {
+ TEGRA_PIN_UART2_CTS_PX7,
+};
+
+static const unsigned int spi3_sck_py0_pins[] = {
+ TEGRA_PIN_SPI3_SCK_PY0,
+};
+
+static const unsigned int spi3_miso_py1_pins[] = {
+ TEGRA_PIN_SPI3_MISO_PY1,
+};
+
+static const unsigned int spi3_mosi_py2_pins[] = {
+ TEGRA_PIN_SPI3_MOSI_PY2,
+};
+
+static const unsigned int spi3_cs0_py3_pins[] = {
+ TEGRA_PIN_SPI3_CS0_PY3,
+};
+
+static const unsigned int spi3_cs1_py4_pins[] = {
+ TEGRA_PIN_SPI3_CS1_PY4,
+};
+
+static const unsigned int uart5_tx_py5_pins[] = {
+ TEGRA_PIN_UART5_TX_PY5,
+};
+
+static const unsigned int uart5_rx_py6_pins[] = {
+ TEGRA_PIN_UART5_RX_PY6,
+};
+
+static const unsigned int uart5_rts_py7_pins[] = {
+ TEGRA_PIN_UART5_RTS_PY7,
+};
+
+static const unsigned int uart5_cts_pz0_pins[] = {
+ TEGRA_PIN_UART5_CTS_PZ0,
+};
+
+static const unsigned int usb_vbus_en0_pz1_pins[] = {
+ TEGRA_PIN_USB_VBUS_EN0_PZ1,
+};
+
+static const unsigned int usb_vbus_en1_pz2_pins[] = {
+ TEGRA_PIN_USB_VBUS_EN1_PZ2,
+};
+
+static const unsigned int spi1_sck_pz3_pins[] = {
+ TEGRA_PIN_SPI1_SCK_PZ3,
+};
+
+static const unsigned int spi1_miso_pz4_pins[] = {
+ TEGRA_PIN_SPI1_MISO_PZ4,
+};
+
+static const unsigned int spi1_mosi_pz5_pins[] = {
+ TEGRA_PIN_SPI1_MOSI_PZ5,
+};
+
+static const unsigned int spi1_cs0_pz6_pins[] = {
+ TEGRA_PIN_SPI1_CS0_PZ6,
+};
+
+static const unsigned int spi1_cs1_pz7_pins[] = {
+ TEGRA_PIN_SPI1_CS1_PZ7,
+};
+
+static const unsigned int can0_dout_paa0_pins[] = {
+ TEGRA_PIN_CAN0_DOUT_PAA0,
+};
+
+static const unsigned int can0_din_paa1_pins[] = {
+ TEGRA_PIN_CAN0_DIN_PAA1,
+};
+
+static const unsigned int can1_dout_paa2_pins[] = {
+ TEGRA_PIN_CAN1_DOUT_PAA2,
+};
+
+static const unsigned int can1_din_paa3_pins[] = {
+ TEGRA_PIN_CAN1_DIN_PAA3,
+};
+
+static const unsigned int can0_stb_paa4_pins[] = {
+ TEGRA_PIN_CAN0_STB_PAA4,
+};
+
+static const unsigned int can0_en_paa5_pins[] = {
+ TEGRA_PIN_CAN0_EN_PAA5,
+};
+
+static const unsigned int soc_gpio49_paa6_pins[] = {
+ TEGRA_PIN_SOC_GPIO49_PAA6,
+};
+
+static const unsigned int can0_err_paa7_pins[] = {
+ TEGRA_PIN_CAN0_ERR_PAA7,
+};
+
+static const unsigned int spi5_sck_pac0_pins[] = {
+ TEGRA_PIN_SPI5_SCK_PAC0,
+};
+
+static const unsigned int spi5_miso_pac1_pins[] = {
+ TEGRA_PIN_SPI5_MISO_PAC1,
+};
+
+static const unsigned int spi5_mosi_pac2_pins[] = {
+ TEGRA_PIN_SPI5_MOSI_PAC2,
+};
+
+static const unsigned int spi5_cs0_pac3_pins[] = {
+ TEGRA_PIN_SPI5_CS0_PAC3,
+};
+
+static const unsigned int soc_gpio57_pac4_pins[] = {
+ TEGRA_PIN_SOC_GPIO57_PAC4,
+};
+
+static const unsigned int soc_gpio58_pac5_pins[] = {
+ TEGRA_PIN_SOC_GPIO58_PAC5,
+};
+
+static const unsigned int soc_gpio59_pac6_pins[] = {
+ TEGRA_PIN_SOC_GPIO59_PAC6,
+};
+
+static const unsigned int soc_gpio60_pac7_pins[] = {
+ TEGRA_PIN_SOC_GPIO60_PAC7,
+};
+
+static const unsigned int soc_gpio45_pad0_pins[] = {
+ TEGRA_PIN_SOC_GPIO45_PAD0,
+};
+
+static const unsigned int soc_gpio46_pad1_pins[] = {
+ TEGRA_PIN_SOC_GPIO46_PAD1,
+};
+
+static const unsigned int soc_gpio47_pad2_pins[] = {
+ TEGRA_PIN_SOC_GPIO47_PAD2,
+};
+
+static const unsigned int soc_gpio48_pad3_pins[] = {
+ TEGRA_PIN_SOC_GPIO48_PAD3,
+};
+
+static const unsigned int ufs0_ref_clk_pae0_pins[] = {
+ TEGRA_PIN_UFS0_REF_CLK_PAE0,
+};
+
+static const unsigned int ufs0_rst_n_pae1_pins[] = {
+ TEGRA_PIN_UFS0_RST_N_PAE1,
+};
+
+static const unsigned int pex_l5_clkreq_n_paf0_pins[] = {
+ TEGRA_PIN_PEX_L5_CLKREQ_N_PAF0,
+};
+
+static const unsigned int pex_l5_rst_n_paf1_pins[] = {
+ TEGRA_PIN_PEX_L5_RST_N_PAF1,
+};
+
+static const unsigned int pex_l6_clkreq_n_paf2_pins[] = {
+ TEGRA_PIN_PEX_L6_CLKREQ_N_PAF2,
+};
+
+static const unsigned int pex_l6_rst_n_paf3_pins[] = {
+ TEGRA_PIN_PEX_L6_RST_N_PAF3,
+};
+
+static const unsigned int pex_l7_clkreq_n_pag0_pins[] = {
+ TEGRA_PIN_PEX_L7_CLKREQ_N_PAG0,
+};
+
+static const unsigned int pex_l7_rst_n_pag1_pins[] = {
+ TEGRA_PIN_PEX_L7_RST_N_PAG1,
+};
+
+static const unsigned int pex_l8_clkreq_n_pag2_pins[] = {
+ TEGRA_PIN_PEX_L8_CLKREQ_N_PAG2,
+};
+
+static const unsigned int pex_l8_rst_n_pag3_pins[] = {
+ TEGRA_PIN_PEX_L8_RST_N_PAG3,
+};
+
+static const unsigned int pex_l9_clkreq_n_pag4_pins[] = {
+ TEGRA_PIN_PEX_L9_CLKREQ_N_PAG4,
+};
+
+static const unsigned int pex_l9_rst_n_pag5_pins[] = {
+ TEGRA_PIN_PEX_L9_RST_N_PAG5,
+};
+
+static const unsigned int pex_l10_clkreq_n_pag6_pins[] = {
+ TEGRA_PIN_PEX_L10_CLKREQ_N_PAG6,
+};
+
+static const unsigned int pex_l10_rst_n_pag7_pins[] = {
+ TEGRA_PIN_PEX_L10_RST_N_PAG7,
+};
+
+static const unsigned int can1_stb_pbb0_pins[] = {
+ TEGRA_PIN_CAN1_STB_PBB0,
+};
+
+static const unsigned int can1_en_pbb1_pins[] = {
+ TEGRA_PIN_CAN1_EN_PBB1,
+};
+
+static const unsigned int soc_gpio50_pbb2_pins[] = {
+ TEGRA_PIN_SOC_GPIO50_PBB2,
+};
+
+static const unsigned int can1_err_pbb3_pins[] = {
+ TEGRA_PIN_CAN1_ERR_PBB3,
+};
+
+static const unsigned int spi2_sck_pcc0_pins[] = {
+ TEGRA_PIN_SPI2_SCK_PCC0,
+};
+
+static const unsigned int spi2_miso_pcc1_pins[] = {
+ TEGRA_PIN_SPI2_MISO_PCC1,
+};
+
+static const unsigned int spi2_mosi_pcc2_pins[] = {
+ TEGRA_PIN_SPI2_MOSI_PCC2,
+};
+
+static const unsigned int spi2_cs0_pcc3_pins[] = {
+ TEGRA_PIN_SPI2_CS0_PCC3,
+};
+
+static const unsigned int touch_clk_pcc4_pins[] = {
+ TEGRA_PIN_TOUCH_CLK_PCC4,
+};
+
+static const unsigned int uart3_tx_pcc5_pins[] = {
+ TEGRA_PIN_UART3_TX_PCC5,
+};
+
+static const unsigned int uart3_rx_pcc6_pins[] = {
+ TEGRA_PIN_UART3_RX_PCC6,
+};
+
+static const unsigned int gen2_i2c_scl_pcc7_pins[] = {
+ TEGRA_PIN_GEN2_I2C_SCL_PCC7,
+};
+
+static const unsigned int gen2_i2c_sda_pdd0_pins[] = {
+ TEGRA_PIN_GEN2_I2C_SDA_PDD0,
+};
+
+static const unsigned int gen8_i2c_scl_pdd1_pins[] = {
+ TEGRA_PIN_GEN8_I2C_SCL_PDD1,
+};
+
+static const unsigned int gen8_i2c_sda_pdd2_pins[] = {
+ TEGRA_PIN_GEN8_I2C_SDA_PDD2,
+};
+
+static const unsigned int sce_error_pee0_pins[] = {
+ TEGRA_PIN_SCE_ERROR_PEE0,
+};
+
+static const unsigned int vcomp_alert_pee1_pins[] = {
+ TEGRA_PIN_VCOMP_ALERT_PEE1,
+};
+
+static const unsigned int ao_retention_n_pee2_pins[] = {
+ TEGRA_PIN_AO_RETENTION_N_PEE2,
+};
+
+static const unsigned int batt_oc_pee3_pins[] = {
+ TEGRA_PIN_BATT_OC_PEE3,
+};
+
+static const unsigned int power_on_pee4_pins[] = {
+ TEGRA_PIN_POWER_ON_PEE4,
+};
+
+static const unsigned int soc_gpio26_pee5_pins[] = {
+ TEGRA_PIN_SOC_GPIO26_PEE5,
+};
+
+static const unsigned int soc_gpio27_pee6_pins[] = {
+ TEGRA_PIN_SOC_GPIO27_PEE6,
+};
+
+static const unsigned int bootv_ctl_n_pee7_pins[] = {
+ TEGRA_PIN_BOOTV_CTL_N_PEE7,
+};
+
+static const unsigned int hdmi_cec_pgg0_pins[] = {
+ TEGRA_PIN_HDMI_CEC_PGG0,
+};
+
+static const unsigned int eqos_comp_pins[] = {
+ TEGRA_PIN_EQOS_COMP,
+};
+
+static const unsigned int qspi_comp_pins[] = {
+ TEGRA_PIN_QSPI_COMP,
+};
+
+static const unsigned int sdmmc1_comp_pins[] = {
+ TEGRA_PIN_SDMMC1_COMP,
+};
+
+/* Define unique ID for each function */
+enum tegra_mux_dt {
+ TEGRA_MUX_GP,
+ TEGRA_MUX_UARTC,
+ TEGRA_MUX_I2C8,
+ TEGRA_MUX_SPI2,
+ TEGRA_MUX_I2C2,
+ TEGRA_MUX_CAN1,
+ TEGRA_MUX_CAN0,
+ TEGRA_MUX_RSVD0,
+ TEGRA_MUX_ETH0,
+ TEGRA_MUX_ETH2,
+ TEGRA_MUX_ETH1,
+ TEGRA_MUX_DP,
+ TEGRA_MUX_ETH3,
+ TEGRA_MUX_I2C4,
+ TEGRA_MUX_I2C7,
+ TEGRA_MUX_I2C9,
+ TEGRA_MUX_EQOS,
+ TEGRA_MUX_PE2,
+ TEGRA_MUX_PE1,
+ TEGRA_MUX_PE0,
+ TEGRA_MUX_PE3,
+ TEGRA_MUX_PE4,
+ TEGRA_MUX_PE5,
+ TEGRA_MUX_PE6,
+ TEGRA_MUX_PE10,
+ TEGRA_MUX_PE7,
+ TEGRA_MUX_PE8,
+ TEGRA_MUX_PE9,
+ TEGRA_MUX_QSPI0,
+ TEGRA_MUX_QSPI1,
+ TEGRA_MUX_QSPI,
+ TEGRA_MUX_SDMMC1,
+ TEGRA_MUX_SCE,
+ TEGRA_MUX_SOC,
+ TEGRA_MUX_GPIO,
+ TEGRA_MUX_HDMI,
+ TEGRA_MUX_UFS0,
+ TEGRA_MUX_SPI3,
+ TEGRA_MUX_SPI1,
+ TEGRA_MUX_UARTB,
+ TEGRA_MUX_UARTE,
+ TEGRA_MUX_USB,
+ TEGRA_MUX_EXTPERIPH2,
+ TEGRA_MUX_EXTPERIPH1,
+ TEGRA_MUX_I2C3,
+ TEGRA_MUX_VI0,
+ TEGRA_MUX_I2C5,
+ TEGRA_MUX_UARTA,
+ TEGRA_MUX_UARTD,
+ TEGRA_MUX_I2C1,
+ TEGRA_MUX_I2S4,
+ TEGRA_MUX_I2S6,
+ TEGRA_MUX_AUD,
+ TEGRA_MUX_SPI5,
+ TEGRA_MUX_TOUCH,
+ TEGRA_MUX_UARTJ,
+ TEGRA_MUX_RSVD1,
+ TEGRA_MUX_WDT,
+ TEGRA_MUX_TSC,
+ TEGRA_MUX_DMIC3,
+ TEGRA_MUX_LED,
+ TEGRA_MUX_VI0_ALT,
+ TEGRA_MUX_I2S5,
+ TEGRA_MUX_NV,
+ TEGRA_MUX_EXTPERIPH3,
+ TEGRA_MUX_EXTPERIPH4,
+ TEGRA_MUX_SPI4,
+ TEGRA_MUX_CCLA,
+ TEGRA_MUX_I2S2,
+ TEGRA_MUX_I2S1,
+ TEGRA_MUX_I2S8,
+ TEGRA_MUX_I2S3,
+ TEGRA_MUX_RSVD2,
+ TEGRA_MUX_DMIC5,
+ TEGRA_MUX_DCA,
+ TEGRA_MUX_DISPLAYB,
+ TEGRA_MUX_DISPLAYA,
+ TEGRA_MUX_VI1,
+ TEGRA_MUX_DCB,
+ TEGRA_MUX_DMIC1,
+ TEGRA_MUX_DMIC4,
+ TEGRA_MUX_I2S7,
+ TEGRA_MUX_DMIC2,
+ TEGRA_MUX_DSPK0,
+ TEGRA_MUX_RSVD3,
+ TEGRA_MUX_TSC_ALT,
+ TEGRA_MUX_ISTCTRL,
+ TEGRA_MUX_VI1_ALT,
+ TEGRA_MUX_DSPK1,
+ TEGRA_MUX_IGPU,
+};
+
+/* Make list of each function name */
+#define TEGRA_PIN_FUNCTION(lid) #lid
+
+static const char * const tegra234_functions[] = {
+ TEGRA_PIN_FUNCTION(gp),
+ TEGRA_PIN_FUNCTION(uartc),
+ TEGRA_PIN_FUNCTION(i2c8),
+ TEGRA_PIN_FUNCTION(spi2),
+ TEGRA_PIN_FUNCTION(i2c2),
+ TEGRA_PIN_FUNCTION(can1),
+ TEGRA_PIN_FUNCTION(can0),
+ TEGRA_PIN_FUNCTION(rsvd0),
+ TEGRA_PIN_FUNCTION(eth0),
+ TEGRA_PIN_FUNCTION(eth2),
+ TEGRA_PIN_FUNCTION(eth1),
+ TEGRA_PIN_FUNCTION(dp),
+ TEGRA_PIN_FUNCTION(eth3),
+ TEGRA_PIN_FUNCTION(i2c4),
+ TEGRA_PIN_FUNCTION(i2c7),
+ TEGRA_PIN_FUNCTION(i2c9),
+ TEGRA_PIN_FUNCTION(eqos),
+ TEGRA_PIN_FUNCTION(pe2),
+ TEGRA_PIN_FUNCTION(pe1),
+ TEGRA_PIN_FUNCTION(pe0),
+ TEGRA_PIN_FUNCTION(pe3),
+ TEGRA_PIN_FUNCTION(pe4),
+ TEGRA_PIN_FUNCTION(pe5),
+ TEGRA_PIN_FUNCTION(pe6),
+ TEGRA_PIN_FUNCTION(pe10),
+ TEGRA_PIN_FUNCTION(pe7),
+ TEGRA_PIN_FUNCTION(pe8),
+ TEGRA_PIN_FUNCTION(pe9),
+ TEGRA_PIN_FUNCTION(qspi0),
+ TEGRA_PIN_FUNCTION(qspi1),
+ TEGRA_PIN_FUNCTION(qspi),
+ TEGRA_PIN_FUNCTION(sdmmc1),
+ TEGRA_PIN_FUNCTION(sce),
+ TEGRA_PIN_FUNCTION(soc),
+ TEGRA_PIN_FUNCTION(gpio),
+ TEGRA_PIN_FUNCTION(hdmi),
+ TEGRA_PIN_FUNCTION(ufs0),
+ TEGRA_PIN_FUNCTION(spi3),
+ TEGRA_PIN_FUNCTION(spi1),
+ TEGRA_PIN_FUNCTION(uartb),
+ TEGRA_PIN_FUNCTION(uarte),
+ TEGRA_PIN_FUNCTION(usb),
+ TEGRA_PIN_FUNCTION(extperiph2),
+ TEGRA_PIN_FUNCTION(extperiph1),
+ TEGRA_PIN_FUNCTION(i2c3),
+ TEGRA_PIN_FUNCTION(vi0),
+ TEGRA_PIN_FUNCTION(i2c5),
+ TEGRA_PIN_FUNCTION(uarta),
+ TEGRA_PIN_FUNCTION(uartd),
+ TEGRA_PIN_FUNCTION(i2c1),
+ TEGRA_PIN_FUNCTION(i2s4),
+ TEGRA_PIN_FUNCTION(i2s6),
+ TEGRA_PIN_FUNCTION(aud),
+ TEGRA_PIN_FUNCTION(spi5),
+ TEGRA_PIN_FUNCTION(touch),
+ TEGRA_PIN_FUNCTION(uartj),
+ TEGRA_PIN_FUNCTION(rsvd1),
+ TEGRA_PIN_FUNCTION(wdt),
+ TEGRA_PIN_FUNCTION(tsc),
+ TEGRA_PIN_FUNCTION(dmic3),
+ TEGRA_PIN_FUNCTION(led),
+ TEGRA_PIN_FUNCTION(vi0_alt),
+ TEGRA_PIN_FUNCTION(i2s5),
+ TEGRA_PIN_FUNCTION(nv),
+ TEGRA_PIN_FUNCTION(extperiph3),
+ TEGRA_PIN_FUNCTION(extperiph4),
+ TEGRA_PIN_FUNCTION(spi4),
+ TEGRA_PIN_FUNCTION(ccla),
+ TEGRA_PIN_FUNCTION(i2s2),
+ TEGRA_PIN_FUNCTION(i2s1),
+ TEGRA_PIN_FUNCTION(i2s8),
+ TEGRA_PIN_FUNCTION(i2s3),
+ TEGRA_PIN_FUNCTION(rsvd2),
+ TEGRA_PIN_FUNCTION(dmic5),
+ TEGRA_PIN_FUNCTION(dca),
+ TEGRA_PIN_FUNCTION(displayb),
+ TEGRA_PIN_FUNCTION(displaya),
+ TEGRA_PIN_FUNCTION(vi1),
+ TEGRA_PIN_FUNCTION(dcb),
+ TEGRA_PIN_FUNCTION(dmic1),
+ TEGRA_PIN_FUNCTION(dmic4),
+ TEGRA_PIN_FUNCTION(i2s7),
+ TEGRA_PIN_FUNCTION(dmic2),
+ TEGRA_PIN_FUNCTION(dspk0),
+ TEGRA_PIN_FUNCTION(rsvd3),
+ TEGRA_PIN_FUNCTION(tsc_alt),
+ TEGRA_PIN_FUNCTION(istctrl),
+ TEGRA_PIN_FUNCTION(vi1_alt),
+ TEGRA_PIN_FUNCTION(dspk1),
+ TEGRA_PIN_FUNCTION(igpu),
+};
+
+#define PINGROUP_REG_Y(r) ((r))
+#define PINGROUP_REG_N(r) -1
+
+#define DRV_PINGROUP_Y(r) ((r))
+#define DRV_PINGROUP_N(r) -1
+
+#define DRV_PINGROUP_ENTRY_N(pg_name) \
+ .drv_reg = -1, \
+ .drv_bank = -1, \
+ .drvdn_bit = -1, \
+ .drvup_bit = -1, \
+ .slwr_bit = -1, \
+ .slwf_bit = -1
+
+#define DRV_PINGROUP_ENTRY_Y(r, drvdn_b, drvdn_w, drvup_b, \
+ drvup_w, slwr_b, slwr_w, slwf_b, \
+ slwf_w, bank) \
+ .drv_reg = DRV_PINGROUP_Y(r), \
+ .drv_bank = bank, \
+ .drvdn_bit = drvdn_b, \
+ .drvdn_width = drvdn_w, \
+ .drvup_bit = drvup_b, \
+ .drvup_width = drvup_w, \
+ .slwr_bit = slwr_b, \
+ .slwr_width = slwr_w, \
+ .slwf_bit = slwf_b, \
+ .slwf_width = slwf_w
+
+#define PIN_PINGROUP_ENTRY_N(pg_name) \
+ .mux_reg = -1, \
+ .pupd_reg = -1, \
+ .tri_reg = -1, \
+ .einput_bit = -1, \
+ .e_io_hv_bit = -1, \
+ .odrain_bit = -1, \
+ .lock_bit = -1, \
+ .parked_bit = -1, \
+ .lpmd_bit = -1, \
+ .drvtype_bit = -1, \
+ .lpdr_bit = -1, \
+ .pbias_buf_bit = -1, \
+ .preemp_bit = -1, \
+ .rfu_in_bit = -1
+
+#define PIN_PINGROUP_ENTRY_Y(r, bank, pupd, e_io_hv, e_lpbk, e_input, \
+ e_lpdr, e_pbias_buf, gpio_sfio_sel, \
+ schmitt_b) \
+ .mux_reg = PINGROUP_REG_Y(r), \
+ .lpmd_bit = -1, \
+ .lock_bit = -1, \
+ .hsm_bit = -1, \
+ .mux_bank = bank, \
+ .mux_bit = 0, \
+ .pupd_reg = PINGROUP_REG_##pupd(r), \
+ .pupd_bank = bank, \
+ .pupd_bit = 2, \
+ .tri_reg = PINGROUP_REG_Y(r), \
+ .tri_bank = bank, \
+ .tri_bit = 4, \
+ .einput_bit = e_input, \
+ .sfsel_bit = gpio_sfio_sel, \
+ .schmitt_bit = schmitt_b, \
+ .drvtype_bit = 13, \
+ .lpdr_bit = e_lpdr, \
+
+/* main drive pin groups */
+#define drive_soc_gpio08_pb0 DRV_PINGROUP_ENTRY_Y(0x500c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio36_pm5 DRV_PINGROUP_ENTRY_Y(0x10004, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio53_pm6 DRV_PINGROUP_ENTRY_Y(0x1000c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio55_pm4 DRV_PINGROUP_ENTRY_Y(0x10014, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio38_pm7 DRV_PINGROUP_ENTRY_Y(0x1001c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio39_pn1 DRV_PINGROUP_ENTRY_Y(0x10024, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio40_pn2 DRV_PINGROUP_ENTRY_Y(0x1002c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch0_hpd_pm0 DRV_PINGROUP_ENTRY_Y(0x10034, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch1_hpd_pm1 DRV_PINGROUP_ENTRY_Y(0x1003c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch2_hpd_pm2 DRV_PINGROUP_ENTRY_Y(0x10044, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch3_hpd_pm3 DRV_PINGROUP_ENTRY_Y(0x1004c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch1_p_pn3 DRV_PINGROUP_ENTRY_Y(0x10054, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch1_n_pn4 DRV_PINGROUP_ENTRY_Y(0x1005c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch2_p_pn5 DRV_PINGROUP_ENTRY_Y(0x10064, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch2_n_pn6 DRV_PINGROUP_ENTRY_Y(0x1006c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch3_p_pn7 DRV_PINGROUP_ENTRY_Y(0x10074, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch3_n_pn0 DRV_PINGROUP_ENTRY_Y(0x1007c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l2_clkreq_n_pk4 DRV_PINGROUP_ENTRY_Y(0x7004, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_wake_n_pl2 DRV_PINGROUP_ENTRY_Y(0x700c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l1_clkreq_n_pk2 DRV_PINGROUP_ENTRY_Y(0x7014, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l1_rst_n_pk3 DRV_PINGROUP_ENTRY_Y(0x701c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l0_clkreq_n_pk0 DRV_PINGROUP_ENTRY_Y(0x7024, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l0_rst_n_pk1 DRV_PINGROUP_ENTRY_Y(0x702c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l2_rst_n_pk5 DRV_PINGROUP_ENTRY_Y(0x7034, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l3_clkreq_n_pk6 DRV_PINGROUP_ENTRY_Y(0x703c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l3_rst_n_pk7 DRV_PINGROUP_ENTRY_Y(0x7044, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l4_clkreq_n_pl0 DRV_PINGROUP_ENTRY_Y(0x704c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l4_rst_n_pl1 DRV_PINGROUP_ENTRY_Y(0x7054, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio34_pl3 DRV_PINGROUP_ENTRY_Y(0x705c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l5_clkreq_n_paf0 DRV_PINGROUP_ENTRY_Y(0x14004, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l5_rst_n_paf1 DRV_PINGROUP_ENTRY_Y(0x1400c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l6_clkreq_n_paf2 DRV_PINGROUP_ENTRY_Y(0x14014, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l6_rst_n_paf3 DRV_PINGROUP_ENTRY_Y(0x1401c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l10_clkreq_n_pag6 DRV_PINGROUP_ENTRY_Y(0x19004, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l10_rst_n_pag7 DRV_PINGROUP_ENTRY_Y(0x1900c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l7_clkreq_n_pag0 DRV_PINGROUP_ENTRY_Y(0x19014, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l7_rst_n_pag1 DRV_PINGROUP_ENTRY_Y(0x1901c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l8_clkreq_n_pag2 DRV_PINGROUP_ENTRY_Y(0x19024, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l8_rst_n_pag3 DRV_PINGROUP_ENTRY_Y(0x1902c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l9_clkreq_n_pag4 DRV_PINGROUP_ENTRY_Y(0x19034, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pex_l9_rst_n_pag5 DRV_PINGROUP_ENTRY_Y(0x1903c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_sdmmc1_clk_pj0 DRV_PINGROUP_ENTRY_Y(0x8004, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_sdmmc1_cmd_pj1 DRV_PINGROUP_ENTRY_Y(0x800c, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_sdmmc1_dat3_pj5 DRV_PINGROUP_ENTRY_Y(0x801c, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_sdmmc1_dat2_pj4 DRV_PINGROUP_ENTRY_Y(0x8024, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_sdmmc1_dat1_pj3 DRV_PINGROUP_ENTRY_Y(0x802c, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_sdmmc1_dat0_pj2 DRV_PINGROUP_ENTRY_Y(0x8034, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_ufs0_rst_n_pae1 DRV_PINGROUP_ENTRY_Y(0x11004, 12, 5, 24, 5, -1, -1, -1, -1, 0)
+#define drive_ufs0_ref_clk_pae0 DRV_PINGROUP_ENTRY_Y(0x1100c, 12, 5, 24, 5, -1, -1, -1, -1, 0)
+#define drive_spi3_miso_py1 DRV_PINGROUP_ENTRY_Y(0xd004, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi1_cs0_pz6 DRV_PINGROUP_ENTRY_Y(0xd00c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi3_cs0_py3 DRV_PINGROUP_ENTRY_Y(0xd014, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi1_miso_pz4 DRV_PINGROUP_ENTRY_Y(0xd01c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi3_cs1_py4 DRV_PINGROUP_ENTRY_Y(0xd024, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi1_sck_pz3 DRV_PINGROUP_ENTRY_Y(0xd02c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi3_sck_py0 DRV_PINGROUP_ENTRY_Y(0xd034, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi1_cs1_pz7 DRV_PINGROUP_ENTRY_Y(0xd03c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi1_mosi_pz5 DRV_PINGROUP_ENTRY_Y(0xd044, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi3_mosi_py2 DRV_PINGROUP_ENTRY_Y(0xd04c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart2_tx_px4 DRV_PINGROUP_ENTRY_Y(0xd054, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart2_rx_px5 DRV_PINGROUP_ENTRY_Y(0xd05c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart2_rts_px6 DRV_PINGROUP_ENTRY_Y(0xd064, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart2_cts_px7 DRV_PINGROUP_ENTRY_Y(0xd06c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart5_tx_py5 DRV_PINGROUP_ENTRY_Y(0xd074, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart5_rx_py6 DRV_PINGROUP_ENTRY_Y(0xd07c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart5_rts_py7 DRV_PINGROUP_ENTRY_Y(0xd084, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart5_cts_pz0 DRV_PINGROUP_ENTRY_Y(0xd08c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_gpu_pwr_req_px0 DRV_PINGROUP_ENTRY_Y(0xd094, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_gp_pwm3_px3 DRV_PINGROUP_ENTRY_Y(0xd09c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_gp_pwm2_px2 DRV_PINGROUP_ENTRY_Y(0xd0a4, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_cv_pwr_req_px1 DRV_PINGROUP_ENTRY_Y(0xd0ac, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_usb_vbus_en0_pz1 DRV_PINGROUP_ENTRY_Y(0xd0b4, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_usb_vbus_en1_pz2 DRV_PINGROUP_ENTRY_Y(0xd0bc, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_extperiph2_clk_pp1 DRV_PINGROUP_ENTRY_Y(0x0004, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_extperiph1_clk_pp0 DRV_PINGROUP_ENTRY_Y(0x000c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_cam_i2c_sda_pp3 DRV_PINGROUP_ENTRY_Y(0x0014, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_cam_i2c_scl_pp2 DRV_PINGROUP_ENTRY_Y(0x001c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio23_pp4 DRV_PINGROUP_ENTRY_Y(0x0024, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio24_pp5 DRV_PINGROUP_ENTRY_Y(0x002c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio25_pp6 DRV_PINGROUP_ENTRY_Y(0x0034, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pwr_i2c_scl_pp7 DRV_PINGROUP_ENTRY_Y(0x003c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_pwr_i2c_sda_pq0 DRV_PINGROUP_ENTRY_Y(0x0044, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio28_pq1 DRV_PINGROUP_ENTRY_Y(0x004c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio29_pq2 DRV_PINGROUP_ENTRY_Y(0x0054, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio30_pq3 DRV_PINGROUP_ENTRY_Y(0x005c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio31_pq4 DRV_PINGROUP_ENTRY_Y(0x0064, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio32_pq5 DRV_PINGROUP_ENTRY_Y(0x006c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio33_pq6 DRV_PINGROUP_ENTRY_Y(0x0074, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio35_pq7 DRV_PINGROUP_ENTRY_Y(0x007c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio37_pr0 DRV_PINGROUP_ENTRY_Y(0x0084, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio56_pr1 DRV_PINGROUP_ENTRY_Y(0x008c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart1_cts_pr5 DRV_PINGROUP_ENTRY_Y(0x0094, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart1_rts_pr4 DRV_PINGROUP_ENTRY_Y(0x009c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart1_rx_pr3 DRV_PINGROUP_ENTRY_Y(0x00a4, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart1_tx_pr2 DRV_PINGROUP_ENTRY_Y(0x00ac, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_cpu_pwr_req_pi5 DRV_PINGROUP_ENTRY_Y(0x4004, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart4_cts_ph6 DRV_PINGROUP_ENTRY_Y(0x400c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart4_rts_ph5 DRV_PINGROUP_ENTRY_Y(0x4014, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart4_rx_ph4 DRV_PINGROUP_ENTRY_Y(0x401c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart4_tx_ph3 DRV_PINGROUP_ENTRY_Y(0x4024, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_gen1_i2c_scl_pi3 DRV_PINGROUP_ENTRY_Y(0x402c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_gen1_i2c_sda_pi4 DRV_PINGROUP_ENTRY_Y(0x4034, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio20_pg7 DRV_PINGROUP_ENTRY_Y(0x403c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio21_ph0 DRV_PINGROUP_ENTRY_Y(0x4044, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio22_ph1 DRV_PINGROUP_ENTRY_Y(0x404c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio13_pg0 DRV_PINGROUP_ENTRY_Y(0x4054, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio14_pg1 DRV_PINGROUP_ENTRY_Y(0x405c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio15_pg2 DRV_PINGROUP_ENTRY_Y(0x4064, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio16_pg3 DRV_PINGROUP_ENTRY_Y(0x406c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio17_pg4 DRV_PINGROUP_ENTRY_Y(0x4074, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio18_pg5 DRV_PINGROUP_ENTRY_Y(0x407c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio19_pg6 DRV_PINGROUP_ENTRY_Y(0x4084, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio41_ph7 DRV_PINGROUP_ENTRY_Y(0x408c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio42_pi0 DRV_PINGROUP_ENTRY_Y(0x4094, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio43_pi1 DRV_PINGROUP_ENTRY_Y(0x409c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio44_pi2 DRV_PINGROUP_ENTRY_Y(0x40a4, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio06_ph2 DRV_PINGROUP_ENTRY_Y(0x40ac, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio07_pi6 DRV_PINGROUP_ENTRY_Y(0x40b4, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dap4_sclk_pa4 DRV_PINGROUP_ENTRY_Y(0x2004, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dap4_dout_pa5 DRV_PINGROUP_ENTRY_Y(0x200c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dap4_din_pa6 DRV_PINGROUP_ENTRY_Y(0x2014, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dap4_fs_pa7 DRV_PINGROUP_ENTRY_Y(0x201c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dap6_sclk_pa0 DRV_PINGROUP_ENTRY_Y(0x2024, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dap6_dout_pa1 DRV_PINGROUP_ENTRY_Y(0x202c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dap6_din_pa2 DRV_PINGROUP_ENTRY_Y(0x2034, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_dap6_fs_pa3 DRV_PINGROUP_ENTRY_Y(0x203c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio45_pad0 DRV_PINGROUP_ENTRY_Y(0x18004, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio46_pad1 DRV_PINGROUP_ENTRY_Y(0x1800c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio47_pad2 DRV_PINGROUP_ENTRY_Y(0x18014, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio48_pad3 DRV_PINGROUP_ENTRY_Y(0x1801c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio57_pac4 DRV_PINGROUP_ENTRY_Y(0x18024, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio58_pac5 DRV_PINGROUP_ENTRY_Y(0x1802c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio59_pac6 DRV_PINGROUP_ENTRY_Y(0x18034, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio60_pac7 DRV_PINGROUP_ENTRY_Y(0x1803c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi5_cs0_pac3 DRV_PINGROUP_ENTRY_Y(0x18044, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi5_miso_pac1 DRV_PINGROUP_ENTRY_Y(0x1804c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi5_mosi_pac2 DRV_PINGROUP_ENTRY_Y(0x18054, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi5_sck_pac0 DRV_PINGROUP_ENTRY_Y(0x1805c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_eqos_td3_pe4 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_td2_pe3 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_td1_pe2 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_td0_pe1 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_rd3_pf1 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_rd2_pf0 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_rd1_pe7 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_sma_mdio_pf4 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_rd0_pe6 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_sma_mdc_pf5 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_comp DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_txc_pe0 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_rxc_pf3 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_tx_ctl_pe5 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_eqos_rx_ctl_pf2 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi0_io3_pc5 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi0_io2_pc4 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi0_io1_pc3 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi0_io0_pc2 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi0_sck_pc0 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi0_cs_n_pc1 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi1_io3_pd3 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi1_io2_pd2 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi1_io1_pd1 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi1_io0_pd0 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi1_sck_pc6 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi1_cs_n_pc7 DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_qspi_comp DRV_PINGROUP_ENTRY_N(no_entry)
+#define drive_sdmmc1_comp DRV_PINGROUP_ENTRY_N(no_entry)
+
+#define PINGROUP(pg_name, f0, f1, f2, f3, r, bank, pupd, e_io_hv, e_lpbk, e_input, e_lpdr, e_pbias_buf, \
+ gpio_sfio_sel, schmitt_b) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = ARRAY_SIZE(pg_name##_pins), \
+ .funcs = { \
+ TEGRA_MUX_##f0, \
+ TEGRA_MUX_##f1, \
+ TEGRA_MUX_##f2, \
+ TEGRA_MUX_##f3, \
+ }, \
+ PIN_PINGROUP_ENTRY_Y(r, bank, pupd, e_io_hv, e_lpbk, \
+ e_input, e_lpdr, e_pbias_buf, \
+ gpio_sfio_sel, schmitt_b) \
+ drive_##pg_name, \
+ }
+
+static const struct tegra_pingroup tegra234_groups[] = {
+ PINGROUP(soc_gpio08_pb0, RSVD0, RSVD1, RSVD2, RSVD3, 0x5008, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio36_pm5, ETH0, RSVD1, DCA, RSVD3, 0x10000, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio53_pm6, ETH0, RSVD1, DCA, RSVD3, 0x10008, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio55_pm4, ETH2, RSVD1, RSVD2, RSVD3, 0x10010, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio38_pm7, ETH1, RSVD1, RSVD2, RSVD3, 0x10018, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio39_pn1, GP, RSVD1, RSVD2, RSVD3, 0x10020, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio40_pn2, ETH1, RSVD1, RSVD2, RSVD3, 0x10028, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dp_aux_ch0_hpd_pm0, DP, RSVD1, RSVD2, RSVD3, 0x10030, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dp_aux_ch1_hpd_pm1, ETH3, RSVD1, RSVD2, RSVD3, 0x10038, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dp_aux_ch2_hpd_pm2, ETH3, RSVD1, DISPLAYB, RSVD3, 0x10040, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dp_aux_ch3_hpd_pm3, ETH2, RSVD1, DISPLAYA, RSVD3, 0x10048, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dp_aux_ch1_p_pn3, I2C4, RSVD1, RSVD2, RSVD3, 0x10050, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dp_aux_ch1_n_pn4, I2C4, RSVD1, RSVD2, RSVD3, 0x10058, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dp_aux_ch2_p_pn5, I2C7, RSVD1, RSVD2, RSVD3, 0x10060, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dp_aux_ch2_n_pn6, I2C7, RSVD1, RSVD2, RSVD3, 0x10068, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dp_aux_ch3_p_pn7, I2C9, RSVD1, RSVD2, RSVD3, 0x10070, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dp_aux_ch3_n_pn0, I2C9, RSVD1, RSVD2, RSVD3, 0x10078, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(eqos_td3_pe4, EQOS, RSVD1, RSVD2, RSVD3, 0x15000, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_td2_pe3, EQOS, RSVD1, RSVD2, RSVD3, 0x15008, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_td1_pe2, EQOS, RSVD1, RSVD2, RSVD3, 0x15010, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_td0_pe1, EQOS, RSVD1, RSVD2, RSVD3, 0x15018, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_rd3_pf1, EQOS, RSVD1, RSVD2, RSVD3, 0x15020, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_rd2_pf0, EQOS, RSVD1, RSVD2, RSVD3, 0x15028, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_rd1_pe7, EQOS, RSVD1, RSVD2, RSVD3, 0x15030, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_sma_mdio_pf4, EQOS, RSVD1, RSVD2, RSVD3, 0x15038, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_rd0_pe6, EQOS, RSVD1, RSVD2, RSVD3, 0x15040, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_sma_mdc_pf5, EQOS, RSVD1, RSVD2, RSVD3, 0x15048, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_comp, EQOS, RSVD1, RSVD2, RSVD3, 0x15050, 0, N, -1, -1, -1, -1, -1, -1, -1),
+ PINGROUP(eqos_txc_pe0, EQOS, RSVD1, RSVD2, RSVD3, 0x15058, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_rxc_pf3, EQOS, RSVD1, RSVD2, RSVD3, 0x15060, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_tx_ctl_pe5, EQOS, RSVD1, RSVD2, RSVD3, 0x15068, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(eqos_rx_ctl_pf2, EQOS, RSVD1, RSVD2, RSVD3, 0x15070, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(pex_l2_clkreq_n_pk4, PE2, RSVD1, RSVD2, RSVD3, 0x7000, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_wake_n_pl2, RSVD0, RSVD1, RSVD2, RSVD3, 0x7008, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l1_clkreq_n_pk2, PE1, RSVD1, RSVD2, RSVD3, 0x7010, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l1_rst_n_pk3, PE1, RSVD1, RSVD2, RSVD3, 0x7018, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l0_clkreq_n_pk0, PE0, RSVD1, RSVD2, RSVD3, 0x7020, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l0_rst_n_pk1, PE0, RSVD1, RSVD2, RSVD3, 0x7028, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l2_rst_n_pk5, PE2, RSVD1, RSVD2, RSVD3, 0x7030, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l3_clkreq_n_pk6, PE3, RSVD1, RSVD2, RSVD3, 0x7038, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l3_rst_n_pk7, PE3, RSVD1, RSVD2, RSVD3, 0x7040, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l4_clkreq_n_pl0, PE4, RSVD1, RSVD2, RSVD3, 0x7048, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l4_rst_n_pl1, PE4, RSVD1, RSVD2, RSVD3, 0x7050, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio34_pl3, RSVD0, RSVD1, RSVD2, RSVD3, 0x7058, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l5_clkreq_n_paf0, PE5, RSVD1, RSVD2, RSVD3, 0x14000, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l5_rst_n_paf1, PE5, RSVD1, RSVD2, RSVD3, 0x14008, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l6_clkreq_n_paf2, PE6, RSVD1, RSVD2, RSVD3, 0x14010, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l6_rst_n_paf3, PE6, RSVD1, RSVD2, RSVD3, 0x14018, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l10_clkreq_n_pag6, PE10, RSVD1, RSVD2, RSVD3, 0x19000, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l10_rst_n_pag7, PE10, RSVD1, RSVD2, RSVD3, 0x19008, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l7_clkreq_n_pag0, PE7, RSVD1, RSVD2, RSVD3, 0x19010, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l7_rst_n_pag1, PE7, RSVD1, RSVD2, RSVD3, 0x19018, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l8_clkreq_n_pag2, PE8, RSVD1, RSVD2, RSVD3, 0x19020, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l8_rst_n_pag3, PE8, RSVD1, RSVD2, RSVD3, 0x19028, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l9_clkreq_n_pag4, PE9, RSVD1, RSVD2, RSVD3, 0x19030, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pex_l9_rst_n_pag5, PE9, RSVD1, RSVD2, RSVD3, 0x19038, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(qspi0_io3_pc5, QSPI0, RSVD1, RSVD2, RSVD3, 0xB000, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(qspi0_io2_pc4, QSPI0, RSVD1, RSVD2, RSVD3, 0xB008, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(qspi0_io1_pc3, QSPI0, RSVD1, RSVD2, RSVD3, 0xB010, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(qspi0_io0_pc2, QSPI0, RSVD1, RSVD2, RSVD3, 0xB018, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(qspi0_sck_pc0, QSPI0, RSVD1, RSVD2, RSVD3, 0xB020, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(qspi0_cs_n_pc1, QSPI0, RSVD1, RSVD2, RSVD3, 0xB028, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(qspi1_io3_pd3, QSPI1, RSVD1, RSVD2, RSVD3, 0xB030, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(qspi1_io2_pd2, QSPI1, RSVD1, RSVD2, RSVD3, 0xB038, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(qspi1_io1_pd1, QSPI1, RSVD1, RSVD2, RSVD3, 0xB040, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(qspi1_io0_pd0, QSPI1, RSVD1, RSVD2, RSVD3, 0xB048, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(qspi1_sck_pc6, QSPI1, RSVD1, RSVD2, RSVD3, 0xB050, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(qspi1_cs_n_pc7, QSPI1, RSVD1, RSVD2, RSVD3, 0xB058, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(qspi_comp, QSPI, RSVD1, RSVD2, RSVD3, 0xB060, 0, N, -1, -1, -1, -1, -1, -1, -1),
+ PINGROUP(sdmmc1_clk_pj0, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8000, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(sdmmc1_cmd_pj1, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8008, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(sdmmc1_comp, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8010, 0, N, -1, -1, -1, -1, -1, -1, -1),
+ PINGROUP(sdmmc1_dat3_pj5, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8018, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(sdmmc1_dat2_pj4, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8020, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(sdmmc1_dat1_pj3, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8028, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(sdmmc1_dat0_pj2, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8030, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(ufs0_rst_n_pae1, UFS0, RSVD1, RSVD2, RSVD3, 0x11000, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(ufs0_ref_clk_pae0, UFS0, RSVD1, RSVD2, RSVD3, 0x11008, 0, Y, -1, 5, 6, -1, -1, 10, 12),
+ PINGROUP(spi3_miso_py1, SPI3, RSVD1, RSVD2, RSVD3, 0xD000, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi1_cs0_pz6, SPI1, RSVD1, RSVD2, RSVD3, 0xD008, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi3_cs0_py3, SPI3, RSVD1, RSVD2, RSVD3, 0xD010, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi1_miso_pz4, SPI1, RSVD1, RSVD2, RSVD3, 0xD018, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi3_cs1_py4, SPI3, RSVD1, RSVD2, RSVD3, 0xD020, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi1_sck_pz3, SPI1, RSVD1, RSVD2, RSVD3, 0xD028, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi3_sck_py0, SPI3, RSVD1, RSVD2, RSVD3, 0xD030, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi1_cs1_pz7, SPI1, RSVD1, RSVD2, RSVD3, 0xD038, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi1_mosi_pz5, SPI1, RSVD1, RSVD2, RSVD3, 0xD040, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi3_mosi_py2, SPI3, RSVD1, RSVD2, RSVD3, 0xD048, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart2_tx_px4, UARTB, RSVD1, RSVD2, RSVD3, 0xD050, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart2_rx_px5, UARTB, RSVD1, RSVD2, RSVD3, 0xD058, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart2_rts_px6, UARTB, RSVD1, RSVD2, RSVD3, 0xD060, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart2_cts_px7, UARTB, RSVD1, RSVD2, RSVD3, 0xD068, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart5_tx_py5, UARTE, RSVD1, RSVD2, RSVD3, 0xD070, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart5_rx_py6, UARTE, RSVD1, RSVD2, RSVD3, 0xD078, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart5_rts_py7, UARTE, RSVD1, RSVD2, RSVD3, 0xD080, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart5_cts_pz0, UARTE, RSVD1, RSVD2, RSVD3, 0xD088, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(gpu_pwr_req_px0, RSVD0, RSVD1, RSVD2, RSVD3, 0xD090, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(gp_pwm3_px3, GP, RSVD1, RSVD2, RSVD3, 0xD098, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(gp_pwm2_px2, GP, RSVD1, RSVD2, RSVD3, 0xD0A0, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(cv_pwr_req_px1, RSVD0, RSVD1, RSVD2, RSVD3, 0xD0A8, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(usb_vbus_en0_pz1, USB, RSVD1, RSVD2, RSVD3, 0xD0B0, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(usb_vbus_en1_pz2, USB, RSVD1, RSVD2, RSVD3, 0xD0B8, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(extperiph2_clk_pp1, EXTPERIPH2, RSVD1, RSVD2, RSVD3, 0x0000, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(extperiph1_clk_pp0, EXTPERIPH1, RSVD1, RSVD2, RSVD3, 0x0008, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(cam_i2c_sda_pp3, I2C3, VI0, RSVD2, VI1, 0x0010, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(cam_i2c_scl_pp2, I2C3, VI0, VI0_ALT, VI1, 0x0018, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio23_pp4, VI0, VI0_ALT, VI1, VI1_ALT, 0x0020, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio24_pp5, VI0, SOC, VI1, VI1_ALT, 0x0028, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio25_pp6, VI0, I2S5, VI1, DMIC1, 0x0030, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pwr_i2c_scl_pp7, I2C5, RSVD1, RSVD2, RSVD3, 0x0038, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(pwr_i2c_sda_pq0, I2C5, RSVD1, RSVD2, RSVD3, 0x0040, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio28_pq1, VI0, RSVD1, VI1, RSVD3, 0x0048, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio29_pq2, RSVD0, NV, RSVD2, RSVD3, 0x0050, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio30_pq3, RSVD0, WDT, RSVD2, RSVD3, 0x0058, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio31_pq4, RSVD0, RSVD1, RSVD2, RSVD3, 0x0060, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio32_pq5, RSVD0, EXTPERIPH3, DCB, RSVD3, 0x0068, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio33_pq6, RSVD0, EXTPERIPH4, DCB, RSVD3, 0x0070, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio35_pq7, RSVD0, I2S5, DMIC1, RSVD3, 0x0078, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio37_pr0, GP, I2S5, DMIC4, DSPK1, 0x0080, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio56_pr1, RSVD0, I2S5, DMIC4, DSPK1, 0x0088, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart1_cts_pr5, UARTA, RSVD1, RSVD2, RSVD3, 0x0090, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart1_rts_pr4, UARTA, RSVD1, RSVD2, RSVD3, 0x0098, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart1_rx_pr3, UARTA, RSVD1, RSVD2, RSVD3, 0x00A0, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart1_tx_pr2, UARTA, RSVD1, RSVD2, RSVD3, 0x00A8, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(cpu_pwr_req_pi5, RSVD0, RSVD1, RSVD2, RSVD3, 0x4000, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart4_cts_ph6, UARTD, RSVD1, I2S7, RSVD3, 0x4008, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart4_rts_ph5, UARTD, SPI4, RSVD2, RSVD3, 0x4010, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart4_rx_ph4, UARTD, RSVD1, I2S7, RSVD3, 0x4018, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart4_tx_ph3, UARTD, SPI4, RSVD2, RSVD3, 0x4020, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(gen1_i2c_scl_pi3, I2C1, RSVD1, RSVD2, RSVD3, 0x4028, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(gen1_i2c_sda_pi4, I2C1, RSVD1, RSVD2, RSVD3, 0x4030, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio20_pg7, RSVD0, SDMMC1, RSVD2, RSVD3, 0x4038, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio21_ph0, RSVD0, GP, I2S7, RSVD3, 0x4040, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio22_ph1, RSVD0, RSVD1, I2S7, RSVD3, 0x4048, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio13_pg0, RSVD0, RSVD1, RSVD2, RSVD3, 0x4050, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio14_pg1, RSVD0, SPI4, RSVD2, RSVD3, 0x4058, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio15_pg2, RSVD0, SPI4, RSVD2, RSVD3, 0x4060, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio16_pg3, RSVD0, SPI4, RSVD2, RSVD3, 0x4068, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio17_pg4, RSVD0, CCLA, RSVD2, RSVD3, 0x4070, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio18_pg5, RSVD0, RSVD1, RSVD2, RSVD3, 0x4078, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio19_pg6, GP, RSVD1, RSVD2, RSVD3, 0x4080, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio41_ph7, RSVD0, I2S2, RSVD2, RSVD3, 0x4088, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio42_pi0, RSVD0, I2S2, RSVD2, RSVD3, 0x4090, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio43_pi1, RSVD0, I2S2, RSVD2, RSVD3, 0x4098, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio44_pi2, RSVD0, I2S2, RSVD2, RSVD3, 0x40A0, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio06_ph2, RSVD0, RSVD1, RSVD2, RSVD3, 0x40A8, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio07_pi6, GP, RSVD1, RSVD2, RSVD3, 0x40B0, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dap4_sclk_pa4, I2S4, RSVD1, RSVD2, RSVD3, 0x2000, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dap4_dout_pa5, I2S4, RSVD1, RSVD2, RSVD3, 0x2008, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dap4_din_pa6, I2S4, RSVD1, RSVD2, RSVD3, 0x2010, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dap4_fs_pa7, I2S4, RSVD1, RSVD2, RSVD3, 0x2018, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dap6_sclk_pa0, I2S6, RSVD1, RSVD2, RSVD3, 0x2020, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dap6_dout_pa1, I2S6, RSVD1, RSVD2, RSVD3, 0x2028, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dap6_din_pa2, I2S6, RSVD1, RSVD2, RSVD3, 0x2030, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(dap6_fs_pa3, I2S6, RSVD1, RSVD2, RSVD3, 0x2038, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio45_pad0, RSVD0, I2S1, RSVD2, RSVD3, 0x18000, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio46_pad1, RSVD0, I2S1, RSVD2, RSVD3, 0x18008, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio47_pad2, RSVD0, I2S1, RSVD2, RSVD3, 0x18010, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio48_pad3, RSVD0, I2S1, RSVD2, RSVD3, 0x18018, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio57_pac4, RSVD0, I2S8, RSVD2, SDMMC1, 0x18020, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio58_pac5, RSVD0, I2S8, RSVD2, SDMMC1, 0x18028, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio59_pac6, AUD, I2S8, RSVD2, RSVD3, 0x18030, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio60_pac7, RSVD0, I2S8, NV, IGPU, 0x18038, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi5_cs0_pac3, SPI5, I2S3, DMIC2, RSVD3, 0x18040, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi5_miso_pac1, SPI5, I2S3, DSPK0, RSVD3, 0x18048, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi5_mosi_pac2, SPI5, I2S3, DMIC2, RSVD3, 0x18050, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi5_sck_pac0, SPI5, I2S3, DSPK0, RSVD3, 0x18058, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+
+};
+
+static const struct tegra_pinctrl_soc_data tegra234_pinctrl = {
+ .pins = tegra234_pins,
+ .npins = ARRAY_SIZE(tegra234_pins),
+ .functions = tegra234_functions,
+ .nfunctions = ARRAY_SIZE(tegra234_functions),
+ .groups = tegra234_groups,
+ .ngroups = ARRAY_SIZE(tegra234_groups),
+ .hsm_in_mux = false,
+ .schmitt_in_mux = true,
+ .drvtype_in_mux = true,
+ .sfsel_in_mux = true,
+};
+
+static const struct pinctrl_pin_desc tegra234_aon_pins[] = {
+ PINCTRL_PIN(TEGRA_PIN_CAN0_DOUT_PAA0, "CAN0_DOUT_PAA0"),
+ PINCTRL_PIN(TEGRA_PIN_CAN0_DIN_PAA1, "CAN0_DIN_PAA1"),
+ PINCTRL_PIN(TEGRA_PIN_CAN1_DOUT_PAA2, "CAN1_DOUT_PAA2"),
+ PINCTRL_PIN(TEGRA_PIN_CAN1_DIN_PAA3, "CAN1_DIN_PAA3"),
+ PINCTRL_PIN(TEGRA_PIN_CAN0_STB_PAA4, "CAN0_STB_PAA4"),
+ PINCTRL_PIN(TEGRA_PIN_CAN0_EN_PAA5, "CAN0_EN_PAA5"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO49_PAA6, "SOC_GPIO49_PAA6"),
+ PINCTRL_PIN(TEGRA_PIN_CAN0_ERR_PAA7, "CAN0_ERR_PAA7"),
+ PINCTRL_PIN(TEGRA_PIN_CAN1_STB_PBB0, "CAN1_STB_PBB0"),
+ PINCTRL_PIN(TEGRA_PIN_CAN1_EN_PBB1, "CAN1_EN_PBB1"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO50_PBB2, "SOC_GPIO50_PBB2"),
+ PINCTRL_PIN(TEGRA_PIN_CAN1_ERR_PBB3, "CAN1_ERR_PBB3"),
+ PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PCC0, "SPI2_SCK_PCC0"),
+ PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PCC1, "SPI2_MISO_PCC1"),
+ PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PCC2, "SPI2_MOSI_PCC2"),
+ PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_PCC3, "SPI2_CS0_PCC3"),
+ PINCTRL_PIN(TEGRA_PIN_TOUCH_CLK_PCC4, "TOUCH_CLK_PCC4"),
+ PINCTRL_PIN(TEGRA_PIN_UART3_TX_PCC5, "UART3_TX_PCC5"),
+ PINCTRL_PIN(TEGRA_PIN_UART3_RX_PCC6, "UART3_RX_PCC6"),
+ PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PCC7, "GEN2_I2C_SCL_PCC7"),
+ PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PDD0, "GEN2_I2C_SDA_PDD0"),
+ PINCTRL_PIN(TEGRA_PIN_GEN8_I2C_SCL_PDD1, "GEN8_I2C_SCL_PDD1"),
+ PINCTRL_PIN(TEGRA_PIN_GEN8_I2C_SDA_PDD2, "GEN8_I2C_SDA_PDD2"),
+ PINCTRL_PIN(TEGRA_PIN_SCE_ERROR_PEE0, "SCE_ERROR_PEE0"),
+ PINCTRL_PIN(TEGRA_PIN_VCOMP_ALERT_PEE1, "VCOMP_ALERT_PEE1"),
+ PINCTRL_PIN(TEGRA_PIN_AO_RETENTION_N_PEE2, "AO_RETENTION_N_PEE2"),
+ PINCTRL_PIN(TEGRA_PIN_BATT_OC_PEE3, "BATT_OC_PEE3"),
+ PINCTRL_PIN(TEGRA_PIN_POWER_ON_PEE4, "POWER_ON_PEE4"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO26_PEE5, "SOC_GPIO26_PEE5"),
+ PINCTRL_PIN(TEGRA_PIN_SOC_GPIO27_PEE6, "SOC_GPIO27_PEE6"),
+ PINCTRL_PIN(TEGRA_PIN_BOOTV_CTL_N_PEE7, "BOOTV_CTL_N_PEE7"),
+ PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PGG0, "HDMI_CEC_PGG0"),
+};
+
+/* AON drive pin groups */
+#define drive_touch_clk_pcc4 DRV_PINGROUP_ENTRY_Y(0x2004, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart3_rx_pcc6 DRV_PINGROUP_ENTRY_Y(0x200c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_uart3_tx_pcc5 DRV_PINGROUP_ENTRY_Y(0x2014, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_gen8_i2c_sda_pdd2 DRV_PINGROUP_ENTRY_Y(0x201c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_gen8_i2c_scl_pdd1 DRV_PINGROUP_ENTRY_Y(0x2024, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi2_mosi_pcc2 DRV_PINGROUP_ENTRY_Y(0x202c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_gen2_i2c_scl_pcc7 DRV_PINGROUP_ENTRY_Y(0x2034, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi2_cs0_pcc3 DRV_PINGROUP_ENTRY_Y(0x203c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_gen2_i2c_sda_pdd0 DRV_PINGROUP_ENTRY_Y(0x2044, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi2_sck_pcc0 DRV_PINGROUP_ENTRY_Y(0x204c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_spi2_miso_pcc1 DRV_PINGROUP_ENTRY_Y(0x2054, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_can1_dout_paa2 DRV_PINGROUP_ENTRY_Y(0x3004, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_can1_din_paa3 DRV_PINGROUP_ENTRY_Y(0x300c, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_can0_dout_paa0 DRV_PINGROUP_ENTRY_Y(0x3014, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_can0_din_paa1 DRV_PINGROUP_ENTRY_Y(0x301c, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_can0_stb_paa4 DRV_PINGROUP_ENTRY_Y(0x3024, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_can0_en_paa5 DRV_PINGROUP_ENTRY_Y(0x302c, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_soc_gpio49_paa6 DRV_PINGROUP_ENTRY_Y(0x3034, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_can0_err_paa7 DRV_PINGROUP_ENTRY_Y(0x303c, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_can1_stb_pbb0 DRV_PINGROUP_ENTRY_Y(0x3044, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_can1_en_pbb1 DRV_PINGROUP_ENTRY_Y(0x304c, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_soc_gpio50_pbb2 DRV_PINGROUP_ENTRY_Y(0x3054, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_can1_err_pbb3 DRV_PINGROUP_ENTRY_Y(0x305c, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_sce_error_pee0 DRV_PINGROUP_ENTRY_Y(0x1014, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_batt_oc_pee3 DRV_PINGROUP_ENTRY_Y(0x1024, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_bootv_ctl_n_pee7 DRV_PINGROUP_ENTRY_Y(0x102c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_power_on_pee4 DRV_PINGROUP_ENTRY_Y(0x103c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio26_pee5 DRV_PINGROUP_ENTRY_Y(0x1044, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_soc_gpio27_pee6 DRV_PINGROUP_ENTRY_Y(0x104c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_ao_retention_n_pee2 DRV_PINGROUP_ENTRY_Y(0x1054, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_vcomp_alert_pee1 DRV_PINGROUP_ENTRY_Y(0x105c, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+#define drive_hdmi_cec_pgg0 DRV_PINGROUP_ENTRY_Y(0x1064, 12, 5, 20, 5, -1, -1, -1, -1, 0)
+
+static const struct tegra_pingroup tegra234_aon_groups[] = {
+ PINGROUP(touch_clk_pcc4, GP, TOUCH, RSVD2, RSVD3, 0x2000, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart3_rx_pcc6, UARTC, UARTJ, RSVD2, RSVD3, 0x2008, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(uart3_tx_pcc5, UARTC, UARTJ, RSVD2, RSVD3, 0x2010, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(gen8_i2c_sda_pdd2, I2C8, RSVD1, RSVD2, RSVD3, 0x2018, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(gen8_i2c_scl_pdd1, I2C8, RSVD1, RSVD2, RSVD3, 0x2020, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi2_mosi_pcc2, SPI2, RSVD1, RSVD2, RSVD3, 0x2028, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(gen2_i2c_scl_pcc7, I2C2, RSVD1, RSVD2, RSVD3, 0x2030, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi2_cs0_pcc3, SPI2, RSVD1, RSVD2, RSVD3, 0x2038, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(gen2_i2c_sda_pdd0, I2C2, RSVD1, RSVD2, RSVD3, 0x2040, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi2_sck_pcc0, SPI2, RSVD1, RSVD2, RSVD3, 0x2048, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(spi2_miso_pcc1, SPI2, RSVD1, RSVD2, RSVD3, 0x2050, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(can1_dout_paa2, CAN1, RSVD1, RSVD2, RSVD3, 0x3000, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(can1_din_paa3, CAN1, RSVD1, RSVD2, RSVD3, 0x3008, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(can0_dout_paa0, CAN0, RSVD1, RSVD2, RSVD3, 0x3010, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(can0_din_paa1, CAN0, RSVD1, RSVD2, RSVD3, 0x3018, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(can0_stb_paa4, RSVD0, WDT, TSC, TSC_ALT, 0x3020, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(can0_en_paa5, RSVD0, RSVD1, RSVD2, RSVD3, 0x3028, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(soc_gpio49_paa6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3030, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(can0_err_paa7, RSVD0, TSC, RSVD2, TSC_ALT, 0x3038, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(can1_stb_pbb0, RSVD0, DMIC3, DMIC5, RSVD3, 0x3040, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(can1_en_pbb1, RSVD0, DMIC3, DMIC5, RSVD3, 0x3048, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(soc_gpio50_pbb2, RSVD0, TSC, RSVD2, TSC_ALT, 0x3050, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(can1_err_pbb3, RSVD0, TSC, RSVD2, TSC_ALT, 0x3058, 0, Y, -1, 5, 6, -1, 9, 10, 12),
+ PINGROUP(sce_error_pee0, SCE, RSVD1, RSVD2, RSVD3, 0x1010, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(batt_oc_pee3, SOC, RSVD1, RSVD2, RSVD3, 0x1020, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(bootv_ctl_n_pee7, RSVD0, RSVD1, RSVD2, RSVD3, 0x1028, 0, Y, -1, 7, 6, 8, -1, 10, 12),
+ PINGROUP(power_on_pee4, RSVD0, RSVD1, RSVD2, RSVD3, 0x1038, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio26_pee5, RSVD0, RSVD1, RSVD2, RSVD3, 0x1040, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(soc_gpio27_pee6, RSVD0, RSVD1, RSVD2, RSVD3, 0x1048, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(ao_retention_n_pee2, GPIO, LED, RSVD2, ISTCTRL, 0x1050, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(vcomp_alert_pee1, SOC, RSVD1, RSVD2, RSVD3, 0x1058, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+ PINGROUP(hdmi_cec_pgg0, HDMI, RSVD1, RSVD2, RSVD3, 0x1060, 0, Y, 5, 7, 6, 8, -1, 10, 12),
+};
+
+static const struct tegra_pinctrl_soc_data tegra234_pinctrl_aon = {
+ .pins = tegra234_aon_pins,
+ .npins = ARRAY_SIZE(tegra234_aon_pins),
+ .functions = tegra234_functions,
+ .nfunctions = ARRAY_SIZE(tegra234_functions),
+ .groups = tegra234_aon_groups,
+ .ngroups = ARRAY_SIZE(tegra234_aon_groups),
+ .hsm_in_mux = false,
+ .schmitt_in_mux = true,
+ .drvtype_in_mux = true,
+ .sfsel_in_mux = true,
+};
+
+static int tegra234_pinctrl_probe(struct platform_device *pdev)
+{
+ const struct tegra_pinctrl_soc_data *soc = device_get_match_data(&pdev->dev);
+
+ return tegra_pinctrl_probe(pdev, soc);
+}
+
+static const struct of_device_id tegra234_pinctrl_of_match[] = {
+ { .compatible = "nvidia,tegra234-pinmux", .data = &tegra234_pinctrl},
+ { .compatible = "nvidia,tegra234-pinmux-aon", .data = &tegra234_pinctrl_aon },
+ { }
+};
+MODULE_DEVICE_TABLE(of, tegra234_pinctrl_of_match);
+
+static struct platform_driver tegra234_pinctrl_driver = {
+ .driver = {
+ .name = "tegra234-pinctrl",
+ .of_match_table = tegra234_pinctrl_of_match,
+ },
+ .probe = tegra234_pinctrl_probe,
+};
+
+static int __init tegra234_pinctrl_init(void)
+{
+ return platform_driver_register(&tegra234_pinctrl_driver);
+}
+arch_initcall(tegra234_pinctrl_init);
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra30.c b/drivers/pinctrl/tegra/pinctrl-tegra30.c
index 7299a371827f..de5aa2d4d28d 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra30.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra30.c
@@ -2010,12 +2010,9 @@ enum tegra_mux {
TEGRA_MUX_VI_ALT3,
};
-#define FUNCTION(fname) \
- { \
- .name = #fname, \
- }
+#define FUNCTION(fname) #fname
-static struct tegra_function tegra30_functions[] = {
+static const char * const tegra30_functions[] = {
FUNCTION(blink),
FUNCTION(cec),
FUNCTION(clk_12m_out),
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index a673c3342470..25f9767c28e8 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -77,7 +77,7 @@ static int cros_typec_get_switch_handles(struct cros_typec_port *port,
{
int ret = 0;
- port->mux = fwnode_typec_mux_get(fwnode, NULL);
+ port->mux = fwnode_typec_mux_get(fwnode);
if (IS_ERR(port->mux)) {
ret = PTR_ERR(port->mux);
dev_dbg(dev, "Mux handle not found: %d.\n", ret);
diff --git a/drivers/platform/mellanox/mlxbf-bootctl.c b/drivers/platform/mellanox/mlxbf-bootctl.c
index 1bad1d278672..fb9f7815c6cd 100644
--- a/drivers/platform/mellanox/mlxbf-bootctl.c
+++ b/drivers/platform/mellanox/mlxbf-bootctl.c
@@ -11,6 +11,7 @@
#include <linux/acpi.h>
#include <linux/arm-smccc.h>
#include <linux/delay.h>
+#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -45,10 +46,39 @@ static const char * const mlxbf_bootctl_lifecycle_states[] = {
[3] = "RMA",
};
+/* Log header format. */
+#define MLXBF_RSH_LOG_TYPE_MASK GENMASK_ULL(59, 56)
+#define MLXBF_RSH_LOG_LEN_MASK GENMASK_ULL(54, 48)
+#define MLXBF_RSH_LOG_LEVEL_MASK GENMASK_ULL(7, 0)
+
+/* Log module ID and type (only MSG type in Linux driver for now). */
+#define MLXBF_RSH_LOG_TYPE_MSG 0x04ULL
+
+/* Log ctl/data register offset. */
+#define MLXBF_RSH_SCRATCH_BUF_CTL_OFF 0
+#define MLXBF_RSH_SCRATCH_BUF_DATA_OFF 0x10
+
+/* Log message levels. */
+enum {
+ MLXBF_RSH_LOG_INFO,
+ MLXBF_RSH_LOG_WARN,
+ MLXBF_RSH_LOG_ERR,
+ MLXBF_RSH_LOG_ASSERT
+};
+
/* Mapped pointer for RSH_BOOT_FIFO_DATA and RSH_BOOT_FIFO_COUNT register. */
static void __iomem *mlxbf_rsh_boot_data;
static void __iomem *mlxbf_rsh_boot_cnt;
+/* Mapped pointer for rsh log semaphore/ctrl/data register. */
+static void __iomem *mlxbf_rsh_semaphore;
+static void __iomem *mlxbf_rsh_scratch_buf_ctl;
+static void __iomem *mlxbf_rsh_scratch_buf_data;
+
+/* Rsh log levels. */
+static const char * const mlxbf_rsh_log_level[] = {
+ "INFO", "WARN", "ERR", "ASSERT"};
+
/* ARM SMC call which is atomic and no need for lock. */
static int mlxbf_bootctl_smc(unsigned int smc_op, int smc_arg)
{
@@ -266,12 +296,108 @@ static ssize_t fw_reset_store(struct device *dev,
return count;
}
+/* Size(8-byte words) of the log buffer. */
+#define RSH_SCRATCH_BUF_CTL_IDX_MASK 0x7f
+
+/* 100ms timeout */
+#define RSH_SCRATCH_BUF_POLL_TIMEOUT 100000
+
+static int mlxbf_rsh_log_sem_lock(void)
+{
+ unsigned long reg;
+
+ return readq_poll_timeout(mlxbf_rsh_semaphore, reg, !reg, 0,
+ RSH_SCRATCH_BUF_POLL_TIMEOUT);
+}
+
+static void mlxbf_rsh_log_sem_unlock(void)
+{
+ writeq(0, mlxbf_rsh_semaphore);
+}
+
+static ssize_t rsh_log_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int rc, idx, num, len, level = MLXBF_RSH_LOG_INFO;
+ size_t size = count;
+ u64 data;
+
+ if (!size)
+ return -EINVAL;
+
+ if (!mlxbf_rsh_semaphore || !mlxbf_rsh_scratch_buf_ctl)
+ return -EOPNOTSUPP;
+
+ /* Ignore line break at the end. */
+ if (buf[size - 1] == '\n')
+ size--;
+
+ /* Check the message prefix. */
+ for (idx = 0; idx < ARRAY_SIZE(mlxbf_rsh_log_level); idx++) {
+ len = strlen(mlxbf_rsh_log_level[idx]);
+ if (len + 1 < size &&
+ !strncmp(buf, mlxbf_rsh_log_level[idx], len)) {
+ buf += len;
+ size -= len;
+ level = idx;
+ break;
+ }
+ }
+
+ /* Ignore leading spaces. */
+ while (size > 0 && buf[0] == ' ') {
+ size--;
+ buf++;
+ }
+
+ /* Take the semaphore. */
+ rc = mlxbf_rsh_log_sem_lock();
+ if (rc)
+ return rc;
+
+ /* Calculate how many words are available. */
+ idx = readq(mlxbf_rsh_scratch_buf_ctl);
+ num = min((int)DIV_ROUND_UP(size, sizeof(u64)),
+ RSH_SCRATCH_BUF_CTL_IDX_MASK - idx - 1);
+ if (num <= 0)
+ goto done;
+
+ /* Write Header. */
+ data = FIELD_PREP(MLXBF_RSH_LOG_TYPE_MASK, MLXBF_RSH_LOG_TYPE_MSG);
+ data |= FIELD_PREP(MLXBF_RSH_LOG_LEN_MASK, num);
+ data |= FIELD_PREP(MLXBF_RSH_LOG_LEVEL_MASK, level);
+ writeq(data, mlxbf_rsh_scratch_buf_data);
+
+ /* Write message. */
+ for (idx = 0; idx < num && size > 0; idx++) {
+ if (size < sizeof(u64)) {
+ data = 0;
+ memcpy(&data, buf, size);
+ size = 0;
+ } else {
+ memcpy(&data, buf, sizeof(u64));
+ size -= sizeof(u64);
+ buf += sizeof(u64);
+ }
+ writeq(data, mlxbf_rsh_scratch_buf_data);
+ }
+
+done:
+ /* Release the semaphore. */
+ mlxbf_rsh_log_sem_unlock();
+
+ /* Ignore the rest if no more space. */
+ return count;
+}
+
static DEVICE_ATTR_RW(post_reset_wdog);
static DEVICE_ATTR_RW(reset_action);
static DEVICE_ATTR_RW(second_reset_action);
static DEVICE_ATTR_RO(lifecycle_state);
static DEVICE_ATTR_RO(secure_boot_fuse_state);
static DEVICE_ATTR_WO(fw_reset);
+static DEVICE_ATTR_WO(rsh_log);
static struct attribute *mlxbf_bootctl_attrs[] = {
&dev_attr_post_reset_wdog.attr,
@@ -280,6 +406,7 @@ static struct attribute *mlxbf_bootctl_attrs[] = {
&dev_attr_lifecycle_state.attr,
&dev_attr_secure_boot_fuse_state.attr,
&dev_attr_fw_reset.attr,
+ &dev_attr_rsh_log.attr,
NULL
};
@@ -345,19 +472,32 @@ static bool mlxbf_bootctl_guid_match(const guid_t *guid,
static int mlxbf_bootctl_probe(struct platform_device *pdev)
{
struct arm_smccc_res res = { 0 };
+ void __iomem *reg;
guid_t guid;
int ret;
- /* Get the resource of the bootfifo data register. */
+ /* Map the resource of the bootfifo data register. */
mlxbf_rsh_boot_data = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mlxbf_rsh_boot_data))
return PTR_ERR(mlxbf_rsh_boot_data);
- /* Get the resource of the bootfifo counter register. */
+ /* Map the resource of the bootfifo counter register. */
mlxbf_rsh_boot_cnt = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(mlxbf_rsh_boot_cnt))
return PTR_ERR(mlxbf_rsh_boot_cnt);
+ /* Map the resource of the rshim semaphore register. */
+ mlxbf_rsh_semaphore = devm_platform_ioremap_resource(pdev, 2);
+ if (IS_ERR(mlxbf_rsh_semaphore))
+ return PTR_ERR(mlxbf_rsh_semaphore);
+
+ /* Map the resource of the scratch buffer (log) registers. */
+ reg = devm_platform_ioremap_resource(pdev, 3);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+ mlxbf_rsh_scratch_buf_ctl = reg + MLXBF_RSH_SCRATCH_BUF_CTL_OFF;
+ mlxbf_rsh_scratch_buf_data = reg + MLXBF_RSH_SCRATCH_BUF_DATA_OFF;
+
/* Ensure we have the UUID we expect for this service. */
arm_smccc_smc(MLXBF_BOOTCTL_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res);
guid_parse(mlxbf_bootctl_svc_uuid_str, &guid);
diff --git a/drivers/platform/surface/aggregator/Kconfig b/drivers/platform/surface/aggregator/Kconfig
index c114f9dd5fe1..88afc38ffdc5 100644
--- a/drivers/platform/surface/aggregator/Kconfig
+++ b/drivers/platform/surface/aggregator/Kconfig
@@ -4,7 +4,7 @@
menuconfig SURFACE_AGGREGATOR
tristate "Microsoft Surface System Aggregator Module Subsystem and Drivers"
depends on SERIAL_DEV_BUS
- depends on ACPI
+ depends on ACPI && !RISCV
select CRC_CCITT
help
The Surface System Aggregator Module (Surface SAM or SSAM) is an
diff --git a/drivers/platform/surface/surface3_power.c b/drivers/platform/surface/surface3_power.c
index 73961a24c849..4c0f92562a79 100644
--- a/drivers/platform/surface/surface3_power.c
+++ b/drivers/platform/surface/surface3_power.c
@@ -573,7 +573,7 @@ static const struct acpi_device_id mshw0011_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, mshw0011_acpi_match);
static struct i2c_driver mshw0011_driver = {
- .probe_new = mshw0011_probe,
+ .probe = mshw0011_probe,
.remove = mshw0011_remove,
.driver = {
.name = "mshw0011",
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 22052031c719..49c2c4cd8d00 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -43,8 +43,8 @@ config WMI_BMOF
default ACPI_WMI
help
Say Y here if you want to be able to read a firmware-embedded
- WMI Binary MOF data. Using this requires userspace tools and may be
- rather tedious.
+ WMI Binary MOF (Managed Object Format) data. Using this requires
+ userspace tools and may be rather tedious.
To compile this driver as a module, choose M here: the module will
be called wmi-bmof.
@@ -121,10 +121,11 @@ config GIGABYTE_WMI
To compile this driver as a module, choose M here: the module will
be called gigabyte-wmi.
-config YOGABOOK_WMI
- tristate "Lenovo Yoga Book tablet WMI key driver"
+config YOGABOOK
+ tristate "Lenovo Yoga Book tablet key driver"
depends on ACPI_WMI
depends on INPUT
+ depends on I2C
select LEDS_CLASS
select NEW_LEDS
help
@@ -132,7 +133,7 @@ config YOGABOOK_WMI
control on the Lenovo Yoga Book tablets.
To compile this driver as a module, choose M here: the module will
- be called lenovo-yogabook-wmi.
+ be called lenovo-yogabook.
config ACERHDF
tristate "Acer Aspire One temperature and fan driver"
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 2cafe51ec4d8..52dfdf574ac2 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -14,7 +14,6 @@ obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
obj-$(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) += nvidia-wmi-ec-backlight.o
obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o
obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o
-obj-$(CONFIG_YOGABOOK_WMI) += lenovo-yogabook-wmi.o
# Acer
obj-$(CONFIG_ACERHDF) += acerhdf.o
@@ -66,6 +65,7 @@ obj-$(CONFIG_LENOVO_YMC) += lenovo-ymc.o
obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
obj-$(CONFIG_THINKPAD_LMI) += think-lmi.o
+obj-$(CONFIG_YOGABOOK) += lenovo-yogabook.o
# Intel
obj-y += intel/
diff --git a/drivers/platform/x86/amd/pmc.c b/drivers/platform/x86/amd/pmc.c
index 1304cd6f13f6..7d3d080ff174 100644
--- a/drivers/platform/x86/amd/pmc.c
+++ b/drivers/platform/x86/amd/pmc.c
@@ -45,7 +45,6 @@
#define AMD_PMC_STB_DUMMY_PC 0xC6000007
/* STB S2D(Spill to DRAM) has different message port offset */
-#define STB_SPILL_TO_DRAM 0xBE
#define AMD_S2D_REGISTER_MESSAGE 0xA20
#define AMD_S2D_REGISTER_RESPONSE 0xA80
#define AMD_S2D_REGISTER_ARGUMENT 0xA88
@@ -99,7 +98,6 @@
#define PMC_MSG_DELAY_MIN_US 50
#define RESPONSE_REGISTER_LOOP_MAX 20000
-#define SOC_SUBSYSTEM_IP_MAX 12
#define DELAY_MIN_US 2000
#define DELAY_MAX_US 3000
#define FIFO_SIZE 4096
@@ -115,6 +113,7 @@ enum s2d_arg {
S2D_PHYS_ADDR_LOW,
S2D_PHYS_ADDR_HIGH,
S2D_NUM_SAMPLES,
+ S2D_DRAM_SIZE,
};
struct amd_pmc_bit_map {
@@ -132,9 +131,18 @@ static const struct amd_pmc_bit_map soc15_ip_blk[] = {
{"ISP", BIT(6)},
{"NBIO", BIT(7)},
{"DF", BIT(8)},
- {"USB0", BIT(9)},
- {"USB1", BIT(10)},
+ {"USB3_0", BIT(9)},
+ {"USB3_1", BIT(10)},
{"LAPIC", BIT(11)},
+ {"USB3_2", BIT(12)},
+ {"USB3_3", BIT(13)},
+ {"USB3_4", BIT(14)},
+ {"USB4_0", BIT(15)},
+ {"USB4_1", BIT(16)},
+ {"MPM", BIT(17)},
+ {"JPEG", BIT(18)},
+ {"IPU", BIT(19)},
+ {"UMSCH", BIT(20)},
{}
};
@@ -147,6 +155,9 @@ struct amd_pmc_dev {
u32 base_addr;
u32 cpu_id;
u32 active_ips;
+ u32 dram_size;
+ u32 num_ips;
+ u32 s2d_msg_id;
/* SMU version information */
u8 smu_program;
u8 major;
@@ -194,8 +205,8 @@ struct smu_metrics {
u64 timein_s0i3_totaltime;
u64 timein_swdrips_lastcapture;
u64 timein_swdrips_totaltime;
- u64 timecondition_notmet_lastcapture[SOC_SUBSYSTEM_IP_MAX];
- u64 timecondition_notmet_totaltime[SOC_SUBSYSTEM_IP_MAX];
+ u64 timecondition_notmet_lastcapture[32];
+ u64 timecondition_notmet_totaltime[32];
} __packed;
static int amd_pmc_stb_debugfs_open(struct inode *inode, struct file *filp)
@@ -261,7 +272,7 @@ static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp)
dev->msg_port = 1;
/* Get the num_samples to calculate the last push location */
- ret = amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &num_samples, STB_SPILL_TO_DRAM, 1);
+ ret = amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &num_samples, dev->s2d_msg_id, true);
/* Clear msg_port for other SMU operation */
dev->msg_port = 0;
if (ret) {
@@ -308,6 +319,23 @@ static const struct file_operations amd_pmc_stb_debugfs_fops_v2 = {
.release = amd_pmc_stb_debugfs_release_v2,
};
+static void amd_pmc_get_ip_info(struct amd_pmc_dev *dev)
+{
+ switch (dev->cpu_id) {
+ case AMD_CPU_ID_PCO:
+ case AMD_CPU_ID_RN:
+ case AMD_CPU_ID_YC:
+ case AMD_CPU_ID_CB:
+ dev->num_ips = 12;
+ dev->s2d_msg_id = 0xBE;
+ break;
+ case AMD_CPU_ID_PS:
+ dev->num_ips = 21;
+ dev->s2d_msg_id = 0x85;
+ break;
+ }
+}
+
static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
{
if (dev->cpu_id == AMD_CPU_ID_PCO) {
@@ -317,15 +345,15 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
/* Get Active devices list from SMU */
if (!dev->active_ips)
- amd_pmc_send_cmd(dev, 0, &dev->active_ips, SMU_MSG_GET_SUP_CONSTRAINTS, 1);
+ amd_pmc_send_cmd(dev, 0, &dev->active_ips, SMU_MSG_GET_SUP_CONSTRAINTS, true);
/* Get dram address */
if (!dev->smu_virt_addr) {
u32 phys_addr_low, phys_addr_hi;
u64 smu_phys_addr;
- amd_pmc_send_cmd(dev, 0, &phys_addr_low, SMU_MSG_LOG_GETDRAM_ADDR_LO, 1);
- amd_pmc_send_cmd(dev, 0, &phys_addr_hi, SMU_MSG_LOG_GETDRAM_ADDR_HI, 1);
+ amd_pmc_send_cmd(dev, 0, &phys_addr_low, SMU_MSG_LOG_GETDRAM_ADDR_LO, true);
+ amd_pmc_send_cmd(dev, 0, &phys_addr_hi, SMU_MSG_LOG_GETDRAM_ADDR_HI, true);
smu_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low);
dev->smu_virt_addr = devm_ioremap(dev->dev, smu_phys_addr,
@@ -335,8 +363,8 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
}
/* Start the logging */
- amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_RESET, 0);
- amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, 0);
+ amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_RESET, false);
+ amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, false);
return 0;
}
@@ -377,7 +405,7 @@ static int amd_pmc_get_smu_version(struct amd_pmc_dev *dev)
if (dev->cpu_id == AMD_CPU_ID_PCO)
return -ENODEV;
- rc = amd_pmc_send_cmd(dev, 0, &val, SMU_MSG_GETSMUVERSION, 1);
+ rc = amd_pmc_send_cmd(dev, 0, &val, SMU_MSG_GETSMUVERSION, true);
if (rc)
return rc;
@@ -469,7 +497,7 @@ static int smu_fw_info_show(struct seq_file *s, void *unused)
table.timeto_resume_to_os_lastcapture);
seq_puts(s, "\n=== Active time (in us) ===\n");
- for (idx = 0 ; idx < SOC_SUBSYSTEM_IP_MAX ; idx++) {
+ for (idx = 0 ; idx < dev->num_ips ; idx++) {
if (soc15_ip_blk[idx].bit_mask & dev->active_ips)
seq_printf(s, "%-8s : %lld\n", soc15_ip_blk[idx].name,
table.timecondition_notmet_lastcapture[idx]);
@@ -562,6 +590,18 @@ static void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev)
debugfs_remove_recursive(dev->dbgfs_dir);
}
+static bool amd_pmc_is_stb_supported(struct amd_pmc_dev *dev)
+{
+ switch (dev->cpu_id) {
+ case AMD_CPU_ID_YC:
+ case AMD_CPU_ID_CB:
+ case AMD_CPU_ID_PS:
+ return true;
+ default:
+ return false;
+ }
+}
+
static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
{
dev->dbgfs_dir = debugfs_create_dir("amd_pmc", NULL);
@@ -573,8 +613,7 @@ static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
&amd_pmc_idlemask_fops);
/* Enable STB only when the module_param is set */
if (enable_stb) {
- if (dev->cpu_id == AMD_CPU_ID_YC || dev->cpu_id == AMD_CPU_ID_CB ||
- dev->cpu_id == AMD_CPU_ID_PS)
+ if (amd_pmc_is_stb_supported(dev))
debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev,
&amd_pmc_stb_debugfs_fops_v2);
else
@@ -794,7 +833,7 @@ static void amd_pmc_s2idle_prepare(void)
}
msg = amd_pmc_get_os_hint(pdev);
- rc = amd_pmc_send_cmd(pdev, arg, NULL, msg, 0);
+ rc = amd_pmc_send_cmd(pdev, arg, NULL, msg, false);
if (rc) {
dev_err(pdev->dev, "suspend failed: %d\n", rc);
return;
@@ -829,7 +868,7 @@ static int amd_pmc_dump_data(struct amd_pmc_dev *pdev)
if (pdev->cpu_id == AMD_CPU_ID_PCO)
return -ENODEV;
- return amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, 0);
+ return amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, false);
}
static void amd_pmc_s2idle_restore(void)
@@ -839,7 +878,7 @@ static void amd_pmc_s2idle_restore(void)
u8 msg;
msg = amd_pmc_get_os_hint(pdev);
- rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, 0);
+ rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, false);
if (rc)
dev_err(pdev->dev, "resume failed: %d\n", rc);
@@ -890,29 +929,65 @@ static const struct pci_device_id pmc_pci_ids[] = {
{ }
};
+static int amd_pmc_get_dram_size(struct amd_pmc_dev *dev)
+{
+ int ret;
+
+ switch (dev->cpu_id) {
+ case AMD_CPU_ID_YC:
+ if (!(dev->major > 90 || (dev->major == 90 && dev->minor > 39))) {
+ ret = -EINVAL;
+ goto err_dram_size;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ goto err_dram_size;
+ }
+
+ ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->s2d_msg_id, true);
+ if (ret || !dev->dram_size)
+ goto err_dram_size;
+
+ return 0;
+
+err_dram_size:
+ dev_err(dev->dev, "DRAM size command not supported for this platform\n");
+ return ret;
+}
+
static int amd_pmc_s2d_init(struct amd_pmc_dev *dev)
{
u32 phys_addr_low, phys_addr_hi;
u64 stb_phys_addr;
u32 size = 0;
+ int ret;
/* Spill to DRAM feature uses separate SMU message port */
dev->msg_port = 1;
- amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, STB_SPILL_TO_DRAM, 1);
+ /* Get num of IP blocks within the SoC */
+ amd_pmc_get_ip_info(dev);
+
+ amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, dev->s2d_msg_id, true);
if (size != S2D_TELEMETRY_BYTES_MAX)
return -EIO;
+ /* Get DRAM size */
+ ret = amd_pmc_get_dram_size(dev);
+ if (ret)
+ dev->dram_size = S2D_TELEMETRY_DRAMBYTES_MAX;
+
/* Get STB DRAM address */
- amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low, STB_SPILL_TO_DRAM, 1);
- amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi, STB_SPILL_TO_DRAM, 1);
+ amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low, dev->s2d_msg_id, true);
+ amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi, dev->s2d_msg_id, true);
stb_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low);
/* Clear msg_port for other SMU operation */
dev->msg_port = 0;
- dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, S2D_TELEMETRY_DRAMBYTES_MAX);
+ dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, dev->dram_size);
if (!dev->stb_virt_addr)
return -ENOMEM;
@@ -1001,7 +1076,7 @@ static int amd_pmc_probe(struct platform_device *pdev)
mutex_init(&dev->lock);
- if (enable_stb && (dev->cpu_id == AMD_CPU_ID_YC || dev->cpu_id == AMD_CPU_ID_CB)) {
+ if (enable_stb && amd_pmc_is_stb_supported(dev)) {
err = amd_pmc_s2d_init(dev);
if (err)
goto err_pci_dev_put;
diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig
index d87986adf91e..3064bc8ea167 100644
--- a/drivers/platform/x86/amd/pmf/Kconfig
+++ b/drivers/platform/x86/amd/pmf/Kconfig
@@ -16,3 +16,14 @@ config AMD_PMF
To compile this driver as a module, choose M here: the module will
be called amd_pmf.
+
+config AMD_PMF_DEBUG
+ bool "PMF debug information"
+ depends on AMD_PMF
+ help
+ Enabling this option would give more debug information on the OEM fed
+ power setting values for each of the PMF feature. PMF driver gets this
+ information after evaluating a ACPI method and the information is stored
+ in the PMF config store.
+
+ Say Y here to enable more debug logs and Say N here if you are not sure.
diff --git a/drivers/platform/x86/amd/pmf/auto-mode.c b/drivers/platform/x86/amd/pmf/auto-mode.c
index 96a8e1832c05..02ff68be10d0 100644
--- a/drivers/platform/x86/amd/pmf/auto-mode.c
+++ b/drivers/platform/x86/amd/pmf/auto-mode.c
@@ -15,6 +15,100 @@
static struct auto_mode_mode_config config_store;
static const char *state_as_str(unsigned int state);
+#ifdef CONFIG_AMD_PMF_DEBUG
+static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data)
+{
+ struct auto_mode_mode_settings *its_mode;
+
+ pr_debug("Auto Mode Data - BEGIN\n");
+
+ /* time constant */
+ pr_debug("balanced_to_perf: %u ms\n",
+ data->transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant);
+ pr_debug("perf_to_balanced: %u ms\n",
+ data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant);
+ pr_debug("quiet_to_balanced: %u ms\n",
+ data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant);
+ pr_debug("balanced_to_quiet: %u ms\n",
+ data->transition[AUTO_TRANSITION_TO_QUIET].time_constant);
+
+ /* power floor */
+ pr_debug("pfloor_perf: %u mW\n", data->mode_set[AUTO_PERFORMANCE].power_floor);
+ pr_debug("pfloor_balanced: %u mW\n", data->mode_set[AUTO_BALANCE].power_floor);
+ pr_debug("pfloor_quiet: %u mW\n", data->mode_set[AUTO_QUIET].power_floor);
+
+ /* Power delta for mode change */
+ pr_debug("pd_balanced_to_perf: %u mW\n",
+ data->transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta);
+ pr_debug("pd_perf_to_balanced: %u mW\n",
+ data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta);
+ pr_debug("pd_quiet_to_balanced: %u mW\n",
+ data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta);
+ pr_debug("pd_balanced_to_quiet: %u mW\n",
+ data->transition[AUTO_TRANSITION_TO_QUIET].power_delta);
+
+ /* skin temperature limits */
+ its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP];
+ pr_debug("stt_apu_perf_on_lap: %u C\n",
+ its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);
+ pr_debug("stt_hs2_perf_on_lap: %u C\n",
+ its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);
+ pr_debug("stt_min_limit_perf_on_lap: %u mW\n", its_mode->power_control.stt_min);
+
+ its_mode = &data->mode_set[AUTO_PERFORMANCE];
+ pr_debug("stt_apu_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);
+ pr_debug("stt_hs2_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);
+ pr_debug("stt_min_limit_perf: %u mW\n", its_mode->power_control.stt_min);
+
+ its_mode = &data->mode_set[AUTO_BALANCE];
+ pr_debug("stt_apu_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);
+ pr_debug("stt_hs2_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);
+ pr_debug("stt_min_limit_balanced: %u mW\n", its_mode->power_control.stt_min);
+
+ its_mode = &data->mode_set[AUTO_QUIET];
+ pr_debug("stt_apu_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);
+ pr_debug("stt_hs2_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);
+ pr_debug("stt_min_limit_quiet: %u mW\n", its_mode->power_control.stt_min);
+
+ /* SPL based power limits */
+ its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP];
+ pr_debug("fppt_perf_on_lap: %u mW\n", its_mode->power_control.fppt);
+ pr_debug("sppt_perf_on_lap: %u mW\n", its_mode->power_control.sppt);
+ pr_debug("spl_perf_on_lap: %u mW\n", its_mode->power_control.spl);
+ pr_debug("sppt_apu_only_perf_on_lap: %u mW\n", its_mode->power_control.sppt_apu_only);
+
+ its_mode = &data->mode_set[AUTO_PERFORMANCE];
+ pr_debug("fppt_perf: %u mW\n", its_mode->power_control.fppt);
+ pr_debug("sppt_perf: %u mW\n", its_mode->power_control.sppt);
+ pr_debug("spl_perf: %u mW\n", its_mode->power_control.spl);
+ pr_debug("sppt_apu_only_perf: %u mW\n", its_mode->power_control.sppt_apu_only);
+
+ its_mode = &data->mode_set[AUTO_BALANCE];
+ pr_debug("fppt_balanced: %u mW\n", its_mode->power_control.fppt);
+ pr_debug("sppt_balanced: %u mW\n", its_mode->power_control.sppt);
+ pr_debug("spl_balanced: %u mW\n", its_mode->power_control.spl);
+ pr_debug("sppt_apu_only_balanced: %u mW\n", its_mode->power_control.sppt_apu_only);
+
+ its_mode = &data->mode_set[AUTO_QUIET];
+ pr_debug("fppt_quiet: %u mW\n", its_mode->power_control.fppt);
+ pr_debug("sppt_quiet: %u mW\n", its_mode->power_control.sppt);
+ pr_debug("spl_quiet: %u mW\n", its_mode->power_control.spl);
+ pr_debug("sppt_apu_only_quiet: %u mW\n", its_mode->power_control.sppt_apu_only);
+
+ /* Fan ID */
+ pr_debug("fan_id_perf: %lu\n",
+ data->mode_set[AUTO_PERFORMANCE].fan_control.fan_id);
+ pr_debug("fan_id_balanced: %lu\n",
+ data->mode_set[AUTO_BALANCE].fan_control.fan_id);
+ pr_debug("fan_id_quiet: %lu\n",
+ data->mode_set[AUTO_QUIET].fan_control.fan_id);
+
+ pr_debug("Auto Mode Data - END\n");
+}
+#else
+static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) {}
+#endif
+
static void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx,
struct auto_mode_mode_config *table)
{
@@ -85,11 +179,34 @@ void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t t
config_store.transition[i].applied = false;
update = true;
}
+
+#ifdef CONFIG_AMD_PMF_DEBUG
+ dev_dbg(dev->dev, "[AUTO MODE] average_power : %d mW mode: %s\n", avg_power,
+ state_as_str(config_store.current_mode));
+
+ dev_dbg(dev->dev, "[AUTO MODE] time: %lld ms timer: %u ms tc: %u ms\n",
+ time_elapsed_ms, config_store.transition[i].timer,
+ config_store.transition[i].time_constant);
+
+ dev_dbg(dev->dev, "[AUTO MODE] shiftup: %u pt: %u mW pf: %u mW pd: %u mW\n",
+ config_store.transition[i].shifting_up,
+ config_store.transition[i].power_threshold,
+ config_store.mode_set[i].power_floor,
+ config_store.transition[i].power_delta);
+#endif
}
dev_dbg(dev->dev, "[AUTO_MODE] avg power: %u mW mode: %s\n", avg_power,
state_as_str(config_store.current_mode));
+#ifdef CONFIG_AMD_PMF_DEBUG
+ dev_dbg(dev->dev, "[AUTO MODE] priority1: %u priority2: %u priority3: %u priority4: %u\n",
+ config_store.transition[0].applied,
+ config_store.transition[1].applied,
+ config_store.transition[2].applied,
+ config_store.transition[3].applied);
+#endif
+
if (update) {
for (j = 0; j < AUTO_TRANSITION_MAX; j++) {
/* Apply the mode with highest priority indentified */
@@ -140,6 +257,30 @@ static void amd_pmf_get_power_threshold(void)
config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_threshold =
config_store.mode_set[AUTO_PERFORMANCE].power_floor -
config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta;
+
+#ifdef CONFIG_AMD_PMF_DEBUG
+ pr_debug("[AUTO MODE TO_QUIET] pt: %u mW pf: %u mW pd: %u mW\n",
+ config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold,
+ config_store.mode_set[AUTO_BALANCE].power_floor,
+ config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta);
+
+ pr_debug("[AUTO MODE TO_PERFORMANCE] pt: %u mW pf: %u mW pd: %u mW\n",
+ config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold,
+ config_store.mode_set[AUTO_BALANCE].power_floor,
+ config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta);
+
+ pr_debug("[AUTO MODE QUIET_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n",
+ config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE]
+ .power_threshold,
+ config_store.mode_set[AUTO_QUIET].power_floor,
+ config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta);
+
+ pr_debug("[AUTO MODE PERFORMANCE_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n",
+ config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE]
+ .power_threshold,
+ config_store.mode_set[AUTO_PERFORMANCE].power_floor,
+ config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta);
+#endif
}
static const char *state_as_str(unsigned int state)
@@ -262,6 +403,8 @@ static void amd_pmf_load_defaults_auto_mode(struct amd_pmf_dev *dev)
/* set to initial default values */
config_store.current_mode = AUTO_BALANCE;
dev->socket_power_history_idx = -1;
+
+ amd_pmf_dump_auto_mode_defaults(&config_store);
}
int amd_pmf_reset_amt(struct amd_pmf_dev *dev)
diff --git a/drivers/platform/x86/amd/pmf/cnqf.c b/drivers/platform/x86/amd/pmf/cnqf.c
index 4beb22a19466..539b186e9027 100644
--- a/drivers/platform/x86/amd/pmf/cnqf.c
+++ b/drivers/platform/x86/amd/pmf/cnqf.c
@@ -13,6 +13,61 @@
static struct cnqf_config config_store;
+#ifdef CONFIG_AMD_PMF_DEBUG
+static const char *state_as_str_cnqf(unsigned int state)
+{
+ switch (state) {
+ case APMF_CNQF_TURBO:
+ return "turbo";
+ case APMF_CNQF_PERFORMANCE:
+ return "performance";
+ case APMF_CNQF_BALANCE:
+ return "balance";
+ case APMF_CNQF_QUIET:
+ return "quiet";
+ default:
+ return "Unknown CnQF State";
+ }
+}
+
+static void amd_pmf_cnqf_dump_defaults(struct apmf_dyn_slider_output *data, int idx)
+{
+ int i;
+
+ pr_debug("Dynamic Slider %s Defaults - BEGIN\n", idx ? "DC" : "AC");
+ pr_debug("size: %u\n", data->size);
+ pr_debug("flags: 0x%x\n", data->flags);
+
+ /* Time constants */
+ pr_debug("t_perf_to_turbo: %u ms\n", data->t_perf_to_turbo);
+ pr_debug("t_balanced_to_perf: %u ms\n", data->t_balanced_to_perf);
+ pr_debug("t_quiet_to_balanced: %u ms\n", data->t_quiet_to_balanced);
+ pr_debug("t_balanced_to_quiet: %u ms\n", data->t_balanced_to_quiet);
+ pr_debug("t_perf_to_balanced: %u ms\n", data->t_perf_to_balanced);
+ pr_debug("t_turbo_to_perf: %u ms\n", data->t_turbo_to_perf);
+
+ for (i = 0 ; i < CNQF_MODE_MAX ; i++) {
+ pr_debug("pfloor_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].pfloor);
+ pr_debug("fppt_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].fppt);
+ pr_debug("sppt_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].sppt);
+ pr_debug("sppt_apuonly_%s: %u mW\n",
+ state_as_str_cnqf(i), data->ps[i].sppt_apu_only);
+ pr_debug("spl_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].spl);
+ pr_debug("stt_minlimit_%s: %u mW\n",
+ state_as_str_cnqf(i), data->ps[i].stt_min_limit);
+ pr_debug("stt_skintemp_apu_%s: %u C\n", state_as_str_cnqf(i),
+ data->ps[i].stt_skintemp[STT_TEMP_APU]);
+ pr_debug("stt_skintemp_hs2_%s: %u C\n", state_as_str_cnqf(i),
+ data->ps[i].stt_skintemp[STT_TEMP_HS2]);
+ pr_debug("fan_id_%s: %u\n", state_as_str_cnqf(i), data->ps[i].fan_id);
+ }
+
+ pr_debug("Dynamic Slider %s Defaults - END\n", idx ? "DC" : "AC");
+}
+#else
+static void amd_pmf_cnqf_dump_defaults(struct apmf_dyn_slider_output *data, int idx) {}
+#endif
+
static int amd_pmf_set_cnqf(struct amd_pmf_dev *dev, int src, int idx,
struct cnqf_config *table)
{
@@ -120,6 +175,13 @@ int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_l
config_store.trans_param[src][i].count++;
tp = &config_store.trans_param[src][i];
+
+#ifdef CONFIG_AMD_PMF_DEBUG
+ dev_dbg(dev->dev, "avg_power: %u mW total_power: %u mW count: %u timer: %u ms\n",
+ avg_power, config_store.trans_param[src][i].total_power,
+ config_store.trans_param[src][i].count,
+ config_store.trans_param[src][i].timer);
+#endif
if (tp->timer >= tp->time_constant && tp->count) {
avg_power = tp->total_power / tp->count;
@@ -140,6 +202,18 @@ int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_l
dev_dbg(dev->dev, "[CNQF] Avg power: %u mW socket power: %u mW mode:%s\n",
avg_power, socket_power, state_as_str(config_store.current_mode));
+#ifdef CONFIG_AMD_PMF_DEBUG
+ dev_dbg(dev->dev, "[CNQF] priority1: %u priority2: %u priority3: %u\n",
+ config_store.trans_param[src][0].priority,
+ config_store.trans_param[src][1].priority,
+ config_store.trans_param[src][2].priority);
+
+ dev_dbg(dev->dev, "[CNQF] priority4: %u priority5: %u priority6: %u\n",
+ config_store.trans_param[src][3].priority,
+ config_store.trans_param[src][4].priority,
+ config_store.trans_param[src][5].priority);
+#endif
+
for (j = 0; j < CNQF_TRANSITION_MAX; j++) {
/* apply the highest priority */
if (config_store.trans_param[src][j].priority) {
@@ -284,6 +358,7 @@ static int amd_pmf_load_defaults_cnqf(struct amd_pmf_dev *dev)
return ret;
}
+ amd_pmf_cnqf_dump_defaults(&out, i);
amd_pmf_update_mode_set(i, &out);
amd_pmf_update_trans_data(i, &out);
amd_pmf_update_power_threshold(i);
diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
index bed762d47a14..445ff053b4df 100644
--- a/drivers/platform/x86/amd/pmf/sps.c
+++ b/drivers/platform/x86/amd/pmf/sps.c
@@ -12,6 +12,60 @@
static struct amd_pmf_static_slider_granular config_store;
+#ifdef CONFIG_AMD_PMF_DEBUG
+static const char *slider_as_str(unsigned int state)
+{
+ switch (state) {
+ case POWER_MODE_PERFORMANCE:
+ return "PERFORMANCE";
+ case POWER_MODE_BALANCED_POWER:
+ return "BALANCED_POWER";
+ case POWER_MODE_POWER_SAVER:
+ return "POWER_SAVER";
+ default:
+ return "Unknown Slider State";
+ }
+}
+
+static const char *source_as_str(unsigned int state)
+{
+ switch (state) {
+ case POWER_SOURCE_AC:
+ return "AC";
+ case POWER_SOURCE_DC:
+ return "DC";
+ default:
+ return "Unknown Power State";
+ }
+}
+
+static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data)
+{
+ int i, j;
+
+ pr_debug("Static Slider Data - BEGIN\n");
+
+ for (i = 0; i < POWER_SOURCE_MAX; i++) {
+ for (j = 0; j < POWER_MODE_MAX; j++) {
+ pr_debug("--- Source:%s Mode:%s ---\n", source_as_str(i), slider_as_str(j));
+ pr_debug("SPL: %u mW\n", data->prop[i][j].spl);
+ pr_debug("SPPT: %u mW\n", data->prop[i][j].sppt);
+ pr_debug("SPPT_ApuOnly: %u mW\n", data->prop[i][j].sppt_apu_only);
+ pr_debug("FPPT: %u mW\n", data->prop[i][j].fppt);
+ pr_debug("STTMinLimit: %u mW\n", data->prop[i][j].stt_min);
+ pr_debug("STT_SkinTempLimit_APU: %u C\n",
+ data->prop[i][j].stt_skin_temp[STT_TEMP_APU]);
+ pr_debug("STT_SkinTempLimit_HS2: %u C\n",
+ data->prop[i][j].stt_skin_temp[STT_TEMP_HS2]);
+ }
+ }
+
+ pr_debug("Static Slider Data - END\n");
+}
+#else
+static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data) {}
+#endif
+
static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev)
{
struct apmf_static_slider_granular_output output;
@@ -36,6 +90,7 @@ static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev)
idx++;
}
}
+ amd_pmf_dump_sps_defaults(&config_store);
}
void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index e02b4aea4f1e..cadbb557a108 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -278,7 +278,7 @@ static u32 gmux_mmio_read32(struct apple_gmux_data *gmux_data, int port)
iowrite8(GMUX_MMIO_READ | sizeof(val),
gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
gmux_mmio_wait(gmux_data);
- val = be32_to_cpu(ioread32(gmux_data->iomem_base));
+ val = ioread32be(gmux_data->iomem_base);
mutex_unlock(&gmux_data->index_lock);
return val;
@@ -288,7 +288,7 @@ static void gmux_mmio_write32(struct apple_gmux_data *gmux_data, int port,
u32 val)
{
mutex_lock(&gmux_data->index_lock);
- iowrite32(cpu_to_be32(val), gmux_data->iomem_base);
+ iowrite32be(val, gmux_data->iomem_base);
iowrite8(port & 0xff, gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
iowrite8(GMUX_MMIO_WRITE | sizeof(val),
gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
diff --git a/drivers/platform/x86/asus-tf103c-dock.c b/drivers/platform/x86/asus-tf103c-dock.c
index aeb1138464df..8f0f87637c5f 100644
--- a/drivers/platform/x86/asus-tf103c-dock.c
+++ b/drivers/platform/x86/asus-tf103c-dock.c
@@ -933,7 +933,7 @@ static struct i2c_driver tf103c_dock_driver = {
.pm = &tf103c_dock_pm_ops,
.acpi_match_table = tf103c_dock_acpi_match,
},
- .probe_new = tf103c_dock_probe,
+ .probe = tf103c_dock_probe,
.remove = tf103c_dock_remove,
};
module_i2c_driver(tf103c_dock_driver);
diff --git a/drivers/platform/x86/dell/dell-rbtn.c b/drivers/platform/x86/dell/dell-rbtn.c
index aa0e6c907494..c8fcb537fd65 100644
--- a/drivers/platform/x86/dell/dell-rbtn.c
+++ b/drivers/platform/x86/dell/dell-rbtn.c
@@ -395,16 +395,16 @@ static int rbtn_add(struct acpi_device *device)
return -EINVAL;
}
+ rbtn_data = devm_kzalloc(&device->dev, sizeof(*rbtn_data), GFP_KERNEL);
+ if (!rbtn_data)
+ return -ENOMEM;
+
ret = rbtn_acquire(device, true);
if (ret < 0) {
dev_err(&device->dev, "Cannot enable device\n");
return ret;
}
- rbtn_data = devm_kzalloc(&device->dev, sizeof(*rbtn_data), GFP_KERNEL);
- if (!rbtn_data)
- return -ENOMEM;
-
rbtn_data->type = type;
device->driver_data = rbtn_data;
@@ -420,10 +420,12 @@ static int rbtn_add(struct acpi_device *device)
break;
default:
ret = -EINVAL;
+ break;
}
+ if (ret)
+ rbtn_acquire(device, false);
return ret;
-
}
static void rbtn_remove(struct acpi_device *device)
@@ -442,7 +444,6 @@ static void rbtn_remove(struct acpi_device *device)
}
rbtn_acquire(device, false);
- device->driver_data = NULL;
}
static void rbtn_notify(struct acpi_device *device, u32 event)
diff --git a/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c b/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c
index 0285b47d99d1..b68dd11cb892 100644
--- a/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c
+++ b/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c
@@ -303,16 +303,13 @@ union acpi_object *get_wmiobj_pointer(int instance_id, const char *guid_string)
*/
int get_instance_count(const char *guid_string)
{
- union acpi_object *wmi_obj = NULL;
- int i = 0;
+ int ret;
- do {
- kfree(wmi_obj);
- wmi_obj = get_wmiobj_pointer(i, guid_string);
- i++;
- } while (wmi_obj);
+ ret = wmi_instance_count(guid_string);
+ if (ret < 0)
+ return 0;
- return (i-1);
+ return ret;
}
/**
diff --git a/drivers/platform/x86/gigabyte-wmi.c b/drivers/platform/x86/gigabyte-wmi.c
index 2a426040f749..f6ba88baee4d 100644
--- a/drivers/platform/x86/gigabyte-wmi.c
+++ b/drivers/platform/x86/gigabyte-wmi.c
@@ -5,7 +5,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/acpi.h>
-#include <linux/dmi.h>
#include <linux/hwmon.h>
#include <linux/module.h>
#include <linux/wmi.h>
@@ -13,10 +12,6 @@
#define GIGABYTE_WMI_GUID "DEADBEEF-2001-0000-00A0-C90629100000"
#define NUM_TEMPERATURE_SENSORS 6
-static bool force_load;
-module_param(force_load, bool, 0444);
-MODULE_PARM_DESC(force_load, "Force loading on unknown platform");
-
static u8 usable_sensors_mask;
enum gigabyte_wmi_commandtype {
@@ -99,7 +94,7 @@ static umode_t gigabyte_wmi_hwmon_is_visible(const void *data, enum hwmon_sensor
return usable_sensors_mask & BIT(channel) ? 0444 : 0;
}
-static const struct hwmon_channel_info *gigabyte_wmi_hwmon_info[] = {
+static const struct hwmon_channel_info * const gigabyte_wmi_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp,
HWMON_T_INPUT,
HWMON_T_INPUT,
@@ -133,49 +128,10 @@ static u8 gigabyte_wmi_detect_sensor_usability(struct wmi_device *wdev)
return r;
}
-#define DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME(name) \
- { .matches = { \
- DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), \
- DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \
- }}
-
-static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = {
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("A320M-S2H V2-CF"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H-CF"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H WIFI-CF"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M S2H V2"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE AX V2"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE V2"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 GAMING X V2"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550I AORUS PRO AX"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M AORUS PRO-P"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M DS3H"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B650 AORUS ELITE AX"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B660 GAMING X DDR4"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B660I AORUS PRO DDR4"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z390 I AORUS PRO WIFI-CF"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z490 AORUS ELITE AC"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 AORUS ELITE"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 AORUS ELITE WIFI"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 GAMING X"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 I AORUS PRO WIFI"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 UD"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570S AORUS ELITE"),
- DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z690M AORUS ELITE AX DDR4"),
- { }
-};
-
static int gigabyte_wmi_probe(struct wmi_device *wdev, const void *context)
{
struct device *hwmon_dev;
- if (!dmi_check_system(gigabyte_wmi_known_working_platforms)) {
- if (!force_load)
- return -ENODEV;
- dev_warn(&wdev->dev, "Forcing load on unknown platform");
- }
-
usable_sensors_mask = gigabyte_wmi_detect_sensor_usability(wdev);
if (!usable_sensors_mask) {
dev_info(&wdev->dev, "No temperature sensors usable");
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 6364ae262705..e76e5458db35 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -66,6 +66,11 @@ static const char *const omen_thermal_profile_force_v0_boards[] = {
"8607", "8746", "8747", "8749", "874A", "8748"
};
+/* DMI Board names of Victus laptops */
+static const char * const victus_thermal_profile_boards[] = {
+ "8A25"
+};
+
enum hp_wmi_radio {
HPWMI_WIFI = 0x0,
HPWMI_BLUETOOTH = 0x1,
@@ -90,6 +95,7 @@ enum hp_wmi_event_ids {
HPWMI_PEAKSHIFT_PERIOD = 0x0F,
HPWMI_BATTERY_CHARGE_PERIOD = 0x10,
HPWMI_SANITIZATION_MODE = 0x17,
+ HPWMI_CAMERA_TOGGLE = 0x1A,
HPWMI_OMEN_KEY = 0x1D,
HPWMI_SMART_EXPERIENCE_APP = 0x21,
};
@@ -176,6 +182,12 @@ enum hp_thermal_profile_omen_v1 {
HP_OMEN_V1_THERMAL_PROFILE_COOL = 0x50,
};
+enum hp_thermal_profile_victus {
+ HP_VICTUS_THERMAL_PROFILE_DEFAULT = 0x00,
+ HP_VICTUS_THERMAL_PROFILE_PERFORMANCE = 0x01,
+ HP_VICTUS_THERMAL_PROFILE_QUIET = 0x03,
+};
+
enum hp_thermal_profile {
HP_THERMAL_PROFILE_PERFORMANCE = 0x00,
HP_THERMAL_PROFILE_DEFAULT = 0x01,
@@ -222,6 +234,7 @@ static const struct key_entry hp_wmi_keymap[] = {
{ KE_IGNORE, 0x121a4, }, /* Win Lock Off */
{ KE_KEY, 0x21a5, { KEY_PROG2 } }, /* HP Omen Key */
{ KE_KEY, 0x21a7, { KEY_FN_ESC } },
+ { KE_KEY, 0x21a8, { KEY_PROG2 } }, /* HP Envy x360 programmable key */
{ KE_KEY, 0x21a9, { KEY_TOUCHPAD_OFF } },
{ KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } },
{ KE_KEY, 0x231b, { KEY_HELP } },
@@ -229,6 +242,7 @@ static const struct key_entry hp_wmi_keymap[] = {
};
static struct input_dev *hp_wmi_input_dev;
+static struct input_dev *camera_shutter_input_dev;
static struct platform_device *hp_wmi_platform_dev;
static struct platform_profile_handler platform_profile_handler;
static bool platform_profile_support;
@@ -740,6 +754,33 @@ static ssize_t postcode_store(struct device *dev, struct device_attribute *attr,
return count;
}
+static int camera_shutter_input_setup(void)
+{
+ int err;
+
+ camera_shutter_input_dev = input_allocate_device();
+ if (!camera_shutter_input_dev)
+ return -ENOMEM;
+
+ camera_shutter_input_dev->name = "HP WMI camera shutter";
+ camera_shutter_input_dev->phys = "wmi/input1";
+ camera_shutter_input_dev->id.bustype = BUS_HOST;
+
+ __set_bit(EV_SW, camera_shutter_input_dev->evbit);
+ __set_bit(SW_CAMERA_LENS_COVER, camera_shutter_input_dev->swbit);
+
+ err = input_register_device(camera_shutter_input_dev);
+ if (err)
+ goto err_free_dev;
+
+ return 0;
+
+ err_free_dev:
+ input_free_device(camera_shutter_input_dev);
+ camera_shutter_input_dev = NULL;
+ return err;
+}
+
static DEVICE_ATTR_RO(display);
static DEVICE_ATTR_RO(hddtemp);
static DEVICE_ATTR_RW(als);
@@ -816,7 +857,6 @@ static void hp_wmi_notify(u32 value, void *context)
case HPWMI_SMART_ADAPTER:
break;
case HPWMI_BEZEL_BUTTON:
- case HPWMI_OMEN_KEY:
key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY);
if (key_code < 0)
break;
@@ -825,6 +865,16 @@ static void hp_wmi_notify(u32 value, void *context)
key_code, 1, true))
pr_info("Unknown key code - 0x%x\n", key_code);
break;
+ case HPWMI_OMEN_KEY:
+ if (event_data) /* Only should be true for HP Omen */
+ key_code = event_data;
+ else
+ key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY);
+
+ if (!sparse_keymap_report_event(hp_wmi_input_dev,
+ key_code, 1, true))
+ pr_info("Unknown key code - 0x%x\n", key_code);
+ break;
case HPWMI_WIRELESS:
if (rfkill2_count) {
hp_wmi_rfkill2_refresh();
@@ -867,6 +917,20 @@ static void hp_wmi_notify(u32 value, void *context)
break;
case HPWMI_SANITIZATION_MODE:
break;
+ case HPWMI_CAMERA_TOGGLE:
+ if (!camera_shutter_input_dev)
+ if (camera_shutter_input_setup()) {
+ pr_err("Failed to setup camera shutter input device\n");
+ break;
+ }
+ if (event_data == 0xff)
+ input_report_switch(camera_shutter_input_dev, SW_CAMERA_LENS_COVER, 1);
+ else if (event_data == 0xfe)
+ input_report_switch(camera_shutter_input_dev, SW_CAMERA_LENS_COVER, 0);
+ else
+ pr_warn("Unknown camera shutter state - 0x%x\n", event_data);
+ input_sync(camera_shutter_input_dev);
+ break;
case HPWMI_SMART_EXPERIENCE_APP:
break;
default:
@@ -1246,6 +1310,70 @@ static int hp_wmi_platform_profile_set(struct platform_profile_handler *pprof,
return 0;
}
+static bool is_victus_thermal_profile(void)
+{
+ const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
+
+ if (!board_name)
+ return false;
+
+ return match_string(victus_thermal_profile_boards,
+ ARRAY_SIZE(victus_thermal_profile_boards),
+ board_name) >= 0;
+}
+
+static int platform_profile_victus_get(struct platform_profile_handler *pprof,
+ enum platform_profile_option *profile)
+{
+ int tp;
+
+ tp = omen_thermal_profile_get();
+ if (tp < 0)
+ return tp;
+
+ switch (tp) {
+ case HP_VICTUS_THERMAL_PROFILE_PERFORMANCE:
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ break;
+ case HP_VICTUS_THERMAL_PROFILE_DEFAULT:
+ *profile = PLATFORM_PROFILE_BALANCED;
+ break;
+ case HP_VICTUS_THERMAL_PROFILE_QUIET:
+ *profile = PLATFORM_PROFILE_QUIET;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int platform_profile_victus_set(struct platform_profile_handler *pprof,
+ enum platform_profile_option profile)
+{
+ int err, tp;
+
+ switch (profile) {
+ case PLATFORM_PROFILE_PERFORMANCE:
+ tp = HP_VICTUS_THERMAL_PROFILE_PERFORMANCE;
+ break;
+ case PLATFORM_PROFILE_BALANCED:
+ tp = HP_VICTUS_THERMAL_PROFILE_DEFAULT;
+ break;
+ case PLATFORM_PROFILE_QUIET:
+ tp = HP_VICTUS_THERMAL_PROFILE_QUIET;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ err = omen_thermal_profile_set(tp);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
static int thermal_profile_setup(void)
{
int err, tp;
@@ -1266,6 +1394,25 @@ static int thermal_profile_setup(void)
platform_profile_handler.profile_get = platform_profile_omen_get;
platform_profile_handler.profile_set = platform_profile_omen_set;
+
+ set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
+ } else if (is_victus_thermal_profile()) {
+ tp = omen_thermal_profile_get();
+ if (tp < 0)
+ return tp;
+
+ /*
+ * call thermal profile write command to ensure that the
+ * firmware correctly sets the OEM variables
+ */
+ err = omen_thermal_profile_set(tp);
+ if (err < 0)
+ return err;
+
+ platform_profile_handler.profile_get = platform_profile_victus_get;
+ platform_profile_handler.profile_set = platform_profile_victus_set;
+
+ set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
} else {
tp = thermal_profile_get();
@@ -1284,9 +1431,9 @@ static int thermal_profile_setup(void)
platform_profile_handler.profile_set = hp_wmi_platform_profile_set;
set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
+ set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
}
- set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
set_bit(PLATFORM_PROFILE_BALANCED, platform_profile_handler.choices);
set_bit(PLATFORM_PROFILE_PERFORMANCE, platform_profile_handler.choices);
@@ -1483,7 +1630,7 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
}
}
-static const struct hwmon_channel_info *info[] = {
+static const struct hwmon_channel_info * const info[] = {
HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT),
HWMON_CHANNEL_INFO(pwm, HWMON_PWM_ENABLE),
NULL
@@ -1565,6 +1712,9 @@ static void __exit hp_wmi_exit(void)
if (wmi_has_guid(HPWMI_EVENT_GUID))
hp_wmi_input_destroy();
+ if (camera_shutter_input_dev)
+ input_unregister_device(camera_shutter_input_dev);
+
if (hp_wmi_platform_dev) {
platform_device_unregister(hp_wmi_platform_dev);
platform_driver_unregister(&hp_wmi_driver);
diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c
index 399f0623ca1b..61aeca804ba2 100644
--- a/drivers/platform/x86/intel/int3472/clk_and_regulator.c
+++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c
@@ -5,6 +5,7 @@
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/device.h>
+#include <linux/dmi.h>
#include <linux/gpio/consumer.h>
#include <linux/regulator/driver.h>
#include <linux/slab.h>
@@ -12,6 +13,41 @@
#include "common.h"
/*
+ * 82c0d13a-78c5-4244-9bb1-eb8b539a8d11
+ * This _DSM GUID allows controlling the sensor clk when it is not controlled
+ * through a GPIO.
+ */
+static const guid_t img_clk_guid =
+ GUID_INIT(0x82c0d13a, 0x78c5, 0x4244,
+ 0x9b, 0xb1, 0xeb, 0x8b, 0x53, 0x9a, 0x8d, 0x11);
+
+static void skl_int3472_enable_clk(struct int3472_clock *clk, int enable)
+{
+ struct int3472_discrete_device *int3472 = to_int3472_device(clk);
+ union acpi_object args[3];
+ union acpi_object argv4;
+
+ if (clk->ena_gpio) {
+ gpiod_set_value_cansleep(clk->ena_gpio, enable);
+ return;
+ }
+
+ args[0].integer.type = ACPI_TYPE_INTEGER;
+ args[0].integer.value = clk->imgclk_index;
+ args[1].integer.type = ACPI_TYPE_INTEGER;
+ args[1].integer.value = enable;
+ args[2].integer.type = ACPI_TYPE_INTEGER;
+ args[2].integer.value = 1;
+
+ argv4.type = ACPI_TYPE_PACKAGE;
+ argv4.package.count = 3;
+ argv4.package.elements = args;
+
+ acpi_evaluate_dsm(acpi_device_handle(int3472->adev), &img_clk_guid,
+ 0, 1, &argv4);
+}
+
+/*
* The regulators have to have .ops to be valid, but the only ops we actually
* support are .enable and .disable which are handled via .ena_gpiod. Pass an
* empty struct to clear the check without lying about capabilities.
@@ -20,17 +56,13 @@ static const struct regulator_ops int3472_gpio_regulator_ops;
static int skl_int3472_clk_prepare(struct clk_hw *hw)
{
- struct int3472_gpio_clock *clk = to_int3472_clk(hw);
-
- gpiod_set_value_cansleep(clk->ena_gpio, 1);
+ skl_int3472_enable_clk(to_int3472_clk(hw), 1);
return 0;
}
static void skl_int3472_clk_unprepare(struct clk_hw *hw)
{
- struct int3472_gpio_clock *clk = to_int3472_clk(hw);
-
- gpiod_set_value_cansleep(clk->ena_gpio, 0);
+ skl_int3472_enable_clk(to_int3472_clk(hw), 0);
}
static int skl_int3472_clk_enable(struct clk_hw *hw)
@@ -73,7 +105,7 @@ static unsigned int skl_int3472_get_clk_frequency(struct int3472_discrete_device
static unsigned long skl_int3472_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct int3472_gpio_clock *clk = to_int3472_clk(hw);
+ struct int3472_clock *clk = to_int3472_clk(hw);
return clk->frequency;
}
@@ -86,8 +118,51 @@ static const struct clk_ops skl_int3472_clock_ops = {
.recalc_rate = skl_int3472_clk_recalc_rate,
};
-int skl_int3472_register_clock(struct int3472_discrete_device *int3472,
- struct acpi_resource_gpio *agpio, u32 polarity)
+int skl_int3472_register_dsm_clock(struct int3472_discrete_device *int3472)
+{
+ struct acpi_device *adev = int3472->adev;
+ struct clk_init_data init = {
+ .ops = &skl_int3472_clock_ops,
+ .flags = CLK_GET_RATE_NOCACHE,
+ };
+ int ret;
+
+ if (int3472->clock.cl)
+ return 0; /* A GPIO controlled clk has already been registered */
+
+ if (!acpi_check_dsm(adev->handle, &img_clk_guid, 0, BIT(1)))
+ return 0; /* DSM clock control is not available */
+
+ init.name = kasprintf(GFP_KERNEL, "%s-clk", acpi_dev_name(adev));
+ if (!init.name)
+ return -ENOMEM;
+
+ int3472->clock.frequency = skl_int3472_get_clk_frequency(int3472);
+ int3472->clock.clk_hw.init = &init;
+ int3472->clock.clk = clk_register(&adev->dev, &int3472->clock.clk_hw);
+ if (IS_ERR(int3472->clock.clk)) {
+ ret = PTR_ERR(int3472->clock.clk);
+ goto out_free_init_name;
+ }
+
+ int3472->clock.cl = clkdev_create(int3472->clock.clk, NULL, int3472->sensor_name);
+ if (!int3472->clock.cl) {
+ ret = -ENOMEM;
+ goto err_unregister_clk;
+ }
+
+ kfree(init.name);
+ return 0;
+
+err_unregister_clk:
+ clk_unregister(int3472->clock.clk);
+out_free_init_name:
+ kfree(init.name);
+ return ret;
+}
+
+int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472,
+ struct acpi_resource_gpio *agpio, u32 polarity)
{
char *path = agpio->resource_source.string_ptr;
struct clk_init_data init = {
@@ -160,32 +235,73 @@ void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472)
gpiod_put(int3472->clock.ena_gpio);
}
+/*
+ * The INT3472 device is going to be the only supplier of a regulator for
+ * the sensor device. But unlike the clk framework the regulator framework
+ * does not allow matching by consumer-device-name only.
+ *
+ * Ideally all sensor drivers would use "avdd" as supply-id. But for drivers
+ * where this cannot be changed because another supply-id is already used in
+ * e.g. DeviceTree files an alias for the other supply-id can be added here.
+ *
+ * Do not forget to update GPIO_REGULATOR_SUPPLY_MAP_COUNT when changing this.
+ */
+static const char * const skl_int3472_regulator_map_supplies[] = {
+ "avdd",
+ "AVDD",
+};
+
+static_assert(ARRAY_SIZE(skl_int3472_regulator_map_supplies) ==
+ GPIO_REGULATOR_SUPPLY_MAP_COUNT);
+
+/*
+ * On some models there is a single GPIO regulator which is shared between
+ * sensors and only listed in the ACPI resources of one sensor.
+ * This DMI table contains the name of the second sensor. This is used to add
+ * entries for the second sensor to the supply_map.
+ */
+const struct dmi_system_id skl_int3472_regulator_second_sensor[] = {
+ {
+ /* Lenovo Miix 510-12IKB */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "MIIX 510-12IKB"),
+ },
+ .driver_data = "i2c-OVTI2680:00",
+ },
+ { }
+};
+
int skl_int3472_register_regulator(struct int3472_discrete_device *int3472,
struct acpi_resource_gpio *agpio)
{
- const struct int3472_sensor_config *sensor_config;
char *path = agpio->resource_source.string_ptr;
- struct regulator_consumer_supply supply_map;
struct regulator_init_data init_data = { };
struct regulator_config cfg = { };
- int ret;
-
- sensor_config = int3472->sensor_config;
- if (IS_ERR(sensor_config)) {
- dev_err(int3472->dev, "No sensor module config\n");
- return PTR_ERR(sensor_config);
- }
-
- if (!sensor_config->supply_map.supply) {
- dev_err(int3472->dev, "No supply name defined\n");
- return -ENODEV;
+ const char *second_sensor = NULL;
+ const struct dmi_system_id *id;
+ int i, j, ret;
+
+ id = dmi_first_match(skl_int3472_regulator_second_sensor);
+ if (id)
+ second_sensor = id->driver_data;
+
+ for (i = 0, j = 0; i < ARRAY_SIZE(skl_int3472_regulator_map_supplies); i++) {
+ int3472->regulator.supply_map[j].supply = skl_int3472_regulator_map_supplies[i];
+ int3472->regulator.supply_map[j].dev_name = int3472->sensor_name;
+ j++;
+
+ if (second_sensor) {
+ int3472->regulator.supply_map[j].supply =
+ skl_int3472_regulator_map_supplies[i];
+ int3472->regulator.supply_map[j].dev_name = second_sensor;
+ j++;
+ }
}
init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
- init_data.num_consumer_supplies = 1;
- supply_map = sensor_config->supply_map;
- supply_map.dev_name = int3472->sensor_name;
- init_data.consumer_supplies = &supply_map;
+ init_data.consumer_supplies = int3472->regulator.supply_map;
+ init_data.num_consumer_supplies = j;
snprintf(int3472->regulator.regulator_name,
sizeof(int3472->regulator.regulator_name), "%s-regulator",
diff --git a/drivers/platform/x86/intel/int3472/common.h b/drivers/platform/x86/intel/int3472/common.h
index 61688e450ce5..9f29baa13860 100644
--- a/drivers/platform/x86/intel/int3472/common.h
+++ b/drivers/platform/x86/intel/int3472/common.h
@@ -28,6 +28,7 @@
#define GPIO_REGULATOR_NAME_LENGTH 21
#define GPIO_REGULATOR_SUPPLY_NAME_LENGTH 9
+#define GPIO_REGULATOR_SUPPLY_MAP_COUNT 2
#define INT3472_LED_MAX_NAME_LEN 32
@@ -43,7 +44,7 @@
}
#define to_int3472_clk(hw) \
- container_of(hw, struct int3472_gpio_clock, clk_hw)
+ container_of(hw, struct int3472_clock, clk_hw)
#define to_int3472_device(clk) \
container_of(clk, struct int3472_discrete_device, clock)
@@ -64,18 +65,9 @@ struct int3472_cldb {
u8 control_logic_type;
u8 control_logic_id;
u8 sensor_card_sku;
- u8 reserved[28];
-};
-
-struct int3472_gpio_function_remap {
- const char *documented;
- const char *actual;
-};
-
-struct int3472_sensor_config {
- const char *sensor_module_name;
- struct regulator_consumer_supply supply_map;
- const struct int3472_gpio_function_remap *function_maps;
+ u8 reserved[10];
+ u8 clock_source;
+ u8 reserved2[17];
};
struct int3472_discrete_device {
@@ -87,6 +79,8 @@ struct int3472_discrete_device {
const struct int3472_sensor_config *sensor_config;
struct int3472_gpio_regulator {
+ /* SUPPLY_MAP_COUNT * 2 to make room for second sensor mappings */
+ struct regulator_consumer_supply supply_map[GPIO_REGULATOR_SUPPLY_MAP_COUNT * 2];
char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
struct gpio_desc *gpio;
@@ -94,12 +88,13 @@ struct int3472_discrete_device {
struct regulator_desc rdesc;
} regulator;
- struct int3472_gpio_clock {
+ struct int3472_clock {
struct clk *clk;
struct clk_hw clk_hw;
struct clk_lookup *cl;
struct gpio_desc *ena_gpio;
u32 frequency;
+ u8 imgclk_index;
} clock;
struct int3472_pled {
@@ -121,8 +116,9 @@ int skl_int3472_get_sensor_adev_and_name(struct device *dev,
struct acpi_device **sensor_adev_ret,
const char **name_ret);
-int skl_int3472_register_clock(struct int3472_discrete_device *int3472,
- struct acpi_resource_gpio *agpio, u32 polarity);
+int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472,
+ struct acpi_resource_gpio *agpio, u32 polarity);
+int skl_int3472_register_dsm_clock(struct int3472_discrete_device *int3472);
void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472);
int skl_int3472_register_regulator(struct int3472_discrete_device *int3472,
diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c
index ef020e23e596..e33c2d75975c 100644
--- a/drivers/platform/x86/intel/int3472/discrete.c
+++ b/drivers/platform/x86/intel/int3472/discrete.c
@@ -2,6 +2,7 @@
/* Author: Dan Scally <djrscally@gmail.com> */
#include <linux/acpi.h>
+#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
@@ -25,6 +26,10 @@ static const guid_t int3472_gpio_guid =
GUID_INIT(0x79234640, 0x9e10, 0x4fea,
0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f);
+#define INT3472_GPIO_DSM_TYPE GENMASK(7, 0)
+#define INT3472_GPIO_DSM_PIN GENMASK(15, 8)
+#define INT3472_GPIO_DSM_SENSOR_ON_VAL GENMASK(31, 24)
+
/*
* 822ace8f-2814-4174-a56b-5f029fe079ee
* This _DSM GUID returns a string from the sensor device, which acts as a
@@ -34,69 +39,23 @@ static const guid_t cio2_sensor_module_guid =
GUID_INIT(0x822ace8f, 0x2814, 0x4174,
0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee);
-/*
- * Here follows platform specific mapping information that we can pass to
- * the functions mapping resources to the sensors. Where the sensors have
- * a power enable pin defined in DSDT we need to provide a supply name so
- * the sensor drivers can find the regulator. The device name will be derived
- * from the sensor's ACPI device within the code. Optionally, we can provide a
- * NULL terminated array of function name mappings to deal with any platform
- * specific deviations from the documented behaviour of GPIOs.
- *
- * Map a GPIO function name to NULL to prevent the driver from mapping that
- * GPIO at all.
- */
-
-static const struct int3472_gpio_function_remap ov2680_gpio_function_remaps[] = {
- { "reset", NULL },
- { "powerdown", "reset" },
- { }
-};
-
-static const struct int3472_sensor_config int3472_sensor_configs[] = {
- /* Lenovo Miix 510-12ISK - OV2680, Front */
- { "GNDF140809R", { 0 }, ov2680_gpio_function_remaps },
- /* Lenovo Miix 510-12ISK - OV5648, Rear */
- { "GEFF150023R", REGULATOR_SUPPLY("avdd", NULL), NULL },
- /* Surface Go 1&2 - OV5693, Front */
- { "YHCU", REGULATOR_SUPPLY("avdd", NULL), NULL },
-};
-
-static const struct int3472_sensor_config *
-skl_int3472_get_sensor_module_config(struct int3472_discrete_device *int3472)
+static void skl_int3472_log_sensor_module_name(struct int3472_discrete_device *int3472)
{
union acpi_object *obj;
- unsigned int i;
obj = acpi_evaluate_dsm_typed(int3472->sensor->handle,
&cio2_sensor_module_guid, 0x00,
0x01, NULL, ACPI_TYPE_STRING);
-
- if (!obj) {
- dev_err(int3472->dev,
- "Failed to get sensor module string from _DSM\n");
- return ERR_PTR(-ENODEV);
+ if (obj) {
+ dev_dbg(int3472->dev, "Sensor module id: '%s'\n", obj->string.pointer);
+ ACPI_FREE(obj);
}
-
- for (i = 0; i < ARRAY_SIZE(int3472_sensor_configs); i++) {
- if (!strcmp(int3472_sensor_configs[i].sensor_module_name,
- obj->string.pointer))
- break;
- }
-
- ACPI_FREE(obj);
-
- if (i >= ARRAY_SIZE(int3472_sensor_configs))
- return ERR_PTR(-EINVAL);
-
- return &int3472_sensor_configs[i];
}
static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472,
struct acpi_resource_gpio *agpio,
const char *func, u32 polarity)
{
- const struct int3472_sensor_config *sensor_config;
char *path = agpio->resource_source.string_ptr;
struct gpiod_lookup *table_entry;
struct acpi_device *adev;
@@ -108,22 +67,6 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347
return -EINVAL;
}
- sensor_config = int3472->sensor_config;
- if (!IS_ERR(sensor_config) && sensor_config->function_maps) {
- const struct int3472_gpio_function_remap *remap;
-
- for (remap = sensor_config->function_maps; remap->documented; remap++) {
- if (!strcmp(func, remap->documented)) {
- func = remap->actual;
- break;
- }
- }
- }
-
- /* Functions mapped to NULL should not be mapped to the sensor */
- if (!func)
- return 0;
-
status = acpi_get_handle(NULL, path, &handle);
if (ACPI_FAILURE(status))
return -EINVAL;
@@ -211,8 +154,8 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
{
struct int3472_discrete_device *int3472 = data;
struct acpi_resource_gpio *agpio;
+ u8 active_value, pin, type;
union acpi_object *obj;
- u8 active_value, type;
const char *err_msg;
const char *func;
u32 polarity;
@@ -236,12 +179,17 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
return 1;
}
- type = obj->integer.value & 0xff;
+ type = FIELD_GET(INT3472_GPIO_DSM_TYPE, obj->integer.value);
int3472_get_func_and_polarity(type, &func, &polarity);
- /* If bits 31-24 of the _DSM entry are all 0 then the signal is inverted */
- active_value = obj->integer.value >> 24;
+ pin = FIELD_GET(INT3472_GPIO_DSM_PIN, obj->integer.value);
+ if (pin != agpio->pin_table[0])
+ dev_warn(int3472->dev, "%s %s pin number mismatch _DSM %d resource %d\n",
+ func, agpio->resource_source.string_ptr, pin,
+ agpio->pin_table[0]);
+
+ active_value = FIELD_GET(INT3472_GPIO_DSM_SENSOR_ON_VAL, obj->integer.value);
if (!active_value)
polarity ^= GPIO_ACTIVE_LOW;
@@ -258,7 +206,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
break;
case INT3472_GPIO_TYPE_CLK_ENABLE:
- ret = skl_int3472_register_clock(int3472, agpio, polarity);
+ ret = skl_int3472_register_gpio_clock(int3472, agpio, polarity);
if (ret)
err_msg = "Failed to register clock\n";
@@ -297,11 +245,7 @@ static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472)
LIST_HEAD(resource_list);
int ret;
- /*
- * No error check, because not having a sensor config is not necessarily
- * a failure mode.
- */
- int3472->sensor_config = skl_int3472_get_sensor_module_config(int3472);
+ skl_int3472_log_sensor_module_name(int3472);
ret = acpi_dev_get_resources(int3472->adev, &resource_list,
skl_int3472_handle_gpio_resources,
@@ -311,6 +255,11 @@ static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472)
acpi_dev_free_resource_list(&resource_list);
+ /* Register _DSM based clock (no-op if a GPIO clock was already registered) */
+ ret = skl_int3472_register_dsm_clock(int3472);
+ if (ret < 0)
+ return ret;
+
int3472->gpios.dev_id = int3472->sensor_name;
gpiod_add_lookup_table(&int3472->gpios);
@@ -356,6 +305,7 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev)
int3472->adev = adev;
int3472->dev = &pdev->dev;
platform_set_drvdata(pdev, int3472);
+ int3472->clock.imgclk_index = cldb.clock_source;
ret = skl_int3472_get_sensor_adev_and_name(&pdev->dev, &int3472->sensor,
&int3472->sensor_name);
diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c
index 5b8d1a9620a5..1e107fd49f82 100644
--- a/drivers/platform/x86/intel/int3472/tps68470.c
+++ b/drivers/platform/x86/intel/int3472/tps68470.c
@@ -250,7 +250,7 @@ static struct i2c_driver int3472_tps68470 = {
.name = "int3472-tps68470",
.acpi_match_table = int3472_device_id,
},
- .probe_new = skl_int3472_tps68470_probe,
+ .probe = skl_int3472_tps68470_probe,
.remove = skl_int3472_tps68470_remove,
};
module_i2c_driver(int3472_tps68470);
diff --git a/drivers/platform/x86/intel/pmc/Makefile b/drivers/platform/x86/intel/pmc/Makefile
index f96bc2e19503..3a4cf1cbc1ca 100644
--- a/drivers/platform/x86/intel/pmc/Makefile
+++ b/drivers/platform/x86/intel/pmc/Makefile
@@ -3,8 +3,8 @@
# Intel x86 Platform-Specific Drivers
#
-intel_pmc_core-y := core.o spt.o cnp.o icl.o tgl.o \
- adl.o mtl.o
+intel_pmc_core-y := core.o core_ssram.o spt.o cnp.o \
+ icl.o tgl.o adl.o mtl.o
obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o
intel_pmc_core_pltdrv-y := pltdrv.o
obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core_pltdrv.o
diff --git a/drivers/platform/x86/intel/pmc/adl.c b/drivers/platform/x86/intel/pmc/adl.c
index 5cbd40979f2a..5006008e01be 100644
--- a/drivers/platform/x86/intel/pmc/adl.c
+++ b/drivers/platform/x86/intel/pmc/adl.c
@@ -309,17 +309,21 @@ const struct pmc_reg_map adl_reg_map = {
.lpm_live_status_offset = ADL_LPM_LIVE_STATUS_OFFSET,
};
-void adl_core_configure(struct pmc_dev *pmcdev)
+int adl_core_init(struct pmc_dev *pmcdev)
{
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ int ret;
+
+ pmc->map = &adl_reg_map;
+ ret = get_primary_reg_base(pmc);
+ if (ret)
+ return ret;
+
/* Due to a hardware limitation, the GBE LTR blocks PC10
* when a cable is attached. Tell the PMC to ignore it.
*/
dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n");
pmc_core_send_ltr_ignore(pmcdev, 3);
-}
-void adl_core_init(struct pmc_dev *pmcdev)
-{
- pmcdev->map = &adl_reg_map;
- pmcdev->core_configure = adl_core_configure;
+ return 0;
}
diff --git a/drivers/platform/x86/intel/pmc/cnp.c b/drivers/platform/x86/intel/pmc/cnp.c
index 7fb38815c4eb..420aaa1d7c76 100644
--- a/drivers/platform/x86/intel/pmc/cnp.c
+++ b/drivers/platform/x86/intel/pmc/cnp.c
@@ -204,7 +204,21 @@ const struct pmc_reg_map cnp_reg_map = {
.etr3_offset = ETR3_OFFSET,
};
-void cnp_core_init(struct pmc_dev *pmcdev)
+int cnp_core_init(struct pmc_dev *pmcdev)
{
- pmcdev->map = &cnp_reg_map;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ int ret;
+
+ pmc->map = &cnp_reg_map;
+ ret = get_primary_reg_base(pmc);
+ if (ret)
+ return ret;
+
+ /* Due to a hardware limitation, the GBE LTR blocks PC10
+ * when a cable is attached. Tell the PMC to ignore it.
+ */
+ dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n");
+ pmc_core_send_ltr_ignore(pmcdev, 3);
+
+ return 0;
}
diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c
index da6e7206d38b..5a36b3f77bc5 100644
--- a/drivers/platform/x86/intel/pmc/core.c
+++ b/drivers/platform/x86/intel/pmc/core.c
@@ -53,18 +53,18 @@ const struct pmc_bit_map msr_map[] = {
{}
};
-static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset)
+static inline u32 pmc_core_reg_read(struct pmc *pmc, int reg_offset)
{
- return readl(pmcdev->regbase + reg_offset);
+ return readl(pmc->regbase + reg_offset);
}
-static inline void pmc_core_reg_write(struct pmc_dev *pmcdev, int reg_offset,
+static inline void pmc_core_reg_write(struct pmc *pmc, int reg_offset,
u32 val)
{
- writel(val, pmcdev->regbase + reg_offset);
+ writel(val, pmc->regbase + reg_offset);
}
-static inline u64 pmc_core_adjust_slp_s0_step(struct pmc_dev *pmcdev, u32 value)
+static inline u64 pmc_core_adjust_slp_s0_step(struct pmc *pmc, u32 value)
{
/*
* ADL PCH does not have the SLP_S0 counter and LPM Residency counters are
@@ -72,17 +72,18 @@ static inline u64 pmc_core_adjust_slp_s0_step(struct pmc_dev *pmcdev, u32 value)
* programs have the legacy SLP_S0 residency counter that is using the 122
* usec tick.
*/
- const int lpm_adj_x2 = pmcdev->map->lpm_res_counter_step_x2;
+ const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2;
- if (pmcdev->map == &adl_reg_map)
+ if (pmc->map == &adl_reg_map)
return (u64)value * GET_X2_COUNTER((u64)lpm_adj_x2);
else
- return (u64)value * pmcdev->map->slp_s0_res_counter_step;
+ return (u64)value * pmc->map->slp_s0_res_counter_step;
}
static int set_etr3(struct pmc_dev *pmcdev)
{
- const struct pmc_reg_map *map = pmcdev->map;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ const struct pmc_reg_map *map = pmc->map;
u32 reg;
int err;
@@ -92,7 +93,7 @@ static int set_etr3(struct pmc_dev *pmcdev)
mutex_lock(&pmcdev->lock);
/* check if CF9 is locked */
- reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+ reg = pmc_core_reg_read(pmc, map->etr3_offset);
if (reg & ETR3_CF9LOCK) {
err = -EACCES;
goto out_unlock;
@@ -100,9 +101,9 @@ static int set_etr3(struct pmc_dev *pmcdev)
/* write CF9 global reset bit */
reg |= ETR3_CF9GR;
- pmc_core_reg_write(pmcdev, map->etr3_offset, reg);
+ pmc_core_reg_write(pmc, map->etr3_offset, reg);
- reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+ reg = pmc_core_reg_read(pmc, map->etr3_offset);
if (!(reg & ETR3_CF9GR)) {
err = -EIO;
goto out_unlock;
@@ -120,11 +121,12 @@ static umode_t etr3_is_visible(struct kobject *kobj,
{
struct device *dev = kobj_to_dev(kobj);
struct pmc_dev *pmcdev = dev_get_drvdata(dev);
- const struct pmc_reg_map *map = pmcdev->map;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ const struct pmc_reg_map *map = pmc->map;
u32 reg;
mutex_lock(&pmcdev->lock);
- reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+ reg = pmc_core_reg_read(pmc, map->etr3_offset);
mutex_unlock(&pmcdev->lock);
return reg & ETR3_CF9LOCK ? attr->mode & (SYSFS_PREALLOC | 0444) : attr->mode;
@@ -134,7 +136,8 @@ static ssize_t etr3_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pmc_dev *pmcdev = dev_get_drvdata(dev);
- const struct pmc_reg_map *map = pmcdev->map;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ const struct pmc_reg_map *map = pmc->map;
u32 reg;
if (!map->etr3_offset)
@@ -142,7 +145,7 @@ static ssize_t etr3_show(struct device *dev,
mutex_lock(&pmcdev->lock);
- reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+ reg = pmc_core_reg_read(pmc, map->etr3_offset);
reg &= ETR3_CF9GR | ETR3_CF9LOCK;
mutex_unlock(&pmcdev->lock);
@@ -191,37 +194,37 @@ static const struct attribute_group *pmc_dev_groups[] = {
static int pmc_core_dev_state_get(void *data, u64 *val)
{
- struct pmc_dev *pmcdev = data;
- const struct pmc_reg_map *map = pmcdev->map;
+ struct pmc *pmc = data;
+ const struct pmc_reg_map *map = pmc->map;
u32 value;
- value = pmc_core_reg_read(pmcdev, map->slp_s0_offset);
- *val = pmc_core_adjust_slp_s0_step(pmcdev, value);
+ value = pmc_core_reg_read(pmc, map->slp_s0_offset);
+ *val = pmc_core_adjust_slp_s0_step(pmc, value);
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(pmc_core_dev_state, pmc_core_dev_state_get, NULL, "%llu\n");
-static int pmc_core_check_read_lock_bit(struct pmc_dev *pmcdev)
+static int pmc_core_check_read_lock_bit(struct pmc *pmc)
{
u32 value;
- value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_cfg_offset);
- return value & BIT(pmcdev->map->pm_read_disable_bit);
+ value = pmc_core_reg_read(pmc, pmc->map->pm_cfg_offset);
+ return value & BIT(pmc->map->pm_read_disable_bit);
}
-static void pmc_core_slps0_display(struct pmc_dev *pmcdev, struct device *dev,
+static void pmc_core_slps0_display(struct pmc *pmc, struct device *dev,
struct seq_file *s)
{
- const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps;
+ const struct pmc_bit_map **maps = pmc->map->slps0_dbg_maps;
const struct pmc_bit_map *map;
- int offset = pmcdev->map->slps0_dbg_offset;
+ int offset = pmc->map->slps0_dbg_offset;
u32 data;
while (*maps) {
map = *maps;
- data = pmc_core_reg_read(pmcdev, offset);
+ data = pmc_core_reg_read(pmc, offset);
offset += 4;
while (map->name) {
if (dev)
@@ -248,8 +251,8 @@ static int pmc_core_lpm_get_arr_size(const struct pmc_bit_map **maps)
return idx;
}
-static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev,
- struct seq_file *s, u32 offset,
+static void pmc_core_lpm_display(struct pmc *pmc, struct device *dev,
+ struct seq_file *s, u32 offset, int pmc_index,
const char *str,
const struct pmc_bit_map **maps)
{
@@ -262,25 +265,25 @@ static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev,
return;
for (index = 0; index < arr_size; index++) {
- lpm_regs[index] = pmc_core_reg_read(pmcdev, offset);
+ lpm_regs[index] = pmc_core_reg_read(pmc, offset);
offset += 4;
}
for (idx = 0; idx < arr_size; idx++) {
if (dev)
- dev_info(dev, "\nLPM_%s_%d:\t0x%x\n", str, idx,
+ dev_info(dev, "\nPMC%d:LPM_%s_%d:\t0x%x\n", pmc_index, str, idx,
lpm_regs[idx]);
if (s)
- seq_printf(s, "\nLPM_%s_%d:\t0x%x\n", str, idx,
+ seq_printf(s, "\nPMC%d:LPM_%s_%d:\t0x%x\n", pmc_index, str, idx,
lpm_regs[idx]);
for (index = 0; maps[idx][index].name && index < len; index++) {
bit_mask = maps[idx][index].bit_mask;
if (dev)
- dev_info(dev, "%-30s %-30d\n",
+ dev_info(dev, "PMC%d:%-30s %-30d\n", pmc_index,
maps[idx][index].name,
lpm_regs[idx] & bit_mask ? 1 : 0);
if (s)
- seq_printf(s, "%-30s %-30d\n",
+ seq_printf(s, "PMC%d:%-30s %-30d\n", pmc_index,
maps[idx][index].name,
lpm_regs[idx] & bit_mask ? 1 : 0);
}
@@ -291,37 +294,46 @@ static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev,
static bool slps0_dbg_latch;
-static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset)
+static inline u8 pmc_core_reg_read_byte(struct pmc *pmc, int offset)
{
- return readb(pmcdev->regbase + offset);
+ return readb(pmc->regbase + offset);
}
static void pmc_core_display_map(struct seq_file *s, int index, int idx, int ip,
- u8 pf_reg, const struct pmc_bit_map **pf_map)
+ int pmc_index, u8 pf_reg, const struct pmc_bit_map **pf_map)
{
- seq_printf(s, "PCH IP: %-2d - %-32s\tState: %s\n",
- ip, pf_map[idx][index].name,
+ seq_printf(s, "PMC%d:PCH IP: %-2d - %-32s\tState: %s\n",
+ pmc_index, ip, pf_map[idx][index].name,
pf_map[idx][index].bit_mask & pf_reg ? "Off" : "On");
}
static int pmc_core_ppfear_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
- const struct pmc_bit_map **maps = pmcdev->map->pfear_sts;
- u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES];
- int index, iter, idx, ip = 0;
+ int i;
- iter = pmcdev->map->ppfear0_offset;
+ for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) {
+ struct pmc *pmc = pmcdev->pmcs[i];
+ const struct pmc_bit_map **maps;
+ u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES];
+ int index, iter, idx, ip = 0;
- for (index = 0; index < pmcdev->map->ppfear_buckets &&
- index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++)
- pf_regs[index] = pmc_core_reg_read_byte(pmcdev, iter);
+ if (!pmc)
+ continue;
+
+ maps = pmc->map->pfear_sts;
+ iter = pmc->map->ppfear0_offset;
+
+ for (index = 0; index < pmc->map->ppfear_buckets &&
+ index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++)
+ pf_regs[index] = pmc_core_reg_read_byte(pmc, iter);
- for (idx = 0; maps[idx]; idx++) {
- for (index = 0; maps[idx][index].name &&
- index < pmcdev->map->ppfear_buckets * 8; ip++, index++)
- pmc_core_display_map(s, index, idx, ip,
- pf_regs[index / 8], maps);
+ for (idx = 0; maps[idx]; idx++) {
+ for (index = 0; maps[idx][index].name &&
+ index < pmc->map->ppfear_buckets * 8; ip++, index++)
+ pmc_core_display_map(s, index, idx, ip, i,
+ pf_regs[index / 8], maps);
+ }
}
return 0;
@@ -329,37 +341,38 @@ static int pmc_core_ppfear_show(struct seq_file *s, void *unused)
DEFINE_SHOW_ATTRIBUTE(pmc_core_ppfear);
/* This function should return link status, 0 means ready */
-static int pmc_core_mtpmc_link_status(struct pmc_dev *pmcdev)
+static int pmc_core_mtpmc_link_status(struct pmc *pmc)
{
u32 value;
- value = pmc_core_reg_read(pmcdev, SPT_PMC_PM_STS_OFFSET);
+ value = pmc_core_reg_read(pmc, SPT_PMC_PM_STS_OFFSET);
return value & BIT(SPT_PMC_MSG_FULL_STS_BIT);
}
-static int pmc_core_send_msg(struct pmc_dev *pmcdev, u32 *addr_xram)
+static int pmc_core_send_msg(struct pmc *pmc, u32 *addr_xram)
{
u32 dest;
int timeout;
for (timeout = NUM_RETRIES; timeout > 0; timeout--) {
- if (pmc_core_mtpmc_link_status(pmcdev) == 0)
+ if (pmc_core_mtpmc_link_status(pmc) == 0)
break;
msleep(5);
}
- if (timeout <= 0 && pmc_core_mtpmc_link_status(pmcdev))
+ if (timeout <= 0 && pmc_core_mtpmc_link_status(pmc))
return -EBUSY;
dest = (*addr_xram & MTPMC_MASK) | (1U << 1);
- pmc_core_reg_write(pmcdev, SPT_PMC_MTPMC_OFFSET, dest);
+ pmc_core_reg_write(pmc, SPT_PMC_MTPMC_OFFSET, dest);
return 0;
}
static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
- const struct pmc_bit_map *map = pmcdev->map->mphy_sts;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ const struct pmc_bit_map *map = pmc->map->mphy_sts;
u32 mphy_core_reg_low, mphy_core_reg_high;
u32 val_low, val_high;
int index, err = 0;
@@ -374,21 +387,21 @@ static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused)
mutex_lock(&pmcdev->lock);
- if (pmc_core_send_msg(pmcdev, &mphy_core_reg_low) != 0) {
+ if (pmc_core_send_msg(pmc, &mphy_core_reg_low) != 0) {
err = -EBUSY;
goto out_unlock;
}
msleep(10);
- val_low = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET);
+ val_low = pmc_core_reg_read(pmc, SPT_PMC_MFPMC_OFFSET);
- if (pmc_core_send_msg(pmcdev, &mphy_core_reg_high) != 0) {
+ if (pmc_core_send_msg(pmc, &mphy_core_reg_high) != 0) {
err = -EBUSY;
goto out_unlock;
}
msleep(10);
- val_high = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET);
+ val_high = pmc_core_reg_read(pmc, SPT_PMC_MFPMC_OFFSET);
for (index = 0; index < 8 && map[index].name; index++) {
seq_printf(s, "%-32s\tState: %s\n",
@@ -413,7 +426,8 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_mphy_pg);
static int pmc_core_pll_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
- const struct pmc_bit_map *map = pmcdev->map->pll_sts;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ const struct pmc_bit_map *map = pmc->map->pll_sts;
u32 mphy_common_reg, val;
int index, err = 0;
@@ -425,14 +439,14 @@ static int pmc_core_pll_show(struct seq_file *s, void *unused)
mphy_common_reg = (SPT_PMC_MPHY_COM_STS_0 << 16);
mutex_lock(&pmcdev->lock);
- if (pmc_core_send_msg(pmcdev, &mphy_common_reg) != 0) {
+ if (pmc_core_send_msg(pmc, &mphy_common_reg) != 0) {
err = -EBUSY;
goto out_unlock;
}
/* Observed PMC HW response latency for MTPMC-MFPMC is ~10 ms */
msleep(10);
- val = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET);
+ val = pmc_core_reg_read(pmc, SPT_PMC_MFPMC_OFFSET);
for (index = 0; map[index].name ; index++) {
seq_printf(s, "%-32s\tState: %s\n",
@@ -448,25 +462,48 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_pll);
int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value)
{
- const struct pmc_reg_map *map = pmcdev->map;
+ struct pmc *pmc;
+ const struct pmc_reg_map *map;
u32 reg;
- int err = 0;
+ int pmc_index, ltr_index;
- mutex_lock(&pmcdev->lock);
+ ltr_index = value;
+ /* For platforms with multiple pmcs, ltr index value given by user
+ * is based on the contiguous indexes from ltr_show output.
+ * pmc index and ltr index needs to be calculated from it.
+ */
+ for (pmc_index = 0; pmc_index < ARRAY_SIZE(pmcdev->pmcs) && ltr_index > 0; pmc_index++) {
+ pmc = pmcdev->pmcs[pmc_index];
- if (value > map->ltr_ignore_max) {
- err = -EINVAL;
- goto out_unlock;
+ if (!pmc)
+ continue;
+
+ map = pmc->map;
+ if (ltr_index <= map->ltr_ignore_max)
+ break;
+
+ /* Along with IP names, ltr_show map includes CURRENT_PLATFORM
+ * and AGGREGATED_SYSTEM values per PMC. Take these two index
+ * values into account in ltr_index calculation. Also, to start
+ * ltr index from zero for next pmc, subtract it by 1.
+ */
+ ltr_index = ltr_index - (map->ltr_ignore_max + 2) - 1;
}
- reg = pmc_core_reg_read(pmcdev, map->ltr_ignore_offset);
- reg |= BIT(value);
- pmc_core_reg_write(pmcdev, map->ltr_ignore_offset, reg);
+ if (pmc_index >= ARRAY_SIZE(pmcdev->pmcs) || ltr_index < 0)
+ return -EINVAL;
+
+ pr_debug("ltr_ignore for pmc%d: ltr_index:%d\n", pmc_index, ltr_index);
+
+ mutex_lock(&pmcdev->lock);
+
+ reg = pmc_core_reg_read(pmc, map->ltr_ignore_offset);
+ reg |= BIT(ltr_index);
+ pmc_core_reg_write(pmc, map->ltr_ignore_offset, reg);
-out_unlock:
mutex_unlock(&pmcdev->lock);
- return err;
+ return 0;
}
static ssize_t pmc_core_ltr_ignore_write(struct file *file,
@@ -509,7 +546,8 @@ static const struct file_operations pmc_core_ltr_ignore_ops = {
static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset)
{
- const struct pmc_reg_map *map = pmcdev->map;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ const struct pmc_reg_map *map = pmc->map;
u32 fd;
mutex_lock(&pmcdev->lock);
@@ -517,12 +555,12 @@ static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset)
if (!reset && !slps0_dbg_latch)
goto out_unlock;
- fd = pmc_core_reg_read(pmcdev, map->slps0_dbg_offset);
+ fd = pmc_core_reg_read(pmc, map->slps0_dbg_offset);
if (reset)
fd &= ~CNP_PMC_LATCH_SLPS0_EVENTS;
else
fd |= CNP_PMC_LATCH_SLPS0_EVENTS;
- pmc_core_reg_write(pmcdev, map->slps0_dbg_offset, fd);
+ pmc_core_reg_write(pmc, map->slps0_dbg_offset, fd);
slps0_dbg_latch = false;
@@ -535,7 +573,7 @@ static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused)
struct pmc_dev *pmcdev = s->private;
pmc_core_slps0_dbg_latch(pmcdev, false);
- pmc_core_slps0_display(pmcdev, NULL, s);
+ pmc_core_slps0_display(pmcdev->pmcs[PMC_IDX_MAIN], NULL, s);
pmc_core_slps0_dbg_latch(pmcdev, true);
return 0;
@@ -579,44 +617,52 @@ static u32 convert_ltr_scale(u32 val)
static int pmc_core_ltr_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
- const struct pmc_bit_map *map = pmcdev->map->ltr_show_sts;
u64 decoded_snoop_ltr, decoded_non_snoop_ltr;
u32 ltr_raw_data, scale, val;
u16 snoop_ltr, nonsnoop_ltr;
- int index;
+ int i, index, ltr_index = 0;
- for (index = 0; map[index].name ; index++) {
- decoded_snoop_ltr = decoded_non_snoop_ltr = 0;
- ltr_raw_data = pmc_core_reg_read(pmcdev,
- map[index].bit_mask);
- snoop_ltr = ltr_raw_data & ~MTPMC_MASK;
- nonsnoop_ltr = (ltr_raw_data >> 0x10) & ~MTPMC_MASK;
-
- if (FIELD_GET(LTR_REQ_NONSNOOP, ltr_raw_data)) {
- scale = FIELD_GET(LTR_DECODED_SCALE, nonsnoop_ltr);
- val = FIELD_GET(LTR_DECODED_VAL, nonsnoop_ltr);
- decoded_non_snoop_ltr = val * convert_ltr_scale(scale);
- }
+ for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) {
+ struct pmc *pmc = pmcdev->pmcs[i];
+ const struct pmc_bit_map *map;
- if (FIELD_GET(LTR_REQ_SNOOP, ltr_raw_data)) {
- scale = FIELD_GET(LTR_DECODED_SCALE, snoop_ltr);
- val = FIELD_GET(LTR_DECODED_VAL, snoop_ltr);
- decoded_snoop_ltr = val * convert_ltr_scale(scale);
- }
+ if (!pmc)
+ continue;
+
+ map = pmc->map->ltr_show_sts;
+ for (index = 0; map[index].name; index++) {
+ decoded_snoop_ltr = decoded_non_snoop_ltr = 0;
+ ltr_raw_data = pmc_core_reg_read(pmc,
+ map[index].bit_mask);
+ snoop_ltr = ltr_raw_data & ~MTPMC_MASK;
+ nonsnoop_ltr = (ltr_raw_data >> 0x10) & ~MTPMC_MASK;
+
+ if (FIELD_GET(LTR_REQ_NONSNOOP, ltr_raw_data)) {
+ scale = FIELD_GET(LTR_DECODED_SCALE, nonsnoop_ltr);
+ val = FIELD_GET(LTR_DECODED_VAL, nonsnoop_ltr);
+ decoded_non_snoop_ltr = val * convert_ltr_scale(scale);
+ }
+ if (FIELD_GET(LTR_REQ_SNOOP, ltr_raw_data)) {
+ scale = FIELD_GET(LTR_DECODED_SCALE, snoop_ltr);
+ val = FIELD_GET(LTR_DECODED_VAL, snoop_ltr);
+ decoded_snoop_ltr = val * convert_ltr_scale(scale);
+ }
- seq_printf(s, "%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\n",
- map[index].name, ltr_raw_data,
- decoded_non_snoop_ltr,
- decoded_snoop_ltr);
+ seq_printf(s, "%d\tPMC%d:%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\n",
+ ltr_index, i, map[index].name, ltr_raw_data,
+ decoded_non_snoop_ltr,
+ decoded_snoop_ltr);
+ ltr_index++;
+ }
}
return 0;
}
DEFINE_SHOW_ATTRIBUTE(pmc_core_ltr);
-static inline u64 adjust_lpm_residency(struct pmc_dev *pmcdev, u32 offset,
+static inline u64 adjust_lpm_residency(struct pmc *pmc, u32 offset,
const int lpm_adj_x2)
{
- u64 lpm_res = pmc_core_reg_read(pmcdev, offset);
+ u64 lpm_res = pmc_core_reg_read(pmc, offset);
return GET_X2_COUNTER((u64)lpm_adj_x2 * lpm_res);
}
@@ -624,15 +670,16 @@ static inline u64 adjust_lpm_residency(struct pmc_dev *pmcdev, u32 offset,
static int pmc_core_substate_res_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
- const int lpm_adj_x2 = pmcdev->map->lpm_res_counter_step_x2;
- u32 offset = pmcdev->map->lpm_residency_offset;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2;
+ u32 offset = pmc->map->lpm_residency_offset;
int i, mode;
seq_printf(s, "%-10s %-15s\n", "Substate", "Residency");
pmc_for_each_mode(i, mode, pmcdev) {
seq_printf(s, "%-10s %-15llu\n", pmc_lpm_modes[mode],
- adjust_lpm_residency(pmcdev, offset + (4 * mode), lpm_adj_x2));
+ adjust_lpm_residency(pmc, offset + (4 * mode), lpm_adj_x2));
}
return 0;
@@ -642,10 +689,19 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_res);
static int pmc_core_substate_sts_regs_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
- const struct pmc_bit_map **maps = pmcdev->map->lpm_sts;
- u32 offset = pmcdev->map->lpm_status_offset;
+ int i;
- pmc_core_lpm_display(pmcdev, NULL, s, offset, "STATUS", maps);
+ for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) {
+ struct pmc *pmc = pmcdev->pmcs[i];
+ const struct pmc_bit_map **maps;
+ u32 offset;
+
+ if (!pmc)
+ continue;
+ maps = pmc->map->lpm_sts;
+ offset = pmc->map->lpm_status_offset;
+ pmc_core_lpm_display(pmc, NULL, s, offset, i, "STATUS", maps);
+ }
return 0;
}
@@ -654,10 +710,19 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_sts_regs);
static int pmc_core_substate_l_sts_regs_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
- const struct pmc_bit_map **maps = pmcdev->map->lpm_sts;
- u32 offset = pmcdev->map->lpm_live_status_offset;
+ int i;
- pmc_core_lpm_display(pmcdev, NULL, s, offset, "LIVE_STATUS", maps);
+ for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) {
+ struct pmc *pmc = pmcdev->pmcs[i];
+ const struct pmc_bit_map **maps;
+ u32 offset;
+
+ if (!pmc)
+ continue;
+ maps = pmc->map->lpm_sts;
+ offset = pmc->map->lpm_live_status_offset;
+ pmc_core_lpm_display(pmc, NULL, s, offset, i, "LIVE_STATUS", maps);
+ }
return 0;
}
@@ -678,11 +743,12 @@ static void pmc_core_substate_req_header_show(struct seq_file *s)
static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
- const struct pmc_bit_map **maps = pmcdev->map->lpm_sts;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ const struct pmc_bit_map **maps = pmc->map->lpm_sts;
const struct pmc_bit_map *map;
- const int num_maps = pmcdev->map->lpm_num_maps;
- u32 sts_offset = pmcdev->map->lpm_status_offset;
- u32 *lpm_req_regs = pmcdev->lpm_req_regs;
+ const int num_maps = pmc->map->lpm_num_maps;
+ u32 sts_offset = pmc->map->lpm_status_offset;
+ u32 *lpm_req_regs = pmc->lpm_req_regs;
int mp;
/* Display the header */
@@ -703,7 +769,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused)
req_mask |= lpm_req_regs[mp + (mode * num_maps)];
/* Get the last latched status for this map */
- lpm_status = pmc_core_reg_read(pmcdev, sts_offset + (mp * 4));
+ lpm_status = pmc_core_reg_read(pmc, sts_offset + (mp * 4));
/* Loop over elements in this map */
map = maps[mp];
@@ -746,11 +812,12 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_req_regs);
static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
bool c10;
u32 reg;
int idx, mode;
- reg = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_sts_latch_en_offset);
+ reg = pmc_core_reg_read(pmc, pmc->map->lpm_sts_latch_en_offset);
if (reg & LPM_STS_LATCH_MODE) {
seq_puts(s, "c10");
c10 = false;
@@ -777,6 +844,7 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file,
{
struct seq_file *s = file->private_data;
struct pmc_dev *pmcdev = s->private;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
bool clear = false, c10 = false;
unsigned char buf[8];
int idx, m, mode;
@@ -813,9 +881,9 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file,
if (clear) {
mutex_lock(&pmcdev->lock);
- reg = pmc_core_reg_read(pmcdev, pmcdev->map->etr3_offset);
+ reg = pmc_core_reg_read(pmc, pmc->map->etr3_offset);
reg |= ETR3_CLEAR_LPM_EVENTS;
- pmc_core_reg_write(pmcdev, pmcdev->map->etr3_offset, reg);
+ pmc_core_reg_write(pmc, pmc->map->etr3_offset, reg);
mutex_unlock(&pmcdev->lock);
@@ -825,9 +893,9 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file,
if (c10) {
mutex_lock(&pmcdev->lock);
- reg = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_sts_latch_en_offset);
+ reg = pmc_core_reg_read(pmc, pmc->map->lpm_sts_latch_en_offset);
reg &= ~LPM_STS_LATCH_MODE;
- pmc_core_reg_write(pmcdev, pmcdev->map->lpm_sts_latch_en_offset, reg);
+ pmc_core_reg_write(pmc, pmc->map->lpm_sts_latch_en_offset, reg);
mutex_unlock(&pmcdev->lock);
@@ -840,7 +908,7 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file,
*/
reg = LPM_STS_LATCH_MODE | BIT(mode);
mutex_lock(&pmcdev->lock);
- pmc_core_reg_write(pmcdev, pmcdev->map->lpm_sts_latch_en_offset, reg);
+ pmc_core_reg_write(pmc, pmc->map->lpm_sts_latch_en_offset, reg);
mutex_unlock(&pmcdev->lock);
return count;
@@ -849,8 +917,8 @@ DEFINE_PMC_CORE_ATTR_WRITE(pmc_core_lpm_latch_mode);
static int pmc_core_pkgc_show(struct seq_file *s, void *unused)
{
- struct pmc_dev *pmcdev = s->private;
- const struct pmc_bit_map *map = pmcdev->map->msr_sts;
+ struct pmc *pmc = s->private;
+ const struct pmc_bit_map *map = pmc->map->msr_sts;
u64 pcstate_count;
int index;
@@ -901,6 +969,7 @@ static bool pmc_core_pri_verify(u32 lpm_pri, u8 *mode_order)
static void pmc_core_get_low_power_modes(struct platform_device *pdev)
{
struct pmc_dev *pmcdev = platform_get_drvdata(pdev);
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
u8 pri_order[LPM_MAX_NUM_MODES] = LPM_DEFAULT_PRI;
u8 mode_order[LPM_MAX_NUM_MODES];
u32 lpm_pri;
@@ -908,10 +977,10 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev)
int mode, i, p;
/* Use LPM Maps to indicate support for substates */
- if (!pmcdev->map->lpm_num_maps)
+ if (!pmc->map->lpm_num_maps)
return;
- lpm_en = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_en_offset);
+ lpm_en = pmc_core_reg_read(pmc, pmc->map->lpm_en_offset);
/* For MTL, BIT 31 is not an lpm mode but a enable bit.
* Lower byte is enough to cover the number of lpm modes for all
* platforms and hence mask the upper 3 bytes.
@@ -919,7 +988,7 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev)
pmcdev->num_lpm_modes = hweight32(lpm_en & 0xFF);
/* Read 32 bit LPM_PRI register */
- lpm_pri = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_priority_offset);
+ lpm_pri = pmc_core_reg_read(pmc, pmc->map->lpm_priority_offset);
/*
@@ -948,6 +1017,25 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev)
}
}
+int get_primary_reg_base(struct pmc *pmc)
+{
+ u64 slp_s0_addr;
+
+ if (lpit_read_residency_count_address(&slp_s0_addr)) {
+ pmc->base_addr = PMC_BASE_ADDR_DEFAULT;
+
+ if (page_is_ram(PHYS_PFN(pmc->base_addr)))
+ return -ENODEV;
+ } else {
+ pmc->base_addr = slp_s0_addr - pmc->map->slp_s0_offset;
+ }
+
+ pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length);
+ if (!pmc->regbase)
+ return -ENOMEM;
+ return 0;
+}
+
static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev)
{
debugfs_remove_recursive(pmcdev->dbgfs_dir);
@@ -955,15 +1043,16 @@ static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev)
static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
{
+ struct pmc *primary_pmc = pmcdev->pmcs[PMC_IDX_MAIN];
struct dentry *dir;
dir = debugfs_create_dir("pmc_core", NULL);
pmcdev->dbgfs_dir = dir;
- debugfs_create_file("slp_s0_residency_usec", 0444, dir, pmcdev,
+ debugfs_create_file("slp_s0_residency_usec", 0444, dir, primary_pmc,
&pmc_core_dev_state);
- if (pmcdev->map->pfear_sts)
+ if (primary_pmc->map->pfear_sts)
debugfs_create_file("pch_ip_power_gating_status", 0444, dir,
pmcdev, &pmc_core_ppfear_fops);
@@ -972,19 +1061,19 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
debugfs_create_file("ltr_show", 0444, dir, pmcdev, &pmc_core_ltr_fops);
- debugfs_create_file("package_cstate_show", 0444, dir, pmcdev,
+ debugfs_create_file("package_cstate_show", 0444, dir, primary_pmc,
&pmc_core_pkgc_fops);
- if (pmcdev->map->pll_sts)
+ if (primary_pmc->map->pll_sts)
debugfs_create_file("pll_status", 0444, dir, pmcdev,
&pmc_core_pll_fops);
- if (pmcdev->map->mphy_sts)
+ if (primary_pmc->map->mphy_sts)
debugfs_create_file("mphy_core_lanes_power_gating_status",
0444, dir, pmcdev,
&pmc_core_mphy_pg_fops);
- if (pmcdev->map->slps0_dbg_maps) {
+ if (primary_pmc->map->slps0_dbg_maps) {
debugfs_create_file("slp_s0_debug_status", 0444,
dir, pmcdev,
&pmc_core_slps0_dbg_fops);
@@ -993,13 +1082,13 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
dir, &slps0_dbg_latch);
}
- if (pmcdev->map->lpm_en_offset) {
+ if (primary_pmc->map->lpm_en_offset) {
debugfs_create_file("substate_residencies", 0444,
pmcdev->dbgfs_dir, pmcdev,
&pmc_core_substate_res_fops);
}
- if (pmcdev->map->lpm_status_offset) {
+ if (primary_pmc->map->lpm_status_offset) {
debugfs_create_file("substate_status_registers", 0444,
pmcdev->dbgfs_dir, pmcdev,
&pmc_core_substate_sts_regs_fops);
@@ -1011,7 +1100,7 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
&pmc_core_lpm_latch_mode_fops);
}
- if (pmcdev->lpm_req_regs) {
+ if (primary_pmc->lpm_req_regs) {
debugfs_create_file("substate_requirements", 0444,
pmcdev->dbgfs_dir, pmcdev,
&pmc_core_substate_req_regs_fops);
@@ -1039,7 +1128,6 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = {
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, tgl_core_init),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, adl_core_init),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, adl_core_init),
- X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE, mtl_core_init),
X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE_L, mtl_core_init),
{}
};
@@ -1063,16 +1151,16 @@ static int quirk_xtal_ignore(const struct dmi_system_id *id)
return 0;
}
-static void pmc_core_xtal_ignore(struct pmc_dev *pmcdev)
+static void pmc_core_xtal_ignore(struct pmc *pmc)
{
u32 value;
- value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_vric1_offset);
+ value = pmc_core_reg_read(pmc, pmc->map->pm_vric1_offset);
/* 24MHz Crystal Shutdown Qualification Disable */
value |= SPT_PMC_VRIC1_XTALSDQDIS;
/* Low Voltage Mode Enable */
value &= ~SPT_PMC_VRIC1_SLPS0LVEN;
- pmc_core_reg_write(pmcdev, pmcdev->map->pm_vric1_offset, value);
+ pmc_core_reg_write(pmc, pmc->map->pm_vric1_offset, value);
}
static const struct dmi_system_id pmc_core_dmi_table[] = {
@@ -1087,12 +1175,32 @@ static const struct dmi_system_id pmc_core_dmi_table[] = {
{}
};
-static void pmc_core_do_dmi_quirks(struct pmc_dev *pmcdev)
+static void pmc_core_do_dmi_quirks(struct pmc *pmc)
{
dmi_check_system(pmc_core_dmi_table);
if (xtal_ignore)
- pmc_core_xtal_ignore(pmcdev);
+ pmc_core_xtal_ignore(pmc);
+}
+
+static void pmc_core_clean_structure(struct platform_device *pdev)
+{
+ struct pmc_dev *pmcdev = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) {
+ struct pmc *pmc = pmcdev->pmcs[i];
+
+ if (pmc)
+ iounmap(pmc->regbase);
+ }
+
+ if (pmcdev->ssram_pcidev) {
+ pci_dev_put(pmcdev->ssram_pcidev);
+ pci_disable_device(pmcdev->ssram_pcidev);
+ }
+ platform_set_drvdata(pdev, NULL);
+ mutex_destroy(&pmcdev->lock);
}
static int pmc_core_probe(struct platform_device *pdev)
@@ -1100,8 +1208,9 @@ static int pmc_core_probe(struct platform_device *pdev)
static bool device_initialized;
struct pmc_dev *pmcdev;
const struct x86_cpu_id *cpu_id;
- void (*core_init)(struct pmc_dev *pmcdev);
- u64 slp_s0_addr;
+ int (*core_init)(struct pmc_dev *pmcdev);
+ struct pmc *primary_pmc;
+ int ret;
if (device_initialized)
return -ENODEV;
@@ -1117,7 +1226,13 @@ static int pmc_core_probe(struct platform_device *pdev)
if (!cpu_id)
return -ENODEV;
- core_init = (void (*)(struct pmc_dev *))cpu_id->driver_data;
+ core_init = (int (*)(struct pmc_dev *))cpu_id->driver_data;
+
+ /* Primary PMC */
+ primary_pmc = devm_kzalloc(&pdev->dev, sizeof(*primary_pmc), GFP_KERNEL);
+ if (!primary_pmc)
+ return -ENOMEM;
+ pmcdev->pmcs[PMC_IDX_MAIN] = primary_pmc;
/*
* Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here
@@ -1128,33 +1243,19 @@ static int pmc_core_probe(struct platform_device *pdev)
core_init = cnp_core_init;
mutex_init(&pmcdev->lock);
- core_init(pmcdev);
-
-
- if (lpit_read_residency_count_address(&slp_s0_addr)) {
- pmcdev->base_addr = PMC_BASE_ADDR_DEFAULT;
-
- if (page_is_ram(PHYS_PFN(pmcdev->base_addr)))
- return -ENODEV;
- } else {
- pmcdev->base_addr = slp_s0_addr - pmcdev->map->slp_s0_offset;
+ ret = core_init(pmcdev);
+ if (ret) {
+ pmc_core_clean_structure(pdev);
+ return ret;
}
- pmcdev->regbase = ioremap(pmcdev->base_addr,
- pmcdev->map->regmap_length);
- if (!pmcdev->regbase)
- return -ENOMEM;
-
- if (pmcdev->core_configure)
- pmcdev->core_configure(pmcdev);
-
- pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(pmcdev);
+ pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(primary_pmc);
pmc_core_get_low_power_modes(pdev);
- pmc_core_do_dmi_quirks(pmcdev);
+ pmc_core_do_dmi_quirks(primary_pmc);
pmc_core_dbgfs_register(pmcdev);
pm_report_max_hw_sleep(FIELD_MAX(SLP_S0_RES_COUNTER_MASK) *
- pmc_core_adjust_slp_s0_step(pmcdev, 1));
+ pmc_core_adjust_slp_s0_step(primary_pmc, 1));
device_initialized = true;
dev_info(&pdev->dev, " initialized\n");
@@ -1165,11 +1266,8 @@ static int pmc_core_probe(struct platform_device *pdev)
static void pmc_core_remove(struct platform_device *pdev)
{
struct pmc_dev *pmcdev = platform_get_drvdata(pdev);
-
pmc_core_dbgfs_unregister(pmcdev);
- platform_set_drvdata(pdev, NULL);
- mutex_destroy(&pmcdev->lock);
- iounmap(pmcdev->regbase);
+ pmc_core_clean_structure(pdev);
}
static bool warn_on_s0ix_failures;
@@ -1179,6 +1277,7 @@ MODULE_PARM_DESC(warn_on_s0ix_failures, "Check and warn for S0ix failures");
static __maybe_unused int pmc_core_suspend(struct device *dev)
{
struct pmc_dev *pmcdev = dev_get_drvdata(dev);
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
/* Check if the syspend will actually use S0ix */
if (pm_suspend_via_firmware())
@@ -1189,7 +1288,7 @@ static __maybe_unused int pmc_core_suspend(struct device *dev)
return -EIO;
/* Save S0ix residency for checking later */
- if (pmc_core_dev_state_get(pmcdev, &pmcdev->s0ix_counter))
+ if (pmc_core_dev_state_get(pmc, &pmcdev->s0ix_counter))
return -EIO;
return 0;
@@ -1212,7 +1311,7 @@ static inline bool pmc_core_is_s0ix_failed(struct pmc_dev *pmcdev)
{
u64 s0ix_counter;
- if (pmc_core_dev_state_get(pmcdev, &s0ix_counter))
+ if (pmc_core_dev_state_get(pmcdev->pmcs[PMC_IDX_MAIN], &s0ix_counter))
return false;
pm_report_hw_sleep_time((u32)(s0ix_counter - pmcdev->s0ix_counter));
@@ -1223,11 +1322,13 @@ static inline bool pmc_core_is_s0ix_failed(struct pmc_dev *pmcdev)
return false;
}
-static __maybe_unused int pmc_core_resume(struct device *dev)
+int pmc_core_resume_common(struct pmc_dev *pmcdev)
{
- struct pmc_dev *pmcdev = dev_get_drvdata(dev);
- const struct pmc_bit_map **maps = pmcdev->map->lpm_sts;
- int offset = pmcdev->map->lpm_status_offset;
+ struct device *dev = &pmcdev->pdev->dev;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ const struct pmc_bit_map **maps = pmc->map->lpm_sts;
+ int offset = pmc->map->lpm_status_offset;
+ int i;
/* Check if the syspend used S0ix */
if (pm_suspend_via_firmware())
@@ -1249,14 +1350,32 @@ static __maybe_unused int pmc_core_resume(struct device *dev)
/* The real interesting case - S0ix failed - lets ask PMC why. */
dev_warn(dev, "CPU did not enter SLP_S0!!! (S0ix cnt=%llu)\n",
pmcdev->s0ix_counter);
- if (pmcdev->map->slps0_dbg_maps)
- pmc_core_slps0_display(pmcdev, dev, NULL);
- if (pmcdev->map->lpm_sts)
- pmc_core_lpm_display(pmcdev, dev, NULL, offset, "STATUS", maps);
+
+ if (pmc->map->slps0_dbg_maps)
+ pmc_core_slps0_display(pmc, dev, NULL);
+
+ for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) {
+ struct pmc *pmc = pmcdev->pmcs[i];
+
+ if (!pmc)
+ continue;
+ if (pmc->map->lpm_sts)
+ pmc_core_lpm_display(pmc, dev, NULL, offset, i, "STATUS", maps);
+ }
return 0;
}
+static __maybe_unused int pmc_core_resume(struct device *dev)
+{
+ struct pmc_dev *pmcdev = dev_get_drvdata(dev);
+
+ if (pmcdev->resume)
+ return pmcdev->resume(pmcdev);
+
+ return pmc_core_resume_common(pmcdev);
+}
+
static const struct dev_pm_ops pmc_core_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(pmc_core_suspend, pmc_core_resume)
};
diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index 9ca9b9746719..0729f593c6a7 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -19,6 +19,7 @@
#define SLP_S0_RES_COUNTER_MASK GENMASK(31, 0)
#define PMC_BASE_ADDR_DEFAULT 0xFE000000
+#define MAX_NUM_PMC 3
/* Sunrise Point Power Management Controller PCI Device ID */
#define SPT_PMC_PCI_DEVICE_ID 0x9d21
@@ -249,6 +250,17 @@ enum ppfear_regs {
#define MTL_LPM_STATUS_LATCH_EN_OFFSET 0x16F8
#define MTL_LPM_STATUS_OFFSET 0x1700
#define MTL_LPM_LIVE_STATUS_OFFSET 0x175C
+#define MTL_PMC_LTR_IOE_PMC 0x1C0C
+#define MTL_PMC_LTR_ESE 0x1BAC
+#define MTL_PMC_LTR_RESERVED 0x1BA4
+#define MTL_IOE_PMC_MMIO_REG_LEN 0x23A4
+#define MTL_SOCM_NUM_IP_IGN_ALLOWED 25
+#define MTL_SOC_PMC_MMIO_REG_LEN 0x2708
+#define MTL_PMC_LTR_SPG 0x1B74
+
+/* Meteor Lake PGD PFET Enable Ack Status */
+#define MTL_SOCM_PPFEAR_NUM_ENTRIES 8
+#define MTL_IOE_PPFEAR_NUM_ENTRIES 10
extern const char *pmc_lpm_modes[];
@@ -311,12 +323,38 @@ struct pmc_reg_map {
};
/**
- * struct pmc_dev - pmc device structure
+ * struct pmc_info - Structure to keep pmc info
+ * @devid: device id of the pmc device
+ * @map: pointer to a pmc_reg_map struct that contains platform
+ * specific attributes
+ */
+struct pmc_info {
+ u16 devid;
+ const struct pmc_reg_map *map;
+};
+
+/**
+ * struct pmc - pmc private info structure
* @base_addr: contains pmc base address
* @regbase: pointer to io-remapped memory location
* @map: pointer to pmc_reg_map struct that contains platform
* specific attributes
+ * @lpm_req_regs: List of substate requirements
+ *
+ * pmc contains info about one power management controller device.
+ */
+struct pmc {
+ u64 base_addr;
+ void __iomem *regbase;
+ const struct pmc_reg_map *map;
+ u32 *lpm_req_regs;
+};
+
+/**
+ * struct pmc_dev - pmc device structure
+ * @devs: pointer to an array of pmc pointers
* @pdev: pointer to platform_device struct
+ * @ssram_pcidev: pointer to pci device struct for the PMC SSRAM
* @dbgfs_dir: path to debugfs interface
* @pmc_xram_read_bit: flag to indicate whether PMC XRAM shadow registers
* used to read MPHY PG and PLL status are available
@@ -325,17 +363,15 @@ struct pmc_reg_map {
* @s0ix_counter: S0ix residency (step adjusted)
* @num_lpm_modes: Count of enabled modes
* @lpm_en_modes: Array of enabled modes from lowest to highest priority
- * @lpm_req_regs: List of substate requirements
- * @core_configure: Function pointer to configure the platform
+ * @resume: Function to perform platform specific resume
*
* pmc_dev contains info about power management controller device.
*/
struct pmc_dev {
- u32 base_addr;
- void __iomem *regbase;
- const struct pmc_reg_map *map;
+ struct pmc *pmcs[MAX_NUM_PMC];
struct dentry *dbgfs_dir;
struct platform_device *pdev;
+ struct pci_dev *ssram_pcidev;
int pmc_xram_read_bit;
struct mutex lock; /* generic mutex lock for PMC Core */
@@ -343,8 +379,20 @@ struct pmc_dev {
u64 s0ix_counter;
int num_lpm_modes;
int lpm_en_modes[LPM_MAX_NUM_MODES];
- u32 *lpm_req_regs;
- void (*core_configure)(struct pmc_dev *pmcdev);
+ int (*resume)(struct pmc_dev *pmcdev);
+
+ bool has_die_c6;
+ u32 die_c6_offset;
+ struct telem_endpoint *punit_ep;
+ struct pmc_info *regmap_list;
+};
+
+enum pmc_index {
+ PMC_IDX_MAIN,
+ PMC_IDX_SOC = PMC_IDX_MAIN,
+ PMC_IDX_IOE,
+ PMC_IDX_PCH,
+ PMC_IDX_MAX
};
extern const struct pmc_bit_map msr_map[];
@@ -393,20 +441,64 @@ extern const struct pmc_bit_map adl_vnn_req_status_3_map[];
extern const struct pmc_bit_map adl_vnn_misc_status_map[];
extern const struct pmc_bit_map *adl_lpm_maps[];
extern const struct pmc_reg_map adl_reg_map;
-extern const struct pmc_reg_map mtl_reg_map;
+extern const struct pmc_bit_map mtl_socm_pfear_map[];
+extern const struct pmc_bit_map *ext_mtl_socm_pfear_map[];
+extern const struct pmc_bit_map mtl_socm_ltr_show_map[];
+extern const struct pmc_bit_map mtl_socm_clocksource_status_map[];
+extern const struct pmc_bit_map mtl_socm_power_gating_status_0_map[];
+extern const struct pmc_bit_map mtl_socm_power_gating_status_1_map[];
+extern const struct pmc_bit_map mtl_socm_power_gating_status_2_map[];
+extern const struct pmc_bit_map mtl_socm_d3_status_0_map[];
+extern const struct pmc_bit_map mtl_socm_d3_status_1_map[];
+extern const struct pmc_bit_map mtl_socm_d3_status_2_map[];
+extern const struct pmc_bit_map mtl_socm_d3_status_3_map[];
+extern const struct pmc_bit_map mtl_socm_vnn_req_status_0_map[];
+extern const struct pmc_bit_map mtl_socm_vnn_req_status_1_map[];
+extern const struct pmc_bit_map mtl_socm_vnn_req_status_2_map[];
+extern const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[];
+extern const struct pmc_bit_map mtl_socm_vnn_misc_status_map[];
+extern const struct pmc_bit_map mtl_socm_signal_status_map[];
+extern const struct pmc_bit_map *mtl_socm_lpm_maps[];
+extern const struct pmc_reg_map mtl_socm_reg_map;
+extern const struct pmc_bit_map mtl_ioep_pfear_map[];
+extern const struct pmc_bit_map *ext_mtl_ioep_pfear_map[];
+extern const struct pmc_bit_map mtl_ioep_ltr_show_map[];
+extern const struct pmc_bit_map mtl_ioep_clocksource_status_map[];
+extern const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[];
+extern const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[];
+extern const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[];
+extern const struct pmc_bit_map mtl_ioep_d3_status_0_map[];
+extern const struct pmc_bit_map mtl_ioep_d3_status_1_map[];
+extern const struct pmc_bit_map mtl_ioep_d3_status_2_map[];
+extern const struct pmc_bit_map mtl_ioep_d3_status_3_map[];
+extern const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[];
+extern const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[];
+extern const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[];
+extern const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[];
+extern const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[];
+extern const struct pmc_bit_map *mtl_ioep_lpm_maps[];
+extern const struct pmc_reg_map mtl_ioep_reg_map;
+extern const struct pmc_bit_map mtl_ioem_pfear_map[];
+extern const struct pmc_bit_map *ext_mtl_ioem_pfear_map[];
+extern const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[];
+extern const struct pmc_bit_map mtl_ioem_vnn_req_status_1_map[];
+extern const struct pmc_bit_map *mtl_ioem_lpm_maps[];
+extern const struct pmc_reg_map mtl_ioem_reg_map;
extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev);
extern int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value);
-void spt_core_init(struct pmc_dev *pmcdev);
-void cnp_core_init(struct pmc_dev *pmcdev);
-void icl_core_init(struct pmc_dev *pmcdev);
-void tgl_core_init(struct pmc_dev *pmcdev);
-void adl_core_init(struct pmc_dev *pmcdev);
-void mtl_core_init(struct pmc_dev *pmcdev);
-void tgl_core_configure(struct pmc_dev *pmcdev);
-void adl_core_configure(struct pmc_dev *pmcdev);
-void mtl_core_configure(struct pmc_dev *pmcdev);
+int pmc_core_resume_common(struct pmc_dev *pmcdev);
+int get_primary_reg_base(struct pmc *pmc);
+
+extern void pmc_core_ssram_init(struct pmc_dev *pmcdev);
+
+int spt_core_init(struct pmc_dev *pmcdev);
+int cnp_core_init(struct pmc_dev *pmcdev);
+int icl_core_init(struct pmc_dev *pmcdev);
+int tgl_core_init(struct pmc_dev *pmcdev);
+int adl_core_init(struct pmc_dev *pmcdev);
+int mtl_core_init(struct pmc_dev *pmcdev);
#define pmc_for_each_mode(i, mode, pmcdev) \
for (i = 0, mode = pmcdev->lpm_en_modes[i]; \
diff --git a/drivers/platform/x86/intel/pmc/core_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c
new file mode 100644
index 000000000000..13fa16f0d52e
--- /dev/null
+++ b/drivers/platform/x86/intel/pmc/core_ssram.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file contains functions to handle discovery of PMC metrics located
+ * in the PMC SSRAM PCI device.
+ *
+ * Copyright (c) 2023, Intel Corporation.
+ * All Rights Reserved.
+ *
+ */
+
+#include <linux/pci.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+
+#include "core.h"
+
+#define SSRAM_HDR_SIZE 0x100
+#define SSRAM_PWRM_OFFSET 0x14
+#define SSRAM_DVSEC_OFFSET 0x1C
+#define SSRAM_DVSEC_SIZE 0x10
+#define SSRAM_PCH_OFFSET 0x60
+#define SSRAM_IOE_OFFSET 0x68
+#define SSRAM_DEVID_OFFSET 0x70
+
+static const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid)
+{
+ for (; list->map; ++list)
+ if (devid == list->devid)
+ return list->map;
+
+ return NULL;
+}
+
+static inline u64 get_base(void __iomem *addr, u32 offset)
+{
+ return lo_hi_readq(addr + offset) & GENMASK_ULL(63, 3);
+}
+
+static void
+pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
+ const struct pmc_reg_map *reg_map, int pmc_index)
+{
+ struct pmc *pmc = pmcdev->pmcs[pmc_index];
+
+ if (!pwrm_base)
+ return;
+
+ /* Memory for primary PMC has been allocated in core.c */
+ if (!pmc) {
+ pmc = devm_kzalloc(&pmcdev->pdev->dev, sizeof(*pmc), GFP_KERNEL);
+ if (!pmc)
+ return;
+ }
+
+ pmc->map = reg_map;
+ pmc->base_addr = pwrm_base;
+ pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length);
+
+ if (!pmc->regbase) {
+ devm_kfree(&pmcdev->pdev->dev, pmc);
+ return;
+ }
+
+ pmcdev->pmcs[pmc_index] = pmc;
+}
+
+static void
+pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, void __iomem *ssram, u32 offset,
+ int pmc_idx)
+{
+ u64 pwrm_base;
+ u16 devid;
+
+ if (pmc_idx != PMC_IDX_SOC) {
+ u64 ssram_base = get_base(ssram, offset);
+
+ if (!ssram_base)
+ return;
+
+ ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+ if (!ssram)
+ return;
+ }
+
+ pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET);
+ devid = readw(ssram + SSRAM_DEVID_OFFSET);
+
+ if (pmcdev->regmap_list) {
+ const struct pmc_reg_map *map;
+
+ map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
+ if (map)
+ pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx);
+ }
+
+ if (pmc_idx != PMC_IDX_SOC)
+ iounmap(ssram);
+}
+
+void pmc_core_ssram_init(struct pmc_dev *pmcdev)
+{
+ void __iomem *ssram;
+ struct pci_dev *pcidev;
+ u64 ssram_base;
+ int ret;
+
+ pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, 2));
+ if (!pcidev)
+ goto out;
+
+ ret = pcim_enable_device(pcidev);
+ if (ret)
+ goto release_dev;
+
+ ssram_base = pcidev->resource[0].start;
+ ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+ if (!ssram)
+ goto disable_dev;
+
+ pmcdev->ssram_pcidev = pcidev;
+
+ pmc_core_ssram_get_pmc(pmcdev, ssram, 0, PMC_IDX_SOC);
+ pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_IOE_OFFSET, PMC_IDX_IOE);
+ pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_PCH_OFFSET, PMC_IDX_PCH);
+
+ iounmap(ssram);
+out:
+ return;
+
+disable_dev:
+ pci_disable_device(pcidev);
+release_dev:
+ pci_dev_put(pcidev);
+}
diff --git a/drivers/platform/x86/intel/pmc/icl.c b/drivers/platform/x86/intel/pmc/icl.c
index 2f11b1a6daeb..d08e3174230d 100644
--- a/drivers/platform/x86/intel/pmc/icl.c
+++ b/drivers/platform/x86/intel/pmc/icl.c
@@ -50,7 +50,10 @@ const struct pmc_reg_map icl_reg_map = {
.etr3_offset = ETR3_OFFSET,
};
-void icl_core_init(struct pmc_dev *pmcdev)
+int icl_core_init(struct pmc_dev *pmcdev)
{
- pmcdev->map = &icl_reg_map;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+
+ pmc->map = &icl_reg_map;
+ return get_primary_reg_base(pmc);
}
diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c
index e8cc156412ce..2204bc666980 100644
--- a/drivers/platform/x86/intel/pmc/mtl.c
+++ b/drivers/platform/x86/intel/pmc/mtl.c
@@ -11,40 +11,937 @@
#include <linux/pci.h>
#include "core.h"
-const struct pmc_reg_map mtl_reg_map = {
- .pfear_sts = ext_tgl_pfear_map,
+/*
+ * Die Mapping to Product.
+ * Product SOCDie IOEDie PCHDie
+ * MTL-M SOC-M IOE-M None
+ * MTL-P SOC-M IOE-P None
+ * MTL-S SOC-S IOE-P PCH-S
+ */
+
+const struct pmc_bit_map mtl_socm_pfear_map[] = {
+ {"PMC", BIT(0)},
+ {"OPI", BIT(1)},
+ {"SPI", BIT(2)},
+ {"XHCI", BIT(3)},
+ {"SPA", BIT(4)},
+ {"SPB", BIT(5)},
+ {"SPC", BIT(6)},
+ {"GBE", BIT(7)},
+
+ {"SATA", BIT(0)},
+ {"DSP0", BIT(1)},
+ {"DSP1", BIT(2)},
+ {"DSP2", BIT(3)},
+ {"DSP3", BIT(4)},
+ {"SPD", BIT(5)},
+ {"LPSS", BIT(6)},
+ {"LPC", BIT(7)},
+
+ {"SMB", BIT(0)},
+ {"ISH", BIT(1)},
+ {"P2SB", BIT(2)},
+ {"NPK_VNN", BIT(3)},
+ {"SDX", BIT(4)},
+ {"SPE", BIT(5)},
+ {"FUSE", BIT(6)},
+ {"SBR8", BIT(7)},
+
+ {"RSVD24", BIT(0)},
+ {"OTG", BIT(1)},
+ {"EXI", BIT(2)},
+ {"CSE", BIT(3)},
+ {"CSME_KVM", BIT(4)},
+ {"CSME_PMT", BIT(5)},
+ {"CSME_CLINK", BIT(6)},
+ {"CSME_PTIO", BIT(7)},
+
+ {"CSME_USBR", BIT(0)},
+ {"CSME_SUSRAM", BIT(1)},
+ {"CSME_SMT1", BIT(2)},
+ {"RSVD35", BIT(3)},
+ {"CSME_SMS2", BIT(4)},
+ {"CSME_SMS", BIT(5)},
+ {"CSME_RTC", BIT(6)},
+ {"CSME_PSF", BIT(7)},
+
+ {"SBR0", BIT(0)},
+ {"SBR1", BIT(1)},
+ {"SBR2", BIT(2)},
+ {"SBR3", BIT(3)},
+ {"SBR4", BIT(4)},
+ {"SBR5", BIT(5)},
+ {"RSVD46", BIT(6)},
+ {"PSF1", BIT(7)},
+
+ {"PSF2", BIT(0)},
+ {"PSF3", BIT(1)},
+ {"PSF4", BIT(2)},
+ {"CNVI", BIT(3)},
+ {"UFSX2", BIT(4)},
+ {"EMMC", BIT(5)},
+ {"SPF", BIT(6)},
+ {"SBR6", BIT(7)},
+
+ {"SBR7", BIT(0)},
+ {"NPK_AON", BIT(1)},
+ {"HDA4", BIT(2)},
+ {"HDA5", BIT(3)},
+ {"HDA6", BIT(4)},
+ {"PSF6", BIT(5)},
+ {"RSVD62", BIT(6)},
+ {"RSVD63", BIT(7)},
+ {}
+};
+
+const struct pmc_bit_map *ext_mtl_socm_pfear_map[] = {
+ mtl_socm_pfear_map,
+ NULL
+};
+
+const struct pmc_bit_map mtl_socm_ltr_show_map[] = {
+ {"SOUTHPORT_A", CNP_PMC_LTR_SPA},
+ {"SOUTHPORT_B", CNP_PMC_LTR_SPB},
+ {"SATA", CNP_PMC_LTR_SATA},
+ {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE},
+ {"XHCI", CNP_PMC_LTR_XHCI},
+ {"SOUTHPORT_F", ADL_PMC_LTR_SPF},
+ {"ME", CNP_PMC_LTR_ME},
+ {"SATA1", CNP_PMC_LTR_EVA},
+ {"SOUTHPORT_C", CNP_PMC_LTR_SPC},
+ {"HD_AUDIO", CNP_PMC_LTR_AZ},
+ {"CNV", CNP_PMC_LTR_CNV},
+ {"LPSS", CNP_PMC_LTR_LPSS},
+ {"SOUTHPORT_D", CNP_PMC_LTR_SPD},
+ {"SOUTHPORT_E", CNP_PMC_LTR_SPE},
+ {"SATA2", CNP_PMC_LTR_CAM},
+ {"ESPI", CNP_PMC_LTR_ESPI},
+ {"SCC", CNP_PMC_LTR_SCC},
+ {"ISH", CNP_PMC_LTR_ISH},
+ {"UFSX2", CNP_PMC_LTR_UFSX2},
+ {"EMMC", CNP_PMC_LTR_EMMC},
+ {"WIGIG", ICL_PMC_LTR_WIGIG},
+ {"THC0", TGL_PMC_LTR_THC0},
+ {"THC1", TGL_PMC_LTR_THC1},
+ {"SOUTHPORT_G", MTL_PMC_LTR_SPG},
+ {"ESE", MTL_PMC_LTR_ESE},
+ {"IOE_PMC", MTL_PMC_LTR_IOE_PMC},
+
+ /* Below two cannot be used for LTR_IGNORE */
+ {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT},
+ {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_clocksource_status_map[] = {
+ {"AON2_OFF_STS", BIT(0)},
+ {"AON3_OFF_STS", BIT(1)},
+ {"AON4_OFF_STS", BIT(2)},
+ {"AON5_OFF_STS", BIT(3)},
+ {"AON1_OFF_STS", BIT(4)},
+ {"XTAL_LVM_OFF_STS", BIT(5)},
+ {"MPFPW1_0_PLL_OFF_STS", BIT(6)},
+ {"MPFPW1_1_PLL_OFF_STS", BIT(7)},
+ {"USB3_PLL_OFF_STS", BIT(8)},
+ {"AON3_SPL_OFF_STS", BIT(9)},
+ {"MPFPW2_0_PLL_OFF_STS", BIT(12)},
+ {"MPFPW3_0_PLL_OFF_STS", BIT(13)},
+ {"XTAL_AGGR_OFF_STS", BIT(17)},
+ {"USB2_PLL_OFF_STS", BIT(18)},
+ {"FILTER_PLL_OFF_STS", BIT(22)},
+ {"ACE_PLL_OFF_STS", BIT(24)},
+ {"FABRIC_PLL_OFF_STS", BIT(25)},
+ {"SOC_PLL_OFF_STS", BIT(26)},
+ {"PCIFAB_PLL_OFF_STS", BIT(27)},
+ {"REF_PLL_OFF_STS", BIT(28)},
+ {"IMG_PLL_OFF_STS", BIT(29)},
+ {"RTC_PLL_OFF_STS", BIT(31)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_power_gating_status_0_map[] = {
+ {"PMC_PGD0_PG_STS", BIT(0)},
+ {"DMI_PGD0_PG_STS", BIT(1)},
+ {"ESPISPI_PGD0_PG_STS", BIT(2)},
+ {"XHCI_PGD0_PG_STS", BIT(3)},
+ {"SPA_PGD0_PG_STS", BIT(4)},
+ {"SPB_PGD0_PG_STS", BIT(5)},
+ {"SPC_PGD0_PG_STS", BIT(6)},
+ {"GBE_PGD0_PG_STS", BIT(7)},
+ {"SATA_PGD0_PG_STS", BIT(8)},
+ {"PSF13_PGD0_PG_STS", BIT(9)},
+ {"SOC_D2D_PGD3_PG_STS", BIT(10)},
+ {"MPFPW3_PGD0_PG_STS", BIT(11)},
+ {"ESE_PGD0_PG_STS", BIT(12)},
+ {"SPD_PGD0_PG_STS", BIT(13)},
+ {"LPSS_PGD0_PG_STS", BIT(14)},
+ {"LPC_PGD0_PG_STS", BIT(15)},
+ {"SMB_PGD0_PG_STS", BIT(16)},
+ {"ISH_PGD0_PG_STS", BIT(17)},
+ {"P2S_PGD0_PG_STS", BIT(18)},
+ {"NPK_PGD0_PG_STS", BIT(19)},
+ {"DBG_SBR_PGD0_PG_STS", BIT(20)},
+ {"SBRG_PGD0_PG_STS", BIT(21)},
+ {"FUSE_PGD0_PG_STS", BIT(22)},
+ {"SBR8_PGD0_PG_STS", BIT(23)},
+ {"SOC_D2D_PGD2_PG_STS", BIT(24)},
+ {"XDCI_PGD0_PG_STS", BIT(25)},
+ {"EXI_PGD0_PG_STS", BIT(26)},
+ {"CSE_PGD0_PG_STS", BIT(27)},
+ {"KVMCC_PGD0_PG_STS", BIT(28)},
+ {"PMT_PGD0_PG_STS", BIT(29)},
+ {"CLINK_PGD0_PG_STS", BIT(30)},
+ {"PTIO_PGD0_PG_STS", BIT(31)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_power_gating_status_1_map[] = {
+ {"USBR0_PGD0_PG_STS", BIT(0)},
+ {"SUSRAM_PGD0_PG_STS", BIT(1)},
+ {"SMT1_PGD0_PG_STS", BIT(2)},
+ {"FIACPCB_U_PGD0_PG_STS", BIT(3)},
+ {"SMS2_PGD0_PG_STS", BIT(4)},
+ {"SMS1_PGD0_PG_STS", BIT(5)},
+ {"CSMERTC_PGD0_PG_STS", BIT(6)},
+ {"CSMEPSF_PGD0_PG_STS", BIT(7)},
+ {"SBR0_PGD0_PG_STS", BIT(8)},
+ {"SBR1_PGD0_PG_STS", BIT(9)},
+ {"SBR2_PGD0_PG_STS", BIT(10)},
+ {"SBR3_PGD0_PG_STS", BIT(11)},
+ {"U3FPW1_PGD0_PG_STS", BIT(12)},
+ {"SBR5_PGD0_PG_STS", BIT(13)},
+ {"MPFPW1_PGD0_PG_STS", BIT(14)},
+ {"UFSPW1_PGD0_PG_STS", BIT(15)},
+ {"FIA_X_PGD0_PG_STS", BIT(16)},
+ {"SOC_D2D_PGD0_PG_STS", BIT(17)},
+ {"MPFPW2_PGD0_PG_STS", BIT(18)},
+ {"CNVI_PGD0_PG_STS", BIT(19)},
+ {"UFSX2_PGD0_PG_STS", BIT(20)},
+ {"ENDBG_PGD0_PG_STS", BIT(21)},
+ {"DBG_PSF_PGD0_PG_STS", BIT(22)},
+ {"SBR6_PGD0_PG_STS", BIT(23)},
+ {"SBR7_PGD0_PG_STS", BIT(24)},
+ {"NPK_PGD1_PG_STS", BIT(25)},
+ {"FIACPCB_X_PGD0_PG_STS", BIT(26)},
+ {"DBC_PGD0_PG_STS", BIT(27)},
+ {"FUSEGPSB_PGD0_PG_STS", BIT(28)},
+ {"PSF6_PGD0_PG_STS", BIT(29)},
+ {"PSF7_PGD0_PG_STS", BIT(30)},
+ {"GBETSN1_PGD0_PG_STS", BIT(31)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_power_gating_status_2_map[] = {
+ {"PSF8_PGD0_PG_STS", BIT(0)},
+ {"FIA_PGD0_PG_STS", BIT(1)},
+ {"SOC_D2D_PGD1_PG_STS", BIT(2)},
+ {"FIA_U_PGD0_PG_STS", BIT(3)},
+ {"TAM_PGD0_PG_STS", BIT(4)},
+ {"GBETSN_PGD0_PG_STS", BIT(5)},
+ {"TBTLSX_PGD0_PG_STS", BIT(6)},
+ {"THC0_PGD0_PG_STS", BIT(7)},
+ {"THC1_PGD0_PG_STS", BIT(8)},
+ {"PMC_PGD1_PG_STS", BIT(9)},
+ {"GNA_PGD0_PG_STS", BIT(10)},
+ {"ACE_PGD0_PG_STS", BIT(11)},
+ {"ACE_PGD1_PG_STS", BIT(12)},
+ {"ACE_PGD2_PG_STS", BIT(13)},
+ {"ACE_PGD3_PG_STS", BIT(14)},
+ {"ACE_PGD4_PG_STS", BIT(15)},
+ {"ACE_PGD5_PG_STS", BIT(16)},
+ {"ACE_PGD6_PG_STS", BIT(17)},
+ {"ACE_PGD7_PG_STS", BIT(18)},
+ {"ACE_PGD8_PG_STS", BIT(19)},
+ {"FIA_PGS_PGD0_PG_STS", BIT(20)},
+ {"FIACPCB_PGS_PGD0_PG_STS", BIT(21)},
+ {"FUSEPMSB_PGD0_PG_STS", BIT(22)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_d3_status_0_map[] = {
+ {"LPSS_D3_STS", BIT(3)},
+ {"XDCI_D3_STS", BIT(4)},
+ {"XHCI_D3_STS", BIT(5)},
+ {"SPA_D3_STS", BIT(12)},
+ {"SPB_D3_STS", BIT(13)},
+ {"SPC_D3_STS", BIT(14)},
+ {"SPD_D3_STS", BIT(15)},
+ {"ESPISPI_D3_STS", BIT(18)},
+ {"SATA_D3_STS", BIT(20)},
+ {"PSTH_D3_STS", BIT(21)},
+ {"DMI_D3_STS", BIT(22)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_d3_status_1_map[] = {
+ {"GBETSN1_D3_STS", BIT(14)},
+ {"GBE_D3_STS", BIT(19)},
+ {"ITSS_D3_STS", BIT(23)},
+ {"P2S_D3_STS", BIT(24)},
+ {"CNVI_D3_STS", BIT(27)},
+ {"UFSX2_D3_STS", BIT(28)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_d3_status_2_map[] = {
+ {"GNA_D3_STS", BIT(0)},
+ {"CSMERTC_D3_STS", BIT(1)},
+ {"SUSRAM_D3_STS", BIT(2)},
+ {"CSE_D3_STS", BIT(4)},
+ {"KVMCC_D3_STS", BIT(5)},
+ {"USBR0_D3_STS", BIT(6)},
+ {"ISH_D3_STS", BIT(7)},
+ {"SMT1_D3_STS", BIT(8)},
+ {"SMT2_D3_STS", BIT(9)},
+ {"SMT3_D3_STS", BIT(10)},
+ {"CLINK_D3_STS", BIT(14)},
+ {"PTIO_D3_STS", BIT(16)},
+ {"PMT_D3_STS", BIT(17)},
+ {"SMS1_D3_STS", BIT(18)},
+ {"SMS2_D3_STS", BIT(19)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_d3_status_3_map[] = {
+ {"ESE_D3_STS", BIT(2)},
+ {"GBETSN_D3_STS", BIT(13)},
+ {"THC0_D3_STS", BIT(14)},
+ {"THC1_D3_STS", BIT(15)},
+ {"ACE_D3_STS", BIT(23)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_vnn_req_status_0_map[] = {
+ {"LPSS_VNN_REQ_STS", BIT(3)},
+ {"FIA_VNN_REQ_STS", BIT(17)},
+ {"ESPISPI_VNN_REQ_STS", BIT(18)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_vnn_req_status_1_map[] = {
+ {"NPK_VNN_REQ_STS", BIT(4)},
+ {"DFXAGG_VNN_REQ_STS", BIT(8)},
+ {"EXI_VNN_REQ_STS", BIT(9)},
+ {"P2D_VNN_REQ_STS", BIT(18)},
+ {"GBE_VNN_REQ_STS", BIT(19)},
+ {"SMB_VNN_REQ_STS", BIT(25)},
+ {"LPC_VNN_REQ_STS", BIT(26)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_vnn_req_status_2_map[] = {
+ {"CSMERTC_VNN_REQ_STS", BIT(1)},
+ {"CSE_VNN_REQ_STS", BIT(4)},
+ {"ISH_VNN_REQ_STS", BIT(7)},
+ {"SMT1_VNN_REQ_STS", BIT(8)},
+ {"CLINK_VNN_REQ_STS", BIT(14)},
+ {"SMS1_VNN_REQ_STS", BIT(18)},
+ {"SMS2_VNN_REQ_STS", BIT(19)},
+ {"GPIOCOM4_VNN_REQ_STS", BIT(20)},
+ {"GPIOCOM3_VNN_REQ_STS", BIT(21)},
+ {"GPIOCOM2_VNN_REQ_STS", BIT(22)},
+ {"GPIOCOM1_VNN_REQ_STS", BIT(23)},
+ {"GPIOCOM0_VNN_REQ_STS", BIT(24)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[] = {
+ {"ESE_VNN_REQ_STS", BIT(2)},
+ {"DTS0_VNN_REQ_STS", BIT(7)},
+ {"GPIOCOM5_VNN_REQ_STS", BIT(11)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_vnn_misc_status_map[] = {
+ {"CPU_C10_REQ_STS", BIT(0)},
+ {"TS_OFF_REQ_STS", BIT(1)},
+ {"PNDE_MET_REQ_STS", BIT(2)},
+ {"PCIE_DEEP_PM_REQ_STS", BIT(3)},
+ {"PMC_CLK_THROTTLE_EN_REQ_STS", BIT(4)},
+ {"NPK_VNNAON_REQ_STS", BIT(5)},
+ {"VNN_SOC_REQ_STS", BIT(6)},
+ {"ISH_VNNAON_REQ_STS", BIT(7)},
+ {"IOE_COND_MET_S02I2_0_REQ_STS", BIT(8)},
+ {"IOE_COND_MET_S02I2_1_REQ_STS", BIT(9)},
+ {"IOE_COND_MET_S02I2_2_REQ_STS", BIT(10)},
+ {"PLT_GREATER_REQ_STS", BIT(11)},
+ {"PCIE_CLKREQ_REQ_STS", BIT(12)},
+ {"PMC_IDLE_FB_OCP_REQ_STS", BIT(13)},
+ {"PM_SYNC_STATES_REQ_STS", BIT(14)},
+ {"EA_REQ_STS", BIT(15)},
+ {"MPHY_CORE_OFF_REQ_STS", BIT(16)},
+ {"BRK_EV_EN_REQ_STS", BIT(17)},
+ {"AUTO_DEMO_EN_REQ_STS", BIT(18)},
+ {"ITSS_CLK_SRC_REQ_STS", BIT(19)},
+ {"LPC_CLK_SRC_REQ_STS", BIT(20)},
+ {"ARC_IDLE_REQ_STS", BIT(21)},
+ {"MPHY_SUS_REQ_STS", BIT(22)},
+ {"FIA_DEEP_PM_REQ_STS", BIT(23)},
+ {"UXD_CONNECTED_REQ_STS", BIT(24)},
+ {"ARC_INTERRUPT_WAKE_REQ_STS", BIT(25)},
+ {"USB2_VNNAON_ACT_REQ_STS", BIT(26)},
+ {"PRE_WAKE0_REQ_STS", BIT(27)},
+ {"PRE_WAKE1_REQ_STS", BIT(28)},
+ {"PRE_WAKE2_EN_REQ_STS", BIT(29)},
+ {"WOV_REQ_STS", BIT(30)},
+ {"CNVI_V1P05_REQ_STS", BIT(31)},
+ {}
+};
+
+const struct pmc_bit_map mtl_socm_signal_status_map[] = {
+ {"LSX_Wake0_En_STS", BIT(0)},
+ {"LSX_Wake0_Pol_STS", BIT(1)},
+ {"LSX_Wake1_En_STS", BIT(2)},
+ {"LSX_Wake1_Pol_STS", BIT(3)},
+ {"LSX_Wake2_En_STS", BIT(4)},
+ {"LSX_Wake2_Pol_STS", BIT(5)},
+ {"LSX_Wake3_En_STS", BIT(6)},
+ {"LSX_Wake3_Pol_STS", BIT(7)},
+ {"LSX_Wake4_En_STS", BIT(8)},
+ {"LSX_Wake4_Pol_STS", BIT(9)},
+ {"LSX_Wake5_En_STS", BIT(10)},
+ {"LSX_Wake5_Pol_STS", BIT(11)},
+ {"LSX_Wake6_En_STS", BIT(12)},
+ {"LSX_Wake6_Pol_STS", BIT(13)},
+ {"LSX_Wake7_En_STS", BIT(14)},
+ {"LSX_Wake7_Pol_STS", BIT(15)},
+ {"LPSS_Wake0_En_STS", BIT(16)},
+ {"LPSS_Wake0_Pol_STS", BIT(17)},
+ {"LPSS_Wake1_En_STS", BIT(18)},
+ {"LPSS_Wake1_Pol_STS", BIT(19)},
+ {"Int_Timer_SS_Wake0_En_STS", BIT(20)},
+ {"Int_Timer_SS_Wake0_Pol_STS", BIT(21)},
+ {"Int_Timer_SS_Wake1_En_STS", BIT(22)},
+ {"Int_Timer_SS_Wake1_Pol_STS", BIT(23)},
+ {"Int_Timer_SS_Wake2_En_STS", BIT(24)},
+ {"Int_Timer_SS_Wake2_Pol_STS", BIT(25)},
+ {"Int_Timer_SS_Wake3_En_STS", BIT(26)},
+ {"Int_Timer_SS_Wake3_Pol_STS", BIT(27)},
+ {"Int_Timer_SS_Wake4_En_STS", BIT(28)},
+ {"Int_Timer_SS_Wake4_Pol_STS", BIT(29)},
+ {"Int_Timer_SS_Wake5_En_STS", BIT(30)},
+ {"Int_Timer_SS_Wake5_Pol_STS", BIT(31)},
+ {}
+};
+
+const struct pmc_bit_map *mtl_socm_lpm_maps[] = {
+ mtl_socm_clocksource_status_map,
+ mtl_socm_power_gating_status_0_map,
+ mtl_socm_power_gating_status_1_map,
+ mtl_socm_power_gating_status_2_map,
+ mtl_socm_d3_status_0_map,
+ mtl_socm_d3_status_1_map,
+ mtl_socm_d3_status_2_map,
+ mtl_socm_d3_status_3_map,
+ mtl_socm_vnn_req_status_0_map,
+ mtl_socm_vnn_req_status_1_map,
+ mtl_socm_vnn_req_status_2_map,
+ mtl_socm_vnn_req_status_3_map,
+ mtl_socm_vnn_misc_status_map,
+ mtl_socm_signal_status_map,
+ NULL
+};
+
+const struct pmc_reg_map mtl_socm_reg_map = {
+ .pfear_sts = ext_mtl_socm_pfear_map,
.slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
.slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP,
- .ltr_show_sts = adl_ltr_show_map,
+ .ltr_show_sts = mtl_socm_ltr_show_map,
.msr_sts = msr_map,
.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
- .regmap_length = CNP_PMC_MMIO_REG_LEN,
+ .regmap_length = MTL_SOC_PMC_MMIO_REG_LEN,
.ppfear0_offset = CNP_PMC_HOST_PPFEAR0A,
- .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES,
+ .ppfear_buckets = MTL_SOCM_PPFEAR_NUM_ENTRIES,
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
- .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED,
- .lpm_num_modes = ADL_LPM_NUM_MODES,
.lpm_num_maps = ADL_LPM_NUM_MAPS,
+ .ltr_ignore_max = MTL_SOCM_NUM_IP_IGN_ALLOWED,
.lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,
.etr3_offset = ETR3_OFFSET,
.lpm_sts_latch_en_offset = MTL_LPM_STATUS_LATCH_EN_OFFSET,
.lpm_priority_offset = MTL_LPM_PRI_OFFSET,
.lpm_en_offset = MTL_LPM_EN_OFFSET,
.lpm_residency_offset = MTL_LPM_RESIDENCY_OFFSET,
- .lpm_sts = adl_lpm_maps,
+ .lpm_sts = mtl_socm_lpm_maps,
.lpm_status_offset = MTL_LPM_STATUS_OFFSET,
.lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,
};
-void mtl_core_configure(struct pmc_dev *pmcdev)
-{
- /* Due to a hardware limitation, the GBE LTR blocks PC10
- * when a cable is attached. Tell the PMC to ignore it.
- */
- dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n");
- pmc_core_send_ltr_ignore(pmcdev, 3);
-}
+const struct pmc_bit_map mtl_ioep_pfear_map[] = {
+ {"PMC_0", BIT(0)},
+ {"OPI", BIT(1)},
+ {"TCSS", BIT(2)},
+ {"RSVD3", BIT(3)},
+ {"SPA", BIT(4)},
+ {"SPB", BIT(5)},
+ {"SPC", BIT(6)},
+ {"IOE_D2D_3", BIT(7)},
+
+ {"RSVD8", BIT(0)},
+ {"RSVD9", BIT(1)},
+ {"SPE", BIT(2)},
+ {"RSVD11", BIT(3)},
+ {"RSVD12", BIT(4)},
+ {"SPD", BIT(5)},
+ {"ACE_7", BIT(6)},
+ {"RSVD15", BIT(7)},
+
+ {"ACE_0", BIT(0)},
+ {"FIACPCB_P", BIT(1)},
+ {"P2S", BIT(2)},
+ {"RSVD19", BIT(3)},
+ {"ACE_8", BIT(4)},
+ {"IOE_D2D_0", BIT(5)},
+ {"FUSE", BIT(6)},
+ {"RSVD23", BIT(7)},
+
+ {"FIACPCB_P5", BIT(0)},
+ {"ACE_3", BIT(1)},
+ {"RSF5", BIT(2)},
+ {"ACE_2", BIT(3)},
+ {"ACE_4", BIT(4)},
+ {"RSVD29", BIT(5)},
+ {"RSF10", BIT(6)},
+ {"MPFPW5", BIT(7)},
+
+ {"PSF9", BIT(0)},
+ {"MPFPW4", BIT(1)},
+ {"RSVD34", BIT(2)},
+ {"RSVD35", BIT(3)},
+ {"RSVD36", BIT(4)},
+ {"RSVD37", BIT(5)},
+ {"RSVD38", BIT(6)},
+ {"RSVD39", BIT(7)},
+
+ {"SBR0", BIT(0)},
+ {"SBR1", BIT(1)},
+ {"SBR2", BIT(2)},
+ {"SBR3", BIT(3)},
+ {"SBR4", BIT(4)},
+ {"SBR5", BIT(5)},
+ {"RSVD46", BIT(6)},
+ {"RSVD47", BIT(7)},
+
+ {"RSVD48", BIT(0)},
+ {"FIA_P5", BIT(1)},
+ {"RSVD50", BIT(2)},
+ {"RSVD51", BIT(3)},
+ {"RSVD52", BIT(4)},
+ {"RSVD53", BIT(5)},
+ {"RSVD54", BIT(6)},
+ {"ACE_1", BIT(7)},
+
+ {"RSVD56", BIT(0)},
+ {"ACE_5", BIT(1)},
+ {"RSVD58", BIT(2)},
+ {"G5FPW1", BIT(3)},
+ {"RSVD60", BIT(4)},
+ {"ACE_6", BIT(5)},
+ {"RSVD62", BIT(6)},
+ {"GBETSN1", BIT(7)},
+
+ {"RSVD64", BIT(0)},
+ {"FIA", BIT(1)},
+ {"RSVD66", BIT(2)},
+ {"FIA_P", BIT(3)},
+ {"TAM", BIT(4)},
+ {"GBETSN", BIT(5)},
+ {"IOE_D2D_2", BIT(6)},
+ {"IOE_D2D_1", BIT(7)},
+
+ {"SPF", BIT(0)},
+ {"PMC_1", BIT(1)},
+ {}
+};
+
+const struct pmc_bit_map *ext_mtl_ioep_pfear_map[] = {
+ mtl_ioep_pfear_map,
+ NULL
+};
+
+const struct pmc_bit_map mtl_ioep_ltr_show_map[] = {
+ {"SOUTHPORT_A", CNP_PMC_LTR_SPA},
+ {"SOUTHPORT_B", CNP_PMC_LTR_SPB},
+ {"SATA", CNP_PMC_LTR_SATA},
+ {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE},
+ {"XHCI", CNP_PMC_LTR_XHCI},
+ {"SOUTHPORT_F", ADL_PMC_LTR_SPF},
+ {"ME", CNP_PMC_LTR_ME},
+ {"SATA1", CNP_PMC_LTR_EVA},
+ {"SOUTHPORT_C", CNP_PMC_LTR_SPC},
+ {"HD_AUDIO", CNP_PMC_LTR_AZ},
+ {"CNV", CNP_PMC_LTR_CNV},
+ {"LPSS", CNP_PMC_LTR_LPSS},
+ {"SOUTHPORT_D", CNP_PMC_LTR_SPD},
+ {"SOUTHPORT_E", CNP_PMC_LTR_SPE},
+ {"SATA2", CNP_PMC_LTR_CAM},
+ {"ESPI", CNP_PMC_LTR_ESPI},
+ {"SCC", CNP_PMC_LTR_SCC},
+ {"Reserved", MTL_PMC_LTR_RESERVED},
+ {"UFSX2", CNP_PMC_LTR_UFSX2},
+ {"EMMC", CNP_PMC_LTR_EMMC},
+ {"WIGIG", ICL_PMC_LTR_WIGIG},
+ {"THC0", TGL_PMC_LTR_THC0},
+ {"THC1", TGL_PMC_LTR_THC1},
+ {"SOUTHPORT_G", MTL_PMC_LTR_SPG},
+
+ /* Below two cannot be used for LTR_IGNORE */
+ {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT},
+ {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT},
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_clocksource_status_map[] = {
+ {"AON2_OFF_STS", BIT(0)},
+ {"AON3_OFF_STS", BIT(1)},
+ {"AON4_OFF_STS", BIT(2)},
+ {"AON5_OFF_STS", BIT(3)},
+ {"AON1_OFF_STS", BIT(4)},
+ {"TBT_PLL_OFF_STS", BIT(5)},
+ {"TMU_PLL_OFF_STS", BIT(6)},
+ {"BCLK_PLL_OFF_STS", BIT(7)},
+ {"D2D_PLL_OFF_STS", BIT(8)},
+ {"AON3_SPL_OFF_STS", BIT(9)},
+ {"MPFPW4_0_PLL_OFF_STS", BIT(12)},
+ {"MPFPW5_0_PLL_OFF_STS", BIT(13)},
+ {"G5FPW_0_PLL_OFF_STS", BIT(14)},
+ {"G5FPW_1_PLL_OFF_STS", BIT(15)},
+ {"XTAL_AGGR_OFF_STS", BIT(17)},
+ {"FABRIC_PLL_OFF_STS", BIT(25)},
+ {"SOC_PLL_OFF_STS", BIT(26)},
+ {"REF_PLL_OFF_STS", BIT(28)},
+ {"RTC_PLL_OFF_STS", BIT(31)},
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[] = {
+ {"PMC_PGD0_PG_STS", BIT(0)},
+ {"DMI_PGD0_PG_STS", BIT(1)},
+ {"TCSS_PGD0_PG_STS", BIT(2)},
+ {"SPA_PGD0_PG_STS", BIT(4)},
+ {"SPB_PGD0_PG_STS", BIT(5)},
+ {"SPC_PGD0_PG_STS", BIT(6)},
+ {"IOE_D2D_PGD3_PG_STS", BIT(7)},
+ {"SPE_PGD0_PG_STS", BIT(10)},
+ {"SPD_PGD0_PG_STS", BIT(13)},
+ {"ACE_PGD7_PG_STS", BIT(14)},
+ {"ACE_PGD0_PG_STS", BIT(16)},
+ {"FIACPCB_P_PGD0_PG_STS", BIT(17)},
+ {"P2S_PGD0_PG_STS", BIT(18)},
+ {"ACE_PGD8_PG_STS", BIT(20)},
+ {"IOE_D2D_PGD0_PG_STS", BIT(21)},
+ {"FUSE_PGD0_PG_STS", BIT(22)},
+ {"FIACPCB_P5_PGD0_PG_STS", BIT(24)},
+ {"ACE_PGD3_PG_STS", BIT(25)},
+ {"PSF5_PGD0_PG_STS", BIT(26)},
+ {"ACE_PGD2_PG_STS", BIT(27)},
+ {"ACE_PGD4_PG_STS", BIT(28)},
+ {"PSF10_PGD0_PG_STS", BIT(30)},
+ {"MPFPW5_PGD0_PG_STS", BIT(31)},
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[] = {
+ {"PSF9_PGD0_PG_STS", BIT(0)},
+ {"MPFPW4_PGD0_PG_STS", BIT(1)},
+ {"SBR0_PGD0_PG_STS", BIT(8)},
+ {"SBR1_PGD0_PG_STS", BIT(9)},
+ {"SBR2_PGD0_PG_STS", BIT(10)},
+ {"SBR3_PGD0_PG_STS", BIT(11)},
+ {"SBR4_PGD0_PG_STS", BIT(12)},
+ {"SBR5_PGD0_PG_STS", BIT(13)},
+ {"FIA_P5_PGD0_PG_STS", BIT(17)},
+ {"ACE_PGD1_PGD0_PG_STS", BIT(23)},
+ {"ACE_PGD5_PGD1_PG_STS", BIT(25)},
+ {"G5FPW1_PGD0_PG_STS", BIT(27)},
+ {"ACE_PGD6_PG_STS", BIT(29)},
+ {"GBETSN1_PGD0_PG_STS", BIT(31)},
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[] = {
+ {"FIA_PGD0_PG_STS", BIT(1)},
+ {"FIA_P_PGD0_PG_STS", BIT(3)},
+ {"TAM_PGD0_PG_STS", BIT(4)},
+ {"GBETSN_PGD0_PG_STS", BIT(5)},
+ {"IOE_D2D_PGD2_PG_STS", BIT(6)},
+ {"IOE_D2D_PGD1_PG_STS", BIT(7)},
+ {"SPF_PGD0_PG_STS", BIT(8)},
+ {"PMC_PGD1_PG_STS", BIT(9)},
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_d3_status_0_map[] = {
+ {"SPF_D3_STS", BIT(0)},
+ {"SPA_D3_STS", BIT(12)},
+ {"SPB_D3_STS", BIT(13)},
+ {"SPC_D3_STS", BIT(14)},
+ {"SPD_D3_STS", BIT(15)},
+ {"SPE_D3_STS", BIT(16)},
+ {"DMI_D3_STS", BIT(22)},
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_d3_status_1_map[] = {
+ {"GBETSN1_D3_STS", BIT(14)},
+ {"P2S_D3_STS", BIT(24)},
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_d3_status_2_map[] = {
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_d3_status_3_map[] = {
+ {"GBETSN_D3_STS", BIT(13)},
+ {"ACE_D3_STS", BIT(23)},
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[] = {
+ {"FIA_VNN_REQ_STS", BIT(17)},
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[] = {
+ {"DFXAGG_VNN_REQ_STS", BIT(8)},
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[] = {
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[] = {
+ {"DTS0_VNN_REQ_STS", BIT(7)},
+ {"DISP_VNN_REQ_STS", BIT(19)},
+ {}
+};
+
+const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[] = {
+ {"CPU_C10_REQ_STS", BIT(0)},
+ {"TS_OFF_REQ_STS", BIT(1)},
+ {"PNDE_MET_REQ_STS", BIT(2)},
+ {"PCIE_DEEP_PM_REQ_STS", BIT(3)},
+ {"PMC_CLK_THROTTLE_EN_REQ_STS", BIT(4)},
+ {"NPK_VNNAON_REQ_STS", BIT(5)},
+ {"VNN_SOC_REQ_STS", BIT(6)},
+ {"USB_DEVICE_ATTACHED_REQ_STS", BIT(8)},
+ {"FIA_EXIT_REQ_STS", BIT(9)},
+ {"USB2_SUS_PG_REQ_STS", BIT(10)},
+ {"PLT_GREATER_REQ_STS", BIT(11)},
+ {"PCIE_CLKREQ_REQ_STS", BIT(12)},
+ {"PMC_IDLE_FB_OCP_REQ_STS", BIT(13)},
+ {"PM_SYNC_STATES_REQ_STS", BIT(14)},
+ {"EA_REQ_STS", BIT(15)},
+ {"MPHY_CORE_OFF_REQ_STS", BIT(16)},
+ {"BRK_EV_EN_REQ_STS", BIT(17)},
+ {"AUTO_DEMO_EN_REQ_STS", BIT(18)},
+ {"ITSS_CLK_SRC_REQ_STS", BIT(19)},
+ {"LPC_CLK_SRC_REQ_STS", BIT(20)},
+ {"ARC_IDLE_REQ_STS", BIT(21)},
+ {"MPHY_SUS_REQ_STS", BIT(22)},
+ {"FIA_DEEP_PM_REQ_STS", BIT(23)},
+ {"UXD_CONNECTED_REQ_STS", BIT(24)},
+ {"ARC_INTERRUPT_WAKE_REQ_STS", BIT(25)},
+ {"USB2_VNNAON_ACT_REQ_STS", BIT(26)},
+ {"PRE_WAKE0_REQ_STS", BIT(27)},
+ {"PRE_WAKE1_REQ_STS", BIT(28)},
+ {"PRE_WAKE2_EN_REQ_STS", BIT(29)},
+ {"WOV_REQ_STS", BIT(30)},
+ {"CNVI_V1P05_REQ_STS", BIT(31)},
+ {}
+};
+
+const struct pmc_bit_map *mtl_ioep_lpm_maps[] = {
+ mtl_ioep_clocksource_status_map,
+ mtl_ioep_power_gating_status_0_map,
+ mtl_ioep_power_gating_status_1_map,
+ mtl_ioep_power_gating_status_2_map,
+ mtl_ioep_d3_status_0_map,
+ mtl_ioep_d3_status_1_map,
+ mtl_ioep_d3_status_2_map,
+ mtl_ioep_d3_status_3_map,
+ mtl_ioep_vnn_req_status_0_map,
+ mtl_ioep_vnn_req_status_1_map,
+ mtl_ioep_vnn_req_status_2_map,
+ mtl_ioep_vnn_req_status_3_map,
+ mtl_ioep_vnn_misc_status_map,
+ mtl_socm_signal_status_map,
+ NULL
+};
+
+const struct pmc_reg_map mtl_ioep_reg_map = {
+ .regmap_length = MTL_IOE_PMC_MMIO_REG_LEN,
+ .pfear_sts = ext_mtl_ioep_pfear_map,
+ .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A,
+ .ppfear_buckets = MTL_IOE_PPFEAR_NUM_ENTRIES,
+ .lpm_status_offset = MTL_LPM_STATUS_OFFSET,
+ .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,
+ .lpm_sts = mtl_ioep_lpm_maps,
+ .ltr_show_sts = mtl_ioep_ltr_show_map,
+ .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
+ .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED,
+};
+
+const struct pmc_bit_map mtl_ioem_pfear_map[] = {
+ {"PMC_0", BIT(0)},
+ {"OPI", BIT(1)},
+ {"TCSS", BIT(2)},
+ {"RSVD3", BIT(3)},
+ {"SPA", BIT(4)},
+ {"SPB", BIT(5)},
+ {"SPC", BIT(6)},
+ {"IOE_D2D_3", BIT(7)},
+
+ {"RSVD8", BIT(0)},
+ {"RSVD9", BIT(1)},
+ {"SPE", BIT(2)},
+ {"RSVD11", BIT(3)},
+ {"RSVD12", BIT(4)},
+ {"SPD", BIT(5)},
+ {"ACE_7", BIT(6)},
+ {"RSVD15", BIT(7)},
+
+ {"ACE_0", BIT(0)},
+ {"FIACPCB_P", BIT(1)},
+ {"P2S", BIT(2)},
+ {"RSVD19", BIT(3)},
+ {"ACE_8", BIT(4)},
+ {"IOE_D2D_0", BIT(5)},
+ {"FUSE", BIT(6)},
+ {"RSVD23", BIT(7)},
+
+ {"FIACPCB_P5", BIT(0)},
+ {"ACE_3", BIT(1)},
+ {"RSF5", BIT(2)},
+ {"ACE_2", BIT(3)},
+ {"ACE_4", BIT(4)},
+ {"RSVD29", BIT(5)},
+ {"RSF10", BIT(6)},
+ {"MPFPW5", BIT(7)},
+
+ {"PSF9", BIT(0)},
+ {"MPFPW4", BIT(1)},
+ {"RSVD34", BIT(2)},
+ {"RSVD35", BIT(3)},
+ {"RSVD36", BIT(4)},
+ {"RSVD37", BIT(5)},
+ {"RSVD38", BIT(6)},
+ {"RSVD39", BIT(7)},
+
+ {"SBR0", BIT(0)},
+ {"SBR1", BIT(1)},
+ {"SBR2", BIT(2)},
+ {"SBR3", BIT(3)},
+ {"SBR4", BIT(4)},
+ {"RSVD45", BIT(5)},
+ {"RSVD46", BIT(6)},
+ {"RSVD47", BIT(7)},
+
+ {"RSVD48", BIT(0)},
+ {"FIA_P5", BIT(1)},
+ {"RSVD50", BIT(2)},
+ {"RSVD51", BIT(3)},
+ {"RSVD52", BIT(4)},
+ {"RSVD53", BIT(5)},
+ {"RSVD54", BIT(6)},
+ {"ACE_1", BIT(7)},
+
+ {"RSVD56", BIT(0)},
+ {"ACE_5", BIT(1)},
+ {"RSVD58", BIT(2)},
+ {"G5FPW1", BIT(3)},
+ {"RSVD60", BIT(4)},
+ {"ACE_6", BIT(5)},
+ {"RSVD62", BIT(6)},
+ {"GBETSN1", BIT(7)},
+
+ {"RSVD64", BIT(0)},
+ {"FIA", BIT(1)},
+ {"RSVD66", BIT(2)},
+ {"FIA_P", BIT(3)},
+ {"TAM", BIT(4)},
+ {"GBETSN", BIT(5)},
+ {"IOE_D2D_2", BIT(6)},
+ {"IOE_D2D_1", BIT(7)},
+
+ {"SPF", BIT(0)},
+ {"PMC_1", BIT(1)},
+ {}
+};
+
+const struct pmc_bit_map *ext_mtl_ioem_pfear_map[] = {
+ mtl_ioem_pfear_map,
+ NULL
+};
+
+const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[] = {
+ {"PSF9_PGD0_PG_STS", BIT(0)},
+ {"MPFPW4_PGD0_PG_STS", BIT(1)},
+ {"SBR0_PGD0_PG_STS", BIT(8)},
+ {"SBR1_PGD0_PG_STS", BIT(9)},
+ {"SBR2_PGD0_PG_STS", BIT(10)},
+ {"SBR3_PGD0_PG_STS", BIT(11)},
+ {"SBR4_PGD0_PG_STS", BIT(12)},
+ {"FIA_P5_PGD0_PG_STS", BIT(17)},
+ {"ACE_PGD1_PGD0_PG_STS", BIT(23)},
+ {"ACE_PGD5_PGD1_PG_STS", BIT(25)},
+ {"G5FPW1_PGD0_PG_STS", BIT(27)},
+ {"ACE_PGD6_PG_STS", BIT(29)},
+ {"GBETSN1_PGD0_PG_STS", BIT(31)},
+ {}
+};
+
+const struct pmc_bit_map *mtl_ioem_lpm_maps[] = {
+ mtl_ioep_clocksource_status_map,
+ mtl_ioep_power_gating_status_0_map,
+ mtl_ioem_power_gating_status_1_map,
+ mtl_ioep_power_gating_status_2_map,
+ mtl_ioep_d3_status_0_map,
+ mtl_ioep_d3_status_1_map,
+ mtl_ioep_d3_status_2_map,
+ mtl_ioep_d3_status_3_map,
+ mtl_ioep_vnn_req_status_0_map,
+ mtl_ioep_vnn_req_status_1_map,
+ mtl_ioep_vnn_req_status_2_map,
+ mtl_ioep_vnn_req_status_3_map,
+ mtl_ioep_vnn_misc_status_map,
+ mtl_socm_signal_status_map,
+ NULL
+};
+
+const struct pmc_reg_map mtl_ioem_reg_map = {
+ .regmap_length = MTL_IOE_PMC_MMIO_REG_LEN,
+ .pfear_sts = ext_mtl_ioem_pfear_map,
+ .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A,
+ .ppfear_buckets = MTL_IOE_PPFEAR_NUM_ENTRIES,
+ .lpm_status_offset = MTL_LPM_STATUS_OFFSET,
+ .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,
+ .lpm_sts = mtl_ioem_lpm_maps,
+ .ltr_show_sts = mtl_ioep_ltr_show_map,
+ .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
+ .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED,
+};
+
+#define PMC_DEVID_SOCM 0x7e7f
+#define PMC_DEVID_IOEP 0x7ecf
+#define PMC_DEVID_IOEM 0x7ebf
+static struct pmc_info mtl_pmc_info_list[] = {
+ {
+ .devid = PMC_DEVID_SOCM,
+ .map = &mtl_socm_reg_map,
+ },
+ {
+ .devid = PMC_DEVID_IOEP,
+ .map = &mtl_ioep_reg_map,
+ },
+ {
+ .devid = PMC_DEVID_IOEM,
+ .map = &mtl_ioem_reg_map
+ },
+ {}
+};
#define MTL_GNA_PCI_DEV 0x7e4c
#define MTL_IPU_PCI_DEV 0x7d19
@@ -68,16 +965,48 @@ static void mtl_set_device_d3(unsigned int device)
}
}
-void mtl_core_init(struct pmc_dev *pmcdev)
+/*
+ * Set power state of select devices that do not have drivers to D3
+ * so that they do not block Package C entry.
+ */
+static void mtl_d3_fixup(void)
{
- pmcdev->map = &mtl_reg_map;
- pmcdev->core_configure = mtl_core_configure;
-
- /*
- * Set power state of select devices that do not have drivers to D3
- * so that they do not block Package C entry.
- */
mtl_set_device_d3(MTL_GNA_PCI_DEV);
mtl_set_device_d3(MTL_IPU_PCI_DEV);
mtl_set_device_d3(MTL_VPU_PCI_DEV);
}
+
+static int mtl_resume(struct pmc_dev *pmcdev)
+{
+ mtl_d3_fixup();
+ return pmc_core_resume_common(pmcdev);
+}
+
+int mtl_core_init(struct pmc_dev *pmcdev)
+{
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC];
+ int ret = 0;
+
+ mtl_d3_fixup();
+
+ pmcdev->resume = mtl_resume;
+
+ pmcdev->regmap_list = mtl_pmc_info_list;
+ pmc_core_ssram_init(pmcdev);
+
+ /* If regbase not assigned, set map and discover using legacy method */
+ if (!pmc->regbase) {
+ pmc->map = &mtl_socm_reg_map;
+ ret = get_primary_reg_base(pmc);
+ if (ret)
+ return ret;
+ }
+
+ /* Due to a hardware limitation, the GBE LTR blocks PC10
+ * when a cable is attached. Tell the PMC to ignore it.
+ */
+ dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n");
+ pmc_core_send_ltr_ignore(pmcdev, 3);
+
+ return 0;
+}
diff --git a/drivers/platform/x86/intel/pmc/spt.c b/drivers/platform/x86/intel/pmc/spt.c
index e16982236778..4b6f5cbda16c 100644
--- a/drivers/platform/x86/intel/pmc/spt.c
+++ b/drivers/platform/x86/intel/pmc/spt.c
@@ -134,7 +134,10 @@ const struct pmc_reg_map spt_reg_map = {
.pm_vric1_offset = SPT_PMC_VRIC1_OFFSET,
};
-void spt_core_init(struct pmc_dev *pmcdev)
+int spt_core_init(struct pmc_dev *pmcdev)
{
- pmcdev->map = &spt_reg_map;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+
+ pmc->map = &spt_reg_map;
+ return get_primary_reg_base(pmc);
}
diff --git a/drivers/platform/x86/intel/pmc/tgl.c b/drivers/platform/x86/intel/pmc/tgl.c
index c245ada849d0..2449940102db 100644
--- a/drivers/platform/x86/intel/pmc/tgl.c
+++ b/drivers/platform/x86/intel/pmc/tgl.c
@@ -208,7 +208,8 @@ const struct pmc_reg_map tgl_reg_map = {
void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev)
{
struct pmc_dev *pmcdev = platform_get_drvdata(pdev);
- const int num_maps = pmcdev->map->lpm_num_maps;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ const int num_maps = pmc->map->lpm_num_maps;
u32 lpm_size = LPM_MAX_NUM_MODES * num_maps * 4;
union acpi_object *out_obj;
struct acpi_device *adev;
@@ -246,24 +247,28 @@ void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev)
goto free_acpi_obj;
memcpy(lpm_req_regs, addr, lpm_size);
- pmcdev->lpm_req_regs = lpm_req_regs;
+ pmc->lpm_req_regs = lpm_req_regs;
free_acpi_obj:
ACPI_FREE(out_obj);
}
-void tgl_core_configure(struct pmc_dev *pmcdev)
+int tgl_core_init(struct pmc_dev *pmcdev)
{
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
+ int ret;
+
+ pmc->map = &tgl_reg_map;
+ ret = get_primary_reg_base(pmc);
+ if (ret)
+ return ret;
+
pmc_core_get_tgl_lpm_reqs(pmcdev->pdev);
/* Due to a hardware limitation, the GBE LTR blocks PC10
* when a cable is attached. Tell the PMC to ignore it.
*/
dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n");
pmc_core_send_ltr_ignore(pmcdev, 3);
-}
-void tgl_core_init(struct pmc_dev *pmcdev)
-{
- pmcdev->map = &tgl_reg_map;
- pmcdev->core_configure = tgl_core_configure;
+ return 0;
}
diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
index 02fe360a59c7..1f59ac55c5f7 100644
--- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
@@ -829,6 +829,7 @@ void isst_if_cdev_unregister(int device_type)
{
isst_misc_unreg();
mutex_lock(&punit_misc_dev_open_lock);
+ punit_callbacks[device_type].def_ioctl = NULL;
punit_callbacks[device_type].registered = 0;
if (device_type == ISST_IF_DEV_MBOX)
isst_delete_hash();
diff --git a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
index 664d2ee60385..63faa2ea8327 100644
--- a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
@@ -1414,6 +1414,8 @@ int tpmi_sst_init(void)
ret = isst_if_cdev_register(ISST_IF_DEV_TPMI, &cb);
if (ret)
kfree(isst_common.sst_inst);
+ else
+ ++isst_core_usage_count;
init_done:
mutex_unlock(&isst_tpmi_dev_lock);
return ret;
diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c
index a5227951decc..9c606ee2030c 100644
--- a/drivers/platform/x86/intel/tpmi.c
+++ b/drivers/platform/x86/intel/tpmi.c
@@ -222,7 +222,7 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
snprintf(feature_id_name, sizeof(feature_id_name), "tpmi-%s", name);
for (i = 0, tmp = res; i < pfs->pfs_header.num_entries; i++, tmp++) {
- u64 entry_size_bytes = pfs->pfs_header.entry_size * 4;
+ u64 entry_size_bytes = pfs->pfs_header.entry_size * sizeof(u32);
tmp->start = pfs->vsec_offset + entry_size_bytes * i;
tmp->end = tmp->start + entry_size_bytes - 1;
@@ -277,7 +277,7 @@ static int tpmi_process_info(struct intel_tpmi_info *tpmi_info,
void __iomem *info_mem;
info_mem = ioremap(pfs->vsec_offset + TPMI_INFO_BUS_INFO_OFFSET,
- pfs->pfs_header.entry_size * 4 - TPMI_INFO_BUS_INFO_OFFSET);
+ pfs->pfs_header.entry_size * sizeof(u32) - TPMI_INFO_BUS_INFO_OFFSET);
if (!info_mem)
return -ENOMEM;
@@ -308,6 +308,8 @@ static int tpmi_fetch_pfs_header(struct intel_tpmi_pm_feature *pfs, u64 start, i
return 0;
}
+#define TPMI_CAP_OFFSET_UNIT 1024
+
static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev)
{
struct intel_vsec_device *vsec_dev = auxdev_to_ivdev(auxdev);
@@ -354,7 +356,7 @@ static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev)
if (!pfs_start)
pfs_start = res_start;
- pfs->pfs_header.cap_offset *= 1024;
+ pfs->pfs_header.cap_offset *= TPMI_CAP_OFFSET_UNIT;
pfs->vsec_offset = pfs_start + pfs->pfs_header.cap_offset;
diff --git a/drivers/platform/x86/intel/uncore-frequency/Kconfig b/drivers/platform/x86/intel/uncore-frequency/Kconfig
index 21b209124916..a56d55056927 100644
--- a/drivers/platform/x86/intel/uncore-frequency/Kconfig
+++ b/drivers/platform/x86/intel/uncore-frequency/Kconfig
@@ -6,9 +6,13 @@
menu "Intel Uncore Frequency Control"
depends on X86_64 || COMPILE_TEST
+config INTEL_UNCORE_FREQ_CONTROL_TPMI
+ tristate
+
config INTEL_UNCORE_FREQ_CONTROL
tristate "Intel Uncore frequency control driver"
depends on X86_64
+ select INTEL_UNCORE_FREQ_CONTROL_TPMI if INTEL_TPMI
help
This driver allows control of Uncore frequency limits on
supported server platforms.
diff --git a/drivers/platform/x86/intel/uncore-frequency/Makefile b/drivers/platform/x86/intel/uncore-frequency/Makefile
index e0f7968e8285..08ff57492b28 100644
--- a/drivers/platform/x86/intel/uncore-frequency/Makefile
+++ b/drivers/platform/x86/intel/uncore-frequency/Makefile
@@ -7,3 +7,5 @@ obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o
intel-uncore-frequency-y := uncore-frequency.o
obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency-common.o
intel-uncore-frequency-common-y := uncore-frequency-common.o
+obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL_TPMI) += intel-uncore-frequency-tpmi.o
+intel-uncore-frequency-tpmi-y := uncore-frequency-tpmi.o
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
index 064f186ae81b..1152deaa0078 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
@@ -16,11 +16,34 @@ static struct kobject *uncore_root_kobj;
/* uncore instance count */
static int uncore_instance_count;
+static DEFINE_IDA(intel_uncore_ida);
+
/* callbacks for actual HW read/write */
static int (*uncore_read)(struct uncore_data *data, unsigned int *min, unsigned int *max);
static int (*uncore_write)(struct uncore_data *data, unsigned int input, unsigned int min_max);
static int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq);
+static ssize_t show_domain_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct uncore_data *data = container_of(attr, struct uncore_data, domain_id_dev_attr);
+
+ return sprintf(buf, "%u\n", data->domain_id);
+}
+
+static ssize_t show_fabric_cluster_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct uncore_data *data = container_of(attr, struct uncore_data, fabric_cluster_id_dev_attr);
+
+ return sprintf(buf, "%u\n", data->cluster_id);
+}
+
+static ssize_t show_package_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct uncore_data *data = container_of(attr, struct uncore_data, package_id_dev_attr);
+
+ return sprintf(buf, "%u\n", data->package_id);
+}
+
static ssize_t show_min_max_freq_khz(struct uncore_data *data,
char *buf, int min_max)
{
@@ -161,6 +184,15 @@ static int create_attr_group(struct uncore_data *data, char *name)
init_attribute_ro(initial_max_freq_khz);
init_attribute_root_ro(current_freq_khz);
+ if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) {
+ init_attribute_root_ro(domain_id);
+ data->uncore_attrs[index++] = &data->domain_id_dev_attr.attr;
+ init_attribute_root_ro(fabric_cluster_id);
+ data->uncore_attrs[index++] = &data->fabric_cluster_id_dev_attr.attr;
+ init_attribute_root_ro(package_id);
+ data->uncore_attrs[index++] = &data->package_id_dev_attr.attr;
+ }
+
data->uncore_attrs[index++] = &data->max_freq_khz_dev_attr.attr;
data->uncore_attrs[index++] = &data->min_freq_khz_dev_attr.attr;
data->uncore_attrs[index++] = &data->initial_min_freq_khz_dev_attr.attr;
@@ -191,12 +223,24 @@ int uncore_freq_add_entry(struct uncore_data *data, int cpu)
goto uncore_unlock;
}
- sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id);
+ if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) {
+ ret = ida_alloc(&intel_uncore_ida, GFP_KERNEL);
+ if (ret < 0)
+ goto uncore_unlock;
+
+ data->instance_id = ret;
+ sprintf(data->name, "uncore%02d", ret);
+ } else {
+ sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id);
+ }
uncore_read(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz);
ret = create_attr_group(data, data->name);
- if (!ret) {
+ if (ret) {
+ if (data->domain_id != UNCORE_DOMAIN_ID_INVALID)
+ ida_free(&intel_uncore_ida, data->instance_id);
+ } else {
data->control_cpu = cpu;
data->valid = true;
}
@@ -214,6 +258,9 @@ void uncore_freq_remove_die_entry(struct uncore_data *data)
delete_attr_group(data, data->name);
data->control_cpu = -1;
data->valid = false;
+ if (data->domain_id != UNCORE_DOMAIN_ID_INVALID)
+ ida_free(&intel_uncore_ida, data->instance_id);
+
mutex_unlock(&uncore_lock);
}
EXPORT_SYMBOL_NS_GPL(uncore_freq_remove_die_entry, INTEL_UNCORE_FREQUENCY);
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h
index f5dcfa2fb285..7afb69977c7e 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h
@@ -21,6 +21,9 @@
* @valid: Mark the data valid/invalid
* @package_id: Package id for this instance
* @die_id: Die id for this instance
+ * @domain_id: Power domain id for this instance
+ * @cluster_id: cluster id in a domain
+ * @instance_id: Unique instance id to append to directory name
* @name: Sysfs entry name for this instance
* @uncore_attr_group: Attribute group storage
* @max_freq_khz_dev_attr: Storage for device attribute max_freq_khz
@@ -28,6 +31,9 @@
* @initial_max_freq_khz_dev_attr: Storage for device attribute initial_max_freq_khz
* @initial_min_freq_khz_dev_attr: Storage for device attribute initial_min_freq_khz
* @current_freq_khz_dev_attr: Storage for device attribute current_freq_khz
+ * @domain_id_dev_attr: Storage for device attribute domain_id
+ * @fabric_cluster_id_dev_attr: Storage for device attribute fabric_cluster_id
+ * @package_id_dev_attr: Storage for device attribute package_id
* @uncore_attrs: Attribute storage for group creation
*
* This structure is used to encapsulate all data related to uncore sysfs
@@ -41,6 +47,9 @@ struct uncore_data {
bool valid;
int package_id;
int die_id;
+ int domain_id;
+ int cluster_id;
+ int instance_id;
char name[32];
struct attribute_group uncore_attr_group;
@@ -49,9 +58,14 @@ struct uncore_data {
struct device_attribute initial_max_freq_khz_dev_attr;
struct device_attribute initial_min_freq_khz_dev_attr;
struct device_attribute current_freq_khz_dev_attr;
- struct attribute *uncore_attrs[6];
+ struct device_attribute domain_id_dev_attr;
+ struct device_attribute fabric_cluster_id_dev_attr;
+ struct device_attribute package_id_dev_attr;
+ struct attribute *uncore_attrs[9];
};
+#define UNCORE_DOMAIN_ID_INVALID -1
+
int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max),
int (*write_control_freq)(struct uncore_data *data, unsigned int input, unsigned int min_max),
int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq));
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
new file mode 100644
index 000000000000..7d0a67f8b517
--- /dev/null
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
@@ -0,0 +1,413 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * uncore-frquency-tpmi: Uncore frequency scaling using TPMI
+ *
+ * Copyright (c) 2023, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * The hardware interface to read/write is basically substitution of
+ * MSR 0x620 and 0x621.
+ * There are specific MMIO offset and bits to get/set minimum and
+ * maximum uncore ratio, similar to MSRs.
+ * The scope of the uncore MSRs was package scope. But TPMI allows
+ * new gen CPUs to have multiple uncore controls at uncore-cluster
+ * level. Each package can have multiple power domains which further
+ * can have multiple clusters.
+ * Here number of power domains = number of resources in this aux
+ * device. There are offsets and bits to discover number of clusters
+ * and offset for each cluster level controls.
+ *
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/intel_tpmi.h>
+
+#include "uncore-frequency-common.h"
+
+#define UNCORE_HEADER_VERSION 1
+#define UNCORE_HEADER_INDEX 0
+#define UNCORE_FABRIC_CLUSTER_OFFSET 8
+
+/* status + control + adv_ctl1 + adv_ctl2 */
+#define UNCORE_FABRIC_CLUSTER_SIZE (4 * 8)
+
+#define UNCORE_STATUS_INDEX 0
+#define UNCORE_CONTROL_INDEX 8
+
+#define UNCORE_FREQ_KHZ_MULTIPLIER 100000
+
+struct tpmi_uncore_struct;
+
+/* Information for each cluster */
+struct tpmi_uncore_cluster_info {
+ bool root_domain;
+ u8 __iomem *cluster_base;
+ struct uncore_data uncore_data;
+ struct tpmi_uncore_struct *uncore_root;
+};
+
+/* Information for each power domain */
+struct tpmi_uncore_power_domain_info {
+ u8 __iomem *uncore_base;
+ int ufs_header_ver;
+ int cluster_count;
+ struct tpmi_uncore_cluster_info *cluster_infos;
+};
+
+/* Information for all power domains in a package */
+struct tpmi_uncore_struct {
+ int power_domain_count;
+ int max_ratio;
+ int min_ratio;
+ struct tpmi_uncore_power_domain_info *pd_info;
+ struct tpmi_uncore_cluster_info root_cluster;
+};
+
+#define UNCORE_GENMASK_MIN_RATIO GENMASK_ULL(21, 15)
+#define UNCORE_GENMASK_MAX_RATIO GENMASK_ULL(14, 8)
+#define UNCORE_GENMASK_CURRENT_RATIO GENMASK_ULL(6, 0)
+
+/* Helper function to read MMIO offset for max/min control frequency */
+static void read_control_freq(struct tpmi_uncore_cluster_info *cluster_info,
+ unsigned int *min, unsigned int *max)
+{
+ u64 control;
+
+ control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX);
+ *max = FIELD_GET(UNCORE_GENMASK_MAX_RATIO, control) * UNCORE_FREQ_KHZ_MULTIPLIER;
+ *min = FIELD_GET(UNCORE_GENMASK_MIN_RATIO, control) * UNCORE_FREQ_KHZ_MULTIPLIER;
+}
+
+#define UNCORE_MAX_RATIO FIELD_MAX(UNCORE_GENMASK_MAX_RATIO)
+
+/* Callback for sysfs read for max/min frequencies. Called under mutex locks */
+static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min,
+ unsigned int *max)
+{
+ struct tpmi_uncore_cluster_info *cluster_info;
+
+ cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data);
+
+ if (cluster_info->root_domain) {
+ struct tpmi_uncore_struct *uncore_root = cluster_info->uncore_root;
+ int i, _min = 0, _max = 0;
+
+ *min = UNCORE_MAX_RATIO * UNCORE_FREQ_KHZ_MULTIPLIER;
+ *max = 0;
+
+ /*
+ * Get the max/min by looking at each cluster. Get the lowest
+ * min and highest max.
+ */
+ for (i = 0; i < uncore_root->power_domain_count; ++i) {
+ int j;
+
+ for (j = 0; j < uncore_root->pd_info[i].cluster_count; ++j) {
+ read_control_freq(&uncore_root->pd_info[i].cluster_infos[j],
+ &_min, &_max);
+ if (*min > _min)
+ *min = _min;
+ if (*max < _max)
+ *max = _max;
+ }
+ }
+ return 0;
+ }
+
+ read_control_freq(cluster_info, min, max);
+
+ return 0;
+}
+
+/* Helper function to write MMIO offset for max/min control frequency */
+static void write_control_freq(struct tpmi_uncore_cluster_info *cluster_info, unsigned int input,
+ unsigned int min_max)
+{
+ u64 control;
+
+ control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX);
+
+ if (min_max) {
+ control &= ~UNCORE_GENMASK_MAX_RATIO;
+ control |= FIELD_PREP(UNCORE_GENMASK_MAX_RATIO, input);
+ } else {
+ control &= ~UNCORE_GENMASK_MIN_RATIO;
+ control |= FIELD_PREP(UNCORE_GENMASK_MIN_RATIO, input);
+ }
+
+ writeq(control, (cluster_info->cluster_base + UNCORE_CONTROL_INDEX));
+}
+
+/* Callback for sysfs write for max/min frequencies. Called under mutex locks */
+static int uncore_write_control_freq(struct uncore_data *data, unsigned int input,
+ unsigned int min_max)
+{
+ struct tpmi_uncore_cluster_info *cluster_info;
+ struct tpmi_uncore_struct *uncore_root;
+
+ input /= UNCORE_FREQ_KHZ_MULTIPLIER;
+ if (!input || input > UNCORE_MAX_RATIO)
+ return -EINVAL;
+
+ cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data);
+ uncore_root = cluster_info->uncore_root;
+
+ /* Update each cluster in a package */
+ if (cluster_info->root_domain) {
+ struct tpmi_uncore_struct *uncore_root = cluster_info->uncore_root;
+ int i;
+
+ for (i = 0; i < uncore_root->power_domain_count; ++i) {
+ int j;
+
+ for (j = 0; j < uncore_root->pd_info[i].cluster_count; ++j)
+ write_control_freq(&uncore_root->pd_info[i].cluster_infos[j],
+ input, min_max);
+ }
+
+ if (min_max)
+ uncore_root->max_ratio = input;
+ else
+ uncore_root->min_ratio = input;
+
+ return 0;
+ }
+
+ if (min_max && uncore_root->max_ratio && uncore_root->max_ratio < input)
+ return -EINVAL;
+
+ if (!min_max && uncore_root->min_ratio && uncore_root->min_ratio > input)
+ return -EINVAL;
+
+ write_control_freq(cluster_info, input, min_max);
+
+ return 0;
+}
+
+/* Callback for sysfs read for the current uncore frequency. Called under mutex locks */
+static int uncore_read_freq(struct uncore_data *data, unsigned int *freq)
+{
+ struct tpmi_uncore_cluster_info *cluster_info;
+ u64 status;
+
+ cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data);
+ if (cluster_info->root_domain)
+ return -ENODATA;
+
+ status = readq((u8 __iomem *)cluster_info->cluster_base + UNCORE_STATUS_INDEX);
+ *freq = FIELD_GET(UNCORE_GENMASK_CURRENT_RATIO, status) * UNCORE_FREQ_KHZ_MULTIPLIER;
+
+ return 0;
+}
+
+static void remove_cluster_entries(struct tpmi_uncore_struct *tpmi_uncore)
+{
+ int i;
+
+ for (i = 0; i < tpmi_uncore->power_domain_count; ++i) {
+ struct tpmi_uncore_power_domain_info *pd_info;
+ int j;
+
+ pd_info = &tpmi_uncore->pd_info[i];
+ if (!pd_info->uncore_base)
+ continue;
+
+ for (j = 0; j < pd_info->cluster_count; ++j) {
+ struct tpmi_uncore_cluster_info *cluster_info;
+
+ cluster_info = &pd_info->cluster_infos[j];
+ uncore_freq_remove_die_entry(&cluster_info->uncore_data);
+ }
+ }
+}
+
+#define UNCORE_VERSION_MASK GENMASK_ULL(7, 0)
+#define UNCORE_LOCAL_FABRIC_CLUSTER_ID_MASK GENMASK_ULL(15, 8)
+#define UNCORE_CLUSTER_OFF_MASK GENMASK_ULL(7, 0)
+#define UNCORE_MAX_CLUSTER_PER_DOMAIN 8
+
+static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
+{
+ struct intel_tpmi_plat_info *plat_info;
+ struct tpmi_uncore_struct *tpmi_uncore;
+ int ret, i, pkg = 0;
+ int num_resources;
+
+ /* Get number of power domains, which is equal to number of resources */
+ num_resources = tpmi_get_resource_count(auxdev);
+ if (!num_resources)
+ return -EINVAL;
+
+ /* Register callbacks to uncore core */
+ ret = uncore_freq_common_init(uncore_read_control_freq, uncore_write_control_freq,
+ uncore_read_freq);
+ if (ret)
+ return ret;
+
+ /* Allocate uncore instance per package */
+ tpmi_uncore = devm_kzalloc(&auxdev->dev, sizeof(*tpmi_uncore), GFP_KERNEL);
+ if (!tpmi_uncore) {
+ ret = -ENOMEM;
+ goto err_rem_common;
+ }
+
+ /* Allocate memory for all power domains in a package */
+ tpmi_uncore->pd_info = devm_kcalloc(&auxdev->dev, num_resources,
+ sizeof(*tpmi_uncore->pd_info),
+ GFP_KERNEL);
+ if (!tpmi_uncore->pd_info) {
+ ret = -ENOMEM;
+ goto err_rem_common;
+ }
+
+ tpmi_uncore->power_domain_count = num_resources;
+
+ /* Get the package ID from the TPMI core */
+ plat_info = tpmi_get_platform_data(auxdev);
+ if (plat_info)
+ pkg = plat_info->package_id;
+ else
+ dev_info(&auxdev->dev, "Platform information is NULL\n");
+
+ for (i = 0; i < num_resources; ++i) {
+ struct tpmi_uncore_power_domain_info *pd_info;
+ struct resource *res;
+ u64 cluster_offset;
+ u8 cluster_mask;
+ int mask, j;
+ u64 header;
+
+ res = tpmi_get_resource_at_index(auxdev, i);
+ if (!res)
+ continue;
+
+ pd_info = &tpmi_uncore->pd_info[i];
+
+ pd_info->uncore_base = devm_ioremap_resource(&auxdev->dev, res);
+ if (IS_ERR(pd_info->uncore_base)) {
+ ret = PTR_ERR(pd_info->uncore_base);
+ /*
+ * Set to NULL so that clean up can still remove other
+ * entries already created if any by
+ * remove_cluster_entries()
+ */
+ pd_info->uncore_base = NULL;
+ goto remove_clusters;
+ }
+
+ /* Check for version and skip this resource if there is mismatch */
+ header = readq(pd_info->uncore_base);
+ pd_info->ufs_header_ver = header & UNCORE_VERSION_MASK;
+ if (pd_info->ufs_header_ver != UNCORE_HEADER_VERSION) {
+ dev_info(&auxdev->dev, "Uncore: Unsupported version:%d\n",
+ pd_info->ufs_header_ver);
+ continue;
+ }
+
+ /* Get Cluster ID Mask */
+ cluster_mask = FIELD_GET(UNCORE_LOCAL_FABRIC_CLUSTER_ID_MASK, header);
+ if (!cluster_mask) {
+ dev_info(&auxdev->dev, "Uncore: Invalid cluster mask:%x\n", cluster_mask);
+ continue;
+ }
+
+ /* Find out number of clusters in this resource */
+ pd_info->cluster_count = hweight8(cluster_mask);
+
+ pd_info->cluster_infos = devm_kcalloc(&auxdev->dev, pd_info->cluster_count,
+ sizeof(struct tpmi_uncore_cluster_info),
+ GFP_KERNEL);
+ if (!pd_info->cluster_infos) {
+ ret = -ENOMEM;
+ goto remove_clusters;
+ }
+ /*
+ * Each byte in the register point to status and control
+ * registers belonging to cluster id 0-8.
+ */
+ cluster_offset = readq(pd_info->uncore_base +
+ UNCORE_FABRIC_CLUSTER_OFFSET);
+
+ for (j = 0; j < pd_info->cluster_count; ++j) {
+ struct tpmi_uncore_cluster_info *cluster_info;
+
+ /* Get the offset for this cluster */
+ mask = (cluster_offset & UNCORE_CLUSTER_OFF_MASK);
+ /* Offset in QWORD, so change to bytes */
+ mask <<= 3;
+
+ cluster_info = &pd_info->cluster_infos[j];
+
+ cluster_info->cluster_base = pd_info->uncore_base + mask;
+
+ cluster_info->uncore_data.package_id = pkg;
+ /* There are no dies like Cascade Lake */
+ cluster_info->uncore_data.die_id = 0;
+ cluster_info->uncore_data.domain_id = i;
+ cluster_info->uncore_data.cluster_id = j;
+
+ cluster_info->uncore_root = tpmi_uncore;
+
+ ret = uncore_freq_add_entry(&cluster_info->uncore_data, 0);
+ if (ret) {
+ cluster_info->cluster_base = NULL;
+ goto remove_clusters;
+ }
+ /* Point to next cluster offset */
+ cluster_offset >>= UNCORE_MAX_CLUSTER_PER_DOMAIN;
+ }
+ }
+
+ auxiliary_set_drvdata(auxdev, tpmi_uncore);
+
+ tpmi_uncore->root_cluster.root_domain = true;
+ tpmi_uncore->root_cluster.uncore_root = tpmi_uncore;
+
+ tpmi_uncore->root_cluster.uncore_data.package_id = pkg;
+ tpmi_uncore->root_cluster.uncore_data.domain_id = UNCORE_DOMAIN_ID_INVALID;
+ ret = uncore_freq_add_entry(&tpmi_uncore->root_cluster.uncore_data, 0);
+ if (ret)
+ goto remove_clusters;
+
+ return 0;
+
+remove_clusters:
+ remove_cluster_entries(tpmi_uncore);
+err_rem_common:
+ uncore_freq_common_exit();
+
+ return ret;
+}
+
+static void uncore_remove(struct auxiliary_device *auxdev)
+{
+ struct tpmi_uncore_struct *tpmi_uncore = auxiliary_get_drvdata(auxdev);
+
+ uncore_freq_remove_die_entry(&tpmi_uncore->root_cluster.uncore_data);
+ remove_cluster_entries(tpmi_uncore);
+
+ uncore_freq_common_exit();
+}
+
+static const struct auxiliary_device_id intel_uncore_id_table[] = {
+ { .name = "intel_vsec.tpmi-uncore" },
+ {}
+};
+MODULE_DEVICE_TABLE(auxiliary, intel_uncore_id_table);
+
+static struct auxiliary_driver intel_uncore_aux_driver = {
+ .id_table = intel_uncore_id_table,
+ .remove = uncore_remove,
+ .probe = uncore_probe,
+};
+
+module_auxiliary_driver(intel_uncore_aux_driver);
+
+MODULE_IMPORT_NS(INTEL_TPMI);
+MODULE_IMPORT_NS(INTEL_UNCORE_FREQUENCY);
+MODULE_DESCRIPTION("Intel TPMI UFS Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c
index 32e2515ee366..a3b25253b6fd 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c
@@ -136,6 +136,7 @@ static int uncore_event_cpu_online(unsigned int cpu)
data->package_id = topology_physical_package_id(cpu);
data->die_id = topology_die_id(cpu);
+ data->domain_id = UNCORE_DOMAIN_ID_INVALID;
return uncore_freq_add_entry(data, cpu);
}
diff --git a/drivers/platform/x86/lenovo-yogabook-wmi.c b/drivers/platform/x86/lenovo-yogabook-wmi.c
deleted file mode 100644
index 5f4bd1eec38a..000000000000
--- a/drivers/platform/x86/lenovo-yogabook-wmi.c
+++ /dev/null
@@ -1,408 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* WMI driver for Lenovo Yoga Book YB1-X90* / -X91* tablets */
-
-#include <linux/acpi.h>
-#include <linux/devm-helpers.h>
-#include <linux/gpio/consumer.h>
-#include <linux/gpio/machine.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/leds.h>
-#include <linux/wmi.h>
-#include <linux/workqueue.h>
-
-#define YB_MBTN_EVENT_GUID "243FEC1D-1963-41C1-8100-06A9D82A94B4"
-#define YB_MBTN_METHOD_GUID "742B0CA1-0B20-404B-9CAA-AEFCABF30CE0"
-
-#define YB_PAD_ENABLE 1
-#define YB_PAD_DISABLE 2
-#define YB_LIGHTUP_BTN 3
-
-#define YB_KBD_BL_DEFAULT 128
-
-/* flags */
-enum {
- YB_KBD_IS_ON,
- YB_DIGITIZER_IS_ON,
- YB_DIGITIZER_MODE,
- YB_TABLET_MODE,
- YB_SUSPENDED,
-};
-
-struct yogabook_wmi {
- struct wmi_device *wdev;
- struct acpi_device *kbd_adev;
- struct acpi_device *dig_adev;
- struct device *kbd_dev;
- struct device *dig_dev;
- struct gpio_desc *backside_hall_gpio;
- int backside_hall_irq;
- struct work_struct work;
- struct led_classdev kbd_bl_led;
- unsigned long flags;
- uint8_t brightness;
-};
-
-static int yogabook_wmi_do_action(struct wmi_device *wdev, int action)
-{
- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_buffer input;
- acpi_status status;
- u32 dummy_arg = 0;
-
- dev_dbg(&wdev->dev, "Do action: %d\n", action);
-
- input.pointer = &dummy_arg;
- input.length = sizeof(dummy_arg);
-
- status = wmi_evaluate_method(YB_MBTN_METHOD_GUID, 0, action, &input,
- &output);
- if (ACPI_FAILURE(status)) {
- dev_err(&wdev->dev, "Calling WMI method failure: 0x%x\n",
- status);
- return status;
- }
-
- kfree(output.pointer);
-
- return 0;
-}
-
-/*
- * To control keyboard backlight, call the method KBLC() of the TCS1 ACPI
- * device (Goodix touchpad acts as virtual sensor keyboard).
- */
-static int yogabook_wmi_set_kbd_backlight(struct wmi_device *wdev,
- uint8_t level)
-{
- struct yogabook_wmi *data = dev_get_drvdata(&wdev->dev);
- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_object_list input;
- union acpi_object param;
- acpi_status status;
-
- if (data->kbd_adev->power.state != ACPI_STATE_D0) {
- dev_warn(&wdev->dev, "keyboard touchscreen not in D0, cannot set brightness\n");
- return -ENXIO;
- }
-
- dev_dbg(&wdev->dev, "Set KBLC level to %u\n", level);
-
- input.count = 1;
- input.pointer = &param;
-
- param.type = ACPI_TYPE_INTEGER;
- param.integer.value = 255 - level;
-
- status = acpi_evaluate_object(acpi_device_handle(data->kbd_adev), "KBLC",
- &input, &output);
- if (ACPI_FAILURE(status)) {
- dev_err(&wdev->dev, "Failed to call KBLC method: 0x%x\n", status);
- return status;
- }
-
- kfree(output.pointer);
- return 0;
-}
-
-static void yogabook_wmi_work(struct work_struct *work)
-{
- struct yogabook_wmi *data = container_of(work, struct yogabook_wmi, work);
- struct device *dev = &data->wdev->dev;
- bool kbd_on, digitizer_on;
- int r;
-
- if (test_bit(YB_SUSPENDED, &data->flags))
- return;
-
- if (test_bit(YB_TABLET_MODE, &data->flags)) {
- kbd_on = false;
- digitizer_on = false;
- } else if (test_bit(YB_DIGITIZER_MODE, &data->flags)) {
- digitizer_on = true;
- kbd_on = false;
- } else {
- kbd_on = true;
- digitizer_on = false;
- }
-
- if (!kbd_on && test_bit(YB_KBD_IS_ON, &data->flags)) {
- /*
- * Must be done before releasing the keyboard touchscreen driver,
- * so that the keyboard touchscreen dev is still in D0.
- */
- yogabook_wmi_set_kbd_backlight(data->wdev, 0);
- device_release_driver(data->kbd_dev);
- clear_bit(YB_KBD_IS_ON, &data->flags);
- }
-
- if (!digitizer_on && test_bit(YB_DIGITIZER_IS_ON, &data->flags)) {
- yogabook_wmi_do_action(data->wdev, YB_PAD_DISABLE);
- device_release_driver(data->dig_dev);
- clear_bit(YB_DIGITIZER_IS_ON, &data->flags);
- }
-
- if (kbd_on && !test_bit(YB_KBD_IS_ON, &data->flags)) {
- r = device_reprobe(data->kbd_dev);
- if (r)
- dev_warn(dev, "Reprobe of keyboard touchscreen failed: %d\n", r);
-
- yogabook_wmi_set_kbd_backlight(data->wdev, data->brightness);
- set_bit(YB_KBD_IS_ON, &data->flags);
- }
-
- if (digitizer_on && !test_bit(YB_DIGITIZER_IS_ON, &data->flags)) {
- r = device_reprobe(data->dig_dev);
- if (r)
- dev_warn(dev, "Reprobe of digitizer failed: %d\n", r);
-
- yogabook_wmi_do_action(data->wdev, YB_PAD_ENABLE);
- set_bit(YB_DIGITIZER_IS_ON, &data->flags);
- }
-}
-
-static void yogabook_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy)
-{
- struct yogabook_wmi *data = dev_get_drvdata(&wdev->dev);
-
- if (test_bit(YB_SUSPENDED, &data->flags))
- return;
-
- if (test_bit(YB_DIGITIZER_MODE, &data->flags))
- clear_bit(YB_DIGITIZER_MODE, &data->flags);
- else
- set_bit(YB_DIGITIZER_MODE, &data->flags);
-
- /*
- * We are called from the ACPI core and the driver [un]binding which is
- * done also needs ACPI functions, use a workqueue to avoid deadlocking.
- */
- schedule_work(&data->work);
-}
-
-static irqreturn_t yogabook_backside_hall_irq(int irq, void *_data)
-{
- struct yogabook_wmi *data = _data;
-
- if (gpiod_get_value(data->backside_hall_gpio))
- set_bit(YB_TABLET_MODE, &data->flags);
- else
- clear_bit(YB_TABLET_MODE, &data->flags);
-
- schedule_work(&data->work);
-
- return IRQ_HANDLED;
-}
-
-static enum led_brightness kbd_brightness_get(struct led_classdev *cdev)
-{
- struct yogabook_wmi *data =
- container_of(cdev, struct yogabook_wmi, kbd_bl_led);
-
- return data->brightness;
-}
-
-static int kbd_brightness_set(struct led_classdev *cdev,
- enum led_brightness value)
-{
- struct yogabook_wmi *data =
- container_of(cdev, struct yogabook_wmi, kbd_bl_led);
- struct wmi_device *wdev = data->wdev;
-
- if ((value < 0) || (value > 255))
- return -EINVAL;
-
- data->brightness = value;
-
- if (data->kbd_adev->power.state != ACPI_STATE_D0)
- return 0;
-
- return yogabook_wmi_set_kbd_backlight(wdev, data->brightness);
-}
-
-static struct gpiod_lookup_table yogabook_wmi_gpios = {
- .dev_id = "243FEC1D-1963-41C1-8100-06A9D82A94B4",
- .table = {
- GPIO_LOOKUP("INT33FF:02", 18, "backside_hall_sw", GPIO_ACTIVE_LOW),
- {}
- },
-};
-
-static void yogabook_wmi_rm_gpio_lookup(void *unused)
-{
- gpiod_remove_lookup_table(&yogabook_wmi_gpios);
-}
-
-static int yogabook_wmi_probe(struct wmi_device *wdev, const void *context)
-{
- struct yogabook_wmi *data;
- int r;
-
- data = devm_kzalloc(&wdev->dev, sizeof(struct yogabook_wmi), GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- dev_set_drvdata(&wdev->dev, data);
-
- data->wdev = wdev;
- data->brightness = YB_KBD_BL_DEFAULT;
- set_bit(YB_KBD_IS_ON, &data->flags);
- set_bit(YB_DIGITIZER_IS_ON, &data->flags);
-
- r = devm_work_autocancel(&wdev->dev, &data->work, yogabook_wmi_work);
- if (r)
- return r;
-
- data->kbd_adev = acpi_dev_get_first_match_dev("GDIX1001", NULL, -1);
- if (!data->kbd_adev) {
- dev_err(&wdev->dev, "Cannot find the touchpad device in ACPI tables\n");
- return -ENODEV;
- }
-
- data->dig_adev = acpi_dev_get_first_match_dev("WCOM0019", NULL, -1);
- if (!data->dig_adev) {
- dev_err(&wdev->dev, "Cannot find the digitizer device in ACPI tables\n");
- r = -ENODEV;
- goto error_put_devs;
- }
-
- data->kbd_dev = get_device(acpi_get_first_physical_node(data->kbd_adev));
- if (!data->kbd_dev || !data->kbd_dev->driver) {
- r = -EPROBE_DEFER;
- goto error_put_devs;
- }
-
- data->dig_dev = get_device(acpi_get_first_physical_node(data->dig_adev));
- if (!data->dig_dev || !data->dig_dev->driver) {
- r = -EPROBE_DEFER;
- goto error_put_devs;
- }
-
- gpiod_add_lookup_table(&yogabook_wmi_gpios);
-
- r = devm_add_action_or_reset(&wdev->dev, yogabook_wmi_rm_gpio_lookup, NULL);
- if (r)
- goto error_put_devs;
-
- data->backside_hall_gpio =
- devm_gpiod_get(&wdev->dev, "backside_hall_sw", GPIOD_IN);
- if (IS_ERR(data->backside_hall_gpio)) {
- r = PTR_ERR(data->backside_hall_gpio);
- dev_err_probe(&wdev->dev, r, "Getting backside_hall_sw GPIO\n");
- goto error_put_devs;
- }
-
- r = gpiod_to_irq(data->backside_hall_gpio);
- if (r < 0) {
- dev_err_probe(&wdev->dev, r, "Getting backside_hall_sw IRQ\n");
- goto error_put_devs;
- }
- data->backside_hall_irq = r;
-
- r = devm_request_irq(&wdev->dev, data->backside_hall_irq,
- yogabook_backside_hall_irq,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- "backside_hall_sw", data);
- if (r) {
- dev_err_probe(&wdev->dev, r, "Requesting backside_hall_sw IRQ\n");
- goto error_put_devs;
- }
-
- schedule_work(&data->work);
-
- data->kbd_bl_led.name = "ybwmi::kbd_backlight";
- data->kbd_bl_led.brightness_set_blocking = kbd_brightness_set;
- data->kbd_bl_led.brightness_get = kbd_brightness_get;
- data->kbd_bl_led.max_brightness = 255;
-
- r = devm_led_classdev_register(&wdev->dev, &data->kbd_bl_led);
- if (r < 0) {
- dev_err_probe(&wdev->dev, r, "Registering backlight LED device\n");
- goto error_put_devs;
- }
-
- return 0;
-
-error_put_devs:
- put_device(data->dig_dev);
- put_device(data->kbd_dev);
- acpi_dev_put(data->dig_adev);
- acpi_dev_put(data->kbd_adev);
- return r;
-}
-
-static void yogabook_wmi_remove(struct wmi_device *wdev)
-{
- struct yogabook_wmi *data = dev_get_drvdata(&wdev->dev);
-
- put_device(data->dig_dev);
- put_device(data->kbd_dev);
- acpi_dev_put(data->dig_adev);
- acpi_dev_put(data->kbd_adev);
-}
-
-static int __maybe_unused yogabook_wmi_suspend(struct device *dev)
-{
- struct wmi_device *wdev = container_of(dev, struct wmi_device, dev);
- struct yogabook_wmi *data = dev_get_drvdata(dev);
-
- set_bit(YB_SUSPENDED, &data->flags);
-
- flush_work(&data->work);
-
- /* Turn off the pen button at sleep */
- if (test_bit(YB_DIGITIZER_IS_ON, &data->flags))
- yogabook_wmi_do_action(wdev, YB_PAD_DISABLE);
-
- return 0;
-}
-
-static int __maybe_unused yogabook_wmi_resume(struct device *dev)
-{
- struct wmi_device *wdev = container_of(dev, struct wmi_device, dev);
- struct yogabook_wmi *data = dev_get_drvdata(dev);
-
- if (test_bit(YB_KBD_IS_ON, &data->flags)) {
- /* Ensure keyboard touchpad is on before we call KBLC() */
- acpi_device_set_power(data->kbd_adev, ACPI_STATE_D0);
- yogabook_wmi_set_kbd_backlight(wdev, data->brightness);
- }
-
- if (test_bit(YB_DIGITIZER_IS_ON, &data->flags))
- yogabook_wmi_do_action(wdev, YB_PAD_ENABLE);
-
- clear_bit(YB_SUSPENDED, &data->flags);
-
- /* Check for YB_TABLET_MODE changes made during suspend */
- schedule_work(&data->work);
-
- return 0;
-}
-
-static const struct wmi_device_id yogabook_wmi_id_table[] = {
- {
- .guid_string = YB_MBTN_EVENT_GUID,
- },
- { } /* Terminating entry */
-};
-
-static SIMPLE_DEV_PM_OPS(yogabook_wmi_pm_ops,
- yogabook_wmi_suspend, yogabook_wmi_resume);
-
-static struct wmi_driver yogabook_wmi_driver = {
- .driver = {
- .name = "yogabook-wmi",
- .pm = &yogabook_wmi_pm_ops,
- },
- .no_notify_data = true,
- .id_table = yogabook_wmi_id_table,
- .probe = yogabook_wmi_probe,
- .remove = yogabook_wmi_remove,
- .notify = yogabook_wmi_notify,
-};
-module_wmi_driver(yogabook_wmi_driver);
-
-MODULE_DEVICE_TABLE(wmi, yogabook_wmi_id_table);
-MODULE_AUTHOR("Yauhen Kharuzhy");
-MODULE_DESCRIPTION("Lenovo Yoga Book WMI driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/x86/lenovo-yogabook.c b/drivers/platform/x86/lenovo-yogabook.c
new file mode 100644
index 000000000000..b8d0239192cb
--- /dev/null
+++ b/drivers/platform/x86/lenovo-yogabook.c
@@ -0,0 +1,573 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Platform driver for Lenovo Yoga Book YB1-X90F/L tablets (Android model)
+ * WMI driver for Lenovo Yoga Book YB1-X91F/L tablets (Windows model)
+ *
+ * The keyboard half of the YB1 models can function as both a capacitive
+ * touch keyboard or as a Wacom digitizer, but not at the same time.
+ *
+ * This driver takes care of switching between the 2 functions.
+ *
+ * Copyright 2023 Hans de Goede <hansg@kernel.org>
+ */
+
+#include <linux/acpi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/wmi.h>
+#include <linux/workqueue.h>
+
+#define YB_MBTN_EVENT_GUID "243FEC1D-1963-41C1-8100-06A9D82A94B4"
+
+#define YB_KBD_BL_DEFAULT 128
+#define YB_KBD_BL_MAX 255
+#define YB_KBD_BL_PWM_PERIOD 13333
+
+#define YB_PDEV_NAME "yogabook-touch-kbd-digitizer-switch"
+
+/* flags */
+enum {
+ YB_KBD_IS_ON,
+ YB_DIGITIZER_IS_ON,
+ YB_DIGITIZER_MODE,
+ YB_TABLET_MODE,
+ YB_SUSPENDED,
+};
+
+struct yogabook_data {
+ struct device *dev;
+ struct acpi_device *kbd_adev;
+ struct acpi_device *dig_adev;
+ struct device *kbd_dev;
+ struct device *dig_dev;
+ struct led_classdev *pen_led;
+ struct gpio_desc *pen_touch_event;
+ struct gpio_desc *kbd_bl_led_enable;
+ struct gpio_desc *backside_hall_gpio;
+ struct pwm_device *kbd_bl_pwm;
+ int (*set_kbd_backlight)(struct yogabook_data *data, uint8_t level);
+ int pen_touch_irq;
+ int backside_hall_irq;
+ struct work_struct work;
+ struct led_classdev kbd_bl_led;
+ unsigned long flags;
+ uint8_t brightness;
+};
+
+static void yogabook_work(struct work_struct *work)
+{
+ struct yogabook_data *data = container_of(work, struct yogabook_data, work);
+ bool kbd_on, digitizer_on;
+ int r;
+
+ if (test_bit(YB_SUSPENDED, &data->flags))
+ return;
+
+ if (test_bit(YB_TABLET_MODE, &data->flags)) {
+ kbd_on = false;
+ digitizer_on = false;
+ } else if (test_bit(YB_DIGITIZER_MODE, &data->flags)) {
+ digitizer_on = true;
+ kbd_on = false;
+ } else {
+ kbd_on = true;
+ digitizer_on = false;
+ }
+
+ if (!kbd_on && test_bit(YB_KBD_IS_ON, &data->flags)) {
+ /*
+ * Must be done before releasing the keyboard touchscreen driver,
+ * so that the keyboard touchscreen dev is still in D0.
+ */
+ data->set_kbd_backlight(data, 0);
+ device_release_driver(data->kbd_dev);
+ clear_bit(YB_KBD_IS_ON, &data->flags);
+ }
+
+ if (!digitizer_on && test_bit(YB_DIGITIZER_IS_ON, &data->flags)) {
+ led_set_brightness(data->pen_led, LED_OFF);
+ device_release_driver(data->dig_dev);
+ clear_bit(YB_DIGITIZER_IS_ON, &data->flags);
+ }
+
+ if (kbd_on && !test_bit(YB_KBD_IS_ON, &data->flags)) {
+ r = device_reprobe(data->kbd_dev);
+ if (r)
+ dev_warn(data->dev, "Reprobe of keyboard touchscreen failed: %d\n", r);
+
+ data->set_kbd_backlight(data, data->brightness);
+ set_bit(YB_KBD_IS_ON, &data->flags);
+ }
+
+ if (digitizer_on && !test_bit(YB_DIGITIZER_IS_ON, &data->flags)) {
+ r = device_reprobe(data->dig_dev);
+ if (r)
+ dev_warn(data->dev, "Reprobe of digitizer failed: %d\n", r);
+
+ led_set_brightness(data->pen_led, LED_FULL);
+ set_bit(YB_DIGITIZER_IS_ON, &data->flags);
+ }
+}
+
+static void yogabook_toggle_digitizer_mode(struct yogabook_data *data)
+{
+ if (test_bit(YB_SUSPENDED, &data->flags))
+ return;
+
+ if (test_bit(YB_DIGITIZER_MODE, &data->flags))
+ clear_bit(YB_DIGITIZER_MODE, &data->flags);
+ else
+ set_bit(YB_DIGITIZER_MODE, &data->flags);
+
+ /*
+ * We are called from the ACPI core and the driver [un]binding which is
+ * done also needs ACPI functions, use a workqueue to avoid deadlocking.
+ */
+ schedule_work(&data->work);
+}
+
+static irqreturn_t yogabook_backside_hall_irq(int irq, void *_data)
+{
+ struct yogabook_data *data = _data;
+
+ if (gpiod_get_value(data->backside_hall_gpio))
+ set_bit(YB_TABLET_MODE, &data->flags);
+ else
+ clear_bit(YB_TABLET_MODE, &data->flags);
+
+ schedule_work(&data->work);
+
+ return IRQ_HANDLED;
+}
+
+#define kbd_led_to_yogabook(cdev) container_of(cdev, struct yogabook_data, kbd_bl_led)
+
+static enum led_brightness kbd_brightness_get(struct led_classdev *cdev)
+{
+ struct yogabook_data *data = kbd_led_to_yogabook(cdev);
+
+ return data->brightness;
+}
+
+static int kbd_brightness_set(struct led_classdev *cdev,
+ enum led_brightness value)
+{
+ struct yogabook_data *data = kbd_led_to_yogabook(cdev);
+
+ if ((value < 0) || (value > YB_KBD_BL_MAX))
+ return -EINVAL;
+
+ data->brightness = value;
+
+ if (!test_bit(YB_KBD_IS_ON, &data->flags))
+ return 0;
+
+ return data->set_kbd_backlight(data, data->brightness);
+}
+
+static struct gpiod_lookup_table yogabook_gpios = {
+ .table = {
+ GPIO_LOOKUP("INT33FF:02", 18, "backside_hall_sw", GPIO_ACTIVE_LOW),
+ {}
+ },
+};
+
+static struct led_lookup_data yogabook_pen_led = {
+ .provider = "platform::indicator",
+ .con_id = "pen-icon-led",
+};
+
+static int yogabook_probe(struct device *dev, struct yogabook_data *data,
+ const char *kbd_bl_led_name)
+{
+ int r;
+
+ data->dev = dev;
+ data->brightness = YB_KBD_BL_DEFAULT;
+ set_bit(YB_KBD_IS_ON, &data->flags);
+ set_bit(YB_DIGITIZER_IS_ON, &data->flags);
+ INIT_WORK(&data->work, yogabook_work);
+
+ yogabook_pen_led.dev_id = dev_name(dev);
+ led_add_lookup(&yogabook_pen_led);
+ data->pen_led = devm_led_get(dev, "pen-icon-led");
+ led_remove_lookup(&yogabook_pen_led);
+
+ if (IS_ERR(data->pen_led))
+ return dev_err_probe(dev, PTR_ERR(data->pen_led), "Getting pen icon LED\n");
+
+ yogabook_gpios.dev_id = dev_name(dev);
+ gpiod_add_lookup_table(&yogabook_gpios);
+ data->backside_hall_gpio = devm_gpiod_get(dev, "backside_hall_sw", GPIOD_IN);
+ gpiod_remove_lookup_table(&yogabook_gpios);
+
+ if (IS_ERR(data->backside_hall_gpio))
+ return dev_err_probe(dev, PTR_ERR(data->backside_hall_gpio),
+ "Getting backside_hall_sw GPIO\n");
+
+ r = gpiod_to_irq(data->backside_hall_gpio);
+ if (r < 0)
+ return dev_err_probe(dev, r, "Getting backside_hall_sw IRQ\n");
+
+ data->backside_hall_irq = r;
+
+ /* Set default brightness before enabling the IRQ */
+ data->set_kbd_backlight(data, YB_KBD_BL_DEFAULT);
+
+ r = request_irq(data->backside_hall_irq, yogabook_backside_hall_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "backside_hall_sw", data);
+ if (r)
+ return dev_err_probe(dev, r, "Requesting backside_hall_sw IRQ\n");
+
+ schedule_work(&data->work);
+
+ data->kbd_bl_led.name = kbd_bl_led_name;
+ data->kbd_bl_led.brightness_set_blocking = kbd_brightness_set;
+ data->kbd_bl_led.brightness_get = kbd_brightness_get;
+ data->kbd_bl_led.max_brightness = YB_KBD_BL_MAX;
+
+ r = devm_led_classdev_register(dev, &data->kbd_bl_led);
+ if (r < 0) {
+ dev_err_probe(dev, r, "Registering backlight LED device\n");
+ goto error_free_irq;
+ }
+
+ dev_set_drvdata(dev, data);
+ return 0;
+
+error_free_irq:
+ free_irq(data->backside_hall_irq, data);
+ cancel_work_sync(&data->work);
+ return r;
+}
+
+static void yogabook_remove(struct yogabook_data *data)
+{
+ int r = 0;
+
+ free_irq(data->backside_hall_irq, data);
+ cancel_work_sync(&data->work);
+
+ if (!test_bit(YB_KBD_IS_ON, &data->flags))
+ r |= device_reprobe(data->kbd_dev);
+
+ if (!test_bit(YB_DIGITIZER_IS_ON, &data->flags))
+ r |= device_reprobe(data->dig_dev);
+
+ if (r)
+ dev_warn(data->dev, "Reprobe of devices failed\n");
+}
+
+static int yogabook_suspend(struct device *dev)
+{
+ struct yogabook_data *data = dev_get_drvdata(dev);
+
+ set_bit(YB_SUSPENDED, &data->flags);
+ flush_work(&data->work);
+
+ if (test_bit(YB_KBD_IS_ON, &data->flags))
+ data->set_kbd_backlight(data, 0);
+
+ return 0;
+}
+
+static int yogabook_resume(struct device *dev)
+{
+ struct yogabook_data *data = dev_get_drvdata(dev);
+
+ if (test_bit(YB_KBD_IS_ON, &data->flags))
+ data->set_kbd_backlight(data, data->brightness);
+
+ clear_bit(YB_SUSPENDED, &data->flags);
+
+ /* Check for YB_TABLET_MODE changes made during suspend */
+ schedule_work(&data->work);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(yogabook_pm_ops, yogabook_suspend, yogabook_resume);
+
+/********** WMI driver code **********/
+
+/*
+ * To control keyboard backlight, call the method KBLC() of the TCS1 ACPI
+ * device (Goodix touchpad acts as virtual sensor keyboard).
+ */
+static int yogabook_wmi_set_kbd_backlight(struct yogabook_data *data,
+ uint8_t level)
+{
+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_object_list input;
+ union acpi_object param;
+ acpi_status status;
+
+ dev_dbg(data->dev, "Set KBLC level to %u\n", level);
+
+ /* Ensure keyboard touchpad is on before we call KBLC() */
+ acpi_device_set_power(data->kbd_adev, ACPI_STATE_D0);
+
+ input.count = 1;
+ input.pointer = &param;
+
+ param.type = ACPI_TYPE_INTEGER;
+ param.integer.value = YB_KBD_BL_MAX - level;
+
+ status = acpi_evaluate_object(acpi_device_handle(data->kbd_adev), "KBLC",
+ &input, &output);
+ if (ACPI_FAILURE(status)) {
+ dev_err(data->dev, "Failed to call KBLC method: 0x%x\n", status);
+ return status;
+ }
+
+ kfree(output.pointer);
+ return 0;
+}
+
+static int yogabook_wmi_probe(struct wmi_device *wdev, const void *context)
+{
+ struct device *dev = &wdev->dev;
+ struct yogabook_data *data;
+ int r;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ data->kbd_adev = acpi_dev_get_first_match_dev("GDIX1001", NULL, -1);
+ if (!data->kbd_adev)
+ return dev_err_probe(dev, -ENODEV, "Cannot find the touchpad device in ACPI tables\n");
+
+ data->dig_adev = acpi_dev_get_first_match_dev("WCOM0019", NULL, -1);
+ if (!data->dig_adev) {
+ r = dev_err_probe(dev, -ENODEV, "Cannot find the digitizer device in ACPI tables\n");
+ goto error_put_devs;
+ }
+
+ data->kbd_dev = get_device(acpi_get_first_physical_node(data->kbd_adev));
+ if (!data->kbd_dev || !data->kbd_dev->driver) {
+ r = -EPROBE_DEFER;
+ goto error_put_devs;
+ }
+
+ data->dig_dev = get_device(acpi_get_first_physical_node(data->dig_adev));
+ if (!data->dig_dev || !data->dig_dev->driver) {
+ r = -EPROBE_DEFER;
+ goto error_put_devs;
+ }
+
+ data->set_kbd_backlight = yogabook_wmi_set_kbd_backlight;
+
+ r = yogabook_probe(dev, data, "ybwmi::kbd_backlight");
+ if (r)
+ goto error_put_devs;
+
+ return 0;
+
+error_put_devs:
+ put_device(data->dig_dev);
+ put_device(data->kbd_dev);
+ acpi_dev_put(data->dig_adev);
+ acpi_dev_put(data->kbd_adev);
+ return r;
+}
+
+static void yogabook_wmi_remove(struct wmi_device *wdev)
+{
+ struct yogabook_data *data = dev_get_drvdata(&wdev->dev);
+
+ yogabook_remove(data);
+
+ put_device(data->dig_dev);
+ put_device(data->kbd_dev);
+ acpi_dev_put(data->dig_adev);
+ acpi_dev_put(data->kbd_adev);
+}
+
+static void yogabook_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy)
+{
+ yogabook_toggle_digitizer_mode(dev_get_drvdata(&wdev->dev));
+}
+
+static const struct wmi_device_id yogabook_wmi_id_table[] = {
+ {
+ .guid_string = YB_MBTN_EVENT_GUID,
+ },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(wmi, yogabook_wmi_id_table);
+
+static struct wmi_driver yogabook_wmi_driver = {
+ .driver = {
+ .name = "yogabook-wmi",
+ .pm = pm_sleep_ptr(&yogabook_pm_ops),
+ },
+ .no_notify_data = true,
+ .id_table = yogabook_wmi_id_table,
+ .probe = yogabook_wmi_probe,
+ .remove = yogabook_wmi_remove,
+ .notify = yogabook_wmi_notify,
+};
+
+/********** platform driver code **********/
+
+static struct gpiod_lookup_table yogabook_pdev_gpios = {
+ .dev_id = YB_PDEV_NAME,
+ .table = {
+ GPIO_LOOKUP("INT33FF:00", 95, "pen_touch_event", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("INT33FF:03", 52, "enable_keyboard_led", GPIO_ACTIVE_HIGH),
+ {}
+ },
+};
+
+static int yogabook_pdev_set_kbd_backlight(struct yogabook_data *data, u8 level)
+{
+ struct pwm_state state = {
+ .period = YB_KBD_BL_PWM_PERIOD,
+ .duty_cycle = YB_KBD_BL_PWM_PERIOD * level / YB_KBD_BL_MAX,
+ .enabled = level,
+ };
+
+ pwm_apply_state(data->kbd_bl_pwm, &state);
+ gpiod_set_value(data->kbd_bl_led_enable, level ? 1 : 0);
+ return 0;
+}
+
+static irqreturn_t yogabook_pen_touch_irq(int irq, void *data)
+{
+ yogabook_toggle_digitizer_mode(data);
+ return IRQ_HANDLED;
+}
+
+static int yogabook_pdev_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct yogabook_data *data;
+ int r;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ data->kbd_dev = bus_find_device_by_name(&i2c_bus_type, NULL, "i2c-goodix_ts");
+ if (!data->kbd_dev || !data->kbd_dev->driver) {
+ r = -EPROBE_DEFER;
+ goto error_put_devs;
+ }
+
+ data->dig_dev = bus_find_device_by_name(&i2c_bus_type, NULL, "i2c-wacom");
+ if (!data->dig_dev || !data->dig_dev->driver) {
+ r = -EPROBE_DEFER;
+ goto error_put_devs;
+ }
+
+ gpiod_add_lookup_table(&yogabook_pdev_gpios);
+ data->pen_touch_event = devm_gpiod_get(dev, "pen_touch_event", GPIOD_IN);
+ data->kbd_bl_led_enable = devm_gpiod_get(dev, "enable_keyboard_led", GPIOD_OUT_HIGH);
+ gpiod_remove_lookup_table(&yogabook_pdev_gpios);
+
+ if (IS_ERR(data->pen_touch_event)) {
+ r = dev_err_probe(dev, PTR_ERR(data->pen_touch_event),
+ "Getting pen_touch_event GPIO\n");
+ goto error_put_devs;
+ }
+
+ if (IS_ERR(data->kbd_bl_led_enable)) {
+ r = dev_err_probe(dev, PTR_ERR(data->kbd_bl_led_enable),
+ "Getting enable_keyboard_led GPIO\n");
+ goto error_put_devs;
+ }
+
+ data->kbd_bl_pwm = devm_pwm_get(dev, "pwm_soc_lpss_2");
+ if (IS_ERR(data->kbd_bl_pwm)) {
+ r = dev_err_probe(dev, PTR_ERR(data->kbd_bl_pwm),
+ "Getting keyboard backlight PWM\n");
+ goto error_put_devs;
+ }
+
+ r = gpiod_to_irq(data->pen_touch_event);
+ if (r < 0) {
+ dev_err_probe(dev, r, "Getting pen_touch_event IRQ\n");
+ goto error_put_devs;
+ }
+ data->pen_touch_irq = r;
+
+ r = request_irq(data->pen_touch_irq, yogabook_pen_touch_irq, IRQF_TRIGGER_FALLING,
+ "pen_touch_event", data);
+ if (r) {
+ dev_err_probe(dev, r, "Requesting pen_touch_event IRQ\n");
+ goto error_put_devs;
+ }
+
+ data->set_kbd_backlight = yogabook_pdev_set_kbd_backlight;
+
+ r = yogabook_probe(dev, data, "yogabook::kbd_backlight");
+ if (r)
+ goto error_free_irq;
+
+ return 0;
+
+error_free_irq:
+ free_irq(data->pen_touch_irq, data);
+ cancel_work_sync(&data->work);
+error_put_devs:
+ put_device(data->dig_dev);
+ put_device(data->kbd_dev);
+ return r;
+}
+
+static void yogabook_pdev_remove(struct platform_device *pdev)
+{
+ struct yogabook_data *data = platform_get_drvdata(pdev);
+
+ yogabook_remove(data);
+ free_irq(data->pen_touch_irq, data);
+ cancel_work_sync(&data->work);
+ put_device(data->dig_dev);
+ put_device(data->kbd_dev);
+}
+
+static struct platform_driver yogabook_pdev_driver = {
+ .probe = yogabook_pdev_probe,
+ .remove_new = yogabook_pdev_remove,
+ .driver = {
+ .name = YB_PDEV_NAME,
+ .pm = pm_sleep_ptr(&yogabook_pm_ops),
+ },
+};
+
+static int __init yogabook_module_init(void)
+{
+ int r;
+
+ r = wmi_driver_register(&yogabook_wmi_driver);
+ if (r)
+ return r;
+
+ r = platform_driver_register(&yogabook_pdev_driver);
+ if (r)
+ wmi_driver_unregister(&yogabook_wmi_driver);
+
+ return r;
+}
+
+static void __exit yogabook_module_exit(void)
+{
+ platform_driver_unregister(&yogabook_pdev_driver);
+ wmi_driver_unregister(&yogabook_wmi_driver);
+}
+
+module_init(yogabook_module_init);
+module_exit(yogabook_module_exit);
+
+MODULE_ALIAS("platform:" YB_PDEV_NAME);
+MODULE_AUTHOR("Yauhen Kharuzhy");
+MODULE_DESCRIPTION("Lenovo Yoga Book driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/x86/simatic-ipc.c b/drivers/platform/x86/simatic-ipc.c
index b3622419cd1a..c773995b230d 100644
--- a/drivers/platform/x86/simatic-ipc.c
+++ b/drivers/platform/x86/simatic-ipc.c
@@ -68,9 +68,10 @@ static int register_platform_devices(u32 station_id)
}
if (ledmode != SIMATIC_IPC_DEVICE_NONE) {
- if (ledmode == SIMATIC_IPC_DEVICE_127E ||
- ledmode == SIMATIC_IPC_DEVICE_227G)
- pdevname = KBUILD_MODNAME "_leds_gpio";
+ if (ledmode == SIMATIC_IPC_DEVICE_127E)
+ pdevname = KBUILD_MODNAME "_leds_gpio_apollolake";
+ if (ledmode == SIMATIC_IPC_DEVICE_227G)
+ pdevname = KBUILD_MODNAME "_leds_gpio_f7188x";
platform_data.devmode = ledmode;
ipc_led_platform_device =
platform_device_register_data(NULL,
diff --git a/drivers/platform/x86/system76_acpi.c b/drivers/platform/x86/system76_acpi.c
index 97f5a8255b91..fc4708fa6ebe 100644
--- a/drivers/platform/x86/system76_acpi.c
+++ b/drivers/platform/x86/system76_acpi.c
@@ -581,7 +581,7 @@ static const struct hwmon_ops thermal_ops = {
};
// Allocate up to 8 fans and temperatures
-static const struct hwmon_channel_info *thermal_channel_info[] = {
+static const struct hwmon_channel_info * const thermal_channel_info[] = {
HWMON_CHANNEL_INFO(fan,
HWMON_F_INPUT | HWMON_F_LABEL,
HWMON_F_INPUT | HWMON_F_LABEL,
diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c
index 1138f770149d..52d1ce8dfe44 100644
--- a/drivers/platform/x86/think-lmi.c
+++ b/drivers/platform/x86/think-lmi.c
@@ -14,6 +14,7 @@
#include <linux/acpi.h>
#include <linux/errno.h>
#include <linux/fs.h>
+#include <linux/mutex.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/dmi.h>
@@ -168,11 +169,11 @@ MODULE_PARM_DESC(debug_support, "Enable debug command support");
*/
#define LENOVO_CERT_THUMBPRINT_GUID "C59119ED-1C0D-4806-A8E9-59AA318176C4"
-#define TLMI_POP_PWD (1 << 0)
-#define TLMI_PAP_PWD (1 << 1)
-#define TLMI_HDD_PWD (1 << 2)
-#define TLMI_SYS_PWD (1 << 3)
-#define TLMI_CERT (1 << 7)
+#define TLMI_POP_PWD BIT(0) /* Supervisor */
+#define TLMI_PAP_PWD BIT(1) /* Power-on */
+#define TLMI_HDD_PWD BIT(2) /* HDD/NVME */
+#define TLMI_SMP_PWD BIT(6) /* System Management */
+#define TLMI_CERT BIT(7) /* Certificate Based */
#define to_tlmi_pwd_setting(kobj) container_of(kobj, struct tlmi_pwd_setting, kobj)
#define to_tlmi_attr_setting(kobj) container_of(kobj, struct tlmi_attr_setting, kobj)
@@ -195,6 +196,7 @@ static const char * const level_options[] = {
};
static struct think_lmi tlmi_priv;
static struct class *fw_attr_class;
+static DEFINE_MUTEX(tlmi_mutex);
/* ------ Utility functions ------------*/
/* Strip out CR if one is present */
@@ -437,6 +439,9 @@ static ssize_t new_password_store(struct kobject *kobj,
/* Strip out CR if one is present, setting password won't work if it is present */
strip_cr(new_pwd);
+ /* Use lock in case multiple WMI operations needed */
+ mutex_lock(&tlmi_mutex);
+
pwdlen = strlen(new_pwd);
/* pwdlen == 0 is allowed to clear the password */
if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) {
@@ -456,9 +461,9 @@ static ssize_t new_password_store(struct kobject *kobj,
sprintf(pwd_type, "mhdp%d", setting->index);
} else if (setting == tlmi_priv.pwd_nvme) {
if (setting->level == TLMI_LEVEL_USER)
- sprintf(pwd_type, "unvp%d", setting->index);
+ sprintf(pwd_type, "udrp%d", setting->index);
else
- sprintf(pwd_type, "mnvp%d", setting->index);
+ sprintf(pwd_type, "adrp%d", setting->index);
} else {
sprintf(pwd_type, "%s", setting->pwd_type);
}
@@ -493,6 +498,7 @@ static ssize_t new_password_store(struct kobject *kobj,
kfree(auth_str);
}
out:
+ mutex_unlock(&tlmi_mutex);
kfree(new_pwd);
return ret ?: count;
}
@@ -879,6 +885,11 @@ static umode_t auth_attr_is_visible(struct kobject *kobj,
return 0;
}
+ /* Don't display un-needed settings if opcode available */
+ if ((attr == &auth_encoding.attr || attr == &auth_kbdlang.attr) &&
+ tlmi_priv.opcode_support)
+ return 0;
+
return attr->mode;
}
@@ -981,6 +992,9 @@ static ssize_t current_value_store(struct kobject *kobj,
/* Strip out CR if one is present */
strip_cr(new_setting);
+ /* Use lock in case multiple WMI operations needed */
+ mutex_lock(&tlmi_mutex);
+
/* Check if certificate authentication is enabled and active */
if (tlmi_priv.certificate_support && tlmi_priv.pwd_admin->cert_installed) {
if (!tlmi_priv.pwd_admin->signature || !tlmi_priv.pwd_admin->save_signature) {
@@ -1001,7 +1015,33 @@ static ssize_t current_value_store(struct kobject *kobj,
tlmi_priv.pwd_admin->save_signature);
if (ret)
goto out;
- } else { /* Non certiifcate based authentication */
+ } else if (tlmi_priv.opcode_support) {
+ /*
+ * If opcode support is present use that interface.
+ * Note - this sets the variable and then the password as separate
+ * WMI calls. Function tlmi_save_bios_settings will error if the
+ * password is incorrect.
+ */
+ set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->display_name,
+ new_setting);
+ if (!set_str) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str);
+ if (ret)
+ goto out;
+
+ if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
+ ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
+ tlmi_priv.pwd_admin->password);
+ if (ret)
+ goto out;
+ }
+
+ ret = tlmi_save_bios_settings("");
+ } else { /* old non-opcode based authentication method (deprecated) */
if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
tlmi_priv.pwd_admin->password,
@@ -1039,6 +1079,7 @@ static ssize_t current_value_store(struct kobject *kobj,
kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE);
}
out:
+ mutex_unlock(&tlmi_mutex);
kfree(auth_str);
kfree(set_str);
kfree(new_setting);
@@ -1483,11 +1524,11 @@ static int tlmi_analyze(void)
tlmi_priv.pwd_power->valid = true;
if (tlmi_priv.opcode_support) {
- tlmi_priv.pwd_system = tlmi_create_auth("sys", "system");
+ tlmi_priv.pwd_system = tlmi_create_auth("smp", "system");
if (!tlmi_priv.pwd_system)
goto fail_clear_attr;
- if (tlmi_priv.pwdcfg.core.password_state & TLMI_SYS_PWD)
+ if (tlmi_priv.pwdcfg.core.password_state & TLMI_SMP_PWD)
tlmi_priv.pwd_system->valid = true;
tlmi_priv.pwd_hdd = tlmi_create_auth("hdd", "hdd");
@@ -1498,6 +1539,10 @@ static int tlmi_analyze(void)
if (!tlmi_priv.pwd_nvme)
goto fail_clear_attr;
+ /* Set default hdd/nvme index to 1 as there is no device 0 */
+ tlmi_priv.pwd_hdd->index = 1;
+ tlmi_priv.pwd_nvme->index = 1;
+
if (tlmi_priv.pwdcfg.core.password_state & TLMI_HDD_PWD) {
/* Check if PWD is configured and set index to first drive found */
if (tlmi_priv.pwdcfg.ext.hdd_user_password ||
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index b3808ad77278..187018ffb068 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -10524,8 +10524,8 @@ unlock:
static void dytc_profile_refresh(void)
{
enum platform_profile_option profile;
- int output, err = 0;
- int perfmode, funcmode;
+ int output = 0, err = 0;
+ int perfmode, funcmode = 0;
mutex_lock(&dytc_mutex);
if (dytc_capabilities & BIT(DYTC_FC_MMC)) {
@@ -10538,6 +10538,8 @@ static void dytc_profile_refresh(void)
err = dytc_command(DYTC_CMD_GET, &output);
/* Check if we are PSC mode, or have AMT enabled */
funcmode = (output >> DYTC_GET_FUNCTION_BIT) & 0xF;
+ } else { /* Unknown profile mode */
+ err = -ENODEV;
}
mutex_unlock(&dytc_mutex);
if (err)
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index b34984bbee33..291f14ef6702 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -3037,7 +3037,7 @@ static int toshiba_acpi_hwmon_read(struct device *dev, enum hwmon_sensor_types t
return -EOPNOTSUPP;
}
-static const struct hwmon_channel_info *toshiba_acpi_hwmon_info[] = {
+static const struct hwmon_channel_info * const toshiba_acpi_hwmon_info[] = {
HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT),
NULL
};
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index d81319a502ef..5b95d7aa5c2f 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -248,7 +248,9 @@ static acpi_status get_event_data(const struct wmi_block *wblock, struct acpi_bu
* @wdev: A wmi bus device from a driver
* @length: Required buffer size
*
- * Allocates memory needed for buffer, stores the buffer size in that memory
+ * Allocates memory needed for buffer, stores the buffer size in that memory.
+ *
+ * Return: 0 on success or a negative error code for failure.
*/
int set_required_buffer_size(struct wmi_device *wdev, u64 length)
{
@@ -262,14 +264,57 @@ int set_required_buffer_size(struct wmi_device *wdev, u64 length)
EXPORT_SYMBOL_GPL(set_required_buffer_size);
/**
- * wmi_evaluate_method - Evaluate a WMI method
+ * wmi_instance_count - Get number of WMI object instances
+ * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
+ *
+ * Get the number of WMI object instances.
+ *
+ * Returns: Number of WMI object instances or negative error code.
+ */
+int wmi_instance_count(const char *guid_string)
+{
+ struct wmi_block *wblock;
+ acpi_status status;
+
+ status = find_guid(guid_string, &wblock);
+ if (ACPI_FAILURE(status)) {
+ if (status == AE_BAD_PARAMETER)
+ return -EINVAL;
+
+ return -ENODEV;
+ }
+
+ return wmidev_instance_count(&wblock->dev);
+}
+EXPORT_SYMBOL_GPL(wmi_instance_count);
+
+/**
+ * wmidev_instance_count - Get number of WMI object instances
+ * @wdev: A wmi bus device from a driver
+ *
+ * Get the number of WMI object instances.
+ *
+ * Returns: Number of WMI object instances.
+ */
+u8 wmidev_instance_count(struct wmi_device *wdev)
+{
+ struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev);
+
+ return wblock->gblock.instance_count;
+}
+EXPORT_SYMBOL_GPL(wmidev_instance_count);
+
+/**
+ * wmi_evaluate_method - Evaluate a WMI method (deprecated)
* @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
* @instance: Instance index
* @method_id: Method ID to call
* @in: Buffer containing input for the method call
* @out: Empty buffer to return the method results
*
- * Call an ACPI-WMI method
+ * Call an ACPI-WMI method, the caller must free @out.
+ *
+ * Return: acpi_status signaling success or error.
*/
acpi_status wmi_evaluate_method(const char *guid_string, u8 instance, u32 method_id,
const struct acpi_buffer *in, struct acpi_buffer *out)
@@ -294,7 +339,9 @@ EXPORT_SYMBOL_GPL(wmi_evaluate_method);
* @in: Buffer containing input for the method call
* @out: Empty buffer to return the method results
*
- * Call an ACPI-WMI method
+ * Call an ACPI-WMI method, the caller must free @out.
+ *
+ * Return: acpi_status signaling success or error.
*/
acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance, u32 method_id,
const struct acpi_buffer *in, struct acpi_buffer *out)
@@ -411,7 +458,9 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance,
* @instance: Instance index
* @out: Empty buffer to return the contents of the data block to
*
- * Return the contents of an ACPI-WMI data block to a buffer
+ * Query a ACPI-WMI block, the caller must free @out.
+ *
+ * Return: ACPI object containing the content of the WMI block.
*/
acpi_status wmi_query_block(const char *guid_string, u8 instance,
struct acpi_buffer *out)
@@ -427,6 +476,15 @@ acpi_status wmi_query_block(const char *guid_string, u8 instance,
}
EXPORT_SYMBOL_GPL(wmi_query_block);
+/**
+ * wmidev_block_query - Return contents of a WMI block
+ * @wdev: A wmi bus device from a driver
+ * @instance: Instance index
+ *
+ * Query an ACPI-WMI block, the caller must free the result.
+ *
+ * Return: ACPI object containing the content of the WMI block.
+ */
union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance)
{
struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -440,12 +498,14 @@ union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance)
EXPORT_SYMBOL_GPL(wmidev_block_query);
/**
- * wmi_set_block - Write to a WMI block
+ * wmi_set_block - Write to a WMI block (deprecated)
* @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
* @instance: Instance index
* @in: Buffer containing new values for the data block
*
- * Write the contents of the input buffer to an ACPI-WMI data block
+ * Write the contents of the input buffer to an ACPI-WMI data block.
+ *
+ * Return: acpi_status signaling success or error.
*/
acpi_status wmi_set_block(const char *guid_string, u8 instance,
const struct acpi_buffer *in)
@@ -549,12 +609,14 @@ static void wmi_notify_debug(u32 value, void *context)
}
/**
- * wmi_install_notify_handler - Register handler for WMI events
+ * wmi_install_notify_handler - Register handler for WMI events (deprecated)
* @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
* @handler: Function to handle notifications
* @data: Data to be returned to handler when event is fired
*
* Register a handler for events sent to the ACPI-WMI mapper device.
+ *
+ * Return: acpi_status signaling success or error.
*/
acpi_status wmi_install_notify_handler(const char *guid,
wmi_notify_handler handler,
@@ -593,10 +655,12 @@ acpi_status wmi_install_notify_handler(const char *guid,
EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
/**
- * wmi_remove_notify_handler - Unregister handler for WMI events
+ * wmi_remove_notify_handler - Unregister handler for WMI events (deprecated)
* @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
*
* Unregister handler for events sent to the ACPI-WMI mapper device.
+ *
+ * Return: acpi_status signaling success or error.
*/
acpi_status wmi_remove_notify_handler(const char *guid)
{
@@ -638,12 +702,14 @@ acpi_status wmi_remove_notify_handler(const char *guid)
EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
/**
- * wmi_get_event_data - Get WMI data associated with an event
+ * wmi_get_event_data - Get WMI data associated with an event (deprecated)
*
* @event: Event to find
- * @out: Buffer to hold event data. out->pointer should be freed with kfree()
+ * @out: Buffer to hold event data
*
- * Returns extra data associated with an event in WMI.
+ * Get extra data associated with an WMI event, the caller needs to free @out.
+ *
+ * Return: acpi_status signaling success or error.
*/
acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
{
@@ -664,7 +730,9 @@ EXPORT_SYMBOL_GPL(wmi_get_event_data);
* wmi_has_guid - Check if a GUID is available
* @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
*
- * Check if a given GUID is defined by _WDG
+ * Check if a given GUID is defined by _WDG.
+ *
+ * Return: True if GUID is available, false otherwise.
*/
bool wmi_has_guid(const char *guid_string)
{
@@ -673,12 +741,12 @@ bool wmi_has_guid(const char *guid_string)
EXPORT_SYMBOL_GPL(wmi_has_guid);
/**
- * wmi_get_acpi_device_uid() - Get _UID name of ACPI device that defines GUID
+ * wmi_get_acpi_device_uid() - Get _UID name of ACPI device that defines GUID (deprecated)
* @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
*
* Find the _UID of ACPI device associated with this WMI GUID.
*
- * Return: The ACPI _UID field value or NULL if the WMI GUID was not found
+ * Return: The ACPI _UID field value or NULL if the WMI GUID was not found.
*/
char *wmi_get_acpi_device_uid(const char *guid_string)
{
@@ -1454,6 +1522,12 @@ int __must_check __wmi_driver_register(struct wmi_driver *driver,
}
EXPORT_SYMBOL(__wmi_driver_register);
+/**
+ * wmi_driver_unregister() - Unregister a WMI driver
+ * @driver: WMI driver to unregister
+ *
+ * Unregisters a WMI driver from the WMI bus.
+ */
void wmi_driver_unregister(struct wmi_driver *driver)
{
driver_unregister(&driver->driver);
diff --git a/drivers/platform/x86/x86-android-tablets/asus.c b/drivers/platform/x86/x86-android-tablets/asus.c
index cfa038b44b43..f9c4083be86d 100644
--- a/drivers/platform/x86/x86-android-tablets/asus.c
+++ b/drivers/platform/x86/x86-android-tablets/asus.c
@@ -24,7 +24,7 @@ static struct gpiod_lookup_table int3496_gpo2_pin22_gpios = {
},
};
-static struct x86_gpio_button asus_me176c_tf103c_lid = {
+static const struct x86_gpio_button asus_me176c_tf103c_lid __initconst = {
.button = {
.code = SW_LID,
.active_low = true,
@@ -175,10 +175,10 @@ const struct x86_dev_info asus_me176c_info __initconst = {
.serdev_info = asus_me176c_serdevs,
.serdev_count = ARRAY_SIZE(asus_me176c_serdevs),
.gpio_button = &asus_me176c_tf103c_lid,
+ .gpio_button_count = 1,
.gpiod_lookup_tables = asus_me176c_gpios,
.bat_swnode = &generic_lipo_hv_4v35_battery_node,
.modules = bq24190_modules,
- .invalid_aei_gpiochip = "INT33FC:02",
};
/* Asus TF103C tablets have an Android factory img with everything hardcoded */
@@ -318,8 +318,8 @@ const struct x86_dev_info asus_tf103c_info __initconst = {
.pdev_info = int3496_pdevs,
.pdev_count = 1,
.gpio_button = &asus_me176c_tf103c_lid,
+ .gpio_button_count = 1,
.gpiod_lookup_tables = asus_tf103c_gpios,
.bat_swnode = &asus_tf103c_battery_node,
.modules = bq24190_modules,
- .invalid_aei_gpiochip = "INT33FC:02",
};
diff --git a/drivers/platform/x86/x86-android-tablets/core.c b/drivers/platform/x86/x86-android-tablets/core.c
index 245167674aa2..2fd6060a31bb 100644
--- a/drivers/platform/x86/x86-android-tablets/core.c
+++ b/drivers/platform/x86/x86-android-tablets/core.c
@@ -124,6 +124,7 @@ static int serdev_count;
static struct i2c_client **i2c_clients;
static struct platform_device **pdevs;
static struct serdev_device **serdevs;
+static struct gpio_keys_button *buttons;
static struct gpiod_lookup_table * const *gpiod_lookup_tables;
static const struct software_node *bat_swnode;
static void (*exit_handler)(void);
@@ -238,6 +239,7 @@ static void x86_android_tablet_cleanup(void)
platform_device_unregister(pdevs[i]);
kfree(pdevs);
+ kfree(buttons);
for (i = 0; i < i2c_client_count; i++)
i2c_unregister_device(i2c_clients[i]);
@@ -353,22 +355,30 @@ static __init int x86_android_tablet_init(void)
}
}
- if (dev_info->gpio_button) {
- struct gpio_keys_platform_data pdata = {
- .buttons = &dev_info->gpio_button->button,
- .nbuttons = 1,
- };
+ if (dev_info->gpio_button_count) {
+ struct gpio_keys_platform_data pdata = { };
struct gpio_desc *gpiod;
- /* Get GPIO for the gpio-button */
- ret = x86_android_tablet_get_gpiod(dev_info->gpio_button->chip,
- dev_info->gpio_button->pin, &gpiod);
- if (ret < 0) {
+ buttons = kcalloc(dev_info->gpio_button_count, sizeof(*buttons), GFP_KERNEL);
+ if (!buttons) {
x86_android_tablet_cleanup();
- return ret;
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < dev_info->gpio_button_count; i++) {
+ ret = x86_android_tablet_get_gpiod(dev_info->gpio_button[i].chip,
+ dev_info->gpio_button[i].pin, &gpiod);
+ if (ret < 0) {
+ x86_android_tablet_cleanup();
+ return ret;
+ }
+
+ buttons[i] = dev_info->gpio_button[i].button;
+ buttons[i].gpio = desc_to_gpio(gpiod);
}
- dev_info->gpio_button->button.gpio = desc_to_gpio(gpiod);
+ pdata.buttons = buttons;
+ pdata.nbuttons = dev_info->gpio_button_count;
pdevs[pdev_count] = platform_device_register_data(NULL, "gpio-keys",
PLATFORM_DEVID_AUTO,
diff --git a/drivers/platform/x86/x86-android-tablets/dmi.c b/drivers/platform/x86/x86-android-tablets/dmi.c
index 23e640b7003d..5d6c12494f08 100644
--- a/drivers/platform/x86/x86-android-tablets/dmi.c
+++ b/drivers/platform/x86/x86-android-tablets/dmi.c
@@ -59,6 +59,17 @@ const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
.driver_data = (void *)&chuwi_hi8_info,
},
{
+ /* Cyberbook T116 Android version */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Default string"),
+ DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+ /* Above strings are much too generic, also match on SKU + BIOS date */
+ DMI_MATCH(DMI_PRODUCT_SKU, "20170531"),
+ DMI_MATCH(DMI_BIOS_DATE, "07/12/2017"),
+ },
+ .driver_data = (void *)&cyberbook_t116_info,
+ },
+ {
/* CZC P10T */
.ident = "CZC ODEON TPC-10 (\"P10T\")",
.matches = {
@@ -127,7 +138,7 @@ const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
.driver_data = (void *)&medion_lifetab_s10346_info,
},
{
- /* Nextbook Ares 8 */
+ /* Nextbook Ares 8 (BYT version) */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"),
@@ -135,6 +146,15 @@ const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
.driver_data = (void *)&nextbook_ares8_info,
},
{
+ /* Nextbook Ares 8A (CHT version)*/
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"),
+ DMI_MATCH(DMI_BIOS_VERSION, "M882"),
+ },
+ .driver_data = (void *)&nextbook_ares8a_info,
+ },
+ {
/* Peaq C1010 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"),
diff --git a/drivers/platform/x86/x86-android-tablets/lenovo.c b/drivers/platform/x86/x86-android-tablets/lenovo.c
index 65cfccaa2894..26a4ef670ad7 100644
--- a/drivers/platform/x86/x86-android-tablets/lenovo.c
+++ b/drivers/platform/x86/x86-android-tablets/lenovo.c
@@ -147,6 +147,32 @@ static const struct platform_device_info lenovo_yb1_x90_pdevs[] __initconst = {
},
};
+/*
+ * DSDT says UART path is "\\_SB.PCIO.URT1" with a letter 'O' instead of
+ * the number '0' add the link manually.
+ */
+static const struct x86_serdev_info lenovo_yb1_x90_serdevs[] __initconst = {
+ {
+ .ctrl_hid = "8086228A",
+ .ctrl_uid = "1",
+ .ctrl_devname = "serial0",
+ .serdev_hid = "BCM2E1A",
+ },
+};
+
+static const struct x86_gpio_button lenovo_yb1_x90_lid __initconst = {
+ .button = {
+ .code = SW_LID,
+ .active_low = true,
+ .desc = "lid_sw",
+ .type = EV_SW,
+ .wakeup = true,
+ .debounce_interval = 50,
+ },
+ .chip = "INT33FF:02",
+ .pin = 19,
+};
+
static struct gpiod_lookup_table lenovo_yb1_x90_goodix_gpios = {
.dev_id = "i2c-goodix_ts",
.table = {
@@ -203,6 +229,10 @@ const struct x86_dev_info lenovo_yogabook_x90_info __initconst = {
.i2c_client_count = ARRAY_SIZE(lenovo_yb1_x90_i2c_clients),
.pdev_info = lenovo_yb1_x90_pdevs,
.pdev_count = ARRAY_SIZE(lenovo_yb1_x90_pdevs),
+ .serdev_info = lenovo_yb1_x90_serdevs,
+ .serdev_count = ARRAY_SIZE(lenovo_yb1_x90_serdevs),
+ .gpio_button = &lenovo_yb1_x90_lid,
+ .gpio_button_count = 1,
.gpiod_lookup_tables = lenovo_yb1_x90_gpios,
.init = lenovo_yb1_x90_init,
};
@@ -239,7 +269,7 @@ static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = {
.properties = lenovo_yoga_tab2_830_1050_bq24190_props,
};
-static struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid = {
+static const struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid __initconst = {
.button = {
.code = SW_LID,
.active_low = true,
@@ -268,6 +298,14 @@ static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __init
},
.adapter_path = "\\_SB_.I2C5",
}, {
+ /* AL3320A ambient light sensor */
+ .board_info = {
+ .type = "al3320a",
+ .addr = 0x1c,
+ .dev_name = "al3320a",
+ },
+ .adapter_path = "\\_SB_.I2C5",
+ }, {
/* bq24292i battery charger */
.board_info = {
.type = "bq24190",
@@ -357,6 +395,7 @@ const struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initconst = {
.pdev_info = int3496_pdevs,
.pdev_count = 1,
.gpio_button = &lenovo_yoga_tab2_830_1050_lid,
+ .gpio_button_count = 1,
.gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios,
.bat_swnode = &generic_lipo_hv_4v35_battery_node,
.modules = bq24190_modules,
diff --git a/drivers/platform/x86/x86-android-tablets/other.c b/drivers/platform/x86/x86-android-tablets/other.c
index 83cd7e16c84c..e79549c6aae1 100644
--- a/drivers/platform/x86/x86-android-tablets/other.c
+++ b/drivers/platform/x86/x86-android-tablets/other.c
@@ -94,7 +94,7 @@ const struct x86_dev_info acer_b1_750_info __initconst = {
* which is not described in the ACPI tables in anyway.
* Use the x86-android-tablets infra to create a gpio-button device for this.
*/
-static struct x86_gpio_button advantech_mica_071_button = {
+static const struct x86_gpio_button advantech_mica_071_button __initconst = {
.button = {
.code = KEY_PROG1,
.active_low = true,
@@ -109,6 +109,7 @@ static struct x86_gpio_button advantech_mica_071_button = {
const struct x86_dev_info advantech_mica_071_info __initconst = {
.gpio_button = &advantech_mica_071_button,
+ .gpio_button_count = 1,
};
/*
@@ -196,6 +197,45 @@ const struct x86_dev_info chuwi_hi8_info __initconst = {
.init = chuwi_hi8_init,
};
+/*
+ * Cyberbook T116 Android version
+ * This comes in both Windows and Android versions and even on Android
+ * the DSDT is mostly sane. This tablet has 2 extra general purpose buttons
+ * in the button row with the power + volume-buttons labeled P and F.
+ * Use the x86-android-tablets infra to create a gpio-button device for these.
+ */
+static const struct x86_gpio_button cyberbook_t116_buttons[] __initconst = {
+ {
+ .button = {
+ .code = KEY_PROG1,
+ .active_low = true,
+ .desc = "prog1_key",
+ .type = EV_KEY,
+ .wakeup = false,
+ .debounce_interval = 50,
+ },
+ .chip = "INT33FF:00",
+ .pin = 30,
+ },
+ {
+ .button = {
+ .code = KEY_PROG2,
+ .active_low = true,
+ .desc = "prog2_key",
+ .type = EV_KEY,
+ .wakeup = false,
+ .debounce_interval = 50,
+ },
+ .chip = "INT33FF:03",
+ .pin = 48,
+ },
+};
+
+const struct x86_dev_info cyberbook_t116_info __initconst = {
+ .gpio_button = cyberbook_t116_buttons,
+ .gpio_button_count = ARRAY_SIZE(cyberbook_t116_buttons),
+};
+
#define CZC_EC_EXTRA_PORT 0x68
#define CZC_EC_ANDROID_KEYS 0x63
@@ -311,7 +351,7 @@ const struct x86_dev_info medion_lifetab_s10346_info __initconst = {
.gpiod_lookup_tables = medion_lifetab_s10346_gpios,
};
-/* Nextbook Ares 8 tablets have an Android factory img with everything hardcoded */
+/* Nextbook Ares 8 (BYT) tablets have an Android factory img with everything hardcoded */
static const char * const nextbook_ares8_accel_mount_matrix[] = {
"0", "-1", "0",
"-1", "0", "0",
@@ -377,7 +417,70 @@ const struct x86_dev_info nextbook_ares8_info __initconst = {
.pdev_info = int3496_pdevs,
.pdev_count = 1,
.gpiod_lookup_tables = nextbook_ares8_gpios,
- .invalid_aei_gpiochip = "INT33FC:02",
+};
+
+/* Nextbook Ares 8A (CHT) tablets have an Android factory img with everything hardcoded */
+static const char * const nextbook_ares8a_accel_mount_matrix[] = {
+ "1", "0", "0",
+ "0", "-1", "0",
+ "0", "0", "1"
+};
+
+static const struct property_entry nextbook_ares8a_accel_props[] = {
+ PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", nextbook_ares8a_accel_mount_matrix),
+ { }
+};
+
+static const struct software_node nextbook_ares8a_accel_node = {
+ .properties = nextbook_ares8a_accel_props,
+};
+
+static const struct x86_i2c_client_info nextbook_ares8a_i2c_clients[] __initconst = {
+ {
+ /* Freescale MMA8653FC accel */
+ .board_info = {
+ .type = "mma8653",
+ .addr = 0x1d,
+ .dev_name = "mma8653",
+ .swnode = &nextbook_ares8a_accel_node,
+ },
+ .adapter_path = "\\_SB_.PCI0.I2C3",
+ }, {
+ /* FT5416DQ9 touchscreen controller */
+ .board_info = {
+ .type = "edt-ft5x06",
+ .addr = 0x38,
+ .dev_name = "ft5416",
+ .swnode = &nextbook_ares8_touchscreen_node,
+ },
+ .adapter_path = "\\_SB_.PCI0.I2C6",
+ .irq_data = {
+ .type = X86_ACPI_IRQ_TYPE_GPIOINT,
+ .chip = "INT33FF:01",
+ .index = 17,
+ .trigger = ACPI_EDGE_SENSITIVE,
+ .polarity = ACPI_ACTIVE_LOW,
+ },
+ },
+};
+
+static struct gpiod_lookup_table nextbook_ares8a_ft5416_gpios = {
+ .dev_id = "i2c-ft5416",
+ .table = {
+ GPIO_LOOKUP("INT33FF:01", 25, "reset", GPIO_ACTIVE_LOW),
+ { }
+ },
+};
+
+static struct gpiod_lookup_table * const nextbook_ares8a_gpios[] = {
+ &nextbook_ares8a_ft5416_gpios,
+ NULL
+};
+
+const struct x86_dev_info nextbook_ares8a_info __initconst = {
+ .i2c_client_info = nextbook_ares8a_i2c_clients,
+ .i2c_client_count = ARRAY_SIZE(nextbook_ares8a_i2c_clients),
+ .gpiod_lookup_tables = nextbook_ares8a_gpios,
};
/*
@@ -386,7 +489,7 @@ const struct x86_dev_info nextbook_ares8_info __initconst = {
* This button has a WMI interface, but that is broken. Instead of trying to
* use the broken WMI interface, instantiate a gpio_keys device for this.
*/
-static struct x86_gpio_button peaq_c1010_button = {
+static const struct x86_gpio_button peaq_c1010_button __initconst = {
.button = {
.code = KEY_SOUND,
.active_low = true,
@@ -401,6 +504,7 @@ static struct x86_gpio_button peaq_c1010_button = {
const struct x86_dev_info peaq_c1010_info __initconst = {
.gpio_button = &peaq_c1010_button,
+ .gpio_button_count = 1,
/*
* Move the ACPI event handler used by the broken WMI interface out of
* the way. This is the only event handler on INT33FC:00.
diff --git a/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h b/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h
index b6802d75dbdd..e46e1128acc8 100644
--- a/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h
+++ b/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h
@@ -73,10 +73,11 @@ struct x86_dev_info {
const struct x86_i2c_client_info *i2c_client_info;
const struct platform_device_info *pdev_info;
const struct x86_serdev_info *serdev_info;
- struct x86_gpio_button *gpio_button;
+ const struct x86_gpio_button *gpio_button;
int i2c_client_count;
int pdev_count;
int serdev_count;
+ int gpio_button_count;
int (*init)(void);
void (*exit)(void);
};
@@ -93,6 +94,7 @@ extern const struct x86_dev_info advantech_mica_071_info;
extern const struct x86_dev_info asus_me176c_info;
extern const struct x86_dev_info asus_tf103c_info;
extern const struct x86_dev_info chuwi_hi8_info;
+extern const struct x86_dev_info cyberbook_t116_info;
extern const struct x86_dev_info czc_p10t;
extern const struct x86_dev_info lenovo_yogabook_x90_info;
extern const struct x86_dev_info lenovo_yogabook_x91_info;
@@ -100,6 +102,7 @@ extern const struct x86_dev_info lenovo_yoga_tab2_830_1050_info;
extern const struct x86_dev_info lenovo_yt3_info;
extern const struct x86_dev_info medion_lifetab_s10346_info;
extern const struct x86_dev_info nextbook_ares8_info;
+extern const struct x86_dev_info nextbook_ares8a_info;
extern const struct x86_dev_info peaq_c1010_info;
extern const struct x86_dev_info whitelabel_tm800a550l_info;
extern const struct x86_dev_info xiaomi_mipad2_info;
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 8c87eeda0fec..fff07b2bd77b 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -158,6 +158,7 @@ config POWER_RESET_OXNAS
config POWER_RESET_PIIX4_POWEROFF
tristate "Intel PIIX4 power-off driver"
depends on PCI
+ depends on HAS_IOPORT
depends on MIPS || COMPILE_TEST
help
This driver supports powering off a system using the Intel PIIX4
diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c
index 741e44a017c3..d6884841a6dc 100644
--- a/drivers/power/reset/at91-reset.c
+++ b/drivers/power/reset/at91-reset.c
@@ -149,11 +149,10 @@ static int at91_reset(struct notifier_block *this, unsigned long mode,
return NOTIFY_DONE;
}
-static void __init at91_reset_status(struct platform_device *pdev,
- void __iomem *base)
+static const char * __init at91_reset_reason(struct at91_reset *reset)
{
+ u32 reg = readl(reset->rstc_base + AT91_RSTC_SR);
const char *reason;
- u32 reg = readl(base + AT91_RSTC_SR);
switch ((reg & AT91_RSTC_RSTTYP) >> 8) {
case RESET_TYPE_GENERAL:
@@ -185,7 +184,7 @@ static void __init at91_reset_status(struct platform_device *pdev,
break;
}
- dev_info(&pdev->dev, "Starting after %s\n", reason);
+ return reason;
}
static const struct of_device_id at91_ramc_of_match[] = {
@@ -392,7 +391,7 @@ static int __init at91_reset_probe(struct platform_device *pdev)
if (ret)
goto disable_clk;
- at91_reset_status(pdev, reset->rstc_base);
+ dev_info(&pdev->dev, "Starting after %s\n", at91_reset_reason(reset));
return 0;
diff --git a/drivers/power/reset/gpio-restart.c b/drivers/power/reset/gpio-restart.c
index 35d981d5e6c8..a479d3536eb1 100644
--- a/drivers/power/reset/gpio-restart.c
+++ b/drivers/power/reset/gpio-restart.c
@@ -105,7 +105,7 @@ static int gpio_restart_probe(struct platform_device *pdev)
return 0;
}
-static int gpio_restart_remove(struct platform_device *pdev)
+static void gpio_restart_remove(struct platform_device *pdev)
{
struct gpio_restart *gpio_restart = platform_get_drvdata(pdev);
int ret;
@@ -115,10 +115,7 @@ static int gpio_restart_remove(struct platform_device *pdev)
dev_err(&pdev->dev,
"%s: cannot unregister restart handler, %d\n",
__func__, ret);
- return -ENODEV;
}
-
- return 0;
}
static const struct of_device_id of_gpio_restart_match[] = {
@@ -128,7 +125,7 @@ static const struct of_device_id of_gpio_restart_match[] = {
static struct platform_driver gpio_restart_driver = {
.probe = gpio_restart_probe,
- .remove = gpio_restart_remove,
+ .remove_new = gpio_restart_remove,
.driver = {
.name = "restart-gpio",
.of_match_table = of_gpio_restart_match,
diff --git a/drivers/power/reset/qcom-pon.c b/drivers/power/reset/qcom-pon.c
index ebdcfb28c4a0..1344b361a475 100644
--- a/drivers/power/reset/qcom-pon.c
+++ b/drivers/power/reset/qcom-pon.c
@@ -17,6 +17,8 @@
#define GEN1_REASON_SHIFT 2
#define GEN2_REASON_SHIFT 1
+#define NO_REASON_SHIFT 0
+
struct pm8916_pon {
struct device *dev;
struct regmap *regmap;
@@ -45,6 +47,7 @@ static int pm8916_reboot_mode_write(struct reboot_mode_driver *reboot,
static int pm8916_pon_probe(struct platform_device *pdev)
{
struct pm8916_pon *pon;
+ long reason_shift;
int error;
pon = devm_kzalloc(&pdev->dev, sizeof(*pon), GFP_KERNEL);
@@ -64,13 +67,17 @@ static int pm8916_pon_probe(struct platform_device *pdev)
if (error)
return error;
- pon->reboot_mode.dev = &pdev->dev;
- pon->reason_shift = (long)of_device_get_match_data(&pdev->dev);
- pon->reboot_mode.write = pm8916_reboot_mode_write;
- error = devm_reboot_mode_register(&pdev->dev, &pon->reboot_mode);
- if (error) {
- dev_err(&pdev->dev, "can't register reboot mode\n");
- return error;
+ reason_shift = (long)of_device_get_match_data(&pdev->dev);
+
+ if (reason_shift != NO_REASON_SHIFT) {
+ pon->reboot_mode.dev = &pdev->dev;
+ pon->reason_shift = reason_shift;
+ pon->reboot_mode.write = pm8916_reboot_mode_write;
+ error = devm_reboot_mode_register(&pdev->dev, &pon->reboot_mode);
+ if (error) {
+ dev_err(&pdev->dev, "can't register reboot mode\n");
+ return error;
+ }
}
platform_set_drvdata(pdev, pon);
@@ -80,6 +87,7 @@ static int pm8916_pon_probe(struct platform_device *pdev)
static const struct of_device_id pm8916_pon_id_table[] = {
{ .compatible = "qcom,pm8916-pon", .data = (void *)GEN1_REASON_SHIFT },
+ { .compatible = "qcom,pm8941-pon", .data = (void *)NO_REASON_SHIFT },
{ .compatible = "qcom,pms405-pon", .data = (void *)GEN1_REASON_SHIFT },
{ .compatible = "qcom,pm8998-pon", .data = (void *)GEN2_REASON_SHIFT },
{ .compatible = "qcom,pmk8350-pon", .data = (void *)GEN2_REASON_SHIFT },
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 4a5e8e1d1237..663a1c423806 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -766,6 +766,14 @@ config BATTERY_RT5033
The fuelgauge calculates and determines the battery state of charge
according to battery open circuit voltage.
+config CHARGER_RT5033
+ tristate "RT5033 battery charger support"
+ depends on MFD_RT5033
+ help
+ This adds support for battery charger in Richtek RT5033 PMIC.
+ The device supports pre-charge mode, fast charge mode and
+ constant voltage mode.
+
config CHARGER_RT9455
tristate "Richtek RT9455 battery charger driver"
depends on I2C
@@ -934,4 +942,13 @@ config BATTERY_UG3105
device is off or suspended, the functionality of this driver is
limited to reporting capacity only.
+config CHARGER_QCOM_SMB2
+ tristate "Qualcomm PMI8998 PMIC charger driver"
+ depends on MFD_SPMI_PMIC
+ depends on IIO
+ help
+ Say Y here to enable the Qualcomm PMIC Charger driver. This
+ adds support for the SMB2 switch mode battery charger found
+ in PMI8998 and related PMICs.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 4adbfba02d05..a8a9fa6de1e9 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
obj-$(CONFIG_BATTERY_MAX1721X) += max1721x_battery.o
obj-$(CONFIG_BATTERY_RT5033) += rt5033_battery.o
+obj-$(CONFIG_CHARGER_RT5033) += rt5033_charger.o
obj-$(CONFIG_CHARGER_RT9455) += rt9455_charger.o
obj-$(CONFIG_CHARGER_RT9467) += rt9467-charger.o
obj-$(CONFIG_CHARGER_RT9471) += rt9471.o
@@ -109,3 +110,4 @@ obj-$(CONFIG_BATTERY_ACER_A500) += acer_a500_battery.o
obj-$(CONFIG_BATTERY_SURFACE) += surface_battery.o
obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o
obj-$(CONFIG_BATTERY_UG3105) += ug3105_battery.o
+obj-$(CONFIG_CHARGER_QCOM_SMB2) += qcom_pmi8998_charger.o
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
index 840db629a46c..3e3a0d118ce5 100644
--- a/drivers/power/supply/adp5061.c
+++ b/drivers/power/supply/adp5061.c
@@ -736,7 +736,7 @@ static struct i2c_driver adp5061_driver = {
.driver = {
.name = KBUILD_MODNAME,
},
- .probe_new = adp5061_probe,
+ .probe = adp5061_probe,
.id_table = adp5061_id,
};
module_i2c_driver(adp5061_driver);
diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index a1e6d1d44808..51c3f9b6458d 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -26,45 +26,48 @@
#define DRVNAME "axp20x-usb-power-supply"
+#define AXP192_USB_OTG_STATUS 0x04
+
#define AXP20X_PWR_STATUS_VBUS_PRESENT BIT(5)
#define AXP20X_PWR_STATUS_VBUS_USED BIT(4)
#define AXP20X_USB_STATUS_VBUS_VALID BIT(2)
-#define AXP20X_VBUS_PATH_SEL BIT(7)
-#define AXP20X_VBUS_PATH_SEL_OFFSET 7
-
#define AXP20X_VBUS_VHOLD_uV(b) (4000000 + (((b) >> 3) & 7) * 100000)
#define AXP20X_VBUS_VHOLD_MASK GENMASK(5, 3)
#define AXP20X_VBUS_VHOLD_OFFSET 3
-#define AXP20X_VBUS_CLIMIT_MASK 3
-#define AXP20X_VBUS_CLIMIT_900mA 0
-#define AXP20X_VBUS_CLIMIT_500mA 1
-#define AXP20X_VBUS_CLIMIT_100mA 2
-#define AXP20X_VBUS_CLIMIT_NONE 3
-
-#define AXP813_VBUS_CLIMIT_900mA 0
-#define AXP813_VBUS_CLIMIT_1500mA 1
-#define AXP813_VBUS_CLIMIT_2000mA 2
-#define AXP813_VBUS_CLIMIT_2500mA 3
#define AXP20X_ADC_EN1_VBUS_CURR BIT(2)
#define AXP20X_ADC_EN1_VBUS_VOLT BIT(3)
-#define AXP20X_VBUS_MON_VBUS_VALID BIT(3)
-
-#define AXP813_BC_EN BIT(0)
-
/*
* Note do not raise the debounce time, we must report Vusb high within
* 100ms otherwise we get Vbus errors in musb.
*/
#define DEBOUNCE_TIME msecs_to_jiffies(50)
+struct axp_data {
+ const struct power_supply_desc *power_desc;
+ const char * const *irq_names;
+ unsigned int num_irq_names;
+ const int *curr_lim_table;
+ struct reg_field curr_lim_fld;
+ struct reg_field vbus_valid_bit;
+ struct reg_field vbus_mon_bit;
+ struct reg_field usb_bc_en_bit;
+ struct reg_field vbus_disable_bit;
+ bool vbus_needs_polling: 1;
+};
+
struct axp20x_usb_power {
struct regmap *regmap;
+ struct regmap_field *curr_lim_fld;
+ struct regmap_field *vbus_valid_bit;
+ struct regmap_field *vbus_mon_bit;
+ struct regmap_field *usb_bc_en_bit;
+ struct regmap_field *vbus_disable_bit;
struct power_supply *supply;
- enum axp20x_variants axp20x_id;
+ const struct axp_data *axp_data;
struct iio_channel *vbus_v;
struct iio_channel *vbus_i;
struct delayed_work vbus_detect;
@@ -81,7 +84,7 @@ static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power)
* present->absent transition implies an online->offline transition
* and will trigger the VBUS_REMOVAL IRQ.
*/
- if (power->axp20x_id >= AXP221_ID && !power->online)
+ if (power->axp_data->vbus_needs_polling && !power->online)
return true;
return false;
@@ -121,60 +124,6 @@ out:
mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
}
-static int axp20x_get_current_max(struct axp20x_usb_power *power, int *val)
-{
- unsigned int v;
- int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
-
- if (ret)
- return ret;
-
- switch (v & AXP20X_VBUS_CLIMIT_MASK) {
- case AXP20X_VBUS_CLIMIT_100mA:
- if (power->axp20x_id == AXP221_ID)
- *val = -1; /* No 100mA limit */
- else
- *val = 100000;
- break;
- case AXP20X_VBUS_CLIMIT_500mA:
- *val = 500000;
- break;
- case AXP20X_VBUS_CLIMIT_900mA:
- *val = 900000;
- break;
- case AXP20X_VBUS_CLIMIT_NONE:
- *val = -1;
- break;
- }
-
- return 0;
-}
-
-static int axp813_get_current_max(struct axp20x_usb_power *power, int *val)
-{
- unsigned int v;
- int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
-
- if (ret)
- return ret;
-
- switch (v & AXP20X_VBUS_CLIMIT_MASK) {
- case AXP813_VBUS_CLIMIT_900mA:
- *val = 900000;
- break;
- case AXP813_VBUS_CLIMIT_1500mA:
- *val = 1500000;
- break;
- case AXP813_VBUS_CLIMIT_2000mA:
- *val = 2000000;
- break;
- case AXP813_VBUS_CLIMIT_2500mA:
- *val = 2500000;
- break;
- }
- return 0;
-}
-
static int axp20x_usb_power_get_property(struct power_supply *psy,
enum power_supply_property psp, union power_supply_propval *val)
{
@@ -213,9 +162,12 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
val->intval = ret * 1700; /* 1 step = 1.7 mV */
return 0;
case POWER_SUPPLY_PROP_CURRENT_MAX:
- if (power->axp20x_id == AXP813_ID)
- return axp813_get_current_max(power, &val->intval);
- return axp20x_get_current_max(power, &val->intval);
+ ret = regmap_field_read(power->curr_lim_fld, &v);
+ if (ret)
+ return ret;
+
+ val->intval = power->axp_data->curr_lim_table[v];
+ return 0;
case POWER_SUPPLY_PROP_CURRENT_NOW:
if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
ret = iio_read_channel_processed(power->vbus_i,
@@ -256,16 +208,15 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
val->intval = POWER_SUPPLY_HEALTH_GOOD;
- if (power->axp20x_id == AXP202_ID) {
- ret = regmap_read(power->regmap,
- AXP20X_USB_OTG_STATUS, &v);
+ if (power->vbus_valid_bit) {
+ ret = regmap_field_read(power->vbus_valid_bit, &v);
if (ret)
return ret;
- if (!(v & AXP20X_USB_STATUS_VBUS_VALID))
- val->intval =
- POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+ if (v == 0)
+ val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
}
+
break;
case POWER_SUPPLY_PROP_PRESENT:
val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);
@@ -280,16 +231,6 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
return 0;
}
-static int axp813_usb_power_set_online(struct axp20x_usb_power *power,
- int intval)
-{
- int val = !intval << AXP20X_VBUS_PATH_SEL_OFFSET;
-
- return regmap_update_bits(power->regmap,
- AXP20X_VBUS_IPSOUT_MGMT,
- AXP20X_VBUS_PATH_SEL, val);
-}
-
static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
int intval)
{
@@ -316,50 +257,17 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
return -EINVAL;
}
-static int axp813_usb_power_set_current_max(struct axp20x_usb_power *power,
- int intval)
+static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power, int intval)
{
- int val;
+ const unsigned int max = GENMASK(power->axp_data->curr_lim_fld.msb,
+ power->axp_data->curr_lim_fld.lsb);
- switch (intval) {
- case 900000:
- return regmap_update_bits(power->regmap,
- AXP20X_VBUS_IPSOUT_MGMT,
- AXP20X_VBUS_CLIMIT_MASK,
- AXP813_VBUS_CLIMIT_900mA);
- case 1500000:
- case 2000000:
- case 2500000:
- val = (intval - 1000000) / 500000;
- return regmap_update_bits(power->regmap,
- AXP20X_VBUS_IPSOUT_MGMT,
- AXP20X_VBUS_CLIMIT_MASK, val);
- default:
+ if (intval == -1)
return -EINVAL;
- }
-
- return -EINVAL;
-}
-
-static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power,
- int intval)
-{
- int val;
- switch (intval) {
- case 100000:
- if (power->axp20x_id == AXP221_ID)
- return -EINVAL;
- fallthrough;
- case 500000:
- case 900000:
- val = (900000 - intval) / 400000;
- return regmap_update_bits(power->regmap,
- AXP20X_VBUS_IPSOUT_MGMT,
- AXP20X_VBUS_CLIMIT_MASK, val);
- default:
- return -EINVAL;
- }
+ for (unsigned int i = 0; i <= max; ++i)
+ if (power->axp_data->curr_lim_table[i] == intval)
+ return regmap_field_write(power->curr_lim_fld, i);
return -EINVAL;
}
@@ -372,17 +280,15 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
- if (power->axp20x_id != AXP813_ID)
+ if (!power->vbus_disable_bit)
return -EINVAL;
- return axp813_usb_power_set_online(power, val->intval);
+
+ return regmap_field_write(power->vbus_disable_bit, !val->intval);
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
return axp20x_usb_power_set_voltage_min(power, val->intval);
case POWER_SUPPLY_PROP_CURRENT_MAX:
- if (power->axp20x_id == AXP813_ID)
- return axp813_usb_power_set_current_max(power,
- val->intval);
return axp20x_usb_power_set_current_max(power, val->intval);
default:
@@ -405,7 +311,7 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
* the VBUS input offline.
*/
if (psp == POWER_SUPPLY_PROP_ONLINE)
- return power->axp20x_id == AXP813_ID;
+ return power->vbus_disable_bit != NULL;
return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
psp == POWER_SUPPLY_PROP_CURRENT_MAX;
@@ -461,39 +367,81 @@ static const char * const axp22x_irq_names[] = {
"VBUS_REMOVAL",
};
-struct axp_data {
- const struct power_supply_desc *power_desc;
- const char * const *irq_names;
- unsigned int num_irq_names;
- enum axp20x_variants axp20x_id;
+static int axp192_usb_curr_lim_table[] = {
+ -1,
+ -1,
+ 500000,
+ 100000,
+};
+
+static int axp20x_usb_curr_lim_table[] = {
+ 900000,
+ 500000,
+ 100000,
+ -1,
+};
+
+static int axp221_usb_curr_lim_table[] = {
+ 900000,
+ 500000,
+ -1,
+ -1,
+};
+
+static int axp813_usb_curr_lim_table[] = {
+ 900000,
+ 1500000,
+ 2000000,
+ 2500000,
+};
+
+static const struct axp_data axp192_data = {
+ .power_desc = &axp20x_usb_power_desc,
+ .irq_names = axp20x_irq_names,
+ .num_irq_names = ARRAY_SIZE(axp20x_irq_names),
+ .curr_lim_table = axp192_usb_curr_lim_table,
+ .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
+ .vbus_valid_bit = REG_FIELD(AXP192_USB_OTG_STATUS, 2, 2),
+ .vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
};
static const struct axp_data axp202_data = {
.power_desc = &axp20x_usb_power_desc,
.irq_names = axp20x_irq_names,
.num_irq_names = ARRAY_SIZE(axp20x_irq_names),
- .axp20x_id = AXP202_ID,
+ .curr_lim_table = axp20x_usb_curr_lim_table,
+ .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
+ .vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2),
+ .vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
};
static const struct axp_data axp221_data = {
.power_desc = &axp22x_usb_power_desc,
.irq_names = axp22x_irq_names,
.num_irq_names = ARRAY_SIZE(axp22x_irq_names),
- .axp20x_id = AXP221_ID,
+ .curr_lim_table = axp221_usb_curr_lim_table,
+ .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
+ .vbus_needs_polling = true,
};
static const struct axp_data axp223_data = {
.power_desc = &axp22x_usb_power_desc,
.irq_names = axp22x_irq_names,
.num_irq_names = ARRAY_SIZE(axp22x_irq_names),
- .axp20x_id = AXP223_ID,
+ .curr_lim_table = axp20x_usb_curr_lim_table,
+ .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
+ .vbus_needs_polling = true,
};
static const struct axp_data axp813_data = {
.power_desc = &axp22x_usb_power_desc,
.irq_names = axp22x_irq_names,
.num_irq_names = ARRAY_SIZE(axp22x_irq_names),
- .axp20x_id = AXP813_ID,
+ .curr_lim_table = axp813_usb_curr_lim_table,
+ .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
+ .usb_bc_en_bit = REG_FIELD(AXP288_BC_GLOBAL, 0, 0),
+ .vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7),
+ .vbus_needs_polling = true,
};
#ifdef CONFIG_PM_SLEEP
@@ -565,6 +513,26 @@ static int configure_adc_registers(struct axp20x_usb_power *power)
AXP20X_ADC_EN1_VBUS_VOLT);
}
+static int axp20x_regmap_field_alloc_optional(struct device *dev,
+ struct regmap *regmap,
+ struct reg_field fdesc,
+ struct regmap_field **fieldp)
+{
+ struct regmap_field *field;
+
+ if (fdesc.reg == 0) {
+ *fieldp = NULL;
+ return 0;
+ }
+
+ field = devm_regmap_field_alloc(dev, regmap, fdesc);
+ if (IS_ERR(field))
+ return PTR_ERR(field);
+
+ *fieldp = field;
+ return 0;
+}
+
static int axp20x_usb_power_probe(struct platform_device *pdev)
{
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
@@ -591,20 +559,47 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, power);
- power->axp20x_id = axp_data->axp20x_id;
+ power->axp_data = axp_data;
power->regmap = axp20x->regmap;
power->num_irqs = axp_data->num_irq_names;
+ power->curr_lim_fld = devm_regmap_field_alloc(&pdev->dev, power->regmap,
+ axp_data->curr_lim_fld);
+ if (IS_ERR(power->curr_lim_fld))
+ return PTR_ERR(power->curr_lim_fld);
+
+ ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
+ axp_data->vbus_valid_bit,
+ &power->vbus_valid_bit);
+ if (ret)
+ return ret;
+
+ ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
+ axp_data->vbus_mon_bit,
+ &power->vbus_mon_bit);
+ if (ret)
+ return ret;
+
+ ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
+ axp_data->usb_bc_en_bit,
+ &power->usb_bc_en_bit);
+ if (ret)
+ return ret;
+
+ ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
+ axp_data->vbus_disable_bit,
+ &power->vbus_disable_bit);
+ if (ret)
+ return ret;
+
ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect,
axp20x_usb_power_poll_vbus);
if (ret)
return ret;
- if (power->axp20x_id == AXP202_ID) {
+ if (power->vbus_mon_bit) {
/* Enable vbus valid checking */
- ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
- AXP20X_VBUS_MON_VBUS_VALID,
- AXP20X_VBUS_MON_VBUS_VALID);
+ ret = regmap_field_write(power->vbus_mon_bit, 1);
if (ret)
return ret;
@@ -617,10 +612,9 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
return ret;
}
- if (power->axp20x_id == AXP813_ID) {
+ if (power->usb_bc_en_bit) {
/* Enable USB Battery Charging specification detection */
- ret = regmap_update_bits(axp20x->regmap, AXP288_BC_GLOBAL,
- AXP813_BC_EN, AXP813_BC_EN);
+ ret = regmap_field_write(power->usb_bc_en_bit, 1);
if (ret)
return ret;
}
@@ -659,6 +653,9 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
static const struct of_device_id axp20x_usb_power_match[] = {
{
+ .compatible = "x-powers,axp192-usb-power-supply",
+ .data = &axp192_data,
+ }, {
.compatible = "x-powers,axp202-usb-power-supply",
.data = &axp202_data,
}, {
diff --git a/drivers/power/supply/bd99954-charger.c b/drivers/power/supply/bd99954-charger.c
index 250362e15c98..086dcf4033c1 100644
--- a/drivers/power/supply/bd99954-charger.c
+++ b/drivers/power/supply/bd99954-charger.c
@@ -1077,7 +1077,7 @@ static struct i2c_driver bd9995x_driver = {
.name = "bd9995x-charger",
.of_match_table = bd9995x_of_match,
},
- .probe_new = bd9995x_probe,
+ .probe = bd9995x_probe,
};
module_i2c_driver(bd9995x_driver);
diff --git a/drivers/power/supply/bq2415x_charger.c b/drivers/power/supply/bq2415x_charger.c
index 349b69d634e6..6a4798a62588 100644
--- a/drivers/power/supply/bq2415x_charger.c
+++ b/drivers/power/supply/bq2415x_charger.c
@@ -1780,7 +1780,7 @@ static struct i2c_driver bq2415x_driver = {
.of_match_table = of_match_ptr(bq2415x_of_match_table),
.acpi_match_table = ACPI_PTR(bq2415x_i2c_acpi_match),
},
- .probe_new = bq2415x_probe,
+ .probe = bq2415x_probe,
.remove = bq2415x_remove,
.id_table = bq2415x_i2c_id_table,
};
diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
index dc33f00fcc06..ef8235848f56 100644
--- a/drivers/power/supply/bq24190_charger.c
+++ b/drivers/power/supply/bq24190_charger.c
@@ -2034,7 +2034,7 @@ static const struct of_device_id bq24190_of_match[] = {
MODULE_DEVICE_TABLE(of, bq24190_of_match);
static struct i2c_driver bq24190_driver = {
- .probe_new = bq24190_probe,
+ .probe = bq24190_probe,
.remove = bq24190_remove,
.shutdown = bq24190_shutdown,
.id_table = bq24190_i2c_ids,
diff --git a/drivers/power/supply/bq24257_charger.c b/drivers/power/supply/bq24257_charger.c
index 45e4ba30da98..2852860abf86 100644
--- a/drivers/power/supply/bq24257_charger.c
+++ b/drivers/power/supply/bq24257_charger.c
@@ -1165,7 +1165,7 @@ static struct i2c_driver bq24257_driver = {
.acpi_match_table = ACPI_PTR(bq24257_acpi_match),
.pm = &bq24257_pm,
},
- .probe_new = bq24257_probe,
+ .probe = bq24257_probe,
.remove = bq24257_remove,
.id_table = bq24257_i2c_ids,
};
diff --git a/drivers/power/supply/bq24735-charger.c b/drivers/power/supply/bq24735-charger.c
index cfca3a82d5a8..8efceeae864c 100644
--- a/drivers/power/supply/bq24735-charger.c
+++ b/drivers/power/supply/bq24735-charger.c
@@ -505,7 +505,7 @@ static struct i2c_driver bq24735_charger_driver = {
.name = "bq24735-charger",
.of_match_table = bq24735_match_ids,
},
- .probe_new = bq24735_charger_probe,
+ .probe = bq24735_charger_probe,
.id_table = bq24735_charger_id,
};
diff --git a/drivers/power/supply/bq2515x_charger.c b/drivers/power/supply/bq2515x_charger.c
index da224ae8dc61..1dbacc9b015d 100644
--- a/drivers/power/supply/bq2515x_charger.c
+++ b/drivers/power/supply/bq2515x_charger.c
@@ -1158,7 +1158,7 @@ static struct i2c_driver bq2515x_driver = {
.name = "bq2515x-charger",
.of_match_table = bq2515x_of_match,
},
- .probe_new = bq2515x_probe,
+ .probe = bq2515x_probe,
.id_table = bq2515x_i2c_ids,
};
module_i2c_driver(bq2515x_driver);
diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c
index e624834ae66c..82d3cd5ee2f9 100644
--- a/drivers/power/supply/bq256xx_charger.c
+++ b/drivers/power/supply/bq256xx_charger.c
@@ -41,6 +41,9 @@
#define BQ256XX_IINDPM_MAX_uA 3200000
#define BQ256XX_IINDPM_DEF_uA 2400000
+#define BQ256XX_TS_IGNORE BIT(6)
+#define BQ256XX_TS_IGNORE_SHIFT 6
+
#define BQ256XX_VINDPM_MASK GENMASK(3, 0)
#define BQ256XX_VINDPM_STEP_uV 100000
#define BQ256XX_VINDPM_OFFSET_uV 3900000
@@ -156,6 +159,7 @@
* @vindpm: input voltage limit
* @ichg_max: maximum fast charge current
* @vbatreg_max: maximum charge voltage
+ * @ts_ignore: TS_IGNORE flag
*/
struct bq256xx_init_data {
u32 ichg;
@@ -166,6 +170,7 @@ struct bq256xx_init_data {
u32 vindpm;
u32 ichg_max;
u32 vbatreg_max;
+ bool ts_ignore;
};
/**
@@ -263,6 +268,7 @@ struct bq256xx_device {
* @bq256xx_set_iprechg: pointer to instance specific set_iprechg function
* @bq256xx_set_vindpm: pointer to instance specific set_vindpm function
* @bq256xx_set_charge_type: pointer to instance specific set_charge_type function
+ * @bq256xx_set_ts_ignore: pointer to instance specific set_ts_ignore function
*
* @bq256xx_def_ichg: default ichg value in microamps
* @bq256xx_def_iindpm: default iindpm value in microamps
@@ -295,6 +301,7 @@ struct bq256xx_chip_info {
int (*bq256xx_set_iprechg)(struct bq256xx_device *bq, int iprechg);
int (*bq256xx_set_vindpm)(struct bq256xx_device *bq, int vindpm);
int (*bq256xx_set_charge_type)(struct bq256xx_device *bq, int type);
+ int (*bq256xx_set_ts_ignore)(struct bq256xx_device *bq, bool ts_ignore);
int bq256xx_def_ichg;
int bq256xx_def_iindpm;
@@ -696,6 +703,12 @@ static int bq25601d_set_chrg_volt(struct bq256xx_device *bq, int vbatreg)
BQ256XX_VBATREG_BIT_SHIFT);
}
+static int bq256xx_set_ts_ignore(struct bq256xx_device *bq, bool ts_ignore)
+{
+ return regmap_update_bits(bq->regmap, BQ256XX_INPUT_CURRENT_LIMIT,
+ BQ256XX_TS_IGNORE, (ts_ignore ? 1 : 0) << BQ256XX_TS_IGNORE_SHIFT);
+}
+
static int bq256xx_get_prechrg_curr(struct bq256xx_device *bq)
{
unsigned int prechg_and_term_curr_lim;
@@ -1312,6 +1325,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_get_iterm = bq256xx_get_term_curr,
.bq256xx_get_iprechg = bq256xx_get_prechrg_curr,
.bq256xx_get_vindpm = bq256xx_get_input_volt_lim,
+ .bq256xx_set_ts_ignore = NULL,
.bq256xx_set_ichg = bq256xx_set_ichg_curr,
.bq256xx_set_iindpm = bq256xx_set_input_curr_lim,
@@ -1351,6 +1365,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
.bq256xx_set_charge_type = bq256xx_set_charge_type,
+ .bq256xx_set_ts_ignore = NULL,
.bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1382,6 +1397,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
.bq256xx_set_charge_type = bq256xx_set_charge_type,
+ .bq256xx_set_ts_ignore = NULL,
.bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1413,6 +1429,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
.bq256xx_set_charge_type = bq256xx_set_charge_type,
+ .bq256xx_set_ts_ignore = NULL,
.bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1444,6 +1461,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
.bq256xx_set_charge_type = bq256xx_set_charge_type,
+ .bq256xx_set_ts_ignore = bq256xx_set_ts_ignore,
.bq256xx_def_ichg = BQ25611D_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1475,6 +1493,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iprechg = bq25618_619_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
.bq256xx_set_charge_type = bq256xx_set_charge_type,
+ .bq256xx_set_ts_ignore = bq256xx_set_ts_ignore,
.bq256xx_def_ichg = BQ25618_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1506,6 +1525,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iprechg = bq25618_619_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
.bq256xx_set_charge_type = bq256xx_set_charge_type,
+ .bq256xx_set_ts_ignore = bq256xx_set_ts_ignore,
.bq256xx_def_ichg = BQ25618_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1622,6 +1642,12 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
if (ret)
return ret;
+ if (bq->chip_info->bq256xx_set_ts_ignore) {
+ ret = bq->chip_info->bq256xx_set_ts_ignore(bq, bq->init_data.ts_ignore);
+ if (ret)
+ return ret;
+ }
+
power_supply_put_battery_info(bq->charger, bat_info);
return 0;
@@ -1656,6 +1682,8 @@ static int bq256xx_parse_dt(struct bq256xx_device *bq,
if (ret)
bq->init_data.iindpm = bq->chip_info->bq256xx_def_iindpm;
+ bq->init_data.ts_ignore = device_property_read_bool(bq->dev, "ti,no-thermistor");
+
return 0;
}
@@ -1784,7 +1812,7 @@ static struct i2c_driver bq256xx_driver = {
.of_match_table = bq256xx_of_match,
.acpi_match_table = bq256xx_acpi_match,
},
- .probe_new = bq256xx_probe,
+ .probe = bq256xx_probe,
.id_table = bq256xx_i2c_ids,
};
module_i2c_driver(bq256xx_driver);
diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c
index f8636cf86505..03fa11a1c9b6 100644
--- a/drivers/power/supply/bq25890_charger.c
+++ b/drivers/power/supply/bq25890_charger.c
@@ -1649,7 +1649,7 @@ static struct i2c_driver bq25890_driver = {
.acpi_match_table = ACPI_PTR(bq25890_acpi_match),
.pm = &bq25890_pm,
},
- .probe_new = bq25890_probe,
+ .probe = bq25890_probe,
.remove = bq25890_remove,
.shutdown = bq25890_shutdown,
.id_table = bq25890_i2c_ids,
diff --git a/drivers/power/supply/bq25980_charger.c b/drivers/power/supply/bq25980_charger.c
index a59d9762bc91..d8411722266f 100644
--- a/drivers/power/supply/bq25980_charger.c
+++ b/drivers/power/supply/bq25980_charger.c
@@ -1287,7 +1287,7 @@ static struct i2c_driver bq25980_driver = {
.name = "bq25980-charger",
.of_match_table = bq25980_of_match,
},
- .probe_new = bq25980_probe,
+ .probe = bq25980_probe,
.id_table = bq25980_i2c_ids,
};
module_i2c_driver(bq25980_driver);
diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
index 6d3c74876339..9b5475590518 100644
--- a/drivers/power/supply/bq27xxx_battery_i2c.c
+++ b/drivers/power/supply/bq27xxx_battery_i2c.c
@@ -296,7 +296,7 @@ static struct i2c_driver bq27xxx_battery_i2c_driver = {
.name = "bq27xxx-battery",
.of_match_table = of_match_ptr(bq27xxx_battery_i2c_of_match_table),
},
- .probe_new = bq27xxx_battery_i2c_probe,
+ .probe = bq27xxx_battery_i2c_probe,
.remove = bq27xxx_battery_i2c_remove,
.id_table = bq27xxx_i2c_id_table,
};
diff --git a/drivers/power/supply/cros_peripheral_charger.c b/drivers/power/supply/cros_peripheral_charger.c
index 1379afd9698d..a204f2355be4 100644
--- a/drivers/power/supply/cros_peripheral_charger.c
+++ b/drivers/power/supply/cros_peripheral_charger.c
@@ -227,8 +227,7 @@ static int cros_pchg_get_prop(struct power_supply *psy,
return 0;
}
-static int cros_pchg_event(const struct charger_data *charger,
- unsigned long host_event)
+static int cros_pchg_event(const struct charger_data *charger)
{
int i;
@@ -256,7 +255,7 @@ static int cros_ec_notify(struct notifier_block *nb,
if (!(host_event & EC_MKBP_PCHG_DEVICE_EVENT))
return NOTIFY_DONE;
- return cros_pchg_event(charger, host_event);
+ return cros_pchg_event(charger);
}
static int cros_pchg_probe(struct platform_device *pdev)
@@ -281,6 +280,8 @@ static int cros_pchg_probe(struct platform_device *pdev)
charger->ec_dev = ec_dev;
charger->ec_device = ec_device;
+ platform_set_drvdata(pdev, charger);
+
ret = cros_pchg_port_count(charger);
if (ret <= 0) {
/*
@@ -349,9 +350,27 @@ static int cros_pchg_probe(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int __maybe_unused cros_pchg_resume(struct device *dev)
+{
+ struct charger_data *charger = dev_get_drvdata(dev);
+
+ /*
+ * Sync all ports on resume in case reports from EC are lost during
+ * the last suspend.
+ */
+ cros_pchg_event(charger);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(cros_pchg_pm_ops, NULL, cros_pchg_resume);
+
static struct platform_driver cros_pchg_driver = {
.driver = {
.name = DRV_NAME,
+ .pm = &cros_pchg_pm_ops,
},
.probe = cros_pchg_probe
};
diff --git a/drivers/power/supply/cw2015_battery.c b/drivers/power/supply/cw2015_battery.c
index 473522b4326a..bb29e9ebd24a 100644
--- a/drivers/power/supply/cw2015_battery.c
+++ b/drivers/power/supply/cw2015_battery.c
@@ -747,7 +747,7 @@ static struct i2c_driver cw_bat_driver = {
.of_match_table = cw2015_of_match,
.pm = &cw_bat_pm_ops,
},
- .probe_new = cw_bat_probe,
+ .probe = cw_bat_probe,
.id_table = cw_bat_id_table,
};
diff --git a/drivers/power/supply/ds2782_battery.c b/drivers/power/supply/ds2782_battery.c
index 9b9619246902..85aa9c465aa4 100644
--- a/drivers/power/supply/ds2782_battery.c
+++ b/drivers/power/supply/ds2782_battery.c
@@ -458,7 +458,7 @@ static struct i2c_driver ds278x_battery_driver = {
.name = "ds2782-battery",
.pm = &ds278x_battery_pm_ops,
},
- .probe_new = ds278x_battery_probe,
+ .probe = ds278x_battery_probe,
.remove = ds278x_battery_remove,
.id_table = ds278x_id,
};
diff --git a/drivers/power/supply/ip5xxx_power.c b/drivers/power/supply/ip5xxx_power.c
index 00221e9c0bfc..82263646ddc6 100644
--- a/drivers/power/supply/ip5xxx_power.c
+++ b/drivers/power/supply/ip5xxx_power.c
@@ -625,7 +625,7 @@ static const struct of_device_id ip5xxx_power_of_match[] = {
MODULE_DEVICE_TABLE(of, ip5xxx_power_of_match);
static struct i2c_driver ip5xxx_power_driver = {
- .probe_new = ip5xxx_power_probe,
+ .probe = ip5xxx_power_probe,
.driver = {
.name = "ip5xxx-power",
.of_match_table = ip5xxx_power_of_match,
diff --git a/drivers/power/supply/lp8727_charger.c b/drivers/power/supply/lp8727_charger.c
index dc42d354b892..0875391f7ac6 100644
--- a/drivers/power/supply/lp8727_charger.c
+++ b/drivers/power/supply/lp8727_charger.c
@@ -615,7 +615,7 @@ static struct i2c_driver lp8727_driver = {
.name = "lp8727",
.of_match_table = of_match_ptr(lp8727_dt_ids),
},
- .probe_new = lp8727_probe,
+ .probe = lp8727_probe,
.remove = lp8727_remove,
.id_table = lp8727_ids,
};
diff --git a/drivers/power/supply/ltc2941-battery-gauge.c b/drivers/power/supply/ltc2941-battery-gauge.c
index d3fb42825983..cad39a8f829d 100644
--- a/drivers/power/supply/ltc2941-battery-gauge.c
+++ b/drivers/power/supply/ltc2941-battery-gauge.c
@@ -635,7 +635,7 @@ static struct i2c_driver ltc294x_driver = {
.of_match_table = ltc294x_i2c_of_match,
.pm = LTC294X_PM_OPS,
},
- .probe_new = ltc294x_i2c_probe,
+ .probe = ltc294x_i2c_probe,
.shutdown = ltc294x_i2c_shutdown,
.id_table = ltc294x_i2c_id,
};
diff --git a/drivers/power/supply/ltc4162-l-charger.c b/drivers/power/supply/ltc4162-l-charger.c
index 285580845e2f..ec5b4a20ad43 100644
--- a/drivers/power/supply/ltc4162-l-charger.c
+++ b/drivers/power/supply/ltc4162-l-charger.c
@@ -915,7 +915,7 @@ static const struct of_device_id ltc4162l_of_match[] __maybe_unused = {
MODULE_DEVICE_TABLE(of, ltc4162l_of_match);
static struct i2c_driver ltc4162l_driver = {
- .probe_new = ltc4162l_probe,
+ .probe = ltc4162l_probe,
.alert = ltc4162l_alert,
.id_table = ltc4162l_i2c_id_table,
.driver = {
diff --git a/drivers/power/supply/max14656_charger_detector.c b/drivers/power/supply/max14656_charger_detector.c
index 0d0180fcfa63..fbdf12cf64eb 100644
--- a/drivers/power/supply/max14656_charger_detector.c
+++ b/drivers/power/supply/max14656_charger_detector.c
@@ -316,7 +316,7 @@ static struct i2c_driver max14656_i2c_driver = {
.name = "max14656",
.of_match_table = max14656_match_table,
},
- .probe_new = max14656_probe,
+ .probe = max14656_probe,
.id_table = max14656_id,
};
module_i2c_driver(max14656_i2c_driver);
diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c
index d1075959dd46..22ea7de47a53 100644
--- a/drivers/power/supply/max17040_battery.c
+++ b/drivers/power/supply/max17040_battery.c
@@ -599,7 +599,7 @@ static struct i2c_driver max17040_i2c_driver = {
.of_match_table = max17040_of_match,
.pm = MAX17040_PM_OPS,
},
- .probe_new = max17040_probe,
+ .probe = max17040_probe,
.id_table = max17040_id,
};
module_i2c_driver(max17040_i2c_driver);
diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c
index 89cabe8ed3b0..17ac2ab78c4e 100644
--- a/drivers/power/supply/max17042_battery.c
+++ b/drivers/power/supply/max17042_battery.c
@@ -499,11 +499,6 @@ static int max17042_property_is_writeable(struct power_supply *psy,
return ret;
}
-static void max17042_external_power_changed(struct power_supply *psy)
-{
- power_supply_changed(psy);
-}
-
static int max17042_write_verify_reg(struct regmap *map, u8 reg, u32 value)
{
int retries = 8;
@@ -1016,7 +1011,7 @@ static const struct power_supply_desc max17042_psy_desc = {
.get_property = max17042_get_property,
.set_property = max17042_set_property,
.property_is_writeable = max17042_property_is_writeable,
- .external_power_changed = max17042_external_power_changed,
+ .external_power_changed = power_supply_changed,
.properties = max17042_battery_props,
.num_properties = ARRAY_SIZE(max17042_battery_props),
};
@@ -1220,7 +1215,7 @@ static struct i2c_driver max17042_i2c_driver = {
.of_match_table = of_match_ptr(max17042_dt_match),
.pm = &max17042_pm_ops,
},
- .probe_new = max17042_probe,
+ .probe = max17042_probe,
.id_table = max17042_id,
};
module_i2c_driver(max17042_i2c_driver);
diff --git a/drivers/power/supply/max77976_charger.c b/drivers/power/supply/max77976_charger.c
index 4fed74511931..99659dc8f5a6 100644
--- a/drivers/power/supply/max77976_charger.c
+++ b/drivers/power/supply/max77976_charger.c
@@ -499,7 +499,7 @@ static struct i2c_driver max77976_driver = {
.name = MAX77976_DRIVER_NAME,
.of_match_table = max77976_of_id,
},
- .probe_new = max77976_probe,
+ .probe = max77976_probe,
.id_table = max77976_i2c_id,
};
module_i2c_driver(max77976_driver);
diff --git a/drivers/power/supply/power_supply_hwmon.c b/drivers/power/supply/power_supply_hwmon.c
index a48aa4afb828..c97893d4c25e 100644
--- a/drivers/power/supply/power_supply_hwmon.c
+++ b/drivers/power/supply/power_supply_hwmon.c
@@ -293,7 +293,7 @@ static const struct hwmon_ops power_supply_hwmon_ops = {
.read_string = power_supply_hwmon_read_string,
};
-static const struct hwmon_channel_info *power_supply_hwmon_info[] = {
+static const struct hwmon_channel_info * const power_supply_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp,
HWMON_T_LABEL |
HWMON_T_INPUT |
diff --git a/drivers/power/supply/power_supply_leds.c b/drivers/power/supply/power_supply_leds.c
index 0674483279d7..c7db29d5fcb8 100644
--- a/drivers/power/supply/power_supply_leds.c
+++ b/drivers/power/supply/power_supply_leds.c
@@ -22,8 +22,6 @@
static void power_supply_update_bat_leds(struct power_supply *psy)
{
union power_supply_propval status;
- unsigned long delay_on = 0;
- unsigned long delay_off = 0;
if (power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
return;
@@ -43,8 +41,7 @@ static void power_supply_update_bat_leds(struct power_supply *psy)
led_trigger_event(psy->charging_full_trig, LED_FULL);
led_trigger_event(psy->charging_trig, LED_FULL);
led_trigger_event(psy->full_trig, LED_OFF);
- led_trigger_blink(psy->charging_blink_full_solid_trig,
- &delay_on, &delay_off);
+ led_trigger_blink(psy->charging_blink_full_solid_trig, 0, 0);
break;
default:
led_trigger_event(psy->charging_full_trig, LED_OFF);
diff --git a/drivers/power/supply/qcom_pmi8998_charger.c b/drivers/power/supply/qcom_pmi8998_charger.c
new file mode 100644
index 000000000000..d16c5ee17249
--- /dev/null
+++ b/drivers/power/supply/qcom_pmi8998_charger.c
@@ -0,0 +1,1059 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Ltd.
+ * Author: Caleb Connolly <caleb.connolly@linaro.org>
+ *
+ * This driver is for the switch-mode battery charger and boost
+ * hardware found in pmi8998 and related PMICs.
+ */
+
+#include <linux/bits.h>
+#include <linux/devm-helpers.h>
+#include <linux/iio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/of.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+/* clang-format off */
+#define BATTERY_CHARGER_STATUS_1 0x06
+#define BVR_INITIAL_RAMP_BIT BIT(7)
+#define CC_SOFT_TERMINATE_BIT BIT(6)
+#define STEP_CHARGING_STATUS_SHIFT 3
+#define STEP_CHARGING_STATUS_MASK GENMASK(5, 3)
+#define BATTERY_CHARGER_STATUS_MASK GENMASK(2, 0)
+
+#define BATTERY_CHARGER_STATUS_2 0x07
+#define INPUT_CURRENT_LIMITED_BIT BIT(7)
+#define CHARGER_ERROR_STATUS_SFT_EXPIRE_BIT BIT(6)
+#define CHARGER_ERROR_STATUS_BAT_OV_BIT BIT(5)
+#define CHARGER_ERROR_STATUS_BAT_TERM_MISSING_BIT BIT(4)
+#define BAT_TEMP_STATUS_MASK GENMASK(3, 0)
+#define BAT_TEMP_STATUS_SOFT_LIMIT_MASK GENMASK(3, 2)
+#define BAT_TEMP_STATUS_HOT_SOFT_LIMIT_BIT BIT(3)
+#define BAT_TEMP_STATUS_COLD_SOFT_LIMIT_BIT BIT(2)
+#define BAT_TEMP_STATUS_TOO_HOT_BIT BIT(1)
+#define BAT_TEMP_STATUS_TOO_COLD_BIT BIT(0)
+
+#define BATTERY_CHARGER_STATUS_4 0x0A
+#define CHARGE_CURRENT_POST_JEITA_MASK GENMASK(7, 0)
+
+#define BATTERY_CHARGER_STATUS_7 0x0D
+#define ENABLE_TRICKLE_BIT BIT(7)
+#define ENABLE_PRE_CHARGING_BIT BIT(6)
+#define ENABLE_FAST_CHARGING_BIT BIT(5)
+#define ENABLE_FULLON_MODE_BIT BIT(4)
+#define TOO_COLD_ADC_BIT BIT(3)
+#define TOO_HOT_ADC_BIT BIT(2)
+#define HOT_SL_ADC_BIT BIT(1)
+#define COLD_SL_ADC_BIT BIT(0)
+
+#define CHARGING_ENABLE_CMD 0x42
+#define CHARGING_ENABLE_CMD_BIT BIT(0)
+
+#define CHGR_CFG2 0x51
+#define CHG_EN_SRC_BIT BIT(7)
+#define CHG_EN_POLARITY_BIT BIT(6)
+#define PRETOFAST_TRANSITION_CFG_BIT BIT(5)
+#define BAT_OV_ECC_BIT BIT(4)
+#define I_TERM_BIT BIT(3)
+#define AUTO_RECHG_BIT BIT(2)
+#define EN_ANALOG_DROP_IN_VBATT_BIT BIT(1)
+#define CHARGER_INHIBIT_BIT BIT(0)
+
+#define PRE_CHARGE_CURRENT_CFG 0x60
+#define PRE_CHARGE_CURRENT_SETTING_MASK GENMASK(5, 0)
+
+#define FAST_CHARGE_CURRENT_CFG 0x61
+#define FAST_CHARGE_CURRENT_SETTING_MASK GENMASK(7, 0)
+
+#define FLOAT_VOLTAGE_CFG 0x70
+#define FLOAT_VOLTAGE_SETTING_MASK GENMASK(7, 0)
+
+#define FG_UPDATE_CFG_2_SEL 0x7D
+#define SOC_LT_OTG_THRESH_SEL_BIT BIT(3)
+#define SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT BIT(2)
+#define VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT BIT(1)
+#define IBT_LT_CHG_TERM_THRESH_SEL_BIT BIT(0)
+
+#define JEITA_EN_CFG 0x90
+#define JEITA_EN_HARDLIMIT_BIT BIT(4)
+#define JEITA_EN_HOT_SL_FCV_BIT BIT(3)
+#define JEITA_EN_COLD_SL_FCV_BIT BIT(2)
+#define JEITA_EN_HOT_SL_CCC_BIT BIT(1)
+#define JEITA_EN_COLD_SL_CCC_BIT BIT(0)
+
+#define INT_RT_STS 0x310
+#define TYPE_C_CHANGE_RT_STS_BIT BIT(7)
+#define USBIN_ICL_CHANGE_RT_STS_BIT BIT(6)
+#define USBIN_SOURCE_CHANGE_RT_STS_BIT BIT(5)
+#define USBIN_PLUGIN_RT_STS_BIT BIT(4)
+#define USBIN_OV_RT_STS_BIT BIT(3)
+#define USBIN_UV_RT_STS_BIT BIT(2)
+#define USBIN_LT_3P6V_RT_STS_BIT BIT(1)
+#define USBIN_COLLAPSE_RT_STS_BIT BIT(0)
+
+#define OTG_CFG 0x153
+#define OTG_RESERVED_MASK GENMASK(7, 6)
+#define DIS_OTG_ON_TLIM_BIT BIT(5)
+#define QUICKSTART_OTG_FASTROLESWAP_BIT BIT(4)
+#define INCREASE_DFP_TIME_BIT BIT(3)
+#define ENABLE_OTG_IN_DEBUG_MODE_BIT BIT(2)
+#define OTG_EN_SRC_CFG_BIT BIT(1)
+#define CONCURRENT_MODE_CFG_BIT BIT(0)
+
+#define OTG_ENG_OTG_CFG 0x1C0
+#define ENG_BUCKBOOST_HALT1_8_MODE_BIT BIT(0)
+
+#define APSD_STATUS 0x307
+#define APSD_STATUS_7_BIT BIT(7)
+#define HVDCP_CHECK_TIMEOUT_BIT BIT(6)
+#define SLOW_PLUGIN_TIMEOUT_BIT BIT(5)
+#define ENUMERATION_DONE_BIT BIT(4)
+#define VADP_CHANGE_DONE_AFTER_AUTH_BIT BIT(3)
+#define QC_AUTH_DONE_STATUS_BIT BIT(2)
+#define QC_CHARGER_BIT BIT(1)
+#define APSD_DTC_STATUS_DONE_BIT BIT(0)
+
+#define APSD_RESULT_STATUS 0x308
+#define ICL_OVERRIDE_LATCH_BIT BIT(7)
+#define APSD_RESULT_STATUS_MASK GENMASK(6, 0)
+#define QC_3P0_BIT BIT(6)
+#define QC_2P0_BIT BIT(5)
+#define FLOAT_CHARGER_BIT BIT(4)
+#define DCP_CHARGER_BIT BIT(3)
+#define CDP_CHARGER_BIT BIT(2)
+#define OCP_CHARGER_BIT BIT(1)
+#define SDP_CHARGER_BIT BIT(0)
+
+#define TYPE_C_STATUS_1 0x30B
+#define UFP_TYPEC_MASK GENMASK(7, 5)
+#define UFP_TYPEC_RDSTD_BIT BIT(7)
+#define UFP_TYPEC_RD1P5_BIT BIT(6)
+#define UFP_TYPEC_RD3P0_BIT BIT(5)
+#define UFP_TYPEC_FMB_255K_BIT BIT(4)
+#define UFP_TYPEC_FMB_301K_BIT BIT(3)
+#define UFP_TYPEC_FMB_523K_BIT BIT(2)
+#define UFP_TYPEC_FMB_619K_BIT BIT(1)
+#define UFP_TYPEC_OPEN_OPEN_BIT BIT(0)
+
+#define TYPE_C_STATUS_2 0x30C
+#define DFP_RA_OPEN_BIT BIT(7)
+#define TIMER_STAGE_BIT BIT(6)
+#define EXIT_UFP_MODE_BIT BIT(5)
+#define EXIT_DFP_MODE_BIT BIT(4)
+#define DFP_TYPEC_MASK GENMASK(3, 0)
+#define DFP_RD_OPEN_BIT BIT(3)
+#define DFP_RD_RA_VCONN_BIT BIT(2)
+#define DFP_RD_RD_BIT BIT(1)
+#define DFP_RA_RA_BIT BIT(0)
+
+#define TYPE_C_STATUS_3 0x30D
+#define ENABLE_BANDGAP_BIT BIT(7)
+#define U_USB_GND_NOVBUS_BIT BIT(6)
+#define U_USB_FLOAT_NOVBUS_BIT BIT(5)
+#define U_USB_GND_BIT BIT(4)
+#define U_USB_FMB1_BIT BIT(3)
+#define U_USB_FLOAT1_BIT BIT(2)
+#define U_USB_FMB2_BIT BIT(1)
+#define U_USB_FLOAT2_BIT BIT(0)
+
+#define TYPE_C_STATUS_4 0x30E
+#define UFP_DFP_MODE_STATUS_BIT BIT(7)
+#define TYPEC_VBUS_STATUS_BIT BIT(6)
+#define TYPEC_VBUS_ERROR_STATUS_BIT BIT(5)
+#define TYPEC_DEBOUNCE_DONE_STATUS_BIT BIT(4)
+#define TYPEC_UFP_AUDIO_ADAPT_STATUS_BIT BIT(3)
+#define TYPEC_VCONN_OVERCURR_STATUS_BIT BIT(2)
+#define CC_ORIENTATION_BIT BIT(1)
+#define CC_ATTACHED_BIT BIT(0)
+
+#define TYPE_C_STATUS_5 0x30F
+#define TRY_SOURCE_FAILED_BIT BIT(6)
+#define TRY_SINK_FAILED_BIT BIT(5)
+#define TIMER_STAGE_2_BIT BIT(4)
+#define TYPEC_LEGACY_CABLE_STATUS_BIT BIT(3)
+#define TYPEC_NONCOMP_LEGACY_CABLE_STATUS_BIT BIT(2)
+#define TYPEC_TRYSOURCE_DETECT_STATUS_BIT BIT(1)
+#define TYPEC_TRYSINK_DETECT_STATUS_BIT BIT(0)
+
+#define CMD_APSD 0x341
+#define ICL_OVERRIDE_BIT BIT(1)
+#define APSD_RERUN_BIT BIT(0)
+
+#define TYPE_C_CFG 0x358
+#define APSD_START_ON_CC_BIT BIT(7)
+#define WAIT_FOR_APSD_BIT BIT(6)
+#define FACTORY_MODE_DETECTION_EN_BIT BIT(5)
+#define FACTORY_MODE_ICL_3A_4A_BIT BIT(4)
+#define FACTORY_MODE_DIS_CHGING_CFG_BIT BIT(3)
+#define SUSPEND_NON_COMPLIANT_CFG_BIT BIT(2)
+#define VCONN_OC_CFG_BIT BIT(1)
+#define TYPE_C_OR_U_USB_BIT BIT(0)
+
+#define TYPE_C_CFG_2 0x359
+#define TYPE_C_DFP_CURRSRC_MODE_BIT BIT(7)
+#define DFP_CC_1P4V_OR_1P6V_BIT BIT(6)
+#define VCONN_SOFTSTART_CFG_MASK GENMASK(5, 4)
+#define EN_TRY_SOURCE_MODE_BIT BIT(3)
+#define USB_FACTORY_MODE_ENABLE_BIT BIT(2)
+#define TYPE_C_UFP_MODE_BIT BIT(1)
+#define EN_80UA_180UA_CUR_SOURCE_BIT BIT(0)
+
+#define TYPE_C_CFG_3 0x35A
+#define TVBUS_DEBOUNCE_BIT BIT(7)
+#define TYPEC_LEGACY_CABLE_INT_EN_BIT BIT(6)
+#define TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN_B BIT(5)
+#define TYPEC_TRYSOURCE_DETECT_INT_EN_BIT BIT(4)
+#define TYPEC_TRYSINK_DETECT_INT_EN_BIT BIT(3)
+#define EN_TRYSINK_MODE_BIT BIT(2)
+#define EN_LEGACY_CABLE_DETECTION_BIT BIT(1)
+#define ALLOW_PD_DRING_UFP_TCCDB_BIT BIT(0)
+
+#define USBIN_OPTIONS_1_CFG 0x362
+#define CABLE_R_SEL_BIT BIT(7)
+#define HVDCP_AUTH_ALG_EN_CFG_BIT BIT(6)
+#define HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT BIT(5)
+#define INPUT_PRIORITY_BIT BIT(4)
+#define AUTO_SRC_DETECT_BIT BIT(3)
+#define HVDCP_EN_BIT BIT(2)
+#define VADP_INCREMENT_VOLTAGE_LIMIT_BIT BIT(1)
+#define VADP_TAPER_TIMER_EN_BIT BIT(0)
+
+#define USBIN_OPTIONS_2_CFG 0x363
+#define WIPWR_RST_EUD_CFG_BIT BIT(7)
+#define SWITCHER_START_CFG_BIT BIT(6)
+#define DCD_TIMEOUT_SEL_BIT BIT(5)
+#define OCD_CURRENT_SEL_BIT BIT(4)
+#define SLOW_PLUGIN_TIMER_EN_CFG_BIT BIT(3)
+#define FLOAT_OPTIONS_MASK GENMASK(2, 0)
+#define FLOAT_DIS_CHGING_CFG_BIT BIT(2)
+#define SUSPEND_FLOAT_CFG_BIT BIT(1)
+#define FORCE_FLOAT_SDP_CFG_BIT BIT(0)
+
+#define TAPER_TIMER_SEL_CFG 0x364
+#define TYPEC_SPARE_CFG_BIT BIT(7)
+#define TYPEC_DRP_DFP_TIME_CFG_BIT BIT(5)
+#define TAPER_TIMER_SEL_MASK GENMASK(1, 0)
+
+#define USBIN_LOAD_CFG 0x365
+#define USBIN_OV_CH_LOAD_OPTION_BIT BIT(7)
+#define ICL_OVERRIDE_AFTER_APSD_BIT BIT(4)
+
+#define USBIN_ICL_OPTIONS 0x366
+#define CFG_USB3P0_SEL_BIT BIT(2)
+#define USB51_MODE_BIT BIT(1)
+#define USBIN_MODE_CHG_BIT BIT(0)
+
+#define TYPE_C_INTRPT_ENB_SOFTWARE_CTRL 0x368
+#define EXIT_SNK_BASED_ON_CC_BIT BIT(7)
+#define VCONN_EN_ORIENTATION_BIT BIT(6)
+#define TYPEC_VCONN_OVERCURR_INT_EN_BIT BIT(5)
+#define VCONN_EN_SRC_BIT BIT(4)
+#define VCONN_EN_VALUE_BIT BIT(3)
+#define TYPEC_POWER_ROLE_CMD_MASK GENMASK(2, 0)
+#define UFP_EN_CMD_BIT BIT(2)
+#define DFP_EN_CMD_BIT BIT(1)
+#define TYPEC_DISABLE_CMD_BIT BIT(0)
+
+#define USBIN_CURRENT_LIMIT_CFG 0x370
+#define USBIN_CURRENT_LIMIT_MASK GENMASK(7, 0)
+
+#define USBIN_AICL_OPTIONS_CFG 0x380
+#define SUSPEND_ON_COLLAPSE_USBIN_BIT BIT(7)
+#define USBIN_AICL_HDC_EN_BIT BIT(6)
+#define USBIN_AICL_START_AT_MAX_BIT BIT(5)
+#define USBIN_AICL_RERUN_EN_BIT BIT(4)
+#define USBIN_AICL_ADC_EN_BIT BIT(3)
+#define USBIN_AICL_EN_BIT BIT(2)
+#define USBIN_HV_COLLAPSE_RESPONSE_BIT BIT(1)
+#define USBIN_LV_COLLAPSE_RESPONSE_BIT BIT(0)
+
+#define USBIN_5V_AICL_THRESHOLD_CFG 0x381
+#define USBIN_5V_AICL_THRESHOLD_CFG_MASK GENMASK(2, 0)
+
+#define USBIN_CONT_AICL_THRESHOLD_CFG 0x384
+#define USBIN_CONT_AICL_THRESHOLD_CFG_MASK GENMASK(5, 0)
+
+#define DC_ENG_SSUPPLY_CFG2 0x4C1
+#define ENG_SSUPPLY_IVREF_OTG_SS_MASK GENMASK(2, 0)
+#define OTG_SS_SLOW 0x3
+
+#define DCIN_AICL_REF_SEL_CFG 0x481
+#define DCIN_CONT_AICL_THRESHOLD_CFG_MASK GENMASK(5, 0)
+
+#define WI_PWR_OPTIONS 0x495
+#define CHG_OK_BIT BIT(7)
+#define WIPWR_UVLO_IRQ_OPT_BIT BIT(6)
+#define BUCK_HOLDOFF_ENABLE_BIT BIT(5)
+#define CHG_OK_HW_SW_SELECT_BIT BIT(4)
+#define WIPWR_RST_ENABLE_BIT BIT(3)
+#define DCIN_WIPWR_IRQ_SELECT_BIT BIT(2)
+#define AICL_SWITCH_ENABLE_BIT BIT(1)
+#define ZIN_ICL_ENABLE_BIT BIT(0)
+
+#define ICL_STATUS 0x607
+#define INPUT_CURRENT_LIMIT_MASK GENMASK(7, 0)
+
+#define POWER_PATH_STATUS 0x60B
+#define P_PATH_INPUT_SS_DONE_BIT BIT(7)
+#define P_PATH_USBIN_SUSPEND_STS_BIT BIT(6)
+#define P_PATH_DCIN_SUSPEND_STS_BIT BIT(5)
+#define P_PATH_USE_USBIN_BIT BIT(4)
+#define P_PATH_USE_DCIN_BIT BIT(3)
+#define P_PATH_POWER_PATH_MASK GENMASK(2, 1)
+#define P_PATH_VALID_INPUT_POWER_SOURCE_STS_BIT BIT(0)
+
+#define BARK_BITE_WDOG_PET 0x643
+#define BARK_BITE_WDOG_PET_BIT BIT(0)
+
+#define WD_CFG 0x651
+#define WATCHDOG_TRIGGER_AFP_EN_BIT BIT(7)
+#define BARK_WDOG_INT_EN_BIT BIT(6)
+#define BITE_WDOG_INT_EN_BIT BIT(5)
+#define SFT_AFTER_WDOG_IRQ_MASK GENMASK(4, 3)
+#define WDOG_IRQ_SFT_BIT BIT(2)
+#define WDOG_TIMER_EN_ON_PLUGIN_BIT BIT(1)
+#define WDOG_TIMER_EN_BIT BIT(0)
+
+#define SNARL_BARK_BITE_WD_CFG 0x653
+#define BITE_WDOG_DISABLE_CHARGING_CFG_BIT BIT(7)
+#define SNARL_WDOG_TIMEOUT_MASK GENMASK(6, 4)
+#define BARK_WDOG_TIMEOUT_MASK GENMASK(3, 2)
+#define BITE_WDOG_TIMEOUT_MASK GENMASK(1, 0)
+
+#define AICL_RERUN_TIME_CFG 0x661
+#define AICL_RERUN_TIME_MASK GENMASK(1, 0)
+
+#define STAT_CFG 0x690
+#define STAT_SW_OVERRIDE_VALUE_BIT BIT(7)
+#define STAT_SW_OVERRIDE_CFG_BIT BIT(6)
+#define STAT_PARALLEL_OFF_DG_CFG_MASK GENMASK(5, 4)
+#define STAT_POLARITY_CFG_BIT BIT(3)
+#define STAT_PARALLEL_CFG_BIT BIT(2)
+#define STAT_FUNCTION_CFG_BIT BIT(1)
+#define STAT_IRQ_PULSING_EN_BIT BIT(0)
+
+#define SDP_CURRENT_UA 500000
+#define CDP_CURRENT_UA 1500000
+#define DCP_CURRENT_UA 1500000
+#define CURRENT_MAX_UA DCP_CURRENT_UA
+
+/* pmi8998 registers represent current in increments of 1/40th of an amp */
+#define CURRENT_SCALE_FACTOR 25000
+/* clang-format on */
+
+enum charger_status {
+ TRICKLE_CHARGE = 0,
+ PRE_CHARGE,
+ FAST_CHARGE,
+ FULLON_CHARGE,
+ TAPER_CHARGE,
+ TERMINATE_CHARGE,
+ INHIBIT_CHARGE,
+ DISABLE_CHARGE,
+};
+
+struct smb2_register {
+ u16 addr;
+ u8 mask;
+ u8 val;
+};
+
+/**
+ * struct smb2_chip - smb2 chip structure
+ * @dev: Device reference for power_supply
+ * @name: The platform device name
+ * @base: Base address for smb2 registers
+ * @regmap: Register map
+ * @batt_info: Battery data from DT
+ * @status_change_work: Worker to handle plug/unplug events
+ * @cable_irq: USB plugin IRQ
+ * @wakeup_enabled: If the cable IRQ will cause a wakeup
+ * @usb_in_i_chan: USB_IN current measurement channel
+ * @usb_in_v_chan: USB_IN voltage measurement channel
+ * @chg_psy: Charger power supply instance
+ */
+struct smb2_chip {
+ struct device *dev;
+ const char *name;
+ unsigned int base;
+ struct regmap *regmap;
+ struct power_supply_battery_info *batt_info;
+
+ struct delayed_work status_change_work;
+ int cable_irq;
+ bool wakeup_enabled;
+
+ struct iio_channel *usb_in_i_chan;
+ struct iio_channel *usb_in_v_chan;
+
+ struct power_supply *chg_psy;
+};
+
+static enum power_supply_property smb2_properties[] = {
+ POWER_SUPPLY_PROP_MANUFACTURER,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_USB_TYPE,
+ POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
+ POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
+};
+
+static enum power_supply_usb_type smb2_usb_types[] = {
+ POWER_SUPPLY_USB_TYPE_UNKNOWN,
+ POWER_SUPPLY_USB_TYPE_SDP,
+ POWER_SUPPLY_USB_TYPE_DCP,
+ POWER_SUPPLY_USB_TYPE_CDP,
+};
+
+static int smb2_get_prop_usb_online(struct smb2_chip *chip, int *val)
+{
+ unsigned int stat;
+ int rc;
+
+ rc = regmap_read(chip->regmap, chip->base + POWER_PATH_STATUS, &stat);
+ if (rc < 0) {
+ dev_err(chip->dev, "Couldn't read power path status: %d\n", rc);
+ return rc;
+ }
+
+ *val = (stat & P_PATH_USE_USBIN_BIT) &&
+ (stat & P_PATH_VALID_INPUT_POWER_SOURCE_STS_BIT);
+ return 0;
+}
+
+/*
+ * Qualcomm "automatic power source detection" aka APSD
+ * tells us what type of charger we're connected to.
+ */
+static int smb2_apsd_get_charger_type(struct smb2_chip *chip, int *val)
+{
+ unsigned int apsd_stat, stat;
+ int usb_online = 0;
+ int rc;
+
+ rc = smb2_get_prop_usb_online(chip, &usb_online);
+ if (!usb_online) {
+ *val = POWER_SUPPLY_USB_TYPE_UNKNOWN;
+ return rc;
+ }
+
+ rc = regmap_read(chip->regmap, chip->base + APSD_STATUS, &apsd_stat);
+ if (rc < 0) {
+ dev_err(chip->dev, "Failed to read apsd status, rc = %d", rc);
+ return rc;
+ }
+ if (!(apsd_stat & APSD_DTC_STATUS_DONE_BIT)) {
+ dev_dbg(chip->dev, "Apsd not ready");
+ return -EAGAIN;
+ }
+
+ rc = regmap_read(chip->regmap, chip->base + APSD_RESULT_STATUS, &stat);
+ if (rc < 0) {
+ dev_err(chip->dev, "Failed to read apsd result, rc = %d", rc);
+ return rc;
+ }
+
+ stat &= APSD_RESULT_STATUS_MASK;
+
+ if (stat & CDP_CHARGER_BIT)
+ *val = POWER_SUPPLY_USB_TYPE_CDP;
+ else if (stat & (DCP_CHARGER_BIT | OCP_CHARGER_BIT | FLOAT_CHARGER_BIT))
+ *val = POWER_SUPPLY_USB_TYPE_DCP;
+ else /* SDP_CHARGER_BIT (or others) */
+ *val = POWER_SUPPLY_USB_TYPE_SDP;
+
+ return 0;
+}
+
+static int smb2_get_prop_status(struct smb2_chip *chip, int *val)
+{
+ unsigned char stat[2];
+ int usb_online = 0;
+ int rc;
+
+ rc = smb2_get_prop_usb_online(chip, &usb_online);
+ if (!usb_online) {
+ *val = POWER_SUPPLY_STATUS_DISCHARGING;
+ return rc;
+ }
+
+ rc = regmap_bulk_read(chip->regmap,
+ chip->base + BATTERY_CHARGER_STATUS_1, &stat, 2);
+ if (rc < 0) {
+ dev_err(chip->dev, "Failed to read charging status ret=%d\n",
+ rc);
+ return rc;
+ }
+
+ if (stat[1] & CHARGER_ERROR_STATUS_BAT_OV_BIT) {
+ *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ return 0;
+ }
+
+ stat[0] = stat[0] & BATTERY_CHARGER_STATUS_MASK;
+
+ switch (stat[0]) {
+ case TRICKLE_CHARGE:
+ case PRE_CHARGE:
+ case FAST_CHARGE:
+ case FULLON_CHARGE:
+ case TAPER_CHARGE:
+ *val = POWER_SUPPLY_STATUS_CHARGING;
+ return rc;
+ case DISABLE_CHARGE:
+ *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ return rc;
+ case TERMINATE_CHARGE:
+ *val = POWER_SUPPLY_STATUS_FULL;
+ return rc;
+ case INHIBIT_CHARGE:
+ default:
+ *val = POWER_SUPPLY_STATUS_UNKNOWN;
+ return rc;
+ }
+}
+
+static inline int smb2_get_current_limit(struct smb2_chip *chip,
+ unsigned int *val)
+{
+ int rc = regmap_read(chip->regmap, chip->base + ICL_STATUS, val);
+
+ if (rc >= 0)
+ *val *= CURRENT_SCALE_FACTOR;
+ return rc;
+}
+
+static int smb2_set_current_limit(struct smb2_chip *chip, unsigned int val)
+{
+ unsigned char val_raw;
+
+ if (val > 4800000) {
+ dev_err(chip->dev,
+ "Can't set current limit higher than 4800000uA");
+ return -EINVAL;
+ }
+ val_raw = val / CURRENT_SCALE_FACTOR;
+
+ return regmap_write(chip->regmap, chip->base + USBIN_CURRENT_LIMIT_CFG,
+ val_raw);
+}
+
+static void smb2_status_change_work(struct work_struct *work)
+{
+ unsigned int charger_type, current_ua;
+ int usb_online, count, rc;
+ struct smb2_chip *chip;
+
+ chip = container_of(work, struct smb2_chip, status_change_work.work);
+
+ smb2_get_prop_usb_online(chip, &usb_online);
+ if (!usb_online)
+ return;
+
+ for (count = 0; count < 3; count++) {
+ dev_dbg(chip->dev, "get charger type retry %d\n", count);
+ rc = smb2_apsd_get_charger_type(chip, &charger_type);
+ if (rc != -EAGAIN)
+ break;
+ msleep(100);
+ }
+
+ if (rc < 0 && rc != -EAGAIN) {
+ dev_err(chip->dev, "get charger type failed: %d\n", rc);
+ return;
+ }
+
+ if (rc < 0) {
+ rc = regmap_update_bits(chip->regmap, chip->base + CMD_APSD,
+ APSD_RERUN_BIT, APSD_RERUN_BIT);
+ schedule_delayed_work(&chip->status_change_work,
+ msecs_to_jiffies(1000));
+ dev_dbg(chip->dev, "get charger type failed, rerun apsd\n");
+ return;
+ }
+
+ switch (charger_type) {
+ case POWER_SUPPLY_USB_TYPE_CDP:
+ current_ua = CDP_CURRENT_UA;
+ break;
+ case POWER_SUPPLY_USB_TYPE_DCP:
+ current_ua = DCP_CURRENT_UA;
+ break;
+ case POWER_SUPPLY_USB_TYPE_SDP:
+ default:
+ current_ua = SDP_CURRENT_UA;
+ break;
+ }
+
+ smb2_set_current_limit(chip, current_ua);
+ power_supply_changed(chip->chg_psy);
+}
+
+static int smb2_get_iio_chan(struct smb2_chip *chip, struct iio_channel *chan,
+ int *val)
+{
+ int rc;
+ union power_supply_propval status;
+
+ rc = power_supply_get_property(chip->chg_psy, POWER_SUPPLY_PROP_STATUS,
+ &status);
+ if (rc < 0 || status.intval != POWER_SUPPLY_STATUS_CHARGING) {
+ *val = 0;
+ return 0;
+ }
+
+ if (IS_ERR(chan)) {
+ dev_err(chip->dev, "Failed to chan, err = %li", PTR_ERR(chan));
+ return PTR_ERR(chan);
+ }
+
+ return iio_read_channel_processed(chan, val);
+}
+
+static int smb2_get_prop_health(struct smb2_chip *chip, int *val)
+{
+ int rc;
+ unsigned int stat;
+
+ rc = regmap_read(chip->regmap, chip->base + BATTERY_CHARGER_STATUS_2,
+ &stat);
+ if (rc < 0) {
+ dev_err(chip->dev, "Couldn't read charger status rc=%d\n", rc);
+ return rc;
+ }
+
+ switch (stat) {
+ case CHARGER_ERROR_STATUS_BAT_OV_BIT:
+ *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ return 0;
+ case BAT_TEMP_STATUS_TOO_COLD_BIT:
+ *val = POWER_SUPPLY_HEALTH_COLD;
+ return 0;
+ case BAT_TEMP_STATUS_TOO_HOT_BIT:
+ *val = POWER_SUPPLY_HEALTH_OVERHEAT;
+ return 0;
+ case BAT_TEMP_STATUS_COLD_SOFT_LIMIT_BIT:
+ *val = POWER_SUPPLY_HEALTH_COOL;
+ return 0;
+ case BAT_TEMP_STATUS_HOT_SOFT_LIMIT_BIT:
+ *val = POWER_SUPPLY_HEALTH_WARM;
+ return 0;
+ default:
+ *val = POWER_SUPPLY_HEALTH_GOOD;
+ return 0;
+ }
+}
+
+static int smb2_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct smb2_chip *chip = power_supply_get_drvdata(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = "Qualcomm";
+ return 0;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = chip->name;
+ return 0;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ return smb2_get_current_limit(chip, &val->intval);
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
+ val->intval = DCP_CURRENT_UA;
+ return 0;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ return smb2_get_iio_chan(chip, chip->usb_in_i_chan,
+ &val->intval);
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ return smb2_get_iio_chan(chip, chip->usb_in_v_chan,
+ &val->intval);
+ case POWER_SUPPLY_PROP_ONLINE:
+ return smb2_get_prop_usb_online(chip, &val->intval);
+ case POWER_SUPPLY_PROP_STATUS:
+ return smb2_get_prop_status(chip, &val->intval);
+ case POWER_SUPPLY_PROP_HEALTH:
+ return smb2_get_prop_health(chip, &val->intval);
+ case POWER_SUPPLY_PROP_USB_TYPE:
+ return smb2_apsd_get_charger_type(chip, &val->intval);
+ default:
+ dev_err(chip->dev, "invalid property: %d\n", psp);
+ return -EINVAL;
+ }
+}
+
+static int smb2_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct smb2_chip *chip = power_supply_get_drvdata(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ return smb2_set_current_limit(chip, val->intval);
+ default:
+ dev_err(chip->dev, "No setter for property: %d\n", psp);
+ return -EINVAL;
+ }
+}
+
+static int smb2_property_is_writable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static irqreturn_t smb2_handle_batt_overvoltage(int irq, void *data)
+{
+ struct smb2_chip *chip = data;
+ unsigned int status;
+
+ regmap_read(chip->regmap, chip->base + BATTERY_CHARGER_STATUS_2,
+ &status);
+
+ if (status & CHARGER_ERROR_STATUS_BAT_OV_BIT) {
+ /* The hardware stops charging automatically */
+ dev_err(chip->dev, "battery overvoltage detected\n");
+ power_supply_changed(chip->chg_psy);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t smb2_handle_usb_plugin(int irq, void *data)
+{
+ struct smb2_chip *chip = data;
+
+ power_supply_changed(chip->chg_psy);
+
+ schedule_delayed_work(&chip->status_change_work,
+ msecs_to_jiffies(1500));
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t smb2_handle_usb_icl_change(int irq, void *data)
+{
+ struct smb2_chip *chip = data;
+
+ power_supply_changed(chip->chg_psy);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t smb2_handle_wdog_bark(int irq, void *data)
+{
+ struct smb2_chip *chip = data;
+ int rc;
+
+ power_supply_changed(chip->chg_psy);
+
+ rc = regmap_write(chip->regmap, BARK_BITE_WDOG_PET,
+ BARK_BITE_WDOG_PET_BIT);
+ if (rc < 0)
+ dev_err(chip->dev, "Couldn't pet the dog rc=%d\n", rc);
+
+ return IRQ_HANDLED;
+}
+
+static const struct power_supply_desc smb2_psy_desc = {
+ .name = "pmi8998_charger",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .usb_types = smb2_usb_types,
+ .num_usb_types = ARRAY_SIZE(smb2_usb_types),
+ .properties = smb2_properties,
+ .num_properties = ARRAY_SIZE(smb2_properties),
+ .get_property = smb2_get_property,
+ .set_property = smb2_set_property,
+ .property_is_writeable = smb2_property_is_writable,
+};
+
+/* Init sequence derived from vendor downstream driver */
+static const struct smb2_register smb2_init_seq[] = {
+ { .addr = AICL_RERUN_TIME_CFG, .mask = AICL_RERUN_TIME_MASK, .val = 0 },
+ /*
+ * By default configure us as an upstream facing port
+ * FIXME: This will be handled by the type-c driver
+ */
+ { .addr = TYPE_C_INTRPT_ENB_SOFTWARE_CTRL,
+ .mask = TYPEC_POWER_ROLE_CMD_MASK | VCONN_EN_SRC_BIT |
+ VCONN_EN_VALUE_BIT,
+ .val = VCONN_EN_SRC_BIT },
+ /*
+ * Disable Type-C factory mode and stay in Attached.SRC state when VCONN
+ * over-current happens
+ */
+ { .addr = TYPE_C_CFG,
+ .mask = FACTORY_MODE_DETECTION_EN_BIT | VCONN_OC_CFG_BIT,
+ .val = 0 },
+ /* Configure VBUS for software control */
+ { .addr = OTG_CFG, .mask = OTG_EN_SRC_CFG_BIT, .val = 0 },
+ /*
+ * Use VBAT to determine the recharge threshold when battery is full
+ * rather than the state of charge.
+ */
+ { .addr = FG_UPDATE_CFG_2_SEL,
+ .mask = SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT |
+ VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT,
+ .val = VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT },
+ /* Enable charging */
+ { .addr = USBIN_OPTIONS_1_CFG, .mask = HVDCP_EN_BIT, .val = 0 },
+ { .addr = CHARGING_ENABLE_CMD,
+ .mask = CHARGING_ENABLE_CMD_BIT,
+ .val = CHARGING_ENABLE_CMD_BIT },
+ /*
+ * Match downstream defaults
+ * CHG_EN_SRC_BIT - charger enable is controlled by software
+ * CHG_EN_POLARITY_BIT - polarity of charge enable pin when in HW control
+ * pulled low on OnePlus 6 and SHIFT6mq
+ * PRETOFAST_TRANSITION_CFG_BIT -
+ * BAT_OV_ECC_BIT -
+ * I_TERM_BIT - Current termination ?? 0 = enabled
+ * AUTO_RECHG_BIT - Enable automatic recharge when battery is full
+ * 0 = enabled
+ * EN_ANALOG_DROP_IN_VBATT_BIT
+ * CHARGER_INHIBIT_BIT - Inhibit charging based on battery voltage
+ * instead of ??
+ */
+ { .addr = CHGR_CFG2,
+ .mask = CHG_EN_SRC_BIT | CHG_EN_POLARITY_BIT |
+ PRETOFAST_TRANSITION_CFG_BIT | BAT_OV_ECC_BIT | I_TERM_BIT |
+ AUTO_RECHG_BIT | EN_ANALOG_DROP_IN_VBATT_BIT |
+ CHARGER_INHIBIT_BIT,
+ .val = CHARGER_INHIBIT_BIT },
+ /* STAT pin software override, match downstream. Parallell charging? */
+ { .addr = STAT_CFG,
+ .mask = STAT_SW_OVERRIDE_CFG_BIT,
+ .val = STAT_SW_OVERRIDE_CFG_BIT },
+ /* Set the default SDP charger type to a 500ma USB 2.0 port */
+ { .addr = USBIN_ICL_OPTIONS,
+ .mask = USB51_MODE_BIT | USBIN_MODE_CHG_BIT,
+ .val = USB51_MODE_BIT },
+ /* Disable watchdog */
+ { .addr = SNARL_BARK_BITE_WD_CFG, .mask = 0xff, .val = 0 },
+ { .addr = WD_CFG,
+ .mask = WATCHDOG_TRIGGER_AFP_EN_BIT | WDOG_TIMER_EN_ON_PLUGIN_BIT |
+ BARK_WDOG_INT_EN_BIT,
+ .val = 0 },
+ /* These bits aren't documented anywhere */
+ { .addr = USBIN_5V_AICL_THRESHOLD_CFG,
+ .mask = USBIN_5V_AICL_THRESHOLD_CFG_MASK,
+ .val = 0x3 },
+ { .addr = USBIN_CONT_AICL_THRESHOLD_CFG,
+ .mask = USBIN_CONT_AICL_THRESHOLD_CFG_MASK,
+ .val = 0x3 },
+ /*
+ * Enable Automatic Input Current Limit, this will slowly ramp up the current
+ * When connected to a wall charger, and automatically stop when it detects
+ * the charger current limit (voltage drop?) or it reaches the programmed limit.
+ */
+ { .addr = USBIN_AICL_OPTIONS_CFG,
+ .mask = USBIN_AICL_START_AT_MAX_BIT | USBIN_AICL_ADC_EN_BIT |
+ USBIN_AICL_EN_BIT | SUSPEND_ON_COLLAPSE_USBIN_BIT |
+ USBIN_HV_COLLAPSE_RESPONSE_BIT |
+ USBIN_LV_COLLAPSE_RESPONSE_BIT,
+ .val = USBIN_HV_COLLAPSE_RESPONSE_BIT |
+ USBIN_LV_COLLAPSE_RESPONSE_BIT | USBIN_AICL_EN_BIT },
+ /*
+ * Set pre charge current to default, the OnePlus 6 bootloader
+ * sets this very conservatively.
+ */
+ { .addr = PRE_CHARGE_CURRENT_CFG,
+ .mask = PRE_CHARGE_CURRENT_SETTING_MASK,
+ .val = 500000 / CURRENT_SCALE_FACTOR },
+ /*
+ * This overrides all of the current limit options exposed to userspace
+ * and prevents the device from pulling more than ~1A. This is done
+ * to minimise potential fire hazard risks.
+ */
+ { .addr = FAST_CHARGE_CURRENT_CFG,
+ .mask = FAST_CHARGE_CURRENT_SETTING_MASK,
+ .val = 1000000 / CURRENT_SCALE_FACTOR },
+};
+
+static int smb2_init_hw(struct smb2_chip *chip)
+{
+ int rc, i;
+
+ for (i = 0; i < ARRAY_SIZE(smb2_init_seq); i++) {
+ dev_dbg(chip->dev, "%d: Writing 0x%02x to 0x%02x\n", i,
+ smb2_init_seq[i].val, smb2_init_seq[i].addr);
+ rc = regmap_update_bits(chip->regmap,
+ chip->base + smb2_init_seq[i].addr,
+ smb2_init_seq[i].mask,
+ smb2_init_seq[i].val);
+ if (rc < 0)
+ return dev_err_probe(chip->dev, rc,
+ "%s: init command %d failed\n",
+ __func__, i);
+ }
+
+ return 0;
+}
+
+static int smb2_init_irq(struct smb2_chip *chip, int *irq, const char *name,
+ irqreturn_t (*handler)(int irq, void *data))
+{
+ int irqnum;
+ int rc;
+
+ irqnum = platform_get_irq_byname(to_platform_device(chip->dev), name);
+ if (irqnum < 0)
+ return dev_err_probe(chip->dev, irqnum,
+ "Couldn't get irq %s byname\n", name);
+
+ rc = devm_request_threaded_irq(chip->dev, irqnum, NULL, handler,
+ IRQF_ONESHOT, name, chip);
+ if (rc < 0)
+ return dev_err_probe(chip->dev, rc, "Couldn't request irq %s\n",
+ name);
+
+ if (irq)
+ *irq = irqnum;
+
+ return 0;
+}
+
+static int smb2_probe(struct platform_device *pdev)
+{
+ struct power_supply_config supply_config = {};
+ struct power_supply_desc *desc;
+ struct smb2_chip *chip;
+ int rc, irq;
+
+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->dev = &pdev->dev;
+ chip->name = pdev->name;
+
+ chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!chip->regmap)
+ return dev_err_probe(chip->dev, -ENODEV,
+ "failed to locate the regmap\n");
+
+ rc = device_property_read_u32(chip->dev, "reg", &chip->base);
+ if (rc < 0)
+ return dev_err_probe(chip->dev, rc,
+ "Couldn't read base address\n");
+
+ chip->usb_in_v_chan = devm_iio_channel_get(chip->dev, "usbin_v");
+ if (IS_ERR(chip->usb_in_v_chan))
+ return dev_err_probe(chip->dev, PTR_ERR(chip->usb_in_v_chan),
+ "Couldn't get usbin_v IIO channel\n");
+
+ chip->usb_in_i_chan = devm_iio_channel_get(chip->dev, "usbin_i");
+ if (IS_ERR(chip->usb_in_i_chan)) {
+ return dev_err_probe(chip->dev, PTR_ERR(chip->usb_in_i_chan),
+ "Couldn't get usbin_i IIO channel\n");
+ }
+
+ rc = smb2_init_hw(chip);
+ if (rc < 0)
+ return rc;
+
+ supply_config.drv_data = chip;
+ supply_config.of_node = pdev->dev.of_node;
+
+ desc = devm_kzalloc(chip->dev, sizeof(smb2_psy_desc), GFP_KERNEL);
+ memcpy(desc, &smb2_psy_desc, sizeof(smb2_psy_desc));
+ desc->name =
+ devm_kasprintf(chip->dev, GFP_KERNEL, "%s-charger",
+ (const char *)device_get_match_data(chip->dev));
+
+ chip->chg_psy =
+ devm_power_supply_register(chip->dev, desc, &supply_config);
+ if (IS_ERR(chip->chg_psy))
+ return dev_err_probe(chip->dev, PTR_ERR(chip->chg_psy),
+ "failed to register power supply\n");
+
+ rc = power_supply_get_battery_info(chip->chg_psy, &chip->batt_info);
+ if (rc)
+ return dev_err_probe(chip->dev, rc,
+ "Failed to get battery info\n");
+
+ rc = devm_delayed_work_autocancel(chip->dev, &chip->status_change_work,
+ smb2_status_change_work);
+ if (rc)
+ return dev_err_probe(chip->dev, rc,
+ "Failed to init status change work\n");
+
+ rc = (chip->batt_info->voltage_max_design_uv - 3487500) / 7500 + 1;
+ rc = regmap_update_bits(chip->regmap, chip->base + FLOAT_VOLTAGE_CFG,
+ FLOAT_VOLTAGE_SETTING_MASK, rc);
+ if (rc < 0)
+ return dev_err_probe(chip->dev, rc, "Couldn't set vbat max\n");
+
+ rc = smb2_init_irq(chip, &irq, "bat-ov", smb2_handle_batt_overvoltage);
+ if (rc < 0)
+ return rc;
+
+ rc = smb2_init_irq(chip, &chip->cable_irq, "usb-plugin",
+ smb2_handle_usb_plugin);
+ if (rc < 0)
+ return rc;
+
+ rc = smb2_init_irq(chip, &irq, "usbin-icl-change",
+ smb2_handle_usb_icl_change);
+ if (rc < 0)
+ return rc;
+ rc = smb2_init_irq(chip, &irq, "wdog-bark", smb2_handle_wdog_bark);
+ if (rc < 0)
+ return rc;
+
+ rc = dev_pm_set_wake_irq(chip->dev, chip->cable_irq);
+ if (rc < 0)
+ return dev_err_probe(chip->dev, rc, "Couldn't set wake irq\n");
+
+ platform_set_drvdata(pdev, chip);
+
+ /* Initialise charger state */
+ schedule_delayed_work(&chip->status_change_work, 0);
+
+ return 0;
+}
+
+static const struct of_device_id smb2_match_id_table[] = {
+ { .compatible = "qcom,pmi8998-charger", .data = "pmi8998" },
+ { .compatible = "qcom,pm660-charger", .data = "pm660" },
+ { /* sentinal */ }
+};
+MODULE_DEVICE_TABLE(of, smb2_match_id_table);
+
+static struct platform_driver qcom_spmi_smb2 = {
+ .probe = smb2_probe,
+ .driver = {
+ .name = "qcom-pmi8998/pm660-charger",
+ .of_match_table = smb2_match_id_table,
+ },
+};
+
+module_platform_driver(qcom_spmi_smb2);
+
+MODULE_AUTHOR("Caleb Connolly <caleb.connolly@linaro.org>");
+MODULE_DESCRIPTION("Qualcomm SMB2 Charger Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/supply/rk817_charger.c b/drivers/power/supply/rk817_charger.c
index 1a2143641e66..8328bcea1a29 100644
--- a/drivers/power/supply/rk817_charger.c
+++ b/drivers/power/supply/rk817_charger.c
@@ -1134,7 +1134,7 @@ static int rk817_charger_probe(struct platform_device *pdev)
&bat_info);
if (ret) {
return dev_err_probe(dev, ret,
- "Unable to get battery info: %d\n", ret);
+ "Unable to get battery info\n");
}
if ((bat_info->charge_full_design_uah <= 0) ||
diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c
index 5c04cf305219..d90b96df8e73 100644
--- a/drivers/power/supply/rt5033_battery.c
+++ b/drivers/power/supply/rt5033_battery.c
@@ -6,11 +6,33 @@
* Author: Beomho Seo <beomho.seo@samsung.com>
*/
+#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
+#include <linux/regmap.h>
#include <linux/mfd/rt5033-private.h>
-#include <linux/mfd/rt5033.h>
+
+struct rt5033_battery {
+ struct i2c_client *client;
+ struct regmap *regmap;
+ struct power_supply *psy;
+};
+
+static int rt5033_battery_get_status(struct i2c_client *client)
+{
+ struct rt5033_battery *battery = i2c_get_clientdata(client);
+ union power_supply_propval val;
+ int ret;
+
+ ret = power_supply_get_property_from_supplier(battery->psy,
+ POWER_SUPPLY_PROP_STATUS,
+ &val);
+ if (ret)
+ val.intval = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ return val.intval;
+}
static int rt5033_battery_get_capacity(struct i2c_client *client)
{
@@ -84,6 +106,9 @@ static int rt5033_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = rt5033_battery_get_capacity(battery->client);
break;
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = rt5033_battery_get_status(battery->client);
+ break;
default:
return -EINVAL;
}
@@ -96,6 +121,7 @@ static enum power_supply_property rt5033_battery_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_OCV,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_STATUS,
};
static const struct regmap_config rt5033_battery_regmap_config = {
@@ -117,7 +143,6 @@ static int rt5033_battery_probe(struct i2c_client *client)
struct i2c_adapter *adapter = client->adapter;
struct power_supply_config psy_cfg = {};
struct rt5033_battery *battery;
- u32 ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
return -EIO;
@@ -135,15 +160,14 @@ static int rt5033_battery_probe(struct i2c_client *client)
}
i2c_set_clientdata(client, battery);
+ psy_cfg.of_node = client->dev.of_node;
psy_cfg.drv_data = battery;
battery->psy = power_supply_register(&client->dev,
&rt5033_battery_desc, &psy_cfg);
- if (IS_ERR(battery->psy)) {
- dev_err(&client->dev, "Failed to register power supply\n");
- ret = PTR_ERR(battery->psy);
- return ret;
- }
+ if (IS_ERR(battery->psy))
+ return dev_err_probe(&client->dev, PTR_ERR(battery->psy),
+ "Failed to register power supply\n");
return 0;
}
@@ -172,7 +196,7 @@ static struct i2c_driver rt5033_battery_driver = {
.name = "rt5033-battery",
.of_match_table = rt5033_battery_of_match,
},
- .probe_new = rt5033_battery_probe,
+ .probe = rt5033_battery_probe,
.remove = rt5033_battery_remove,
.id_table = rt5033_battery_id,
};
diff --git a/drivers/power/supply/rt5033_charger.c b/drivers/power/supply/rt5033_charger.c
new file mode 100644
index 000000000000..5218dfbf5e1b
--- /dev/null
+++ b/drivers/power/supply/rt5033_charger.c
@@ -0,0 +1,472 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Battery charger driver for RT5033
+ *
+ * Copyright (C) 2014 Samsung Electronics, Co., Ltd.
+ * Author: Beomho Seo <beomho.seo@samsung.com>
+ */
+
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/mfd/rt5033-private.h>
+
+struct rt5033_charger_data {
+ unsigned int pre_uamp;
+ unsigned int pre_uvolt;
+ unsigned int const_uvolt;
+ unsigned int eoc_uamp;
+ unsigned int fast_uamp;
+};
+
+struct rt5033_charger {
+ struct device *dev;
+ struct regmap *regmap;
+ struct power_supply *psy;
+ struct rt5033_charger_data *chg;
+};
+
+static int rt5033_get_charger_state(struct rt5033_charger *charger)
+{
+ struct regmap *regmap = charger->regmap;
+ unsigned int reg_data;
+ int state;
+
+ if (!regmap)
+ return POWER_SUPPLY_STATUS_UNKNOWN;
+
+ regmap_read(regmap, RT5033_REG_CHG_STAT, &reg_data);
+
+ switch (reg_data & RT5033_CHG_STAT_MASK) {
+ case RT5033_CHG_STAT_DISCHARGING:
+ state = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ case RT5033_CHG_STAT_CHARGING:
+ state = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ case RT5033_CHG_STAT_FULL:
+ state = POWER_SUPPLY_STATUS_FULL;
+ break;
+ case RT5033_CHG_STAT_NOT_CHARGING:
+ state = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ break;
+ default:
+ state = POWER_SUPPLY_STATUS_UNKNOWN;
+ }
+
+ return state;
+}
+
+static int rt5033_get_charger_type(struct rt5033_charger *charger)
+{
+ struct regmap *regmap = charger->regmap;
+ unsigned int reg_data;
+ int state;
+
+ regmap_read(regmap, RT5033_REG_CHG_STAT, &reg_data);
+
+ switch (reg_data & RT5033_CHG_STAT_TYPE_MASK) {
+ case RT5033_CHG_STAT_TYPE_FAST:
+ state = POWER_SUPPLY_CHARGE_TYPE_FAST;
+ break;
+ case RT5033_CHG_STAT_TYPE_PRE:
+ state = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+ break;
+ default:
+ state = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ }
+
+ return state;
+}
+
+static int rt5033_get_charger_current_limit(struct rt5033_charger *charger)
+{
+ struct regmap *regmap = charger->regmap;
+ unsigned int state, reg_data, data;
+
+ regmap_read(regmap, RT5033_REG_CHG_CTRL5, &reg_data);
+
+ state = (reg_data & RT5033_CHGCTRL5_ICHG_MASK)
+ >> RT5033_CHGCTRL5_ICHG_SHIFT;
+
+ data = RT5033_CHARGER_FAST_CURRENT_MIN +
+ RT5033_CHARGER_FAST_CURRENT_STEP_NUM * state;
+
+ return data;
+}
+
+static int rt5033_get_charger_const_voltage(struct rt5033_charger *charger)
+{
+ struct regmap *regmap = charger->regmap;
+ unsigned int state, reg_data, data;
+
+ regmap_read(regmap, RT5033_REG_CHG_CTRL2, &reg_data);
+
+ state = (reg_data & RT5033_CHGCTRL2_CV_MASK)
+ >> RT5033_CHGCTRL2_CV_SHIFT;
+
+ data = RT5033_CHARGER_CONST_VOLTAGE_LIMIT_MIN +
+ RT5033_CHARGER_CONST_VOLTAGE_STEP_NUM * state;
+
+ return data;
+}
+
+static inline int rt5033_init_const_charge(struct rt5033_charger *charger)
+{
+ struct rt5033_charger_data *chg = charger->chg;
+ int ret;
+ unsigned int val;
+ u8 reg_data;
+
+ /* Set constant voltage mode */
+ if (chg->const_uvolt < RT5033_CHARGER_CONST_VOLTAGE_LIMIT_MIN ||
+ chg->const_uvolt > RT5033_CHARGER_CONST_VOLTAGE_LIMIT_MAX) {
+ dev_err(charger->dev,
+ "Value 'constant-charge-voltage-max-microvolt' out of range\n");
+ return -EINVAL;
+ }
+
+ if (chg->const_uvolt == RT5033_CHARGER_CONST_VOLTAGE_LIMIT_MIN)
+ reg_data = 0x00;
+ else if (chg->const_uvolt == RT5033_CHARGER_CONST_VOLTAGE_LIMIT_MAX)
+ reg_data = RT5033_CV_MAX_VOLTAGE;
+ else {
+ val = chg->const_uvolt;
+ val -= RT5033_CHARGER_CONST_VOLTAGE_LIMIT_MIN;
+ val /= RT5033_CHARGER_CONST_VOLTAGE_STEP_NUM;
+ reg_data = val;
+ }
+
+ ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL2,
+ RT5033_CHGCTRL2_CV_MASK,
+ reg_data << RT5033_CHGCTRL2_CV_SHIFT);
+ if (ret) {
+ dev_err(charger->dev, "Failed regmap update\n");
+ return -EINVAL;
+ }
+
+ /* Set end of charge current */
+ if (chg->eoc_uamp < RT5033_CHARGER_EOC_MIN ||
+ chg->eoc_uamp > RT5033_CHARGER_EOC_MAX) {
+ dev_err(charger->dev,
+ "Value 'charge-term-current-microamp' out of range\n");
+ return -EINVAL;
+ }
+
+ if (chg->eoc_uamp == RT5033_CHARGER_EOC_MIN)
+ reg_data = 0x01;
+ else if (chg->eoc_uamp == RT5033_CHARGER_EOC_MAX)
+ reg_data = 0x07;
+ else {
+ val = chg->eoc_uamp;
+ if (val < RT5033_CHARGER_EOC_REF) {
+ val -= RT5033_CHARGER_EOC_MIN;
+ val /= RT5033_CHARGER_EOC_STEP_NUM1;
+ reg_data = 0x01 + val;
+ } else if (val > RT5033_CHARGER_EOC_REF) {
+ val -= RT5033_CHARGER_EOC_REF;
+ val /= RT5033_CHARGER_EOC_STEP_NUM2;
+ reg_data = 0x04 + val;
+ } else {
+ reg_data = 0x04;
+ }
+ }
+
+ ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL4,
+ RT5033_CHGCTRL4_EOC_MASK, reg_data);
+ if (ret) {
+ dev_err(charger->dev, "Failed regmap update\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static inline int rt5033_init_fast_charge(struct rt5033_charger *charger)
+{
+ struct rt5033_charger_data *chg = charger->chg;
+ int ret;
+ unsigned int val;
+ u8 reg_data;
+
+ /* Set limit input current */
+ ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL1,
+ RT5033_CHGCTRL1_IAICR_MASK, RT5033_AICR_2000_MODE);
+ if (ret) {
+ dev_err(charger->dev, "Failed regmap update\n");
+ return -EINVAL;
+ }
+
+ /* Set fast-charge mode charging current */
+ if (chg->fast_uamp < RT5033_CHARGER_FAST_CURRENT_MIN ||
+ chg->fast_uamp > RT5033_CHARGER_FAST_CURRENT_MAX) {
+ dev_err(charger->dev,
+ "Value 'constant-charge-current-max-microamp' out of range\n");
+ return -EINVAL;
+ }
+
+ if (chg->fast_uamp == RT5033_CHARGER_FAST_CURRENT_MIN)
+ reg_data = 0x00;
+ else if (chg->fast_uamp == RT5033_CHARGER_FAST_CURRENT_MAX)
+ reg_data = RT5033_CHG_MAX_CURRENT;
+ else {
+ val = chg->fast_uamp;
+ val -= RT5033_CHARGER_FAST_CURRENT_MIN;
+ val /= RT5033_CHARGER_FAST_CURRENT_STEP_NUM;
+ reg_data = val;
+ }
+
+ ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL5,
+ RT5033_CHGCTRL5_ICHG_MASK,
+ reg_data << RT5033_CHGCTRL5_ICHG_SHIFT);
+ if (ret) {
+ dev_err(charger->dev, "Failed regmap update\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static inline int rt5033_init_pre_charge(struct rt5033_charger *charger)
+{
+ struct rt5033_charger_data *chg = charger->chg;
+ int ret;
+ unsigned int val;
+ u8 reg_data;
+
+ /* Set pre-charge threshold voltage */
+ if (chg->pre_uvolt < RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MIN ||
+ chg->pre_uvolt > RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MAX) {
+ dev_err(charger->dev,
+ "Value 'precharge-upper-limit-microvolt' out of range\n");
+ return -EINVAL;
+ }
+
+ if (chg->pre_uvolt == RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MIN)
+ reg_data = 0x00;
+ else if (chg->pre_uvolt == RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MAX)
+ reg_data = 0x0f;
+ else {
+ val = chg->pre_uvolt;
+ val -= RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MIN;
+ val /= RT5033_CHARGER_PRE_THRESHOLD_STEP_NUM;
+ reg_data = val;
+ }
+
+ ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL5,
+ RT5033_CHGCTRL5_VPREC_MASK, reg_data);
+ if (ret) {
+ dev_err(charger->dev, "Failed regmap update\n");
+ return -EINVAL;
+ }
+
+ /* Set pre-charge mode charging current */
+ if (chg->pre_uamp < RT5033_CHARGER_PRE_CURRENT_LIMIT_MIN ||
+ chg->pre_uamp > RT5033_CHARGER_PRE_CURRENT_LIMIT_MAX) {
+ dev_err(charger->dev,
+ "Value 'precharge-current-microamp' out of range\n");
+ return -EINVAL;
+ }
+
+ if (chg->pre_uamp == RT5033_CHARGER_PRE_CURRENT_LIMIT_MIN)
+ reg_data = 0x00;
+ else if (chg->pre_uamp == RT5033_CHARGER_PRE_CURRENT_LIMIT_MAX)
+ reg_data = RT5033_CHG_MAX_PRE_CURRENT;
+ else {
+ val = chg->pre_uamp;
+ val -= RT5033_CHARGER_PRE_CURRENT_LIMIT_MIN;
+ val /= RT5033_CHARGER_PRE_CURRENT_STEP_NUM;
+ reg_data = val;
+ }
+
+ ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL4,
+ RT5033_CHGCTRL4_IPREC_MASK,
+ reg_data << RT5033_CHGCTRL4_IPREC_SHIFT);
+ if (ret) {
+ dev_err(charger->dev, "Failed regmap update\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rt5033_charger_reg_init(struct rt5033_charger *charger)
+{
+ int ret = 0;
+
+ /* Enable charging termination */
+ ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL1,
+ RT5033_CHGCTRL1_TE_EN_MASK, RT5033_TE_ENABLE);
+ if (ret) {
+ dev_err(charger->dev, "Failed to enable charging termination.\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Disable minimum input voltage regulation (MIVR), this improves
+ * the charging performance.
+ */
+ ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL4,
+ RT5033_CHGCTRL4_MIVR_MASK, RT5033_CHARGER_MIVR_DISABLE);
+ if (ret) {
+ dev_err(charger->dev, "Failed to disable MIVR.\n");
+ return -EINVAL;
+ }
+
+ ret = rt5033_init_pre_charge(charger);
+ if (ret)
+ return ret;
+
+ ret = rt5033_init_fast_charge(charger);
+ if (ret)
+ return ret;
+
+ ret = rt5033_init_const_charge(charger);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static enum power_supply_property rt5033_charger_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static int rt5033_charger_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct rt5033_charger *charger = power_supply_get_drvdata(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = rt5033_get_charger_state(charger);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ val->intval = rt5033_get_charger_type(charger);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ val->intval = rt5033_get_charger_current_limit(charger);
+ break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+ val->intval = rt5033_get_charger_const_voltage(charger);
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = RT5033_CHARGER_MODEL;
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = RT5033_MANUFACTURER;
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = (rt5033_get_charger_state(charger) ==
+ POWER_SUPPLY_STATUS_CHARGING);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct rt5033_charger_data *rt5033_charger_dt_init(
+ struct rt5033_charger *charger)
+{
+ struct rt5033_charger_data *chg;
+ struct power_supply_battery_info *info;
+ int ret;
+
+ chg = devm_kzalloc(charger->dev, sizeof(*chg), GFP_KERNEL);
+ if (!chg)
+ return ERR_PTR(-ENOMEM);
+
+ ret = power_supply_get_battery_info(charger->psy, &info);
+ if (ret)
+ return ERR_PTR(dev_err_probe(charger->dev, -EINVAL,
+ "missing battery info\n"));
+
+ /* Assign data. Validity will be checked in the init functions. */
+ chg->pre_uamp = info->precharge_current_ua;
+ chg->fast_uamp = info->constant_charge_current_max_ua;
+ chg->eoc_uamp = info->charge_term_current_ua;
+ chg->pre_uvolt = info->precharge_voltage_max_uv;
+ chg->const_uvolt = info->constant_charge_voltage_max_uv;
+
+ return chg;
+}
+
+static const struct power_supply_desc rt5033_charger_desc = {
+ .name = "rt5033-charger",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .properties = rt5033_charger_props,
+ .num_properties = ARRAY_SIZE(rt5033_charger_props),
+ .get_property = rt5033_charger_get_property,
+};
+
+static int rt5033_charger_probe(struct platform_device *pdev)
+{
+ struct rt5033_charger *charger;
+ struct power_supply_config psy_cfg = {};
+ int ret;
+
+ charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
+ if (!charger)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, charger);
+ charger->dev = &pdev->dev;
+ charger->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+
+ psy_cfg.of_node = pdev->dev.of_node;
+ psy_cfg.drv_data = charger;
+
+ charger->psy = devm_power_supply_register(&pdev->dev,
+ &rt5033_charger_desc,
+ &psy_cfg);
+ if (IS_ERR(charger->psy))
+ return dev_err_probe(&pdev->dev, PTR_ERR(charger->psy),
+ "Failed to register power supply\n");
+
+ charger->chg = rt5033_charger_dt_init(charger);
+ if (IS_ERR_OR_NULL(charger->chg))
+ return PTR_ERR(charger->chg);
+
+ ret = rt5033_charger_reg_init(charger);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct platform_device_id rt5033_charger_id[] = {
+ { "rt5033-charger", },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, rt5033_charger_id);
+
+static const struct of_device_id rt5033_charger_of_match[] = {
+ { .compatible = "richtek,rt5033-charger", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rt5033_charger_of_match);
+
+static struct platform_driver rt5033_charger_driver = {
+ .driver = {
+ .name = "rt5033-charger",
+ .of_match_table = rt5033_charger_of_match,
+ },
+ .probe = rt5033_charger_probe,
+ .id_table = rt5033_charger_id,
+};
+module_platform_driver(rt5033_charger_driver);
+
+MODULE_DESCRIPTION("Richtek RT5033 charger driver");
+MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/supply/rt9455_charger.c b/drivers/power/supply/rt9455_charger.c
index 0149e00f2bf8..ff4dcf77c788 100644
--- a/drivers/power/supply/rt9455_charger.c
+++ b/drivers/power/supply/rt9455_charger.c
@@ -1737,7 +1737,7 @@ MODULE_DEVICE_TABLE(acpi, rt9455_i2c_acpi_match);
#endif
static struct i2c_driver rt9455_driver = {
- .probe_new = rt9455_probe,
+ .probe = rt9455_probe,
.remove = rt9455_remove,
.id_table = rt9455_i2c_id_table,
.driver = {
diff --git a/drivers/power/supply/rt9467-charger.c b/drivers/power/supply/rt9467-charger.c
index ea33693b6977..683adb18253d 100644
--- a/drivers/power/supply/rt9467-charger.c
+++ b/drivers/power/supply/rt9467-charger.c
@@ -1192,7 +1192,7 @@ static int rt9467_charger_probe(struct i2c_client *i2c)
i2c_set_clientdata(i2c, data);
/* Default pull charge enable gpio to make 'CHG_EN' by SW control only */
- ceb_gpio = devm_gpiod_get_optional(dev, "charge-enable", GPIOD_OUT_LOW);
+ ceb_gpio = devm_gpiod_get_optional(dev, "charge-enable", GPIOD_OUT_HIGH);
if (IS_ERR(ceb_gpio))
return dev_err_probe(dev, PTR_ERR(ceb_gpio),
"Failed to config charge enable gpio\n");
@@ -1272,7 +1272,7 @@ static struct i2c_driver rt9467_charger_driver = {
.name = "rt9467-charger",
.of_match_table = rt9467_charger_of_match_table,
},
- .probe_new = rt9467_charger_probe,
+ .probe = rt9467_charger_probe,
};
module_i2c_driver(rt9467_charger_driver);
diff --git a/drivers/power/supply/rt9471.c b/drivers/power/supply/rt9471.c
index 1ea40876494b..868b0703d15c 100644
--- a/drivers/power/supply/rt9471.c
+++ b/drivers/power/supply/rt9471.c
@@ -919,7 +919,7 @@ static struct i2c_driver rt9471_driver = {
.name = "rt9471",
.of_match_table = rt9471_of_device_id,
},
- .probe_new = rt9471_probe,
+ .probe = rt9471_probe,
.shutdown = rt9471_shutdown,
};
module_i2c_driver(rt9471_driver);
diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c
index c4a95b01463a..62a354e01204 100644
--- a/drivers/power/supply/sbs-battery.c
+++ b/drivers/power/supply/sbs-battery.c
@@ -1275,7 +1275,7 @@ static const struct of_device_id sbs_dt_ids[] = {
MODULE_DEVICE_TABLE(of, sbs_dt_ids);
static struct i2c_driver sbs_battery_driver = {
- .probe_new = sbs_probe,
+ .probe = sbs_probe,
.alert = sbs_alert,
.id_table = sbs_id,
.driver = {
diff --git a/drivers/power/supply/sbs-charger.c b/drivers/power/supply/sbs-charger.c
index a14e89ac0369..f4adde449270 100644
--- a/drivers/power/supply/sbs-charger.c
+++ b/drivers/power/supply/sbs-charger.c
@@ -240,7 +240,7 @@ static const struct i2c_device_id sbs_id[] = {
MODULE_DEVICE_TABLE(i2c, sbs_id);
static struct i2c_driver sbs_driver = {
- .probe_new = sbs_probe,
+ .probe = sbs_probe,
.id_table = sbs_id,
.driver = {
.name = "sbs-charger",
diff --git a/drivers/power/supply/sbs-manager.c b/drivers/power/supply/sbs-manager.c
index bde977391fd4..9e4141cffbf9 100644
--- a/drivers/power/supply/sbs-manager.c
+++ b/drivers/power/supply/sbs-manager.c
@@ -409,7 +409,7 @@ static struct i2c_driver sbsm_driver = {
.name = "sbsm",
.of_match_table = of_match_ptr(sbsm_dt_ids),
},
- .probe_new = sbsm_probe,
+ .probe = sbsm_probe,
.alert = sbsm_alert,
.id_table = sbsm_ids
};
diff --git a/drivers/power/supply/smb347-charger.c b/drivers/power/supply/smb347-charger.c
index b5f038310282..c8392933ee28 100644
--- a/drivers/power/supply/smb347-charger.c
+++ b/drivers/power/supply/smb347-charger.c
@@ -1629,7 +1629,7 @@ static struct i2c_driver smb347_driver = {
.name = "smb347",
.of_match_table = smb3xx_of_match,
},
- .probe_new = smb347_probe,
+ .probe = smb347_probe,
.remove = smb347_remove,
.shutdown = smb347_shutdown,
.id_table = smb347_id,
diff --git a/drivers/power/supply/twl4030_madc_battery.c b/drivers/power/supply/twl4030_madc_battery.c
index 48649dcfe3a9..7fe029673b22 100644
--- a/drivers/power/supply/twl4030_madc_battery.c
+++ b/drivers/power/supply/twl4030_madc_battery.c
@@ -168,19 +168,13 @@ static int twl4030_madc_bat_get_property(struct power_supply *psy,
return 0;
}
-static void twl4030_madc_bat_ext_changed(struct power_supply *psy)
-{
- power_supply_changed(psy);
-}
-
static const struct power_supply_desc twl4030_madc_bat_desc = {
.name = "twl4030_battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
.properties = twl4030_madc_bat_props,
.num_properties = ARRAY_SIZE(twl4030_madc_bat_props),
.get_property = twl4030_madc_bat_get_property,
- .external_power_changed = twl4030_madc_bat_ext_changed,
-
+ .external_power_changed = power_supply_changed,
};
static int twl4030_cmp(const void *a, const void *b)
diff --git a/drivers/power/supply/ucs1002_power.c b/drivers/power/supply/ucs1002_power.c
index 836d44c9fb74..954feba6600b 100644
--- a/drivers/power/supply/ucs1002_power.c
+++ b/drivers/power/supply/ucs1002_power.c
@@ -680,7 +680,7 @@ static struct i2c_driver ucs1002_driver = {
.name = "ucs1002",
.of_match_table = ucs1002_of_match,
},
- .probe_new = ucs1002_probe,
+ .probe = ucs1002_probe,
};
module_i2c_driver(ucs1002_driver);
diff --git a/drivers/power/supply/ug3105_battery.c b/drivers/power/supply/ug3105_battery.c
index fbc966842509..ccc5c4d2e230 100644
--- a/drivers/power/supply/ug3105_battery.c
+++ b/drivers/power/supply/ug3105_battery.c
@@ -476,7 +476,7 @@ static struct i2c_driver ug3105_i2c_driver = {
.name = "ug3105",
.pm = &ug3105_pm_ops,
},
- .probe_new = ug3105_probe,
+ .probe = ug3105_probe,
.id_table = ug3105_id,
};
module_i2c_driver(ug3105_i2c_driver);
diff --git a/drivers/powercap/arm_scmi_powercap.c b/drivers/powercap/arm_scmi_powercap.c
index 05d0e516176a..5231f6d52ae3 100644
--- a/drivers/powercap/arm_scmi_powercap.c
+++ b/drivers/powercap/arm_scmi_powercap.c
@@ -70,10 +70,26 @@ static int scmi_powercap_get_power_uw(struct powercap_zone *pz,
return 0;
}
+static int scmi_powercap_zone_enable_set(struct powercap_zone *pz, bool mode)
+{
+ struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
+
+ return powercap_ops->cap_enable_set(spz->ph, spz->info->id, mode);
+}
+
+static int scmi_powercap_zone_enable_get(struct powercap_zone *pz, bool *mode)
+{
+ struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
+
+ return powercap_ops->cap_enable_get(spz->ph, spz->info->id, mode);
+}
+
static const struct powercap_zone_ops zone_ops = {
.get_max_power_range_uw = scmi_powercap_get_max_power_range_uw,
.get_power_uw = scmi_powercap_get_power_uw,
.release = scmi_powercap_zone_release,
+ .set_enable = scmi_powercap_zone_enable_set,
+ .get_enable = scmi_powercap_zone_enable_get,
};
static void scmi_powercap_normalize_cap(const struct scmi_powercap_zone *spz,
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 8df861b1f4a3..6210babb0741 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -405,6 +405,16 @@ config PWM_MEDIATEK
To compile this driver as a module, choose M here: the module
will be called pwm-mediatek.
+config PWM_MICROCHIP_CORE
+ tristate "Microchip corePWM PWM support"
+ depends on SOC_MICROCHIP_POLARFIRE || COMPILE_TEST
+ depends on HAS_IOMEM && OF
+ help
+ PWM driver for Microchip FPGA soft IP core.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-microchip-core.
+
config PWM_MXS
tristate "Freescale MXS PWM support"
depends on ARCH_MXS || COMPILE_TEST
@@ -493,6 +503,17 @@ config PWM_ROCKCHIP
Generic PWM framework driver for the PWM controller found on
Rockchip SoCs.
+config PWM_RZ_MTU3
+ tristate "Renesas RZ/G2L MTU3a PWM Timer support"
+ depends on RZ_MTU3 || COMPILE_TEST
+ depends on HAS_IOMEM
+ help
+ This driver exposes the MTU3a PWM Timer controller found in Renesas
+ RZ/G2L like chips through the PWM API.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-rz-mtu3.
+
config PWM_SAMSUNG
tristate "Samsung PWM support"
depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 19899b912e00..c822389c2a24 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-pci.o
obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o
obj-$(CONFIG_PWM_MESON) += pwm-meson.o
obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o
+obj-$(CONFIG_PWM_MICROCHIP_CORE) += pwm-microchip-core.o
obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o
obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
obj-$(CONFIG_PWM_NTXEC) += pwm-ntxec.o
@@ -45,6 +46,7 @@ obj-$(CONFIG_PWM_RASPBERRYPI_POE) += pwm-raspberrypi-poe.o
obj-$(CONFIG_PWM_RCAR) += pwm-rcar.o
obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o
obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o
+obj-$(CONFIG_PWM_RZ_MTU3) += pwm-rz-mtu3.o
obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o
obj-$(CONFIG_PWM_SL28CPLD) += pwm-sl28cpld.o
diff --git a/drivers/pwm/pwm-ab8500.c b/drivers/pwm/pwm-ab8500.c
index 507ff0d5f7bd..583a7d69c741 100644
--- a/drivers/pwm/pwm-ab8500.c
+++ b/drivers/pwm/pwm-ab8500.c
@@ -190,7 +190,7 @@ static int ab8500_pwm_probe(struct platform_device *pdev)
int err;
if (pdev->id < 1 || pdev->id > 31)
- return dev_err_probe(&pdev->dev, EINVAL, "Invalid device id %d\n", pdev->id);
+ return dev_err_probe(&pdev->dev, -EINVAL, "Invalid device id %d\n", pdev->id);
/*
* Nothing to be done in probe, this is required to get the
diff --git a/drivers/pwm/pwm-clk.c b/drivers/pwm/pwm-clk.c
index f1da99881adf..0ee4d2aee4df 100644
--- a/drivers/pwm/pwm-clk.c
+++ b/drivers/pwm/pwm-clk.c
@@ -89,7 +89,7 @@ static int pwm_clk_probe(struct platform_device *pdev)
if (!pcchip)
return -ENOMEM;
- pcchip->clk = devm_clk_get(&pdev->dev, NULL);
+ pcchip->clk = devm_clk_get_prepared(&pdev->dev, NULL);
if (IS_ERR(pcchip->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(pcchip->clk),
"Failed to get clock\n");
@@ -98,15 +98,9 @@ static int pwm_clk_probe(struct platform_device *pdev)
pcchip->chip.ops = &pwm_clk_ops;
pcchip->chip.npwm = 1;
- ret = clk_prepare(pcchip->clk);
- if (ret < 0)
- return dev_err_probe(&pdev->dev, ret, "Failed to prepare clock\n");
-
ret = pwmchip_add(&pcchip->chip);
- if (ret < 0) {
- clk_unprepare(pcchip->clk);
+ if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "Failed to add pwm chip\n");
- }
platform_set_drvdata(pdev, pcchip);
return 0;
@@ -120,8 +114,6 @@ static void pwm_clk_remove(struct platform_device *pdev)
if (pcchip->clk_enabled)
clk_disable(pcchip->clk);
-
- clk_unprepare(pcchip->clk);
}
static const struct of_device_id pwm_clk_dt_ids[] = {
diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c
index 5e2b452ee5f2..98ab65c89685 100644
--- a/drivers/pwm/pwm-imx-tpm.c
+++ b/drivers/pwm/pwm-imx-tpm.c
@@ -397,6 +397,13 @@ static int __maybe_unused pwm_imx_tpm_suspend(struct device *dev)
if (tpm->enable_count > 0)
return -EBUSY;
+ /*
+ * Force 'real_period' to be zero to force period update code
+ * can be executed after system resume back, since suspend causes
+ * the period related registers to become their reset values.
+ */
+ tpm->real_period = 0;
+
clk_disable_unprepare(tpm->clk);
return 0;
diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
index 5b5eeaff35da..7a51d210a877 100644
--- a/drivers/pwm/pwm-mediatek.c
+++ b/drivers/pwm/pwm-mediatek.c
@@ -38,6 +38,7 @@ struct pwm_mediatek_of_data {
unsigned int num_pwms;
bool pwm45_fixup;
bool has_ck_26m_sel;
+ const unsigned int *reg_offset;
};
/**
@@ -59,10 +60,14 @@ struct pwm_mediatek_chip {
const struct pwm_mediatek_of_data *soc;
};
-static const unsigned int pwm_mediatek_reg_offset[] = {
+static const unsigned int mtk_pwm_reg_offset_v1[] = {
0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220
};
+static const unsigned int mtk_pwm_reg_offset_v2[] = {
+ 0x0080, 0x00c0, 0x0100, 0x0140, 0x0180, 0x01c0, 0x0200, 0x0240
+};
+
static inline struct pwm_mediatek_chip *
to_pwm_mediatek_chip(struct pwm_chip *chip)
{
@@ -111,7 +116,7 @@ static inline void pwm_mediatek_writel(struct pwm_mediatek_chip *chip,
unsigned int num, unsigned int offset,
u32 value)
{
- writel(value, chip->regs + pwm_mediatek_reg_offset[num] + offset);
+ writel(value, chip->regs + chip->soc->reg_offset[num] + offset);
}
static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -285,60 +290,77 @@ static const struct pwm_mediatek_of_data mt2712_pwm_data = {
.num_pwms = 8,
.pwm45_fixup = false,
.has_ck_26m_sel = false,
+ .reg_offset = mtk_pwm_reg_offset_v1,
};
static const struct pwm_mediatek_of_data mt6795_pwm_data = {
.num_pwms = 7,
.pwm45_fixup = false,
.has_ck_26m_sel = false,
+ .reg_offset = mtk_pwm_reg_offset_v1,
};
static const struct pwm_mediatek_of_data mt7622_pwm_data = {
.num_pwms = 6,
.pwm45_fixup = false,
.has_ck_26m_sel = true,
+ .reg_offset = mtk_pwm_reg_offset_v1,
};
static const struct pwm_mediatek_of_data mt7623_pwm_data = {
.num_pwms = 5,
.pwm45_fixup = true,
.has_ck_26m_sel = false,
+ .reg_offset = mtk_pwm_reg_offset_v1,
};
static const struct pwm_mediatek_of_data mt7628_pwm_data = {
.num_pwms = 4,
.pwm45_fixup = true,
.has_ck_26m_sel = false,
+ .reg_offset = mtk_pwm_reg_offset_v1,
};
static const struct pwm_mediatek_of_data mt7629_pwm_data = {
.num_pwms = 1,
.pwm45_fixup = false,
.has_ck_26m_sel = false,
+ .reg_offset = mtk_pwm_reg_offset_v1,
};
-static const struct pwm_mediatek_of_data mt8183_pwm_data = {
- .num_pwms = 4,
+static const struct pwm_mediatek_of_data mt7981_pwm_data = {
+ .num_pwms = 3,
.pwm45_fixup = false,
.has_ck_26m_sel = true,
+ .reg_offset = mtk_pwm_reg_offset_v2,
};
-static const struct pwm_mediatek_of_data mt8365_pwm_data = {
- .num_pwms = 3,
+static const struct pwm_mediatek_of_data mt7986_pwm_data = {
+ .num_pwms = 2,
.pwm45_fixup = false,
.has_ck_26m_sel = true,
+ .reg_offset = mtk_pwm_reg_offset_v1,
};
-static const struct pwm_mediatek_of_data mt7986_pwm_data = {
- .num_pwms = 2,
+static const struct pwm_mediatek_of_data mt8183_pwm_data = {
+ .num_pwms = 4,
+ .pwm45_fixup = false,
+ .has_ck_26m_sel = true,
+ .reg_offset = mtk_pwm_reg_offset_v1,
+};
+
+static const struct pwm_mediatek_of_data mt8365_pwm_data = {
+ .num_pwms = 3,
.pwm45_fixup = false,
.has_ck_26m_sel = true,
+ .reg_offset = mtk_pwm_reg_offset_v1,
};
static const struct pwm_mediatek_of_data mt8516_pwm_data = {
.num_pwms = 5,
.pwm45_fixup = false,
.has_ck_26m_sel = true,
+ .reg_offset = mtk_pwm_reg_offset_v1,
};
static const struct of_device_id pwm_mediatek_of_match[] = {
@@ -348,6 +370,7 @@ static const struct of_device_id pwm_mediatek_of_match[] = {
{ .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data },
{ .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data },
{ .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data },
+ { .compatible = "mediatek,mt7981-pwm", .data = &mt7981_pwm_data },
{ .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data },
{ .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data },
{ .compatible = "mediatek,mt8365-pwm", .data = &mt8365_pwm_data },
diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
index 5732300eb004..22f54db3ae8e 100644
--- a/drivers/pwm/pwm-meson.c
+++ b/drivers/pwm/pwm-meson.c
@@ -49,9 +49,9 @@
#define PWM_HIGH_MASK GENMASK(31, 16)
#define REG_MISC_AB 0x8
-#define MISC_B_CLK_EN BIT(23)
-#define MISC_A_CLK_EN BIT(15)
-#define MISC_CLK_DIV_MASK 0x7f
+#define MISC_B_CLK_EN_SHIFT 23
+#define MISC_A_CLK_EN_SHIFT 15
+#define MISC_CLK_DIV_WIDTH 7
#define MISC_B_CLK_DIV_SHIFT 16
#define MISC_A_CLK_DIV_SHIFT 8
#define MISC_B_CLK_SEL_SHIFT 6
@@ -61,37 +61,39 @@
#define MISC_A_EN BIT(0)
#define MESON_NUM_PWMS 2
+#define MESON_MAX_MUX_PARENTS 4
static struct meson_pwm_channel_data {
u8 reg_offset;
u8 clk_sel_shift;
u8 clk_div_shift;
- u32 clk_en_mask;
+ u8 clk_en_shift;
u32 pwm_en_mask;
} meson_pwm_per_channel_data[MESON_NUM_PWMS] = {
{
.reg_offset = REG_PWM_A,
.clk_sel_shift = MISC_A_CLK_SEL_SHIFT,
.clk_div_shift = MISC_A_CLK_DIV_SHIFT,
- .clk_en_mask = MISC_A_CLK_EN,
+ .clk_en_shift = MISC_A_CLK_EN_SHIFT,
.pwm_en_mask = MISC_A_EN,
},
{
.reg_offset = REG_PWM_B,
.clk_sel_shift = MISC_B_CLK_SEL_SHIFT,
.clk_div_shift = MISC_B_CLK_DIV_SHIFT,
- .clk_en_mask = MISC_B_CLK_EN,
+ .clk_en_shift = MISC_B_CLK_EN_SHIFT,
.pwm_en_mask = MISC_B_EN,
}
};
struct meson_pwm_channel {
+ unsigned long rate;
unsigned int hi;
unsigned int lo;
- u8 pre_div;
- struct clk *clk_parent;
struct clk_mux mux;
+ struct clk_divider div;
+ struct clk_gate gate;
struct clk *clk;
};
@@ -124,16 +126,6 @@ static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
struct device *dev = chip->dev;
int err;
- if (channel->clk_parent) {
- err = clk_set_parent(channel->clk, channel->clk_parent);
- if (err < 0) {
- dev_err(dev, "failed to set parent %s for %s: %d\n",
- __clk_get_name(channel->clk_parent),
- __clk_get_name(channel->clk), err);
- return err;
- }
- }
-
err = clk_prepare_enable(channel->clk);
if (err < 0) {
dev_err(dev, "failed to enable clock %s: %d\n",
@@ -156,8 +148,9 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
const struct pwm_state *state)
{
struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
- unsigned int duty, period, pre_div, cnt, duty_cnt;
+ unsigned int cnt, duty_cnt;
unsigned long fin_freq;
+ u64 duty, period, freq;
duty = state->duty_cycle;
period = state->period;
@@ -171,7 +164,11 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
if (state->polarity == PWM_POLARITY_INVERSED)
duty = period - duty;
- fin_freq = clk_get_rate(channel->clk);
+ freq = div64_u64(NSEC_PER_SEC * 0xffffULL, period);
+ if (freq > ULONG_MAX)
+ freq = ULONG_MAX;
+
+ fin_freq = clk_round_rate(channel->clk, freq);
if (fin_freq == 0) {
dev_err(meson->chip.dev, "invalid source clock frequency\n");
return -EINVAL;
@@ -179,46 +176,31 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
dev_dbg(meson->chip.dev, "fin_freq: %lu Hz\n", fin_freq);
- pre_div = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * 0xffffLL);
- if (pre_div > MISC_CLK_DIV_MASK) {
- dev_err(meson->chip.dev, "unable to get period pre_div\n");
- return -EINVAL;
- }
-
- cnt = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * (pre_div + 1));
+ cnt = div_u64(fin_freq * period, NSEC_PER_SEC);
if (cnt > 0xffff) {
dev_err(meson->chip.dev, "unable to get period cnt\n");
return -EINVAL;
}
- dev_dbg(meson->chip.dev, "period=%u pre_div=%u cnt=%u\n", period,
- pre_div, cnt);
+ dev_dbg(meson->chip.dev, "period=%llu cnt=%u\n", period, cnt);
if (duty == period) {
- channel->pre_div = pre_div;
channel->hi = cnt;
channel->lo = 0;
} else if (duty == 0) {
- channel->pre_div = pre_div;
channel->hi = 0;
channel->lo = cnt;
} else {
- /* Then check is we can have the duty with the same pre_div */
- duty_cnt = div64_u64(fin_freq * (u64)duty,
- NSEC_PER_SEC * (pre_div + 1));
- if (duty_cnt > 0xffff) {
- dev_err(meson->chip.dev, "unable to get duty cycle\n");
- return -EINVAL;
- }
+ duty_cnt = div_u64(fin_freq * duty, NSEC_PER_SEC);
- dev_dbg(meson->chip.dev, "duty=%u pre_div=%u duty_cnt=%u\n",
- duty, pre_div, duty_cnt);
+ dev_dbg(meson->chip.dev, "duty=%llu duty_cnt=%u\n", duty, duty_cnt);
- channel->pre_div = pre_div;
channel->hi = duty_cnt;
channel->lo = cnt - duty_cnt;
}
+ channel->rate = fin_freq;
+
return 0;
}
@@ -228,16 +210,15 @@ static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm)
struct meson_pwm_channel_data *channel_data;
unsigned long flags;
u32 value;
+ int err;
channel_data = &meson_pwm_per_channel_data[pwm->hwpwm];
- spin_lock_irqsave(&meson->lock, flags);
+ err = clk_set_rate(channel->clk, channel->rate);
+ if (err)
+ dev_err(meson->chip.dev, "setting clock rate failed\n");
- value = readl(meson->base + REG_MISC_AB);
- value &= ~(MISC_CLK_DIV_MASK << channel_data->clk_div_shift);
- value |= channel->pre_div << channel_data->clk_div_shift;
- value |= channel_data->clk_en_mask;
- writel(value, meson->base + REG_MISC_AB);
+ spin_lock_irqsave(&meson->lock, flags);
value = FIELD_PREP(PWM_HIGH_MASK, channel->hi) |
FIELD_PREP(PWM_LOW_MASK, channel->lo);
@@ -276,16 +257,16 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
/*
* This IP block revision doesn't have an "always high"
* setting which we can use for "inverted disabled".
- * Instead we achieve this using the same settings
- * that we use a pre_div of 0 (to get the shortest
- * possible duration for one "count") and
- * "period == duty_cycle". This results in a signal
+ * Instead we achieve this by setting mux parent with
+ * highest rate and minimum divider value, resulting
+ * in the shortest possible duration for one "count"
+ * and "period == duty_cycle". This results in a signal
* which is LOW for one "count", while being HIGH for
* the rest of the (so the signal is HIGH for slightly
* less than 100% of the period, but this is the best
* we can achieve).
*/
- channel->pre_div = 0;
+ channel->rate = ULONG_MAX;
channel->hi = ~0;
channel->lo = 0;
@@ -304,13 +285,12 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;
}
-static unsigned int meson_pwm_cnt_to_ns(struct pwm_chip *chip,
- struct pwm_device *pwm, u32 cnt)
+static u64 meson_pwm_cnt_to_ns(struct pwm_chip *chip, struct pwm_device *pwm,
+ u32 cnt)
{
struct meson_pwm *meson = to_meson_pwm(chip);
struct meson_pwm_channel *channel;
unsigned long fin_freq;
- u32 fin_ns;
/* to_meson_pwm() can only be used after .get_state() is called */
channel = &meson->channels[pwm->hwpwm];
@@ -319,9 +299,7 @@ static unsigned int meson_pwm_cnt_to_ns(struct pwm_chip *chip,
if (fin_freq == 0)
return 0;
- fin_ns = div_u64(NSEC_PER_SEC, fin_freq);
-
- return cnt * fin_ns * (channel->pre_div + 1);
+ return div64_ul(NSEC_PER_SEC * (u64)cnt, fin_freq);
}
static int meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -330,7 +308,7 @@ static int meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct meson_pwm *meson = to_meson_pwm(chip);
struct meson_pwm_channel_data *channel_data;
struct meson_pwm_channel *channel;
- u32 value, tmp;
+ u32 value;
if (!state)
return 0;
@@ -339,30 +317,14 @@ static int meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
channel_data = &meson_pwm_per_channel_data[pwm->hwpwm];
value = readl(meson->base + REG_MISC_AB);
-
- tmp = channel_data->pwm_en_mask | channel_data->clk_en_mask;
- state->enabled = (value & tmp) == tmp;
-
- tmp = value >> channel_data->clk_div_shift;
- channel->pre_div = FIELD_GET(MISC_CLK_DIV_MASK, tmp);
+ state->enabled = value & channel_data->pwm_en_mask;
value = readl(meson->base + channel_data->reg_offset);
-
channel->lo = FIELD_GET(PWM_LOW_MASK, value);
channel->hi = FIELD_GET(PWM_HIGH_MASK, value);
- if (channel->lo == 0) {
- state->period = meson_pwm_cnt_to_ns(chip, pwm, channel->hi);
- state->duty_cycle = state->period;
- } else if (channel->lo >= channel->hi) {
- state->period = meson_pwm_cnt_to_ns(chip, pwm,
- channel->lo + channel->hi);
- state->duty_cycle = meson_pwm_cnt_to_ns(chip, pwm,
- channel->hi);
- } else {
- state->period = 0;
- state->duty_cycle = 0;
- }
+ state->period = meson_pwm_cnt_to_ns(chip, pwm, channel->lo + channel->hi);
+ state->duty_cycle = meson_pwm_cnt_to_ns(chip, pwm, channel->hi);
state->polarity = PWM_POLARITY_NORMAL;
@@ -378,7 +340,7 @@ static const struct pwm_ops meson_pwm_ops = {
};
static const char * const pwm_meson8b_parent_names[] = {
- "xtal", "vid_pll", "fclk_div4", "fclk_div3"
+ "xtal", NULL, "fclk_div4", "fclk_div3"
};
static const struct meson_pwm_data pwm_meson8b_data = {
@@ -386,15 +348,6 @@ static const struct meson_pwm_data pwm_meson8b_data = {
.num_parents = ARRAY_SIZE(pwm_meson8b_parent_names),
};
-static const char * const pwm_gxbb_parent_names[] = {
- "xtal", "hdmi_pll", "fclk_div4", "fclk_div3"
-};
-
-static const struct meson_pwm_data pwm_gxbb_data = {
- .parent_names = pwm_gxbb_parent_names,
- .num_parents = ARRAY_SIZE(pwm_gxbb_parent_names),
-};
-
/*
* Only the 2 first inputs of the GXBB AO PWMs are valid
* The last 2 are grounded
@@ -444,15 +397,6 @@ static const struct meson_pwm_data pwm_g12a_ao_cd_data = {
.num_parents = ARRAY_SIZE(pwm_g12a_ao_cd_parent_names),
};
-static const char * const pwm_g12a_ee_parent_names[] = {
- "xtal", "hdmi_pll", "fclk_div4", "fclk_div3"
-};
-
-static const struct meson_pwm_data pwm_g12a_ee_data = {
- .parent_names = pwm_g12a_ee_parent_names,
- .num_parents = ARRAY_SIZE(pwm_g12a_ee_parent_names),
-};
-
static const struct of_device_id meson_pwm_matches[] = {
{
.compatible = "amlogic,meson8b-pwm",
@@ -460,7 +404,7 @@ static const struct of_device_id meson_pwm_matches[] = {
},
{
.compatible = "amlogic,meson-gxbb-pwm",
- .data = &pwm_gxbb_data
+ .data = &pwm_meson8b_data
},
{
.compatible = "amlogic,meson-gxbb-ao-pwm",
@@ -476,7 +420,7 @@ static const struct of_device_id meson_pwm_matches[] = {
},
{
.compatible = "amlogic,meson-g12a-ee-pwm",
- .data = &pwm_g12a_ee_data
+ .data = &pwm_meson8b_data
},
{
.compatible = "amlogic,meson-g12a-ao-pwm-ab",
@@ -492,21 +436,28 @@ MODULE_DEVICE_TABLE(of, meson_pwm_matches);
static int meson_pwm_init_channels(struct meson_pwm *meson)
{
+ struct clk_parent_data mux_parent_data[MESON_MAX_MUX_PARENTS] = {};
struct device *dev = meson->chip.dev;
- struct clk_init_data init;
unsigned int i;
char name[255];
int err;
+ for (i = 0; i < meson->data->num_parents; i++) {
+ mux_parent_data[i].index = -1;
+ mux_parent_data[i].name = meson->data->parent_names[i];
+ }
+
for (i = 0; i < meson->chip.npwm; i++) {
struct meson_pwm_channel *channel = &meson->channels[i];
+ struct clk_parent_data div_parent = {}, gate_parent = {};
+ struct clk_init_data init = {};
snprintf(name, sizeof(name), "%s#mux%u", dev_name(dev), i);
init.name = name;
init.ops = &clk_mux_ops;
init.flags = 0;
- init.parent_names = meson->data->parent_names;
+ init.parent_data = mux_parent_data;
init.num_parents = meson->data->num_parents;
channel->mux.reg = meson->base + REG_MISC_AB;
@@ -518,18 +469,63 @@ static int meson_pwm_init_channels(struct meson_pwm *meson)
channel->mux.table = NULL;
channel->mux.hw.init = &init;
- channel->clk = devm_clk_register(dev, &channel->mux.hw);
- if (IS_ERR(channel->clk)) {
- err = PTR_ERR(channel->clk);
+ err = devm_clk_hw_register(dev, &channel->mux.hw);
+ if (err) {
+ dev_err(dev, "failed to register %s: %d\n", name, err);
+ return err;
+ }
+
+ snprintf(name, sizeof(name), "%s#div%u", dev_name(dev), i);
+
+ init.name = name;
+ init.ops = &clk_divider_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ div_parent.index = -1;
+ div_parent.hw = &channel->mux.hw;
+ init.parent_data = &div_parent;
+ init.num_parents = 1;
+
+ channel->div.reg = meson->base + REG_MISC_AB;
+ channel->div.shift = meson_pwm_per_channel_data[i].clk_div_shift;
+ channel->div.width = MISC_CLK_DIV_WIDTH;
+ channel->div.hw.init = &init;
+ channel->div.flags = 0;
+ channel->div.lock = &meson->lock;
+
+ err = devm_clk_hw_register(dev, &channel->div.hw);
+ if (err) {
dev_err(dev, "failed to register %s: %d\n", name, err);
return err;
}
- snprintf(name, sizeof(name), "clkin%u", i);
+ snprintf(name, sizeof(name), "%s#gate%u", dev_name(dev), i);
- channel->clk_parent = devm_clk_get_optional(dev, name);
- if (IS_ERR(channel->clk_parent))
- return PTR_ERR(channel->clk_parent);
+ init.name = name;
+ init.ops = &clk_gate_ops;
+ init.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED;
+ gate_parent.index = -1;
+ gate_parent.hw = &channel->div.hw;
+ init.parent_data = &gate_parent;
+ init.num_parents = 1;
+
+ channel->gate.reg = meson->base + REG_MISC_AB;
+ channel->gate.bit_idx = meson_pwm_per_channel_data[i].clk_en_shift;
+ channel->gate.hw.init = &init;
+ channel->gate.flags = 0;
+ channel->gate.lock = &meson->lock;
+
+ err = devm_clk_hw_register(dev, &channel->gate.hw);
+ if (err) {
+ dev_err(dev, "failed to register %s: %d\n", name, err);
+ return err;
+ }
+
+ channel->clk = devm_clk_hw_get_clk(dev, &channel->gate.hw, NULL);
+ if (IS_ERR(channel->clk)) {
+ err = PTR_ERR(channel->clk);
+ dev_err(dev, "failed to register %s: %d\n", name, err);
+ return err;
+ }
}
return 0;
diff --git a/drivers/pwm/pwm-microchip-core.c b/drivers/pwm/pwm-microchip-core.c
new file mode 100644
index 000000000000..8750b57684a9
--- /dev/null
+++ b/drivers/pwm/pwm-microchip-core.c
@@ -0,0 +1,507 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * corePWM driver for Microchip "soft" FPGA IP cores.
+ *
+ * Copyright (c) 2021-2023 Microchip Corporation. All rights reserved.
+ * Author: Conor Dooley <conor.dooley@microchip.com>
+ * Documentation:
+ * https://www.microsemi.com/document-portal/doc_download/1245275-corepwm-hb
+ *
+ * Limitations:
+ * - If the IP block is configured without "shadow registers", all register
+ * writes will take effect immediately, causing glitches on the output.
+ * If shadow registers *are* enabled, setting the "SYNC_UPDATE" register
+ * notifies the core that it needs to update the registers defining the
+ * waveform from the contents of the "shadow registers". Otherwise, changes
+ * will take effective immediately, even for those channels.
+ * As setting the period/duty cycle takes 4 register writes, there is a window
+ * in which this races against the start of a new period.
+ * - The IP block has no concept of a duty cycle, only rising/falling edges of
+ * the waveform. Unfortunately, if the rising & falling edges registers have
+ * the same value written to them the IP block will do whichever of a rising
+ * or a falling edge is possible. I.E. a 50% waveform at twice the requested
+ * period. Therefore to get a 0% waveform, the output is set the max high/low
+ * time depending on polarity.
+ * If the duty cycle is 0%, and the requested period is less than the
+ * available period resolution, this will manifest as a ~100% waveform (with
+ * some output glitches) rather than 50%.
+ * - The PWM period is set for the whole IP block not per channel. The driver
+ * will only change the period if no other PWM output is enabled.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ktime.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+
+#define MCHPCOREPWM_PRESCALE_MAX 0xff
+#define MCHPCOREPWM_PERIOD_STEPS_MAX 0xfe
+#define MCHPCOREPWM_PERIOD_MAX 0xff00
+
+#define MCHPCOREPWM_PRESCALE 0x00
+#define MCHPCOREPWM_PERIOD 0x04
+#define MCHPCOREPWM_EN(i) (0x08 + 0x04 * (i)) /* 0x08, 0x0c */
+#define MCHPCOREPWM_POSEDGE(i) (0x10 + 0x08 * (i)) /* 0x10, 0x18, ..., 0x88 */
+#define MCHPCOREPWM_NEGEDGE(i) (0x14 + 0x08 * (i)) /* 0x14, 0x1c, ..., 0x8c */
+#define MCHPCOREPWM_SYNC_UPD 0xe4
+#define MCHPCOREPWM_TIMEOUT_MS 100u
+
+struct mchp_core_pwm_chip {
+ struct pwm_chip chip;
+ struct clk *clk;
+ void __iomem *base;
+ struct mutex lock; /* protects the shared period */
+ ktime_t update_timestamp;
+ u32 sync_update_mask;
+ u16 channel_enabled;
+};
+
+static inline struct mchp_core_pwm_chip *to_mchp_core_pwm(struct pwm_chip *chip)
+{
+ return container_of(chip, struct mchp_core_pwm_chip, chip);
+}
+
+static void mchp_core_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm,
+ bool enable, u64 period)
+{
+ struct mchp_core_pwm_chip *mchp_core_pwm = to_mchp_core_pwm(chip);
+ u8 channel_enable, reg_offset, shift;
+
+ /*
+ * There are two adjacent 8 bit control regs, the lower reg controls
+ * 0-7 and the upper reg 8-15. Check if the pwm is in the upper reg
+ * and if so, offset by the bus width.
+ */
+ reg_offset = MCHPCOREPWM_EN(pwm->hwpwm >> 3);
+ shift = pwm->hwpwm & 7;
+
+ channel_enable = readb_relaxed(mchp_core_pwm->base + reg_offset);
+ channel_enable &= ~(1 << shift);
+ channel_enable |= (enable << shift);
+
+ writel_relaxed(channel_enable, mchp_core_pwm->base + reg_offset);
+ mchp_core_pwm->channel_enabled &= ~BIT(pwm->hwpwm);
+ mchp_core_pwm->channel_enabled |= enable << pwm->hwpwm;
+
+ /*
+ * The updated values will not appear on the bus until they have been
+ * applied to the waveform at the beginning of the next period.
+ * This is a NO-OP if the channel does not have shadow registers.
+ */
+ if (mchp_core_pwm->sync_update_mask & (1 << pwm->hwpwm))
+ mchp_core_pwm->update_timestamp = ktime_add_ns(ktime_get(), period);
+}
+
+static void mchp_core_pwm_wait_for_sync_update(struct mchp_core_pwm_chip *mchp_core_pwm,
+ unsigned int channel)
+{
+ /*
+ * If a shadow register is used for this PWM channel, and iff there is
+ * a pending update to the waveform, we must wait for it to be applied
+ * before attempting to read its state. Reading the registers yields
+ * the currently implemented settings & the new ones are only readable
+ * once the current period has ended.
+ */
+
+ if (mchp_core_pwm->sync_update_mask & (1 << channel)) {
+ ktime_t current_time = ktime_get();
+ s64 remaining_ns;
+ u32 delay_us;
+
+ remaining_ns = ktime_to_ns(ktime_sub(mchp_core_pwm->update_timestamp,
+ current_time));
+
+ /*
+ * If the update has gone through, don't bother waiting for
+ * obvious reasons. Otherwise wait around for an appropriate
+ * amount of time for the update to go through.
+ */
+ if (remaining_ns <= 0)
+ return;
+
+ delay_us = DIV_ROUND_UP_ULL(remaining_ns, NSEC_PER_USEC);
+ fsleep(delay_us);
+ }
+}
+
+static u64 mchp_core_pwm_calc_duty(const struct pwm_state *state, u64 clk_rate,
+ u8 prescale, u8 period_steps)
+{
+ u64 duty_steps, tmp;
+
+ /*
+ * Calculate the duty cycle in multiples of the prescaled period:
+ * duty_steps = duty_in_ns / step_in_ns
+ * step_in_ns = (prescale * NSEC_PER_SEC) / clk_rate
+ * The code below is rearranged slightly to only divide once.
+ */
+ tmp = (((u64)prescale) + 1) * NSEC_PER_SEC;
+ duty_steps = mul_u64_u64_div_u64(state->duty_cycle, clk_rate, tmp);
+
+ return duty_steps;
+}
+
+static void mchp_core_pwm_apply_duty(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state, u64 duty_steps,
+ u16 period_steps)
+{
+ struct mchp_core_pwm_chip *mchp_core_pwm = to_mchp_core_pwm(chip);
+ u8 posedge, negedge;
+ u8 first_edge = 0, second_edge = duty_steps;
+
+ /*
+ * Setting posedge == negedge doesn't yield a constant output,
+ * so that's an unsuitable setting to model duty_steps = 0.
+ * In that case set the unwanted edge to a value that never
+ * triggers.
+ */
+ if (duty_steps == 0)
+ first_edge = period_steps + 1;
+
+ if (state->polarity == PWM_POLARITY_INVERSED) {
+ negedge = first_edge;
+ posedge = second_edge;
+ } else {
+ posedge = first_edge;
+ negedge = second_edge;
+ }
+
+ /*
+ * Set the sync bit which ensures that periods that already started are
+ * completed unaltered. At each counter reset event the values are
+ * updated from the shadow registers.
+ */
+ writel_relaxed(posedge, mchp_core_pwm->base + MCHPCOREPWM_POSEDGE(pwm->hwpwm));
+ writel_relaxed(negedge, mchp_core_pwm->base + MCHPCOREPWM_NEGEDGE(pwm->hwpwm));
+}
+
+static int mchp_core_pwm_calc_period(const struct pwm_state *state, unsigned long clk_rate,
+ u16 *prescale, u16 *period_steps)
+{
+ u64 tmp;
+
+ /*
+ * Calculate the period cycles and prescale values.
+ * The registers are each 8 bits wide & multiplied to compute the period
+ * using the formula:
+ * (prescale + 1) * (period_steps + 1)
+ * period = -------------------------------------
+ * clk_rate
+ * so the maximum period that can be generated is 0x10000 times the
+ * period of the input clock.
+ * However, due to the design of the "hardware", it is not possible to
+ * attain a 100% duty cycle if the full range of period_steps is used.
+ * Therefore period_steps is restricted to 0xfe and the maximum multiple
+ * of the clock period attainable is (0xff + 1) * (0xfe + 1) = 0xff00
+ *
+ * The prescale and period_steps registers operate similarly to
+ * CLK_DIVIDER_ONE_BASED, where the value used by the hardware is that
+ * in the register plus one.
+ * It's therefore not possible to set a period lower than 1/clk_rate, so
+ * if tmp is 0, abort. Without aborting, we will set a period that is
+ * greater than that requested and, more importantly, will trigger the
+ * neg-/pos-edge issue described in the limitations.
+ */
+ tmp = mul_u64_u64_div_u64(state->period, clk_rate, NSEC_PER_SEC);
+ if (tmp >= MCHPCOREPWM_PERIOD_MAX) {
+ *prescale = MCHPCOREPWM_PRESCALE_MAX;
+ *period_steps = MCHPCOREPWM_PERIOD_STEPS_MAX;
+
+ return 0;
+ }
+
+ /*
+ * There are multiple strategies that could be used to choose the
+ * prescale & period_steps values.
+ * Here the idea is to pick values so that the selection of duty cycles
+ * is as finegrain as possible, while also keeping the period less than
+ * that requested.
+ *
+ * A simple way to satisfy the first condition is to always set
+ * period_steps to its maximum value. This neatly also satisfies the
+ * second condition too, since using the maximum value of period_steps
+ * to calculate prescale actually calculates its upper bound.
+ * Integer division will ensure a round down, so the period will thereby
+ * always be less than that requested.
+ *
+ * The downside of this approach is a significant degree of inaccuracy,
+ * especially as tmp approaches integer multiples of
+ * MCHPCOREPWM_PERIOD_STEPS_MAX.
+ *
+ * As we must produce a period less than that requested, and for the
+ * sake of creating a simple algorithm, disallow small values of tmp
+ * that would need special handling.
+ */
+ if (tmp < MCHPCOREPWM_PERIOD_STEPS_MAX + 1)
+ return -EINVAL;
+
+ /*
+ * This "optimal" value for prescale is be calculated using the maximum
+ * permitted value of period_steps, 0xfe.
+ *
+ * period * clk_rate
+ * prescale = ------------------------- - 1
+ * NSEC_PER_SEC * (0xfe + 1)
+ *
+ *
+ * period * clk_rate
+ * ------------------- was precomputed as `tmp`
+ * NSEC_PER_SEC
+ */
+ *prescale = ((u16)tmp) / (MCHPCOREPWM_PERIOD_STEPS_MAX + 1) - 1;
+
+ /*
+ * period_steps can be computed from prescale:
+ * period * clk_rate
+ * period_steps = ----------------------------- - 1
+ * NSEC_PER_SEC * (prescale + 1)
+ *
+ * However, in this approximation, we simply use the maximum value that
+ * was used to compute prescale.
+ */
+ *period_steps = MCHPCOREPWM_PERIOD_STEPS_MAX;
+
+ return 0;
+}
+
+static int mchp_core_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct mchp_core_pwm_chip *mchp_core_pwm = to_mchp_core_pwm(chip);
+ bool period_locked;
+ unsigned long clk_rate;
+ u64 duty_steps;
+ u16 prescale, period_steps;
+ int ret;
+
+ if (!state->enabled) {
+ mchp_core_pwm_enable(chip, pwm, false, pwm->state.period);
+ return 0;
+ }
+
+ /*
+ * If clk_rate is too big, the following multiplication might overflow.
+ * However this is implausible, as the fabric of current FPGAs cannot
+ * provide clocks at a rate high enough.
+ */
+ clk_rate = clk_get_rate(mchp_core_pwm->clk);
+ if (clk_rate >= NSEC_PER_SEC)
+ return -EINVAL;
+
+ ret = mchp_core_pwm_calc_period(state, clk_rate, &prescale, &period_steps);
+ if (ret)
+ return ret;
+
+ /*
+ * If the only thing that has changed is the duty cycle or the polarity,
+ * we can shortcut the calculations and just compute/apply the new duty
+ * cycle pos & neg edges
+ * As all the channels share the same period, do not allow it to be
+ * changed if any other channels are enabled.
+ * If the period is locked, it may not be possible to use a period
+ * less than that requested. In that case, we just abort.
+ */
+ period_locked = mchp_core_pwm->channel_enabled & ~(1 << pwm->hwpwm);
+
+ if (period_locked) {
+ u16 hw_prescale;
+ u16 hw_period_steps;
+
+ hw_prescale = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_PRESCALE);
+ hw_period_steps = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_PERIOD);
+
+ if ((period_steps + 1) * (prescale + 1) <
+ (hw_period_steps + 1) * (hw_prescale + 1))
+ return -EINVAL;
+
+ /*
+ * It is possible that something could have set the period_steps
+ * register to 0xff, which would prevent us from setting a 100%
+ * or 0% relative duty cycle, as explained above in
+ * mchp_core_pwm_calc_period().
+ * The period is locked and we cannot change this, so we abort.
+ */
+ if (hw_period_steps == MCHPCOREPWM_PERIOD_STEPS_MAX)
+ return -EINVAL;
+
+ prescale = hw_prescale;
+ period_steps = hw_period_steps;
+ }
+
+ duty_steps = mchp_core_pwm_calc_duty(state, clk_rate, prescale, period_steps);
+
+ /*
+ * Because the period is not per channel, it is possible that the
+ * requested duty cycle is longer than the period, in which case cap it
+ * to the period, IOW a 100% duty cycle.
+ */
+ if (duty_steps > period_steps)
+ duty_steps = period_steps + 1;
+
+ if (!period_locked) {
+ writel_relaxed(prescale, mchp_core_pwm->base + MCHPCOREPWM_PRESCALE);
+ writel_relaxed(period_steps, mchp_core_pwm->base + MCHPCOREPWM_PERIOD);
+ }
+
+ mchp_core_pwm_apply_duty(chip, pwm, state, duty_steps, period_steps);
+
+ mchp_core_pwm_enable(chip, pwm, true, pwm->state.period);
+
+ return 0;
+}
+
+static int mchp_core_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct mchp_core_pwm_chip *mchp_core_pwm = to_mchp_core_pwm(chip);
+ int ret;
+
+ mutex_lock(&mchp_core_pwm->lock);
+
+ mchp_core_pwm_wait_for_sync_update(mchp_core_pwm, pwm->hwpwm);
+
+ ret = mchp_core_pwm_apply_locked(chip, pwm, state);
+
+ mutex_unlock(&mchp_core_pwm->lock);
+
+ return ret;
+}
+
+static int mchp_core_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct mchp_core_pwm_chip *mchp_core_pwm = to_mchp_core_pwm(chip);
+ u64 rate;
+ u16 prescale, period_steps;
+ u8 duty_steps, posedge, negedge;
+
+ mutex_lock(&mchp_core_pwm->lock);
+
+ mchp_core_pwm_wait_for_sync_update(mchp_core_pwm, pwm->hwpwm);
+
+ if (mchp_core_pwm->channel_enabled & (1 << pwm->hwpwm))
+ state->enabled = true;
+ else
+ state->enabled = false;
+
+ rate = clk_get_rate(mchp_core_pwm->clk);
+
+ /*
+ * Calculating the period:
+ * The registers are each 8 bits wide & multiplied to compute the period
+ * using the formula:
+ * (prescale + 1) * (period_steps + 1)
+ * period = -------------------------------------
+ * clk_rate
+ *
+ * Note:
+ * The prescale and period_steps registers operate similarly to
+ * CLK_DIVIDER_ONE_BASED, where the value used by the hardware is that
+ * in the register plus one.
+ */
+ prescale = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_PRESCALE);
+ period_steps = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_PERIOD);
+
+ state->period = (period_steps + 1) * (prescale + 1);
+ state->period *= NSEC_PER_SEC;
+ state->period = DIV64_U64_ROUND_UP(state->period, rate);
+
+ posedge = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_POSEDGE(pwm->hwpwm));
+ negedge = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_NEGEDGE(pwm->hwpwm));
+
+ mutex_unlock(&mchp_core_pwm->lock);
+
+ if (negedge == posedge) {
+ state->duty_cycle = state->period;
+ state->period *= 2;
+ } else {
+ duty_steps = abs((s16)posedge - (s16)negedge);
+ state->duty_cycle = duty_steps * (prescale + 1) * NSEC_PER_SEC;
+ state->duty_cycle = DIV64_U64_ROUND_UP(state->duty_cycle, rate);
+ }
+
+ state->polarity = negedge < posedge ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL;
+
+ return 0;
+}
+
+static const struct pwm_ops mchp_core_pwm_ops = {
+ .apply = mchp_core_pwm_apply,
+ .get_state = mchp_core_pwm_get_state,
+ .owner = THIS_MODULE,
+};
+
+static const struct of_device_id mchp_core_of_match[] = {
+ {
+ .compatible = "microchip,corepwm-rtl-v4",
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mchp_core_of_match);
+
+static int mchp_core_pwm_probe(struct platform_device *pdev)
+{
+ struct mchp_core_pwm_chip *mchp_core_pwm;
+ struct resource *regs;
+ int ret;
+
+ mchp_core_pwm = devm_kzalloc(&pdev->dev, sizeof(*mchp_core_pwm), GFP_KERNEL);
+ if (!mchp_core_pwm)
+ return -ENOMEM;
+
+ mchp_core_pwm->base = devm_platform_get_and_ioremap_resource(pdev, 0, &regs);
+ if (IS_ERR(mchp_core_pwm->base))
+ return PTR_ERR(mchp_core_pwm->base);
+
+ mchp_core_pwm->clk = devm_clk_get_enabled(&pdev->dev, NULL);
+ if (IS_ERR(mchp_core_pwm->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(mchp_core_pwm->clk),
+ "failed to get PWM clock\n");
+
+ if (of_property_read_u32(pdev->dev.of_node, "microchip,sync-update-mask",
+ &mchp_core_pwm->sync_update_mask))
+ mchp_core_pwm->sync_update_mask = 0;
+
+ mutex_init(&mchp_core_pwm->lock);
+
+ mchp_core_pwm->chip.dev = &pdev->dev;
+ mchp_core_pwm->chip.ops = &mchp_core_pwm_ops;
+ mchp_core_pwm->chip.npwm = 16;
+
+ mchp_core_pwm->channel_enabled = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_EN(0));
+ mchp_core_pwm->channel_enabled |=
+ readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_EN(1)) << 8;
+
+ /*
+ * Enable synchronous update mode for all channels for which shadow
+ * registers have been synthesised.
+ */
+ writel_relaxed(1U, mchp_core_pwm->base + MCHPCOREPWM_SYNC_UPD);
+ mchp_core_pwm->update_timestamp = ktime_get();
+
+ ret = devm_pwmchip_add(&pdev->dev, &mchp_core_pwm->chip);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Failed to add pwmchip\n");
+
+ return 0;
+}
+
+static struct platform_driver mchp_core_pwm_driver = {
+ .driver = {
+ .name = "mchp-core-pwm",
+ .of_match_table = mchp_core_of_match,
+ },
+ .probe = mchp_core_pwm_probe,
+};
+module_platform_driver(mchp_core_pwm_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
+MODULE_DESCRIPTION("corePWM driver for Microchip FPGAs");
diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c
index 79e321e96f56..2401b6733241 100644
--- a/drivers/pwm/pwm-mtk-disp.c
+++ b/drivers/pwm/pwm-mtk-disp.c
@@ -79,14 +79,11 @@ static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (state->polarity != PWM_POLARITY_NORMAL)
return -EINVAL;
- if (!state->enabled) {
- mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
- 0x0);
-
- if (mdp->enabled) {
- clk_disable_unprepare(mdp->clk_mm);
- clk_disable_unprepare(mdp->clk_main);
- }
+ if (!state->enabled && mdp->enabled) {
+ mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN,
+ mdp->data->enable_mask, 0x0);
+ clk_disable_unprepare(mdp->clk_mm);
+ clk_disable_unprepare(mdp->clk_main);
mdp->enabled = false;
return 0;
diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c
index 3ed5a48ca581..3038a68412a7 100644
--- a/drivers/pwm/pwm-pca9685.c
+++ b/drivers/pwm/pwm-pca9685.c
@@ -665,7 +665,7 @@ static struct i2c_driver pca9685_i2c_driver = {
.of_match_table = of_match_ptr(pca9685_dt_ids),
.pm = &pca9685_pwm_pm,
},
- .probe_new = pca9685_pwm_probe,
+ .probe = pca9685_pwm_probe,
.remove = pca9685_pwm_remove,
.id_table = pca9685_id,
};
diff --git a/drivers/pwm/pwm-rz-mtu3.c b/drivers/pwm/pwm-rz-mtu3.c
new file mode 100644
index 000000000000..bed8bd671e37
--- /dev/null
+++ b/drivers/pwm/pwm-rz-mtu3.c
@@ -0,0 +1,551 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G2L MTU3a PWM Timer driver
+ *
+ * Copyright (C) 2023 Renesas Electronics Corporation
+ *
+ * Hardware manual for this IP can be found here
+ * https://www.renesas.com/eu/en/document/mah/rzg2l-group-rzg2lc-group-users-manual-hardware-0?language=en
+ *
+ * Limitations:
+ * - When PWM is disabled, the output is driven to Hi-Z.
+ * - While the hardware supports both polarities, the driver (for now)
+ * only handles normal polarity.
+ * - HW uses one counter and two match components to configure duty_cycle
+ * and period.
+ * - Multi-Function Timer Pulse Unit (a.k.a MTU) has 7 HW channels for PWM
+ * operations. (The channels are MTU{0..4, 6, 7}.)
+ * - MTU{1, 2} channels have a single IO, whereas all other HW channels have
+ * 2 IOs.
+ * - Each IO is modelled as an independent PWM channel.
+ * - rz_mtu3_channel_io_map table is used to map the PWM channel to the
+ * corresponding HW channel as there are difference in number of IOs
+ * between HW channels.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/limits.h>
+#include <linux/mfd/rz-mtu3.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/pwm.h>
+#include <linux/time.h>
+
+#define RZ_MTU3_MAX_PWM_CHANNELS 12
+#define RZ_MTU3_MAX_HW_CHANNELS 7
+
+/**
+ * struct rz_mtu3_channel_io_map - MTU3 pwm channel map
+ *
+ * @base_pwm_number: First PWM of a channel
+ * @num: number of IOs on the HW channel.
+ */
+struct rz_mtu3_channel_io_map {
+ u8 base_pwm_number;
+ u8 num_channel_ios;
+};
+
+/**
+ * struct rz_mtu3_pwm_channel - MTU3 pwm channel data
+ *
+ * @mtu: MTU3 channel data
+ * @map: MTU3 pwm channel map
+ */
+struct rz_mtu3_pwm_channel {
+ struct rz_mtu3_channel *mtu;
+ const struct rz_mtu3_channel_io_map *map;
+};
+
+/**
+ * struct rz_mtu3_pwm_chip - MTU3 pwm private data
+ *
+ * @chip: MTU3 pwm chip data
+ * @clk: MTU3 module clock
+ * @lock: Lock to prevent concurrent access for usage count
+ * @rate: MTU3 clock rate
+ * @user_count: MTU3 usage count
+ * @enable_count: MTU3 enable count
+ * @prescale: MTU3 prescale
+ * @channel_data: MTU3 pwm channel data
+ */
+
+struct rz_mtu3_pwm_chip {
+ struct pwm_chip chip;
+ struct clk *clk;
+ struct mutex lock;
+ unsigned long rate;
+ u32 user_count[RZ_MTU3_MAX_HW_CHANNELS];
+ u32 enable_count[RZ_MTU3_MAX_HW_CHANNELS];
+ u8 prescale[RZ_MTU3_MAX_HW_CHANNELS];
+ struct rz_mtu3_pwm_channel channel_data[RZ_MTU3_MAX_HW_CHANNELS];
+};
+
+/*
+ * The MTU channels are {0..4, 6, 7} and the number of IO on MTU1
+ * and MTU2 channel is 1 compared to 2 on others.
+ */
+static const struct rz_mtu3_channel_io_map channel_map[] = {
+ { 0, 2 }, { 2, 1 }, { 3, 1 }, { 4, 2 }, { 6, 2 }, { 8, 2 }, { 10, 2 }
+};
+
+static inline struct rz_mtu3_pwm_chip *to_rz_mtu3_pwm_chip(struct pwm_chip *chip)
+{
+ return container_of(chip, struct rz_mtu3_pwm_chip, chip);
+}
+
+static void rz_mtu3_pwm_read_tgr_registers(struct rz_mtu3_pwm_channel *priv,
+ u16 reg_pv_offset, u16 *pv_val,
+ u16 reg_dc_offset, u16 *dc_val)
+{
+ *pv_val = rz_mtu3_16bit_ch_read(priv->mtu, reg_pv_offset);
+ *dc_val = rz_mtu3_16bit_ch_read(priv->mtu, reg_dc_offset);
+}
+
+static void rz_mtu3_pwm_write_tgr_registers(struct rz_mtu3_pwm_channel *priv,
+ u16 reg_pv_offset, u16 pv_val,
+ u16 reg_dc_offset, u16 dc_val)
+{
+ rz_mtu3_16bit_ch_write(priv->mtu, reg_pv_offset, pv_val);
+ rz_mtu3_16bit_ch_write(priv->mtu, reg_dc_offset, dc_val);
+}
+
+static u8 rz_mtu3_pwm_calculate_prescale(struct rz_mtu3_pwm_chip *rz_mtu3,
+ u64 period_cycles)
+{
+ u32 prescaled_period_cycles;
+ u8 prescale;
+
+ /*
+ * Supported prescale values are 1, 4, 16 and 64.
+ * TODO: Support prescale values 2, 8, 32, 256 and 1024.
+ */
+ prescaled_period_cycles = period_cycles >> 16;
+ if (prescaled_period_cycles >= 16)
+ prescale = 3;
+ else
+ prescale = (fls(prescaled_period_cycles) + 1) / 2;
+
+ return prescale;
+}
+
+static struct rz_mtu3_pwm_channel *
+rz_mtu3_get_channel(struct rz_mtu3_pwm_chip *rz_mtu3_pwm, u32 hwpwm)
+{
+ struct rz_mtu3_pwm_channel *priv = rz_mtu3_pwm->channel_data;
+ unsigned int ch;
+
+ for (ch = 0; ch < RZ_MTU3_MAX_HW_CHANNELS; ch++, priv++) {
+ if (priv->map->base_pwm_number + priv->map->num_channel_ios > hwpwm)
+ break;
+ }
+
+ return priv;
+}
+
+static bool rz_mtu3_pwm_is_ch_enabled(struct rz_mtu3_pwm_chip *rz_mtu3_pwm,
+ u32 hwpwm)
+{
+ struct rz_mtu3_pwm_channel *priv;
+ bool is_channel_en;
+ u8 val;
+
+ priv = rz_mtu3_get_channel(rz_mtu3_pwm, hwpwm);
+ is_channel_en = rz_mtu3_is_enabled(priv->mtu);
+ if (!is_channel_en)
+ return false;
+
+ if (priv->map->base_pwm_number == hwpwm)
+ val = rz_mtu3_8bit_ch_read(priv->mtu, RZ_MTU3_TIORH);
+ else
+ val = rz_mtu3_8bit_ch_read(priv->mtu, RZ_MTU3_TIORL);
+
+ return val & RZ_MTU3_TIOR_IOA;
+}
+
+static int rz_mtu3_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip);
+ struct rz_mtu3_pwm_channel *priv;
+ bool is_mtu3_channel_available;
+ u32 ch;
+
+ priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm);
+ ch = priv - rz_mtu3_pwm->channel_data;
+
+ mutex_lock(&rz_mtu3_pwm->lock);
+ /*
+ * Each channel must be requested only once, so if the channel
+ * serves two PWMs and the other is already requested, skip over
+ * rz_mtu3_request_channel()
+ */
+ if (!rz_mtu3_pwm->user_count[ch]) {
+ is_mtu3_channel_available = rz_mtu3_request_channel(priv->mtu);
+ if (!is_mtu3_channel_available) {
+ mutex_unlock(&rz_mtu3_pwm->lock);
+ return -EBUSY;
+ }
+ }
+
+ rz_mtu3_pwm->user_count[ch]++;
+ mutex_unlock(&rz_mtu3_pwm->lock);
+
+ return 0;
+}
+
+static void rz_mtu3_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip);
+ struct rz_mtu3_pwm_channel *priv;
+ u32 ch;
+
+ priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm);
+ ch = priv - rz_mtu3_pwm->channel_data;
+
+ mutex_lock(&rz_mtu3_pwm->lock);
+ rz_mtu3_pwm->user_count[ch]--;
+ if (!rz_mtu3_pwm->user_count[ch])
+ rz_mtu3_release_channel(priv->mtu);
+
+ mutex_unlock(&rz_mtu3_pwm->lock);
+}
+
+static int rz_mtu3_pwm_enable(struct rz_mtu3_pwm_chip *rz_mtu3_pwm,
+ struct pwm_device *pwm)
+{
+ struct rz_mtu3_pwm_channel *priv;
+ u32 ch;
+ u8 val;
+ int rc;
+
+ rc = pm_runtime_resume_and_get(rz_mtu3_pwm->chip.dev);
+ if (rc)
+ return rc;
+
+ priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm);
+ ch = priv - rz_mtu3_pwm->channel_data;
+ val = RZ_MTU3_TIOR_OC_IOB_TOGGLE | RZ_MTU3_TIOR_OC_IOA_H_COMP_MATCH;
+
+ rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_MD_PWMMODE1);
+ if (priv->map->base_pwm_number == pwm->hwpwm)
+ rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TIORH, val);
+ else
+ rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TIORL, val);
+
+ mutex_lock(&rz_mtu3_pwm->lock);
+ if (!rz_mtu3_pwm->enable_count[ch])
+ rz_mtu3_enable(priv->mtu);
+
+ rz_mtu3_pwm->enable_count[ch]++;
+ mutex_unlock(&rz_mtu3_pwm->lock);
+
+ return 0;
+}
+
+static void rz_mtu3_pwm_disable(struct rz_mtu3_pwm_chip *rz_mtu3_pwm,
+ struct pwm_device *pwm)
+{
+ struct rz_mtu3_pwm_channel *priv;
+ u32 ch;
+
+ priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm);
+ ch = priv - rz_mtu3_pwm->channel_data;
+
+ /* Disable output pins of MTU3 channel */
+ if (priv->map->base_pwm_number == pwm->hwpwm)
+ rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TIORH, RZ_MTU3_TIOR_OC_RETAIN);
+ else
+ rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TIORL, RZ_MTU3_TIOR_OC_RETAIN);
+
+ mutex_lock(&rz_mtu3_pwm->lock);
+ rz_mtu3_pwm->enable_count[ch]--;
+ if (!rz_mtu3_pwm->enable_count[ch])
+ rz_mtu3_disable(priv->mtu);
+
+ mutex_unlock(&rz_mtu3_pwm->lock);
+
+ pm_runtime_put_sync(rz_mtu3_pwm->chip.dev);
+}
+
+static int rz_mtu3_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip);
+ int rc;
+
+ rc = pm_runtime_resume_and_get(chip->dev);
+ if (rc)
+ return rc;
+
+ state->enabled = rz_mtu3_pwm_is_ch_enabled(rz_mtu3_pwm, pwm->hwpwm);
+ if (state->enabled) {
+ struct rz_mtu3_pwm_channel *priv;
+ u8 prescale, val;
+ u16 dc, pv;
+ u64 tmp;
+
+ priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm);
+ if (priv->map->base_pwm_number == pwm->hwpwm)
+ rz_mtu3_pwm_read_tgr_registers(priv, RZ_MTU3_TGRA, &pv,
+ RZ_MTU3_TGRB, &dc);
+ else
+ rz_mtu3_pwm_read_tgr_registers(priv, RZ_MTU3_TGRC, &pv,
+ RZ_MTU3_TGRD, &dc);
+
+ val = rz_mtu3_8bit_ch_read(priv->mtu, RZ_MTU3_TCR);
+ prescale = FIELD_GET(RZ_MTU3_TCR_TPCS, val);
+
+ /* With prescale <= 7 and pv <= 0xffff this doesn't overflow. */
+ tmp = NSEC_PER_SEC * (u64)pv << (2 * prescale);
+ state->period = DIV_ROUND_UP_ULL(tmp, rz_mtu3_pwm->rate);
+ tmp = NSEC_PER_SEC * (u64)dc << (2 * prescale);
+ state->duty_cycle = DIV_ROUND_UP_ULL(tmp, rz_mtu3_pwm->rate);
+
+ if (state->duty_cycle > state->period)
+ state->duty_cycle = state->period;
+ }
+
+ state->polarity = PWM_POLARITY_NORMAL;
+ pm_runtime_put(chip->dev);
+
+ return 0;
+}
+
+static u16 rz_mtu3_pwm_calculate_pv_or_dc(u64 period_or_duty_cycle, u8 prescale)
+{
+ return min(period_or_duty_cycle >> (2 * prescale), (u64)U16_MAX);
+}
+
+static int rz_mtu3_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip);
+ struct rz_mtu3_pwm_channel *priv;
+ u64 period_cycles;
+ u64 duty_cycles;
+ u8 prescale;
+ u16 pv, dc;
+ u8 val;
+ u32 ch;
+
+ priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm);
+ ch = priv - rz_mtu3_pwm->channel_data;
+
+ period_cycles = mul_u64_u32_div(state->period, rz_mtu3_pwm->rate,
+ NSEC_PER_SEC);
+ prescale = rz_mtu3_pwm_calculate_prescale(rz_mtu3_pwm, period_cycles);
+
+ /*
+ * Prescalar is shared by multiple channels, so prescale can
+ * NOT be modified when there are multiple channels in use with
+ * different settings. Modify prescalar if other PWM is off or handle
+ * it, if current prescale value is less than the one we want to set.
+ */
+ if (rz_mtu3_pwm->enable_count[ch] > 1) {
+ if (rz_mtu3_pwm->prescale[ch] > prescale)
+ return -EBUSY;
+
+ prescale = rz_mtu3_pwm->prescale[ch];
+ }
+
+ pv = rz_mtu3_pwm_calculate_pv_or_dc(period_cycles, prescale);
+
+ duty_cycles = mul_u64_u32_div(state->duty_cycle, rz_mtu3_pwm->rate,
+ NSEC_PER_SEC);
+ dc = rz_mtu3_pwm_calculate_pv_or_dc(duty_cycles, prescale);
+
+ /*
+ * If the PWM channel is disabled, make sure to turn on the clock
+ * before writing the register.
+ */
+ if (!pwm->state.enabled) {
+ int rc;
+
+ rc = pm_runtime_resume_and_get(chip->dev);
+ if (rc)
+ return rc;
+ }
+
+ val = RZ_MTU3_TCR_CKEG_RISING | prescale;
+
+ /* Counter must be stopped while updating TCR register */
+ if (rz_mtu3_pwm->prescale[ch] != prescale && rz_mtu3_pwm->enable_count[ch])
+ rz_mtu3_disable(priv->mtu);
+
+ if (priv->map->base_pwm_number == pwm->hwpwm) {
+ rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TCR,
+ RZ_MTU3_TCR_CCLR_TGRA | val);
+ rz_mtu3_pwm_write_tgr_registers(priv, RZ_MTU3_TGRA, pv,
+ RZ_MTU3_TGRB, dc);
+ } else {
+ rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TCR,
+ RZ_MTU3_TCR_CCLR_TGRC | val);
+ rz_mtu3_pwm_write_tgr_registers(priv, RZ_MTU3_TGRC, pv,
+ RZ_MTU3_TGRD, dc);
+ }
+
+ if (rz_mtu3_pwm->prescale[ch] != prescale) {
+ /*
+ * Prescalar is shared by multiple channels, we cache the
+ * prescalar value from first enabled channel and use the same
+ * value for both channels.
+ */
+ rz_mtu3_pwm->prescale[ch] = prescale;
+
+ if (rz_mtu3_pwm->enable_count[ch])
+ rz_mtu3_enable(priv->mtu);
+ }
+
+ /* If the PWM is not enabled, turn the clock off again to save power. */
+ if (!pwm->state.enabled)
+ pm_runtime_put(chip->dev);
+
+ return 0;
+}
+
+static int rz_mtu3_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip);
+ bool enabled = pwm->state.enabled;
+ int ret;
+
+ if (state->polarity != PWM_POLARITY_NORMAL)
+ return -EINVAL;
+
+ if (!state->enabled) {
+ if (enabled)
+ rz_mtu3_pwm_disable(rz_mtu3_pwm, pwm);
+
+ return 0;
+ }
+
+ mutex_lock(&rz_mtu3_pwm->lock);
+ ret = rz_mtu3_pwm_config(chip, pwm, state);
+ mutex_unlock(&rz_mtu3_pwm->lock);
+ if (ret)
+ return ret;
+
+ if (!enabled)
+ ret = rz_mtu3_pwm_enable(rz_mtu3_pwm, pwm);
+
+ return ret;
+}
+
+static const struct pwm_ops rz_mtu3_pwm_ops = {
+ .request = rz_mtu3_pwm_request,
+ .free = rz_mtu3_pwm_free,
+ .get_state = rz_mtu3_pwm_get_state,
+ .apply = rz_mtu3_pwm_apply,
+ .owner = THIS_MODULE,
+};
+
+static int rz_mtu3_pwm_pm_runtime_suspend(struct device *dev)
+{
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(rz_mtu3_pwm->clk);
+
+ return 0;
+}
+
+static int rz_mtu3_pwm_pm_runtime_resume(struct device *dev)
+{
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = dev_get_drvdata(dev);
+
+ return clk_prepare_enable(rz_mtu3_pwm->clk);
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(rz_mtu3_pwm_pm_ops,
+ rz_mtu3_pwm_pm_runtime_suspend,
+ rz_mtu3_pwm_pm_runtime_resume, NULL);
+
+static void rz_mtu3_pwm_pm_disable(void *data)
+{
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = data;
+
+ clk_rate_exclusive_put(rz_mtu3_pwm->clk);
+ pm_runtime_disable(rz_mtu3_pwm->chip.dev);
+ pm_runtime_set_suspended(rz_mtu3_pwm->chip.dev);
+}
+
+static int rz_mtu3_pwm_probe(struct platform_device *pdev)
+{
+ struct rz_mtu3 *parent_ddata = dev_get_drvdata(pdev->dev.parent);
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm;
+ struct device *dev = &pdev->dev;
+ unsigned int i, j = 0;
+ int ret;
+
+ rz_mtu3_pwm = devm_kzalloc(&pdev->dev, sizeof(*rz_mtu3_pwm), GFP_KERNEL);
+ if (!rz_mtu3_pwm)
+ return -ENOMEM;
+
+ rz_mtu3_pwm->clk = parent_ddata->clk;
+
+ for (i = 0; i < RZ_MTU_NUM_CHANNELS; i++) {
+ if (i == RZ_MTU3_CHAN_5 || i == RZ_MTU3_CHAN_8)
+ continue;
+
+ rz_mtu3_pwm->channel_data[j].mtu = &parent_ddata->channels[i];
+ rz_mtu3_pwm->channel_data[j].mtu->dev = dev;
+ rz_mtu3_pwm->channel_data[j].map = &channel_map[j];
+ j++;
+ }
+
+ mutex_init(&rz_mtu3_pwm->lock);
+ platform_set_drvdata(pdev, rz_mtu3_pwm);
+ ret = clk_prepare_enable(rz_mtu3_pwm->clk);
+ if (ret)
+ return dev_err_probe(dev, ret, "Clock enable failed\n");
+
+ clk_rate_exclusive_get(rz_mtu3_pwm->clk);
+
+ rz_mtu3_pwm->rate = clk_get_rate(rz_mtu3_pwm->clk);
+ /*
+ * Refuse clk rates > 1 GHz to prevent overflow later for computing
+ * period and duty cycle.
+ */
+ if (rz_mtu3_pwm->rate > NSEC_PER_SEC) {
+ ret = -EINVAL;
+ clk_rate_exclusive_put(rz_mtu3_pwm->clk);
+ goto disable_clock;
+ }
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ rz_mtu3_pwm->chip.dev = &pdev->dev;
+ ret = devm_add_action_or_reset(&pdev->dev, rz_mtu3_pwm_pm_disable,
+ rz_mtu3_pwm);
+ if (ret < 0)
+ return ret;
+
+ rz_mtu3_pwm->chip.ops = &rz_mtu3_pwm_ops;
+ rz_mtu3_pwm->chip.npwm = RZ_MTU3_MAX_PWM_CHANNELS;
+ ret = devm_pwmchip_add(&pdev->dev, &rz_mtu3_pwm->chip);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n");
+
+ pm_runtime_idle(&pdev->dev);
+
+ return 0;
+
+disable_clock:
+ clk_disable_unprepare(rz_mtu3_pwm->clk);
+ return ret;
+}
+
+static struct platform_driver rz_mtu3_pwm_driver = {
+ .driver = {
+ .name = "pwm-rz-mtu3",
+ .pm = pm_ptr(&rz_mtu3_pwm_pm_ops),
+ },
+ .probe = rz_mtu3_pwm_probe,
+};
+module_platform_driver(rz_mtu3_pwm_driver);
+
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
+MODULE_ALIAS("platform:pwm-rz-mtu3");
+MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a PWM Timer Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c
index 5b0574f635f6..ae49d67ab2b1 100644
--- a/drivers/pwm/pwm-sifive.c
+++ b/drivers/pwm/pwm-sifive.c
@@ -244,12 +244,12 @@ static int pwm_sifive_probe(struct platform_device *pdev)
if (IS_ERR(ddata->regs))
return PTR_ERR(ddata->regs);
- ddata->clk = devm_clk_get(dev, NULL);
+ ddata->clk = devm_clk_get_prepared(dev, NULL);
if (IS_ERR(ddata->clk))
return dev_err_probe(dev, PTR_ERR(ddata->clk),
"Unable to find controller clock\n");
- ret = clk_prepare_enable(ddata->clk);
+ ret = clk_enable(ddata->clk);
if (ret) {
dev_err(dev, "failed to enable clock for pwm: %d\n", ret);
return ret;
@@ -308,7 +308,6 @@ disable_clk:
clk_disable(ddata->clk);
--enabled_clks;
}
- clk_unprepare(ddata->clk);
return ret;
}
@@ -327,8 +326,6 @@ static void pwm_sifive_remove(struct platform_device *dev)
if (pwm->state.enabled)
clk_disable(ddata->clk);
}
-
- clk_unprepare(ddata->clk);
}
static const struct of_device_id pwm_sifive_of_match[] = {
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index 1a106ec32939..8d1254761e4d 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -424,6 +424,13 @@ static int pwm_class_resume_npwm(struct device *parent, unsigned int npwm)
if (!export)
continue;
+ /* If pwmchip was not enabled before suspend, do nothing. */
+ if (!export->suspend.enabled) {
+ /* release lock taken in pwm_class_get_state */
+ mutex_unlock(&export->lock);
+ continue;
+ }
+
state.enabled = export->suspend.enabled;
ret = pwm_class_apply_state(export, pwm, &state);
if (ret < 0)
@@ -448,7 +455,17 @@ static int pwm_class_suspend(struct device *parent)
if (!export)
continue;
+ /*
+ * If pwmchip was not enabled before suspend, save
+ * state for resume time and do nothing else.
+ */
export->suspend = state;
+ if (!state.enabled) {
+ /* release lock taken in pwm_class_get_state */
+ mutex_unlock(&export->lock);
+ continue;
+ }
+
state.enabled = false;
ret = pwm_class_apply_state(export, pwm, &state);
if (ret < 0) {
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 2c2405024ace..08d33290296b 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -556,6 +556,17 @@ config REGULATOR_MAX597X
The MAX5970/5978 is a smart switch with no output regulation, but
fault protection and voltage and current monitoring capabilities.
+config REGULATOR_MAX77541
+ tristate "Analog Devices MAX77541/77540 Regulator"
+ depends on MFD_MAX77541
+ help
+ This driver controls a Analog Devices MAX77541/77540 regulators
+ via I2C bus. Both MAX77540 and MAX77541 are dual-phase
+ high-efficiency buck converter. Say Y here to
+ enable the regulator driver.
+ Say M here if you want to include support for the regulator as a
+ module.
+
config REGULATOR_MAX77620
tristate "Maxim 77620/MAX20024 voltage regulator"
depends on MFD_MAX77620 || COMPILE_TEST
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index ebfa75379c20..15e0d614ff66 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o
obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o
obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
obj-$(CONFIG_REGULATOR_MAX597X) += max597x-regulator.o
+obj-$(CONFIG_REGULATOR_MAX77541) += max77541-regulator.o
obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o
obj-$(CONFIG_REGULATOR_MAX77650) += max77650-regulator.o
obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
diff --git a/drivers/regulator/max77541-regulator.c b/drivers/regulator/max77541-regulator.c
new file mode 100644
index 000000000000..2976f9cb3e26
--- /dev/null
+++ b/drivers/regulator/max77541-regulator.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022 Analog Devices, Inc.
+ * ADI Regulator driver for the MAX77540 and MAX77541
+ */
+
+#include <linux/mfd/max77541.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+static const struct regulator_ops max77541_buck_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_pickable_linear_range,
+ .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap,
+};
+
+static const struct linear_range max77540_buck_ranges[] = {
+ /* Ranges when VOLT_SEL bits are 0x00 */
+ REGULATOR_LINEAR_RANGE(500000, 0x00, 0x8B, 5000),
+ REGULATOR_LINEAR_RANGE(1200000, 0x8C, 0xFF, 0),
+ /* Ranges when VOLT_SEL bits are 0x40 */
+ REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x8B, 10000),
+ REGULATOR_LINEAR_RANGE(2400000, 0x8C, 0xFF, 0),
+ /* Ranges when VOLT_SEL bits are 0x80 */
+ REGULATOR_LINEAR_RANGE(2000000, 0x00, 0x9F, 20000),
+ REGULATOR_LINEAR_RANGE(5200000, 0xA0, 0xFF, 0),
+};
+
+static const struct linear_range max77541_buck_ranges[] = {
+ /* Ranges when VOLT_SEL bits are 0x00 */
+ REGULATOR_LINEAR_RANGE(300000, 0x00, 0xB3, 5000),
+ REGULATOR_LINEAR_RANGE(1200000, 0xB4, 0xFF, 0),
+ /* Ranges when VOLT_SEL bits are 0x40 */
+ REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x8B, 10000),
+ REGULATOR_LINEAR_RANGE(2400000, 0x8C, 0xFF, 0),
+ /* Ranges when VOLT_SEL bits are 0x80 */
+ REGULATOR_LINEAR_RANGE(2000000, 0x00, 0x9F, 20000),
+ REGULATOR_LINEAR_RANGE(5200000, 0xA0, 0xFF, 0),
+};
+
+static const unsigned int max77541_buck_volt_range_sel[] = {
+ 0x00, 0x00, 0x40, 0x40, 0x80, 0x80,
+};
+
+enum max77541_regulators {
+ MAX77541_BUCK1 = 1,
+ MAX77541_BUCK2,
+};
+
+#define MAX77540_BUCK(_id, _ops) \
+ { .id = MAX77541_BUCK ## _id, \
+ .name = "buck"#_id, \
+ .of_match = "buck"#_id, \
+ .regulators_node = "regulators", \
+ .enable_reg = MAX77541_REG_EN_CTRL, \
+ .enable_mask = MAX77541_BIT_M ## _id ## _EN, \
+ .ops = &(_ops), \
+ .type = REGULATOR_VOLTAGE, \
+ .linear_ranges = max77540_buck_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(max77540_buck_ranges), \
+ .vsel_reg = MAX77541_REG_M ## _id ## _VOUT, \
+ .vsel_mask = MAX77541_BITS_MX_VOUT, \
+ .vsel_range_reg = MAX77541_REG_M ## _id ## _CFG1, \
+ .vsel_range_mask = MAX77541_BITS_MX_CFG1_RNG, \
+ .linear_range_selectors = max77541_buck_volt_range_sel, \
+ .owner = THIS_MODULE, \
+ }
+
+#define MAX77541_BUCK(_id, _ops) \
+ { .id = MAX77541_BUCK ## _id, \
+ .name = "buck"#_id, \
+ .of_match = "buck"#_id, \
+ .regulators_node = "regulators", \
+ .enable_reg = MAX77541_REG_EN_CTRL, \
+ .enable_mask = MAX77541_BIT_M ## _id ## _EN, \
+ .ops = &(_ops), \
+ .type = REGULATOR_VOLTAGE, \
+ .linear_ranges = max77541_buck_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(max77541_buck_ranges), \
+ .vsel_reg = MAX77541_REG_M ## _id ## _VOUT, \
+ .vsel_mask = MAX77541_BITS_MX_VOUT, \
+ .vsel_range_reg = MAX77541_REG_M ## _id ## _CFG1, \
+ .vsel_range_mask = MAX77541_BITS_MX_CFG1_RNG, \
+ .linear_range_selectors = max77541_buck_volt_range_sel, \
+ .owner = THIS_MODULE, \
+ }
+
+static const struct regulator_desc max77540_regulators_desc[] = {
+ MAX77540_BUCK(1, max77541_buck_ops),
+ MAX77540_BUCK(2, max77541_buck_ops),
+};
+
+static const struct regulator_desc max77541_regulators_desc[] = {
+ MAX77541_BUCK(1, max77541_buck_ops),
+ MAX77541_BUCK(2, max77541_buck_ops),
+};
+
+static int max77541_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_config config = {};
+ const struct regulator_desc *desc;
+ struct device *dev = &pdev->dev;
+ struct regulator_dev *rdev;
+ struct max77541 *max77541 = dev_get_drvdata(dev->parent);
+ unsigned int i;
+
+ config.dev = dev->parent;
+
+ switch (max77541->id) {
+ case MAX77540:
+ desc = max77540_regulators_desc;
+ break;
+ case MAX77541:
+ desc = max77541_regulators_desc;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < MAX77541_MAX_REGULATORS; i++) {
+ rdev = devm_regulator_register(dev, &desc[i], &config);
+ if (IS_ERR(rdev))
+ return dev_err_probe(dev, PTR_ERR(rdev),
+ "Failed to register regulator\n");
+ }
+
+ return 0;
+}
+
+static const struct platform_device_id max77541_regulator_platform_id[] = {
+ { "max77540-regulator" },
+ { "max77541-regulator" },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, max77541_regulator_platform_id);
+
+static struct platform_driver max77541_regulator_driver = {
+ .driver = {
+ .name = "max77541-regulator",
+ },
+ .probe = max77541_regulator_probe,
+ .id_table = max77541_regulator_platform_id,
+};
+module_platform_driver(max77541_regulator_driver);
+
+MODULE_AUTHOR("Okan Sahin <Okan.Sahin@analog.com>");
+MODULE_DESCRIPTION("MAX77540/MAX77541 regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index a850e9f486dd..48845dc8fa85 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -313,7 +313,7 @@ config ST_SLIM_REMOTEPROC
config STM32_RPROC
tristate "STM32 remoteproc support"
- depends on ARCH_STM32
+ depends on ARCH_STM32 || COMPILE_TEST
depends on REMOTEPROC
select MAILBOX
help
diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c
index 768217f0f5cd..9041a0e07fb2 100644
--- a/drivers/remoteproc/da8xx_remoteproc.c
+++ b/drivers/remoteproc/da8xx_remoteproc.c
@@ -357,7 +357,7 @@ free_mem:
return ret;
}
-static int da8xx_rproc_remove(struct platform_device *pdev)
+static void da8xx_rproc_remove(struct platform_device *pdev)
{
struct rproc *rproc = platform_get_drvdata(pdev);
struct da8xx_rproc *drproc = rproc->priv;
@@ -374,8 +374,6 @@ static int da8xx_rproc_remove(struct platform_device *pdev)
rproc_free(rproc);
if (dev->of_node)
of_reserved_mem_device_release(dev);
-
- return 0;
}
static const struct of_device_id davinci_rproc_of_match[] __maybe_unused = {
@@ -386,7 +384,7 @@ MODULE_DEVICE_TABLE(of, davinci_rproc_of_match);
static struct platform_driver da8xx_rproc_driver = {
.probe = da8xx_rproc_probe,
- .remove = da8xx_rproc_remove,
+ .remove_new = da8xx_rproc_remove,
.driver = {
.name = "davinci-rproc",
.of_match_table = of_match_ptr(davinci_rproc_of_match),
diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
index cab06dbf37fb..d95fa5586189 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -1161,7 +1161,7 @@ err_put_rproc:
return ret;
}
-static int imx_dsp_rproc_remove(struct platform_device *pdev)
+static void imx_dsp_rproc_remove(struct platform_device *pdev)
{
struct rproc *rproc = platform_get_drvdata(pdev);
struct imx_dsp_rproc *priv = rproc->priv;
@@ -1170,8 +1170,6 @@ static int imx_dsp_rproc_remove(struct platform_device *pdev)
rproc_del(rproc);
imx_dsp_detach_pm_domains(priv);
rproc_free(rproc);
-
- return 0;
}
/* pm runtime functions */
@@ -1243,7 +1241,7 @@ out:
release_firmware(fw);
}
-static __maybe_unused int imx_dsp_suspend(struct device *dev)
+static int imx_dsp_suspend(struct device *dev)
{
struct rproc *rproc = dev_get_drvdata(dev);
struct imx_dsp_rproc *priv = rproc->priv;
@@ -1278,7 +1276,7 @@ out:
return pm_runtime_force_suspend(dev);
}
-static __maybe_unused int imx_dsp_resume(struct device *dev)
+static int imx_dsp_resume(struct device *dev)
{
struct rproc *rproc = dev_get_drvdata(dev);
int ret = 0;
@@ -1312,9 +1310,8 @@ err:
}
static const struct dev_pm_ops imx_dsp_rproc_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(imx_dsp_suspend, imx_dsp_resume)
- SET_RUNTIME_PM_OPS(imx_dsp_runtime_suspend,
- imx_dsp_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(imx_dsp_suspend, imx_dsp_resume)
+ RUNTIME_PM_OPS(imx_dsp_runtime_suspend, imx_dsp_runtime_resume, NULL)
};
static const struct of_device_id imx_dsp_rproc_of_match[] = {
@@ -1328,11 +1325,11 @@ MODULE_DEVICE_TABLE(of, imx_dsp_rproc_of_match);
static struct platform_driver imx_dsp_rproc_driver = {
.probe = imx_dsp_rproc_probe,
- .remove = imx_dsp_rproc_remove,
+ .remove_new = imx_dsp_rproc_remove,
.driver = {
.name = "imx-dsp-rproc",
.of_match_table = imx_dsp_rproc_of_match,
- .pm = &imx_dsp_rproc_pm_ops,
+ .pm = pm_ptr(&imx_dsp_rproc_pm_ops),
},
};
module_platform_driver(imx_dsp_rproc_driver);
diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 0ab840dc7e97..f9874fc5a80f 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -1112,7 +1112,7 @@ err_put_rproc:
return ret;
}
-static int imx_rproc_remove(struct platform_device *pdev)
+static void imx_rproc_remove(struct platform_device *pdev)
{
struct rproc *rproc = platform_get_drvdata(pdev);
struct imx_rproc *priv = rproc->priv;
@@ -1123,8 +1123,6 @@ static int imx_rproc_remove(struct platform_device *pdev)
imx_rproc_free_mbox(rproc);
destroy_workqueue(priv->workqueue);
rproc_free(rproc);
-
- return 0;
}
static const struct of_device_id imx_rproc_of_match[] = {
@@ -1145,7 +1143,7 @@ MODULE_DEVICE_TABLE(of, imx_rproc_of_match);
static struct platform_driver imx_rproc_driver = {
.probe = imx_rproc_probe,
- .remove = imx_rproc_remove,
+ .remove_new = imx_rproc_remove,
.driver = {
.name = "imx-rproc",
.of_match_table = imx_rproc_of_match,
diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c
index 95b39741925d..7e57b90bcaf8 100644
--- a/drivers/remoteproc/keystone_remoteproc.c
+++ b/drivers/remoteproc/keystone_remoteproc.c
@@ -476,7 +476,7 @@ free_rproc:
return ret;
}
-static int keystone_rproc_remove(struct platform_device *pdev)
+static void keystone_rproc_remove(struct platform_device *pdev)
{
struct keystone_rproc *ksproc = platform_get_drvdata(pdev);
@@ -486,8 +486,6 @@ static int keystone_rproc_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
rproc_free(ksproc->rproc);
of_reserved_mem_device_release(&pdev->dev);
-
- return 0;
}
static const struct of_device_id keystone_rproc_of_match[] = {
@@ -501,7 +499,7 @@ MODULE_DEVICE_TABLE(of, keystone_rproc_of_match);
static struct platform_driver keystone_rproc_driver = {
.probe = keystone_rproc_probe,
- .remove = keystone_rproc_remove,
+ .remove_new = keystone_rproc_remove,
.driver = {
.name = "keystone-rproc",
.of_match_table = keystone_rproc_of_match,
diff --git a/drivers/remoteproc/meson_mx_ao_arc.c b/drivers/remoteproc/meson_mx_ao_arc.c
index 462cddab6518..f6744b538323 100644
--- a/drivers/remoteproc/meson_mx_ao_arc.c
+++ b/drivers/remoteproc/meson_mx_ao_arc.c
@@ -228,15 +228,13 @@ err_free_genpool:
return ret;
}
-static int meson_mx_ao_arc_rproc_remove(struct platform_device *pdev)
+static void meson_mx_ao_arc_rproc_remove(struct platform_device *pdev)
{
struct rproc *rproc = platform_get_drvdata(pdev);
struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv;
rproc_del(rproc);
gen_pool_free(priv->sram_pool, priv->sram_va, priv->sram_size);
-
- return 0;
}
static const struct of_device_id meson_mx_ao_arc_rproc_match[] = {
@@ -248,7 +246,7 @@ MODULE_DEVICE_TABLE(of, meson_mx_ao_arc_rproc_match);
static struct platform_driver meson_mx_ao_arc_rproc_driver = {
.probe = meson_mx_ao_arc_rproc_probe,
- .remove = meson_mx_ao_arc_rproc_remove,
+ .remove_new = meson_mx_ao_arc_rproc_remove,
.driver = {
.name = "meson-mx-ao-arc-rproc",
.of_match_table = meson_mx_ao_arc_rproc_match,
diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
index e1d93e63d7df..dcc94ee2458d 100644
--- a/drivers/remoteproc/mtk_scp.c
+++ b/drivers/remoteproc/mtk_scp.c
@@ -913,7 +913,7 @@ release_dev_mem:
return ret;
}
-static int scp_remove(struct platform_device *pdev)
+static void scp_remove(struct platform_device *pdev)
{
struct mtk_scp *scp = platform_get_drvdata(pdev);
int i;
@@ -925,8 +925,6 @@ static int scp_remove(struct platform_device *pdev)
for (i = 0; i < SCP_IPI_MAX; i++)
mutex_destroy(&scp->ipi_desc[i].lock);
mutex_destroy(&scp->send_lock);
-
- return 0;
}
static const struct mtk_scp_of_data mt8183_of_data = {
@@ -1003,7 +1001,7 @@ MODULE_DEVICE_TABLE(of, mtk_scp_of_match);
static struct platform_driver mtk_scp_driver = {
.probe = scp_probe,
- .remove = scp_remove,
+ .remove_new = scp_remove,
.driver = {
.name = "mtk-scp",
.of_match_table = mtk_scp_of_match,
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
index 430fab0266ed..82ed90f03d91 100644
--- a/drivers/remoteproc/omap_remoteproc.c
+++ b/drivers/remoteproc/omap_remoteproc.c
@@ -1363,15 +1363,13 @@ free_rproc:
return ret;
}
-static int omap_rproc_remove(struct platform_device *pdev)
+static void omap_rproc_remove(struct platform_device *pdev)
{
struct rproc *rproc = platform_get_drvdata(pdev);
rproc_del(rproc);
rproc_free(rproc);
of_reserved_mem_device_release(&pdev->dev);
-
- return 0;
}
static const struct dev_pm_ops omap_rproc_pm_ops = {
@@ -1382,7 +1380,7 @@ static const struct dev_pm_ops omap_rproc_pm_ops = {
static struct platform_driver omap_rproc_driver = {
.probe = omap_rproc_probe,
- .remove = omap_rproc_remove,
+ .remove_new = omap_rproc_remove,
.driver = {
.name = "omap-rproc",
.pm = &omap_rproc_pm_ops,
diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
index 095f66130f48..2874c8d324f7 100644
--- a/drivers/remoteproc/pru_rproc.c
+++ b/drivers/remoteproc/pru_rproc.c
@@ -82,21 +82,6 @@ enum pru_iomem {
};
/**
- * enum pru_type - PRU core type identifier
- *
- * @PRU_TYPE_PRU: Programmable Real-time Unit
- * @PRU_TYPE_RTU: Auxiliary Programmable Real-Time Unit
- * @PRU_TYPE_TX_PRU: Transmit Programmable Real-Time Unit
- * @PRU_TYPE_MAX: just keep this one at the end
- */
-enum pru_type {
- PRU_TYPE_PRU = 0,
- PRU_TYPE_RTU,
- PRU_TYPE_TX_PRU,
- PRU_TYPE_MAX,
-};
-
-/**
* struct pru_private_data - device data for a PRU core
* @type: type of the PRU core (PRU, RTU, Tx_PRU)
* @is_k3: flag used to identify the need for special load handling
@@ -1071,14 +1056,12 @@ static int pru_rproc_probe(struct platform_device *pdev)
return 0;
}
-static int pru_rproc_remove(struct platform_device *pdev)
+static void pru_rproc_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rproc *rproc = platform_get_drvdata(pdev);
dev_dbg(dev, "%s: removing rproc %s\n", __func__, rproc->name);
-
- return 0;
}
static const struct pru_private_data pru_data = {
@@ -1126,7 +1109,7 @@ static struct platform_driver pru_rproc_driver = {
.suppress_bind_attrs = true,
},
.probe = pru_rproc_probe,
- .remove = pru_rproc_remove,
+ .remove_new = pru_rproc_remove,
};
module_platform_driver(pru_rproc_driver);
diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
index d546ab9dc141..6777a3bd6226 100644
--- a/drivers/remoteproc/qcom_q6v5_adsp.c
+++ b/drivers/remoteproc/qcom_q6v5_adsp.c
@@ -763,7 +763,7 @@ free_rproc:
return ret;
}
-static int adsp_remove(struct platform_device *pdev)
+static void adsp_remove(struct platform_device *pdev)
{
struct qcom_adsp *adsp = platform_get_drvdata(pdev);
@@ -775,8 +775,6 @@ static int adsp_remove(struct platform_device *pdev)
qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
qcom_rproc_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
rproc_free(adsp->rproc);
-
- return 0;
}
static const struct adsp_pil_data adsp_resource_init = {
@@ -859,7 +857,7 @@ MODULE_DEVICE_TABLE(of, adsp_of_match);
static struct platform_driver adsp_pil_driver = {
.probe = adsp_probe,
- .remove = adsp_remove,
+ .remove_new = adsp_remove,
.driver = {
.name = "qcom_q6v5_adsp",
.of_match_table = adsp_of_match,
diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index 8e15e4f85de1..70bffc9f33f6 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -2110,7 +2110,7 @@ free_rproc:
return ret;
}
-static int q6v5_remove(struct platform_device *pdev)
+static void q6v5_remove(struct platform_device *pdev)
{
struct q6v5 *qproc = platform_get_drvdata(pdev);
struct rproc *rproc = qproc->rproc;
@@ -2128,8 +2128,6 @@ static int q6v5_remove(struct platform_device *pdev)
q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
rproc_free(rproc);
-
- return 0;
}
static const struct rproc_hexagon_res sc7180_mss = {
@@ -2482,7 +2480,7 @@ MODULE_DEVICE_TABLE(of, q6v5_of_match);
static struct platform_driver q6v5_driver = {
.probe = q6v5_probe,
- .remove = q6v5_remove,
+ .remove_new = q6v5_remove,
.driver = {
.name = "qcom-q6v5-mss",
.of_match_table = q6v5_of_match,
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index e34d82b18a67..3153d82037e7 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -105,7 +105,7 @@ struct qcom_adsp {
struct qcom_scm_pas_metadata dtb_pas_metadata;
};
-void adsp_segment_dump(struct rproc *rproc, struct rproc_dump_segment *segment,
+static void adsp_segment_dump(struct rproc *rproc, struct rproc_dump_segment *segment,
void *dest, size_t offset, size_t size)
{
struct qcom_adsp *adsp = rproc->priv;
@@ -754,7 +754,7 @@ free_rproc:
return ret;
}
-static int adsp_remove(struct platform_device *pdev)
+static void adsp_remove(struct platform_device *pdev)
{
struct qcom_adsp *adsp = platform_get_drvdata(pdev);
@@ -769,8 +769,6 @@ static int adsp_remove(struct platform_device *pdev)
adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
device_init_wakeup(adsp->dev, false);
rproc_free(adsp->rproc);
-
- return 0;
}
static const struct adsp_data adsp_resource_init = {
@@ -1232,7 +1230,7 @@ MODULE_DEVICE_TABLE(of, adsp_of_match);
static struct platform_driver adsp_driver = {
.probe = adsp_probe,
- .remove = adsp_remove,
+ .remove_new = adsp_remove,
.driver = {
.name = "qcom_q6v5_pas",
.of_match_table = adsp_of_match,
diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
index ba24d745b2d6..b437044aa126 100644
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -1074,7 +1074,7 @@ free_rproc:
return ret;
}
-static int q6v5_wcss_remove(struct platform_device *pdev)
+static void q6v5_wcss_remove(struct platform_device *pdev)
{
struct rproc *rproc = platform_get_drvdata(pdev);
struct q6v5_wcss *wcss = rproc->priv;
@@ -1082,8 +1082,6 @@ static int q6v5_wcss_remove(struct platform_device *pdev)
qcom_q6v5_deinit(&wcss->q6v5);
rproc_del(rproc);
rproc_free(rproc);
-
- return 0;
}
static const struct wcss_data wcss_ipq8074_res_init = {
@@ -1117,7 +1115,7 @@ MODULE_DEVICE_TABLE(of, q6v5_wcss_of_match);
static struct platform_driver q6v5_wcss_driver = {
.probe = q6v5_wcss_probe,
- .remove = q6v5_wcss_remove,
+ .remove_new = q6v5_wcss_remove,
.driver = {
.name = "qcom-q6v5-wcss-pil",
.of_match_table = q6v5_wcss_of_match,
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index 0fc317265064..1ed0647bc962 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -666,7 +666,7 @@ free_rproc:
return ret;
}
-static int wcnss_remove(struct platform_device *pdev)
+static void wcnss_remove(struct platform_device *pdev)
{
struct qcom_wcnss *wcnss = platform_get_drvdata(pdev);
@@ -678,8 +678,6 @@ static int wcnss_remove(struct platform_device *pdev)
qcom_remove_smd_subdev(wcnss->rproc, &wcnss->smd_subdev);
wcnss_release_pds(wcnss);
rproc_free(wcnss->rproc);
-
- return 0;
}
static const struct of_device_id wcnss_of_match[] = {
@@ -693,7 +691,7 @@ MODULE_DEVICE_TABLE(of, wcnss_of_match);
static struct platform_driver wcnss_driver = {
.probe = wcnss_probe,
- .remove = wcnss_remove,
+ .remove_new = wcnss_remove,
.driver = {
.name = "qcom-wcnss-pil",
.of_match_table = wcnss_of_match,
diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c
index 1ff2a73ade90..90e8769d5624 100644
--- a/drivers/remoteproc/rcar_rproc.c
+++ b/drivers/remoteproc/rcar_rproc.c
@@ -197,13 +197,11 @@ pm_disable:
return ret;
}
-static int rcar_rproc_remove(struct platform_device *pdev)
+static void rcar_rproc_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
pm_runtime_disable(dev);
-
- return 0;
}
static const struct of_device_id rcar_rproc_of_match[] = {
@@ -215,7 +213,7 @@ MODULE_DEVICE_TABLE(of, rcar_rproc_of_match);
static struct platform_driver rcar_rproc_driver = {
.probe = rcar_rproc_probe,
- .remove = rcar_rproc_remove,
+ .remove_new = rcar_rproc_remove,
.driver = {
.name = "rcar-rproc",
.of_match_table = rcar_rproc_of_match,
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index 0e95525c1158..83d76915a6ad 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -569,7 +569,7 @@ unwind_vring_allocations:
return ret;
}
-static int rproc_virtio_remove(struct platform_device *pdev)
+static void rproc_virtio_remove(struct platform_device *pdev)
{
struct rproc_vdev *rvdev = dev_get_drvdata(&pdev->dev);
struct rproc *rproc = rvdev->rproc;
@@ -588,14 +588,12 @@ static int rproc_virtio_remove(struct platform_device *pdev)
dma_release_coherent_memory(&pdev->dev);
put_device(&rproc->dev);
-
- return 0;
}
/* Platform driver */
static struct platform_driver rproc_virtio_driver = {
.probe = rproc_virtio_probe,
- .remove = rproc_virtio_remove,
+ .remove_new = rproc_virtio_remove,
.driver = {
.name = "rproc-virtio",
},
diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c
index 3f1b8963639f..e3ce01d98b4c 100644
--- a/drivers/remoteproc/st_remoteproc.c
+++ b/drivers/remoteproc/st_remoteproc.c
@@ -448,7 +448,7 @@ free_rproc:
return ret;
}
-static int st_rproc_remove(struct platform_device *pdev)
+static void st_rproc_remove(struct platform_device *pdev)
{
struct rproc *rproc = platform_get_drvdata(pdev);
struct st_rproc *ddata = rproc->priv;
@@ -462,13 +462,11 @@ static int st_rproc_remove(struct platform_device *pdev)
mbox_free_channel(ddata->mbox_chan[i]);
rproc_free(rproc);
-
- return 0;
}
static struct platform_driver st_rproc_driver = {
.probe = st_rproc_probe,
- .remove = st_rproc_remove,
+ .remove_new = st_rproc_remove,
.driver = {
.name = "st-rproc",
.of_match_table = of_match_ptr(st_rproc_match),
diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
index 8746cbb1f168..cf073bac79f7 100644
--- a/drivers/remoteproc/stm32_rproc.c
+++ b/drivers/remoteproc/stm32_rproc.c
@@ -79,6 +79,7 @@ struct stm32_mbox {
struct stm32_rproc {
struct reset_control *rst;
+ struct reset_control *hold_boot_rst;
struct stm32_syscon hold_boot;
struct stm32_syscon pdds;
struct stm32_syscon m4_state;
@@ -88,7 +89,7 @@ struct stm32_rproc {
struct stm32_rproc_mem *rmems;
struct stm32_mbox mb[MBOX_NB_MBX];
struct workqueue_struct *workqueue;
- bool secured_soc;
+ bool hold_boot_smc;
void __iomem *rsc_va;
};
@@ -118,10 +119,10 @@ static int stm32_rproc_mem_alloc(struct rproc *rproc,
struct device *dev = rproc->dev.parent;
void *va;
- dev_dbg(dev, "map memory: %pa+%x\n", &mem->dma, mem->len);
+ dev_dbg(dev, "map memory: %pad+%zx\n", &mem->dma, mem->len);
va = ioremap_wc(mem->dma, mem->len);
if (IS_ERR_OR_NULL(va)) {
- dev_err(dev, "Unable to map memory region: %pa+%x\n",
+ dev_err(dev, "Unable to map memory region: %pad+0x%zx\n",
&mem->dma, mem->len);
return -ENOMEM;
}
@@ -413,13 +414,28 @@ static int stm32_rproc_set_hold_boot(struct rproc *rproc, bool hold)
struct arm_smccc_res smc_res;
int val, err;
+ /*
+ * Three ways to manage the hold boot
+ * - using SCMI: the hold boot is managed as a reset,
+ * - using Linux(no SCMI): the hold boot is managed as a syscon register
+ * - using SMC call (deprecated): use SMC reset interface
+ */
+
val = hold ? HOLD_BOOT : RELEASE_BOOT;
- if (IS_ENABLED(CONFIG_HAVE_ARM_SMCCC) && ddata->secured_soc) {
+ if (ddata->hold_boot_rst) {
+ /* Use the SCMI reset controller */
+ if (!hold)
+ err = reset_control_deassert(ddata->hold_boot_rst);
+ else
+ err = reset_control_assert(ddata->hold_boot_rst);
+ } else if (IS_ENABLED(CONFIG_HAVE_ARM_SMCCC) && ddata->hold_boot_smc) {
+ /* Use the SMC call */
arm_smccc_smc(STM32_SMC_RCC, STM32_SMC_REG_WRITE,
hold_boot.reg, val, 0, 0, 0, 0, &smc_res);
err = smc_res.a0;
} else {
+ /* Use syscon */
err = regmap_update_bits(hold_boot.map, hold_boot.reg,
hold_boot.mask, val);
}
@@ -627,7 +643,7 @@ stm32_rproc_get_loaded_rsc_table(struct rproc *rproc, size_t *table_sz)
ddata->rsc_va = devm_ioremap_wc(dev, rsc_pa, RSC_TBL_SIZE);
if (IS_ERR_OR_NULL(ddata->rsc_va)) {
- dev_err(dev, "Unable to map memory region: %pa+%zx\n",
+ dev_err(dev, "Unable to map memory region: %pa+%x\n",
&rsc_pa, RSC_TBL_SIZE);
ddata->rsc_va = NULL;
return ERR_PTR(-ENOMEM);
@@ -717,34 +733,52 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev,
dev_info(dev, "wdg irq registered\n");
}
- ddata->rst = devm_reset_control_get_by_index(dev, 0);
+ ddata->rst = devm_reset_control_get_optional(dev, "mcu_rst");
+ if (!ddata->rst) {
+ /* Try legacy fallback method: get it by index */
+ ddata->rst = devm_reset_control_get_by_index(dev, 0);
+ }
if (IS_ERR(ddata->rst))
return dev_err_probe(dev, PTR_ERR(ddata->rst),
"failed to get mcu_reset\n");
/*
- * if platform is secured the hold boot bit must be written by
- * smc call and read normally.
- * if not secure the hold boot bit could be read/write normally
+ * Three ways to manage the hold boot
+ * - using SCMI: the hold boot is managed as a reset
+ * The DT "reset-mames" property should be defined with 2 items:
+ * reset-names = "mcu_rst", "hold_boot";
+ * - using SMC call (deprecated): use SMC reset interface
+ * The DT "reset-mames" property is optional, "st,syscfg-tz" is required
+ * - default(no SCMI, no SMC): the hold boot is managed as a syscon register
+ * The DT "reset-mames" property is optional, "st,syscfg-holdboot" is required
*/
- err = stm32_rproc_get_syscon(np, "st,syscfg-tz", &tz);
- if (err) {
- dev_err(dev, "failed to get tz syscfg\n");
- return err;
- }
- err = regmap_read(tz.map, tz.reg, &tzen);
- if (err) {
- dev_err(dev, "failed to read tzen\n");
- return err;
+ ddata->hold_boot_rst = devm_reset_control_get_optional(dev, "hold_boot");
+ if (IS_ERR(ddata->hold_boot_rst))
+ return dev_err_probe(dev, PTR_ERR(ddata->hold_boot_rst),
+ "failed to get hold_boot reset\n");
+
+ if (!ddata->hold_boot_rst && IS_ENABLED(CONFIG_HAVE_ARM_SMCCC)) {
+ /* Manage the MCU_BOOT using SMC call */
+ err = stm32_rproc_get_syscon(np, "st,syscfg-tz", &tz);
+ if (!err) {
+ err = regmap_read(tz.map, tz.reg, &tzen);
+ if (err) {
+ dev_err(dev, "failed to read tzen\n");
+ return err;
+ }
+ ddata->hold_boot_smc = tzen & tz.mask;
+ }
}
- ddata->secured_soc = tzen & tz.mask;
- err = stm32_rproc_get_syscon(np, "st,syscfg-holdboot",
- &ddata->hold_boot);
- if (err) {
- dev_err(dev, "failed to get hold boot\n");
- return err;
+ if (!ddata->hold_boot_rst && !ddata->hold_boot_smc) {
+ /* Default: hold boot manage it through the syscon controller */
+ err = stm32_rproc_get_syscon(np, "st,syscfg-holdboot",
+ &ddata->hold_boot);
+ if (err) {
+ dev_err(dev, "failed to get hold boot\n");
+ return err;
+ }
}
err = stm32_rproc_get_syscon(np, "st,syscfg-pdds", &ddata->pdds);
@@ -867,7 +901,7 @@ free_rproc:
return ret;
}
-static int stm32_rproc_remove(struct platform_device *pdev)
+static void stm32_rproc_remove(struct platform_device *pdev)
{
struct rproc *rproc = platform_get_drvdata(pdev);
struct stm32_rproc *ddata = rproc->priv;
@@ -885,8 +919,6 @@ static int stm32_rproc_remove(struct platform_device *pdev)
device_init_wakeup(dev, false);
}
rproc_free(rproc);
-
- return 0;
}
static int __maybe_unused stm32_rproc_suspend(struct device *dev)
@@ -916,7 +948,7 @@ static SIMPLE_DEV_PM_OPS(stm32_rproc_pm_ops,
static struct platform_driver stm32_rproc_driver = {
.probe = stm32_rproc_probe,
- .remove = stm32_rproc_remove,
+ .remove_new = stm32_rproc_remove,
.driver = {
.name = "stm32-rproc",
.pm = &stm32_rproc_pm_ops,
diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c
index a0c204cb0979..120dc7d2dac1 100644
--- a/drivers/remoteproc/wkup_m3_rproc.c
+++ b/drivers/remoteproc/wkup_m3_rproc.c
@@ -223,7 +223,7 @@ err:
return ret;
}
-static int wkup_m3_rproc_remove(struct platform_device *pdev)
+static void wkup_m3_rproc_remove(struct platform_device *pdev)
{
struct rproc *rproc = platform_get_drvdata(pdev);
@@ -231,8 +231,6 @@ static int wkup_m3_rproc_remove(struct platform_device *pdev)
rproc_free(rproc);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -253,7 +251,7 @@ static const struct dev_pm_ops wkup_m3_rproc_pm_ops = {
static struct platform_driver wkup_m3_rproc_driver = {
.probe = wkup_m3_rproc_probe,
- .remove = wkup_m3_rproc_remove,
+ .remove_new = wkup_m3_rproc_remove,
.driver = {
.name = "wkup_m3_rproc",
.of_match_table = wkup_m3_rproc_of_match,
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 6aa8f243b30c..ccd59ddd7610 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -143,8 +143,12 @@ config RESET_NPCM
This enables the reset controller driver for Nuvoton NPCM
BMC SoCs.
-config RESET_OXNAS
- bool
+config RESET_NUVOTON_MA35D1
+ bool "Nuvoton MA35D1 Reset Driver"
+ depends on ARCH_MA35 || COMPILE_TEST
+ default ARCH_MA35
+ help
+ This enables the reset controller driver for Nuvoton MA35D1 SoC.
config RESET_PISTACHIO
bool "Pistachio Reset Driver"
@@ -154,7 +158,8 @@ config RESET_PISTACHIO
config RESET_POLARFIRE_SOC
bool "Microchip PolarFire SoC (MPFS) Reset Driver"
- depends on AUXILIARY_BUS && MCHP_CLK_MPFS
+ depends on MCHP_CLK_MPFS
+ select AUXILIARY_BUS
default MCHP_CLK_MPFS
help
This driver supports peripheral reset for the Microchip PolarFire SoC
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 7fec5af6c964..8270da8a4baa 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_RESET_MCHP_SPARX5) += reset-microchip-sparx5.o
obj-$(CONFIG_RESET_MESON) += reset-meson.o
obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o
obj-$(CONFIG_RESET_NPCM) += reset-npcm.o
-obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
+obj-$(CONFIG_RESET_NUVOTON_MA35D1) += reset-ma35d1.o
obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
obj-$(CONFIG_RESET_POLARFIRE_SOC) += reset-mpfs.o
obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
diff --git a/drivers/reset/reset-ath79.c b/drivers/reset/reset-ath79.c
index e48d8fcb3133..a8b8f5ea77ec 100644
--- a/drivers/reset/reset-ath79.c
+++ b/drivers/reset/reset-ath79.c
@@ -86,7 +86,6 @@ static int ath79_reset_restart_handler(struct notifier_block *nb,
static int ath79_reset_probe(struct platform_device *pdev)
{
struct ath79_reset *ath79_reset;
- struct resource *res;
int err;
ath79_reset = devm_kzalloc(&pdev->dev,
@@ -96,8 +95,7 @@ static int ath79_reset_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ath79_reset);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ath79_reset->base = devm_ioremap_resource(&pdev->dev, res);
+ ath79_reset->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ath79_reset->base))
return PTR_ERR(ath79_reset->base);
diff --git a/drivers/reset/reset-axs10x.c b/drivers/reset/reset-axs10x.c
index a854ef41364d..115f69e0db33 100644
--- a/drivers/reset/reset-axs10x.c
+++ b/drivers/reset/reset-axs10x.c
@@ -44,14 +44,12 @@ static const struct reset_control_ops axs10x_reset_ops = {
static int axs10x_reset_probe(struct platform_device *pdev)
{
struct axs10x_rst *rst;
- struct resource *mem;
rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL);
if (!rst)
return -ENOMEM;
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- rst->regs_rst = devm_ioremap_resource(&pdev->dev, mem);
+ rst->regs_rst = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rst->regs_rst))
return PTR_ERR(rst->regs_rst);
diff --git a/drivers/reset/reset-brcmstb-rescal.c b/drivers/reset/reset-brcmstb-rescal.c
index 433fa0c40e47..823317772bac 100644
--- a/drivers/reset/reset-brcmstb-rescal.c
+++ b/drivers/reset/reset-brcmstb-rescal.c
@@ -66,14 +66,12 @@ static const struct reset_control_ops brcm_rescal_reset_ops = {
static int brcm_rescal_reset_probe(struct platform_device *pdev)
{
struct brcm_rescal_reset *data;
- struct resource *res;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- data->base = devm_ioremap_resource(&pdev->dev, res);
+ data->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(data->base))
return PTR_ERR(data->base);
diff --git a/drivers/reset/reset-hsdk.c b/drivers/reset/reset-hsdk.c
index 4c7b8647b49c..98460e08752c 100644
--- a/drivers/reset/reset-hsdk.c
+++ b/drivers/reset/reset-hsdk.c
@@ -92,19 +92,16 @@ static const struct reset_control_ops hsdk_reset_ops = {
static int hsdk_reset_probe(struct platform_device *pdev)
{
struct hsdk_rst *rst;
- struct resource *mem;
rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL);
if (!rst)
return -ENOMEM;
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- rst->regs_ctl = devm_ioremap_resource(&pdev->dev, mem);
+ rst->regs_ctl = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rst->regs_ctl))
return PTR_ERR(rst->regs_ctl);
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- rst->regs_rst = devm_ioremap_resource(&pdev->dev, mem);
+ rst->regs_rst = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(rst->regs_rst))
return PTR_ERR(rst->regs_rst);
diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c
index 35d8dd4cccfc..36ec95518905 100644
--- a/drivers/reset/reset-lpc18xx.c
+++ b/drivers/reset/reset-lpc18xx.c
@@ -139,7 +139,6 @@ static const struct reset_control_ops lpc18xx_rgu_ops = {
static int lpc18xx_rgu_probe(struct platform_device *pdev)
{
struct lpc18xx_rgu_data *rc;
- struct resource *res;
u32 fcclk, firc;
int ret;
@@ -147,8 +146,7 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
if (!rc)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- rc->base = devm_ioremap_resource(&pdev->dev, res);
+ rc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rc->base))
return PTR_ERR(rc->base);
diff --git a/drivers/reset/reset-ma35d1.c b/drivers/reset/reset-ma35d1.c
new file mode 100644
index 000000000000..54e53863c98a
--- /dev/null
+++ b/drivers/reset/reset-ma35d1.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023 Nuvoton Technology Corp.
+ * Author: Chi-Fang Li <cfli0@nuvoton.com>
+ */
+
+#include <linux/bits.h>
+#include <linux/container_of.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/reset-controller.h>
+#include <linux/spinlock.h>
+#include <dt-bindings/reset/nuvoton,ma35d1-reset.h>
+
+struct ma35d1_reset_data {
+ struct reset_controller_dev rcdev;
+ struct notifier_block restart_handler;
+ void __iomem *base;
+ /* protect registers against concurrent read-modify-write */
+ spinlock_t lock;
+};
+
+static const struct {
+ u32 reg_ofs;
+ u32 bit;
+} ma35d1_reset_map[] = {
+ [MA35D1_RESET_CHIP] = {0x20, 0},
+ [MA35D1_RESET_CA35CR0] = {0x20, 1},
+ [MA35D1_RESET_CA35CR1] = {0x20, 2},
+ [MA35D1_RESET_CM4] = {0x20, 3},
+ [MA35D1_RESET_PDMA0] = {0x20, 4},
+ [MA35D1_RESET_PDMA1] = {0x20, 5},
+ [MA35D1_RESET_PDMA2] = {0x20, 6},
+ [MA35D1_RESET_PDMA3] = {0x20, 7},
+ [MA35D1_RESET_DISP] = {0x20, 9},
+ [MA35D1_RESET_VCAP0] = {0x20, 10},
+ [MA35D1_RESET_VCAP1] = {0x20, 11},
+ [MA35D1_RESET_GFX] = {0x20, 12},
+ [MA35D1_RESET_VDEC] = {0x20, 13},
+ [MA35D1_RESET_WHC0] = {0x20, 14},
+ [MA35D1_RESET_WHC1] = {0x20, 15},
+ [MA35D1_RESET_GMAC0] = {0x20, 16},
+ [MA35D1_RESET_GMAC1] = {0x20, 17},
+ [MA35D1_RESET_HWSEM] = {0x20, 18},
+ [MA35D1_RESET_EBI] = {0x20, 19},
+ [MA35D1_RESET_HSUSBH0] = {0x20, 20},
+ [MA35D1_RESET_HSUSBH1] = {0x20, 21},
+ [MA35D1_RESET_HSUSBD] = {0x20, 22},
+ [MA35D1_RESET_USBHL] = {0x20, 23},
+ [MA35D1_RESET_SDH0] = {0x20, 24},
+ [MA35D1_RESET_SDH1] = {0x20, 25},
+ [MA35D1_RESET_NAND] = {0x20, 26},
+ [MA35D1_RESET_GPIO] = {0x20, 27},
+ [MA35D1_RESET_MCTLP] = {0x20, 28},
+ [MA35D1_RESET_MCTLC] = {0x20, 29},
+ [MA35D1_RESET_DDRPUB] = {0x20, 30},
+ [MA35D1_RESET_TMR0] = {0x24, 2},
+ [MA35D1_RESET_TMR1] = {0x24, 3},
+ [MA35D1_RESET_TMR2] = {0x24, 4},
+ [MA35D1_RESET_TMR3] = {0x24, 5},
+ [MA35D1_RESET_I2C0] = {0x24, 8},
+ [MA35D1_RESET_I2C1] = {0x24, 9},
+ [MA35D1_RESET_I2C2] = {0x24, 10},
+ [MA35D1_RESET_I2C3] = {0x24, 11},
+ [MA35D1_RESET_QSPI0] = {0x24, 12},
+ [MA35D1_RESET_SPI0] = {0x24, 13},
+ [MA35D1_RESET_SPI1] = {0x24, 14},
+ [MA35D1_RESET_SPI2] = {0x24, 15},
+ [MA35D1_RESET_UART0] = {0x24, 16},
+ [MA35D1_RESET_UART1] = {0x24, 17},
+ [MA35D1_RESET_UART2] = {0x24, 18},
+ [MA35D1_RESET_UART3] = {0x24, 19},
+ [MA35D1_RESET_UART4] = {0x24, 20},
+ [MA35D1_RESET_UART5] = {0x24, 21},
+ [MA35D1_RESET_UART6] = {0x24, 22},
+ [MA35D1_RESET_UART7] = {0x24, 23},
+ [MA35D1_RESET_CANFD0] = {0x24, 24},
+ [MA35D1_RESET_CANFD1] = {0x24, 25},
+ [MA35D1_RESET_EADC0] = {0x24, 28},
+ [MA35D1_RESET_I2S0] = {0x24, 29},
+ [MA35D1_RESET_SC0] = {0x28, 0},
+ [MA35D1_RESET_SC1] = {0x28, 1},
+ [MA35D1_RESET_QSPI1] = {0x28, 4},
+ [MA35D1_RESET_SPI3] = {0x28, 6},
+ [MA35D1_RESET_EPWM0] = {0x28, 16},
+ [MA35D1_RESET_EPWM1] = {0x28, 17},
+ [MA35D1_RESET_QEI0] = {0x28, 22},
+ [MA35D1_RESET_QEI1] = {0x28, 23},
+ [MA35D1_RESET_ECAP0] = {0x28, 26},
+ [MA35D1_RESET_ECAP1] = {0x28, 27},
+ [MA35D1_RESET_CANFD2] = {0x28, 28},
+ [MA35D1_RESET_ADC0] = {0x28, 31},
+ [MA35D1_RESET_TMR4] = {0x2C, 0},
+ [MA35D1_RESET_TMR5] = {0x2C, 1},
+ [MA35D1_RESET_TMR6] = {0x2C, 2},
+ [MA35D1_RESET_TMR7] = {0x2C, 3},
+ [MA35D1_RESET_TMR8] = {0x2C, 4},
+ [MA35D1_RESET_TMR9] = {0x2C, 5},
+ [MA35D1_RESET_TMR10] = {0x2C, 6},
+ [MA35D1_RESET_TMR11] = {0x2C, 7},
+ [MA35D1_RESET_UART8] = {0x2C, 8},
+ [MA35D1_RESET_UART9] = {0x2C, 9},
+ [MA35D1_RESET_UART10] = {0x2C, 10},
+ [MA35D1_RESET_UART11] = {0x2C, 11},
+ [MA35D1_RESET_UART12] = {0x2C, 12},
+ [MA35D1_RESET_UART13] = {0x2C, 13},
+ [MA35D1_RESET_UART14] = {0x2C, 14},
+ [MA35D1_RESET_UART15] = {0x2C, 15},
+ [MA35D1_RESET_UART16] = {0x2C, 16},
+ [MA35D1_RESET_I2S1] = {0x2C, 17},
+ [MA35D1_RESET_I2C4] = {0x2C, 18},
+ [MA35D1_RESET_I2C5] = {0x2C, 19},
+ [MA35D1_RESET_EPWM2] = {0x2C, 20},
+ [MA35D1_RESET_ECAP2] = {0x2C, 21},
+ [MA35D1_RESET_QEI2] = {0x2C, 22},
+ [MA35D1_RESET_CANFD3] = {0x2C, 23},
+ [MA35D1_RESET_KPI] = {0x2C, 24},
+ [MA35D1_RESET_GIC] = {0x2C, 28},
+ [MA35D1_RESET_SSMCC] = {0x2C, 30},
+ [MA35D1_RESET_SSPCC] = {0x2C, 31}
+};
+
+static int ma35d1_restart_handler(struct notifier_block *this, unsigned long mode, void *cmd)
+{
+ struct ma35d1_reset_data *data =
+ container_of(this, struct ma35d1_reset_data, restart_handler);
+ u32 id = MA35D1_RESET_CHIP;
+
+ writel_relaxed(BIT(ma35d1_reset_map[id].bit),
+ data->base + ma35d1_reset_map[id].reg_ofs);
+ return 0;
+}
+
+static int ma35d1_reset_update(struct reset_controller_dev *rcdev, unsigned long id, bool assert)
+{
+ struct ma35d1_reset_data *data = container_of(rcdev, struct ma35d1_reset_data, rcdev);
+ unsigned long flags;
+ u32 reg;
+
+ if (WARN_ON_ONCE(id >= ARRAY_SIZE(ma35d1_reset_map)))
+ return -EINVAL;
+
+ spin_lock_irqsave(&data->lock, flags);
+ reg = readl_relaxed(data->base + ma35d1_reset_map[id].reg_ofs);
+ if (assert)
+ reg |= BIT(ma35d1_reset_map[id].bit);
+ else
+ reg &= ~(BIT(ma35d1_reset_map[id].bit));
+ writel_relaxed(reg, data->base + ma35d1_reset_map[id].reg_ofs);
+ spin_unlock_irqrestore(&data->lock, flags);
+
+ return 0;
+}
+
+static int ma35d1_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ return ma35d1_reset_update(rcdev, id, true);
+}
+
+static int ma35d1_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ return ma35d1_reset_update(rcdev, id, false);
+}
+
+static int ma35d1_reset_status(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ struct ma35d1_reset_data *data = container_of(rcdev, struct ma35d1_reset_data, rcdev);
+ u32 reg;
+
+ if (WARN_ON_ONCE(id >= ARRAY_SIZE(ma35d1_reset_map)))
+ return -EINVAL;
+
+ reg = readl_relaxed(data->base + ma35d1_reset_map[id].reg_ofs);
+ return !!(reg & BIT(ma35d1_reset_map[id].bit));
+}
+
+static const struct reset_control_ops ma35d1_reset_ops = {
+ .assert = ma35d1_reset_assert,
+ .deassert = ma35d1_reset_deassert,
+ .status = ma35d1_reset_status,
+};
+
+static const struct of_device_id ma35d1_reset_dt_ids[] = {
+ { .compatible = "nuvoton,ma35d1-reset" },
+ { },
+};
+
+static int ma35d1_reset_probe(struct platform_device *pdev)
+{
+ struct ma35d1_reset_data *reset_data;
+ struct device *dev = &pdev->dev;
+ int err;
+
+ if (!pdev->dev.of_node) {
+ dev_err(&pdev->dev, "Device tree node not found\n");
+ return -EINVAL;
+ }
+
+ reset_data = devm_kzalloc(dev, sizeof(*reset_data), GFP_KERNEL);
+ if (!reset_data)
+ return -ENOMEM;
+
+ reset_data->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(reset_data->base))
+ return PTR_ERR(reset_data->base);
+
+ reset_data->rcdev.owner = THIS_MODULE;
+ reset_data->rcdev.nr_resets = MA35D1_RESET_COUNT;
+ reset_data->rcdev.ops = &ma35d1_reset_ops;
+ reset_data->rcdev.of_node = dev->of_node;
+ reset_data->restart_handler.notifier_call = ma35d1_restart_handler;
+ reset_data->restart_handler.priority = 192;
+ spin_lock_init(&reset_data->lock);
+
+ err = register_restart_handler(&reset_data->restart_handler);
+ if (err)
+ dev_warn(&pdev->dev, "failed to register restart handler\n");
+
+ return devm_reset_controller_register(dev, &reset_data->rcdev);
+}
+
+static struct platform_driver ma35d1_reset_driver = {
+ .probe = ma35d1_reset_probe,
+ .driver = {
+ .name = "ma35d1-reset",
+ .of_match_table = ma35d1_reset_dt_ids,
+ },
+};
+
+builtin_platform_driver(ma35d1_reset_driver);
diff --git a/drivers/reset/reset-meson-audio-arb.c b/drivers/reset/reset-meson-audio-arb.c
index 1dc06e08a8da..6a3f6a6a3bbf 100644
--- a/drivers/reset/reset-meson-audio-arb.c
+++ b/drivers/reset/reset-meson-audio-arb.c
@@ -151,11 +151,8 @@ static int meson_audio_arb_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, arb);
arb->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(arb->clk)) {
- if (PTR_ERR(arb->clk) != -EPROBE_DEFER)
- dev_err(dev, "failed to get clock\n");
- return PTR_ERR(arb->clk);
- }
+ if (IS_ERR(arb->clk))
+ return dev_err_probe(dev, PTR_ERR(arb->clk), "failed to get clock\n");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
arb->regs = devm_ioremap_resource(dev, res);
diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
index 26dc54778615..13878ca2779d 100644
--- a/drivers/reset/reset-meson.c
+++ b/drivers/reset/reset-meson.c
@@ -116,14 +116,12 @@ MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
static int meson_reset_probe(struct platform_device *pdev)
{
struct meson_reset *data;
- struct resource *res;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- data->reg_base = devm_ioremap_resource(&pdev->dev, res);
+ data->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(data->reg_base))
return PTR_ERR(data->reg_base);
diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c
deleted file mode 100644
index 8209f922dc16..000000000000
--- a/drivers/reset/reset-oxnas.c
+++ /dev/null
@@ -1,114 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Oxford Semiconductor Reset Controller driver
- *
- * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
- * Copyright (C) 2014 Ma Haijun <mahaijuns@gmail.com>
- * Copyright (C) 2009 Oxford Semiconductor Ltd
- */
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/reset-controller.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-
-/* Regmap offsets */
-#define RST_SET_REGOFFSET 0x34
-#define RST_CLR_REGOFFSET 0x38
-
-struct oxnas_reset {
- struct regmap *regmap;
- struct reset_controller_dev rcdev;
-};
-
-static int oxnas_reset_reset(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- struct oxnas_reset *data =
- container_of(rcdev, struct oxnas_reset, rcdev);
-
- regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
- msleep(50);
- regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
-
- return 0;
-}
-
-static int oxnas_reset_assert(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- struct oxnas_reset *data =
- container_of(rcdev, struct oxnas_reset, rcdev);
-
- regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id));
-
- return 0;
-}
-
-static int oxnas_reset_deassert(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- struct oxnas_reset *data =
- container_of(rcdev, struct oxnas_reset, rcdev);
-
- regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id));
-
- return 0;
-}
-
-static const struct reset_control_ops oxnas_reset_ops = {
- .reset = oxnas_reset_reset,
- .assert = oxnas_reset_assert,
- .deassert = oxnas_reset_deassert,
-};
-
-static const struct of_device_id oxnas_reset_dt_ids[] = {
- { .compatible = "oxsemi,ox810se-reset", },
- { .compatible = "oxsemi,ox820-reset", },
- { /* sentinel */ },
-};
-
-static int oxnas_reset_probe(struct platform_device *pdev)
-{
- struct oxnas_reset *data;
- struct device *parent;
-
- parent = pdev->dev.parent;
- if (!parent) {
- dev_err(&pdev->dev, "no parent\n");
- return -ENODEV;
- }
-
- data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- data->regmap = syscon_node_to_regmap(parent->of_node);
- if (IS_ERR(data->regmap)) {
- dev_err(&pdev->dev, "failed to get parent regmap\n");
- return PTR_ERR(data->regmap);
- }
-
- platform_set_drvdata(pdev, data);
-
- data->rcdev.owner = THIS_MODULE;
- data->rcdev.nr_resets = 32;
- data->rcdev.ops = &oxnas_reset_ops;
- data->rcdev.of_node = pdev->dev.of_node;
-
- return devm_reset_controller_register(&pdev->dev, &data->rcdev);
-}
-
-static struct platform_driver oxnas_reset_driver = {
- .probe = oxnas_reset_probe,
- .driver = {
- .name = "oxnas-reset",
- .of_match_table = oxnas_reset_dt_ids,
- },
-};
-builtin_platform_driver(oxnas_reset_driver);
diff --git a/drivers/reset/starfive/Kconfig b/drivers/reset/starfive/Kconfig
index 1fa706a2c3dc..d832339f61bc 100644
--- a/drivers/reset/starfive/Kconfig
+++ b/drivers/reset/starfive/Kconfig
@@ -13,7 +13,8 @@ config RESET_STARFIVE_JH7100
config RESET_STARFIVE_JH7110
bool "StarFive JH7110 Reset Driver"
- depends on AUXILIARY_BUS && CLK_STARFIVE_JH7110_SYS
+ depends on CLK_STARFIVE_JH7110_SYS
+ select AUXILIARY_BUS
select RESET_STARFIVE_JH71X0
default ARCH_STARFIVE
help
diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig
index 9455e1c7a5aa..a2622e146b8b 100644
--- a/drivers/reset/sti/Kconfig
+++ b/drivers/reset/sti/Kconfig
@@ -1,11 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
if ARCH_STI
-config STI_RESET_SYSCFG
- bool
-
config STIH407_RESET
bool
- select STI_RESET_SYSCFG
endif
diff --git a/drivers/reset/sti/Makefile b/drivers/reset/sti/Makefile
index 3eb30f7e8e3d..5e833496cee3 100644
--- a/drivers/reset/sti/Makefile
+++ b/drivers/reset/sti/Makefile
@@ -1,4 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_STI_RESET_SYSCFG) += reset-syscfg.o
-
-obj-$(CONFIG_STIH407_RESET) += reset-stih407.o
+obj-$(CONFIG_STIH407_RESET) += reset-stih407.o reset-syscfg.o
diff --git a/drivers/reset/sti/reset-syscfg.c b/drivers/reset/sti/reset-syscfg.c
index b4b46e0f207e..c1ba04f6f155 100644
--- a/drivers/reset/sti/reset-syscfg.c
+++ b/drivers/reset/sti/reset-syscfg.c
@@ -64,22 +64,12 @@ static int syscfg_reset_program_hw(struct reset_controller_dev *rcdev,
return err;
if (ch->ack) {
- unsigned long timeout = jiffies + msecs_to_jiffies(1000);
u32 ack_val;
- while (true) {
- err = regmap_field_read(ch->ack, &ack_val);
- if (err)
- return err;
-
- if (ack_val == ctrl_val)
- break;
-
- if (time_after(jiffies, timeout))
- return -ETIME;
-
- cpu_relax();
- }
+ err = regmap_field_read_poll_timeout(ch->ack, ack_val, (ack_val == ctrl_val),
+ 100, USEC_PER_SEC);
+ if (err)
+ return err;
}
return 0;
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index ffca9a8bb878..05f4b2d66290 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -956,6 +956,7 @@ comment "Platform RTC drivers"
config RTC_DRV_CMOS
tristate "PC-style 'CMOS'"
depends on X86 || ARM || PPC || MIPS || SPARC64
+ depends on HAS_IOPORT || MACH_DECSTATION
default y if X86
select RTC_MC146818_LIB
help
@@ -976,6 +977,7 @@ config RTC_DRV_CMOS
config RTC_DRV_ALPHA
bool "Alpha PC-style CMOS"
depends on ALPHA
+ depends on HAS_IOPORT
select RTC_MC146818_LIB
default y
help
@@ -1193,7 +1195,7 @@ config RTC_DRV_MSM6242
config RTC_DRV_BQ4802
tristate "TI BQ4802"
- depends on HAS_IOMEM
+ depends on HAS_IOMEM && HAS_IOPORT
help
If you say Y here you will get support for the TI
BQ4802 RTC chip.
@@ -1685,6 +1687,19 @@ config RTC_DRV_JZ4740
This driver can also be built as a module. If so, the module
will be called rtc-jz4740.
+config RTC_DRV_LOONGSON
+ tristate "Loongson On-chip RTC"
+ depends on MACH_LOONGSON32 || MACH_LOONGSON64 || COMPILE_TEST
+ select REGMAP_MMIO
+ help
+ This is a driver for the Loongson on-chip Counter0 (Time-Of-Year
+ counter) to be used as a RTC.
+ It can be found on Loongson-1 series cpu, Loongson-2K series cpu
+ and Loongson LS7A bridge chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-loongson.
+
config RTC_DRV_LPC24XX
tristate "NXP RTC for LPC178x/18xx/408x/43xx"
depends on ARCH_LPC18XX || COMPILE_TEST
@@ -1726,16 +1741,6 @@ config RTC_DRV_TEGRA
This drive can also be built as a module. If so, the module
will be called rtc-tegra.
-config RTC_DRV_LOONGSON1
- tristate "loongson1 RTC support"
- depends on MACH_LOONGSON32
- help
- This is a driver for the loongson1 on-chip Counter0 (Time-Of-Year
- counter) to be used as a RTC.
-
- This driver can also be built as a module. If so, the module
- will be called rtc-ls1x.
-
config RTC_DRV_MXC
tristate "Freescale MXC Real Time Clock"
depends on ARCH_MXC || COMPILE_TEST
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index ea445d1ebb17..fd209883ee2e 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -78,7 +78,7 @@ obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o
obj-$(CONFIG_RTC_DRV_ISL12026) += rtc-isl12026.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o
-obj-$(CONFIG_RTC_DRV_LOONGSON1) += rtc-ls1x.o
+obj-$(CONFIG_RTC_DRV_LOONGSON) += rtc-loongson.o
obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o
obj-$(CONFIG_RTC_DRV_LPC24XX) += rtc-lpc24xx.o
obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o
diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c
index f2b0971d2c65..100062001831 100644
--- a/drivers/rtc/rtc-ab-b5ze-s3.c
+++ b/drivers/rtc/rtc-ab-b5ze-s3.c
@@ -944,7 +944,7 @@ static struct i2c_driver abb5zes3_driver = {
.pm = &abb5zes3_rtc_pm_ops,
.of_match_table = of_match_ptr(abb5zes3_dt_match),
},
- .probe_new = abb5zes3_probe,
+ .probe = abb5zes3_probe,
.id_table = abb5zes3_id,
};
module_i2c_driver(abb5zes3_driver);
diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c
index 34611f6dedcb..04e1b8e93bc1 100644
--- a/drivers/rtc/rtc-ab-eoz9.c
+++ b/drivers/rtc/rtc-ab-eoz9.c
@@ -455,7 +455,7 @@ static const struct hwmon_channel_info abeoz9_temp = {
.config = abeoz9_temp_config,
};
-static const struct hwmon_channel_info *abeoz9_info[] = {
+static const struct hwmon_channel_info * const abeoz9_info[] = {
&abeoz9_chip,
&abeoz9_temp,
NULL
@@ -584,7 +584,7 @@ static struct i2c_driver abeoz9_driver = {
.name = "rtc-ab-eoz9",
.of_match_table = of_match_ptr(abeoz9_dt_match),
},
- .probe_new = abeoz9_probe,
+ .probe = abeoz9_probe,
.id_table = abeoz9_id,
};
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index f34a2e59cac7..e08d3181bd2a 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -992,7 +992,7 @@ static struct i2c_driver abx80x_driver = {
.name = "rtc-abx80x",
.of_match_table = of_match_ptr(abx80x_of_match),
},
- .probe_new = abx80x_probe,
+ .probe = abx80x_probe,
.id_table = abx80x_id,
};
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c
index 967ddc6bf76d..591e42391747 100644
--- a/drivers/rtc/rtc-bq32k.c
+++ b/drivers/rtc/rtc-bq32k.c
@@ -320,7 +320,7 @@ static struct i2c_driver bq32k_driver = {
.name = "bq32k",
.of_match_table = of_match_ptr(bq32k_of_match),
},
- .probe_new = bq32k_probe,
+ .probe = bq32k_probe,
.remove = bq32k_remove,
.id_table = bq32k_id,
};
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index e86ba84df6cb..cb5acecc11aa 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -2011,7 +2011,7 @@ static struct i2c_driver ds1307_driver = {
.name = "rtc-ds1307",
.of_match_table = ds1307_of_match,
},
- .probe_new = ds1307_probe,
+ .probe = ds1307_probe,
.id_table = ds1307_id,
};
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 7f089f066163..4a5005cb23f5 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -572,7 +572,7 @@ static struct i2c_driver ds1374_driver = {
.of_match_table = of_match_ptr(ds1374_of_match),
.pm = &ds1374_pm,
},
- .probe_new = ds1374_probe,
+ .probe = ds1374_probe,
.remove = ds1374_remove,
.id_table = ds1374_id,
};
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index a3bb2cd9c881..641799f30baa 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -149,7 +149,7 @@ static struct i2c_driver ds1672_driver = {
.name = "rtc-ds1672",
.of_match_table = of_match_ptr(ds1672_of_match),
},
- .probe_new = ds1672_probe,
+ .probe = ds1672_probe,
.id_table = ds1672_id,
};
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index dd31a60c1fc6..89d7b085f721 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -359,7 +359,7 @@ static const struct hwmon_channel_info ds3232_hwmon_temp = {
.config = ds3232_hwmon_temp_config,
};
-static const struct hwmon_channel_info *ds3232_hwmon_info[] = {
+static const struct hwmon_channel_info * const ds3232_hwmon_info[] = {
&ds3232_hwmon_chip,
&ds3232_hwmon_temp,
NULL
@@ -603,7 +603,7 @@ static struct i2c_driver ds3232_driver = {
.of_match_table = of_match_ptr(ds3232_of_match),
.pm = &ds3232_pm_ops,
},
- .probe_new = ds3232_i2c_probe,
+ .probe = ds3232_i2c_probe,
.id_table = ds3232_id,
};
diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c
index 53f9f9391a5f..fc772eae5da5 100644
--- a/drivers/rtc/rtc-em3027.c
+++ b/drivers/rtc/rtc-em3027.c
@@ -147,7 +147,7 @@ static struct i2c_driver em3027_driver = {
.name = "rtc-em3027",
.of_match_table = of_match_ptr(em3027_of_match),
},
- .probe_new = em3027_probe,
+ .probe = em3027_probe,
.id_table = em3027_id,
};
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c
index f59bb81f23c0..400ce4ad0c49 100644
--- a/drivers/rtc/rtc-fm3130.c
+++ b/drivers/rtc/rtc-fm3130.c
@@ -517,7 +517,7 @@ static struct i2c_driver fm3130_driver = {
.driver = {
.name = "rtc-fm3130",
},
- .probe_new = fm3130_probe,
+ .probe = fm3130_probe,
.id_table = fm3130_id,
};
diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
index 7d5a298a9a3b..b018535c842b 100644
--- a/drivers/rtc/rtc-hym8563.c
+++ b/drivers/rtc/rtc-hym8563.c
@@ -576,7 +576,7 @@ static struct i2c_driver hym8563_driver = {
.pm = &hym8563_pm_ops,
.of_match_table = hym8563_dt_idtable,
},
- .probe_new = hym8563_probe,
+ .probe = hym8563_probe,
.id_table = hym8563_id,
};
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c
index e68a79b5e00e..a613257d1574 100644
--- a/drivers/rtc/rtc-isl12022.c
+++ b/drivers/rtc/rtc-isl12022.c
@@ -89,7 +89,7 @@ static int isl12022_hwmon_read(struct device *dev,
return -EOPNOTSUPP;
}
-static const struct hwmon_channel_info *isl12022_hwmon_info[] = {
+static const struct hwmon_channel_info * const isl12022_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
NULL
};
@@ -262,7 +262,7 @@ static struct i2c_driver isl12022_driver = {
.name = "rtc-isl12022",
.of_match_table = isl12022_dt_match,
},
- .probe_new = isl12022_probe,
+ .probe = isl12022_probe,
.id_table = isl12022_id,
};
diff --git a/drivers/rtc/rtc-isl12026.c b/drivers/rtc/rtc-isl12026.c
index 1bfca39079d4..5abff5d348ac 100644
--- a/drivers/rtc/rtc-isl12026.c
+++ b/drivers/rtc/rtc-isl12026.c
@@ -490,7 +490,7 @@ static struct i2c_driver isl12026_driver = {
.name = "rtc-isl12026",
.of_match_table = isl12026_dt_match,
},
- .probe_new = isl12026_probe_new,
+ .probe = isl12026_probe_new,
.remove = isl12026_remove,
};
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index 73cc6aaf9b8b..b0712b4e3648 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -6,6 +6,7 @@
*/
#include <linux/bcd.h>
+#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of_device.h>
@@ -68,42 +69,60 @@
static struct i2c_driver isl1208_driver;
-/* ISL1208 various variants */
-enum isl1208_id {
- TYPE_ISL1208 = 0,
- TYPE_ISL1209,
- TYPE_ISL1218,
- TYPE_ISL1219,
- ISL_LAST_ID
-};
-
/* Chip capabilities table */
-static const struct isl1208_config {
- const char name[8];
+struct isl1208_config {
unsigned int nvmem_length;
unsigned has_tamper:1;
unsigned has_timestamp:1;
-} isl1208_configs[] = {
- [TYPE_ISL1208] = { "isl1208", 2, false, false },
- [TYPE_ISL1209] = { "isl1209", 2, true, false },
- [TYPE_ISL1218] = { "isl1218", 8, false, false },
- [TYPE_ISL1219] = { "isl1219", 2, true, true },
+ unsigned has_inverted_osc_bit:1;
+};
+
+static const struct isl1208_config config_isl1208 = {
+ .nvmem_length = 2,
+ .has_tamper = false,
+ .has_timestamp = false
+};
+
+static const struct isl1208_config config_isl1209 = {
+ .nvmem_length = 2,
+ .has_tamper = true,
+ .has_timestamp = false
+};
+
+static const struct isl1208_config config_isl1218 = {
+ .nvmem_length = 8,
+ .has_tamper = false,
+ .has_timestamp = false
+};
+
+static const struct isl1208_config config_isl1219 = {
+ .nvmem_length = 2,
+ .has_tamper = true,
+ .has_timestamp = true
+};
+
+static const struct isl1208_config config_raa215300_a0 = {
+ .nvmem_length = 2,
+ .has_tamper = false,
+ .has_timestamp = false,
+ .has_inverted_osc_bit = true
};
static const struct i2c_device_id isl1208_id[] = {
- { "isl1208", TYPE_ISL1208 },
- { "isl1209", TYPE_ISL1209 },
- { "isl1218", TYPE_ISL1218 },
- { "isl1219", TYPE_ISL1219 },
+ { "isl1208", .driver_data = (kernel_ulong_t)&config_isl1208 },
+ { "isl1209", .driver_data = (kernel_ulong_t)&config_isl1209 },
+ { "isl1218", .driver_data = (kernel_ulong_t)&config_isl1218 },
+ { "isl1219", .driver_data = (kernel_ulong_t)&config_isl1219 },
+ { "raa215300_a0", .driver_data = (kernel_ulong_t)&config_raa215300_a0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, isl1208_id);
static const __maybe_unused struct of_device_id isl1208_of_match[] = {
- { .compatible = "isil,isl1208", .data = &isl1208_configs[TYPE_ISL1208] },
- { .compatible = "isil,isl1209", .data = &isl1208_configs[TYPE_ISL1209] },
- { .compatible = "isil,isl1218", .data = &isl1208_configs[TYPE_ISL1218] },
- { .compatible = "isil,isl1219", .data = &isl1208_configs[TYPE_ISL1219] },
+ { .compatible = "isil,isl1208", .data = &config_isl1208 },
+ { .compatible = "isil,isl1209", .data = &config_isl1209 },
+ { .compatible = "isil,isl1218", .data = &config_isl1218 },
+ { .compatible = "isil,isl1219", .data = &config_isl1219 },
{ }
};
MODULE_DEVICE_TABLE(of, isl1208_of_match);
@@ -166,6 +185,20 @@ isl1208_i2c_validate_client(struct i2c_client *client)
return 0;
}
+static int isl1208_set_xtoscb(struct i2c_client *client, int sr, int xtosb_val)
+{
+ /* Do nothing if bit is already set to desired value */
+ if ((sr & ISL1208_REG_SR_XTOSCB) == xtosb_val)
+ return 0;
+
+ if (xtosb_val)
+ sr |= ISL1208_REG_SR_XTOSCB;
+ else
+ sr &= ~ISL1208_REG_SR_XTOSCB;
+
+ return i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr);
+}
+
static int
isl1208_i2c_get_sr(struct i2c_client *client)
{
@@ -502,7 +535,6 @@ isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
return 0;
}
-
static int
isl1208_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
@@ -797,11 +829,25 @@ static int isl1208_setup_irq(struct i2c_client *client, int irq)
}
static int
+isl1208_clk_present(struct i2c_client *client, const char *name)
+{
+ struct clk *clk;
+
+ clk = devm_clk_get_optional(&client->dev, name);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ return !!clk;
+}
+
+static int
isl1208_probe(struct i2c_client *client)
{
- int rc = 0;
struct isl1208_state *isl1208;
int evdet_irq = -1;
+ int xtosb_val = 0;
+ int rc = 0;
+ int sr;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
@@ -823,9 +869,22 @@ isl1208_probe(struct i2c_client *client)
} else {
const struct i2c_device_id *id = i2c_match_id(isl1208_id, client);
- if (id->driver_data >= ISL_LAST_ID)
+ if (!id)
return -ENODEV;
- isl1208->config = &isl1208_configs[id->driver_data];
+ isl1208->config = (struct isl1208_config *)id->driver_data;
+ }
+
+ rc = isl1208_clk_present(client, "xin");
+ if (rc < 0)
+ return rc;
+
+ if (!rc) {
+ rc = isl1208_clk_present(client, "clkin");
+ if (rc < 0)
+ return rc;
+
+ if (rc)
+ xtosb_val = 1;
}
isl1208->rtc = devm_rtc_allocate_device(&client->dev);
@@ -839,13 +898,20 @@ isl1208_probe(struct i2c_client *client)
isl1208->nvmem_config.size = isl1208->config->nvmem_length;
isl1208->nvmem_config.priv = isl1208;
- rc = isl1208_i2c_get_sr(client);
- if (rc < 0) {
+ sr = isl1208_i2c_get_sr(client);
+ if (sr < 0) {
dev_err(&client->dev, "reading status failed\n");
- return rc;
+ return sr;
}
- if (rc & ISL1208_REG_SR_RTCF)
+ if (isl1208->config->has_inverted_osc_bit)
+ xtosb_val = !xtosb_val;
+
+ rc = isl1208_set_xtoscb(client, sr, xtosb_val);
+ if (rc)
+ return rc;
+
+ if (sr & ISL1208_REG_SR_RTCF)
dev_warn(&client->dev, "rtc power failure detected, "
"please set clock.\n");
@@ -908,7 +974,7 @@ static struct i2c_driver isl1208_driver = {
.name = "rtc-isl1208",
.of_match_table = of_match_ptr(isl1208_of_match),
},
- .probe_new = isl1208_probe,
+ .probe = isl1208_probe,
.id_table = isl1208_id,
};
diff --git a/drivers/rtc/rtc-loongson.c b/drivers/rtc/rtc-loongson.c
new file mode 100644
index 000000000000..e8ffc1ab90b0
--- /dev/null
+++ b/drivers/rtc/rtc-loongson.c
@@ -0,0 +1,397 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Loongson RTC driver
+ *
+ * Maintained out-of-tree by Huacai Chen <chenhuacai@kernel.org>.
+ * Rewritten for mainline by WANG Xuerui <git@xen0n.name>.
+ * Binbin Zhou <zhoubinbin@loongson.cn>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/acpi.h>
+
+/* Time Of Year(TOY) counters registers */
+#define TOY_TRIM_REG 0x20 /* Must be initialized to 0 */
+#define TOY_WRITE0_REG 0x24 /* TOY low 32-bits value (write-only) */
+#define TOY_WRITE1_REG 0x28 /* TOY high 32-bits value (write-only) */
+#define TOY_READ0_REG 0x2c /* TOY low 32-bits value (read-only) */
+#define TOY_READ1_REG 0x30 /* TOY high 32-bits value (read-only) */
+#define TOY_MATCH0_REG 0x34 /* TOY timing interrupt 0 */
+#define TOY_MATCH1_REG 0x38 /* TOY timing interrupt 1 */
+#define TOY_MATCH2_REG 0x3c /* TOY timing interrupt 2 */
+
+/* RTC counters registers */
+#define RTC_CTRL_REG 0x40 /* TOY and RTC control register */
+#define RTC_TRIM_REG 0x60 /* Must be initialized to 0 */
+#define RTC_WRITE0_REG 0x64 /* RTC counters value (write-only) */
+#define RTC_READ0_REG 0x68 /* RTC counters value (read-only) */
+#define RTC_MATCH0_REG 0x6c /* RTC timing interrupt 0 */
+#define RTC_MATCH1_REG 0x70 /* RTC timing interrupt 1 */
+#define RTC_MATCH2_REG 0x74 /* RTC timing interrupt 2 */
+
+/* bitmask of TOY_WRITE0_REG */
+#define TOY_MON GENMASK(31, 26)
+#define TOY_DAY GENMASK(25, 21)
+#define TOY_HOUR GENMASK(20, 16)
+#define TOY_MIN GENMASK(15, 10)
+#define TOY_SEC GENMASK(9, 4)
+#define TOY_MSEC GENMASK(3, 0)
+
+/* bitmask of TOY_MATCH0/1/2_REG */
+#define TOY_MATCH_YEAR GENMASK(31, 26)
+#define TOY_MATCH_MON GENMASK(25, 22)
+#define TOY_MATCH_DAY GENMASK(21, 17)
+#define TOY_MATCH_HOUR GENMASK(16, 12)
+#define TOY_MATCH_MIN GENMASK(11, 6)
+#define TOY_MATCH_SEC GENMASK(5, 0)
+
+/* bitmask of RTC_CTRL_REG */
+#define RTC_ENABLE BIT(13) /* 1: RTC counters enable */
+#define TOY_ENABLE BIT(11) /* 1: TOY counters enable */
+#define OSC_ENABLE BIT(8) /* 1: 32.768k crystal enable */
+#define TOY_ENABLE_MASK (TOY_ENABLE | OSC_ENABLE)
+
+/* PM domain registers */
+#define PM1_STS_REG 0x0c /* Power management 1 status register */
+#define RTC_STS BIT(10) /* RTC status */
+#define PM1_EN_REG 0x10 /* Power management 1 enable register */
+#define RTC_EN BIT(10) /* RTC event enable */
+
+/*
+ * According to the LS1C manual, RTC_CTRL and alarm-related registers are not defined.
+ * Accessing the relevant registers will cause the system to hang.
+ */
+#define LS1C_RTC_CTRL_WORKAROUND BIT(0)
+
+struct loongson_rtc_config {
+ u32 pm_offset; /* Offset of PM domain, for RTC alarm wakeup */
+ u32 flags; /* Workaround bits */
+};
+
+struct loongson_rtc_priv {
+ spinlock_t lock; /* protects PM registers access */
+ u32 fix_year; /* RTC alarm year compensation value */
+ struct rtc_device *rtcdev;
+ struct regmap *regmap;
+ void __iomem *pm_base; /* PM domain base, for RTC alarm wakeup */
+ const struct loongson_rtc_config *config;
+};
+
+static const struct loongson_rtc_config ls1b_rtc_config = {
+ .pm_offset = 0,
+ .flags = 0,
+};
+
+static const struct loongson_rtc_config ls1c_rtc_config = {
+ .pm_offset = 0,
+ .flags = LS1C_RTC_CTRL_WORKAROUND,
+};
+
+static const struct loongson_rtc_config generic_rtc_config = {
+ .pm_offset = 0x100,
+ .flags = 0,
+};
+
+static const struct loongson_rtc_config ls2k1000_rtc_config = {
+ .pm_offset = 0x800,
+ .flags = 0,
+};
+
+static const struct regmap_config loongson_rtc_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+/* RTC alarm irq handler */
+static irqreturn_t loongson_rtc_isr(int irq, void *id)
+{
+ struct loongson_rtc_priv *priv = (struct loongson_rtc_priv *)id;
+
+ rtc_update_irq(priv->rtcdev, 1, RTC_AF | RTC_IRQF);
+ return IRQ_HANDLED;
+}
+
+/* For ACPI fixed event handler */
+static u32 loongson_rtc_handler(void *id)
+{
+ struct loongson_rtc_priv *priv = (struct loongson_rtc_priv *)id;
+
+ spin_lock(&priv->lock);
+ /* Disable RTC alarm wakeup and interrupt */
+ writel(readl(priv->pm_base + PM1_EN_REG) & ~RTC_EN,
+ priv->pm_base + PM1_EN_REG);
+
+ /* Clear RTC interrupt status */
+ writel(RTC_STS, priv->pm_base + PM1_STS_REG);
+ spin_unlock(&priv->lock);
+
+ /*
+ * The TOY_MATCH0_REG should be cleared 0 here,
+ * otherwise the interrupt cannot be cleared.
+ */
+ return regmap_write(priv->regmap, TOY_MATCH0_REG, 0);
+}
+
+static int loongson_rtc_set_enabled(struct device *dev)
+{
+ struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
+
+ if (priv->config->flags & LS1C_RTC_CTRL_WORKAROUND)
+ return 0;
+
+ /* Enable RTC TOY counters and crystal */
+ return regmap_update_bits(priv->regmap, RTC_CTRL_REG, TOY_ENABLE_MASK,
+ TOY_ENABLE_MASK);
+}
+
+static bool loongson_rtc_get_enabled(struct device *dev)
+{
+ int ret;
+ u32 ctrl_data;
+ struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
+
+ if (priv->config->flags & LS1C_RTC_CTRL_WORKAROUND)
+ return true;
+
+ ret = regmap_read(priv->regmap, RTC_CTRL_REG, &ctrl_data);
+ if (ret < 0)
+ return false;
+
+ return ctrl_data & TOY_ENABLE_MASK;
+}
+
+static int loongson_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ int ret;
+ u32 rtc_data[2];
+ struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
+
+ if (!loongson_rtc_get_enabled(dev))
+ return -EINVAL;
+
+ ret = regmap_bulk_read(priv->regmap, TOY_READ0_REG, rtc_data,
+ ARRAY_SIZE(rtc_data));
+ if (ret < 0)
+ return ret;
+
+ tm->tm_sec = FIELD_GET(TOY_SEC, rtc_data[0]);
+ tm->tm_min = FIELD_GET(TOY_MIN, rtc_data[0]);
+ tm->tm_hour = FIELD_GET(TOY_HOUR, rtc_data[0]);
+ tm->tm_mday = FIELD_GET(TOY_DAY, rtc_data[0]);
+ tm->tm_mon = FIELD_GET(TOY_MON, rtc_data[0]) - 1;
+ tm->tm_year = rtc_data[1];
+
+ /* Prepare for RTC alarm year compensation value. */
+ priv->fix_year = tm->tm_year / 64 * 64;
+ return 0;
+}
+
+static int loongson_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ int ret;
+ u32 rtc_data[2];
+ struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
+
+ rtc_data[0] = FIELD_PREP(TOY_SEC, tm->tm_sec)
+ | FIELD_PREP(TOY_MIN, tm->tm_min)
+ | FIELD_PREP(TOY_HOUR, tm->tm_hour)
+ | FIELD_PREP(TOY_DAY, tm->tm_mday)
+ | FIELD_PREP(TOY_MON, tm->tm_mon + 1);
+ rtc_data[1] = tm->tm_year;
+
+ ret = regmap_bulk_write(priv->regmap, TOY_WRITE0_REG, rtc_data,
+ ARRAY_SIZE(rtc_data));
+ if (ret < 0)
+ return ret;
+
+ return loongson_rtc_set_enabled(dev);
+}
+
+static int loongson_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ int ret;
+ u32 alarm_data;
+ struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
+
+ ret = regmap_read(priv->regmap, TOY_MATCH0_REG, &alarm_data);
+ if (ret < 0)
+ return ret;
+
+ alrm->time.tm_sec = FIELD_GET(TOY_MATCH_SEC, alarm_data);
+ alrm->time.tm_min = FIELD_GET(TOY_MATCH_MIN, alarm_data);
+ alrm->time.tm_hour = FIELD_GET(TOY_MATCH_HOUR, alarm_data);
+ alrm->time.tm_mday = FIELD_GET(TOY_MATCH_DAY, alarm_data);
+ alrm->time.tm_mon = FIELD_GET(TOY_MATCH_MON, alarm_data) - 1;
+ /*
+ * This is a hardware bug: the year field of SYS_TOYMATCH is only 6 bits,
+ * making it impossible to save year values larger than 64.
+ *
+ * SYS_TOYMATCH is used to match the alarm time value and determine if
+ * an alarm is triggered, so we must keep the lower 6 bits of the year
+ * value constant during the value conversion.
+ *
+ * In summary, we need to manually add 64(or a multiple of 64) to the
+ * year value to avoid the invalid alarm prompt at startup.
+ */
+ alrm->time.tm_year = FIELD_GET(TOY_MATCH_YEAR, alarm_data) + priv->fix_year;
+
+ alrm->enabled = !!(readl(priv->pm_base + PM1_EN_REG) & RTC_EN);
+ return 0;
+}
+
+static int loongson_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ u32 val;
+ struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
+
+ spin_lock(&priv->lock);
+ val = readl(priv->pm_base + PM1_EN_REG);
+ /* Enable RTC alarm wakeup */
+ writel(enabled ? val | RTC_EN : val & ~RTC_EN,
+ priv->pm_base + PM1_EN_REG);
+ spin_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int loongson_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ int ret;
+ u32 alarm_data;
+ struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
+
+ alarm_data = FIELD_PREP(TOY_MATCH_SEC, alrm->time.tm_sec)
+ | FIELD_PREP(TOY_MATCH_MIN, alrm->time.tm_min)
+ | FIELD_PREP(TOY_MATCH_HOUR, alrm->time.tm_hour)
+ | FIELD_PREP(TOY_MATCH_DAY, alrm->time.tm_mday)
+ | FIELD_PREP(TOY_MATCH_MON, alrm->time.tm_mon + 1)
+ | FIELD_PREP(TOY_MATCH_YEAR, alrm->time.tm_year - priv->fix_year);
+
+ ret = regmap_write(priv->regmap, TOY_MATCH0_REG, alarm_data);
+ if (ret < 0)
+ return ret;
+
+ return loongson_rtc_alarm_irq_enable(dev, alrm->enabled);
+}
+
+static const struct rtc_class_ops loongson_rtc_ops = {
+ .read_time = loongson_rtc_read_time,
+ .set_time = loongson_rtc_set_time,
+ .read_alarm = loongson_rtc_read_alarm,
+ .set_alarm = loongson_rtc_set_alarm,
+ .alarm_irq_enable = loongson_rtc_alarm_irq_enable,
+};
+
+static int loongson_rtc_probe(struct platform_device *pdev)
+{
+ int ret, alarm_irq;
+ void __iomem *regs;
+ struct loongson_rtc_priv *priv;
+ struct device *dev = &pdev->dev;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(regs))
+ return dev_err_probe(dev, PTR_ERR(regs),
+ "devm_platform_ioremap_resource failed\n");
+
+ priv->regmap = devm_regmap_init_mmio(dev, regs,
+ &loongson_rtc_regmap_config);
+ if (IS_ERR(priv->regmap))
+ return dev_err_probe(dev, PTR_ERR(priv->regmap),
+ "devm_regmap_init_mmio failed\n");
+
+ priv->config = device_get_match_data(dev);
+ spin_lock_init(&priv->lock);
+ platform_set_drvdata(pdev, priv);
+
+ priv->rtcdev = devm_rtc_allocate_device(dev);
+ if (IS_ERR(priv->rtcdev))
+ return dev_err_probe(dev, PTR_ERR(priv->rtcdev),
+ "devm_rtc_allocate_device failed\n");
+
+ /* Get RTC alarm irq */
+ alarm_irq = platform_get_irq(pdev, 0);
+ if (alarm_irq > 0) {
+ ret = devm_request_irq(dev, alarm_irq, loongson_rtc_isr,
+ 0, "loongson-alarm", priv);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Unable to request irq %d\n",
+ alarm_irq);
+
+ priv->pm_base = regs - priv->config->pm_offset;
+ device_init_wakeup(dev, 1);
+
+ if (has_acpi_companion(dev))
+ acpi_install_fixed_event_handler(ACPI_EVENT_RTC,
+ loongson_rtc_handler, priv);
+ } else {
+ /* Loongson-1C RTC does not support alarm */
+ clear_bit(RTC_FEATURE_ALARM, priv->rtcdev->features);
+ }
+
+ /* Loongson RTC does not support UIE */
+ clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, priv->rtcdev->features);
+ priv->rtcdev->ops = &loongson_rtc_ops;
+ priv->rtcdev->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ priv->rtcdev->range_max = RTC_TIMESTAMP_END_2099;
+
+ return devm_rtc_register_device(priv->rtcdev);
+}
+
+static void loongson_rtc_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
+
+ if (!test_bit(RTC_FEATURE_ALARM, priv->rtcdev->features))
+ return;
+
+ if (has_acpi_companion(dev))
+ acpi_remove_fixed_event_handler(ACPI_EVENT_RTC,
+ loongson_rtc_handler);
+
+ device_init_wakeup(dev, 0);
+ loongson_rtc_alarm_irq_enable(dev, 0);
+}
+
+static const struct of_device_id loongson_rtc_of_match[] = {
+ { .compatible = "loongson,ls1b-rtc", .data = &ls1b_rtc_config },
+ { .compatible = "loongson,ls1c-rtc", .data = &ls1c_rtc_config },
+ { .compatible = "loongson,ls7a-rtc", .data = &generic_rtc_config },
+ { .compatible = "loongson,ls2k1000-rtc", .data = &ls2k1000_rtc_config },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, loongson_rtc_of_match);
+
+static const struct acpi_device_id loongson_rtc_acpi_match[] = {
+ { "LOON0001", .driver_data = (kernel_ulong_t)&generic_rtc_config },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, loongson_rtc_acpi_match);
+
+static struct platform_driver loongson_rtc_driver = {
+ .probe = loongson_rtc_probe,
+ .remove_new = loongson_rtc_remove,
+ .driver = {
+ .name = "loongson-rtc",
+ .of_match_table = loongson_rtc_of_match,
+ .acpi_match_table = loongson_rtc_acpi_match,
+ },
+};
+module_platform_driver(loongson_rtc_driver);
+
+MODULE_DESCRIPTION("Loongson RTC driver");
+MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>");
+MODULE_AUTHOR("WANG Xuerui <git@xen0n.name>");
+MODULE_AUTHOR("Huacai Chen <chenhuacai@kernel.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c
deleted file mode 100644
index 5af26dc5c2a3..000000000000
--- a/drivers/rtc/rtc-ls1x.c
+++ /dev/null
@@ -1,192 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) 2011 Zhao Zhang <zhzhl555@gmail.com>
- *
- * Derived from driver/rtc/rtc-au1xxx.c
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/rtc.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/io.h>
-#include <loongson1.h>
-
-#define LS1X_RTC_REG_OFFSET (LS1X_RTC_BASE + 0x20)
-#define LS1X_RTC_REGS(x) \
- ((void __iomem *)KSEG1ADDR(LS1X_RTC_REG_OFFSET + (x)))
-
-/*RTC programmable counters 0 and 1*/
-#define SYS_COUNTER_CNTRL (LS1X_RTC_REGS(0x20))
-#define SYS_CNTRL_ERS (1 << 23)
-#define SYS_CNTRL_RTS (1 << 20)
-#define SYS_CNTRL_RM2 (1 << 19)
-#define SYS_CNTRL_RM1 (1 << 18)
-#define SYS_CNTRL_RM0 (1 << 17)
-#define SYS_CNTRL_RS (1 << 16)
-#define SYS_CNTRL_BP (1 << 14)
-#define SYS_CNTRL_REN (1 << 13)
-#define SYS_CNTRL_BRT (1 << 12)
-#define SYS_CNTRL_TEN (1 << 11)
-#define SYS_CNTRL_BTT (1 << 10)
-#define SYS_CNTRL_E0 (1 << 8)
-#define SYS_CNTRL_ETS (1 << 7)
-#define SYS_CNTRL_32S (1 << 5)
-#define SYS_CNTRL_TTS (1 << 4)
-#define SYS_CNTRL_TM2 (1 << 3)
-#define SYS_CNTRL_TM1 (1 << 2)
-#define SYS_CNTRL_TM0 (1 << 1)
-#define SYS_CNTRL_TS (1 << 0)
-
-/* Programmable Counter 0 Registers */
-#define SYS_TOYTRIM (LS1X_RTC_REGS(0))
-#define SYS_TOYWRITE0 (LS1X_RTC_REGS(4))
-#define SYS_TOYWRITE1 (LS1X_RTC_REGS(8))
-#define SYS_TOYREAD0 (LS1X_RTC_REGS(0xC))
-#define SYS_TOYREAD1 (LS1X_RTC_REGS(0x10))
-#define SYS_TOYMATCH0 (LS1X_RTC_REGS(0x14))
-#define SYS_TOYMATCH1 (LS1X_RTC_REGS(0x18))
-#define SYS_TOYMATCH2 (LS1X_RTC_REGS(0x1C))
-
-/* Programmable Counter 1 Registers */
-#define SYS_RTCTRIM (LS1X_RTC_REGS(0x40))
-#define SYS_RTCWRITE0 (LS1X_RTC_REGS(0x44))
-#define SYS_RTCREAD0 (LS1X_RTC_REGS(0x48))
-#define SYS_RTCMATCH0 (LS1X_RTC_REGS(0x4C))
-#define SYS_RTCMATCH1 (LS1X_RTC_REGS(0x50))
-#define SYS_RTCMATCH2 (LS1X_RTC_REGS(0x54))
-
-#define LS1X_SEC_OFFSET (4)
-#define LS1X_MIN_OFFSET (10)
-#define LS1X_HOUR_OFFSET (16)
-#define LS1X_DAY_OFFSET (21)
-#define LS1X_MONTH_OFFSET (26)
-
-
-#define LS1X_SEC_MASK (0x3f)
-#define LS1X_MIN_MASK (0x3f)
-#define LS1X_HOUR_MASK (0x1f)
-#define LS1X_DAY_MASK (0x1f)
-#define LS1X_MONTH_MASK (0x3f)
-#define LS1X_YEAR_MASK (0xffffffff)
-
-#define ls1x_get_sec(t) (((t) >> LS1X_SEC_OFFSET) & LS1X_SEC_MASK)
-#define ls1x_get_min(t) (((t) >> LS1X_MIN_OFFSET) & LS1X_MIN_MASK)
-#define ls1x_get_hour(t) (((t) >> LS1X_HOUR_OFFSET) & LS1X_HOUR_MASK)
-#define ls1x_get_day(t) (((t) >> LS1X_DAY_OFFSET) & LS1X_DAY_MASK)
-#define ls1x_get_month(t) (((t) >> LS1X_MONTH_OFFSET) & LS1X_MONTH_MASK)
-
-#define RTC_CNTR_OK (SYS_CNTRL_E0 | SYS_CNTRL_32S)
-
-static int ls1x_rtc_read_time(struct device *dev, struct rtc_time *rtm)
-{
- unsigned long v;
- time64_t t;
-
- v = readl(SYS_TOYREAD0);
- t = readl(SYS_TOYREAD1);
-
- memset(rtm, 0, sizeof(struct rtc_time));
- t = mktime64((t & LS1X_YEAR_MASK), ls1x_get_month(v),
- ls1x_get_day(v), ls1x_get_hour(v),
- ls1x_get_min(v), ls1x_get_sec(v));
- rtc_time64_to_tm(t, rtm);
-
- return 0;
-}
-
-static int ls1x_rtc_set_time(struct device *dev, struct rtc_time *rtm)
-{
- unsigned long v, t, c;
- int ret = -ETIMEDOUT;
-
- v = ((rtm->tm_mon + 1) << LS1X_MONTH_OFFSET)
- | (rtm->tm_mday << LS1X_DAY_OFFSET)
- | (rtm->tm_hour << LS1X_HOUR_OFFSET)
- | (rtm->tm_min << LS1X_MIN_OFFSET)
- | (rtm->tm_sec << LS1X_SEC_OFFSET);
-
- writel(v, SYS_TOYWRITE0);
- c = 0x10000;
- /* add timeout check counter, for more safe */
- while ((readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TS) && --c)
- usleep_range(1000, 3000);
-
- if (!c) {
- dev_err(dev, "set time timeout!\n");
- goto err;
- }
-
- t = rtm->tm_year + 1900;
- writel(t, SYS_TOYWRITE1);
- c = 0x10000;
- while ((readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TS) && --c)
- usleep_range(1000, 3000);
-
- if (!c) {
- dev_err(dev, "set time timeout!\n");
- goto err;
- }
- return 0;
-err:
- return ret;
-}
-
-static const struct rtc_class_ops ls1x_rtc_ops = {
- .read_time = ls1x_rtc_read_time,
- .set_time = ls1x_rtc_set_time,
-};
-
-static int ls1x_rtc_probe(struct platform_device *pdev)
-{
- struct rtc_device *rtcdev;
- unsigned long v;
-
- v = readl(SYS_COUNTER_CNTRL);
- if (!(v & RTC_CNTR_OK)) {
- dev_err(&pdev->dev, "rtc counters not working\n");
- return -ENODEV;
- }
-
- /* set to 1 HZ if needed */
- if (readl(SYS_TOYTRIM) != 32767) {
- v = 0x100000;
- while ((readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TTS) && --v)
- usleep_range(1000, 3000);
-
- if (!v) {
- dev_err(&pdev->dev, "time out\n");
- return -ETIMEDOUT;
- }
- writel(32767, SYS_TOYTRIM);
- }
- /* this loop coundn't be endless */
- while (readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TTS)
- usleep_range(1000, 3000);
-
- rtcdev = devm_rtc_allocate_device(&pdev->dev);
- if (IS_ERR(rtcdev))
- return PTR_ERR(rtcdev);
-
- platform_set_drvdata(pdev, rtcdev);
- rtcdev->ops = &ls1x_rtc_ops;
- rtcdev->range_min = RTC_TIMESTAMP_BEGIN_1900;
- rtcdev->range_max = RTC_TIMESTAMP_END_2099;
-
- return devm_rtc_register_device(rtcdev);
-}
-
-static struct platform_driver ls1x_rtc_driver = {
- .driver = {
- .name = "ls1x-rtc",
- },
- .probe = ls1x_rtc_probe,
-};
-
-module_platform_driver(ls1x_rtc_driver);
-
-MODULE_AUTHOR("zhao zhang <zhzhl555@gmail.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index c1963f7c424d..3cc5151e0986 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -1013,7 +1013,7 @@ static struct i2c_driver m41t80_driver = {
.of_match_table = of_match_ptr(m41t80_of_match),
.pm = &m41t80_pm,
},
- .probe_new = m41t80_probe,
+ .probe = m41t80_probe,
.remove = m41t80_remove,
.id_table = m41t80_id,
};
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c
index 0a33851cc51f..31b910e4d91a 100644
--- a/drivers/rtc/rtc-max6900.c
+++ b/drivers/rtc/rtc-max6900.c
@@ -224,7 +224,7 @@ static struct i2c_driver max6900_driver = {
.driver = {
.name = "rtc-max6900",
},
- .probe_new = max6900_probe,
+ .probe = max6900_probe,
.id_table = max6900_id,
};
diff --git a/drivers/rtc/rtc-nct3018y.c b/drivers/rtc/rtc-nct3018y.c
index 0a3b14c95d90..a4e3f924837e 100644
--- a/drivers/rtc/rtc-nct3018y.c
+++ b/drivers/rtc/rtc-nct3018y.c
@@ -540,7 +540,7 @@ static struct i2c_driver nct3018y_driver = {
.name = "rtc-nct3018y",
.of_match_table = of_match_ptr(nct3018y_of_match),
},
- .probe_new = nct3018y_probe,
+ .probe = nct3018y_probe,
.id_table = nct3018y_id,
};
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 87f4fc9df68b..ee03b04b74ba 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -923,7 +923,7 @@ static struct i2c_driver pcf2127_i2c_driver = {
.name = "rtc-pcf2127-i2c",
.of_match_table = of_match_ptr(pcf2127_of_match),
},
- .probe_new = pcf2127_i2c_probe,
+ .probe = pcf2127_i2c_probe,
.id_table = pcf2127_i2c_id,
};
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 71a456355981..e517abfaee2a 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -681,7 +681,7 @@ static struct i2c_driver pcf85063_driver = {
.name = "rtc-pcf85063",
.of_match_table = of_match_ptr(pcf85063_of_match),
},
- .probe_new = pcf85063_probe,
+ .probe = pcf85063_probe,
.id_table = pcf85063_ids,
};
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c
index e7115ebef707..d1efde3e7a80 100644
--- a/drivers/rtc/rtc-pcf8523.c
+++ b/drivers/rtc/rtc-pcf8523.c
@@ -488,7 +488,7 @@ static struct i2c_driver pcf8523_driver = {
.name = "rtc-pcf8523",
.of_match_table = pcf8523_of_match,
},
- .probe_new = pcf8523_probe,
+ .probe = pcf8523_probe,
.id_table = pcf8523_id,
};
module_i2c_driver(pcf8523_driver);
diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c
index 8958eadf1c3e..65b8b1338dbb 100644
--- a/drivers/rtc/rtc-pcf85363.c
+++ b/drivers/rtc/rtc-pcf85363.c
@@ -475,7 +475,7 @@ static struct i2c_driver pcf85363_driver = {
.name = "pcf85363",
.of_match_table = of_match_ptr(dev_ids),
},
- .probe_new = pcf85363_probe,
+ .probe = pcf85363_probe,
};
module_i2c_driver(pcf85363_driver);
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index 7e720472213c..ea82b89d8929 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -612,7 +612,7 @@ static struct i2c_driver pcf8563_driver = {
.name = "rtc-pcf8563",
.of_match_table = of_match_ptr(pcf8563_of_match),
},
- .probe_new = pcf8563_probe,
+ .probe = pcf8563_probe,
.id_table = pcf8563_id,
};
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
index 87074d178274..a7e0fc360b6a 100644
--- a/drivers/rtc/rtc-pcf8583.c
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -306,7 +306,7 @@ static struct i2c_driver pcf8583_driver = {
.driver = {
.name = "pcf8583",
},
- .probe_new = pcf8583_probe,
+ .probe = pcf8583_probe,
.id_table = pcf8583_id,
};
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index b4c5d016eca3..a5a6c8772ecd 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -921,7 +921,7 @@ static struct i2c_driver rs5c372_driver = {
.name = "rtc-rs5c372",
.of_match_table = of_match_ptr(rs5c372_of_match),
},
- .probe_new = rs5c372_probe,
+ .probe = rs5c372_probe,
.remove = rs5c372_remove,
.id_table = rs5c372_id,
};
diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c
index ec5d7a614e2d..076e56f4e01a 100644
--- a/drivers/rtc/rtc-rv3028.c
+++ b/drivers/rtc/rtc-rv3028.c
@@ -994,13 +994,20 @@ static const __maybe_unused struct of_device_id rv3028_of_match[] = {
};
MODULE_DEVICE_TABLE(of, rv3028_of_match);
+static const struct i2c_device_id rv3028_id_table[] = {
+ { .name = "rv3028", },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, rv3028_id_table);
+
static struct i2c_driver rv3028_driver = {
.driver = {
.name = "rtc-rv3028",
.acpi_match_table = rv3028_i2c_acpi_match,
.of_match_table = of_match_ptr(rv3028_of_match),
},
- .probe_new = rv3028_probe,
+ .id_table = rv3028_id_table,
+ .probe = rv3028_probe,
};
module_i2c_driver(rv3028_driver);
diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index 0852f6709a85..4a81feeb00ff 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -824,7 +824,7 @@ static struct i2c_driver rv3029_driver = {
.name = "rv3029",
.of_match_table = of_match_ptr(rv3029_of_match),
},
- .probe_new = rv3029_i2c_probe,
+ .probe = rv3029_i2c_probe,
.id_table = rv3029_id,
};
diff --git a/drivers/rtc/rtc-rv3032.c b/drivers/rtc/rtc-rv3032.c
index 1ff4f2e6fa77..6b8eb2039a33 100644
--- a/drivers/rtc/rtc-rv3032.c
+++ b/drivers/rtc/rtc-rv3032.c
@@ -842,7 +842,7 @@ static int rv3032_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
return err;
}
-static const struct hwmon_channel_info *rv3032_hwmon_info[] = {
+static const struct hwmon_channel_info * const rv3032_hwmon_info[] = {
HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST),
NULL
@@ -998,7 +998,7 @@ static struct i2c_driver rv3032_driver = {
.acpi_match_table = rv3032_i2c_acpi_match,
.of_match_table = of_match_ptr(rv3032_of_match),
},
- .probe_new = rv3032_probe,
+ .probe = rv3032_probe,
};
module_i2c_driver(rv3032_driver);
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 25c3b9e4f515..98679cae13e8 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -739,7 +739,7 @@ static struct i2c_driver rv8803_driver = {
.name = "rtc-rv8803",
.of_match_table = of_match_ptr(rv8803_of_match),
},
- .probe_new = rv8803_probe,
+ .probe = rv8803_probe,
.id_table = rv8803_id,
};
module_i2c_driver(rv8803_driver);
diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c
index 37608883a796..8702db6096ba 100644
--- a/drivers/rtc/rtc-rx6110.c
+++ b/drivers/rtc/rtc-rx6110.c
@@ -462,7 +462,7 @@ static struct i2c_driver rx6110_i2c_driver = {
.name = RX6110_DRIVER_NAME,
.acpi_match_table = rx6110_i2c_acpi_match,
},
- .probe_new = rx6110_i2c_probe,
+ .probe = rx6110_i2c_probe,
.id_table = rx6110_i2c_id,
};
diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c
index b9c8dad26208..f44e212c07de 100644
--- a/drivers/rtc/rtc-rx8010.c
+++ b/drivers/rtc/rtc-rx8010.c
@@ -424,7 +424,7 @@ static struct i2c_driver rx8010_driver = {
.name = "rtc-rx8010",
.of_match_table = of_match_ptr(rx8010_of_match),
},
- .probe_new = rx8010_probe,
+ .probe = rx8010_probe,
.id_table = rx8010_id,
};
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index 331c20d4d843..aabe62c283a1 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -581,7 +581,7 @@ static struct i2c_driver rx8025_driver = {
.driver = {
.name = "rtc-rx8025",
},
- .probe_new = rx8025_probe,
+ .probe = rx8025_probe,
.id_table = rx8025_id,
};
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c
index 14edb7534c97..82881fd2e14a 100644
--- a/drivers/rtc/rtc-rx8581.c
+++ b/drivers/rtc/rtc-rx8581.c
@@ -325,7 +325,7 @@ static struct i2c_driver rx8581_driver = {
.name = "rtc-rx8581",
.of_match_table = of_match_ptr(rx8581_of_match),
},
- .probe_new = rx8581_probe,
+ .probe = rx8581_probe,
.id_table = rx8581_id,
};
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index b18daaf72b17..90a3028ac574 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -499,7 +499,7 @@ static struct i2c_driver s35390a_driver = {
.name = "rtc-s35390a",
.of_match_table = of_match_ptr(s35390a_of_match),
},
- .probe_new = s35390a_probe,
+ .probe = s35390a_probe,
.id_table = s35390a_id,
};
diff --git a/drivers/rtc/rtc-sd3078.c b/drivers/rtc/rtc-sd3078.c
index e2f90d768ca8..7760394ccd2d 100644
--- a/drivers/rtc/rtc-sd3078.c
+++ b/drivers/rtc/rtc-sd3078.c
@@ -217,7 +217,7 @@ static struct i2c_driver sd3078_driver = {
.name = "sd3078",
.of_match_table = of_match_ptr(rtc_dt_match),
},
- .probe_new = sd3078_probe,
+ .probe = sd3078_probe,
.id_table = sd3078_id,
};
diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c
index 0f8e4231098e..d492a2d26600 100644
--- a/drivers/rtc/rtc-st-lpc.c
+++ b/drivers/rtc/rtc-st-lpc.c
@@ -228,17 +228,13 @@ static int st_rtc_probe(struct platform_device *pdev)
enable_irq_wake(rtc->irq);
disable_irq(rtc->irq);
- rtc->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(rtc->clk)) {
- dev_err(&pdev->dev, "Unable to request clock\n");
- return PTR_ERR(rtc->clk);
- }
-
- clk_prepare_enable(rtc->clk);
+ rtc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
+ if (IS_ERR(rtc->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(rtc->clk),
+ "Unable to request clock\n");
rtc->clkrate = clk_get_rate(rtc->clk);
if (!rtc->clkrate) {
- clk_disable_unprepare(rtc->clk);
dev_err(&pdev->dev, "Unable to fetch clock rate\n");
return -EINVAL;
}
@@ -252,10 +248,8 @@ static int st_rtc_probe(struct platform_device *pdev)
do_div(rtc->rtc_dev->range_max, rtc->clkrate);
ret = devm_rtc_register_device(rtc->rtc_dev);
- if (ret) {
- clk_disable_unprepare(rtc->clk);
+ if (ret)
return ret;
- }
return 0;
}
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index 229cb2847cc4..3d36e11cff80 100644
--- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c
@@ -114,7 +114,6 @@ struct stm32_rtc_data {
void (*clear_events)(struct stm32_rtc *rtc, unsigned int flags);
bool has_pclk;
bool need_dbp;
- bool has_wakeirq;
};
struct stm32_rtc {
@@ -127,7 +126,6 @@ struct stm32_rtc {
struct clk *rtc_ck;
const struct stm32_rtc_data *data;
int irq_alarm;
- int wakeirq_alarm;
};
static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
@@ -547,7 +545,6 @@ static void stm32_rtc_clear_events(struct stm32_rtc *rtc,
static const struct stm32_rtc_data stm32_rtc_data = {
.has_pclk = false,
.need_dbp = true,
- .has_wakeirq = false,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -569,7 +566,6 @@ static const struct stm32_rtc_data stm32_rtc_data = {
static const struct stm32_rtc_data stm32h7_rtc_data = {
.has_pclk = true,
.need_dbp = true,
- .has_wakeirq = false,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -600,7 +596,6 @@ static void stm32mp1_rtc_clear_events(struct stm32_rtc *rtc,
static const struct stm32_rtc_data stm32mp1_data = {
.has_pclk = true,
.need_dbp = false,
- .has_wakeirq = true,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -779,19 +774,12 @@ static int stm32_rtc_probe(struct platform_device *pdev)
}
ret = device_init_wakeup(&pdev->dev, true);
- if (rtc->data->has_wakeirq) {
- rtc->wakeirq_alarm = platform_get_irq(pdev, 1);
- if (rtc->wakeirq_alarm > 0) {
- ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
- rtc->wakeirq_alarm);
- } else {
- ret = rtc->wakeirq_alarm;
- if (rtc->wakeirq_alarm == -EPROBE_DEFER)
- goto err;
- }
- }
if (ret)
- dev_warn(&pdev->dev, "alarm can't wake up the system: %d", ret);
+ goto err;
+
+ ret = dev_pm_set_wake_irq(&pdev->dev, rtc->irq_alarm);
+ if (ret)
+ goto err;
platform_set_drvdata(pdev, rtc);
@@ -879,9 +867,6 @@ static int stm32_rtc_suspend(struct device *dev)
if (rtc->data->has_pclk)
clk_disable_unprepare(rtc->pclk);
- if (device_may_wakeup(dev))
- return enable_irq_wake(rtc->irq_alarm);
-
return 0;
}
@@ -903,9 +888,6 @@ static int stm32_rtc_resume(struct device *dev)
return ret;
}
- if (device_may_wakeup(dev))
- return disable_irq_wake(rtc->irq_alarm);
-
return ret;
}
#endif
diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index dc76537f1b62..71548dd59a3a 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -214,6 +214,7 @@ static int sun6i_rtc_osc_set_parent(struct clk_hw *hw, u8 index)
static const struct clk_ops sun6i_rtc_osc_ops = {
.recalc_rate = sun6i_rtc_osc_recalc_rate,
+ .determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = sun6i_rtc_osc_get_parent,
.set_parent = sun6i_rtc_osc_set_parent,
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index f587afa84357..807f953ae0ae 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -679,7 +679,7 @@ static struct i2c_driver x1205_driver = {
.name = "rtc-x1205",
.of_match_table = x1205_dt_ids,
},
- .probe_new = x1205_probe,
+ .probe = x1205_probe,
.remove = x1205_remove,
.id_table = x1205_id,
};
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 45788955c4e6..edcbf77852c3 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -2737,7 +2737,12 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr)
else if (status == 0) {
switch (cqr->intrc) {
case -EPERM:
- error = BLK_STS_NEXUS;
+ /*
+ * DASD doesn't implement SCSI/NVMe reservations, but it
+ * implements a locking scheme similar to them. We
+ * return this error when we no longer have the lock.
+ */
+ error = BLK_STS_RESV_CONFLICT;
break;
case -ENOLINK:
error = BLK_STS_TRANSPORT;
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 200f88f0e451..405d76df9427 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -54,7 +54,8 @@ static int dcssblk_dax_zero_page_range(struct dax_device *dax_dev,
rc = dax_direct_access(dax_dev, pgoff, nr_pages, DAX_ACCESS,
&kaddr, NULL);
if (rc < 0)
- return rc;
+ return dax_mem2blk_err(rc);
+
memset(kaddr, 0, nr_pages << PAGE_SHIFT);
dax_flush(dax_dev, kaddr, nr_pages << PAGE_SHIFT);
return 0;
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig
index 80c4e5101c97..8a03af5ee5b3 100644
--- a/drivers/s390/char/Kconfig
+++ b/drivers/s390/char/Kconfig
@@ -96,7 +96,7 @@ config SCLP_OFB
config S390_UV_UAPI
def_tristate m
prompt "Ultravisor userspace API"
- depends on S390
+ depends on S390 && (KVM || PROTECTED_VIRTUALIZATION_GUEST)
help
Selecting exposes parts of the UV interface to userspace
by providing a misc character device at /dev/uv.
diff --git a/drivers/s390/char/uvdevice.c b/drivers/s390/char/uvdevice.c
index 1d40457c7b10..144cd2e03590 100644
--- a/drivers/s390/char/uvdevice.c
+++ b/drivers/s390/char/uvdevice.c
@@ -32,6 +32,55 @@
#include <asm/uvdevice.h>
#include <asm/uv.h>
+#define BIT_UVIO_INTERNAL U32_MAX
+/* Mapping from IOCTL-nr to UVC-bit */
+static const u32 ioctl_nr_to_uvc_bit[] __initconst = {
+ [UVIO_IOCTL_UVDEV_INFO_NR] = BIT_UVIO_INTERNAL,
+ [UVIO_IOCTL_ATT_NR] = BIT_UVC_CMD_RETR_ATTEST,
+ [UVIO_IOCTL_ADD_SECRET_NR] = BIT_UVC_CMD_ADD_SECRET,
+ [UVIO_IOCTL_LIST_SECRETS_NR] = BIT_UVC_CMD_LIST_SECRETS,
+ [UVIO_IOCTL_LOCK_SECRETS_NR] = BIT_UVC_CMD_LOCK_SECRETS,
+};
+
+static_assert(ARRAY_SIZE(ioctl_nr_to_uvc_bit) == UVIO_IOCTL_NUM_IOCTLS);
+
+static struct uvio_uvdev_info uvdev_info = {
+ .supp_uvio_cmds = GENMASK_ULL(UVIO_IOCTL_NUM_IOCTLS - 1, 0),
+};
+
+static void __init set_supp_uv_cmds(unsigned long *supp_uv_cmds)
+{
+ int i;
+
+ for (i = 0; i < UVIO_IOCTL_NUM_IOCTLS; i++) {
+ if (ioctl_nr_to_uvc_bit[i] == BIT_UVIO_INTERNAL)
+ continue;
+ if (!test_bit_inv(ioctl_nr_to_uvc_bit[i], uv_info.inst_calls_list))
+ continue;
+ __set_bit(i, supp_uv_cmds);
+ }
+}
+
+/**
+ * uvio_uvdev_info() - get information about the uvdevice
+ *
+ * @uv_ioctl: ioctl control block
+ *
+ * Lists all IOCTLs that are supported by this uvdevice
+ */
+static int uvio_uvdev_info(struct uvio_ioctl_cb *uv_ioctl)
+{
+ void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr;
+
+ if (uv_ioctl->argument_len < sizeof(uvdev_info))
+ return -EINVAL;
+ if (copy_to_user(user_buf_arg, &uvdev_info, sizeof(uvdev_info)))
+ return -EFAULT;
+
+ uv_ioctl->uv_rc = UVC_RC_EXECUTED;
+ return 0;
+}
+
static int uvio_build_uvcb_attest(struct uv_cb_attest *uvcb_attest, u8 *arcb,
u8 *meas, u8 *add_data, struct uvio_attest *uvio_attest)
{
@@ -185,8 +234,161 @@ out:
return ret;
}
-static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *argp)
+/** uvio_add_secret() - perform an Add Secret UVC
+ *
+ * @uv_ioctl: ioctl control block
+ *
+ * uvio_add_secret() performs the Add Secret Ultravisor Call.
+ *
+ * The given userspace argument address and size are verified to be
+ * valid but every other check is made by the Ultravisor
+ * (UV). Therefore UV errors won't result in a negative return
+ * value. The request is then copied to kernelspace, the UV-call is
+ * performed and the results are copied back to userspace.
+ *
+ * The argument has to point to an Add Secret Request Control Block
+ * which is an encrypted and cryptographically verified request that
+ * inserts a protected guest's secrets into the Ultravisor for later
+ * use.
+ *
+ * If the Add Secret UV facility is not present, UV will return
+ * invalid command rc. This won't be fenced in the driver and does not
+ * result in a negative return value.
+ *
+ * Context: might sleep
+ *
+ * Return: 0 on success or a negative error code on error.
+ */
+static int uvio_add_secret(struct uvio_ioctl_cb *uv_ioctl)
{
+ void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr;
+ struct uv_cb_guest_addr uvcb = {
+ .header.len = sizeof(uvcb),
+ .header.cmd = UVC_CMD_ADD_SECRET,
+ };
+ void *asrcb = NULL;
+ int ret;
+
+ if (uv_ioctl->argument_len > UVIO_ADD_SECRET_MAX_LEN)
+ return -EINVAL;
+ if (uv_ioctl->argument_len == 0)
+ return -EINVAL;
+
+ asrcb = kvzalloc(uv_ioctl->argument_len, GFP_KERNEL);
+ if (!asrcb)
+ return -ENOMEM;
+
+ ret = -EFAULT;
+ if (copy_from_user(asrcb, user_buf_arg, uv_ioctl->argument_len))
+ goto out;
+
+ ret = 0;
+ uvcb.addr = (u64)asrcb;
+ uv_call_sched(0, (u64)&uvcb);
+ uv_ioctl->uv_rc = uvcb.header.rc;
+ uv_ioctl->uv_rrc = uvcb.header.rrc;
+
+out:
+ kvfree(asrcb);
+ return ret;
+}
+
+/** uvio_list_secrets() - perform a List Secret UVC
+ * @uv_ioctl: ioctl control block
+ *
+ * uvio_list_secrets() performs the List Secret Ultravisor Call. It verifies
+ * that the given userspace argument address is valid and its size is sane.
+ * Every other check is made by the Ultravisor (UV) and won't result in a
+ * negative return value. It builds the request, performs the UV-call, and
+ * copies the result to userspace.
+ *
+ * The argument specifies the location for the result of the UV-Call.
+ *
+ * If the List Secrets UV facility is not present, UV will return invalid
+ * command rc. This won't be fenced in the driver and does not result in a
+ * negative return value.
+ *
+ * Context: might sleep
+ *
+ * Return: 0 on success or a negative error code on error.
+ */
+static int uvio_list_secrets(struct uvio_ioctl_cb *uv_ioctl)
+{
+ void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr;
+ struct uv_cb_guest_addr uvcb = {
+ .header.len = sizeof(uvcb),
+ .header.cmd = UVC_CMD_LIST_SECRETS,
+ };
+ void *secrets = NULL;
+ int ret = 0;
+
+ if (uv_ioctl->argument_len != UVIO_LIST_SECRETS_LEN)
+ return -EINVAL;
+
+ secrets = kvzalloc(UVIO_LIST_SECRETS_LEN, GFP_KERNEL);
+ if (!secrets)
+ return -ENOMEM;
+
+ uvcb.addr = (u64)secrets;
+ uv_call_sched(0, (u64)&uvcb);
+ uv_ioctl->uv_rc = uvcb.header.rc;
+ uv_ioctl->uv_rrc = uvcb.header.rrc;
+
+ if (copy_to_user(user_buf_arg, secrets, UVIO_LIST_SECRETS_LEN))
+ ret = -EFAULT;
+
+ kvfree(secrets);
+ return ret;
+}
+
+/** uvio_lock_secrets() - perform a Lock Secret Store UVC
+ * @uv_ioctl: ioctl control block
+ *
+ * uvio_lock_secrets() performs the Lock Secret Store Ultravisor Call. It
+ * performs the UV-call and copies the return codes to the ioctl control block.
+ * After this call was dispatched successfully every following Add Secret UVC
+ * and Lock Secrets UVC will fail with return code 0x102.
+ *
+ * The argument address and size must be 0.
+ *
+ * If the Lock Secrets UV facility is not present, UV will return invalid
+ * command rc. This won't be fenced in the driver and does not result in a
+ * negative return value.
+ *
+ * Context: might sleep
+ *
+ * Return: 0 on success or a negative error code on error.
+ */
+static int uvio_lock_secrets(struct uvio_ioctl_cb *ioctl)
+{
+ struct uv_cb_nodata uvcb = {
+ .header.len = sizeof(uvcb),
+ .header.cmd = UVC_CMD_LOCK_SECRETS,
+ };
+
+ if (ioctl->argument_addr || ioctl->argument_len)
+ return -EINVAL;
+
+ uv_call(0, (u64)&uvcb);
+ ioctl->uv_rc = uvcb.header.rc;
+ ioctl->uv_rrc = uvcb.header.rrc;
+
+ return 0;
+}
+
+static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *argp,
+ unsigned long cmd)
+{
+ u8 nr = _IOC_NR(cmd);
+
+ if (_IOC_DIR(cmd) != (_IOC_READ | _IOC_WRITE))
+ return -ENOIOCTLCMD;
+ if (_IOC_TYPE(cmd) != UVIO_TYPE_UVC)
+ return -ENOIOCTLCMD;
+ if (nr >= UVIO_IOCTL_NUM_IOCTLS)
+ return -ENOIOCTLCMD;
+ if (_IOC_SIZE(cmd) != sizeof(*ioctl))
+ return -ENOIOCTLCMD;
if (copy_from_user(ioctl, argp, sizeof(*ioctl)))
return -EFAULT;
if (ioctl->flags != 0)
@@ -194,7 +396,7 @@ static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *a
if (memchr_inv(ioctl->reserved14, 0, sizeof(ioctl->reserved14)))
return -EINVAL;
- return 0;
+ return nr;
}
/*
@@ -205,14 +407,28 @@ static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
struct uvio_ioctl_cb uv_ioctl = { };
long ret;
+ int nr;
- switch (cmd) {
- case UVIO_IOCTL_ATT:
- ret = uvio_copy_and_check_ioctl(&uv_ioctl, argp);
- if (ret)
- return ret;
+ nr = uvio_copy_and_check_ioctl(&uv_ioctl, argp, cmd);
+ if (nr < 0)
+ return nr;
+
+ switch (nr) {
+ case UVIO_IOCTL_UVDEV_INFO_NR:
+ ret = uvio_uvdev_info(&uv_ioctl);
+ break;
+ case UVIO_IOCTL_ATT_NR:
ret = uvio_attestation(&uv_ioctl);
break;
+ case UVIO_IOCTL_ADD_SECRET_NR:
+ ret = uvio_add_secret(&uv_ioctl);
+ break;
+ case UVIO_IOCTL_LIST_SECRETS_NR:
+ ret = uvio_list_secrets(&uv_ioctl);
+ break;
+ case UVIO_IOCTL_LOCK_SECRETS_NR:
+ ret = uvio_lock_secrets(&uv_ioctl);
+ break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -245,6 +461,7 @@ static void __exit uvio_dev_exit(void)
static int __init uvio_dev_init(void)
{
+ set_supp_uv_cmds((unsigned long *)&uvdev_info.supp_uv_cmds);
return misc_register(&uvio_dev_miscdev);
}
diff --git a/drivers/sbus/char/oradax.c b/drivers/sbus/char/oradax.c
index aafce8d00000..a536dd6f4f7c 100644
--- a/drivers/sbus/char/oradax.c
+++ b/drivers/sbus/char/oradax.c
@@ -226,8 +226,10 @@ static int dax_ccb_info(u64 ca, struct ccb_info_result *info);
static int dax_ccb_kill(u64 ca, u16 *kill_res);
static struct cdev c_dev;
-static struct class *cl;
static dev_t first;
+static const struct class cl = {
+ .name = DAX_NAME,
+};
static int max_ccb_version;
static int dax_debug;
@@ -323,14 +325,11 @@ static int __init dax_attach(void)
goto done;
}
- cl = class_create(DAX_NAME);
- if (IS_ERR(cl)) {
- dax_err("class_create failed");
- ret = PTR_ERR(cl);
+ ret = class_register(&cl);
+ if (ret)
goto class_error;
- }
- if (device_create(cl, NULL, first, NULL, dax_name) == NULL) {
+ if (device_create(&cl, NULL, first, NULL, dax_name) == NULL) {
dax_err("device_create failed");
ret = -ENXIO;
goto device_error;
@@ -347,9 +346,9 @@ static int __init dax_attach(void)
goto done;
cdev_error:
- device_destroy(cl, first);
+ device_destroy(&cl, first);
device_error:
- class_destroy(cl);
+ class_unregister(&cl);
class_error:
unregister_chrdev_region(first, 1);
done:
@@ -362,8 +361,8 @@ static void __exit dax_detach(void)
{
pr_info("Cleaning up DAX module\n");
cdev_del(&c_dev);
- device_destroy(cl, first);
- class_destroy(cl);
+ device_destroy(&cl, first);
+ class_unregister(&cl);
unregister_chrdev_region(first, 1);
}
module_exit(dax_detach);
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 36c34ced0cc1..f39c9ec2e781 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -2305,8 +2305,10 @@ static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
TW_DISABLE_INTERRUPTS(tw_dev);
/* Initialize the card */
- if (tw_reset_sequence(tw_dev))
+ if (tw_reset_sequence(tw_dev)) {
+ retval = -EINVAL;
goto out_release_mem_region;
+ }
/* Set host specific parameters */
host->max_id = TW_MAX_UNITS;
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 0704809d9d99..4962ce989113 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -334,7 +334,7 @@ config SGIWD93_SCSI
config BLK_DEV_3W_XXXX_RAID
tristate "3ware 5/6/7/8xxx ATA-RAID support"
- depends on PCI && SCSI
+ depends on PCI && HAS_IOPORT && SCSI
help
3ware is the only hardware ATA-Raid product in Linux to date.
This card is 2,4, or 8 channel master mode support only.
@@ -381,7 +381,7 @@ config SCSI_3W_SAS
config SCSI_ACARD
tristate "ACARD SCSI support"
- depends on PCI && SCSI
+ depends on PCI && HAS_IOPORT && SCSI
help
This driver supports the ACARD SCSI host adapter.
Support Chip <ATP870 ATP876 ATP880 ATP885>
@@ -462,7 +462,7 @@ config SCSI_MVUMI
config SCSI_ADVANSYS
tristate "AdvanSys SCSI support"
depends on SCSI
- depends on ISA || EISA || PCI
+ depends on (ISA || EISA || PCI) && HAS_IOPORT
depends on ISA_DMA_API || !ISA
help
This is a driver for all SCSI host adapters manufactured by
@@ -503,7 +503,7 @@ config SCSI_HPTIOP
config SCSI_BUSLOGIC
tristate "BusLogic SCSI support"
- depends on PCI && SCSI
+ depends on SCSI && PCI && HAS_IOPORT
help
This is support for BusLogic MultiMaster and FlashPoint SCSI Host
Adapters. Consult the SCSI-HOWTO, available from
@@ -518,7 +518,7 @@ config SCSI_BUSLOGIC
config SCSI_FLASHPOINT
bool "FlashPoint support"
- depends on SCSI_BUSLOGIC && PCI
+ depends on SCSI_BUSLOGIC && PCI && HAS_IOPORT
help
This option allows you to add FlashPoint support to the
BusLogic SCSI driver. The FlashPoint SCCB Manager code is
@@ -632,7 +632,7 @@ config SCSI_SNIC_DEBUG_FS
config SCSI_DMX3191D
tristate "DMX3191D SCSI support"
- depends on PCI && SCSI
+ depends on PCI && HAS_IOPORT && SCSI
select SCSI_SPI_ATTRS
help
This is support for Domex DMX3191D SCSI Host Adapters.
@@ -646,7 +646,7 @@ config SCSI_FDOMAIN
config SCSI_FDOMAIN_PCI
tristate "Future Domain TMC-3260/AHA-2920A PCI SCSI support"
- depends on PCI && SCSI
+ depends on PCI && HAS_IOPORT && SCSI
select SCSI_FDOMAIN
help
This is support for Future Domain's PCI SCSI host adapters (TMC-3260)
@@ -699,7 +699,7 @@ config SCSI_GENERIC_NCR5380
config SCSI_IPS
tristate "IBM ServeRAID support"
- depends on PCI && SCSI
+ depends on PCI && HAS_IOPORT && SCSI
help
This is support for the IBM ServeRAID hardware RAID controllers.
See <http://www.developer.ibm.com/welcome/netfinity/serveraid.html>
@@ -759,7 +759,7 @@ config SCSI_IBMVFC_TRACE
config SCSI_INITIO
tristate "Initio 9100U(W) support"
- depends on PCI && SCSI
+ depends on PCI && HAS_IOPORT && SCSI
help
This is support for the Initio 91XXU(W) SCSI host adapter. Please
read the SCSI-HOWTO, available from
@@ -770,7 +770,7 @@ config SCSI_INITIO
config SCSI_INIA100
tristate "Initio INI-A100U2W support"
- depends on PCI && SCSI
+ depends on PCI && HAS_IOPORT && SCSI
help
This is support for the Initio INI-A100U2W SCSI host adapter.
Please read the SCSI-HOWTO, available from
@@ -782,6 +782,7 @@ config SCSI_INIA100
config SCSI_PPA
tristate "IOMEGA parallel port (ppa - older drives)"
depends on SCSI && PARPORT_PC
+ depends on HAS_IOPORT
help
This driver supports older versions of IOMEGA's parallel port ZIP
drive (a 100 MB removable media device).
@@ -1175,7 +1176,7 @@ config SCSI_SIM710
config SCSI_DC395x
tristate "Tekram DC395(U/UW/F) and DC315(U) SCSI support"
- depends on PCI && SCSI
+ depends on PCI && HAS_IOPORT && SCSI
select SCSI_SPI_ATTRS
help
This driver supports PCI SCSI host adapters based on the ASIC
@@ -1207,7 +1208,7 @@ config SCSI_AM53C974
config SCSI_NSP32
tristate "Workbit NinjaSCSI-32Bi/UDE support"
- depends on PCI && SCSI && !64BIT
+ depends on PCI && SCSI && !64BIT && HAS_IOPORT
help
This is support for the Workbit NinjaSCSI-32Bi/UDE PCI/Cardbus
SCSI host adapter. Please read the SCSI-HOWTO, available from
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index a47dbd500e9a..4bc53eec4c83 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -5,7 +5,7 @@
#
config SCSI_AIC79XX
tristate "Adaptec AIC79xx U320 support"
- depends on PCI && SCSI
+ depends on PCI && HAS_IOPORT && SCSI
select SCSI_SPI_ATTRS
help
This driver supports all of Adaptec's Ultra 320 PCI-X
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index 0cfd92ce750a..f0425145a5f4 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -5,7 +5,7 @@
#
config SCSI_AIC7XXX
tristate "Adaptec AIC7xxx Fast -> U160 support"
- depends on (PCI || EISA) && SCSI
+ depends on (PCI || EISA) && HAS_IOPORT && SCSI
select SCSI_SPI_ATTRS
help
This driver supports all of Adaptec's Fast through Ultra 160 PCI
diff --git a/drivers/scsi/aic94xx/Kconfig b/drivers/scsi/aic94xx/Kconfig
index 71931c371b1c..aaa8dadc6e1c 100644
--- a/drivers/scsi/aic94xx/Kconfig
+++ b/drivers/scsi/aic94xx/Kconfig
@@ -8,7 +8,7 @@
config SCSI_AIC94XX
tristate "Adaptec AIC94xx SAS/SATA support"
- depends on PCI
+ depends on PCI && HAS_IOPORT
select SCSI_SAS_LIBSAS
select FW_LOADER
help
diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
index df18d9d2af53..773c84af784c 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.c
+++ b/drivers/scsi/bfa/bfa_fcbuild.c
@@ -1134,7 +1134,7 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s));
rspnid->dap = s_id;
- strlcpy(rspnid->spn, name, sizeof(rspnid->spn));
+ strscpy(rspnid->spn, name, sizeof(rspnid->spn));
rspnid->spn_len = (u8) strlen(rspnid->spn);
return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s);
@@ -1155,7 +1155,7 @@ fc_rsnn_nn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
memset(rsnn_nn, 0, sizeof(struct fcgs_rsnn_nn_req_s));
rsnn_nn->node_name = node_name;
- strlcpy(rsnn_nn->snn, name, sizeof(rsnn_nn->snn));
+ strscpy(rsnn_nn->snn, name, sizeof(rsnn_nn->snn));
rsnn_nn->snn_len = (u8) strlen(rsnn_nn->snn);
return sizeof(struct fcgs_rsnn_nn_req_s) + sizeof(struct ct_hdr_s);
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index d2d396ca0e9a..5023c0ab4277 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -761,7 +761,7 @@ bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
/* Model name/number */
- strlcpy(port_cfg->sym_name.symname, model,
+ strscpy(port_cfg->sym_name.symname, model,
BFA_SYMNAME_MAXLEN);
strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
BFA_SYMNAME_MAXLEN);
@@ -822,7 +822,7 @@ bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric)
bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
/* Model name/number */
- strlcpy(port_cfg->node_sym_name.symname, model,
+ strscpy(port_cfg->node_sym_name.symname, model,
BFA_SYMNAME_MAXLEN);
strlcat(port_cfg->node_sym_name.symname,
BFA_FCS_PORT_SYMBNAME_SEPARATOR,
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index b12afcc4b189..008afd817087 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -2642,10 +2642,10 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
hba_attr->fw_version);
- strlcpy(hba_attr->driver_version, (char *)driver_info->version,
+ strscpy(hba_attr->driver_version, (char *)driver_info->version,
sizeof(hba_attr->driver_version));
- strlcpy(hba_attr->os_name, driver_info->host_os_name,
+ strscpy(hba_attr->os_name, driver_info->host_os_name,
sizeof(hba_attr->os_name));
/*
@@ -2663,13 +2663,13 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size;
- strlcpy(hba_attr->node_sym_name.symname,
+ strscpy(hba_attr->node_sym_name.symname,
port->port_cfg.node_sym_name.symname, BFA_SYMNAME_MAXLEN);
strcpy(hba_attr->vendor_info, "QLogic");
hba_attr->num_ports =
cpu_to_be32(bfa_ioc_get_nports(&port->fcs->bfa->ioc));
hba_attr->fabric_name = port->fabric->lps->pr_nwwn;
- strlcpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN);
+ strscpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN);
}
@@ -2736,19 +2736,19 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
/*
* OS device Name
*/
- strlcpy(port_attr->os_device_name, driver_info->os_device_name,
+ strscpy(port_attr->os_device_name, driver_info->os_device_name,
sizeof(port_attr->os_device_name));
/*
* Host name
*/
- strlcpy(port_attr->host_name, driver_info->host_machine_name,
+ strscpy(port_attr->host_name, driver_info->host_machine_name,
sizeof(port_attr->host_name));
port_attr->node_name = bfa_fcs_lport_get_nwwn(port);
port_attr->port_name = bfa_fcs_lport_get_pwwn(port);
- strlcpy(port_attr->port_sym_name.symname,
+ strscpy(port_attr->port_sym_name.symname,
bfa_fcs_lport_get_psym_name(port).symname, BFA_SYMNAME_MAXLEN);
bfa_fcs_lport_get_attr(port, &lport_attr);
port_attr->port_type = cpu_to_be32(lport_attr.port_type);
@@ -3229,7 +3229,7 @@ bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
rsp_str[gmal_entry->len-1] = 0;
/* copy IP Address to fabric */
- strlcpy(bfa_fcs_lport_get_fabric_ipaddr(port),
+ strscpy(bfa_fcs_lport_get_fabric_ipaddr(port),
gmal_entry->ip_addr,
BFA_FCS_FABRIC_IPADDR_SZ);
break;
@@ -4667,7 +4667,7 @@ bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
* to that of the base port.
*/
- strlcpy(symbl,
+ strscpy(symbl,
(char *)&(bfa_fcs_lport_get_psym_name
(bfa_fcs_get_base_port(port->fcs))),
sizeof(symbl));
@@ -5194,7 +5194,7 @@ bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
* For Vports, we append the vport's port symbolic name
* to that of the base port.
*/
- strlcpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name
+ strscpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name
(bfa_fcs_get_base_port(port->fcs))),
sizeof(symbl));
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 5740302d83ac..e1ed1424fddb 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -2788,7 +2788,7 @@ void
bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer)
{
memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
- strlcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
+ strscpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
}
void
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index 4e3cef02f10f..c9745c0b4eee 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -330,7 +330,7 @@ bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
lp.eid = event;
lp.log_type = BFA_PL_LOG_TYPE_STRING;
lp.misc = misc;
- strlcpy(lp.log_entry.string_log, log_str,
+ strscpy(lp.log_entry.string_log, log_str,
BFA_PL_STRING_LOG_SZ);
lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
bfa_plog_add(plog, &lp);
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 529b73a83d69..62cb7a864fd5 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -965,19 +965,19 @@ bfad_start_ops(struct bfad_s *bfad) {
/* Fill the driver_info info to fcs*/
memset(&driver_info, 0, sizeof(driver_info));
- strlcpy(driver_info.version, BFAD_DRIVER_VERSION,
+ strscpy(driver_info.version, BFAD_DRIVER_VERSION,
sizeof(driver_info.version));
if (host_name)
- strlcpy(driver_info.host_machine_name, host_name,
+ strscpy(driver_info.host_machine_name, host_name,
sizeof(driver_info.host_machine_name));
if (os_name)
- strlcpy(driver_info.host_os_name, os_name,
+ strscpy(driver_info.host_os_name, os_name,
sizeof(driver_info.host_os_name));
if (os_patch)
- strlcpy(driver_info.host_os_patch, os_patch,
+ strscpy(driver_info.host_os_patch, os_patch,
sizeof(driver_info.host_os_patch));
- strlcpy(driver_info.os_device_name, bfad->pci_name,
+ strscpy(driver_info.os_device_name, bfad->pci_name,
sizeof(driver_info.os_device_name));
/* FCS driver info init */
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index 5a85401e9e2d..e96e4b6df265 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -834,7 +834,7 @@ bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr,
char symname[BFA_SYMNAME_MAXLEN];
bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
- strlcpy(symname, port_attr.port_cfg.sym_name.symname,
+ strscpy(symname, port_attr.port_cfg.sym_name.symname,
BFA_SYMNAME_MAXLEN);
return sysfs_emit(buf, "%s\n", symname);
}
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 79d4f7ee5bcb..520f9152f3bf 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -119,7 +119,7 @@ bfad_iocmd_ioc_get_attr(struct bfad_s *bfad, void *cmd)
/* fill in driver attr info */
strcpy(iocmd->ioc_attr.driver_attr.driver, BFAD_DRIVER_NAME);
- strlcpy(iocmd->ioc_attr.driver_attr.driver_ver,
+ strscpy(iocmd->ioc_attr.driver_attr.driver_ver,
BFAD_DRIVER_VERSION, BFA_VERSION_LEN);
strcpy(iocmd->ioc_attr.driver_attr.fw_ver,
iocmd->ioc_attr.adapter_attr.fw_ver);
@@ -307,7 +307,7 @@ bfad_iocmd_port_get_attr(struct bfad_s *bfad, void *cmd)
iocmd->attr.port_type = port_attr.port_type;
iocmd->attr.loopback = port_attr.loopback;
iocmd->attr.authfail = port_attr.authfail;
- strlcpy(iocmd->attr.port_symname.symname,
+ strscpy(iocmd->attr.port_symname.symname,
port_attr.port_cfg.sym_name.symname,
sizeof(iocmd->attr.port_symname.symname));
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index c335f7a188d2..a9d3d8562d3c 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -1046,7 +1046,7 @@ bfad_fc_host_init(struct bfad_im_port_s *im_port)
/* For fibre channel services type 0x20 */
fc_host_supported_fc4s(host)[7] = 1;
- strlcpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname,
+ strscpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname,
BFA_SYMNAME_MAXLEN);
sprintf(fc_host_symbolic_name(host), "%s", symname);
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c
index 46b0bf237be1..a48d24af9ac3 100644
--- a/drivers/scsi/fcoe/fcoe_transport.c
+++ b/drivers/scsi/fcoe/fcoe_transport.c
@@ -711,7 +711,7 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer)
char ifname[IFNAMSIZ + 2];
if (buffer) {
- strlcpy(ifname, buffer, IFNAMSIZ);
+ strscpy(ifname, buffer, IFNAMSIZ);
cp = ifname + strlen(ifname);
while (--cp >= ifname && *cp == '\n')
*cp = '\0';
diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c
index 6fedc3b7d1ab..c4d9ed0d7d75 100644
--- a/drivers/scsi/fnic/fnic_debugfs.c
+++ b/drivers/scsi/fnic/fnic_debugfs.c
@@ -201,25 +201,21 @@ static int fnic_trace_debugfs_open(struct inode *inode,
return -ENOMEM;
if (*rdata_ptr == fc_trc_flag->fnic_trace) {
- fnic_dbg_prt->buffer = vmalloc(array3_size(3, trace_max_pages,
+ fnic_dbg_prt->buffer = vzalloc(array3_size(3, trace_max_pages,
PAGE_SIZE));
if (!fnic_dbg_prt->buffer) {
kfree(fnic_dbg_prt);
return -ENOMEM;
}
- memset((void *)fnic_dbg_prt->buffer, 0,
- 3 * (trace_max_pages * PAGE_SIZE));
fnic_dbg_prt->buffer_len = fnic_get_trace_data(fnic_dbg_prt);
} else {
fnic_dbg_prt->buffer =
- vmalloc(array3_size(3, fnic_fc_trace_max_pages,
+ vzalloc(array3_size(3, fnic_fc_trace_max_pages,
PAGE_SIZE));
if (!fnic_dbg_prt->buffer) {
kfree(fnic_dbg_prt);
return -ENOMEM;
}
- memset((void *)fnic_dbg_prt->buffer, 0,
- 3 * (fnic_fc_trace_max_pages * PAGE_SIZE));
fnic_dbg_prt->buffer_len =
fnic_fc_trace_get_data(fnic_dbg_prt, *rdata_ptr);
}
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index fb7c52c119df..9e73e9cbbcfc 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -642,7 +642,7 @@ extern void hisi_sas_sata_done(struct sas_task *task,
extern int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba);
extern int hisi_sas_probe(struct platform_device *pdev,
const struct hisi_sas_hw *ops);
-extern int hisi_sas_remove(struct platform_device *pdev);
+extern void hisi_sas_remove(struct platform_device *pdev);
extern int hisi_sas_slave_configure(struct scsi_device *sdev);
extern int hisi_sas_slave_alloc(struct scsi_device *sdev);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 412431c901a7..8f22ece957bd 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -2560,7 +2560,7 @@ err_out_ha:
}
EXPORT_SYMBOL_GPL(hisi_sas_probe);
-int hisi_sas_remove(struct platform_device *pdev)
+void hisi_sas_remove(struct platform_device *pdev)
{
struct sas_ha_struct *sha = platform_get_drvdata(pdev);
struct hisi_hba *hisi_hba = sha->lldd_ha;
@@ -2573,7 +2573,6 @@ int hisi_sas_remove(struct platform_device *pdev)
hisi_sas_free(hisi_hba);
scsi_host_put(shost);
- return 0;
}
EXPORT_SYMBOL_GPL(hisi_sas_remove);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 0aa8c9c88535..94fbbceddc2e 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1790,11 +1790,6 @@ static int hisi_sas_v1_probe(struct platform_device *pdev)
return hisi_sas_probe(pdev, &hisi_sas_v1_hw);
}
-static int hisi_sas_v1_remove(struct platform_device *pdev)
-{
- return hisi_sas_remove(pdev);
-}
-
static const struct of_device_id sas_v1_of_match[] = {
{ .compatible = "hisilicon,hip05-sas-v1",},
{},
@@ -1810,7 +1805,7 @@ MODULE_DEVICE_TABLE(acpi, sas_v1_acpi_match);
static struct platform_driver hisi_sas_v1_driver = {
.probe = hisi_sas_v1_probe,
- .remove = hisi_sas_v1_remove,
+ .remove_new = hisi_sas_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = sas_v1_of_match,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index cd78e4c983aa..87d8e408ccd1 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -3619,11 +3619,6 @@ static int hisi_sas_v2_probe(struct platform_device *pdev)
return hisi_sas_probe(pdev, &hisi_sas_v2_hw);
}
-static int hisi_sas_v2_remove(struct platform_device *pdev)
-{
- return hisi_sas_remove(pdev);
-}
-
static const struct of_device_id sas_v2_of_match[] = {
{ .compatible = "hisilicon,hip06-sas-v2",},
{ .compatible = "hisilicon,hip07-sas-v2",},
@@ -3640,7 +3635,7 @@ MODULE_DEVICE_TABLE(acpi, sas_v2_acpi_match);
static struct platform_driver hisi_sas_v2_driver = {
.probe = hisi_sas_v2_probe,
- .remove = hisi_sas_v2_remove,
+ .remove_new = hisi_sas_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = sas_v2_of_match,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 12d588454f5d..20e1607c6282 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -30,6 +30,7 @@
#define SATA_INITI_D2H_STORE_ADDR_LO 0x60
#define SATA_INITI_D2H_STORE_ADDR_HI 0x64
#define CFG_MAX_TAG 0x68
+#define TRANS_LOCK_ICT_TIME 0X70
#define HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL 0x84
#define HGC_SAS_TXFAIL_RETRY_CTRL 0x88
#define HGC_GET_ITV_TIME 0x90
@@ -627,13 +628,15 @@ static void interrupt_enable_v3_hw(struct hisi_hba *hisi_hba)
static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
{
+ struct pci_dev *pdev = hisi_hba->pci_dev;
int i, j;
/* Global registers init */
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE,
(u32)((1ULL << hisi_hba->queue_count) - 1));
- hisi_sas_write32(hisi_hba, SAS_AXI_USER3, 0);
hisi_sas_write32(hisi_hba, CFG_MAX_TAG, 0xfff0400);
+ /* time / CLK_AHB = 2.5s / 2ns = 0x4A817C80 */
+ hisi_sas_write32(hisi_hba, TRANS_LOCK_ICT_TIME, 0x4A817C80);
hisi_sas_write32(hisi_hba, HGC_SAS_TXFAIL_RETRY_CTRL, 0x108);
hisi_sas_write32(hisi_hba, CFG_AGING_TIME, 0x1);
hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x1);
@@ -652,6 +655,9 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_write32(hisi_hba, ARQOS_ARCACHE_CFG, 0xf0f0);
hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1);
+ if (pdev->revision < 0x30)
+ hisi_sas_write32(hisi_hba, SAS_AXI_USER3, 0);
+
interrupt_enable_v3_hw(hisi_hba);
for (i = 0; i < hisi_hba->n_phy; i++) {
enum sas_linkrate max;
@@ -669,7 +675,6 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE,
prog_phy_link_rate);
- hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00);
hisi_sas_phy_write32(hisi_hba, i, SAS_RX_TRAIN_TIMER, 0x13e80);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff);
@@ -680,13 +685,18 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x1);
hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7f7a120);
hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER, 0x2a0a01);
- hisi_sas_phy_write32(hisi_hba, i, SAS_SSP_CON_TIMER_CFG, 0x32);
hisi_sas_phy_write32(hisi_hba, i, SAS_EC_INT_COAL_TIME,
0x30f4240);
- /* used for 12G negotiate */
- hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e);
hisi_sas_phy_write32(hisi_hba, i, AIP_LIMIT, 0x2ffff);
+ /* set value through firmware for 920B and later version */
+ if (pdev->revision < 0x30) {
+ hisi_sas_phy_write32(hisi_hba, i, SAS_SSP_CON_TIMER_CFG, 0x32);
+ hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00);
+ /* used for 12G negotiate */
+ hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e);
+ }
+
/* get default FFE configuration for BIST */
for (j = 0; j < FFE_CFG_MAX; j++) {
u32 val = hisi_sas_phy_read32(hisi_hba, i,
@@ -2206,6 +2216,7 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
u32 trans_tx_fail_type = le32_to_cpu(record->trans_tx_fail_type);
u16 sipc_rx_err_type = le16_to_cpu(record->sipc_rx_err_type);
u32 dw3 = le32_to_cpu(complete_hdr->dw3);
+ u32 dw0 = le32_to_cpu(complete_hdr->dw0);
switch (task->task_proto) {
case SAS_PROTOCOL_SSP:
@@ -2215,8 +2226,8 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
* but I/O information has been written to the host memory, we examine
* response IU.
*/
- if (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_GOOD_MSK) &&
- (complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))
+ if (!(dw0 & CMPLT_HDR_RSPNS_GOOD_MSK) &&
+ (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))
return false;
ts->residual = trans_tx_fail_type;
@@ -2232,7 +2243,7 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
case SAS_PROTOCOL_SATA:
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
- if ((complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) &&
+ if ((dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) &&
(sipc_rx_err_type & RX_FIS_STATUS_ERR_MSK)) {
ts->stat = SAS_PROTO_RESPONSE;
} else if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) {
@@ -2999,6 +3010,7 @@ static const struct hisi_sas_debugfs_reg_lu debugfs_global_reg_lu[] = {
HISI_SAS_DEBUGFS_REG(SATA_INITI_D2H_STORE_ADDR_LO),
HISI_SAS_DEBUGFS_REG(SATA_INITI_D2H_STORE_ADDR_HI),
HISI_SAS_DEBUGFS_REG(CFG_MAX_TAG),
+ HISI_SAS_DEBUGFS_REG(TRANS_LOCK_ICT_TIME),
HISI_SAS_DEBUGFS_REG(HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL),
HISI_SAS_DEBUGFS_REG(HGC_SAS_TXFAIL_RETRY_CTRL),
HISI_SAS_DEBUGFS_REG(HGC_GET_ITV_TIME),
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index f0bc8bbb3938..198edf03f929 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -441,6 +441,7 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv
shost->cmd_per_lun = sht->cmd_per_lun;
shost->no_write_same = sht->no_write_same;
shost->host_tagset = sht->host_tagset;
+ shost->queuecommand_may_block = sht->queuecommand_may_block;
if (shost_eh_deadline == -1 || !sht->eh_host_reset_handler)
shost->eh_deadline = -1;
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index dc670304f181..adcac57aaee6 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -1198,37 +1198,37 @@ static void sas_print_parent_topology_bug(struct domain_device *child,
sas_route_char(child, child_phy));
}
+static bool sas_eeds_valid(struct domain_device *parent,
+ struct domain_device *child)
+{
+ struct sas_discovery *disc = &parent->port->disc;
+
+ return (SAS_ADDR(disc->eeds_a) == SAS_ADDR(parent->sas_addr) ||
+ SAS_ADDR(disc->eeds_a) == SAS_ADDR(child->sas_addr)) &&
+ (SAS_ADDR(disc->eeds_b) == SAS_ADDR(parent->sas_addr) ||
+ SAS_ADDR(disc->eeds_b) == SAS_ADDR(child->sas_addr));
+}
+
static int sas_check_eeds(struct domain_device *child,
- struct ex_phy *parent_phy,
- struct ex_phy *child_phy)
+ struct ex_phy *parent_phy,
+ struct ex_phy *child_phy)
{
int res = 0;
struct domain_device *parent = child->parent;
+ struct sas_discovery *disc = &parent->port->disc;
- if (SAS_ADDR(parent->port->disc.fanout_sas_addr) != 0) {
+ if (SAS_ADDR(disc->fanout_sas_addr) != 0) {
res = -ENODEV;
pr_warn("edge ex %016llx phy S:%02d <--> edge ex %016llx phy S:%02d, while there is a fanout ex %016llx\n",
SAS_ADDR(parent->sas_addr),
parent_phy->phy_id,
SAS_ADDR(child->sas_addr),
child_phy->phy_id,
- SAS_ADDR(parent->port->disc.fanout_sas_addr));
- } else if (SAS_ADDR(parent->port->disc.eeds_a) == 0) {
- memcpy(parent->port->disc.eeds_a, parent->sas_addr,
- SAS_ADDR_SIZE);
- memcpy(parent->port->disc.eeds_b, child->sas_addr,
- SAS_ADDR_SIZE);
- } else if (((SAS_ADDR(parent->port->disc.eeds_a) ==
- SAS_ADDR(parent->sas_addr)) ||
- (SAS_ADDR(parent->port->disc.eeds_a) ==
- SAS_ADDR(child->sas_addr)))
- &&
- ((SAS_ADDR(parent->port->disc.eeds_b) ==
- SAS_ADDR(parent->sas_addr)) ||
- (SAS_ADDR(parent->port->disc.eeds_b) ==
- SAS_ADDR(child->sas_addr))))
- ;
- else {
+ SAS_ADDR(disc->fanout_sas_addr));
+ } else if (SAS_ADDR(disc->eeds_a) == 0) {
+ memcpy(disc->eeds_a, parent->sas_addr, SAS_ADDR_SIZE);
+ memcpy(disc->eeds_b, child->sas_addr, SAS_ADDR_SIZE);
+ } else if (!sas_eeds_valid(parent, child)) {
res = -ENODEV;
pr_warn("edge ex %016llx phy%02d <--> edge ex %016llx phy%02d link forms a third EEDS!\n",
SAS_ADDR(parent->sas_addr),
@@ -1240,11 +1240,56 @@ static int sas_check_eeds(struct domain_device *child,
return res;
}
-/* Here we spill over 80 columns. It is intentional.
- */
-static int sas_check_parent_topology(struct domain_device *child)
+static int sas_check_edge_expander_topo(struct domain_device *child,
+ struct ex_phy *parent_phy)
+{
+ struct expander_device *child_ex = &child->ex_dev;
+ struct expander_device *parent_ex = &child->parent->ex_dev;
+ struct ex_phy *child_phy;
+
+ child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id];
+
+ if (child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
+ if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING ||
+ child_phy->routing_attr != TABLE_ROUTING)
+ goto error;
+ } else if (parent_phy->routing_attr == SUBTRACTIVE_ROUTING) {
+ if (child_phy->routing_attr == SUBTRACTIVE_ROUTING)
+ return sas_check_eeds(child, parent_phy, child_phy);
+ else if (child_phy->routing_attr != TABLE_ROUTING)
+ goto error;
+ } else if (parent_phy->routing_attr == TABLE_ROUTING) {
+ if (child_phy->routing_attr != SUBTRACTIVE_ROUTING &&
+ (child_phy->routing_attr != TABLE_ROUTING ||
+ !child_ex->t2t_supp || !parent_ex->t2t_supp))
+ goto error;
+ }
+
+ return 0;
+error:
+ sas_print_parent_topology_bug(child, parent_phy, child_phy);
+ return -ENODEV;
+}
+
+static int sas_check_fanout_expander_topo(struct domain_device *child,
+ struct ex_phy *parent_phy)
{
struct expander_device *child_ex = &child->ex_dev;
+ struct ex_phy *child_phy;
+
+ child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id];
+
+ if (parent_phy->routing_attr == TABLE_ROUTING &&
+ child_phy->routing_attr == SUBTRACTIVE_ROUTING)
+ return 0;
+
+ sas_print_parent_topology_bug(child, parent_phy, child_phy);
+
+ return -ENODEV;
+}
+
+static int sas_check_parent_topology(struct domain_device *child)
+{
struct expander_device *parent_ex;
int i;
int res = 0;
@@ -1259,7 +1304,6 @@ static int sas_check_parent_topology(struct domain_device *child)
for (i = 0; i < parent_ex->num_phys; i++) {
struct ex_phy *parent_phy = &parent_ex->ex_phy[i];
- struct ex_phy *child_phy;
if (parent_phy->phy_state == PHY_VACANT ||
parent_phy->phy_state == PHY_NOT_PRESENT)
@@ -1268,40 +1312,14 @@ static int sas_check_parent_topology(struct domain_device *child)
if (!sas_phy_match_dev_addr(child, parent_phy))
continue;
- child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id];
-
switch (child->parent->dev_type) {
case SAS_EDGE_EXPANDER_DEVICE:
- if (child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
- if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING ||
- child_phy->routing_attr != TABLE_ROUTING) {
- sas_print_parent_topology_bug(child, parent_phy, child_phy);
- res = -ENODEV;
- }
- } else if (parent_phy->routing_attr == SUBTRACTIVE_ROUTING) {
- if (child_phy->routing_attr == SUBTRACTIVE_ROUTING) {
- res = sas_check_eeds(child, parent_phy, child_phy);
- } else if (child_phy->routing_attr != TABLE_ROUTING) {
- sas_print_parent_topology_bug(child, parent_phy, child_phy);
- res = -ENODEV;
- }
- } else if (parent_phy->routing_attr == TABLE_ROUTING) {
- if (child_phy->routing_attr == SUBTRACTIVE_ROUTING ||
- (child_phy->routing_attr == TABLE_ROUTING &&
- child_ex->t2t_supp && parent_ex->t2t_supp)) {
- /* All good */;
- } else {
- sas_print_parent_topology_bug(child, parent_phy, child_phy);
- res = -ENODEV;
- }
- }
+ if (sas_check_edge_expander_topo(child, parent_phy))
+ res = -ENODEV;
break;
case SAS_FANOUT_EXPANDER_DEVICE:
- if (parent_phy->routing_attr != TABLE_ROUTING ||
- child_phy->routing_attr != SUBTRACTIVE_ROUTING) {
- sas_print_parent_topology_bug(child, parent_phy, child_phy);
+ if (sas_check_fanout_expander_topo(child, parent_phy))
res = -ENODEV;
- }
break;
default:
break;
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index a36fa1c128a8..94c5f14f3c16 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -872,8 +872,7 @@ int sas_change_queue_depth(struct scsi_device *sdev, int depth)
struct domain_device *dev = sdev_to_domain_dev(sdev);
if (dev_is_sata(dev))
- return ata_change_queue_depth(dev->sata_dev.ap,
- sas_to_ata_dev(dev), sdev, depth);
+ return ata_change_queue_depth(dev->sata_dev.ap, sdev, depth);
if (!sdev->tagged_supported)
depth = 1;
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 5e3a93d13a91..9a8963684369 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -429,6 +429,15 @@ struct lpfc_cgn_param {
/* Max number of days of congestion data */
#define LPFC_MAX_CGN_DAYS 10
+struct lpfc_cgn_ts {
+ uint8_t month;
+ uint8_t day;
+ uint8_t year;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+};
+
/* Format of congestion buffer info
* This structure defines memory thats allocated and registered with
* the HBA firmware. When adding or removing fields from this structure
@@ -442,6 +451,7 @@ struct lpfc_cgn_info {
#define LPFC_CGN_INFO_V1 1
#define LPFC_CGN_INFO_V2 2
#define LPFC_CGN_INFO_V3 3
+#define LPFC_CGN_INFO_V4 4
uint8_t cgn_info_mode; /* 0=off 1=managed 2=monitor only */
uint8_t cgn_info_detect;
uint8_t cgn_info_action;
@@ -450,12 +460,7 @@ struct lpfc_cgn_info {
uint8_t cgn_info_level2;
/* Start Time */
- uint8_t cgn_info_month;
- uint8_t cgn_info_day;
- uint8_t cgn_info_year;
- uint8_t cgn_info_hour;
- uint8_t cgn_info_minute;
- uint8_t cgn_info_second;
+ struct lpfc_cgn_ts base_time;
/* minute / hours / daily indices */
uint8_t cgn_index_minute;
@@ -496,45 +501,17 @@ struct lpfc_cgn_info {
uint8_t cgn_stat_npm; /* Notifications per minute */
/* Start Time */
- uint8_t cgn_stat_month;
- uint8_t cgn_stat_day;
- uint8_t cgn_stat_year;
- uint8_t cgn_stat_hour;
- uint8_t cgn_stat_minute;
- uint8_t cgn_pad2[2];
+ struct lpfc_cgn_ts stat_start; /* Base time */
+ uint8_t cgn_pad2;
__le32 cgn_notification;
__le32 cgn_peer_notification;
__le32 link_integ_notification;
__le32 delivery_notification;
-
- uint8_t cgn_stat_cgn_month; /* Last congestion notification FPIN */
- uint8_t cgn_stat_cgn_day;
- uint8_t cgn_stat_cgn_year;
- uint8_t cgn_stat_cgn_hour;
- uint8_t cgn_stat_cgn_min;
- uint8_t cgn_stat_cgn_sec;
-
- uint8_t cgn_stat_peer_month; /* Last peer congestion FPIN */
- uint8_t cgn_stat_peer_day;
- uint8_t cgn_stat_peer_year;
- uint8_t cgn_stat_peer_hour;
- uint8_t cgn_stat_peer_min;
- uint8_t cgn_stat_peer_sec;
-
- uint8_t cgn_stat_lnk_month; /* Last link integrity FPIN */
- uint8_t cgn_stat_lnk_day;
- uint8_t cgn_stat_lnk_year;
- uint8_t cgn_stat_lnk_hour;
- uint8_t cgn_stat_lnk_min;
- uint8_t cgn_stat_lnk_sec;
-
- uint8_t cgn_stat_del_month; /* Last delivery notification FPIN */
- uint8_t cgn_stat_del_day;
- uint8_t cgn_stat_del_year;
- uint8_t cgn_stat_del_hour;
- uint8_t cgn_stat_del_min;
- uint8_t cgn_stat_del_sec;
+ struct lpfc_cgn_ts stat_fpin; /* Last congestion notification FPIN */
+ struct lpfc_cgn_ts stat_peer; /* Last peer congestion FPIN */
+ struct lpfc_cgn_ts stat_lnk; /* Last link integrity FPIN */
+ struct lpfc_cgn_ts stat_delivery; /* Last delivery notification FPIN */
);
__le32 cgn_info_crc;
@@ -932,8 +909,6 @@ struct lpfc_hba {
void (*__lpfc_sli_release_iocbq)(struct lpfc_hba *,
struct lpfc_iocbq *);
int (*lpfc_hba_down_post)(struct lpfc_hba *phba);
- void (*lpfc_scsi_cmd_iocb_cmpl)
- (struct lpfc_hba *, struct lpfc_iocbq *, struct lpfc_iocbq *);
/* MBOX interface function jump table entries */
int (*lpfc_sli_issue_mbox)
@@ -1045,8 +1020,6 @@ struct lpfc_hba {
* capability
*/
#define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */
-#define HBA_SHORT_CMF 0x200000 /* shorter CMF timer routine */
-#define HBA_CGN_DAY_WRAP 0x400000 /* HBA Congestion info day wraps */
#define HBA_DEFER_FLOGI 0x800000 /* Defer FLOGI till read_sparm cmpl */
#define HBA_SETUP 0x1000000 /* Signifies HBA setup is completed */
#define HBA_NEEDS_CFG_PORT 0x2000000 /* SLI3 - needs a CONFIG_PORT mbox */
@@ -1529,6 +1502,7 @@ struct lpfc_hba {
uint64_t cmf_last_sync_bw;
#define LPFC_CMF_BLK_SIZE 512
struct hrtimer cmf_timer;
+ struct hrtimer cmf_stats_timer; /* 1 minute stats timer */
atomic_t cmf_bw_wait;
atomic_t cmf_busy;
atomic_t cmf_stop_io; /* To block request and stop IO's */
@@ -1576,12 +1550,11 @@ struct lpfc_hba {
atomic_t cgn_sync_alarm_cnt; /* Total alarm events for SYNC wqe */
atomic_t cgn_driver_evt_cnt; /* Total driver cgn events for fmw */
atomic_t cgn_latency_evt_cnt;
- struct timespec64 cgn_daily_ts;
atomic64_t cgn_latency_evt; /* Avg latency per minute */
unsigned long cgn_evt_timestamp;
#define LPFC_CGN_TIMER_TO_MIN 60000 /* ms in a minute */
uint32_t cgn_evt_minute;
-#define LPFC_SEC_MIN 60
+#define LPFC_SEC_MIN 60UL
#define LPFC_MIN_HOUR 60
#define LPFC_HOUR_DAY 24
#define LPFC_MIN_DAY (LPFC_MIN_HOUR * LPFC_HOUR_DAY)
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 3863a5341782..21c7ecd3ede5 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5858,8 +5858,8 @@ int lpfc_fabric_cgn_frequency = 100; /* 100 ms default */
module_param(lpfc_fabric_cgn_frequency, int, 0444);
MODULE_PARM_DESC(lpfc_fabric_cgn_frequency, "Congestion signaling fabric freq");
-int lpfc_acqe_cgn_frequency = 10; /* 10 sec default */
-module_param(lpfc_acqe_cgn_frequency, int, 0444);
+unsigned char lpfc_acqe_cgn_frequency = 10; /* 10 sec default */
+module_param(lpfc_acqe_cgn_frequency, byte, 0444);
MODULE_PARM_DESC(lpfc_acqe_cgn_frequency, "Congestion signaling ACQE freq");
int lpfc_use_cgn_signal = 1; /* 0 - only use FPINs, 1 - Use signals if avail */
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index b833b983e69d..d4e46a08f94d 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -134,7 +134,6 @@ void lpfc_check_nlp_post_devloss(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp);
void lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb);
-int lpfc_nlp_not_used(struct lpfc_nodelist *ndlp);
struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_vport *, uint32_t);
void lpfc_disc_list_loopmap(struct lpfc_vport *);
void lpfc_disc_start(struct lpfc_vport *);
@@ -248,6 +247,7 @@ irqreturn_t lpfc_sli_sp_intr_handler(int, void *);
irqreturn_t lpfc_sli_fp_intr_handler(int, void *);
irqreturn_t lpfc_sli4_intr_handler(int, void *);
irqreturn_t lpfc_sli4_hba_intr_handler(int, void *);
+irqreturn_t lpfc_sli4_hba_intr_handler_th(int irq, void *dev_id);
int lpfc_read_object(struct lpfc_hba *phba, char *s, uint32_t *datap,
uint32_t len);
@@ -664,7 +664,7 @@ extern int lpfc_enable_nvmet_cnt;
extern unsigned long long lpfc_enable_nvmet[];
extern int lpfc_no_hba_reset_cnt;
extern unsigned long lpfc_no_hba_reset[];
-extern int lpfc_acqe_cgn_frequency;
+extern unsigned char lpfc_acqe_cgn_frequency;
extern int lpfc_fabric_cgn_frequency;
extern int lpfc_use_cgn_signal;
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index f3bdcebe67f5..474834f313a7 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -287,7 +287,7 @@ lpfc_ct_handle_mibreq(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocbq)
u32 ulp_status = get_job_ulpstatus(phba, ctiocbq);
u32 ulp_word4 = get_job_word4(phba, ctiocbq);
u32 did;
- u32 mi_cmd;
+ u16 mi_cmd;
did = bf_get(els_rsp64_sid, &ctiocbq->wqe.xmit_els_rsp);
if (ulp_status) {
@@ -311,7 +311,7 @@ lpfc_ct_handle_mibreq(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocbq)
ct_req = (struct lpfc_sli_ct_request *)ctiocbq->cmd_dmabuf->virt;
- mi_cmd = ct_req->CommandResponse.bits.CmdRsp;
+ mi_cmd = be16_to_cpu(ct_req->CommandResponse.bits.CmdRsp);
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"6442 : MI Cmd : x%x Not Supported\n", mi_cmd);
lpfc_ct_reject_event(ndlp, ct_req,
@@ -486,7 +486,7 @@ lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
}
static struct lpfc_dmabuf *
-lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
+lpfc_alloc_ct_rsp(struct lpfc_hba *phba, __be16 cmdcode, struct ulp_bde64 *bpl,
uint32_t size, int *entries)
{
struct lpfc_dmabuf *mlist = NULL;
@@ -507,8 +507,8 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
INIT_LIST_HEAD(&mp->list);
- if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT) ||
- cmdcode == be16_to_cpu(SLI_CTNS_GFF_ID))
+ if (be16_to_cpu(cmdcode) == SLI_CTNS_GID_FT ||
+ be16_to_cpu(cmdcode) == SLI_CTNS_GFF_ID)
mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
else
mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys));
@@ -671,7 +671,7 @@ lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp,
struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt;
struct lpfc_dmabuf *outmp;
int cnt = 0, status;
- int cmdcode = ((struct lpfc_sli_ct_request *) inmp->virt)->
+ __be16 cmdcode = ((struct lpfc_sli_ct_request *)inmp->virt)->
CommandResponse.bits.CmdRsp;
bpl++; /* Skip past ct request */
@@ -1043,8 +1043,8 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
outp,
CTreq->un.gid.Fc4Type,
get_job_data_placed(phba, rspiocb));
- } else if (CTrsp->CommandResponse.bits.CmdRsp ==
- be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
+ } else if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) ==
+ SLI_CT_RESPONSE_FS_RJT) {
/* NameServer Rsp Error */
if ((CTrsp->ReasonCode == SLI_CT_UNABLE_TO_PERFORM_REQ)
&& (CTrsp->Explanation == SLI_CT_NO_FC4_TYPES)) {
@@ -1052,14 +1052,14 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
LOG_DISCOVERY,
"0269 No NameServer Entries "
"Data: x%x x%x x%x x%x\n",
- CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
(uint32_t) CTrsp->ReasonCode,
(uint32_t) CTrsp->Explanation,
vport->fc_flag);
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
"GID_FT no entry cmd:x%x rsn:x%x exp:x%x",
- (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
(uint32_t) CTrsp->ReasonCode,
(uint32_t) CTrsp->Explanation);
} else {
@@ -1067,14 +1067,14 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
LOG_DISCOVERY,
"0240 NameServer Rsp Error "
"Data: x%x x%x x%x x%x\n",
- CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
(uint32_t) CTrsp->ReasonCode,
(uint32_t) CTrsp->Explanation,
vport->fc_flag);
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
"GID_FT rsp err1 cmd:x%x rsn:x%x exp:x%x",
- (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
(uint32_t) CTrsp->ReasonCode,
(uint32_t) CTrsp->Explanation);
}
@@ -1085,14 +1085,14 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0241 NameServer Rsp Error "
"Data: x%x x%x x%x x%x\n",
- CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
(uint32_t) CTrsp->ReasonCode,
(uint32_t) CTrsp->Explanation,
vport->fc_flag);
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
"GID_FT rsp err2 cmd:x%x rsn:x%x exp:x%x",
- (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
(uint32_t) CTrsp->ReasonCode,
(uint32_t) CTrsp->Explanation);
}
@@ -1247,8 +1247,8 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* Good status, continue checking */
CTreq = (struct lpfc_sli_ct_request *)inp->virt;
CTrsp = (struct lpfc_sli_ct_request *)outp->virt;
- if (CTrsp->CommandResponse.bits.CmdRsp ==
- cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
+ if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) ==
+ SLI_CT_RESPONSE_FS_ACC) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"4105 NameServer Rsp Data: x%x x%x "
"x%x x%x sz x%x\n",
@@ -1262,8 +1262,8 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
outp,
CTreq->un.gid.Fc4Type,
get_job_data_placed(phba, rspiocb));
- } else if (CTrsp->CommandResponse.bits.CmdRsp ==
- be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
+ } else if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) ==
+ SLI_CT_RESPONSE_FS_RJT) {
/* NameServer Rsp Error */
if ((CTrsp->ReasonCode == SLI_CT_UNABLE_TO_PERFORM_REQ)
&& (CTrsp->Explanation == SLI_CT_NO_FC4_TYPES)) {
@@ -1271,7 +1271,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
vport, KERN_INFO, LOG_DISCOVERY,
"4106 No NameServer Entries "
"Data: x%x x%x x%x x%x\n",
- CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
(uint32_t)CTrsp->ReasonCode,
(uint32_t)CTrsp->Explanation,
vport->fc_flag);
@@ -1279,7 +1279,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_debugfs_disc_trc(
vport, LPFC_DISC_TRC_CT,
"GID_PT no entry cmd:x%x rsn:x%x exp:x%x",
- (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
(uint32_t)CTrsp->ReasonCode,
(uint32_t)CTrsp->Explanation);
} else {
@@ -1287,7 +1287,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
vport, KERN_INFO, LOG_DISCOVERY,
"4107 NameServer Rsp Error "
"Data: x%x x%x x%x x%x\n",
- CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
(uint32_t)CTrsp->ReasonCode,
(uint32_t)CTrsp->Explanation,
vport->fc_flag);
@@ -1295,7 +1295,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_debugfs_disc_trc(
vport, LPFC_DISC_TRC_CT,
"GID_PT rsp err1 cmd:x%x rsn:x%x exp:x%x",
- (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
(uint32_t)CTrsp->ReasonCode,
(uint32_t)CTrsp->Explanation);
}
@@ -1304,7 +1304,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"4109 NameServer Rsp Error "
"Data: x%x x%x x%x x%x\n",
- CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
(uint32_t)CTrsp->ReasonCode,
(uint32_t)CTrsp->Explanation,
vport->fc_flag);
@@ -1312,7 +1312,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_debugfs_disc_trc(
vport, LPFC_DISC_TRC_CT,
"GID_PT rsp err2 cmd:x%x rsn:x%x exp:x%x",
- (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
(uint32_t)CTrsp->ReasonCode,
(uint32_t)CTrsp->Explanation);
}
@@ -1391,8 +1391,8 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
(fbits & FC4_FEATURE_INIT) ? "Initiator" : " ",
(fbits & FC4_FEATURE_TARGET) ? "Target" : " ");
- if (CTrsp->CommandResponse.bits.CmdRsp ==
- be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
+ if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) ==
+ SLI_CT_RESPONSE_FS_ACC) {
if ((fbits & FC4_FEATURE_INIT) &&
!(fbits & FC4_FEATURE_TARGET)) {
lpfc_printf_vlog(vport, KERN_INFO,
@@ -1631,7 +1631,7 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
"0209 CT Request completes, latt %d, "
"ulp_status x%x CmdRsp x%x, Context x%x, Tag x%x\n",
latt, ulp_status,
- CTrsp->CommandResponse.bits.CmdRsp,
+ be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp),
get_job_ulpcontext(phba, cmdiocb), cmdiocb->iotag);
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
@@ -1681,8 +1681,8 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
outp = cmdiocb->rsp_dmabuf;
CTrsp = (struct lpfc_sli_ct_request *)outp->virt;
- if (CTrsp->CommandResponse.bits.CmdRsp ==
- be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
+ if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) ==
+ SLI_CT_RESPONSE_FS_ACC)
vport->ct_flags |= FC_CT_RFT_ID;
}
lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
@@ -1702,8 +1702,8 @@ lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
outp = cmdiocb->rsp_dmabuf;
CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
- if (CTrsp->CommandResponse.bits.CmdRsp ==
- be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
+ if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) ==
+ SLI_CT_RESPONSE_FS_ACC)
vport->ct_flags |= FC_CT_RNN_ID;
}
lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
@@ -1723,8 +1723,8 @@ lpfc_cmpl_ct_cmd_rspn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
outp = cmdiocb->rsp_dmabuf;
CTrsp = (struct lpfc_sli_ct_request *)outp->virt;
- if (CTrsp->CommandResponse.bits.CmdRsp ==
- be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
+ if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) ==
+ SLI_CT_RESPONSE_FS_ACC)
vport->ct_flags |= FC_CT_RSPN_ID;
}
lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
@@ -1744,8 +1744,8 @@ lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
outp = cmdiocb->rsp_dmabuf;
CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
- if (CTrsp->CommandResponse.bits.CmdRsp ==
- be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
+ if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) ==
+ SLI_CT_RESPONSE_FS_ACC)
vport->ct_flags |= FC_CT_RSNN_NN;
}
lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
@@ -1777,8 +1777,8 @@ lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
outp = cmdiocb->rsp_dmabuf;
CTrsp = (struct lpfc_sli_ct_request *)outp->virt;
- if (CTrsp->CommandResponse.bits.CmdRsp ==
- be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
+ if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) ==
+ SLI_CT_RESPONSE_FS_ACC)
vport->ct_flags |= FC_CT_RFF_ID;
}
lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
@@ -2217,8 +2217,8 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_dmabuf *outp = cmdiocb->rsp_dmabuf;
struct lpfc_sli_ct_request *CTcmd = inp->virt;
struct lpfc_sli_ct_request *CTrsp = outp->virt;
- uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
- uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
+ __be16 fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
+ __be16 fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
struct lpfc_nodelist *ndlp, *free_ndlp = NULL;
uint32_t latt, cmd, err;
u32 ulp_status = get_job_ulpstatus(phba, rspiocb);
@@ -2278,7 +2278,7 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* Check for a CT LS_RJT response */
cmd = be16_to_cpu(fdmi_cmd);
- if (fdmi_rsp == cpu_to_be16(SLI_CT_RESPONSE_FS_RJT)) {
+ if (be16_to_cpu(fdmi_rsp) == SLI_CT_RESPONSE_FS_RJT) {
/* FDMI rsp failed */
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY | LOG_ELS,
"0220 FDMI cmd failed FS_RJT Data: x%x", cmd);
@@ -3110,7 +3110,7 @@ lpfc_fdmi_vendor_attr_mi(struct lpfc_vport *vport, void *attr)
}
/* RHBA attribute jump table */
-int (*lpfc_fdmi_hba_action[])
+static int (*lpfc_fdmi_hba_action[])
(struct lpfc_vport *vport, void *attrbuf) = {
/* Action routine Mask bit Attribute type */
lpfc_fdmi_hba_attr_wwnn, /* bit0 RHBA_NODENAME */
@@ -3134,7 +3134,7 @@ int (*lpfc_fdmi_hba_action[])
};
/* RPA / RPRT attribute jump table */
-int (*lpfc_fdmi_port_action[])
+static int (*lpfc_fdmi_port_action[])
(struct lpfc_vport *vport, void *attrbuf) = {
/* Action routine Mask bit Attribute type */
lpfc_fdmi_port_attr_fc4type, /* bit0 RPRT_SUPPORT_FC4_TYPES */
@@ -3570,7 +3570,7 @@ lpfc_cmpl_ct_cmd_vmid(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_dmabuf *outp = cmdiocb->rsp_dmabuf;
struct lpfc_sli_ct_request *ctcmd = inp->virt;
struct lpfc_sli_ct_request *ctrsp = outp->virt;
- u16 rsp = ctrsp->CommandResponse.bits.CmdRsp;
+ __be16 rsp = ctrsp->CommandResponse.bits.CmdRsp;
struct app_id_object *app;
struct lpfc_nodelist *ndlp = cmdiocb->ndlp;
u32 cmd, hash, bucket;
@@ -3587,7 +3587,7 @@ lpfc_cmpl_ct_cmd_vmid(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
goto free_res;
}
/* Check for a CT LS_RJT response */
- if (rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
+ if (be16_to_cpu(rsp) == SLI_CT_RESPONSE_FS_RJT) {
if (cmd != SLI_CTAS_DALLAPP_ID)
lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY,
"3306 VMID FS_RJT Data: x%x x%x x%x\n",
@@ -3748,7 +3748,7 @@ lpfc_vmid_cmd(struct lpfc_vport *vport,
rap->obj[0].entity_id_len = vmid->vmid_len;
memcpy(rap->obj[0].entity_id, vmid->host_vmid, vmid->vmid_len);
size = RAPP_IDENT_OFFSET +
- sizeof(struct lpfc_vmid_rapp_ident_list);
+ struct_size(rap, obj, be32_to_cpu(rap->no_of_objects));
retry = 1;
break;
@@ -3767,7 +3767,7 @@ lpfc_vmid_cmd(struct lpfc_vport *vport,
dap->obj[0].entity_id_len = vmid->vmid_len;
memcpy(dap->obj[0].entity_id, vmid->host_vmid, vmid->vmid_len);
size = DAPP_IDENT_OFFSET +
- sizeof(struct lpfc_vmid_dapp_ident_list);
+ struct_size(dap, obj, be32_to_cpu(dap->no_of_objects));
write_lock(&vport->vmid_lock);
vmid->flag &= ~LPFC_VMID_REGISTERED;
write_unlock(&vport->vmid_lock);
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index bdf34af4ef36..7f9b221e7c34 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -2259,11 +2259,15 @@ lpfc_debugfs_ras_log_open(struct inode *inode, struct file *file)
goto out;
}
spin_unlock_irq(&phba->hbalock);
- debug = kmalloc(sizeof(*debug), GFP_KERNEL);
+
+ if (check_mul_overflow(LPFC_RAS_MIN_BUFF_POST_SIZE,
+ phba->cfg_ras_fwlog_buffsize, &size))
+ goto out;
+
+ debug = kzalloc(sizeof(*debug), GFP_KERNEL);
if (!debug)
goto out;
- size = LPFC_RAS_MIN_BUFF_POST_SIZE * phba->cfg_ras_fwlog_buffsize;
debug->buffer = vmalloc(size);
if (!debug->buffer)
goto free_debug;
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 6a15f879e517..2bad9954c355 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -5205,14 +5205,9 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
*
* This routine is the completion callback function to the Logout (LOGO)
* Accept (ACC) Response ELS command. This routine is invoked to indicate
- * the completion of the LOGO process. It invokes the lpfc_nlp_not_used() to
- * release the ndlp if it has the last reference remaining (reference count
- * is 1). If succeeded (meaning ndlp released), it sets the iocb ndlp
- * field to NULL to inform the following lpfc_els_free_iocb() routine no
- * ndlp reference count needs to be decremented. Otherwise, the ndlp
- * reference use-count shall be decremented by the lpfc_els_free_iocb()
- * routine. Finally, the lpfc_els_free_iocb() is invoked to release the
- * IOCB data structure.
+ * the completion of the LOGO process. If the node has transitioned to NPR,
+ * this routine unregisters the RPI if it is still registered. The
+ * lpfc_els_free_iocb() is invoked to release the IOCB data structure.
**/
static void
lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
@@ -5253,19 +5248,9 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
(ndlp->nlp_last_elscmd == ELS_CMD_PLOGI))
goto out;
- /* NPort Recovery mode or node is just allocated */
- if (!lpfc_nlp_not_used(ndlp)) {
- /* A LOGO is completing and the node is in NPR state.
- * Just unregister the RPI because the node is still
- * required.
- */
+ if (ndlp->nlp_flag & NLP_RPI_REGISTERED)
lpfc_unreg_rpi(vport, ndlp);
- } else {
- /* Indicate the node has already released, should
- * not reference to it from within lpfc_els_free_iocb.
- */
- cmdiocb->ndlp = NULL;
- }
+
}
out:
/*
@@ -5285,9 +5270,8 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
* RPI (Remote Port Index) mailbox command to the @phba. It simply releases
* the associated lpfc Direct Memory Access (DMA) buffer back to the pool and
* decrements the ndlp reference count held for this completion callback
- * function. After that, it invokes the lpfc_nlp_not_used() to check
- * whether there is only one reference left on the ndlp. If so, it will
- * perform one more decrement and trigger the release of the ndlp.
+ * function. After that, it invokes the lpfc_drop_node to check
+ * whether it is appropriate to release the node.
**/
void
lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
@@ -5468,9 +5452,19 @@ out:
ndlp->nlp_flag &= ~NLP_RELEASE_RPI;
spin_unlock_irq(&ndlp->lock);
}
+ lpfc_drop_node(vport, ndlp);
+ } else if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE &&
+ ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE &&
+ ndlp->nlp_state != NLP_STE_PRLI_ISSUE) {
+ /* Drop ndlp if there is no planned or outstanding
+ * issued PRLI.
+ *
+ * In cases when the ndlp is acting as both an initiator
+ * and target function, let our issued PRLI determine
+ * the final ndlp kref drop.
+ */
+ lpfc_drop_node(vport, ndlp);
}
-
- lpfc_drop_node(vport, ndlp);
}
/* Release the originating I/O reference. */
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 5ba3a9ad9501..499849b58ee4 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -458,11 +458,9 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
if (ndlp->nlp_type & NLP_FABRIC) {
spin_lock_irqsave(&ndlp->lock, iflags);
- /* In massive vport configuration settings or when the FLOGI
- * completes with a sequence timeout, it's possible
- * dev_loss_tmo fired during node recovery. The driver has to
- * account for this race to allow for recovery and keep
- * the reference counting correct.
+ /* The driver has to account for a race between any fabric
+ * node that's in recovery when dev_loss_tmo expires. When this
+ * happens, the driver has to allow node recovery.
*/
switch (ndlp->nlp_DID) {
case Fabric_DID:
@@ -489,6 +487,17 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE)
recovering = true;
break;
+ default:
+ /* Ensure the nlp_DID at least has the correct prefix.
+ * The fabric domain controller's last three nibbles
+ * vary so we handle it in the default case.
+ */
+ if (ndlp->nlp_DID & Fabric_DID_MASK) {
+ if (ndlp->nlp_state >= NLP_STE_PLOGI_ISSUE &&
+ ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE)
+ recovering = true;
+ }
+ break;
}
spin_unlock_irqrestore(&ndlp->lock, iflags);
@@ -556,6 +565,9 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
ndlp->nlp_DID, ndlp->nlp_flag,
ndlp->nlp_state, ndlp->nlp_rpi);
}
+ spin_lock_irqsave(&ndlp->lock, iflags);
+ ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS;
+ spin_unlock_irqrestore(&ndlp->lock, iflags);
/* If we are devloss, but we are in the process of rediscovering the
* ndlp, don't issue a NLP_EVT_DEVICE_RM event.
@@ -565,9 +577,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
return fcf_inuse;
}
- spin_lock_irqsave(&ndlp->lock, iflags);
- ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS;
- spin_unlock_irqrestore(&ndlp->lock, iflags);
if (!(ndlp->fc4_xpt_flags & NVME_XPT_REGD))
lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
@@ -4333,13 +4342,14 @@ out:
/* If the node is not registered with the scsi or nvme
* transport, remove the fabric node. The failed reg_login
- * is terminal.
+ * is terminal and forces the removal of the last node
+ * reference.
*/
if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) {
spin_lock_irq(&ndlp->lock);
ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
spin_unlock_irq(&ndlp->lock);
- lpfc_nlp_not_used(ndlp);
+ lpfc_nlp_put(ndlp);
}
if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
@@ -4497,14 +4507,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
if (vport->load_flag & FC_UNLOADING)
return;
- /*
- * Disassociate any older association between this ndlp and rport
- */
- if (ndlp->rport) {
- rdata = ndlp->rport->dd_data;
- rdata->pnode = NULL;
- }
-
ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids);
if (!rport) {
dev_printk(KERN_WARNING, &phba->pcidev->dev,
@@ -4835,7 +4837,7 @@ lpfc_nlp_state_name(char *buffer, size_t size, int state)
};
if (state < NLP_STE_MAX_STATE && states[state])
- strlcpy(buffer, states[state], size);
+ strscpy(buffer, states[state], size);
else
snprintf(buffer, size, "unknown (%d)", state);
return buffer;
@@ -6704,25 +6706,6 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp)
return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0;
}
-/* This routine free's the specified nodelist if it is not in use
- * by any other discovery thread. This routine returns 1 if the
- * ndlp has been freed. A return value of 0 indicates the ndlp is
- * not yet been released.
- */
-int
-lpfc_nlp_not_used(struct lpfc_nodelist *ndlp)
-{
- lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE,
- "node not used: did:x%x flg:x%x refcnt:x%x",
- ndlp->nlp_DID, ndlp->nlp_flag,
- kref_read(&ndlp->kref));
-
- if (kref_read(&ndlp->kref) == 1)
- if (lpfc_nlp_put(ndlp))
- return 1;
- return 0;
-}
-
/**
* lpfc_fcf_inuse - Check if FCF can be unregistered.
* @phba: Pointer to hba context object.
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 19b2d2754f32..663755842e4a 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -86,8 +86,8 @@ union CtRevisionId {
union CtCommandResponse {
/* Structure is in Big Endian format */
struct {
- uint32_t CmdRsp:16;
- uint32_t Size:16;
+ __be16 CmdRsp;
+ __be16 Size;
} bits;
uint32_t word;
};
@@ -124,7 +124,7 @@ struct lpfc_sli_ct_request {
#define LPFC_CT_PREAMBLE 20 /* Size of CTReq + 4 up to here */
union {
- uint32_t PortID;
+ __be32 PortID;
struct gid {
uint8_t PortType; /* for GID_PT requests */
#define GID_PT_N_PORT 1
@@ -1408,19 +1408,19 @@ struct entity_id_object {
};
struct app_id_object {
- uint32_t port_id;
- uint32_t app_id;
+ __be32 port_id;
+ __be32 app_id;
struct entity_id_object obj;
};
struct lpfc_vmid_rapp_ident_list {
- uint32_t no_of_objects;
- struct entity_id_object obj[1];
+ __be32 no_of_objects;
+ struct entity_id_object obj[];
};
struct lpfc_vmid_dapp_ident_list {
- uint32_t no_of_objects;
- struct entity_id_object obj[1];
+ __be32 no_of_objects;
+ struct entity_id_object obj[];
};
#define GALLAPPIA_ID_LAST 0x80
@@ -1512,7 +1512,7 @@ struct lpfc_fdmi_hba_ident {
* Registered Port List Format
*/
struct lpfc_fdmi_reg_port_list {
- uint32_t EntryCnt;
+ __be32 EntryCnt;
struct lpfc_fdmi_port_entry pe;
} __packed;
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 58fa39c403a0..5d4f9f27084d 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -395,9 +395,6 @@ struct lpfc_cqe {
#define CQE_STATUS_NEED_BUFF_ENTRY 0xf
#define CQE_STATUS_DI_ERROR 0x16
-/* Used when mapping CQE status to IOCB */
-#define LPFC_IOCB_STATUS_MASK 0xf
-
/* Status returned by hardware (valid only if status = CQE_STATUS_SUCCESS). */
#define CQE_HW_STATUS_NO_ERR 0x0
#define CQE_HW_STATUS_UNDERRUN 0x1
@@ -536,9 +533,9 @@ struct sli4_wcqe_xri_aborted {
/* completion queue entry structure for rqe completion */
struct lpfc_rcqe {
uint32_t word0;
-#define lpfc_rcqe_bindex_SHIFT 16
-#define lpfc_rcqe_bindex_MASK 0x0000FFF
-#define lpfc_rcqe_bindex_WORD word0
+#define lpfc_rcqe_iv_SHIFT 31
+#define lpfc_rcqe_iv_MASK 0x00000001
+#define lpfc_rcqe_iv_WORD word0
#define lpfc_rcqe_status_SHIFT 8
#define lpfc_rcqe_status_MASK 0x000000FF
#define lpfc_rcqe_status_WORD word0
@@ -546,6 +543,7 @@ struct lpfc_rcqe {
#define FC_STATUS_RQ_BUF_LEN_EXCEEDED 0x11 /* payload truncated */
#define FC_STATUS_INSUFF_BUF_NEED_BUF 0x12 /* Insufficient buffers */
#define FC_STATUS_INSUFF_BUF_FRM_DISC 0x13 /* Frame Discard */
+#define FC_STATUS_RQ_DMA_FAILURE 0x14 /* DMA failure */
uint32_t word1;
#define lpfc_rcqe_fcf_id_v1_SHIFT 0
#define lpfc_rcqe_fcf_id_v1_MASK 0x0000003F
@@ -4813,8 +4811,8 @@ struct cmf_sync_wqe {
#define cmf_sync_cqid_WORD word11
uint32_t read_bytes;
uint32_t word13;
-#define cmf_sync_period_SHIFT 16
-#define cmf_sync_period_MASK 0x0000ffff
+#define cmf_sync_period_SHIFT 24
+#define cmf_sync_period_MASK 0x000000ff
#define cmf_sync_period_WORD word13
uint32_t word14;
uint32_t word15;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 867b4c788f08..3221a934066b 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -101,6 +101,7 @@ static struct scsi_transport_template *lpfc_vport_transport_template = NULL;
static DEFINE_IDR(lpfc_hba_index);
#define LPFC_NVMET_BUF_POST 254
static int lpfc_vmid_res_alloc(struct lpfc_hba *phba, struct lpfc_vport *vport);
+static void lpfc_cgn_update_tstamp(struct lpfc_hba *phba, struct lpfc_cgn_ts *ts);
/**
* lpfc_config_port_prep - Perform lpfc initialization prior to config port
@@ -1279,7 +1280,7 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
/*
* lpfc_idle_stat_delay_work - idle_stat tracking
*
- * This routine tracks per-cq idle_stat and determines polling decisions.
+ * This routine tracks per-eq idle_stat and determines polling decisions.
*
* Return codes:
* None
@@ -1290,7 +1291,7 @@ lpfc_idle_stat_delay_work(struct work_struct *work)
struct lpfc_hba *phba = container_of(to_delayed_work(work),
struct lpfc_hba,
idle_stat_delay_work);
- struct lpfc_queue *cq;
+ struct lpfc_queue *eq;
struct lpfc_sli4_hdw_queue *hdwq;
struct lpfc_idle_stat *idle_stat;
u32 i, idle_percent;
@@ -1306,10 +1307,10 @@ lpfc_idle_stat_delay_work(struct work_struct *work)
for_each_present_cpu(i) {
hdwq = &phba->sli4_hba.hdwq[phba->sli4_hba.cpu_map[i].hdwq];
- cq = hdwq->io_cq;
+ eq = hdwq->hba_eq;
- /* Skip if we've already handled this cq's primary CPU */
- if (cq->chann != i)
+ /* Skip if we've already handled this eq's primary CPU */
+ if (eq->chann != i)
continue;
idle_stat = &phba->sli4_hba.idle_stat[i];
@@ -1333,9 +1334,9 @@ lpfc_idle_stat_delay_work(struct work_struct *work)
idle_percent = 100 - idle_percent;
if (idle_percent < 15)
- cq->poll_mode = LPFC_QUEUE_WORK;
+ eq->poll_mode = LPFC_QUEUE_WORK;
else
- cq->poll_mode = LPFC_IRQ_POLL;
+ eq->poll_mode = LPFC_THREADED_IRQ;
idle_stat->prev_idle = wall_idle;
idle_stat->prev_wall = wall;
@@ -3197,6 +3198,7 @@ lpfc_cmf_stop(struct lpfc_hba *phba)
"6221 Stop CMF / Cancel Timer\n");
/* Cancel the CMF timer */
+ hrtimer_cancel(&phba->cmf_stats_timer);
hrtimer_cancel(&phba->cmf_timer);
/* Zero CMF counters */
@@ -3283,7 +3285,10 @@ lpfc_cmf_start(struct lpfc_hba *phba)
phba->cmf_timer_cnt = 0;
hrtimer_start(&phba->cmf_timer,
- ktime_set(0, LPFC_CMF_INTERVAL * 1000000),
+ ktime_set(0, LPFC_CMF_INTERVAL * NSEC_PER_MSEC),
+ HRTIMER_MODE_REL);
+ hrtimer_start(&phba->cmf_stats_timer,
+ ktime_set(0, LPFC_SEC_MIN * NSEC_PER_SEC),
HRTIMER_MODE_REL);
/* Setup for latency check in IO cmpl routines */
ktime_get_real_ts64(&phba->cmf_latency);
@@ -4357,6 +4362,7 @@ lpfc_io_buf_replenish(struct lpfc_hba *phba, struct list_head *cbuf)
struct lpfc_sli4_hdw_queue *qp;
struct lpfc_io_buf *lpfc_cmd;
int idx, cnt;
+ unsigned long iflags;
qp = phba->sli4_hba.hdwq;
cnt = 0;
@@ -4371,12 +4377,13 @@ lpfc_io_buf_replenish(struct lpfc_hba *phba, struct list_head *cbuf)
lpfc_cmd->hdwq_no = idx;
lpfc_cmd->hdwq = qp;
lpfc_cmd->cur_iocbq.cmd_cmpl = NULL;
- spin_lock(&qp->io_buf_list_put_lock);
+ spin_lock_irqsave(&qp->io_buf_list_put_lock, iflags);
list_add_tail(&lpfc_cmd->list,
&qp->lpfc_io_buf_list_put);
qp->put_io_bufs++;
qp->total_io_bufs++;
- spin_unlock(&qp->io_buf_list_put_lock);
+ spin_unlock_irqrestore(&qp->io_buf_list_put_lock,
+ iflags);
}
}
return cnt;
@@ -5593,81 +5600,74 @@ void
lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag)
{
struct lpfc_cgn_info *cp;
- struct tm broken;
- struct timespec64 cur_time;
- u32 cnt;
u32 value;
/* Make sure we have a congestion info buffer */
if (!phba->cgn_i)
return;
cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;
- ktime_get_real_ts64(&cur_time);
- time64_to_tm(cur_time.tv_sec, 0, &broken);
/* Update congestion statistics */
switch (dtag) {
case ELS_DTAG_LNK_INTEGRITY:
- cnt = le32_to_cpu(cp->link_integ_notification);
- cnt++;
- cp->link_integ_notification = cpu_to_le32(cnt);
-
- cp->cgn_stat_lnk_month = broken.tm_mon + 1;
- cp->cgn_stat_lnk_day = broken.tm_mday;
- cp->cgn_stat_lnk_year = broken.tm_year - 100;
- cp->cgn_stat_lnk_hour = broken.tm_hour;
- cp->cgn_stat_lnk_min = broken.tm_min;
- cp->cgn_stat_lnk_sec = broken.tm_sec;
+ le32_add_cpu(&cp->link_integ_notification, 1);
+ lpfc_cgn_update_tstamp(phba, &cp->stat_lnk);
break;
case ELS_DTAG_DELIVERY:
- cnt = le32_to_cpu(cp->delivery_notification);
- cnt++;
- cp->delivery_notification = cpu_to_le32(cnt);
-
- cp->cgn_stat_del_month = broken.tm_mon + 1;
- cp->cgn_stat_del_day = broken.tm_mday;
- cp->cgn_stat_del_year = broken.tm_year - 100;
- cp->cgn_stat_del_hour = broken.tm_hour;
- cp->cgn_stat_del_min = broken.tm_min;
- cp->cgn_stat_del_sec = broken.tm_sec;
+ le32_add_cpu(&cp->delivery_notification, 1);
+ lpfc_cgn_update_tstamp(phba, &cp->stat_delivery);
break;
case ELS_DTAG_PEER_CONGEST:
- cnt = le32_to_cpu(cp->cgn_peer_notification);
- cnt++;
- cp->cgn_peer_notification = cpu_to_le32(cnt);
-
- cp->cgn_stat_peer_month = broken.tm_mon + 1;
- cp->cgn_stat_peer_day = broken.tm_mday;
- cp->cgn_stat_peer_year = broken.tm_year - 100;
- cp->cgn_stat_peer_hour = broken.tm_hour;
- cp->cgn_stat_peer_min = broken.tm_min;
- cp->cgn_stat_peer_sec = broken.tm_sec;
+ le32_add_cpu(&cp->cgn_peer_notification, 1);
+ lpfc_cgn_update_tstamp(phba, &cp->stat_peer);
break;
case ELS_DTAG_CONGESTION:
- cnt = le32_to_cpu(cp->cgn_notification);
- cnt++;
- cp->cgn_notification = cpu_to_le32(cnt);
-
- cp->cgn_stat_cgn_month = broken.tm_mon + 1;
- cp->cgn_stat_cgn_day = broken.tm_mday;
- cp->cgn_stat_cgn_year = broken.tm_year - 100;
- cp->cgn_stat_cgn_hour = broken.tm_hour;
- cp->cgn_stat_cgn_min = broken.tm_min;
- cp->cgn_stat_cgn_sec = broken.tm_sec;
+ le32_add_cpu(&cp->cgn_notification, 1);
+ lpfc_cgn_update_tstamp(phba, &cp->stat_fpin);
}
if (phba->cgn_fpin_frequency &&
phba->cgn_fpin_frequency != LPFC_FPIN_INIT_FREQ) {
value = LPFC_CGN_TIMER_TO_MIN / phba->cgn_fpin_frequency;
cp->cgn_stat_npm = value;
}
+
value = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ,
LPFC_CGN_CRC32_SEED);
cp->cgn_info_crc = cpu_to_le32(value);
}
/**
- * lpfc_cgn_save_evt_cnt - Save data into registered congestion buffer
+ * lpfc_cgn_update_tstamp - Update cmf timestamp
* @phba: pointer to lpfc hba data structure.
+ * @ts: structure to write the timestamp to.
+ */
+void
+lpfc_cgn_update_tstamp(struct lpfc_hba *phba, struct lpfc_cgn_ts *ts)
+{
+ struct timespec64 cur_time;
+ struct tm tm_val;
+
+ ktime_get_real_ts64(&cur_time);
+ time64_to_tm(cur_time.tv_sec, 0, &tm_val);
+
+ ts->month = tm_val.tm_mon + 1;
+ ts->day = tm_val.tm_mday;
+ ts->year = tm_val.tm_year - 100;
+ ts->hour = tm_val.tm_hour;
+ ts->minute = tm_val.tm_min;
+ ts->second = tm_val.tm_sec;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "2646 Updated CMF timestamp : "
+ "%u/%u/%u %u:%u:%u\n",
+ ts->day, ts->month,
+ ts->year, ts->hour,
+ ts->minute, ts->second);
+}
+
+/**
+ * lpfc_cmf_stats_timer - Save data into registered congestion buffer
+ * @timer: Timer cookie to access lpfc private data
*
* Save the congestion event data every minute.
* On the hour collapse all the minute data into hour data. Every day
@@ -5675,12 +5675,11 @@ lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag)
* and fabrc congestion event counters that will be saved out
* to the registered congestion buffer every minute.
*/
-static void
-lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba)
+static enum hrtimer_restart
+lpfc_cmf_stats_timer(struct hrtimer *timer)
{
+ struct lpfc_hba *phba;
struct lpfc_cgn_info *cp;
- struct tm broken;
- struct timespec64 cur_time;
uint32_t i, index;
uint16_t value, mvalue;
uint64_t bps;
@@ -5691,21 +5690,18 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba)
__le32 *lptr;
__le16 *mptr;
+ phba = container_of(timer, struct lpfc_hba, cmf_stats_timer);
/* Make sure we have a congestion info buffer */
if (!phba->cgn_i)
- return;
+ return HRTIMER_NORESTART;
cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;
- if (time_before(jiffies, phba->cgn_evt_timestamp))
- return;
phba->cgn_evt_timestamp = jiffies +
msecs_to_jiffies(LPFC_CGN_TIMER_TO_MIN);
phba->cgn_evt_minute++;
/* We should get to this point in the routine on 1 minute intervals */
-
- ktime_get_real_ts64(&cur_time);
- time64_to_tm(cur_time.tv_sec, 0, &broken);
+ lpfc_cgn_update_tstamp(phba, &cp->base_time);
if (phba->cgn_fpin_frequency &&
phba->cgn_fpin_frequency != LPFC_FPIN_INIT_FREQ) {
@@ -5858,31 +5854,6 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba)
index = 0;
}
- /* Anytime we overwrite daily index 0, after we wrap,
- * we will be overwriting the oldest day, so we must
- * update the congestion data start time for that day.
- * That start time should have previously been saved after
- * we wrote the last days worth of data.
- */
- if ((phba->hba_flag & HBA_CGN_DAY_WRAP) && index == 0) {
- time64_to_tm(phba->cgn_daily_ts.tv_sec, 0, &broken);
-
- cp->cgn_info_month = broken.tm_mon + 1;
- cp->cgn_info_day = broken.tm_mday;
- cp->cgn_info_year = broken.tm_year - 100;
- cp->cgn_info_hour = broken.tm_hour;
- cp->cgn_info_minute = broken.tm_min;
- cp->cgn_info_second = broken.tm_sec;
-
- lpfc_printf_log
- (phba, KERN_INFO, LOG_CGN_MGMT,
- "2646 CGNInfo idx0 Start Time: "
- "%d/%d/%d %d:%d:%d\n",
- cp->cgn_info_day, cp->cgn_info_month,
- cp->cgn_info_year, cp->cgn_info_hour,
- cp->cgn_info_minute, cp->cgn_info_second);
- }
-
dvalue = 0;
wvalue = 0;
lvalue = 0;
@@ -5916,15 +5887,6 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba)
"2420 Congestion Info - daily (%d): "
"%d %d %d %d %d\n",
index, dvalue, wvalue, lvalue, mvalue, avalue);
-
- /* We just wrote LPFC_MAX_CGN_DAYS of data,
- * so we are wrapped on any data after this.
- * Save this as the start time for the next day.
- */
- if (index == (LPFC_MAX_CGN_DAYS - 1)) {
- phba->hba_flag |= HBA_CGN_DAY_WRAP;
- ktime_get_real_ts64(&phba->cgn_daily_ts);
- }
}
/* Use the frequency found in the last rcv'ed FPIN */
@@ -5935,6 +5897,10 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba)
lvalue = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ,
LPFC_CGN_CRC32_SEED);
cp->cgn_info_crc = cpu_to_le32(lvalue);
+
+ hrtimer_forward_now(timer, ktime_set(0, LPFC_SEC_MIN * NSEC_PER_SEC));
+
+ return HRTIMER_RESTART;
}
/**
@@ -6065,13 +6031,6 @@ lpfc_cmf_timer(struct hrtimer *timer)
if (ms && ms < LPFC_CMF_INTERVAL) {
cnt = div_u64(total, ms); /* bytes per ms */
cnt *= LPFC_CMF_INTERVAL; /* what total should be */
-
- /* If the timeout is scheduled to be shorter,
- * this value may skew the data, so cap it at mbpi.
- */
- if ((phba->hba_flag & HBA_SHORT_CMF) && cnt > mbpi)
- cnt = mbpi;
-
extra = cnt - total;
}
lpfc_issue_cmf_sync_wqe(phba, LPFC_CMF_INTERVAL, total + extra);
@@ -6141,34 +6100,6 @@ lpfc_cmf_timer(struct hrtimer *timer)
}
phba->rx_block_cnt += div_u64(rcv, 512); /* save 512 byte block cnt */
- /* Each minute save Fabric and Driver congestion information */
- lpfc_cgn_save_evt_cnt(phba);
-
- phba->hba_flag &= ~HBA_SHORT_CMF;
-
- /* Since we need to call lpfc_cgn_save_evt_cnt every minute, on the
- * minute, adjust our next timer interval, if needed, to ensure a
- * 1 minute granularity when we get the next timer interrupt.
- */
- if (time_after(jiffies + msecs_to_jiffies(LPFC_CMF_INTERVAL),
- phba->cgn_evt_timestamp)) {
- timer_interval = jiffies_to_msecs(phba->cgn_evt_timestamp -
- jiffies);
- if (timer_interval <= 0)
- timer_interval = LPFC_CMF_INTERVAL;
- else
- phba->hba_flag |= HBA_SHORT_CMF;
-
- /* If we adjust timer_interval, max_bytes_per_interval
- * needs to be adjusted as well.
- */
- phba->cmf_link_byte_count = div_u64(phba->cmf_max_line_rate *
- timer_interval, 1000);
- if (phba->cmf_active_mode == LPFC_CFG_MONITOR)
- phba->cmf_max_bytes_per_interval =
- phba->cmf_link_byte_count;
- }
-
/* Since total_bytes has already been zero'ed, its okay to unblock
* after max_bytes_per_interval is setup.
*/
@@ -8014,6 +7945,9 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
/* CMF congestion timer */
hrtimer_init(&phba->cmf_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
phba->cmf_timer.function = lpfc_cmf_timer;
+ /* CMF 1 minute stats collection timer */
+ hrtimer_init(&phba->cmf_stats_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ phba->cmf_stats_timer.function = lpfc_cmf_stats_timer;
/*
* Control structure for handling external multi-buffer mailbox
@@ -13117,8 +13051,10 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
}
eqhdl->irq = rc;
- rc = request_irq(eqhdl->irq, &lpfc_sli4_hba_intr_handler, 0,
- name, eqhdl);
+ rc = request_threaded_irq(eqhdl->irq,
+ &lpfc_sli4_hba_intr_handler,
+ &lpfc_sli4_hba_intr_handler_th,
+ IRQF_ONESHOT, name, eqhdl);
if (rc) {
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
"0486 MSI-X fast-path (%d) "
@@ -13521,6 +13457,7 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
struct pci_dev *pdev = phba->pcidev;
lpfc_stop_hba_timers(phba);
+ hrtimer_cancel(&phba->cmf_stats_timer);
hrtimer_cancel(&phba->cmf_timer);
if (phba->pport)
@@ -13645,8 +13582,6 @@ void
lpfc_init_congestion_buf(struct lpfc_hba *phba)
{
struct lpfc_cgn_info *cp;
- struct timespec64 cmpl_time;
- struct tm broken;
uint16_t size;
uint32_t crc;
@@ -13666,11 +13601,10 @@ lpfc_init_congestion_buf(struct lpfc_hba *phba)
atomic_set(&phba->cgn_latency_evt_cnt, 0);
atomic64_set(&phba->cgn_latency_evt, 0);
phba->cgn_evt_minute = 0;
- phba->hba_flag &= ~HBA_CGN_DAY_WRAP;
memset(cp, 0xff, offsetof(struct lpfc_cgn_info, cgn_stat));
cp->cgn_info_size = cpu_to_le16(LPFC_CGN_INFO_SZ);
- cp->cgn_info_version = LPFC_CGN_INFO_V3;
+ cp->cgn_info_version = LPFC_CGN_INFO_V4;
/* cgn parameters */
cp->cgn_info_mode = phba->cgn_p.cgn_param_mode;
@@ -13678,22 +13612,7 @@ lpfc_init_congestion_buf(struct lpfc_hba *phba)
cp->cgn_info_level1 = phba->cgn_p.cgn_param_level1;
cp->cgn_info_level2 = phba->cgn_p.cgn_param_level2;
- ktime_get_real_ts64(&cmpl_time);
- time64_to_tm(cmpl_time.tv_sec, 0, &broken);
-
- cp->cgn_info_month = broken.tm_mon + 1;
- cp->cgn_info_day = broken.tm_mday;
- cp->cgn_info_year = broken.tm_year - 100; /* relative to 2000 */
- cp->cgn_info_hour = broken.tm_hour;
- cp->cgn_info_minute = broken.tm_min;
- cp->cgn_info_second = broken.tm_sec;
-
- lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT,
- "2643 CGNInfo Init: Start Time "
- "%d/%d/%d %d:%d:%d\n",
- cp->cgn_info_day, cp->cgn_info_month,
- cp->cgn_info_year, cp->cgn_info_hour,
- cp->cgn_info_minute, cp->cgn_info_second);
+ lpfc_cgn_update_tstamp(phba, &cp->base_time);
/* Fill in default LUN qdepth */
if (phba->pport) {
@@ -13716,8 +13635,6 @@ void
lpfc_init_congestion_stat(struct lpfc_hba *phba)
{
struct lpfc_cgn_info *cp;
- struct timespec64 cmpl_time;
- struct tm broken;
uint32_t crc;
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
@@ -13729,22 +13646,7 @@ lpfc_init_congestion_stat(struct lpfc_hba *phba)
cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;
memset(&cp->cgn_stat, 0, sizeof(cp->cgn_stat));
- ktime_get_real_ts64(&cmpl_time);
- time64_to_tm(cmpl_time.tv_sec, 0, &broken);
-
- cp->cgn_stat_month = broken.tm_mon + 1;
- cp->cgn_stat_day = broken.tm_mday;
- cp->cgn_stat_year = broken.tm_year - 100; /* relative to 2000 */
- cp->cgn_stat_hour = broken.tm_hour;
- cp->cgn_stat_minute = broken.tm_min;
-
- lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT,
- "2647 CGNstat Init: Start Time "
- "%d/%d/%d %d:%d\n",
- cp->cgn_stat_day, cp->cgn_stat_month,
- cp->cgn_stat_year, cp->cgn_stat_hour,
- cp->cgn_stat_minute);
-
+ lpfc_cgn_update_tstamp(phba, &cp->stat_start);
crc = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED);
cp->cgn_info_crc = cpu_to_le32(crc);
}
@@ -14743,10 +14645,10 @@ lpfc_write_firmware(const struct firmware *fw, void *context)
INIT_LIST_HEAD(&dma_buffer_list);
lpfc_decode_firmware_rev(phba, fwrev, 1);
if (strncmp(fwrev, image->revision, strnlen(image->revision, 16))) {
- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "3023 Updating Firmware, Current Version:%s "
- "New Version:%s\n",
- fwrev, image->revision);
+ lpfc_log_msg(phba, KERN_NOTICE, LOG_INIT | LOG_SLI,
+ "3023 Updating Firmware, Current Version:%s "
+ "New Version:%s\n",
+ fwrev, image->revision);
for (i = 0; i < LPFC_MBX_WR_CONFIG_MAX_BDE; i++) {
dmabuf = kzalloc(sizeof(struct lpfc_dmabuf),
GFP_KERNEL);
@@ -14793,10 +14695,10 @@ lpfc_write_firmware(const struct firmware *fw, void *context)
}
rc = offset;
} else
- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "3029 Skipped Firmware update, Current "
- "Version:%s New Version:%s\n",
- fwrev, image->revision);
+ lpfc_log_msg(phba, KERN_NOTICE, LOG_INIT | LOG_SLI,
+ "3029 Skipped Firmware update, Current "
+ "Version:%s New Version:%s\n",
+ fwrev, image->revision);
release_out:
list_for_each_entry_safe(dmabuf, next, &dma_buffer_list, list) {
@@ -14808,11 +14710,11 @@ release_out:
release_firmware(fw);
out:
if (rc < 0)
- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "3062 Firmware update error, status %d.\n", rc);
+ lpfc_log_msg(phba, KERN_ERR, LOG_INIT | LOG_SLI,
+ "3062 Firmware update error, status %d.\n", rc);
else
- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "3024 Firmware update success: size %d.\n", rc);
+ lpfc_log_msg(phba, KERN_NOTICE, LOG_INIT | LOG_SLI,
+ "3024 Firmware update success: size %d.\n", rc);
}
/**
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index b39cefcd8703..f896ec610433 100644
--- a/drivers/scsi/lpfc/lpfc_logmsg.h
+++ b/drivers/scsi/lpfc/lpfc_logmsg.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2009 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -55,7 +55,7 @@ void lpfc_dbg_print(struct lpfc_hba *phba, const char *fmt, ...);
/* generate message by verbose log setting or severity */
#define lpfc_vlog_msg(vport, level, mask, fmt, arg...) \
-{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '4')) \
+{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '5')) \
dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \
fmt, (vport)->phba->brd_no, vport->vpi, ##arg); }
@@ -64,7 +64,7 @@ do { \
{ uint32_t log_verbose = (phba)->pport ? \
(phba)->pport->cfg_log_verbose : \
(phba)->cfg_log_verbose; \
- if (((mask) & log_verbose) || (level[1] <= '4')) \
+ if (((mask) & log_verbose) || (level[1] <= '5')) \
dev_printk(level, &((phba)->pcidev)->dev, "%d:" \
fmt, phba->brd_no, ##arg); \
} \
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index adda70423c77..8db7cb99903d 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -310,20 +310,20 @@ lpfc_nvme_handle_lsreq(struct lpfc_hba *phba,
* for the LS request.
**/
void
-__lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport,
+__lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport,
struct lpfc_iocbq *cmdwqe,
struct lpfc_wcqe_complete *wcqe)
{
struct nvmefc_ls_req *pnvme_lsreq;
struct lpfc_dmabuf *buf_ptr;
struct lpfc_nodelist *ndlp;
- uint32_t status;
+ int status;
pnvme_lsreq = cmdwqe->context_un.nvme_lsreq;
ndlp = cmdwqe->ndlp;
buf_ptr = cmdwqe->bpl_dmabuf;
- status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK;
+ status = bf_get(lpfc_wcqe_c_status, wcqe);
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
"6047 NVMEx LS REQ x%px cmpl DID %x Xri: %x "
@@ -343,14 +343,17 @@ __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport,
kfree(buf_ptr);
cmdwqe->bpl_dmabuf = NULL;
}
- if (pnvme_lsreq->done)
+ if (pnvme_lsreq->done) {
+ if (status != CQE_STATUS_SUCCESS)
+ status = -ENXIO;
pnvme_lsreq->done(pnvme_lsreq, status);
- else
+ } else {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6046 NVMEx cmpl without done call back? "
"Data x%px DID %x Xri: %x status %x\n",
pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0,
cmdwqe->sli4_xritag, status);
+ }
if (ndlp) {
lpfc_nlp_put(ndlp);
cmdwqe->ndlp = NULL;
@@ -367,7 +370,7 @@ lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
uint32_t status;
struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
- status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK;
+ status = bf_get(lpfc_wcqe_c_status, wcqe);
if (vport->localport) {
lport = (struct lpfc_nvme_lport *)vport->localport->private;
@@ -1040,7 +1043,7 @@ lpfc_nvme_io_cmd_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
nCmd->rcv_rsplen = LPFC_NVME_ERSP_LEN;
nCmd->transferred_length = nCmd->payload_length;
} else {
- lpfc_ncmd->status = (status & LPFC_IOCB_STATUS_MASK);
+ lpfc_ncmd->status = status;
lpfc_ncmd->result = (wcqe->parameter & IOERR_PARAM_MASK);
/* For NVME, the only failure path that results in an
@@ -1893,38 +1896,38 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport,
pnvme_rport->port_id,
pnvme_fcreq);
- /* If the hba is getting reset, this flag is set. It is
- * cleared when the reset is complete and rings reestablished.
- */
- spin_lock_irqsave(&phba->hbalock, flags);
- /* driver queued commands are in process of being flushed */
- if (phba->hba_flag & HBA_IOQ_FLUSH) {
- spin_unlock_irqrestore(&phba->hbalock, flags);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
- "6139 Driver in reset cleanup - flushing "
- "NVME Req now. hba_flag x%x\n",
- phba->hba_flag);
- return;
- }
-
lpfc_nbuf = freqpriv->nvme_buf;
if (!lpfc_nbuf) {
- spin_unlock_irqrestore(&phba->hbalock, flags);
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6140 NVME IO req has no matching lpfc nvme "
"io buffer. Skipping abort req.\n");
return;
} else if (!lpfc_nbuf->nvmeCmd) {
- spin_unlock_irqrestore(&phba->hbalock, flags);
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6141 lpfc NVME IO req has no nvme_fcreq "
"io buffer. Skipping abort req.\n");
return;
}
- nvmereq_wqe = &lpfc_nbuf->cur_iocbq;
/* Guard against IO completion being called at same time */
- spin_lock(&lpfc_nbuf->buf_lock);
+ spin_lock_irqsave(&lpfc_nbuf->buf_lock, flags);
+
+ /* If the hba is getting reset, this flag is set. It is
+ * cleared when the reset is complete and rings reestablished.
+ */
+ spin_lock(&phba->hbalock);
+ /* driver queued commands are in process of being flushed */
+ if (phba->hba_flag & HBA_IOQ_FLUSH) {
+ spin_unlock(&phba->hbalock);
+ spin_unlock_irqrestore(&lpfc_nbuf->buf_lock, flags);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6139 Driver in reset cleanup - flushing "
+ "NVME Req now. hba_flag x%x\n",
+ phba->hba_flag);
+ return;
+ }
+
+ nvmereq_wqe = &lpfc_nbuf->cur_iocbq;
/*
* The lpfc_nbuf and the mapped nvme_fcreq in the driver's
@@ -1971,8 +1974,8 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport,
ret_val = lpfc_sli4_issue_abort_iotag(phba, nvmereq_wqe,
lpfc_nvme_abort_fcreq_cmpl);
- spin_unlock(&lpfc_nbuf->buf_lock);
- spin_unlock_irqrestore(&phba->hbalock, flags);
+ spin_unlock(&phba->hbalock);
+ spin_unlock_irqrestore(&lpfc_nbuf->buf_lock, flags);
/* Make sure HBA is alive */
lpfc_issue_hb_tmo(phba);
@@ -1998,8 +2001,8 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport,
return;
out_unlock:
- spin_unlock(&lpfc_nbuf->buf_lock);
- spin_unlock_irqrestore(&phba->hbalock, flags);
+ spin_unlock(&phba->hbalock);
+ spin_unlock_irqrestore(&lpfc_nbuf->buf_lock, flags);
return;
}
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
index 7517dd55fe91..dff4584d338b 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.c
+++ b/drivers/scsi/lpfc/lpfc_nvmet.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -300,7 +300,7 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
struct nvmefc_ls_rsp *ls_rsp = &axchg->ls_rsp;
uint32_t status, result;
- status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK;
+ status = bf_get(lpfc_wcqe_c_status, wcqe);
result = wcqe->parameter;
if (axchg->state != LPFC_NVME_STE_LS_RSP || axchg->entry_cnt != 2) {
@@ -350,7 +350,7 @@ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
if (!phba->targetport)
goto finish;
- status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK;
+ status = bf_get(lpfc_wcqe_c_status, wcqe);
result = wcqe->parameter;
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index e989f130434e..a62e091894f6 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -4026,7 +4026,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
struct lpfc_fast_path_event *fast_path_evt;
struct Scsi_Host *shost;
u32 logit = LOG_FCP;
- u32 status, idx;
+ u32 idx;
u32 lat;
u8 wait_xb_clr = 0;
@@ -4061,8 +4061,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
#endif
shost = cmd->device->host;
- status = bf_get(lpfc_wcqe_c_status, wcqe);
- lpfc_cmd->status = (status & LPFC_IOCB_STATUS_MASK);
+ lpfc_cmd->status = bf_get(lpfc_wcqe_c_status, wcqe);
lpfc_cmd->result = (wcqe->parameter & IOERR_PARAM_MASK);
lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY;
@@ -4104,11 +4103,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
}
#endif
if (unlikely(lpfc_cmd->status)) {
- if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT &&
- (lpfc_cmd->result & IOERR_DRVR_MASK))
- lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
- else if (lpfc_cmd->status >= IOSTAT_CNT)
- lpfc_cmd->status = IOSTAT_DEFAULT;
if (lpfc_cmd->status == IOSTAT_FCP_RSP_ERROR &&
!lpfc_cmd->fcp_rsp->rspStatus3 &&
(lpfc_cmd->fcp_rsp->rspStatus2 & RESID_UNDER) &&
@@ -4133,16 +4127,16 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
}
switch (lpfc_cmd->status) {
- case IOSTAT_SUCCESS:
+ case CQE_STATUS_SUCCESS:
cmd->result = DID_OK << 16;
break;
- case IOSTAT_FCP_RSP_ERROR:
+ case CQE_STATUS_FCP_RSP_FAILURE:
lpfc_handle_fcp_err(vport, lpfc_cmd,
pwqeIn->wqe.fcp_iread.total_xfer_len -
wcqe->total_data_placed);
break;
- case IOSTAT_NPORT_BSY:
- case IOSTAT_FABRIC_BSY:
+ case CQE_STATUS_NPORT_BSY:
+ case CQE_STATUS_FABRIC_BSY:
cmd->result = DID_TRANSPORT_DISRUPTED << 16;
fast_path_evt = lpfc_alloc_fast_evt(phba);
if (!fast_path_evt)
@@ -4185,7 +4179,27 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
wcqe->total_data_placed,
lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
break;
- case IOSTAT_REMOTE_STOP:
+ case CQE_STATUS_DI_ERROR:
+ if (bf_get(lpfc_wcqe_c_bg_edir, wcqe))
+ lpfc_cmd->result = IOERR_RX_DMA_FAILED;
+ else
+ lpfc_cmd->result = IOERR_TX_DMA_FAILED;
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_BG,
+ "9048 DI Error xri x%x status x%x DI ext "
+ "status x%x data placed x%x\n",
+ lpfc_cmd->cur_iocbq.sli4_xritag,
+ lpfc_cmd->status, wcqe->parameter,
+ wcqe->total_data_placed);
+ if (scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) {
+ /* BG enabled cmd. Parse BG error */
+ lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut);
+ break;
+ }
+ cmd->result = DID_ERROR << 16;
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG,
+ "9040 DI Error on unprotected cmd\n");
+ break;
+ case CQE_STATUS_REMOTE_STOP:
if (ndlp) {
/* This I/O was aborted by the target, we don't
* know the rxid and because we did not send the
@@ -4196,7 +4210,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
0, 0);
}
fallthrough;
- case IOSTAT_LOCAL_REJECT:
+ case CQE_STATUS_LOCAL_REJECT:
if (lpfc_cmd->result & IOERR_DRVR_MASK)
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
if (lpfc_cmd->result == IOERR_ELXSEC_KEY_UNWRAP_ERROR ||
@@ -4217,24 +4231,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
cmd->result = DID_TRANSPORT_DISRUPTED << 16;
break;
}
- if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED ||
- lpfc_cmd->result == IOERR_TX_DMA_FAILED) &&
- status == CQE_STATUS_DI_ERROR) {
- if (scsi_get_prot_op(cmd) !=
- SCSI_PROT_NORMAL) {
- /*
- * This is a response for a BG enabled
- * cmd. Parse BG error
- */
- lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut);
- break;
- } else {
- lpfc_printf_vlog(vport, KERN_WARNING,
- LOG_BG,
- "9040 non-zero BGSTAT "
- "on unprotected cmd\n");
- }
- }
lpfc_printf_vlog(vport, KERN_WARNING, logit,
"9036 Local Reject FCP cmd x%x failed"
" <%d/%lld> "
@@ -4253,10 +4249,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
fallthrough;
default:
- if (lpfc_cmd->status >= IOSTAT_CNT)
- lpfc_cmd->status = IOSTAT_DEFAULT;
cmd->result = DID_ERROR << 16;
- lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
"9037 FCP Completion Error: xri %x "
"status x%x result x%x [x%x] "
"placed x%x\n",
@@ -4273,7 +4267,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
"x%x SNS x%x x%x LBA x%llx Data: x%x x%x\n",
cmd->device->id, cmd->device->lun, cmd,
cmd->result, *lp, *(lp + 3),
- (u64)scsi_get_lba(cmd),
+ (cmd->device->sector_size) ?
+ (u64)scsi_get_lba(cmd) : 0,
cmd->retries, scsi_get_resid(cmd));
}
@@ -5009,7 +5004,6 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
return -ENODEV;
}
phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth;
- phba->lpfc_scsi_cmd_iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl;
return 0;
}
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 8693578888f1..58d10f8f75a7 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -82,7 +82,8 @@ static int lpfc_sli4_post_sgl_list(struct lpfc_hba *, struct list_head *,
int);
static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba,
struct lpfc_queue *eq,
- struct lpfc_eqe *eqe);
+ struct lpfc_eqe *eqe,
+ enum lpfc_poll_mode poll_mode);
static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba);
static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba);
static struct lpfc_cqe *lpfc_sli4_cq_get(struct lpfc_queue *q);
@@ -629,7 +630,7 @@ lpfc_sli4_eqcq_flush(struct lpfc_hba *phba, struct lpfc_queue *eq)
static int
lpfc_sli4_process_eq(struct lpfc_hba *phba, struct lpfc_queue *eq,
- uint8_t rearm)
+ u8 rearm, enum lpfc_poll_mode poll_mode)
{
struct lpfc_eqe *eqe;
int count = 0, consumed = 0;
@@ -639,7 +640,7 @@ lpfc_sli4_process_eq(struct lpfc_hba *phba, struct lpfc_queue *eq,
eqe = lpfc_sli4_eq_get(eq);
while (eqe) {
- lpfc_sli4_hba_handle_eqe(phba, eq, eqe);
+ lpfc_sli4_hba_handle_eqe(phba, eq, eqe, poll_mode);
__lpfc_sli4_consume_eqe(phba, eq, eqe);
consumed++;
@@ -1931,7 +1932,7 @@ lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total)
unsigned long iflags;
u32 ret_val;
u32 atot, wtot, max;
- u16 warn_sync_period = 0;
+ u8 warn_sync_period = 0;
/* First address any alarm / warning activity */
atot = atomic_xchg(&phba->cgn_sync_alarm_cnt, 0);
@@ -7957,7 +7958,7 @@ out_rdf:
* lpfc_init_idle_stat_hb - Initialize idle_stat tracking
* @phba: pointer to lpfc hba data structure.
*
- * This routine initializes the per-cq idle_stat to dynamically dictate
+ * This routine initializes the per-eq idle_stat to dynamically dictate
* polling decisions.
*
* Return codes:
@@ -7967,16 +7968,16 @@ static void lpfc_init_idle_stat_hb(struct lpfc_hba *phba)
{
int i;
struct lpfc_sli4_hdw_queue *hdwq;
- struct lpfc_queue *cq;
+ struct lpfc_queue *eq;
struct lpfc_idle_stat *idle_stat;
u64 wall;
for_each_present_cpu(i) {
hdwq = &phba->sli4_hba.hdwq[phba->sli4_hba.cpu_map[i].hdwq];
- cq = hdwq->io_cq;
+ eq = hdwq->hba_eq;
- /* Skip if we've already handled this cq's primary CPU */
- if (cq->chann != i)
+ /* Skip if we've already handled this eq's primary CPU */
+ if (eq->chann != i)
continue;
idle_stat = &phba->sli4_hba.idle_stat[i];
@@ -7985,13 +7986,14 @@ static void lpfc_init_idle_stat_hb(struct lpfc_hba *phba)
idle_stat->prev_wall = wall;
if (phba->nvmet_support ||
- phba->cmf_active_mode != LPFC_CFG_OFF)
- cq->poll_mode = LPFC_QUEUE_WORK;
+ phba->cmf_active_mode != LPFC_CFG_OFF ||
+ phba->intr_type != MSIX)
+ eq->poll_mode = LPFC_QUEUE_WORK;
else
- cq->poll_mode = LPFC_IRQ_POLL;
+ eq->poll_mode = LPFC_THREADED_IRQ;
}
- if (!phba->nvmet_support)
+ if (!phba->nvmet_support && phba->intr_type == MSIX)
schedule_delayed_work(&phba->idle_stat_delay_work,
msecs_to_jiffies(LPFC_IDLE_STAT_DELAY));
}
@@ -9218,7 +9220,8 @@ lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba)
if (mbox_pending)
/* process and rearm the EQ */
- lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM);
+ lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM,
+ LPFC_QUEUE_WORK);
else
/* Always clear and re-arm the EQ */
sli4_hba->sli4_write_eq_db(phba, fpeq, 0, LPFC_QUEUE_REARM);
@@ -11254,7 +11257,8 @@ inline void lpfc_sli4_poll_eq(struct lpfc_queue *eq)
* will be handled through a sched from polling timer
* function which is currently triggered every 1msec.
*/
- lpfc_sli4_process_eq(phba, eq, LPFC_QUEUE_NOARM);
+ lpfc_sli4_process_eq(phba, eq, LPFC_QUEUE_NOARM,
+ LPFC_QUEUE_WORK);
}
/**
@@ -14682,6 +14686,38 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
spin_unlock_irqrestore(&phba->hbalock, iflags);
workposted = true;
break;
+ case FC_STATUS_RQ_DMA_FAILURE:
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2564 RQE DMA Error x%x, x%08x x%08x x%08x "
+ "x%08x\n",
+ status, rcqe->word0, rcqe->word1,
+ rcqe->word2, rcqe->word3);
+
+ /* If IV set, no further recovery */
+ if (bf_get(lpfc_rcqe_iv, rcqe))
+ break;
+
+ /* recycle consumed resource */
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ lpfc_sli4_rq_release(hrq, drq);
+ dma_buf = lpfc_sli_hbqbuf_get(&phba->hbqs[0].hbq_buffer_list);
+ if (!dma_buf) {
+ hrq->RQ_no_buf_found++;
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ break;
+ }
+ hrq->RQ_rcv_buf++;
+ hrq->RQ_buf_posted--;
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ lpfc_in_buf_free(phba, &dma_buf->dbuf);
+ break;
+ default:
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2565 Unexpected RQE Status x%x, w0-3 x%08x "
+ "x%08x x%08x x%08x\n",
+ status, rcqe->word0, rcqe->word1,
+ rcqe->word2, rcqe->word3);
+ break;
}
out:
return workposted;
@@ -14803,7 +14839,6 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
* @cq: Pointer to CQ to be processed
* @handler: Routine to process each cqe
* @delay: Pointer to usdelay to set in case of rescheduling of the handler
- * @poll_mode: Polling mode we were called from
*
* This routine processes completion queue entries in a CQ. While a valid
* queue element is found, the handler is called. During processing checks
@@ -14821,8 +14856,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
static bool
__lpfc_sli4_process_cq(struct lpfc_hba *phba, struct lpfc_queue *cq,
bool (*handler)(struct lpfc_hba *, struct lpfc_queue *,
- struct lpfc_cqe *), unsigned long *delay,
- enum lpfc_poll_mode poll_mode)
+ struct lpfc_cqe *), unsigned long *delay)
{
struct lpfc_cqe *cqe;
bool workposted = false;
@@ -14863,10 +14897,6 @@ __lpfc_sli4_process_cq(struct lpfc_hba *phba, struct lpfc_queue *cq,
arm = false;
}
- /* Note: complete the irq_poll softirq before rearming CQ */
- if (poll_mode == LPFC_IRQ_POLL)
- irq_poll_complete(&cq->iop);
-
/* Track the max number of CQEs processed in 1 EQ */
if (count > cq->CQ_max_cqe)
cq->CQ_max_cqe = count;
@@ -14916,17 +14946,17 @@ __lpfc_sli4_sp_process_cq(struct lpfc_queue *cq)
case LPFC_MCQ:
workposted |= __lpfc_sli4_process_cq(phba, cq,
lpfc_sli4_sp_handle_mcqe,
- &delay, LPFC_QUEUE_WORK);
+ &delay);
break;
case LPFC_WCQ:
if (cq->subtype == LPFC_IO)
workposted |= __lpfc_sli4_process_cq(phba, cq,
lpfc_sli4_fp_handle_cqe,
- &delay, LPFC_QUEUE_WORK);
+ &delay);
else
workposted |= __lpfc_sli4_process_cq(phba, cq,
lpfc_sli4_sp_handle_cqe,
- &delay, LPFC_QUEUE_WORK);
+ &delay);
break;
default:
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
@@ -15203,6 +15233,38 @@ drop:
hrq->RQ_no_posted_buf++;
/* Post more buffers if possible */
break;
+ case FC_STATUS_RQ_DMA_FAILURE:
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2575 RQE DMA Error x%x, x%08x x%08x x%08x "
+ "x%08x\n",
+ status, rcqe->word0, rcqe->word1,
+ rcqe->word2, rcqe->word3);
+
+ /* If IV set, no further recovery */
+ if (bf_get(lpfc_rcqe_iv, rcqe))
+ break;
+
+ /* recycle consumed resource */
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ lpfc_sli4_rq_release(hrq, drq);
+ dma_buf = lpfc_sli_rqbuf_get(phba, hrq);
+ if (!dma_buf) {
+ hrq->RQ_no_buf_found++;
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ break;
+ }
+ hrq->RQ_rcv_buf++;
+ hrq->RQ_buf_posted--;
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ lpfc_rq_buf_free(phba, &dma_buf->hbuf);
+ break;
+ default:
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2576 Unexpected RQE Status x%x, w0-3 x%08x "
+ "x%08x x%08x x%08x\n",
+ status, rcqe->word0, rcqe->word1,
+ rcqe->word2, rcqe->word3);
+ break;
}
out:
return workposted;
@@ -15271,45 +15333,64 @@ lpfc_sli4_fp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
}
/**
- * lpfc_sli4_sched_cq_work - Schedules cq work
- * @phba: Pointer to HBA context object.
- * @cq: Pointer to CQ
- * @cqid: CQ ID
- *
- * This routine checks the poll mode of the CQ corresponding to
- * cq->chann, then either schedules a softirq or queue_work to complete
- * cq work.
+ * __lpfc_sli4_hba_process_cq - Process a fast-path event queue entry
+ * @cq: Pointer to CQ to be processed
*
- * queue_work path is taken if in NVMET mode, or if poll_mode is in
- * LPFC_QUEUE_WORK mode. Otherwise, softirq path is taken.
+ * This routine calls the cq processing routine with the handler for
+ * fast path CQEs.
*
+ * The CQ routine returns two values: the first is the calling status,
+ * which indicates whether work was queued to the background discovery
+ * thread. If true, the routine should wakeup the discovery thread;
+ * the second is the delay parameter. If non-zero, rather than rearming
+ * the CQ and yet another interrupt, the CQ handler should be queued so
+ * that it is processed in a subsequent polling action. The value of
+ * the delay indicates when to reschedule it.
**/
-static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba,
- struct lpfc_queue *cq, uint16_t cqid)
+static void
+__lpfc_sli4_hba_process_cq(struct lpfc_queue *cq)
{
- int ret = 0;
+ struct lpfc_hba *phba = cq->phba;
+ unsigned long delay;
+ bool workposted = false;
+ int ret;
- switch (cq->poll_mode) {
- case LPFC_IRQ_POLL:
- /* CGN mgmt is mutually exclusive from softirq processing */
- if (phba->cmf_active_mode == LPFC_CFG_OFF) {
- irq_poll_sched(&cq->iop);
- break;
- }
- fallthrough;
- case LPFC_QUEUE_WORK:
- default:
+ /* process and rearm the CQ */
+ workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_fp_handle_cqe,
+ &delay);
+
+ if (delay) {
if (is_kdump_kernel())
- ret = queue_work(phba->wq, &cq->irqwork);
+ ret = queue_delayed_work(phba->wq, &cq->sched_irqwork,
+ delay);
else
- ret = queue_work_on(cq->chann, phba->wq, &cq->irqwork);
+ ret = queue_delayed_work_on(cq->chann, phba->wq,
+ &cq->sched_irqwork, delay);
if (!ret)
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "0383 Cannot schedule queue work "
- "for CQ eqcqid=%d, cqid=%d on CPU %d\n",
- cqid, cq->queue_id,
- raw_smp_processor_id());
+ "0367 Cannot schedule queue work "
+ "for cqid=%d on CPU %d\n",
+ cq->queue_id, cq->chann);
}
+
+ /* wake up worker thread if there are works to be done */
+ if (workposted)
+ lpfc_worker_wake_up(phba);
+}
+
+/**
+ * lpfc_sli4_hba_process_cq - fast-path work handler when started by
+ * interrupt
+ * @work: pointer to work element
+ *
+ * translates from the work handler and calls the fast-path handler.
+ **/
+static void
+lpfc_sli4_hba_process_cq(struct work_struct *work)
+{
+ struct lpfc_queue *cq = container_of(work, struct lpfc_queue, irqwork);
+
+ __lpfc_sli4_hba_process_cq(cq);
}
/**
@@ -15317,6 +15398,7 @@ static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba,
* @phba: Pointer to HBA context object.
* @eq: Pointer to the queue structure.
* @eqe: Pointer to fast-path event queue entry.
+ * @poll_mode: poll_mode to execute processing the cq.
*
* This routine process a event queue entry from the fast-path event queue.
* It will check the MajorCode and MinorCode to determine this is for a
@@ -15327,11 +15409,12 @@ static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba,
**/
static void
lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_queue *eq,
- struct lpfc_eqe *eqe)
+ struct lpfc_eqe *eqe, enum lpfc_poll_mode poll_mode)
{
struct lpfc_queue *cq = NULL;
uint32_t qidx = eq->hdwq;
uint16_t cqid, id;
+ int ret;
if (unlikely(bf_get_le32(lpfc_eqe_major_code, eqe) != 0)) {
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
@@ -15391,70 +15474,25 @@ work_cq:
else
cq->isr_timestamp = 0;
#endif
- lpfc_sli4_sched_cq_work(phba, cq, cqid);
-}
-
-/**
- * __lpfc_sli4_hba_process_cq - Process a fast-path event queue entry
- * @cq: Pointer to CQ to be processed
- * @poll_mode: Enum lpfc_poll_state to determine poll mode
- *
- * This routine calls the cq processing routine with the handler for
- * fast path CQEs.
- *
- * The CQ routine returns two values: the first is the calling status,
- * which indicates whether work was queued to the background discovery
- * thread. If true, the routine should wakeup the discovery thread;
- * the second is the delay parameter. If non-zero, rather than rearming
- * the CQ and yet another interrupt, the CQ handler should be queued so
- * that it is processed in a subsequent polling action. The value of
- * the delay indicates when to reschedule it.
- **/
-static void
-__lpfc_sli4_hba_process_cq(struct lpfc_queue *cq,
- enum lpfc_poll_mode poll_mode)
-{
- struct lpfc_hba *phba = cq->phba;
- unsigned long delay;
- bool workposted = false;
- int ret = 0;
-
- /* process and rearm the CQ */
- workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_fp_handle_cqe,
- &delay, poll_mode);
- if (delay) {
+ switch (poll_mode) {
+ case LPFC_THREADED_IRQ:
+ __lpfc_sli4_hba_process_cq(cq);
+ break;
+ case LPFC_QUEUE_WORK:
+ default:
if (is_kdump_kernel())
- ret = queue_delayed_work(phba->wq, &cq->sched_irqwork,
- delay);
+ ret = queue_work(phba->wq, &cq->irqwork);
else
- ret = queue_delayed_work_on(cq->chann, phba->wq,
- &cq->sched_irqwork, delay);
+ ret = queue_work_on(cq->chann, phba->wq, &cq->irqwork);
if (!ret)
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "0367 Cannot schedule queue work "
- "for cqid=%d on CPU %d\n",
- cq->queue_id, cq->chann);
+ "0383 Cannot schedule queue work "
+ "for CQ eqcqid=%d, cqid=%d on CPU %d\n",
+ cqid, cq->queue_id,
+ raw_smp_processor_id());
+ break;
}
-
- /* wake up worker thread if there are works to be done */
- if (workposted)
- lpfc_worker_wake_up(phba);
-}
-
-/**
- * lpfc_sli4_hba_process_cq - fast-path work handler when started by
- * interrupt
- * @work: pointer to work element
- *
- * translates from the work handler and calls the fast-path handler.
- **/
-static void
-lpfc_sli4_hba_process_cq(struct work_struct *work)
-{
- struct lpfc_queue *cq = container_of(work, struct lpfc_queue, irqwork);
-
- __lpfc_sli4_hba_process_cq(cq, LPFC_QUEUE_WORK);
}
/**
@@ -15469,7 +15507,7 @@ lpfc_sli4_dly_hba_process_cq(struct work_struct *work)
struct lpfc_queue *cq = container_of(to_delayed_work(work),
struct lpfc_queue, sched_irqwork);
- __lpfc_sli4_hba_process_cq(cq, LPFC_QUEUE_WORK);
+ __lpfc_sli4_hba_process_cq(cq);
}
/**
@@ -15495,8 +15533,9 @@ lpfc_sli4_dly_hba_process_cq(struct work_struct *work)
* and returns for these events. This function is called without any lock
* held. It gets the hbalock to access and update SLI data structures.
*
- * This function returns IRQ_HANDLED when interrupt is handled else it
- * returns IRQ_NONE.
+ * This function returns IRQ_HANDLED when interrupt is handled, IRQ_WAKE_THREAD
+ * when interrupt is scheduled to be handled from a threaded irq context, or
+ * else returns IRQ_NONE.
**/
irqreturn_t
lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
@@ -15505,8 +15544,8 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
struct lpfc_hba_eq_hdl *hba_eq_hdl;
struct lpfc_queue *fpeq;
unsigned long iflag;
- int ecount = 0;
int hba_eqidx;
+ int ecount = 0;
struct lpfc_eq_intr_info *eqi;
/* Get the driver's phba structure from the dev_id */
@@ -15535,30 +15574,41 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
return IRQ_NONE;
}
- eqi = this_cpu_ptr(phba->sli4_hba.eq_info);
- eqi->icnt++;
-
- fpeq->last_cpu = raw_smp_processor_id();
+ switch (fpeq->poll_mode) {
+ case LPFC_THREADED_IRQ:
+ /* CGN mgmt is mutually exclusive from irq processing */
+ if (phba->cmf_active_mode == LPFC_CFG_OFF)
+ return IRQ_WAKE_THREAD;
+ fallthrough;
+ case LPFC_QUEUE_WORK:
+ default:
+ eqi = this_cpu_ptr(phba->sli4_hba.eq_info);
+ eqi->icnt++;
- if (eqi->icnt > LPFC_EQD_ISR_TRIGGER &&
- fpeq->q_flag & HBA_EQ_DELAY_CHK &&
- phba->cfg_auto_imax &&
- fpeq->q_mode != LPFC_MAX_AUTO_EQ_DELAY &&
- phba->sli.sli_flag & LPFC_SLI_USE_EQDR)
- lpfc_sli4_mod_hba_eq_delay(phba, fpeq, LPFC_MAX_AUTO_EQ_DELAY);
+ fpeq->last_cpu = raw_smp_processor_id();
- /* process and rearm the EQ */
- ecount = lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM);
+ if (eqi->icnt > LPFC_EQD_ISR_TRIGGER &&
+ fpeq->q_flag & HBA_EQ_DELAY_CHK &&
+ phba->cfg_auto_imax &&
+ fpeq->q_mode != LPFC_MAX_AUTO_EQ_DELAY &&
+ phba->sli.sli_flag & LPFC_SLI_USE_EQDR)
+ lpfc_sli4_mod_hba_eq_delay(phba, fpeq,
+ LPFC_MAX_AUTO_EQ_DELAY);
- if (unlikely(ecount == 0)) {
- fpeq->EQ_no_entry++;
- if (phba->intr_type == MSIX)
- /* MSI-X treated interrupt served as no EQ share INT */
- lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
- "0358 MSI-X interrupt with no EQE\n");
- else
- /* Non MSI-X treated on interrupt as EQ share INT */
- return IRQ_NONE;
+ /* process and rearm the EQ */
+ ecount = lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM,
+ LPFC_QUEUE_WORK);
+
+ if (unlikely(ecount == 0)) {
+ fpeq->EQ_no_entry++;
+ if (phba->intr_type == MSIX)
+ /* MSI-X treated interrupt served as no EQ share INT */
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "0358 MSI-X interrupt with no EQE\n");
+ else
+ /* Non MSI-X treated on interrupt as EQ share INT */
+ return IRQ_NONE;
+ }
}
return IRQ_HANDLED;
@@ -16115,13 +16165,69 @@ out:
return status;
}
-static int lpfc_cq_poll_hdler(struct irq_poll *iop, int budget)
+/**
+ * lpfc_sli4_hba_intr_handler_th - SLI4 HBA threaded interrupt handler
+ * @irq: Interrupt number.
+ * @dev_id: The device context pointer.
+ *
+ * This routine is a mirror of lpfc_sli4_hba_intr_handler, but executed within
+ * threaded irq context.
+ *
+ * Returns
+ * IRQ_HANDLED - interrupt is handled
+ * IRQ_NONE - otherwise
+ **/
+irqreturn_t lpfc_sli4_hba_intr_handler_th(int irq, void *dev_id)
{
- struct lpfc_queue *cq = container_of(iop, struct lpfc_queue, iop);
+ struct lpfc_hba *phba;
+ struct lpfc_hba_eq_hdl *hba_eq_hdl;
+ struct lpfc_queue *fpeq;
+ int ecount = 0;
+ int hba_eqidx;
+ struct lpfc_eq_intr_info *eqi;
- __lpfc_sli4_hba_process_cq(cq, LPFC_IRQ_POLL);
+ /* Get the driver's phba structure from the dev_id */
+ hba_eq_hdl = (struct lpfc_hba_eq_hdl *)dev_id;
+ phba = hba_eq_hdl->phba;
+ hba_eqidx = hba_eq_hdl->idx;
- return 1;
+ if (unlikely(!phba))
+ return IRQ_NONE;
+ if (unlikely(!phba->sli4_hba.hdwq))
+ return IRQ_NONE;
+
+ /* Get to the EQ struct associated with this vector */
+ fpeq = phba->sli4_hba.hba_eq_hdl[hba_eqidx].eq;
+ if (unlikely(!fpeq))
+ return IRQ_NONE;
+
+ eqi = per_cpu_ptr(phba->sli4_hba.eq_info, raw_smp_processor_id());
+ eqi->icnt++;
+
+ fpeq->last_cpu = raw_smp_processor_id();
+
+ if (eqi->icnt > LPFC_EQD_ISR_TRIGGER &&
+ fpeq->q_flag & HBA_EQ_DELAY_CHK &&
+ phba->cfg_auto_imax &&
+ fpeq->q_mode != LPFC_MAX_AUTO_EQ_DELAY &&
+ phba->sli.sli_flag & LPFC_SLI_USE_EQDR)
+ lpfc_sli4_mod_hba_eq_delay(phba, fpeq, LPFC_MAX_AUTO_EQ_DELAY);
+
+ /* process and rearm the EQ */
+ ecount = lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM,
+ LPFC_THREADED_IRQ);
+
+ if (unlikely(ecount == 0)) {
+ fpeq->EQ_no_entry++;
+ if (phba->intr_type == MSIX)
+ /* MSI-X treated interrupt served as no EQ share INT */
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "3358 MSI-X interrupt with no EQE\n");
+ else
+ /* Non MSI-X treated on interrupt as EQ share INT */
+ return IRQ_NONE;
+ }
+ return IRQ_HANDLED;
}
/**
@@ -16265,8 +16371,6 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
if (cq->queue_id > phba->sli4_hba.cq_max)
phba->sli4_hba.cq_max = cq->queue_id;
-
- irq_poll_init(&cq->iop, LPFC_IRQ_POLL_WEIGHT, lpfc_cq_poll_hdler);
out:
mempool_free(mbox, phba->mbox_mem_pool);
return status;
@@ -20696,23 +20800,23 @@ lpfc_log_fw_write_cmpl(struct lpfc_hba *phba, u32 shdr_status,
if (shdr_add_status == LPFC_ADD_STATUS_INCOMPAT_OBJ) {
switch (shdr_add_status_2) {
case LPFC_ADD_STATUS_2_INCOMPAT_FLASH:
- lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
- "4199 Firmware write failed: "
- "image incompatible with flash x%02x\n",
- phba->sli4_hba.flash_id);
+ lpfc_log_msg(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
+ "4199 Firmware write failed: "
+ "image incompatible with flash x%02x\n",
+ phba->sli4_hba.flash_id);
break;
case LPFC_ADD_STATUS_2_INCORRECT_ASIC:
- lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
- "4200 Firmware write failed: "
- "image incompatible with ASIC "
- "architecture x%02x\n",
- phba->sli4_hba.asic_rev);
+ lpfc_log_msg(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
+ "4200 Firmware write failed: "
+ "image incompatible with ASIC "
+ "architecture x%02x\n",
+ phba->sli4_hba.asic_rev);
break;
default:
- lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
- "4210 Firmware write failed: "
- "add_status_2 x%02x\n",
- shdr_add_status_2);
+ lpfc_log_msg(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
+ "4210 Firmware write failed: "
+ "add_status_2 x%02x\n",
+ shdr_add_status_2);
break;
}
} else if (!shdr_status && !shdr_add_status) {
@@ -20725,26 +20829,26 @@ lpfc_log_fw_write_cmpl(struct lpfc_hba *phba, u32 shdr_status,
switch (shdr_change_status) {
case (LPFC_CHANGE_STATUS_PHYS_DEV_RESET):
- lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
- "3198 Firmware write complete: System "
- "reboot required to instantiate\n");
+ lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI,
+ "3198 Firmware write complete: System "
+ "reboot required to instantiate\n");
break;
case (LPFC_CHANGE_STATUS_FW_RESET):
- lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
- "3199 Firmware write complete: "
- "Firmware reset required to "
- "instantiate\n");
+ lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI,
+ "3199 Firmware write complete: "
+ "Firmware reset required to "
+ "instantiate\n");
break;
case (LPFC_CHANGE_STATUS_PORT_MIGRATION):
- lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
- "3200 Firmware write complete: Port "
- "Migration or PCI Reset required to "
- "instantiate\n");
+ lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI,
+ "3200 Firmware write complete: Port "
+ "Migration or PCI Reset required to "
+ "instantiate\n");
break;
case (LPFC_CHANGE_STATUS_PCI_RESET):
- lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
- "3201 Firmware write complete: PCI "
- "Reset required to instantiate\n");
+ lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI,
+ "3201 Firmware write complete: PCI "
+ "Reset required to instantiate\n");
break;
default:
break;
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index 2a0864e6d7cd..2541a8fba093 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -140,7 +140,7 @@ struct lpfc_rqb {
enum lpfc_poll_mode {
LPFC_QUEUE_WORK,
- LPFC_IRQ_POLL
+ LPFC_THREADED_IRQ,
};
struct lpfc_idle_stat {
@@ -279,8 +279,6 @@ struct lpfc_queue {
struct list_head _poll_list;
void **q_pgs; /* array to index entries per page */
-#define LPFC_IRQ_POLL_WEIGHT 256
- struct irq_poll iop;
enum lpfc_poll_mode poll_mode;
};
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index c97411b0992e..6f35491aed0f 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "14.2.0.11"
+#define LPFC_DRIVER_VERSION "14.2.0.13"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */
diff --git a/drivers/scsi/megaraid/Kconfig.megaraid b/drivers/scsi/megaraid/Kconfig.megaraid
index 2adc2afd9f91..3f2ce1eb081c 100644
--- a/drivers/scsi/megaraid/Kconfig.megaraid
+++ b/drivers/scsi/megaraid/Kconfig.megaraid
@@ -1,13 +1,13 @@
# SPDX-License-Identifier: GPL-2.0-only
config MEGARAID_NEWGEN
bool "LSI Logic New Generation RAID Device Drivers"
- depends on PCI && SCSI
+ depends on PCI && HAS_IOPORT && SCSI
help
LSI Logic RAID Device Drivers
config MEGARAID_MM
tristate "LSI Logic Management Module (New Driver)"
- depends on PCI && SCSI && MEGARAID_NEWGEN
+ depends on PCI && HAS_IOPORT && SCSI && MEGARAID_NEWGEN
help
Management Module provides ioctl, sysfs support for LSI Logic
RAID controllers.
@@ -67,7 +67,7 @@ config MEGARAID_MAILBOX
config MEGARAID_LEGACY
tristate "LSI Logic Legacy MegaRAID Driver"
- depends on PCI && SCSI
+ depends on PCI && HAS_IOPORT && SCSI
help
This driver supports the LSI MegaRAID 418, 428, 438, 466, 762, 490
and 467 SCSI host adapters. This driver also support the all U320
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 63bac3684c19..3554f6b07727 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -1722,11 +1722,9 @@ struct megasas_sge_skinny {
} __packed;
union megasas_sgl {
-
- struct megasas_sge32 sge32[1];
- struct megasas_sge64 sge64[1];
- struct megasas_sge_skinny sge_skinny[1];
-
+ DECLARE_FLEX_ARRAY(struct megasas_sge32, sge32);
+ DECLARE_FLEX_ARRAY(struct megasas_sge64, sge64);
+ DECLARE_FLEX_ARRAY(struct megasas_sge_skinny, sge_skinny);
} __attribute__ ((packed));
struct megasas_header {
diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h
index dfe6b87fe288..0afb687402e1 100644
--- a/drivers/scsi/mpi3mr/mpi3mr.h
+++ b/drivers/scsi/mpi3mr/mpi3mr.h
@@ -1133,18 +1133,18 @@ struct mpi3mr_ioc {
u32 chain_buf_count;
struct dma_pool *chain_buf_pool;
struct chain_element *chain_sgl_list;
- void *chain_bitmap;
+ unsigned long *chain_bitmap;
spinlock_t chain_buf_lock;
struct mpi3mr_drv_cmd bsg_cmds;
struct mpi3mr_drv_cmd host_tm_cmds;
struct mpi3mr_drv_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD];
struct mpi3mr_drv_cmd evtack_cmds[MPI3MR_NUM_EVTACKCMD];
- void *devrem_bitmap;
+ unsigned long *devrem_bitmap;
u16 dev_handle_bitmap_bits;
- void *removepend_bitmap;
+ unsigned long *removepend_bitmap;
struct list_head delayed_rmhs_list;
- void *evtack_cmds_bitmap;
+ unsigned long *evtack_cmds_bitmap;
struct list_head delayed_evtack_cmds_list;
u32 ts_update_counter;
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
index 075fa67e95ee..5fa07d6ee5b8 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
@@ -402,6 +402,11 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc,
memcpy((u8 *)cmdptr->reply, (u8 *)def_reply,
mrioc->reply_sz);
}
+ if (sense_buf && cmdptr->sensebuf) {
+ cmdptr->is_sense = 1;
+ memcpy(cmdptr->sensebuf, sense_buf,
+ MPI3MR_SENSE_BUF_SZ);
+ }
if (cmdptr->is_waiting) {
complete(&cmdptr->done);
cmdptr->is_waiting = 0;
@@ -1134,7 +1139,7 @@ static int mpi3mr_issue_and_process_mur(struct mpi3mr_ioc *mrioc,
static int
mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc)
{
- void *removepend_bitmap;
+ unsigned long *removepend_bitmap;
if (mrioc->facts.reply_sz > mrioc->reply_sz) {
ioc_err(mrioc,
diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c
index 4d84d5bd173f..82b55e955730 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_transport.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c
@@ -2058,7 +2058,7 @@ int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle)
sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node),
GFP_KERNEL);
if (!sas_expander)
- return -1;
+ return -ENOMEM;
sas_expander->handle = handle;
sas_expander->num_phys = expander_pg0.num_phys;
diff --git a/drivers/scsi/mvsas/Kconfig b/drivers/scsi/mvsas/Kconfig
index 79812b80743b..5ac7fd593b17 100644
--- a/drivers/scsi/mvsas/Kconfig
+++ b/drivers/scsi/mvsas/Kconfig
@@ -9,7 +9,7 @@
config SCSI_MVSAS
tristate "Marvell 88SE64XX/88SE94XX SAS/SATA support"
- depends on PCI
+ depends on PCI && HAS_IOPORT
select SCSI_SAS_LIBSAS
select FW_LOADER
help
diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
index 9696b6b5591f..449bd85db7bb 100644
--- a/drivers/scsi/pcmcia/Kconfig
+++ b/drivers/scsi/pcmcia/Kconfig
@@ -12,6 +12,7 @@ if SCSI_LOWLEVEL_PCMCIA && SCSI && PCMCIA && m
config PCMCIA_AHA152X
tristate "Adaptec AHA152X PCMCIA support"
+ depends on HAS_IOPORT
select SCSI_SPI_ATTRS
help
Say Y here if you intend to attach this type of PCMCIA SCSI host
@@ -22,6 +23,7 @@ config PCMCIA_AHA152X
config PCMCIA_FDOMAIN
tristate "Future Domain PCMCIA support"
+ depends on HAS_IOPORT
select SCSI_FDOMAIN
help
Say Y here if you intend to attach this type of PCMCIA SCSI host
@@ -32,7 +34,7 @@ config PCMCIA_FDOMAIN
config PCMCIA_NINJA_SCSI
tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support"
- depends on !64BIT || COMPILE_TEST
+ depends on (!64BIT || COMPILE_TEST) && HAS_IOPORT
help
If you intend to attach this type of PCMCIA SCSI host adapter to
your computer, say Y here and read
@@ -66,6 +68,7 @@ config PCMCIA_NINJA_SCSI
config PCMCIA_QLOGIC
tristate "Qlogic PCMCIA support"
+ depends on HAS_IOPORT
help
Say Y here if you intend to attach this type of PCMCIA SCSI host
adapter to your computer.
@@ -75,6 +78,7 @@ config PCMCIA_QLOGIC
config PCMCIA_SYM53C500
tristate "Symbios 53c500 PCMCIA support"
+ depends on HAS_IOPORT
help
Say Y here if you have a New Media Bus Toaster or other PCMCIA
SCSI adapter based on the Symbios 53c500 controller.
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 8b9490011e36..2e886c1d867d 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -43,7 +43,8 @@
#include "pm8001_chips.h"
#include "pm80xx_hwi.h"
-static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING;
+static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING |
+ PM8001_EVENT_LOGGING | PM8001_INIT_LOGGING;
module_param(logging_level, ulong, 0644);
MODULE_PARM_DESC(logging_level, " bits for enabling logging info.");
@@ -666,7 +667,7 @@ static void pm8001_post_sas_ha_init(struct Scsi_Host *shost,
* Currently we just set the fixed SAS address to our HBA, for manufacture,
* it should read from the EEPROM
*/
-static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
+static int pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
{
u8 i, j;
u8 sas_add[8];
@@ -679,6 +680,12 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
struct pm8001_ioctl_payload payload;
u16 deviceid;
int rc;
+ unsigned long time_remaining;
+
+ if (PM8001_CHIP_DISP->fatal_errors(pm8001_ha)) {
+ pm8001_dbg(pm8001_ha, FAIL, "controller is in fatal error state\n");
+ return -EIO;
+ }
pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
pm8001_ha->nvmd_completion = &completion;
@@ -703,16 +710,23 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
payload.offset = 0;
payload.func_specific = kzalloc(payload.rd_length, GFP_KERNEL);
if (!payload.func_specific) {
- pm8001_dbg(pm8001_ha, INIT, "mem alloc fail\n");
- return;
+ pm8001_dbg(pm8001_ha, FAIL, "mem alloc fail\n");
+ return -ENOMEM;
}
rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
if (rc) {
kfree(payload.func_specific);
- pm8001_dbg(pm8001_ha, INIT, "nvmd failed\n");
- return;
+ pm8001_dbg(pm8001_ha, FAIL, "nvmd failed\n");
+ return -EIO;
+ }
+ time_remaining = wait_for_completion_timeout(&completion,
+ msecs_to_jiffies(60*1000)); // 1 min
+ if (!time_remaining) {
+ kfree(payload.func_specific);
+ pm8001_dbg(pm8001_ha, FAIL, "get_nvmd_req timeout\n");
+ return -EIO;
}
- wait_for_completion(&completion);
+
for (i = 0, j = 0; i <= 7; i++, j++) {
if (pm8001_ha->chip_id == chip_8001) {
@@ -751,6 +765,7 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
memcpy(pm8001_ha->sas_addr, &pm8001_ha->phy[0].dev_sas_addr,
SAS_ADDR_SIZE);
#endif
+ return 0;
}
/*
@@ -1166,7 +1181,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
pm80xx_set_thermal_config(pm8001_ha);
}
- pm8001_init_sas_add(pm8001_ha);
+ if (pm8001_init_sas_add(pm8001_ha))
+ goto err_out_shost;
/* phy setting support for motherboard controller */
rc = pm8001_configure_phy_settings(pm8001_ha);
if (rc)
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index e5673c774f66..a5a31dfa4512 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -167,6 +167,17 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
pm8001_ha = sas_phy->ha->lldd_ha;
phy = &pm8001_ha->phy[phy_id];
pm8001_ha->phy[phy_id].enable_completion = &completion;
+
+ if (PM8001_CHIP_DISP->fatal_errors(pm8001_ha)) {
+ /*
+ * If the controller is in fatal error state,
+ * we will not get a response from the controller
+ */
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Phy control failed due to fatal errors\n");
+ return -EFAULT;
+ }
+
switch (func) {
case PHY_FUNC_SET_LINK_RATE:
rates = funcdata;
@@ -908,6 +919,17 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
struct pm8001_device *pm8001_dev = dev->lldd_dev;
struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev);
DECLARE_COMPLETION_ONSTACK(completion_setstate);
+
+ if (PM8001_CHIP_DISP->fatal_errors(pm8001_ha)) {
+ /*
+ * If the controller is in fatal error state,
+ * we will not get a response from the controller
+ */
+ pm8001_dbg(pm8001_ha, FAIL,
+ "LUN reset failed due to fatal errors\n");
+ return rc;
+ }
+
if (dev_is_sata(dev)) {
struct sas_phy *phy = sas_get_local_phy(dev);
sas_execute_internal_abort_dev(dev, 0, NULL);
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index dc1f4d958e03..953572fc0d9e 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -71,6 +71,7 @@
#define PM8001_DEV_LOGGING 0x80 /* development message logging */
#define PM8001_DEVIO_LOGGING 0x100 /* development io message logging */
#define PM8001_IOERR_LOGGING 0x200 /* development io err message logging */
+#define PM8001_EVENT_LOGGING 0x400 /* HW event logging */
#define pm8001_info(HBA, fmt, ...) \
pr_info("%s:: %s %d: " fmt, \
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 9584cadc4201..39a12ee94a72 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -3239,9 +3239,9 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
struct pm8001_port *port = &pm8001_ha->port[port_id];
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
unsigned long flags;
- pm8001_dbg(pm8001_ha, DEVIO,
- "port id %d, phy id %d link_rate %d portstate 0x%x\n",
- port_id, phy_id, link_rate, portstate);
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_SATA_PHY_UP phyid:%#x port_id:%#x link_rate:%d portstate:%#x\n",
+ phy_id, port_id, link_rate, portstate);
phy->port = port;
port->port_id = port_id;
@@ -3291,10 +3291,14 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
phy->phy_attached = 0;
switch (portstate) {
case PORT_VALID:
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_VALID\n",
+ phy_id, port_id);
break;
case PORT_INVALID:
- pm8001_dbg(pm8001_ha, MSG, " PortInvalid portID %d\n",
- port_id);
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_INVALID\n",
+ phy_id, port_id);
pm8001_dbg(pm8001_ha, MSG,
" Last phy Down and port invalid\n");
if (port_sata) {
@@ -3306,18 +3310,21 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
sas_phy_disconnected(&phy->sas_phy);
break;
case PORT_IN_RESET:
- pm8001_dbg(pm8001_ha, MSG, " Port In Reset portID %d\n",
- port_id);
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_IN_RESET\n",
+ phy_id, port_id);
break;
case PORT_NOT_ESTABLISHED:
- pm8001_dbg(pm8001_ha, MSG,
- " Phy Down and PORT_NOT_ESTABLISHED\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_NOT_ESTABLISHED\n",
+ phy_id, port_id);
port->port_attached = 0;
break;
case PORT_LOSTCOMM:
- pm8001_dbg(pm8001_ha, MSG, " Phy Down and PORT_LOSTCOMM\n");
- pm8001_dbg(pm8001_ha, MSG,
- " Last phy Down and port invalid\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_LOSTCOMM\n",
+ phy_id, port_id);
+ pm8001_dbg(pm8001_ha, MSG, " Last phy Down and port invalid\n");
if (port_sata) {
port->port_attached = 0;
phy->phy_type = 0;
@@ -3328,9 +3335,9 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
default:
port->port_attached = 0;
- pm8001_dbg(pm8001_ha, DEVIO,
- " Phy Down and(default) = 0x%x\n",
- portstate);
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate:%#x\n",
+ phy_id, port_id, portstate);
break;
}
@@ -3410,6 +3417,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
u8 phy_id =
(u8)((phyid_npip_portstate & 0xFF0000) >> 16);
+ u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
u16 eventType =
(u16)((lr_status_evt_portid & 0x00FFFF00) >> 8);
u8 status =
@@ -3425,26 +3433,29 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
switch (eventType) {
case HW_EVENT_SAS_PHY_UP:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_START_STATUS\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_SAS_PHY_UP phyid:%#x port_id:%#x\n",
+ phy_id, port_id);
hw_event_sas_phy_up(pm8001_ha, piomb);
break;
case HW_EVENT_SATA_PHY_UP:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_PHY_UP\n");
hw_event_sata_phy_up(pm8001_ha, piomb);
break;
case HW_EVENT_SATA_SPINUP_HOLD:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_SATA_SPINUP_HOLD phyid:%#x port_id:%#x\n",
+ phy_id, port_id);
sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD,
GFP_ATOMIC);
break;
case HW_EVENT_PHY_DOWN:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n");
hw_event_phy_down(pm8001_ha, piomb);
- phy->phy_attached = 0;
phy->phy_state = PHY_LINK_DISABLE;
break;
case HW_EVENT_PORT_INVALID:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_PORT_INVALID phyid:%#x port_id:%#x\n",
+ phy_id, port_id);
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR,
@@ -3463,7 +3474,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
GFP_ATOMIC);
break;
case HW_EVENT_PHY_ERROR:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_PHY_ERROR phyid:%#x port_id:%#x\n",
+ phy_id, port_id);
sas_phy_disconnected(&phy->sas_phy);
phy->phy_attached = 0;
sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR, GFP_ATOMIC);
@@ -3477,34 +3490,39 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
GFP_ATOMIC);
break;
case HW_EVENT_LINK_ERR_INVALID_DWORD:
- pm8001_dbg(pm8001_ha, MSG,
- "HW_EVENT_LINK_ERR_INVALID_DWORD\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_LINK_ERR_INVALID_DWORD phyid:%#x port_id:%#x\n",
+ phy_id, port_id);
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0);
break;
case HW_EVENT_LINK_ERR_DISPARITY_ERROR:
- pm8001_dbg(pm8001_ha, MSG,
- "HW_EVENT_LINK_ERR_DISPARITY_ERROR\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_LINK_ERR_DISPARITY_ERROR phyid:%#x port_id:%#x\n",
+ phy_id, port_id);
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_DISPARITY_ERROR,
port_id, phy_id, 0, 0);
break;
case HW_EVENT_LINK_ERR_CODE_VIOLATION:
- pm8001_dbg(pm8001_ha, MSG,
- "HW_EVENT_LINK_ERR_CODE_VIOLATION\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_LINK_ERR_CODE_VIOLATION phyid:%#x port_id:%#x\n",
+ phy_id, port_id);
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_CODE_VIOLATION,
port_id, phy_id, 0, 0);
break;
case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH:
- pm8001_dbg(pm8001_ha, MSG,
- "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH phyid:%#x port_id:%#x\n",
+ phy_id, port_id);
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH,
port_id, phy_id, 0, 0);
break;
case HW_EVENT_MALFUNCTION:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_MALFUNCTION\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_MALFUNCTION phyid:%#x\n", phy_id);
break;
case HW_EVENT_BROADCAST_SES:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_SES\n");
@@ -3515,25 +3533,30 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
GFP_ATOMIC);
break;
case HW_EVENT_INBOUND_CRC_ERROR:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_INBOUND_CRC_ERROR\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_INBOUND_CRC_ERROR phyid:%#x port_id:%#x\n",
+ phy_id, port_id);
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_INBOUND_CRC_ERROR,
port_id, phy_id, 0, 0);
break;
case HW_EVENT_HARD_RESET_RECEIVED:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_HARD_RESET_RECEIVED\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_HARD_RESET_RECEIVED phyid:%#x\n", phy_id);
sas_notify_port_event(sas_phy, PORTE_HARD_RESET, GFP_ATOMIC);
break;
case HW_EVENT_ID_FRAME_TIMEOUT:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_ID_FRAME_TIMEOUT\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_ID_FRAME_TIMEOUT phyid:%#x\n", phy_id);
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR,
GFP_ATOMIC);
break;
case HW_EVENT_LINK_ERR_PHY_RESET_FAILED:
- pm8001_dbg(pm8001_ha, MSG,
- "HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_LINK_ERR_PHY_RESET_FAILED phyid:%#x port_id:%#x\n",
+ phy_id, port_id);
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_PHY_RESET_FAILED,
port_id, phy_id, 0, 0);
@@ -3543,13 +3566,16 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
GFP_ATOMIC);
break;
case HW_EVENT_PORT_RESET_TIMER_TMO:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_TIMER_TMO\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_PORT_RESET_TIMER_TMO phyid:%#x port_id:%#x portstate:%#x\n",
+ phy_id, port_id, portstate);
if (!pm8001_ha->phy[phy_id].reset_completion) {
pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
port_id, phy_id, 0, 0);
}
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
+ port->port_state = portstate;
sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR,
GFP_ATOMIC);
if (pm8001_ha->phy[phy_id].reset_completion) {
@@ -3560,8 +3586,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
}
break;
case HW_EVENT_PORT_RECOVERY_TIMER_TMO:
- pm8001_dbg(pm8001_ha, MSG,
- "HW_EVENT_PORT_RECOVERY_TIMER_TMO\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_PORT_RECOVERY_TIMER_TMO phyid:%#x port_id:%#x\n",
+ phy_id, port_id);
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_PORT_RECOVERY_TIMER_TMO,
port_id, phy_id, 0, 0);
@@ -3575,24 +3602,32 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
}
break;
case HW_EVENT_PORT_RECOVER:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RECOVER\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_PORT_RECOVER phyid:%#x port_id:%#x\n",
+ phy_id, port_id);
hw_event_port_recover(pm8001_ha, piomb);
break;
case HW_EVENT_PORT_RESET_COMPLETE:
- pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_COMPLETE\n");
+ pm8001_dbg(pm8001_ha, EVENT,
+ "HW_EVENT_PORT_RESET_COMPLETE phyid:%#x port_id:%#x portstate:%#x\n",
+ phy_id, port_id, portstate);
if (pm8001_ha->phy[phy_id].reset_completion) {
pm8001_ha->phy[phy_id].port_reset_status =
PORT_RESET_SUCCESS;
complete(pm8001_ha->phy[phy_id].reset_completion);
pm8001_ha->phy[phy_id].reset_completion = NULL;
}
+ phy->phy_attached = 1;
+ phy->phy_state = PHY_STATE_LINK_UP_SPCV;
+ port->port_state = portstate;
break;
case EVENT_BROADCAST_ASYNCH_EVENT:
pm8001_dbg(pm8001_ha, MSG, "EVENT_BROADCAST_ASYNCH_EVENT\n");
break;
default:
- pm8001_dbg(pm8001_ha, DEVIO, "Unknown event type 0x%x\n",
- eventType);
+ pm8001_dbg(pm8001_ha, DEVIO,
+ "Unknown event portid:%d phyid:%d event:0x%x status:0x%x\n",
+ port_id, phy_id, eventType, status);
break;
}
return 0;
@@ -4726,6 +4761,9 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
SAS_ADDR_SIZE);
+ pm8001_dbg(pm8001_ha, INIT,
+ "register device req phy_id 0x%x port_id 0x%x\n", phy_id,
+ (port->port_id & 0xFF));
rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
sizeof(payload), 0);
if (rc)
@@ -4815,7 +4853,7 @@ static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
payload.tag = cpu_to_le32(tag);
payload.ppc_phyid =
cpu_to_le32(((operation & 0xF) << 8) | (phyid & 0xFF));
- pm8001_dbg(pm8001_ha, INIT,
+ pm8001_dbg(pm8001_ha, DISC,
" phy profile command for phy %x ,length is %d\n",
le32_to_cpu(payload.ppc_phyid), length);
for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) {
diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index 3b64de81ea0d..2a31ddc99dde 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -3041,9 +3041,8 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
* addresses of our queues
*/
if (!qedf->p_cpuq) {
- status = -EINVAL;
QEDF_ERR(&qedf->dbg_ctx, "p_cpuq is NULL.\n");
- goto mem_alloc_failure;
+ return -EINVAL;
}
qedf->global_queues = kzalloc((sizeof(struct global_queue *)
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index 802c373fd6d9..a584708d3056 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config SCSI_QLA_FC
tristate "QLogic QLA2XXX Fibre Channel Support"
- depends on PCI && SCSI
+ depends on PCI && HAS_IOPORT && SCSI
depends on SCSI_FC_ATTRS
depends on NVME_FC || !NVME_FC
select FW_LOADER
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 70cfc94c3d43..b00222459607 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -2750,6 +2750,7 @@ static void
qla2x00_terminate_rport_io(struct fc_rport *rport)
{
fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
+ scsi_qla_host_t *vha;
if (!fcport)
return;
@@ -2759,9 +2760,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
return;
+ vha = fcport->vha;
if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
+ qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24,
+ 0, WAIT_TARGET);
return;
}
/*
@@ -2786,6 +2790,15 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
qla2x00_port_logout(fcport->vha, fcport);
}
}
+
+ /* check for any straggling io left behind */
+ if (qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 0, WAIT_TARGET)) {
+ ql_log(ql_log_warn, vha, 0x300b,
+ "IO not return. Resetting. \n");
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ qla2x00_wait_for_chip_reset(vha);
+ }
}
static int
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index dba7bba788d7..19bb64bdd88b 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -283,6 +283,10 @@ qla2x00_process_els(struct bsg_job *bsg_job)
if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
rport = fc_bsg_to_rport(bsg_job);
+ if (!rport) {
+ rval = -ENOMEM;
+ goto done;
+ }
fcport = *(fc_port_t **) rport->dd_data;
host = rport_to_shost(rport);
vha = shost_priv(host);
@@ -2992,6 +2996,8 @@ qla24xx_bsg_request(struct bsg_job *bsg_job)
if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
rport = fc_bsg_to_rport(bsg_job);
+ if (!rport)
+ return ret;
host = rport_to_shost(rport);
vha = shost_priv(host);
} else {
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 84aa3571be6d..d44c4d37b50b 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -465,6 +465,15 @@ static inline be_id_t port_id_to_be_id(port_id_t port_id)
return res;
}
+struct tmf_arg {
+ struct qla_qpair *qpair;
+ struct fc_port *fcport;
+ struct scsi_qla_host *vha;
+ u64 lun;
+ u32 flags;
+ uint8_t modifier;
+};
+
struct els_logo_payload {
uint8_t opcode;
uint8_t rsvd[3];
@@ -544,6 +553,10 @@ struct srb_iocb {
uint32_t data;
struct completion comp;
__le16 comp_status;
+
+ uint8_t modifier;
+ uint8_t vp_index;
+ uint16_t loop_id;
} tmf;
struct {
#define SRB_FXDISC_REQ_DMA_VALID BIT_0
@@ -647,6 +660,7 @@ struct srb_iocb {
#define SRB_SA_UPDATE 25
#define SRB_ELS_CMD_HST_NOLOGIN 26
#define SRB_SA_REPLACE 27
+#define SRB_MARKER 28
struct qla_els_pt_arg {
u8 els_opcode;
@@ -689,7 +703,6 @@ typedef struct srb {
struct iocb_resource iores;
struct kref cmd_kref; /* need to migrate ref_count over to this */
void *priv;
- wait_queue_head_t nvme_ls_waitq;
struct fc_port *fcport;
struct scsi_qla_host *vha;
unsigned int start_timer:1;
@@ -2528,6 +2541,7 @@ enum rscn_addr_format {
typedef struct fc_port {
struct list_head list;
struct scsi_qla_host *vha;
+ struct list_head tmf_pending;
unsigned int conf_compl_supported:1;
unsigned int deleted:2;
@@ -2548,6 +2562,8 @@ typedef struct fc_port {
unsigned int do_prli_nvme:1;
uint8_t nvme_flag;
+ uint8_t active_tmf;
+#define MAX_ACTIVE_TMF 8
uint8_t node_name[WWN_SIZE];
uint8_t port_name[WWN_SIZE];
@@ -3157,12 +3173,12 @@ struct ct_sns_gpnft_rsp {
uint8_t vendor_unique;
};
/* Assume the largest number of targets for the union */
- struct ct_sns_gpn_ft_data {
+ DECLARE_FLEX_ARRAY(struct ct_sns_gpn_ft_data {
u8 control_byte;
u8 port_id[3];
u32 reserved;
u8 port_name[8];
- } entries[1];
+ }, entries);
};
/* CT command response */
@@ -5499,4 +5515,8 @@ struct ql_vnd_tgt_stats_resp {
_fp->disc_state, _fp->scan_state, _fp->loop_id, _fp->deleted, \
_fp->flags
+#define TMF_NOT_READY(_fcport) \
+ (!_fcport || IS_SESSION_DELETED(_fcport) || atomic_read(&_fcport->state) != FCS_ONLINE || \
+ !_fcport->vha->hw->flags.fw_started)
+
#endif
diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
index ec0e20255bd3..26e6b3e3af43 100644
--- a/drivers/scsi/qla2xxx/qla_edif.c
+++ b/drivers/scsi/qla2xxx/qla_edif.c
@@ -2361,8 +2361,8 @@ qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e)
if (!sa_ctl) {
ql_dbg(ql_dbg_edif, vha, 0x70e6,
"sa_ctl allocation failed\n");
- rval = -ENOMEM;
- goto done;
+ rval = -ENOMEM;
+ return rval;
}
fcport = sa_ctl->fcport;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 391c8b3623a6..ba7831f24734 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -69,7 +69,7 @@ extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *);
extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
-extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t);
+extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint64_t, uint32_t);
struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *,
enum qla_work_type);
extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 4738f8935f7f..1cf9d200d563 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3776,8 +3776,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;
rspsz = sizeof(struct ct_sns_gpnft_rsp) +
- ((vha->hw->max_fibre_devices - 1) *
- sizeof(struct ct_sns_gpn_ft_data));
+ vha->hw->max_fibre_devices *
+ sizeof(struct ct_sns_gpn_ft_data);
sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
rspsz,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 1a955c3ff3d6..c3dd8dd4f734 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1996,6 +1996,11 @@ qla2x00_tmf_iocb_timeout(void *data)
int rc, h;
unsigned long flags;
+ if (sp->type == SRB_MARKER) {
+ complete(&tmf->u.tmf.comp);
+ return;
+ }
+
rc = qla24xx_async_abort_cmd(sp, false);
if (rc) {
spin_lock_irqsave(sp->qpair->qp_lock_ptr, flags);
@@ -2013,24 +2018,131 @@ qla2x00_tmf_iocb_timeout(void *data)
}
}
+static void qla_marker_sp_done(srb_t *sp, int res)
+{
+ struct srb_iocb *tmf = &sp->u.iocb_cmd;
+
+ if (res != QLA_SUCCESS)
+ ql_dbg(ql_dbg_taskm, sp->vha, 0x8004,
+ "Async-marker fail hdl=%x portid=%06x ctrl=%x lun=%lld qp=%d.\n",
+ sp->handle, sp->fcport->d_id.b24, sp->u.iocb_cmd.u.tmf.flags,
+ sp->u.iocb_cmd.u.tmf.lun, sp->qpair->id);
+
+ sp->u.iocb_cmd.u.tmf.data = res;
+ complete(&tmf->u.tmf.comp);
+}
+
+#define START_SP_W_RETRIES(_sp, _rval) \
+{\
+ int cnt = 5; \
+ do { \
+ _rval = qla2x00_start_sp(_sp); \
+ if (_rval == EAGAIN) \
+ msleep(1); \
+ else \
+ break; \
+ cnt--; \
+ } while (cnt); \
+}
+
+/**
+ * qla26xx_marker: send marker IOCB and wait for the completion of it.
+ * @arg: pointer to argument list.
+ * It is assume caller will provide an fcport pointer and modifier
+ */
+static int
+qla26xx_marker(struct tmf_arg *arg)
+{
+ struct scsi_qla_host *vha = arg->vha;
+ struct srb_iocb *tm_iocb;
+ srb_t *sp;
+ int rval = QLA_FUNCTION_FAILED;
+ fc_port_t *fcport = arg->fcport;
+
+ if (TMF_NOT_READY(arg->fcport)) {
+ ql_dbg(ql_dbg_taskm, vha, 0x8039,
+ "FC port not ready for marker loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n",
+ fcport->loop_id, fcport->d_id.b24,
+ arg->modifier, arg->lun, arg->qpair->id);
+ return QLA_SUSPENDED;
+ }
+
+ /* ref: INIT */
+ sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ sp->type = SRB_MARKER;
+ sp->name = "marker";
+ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha), qla_marker_sp_done);
+ sp->u.iocb_cmd.timeout = qla2x00_tmf_iocb_timeout;
+
+ tm_iocb = &sp->u.iocb_cmd;
+ init_completion(&tm_iocb->u.tmf.comp);
+ tm_iocb->u.tmf.modifier = arg->modifier;
+ tm_iocb->u.tmf.lun = arg->lun;
+ tm_iocb->u.tmf.loop_id = fcport->loop_id;
+ tm_iocb->u.tmf.vp_index = vha->vp_idx;
+
+ START_SP_W_RETRIES(sp, rval);
+
+ ql_dbg(ql_dbg_taskm, vha, 0x8006,
+ "Async-marker hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n",
+ sp->handle, fcport->loop_id, fcport->d_id.b24,
+ arg->modifier, arg->lun, sp->qpair->id, rval);
+
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x8031,
+ "Marker IOCB send failure (%x).\n", rval);
+ goto done_free_sp;
+ }
+
+ wait_for_completion(&tm_iocb->u.tmf.comp);
+ rval = tm_iocb->u.tmf.data;
+
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x8019,
+ "Marker failed hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n",
+ sp->handle, fcport->loop_id, fcport->d_id.b24,
+ arg->modifier, arg->lun, sp->qpair->id, rval);
+ }
+
+done_free_sp:
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+done:
+ return rval;
+}
+
static void qla2x00_tmf_sp_done(srb_t *sp, int res)
{
struct srb_iocb *tmf = &sp->u.iocb_cmd;
+ if (res)
+ tmf->u.tmf.data = res;
complete(&tmf->u.tmf.comp);
}
-int
-qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
- uint32_t tag)
+static int
+__qla2x00_async_tm_cmd(struct tmf_arg *arg)
{
- struct scsi_qla_host *vha = fcport->vha;
+ struct scsi_qla_host *vha = arg->vha;
struct srb_iocb *tm_iocb;
srb_t *sp;
int rval = QLA_FUNCTION_FAILED;
+ fc_port_t *fcport = arg->fcport;
+
+ if (TMF_NOT_READY(arg->fcport)) {
+ ql_dbg(ql_dbg_taskm, vha, 0x8032,
+ "FC port not ready for TM command loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n",
+ fcport->loop_id, fcport->d_id.b24,
+ arg->modifier, arg->lun, arg->qpair->id);
+ return QLA_SUSPENDED;
+ }
+
/* ref: INIT */
- sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL);
if (!sp)
goto done;
@@ -2043,15 +2155,16 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
tm_iocb = &sp->u.iocb_cmd;
init_completion(&tm_iocb->u.tmf.comp);
- tm_iocb->u.tmf.flags = flags;
- tm_iocb->u.tmf.lun = lun;
+ tm_iocb->u.tmf.flags = arg->flags;
+ tm_iocb->u.tmf.lun = arg->lun;
+
+ START_SP_W_RETRIES(sp, rval);
ql_dbg(ql_dbg_taskm, vha, 0x802f,
- "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
- sp->handle, fcport->loop_id, fcport->d_id.b.domain,
- fcport->d_id.b.area, fcport->d_id.b.al_pa);
+ "Async-tmf hdl=%x loop-id=%x portid=%06x ctrl=%x lun=%lld qp=%d rval=%x.\n",
+ sp->handle, fcport->loop_id, fcport->d_id.b24,
+ arg->flags, arg->lun, sp->qpair->id, rval);
- rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS)
goto done_free_sp;
wait_for_completion(&tm_iocb->u.tmf.comp);
@@ -2063,15 +2176,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
"TM IOCB failed (%x).\n", rval);
}
- if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) {
- flags = tm_iocb->u.tmf.flags;
- lun = (uint16_t)tm_iocb->u.tmf.lun;
-
- /* Issue Marker IOCB */
- qla2x00_marker(vha, vha->hw->base_qpair,
- fcport->loop_id, lun,
- flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
- }
+ if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw))
+ rval = qla26xx_marker(arg);
done_free_sp:
/* ref: INIT */
@@ -2080,6 +2186,115 @@ done:
return rval;
}
+static void qla_put_tmf(fc_port_t *fcport)
+{
+ struct scsi_qla_host *vha = fcport->vha;
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ fcport->active_tmf--;
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+}
+
+static
+int qla_get_tmf(fc_port_t *fcport)
+{
+ struct scsi_qla_host *vha = fcport->vha;
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long flags;
+ int rc = 0;
+ LIST_HEAD(tmf_elem);
+
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ list_add_tail(&tmf_elem, &fcport->tmf_pending);
+
+ while (fcport->active_tmf >= MAX_ACTIVE_TMF) {
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+
+ msleep(1);
+
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ if (TMF_NOT_READY(fcport)) {
+ ql_log(ql_log_warn, vha, 0x802c,
+ "Unable to acquire TM resource due to disruption.\n");
+ rc = EIO;
+ break;
+ }
+ if (fcport->active_tmf < MAX_ACTIVE_TMF &&
+ list_is_first(&tmf_elem, &fcport->tmf_pending))
+ break;
+ }
+
+ list_del(&tmf_elem);
+
+ if (!rc)
+ fcport->active_tmf++;
+
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+
+ return rc;
+}
+
+int
+qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
+ uint32_t tag)
+{
+ struct scsi_qla_host *vha = fcport->vha;
+ struct qla_qpair *qpair;
+ struct tmf_arg a;
+ int i, rval = QLA_SUCCESS;
+
+ if (TMF_NOT_READY(fcport))
+ return QLA_SUSPENDED;
+
+ a.vha = fcport->vha;
+ a.fcport = fcport;
+ a.lun = lun;
+ if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) {
+ a.modifier = MK_SYNC_ID_LUN;
+
+ if (qla_get_tmf(fcport))
+ return QLA_FUNCTION_FAILED;
+ } else {
+ a.modifier = MK_SYNC_ID;
+ }
+
+ if (vha->hw->mqenable) {
+ for (i = 0; i < vha->hw->num_qpairs; i++) {
+ qpair = vha->hw->queue_pair_map[i];
+ if (!qpair)
+ continue;
+
+ if (TMF_NOT_READY(fcport)) {
+ ql_log(ql_log_warn, vha, 0x8026,
+ "Unable to send TM due to disruption.\n");
+ rval = QLA_SUSPENDED;
+ break;
+ }
+
+ a.qpair = qpair;
+ a.flags = flags|TCF_NOTMCMD_TO_TARGET;
+ rval = __qla2x00_async_tm_cmd(&a);
+ if (rval)
+ break;
+ }
+ }
+
+ if (rval)
+ goto bailout;
+
+ a.qpair = vha->hw->base_qpair;
+ a.flags = flags;
+ rval = __qla2x00_async_tm_cmd(&a);
+
+bailout:
+ if (a.modifier == MK_SYNC_ID_LUN)
+ qla_put_tmf(fcport);
+
+ return rval;
+}
+
int
qla24xx_async_abort_command(srb_t *sp)
{
@@ -4861,7 +5076,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
if (use_tbl &&
ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES)
- strlcpy(ha->model_desc,
+ strscpy(ha->model_desc,
qla2x00_model_name[index * 2 + 1],
sizeof(ha->model_desc));
} else {
@@ -4869,14 +5084,14 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
if (use_tbl &&
ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES) {
- strlcpy(ha->model_number,
+ strscpy(ha->model_number,
qla2x00_model_name[index * 2],
sizeof(ha->model_number));
- strlcpy(ha->model_desc,
+ strscpy(ha->model_desc,
qla2x00_model_name[index * 2 + 1],
sizeof(ha->model_desc));
} else {
- strlcpy(ha->model_number, def,
+ strscpy(ha->model_number, def,
sizeof(ha->model_number));
}
}
@@ -5291,6 +5506,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
INIT_WORK(&fcport->reg_work, qla_register_fcport_fn);
INIT_LIST_HEAD(&fcport->gnl_entry);
INIT_LIST_HEAD(&fcport->list);
+ INIT_LIST_HEAD(&fcport->tmf_pending);
INIT_LIST_HEAD(&fcport->sess_cmd_list);
spin_lock_init(&fcport->sess_cmd_lock);
@@ -5333,7 +5549,7 @@ static void qla_get_login_template(scsi_qla_host_t *vha)
__be32 *q;
memset(ha->init_cb, 0, ha->init_cb_size);
- sz = min_t(int, sizeof(struct fc_els_flogi), ha->init_cb_size);
+ sz = min_t(int, sizeof(struct fc_els_csp), ha->init_cb_size);
rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma,
ha->init_cb, sz);
if (rval != QLA_SUCCESS) {
@@ -6004,7 +6220,6 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
fc_port_t *fcport;
uint16_t mb[MAILBOX_REGISTER_COUNT];
uint16_t loop_id;
- LIST_HEAD(new_fcports);
struct qla_hw_data *ha = vha->hw;
int discovery_gen;
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 7b42558a8839..0167e85ba058 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -109,11 +109,13 @@ qla2x00_set_fcport_disc_state(fc_port_t *fcport, int state)
{
int old_val;
uint8_t shiftbits, mask;
+ uint8_t port_dstate_str_sz;
/* This will have to change when the max no. of states > 16 */
shiftbits = 4;
mask = (1 << shiftbits) - 1;
+ port_dstate_str_sz = sizeof(port_dstate_str) / sizeof(char *);
fcport->disc_state = state;
while (1) {
old_val = atomic_read(&fcport->shadow_disc_state);
@@ -121,7 +123,8 @@ qla2x00_set_fcport_disc_state(fc_port_t *fcport, int state)
old_val, (old_val << shiftbits) | state)) {
ql_dbg(ql_dbg_disc, fcport->vha, 0x2134,
"FCPort %8phC disc_state transition: %s to %s - portid=%06x.\n",
- fcport->port_name, port_dstate_str[old_val & mask],
+ fcport->port_name, (old_val & mask) < port_dstate_str_sz ?
+ port_dstate_str[old_val & mask] : "Unknown",
port_dstate_str[state], fcport->d_id.b24);
return;
}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index b9b3e6f80ea9..a1675f056a5c 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -522,21 +522,25 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair,
return (QLA_FUNCTION_FAILED);
}
+ mrk24 = (struct mrk_entry_24xx *)mrk;
+
mrk->entry_type = MARKER_TYPE;
mrk->modifier = type;
if (type != MK_SYNC_ALL) {
if (IS_FWI2_CAPABLE(ha)) {
- mrk24 = (struct mrk_entry_24xx *) mrk;
mrk24->nport_handle = cpu_to_le16(loop_id);
int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun);
host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun));
mrk24->vp_index = vha->vp_idx;
- mrk24->handle = make_handle(req->id, mrk24->handle);
} else {
SET_TARGET_ID(ha, mrk->target, loop_id);
mrk->lun = cpu_to_le16((uint16_t)lun);
}
}
+
+ if (IS_FWI2_CAPABLE(ha))
+ mrk24->handle = QLA_SKIP_HANDLE;
+
wmb();
qla2x00_start_iocbs(vha, req);
@@ -603,7 +607,8 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
put_unaligned_le32(COMMAND_TYPE_6, &cmd_pkt->entry_type);
/* No data transfer */
- if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
+ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE ||
+ tot_dsds == 0) {
cmd_pkt->byte_count = cpu_to_le32(0);
return 0;
}
@@ -2541,7 +2546,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
scsi_qla_host_t *vha = fcport->vha;
struct qla_hw_data *ha = vha->hw;
struct srb_iocb *iocb = &sp->u.iocb_cmd;
- struct req_que *req = vha->req;
+ struct req_que *req = sp->qpair->req;
flags = iocb->u.tmf.flags;
lun = iocb->u.tmf.lun;
@@ -2557,7 +2562,8 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
tsk->port_id[2] = fcport->d_id.b.domain;
tsk->vp_index = fcport->vha->vp_idx;
- if (flags == TCF_LUN_RESET) {
+ if (flags & (TCF_LUN_RESET | TCF_ABORT_TASK_SET|
+ TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) {
int_to_scsilun(lun, &tsk->lun);
host_to_fcp_swap((uint8_t *)&tsk->lun,
sizeof(tsk->lun));
@@ -3852,9 +3858,9 @@ static int qla_get_iocbs_resource(struct srb *sp)
case SRB_NACK_LOGO:
case SRB_LOGOUT_CMD:
case SRB_CTRL_VP:
- push_it_through = true;
- fallthrough;
+ case SRB_MARKER:
default:
+ push_it_through = true;
get_exch = false;
}
@@ -3870,6 +3876,19 @@ static int qla_get_iocbs_resource(struct srb *sp)
return qla_get_fw_resources(sp->qpair, &sp->iores);
}
+static void
+qla_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk)
+{
+ mrk->entry_type = MARKER_TYPE;
+ mrk->modifier = sp->u.iocb_cmd.u.tmf.modifier;
+ if (sp->u.iocb_cmd.u.tmf.modifier != MK_SYNC_ALL) {
+ mrk->nport_handle = cpu_to_le16(sp->u.iocb_cmd.u.tmf.loop_id);
+ int_to_scsilun(sp->u.iocb_cmd.u.tmf.lun, (struct scsi_lun *)&mrk->lun);
+ host_to_fcp_swap(mrk->lun, sizeof(mrk->lun));
+ mrk->vp_index = sp->u.iocb_cmd.u.tmf.vp_index;
+ }
+}
+
int
qla2x00_start_sp(srb_t *sp)
{
@@ -3973,6 +3992,9 @@ qla2x00_start_sp(srb_t *sp)
case SRB_SA_REPLACE:
qla24xx_sa_replace_iocb(sp, pkt);
break;
+ case SRB_MARKER:
+ qla_marker_iocb(sp, pkt);
+ break;
default:
break;
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 245e3a5d81fd..656700f79325 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1862,9 +1862,9 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
}
}
-srb_t *
-qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
- struct req_que *req, void *iocb)
+static srb_t *
+qla_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
+ struct req_que *req, void *iocb, u16 *ret_index)
{
struct qla_hw_data *ha = vha->hw;
sts_entry_t *pkt = iocb;
@@ -1899,12 +1899,25 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
return NULL;
}
- req->outstanding_cmds[index] = NULL;
-
+ *ret_index = index;
qla_put_fw_resources(sp->qpair, &sp->iores);
return sp;
}
+srb_t *
+qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
+ struct req_que *req, void *iocb)
+{
+ uint16_t index;
+ srb_t *sp;
+
+ sp = qla_get_sp_from_handle(vha, func, req, iocb, &index);
+ if (sp)
+ req->outstanding_cmds[index] = NULL;
+
+ return sp;
+}
+
static void
qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
struct mbx_entry *mbx)
@@ -3237,13 +3250,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
return;
}
- req->outstanding_cmds[handle] = NULL;
cp = GET_CMD_SP(sp);
if (cp == NULL) {
ql_dbg(ql_dbg_io, vha, 0x3018,
"Command already returned (0x%x/%p).\n",
sts->handle, sp);
+ req->outstanding_cmds[handle] = NULL;
return;
}
@@ -3514,6 +3527,9 @@ out:
if (rsp->status_srb == NULL)
sp->done(sp, res);
+
+ /* for io's, clearing of outstanding_cmds[handle] means scsi_done was called */
+ req->outstanding_cmds[handle] = NULL;
}
/**
@@ -3590,6 +3606,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
uint16_t que = MSW(pkt->handle);
struct req_que *req = NULL;
int res = DID_ERROR << 16;
+ u16 index;
ql_dbg(ql_dbg_async, vha, 0x502a,
"iocb type %xh with error status %xh, handle %xh, rspq id %d\n",
@@ -3608,7 +3625,6 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
switch (pkt->entry_type) {
case NOTIFY_ACK_TYPE:
- case STATUS_TYPE:
case STATUS_CONT_TYPE:
case LOGINOUT_PORT_IOCB_TYPE:
case CT_IOCB_TYPE:
@@ -3628,6 +3644,14 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
case CTIO_TYPE7:
case CTIO_CRC2:
return 1;
+ case STATUS_TYPE:
+ sp = qla_get_sp_from_handle(vha, func, req, pkt, &index);
+ if (sp) {
+ sp->done(sp, res);
+ req->outstanding_cmds[index] = NULL;
+ return 0;
+ }
+ break;
}
fatal:
ql_log(ql_log_warn, vha, 0x5030,
@@ -3750,6 +3774,28 @@ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
return rc;
}
+static void qla_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
+ struct mrk_entry_24xx *pkt)
+{
+ const char func[] = "MRK-IOCB";
+ srb_t *sp;
+ int res = QLA_SUCCESS;
+
+ if (!IS_FWI2_CAPABLE(vha->hw))
+ return;
+
+ sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
+ if (!sp)
+ return;
+
+ if (pkt->entry_status) {
+ ql_dbg(ql_dbg_taskm, vha, 0x8025, "marker failure.\n");
+ res = QLA_COMMAND_ERROR;
+ }
+ sp->u.iocb_cmd.u.tmf.data = res;
+ sp->done(sp, res);
+}
+
/**
* qla24xx_process_response_queue() - Process response queue entries.
* @vha: SCSI driver HA context
@@ -3866,9 +3912,7 @@ process_err:
(struct nack_to_isp *)pkt);
break;
case MARKER_TYPE:
- /* Do nothing in this case, this check is to prevent it
- * from falling into default case
- */
+ qla_marker_iocb_entry(vha, rsp->req, (struct mrk_entry_24xx *)pkt);
break;
case ABORT_IOCB_TYPE:
qla24xx_abort_iocb_entry(vha, rsp->req,
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index f726eb8449c5..083f94e43fba 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -691,7 +691,7 @@ qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len)
struct qla_hw_data *ha = vha->hw;
if (pci_is_pcie(ha->pdev))
- strlcpy(str, "PCIe iSA", str_len);
+ strscpy(str, "PCIe iSA", str_len);
return str;
}
@@ -1850,21 +1850,21 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
phost_info = &preg_hsi->hsi;
memset(preg_hsi, 0, sizeof(struct register_host_info));
phost_info->os_type = OS_TYPE_LINUX;
- strlcpy(phost_info->sysname, p_sysid->sysname,
+ strscpy(phost_info->sysname, p_sysid->sysname,
sizeof(phost_info->sysname));
- strlcpy(phost_info->nodename, p_sysid->nodename,
+ strscpy(phost_info->nodename, p_sysid->nodename,
sizeof(phost_info->nodename));
if (!strcmp(phost_info->nodename, "(none)"))
ha->mr.host_info_resend = true;
- strlcpy(phost_info->release, p_sysid->release,
+ strscpy(phost_info->release, p_sysid->release,
sizeof(phost_info->release));
- strlcpy(phost_info->version, p_sysid->version,
+ strscpy(phost_info->version, p_sysid->version,
sizeof(phost_info->version));
- strlcpy(phost_info->machine, p_sysid->machine,
+ strscpy(phost_info->machine, p_sysid->machine,
sizeof(phost_info->machine));
- strlcpy(phost_info->domainname, p_sysid->domainname,
+ strscpy(phost_info->domainname, p_sysid->domainname,
sizeof(phost_info->domainname));
- strlcpy(phost_info->hostdriver, QLA2XXX_VERSION,
+ strscpy(phost_info->hostdriver, QLA2XXX_VERSION,
sizeof(phost_info->hostdriver));
preg_hsi->utc = (uint64_t)ktime_get_real_seconds();
ql_dbg(ql_dbg_init, vha, 0x0149,
@@ -1909,9 +1909,9 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
if (fx_type == FXDISC_GET_CONFIG_INFO) {
struct config_info_data *pinfo =
(struct config_info_data *) fdisc->u.fxiocb.rsp_addr;
- strlcpy(vha->hw->model_number, pinfo->model_num,
+ strscpy(vha->hw->model_number, pinfo->model_num,
ARRAY_SIZE(vha->hw->model_number));
- strlcpy(vha->hw->model_desc, pinfo->model_description,
+ strscpy(vha->hw->model_desc, pinfo->model_description,
ARRAY_SIZE(vha->hw->model_desc));
memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name,
sizeof(vha->hw->mr.symbolic_name));
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
index 648e8f798606..86e85f2f4782 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -360,7 +360,6 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x700e,
"qla2x00_start_sp failed = %d\n", rval);
- wake_up(&sp->nvme_ls_waitq);
sp->priv = NULL;
priv->sp = NULL;
qla2x00_rel_sp(sp);
@@ -652,7 +651,6 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,
if (!sp)
return -EBUSY;
- init_waitqueue_head(&sp->nvme_ls_waitq);
kref_init(&sp->cmd_kref);
spin_lock_init(&priv->cmd_lock);
sp->priv = priv;
@@ -671,7 +669,6 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x212d,
"qla2x00_start_nvme_mq failed = %d\n", rval);
- wake_up(&sp->nvme_ls_waitq);
sp->priv = NULL;
priv->sp = NULL;
qla2xxx_rel_qpair_sp(sp->qpair, sp);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 2fa695bf38b7..877e4f446709 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1079,43 +1079,6 @@ qc24_fail_command:
}
/*
- * qla2x00_eh_wait_on_command
- * Waits for the command to be returned by the Firmware for some
- * max time.
- *
- * Input:
- * cmd = Scsi Command to wait on.
- *
- * Return:
- * Completed in time : QLA_SUCCESS
- * Did not complete in time : QLA_FUNCTION_FAILED
- */
-static int
-qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
-{
-#define ABORT_POLLING_PERIOD 1000
-#define ABORT_WAIT_ITER ((2 * 1000) / (ABORT_POLLING_PERIOD))
- unsigned long wait_iter = ABORT_WAIT_ITER;
- scsi_qla_host_t *vha = shost_priv(cmd->device->host);
- struct qla_hw_data *ha = vha->hw;
- srb_t *sp = scsi_cmd_priv(cmd);
- int ret = QLA_SUCCESS;
-
- if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) {
- ql_dbg(ql_dbg_taskm, vha, 0x8005,
- "Return:eh_wait.\n");
- return ret;
- }
-
- while (sp->type && wait_iter--)
- msleep(ABORT_POLLING_PERIOD);
- if (sp->type)
- ret = QLA_FUNCTION_FAILED;
-
- return ret;
-}
-
-/*
* qla2x00_wait_for_hba_online
* Wait till the HBA is online after going through
* <= MAX_RETRIES_OF_ISP_ABORT or
@@ -1365,6 +1328,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
return ret;
}
+#define ABORT_POLLING_PERIOD 1000
+#define ABORT_WAIT_ITER ((2 * 1000) / (ABORT_POLLING_PERIOD))
+
/*
* Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED.
*/
@@ -1378,41 +1344,73 @@ __qla2x00_eh_wait_for_pending_commands(struct qla_qpair *qpair, unsigned int t,
struct req_que *req = qpair->req;
srb_t *sp;
struct scsi_cmnd *cmd;
+ unsigned long wait_iter = ABORT_WAIT_ITER;
+ bool found;
+ struct qla_hw_data *ha = vha->hw;
status = QLA_SUCCESS;
- spin_lock_irqsave(qpair->qp_lock_ptr, flags);
- for (cnt = 1; status == QLA_SUCCESS &&
- cnt < req->num_outstanding_cmds; cnt++) {
- sp = req->outstanding_cmds[cnt];
- if (!sp)
- continue;
- if (sp->type != SRB_SCSI_CMD)
- continue;
- if (vha->vp_idx != sp->vha->vp_idx)
- continue;
- match = 0;
- cmd = GET_CMD_SP(sp);
- switch (type) {
- case WAIT_HOST:
- match = 1;
- break;
- case WAIT_TARGET:
- match = cmd->device->id == t;
- break;
- case WAIT_LUN:
- match = (cmd->device->id == t &&
- cmd->device->lun == l);
- break;
- }
- if (!match)
- continue;
+ while (wait_iter--) {
+ found = false;
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
- status = qla2x00_eh_wait_on_command(cmd);
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+ for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
+ sp = req->outstanding_cmds[cnt];
+ if (!sp)
+ continue;
+ if (sp->type != SRB_SCSI_CMD)
+ continue;
+ if (vha->vp_idx != sp->vha->vp_idx)
+ continue;
+ match = 0;
+ cmd = GET_CMD_SP(sp);
+ switch (type) {
+ case WAIT_HOST:
+ match = 1;
+ break;
+ case WAIT_TARGET:
+ if (sp->fcport)
+ match = sp->fcport->d_id.b24 == t;
+ else
+ match = 0;
+ break;
+ case WAIT_LUN:
+ if (sp->fcport)
+ match = (sp->fcport->d_id.b24 == t &&
+ cmd->device->lun == l);
+ else
+ match = 0;
+ break;
+ }
+ if (!match)
+ continue;
+
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+
+ if (unlikely(pci_channel_offline(ha->pdev)) ||
+ ha->flags.eeh_busy) {
+ ql_dbg(ql_dbg_taskm, vha, 0x8005,
+ "Return:eh_wait.\n");
+ return status;
+ }
+
+ /*
+ * SRB_SCSI_CMD is still in the outstanding_cmds array.
+ * it means scsi_done has not called. Wait for it to
+ * clear from outstanding_cmds.
+ */
+ msleep(ABORT_POLLING_PERIOD);
+ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+ found = true;
+ }
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+
+ if (!found)
+ break;
}
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+
+ if (wait_iter == -1)
+ status = QLA_FUNCTION_FAILED;
return status;
}
@@ -5090,7 +5088,8 @@ struct scsi_qla_host *qla2x00_create_host(const struct scsi_host_template *sht,
}
INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn);
- sprintf(vha->host_str, "%s_%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
+ snprintf(vha->host_str, sizeof(vha->host_str), "%s_%lu",
+ QLA2XXX_DRIVER_NAME, vha->host_no);
ql_dbg(ql_dbg_init, vha, 0x0041,
"Allocated the host=%p hw=%p vha=%p dev_name=%s",
vha->host, vha->hw, vha,
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 42d69d89834f..e3771923b0d7 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -6,9 +6,9 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "10.02.08.200-k"
+#define QLA2XXX_VERSION "10.02.08.400-k"
#define QLA_DRIVER_MAJOR_VER 10
#define QLA_DRIVER_MINOR_VER 2
#define QLA_DRIVER_PATCH_VER 8
-#define QLA_DRIVER_BETA_VER 200
+#define QLA_DRIVER_BETA_VER 400
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index cd71074f3abe..249f1d7021d4 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -1611,8 +1611,8 @@ int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
goto exit_get_chap;
}
- strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
- strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
+ strscpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
+ strscpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
chap_table->cookie = cpu_to_le16(CHAP_VALID_COOKIE);
exit_get_chap:
@@ -1732,8 +1732,8 @@ int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username,
goto exit_unlock_uni_chap;
}
- strlcpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN);
- strlcpy(username, chap_table->name, MAX_CHAP_NAME_LEN);
+ strscpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN);
+ strscpy(username, chap_table->name, MAX_CHAP_NAME_LEN);
rval = QLA_SUCCESS;
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index ee6d784c095c..b2a3988e1e15 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -798,9 +798,9 @@ static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx,
continue;
chap_rec->chap_tbl_idx = i;
- strlcpy(chap_rec->username, chap_table->name,
+ strscpy(chap_rec->username, chap_table->name,
ISCSI_CHAP_AUTH_NAME_MAX_LEN);
- strlcpy(chap_rec->password, chap_table->secret,
+ strscpy(chap_rec->password, chap_table->secret,
QL4_CHAP_MAX_SECRET_LEN);
chap_rec->password_length = chap_table->secret_len;
@@ -6052,8 +6052,8 @@ static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username,
if (!(chap_table->flags & BIT_6)) /* Not BIDI */
continue;
- strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
- strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
+ strscpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
+ strscpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
ret = 0;
break;
}
@@ -6281,8 +6281,8 @@ static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry,
tddb->tpgt = sess->tpgt;
tddb->port = conn->persistent_port;
- strlcpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE);
- strlcpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN);
+ strscpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE);
+ strscpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN);
}
static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry,
@@ -7781,7 +7781,7 @@ static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess,
goto exit_ddb_logout;
}
- strlcpy(flash_tddb->iscsi_name, fnode_sess->targetname,
+ strscpy(flash_tddb->iscsi_name, fnode_sess->targetname,
ISCSI_NAME_SIZE);
if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 09ef0b31dfc0..c4bf99a842f3 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -504,18 +504,22 @@ void scsi_attach_vpd(struct scsi_device *sdev)
}
/**
- * scsi_report_opcode - Find out if a given command opcode is supported
+ * scsi_report_opcode - Find out if a given command is supported
* @sdev: scsi device to query
* @buffer: scratch buffer (must be at least 20 bytes long)
* @len: length of buffer
- * @opcode: opcode for command to look up
- *
- * Uses the REPORT SUPPORTED OPERATION CODES to look up the given
- * opcode. Returns -EINVAL if RSOC fails, 0 if the command opcode is
- * unsupported and 1 if the device claims to support the command.
+ * @opcode: opcode for the command to look up
+ * @sa: service action for the command to look up
+ *
+ * Uses the REPORT SUPPORTED OPERATION CODES to check support for the
+ * command identified with @opcode and @sa. If the command does not
+ * have a service action, @sa must be 0. Returns -EINVAL if RSOC fails,
+ * 0 if the command is not supported and 1 if the device claims to
+ * support the command.
*/
int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
- unsigned int len, unsigned char opcode)
+ unsigned int len, unsigned char opcode,
+ unsigned short sa)
{
unsigned char cmd[16];
struct scsi_sense_hdr sshdr;
@@ -539,8 +543,14 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
memset(cmd, 0, 16);
cmd[0] = MAINTENANCE_IN;
cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES;
- cmd[2] = 1; /* One command format */
- cmd[3] = opcode;
+ if (!sa) {
+ cmd[2] = 1; /* One command format */
+ cmd[3] = opcode;
+ } else {
+ cmd[2] = 3; /* One command format with service action */
+ cmd[3] = opcode;
+ put_unaligned_be16(sa, &cmd[4]);
+ }
put_unaligned_be32(request_len, &cmd[6]);
memset(buffer, 0, len);
@@ -560,6 +570,149 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
}
EXPORT_SYMBOL(scsi_report_opcode);
+#define SCSI_CDL_CHECK_BUF_LEN 64
+
+static bool scsi_cdl_check_cmd(struct scsi_device *sdev, u8 opcode, u16 sa,
+ unsigned char *buf)
+{
+ int ret;
+ u8 cdlp;
+
+ /* Check operation code */
+ ret = scsi_report_opcode(sdev, buf, SCSI_CDL_CHECK_BUF_LEN, opcode, sa);
+ if (ret <= 0)
+ return false;
+
+ if ((buf[1] & 0x03) != 0x03)
+ return false;
+
+ /* See SPC-6, one command format of REPORT SUPPORTED OPERATION CODES */
+ cdlp = (buf[1] & 0x18) >> 3;
+ if (buf[0] & 0x01) {
+ /* rwcdlp == 1 */
+ switch (cdlp) {
+ case 0x01:
+ /* T2A page */
+ return true;
+ case 0x02:
+ /* T2B page */
+ return true;
+ }
+ } else {
+ /* rwcdlp == 0 */
+ switch (cdlp) {
+ case 0x01:
+ /* A page */
+ return true;
+ case 0x02:
+ /* B page */
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * scsi_cdl_check - Check if a SCSI device supports Command Duration Limits
+ * @sdev: The device to check
+ */
+void scsi_cdl_check(struct scsi_device *sdev)
+{
+ bool cdl_supported;
+ unsigned char *buf;
+
+ buf = kmalloc(SCSI_CDL_CHECK_BUF_LEN, GFP_KERNEL);
+ if (!buf) {
+ sdev->cdl_supported = 0;
+ return;
+ }
+
+ /* Check support for READ_16, WRITE_16, READ_32 and WRITE_32 commands */
+ cdl_supported =
+ scsi_cdl_check_cmd(sdev, READ_16, 0, buf) ||
+ scsi_cdl_check_cmd(sdev, WRITE_16, 0, buf) ||
+ scsi_cdl_check_cmd(sdev, VARIABLE_LENGTH_CMD, READ_32, buf) ||
+ scsi_cdl_check_cmd(sdev, VARIABLE_LENGTH_CMD, WRITE_32, buf);
+ if (cdl_supported) {
+ /*
+ * We have CDL support: force the use of READ16/WRITE16.
+ * READ32 and WRITE32 will be used for devices that support
+ * the T10_PI_TYPE2_PROTECTION protection type.
+ */
+ sdev->use_16_for_rw = 1;
+ sdev->use_10_for_rw = 0;
+
+ sdev->cdl_supported = 1;
+ } else {
+ sdev->cdl_supported = 0;
+ }
+
+ kfree(buf);
+}
+
+/**
+ * scsi_cdl_enable - Enable or disable a SCSI device supports for Command
+ * Duration Limits
+ * @sdev: The target device
+ * @enable: the target state
+ */
+int scsi_cdl_enable(struct scsi_device *sdev, bool enable)
+{
+ struct scsi_mode_data data;
+ struct scsi_sense_hdr sshdr;
+ struct scsi_vpd *vpd;
+ bool is_ata = false;
+ char buf[64];
+ int ret;
+
+ if (!sdev->cdl_supported)
+ return -EOPNOTSUPP;
+
+ rcu_read_lock();
+ vpd = rcu_dereference(sdev->vpd_pg89);
+ if (vpd)
+ is_ata = true;
+ rcu_read_unlock();
+
+ /*
+ * For ATA devices, CDL needs to be enabled with a SET FEATURES command.
+ */
+ if (is_ata) {
+ char *buf_data;
+ int len;
+
+ ret = scsi_mode_sense(sdev, 0x08, 0x0a, 0xf2, buf, sizeof(buf),
+ 5 * HZ, 3, &data, NULL);
+ if (ret)
+ return -EINVAL;
+
+ /* Enable CDL using the ATA feature page */
+ len = min_t(size_t, sizeof(buf),
+ data.length - data.header_length -
+ data.block_descriptor_length);
+ buf_data = buf + data.header_length +
+ data.block_descriptor_length;
+ if (enable)
+ buf_data[4] = 0x02;
+ else
+ buf_data[4] = 0;
+
+ ret = scsi_mode_select(sdev, 1, 0, buf_data, len, 5 * HZ, 3,
+ &data, &sshdr);
+ if (ret) {
+ if (scsi_sense_valid(&sshdr))
+ scsi_print_sense_hdr(sdev,
+ dev_name(&sdev->sdev_gendev), &sshdr);
+ return ret;
+ }
+ }
+
+ sdev->cdl_enable = enable;
+
+ return 0;
+}
+
/**
* scsi_device_get - get an additional reference to a scsi_device
* @sdev: device to get a reference to
diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c
index 6e50e81a8216..9c14fdf61037 100644
--- a/drivers/scsi/scsi_common.c
+++ b/drivers/scsi/scsi_common.c
@@ -8,6 +8,7 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/module.h>
+#include <uapi/linux/pr.h>
#include <asm/unaligned.h>
#include <scsi/scsi_common.h>
@@ -63,6 +64,48 @@ const char *scsi_device_type(unsigned type)
}
EXPORT_SYMBOL(scsi_device_type);
+enum pr_type scsi_pr_type_to_block(enum scsi_pr_type type)
+{
+ switch (type) {
+ case SCSI_PR_WRITE_EXCLUSIVE:
+ return PR_WRITE_EXCLUSIVE;
+ case SCSI_PR_EXCLUSIVE_ACCESS:
+ return PR_EXCLUSIVE_ACCESS;
+ case SCSI_PR_WRITE_EXCLUSIVE_REG_ONLY:
+ return PR_WRITE_EXCLUSIVE_REG_ONLY;
+ case SCSI_PR_EXCLUSIVE_ACCESS_REG_ONLY:
+ return PR_EXCLUSIVE_ACCESS_REG_ONLY;
+ case SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS:
+ return PR_WRITE_EXCLUSIVE_ALL_REGS;
+ case SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS:
+ return PR_EXCLUSIVE_ACCESS_ALL_REGS;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_pr_type_to_block);
+
+enum scsi_pr_type block_pr_type_to_scsi(enum pr_type type)
+{
+ switch (type) {
+ case PR_WRITE_EXCLUSIVE:
+ return SCSI_PR_WRITE_EXCLUSIVE;
+ case PR_EXCLUSIVE_ACCESS:
+ return SCSI_PR_EXCLUSIVE_ACCESS;
+ case PR_WRITE_EXCLUSIVE_REG_ONLY:
+ return SCSI_PR_WRITE_EXCLUSIVE_REG_ONLY;
+ case PR_EXCLUSIVE_ACCESS_REG_ONLY:
+ return SCSI_PR_EXCLUSIVE_ACCESS_REG_ONLY;
+ case PR_WRITE_EXCLUSIVE_ALL_REGS:
+ return SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS;
+ case PR_EXCLUSIVE_ACCESS_ALL_REGS:
+ return SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(block_pr_type_to_scsi);
+
/**
* scsilun_to_int - convert a scsi_lun to an int
* @scsilun: struct scsi_lun to be converted.
@@ -176,8 +219,7 @@ bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
if (sb_len > 2)
sshdr->sense_key = (sense_buffer[2] & 0xf);
if (sb_len > 7) {
- sb_len = (sb_len < (sense_buffer[7] + 8)) ?
- sb_len : (sense_buffer[7] + 8);
+ sb_len = min(sb_len, sense_buffer[7] + 8);
if (sb_len > 12)
sshdr->asc = sense_buffer[12];
if (sb_len > 13)
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 3ec8bfd4090f..c67cdcdc3ba8 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -536,6 +536,7 @@ static inline void set_scsi_ml_byte(struct scsi_cmnd *cmd, u8 status)
*/
enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd)
{
+ struct request *req = scsi_cmd_to_rq(scmd);
struct scsi_device *sdev = scmd->device;
struct scsi_sense_hdr sshdr;
@@ -595,6 +596,22 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd)
if (sshdr.asc == 0x10) /* DIF */
return SUCCESS;
+ /*
+ * Check aborts due to command duration limit policy:
+ * ABORTED COMMAND additional sense code with the
+ * COMMAND TIMEOUT BEFORE PROCESSING or
+ * COMMAND TIMEOUT DURING PROCESSING or
+ * COMMAND TIMEOUT DURING PROCESSING DUE TO ERROR RECOVERY
+ * additional sense code qualifiers.
+ */
+ if (sshdr.asc == 0x2e &&
+ sshdr.ascq >= 0x01 && sshdr.ascq <= 0x03) {
+ set_scsi_ml_byte(scmd, SCSIML_STAT_DL_TIMEOUT);
+ req->cmd_flags |= REQ_FAILFAST_DEV;
+ req->rq_flags |= RQF_QUIET;
+ return SUCCESS;
+ }
+
if (sshdr.asc == 0x44 && sdev->sdev_bflags & BLIST_RETRY_ITF)
return ADD_TO_MLQUEUE;
if (sshdr.asc == 0xc1 && sshdr.ascq == 0x01 &&
@@ -691,6 +708,14 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd)
}
return SUCCESS;
+ case COMPLETED:
+ if (sshdr.asc == 0x55 && sshdr.ascq == 0x0a) {
+ set_scsi_ml_byte(scmd, SCSIML_STAT_DL_TIMEOUT);
+ req->cmd_flags |= REQ_FAILFAST_DEV;
+ req->rq_flags |= RQF_QUIET;
+ }
+ return SUCCESS;
+
default:
return SUCCESS;
}
@@ -785,6 +810,14 @@ static enum scsi_disposition scsi_eh_completed_normally(struct scsi_cmnd *scmd)
switch (get_status_byte(scmd)) {
case SAM_STAT_GOOD:
scsi_handle_queue_ramp_up(scmd->device);
+ if (scmd->sense_buffer && SCSI_SENSE_VALID(scmd))
+ /*
+ * If we have sense data, call scsi_check_sense() in
+ * order to set the correct SCSI ML byte (if any).
+ * No point in checking the return value, since the
+ * command has already completed successfully.
+ */
+ scsi_check_sense(scmd);
fallthrough;
case SAM_STAT_COMMAND_TERMINATED:
return SUCCESS;
@@ -1807,6 +1840,10 @@ bool scsi_noretry_cmd(struct scsi_cmnd *scmd)
return !!(req->cmd_flags & REQ_FAILFAST_DRIVER);
}
+ /* Never retry commands aborted due to a duration limit timeout */
+ if (scsi_ml_byte(scmd->result) == SCSIML_STAT_DL_TIMEOUT)
+ return true;
+
if (!scsi_status_is_check_condition(scmd->result))
return false;
@@ -1966,6 +2003,14 @@ enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *scmd)
if (scmd->cmnd[0] == REPORT_LUNS)
scmd->device->sdev_target->expecting_lun_change = 0;
scsi_handle_queue_ramp_up(scmd->device);
+ if (scmd->sense_buffer && SCSI_SENSE_VALID(scmd))
+ /*
+ * If we have sense data, call scsi_check_sense() in
+ * order to set the correct SCSI ML byte (if any).
+ * No point in checking the return value, since the
+ * command has already completed successfully.
+ */
+ scsi_check_sense(scmd);
fallthrough;
case SAM_STAT_COMMAND_TERMINATED:
return SUCCESS;
@@ -2165,7 +2210,8 @@ void scsi_eh_flush_done_q(struct list_head *done_q)
* scsi_eh_get_sense), scmd->result is already
* set, do not set DID_TIME_OUT.
*/
- if (!scmd->result)
+ if (!scmd->result &&
+ !(scmd->flags & SCMD_FORCE_EH_SUCCESS))
scmd->result |= (DID_TIME_OUT << 16);
SCSI_LOG_ERROR_RECOVERY(3,
scmd_printk(KERN_INFO, scmd,
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 0226c9279cef..ad9afae49544 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -122,11 +122,9 @@ static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd, unsigned long msecs)
WARN_ON_ONCE(true);
}
- if (msecs) {
- blk_mq_requeue_request(rq, false);
+ blk_mq_requeue_request(rq, false);
+ if (!scsi_host_in_recovery(cmd->device->host))
blk_mq_delay_kick_requeue_list(rq->q, msecs);
- } else
- blk_mq_requeue_request(rq, true);
}
/**
@@ -165,7 +163,8 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy)
*/
cmd->result = 0;
- blk_mq_requeue_request(scsi_cmd_to_rq(cmd), true);
+ blk_mq_requeue_request(scsi_cmd_to_rq(cmd),
+ !scsi_host_in_recovery(cmd->device->host));
}
/**
@@ -453,6 +452,7 @@ static void scsi_run_queue(struct request_queue *q)
if (!list_empty(&sdev->host->starved_list))
scsi_starved_list_run(sdev->host);
+ blk_mq_kick_requeue_list(q);
blk_mq_run_hw_queues(q, false);
}
@@ -503,6 +503,9 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd)
static void scsi_run_queue_async(struct scsi_device *sdev)
{
+ if (scsi_host_in_recovery(sdev->host))
+ return;
+
if (scsi_target(sdev)->single_lun ||
!list_empty(&sdev->host->starved_list)) {
kblockd_schedule_work(&sdev->requeue_work);
@@ -578,11 +581,6 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
return false;
}
-static inline u8 get_scsi_ml_byte(int result)
-{
- return (result >> 8) & 0xff;
-}
-
/**
* scsi_result_to_blk_status - translate a SCSI result code into blk_status_t
* @result: scsi error code
@@ -595,17 +593,19 @@ static blk_status_t scsi_result_to_blk_status(int result)
* Check the scsi-ml byte first in case we converted a host or status
* byte.
*/
- switch (get_scsi_ml_byte(result)) {
+ switch (scsi_ml_byte(result)) {
case SCSIML_STAT_OK:
break;
case SCSIML_STAT_RESV_CONFLICT:
- return BLK_STS_NEXUS;
+ return BLK_STS_RESV_CONFLICT;
case SCSIML_STAT_NOSPC:
return BLK_STS_NOSPC;
case SCSIML_STAT_MED_ERROR:
return BLK_STS_MEDIUM;
case SCSIML_STAT_TGT_FAILURE:
return BLK_STS_TARGET;
+ case SCSIML_STAT_DL_TIMEOUT:
+ return BLK_STS_DURATION_LIMIT;
}
switch (host_byte(result)) {
@@ -803,6 +803,8 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
blk_stat = BLK_STS_ZONE_OPEN_RESOURCE;
}
break;
+ case COMPLETED:
+ fallthrough;
default:
action = ACTION_FAIL;
break;
@@ -1985,6 +1987,8 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost)
tag_set->flags = BLK_MQ_F_SHOULD_MERGE;
tag_set->flags |=
BLK_ALLOC_POLICY_TO_MQ_FLAG(shost->hostt->tag_alloc_policy);
+ if (shost->queuecommand_may_block)
+ tag_set->flags |= BLK_MQ_F_BLOCKING;
tag_set->driver_data = shost;
if (shost->host_tagset)
tag_set->flags |= BLK_MQ_F_TAG_HCTX_SHARED;
@@ -2152,6 +2156,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select);
* @sdev: SCSI device to be queried
* @dbd: set to prevent mode sense from returning block descriptors
* @modepage: mode page being requested
+ * @subpage: sub-page of the mode page being requested
* @buffer: request buffer (may not be smaller than eight bytes)
* @len: length of request buffer.
* @timeout: command timeout
@@ -2163,7 +2168,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select);
* Returns zero if successful, or a negative error number on failure
*/
int
-scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
+scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, int subpage,
unsigned char *buffer, int len, int timeout, int retries,
struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr)
{
@@ -2183,6 +2188,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
dbd = sdev->set_dbd_for_ms ? 8 : dbd;
cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */
cmd[2] = modepage;
+ cmd[3] = subpage;
sshdr = exec_args.sshdr;
@@ -2728,24 +2734,16 @@ void scsi_start_queue(struct scsi_device *sdev)
blk_mq_unquiesce_queue(sdev->request_queue);
}
-static void scsi_stop_queue(struct scsi_device *sdev, bool nowait)
+static void scsi_stop_queue(struct scsi_device *sdev)
{
/*
* The atomic variable of ->queue_stopped covers that
* blk_mq_quiesce_queue* is balanced with blk_mq_unquiesce_queue.
*
- * However, we still need to wait until quiesce is done
- * in case that queue has been stopped.
+ * The caller needs to wait until quiesce is done.
*/
- if (!cmpxchg(&sdev->queue_stopped, 0, 1)) {
- if (nowait)
- blk_mq_quiesce_queue_nowait(sdev->request_queue);
- else
- blk_mq_quiesce_queue(sdev->request_queue);
- } else {
- if (!nowait)
- blk_mq_wait_quiesce_done(sdev->request_queue->tag_set);
- }
+ if (!cmpxchg(&sdev->queue_stopped, 0, 1))
+ blk_mq_quiesce_queue_nowait(sdev->request_queue);
}
/**
@@ -2772,19 +2770,19 @@ int scsi_internal_device_block_nowait(struct scsi_device *sdev)
* request queue.
*/
if (!ret)
- scsi_stop_queue(sdev, true);
+ scsi_stop_queue(sdev);
return ret;
}
EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait);
/**
- * scsi_internal_device_block - try to transition to the SDEV_BLOCK state
+ * scsi_device_block - try to transition to the SDEV_BLOCK state
* @sdev: device to block
+ * @data: dummy argument, ignored
*
- * Pause SCSI command processing on the specified device and wait until all
- * ongoing scsi_request_fn() / scsi_queue_rq() calls have finished. May sleep.
- *
- * Returns zero if successful or a negative error code upon failure.
+ * Pause SCSI command processing on the specified device. Callers must wait
+ * until all ongoing scsi_queue_rq() calls have finished after this function
+ * returns.
*
* Note:
* This routine transitions the device to the SDEV_BLOCK state (which must be
@@ -2792,17 +2790,26 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait);
* is paused until the device leaves the SDEV_BLOCK state. See also
* scsi_internal_device_unblock().
*/
-static int scsi_internal_device_block(struct scsi_device *sdev)
+static void scsi_device_block(struct scsi_device *sdev, void *data)
{
int err;
+ enum scsi_device_state state;
mutex_lock(&sdev->state_mutex);
err = __scsi_internal_device_block_nowait(sdev);
+ state = sdev->sdev_state;
if (err == 0)
- scsi_stop_queue(sdev, false);
+ /*
+ * scsi_stop_queue() must be called with the state_mutex
+ * held. Otherwise a simultaneous scsi_start_queue() call
+ * might unquiesce the queue before we quiesce it.
+ */
+ scsi_stop_queue(sdev);
+
mutex_unlock(&sdev->state_mutex);
- return err;
+ WARN_ONCE(err, "%s: failed to block %s in state %d\n",
+ __func__, dev_name(&sdev->sdev_gendev), state);
}
/**
@@ -2885,36 +2892,35 @@ static int scsi_internal_device_unblock(struct scsi_device *sdev,
return ret;
}
-static void
-device_block(struct scsi_device *sdev, void *data)
-{
- int ret;
-
- ret = scsi_internal_device_block(sdev);
-
- WARN_ONCE(ret, "scsi_internal_device_block(%s) failed: ret = %d\n",
- dev_name(&sdev->sdev_gendev), ret);
-}
-
static int
target_block(struct device *dev, void *data)
{
if (scsi_is_target_device(dev))
starget_for_each_device(to_scsi_target(dev), NULL,
- device_block);
+ scsi_device_block);
return 0;
}
+/**
+ * scsi_block_targets - transition all SCSI child devices to SDEV_BLOCK state
+ * @dev: a parent device of one or more scsi_target devices
+ * @shost: the Scsi_Host to which this device belongs
+ *
+ * Iterate over all children of @dev, which should be scsi_target devices,
+ * and switch all subordinate scsi devices to SDEV_BLOCK state. Wait for
+ * ongoing scsi_queue_rq() calls to finish. May sleep.
+ *
+ * Note:
+ * @dev must not itself be a scsi_target device.
+ */
void
-scsi_target_block(struct device *dev)
+scsi_block_targets(struct Scsi_Host *shost, struct device *dev)
{
- if (scsi_is_target_device(dev))
- starget_for_each_device(to_scsi_target(dev), NULL,
- device_block);
- else
- device_for_each_child(dev, NULL, target_block);
+ WARN_ON_ONCE(scsi_is_target_device(dev));
+ device_for_each_child(dev, NULL, target_block);
+ blk_mq_wait_quiesce_done(&shost->tag_set);
}
-EXPORT_SYMBOL_GPL(scsi_target_block);
+EXPORT_SYMBOL_GPL(scsi_block_targets);
static void
device_unblock(struct scsi_device *sdev, void *data)
@@ -2942,11 +2948,20 @@ scsi_target_unblock(struct device *dev, enum scsi_device_state new_state)
}
EXPORT_SYMBOL_GPL(scsi_target_unblock);
+/**
+ * scsi_host_block - Try to transition all logical units to the SDEV_BLOCK state
+ * @shost: device to block
+ *
+ * Pause SCSI command processing for all logical units associated with the SCSI
+ * host and wait until pending scsi_queue_rq() calls have finished.
+ *
+ * Returns zero if successful or a negative error code upon failure.
+ */
int
scsi_host_block(struct Scsi_Host *shost)
{
struct scsi_device *sdev;
- int ret = 0;
+ int ret;
/*
* Call scsi_internal_device_block_nowait so we can avoid
@@ -2958,20 +2973,14 @@ scsi_host_block(struct Scsi_Host *shost)
mutex_unlock(&sdev->state_mutex);
if (ret) {
scsi_device_put(sdev);
- break;
+ return ret;
}
}
- /*
- * SCSI never enables blk-mq's BLK_MQ_F_BLOCKING flag so
- * calling synchronize_rcu() once is enough.
- */
- WARN_ON_ONCE(shost->tag_set.flags & BLK_MQ_F_BLOCKING);
-
- if (!ret)
- synchronize_rcu();
+ /* Wait for ongoing scsi_queue_rq() calls to finish. */
+ blk_mq_wait_quiesce_done(&shost->tag_set);
- return ret;
+ return 0;
}
EXPORT_SYMBOL_GPL(scsi_host_block);
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 96284a0e13fe..f42388ecb024 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -27,8 +27,14 @@ enum scsi_ml_status {
SCSIML_STAT_NOSPC = 0x02, /* Space allocation on the dev failed */
SCSIML_STAT_MED_ERROR = 0x03, /* Medium error */
SCSIML_STAT_TGT_FAILURE = 0x04, /* Permanent target failure */
+ SCSIML_STAT_DL_TIMEOUT = 0x05, /* Command Duration Limit timeout */
};
+static inline u8 scsi_ml_byte(int result)
+{
+ return (result >> 8) & 0xff;
+}
+
/*
* Scsi Error Handler Flags
*/
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index d217be323cc6..aa13feb17c62 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1087,6 +1087,8 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
if (sdev->scsi_level >= SCSI_3)
scsi_attach_vpd(sdev);
+ scsi_cdl_check(sdev);
+
sdev->max_queue_depth = sdev->queue_depth;
WARN_ON_ONCE(sdev->max_queue_depth > sdev->budget_map.depth);
sdev->sdev_bflags = *bflags;
@@ -1624,6 +1626,7 @@ void scsi_rescan_device(struct device *dev)
device_lock(dev);
scsi_attach_vpd(sdev);
+ scsi_cdl_check(sdev);
if (sdev->handler && sdev->handler->rescan)
sdev->handler->rescan(sdev);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 603e8fcfcb8a..60317676e45f 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -670,6 +670,7 @@ sdev_rd_attr (scsi_level, "%d\n");
sdev_rd_attr (vendor, "%.8s\n");
sdev_rd_attr (model, "%.16s\n");
sdev_rd_attr (rev, "%.4s\n");
+sdev_rd_attr (cdl_supported, "%d\n");
static ssize_t
sdev_show_device_busy(struct device *dev, struct device_attribute *attr,
@@ -1221,6 +1222,33 @@ static DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR,
sdev_show_queue_ramp_up_period,
sdev_store_queue_ramp_up_period);
+static ssize_t sdev_show_cdl_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ return sysfs_emit(buf, "%d\n", (int)sdev->cdl_enable);
+}
+
+static ssize_t sdev_store_cdl_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+ bool v;
+
+ if (kstrtobool(buf, &v))
+ return -EINVAL;
+
+ ret = scsi_cdl_enable(to_scsi_device(dev), v);
+ if (ret)
+ return ret;
+
+ return count;
+}
+static DEVICE_ATTR(cdl_enable, S_IRUGO | S_IWUSR,
+ sdev_show_cdl_enable, sdev_store_cdl_enable);
+
static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int i)
{
@@ -1300,6 +1328,8 @@ static struct attribute *scsi_sdev_attrs[] = {
&dev_attr_preferred_path.attr,
#endif
&dev_attr_queue_ramp_up_period.attr,
+ &dev_attr_cdl_supported.attr,
+ &dev_attr_cdl_enable.attr,
REF_EVT(media_change),
REF_EVT(inquiry_change_reported),
REF_EVT(capacity_change_reported),
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 64ff2629eaf9..b04075f19445 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -3451,7 +3451,7 @@ fc_remote_port_delete(struct fc_rport *rport)
spin_unlock_irqrestore(shost->host_lock, flags);
- scsi_target_block(&rport->dev);
+ scsi_block_targets(shost, &rport->dev);
/* see if we need to kill io faster than waiting for device loss */
if ((rport->fast_io_fail_tmo != -1) &&
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index b9b97300e3b3..e527ece12453 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1943,13 +1943,14 @@ static void __iscsi_block_session(struct work_struct *work)
struct iscsi_cls_session *session =
container_of(work, struct iscsi_cls_session,
block_work);
+ struct Scsi_Host *shost = iscsi_session_to_shost(session);
unsigned long flags;
ISCSI_DBG_TRANS_SESSION(session, "Blocking session\n");
spin_lock_irqsave(&session->lock, flags);
session->state = ISCSI_SESSION_FAILED;
spin_unlock_irqrestore(&session->lock, flags);
- scsi_target_block(&session->dev);
+ scsi_block_targets(shost, &session->dev);
ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n");
if (session->recovery_tmo >= 0)
queue_delayed_work(session->workq,
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 74b99f2b0b74..d704c484a251 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -1245,7 +1245,7 @@ int sas_read_port_mode_page(struct scsi_device *sdev)
if (!buffer)
return -ENOMEM;
- error = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3,
+ error = scsi_mode_sense(sdev, 1, 0x19, 0, buffer, BUF_SIZE, 30*HZ, 3,
&mode_data, NULL);
if (error)
diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c
index 87d0fb8dc503..64f6b22e8cc0 100644
--- a/drivers/scsi/scsi_transport_srp.c
+++ b/drivers/scsi/scsi_transport_srp.c
@@ -396,7 +396,7 @@ static void srp_reconnect_work(struct work_struct *work)
}
/*
- * scsi_target_block() must have been called before this function is
+ * scsi_block_targets() must have been called before this function is
* called to guarantee that no .queuecommand() calls are in progress.
*/
static void __rport_fail_io_fast(struct srp_rport *rport)
@@ -480,7 +480,7 @@ static void __srp_start_tl_fail_timers(struct srp_rport *rport)
srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) {
pr_debug("%s new state: %d\n", dev_name(&shost->shost_gendev),
rport->state);
- scsi_target_block(&shost->shost_gendev);
+ scsi_block_targets(shost, &shost->shost_gendev);
if (fast_io_fail_tmo >= 0)
queue_delayed_work(system_long_wq,
&rport->fast_io_fail_work,
@@ -548,7 +548,7 @@ int srp_reconnect_rport(struct srp_rport *rport)
* later is ok though, scsi_internal_device_unblock_nowait()
* treats SDEV_TRANSPORT_OFFLINE like SDEV_BLOCK.
*/
- scsi_target_block(&shost->shost_gendev);
+ scsi_block_targets(shost, &shost->shost_gendev);
res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV;
pr_debug("%s (state %d): transport.reconnect() returned %d\n",
dev_name(&shost->shost_gendev), rport->state, res);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index ab216976dbdc..68b12afa0721 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -67,6 +67,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/scsicam.h>
+#include <scsi/scsi_common.h>
#include "sd.h"
#include "scsi_priv.h"
@@ -183,7 +184,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
return count;
}
- if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT,
+ if (scsi_mode_sense(sdp, 0x08, 8, 0, buffer, sizeof(buffer), SD_TIMEOUT,
sdkp->max_retries, &data, NULL))
return -EINVAL;
len = min_t(size_t, sizeof(buffer), data.length - data.header_length -
@@ -1041,13 +1042,14 @@ static blk_status_t sd_setup_flush_cmnd(struct scsi_cmnd *cmd)
static blk_status_t sd_setup_rw32_cmnd(struct scsi_cmnd *cmd, bool write,
sector_t lba, unsigned int nr_blocks,
- unsigned char flags)
+ unsigned char flags, unsigned int dld)
{
cmd->cmd_len = SD_EXT_CDB_SIZE;
cmd->cmnd[0] = VARIABLE_LENGTH_CMD;
cmd->cmnd[7] = 0x18; /* Additional CDB len */
cmd->cmnd[9] = write ? WRITE_32 : READ_32;
cmd->cmnd[10] = flags;
+ cmd->cmnd[11] = dld & 0x07;
put_unaligned_be64(lba, &cmd->cmnd[12]);
put_unaligned_be32(lba, &cmd->cmnd[20]); /* Expected Indirect LBA */
put_unaligned_be32(nr_blocks, &cmd->cmnd[28]);
@@ -1057,12 +1059,12 @@ static blk_status_t sd_setup_rw32_cmnd(struct scsi_cmnd *cmd, bool write,
static blk_status_t sd_setup_rw16_cmnd(struct scsi_cmnd *cmd, bool write,
sector_t lba, unsigned int nr_blocks,
- unsigned char flags)
+ unsigned char flags, unsigned int dld)
{
cmd->cmd_len = 16;
cmd->cmnd[0] = write ? WRITE_16 : READ_16;
- cmd->cmnd[1] = flags;
- cmd->cmnd[14] = 0;
+ cmd->cmnd[1] = flags | ((dld >> 2) & 0x01);
+ cmd->cmnd[14] = (dld & 0x03) << 6;
cmd->cmnd[15] = 0;
put_unaligned_be64(lba, &cmd->cmnd[2]);
put_unaligned_be32(nr_blocks, &cmd->cmnd[10]);
@@ -1114,6 +1116,31 @@ static blk_status_t sd_setup_rw6_cmnd(struct scsi_cmnd *cmd, bool write,
return BLK_STS_OK;
}
+/*
+ * Check if a command has a duration limit set. If it does, and the target
+ * device supports CDL and the feature is enabled, return the limit
+ * descriptor index to use. Return 0 (no limit) otherwise.
+ */
+static int sd_cdl_dld(struct scsi_disk *sdkp, struct scsi_cmnd *scmd)
+{
+ struct scsi_device *sdp = sdkp->device;
+ int hint;
+
+ if (!sdp->cdl_supported || !sdp->cdl_enable)
+ return 0;
+
+ /*
+ * Use "no limit" if the request ioprio does not specify a duration
+ * limit hint.
+ */
+ hint = IOPRIO_PRIO_HINT(req_get_ioprio(scsi_cmd_to_rq(scmd)));
+ if (hint < IOPRIO_HINT_DEV_DURATION_LIMIT_1 ||
+ hint > IOPRIO_HINT_DEV_DURATION_LIMIT_7)
+ return 0;
+
+ return (hint - IOPRIO_HINT_DEV_DURATION_LIMIT_1) + 1;
+}
+
static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd)
{
struct request *rq = scsi_cmd_to_rq(cmd);
@@ -1125,6 +1152,7 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd)
unsigned int mask = logical_to_sectors(sdp, 1) - 1;
bool write = rq_data_dir(rq) == WRITE;
unsigned char protect, fua;
+ unsigned int dld;
blk_status_t ret;
unsigned int dif;
bool dix;
@@ -1174,6 +1202,7 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd)
fua = rq->cmd_flags & REQ_FUA ? 0x8 : 0;
dix = scsi_prot_sg_count(cmd);
dif = scsi_host_dif_capable(cmd->device->host, sdkp->protection_type);
+ dld = sd_cdl_dld(sdkp, cmd);
if (dif || dix)
protect = sd_setup_protect_cmnd(cmd, dix, dif);
@@ -1182,10 +1211,10 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd)
if (protect && sdkp->protection_type == T10_PI_TYPE2_PROTECTION) {
ret = sd_setup_rw32_cmnd(cmd, write, lba, nr_blocks,
- protect | fua);
+ protect | fua, dld);
} else if (sdp->use_16_for_rw || (nr_blocks > 0xffff)) {
ret = sd_setup_rw16_cmnd(cmd, write, lba, nr_blocks,
- protect | fua);
+ protect | fua, dld);
} else if ((nr_blocks > 0xff) || (lba > 0x1fffff) ||
sdp->use_10_for_rw || protect) {
ret = sd_setup_rw10_cmnd(cmd, write, lba, nr_blocks,
@@ -1690,26 +1719,6 @@ out_unlock:
return ret;
}
-static char sd_pr_type(enum pr_type type)
-{
- switch (type) {
- case PR_WRITE_EXCLUSIVE:
- return 0x01;
- case PR_EXCLUSIVE_ACCESS:
- return 0x03;
- case PR_WRITE_EXCLUSIVE_REG_ONLY:
- return 0x05;
- case PR_EXCLUSIVE_ACCESS_REG_ONLY:
- return 0x06;
- case PR_WRITE_EXCLUSIVE_ALL_REGS:
- return 0x07;
- case PR_EXCLUSIVE_ACCESS_ALL_REGS:
- return 0x08;
- default:
- return 0;
- }
-};
-
static int sd_scsi_to_pr_err(struct scsi_sense_hdr *sshdr, int result)
{
switch (host_byte(result)) {
@@ -1740,8 +1749,97 @@ static int sd_scsi_to_pr_err(struct scsi_sense_hdr *sshdr, int result)
}
}
-static int sd_pr_command(struct block_device *bdev, u8 sa,
- u64 key, u64 sa_key, u8 type, u8 flags)
+static int sd_pr_in_command(struct block_device *bdev, u8 sa,
+ unsigned char *data, int data_len)
+{
+ struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
+ struct scsi_device *sdev = sdkp->device;
+ struct scsi_sense_hdr sshdr;
+ u8 cmd[10] = { PERSISTENT_RESERVE_IN, sa };
+ const struct scsi_exec_args exec_args = {
+ .sshdr = &sshdr,
+ };
+ int result;
+
+ put_unaligned_be16(data_len, &cmd[7]);
+
+ result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, data, data_len,
+ SD_TIMEOUT, sdkp->max_retries, &exec_args);
+ if (scsi_status_is_check_condition(result) &&
+ scsi_sense_valid(&sshdr)) {
+ sdev_printk(KERN_INFO, sdev, "PR command failed: %d\n", result);
+ scsi_print_sense_hdr(sdev, NULL, &sshdr);
+ }
+
+ if (result <= 0)
+ return result;
+
+ return sd_scsi_to_pr_err(&sshdr, result);
+}
+
+static int sd_pr_read_keys(struct block_device *bdev, struct pr_keys *keys_info)
+{
+ int result, i, data_offset, num_copy_keys;
+ u32 num_keys = keys_info->num_keys;
+ int data_len = num_keys * 8 + 8;
+ u8 *data;
+
+ data = kzalloc(data_len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ result = sd_pr_in_command(bdev, READ_KEYS, data, data_len);
+ if (result)
+ goto free_data;
+
+ keys_info->generation = get_unaligned_be32(&data[0]);
+ keys_info->num_keys = get_unaligned_be32(&data[4]) / 8;
+
+ data_offset = 8;
+ num_copy_keys = min(num_keys, keys_info->num_keys);
+
+ for (i = 0; i < num_copy_keys; i++) {
+ keys_info->keys[i] = get_unaligned_be64(&data[data_offset]);
+ data_offset += 8;
+ }
+
+free_data:
+ kfree(data);
+ return result;
+}
+
+static int sd_pr_read_reservation(struct block_device *bdev,
+ struct pr_held_reservation *rsv)
+{
+ struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
+ struct scsi_device *sdev = sdkp->device;
+ u8 data[24] = { };
+ int result, len;
+
+ result = sd_pr_in_command(bdev, READ_RESERVATION, data, sizeof(data));
+ if (result)
+ return result;
+
+ len = get_unaligned_be32(&data[4]);
+ if (!len)
+ return 0;
+
+ /* Make sure we have at least the key and type */
+ if (len < 14) {
+ sdev_printk(KERN_INFO, sdev,
+ "READ RESERVATION failed due to short return buffer of %d bytes\n",
+ len);
+ return -EINVAL;
+ }
+
+ rsv->generation = get_unaligned_be32(&data[0]);
+ rsv->key = get_unaligned_be64(&data[8]);
+ rsv->type = scsi_pr_type_to_block(data[21] & 0x0f);
+ return 0;
+}
+
+static int sd_pr_out_command(struct block_device *bdev, u8 sa, u64 key,
+ u64 sa_key, enum scsi_pr_type type, u8 flags)
{
struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
struct scsi_device *sdev = sdkp->device;
@@ -1783,7 +1881,7 @@ static int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
{
if (flags & ~PR_FL_IGNORE_KEY)
return -EOPNOTSUPP;
- return sd_pr_command(bdev, (flags & PR_FL_IGNORE_KEY) ? 0x06 : 0x00,
+ return sd_pr_out_command(bdev, (flags & PR_FL_IGNORE_KEY) ? 0x06 : 0x00,
old_key, new_key, 0,
(1 << 0) /* APTPL */);
}
@@ -1793,24 +1891,26 @@ static int sd_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type,
{
if (flags)
return -EOPNOTSUPP;
- return sd_pr_command(bdev, 0x01, key, 0, sd_pr_type(type), 0);
+ return sd_pr_out_command(bdev, 0x01, key, 0,
+ block_pr_type_to_scsi(type), 0);
}
static int sd_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
{
- return sd_pr_command(bdev, 0x02, key, 0, sd_pr_type(type), 0);
+ return sd_pr_out_command(bdev, 0x02, key, 0,
+ block_pr_type_to_scsi(type), 0);
}
static int sd_pr_preempt(struct block_device *bdev, u64 old_key, u64 new_key,
enum pr_type type, bool abort)
{
- return sd_pr_command(bdev, abort ? 0x05 : 0x04, old_key, new_key,
- sd_pr_type(type), 0);
+ return sd_pr_out_command(bdev, abort ? 0x05 : 0x04, old_key, new_key,
+ block_pr_type_to_scsi(type), 0);
}
static int sd_pr_clear(struct block_device *bdev, u64 key)
{
- return sd_pr_command(bdev, 0x03, key, 0, 0, 0);
+ return sd_pr_out_command(bdev, 0x03, key, 0, 0, 0);
}
static const struct pr_ops sd_pr_ops = {
@@ -1819,6 +1919,8 @@ static const struct pr_ops sd_pr_ops = {
.pr_release = sd_pr_release,
.pr_preempt = sd_pr_preempt,
.pr_clear = sd_pr_clear,
+ .pr_read_keys = sd_pr_read_keys,
+ .pr_read_reservation = sd_pr_read_reservation,
};
static void scsi_disk_free_disk(struct gendisk *disk)
@@ -2608,9 +2710,8 @@ sd_do_mode_sense(struct scsi_disk *sdkp, int dbd, int modepage,
if (sdkp->device->use_10_for_ms && len < 8)
len = 8;
- return scsi_mode_sense(sdkp->device, dbd, modepage, buffer, len,
- SD_TIMEOUT, sdkp->max_retries, data,
- sshdr);
+ return scsi_mode_sense(sdkp->device, dbd, modepage, 0, buffer, len,
+ SD_TIMEOUT, sdkp->max_retries, data, sshdr);
}
/*
@@ -2867,7 +2968,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
if (sdkp->protection_type == 0)
return;
- res = scsi_mode_sense(sdp, 1, 0x0a, buffer, 36, SD_TIMEOUT,
+ res = scsi_mode_sense(sdp, 1, 0x0a, 0, buffer, 36, SD_TIMEOUT,
sdkp->max_retries, &data, &sshdr);
if (res < 0 || !data.header_length ||
@@ -3056,7 +3157,7 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
return;
}
- if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY, 0) < 0) {
struct scsi_vpd *vpd;
sdev->no_report_opcodes = 1;
@@ -3072,10 +3173,10 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
rcu_read_unlock();
}
- if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16) == 1)
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16, 0) == 1)
sdkp->ws16 = 1;
- if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME) == 1)
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME, 0) == 1)
sdkp->ws10 = 1;
}
@@ -3087,9 +3188,9 @@ static void sd_read_security(struct scsi_disk *sdkp, unsigned char *buffer)
return;
if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE,
- SECURITY_PROTOCOL_IN) == 1 &&
+ SECURITY_PROTOCOL_IN, 0) == 1 &&
scsi_report_opcode(sdev, buffer, SD_BUF_SIZE,
- SECURITY_PROTOCOL_OUT) == 1)
+ SECURITY_PROTOCOL_OUT, 0) == 1)
sdkp->security = 1;
}
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 22801c24ea19..abbd08933ac7 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -889,7 +889,7 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
}
max_append = min_t(u32, logical_to_sectors(sdkp->device, zone_blocks),
- q->limits.max_segments << (PAGE_SHIFT - 9));
+ q->limits.max_segments << PAGE_SECTORS_SHIFT);
max_append = min_t(u32, max_append, queue_max_hw_sectors(q));
blk_queue_max_zone_append_sectors(q, max_append);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index dcb73787c29d..89fa046c7158 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -71,7 +71,7 @@ static int sg_proc_init(void);
#define SG_ALLOW_DIO_DEF 0
-#define SG_MAX_DEVS 32768
+#define SG_MAX_DEVS (1 << MINORBITS)
/* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
* of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater
diff --git a/drivers/scsi/smartpqi/Kconfig b/drivers/scsi/smartpqi/Kconfig
index 973d240649ab..789460b0a342 100644
--- a/drivers/scsi/smartpqi/Kconfig
+++ b/drivers/scsi/smartpqi/Kconfig
@@ -1,7 +1,7 @@
#
# Kernel configuration file for the SMARTPQI
#
-# Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries
+# Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries
# Copyright (c) 2017-2018 Microsemi Corporation
# Copyright (c) 2016 Microsemi Corporation
# Copyright (c) 2016 PMC-Sierra, Inc.
diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 228838eb3686..f960b5095d09 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* driver for Microchip PQI-based storage controllers
- * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries
+ * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
@@ -1108,6 +1108,7 @@ struct pqi_scsi_dev {
u8 volume_offline : 1;
u8 rescan : 1;
u8 ignore_device : 1;
+ u8 erase_in_progress : 1;
bool aio_enabled; /* only valid for physical disks */
bool in_remove;
bool device_offline;
@@ -1147,7 +1148,7 @@ struct pqi_scsi_dev {
struct pqi_stream_data stream_data[NUM_STREAMS_PER_LUN];
atomic_t scsi_cmds_outstanding[PQI_MAX_LUNS_PER_DEVICE];
- atomic_t raid_bypass_cnt;
+ unsigned int raid_bypass_cnt;
};
/* VPD inquiry pages */
@@ -1357,6 +1358,7 @@ struct pqi_ctrl_info {
u32 max_write_raid_5_6;
u32 max_write_raid_1_10_2drive;
u32 max_write_raid_1_10_3drive;
+ int numa_node;
struct list_head scsi_device_list;
spinlock_t scsi_device_list_lock;
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index f4e0aa262164..19af36e9a16d 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* driver for Microchip PQI-based storage controllers
- * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries
+ * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
@@ -33,11 +33,11 @@
#define BUILD_TIMESTAMP
#endif
-#define DRIVER_VERSION "2.1.20-035"
+#define DRIVER_VERSION "2.1.22-040"
#define DRIVER_MAJOR 2
#define DRIVER_MINOR 1
-#define DRIVER_RELEASE 20
-#define DRIVER_REVISION 35
+#define DRIVER_RELEASE 22
+#define DRIVER_REVISION 40
#define DRIVER_NAME "Microchip SmartPQI Driver (v" \
DRIVER_VERSION BUILD_TIMESTAMP ")"
@@ -519,6 +519,36 @@ static inline void pqi_clear_soft_reset_status(struct pqi_ctrl_info *ctrl_info)
writeb(status, ctrl_info->soft_reset_status);
}
+static inline bool pqi_is_io_high_priority(struct pqi_scsi_dev *device, struct scsi_cmnd *scmd)
+{
+ bool io_high_prio;
+ int priority_class;
+
+ io_high_prio = false;
+
+ if (device->ncq_prio_enable) {
+ priority_class =
+ IOPRIO_PRIO_CLASS(req_get_ioprio(scsi_cmd_to_rq(scmd)));
+ if (priority_class == IOPRIO_CLASS_RT) {
+ /* Set NCQ priority for read/write commands. */
+ switch (scmd->cmnd[0]) {
+ case WRITE_16:
+ case READ_16:
+ case WRITE_12:
+ case READ_12:
+ case WRITE_10:
+ case READ_10:
+ case WRITE_6:
+ case READ_6:
+ io_high_prio = true;
+ break;
+ }
+ }
+ }
+
+ return io_high_prio;
+}
+
static int pqi_map_single(struct pci_dev *pci_dev,
struct pqi_sg_descriptor *sg_descriptor, void *buffer,
size_t buffer_length, enum dma_data_direction data_direction)
@@ -578,10 +608,6 @@ static int pqi_build_raid_path_request(struct pqi_ctrl_info *ctrl_info,
cdb = request->cdb;
switch (cmd) {
- case TEST_UNIT_READY:
- request->data_direction = SOP_READ_FLAG;
- cdb[0] = TEST_UNIT_READY;
- break;
case INQUIRY:
request->data_direction = SOP_READ_FLAG;
cdb[0] = INQUIRY;
@@ -708,7 +734,8 @@ static inline struct pqi_io_request *pqi_alloc_io_request(struct pqi_ctrl_info *
}
}
- pqi_reinit_io_request(io_request);
+ if (io_request)
+ pqi_reinit_io_request(io_request);
return io_request;
}
@@ -1588,6 +1615,7 @@ no_buffer:
#define PQI_DEVICE_NCQ_PRIO_SUPPORTED 0x01
#define PQI_DEVICE_PHY_MAP_SUPPORTED 0x10
+#define PQI_DEVICE_ERASE_IN_PROGRESS 0x10
static int pqi_get_physical_device_info(struct pqi_ctrl_info *ctrl_info,
struct pqi_scsi_dev *device,
@@ -1636,6 +1664,8 @@ static int pqi_get_physical_device_info(struct pqi_ctrl_info *ctrl_info,
((get_unaligned_le32(&id_phys->misc_drive_flags) >> 16) &
PQI_DEVICE_NCQ_PRIO_SUPPORTED);
+ device->erase_in_progress = !!(get_unaligned_le16(&id_phys->extra_physical_drive_flags) & PQI_DEVICE_ERASE_IN_PROGRESS);
+
return 0;
}
@@ -1681,7 +1711,7 @@ out:
/*
* Prevent adding drive to OS for some corner cases such as a drive
- * undergoing a sanitize operation. Some OSes will continue to poll
+ * undergoing a sanitize (erase) operation. Some OSes will continue to poll
* the drive until the sanitize completes, which can take hours,
* resulting in long bootup delays. Commands such as TUR, READ_CAP
* are allowed, but READ/WRITE cause check condition. So the OS
@@ -1689,73 +1719,9 @@ out:
* Note: devices that have completed sanitize must be re-enabled
* using the management utility.
*/
-static bool pqi_keep_device_offline(struct pqi_ctrl_info *ctrl_info,
- struct pqi_scsi_dev *device)
+static inline bool pqi_keep_device_offline(struct pqi_scsi_dev *device)
{
- u8 scsi_status;
- int rc;
- enum dma_data_direction dir;
- char *buffer;
- int buffer_length = 64;
- size_t sense_data_length;
- struct scsi_sense_hdr sshdr;
- struct pqi_raid_path_request request;
- struct pqi_raid_error_info error_info;
- bool offline = false; /* Assume keep online */
-
- /* Do not check controllers. */
- if (pqi_is_hba_lunid(device->scsi3addr))
- return false;
-
- /* Do not check LVs. */
- if (pqi_is_logical_device(device))
- return false;
-
- buffer = kmalloc(buffer_length, GFP_KERNEL);
- if (!buffer)
- return false; /* Assume not offline */
-
- /* Check for SANITIZE in progress using TUR */
- rc = pqi_build_raid_path_request(ctrl_info, &request,
- TEST_UNIT_READY, RAID_CTLR_LUNID, buffer,
- buffer_length, 0, &dir);
- if (rc)
- goto out; /* Assume not offline */
-
- memcpy(request.lun_number, device->scsi3addr, sizeof(request.lun_number));
-
- rc = pqi_submit_raid_request_synchronous(ctrl_info, &request.header, 0, &error_info);
-
- if (rc)
- goto out; /* Assume not offline */
-
- scsi_status = error_info.status;
- sense_data_length = get_unaligned_le16(&error_info.sense_data_length);
- if (sense_data_length == 0)
- sense_data_length =
- get_unaligned_le16(&error_info.response_data_length);
- if (sense_data_length) {
- if (sense_data_length > sizeof(error_info.data))
- sense_data_length = sizeof(error_info.data);
-
- /*
- * Check for sanitize in progress: asc:0x04, ascq: 0x1b
- */
- if (scsi_status == SAM_STAT_CHECK_CONDITION &&
- scsi_normalize_sense(error_info.data,
- sense_data_length, &sshdr) &&
- sshdr.sense_key == NOT_READY &&
- sshdr.asc == 0x04 &&
- sshdr.ascq == 0x1b) {
- device->device_offline = true;
- offline = true;
- goto out; /* Keep device offline */
- }
- }
-
-out:
- kfree(buffer);
- return offline;
+ return device->erase_in_progress;
}
static int pqi_get_device_info_phys_logical(struct pqi_ctrl_info *ctrl_info,
@@ -2499,10 +2465,6 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info)
if (!pqi_is_supported_device(device))
continue;
- /* Do not present disks that the OS cannot fully probe */
- if (pqi_keep_device_offline(ctrl_info, device))
- continue;
-
/* Gather information about the device. */
rc = pqi_get_device_info(ctrl_info, device, id_phys);
if (rc == -ENOMEM) {
@@ -2525,6 +2487,10 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info)
continue;
}
+ /* Do not present disks that the OS cannot fully probe. */
+ if (pqi_keep_device_offline(device))
+ continue;
+
pqi_assign_bus_target_lun(device);
if (device->is_physical_device) {
@@ -5504,15 +5470,19 @@ static void pqi_raid_io_complete(struct pqi_io_request *io_request,
pqi_scsi_done(scmd);
}
-static int pqi_raid_submit_scsi_cmd_with_io_request(
- struct pqi_ctrl_info *ctrl_info, struct pqi_io_request *io_request,
+static int pqi_raid_submit_io(struct pqi_ctrl_info *ctrl_info,
struct pqi_scsi_dev *device, struct scsi_cmnd *scmd,
- struct pqi_queue_group *queue_group)
+ struct pqi_queue_group *queue_group, bool io_high_prio)
{
int rc;
size_t cdb_length;
+ struct pqi_io_request *io_request;
struct pqi_raid_path_request *request;
+ io_request = pqi_alloc_io_request(ctrl_info, scmd);
+ if (!io_request)
+ return SCSI_MLQUEUE_HOST_BUSY;
+
io_request->io_complete_callback = pqi_raid_io_complete;
io_request->scmd = scmd;
@@ -5522,6 +5492,7 @@ static int pqi_raid_submit_scsi_cmd_with_io_request(
request->header.iu_type = PQI_REQUEST_IU_RAID_PATH_IO;
put_unaligned_le32(scsi_bufflen(scmd), &request->buffer_length);
request->task_attribute = SOP_TASK_ATTRIBUTE_SIMPLE;
+ request->command_priority = io_high_prio;
put_unaligned_le16(io_request->index, &request->request_id);
request->error_index = request->request_id;
memcpy(request->lun_number, device->scsi3addr, sizeof(request->lun_number));
@@ -5587,14 +5558,11 @@ static inline int pqi_raid_submit_scsi_cmd(struct pqi_ctrl_info *ctrl_info,
struct pqi_scsi_dev *device, struct scsi_cmnd *scmd,
struct pqi_queue_group *queue_group)
{
- struct pqi_io_request *io_request;
+ bool io_high_prio;
- io_request = pqi_alloc_io_request(ctrl_info, scmd);
- if (!io_request)
- return SCSI_MLQUEUE_HOST_BUSY;
+ io_high_prio = pqi_is_io_high_priority(device, scmd);
- return pqi_raid_submit_scsi_cmd_with_io_request(ctrl_info, io_request,
- device, scmd, queue_group);
+ return pqi_raid_submit_io(ctrl_info, device, scmd, queue_group, io_high_prio);
}
static bool pqi_raid_bypass_retry_needed(struct pqi_io_request *io_request)
@@ -5639,44 +5607,13 @@ static void pqi_aio_io_complete(struct pqi_io_request *io_request,
pqi_scsi_done(scmd);
}
-static inline bool pqi_is_io_high_priority(struct pqi_ctrl_info *ctrl_info,
- struct pqi_scsi_dev *device, struct scsi_cmnd *scmd)
-{
- bool io_high_prio;
- int priority_class;
-
- io_high_prio = false;
-
- if (device->ncq_prio_enable) {
- priority_class =
- IOPRIO_PRIO_CLASS(req_get_ioprio(scsi_cmd_to_rq(scmd)));
- if (priority_class == IOPRIO_CLASS_RT) {
- /* Set NCQ priority for read/write commands. */
- switch (scmd->cmnd[0]) {
- case WRITE_16:
- case READ_16:
- case WRITE_12:
- case READ_12:
- case WRITE_10:
- case READ_10:
- case WRITE_6:
- case READ_6:
- io_high_prio = true;
- break;
- }
- }
- }
-
- return io_high_prio;
-}
-
static inline int pqi_aio_submit_scsi_cmd(struct pqi_ctrl_info *ctrl_info,
struct pqi_scsi_dev *device, struct scsi_cmnd *scmd,
struct pqi_queue_group *queue_group)
{
bool io_high_prio;
- io_high_prio = pqi_is_io_high_priority(ctrl_info, device, scmd);
+ io_high_prio = pqi_is_io_high_priority(device, scmd);
return pqi_aio_submit_io(ctrl_info, scmd, device->aio_handle,
scmd->cmnd, scmd->cmd_len, queue_group, NULL,
@@ -5694,10 +5631,10 @@ static int pqi_aio_submit_io(struct pqi_ctrl_info *ctrl_info,
struct pqi_aio_path_request *request;
struct pqi_scsi_dev *device;
- device = scmd->device->hostdata;
io_request = pqi_alloc_io_request(ctrl_info, scmd);
if (!io_request)
return SCSI_MLQUEUE_HOST_BUSY;
+
io_request->io_complete_callback = pqi_aio_io_complete;
io_request->scmd = scmd;
io_request->raid_bypass = raid_bypass;
@@ -5712,6 +5649,7 @@ static int pqi_aio_submit_io(struct pqi_ctrl_info *ctrl_info,
request->command_priority = io_high_prio;
put_unaligned_le16(io_request->index, &request->request_id);
request->error_index = request->request_id;
+ device = scmd->device->hostdata;
if (!pqi_is_logical_device(device) && ctrl_info->multi_lun_device_supported)
put_unaligned_le64(((scmd->device->lun) << 8), &request->lun_number);
if (cdb_length > sizeof(request->cdb))
@@ -6052,7 +5990,7 @@ static int pqi_scsi_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scm
rc = pqi_raid_bypass_submit_scsi_cmd(ctrl_info, device, scmd, queue_group);
if (rc == 0 || rc == SCSI_MLQUEUE_HOST_BUSY) {
raid_bypassed = true;
- atomic_inc(&device->raid_bypass_cnt);
+ device->raid_bypass_cnt++;
}
}
if (!raid_bypassed)
@@ -6903,7 +6841,7 @@ static ssize_t pqi_lockup_action_store(struct device *dev,
char *action_name;
char action_name_buffer[32];
- strlcpy(action_name_buffer, buffer, sizeof(action_name_buffer));
+ strscpy(action_name_buffer, buffer, sizeof(action_name_buffer));
action_name = strstrip(action_name_buffer);
for (i = 0; i < ARRAY_SIZE(pqi_lockup_actions); i++) {
@@ -7288,7 +7226,7 @@ static ssize_t pqi_raid_bypass_cnt_show(struct device *dev,
struct scsi_device *sdev;
struct pqi_scsi_dev *device;
unsigned long flags;
- int raid_bypass_cnt;
+ unsigned int raid_bypass_cnt;
sdev = to_scsi_device(dev);
ctrl_info = shost_to_hba(sdev->host);
@@ -7304,7 +7242,7 @@ static ssize_t pqi_raid_bypass_cnt_show(struct device *dev,
return -ENODEV;
}
- raid_bypass_cnt = atomic_read(&device->raid_bypass_cnt);
+ raid_bypass_cnt = device->raid_bypass_cnt;
spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
@@ -7366,8 +7304,7 @@ static ssize_t pqi_sas_ncq_prio_enable_store(struct device *dev,
return -ENODEV;
}
- if (!device->ncq_prio_support ||
- !device->is_physical_device) {
+ if (!device->ncq_prio_support) {
spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
return -EINVAL;
}
@@ -7379,6 +7316,18 @@ static ssize_t pqi_sas_ncq_prio_enable_store(struct device *dev,
return strlen(buf);
}
+static ssize_t pqi_numa_node_show(struct device *dev,
+ struct device_attribute *attr, char *buffer)
+{
+ struct scsi_device *sdev;
+ struct pqi_ctrl_info *ctrl_info;
+
+ sdev = to_scsi_device(dev);
+ ctrl_info = shost_to_hba(sdev->host);
+
+ return scnprintf(buffer, PAGE_SIZE, "%d\n", ctrl_info->numa_node);
+}
+
static DEVICE_ATTR(lunid, 0444, pqi_lunid_show, NULL);
static DEVICE_ATTR(unique_id, 0444, pqi_unique_id_show, NULL);
static DEVICE_ATTR(path_info, 0444, pqi_path_info_show, NULL);
@@ -7388,6 +7337,7 @@ static DEVICE_ATTR(raid_level, 0444, pqi_raid_level_show, NULL);
static DEVICE_ATTR(raid_bypass_cnt, 0444, pqi_raid_bypass_cnt_show, NULL);
static DEVICE_ATTR(sas_ncq_prio_enable, 0644,
pqi_sas_ncq_prio_enable_show, pqi_sas_ncq_prio_enable_store);
+static DEVICE_ATTR(numa_node, 0444, pqi_numa_node_show, NULL);
static struct attribute *pqi_sdev_attrs[] = {
&dev_attr_lunid.attr,
@@ -7398,6 +7348,7 @@ static struct attribute *pqi_sdev_attrs[] = {
&dev_attr_raid_level.attr,
&dev_attr_raid_bypass_cnt.attr,
&dev_attr_sas_ncq_prio_enable.attr,
+ &dev_attr_numa_node.attr,
NULL
};
@@ -7716,8 +7667,8 @@ static int pqi_enable_firmware_features(struct pqi_ctrl_info *ctrl_info,
features_requested_iomem_addr +
(le16_to_cpu(firmware_features->num_elements) * 2) +
sizeof(__le16);
- writew(PQI_FIRMWARE_FEATURE_MAXIMUM,
- host_max_known_feature_iomem_addr);
+ writeb(PQI_FIRMWARE_FEATURE_MAXIMUM & 0xFF, host_max_known_feature_iomem_addr);
+ writeb((PQI_FIRMWARE_FEATURE_MAXIMUM & 0xFF00) >> 8, host_max_known_feature_iomem_addr + 1);
}
return pqi_config_table_update(ctrl_info,
@@ -8560,7 +8511,7 @@ static int pqi_pci_init(struct pqi_ctrl_info *ctrl_info)
ctrl_info->iomem_base = ioremap(pci_resource_start(
ctrl_info->pci_dev, 0),
- sizeof(struct pqi_ctrl_registers));
+ pci_resource_len(ctrl_info->pci_dev, 0));
if (!ctrl_info->iomem_base) {
dev_err(&ctrl_info->pci_dev->dev,
"failed to map memory for controller registers\n");
@@ -9018,6 +8969,7 @@ static int pqi_pci_probe(struct pci_dev *pci_dev,
"failed to allocate controller info block\n");
return -ENOMEM;
}
+ ctrl_info->numa_node = node;
ctrl_info->pci_dev = pci_dev;
@@ -9929,6 +9881,18 @@ static const struct pci_device_id pqi_pci_id_table[] = {
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1cf2, 0x0804)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1cf2, 0x0805)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1cf2, 0x0806)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x1cf2, 0x5445)
},
{
@@ -9965,6 +9929,18 @@ static const struct pci_device_id pqi_pci_id_table[] = {
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1cf2, 0x54da)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1cf2, 0x54db)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1cf2, 0x54dc)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x1cf2, 0x0b27)
},
{
@@ -10017,6 +9993,10 @@ static const struct pci_device_id pqi_pci_id_table[] = {
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1014, 0x0718)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x1e93, 0x1000)
},
{
@@ -10029,6 +10009,50 @@ static const struct pci_device_id pqi_pci_id_table[] = {
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1e93, 0x1005)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1f51, 0x1001)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1f51, 0x1002)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1f51, 0x1003)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1f51, 0x1004)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1f51, 0x1005)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1f51, 0x1006)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1f51, 0x1007)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1f51, 0x1008)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1f51, 0x1009)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ 0x1f51, 0x100a)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
PCI_ANY_ID, PCI_ANY_ID)
},
{ 0 }
diff --git a/drivers/scsi/smartpqi/smartpqi_sas_transport.c b/drivers/scsi/smartpqi/smartpqi_sas_transport.c
index 13e8c539010e..a981d0377948 100644
--- a/drivers/scsi/smartpqi/smartpqi_sas_transport.c
+++ b/drivers/scsi/smartpqi/smartpqi_sas_transport.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* driver for Microchip PQI-based storage controllers
- * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries
+ * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
@@ -92,25 +92,23 @@ static int pqi_sas_port_add_rphy(struct pqi_sas_port *pqi_sas_port,
identify = &rphy->identify;
identify->sas_address = pqi_sas_port->sas_address;
+ identify->phy_identifier = pqi_sas_port->device->phy_id;
identify->initiator_port_protocols = SAS_PROTOCOL_ALL;
identify->target_port_protocols = SAS_PROTOCOL_STP;
- if (pqi_sas_port->device) {
- identify->phy_identifier = pqi_sas_port->device->phy_id;
- switch (pqi_sas_port->device->device_type) {
- case SA_DEVICE_TYPE_SAS:
- case SA_DEVICE_TYPE_SES:
- case SA_DEVICE_TYPE_NVME:
- identify->target_port_protocols = SAS_PROTOCOL_SSP;
- break;
- case SA_DEVICE_TYPE_EXPANDER_SMP:
- identify->target_port_protocols = SAS_PROTOCOL_SMP;
- break;
- case SA_DEVICE_TYPE_SATA:
- default:
- break;
- }
+ switch (pqi_sas_port->device->device_type) {
+ case SA_DEVICE_TYPE_SAS:
+ case SA_DEVICE_TYPE_SES:
+ case SA_DEVICE_TYPE_NVME:
+ identify->target_port_protocols = SAS_PROTOCOL_SSP;
+ break;
+ case SA_DEVICE_TYPE_EXPANDER_SMP:
+ identify->target_port_protocols = SAS_PROTOCOL_SMP;
+ break;
+ case SA_DEVICE_TYPE_SATA:
+ default:
+ break;
}
return sas_rphy_add(rphy);
@@ -295,10 +293,12 @@ int pqi_add_sas_device(struct pqi_sas_node *pqi_sas_node,
rc = pqi_sas_port_add_rphy(pqi_sas_port, rphy);
if (rc)
- goto free_sas_port;
+ goto free_sas_rphy;
return 0;
+free_sas_rphy:
+ sas_rphy_free(rphy);
free_sas_port:
pqi_free_sas_port(pqi_sas_port);
device->sas_port = NULL;
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c b/drivers/scsi/smartpqi/smartpqi_sis.c
index 5811fb3c22a9..673437c7152b 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.c
+++ b/drivers/scsi/smartpqi/smartpqi_sis.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* driver for Microchip PQI-based storage controllers
- * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries
+ * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.h b/drivers/scsi/smartpqi/smartpqi_sis.h
index 9dcbae96a5c6..0c97626d87d4 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.h
+++ b/drivers/scsi/smartpqi/smartpqi_sis.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* driver for Microchip PQI-based storage controllers
- * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries
+ * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
diff --git a/drivers/scsi/snic/snic_disc.c b/drivers/scsi/snic/snic_disc.c
index 8fbf3c1b1311..3e2e5783924d 100644
--- a/drivers/scsi/snic/snic_disc.c
+++ b/drivers/scsi/snic/snic_disc.c
@@ -214,7 +214,7 @@ snic_tgt_del(struct work_struct *work)
scsi_flush_work(shost);
/* Block IOs on child devices, stops new IOs */
- scsi_target_block(&tgt->dev);
+ scsi_block_targets(shost, &tgt->dev);
/* Cleanup IOs */
snic_tgt_scsi_abort_io(tgt);
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index ce886c8c9dbe..07ef3db3d1a1 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -825,7 +825,7 @@ static int get_capabilities(struct scsi_cd *cd)
scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr);
/* ask for mode page 0x2a */
- rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, ms_len,
+ rc = scsi_mode_sense(cd->device, 0, 0x2a, 0, buffer, ms_len,
SR_TIMEOUT, 3, &data, NULL);
if (rc < 0 || data.length > ms_len ||
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index ee36a9c15d9c..17491ba10439 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -1286,7 +1286,7 @@ static struct Scsi_Host *sym_attach(const struct scsi_host_template *tpnt, int u
/*
* Edit its name.
*/
- strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name));
+ strscpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name));
sprintf(np->s.inst_name, "sym%d", np->s.unit);
if ((SYM_CONF_DMA_ADDRESSING_MODE > 0) && (np->features & FE_DAC) &&
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 58498da9869a..bd5633667d01 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -338,10 +338,8 @@ static int virtscsi_rescan_hotunplug(struct virtio_scsi *vscsi)
int result, inquiry_len, inq_result_len = 256;
char *inq_result = kmalloc(inq_result_len, GFP_KERNEL);
- if (!inq_result) {
- kfree(inq_result);
+ if (!inq_result)
return -ENOMEM;
- }
shost_for_each_device(sdev, shost) {
inquiry_len = sdev->inquiry_len ? sdev->inquiry_len : 36;
diff --git a/drivers/soc/amlogic/meson-secure-pwrc.c b/drivers/soc/amlogic/meson-secure-pwrc.c
index e93518763526..25b4b71df9b8 100644
--- a/drivers/soc/amlogic/meson-secure-pwrc.c
+++ b/drivers/soc/amlogic/meson-secure-pwrc.c
@@ -105,7 +105,7 @@ static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = {
SEC_PD(ACODEC, 0),
SEC_PD(AUDIO, 0),
SEC_PD(OTP, 0),
- SEC_PD(DMA, 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 */
diff --git a/drivers/soc/fsl/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c
index 74eace3109a1..9e3fddd8f5a9 100644
--- a/drivers/soc/fsl/dpio/dpio-driver.c
+++ b/drivers/soc/fsl/dpio/dpio-driver.c
@@ -270,7 +270,7 @@ static void dpio_teardown_irqs(struct fsl_mc_device *dpio_dev)
fsl_mc_free_irqs(dpio_dev);
}
-static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev)
+static void dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev)
{
struct device *dev;
struct dpio_priv *priv;
@@ -297,14 +297,8 @@ static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev)
dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
- fsl_mc_portal_free(dpio_dev->mc_io);
-
- return 0;
-
err_open:
fsl_mc_portal_free(dpio_dev->mc_io);
-
- return err;
}
static const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = {
diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig
index e0d096607fef..fa9ffbed0e92 100644
--- a/drivers/soc/fsl/qe/Kconfig
+++ b/drivers/soc/fsl/qe/Kconfig
@@ -62,6 +62,7 @@ config QE_TDM
config QE_USB
bool
+ depends on QUICC_ENGINE
default y if USB_FSL_QE
help
QE USB Controller support
diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index 26f3d9a41496..4aa0913817ae 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -1051,7 +1051,6 @@ static struct platform_driver mtk_mutex_driver = {
.probe = mtk_mutex_probe,
.driver = {
.name = "mediatek-mutex",
- .owner = THIS_MODULE,
.of_match_table = mutex_driver_dt_match,
},
};
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index 15789a03e6c6..11095b8de71a 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -47,6 +47,7 @@
/* macro for device wrapper default value */
#define PWRAP_DEW_READ_TEST_VAL 0x5aa5
+#define PWRAP_DEW_COMP_READ_TEST_VAL 0xa55a
#define PWRAP_DEW_WRITE_TEST_VAL 0xa55a
/* macro for manual command */
@@ -169,6 +170,40 @@ static const u32 mt6323_regs[] = {
[PWRAP_DEW_RDDMY_NO] = 0x01a4,
};
+static const u32 mt6331_regs[] = {
+ [PWRAP_DEW_DIO_EN] = 0x018c,
+ [PWRAP_DEW_READ_TEST] = 0x018e,
+ [PWRAP_DEW_WRITE_TEST] = 0x0190,
+ [PWRAP_DEW_CRC_SWRST] = 0x0192,
+ [PWRAP_DEW_CRC_EN] = 0x0194,
+ [PWRAP_DEW_CRC_VAL] = 0x0196,
+ [PWRAP_DEW_MON_GRP_SEL] = 0x0198,
+ [PWRAP_DEW_CIPHER_KEY_SEL] = 0x019a,
+ [PWRAP_DEW_CIPHER_IV_SEL] = 0x019c,
+ [PWRAP_DEW_CIPHER_EN] = 0x019e,
+ [PWRAP_DEW_CIPHER_RDY] = 0x01a0,
+ [PWRAP_DEW_CIPHER_MODE] = 0x01a2,
+ [PWRAP_DEW_CIPHER_SWRST] = 0x01a4,
+ [PWRAP_DEW_RDDMY_NO] = 0x01a6,
+};
+
+static const u32 mt6332_regs[] = {
+ [PWRAP_DEW_DIO_EN] = 0x80f6,
+ [PWRAP_DEW_READ_TEST] = 0x80f8,
+ [PWRAP_DEW_WRITE_TEST] = 0x80fa,
+ [PWRAP_DEW_CRC_SWRST] = 0x80fc,
+ [PWRAP_DEW_CRC_EN] = 0x80fe,
+ [PWRAP_DEW_CRC_VAL] = 0x8100,
+ [PWRAP_DEW_MON_GRP_SEL] = 0x8102,
+ [PWRAP_DEW_CIPHER_KEY_SEL] = 0x8104,
+ [PWRAP_DEW_CIPHER_IV_SEL] = 0x8106,
+ [PWRAP_DEW_CIPHER_EN] = 0x8108,
+ [PWRAP_DEW_CIPHER_RDY] = 0x810a,
+ [PWRAP_DEW_CIPHER_MODE] = 0x810c,
+ [PWRAP_DEW_CIPHER_SWRST] = 0x810e,
+ [PWRAP_DEW_RDDMY_NO] = 0x8110,
+};
+
static const u32 mt6351_regs[] = {
[PWRAP_DEW_DIO_EN] = 0x02F2,
[PWRAP_DEW_READ_TEST] = 0x02F4,
@@ -604,6 +639,91 @@ static int mt6779_regs[] = {
[PWRAP_WACS2_VLDCLR] = 0xC28,
};
+static int mt6795_regs[] = {
+ [PWRAP_MUX_SEL] = 0x0,
+ [PWRAP_WRAP_EN] = 0x4,
+ [PWRAP_DIO_EN] = 0x8,
+ [PWRAP_SIDLY] = 0xc,
+ [PWRAP_RDDMY] = 0x10,
+ [PWRAP_SI_CK_CON] = 0x14,
+ [PWRAP_CSHEXT_WRITE] = 0x18,
+ [PWRAP_CSHEXT_READ] = 0x1c,
+ [PWRAP_CSLEXT_START] = 0x20,
+ [PWRAP_CSLEXT_END] = 0x24,
+ [PWRAP_STAUPD_PRD] = 0x28,
+ [PWRAP_STAUPD_GRPEN] = 0x2c,
+ [PWRAP_EINT_STA0_ADR] = 0x30,
+ [PWRAP_EINT_STA1_ADR] = 0x34,
+ [PWRAP_STAUPD_MAN_TRIG] = 0x40,
+ [PWRAP_STAUPD_STA] = 0x44,
+ [PWRAP_WRAP_STA] = 0x48,
+ [PWRAP_HARB_INIT] = 0x4c,
+ [PWRAP_HARB_HPRIO] = 0x50,
+ [PWRAP_HIPRIO_ARB_EN] = 0x54,
+ [PWRAP_HARB_STA0] = 0x58,
+ [PWRAP_HARB_STA1] = 0x5c,
+ [PWRAP_MAN_EN] = 0x60,
+ [PWRAP_MAN_CMD] = 0x64,
+ [PWRAP_MAN_RDATA] = 0x68,
+ [PWRAP_MAN_VLDCLR] = 0x6c,
+ [PWRAP_WACS0_EN] = 0x70,
+ [PWRAP_INIT_DONE0] = 0x74,
+ [PWRAP_WACS0_CMD] = 0x78,
+ [PWRAP_WACS0_RDATA] = 0x7c,
+ [PWRAP_WACS0_VLDCLR] = 0x80,
+ [PWRAP_WACS1_EN] = 0x84,
+ [PWRAP_INIT_DONE1] = 0x88,
+ [PWRAP_WACS1_CMD] = 0x8c,
+ [PWRAP_WACS1_RDATA] = 0x90,
+ [PWRAP_WACS1_VLDCLR] = 0x94,
+ [PWRAP_WACS2_EN] = 0x98,
+ [PWRAP_INIT_DONE2] = 0x9c,
+ [PWRAP_WACS2_CMD] = 0xa0,
+ [PWRAP_WACS2_RDATA] = 0xa4,
+ [PWRAP_WACS2_VLDCLR] = 0xa8,
+ [PWRAP_INT_EN] = 0xac,
+ [PWRAP_INT_FLG_RAW] = 0xb0,
+ [PWRAP_INT_FLG] = 0xb4,
+ [PWRAP_INT_CLR] = 0xb8,
+ [PWRAP_SIG_ADR] = 0xbc,
+ [PWRAP_SIG_MODE] = 0xc0,
+ [PWRAP_SIG_VALUE] = 0xc4,
+ [PWRAP_SIG_ERRVAL] = 0xc8,
+ [PWRAP_CRC_EN] = 0xcc,
+ [PWRAP_TIMER_EN] = 0xd0,
+ [PWRAP_TIMER_STA] = 0xd4,
+ [PWRAP_WDT_UNIT] = 0xd8,
+ [PWRAP_WDT_SRC_EN] = 0xdc,
+ [PWRAP_WDT_FLG] = 0xe0,
+ [PWRAP_DEBUG_INT_SEL] = 0xe4,
+ [PWRAP_DVFS_ADR0] = 0xe8,
+ [PWRAP_DVFS_WDATA0] = 0xec,
+ [PWRAP_DVFS_ADR1] = 0xf0,
+ [PWRAP_DVFS_WDATA1] = 0xf4,
+ [PWRAP_DVFS_ADR2] = 0xf8,
+ [PWRAP_DVFS_WDATA2] = 0xfc,
+ [PWRAP_DVFS_ADR3] = 0x100,
+ [PWRAP_DVFS_WDATA3] = 0x104,
+ [PWRAP_DVFS_ADR4] = 0x108,
+ [PWRAP_DVFS_WDATA4] = 0x10c,
+ [PWRAP_DVFS_ADR5] = 0x110,
+ [PWRAP_DVFS_WDATA5] = 0x114,
+ [PWRAP_DVFS_ADR6] = 0x118,
+ [PWRAP_DVFS_WDATA6] = 0x11c,
+ [PWRAP_DVFS_ADR7] = 0x120,
+ [PWRAP_DVFS_WDATA7] = 0x124,
+ [PWRAP_SPMINF_STA] = 0x128,
+ [PWRAP_CIPHER_KEY_SEL] = 0x12c,
+ [PWRAP_CIPHER_IV_SEL] = 0x130,
+ [PWRAP_CIPHER_EN] = 0x134,
+ [PWRAP_CIPHER_RDY] = 0x138,
+ [PWRAP_CIPHER_MODE] = 0x13c,
+ [PWRAP_CIPHER_SWRST] = 0x140,
+ [PWRAP_DCM_EN] = 0x144,
+ [PWRAP_DCM_DBC_PRD] = 0x148,
+ [PWRAP_EXT_CK] = 0x14c,
+};
+
static int mt6797_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
@@ -1181,6 +1301,8 @@ static int mt8186_regs[] = {
enum pmic_type {
PMIC_MT6323,
+ PMIC_MT6331,
+ PMIC_MT6332,
PMIC_MT6351,
PMIC_MT6357,
PMIC_MT6358,
@@ -1193,6 +1315,7 @@ enum pwrap_type {
PWRAP_MT2701,
PWRAP_MT6765,
PWRAP_MT6779,
+ PWRAP_MT6795,
PWRAP_MT6797,
PWRAP_MT6873,
PWRAP_MT7622,
@@ -1218,11 +1341,21 @@ struct pwrap_slv_regops {
int (*pwrap_write)(struct pmic_wrapper *wrp, u32 adr, u32 wdata);
};
+/**
+ * struct pwrap_slv_type - PMIC device wrapper definitions
+ * @dew_regs: Device Wrapper (DeW) register offsets
+ * @type: PMIC Type (model)
+ * @comp_dew_regs: Device Wrapper (DeW) register offsets for companion device
+ * @comp_type: Companion PMIC Type (model)
+ * @regops: Register R/W ops
+ * @caps: Capability flags for the target device
+ */
struct pwrap_slv_type {
const u32 *dew_regs;
enum pmic_type type;
+ const u32 *comp_dew_regs;
+ enum pmic_type comp_type;
const struct pwrap_slv_regops *regops;
- /* Flags indicating the capability for the target slave */
u32 caps;
};
@@ -1455,6 +1588,18 @@ static int pwrap_regmap_write(void *context, u32 adr, u32 wdata)
return pwrap_write(context, adr, wdata);
}
+static bool pwrap_pmic_read_test(struct pmic_wrapper *wrp, const u32 *dew_regs,
+ u16 read_test_val)
+{
+ bool is_success;
+ u32 rdata;
+
+ pwrap_read(wrp, dew_regs[PWRAP_DEW_READ_TEST], &rdata);
+ is_success = ((rdata & U16_MAX) == read_test_val);
+
+ return is_success;
+}
+
static int pwrap_reset_spislave(struct pmic_wrapper *wrp)
{
bool tmp;
@@ -1498,18 +1643,18 @@ static int pwrap_reset_spislave(struct pmic_wrapper *wrp)
*/
static int pwrap_init_sidly(struct pmic_wrapper *wrp)
{
- u32 rdata;
u32 i;
u32 pass = 0;
+ bool read_ok;
signed char dly[16] = {
-1, 0, 1, 0, 2, -1, 1, 1, 3, -1, -1, -1, 3, -1, 2, 1
};
for (i = 0; i < 4; i++) {
pwrap_writel(wrp, i, PWRAP_SIDLY);
- pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST],
- &rdata);
- if (rdata == PWRAP_DEW_READ_TEST_VAL) {
+ read_ok = pwrap_pmic_read_test(wrp, wrp->slave->dew_regs,
+ PWRAP_DEW_READ_TEST_VAL);
+ if (read_ok) {
dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i);
pass |= 1 << i;
}
@@ -1529,11 +1674,13 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp)
static int pwrap_init_dual_io(struct pmic_wrapper *wrp)
{
int ret;
- bool tmp;
- u32 rdata;
+ bool read_ok, tmp;
+ bool comp_read_ok = true;
/* Enable dual IO mode */
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1);
+ if (wrp->slave->comp_dew_regs)
+ pwrap_write(wrp, wrp->slave->comp_dew_regs[PWRAP_DEW_DIO_EN], 1);
/* Check IDLE & INIT_DONE in advance */
ret = readx_poll_timeout(pwrap_is_fsm_idle_and_sync_idle, wrp, tmp, tmp,
@@ -1546,12 +1693,15 @@ static int pwrap_init_dual_io(struct pmic_wrapper *wrp)
pwrap_writel(wrp, 1, PWRAP_DIO_EN);
/* Read Test */
- pwrap_read(wrp,
- wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], &rdata);
- if (rdata != PWRAP_DEW_READ_TEST_VAL) {
- dev_err(wrp->dev,
- "Read failed on DIO mode: 0x%04x!=0x%04x\n",
- PWRAP_DEW_READ_TEST_VAL, rdata);
+ read_ok = pwrap_pmic_read_test(wrp, wrp->slave->dew_regs, PWRAP_DEW_READ_TEST_VAL);
+ if (wrp->slave->comp_dew_regs)
+ comp_read_ok = pwrap_pmic_read_test(wrp, wrp->slave->comp_dew_regs,
+ PWRAP_DEW_COMP_READ_TEST_VAL);
+ if (!read_ok || !comp_read_ok) {
+ dev_err(wrp->dev, "Read failed on DIO mode. Main PMIC %s%s\n",
+ !read_ok ? "fail" : "success",
+ wrp->slave->comp_dew_regs && !comp_read_ok ?
+ ", Companion PMIC fail" : "");
return -EFAULT;
}
@@ -1586,6 +1736,20 @@ static void pwrap_init_chip_select_ext(struct pmic_wrapper *wrp, u8 hext_write,
static int pwrap_common_init_reg_clock(struct pmic_wrapper *wrp)
{
switch (wrp->master->type) {
+ case PWRAP_MT6795:
+ if (wrp->slave->type == PMIC_MT6331) {
+ const u32 *dew_regs = wrp->slave->dew_regs;
+
+ pwrap_write(wrp, dew_regs[PWRAP_DEW_RDDMY_NO], 0x8);
+
+ if (wrp->slave->comp_type == PMIC_MT6332) {
+ dew_regs = wrp->slave->comp_dew_regs;
+ pwrap_write(wrp, dew_regs[PWRAP_DEW_RDDMY_NO], 0x8);
+ }
+ }
+ pwrap_writel(wrp, 0x88, PWRAP_RDDMY);
+ pwrap_init_chip_select_ext(wrp, 15, 15, 15, 15);
+ break;
case PWRAP_MT8173:
pwrap_init_chip_select_ext(wrp, 0, 4, 2, 2);
break;
@@ -1626,19 +1790,41 @@ static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp)
return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1;
}
-static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
+static bool __pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp, const u32 *dew_regs)
{
u32 rdata;
int ret;
- ret = pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_RDY],
- &rdata);
+ ret = pwrap_read(wrp, dew_regs[PWRAP_DEW_CIPHER_RDY], &rdata);
if (ret)
return false;
return rdata == 1;
}
+
+static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
+{
+ bool ret = __pwrap_is_pmic_cipher_ready(wrp, wrp->slave->dew_regs);
+
+ if (!ret)
+ return ret;
+
+ /* If there's any companion, wait for it to be ready too */
+ if (wrp->slave->comp_dew_regs)
+ ret = __pwrap_is_pmic_cipher_ready(wrp, wrp->slave->comp_dew_regs);
+
+ return ret;
+}
+
+static void pwrap_config_cipher(struct pmic_wrapper *wrp, const u32 *dew_regs)
+{
+ pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1);
+ pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
+ pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
+ pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
+}
+
static int pwrap_init_cipher(struct pmic_wrapper *wrp)
{
int ret;
@@ -1658,6 +1844,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
case PWRAP_MT2701:
case PWRAP_MT6765:
case PWRAP_MT6779:
+ case PWRAP_MT6795:
case PWRAP_MT6797:
case PWRAP_MT8173:
case PWRAP_MT8186:
@@ -1675,10 +1862,11 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
}
/* Config cipher mode @PMIC */
- pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1);
- pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
- pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
- pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
+ pwrap_config_cipher(wrp, wrp->slave->dew_regs);
+
+ /* If there is any companion PMIC, configure cipher mode there too */
+ if (wrp->slave->comp_type > 0)
+ pwrap_config_cipher(wrp, wrp->slave->comp_dew_regs);
switch (wrp->slave->type) {
case PMIC_MT6397:
@@ -1740,6 +1928,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
static int pwrap_init_security(struct pmic_wrapper *wrp)
{
+ u32 crc_val;
int ret;
/* Enable encryption */
@@ -1748,14 +1937,21 @@ static int pwrap_init_security(struct pmic_wrapper *wrp)
return ret;
/* Signature checking - using CRC */
- if (pwrap_write(wrp,
- wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1))
- return -EFAULT;
+ ret = pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1);
+ if (ret == 0 && wrp->slave->comp_dew_regs)
+ ret = pwrap_write(wrp, wrp->slave->comp_dew_regs[PWRAP_DEW_CRC_EN], 0x1);
pwrap_writel(wrp, 0x1, PWRAP_CRC_EN);
pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE);
- pwrap_writel(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL],
- PWRAP_SIG_ADR);
+
+ /* CRC value */
+ crc_val = wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL];
+ if (wrp->slave->comp_dew_regs)
+ crc_val |= wrp->slave->comp_dew_regs[PWRAP_DEW_CRC_VAL] << 16;
+
+ pwrap_writel(wrp, crc_val, PWRAP_SIG_ADR);
+
+ /* PMIC Wrapper Arbiter priority */
pwrap_writel(wrp,
wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN);
@@ -1819,6 +2015,19 @@ static int pwrap_mt2701_init_soc_specific(struct pmic_wrapper *wrp)
return 0;
}
+static int pwrap_mt6795_init_soc_specific(struct pmic_wrapper *wrp)
+{
+ pwrap_writel(wrp, 0xf, PWRAP_STAUPD_GRPEN);
+
+ if (wrp->slave->type == PMIC_MT6331)
+ pwrap_writel(wrp, 0x1b4, PWRAP_EINT_STA0_ADR);
+
+ if (wrp->slave->comp_type == PMIC_MT6332)
+ pwrap_writel(wrp, 0x8112, PWRAP_EINT_STA1_ADR);
+
+ return 0;
+}
+
static int pwrap_mt7622_init_soc_specific(struct pmic_wrapper *wrp)
{
pwrap_writel(wrp, 0, PWRAP_STAUPD_PRD);
@@ -1854,10 +2063,16 @@ static int pwrap_init(struct pmic_wrapper *wrp)
if (wrp->rstc_bridge)
reset_control_reset(wrp->rstc_bridge);
- if (wrp->master->type == PWRAP_MT8173) {
+ switch (wrp->master->type) {
+ case PWRAP_MT6795:
+ fallthrough;
+ case PWRAP_MT8173:
/* Enable DCM */
pwrap_writel(wrp, 3, PWRAP_DCM_EN);
pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD);
+ break;
+ default:
+ break;
}
if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_SPI)) {
@@ -1982,6 +2197,16 @@ static const struct pwrap_slv_type pmic_mt6323 = {
PWRAP_SLV_CAP_SECURITY,
};
+static const struct pwrap_slv_type pmic_mt6331 = {
+ .dew_regs = mt6331_regs,
+ .type = PMIC_MT6331,
+ .comp_dew_regs = mt6332_regs,
+ .comp_type = PMIC_MT6332,
+ .regops = &pwrap_regops16,
+ .caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO |
+ PWRAP_SLV_CAP_SECURITY,
+};
+
static const struct pwrap_slv_type pmic_mt6351 = {
.dew_regs = mt6351_regs,
.type = PMIC_MT6351,
@@ -2027,6 +2252,7 @@ static const struct pwrap_slv_type pmic_mt6397 = {
static const struct of_device_id of_slave_match_tbl[] = {
{ .compatible = "mediatek,mt6323", .data = &pmic_mt6323 },
+ { .compatible = "mediatek,mt6331", .data = &pmic_mt6331 },
{ .compatible = "mediatek,mt6351", .data = &pmic_mt6351 },
{ .compatible = "mediatek,mt6357", .data = &pmic_mt6357 },
{ .compatible = "mediatek,mt6358", .data = &pmic_mt6358 },
@@ -2079,6 +2305,19 @@ static const struct pmic_wrapper_type pwrap_mt6779 = {
.init_soc_specific = NULL,
};
+static const struct pmic_wrapper_type pwrap_mt6795 = {
+ .regs = mt6795_regs,
+ .type = PWRAP_MT6795,
+ .arb_en_all = 0x3f,
+ .int_en_all = ~(u32)(BIT(31) | BIT(2) | BIT(1)),
+ .int1_en_all = 0,
+ .spi_w = PWRAP_MAN_CMD_SPI_WRITE,
+ .wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD,
+ .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM,
+ .init_reg_clock = pwrap_common_init_reg_clock,
+ .init_soc_specific = pwrap_mt6795_init_soc_specific,
+};
+
static const struct pmic_wrapper_type pwrap_mt6797 = {
.regs = mt6797_regs,
.type = PWRAP_MT6797,
@@ -2212,6 +2451,7 @@ static const struct of_device_id of_pwrap_match_tbl[] = {
{ .compatible = "mediatek,mt2701-pwrap", .data = &pwrap_mt2701 },
{ .compatible = "mediatek,mt6765-pwrap", .data = &pwrap_mt6765 },
{ .compatible = "mediatek,mt6779-pwrap", .data = &pwrap_mt6779 },
+ { .compatible = "mediatek,mt6795-pwrap", .data = &pwrap_mt6795 },
{ .compatible = "mediatek,mt6797-pwrap", .data = &pwrap_mt6797 },
{ .compatible = "mediatek,mt6873-pwrap", .data = &pwrap_mt6873 },
{ .compatible = "mediatek,mt7622-pwrap", .data = &pwrap_mt7622 },
diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c
index 81585733c8a9..3a2f97cd5272 100644
--- a/drivers/soc/mediatek/mtk-svs.c
+++ b/drivers/soc/mediatek/mtk-svs.c
@@ -2061,9 +2061,9 @@ static int svs_mt8192_platform_probe(struct svs_platform *svsp)
svsb = &svsp->banks[idx];
if (svsb->type == SVSB_HIGH)
- svsb->opp_dev = svs_add_device_link(svsp, "mali");
+ svsb->opp_dev = svs_add_device_link(svsp, "gpu");
else if (svsb->type == SVSB_LOW)
- svsb->opp_dev = svs_get_subsys_device(svsp, "mali");
+ svsb->opp_dev = svs_get_subsys_device(svsp, "gpu");
if (IS_ERR(svsb->opp_dev))
return dev_err_probe(svsp->dev, PTR_ERR(svsb->opp_dev),
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index a491718f8064..e597799e8121 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -135,6 +135,17 @@ config QCOM_RMTFS_MEM
Say y here if you intend to boot the modem remoteproc.
+config QCOM_RPM_MASTER_STATS
+ tristate "Qualcomm RPM Master stats"
+ depends on ARCH_QCOM || COMPILE_TEST
+ help
+ The RPM Master sleep stats driver provides detailed per-subsystem
+ sleep/wake data, read from the RPM message RAM. It can be used to
+ assess whether all the low-power modes available are entered as
+ expected or to check which part of the SoC prevents it from sleeping.
+
+ Say y here if you intend to debug or monitor platform sleep.
+
config QCOM_RPMH
tristate "Qualcomm RPM-Hardened (RPMH) Communication"
depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 89b775512bef..99114c71092b 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o
qmi_helpers-y += qmi_encdec.o qmi_interface.o
obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o
obj-$(CONFIG_QCOM_RMTFS_MEM) += rmtfs_mem.o
+obj-$(CONFIG_QCOM_RPM_MASTER_STATS) += rpm_master_stats.o
obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o
qcom_rpmh-y += rpmh-rsc.o
qcom_rpmh-y += rpmh.o
diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c
index f65bfeca7ed6..40068a285913 100644
--- a/drivers/soc/qcom/icc-bwmon.c
+++ b/drivers/soc/qcom/icc-bwmon.c
@@ -806,7 +806,7 @@ static int bwmon_remove(struct platform_device *pdev)
static const struct icc_bwmon_data msm8998_bwmon_data = {
.sample_ms = 4,
- .count_unit_kb = 64,
+ .count_unit_kb = 1024,
.default_highbw_kbps = 4800 * 1024, /* 4.8 GBps */
.default_medbw_kbps = 512 * 1024, /* 512 MBps */
.default_lowbw_kbps = 0,
diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 33dd8c315eb7..6f177e46fa0f 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -210,6 +210,7 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
const struct elf32_hdr *ehdr;
phys_addr_t min_addr = PHYS_ADDR_MAX;
phys_addr_t max_addr = 0;
+ bool relocate = false;
size_t metadata_len;
void *metadata;
int ret;
@@ -224,6 +225,9 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
if (!mdt_phdr_valid(phdr))
continue;
+ if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
+ relocate = true;
+
if (phdr->p_paddr < min_addr)
min_addr = phdr->p_paddr;
@@ -246,11 +250,13 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
goto out;
}
- ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr);
- if (ret) {
- /* Unable to set up relocation */
- dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name);
- goto out;
+ if (relocate) {
+ ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr);
+ if (ret) {
+ /* Unable to set up relocation */
+ dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name);
+ goto out;
+ }
}
out:
@@ -258,6 +264,34 @@ out:
}
EXPORT_SYMBOL_GPL(qcom_mdt_pas_init);
+static bool qcom_mdt_bins_are_split(const struct firmware *fw, const char *fw_name)
+{
+ const struct elf32_phdr *phdrs;
+ const struct elf32_hdr *ehdr;
+ uint64_t seg_start, seg_end;
+ int i;
+
+ ehdr = (struct elf32_hdr *)fw->data;
+ phdrs = (struct elf32_phdr *)(ehdr + 1);
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ /*
+ * The size of the MDT file is not padded to include any
+ * zero-sized segments at the end. Ignore these, as they should
+ * not affect the decision about image being split or not.
+ */
+ if (!phdrs[i].p_filesz)
+ continue;
+
+ seg_start = phdrs[i].p_offset;
+ seg_end = phdrs[i].p_offset + phdrs[i].p_filesz;
+ if (seg_start > fw->size || seg_end > fw->size)
+ return true;
+ }
+
+ return false;
+}
+
static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id, void *mem_region,
phys_addr_t mem_phys, size_t mem_size,
@@ -270,6 +304,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
phys_addr_t min_addr = PHYS_ADDR_MAX;
ssize_t offset;
bool relocate = false;
+ bool is_split;
void *ptr;
int ret = 0;
int i;
@@ -277,6 +312,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
if (!fw || !mem_region || !mem_phys || !mem_size)
return -EINVAL;
+ is_split = qcom_mdt_bins_are_split(fw, fw_name);
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);
@@ -330,8 +366,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
ptr = mem_region + offset;
- if (phdr->p_filesz && phdr->p_offset < fw->size &&
- phdr->p_offset + phdr->p_filesz <= fw->size) {
+ if (phdr->p_filesz && !is_split) {
/* Firmware is large enough to be non-split */
if (phdr->p_offset + phdr->p_filesz > fw->size) {
dev_err(dev, "file %s segment %d would be truncated\n",
diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c
index 199fe9872035..aaddc3cc53b7 100644
--- a/drivers/soc/qcom/ocmem.c
+++ b/drivers/soc/qcom/ocmem.c
@@ -76,6 +76,10 @@ struct ocmem {
#define OCMEM_REG_GFX_MPU_START 0x00001004
#define OCMEM_REG_GFX_MPU_END 0x00001008
+#define OCMEM_HW_VERSION_MAJOR(val) FIELD_GET(GENMASK(31, 28), val)
+#define OCMEM_HW_VERSION_MINOR(val) FIELD_GET(GENMASK(27, 16), val)
+#define OCMEM_HW_VERSION_STEP(val) FIELD_GET(GENMASK(15, 0), val)
+
#define OCMEM_HW_PROFILE_NUM_PORTS(val) FIELD_PREP(0x0000000f, (val))
#define OCMEM_HW_PROFILE_NUM_MACROS(val) FIELD_PREP(0x00003f00, (val))
@@ -355,6 +359,12 @@ static int ocmem_dev_probe(struct platform_device *pdev)
}
}
+ reg = ocmem_read(ocmem, OCMEM_REG_HW_VERSION);
+ dev_dbg(dev, "OCMEM hardware version: %lu.%lu.%lu\n",
+ OCMEM_HW_VERSION_MAJOR(reg),
+ OCMEM_HW_VERSION_MINOR(reg),
+ OCMEM_HW_VERSION_STEP(reg));
+
reg = ocmem_read(ocmem, OCMEM_REG_HW_PROFILE);
ocmem->num_ports = OCMEM_HW_PROFILE_NUM_PORTS(reg);
ocmem->num_macros = OCMEM_HW_PROFILE_NUM_MACROS(reg);
diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c
index 8bf95df0a56a..c87056769ebd 100644
--- a/drivers/soc/qcom/pmic_glink.c
+++ b/drivers/soc/qcom/pmic_glink.c
@@ -338,13 +338,17 @@ static int pmic_glink_remove(struct platform_device *pdev)
return 0;
}
-/* Do not handle altmode for now on those platforms */
static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
+ BIT(PMIC_GLINK_CLIENT_ALTMODE) |
+ BIT(PMIC_GLINK_CLIENT_UCSI);
+
+/* Do not handle altmode for now on those platforms */
+static const unsigned long pmic_glink_sm8550_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
BIT(PMIC_GLINK_CLIENT_UCSI);
static const struct of_device_id pmic_glink_of_match[] = {
{ .compatible = "qcom,sm8450-pmic-glink", .data = &pmic_glink_sm8450_client_mask },
- { .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8450_client_mask },
+ { .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8550_client_mask },
{ .compatible = "qcom,pmic-glink" },
{}
};
diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c
index 4d7895bdeaf2..df48fbea4b68 100644
--- a/drivers/soc/qcom/pmic_glink_altmode.c
+++ b/drivers/soc/qcom/pmic_glink_altmode.c
@@ -369,7 +369,6 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev,
{
struct pmic_glink_altmode_port *alt_port;
struct pmic_glink_altmode *altmode;
- struct typec_altmode_desc mux_desc = {};
const struct of_device_id *match;
struct fwnode_handle *fwnode;
struct device *dev = &adev->dev;
@@ -427,9 +426,7 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev,
alt_port->dp_alt.mode = USB_TYPEC_DP_MODE;
alt_port->dp_alt.active = 1;
- mux_desc.svid = USB_TYPEC_DP_SID;
- mux_desc.mode = USB_TYPEC_DP_MODE;
- alt_port->typec_mux = fwnode_typec_mux_get(fwnode, &mux_desc);
+ alt_port->typec_mux = fwnode_typec_mux_get(fwnode);
if (IS_ERR(alt_port->typec_mux))
return dev_err_probe(dev, PTR_ERR(alt_port->typec_mux),
"failed to acquire mode-switch for port: %d\n",
diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
index dd50a255fa6c..ba788762835f 100644
--- a/drivers/soc/qcom/qcom-geni-se.c
+++ b/drivers/soc/qcom/qcom-geni-se.c
@@ -281,27 +281,14 @@ static void geni_se_select_fifo_mode(struct geni_se *se)
geni_se_irq_clear(se);
- /*
- * The RX path for the UART is asynchronous and so needs more
- * complex logic for enabling / disabling its interrupts.
- *
- * Specific notes:
- * - The done and TX-related interrupts are managed manually.
- * - We don't RX from the main sequencer (we use the secondary) so
- * we don't need the RX-related interrupts enabled in the main
- * sequencer for UART.
- */
+ /* UART driver manages enabling / disabling interrupts internally */
if (proto != GENI_SE_UART) {
+ /* Non-UART use only primary sequencer so dont bother about S_IRQ */
val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN;
val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
-
- val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
- val |= S_CMD_DONE_EN;
- if (val != val_old)
- writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
}
val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
@@ -317,17 +304,14 @@ static void geni_se_select_dma_mode(struct geni_se *se)
geni_se_irq_clear(se);
+ /* UART driver manages enabling / disabling interrupts internally */
if (proto != GENI_SE_UART) {
+ /* Non-UART use only primary sequencer so dont bother about S_IRQ */
val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN);
val &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
-
- val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
- val &= ~S_CMD_DONE_EN;
- if (val != val_old)
- writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
}
val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
@@ -344,10 +328,6 @@ static void geni_se_select_gpi_mode(struct geni_se *se)
writel(0, se->base + SE_IRQ_EN);
- val = readl(se->base + SE_GENI_S_IRQ_EN);
- val &= ~S_CMD_DONE_EN;
- writel(val, se->base + SE_GENI_S_IRQ_EN);
-
val = readl(se->base + SE_GENI_M_IRQ_EN);
val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN |
M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c
index 820bdd9f8e46..78d7361fdcf2 100644
--- a/drivers/soc/qcom/qmi_interface.c
+++ b/drivers/soc/qcom/qmi_interface.c
@@ -650,7 +650,7 @@ int qmi_handle_init(struct qmi_handle *qmi, size_t recv_buf_size,
if (!qmi->recv_buf)
return -ENOMEM;
- qmi->wq = alloc_workqueue("qmi_msg_handler", WQ_UNBOUND, 1);
+ qmi->wq = alloc_ordered_workqueue("qmi_msg_handler", 0);
if (!qmi->wq) {
ret = -ENOMEM;
goto err_free_recv_buf;
diff --git a/drivers/soc/qcom/ramp_controller.c b/drivers/soc/qcom/ramp_controller.c
index 5e3ba0be0903..e9a0cca07189 100644
--- a/drivers/soc/qcom/ramp_controller.c
+++ b/drivers/soc/qcom/ramp_controller.c
@@ -308,12 +308,15 @@ static int qcom_ramp_controller_probe(struct platform_device *pdev)
return qcom_ramp_controller_start(qrc);
}
-static int qcom_ramp_controller_remove(struct platform_device *pdev)
+static void qcom_ramp_controller_remove(struct platform_device *pdev)
{
struct qcom_ramp_controller *qrc = platform_get_drvdata(pdev);
+ int ret;
- return rc_write_cfg(qrc, qrc->desc->cfg_ramp_dis,
- RC_DCVS_CFG_SID, qrc->desc->num_ramp_dis);
+ ret = rc_write_cfg(qrc, qrc->desc->cfg_ramp_dis,
+ RC_DCVS_CFG_SID, qrc->desc->num_ramp_dis);
+ if (ret)
+ dev_err(&pdev->dev, "Failed to send disable sequence\n");
}
static const struct of_device_id qcom_ramp_controller_match_table[] = {
@@ -329,7 +332,7 @@ static struct platform_driver qcom_ramp_controller_driver = {
.suppress_bind_attrs = true,
},
.probe = qcom_ramp_controller_probe,
- .remove = qcom_ramp_controller_remove,
+ .remove_new = qcom_ramp_controller_remove,
};
static int __init qcom_ramp_controller_init(void)
diff --git a/drivers/soc/qcom/rpm_master_stats.c b/drivers/soc/qcom/rpm_master_stats.c
new file mode 100644
index 000000000000..9ca13bcf67d3
--- /dev/null
+++ b/drivers/soc/qcom/rpm_master_stats.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Limited
+ *
+ * This driver supports what is known as "Master Stats v2" in Qualcomm
+ * downstream kernel terms, which seems to be the only version which has
+ * ever shipped, all the way from 2013 to 2023.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+struct master_stats_data {
+ void __iomem *base;
+ const char *label;
+};
+
+struct rpm_master_stats {
+ u32 active_cores;
+ u32 num_shutdowns;
+ u64 shutdown_req;
+ u64 wakeup_idx;
+ u64 bringup_req;
+ u64 bringup_ack;
+ u32 wakeup_reason; /* 0 = "rude wakeup", 1 = scheduled wakeup */
+ u32 last_sleep_trans_dur;
+ u32 last_wake_trans_dur;
+
+ /* Per-subsystem (*not necessarily* SoC-wide) XO shutdown stats */
+ u32 xo_count;
+ u64 xo_last_enter;
+ u64 last_exit;
+ u64 xo_total_dur;
+} __packed;
+
+static int master_stats_show(struct seq_file *s, void *unused)
+{
+ struct master_stats_data *data = s->private;
+ struct rpm_master_stats stat;
+
+ memcpy_fromio(&stat, data->base, sizeof(stat));
+
+ seq_printf(s, "%s:\n", data->label);
+
+ seq_printf(s, "\tLast shutdown @ %llu\n", stat.shutdown_req);
+ seq_printf(s, "\tLast bringup req @ %llu\n", stat.bringup_req);
+ seq_printf(s, "\tLast bringup ack @ %llu\n", stat.bringup_ack);
+ seq_printf(s, "\tLast wakeup idx: %llu\n", stat.wakeup_idx);
+ seq_printf(s, "\tLast XO shutdown enter @ %llu\n", stat.xo_last_enter);
+ seq_printf(s, "\tLast XO shutdown exit @ %llu\n", stat.last_exit);
+ seq_printf(s, "\tXO total duration: %llu\n", stat.xo_total_dur);
+ seq_printf(s, "\tLast sleep transition duration: %u\n", stat.last_sleep_trans_dur);
+ seq_printf(s, "\tLast wake transition duration: %u\n", stat.last_wake_trans_dur);
+ seq_printf(s, "\tXO shutdown count: %u\n", stat.xo_count);
+ seq_printf(s, "\tWakeup reason: 0x%x\n", stat.wakeup_reason);
+ seq_printf(s, "\tShutdown count: %u\n", stat.num_shutdowns);
+ seq_printf(s, "\tActive cores bitmask: 0x%x\n", stat.active_cores);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(master_stats);
+
+static int master_stats_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct master_stats_data *data;
+ struct device_node *msgram_np;
+ struct dentry *dent, *root;
+ struct resource res;
+ int count, i, ret;
+
+ count = of_property_count_strings(dev->of_node, "qcom,master-names");
+ if (count < 0)
+ return count;
+
+ data = devm_kzalloc(dev, count * sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ root = debugfs_create_dir("qcom_rpm_master_stats", NULL);
+ platform_set_drvdata(pdev, root);
+
+ for (i = 0; i < count; i++) {
+ msgram_np = of_parse_phandle(dev->of_node, "qcom,rpm-msg-ram", i);
+ if (!msgram_np) {
+ debugfs_remove_recursive(root);
+ return dev_err_probe(dev, -ENODEV,
+ "Couldn't parse MSG RAM phandle idx %d", i);
+ }
+
+ /*
+ * Purposefully skip devm_platform helpers as we're using a
+ * shared resource.
+ */
+ ret = of_address_to_resource(msgram_np, 0, &res);
+ of_node_put(msgram_np);
+ if (ret < 0) {
+ debugfs_remove_recursive(root);
+ return ret;
+ }
+
+ data[i].base = devm_ioremap(dev, res.start, resource_size(&res));
+ if (!data[i].base) {
+ debugfs_remove_recursive(root);
+ return dev_err_probe(dev, -EINVAL,
+ "Could not map the MSG RAM slice idx %d!\n", i);
+ }
+
+ ret = of_property_read_string_index(dev->of_node, "qcom,master-names", i,
+ &data[i].label);
+ if (ret < 0) {
+ debugfs_remove_recursive(root);
+ return dev_err_probe(dev, ret,
+ "Could not read name idx %d!\n", i);
+ }
+
+ /*
+ * Generally it's not advised to fail on debugfs errors, but this
+ * driver's only job is exposing data therein.
+ */
+ dent = debugfs_create_file(data[i].label, 0444, root,
+ &data[i], &master_stats_fops);
+ if (IS_ERR(dent)) {
+ debugfs_remove_recursive(root);
+ return dev_err_probe(dev, PTR_ERR(dent),
+ "Failed to create debugfs file %s!\n", data[i].label);
+ }
+ }
+
+ device_set_pm_not_required(dev);
+
+ return 0;
+}
+
+static void master_stats_remove(struct platform_device *pdev)
+{
+ struct dentry *root = platform_get_drvdata(pdev);
+
+ debugfs_remove_recursive(root);
+}
+
+static const struct of_device_id rpm_master_table[] = {
+ { .compatible = "qcom,rpm-master-stats" },
+ { },
+};
+
+static struct platform_driver master_stats_driver = {
+ .probe = master_stats_probe,
+ .remove_new = master_stats_remove,
+ .driver = {
+ .name = "qcom_rpm_master_stats",
+ .of_match_table = rpm_master_table,
+ },
+};
+module_platform_driver(master_stats_driver);
+
+MODULE_DESCRIPTION("Qualcomm RPM Master Statistics driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
index f8397dcb146c..99b017fd76b7 100644
--- a/drivers/soc/qcom/rpmpd.c
+++ b/drivers/soc/qcom/rpmpd.c
@@ -892,8 +892,8 @@ static int rpmpd_set_performance(struct generic_pm_domain *domain,
pd->corner = state;
/* Always send updates for vfc and vfl */
- if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
- pd->key != KEY_FLOOR_LEVEL)
+ 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);
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 6be7ea93c78c..b0d59e815c3b 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -14,6 +14,7 @@
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/soc/qcom/smem.h>
+#include <linux/soc/qcom/socinfo.h>
/*
* The Qualcomm shared memory system is a allocate only heap structure that
@@ -500,7 +501,7 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
return ret;
}
-EXPORT_SYMBOL(qcom_smem_alloc);
+EXPORT_SYMBOL_GPL(qcom_smem_alloc);
static void *qcom_smem_get_global(struct qcom_smem *smem,
unsigned item,
@@ -674,7 +675,7 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
return ptr;
}
-EXPORT_SYMBOL(qcom_smem_get);
+EXPORT_SYMBOL_GPL(qcom_smem_get);
/**
* qcom_smem_get_free_space() - retrieve amount of free space in a partition
@@ -719,7 +720,7 @@ int qcom_smem_get_free_space(unsigned host)
return ret;
}
-EXPORT_SYMBOL(qcom_smem_get_free_space);
+EXPORT_SYMBOL_GPL(qcom_smem_get_free_space);
static bool addr_in_range(void __iomem *base, size_t size, void *addr)
{
@@ -770,7 +771,29 @@ phys_addr_t qcom_smem_virt_to_phys(void *p)
return 0;
}
-EXPORT_SYMBOL(qcom_smem_virt_to_phys);
+EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys);
+
+/**
+ * qcom_smem_get_soc_id() - return the SoC ID
+ * @id: On success, we return the SoC ID here.
+ *
+ * Look up SoC ID from HW/SW build ID and return it.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int qcom_smem_get_soc_id(u32 *id)
+{
+ struct socinfo *info;
+
+ info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL);
+ if (IS_ERR(info))
+ return PTR_ERR(info);
+
+ *id = __le32_to_cpu(info->id);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id);
static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
{
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index c2e4a57dd666..4d49945b3a35 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -11,6 +11,7 @@
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/soc/qcom/smem.h>
+#include <linux/soc/qcom/socinfo.h>
#include <linux/string.h>
#include <linux/stringify.h>
#include <linux/sys_soc.h>
@@ -32,15 +33,6 @@
#define qcom_board_id(id) QCOM_ID_ ## id, __stringify(id)
#define qcom_board_id_named(id, name) QCOM_ID_ ## id, (name)
-#define SMEM_SOCINFO_BUILD_ID_LENGTH 32
-#define SMEM_SOCINFO_CHIP_ID_LENGTH 32
-
-/*
- * SMEM item id, used to acquire handles to respective
- * SMEM region.
- */
-#define SMEM_HW_SW_BUILD_ID 137
-
#ifdef CONFIG_DEBUG_FS
#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32
#define SMEM_IMAGE_VERSION_SIZE 4096
@@ -126,64 +118,7 @@ static const char *const pmic_models[] = {
[58] = "PM8450",
[65] = "PM8010",
};
-#endif /* CONFIG_DEBUG_FS */
-/* Socinfo SMEM item structure */
-struct socinfo {
- __le32 fmt;
- __le32 id;
- __le32 ver;
- char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH];
- /* Version 2 */
- __le32 raw_id;
- __le32 raw_ver;
- /* Version 3 */
- __le32 hw_plat;
- /* Version 4 */
- __le32 plat_ver;
- /* Version 5 */
- __le32 accessory_chip;
- /* Version 6 */
- __le32 hw_plat_subtype;
- /* Version 7 */
- __le32 pmic_model;
- __le32 pmic_die_rev;
- /* Version 8 */
- __le32 pmic_model_1;
- __le32 pmic_die_rev_1;
- __le32 pmic_model_2;
- __le32 pmic_die_rev_2;
- /* Version 9 */
- __le32 foundry_id;
- /* Version 10 */
- __le32 serial_num;
- /* Version 11 */
- __le32 num_pmics;
- __le32 pmic_array_offset;
- /* Version 12 */
- __le32 chip_family;
- __le32 raw_device_family;
- __le32 raw_device_num;
- /* Version 13 */
- __le32 nproduct_id;
- char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH];
- /* Version 14 */
- __le32 num_clusters;
- __le32 ncluster_array_offset;
- __le32 num_defective_parts;
- __le32 ndefective_parts_array_offset;
- /* Version 15 */
- __le32 nmodem_supported;
- /* Version 16 */
- __le32 feature_code;
- __le32 pcode;
- __le32 npartnamemap_offset;
- __le32 nnum_partname_mapping;
- /* Version 17 */
- __le32 oem_variant;
-};
-
-#ifdef CONFIG_DEBUG_FS
struct socinfo_params {
u32 raw_device_family;
u32 hw_plat_subtype;
@@ -198,12 +133,15 @@ struct socinfo_params {
u32 nproduct_id;
u32 num_clusters;
u32 ncluster_array_offset;
- u32 num_defective_parts;
- u32 ndefective_parts_array_offset;
+ u32 num_subset_parts;
+ u32 nsubset_parts_array_offset;
u32 nmodem_supported;
u32 feature_code;
u32 pcode;
u32 oem_variant;
+ u32 num_func_clusters;
+ u32 boot_cluster;
+ u32 boot_core;
};
struct smem_image_version {
@@ -434,6 +372,9 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(SM8350) },
{ qcom_board_id(QCM2290) },
{ qcom_board_id(SM6115) },
+ { qcom_board_id(IPQ5010) },
+ { qcom_board_id(IPQ5018) },
+ { qcom_board_id(IPQ5028) },
{ qcom_board_id(SC8280XP) },
{ qcom_board_id(IPQ6005) },
{ qcom_board_id(QRB5165) },
@@ -447,6 +388,9 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id_named(SM8450_3, "SM8450") },
{ qcom_board_id(SC7280) },
{ qcom_board_id(SC7180P) },
+ { qcom_board_id(IPQ5000) },
+ { qcom_board_id(IPQ0509) },
+ { qcom_board_id(IPQ0518) },
{ qcom_board_id(SM6375) },
{ qcom_board_id(IPQ9514) },
{ qcom_board_id(IPQ9550) },
@@ -454,6 +398,7 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(IPQ9570) },
{ qcom_board_id(IPQ9574) },
{ qcom_board_id(SM8550) },
+ { qcom_board_id(IPQ5016) },
{ qcom_board_id(IPQ9510) },
{ qcom_board_id(QRB4210) },
{ qcom_board_id(QRB2210) },
@@ -461,11 +406,15 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(QRU1000) },
{ qcom_board_id(QDU1000) },
{ qcom_board_id(QDU1010) },
+ { qcom_board_id(IPQ5019) },
{ qcom_board_id(QRU1032) },
{ qcom_board_id(QRU1052) },
{ qcom_board_id(QRU1062) },
{ qcom_board_id(IPQ5332) },
{ qcom_board_id(IPQ5322) },
+ { qcom_board_id(IPQ5312) },
+ { qcom_board_id(IPQ5302) },
+ { qcom_board_id(IPQ5300) },
};
static const char *socinfo_machine(struct device *dev, unsigned int id)
@@ -620,6 +569,19 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
&qcom_socinfo->info.fmt);
switch (qcom_socinfo->info.fmt) {
+ case SOCINFO_VERSION(0, 19):
+ qcom_socinfo->info.num_func_clusters = __le32_to_cpu(info->num_func_clusters);
+ qcom_socinfo->info.boot_cluster = __le32_to_cpu(info->boot_cluster);
+ qcom_socinfo->info.boot_core = __le32_to_cpu(info->boot_core);
+
+ debugfs_create_u32("num_func_clusters", 0444, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.num_func_clusters);
+ debugfs_create_u32("boot_cluster", 0444, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.boot_cluster);
+ debugfs_create_u32("boot_core", 0444, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.boot_core);
+ fallthrough;
+ case SOCINFO_VERSION(0, 18):
case SOCINFO_VERSION(0, 17):
qcom_socinfo->info.oem_variant = __le32_to_cpu(info->oem_variant);
debugfs_create_u32("oem_variant", 0444, qcom_socinfo->dbg_root,
@@ -643,17 +605,18 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
case SOCINFO_VERSION(0, 14):
qcom_socinfo->info.num_clusters = __le32_to_cpu(info->num_clusters);
qcom_socinfo->info.ncluster_array_offset = __le32_to_cpu(info->ncluster_array_offset);
- qcom_socinfo->info.num_defective_parts = __le32_to_cpu(info->num_defective_parts);
- qcom_socinfo->info.ndefective_parts_array_offset = __le32_to_cpu(info->ndefective_parts_array_offset);
+ qcom_socinfo->info.num_subset_parts = __le32_to_cpu(info->num_subset_parts);
+ qcom_socinfo->info.nsubset_parts_array_offset =
+ __le32_to_cpu(info->nsubset_parts_array_offset);
debugfs_create_u32("num_clusters", 0444, qcom_socinfo->dbg_root,
&qcom_socinfo->info.num_clusters);
debugfs_create_u32("ncluster_array_offset", 0444, qcom_socinfo->dbg_root,
&qcom_socinfo->info.ncluster_array_offset);
- debugfs_create_u32("num_defective_parts", 0444, qcom_socinfo->dbg_root,
- &qcom_socinfo->info.num_defective_parts);
- debugfs_create_u32("ndefective_parts_array_offset", 0444, qcom_socinfo->dbg_root,
- &qcom_socinfo->info.ndefective_parts_array_offset);
+ debugfs_create_u32("num_subset_parts", 0444, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.num_subset_parts);
+ debugfs_create_u32("nsubset_parts_array_offset", 0444, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.nsubset_parts_array_offset);
fallthrough;
case SOCINFO_VERSION(0, 13):
qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id);
diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c
index e1c7e91f5a86..98fd97da6cd4 100644
--- a/drivers/soc/renesas/rcar-rst.c
+++ b/drivers/soc/renesas/rcar-rst.c
@@ -12,6 +12,7 @@
#define WDTRSTCR_RESET 0xA55A0002
#define WDTRSTCR 0x0054
+#define GEN4_WDTRSTCR 0x0010
#define CR7BAR 0x0070
#define CR7BAREN BIT(4)
@@ -27,6 +28,12 @@ static int rcar_rst_enable_wdt_reset(void __iomem *base)
return 0;
}
+static int rcar_rst_v3u_enable_wdt_reset(void __iomem *base)
+{
+ iowrite32(WDTRSTCR_RESET, base + GEN4_WDTRSTCR);
+ return 0;
+}
+
/*
* Most of the R-Car Gen3 SoCs have an ARM Realtime Core.
* Firmware boot address has to be set in CR7BAR before
@@ -66,6 +73,12 @@ static const struct rst_config rcar_rst_gen3 __initconst = {
.set_rproc_boot_addr = rcar_rst_set_gen3_rproc_boot_addr,
};
+/* V3U firmware doesn't enable WDT reset and there won't be updates anymore */
+static const struct rst_config rcar_rst_v3u __initconst = {
+ .modemr = 0x00, /* MODEMR0 and it has CPG related bits */
+ .configure = rcar_rst_v3u_enable_wdt_reset,
+};
+
static const struct rst_config rcar_rst_gen4 __initconst = {
.modemr = 0x00, /* MODEMR0 and it has CPG related bits */
};
@@ -101,7 +114,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = {
{ .compatible = "renesas,r8a77990-rst", .data = &rcar_rst_gen3 },
{ .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen3 },
/* R-Car Gen4 */
- { .compatible = "renesas,r8a779a0-rst", .data = &rcar_rst_gen4 },
+ { .compatible = "renesas,r8a779a0-rst", .data = &rcar_rst_v3u },
{ .compatible = "renesas,r8a779f0-rst", .data = &rcar_rst_gen4 },
{ .compatible = "renesas,r8a779g0-rst", .data = &rcar_rst_gen4 },
{ /* sentinel */ }
diff --git a/drivers/soc/renesas/rmobile-sysc.c b/drivers/soc/renesas/rmobile-sysc.c
index 728ebac98e14..912daadaa10d 100644
--- a/drivers/soc/renesas/rmobile-sysc.c
+++ b/drivers/soc/renesas/rmobile-sysc.c
@@ -12,6 +12,8 @@
#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>
@@ -19,8 +21,6 @@
#include <linux/pm_domain.h>
#include <linux/slab.h>
-#include <asm/io.h>
-
/* SYSC */
#define SPDCR 0x08 /* SYS Power Down Control Register */
#define SWUCR 0x14 /* SYS Wakeup Control Register */
@@ -47,6 +47,7 @@ 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();
@@ -56,14 +57,10 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
}
if (readl(rmobile_pd->base + PSTR) & mask) {
- unsigned int retry_count;
writel(mask, rmobile_pd->base + SPDCR);
- for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
- if (!(readl(rmobile_pd->base + SPDCR) & mask))
- break;
- cpu_relax();
- }
+ 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,
@@ -74,8 +71,7 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd)
{
- unsigned int mask = BIT(rmobile_pd->bit_shift);
- unsigned int retry_count;
+ unsigned int val, mask = BIT(rmobile_pd->bit_shift);
int ret = 0;
if (readl(rmobile_pd->base + PSTR) & mask)
@@ -83,16 +79,9 @@ static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd)
writel(mask, rmobile_pd->base + SWUCR);
- for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
- if (!(readl(rmobile_pd->base + SWUCR) & mask))
- break;
- if (retry_count > PSTR_RETRIES)
- udelay(PSTR_DELAY_US);
- else
- cpu_relax();
- }
- if (!retry_count)
- ret = -EIO;
+ 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,
diff --git a/drivers/soc/rockchip/dtpm.c b/drivers/soc/rockchip/dtpm.c
index 5a23784b5221..b36d4f752c30 100644
--- a/drivers/soc/rockchip/dtpm.c
+++ b/drivers/soc/rockchip/dtpm.c
@@ -12,33 +12,33 @@
#include <linux/platform_device.h>
static struct dtpm_node __initdata rk3399_hierarchy[] = {
- [0]{ .name = "rk3399",
- .type = DTPM_NODE_VIRTUAL },
- [1]{ .name = "package",
- .type = DTPM_NODE_VIRTUAL,
- .parent = &rk3399_hierarchy[0] },
- [2]{ .name = "/cpus/cpu@0",
- .type = DTPM_NODE_DT,
- .parent = &rk3399_hierarchy[1] },
- [3]{ .name = "/cpus/cpu@1",
- .type = DTPM_NODE_DT,
- .parent = &rk3399_hierarchy[1] },
- [4]{ .name = "/cpus/cpu@2",
- .type = DTPM_NODE_DT,
- .parent = &rk3399_hierarchy[1] },
- [5]{ .name = "/cpus/cpu@3",
- .type = DTPM_NODE_DT,
- .parent = &rk3399_hierarchy[1] },
- [6]{ .name = "/cpus/cpu@100",
- .type = DTPM_NODE_DT,
- .parent = &rk3399_hierarchy[1] },
- [7]{ .name = "/cpus/cpu@101",
- .type = DTPM_NODE_DT,
- .parent = &rk3399_hierarchy[1] },
- [8]{ .name = "/gpu@ff9a0000",
- .type = DTPM_NODE_DT,
- .parent = &rk3399_hierarchy[1] },
- [9]{ /* sentinel */ }
+ [0] = { .name = "rk3399",
+ .type = DTPM_NODE_VIRTUAL },
+ [1] = { .name = "package",
+ .type = DTPM_NODE_VIRTUAL,
+ .parent = &rk3399_hierarchy[0] },
+ [2] = { .name = "/cpus/cpu@0",
+ .type = DTPM_NODE_DT,
+ .parent = &rk3399_hierarchy[1] },
+ [3] = { .name = "/cpus/cpu@1",
+ .type = DTPM_NODE_DT,
+ .parent = &rk3399_hierarchy[1] },
+ [4] = { .name = "/cpus/cpu@2",
+ .type = DTPM_NODE_DT,
+ .parent = &rk3399_hierarchy[1] },
+ [5] = { .name = "/cpus/cpu@3",
+ .type = DTPM_NODE_DT,
+ .parent = &rk3399_hierarchy[1] },
+ [6] = { .name = "/cpus/cpu@100",
+ .type = DTPM_NODE_DT,
+ .parent = &rk3399_hierarchy[1] },
+ [7] = { .name = "/cpus/cpu@101",
+ .type = DTPM_NODE_DT,
+ .parent = &rk3399_hierarchy[1] },
+ [8] = { .name = "/gpu@ff9a0000",
+ .type = DTPM_NODE_DT,
+ .parent = &rk3399_hierarchy[1] },
+ [9] = { /* sentinel */ }
};
static struct of_device_id __initdata rockchip_dtpm_match_table[] = {
diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c
index 84bc022f9e5b..e3de49e671dc 100644
--- a/drivers/soc/rockchip/pm_domains.c
+++ b/drivers/soc/rockchip/pm_domains.c
@@ -43,8 +43,10 @@ struct rockchip_domain_info {
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;
};
@@ -54,6 +56,9 @@ struct rockchip_pmu_info {
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;
@@ -119,13 +124,15 @@ struct rockchip_pmu {
.active_wakeup = wakeup, \
}
-#define DOMAIN_M_O_R(_name, p_offset, pwr, status, r_status, r_offset, req, idle, ack, 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, \
@@ -269,8 +276,8 @@ void rockchip_pmu_unblock(void)
}
EXPORT_SYMBOL_GPL(rockchip_pmu_unblock);
-#define DOMAIN_RK3588(name, p_offset, pwr, status, r_status, r_offset, req, idle, wakeup) \
- DOMAIN_M_O_R(name, p_offset, pwr, status, r_status, r_offset, req, idle, idle, wakeup)
+#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)
{
@@ -408,17 +415,92 @@ static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
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;
+ bool is_on, is_mem_on = false;
if (pd->info->pwr_mask == 0)
return;
- else if (pd->info->pwr_w_mask)
+
+ 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));
@@ -428,6 +510,9 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
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,
@@ -645,7 +730,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
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));
+ 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;
@@ -1024,35 +1111,35 @@ static const struct rockchip_domain_info rk3568_pm_domains[] = {
};
static const struct rockchip_domain_info rk3588_pm_domains[] = {
- [RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, BIT(1), 0x0, BIT(0), BIT(0), false),
- [RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0, 0x0, 0, 0, false),
- [RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0, 0x0, 0, 0, false),
- [RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, BIT(2), 0x0, BIT(1), BIT(1), false),
- [RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, BIT(3), 0x0, BIT(2), BIT(2), false),
- [RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, BIT(4), 0x0, BIT(3), BIT(3), false),
- [RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, BIT(5), 0x0, BIT(4), BIT(4), false),
- [RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, BIT(6), 0x0, BIT(5), BIT(5), false),
- [RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, BIT(7), 0x0, BIT(6), BIT(6), false),
- [RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, BIT(8), 0x0, BIT(7), BIT(7), false),
- [RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, BIT(9), 0x0, BIT(8), BIT(8), false),
- [RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, BIT(10), 0x0, 0, 0, false),
- [RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, BIT(11), 0x0, BIT(9), BIT(9), false),
- [RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, BIT(12), 0x0, BIT(10), BIT(10), false),
- [RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, BIT(13), 0x0, 0, 0, false),
- [RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, BIT(14), 0x0, BIT(11), BIT(11), false),
- [RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, BIT(15), 0x0, BIT(12), BIT(12), false),
- [RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false),
- [RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, BIT(17), 0x0, BIT(15), BIT(15), false),
- [RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, BIT(18), 0x4, BIT(0), BIT(16), false),
- [RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, BIT(19), 0x4, BIT(1), BIT(17), false),
- [RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, BIT(20), 0x4, BIT(5), BIT(21), false),
- [RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, BIT(21), 0x0, 0, 0, false),
- [RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, BIT(22), 0x0, 0, 0, true),
- [RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0, 0x4, BIT(2), BIT(18), false),
- [RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, BIT(23), 0x0, 0, 0, false),
- [RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, BIT(24), 0x4, BIT(3), BIT(19), false),
- [RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, BIT(25), 0x4, BIT(4), BIT(20), true),
- [RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, BIT(26), 0x0, 0, 0, false),
+ [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 = {
@@ -1207,6 +1294,9 @@ static const struct rockchip_pmu_info rk3588_pmu = {
.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),
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index 732c86ce2be8..5b2664da9853 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -57,6 +57,12 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
if (pmu_data->powerdown_conf_extra)
pmu_data->powerdown_conf_extra(mode);
+
+ if (pmu_data->pmu_config_extra) {
+ for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++)
+ pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode],
+ pmu_data->pmu_config_extra[i].offset);
+ }
}
/*
@@ -80,6 +86,9 @@ static const struct of_device_id exynos_pmu_of_device_ids[] = {
.compatible = "samsung,exynos4210-pmu",
.data = exynos_pmu_data_arm_ptr(exynos4210_pmu_data),
}, {
+ .compatible = "samsung,exynos4212-pmu",
+ .data = exynos_pmu_data_arm_ptr(exynos4212_pmu_data),
+ }, {
.compatible = "samsung,exynos4412-pmu",
.data = exynos_pmu_data_arm_ptr(exynos4412_pmu_data),
}, {
diff --git a/drivers/soc/samsung/exynos-pmu.h b/drivers/soc/samsung/exynos-pmu.h
index 5e851f32307e..1c652ffd79b4 100644
--- a/drivers/soc/samsung/exynos-pmu.h
+++ b/drivers/soc/samsung/exynos-pmu.h
@@ -20,6 +20,7 @@ struct exynos_pmu_conf {
struct exynos_pmu_data {
const struct exynos_pmu_conf *pmu_config;
+ const struct exynos_pmu_conf *pmu_config_extra;
void (*pmu_init)(void);
void (*powerdown_conf)(enum sys_powerdown);
@@ -32,6 +33,7 @@ extern void __iomem *pmu_base_addr;
/* list of all exported SoC specific data */
extern const struct exynos_pmu_data exynos3250_pmu_data;
extern const struct exynos_pmu_data exynos4210_pmu_data;
+extern const struct exynos_pmu_data exynos4212_pmu_data;
extern const struct exynos_pmu_data exynos4412_pmu_data;
extern const struct exynos_pmu_data exynos5250_pmu_data;
extern const struct exynos_pmu_data exynos5420_pmu_data;
diff --git a/drivers/soc/samsung/exynos4-pmu.c b/drivers/soc/samsung/exynos4-pmu.c
index cb35103565a6..f8092190b938 100644
--- a/drivers/soc/samsung/exynos4-pmu.c
+++ b/drivers/soc/samsung/exynos4-pmu.c
@@ -86,7 +86,7 @@ static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
{ PMU_TABLE_END,},
};
-static const struct exynos_pmu_conf exynos4412_pmu_config[] = {
+static const struct exynos_pmu_conf exynos4x12_pmu_config[] = {
{ S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } },
{ S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } },
{ S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } },
@@ -191,6 +191,10 @@ static const struct exynos_pmu_conf exynos4412_pmu_config[] = {
{ S5P_GPS_ALIVE_LOWPWR, { 0x7, 0x0, 0x0 } },
{ S5P_CMU_SYSCLK_ISP_LOWPWR, { 0x1, 0x0, 0x0 } },
{ S5P_CMU_SYSCLK_GPS_LOWPWR, { 0x1, 0x0, 0x0 } },
+ { PMU_TABLE_END,},
+};
+
+static const struct exynos_pmu_conf exynos4412_pmu_config[] = {
{ S5P_ARM_CORE2_LOWPWR, { 0x0, 0x0, 0x2 } },
{ S5P_DIS_IRQ_CORE2, { 0x0, 0x0, 0x0 } },
{ S5P_DIS_IRQ_CENTRAL2, { 0x0, 0x0, 0x0 } },
@@ -204,6 +208,11 @@ const struct exynos_pmu_data exynos4210_pmu_data = {
.pmu_config = exynos4210_pmu_config,
};
+const struct exynos_pmu_data exynos4212_pmu_data = {
+ .pmu_config = exynos4x12_pmu_config,
+};
+
const struct exynos_pmu_data exynos4412_pmu_data = {
- .pmu_config = exynos4412_pmu_config,
+ .pmu_config = exynos4x12_pmu_config,
+ .pmu_config_extra = exynos4412_pmu_config,
};
diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig
index 3658fb0f0c5b..6f3098822969 100644
--- a/drivers/soc/tegra/Kconfig
+++ b/drivers/soc/tegra/Kconfig
@@ -125,6 +125,7 @@ config ARCH_TEGRA_234_SOC
bool "NVIDIA Tegra234 SoC"
depends on !CPU_BIG_ENDIAN
select MAILBOX
+ select PINCTRL_TEGRA234
select TEGRA_BPMP
select TEGRA_HSP_MBOX
select TEGRA_IVC
diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c
index 932a03c64534..c759fb7c8adc 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra30.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra30.c
@@ -663,7 +663,7 @@ static const struct nvmem_keepout tegra234_fuse_keepouts[] = {
static const struct tegra_fuse_info tegra234_fuse_info = {
.read = tegra30_fuse_read,
- .size = 0x98c,
+ .size = 0xf90,
.spare = 0x280,
};
diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
index 4591c5bcb690..eb0a1d924526 100644
--- a/drivers/soc/tegra/fuse/tegra-apbmisc.c
+++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/export.h>
@@ -62,6 +62,7 @@ bool tegra_is_silicon(void)
switch (tegra_get_chip_id()) {
case TEGRA194:
case TEGRA234:
+ case TEGRA264:
if (tegra_get_platform() == 0)
return true;
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 5d17799524c9..162f52456f65 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -396,7 +396,6 @@ struct tegra_pmc_soc {
* @clk: pointer to pclk clock
* @soc: pointer to SoC data structure
* @tz_only: flag specifying if the PMC can only be accessed via TrustZone
- * @debugfs: pointer to debugfs entry
* @rate: currently configured rate of pclk
* @suspend_mode: lowest suspend mode available
* @cpu_good_time: CPU power good time (in microseconds)
@@ -431,7 +430,6 @@ struct tegra_pmc {
void __iomem *aotag;
void __iomem *scratch;
struct clk *clk;
- struct dentry *debugfs;
const struct tegra_pmc_soc *soc;
bool tz_only;
@@ -1190,16 +1188,6 @@ static int powergate_show(struct seq_file *s, void *data)
DEFINE_SHOW_ATTRIBUTE(powergate);
-static int tegra_powergate_debugfs_init(void)
-{
- pmc->debugfs = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
- &powergate_fops);
- if (!pmc->debugfs)
- return -ENOMEM;
-
- return 0;
-}
-
static int tegra_powergate_of_get_clks(struct tegra_powergate *pg,
struct device_node *np)
{
@@ -3004,7 +2992,8 @@ static int tegra_pmc_probe(struct platform_device *pdev)
*/
if (pmc->clk) {
pmc->clk_nb.notifier_call = tegra_pmc_clk_notify_cb;
- err = clk_notifier_register(pmc->clk, &pmc->clk_nb);
+ err = devm_clk_notifier_register(&pdev->dev, pmc->clk,
+ &pmc->clk_nb);
if (err) {
dev_err(&pdev->dev,
"failed to register clk notifier\n");
@@ -3026,19 +3015,13 @@ static int tegra_pmc_probe(struct platform_device *pdev)
tegra_pmc_reset_sysfs_init(pmc);
- if (IS_ENABLED(CONFIG_DEBUG_FS)) {
- err = tegra_powergate_debugfs_init();
- if (err < 0)
- goto cleanup_sysfs;
- }
-
err = tegra_pmc_pinctrl_init(pmc);
if (err)
- goto cleanup_debugfs;
+ goto cleanup_sysfs;
err = tegra_pmc_regmap_init(pmc);
if (err < 0)
- goto cleanup_debugfs;
+ goto cleanup_sysfs;
err = tegra_powergate_init(pmc, pdev->dev.of_node);
if (err < 0)
@@ -3061,16 +3044,15 @@ static int tegra_pmc_probe(struct platform_device *pdev)
if (pmc->soc->set_wake_filters)
pmc->soc->set_wake_filters(pmc);
+ debugfs_create_file("powergate", 0444, NULL, NULL, &powergate_fops);
+
return 0;
cleanup_powergates:
tegra_powergate_remove_all(pdev->dev.of_node);
-cleanup_debugfs:
- debugfs_remove(pmc->debugfs);
cleanup_sysfs:
device_remove_file(&pdev->dev, &dev_attr_reset_reason);
device_remove_file(&pdev->dev, &dev_attr_reset_level);
- clk_notifier_unregister(pmc->clk, &pmc->clk_nb);
return err;
}
@@ -4250,6 +4232,7 @@ static const struct tegra_wake_event tegra234_wake_events[] = {
TEGRA_WAKE_GPIO("power", 29, 1, TEGRA234_AON_GPIO(EE, 4)),
TEGRA_WAKE_GPIO("mgbe", 56, 0, TEGRA234_MAIN_GPIO(Y, 3)),
TEGRA_WAKE_IRQ("rtc", 73, 10),
+ TEGRA_WAKE_IRQ("sw-wake", SW_WAKE_ID, 179),
};
static const struct tegra_pmc_soc tegra234_pmc_soc = {
diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig
index 8c2a1036bef5..2cae17b65fd9 100644
--- a/drivers/soc/ti/Kconfig
+++ b/drivers/soc/ti/Kconfig
@@ -85,7 +85,7 @@ config TI_K3_SOCINFO
config TI_PRUSS
tristate "TI PRU-ICSS Subsystem Platform drivers"
- depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3
+ depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST
select MFD_SYSCON
help
TI PRU-ICSS Subsystem platform specific support.
diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c
index 6882c86b3ce5..7fdefee1ed87 100644
--- a/drivers/soc/ti/pruss.c
+++ b/drivers/soc/ti/pruss.c
@@ -6,6 +6,7 @@
* Author(s):
* Suman Anna <s-anna@ti.com>
* Andrew F. Davis <afd@ti.com>
+ * Tero Kristo <t-kristo@ti.com>
*/
#include <linux/clk-provider.h>
@@ -18,7 +19,9 @@
#include <linux/pm_runtime.h>
#include <linux/pruss_driver.h>
#include <linux/regmap.h>
+#include <linux/remoteproc.h>
#include <linux/slab.h>
+#include "pruss.h"
/**
* struct pruss_private_data - PRUSS driver private data
@@ -30,6 +33,257 @@ struct pruss_private_data {
bool has_core_mux_clock;
};
+/**
+ * pruss_get() - get the pruss for a given PRU remoteproc
+ * @rproc: remoteproc handle of a PRU instance
+ *
+ * Finds the parent pruss device for a PRU given the @rproc handle of the
+ * PRU remote processor. This function increments the pruss device's refcount,
+ * so always use pruss_put() to decrement it back once pruss isn't needed
+ * anymore.
+ *
+ * This API doesn't check if @rproc is valid or not. It is expected the caller
+ * will have done a pru_rproc_get() on @rproc, before calling this API to make
+ * sure that @rproc is valid.
+ *
+ * Return: pruss handle on success, and an ERR_PTR on failure using one
+ * of the following error values
+ * -EINVAL if invalid parameter
+ * -ENODEV if PRU device or PRUSS device is not found
+ */
+struct pruss *pruss_get(struct rproc *rproc)
+{
+ struct pruss *pruss;
+ struct device *dev;
+ struct platform_device *ppdev;
+
+ if (IS_ERR_OR_NULL(rproc))
+ return ERR_PTR(-EINVAL);
+
+ dev = &rproc->dev;
+
+ /* make sure it is PRU rproc */
+ if (!dev->parent || !is_pru_rproc(dev->parent))
+ return ERR_PTR(-ENODEV);
+
+ ppdev = to_platform_device(dev->parent->parent);
+ pruss = platform_get_drvdata(ppdev);
+ if (!pruss)
+ return ERR_PTR(-ENODEV);
+
+ get_device(pruss->dev);
+
+ return pruss;
+}
+EXPORT_SYMBOL_GPL(pruss_get);
+
+/**
+ * pruss_put() - decrement pruss device's usecount
+ * @pruss: pruss handle
+ *
+ * Complimentary function for pruss_get(). Needs to be called
+ * after the PRUSS is used, and only if the pruss_get() succeeds.
+ */
+void pruss_put(struct pruss *pruss)
+{
+ if (IS_ERR_OR_NULL(pruss))
+ return;
+
+ put_device(pruss->dev);
+}
+EXPORT_SYMBOL_GPL(pruss_put);
+
+/**
+ * pruss_request_mem_region() - request a memory resource
+ * @pruss: the pruss instance
+ * @mem_id: the memory resource id
+ * @region: pointer to memory region structure to be filled in
+ *
+ * This function allows a client driver to request a memory resource,
+ * and if successful, will let the client driver own the particular
+ * memory region until released using the pruss_release_mem_region()
+ * API.
+ *
+ * Return: 0 if requested memory region is available (in such case pointer to
+ * memory region is returned via @region), an error otherwise
+ */
+int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id,
+ struct pruss_mem_region *region)
+{
+ if (!pruss || !region || mem_id >= PRUSS_MEM_MAX)
+ return -EINVAL;
+
+ mutex_lock(&pruss->lock);
+
+ if (pruss->mem_in_use[mem_id]) {
+ mutex_unlock(&pruss->lock);
+ return -EBUSY;
+ }
+
+ *region = pruss->mem_regions[mem_id];
+ pruss->mem_in_use[mem_id] = region;
+
+ mutex_unlock(&pruss->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pruss_request_mem_region);
+
+/**
+ * pruss_release_mem_region() - release a memory resource
+ * @pruss: the pruss instance
+ * @region: the memory region to release
+ *
+ * This function is the complimentary function to
+ * pruss_request_mem_region(), and allows the client drivers to
+ * release back a memory resource.
+ *
+ * Return: 0 on success, an error code otherwise
+ */
+int pruss_release_mem_region(struct pruss *pruss,
+ struct pruss_mem_region *region)
+{
+ int id;
+
+ if (!pruss || !region)
+ return -EINVAL;
+
+ mutex_lock(&pruss->lock);
+
+ /* find out the memory region being released */
+ for (id = 0; id < PRUSS_MEM_MAX; id++) {
+ if (pruss->mem_in_use[id] == region)
+ break;
+ }
+
+ if (id == PRUSS_MEM_MAX) {
+ mutex_unlock(&pruss->lock);
+ return -EINVAL;
+ }
+
+ pruss->mem_in_use[id] = NULL;
+
+ mutex_unlock(&pruss->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pruss_release_mem_region);
+
+/**
+ * pruss_cfg_get_gpmux() - get the current GPMUX value for a PRU device
+ * @pruss: pruss instance
+ * @pru_id: PRU identifier (0-1)
+ * @mux: pointer to store the current mux value into
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int pruss_cfg_get_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 *mux)
+{
+ int ret;
+ u32 val;
+
+ if (pru_id >= PRUSS_NUM_PRUS || !mux)
+ return -EINVAL;
+
+ ret = pruss_cfg_read(pruss, PRUSS_CFG_GPCFG(pru_id), &val);
+ if (!ret)
+ *mux = (u8)((val & PRUSS_GPCFG_PRU_MUX_SEL_MASK) >>
+ PRUSS_GPCFG_PRU_MUX_SEL_SHIFT);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pruss_cfg_get_gpmux);
+
+/**
+ * pruss_cfg_set_gpmux() - set the GPMUX value for a PRU device
+ * @pruss: pruss instance
+ * @pru_id: PRU identifier (0-1)
+ * @mux: new mux value for PRU
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux)
+{
+ if (mux >= PRUSS_GP_MUX_SEL_MAX ||
+ pru_id >= PRUSS_NUM_PRUS)
+ return -EINVAL;
+
+ return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id),
+ PRUSS_GPCFG_PRU_MUX_SEL_MASK,
+ (u32)mux << PRUSS_GPCFG_PRU_MUX_SEL_SHIFT);
+}
+EXPORT_SYMBOL_GPL(pruss_cfg_set_gpmux);
+
+/**
+ * pruss_cfg_gpimode() - set the GPI mode of the PRU
+ * @pruss: the pruss instance handle
+ * @pru_id: id of the PRU core within the PRUSS
+ * @mode: GPI mode to set
+ *
+ * Sets the GPI mode for a given PRU by programming the
+ * corresponding PRUSS_CFG_GPCFGx register
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int pruss_cfg_gpimode(struct pruss *pruss, enum pruss_pru_id pru_id,
+ enum pruss_gpi_mode mode)
+{
+ if (pru_id >= PRUSS_NUM_PRUS || mode >= PRUSS_GPI_MODE_MAX)
+ return -EINVAL;
+
+ return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id),
+ PRUSS_GPCFG_PRU_GPI_MODE_MASK,
+ mode << PRUSS_GPCFG_PRU_GPI_MODE_SHIFT);
+}
+EXPORT_SYMBOL_GPL(pruss_cfg_gpimode);
+
+/**
+ * pruss_cfg_miirt_enable() - Enable/disable MII RT Events
+ * @pruss: the pruss instance
+ * @enable: enable/disable
+ *
+ * Enable/disable the MII RT Events for the PRUSS.
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int pruss_cfg_miirt_enable(struct pruss *pruss, bool enable)
+{
+ u32 set = enable ? PRUSS_MII_RT_EVENT_EN : 0;
+
+ return pruss_cfg_update(pruss, PRUSS_CFG_MII_RT,
+ PRUSS_MII_RT_EVENT_EN, set);
+}
+EXPORT_SYMBOL_GPL(pruss_cfg_miirt_enable);
+
+/**
+ * pruss_cfg_xfr_enable() - Enable/disable XIN XOUT shift functionality
+ * @pruss: the pruss instance
+ * @pru_type: PRU core type identifier
+ * @enable: enable/disable
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int pruss_cfg_xfr_enable(struct pruss *pruss, enum pru_type pru_type,
+ bool enable)
+{
+ u32 mask, set;
+
+ switch (pru_type) {
+ case PRU_TYPE_PRU:
+ mask = PRUSS_SPP_XFER_SHIFT_EN;
+ break;
+ case PRU_TYPE_RTU:
+ mask = PRUSS_SPP_RTU_XFR_SHIFT_EN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ set = enable ? mask : 0;
+
+ return pruss_cfg_update(pruss, PRUSS_CFG_SPP, mask, set);
+}
+EXPORT_SYMBOL_GPL(pruss_cfg_xfr_enable);
+
static void pruss_of_free_clk_provider(void *data)
{
struct device_node *clk_mux_np = data;
@@ -38,6 +292,11 @@ static void pruss_of_free_clk_provider(void *data)
of_node_put(clk_mux_np);
}
+static void pruss_clk_unregister_mux(void *data)
+{
+ clk_unregister_mux(data);
+}
+
static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux,
char *mux_name, struct device_node *clks_np)
{
@@ -93,8 +352,7 @@ static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux,
goto put_clk_mux_np;
}
- ret = devm_add_action_or_reset(dev, (void(*)(void *))clk_unregister_mux,
- clk_mux);
+ ret = devm_add_action_or_reset(dev, pruss_clk_unregister_mux, clk_mux);
if (ret) {
dev_err(dev, "failed to add clkmux unregister action %d", ret);
goto put_clk_mux_np;
@@ -232,6 +490,7 @@ static int pruss_probe(struct platform_device *pdev)
return -ENOMEM;
pruss->dev = dev;
+ mutex_init(&pruss->lock);
child = of_get_child_by_name(np, "memories");
if (!child) {
diff --git a/drivers/soc/ti/pruss.h b/drivers/soc/ti/pruss.h
new file mode 100644
index 000000000000..6c55987e0e55
--- /dev/null
+++ b/drivers/soc/ti/pruss.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * PRU-ICSS Subsystem user interfaces
+ *
+ * Copyright (C) 2015-2023 Texas Instruments Incorporated - http://www.ti.com
+ * MD Danish Anwar <danishanwar@ti.com>
+ */
+
+#ifndef _SOC_TI_PRUSS_H_
+#define _SOC_TI_PRUSS_H_
+
+#include <linux/bits.h>
+#include <linux/regmap.h>
+
+/*
+ * PRU_ICSS_CFG registers
+ * SYSCFG, ISRP, ISP, IESP, IECP, SCRP applicable on AMxxxx devices only
+ */
+#define PRUSS_CFG_REVID 0x00
+#define PRUSS_CFG_SYSCFG 0x04
+#define PRUSS_CFG_GPCFG(x) (0x08 + (x) * 4)
+#define PRUSS_CFG_CGR 0x10
+#define PRUSS_CFG_ISRP 0x14
+#define PRUSS_CFG_ISP 0x18
+#define PRUSS_CFG_IESP 0x1C
+#define PRUSS_CFG_IECP 0x20
+#define PRUSS_CFG_SCRP 0x24
+#define PRUSS_CFG_PMAO 0x28
+#define PRUSS_CFG_MII_RT 0x2C
+#define PRUSS_CFG_IEPCLK 0x30
+#define PRUSS_CFG_SPP 0x34
+#define PRUSS_CFG_PIN_MX 0x40
+
+/* PRUSS_GPCFG register bits */
+#define PRUSS_GPCFG_PRU_GPI_MODE_MASK GENMASK(1, 0)
+#define PRUSS_GPCFG_PRU_GPI_MODE_SHIFT 0
+
+#define PRUSS_GPCFG_PRU_MUX_SEL_SHIFT 26
+#define PRUSS_GPCFG_PRU_MUX_SEL_MASK GENMASK(29, 26)
+
+/* PRUSS_MII_RT register bits */
+#define PRUSS_MII_RT_EVENT_EN BIT(0)
+
+/* PRUSS_SPP register bits */
+#define PRUSS_SPP_XFER_SHIFT_EN BIT(1)
+#define PRUSS_SPP_PRU1_PAD_HP_EN BIT(0)
+#define PRUSS_SPP_RTU_XFR_SHIFT_EN BIT(3)
+
+/**
+ * pruss_cfg_read() - read a PRUSS CFG sub-module register
+ * @pruss: the pruss instance handle
+ * @reg: register offset within the CFG sub-module
+ * @val: pointer to return the value in
+ *
+ * Reads a given register within the PRUSS CFG sub-module and
+ * returns it through the passed-in @val pointer
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+static int pruss_cfg_read(struct pruss *pruss, unsigned int reg, unsigned int *val)
+{
+ if (IS_ERR_OR_NULL(pruss))
+ return -EINVAL;
+
+ return regmap_read(pruss->cfg_regmap, reg, val);
+}
+
+/**
+ * pruss_cfg_update() - configure a PRUSS CFG sub-module register
+ * @pruss: the pruss instance handle
+ * @reg: register offset within the CFG sub-module
+ * @mask: bit mask to use for programming the @val
+ * @val: value to write
+ *
+ * Programs a given register within the PRUSS CFG sub-module
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+static int pruss_cfg_update(struct pruss *pruss, unsigned int reg,
+ unsigned int mask, unsigned int val)
+{
+ if (IS_ERR_OR_NULL(pruss))
+ return -EINVAL;
+
+ return regmap_update_bits(pruss->cfg_regmap, reg, mask, val);
+}
+
+#endif /* _SOC_TI_PRUSS_H_ */
diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c
index da7898239a46..62b2f1464e46 100644
--- a/drivers/soc/ti/smartreflex.c
+++ b/drivers/soc/ti/smartreflex.c
@@ -815,7 +815,6 @@ static int omap_sr_probe(struct platform_device *pdev)
{
struct omap_sr *sr_info;
struct omap_sr_data *pdata = pdev->dev.platform_data;
- struct resource *mem;
struct dentry *nvalue_dir;
int i, ret = 0;
@@ -835,8 +834,7 @@ static int omap_sr_probe(struct platform_device *pdev)
return -EINVAL;
}
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- sr_info->base = devm_ioremap_resource(&pdev->dev, mem);
+ sr_info->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sr_info->base))
return PTR_ERR(sr_info->base);
diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c
index c9197912ec24..3aff106fc11a 100644
--- a/drivers/soc/ti/wkup_m3_ipc.c
+++ b/drivers/soc/ti/wkup_m3_ipc.c
@@ -202,7 +202,7 @@ static int wkup_m3_ipc_dbg_init(struct wkup_m3_ipc *m3_ipc)
{
m3_ipc->dbg_path = debugfs_create_dir("wkup_m3_ipc", NULL);
- if (!m3_ipc->dbg_path)
+ if (IS_ERR(m3_ipc->dbg_path))
return -EINVAL;
(void)debugfs_create_file("enable_late_halt", 0644,
diff --git a/drivers/soc/xilinx/xlnx_event_manager.c b/drivers/soc/xilinx/xlnx_event_manager.c
index c76381899ef4..f9d9b82b562d 100644
--- a/drivers/soc/xilinx/xlnx_event_manager.c
+++ b/drivers/soc/xilinx/xlnx_event_manager.c
@@ -192,11 +192,12 @@ static int xlnx_remove_cb_for_suspend(event_cb_func_t cb_fun)
struct registered_event_data *eve_data;
struct agent_cb *cb_pos;
struct agent_cb *cb_next;
+ struct hlist_node *tmp;
is_need_to_unregister = false;
/* Check for existing entry in hash table for given cb_type */
- hash_for_each_possible(reg_driver_map, eve_data, hentry, PM_INIT_SUSPEND_CB) {
+ hash_for_each_possible_safe(reg_driver_map, eve_data, tmp, hentry, PM_INIT_SUSPEND_CB) {
if (eve_data->cb_type == PM_INIT_SUSPEND_CB) {
/* Delete the list of callback */
list_for_each_entry_safe(cb_pos, cb_next, &eve_data->cb_list_head, list) {
@@ -228,11 +229,12 @@ static int xlnx_remove_cb_for_notify_event(const u32 node_id, const u32 event,
u64 key = ((u64)node_id << 32U) | (u64)event;
struct agent_cb *cb_pos;
struct agent_cb *cb_next;
+ struct hlist_node *tmp;
is_need_to_unregister = false;
/* Check for existing entry in hash table for given key id */
- hash_for_each_possible(reg_driver_map, eve_data, hentry, key) {
+ hash_for_each_possible_safe(reg_driver_map, eve_data, tmp, hentry, key) {
if (eve_data->key == key) {
/* Delete the list of callback */
list_for_each_entry_safe(cb_pos, cb_next, &eve_data->cb_list_head, list) {
diff --git a/drivers/soc/xilinx/zynqmp_power.c b/drivers/soc/xilinx/zynqmp_power.c
index 78a8a7545d1e..641dcc958911 100644
--- a/drivers/soc/xilinx/zynqmp_power.c
+++ b/drivers/soc/xilinx/zynqmp_power.c
@@ -218,7 +218,7 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
} else if (ret != -EACCES && ret != -ENODEV) {
dev_err(&pdev->dev, "Failed to Register with Xilinx Event manager %d\n", ret);
return ret;
- } else if (of_find_property(pdev->dev.of_node, "mboxes", NULL)) {
+ } else if (of_property_present(pdev->dev.of_node, "mboxes")) {
zynqmp_pm_init_suspend_work =
devm_kzalloc(&pdev->dev,
sizeof(struct zynqmp_pm_work_struct),
@@ -240,7 +240,7 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Failed to request rx channel\n");
return PTR_ERR(rx_chan);
}
- } else if (of_find_property(pdev->dev.of_node, "interrupts", NULL)) {
+ } else if (of_property_present(pdev->dev.of_node, "interrupts")) {
irq = platform_get_irq(pdev, 0);
if (irq <= 0)
return -ENXIO;
diff --git a/drivers/soundwire/Kconfig b/drivers/soundwire/Kconfig
index fa71c9a36df7..4d8f3b7024ae 100644
--- a/drivers/soundwire/Kconfig
+++ b/drivers/soundwire/Kconfig
@@ -37,6 +37,7 @@ config SOUNDWIRE_INTEL
select SOUNDWIRE_GENERIC_ALLOCATION
select AUXILIARY_BUS
depends on ACPI && SND_SOC
+ depends on SND_SOC_SOF_HDA_MLINK || !SND_SOC_SOF_HDA_MLINK
help
SoundWire Intel Master driver.
If you have an Intel platform which has a SoundWire Master then
diff --git a/drivers/soundwire/Makefile b/drivers/soundwire/Makefile
index 925566ff4272..c3d3ab3262d3 100644
--- a/drivers/soundwire/Makefile
+++ b/drivers/soundwire/Makefile
@@ -24,7 +24,8 @@ soundwire-cadence-y := cadence_master.o
obj-$(CONFIG_SOUNDWIRE_CADENCE) += soundwire-cadence.o
#Intel driver
-soundwire-intel-y := intel.o intel_auxdevice.o intel_init.o dmi-quirks.o \
+soundwire-intel-y := intel.o intel_ace2x.o intel_ace2x_debugfs.o \
+ intel_auxdevice.o intel_init.o dmi-quirks.o \
intel_bus_common.o
obj-$(CONFIG_SOUNDWIRE_INTEL) += soundwire-intel.o
diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c
index 9fb7f91ca182..08aeb7ed00e1 100644
--- a/drivers/soundwire/amd_manager.c
+++ b/drivers/soundwire/amd_manager.c
@@ -972,15 +972,18 @@ static int amd_sdw_manager_probe(struct platform_device *pdev)
return 0;
}
-static int amd_sdw_manager_remove(struct platform_device *pdev)
+static void amd_sdw_manager_remove(struct platform_device *pdev)
{
struct amd_sdw_manager *amd_manager = dev_get_drvdata(&pdev->dev);
+ int ret;
pm_runtime_disable(&pdev->dev);
cancel_work_sync(&amd_manager->probe_work);
amd_disable_sdw_interrupts(amd_manager);
sdw_bus_master_delete(&amd_manager->bus);
- return amd_disable_sdw_manager(amd_manager);
+ ret = amd_disable_sdw_manager(amd_manager);
+ if (ret)
+ dev_err(&pdev->dev, "Failed to disable device (%pe)\n", ERR_PTR(ret));
}
static int amd_sdw_clock_stop(struct amd_sdw_manager *amd_manager)
@@ -1194,7 +1197,7 @@ static const struct dev_pm_ops amd_pm = {
static struct platform_driver amd_sdw_driver = {
.probe = &amd_sdw_manager_probe,
- .remove = &amd_sdw_manager_remove,
+ .remove_new = &amd_sdw_manager_remove,
.driver = {
.name = "amd_sdw_manager",
.pm = &amd_pm,
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index 1ea6a64f8c4a..dba920ec88f6 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -69,8 +69,17 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
return -EINVAL;
}
- mutex_init(&bus->msg_lock);
- mutex_init(&bus->bus_lock);
+ /*
+ * Give each bus_lock and msg_lock a unique key so that lockdep won't
+ * trigger a deadlock warning when the locks of several buses are
+ * grabbed during configuration of a multi-bus stream.
+ */
+ lockdep_register_key(&bus->msg_lock_key);
+ __mutex_init(&bus->msg_lock, "msg_lock", &bus->msg_lock_key);
+
+ lockdep_register_key(&bus->bus_lock_key);
+ __mutex_init(&bus->bus_lock, "bus_lock", &bus->bus_lock_key);
+
INIT_LIST_HEAD(&bus->slaves);
INIT_LIST_HEAD(&bus->m_rt_list);
@@ -181,6 +190,8 @@ void sdw_bus_master_delete(struct sdw_bus *bus)
sdw_master_device_del(bus);
sdw_bus_debugfs_exit(bus);
+ lockdep_unregister_key(&bus->bus_lock_key);
+ lockdep_unregister_key(&bus->msg_lock_key);
ida_free(&sdw_bus_ida, bus->id);
}
EXPORT_SYMBOL(sdw_bus_master_delete);
@@ -769,6 +780,9 @@ static int sdw_assign_device_num(struct sdw_slave *slave)
/* After xfer of msg, restore dev_num */
slave->dev_num = slave->dev_num_sticky;
+ if (bus->ops && bus->ops->new_peripheral_assigned)
+ bus->ops->new_peripheral_assigned(bus, dev_num);
+
return 0;
}
@@ -1588,7 +1602,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
unsigned long port;
bool slave_notify;
u8 sdca_cascade = 0;
- u8 buf, buf2[2], _buf, _buf2[2];
+ u8 buf, buf2[2];
bool parity_check;
bool parity_quirk;
@@ -1745,9 +1759,9 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
"SDW_SCP_INT1 recheck read failed:%d\n", ret);
goto io_err;
}
- _buf = ret;
+ buf = ret;
- ret = sdw_nread_no_pm(slave, SDW_SCP_INTSTAT2, 2, _buf2);
+ ret = sdw_nread_no_pm(slave, SDW_SCP_INTSTAT2, 2, buf2);
if (ret < 0) {
dev_err(&slave->dev,
"SDW_SCP_INT2/3 recheck read failed:%d\n", ret);
@@ -1765,12 +1779,8 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
}
/*
- * Make sure no interrupts are pending, but filter to limit loop
- * to interrupts identified in the first status read
+ * Make sure no interrupts are pending
*/
- buf &= _buf;
- buf2[0] &= _buf2[0];
- buf2[1] &= _buf2[1];
stat = buf || buf2[0] || buf2[1] || sdca_cascade;
/*
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c
index 39502bc75712..0efc1c3bee5f 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -283,6 +283,29 @@ static int cdns_config_update(struct sdw_cdns *cdns)
return ret;
}
+/**
+ * sdw_cdns_config_update() - Update configurations
+ * @cdns: Cadence instance
+ */
+void sdw_cdns_config_update(struct sdw_cdns *cdns)
+{
+ /* commit changes */
+ cdns_writel(cdns, CDNS_MCP_CONFIG_UPDATE, CDNS_MCP_CONFIG_UPDATE_BIT);
+}
+EXPORT_SYMBOL(sdw_cdns_config_update);
+
+/**
+ * sdw_cdns_config_update_set_wait() - wait until configuration update bit is self-cleared
+ * @cdns: Cadence instance
+ */
+int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns)
+{
+ /* the hardware recommendation is to wait at least 300us */
+ return cdns_set_wait(cdns, CDNS_MCP_CONFIG_UPDATE,
+ CDNS_MCP_CONFIG_UPDATE_BIT, 0);
+}
+EXPORT_SYMBOL(sdw_cdns_config_update_set_wait);
+
/*
* debugfs
*/
@@ -433,9 +456,9 @@ static int cdns_parity_error_injection(void *data, u64 value)
CDNS_IP_MCP_CMDCTRL_INSERT_PARITY_ERR);
/* commit changes */
- cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE,
- CDNS_MCP_CONFIG_UPDATE_BIT,
- CDNS_MCP_CONFIG_UPDATE_BIT);
+ ret = cdns_clear_bit(cdns, CDNS_MCP_CONFIG_UPDATE, CDNS_MCP_CONFIG_UPDATE_BIT);
+ if (ret < 0)
+ goto unlock;
/* do a broadcast dummy read to avoid bus clashes */
ret = sdw_bread_no_pm_unlocked(&cdns->bus, 0xf, SDW_SCP_DEVID_0);
@@ -447,16 +470,17 @@ static int cdns_parity_error_injection(void *data, u64 value)
0);
/* commit changes */
- cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE,
- CDNS_MCP_CONFIG_UPDATE_BIT,
- CDNS_MCP_CONFIG_UPDATE_BIT);
-
- /* Continue bus operation with parity error injection disabled */
- mutex_unlock(&bus->bus_lock);
+ ret = cdns_clear_bit(cdns, CDNS_MCP_CONFIG_UPDATE, CDNS_MCP_CONFIG_UPDATE_BIT);
+ if (ret < 0)
+ goto unlock;
/* Userspace changed the hardware state behind the kernel's back */
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+unlock:
+ /* Continue bus operation with parity error injection disabled */
+ mutex_unlock(&bus->bus_lock);
+
/*
* allow Master device to enter pm_runtime suspend. This may
* also result in Slave devices suspending.
@@ -1116,13 +1140,7 @@ int sdw_cdns_exit_reset(struct sdw_cdns *cdns)
CDNS_MCP_CONTROL_HW_RST);
/* commit changes */
- cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE,
- CDNS_MCP_CONFIG_UPDATE_BIT,
- CDNS_MCP_CONFIG_UPDATE_BIT);
-
- /* don't wait here */
- return 0;
-
+ return cdns_config_update(cdns);
}
EXPORT_SYMBOL(sdw_cdns_exit_reset);
diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h
index 27c56274217f..bc84435e420f 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -14,6 +14,8 @@
*/
#define CDNS_MCP_IP_MAX_CMD_LEN 32
+#define SDW_CADENCE_MCP_IP_OFFSET 0x4000
+
/**
* struct sdw_cdns_pdi: PDI (Physical Data Interface) instance
*
@@ -197,4 +199,7 @@ int cdns_set_sdw_stream(struct snd_soc_dai *dai,
void sdw_cdns_check_self_clearing_bits(struct sdw_cdns *cdns, const char *string,
bool initial_delay, int reset_iterations);
+void sdw_cdns_config_update(struct sdw_cdns *cdns);
+int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns);
+
#endif /* __SDW_CADENCE_H */
diff --git a/drivers/soundwire/debugfs.c b/drivers/soundwire/debugfs.c
index dea782e0edc4..d1553cb77187 100644
--- a/drivers/soundwire/debugfs.c
+++ b/drivers/soundwire/debugfs.c
@@ -56,8 +56,9 @@ static int sdw_slave_reg_show(struct seq_file *s_file, void *data)
if (!buf)
return -ENOMEM;
- ret = pm_runtime_resume_and_get(&slave->dev);
+ ret = pm_runtime_get_sync(&slave->dev);
if (ret < 0 && ret != -EACCES) {
+ pm_runtime_put_noidle(&slave->dev);
kfree(buf);
return ret;
}
@@ -85,10 +86,17 @@ static int sdw_slave_reg_show(struct seq_file *s_file, void *data)
/* SCP registers */
ret += scnprintf(buf + ret, RD_BUF - ret, "\nSCP\n");
- for (i = SDW_SCP_INT1; i <= SDW_SCP_BANKDELAY; i++)
+ for (i = SDW_SCP_INT1; i <= SDW_SCP_BUS_CLOCK_BASE; i++)
ret += sdw_sprintf(slave, buf, ret, i);
for (i = SDW_SCP_DEVID_0; i <= SDW_SCP_DEVID_5; i++)
ret += sdw_sprintf(slave, buf, ret, i);
+ for (i = SDW_SCP_FRAMECTRL_B0; i <= SDW_SCP_BUSCLOCK_SCALE_B0; i++)
+ ret += sdw_sprintf(slave, buf, ret, i);
+ for (i = SDW_SCP_FRAMECTRL_B1; i <= SDW_SCP_BUSCLOCK_SCALE_B1; i++)
+ ret += sdw_sprintf(slave, buf, ret, i);
+ for (i = SDW_SCP_PHY_OUT_CTRL_0; i <= SDW_SCP_PHY_OUT_CTRL_7; i++)
+ ret += sdw_sprintf(slave, buf, ret, i);
+
/*
* SCP Bank 0/1 registers are read-only and cannot be
diff --git a/drivers/soundwire/generic_bandwidth_allocation.c b/drivers/soundwire/generic_bandwidth_allocation.c
index 325c475b6a66..31162f2b5638 100644
--- a/drivers/soundwire/generic_bandwidth_allocation.c
+++ b/drivers/soundwire/generic_bandwidth_allocation.c
@@ -139,20 +139,16 @@ static void _sdw_compute_port_params(struct sdw_bus *bus,
{
struct sdw_master_runtime *m_rt;
int hstop = bus->params.col - 1;
- int block_offset, port_bo, i;
+ int port_bo, i;
/* Run loop for all groups to compute transport parameters */
for (i = 0; i < count; i++) {
port_bo = 1;
- block_offset = 1;
list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) {
- sdw_compute_master_ports(m_rt, &params[i],
- port_bo, hstop);
+ sdw_compute_master_ports(m_rt, &params[i], port_bo, hstop);
- block_offset += m_rt->ch_count *
- m_rt->stream->params.bps;
- port_bo = block_offset;
+ port_bo += m_rt->ch_count * m_rt->stream->params.bps;
}
hstop = hstop - params[i].hwidth;
diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 238acf5c97a9..26d8485427dd 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -260,7 +260,7 @@ static void intel_shim_init(struct sdw_intel *sdw)
{
void __iomem *shim = sdw->link_res->shim;
unsigned int link_id = sdw->instance;
- u16 ioctl = 0, act = 0;
+ u16 ioctl = 0, act;
/* Initialize Shim */
ioctl |= SDW_SHIM_IOCTL_BKE;
@@ -281,6 +281,7 @@ static void intel_shim_init(struct sdw_intel *sdw)
intel_shim_glue_to_master_ip(sdw);
+ act = intel_readw(shim, SDW_SHIM_CTMCTL(link_id));
u16p_replace_bits(&act, 0x1, SDW_SHIM_CTMCTL_DOAIS);
act |= SDW_SHIM_CTMCTL_DACTQE;
act |= SDW_SHIM_CTMCTL_DODS;
@@ -643,7 +644,7 @@ intel_pdi_alh_configure(struct sdw_intel *sdw, struct sdw_cdns_pdi *pdi)
}
static int intel_params_stream(struct sdw_intel *sdw,
- int stream,
+ struct snd_pcm_substream *substream,
struct snd_soc_dai *dai,
struct snd_pcm_hw_params *hw_params,
int link_id, int alh_stream_id)
@@ -651,7 +652,7 @@ static int intel_params_stream(struct sdw_intel *sdw,
struct sdw_intel_link_res *res = sdw->link_res;
struct sdw_intel_stream_params_data params_data;
- params_data.stream = stream; /* direction */
+ params_data.substream = substream;
params_data.dai = dai;
params_data.hw_params = hw_params;
params_data.link_id = link_id;
@@ -663,25 +664,6 @@ static int intel_params_stream(struct sdw_intel *sdw,
return -EIO;
}
-static int intel_free_stream(struct sdw_intel *sdw,
- int stream,
- struct snd_soc_dai *dai,
- int link_id)
-{
- struct sdw_intel_link_res *res = sdw->link_res;
- struct sdw_intel_stream_free_data free_data;
-
- free_data.stream = stream; /* direction */
- free_data.dai = dai;
- free_data.link_id = link_id;
-
- if (res->ops && res->ops->free_stream && res->dev)
- return res->ops->free_stream(res->dev,
- &free_data);
-
- return 0;
-}
-
/*
* DAI routines
*/
@@ -727,7 +709,7 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
dai_runtime->pdi = pdi;
/* Inform DSP about PDI stream number */
- ret = intel_params_stream(sdw, substream->stream, dai, params,
+ ret = intel_params_stream(sdw, substream, dai, params,
sdw->instance,
pdi->intel_alh_id);
if (ret)
@@ -804,7 +786,7 @@ static int intel_prepare(struct snd_pcm_substream *substream,
sdw_cdns_config_stream(cdns, ch, dir, dai_runtime->pdi);
/* Inform DSP about PDI stream number */
- ret = intel_params_stream(sdw, substream->stream, dai,
+ ret = intel_params_stream(sdw, substream, dai,
hw_params,
sdw->instance,
dai_runtime->pdi->intel_alh_id);
@@ -817,7 +799,6 @@ static int
intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
{
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
- struct sdw_intel *sdw = cdns_to_intel(cdns);
struct sdw_cdns_dai_runtime *dai_runtime;
int ret;
@@ -838,12 +819,6 @@ intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
return ret;
}
- ret = intel_free_stream(sdw, substream->stream, dai, sdw->instance);
- if (ret < 0) {
- dev_err(dai->dev, "intel_free_stream: failed %d\n", ret);
- return ret;
- }
-
dai_runtime->pdi = NULL;
return 0;
@@ -871,19 +846,9 @@ static void *intel_get_sdw_stream(struct snd_soc_dai *dai,
static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
{
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
- struct sdw_intel *sdw = cdns_to_intel(cdns);
- struct sdw_intel_link_res *res = sdw->link_res;
struct sdw_cdns_dai_runtime *dai_runtime;
int ret = 0;
- /*
- * The .trigger callback is used to send required IPC to audio
- * firmware. The .free_stream callback will still be called
- * by intel_free_stream() in the TRIGGER_SUSPEND case.
- */
- if (res->ops && res->ops->trigger)
- res->ops->trigger(dai, cmd, substream->stream);
-
dai_runtime = cdns->dai_runtime_array[dai->id];
if (!dai_runtime) {
dev_err(dai->dev, "failed to get dai runtime in %s\n",
@@ -903,7 +868,6 @@ static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct sn
dai_runtime->suspended = true;
- ret = intel_free_stream(sdw, substream->stream, dai, sdw->instance);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -949,9 +913,7 @@ static int intel_component_dais_suspend(struct snd_soc_component *component)
*/
for_each_component_dais(component, dai) {
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
- struct sdw_intel *sdw = cdns_to_intel(cdns);
struct sdw_cdns_dai_runtime *dai_runtime;
- int ret;
dai_runtime = cdns->dai_runtime_array[dai->id];
@@ -961,13 +923,8 @@ static int intel_component_dais_suspend(struct snd_soc_component *component)
if (dai_runtime->suspended)
continue;
- if (dai_runtime->paused) {
+ if (dai_runtime->paused)
dai_runtime->suspended = true;
-
- ret = intel_free_stream(sdw, dai_runtime->direction, dai, sdw->instance);
- if (ret < 0)
- return ret;
- }
}
return 0;
diff --git a/drivers/soundwire/intel.h b/drivers/soundwire/intel.h
index 09d479f2c77b..511932c55216 100644
--- a/drivers/soundwire/intel.h
+++ b/drivers/soundwire/intel.h
@@ -4,13 +4,17 @@
#ifndef __SDW_INTEL_LOCAL_H
#define __SDW_INTEL_LOCAL_H
+struct hdac_bus;
+
/**
* struct sdw_intel_link_res - Soundwire Intel link resource structure,
* typically populated by the controller driver.
* @hw_ops: platform-specific ops
* @mmio_base: mmio base of SoundWire registers
* @registers: Link IO registers base
+ * @ip_offset: offset for MCP_IP registers
* @shim: Audio shim pointer
+ * @shim_vs: Audio vendor-specific shim pointer
* @alh: ALH (Audio Link Hub) pointer
* @irq: Interrupt line
* @ops: Shim callback ops
@@ -21,13 +25,16 @@
* @link_mask: global mask needed for power-up/down sequences
* @cdns: Cadence master descriptor
* @list: used to walk-through all masters exposed by the same controller
+ * @hbus: hdac_bus pointer, needed for power management
*/
struct sdw_intel_link_res {
const struct sdw_intel_hw_ops *hw_ops;
void __iomem *mmio_base; /* not strictly needed, useful for debug */
void __iomem *registers;
+ u32 ip_offset;
void __iomem *shim;
+ void __iomem *shim_vs;
void __iomem *alh;
int irq;
const struct sdw_intel_ops *ops;
@@ -38,6 +45,7 @@ struct sdw_intel_link_res {
u32 link_mask;
struct sdw_cdns *cdns;
struct list_head list;
+ struct hdac_bus *hbus;
};
struct sdw_intel {
@@ -87,6 +95,14 @@ static inline void intel_writew(void __iomem *base, int offset, u16 value)
(sdw)->link_res->hw_ops->cb)
#define SDW_INTEL_OPS(sdw, cb) ((sdw)->link_res->hw_ops->cb)
+#ifdef CONFIG_DEBUG_FS
+void intel_ace2x_debugfs_init(struct sdw_intel *sdw);
+void intel_ace2x_debugfs_exit(struct sdw_intel *sdw);
+#else
+static inline void intel_ace2x_debugfs_init(struct sdw_intel *sdw) {}
+static inline void intel_ace2x_debugfs_exit(struct sdw_intel *sdw) {}
+#endif
+
static inline void sdw_intel_debugfs_init(struct sdw_intel *sdw)
{
if (SDW_INTEL_CHECK_OPS(sdw, debugfs_init))
diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c
new file mode 100644
index 000000000000..1be0bea5f40f
--- /dev/null
+++ b/drivers/soundwire/intel_ace2x.c
@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+// Copyright(c) 2023 Intel Corporation. All rights reserved.
+
+/*
+ * Soundwire Intel ops for LunarLake
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/soundwire/sdw_registers.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_intel.h>
+#include <sound/hda-mlink.h>
+#include "cadence_master.h"
+#include "bus.h"
+#include "intel.h"
+
+/*
+ * shim vendor-specific (vs) ops
+ */
+
+static void intel_shim_vs_init(struct sdw_intel *sdw)
+{
+ void __iomem *shim_vs = sdw->link_res->shim_vs;
+ u16 act = 0;
+
+ u16p_replace_bits(&act, 0x1, SDW_SHIM2_INTEL_VS_ACTMCTL_DOAIS);
+ act |= SDW_SHIM2_INTEL_VS_ACTMCTL_DACTQE;
+ act |= SDW_SHIM2_INTEL_VS_ACTMCTL_DODS;
+ intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_ACTMCTL, act);
+ usleep_range(10, 15);
+}
+
+static int intel_shim_check_wake(struct sdw_intel *sdw)
+{
+ void __iomem *shim_vs;
+ u16 wake_sts;
+
+ shim_vs = sdw->link_res->shim_vs;
+ wake_sts = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_WAKESTS);
+
+ return wake_sts & SDW_SHIM2_INTEL_VS_WAKEEN_PWS;
+}
+
+static void intel_shim_wake(struct sdw_intel *sdw, bool wake_enable)
+{
+ void __iomem *shim_vs = sdw->link_res->shim_vs;
+ u16 wake_en;
+ u16 wake_sts;
+
+ wake_en = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_WAKEEN);
+
+ if (wake_enable) {
+ /* Enable the wakeup */
+ wake_en |= SDW_SHIM2_INTEL_VS_WAKEEN_PWE;
+ intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_WAKEEN, wake_en);
+ } else {
+ /* Disable the wake up interrupt */
+ wake_en &= ~SDW_SHIM2_INTEL_VS_WAKEEN_PWE;
+ intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_WAKEEN, wake_en);
+
+ /* Clear wake status (W1C) */
+ wake_sts = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_WAKESTS);
+ wake_sts |= SDW_SHIM2_INTEL_VS_WAKEEN_PWS;
+ intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_WAKESTS, wake_sts);
+ }
+}
+
+static int intel_link_power_up(struct sdw_intel *sdw)
+{
+ struct sdw_bus *bus = &sdw->cdns.bus;
+ struct sdw_master_prop *prop = &bus->prop;
+ u32 *shim_mask = sdw->link_res->shim_mask;
+ unsigned int link_id = sdw->instance;
+ u32 syncprd;
+ int ret;
+
+ mutex_lock(sdw->link_res->shim_lock);
+
+ if (!*shim_mask) {
+ /* we first need to program the SyncPRD/CPU registers */
+ dev_dbg(sdw->cdns.dev, "first link up, programming SYNCPRD\n");
+
+ if (prop->mclk_freq % 6000000)
+ syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_38_4;
+ else
+ syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24;
+
+ ret = hdac_bus_eml_sdw_set_syncprd_unlocked(sdw->link_res->hbus, syncprd);
+ if (ret < 0) {
+ dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_set_syncprd failed: %d\n",
+ __func__, ret);
+ goto out;
+ }
+ }
+
+ ret = hdac_bus_eml_sdw_power_up_unlocked(sdw->link_res->hbus, link_id);
+ if (ret < 0) {
+ dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_power_up failed: %d\n",
+ __func__, ret);
+ goto out;
+ }
+
+ if (!*shim_mask) {
+ /* SYNCPU will change once link is active */
+ ret = hdac_bus_eml_sdw_wait_syncpu_unlocked(sdw->link_res->hbus);
+ if (ret < 0) {
+ dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_wait_syncpu failed: %d\n",
+ __func__, ret);
+ goto out;
+ }
+ }
+
+ *shim_mask |= BIT(link_id);
+
+ sdw->cdns.link_up = true;
+
+ intel_shim_vs_init(sdw);
+
+out:
+ mutex_unlock(sdw->link_res->shim_lock);
+
+ return ret;
+}
+
+static int intel_link_power_down(struct sdw_intel *sdw)
+{
+ u32 *shim_mask = sdw->link_res->shim_mask;
+ unsigned int link_id = sdw->instance;
+ int ret;
+
+ mutex_lock(sdw->link_res->shim_lock);
+
+ sdw->cdns.link_up = false;
+
+ *shim_mask &= ~BIT(link_id);
+
+ ret = hdac_bus_eml_sdw_power_down_unlocked(sdw->link_res->hbus, link_id);
+ if (ret < 0) {
+ dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_power_down failed: %d\n",
+ __func__, ret);
+
+ /*
+ * we leave the sdw->cdns.link_up flag as false since we've disabled
+ * the link at this point and cannot handle interrupts any longer.
+ */
+ }
+
+ mutex_unlock(sdw->link_res->shim_lock);
+
+ return ret;
+}
+
+static void intel_sync_arm(struct sdw_intel *sdw)
+{
+ unsigned int link_id = sdw->instance;
+
+ mutex_lock(sdw->link_res->shim_lock);
+
+ hdac_bus_eml_sdw_sync_arm_unlocked(sdw->link_res->hbus, link_id);
+
+ mutex_unlock(sdw->link_res->shim_lock);
+}
+
+static int intel_sync_go_unlocked(struct sdw_intel *sdw)
+{
+ int ret;
+
+ ret = hdac_bus_eml_sdw_sync_go_unlocked(sdw->link_res->hbus);
+ if (ret < 0)
+ dev_err(sdw->cdns.dev, "%s: SyncGO clear failed: %d\n", __func__, ret);
+
+ return ret;
+}
+
+static int intel_sync_go(struct sdw_intel *sdw)
+{
+ int ret;
+
+ mutex_lock(sdw->link_res->shim_lock);
+
+ ret = intel_sync_go_unlocked(sdw);
+
+ mutex_unlock(sdw->link_res->shim_lock);
+
+ return ret;
+}
+
+static bool intel_check_cmdsync_unlocked(struct sdw_intel *sdw)
+{
+ return hdac_bus_eml_sdw_check_cmdsync_unlocked(sdw->link_res->hbus);
+}
+
+/*
+ * DAI operations
+ */
+static const struct snd_soc_dai_ops intel_pcm_dai_ops = {
+};
+
+static const struct snd_soc_component_driver dai_component = {
+ .name = "soundwire",
+};
+
+/*
+ * PDI routines
+ */
+static void intel_pdi_init(struct sdw_intel *sdw,
+ struct sdw_cdns_stream_config *config)
+{
+ void __iomem *shim = sdw->link_res->shim;
+ int pcm_cap;
+
+ /* PCM Stream Capability */
+ pcm_cap = intel_readw(shim, SDW_SHIM2_PCMSCAP);
+
+ config->pcm_bd = FIELD_GET(SDW_SHIM2_PCMSCAP_BSS, pcm_cap);
+ config->pcm_in = FIELD_GET(SDW_SHIM2_PCMSCAP_ISS, pcm_cap);
+ config->pcm_out = FIELD_GET(SDW_SHIM2_PCMSCAP_ISS, pcm_cap);
+
+ dev_dbg(sdw->cdns.dev, "PCM cap bd:%d in:%d out:%d\n",
+ config->pcm_bd, config->pcm_in, config->pcm_out);
+}
+
+static int
+intel_pdi_get_ch_cap(struct sdw_intel *sdw, unsigned int pdi_num)
+{
+ void __iomem *shim = sdw->link_res->shim;
+
+ /* zero based values for channel count in register */
+ return intel_readw(shim, SDW_SHIM2_PCMSYCHC(pdi_num)) + 1;
+}
+
+static void intel_pdi_get_ch_update(struct sdw_intel *sdw,
+ struct sdw_cdns_pdi *pdi,
+ unsigned int num_pdi,
+ unsigned int *num_ch)
+{
+ int ch_count = 0;
+ int i;
+
+ for (i = 0; i < num_pdi; i++) {
+ pdi->ch_count = intel_pdi_get_ch_cap(sdw, pdi->num);
+ ch_count += pdi->ch_count;
+ pdi++;
+ }
+
+ *num_ch = ch_count;
+}
+
+static void intel_pdi_stream_ch_update(struct sdw_intel *sdw,
+ struct sdw_cdns_streams *stream)
+{
+ intel_pdi_get_ch_update(sdw, stream->bd, stream->num_bd,
+ &stream->num_ch_bd);
+
+ intel_pdi_get_ch_update(sdw, stream->in, stream->num_in,
+ &stream->num_ch_in);
+
+ intel_pdi_get_ch_update(sdw, stream->out, stream->num_out,
+ &stream->num_ch_out);
+}
+
+static int intel_create_dai(struct sdw_cdns *cdns,
+ struct snd_soc_dai_driver *dais,
+ enum intel_pdi_type type,
+ u32 num, u32 off, u32 max_ch)
+{
+ int i;
+
+ if (!num)
+ return 0;
+
+ for (i = off; i < (off + num); i++) {
+ dais[i].name = devm_kasprintf(cdns->dev, GFP_KERNEL,
+ "SDW%d Pin%d",
+ cdns->instance, i);
+ if (!dais[i].name)
+ return -ENOMEM;
+
+ if (type == INTEL_PDI_BD || type == INTEL_PDI_OUT) {
+ dais[i].playback.channels_min = 1;
+ dais[i].playback.channels_max = max_ch;
+ }
+
+ if (type == INTEL_PDI_BD || type == INTEL_PDI_IN) {
+ dais[i].capture.channels_min = 1;
+ dais[i].capture.channels_max = max_ch;
+ }
+
+ dais[i].ops = &intel_pcm_dai_ops;
+ }
+
+ return 0;
+}
+
+static int intel_register_dai(struct sdw_intel *sdw)
+{
+ struct sdw_cdns_dai_runtime **dai_runtime_array;
+ struct sdw_cdns_stream_config config;
+ struct sdw_cdns *cdns = &sdw->cdns;
+ struct sdw_cdns_streams *stream;
+ struct snd_soc_dai_driver *dais;
+ int num_dai;
+ int ret;
+ int off = 0;
+
+ /* Read the PDI config and initialize cadence PDI */
+ intel_pdi_init(sdw, &config);
+ ret = sdw_cdns_pdi_init(cdns, config);
+ if (ret)
+ return ret;
+
+ intel_pdi_stream_ch_update(sdw, &sdw->cdns.pcm);
+
+ /* DAIs are created based on total number of PDIs supported */
+ num_dai = cdns->pcm.num_pdi;
+
+ dai_runtime_array = devm_kcalloc(cdns->dev, num_dai,
+ sizeof(struct sdw_cdns_dai_runtime *),
+ GFP_KERNEL);
+ if (!dai_runtime_array)
+ return -ENOMEM;
+ cdns->dai_runtime_array = dai_runtime_array;
+
+ dais = devm_kcalloc(cdns->dev, num_dai, sizeof(*dais), GFP_KERNEL);
+ if (!dais)
+ return -ENOMEM;
+
+ /* Create PCM DAIs */
+ stream = &cdns->pcm;
+
+ ret = intel_create_dai(cdns, dais, INTEL_PDI_IN, cdns->pcm.num_in,
+ off, stream->num_ch_in);
+ if (ret)
+ return ret;
+
+ off += cdns->pcm.num_in;
+ ret = intel_create_dai(cdns, dais, INTEL_PDI_OUT, cdns->pcm.num_out,
+ off, stream->num_ch_out);
+ if (ret)
+ return ret;
+
+ off += cdns->pcm.num_out;
+ ret = intel_create_dai(cdns, dais, INTEL_PDI_BD, cdns->pcm.num_bd,
+ off, stream->num_ch_bd);
+ if (ret)
+ return ret;
+
+ return devm_snd_soc_register_component(cdns->dev, &dai_component,
+ dais, num_dai);
+}
+
+static void intel_program_sdi(struct sdw_intel *sdw, int dev_num)
+{
+ int ret;
+
+ ret = hdac_bus_eml_sdw_set_lsdiid(sdw->link_res->hbus, sdw->instance, dev_num);
+ if (ret < 0)
+ dev_err(sdw->cdns.dev, "%s: could not set lsdiid for link %d %d\n",
+ __func__, sdw->instance, dev_num);
+}
+
+const struct sdw_intel_hw_ops sdw_intel_lnl_hw_ops = {
+ .debugfs_init = intel_ace2x_debugfs_init,
+ .debugfs_exit = intel_ace2x_debugfs_exit,
+
+ .register_dai = intel_register_dai,
+
+ .check_clock_stop = intel_check_clock_stop,
+ .start_bus = intel_start_bus,
+ .start_bus_after_reset = intel_start_bus_after_reset,
+ .start_bus_after_clock_stop = intel_start_bus_after_clock_stop,
+ .stop_bus = intel_stop_bus,
+
+ .link_power_up = intel_link_power_up,
+ .link_power_down = intel_link_power_down,
+
+ .shim_check_wake = intel_shim_check_wake,
+ .shim_wake = intel_shim_wake,
+
+ .pre_bank_switch = intel_pre_bank_switch,
+ .post_bank_switch = intel_post_bank_switch,
+
+ .sync_arm = intel_sync_arm,
+ .sync_go_unlocked = intel_sync_go_unlocked,
+ .sync_go = intel_sync_go,
+ .sync_check_cmdsync_unlocked = intel_check_cmdsync_unlocked,
+
+ .program_sdi = intel_program_sdi,
+};
+EXPORT_SYMBOL_NS(sdw_intel_lnl_hw_ops, SOUNDWIRE_INTEL);
+
+MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK);
diff --git a/drivers/soundwire/intel_ace2x_debugfs.c b/drivers/soundwire/intel_ace2x_debugfs.c
new file mode 100644
index 000000000000..3d24661ffd37
--- /dev/null
+++ b/drivers/soundwire/intel_ace2x_debugfs.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright(c) 2023 Intel Corporation. All rights reserved.
+
+#include <linux/acpi.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_intel.h>
+#include <linux/soundwire/sdw_registers.h>
+#include "bus.h"
+#include "cadence_master.h"
+#include "intel.h"
+
+/*
+ * debugfs
+ */
+#ifdef CONFIG_DEBUG_FS
+
+#define RD_BUF (2 * PAGE_SIZE)
+
+static ssize_t intel_sprintf(void __iomem *mem, bool l,
+ char *buf, size_t pos, unsigned int reg)
+{
+ int value;
+
+ if (l)
+ value = intel_readl(mem, reg);
+ else
+ value = intel_readw(mem, reg);
+
+ return scnprintf(buf + pos, RD_BUF - pos, "%4x\t%4x\n", reg, value);
+}
+
+static int intel_reg_show(struct seq_file *s_file, void *data)
+{
+ struct sdw_intel *sdw = s_file->private;
+ void __iomem *s = sdw->link_res->shim;
+ void __iomem *vs_s = sdw->link_res->shim_vs;
+ ssize_t ret;
+ u32 pcm_cap;
+ int pcm_bd;
+ char *buf;
+ int j;
+
+ buf = kzalloc(RD_BUF, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = scnprintf(buf, RD_BUF, "Register Value\n");
+ ret += scnprintf(buf + ret, RD_BUF - ret, "\nShim\n");
+
+ ret += intel_sprintf(s, true, buf, ret, SDW_SHIM2_LECAP);
+ ret += intel_sprintf(s, false, buf, ret, SDW_SHIM2_PCMSCAP);
+
+ pcm_cap = intel_readw(s, SDW_SHIM2_PCMSCAP);
+ pcm_bd = FIELD_GET(SDW_SHIM2_PCMSCAP_BSS, pcm_cap);
+
+ for (j = 0; j < pcm_bd; j++) {
+ ret += intel_sprintf(s, false, buf, ret,
+ SDW_SHIM2_PCMSYCHM(j));
+ ret += intel_sprintf(s, false, buf, ret,
+ SDW_SHIM2_PCMSYCHC(j));
+ }
+
+ ret += scnprintf(buf + ret, RD_BUF - ret, "\nVS CLK controls\n");
+ ret += intel_sprintf(vs_s, true, buf, ret, SDW_SHIM2_INTEL_VS_LVSCTL);
+
+ ret += scnprintf(buf + ret, RD_BUF - ret, "\nVS Wake registers\n");
+ ret += intel_sprintf(vs_s, false, buf, ret, SDW_SHIM2_INTEL_VS_WAKEEN);
+ ret += intel_sprintf(vs_s, false, buf, ret, SDW_SHIM2_INTEL_VS_WAKESTS);
+
+ ret += scnprintf(buf + ret, RD_BUF - ret, "\nVS IOCTL, ACTMCTL\n");
+ ret += intel_sprintf(vs_s, false, buf, ret, SDW_SHIM2_INTEL_VS_IOCTL);
+ ret += intel_sprintf(vs_s, false, buf, ret, SDW_SHIM2_INTEL_VS_ACTMCTL);
+
+ seq_printf(s_file, "%s", buf);
+ kfree(buf);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(intel_reg);
+
+static int intel_set_m_datamode(void *data, u64 value)
+{
+ struct sdw_intel *sdw = data;
+ struct sdw_bus *bus = &sdw->cdns.bus;
+
+ if (value > SDW_PORT_DATA_MODE_STATIC_1)
+ return -EINVAL;
+
+ /* Userspace changed the hardware state behind the kernel's back */
+ add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+
+ bus->params.m_data_mode = value;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(intel_set_m_datamode_fops, NULL,
+ intel_set_m_datamode, "%llu\n");
+
+static int intel_set_s_datamode(void *data, u64 value)
+{
+ struct sdw_intel *sdw = data;
+ struct sdw_bus *bus = &sdw->cdns.bus;
+
+ if (value > SDW_PORT_DATA_MODE_STATIC_1)
+ return -EINVAL;
+
+ /* Userspace changed the hardware state behind the kernel's back */
+ add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+
+ bus->params.s_data_mode = value;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(intel_set_s_datamode_fops, NULL,
+ intel_set_s_datamode, "%llu\n");
+
+void intel_ace2x_debugfs_init(struct sdw_intel *sdw)
+{
+ struct dentry *root = sdw->cdns.bus.debugfs;
+
+ if (!root)
+ return;
+
+ sdw->debugfs = debugfs_create_dir("intel-sdw", root);
+
+ debugfs_create_file("intel-registers", 0400, sdw->debugfs, sdw,
+ &intel_reg_fops);
+
+ debugfs_create_file("intel-m-datamode", 0200, sdw->debugfs, sdw,
+ &intel_set_m_datamode_fops);
+
+ debugfs_create_file("intel-s-datamode", 0200, sdw->debugfs, sdw,
+ &intel_set_s_datamode_fops);
+
+ sdw_cdns_debugfs_init(&sdw->cdns, sdw->debugfs);
+}
+
+void intel_ace2x_debugfs_exit(struct sdw_intel *sdw)
+{
+ debugfs_remove_recursive(sdw->debugfs);
+}
+#endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c
index b21e86084f7b..0daa6ca9a224 100644
--- a/drivers/soundwire/intel_auxdevice.c
+++ b/drivers/soundwire/intel_auxdevice.c
@@ -60,6 +60,21 @@ static int generic_post_bank_switch(struct sdw_bus *bus)
return sdw->link_res->hw_ops->post_bank_switch(sdw);
}
+static void generic_new_peripheral_assigned(struct sdw_bus *bus, int dev_num)
+{
+ struct sdw_cdns *cdns = bus_to_cdns(bus);
+ struct sdw_intel *sdw = cdns_to_intel(cdns);
+
+ /* paranoia check, this should never happen */
+ if (dev_num < INTEL_DEV_NUM_IDA_MIN || dev_num > SDW_MAX_DEVICES) {
+ dev_err(bus->dev, "%s: invalid dev_num %d\n", __func__, dev_num);
+ return;
+ }
+
+ if (sdw->link_res->hw_ops->program_sdi)
+ sdw->link_res->hw_ops->program_sdi(sdw, dev_num);
+}
+
static int sdw_master_read_intel_prop(struct sdw_bus *bus)
{
struct sdw_master_prop *prop = &bus->prop;
@@ -117,6 +132,7 @@ static struct sdw_master_ops sdw_intel_ops = {
.pre_bank_switch = generic_pre_bank_switch,
.post_bank_switch = generic_post_bank_switch,
.read_ping_status = cdns_read_ping_status,
+ .new_peripheral_assigned = generic_new_peripheral_assigned,
};
/*
@@ -144,6 +160,7 @@ static int intel_link_probe(struct auxiliary_device *auxdev,
sdw->link_res = &ldev->link_res;
cdns->dev = dev;
cdns->registers = sdw->link_res->registers;
+ cdns->ip_offset = sdw->link_res->ip_offset;
cdns->instance = sdw->instance;
cdns->msg_count = 0;
diff --git a/drivers/soundwire/intel_bus_common.c b/drivers/soundwire/intel_bus_common.c
index f180e3bea989..e5ac3cc7cb79 100644
--- a/drivers/soundwire/intel_bus_common.c
+++ b/drivers/soundwire/intel_bus_common.c
@@ -16,12 +16,6 @@ int intel_start_bus(struct sdw_intel *sdw)
struct sdw_bus *bus = &cdns->bus;
int ret;
- ret = sdw_cdns_enable_interrupt(cdns, true);
- if (ret < 0) {
- dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret);
- return ret;
- }
-
/*
* follow recommended programming flows to avoid timeouts when
* gsync is enabled
@@ -32,30 +26,41 @@ int intel_start_bus(struct sdw_intel *sdw)
ret = sdw_cdns_init(cdns);
if (ret < 0) {
dev_err(dev, "%s: unable to initialize Cadence IP: %d\n", __func__, ret);
- goto err_interrupt;
+ return ret;
}
- ret = sdw_cdns_exit_reset(cdns);
- if (ret < 0) {
- dev_err(dev, "%s: unable to exit bus reset sequence: %d\n", __func__, ret);
- goto err_interrupt;
- }
+ sdw_cdns_config_update(cdns);
if (bus->multi_link) {
ret = sdw_intel_sync_go(sdw);
if (ret < 0) {
dev_err(dev, "%s: sync go failed: %d\n", __func__, ret);
- goto err_interrupt;
+ return ret;
}
}
+
+ ret = sdw_cdns_config_update_set_wait(cdns);
+ if (ret < 0) {
+ dev_err(dev, "%s: CONFIG_UPDATE BIT still set\n", __func__);
+ return ret;
+ }
+
+ ret = sdw_cdns_exit_reset(cdns);
+ if (ret < 0) {
+ dev_err(dev, "%s: unable to exit bus reset sequence: %d\n", __func__, ret);
+ return ret;
+ }
+
+ ret = sdw_cdns_enable_interrupt(cdns, true);
+ if (ret < 0) {
+ dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret);
+ return ret;
+ }
+
sdw_cdns_check_self_clearing_bits(cdns, __func__,
true, INTEL_MASTER_RESET_ITERATIONS);
return 0;
-
-err_interrupt:
- sdw_cdns_enable_interrupt(cdns, false);
- return ret;
}
int intel_start_bus_after_reset(struct sdw_intel *sdw)
@@ -86,12 +91,6 @@ int intel_start_bus_after_reset(struct sdw_intel *sdw)
status = SDW_UNATTACH_REQUEST_MASTER_RESET;
sdw_clear_slave_status(bus, status);
- ret = sdw_cdns_enable_interrupt(cdns, true);
- if (ret < 0) {
- dev_err(dev, "cannot enable interrupts during resume\n");
- return ret;
- }
-
/*
* follow recommended programming flows to avoid
* timeouts when gsync is enabled
@@ -115,31 +114,44 @@ int intel_start_bus_after_reset(struct sdw_intel *sdw)
ret = sdw_cdns_clock_restart(cdns, !clock_stop0);
if (ret < 0) {
dev_err(dev, "unable to restart clock during resume\n");
- goto err_interrupt;
+ if (!clock_stop0)
+ sdw_cdns_enable_interrupt(cdns, false);
+ return ret;
}
if (!clock_stop0) {
- ret = sdw_cdns_exit_reset(cdns);
- if (ret < 0) {
- dev_err(dev, "unable to exit bus reset sequence during resume\n");
- goto err_interrupt;
- }
+ sdw_cdns_config_update(cdns);
if (bus->multi_link) {
ret = sdw_intel_sync_go(sdw);
if (ret < 0) {
dev_err(sdw->cdns.dev, "sync go failed during resume\n");
- goto err_interrupt;
+ return ret;
}
}
+
+ ret = sdw_cdns_config_update_set_wait(cdns);
+ if (ret < 0) {
+ dev_err(dev, "%s: CONFIG_UPDATE BIT still set\n", __func__);
+ return ret;
+ }
+
+ ret = sdw_cdns_exit_reset(cdns);
+ if (ret < 0) {
+ dev_err(dev, "unable to exit bus reset sequence during resume\n");
+ return ret;
+ }
+
+ ret = sdw_cdns_enable_interrupt(cdns, true);
+ if (ret < 0) {
+ dev_err(dev, "cannot enable interrupts during resume\n");
+ return ret;
+ }
+
}
sdw_cdns_check_self_clearing_bits(cdns, __func__, true, INTEL_MASTER_RESET_ITERATIONS);
return 0;
-
-err_interrupt:
- sdw_cdns_enable_interrupt(cdns, false);
- return ret;
}
void intel_check_clock_stop(struct sdw_intel *sdw)
@@ -158,21 +170,19 @@ int intel_start_bus_after_clock_stop(struct sdw_intel *sdw)
struct sdw_cdns *cdns = &sdw->cdns;
int ret;
- ret = sdw_cdns_enable_interrupt(cdns, true);
+ ret = sdw_cdns_clock_restart(cdns, false);
if (ret < 0) {
- dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret);
+ dev_err(dev, "%s: unable to restart clock: %d\n", __func__, ret);
return ret;
}
- ret = sdw_cdns_clock_restart(cdns, false);
+ ret = sdw_cdns_enable_interrupt(cdns, true);
if (ret < 0) {
- dev_err(dev, "%s: unable to restart clock: %d\n", __func__, ret);
- sdw_cdns_enable_interrupt(cdns, false);
+ dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret);
return ret;
}
- sdw_cdns_check_self_clearing_bits(cdns, "intel_resume_runtime no_quirks",
- true, INTEL_MASTER_RESET_ITERATIONS);
+ sdw_cdns_check_self_clearing_bits(cdns, __func__, true, INTEL_MASTER_RESET_ITERATIONS);
return 0;
}
diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c
index cbe56b993c6c..534c8795e7e8 100644
--- a/drivers/soundwire/intel_init.c
+++ b/drivers/soundwire/intel_init.c
@@ -63,19 +63,30 @@ static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res *
link = &ldev->link_res;
link->hw_ops = res->hw_ops;
link->mmio_base = res->mmio_base;
- link->registers = res->mmio_base + SDW_LINK_BASE
- + (SDW_LINK_SIZE * link_id);
- link->shim = res->mmio_base + res->shim_base;
- link->alh = res->mmio_base + res->alh_base;
+ if (!res->ext) {
+ link->registers = res->mmio_base + SDW_LINK_BASE
+ + (SDW_LINK_SIZE * link_id);
+ link->ip_offset = 0;
+ link->shim = res->mmio_base + res->shim_base;
+ link->alh = res->mmio_base + res->alh_base;
+ link->shim_lock = &ctx->shim_lock;
+ } else {
+ link->registers = res->mmio_base + SDW_IP_BASE(link_id);
+ link->ip_offset = SDW_CADENCE_MCP_IP_OFFSET;
+ link->shim = res->mmio_base + SDW_SHIM2_GENERIC_BASE(link_id);
+ link->shim_vs = res->mmio_base + SDW_SHIM2_VS_BASE(link_id);
+ link->shim_lock = res->eml_lock;
+ }
link->ops = res->ops;
link->dev = res->dev;
link->clock_stop_quirks = res->clock_stop_quirks;
- link->shim_lock = &ctx->shim_lock;
link->shim_mask = &ctx->shim_mask;
link->link_mask = ctx->link_mask;
+ link->hbus = res->hbus;
+
/* now follow the two-step init/add sequence */
ret = auxiliary_device_init(auxdev);
if (ret < 0) {
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index 280455f047a3..7970fdb27ba0 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -31,6 +31,7 @@
#define SWRM_VERSION_1_3_0 0x01030000
#define SWRM_VERSION_1_5_1 0x01050001
#define SWRM_VERSION_1_7_0 0x01070000
+#define SWRM_VERSION_2_0_0 0x02000000
#define SWRM_COMP_HW_VERSION 0x00
#define SWRM_COMP_CFG_ADDR 0x04
#define SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK BIT(1)
@@ -41,7 +42,8 @@
#define SWRM_COMP_PARAMS_DOUT_PORTS_MASK GENMASK(4, 0)
#define SWRM_COMP_PARAMS_DIN_PORTS_MASK GENMASK(9, 5)
#define SWRM_COMP_MASTER_ID 0x104
-#define SWRM_INTERRUPT_STATUS 0x200
+#define SWRM_V1_3_INTERRUPT_STATUS 0x200
+#define SWRM_V2_0_INTERRUPT_STATUS 0x5000
#define SWRM_INTERRUPT_STATUS_RMSK GENMASK(16, 0)
#define SWRM_INTERRUPT_STATUS_SLAVE_PEND_IRQ BIT(0)
#define SWRM_INTERRUPT_STATUS_NEW_SLAVE_ATTACHED BIT(1)
@@ -54,24 +56,32 @@
#define SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION BIT(8)
#define SWRM_INTERRUPT_STATUS_READ_EN_RD_VALID_MISMATCH BIT(9)
#define SWRM_INTERRUPT_STATUS_SPECIAL_CMD_ID_FINISHED BIT(10)
-#define SWRM_INTERRUPT_STATUS_BUS_RESET_FINISHED_V2 BIT(13)
-#define SWRM_INTERRUPT_STATUS_CLK_STOP_FINISHED_V2 BIT(14)
-#define SWRM_INTERRUPT_STATUS_EXT_CLK_STOP_WAKEUP BIT(16)
+#define SWRM_INTERRUPT_STATUS_AUTO_ENUM_FAILED BIT(11)
+#define SWRM_INTERRUPT_STATUS_AUTO_ENUM_TABLE_IS_FULL BIT(12)
+#define SWRM_INTERRUPT_STATUS_BUS_RESET_FINISHED_V2 BIT(13)
+#define SWRM_INTERRUPT_STATUS_CLK_STOP_FINISHED_V2 BIT(14)
+#define SWRM_INTERRUPT_STATUS_EXT_CLK_STOP_WAKEUP BIT(16)
#define SWRM_INTERRUPT_MAX 17
-#define SWRM_INTERRUPT_MASK_ADDR 0x204
-#define SWRM_INTERRUPT_CLEAR 0x208
-#define SWRM_INTERRUPT_CPU_EN 0x210
-#define SWRM_CMD_FIFO_WR_CMD 0x300
-#define SWRM_CMD_FIFO_RD_CMD 0x304
+#define SWRM_V1_3_INTERRUPT_MASK_ADDR 0x204
+#define SWRM_V1_3_INTERRUPT_CLEAR 0x208
+#define SWRM_V2_0_INTERRUPT_CLEAR 0x5008
+#define SWRM_V1_3_INTERRUPT_CPU_EN 0x210
+#define SWRM_V2_0_INTERRUPT_CPU_EN 0x5004
+#define SWRM_V1_3_CMD_FIFO_WR_CMD 0x300
+#define SWRM_V2_0_CMD_FIFO_WR_CMD 0x5020
+#define SWRM_V1_3_CMD_FIFO_RD_CMD 0x304
+#define SWRM_V2_0_CMD_FIFO_RD_CMD 0x5024
#define SWRM_CMD_FIFO_CMD 0x308
#define SWRM_CMD_FIFO_FLUSH 0x1
-#define SWRM_CMD_FIFO_STATUS 0x30C
+#define SWRM_V1_3_CMD_FIFO_STATUS 0x30C
+#define SWRM_V2_0_CMD_FIFO_STATUS 0x5050
#define SWRM_RD_CMD_FIFO_CNT_MASK GENMASK(20, 16)
#define SWRM_WR_CMD_FIFO_CNT_MASK GENMASK(12, 8)
#define SWRM_CMD_FIFO_CFG_ADDR 0x314
#define SWRM_CONTINUE_EXEC_ON_CMD_IGNORE BIT(31)
#define SWRM_RD_WR_CMD_RETRIES 0x7
-#define SWRM_CMD_FIFO_RD_FIFO_ADDR 0x318
+#define SWRM_V1_3_CMD_FIFO_RD_FIFO_ADDR 0x318
+#define SWRM_V2_0_CMD_FIFO_RD_FIFO_ADDR 0x5040
#define SWRM_RD_FIFO_CMD_ID_MASK GENMASK(11, 8)
#define SWRM_ENUMERATOR_CFG_ADDR 0x500
#define SWRM_ENUMERATOR_SLAVE_DEV_ID_1(m) (0x530 + 0x8 * (m))
@@ -95,8 +105,14 @@
#define SWRM_DP_BLOCK_CTRL2_BANK(n, m) (0x1130 + 0x100 * (n - 1) + 0x40 * m)
#define SWRM_DP_PORT_HCTRL_BANK(n, m) (0x1134 + 0x100 * (n - 1) + 0x40 * m)
#define SWRM_DP_BLOCK_CTRL3_BANK(n, m) (0x1138 + 0x100 * (n - 1) + 0x40 * m)
+#define SWRM_DP_SAMPLECTRL2_BANK(n, m) (0x113C + 0x100 * (n - 1) + 0x40 * m)
#define SWRM_DIN_DPn_PCM_PORT_CTRL(n) (0x1054 + 0x100 * (n - 1))
-#define SWR_MSTR_MAX_REG_ADDR (0x1740)
+#define SWR_V1_3_MSTR_MAX_REG_ADDR 0x1740
+#define SWR_V2_0_MSTR_MAX_REG_ADDR 0x50ac
+
+#define SWRM_V2_0_CLK_CTRL 0x5060
+#define SWRM_V2_0_CLK_CTRL_CLK_START BIT(0)
+#define SWRM_V2_0_LINK_STATUS 0x5064
#define SWRM_DP_PORT_CTRL_EN_CHAN_SHFT 0x18
#define SWRM_DP_PORT_CTRL_OFFSET2_SHFT 0x10
@@ -109,20 +125,20 @@
#define SWRM_REG_VAL_PACK(data, dev, id, reg) \
((reg) | ((id) << 16) | ((dev) << 20) | ((data) << 24))
-#define MAX_FREQ_NUM 1
-#define TIMEOUT_MS 100
-#define QCOM_SWRM_MAX_RD_LEN 0x1
-#define QCOM_SDW_MAX_PORTS 14
-#define DEFAULT_CLK_FREQ 9600000
-#define SWRM_MAX_DAIS 0xF
-#define SWR_INVALID_PARAM 0xFF
-#define SWR_HSTOP_MAX_VAL 0xF
-#define SWR_HSTART_MIN_VAL 0x0
-#define SWR_BROADCAST_CMD_ID 0x0F
-#define SWR_MAX_CMD_ID 14
-#define MAX_FIFO_RD_RETRY 3
-#define SWR_OVERFLOW_RETRY_COUNT 30
-#define SWRM_LINK_STATUS_RETRY_CNT 100
+#define MAX_FREQ_NUM 1
+#define TIMEOUT_MS 100
+#define QCOM_SWRM_MAX_RD_LEN 0x1
+#define QCOM_SDW_MAX_PORTS 14
+#define DEFAULT_CLK_FREQ 9600000
+#define SWRM_MAX_DAIS 0xF
+#define SWR_INVALID_PARAM 0xFF
+#define SWR_HSTOP_MAX_VAL 0xF
+#define SWR_HSTART_MIN_VAL 0x0
+#define SWR_BROADCAST_CMD_ID 0x0F
+#define SWR_MAX_CMD_ID 14
+#define MAX_FIFO_RD_RETRY 3
+#define SWR_OVERFLOW_RETRY_COUNT 30
+#define SWRM_LINK_STATUS_RETRY_CNT 100
enum {
MASTER_ID_WSA = 1,
@@ -131,7 +147,7 @@ enum {
};
struct qcom_swrm_port_config {
- u8 si;
+ u16 si;
u8 off1;
u8 off2;
u8 bp_mode;
@@ -142,10 +158,28 @@ struct qcom_swrm_port_config {
u8 lane_control;
};
+/*
+ * Internal IDs for different register layouts. Only few registers differ per
+ * each variant, so the list of IDs below does not include all of registers.
+ */
+enum {
+ SWRM_REG_FRAME_GEN_ENABLED,
+ SWRM_REG_INTERRUPT_STATUS,
+ SWRM_REG_INTERRUPT_MASK_ADDR,
+ SWRM_REG_INTERRUPT_CLEAR,
+ SWRM_REG_INTERRUPT_CPU_EN,
+ SWRM_REG_CMD_FIFO_WR_CMD,
+ SWRM_REG_CMD_FIFO_RD_CMD,
+ SWRM_REG_CMD_FIFO_STATUS,
+ SWRM_REG_CMD_FIFO_RD_FIFO_ADDR,
+};
+
struct qcom_swrm_ctrl {
struct sdw_bus bus;
struct device *dev;
struct regmap *regmap;
+ u32 max_reg;
+ const unsigned int *reg_layout;
void __iomem *mmio;
struct reset_control *audio_cgcr;
#ifdef CONFIG_DEBUG_FS
@@ -153,12 +187,9 @@ struct qcom_swrm_ctrl {
#endif
struct completion broadcast;
struct completion enumeration;
- struct work_struct slave_work;
/* Port alloc/free lock */
struct mutex port_lock;
struct clk *hclk;
- u8 wr_cmd_id;
- u8 rd_cmd_id;
int irq;
unsigned int version;
int wake_irq;
@@ -171,7 +202,8 @@ struct qcom_swrm_ctrl {
u32 intr_mask;
u8 rcmd_id;
u8 wcmd_id;
- struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS];
+ /* Port numbers are 1 - 14 */
+ struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS + 1];
struct sdw_stream_runtime *sruntime[SWRM_MAX_DAIS];
enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
int (*reg_read)(struct qcom_swrm_ctrl *ctrl, int reg, u32 *val);
@@ -186,22 +218,62 @@ struct qcom_swrm_data {
u32 default_cols;
u32 default_rows;
bool sw_clk_gate_required;
+ u32 max_reg;
+ const unsigned int *reg_layout;
+};
+
+static const unsigned int swrm_v1_3_reg_layout[] = {
+ [SWRM_REG_FRAME_GEN_ENABLED] = SWRM_COMP_STATUS,
+ [SWRM_REG_INTERRUPT_STATUS] = SWRM_V1_3_INTERRUPT_STATUS,
+ [SWRM_REG_INTERRUPT_MASK_ADDR] = SWRM_V1_3_INTERRUPT_MASK_ADDR,
+ [SWRM_REG_INTERRUPT_CLEAR] = SWRM_V1_3_INTERRUPT_CLEAR,
+ [SWRM_REG_INTERRUPT_CPU_EN] = SWRM_V1_3_INTERRUPT_CPU_EN,
+ [SWRM_REG_CMD_FIFO_WR_CMD] = SWRM_V1_3_CMD_FIFO_WR_CMD,
+ [SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V1_3_CMD_FIFO_RD_CMD,
+ [SWRM_REG_CMD_FIFO_STATUS] = SWRM_V1_3_CMD_FIFO_STATUS,
+ [SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V1_3_CMD_FIFO_RD_FIFO_ADDR,
};
static const struct qcom_swrm_data swrm_v1_3_data = {
.default_rows = 48,
.default_cols = 16,
+ .max_reg = SWR_V1_3_MSTR_MAX_REG_ADDR,
+ .reg_layout = swrm_v1_3_reg_layout,
};
static const struct qcom_swrm_data swrm_v1_5_data = {
.default_rows = 50,
.default_cols = 16,
+ .max_reg = SWR_V1_3_MSTR_MAX_REG_ADDR,
+ .reg_layout = swrm_v1_3_reg_layout,
};
static const struct qcom_swrm_data swrm_v1_6_data = {
.default_rows = 50,
.default_cols = 16,
.sw_clk_gate_required = true,
+ .max_reg = SWR_V1_3_MSTR_MAX_REG_ADDR,
+ .reg_layout = swrm_v1_3_reg_layout,
+};
+
+static const unsigned int swrm_v2_0_reg_layout[] = {
+ [SWRM_REG_FRAME_GEN_ENABLED] = SWRM_V2_0_LINK_STATUS,
+ [SWRM_REG_INTERRUPT_STATUS] = SWRM_V2_0_INTERRUPT_STATUS,
+ [SWRM_REG_INTERRUPT_MASK_ADDR] = 0, /* Not present */
+ [SWRM_REG_INTERRUPT_CLEAR] = SWRM_V2_0_INTERRUPT_CLEAR,
+ [SWRM_REG_INTERRUPT_CPU_EN] = SWRM_V2_0_INTERRUPT_CPU_EN,
+ [SWRM_REG_CMD_FIFO_WR_CMD] = SWRM_V2_0_CMD_FIFO_WR_CMD,
+ [SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V2_0_CMD_FIFO_RD_CMD,
+ [SWRM_REG_CMD_FIFO_STATUS] = SWRM_V2_0_CMD_FIFO_STATUS,
+ [SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V2_0_CMD_FIFO_RD_FIFO_ADDR,
+};
+
+static const struct qcom_swrm_data swrm_v2_0_data = {
+ .default_rows = 50,
+ .default_cols = 16,
+ .sw_clk_gate_required = true,
+ .max_reg = SWR_V2_0_MSTR_MAX_REG_ADDR,
+ .reg_layout = swrm_v2_0_reg_layout,
};
#define to_qcom_sdw(b) container_of(b, struct qcom_swrm_ctrl, bus)
@@ -278,14 +350,15 @@ static u32 swrm_get_packed_reg_val(u8 *cmd_id, u8 cmd_data,
return val;
}
-static int swrm_wait_for_rd_fifo_avail(struct qcom_swrm_ctrl *swrm)
+static int swrm_wait_for_rd_fifo_avail(struct qcom_swrm_ctrl *ctrl)
{
u32 fifo_outstanding_data, value;
int fifo_retry_count = SWR_OVERFLOW_RETRY_COUNT;
do {
/* Check for fifo underflow during read */
- swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value);
+ ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS],
+ &value);
fifo_outstanding_data = FIELD_GET(SWRM_RD_CMD_FIFO_CNT_MASK, value);
/* Check if read data is available in read fifo */
@@ -296,39 +369,66 @@ static int swrm_wait_for_rd_fifo_avail(struct qcom_swrm_ctrl *swrm)
} while (fifo_retry_count--);
if (fifo_outstanding_data == 0) {
- dev_err_ratelimited(swrm->dev, "%s err read underflow\n", __func__);
+ dev_err_ratelimited(ctrl->dev, "%s err read underflow\n", __func__);
return -EIO;
}
return 0;
}
-static int swrm_wait_for_wr_fifo_avail(struct qcom_swrm_ctrl *swrm)
+static int swrm_wait_for_wr_fifo_avail(struct qcom_swrm_ctrl *ctrl)
{
u32 fifo_outstanding_cmds, value;
int fifo_retry_count = SWR_OVERFLOW_RETRY_COUNT;
do {
/* Check for fifo overflow during write */
- swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value);
+ ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS],
+ &value);
fifo_outstanding_cmds = FIELD_GET(SWRM_WR_CMD_FIFO_CNT_MASK, value);
/* Check for space in write fifo before writing */
- if (fifo_outstanding_cmds < swrm->wr_fifo_depth)
+ if (fifo_outstanding_cmds < ctrl->wr_fifo_depth)
return 0;
usleep_range(500, 510);
} while (fifo_retry_count--);
- if (fifo_outstanding_cmds == swrm->wr_fifo_depth) {
- dev_err_ratelimited(swrm->dev, "%s err write overflow\n", __func__);
+ if (fifo_outstanding_cmds == ctrl->wr_fifo_depth) {
+ dev_err_ratelimited(ctrl->dev, "%s err write overflow\n", __func__);
return -EIO;
}
return 0;
}
-static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *swrm, u8 cmd_data,
+static bool swrm_wait_for_wr_fifo_done(struct qcom_swrm_ctrl *ctrl)
+{
+ u32 fifo_outstanding_cmds, value;
+ int fifo_retry_count = SWR_OVERFLOW_RETRY_COUNT;
+
+ /* Check for fifo overflow during write */
+ ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS], &value);
+ fifo_outstanding_cmds = FIELD_GET(SWRM_WR_CMD_FIFO_CNT_MASK, value);
+
+ if (fifo_outstanding_cmds) {
+ while (fifo_retry_count) {
+ usleep_range(500, 510);
+ ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS], &value);
+ fifo_outstanding_cmds = FIELD_GET(SWRM_WR_CMD_FIFO_CNT_MASK, value);
+ fifo_retry_count--;
+ if (fifo_outstanding_cmds == 0)
+ return true;
+ }
+ } else {
+ return true;
+ }
+
+
+ return false;
+}
+
+static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *ctrl, u8 cmd_data,
u8 dev_addr, u16 reg_addr)
{
@@ -341,28 +441,29 @@ static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *swrm, u8 cmd_data,
val = swrm_get_packed_reg_val(&cmd_id, cmd_data,
dev_addr, reg_addr);
} else {
- val = swrm_get_packed_reg_val(&swrm->wcmd_id, cmd_data,
+ val = swrm_get_packed_reg_val(&ctrl->wcmd_id, cmd_data,
dev_addr, reg_addr);
}
- if (swrm_wait_for_wr_fifo_avail(swrm))
+ if (swrm_wait_for_wr_fifo_avail(ctrl))
return SDW_CMD_FAIL_OTHER;
if (cmd_id == SWR_BROADCAST_CMD_ID)
- reinit_completion(&swrm->broadcast);
+ reinit_completion(&ctrl->broadcast);
/* Its assumed that write is okay as we do not get any status back */
- swrm->reg_write(swrm, SWRM_CMD_FIFO_WR_CMD, val);
+ ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_WR_CMD], val);
- if (swrm->version <= SWRM_VERSION_1_3_0)
+ if (ctrl->version <= SWRM_VERSION_1_3_0)
usleep_range(150, 155);
if (cmd_id == SWR_BROADCAST_CMD_ID) {
+ swrm_wait_for_wr_fifo_done(ctrl);
/*
* sleep for 10ms for MSM soundwire variant to allow broadcast
* command to complete.
*/
- ret = wait_for_completion_timeout(&swrm->broadcast,
+ ret = wait_for_completion_timeout(&ctrl->broadcast,
msecs_to_jiffies(TIMEOUT_MS));
if (!ret)
ret = SDW_CMD_IGNORED;
@@ -375,41 +476,44 @@ static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *swrm, u8 cmd_data,
return ret;
}
-static int qcom_swrm_cmd_fifo_rd_cmd(struct qcom_swrm_ctrl *swrm,
+static int qcom_swrm_cmd_fifo_rd_cmd(struct qcom_swrm_ctrl *ctrl,
u8 dev_addr, u16 reg_addr,
u32 len, u8 *rval)
{
u32 cmd_data, cmd_id, val, retry_attempt = 0;
- val = swrm_get_packed_reg_val(&swrm->rcmd_id, len, dev_addr, reg_addr);
+ val = swrm_get_packed_reg_val(&ctrl->rcmd_id, len, dev_addr, reg_addr);
/*
* Check for outstanding cmd wrt. write fifo depth to avoid
* overflow as read will also increase write fifo cnt.
*/
- swrm_wait_for_wr_fifo_avail(swrm);
+ swrm_wait_for_wr_fifo_avail(ctrl);
/* wait for FIFO RD to complete to avoid overflow */
usleep_range(100, 105);
- swrm->reg_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
+ ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_RD_CMD], val);
/* wait for FIFO RD CMD complete to avoid overflow */
usleep_range(250, 255);
- if (swrm_wait_for_rd_fifo_avail(swrm))
+ if (swrm_wait_for_rd_fifo_avail(ctrl))
return SDW_CMD_FAIL_OTHER;
do {
- swrm->reg_read(swrm, SWRM_CMD_FIFO_RD_FIFO_ADDR, &cmd_data);
+ ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_RD_FIFO_ADDR],
+ &cmd_data);
rval[0] = cmd_data & 0xFF;
cmd_id = FIELD_GET(SWRM_RD_FIFO_CMD_ID_MASK, cmd_data);
- if (cmd_id != swrm->rcmd_id) {
+ if (cmd_id != ctrl->rcmd_id) {
if (retry_attempt < (MAX_FIFO_RD_RETRY - 1)) {
/* wait 500 us before retry on fifo read failure */
usleep_range(500, 505);
- swrm->reg_write(swrm, SWRM_CMD_FIFO_CMD,
+ ctrl->reg_write(ctrl, SWRM_CMD_FIFO_CMD,
SWRM_CMD_FIFO_FLUSH);
- swrm->reg_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
+ ctrl->reg_write(ctrl,
+ ctrl->reg_layout[SWRM_REG_CMD_FIFO_RD_CMD],
+ val);
}
retry_attempt++;
} else {
@@ -418,9 +522,9 @@ static int qcom_swrm_cmd_fifo_rd_cmd(struct qcom_swrm_ctrl *swrm,
} while (retry_attempt < MAX_FIFO_RD_RETRY);
- dev_err(swrm->dev, "failed to read fifo: reg: 0x%x, rcmd_id: 0x%x,\
+ dev_err(ctrl->dev, "failed to read fifo: reg: 0x%x, rcmd_id: 0x%x,\
dev_num: 0x%x, cmd_data: 0x%x\n",
- reg_addr, swrm->rcmd_id, dev_addr, cmd_data);
+ reg_addr, ctrl->rcmd_id, dev_addr, cmd_data);
return SDW_CMD_IGNORED;
}
@@ -511,10 +615,14 @@ static int qcom_swrm_enumerate(struct sdw_bus *bus)
sdw_extract_slave_id(bus, addr, &id);
found = false;
+ ctrl->clock_stop_not_supported = false;
/* Now compare with entries */
list_for_each_entry_safe(slave, _s, &bus->slaves, node) {
if (sdw_compare_devid(slave, id) == 0) {
qcom_swrm_set_slave_dev_num(bus, slave, i);
+ if (slave->prop.clk_stop_mode1)
+ ctrl->clock_stop_not_supported = true;
+
found = true;
break;
}
@@ -532,39 +640,41 @@ static int qcom_swrm_enumerate(struct sdw_bus *bus)
static irqreturn_t qcom_swrm_wake_irq_handler(int irq, void *dev_id)
{
- struct qcom_swrm_ctrl *swrm = dev_id;
+ struct qcom_swrm_ctrl *ctrl = dev_id;
int ret;
- ret = pm_runtime_resume_and_get(swrm->dev);
+ ret = pm_runtime_get_sync(ctrl->dev);
if (ret < 0 && ret != -EACCES) {
- dev_err_ratelimited(swrm->dev,
- "pm_runtime_resume_and_get failed in %s, ret %d\n",
+ dev_err_ratelimited(ctrl->dev,
+ "pm_runtime_get_sync failed in %s, ret %d\n",
__func__, ret);
+ pm_runtime_put_noidle(ctrl->dev);
return ret;
}
- if (swrm->wake_irq > 0) {
- if (!irqd_irq_disabled(irq_get_irq_data(swrm->wake_irq)))
- disable_irq_nosync(swrm->wake_irq);
+ if (ctrl->wake_irq > 0) {
+ if (!irqd_irq_disabled(irq_get_irq_data(ctrl->wake_irq)))
+ disable_irq_nosync(ctrl->wake_irq);
}
- pm_runtime_mark_last_busy(swrm->dev);
- pm_runtime_put_autosuspend(swrm->dev);
+ pm_runtime_mark_last_busy(ctrl->dev);
+ pm_runtime_put_autosuspend(ctrl->dev);
return IRQ_HANDLED;
}
static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id)
{
- struct qcom_swrm_ctrl *swrm = dev_id;
+ struct qcom_swrm_ctrl *ctrl = dev_id;
u32 value, intr_sts, intr_sts_masked, slave_status;
u32 i;
int devnum;
int ret = IRQ_HANDLED;
- clk_prepare_enable(swrm->hclk);
+ clk_prepare_enable(ctrl->hclk);
- swrm->reg_read(swrm, SWRM_INTERRUPT_STATUS, &intr_sts);
- intr_sts_masked = intr_sts & swrm->intr_mask;
+ ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_STATUS],
+ &intr_sts);
+ intr_sts_masked = intr_sts & ctrl->intr_mask;
do {
for (i = 0; i < SWRM_INTERRUPT_MAX; i++) {
@@ -574,80 +684,92 @@ static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id)
switch (value) {
case SWRM_INTERRUPT_STATUS_SLAVE_PEND_IRQ:
- devnum = qcom_swrm_get_alert_slave_dev_num(swrm);
+ devnum = qcom_swrm_get_alert_slave_dev_num(ctrl);
if (devnum < 0) {
- dev_err_ratelimited(swrm->dev,
+ dev_err_ratelimited(ctrl->dev,
"no slave alert found.spurious interrupt\n");
} else {
- sdw_handle_slave_status(&swrm->bus, swrm->status);
+ sdw_handle_slave_status(&ctrl->bus, ctrl->status);
}
break;
case SWRM_INTERRUPT_STATUS_NEW_SLAVE_ATTACHED:
case SWRM_INTERRUPT_STATUS_CHANGE_ENUM_SLAVE_STATUS:
- dev_dbg_ratelimited(swrm->dev, "SWR new slave attached\n");
- swrm->reg_read(swrm, SWRM_MCP_SLV_STATUS, &slave_status);
- if (swrm->slave_status == slave_status) {
- dev_dbg(swrm->dev, "Slave status not changed %x\n",
+ dev_dbg_ratelimited(ctrl->dev, "SWR new slave attached\n");
+ ctrl->reg_read(ctrl, SWRM_MCP_SLV_STATUS, &slave_status);
+ if (ctrl->slave_status == slave_status) {
+ dev_dbg(ctrl->dev, "Slave status not changed %x\n",
slave_status);
} else {
- qcom_swrm_get_device_status(swrm);
- qcom_swrm_enumerate(&swrm->bus);
- sdw_handle_slave_status(&swrm->bus, swrm->status);
+ qcom_swrm_get_device_status(ctrl);
+ qcom_swrm_enumerate(&ctrl->bus);
+ sdw_handle_slave_status(&ctrl->bus, ctrl->status);
}
break;
case SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET:
- dev_err_ratelimited(swrm->dev,
+ dev_err_ratelimited(ctrl->dev,
"%s: SWR bus clsh detected\n",
__func__);
- swrm->intr_mask &= ~SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET;
- swrm->reg_write(swrm, SWRM_INTERRUPT_CPU_EN, swrm->intr_mask);
+ ctrl->intr_mask &= ~SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET;
+ ctrl->reg_write(ctrl,
+ ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
+ ctrl->intr_mask);
break;
case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW:
- swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value);
- dev_err_ratelimited(swrm->dev,
+ ctrl->reg_read(ctrl,
+ ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS],
+ &value);
+ dev_err_ratelimited(ctrl->dev,
"%s: SWR read FIFO overflow fifo status 0x%x\n",
__func__, value);
break;
case SWRM_INTERRUPT_STATUS_RD_FIFO_UNDERFLOW:
- swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value);
- dev_err_ratelimited(swrm->dev,
+ ctrl->reg_read(ctrl,
+ ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS],
+ &value);
+ dev_err_ratelimited(ctrl->dev,
"%s: SWR read FIFO underflow fifo status 0x%x\n",
__func__, value);
break;
case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW:
- swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value);
- dev_err(swrm->dev,
+ ctrl->reg_read(ctrl,
+ ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS],
+ &value);
+ dev_err(ctrl->dev,
"%s: SWR write FIFO overflow fifo status %x\n",
__func__, value);
- swrm->reg_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
+ ctrl->reg_write(ctrl, SWRM_CMD_FIFO_CMD, 0x1);
break;
case SWRM_INTERRUPT_STATUS_CMD_ERROR:
- swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value);
- dev_err_ratelimited(swrm->dev,
+ ctrl->reg_read(ctrl,
+ ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS],
+ &value);
+ dev_err_ratelimited(ctrl->dev,
"%s: SWR CMD error, fifo status 0x%x, flushing fifo\n",
__func__, value);
- swrm->reg_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
+ ctrl->reg_write(ctrl, SWRM_CMD_FIFO_CMD, 0x1);
break;
case SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION:
- dev_err_ratelimited(swrm->dev,
+ dev_err_ratelimited(ctrl->dev,
"%s: SWR Port collision detected\n",
__func__);
- swrm->intr_mask &= ~SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION;
- swrm->reg_write(swrm,
- SWRM_INTERRUPT_CPU_EN, swrm->intr_mask);
+ ctrl->intr_mask &= ~SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION;
+ ctrl->reg_write(ctrl,
+ ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
+ ctrl->intr_mask);
break;
case SWRM_INTERRUPT_STATUS_READ_EN_RD_VALID_MISMATCH:
- dev_err_ratelimited(swrm->dev,
+ dev_err_ratelimited(ctrl->dev,
"%s: SWR read enable valid mismatch\n",
__func__);
- swrm->intr_mask &=
+ ctrl->intr_mask &=
~SWRM_INTERRUPT_STATUS_READ_EN_RD_VALID_MISMATCH;
- swrm->reg_write(swrm,
- SWRM_INTERRUPT_CPU_EN, swrm->intr_mask);
+ ctrl->reg_write(ctrl,
+ ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
+ ctrl->intr_mask);
break;
case SWRM_INTERRUPT_STATUS_SPECIAL_CMD_ID_FINISHED:
- complete(&swrm->broadcast);
+ complete(&ctrl->broadcast);
break;
case SWRM_INTERRUPT_STATUS_BUS_RESET_FINISHED_V2:
break;
@@ -656,22 +778,44 @@ static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id)
case SWRM_INTERRUPT_STATUS_EXT_CLK_STOP_WAKEUP:
break;
default:
- dev_err_ratelimited(swrm->dev,
+ dev_err_ratelimited(ctrl->dev,
"%s: SWR unknown interrupt value: %d\n",
__func__, value);
ret = IRQ_NONE;
break;
}
}
- swrm->reg_write(swrm, SWRM_INTERRUPT_CLEAR, intr_sts);
- swrm->reg_read(swrm, SWRM_INTERRUPT_STATUS, &intr_sts);
- intr_sts_masked = intr_sts & swrm->intr_mask;
+ ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR],
+ intr_sts);
+ ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_STATUS],
+ &intr_sts);
+ intr_sts_masked = intr_sts & ctrl->intr_mask;
} while (intr_sts_masked);
- clk_disable_unprepare(swrm->hclk);
+ clk_disable_unprepare(ctrl->hclk);
return ret;
}
+static bool swrm_wait_for_frame_gen_enabled(struct qcom_swrm_ctrl *ctrl)
+{
+ int retry = SWRM_LINK_STATUS_RETRY_CNT;
+ int comp_sts;
+
+ do {
+ ctrl->reg_read(ctrl, SWRM_COMP_STATUS, &comp_sts);
+
+ if (comp_sts & SWRM_FRM_GEN_ENABLED)
+ return true;
+
+ usleep_range(500, 510);
+ } while (retry--);
+
+ dev_err(ctrl->dev, "%s: link status not %s\n", __func__,
+ comp_sts & SWRM_FRM_GEN_ENABLED ? "connected" : "disconnected");
+
+ return false;
+}
+
static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
{
u32 val;
@@ -689,18 +833,23 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
ctrl->intr_mask = SWRM_INTERRUPT_STATUS_RMSK;
/* Mask soundwire interrupts */
- ctrl->reg_write(ctrl, SWRM_INTERRUPT_MASK_ADDR,
- SWRM_INTERRUPT_STATUS_RMSK);
+ if (ctrl->version < SWRM_VERSION_2_0_0)
+ ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_MASK_ADDR],
+ SWRM_INTERRUPT_STATUS_RMSK);
/* Configure No pings */
ctrl->reg_read(ctrl, SWRM_MCP_CFG_ADDR, &val);
u32p_replace_bits(&val, SWRM_DEF_CMD_NO_PINGS, SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK);
ctrl->reg_write(ctrl, SWRM_MCP_CFG_ADDR, val);
- if (ctrl->version >= SWRM_VERSION_1_7_0) {
+ if (ctrl->version == SWRM_VERSION_1_7_0) {
ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU);
+ } else if (ctrl->version >= SWRM_VERSION_2_0_0) {
+ ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
+ ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL,
+ SWRM_V2_0_CLK_CTRL_CLK_START);
} else {
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START);
}
@@ -715,16 +864,28 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
SWRM_RD_WR_CMD_RETRIES);
}
+ /* COMP Enable */
+ ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR, SWRM_COMP_CFG_ENABLE_MSK);
+
/* Set IRQ to PULSE */
ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR,
- SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK |
- SWRM_COMP_CFG_ENABLE_MSK);
+ SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK);
+
+ ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR],
+ 0xFFFFFFFF);
/* enable CPU IRQs */
if (ctrl->mmio) {
- ctrl->reg_write(ctrl, SWRM_INTERRUPT_CPU_EN,
+ ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
SWRM_INTERRUPT_STATUS_RMSK);
}
+
+ /* Set IRQ to PULSE */
+ ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR,
+ SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK |
+ SWRM_COMP_CFG_ENABLE_MSK);
+
+ swrm_wait_for_frame_gen_enabled(ctrl);
ctrl->slave_status = 0;
ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val);
ctrl->rd_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_RD_FIFO_DEPTH, val);
@@ -806,12 +967,20 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus,
value = pcfg->off1 << SWRM_DP_PORT_CTRL_OFFSET1_SHFT;
value |= pcfg->off2 << SWRM_DP_PORT_CTRL_OFFSET2_SHFT;
- value |= pcfg->si;
+ value |= pcfg->si & 0xff;
ret = ctrl->reg_write(ctrl, reg, value);
if (ret)
goto err;
+ if (pcfg->si > 0xff) {
+ value = (pcfg->si >> 8) & 0xff;
+ reg = SWRM_DP_SAMPLECTRL2_BANK(params->port_num, bank);
+ ret = ctrl->reg_write(ctrl, reg, value);
+ if (ret)
+ goto err;
+ }
+
if (pcfg->lane_control != SWR_INVALID_PARAM) {
reg = SWRM_DP_PORT_CTRL_2_BANK(params->port_num, bank);
value = pcfg->lane_control;
@@ -1090,11 +1259,12 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai;
int ret, i;
- ret = pm_runtime_resume_and_get(ctrl->dev);
+ ret = pm_runtime_get_sync(ctrl->dev);
if (ret < 0 && ret != -EACCES) {
dev_err_ratelimited(ctrl->dev,
- "pm_runtime_resume_and_get failed in %s, ret %d\n",
+ "pm_runtime_get_sync failed in %s, ret %d\n",
__func__, ret);
+ pm_runtime_put_noidle(ctrl->dev);
return ret;
}
@@ -1132,6 +1302,7 @@ static void qcom_swrm_shutdown(struct snd_pcm_substream *substream,
{
struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev);
+ swrm_wait_for_wr_fifo_done(ctrl);
sdw_release_stream(ctrl->sruntime[dai->id]);
ctrl->sruntime[dai->id] = NULL;
pm_runtime_mark_last_busy(ctrl->dev);
@@ -1194,7 +1365,7 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
struct device_node *np = ctrl->dev->of_node;
u8 off1[QCOM_SDW_MAX_PORTS];
u8 off2[QCOM_SDW_MAX_PORTS];
- u8 si[QCOM_SDW_MAX_PORTS];
+ u16 si[QCOM_SDW_MAX_PORTS];
u8 bp_mode[QCOM_SDW_MAX_PORTS] = { 0, };
u8 hstart[QCOM_SDW_MAX_PORTS];
u8 hstop[QCOM_SDW_MAX_PORTS];
@@ -1202,6 +1373,7 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
u8 blk_group_count[QCOM_SDW_MAX_PORTS];
u8 lane_control[QCOM_SDW_MAX_PORTS];
int i, ret, nports, val;
+ bool si_16 = false;
ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val);
@@ -1245,9 +1417,14 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
return ret;
ret = of_property_read_u8_array(np, "qcom,ports-sinterval-low",
- si, nports);
- if (ret)
- return ret;
+ (u8 *)si, nports);
+ if (ret) {
+ ret = of_property_read_u16_array(np, "qcom,ports-sinterval",
+ si, nports);
+ if (ret)
+ return ret;
+ si_16 = true;
+ }
ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode",
bp_mode, nports);
@@ -1275,7 +1452,10 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
for (i = 0; i < nports; i++) {
/* Valid port number range is from 1-14 */
- ctrl->pconfig[i + 1].si = si[i];
+ if (si_16)
+ ctrl->pconfig[i + 1].si = si[i];
+ else
+ ctrl->pconfig[i + 1].si = ((u8 *)si)[i];
ctrl->pconfig[i + 1].off1 = off1[i];
ctrl->pconfig[i + 1].off2 = off2[i];
ctrl->pconfig[i + 1].bp_mode = bp_mode[i];
@@ -1292,23 +1472,24 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
#ifdef CONFIG_DEBUG_FS
static int swrm_reg_show(struct seq_file *s_file, void *data)
{
- struct qcom_swrm_ctrl *swrm = s_file->private;
+ struct qcom_swrm_ctrl *ctrl = s_file->private;
int reg, reg_val, ret;
- ret = pm_runtime_resume_and_get(swrm->dev);
+ ret = pm_runtime_get_sync(ctrl->dev);
if (ret < 0 && ret != -EACCES) {
- dev_err_ratelimited(swrm->dev,
- "pm_runtime_resume_and_get failed in %s, ret %d\n",
+ dev_err_ratelimited(ctrl->dev,
+ "pm_runtime_get_sync failed in %s, ret %d\n",
__func__, ret);
+ pm_runtime_put_noidle(ctrl->dev);
return ret;
}
- for (reg = 0; reg <= SWR_MSTR_MAX_REG_ADDR; reg += 4) {
- swrm->reg_read(swrm, reg, &reg_val);
+ for (reg = 0; reg <= ctrl->max_reg; reg += 4) {
+ ctrl->reg_read(ctrl, reg, &reg_val);
seq_printf(s_file, "0x%.3x: 0x%.2x\n", reg, reg_val);
}
- pm_runtime_mark_last_busy(swrm->dev);
- pm_runtime_put_autosuspend(swrm->dev);
+ pm_runtime_mark_last_busy(ctrl->dev);
+ pm_runtime_put_autosuspend(ctrl->dev);
return 0;
@@ -1331,6 +1512,8 @@ static int qcom_swrm_probe(struct platform_device *pdev)
return -ENOMEM;
data = of_device_get_match_data(dev);
+ ctrl->max_reg = data->max_reg;
+ ctrl->reg_layout = data->reg_layout;
ctrl->rows_index = sdw_find_row_index(data->default_rows);
ctrl->cols_index = sdw_find_col_index(data->default_cols);
#if IS_REACHABLE(CONFIG_SLIMBUS)
@@ -1454,15 +1637,6 @@ static int qcom_swrm_probe(struct platform_device *pdev)
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
- /* Clk stop is not supported on WSA Soundwire masters */
- if (ctrl->version <= SWRM_VERSION_1_3_0) {
- ctrl->clock_stop_not_supported = true;
- } else {
- ctrl->reg_read(ctrl, SWRM_COMP_MASTER_ID, &val);
- if (val == MASTER_ID_WSA)
- ctrl->clock_stop_not_supported = true;
- }
-
#ifdef CONFIG_DEBUG_FS
ctrl->debugfs = debugfs_create_dir("qualcomm-sdw", ctrl->bus.debugfs);
debugfs_create_file("qualcomm-registers", 0400, ctrl->debugfs, ctrl,
@@ -1489,26 +1663,6 @@ static int qcom_swrm_remove(struct platform_device *pdev)
return 0;
}
-static bool swrm_wait_for_frame_gen_enabled(struct qcom_swrm_ctrl *swrm)
-{
- int retry = SWRM_LINK_STATUS_RETRY_CNT;
- int comp_sts;
-
- do {
- swrm->reg_read(swrm, SWRM_COMP_STATUS, &comp_sts);
-
- if (comp_sts & SWRM_FRM_GEN_ENABLED)
- return true;
-
- usleep_range(500, 510);
- } while (retry--);
-
- dev_err(swrm->dev, "%s: link status not %s\n", __func__,
- comp_sts & SWRM_FRM_GEN_ENABLED ? "connected" : "disconnected");
-
- return false;
-}
-
static int __maybe_unused swrm_runtime_resume(struct device *dev)
{
struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dev);
@@ -1540,19 +1694,27 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev)
} else {
reset_control_reset(ctrl->audio_cgcr);
- if (ctrl->version >= SWRM_VERSION_1_7_0) {
+ if (ctrl->version == SWRM_VERSION_1_7_0) {
ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU);
+ } else if (ctrl->version >= SWRM_VERSION_2_0_0) {
+ ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
+ ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL,
+ SWRM_V2_0_CLK_CTRL_CLK_START);
} else {
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START);
}
- ctrl->reg_write(ctrl, SWRM_INTERRUPT_CLEAR,
+ ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR],
SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET);
ctrl->intr_mask |= SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET;
- ctrl->reg_write(ctrl, SWRM_INTERRUPT_MASK_ADDR, ctrl->intr_mask);
- ctrl->reg_write(ctrl, SWRM_INTERRUPT_CPU_EN, ctrl->intr_mask);
+ if (ctrl->version < SWRM_VERSION_2_0_0)
+ ctrl->reg_write(ctrl,
+ ctrl->reg_layout[SWRM_REG_INTERRUPT_MASK_ADDR],
+ ctrl->intr_mask);
+ ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
+ ctrl->intr_mask);
usleep_range(100, 105);
if (!swrm_wait_for_frame_gen_enabled(ctrl))
@@ -1571,11 +1733,16 @@ static int __maybe_unused swrm_runtime_suspend(struct device *dev)
struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dev);
int ret;
+ swrm_wait_for_wr_fifo_done(ctrl);
if (!ctrl->clock_stop_not_supported) {
/* Mask bus clash interrupt */
ctrl->intr_mask &= ~SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET;
- ctrl->reg_write(ctrl, SWRM_INTERRUPT_MASK_ADDR, ctrl->intr_mask);
- ctrl->reg_write(ctrl, SWRM_INTERRUPT_CPU_EN, ctrl->intr_mask);
+ if (ctrl->version < SWRM_VERSION_2_0_0)
+ ctrl->reg_write(ctrl,
+ ctrl->reg_layout[SWRM_REG_INTERRUPT_MASK_ADDR],
+ ctrl->intr_mask);
+ ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
+ ctrl->intr_mask);
/* Prepare slaves for clock stop */
ret = sdw_bus_prep_clk_stop(&ctrl->bus);
if (ret < 0 && ret != -ENODATA) {
@@ -1611,6 +1778,7 @@ static const struct of_device_id qcom_swrm_of_match[] = {
{ .compatible = "qcom,soundwire-v1.5.1", .data = &swrm_v1_5_data },
{ .compatible = "qcom,soundwire-v1.6.0", .data = &swrm_v1_6_data },
{ .compatible = "qcom,soundwire-v1.7.0", .data = &swrm_v1_5_data },
+ { .compatible = "qcom,soundwire-v2.0.0", .data = &swrm_v2_0_data },
{/* sentinel */},
};
diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c
index 379228f22186..d77a8a0d42c8 100644
--- a/drivers/soundwire/stream.c
+++ b/drivers/soundwire/stream.c
@@ -1150,7 +1150,8 @@ static struct sdw_master_runtime
*sdw_master_rt_alloc(struct sdw_bus *bus,
struct sdw_stream_runtime *stream)
{
- struct sdw_master_runtime *m_rt;
+ struct sdw_master_runtime *m_rt, *walk_m_rt;
+ struct list_head *insert_after;
m_rt = kzalloc(sizeof(*m_rt), GFP_KERNEL);
if (!m_rt)
@@ -1159,7 +1160,20 @@ static struct sdw_master_runtime
/* Initialization of Master runtime handle */
INIT_LIST_HEAD(&m_rt->port_list);
INIT_LIST_HEAD(&m_rt->slave_rt_list);
- list_add_tail(&m_rt->stream_node, &stream->master_list);
+
+ /*
+ * Add in order of bus id so that when taking the bus_lock
+ * of multiple buses they will always be taken in the same
+ * order to prevent a mutex deadlock.
+ */
+ insert_after = &stream->master_list;
+ list_for_each_entry_reverse(walk_m_rt, &stream->master_list, stream_node) {
+ if (walk_m_rt->bus->id < bus->id) {
+ insert_after = &walk_m_rt->stream_node;
+ break;
+ }
+ }
+ list_add(&m_rt->stream_node, insert_after);
list_add_tail(&m_rt->bus_node, &bus->m_rt_list);
@@ -1338,7 +1352,7 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream,
bool update_params)
{
struct sdw_master_runtime *m_rt;
- struct sdw_bus *bus = NULL;
+ struct sdw_bus *bus;
struct sdw_master_prop *prop;
struct sdw_bus_params params;
int ret;
@@ -1355,25 +1369,23 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream,
return -EINVAL;
}
- if (!update_params)
- goto program_params;
-
- /* Increment cumulative bus bandwidth */
- /* TODO: Update this during Device-Device support */
- bus->params.bandwidth += m_rt->stream->params.rate *
- m_rt->ch_count * m_rt->stream->params.bps;
+ if (update_params) {
+ /* Increment cumulative bus bandwidth */
+ /* TODO: Update this during Device-Device support */
+ bus->params.bandwidth += m_rt->stream->params.rate *
+ m_rt->ch_count * m_rt->stream->params.bps;
- /* Compute params */
- if (bus->compute_params) {
- ret = bus->compute_params(bus);
- if (ret < 0) {
- dev_err(bus->dev, "Compute params failed: %d\n",
- ret);
- goto restore_params;
+ /* Compute params */
+ if (bus->compute_params) {
+ ret = bus->compute_params(bus);
+ if (ret < 0) {
+ dev_err(bus->dev, "Compute params failed: %d\n",
+ ret);
+ goto restore_params;
+ }
}
}
-program_params:
/* Program params */
ret = sdw_program_params(bus, true);
if (ret < 0) {
@@ -1382,11 +1394,6 @@ program_params:
}
}
- if (!bus) {
- pr_err("Configuration error in %s\n", __func__);
- return -EINVAL;
- }
-
ret = do_bank_switch(stream);
if (ret < 0) {
pr_err("%s: do_bank_switch failed: %d\n", __func__, ret);
@@ -1467,7 +1474,7 @@ EXPORT_SYMBOL(sdw_prepare_stream);
static int _sdw_enable_stream(struct sdw_stream_runtime *stream)
{
struct sdw_master_runtime *m_rt;
- struct sdw_bus *bus = NULL;
+ struct sdw_bus *bus;
int ret;
/* Enable Master(s) and Slave(s) port(s) associated with stream */
@@ -1490,11 +1497,6 @@ static int _sdw_enable_stream(struct sdw_stream_runtime *stream)
}
}
- if (!bus) {
- pr_err("Configuration error in %s\n", __func__);
- return -EINVAL;
- }
-
ret = do_bank_switch(stream);
if (ret < 0) {
pr_err("%s: do_bank_switch failed: %d\n", __func__, ret);
@@ -1864,7 +1866,7 @@ int sdw_stream_add_master(struct sdw_bus *bus,
struct sdw_stream_runtime *stream)
{
struct sdw_master_runtime *m_rt;
- bool alloc_master_rt = true;
+ bool alloc_master_rt = false;
int ret;
mutex_lock(&bus->bus_lock);
@@ -1886,30 +1888,25 @@ int sdw_stream_add_master(struct sdw_bus *bus,
* it first), if so skip allocation and go to configuration
*/
m_rt = sdw_master_rt_find(bus, stream);
- if (m_rt) {
- alloc_master_rt = false;
- goto skip_alloc_master_rt;
- }
-
- m_rt = sdw_master_rt_alloc(bus, stream);
if (!m_rt) {
- dev_err(bus->dev, "%s: Master runtime alloc failed for stream:%s\n",
- __func__, stream->name);
- ret = -ENOMEM;
- goto unlock;
- }
-skip_alloc_master_rt:
-
- if (sdw_master_port_allocated(m_rt))
- goto skip_alloc_master_port;
+ m_rt = sdw_master_rt_alloc(bus, stream);
+ if (!m_rt) {
+ dev_err(bus->dev, "%s: Master runtime alloc failed for stream:%s\n",
+ __func__, stream->name);
+ ret = -ENOMEM;
+ goto unlock;
+ }
- ret = sdw_master_port_alloc(m_rt, num_ports);
- if (ret)
- goto alloc_error;
+ alloc_master_rt = true;
+ }
- stream->m_rt_count++;
+ if (!sdw_master_port_allocated(m_rt)) {
+ ret = sdw_master_port_alloc(m_rt, num_ports);
+ if (ret)
+ goto alloc_error;
-skip_alloc_master_port:
+ stream->m_rt_count++;
+ }
ret = sdw_master_rt_config(m_rt, stream_config);
if (ret < 0)
@@ -1990,8 +1987,8 @@ int sdw_stream_add_slave(struct sdw_slave *slave,
{
struct sdw_slave_runtime *s_rt;
struct sdw_master_runtime *m_rt;
- bool alloc_master_rt = true;
- bool alloc_slave_rt = true;
+ bool alloc_master_rt = false;
+ bool alloc_slave_rt = false;
int ret;
@@ -2002,47 +1999,41 @@ int sdw_stream_add_slave(struct sdw_slave *slave,
* and go to configuration
*/
m_rt = sdw_master_rt_find(slave->bus, stream);
- if (m_rt) {
- alloc_master_rt = false;
- goto skip_alloc_master_rt;
- }
-
- /*
- * If this API is invoked by Slave first then m_rt is not valid.
- * So, allocate m_rt and add Slave to it.
- */
- m_rt = sdw_master_rt_alloc(slave->bus, stream);
if (!m_rt) {
- dev_err(&slave->dev, "%s: Master runtime alloc failed for stream:%s\n",
- __func__, stream->name);
- ret = -ENOMEM;
- goto unlock;
- }
+ /*
+ * If this API is invoked by Slave first then m_rt is not valid.
+ * So, allocate m_rt and add Slave to it.
+ */
+ m_rt = sdw_master_rt_alloc(slave->bus, stream);
+ if (!m_rt) {
+ dev_err(&slave->dev, "%s: Master runtime alloc failed for stream:%s\n",
+ __func__, stream->name);
+ ret = -ENOMEM;
+ goto unlock;
+ }
-skip_alloc_master_rt:
- s_rt = sdw_slave_rt_find(slave, stream);
- if (s_rt) {
- alloc_slave_rt = false;
- goto skip_alloc_slave_rt;
+ alloc_master_rt = true;
}
- s_rt = sdw_slave_rt_alloc(slave, m_rt);
+ s_rt = sdw_slave_rt_find(slave, stream);
if (!s_rt) {
- dev_err(&slave->dev, "Slave runtime alloc failed for stream:%s\n", stream->name);
- alloc_slave_rt = false;
- ret = -ENOMEM;
- goto alloc_error;
- }
+ s_rt = sdw_slave_rt_alloc(slave, m_rt);
+ if (!s_rt) {
+ dev_err(&slave->dev, "Slave runtime alloc failed for stream:%s\n",
+ stream->name);
+ ret = -ENOMEM;
+ goto alloc_error;
+ }
-skip_alloc_slave_rt:
- if (sdw_slave_port_allocated(s_rt))
- goto skip_port_alloc;
+ alloc_slave_rt = true;
+ }
- ret = sdw_slave_port_alloc(slave, s_rt, num_ports);
- if (ret)
- goto alloc_error;
+ if (!sdw_slave_port_allocated(s_rt)) {
+ ret = sdw_slave_port_alloc(slave, s_rt, num_ports);
+ if (ret)
+ goto alloc_error;
+ }
-skip_port_alloc:
ret = sdw_master_rt_config(m_rt, stream_config);
if (ret)
goto unlock;
diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c
index 7a21f2423204..98db47cb4fa4 100644
--- a/drivers/staging/axis-fifo/axis-fifo.c
+++ b/drivers/staging/axis-fifo/axis-fifo.c
@@ -906,9 +906,6 @@ static int axis_fifo_probe(struct platform_device *pdev)
if (rc < 0)
goto err_initial;
- dev_info(fifo->dt_device, "axis-fifo created at %pa mapped to 0x%pa, irq=%i\n",
- &r_mem->start, &fifo->base_addr, fifo->irq);
-
return 0;
err_initial:
diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c
index 7e3d1a6f30ba..6c1f91c859ca 100644
--- a/drivers/staging/iio/addac/adt7316-i2c.c
+++ b/drivers/staging/iio/addac/adt7316-i2c.c
@@ -138,7 +138,7 @@ static struct i2c_driver adt7316_driver = {
.of_match_table = adt7316_of_match,
.pm = ADT7316_PM_OPS,
},
- .probe_new = adt7316_i2c_probe,
+ .probe = adt7316_i2c_probe,
.id_table = adt7316_i2c_id,
};
module_i2c_driver(adt7316_driver);
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index b3152f7153fb..46db6d91542a 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -781,7 +781,7 @@ static struct i2c_driver ad5933_driver = {
.name = "ad5933",
.of_match_table = ad5933_of_match,
},
- .probe_new = ad5933_probe,
+ .probe = ad5933_probe,
.id_table = ad5933_id,
};
module_i2c_driver(ad5933_driver);
diff --git a/drivers/staging/media/atomisp/Makefile b/drivers/staging/media/atomisp/Makefile
index 532e12ed72e6..38b370124109 100644
--- a/drivers/staging/media/atomisp/Makefile
+++ b/drivers/staging/media/atomisp/Makefile
@@ -16,6 +16,7 @@ atomisp-objs += \
pci/atomisp_cmd.o \
pci/atomisp_compat_css20.o \
pci/atomisp_csi2.o \
+ pci/atomisp_csi2_bridge.o \
pci/atomisp_drvfs.o \
pci/atomisp_fops.o \
pci/atomisp_ioctl.o \
diff --git a/drivers/staging/media/atomisp/TODO b/drivers/staging/media/atomisp/TODO
index 43b842043f29..ecf8ba67b7af 100644
--- a/drivers/staging/media/atomisp/TODO
+++ b/drivers/staging/media/atomisp/TODO
@@ -1,213 +1,113 @@
-For both Cherrytrail (CHT) and Baytrail (BHT) the driver
-requires the "candrpv_0415_20150521_0458" firmware version.
-It should be noticed that the firmware file is different,
-depending on the ISP model, so they're stored with different
-names:
+Required firmware
+=================
-- for BHT: /lib/firmware/shisp_2400b0_v21.bin
+The atomisp driver requires the following firmware:
- Warning: The driver was not tested yet for BHT.
+- for BYT: /lib/firmware/shisp_2400b0_v21.bin
-- for CHT: /lib/firmware/shisp_2401a0_v21.bin
-
- https://github.com/intel-aero/meta-intel-aero-base/blob/master/recipes-kernel/linux/linux-yocto/shisp_2401a0_v21.bin
-
-NOTE:
-=====
-
-This driver currently doesn't work with most V4L2 applications,
-as there are still some issues with regards to implementing
-certain APIs at the standard way.
-
-Also, currently only USERPTR streaming mode is working.
-
-In order to test, it is needed to know what's the sensor's
-resolution. This can be checked with:
-
-$ v4l2-ctl --get-fmt-video
- Format Video Capture:
- Width/Height : 1600/1200
- ...
+ With a version of "irci_stable_candrpv_0415_20150423_1753" to check
+ the version run: "strings shisp_2400b0_v21.bin | head -n1", sha256sum:
-It is known to work with:
+ 3847b95fb9f1f8352c595ba7394d55b33176751372baae17f89aa483ec02a21b shisp_2400b0_v21.bin
-- v4l2grab at contrib/test directory at https://git.linuxtv.org/v4l-utils.git/
+ The shisp_2400b0_v21.bin file with this version can be found on
+ the Android factory images of various X86 Android tablets such as
+ e.g. the Chuwi Hi8 Pro.
- The resolution should not be bigger than the max resolution
- supported by the sensor, or it will fail. So, if the sensor
- reports:
-
- The driver can be tested with:
-
- v4l2grab -f YUYV -x 1600 -y 1200 -d /dev/video2 -u
+- for CHT: /lib/firmware/shisp_2401a0_v21.bin
-- NVT at https://github.com/intel/nvt
+ With a version of "irci_stable_candrpv_0415_20150521_0458", sha256sum:
- $ ./v4l2n -o testimage_@.raw \
- --device /dev/video2 \
- --input 0 \
- --exposure=30000,30000,30000,30000 \
- --parm type=1,capturemode=CI_MODE_PREVIEW \
- --fmt type=1,width=1600,height=1200,pixelformat=YUYV \
- --reqbufs count=2,memory=USERPTR \
- --parameters=wb_config.r=32768,wb_config.gr=21043,wb_config.gb=21043,wb_config.b=30863 \
- --capture=20
+ e89359f4e4934c410c83d525e283f34c5fcce9cb5caa75ad8a32d66d3842d95c shisp_2401a0_v21.bin
- As the output is in raw format, images need to be converted with:
+ This can be found here:
+ https://github.com/intel-aero/meta-intel-aero-base/blob/master/recipes-kernel/linux/linux-yocto/shisp_2401a0_v21.bin
- $ for i in $(seq 0 19); do
- name="testimage_$(printf "%03i" $i)"
- ./raw2pnm -x$WIDTH -y$HEIGHT -f$FORMAT $name.raw $name.pnm
- rm $name.raw
- done
TODO
====
-1. Fix support for MMAP streaming mode. This is required for most
- V4L2 applications;
-
-2. Implement and/or fix V4L2 ioctls in order to allow a normal app to
- use it;
-
-3. Ensure that the driver will pass v4l2-compliance tests;
-
-4. Get manufacturer's authorization to redistribute the binaries for
- the firmware files;
-
-5. remove VIDEO_ATOMISP_ISP2401, making the driver to auto-detect the
- register address differences between ISP2400 and ISP2401;
-
-6. Cleanup the driver code, removing the abstraction layers inside it;
-
-7. The atomisp doesn't rely at the usual i2c stuff to discover the
- sensors. Instead, it calls a function from atomisp_gmin_platform.c.
- There are some hacks added there for it to wait for sensors to be
- probed (with a timeout of 2 seconds or so). This should be converted
- to the usual way, using V4L2 async subdev framework to wait for
- cameras to be probed;
-
-8. Switch to standard V4L2 sub-device API for sensor and lens. In
- particular, the user space API needs to support V4L2 controls as
- defined in the V4L2 spec and references to atomisp must be removed from
- these drivers.
-
-9. Use LED flash API for flash LED drivers such as LM3554 (which already
- has a LED class driver).
-
-10. Migrate the sensor drivers out of staging or re-using existing
- drivers;
-
-11. Switch the driver to use pm_runtime stuff. Right now, it probes the
- existing PMIC code and sensors call it directly.
-
-12. There's a problem on sensor drivers: when trying to set a video
- format, the atomisp main driver calls the sensor drivers with the
- sensor turned off. This causes them to fail.
-
- This was fixed at atomisp-ov2880, which has a hack inside it
- to turn it on when VIDIOC_S_FMT is called, but this has to be
- cheked on other drivers as well.
-
- The right fix seems to power on the sensor when a video device is
- opened (or at the first VIDIOC_ ioctl - except for VIDIOC_QUERYCAP),
- powering it down at close() syscall.
-
- Such kind of control would need to be done inside the atomisp driver,
- not at the sensors code.
-
-13. There are several issues related to memory management, that can
- cause crashes and/or memory leaks. The atomisp splits the memory
- management on three separate regions:
-
- - dynamic pool;
- - reserved pool;
- - generic pool
-
- The code implementing it is at:
-
- drivers/staging/media/atomisp/pci/hmm/
+1. Items which MUST be fixed before the driver can be moved out of staging:
- It also has a separate code for managing DMA buffers at:
+* The atomisp ov2680 and ov5693 sensor drivers bind to the same hw-ids as
+ the standard ov2680 and ov5693 drivers under drivers/media/i2c, which
+ conflicts. Drop the atomisp private ov2680 and ov5693 drivers:
+ * Port various ov2680 improvements from atomisp_ov2680.c to regular ov2680.c
+ and switch to regular ov2680 driver
+ * Make atomisp work with the regular ov5693 driver and drop atomisp_ov5693
- drivers/staging/media/atomisp/pci/mmu/
+* Fix atomisp causing the whole machine to hang in its probe() error-exit
+ path taken in the firmware missing case
- The code there is really dirty, ugly and probably wrong. I fixed
- one bug there already, but the best would be to just trash it and use
- something else. Maybe the code from the newer intel driver could
- serve as a model:
+* Remove/disable private IOCTLs
- drivers/staging/media/ipu3/ipu3-mmu.c
+* Remove/disable custom v4l2-ctrls
- But converting it to use something like that is painful and may
- cause some breakages.
+* Remove custom sysfs files created by atomisp_drvfs.c
-14. The file structure needs to get tidied up to resemble a normal Linux
- driver.
+* Remove abuse of priv field in various v4l2 userspace API structs
-15. Lots of the midlayer glue. Unused code and abstraction needs removing.
+* Without a 3A library the capture behaviour is not very good. To take a good
+ picture, the exposure/gain needs to be tuned using v4l2-ctl on the sensor
+ subdev. To fix this, support for the atomisp needs to be added to libcamera.
-16. The AtomISP driver includes some special IOCTLS (ATOMISP_IOC_XXXX_XXXX)
- and controls that require some cleanup. Some of those code may have
- been removed during the cleanups. They could be needed in order to
- properly support 3A algorithms.
+ This MUST be done before moving the driver out of staging so that we can
+ still make changes to e.g. the mediactl topology if necessary for
+ libcamera integration. Since this would be a userspace API break, this
+ means that at least proof-of-concept libcamera integration needs to be
+ ready before moving the driver out of staging.
- Such IOCTL interface needs more documentation. The better would
- be to use something close to the interface used by the IPU3 IMGU driver.
-17. The ISP code has some dependencies of the exact FW version.
- The version defined in pci/sh_css_firmware.c:
+2. Items which SHOULD also be fixed eventually:
- BYT (isp2400): "irci_stable_candrpv_0415_20150521_0458"
+* Remove VIDEO_ATOMISP_ISP2401, making the driver to auto-detect the
+ register address differences between ISP2400 and ISP2401
- CHT (isp2401): "irci_ecr - master_20150911_0724"
+* The driver is intended to drive the PCI exposed versions of the device.
+ It will not detect those devices enumerated via ACPI as a field of the
+ i915 GPU driver (only a problem on BYT).
- Those versions don't seem to be available anymore. On the tests we've
- done so far, this version also seems to work for CHT:
+ There are some patches adding i915 GPU support floating at the Yocto's
+ Aero repository (so far, untested upstream).
- "irci_stable_candrpv_0415_20150521_0458"
+* Ensure that the driver will pass v4l2-compliance tests
- Which can be obtainable from Yocto Atom ISP respository.
+* Fix not all v4l2 apps working, e.g. cheese does not work
- but this was not thoroughly tested.
+* Get manufacturer's authorization to redistribute the binaries for
+ the firmware files
- At some point we may need to round up a few driver versions and see if
- there are any specific things that can be done to fold in support for
- multiple firmware versions.
+* The atomisp code still has a lot of cruft which needs cleaning up
-18. Switch from videobuf1 to videobuf2. Videobuf1 is being removed!
+Testing
+=======
-19. Correct Coding Style. Please refrain sending coding style patches
- for this driver until the other work is done, as there will be a lot
- of code churn until this driver becomes functional again.
+Since libcamera support is not available yet, the easiest way to test for
+now is using v4l2-ctl to select the input and gstreamer for streaming.
-20. Remove the logic which sets up pipelines inside it, moving it to
- libcamera and implement MC support.
+To select the input run:
+v4l2-ctl -i <input>
-Limitations
-===========
+Where <input> is 0 (front cam) or 1 (back cam).
-1. To test the patches, you also need the ISP firmware
+The simplest gstreamer pipeline for testing running the sensor
+at its max resolution is:
- for BYT: /lib/firmware/shisp_2400b0_v21.bin
- for CHT: /lib/firmware/shisp_2401a0_v21.bin
+gst-launch-1.0 v4l2src ! videoconvert ! xvimagesink sync=false
- The firmware files will usually be found in /etc/firmware on an Android
- device but can also be extracted from the upgrade kit if you've managed
- to lose them somehow.
+To select e.g 640x480 as resolution use:
-2. Without a 3A library the capture behaviour is not very good. To take a good
- picture, you need tune ISP parameters by IOCTL functions or use a 3A library
- such as libxcam.
+gst-launch-1.0 v4l2src ! video/x-raw,format=YV12,width=640,height=480 ! \
+ videoconvert ! xvimagesink sync=false
-3. The driver is intended to drive the PCI exposed versions of the device.
- It will not detect those devices enumerated via ACPI as a field of the
- i915 GPU driver.
+And to show fps use:
- There are some patches adding i915 GPU support floating at the Yocto's
- Aero repository (so far, untested upstream).
+gst-launch-1.0 v4l2src ! video/x-raw,format=YV12,width=640,height=480 ! \
+ videoconvert ! fpsdisplaysink video-sink=xvimagesink sync=false
-4. The driver supports only v2 of the IPU/Camera. It will not work with the
- versions of the hardware in other SoCs.
+Often the image will be over / under exposed. This can be fixed by using
+v4l2-ctl on the sensor subdev to tweak the exposure ctrl; or by using a GUI
+app for v4l2-controls which also supports subdev such as the Fedora patched
+gtk-v4l tool.
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
index 273155308fe3..9a11793f34f7 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
@@ -16,27 +16,259 @@
*
*/
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kmod.h>
-#include <linux/device.h>
#include <linux/delay.h>
-#include <linux/slab.h>
+#include <linux/errno.h>
#include <linux/gpio/consumer.h>
-#include <linux/gpio/machine.h>
#include <linux/i2c.h>
-#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/pm_runtime.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
-#include <linux/io.h>
-#include "../include/linux/atomisp_gmin_platform.h"
-#include "gc0310.h"
+#define GC0310_NATIVE_WIDTH 656
+#define GC0310_NATIVE_HEIGHT 496
+
+#define GC0310_FPS 30
+#define GC0310_SKIP_FRAMES 3
+
+#define GC0310_FOCAL_LENGTH_NUM 278 /* 2.78mm */
+
+#define GC0310_ID 0xa310
+
+#define GC0310_RESET_RELATED 0xFE
+#define GC0310_REGISTER_PAGE_0 0x0
+#define GC0310_REGISTER_PAGE_3 0x3
+
+/*
+ * GC0310 System control registers
+ */
+#define GC0310_SW_STREAM 0x10
+
+#define GC0310_SC_CMMN_CHIP_ID_H 0xf0
+#define GC0310_SC_CMMN_CHIP_ID_L 0xf1
+
+#define GC0310_AEC_PK_EXPO_H 0x03
+#define GC0310_AEC_PK_EXPO_L 0x04
+#define GC0310_AGC_ADJ 0x48
+#define GC0310_DGC_ADJ 0x71
+#define GC0310_GROUP_ACCESS 0x3208
+
+#define GC0310_H_CROP_START_H 0x09
+#define GC0310_H_CROP_START_L 0x0A
+#define GC0310_V_CROP_START_H 0x0B
+#define GC0310_V_CROP_START_L 0x0C
+#define GC0310_H_OUTSIZE_H 0x0F
+#define GC0310_H_OUTSIZE_L 0x10
+#define GC0310_V_OUTSIZE_H 0x0D
+#define GC0310_V_OUTSIZE_L 0x0E
+#define GC0310_H_BLANKING_H 0x05
+#define GC0310_H_BLANKING_L 0x06
+#define GC0310_V_BLANKING_H 0x07
+#define GC0310_V_BLANKING_L 0x08
+#define GC0310_SH_DELAY 0x11
+
+#define GC0310_START_STREAMING 0x94 /* 8-bit enable */
+#define GC0310_STOP_STREAMING 0x0 /* 8-bit disable */
+
+#define to_gc0310_sensor(x) container_of(x, struct gc0310_device, sd)
+
+struct gc0310_device {
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+ /* Protect against concurrent changes to controls */
+ struct mutex input_lock;
+ bool is_streaming;
+
+ struct fwnode_handle *ep_fwnode;
+ struct gpio_desc *reset;
+ struct gpio_desc *powerdown;
+
+ struct gc0310_mode {
+ struct v4l2_mbus_framefmt fmt;
+ } mode;
+
+ struct gc0310_ctrls {
+ struct v4l2_ctrl_handler handler;
+ struct v4l2_ctrl *exposure;
+ struct v4l2_ctrl *gain;
+ } ctrls;
+};
+
+struct gc0310_reg {
+ u8 reg;
+ u8 val;
+};
+
+static const struct gc0310_reg gc0310_reset_register[] = {
+ /* System registers */
+ { 0xfe, 0xf0 },
+ { 0xfe, 0xf0 },
+ { 0xfe, 0x00 },
+
+ { 0xfc, 0x0e }, /* 4e */
+ { 0xfc, 0x0e }, /* 16//4e // [0]apwd [6]regf_clk_gate */
+ { 0xf2, 0x80 }, /* sync output */
+ { 0xf3, 0x00 }, /* 1f//01 data output */
+ { 0xf7, 0x33 }, /* f9 */
+ { 0xf8, 0x05 }, /* 00 */
+ { 0xf9, 0x0e }, /* 0x8e //0f */
+ { 0xfa, 0x11 },
+
+ /* MIPI */
+ { 0xfe, 0x03 },
+ { 0x01, 0x03 }, /* mipi 1lane */
+ { 0x02, 0x22 }, /* 0x33 */
+ { 0x03, 0x94 },
+ { 0x04, 0x01 }, /* fifo_prog */
+ { 0x05, 0x00 }, /* fifo_prog */
+ { 0x06, 0x80 }, /* b0 //YUV ISP data */
+ { 0x11, 0x2a }, /* 1e //LDI set YUV422 */
+ { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */
+ { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */
+ { 0x15, 0x12 }, /* 0x10 //DPHYY_MODE read_ready */
+ { 0x17, 0x01 },
+ { 0x40, 0x08 },
+ { 0x41, 0x00 },
+ { 0x42, 0x00 },
+ { 0x43, 0x00 },
+ { 0x21, 0x02 }, /* 0x01 */
+ { 0x22, 0x02 }, /* 0x01 */
+ { 0x23, 0x01 }, /* 0x05 //Nor:0x05 DOU:0x06 */
+ { 0x29, 0x00 },
+ { 0x2A, 0x25 }, /* 0x05 //data zero 0x7a de */
+ { 0x2B, 0x02 },
+
+ { 0xfe, 0x00 },
+
+ /* CISCTL */
+ { 0x00, 0x2f }, /* 2f//0f//02//01 */
+ { 0x01, 0x0f }, /* 06 */
+ { 0x02, 0x04 },
+ { 0x4f, 0x00 }, /* AEC 0FF */
+ { 0x03, 0x01 }, /* 0x03 //04 */
+ { 0x04, 0xc0 }, /* 0xe8 //58 */
+ { 0x05, 0x00 },
+ { 0x06, 0xb2 }, /* 0x0a //HB */
+ { 0x07, 0x00 },
+ { 0x08, 0x0c }, /* 0x89 //VB */
+ { 0x09, 0x00 }, /* row start */
+ { 0x0a, 0x00 },
+ { 0x0b, 0x00 }, /* col start */
+ { 0x0c, 0x00 },
+ { 0x0d, 0x01 }, /* height */
+ { 0x0e, 0xf2 }, /* 0xf7 //height */
+ { 0x0f, 0x02 }, /* width */
+ { 0x10, 0x94 }, /* 0xa0 //height */
+ { 0x17, 0x14 },
+ { 0x18, 0x1a }, /* 0a//[4]double reset */
+ { 0x19, 0x14 }, /* AD pipeline */
+ { 0x1b, 0x48 },
+ { 0x1e, 0x6b }, /* 3b//col bias */
+ { 0x1f, 0x28 }, /* 20//00//08//txlow */
+ { 0x20, 0x89 }, /* 88//0c//[3:2]DA15 */
+ { 0x21, 0x49 }, /* 48//[3] txhigh */
+ { 0x22, 0xb0 },
+ { 0x23, 0x04 }, /* [1:0]vcm_r */
+ { 0x24, 0x16 }, /* 15 */
+ { 0x34, 0x20 }, /* [6:4] rsg high//range */
+
+ /* BLK */
+ { 0x26, 0x23 }, /* [1]dark_current_en [0]offset_en */
+ { 0x28, 0xff }, /* BLK_limie_value */
+ { 0x29, 0x00 }, /* global offset */
+ { 0x33, 0x18 }, /* offset_ratio */
+ { 0x37, 0x20 }, /* dark_current_ratio */
+ { 0x2a, 0x00 },
+ { 0x2b, 0x00 },
+ { 0x2c, 0x00 },
+ { 0x2d, 0x00 },
+ { 0x2e, 0x00 },
+ { 0x2f, 0x00 },
+ { 0x30, 0x00 },
+ { 0x31, 0x00 },
+ { 0x47, 0x80 }, /* a7 */
+ { 0x4e, 0x66 }, /* select_row */
+ { 0xa8, 0x02 }, /* win_width_dark, same with crop_win_width */
+ { 0xa9, 0x80 },
+
+ /* ISP */
+ { 0x40, 0x06 }, /* 0xff //ff //48 */
+ { 0x41, 0x00 }, /* 0x21 //00//[0]curve_en */
+ { 0x42, 0x04 }, /* 0xcf //0a//[1]awn_en */
+ { 0x44, 0x18 }, /* 0x18 //02 */
+ { 0x46, 0x02 }, /* 0x03 //sync */
+ { 0x49, 0x03 },
+ { 0x4c, 0x20 }, /* 00[5]pretect exp */
+ { 0x50, 0x01 }, /* crop enable */
+ { 0x51, 0x00 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x01 },
+ { 0x55, 0x01 }, /* crop window height */
+ { 0x56, 0xf0 },
+ { 0x57, 0x02 }, /* crop window width */
+ { 0x58, 0x90 },
+
+ /* Gain */
+ { 0x70, 0x70 }, /* 70 //80//global gain */
+ { 0x71, 0x20 }, /* pregain gain */
+ { 0x72, 0x40 }, /* post gain */
+ { 0x5a, 0x84 }, /* 84//analog gain 0 */
+ { 0x5b, 0xc9 }, /* c9 */
+ { 0x5c, 0xed }, /* ed//not use pga gain highest level */
+ { 0x77, 0x40 }, /* R gain 0x74 //awb gain */
+ { 0x78, 0x40 }, /* G gain */
+ { 0x79, 0x40 }, /* B gain 0x5f */
+
+ { 0x48, 0x00 },
+ { 0xfe, 0x01 },
+ { 0x0a, 0x45 }, /* [7]col gain mode */
+
+ { 0x3e, 0x40 },
+ { 0x3f, 0x5c },
+ { 0x40, 0x7b },
+ { 0x41, 0xbd },
+ { 0x42, 0xf6 },
+ { 0x43, 0x63 },
+ { 0x03, 0x60 },
+ { 0x44, 0x03 },
+
+ /* Dark / Sun mode related */
+ { 0xfe, 0x01 },
+ { 0x45, 0xa4 }, /* 0xf7 */
+ { 0x46, 0xf0 }, /* 0xff //f0//sun value th */
+ { 0x48, 0x03 }, /* sun mode */
+ { 0x4f, 0x60 }, /* sun_clamp */
+ { 0xfe, 0x00 },
+};
+
+static const struct gc0310_reg gc0310_VGA_30fps[] = {
+ { 0xfe, 0x00 },
+ { 0x0d, 0x01 }, /* height */
+ { 0x0e, 0xf2 }, /* 0xf7 //height */
+ { 0x0f, 0x02 }, /* width */
+ { 0x10, 0x94 }, /* 0xa0 //height */
+
+ { 0x50, 0x01 }, /* crop enable */
+ { 0x51, 0x00 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x01 },
+ { 0x55, 0x01 }, /* crop window height */
+ { 0x56, 0xf0 },
+ { 0x57, 0x02 }, /* crop window width */
+ { 0x58, 0x90 },
+
+ { 0xfe, 0x03 },
+ { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */
+ { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */
+
+ { 0xfe, 0x00 },
+};
/*
* gc0310_write_reg_array - Initializes a list of GC0310 registers
@@ -179,7 +411,10 @@ static int gc0310_detect(struct i2c_client *client)
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
return -ENODEV;
- ret = i2c_smbus_read_word_swapped(client, GC0310_SC_CMMN_CHIP_ID_H);
+ ret = pm_runtime_get_sync(&client->dev);
+ if (ret >= 0)
+ ret = i2c_smbus_read_word_swapped(client, GC0310_SC_CMMN_CHIP_ID_H);
+ pm_runtime_put(&client->dev);
if (ret < 0) {
dev_err(&client->dev, "read sensor_id failed: %d\n", ret);
return -ENODEV;
@@ -268,19 +503,6 @@ error_unlock:
return ret;
}
-static int gc0310_s_config(struct v4l2_subdev *sd)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- int ret;
-
- ret = pm_runtime_get_sync(&client->dev);
- if (ret >= 0)
- ret = gc0310_detect(client);
-
- pm_runtime_put(&client->dev);
- return ret;
-}
-
static int gc0310_g_frame_interval(struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval)
{
@@ -373,12 +595,12 @@ static void gc0310_remove(struct i2c_client *client)
dev_dbg(&client->dev, "gc0310_remove...\n");
- atomisp_unregister_subdev(sd);
- v4l2_device_unregister_subdev(sd);
+ v4l2_async_unregister_subdev(sd);
media_entity_cleanup(&dev->sd.entity);
v4l2_ctrl_handler_free(&dev->ctrls.handler);
+ mutex_destroy(&dev->input_lock);
+ fwnode_handle_put(dev->ep_fwnode);
pm_runtime_disable(&client->dev);
- kfree(dev);
}
static int gc0310_probe(struct i2c_client *client)
@@ -390,19 +612,27 @@ static int gc0310_probe(struct i2c_client *client)
if (!dev)
return -ENOMEM;
- ret = v4l2_get_acpi_sensor_info(&client->dev, NULL);
- if (ret)
- return ret;
+ /*
+ * Sometimes the fwnode graph is initialized by the bridge driver.
+ * Bridge drivers doing this may also add GPIO mappings, wait for this.
+ */
+ dev->ep_fwnode = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
+ if (!dev->ep_fwnode)
+ return dev_err_probe(&client->dev, -EPROBE_DEFER, "waiting for fwnode graph endpoint\n");
dev->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
- if (IS_ERR(dev->reset))
+ if (IS_ERR(dev->reset)) {
+ fwnode_handle_put(dev->ep_fwnode);
return dev_err_probe(&client->dev, PTR_ERR(dev->reset),
"getting reset GPIO\n");
+ }
dev->powerdown = devm_gpiod_get(&client->dev, "powerdown", GPIOD_OUT_HIGH);
- if (IS_ERR(dev->powerdown))
+ if (IS_ERR(dev->powerdown)) {
+ fwnode_handle_put(dev->ep_fwnode);
return dev_err_probe(&client->dev, PTR_ERR(dev->powerdown),
"getting powerdown GPIO\n");
+ }
mutex_init(&dev->input_lock);
v4l2_i2c_subdev_init(&dev->sd, client, &gc0310_ops);
@@ -413,7 +643,7 @@ static int gc0310_probe(struct i2c_client *client)
pm_runtime_set_autosuspend_delay(&client->dev, 1000);
pm_runtime_use_autosuspend(&client->dev);
- ret = gc0310_s_config(&dev->sd);
+ ret = gc0310_detect(client);
if (ret) {
gc0310_remove(client);
return ret;
@@ -422,6 +652,7 @@ static int gc0310_probe(struct i2c_client *client)
dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
dev->pad.flags = MEDIA_PAD_FL_SOURCE;
dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+ dev->sd.fwnode = dev->ep_fwnode;
ret = gc0310_init_controls(dev);
if (ret) {
@@ -435,8 +666,7 @@ static int gc0310_probe(struct i2c_client *client)
return ret;
}
- ret = atomisp_register_sensor_no_gmin(&dev->sd, 1, ATOMISP_INPUT_FORMAT_RAW_8,
- atomisp_bayer_order_grbg);
+ ret = v4l2_async_register_subdev_sensor(&dev->sd);
if (ret) {
gc0310_remove(client);
return ret;
@@ -471,7 +701,6 @@ static int gc0310_resume(struct device *dev)
static DEFINE_RUNTIME_DEV_PM_OPS(gc0310_pm_ops, gc0310_suspend, gc0310_resume, NULL);
static const struct acpi_device_id gc0310_acpi_match[] = {
- {"XXGC0310"},
{"INT0310"},
{},
};
@@ -483,7 +712,7 @@ static struct i2c_driver gc0310_driver = {
.pm = pm_sleep_ptr(&gc0310_pm_ops),
.acpi_match_table = gc0310_acpi_match,
},
- .probe_new = gc0310_probe,
+ .probe = gc0310_probe,
.remove = gc0310_remove,
};
module_i2c_driver(gc0310_driver);
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
index cb4c79b483ca..9fa390fbc5f3 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
@@ -864,7 +864,7 @@ static struct i2c_driver gc2235_driver = {
.name = "gc2235",
.acpi_match_table = gc2235_acpi_match,
},
- .probe_new = gc2235_probe,
+ .probe = gc2235_probe,
.remove = gc2235_remove,
};
module_i2c_driver(gc2235_driver);
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c
index c4ce4cd445d7..cf5d9317b11a 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c
@@ -945,7 +945,7 @@ static struct i2c_driver lm3554_driver = {
.pm = &lm3554_pm_ops,
.acpi_match_table = lm3554_acpi_match,
},
- .probe_new = lm3554_probe,
+ .probe = lm3554_probe,
.remove = lm3554_remove,
};
module_i2c_driver(lm3554_driver);
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
index 0e5a981dd331..1c6643c442ef 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
@@ -1600,7 +1600,7 @@ static struct i2c_driver mt9m114_driver = {
.name = "mt9m114",
.acpi_match_table = mt9m114_acpi_match,
},
- .probe_new = mt9m114_probe,
+ .probe = mt9m114_probe,
.remove = mt9m114_remove,
};
module_i2c_driver(mt9m114_driver);
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
index c079368019e8..4cc2839937af 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
@@ -28,15 +28,13 @@
#include <media/ov_16bit_addr_reg_helpers.h>
#include <media/v4l2-device.h>
-#include "../include/linux/atomisp_gmin_platform.h"
-
#include "ov2680.h"
-static enum atomisp_bayer_order ov2680_bayer_order_mapping[] = {
- atomisp_bayer_order_bggr,
- atomisp_bayer_order_grbg,
- atomisp_bayer_order_gbrg,
- atomisp_bayer_order_rggb,
+static const struct v4l2_rect ov2680_default_crop = {
+ .left = OV2680_ACTIVE_START_LEFT,
+ .top = OV2680_ACTIVE_START_TOP,
+ .width = OV2680_ACTIVE_WIDTH,
+ .height = OV2680_ACTIVE_HEIGHT,
};
static int ov2680_write_reg_array(struct i2c_client *client,
@@ -54,7 +52,7 @@ static int ov2680_write_reg_array(struct i2c_client *client,
return 0;
}
-static void ov2680_set_bayer_order(struct ov2680_device *sensor, struct v4l2_mbus_framefmt *fmt)
+static void ov2680_set_bayer_order(struct ov2680_dev *sensor, struct v4l2_mbus_framefmt *fmt)
{
static const int ov2680_hv_flip_bayer_order[] = {
MEDIA_BUS_FMT_SBGGR10_1X10,
@@ -62,7 +60,6 @@ static void ov2680_set_bayer_order(struct ov2680_device *sensor, struct v4l2_mbu
MEDIA_BUS_FMT_SGBRG10_1X10,
MEDIA_BUS_FMT_SRGGB10_1X10,
};
- struct camera_mipi_info *ov2680_info;
int hv_flip = 0;
if (sensor->ctrls.vflip->val)
@@ -72,14 +69,9 @@ static void ov2680_set_bayer_order(struct ov2680_device *sensor, struct v4l2_mbu
hv_flip += 2;
fmt->code = ov2680_hv_flip_bayer_order[hv_flip];
-
- /* TODO atomisp specific custom API, should be removed */
- ov2680_info = v4l2_get_subdev_hostdata(&sensor->sd);
- if (ov2680_info)
- ov2680_info->raw_bayer_order = ov2680_bayer_order_mapping[hv_flip];
}
-static int ov2680_set_vflip(struct ov2680_device *sensor, s32 val)
+static int ov2680_set_vflip(struct ov2680_dev *sensor, s32 val)
{
int ret;
@@ -94,7 +86,7 @@ static int ov2680_set_vflip(struct ov2680_device *sensor, s32 val)
return 0;
}
-static int ov2680_set_hflip(struct ov2680_device *sensor, s32 val)
+static int ov2680_set_hflip(struct ov2680_dev *sensor, s32 val)
{
int ret;
@@ -109,17 +101,17 @@ static int ov2680_set_hflip(struct ov2680_device *sensor, s32 val)
return 0;
}
-static int ov2680_exposure_set(struct ov2680_device *sensor, u32 exp)
+static int ov2680_exposure_set(struct ov2680_dev *sensor, u32 exp)
{
return ov_write_reg24(sensor->client, OV2680_REG_EXPOSURE_PK_HIGH, exp << 4);
}
-static int ov2680_gain_set(struct ov2680_device *sensor, u32 gain)
+static int ov2680_gain_set(struct ov2680_dev *sensor, u32 gain)
{
return ov_write_reg16(sensor->client, OV2680_REG_GAIN_PK, gain);
}
-static int ov2680_test_pattern_set(struct ov2680_device *sensor, int value)
+static int ov2680_test_pattern_set(struct ov2680_dev *sensor, int value)
{
int ret;
@@ -140,7 +132,7 @@ static int ov2680_test_pattern_set(struct ov2680_device *sensor, int value)
static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
- struct ov2680_device *sensor = to_ov2680_sensor(sd);
+ struct ov2680_dev *sensor = to_ov2680_sensor(sd);
int ret;
/* Only apply changes to the controls if the device is powered up */
@@ -183,14 +175,17 @@ static int ov2680_init_registers(struct v4l2_subdev *sd)
int ret;
ret = ov_write_reg8(client, OV2680_SW_RESET, 0x01);
+
+ /* Wait for sensor reset */
+ usleep_range(1000, 2000);
+
ret |= ov2680_write_reg_array(client, ov2680_global_setting);
return ret;
}
static struct v4l2_mbus_framefmt *
-__ov2680_get_pad_format(struct ov2680_device *sensor,
- struct v4l2_subdev_state *state,
+__ov2680_get_pad_format(struct ov2680_dev *sensor, struct v4l2_subdev_state *state,
unsigned int pad, enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
@@ -199,7 +194,17 @@ __ov2680_get_pad_format(struct ov2680_device *sensor,
return &sensor->mode.fmt;
}
-static void ov2680_fill_format(struct ov2680_device *sensor,
+static struct v4l2_rect *
+__ov2680_get_pad_crop(struct ov2680_dev *sensor, struct v4l2_subdev_state *state,
+ unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+ if (which == V4L2_SUBDEV_FORMAT_TRY)
+ return v4l2_subdev_get_try_crop(&sensor->sd, state, pad);
+
+ return &sensor->mode.crop;
+}
+
+static void ov2680_fill_format(struct ov2680_dev *sensor,
struct v4l2_mbus_framefmt *fmt,
unsigned int width, unsigned int height)
{
@@ -210,13 +215,15 @@ static void ov2680_fill_format(struct ov2680_device *sensor,
ov2680_set_bayer_order(sensor, fmt);
}
-static void ov2680_calc_mode(struct ov2680_device *sensor, int width, int height)
+static void ov2680_calc_mode(struct ov2680_dev *sensor)
{
+ int width = sensor->mode.fmt.width;
+ int height = sensor->mode.fmt.height;
int orig_width = width;
int orig_height = height;
- if (width <= (OV2680_NATIVE_WIDTH / 2) &&
- height <= (OV2680_NATIVE_HEIGHT / 2)) {
+ if (width <= (sensor->mode.crop.width / 2) &&
+ height <= (sensor->mode.crop.height / 2)) {
sensor->mode.binning = true;
width *= 2;
height *= 2;
@@ -224,8 +231,10 @@ static void ov2680_calc_mode(struct ov2680_device *sensor, int width, int height
sensor->mode.binning = false;
}
- sensor->mode.h_start = ((OV2680_NATIVE_WIDTH - width) / 2) & ~1;
- sensor->mode.v_start = ((OV2680_NATIVE_HEIGHT - height) / 2) & ~1;
+ sensor->mode.h_start =
+ (sensor->mode.crop.left + (sensor->mode.crop.width - width) / 2) & ~1;
+ sensor->mode.v_start =
+ (sensor->mode.crop.top + (sensor->mode.crop.height - height) / 2) & ~1;
sensor->mode.h_end = min(sensor->mode.h_start + width + OV2680_END_MARGIN - 1,
OV2680_NATIVE_WIDTH - 1);
sensor->mode.v_end = min(sensor->mode.v_start + height + OV2680_END_MARGIN - 1,
@@ -236,31 +245,25 @@ static void ov2680_calc_mode(struct ov2680_device *sensor, int width, int height
sensor->mode.vts = OV2680_LINES_PER_FRAME;
}
-static int ov2680_set_mode(struct ov2680_device *sensor)
+static int ov2680_set_mode(struct ov2680_dev *sensor)
{
struct i2c_client *client = sensor->client;
- u8 pll_div, unknown, inc, fmt1, fmt2;
+ u8 sensor_ctrl_0a, inc, fmt1, fmt2;
int ret;
if (sensor->mode.binning) {
- pll_div = 1;
- unknown = 0x23;
+ sensor_ctrl_0a = 0x23;
inc = 0x31;
fmt1 = 0xc2;
fmt2 = 0x01;
} else {
- pll_div = 0;
- unknown = 0x21;
+ sensor_ctrl_0a = 0x21;
inc = 0x11;
fmt1 = 0xc0;
fmt2 = 0x00;
}
- ret = ov_write_reg8(client, 0x3086, pll_div);
- if (ret)
- return ret;
-
- ret = ov_write_reg8(client, 0x370a, unknown);
+ ret = ov_write_reg8(client, OV2680_REG_SENSOR_CTRL_0A, sensor_ctrl_0a);
if (ret)
return ret;
@@ -337,12 +340,18 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
- struct ov2680_device *sensor = to_ov2680_sensor(sd);
+ struct ov2680_dev *sensor = to_ov2680_sensor(sd);
struct v4l2_mbus_framefmt *fmt;
+ const struct v4l2_rect *crop;
unsigned int width, height;
- width = min_t(unsigned int, ALIGN(format->format.width, 2), OV2680_NATIVE_WIDTH);
- height = min_t(unsigned int, ALIGN(format->format.height, 2), OV2680_NATIVE_HEIGHT);
+ crop = __ov2680_get_pad_crop(sensor, sd_state, format->pad, format->which);
+
+ /* Limit set_fmt max size to crop width / height */
+ width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
+ OV2680_MIN_CROP_WIDTH, crop->width);
+ height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
+ OV2680_MIN_CROP_HEIGHT, crop->height);
fmt = __ov2680_get_pad_format(sensor, sd_state, format->pad, format->which);
ov2680_fill_format(sensor, fmt, width, height);
@@ -352,9 +361,9 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
return 0;
- mutex_lock(&sensor->input_lock);
- ov2680_calc_mode(sensor, fmt->width, fmt->height);
- mutex_unlock(&sensor->input_lock);
+ mutex_lock(&sensor->lock);
+ ov2680_calc_mode(sensor);
+ mutex_unlock(&sensor->lock);
return 0;
}
@@ -362,7 +371,7 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
- struct ov2680_device *sensor = to_ov2680_sensor(sd);
+ struct ov2680_dev *sensor = to_ov2680_sensor(sd);
struct v4l2_mbus_framefmt *fmt;
fmt = __ov2680_get_pad_format(sensor, sd_state, format->pad, format->which);
@@ -370,6 +379,105 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd,
return 0;
}
+static int ov2680_get_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_selection *sel)
+{
+ struct ov2680_dev *sensor = to_ov2680_sensor(sd);
+
+ switch (sel->target) {
+ case V4L2_SEL_TGT_CROP:
+ mutex_lock(&sensor->lock);
+ sel->r = *__ov2680_get_pad_crop(sensor, state, sel->pad, sel->which);
+ mutex_unlock(&sensor->lock);
+ break;
+ case V4L2_SEL_TGT_NATIVE_SIZE:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = OV2680_NATIVE_WIDTH;
+ sel->r.height = OV2680_NATIVE_HEIGHT;
+ break;
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ sel->r.top = OV2680_ACTIVE_START_TOP;
+ sel->r.left = OV2680_ACTIVE_START_LEFT;
+ sel->r.width = OV2680_ACTIVE_WIDTH;
+ sel->r.height = OV2680_ACTIVE_HEIGHT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ov2680_set_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_selection *sel)
+{
+ struct ov2680_dev *sensor = to_ov2680_sensor(sd);
+ struct v4l2_mbus_framefmt *format;
+ struct v4l2_rect *__crop;
+ struct v4l2_rect rect;
+
+ if (sel->target != V4L2_SEL_TGT_CROP)
+ return -EINVAL;
+
+ /*
+ * Clamp the boundaries of the crop rectangle to the size of the sensor
+ * pixel array. Align to multiples of 2 to ensure Bayer pattern isn't
+ * disrupted.
+ */
+ rect.left = clamp(ALIGN(sel->r.left, 2), OV2680_NATIVE_START_LEFT,
+ OV2680_NATIVE_WIDTH);
+ rect.top = clamp(ALIGN(sel->r.top, 2), OV2680_NATIVE_START_TOP,
+ OV2680_NATIVE_HEIGHT);
+ rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
+ OV2680_MIN_CROP_WIDTH, OV2680_NATIVE_WIDTH);
+ rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
+ OV2680_MIN_CROP_HEIGHT, OV2680_NATIVE_HEIGHT);
+
+ /* Make sure the crop rectangle isn't outside the bounds of the array */
+ rect.width = min_t(unsigned int, rect.width,
+ OV2680_NATIVE_WIDTH - rect.left);
+ rect.height = min_t(unsigned int, rect.height,
+ OV2680_NATIVE_HEIGHT - rect.top);
+
+ __crop = __ov2680_get_pad_crop(sensor, state, sel->pad, sel->which);
+
+ if (rect.width != __crop->width || rect.height != __crop->height) {
+ /*
+ * Reset the output image size if the crop rectangle size has
+ * been modified.
+ */
+ format = __ov2680_get_pad_format(sensor, state, sel->pad, sel->which);
+ format->width = rect.width;
+ format->height = rect.height;
+ }
+
+ *__crop = rect;
+ sel->r = rect;
+
+ return 0;
+}
+
+static int ov2680_init_cfg(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
+{
+ struct v4l2_subdev_format fmt = {
+ .which = sd_state ? V4L2_SUBDEV_FORMAT_TRY
+ : V4L2_SUBDEV_FORMAT_ACTIVE,
+ .format = {
+ .width = 800,
+ .height = 600,
+ },
+ };
+
+ sd_state->pads[0].try_crop = ov2680_default_crop;
+
+ return ov2680_set_fmt(sd, sd_state, &fmt);
+}
+
static int ov2680_detect(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
@@ -405,11 +513,11 @@ static int ov2680_detect(struct i2c_client *client)
static int ov2680_s_stream(struct v4l2_subdev *sd, int enable)
{
- struct ov2680_device *sensor = to_ov2680_sensor(sd);
+ struct ov2680_dev *sensor = to_ov2680_sensor(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
int ret = 0;
- mutex_lock(&sensor->input_lock);
+ mutex_lock(&sensor->lock);
if (sensor->is_streaming == enable) {
dev_warn(&client->dev, "stream already %s\n", enable ? "started" : "stopped");
@@ -442,14 +550,14 @@ static int ov2680_s_stream(struct v4l2_subdev *sd, int enable)
v4l2_ctrl_activate(sensor->ctrls.vflip, !enable);
v4l2_ctrl_activate(sensor->ctrls.hflip, !enable);
- mutex_unlock(&sensor->input_lock);
+ mutex_unlock(&sensor->lock);
return 0;
error_power_down:
pm_runtime_put(sensor->sd.dev);
sensor->is_streaming = false;
error_unlock:
- mutex_unlock(&sensor->input_lock);
+ mutex_unlock(&sensor->lock);
return ret;
}
@@ -550,11 +658,14 @@ static const struct v4l2_subdev_sensor_ops ov2680_sensor_ops = {
};
static const struct v4l2_subdev_pad_ops ov2680_pad_ops = {
+ .init_cfg = ov2680_init_cfg,
.enum_mbus_code = ov2680_enum_mbus_code,
.enum_frame_size = ov2680_enum_frame_size,
.enum_frame_interval = ov2680_enum_frame_interval,
.get_fmt = ov2680_get_fmt,
.set_fmt = ov2680_set_fmt,
+ .get_selection = ov2680_get_selection,
+ .set_selection = ov2680_set_selection,
};
static const struct v4l2_subdev_ops ov2680_ops = {
@@ -563,7 +674,7 @@ static const struct v4l2_subdev_ops ov2680_ops = {
.sensor = &ov2680_sensor_ops,
};
-static int ov2680_init_controls(struct ov2680_device *sensor)
+static int ov2680_init_controls(struct ov2680_dev *sensor)
{
static const char * const test_pattern_menu[] = {
"Disabled",
@@ -579,7 +690,7 @@ static int ov2680_init_controls(struct ov2680_device *sensor)
v4l2_ctrl_handler_init(hdl, 4);
- hdl->lock = &sensor->input_lock;
+ hdl->lock = &sensor->lock;
ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
@@ -605,39 +716,46 @@ static int ov2680_init_controls(struct ov2680_device *sensor)
static void ov2680_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
- struct ov2680_device *sensor = to_ov2680_sensor(sd);
+ struct ov2680_dev *sensor = to_ov2680_sensor(sd);
dev_dbg(&client->dev, "ov2680_remove...\n");
- atomisp_unregister_subdev(sd);
- v4l2_device_unregister_subdev(sd);
+ v4l2_async_unregister_subdev(&sensor->sd);
media_entity_cleanup(&sensor->sd.entity);
v4l2_ctrl_handler_free(&sensor->ctrls.handler);
+ mutex_destroy(&sensor->lock);
+ fwnode_handle_put(sensor->ep_fwnode);
pm_runtime_disable(&client->dev);
}
static int ov2680_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
- struct ov2680_device *sensor;
+ struct ov2680_dev *sensor;
int ret;
sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
if (!sensor)
return -ENOMEM;
- mutex_init(&sensor->input_lock);
+ mutex_init(&sensor->lock);
sensor->client = client;
v4l2_i2c_subdev_init(&sensor->sd, client, &ov2680_ops);
- ret = v4l2_get_acpi_sensor_info(dev, NULL);
- if (ret)
- return ret;
+ /*
+ * Sometimes the fwnode graph is initialized by the bridge driver.
+ * Bridge drivers doing this may also add GPIO mappings, wait for this.
+ */
+ sensor->ep_fwnode = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
+ if (!sensor->ep_fwnode)
+ return dev_err_probe(dev, -EPROBE_DEFER, "waiting for fwnode graph endpoint\n");
sensor->powerdown = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH);
- if (IS_ERR(sensor->powerdown))
+ if (IS_ERR(sensor->powerdown)) {
+ fwnode_handle_put(sensor->ep_fwnode);
return dev_err_probe(dev, PTR_ERR(sensor->powerdown), "getting powerdown GPIO\n");
+ }
pm_runtime_set_suspended(dev);
pm_runtime_enable(dev);
@@ -653,6 +771,7 @@ static int ov2680_probe(struct i2c_client *client)
sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+ sensor->sd.fwnode = sensor->ep_fwnode;
ret = ov2680_init_controls(sensor);
if (ret) {
@@ -666,10 +785,11 @@ static int ov2680_probe(struct i2c_client *client)
return ret;
}
+ sensor->mode.crop = ov2680_default_crop;
ov2680_fill_format(sensor, &sensor->mode.fmt, OV2680_NATIVE_WIDTH, OV2680_NATIVE_HEIGHT);
+ ov2680_calc_mode(sensor);
- ret = atomisp_register_sensor_no_gmin(&sensor->sd, 1, ATOMISP_INPUT_FORMAT_RAW_10,
- atomisp_bayer_order_bggr);
+ ret = v4l2_async_register_subdev_sensor(&sensor->sd);
if (ret) {
ov2680_remove(client);
return ret;
@@ -681,7 +801,7 @@ static int ov2680_probe(struct i2c_client *client)
static int ov2680_suspend(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
- struct ov2680_device *sensor = to_ov2680_sensor(sd);
+ struct ov2680_dev *sensor = to_ov2680_sensor(sd);
gpiod_set_value_cansleep(sensor->powerdown, 1);
return 0;
@@ -690,7 +810,7 @@ static int ov2680_suspend(struct device *dev)
static int ov2680_resume(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
- struct ov2680_device *sensor = to_ov2680_sensor(sd);
+ struct ov2680_dev *sensor = to_ov2680_sensor(sd);
/* according to DS, at least 5ms is needed after DOVDD (enabled by ACPI) */
usleep_range(5000, 6000);
@@ -719,7 +839,7 @@ static struct i2c_driver ov2680_driver = {
.pm = pm_sleep_ptr(&ov2680_pm_ops),
.acpi_match_table = ov2680_acpi_match,
},
- .probe_new = ov2680_probe,
+ .probe = ov2680_probe,
.remove = ov2680_remove,
};
module_i2c_driver(ov2680_driver);
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c
index 5d2e6e2e72f0..6a72691ed5b7 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c
@@ -1019,7 +1019,7 @@ static struct i2c_driver ov2722_driver = {
.name = "ov2722",
.acpi_match_table = ov2722_acpi_match,
},
- .probe_new = ov2722_probe,
+ .probe = ov2722_probe,
.remove = ov2722_remove,
};
module_i2c_driver(ov2722_driver);
diff --git a/drivers/staging/media/atomisp/i2c/gc0310.h b/drivers/staging/media/atomisp/i2c/gc0310.h
deleted file mode 100644
index d40406289598..000000000000
--- a/drivers/staging/media/atomisp/i2c/gc0310.h
+++ /dev/null
@@ -1,309 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Support for GalaxyCore GC0310 VGA camera sensor.
- *
- * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- *
- */
-
-#ifndef __GC0310_H__
-#define __GC0310_H__
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/i2c.h>
-#include <linux/acpi.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-#include <linux/spinlock.h>
-#include <media/v4l2-subdev.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-#include <linux/v4l2-mediabus.h>
-#include <media/media-entity.h>
-
-#include "../include/linux/atomisp_platform.h"
-
-#define GC0310_NATIVE_WIDTH 656
-#define GC0310_NATIVE_HEIGHT 496
-
-#define GC0310_FPS 30
-#define GC0310_SKIP_FRAMES 3
-
-#define GC0310_FOCAL_LENGTH_NUM 278 /* 2.78mm */
-
-#define GC0310_ID 0xa310
-
-#define GC0310_RESET_RELATED 0xFE
-#define GC0310_REGISTER_PAGE_0 0x0
-#define GC0310_REGISTER_PAGE_3 0x3
-
-#define GC0310_FINE_INTG_TIME_MIN 0
-#define GC0310_FINE_INTG_TIME_MAX_MARGIN 0
-#define GC0310_COARSE_INTG_TIME_MIN 1
-#define GC0310_COARSE_INTG_TIME_MAX_MARGIN 6
-
-/*
- * GC0310 System control registers
- */
-#define GC0310_SW_STREAM 0x10
-
-#define GC0310_SC_CMMN_CHIP_ID_H 0xf0
-#define GC0310_SC_CMMN_CHIP_ID_L 0xf1
-
-#define GC0310_AEC_PK_EXPO_H 0x03
-#define GC0310_AEC_PK_EXPO_L 0x04
-#define GC0310_AGC_ADJ 0x48
-#define GC0310_DGC_ADJ 0x71
-#if 0
-#define GC0310_GROUP_ACCESS 0x3208
-#endif
-
-#define GC0310_H_CROP_START_H 0x09
-#define GC0310_H_CROP_START_L 0x0A
-#define GC0310_V_CROP_START_H 0x0B
-#define GC0310_V_CROP_START_L 0x0C
-#define GC0310_H_OUTSIZE_H 0x0F
-#define GC0310_H_OUTSIZE_L 0x10
-#define GC0310_V_OUTSIZE_H 0x0D
-#define GC0310_V_OUTSIZE_L 0x0E
-#define GC0310_H_BLANKING_H 0x05
-#define GC0310_H_BLANKING_L 0x06
-#define GC0310_V_BLANKING_H 0x07
-#define GC0310_V_BLANKING_L 0x08
-#define GC0310_SH_DELAY 0x11
-
-#define GC0310_START_STREAMING 0x94 /* 8-bit enable */
-#define GC0310_STOP_STREAMING 0x0 /* 8-bit disable */
-
-/*
- * gc0310 device structure.
- */
-struct gc0310_device {
- struct v4l2_subdev sd;
- struct media_pad pad;
- struct mutex input_lock;
- bool is_streaming;
-
- struct gpio_desc *reset;
- struct gpio_desc *powerdown;
-
- struct gc0310_mode {
- struct v4l2_mbus_framefmt fmt;
- } mode;
-
- struct gc0310_ctrls {
- struct v4l2_ctrl_handler handler;
- struct v4l2_ctrl *exposure;
- struct v4l2_ctrl *gain;
- } ctrls;
-};
-
-/**
- * struct gc0310_reg - MI sensor register format
- * @reg: 16-bit offset to register
- * @val: 8/16/32-bit register value
- *
- * Define a structure for sensor register initialization values
- */
-struct gc0310_reg {
- u8 reg;
- u8 val; /* @set value for read/mod/write, @mask */
-};
-
-#define to_gc0310_sensor(x) container_of(x, struct gc0310_device, sd)
-
-/*
- * Register settings for various resolution
- */
-static const struct gc0310_reg gc0310_reset_register[] = {
-/////////////////////////////////////////////////
-///////////////// system reg /////////////////
-/////////////////////////////////////////////////
- { 0xfe, 0xf0 },
- { 0xfe, 0xf0 },
- { 0xfe, 0x00 },
-
- { 0xfc, 0x0e }, /* 4e */
- { 0xfc, 0x0e }, /* 16//4e // [0]apwd [6]regf_clk_gate */
- { 0xf2, 0x80 }, /* sync output */
- { 0xf3, 0x00 }, /* 1f//01 data output */
- { 0xf7, 0x33 }, /* f9 */
- { 0xf8, 0x05 }, /* 00 */
- { 0xf9, 0x0e }, /* 0x8e //0f */
- { 0xfa, 0x11 },
-
-/////////////////////////////////////////////////
-/////////////////// MIPI ////////////////////
-/////////////////////////////////////////////////
- { 0xfe, 0x03 },
- { 0x01, 0x03 }, /* mipi 1lane */
- { 0x02, 0x22 }, /* 0x33 */
- { 0x03, 0x94 },
- { 0x04, 0x01 }, /* fifo_prog */
- { 0x05, 0x00 }, /* fifo_prog */
- { 0x06, 0x80 }, /* b0 //YUV ISP data */
- { 0x11, 0x2a }, /* 1e //LDI set YUV422 */
- { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */
- { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */
- { 0x15, 0x12 }, /* 0x10 //DPHYY_MODE read_ready */
- { 0x17, 0x01 },
- { 0x40, 0x08 },
- { 0x41, 0x00 },
- { 0x42, 0x00 },
- { 0x43, 0x00 },
- { 0x21, 0x02 }, /* 0x01 */
- { 0x22, 0x02 }, /* 0x01 */
- { 0x23, 0x01 }, /* 0x05 //Nor:0x05 DOU:0x06 */
- { 0x29, 0x00 },
- { 0x2A, 0x25 }, /* 0x05 //data zero 0x7a de */
- { 0x2B, 0x02 },
-
- { 0xfe, 0x00 },
-
-/////////////////////////////////////////////////
-///////////////// CISCTL reg /////////////////
-/////////////////////////////////////////////////
- { 0x00, 0x2f }, /* 2f//0f//02//01 */
- { 0x01, 0x0f }, /* 06 */
- { 0x02, 0x04 },
- { 0x4f, 0x00 }, /* AEC 0FF */
- { 0x03, 0x01 }, /* 0x03 //04 */
- { 0x04, 0xc0 }, /* 0xe8 //58 */
- { 0x05, 0x00 },
- { 0x06, 0xb2 }, /* 0x0a //HB */
- { 0x07, 0x00 },
- { 0x08, 0x0c }, /* 0x89 //VB */
- { 0x09, 0x00 }, /* row start */
- { 0x0a, 0x00 },
- { 0x0b, 0x00 }, /* col start */
- { 0x0c, 0x00 },
- { 0x0d, 0x01 }, /* height */
- { 0x0e, 0xf2 }, /* 0xf7 //height */
- { 0x0f, 0x02 }, /* width */
- { 0x10, 0x94 }, /* 0xa0 //height */
- { 0x17, 0x14 },
- { 0x18, 0x1a }, /* 0a//[4]double reset */
- { 0x19, 0x14 }, /* AD pipeline */
- { 0x1b, 0x48 },
- { 0x1e, 0x6b }, /* 3b//col bias */
- { 0x1f, 0x28 }, /* 20//00//08//txlow */
- { 0x20, 0x89 }, /* 88//0c//[3:2]DA15 */
- { 0x21, 0x49 }, /* 48//[3] txhigh */
- { 0x22, 0xb0 },
- { 0x23, 0x04 }, /* [1:0]vcm_r */
- { 0x24, 0x16 }, /* 15 */
- { 0x34, 0x20 }, /* [6:4] rsg high//range */
-
-/////////////////////////////////////////////////
-//////////////////// BLK ////////////////////
-/////////////////////////////////////////////////
- { 0x26, 0x23 }, /* [1]dark_current_en [0]offset_en */
- { 0x28, 0xff }, /* BLK_limie_value */
- { 0x29, 0x00 }, /* global offset */
- { 0x33, 0x18 }, /* offset_ratio */
- { 0x37, 0x20 }, /* dark_current_ratio */
- { 0x2a, 0x00 },
- { 0x2b, 0x00 },
- { 0x2c, 0x00 },
- { 0x2d, 0x00 },
- { 0x2e, 0x00 },
- { 0x2f, 0x00 },
- { 0x30, 0x00 },
- { 0x31, 0x00 },
- { 0x47, 0x80 }, /* a7 */
- { 0x4e, 0x66 }, /* select_row */
- { 0xa8, 0x02 }, /* win_width_dark, same with crop_win_width */
- { 0xa9, 0x80 },
-
-/////////////////////////////////////////////////
-////////////////// ISP reg ///////////////////
-/////////////////////////////////////////////////
- { 0x40, 0x06 }, /* 0xff //ff //48 */
- { 0x41, 0x00 }, /* 0x21 //00//[0]curve_en */
- { 0x42, 0x04 }, /* 0xcf //0a//[1]awn_en */
- { 0x44, 0x18 }, /* 0x18 //02 */
- { 0x46, 0x02 }, /* 0x03 //sync */
- { 0x49, 0x03 },
- { 0x4c, 0x20 }, /* 00[5]pretect exp */
- { 0x50, 0x01 }, /* crop enable */
- { 0x51, 0x00 },
- { 0x52, 0x00 },
- { 0x53, 0x00 },
- { 0x54, 0x01 },
- { 0x55, 0x01 }, /* crop window height */
- { 0x56, 0xf0 },
- { 0x57, 0x02 }, /* crop window width */
- { 0x58, 0x90 },
-
-/////////////////////////////////////////////////
-/////////////////// GAIN ////////////////////
-/////////////////////////////////////////////////
- { 0x70, 0x70 }, /* 70 //80//global gain */
- { 0x71, 0x20 }, /* pregain gain */
- { 0x72, 0x40 }, /* post gain */
- { 0x5a, 0x84 }, /* 84//analog gain 0 */
- { 0x5b, 0xc9 }, /* c9 */
- { 0x5c, 0xed }, /* ed//not use pga gain highest level */
- { 0x77, 0x40 }, /* R gain 0x74 //awb gain */
- { 0x78, 0x40 }, /* G gain */
- { 0x79, 0x40 }, /* B gain 0x5f */
-
- { 0x48, 0x00 },
- { 0xfe, 0x01 },
- { 0x0a, 0x45 }, /* [7]col gain mode */
-
- { 0x3e, 0x40 },
- { 0x3f, 0x5c },
- { 0x40, 0x7b },
- { 0x41, 0xbd },
- { 0x42, 0xf6 },
- { 0x43, 0x63 },
- { 0x03, 0x60 },
- { 0x44, 0x03 },
-
-/////////////////////////////////////////////////
-///////////////// dark sun //////////////////
-/////////////////////////////////////////////////
- { 0xfe, 0x01 },
- { 0x45, 0xa4 }, /* 0xf7 */
- { 0x46, 0xf0 }, /* 0xff //f0//sun value th */
- { 0x48, 0x03 }, /* sun mode */
- { 0x4f, 0x60 }, /* sun_clamp */
- { 0xfe, 0x00 },
-};
-
-static struct gc0310_reg const gc0310_VGA_30fps[] = {
- { 0xfe, 0x00 },
- { 0x0d, 0x01 }, /* height */
- { 0x0e, 0xf2 }, /* 0xf7 //height */
- { 0x0f, 0x02 }, /* width */
- { 0x10, 0x94 }, /* 0xa0 //height */
-
- { 0x50, 0x01 }, /* crop enable */
- { 0x51, 0x00 },
- { 0x52, 0x00 },
- { 0x53, 0x00 },
- { 0x54, 0x01 },
- { 0x55, 0x01 }, /* crop window height */
- { 0x56, 0xf0 },
- { 0x57, 0x02 }, /* crop window width */
- { 0x58, 0x90 },
-
- { 0xfe, 0x03 },
- { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */
- { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */
-
- { 0xfe, 0x00 },
-};
-
-#endif
diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h
index baf49eb0659e..d032af245674 100644
--- a/drivers/staging/media/atomisp/i2c/ov2680.h
+++ b/drivers/staging/media/atomisp/i2c/ov2680.h
@@ -30,10 +30,16 @@
#include <linux/v4l2-mediabus.h>
#include <media/media-entity.h>
-#include "../include/linux/atomisp_platform.h"
-
#define OV2680_NATIVE_WIDTH 1616
#define OV2680_NATIVE_HEIGHT 1216
+#define OV2680_NATIVE_START_LEFT 0
+#define OV2680_NATIVE_START_TOP 0
+#define OV2680_ACTIVE_WIDTH 1600
+#define OV2680_ACTIVE_HEIGHT 1200
+#define OV2680_ACTIVE_START_LEFT 8
+#define OV2680_ACTIVE_START_TOP 8
+#define OV2680_MIN_CROP_WIDTH 2
+#define OV2680_MIN_CROP_HEIGHT 2
/* 1704 * 1294 * 30fps = 66MHz pixel clock */
#define OV2680_PIXELS_PER_LINE 1704
@@ -66,6 +72,8 @@
#define OV2680_REG_EXPOSURE_PK_HIGH 0x3500
#define OV2680_REG_GAIN_PK 0x350a
+#define OV2680_REG_SENSOR_CTRL_0A 0x370a
+
#define OV2680_HORIZONTAL_START_H 0x3800 /* Bit[11:8] */
#define OV2680_HORIZONTAL_START_L 0x3801 /* Bit[7:0] */
#define OV2680_VERTICAL_START_H 0x3802 /* Bit[11:8] */
@@ -108,15 +116,18 @@
/*
* ov2680 device structure.
*/
-struct ov2680_device {
+struct ov2680_dev {
struct v4l2_subdev sd;
struct media_pad pad;
- struct mutex input_lock;
+ /* Protect against concurrent changes to controls */
+ struct mutex lock;
struct i2c_client *client;
struct gpio_desc *powerdown;
+ struct fwnode_handle *ep_fwnode;
bool is_streaming;
struct ov2680_mode {
+ struct v4l2_rect crop;
struct v4l2_mbus_framefmt fmt;
bool binning;
u16 h_start;
@@ -152,92 +163,86 @@ struct ov2680_reg {
u32 val; /* @set value for read/mod/write, @mask */
};
-#define to_ov2680_sensor(x) container_of(x, struct ov2680_device, sd)
+#define to_ov2680_sensor(x) container_of(x, struct ov2680_dev, sd)
static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
{
- struct ov2680_device *sensor =
- container_of(ctrl->handler, struct ov2680_device, ctrls.handler);
+ struct ov2680_dev *sensor =
+ container_of(ctrl->handler, struct ov2680_dev, ctrls.handler);
return &sensor->sd;
}
static struct ov2680_reg const ov2680_global_setting[] = {
- {0x0103, 0x01},
- {0x3002, 0x00},
+ /* MIPI PHY, 0x10 -> 0x1c enable bp_c_hs_en_lat and bp_d_hs_en_lat */
{0x3016, 0x1c},
- {0x3018, 0x44},
- {0x3020, 0x00},
- {0x3080, 0x02},
+
+ /* PLL MULT bits 0-7, datasheet default 0x37 for 24MHz extclk, use 0x45 for 19.2 Mhz extclk */
{0x3082, 0x45},
- {0x3084, 0x09},
- {0x3085, 0x04},
+
+ /* R MANUAL set exposure (0x01) and gain (0x02) to manual (hw does not do auto) */
{0x3503, 0x03},
- {0x350b, 0x36},
- {0x3600, 0xb4},
- {0x3603, 0x39},
- {0x3604, 0x24},
- {0x3605, 0x00},
- {0x3620, 0x26},
- {0x3621, 0x37},
- {0x3622, 0x04},
- {0x3628, 0x00},
- {0x3705, 0x3c},
- {0x370c, 0x50},
- {0x370d, 0xc0},
- {0x3718, 0x88},
- {0x3720, 0x00},
- {0x3721, 0x00},
- {0x3722, 0x00},
- {0x3723, 0x00},
- {0x3738, 0x00},
- {0x3717, 0x58},
- {0x3781, 0x80},
- {0x3789, 0x60},
- {0x3800, 0x00},
- {0x3819, 0x04},
+
+ /* Analog control register tweaks */
+ {0x3603, 0x39}, /* Reset value 0x99 */
+ {0x3604, 0x24}, /* Reset value 0x74 */
+ {0x3621, 0x37}, /* Reset value 0x44 */
+
+ /* Sensor control register tweaks */
+ {0x3701, 0x64}, /* Reset value 0x61 */
+ {0x3705, 0x3c}, /* Reset value 0x21 */
+ {0x370c, 0x50}, /* Reset value 0x10 */
+ {0x370d, 0xc0}, /* Reset value 0x00 */
+ {0x3718, 0x88}, /* Reset value 0x80 */
+
+ /* PSRAM tweaks */
+ {0x3781, 0x80}, /* Reset value 0x00 */
+ {0x3784, 0x0c}, /* Reset value 0x00, based on OV2680_R1A_AM10.ovt */
+ {0x3789, 0x60}, /* Reset value 0x50 */
+
+ /* BLC CTRL00 0x01 -> 0x81 set avg_weight to 8 */
{0x4000, 0x81},
- {0x4001, 0x40},
+
+ /* Set black level compensation range to 0 - 3 (default 0 - 11) */
{0x4008, 0x00},
{0x4009, 0x03},
+
+ /* VFIFO R2 0x00 -> 0x02 set Frame reset enable */
{0x4602, 0x02},
+
+ /* MIPI ctrl CLK PREPARE MIN change from 0x26 (38) -> 0x36 (54) */
{0x481f, 0x36},
+
+ /* MIPI ctrl CLK LPX P MIN change from 0x32 (50) -> 0x36 (54) */
{0x4825, 0x36},
- {0x4837, 0x18},
+
+ /* R ISP CTRL2 0x20 -> 0x30, set sof_sel bit */
{0x5002, 0x30},
- {0x5004, 0x04},//manual awb 1x
- {0x5005, 0x00},
- {0x5006, 0x04},
- {0x5007, 0x00},
- {0x5008, 0x04},
- {0x5009, 0x00},
- {0x5080, 0x00},
- {0x5081, 0x41},
- {0x5708, 0x01}, /* add for full size flip off and mirror off 2014/09/11 */
- {0x3701, 0x64}, //add on 14/05/13
- {0x3784, 0x0c}, //based OV2680_R1A_AM10.ovt add on 14/06/13
- {0x5780, 0x3e}, //based OV2680_R1A_AM10.ovt,Adjust DPC setting (57xx) on 14/06/13
- {0x5781, 0x0f},
- {0x5782, 0x04},
- {0x5783, 0x02},
- {0x5784, 0x01},
- {0x5785, 0x01},
- {0x5786, 0x00},
- {0x5787, 0x04},
+
+ /*
+ * Window CONTROL 0x00 -> 0x01, enable manual window control,
+ * this is necessary for full size flip and mirror support.
+ */
+ {0x5708, 0x01},
+
+ /*
+ * DPC CTRL0 0x14 -> 0x3e, set enable_tail, enable_3x3_cluster
+ * and enable_general_tail bits based OV2680_R1A_AM10.ovt.
+ */
+ {0x5780, 0x3e},
+
+ /* DPC MORE CONNECTION CASE THRE 0x0c (12) -> 0x02 (2) */
{0x5788, 0x02},
- {0x5789, 0x00},
- {0x578a, 0x01},
- {0x578b, 0x02},
- {0x578c, 0x03},
- {0x578d, 0x03},
+
+ /* DPC GAIN LIST1 0x0f (15) -> 0x08 (8) */
{0x578e, 0x08},
+
+ /* DPC GAIN LIST2 0x3f (63) -> 0x0c (12) */
{0x578f, 0x0c},
- {0x5790, 0x08},
- {0x5791, 0x04},
+
+ /* DPC THRE RATIO 0x04 (4) -> 0x00 (0) */
{0x5792, 0x00},
- {0x5793, 0x00},
- {0x5794, 0x03}, //based OV2680_R1A_AM10.ovt,Adjust DPC setting (57xx) on 14/06/13
- {0x0100, 0x00}, //stream off
+
{}
};
diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
index da8c3b1d3bcd..460a4e34c55b 100644
--- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
+++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
@@ -726,51 +726,11 @@ static void *ov5693_otp_read(struct v4l2_subdev *sd)
return buf;
}
-static int ov5693_g_priv_int_data(struct v4l2_subdev *sd,
- struct v4l2_private_int_data *priv)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct ov5693_device *dev = to_ov5693_sensor(sd);
- u8 __user *to = priv->data;
- u32 read_size = priv->size;
- int ret;
-
- /* No need to copy data if size is 0 */
- if (!read_size)
- goto out;
-
- if (IS_ERR(dev->otp_data)) {
- dev_err(&client->dev, "OTP data not available");
- return PTR_ERR(dev->otp_data);
- }
-
- /* Correct read_size value only if bigger than maximum */
- if (read_size > OV5693_OTP_DATA_SIZE)
- read_size = OV5693_OTP_DATA_SIZE;
-
- ret = copy_to_user(to, dev->otp_data, read_size);
- if (ret) {
- dev_err(&client->dev, "%s: failed to copy OTP data to user\n",
- __func__);
- return -EFAULT;
- }
-
- pr_debug("%s read_size:%d\n", __func__, read_size);
-
-out:
- /* Return correct size */
- priv->size = dev->otp_size;
-
- return 0;
-}
-
static long ov5693_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
switch (cmd) {
case ATOMISP_IOC_S_EXPOSURE:
return ov5693_s_exposure(sd, arg);
- case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA:
- return ov5693_g_priv_int_data(sd, arg);
default:
return -EINVAL;
}
@@ -1794,7 +1754,7 @@ static struct i2c_driver ov5693_driver = {
.name = "ov5693",
.acpi_match_table = ov5693_acpi_match,
},
- .probe_new = ov5693_probe,
+ .probe = ov5693_probe,
.remove = ov5693_remove,
};
module_i2c_driver(ov5693_driver);
diff --git a/drivers/staging/media/atomisp/include/linux/atomisp.h b/drivers/staging/media/atomisp/include/linux/atomisp.h
index c7ec56a1c064..14b1757e6674 100644
--- a/drivers/staging/media/atomisp/include/linux/atomisp.h
+++ b/drivers/staging/media/atomisp/include/linux/atomisp.h
@@ -38,7 +38,6 @@
#define CI_MODE_PREVIEW 0x8000
#define CI_MODE_VIDEO 0x4000
#define CI_MODE_STILL_CAPTURE 0x2000
-#define CI_MODE_CONTINUOUS 0x1000
#define CI_MODE_NONE 0x0000
#define OUTPUT_MODE_FILE 0x0100
@@ -150,12 +149,6 @@ enum atomisp_calibration_type {
calibration_type3
};
-struct atomisp_calibration_group {
- unsigned int size;
- unsigned int type;
- unsigned short *calb_grp_values;
-};
-
struct atomisp_gc_config {
__u16 gain_k1;
__u16 gain_k2;
@@ -266,26 +259,6 @@ enum atomisp_metadata_type {
ATOMISP_METADATA_TYPE_NUM,
};
-struct atomisp_metadata_with_type {
- /* to specify which type of metadata to get */
- enum atomisp_metadata_type type;
- void __user *data;
- u32 width;
- u32 height;
- u32 stride; /* in bytes */
- u32 exp_id; /* exposure ID */
- u32 *effective_width; /* mipi packets valid data size */
-};
-
-struct atomisp_metadata {
- void __user *data;
- u32 width;
- u32 height;
- u32 stride; /* in bytes */
- u32 exp_id; /* exposure ID */
- u32 *effective_width; /* mipi packets valid data size */
-};
-
struct atomisp_ext_isp_ctrl {
u32 id;
u32 data;
@@ -299,14 +272,6 @@ struct atomisp_3a_statistics {
u32 isp_config_id; /* isp config ID */
};
-struct atomisp_ae_window {
- int x_left;
- int x_right;
- int y_top;
- int y_bottom;
- int weight;
-};
-
/* White Balance (Gain Adjust) */
struct atomisp_wb_config {
unsigned int integer_bits;
@@ -755,53 +720,6 @@ struct atomisp_s_runmode {
__u32 mode;
};
-struct atomisp_update_exposure {
- unsigned int gain;
- unsigned int digi_gain;
- unsigned int update_gain;
- unsigned int update_digi_gain;
-};
-
-/*
- * V4L2 private internal data interface.
- * -----------------------------------------------------------------------------
- * struct v4l2_private_int_data - request private data stored in video device
- * internal memory.
- * @size: sanity check to ensure userspace's buffer fits whole private data.
- * If not, kernel will make partial copy (or nothing if @size == 0).
- * @size is always corrected for the minimum necessary if IOCTL returns
- * no error.
- * @data: pointer to userspace buffer.
- */
-struct v4l2_private_int_data {
- __u32 size;
- void __user *data;
- __u32 reserved[2];
-};
-
-enum atomisp_sensor_ae_bracketing_mode {
- SENSOR_AE_BRACKETING_MODE_OFF = 0,
- SENSOR_AE_BRACKETING_MODE_SINGLE, /* back to SW standby after bracketing */
- SENSOR_AE_BRACKETING_MODE_SINGLE_TO_STREAMING, /* back to normal streaming after bracketing */
- SENSOR_AE_BRACKETING_MODE_LOOP, /* continue AE bracketing in loop mode */
-};
-
-struct atomisp_sensor_ae_bracketing_info {
- unsigned int modes; /* bit mask to indicate supported modes */
- unsigned int lut_depth;
-};
-
-struct atomisp_sensor_ae_bracketing_lut_entry {
- __u16 coarse_integration_time;
- __u16 analog_gain;
- __u16 digital_gain;
-};
-
-struct atomisp_sensor_ae_bracketing_lut {
- struct atomisp_sensor_ae_bracketing_lut_entry *lut;
- unsigned int lut_size;
-};
-
/*Private IOCTLs for ISP */
#define ATOMISP_IOC_G_XNR \
_IOR('v', BASE_VIDIOC_PRIVATE + 0, int)
@@ -906,20 +824,12 @@ struct atomisp_sensor_ae_bracketing_lut {
#define ATOMISP_IOC_S_EXPOSURE \
_IOW('v', BASE_VIDIOC_PRIVATE + 21, struct atomisp_exposure)
-/* sensor calibration registers group */
-#define ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP \
- _IOWR('v', BASE_VIDIOC_PRIVATE + 22, struct atomisp_calibration_group)
-
/* white balance Correction */
#define ATOMISP_IOC_G_3A_CONFIG \
_IOR('v', BASE_VIDIOC_PRIVATE + 23, struct atomisp_3a_config)
#define ATOMISP_IOC_S_3A_CONFIG \
_IOW('v', BASE_VIDIOC_PRIVATE + 23, struct atomisp_3a_config)
-/* sensor OTP memory read */
-#define ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA \
- _IOWR('v', BASE_VIDIOC_PRIVATE + 26, struct v4l2_private_int_data)
-
/* LCS (shading) table write */
#define ATOMISP_IOC_S_ISP_SHD_TAB \
_IOWR('v', BASE_VIDIOC_PRIVATE + 27, struct atomisp_shading_table)
@@ -931,19 +841,9 @@ struct atomisp_sensor_ae_bracketing_lut {
#define ATOMISP_IOC_S_ISP_GAMMA_CORRECTION \
_IOW('v', BASE_VIDIOC_PRIVATE + 28, struct atomisp_gc_config)
-/* motor internal memory read */
-#define ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA \
- _IOWR('v', BASE_VIDIOC_PRIVATE + 29, struct v4l2_private_int_data)
-
#define ATOMISP_IOC_S_PARAMETERS \
_IOW('v', BASE_VIDIOC_PRIVATE + 32, struct atomisp_parameters)
-#define ATOMISP_IOC_G_METADATA \
- _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata)
-
-#define ATOMISP_IOC_G_METADATA_BY_TYPE \
- _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata_with_type)
-
#define ATOMISP_IOC_EXT_ISP_CTRL \
_IOWR('v', BASE_VIDIOC_PRIVATE + 35, struct atomisp_ext_isp_ctrl)
@@ -962,27 +862,9 @@ struct atomisp_sensor_ae_bracketing_lut {
#define ATOMISP_IOC_S_FORMATS_CONFIG \
_IOW('v', BASE_VIDIOC_PRIVATE + 39, struct atomisp_formats_config)
-#define ATOMISP_IOC_S_EXPOSURE_WINDOW \
- _IOW('v', BASE_VIDIOC_PRIVATE + 40, struct atomisp_ae_window)
-
#define ATOMISP_IOC_INJECT_A_FAKE_EVENT \
_IOW('v', BASE_VIDIOC_PRIVATE + 42, int)
-#define ATOMISP_IOC_G_SENSOR_AE_BRACKETING_INFO \
- _IOR('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_info)
-
-#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_MODE \
- _IOW('v', BASE_VIDIOC_PRIVATE + 43, unsigned int)
-
-#define ATOMISP_IOC_G_SENSOR_AE_BRACKETING_MODE \
- _IOR('v', BASE_VIDIOC_PRIVATE + 43, unsigned int)
-
-#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT \
- _IOW('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_lut)
-
-#define ATOMISP_IOC_G_INVALID_FRAME_NUM \
- _IOR('v', BASE_VIDIOC_PRIVATE + 44, unsigned int)
-
#define ATOMISP_IOC_S_ARRAY_RESOLUTION \
_IOW('v', BASE_VIDIOC_PRIVATE + 45, struct atomisp_resolution)
@@ -996,9 +878,6 @@ struct atomisp_sensor_ae_bracketing_lut {
#define ATOMISP_IOC_S_SENSOR_RUNMODE \
_IOW('v', BASE_VIDIOC_PRIVATE + 48, struct atomisp_s_runmode)
-#define ATOMISP_IOC_G_UPDATE_EXPOSURE \
- _IOWR('v', BASE_VIDIOC_PRIVATE + 49, struct atomisp_update_exposure)
-
/*
* Reserved ioctls. We have customer implementing it internally.
* We can't use both numbers to not cause ABI conflict.
@@ -1059,9 +938,9 @@ struct atomisp_sensor_ae_bracketing_lut {
#define V4L2_CID_RUN_MODE (V4L2_CID_CAMERA_LASTP1 + 20)
#define ATOMISP_RUN_MODE_VIDEO 1
#define ATOMISP_RUN_MODE_STILL_CAPTURE 2
-#define ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE 3
-#define ATOMISP_RUN_MODE_PREVIEW 4
-#define ATOMISP_RUN_MODE_SDV 5
+#define ATOMISP_RUN_MODE_PREVIEW 3
+#define ATOMISP_RUN_MODE_MIN 1
+#define ATOMISP_RUN_MODE_MAX 3
#define V4L2_CID_ENABLE_VFPP (V4L2_CID_CAMERA_LASTP1 + 21)
#define V4L2_CID_ATOMISP_CONTINUOUS_MODE (V4L2_CID_CAMERA_LASTP1 + 22)
diff --git a/drivers/staging/media/atomisp/include/linux/atomisp_platform.h b/drivers/staging/media/atomisp/include/linux/atomisp_platform.h
index e8e965f73fc8..487ef5846c24 100644
--- a/drivers/staging/media/atomisp/include/linux/atomisp_platform.h
+++ b/drivers/staging/media/atomisp/include/linux/atomisp_platform.h
@@ -125,6 +125,7 @@ struct intel_v4l2_subdev_id {
struct intel_v4l2_subdev_table {
enum intel_v4l2_subdev_type type;
enum atomisp_camera_port port;
+ unsigned int lanes;
struct v4l2_subdev *subdev;
};
diff --git a/drivers/staging/media/atomisp/pci/atomisp-regs.h b/drivers/staging/media/atomisp/pci/atomisp-regs.h
index 022997f47121..a7b0196686be 100644
--- a/drivers/staging/media/atomisp/pci/atomisp-regs.h
+++ b/drivers/staging/media/atomisp/pci/atomisp-regs.h
@@ -112,7 +112,6 @@
/* MRFLD CSI lane configuration related */
#define MRFLD_PORT_CONFIG_NUM 8
-#define MRFLD_PORT_NUM 3
#define MRFLD_PORT1_ENABLE_SHIFT 0
#define MRFLD_PORT2_ENABLE_SHIFT 1
#define MRFLD_PORT3_ENABLE_SHIFT 2
diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
index aa790ae746f3..e27f9dc8e7aa 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
@@ -229,8 +229,8 @@ int atomisp_freq_scaling(struct atomisp_device *isp,
goto done;
}
- curr_rules.width = isp->asd.fmt[isp->asd.capture_pad].fmt.width;
- curr_rules.height = isp->asd.fmt[isp->asd.capture_pad].fmt.height;
+ curr_rules.width = isp->asd.fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.width;
+ curr_rules.height = isp->asd.fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.height;
curr_rules.fps = fps;
curr_rules.run_mode = isp->asd.run_mode->val;
@@ -472,39 +472,31 @@ irqreturn_t atomisp_isr(int irq, void *dev)
clear_irq_reg(isp);
- if (!atomisp_streaming_count(isp))
+ if (!isp->asd.streaming)
goto out_nowake;
- if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED) {
- if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) {
- atomic_inc(&isp->asd.sof_count);
- atomisp_sof_event(&isp->asd);
-
- /* If sequence_temp and sequence are the same
- * there where no frames lost so we can increase
- * sequence_temp.
- * If not then processing of frame is still in progress
- * and driver needs to keep old sequence_temp value.
- * NOTE: There is assumption here that ISP will not
- * start processing next frame from sensor before old
- * one is completely done. */
- if (atomic_read(&isp->asd.sequence) ==
- atomic_read(&isp->asd.sequence_temp))
- atomic_set(&isp->asd.sequence_temp,
- atomic_read(&isp->asd.sof_count));
- }
- if (irq_infos & IA_CSS_IRQ_INFO_EVENTS_READY)
- atomic_set(&isp->asd.sequence,
- atomic_read(&isp->asd.sequence_temp));
- }
-
if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) {
- dev_dbg_ratelimited(isp->dev,
- "irq:0x%x (SOF)\n",
- irq_infos);
+ atomic_inc(&isp->asd.sof_count);
+ atomisp_sof_event(&isp->asd);
+
+ /*
+ * If sequence_temp and sequence are the same there where no frames
+ * lost so we can increase sequence_temp.
+ * If not then processing of frame is still in progress and driver
+ * needs to keep old sequence_temp value.
+ * NOTE: There is assumption here that ISP will not start processing
+ * next frame from sensor before old one is completely done.
+ */
+ if (atomic_read(&isp->asd.sequence) == atomic_read(&isp->asd.sequence_temp))
+ atomic_set(&isp->asd.sequence_temp, atomic_read(&isp->asd.sof_count));
+
+ dev_dbg_ratelimited(isp->dev, "irq:0x%x (SOF)\n", irq_infos);
irq_infos &= ~IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF;
}
+ if (irq_infos & IA_CSS_IRQ_INFO_EVENTS_READY)
+ atomic_set(&isp->asd.sequence, atomic_read(&isp->asd.sequence_temp));
+
if ((irq_infos & IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR) ||
(irq_infos & IA_CSS_IRQ_INFO_IF_ERROR)) {
/* handle mipi receiver error */
@@ -640,15 +632,6 @@ void atomisp_flush_video_pipe(struct atomisp_video_pipe *pipe, enum vb2_buffer_s
spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
}
-/* Returns queued buffers back to video-core */
-void atomisp_flush_bufs_and_wakeup(struct atomisp_sub_device *asd)
-{
- atomisp_flush_video_pipe(&asd->video_out_capture, VB2_BUF_STATE_ERROR, false);
- atomisp_flush_video_pipe(&asd->video_out_vf, VB2_BUF_STATE_ERROR, false);
- atomisp_flush_video_pipe(&asd->video_out_preview, VB2_BUF_STATE_ERROR, false);
- atomisp_flush_video_pipe(&asd->video_out_video_capture, VB2_BUF_STATE_ERROR, false);
-}
-
/* clean out the parameters that did not apply */
void atomisp_flush_params_queue(struct atomisp_video_pipe *pipe)
{
@@ -944,53 +927,39 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
atomisp_qbuffers_to_css(asd);
}
-static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout)
+void atomisp_assert_recovery_work(struct work_struct *work)
{
+ struct atomisp_device *isp = container_of(work, struct atomisp_device,
+ assert_recovery_work);
struct pci_dev *pdev = to_pci_dev(isp->dev);
- enum ia_css_pipe_id css_pipe_id;
- bool stream_restart = false;
unsigned long flags;
int ret;
- lockdep_assert_held(&isp->mutex);
+ mutex_lock(&isp->mutex);
- if (!atomisp_streaming_count(isp))
- return;
+ if (!isp->asd.streaming)
+ goto out_unlock;
atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false);
- if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED ||
- isp->asd.stream_prepared) {
- stream_restart = true;
-
- spin_lock_irqsave(&isp->lock, flags);
- isp->asd.streaming = ATOMISP_DEVICE_STREAMING_STOPPING;
- spin_unlock_irqrestore(&isp->lock, flags);
-
- /* stream off sensor */
- ret = v4l2_subdev_call(
- isp->inputs[isp->asd.input_curr].
- camera, video, s_stream, 0);
- if (ret)
- dev_warn(isp->dev,
- "can't stop streaming on sensor!\n");
+ spin_lock_irqsave(&isp->lock, flags);
+ isp->asd.streaming = false;
+ spin_unlock_irqrestore(&isp->lock, flags);
- atomisp_clear_css_buffer_counters(&isp->asd);
+ /* stream off sensor */
+ ret = v4l2_subdev_call(isp->inputs[isp->asd.input_curr].camera, video, s_stream, 0);
+ if (ret)
+ dev_warn(isp->dev, "Stopping sensor stream failed: %d\n", ret);
- css_pipe_id = atomisp_get_css_pipe_id(&isp->asd);
- atomisp_css_stop(&isp->asd, css_pipe_id, true);
+ atomisp_clear_css_buffer_counters(&isp->asd);
- spin_lock_irqsave(&isp->lock, flags);
- isp->asd.streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
- spin_unlock_irqrestore(&isp->lock, flags);
+ atomisp_css_stop(&isp->asd, true);
- isp->asd.preview_exp_id = 1;
- isp->asd.postview_exp_id = 1;
- /* notify HAL the CSS reset */
- dev_dbg(isp->dev,
- "send reset event to %s\n", isp->asd.subdev.devnode->name);
- atomisp_reset_event(&isp->asd);
- }
+ isp->asd.preview_exp_id = 1;
+ isp->asd.postview_exp_id = 1;
+ /* notify HAL the CSS reset */
+ dev_dbg(isp->dev, "send reset event to %s\n", isp->asd.subdev.devnode->name);
+ atomisp_reset_event(&isp->asd);
/* clear irq */
disable_isp_irq(hrt_isp_css_irq_sp);
@@ -1001,71 +970,46 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout)
isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK);
/* reset ISP and restore its state */
- isp->isp_timeout = true;
atomisp_reset(isp);
- isp->isp_timeout = false;
- if (stream_restart) {
- atomisp_css_input_set_mode(&isp->asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
+ atomisp_css_input_set_mode(&isp->asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
- css_pipe_id = atomisp_get_css_pipe_id(&isp->asd);
- if (atomisp_css_start(&isp->asd, css_pipe_id, true)) {
- dev_warn(isp->dev,
- "start SP failed, so do not set streaming to be enable!\n");
- } else {
- spin_lock_irqsave(&isp->lock, flags);
- isp->asd.streaming = ATOMISP_DEVICE_STREAMING_ENABLED;
- spin_unlock_irqrestore(&isp->lock, flags);
- }
+ /* Recreate streams destroyed by atomisp_css_stop() */
+ atomisp_create_pipes_stream(&isp->asd);
+
+ /* Invalidate caches. FIXME: should flush only necessary buffers */
+ wbinvd();
- atomisp_csi2_configure(&isp->asd);
+ if (atomisp_css_start(&isp->asd)) {
+ dev_warn(isp->dev, "start SP failed, so do not set streaming to be enable!\n");
+ } else {
+ spin_lock_irqsave(&isp->lock, flags);
+ isp->asd.streaming = true;
+ spin_unlock_irqrestore(&isp->lock, flags);
}
+ atomisp_csi2_configure(&isp->asd);
+
atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF,
atomisp_css_valid_sof(isp));
if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, true) < 0)
dev_dbg(isp->dev, "DFS auto failed while recovering!\n");
- if (stream_restart) {
- /*
- * dequeueing buffers is not needed. CSS will recycle
- * buffers that it has.
- */
- atomisp_flush_bufs_and_wakeup(&isp->asd);
+ /* Dequeueing buffers is not needed, CSS will recycle buffers that it has */
+ atomisp_flush_video_pipe(&isp->asd.video_out, VB2_BUF_STATE_ERROR, false);
- /* Requeue unprocessed per-frame parameters. */
- atomisp_recover_params_queue(&isp->asd.video_out_capture);
- atomisp_recover_params_queue(&isp->asd.video_out_preview);
- atomisp_recover_params_queue(&isp->asd.video_out_video_capture);
-
- ret = v4l2_subdev_call(
- isp->inputs[isp->asd.input_curr].camera, video,
- s_stream, 1);
- if (ret)
- dev_warn(isp->dev,
- "can't start streaming on sensor!\n");
- }
-}
+ /* Requeue unprocessed per-frame parameters. */
+ atomisp_recover_params_queue(&isp->asd.video_out);
-void atomisp_assert_recovery_work(struct work_struct *work)
-{
- struct atomisp_device *isp = container_of(work, struct atomisp_device,
- assert_recovery_work);
+ ret = v4l2_subdev_call(isp->inputs[isp->asd.input_curr].camera, video, s_stream, 1);
+ if (ret)
+ dev_err(isp->dev, "Starting sensor stream failed: %d\n", ret);
- mutex_lock(&isp->mutex);
- __atomisp_css_recover(isp, true);
+out_unlock:
mutex_unlock(&isp->mutex);
}
-void atomisp_css_flush(struct atomisp_device *isp)
-{
- /* Start recover */
- __atomisp_css_recover(isp, false);
-
- dev_dbg(isp->dev, "atomisp css flush done\n");
-}
-
void atomisp_setup_flash(struct atomisp_sub_device *asd)
{
struct atomisp_device *isp = asd->isp;
@@ -1105,7 +1049,7 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr)
spin_lock_irqsave(&isp->lock, flags);
- if (!atomisp_streaming_count(isp)) {
+ if (!isp->asd.streaming) {
spin_unlock_irqrestore(&isp->lock, flags);
return IRQ_HANDLED;
}
@@ -1141,7 +1085,7 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr)
if (atomisp_css_isr_thread(isp))
goto out;
- if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED)
+ if (isp->asd.streaming)
atomisp_setup_flash(&isp->asd);
out:
mutex_unlock(&isp->mutex);
@@ -1298,7 +1242,7 @@ static void atomisp_update_capture_mode(struct atomisp_sub_device *asd)
atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_ADVANCED);
else if (asd->params.low_light)
atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_LOW_LIGHT);
- else if (asd->video_out_capture.sh_fmt == IA_CSS_FRAME_FORMAT_RAW)
+ else if (asd->video_out.sh_fmt == IA_CSS_FRAME_FORMAT_RAW)
atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_RAW);
else
atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_PRIMARY);
@@ -1553,13 +1497,12 @@ void atomisp_free_internal_buffers(struct atomisp_sub_device *asd)
}
static void atomisp_update_grid_info(struct atomisp_sub_device *asd,
- enum ia_css_pipe_id pipe_id,
- int source_pad)
+ enum ia_css_pipe_id pipe_id)
{
struct atomisp_device *isp = asd->isp;
int err;
- if (atomisp_css_get_grid_info(asd, pipe_id, source_pad))
+ if (atomisp_css_get_grid_info(asd, pipe_id))
return;
/* We must free all buffers because they no longer match
@@ -1908,161 +1851,6 @@ int atomisp_3a_stat(struct atomisp_sub_device *asd, int flag,
return 0;
}
-int atomisp_get_metadata(struct atomisp_sub_device *asd, int flag,
- struct atomisp_metadata *md)
-{
- struct atomisp_device *isp = asd->isp;
- struct ia_css_stream_info *stream_info;
- struct camera_mipi_info *mipi_info;
- struct atomisp_metadata_buf *md_buf;
- enum atomisp_metadata_type md_type = ATOMISP_MAIN_METADATA;
- int ret, i;
-
- if (flag != 0)
- return -EINVAL;
-
- stream_info = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
- stream_info;
-
- /* We always return the resolution and stride even if there is
- * no valid metadata. This allows the caller to get the information
- * needed to allocate user-space buffers. */
- md->width = stream_info->metadata_info.resolution.width;
- md->height = stream_info->metadata_info.resolution.height;
- md->stride = stream_info->metadata_info.stride;
-
- /* sanity check to avoid writing into unallocated memory.
- * This does not return an error because it is a valid way
- * for applications to detect that metadata is not enabled. */
- if (md->width == 0 || md->height == 0 || !md->data)
- return 0;
-
- /* This is done in the atomisp_buf_done() */
- if (list_empty(&asd->metadata_ready[md_type])) {
- dev_warn(isp->dev, "Metadata queue is empty now!\n");
- return -EAGAIN;
- }
-
- mipi_info = atomisp_to_sensor_mipi_info(
- isp->inputs[asd->input_curr].camera);
- if (!mipi_info)
- return -EINVAL;
-
- if (mipi_info->metadata_effective_width) {
- for (i = 0; i < md->height; i++)
- md->effective_width[i] =
- mipi_info->metadata_effective_width[i];
- }
-
- md_buf = list_entry(asd->metadata_ready[md_type].next,
- struct atomisp_metadata_buf, list);
- md->exp_id = md_buf->metadata->exp_id;
- if (md_buf->md_vptr) {
- ret = copy_to_user(md->data,
- md_buf->md_vptr,
- stream_info->metadata_info.size);
- } else {
- hmm_load(md_buf->metadata->address,
- asd->params.metadata_user[md_type],
- stream_info->metadata_info.size);
-
- ret = copy_to_user(md->data,
- asd->params.metadata_user[md_type],
- stream_info->metadata_info.size);
- }
- if (ret) {
- dev_err(isp->dev, "copy to user failed: copied %d bytes\n",
- ret);
- return -EFAULT;
- }
-
- list_del_init(&md_buf->list);
- list_add_tail(&md_buf->list, &asd->metadata[md_type]);
-
- dev_dbg(isp->dev, "%s: HAL de-queued metadata type %d with exp_id %d\n",
- __func__, md_type, md->exp_id);
- return 0;
-}
-
-int atomisp_get_metadata_by_type(struct atomisp_sub_device *asd, int flag,
- struct atomisp_metadata_with_type *md)
-{
- struct atomisp_device *isp = asd->isp;
- struct ia_css_stream_info *stream_info;
- struct camera_mipi_info *mipi_info;
- struct atomisp_metadata_buf *md_buf;
- enum atomisp_metadata_type md_type;
- int ret, i;
-
- if (flag != 0)
- return -EINVAL;
-
- stream_info = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
- stream_info;
-
- /* We always return the resolution and stride even if there is
- * no valid metadata. This allows the caller to get the information
- * needed to allocate user-space buffers. */
- md->width = stream_info->metadata_info.resolution.width;
- md->height = stream_info->metadata_info.resolution.height;
- md->stride = stream_info->metadata_info.stride;
-
- /* sanity check to avoid writing into unallocated memory.
- * This does not return an error because it is a valid way
- * for applications to detect that metadata is not enabled. */
- if (md->width == 0 || md->height == 0 || !md->data)
- return 0;
-
- md_type = md->type;
- if (md_type < 0 || md_type >= ATOMISP_METADATA_TYPE_NUM)
- return -EINVAL;
-
- /* This is done in the atomisp_buf_done() */
- if (list_empty(&asd->metadata_ready[md_type])) {
- dev_warn(isp->dev, "Metadata queue is empty now!\n");
- return -EAGAIN;
- }
-
- mipi_info = atomisp_to_sensor_mipi_info(
- isp->inputs[asd->input_curr].camera);
- if (!mipi_info)
- return -EINVAL;
-
- if (mipi_info->metadata_effective_width) {
- for (i = 0; i < md->height; i++)
- md->effective_width[i] =
- mipi_info->metadata_effective_width[i];
- }
-
- md_buf = list_entry(asd->metadata_ready[md_type].next,
- struct atomisp_metadata_buf, list);
- md->exp_id = md_buf->metadata->exp_id;
- if (md_buf->md_vptr) {
- ret = copy_to_user(md->data,
- md_buf->md_vptr,
- stream_info->metadata_info.size);
- } else {
- hmm_load(md_buf->metadata->address,
- asd->params.metadata_user[md_type],
- stream_info->metadata_info.size);
-
- ret = copy_to_user(md->data,
- asd->params.metadata_user[md_type],
- stream_info->metadata_info.size);
- }
- if (ret) {
- dev_err(isp->dev, "copy to user failed: copied %d bytes\n",
- ret);
- return -EFAULT;
- } else {
- list_del_init(&md_buf->list);
- list_add_tail(&md_buf->list, &asd->metadata[md_type]);
- }
- dev_dbg(isp->dev, "%s: HAL de-queued metadata type %d with exp_id %d\n",
- __func__, md_type, md->exp_id);
- return 0;
-}
-
/*
* Function to calculate real zoom region for every pipe
*/
@@ -3221,14 +3009,11 @@ void atomisp_handle_parameter_and_buffer(struct atomisp_video_pipe *pipe)
lockdep_assert_held(&asd->isp->mutex);
- if (atomisp_is_vf_pipe(pipe))
- return;
-
/*
* CSS/FW requires set parameter and enqueue buffer happen after ISP
* is streamon.
*/
- if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
+ if (!asd->streaming)
return;
if (list_empty(&pipe->per_frame_params) ||
@@ -3299,15 +3084,7 @@ int atomisp_set_parameters(struct video_device *vdev,
dev_dbg(asd->isp->dev, "set parameter(per_frame_setting %d) isp_config_id %d of %s\n",
arg->per_frame_setting, arg->isp_config_id, vdev->name);
- if (IS_ISP2401) {
- if (atomisp_is_vf_pipe(pipe) && arg->per_frame_setting) {
- dev_err(asd->isp->dev, "%s: vf pipe not support per_frame_setting",
- __func__);
- return -EINVAL;
- }
- }
-
- if (arg->per_frame_setting && !atomisp_is_vf_pipe(pipe)) {
+ if (arg->per_frame_setting) {
/*
* Per-frame setting enabled, we allocate a new parameter
* buffer to cache the parameters and only when frame buffers
@@ -3346,7 +3123,7 @@ int atomisp_set_parameters(struct video_device *vdev,
if (ret)
goto apply_parameter_failed;
- if (!(arg->per_frame_setting && !atomisp_is_vf_pipe(pipe))) {
+ if (!arg->per_frame_setting) {
/* indicate to CSS that we have parameters to be updated */
asd->params.css_update_params_needed = true;
} else {
@@ -3880,66 +3657,202 @@ static void __atomisp_init_stream_info(u16 stream_index,
}
}
+static void atomisp_fill_pix_format(struct v4l2_pix_format *f,
+ u32 width, u32 height,
+ const struct atomisp_format_bridge *br_fmt)
+{
+ u32 bytes;
+
+ f->width = width;
+ f->height = height;
+ f->pixelformat = br_fmt->pixelformat;
+
+ /* Adding padding to width for bytesperline calculation */
+ width = ia_css_frame_pad_width(width, br_fmt->sh_fmt);
+ bytes = BITS_TO_BYTES(br_fmt->depth * width);
+
+ if (br_fmt->planar)
+ f->bytesperline = width;
+ else
+ f->bytesperline = bytes;
+
+ f->sizeimage = PAGE_ALIGN(height * bytes);
+
+ if (f->field == V4L2_FIELD_ANY)
+ f->field = V4L2_FIELD_NONE;
+
+ /*
+ * FIXME: do we need to set this up differently, depending on the
+ * sensor or the pipeline?
+ */
+ f->colorspace = V4L2_COLORSPACE_REC709;
+ f->ycbcr_enc = V4L2_YCBCR_ENC_709;
+ f->xfer_func = V4L2_XFER_FUNC_709;
+}
+
+/* Get sensor padding values for the non padded width x height resolution */
+void atomisp_get_padding(struct atomisp_device *isp, u32 width, u32 height,
+ u32 *padding_w, u32 *padding_h)
+{
+ struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr];
+ struct v4l2_rect native_rect = input->native_rect;
+ const struct atomisp_in_fmt_conv *fc = NULL;
+ u32 min_pad_w = ISP2400_MIN_PAD_W;
+ u32 min_pad_h = ISP2400_MIN_PAD_H;
+ struct v4l2_mbus_framefmt *sink;
+
+ if (!input->crop_support) {
+ *padding_w = pad_w;
+ *padding_h = pad_h;
+ return;
+ }
+
+ width = min(width, input->active_rect.width);
+ height = min(height, input->active_rect.height);
+
+ if (input->binning_support && width <= (input->active_rect.width / 2) &&
+ height <= (input->active_rect.height / 2)) {
+ native_rect.width /= 2;
+ native_rect.height /= 2;
+ }
+
+ *padding_w = min_t(u32, (native_rect.width - width) & ~1, pad_w);
+ *padding_h = min_t(u32, (native_rect.height - height) & ~1, pad_h);
+
+ /* The below minimum padding requirements are for BYT / ISP2400 only */
+ if (IS_ISP2401)
+ return;
+
+ sink = atomisp_subdev_get_ffmt(&isp->asd.subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE,
+ ATOMISP_SUBDEV_PAD_SINK);
+ if (sink)
+ fc = atomisp_find_in_fmt_conv(sink->code);
+ if (!fc) {
+ dev_warn(isp->dev, "%s: Could not get sensor format\n", __func__);
+ goto apply_min_padding;
+ }
+
+ /*
+ * The ISP only supports GRBG for other bayer-orders additional padding
+ * is used so that the raw sensor data can be cropped to fix the order.
+ */
+ if (fc->bayer_order == IA_CSS_BAYER_ORDER_RGGB ||
+ fc->bayer_order == IA_CSS_BAYER_ORDER_GBRG)
+ min_pad_w += 2;
+
+ if (fc->bayer_order == IA_CSS_BAYER_ORDER_BGGR ||
+ fc->bayer_order == IA_CSS_BAYER_ORDER_GBRG)
+ min_pad_h += 2;
+
+apply_min_padding:
+ *padding_w = max_t(u32, *padding_w, min_pad_w);
+ *padding_h = max_t(u32, *padding_h, min_pad_h);
+}
+
+static int atomisp_set_crop(struct atomisp_device *isp,
+ const struct v4l2_mbus_framefmt *format,
+ int which)
+{
+ struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr];
+ struct v4l2_subdev_state pad_state = {
+ .pads = &input->pad_cfg,
+ };
+ struct v4l2_subdev_selection sel = {
+ .which = which,
+ .target = V4L2_SEL_TGT_CROP,
+ .r.width = format->width,
+ .r.height = format->height,
+ };
+ int ret;
+
+ if (!input->crop_support)
+ return 0;
+
+ /* Cropping is done before binning, when binning double the crop rect */
+ if (input->binning_support && sel.r.width <= (input->native_rect.width / 2) &&
+ sel.r.height <= (input->native_rect.height / 2)) {
+ sel.r.width *= 2;
+ sel.r.height *= 2;
+ }
+
+ /* Clamp to avoid top/left calculations overflowing */
+ sel.r.width = min(sel.r.width, input->native_rect.width);
+ sel.r.height = min(sel.r.height, input->native_rect.height);
+
+ sel.r.left = ((input->native_rect.width - sel.r.width) / 2) & ~1;
+ sel.r.top = ((input->native_rect.height - sel.r.height) / 2) & ~1;
+
+ ret = v4l2_subdev_call(input->camera, pad, set_selection, &pad_state, &sel);
+ if (ret)
+ dev_err(isp->dev, "Error setting crop to %ux%u @%ux%u: %d\n",
+ sel.r.width, sel.r.height, sel.r.left, sel.r.top, ret);
+
+ return ret;
+}
+
/* This function looks up the closest available resolution. */
-int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f,
- bool *res_overflow)
+int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
+ const struct atomisp_format_bridge **fmt_ret,
+ const struct atomisp_format_bridge **snr_fmt_ret)
{
- struct atomisp_device *isp = video_get_drvdata(vdev);
- struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
- struct v4l2_subdev_pad_config pad_cfg;
+ const struct atomisp_format_bridge *fmt, *snr_fmt;
+ struct atomisp_sub_device *asd = &isp->asd;
+ struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
struct v4l2_subdev_state pad_state = {
- .pads = &pad_cfg,
+ .pads = &input->pad_cfg,
};
struct v4l2_subdev_format format = {
.which = V4L2_SUBDEV_FORMAT_TRY,
};
- const struct atomisp_format_bridge *fmt;
+ u32 padding_w, padding_h;
int ret;
- if (!asd) {
- dev_err(isp->dev, "%s(): asd is NULL, device is %s\n",
- __func__, vdev->name);
- return -EINVAL;
- }
-
- if (!isp->inputs[asd->input_curr].camera)
+ if (!input->camera)
return -EINVAL;
fmt = atomisp_get_format_bridge(f->pixelformat);
- if (!fmt) {
- dev_err(isp->dev, "unsupported pixelformat!\n");
- fmt = atomisp_output_fmts;
- }
-
- if (f->width <= 0 || f->height <= 0)
- return -EINVAL;
+ /* Currently, raw formats are broken!!! */
+ if (!fmt || fmt->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) {
+ f->pixelformat = V4L2_PIX_FMT_YUV420;
- format.format.code = fmt->mbus_code;
- format.format.width = f->width;
- format.format.height = f->height;
+ fmt = atomisp_get_format_bridge(f->pixelformat);
+ if (!fmt)
+ return -EINVAL;
+ }
- __atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL,
- (struct atomisp_input_stream_info *)format.format.reserved);
+ /*
+ * atomisp_set_fmt() will set the sensor resolution to the requested
+ * resolution + padding. Add padding here and remove it again after
+ * the set_fmt call, like atomisp_set_fmt_to_snr() does.
+ */
+ atomisp_get_padding(isp, f->width, f->height, &padding_w, &padding_h);
+ v4l2_fill_mbus_format(&format.format, f, fmt->mbus_code);
+ format.format.width += padding_w;
+ format.format.height += padding_h;
dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n",
format.format.width, format.format.height);
- ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
- pad, set_fmt, &pad_state, &format);
+ ret = atomisp_set_crop(isp, &format.format, V4L2_SUBDEV_FORMAT_TRY);
+ if (ret)
+ return ret;
+
+ ret = v4l2_subdev_call(input->camera, pad, set_fmt, &pad_state, &format);
if (ret)
return ret;
dev_dbg(isp->dev, "try_mbus_fmt: got %ux%u\n",
format.format.width, format.format.height);
- fmt = atomisp_get_format_bridge_from_mbus(format.format.code);
- if (!fmt) {
+ snr_fmt = atomisp_get_format_bridge_from_mbus(format.format.code);
+ if (!snr_fmt) {
dev_err(isp->dev, "unknown sensor format 0x%8.8x\n",
format.format.code);
return -EINVAL;
}
- f->pixelformat = fmt->pixelformat;
+ f->width = format.format.width - padding_w;
+ f->height = format.format.height - padding_h;
/*
* If the format is jpeg or custom RAW, then the width and height will
@@ -3948,22 +3861,8 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f,
* the sensor driver.
*/
if (f->pixelformat == V4L2_PIX_FMT_JPEG ||
- f->pixelformat == V4L2_PIX_FMT_CUSTOM_M10MO_RAW) {
- f->width = format.format.width;
- f->height = format.format.height;
- return 0;
- }
-
- if (!res_overflow || (format.format.width < f->width &&
- format.format.height < f->height)) {
- f->width = format.format.width;
- f->height = format.format.height;
- /* Set the flag when resolution requested is
- * beyond the max value supported by sensor
- */
- if (res_overflow)
- *res_overflow = true;
- }
+ f->pixelformat == V4L2_PIX_FMT_CUSTOM_M10MO_RAW)
+ goto out_fill_pix_format;
/* app vs isp */
f->width = rounddown(clamp_t(u32, f->width, ATOM_ISP_MIN_WIDTH,
@@ -3971,11 +3870,20 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f,
f->height = rounddown(clamp_t(u32, f->height, ATOM_ISP_MIN_HEIGHT,
ATOM_ISP_MAX_HEIGHT), ATOM_ISP_STEP_HEIGHT);
+out_fill_pix_format:
+ atomisp_fill_pix_format(f, f->width, f->height, fmt);
+
+ if (fmt_ret)
+ *fmt_ret = fmt;
+
+ if (snr_fmt_ret)
+ *snr_fmt_ret = snr_fmt;
+
return 0;
}
-enum mipi_port_id __get_mipi_port(struct atomisp_device *isp,
- enum atomisp_camera_port port)
+enum mipi_port_id atomisp_port_to_mipi_port(struct atomisp_device *isp,
+ enum atomisp_camera_port port)
{
switch (port) {
case ATOMISP_CAMERA_PORT_PRIMARY:
@@ -3983,9 +3891,7 @@ enum mipi_port_id __get_mipi_port(struct atomisp_device *isp,
case ATOMISP_CAMERA_PORT_SECONDARY:
return MIPI_PORT1_ID;
case ATOMISP_CAMERA_PORT_TERTIARY:
- if (MIPI_PORT1_ID + 1 != N_MIPI_PORT_ID)
- return MIPI_PORT1_ID + 1;
- fallthrough;
+ return MIPI_PORT2_ID;
default:
dev_err(isp->dev, "unsupported port: %d\n", port);
return MIPI_PORT0_ID;
@@ -3999,13 +3905,15 @@ static inline int atomisp_set_sensor_mipi_to_isp(
{
struct v4l2_control ctrl;
struct atomisp_device *isp = asd->isp;
+ struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
const struct atomisp_in_fmt_conv *fc;
int mipi_freq = 0;
unsigned int input_format, bayer_order;
+ enum atomisp_input_format metadata_format = ATOMISP_INPUT_FORMAT_EMBEDDED;
+ u32 mipi_port, metadata_width = 0, metadata_height = 0;
ctrl.id = V4L2_CID_LINK_FREQ;
- if (v4l2_g_ctrl
- (isp->inputs[asd->input_curr].camera->ctrl_handler, &ctrl) == 0)
+ if (v4l2_g_ctrl(input->camera->ctrl_handler, &ctrl) == 0)
mipi_freq = ctrl.value;
if (asd->stream_env[stream_id].isys_configs == 1) {
@@ -4029,7 +3937,7 @@ static inline int atomisp_set_sensor_mipi_to_isp(
/* Compatibility for sensors which provide no media bus code
* in s_mbus_framefmt() nor support pad formats. */
- if (mipi_info->input_format != -1) {
+ if (mipi_info && mipi_info->input_format != -1) {
bayer_order = mipi_info->raw_bayer_order;
/* Input stream config is still needs configured */
@@ -4039,6 +3947,9 @@ static inline int atomisp_set_sensor_mipi_to_isp(
if (!fc)
return -EINVAL;
input_format = fc->atomisp_in_fmt;
+ metadata_format = mipi_info->metadata_format;
+ metadata_width = mipi_info->metadata_width;
+ metadata_height = mipi_info->metadata_height;
} else {
struct v4l2_mbus_framefmt *sink;
@@ -4055,18 +3966,17 @@ static inline int atomisp_set_sensor_mipi_to_isp(
atomisp_css_input_set_format(asd, stream_id, input_format);
atomisp_css_input_set_bayer_order(asd, stream_id, bayer_order);
- fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt(
- mipi_info->metadata_format);
+ fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt(metadata_format);
if (!fc)
return -EINVAL;
+
input_format = fc->atomisp_in_fmt;
- atomisp_css_input_configure_port(asd,
- __get_mipi_port(asd->isp, mipi_info->port),
- mipi_info->num_lanes,
+ mipi_port = atomisp_port_to_mipi_port(isp, input->port);
+ atomisp_css_input_configure_port(asd, mipi_port,
+ isp->sensor_lanes[mipi_port],
0xffff4, mipi_freq,
input_format,
- mipi_info->metadata_width,
- mipi_info->metadata_height);
+ metadata_width, metadata_height);
return 0;
}
@@ -4134,16 +4044,15 @@ static int css_input_resolution_changed(struct atomisp_sub_device *asd,
static int atomisp_set_fmt_to_isp(struct video_device *vdev,
struct ia_css_frame_info *output_info,
- struct v4l2_pix_format *pix,
- unsigned int source_pad)
+ const struct v4l2_pix_format *pix)
{
struct camera_mipi_info *mipi_info;
struct atomisp_device *isp = video_get_drvdata(vdev);
struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
+ struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
const struct atomisp_format_bridge *format;
struct v4l2_rect *isp_sink_crop;
enum ia_css_pipe_id pipe_id;
- struct v4l2_subdev_fh fh;
int (*configure_output)(struct atomisp_sub_device *asd,
unsigned int width, unsigned int height,
unsigned int min_width,
@@ -4155,7 +4064,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
int (*configure_pp_input)(struct atomisp_sub_device *asd,
unsigned int width, unsigned int height) =
configure_pp_input_nop;
- const struct atomisp_in_fmt_conv *fc;
+ const struct atomisp_in_fmt_conv *fc = NULL;
int ret, i;
if (!asd) {
@@ -4164,8 +4073,6 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
return -EINVAL;
}
- v4l2_fh_init(&fh.vfh, vdev);
-
isp_sink_crop = atomisp_subdev_get_rect(
&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE,
ATOMISP_SUBDEV_PAD_SINK, V4L2_SEL_TGT_CROP);
@@ -4174,18 +4081,16 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
if (!format)
return -EINVAL;
- if (isp->inputs[asd->input_curr].type != TEST_PATTERN) {
- mipi_info = atomisp_to_sensor_mipi_info(
- isp->inputs[asd->input_curr].camera);
- if (!mipi_info) {
- dev_err(isp->dev, "mipi_info is NULL\n");
- return -EINVAL;
- }
+ if (input->type != TEST_PATTERN) {
+ mipi_info = atomisp_to_sensor_mipi_info(input->camera);
+
if (atomisp_set_sensor_mipi_to_isp(asd, ATOMISP_INPUT_STREAM_GENERAL,
mipi_info))
return -EINVAL;
- fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt(
- mipi_info->input_format);
+
+ if (mipi_info)
+ fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt(mipi_info->input_format);
+
if (!fc)
fc = atomisp_find_in_fmt_conv(
atomisp_subdev_get_ffmt(&asd->subdev,
@@ -4204,49 +4109,24 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
* CSS still requires viewfinder configuration.
*/
{
- struct v4l2_rect vf_size = {0};
- struct v4l2_mbus_framefmt vf_ffmt = {0};
+ u32 width, height;
if (pix->width < 640 || pix->height < 480) {
- vf_size.width = pix->width;
- vf_size.height = pix->height;
+ width = pix->width;
+ height = pix->height;
} else {
- vf_size.width = 640;
- vf_size.height = 480;
+ width = 640;
+ height = 480;
}
- /* FIXME: proper format name for this one. See
- atomisp_output_fmts[] in atomisp_v4l2.c */
- vf_ffmt.code = V4L2_MBUS_FMT_CUSTOM_YUV420;
-
- atomisp_subdev_set_selection(&asd->subdev, fh.state,
- V4L2_SUBDEV_FORMAT_ACTIVE,
- ATOMISP_SUBDEV_PAD_SOURCE_VF,
- V4L2_SEL_TGT_COMPOSE, 0, &vf_size);
- atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
- V4L2_SUBDEV_FORMAT_ACTIVE,
- ATOMISP_SUBDEV_PAD_SOURCE_VF, &vf_ffmt);
- asd->video_out_vf.sh_fmt = IA_CSS_FRAME_FORMAT_NV12;
-
- if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
- atomisp_css_video_configure_viewfinder(asd,
- vf_size.width, vf_size.height, 0,
- asd->video_out_vf.sh_fmt);
- } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
- if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW ||
- source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO)
- atomisp_css_video_configure_viewfinder(asd,
- vf_size.width, vf_size.height, 0,
- asd->video_out_vf.sh_fmt);
- else
- atomisp_css_capture_configure_viewfinder(asd,
- vf_size.width, vf_size.height, 0,
- asd->video_out_vf.sh_fmt);
- } else if (source_pad != ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW ||
+ if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO ||
+ asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
+ atomisp_css_video_configure_viewfinder(asd, width, height, 0,
+ IA_CSS_FRAME_FORMAT_NV12);
+ } else if (asd->run_mode->val == ATOMISP_RUN_MODE_STILL_CAPTURE ||
asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
- atomisp_css_capture_configure_viewfinder(asd,
- vf_size.width, vf_size.height, 0,
- asd->video_out_vf.sh_fmt);
+ atomisp_css_capture_configure_viewfinder(asd, width, height, 0,
+ IA_CSS_FRAME_FORMAT_NV12);
}
}
@@ -4268,7 +4148,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
configure_output = atomisp_css_video_configure_output;
get_frame_info = atomisp_css_video_get_output_frame_info;
pipe_id = IA_CSS_PIPE_ID_VIDEO;
- } else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW) {
+ } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
configure_output = atomisp_css_preview_configure_output;
get_frame_info = atomisp_css_preview_get_output_frame_info;
configure_pp_input = atomisp_css_preview_configure_pp_input;
@@ -4333,7 +4213,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
return ret;
}
- atomisp_update_grid_info(asd, pipe_id, source_pad);
+ atomisp_update_grid_info(asd, pipe_id);
return 0;
}
@@ -4357,7 +4237,7 @@ static void atomisp_get_dis_envelop(struct atomisp_sub_device *asd,
}
static void atomisp_check_copy_mode(struct atomisp_sub_device *asd,
- int source_pad, const struct v4l2_pix_format *f)
+ const struct v4l2_pix_format *f)
{
struct v4l2_mbus_framefmt *sink, *src;
@@ -4370,7 +4250,7 @@ static void atomisp_check_copy_mode(struct atomisp_sub_device *asd,
sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK);
src = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
- V4L2_SUBDEV_FORMAT_ACTIVE, source_pad);
+ V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE);
if (sink->code == src->code && sink->width == f->width && sink->height == f->height)
asd->copy_mode = true;
@@ -4381,26 +4261,23 @@ static void atomisp_check_copy_mode(struct atomisp_sub_device *asd,
}
static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_pix_format *f,
- unsigned int padding_w, unsigned int padding_h,
unsigned int dvs_env_w, unsigned int dvs_env_h)
{
struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
struct atomisp_sub_device *asd = pipe->asd;
+ struct atomisp_device *isp = asd->isp;
+ struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
const struct atomisp_format_bridge *format;
- struct v4l2_subdev_pad_config pad_cfg;
struct v4l2_subdev_state pad_state = {
- .pads = &pad_cfg,
+ .pads = &input->pad_cfg,
};
struct v4l2_subdev_format vformat = {
.which = V4L2_SUBDEV_FORMAT_TRY,
};
struct v4l2_mbus_framefmt *ffmt = &vformat.format;
struct v4l2_mbus_framefmt *req_ffmt;
- struct atomisp_device *isp;
struct atomisp_input_stream_info *stream_info =
(struct atomisp_input_stream_info *)ffmt->reserved;
- int source_pad = atomisp_subdev_source_pad(vdev);
- struct v4l2_subdev_fh fh;
int ret;
if (!asd) {
@@ -4409,20 +4286,16 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p
return -EINVAL;
}
- isp = asd->isp;
-
- v4l2_fh_init(&fh.vfh, vdev);
-
format = atomisp_get_format_bridge(f->pixelformat);
if (!format)
return -EINVAL;
v4l2_fill_mbus_format(ffmt, f, format->mbus_code);
- ffmt->height += padding_h + dvs_env_h;
- ffmt->width += padding_w + dvs_env_w;
+ ffmt->height += asd->sink_pad_padding_h + dvs_env_h;
+ ffmt->width += asd->sink_pad_padding_w + dvs_env_w;
dev_dbg(isp->dev, "s_mbus_fmt: ask %ux%u (padding %ux%u, dvs %ux%u)\n",
- ffmt->width, ffmt->height, padding_w, padding_h,
+ ffmt->width, ffmt->height, asd->sink_pad_padding_w, asd->sink_pad_padding_h,
dvs_env_w, dvs_env_h);
__atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL, stream_info);
@@ -4430,11 +4303,13 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p
req_ffmt = ffmt;
/* Disable dvs if resolution can't be supported by sensor */
- if (asd->params.video_dis_en &&
- source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) {
+ if (asd->params.video_dis_en && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
+ ret = atomisp_set_crop(isp, &vformat.format, V4L2_SUBDEV_FORMAT_TRY);
+ if (ret)
+ return ret;
+
vformat.which = V4L2_SUBDEV_FORMAT_TRY;
- ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
- pad, set_fmt, &pad_state, &vformat);
+ ret = v4l2_subdev_call(input->camera, pad, set_fmt, &pad_state, &vformat);
if (ret)
return ret;
@@ -4451,9 +4326,13 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p
asd->params.video_dis_en = false;
}
}
+
+ ret = atomisp_set_crop(isp, &vformat.format, V4L2_SUBDEV_FORMAT_ACTIVE);
+ if (ret)
+ return ret;
+
vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE;
- ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad,
- set_fmt, NULL, &vformat);
+ ret = v4l2_subdev_call(input->camera, pad, set_fmt, NULL, &vformat);
if (ret)
return ret;
@@ -4466,15 +4345,14 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p
ffmt->height < ATOM_ISP_STEP_HEIGHT)
return -EINVAL;
- if (asd->params.video_dis_en &&
- source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO &&
+ if (asd->params.video_dis_en && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
(ffmt->width < req_ffmt->width || ffmt->height < req_ffmt->height)) {
dev_warn(isp->dev,
"can not enable video dis due to sensor limitation.");
asd->params.video_dis_en = false;
}
- atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
+ atomisp_subdev_set_ffmt(&asd->subdev, NULL,
V4L2_SUBDEV_FORMAT_ACTIVE,
ATOMISP_SUBDEV_PAD_SINK, ffmt);
@@ -4490,65 +4368,25 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
const struct atomisp_format_bridge *snr_format_bridge;
struct ia_css_frame_info output_info;
unsigned int dvs_env_w = 0, dvs_env_h = 0;
- unsigned int padding_w = pad_w, padding_h = pad_h;
struct v4l2_mbus_framefmt isp_source_fmt = {0};
- struct v4l2_subdev_format vformat = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- };
struct v4l2_rect isp_sink_crop;
- u16 source_pad = atomisp_subdev_source_pad(vdev);
- struct v4l2_subdev_fh fh;
int ret;
ret = atomisp_pipe_check(pipe, true);
if (ret)
return ret;
- if (source_pad >= ATOMISP_SUBDEV_PADS_NUM)
- return -EINVAL;
-
dev_dbg(isp->dev,
- "setting resolution %ux%u on pad %u bytesperline %u\n",
- f->fmt.pix.width, f->fmt.pix.height, source_pad, f->fmt.pix.bytesperline);
-
- v4l2_fh_init(&fh.vfh, vdev);
-
- format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
- if (!format_bridge)
- return -EINVAL;
-
- /* Currently, raw formats are broken!!! */
-
- if (format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) {
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
-
- format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
- if (!format_bridge)
- return -EINVAL;
- }
- pipe->sh_fmt = format_bridge->sh_fmt;
- pipe->pix.pixelformat = f->fmt.pix.pixelformat;
+ "setting resolution %ux%u bytesperline %u\n",
+ f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.bytesperline);
/* Ensure that the resolution is equal or below the maximum supported */
-
- vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE;
- v4l2_fill_mbus_format(&vformat.format, &f->fmt.pix, format_bridge->mbus_code);
- vformat.format.height += padding_h;
- vformat.format.width += padding_w;
-
- ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad,
- set_fmt, NULL, &vformat);
+ ret = atomisp_try_fmt(isp, &f->fmt.pix, &format_bridge, &snr_format_bridge);
if (ret)
return ret;
- f->fmt.pix.width = vformat.format.width - padding_w;
- f->fmt.pix.height = vformat.format.height - padding_h;
-
- snr_format_bridge = atomisp_get_format_bridge_from_mbus(vformat.format.code);
- if (!snr_format_bridge) {
- dev_warn(isp->dev, "Can't find bridge format\n");
- return -EINVAL;
- }
+ pipe->sh_fmt = format_bridge->sh_fmt;
+ pipe->pix.pixelformat = format_bridge->pixelformat;
atomisp_subdev_get_ffmt(&asd->subdev, NULL,
V4L2_SUBDEV_FORMAT_ACTIVE,
@@ -4556,22 +4394,22 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
snr_format_bridge->mbus_code;
isp_source_fmt.code = format_bridge->mbus_code;
- atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
+ atomisp_subdev_set_ffmt(&asd->subdev, NULL,
V4L2_SUBDEV_FORMAT_ACTIVE,
- source_pad, &isp_source_fmt);
+ ATOMISP_SUBDEV_PAD_SOURCE, &isp_source_fmt);
- if (!atomisp_subdev_format_conversion(asd, source_pad)) {
- padding_w = 0;
- padding_h = 0;
+ if (atomisp_subdev_format_conversion(asd)) {
+ atomisp_get_padding(isp, f->fmt.pix.width, f->fmt.pix.height,
+ &asd->sink_pad_padding_w, &asd->sink_pad_padding_h);
+ } else {
+ asd->sink_pad_padding_w = 0;
+ asd->sink_pad_padding_h = 0;
}
atomisp_get_dis_envelop(asd, f->fmt.pix.width, f->fmt.pix.height,
&dvs_env_w, &dvs_env_h);
- asd->capture_pad = source_pad;
-
- ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix,
- padding_w, padding_h, dvs_env_w, dvs_env_h);
+ ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix, dvs_env_w, dvs_env_h);
if (ret) {
dev_warn(isp->dev,
"Set format to sensor failed with %d\n", ret);
@@ -4580,7 +4418,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
atomisp_csi_lane_config(isp);
- atomisp_check_copy_mode(asd, source_pad, &f->fmt.pix);
+ atomisp_check_copy_mode(asd, &f->fmt.pix);
isp_sink_crop = *atomisp_subdev_get_rect(&asd->subdev, NULL,
V4L2_SUBDEV_FORMAT_ACTIVE,
@@ -4589,25 +4427,20 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
/* Try to enable YUV downscaling if ISP input is 10 % (either
* width or height) bigger than the desired result. */
- if (isp_sink_crop.width * 9 / 10 < f->fmt.pix.width ||
+ if (!IS_MOFD ||
+ isp_sink_crop.width * 9 / 10 < f->fmt.pix.width ||
isp_sink_crop.height * 9 / 10 < f->fmt.pix.height ||
- (atomisp_subdev_format_conversion(asd, source_pad) &&
+ (atomisp_subdev_format_conversion(asd) &&
(asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO ||
asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER))) {
isp_sink_crop.width = f->fmt.pix.width;
isp_sink_crop.height = f->fmt.pix.height;
- atomisp_subdev_set_selection(&asd->subdev, fh.state,
+ atomisp_subdev_set_selection(&asd->subdev, NULL,
V4L2_SUBDEV_FORMAT_ACTIVE,
- ATOMISP_SUBDEV_PAD_SINK,
- V4L2_SEL_TGT_CROP,
- V4L2_SEL_FLAG_KEEP_CONFIG,
- &isp_sink_crop);
- atomisp_subdev_set_selection(&asd->subdev, fh.state,
- V4L2_SUBDEV_FORMAT_ACTIVE,
- source_pad, V4L2_SEL_TGT_COMPOSE,
+ ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE,
0, &isp_sink_crop);
- } else if (IS_MOFD) {
+ } else {
struct v4l2_rect main_compose = {0};
main_compose.width = isp_sink_crop.width;
@@ -4622,104 +4455,25 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
f->fmt.pix.height);
}
- atomisp_subdev_set_selection(&asd->subdev, fh.state,
+ atomisp_subdev_set_selection(&asd->subdev, NULL,
V4L2_SUBDEV_FORMAT_ACTIVE,
- source_pad,
- V4L2_SEL_TGT_COMPOSE, 0,
- &main_compose);
- } else {
- struct v4l2_rect sink_crop = {0};
- struct v4l2_rect main_compose = {0};
-
- main_compose.width = f->fmt.pix.width;
- main_compose.height = f->fmt.pix.height;
-
- /* WORKAROUND: this override is universally enabled in
- * GMIN to work around a CTS failures (GMINL-539)
- * which appears to be related by a hardware
- * performance limitation. It's unclear why this
- * particular code triggers the issue. */
- if (isp_sink_crop.width * main_compose.height >
- isp_sink_crop.height * main_compose.width) {
- sink_crop.height = isp_sink_crop.height;
- sink_crop.width =
- DIV_NEAREST_STEP(sink_crop.height * f->fmt.pix.width,
- f->fmt.pix.height,
- ATOM_ISP_STEP_WIDTH);
- } else {
- sink_crop.width = isp_sink_crop.width;
- sink_crop.height =
- DIV_NEAREST_STEP(sink_crop.width * f->fmt.pix.height,
- f->fmt.pix.width,
- ATOM_ISP_STEP_HEIGHT);
- }
- atomisp_subdev_set_selection(&asd->subdev, fh.state,
- V4L2_SUBDEV_FORMAT_ACTIVE,
- ATOMISP_SUBDEV_PAD_SINK,
- V4L2_SEL_TGT_CROP,
- V4L2_SEL_FLAG_KEEP_CONFIG,
- &sink_crop);
-
- atomisp_subdev_set_selection(&asd->subdev, fh.state,
- V4L2_SUBDEV_FORMAT_ACTIVE,
- source_pad,
+ ATOMISP_SUBDEV_PAD_SOURCE,
V4L2_SEL_TGT_COMPOSE, 0,
&main_compose);
}
- ret = atomisp_set_fmt_to_isp(vdev, &output_info, &f->fmt.pix, source_pad);
+ ret = atomisp_set_fmt_to_isp(vdev, &output_info, &f->fmt.pix);
if (ret) {
dev_warn(isp->dev, "Can't set format on ISP. Error %d\n", ret);
return -EINVAL;
}
- pipe->pix.width = f->fmt.pix.width;
- pipe->pix.height = f->fmt.pix.height;
- pipe->pix.pixelformat = f->fmt.pix.pixelformat;
- /*
- * FIXME: do we need to setup this differently, depending on the
- * sensor or the pipeline?
- */
- pipe->pix.colorspace = V4L2_COLORSPACE_REC709;
- pipe->pix.ycbcr_enc = V4L2_YCBCR_ENC_709;
- pipe->pix.xfer_func = V4L2_XFER_FUNC_709;
-
- if (format_bridge->planar) {
- pipe->pix.bytesperline = output_info.padded_width;
- pipe->pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height *
- DIV_ROUND_UP(format_bridge->depth *
- output_info.padded_width, 8));
- } else {
- pipe->pix.bytesperline =
- DIV_ROUND_UP(format_bridge->depth *
- output_info.padded_width, 8);
- pipe->pix.sizeimage =
- PAGE_ALIGN(f->fmt.pix.height * pipe->pix.bytesperline);
- }
- dev_dbg(isp->dev, "%s: image size: %d, %d bytes per line\n",
- __func__, pipe->pix.sizeimage, pipe->pix.bytesperline);
-
- if (f->fmt.pix.field == V4L2_FIELD_ANY)
- f->fmt.pix.field = V4L2_FIELD_NONE;
- pipe->pix.field = f->fmt.pix.field;
+ atomisp_fill_pix_format(&pipe->pix, f->fmt.pix.width, f->fmt.pix.height, format_bridge);
f->fmt.pix = pipe->pix;
f->fmt.pix.priv = PAGE_ALIGN(pipe->pix.width *
pipe->pix.height * 2);
- /*
- * If in video 480P case, no GFX throttle
- */
- if (asd->run_mode->val == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO &&
- f->fmt.pix.width == 720 && f->fmt.pix.height == 480)
- isp->need_gfx_throttle = false;
- else
- isp->need_gfx_throttle = true;
-
- /* Report the needed sizes */
- f->fmt.pix.sizeimage = pipe->pix.sizeimage;
- f->fmt.pix.bytesperline = pipe->pix.bytesperline;
-
dev_dbg(isp->dev, "%s: %dx%d, image size: %d, %d bytes per line\n",
__func__,
f->fmt.pix.width, f->fmt.pix.height,
@@ -4790,30 +4544,6 @@ out:
return ret;
}
-/*
- * set auto exposure metering window to camera sensor
- */
-int atomisp_s_ae_window(struct atomisp_sub_device *asd,
- struct atomisp_ae_window *arg)
-{
- struct atomisp_device *isp = asd->isp;
- /* Coverity CID 298071 - initialzize struct */
- struct v4l2_subdev_selection sel = { 0 };
-
- sel.r.left = arg->x_left;
- sel.r.top = arg->y_top;
- sel.r.width = arg->x_right - arg->x_left + 1;
- sel.r.height = arg->y_bottom - arg->y_top + 1;
-
- if (v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
- pad, set_selection, NULL, &sel)) {
- dev_err(isp->dev, "failed to call sensor set_selection.\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
int atomisp_flash_enable(struct atomisp_sub_device *asd, int num_frames)
{
struct atomisp_device *isp = asd->isp;
@@ -4836,26 +4566,6 @@ int atomisp_flash_enable(struct atomisp_sub_device *asd, int num_frames)
return 0;
}
-bool atomisp_is_vf_pipe(struct atomisp_video_pipe *pipe)
-{
- struct atomisp_sub_device *asd = pipe->asd;
-
- if (!asd) {
- dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n",
- __func__, pipe->vdev.name);
- return false;
- }
-
- if (pipe == &asd->video_out_vf)
- return true;
-
- if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
- pipe == &asd->video_out_preview)
- return true;
-
- return false;
-}
-
static int __checking_exp_id(struct atomisp_sub_device *asd, int exp_id)
{
struct atomisp_device *isp = asd->isp;
@@ -4864,7 +4574,7 @@ static int __checking_exp_id(struct atomisp_sub_device *asd, int exp_id)
dev_warn(isp->dev, "%s Raw Buffer Lock is disable.\n", __func__);
return -EINVAL;
}
- if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) {
+ if (!asd->streaming) {
dev_err(isp->dev, "%s streaming %d invalid exp_id %d.\n",
__func__, exp_id, asd->streaming);
return -EINVAL;
@@ -4986,7 +4696,7 @@ int atomisp_enable_dz_capt_pipe(struct atomisp_sub_device *asd,
int atomisp_inject_a_fake_event(struct atomisp_sub_device *asd, int *event)
{
- if (!event || asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
+ if (!event || !asd->streaming)
return -EINVAL;
lockdep_assert_held(&asd->isp->mutex);
@@ -5013,69 +4723,3 @@ int atomisp_inject_a_fake_event(struct atomisp_sub_device *asd, int *event)
return 0;
}
-
-static int atomisp_get_pipe_id(struct atomisp_video_pipe *pipe)
-{
- struct atomisp_sub_device *asd = pipe->asd;
-
- if (!asd) {
- dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n",
- __func__, pipe->vdev.name);
- return -EINVAL;
- }
-
- if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
- return IA_CSS_PIPE_ID_VIDEO;
- } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
- return IA_CSS_PIPE_ID_CAPTURE;
- } else if (pipe == &asd->video_out_video_capture) {
- return IA_CSS_PIPE_ID_VIDEO;
- } else if (pipe == &asd->video_out_vf) {
- return IA_CSS_PIPE_ID_CAPTURE;
- } else if (pipe == &asd->video_out_preview) {
- if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
- return IA_CSS_PIPE_ID_VIDEO;
- else
- return IA_CSS_PIPE_ID_PREVIEW;
- } else if (pipe == &asd->video_out_capture) {
- if (asd->copy_mode)
- return IA_CSS_PIPE_ID_COPY;
- else
- return IA_CSS_PIPE_ID_CAPTURE;
- }
-
- /* fail through */
- dev_warn(asd->isp->dev, "%s failed to find proper pipe\n",
- __func__);
- return IA_CSS_PIPE_ID_CAPTURE;
-}
-
-int atomisp_get_invalid_frame_num(struct video_device *vdev,
- int *invalid_frame_num)
-{
- struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
- struct atomisp_sub_device *asd = pipe->asd;
- enum ia_css_pipe_id pipe_id;
- struct ia_css_pipe_info p_info;
- int ret;
-
- pipe_id = atomisp_get_pipe_id(pipe);
- if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].pipes[pipe_id]) {
- dev_warn(asd->isp->dev,
- "%s pipe %d has not been created yet, do SET_FMT first!\n",
- __func__, pipe_id);
- return -EINVAL;
- }
-
- ret = ia_css_pipe_get_info(
- asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
- .pipes[pipe_id], &p_info);
- if (!ret) {
- *invalid_frame_num = p_info.num_invalid_frames;
- return 0;
- } else {
- dev_warn(asd->isp->dev, "%s get pipe infor failed %d\n",
- __func__, ret);
- return -EINVAL;
- }
-}
diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h
index 399b549bcf83..8305161d2062 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h
@@ -59,7 +59,6 @@ int atomisp_buffers_in_css(struct atomisp_video_pipe *pipe);
void atomisp_buffer_done(struct ia_css_frame *frame, enum vb2_buffer_state state);
void atomisp_flush_video_pipe(struct atomisp_video_pipe *pipe, enum vb2_buffer_state state,
bool warn_on_css_frames);
-void atomisp_flush_bufs_and_wakeup(struct atomisp_sub_device *asd);
void atomisp_clear_css_buffer_counters(struct atomisp_sub_device *asd);
/* Interrupt functions */
@@ -160,13 +159,6 @@ int atomisp_set_dis_vector(struct atomisp_sub_device *asd,
int atomisp_3a_stat(struct atomisp_sub_device *asd, int flag,
struct atomisp_3a_statistics *config);
-/* Function to get metadata from isp */
-int atomisp_get_metadata(struct atomisp_sub_device *asd, int flag,
- struct atomisp_metadata *config);
-
-int atomisp_get_metadata_by_type(struct atomisp_sub_device *asd, int flag,
- struct atomisp_metadata_with_type *config);
-
int atomisp_set_parameters(struct video_device *vdev,
struct atomisp_parameters *arg);
@@ -258,9 +250,14 @@ int atomisp_makeup_css_parameters(struct atomisp_sub_device *asd,
int atomisp_compare_grid(struct atomisp_sub_device *asd,
struct atomisp_grid_info *atomgrid);
+/* Get sensor padding values for the non padded width x height resolution */
+void atomisp_get_padding(struct atomisp_device *isp, u32 width, u32 height,
+ u32 *padding_w, u32 *padding_h);
+
/* This function looks up the closest available resolution. */
-int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f,
- bool *res_overflow);
+int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
+ const struct atomisp_format_bridge **fmt_ret,
+ const struct atomisp_format_bridge **snr_fmt_ret);
int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f);
@@ -269,9 +266,6 @@ int atomisp_set_shading_table(struct atomisp_sub_device *asd,
void atomisp_free_internal_buffers(struct atomisp_sub_device *asd);
-int atomisp_s_ae_window(struct atomisp_sub_device *asd,
- struct atomisp_ae_window *arg);
-
int atomisp_flash_enable(struct atomisp_sub_device *asd,
int num_frames);
@@ -284,15 +278,11 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
enum ia_css_pipe_id css_pipe_id,
bool q_buffers, enum atomisp_input_stream_id stream_id);
-void atomisp_css_flush(struct atomisp_device *isp);
-
/* Events. Only one event has to be exported for now. */
void atomisp_eof_event(struct atomisp_sub_device *asd, uint8_t exp_id);
-enum mipi_port_id __get_mipi_port(struct atomisp_device *isp,
- enum atomisp_camera_port port);
-
-bool atomisp_is_vf_pipe(struct atomisp_video_pipe *pipe);
+enum mipi_port_id atomisp_port_to_mipi_port(struct atomisp_device *isp,
+ enum atomisp_camera_port port);
void atomisp_apply_css_parameters(
struct atomisp_sub_device *asd,
diff --git a/drivers/staging/media/atomisp/pci/atomisp_common.h b/drivers/staging/media/atomisp/pci/atomisp_common.h
index 07c38e487a66..9d23a6ccfc33 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_common.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_common.h
@@ -37,6 +37,10 @@ extern int mipicsi_flag;
extern int pad_w;
extern int pad_h;
+/* Minimum padding requirements for ISP2400 (BYT) */
+#define ISP2400_MIN_PAD_W 12
+#define ISP2400_MIN_PAD_H 12
+
#define CSS_DTRACE_VERBOSITY_LEVEL 5 /* Controls trace verbosity */
#define CSS_DTRACE_VERBOSITY_TIMEOUT 9 /* Verbosity on ISP timeout */
#define MRFLD_MAX_ZOOM_FACTOR 1024
diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat.h b/drivers/staging/media/atomisp/pci/atomisp_compat.h
index 218e8ac276c8..e9e4bfb0f5f9 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_compat.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_compat.h
@@ -78,8 +78,7 @@ int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
void ia_css_mmu_invalidate_cache(void);
-int atomisp_css_start(struct atomisp_sub_device *asd,
- enum ia_css_pipe_id pipe_id, bool in_reset);
+int atomisp_css_start(struct atomisp_sub_device *asd);
void atomisp_css_update_isp_params(struct atomisp_sub_device *asd);
void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd,
@@ -113,8 +112,7 @@ void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf
*metadata_buf);
int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
- enum ia_css_pipe_id pipe_id,
- int source_pad);
+ enum ia_css_pipe_id pipe_id);
int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd);
@@ -151,10 +149,6 @@ int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
struct v4l2_mbus_framefmt *ffmt);
-int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
- enum atomisp_input_stream_id stream_id,
- enum atomisp_input_format input_format);
-
void atomisp_css_isys_two_stream_cfg_update_stream1(
struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
@@ -210,15 +204,6 @@ void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd,
void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
unsigned short stream_index, bool enable);
-void atomisp_css_video_enable_online(struct atomisp_sub_device *asd,
- bool enable);
-
-void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
- bool enable);
-
-void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
- bool enable);
-
int atomisp_css_input_configure_port(struct atomisp_sub_device *asd,
enum mipi_port_id port,
unsigned int num_lanes,
@@ -229,10 +214,9 @@ int atomisp_css_input_configure_port(struct atomisp_sub_device *asd,
unsigned int metadata_height);
int atomisp_create_pipes_stream(struct atomisp_sub_device *asd);
-void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd);
+void atomisp_destroy_pipes_stream(struct atomisp_sub_device *asd);
-void atomisp_css_stop(struct atomisp_sub_device *asd,
- enum ia_css_pipe_id pipe_id, bool in_reset);
+void atomisp_css_stop(struct atomisp_sub_device *asd, bool in_reset);
void atomisp_css_continuous_set_num_raw_frames(
struct atomisp_sub_device *asd,
@@ -244,22 +228,6 @@ int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
unsigned int padded_width,
enum ia_css_frame_format format);
-int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd,
- unsigned int stream_index,
- unsigned int width, unsigned int height,
- unsigned int padded_width,
- enum ia_css_frame_format format);
-
-int atomisp_css_yuvpp_get_output_frame_info(
- struct atomisp_sub_device *asd,
- unsigned int stream_index,
- struct ia_css_frame_info *info);
-
-int atomisp_css_yuvpp_get_viewfinder_frame_info(
- struct atomisp_sub_device *asd,
- unsigned int stream_index,
- struct ia_css_frame_info *info);
-
int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
unsigned int width, unsigned int height,
unsigned int min_width,
@@ -276,7 +244,6 @@ int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
enum ia_css_frame_format format);
int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
- u16 source_pad,
struct ia_css_frame_info *frame_info);
int atomisp_css_video_configure_viewfinder(struct atomisp_sub_device *asd,
diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
index 1dae2a7cfdd9..b13d1cb4668d 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
@@ -548,7 +548,7 @@ static int __destroy_pipes(struct atomisp_sub_device *asd)
return 0;
}
-void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd)
+void atomisp_destroy_pipes_stream(struct atomisp_sub_device *asd)
{
if (__destroy_streams(asd))
dev_warn(asd->isp->dev, "destroy stream failed.\n");
@@ -650,23 +650,11 @@ static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
return true;
return false;
- case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE:
- if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
- pipe_id == IA_CSS_PIPE_ID_PREVIEW)
- return true;
-
- return false;
case ATOMISP_RUN_MODE_VIDEO:
if (pipe_id == IA_CSS_PIPE_ID_VIDEO || pipe_id == IA_CSS_PIPE_ID_YUVPP)
return true;
return false;
- case ATOMISP_RUN_MODE_SDV:
- if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
- pipe_id == IA_CSS_PIPE_ID_VIDEO)
- return true;
-
- return false;
}
return false;
@@ -758,7 +746,7 @@ int atomisp_create_pipes_stream(struct atomisp_sub_device *asd)
int atomisp_css_update_stream(struct atomisp_sub_device *asd)
{
- atomisp_destroy_pipes_stream_force(asd);
+ atomisp_destroy_pipes_stream(asd);
return atomisp_create_pipes_stream(asd);
}
@@ -997,57 +985,22 @@ int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
return 0;
}
-int atomisp_css_start(struct atomisp_sub_device *asd,
- enum ia_css_pipe_id pipe_id, bool in_reset)
+int atomisp_css_start(struct atomisp_sub_device *asd)
{
struct atomisp_device *isp = asd->isp;
bool sp_is_started = false;
int ret = 0, i = 0;
- if (in_reset) {
- ret = atomisp_css_update_stream(asd);
- if (ret)
- return ret;
+ if (!sh_css_hrt_system_is_idle())
+ dev_err(isp->dev, "CSS HW not idle before starting SP\n");
- /* Invalidate caches. FIXME: should flush only necessary buffers */
- wbinvd();
+ if (ia_css_start_sp()) {
+ dev_err(isp->dev, "start sp error.\n");
+ ret = -EINVAL;
+ goto start_err;
}
- /*
- * For dual steam case, it is possible that:
- * 1: for this stream, it is at the stage that:
- * - after set_fmt is called
- * - before stream on is called
- * 2: for the other stream, the stream off is called which css reset
- * has been done.
- *
- * Thus the stream created in set_fmt get destroyed and need to be
- * recreated in the next stream on.
- */
- if (!asd->stream_prepared) {
- ret = atomisp_create_pipes_stream(asd);
- if (ret)
- return ret;
- }
- /*
- * SP can only be started one time
- * if atomisp_subdev_streaming_count() tell there already has some
- * subdev at streamming, then SP should already be started previously,
- * so need to skip start sp procedure
- */
- if (atomisp_streaming_count(isp)) {
- dev_dbg(isp->dev, "skip start sp\n");
- } else {
- if (!sh_css_hrt_system_is_idle())
- dev_err(isp->dev, "CSS HW not idle before starting SP\n");
- if (ia_css_start_sp()) {
- dev_err(isp->dev, "start sp error.\n");
- ret = -EINVAL;
- goto start_err;
- } else {
- sp_is_started = true;
- }
- }
+ sp_is_started = true;
for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
if (asd->stream_env[i].stream) {
@@ -1066,16 +1019,15 @@ int atomisp_css_start(struct atomisp_sub_device *asd,
return 0;
start_err:
- atomisp_destroy_pipes_stream_force(asd);
-
- /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
- * destroy all pipes
- */
/*
- * SP can not be stop if other streams are in use
+ * CSS 2.0 API limitation: ia_css_stop_sp() can only be called after
+ * destroying all pipes.
*/
- if ((atomisp_streaming_count(isp) == 0) && sp_is_started)
+ if (sp_is_started) {
+ atomisp_destroy_pipes_stream(asd);
ia_css_stop_sp();
+ atomisp_create_pipes_stream(asd);
+ }
return ret;
}
@@ -1340,8 +1292,7 @@ void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd)
}
int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
- enum ia_css_pipe_id pipe_id,
- int source_pad)
+ enum ia_css_pipe_id pipe_id)
{
struct ia_css_pipe_info p_info;
struct ia_css_grid_info old_info;
@@ -1624,29 +1575,6 @@ int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
return 0;
}
-int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
- enum atomisp_input_stream_id stream_id,
- enum atomisp_input_format input_format)
-{
- struct ia_css_stream_config *s_config =
- &asd->stream_env[stream_id].stream_config;
-
- s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
- s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width;
-
- s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
- s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2;
-
- s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
- = IA_CSS_STREAM_ISYS_STREAM_0;
- s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
- ATOMISP_INPUT_FORMAT_USER_DEF1;
- s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
- ATOMISP_INPUT_FORMAT_USER_DEF2;
- s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
- return 0;
-}
-
void atomisp_css_isys_two_stream_cfg_update_stream1(
struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
@@ -1832,49 +1760,6 @@ void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
}
}
-void atomisp_css_video_enable_online(struct atomisp_sub_device *asd,
- bool enable)
-{
- struct atomisp_stream_env *stream_env =
- &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO];
- int i;
-
- if (stream_env->stream_config.online != enable) {
- stream_env->stream_config.online = enable;
- for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
- stream_env->update_pipe[i] = true;
- }
-}
-
-void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
- bool enable)
-{
- struct atomisp_stream_env *stream_env =
- &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
- int i;
-
- if (stream_env->stream_config.continuous != !!enable) {
- stream_env->stream_config.continuous = !!enable;
- stream_env->stream_config.pack_raw_pixels = true;
- for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
- stream_env->update_pipe[i] = true;
- }
-}
-
-void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
- bool enable)
-{
- struct atomisp_stream_env *stream_env =
- &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
- int i;
-
- if (stream_env->stream_config.disable_cont_viewfinder != !enable) {
- stream_env->stream_config.disable_cont_viewfinder = !enable;
- for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
- stream_env->update_pipe[i] = true;
- }
-}
-
int atomisp_css_input_configure_port(
struct atomisp_sub_device *asd,
enum mipi_port_id port,
@@ -1919,23 +1804,20 @@ int atomisp_css_input_configure_port(
return 0;
}
-void atomisp_css_stop(struct atomisp_sub_device *asd,
- enum ia_css_pipe_id pipe_id, bool in_reset)
+void atomisp_css_stop(struct atomisp_sub_device *asd, bool in_reset)
{
- struct atomisp_device *isp = asd->isp;
unsigned long irqflags;
unsigned int i;
- /* if is called in atomisp_reset(), force destroy streams and pipes */
- atomisp_destroy_pipes_stream_force(asd);
+ /*
+ * CSS 2.0 API limitation: ia_css_stop_sp() can only be called after
+ * destroying all pipes.
+ */
+ atomisp_destroy_pipes_stream(asd);
atomisp_init_raw_buffer_bitmap(asd);
- /*
- * SP can not be stop if other streams are in use
- */
- if (atomisp_streaming_count(isp) == 0)
- ia_css_stop_sp();
+ ia_css_stop_sp();
if (!in_reset) {
struct atomisp_stream_env *stream_env;
@@ -1970,10 +1852,7 @@ void atomisp_css_stop(struct atomisp_sub_device *asd,
list_splice_init(&asd->metadata_ready[i], &asd->metadata[i]);
}
- atomisp_flush_params_queue(&asd->video_out_capture);
- atomisp_flush_params_queue(&asd->video_out_vf);
- atomisp_flush_params_queue(&asd->video_out_preview);
- atomisp_flush_params_queue(&asd->video_out_video_capture);
+ atomisp_flush_params_queue(&asd->video_out);
atomisp_free_css_parameters(&asd->params.css_param);
memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
}
@@ -2424,54 +2303,33 @@ static int __get_frame_info(struct atomisp_sub_device *asd,
return 0;
get_info_err:
- atomisp_destroy_pipes_stream_force(asd);
+ atomisp_destroy_pipes_stream(asd);
return -EINVAL;
}
-static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
- uint16_t source_pad)
+static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd)
{
- struct atomisp_device *isp = asd->isp;
-
- switch (source_pad) {
- case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
- if (asd->copy_mode)
- return IA_CSS_PIPE_ID_COPY;
- if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO
- || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
- return IA_CSS_PIPE_ID_VIDEO;
-
- return IA_CSS_PIPE_ID_CAPTURE;
- case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
- if (asd->copy_mode)
- return IA_CSS_PIPE_ID_COPY;
+ if (asd->copy_mode)
+ return IA_CSS_PIPE_ID_COPY;
+ switch (asd->run_mode->val) {
+ case ATOMISP_RUN_MODE_VIDEO:
+ return IA_CSS_PIPE_ID_VIDEO;
+ case ATOMISP_RUN_MODE_STILL_CAPTURE:
return IA_CSS_PIPE_ID_CAPTURE;
- case ATOMISP_SUBDEV_PAD_SOURCE_VF:
- if (!atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code)) {
- return IA_CSS_PIPE_ID_CAPTURE;
- }
- fallthrough;
- case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
- if (asd->copy_mode)
- return IA_CSS_PIPE_ID_COPY;
- if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
- return IA_CSS_PIPE_ID_VIDEO;
-
+ case ATOMISP_RUN_MODE_PREVIEW:
return IA_CSS_PIPE_ID_PREVIEW;
}
- dev_warn(isp->dev,
- "invalid source pad:%d, return default preview pipe index.\n",
- source_pad);
+
+ dev_warn(asd->isp->dev, "cannot determine pipe-index return default preview pipe\n");
return IA_CSS_PIPE_ID_PREVIEW;
}
int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
- u16 source_pad,
struct ia_css_frame_info *frame_info)
{
struct ia_css_pipe_info info;
- int pipe_index = atomisp_get_pipe_index(asd, source_pad);
+ int pipe_index = atomisp_get_pipe_index(asd);
int stream_index;
struct atomisp_device *isp = asd->isp;
@@ -2485,34 +2343,8 @@ int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
return -EINVAL;
}
- switch (source_pad) {
- case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
- *frame_info = info.output_info[0];
- break;
- case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
- *frame_info = info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
- break;
- case ATOMISP_SUBDEV_PAD_SOURCE_VF:
- if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW)
- *frame_info = info.output_info[0];
- else
- *frame_info = info.vf_output_info[0];
- break;
- case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
- if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
- (pipe_index == IA_CSS_PIPE_ID_VIDEO ||
- pipe_index == IA_CSS_PIPE_ID_YUVPP))
- *frame_info = info.vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
- else
- *frame_info =
- info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
-
- break;
- default:
- frame_info = NULL;
- break;
- }
- return frame_info ? 0 : -EINVAL;
+ *frame_info = info.output_info[0];
+ return 0;
}
int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
@@ -2530,39 +2362,6 @@ int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
return 0;
}
-int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd,
- unsigned int stream_index,
- unsigned int width, unsigned int height,
- unsigned int padded_width,
- enum ia_css_frame_format format)
-{
- asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP].
- default_capture_config.mode =
- IA_CSS_CAPTURE_MODE_RAW;
-
- __configure_output(asd, stream_index, width, height, padded_width,
- format, IA_CSS_PIPE_ID_YUVPP);
- return 0;
-}
-
-int atomisp_css_yuvpp_get_output_frame_info(
- struct atomisp_sub_device *asd,
- unsigned int stream_index,
- struct ia_css_frame_info *info)
-{
- return __get_frame_info(asd, stream_index, info,
- ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP);
-}
-
-int atomisp_css_yuvpp_get_viewfinder_frame_info(
- struct atomisp_sub_device *asd,
- unsigned int stream_index,
- struct ia_css_frame_info *info)
-{
- return __get_frame_info(asd, stream_index, info,
- ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP);
-}
-
int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
unsigned int width, unsigned int height,
unsigned int min_width,
@@ -3271,7 +3070,7 @@ int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
return -EINVAL;
/* isp needs to be streaming to get DIS statistics */
- if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
+ if (!asd->streaming)
return -EINVAL;
if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0)
@@ -3400,7 +3199,7 @@ static bool atomisp_css_isr_get_stream_id(struct ia_css_pipe *css_pipe,
struct atomisp_stream_env *stream_env;
int i, j;
- if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_DISABLED)
+ if (!isp->asd.streaming)
return false;
for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h b/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h
index 33821b51d90e..762520ed87a5 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h
@@ -67,26 +67,6 @@ struct atomisp_3a_statistics32 {
u32 isp_config_id;
};
-struct atomisp_metadata_with_type32 {
- /* to specify which type of metadata to get */
- enum atomisp_metadata_type type;
- compat_uptr_t data;
- u32 width;
- u32 height;
- u32 stride; /* in bytes */
- u32 exp_id; /* exposure ID */
- compat_uptr_t effective_width;
-};
-
-struct atomisp_metadata32 {
- compat_uptr_t data;
- u32 width;
- u32 height;
- u32 stride;
- u32 exp_id;
- compat_uptr_t effective_width;
-};
-
struct atomisp_morph_table32 {
unsigned int enabled;
unsigned int height;
@@ -134,18 +114,6 @@ struct atomisp_overlay32 {
unsigned int overlay_start_y;
};
-struct atomisp_calibration_group32 {
- unsigned int size;
- unsigned int type;
- compat_uptr_t calb_grp_values;
-};
-
-struct v4l2_private_int_data32 {
- __u32 size;
- compat_uptr_t data;
- __u32 reserved[2];
-};
-
struct atomisp_shading_table32 {
__u32 enable;
__u32 sensor_width;
@@ -249,11 +217,6 @@ struct atomisp_dvs_6axis_config32 {
compat_uptr_t ycoords_uv;
};
-struct atomisp_sensor_ae_bracketing_lut32 {
- compat_uptr_t lut;
- unsigned int lut_size;
-};
-
#define ATOMISP_IOC_G_HISTOGRAM32 \
_IOWR('v', BASE_VIDIOC_PRIVATE + 3, struct atomisp_histogram32)
#define ATOMISP_IOC_S_HISTOGRAM32 \
@@ -283,28 +246,10 @@ struct atomisp_sensor_ae_bracketing_lut32 {
#define ATOMISP_IOC_S_ISP_OVERLAY32 \
_IOW('v', BASE_VIDIOC_PRIVATE + 18, struct atomisp_overlay32)
-#define ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP32 \
- _IOWR('v', BASE_VIDIOC_PRIVATE + 22, struct atomisp_calibration_group32)
-
-#define ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA32 \
- _IOWR('v', BASE_VIDIOC_PRIVATE + 26, struct v4l2_private_int_data32)
-
#define ATOMISP_IOC_S_ISP_SHD_TAB32 \
_IOWR('v', BASE_VIDIOC_PRIVATE + 27, struct atomisp_shading_table32)
-#define ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA32 \
- _IOWR('v', BASE_VIDIOC_PRIVATE + 29, struct v4l2_private_int_data32)
-
#define ATOMISP_IOC_S_PARAMETERS32 \
_IOW('v', BASE_VIDIOC_PRIVATE + 32, struct atomisp_parameters32)
-#define ATOMISP_IOC_G_METADATA32 \
- _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata32)
-
-#define ATOMISP_IOC_G_METADATA_BY_TYPE32 \
- _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata_with_type32)
-
-#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT32 \
- _IOW('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_lut32)
-
#endif /* __ATOMISP_COMPAT_IOCTL32_H__ */
diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.c b/drivers/staging/media/atomisp/pci/atomisp_csi2.c
index b00bc0b7aaad..abf55a86f795 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_csi2.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.c
@@ -322,15 +322,11 @@ static void atomisp_csi2_configure_isp2401(struct atomisp_sub_device *asd)
struct v4l2_control ctrl;
struct atomisp_device *isp = asd->isp;
- struct camera_mipi_info *mipi_info;
int mipi_freq = 0;
enum atomisp_camera_port port;
-
int n;
- mipi_info = atomisp_to_sensor_mipi_info(
- isp->inputs[asd->input_curr].camera);
- port = mipi_info->port;
+ port = isp->inputs[asd->input_curr].port;
ctrl.id = V4L2_CID_LINK_FREQ;
if (v4l2_g_ctrl
@@ -375,6 +371,10 @@ int atomisp_mipi_csi2_init(struct atomisp_device *isp)
unsigned int i;
int ret;
+ ret = atomisp_csi2_bridge_init(isp);
+ if (ret < 0)
+ return ret;
+
for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
csi2_port = &isp->csi2_port[i];
csi2_port->isp = isp;
diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.h b/drivers/staging/media/atomisp/pci/atomisp_csi2.h
index b245b2f5ce99..16ddb3ab2963 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_csi2.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.h
@@ -18,17 +18,107 @@
#ifndef __ATOMISP_CSI2_H__
#define __ATOMISP_CSI2_H__
+#include <linux/gpio/consumer.h>
+#include <linux/property.h>
+
#include <media/v4l2-subdev.h>
#include <media/v4l2-ctrls.h>
+#include "../../include/linux/atomisp.h"
+
#define CSI2_PAD_SINK 0
#define CSI2_PAD_SOURCE 1
#define CSI2_PADS_NUM 2
-struct atomisp_device;
+#define CSI2_MAX_LANES 4
+#define CSI2_MAX_LINK_FREQS 3
+
+#define CSI2_MAX_ACPI_GPIOS 2u
+
+struct acpi_device;
struct v4l2_device;
+
+struct atomisp_device;
struct atomisp_sub_device;
+struct atomisp_csi2_acpi_gpio_map {
+ struct acpi_gpio_params params[CSI2_MAX_ACPI_GPIOS];
+ struct acpi_gpio_mapping mapping[CSI2_MAX_ACPI_GPIOS + 1];
+};
+
+struct atomisp_csi2_acpi_gpio_parsing_data {
+ struct acpi_device *adev;
+ struct atomisp_csi2_acpi_gpio_map *map;
+ u32 settings[CSI2_MAX_ACPI_GPIOS];
+ unsigned int settings_count;
+ unsigned int res_count;
+ unsigned int map_count;
+};
+
+enum atomisp_csi2_sensor_swnodes {
+ SWNODE_SENSOR,
+ SWNODE_SENSOR_PORT,
+ SWNODE_SENSOR_ENDPOINT,
+ SWNODE_CSI2_PORT,
+ SWNODE_CSI2_ENDPOINT,
+ SWNODE_COUNT
+};
+
+struct atomisp_csi2_property_names {
+ char clock_frequency[16];
+ char rotation[9];
+ char bus_type[9];
+ char data_lanes[11];
+ char remote_endpoint[16];
+ char link_frequencies[17];
+};
+
+struct atomisp_csi2_node_names {
+ char port[7];
+ char endpoint[11];
+ char remote_port[7];
+};
+
+struct atomisp_csi2_sensor_config {
+ const char *hid;
+ int lanes;
+ int nr_link_freqs;
+ u64 link_freqs[CSI2_MAX_LINK_FREQS];
+};
+
+struct atomisp_csi2_sensor {
+ /* Append port in "-%u" format as suffix of HID */
+ char name[ACPI_ID_LEN + 4];
+ struct acpi_device *adev;
+ int port;
+ int lanes;
+
+ /* SWNODE_COUNT + 1 for terminating NULL */
+ const struct software_node *group[SWNODE_COUNT + 1];
+ struct software_node swnodes[SWNODE_COUNT];
+ struct atomisp_csi2_node_names node_names;
+ struct atomisp_csi2_property_names prop_names;
+ /* "clock-frequency", "rotation" + terminating entry */
+ struct property_entry dev_properties[3];
+ /* "bus-type", "data-lanes", "remote-endpoint" + "link-freq" + terminating entry */
+ struct property_entry ep_properties[5];
+ /* "data-lanes", "remote-endpoint" + terminating entry */
+ struct property_entry csi2_properties[3];
+ struct software_node_ref_args local_ref[1];
+ struct software_node_ref_args remote_ref[1];
+ struct software_node_ref_args vcm_ref[1];
+ /* GPIO mappings storage */
+ struct atomisp_csi2_acpi_gpio_map gpio_map;
+};
+
+struct atomisp_csi2_bridge {
+ struct software_node csi2_node;
+ char csi2_node_name[14];
+ u32 data_lanes[CSI2_MAX_LANES];
+ unsigned int n_sensors;
+ struct atomisp_csi2_sensor sensors[ATOMISP_CAMERA_NR_PORTS];
+};
+
struct atomisp_mipi_csi2_device {
struct v4l2_subdev subdev;
struct media_pad pads[CSI2_PADS_NUM];
@@ -48,6 +138,8 @@ void atomisp_mipi_csi2_unregister_entities(
struct atomisp_mipi_csi2_device *csi2);
int atomisp_mipi_csi2_register_entities(struct atomisp_mipi_csi2_device *csi2,
struct v4l2_device *vdev);
+int atomisp_csi2_bridge_init(struct atomisp_device *isp);
+int atomisp_csi2_bridge_parse_firmware(struct atomisp_device *isp);
void atomisp_csi2_configure(struct atomisp_sub_device *asd);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c
new file mode 100644
index 000000000000..0d12ba78d9c1
--- /dev/null
+++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c
@@ -0,0 +1,874 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Code to build software firmware node graph for atomisp2 connected sensors
+ * from ACPI tables.
+ *
+ * Copyright (C) 2023 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on drivers/media/pci/intel/ipu3/cio2-bridge.c written by:
+ * Dan Scally <djrscally@gmail.com>
+ */
+
+#include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/dmi.h>
+#include <linux/property.h>
+#include <media/v4l2-fwnode.h>
+
+#include "atomisp_cmd.h"
+#include "atomisp_csi2.h"
+#include "atomisp_internal.h"
+
+#define NODE_SENSOR(_HID, _PROPS) \
+ ((const struct software_node) { \
+ .name = _HID, \
+ .properties = _PROPS, \
+ })
+
+#define NODE_PORT(_PORT, _SENSOR_NODE) \
+ ((const struct software_node) { \
+ .name = _PORT, \
+ .parent = _SENSOR_NODE, \
+ })
+
+#define NODE_ENDPOINT(_EP, _PORT, _PROPS) \
+ ((const struct software_node) { \
+ .name = _EP, \
+ .parent = _PORT, \
+ .properties = _PROPS, \
+ })
+
+#define PMC_CLK_RATE_19_2MHZ 19200000
+
+/*
+ * 79234640-9e10-4fea-a5c1-b5aa8b19756f
+ * This _DSM GUID returns information about the GPIO lines mapped to a sensor.
+ * Function number 1 returns a count of the GPIO lines that are mapped.
+ * Subsequent functions return 32 bit ints encoding information about the GPIO.
+ */
+static const guid_t intel_sensor_gpio_info_guid =
+ GUID_INIT(0x79234640, 0x9e10, 0x4fea,
+ 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f);
+
+#define INTEL_GPIO_DSM_TYPE_SHIFT 0
+#define INTEL_GPIO_DSM_TYPE_MASK GENMASK(7, 0)
+#define INTEL_GPIO_DSM_PIN_SHIFT 8
+#define INTEL_GPIO_DSM_PIN_MASK GENMASK(15, 8)
+#define INTEL_GPIO_DSM_SENSOR_ON_VAL_SHIFT 24
+#define INTEL_GPIO_DSM_SENSOR_ON_VAL_MASK GENMASK(31, 24)
+
+#define INTEL_GPIO_DSM_TYPE(x) \
+ (((x) & INTEL_GPIO_DSM_TYPE_MASK) >> INTEL_GPIO_DSM_TYPE_SHIFT)
+#define INTEL_GPIO_DSM_PIN(x) \
+ (((x) & INTEL_GPIO_DSM_PIN_MASK) >> INTEL_GPIO_DSM_PIN_SHIFT)
+#define INTEL_GPIO_DSM_SENSOR_ON_VAL(x) \
+ (((x) & INTEL_GPIO_DSM_SENSOR_ON_VAL_MASK) >> INTEL_GPIO_DSM_SENSOR_ON_VAL_SHIFT)
+
+/*
+ * 822ace8f-2814-4174-a56b-5f029fe079ee
+ * This _DSM GUID returns a string from the sensor device, which acts as a
+ * module identifier.
+ */
+static const guid_t intel_sensor_module_guid =
+ GUID_INIT(0x822ace8f, 0x2814, 0x4174,
+ 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee);
+
+/*
+ * dc2f6c4f-045b-4f1d-97b9-882a6860a4be
+ * This _DSM GUID returns a package with n*2 strings, with each set of 2 strings
+ * forming a key, value pair for settings like e.g. "CsiLanes" = "1".
+ */
+static const guid_t atomisp_dsm_guid =
+ GUID_INIT(0xdc2f6c4f, 0x045b, 0x4f1d,
+ 0x97, 0xb9, 0x88, 0x2a, 0x68, 0x60, 0xa4, 0xbe);
+
+/*
+ * Extend this array with ACPI Hardware IDs of sensors known to be working
+ * plus the default number of links + link-frequencies.
+ *
+ * Do not add an entry for a sensor that is not actually supported,
+ * or which have not yet been converted to work without atomisp_gmin
+ * power-management and with v4l2-async probing.
+ */
+static const struct atomisp_csi2_sensor_config supported_sensors[] = {
+ /* GalaxyCore GC0310 */
+ { "INT0310", 1 },
+ /* Omnivision OV2680 */
+ { "OVTI2680", 1 },
+};
+
+/*
+ * gmin_cfg parsing code. This is a cleaned up version of the gmin_cfg parsing
+ * code from atomisp_gmin_platform.c.
+ * Once all sensors are moved to v4l2-async probing atomisp_gmin_platform.c can
+ * be removed and the duplication of this code goes away.
+ */
+struct gmin_cfg_var {
+ const char *acpi_dev_name;
+ const char *key;
+ const char *val;
+};
+
+static struct gmin_cfg_var lenovo_ideapad_miix_310_vars[] = {
+ /* _DSM contains the wrong CsiPort! */
+ { "OVTI2680:01", "CsiPort", "0" },
+ {}
+};
+
+static const struct dmi_system_id gmin_cfg_dmi_overrides[] = {
+ {
+ /* Lenovo Ideapad Miix 310 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "MIIX 310-10"),
+ },
+ .driver_data = lenovo_ideapad_miix_310_vars,
+ },
+ {}
+};
+
+static char *gmin_cfg_get_dsm(struct acpi_device *adev, const char *key)
+{
+ union acpi_object *obj, *key_el, *val_el;
+ char *val = NULL;
+ int i;
+
+ obj = acpi_evaluate_dsm_typed(adev->handle, &atomisp_dsm_guid, 0, 0,
+ NULL, ACPI_TYPE_PACKAGE);
+ if (!obj)
+ return NULL;
+
+ for (i = 0; i < obj->package.count - 1; i += 2) {
+ key_el = &obj->package.elements[i + 0];
+ val_el = &obj->package.elements[i + 1];
+
+ if (key_el->type != ACPI_TYPE_STRING || val_el->type != ACPI_TYPE_STRING)
+ break;
+
+ if (!strcmp(key_el->string.pointer, key)) {
+ val = kstrdup(val_el->string.pointer, GFP_KERNEL);
+ if (!val)
+ break;
+
+ acpi_handle_info(adev->handle, "Using DSM entry %s=%s\n", key, val);
+ break;
+ }
+ }
+
+ ACPI_FREE(obj);
+ return val;
+}
+
+static char *gmin_cfg_get_dmi_override(struct acpi_device *adev, const char *key)
+{
+ const struct dmi_system_id *id;
+ struct gmin_cfg_var *gv;
+
+ id = dmi_first_match(gmin_cfg_dmi_overrides);
+ if (!id)
+ return NULL;
+
+ for (gv = id->driver_data; gv->acpi_dev_name; gv++) {
+ if (strcmp(gv->acpi_dev_name, acpi_dev_name(adev)))
+ continue;
+
+ if (strcmp(key, gv->key))
+ continue;
+
+ acpi_handle_info(adev->handle, "Using DMI entry %s=%s\n", key, gv->val);
+ return kstrdup(gv->val, GFP_KERNEL);
+ }
+
+ return NULL;
+}
+
+static char *gmin_cfg_get(struct acpi_device *adev, const char *key)
+{
+ char *val;
+
+ val = gmin_cfg_get_dmi_override(adev, key);
+ if (val)
+ return val;
+
+ return gmin_cfg_get_dsm(adev, key);
+}
+
+static int gmin_cfg_get_int(struct acpi_device *adev, const char *key, int default_val)
+{
+ char *str_val;
+ long int_val;
+ int ret;
+
+ str_val = gmin_cfg_get(adev, key);
+ if (!str_val)
+ goto out_use_default;
+
+ ret = kstrtoul(str_val, 0, &int_val);
+ kfree(str_val);
+ if (ret)
+ goto out_use_default;
+
+ return int_val;
+
+out_use_default:
+ acpi_handle_info(adev->handle, "Using default %s=%d\n", key, default_val);
+ return default_val;
+}
+
+static int atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(struct acpi_device *adev)
+{
+ /* ACPI_PATH_SEGMENT_LENGTH is guaranteed to be big enough for name + 0 term. */
+ char name[ACPI_PATH_SEGMENT_LENGTH];
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer b_name = { sizeof(name), name };
+ union acpi_object *package, *element;
+ int i, ret = -ENOENT;
+ acpi_handle rhandle;
+ acpi_status status;
+ u8 clock_num;
+
+ status = acpi_evaluate_object_typed(adev->handle, "_PR0", NULL, &buffer, ACPI_TYPE_PACKAGE);
+ if (ACPI_FAILURE(status))
+ return -ENOENT;
+
+ package = buffer.pointer;
+ for (i = 0; i < package->package.count; i++) {
+ element = &package->package.elements[i];
+
+ if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
+ continue;
+
+ rhandle = element->reference.handle;
+ if (!rhandle)
+ continue;
+
+ acpi_get_name(rhandle, ACPI_SINGLE_NAME, &b_name);
+
+ if (str_has_prefix(name, "CLK") && !kstrtou8(&name[3], 10, &clock_num) &&
+ clock_num <= 4) {
+ ret = clock_num;
+ break;
+ }
+ }
+
+ ACPI_FREE(buffer.pointer);
+
+ if (ret < 0)
+ acpi_handle_warn(adev->handle, "Could not find PMC clk in _PR0\n");
+
+ return ret;
+}
+
+static int atomisp_csi2_set_pmc_clk_freq(struct acpi_device *adev, int clock_num)
+{
+ struct clk *clk;
+ char name[14];
+ int ret;
+
+ if (clock_num < 0)
+ return 0;
+
+ snprintf(name, sizeof(name), "pmc_plt_clk_%d", clock_num);
+
+ clk = clk_get(NULL, name);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ acpi_handle_err(adev->handle, "Error getting clk %s:%d\n", name, ret);
+ return ret;
+ }
+
+ /*
+ * The firmware might enable the clock at boot, to change
+ * the rate we must ensure the clock is disabled.
+ */
+ ret = clk_prepare_enable(clk);
+ if (!ret)
+ clk_disable_unprepare(clk);
+ if (!ret)
+ ret = clk_set_rate(clk, PMC_CLK_RATE_19_2MHZ);
+ if (ret)
+ acpi_handle_err(adev->handle, "Error setting clk-rate for %s:%d\n", name, ret);
+
+ clk_put(clk);
+ return ret;
+}
+
+static int atomisp_csi2_get_port(struct acpi_device *adev, int clock_num)
+{
+ int port;
+
+ /*
+ * Compare clock-number to the PMC-clock used for CsiPort 1
+ * in the CHT/BYT reference designs.
+ */
+ if (IS_ISP2401)
+ port = clock_num == 4 ? 1 : 0;
+ else
+ port = clock_num == 0 ? 1 : 0;
+
+ /* Intel DSM or DMI quirk overrides _PR0 CLK derived default */
+ return gmin_cfg_get_int(adev, "CsiPort", port);
+}
+
+/* Note this always returns 1 to continue looping so that res_count is accurate */
+static int atomisp_csi2_handle_acpi_gpio_res(struct acpi_resource *ares, void *_data)
+{
+ struct atomisp_csi2_acpi_gpio_parsing_data *data = _data;
+ struct acpi_resource_gpio *agpio;
+ const char *name;
+ bool active_low;
+ unsigned int i;
+ u32 settings = 0;
+ u16 pin;
+
+ if (!acpi_gpio_get_io_resource(ares, &agpio))
+ return 1; /* Not a GPIO, continue the loop */
+
+ data->res_count++;
+
+ pin = agpio->pin_table[0];
+ for (i = 0; i < data->settings_count; i++) {
+ if (INTEL_GPIO_DSM_PIN(data->settings[i]) == pin) {
+ settings = data->settings[i];
+ break;
+ }
+ }
+
+ if (i == data->settings_count) {
+ acpi_handle_warn(data->adev->handle,
+ "Could not find DSM GPIO settings for pin %u\n", pin);
+ return 1;
+ }
+
+ switch (INTEL_GPIO_DSM_TYPE(settings)) {
+ case 0:
+ name = "reset-gpios";
+ break;
+ case 1:
+ name = "powerdown-gpios";
+ break;
+ default:
+ acpi_handle_warn(data->adev->handle, "Unknown GPIO type 0x%02lx for pin %u\n",
+ INTEL_GPIO_DSM_TYPE(settings), pin);
+ return 1;
+ }
+
+ /*
+ * Both reset and power-down need to be logical false when the sensor
+ * is on (sensor should not be in reset and not be powered-down). So
+ * when the sensor-on-value (which is the physical pin value) is high,
+ * then the signal is active-low.
+ */
+ active_low = INTEL_GPIO_DSM_SENSOR_ON_VAL(settings);
+
+ i = data->map_count;
+ if (i == CSI2_MAX_ACPI_GPIOS)
+ return 1;
+
+ /* res_count is already incremented */
+ data->map->params[i].crs_entry_index = data->res_count - 1;
+ data->map->params[i].active_low = active_low;
+ data->map->mapping[i].name = name;
+ data->map->mapping[i].data = &data->map->params[i];
+ data->map->mapping[i].size = 1;
+ data->map_count++;
+
+ acpi_handle_info(data->adev->handle, "%s crs %d %s pin %u active-%s\n", name,
+ data->res_count - 1, agpio->resource_source.string_ptr,
+ pin, active_low ? "low" : "high");
+
+ return 1;
+}
+
+/*
+ * Helper function to create an ACPI GPIO lookup table for sensor reset and
+ * powerdown signals on Intel Bay Trail (BYT) and Cherry Trail (CHT) devices,
+ * including setting the correct polarity for the GPIO.
+ *
+ * This uses the "79234640-9e10-4fea-a5c1-b5aa8b19756f" DSM method directly
+ * on the sensor device's ACPI node. This is different from later Intel
+ * hardware which has a separate INT3472 acpi_device with this info.
+ *
+ * This function must be called before creating the sw-noded describing
+ * the fwnode graph endpoint. And sensor drivers used on these devices
+ * must return -EPROBE_DEFER when there is no endpoint description yet.
+ * Together this guarantees that the GPIO lookups are in place before
+ * the sensor driver tries to get GPIOs with gpiod_get().
+ *
+ * Note this code uses the same DSM GUID as the int3472_gpio_guid in
+ * the INT3472 discrete.c code and there is some overlap, but there are
+ * enough differences that it is difficult to share the code.
+ */
+static int atomisp_csi2_add_gpio_mappings(struct atomisp_csi2_sensor *sensor,
+ struct acpi_device *adev)
+{
+ struct atomisp_csi2_acpi_gpio_parsing_data data = { };
+ LIST_HEAD(resource_list);
+ union acpi_object *obj;
+ unsigned int i, j;
+ int ret;
+
+ obj = acpi_evaluate_dsm_typed(adev->handle, &intel_sensor_module_guid,
+ 0x00, 1, NULL, ACPI_TYPE_STRING);
+ if (obj) {
+ acpi_handle_info(adev->handle, "Sensor module id: '%s'\n", obj->string.pointer);
+ ACPI_FREE(obj);
+ }
+
+ /*
+ * First get the GPIO-settings count and then get count GPIO-settings
+ * values. Note the order of these may differ from the order in which
+ * the GPIOs are listed on the ACPI resources! So we first store them all
+ * and then enumerate the ACPI resources and match them up by pin number.
+ */
+ obj = acpi_evaluate_dsm_typed(adev->handle,
+ &intel_sensor_gpio_info_guid, 0x00, 1,
+ NULL, ACPI_TYPE_INTEGER);
+ if (!obj) {
+ acpi_handle_err(adev->handle, "No _DSM entry for GPIO pin count\n");
+ return -EIO;
+ }
+
+ data.settings_count = obj->integer.value;
+ ACPI_FREE(obj);
+
+ if (data.settings_count > CSI2_MAX_ACPI_GPIOS) {
+ acpi_handle_err(adev->handle, "Too many GPIOs %u > %u\n", data.settings_count, CSI2_MAX_ACPI_GPIOS);
+ return -EOVERFLOW;
+ }
+
+ for (i = 0; i < data.settings_count; i++) {
+ /*
+ * i + 2 because the index of this _DSM function is 1-based
+ * and the first function is just a count.
+ */
+ obj = acpi_evaluate_dsm_typed(adev->handle,
+ &intel_sensor_gpio_info_guid,
+ 0x00, i + 2,
+ NULL, ACPI_TYPE_INTEGER);
+ if (!obj) {
+ acpi_handle_err(adev->handle, "No _DSM entry for pin %u\n", i);
+ return -EIO;
+ }
+
+ data.settings[i] = obj->integer.value;
+ ACPI_FREE(obj);
+ }
+
+ /* Since we match up by pin-number the pin-numbers must be unique */
+ for (i = 0; i < data.settings_count; i++) {
+ for (j = i + 1; j < data.settings_count; j++) {
+ if (INTEL_GPIO_DSM_PIN(data.settings[i]) !=
+ INTEL_GPIO_DSM_PIN(data.settings[j]))
+ continue;
+
+ acpi_handle_err(adev->handle, "Duplicate pin number %lu\n",
+ INTEL_GPIO_DSM_PIN(data.settings[i]));
+ return -EIO;
+ }
+ }
+
+ /* Now parse the ACPI resources and build the lookup table */
+ data.adev = adev;
+ data.map = &sensor->gpio_map;
+ ret = acpi_dev_get_resources(adev, &resource_list,
+ atomisp_csi2_handle_acpi_gpio_res, &data);
+ if (ret < 0)
+ return ret;
+
+ acpi_dev_free_resource_list(&resource_list);
+
+ if (data.map_count != data.settings_count ||
+ data.res_count != data.settings_count)
+ acpi_handle_warn(adev->handle, "ACPI GPIO resources vs DSM GPIO-info count mismatch (dsm: %d res: %d map %d\n",
+ data.settings_count, data.res_count, data.map_count);
+
+ ret = acpi_dev_add_driver_gpios(adev, data.map->mapping);
+ if (ret)
+ acpi_handle_err(adev->handle, "Error adding driver GPIOs: %d\n", ret);
+
+ return ret;
+}
+
+static const struct atomisp_csi2_property_names prop_names = {
+ .clock_frequency = "clock-frequency",
+ .rotation = "rotation",
+ .bus_type = "bus-type",
+ .data_lanes = "data-lanes",
+ .remote_endpoint = "remote-endpoint",
+ .link_frequencies = "link-frequencies",
+};
+
+static void atomisp_csi2_create_fwnode_properties(struct atomisp_csi2_sensor *sensor,
+ struct atomisp_csi2_bridge *bridge,
+ const struct atomisp_csi2_sensor_config *cfg)
+{
+ sensor->prop_names = prop_names;
+
+ sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CSI2_ENDPOINT]);
+ sensor->remote_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_SENSOR_ENDPOINT]);
+
+ sensor->dev_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.clock_frequency,
+ PMC_CLK_RATE_19_2MHZ);
+ sensor->dev_properties[1] = PROPERTY_ENTRY_U32(sensor->prop_names.rotation, 0);
+
+ sensor->ep_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.bus_type,
+ V4L2_FWNODE_BUS_TYPE_CSI2_DPHY);
+ sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes,
+ bridge->data_lanes,
+ sensor->lanes);
+ sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint,
+ sensor->local_ref);
+ if (cfg->nr_link_freqs > 0)
+ sensor->ep_properties[3] =
+ PROPERTY_ENTRY_U64_ARRAY_LEN(sensor->prop_names.link_frequencies,
+ cfg->link_freqs, cfg->nr_link_freqs);
+
+ sensor->csi2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes,
+ bridge->data_lanes,
+ sensor->lanes);
+ sensor->csi2_properties[1] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint,
+ sensor->remote_ref);
+}
+
+static void atomisp_csi2_init_swnode_names(struct atomisp_csi2_sensor *sensor)
+{
+ snprintf(sensor->node_names.remote_port,
+ sizeof(sensor->node_names.remote_port),
+ SWNODE_GRAPH_PORT_NAME_FMT, sensor->port);
+ snprintf(sensor->node_names.port,
+ sizeof(sensor->node_names.port),
+ SWNODE_GRAPH_PORT_NAME_FMT, 0); /* Always port 0 */
+ snprintf(sensor->node_names.endpoint,
+ sizeof(sensor->node_names.endpoint),
+ SWNODE_GRAPH_ENDPOINT_NAME_FMT, 0); /* And endpoint 0 */
+}
+
+static void atomisp_csi2_init_swnode_group(struct atomisp_csi2_sensor *sensor)
+{
+ struct software_node *nodes = sensor->swnodes;
+
+ sensor->group[SWNODE_SENSOR] = &nodes[SWNODE_SENSOR];
+ sensor->group[SWNODE_SENSOR_PORT] = &nodes[SWNODE_SENSOR_PORT];
+ sensor->group[SWNODE_SENSOR_ENDPOINT] = &nodes[SWNODE_SENSOR_ENDPOINT];
+ sensor->group[SWNODE_CSI2_PORT] = &nodes[SWNODE_CSI2_PORT];
+ sensor->group[SWNODE_CSI2_ENDPOINT] = &nodes[SWNODE_CSI2_ENDPOINT];
+}
+
+static void atomisp_csi2_create_connection_swnodes(struct atomisp_csi2_bridge *bridge,
+ struct atomisp_csi2_sensor *sensor)
+{
+ struct software_node *nodes = sensor->swnodes;
+
+ atomisp_csi2_init_swnode_names(sensor);
+
+ nodes[SWNODE_SENSOR] = NODE_SENSOR(sensor->name,
+ sensor->dev_properties);
+ nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port,
+ &nodes[SWNODE_SENSOR]);
+ nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint,
+ &nodes[SWNODE_SENSOR_PORT],
+ sensor->ep_properties);
+ nodes[SWNODE_CSI2_PORT] = NODE_PORT(sensor->node_names.remote_port,
+ &bridge->csi2_node);
+ nodes[SWNODE_CSI2_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint,
+ &nodes[SWNODE_CSI2_PORT],
+ sensor->csi2_properties);
+
+ atomisp_csi2_init_swnode_group(sensor);
+}
+
+static void atomisp_csi2_unregister_sensors(struct atomisp_csi2_bridge *bridge)
+{
+ struct atomisp_csi2_sensor *sensor;
+ unsigned int i;
+
+ for (i = 0; i < bridge->n_sensors; i++) {
+ sensor = &bridge->sensors[i];
+ software_node_unregister_node_group(sensor->group);
+ acpi_dev_remove_driver_gpios(sensor->adev);
+ acpi_dev_put(sensor->adev);
+ }
+}
+
+static int atomisp_csi2_connect_sensor(const struct atomisp_csi2_sensor_config *cfg,
+ struct atomisp_csi2_bridge *bridge,
+ struct atomisp_device *isp)
+{
+ struct fwnode_handle *fwnode, *primary;
+ struct atomisp_csi2_sensor *sensor;
+ struct acpi_device *adev;
+ int ret, clock_num;
+
+ for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) {
+ if (!adev->status.enabled)
+ continue;
+
+ if (bridge->n_sensors >= ATOMISP_CAMERA_NR_PORTS) {
+ dev_err(isp->dev, "Exceeded available CSI2 ports\n");
+ ret = -EOVERFLOW;
+ goto err_put_adev;
+ }
+
+ sensor = &bridge->sensors[bridge->n_sensors];
+
+ /*
+ * ACPI takes care of turning the PMC clock on and off, but on BYT
+ * the clock defaults to 25 MHz instead of the expected 19.2 MHz.
+ * Get the PMC-clock number from ACPI _PR0 method and set it to 19.2 MHz.
+ * The PMC-clock number is also used to determine the default CSI port.
+ */
+ clock_num = atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(adev);
+
+ ret = atomisp_csi2_set_pmc_clk_freq(adev, clock_num);
+ if (ret)
+ goto err_put_adev;
+
+ sensor->port = atomisp_csi2_get_port(adev, clock_num);
+ if (sensor->port >= ATOMISP_CAMERA_NR_PORTS) {
+ acpi_handle_err(adev->handle, "Invalid port: %d\n", sensor->port);
+ ret = -EINVAL;
+ goto err_put_adev;
+ }
+
+ sensor->lanes = gmin_cfg_get_int(adev, "CsiLanes", cfg->lanes);
+ if (sensor->lanes > CSI2_MAX_LANES) {
+ acpi_handle_err(adev->handle, "Invalid number of lanes: %d\n", sensor->lanes);
+ ret = -EINVAL;
+ goto err_put_adev;
+ }
+
+ ret = atomisp_csi2_add_gpio_mappings(sensor, adev);
+ if (ret)
+ goto err_put_adev;
+
+ snprintf(sensor->name, sizeof(sensor->name), "%s-%u",
+ cfg->hid, sensor->port);
+
+ atomisp_csi2_create_fwnode_properties(sensor, bridge, cfg);
+ atomisp_csi2_create_connection_swnodes(bridge, sensor);
+
+ ret = software_node_register_node_group(sensor->group);
+ if (ret)
+ goto err_remove_mappings;
+
+ fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR]);
+ if (!fwnode) {
+ ret = -ENODEV;
+ goto err_free_swnodes;
+ }
+
+ sensor->adev = acpi_dev_get(adev);
+
+ primary = acpi_fwnode_handle(adev);
+ primary->secondary = fwnode;
+
+ bridge->n_sensors++;
+ }
+
+ return 0;
+
+err_free_swnodes:
+ software_node_unregister_node_group(sensor->group);
+err_remove_mappings:
+ acpi_dev_remove_driver_gpios(adev);
+err_put_adev:
+ acpi_dev_put(adev);
+ return ret;
+}
+
+static int atomisp_csi2_connect_sensors(struct atomisp_csi2_bridge *bridge,
+ struct atomisp_device *isp)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(supported_sensors); i++) {
+ const struct atomisp_csi2_sensor_config *cfg = &supported_sensors[i];
+
+ ret = atomisp_csi2_connect_sensor(cfg, bridge, isp);
+ if (ret)
+ goto err_unregister_sensors;
+ }
+
+ return 0;
+
+err_unregister_sensors:
+ atomisp_csi2_unregister_sensors(bridge);
+ return ret;
+}
+
+int atomisp_csi2_bridge_init(struct atomisp_device *isp)
+{
+ struct atomisp_csi2_bridge *bridge;
+ struct device *dev = isp->dev;
+ struct fwnode_handle *fwnode;
+ int i, ret;
+
+ /*
+ * This function is intended to run only once and then leave
+ * the created nodes attached even after a rmmod, therefore:
+ * 1. The bridge memory is leaked deliberately on success
+ * 2. If a secondary fwnode is already set exit early.
+ */
+ fwnode = dev_fwnode(dev);
+ if (fwnode && fwnode->secondary)
+ return 0;
+
+ bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
+ if (!bridge)
+ return -ENOMEM;
+
+ strscpy(bridge->csi2_node_name, "atomisp-csi2", sizeof(bridge->csi2_node_name));
+ bridge->csi2_node.name = bridge->csi2_node_name;
+
+ ret = software_node_register(&bridge->csi2_node);
+ if (ret < 0) {
+ dev_err(dev, "Failed to register the CSI2 HID node\n");
+ goto err_free_bridge;
+ }
+
+ /*
+ * Map the lane arrangement, which is fixed for the ISP2 (meaning we
+ * only need one, rather than one per sensor). We include it as a
+ * member of the bridge struct rather than a global variable so
+ * that it survives if the module is unloaded along with the rest of
+ * the struct.
+ */
+ for (i = 0; i < CSI2_MAX_LANES; i++)
+ bridge->data_lanes[i] = i + 1;
+
+ ret = atomisp_csi2_connect_sensors(bridge, isp);
+ if (ret || bridge->n_sensors == 0)
+ goto err_unregister_csi2;
+
+ fwnode = software_node_fwnode(&bridge->csi2_node);
+ if (!fwnode) {
+ dev_err(dev, "Error getting fwnode from csi2 software_node\n");
+ ret = -ENODEV;
+ goto err_unregister_sensors;
+ }
+
+ set_secondary_fwnode(dev, fwnode);
+
+ return 0;
+
+err_unregister_sensors:
+ atomisp_csi2_unregister_sensors(bridge);
+err_unregister_csi2:
+ software_node_unregister(&bridge->csi2_node);
+err_free_bridge:
+ kfree(bridge);
+
+ return ret;
+}
+
+/******* V4L2 sub-device asynchronous registration callbacks***********/
+
+struct sensor_async_subdev {
+ struct v4l2_async_subdev asd;
+ int port;
+};
+
+#define to_sensor_asd(a) container_of(a, struct sensor_async_subdev, asd)
+#define notifier_to_atomisp(n) container_of(n, struct atomisp_device, notifier)
+
+/* .bound() notifier callback when a match is found */
+static int atomisp_notifier_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+ struct atomisp_device *isp = notifier_to_atomisp(notifier);
+ struct sensor_async_subdev *s_asd = to_sensor_asd(asd);
+
+ if (s_asd->port >= ATOMISP_CAMERA_NR_PORTS) {
+ dev_err(isp->dev, "port %d not supported\n", s_asd->port);
+ return -EINVAL;
+ }
+
+ if (isp->sensor_subdevs[s_asd->port]) {
+ dev_err(isp->dev, "port %d already has a sensor attached\n", s_asd->port);
+ return -EBUSY;
+ }
+
+ isp->sensor_subdevs[s_asd->port] = sd;
+ return 0;
+}
+
+/* The .unbind callback */
+static void atomisp_notifier_unbind(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+ struct atomisp_device *isp = notifier_to_atomisp(notifier);
+ struct sensor_async_subdev *s_asd = to_sensor_asd(asd);
+
+ isp->sensor_subdevs[s_asd->port] = NULL;
+}
+
+/* .complete() is called after all subdevices have been located */
+static int atomisp_notifier_complete(struct v4l2_async_notifier *notifier)
+{
+ struct atomisp_device *isp = notifier_to_atomisp(notifier);
+
+ return atomisp_register_device_nodes(isp);
+}
+
+static const struct v4l2_async_notifier_operations atomisp_async_ops = {
+ .bound = atomisp_notifier_bound,
+ .unbind = atomisp_notifier_unbind,
+ .complete = atomisp_notifier_complete,
+};
+
+int atomisp_csi2_bridge_parse_firmware(struct atomisp_device *isp)
+{
+ int i, mipi_port, ret;
+
+ v4l2_async_nf_init(&isp->notifier);
+ isp->notifier.ops = &atomisp_async_ops;
+
+ for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
+ struct v4l2_fwnode_endpoint vep = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY,
+ };
+ struct sensor_async_subdev *s_asd;
+ struct fwnode_handle *ep;
+
+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(isp->dev), i, 0,
+ FWNODE_GRAPH_ENDPOINT_NEXT);
+ if (!ep)
+ continue;
+
+ ret = v4l2_fwnode_endpoint_parse(ep, &vep);
+ if (ret)
+ goto err_parse;
+
+ if (vep.base.port >= ATOMISP_CAMERA_NR_PORTS) {
+ dev_err(isp->dev, "port %d not supported\n", vep.base.port);
+ ret = -EINVAL;
+ goto err_parse;
+ }
+
+ mipi_port = atomisp_port_to_mipi_port(isp, vep.base.port);
+ isp->sensor_lanes[mipi_port] = vep.bus.mipi_csi2.num_data_lanes;
+
+ s_asd = v4l2_async_nf_add_fwnode_remote(&isp->notifier, ep,
+ struct sensor_async_subdev);
+ if (IS_ERR(s_asd)) {
+ ret = PTR_ERR(s_asd);
+ goto err_parse;
+ }
+
+ s_asd->port = vep.base.port;
+
+ fwnode_handle_put(ep);
+ continue;
+
+err_parse:
+ fwnode_handle_put(ep);
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/staging/media/atomisp/pci/atomisp_drvfs.c b/drivers/staging/media/atomisp/pci/atomisp_drvfs.c
index 3ddc935ec01d..1df534bf54d3 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_drvfs.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_drvfs.c
@@ -69,7 +69,7 @@ static inline int iunit_dump_dbgopt(struct atomisp_device *isp,
}
if (opt & OPTION_BIN_RUN) {
- if (atomisp_streaming_count(isp)) {
+ if (isp->asd.streaming) {
atomisp_css_dump_sp_raw_copy_linecount(true);
atomisp_css_debug_dump_isp_binary();
} else {
diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c
index fa362c8a37e8..54466d2f323a 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_fops.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c
@@ -47,7 +47,6 @@ static int atomisp_queue_setup(struct vb2_queue *vq,
unsigned int sizes[], struct device *alloc_devs[])
{
struct atomisp_video_pipe *pipe = container_of(vq, struct atomisp_video_pipe, vb_queue);
- u16 source_pad = atomisp_subdev_source_pad(&pipe->vdev);
int ret;
mutex_lock(&pipe->asd->isp->mutex); /* for get_css_frame_info() / set_fmt() */
@@ -56,7 +55,7 @@ static int atomisp_queue_setup(struct vb2_queue *vq,
* When VIDIOC_S_FMT has not been called before VIDIOC_REQBUFS, then
* this will fail. Call atomisp_set_fmt() ourselves and try again.
*/
- ret = atomisp_get_css_frame_info(pipe->asd, source_pad, &pipe->frame_info);
+ ret = atomisp_get_css_frame_info(pipe->asd, &pipe->frame_info);
if (ret) {
struct v4l2_format f = {
.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420,
@@ -68,7 +67,7 @@ static int atomisp_queue_setup(struct vb2_queue *vq,
if (ret)
goto out;
- ret = atomisp_get_css_frame_info(pipe->asd, source_pad, &pipe->frame_info);
+ ret = atomisp_get_css_frame_info(pipe->asd, &pipe->frame_info);
if (ret)
goto out;
}
@@ -342,119 +341,29 @@ static int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd,
return 0;
}
-static int atomisp_get_css_buf_type(struct atomisp_sub_device *asd,
- enum ia_css_pipe_id pipe_id,
- uint16_t source_pad)
-{
- if (pipe_id == IA_CSS_PIPE_ID_COPY ||
- source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE ||
- source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO ||
- (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW &&
- asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO))
- return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
- else
- return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
-}
-
/* queue all available buffers to css */
int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd)
{
- enum ia_css_buffer_type buf_type;
- enum ia_css_pipe_id css_capture_pipe_id = IA_CSS_PIPE_ID_NUM;
- enum ia_css_pipe_id css_preview_pipe_id = IA_CSS_PIPE_ID_NUM;
- enum ia_css_pipe_id css_video_pipe_id = IA_CSS_PIPE_ID_NUM;
- enum atomisp_input_stream_id input_stream_id;
- struct atomisp_video_pipe *capture_pipe = NULL;
- struct atomisp_video_pipe *vf_pipe = NULL;
- struct atomisp_video_pipe *preview_pipe = NULL;
- struct atomisp_video_pipe *video_pipe = NULL;
- bool raw_mode = atomisp_is_mbuscode_raw(
- asd->fmt[asd->capture_pad].fmt.code);
-
- if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
- video_pipe = &asd->video_out_video_capture;
- css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO;
+ enum ia_css_pipe_id pipe_id;
+
+ if (asd->copy_mode) {
+ pipe_id = IA_CSS_PIPE_ID_COPY;
+ } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
+ pipe_id = IA_CSS_PIPE_ID_VIDEO;
} else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
- preview_pipe = &asd->video_out_capture;
- css_preview_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
+ pipe_id = IA_CSS_PIPE_ID_CAPTURE;
} else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
- video_pipe = &asd->video_out_video_capture;
- preview_pipe = &asd->video_out_preview;
- css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO;
- css_preview_pipe_id = IA_CSS_PIPE_ID_VIDEO;
+ pipe_id = IA_CSS_PIPE_ID_VIDEO;
} else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
- preview_pipe = &asd->video_out_preview;
- css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW;
+ pipe_id = IA_CSS_PIPE_ID_PREVIEW;
} else {
/* ATOMISP_RUN_MODE_STILL_CAPTURE */
- capture_pipe = &asd->video_out_capture;
- if (!raw_mode)
- vf_pipe = &asd->video_out_vf;
- css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
- }
-
- if (IS_ISP2401 && asd->copy_mode) {
- css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
- css_preview_pipe_id = IA_CSS_PIPE_ID_COPY;
- css_video_pipe_id = IA_CSS_PIPE_ID_COPY;
- }
-
- if (capture_pipe) {
- buf_type = atomisp_get_css_buf_type(
- asd, css_capture_pipe_id,
- atomisp_subdev_source_pad(&capture_pipe->vdev));
- input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
-
- atomisp_q_video_buffers_to_css(asd, capture_pipe,
- input_stream_id,
- buf_type, css_capture_pipe_id);
- }
-
- if (vf_pipe) {
- buf_type = atomisp_get_css_buf_type(
- asd, css_capture_pipe_id,
- atomisp_subdev_source_pad(&vf_pipe->vdev));
- if (asd->stream_env[ATOMISP_INPUT_STREAM_POSTVIEW].stream)
- input_stream_id = ATOMISP_INPUT_STREAM_POSTVIEW;
- else
- input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
-
- atomisp_q_video_buffers_to_css(asd, vf_pipe,
- input_stream_id,
- buf_type, css_capture_pipe_id);
- }
-
- if (preview_pipe) {
- buf_type = atomisp_get_css_buf_type(
- asd, css_preview_pipe_id,
- atomisp_subdev_source_pad(&preview_pipe->vdev));
-
- if (css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
- input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
- else if (asd->stream_env[ATOMISP_INPUT_STREAM_PREVIEW].stream)
- input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW;
- else
- input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
-
- atomisp_q_video_buffers_to_css(asd, preview_pipe,
- input_stream_id,
- buf_type, css_preview_pipe_id);
- }
-
- if (video_pipe) {
- buf_type = atomisp_get_css_buf_type(
- asd, css_video_pipe_id,
- atomisp_subdev_source_pad(&video_pipe->vdev));
- if (asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO].stream)
- input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
- else
- input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
-
- atomisp_q_video_buffers_to_css(asd, video_pipe,
- input_stream_id,
- buf_type, css_video_pipe_id);
+ pipe_id = IA_CSS_PIPE_ID_CAPTURE;
}
+ atomisp_q_video_buffers_to_css(asd, &asd->video_out,
+ ATOMISP_INPUT_STREAM_GENERAL,
+ IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, pipe_id);
return 0;
}
@@ -493,9 +402,8 @@ static void atomisp_buf_queue(struct vb2_buffer *vb)
* is put to waiting list until previous per-frame parameter buffers
* get enqueued.
*/
- if (!atomisp_is_vf_pipe(pipe) &&
- (pipe->frame_request_config_id[vb->index] ||
- !list_empty(&pipe->buffers_waiting_for_param)))
+ if (pipe->frame_request_config_id[vb->index] ||
+ !list_empty(&pipe->buffers_waiting_for_param))
list_add_tail(&frame->queue, &pipe->buffers_waiting_for_param);
else
list_add_tail(&frame->queue, &pipe->activeq);
@@ -503,7 +411,7 @@ static void atomisp_buf_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
/* TODO: do this better, not best way to queue to css */
- if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) {
+ if (asd->streaming) {
if (!list_empty(&pipe->buffers_waiting_for_param))
atomisp_handle_parameter_and_buffer(pipe);
else
@@ -539,9 +447,7 @@ static void atomisp_dev_init_struct(struct atomisp_device *isp)
{
unsigned int i;
- isp->need_gfx_throttle = true;
isp->isp_fatal_error = false;
- isp->mipi_frame_size = 0;
for (i = 0; i < isp->input_cnt; i++)
isp->inputs[i].asd = NULL;
@@ -568,10 +474,6 @@ static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd)
/* s3a grid not enabled for any pipe */
asd->params.s3a_enabled_pipe = IA_CSS_PIPE_ID_NUM;
- /* Add for channel */
- asd->input_curr = 0;
-
- asd->mipi_frame_size = 0;
asd->copy_mode = false;
asd->stream_prepared = false;
@@ -584,19 +486,6 @@ static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd)
/*
* file operation functions
*/
-static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd)
-{
- return asd->video_out_preview.users +
- asd->video_out_vf.users +
- asd->video_out_capture.users +
- asd->video_out_video_capture.users;
-}
-
-unsigned int atomisp_dev_users(struct atomisp_device *isp)
-{
- return atomisp_subdev_users(&isp->asd);
-}
-
static int atomisp_open(struct file *file)
{
struct video_device *vdev = video_devdata(file);
@@ -613,8 +502,6 @@ static int atomisp_open(struct file *file)
mutex_lock(&isp->mutex);
- asd->subdev.devnode = vdev;
-
if (!isp->input_cnt) {
dev_err(isp->dev, "no camera attached\n");
ret = -EINVAL;
@@ -630,11 +517,6 @@ static int atomisp_open(struct file *file)
return -EBUSY;
}
- if (atomisp_dev_users(isp)) {
- dev_dbg(isp->dev, "skip init isp in open\n");
- goto init_subdev;
- }
-
/* runtime power management, turn on ISP */
ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev);
if (ret < 0) {
@@ -650,19 +532,12 @@ static int atomisp_open(struct file *file)
goto css_error;
}
-init_subdev:
- if (atomisp_subdev_users(asd))
- goto done;
-
atomisp_subdev_init_struct(asd);
/* Ensure that a mode is set */
- v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode);
+ v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_PREVIEW);
-done:
pipe->users++;
mutex_unlock(&isp->mutex);
-
-
return 0;
css_error:
@@ -681,23 +556,18 @@ static int atomisp_release(struct file *file)
struct atomisp_sub_device *asd = pipe->asd;
struct v4l2_subdev_fh fh;
struct v4l2_rect clear_compose = {0};
- unsigned long flags;
int ret;
v4l2_fh_init(&fh.vfh, vdev);
dev_dbg(isp->dev, "release device %s\n", vdev->name);
- asd->subdev.devnode = vdev;
-
/* Note file must not be used after this! */
vb2_fop_release(file);
mutex_lock(&isp->mutex);
pipe->users--;
- if (pipe->users)
- goto done;
/*
* A little trick here:
@@ -714,9 +584,6 @@ static int atomisp_release(struct file *file)
ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
}
- if (atomisp_subdev_users(asd))
- goto done;
-
atomisp_css_free_stat_buffers(asd);
atomisp_free_internal_buffers(asd);
@@ -730,14 +597,7 @@ static int atomisp_release(struct file *file)
isp->inputs[asd->input_curr].asd = NULL;
}
- spin_lock_irqsave(&isp->lock, flags);
- asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
- spin_unlock_irqrestore(&isp->lock, flags);
-
- if (atomisp_dev_users(isp))
- goto done;
-
- atomisp_destroy_pipes_stream_force(asd);
+ atomisp_destroy_pipes_stream(asd);
ret = v4l2_subdev_call(isp->flash, core, s_power, 0);
if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD)
@@ -746,10 +606,9 @@ static int atomisp_release(struct file *file)
if (pm_runtime_put_sync(vdev->v4l2_dev->dev) < 0)
dev_err(isp->dev, "Failed to power off device\n");
-done:
atomisp_subdev_set_selection(&asd->subdev, fh.state,
V4L2_SUBDEV_FORMAT_ACTIVE,
- atomisp_subdev_source_pad(vdev),
+ ATOMISP_SUBDEV_PAD_SOURCE,
V4L2_SEL_TGT_COMPOSE, 0,
&clear_compose);
mutex_unlock(&isp->mutex);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.h b/drivers/staging/media/atomisp/pci/atomisp_fops.h
index 883c1851c1c9..ad1cb1ac8aa4 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_fops.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_fops.h
@@ -22,9 +22,6 @@
#define __ATOMISP_FOPS_H__
#include "atomisp_subdev.h"
-unsigned int atomisp_dev_users(struct atomisp_device *isp);
-unsigned int atomisp_sub_dev_users(struct atomisp_sub_device *asd);
-
/*
* Memory help functions for image frame and private parameters
*/
diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
index c718a74ea70a..139ad7ad1dcf 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
@@ -189,6 +189,7 @@ int atomisp_register_i2c_module(struct v4l2_subdev *subdev,
pdata.subdevs[i].type = type;
pdata.subdevs[i].port = gs->csi_port;
+ pdata.subdevs[i].lanes = gs->csi_lanes;
pdata.subdevs[i].subdev = subdev;
return 0;
}
@@ -1150,6 +1151,7 @@ int atomisp_register_sensor_no_gmin(struct v4l2_subdev *subdev, u32 lanes,
pdata.subdevs[i].type = RAW_CAMERA;
pdata.subdevs[i].port = port;
+ pdata.subdevs[i].lanes = lanes;
pdata.subdevs[i].subdev = subdev;
return 0;
}
@@ -1357,7 +1359,7 @@ static int gmin_get_config_dsm_var(struct device *dev,
dev_info(dev, "found _DSM entry for '%s': %s\n", var,
cur->string.pointer);
strscpy(out, cur->string.pointer, *out_len);
- *out_len = strlen(cur->string.pointer);
+ *out_len = strlen(out);
ACPI_FREE(obj);
return 0;
@@ -1427,8 +1429,8 @@ static int gmin_get_config_var(struct device *maindev,
int gmin_get_var_int(struct device *dev, bool is_gmin, const char *var, int def)
{
- char val[CFG_VAR_NAME_MAX];
- size_t len = sizeof(val);
+ char val[CFG_VAR_NAME_MAX + 1];
+ size_t len = CFG_VAR_NAME_MAX;
long result;
int ret;
@@ -1458,243 +1460,3 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0f38, isp_pm_cap_fixup);
MODULE_DESCRIPTION("Ancillary routines for binding ACPI devices");
MODULE_LICENSE("GPL");
-
-/*
- * The below helper functions don't really belong here and should eventually be
- * moved to some place under drivers/media/v4l2-core.
- */
-#include <linux/platform_data/x86/soc.h>
-
-/*
- * 79234640-9e10-4fea-a5c1-b5aa8b19756f
- * This _DSM GUID returns information about the GPIO lines mapped to a sensor.
- * Function number 1 returns a count of the GPIO lines that are mapped.
- * Subsequent functions return 32 bit ints encoding information about the GPIO.
- */
-static const guid_t intel_sensor_gpio_info_guid =
- GUID_INIT(0x79234640, 0x9e10, 0x4fea,
- 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f);
-
-/*
- * 822ace8f-2814-4174-a56b-5f029fe079ee
- * This _DSM GUID returns a string from the sensor device, which acts as a
- * module identifier.
- */
-static const guid_t intel_sensor_module_guid =
- GUID_INIT(0x822ace8f, 0x2814, 0x4174,
- 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee);
-
-#define INTEL_DSM_TYPE_SHIFT 0
-#define INTEL_DSM_TYPE_MASK GENMASK(7, 0)
-#define INTEL_DSM_PIN_SHIFT 8
-#define INTEL_DSM_PIN_MASK GENMASK(15, 8)
-#define INTEL_DSM_SENSOR_ON_VAL_SHIFT 24
-#define INTEL_DSM_SENSOR_ON_VAL_MASK GENMASK(31, 24)
-
-#define INTEL_DSM_TYPE(x) \
- (((x) & INTEL_DSM_TYPE_MASK) >> INTEL_DSM_TYPE_SHIFT)
-#define INTEL_DSM_PIN(x) \
- (((x) & INTEL_DSM_PIN_MASK) >> INTEL_DSM_PIN_SHIFT)
-#define INTEL_DSM_SENSOR_ON_VAL(x) \
- (((x) & INTEL_DSM_SENSOR_ON_VAL_MASK) >> INTEL_DSM_SENSOR_ON_VAL_SHIFT)
-
-#define V4L2_SENSOR_MAX_ACPI_GPIOS 2u
-
-struct v4l2_acpi_gpio_map {
- struct acpi_gpio_params params[V4L2_SENSOR_MAX_ACPI_GPIOS];
- struct acpi_gpio_mapping mapping[V4L2_SENSOR_MAX_ACPI_GPIOS + 1];
-};
-
-struct v4l2_acpi_gpio_parsing_data {
- struct device *dev;
- u32 settings[V4L2_SENSOR_MAX_ACPI_GPIOS];
- unsigned int settings_count;
- unsigned int res_count;
- unsigned int map_count;
- struct v4l2_acpi_gpio_map *map;
-};
-
-/* Note this always returns 1 to continue looping so that res_count is accurate */
-static int v4l2_acpi_handle_gpio_res(struct acpi_resource *ares, void *_data)
-{
- struct v4l2_acpi_gpio_parsing_data *data = _data;
- struct acpi_resource_gpio *agpio;
- const char *name;
- bool active_low;
- unsigned int i;
- u32 settings;
- u8 pin;
-
- if (!acpi_gpio_get_io_resource(ares, &agpio))
- return 1; /* Not a GPIO, continue the loop */
-
- data->res_count++;
-
- pin = agpio->pin_table[0];
- for (i = 0; i < data->settings_count; i++) {
- if (INTEL_DSM_PIN(data->settings[i]) == pin) {
- settings = data->settings[i];
- break;
- }
- }
-
- if (i == data->settings_count) {
- dev_warn(data->dev, "Could not find DSM GPIO settings for pin %d\n", pin);
- return 1;
- }
-
- switch (INTEL_DSM_TYPE(settings)) {
- case 0:
- name = "reset-gpios";
- break;
- case 1:
- name = "powerdown-gpios";
- break;
- default:
- dev_warn(data->dev, "Unknown GPIO type 0x%02lx for pin %d\n",
- INTEL_DSM_TYPE(settings), pin);
- return 1;
- }
-
- /*
- * Both reset and power-down need to be logical false when the sensor
- * is on (sensor should not be in reset and not be powered-down). So
- * when the sensor-on-value (which is the physical pin value) is high,
- * then the signal is active-low.
- */
- active_low = INTEL_DSM_SENSOR_ON_VAL(settings) ? true : false;
-
- i = data->map_count;
- if (i == V4L2_SENSOR_MAX_ACPI_GPIOS)
- return 1;
-
- /* res_count is already incremented */
- data->map->params[i].crs_entry_index = data->res_count - 1;
- data->map->params[i].active_low = active_low;
- data->map->mapping[i].name = name;
- data->map->mapping[i].data = &data->map->params[i];
- data->map->mapping[i].size = 1;
- data->map_count++;
-
- dev_info(data->dev, "%s crs %d %s pin %d active-%s\n", name,
- data->res_count - 1, agpio->resource_source.string_ptr,
- pin, active_low ? "low" : "high");
-
- return 1;
-}
-
-/*
- * Helper function to create an ACPI GPIO lookup table for sensor reset and
- * powerdown signals on Intel Bay Trail (BYT) and Cherry Trail (CHT) devices,
- * including setting the correct polarity for the GPIO.
- *
- * This uses the "79234640-9e10-4fea-a5c1-b5aa8b19756f" DSM method directly
- * on the sensor device's ACPI node. This is different from later Intel
- * hardware which has a separate INT3472 with this info. Since there is
- * no separate firmware-node to which we can bind to register the GPIO lookups
- * this unfortunately means that all sensor drivers which may be used on
- * BYT or CHT hw need to call this function. This also means that this function
- * may only fail when it is actually called on BYT/CHT hw. In all other cases
- * it must always succeed.
- *
- * Note this code uses the same DSM GUID as the INT3472 discrete.c code
- * and there is some overlap, but there are enough differences that it is
- * difficult to share the code.
- */
-int v4l2_get_acpi_sensor_info(struct device *dev, char **module_id_str)
-{
- struct acpi_device *adev = ACPI_COMPANION(dev);
- struct v4l2_acpi_gpio_parsing_data data = { };
- LIST_HEAD(resource_list);
- union acpi_object *obj;
- unsigned int i, j;
- int ret;
-
- if (module_id_str)
- *module_id_str = NULL;
-
- if (!adev)
- return 0;
-
- obj = acpi_evaluate_dsm_typed(adev->handle, &intel_sensor_module_guid,
- 0x00, 0x01, NULL, ACPI_TYPE_STRING);
- if (obj) {
- dev_info(dev, "Sensor module id: '%s'\n", obj->string.pointer);
- if (module_id_str)
- *module_id_str = kstrdup(obj->string.pointer, GFP_KERNEL);
-
- ACPI_FREE(obj);
- }
-
- if (!soc_intel_is_byt() && !soc_intel_is_cht())
- return 0;
-
- /*
- * First get the GPIO-settings count and then get count GPIO-settings
- * values. Note the order of these may differ from the order in which
- * the GPIOs are listed on the ACPI resources! So we first store them all
- * and then enumerate the ACPI resources and match them up by pin number.
- */
- obj = acpi_evaluate_dsm_typed(adev->handle,
- &intel_sensor_gpio_info_guid, 0x00, 1,
- NULL, ACPI_TYPE_INTEGER);
- if (!obj)
- return dev_err_probe(dev, -EIO, "No _DSM entry for GPIO pin count\n");
-
- data.settings_count = obj->integer.value;
- ACPI_FREE(obj);
-
- if (data.settings_count > V4L2_SENSOR_MAX_ACPI_GPIOS)
- return dev_err_probe(dev, -EIO, "Too many GPIOs %u > %u\n",
- data.settings_count, V4L2_SENSOR_MAX_ACPI_GPIOS);
-
- for (i = 0; i < data.settings_count; i++) {
- /*
- * i + 2 because the index of this _DSM function is 1-based
- * and the first function is just a count.
- */
- obj = acpi_evaluate_dsm_typed(adev->handle,
- &intel_sensor_gpio_info_guid,
- 0x00, i + 2,
- NULL, ACPI_TYPE_INTEGER);
- if (!obj)
- return dev_err_probe(dev, -EIO, "No _DSM entry for GPIO pin %u\n", i);
-
- data.settings[i] = obj->integer.value;
- ACPI_FREE(obj);
- }
-
- /* Since we match up by pin-number the pin-numbers must be unique */
- for (i = 0; i < data.settings_count; i++) {
- for (j = i + 1; j < data.settings_count; j++) {
- if (INTEL_DSM_PIN(data.settings[i]) !=
- INTEL_DSM_PIN(data.settings[j]))
- continue;
-
- return dev_err_probe(dev, -EIO, "Duplicate pin number %lu\n",
- INTEL_DSM_PIN(data.settings[i]));
- }
- }
-
- /* Use devm_kzalloc() for the mappings + params to auto-free them */
- data.map = devm_kzalloc(dev, sizeof(*data.map), GFP_KERNEL);
- if (!data.map)
- return -ENOMEM;
-
- /* Now parse the ACPI resources and build the lookup table */
- data.dev = dev;
- ret = acpi_dev_get_resources(adev, &resource_list,
- v4l2_acpi_handle_gpio_res, &data);
- if (ret < 0)
- return ret;
-
- acpi_dev_free_resource_list(&resource_list);
-
- if (data.map_count != data.settings_count ||
- data.res_count != data.settings_count)
- dev_warn(dev, "ACPI GPIO resources vs DSM GPIO-info count mismatch (dsm: %d res: %d map %d\n",
- data.settings_count, data.res_count, data.map_count);
-
- return devm_acpi_dev_add_driver_gpios(dev, data.map->mapping);
-}
-EXPORT_SYMBOL_GPL(v4l2_get_acpi_sensor_info);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h
index 1fac99f4e2b0..f7b4bee9574b 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_internal.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h
@@ -27,6 +27,7 @@
#include <linux/idr.h>
#include <media/media-device.h>
+#include <media/v4l2-async.h>
#include <media/v4l2-subdev.h>
/* ISP2400*/
@@ -124,17 +125,23 @@
struct atomisp_input_subdev {
unsigned int type;
enum atomisp_camera_port port;
+ u32 code; /* MEDIA_BUS_FMT_* */
+ bool binning_support;
+ bool crop_support;
struct v4l2_subdev *camera;
+ /* Sensor rects for sensors which support crop */
+ struct v4l2_rect native_rect;
+ struct v4l2_rect active_rect;
+ /* Sensor pad_cfg for which == V4L2_SUBDEV_FORMAT_TRY calls */
+ struct v4l2_subdev_pad_config pad_cfg;
+
struct v4l2_subdev *motor;
- struct v4l2_frmsizeenum frame_size;
/*
* To show this resource is used by
* which stream, in ISP multiple stream mode
*/
struct atomisp_sub_device *asd;
-
- int sensor_index;
};
enum atomisp_dfs_mode {
@@ -168,10 +175,6 @@ struct atomisp_regs {
u32 csi_access_viol;
};
-#define ATOMISP_DEVICE_STREAMING_DISABLED 0
-#define ATOMISP_DEVICE_STREAMING_ENABLED 1
-#define ATOMISP_DEVICE_STREAMING_STOPPING 2
-
/*
* ci device struct
*/
@@ -180,6 +183,7 @@ struct atomisp_device {
struct v4l2_device v4l2_dev;
struct media_device media_dev;
struct atomisp_sub_device asd;
+ struct v4l2_async_notifier notifier;
struct atomisp_platform_data *pdata;
void *mmu_l1_base;
void __iomem *base;
@@ -196,6 +200,12 @@ struct atomisp_device {
* structures and css API calls. */
struct mutex mutex;
+ /*
+ * Number of lanes used by each sensor per port.
+ * Note this is indexed by mipi_port_id not atomisp_camera_port.
+ */
+ int sensor_lanes[N_MIPI_PORT_ID];
+ struct v4l2_subdev *sensor_subdevs[ATOMISP_CAMERA_NR_PORTS];
unsigned int input_cnt;
struct atomisp_input_subdev inputs[ATOM_ISP_MAX_INPUTS];
struct v4l2_subdev *flash;
@@ -204,16 +214,11 @@ struct atomisp_device {
struct atomisp_regs saved_regs;
struct atomisp_css_env css_env;
- /* isp timeout status flag */
- bool isp_timeout;
bool isp_fatal_error;
struct work_struct assert_recovery_work;
spinlock_t lock; /* Protects asd.streaming */
- bool need_gfx_throttle;
-
- unsigned int mipi_frame_size;
const struct atomisp_dfs_config *dfs;
unsigned int hpll_freq;
unsigned int running_freq;
diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
index 384f31fc66c5..d2174156573a 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
@@ -528,22 +528,6 @@ int atomisp_pipe_check(struct atomisp_video_pipe *pipe, bool settings_change)
return -EBUSY;
}
- switch (pipe->asd->streaming) {
- case ATOMISP_DEVICE_STREAMING_DISABLED:
- break;
- case ATOMISP_DEVICE_STREAMING_ENABLED:
- if (settings_change) {
- dev_err(pipe->isp->dev, "Set fmt/input IOCTL while streaming\n");
- return -EBUSY;
- }
- break;
- case ATOMISP_DEVICE_STREAMING_STOPPING:
- dev_err(pipe->isp->dev, "IOCTL issued while stopping\n");
- return -EBUSY;
- default:
- return -EINVAL;
- }
-
return 0;
}
@@ -615,20 +599,6 @@ static int atomisp_enum_input(struct file *file, void *fh,
return 0;
}
-static unsigned int
-atomisp_subdev_streaming_count(struct atomisp_sub_device *asd)
-{
- return vb2_start_streaming_called(&asd->video_out_preview.vb_queue) +
- vb2_start_streaming_called(&asd->video_out_capture.vb_queue) +
- vb2_start_streaming_called(&asd->video_out_video_capture.vb_queue) +
- vb2_start_streaming_called(&asd->video_out_vf.vb_queue);
-}
-
-unsigned int atomisp_streaming_count(struct atomisp_device *isp)
-{
- return isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED;
-}
-
/*
* get input are used to get current primary/secondary camera
*/
@@ -703,7 +673,7 @@ static int atomisp_s_input(struct file *file, void *fh, unsigned int input)
/* select operating sensor */
ret = v4l2_subdev_call(isp->inputs[input].camera, video, s_routing,
- 0, isp->inputs[input].sensor_index, 0);
+ 0, 0, 0);
if (ret && (ret != -ENOIOCTLCMD)) {
dev_err(isp->dev, "Failed to select sensor\n");
return ret;
@@ -727,20 +697,98 @@ static int atomisp_s_input(struct file *file, void *fh, unsigned int input)
return 0;
}
+/*
+ * With crop any framesize <= sensor-size can be made, give
+ * userspace a list of sizes to choice from.
+ */
+static int atomisp_enum_framesizes_crop_inner(struct atomisp_device *isp,
+ struct v4l2_frmsizeenum *fsize,
+ const struct v4l2_rect *active,
+ const struct v4l2_rect *native,
+ int *valid_sizes)
+{
+ static const struct v4l2_frmsize_discrete frame_sizes[] = {
+ { 1600, 1200 },
+ { 1600, 1080 },
+ { 1600, 900 },
+ { 1440, 1080 },
+ { 1280, 960 },
+ { 1280, 720 },
+ { 800, 600 },
+ { 640, 480 },
+ };
+ u32 padding_w, padding_h;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(frame_sizes); i++) {
+ atomisp_get_padding(isp, frame_sizes[i].width, frame_sizes[i].height,
+ &padding_w, &padding_h);
+
+ if ((frame_sizes[i].width + padding_w) > native->width ||
+ (frame_sizes[i].height + padding_h) > native->height)
+ continue;
+
+ /*
+ * Skip sizes where width and height are less then 2/3th of the
+ * sensor size to avoid sizes with a too small field of view.
+ */
+ if (frame_sizes[i].width < (active->width * 2 / 3) &&
+ frame_sizes[i].height < (active->height * 2 / 3))
+ continue;
+
+ if (*valid_sizes == fsize->index) {
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete = frame_sizes[i];
+ return 0;
+ }
+
+ (*valid_sizes)++;
+ }
+
+ return -EINVAL;
+}
+
+static int atomisp_enum_framesizes_crop(struct atomisp_device *isp,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr];
+ struct v4l2_rect active = input->active_rect;
+ struct v4l2_rect native = input->native_rect;
+ int ret, valid_sizes = 0;
+
+ ret = atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &native, &valid_sizes);
+ if (ret == 0)
+ return 0;
+
+ if (!input->binning_support)
+ return -EINVAL;
+
+ active.width /= 2;
+ active.height /= 2;
+ native.width /= 2;
+ native.height /= 2;
+
+ return atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &native, &valid_sizes);
+}
+
static int atomisp_enum_framesizes(struct file *file, void *priv,
struct v4l2_frmsizeenum *fsize)
{
struct video_device *vdev = video_devdata(file);
struct atomisp_device *isp = video_get_drvdata(vdev);
struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
+ struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
struct v4l2_subdev_frame_size_enum fse = {
.index = fsize->index,
.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .code = input->code,
};
int ret;
- ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
- pad, enum_frame_size, NULL, &fse);
+ if (input->crop_support)
+ return atomisp_enum_framesizes_crop(isp, fsize);
+
+ ret = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse);
if (ret)
return ret;
@@ -836,77 +884,14 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh,
return -EINVAL;
}
-static int atomisp_adjust_fmt(struct v4l2_format *f)
-{
- const struct atomisp_format_bridge *format_bridge;
- u32 padded_width;
-
- format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
- /* Currently, raw formats are broken!!! */
- if (!format_bridge || format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) {
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
-
- format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
- if (!format_bridge)
- return -EINVAL;
- }
-
- padded_width = f->fmt.pix.width + pad_w;
-
- if (format_bridge->planar) {
- f->fmt.pix.bytesperline = padded_width;
- f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height *
- DIV_ROUND_UP(format_bridge->depth *
- padded_width, 8));
- } else {
- f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth *
- padded_width, 8);
- f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline);
- }
-
- if (f->fmt.pix.field == V4L2_FIELD_ANY)
- f->fmt.pix.field = V4L2_FIELD_NONE;
-
- /*
- * FIXME: do we need to setup this differently, depending on the
- * sensor or the pipeline?
- */
- f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
- f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_709;
- f->fmt.pix.xfer_func = V4L2_XFER_FUNC_709;
-
- f->fmt.pix.width -= pad_w;
- f->fmt.pix.height -= pad_h;
-
- return 0;
-}
-
/* This function looks up the closest available resolution. */
static int atomisp_try_fmt_cap(struct file *file, void *fh,
struct v4l2_format *f)
{
struct video_device *vdev = video_devdata(file);
- u32 pixfmt = f->fmt.pix.pixelformat;
- int ret;
-
- /*
- * atomisp_try_fmt() gived results with padding included, note
- * (this gets removed again by the atomisp_adjust_fmt() call below.
- */
- f->fmt.pix.width += pad_w;
- f->fmt.pix.height += pad_h;
-
- ret = atomisp_try_fmt(vdev, &f->fmt.pix, NULL);
- if (ret)
- return ret;
-
- /*
- * atomisp_try_fmt() replaces pixelformat with the sensors native
- * format, restore the actual format requested by userspace.
- */
- f->fmt.pix.pixelformat = pixfmt;
+ struct atomisp_device *isp = video_get_drvdata(vdev);
- return atomisp_adjust_fmt(f);
+ return atomisp_try_fmt(isp, &f->fmt.pix, NULL, NULL);
}
static int atomisp_g_fmt_cap(struct file *file, void *fh,
@@ -1048,8 +1033,7 @@ static int atomisp_qbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
if (buf->index >= vdev->queue->num_buffers)
return -EINVAL;
- if (!atomisp_is_vf_pipe(pipe) &&
- (buf->reserved2 & ATOMISP_BUFFER_HAS_PER_FRAME_SETTING)) {
+ if (buf->reserved2 & ATOMISP_BUFFER_HAS_PER_FRAME_SETTING) {
/* this buffer will have a per-frame parameter */
pipe->frame_request_config_id[buf->index] = buf->reserved2 &
~ATOMISP_BUFFER_HAS_PER_FRAME_SETTING;
@@ -1099,48 +1083,6 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
return 0;
}
-enum ia_css_pipe_id atomisp_get_css_pipe_id(struct atomisp_sub_device *asd)
-{
- /*
- * Disable vf_pp and run CSS in video mode. This allows using ISP
- * scaling but it has one frame delay due to CSS internal buffering.
- */
- if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
- return IA_CSS_PIPE_ID_VIDEO;
-
- /*
- * Disable vf_pp and run CSS in still capture mode. In this mode
- * CSS does not cause extra latency with buffering, but scaling
- * is not available.
- */
- if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT)
- return IA_CSS_PIPE_ID_CAPTURE;
-
- switch (asd->run_mode->val) {
- case ATOMISP_RUN_MODE_PREVIEW:
- return IA_CSS_PIPE_ID_PREVIEW;
- case ATOMISP_RUN_MODE_VIDEO:
- return IA_CSS_PIPE_ID_VIDEO;
- case ATOMISP_RUN_MODE_STILL_CAPTURE:
- default:
- return IA_CSS_PIPE_ID_CAPTURE;
- }
-}
-
-static unsigned int atomisp_sensor_start_stream(struct atomisp_sub_device *asd)
-{
- if (asd->vfpp->val != ATOMISP_VFPP_ENABLE ||
- asd->copy_mode)
- return 1;
-
- if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO ||
- (asd->run_mode->val == ATOMISP_RUN_MODE_STILL_CAPTURE &&
- !atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code)))
- return 2;
- else
- return 1;
-}
-
/* Input system HW workaround */
/* Input system address translation corrupts burst during */
/* invalidate. SW workaround for this is to set burst length */
@@ -1163,17 +1105,14 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct atomisp_video_pipe *pipe = vq_to_pipe(vq);
struct atomisp_sub_device *asd = pipe->asd;
- struct video_device *vdev = &pipe->vdev;
struct atomisp_device *isp = asd->isp;
struct pci_dev *pdev = to_pci_dev(isp->dev);
- enum ia_css_pipe_id css_pipe_id;
- unsigned int sensor_start_stream;
unsigned long irqflags;
int ret;
- mutex_lock(&isp->mutex);
+ dev_dbg(isp->dev, "Start stream\n");
- dev_dbg(isp->dev, "Start stream on pad %d\n", atomisp_subdev_source_pad(vdev));
+ mutex_lock(&isp->mutex);
ret = atomisp_pipe_check(pipe, false);
if (ret)
@@ -1182,25 +1121,6 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count)
/* Input system HW workaround */
atomisp_dma_burst_len_cfg(asd);
- /*
- * The number of streaming video nodes is based on which
- * binary is going to be run.
- */
- sensor_start_stream = atomisp_sensor_start_stream(asd);
-
- if (atomisp_subdev_streaming_count(asd) > sensor_start_stream) {
- atomisp_qbuffers_to_css(asd);
- ret = 0;
- goto out_unlock;
- }
-
- if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) {
- atomisp_qbuffers_to_css(asd);
- goto start_sensor;
- }
-
- css_pipe_id = atomisp_get_css_pipe_id(asd);
-
/* Invalidate caches. FIXME: should flush only necessary buffers */
wbinvd();
@@ -1215,14 +1135,14 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count)
}
asd->params.dvs_6axis = NULL;
- ret = atomisp_css_start(asd, css_pipe_id, false);
+ ret = atomisp_css_start(asd);
if (ret) {
atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_QUEUED, true);
goto out_unlock;
}
spin_lock_irqsave(&isp->lock, irqflags);
- asd->streaming = ATOMISP_DEVICE_STREAMING_ENABLED;
+ asd->streaming = true;
spin_unlock_irqrestore(&isp->lock, irqflags);
atomic_set(&asd->sof_count, -1);
atomic_set(&asd->sequence, -1);
@@ -1238,13 +1158,6 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count)
atomisp_qbuffers_to_css(asd);
- /* Only start sensor when the last streaming instance started */
- if (atomisp_subdev_streaming_count(asd) < sensor_start_stream) {
- ret = 0;
- goto out_unlock;
- }
-
-start_sensor:
if (isp->flash) {
asd->params.num_flash_frames = 0;
asd->params.flash_state = ATOMISP_FLASH_IDLE;
@@ -1254,19 +1167,9 @@ start_sensor:
atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF,
atomisp_css_valid_sof(isp));
atomisp_csi2_configure(asd);
- /*
- * set freq to max when streaming count > 1 which indicate
- * dual camera would run
- */
- if (atomisp_streaming_count(isp) > 1) {
- if (atomisp_freq_scaling(isp,
- ATOMISP_DFS_MODE_MAX, false) < 0)
- dev_dbg(isp->dev, "DFS max mode failed!\n");
- } else {
- if (atomisp_freq_scaling(isp,
- ATOMISP_DFS_MODE_AUTO, false) < 0)
- dev_dbg(isp->dev, "DFS auto mode failed!\n");
- }
+
+ if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, false) < 0)
+ dev_dbg(isp->dev, "DFS auto mode failed!\n");
/* Enable the CSI interface on ANN B0/K0 */
if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 <<
@@ -1279,8 +1182,9 @@ start_sensor:
ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
video, s_stream, 1);
if (ret) {
+ dev_err(isp->dev, "Starting sensor stream failed: %d\n", ret);
spin_lock_irqsave(&isp->lock, irqflags);
- asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
+ asd->streaming = false;
spin_unlock_irqrestore(&isp->lock, irqflags);
ret = -EINVAL;
goto out_unlock;
@@ -1295,19 +1199,14 @@ void atomisp_stop_streaming(struct vb2_queue *vq)
{
struct atomisp_video_pipe *pipe = vq_to_pipe(vq);
struct atomisp_sub_device *asd = pipe->asd;
- struct video_device *vdev = &pipe->vdev;
struct atomisp_device *isp = asd->isp;
struct pci_dev *pdev = to_pci_dev(isp->dev);
- enum ia_css_pipe_id css_pipe_id;
- bool recreate_stream = false;
- bool first_streamoff = false;
unsigned long flags;
int ret;
- mutex_lock(&isp->mutex);
-
- dev_dbg(isp->dev, "Stop stream on pad %d\n", atomisp_subdev_source_pad(vdev));
+ dev_dbg(isp->dev, "Stop stream\n");
+ mutex_lock(&isp->mutex);
/*
* There is no guarantee that the buffers queued to / owned by the ISP
* will properly be returned to the queue when stopping. Set a flag to
@@ -1324,46 +1223,29 @@ void atomisp_stop_streaming(struct vb2_queue *vq)
if (ret == 0)
dev_warn(isp->dev, "Warning timeout waiting for CSS to return buffers\n");
- if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED)
- first_streamoff = true;
-
spin_lock_irqsave(&isp->lock, flags);
- if (atomisp_subdev_streaming_count(asd) == 1)
- asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
- else
- asd->streaming = ATOMISP_DEVICE_STREAMING_STOPPING;
+ asd->streaming = false;
spin_unlock_irqrestore(&isp->lock, flags);
- if (!first_streamoff)
- goto stopsensor;
-
atomisp_clear_css_buffer_counters(asd);
atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false);
- css_pipe_id = atomisp_get_css_pipe_id(asd);
- atomisp_css_stop(asd, css_pipe_id, false);
+ atomisp_css_stop(asd, false);
atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_ERROR, true);
atomisp_subdev_cleanup_pending_events(asd);
-stopsensor:
- if (atomisp_subdev_streaming_count(asd) != atomisp_sensor_start_stream(asd))
- goto out_unlock;
ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
video, s_stream, 0);
+ if (ret)
+ dev_warn(isp->dev, "Stopping sensor stream failed: %d\n", ret);
if (isp->flash) {
asd->params.num_flash_frames = 0;
asd->params.flash_state = ATOMISP_FLASH_IDLE;
}
- /* if other streams are running, isp should not be powered off */
- if (atomisp_streaming_count(isp)) {
- atomisp_css_flush(isp);
- goto out_unlock;
- }
-
/* Disable the CSI interface on ANN B0/K0 */
if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 <<
ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) {
@@ -1373,45 +1255,21 @@ stopsensor:
if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_LOW, false))
dev_warn(isp->dev, "DFS failed.\n");
+
/*
- * ISP work around, need to reset isp
- * Is it correct time to reset ISP when first node does streamoff?
- */
- if (isp->isp_timeout)
- dev_err(isp->dev, "%s: Resetting with WA activated",
- __func__);
- /*
- * It is possible that the other asd stream is in the stage
- * that v4l2_setfmt is just get called on it, which will
- * create css stream on that stream. But at this point, there
- * is no way to destroy the css stream created on that stream.
- *
- * So force stream destroy here.
+ * ISP work around, need to reset ISP to allow next stream on to work.
+ * Streams have already been destroyed by atomisp_css_stop().
+ * Disable PUNIT/ISP acknowlede/handshake - SRSE=3 and then reset.
*/
- if (isp->asd.stream_prepared) {
- atomisp_destroy_pipes_stream_force(&isp->asd);
- recreate_stream = true;
- }
-
- /* disable PUNIT/ISP acknowlede/handshake - SRSE=3 */
pci_write_config_dword(pdev, PCI_I_CONTROL,
isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK);
- dev_err(isp->dev, "atomisp_reset");
atomisp_reset(isp);
- if (recreate_stream) {
- int ret2;
-
- ret2 = atomisp_create_pipes_stream(&isp->asd);
- if (ret2) {
- dev_err(isp->dev, "%s error re-creating streams: %d\n", __func__, ret2);
- if (!ret)
- ret = ret2;
- }
- }
+ /* Streams were destroyed by atomisp_css_stop(), recreate them. */
+ ret = atomisp_create_pipes_stream(&isp->asd);
+ if (ret)
+ dev_warn(isp->dev, "Recreating streams failed: %d\n", ret);
- isp->isp_timeout = false;
-out_unlock:
mutex_unlock(&isp->mutex);
}
@@ -1902,9 +1760,6 @@ static int atomisp_s_parm(struct file *file, void *fh,
case CI_MODE_STILL_CAPTURE:
mode = ATOMISP_RUN_MODE_STILL_CAPTURE;
break;
- case CI_MODE_CONTINUOUS:
- mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE;
- break;
case CI_MODE_PREVIEW:
mode = ATOMISP_RUN_MODE_PREVIEW;
break;
@@ -1923,14 +1778,8 @@ static long atomisp_vidioc_default(struct file *file, void *fh,
struct video_device *vdev = video_devdata(file);
struct atomisp_device *isp = video_get_drvdata(vdev);
struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
- struct v4l2_subdev *motor;
int err;
- if (!IS_ISP2401)
- motor = isp->inputs[asd->input_curr].motor;
- else
- motor = isp->motor;
-
switch (cmd) {
case ATOMISP_IOC_S_SENSOR_RUNMODE:
if (IS_ISP2401)
@@ -2081,31 +1930,10 @@ static long atomisp_vidioc_default(struct file *file, void *fh,
err = atomisp_fixed_pattern_table(asd, arg);
break;
- case ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA:
- if (motor)
- err = v4l2_subdev_call(motor, core, ioctl, cmd, arg);
- else
- err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
- core, ioctl, cmd, arg);
- break;
-
case ATOMISP_IOC_S_EXPOSURE:
- case ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP:
- case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA:
- case ATOMISP_IOC_G_SENSOR_AE_BRACKETING_INFO:
- case ATOMISP_IOC_S_SENSOR_AE_BRACKETING_MODE:
- case ATOMISP_IOC_G_SENSOR_AE_BRACKETING_MODE:
- case ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT:
err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
core, ioctl, cmd, arg);
break;
- case ATOMISP_IOC_G_UPDATE_EXPOSURE:
- if (IS_ISP2401)
- err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
- core, ioctl, cmd, arg);
- else
- err = -EINVAL;
- break;
case ATOMISP_IOC_S_ISP_SHD_TAB:
err = atomisp_set_shading_table(asd, arg);
@@ -2123,12 +1951,6 @@ static long atomisp_vidioc_default(struct file *file, void *fh,
err = atomisp_set_parameters(vdev, arg);
break;
- case ATOMISP_IOC_G_METADATA:
- err = atomisp_get_metadata(asd, 0, arg);
- break;
- case ATOMISP_IOC_G_METADATA_BY_TYPE:
- err = atomisp_get_metadata_by_type(asd, 0, arg);
- break;
case ATOMISP_IOC_EXT_ISP_CTRL:
err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
core, ioctl, cmd, arg);
@@ -2149,15 +1971,9 @@ static long atomisp_vidioc_default(struct file *file, void *fh,
case ATOMISP_IOC_S_FORMATS_CONFIG:
err = atomisp_formats(asd, 1, arg);
break;
- case ATOMISP_IOC_S_EXPOSURE_WINDOW:
- err = atomisp_s_ae_window(asd, arg);
- break;
case ATOMISP_IOC_INJECT_A_FAKE_EVENT:
err = atomisp_inject_a_fake_event(asd, arg);
break;
- case ATOMISP_IOC_G_INVALID_FRAME_NUM:
- err = atomisp_get_invalid_frame_num(vdev, arg);
- break;
case ATOMISP_IOC_S_ARRAY_RESOLUTION:
err = atomisp_set_array_res(asd, arg);
break;
diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.h b/drivers/staging/media/atomisp/pci/atomisp_ioctl.h
index db6da77df06b..56d3df86c706 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.h
@@ -42,13 +42,8 @@ int atomisp_alloc_css_stat_bufs(struct atomisp_sub_device *asd,
int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count);
void atomisp_stop_streaming(struct vb2_queue *vq);
-enum ia_css_pipe_id atomisp_get_css_pipe_id(struct atomisp_sub_device
- *asd);
-
extern const struct v4l2_ioctl_ops atomisp_ioctl_ops;
-unsigned int atomisp_streaming_count(struct atomisp_device *isp);
-
/* compat_ioctl for 32bit userland app and 64bit kernel */
long atomisp_compat_ioctl32(struct file *file,
unsigned int cmd, unsigned long arg);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c
index a0acfdb87177..45073e401bac 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c
@@ -117,35 +117,19 @@ const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_by_atomisp_in_fmt(
return NULL;
}
-bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd,
- unsigned int source_pad)
+bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd)
{
struct v4l2_mbus_framefmt *sink, *src;
sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
- V4L2_SUBDEV_FORMAT_ACTIVE,
- ATOMISP_SUBDEV_PAD_SINK);
+ V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK);
src = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
- V4L2_SUBDEV_FORMAT_ACTIVE, source_pad);
+ V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE);
return atomisp_is_mbuscode_raw(sink->code)
&& !atomisp_is_mbuscode_raw(src->code);
}
-uint16_t atomisp_subdev_source_pad(struct video_device *vdev)
-{
- struct media_link *link;
- u16 ret = 0;
-
- list_for_each_entry(link, &vdev->entity.links, list) {
- if (link->source) {
- ret = link->source->index;
- break;
- }
- }
- return ret;
-}
-
/*
* V4L2 subdev operations
*/
@@ -355,10 +339,7 @@ static const char *atomisp_pad_str(unsigned int pad)
{
static const char *const pad_str[] = {
"ATOMISP_SUBDEV_PAD_SINK",
- "ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE",
- "ATOMISP_SUBDEV_PAD_SOURCE_VF",
- "ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW",
- "ATOMISP_SUBDEV_PAD_SOURCE_VIDEO",
+ "ATOMISP_SUBDEV_PAD_SOURCE",
};
if (pad >= ARRAY_SIZE(pad_str))
@@ -376,9 +357,10 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
*comp[ATOMISP_SUBDEV_PADS_NUM];
- unsigned int i;
- unsigned int padding_w = pad_w;
- unsigned int padding_h = pad_h;
+
+ if ((pad == ATOMISP_SUBDEV_PAD_SINK && target != V4L2_SEL_TGT_CROP) ||
+ (pad == ATOMISP_SUBDEV_PAD_SOURCE && target != V4L2_SEL_TGT_COMPOSE))
+ return -EINVAL;
isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp);
@@ -393,27 +375,17 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
r->width = rounddown(r->width, ATOM_ISP_STEP_WIDTH);
r->height = rounddown(r->height, ATOM_ISP_STEP_HEIGHT);
- switch (pad) {
- case ATOMISP_SUBDEV_PAD_SINK: {
+ if (pad == ATOMISP_SUBDEV_PAD_SINK) {
/* Only crop target supported on sink pad. */
unsigned int dvs_w, dvs_h;
crop[pad]->width = ffmt[pad]->width;
crop[pad]->height = ffmt[pad]->height;
- /* Workaround for BYT 1080p perfectshot since the maxinum resolution of
- * front camera ov2722 is 1932x1092 and cannot use pad_w > 12*/
- if (!strncmp(isp->inputs[isp_sd->input_curr].camera->name,
- "ov2722", 6) && crop[pad]->height == 1092) {
- padding_w = 12;
- padding_h = 12;
- }
-
- if (atomisp_subdev_format_conversion(isp_sd,
- isp_sd->capture_pad)
+ if (atomisp_subdev_format_conversion(isp_sd)
&& crop[pad]->width && crop[pad]->height) {
- crop[pad]->width -= padding_w;
- crop[pad]->height -= padding_h;
+ crop[pad]->width -= isp_sd->sink_pad_padding_w;
+ crop[pad]->height -= isp_sd->sink_pad_padding_h;
}
if (isp_sd->params.video_dis_en &&
@@ -433,19 +405,15 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
crop[pad]->height = min(crop[pad]->height, r->height);
if (!(flags & V4L2_SEL_FLAG_KEEP_CONFIG)) {
- for (i = ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE;
- i < ATOMISP_SUBDEV_PADS_NUM; i++) {
- struct v4l2_rect tmp = *crop[pad];
-
- atomisp_subdev_set_selection(
- sd, sd_state, which, i,
- V4L2_SEL_TGT_COMPOSE,
- flags, &tmp);
- }
+ struct v4l2_rect tmp = *crop[pad];
+
+ atomisp_subdev_set_selection(sd, sd_state, which,
+ ATOMISP_SUBDEV_PAD_SOURCE,
+ V4L2_SEL_TGT_COMPOSE, flags, &tmp);
}
if (which == V4L2_SUBDEV_FORMAT_TRY)
- break;
+ goto get_rect;
if (isp_sd->params.video_dis_en &&
isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
@@ -468,12 +436,8 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
ATOMISP_INPUT_STREAM_GENERAL,
crop[pad]->width,
crop[pad]->height);
- break;
- }
- case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
- case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: {
+ } else if (isp_sd->run_mode->val != ATOMISP_RUN_MODE_PREVIEW) {
/* Only compose target is supported on source pads. */
-
if (isp_sd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
/* Scaling is disabled in this mode */
r->width = crop[ATOMISP_SUBDEV_PAD_SINK]->width;
@@ -492,7 +456,7 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
if (r->width == 0 || r->height == 0 ||
crop[ATOMISP_SUBDEV_PAD_SINK]->width == 0 ||
crop[ATOMISP_SUBDEV_PAD_SINK]->height == 0)
- break;
+ goto get_rect;
/*
* do cropping on sensor input if ratio of required resolution
* is different with sensor output resolution ratio:
@@ -522,18 +486,12 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
width * r->height / r->width,
ATOM_ISP_STEP_WIDTH));
-
- break;
- }
- case ATOMISP_SUBDEV_PAD_SOURCE_VF:
- case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
+ } else {
comp[pad]->width = r->width;
comp[pad]->height = r->height;
- break;
- default:
- return -EINVAL;
}
+get_rect:
/* Set format dimensions on non-sink pads as well. */
if (pad != ATOMISP_SUBDEV_PAD_SINK) {
ffmt[pad]->width = comp[pad]->width;
@@ -612,10 +570,7 @@ void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd,
break;
}
- case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
- case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
- case ATOMISP_SUBDEV_PAD_SOURCE_VF:
- case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
+ case ATOMISP_SUBDEV_PAD_SOURCE:
__ffmt->code = ffmt->code;
break;
}
@@ -755,11 +710,9 @@ static const struct v4l2_ctrl_ops ctrl_ops = {
};
static const char *const ctrl_run_mode_menu[] = {
- NULL,
- "Video",
- "Still capture",
- "Continuous capture",
- "Preview",
+ [ATOMISP_RUN_MODE_VIDEO] = "Video",
+ [ATOMISP_RUN_MODE_STILL_CAPTURE] = "Still capture",
+ [ATOMISP_RUN_MODE_PREVIEW] = "Preview",
};
static const struct v4l2_ctrl_config ctrl_run_mode = {
@@ -767,9 +720,9 @@ static const struct v4l2_ctrl_config ctrl_run_mode = {
.id = V4L2_CID_RUN_MODE,
.name = "Atomisp run mode",
.type = V4L2_CTRL_TYPE_MENU,
- .min = 1,
- .def = 1,
- .max = 4,
+ .min = ATOMISP_RUN_MODE_MIN,
+ .def = ATOMISP_RUN_MODE_PREVIEW,
+ .max = ATOMISP_RUN_MODE_MAX,
.qmenu = ctrl_run_mode_menu,
};
@@ -921,23 +874,13 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
sprintf(sd->name, "ATOMISP_SUBDEV");
v4l2_set_subdevdata(sd, asd);
sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+ sd->devnode = &asd->video_out.vdev;
pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
- pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE;
- pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE;
- pads[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].flags = MEDIA_PAD_FL_SOURCE;
- pads[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].flags = MEDIA_PAD_FL_SOURCE;
-
- asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code =
- MEDIA_BUS_FMT_SBGGR10_1X10;
- asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code =
- MEDIA_BUS_FMT_SBGGR10_1X10;
- asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VF].fmt.code =
- MEDIA_BUS_FMT_SBGGR10_1X10;
- asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].fmt.code =
- MEDIA_BUS_FMT_SBGGR10_1X10;
- asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].fmt.code =
- MEDIA_BUS_FMT_SBGGR10_1X10;
+ pads[ATOMISP_SUBDEV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+ asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10;
me->ops = &isp_subdev_media_ops;
me->function = MEDIA_ENT_F_PROC_VIDEO_ISP;
@@ -945,43 +888,11 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
if (ret < 0)
return ret;
- ret = atomisp_init_subdev_pipe(asd, &asd->video_out_preview,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ ret = atomisp_init_subdev_pipe(asd, &asd->video_out, V4L2_BUF_TYPE_VIDEO_CAPTURE);
if (ret)
return ret;
- ret = atomisp_init_subdev_pipe(asd, &asd->video_out_vf,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
- if (ret)
- return ret;
-
- ret = atomisp_init_subdev_pipe(asd, &asd->video_out_capture,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
- if (ret)
- return ret;
-
- ret = atomisp_init_subdev_pipe(asd, &asd->video_out_video_capture,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
- if (ret)
- return ret;
-
- ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE",
- ATOMISP_RUN_MODE_STILL_CAPTURE);
- if (ret < 0)
- return ret;
-
- ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER",
- ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE);
- if (ret < 0)
- return ret;
-
- ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW",
- ATOMISP_RUN_MODE_PREVIEW);
- if (ret < 0)
- return ret;
-
- ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO",
- ATOMISP_RUN_MODE_VIDEO);
+ ret = atomisp_video_init(&asd->video_out);
if (ret < 0)
return ret;
@@ -1016,57 +927,6 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
return asd->ctrl_handler.error;
}
-int atomisp_create_pads_links(struct atomisp_device *isp)
-{
- int i, ret;
-
- for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
- ret = media_create_pad_link(&isp->csi2_port[i].subdev.entity,
- CSI2_PAD_SOURCE, &isp->asd.subdev.entity,
- ATOMISP_SUBDEV_PAD_SINK, 0);
- if (ret < 0)
- return ret;
- }
-
- for (i = 0; i < isp->input_cnt; i++) {
- /* Don't create links for the test-pattern-generator */
- if (isp->inputs[i].type == TEST_PATTERN)
- continue;
-
- ret = media_create_pad_link(&isp->inputs[i].camera->entity, 0,
- &isp->csi2_port[isp->inputs[i].
- port].subdev.entity,
- CSI2_PAD_SINK,
- MEDIA_LNK_FL_ENABLED |
- MEDIA_LNK_FL_IMMUTABLE);
- if (ret < 0)
- return ret;
- }
-
- ret = media_create_pad_link(&isp->asd.subdev.entity,
- ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW,
- &isp->asd.video_out_preview.vdev.entity, 0, 0);
- if (ret < 0)
- return ret;
- ret = media_create_pad_link(&isp->asd.subdev.entity,
- ATOMISP_SUBDEV_PAD_SOURCE_VF,
- &isp->asd.video_out_vf.vdev.entity, 0, 0);
- if (ret < 0)
- return ret;
- ret = media_create_pad_link(&isp->asd.subdev.entity,
- ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE,
- &isp->asd.video_out_capture.vdev.entity, 0, 0);
- if (ret < 0)
- return ret;
- ret = media_create_pad_link(&isp->asd.subdev.entity,
- ATOMISP_SUBDEV_PAD_SOURCE_VIDEO,
- &isp->asd.video_out_video_capture.vdev.entity, 0, 0);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
static void atomisp_subdev_cleanup_entities(struct atomisp_sub_device *asd)
{
v4l2_ctrl_handler_free(&asd->ctrl_handler);
@@ -1092,10 +952,7 @@ void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd)
{
atomisp_subdev_cleanup_entities(asd);
v4l2_device_unregister_subdev(&asd->subdev);
- atomisp_video_unregister(&asd->video_out_preview);
- atomisp_video_unregister(&asd->video_out_vf);
- atomisp_video_unregister(&asd->video_out_capture);
- atomisp_video_unregister(&asd->video_out_video_capture);
+ atomisp_video_unregister(&asd->video_out);
}
int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd,
@@ -1104,51 +961,6 @@ int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd,
return v4l2_device_register_subdev(vdev, &asd->subdev);
}
-int atomisp_subdev_register_video_nodes(struct atomisp_sub_device *asd,
- struct v4l2_device *vdev)
-{
- int ret;
-
- /*
- * FIXME: check if all device caps are properly initialized.
- * Should any of those use V4L2_CAP_META_CAPTURE? Probably yes.
- */
-
- asd->video_out_preview.vdev.v4l2_dev = vdev;
- asd->video_out_preview.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- ret = video_register_device(&asd->video_out_preview.vdev,
- VFL_TYPE_VIDEO, -1);
- if (ret < 0)
- goto error;
-
- asd->video_out_capture.vdev.v4l2_dev = vdev;
- asd->video_out_capture.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- ret = video_register_device(&asd->video_out_capture.vdev,
- VFL_TYPE_VIDEO, -1);
- if (ret < 0)
- goto error;
-
- asd->video_out_vf.vdev.v4l2_dev = vdev;
- asd->video_out_vf.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- ret = video_register_device(&asd->video_out_vf.vdev,
- VFL_TYPE_VIDEO, -1);
- if (ret < 0)
- goto error;
-
- asd->video_out_video_capture.vdev.v4l2_dev = vdev;
- asd->video_out_video_capture.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- ret = video_register_device(&asd->video_out_video_capture.vdev,
- VFL_TYPE_VIDEO, -1);
- if (ret < 0)
- goto error;
-
- return 0;
-
-error:
- atomisp_subdev_unregister_entities(asd);
- return ret;
-}
-
/*
* atomisp_subdev_init - ISP Subdevice initialization.
* @dev: Device pointer specific to the ATOM ISP.
diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h
index fee663bc415a..9a04511b9efd 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h
@@ -32,15 +32,8 @@
#define ATOMISP_MAX_EXP_ID (250)
#define ATOMISP_SUBDEV_PAD_SINK 0
-/* capture output for still frames */
-#define ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE 1
-/* viewfinder output for downscaled capture output */
-#define ATOMISP_SUBDEV_PAD_SOURCE_VF 2
-/* preview output for display */
-#define ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW 3
-/* main output for video pipeline */
-#define ATOMISP_SUBDEV_PAD_SOURCE_VIDEO 4
-#define ATOMISP_SUBDEV_PADS_NUM 5
+#define ATOMISP_SUBDEV_PAD_SOURCE 1
+#define ATOMISP_SUBDEV_PADS_NUM 2
struct atomisp_in_fmt_conv {
u32 code;
@@ -74,8 +67,6 @@ struct atomisp_video_pipe {
/* Filled through atomisp_get_css_frame_info() on queue setup */
struct ia_css_frame_info frame_info;
- /* Store here the initial run mode */
- unsigned int default_run_mode;
/* Set from streamoff to disallow queuing further buffers in CSS */
bool stopping;
@@ -248,15 +239,12 @@ struct atomisp_sub_device {
struct v4l2_subdev subdev;
struct media_pad pads[ATOMISP_SUBDEV_PADS_NUM];
struct atomisp_pad_format fmt[ATOMISP_SUBDEV_PADS_NUM];
- u16 capture_pad; /* main capture pad; defines much of isp config */
+ /* Padding for currently set sink-pad fmt */
+ u32 sink_pad_padding_w;
+ u32 sink_pad_padding_h;
unsigned int output;
- struct atomisp_video_pipe video_out_capture; /* capture output */
- struct atomisp_video_pipe video_out_vf; /* viewfinder output */
- struct atomisp_video_pipe video_out_preview; /* preview output */
- /* video pipe main output */
- struct atomisp_video_pipe video_out_video_capture;
- /* struct isp_subdev_params params; */
+ struct atomisp_video_pipe video_out;
struct atomisp_device *isp;
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_ctrl *run_mode;
@@ -312,13 +300,12 @@ struct atomisp_sub_device {
* Writers of streaming must hold both isp->mutex and isp->lock.
* Readers of streaming need to hold only one of the two locks.
*/
- unsigned int streaming;
+ bool streaming;
bool stream_prepared; /* whether css stream is created */
+ bool recreate_streams_on_resume;
unsigned int latest_preview_exp_id; /* CSS ZSL/SDV raw buffer id */
- unsigned int mipi_frame_size;
-
bool copy_mode; /* CSI2+ use copy mode */
int raw_buffer_bitmap[ATOMISP_MAX_EXP_ID / 32 +
@@ -352,9 +339,7 @@ const struct atomisp_in_fmt_conv
atomisp_in_fmt);
const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_compressed(u32 code);
-bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd,
- unsigned int source_pad);
-uint16_t atomisp_subdev_source_pad(struct video_device *vdev);
+bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd);
/* Get pointer to appropriate format */
struct v4l2_mbus_framefmt
@@ -382,10 +367,7 @@ void atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device *asd);
void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd);
int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd,
struct v4l2_device *vdev);
-int atomisp_subdev_register_video_nodes(struct atomisp_sub_device *asd,
- struct v4l2_device *vdev);
int atomisp_subdev_init(struct atomisp_device *isp);
void atomisp_subdev_cleanup(struct atomisp_device *isp);
-int atomisp_create_pads_links(struct atomisp_device *isp);
#endif /* __ATOMISP_SUBDEV_H__ */
diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
index 3f315dabbeeb..c43b916a006e 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
@@ -27,6 +27,7 @@
#include <linux/dmi.h>
#include <linux/interrupt.h>
#include <linux/bits.h>
+#include <media/v4l2-fwnode.h>
#include <asm/iosf_mbi.h>
@@ -124,22 +125,8 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr[] = {
.height = ISP_FREQ_RULE_ANY,
.fps = ISP_FREQ_RULE_ANY,
.isp_freq = ISP_FREQ_400MHZ,
- .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE,
- },
- {
- .width = ISP_FREQ_RULE_ANY,
- .height = ISP_FREQ_RULE_ANY,
- .fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_400MHZ,
.run_mode = ATOMISP_RUN_MODE_PREVIEW,
},
- {
- .width = ISP_FREQ_RULE_ANY,
- .height = ISP_FREQ_RULE_ANY,
- .fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_457MHZ,
- .run_mode = ATOMISP_RUN_MODE_SDV,
- },
};
/* Merrifield and Moorefield DFS rules */
@@ -171,22 +158,8 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr_1179[] = {
.height = ISP_FREQ_RULE_ANY,
.fps = ISP_FREQ_RULE_ANY,
.isp_freq = ISP_FREQ_400MHZ,
- .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE,
- },
- {
- .width = ISP_FREQ_RULE_ANY,
- .height = ISP_FREQ_RULE_ANY,
- .fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_400MHZ,
.run_mode = ATOMISP_RUN_MODE_PREVIEW,
},
- {
- .width = ISP_FREQ_RULE_ANY,
- .height = ISP_FREQ_RULE_ANY,
- .fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_400MHZ,
- .run_mode = ATOMISP_RUN_MODE_SDV,
- },
};
static const struct atomisp_dfs_config dfs_config_merr_1179 = {
@@ -251,23 +224,9 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr_117a[] = {
.width = ISP_FREQ_RULE_ANY,
.height = ISP_FREQ_RULE_ANY,
.fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_400MHZ,
- .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE,
- },
- {
- .width = ISP_FREQ_RULE_ANY,
- .height = ISP_FREQ_RULE_ANY,
- .fps = ISP_FREQ_RULE_ANY,
.isp_freq = ISP_FREQ_200MHZ,
.run_mode = ATOMISP_RUN_MODE_PREVIEW,
},
- {
- .width = ISP_FREQ_RULE_ANY,
- .height = ISP_FREQ_RULE_ANY,
- .fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_400MHZ,
- .run_mode = ATOMISP_RUN_MODE_SDV,
- },
};
static struct atomisp_dfs_config dfs_config_merr_117a = {
@@ -298,22 +257,8 @@ static const struct atomisp_freq_scaling_rule dfs_rules_byt[] = {
.height = ISP_FREQ_RULE_ANY,
.fps = ISP_FREQ_RULE_ANY,
.isp_freq = ISP_FREQ_400MHZ,
- .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE,
- },
- {
- .width = ISP_FREQ_RULE_ANY,
- .height = ISP_FREQ_RULE_ANY,
- .fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_400MHZ,
.run_mode = ATOMISP_RUN_MODE_PREVIEW,
},
- {
- .width = ISP_FREQ_RULE_ANY,
- .height = ISP_FREQ_RULE_ANY,
- .fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_400MHZ,
- .run_mode = ATOMISP_RUN_MODE_SDV,
- },
};
static const struct atomisp_dfs_config dfs_config_byt = {
@@ -344,29 +289,8 @@ static const struct atomisp_freq_scaling_rule dfs_rules_cht[] = {
.height = ISP_FREQ_RULE_ANY,
.fps = ISP_FREQ_RULE_ANY,
.isp_freq = ISP_FREQ_320MHZ,
- .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE,
- },
- {
- .width = ISP_FREQ_RULE_ANY,
- .height = ISP_FREQ_RULE_ANY,
- .fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_320MHZ,
.run_mode = ATOMISP_RUN_MODE_PREVIEW,
},
- {
- .width = 1280,
- .height = 720,
- .fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_320MHZ,
- .run_mode = ATOMISP_RUN_MODE_SDV,
- },
- {
- .width = ISP_FREQ_RULE_ANY,
- .height = ISP_FREQ_RULE_ANY,
- .fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_356MHZ,
- .run_mode = ATOMISP_RUN_MODE_SDV,
- },
};
static const struct atomisp_freq_scaling_rule dfs_rules_cht_soc[] = {
@@ -389,22 +313,8 @@ static const struct atomisp_freq_scaling_rule dfs_rules_cht_soc[] = {
.height = ISP_FREQ_RULE_ANY,
.fps = ISP_FREQ_RULE_ANY,
.isp_freq = ISP_FREQ_320MHZ,
- .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE,
- },
- {
- .width = ISP_FREQ_RULE_ANY,
- .height = ISP_FREQ_RULE_ANY,
- .fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_320MHZ,
.run_mode = ATOMISP_RUN_MODE_PREVIEW,
},
- {
- .width = ISP_FREQ_RULE_ANY,
- .height = ISP_FREQ_RULE_ANY,
- .fps = ISP_FREQ_RULE_ANY,
- .isp_freq = ISP_FREQ_356MHZ,
- .run_mode = ATOMISP_RUN_MODE_SDV,
- },
};
static const struct atomisp_dfs_config dfs_config_cht = {
@@ -424,34 +334,22 @@ const struct atomisp_dfs_config dfs_config_cht_soc = {
.dfs_table_size = ARRAY_SIZE(dfs_rules_cht_soc),
};
-int atomisp_video_init(struct atomisp_video_pipe *video, const char *name,
- unsigned int run_mode)
+int atomisp_video_init(struct atomisp_video_pipe *video)
{
int ret;
- const char *direction;
-
- switch (video->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- direction = "output";
- video->pad.flags = MEDIA_PAD_FL_SINK;
- video->vdev.fops = &atomisp_fops;
- video->vdev.ioctl_ops = &atomisp_ioctl_ops;
- video->vdev.lock = &video->isp->mutex;
- break;
- default:
- return -EINVAL;
- }
+ video->pad.flags = MEDIA_PAD_FL_SINK;
ret = media_entity_pads_init(&video->vdev.entity, 1, &video->pad);
if (ret < 0)
return ret;
/* Initialize the video device. */
- snprintf(video->vdev.name, sizeof(video->vdev.name),
- "ATOMISP ISP %s %s", name, direction);
+ strscpy(video->vdev.name, "ATOMISP video output", sizeof(video->vdev.name));
+ video->vdev.fops = &atomisp_fops;
+ video->vdev.ioctl_ops = &atomisp_ioctl_ops;
+ video->vdev.lock = &video->isp->mutex;
video->vdev.release = video_device_release_empty;
video_set_drvdata(&video->vdev, video->isp);
- video->default_run_mode = run_mode;
return 0;
}
@@ -755,15 +653,9 @@ static int atomisp_suspend(struct device *dev)
dev_get_drvdata(dev);
unsigned long flags;
- /*
- * FIXME: Suspend is not supported by sensors. Abort if any video
- * node was opened.
- */
- if (atomisp_dev_users(isp))
- return -EBUSY;
-
+ /* FIXME: Suspend is not supported by sensors. Abort if streaming. */
spin_lock_irqsave(&isp->lock, flags);
- if (isp->asd.streaming != ATOMISP_DEVICE_STREAMING_DISABLED) {
+ if (isp->asd.streaming) {
spin_unlock_irqrestore(&isp->lock, flags);
dev_err(isp->dev, "atomisp cannot suspend at this time.\n");
return -EINVAL;
@@ -772,12 +664,25 @@ static int atomisp_suspend(struct device *dev)
pm_runtime_resume(dev);
+ isp->asd.recreate_streams_on_resume = isp->asd.stream_prepared;
+ atomisp_destroy_pipes_stream(&isp->asd);
+
return atomisp_power_off(dev);
}
static int atomisp_resume(struct device *dev)
{
- return atomisp_power_on(dev);
+ struct atomisp_device *isp = dev_get_drvdata(dev);
+ int ret;
+
+ ret = atomisp_power_on(dev);
+ if (ret)
+ return ret;
+
+ if (isp->asd.recreate_streams_on_resume)
+ ret = atomisp_create_pipes_stream(&isp->asd);
+
+ return ret;
}
int atomisp_csi_lane_config(struct atomisp_device *isp)
@@ -785,7 +690,7 @@ int atomisp_csi_lane_config(struct atomisp_device *isp)
struct pci_dev *pdev = to_pci_dev(isp->dev);
static const struct {
u8 code;
- u8 lanes[MRFLD_PORT_NUM];
+ u8 lanes[N_MIPI_PORT_ID];
} portconfigs[] = {
/* Tangier/Merrifield available lane configurations */
{ 0x00, { 4, 1, 0 } }, /* 00000 */
@@ -809,7 +714,6 @@ int atomisp_csi_lane_config(struct atomisp_device *isp)
};
unsigned int i, j;
- u8 sensor_lanes[MRFLD_PORT_NUM] = { 0 };
u32 csi_control;
int nportconfigs;
u32 port_config_mask;
@@ -837,41 +741,13 @@ int atomisp_csi_lane_config(struct atomisp_device *isp)
nportconfigs = ARRAY_SIZE(portconfigs);
}
- for (i = 0; i < isp->input_cnt; i++) {
- struct camera_mipi_info *mipi_info;
-
- if (isp->inputs[i].type != RAW_CAMERA)
- continue;
-
- mipi_info = atomisp_to_sensor_mipi_info(isp->inputs[i].camera);
- if (!mipi_info)
- continue;
-
- switch (mipi_info->port) {
- case ATOMISP_CAMERA_PORT_PRIMARY:
- sensor_lanes[0] = mipi_info->num_lanes;
- break;
- case ATOMISP_CAMERA_PORT_SECONDARY:
- sensor_lanes[1] = mipi_info->num_lanes;
- break;
- case ATOMISP_CAMERA_PORT_TERTIARY:
- sensor_lanes[2] = mipi_info->num_lanes;
- break;
- default:
- dev_err(isp->dev,
- "%s: invalid port: %d for the %dth sensor\n",
- __func__, mipi_info->port, i);
- return -EINVAL;
- }
- }
-
for (i = 0; i < nportconfigs; i++) {
- for (j = 0; j < MRFLD_PORT_NUM; j++)
- if (sensor_lanes[j] &&
- sensor_lanes[j] != portconfigs[i].lanes[j])
+ for (j = 0; j < N_MIPI_PORT_ID; j++)
+ if (isp->sensor_lanes[j] &&
+ isp->sensor_lanes[j] != portconfigs[i].lanes[j])
break;
- if (j == MRFLD_PORT_NUM)
+ if (j == N_MIPI_PORT_ID)
break; /* Found matching setting */
}
@@ -879,7 +755,7 @@ int atomisp_csi_lane_config(struct atomisp_device *isp)
dev_err(isp->dev,
"%s: could not find the CSI port setting for %d-%d-%d\n",
__func__,
- sensor_lanes[0], sensor_lanes[1], sensor_lanes[2]);
+ isp->sensor_lanes[0], isp->sensor_lanes[1], isp->sensor_lanes[2]);
return -EINVAL;
}
@@ -907,7 +783,11 @@ static int atomisp_subdev_probe(struct atomisp_device *isp)
{
const struct atomisp_platform_data *pdata;
struct intel_v4l2_subdev_table *subdevs;
- int ret, raw_index = -1, count;
+ int ret, mipi_port;
+
+ ret = atomisp_csi2_bridge_parse_firmware(isp);
+ if (ret)
+ return ret;
pdata = atomisp_get_platform_data();
if (!pdata) {
@@ -915,23 +795,12 @@ static int atomisp_subdev_probe(struct atomisp_device *isp)
return 0;
}
- /* FIXME: should return -EPROBE_DEFER if not all subdevs were probed */
- for (count = 0; count < SUBDEV_WAIT_TIMEOUT_MAX_COUNT; count++) {
- int camera_count = 0;
-
- for (subdevs = pdata->subdevs; subdevs->type; ++subdevs) {
- if (subdevs->type == RAW_CAMERA)
- camera_count++;
- }
- if (camera_count)
- break;
- msleep(SUBDEV_WAIT_TIMEOUT);
- }
- /* Wait more time to give more time for subdev init code to finish */
- msleep(5 * SUBDEV_WAIT_TIMEOUT);
-
- /* FIXME: should, instead, use I2C probe */
-
+ /*
+ * TODO: this is left here for now to allow testing atomisp-sensor
+ * drivers which are still using the atomisp_gmin_platform infra before
+ * converting them to standard v4l2 sensor drivers using runtime-pm +
+ * ACPI for pm and v4l2_async_register_subdev_sensor() registration.
+ */
for (subdevs = pdata->subdevs; subdevs->type; ++subdevs) {
ret = v4l2_device_register_subdev(&isp->v4l2_dev, subdevs->subdev);
if (ret)
@@ -939,25 +808,20 @@ static int atomisp_subdev_probe(struct atomisp_device *isp)
switch (subdevs->type) {
case RAW_CAMERA:
- dev_dbg(isp->dev, "raw_index: %d\n", raw_index);
- raw_index = isp->input_cnt;
- if (isp->input_cnt >= ATOM_ISP_MAX_INPUTS) {
- dev_warn(isp->dev,
- "too many atomisp inputs, ignored\n");
+ if (subdevs->port >= ATOMISP_CAMERA_NR_PORTS) {
+ dev_err(isp->dev, "port %d not supported\n", subdevs->port);
+ break;
+ }
+
+ if (isp->sensor_subdevs[subdevs->port]) {
+ dev_err(isp->dev, "port %d already has a sensor attached\n",
+ subdevs->port);
break;
}
- isp->inputs[isp->input_cnt].type = subdevs->type;
- isp->inputs[isp->input_cnt].port = subdevs->port;
- isp->inputs[isp->input_cnt].camera = subdevs->subdev;
- isp->inputs[isp->input_cnt].sensor_index = 0;
- /*
- * initialize the subdev frame size, then next we can
- * judge whether frame_size store effective value via
- * pixel_format.
- */
- isp->inputs[isp->input_cnt].frame_size.pixel_format = 0;
- isp->input_cnt++;
+ mipi_port = atomisp_port_to_mipi_port(isp, subdevs->port);
+ isp->sensor_lanes[mipi_port] = subdevs->lanes;
+ isp->sensor_subdevs[subdevs->port] = subdevs->subdev;
break;
case CAMERA_MOTOR:
if (isp->motor) {
@@ -979,21 +843,6 @@ static int atomisp_subdev_probe(struct atomisp_device *isp)
}
}
- /*
- * HACK: Currently VCM belongs to primary sensor only, but correct
- * approach must be to acquire from platform code which sensor
- * owns it.
- */
- if (isp->motor && raw_index >= 0)
- isp->inputs[raw_index].motor = isp->motor;
-
- /* Proceed even if no modules detected. For COS mode and no modules. */
- if (!isp->input_cnt)
- dev_warn(isp->dev, "no camera attached or fail to detect\n");
- else
- dev_info(isp->dev, "detected %d camera sensors\n",
- isp->input_cnt);
-
return atomisp_csi_lane_config(isp);
}
@@ -1067,29 +916,8 @@ static int atomisp_register_entities(struct atomisp_device *isp)
goto subdev_register_failed;
}
- for (i = 0; i < isp->input_cnt; i++) {
- if (isp->inputs[i].port >= ATOMISP_CAMERA_NR_PORTS) {
- dev_err(isp->dev, "isp->inputs port %d not supported\n",
- isp->inputs[i].port);
- ret = -EINVAL;
- goto link_failed;
- }
- }
-
- if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) {
- dev_dbg(isp->dev,
- "TPG detected, camera_cnt: %d\n", isp->input_cnt);
- isp->inputs[isp->input_cnt].type = TEST_PATTERN;
- isp->inputs[isp->input_cnt].port = -1;
- isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd;
- } else {
- dev_warn(isp->dev, "too many atomisp inputs, TPG ignored.\n");
- }
-
return 0;
-link_failed:
- atomisp_subdev_unregister_entities(&isp->asd);
subdev_register_failed:
atomisp_tpg_unregister_entities(&isp->tpg);
tpg_register_failed:
@@ -1103,15 +931,152 @@ v4l2_device_failed:
return ret;
}
-static int atomisp_register_device_nodes(struct atomisp_device *isp)
+static void atomisp_init_sensor(struct atomisp_input_subdev *input)
+{
+ struct v4l2_subdev_mbus_code_enum mbus_code_enum = { };
+ struct v4l2_subdev_frame_size_enum fse = { };
+ struct v4l2_subdev_state sd_state = {
+ .pads = &input->pad_cfg,
+ };
+ struct v4l2_subdev_selection sel = { };
+ int i, err;
+
+ mbus_code_enum.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ err = v4l2_subdev_call(input->camera, pad, enum_mbus_code, NULL, &mbus_code_enum);
+ if (!err)
+ input->code = mbus_code_enum.code;
+
+ sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ sel.target = V4L2_SEL_TGT_NATIVE_SIZE;
+ err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel);
+ if (err)
+ return;
+
+ input->native_rect = sel.r;
+
+ sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ sel.target = V4L2_SEL_TGT_CROP_DEFAULT;
+ err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel);
+ if (err)
+ return;
+
+ input->active_rect = sel.r;
+
+ /*
+ * Check for a framesize with half active_rect width and height,
+ * if found assume the sensor supports binning.
+ * Do this before changing the crop-rect since that may influence
+ * enum_frame_size results.
+ */
+ for (i = 0; ; i++) {
+ fse.index = i;
+ fse.code = input->code;
+ fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+
+ err = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse);
+ if (err)
+ break;
+
+ if (fse.min_width <= (input->active_rect.width / 2) &&
+ fse.min_height <= (input->active_rect.height / 2)) {
+ input->binning_support = true;
+ break;
+ }
+ }
+
+ /*
+ * The ISP also wants the non-active pixels at the border of the sensor
+ * for padding, set the crop rect to cover the entire sensor instead
+ * of only the default active area.
+ *
+ * Do this for both try and active formats since the try_crop rect in
+ * pad_cfg may influence (clamp) future try_fmt calls with which == try.
+ */
+ sel.which = V4L2_SUBDEV_FORMAT_TRY;
+ sel.target = V4L2_SEL_TGT_CROP;
+ sel.r = input->native_rect;
+ err = v4l2_subdev_call(input->camera, pad, set_selection, &sd_state, &sel);
+ if (err)
+ return;
+
+ sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ sel.target = V4L2_SEL_TGT_CROP;
+ sel.r = input->native_rect;
+ err = v4l2_subdev_call(input->camera, pad, set_selection, NULL, &sel);
+ if (err)
+ return;
+
+ dev_info(input->camera->dev, "Supports crop native %dx%d active %dx%d binning %d\n",
+ input->native_rect.width, input->native_rect.height,
+ input->active_rect.width, input->active_rect.height,
+ input->binning_support);
+
+ input->crop_support = true;
+}
+
+int atomisp_register_device_nodes(struct atomisp_device *isp)
{
- int err;
+ struct atomisp_input_subdev *input;
+ int i, err;
+
+ for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
+ err = media_create_pad_link(&isp->csi2_port[i].subdev.entity,
+ CSI2_PAD_SOURCE, &isp->asd.subdev.entity,
+ ATOMISP_SUBDEV_PAD_SINK, 0);
+ if (err)
+ return err;
+
+ if (!isp->sensor_subdevs[i])
+ continue;
- err = atomisp_subdev_register_video_nodes(&isp->asd, &isp->v4l2_dev);
+ input = &isp->inputs[isp->input_cnt];
+
+ input->type = RAW_CAMERA;
+ input->port = i;
+ input->camera = isp->sensor_subdevs[i];
+
+ atomisp_init_sensor(input);
+
+ /*
+ * HACK: Currently VCM belongs to primary sensor only, but correct
+ * approach must be to acquire from platform code which sensor
+ * owns it.
+ */
+ if (i == ATOMISP_CAMERA_PORT_PRIMARY)
+ input->motor = isp->motor;
+
+ err = media_create_pad_link(&input->camera->entity, 0,
+ &isp->csi2_port[i].subdev.entity,
+ CSI2_PAD_SINK,
+ MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+ if (err)
+ return err;
+
+ isp->input_cnt++;
+ }
+
+ if (!isp->input_cnt)
+ dev_warn(isp->dev, "no camera attached or fail to detect\n");
+ else
+ dev_info(isp->dev, "detected %d camera sensors\n", isp->input_cnt);
+
+ if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) {
+ dev_dbg(isp->dev, "TPG detected, camera_cnt: %d\n", isp->input_cnt);
+ isp->inputs[isp->input_cnt].type = TEST_PATTERN;
+ isp->inputs[isp->input_cnt].port = -1;
+ isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd;
+ } else {
+ dev_warn(isp->dev, "too many atomisp inputs, TPG ignored.\n");
+ }
+
+ isp->asd.video_out.vdev.v4l2_dev = &isp->v4l2_dev;
+ isp->asd.video_out.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+ err = video_register_device(&isp->asd.video_out.vdev, VFL_TYPE_VIDEO, -1);
if (err)
return err;
- err = atomisp_create_pads_links(isp);
+ err = media_create_pad_link(&isp->asd.subdev.entity, ATOMISP_SUBDEV_PAD_SOURCE,
+ &isp->asd.video_out.vdev.entity, 0, 0);
if (err)
return err;
@@ -1543,9 +1508,11 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
isp->firmware = NULL;
isp->css_env.isp_css_fw.data = NULL;
- err = atomisp_register_device_nodes(isp);
- if (err)
+ err = v4l2_async_nf_register(&isp->v4l2_dev, &isp->notifier);
+ if (err) {
+ dev_err(isp->dev, "failed to register async notifier : %d\n", err);
goto css_init_fail;
+ }
atomisp_drvfs_init(isp);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.h b/drivers/staging/media/atomisp/pci/atomisp_v4l2.h
index ccf1c0ac17b2..fad9573374b3 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.h
@@ -26,10 +26,10 @@ struct v4l2_device;
struct atomisp_device;
struct firmware;
-int atomisp_video_init(struct atomisp_video_pipe *video, const char *name,
- unsigned int run_mode);
+int atomisp_video_init(struct atomisp_video_pipe *video);
void atomisp_video_unregister(struct atomisp_video_pipe *video);
const struct firmware *atomisp_load_firmware(struct atomisp_device *isp);
int atomisp_csi_lane_config(struct atomisp_device *isp);
+int atomisp_register_device_nodes(struct atomisp_device *isp);
#endif /* __ATOMISP_V4L2_H__ */
diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h b/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h
index 700070c58eda..90c17884968b 100644
--- a/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h
+++ b/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h
@@ -138,4 +138,6 @@ bool ia_css_frame_is_same_type(
int ia_css_dma_configure_from_info(struct dma_port_config *config,
const struct ia_css_frame_info *info);
+unsigned int ia_css_frame_pad_width(unsigned int width, enum ia_css_frame_format format);
+
#endif /* __IA_CSS_FRAME_H__ */
diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c
index 83bb42e05421..2d7fddb114f6 100644
--- a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c
+++ b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c
@@ -269,6 +269,34 @@ int ia_css_frame_init_planes(struct ia_css_frame *frame)
return 0;
}
+unsigned int ia_css_frame_pad_width(unsigned int width, enum ia_css_frame_format format)
+{
+ switch (format) {
+ /*
+ * Frames with a U and V plane of 8 bits per pixel need to have
+ * all planes aligned, this means double the alignment for the
+ * Y plane if the horizontal decimation is 2.
+ */
+ case IA_CSS_FRAME_FORMAT_YUV420:
+ case IA_CSS_FRAME_FORMAT_YV12:
+ case IA_CSS_FRAME_FORMAT_NV12:
+ case IA_CSS_FRAME_FORMAT_NV21:
+ case IA_CSS_FRAME_FORMAT_BINARY_8:
+ case IA_CSS_FRAME_FORMAT_YUV_LINE:
+ return CEIL_MUL(width, 2 * HIVE_ISP_DDR_WORD_BYTES);
+
+ case IA_CSS_FRAME_FORMAT_NV12_TILEY:
+ return CEIL_MUL(width, NV12_TILEY_TILE_WIDTH);
+
+ case IA_CSS_FRAME_FORMAT_RAW:
+ case IA_CSS_FRAME_FORMAT_RAW_PACKED:
+ return CEIL_MUL(width, 2 * ISP_VEC_NELEMS);
+
+ default:
+ return CEIL_MUL(width, HIVE_ISP_DDR_WORD_BYTES);
+ }
+}
+
void ia_css_frame_info_set_width(struct ia_css_frame_info *info,
unsigned int width,
unsigned int min_padded_width)
@@ -285,25 +313,8 @@ void ia_css_frame_info_set_width(struct ia_css_frame_info *info,
align = max(min_padded_width, width);
info->res.width = width;
- /* frames with a U and V plane of 8 bits per pixel need to have
- all planes aligned, this means double the alignment for the
- Y plane if the horizontal decimation is 2. */
- if (info->format == IA_CSS_FRAME_FORMAT_YUV420 ||
- info->format == IA_CSS_FRAME_FORMAT_YV12 ||
- info->format == IA_CSS_FRAME_FORMAT_NV12 ||
- info->format == IA_CSS_FRAME_FORMAT_NV21 ||
- info->format == IA_CSS_FRAME_FORMAT_BINARY_8 ||
- info->format == IA_CSS_FRAME_FORMAT_YUV_LINE)
- info->padded_width =
- CEIL_MUL(align, 2 * HIVE_ISP_DDR_WORD_BYTES);
- else if (info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY)
- info->padded_width = CEIL_MUL(align, NV12_TILEY_TILE_WIDTH);
- else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
- info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED)
- info->padded_width = CEIL_MUL(align, 2 * ISP_VEC_NELEMS);
- else {
- info->padded_width = CEIL_MUL(align, HIVE_ISP_DDR_WORD_BYTES);
- }
+ info->padded_width = ia_css_frame_pad_width(align, info->format);
+
IA_CSS_LEAVE_PRIVATE("");
}
@@ -601,9 +612,6 @@ static void frame_init_qplane6_planes(struct ia_css_frame *frame)
static int frame_allocate_buffer_data(struct ia_css_frame *frame)
{
-#ifdef ISP2401
- IA_CSS_ENTER_LEAVE_PRIVATE("frame->data_bytes=%d\n", frame->data_bytes);
-#endif
frame->data = hmm_alloc(frame->data_bytes);
if (frame->data == mmgr_NULL)
return -ENOMEM;
@@ -635,15 +643,11 @@ static int frame_allocate_with_data(struct ia_css_frame **frame,
if (err) {
kvfree(me);
-#ifndef ISP2401
- return err;
-#else
- me = NULL;
-#endif
+ *frame = NULL;
+ } else {
+ *frame = me;
}
- *frame = me;
-
return err;
}
diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c
index 93789500416f..4b3fa6d93fe0 100644
--- a/drivers/staging/media/atomisp/pci/sh_css.c
+++ b/drivers/staging/media/atomisp/pci/sh_css.c
@@ -1529,15 +1529,14 @@ ia_css_init(struct device *dev, const struct ia_css_env *env,
mipi_init();
-#ifndef ISP2401
/*
* In case this has been programmed already, update internal
* data structure ...
* DEPRECATED
*/
- my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID);
+ if (!IS_ISP2401)
+ my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID);
-#endif
my_css.irq_type = irq_type;
my_css_save.irq_type = irq_type;
@@ -1596,10 +1595,8 @@ ia_css_init(struct device *dev, const struct ia_css_env *env,
* sh_css_init_buffer_queues();
*/
-#if defined(ISP2401)
- gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1);
-#endif
-
+ if (IS_ISP2401)
+ gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1);
if (!IS_ISP2401)
dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
@@ -2128,13 +2125,8 @@ ia_css_pipe_destroy(struct ia_css_pipe *pipe)
err);
}
}
-#ifndef ISP2401
ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES,
pipe->pipe_settings.video.tnr_frames);
-#else
- ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES,
- pipe->pipe_settings.video.tnr_frames);
-#endif
ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
pipe->pipe_settings.video.delay_frames);
break;
@@ -2238,11 +2230,10 @@ int ia_css_irq_translate(
case virq_isys_csi:
infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR;
break;
-#if !defined(ISP2401)
case virq_ifmt0_id:
- infos |= IA_CSS_IRQ_INFO_IF_ERROR;
+ if (!IS_ISP2401)
+ infos |= IA_CSS_IRQ_INFO_IF_ERROR;
break;
-#endif
case virq_dma:
infos |= IA_CSS_IRQ_INFO_DMA_ERROR;
break;
@@ -2277,27 +2268,34 @@ int ia_css_irq_enable(
IA_CSS_ENTER("info=%d, enable=%d", info, enable);
switch (info) {
-#if !defined(ISP2401)
case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
+ if (IS_ISP2401)
+ /* Just ignore those unused IRQs without printing errors */
+ return 0;
+
irq = virq_isys_sof;
break;
case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
+ if (IS_ISP2401)
+ /* Just ignore those unused IRQs without printing errors */
+ return 0;
+
irq = virq_isys_eof;
break;
case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
+ if (IS_ISP2401)
+ /* Just ignore those unused IRQs without printing errors */
+ return 0;
+
irq = virq_isys_csi;
break;
case IA_CSS_IRQ_INFO_IF_ERROR:
+ if (IS_ISP2401)
+ /* Just ignore those unused IRQs without printing errors */
+ return 0;
+
irq = virq_ifmt0_id;
break;
-#else
- case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
- case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
- case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
- case IA_CSS_IRQ_INFO_IF_ERROR:
- /* Just ignore those unused IRQs without printing errors */
- return 0;
-#endif
case IA_CSS_IRQ_INFO_DMA_ERROR:
irq = virq_dma;
break;
@@ -2413,14 +2411,14 @@ alloc_continuous_frames(struct ia_css_pipe *pipe, bool init_time)
return -EINVAL;
}
-#if defined(ISP2401)
- /* For CSI2+, the continuous frame will hold the full input frame */
- ref_info.res.width = pipe->stream->config.input_config.input_res.width;
- ref_info.res.height = pipe->stream->config.input_config.input_res.height;
+ if (IS_ISP2401) {
+ /* For CSI2+, the continuous frame will hold the full input frame */
+ ref_info.res.width = pipe->stream->config.input_config.input_res.width;
+ ref_info.res.height = pipe->stream->config.input_config.input_res.height;
- /* Ensure padded width is aligned for 2401 */
- ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS);
-#endif
+ /* Ensure padded width is aligned for 2401 */
+ ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS);
+ }
if (pipe->stream->config.pack_raw_pixels) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
@@ -2499,11 +2497,9 @@ load_preview_binaries(struct ia_css_pipe *pipe)
int err = 0;
bool need_vf_pp = false;
bool need_isp_copy_binary = false;
-#ifdef ISP2401
bool sensor = false;
-#else
bool continuous;
-#endif
+
/* preview only have 1 output pin now */
struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0];
struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview;
@@ -2514,11 +2510,9 @@ load_preview_binaries(struct ia_css_pipe *pipe)
assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW);
online = pipe->stream->config.online;
-#ifdef ISP2401
+
sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
-#else
continuous = pipe->stream->config.continuous;
-#endif
if (mycs->preview_binary.info)
return 0;
@@ -2627,24 +2621,22 @@ load_preview_binaries(struct ia_css_pipe *pipe)
return err;
}
-#ifdef ISP2401
- /*
- * When the input system is 2401, only the Direct Sensor Mode
- * Offline Preview uses the ISP copy binary.
- */
- need_isp_copy_binary = !online && sensor;
-#else
- /*
- * About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY:
- * This is typical the case with SkyCam (which has no input system) but it also applies to all cases
- * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical
- * copies sensor data to DDR) does not have much use.
- */
- if (!IS_ISP2401)
+ if (IS_ISP2401) {
+ /*
+ * When the input system is 2401, only the Direct Sensor Mode
+ * Offline Preview uses the ISP copy binary.
+ */
+ need_isp_copy_binary = !online && sensor;
+ } else {
+ /*
+ * About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY:
+ * This is typical the case with SkyCam (which has no input system) but it also
+ * applies to all cases where the driver chooses for memory based input frames.
+ * In these cases, a copy binary (which typical copies sensor data to DDR) does
+ * not have much use.
+ */
need_isp_copy_binary = !online && !continuous;
- else
- need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY);
-#endif
+ }
/* Copy */
if (need_isp_copy_binary) {
@@ -3125,11 +3117,10 @@ init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
in_frame->frame_info.format = format;
-#ifdef ISP2401
- if (format == IA_CSS_FRAME_FORMAT_RAW)
+ if (IS_ISP2401 && format == IA_CSS_FRAME_FORMAT_RAW) {
in_frame->frame_info.format = (pipe->stream->config.pack_raw_pixels) ?
IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW;
-#endif
+ }
in_frame->frame_info.res.width = pipe->stream->config.input_config.input_res.width;
in_frame->frame_info.res.height = pipe->stream->config.input_config.input_res.height;
@@ -3211,18 +3202,18 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe)
me->dvs_frame_delay = pipe->dvs_frame_delay;
-#ifdef ISP2401
- /*
- * When the input system is 2401, always enable 'in_frameinfo_memory'
- * except for the following: online or continuous
- */
- need_in_frameinfo_memory = !(pipe->stream->config.online ||
- pipe->stream->config.continuous);
-#else
- /* Construct in_frame info (only in case we have dynamic input */
- need_in_frameinfo_memory = pipe->stream->config.mode ==
- IA_CSS_INPUT_MODE_MEMORY;
-#endif
+ if (IS_ISP2401) {
+ /*
+ * When the input system is 2401, always enable 'in_frameinfo_memory'
+ * except for the following: online or continuous
+ */
+ need_in_frameinfo_memory = !(pipe->stream->config.online ||
+ pipe->stream->config.continuous);
+ } else {
+ /* Construct in_frame info (only in case we have dynamic input */
+ need_in_frameinfo_memory = pipe->stream->config.mode ==
+ IA_CSS_INPUT_MODE_MEMORY;
+ }
/* Construct in_frame info (only in case we have dynamic input */
if (need_in_frameinfo_memory) {
@@ -3268,15 +3259,14 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe)
goto ERR;
in_frame = me->stages->args.out_frame[0];
} else if (pipe->stream->config.continuous) {
-#ifdef ISP2401
- /*
- * When continuous is enabled, configure in_frame with the
- * last pipe, which is the copy pipe.
- */
- in_frame = pipe->stream->last_pipe->continuous_frames[0];
-#else
- in_frame = pipe->continuous_frames[0];
-#endif
+ if (IS_ISP2401)
+ /*
+ * When continuous is enabled, configure in_frame with the
+ * last pipe, which is the copy pipe.
+ */
+ in_frame = pipe->stream->last_pipe->continuous_frames[0];
+ else
+ in_frame = pipe->continuous_frames[0];
}
ia_css_pipe_util_set_output_frames(out_frames, 0,
@@ -3373,12 +3363,10 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe)
struct ia_css_frame *out_frame;
struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
bool need_in_frameinfo_memory = false;
-#ifdef ISP2401
bool sensor = false;
bool buffered_sensor = false;
bool online = false;
bool continuous = false;
-#endif
IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
@@ -3391,25 +3379,26 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe)
me = &pipe->pipeline;
ia_css_pipeline_clean(me);
-#ifdef ISP2401
- /*
- * When the input system is 2401, always enable 'in_frameinfo_memory'
- * except for the following:
- * - Direct Sensor Mode Online Preview
- * - Buffered Sensor Mode Online Preview
- * - Direct Sensor Mode Continuous Preview
- * - Buffered Sensor Mode Continuous Preview
- */
- sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
- buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
- online = pipe->stream->config.online;
- continuous = pipe->stream->config.continuous;
- need_in_frameinfo_memory =
- !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
-#else
- /* Construct in_frame info (only in case we have dynamic input */
- need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
-#endif
+ if (IS_ISP2401) {
+ /*
+ * When the input system is 2401, always enable 'in_frameinfo_memory'
+ * except for the following:
+ * - Direct Sensor Mode Online Preview
+ * - Buffered Sensor Mode Online Preview
+ * - Direct Sensor Mode Continuous Preview
+ * - Buffered Sensor Mode Continuous Preview
+ */
+ sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
+ buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
+ online = pipe->stream->config.online;
+ continuous = pipe->stream->config.continuous;
+ need_in_frameinfo_memory =
+ !((sensor && (online || continuous)) || (buffered_sensor &&
+ (online || continuous)));
+ } else {
+ /* Construct in_frame info (only in case we have dynamic input */
+ need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
+ }
if (need_in_frameinfo_memory) {
err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
IA_CSS_FRAME_FORMAT_RAW);
@@ -3420,7 +3409,6 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe)
} else {
in_frame = NULL;
}
-
err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
if (err)
goto ERR;
@@ -3441,17 +3429,16 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe)
goto ERR;
in_frame = me->stages->args.out_frame[0];
} else if (pipe->stream->config.continuous) {
-#ifdef ISP2401
- /*
- * When continuous is enabled, configure in_frame with the
- * last pipe, which is the copy pipe.
- */
- if (continuous || !online)
- in_frame = pipe->stream->last_pipe->continuous_frames[0];
-
-#else
- in_frame = pipe->continuous_frames[0];
-#endif
+ if (IS_ISP2401) {
+ /*
+ * When continuous is enabled, configure in_frame with the
+ * last pipe, which is the copy pipe.
+ */
+ if (continuous || !online)
+ in_frame = pipe->stream->last_pipe->continuous_frames[0];
+ } else {
+ in_frame = pipe->continuous_frames[0];
+ }
}
if (vf_pp_binary) {
@@ -3925,19 +3912,19 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
if (pipe && pipe->stop_requested) {
-#if !defined(ISP2401)
- /*
- * free mipi frames only for old input
- * system for 2401 it is done in
- * ia_css_stream_destroy call
- */
- return_err = free_mipi_frames(pipe);
- if (return_err) {
- IA_CSS_LOG("free_mipi_frames() failed");
- IA_CSS_LEAVE_ERR(return_err);
- return return_err;
+ if (!IS_ISP2401) {
+ /*
+ * free mipi frames only for old input
+ * system for 2401 it is done in
+ * ia_css_stream_destroy call
+ */
+ return_err = free_mipi_frames(pipe);
+ if (return_err) {
+ IA_CSS_LOG("free_mipi_frames() failed");
+ IA_CSS_LEAVE_ERR(return_err);
+ return return_err;
+ }
}
-#endif
pipe->stop_requested = false;
}
fallthrough;
@@ -3959,12 +3946,11 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
pipe->num_invalid_frames--;
if (frame->frame_info.format == IA_CSS_FRAME_FORMAT_BINARY_8) {
-#ifdef ISP2401
- frame->planes.binary.size = frame->data_bytes;
-#else
- frame->planes.binary.size =
- sh_css_sp_get_binary_copy_size();
-#endif
+ if (IS_ISP2401)
+ frame->planes.binary.size = frame->data_bytes;
+ else
+ frame->planes.binary.size =
+ sh_css_sp_get_binary_copy_size();
}
if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d",
@@ -4880,22 +4866,20 @@ static int load_video_binaries(struct ia_css_pipe *pipe)
pipe->num_invalid_frames, pipe->dvs_frame_delay);
/* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */
-#if !defined(ISP2401)
- /* Copy */
- if (!online && !continuous) {
- /*
- * TODO: what exactly needs doing, prepend the copy binary to
- * video base this only on !online?
- */
- err = load_copy_binary(pipe,
- &mycs->copy_binary,
- &mycs->video_binary);
- if (err)
- return err;
+ if (!IS_ISP2401) {
+ /* Copy */
+ if (!online && !continuous) {
+ /*
+ * TODO: what exactly needs doing, prepend the copy binary to
+ * video base this only on !online?
+ */
+ err = load_copy_binary(pipe,
+ &mycs->copy_binary,
+ &mycs->video_binary);
+ if (err)
+ return err;
+ }
}
-#else
- (void)continuous;
-#endif
if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) {
struct ia_css_binary_descr vf_pp_descr;
@@ -5227,11 +5211,8 @@ static int load_primary_binaries(
bool need_pp = false;
bool need_isp_copy_binary = false;
bool need_ldc = false;
-#ifdef ISP2401
bool sensor = false;
-#else
bool memory, continuous;
-#endif
struct ia_css_frame_info prim_in_info,
prim_out_info,
capt_pp_out_info, vf_info,
@@ -5251,12 +5232,9 @@ static int load_primary_binaries(
pipe->mode == IA_CSS_PIPE_ID_COPY);
online = pipe->stream->config.online;
-#ifdef ISP2401
sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
-#else
memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
continuous = pipe->stream->config.continuous;
-#endif
mycs = &pipe->pipe_settings.capture;
pipe_out_info = &pipe->output_info[0];
@@ -5462,15 +5440,14 @@ static int load_primary_binaries(
if (err)
return err;
-#ifdef ISP2401
- /*
- * When the input system is 2401, only the Direct Sensor Mode
- * Offline Capture uses the ISP copy binary.
- */
- need_isp_copy_binary = !online && sensor;
-#else
- need_isp_copy_binary = !online && !continuous && !memory;
-#endif
+ if (IS_ISP2401)
+ /*
+ * When the input system is 2401, only the Direct Sensor Mode
+ * Offline Capture uses the ISP copy binary.
+ */
+ need_isp_copy_binary = !online && sensor;
+ else
+ need_isp_copy_binary = !online && !continuous && !memory;
/* ISP Copy */
if (need_isp_copy_binary) {
@@ -5681,10 +5658,10 @@ static int load_advanced_binaries(struct ia_css_pipe *pipe)
}
/* Copy */
-#ifdef ISP2401
- /* For CSI2+, only the direct sensor mode/online requires ISP copy */
- need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
-#endif
+ if (IS_ISP2401)
+ /* For CSI2+, only the direct sensor mode/online requires ISP copy */
+ need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
+
if (need_isp_copy)
load_copy_binary(pipe,
&pipe->pipe_settings.capture.copy_binary,
@@ -5829,10 +5806,10 @@ static int load_low_light_binaries(struct ia_css_pipe *pipe)
}
/* Copy */
-#ifdef ISP2401
- /* For CSI2+, only the direct sensor mode/online requires ISP copy */
- need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
-#endif
+ if (IS_ISP2401)
+ /* For CSI2+, only the direct sensor mode/online requires ISP copy */
+ need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
+
if (need_isp_copy)
err = load_copy_binary(pipe,
&pipe->pipe_settings.capture.copy_binary,
@@ -5902,10 +5879,9 @@ static int load_capture_binaries(struct ia_css_pipe *pipe)
switch (pipe->config.default_capture_config.mode) {
case IA_CSS_CAPTURE_MODE_RAW:
err = load_copy_binaries(pipe);
-#if defined(ISP2401)
- if (!err)
+ if (!err && IS_ISP2401)
pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
-#endif
+
break;
case IA_CSS_CAPTURE_MODE_BAYER:
err = load_bayer_isp_binaries(pipe);
@@ -6409,7 +6385,6 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe)
else
next_binary = NULL;
-#if defined(ISP2401)
/*
* NOTES
* - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when
@@ -6427,11 +6402,11 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe)
* pp_defs.h" for the list of input-frame formats that are supported by the
* "yuv_scale_binary".
*/
- need_isp_copy_binary =
- (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8);
-#else /* !ISP2401 */
- need_isp_copy_binary = true;
-#endif /* ISP2401 */
+ if (IS_ISP2401)
+ need_isp_copy_binary =
+ (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8);
+ else
+ need_isp_copy_binary = true;
if (need_isp_copy_binary) {
err = load_copy_binary(pipe,
@@ -6678,12 +6653,10 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe)
struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
struct ia_css_pipeline_stage_desc stage_desc;
bool need_in_frameinfo_memory = false;
-#ifdef ISP2401
bool sensor = false;
bool buffered_sensor = false;
bool online = false;
bool continuous = false;
-#endif
IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
@@ -6700,24 +6673,24 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe)
num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler;
num_output_stage = pipe->pipe_settings.yuvpp.num_output;
-#ifdef ISP2401
- /*
- * When the input system is 2401, always enable 'in_frameinfo_memory'
- * except for the following:
- * - Direct Sensor Mode Online Capture
- * - Direct Sensor Mode Continuous Capture
- * - Buffered Sensor Mode Continuous Capture
- */
- sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
- buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
- online = pipe->stream->config.online;
- continuous = pipe->stream->config.continuous;
- need_in_frameinfo_memory =
- !((sensor && (online || continuous)) || (buffered_sensor && continuous));
-#else
- /* Construct in_frame info (only in case we have dynamic input */
- need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
-#endif
+ if (IS_ISP2401) {
+ /*
+ * When the input system is 2401, always enable 'in_frameinfo_memory'
+ * except for the following:
+ * - Direct Sensor Mode Online Capture
+ * - Direct Sensor Mode Continuous Capture
+ * - Buffered Sensor Mode Continuous Capture
+ */
+ sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
+ buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
+ online = pipe->stream->config.online;
+ continuous = pipe->stream->config.continuous;
+ need_in_frameinfo_memory =
+ !((sensor && (online || continuous)) || (buffered_sensor && continuous));
+ } else {
+ /* Construct in_frame info (only in case we have dynamic input */
+ need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
+ }
/*
* the input frame can come from:
*
@@ -6808,11 +6781,10 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe)
if (pipe->pipe_settings.yuvpp.copy_binary.info) {
struct ia_css_frame *in_frame_local = NULL;
-#ifdef ISP2401
- /* After isp copy is enabled in_frame needs to be passed. */
- if (!online)
+ if (IS_ISP2401 && !online) {
+ /* After isp copy is enabled in_frame needs to be passed. */
in_frame_local = in_frame;
-#endif
+ }
if (need_scaler) {
ia_css_pipe_util_set_output_frames(bin_out_frame,
@@ -7031,12 +7003,10 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe)
struct ia_css_frame *vf_frame;
struct ia_css_pipeline_stage_desc stage_desc;
bool need_in_frameinfo_memory = false;
-#ifdef ISP2401
bool sensor = false;
bool buffered_sensor = false;
bool online = false;
bool continuous = false;
-#endif
unsigned int i, num_yuv_scaler, num_primary_stage;
bool need_yuv_pp = false;
bool *is_output_stage = NULL;
@@ -7054,25 +7024,27 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe)
ia_css_pipeline_clean(me);
ia_css_pipe_util_create_output_frames(out_frames);
-#ifdef ISP2401
- /*
- * When the input system is 2401, always enable 'in_frameinfo_memory'
- * except for the following:
- * - Direct Sensor Mode Online Capture
- * - Direct Sensor Mode Online Capture
- * - Direct Sensor Mode Continuous Capture
- * - Buffered Sensor Mode Continuous Capture
- */
- sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
- buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
- online = pipe->stream->config.online;
- continuous = pipe->stream->config.continuous;
- need_in_frameinfo_memory =
- !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
-#else
- /* Construct in_frame info (only in case we have dynamic input */
- need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
-#endif
+ if (IS_ISP2401) {
+ /*
+ * When the input system is 2401, always enable 'in_frameinfo_memory'
+ * except for the following:
+ * - Direct Sensor Mode Online Capture
+ * - Direct Sensor Mode Online Capture
+ * - Direct Sensor Mode Continuous Capture
+ * - Buffered Sensor Mode Continuous Capture
+ */
+ sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
+ buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
+ online = pipe->stream->config.online;
+ continuous = pipe->stream->config.continuous;
+ need_in_frameinfo_memory =
+ !((sensor && (online || continuous)) || (buffered_sensor &&
+ (online || continuous)));
+ } else {
+ /* Construct in_frame info (only in case we have dynamic input */
+ need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
+ }
+
if (need_in_frameinfo_memory) {
err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
IA_CSS_FRAME_FORMAT_RAW);
@@ -7135,27 +7107,27 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe)
if (pipe->pipe_settings.capture.copy_binary.info) {
if (raw) {
ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
-#if defined(ISP2401)
- if (!continuous) {
- ia_css_pipe_get_generic_stage_desc(&stage_desc,
- copy_binary,
- out_frames,
- in_frame,
- NULL);
+ if (IS_ISP2401) {
+ if (!continuous) {
+ ia_css_pipe_get_generic_stage_desc(&stage_desc,
+ copy_binary,
+ out_frames,
+ in_frame,
+ NULL);
+ } else {
+ in_frame = pipe->stream->last_pipe->continuous_frames[0];
+ ia_css_pipe_get_generic_stage_desc(&stage_desc,
+ copy_binary,
+ out_frames,
+ in_frame,
+ NULL);
+ }
} else {
- in_frame = pipe->stream->last_pipe->continuous_frames[0];
ia_css_pipe_get_generic_stage_desc(&stage_desc,
copy_binary,
out_frames,
- in_frame,
- NULL);
+ NULL, NULL);
}
-#else
- ia_css_pipe_get_generic_stage_desc(&stage_desc,
- copy_binary,
- out_frames,
- NULL, NULL);
-#endif
} else {
ia_css_pipe_util_set_output_frames(out_frames, 0,
in_frame);
@@ -7185,11 +7157,7 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe)
local_in_frame = in_frame;
else
local_in_frame = NULL;
-#ifndef ISP2401
- if (!need_pp && (i == num_primary_stage - 1))
-#else
- if (!need_pp && (i == num_primary_stage - 1) && !need_ldc)
-#endif
+ if (!need_pp && (i == num_primary_stage - 1) && (!IS_ISP2401 || !need_ldc))
local_out_frame = out_frame;
else
local_out_frame = NULL;
@@ -7400,23 +7368,14 @@ static int capture_start(struct ia_css_pipe *pipe)
return err;
}
}
-
-#if !defined(ISP2401)
/* old isys: need to send_mipi_frames() in all pipe modes */
- err = send_mipi_frames(pipe);
- if (err) {
- IA_CSS_LEAVE_ERR_PRIVATE(err);
- return err;
- }
-#else
- if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) {
+ if (!IS_ISP2401 || (IS_ISP2401 && pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
err = send_mipi_frames(pipe);
if (err) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
}
-#endif
ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
copy_ovrd = 1 << thread_id;
@@ -8123,24 +8082,22 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
return err;
}
-#if !defined(ISP2401)
- /* We don't support metadata for JPEG stream, since they both use str2mem */
- if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 &&
- stream_config->metadata_config.resolution.height > 0) {
- err = -EINVAL;
- IA_CSS_LEAVE_ERR(err);
- return err;
- }
-#endif
-
-#ifdef ISP2401
- if (stream_config->online && stream_config->pack_raw_pixels) {
- IA_CSS_LOG("online and pack raw is invalid on input system 2401");
- err = -EINVAL;
- IA_CSS_LEAVE_ERR(err);
- return err;
+ if (!IS_ISP2401) {
+ /* We don't support metadata for JPEG stream, since they both use str2mem */
+ if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 &&
+ stream_config->metadata_config.resolution.height > 0) {
+ err = -EINVAL;
+ IA_CSS_LEAVE_ERR(err);
+ return err;
+ }
+ } else {
+ if (stream_config->online && stream_config->pack_raw_pixels) {
+ IA_CSS_LOG("online and pack raw is invalid on input system 2401");
+ err = -EINVAL;
+ IA_CSS_LEAVE_ERR(err);
+ return err;
+ }
}
-#endif
ia_css_debug_pipe_graph_dump_stream_config(stream_config);
@@ -8223,19 +8180,17 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
/* take over stream config */
curr_stream->config = *stream_config;
-#if defined(ISP2401)
- if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR &&
- stream_config->online)
- curr_stream->config.online = false;
-#endif
+ if (IS_ISP2401) {
+ if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR &&
+ stream_config->online)
+ curr_stream->config.online = false;
-#ifdef ISP2401
- if (curr_stream->config.online) {
- curr_stream->config.source.port.num_lanes =
- stream_config->source.port.num_lanes;
- curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
+ if (curr_stream->config.online) {
+ curr_stream->config.source.port.num_lanes =
+ stream_config->source.port.num_lanes;
+ curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
+ }
}
-#endif
/* in case driver doesn't configure init number of raw buffers, configure it here */
if (curr_stream->config.target_num_cont_raw_buf == 0)
curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES;
@@ -9162,11 +9117,10 @@ void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map)
ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
-#if defined(ISP2401)
- need_input_queue = true;
-#else
- need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
-#endif
+ if (IS_ISP2401)
+ need_input_queue = true;
+ else
+ need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
/* map required buffer queues to resources */
/* TODO: to be improved */
diff --git a/drivers/staging/media/atomisp/pci/sh_css_firmware.c b/drivers/staging/media/atomisp/pci/sh_css_firmware.c
index e7ef578db8ab..197ab2085e8d 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_firmware.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_firmware.c
@@ -56,11 +56,8 @@ static struct firmware_header *firmware_header;
* which will be replaced with the actual RELEASE_VERSION
* during package generation. Please do not modify
*/
-#ifdef ISP2401
-static const char *release_version = STR(irci_stable_candrpv_0415_20150521_0458);
-#else
-static const char *release_version = STR(irci_stable_candrpv_0415_20150423_1753);
-#endif
+static const char *release_version_2401 = STR(irci_stable_candrpv_0415_20150521_0458);
+static const char *release_version_2400 = STR(irci_stable_candrpv_0415_20150423_1753);
#define MAX_FW_REL_VER_NAME 300
static char FW_rel_ver_name[MAX_FW_REL_VER_NAME] = "---";
@@ -191,8 +188,14 @@ sh_css_load_blob_info(const char *fw, const struct ia_css_fw_info *bi,
bool
sh_css_check_firmware_version(struct device *dev, const char *fw_data)
{
+ const char *release_version;
struct sh_css_fw_bi_file_h *file_header;
+ if (IS_ISP2401)
+ release_version = release_version_2401;
+ else
+ release_version = release_version_2400;
+
firmware_header = (struct firmware_header *)fw_data;
file_header = &firmware_header->file_header;
@@ -225,15 +228,28 @@ sh_css_load_firmware(struct device *dev, const char *fw_data,
unsigned int fw_size)
{
unsigned int i;
+ const char *release_version;
struct ia_css_fw_info *binaries;
struct sh_css_fw_bi_file_h *file_header;
int ret;
+ /* some sanity checks */
+ if (!fw_data || fw_size < sizeof(struct sh_css_fw_bi_file_h))
+ return -EINVAL;
+
firmware_header = (struct firmware_header *)fw_data;
file_header = &firmware_header->file_header;
+
+ if (file_header->h_size != sizeof(struct sh_css_fw_bi_file_h))
+ return -EINVAL;
+
binaries = &firmware_header->binary_header;
strscpy(FW_rel_ver_name, file_header->version,
min(sizeof(FW_rel_ver_name), sizeof(file_header->version)));
+ if (IS_ISP2401)
+ release_version = release_version_2401;
+ else
+ release_version = release_version_2400;
ret = sh_css_check_firmware_version(dev, fw_data);
if (ret) {
IA_CSS_ERROR("CSS code version (%s) and firmware version (%s) mismatch!",
@@ -243,13 +259,6 @@ sh_css_load_firmware(struct device *dev, const char *fw_data,
IA_CSS_LOG("successfully load firmware version %s", release_version);
}
- /* some sanity checks */
- if (!fw_data || fw_size < sizeof(struct sh_css_fw_bi_file_h))
- return -EINVAL;
-
- if (file_header->h_size != sizeof(struct sh_css_fw_bi_file_h))
- return -EINVAL;
-
sh_css_num_binaries = file_header->binary_nr;
/* Only allocate memory for ISP blob info */
if (sh_css_num_binaries > NUM_OF_SPS) {
diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c
index bc6e8598a776..b20acaab0595 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c
@@ -67,13 +67,12 @@ ia_css_mipi_frame_calculate_size(const unsigned int width,
unsigned int mem_words = 0;
unsigned int width_padded = width;
-#if defined(ISP2401)
/* The changes will be reverted as soon as RAW
* Buffers are deployed by the 2401 Input System
* in the non-continuous use scenario.
*/
- width_padded += (2 * ISP_VEC_NELEMS);
-#endif
+ if (IS_ISP2401)
+ width_padded += (2 * ISP_VEC_NELEMS);
IA_CSS_ENTER("padded_width=%d, height=%d, format=%d, hasSOLandEOL=%d, embedded_data_size_words=%d\n",
width_padded, height, format, hasSOLandEOL, embedded_data_size_words);
@@ -235,7 +234,6 @@ bool mipi_is_free(void)
return true;
}
-#if defined(ISP2401)
/*
* @brief Calculate the required MIPI buffer sizes.
* Based on the stream configuration, calculate the
@@ -342,7 +340,6 @@ static int calculate_mipi_buff_size(struct ia_css_stream_config *stream_cfg,
IA_CSS_LEAVE_ERR(err);
return err;
}
-#endif
int
allocate_mipi_frames(struct ia_css_pipe *pipe,
@@ -363,15 +360,13 @@ allocate_mipi_frames(struct ia_css_pipe *pipe,
return -EINVAL;
}
-#ifdef ISP2401
- if (pipe->stream->config.online) {
+ if (IS_ISP2401 && pipe->stream->config.online) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"allocate_mipi_frames(%p) exit: no buffers needed for 2401 pipe mode.\n",
pipe);
return 0;
}
-#endif
if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"allocate_mipi_frames(%p) exit: no buffers needed for pipe mode.\n",
@@ -386,9 +381,10 @@ allocate_mipi_frames(struct ia_css_pipe *pipe,
return -EINVAL;
}
-#ifdef ISP2401
- err = calculate_mipi_buff_size(&pipe->stream->config,
- &my_css.mipi_frame_size[port]);
+ if (IS_ISP2401)
+ err = calculate_mipi_buff_size(&pipe->stream->config,
+ &my_css.mipi_frame_size[port]);
+
/*
* 2401 system allows multiple streams to use same physical port. This is not
* true for 2400 system. Currently 2401 uses MIPI buffers as a temporary solution.
@@ -396,20 +392,14 @@ allocate_mipi_frames(struct ia_css_pipe *pipe,
* In that case only 2400 related code should remain.
*/
if (ref_count_mipi_allocation[port] != 0) {
- ref_count_mipi_allocation[port]++;
+ if (IS_ISP2401)
+ ref_count_mipi_allocation[port]++;
+
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"allocate_mipi_frames(%p) leave: nothing to do, already allocated for this port (port=%d).\n",
pipe, port);
return 0;
}
-#else
- if (ref_count_mipi_allocation[port] != 0) {
- ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
- "allocate_mipi_frames(%p) exit: already allocated for this port (port=%d).\n",
- pipe, port);
- return 0;
- }
-#endif
ref_count_mipi_allocation[port]++;
@@ -503,14 +493,14 @@ free_mipi_frames(struct ia_css_pipe *pipe)
}
if (ref_count_mipi_allocation[port] > 0) {
-#if !defined(ISP2401)
- assert(ref_count_mipi_allocation[port] == 1);
- if (ref_count_mipi_allocation[port] != 1) {
- IA_CSS_ERROR("free_mipi_frames(%p) exit: wrong ref_count (ref_count=%d).",
- pipe, ref_count_mipi_allocation[port]);
- return err;
+ if (!IS_ISP2401) {
+ assert(ref_count_mipi_allocation[port] == 1);
+ if (ref_count_mipi_allocation[port] != 1) {
+ IA_CSS_ERROR("free_mipi_frames(%p) exit: wrong ref_count (ref_count=%d).",
+ pipe, ref_count_mipi_allocation[port]);
+ return err;
+ }
}
-#endif
ref_count_mipi_allocation[port]--;
@@ -534,18 +524,6 @@ free_mipi_frames(struct ia_css_pipe *pipe)
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"free_mipi_frames(%p) exit (deallocated).\n", pipe);
}
-#if defined(ISP2401)
- else {
- /* 2401 system allows multiple streams to use same physical port. This is not
- * true for 2400 system. Currently 2401 uses MIPI buffers as a temporary solution.
- * TODO AM: Once that is changed (removed) this code should be removed as well.
- * In that case only 2400 related code should remain.
- */
- ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
- "free_mipi_frames(%p) leave: nothing to do, other streams still use this port (port=%d).\n",
- pipe, port);
- }
-#endif
}
} else { /* pipe ==NULL */
/* AM TEMP: free-ing all mipi buffers just like a legacy code. */
diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c
index 0dd58a7fe2cc..297e1b981720 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_sp.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c
@@ -952,12 +952,10 @@ sh_css_sp_init_stage(struct ia_css_binary *binary,
return 0;
}
-#if defined(ISP2401)
- (void)continuous;
- sh_css_sp_stage.deinterleaved = 0;
-#else
- sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous);
-#endif
+ if (IS_ISP2401)
+ sh_css_sp_stage.deinterleaved = 0;
+ else
+ sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous);
initialize_stage_frames(&sh_css_sp_stage.frames);
/*
diff --git a/drivers/staging/media/av7110/av7110_av.c b/drivers/staging/media/av7110/av7110_av.c
index a5c5bebad306..00dd6a7fea64 100644
--- a/drivers/staging/media/av7110/av7110_av.c
+++ b/drivers/staging/media/av7110/av7110_av.c
@@ -78,7 +78,7 @@ static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, s
int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len)
{
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) p2t->priv;
+ struct dvb_demux_feed *dvbdmxfeed = p2t->priv;
if (!(dvbdmxfeed->ts_type & TS_PACKET))
return 0;
@@ -837,7 +837,7 @@ static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, s
int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len)
{
struct dvb_demux *demux = feed->demux;
- struct av7110 *av7110 = (struct av7110 *) demux->priv;
+ struct av7110 *av7110 = demux->priv;
dprintk(2, "av7110:%p, \n", av7110);
diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c
index 2d712eda2c5d..064dc562bc96 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -7,7 +7,7 @@
#include <linux/module.h>
#include "imx-media.h"
-#define IMX_BUS_FMTS(fmt...) (const u32[]) {fmt, 0}
+#define IMX_BUS_FMTS(fmt...) ((const u32[]) {fmt, 0})
/*
* List of supported pixel formats for the subdevs.
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index c07994ea6e96..ab565b4e29ec 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
+#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mc.h>
@@ -564,6 +565,49 @@ static int csi2_registered(struct v4l2_subdev *sd)
V4L2_FIELD_NONE, NULL);
}
+/* --------------- CORE OPS --------------- */
+
+static int csi2_log_status(struct v4l2_subdev *sd)
+{
+ struct csi2_dev *csi2 = sd_to_dev(sd);
+
+ v4l2_info(sd, "-----MIPI CSI status-----\n");
+ v4l2_info(sd, "VERSION: 0x%x\n",
+ readl(csi2->base + CSI2_VERSION));
+ v4l2_info(sd, "N_LANES: 0x%x\n",
+ readl(csi2->base + CSI2_N_LANES));
+ v4l2_info(sd, "PHY_SHUTDOWNZ: 0x%x\n",
+ readl(csi2->base + CSI2_PHY_SHUTDOWNZ));
+ v4l2_info(sd, "DPHY_RSTZ: 0x%x\n",
+ readl(csi2->base + CSI2_DPHY_RSTZ));
+ v4l2_info(sd, "RESETN: 0x%x\n",
+ readl(csi2->base + CSI2_RESETN));
+ v4l2_info(sd, "PHY_STATE: 0x%x\n",
+ readl(csi2->base + CSI2_PHY_STATE));
+ v4l2_info(sd, "DATA_IDS_1: 0x%x\n",
+ readl(csi2->base + CSI2_DATA_IDS_1));
+ v4l2_info(sd, "DATA_IDS_2: 0x%x\n",
+ readl(csi2->base + CSI2_DATA_IDS_2));
+ v4l2_info(sd, "ERR1: 0x%x\n",
+ readl(csi2->base + CSI2_ERR1));
+ v4l2_info(sd, "ERR2: 0x%x\n",
+ readl(csi2->base + CSI2_ERR2));
+ v4l2_info(sd, "MSK1: 0x%x\n",
+ readl(csi2->base + CSI2_MSK1));
+ v4l2_info(sd, "MSK2: 0x%x\n",
+ readl(csi2->base + CSI2_MSK2));
+ v4l2_info(sd, "PHY_TST_CTRL0: 0x%x\n",
+ readl(csi2->base + CSI2_PHY_TST_CTRL0));
+ v4l2_info(sd, "PHY_TST_CTRL1: 0x%x\n",
+ readl(csi2->base + CSI2_PHY_TST_CTRL1));
+
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops csi2_core_ops = {
+ .log_status = csi2_log_status,
+};
+
static const struct media_entity_operations csi2_entity_ops = {
.link_setup = csi2_link_setup,
.link_validate = v4l2_subdev_link_validate,
@@ -581,6 +625,7 @@ static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
};
static const struct v4l2_subdev_ops csi2_subdev_ops = {
+ .core = &csi2_core_ops,
.video = &csi2_video_ops,
.pad = &csi2_pad_ops,
};
diff --git a/drivers/staging/media/max96712/max96712.c b/drivers/staging/media/max96712/max96712.c
index 99b333b68198..c44145284aa1 100644
--- a/drivers/staging/media/max96712/max96712.c
+++ b/drivers/staging/media/max96712/max96712.c
@@ -30,6 +30,7 @@ struct max96712_priv {
struct regmap *regmap;
struct gpio_desc *gpiod_pwdn;
+ bool cphy;
struct v4l2_mbus_config_mipi_csi2 mipi;
struct v4l2_subdev sd;
@@ -127,10 +128,18 @@ static void max96712_mipi_configure(struct max96712_priv *priv)
/* Select 2x4 mode. */
max96712_write(priv, 0x8a0, 0x04);
- /* Configure a 4-lane DPHY using PHY0 and PHY1. */
/* TODO: Add support for 2-lane and 1-lane configurations. */
- /* TODO: Add support CPHY mode. */
- max96712_write(priv, 0x94a, 0xc0);
+ if (priv->cphy) {
+ /* Configure a 3-lane C-PHY using PHY0 and PHY1. */
+ max96712_write(priv, 0x94a, 0xa0);
+
+ /* Configure C-PHY timings. */
+ max96712_write(priv, 0x8ad, 0x3f);
+ max96712_write(priv, 0x8ae, 0x7d);
+ } else {
+ /* Configure a 4-lane D-PHY using PHY0 and PHY1. */
+ max96712_write(priv, 0x94a, 0xc0);
+ }
/* Configure lane mapping for PHY0 and PHY1. */
/* TODO: Add support for lane swapping. */
@@ -332,8 +341,9 @@ static int max96712_parse_dt(struct max96712_priv *priv)
{
struct fwnode_handle *ep;
struct v4l2_fwnode_endpoint v4l2_ep = {
- .bus_type = V4L2_MBUS_CSI2_DPHY
+ .bus_type = V4L2_MBUS_UNKNOWN,
};
+ unsigned int supported_lanes;
int ret;
ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(&priv->client->dev), 4,
@@ -350,8 +360,24 @@ static int max96712_parse_dt(struct max96712_priv *priv)
return -EINVAL;
}
- if (v4l2_ep.bus.mipi_csi2.num_data_lanes != 4) {
- dev_err(&priv->client->dev, "Only 4 data lanes supported\n");
+ switch (v4l2_ep.bus_type) {
+ case V4L2_MBUS_CSI2_DPHY:
+ supported_lanes = 4;
+ priv->cphy = false;
+ break;
+ case V4L2_MBUS_CSI2_CPHY:
+ supported_lanes = 3;
+ priv->cphy = true;
+ break;
+ default:
+ dev_err(&priv->client->dev, "Unsupported bus-type %u\n",
+ v4l2_ep.bus_type);
+ return -EINVAL;
+ }
+
+ if (v4l2_ep.bus.mipi_csi2.num_data_lanes != supported_lanes) {
+ dev_err(&priv->client->dev, "Only %u data lanes supported\n",
+ supported_lanes);
return -EINVAL;
}
@@ -427,7 +453,7 @@ static struct i2c_driver max96712_i2c_driver = {
.name = "max96712",
.of_match_table = of_match_ptr(max96712_of_table),
},
- .probe_new = max96712_probe,
+ .probe = max96712_probe,
.remove = max96712_remove,
};
diff --git a/drivers/staging/media/tegra-video/Kconfig b/drivers/staging/media/tegra-video/Kconfig
index df1b2cff2417..c53441822fdf 100644
--- a/drivers/staging/media/tegra-video/Kconfig
+++ b/drivers/staging/media/tegra-video/Kconfig
@@ -15,5 +15,6 @@ config VIDEO_TEGRA
config VIDEO_TEGRA_TPG
bool "NVIDIA Tegra VI driver TPG mode"
depends on VIDEO_TEGRA
+ depends on ARCH_TEGRA_210_SOC
help
Say yes here to enable Tegra internal TPG mode
diff --git a/drivers/staging/media/tegra-video/Makefile b/drivers/staging/media/tegra-video/Makefile
index dfa2ef8f99ef..6c7552e05109 100644
--- a/drivers/staging/media/tegra-video/Makefile
+++ b/drivers/staging/media/tegra-video/Makefile
@@ -2,7 +2,9 @@
tegra-video-objs := \
video.o \
vi.o \
+ vip.o \
csi.o
+tegra-video-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20.o
tegra-video-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
obj-$(CONFIG_VIDEO_TEGRA) += tegra-video.o
diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c
index 36ca639622c9..052172017b3b 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -328,12 +328,42 @@ static int tegra_csi_enable_stream(struct v4l2_subdev *subdev)
}
csi_chan->pg_mode = chan->pg_mode;
+
+ /*
+ * Tegra CSI receiver can detect the first LP to HS transition.
+ * So, start the CSI stream-on prior to sensor stream-on and
+ * vice-versa for stream-off.
+ */
ret = csi->ops->csi_start_streaming(csi_chan);
if (ret < 0)
goto finish_calibration;
+ if (csi_chan->mipi) {
+ struct v4l2_subdev *src_subdev;
+ /*
+ * TRM has incorrectly documented to wait for done status from
+ * calibration logic after CSI interface power on.
+ * As per the design, calibration results are latched and applied
+ * to the pads only when the link is in LP11 state which will happen
+ * during the sensor stream-on.
+ * CSI subdev stream-on triggers start of MIPI pads calibration.
+ * Wait for calibration to finish here after sensor subdev stream-on.
+ */
+ src_subdev = tegra_channel_get_remote_source_subdev(chan);
+ ret = v4l2_subdev_call(src_subdev, video, s_stream, true);
+
+ if (ret < 0 && ret != -ENOIOCTLCMD)
+ goto disable_csi_stream;
+
+ err = tegra_mipi_finish_calibration(csi_chan->mipi);
+ if (err < 0)
+ dev_warn(csi->dev, "MIPI calibration failed: %d\n", err);
+ }
+
return 0;
+disable_csi_stream:
+ csi->ops->csi_stop_streaming(csi_chan);
finish_calibration:
if (csi_chan->mipi)
tegra_mipi_finish_calibration(csi_chan->mipi);
@@ -352,10 +382,24 @@ rpm_put:
static int tegra_csi_disable_stream(struct v4l2_subdev *subdev)
{
+ struct tegra_vi_channel *chan = v4l2_get_subdev_hostdata(subdev);
struct tegra_csi_channel *csi_chan = to_csi_chan(subdev);
struct tegra_csi *csi = csi_chan->csi;
int err;
+ /*
+ * Stream-off subdevices in reverse order to stream-on.
+ * Remote source subdev in TPG mode is same as CSI subdev.
+ */
+ if (csi_chan->mipi) {
+ struct v4l2_subdev *src_subdev;
+
+ src_subdev = tegra_channel_get_remote_source_subdev(chan);
+ err = v4l2_subdev_call(src_subdev, video, s_stream, false);
+ if (err < 0 && err != -ENOIOCTLCMD)
+ dev_err_probe(csi->dev, err, "source subdev stream off failed\n");
+ }
+
csi->ops->csi_stop_streaming(csi_chan);
if (csi_chan->mipi) {
@@ -786,6 +830,10 @@ static int tegra_csi_remove(struct platform_device *pdev)
return 0;
}
+#if defined(CONFIG_ARCH_TEGRA_210_SOC)
+extern const struct tegra_csi_soc tegra210_csi_soc;
+#endif
+
static const struct of_device_id tegra_csi_of_id_table[] = {
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
{ .compatible = "nvidia,tegra210-csi", .data = &tegra210_csi_soc },
diff --git a/drivers/staging/media/tegra-video/csi.h b/drivers/staging/media/tegra-video/csi.h
index 6960ea2e3d36..3e6e5ee1bb1e 100644
--- a/drivers/staging/media/tegra-video/csi.h
+++ b/drivers/staging/media/tegra-video/csi.h
@@ -151,10 +151,6 @@ struct tegra_csi {
struct list_head csi_chans;
};
-#if defined(CONFIG_ARCH_TEGRA_210_SOC)
-extern const struct tegra_csi_soc tegra210_csi_soc;
-#endif
-
void tegra_csi_error_recover(struct v4l2_subdev *subdev);
void tegra_csi_calc_settle_time(struct tegra_csi_channel *csi_chan,
u8 csi_port_num,
diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
new file mode 100644
index 000000000000..c25286772603
--- /dev/null
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -0,0 +1,661 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Tegra20-specific VI implementation
+ *
+ * Copyright (C) 2023 SKIDATA GmbH
+ * Author: Luca Ceresoli <luca.ceresoli@bootlin.com>
+ */
+
+/*
+ * This source file contains Tegra20 supported video formats,
+ * VI and VIP SoC specific data, operations and registers accessors.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/host1x.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/v4l2-mediabus.h>
+
+#include "vip.h"
+#include "vi.h"
+
+#define TEGRA_VI_SYNCPT_WAIT_TIMEOUT msecs_to_jiffies(200)
+
+/* This are just good-sense numbers. The actual min/max is not documented. */
+#define TEGRA20_MIN_WIDTH 32U
+#define TEGRA20_MIN_HEIGHT 32U
+#define TEGRA20_MAX_WIDTH 2048U
+#define TEGRA20_MAX_HEIGHT 2048U
+
+/* --------------------------------------------------------------------------
+ * Registers
+ */
+
+#define TEGRA_VI_CONT_SYNCPT_OUT_1 0x0060
+#define VI_CONT_SYNCPT_OUT_1_CONTINUOUS_SYNCPT BIT(8)
+#define VI_CONT_SYNCPT_OUT_1_SYNCPT_IDX_SFT 0
+
+#define TEGRA_VI_VI_INPUT_CONTROL 0x0088
+#define VI_INPUT_FIELD_DETECT BIT(27)
+#define VI_INPUT_BT656 BIT(25)
+#define VI_INPUT_YUV_INPUT_FORMAT_SFT 8 /* bits [9:8] */
+#define VI_INPUT_YUV_INPUT_FORMAT_UYVY (0 << VI_INPUT_YUV_INPUT_FORMAT_SFT)
+#define VI_INPUT_YUV_INPUT_FORMAT_VYUY (1 << VI_INPUT_YUV_INPUT_FORMAT_SFT)
+#define VI_INPUT_YUV_INPUT_FORMAT_YUYV (2 << VI_INPUT_YUV_INPUT_FORMAT_SFT)
+#define VI_INPUT_YUV_INPUT_FORMAT_YVYU (3 << VI_INPUT_YUV_INPUT_FORMAT_SFT)
+#define VI_INPUT_INPUT_FORMAT_SFT 2 /* bits [5:2] */
+#define VI_INPUT_INPUT_FORMAT_YUV422 (0 << VI_INPUT_INPUT_FORMAT_SFT)
+#define VI_INPUT_VIP_INPUT_ENABLE BIT(1)
+
+#define TEGRA_VI_VI_CORE_CONTROL 0x008c
+#define VI_VI_CORE_CONTROL_PLANAR_CONV_IN_SEL_EXT BIT(31)
+#define VI_VI_CORE_CONTROL_CSC_INPUT_SEL_EXT BIT(30)
+#define VI_VI_CORE_CONTROL_INPUT_TO_ALT_MUX_SFT 27
+#define VI_VI_CORE_CONTROL_INPUT_TO_CORE_EXT_SFT 24
+#define VI_VI_CORE_CONTROL_OUTPUT_TO_ISP_EXT_SFT 21
+#define VI_VI_CORE_CONTROL_ISP_HOST_STALL_OFF BIT(20)
+#define VI_VI_CORE_CONTROL_V_DOWNSCALING BIT(19)
+#define VI_VI_CORE_CONTROL_V_AVERAGING BIT(18)
+#define VI_VI_CORE_CONTROL_H_DOWNSCALING BIT(17)
+#define VI_VI_CORE_CONTROL_H_AVERAGING BIT(16)
+#define VI_VI_CORE_CONTROL_CSC_INPUT_SEL BIT(11)
+#define VI_VI_CORE_CONTROL_PLANAR_CONV_INPUT_SEL BIT(10)
+#define VI_VI_CORE_CONTROL_INPUT_TO_CORE_SFT 8
+#define VI_VI_CORE_CONTROL_ISP_DOWNSAMPLE_SFT 5
+#define VI_VI_CORE_CONTROL_OUTPUT_TO_EPP_SFT 2
+#define VI_VI_CORE_CONTROL_OUTPUT_TO_ISP_SFT 0
+
+#define TEGRA_VI_VI_FIRST_OUTPUT_CONTROL 0x0090
+#define VI_OUTPUT_FORMAT_EXT BIT(22)
+#define VI_OUTPUT_V_DIRECTION BIT(20)
+#define VI_OUTPUT_H_DIRECTION BIT(19)
+#define VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT 17
+#define VI_OUTPUT_YUV_OUTPUT_FORMAT_UYVY (0 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT)
+#define VI_OUTPUT_YUV_OUTPUT_FORMAT_VYUY (1 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT)
+#define VI_OUTPUT_YUV_OUTPUT_FORMAT_YUYV (2 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT)
+#define VI_OUTPUT_YUV_OUTPUT_FORMAT_YVYU (3 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT)
+#define VI_OUTPUT_OUTPUT_BYTE_SWAP BIT(16)
+#define VI_OUTPUT_LAST_PIXEL_DUPLICATION BIT(8)
+#define VI_OUTPUT_OUTPUT_FORMAT_SFT 0
+#define VI_OUTPUT_OUTPUT_FORMAT_YUV422POST (3 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
+#define VI_OUTPUT_OUTPUT_FORMAT_YUV420PLANAR (6 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
+
+#define TEGRA_VI_VIP_H_ACTIVE 0x00a4
+#define VI_VIP_H_ACTIVE_PERIOD_SFT 16 /* active pixels/line, must be even */
+#define VI_VIP_H_ACTIVE_START_SFT 0
+
+#define TEGRA_VI_VIP_V_ACTIVE 0x00a8
+#define VI_VIP_V_ACTIVE_PERIOD_SFT 16 /* active lines */
+#define VI_VIP_V_ACTIVE_START_SFT 0
+
+#define TEGRA_VI_VB0_START_ADDRESS_FIRST 0x00c4
+#define TEGRA_VI_VB0_BASE_ADDRESS_FIRST 0x00c8
+#define TEGRA_VI_VB0_START_ADDRESS_U 0x00cc
+#define TEGRA_VI_VB0_BASE_ADDRESS_U 0x00d0
+#define TEGRA_VI_VB0_START_ADDRESS_V 0x00d4
+#define TEGRA_VI_VB0_BASE_ADDRESS_V 0x00d8
+
+#define TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE 0x00e0
+#define VI_FIRST_OUTPUT_FRAME_HEIGHT_SFT 16
+#define VI_FIRST_OUTPUT_FRAME_WIDTH_SFT 0
+
+#define TEGRA_VI_VB0_COUNT_FIRST 0x00e4
+
+#define TEGRA_VI_VB0_SIZE_FIRST 0x00e8
+#define VI_VB0_SIZE_FIRST_V_SFT 16
+#define VI_VB0_SIZE_FIRST_H_SFT 0
+
+#define TEGRA_VI_VB0_BUFFER_STRIDE_FIRST 0x00ec
+#define VI_VB0_BUFFER_STRIDE_FIRST_CHROMA_SFT 30
+#define VI_VB0_BUFFER_STRIDE_FIRST_LUMA_SFT 0
+
+#define TEGRA_VI_H_LPF_CONTROL 0x0108
+#define VI_H_LPF_CONTROL_CHROMA_SFT 16
+#define VI_H_LPF_CONTROL_LUMA_SFT 0
+
+#define TEGRA_VI_H_DOWNSCALE_CONTROL 0x010c
+#define TEGRA_VI_V_DOWNSCALE_CONTROL 0x0110
+
+#define TEGRA_VI_VIP_INPUT_STATUS 0x0144
+
+#define TEGRA_VI_VI_DATA_INPUT_CONTROL 0x0168
+#define VI_DATA_INPUT_SFT 0 /* [11:0] = mask pin inputs to VI core */
+
+#define TEGRA_VI_PIN_INPUT_ENABLE 0x016c
+#define VI_PIN_INPUT_VSYNC BIT(14)
+#define VI_PIN_INPUT_HSYNC BIT(13)
+#define VI_PIN_INPUT_VD_SFT 0 /* [11:0] = data bin N input enable */
+
+#define TEGRA_VI_PIN_INVERSION 0x0174
+#define VI_PIN_INVERSION_VSYNC_ACTIVE_HIGH BIT(1)
+#define VI_PIN_INVERSION_HSYNC_ACTIVE_HIGH BIT(0)
+
+#define TEGRA_VI_CAMERA_CONTROL 0x01a0
+#define VI_CAMERA_CONTROL_STOP_CAPTURE BIT(2)
+#define VI_CAMERA_CONTROL_TEST_MODE BIT(1)
+#define VI_CAMERA_CONTROL_VIP_ENABLE BIT(0)
+
+#define TEGRA_VI_VI_ENABLE 0x01a4
+#define VI_VI_ENABLE_SW_FLOW_CONTROL_OUT1 BIT(1)
+#define VI_VI_ENABLE_FIRST_OUTPUT_TO_MEM_DISABLE BIT(0)
+
+#define TEGRA_VI_VI_RAISE 0x01ac
+#define VI_VI_RAISE_ON_EDGE BIT(0)
+
+/* --------------------------------------------------------------------------
+ * VI
+ */
+
+static void tegra20_vi_write(struct tegra_vi_channel *chan, unsigned int addr, u32 val)
+{
+ writel(val, chan->vi->iomem + addr);
+}
+
+/*
+ * Get the main input format (YUV/RGB...) and the YUV variant as values to
+ * be written into registers for the current VI input mbus code.
+ */
+static void tegra20_vi_get_input_formats(struct tegra_vi_channel *chan,
+ unsigned int *main_input_format,
+ unsigned int *yuv_input_format)
+{
+ unsigned int input_mbus_code = chan->fmtinfo->code;
+
+ (*main_input_format) = VI_INPUT_INPUT_FORMAT_YUV422;
+
+ switch (input_mbus_code) {
+ case MEDIA_BUS_FMT_UYVY8_2X8:
+ (*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_UYVY;
+ break;
+ case MEDIA_BUS_FMT_VYUY8_2X8:
+ (*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_VYUY;
+ break;
+ case MEDIA_BUS_FMT_YUYV8_2X8:
+ (*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_YUYV;
+ break;
+ case MEDIA_BUS_FMT_YVYU8_2X8:
+ (*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_YVYU;
+ break;
+ }
+}
+
+/*
+ * Get the main output format (YUV/RGB...) and the YUV variant as values to
+ * be written into registers for the current VI output pixel format.
+ */
+static void tegra20_vi_get_output_formats(struct tegra_vi_channel *chan,
+ unsigned int *main_output_format,
+ unsigned int *yuv_output_format)
+{
+ u32 output_fourcc = chan->format.pixelformat;
+
+ /* Default to YUV422 non-planar (U8Y8V8Y8) after downscaling */
+ (*main_output_format) = VI_OUTPUT_OUTPUT_FORMAT_YUV422POST;
+ (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_UYVY;
+
+ switch (output_fourcc) {
+ case V4L2_PIX_FMT_UYVY:
+ (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_UYVY;
+ break;
+ case V4L2_PIX_FMT_VYUY:
+ (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_VYUY;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_YUYV;
+ break;
+ case V4L2_PIX_FMT_YVYU:
+ (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_YVYU;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ (*main_output_format) = VI_OUTPUT_OUTPUT_FORMAT_YUV420PLANAR;
+ break;
+ }
+}
+
+/*
+ * Make the VI accessible (needed on Tegra20).
+ *
+ * This function writes an unknown bit into an unknown register. The code
+ * comes from a downstream 3.1 kernel that has a working VIP driver for
+ * Tegra20, and removing it makes the VI completely unaccessible. It should
+ * be rewritten and possibly moved elsewhere, but the appropriate location
+ * and implementation is unknown due to a total lack of documentation.
+ */
+static int tegra20_vi_enable(struct tegra_vi *vi, bool on)
+{
+ /* from arch/arm/mach-tegra/iomap.h */
+ const phys_addr_t TEGRA_APB_MISC_BASE = 0x70000000;
+ const unsigned long reg_offset = 0x42c;
+ void __iomem *apb_misc;
+ u32 val;
+
+ apb_misc = ioremap(TEGRA_APB_MISC_BASE, PAGE_SIZE);
+ if (!apb_misc)
+ apb_misc = ERR_PTR(-ENOENT);
+ if (IS_ERR(apb_misc))
+ return dev_err_probe(vi->dev, PTR_ERR(apb_misc), "cannot access APB_MISC");
+
+ val = readl(apb_misc + reg_offset);
+ val &= ~BIT(0);
+ val |= on ? BIT(0) : 0;
+ writel(val, apb_misc + reg_offset);
+ iounmap(apb_misc);
+
+ return 0;
+}
+
+static int tegra20_channel_host1x_syncpt_init(struct tegra_vi_channel *chan)
+{
+ struct tegra_vi *vi = chan->vi;
+ struct host1x_syncpt *out_sp;
+
+ out_sp = host1x_syncpt_request(&vi->client, HOST1X_SYNCPT_CLIENT_MANAGED);
+ if (!out_sp)
+ return dev_err_probe(vi->dev, -ENOMEM, "failed to request syncpoint\n");
+
+ chan->mw_ack_sp[0] = out_sp;
+
+ return 0;
+}
+
+static void tegra20_channel_host1x_syncpt_free(struct tegra_vi_channel *chan)
+{
+ host1x_syncpt_put(chan->mw_ack_sp[0]);
+}
+
+static void tegra20_fmt_align(struct v4l2_pix_format *pix, unsigned int bpp)
+{
+ pix->width = clamp(pix->width, TEGRA20_MIN_WIDTH, TEGRA20_MAX_WIDTH);
+ pix->height = clamp(pix->height, TEGRA20_MIN_HEIGHT, TEGRA20_MAX_HEIGHT);
+
+ switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ pix->bytesperline = roundup(pix->width, 2) * 2;
+ pix->sizeimage = roundup(pix->width, 2) * 2 * pix->height;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ pix->bytesperline = roundup(pix->width, 8);
+ pix->sizeimage = roundup(pix->width, 8) * pix->height * 3 / 2;
+ break;
+ }
+}
+
+/*
+ * Compute buffer offsets once per stream so that
+ * tegra20_channel_vi_buffer_setup() only has to do very simple maths for
+ * each buffer.
+ */
+static void tegra20_channel_queue_setup(struct tegra_vi_channel *chan)
+{
+ unsigned int stride = chan->format.bytesperline;
+ unsigned int height = chan->format.height;
+
+ chan->start_offset = 0;
+
+ switch (chan->format.pixelformat) {
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ if (chan->vflip)
+ chan->start_offset += stride * (height - 1);
+ if (chan->hflip)
+ chan->start_offset += stride - 1;
+ break;
+
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ chan->addr_offset_u = stride * height;
+ chan->addr_offset_v = chan->addr_offset_u + stride * height / 4;
+
+ /* For YVU420, we swap the locations of the U and V planes. */
+ if (chan->format.pixelformat == V4L2_PIX_FMT_YVU420) {
+ unsigned long temp;
+
+ temp = chan->addr_offset_u;
+ chan->addr_offset_u = chan->addr_offset_v;
+ chan->addr_offset_v = temp;
+ }
+
+ chan->start_offset_u = chan->addr_offset_u;
+ chan->start_offset_v = chan->addr_offset_v;
+
+ if (chan->vflip) {
+ chan->start_offset += stride * (height - 1);
+ chan->start_offset_u += (stride / 2) * ((height / 2) - 1);
+ chan->start_offset_v += (stride / 2) * ((height / 2) - 1);
+ }
+ if (chan->hflip) {
+ chan->start_offset += stride - 1;
+ chan->start_offset_u += (stride / 2) - 1;
+ chan->start_offset_v += (stride / 2) - 1;
+ }
+ break;
+ }
+}
+
+static void release_buffer(struct tegra_vi_channel *chan,
+ struct tegra_channel_buffer *buf,
+ enum vb2_buffer_state state)
+{
+ struct vb2_v4l2_buffer *vb = &buf->buf;
+
+ vb->sequence = chan->sequence++;
+ vb->field = V4L2_FIELD_NONE;
+ vb->vb2_buf.timestamp = ktime_get_ns();
+ vb2_buffer_done(&vb->vb2_buf, state);
+}
+
+static void tegra20_channel_vi_buffer_setup(struct tegra_vi_channel *chan,
+ struct tegra_channel_buffer *buf)
+{
+ dma_addr_t base = buf->addr;
+
+ switch (chan->fmtinfo->fourcc) {
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_U, base + chan->addr_offset_u);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_U, base + chan->start_offset_u);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_V, base + chan->addr_offset_v);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_V, base + chan->start_offset_v);
+ fallthrough;
+
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_FIRST, base);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_FIRST, base + chan->start_offset);
+ break;
+ }
+}
+
+static int tegra20_channel_capture_frame(struct tegra_vi_channel *chan,
+ struct tegra_channel_buffer *buf)
+{
+ int err;
+
+ chan->next_out_sp_idx++;
+
+ tegra20_channel_vi_buffer_setup(chan, buf);
+
+ tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_VIP_ENABLE);
+
+ /* Wait for syncpt counter to reach frame start event threshold */
+ err = host1x_syncpt_wait(chan->mw_ack_sp[0], chan->next_out_sp_idx,
+ TEGRA_VI_SYNCPT_WAIT_TIMEOUT, NULL);
+ if (err) {
+ host1x_syncpt_incr(chan->mw_ack_sp[0]);
+ dev_err_ratelimited(&chan->video.dev, "frame start syncpt timeout: %d\n", err);
+ release_buffer(chan, buf, VB2_BUF_STATE_ERROR);
+ return err;
+ }
+
+ tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL,
+ VI_CAMERA_CONTROL_STOP_CAPTURE | VI_CAMERA_CONTROL_VIP_ENABLE);
+
+ release_buffer(chan, buf, VB2_BUF_STATE_DONE);
+
+ return 0;
+}
+
+static int tegra20_chan_capture_kthread_start(void *data)
+{
+ struct tegra_vi_channel *chan = data;
+ struct tegra_channel_buffer *buf;
+ unsigned int retries = 0;
+ int err = 0;
+
+ while (1) {
+ /*
+ * Source is not streaming if error is non-zero.
+ * So, do not dequeue buffers on error and let the thread sleep
+ * till kthread stop signal is received.
+ */
+ wait_event_interruptible(chan->start_wait,
+ kthread_should_stop() ||
+ (!list_empty(&chan->capture) && !err));
+
+ if (kthread_should_stop())
+ break;
+
+ /* dequeue the buffer and start capture */
+ spin_lock(&chan->start_lock);
+ if (list_empty(&chan->capture)) {
+ spin_unlock(&chan->start_lock);
+ continue;
+ }
+
+ buf = list_first_entry(&chan->capture, struct tegra_channel_buffer, queue);
+ list_del_init(&buf->queue);
+ spin_unlock(&chan->start_lock);
+
+ err = tegra20_channel_capture_frame(chan, buf);
+ if (!err) {
+ retries = 0;
+ continue;
+ }
+
+ if (retries++ > chan->syncpt_timeout_retry)
+ vb2_queue_error(&chan->queue);
+ else
+ err = 0;
+ }
+
+ return 0;
+}
+
+static void tegra20_camera_capture_setup(struct tegra_vi_channel *chan)
+{
+ u32 output_fourcc = chan->format.pixelformat;
+ int width = chan->format.width;
+ int height = chan->format.height;
+ int stride_l = chan->format.bytesperline;
+ int stride_c = (output_fourcc == V4L2_PIX_FMT_YUV420 ||
+ output_fourcc == V4L2_PIX_FMT_YVU420) ? 1 : 0;
+ int main_output_format;
+ int yuv_output_format;
+
+ tegra20_vi_get_output_formats(chan, &main_output_format, &yuv_output_format);
+
+ /*
+ * Set up low pass filter. Use 0x240 for chromaticity and 0x240
+ * for luminance, which is the default and means not to touch
+ * anything.
+ */
+ tegra20_vi_write(chan, TEGRA_VI_H_LPF_CONTROL,
+ 0x0240 << VI_H_LPF_CONTROL_LUMA_SFT |
+ 0x0240 << VI_H_LPF_CONTROL_CHROMA_SFT);
+
+ /* Set up raise-on-edge, so we get an interrupt on end of frame. */
+ tegra20_vi_write(chan, TEGRA_VI_VI_RAISE, VI_VI_RAISE_ON_EDGE);
+
+ tegra20_vi_write(chan, TEGRA_VI_VI_FIRST_OUTPUT_CONTROL,
+ (chan->vflip ? VI_OUTPUT_V_DIRECTION : 0) |
+ (chan->hflip ? VI_OUTPUT_H_DIRECTION : 0) |
+ yuv_output_format << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT |
+ main_output_format << VI_OUTPUT_OUTPUT_FORMAT_SFT);
+
+ /* Set up frame size */
+ tegra20_vi_write(chan, TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE,
+ height << VI_FIRST_OUTPUT_FRAME_HEIGHT_SFT |
+ width << VI_FIRST_OUTPUT_FRAME_WIDTH_SFT);
+
+ /* First output memory enabled */
+ tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE, 0);
+
+ /* Set the number of frames in the buffer */
+ tegra20_vi_write(chan, TEGRA_VI_VB0_COUNT_FIRST, 1);
+
+ /* Set up buffer frame size */
+ tegra20_vi_write(chan, TEGRA_VI_VB0_SIZE_FIRST,
+ height << VI_VB0_SIZE_FIRST_V_SFT |
+ width << VI_VB0_SIZE_FIRST_H_SFT);
+
+ tegra20_vi_write(chan, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST,
+ stride_l << VI_VB0_BUFFER_STRIDE_FIRST_LUMA_SFT |
+ stride_c << VI_VB0_BUFFER_STRIDE_FIRST_CHROMA_SFT);
+
+ tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE, 0);
+}
+
+static int tegra20_vi_start_streaming(struct vb2_queue *vq, u32 count)
+{
+ struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
+ struct media_pipeline *pipe = &chan->video.pipe;
+ int err;
+
+ chan->next_out_sp_idx = host1x_syncpt_read(chan->mw_ack_sp[0]);
+
+ err = video_device_pipeline_start(&chan->video, pipe);
+ if (err)
+ goto error_pipeline_start;
+
+ tegra20_camera_capture_setup(chan);
+
+ err = tegra_channel_set_stream(chan, true);
+ if (err)
+ goto error_set_stream;
+
+ chan->sequence = 0;
+
+ chan->kthread_start_capture = kthread_run(tegra20_chan_capture_kthread_start,
+ chan, "%s:0", chan->video.name);
+ if (IS_ERR(chan->kthread_start_capture)) {
+ err = PTR_ERR(chan->kthread_start_capture);
+ chan->kthread_start_capture = NULL;
+ dev_err_probe(&chan->video.dev, err, "failed to run capture kthread\n");
+ goto error_kthread_start;
+ }
+
+ return 0;
+
+error_kthread_start:
+ tegra_channel_set_stream(chan, false);
+error_set_stream:
+ video_device_pipeline_stop(&chan->video);
+error_pipeline_start:
+ tegra_channel_release_buffers(chan, VB2_BUF_STATE_QUEUED);
+
+ return err;
+}
+
+static void tegra20_vi_stop_streaming(struct vb2_queue *vq)
+{
+ struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
+
+ if (chan->kthread_start_capture) {
+ kthread_stop(chan->kthread_start_capture);
+ chan->kthread_start_capture = NULL;
+ }
+
+ tegra_channel_release_buffers(chan, VB2_BUF_STATE_ERROR);
+ tegra_channel_set_stream(chan, false);
+ video_device_pipeline_stop(&chan->video);
+}
+
+static const struct tegra_vi_ops tegra20_vi_ops = {
+ .vi_enable = tegra20_vi_enable,
+ .channel_host1x_syncpt_init = tegra20_channel_host1x_syncpt_init,
+ .channel_host1x_syncpt_free = tegra20_channel_host1x_syncpt_free,
+ .vi_fmt_align = tegra20_fmt_align,
+ .channel_queue_setup = tegra20_channel_queue_setup,
+ .vi_start_streaming = tegra20_vi_start_streaming,
+ .vi_stop_streaming = tegra20_vi_stop_streaming,
+};
+
+#define TEGRA20_VIDEO_FMT(MBUS_CODE, BPP, FOURCC) \
+{ \
+ .code = MEDIA_BUS_FMT_##MBUS_CODE, \
+ .bpp = BPP, \
+ .fourcc = V4L2_PIX_FMT_##FOURCC, \
+}
+
+static const struct tegra_video_format tegra20_video_formats[] = {
+ TEGRA20_VIDEO_FMT(UYVY8_2X8, 2, UYVY),
+ TEGRA20_VIDEO_FMT(VYUY8_2X8, 2, VYUY),
+ TEGRA20_VIDEO_FMT(YUYV8_2X8, 2, YUYV),
+ TEGRA20_VIDEO_FMT(YVYU8_2X8, 2, YVYU),
+ TEGRA20_VIDEO_FMT(UYVY8_2X8, 1, YUV420),
+ TEGRA20_VIDEO_FMT(UYVY8_2X8, 1, YVU420),
+};
+
+const struct tegra_vi_soc tegra20_vi_soc = {
+ .video_formats = tegra20_video_formats,
+ .nformats = ARRAY_SIZE(tegra20_video_formats),
+ .default_video_format = &tegra20_video_formats[0],
+ .ops = &tegra20_vi_ops,
+ .vi_max_channels = 1, /* parallel input (VIP) */
+ .vi_max_clk_hz = 150000000,
+ .has_h_v_flip = true,
+};
+
+/* --------------------------------------------------------------------------
+ * VIP
+ */
+
+/*
+ * VIP-specific configuration for stream start.
+ *
+ * Whatever is common among VIP and CSI is done by the VI component (see
+ * tegra20_vi_start_streaming()). Here we do what is VIP-specific.
+ */
+static int tegra20_vip_start_streaming(struct tegra_vip_channel *vip_chan)
+{
+ struct tegra_vi_channel *vi_chan = v4l2_get_subdev_hostdata(&vip_chan->subdev);
+ int width = vi_chan->format.width;
+ int height = vi_chan->format.height;
+
+ unsigned int main_input_format;
+ unsigned int yuv_input_format;
+
+ tegra20_vi_get_input_formats(vi_chan, &main_input_format, &yuv_input_format);
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_VI_CORE_CONTROL, 0);
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_VI_INPUT_CONTROL,
+ VI_INPUT_VIP_INPUT_ENABLE | main_input_format | yuv_input_format);
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_V_DOWNSCALE_CONTROL, 0);
+ tegra20_vi_write(vi_chan, TEGRA_VI_H_DOWNSCALE_CONTROL, 0);
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_VIP_V_ACTIVE, height << VI_VIP_V_ACTIVE_PERIOD_SFT);
+ tegra20_vi_write(vi_chan, TEGRA_VI_VIP_H_ACTIVE,
+ roundup(width, 2) << VI_VIP_H_ACTIVE_PERIOD_SFT);
+
+ /*
+ * For VIP, D9..D2 is mapped to the video decoder's P7..P0.
+ * Disable/mask out the other Dn wires. When not in BT656
+ * mode we also need the V/H sync.
+ */
+ tegra20_vi_write(vi_chan, TEGRA_VI_PIN_INPUT_ENABLE,
+ GENMASK(9, 2) << VI_PIN_INPUT_VD_SFT |
+ VI_PIN_INPUT_HSYNC | VI_PIN_INPUT_VSYNC);
+ tegra20_vi_write(vi_chan, TEGRA_VI_VI_DATA_INPUT_CONTROL,
+ GENMASK(9, 2) << VI_DATA_INPUT_SFT);
+ tegra20_vi_write(vi_chan, TEGRA_VI_PIN_INVERSION, 0);
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_OUT_1,
+ VI_CONT_SYNCPT_OUT_1_CONTINUOUS_SYNCPT |
+ host1x_syncpt_id(vi_chan->mw_ack_sp[0])
+ << VI_CONT_SYNCPT_OUT_1_SYNCPT_IDX_SFT);
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_STOP_CAPTURE);
+
+ return 0;
+}
+
+static const struct tegra_vip_ops tegra20_vip_ops = {
+ .vip_start_streaming = tegra20_vip_start_streaming,
+};
+
+const struct tegra_vip_soc tegra20_vip_soc = {
+ .ops = &tegra20_vip_ops,
+};
diff --git a/drivers/staging/media/tegra-video/tegra210.c b/drivers/staging/media/tegra-video/tegra210.c
index d58370a84737..da99f19a39e7 100644
--- a/drivers/staging/media/tegra-video/tegra210.c
+++ b/drivers/staging/media/tegra-video/tegra210.c
@@ -17,6 +17,13 @@
#include "csi.h"
#include "vi.h"
+#define TEGRA210_MIN_WIDTH 32U
+#define TEGRA210_MAX_WIDTH 32768U
+#define TEGRA210_MIN_HEIGHT 32U
+#define TEGRA210_MAX_HEIGHT 32768U
+
+#define SURFACE_ALIGN_BYTES 64
+
#define TEGRA_VI_SYNCPT_WAIT_TIMEOUT msecs_to_jiffies(200)
/* Tegra210 VI registers */
@@ -172,6 +179,84 @@ static u32 vi_csi_read(struct tegra_vi_channel *chan, u8 portno,
/*
* Tegra210 VI channel capture operations
*/
+
+static int tegra210_channel_host1x_syncpt_init(struct tegra_vi_channel *chan)
+{
+ struct tegra_vi *vi = chan->vi;
+ unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
+ struct host1x_syncpt *fs_sp;
+ struct host1x_syncpt *mw_sp;
+ int ret, i;
+
+ for (i = 0; i < chan->numgangports; i++) {
+ fs_sp = host1x_syncpt_request(&vi->client, flags);
+ if (!fs_sp) {
+ dev_err(vi->dev, "failed to request frame start syncpoint\n");
+ ret = -ENOMEM;
+ goto free_syncpts;
+ }
+
+ mw_sp = host1x_syncpt_request(&vi->client, flags);
+ if (!mw_sp) {
+ dev_err(vi->dev, "failed to request memory ack syncpoint\n");
+ host1x_syncpt_put(fs_sp);
+ ret = -ENOMEM;
+ goto free_syncpts;
+ }
+
+ chan->frame_start_sp[i] = fs_sp;
+ chan->mw_ack_sp[i] = mw_sp;
+ spin_lock_init(&chan->sp_incr_lock[i]);
+ }
+
+ return 0;
+
+free_syncpts:
+ for (i = 0; i < chan->numgangports; i++) {
+ host1x_syncpt_put(chan->mw_ack_sp[i]);
+ host1x_syncpt_put(chan->frame_start_sp[i]);
+ }
+ return ret;
+}
+
+static void tegra210_channel_host1x_syncpt_free(struct tegra_vi_channel *chan)
+{
+ int i;
+
+ for (i = 0; i < chan->numgangports; i++) {
+ host1x_syncpt_put(chan->mw_ack_sp[i]);
+ host1x_syncpt_put(chan->frame_start_sp[i]);
+ }
+}
+
+static void tegra210_fmt_align(struct v4l2_pix_format *pix, unsigned int bpp)
+{
+ unsigned int min_bpl;
+ unsigned int max_bpl;
+ unsigned int bpl;
+
+ /*
+ * The transfer alignment requirements are expressed in bytes.
+ * Clamp the requested width and height to the limits.
+ */
+ pix->width = clamp(pix->width, TEGRA210_MIN_WIDTH, TEGRA210_MAX_WIDTH);
+ pix->height = clamp(pix->height, TEGRA210_MIN_HEIGHT, TEGRA210_MAX_HEIGHT);
+
+ /* Clamp the requested bytes per line value. If the maximum bytes per
+ * line value is zero, the module doesn't support user configurable
+ * line sizes. Override the requested value with the minimum in that
+ * case.
+ */
+ min_bpl = pix->width * bpp;
+ max_bpl = rounddown(TEGRA210_MAX_WIDTH, SURFACE_ALIGN_BYTES);
+ bpl = roundup(pix->bytesperline, SURFACE_ALIGN_BYTES);
+
+ pix->bytesperline = clamp(bpl, min_bpl, max_bpl);
+ pix->sizeimage = pix->bytesperline * pix->height;
+ if (pix->pixelformat == V4L2_PIX_FMT_NV16)
+ pix->sizeimage *= 2;
+}
+
static int tegra_channel_capture_setup(struct tegra_vi_channel *chan,
u8 portno)
{
@@ -718,6 +803,9 @@ static const struct tegra_video_format tegra210_video_formats[] = {
/* Tegra210 VI operations */
static const struct tegra_vi_ops tegra210_vi_ops = {
+ .channel_host1x_syncpt_init = tegra210_channel_host1x_syncpt_init,
+ .channel_host1x_syncpt_free = tegra210_channel_host1x_syncpt_free,
+ .vi_fmt_align = tegra210_fmt_align,
.vi_start_streaming = tegra210_vi_start_streaming,
.vi_stop_streaming = tegra210_vi_stop_streaming,
};
@@ -730,8 +818,10 @@ const struct tegra_vi_soc tegra210_vi_soc = {
.hw_revision = 3,
.vi_max_channels = 6,
#if IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)
+ .default_video_format = &tegra210_video_formats[0],
.vi_max_clk_hz = 499200000,
#else
+ .default_video_format = &tegra210_video_formats[4],
.vi_max_clk_hz = 998400000,
#endif
};
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index 2f1aff7e8717..79284c3b6cae 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -30,15 +30,19 @@
#include "vi.h"
#include "video.h"
-#define MAX_CID_CONTROLS 1
-
-static const struct tegra_video_format tegra_default_format = {
- .img_dt = TEGRA_IMAGE_DT_RAW10,
- .bit_width = 10,
- .code = MEDIA_BUS_FMT_SRGGB10_1X10,
- .bpp = 2,
- .img_fmt = TEGRA_IMAGE_FORMAT_DEF,
- .fourcc = V4L2_PIX_FMT_SRGGB10,
+#define MAX_CID_CONTROLS 3
+
+/**
+ * struct tegra_vi_graph_entity - Entity in the video graph
+ *
+ * @asd: subdev asynchronous registration information
+ * @entity: media entity from the corresponding V4L2 subdev
+ * @subdev: V4L2 subdev
+ */
+struct tegra_vi_graph_entity {
+ struct v4l2_async_subdev asd;
+ struct media_entity *entity;
+ struct v4l2_subdev *subdev;
};
static inline struct tegra_vi *
@@ -98,6 +102,7 @@ tegra_get_format_by_fourcc(struct tegra_vi *vi, u32 fourcc)
/*
* videobuf2 queue operations
*/
+
static int tegra_channel_queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers,
unsigned int *nplanes,
@@ -113,6 +118,9 @@ static int tegra_channel_queue_setup(struct vb2_queue *vq,
sizes[0] = chan->format.sizeimage;
alloc_devs[0] = chan->vi->dev;
+ if (chan->vi->ops->channel_queue_setup)
+ chan->vi->ops->channel_queue_setup(chan);
+
return 0;
}
@@ -164,6 +172,9 @@ tegra_channel_get_remote_csi_subdev(struct tegra_vi_channel *chan)
return media_entity_to_v4l2_subdev(pad->entity);
}
+/*
+ * Walk up the chain until the initial source (e.g. image sensor)
+ */
struct v4l2_subdev *
tegra_channel_get_remote_source_subdev(struct tegra_vi_channel *chan)
{
@@ -190,49 +201,15 @@ tegra_channel_get_remote_source_subdev(struct tegra_vi_channel *chan)
static int tegra_channel_enable_stream(struct tegra_vi_channel *chan)
{
- struct v4l2_subdev *csi_subdev, *src_subdev;
- struct tegra_csi_channel *csi_chan;
- int ret, err;
+ struct v4l2_subdev *subdev;
+ int ret;
- /*
- * Tegra CSI receiver can detect the first LP to HS transition.
- * So, start the CSI stream-on prior to sensor stream-on and
- * vice-versa for stream-off.
- */
- csi_subdev = tegra_channel_get_remote_csi_subdev(chan);
- ret = v4l2_subdev_call(csi_subdev, video, s_stream, true);
+ subdev = tegra_channel_get_remote_csi_subdev(chan);
+ ret = v4l2_subdev_call(subdev, video, s_stream, true);
if (ret < 0 && ret != -ENOIOCTLCMD)
return ret;
- if (IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
- return 0;
-
- csi_chan = v4l2_get_subdevdata(csi_subdev);
- /*
- * TRM has incorrectly documented to wait for done status from
- * calibration logic after CSI interface power on.
- * As per the design, calibration results are latched and applied
- * to the pads only when the link is in LP11 state which will happen
- * during the sensor stream-on.
- * CSI subdev stream-on triggers start of MIPI pads calibration.
- * Wait for calibration to finish here after sensor subdev stream-on.
- */
- src_subdev = tegra_channel_get_remote_source_subdev(chan);
- ret = v4l2_subdev_call(src_subdev, video, s_stream, true);
- err = tegra_mipi_finish_calibration(csi_chan->mipi);
-
- if (ret < 0 && ret != -ENOIOCTLCMD)
- goto err_disable_csi_stream;
-
- if (err < 0)
- dev_warn(csi_chan->csi->dev,
- "MIPI calibration failed: %d\n", err);
-
return 0;
-
-err_disable_csi_stream:
- v4l2_subdev_call(csi_subdev, video, s_stream, false);
- return ret;
}
static int tegra_channel_disable_stream(struct tegra_vi_channel *chan)
@@ -240,18 +217,6 @@ static int tegra_channel_disable_stream(struct tegra_vi_channel *chan)
struct v4l2_subdev *subdev;
int ret;
- /*
- * Stream-off subdevices in reverse order to stream-on.
- * Remote source subdev in TPG mode is same as CSI subdev.
- */
- subdev = tegra_channel_get_remote_source_subdev(chan);
- ret = v4l2_subdev_call(subdev, video, s_stream, false);
- if (ret < 0 && ret != -ENOIOCTLCMD)
- return ret;
-
- if (IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
- return 0;
-
subdev = tegra_channel_get_remote_csi_subdev(chan);
ret = v4l2_subdev_call(subdev, video, s_stream, false);
if (ret < 0 && ret != -ENOIOCTLCMD)
@@ -457,36 +422,6 @@ static int tegra_channel_get_format(struct file *file, void *fh,
return 0;
}
-static void tegra_channel_fmt_align(struct tegra_vi_channel *chan,
- struct v4l2_pix_format *pix,
- unsigned int bpp)
-{
- unsigned int min_bpl;
- unsigned int max_bpl;
- unsigned int bpl;
-
- /*
- * The transfer alignment requirements are expressed in bytes.
- * Clamp the requested width and height to the limits.
- */
- pix->width = clamp(pix->width, TEGRA_MIN_WIDTH, TEGRA_MAX_WIDTH);
- pix->height = clamp(pix->height, TEGRA_MIN_HEIGHT, TEGRA_MAX_HEIGHT);
-
- /* Clamp the requested bytes per line value. If the maximum bytes per
- * line value is zero, the module doesn't support user configurable
- * line sizes. Override the requested value with the minimum in that
- * case.
- */
- min_bpl = pix->width * bpp;
- max_bpl = rounddown(TEGRA_MAX_WIDTH, SURFACE_ALIGN_BYTES);
- bpl = roundup(pix->bytesperline, SURFACE_ALIGN_BYTES);
-
- pix->bytesperline = clamp(bpl, min_bpl, max_bpl);
- pix->sizeimage = pix->bytesperline * pix->height;
- if (pix->pixelformat == V4L2_PIX_FMT_NV16)
- pix->sizeimage *= 2;
-}
-
static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
struct v4l2_pix_format *pix)
{
@@ -563,7 +498,7 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
return ret;
v4l2_fill_pix_format(pix, &fmt.format);
- tegra_channel_fmt_align(chan, pix, fmtinfo->bpp);
+ chan->vi->ops->vi_fmt_align(pix, fmtinfo->bpp);
__v4l2_subdev_state_free(sd_state);
@@ -616,7 +551,7 @@ static int tegra_channel_set_format(struct file *file, void *fh,
return ret;
v4l2_fill_pix_format(pix, &fmt.format);
- tegra_channel_fmt_align(chan, pix, fmtinfo->bpp);
+ chan->vi->ops->vi_fmt_align(pix, fmtinfo->bpp);
chan->format = *pix;
chan->fmtinfo = fmtinfo;
@@ -652,7 +587,7 @@ static int tegra_channel_set_subdev_active_fmt(struct tegra_vi_channel *chan)
chan->format.bytesperline = chan->format.width * chan->fmtinfo->bpp;
chan->format.sizeimage = chan->format.bytesperline *
chan->format.height;
- tegra_channel_fmt_align(chan, &chan->format, chan->fmtinfo->bpp);
+ chan->vi->ops->vi_fmt_align(&chan->format, chan->fmtinfo->bpp);
tegra_channel_update_gangports(chan);
return 0;
@@ -821,7 +756,7 @@ static int tegra_channel_s_dv_timings(struct file *file, void *fh,
chan->format.height = bt->height;
chan->format.bytesperline = bt->width * chan->fmtinfo->bpp;
chan->format.sizeimage = chan->format.bytesperline * bt->height;
- tegra_channel_fmt_align(chan, &chan->format, chan->fmtinfo->bpp);
+ chan->vi->ops->vi_fmt_align(&chan->format, chan->fmtinfo->bpp);
tegra_channel_update_gangports(chan);
return 0;
@@ -977,6 +912,12 @@ static int vi_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_TEGRA_SYNCPT_TIMEOUT_RETRY:
chan->syncpt_timeout_retry = ctrl->val;
break;
+ case V4L2_CID_HFLIP:
+ chan->hflip = ctrl->val;
+ break;
+ case V4L2_CID_VFLIP:
+ chan->vflip = ctrl->val;
+ break;
default:
return -EINVAL;
}
@@ -1048,6 +989,12 @@ static int tegra_channel_setup_ctrl_handler(struct tegra_vi_channel *chan)
v4l2_ctrl_handler_free(&chan->ctrl_handler);
return ret;
}
+
+ if (chan->vi->soc->has_h_v_flip) {
+ v4l2_ctrl_new_std(&chan->ctrl_handler, &vi_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(&chan->ctrl_handler, &vi_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
+ }
+
#endif
/* setup the controls */
@@ -1119,7 +1066,7 @@ static int vi_fmts_bitmap_init(struct tegra_vi_channel *chan)
* there are no matched formats.
*/
if (!match_code) {
- match_code = tegra_default_format.code;
+ match_code = chan->vi->soc->default_video_format->code;
index = tegra_get_format_idx_by_code(chan->vi, match_code, 0);
if (WARN_ON(index < 0))
return -EINVAL;
@@ -1133,21 +1080,11 @@ static int vi_fmts_bitmap_init(struct tegra_vi_channel *chan)
return 0;
}
-static void tegra_channel_host1x_syncpts_free(struct tegra_vi_channel *chan)
-{
- int i;
-
- for (i = 0; i < chan->numgangports; i++) {
- host1x_syncpt_put(chan->mw_ack_sp[i]);
- host1x_syncpt_put(chan->frame_start_sp[i]);
- }
-}
-
static void tegra_channel_cleanup(struct tegra_vi_channel *chan)
{
v4l2_ctrl_handler_free(&chan->ctrl_handler);
media_entity_cleanup(&chan->video.entity);
- tegra_channel_host1x_syncpts_free(chan);
+ chan->vi->ops->channel_host1x_syncpt_free(chan);
mutex_destroy(&chan->video_lock);
}
@@ -1165,42 +1102,6 @@ void tegra_channels_cleanup(struct tegra_vi *vi)
}
}
-static int tegra_channel_host1x_syncpt_init(struct tegra_vi_channel *chan)
-{
- struct tegra_vi *vi = chan->vi;
- unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
- struct host1x_syncpt *fs_sp;
- struct host1x_syncpt *mw_sp;
- int ret, i;
-
- for (i = 0; i < chan->numgangports; i++) {
- fs_sp = host1x_syncpt_request(&vi->client, flags);
- if (!fs_sp) {
- dev_err(vi->dev, "failed to request frame start syncpoint\n");
- ret = -ENOMEM;
- goto free_syncpts;
- }
-
- mw_sp = host1x_syncpt_request(&vi->client, flags);
- if (!mw_sp) {
- dev_err(vi->dev, "failed to request memory ack syncpoint\n");
- host1x_syncpt_put(fs_sp);
- ret = -ENOMEM;
- goto free_syncpts;
- }
-
- chan->frame_start_sp[i] = fs_sp;
- chan->mw_ack_sp[i] = mw_sp;
- spin_lock_init(&chan->sp_incr_lock[i]);
- }
-
- return 0;
-
-free_syncpts:
- tegra_channel_host1x_syncpts_free(chan);
- return ret;
-}
-
static int tegra_channel_init(struct tegra_vi_channel *chan)
{
struct tegra_vi *vi = chan->vi;
@@ -1216,7 +1117,7 @@ static int tegra_channel_init(struct tegra_vi_channel *chan)
init_waitqueue_head(&chan->done_wait);
/* initialize the video format */
- chan->fmtinfo = &tegra_default_format;
+ chan->fmtinfo = chan->vi->soc->default_video_format;
chan->format.pixelformat = chan->fmtinfo->fourcc;
chan->format.colorspace = V4L2_COLORSPACE_SRGB;
chan->format.field = V4L2_FIELD_NONE;
@@ -1224,9 +1125,9 @@ static int tegra_channel_init(struct tegra_vi_channel *chan)
chan->format.height = TEGRA_DEF_HEIGHT;
chan->format.bytesperline = TEGRA_DEF_WIDTH * chan->fmtinfo->bpp;
chan->format.sizeimage = chan->format.bytesperline * TEGRA_DEF_HEIGHT;
- tegra_channel_fmt_align(chan, &chan->format, chan->fmtinfo->bpp);
+ vi->ops->vi_fmt_align(&chan->format, chan->fmtinfo->bpp);
- ret = tegra_channel_host1x_syncpt_init(chan);
+ ret = vi->ops->channel_host1x_syncpt_init(chan);
if (ret)
return ret;
@@ -1289,7 +1190,7 @@ free_v4l2_ctrl_hdl:
cleanup_media:
media_entity_cleanup(&chan->video.entity);
free_syncpts:
- tegra_channel_host1x_syncpts_free(chan);
+ vi->ops->channel_host1x_syncpt_free(chan);
return ret;
}
@@ -1351,7 +1252,7 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi)
struct device_node *node = vi->dev->of_node;
struct device_node *ep = NULL;
struct device_node *ports;
- struct device_node *port;
+ struct device_node *port = NULL;
unsigned int port_num;
struct device_node *parent;
struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 };
@@ -1360,7 +1261,7 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi)
ports = of_get_child_by_name(node, "ports");
if (!ports)
- return -ENODEV;
+ return dev_err_probe(vi->dev, -ENODEV, "%pOF: missing 'ports' node\n", node);
for_each_child_of_node(ports, port) {
if (!of_node_name_eq(port, "port"))
@@ -1374,7 +1275,6 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi)
dev_err(vi->dev, "invalid port num %d for %pOF\n",
port_num, port);
ret = -EINVAL;
- of_node_put(port);
goto cleanup;
}
@@ -1397,13 +1297,12 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi)
lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes;
ret = tegra_vi_channel_alloc(vi, port_num, port, lanes);
- if (ret < 0) {
- of_node_put(port);
+ if (ret < 0)
goto cleanup;
- }
}
cleanup:
+ of_node_put(port);
of_node_put(ports);
return ret;
}
@@ -1858,10 +1757,10 @@ static int tegra_vi_graph_init(struct tegra_vi *vi)
* Walk the links to parse the full graph. Each channel will have
* one endpoint of the composite node. Start by parsing the
* composite node and parse the remote entities in turn.
- * Each channel will register v4l2 async notifier to make the graph
- * independent between the channels so we can the current channel
+ * Each channel will register a v4l2 async notifier to make the graph
+ * independent between the channels so we can skip the current channel
* in case of something wrong during graph parsing and continue with
- * next channels.
+ * the next channels.
*/
list_for_each_entry(chan, &vi->vi_chans, list) {
struct fwnode_handle *ep, *remote;
@@ -1920,11 +1819,8 @@ static int tegra_vi_init(struct host1x_client *client)
ret = tegra_vi_tpg_channels_alloc(vi);
else
ret = tegra_vi_channels_alloc(vi);
- if (ret < 0) {
- dev_err(vi->dev,
- "failed to allocate vi channels: %d\n", ret);
+ if (ret < 0)
goto free_chans;
- }
ret = tegra_vi_channels_init(vi);
if (ret < 0)
@@ -2026,6 +1922,9 @@ static int tegra_vi_probe(struct platform_device *pdev)
vi->client.ops = &vi_client_ops;
vi->client.dev = &pdev->dev;
+ if (vi->ops->vi_enable)
+ vi->ops->vi_enable(vi, true);
+
ret = host1x_client_register(&vi->client);
if (ret < 0) {
dev_err(&pdev->dev,
@@ -2036,6 +1935,8 @@ static int tegra_vi_probe(struct platform_device *pdev)
return 0;
rpm_disable:
+ if (vi->ops->vi_enable)
+ vi->ops->vi_enable(vi, false);
pm_runtime_disable(&pdev->dev);
return ret;
}
@@ -2046,12 +1947,17 @@ static int tegra_vi_remove(struct platform_device *pdev)
host1x_client_unregister(&vi->client);
+ if (vi->ops->vi_enable)
+ vi->ops->vi_enable(vi, false);
pm_runtime_disable(&pdev->dev);
return 0;
}
static const struct of_device_id tegra_vi_of_id_table[] = {
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ { .compatible = "nvidia,tegra20-vi", .data = &tegra20_vi_soc },
+#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
{ .compatible = "nvidia,tegra210-vi", .data = &tegra210_vi_soc },
#endif
diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h
index a68e2c02c7b0..1e6a5caa7082 100644
--- a/drivers/staging/media/tegra-video/vi.h
+++ b/drivers/staging/media/tegra-video/vi.h
@@ -25,17 +25,11 @@
#define V4L2_CID_TEGRA_SYNCPT_TIMEOUT_RETRY (V4L2_CTRL_CLASS_CAMERA | 0x1001)
-#define TEGRA_MIN_WIDTH 32U
-#define TEGRA_MAX_WIDTH 32768U
-#define TEGRA_MIN_HEIGHT 32U
-#define TEGRA_MAX_HEIGHT 32768U
-
#define TEGRA_DEF_WIDTH 1920
#define TEGRA_DEF_HEIGHT 1080
#define TEGRA_IMAGE_FORMAT_DEF 32
#define MAX_FORMAT_NUM 64
-#define SURFACE_ALIGN_BYTES 64
enum tegra_vi_pg_mode {
TEGRA_VI_PG_DISABLED = 0,
@@ -43,8 +37,17 @@ enum tegra_vi_pg_mode {
TEGRA_VI_PG_PATCH,
};
+struct tegra_vi;
+struct tegra_vi_channel;
+
/**
* struct tegra_vi_ops - Tegra VI operations
+ * @vi_enable: soc-specific operations needed to enable/disable the VI peripheral
+ * @channel_host1x_syncpt_init: initialize synchronization points
+ * @channel_host1x_syncpt_free: free all synchronization points
+ * @vi_fmt_align: modify `pix` to fit the hardware alignment
+ * requirements and fill image geometry
+ * @channel_queue_setup: additional operations at the end of vb2_ops::queue_setup
* @vi_start_streaming: starts media pipeline, subdevice streaming, sets up
* VI for capture and runs capture start and capture finish
* kthreads for capturing frames to buffer and returns them back.
@@ -52,6 +55,11 @@ enum tegra_vi_pg_mode {
* back any queued buffers.
*/
struct tegra_vi_ops {
+ int (*vi_enable)(struct tegra_vi *vi, bool on);
+ int (*channel_host1x_syncpt_init)(struct tegra_vi_channel *chan);
+ void (*channel_host1x_syncpt_free)(struct tegra_vi_channel *chan);
+ void (*vi_fmt_align)(struct v4l2_pix_format *pix, unsigned int bpp);
+ void (*channel_queue_setup)(struct tegra_vi_channel *chan);
int (*vi_start_streaming)(struct vb2_queue *vq, u32 count);
void (*vi_stop_streaming)(struct vb2_queue *vq);
};
@@ -61,18 +69,22 @@ struct tegra_vi_ops {
*
* @video_formats: supported video formats
* @nformats: total video formats
+ * @default_video_format: default video format (pointer to a @video_formats item)
* @ops: vi operations
* @hw_revision: VI hw_revision
* @vi_max_channels: supported max streaming channels
* @vi_max_clk_hz: VI clock max frequency
+ * @has_h_v_flip: the chip can do H and V flip, and the driver implements it
*/
struct tegra_vi_soc {
const struct tegra_video_format *video_formats;
const unsigned int nformats;
+ const struct tegra_video_format *default_video_format;
const struct tegra_vi_ops *ops;
u32 hw_revision;
unsigned int vi_max_channels;
unsigned int vi_max_clk_hz;
+ bool has_h_v_flip:1;
};
/**
@@ -99,19 +111,6 @@ struct tegra_vi {
};
/**
- * struct tegra_vi_graph_entity - Entity in the video graph
- *
- * @asd: subdev asynchronous registration information
- * @entity: media entity from the corresponding V4L2 subdev
- * @subdev: V4L2 subdev
- */
-struct tegra_vi_graph_entity {
- struct v4l2_async_subdev asd;
- struct media_entity *entity;
- struct v4l2_subdev *subdev;
-};
-
-/**
* struct tegra_vi_channel - Tegra video channel
*
* @list: list head for this entry
@@ -122,11 +121,13 @@ struct tegra_vi_graph_entity {
* @vi: Tegra video input device structure
* @frame_start_sp: host1x syncpoint pointer to synchronize programmed capture
* start condition with hardware frame start events through host1x
- * syncpoint counters.
+ * syncpoint counters. (Tegra210)
* @mw_ack_sp: host1x syncpoint pointer to synchronize programmed memory write
* ack trigger condition with hardware memory write done at end of
- * frame through host1x syncpoint counters.
+ * frame through host1x syncpoint counters (On Tegra20 used for the
+ * OUT_1 syncpt)
* @sp_incr_lock: protects cpu syncpoint increment.
+ * @next_out_sp_idx: next expected value for mw_ack_sp[0], i.e. OUT_1 (Tegra20)
*
* @kthread_start_capture: kthread to start capture of single frame when
* vb buffer is available. This thread programs VI CSI hardware
@@ -151,6 +152,12 @@ struct tegra_vi_graph_entity {
* @queue: vb2 buffers queue
* @sequence: V4L2 buffers sequence number
*
+ * @addr_offset_u: U plane base address, relative to buffer base address (only for planar)
+ * @addr_offset_v: V plane base address, relative to buffer base address (only for planar)
+ * @start_offset: 1st Y byte to write, relative to buffer base address (for H/V flip)
+ * @start_offset_u: 1st U byte to write, relative to buffer base address (for H/V flip)
+ * @start_offset_v: 1st V byte to write, relative to buffer base address (for H/V flip)
+ *
* @capture: list of queued buffers for capture
* @start_lock: protects the capture queued list
* @done: list of capture done queued buffers
@@ -167,6 +174,9 @@ struct tegra_vi_graph_entity {
* @tpg_fmts_bitmap: a bitmap for supported TPG formats
* @pg_mode: test pattern generator mode (disabled/direct/patch)
* @notifier: V4L2 asynchronous subdevs notifier
+ *
+ * @hflip: Horizontal flip is enabled
+ * @vflip: Vertical flip is enabled
*/
struct tegra_vi_channel {
struct list_head list;
@@ -180,6 +190,7 @@ struct tegra_vi_channel {
struct host1x_syncpt *mw_ack_sp[GANG_PORTS_MAX];
/* protects the cpu syncpoint increment */
spinlock_t sp_incr_lock[GANG_PORTS_MAX];
+ u32 next_out_sp_idx;
struct task_struct *kthread_start_capture;
wait_queue_head_t start_wait;
@@ -191,6 +202,12 @@ struct tegra_vi_channel {
struct vb2_queue queue;
u32 sequence;
+ unsigned int addr_offset_u;
+ unsigned int addr_offset_v;
+ unsigned int start_offset;
+ unsigned int start_offset_u;
+ unsigned int start_offset_v;
+
struct list_head capture;
/* protects the capture queued list */
spinlock_t start_lock;
@@ -210,6 +227,9 @@ struct tegra_vi_channel {
enum tegra_vi_pg_mode pg_mode;
struct v4l2_async_notifier notifier;
+
+ bool hflip:1;
+ bool vflip:1;
};
/**
@@ -260,11 +280,11 @@ enum tegra_image_dt {
/**
* struct tegra_video_format - Tegra video format description
*
- * @img_dt: image data type
- * @bit_width: format width in bits per component
+ * @img_dt: MIPI CSI-2 data type (for CSI-2 only)
+ * @bit_width: format width in bits per component (for CSI/Tegra210 only)
* @code: media bus format code
* @bpp: bytes per pixel (when stored in memory)
- * @img_fmt: image format
+ * @img_fmt: image format (for CSI/Tegra210 only)
* @fourcc: V4L2 pixel format FCC identifier
*/
struct tegra_video_format {
@@ -276,6 +296,9 @@ struct tegra_video_format {
u32 fourcc;
};
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+extern const struct tegra_vi_soc tegra20_vi_soc;
+#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
extern const struct tegra_vi_soc tegra210_vi_soc;
#endif
diff --git a/drivers/staging/media/tegra-video/video.c b/drivers/staging/media/tegra-video/video.c
index d966b319553f..074ad0dc56ca 100644
--- a/drivers/staging/media/tegra-video/video.c
+++ b/drivers/staging/media/tegra-video/video.c
@@ -123,6 +123,10 @@ static int host1x_video_remove(struct host1x_device *dev)
}
static const struct of_device_id host1x_video_subdevs[] = {
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ { .compatible = "nvidia,tegra20-vip", },
+ { .compatible = "nvidia,tegra20-vi", },
+#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
{ .compatible = "nvidia,tegra210-csi", },
{ .compatible = "nvidia,tegra210-vi", },
@@ -141,6 +145,7 @@ static struct host1x_driver host1x_video_driver = {
static struct platform_driver * const drivers[] = {
&tegra_csi_driver,
+ &tegra_vip_driver,
&tegra_vi_driver,
};
diff --git a/drivers/staging/media/tegra-video/video.h b/drivers/staging/media/tegra-video/video.h
index fadaf2189dc9..7275affa6558 100644
--- a/drivers/staging/media/tegra-video/video.h
+++ b/drivers/staging/media/tegra-video/video.h
@@ -12,7 +12,6 @@
#include <media/v4l2-device.h>
#include "vi.h"
-#include "csi.h"
struct tegra_video_device {
struct v4l2_device v4l2_dev;
@@ -25,5 +24,6 @@ int tegra_v4l2_nodes_setup_tpg(struct tegra_video_device *vid);
void tegra_v4l2_nodes_cleanup_tpg(struct tegra_video_device *vid);
extern struct platform_driver tegra_vi_driver;
+extern struct platform_driver tegra_vip_driver;
extern struct platform_driver tegra_csi_driver;
#endif
diff --git a/drivers/staging/media/tegra-video/vip.c b/drivers/staging/media/tegra-video/vip.c
new file mode 100644
index 000000000000..a1ab886acc18
--- /dev/null
+++ b/drivers/staging/media/tegra-video/vip.c
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Parallel video capture module (VIP) for the Tegra VI.
+ *
+ * This file implements the VIP-specific infrastructure.
+ *
+ * Copyright (C) 2023 SKIDATA GmbH
+ * Author: Luca Ceresoli <luca.ceresoli@bootlin.com>
+ */
+
+#include <linux/device.h>
+#include <linux/host1x.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include <media/v4l2-fwnode.h>
+
+#include "vip.h"
+
+static inline struct tegra_vip *host1x_client_to_vip(struct host1x_client *client)
+{
+ return container_of(client, struct tegra_vip, client);
+}
+
+static inline struct tegra_vip_channel *subdev_to_vip_channel(struct v4l2_subdev *subdev)
+{
+ return container_of(subdev, struct tegra_vip_channel, subdev);
+}
+
+static inline struct tegra_vip *vip_channel_to_vip(struct tegra_vip_channel *chan)
+{
+ return container_of(chan, struct tegra_vip, chan);
+}
+
+/* Find the previous subdev in the pipeline (i.e. the one connected to our sink pad) */
+static struct v4l2_subdev *tegra_vip_channel_get_prev_subdev(struct tegra_vip_channel *chan)
+{
+ struct media_pad *remote_pad;
+
+ remote_pad = media_pad_remote_pad_first(&chan->pads[TEGRA_VIP_PAD_SINK]);
+ if (!remote_pad)
+ return NULL;
+
+ return media_entity_to_v4l2_subdev(remote_pad->entity);
+}
+
+static int tegra_vip_enable_stream(struct v4l2_subdev *subdev)
+{
+ struct tegra_vip_channel *vip_chan = subdev_to_vip_channel(subdev);
+ struct tegra_vip *vip = vip_channel_to_vip(vip_chan);
+ struct v4l2_subdev *prev_subdev = tegra_vip_channel_get_prev_subdev(vip_chan);
+ int err;
+
+ err = pm_runtime_resume_and_get(vip->dev);
+ if (err)
+ return dev_err_probe(vip->dev, err, "failed to get runtime PM\n");
+
+ err = vip->soc->ops->vip_start_streaming(vip_chan);
+ if (err < 0)
+ goto err_start_streaming;
+
+ err = v4l2_subdev_call(prev_subdev, video, s_stream, true);
+ if (err < 0 && err != -ENOIOCTLCMD)
+ goto err_prev_subdev_start_stream;
+
+ return 0;
+
+err_prev_subdev_start_stream:
+err_start_streaming:
+ pm_runtime_put(vip->dev);
+ return err;
+}
+
+static int tegra_vip_disable_stream(struct v4l2_subdev *subdev)
+{
+ struct tegra_vip_channel *vip_chan = subdev_to_vip_channel(subdev);
+ struct tegra_vip *vip = vip_channel_to_vip(vip_chan);
+ struct v4l2_subdev *prev_subdev = tegra_vip_channel_get_prev_subdev(vip_chan);
+
+ v4l2_subdev_call(prev_subdev, video, s_stream, false);
+
+ pm_runtime_put(vip->dev);
+
+ return 0;
+}
+
+static int tegra_vip_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+ int err;
+
+ if (enable)
+ err = tegra_vip_enable_stream(subdev);
+ else
+ err = tegra_vip_disable_stream(subdev);
+
+ return err;
+}
+
+static const struct v4l2_subdev_video_ops tegra_vip_video_ops = {
+ .s_stream = tegra_vip_s_stream,
+};
+
+static const struct v4l2_subdev_ops tegra_vip_ops = {
+ .video = &tegra_vip_video_ops,
+};
+
+static int tegra_vip_channel_of_parse(struct tegra_vip *vip)
+{
+ struct device *dev = vip->dev;
+ struct device_node *np = dev->of_node;
+ struct v4l2_fwnode_endpoint v4l2_ep = {
+ .bus_type = V4L2_MBUS_PARALLEL
+ };
+ struct fwnode_handle *fwh;
+ struct device_node *ep;
+ unsigned int num_pads;
+ int err;
+
+ dev_dbg(dev, "Parsing %pOF", np);
+
+ ep = of_graph_get_endpoint_by_regs(np, 0, 0);
+ if (!ep) {
+ err = -EINVAL;
+ dev_err_probe(dev, err, "%pOF: error getting endpoint node\n", np);
+ goto err_node_put;
+ }
+
+ fwh = of_fwnode_handle(ep);
+ err = v4l2_fwnode_endpoint_parse(fwh, &v4l2_ep);
+ of_node_put(ep);
+ if (err) {
+ dev_err_probe(dev, err, "%pOF: failed to parse v4l2 endpoint\n", np);
+ goto err_node_put;
+ }
+
+ num_pads = of_graph_get_endpoint_count(np);
+ if (num_pads != TEGRA_VIP_PADS_NUM) {
+ err = -EINVAL;
+ dev_err_probe(dev, err, "%pOF: need 2 pads, got %d\n", np, num_pads);
+ goto err_node_put;
+ }
+
+ vip->chan.of_node = of_node_get(np);
+ vip->chan.pads[TEGRA_VIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+ vip->chan.pads[TEGRA_VIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+ return 0;
+
+err_node_put:
+ of_node_put(np);
+ return err;
+}
+
+static int tegra_vip_channel_init(struct tegra_vip *vip)
+{
+ struct v4l2_subdev *subdev;
+ int err;
+
+ subdev = &vip->chan.subdev;
+ v4l2_subdev_init(subdev, &tegra_vip_ops);
+ subdev->dev = vip->dev;
+ snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "%s",
+ kbasename(vip->chan.of_node->full_name));
+
+ v4l2_set_subdevdata(subdev, &vip->chan);
+ subdev->fwnode = of_fwnode_handle(vip->chan.of_node);
+ subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+
+ err = media_entity_pads_init(&subdev->entity, TEGRA_VIP_PADS_NUM, vip->chan.pads);
+ if (err)
+ return dev_err_probe(vip->dev, err, "failed to initialize media entity\n");
+
+ err = v4l2_async_register_subdev(subdev);
+ if (err) {
+ dev_err_probe(vip->dev, err, "failed to register subdev\n");
+ goto err_register_subdev;
+ }
+
+ return 0;
+
+err_register_subdev:
+ media_entity_cleanup(&subdev->entity);
+ return err;
+}
+
+static int tegra_vip_init(struct host1x_client *client)
+{
+ struct tegra_vip *vip = host1x_client_to_vip(client);
+ int err;
+
+ err = tegra_vip_channel_of_parse(vip);
+ if (err)
+ return err;
+
+ err = tegra_vip_channel_init(vip);
+ if (err)
+ goto err_init;
+
+ return 0;
+
+err_init:
+ of_node_put(vip->chan.of_node);
+ return err;
+}
+
+static int tegra_vip_exit(struct host1x_client *client)
+{
+ struct tegra_vip *vip = host1x_client_to_vip(client);
+ struct v4l2_subdev *subdev = &vip->chan.subdev;
+
+ v4l2_async_unregister_subdev(subdev);
+ media_entity_cleanup(&subdev->entity);
+ of_node_put(vip->chan.of_node);
+
+ return 0;
+}
+
+static const struct host1x_client_ops vip_client_ops = {
+ .init = tegra_vip_init,
+ .exit = tegra_vip_exit,
+};
+
+static int tegra_vip_probe(struct platform_device *pdev)
+{
+ struct tegra_vip *vip;
+ int err;
+
+ dev_dbg(&pdev->dev, "Probing VIP \"%s\" from %pOF\n", pdev->name, pdev->dev.of_node);
+
+ vip = devm_kzalloc(&pdev->dev, sizeof(*vip), GFP_KERNEL);
+ if (!vip)
+ return -ENOMEM;
+
+ vip->soc = of_device_get_match_data(&pdev->dev);
+
+ vip->dev = &pdev->dev;
+ platform_set_drvdata(pdev, vip);
+
+ /* initialize host1x interface */
+ INIT_LIST_HEAD(&vip->client.list);
+ vip->client.ops = &vip_client_ops;
+ vip->client.dev = &pdev->dev;
+
+ err = host1x_client_register(&vip->client);
+ if (err)
+ return dev_err_probe(&pdev->dev, err, "failed to register host1x client\n");
+
+ pm_runtime_enable(&pdev->dev);
+
+ return 0;
+}
+
+static int tegra_vip_remove(struct platform_device *pdev)
+{
+ struct tegra_vip *vip = platform_get_drvdata(pdev);
+
+ host1x_client_unregister(&vip->client);
+
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+extern const struct tegra_vip_soc tegra20_vip_soc;
+#endif
+
+static const struct of_device_id tegra_vip_of_id_table[] = {
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ { .compatible = "nvidia,tegra20-vip", .data = &tegra20_vip_soc },
+#endif
+ { }
+};
+MODULE_DEVICE_TABLE(of, tegra_vip_of_id_table);
+
+struct platform_driver tegra_vip_driver = {
+ .driver = {
+ .name = "tegra-vip",
+ .of_match_table = tegra_vip_of_id_table,
+ },
+ .probe = tegra_vip_probe,
+ .remove = tegra_vip_remove,
+};
diff --git a/drivers/staging/media/tegra-video/vip.h b/drivers/staging/media/tegra-video/vip.h
new file mode 100644
index 000000000000..32ceaaccbba2
--- /dev/null
+++ b/drivers/staging/media/tegra-video/vip.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 SKIDATA GmbH
+ * Author: Luca Ceresoli <luca.ceresoli@bootlin.com>
+ */
+
+#ifndef __TEGRA_VIP_H__
+#define __TEGRA_VIP_H__
+
+#include <media/media-entity.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-subdev.h>
+
+enum {
+ TEGRA_VIP_PAD_SINK,
+ TEGRA_VIP_PAD_SOURCE,
+ TEGRA_VIP_PADS_NUM,
+};
+
+struct tegra_vip;
+
+/**
+ * struct tegra_vip_channel - Tegra VIP (parallel video capture) channel
+ *
+ * @subdev: V4L2 subdevice associated with this channel
+ * @pads: media pads for the subdevice entity
+ * @of_node: vip device tree node
+ */
+struct tegra_vip_channel {
+ struct v4l2_subdev subdev;
+ struct media_pad pads[TEGRA_VIP_PADS_NUM];
+ struct device_node *of_node;
+};
+
+/**
+ * struct tegra_vip_ops - Tegra VIP operations
+ *
+ * @vip_start_streaming: programs vip hardware to enable streaming.
+ */
+struct tegra_vip_ops {
+ int (*vip_start_streaming)(struct tegra_vip_channel *vip_chan);
+};
+
+/**
+ * struct tegra_vip_soc - NVIDIA Tegra VIP SoC structure
+ *
+ * @ops: vip hardware operations
+ */
+struct tegra_vip_soc {
+ const struct tegra_vip_ops *ops;
+};
+
+/**
+ * struct tegra_vip - NVIDIA Tegra VIP device structure
+ *
+ * @dev: device struct
+ * @client: host1x_client struct
+ * @soc: pointer to SoC data structure
+ * @chan: the VIP channel
+ */
+struct tegra_vip {
+ struct device *dev;
+ struct host1x_client client;
+ const struct tegra_vip_soc *soc;
+ struct tegra_vip_channel chan;
+};
+
+#endif
diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c
index 4e85e681922f..ce869280a056 100644
--- a/drivers/staging/most/i2c/i2c.c
+++ b/drivers/staging/most/i2c/i2c.c
@@ -362,7 +362,7 @@ static struct i2c_driver i2c_driver = {
.driver = {
.name = "hdm_i2c",
},
- .probe_new = i2c_probe,
+ .probe = i2c_probe,
.remove = i2c_remove,
.id_table = i2c_id,
};
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index 2fba52e0bd7b..d5271eac14f6 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -779,7 +779,7 @@ static struct i2c_driver dcon_driver = {
},
.class = I2C_CLASS_DDC | I2C_CLASS_HWMON,
.id_table = dcon_idtable,
- .probe_new = dcon_probe,
+ .probe = dcon_probe,
.remove = dcon_remove,
.detect = dcon_detect,
.address_list = normal_i2c,
diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c
index f08fdf06d566..220e157d4a5e 100644
--- a/drivers/staging/pi433/pi433_if.c
+++ b/drivers/staging/pi433/pi433_if.c
@@ -1019,7 +1019,6 @@ static int setup_gpio(struct pi433_device *device)
}
/* configure the pin */
- gpiod_unexport(device->gpiod[i]);
retval = gpiod_direction_input(device->gpiod[i]);
if (retval)
return retval;
diff --git a/drivers/staging/rtl8192e/rtl8192e/Kconfig b/drivers/staging/rtl8192e/rtl8192e/Kconfig
index eae8167f79dd..f8f774a16295 100644
--- a/drivers/staging/rtl8192e/rtl8192e/Kconfig
+++ b/drivers/staging/rtl8192e/rtl8192e/Kconfig
@@ -3,6 +3,7 @@ config RTL8192E
tristate "RealTek RTL8192E Wireless LAN NIC driver"
depends on PCI && WLAN && RTLLIB
depends on m
+ select CFG80211
select WIRELESS_EXT
select WEXT_PRIV
select CRYPTO
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h
index 385cca79f484..c229fd244a48 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h
@@ -85,7 +85,6 @@ enum rtl819x_loopback {
#define HAL_PRIME_CHNL_OFFSET_LOWER 1
#define HAL_PRIME_CHNL_OFFSET_UPPER 2
-
enum version_8190_loopback {
VERSION_8190_BD = 0x3,
VERSION_8190_BE
@@ -139,8 +138,6 @@ struct tx_fwinfo_8190pci {
u32 Retry_Limit:4;
u32 Reserved2:1;
u32 PacketID:13;
-
-
};
struct phy_ofdm_rx_status_rxsc_sgien_exintfflag {
@@ -172,7 +169,6 @@ struct phy_sts_cck_819xpci {
u8 cck_agc_rpt;
};
-
#define PHY_RSSI_SLID_WIN_MAX 100
#define PHY_Beacon_RSSI_SLID_WIN_MAX 10
@@ -214,7 +210,6 @@ struct tx_desc {
u32 Reserved7;
};
-
struct tx_desc_cmd {
u16 PktSize;
u8 Reserved1;
@@ -256,10 +251,8 @@ struct rx_desc {
u32 Reserved3;
u32 BufferAddress;
-
};
-
struct rx_fwinfo {
u16 Reserved1:12;
u16 PartAggr:1;
@@ -278,7 +271,6 @@ struct rx_fwinfo {
u8 Reserved4:1;
u32 TSFL;
-
};
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
index bb4539e337c8..7061f1cf4d3a 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
@@ -73,11 +73,11 @@ bool rtl92e_config_rf(struct net_device *dev)
break;
case RF90_PATH_B:
u4RegValue = rtl92e_get_bb_reg(dev, pPhyReg->rfintfs,
- bRFSI_RFENV<<16);
+ bRFSI_RFENV << 16);
break;
}
- rtl92e_set_bb_reg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
+ rtl92e_set_bb_reg(dev, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1);
rtl92e_set_bb_reg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
@@ -117,7 +117,7 @@ bool rtl92e_config_rf(struct net_device *dev)
break;
case RF90_PATH_B:
rtl92e_set_bb_reg(dev, pPhyReg->rfintfs,
- bRFSI_RFENV<<16, u4RegValue);
+ bRFSI_RFENV << 16, u4RegValue);
break;
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
index aed53fedeb61..e5925899402c 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
@@ -36,8 +36,8 @@ void rtl92e_start_beacon(struct net_device *dev)
rtl92e_writeb(dev, BCN_ERR_THRESH, 100);
- BcnTimeCfg |= BcnCW<<BCN_TCFG_CW_SHIFT;
- BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
+ BcnTimeCfg |= BcnCW << BCN_TCFG_CW_SHIFT;
+ BcnTimeCfg |= BcnIFS << BCN_TCFG_IFS;
rtl92e_writew(dev, BCN_TCFG, BcnTimeCfg);
rtl92e_irq_enable(dev);
}
@@ -46,23 +46,21 @@ static void _rtl92e_update_msr(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
u8 msr;
- enum led_ctl_mode LedAction = LED_CTL_NO_LINK;
msr = rtl92e_readb(dev, MSR);
msr &= ~MSR_LINK_MASK;
switch (priv->rtllib->iw_mode) {
case IW_MODE_INFRA:
- if (priv->rtllib->state == RTLLIB_LINKED)
+ if (priv->rtllib->link_state == MAC80211_LINKED)
msr |= MSR_LINK_MANAGED;
- LedAction = LED_CTL_LINK;
break;
case IW_MODE_ADHOC:
- if (priv->rtllib->state == RTLLIB_LINKED)
+ if (priv->rtllib->link_state == MAC80211_LINKED)
msr |= MSR_LINK_ADHOC;
break;
case IW_MODE_MASTER:
- if (priv->rtllib->state == RTLLIB_LINKED)
+ if (priv->rtllib->link_state == MAC80211_LINKED)
msr |= MSR_LINK_MASTER;
break;
default:
@@ -70,8 +68,6 @@ static void _rtl92e_update_msr(struct net_device *dev)
}
rtl92e_writeb(dev, MSR, msr);
- if (priv->rtllib->LedControlHandler)
- priv->rtllib->LedControlHandler(dev, LedAction);
}
void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val)
@@ -111,7 +107,6 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val)
}
rtl92e_writeb(dev, MSR, btMsr);
-
}
break;
@@ -130,7 +125,6 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val)
rtl92e_writel(dev, RCR, RegRCR);
priv->receive_config = RegRCR;
-
}
break;
@@ -168,7 +162,7 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val)
&priv->rtllib->current_network.qos_data.parameters;
u1bAIFS = qop->aifs[pAcParam] *
- ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
+ ((mode & (WIRELESS_MODE_G | WIRELESS_MODE_N_24G)) ? 9 : 20) + aSifsTime;
rtl92e_dm_init_edca_turbo(dev);
@@ -256,7 +250,7 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val)
case HW_VAR_SIFS:
rtl92e_writeb(dev, SIFS, val[0]);
- rtl92e_writeb(dev, SIFS+1, val[0]);
+ rtl92e_writeb(dev, SIFS + 1, val[0]);
break;
case HW_VAR_RF_TIMING:
@@ -270,7 +264,6 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val)
default:
break;
}
-
}
static void _rtl92e_read_eeprom_info(struct net_device *dev)
@@ -299,12 +292,12 @@ static void _rtl92e_read_eeprom_info(struct net_device *dev)
(EEPROM_Customer_ID >> 1)) >> 8;
priv->eeprom_customer_id = usValue & 0xff;
usValue = rtl92e_eeprom_read(dev,
- EEPROM_ICVersion_ChannelPlan>>1);
- priv->eeprom_chnl_plan = usValue&0xff;
- IC_Version = (usValue & 0xff00)>>8;
+ EEPROM_ICVersion_ChannelPlan >> 1);
+ priv->eeprom_chnl_plan = usValue & 0xff;
+ IC_Version = (usValue & 0xff00) >> 8;
ICVer8192 = IC_Version & 0xf;
- ICVer8256 = (IC_Version & 0xf0)>>4;
+ ICVer8256 = (IC_Version & 0xf0) >> 4;
if (ICVer8192 == 0x2) {
if (ICVer8256 == 0x5)
priv->card_8192_version = VERSION_8190_BE;
@@ -354,7 +347,7 @@ static void _rtl92e_read_eeprom_info(struct net_device *dev)
if (!priv->autoload_fail_flag)
priv->eeprom_thermal_meter = ((rtl92e_eeprom_read(dev,
- (EEPROM_ThermalMeter>>1))) &
+ (EEPROM_ThermalMeter >> 1))) &
0xff00) >> 8;
else
priv->eeprom_thermal_meter = EEPROM_Default_ThermalMeter;
@@ -596,7 +589,7 @@ start:
RSVD_FW_QUEUE_PAGE_MGNT_SHIFT);
rtl92e_writel(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW |
NUM_OF_PAGE_IN_FW_QUEUE_BCN <<
- RSVD_FW_QUEUE_PAGE_BCN_SHIFT|
+ RSVD_FW_QUEUE_PAGE_BCN_SHIFT |
NUM_OF_PAGE_IN_FW_QUEUE_PUB <<
RSVD_FW_QUEUE_PAGE_PUB_SHIFT);
@@ -605,7 +598,7 @@ start:
ulRegRead = (0xFFF00000 & rtl92e_readl(dev, RRSR)) |
RATE_ALL_OFDM_AG | RATE_ALL_CCK;
rtl92e_writel(dev, RRSR, ulRegRead);
- rtl92e_writel(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
+ rtl92e_writel(dev, RATR0 + 4 * 7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
rtl92e_writeb(dev, ACK_TIMEOUT, 0x30);
@@ -718,7 +711,6 @@ end:
static void _rtl92e_net_update(struct net_device *dev)
{
-
struct r8192_priv *priv = rtllib_priv(dev);
struct rtllib_network *net;
u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
@@ -738,8 +730,8 @@ static void _rtl92e_net_update(struct net_device *dev)
rtl92e_writew(dev, BCN_DRV_EARLY_INT, 10);
rtl92e_writeb(dev, BCN_ERR_THRESH, 100);
- BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
- BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
+ BcnTimeCfg |= (BcnCW << BCN_TCFG_CW_SHIFT);
+ BcnTimeCfg |= BcnIFS << BCN_TCFG_IFS;
rtl92e_writew(dev, BCN_TCFG, BcnTimeCfg);
}
@@ -753,7 +745,7 @@ void rtl92e_link_change(struct net_device *dev)
if (!priv->up)
return;
- if (ieee->state == RTLLIB_LINKED) {
+ if (ieee->link_state == MAC80211_LINKED) {
_rtl92e_net_update(dev);
rtl92e_update_ratr_table(dev);
if ((ieee->pairwise_key_type == KEY_TYPE_WEP40) ||
@@ -768,13 +760,14 @@ void rtl92e_link_change(struct net_device *dev)
u32 reg;
reg = rtl92e_readl(dev, RCR);
- if (priv->rtllib->state == RTLLIB_LINKED) {
+ if (priv->rtllib->link_state == MAC80211_LINKED) {
if (ieee->intel_promiscuous_md_info.promiscuous_on)
;
else
priv->receive_config = reg |= RCR_CBSSID;
- } else
+ } else {
priv->receive_config = reg &= ~RCR_CBSSID;
+ }
rtl92e_writel(dev, RCR, reg);
}
@@ -883,7 +876,7 @@ static u8 _rtl92e_rate_mgn_to_hw(u8 rate)
case MGN_MCS15:
ret = DESC90_RATEMCS15;
break;
- case (0x80|0x20):
+ case (0x80 | 0x20):
ret = DESC90_RATEMCS32;
break;
default:
@@ -973,7 +966,7 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
pTxFwInfo->RtsEnable = (cb_desc->bRTSEnable) ? 1 : 0;
pTxFwInfo->CtsEnable = (cb_desc->bCTSEnable) ? 1 : 0;
pTxFwInfo->RtsSTBC = (cb_desc->bRTSSTBC) ? 1 : 0;
- pTxFwInfo->RtsHT = (cb_desc->rts_rate&0x80) ? 1 : 0;
+ pTxFwInfo->RtsHT = (cb_desc->rts_rate & 0x80) ? 1 : 0;
pTxFwInfo->RtsRate = _rtl92e_rate_mgn_to_hw(cb_desc->rts_rate);
pTxFwInfo->RtsBandwidth = 0;
pTxFwInfo->RtsSubcarrier = cb_desc->RTSSC;
@@ -1008,8 +1001,7 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
pdesc->PktSize = skb->len - sizeof(struct tx_fwinfo_8190pci);
pdesc->SecCAMID = 0;
- pdesc->RATid = cb_desc->RATRIndex;
-
+ pdesc->RATid = cb_desc->ratr_index;
pdesc->NoEnc = 1;
pdesc->SecType = 0x0;
@@ -1217,7 +1209,6 @@ static long _rtl92e_signal_scale_mapping(struct r8192_priv *priv, long currsig)
return retsig;
}
-
#define rx_hal_is_cck_rate(_pdrvinfo)\
((_pdrvinfo->RxRate == DESC90_RATE1M ||\
_pdrvinfo->RxRate == DESC90_RATE2M ||\
@@ -1265,7 +1256,6 @@ static void _rtl92e_query_rxphystatus(
check_reg824 = 1;
}
-
prxpkt = (u8 *)pdrvinfo;
prxpkt += sizeof(struct rx_fwinfo);
@@ -1345,7 +1335,7 @@ static void _rtl92e_query_rxphystatus(
else if (pcck_buf->sq_rpt < 20)
sq = 100;
else
- sq = ((64-sq) * 100) / 44;
+ sq = ((64 - sq) * 100) / 44;
}
pstats->SignalQuality = sq;
precord_stats->SignalQuality = sq;
@@ -1372,7 +1362,6 @@ static void _rtl92e_query_rxphystatus(
}
}
-
rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1) & 0x7f) - 106;
pwdb_all = rtl92e_rx_db_to_percent(rx_pwr_all);
@@ -1452,7 +1441,7 @@ static void _rtl92e_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
slide_rssi_index = 0;
- tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
+ tmp_val = priv->stats.slide_rssi_total / slide_rssi_statistics;
priv->stats.signal_strength = rtl92e_translate_to_dbm(priv, tmp_val);
curr_st->rssi = priv->stats.signal_strength;
if (!prev_st->bPacketMatchBSSID) {
@@ -1482,14 +1471,13 @@ static void _rtl92e_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
} else {
priv->stats.rx_rssi_percentage[rfpath] =
((priv->stats.rx_rssi_percentage[rfpath] *
- (RX_SMOOTH-1)) +
+ (RX_SMOOTH - 1)) +
(prev_st->RxMIMOSignalStrength[rfpath])) /
(RX_SMOOTH);
}
}
}
-
if (prev_st->bPacketBeacon) {
if (slide_beacon_adc_pwdb_statistics++ >=
PHY_Beacon_RSSI_SLID_WIN_MAX) {
@@ -1517,14 +1505,14 @@ static void _rtl92e_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
if (prev_st->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) {
priv->undecorated_smoothed_pwdb =
(((priv->undecorated_smoothed_pwdb) *
- (RX_SMOOTH-1)) +
+ (RX_SMOOTH - 1)) +
(prev_st->RxPWDBAll)) / (RX_SMOOTH);
priv->undecorated_smoothed_pwdb =
priv->undecorated_smoothed_pwdb + 1;
} else {
priv->undecorated_smoothed_pwdb =
(((priv->undecorated_smoothed_pwdb) *
- (RX_SMOOTH-1)) +
+ (RX_SMOOTH - 1)) +
(prev_st->RxPWDBAll)) / (RX_SMOOTH);
}
rtl92e_update_rx_statistics(priv, prev_st);
@@ -1753,7 +1741,7 @@ bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats,
(pDrvInfo->FirstAGGR == 1);
stats->TimeStampLow = pDrvInfo->TSFL;
- stats->TimeStampHigh = rtl92e_readl(dev, TSFR+4);
+ stats->TimeStampHigh = rtl92e_readl(dev, TSFR + 4);
rtl92e_update_rx_pkt_timestamp(dev, stats);
@@ -1766,7 +1754,7 @@ bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats,
skb_trim(skb, skb->len - S_CRC_LEN);
- stats->packetlength = stats->Length-4;
+ stats->packetlength = stats->Length - 4;
stats->fraglength = stats->packetlength;
stats->fragoffset = 0;
stats->ntotalfrag = 1;
@@ -1806,7 +1794,6 @@ void rtl92e_stop_adapter(struct net_device *dev, bool reset)
rtl92e_writel(dev, WFCRC1, 0xffffffff);
rtl92e_writel(dev, WFCRC2, 0xffffffff);
-
rtl92e_writeb(dev, PMR, 0x5);
rtl92e_writeb(dev, MAC_BLK_CTRL, 0xa);
}
@@ -1830,18 +1817,14 @@ void rtl92e_update_ratr_table(struct net_device *dev)
rtl92e_config_rate(dev, &rate_config);
ratr_value = rate_config | *pMcsRate << 12;
switch (ieee->mode) {
- case IEEE_A:
- ratr_value &= 0x00000FF0;
- break;
- case IEEE_B:
+ case WIRELESS_MODE_B:
ratr_value &= 0x0000000F;
break;
- case IEEE_G:
- case IEEE_G|IEEE_B:
+ case WIRELESS_MODE_G:
+ case WIRELESS_MODE_G | WIRELESS_MODE_B:
ratr_value &= 0x00000FF7;
break;
- case IEEE_N_24G:
- case IEEE_N_5G:
+ case WIRELESS_MODE_N_24G:
if (ieee->ht_info->peer_mimo_ps == 0)
ratr_value &= 0x0007F007;
else
@@ -1857,7 +1840,7 @@ void rtl92e_update_ratr_table(struct net_device *dev)
else if (!ieee->ht_info->cur_tx_bw40mhz &&
ieee->ht_info->bCurShortGI20MHz)
ratr_value |= 0x80000000;
- rtl92e_writel(dev, RATR0+rate_index*4, ratr_value);
+ rtl92e_writel(dev, RATR0 + rate_index * 4, ratr_value);
rtl92e_writeb(dev, UFWP, 1);
}
@@ -1881,7 +1864,7 @@ rtl92e_init_variables(struct net_device *dev)
RCR_AMF | RCR_ADF |
RCR_AICV |
RCR_AB | RCR_AM | RCR_APM |
- RCR_AAP | ((u32)7<<RCR_MXDMA_OFFSET) |
+ RCR_AAP | ((u32)7 << RCR_MXDMA_OFFSET) |
((u32)7 << RCR_FIFO_OFFSET) | RCR_ONLYERLPKT;
priv->irq_mask[0] = (u32)(IMR_ROK | IMR_VODOK | IMR_VIDOK |
@@ -1901,7 +1884,6 @@ void rtl92e_enable_irq(struct net_device *dev)
priv->irq_enabled = 1;
rtl92e_writel(dev, INTA_MASK, priv->irq_mask[0]);
-
}
void rtl92e_disable_irq(struct net_device *dev)
@@ -1933,7 +1915,6 @@ void rtl92e_enable_tx(struct net_device *dev)
rtl92e_writel(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma);
}
-
void rtl92e_ack_irq(struct net_device *dev, u32 *p_inta, u32 *p_intb)
{
*p_inta = rtl92e_readl(dev, ISR);
@@ -1976,7 +1957,7 @@ bool rtl92e_is_rx_stuck(struct net_device *dev)
}
- SlotIndex = (priv->silent_reset_rx_slot_index++)%SilentResetRxSoltNum;
+ SlotIndex = (priv->silent_reset_rx_slot_index++) % SilentResetRxSoltNum;
if (priv->rx_ctr == RegRxCounter) {
priv->silent_reset_rx_stuck_event[SlotIndex] = 1;
@@ -1990,8 +1971,6 @@ bool rtl92e_is_rx_stuck(struct net_device *dev)
TotalRxStuckCount +=
priv->silent_reset_rx_stuck_event[i];
}
-
-
} else {
priv->silent_reset_rx_stuck_event[SlotIndex] = 0;
}
@@ -2021,7 +2000,7 @@ bool rtl92e_get_nmode_support_by_sec(struct net_device *dev)
struct rtllib_device *ieee = priv->rtllib;
if (ieee->rtllib_ap_sec_type &&
- (ieee->rtllib_ap_sec_type(priv->rtllib)&(SEC_ALG_WEP |
+ (ieee->rtllib_ap_sec_type(priv->rtllib) & (SEC_ALG_WEP |
SEC_ALG_TKIP))) {
return false;
} else {
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h
index f4d4b01630a2..09f8c76b7e65 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h
@@ -159,7 +159,6 @@ enum _RTL8192PCI_HW {
WFCRC2 = 0x2f8,
BW_OPMODE = 0x300,
-#define BW_OPMODE_5G BIT1
#define BW_OPMODE_20MHZ BIT2
IC_VERRSION = 0x301,
MSR = 0x303,
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
index 4b0ebe96302e..875540a2079d 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
@@ -32,7 +32,6 @@ static u32 _rtl92e_calculate_bit_shift(u32 dwBitMask)
void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask,
u32 dwData)
{
-
u32 OriginalValue, BitShift, NewValue;
if (dwBitMask != bMaskDWord) {
@@ -40,8 +39,9 @@ void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask,
BitShift = _rtl92e_calculate_bit_shift(dwBitMask);
NewValue = (OriginalValue & ~dwBitMask) | (dwData << BitShift);
rtl92e_writel(dev, dwRegAddr, NewValue);
- } else
+ } else {
rtl92e_writel(dev, dwRegAddr, dwData);
+ }
}
u32 rtl92e_get_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask)
@@ -99,7 +99,6 @@ static u32 _rtl92e_phy_rf_read(struct net_device *dev,
rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);
return ret;
-
}
static void _rtl92e_phy_rf_write(struct net_device *dev,
@@ -165,10 +164,10 @@ void rtl92e_set_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath,
_rtl92e_phy_rf_fw_write(dev, eRFPath, RegAddr,
New_Value);
- } else
+ } else {
_rtl92e_phy_rf_fw_write(dev, eRFPath, RegAddr, Data);
+ }
udelay(200);
-
} else {
if (BitMask != bMask12Bits) {
Original_Value = _rtl92e_phy_rf_read(dev, eRFPath,
@@ -177,8 +176,9 @@ void rtl92e_set_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath,
New_Value = (Original_Value & ~BitMask) | (Data << BitShift);
_rtl92e_phy_rf_write(dev, eRFPath, RegAddr, New_Value);
- } else
+ } else {
_rtl92e_phy_rf_write(dev, eRFPath, RegAddr, Data);
+ }
}
}
@@ -226,7 +226,6 @@ static u32 _rtl92e_phy_rf_fw_read(struct net_device *dev,
return 0;
}
return rtl92e_readl(dev, RF_DATA);
-
}
static void _rtl92e_phy_rf_fw_write(struct net_device *dev,
@@ -247,10 +246,8 @@ static void _rtl92e_phy_rf_fw_write(struct net_device *dev,
break;
}
rtl92e_writel(dev, QPNR, Data);
-
}
-
void rtl92e_config_mac(struct net_device *dev)
{
u32 dwArrayLen = 0, i = 0;
@@ -267,12 +264,10 @@ void rtl92e_config_mac(struct net_device *dev)
}
for (i = 0; i < dwArrayLen; i += 3) {
if (pdwArray[i] == 0x318)
- pdwArray[i+2] = 0x00000800;
- rtl92e_set_bb_reg(dev, pdwArray[i], pdwArray[i+1],
- pdwArray[i+2]);
+ pdwArray[i + 2] = 0x00000800;
+ rtl92e_set_bb_reg(dev, pdwArray[i], pdwArray[i + 1],
+ pdwArray[i + 2]);
}
- return;
-
}
static void _rtl92e_phy_config_bb(struct net_device *dev, u8 ConfigType)
@@ -291,13 +286,13 @@ static void _rtl92e_phy_config_bb(struct net_device *dev, u8 ConfigType)
for (i = 0; i < PHY_REGArrayLen; i += 2) {
rtl92e_set_bb_reg(dev, Rtl819XPHY_REGArray_Table[i],
bMaskDWord,
- Rtl819XPHY_REGArray_Table[i+1]);
+ Rtl819XPHY_REGArray_Table[i + 1]);
}
} else if (ConfigType == BB_CONFIG_AGC_TAB) {
for (i = 0; i < AGCTAB_ArrayLen; i += 2) {
rtl92e_set_bb_reg(dev, Rtl819XAGCTAB_Array_Table[i],
bMaskDWord,
- Rtl819XAGCTAB_Array_Table[i+1]);
+ Rtl819XAGCTAB_Array_Table[i + 1]);
}
}
}
@@ -370,7 +365,6 @@ bool rtl92e_check_bb_and_rf(struct net_device *dev, enum hw90_block CheckBlock,
break;
}
-
if (dwRegRead != WriteData[i]) {
netdev_warn(dev, "%s(): Check failed.\n", __func__);
ret = false;
@@ -389,10 +383,10 @@ static bool _rtl92e_bb_config_para_file(struct net_device *dev)
u32 dwRegValue = 0;
bRegValue = rtl92e_readb(dev, BB_GLOBAL_RESET);
- rtl92e_writeb(dev, BB_GLOBAL_RESET, (bRegValue|BB_GLOBAL_RESET_BIT));
+ rtl92e_writeb(dev, BB_GLOBAL_RESET, (bRegValue | BB_GLOBAL_RESET_BIT));
dwRegValue = rtl92e_readl(dev, CPU_GEN);
- rtl92e_writel(dev, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST)));
+ rtl92e_writel(dev, CPU_GEN, (dwRegValue & (~CPU_GEN_BB_RST)));
for (eCheckItem = (enum hw90_block)HW90_BLOCK_PHY0;
eCheckItem <= HW90_BLOCK_PHY1; eCheckItem++) {
@@ -402,19 +396,18 @@ static bool _rtl92e_bb_config_para_file(struct net_device *dev)
if (!rtStatus)
return rtStatus;
}
- rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0);
+ rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bCCKEn | bOFDMEn, 0x0);
_rtl92e_phy_config_bb(dev, BB_CONFIG_PHY_REG);
dwRegValue = rtl92e_readl(dev, CPU_GEN);
- rtl92e_writel(dev, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST));
+ rtl92e_writel(dev, CPU_GEN, (dwRegValue | CPU_GEN_BB_RST));
_rtl92e_phy_config_bb(dev, BB_CONFIG_AGC_TAB);
if (priv->ic_cut > VERSION_8190_BD) {
dwRegValue = 0x0;
rtl92e_set_bb_reg(dev, rFPGA0_TxGainStage,
- (bXBTxAGC|bXCTxAGC|bXDTxAGC), dwRegValue);
-
+ (bXBTxAGC | bXCTxAGC | bXDTxAGC), dwRegValue);
dwRegValue = priv->crystal_cap;
rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, bXtalCap92x,
@@ -470,7 +463,6 @@ void rtl92e_set_tx_power(struct net_device *dev, u8 channel)
u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath)
{
-
int i;
switch (eRFPath) {
@@ -483,7 +475,6 @@ u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath)
rtl92e_set_rf_reg(dev, eRFPath, RTL8192E_RADIO_A_ARR[i],
bMask12Bits,
RTL8192E_RADIO_A_ARR[i + 1]);
-
}
break;
case RF90_PATH_B:
@@ -495,7 +486,6 @@ u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath)
rtl92e_set_rf_reg(dev, eRFPath, RTL8192E_RADIO_B_ARR[i],
bMask12Bits,
RTL8192E_RADIO_B_ARR[i + 1]);
-
}
break;
default:
@@ -503,7 +493,6 @@ u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath)
}
return 0;
-
}
static void _rtl92e_set_tx_power_level(struct net_device *dev, u8 channel)
@@ -645,7 +634,7 @@ static u8 _rtl92e_phy_switch_channel_step(struct net_device *dev, u8 channel,
rtl92e_set_rf_reg(dev,
(enum rf90_radio_path)eRFPath,
CurrentCmd->Para1, bMask12Bits,
- CurrentCmd->Para2<<7);
+ CurrentCmd->Para2 << 7);
break;
default:
break;
@@ -677,7 +666,6 @@ static void _rtl92e_phy_switch_channel(struct net_device *dev, u8 channel)
static void _rtl92e_phy_switch_channel_work_item(struct net_device *dev)
{
-
struct r8192_priv *priv = rtllib_priv(dev);
_rtl92e_phy_switch_channel(dev, priv->chan);
@@ -694,7 +682,6 @@ u8 rtl92e_set_channel(struct net_device *dev, u8 channel)
if (priv->sw_chnl_in_progress)
return false;
-
switch (priv->rtllib->mode) {
case WIRELESS_MODE_B:
if (channel > 14) {
@@ -824,7 +811,6 @@ static void _rtl92e_cck_tx_power_track_bw_switch(struct net_device *dev)
static void _rtl92e_set_bw_mode_work_item(struct net_device *dev)
{
-
struct r8192_priv *priv = rtllib_priv(dev);
u8 regBwOpMode;
@@ -880,7 +866,7 @@ static void _rtl92e_set_bw_mode_work_item(struct net_device *dev)
}
rtl92e_set_bb_reg(dev, rCCK0_System, bCCKSideBand,
- (priv->n_cur_40mhz_prime_sc>>1));
+ (priv->n_cur_40mhz_prime_sc >> 1));
rtl92e_set_bb_reg(dev, rOFDM1_LSTF, 0xC00,
priv->n_cur_40mhz_prime_sc);
@@ -890,7 +876,6 @@ static void _rtl92e_set_bw_mode_work_item(struct net_device *dev)
netdev_err(dev, "%s(): unknown Bandwidth: %#X\n", __func__,
priv->current_chnl_bw);
break;
-
}
rtl92e_set_bandwidth(dev, priv->current_chnl_bw);
@@ -904,7 +889,6 @@ void rtl92e_set_bw_mode(struct net_device *dev, enum ht_channel_width bandwidth,
{
struct r8192_priv *priv = rtllib_priv(dev);
-
if (priv->set_bw_mode_in_progress)
return;
@@ -921,7 +905,6 @@ void rtl92e_set_bw_mode(struct net_device *dev, enum ht_channel_width bandwidth,
priv->n_cur_40mhz_prime_sc = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
_rtl92e_set_bw_mode_work_item(dev);
-
}
void rtl92e_init_gain(struct net_device *dev, u8 Operation)
@@ -993,7 +976,6 @@ void rtl92e_init_gain(struct net_device *dev, u8 Operation)
void rtl92e_set_rf_off(struct net_device *dev)
{
-
rtl92e_set_bb_reg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0);
rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0);
@@ -1002,7 +984,6 @@ void rtl92e_set_rf_off(struct net_device *dev)
rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);
rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0);
rtl92e_writeb(dev, ANAPAR_FOR_8192PCIE, 0x07);
-
}
static bool _rtl92e_set_rf_power_state(struct net_device *dev,
@@ -1099,9 +1080,8 @@ static bool _rtl92e_set_rf_power_state(struct net_device *dev,
break;
}
- if (bResult) {
+ if (bResult)
priv->rtllib->rf_power_state = rf_power_state;
- }
priv->set_rf_pwr_state_in_progress = false;
return bResult;
@@ -1130,11 +1110,11 @@ void rtl92e_scan_op_backup(struct net_device *dev, u8 Operation)
if (priv->up) {
switch (Operation) {
case SCAN_OPT_BACKUP:
- priv->rtllib->InitialGainHandler(dev, IG_Backup);
+ priv->rtllib->init_gain_handler(dev, IG_Backup);
break;
case SCAN_OPT_RESTORE:
- priv->rtllib->InitialGainHandler(dev, IG_Restore);
+ priv->rtllib->init_gain_handler(dev, IG_Restore);
break;
}
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h
index e1b30fbdf8cc..24fb0ca539ea 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h
@@ -7,7 +7,6 @@
#ifndef _R819XU_PHYREG_H
#define _R819XU_PHYREG_H
-
#define RF_DATA 0x1d4
#define rPMAC_Reset 0x100
@@ -125,7 +124,6 @@
#define rOFDM0_TxCoeff5 0xcb4
#define rOFDM0_TxCoeff6 0xcb8
-
#define rOFDM1_LSTF 0xd00
#define rOFDM1_TRxPathEnable 0xd04
#define rOFDM1_CFO 0xd08
@@ -163,7 +161,6 @@
#define rTxAGC_Mcs11_Mcs08 0xe18
#define rTxAGC_Mcs15_Mcs12 0xe1c
-
#define rZebra1_HSSIEnable 0x0
#define rZebra1_TRxEnable1 0x1
#define rZebra1_TRxEnable2 0x2
@@ -269,7 +266,6 @@
#define b3WireAddressLength 0x400
#define b3WireRFPowerDown 0x1
/*#define bHWSISelect 0x8 */
-#define b5GPAPEPolarity 0x40000000
#define b2GPAPEPolarity 0x80000000
#define bRFSW_TxDefaultAnt 0x3
#define bRFSW_TxOptionAnt 0x30
@@ -287,7 +283,6 @@
#define bRFSI_ANTSW 0x100
#define bRFSI_ANTSWB 0x200
#define bRFSI_PAPE 0x400
-#define bRFSI_PAPE5G 0x800
#define bBandSelect 0x1
#define bHTSIG2_GI 0x80
#define bHTSIG2_Smoothing 0x01
@@ -819,7 +814,6 @@
#define bOFDMPHY0_End 0xcff
#define bOFDMPHY1_End 0xdff
-
#define bPMACControl 0x0
#define bWMACControl 0x1
#define bWNICControl 0x2
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
index a4d65b4d99c2..6d9e5c27017d 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
@@ -101,7 +101,6 @@ void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
else
usConfig |= BIT15 | (KeyType << 2) | KeyIndex;
-
for (i = 0; i < CAM_CONTENT_COUNT; i++) {
TargetCommand = i + CAM_CONTENT_COUNT * EntryNo;
TargetCommand |= BIT31 | BIT16;
@@ -149,7 +148,6 @@ void rtl92e_cam_restore(struct net_device *dev)
if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
(priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
-
for (EntryId = 0; EntryId < 4; EntryId++) {
MacAddr = CAM_CONST_ADDR[EntryId];
if (priv->rtllib->swcamtable[EntryId].bused) {
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index 27040d1e3230..4447489a16ea 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -169,7 +169,7 @@ bool rtl92e_set_rf_state(struct net_device *dev,
(priv->rtllib->iw_mode == IW_MODE_ADHOC)) {
if ((priv->rtllib->rf_off_reason > RF_CHANGE_BY_IPS) ||
(change_source > RF_CHANGE_BY_IPS)) {
- if (ieee->state == RTLLIB_LINKED)
+ if (ieee->link_state == MAC80211_LINKED)
priv->blinked_ingpio = true;
else
priv->blinked_ingpio = false;
@@ -277,7 +277,7 @@ static void _rtl92e_update_cap(struct net_device *dev, u16 cap)
}
}
- if (net->mode & (IEEE_G | IEEE_N_24G)) {
+ if (net->mode & (WIRELESS_MODE_G | WIRELESS_MODE_N_24G)) {
u8 slot_time_val;
u8 cur_slot_time = priv->slot_time;
@@ -327,7 +327,7 @@ static void _rtl92e_qos_activate(void *data)
int i;
mutex_lock(&priv->mutex);
- if (priv->rtllib->state != RTLLIB_LINKED)
+ if (priv->rtllib->link_state != MAC80211_LINKED)
goto success;
for (i = 0; i < QOS_QUEUE_NUM; i++)
@@ -344,7 +344,7 @@ static int _rtl92e_qos_handle_probe_response(struct r8192_priv *priv,
int ret = 0;
u32 size = sizeof(struct rtllib_qos_parameters);
- if (priv->rtllib->state != RTLLIB_LINKED)
+ if (priv->rtllib->link_state != MAC80211_LINKED)
return ret;
if (priv->rtllib->iw_mode != IW_MODE_INFRA)
@@ -400,7 +400,7 @@ static int _rtl92e_qos_assoc_resp(struct r8192_priv *priv,
if (!priv || !network)
return 0;
- if (priv->rtllib->state != RTLLIB_LINKED)
+ if (priv->rtllib->link_state != MAC80211_LINKED)
return 0;
if (priv->rtllib->iw_mode != IW_MODE_INFRA)
@@ -466,7 +466,7 @@ static void _rtl92e_prepare_beacon(struct tasklet_struct *t)
tcb_desc = (struct cb_desc *)(pnewskb->cb + 8);
tcb_desc->queue_index = BEACON_QUEUE;
tcb_desc->data_rate = 2;
- tcb_desc->RATRIndex = 7;
+ tcb_desc->ratr_index = 7;
tcb_desc->tx_dis_rate_fallback = 1;
tcb_desc->tx_use_drv_assinged_rate = 1;
skb_push(pnewskb, priv->rtllib->tx_headroom);
@@ -635,7 +635,7 @@ static int _rtl92e_sta_up(struct net_device *dev, bool is_silent_reset)
if (priv->polling_timer_on == 0)
rtl92e_check_rfctrl_gpio_timer(&priv->gpio_polling_timer);
- if (priv->rtllib->state != RTLLIB_LINKED)
+ if (priv->rtllib->link_state != MAC80211_LINKED)
rtllib_softmac_start_protocol(priv->rtllib, 0);
rtllib_reset_queue(priv->rtllib);
_rtl92e_watchdog_timer_cb(&priv->watch_dog_timer);
@@ -660,7 +660,7 @@ static int _rtl92e_sta_down(struct net_device *dev, bool shutdownrf)
priv->rtllib->rtllib_ips_leave(dev);
- if (priv->rtllib->state == RTLLIB_LINKED)
+ if (priv->rtllib->link_state == MAC80211_LINKED)
rtl92e_leisure_ps_leave(dev);
priv->up = 0;
@@ -716,9 +716,9 @@ static void _rtl92e_init_priv_handler(struct net_device *dev)
priv->rtllib->check_nic_enough_desc = _rtl92e_check_nic_enough_desc;
priv->rtllib->handle_assoc_response = _rtl92e_handle_assoc_response;
priv->rtllib->handle_beacon = _rtl92e_handle_beacon;
- priv->rtllib->SetWirelessMode = rtl92e_set_wireless_mode;
- priv->rtllib->LeisurePSLeave = rtl92e_leisure_ps_leave;
- priv->rtllib->SetBWModeHandler = rtl92e_set_bw_mode;
+ priv->rtllib->set_wireless_mode = rtl92e_set_wireless_mode;
+ priv->rtllib->leisure_ps_leave = rtl92e_leisure_ps_leave;
+ priv->rtllib->set_bw_mode_handler = rtl92e_set_bw_mode;
priv->rf_set_chan = rtl92e_set_channel;
priv->rtllib->start_send_beacons = rtl92e_start_beacon;
@@ -734,14 +734,9 @@ static void _rtl92e_init_priv_handler(struct net_device *dev)
priv->rtllib->SetHwRegHandler = rtl92e_set_reg;
priv->rtllib->AllowAllDestAddrHandler = rtl92e_set_monitor_mode;
- priv->rtllib->SetFwCmdHandler = NULL;
- priv->rtllib->InitialGainHandler = rtl92e_init_gain;
+ priv->rtllib->init_gain_handler = rtl92e_init_gain;
priv->rtllib->rtllib_ips_leave_wq = rtl92e_rtllib_ips_leave_wq;
priv->rtllib->rtllib_ips_leave = rtl92e_rtllib_ips_leave;
-
- priv->rtllib->LedControlHandler = NULL;
- priv->rtllib->UpdateBeaconInterruptHandler = NULL;
-
priv->rtllib->ScanOperationBackupHandler = rtl92e_scan_op_backup;
}
@@ -1014,7 +1009,7 @@ static enum reset_type _rtl92e_if_check_reset(struct net_device *dev)
if (rfState == rf_on &&
(priv->rtllib->iw_mode == IW_MODE_INFRA) &&
- (priv->rtllib->state == RTLLIB_LINKED))
+ (priv->rtllib->link_state == MAC80211_LINKED))
RxResetType = _rtl92e_rx_check_stuck(dev);
if (TxResetType == RESET_TYPE_NORMAL ||
@@ -1056,7 +1051,7 @@ RESET_START:
mutex_lock(&priv->wx_mutex);
- if (priv->rtllib->state == RTLLIB_LINKED)
+ if (priv->rtllib->link_state == MAC80211_LINKED)
rtl92e_leisure_ps_leave(dev);
if (priv->up) {
@@ -1078,9 +1073,9 @@ RESET_START:
rtl92e_dm_deinit(dev);
rtllib_stop_scan_syncro(ieee);
- if (ieee->state == RTLLIB_LINKED) {
+ if (ieee->link_state == MAC80211_LINKED) {
mutex_lock(&ieee->wx_mutex);
- netdev_info(dev, "ieee->state is RTLLIB_LINKED\n");
+ netdev_info(dev, "ieee->link_state is MAC80211_LINKED\n");
rtllib_stop_send_beacons(priv->rtllib);
del_timer_sync(&ieee->associate_timer);
cancel_delayed_work(&ieee->associate_retry_wq);
@@ -1088,7 +1083,7 @@ RESET_START:
netif_carrier_off(dev);
mutex_unlock(&ieee->wx_mutex);
} else {
- netdev_info(dev, "ieee->state is NOT LINKED\n");
+ netdev_info(dev, "ieee->link_state is NOT LINKED\n");
rtllib_softmac_stop_protocol(priv->rtllib, 0, true);
}
@@ -1115,14 +1110,14 @@ RESET_START:
rtl92e_enable_hw_security_config(dev);
- if (ieee->state == RTLLIB_LINKED && ieee->iw_mode ==
+ if (ieee->link_state == MAC80211_LINKED && ieee->iw_mode ==
IW_MODE_INFRA) {
ieee->set_chan(ieee->dev,
ieee->current_network.channel);
schedule_work(&ieee->associate_complete_wq);
- } else if (ieee->state == RTLLIB_LINKED && ieee->iw_mode ==
+ } else if (ieee->link_state == MAC80211_LINKED && ieee->iw_mode ==
IW_MODE_ADHOC) {
ieee->set_chan(ieee->dev,
ieee->current_network.channel);
@@ -1186,7 +1181,7 @@ static void _rtl92e_watchdog_wq_cb(void *data)
if (!priv->up || priv->hw_radio_off)
return;
- if (priv->rtllib->state >= RTLLIB_LINKED) {
+ if (priv->rtllib->link_state >= MAC80211_LINKED) {
if (priv->rtllib->CntAfterLink < 2)
priv->rtllib->CntAfterLink++;
} else {
@@ -1196,8 +1191,8 @@ static void _rtl92e_watchdog_wq_cb(void *data)
rtl92e_dm_watchdog(dev);
if (!rtllib_act_scanning(priv->rtllib, false)) {
- if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state ==
- RTLLIB_NOLINK) &&
+ if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->link_state ==
+ MAC80211_NOLINK) &&
(ieee->rf_power_state == rf_on) && !ieee->is_set_key &&
(!ieee->proto_stoppping) && !ieee->wx_set_enc) {
if ((ieee->pwr_save_ctrl.ReturnPoint ==
@@ -1207,7 +1202,7 @@ static void _rtl92e_watchdog_wq_cb(void *data)
}
}
}
- if ((ieee->state == RTLLIB_LINKED) && (ieee->iw_mode ==
+ if ((ieee->link_state == MAC80211_LINKED) && (ieee->iw_mode ==
IW_MODE_INFRA) && (!ieee->net_promiscuous_md)) {
if (ieee->link_detect_info.NumRxOkInPeriod > 100 ||
ieee->link_detect_info.NumTxOkInPeriod > 100)
@@ -1249,7 +1244,7 @@ static void _rtl92e_watchdog_wq_cb(void *data)
ieee->link_detect_info.bHigherBusyTraffic = bHigherBusyTraffic;
ieee->link_detect_info.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
- if (ieee->state == RTLLIB_LINKED && ieee->iw_mode == IW_MODE_INFRA) {
+ if (ieee->link_state == MAC80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) {
u32 TotalRxBcnNum = 0;
u32 TotalRxDataNum = 0;
@@ -1268,17 +1263,13 @@ static void _rtl92e_watchdog_wq_cb(void *data)
"===>%s(): AP is power off, chan:%d, connect another one\n",
__func__, priv->chan);
- ieee->state = RTLLIB_ASSOCIATING;
+ ieee->link_state = RTLLIB_ASSOCIATING;
RemovePeerTS(priv->rtllib,
priv->rtllib->current_network.bssid);
ieee->is_roaming = true;
ieee->is_set_key = false;
ieee->link_change(dev);
- if (ieee->LedControlHandler)
- ieee->LedControlHandler(ieee->dev,
- LED_CTL_START_TO_LINK);
-
notify_wx_assoc_event(ieee);
if (!(ieee->rtllib_ap_sec_type(ieee) &
@@ -1440,7 +1431,7 @@ static int _rtl92e_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
- tcb_desc->RATRIndex = 7;
+ tcb_desc->ratr_index = 7;
tcb_desc->tx_dis_rate_fallback = 1;
tcb_desc->tx_use_drv_assinged_rate = 1;
tcb_desc->bTxEnableFwCalcDur = 1;
@@ -1509,7 +1500,6 @@ static short _rtl92e_tx(struct net_device *dev, struct sk_buff *skb)
MAX_DEV_ADDR_SIZE);
struct tx_desc *pdesc = NULL;
struct rtllib_hdr_1addr *header = NULL;
- u16 fc = 0, type = 0;
u8 *pda_addr = NULL;
int idx;
u32 fwinfo_size = 0;
@@ -1525,8 +1515,6 @@ static short _rtl92e_tx(struct net_device *dev, struct sk_buff *skb)
fwinfo_size = sizeof(struct tx_fwinfo_8190pci);
header = (struct rtllib_hdr_1addr *)(((u8 *)skb->data) + fwinfo_size);
- fc = le16_to_cpu(header->frame_ctl);
- type = WLAN_FC_GET_TYPE(fc);
pda_addr = header->addr1;
if (!is_broadcast_ether_addr(pda_addr) && !is_multicast_ether_addr(pda_addr))
@@ -1548,11 +1536,6 @@ static short _rtl92e_tx(struct net_device *dev, struct sk_buff *skb)
spin_unlock_irqrestore(&priv->irq_th_lock, flags);
return skb->len;
}
-
- if (type == RTLLIB_FTYPE_DATA) {
- if (priv->rtllib->LedControlHandler)
- priv->rtllib->LedControlHandler(dev, LED_CTL_TX);
- }
rtl92e_fill_tx_desc(dev, pdesc, tcb_desc, skb);
__skb_queue_tail(&ring->queue, skb);
pdesc->OWN = 1;
@@ -1779,8 +1762,6 @@ static void _rtl92e_rx_normal(struct net_device *dev)
struct r8192_priv *priv = rtllib_priv(dev);
struct rtllib_hdr_1addr *rtllib_hdr = NULL;
bool unicast_packet = false;
- bool bLedBlinking = true;
- u16 fc = 0, type = 0;
u32 skb_len = 0;
int rx_queue_idx = RX_MPDU_QUEUE;
@@ -1788,7 +1769,6 @@ static void _rtl92e_rx_normal(struct net_device *dev)
.signal = 0,
.noise = (u8)-98,
.rate = 0,
- .freq = RTLLIB_24GHZ_BAND,
};
unsigned int count = priv->rxringcount;
@@ -1824,16 +1804,6 @@ static void _rtl92e_rx_normal(struct net_device *dev)
/* unicast packet */
unicast_packet = true;
}
- fc = le16_to_cpu(rtllib_hdr->frame_ctl);
- type = WLAN_FC_GET_TYPE(fc);
- if (type == RTLLIB_FTYPE_MGMT)
- bLedBlinking = false;
-
- if (bLedBlinking)
- if (priv->rtllib->LedControlHandler)
- priv->rtllib->LedControlHandler(dev,
- LED_CTL_RX);
-
skb_len = skb->len;
if (!rtllib_rx(priv->rtllib, skb, &stats)) {
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
index 285dac32c074..ec9e454299a8 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
@@ -231,7 +231,6 @@ struct r8192_priv {
struct rt_stats stats;
struct iw_statistics wstats;
- short (*rf_set_sens)(struct net_device *dev, short sens);
u8 (*rf_set_chan)(struct net_device *dev, u8 ch);
struct rx_desc *rx_ring[MAX_RX_QUEUE];
@@ -271,8 +270,6 @@ struct r8192_priv {
short promisc;
short chan;
- short sens;
- short max_sens;
bool ps_force;
u32 irq_mask[2];
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
index 56a8ec517c06..37c275cac40b 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
@@ -159,7 +159,6 @@ static void _rtl92e_dm_check_rate_adaptive(struct net_device *dev);
static void _rtl92e_dm_init_bandwidth_autoswitch(struct net_device *dev);
static void _rtl92e_dm_bandwidth_autoswitch(struct net_device *dev);
-
static void _rtl92e_dm_check_tx_power_tracking(struct net_device *dev);
static void _rtl92e_dm_bb_initialgain_restore(struct net_device *dev);
@@ -179,7 +178,6 @@ static void _rtl92e_dm_check_rx_path_selection(struct net_device *dev);
static void _rtl92e_dm_init_rx_path_selection(struct net_device *dev);
static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev);
-
static void _rtl92e_dm_init_fsync(struct net_device *dev);
static void _rtl92e_dm_deinit_fsync(struct net_device *dev);
@@ -219,9 +217,7 @@ void rtl92e_dm_init(struct net_device *dev)
void rtl92e_dm_deinit(struct net_device *dev)
{
-
_rtl92e_dm_deinit_fsync(dev);
-
}
void rtl92e_dm_watchdog(struct net_device *dev)
@@ -250,7 +246,6 @@ void rtl92e_dm_watchdog(struct net_device *dev)
void rtl92e_init_adaptive_rate(struct net_device *dev)
{
-
struct r8192_priv *priv = rtllib_priv(dev);
struct rate_adaptive *pra = &priv->rate_adaptive;
@@ -296,8 +291,7 @@ static void _rtl92e_dm_check_rate_adaptive(struct net_device *dev)
if (priv->rtllib->mode != WIRELESS_MODE_N_24G)
return;
- if (priv->rtllib->state == RTLLIB_LINKED) {
-
+ if (priv->rtllib->link_state == MAC80211_LINKED) {
bshort_gi_enabled = (ht_info->cur_tx_bw40mhz &&
ht_info->bCurShortGI40MHz) ||
(!ht_info->cur_tx_bw40mhz &&
@@ -353,7 +347,7 @@ static void _rtl92e_dm_check_rate_adaptive(struct net_device *dev)
if (pra->ping_rssi_enable) {
if (priv->undecorated_smoothed_pwdb <
- (long)(pra->ping_rssi_thresh_for_ra+5)) {
+ (long)(pra->ping_rssi_thresh_for_ra + 5)) {
if ((priv->undecorated_smoothed_pwdb <
(long)pra->ping_rssi_thresh_for_ra) ||
ping_rssi_state) {
@@ -524,7 +518,6 @@ static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev)
priv->rtllib->bdynamic_txpower_enable = false;
for (j = 0; j <= 30; j++) {
-
tx_cmd.op = TXCMD_SET_TX_PWR_TRACKING;
tx_cmd.length = 4;
tx_cmd.value = priv->pwr_track >> 24;
@@ -562,7 +555,7 @@ static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev)
for (k = 0; k < 5; k++) {
if (k != 4)
tmp_report[k] = rtl92e_readb(dev,
- Tssi_Report_Value1+k);
+ Tssi_Report_Value1 + k);
else
tmp_report[k] = rtl92e_readb(dev,
Tssi_Report_Value2);
@@ -629,8 +622,9 @@ static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev)
} else if (priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14) {
priv->bcck_in_ch14 = false;
rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
- } else
+ } else {
rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ }
}
if (priv->cck_present_attn_diff <= -12 ||
@@ -657,21 +651,21 @@ static void _rtl92e_dm_tx_power_tracking_cb_thermal(struct net_device *dev)
{
#define ThermalMeterVal 9
struct r8192_priv *priv = rtllib_priv(dev);
- u32 tmpRegA, TempCCk;
- u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval;
+ u32 tmp_reg, tmp_cck;
+ u8 tmp_ofdm_index, tmp_cck_index, tmp_cck_20m_index, tmp_cck_40m_index, tmpval;
int i = 0, CCKSwingNeedUpdate = 0;
if (!priv->tx_pwr_tracking_init) {
- tmpRegA = rtl92e_get_bb_reg(dev, rOFDM0_XATxIQImbalance,
+ tmp_reg = rtl92e_get_bb_reg(dev, rOFDM0_XATxIQImbalance,
bMaskDWord);
for (i = 0; i < OFDM_TABLE_LEN; i++) {
- if (tmpRegA == OFDMSwingTable[i])
+ if (tmp_reg == OFDMSwingTable[i])
priv->ofdm_index[0] = i;
}
- TempCCk = rtl92e_get_bb_reg(dev, rCCK0_TxFilter1, bMaskByte2);
+ tmp_cck = rtl92e_get_bb_reg(dev, rCCK0_TxFilter1, bMaskByte2);
for (i = 0; i < CCK_TABLE_LEN; i++) {
- if (TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0]) {
+ if (tmp_cck == (u32)CCKSwingTable_Ch1_Ch13[i][0]) {
priv->cck_index = i;
break;
}
@@ -680,42 +674,42 @@ static void _rtl92e_dm_tx_power_tracking_cb_thermal(struct net_device *dev)
return;
}
- tmpRegA = rtl92e_get_rf_reg(dev, RF90_PATH_A, 0x12, 0x078);
- if (tmpRegA < 3 || tmpRegA > 13)
+ tmp_reg = rtl92e_get_rf_reg(dev, RF90_PATH_A, 0x12, 0x078);
+ if (tmp_reg < 3 || tmp_reg > 13)
return;
- if (tmpRegA >= 12)
- tmpRegA = 12;
+ if (tmp_reg >= 12)
+ tmp_reg = 12;
priv->thermal_meter[0] = ThermalMeterVal;
priv->thermal_meter[1] = ThermalMeterVal;
- if (priv->thermal_meter[0] >= (u8)tmpRegA) {
- tmpOFDMindex = tmpCCK20Mindex = 6+(priv->thermal_meter[0] -
- (u8)tmpRegA);
- tmpCCK40Mindex = tmpCCK20Mindex - 6;
- if (tmpOFDMindex >= OFDM_TABLE_LEN)
- tmpOFDMindex = OFDM_TABLE_LEN - 1;
- if (tmpCCK20Mindex >= CCK_TABLE_LEN)
- tmpCCK20Mindex = CCK_TABLE_LEN - 1;
- if (tmpCCK40Mindex >= CCK_TABLE_LEN)
- tmpCCK40Mindex = CCK_TABLE_LEN - 1;
+ if (priv->thermal_meter[0] >= (u8)tmp_reg) {
+ tmp_ofdm_index = 6 + (priv->thermal_meter[0] - (u8)tmp_reg);
+ tmp_cck_20m_index = tmp_ofdm_index;
+ tmp_cck_40m_index = tmp_cck_20m_index - 6;
+ if (tmp_ofdm_index >= OFDM_TABLE_LEN)
+ tmp_ofdm_index = OFDM_TABLE_LEN - 1;
+ if (tmp_cck_20m_index >= CCK_TABLE_LEN)
+ tmp_cck_20m_index = CCK_TABLE_LEN - 1;
+ if (tmp_cck_40m_index >= CCK_TABLE_LEN)
+ tmp_cck_40m_index = CCK_TABLE_LEN - 1;
} else {
- tmpval = (u8)tmpRegA - priv->thermal_meter[0];
+ tmpval = (u8)tmp_reg - priv->thermal_meter[0];
if (tmpval >= 6) {
- tmpOFDMindex = 0;
- tmpCCK20Mindex = 0;
+ tmp_ofdm_index = 0;
+ tmp_cck_20m_index = 0;
} else {
- tmpOFDMindex = 6 - tmpval;
- tmpCCK20Mindex = 6 - tmpval;
+ tmp_ofdm_index = 6 - tmpval;
+ tmp_cck_20m_index = 6 - tmpval;
}
- tmpCCK40Mindex = 0;
+ tmp_cck_40m_index = 0;
}
if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20)
- tmpCCKindex = tmpCCK40Mindex;
+ tmp_cck_index = tmp_cck_40m_index;
else
- tmpCCKindex = tmpCCK20Mindex;
+ tmp_cck_index = tmp_cck_20m_index;
- priv->rec_cck_20m_idx = tmpCCK20Mindex;
- priv->rec_cck_40m_idx = tmpCCK40Mindex;
+ priv->rec_cck_20m_idx = tmp_cck_20m_index;
+ priv->rec_cck_40m_idx = tmp_cck_40m_index;
if (priv->rtllib->current_network.channel == 14 &&
!priv->bcck_in_ch14) {
@@ -727,15 +721,15 @@ static void _rtl92e_dm_tx_power_tracking_cb_thermal(struct net_device *dev)
CCKSwingNeedUpdate = 1;
}
- if (priv->cck_index != tmpCCKindex) {
- priv->cck_index = tmpCCKindex;
+ if (priv->cck_index != tmp_cck_index) {
+ priv->cck_index = tmp_cck_index;
CCKSwingNeedUpdate = 1;
}
if (CCKSwingNeedUpdate)
rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
- if (priv->ofdm_index[0] != tmpOFDMindex) {
- priv->ofdm_index[0] = tmpOFDMindex;
+ if (priv->ofdm_index[0] != tmp_ofdm_index) {
+ priv->ofdm_index[0] = tmp_ofdm_index;
rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, bMaskDWord,
OFDMSwingTable[priv->ofdm_index[0]]);
}
@@ -756,20 +750,17 @@ void rtl92e_dm_txpower_tracking_wq(void *data)
static void _rtl92e_dm_initialize_tx_power_tracking_tssi(struct net_device *dev)
{
-
struct r8192_priv *priv = rtllib_priv(dev);
priv->btxpower_tracking = true;
priv->txpower_count = 0;
priv->tx_pwr_tracking_init = false;
-
}
static void _rtl92e_dm_init_tx_power_tracking_thermal(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
-
if (priv->rtllib->FwRWRF)
priv->btxpower_tracking = true;
else
@@ -799,12 +790,10 @@ static void _rtl92e_dm_check_tx_power_tracking_tssi(struct net_device *dev)
return;
tx_power_track_counter++;
-
if (tx_power_track_counter >= 180) {
schedule_delayed_work(&priv->txpower_tracking_wq, 0);
tx_power_track_counter = 0;
}
-
}
static void _rtl92e_dm_check_tx_power_tracking_thermal(struct net_device *dev)
@@ -833,7 +822,6 @@ static void _rtl92e_dm_check_tx_power_tracking_thermal(struct net_device *dev)
netdev_info(dev, "===============>Schedule TxPowerTrackingWorkItem\n");
schedule_delayed_work(&priv->txpower_tracking_wq, 0);
TM_Trigger = 0;
-
}
static void _rtl92e_dm_check_tx_power_tracking(struct net_device *dev)
@@ -861,7 +849,7 @@ static void _rtl92e_dm_cck_tx_power_adjust_tssi(struct net_device *dev,
rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
TempVal = (u32)((dm_cck_tx_bb_gain[attenuation][2]) +
(dm_cck_tx_bb_gain[attenuation][3] << 8) +
- (dm_cck_tx_bb_gain[attenuation][4] << 16)+
+ (dm_cck_tx_bb_gain[attenuation][4] << 16) +
(dm_cck_tx_bb_gain[attenuation][5] << 24));
rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
TempVal = (u32)(dm_cck_tx_bb_gain[attenuation][6] +
@@ -875,7 +863,7 @@ static void _rtl92e_dm_cck_tx_power_adjust_tssi(struct net_device *dev,
rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][2]) +
(dm_cck_tx_bb_gain_ch14[attenuation][3] << 8) +
- (dm_cck_tx_bb_gain_ch14[attenuation][4] << 16)+
+ (dm_cck_tx_bb_gain_ch14[attenuation][4] << 16) +
(dm_cck_tx_bb_gain_ch14[attenuation][5] << 24));
rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][6]) +
@@ -898,7 +886,7 @@ static void _rtl92e_dm_cck_tx_power_adjust_thermal_meter(struct net_device *dev,
rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
TempVal = CCKSwingTable_Ch1_Ch13[priv->cck_index][2] +
(CCKSwingTable_Ch1_Ch13[priv->cck_index][3] << 8) +
- (CCKSwingTable_Ch1_Ch13[priv->cck_index][4] << 16)+
+ (CCKSwingTable_Ch1_Ch13[priv->cck_index][4] << 16) +
(CCKSwingTable_Ch1_Ch13[priv->cck_index][5] << 24);
rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
TempVal = CCKSwingTable_Ch1_Ch13[priv->cck_index][6] +
@@ -912,11 +900,11 @@ static void _rtl92e_dm_cck_tx_power_adjust_thermal_meter(struct net_device *dev,
rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
TempVal = CCKSwingTable_Ch14[priv->cck_index][2] +
(CCKSwingTable_Ch14[priv->cck_index][3] << 8) +
- (CCKSwingTable_Ch14[priv->cck_index][4] << 16)+
+ (CCKSwingTable_Ch14[priv->cck_index][4] << 16) +
(CCKSwingTable_Ch14[priv->cck_index][5] << 24);
rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
TempVal = CCKSwingTable_Ch14[priv->cck_index][6] +
- (CCKSwingTable_Ch14[priv->cck_index][7]<<8);
+ (CCKSwingTable_Ch14[priv->cck_index][7] << 8);
rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
}
@@ -965,7 +953,6 @@ void rtl92e_dm_restore_state(struct net_device *dev)
_rtl92e_dm_tx_power_reset_recovery(dev);
_rtl92e_dm_bb_initialgain_restore(dev);
-
}
static void _rtl92e_dm_bb_initialgain_restore(struct net_device *dev)
@@ -989,7 +976,6 @@ static void _rtl92e_dm_bb_initialgain_restore(struct net_device *dev)
rtl92e_set_bb_reg(dev, rCCK0_CCA, bit_mask,
(u32)priv->initgain_backup.cca);
rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1);
-
}
void rtl92e_dm_backup_state(struct net_device *dev)
@@ -1043,7 +1029,6 @@ static void _rtl92e_dm_dig_init(struct net_device *dev)
static void _rtl92e_dm_ctrl_initgain_byrssi(struct net_device *dev)
{
-
if (!dm_digtable.dig_enable_flag)
return;
@@ -1091,12 +1076,11 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_driver(struct net_device *dev)
dm_digtable.dig_state = DM_STA_DIG_OFF;
}
- if (priv->rtllib->state == RTLLIB_LINKED)
+ if (priv->rtllib->link_state == MAC80211_LINKED)
dm_digtable.cur_sta_connect_state = DIG_STA_CONNECT;
else
dm_digtable.cur_sta_connect_state = DIG_STA_DISCONNECT;
-
dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb;
_rtl92e_dm_initial_gain(dev);
_rtl92e_dm_pd_th(dev);
@@ -1104,7 +1088,6 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_driver(struct net_device *dev)
if (dm_digtable.dig_algorithm_switch)
dm_digtable.dig_algorithm_switch = 0;
dm_digtable.pre_sta_connect_state = dm_digtable.cur_sta_connect_state;
-
}
static void _rtl92e_dm_ctrl_initgain_byrssi_false_alarm(struct net_device *dev)
@@ -1123,7 +1106,7 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_false_alarm(struct net_device *dev)
dm_digtable.dig_algorithm_switch = 0;
}
- if (priv->rtllib->state != RTLLIB_LINKED)
+ if (priv->rtllib->link_state != MAC80211_LINKED)
return;
if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) &&
@@ -1146,7 +1129,7 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_false_alarm(struct net_device *dev)
rtl92e_writeb(dev, rOFDM0_XDAGCCore1, 0x17);
if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20)
- rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x00);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x00);
else
rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x42);
@@ -1183,7 +1166,7 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_false_alarm(struct net_device *dev)
}
if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20)
- rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x20);
else
rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44);
@@ -1194,7 +1177,6 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_false_alarm(struct net_device *dev)
_rtl92e_dm_ctrl_initgain_byrssi_highpwr(dev);
}
-
static void _rtl92e_dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1214,7 +1196,7 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev)
dm_digtable.dig_highpwr_state = DM_STA_DIG_ON;
if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20)
- rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x10);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x10);
else
rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x43);
} else {
@@ -1228,7 +1210,7 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev)
(priv->undecorated_smoothed_pwdb >=
dm_digtable.rssi_high_thresh)) {
if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20)
- rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x20);
else
rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44);
}
@@ -1339,18 +1321,18 @@ static void _rtl92e_dm_pd_th(struct net_device *dev)
(initialized <= 3) || force_write) {
if (dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) {
if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20)
- rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x00);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x00);
else
rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x42);
} else if (dm_digtable.curpd_thstate ==
DIG_PD_AT_NORMAL_POWER) {
if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20)
- rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x20);
else
rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44);
} else if (dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) {
if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20)
- rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x10);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x10);
else
rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x43);
}
@@ -1392,7 +1374,6 @@ static void _rtl92e_dm_cs_ratio(struct net_device *dev)
reset_cnt = priv->reset_count;
}
-
if ((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) ||
!initialized || force_write) {
if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER)
@@ -1426,7 +1407,7 @@ static void _rtl92e_dm_check_edca_turbo(struct net_device *dev)
if (priv->rtllib->iw_mode == IW_MODE_ADHOC)
goto dm_CheckEdcaTurbo_EXIT;
- if (priv->rtllib->state != RTLLIB_LINKED)
+ if (priv->rtllib->link_state != MAC80211_LINKED)
goto dm_CheckEdcaTurbo_EXIT;
if (priv->rtllib->ht_info->iot_action & HT_IOT_ACT_DISABLE_EDCA_TURBO)
goto dm_CheckEdcaTurbo_EXIT;
@@ -1435,7 +1416,7 @@ static void _rtl92e_dm_check_edca_turbo(struct net_device *dev)
curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
if (ht_info->iot_action & HT_IOT_ACT_EDCA_BIAS_ON_RX) {
- if (curTxOkCnt > 4*curRxOkCnt) {
+ if (curTxOkCnt > 4 * curRxOkCnt) {
if (priv->bis_cur_rdlstate ||
!priv->bcurrent_turbo_EDCA) {
rtl92e_writel(dev, EDCAPARA_BE,
@@ -1456,7 +1437,7 @@ static void _rtl92e_dm_check_edca_turbo(struct net_device *dev)
}
priv->bcurrent_turbo_EDCA = true;
} else {
- if (curRxOkCnt > 4*curTxOkCnt) {
+ if (curRxOkCnt > 4 * curTxOkCnt) {
if (!priv->bis_cur_rdlstate ||
!priv->bcurrent_turbo_EDCA) {
if (priv->rtllib->mode == WIRELESS_MODE_G)
@@ -1474,7 +1455,6 @@ static void _rtl92e_dm_check_edca_turbo(struct net_device *dev)
edca_setting_UL[ht_info->IOTPeer]);
priv->bis_cur_rdlstate = false;
}
-
}
priv->bcurrent_turbo_EDCA = true;
@@ -1489,7 +1469,6 @@ static void _rtl92e_dm_check_edca_turbo(struct net_device *dev)
}
}
-
dm_CheckEdcaTurbo_EXIT:
priv->rtllib->bis_any_nonbepkts = false;
lastTxOkCnt = priv->stats.txbytesunicast;
@@ -1519,7 +1498,7 @@ static void _rtl92e_dm_cts_to_self(struct net_device *dev)
if (ht_info->IOTPeer == HT_IOT_PEER_BROADCOM) {
curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
- if (curRxOkCnt > 4*curTxOkCnt)
+ if (curRxOkCnt > 4 * curTxOkCnt)
ht_info->iot_action &= ~HT_IOT_ACT_FORCED_CTS2SELF;
else
ht_info->iot_action |= HT_IOT_ACT_FORCED_CTS2SELF;
@@ -1546,7 +1525,7 @@ static void _rtl92e_dm_check_rf_ctrl_gpio(void *data)
tmp1byte = rtl92e_readb(dev, GPI);
- rf_power_state_to_set = (tmp1byte&BIT1) ? rf_on : rf_off;
+ rf_power_state_to_set = (tmp1byte & BIT1) ? rf_on : rf_off;
if (priv->hw_radio_off && (rf_power_state_to_set == rf_on)) {
netdev_info(dev, "gpiochangeRF - HW Radio ON\n");
@@ -1576,7 +1555,7 @@ void rtl92e_dm_rf_pathcheck_wq(void *data)
rfpath = rtl92e_readb(dev, 0xc04);
for (i = 0; i < RF90_PATH_MAX; i++) {
- if (rfpath & (0x01<<i))
+ if (rfpath & (0x01 << i))
priv->brfpath_rxenable[i] = true;
else
priv->brfpath_rxenable[i] = false;
@@ -1627,7 +1606,7 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev)
u8 update_cck_rx_path;
if (!cck_Rx_Path_initialized) {
- dm_rx_path_sel_table.cck_rx_path = (rtl92e_readb(dev, 0xa07)&0xf);
+ dm_rx_path_sel_table.cck_rx_path = (rtl92e_readb(dev, 0xa07) & 0xf);
cck_Rx_Path_initialized = 1;
}
@@ -1746,7 +1725,6 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev)
tmp_cck_min_pwdb = cur_cck_pwdb;
}
}
-
}
}
}
@@ -1763,11 +1741,11 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev)
if ((tmp_max_rssi - tmp_min_rssi) >=
dm_rx_path_sel_table.diff_th) {
dm_rx_path_sel_table.rf_enable_rssi_th[min_rssi_index] =
- tmp_max_rssi+5;
+ tmp_max_rssi + 5;
rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable,
- 0x1<<min_rssi_index, 0x0);
+ 0x1 << min_rssi_index, 0x0);
rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable,
- 0x1<<min_rssi_index, 0x0);
+ 0x1 << min_rssi_index, 0x0);
disabled_rf_cnt++;
}
if (dm_rx_path_sel_table.cck_method == CCK_Rx_Version_1) {
@@ -1779,7 +1757,7 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev)
}
if (update_cck_rx_path) {
- dm_rx_path_sel_table.cck_rx_path = (cck_default_Rx<<2) |
+ dm_rx_path_sel_table.cck_rx_path = (cck_default_Rx << 2) |
(cck_optional_Rx);
rtl92e_set_bb_reg(dev, rCCK0_AFESetting, 0x0f000000,
dm_rx_path_sel_table.cck_rx_path);
@@ -1812,7 +1790,6 @@ static void _rtl92e_dm_check_rx_path_selection(struct net_device *dev)
schedule_delayed_work(&priv->rfpath_check_wq, 0);
}
-
static void _rtl92e_dm_init_fsync(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1829,7 +1806,6 @@ static void _rtl92e_dm_init_fsync(struct net_device *dev)
timer_setup(&priv->fsync_timer, _rtl92e_dm_fsync_timer_callback, 0);
}
-
static void _rtl92e_dm_deinit_fsync(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1845,7 +1821,7 @@ static void _rtl92e_dm_fsync_timer_callback(struct timer_list *t)
bool bSwitchFromCountDiff = false;
bool bDoubleTimeInterval = false;
- if (priv->rtllib->state == RTLLIB_LINKED &&
+ if (priv->rtllib->link_state == MAC80211_LINKED &&
priv->rtllib->bfsync_enable &&
(priv->rtllib->ht_info->iot_action & HT_IOT_ACT_CDD_FSYNC)) {
u32 rate_bitmap;
@@ -1864,7 +1840,6 @@ static void _rtl92e_dm_fsync_timer_callback(struct timer_list *t)
else
rate_count_diff = rate_count - priv->rate_record;
if (rate_count_diff < priv->rate_count_diff_rec) {
-
u32 DiffNum = priv->rate_count_diff_rec -
rate_count_diff;
if (DiffNum >=
@@ -2005,7 +1980,6 @@ static void _rtl92e_dm_start_sw_fsync(struct net_device *dev)
add_timer(&priv->fsync_timer);
rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c12cd);
-
}
static void _rtl92e_dm_check_fsync(struct net_device *dev)
@@ -2017,7 +1991,7 @@ static void _rtl92e_dm_check_fsync(struct net_device *dev)
static u8 reg_c38_State = RegC38_Default;
static u32 reset_cnt;
- if (priv->rtllib->state == RTLLIB_LINKED &&
+ if (priv->rtllib->link_state == MAC80211_LINKED &&
priv->rtllib->ht_info->IOTPeer == HT_IOT_PEER_BROADCOM) {
if (priv->rtllib->bfsync_enable == 0) {
switch (priv->rtllib->fsync_state) {
@@ -2048,7 +2022,6 @@ static void _rtl92e_dm_check_fsync(struct net_device *dev)
case SW_Fsync:
default:
break;
-
}
}
if (reg_c38_State != RegC38_Fsync_AP_BCM) {
@@ -2071,7 +2044,7 @@ static void _rtl92e_dm_check_fsync(struct net_device *dev)
break;
}
- if (priv->rtllib->state == RTLLIB_LINKED) {
+ if (priv->rtllib->link_state == MAC80211_LINKED) {
if (priv->undecorated_smoothed_pwdb <=
RegC38_TH) {
if (reg_c38_State !=
@@ -2084,7 +2057,7 @@ static void _rtl92e_dm_check_fsync(struct net_device *dev)
RegC38_NonFsync_Other_AP;
}
} else if (priv->undecorated_smoothed_pwdb >=
- (RegC38_TH+5)) {
+ (RegC38_TH + 5)) {
if (reg_c38_State) {
rtl92e_writeb(dev,
rOFDM0_RxDetector3,
@@ -2132,7 +2105,7 @@ static void _rtl92e_dm_dynamic_tx_power(struct net_device *dev)
return;
}
if ((priv->rtllib->ht_info->IOTPeer == HT_IOT_PEER_ATHEROS) &&
- (priv->rtllib->mode == IEEE_G)) {
+ (priv->rtllib->mode == WIRELESS_MODE_G)) {
txhipower_threshold = TX_POWER_ATHEROAP_THRESH_HIGH;
txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW;
} else {
@@ -2140,7 +2113,7 @@ static void _rtl92e_dm_dynamic_tx_power(struct net_device *dev)
txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW;
}
- if (priv->rtllib->state == RTLLIB_LINKED) {
+ if (priv->rtllib->link_state == MAC80211_LINKED) {
if (priv->undecorated_smoothed_pwdb >= txhipower_threshold) {
priv->dynamic_tx_high_pwr = true;
priv->dynamic_tx_low_pwr = false;
@@ -2164,7 +2137,6 @@ static void _rtl92e_dm_dynamic_tx_power(struct net_device *dev)
}
priv->last_dtp_flag_high = priv->dynamic_tx_high_pwr;
priv->last_dtp_flag_low = priv->dynamic_tx_low_pwr;
-
}
static void _rtl92e_dm_check_txrateandretrycount(struct net_device *dev)
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c
index f4f7b74c8cd1..fab8932e67da 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c
@@ -27,8 +27,8 @@ static u32 _rtl92e_ethtool_get_link(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
- return ((priv->rtllib->state == RTLLIB_LINKED) ||
- (priv->rtllib->state == RTLLIB_LINKED_SCANNING));
+ return ((priv->rtllib->link_state == MAC80211_LINKED) ||
+ (priv->rtllib->link_state == MAC80211_LINKED_SCANNING));
}
const struct ethtool_ops rtl819x_ethtool_ops = {
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c
index 9c80dc1b6e12..d124b5eee0cc 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c
@@ -9,7 +9,6 @@
#include "r8190P_rtl8256.h"
#include "rtl_pm.h"
-
int rtl92e_suspend(struct device *dev_d)
{
struct net_device *dev = dev_get_drvdata(dev_d);
@@ -62,7 +61,6 @@ int rtl92e_resume(struct device *dev_d)
netdev_info(dev, "================>r8192E resume call.\n");
-
pci_read_config_dword(pdev, 0x40, &val);
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c
index 5a1cd22f5e25..1c49d5da68eb 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c
@@ -118,7 +118,7 @@ void rtl92e_ips_enter(struct net_device *dev)
rt_state = priv->rtllib->rf_power_state;
if (rt_state == rf_on && !psc->bSwRfProcessing &&
- (priv->rtllib->state != RTLLIB_LINKED) &&
+ (priv->rtllib->link_state != MAC80211_LINKED) &&
(priv->rtllib->iw_mode != IW_MODE_MASTER)) {
psc->eInactivePowerState = rf_off;
_rtl92e_ps_update_rf_state(dev);
@@ -209,7 +209,7 @@ void rtl92e_leisure_ps_enter(struct net_device *dev)
&priv->rtllib->pwr_save_ctrl;
if (!((priv->rtllib->iw_mode == IW_MODE_INFRA) &&
- (priv->rtllib->state == RTLLIB_LINKED))
+ (priv->rtllib->link_state == MAC80211_LINKED))
|| (priv->rtllib->iw_mode == IW_MODE_ADHOC) ||
(priv->rtllib->iw_mode == IW_MODE_MASTER))
return;
@@ -217,14 +217,11 @@ void rtl92e_leisure_ps_enter(struct net_device *dev)
if (psc->bLeisurePs) {
if (psc->LpsIdleCount >= RT_CHECK_FOR_HANG_PERIOD) {
- if (priv->rtllib->ps == RTLLIB_PS_DISABLED) {
- if (priv->rtllib->SetFwCmdHandler)
- priv->rtllib->SetFwCmdHandler(dev, FW_CMD_LPS_ENTER);
- _rtl92e_ps_set_mode(dev, RTLLIB_PS_MBCAST |
- RTLLIB_PS_UNICAST);
- }
- } else
+ if (priv->rtllib->ps == RTLLIB_PS_DISABLED)
+ _rtl92e_ps_set_mode(dev, RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST);
+ } else {
psc->LpsIdleCount++;
+ }
}
}
@@ -235,10 +232,7 @@ void rtl92e_leisure_ps_leave(struct net_device *dev)
&priv->rtllib->pwr_save_ctrl;
if (psc->bLeisurePs) {
- if (priv->rtllib->ps != RTLLIB_PS_DISABLED) {
+ if (priv->rtllib->ps != RTLLIB_PS_DISABLED)
_rtl92e_ps_set_mode(dev, RTLLIB_PS_DISABLED);
- if (priv->rtllib->SetFwCmdHandler)
- priv->rtllib->SetFwCmdHandler(dev, FW_CMD_LPS_LEAVE);
- }
}
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
index cb28288a618b..88975dc804c6 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
@@ -169,7 +169,7 @@ static int _rtl92e_wx_adapter_power_status(struct net_device *dev,
priv->ps_force = false;
psc->bLeisurePs = true;
} else {
- if (priv->rtllib->state == RTLLIB_LINKED)
+ if (priv->rtllib->link_state == MAC80211_LINKED)
rtl92e_leisure_ps_leave(dev);
priv->ps_force = true;
@@ -311,10 +311,6 @@ static int _rtl92e_wx_get_range(struct net_device *dev,
/* ~130 Mb/s real (802.11n) */
range->throughput = 130 * 1000 * 1000;
- if (priv->rf_set_sens != NULL)
- /* signal level threshold range */
- range->sensitivity = priv->max_sens;
-
range->max_qual.qual = 100;
range->max_qual.level = 0;
range->max_qual.noise = 0;
@@ -346,9 +342,11 @@ static int _rtl92e_wx_get_range(struct net_device *dev,
for (i = 0, val = 0; i < 14; i++) {
if ((priv->rtllib->active_channel_map)[i + 1]) {
+ s32 freq_khz;
+
range->freq[val].i = i + 1;
- range->freq[val].m = rtllib_wlan_frequencies[i] *
- 100000;
+ freq_khz = ieee80211_channel_to_freq_khz(i + 1, NL80211_BAND_2GHZ);
+ range->freq[val].m = freq_khz * 100;
range->freq[val].e = 1;
val++;
}
@@ -377,10 +375,10 @@ static int _rtl92e_wx_set_scan(struct net_device *dev,
int ret;
if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) {
- if ((ieee->state >= RTLLIB_ASSOCIATING) &&
- (ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED))
+ if ((ieee->link_state >= RTLLIB_ASSOCIATING) &&
+ (ieee->link_state <= RTLLIB_ASSOCIATING_AUTHENTICATED))
return 0;
- if ((priv->rtllib->state == RTLLIB_LINKED) &&
+ if ((priv->rtllib->link_state == MAC80211_LINKED) &&
(priv->rtllib->CntAfterLink < 2))
return 0;
}
@@ -393,7 +391,7 @@ static int _rtl92e_wx_set_scan(struct net_device *dev,
rt_state = priv->rtllib->rf_power_state;
if (!priv->up)
return -ENETDOWN;
- if (priv->rtllib->link_detect_info.bBusyTraffic == true)
+ if (priv->rtllib->link_detect_info.bBusyTraffic)
return -EAGAIN;
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
@@ -411,7 +409,7 @@ static int _rtl92e_wx_set_scan(struct net_device *dev,
priv->rtllib->FirstIe_InScan = true;
- if (priv->rtllib->state != RTLLIB_LINKED) {
+ if (priv->rtllib->link_state != MAC80211_LINKED) {
if (rt_state == rf_off) {
if (priv->rtllib->rf_off_reason >
RF_CHANGE_BY_IPS) {
@@ -425,10 +423,6 @@ static int _rtl92e_wx_set_scan(struct net_device *dev,
mutex_unlock(&priv->rtllib->ips_mutex);
}
rtllib_stop_scan(priv->rtllib);
- if (priv->rtllib->LedControlHandler)
- priv->rtllib->LedControlHandler(dev,
- LED_CTL_SITE_SURVEY);
-
if (priv->rtllib->rf_power_state != rf_off) {
priv->rtllib->actscanning = true;
@@ -574,9 +568,9 @@ static int _rtl92e_wx_set_frag(struct net_device *dev,
if (priv->hw_radio_off)
return 0;
- if (wrqu->frag.disabled)
+ if (wrqu->frag.disabled) {
priv->rtllib->fts = DEFAULT_FRAG_THRESHOLD;
- else {
+ } else {
if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
wrqu->frag.value > MAX_FRAG_THRESHOLD)
return -EINVAL;
@@ -807,45 +801,6 @@ static int _rtl92e_wx_get_retry(struct net_device *dev,
return 0;
}
-static int _rtl92e_wx_get_sens(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8192_priv *priv = rtllib_priv(dev);
-
- if (priv->rf_set_sens == NULL)
- return -1; /* we have not this support for this radio */
- wrqu->sens.value = priv->sens;
- return 0;
-}
-
-static int _rtl92e_wx_set_sens(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8192_priv *priv = rtllib_priv(dev);
-
- short err = 0;
-
- if (priv->hw_radio_off)
- return 0;
-
- mutex_lock(&priv->wx_mutex);
- if (priv->rf_set_sens == NULL) {
- err = -1; /* we have not this support for this radio */
- goto exit;
- }
- if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
- priv->sens = wrqu->sens.value;
- else
- err = -EINVAL;
-
-exit:
- mutex_unlock(&priv->wx_mutex);
-
- return err;
-}
-
static int _rtl92e_wx_set_encode_ext(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
@@ -1066,8 +1021,6 @@ static iw_handler r8192_wx_handlers[] = {
[IW_IOCTL(SIOCGIWFREQ)] = _rtl92e_wx_get_freq,
[IW_IOCTL(SIOCSIWMODE)] = _rtl92e_wx_set_mode,
[IW_IOCTL(SIOCGIWMODE)] = _rtl92e_wx_get_mode,
- [IW_IOCTL(SIOCSIWSENS)] = _rtl92e_wx_set_sens,
- [IW_IOCTL(SIOCGIWSENS)] = _rtl92e_wx_get_sens,
[IW_IOCTL(SIOCGIWRANGE)] = _rtl92e_wx_get_range,
[IW_IOCTL(SIOCSIWAP)] = _rtl92e_wx_set_wap,
[IW_IOCTL(SIOCGIWAP)] = _rtl92e_wx_get_wap,
@@ -1171,7 +1124,7 @@ static struct iw_statistics *_rtl92e_get_wireless_stats(struct net_device *dev)
int tmp_qual = 0;
int tmp_noise = 0;
- if (ieee->state < RTLLIB_LINKED) {
+ if (ieee->link_state < MAC80211_LINKED) {
wstats->qual.qual = 10;
wstats->qual.level = 0;
wstats->qual.noise = 0x100 - 100; /* -100 dBm */
diff --git a/drivers/staging/rtl8192e/rtl819x_HT.h b/drivers/staging/rtl8192e/rtl819x_HT.h
index f4e9fa849796..2bbd01048561 100644
--- a/drivers/staging/rtl8192e/rtl819x_HT.h
+++ b/drivers/staging/rtl8192e/rtl819x_HT.h
@@ -24,7 +24,6 @@ enum ht_extchnl_offset {
};
struct ht_capab_ele {
-
u8 AdvCoding:1;
u8 ChlWidth:1;
u8 MimoPwrSave:2;
@@ -46,7 +45,6 @@ struct ht_capab_ele {
u8 MCS[16];
-
u16 ExtHTCapInfo;
u8 TxBFCap[4];
@@ -55,7 +53,6 @@ struct ht_capab_ele {
} __packed;
-
struct ht_info_ele {
u8 ControlChl;
@@ -94,72 +91,54 @@ enum ht_aggre_mode {
HT_AGG_FORCE_DISABLE = 2,
};
-
struct rt_hi_throughput {
- u8 enable_ht;
- u8 bCurrentHTSupport;
-
- u8 bRegBW40MHz;
- u8 bCurBW40MHz;
-
- u8 bRegShortGI40MHz;
- u8 bCurShortGI40MHz;
-
- u8 bRegShortGI20MHz;
- u8 bCurShortGI20MHz;
-
- u8 bRegSuppCCK;
- u8 bCurSuppCCK;
-
+ u8 enable_ht;
+ u8 bCurrentHTSupport;
+ u8 bRegBW40MHz;
+ u8 bCurBW40MHz;
+ u8 bRegShortGI40MHz;
+ u8 bCurShortGI40MHz;
+ u8 bRegShortGI20MHz;
+ u8 bCurShortGI20MHz;
+ u8 bRegSuppCCK;
+ u8 bCurSuppCCK;
enum ht_spec_ver ePeerHTSpecVer;
-
-
struct ht_capab_ele SelfHTCap;
struct ht_info_ele SelfHTInfo;
-
- u8 PeerHTCapBuf[32];
- u8 PeerHTInfoBuf[32];
-
-
- u8 bAMSDU_Support;
- u16 nAMSDU_MaxSize;
- u8 bCurrent_AMSDU_Support;
- u16 nCurrent_AMSDU_MaxSize;
-
- u8 bAMPDUEnable;
- u8 bCurrentAMPDUEnable;
- u8 AMPDU_Factor;
- u8 CurrentAMPDUFactor;
- u8 MPDU_Density;
+ u8 PeerHTCapBuf[32];
+ u8 PeerHTInfoBuf[32];
+ u8 bAMSDU_Support;
+ u16 nAMSDU_MaxSize;
+ u8 bCurrent_AMSDU_Support;
+ u16 nCurrent_AMSDU_MaxSize;
+ u8 bAMPDUEnable;
+ u8 bCurrentAMPDUEnable;
+ u8 AMPDU_Factor;
+ u8 CurrentAMPDUFactor;
+ u8 MPDU_Density;
u8 current_mpdu_density;
-
enum ht_aggre_mode ForcedAMPDUMode;
u8 forced_ampdu_factor;
u8 forced_mpdu_density;
-
enum ht_aggre_mode ForcedAMSDUMode;
u8 forced_short_gi;
-
u8 current_op_mode;
-
u8 self_mimo_ps;
u8 peer_mimo_ps;
-
enum ht_extchnl_offset CurSTAExtChnlOffset;
u8 cur_tx_bw40mhz;
u8 sw_bw_in_progress;
u8 reg_rt2rt_aggregation;
- u8 RT2RT_HT_Mode;
+ u8 RT2RT_HT_Mode;
u8 current_rt2rt_aggregation;
u8 current_rt2rt_long_slot_time;
u8 sz_rt2rt_agg_buf[10];
-
u8 reg_rx_reorder_enable;
u8 cur_rx_reorder_enable;
u8 rx_reorder_win_size;
u8 rx_reorder_pending_time;
u16 rx_reorder_drop_counter;
- u8 IOTPeer;
+ u8 IOTPeer;
u32 iot_action;
u8 iot_ra_func;
} __packed;
diff --git a/drivers/staging/rtl8192e/rtl819x_HTProc.c b/drivers/staging/rtl8192e/rtl819x_HTProc.c
index fe30a291e64c..f9fa3f2bb728 100644
--- a/drivers/staging/rtl8192e/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192e/rtl819x_HTProc.c
@@ -424,14 +424,12 @@ static u8 HT_PickMCSRate(struct rtllib_device *ieee, u8 *pOperateMCS)
}
switch (ieee->mode) {
- case IEEE_A:
- case IEEE_B:
- case IEEE_G:
+ case WIRELESS_MODE_B:
+ case WIRELESS_MODE_G:
for (i = 0; i <= 15; i++)
pOperateMCS[i] = 0;
break;
- case IEEE_N_24G:
- case IEEE_N_5G:
+ case WIRELESS_MODE_N_24G:
pOperateMCS[0] &= RATE_ADPT_1SS_MASK;
pOperateMCS[1] &= RATE_ADPT_2SS_MASK;
pOperateMCS[3] &= RATE_ADPT_MCS32_MASK;
@@ -835,11 +833,11 @@ static void HTSetConnectBwModeCallback(struct rtllib_device *ieee)
ieee->set_chan(ieee->dev,
ieee->current_network.channel);
- ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20_40,
+ ieee->set_bw_mode_handler(ieee->dev, HT_CHANNEL_WIDTH_20_40,
ht_info->CurSTAExtChnlOffset);
} else {
ieee->set_chan(ieee->dev, ieee->current_network.channel);
- ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20,
+ ieee->set_bw_mode_handler(ieee->dev, HT_CHANNEL_WIDTH_20,
HT_EXTCHNL_OFFSET_NO_EXT);
}
diff --git a/drivers/staging/rtl8192e/rtl819x_Qos.h b/drivers/staging/rtl8192e/rtl819x_Qos.h
index c010eb0d6036..0499711ea2bf 100644
--- a/drivers/staging/rtl8192e/rtl819x_Qos.h
+++ b/drivers/staging/rtl8192e/rtl819x_Qos.h
@@ -104,7 +104,6 @@ struct acm {
};
union qos_tclas {
-
struct _TYPE_GENERAL {
u8 Priority;
u8 ClassifierType;
diff --git a/drivers/staging/rtl8192e/rtl819x_TS.h b/drivers/staging/rtl8192e/rtl819x_TS.h
index 4aa9b12a2dd5..37760d0bc35d 100644
--- a/drivers/staging/rtl8192e/rtl819x_TS.h
+++ b/drivers/staging/rtl8192e/rtl819x_TS.h
@@ -53,6 +53,4 @@ struct rx_ts_record {
u8 num;
};
-
-
#endif
diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h
index 6e665e866f1f..e3ce4431d460 100644
--- a/drivers/staging/rtl8192e/rtllib.h
+++ b/drivers/staging/rtl8192e/rtllib.h
@@ -38,6 +38,7 @@
#include <linux/netdevice.h>
#include <linux/if_arp.h> /* ARPHRD_ETHER */
+#include <net/cfg80211.h>
#include <net/lib80211.h>
#define MAX_PRECMD_CNT 16
@@ -139,7 +140,7 @@ struct cb_desc {
u8 rata_index;
u8 queue_index;
u16 txbuf_size;
- u8 RATRIndex;
+ u8 ratr_index;
u8 bAMSDU:1;
u8 bFromAggrQ:1;
u8 reserved6:6;
@@ -308,9 +309,7 @@ enum rt_op_mode {
};
#define aSifsTime \
- (((priv->rtllib->current_network.mode == IEEE_A) \
- || (priv->rtllib->current_network.mode == IEEE_N_24G) \
- || (priv->rtllib->current_network.mode == IEEE_N_5G)) ? 16 : 10)
+ ((priv->rtllib->current_network.mode == WIRELESS_MODE_N_24G) ? 16 : 10)
#define MGMT_QUEUE_NUM 5
@@ -421,17 +420,6 @@ enum init_gain_op_type {
IG_Max
};
-enum led_ctl_mode {
- LED_CTL_POWER_ON = 1,
- LED_CTL_LINK = 2,
- LED_CTL_NO_LINK = 3,
- LED_CTL_TX = 4,
- LED_CTL_RX = 5,
- LED_CTL_SITE_SURVEY = 6,
- LED_CTL_POWER_OFF = 7,
- LED_CTL_START_TO_LINK = 8,
-};
-
enum wireless_mode {
WIRELESS_MODE_UNKNOWN = 0x00,
WIRELESS_MODE_A = 0x01,
@@ -439,7 +427,6 @@ enum wireless_mode {
WIRELESS_MODE_G = 0x04,
WIRELESS_MODE_AUTO = 0x08,
WIRELESS_MODE_N_24G = 0x10,
- WIRELESS_MODE_N_5G = 0x20
};
#ifndef ETH_P_PAE
@@ -499,9 +486,6 @@ enum _REG_PREAMBLE_MODE {
#define RTLLIB_CCK_MODULATION (1<<0)
#define RTLLIB_OFDM_MODULATION (1<<1)
-#define RTLLIB_24GHZ_BAND (1<<0)
-#define RTLLIB_52GHZ_BAND (1<<1)
-
#define RTLLIB_CCK_RATE_LEN 4
#define RTLLIB_CCK_RATE_1MB 0x02
#define RTLLIB_CCK_RATE_2MB 0x04
@@ -548,10 +532,8 @@ struct rtllib_rx_stats {
u8 signal;
u8 noise;
u16 rate; /* in 100 kbps */
- u8 received_channel;
u8 control;
u8 mask;
- u8 freq;
u16 len;
u64 tsf;
u32 beacon_time;
@@ -1136,10 +1118,9 @@ struct rtllib_network {
struct list_head list;
};
-enum rtllib_state {
-
+enum rtl_link_state {
/* the card is not linked at all */
- RTLLIB_NOLINK = 0,
+ MAC80211_NOLINK = 0,
/* RTLLIB_ASSOCIATING* are for BSS client mode
* the driver shall not perform RX filtering unless
@@ -1164,14 +1145,14 @@ enum rtllib_state {
/* the link is ok. the card associated to a BSS or linked
* to a ibss cell or acting as an AP and creating the bss
*/
- RTLLIB_LINKED,
+ MAC80211_LINKED,
/* same as LINKED, but the driver shall apply RX filter
* rules as we are in NO_LINK mode. As the card is still
* logically linked, but it is doing a syncro site survey
* then it will be back to LINKED state.
*/
- RTLLIB_LINKED_SCANNING,
+ MAC80211_LINKED_SCANNING,
};
#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
@@ -1298,7 +1279,6 @@ enum fw_cmd_io_type {
#define RT_MAX_LD_SLOT_NUM 10
struct rt_link_detect {
-
u32 NumRecvBcnInPeriod;
u32 NumRecvDataInPeriod;
@@ -1316,7 +1296,6 @@ struct rt_link_detect {
};
struct sw_cam_table {
-
u8 macaddr[ETH_ALEN];
bool bused;
u8 key_buf[16];
@@ -1509,7 +1488,7 @@ struct rtllib_device {
*/
struct rtllib_network current_network;
- enum rtllib_state state;
+ enum rtl_link_state link_state;
int short_slot;
int mode; /* A, B, G */
@@ -1651,17 +1630,6 @@ struct rtllib_device {
};
/* Callback functions */
- void (*set_security)(struct net_device *dev,
- struct rtllib_security *sec);
-
- /* Used to TX data frame by using txb structs.
- * this is not used if in the softmac_features
- * is set the flag IEEE_SOFTMAC_TX_QUEUE
- */
- int (*hard_start_xmit)(struct rtllib_txb *txb,
- struct net_device *dev);
-
- int (*reset_port)(struct net_device *dev);
/* Softmac-generated frames (management) are TXed via this
* callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is
@@ -1682,24 +1650,12 @@ struct rtllib_device {
void (*softmac_data_hard_start_xmit)(struct sk_buff *skb,
struct net_device *dev, int rate);
- /* stops the HW queue for DATA frames. Useful to avoid
- * waste time to TX data frame when we are reassociating
- * This function can sleep.
- */
- void (*data_hard_stop)(struct net_device *dev);
-
- /* OK this is complementing to data_poll_hard_stop */
- void (*data_hard_resume)(struct net_device *dev);
-
/* ask to the driver to retune the radio.
* This function can sleep. the driver should ensure
* the radio has been switched before return.
*/
void (*set_chan)(struct net_device *dev, short ch);
- void (*rtllib_start_hw_scan)(struct net_device *dev);
- void (*rtllib_stop_hw_scan)(struct net_device *dev);
-
/* indicate the driver that the link state is changed
* for example it may indicate the card is associated now.
* Driver might be interested in this to apply RX filter
@@ -1729,22 +1685,16 @@ struct rtllib_device {
/* check whether Tx hw resource available */
short (*check_nic_enough_desc)(struct net_device *dev, int queue_index);
- void (*SetBWModeHandler)(struct net_device *dev,
- enum ht_channel_width bandwidth,
- enum ht_extchnl_offset Offset);
+ void (*set_bw_mode_handler)(struct net_device *dev,
+ enum ht_channel_width bandwidth,
+ enum ht_extchnl_offset Offset);
bool (*GetNmodeSupportBySecCfg)(struct net_device *dev);
- void (*SetWirelessMode)(struct net_device *dev, u8 wireless_mode);
+ void (*set_wireless_mode)(struct net_device *dev, u8 wireless_mode);
bool (*GetHalfNmodeSupportByAPsHandler)(struct net_device *dev);
u8 (*rtllib_ap_sec_type)(struct rtllib_device *ieee);
- void (*InitialGainHandler)(struct net_device *dev, u8 Operation);
- bool (*SetFwCmdHandler)(struct net_device *dev,
- enum fw_cmd_io_type FwCmdIO);
- void (*UpdateBeaconInterruptHandler)(struct net_device *dev,
- bool start);
+ void (*init_gain_handler)(struct net_device *dev, u8 Operation);
void (*ScanOperationBackupHandler)(struct net_device *dev,
u8 Operation);
- void (*LedControlHandler)(struct net_device *dev,
- enum led_ctl_mode LedAction);
void (*SetHwRegHandler)(struct net_device *dev, u8 variable, u8 *val);
void (*AllowAllDestAddrHandler)(struct net_device *dev,
@@ -1752,7 +1702,7 @@ struct rtllib_device {
void (*rtllib_ips_leave_wq)(struct net_device *dev);
void (*rtllib_ips_leave)(struct net_device *dev);
- void (*LeisurePSLeave)(struct net_device *dev);
+ void (*leisure_ps_leave)(struct net_device *dev);
/* This must be the last item so that it points to the data
* allocated beyond this structure by alloc_rtllib
@@ -1760,12 +1710,7 @@ struct rtllib_device {
u8 priv[];
};
-#define IEEE_A (1<<0)
-#define IEEE_B (1<<1)
-#define IEEE_G (1<<2)
-#define IEEE_N_24G (1<<4)
-#define IEEE_N_5G (1<<5)
-#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G)
+#define IEEE_MODE_MASK (WIRELESS_MODE_B | WIRELESS_MODE_G)
/* Generate a 802.11 header */
@@ -2080,8 +2025,6 @@ void TsStartAddBaProcess(struct rtllib_device *ieee,
void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr);
void RemoveAllTS(struct rtllib_device *ieee);
-extern const long rtllib_wlan_frequencies[];
-
static inline const char *escape_essid(const char *essid, u8 essid_len)
{
static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
index b649d02dc5c8..91dd3c373aef 100644
--- a/drivers/staging/rtl8192e/rtllib_rx.c
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -225,18 +225,6 @@ rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb,
return 0;
}
-/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation
- * Ethernet-II snap header (RFC1042 for most EtherTypes)
- */
-static unsigned char rfc1042_header[] = {
- 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
-};
-
-/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
-static unsigned char bridge_tunnel_header[] = {
- 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8
-};
-
/* No encapsulation header if EtherType < 0x600 (=length) */
/* Called by rtllib_rx_frame_decrypt */
@@ -264,8 +252,9 @@ static int rtllib_is_eapol_frame(struct rtllib_device *ieee,
RTLLIB_FCTL_FROMDS &&
memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
/* FromDS frame with own addr as DA */
- } else
+ } else {
return 0;
+ }
if (skb->len < 24 + 8)
return 0;
@@ -433,8 +422,9 @@ static int is_duplicate_packet(struct rtllib_device *ieee,
if (*last_frag + 1 != frag)
/* out-of-order fragment */
goto drop;
- } else
+ } else {
*last_seq = seq;
+ }
*last_frag = frag;
*last_time = jiffies;
@@ -1206,11 +1196,11 @@ static void rtllib_rx_check_leave_lps(struct rtllib_device *ieee, u8 unicast,
u8 nr_subframes)
{
if (unicast) {
- if (ieee->state == RTLLIB_LINKED) {
+ if (ieee->link_state == MAC80211_LINKED) {
if (((ieee->link_detect_info.NumRxUnicastOkInPeriod +
ieee->link_detect_info.NumTxOkInPeriod) > 8) ||
(ieee->link_detect_info.NumRxUnicastOkInPeriod > 2)) {
- ieee->LeisurePSLeave(ieee->dev);
+ ieee->leisure_ps_leave(ieee->dev);
}
}
}
@@ -2127,7 +2117,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee,
network->tim.tim_period = info_element->data[1];
network->dtim_period = info_element->data[1];
- if (ieee->state != RTLLIB_LINKED)
+ if (ieee->link_state != MAC80211_LINKED)
break;
network->last_dtim_sta_time = jiffies;
@@ -2311,11 +2301,7 @@ static inline int rtllib_network_init(
network->CountryIeLen = 0;
memset(network->CountryIeBuf, 0, MAX_IE_LEN);
HTInitializeBssDesc(&network->bssht);
- if (stats->freq == RTLLIB_52GHZ_BAND) {
- /* for A band (No DS info) */
- network->channel = stats->received_channel;
- } else
- network->flags |= NETWORK_HAS_CCK;
+ network->flags |= NETWORK_HAS_CCK;
network->wpa_ie_len = 0;
network->rsn_ie_len = 0;
@@ -2329,14 +2315,11 @@ static inline int rtllib_network_init(
return 1;
network->mode = 0;
- if (stats->freq == RTLLIB_52GHZ_BAND)
- network->mode = IEEE_A;
- else {
- if (network->flags & NETWORK_HAS_OFDM)
- network->mode |= IEEE_G;
- if (network->flags & NETWORK_HAS_CCK)
- network->mode |= IEEE_B;
- }
+
+ if (network->flags & NETWORK_HAS_OFDM)
+ network->mode |= WIRELESS_MODE_G;
+ if (network->flags & NETWORK_HAS_CCK)
+ network->mode |= WIRELESS_MODE_B;
if (network->mode == 0) {
netdev_dbg(ieee->dev, "Filtered out '%s (%pM)' network.\n",
@@ -2346,10 +2329,8 @@ static inline int rtllib_network_init(
}
if (network->bssht.bd_support_ht) {
- if (network->mode == IEEE_A)
- network->mode = IEEE_N_5G;
- else if (network->mode & (IEEE_G | IEEE_B))
- network->mode = IEEE_N_24G;
+ if (network->mode & (WIRELESS_MODE_G | WIRELESS_MODE_B))
+ network->mode = WIRELESS_MODE_N_24G;
}
if (rtllib_is_empty_essid(network->ssid, network->ssid_len))
network->flags |= NETWORK_EMPTY_ESSID;
@@ -2595,8 +2576,8 @@ static inline void rtllib_process_probe_response(
if (is_same_network(&ieee->current_network, network,
(network->ssid_len ? 1 : 0))) {
update_network(ieee, &ieee->current_network, network);
- if ((ieee->current_network.mode == IEEE_N_24G ||
- ieee->current_network.mode == IEEE_G) &&
+ if ((ieee->current_network.mode == WIRELESS_MODE_N_24G ||
+ ieee->current_network.mode == WIRELESS_MODE_G) &&
ieee->current_network.berp_info_valid) {
if (ieee->current_network.erp_value & ERP_UseProtection)
ieee->current_network.buseprotection = true;
@@ -2604,7 +2585,7 @@ static inline void rtllib_process_probe_response(
ieee->current_network.buseprotection = false;
}
if (is_beacon(frame_ctl)) {
- if (ieee->state >= RTLLIB_LINKED)
+ if (ieee->link_state >= MAC80211_LINKED)
ieee->link_detect_info.NumRecvBcnInPeriod++;
}
}
@@ -2662,7 +2643,7 @@ static inline void rtllib_process_probe_response(
|| ((ieee->current_network.ssid_len == network->ssid_len) &&
(strncmp(ieee->current_network.ssid, network->ssid,
network->ssid_len) == 0) &&
- (ieee->state == RTLLIB_NOLINK))))
+ (ieee->link_state == MAC80211_NOLINK))))
renew = 1;
update_network(ieee, target, network);
if (renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE))
@@ -2673,7 +2654,7 @@ static inline void rtllib_process_probe_response(
if (is_beacon(frame_ctl) &&
is_same_network(&ieee->current_network, network,
(network->ssid_len ? 1 : 0)) &&
- (ieee->state == RTLLIB_LINKED)) {
+ (ieee->link_state == MAC80211_LINKED)) {
ieee->handle_beacon(ieee->dev, beacon, &ieee->current_network);
}
free_network:
@@ -2702,7 +2683,7 @@ static void rtllib_rx_mgt(struct rtllib_device *ieee,
if (ieee->sta_sleep || (ieee->ps != RTLLIB_PS_DISABLED &&
ieee->iw_mode == IW_MODE_INFRA &&
- ieee->state == RTLLIB_LINKED))
+ ieee->link_state == MAC80211_LINKED))
schedule_work(&ieee->ps_task);
break;
@@ -2719,7 +2700,7 @@ static void rtllib_rx_mgt(struct rtllib_device *ieee,
if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
((ieee->iw_mode == IW_MODE_ADHOC ||
ieee->iw_mode == IW_MODE_MASTER) &&
- ieee->state == RTLLIB_LINKED))
+ ieee->link_state == MAC80211_LINKED))
rtllib_rx_probe_rq(ieee, skb);
break;
}
diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c
index b9886e83a6dc..425d4acbcdf0 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac.c
@@ -22,7 +22,6 @@
static void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl);
-
static short rtllib_is_54g(struct rtllib_network *net)
{
return (net->rates_ex_len > 0) || (net->rates_len > 4);
@@ -139,7 +138,6 @@ static void enqueue_mgmt(struct rtllib_device *ieee, struct sk_buff *skb)
*/
ieee->mgmt_queue_head = nh;
ieee->mgmt_queue_ring[nh] = skb;
-
}
static void init_mgmt_queue(struct rtllib_device *ieee)
@@ -147,16 +145,14 @@ static void init_mgmt_queue(struct rtllib_device *ieee)
ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
}
-
u8 MgntQuery_TxRateExcludeCCKRates(struct rtllib_device *ieee)
{
u16 i;
u8 QueryRate = 0;
u8 BasicRate;
-
for (i = 0; i < ieee->current_network.rates_len; i++) {
- BasicRate = ieee->current_network.rates[i]&0x7F;
+ BasicRate = ieee->current_network.rates[i] & 0x7F;
if (!rtllib_is_cck_rate(BasicRate)) {
if (QueryRate == 0) {
QueryRate = BasicRate;
@@ -185,9 +181,7 @@ static u8 MgntQuery_MgntFrameTxRate(struct rtllib_device *ieee)
rate = ieee->basic_rate & 0x7f;
if (rate == 0) {
- if (ieee->mode == IEEE_A ||
- ieee->mode == IEEE_N_5G ||
- (ieee->mode == IEEE_N_24G && !ht_info->bCurSuppCCK))
+ if (ieee->mode == WIRELESS_MODE_N_24G && !ht_info->bCurSuppCCK)
rate = 0x0c;
else
rate = 0x02;
@@ -219,14 +213,14 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee)
tcb_desc->queue_index = HIGH_QUEUE;
tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
- tcb_desc->RATRIndex = 7;
+ tcb_desc->ratr_index = 7;
tcb_desc->tx_dis_rate_fallback = 1;
tcb_desc->tx_use_drv_assinged_rate = 1;
if (single) {
if (ieee->queue_stop) {
enqueue_mgmt(ieee, skb);
} else {
- header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
@@ -286,7 +280,6 @@ softmac_ps_mgmt_xmit(struct sk_buff *skb,
type = WLAN_FC_GET_TYPE(fc);
stype = WLAN_FC_GET_STYPE(fc);
-
if (stype != RTLLIB_STYPE_PSPOLL)
tcb_desc->queue_index = MGNT_QUEUE;
else
@@ -295,9 +288,8 @@ softmac_ps_mgmt_xmit(struct sk_buff *skb,
if (ieee->disable_mgnt_queue)
tcb_desc->queue_index = HIGH_QUEUE;
-
tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
- tcb_desc->RATRIndex = 7;
+ tcb_desc->ratr_index = 7;
tcb_desc->tx_dis_rate_fallback = 1;
tcb_desc->tx_use_drv_assinged_rate = 1;
if (single) {
@@ -308,7 +300,6 @@ softmac_ps_mgmt_xmit(struct sk_buff *skb,
ieee->seq_ctrl[0] = 0;
else
ieee->seq_ctrl[0]++;
-
}
/* avoid watchdog triggers */
ieee->softmac_data_hard_start_xmit(skb, ieee->dev,
@@ -324,7 +315,6 @@ softmac_ps_mgmt_xmit(struct sk_buff *skb,
ieee->seq_ctrl[0]++;
}
ieee->softmac_hard_start_xmit(skb, ieee->dev);
-
}
}
@@ -388,7 +378,6 @@ static void rtllib_send_beacon(struct rtllib_device *ieee)
(msecs_to_jiffies(ieee->current_network.beacon_interval - 5)));
}
-
static void rtllib_send_beacon_cb(struct timer_list *t)
{
struct rtllib_device *ieee =
@@ -411,7 +400,6 @@ void rtllib_EnableNetMonitorMode(struct net_device *dev,
ieee->AllowAllDestAddrHandler(dev, true, !bInitState);
}
-
/* Disables network monitor mode. Only packets destinated to
* us will be received.
*/
@@ -425,7 +413,6 @@ void rtllib_DisableNetMonitorMode(struct net_device *dev,
ieee->AllowAllDestAddrHandler(dev, false, !bInitState);
}
-
/* Enables the specialized promiscuous mode required by Intel.
* In this mode, Intel intends to hear traffics from/to other STAs in the
* same BSS. Therefore we don't have to disable checking BSSID and we only need
@@ -449,7 +436,6 @@ void rtllib_EnableIntelPromiscuousMode(struct net_device *dev,
}
EXPORT_SYMBOL(rtllib_EnableIntelPromiscuousMode);
-
/* Disables the specialized promiscuous mode required by Intel.
* See MgntEnableIntelPromiscuousMode for detail.
*/
@@ -481,7 +467,6 @@ static void rtllib_send_probe(struct rtllib_device *ieee, u8 is_mesh)
}
}
-
static void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh)
{
if (ieee->active_scan && (ieee->softmac_features &
@@ -494,7 +479,7 @@ static void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh)
static void rtllib_update_active_chan_map(struct rtllib_device *ieee)
{
memcpy(ieee->active_channel_map, GET_DOT11D_INFO(ieee)->channel_map,
- MAX_CHANNEL_NUMBER+1);
+ MAX_CHANNEL_NUMBER + 1);
}
/* this performs syncro scan blocking the caller until all channels
@@ -523,12 +508,12 @@ static void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
* performing a complete syncro scan before conclude
* there are no interesting cell and to create a
* new one. In this case the link state is
- * RTLLIB_NOLINK until we found an interesting cell.
+ * MAC80211_NOLINK until we found an interesting cell.
* If so the ieee8021_new_net, called by the RX path
- * will set the state to RTLLIB_LINKED, so we stop
+ * will set the state to MAC80211_LINKED, so we stop
* scanning
* 2- We are linked and the root uses run iwlist scan.
- * So we switch to RTLLIB_LINKED_SCANNING to remember
+ * So we switch to MAC80211_LINKED_SCANNING to remember
* that we are still logically linked (not interested in
* new network events, despite for updating the net list,
* but we are temporarly 'unlinked' as the driver shall
@@ -537,7 +522,7 @@ static void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
* if the state become LINKED because of the #1 situation
*/
- if (ieee->state == RTLLIB_LINKED)
+ if (ieee->link_state == MAC80211_LINKED)
goto out;
if (ieee->sync_scan_hurryup) {
netdev_info(ieee->dev,
@@ -558,7 +543,7 @@ out:
ieee->actscanning = false;
ieee->sync_scan_hurryup = 0;
- if (ieee->state >= RTLLIB_LINKED) {
+ if (ieee->link_state >= MAC80211_LINKED) {
if (IS_DOT11D_ENABLE(ieee))
dot11d_scan_complete(ieee);
}
@@ -629,8 +614,6 @@ out1:
mutex_unlock(&ieee->scan_mutex);
}
-
-
static void rtllib_beacons_start(struct rtllib_device *ieee)
{
unsigned long flags;
@@ -653,10 +636,8 @@ static void rtllib_beacons_stop(struct rtllib_device *ieee)
spin_unlock_irqrestore(&ieee->beacon_lock, flags);
del_timer_sync(&ieee->beacon_timer);
-
}
-
void rtllib_stop_send_beacons(struct rtllib_device *ieee)
{
ieee->stop_send_beacons(ieee->dev);
@@ -665,7 +646,6 @@ void rtllib_stop_send_beacons(struct rtllib_device *ieee)
}
EXPORT_SYMBOL(rtllib_stop_send_beacons);
-
void rtllib_start_send_beacons(struct rtllib_device *ieee)
{
ieee->start_send_beacons(ieee->dev);
@@ -674,7 +654,6 @@ void rtllib_start_send_beacons(struct rtllib_device *ieee)
}
EXPORT_SYMBOL(rtllib_start_send_beacons);
-
static void rtllib_softmac_stop_scan(struct rtllib_device *ieee)
{
mutex_lock(&ieee->scan_mutex);
@@ -682,32 +661,24 @@ static void rtllib_softmac_stop_scan(struct rtllib_device *ieee)
if (ieee->scanning_continue == 1) {
ieee->scanning_continue = 0;
ieee->actscanning = false;
-
+ mutex_unlock(&ieee->scan_mutex);
cancel_delayed_work_sync(&ieee->softmac_scan_wq);
+ } else {
+ mutex_unlock(&ieee->scan_mutex);
}
-
- mutex_unlock(&ieee->scan_mutex);
}
void rtllib_stop_scan(struct rtllib_device *ieee)
{
- if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) {
+ if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
rtllib_softmac_stop_scan(ieee);
- } else {
- if (ieee->rtllib_stop_hw_scan)
- ieee->rtllib_stop_hw_scan(ieee->dev);
- }
}
EXPORT_SYMBOL(rtllib_stop_scan);
void rtllib_stop_scan_syncro(struct rtllib_device *ieee)
{
- if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) {
+ if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
ieee->sync_scan_hurryup = 1;
- } else {
- if (ieee->rtllib_stop_hw_scan)
- ieee->rtllib_stop_hw_scan(ieee->dev);
- }
}
EXPORT_SYMBOL(rtllib_stop_scan_syncro);
@@ -739,9 +710,6 @@ static void rtllib_start_scan(struct rtllib_device *ieee)
ieee->scanning_continue = 1;
schedule_delayed_work(&ieee->softmac_scan_wq, 0);
}
- } else {
- if (ieee->rtllib_start_hw_scan)
- ieee->rtllib_start_hw_scan(ieee->dev);
}
}
@@ -753,12 +721,8 @@ void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
RESET_CIE_WATCHDOG(ieee);
}
ieee->sync_scan_hurryup = 0;
- if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) {
+ if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
rtllib_softmac_scan_syncro(ieee, is_mesh);
- } else {
- if (ieee->rtllib_start_hw_scan)
- ieee->rtllib_start_hw_scan(ieee->dev);
- }
}
EXPORT_SYMBOL(rtllib_start_scan_syncro);
@@ -817,7 +781,7 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee,
char *ssid = ieee->current_network.ssid;
int ssid_len = ieee->current_network.ssid_len;
- int rate_len = ieee->current_network.rates_len+2;
+ int rate_len = ieee->current_network.rates_len + 2;
int rate_ex_len = ieee->current_network.rates_ex_len;
int wpa_ie_len = ieee->wpa_ie_len;
u8 erpinfo_content = 0;
@@ -838,15 +802,16 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee,
else
atim_len = 0;
- if ((ieee->current_network.mode == IEEE_G) ||
- (ieee->current_network.mode == IEEE_N_24G &&
+ if ((ieee->current_network.mode == WIRELESS_MODE_G) ||
+ (ieee->current_network.mode == WIRELESS_MODE_N_24G &&
ieee->ht_info->bCurSuppCCK)) {
erp_len = 3;
erpinfo_content = 0;
if (ieee->current_network.buseprotection)
erpinfo_content |= ERP_UseProtection;
- } else
+ } else {
erp_len = 0;
+ }
crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
encrypt = ieee->host_encrypt && crypt && crypt->ops &&
@@ -870,7 +835,7 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee,
}
}
- beacon_size = sizeof(struct rtllib_probe_response)+2+
+ beacon_size = sizeof(struct rtllib_probe_response) + 2 +
ssid_len + 3 + rate_len + rate_ex_len + atim_len + erp_len
+ wpa_ie_len + ieee->tx_headroom;
skb = dev_alloc_skb(beacon_size);
@@ -903,7 +868,6 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee,
if (encrypt)
beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
-
beacon_buf->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_RESP);
beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
beacon_buf->info_element[0].len = ssid_len;
@@ -915,9 +879,9 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee,
tag += ssid_len;
*(tag++) = MFIE_TYPE_RATES;
- *(tag++) = rate_len-2;
- memcpy(tag, ieee->current_network.rates, rate_len-2);
- tag += rate_len-2;
+ *(tag++) = rate_len - 2;
+ memcpy(tag, ieee->current_network.rates, rate_len - 2);
+ tag += rate_len - 2;
*(tag++) = MFIE_TYPE_DS_SET;
*(tag++) = 1;
@@ -939,9 +903,9 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee,
}
if (rate_ex_len) {
*(tag++) = MFIE_TYPE_RATES_EX;
- *(tag++) = rate_ex_len-2;
- memcpy(tag, ieee->current_network.rates_ex, rate_ex_len-2);
- tag += rate_ex_len-2;
+ *(tag++) = rate_ex_len - 2;
+ memcpy(tag, ieee->current_network.rates_ex, rate_ex_len - 2);
+ tag += rate_ex_len - 2;
}
if (wpa_ie_len) {
@@ -982,7 +946,6 @@ static struct sk_buff *rtllib_assoc_resp(struct rtllib_device *ieee, u8 *dest)
assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
WLAN_CAPABILITY_ESS : WLAN_CAPABILITY_IBSS);
-
if (ieee->short_slot)
assoc->capability |=
cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
@@ -1037,8 +1000,6 @@ static struct sk_buff *rtllib_auth_resp(struct rtllib_device *ieee, int status,
ether_addr_copy(auth->header.addr1, dest);
auth->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_AUTH);
return skb;
-
-
}
static struct sk_buff *rtllib_null_func(struct rtllib_device *ieee, short pwr)
@@ -1046,7 +1007,7 @@ static struct sk_buff *rtllib_null_func(struct rtllib_device *ieee, short pwr)
struct sk_buff *skb;
struct rtllib_hdr_3addr *hdr;
- skb = dev_alloc_skb(sizeof(struct rtllib_hdr_3addr)+ieee->tx_headroom);
+ skb = dev_alloc_skb(sizeof(struct rtllib_hdr_3addr) + ieee->tx_headroom);
if (!skb)
return NULL;
@@ -1063,8 +1024,6 @@ static struct sk_buff *rtllib_null_func(struct rtllib_device *ieee, short pwr)
(pwr ? RTLLIB_FCTL_PM : 0));
return skb;
-
-
}
static struct sk_buff *rtllib_pspoll_func(struct rtllib_device *ieee)
@@ -1072,7 +1031,7 @@ static struct sk_buff *rtllib_pspoll_func(struct rtllib_device *ieee)
struct sk_buff *skb;
struct rtllib_pspoll_hdr *hdr;
- skb = dev_alloc_skb(sizeof(struct rtllib_pspoll_hdr)+ieee->tx_headroom);
+ skb = dev_alloc_skb(sizeof(struct rtllib_pspoll_hdr) + ieee->tx_headroom);
if (!skb)
return NULL;
@@ -1088,7 +1047,6 @@ static struct sk_buff *rtllib_pspoll_func(struct rtllib_device *ieee)
RTLLIB_FCTL_PM);
return skb;
-
}
static void rtllib_resp_to_assoc_rq(struct rtllib_device *ieee, u8 *dest)
@@ -1099,7 +1057,6 @@ static void rtllib_resp_to_assoc_rq(struct rtllib_device *ieee, u8 *dest)
softmac_mgmt_xmit(buf, ieee);
}
-
static void rtllib_resp_to_auth(struct rtllib_device *ieee, int s, u8 *dest)
{
struct sk_buff *buf = rtllib_auth_resp(ieee, s, dest);
@@ -1108,7 +1065,6 @@ static void rtllib_resp_to_auth(struct rtllib_device *ieee, int s, u8 *dest)
softmac_mgmt_xmit(buf, ieee);
}
-
static void rtllib_resp_to_probe(struct rtllib_device *ieee, u8 *dest)
{
struct sk_buff *buf = rtllib_probe_resp(ieee, dest);
@@ -1117,7 +1073,6 @@ static void rtllib_resp_to_probe(struct rtllib_device *ieee, u8 *dest)
softmac_mgmt_xmit(buf, ieee);
}
-
static inline int SecIsInPMKIDList(struct rtllib_device *ieee, u8 *bssid)
{
int i = 0;
@@ -1195,11 +1150,11 @@ rtllib_association_req(struct rtllib_network *beacon,
}
if (beacon->bCkipSupported)
- ckip_ie_len = 30+2;
+ ckip_ie_len = 30 + 2;
if (beacon->bCcxRmEnable)
- ccxrm_ie_len = 6+2;
+ ccxrm_ie_len = 6 + 2;
if (beacon->BssCcxVerNumber >= 2)
- cxvernum_ie_len = 5+2;
+ cxvernum_ie_len = 5 + 2;
PMKCacheIdx = SecIsInPMKIDList(ieee, ieee->current_network.bssid);
if (PMKCacheIdx >= 0) {
@@ -1230,7 +1185,6 @@ rtllib_association_req(struct rtllib_network *beacon,
hdr = skb_put(skb, sizeof(struct rtllib_assoc_request_frame) + 2);
-
hdr->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_ASSOC_REQ);
hdr->header.duration_id = cpu_to_le16(37);
ether_addr_copy(hdr->header.addr1, beacon->bssid);
@@ -1247,10 +1201,9 @@ rtllib_association_req(struct rtllib_network *beacon,
hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
if (ieee->short_slot &&
- (beacon->capability&WLAN_CAPABILITY_SHORT_SLOT_TIME))
+ (beacon->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME))
hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
-
hdr->listen_interval = cpu_to_le16(beacon->listen_interval);
hdr->info_element[0].id = MFIE_TYPE_SSID;
@@ -1286,7 +1239,7 @@ rtllib_association_req(struct rtllib_network *beacon,
sizeof(AironetIeOui));
osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |=
- (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC);
+ (SUPPORT_CKIP_PK | SUPPORT_CKIP_MIC);
tag = skb_put(skb, ckip_ie_len);
*tag++ = MFIE_TYPE_AIRONET;
*tag++ = osCcxAironetIE.Length;
@@ -1397,7 +1350,7 @@ static void rtllib_associate_abort(struct rtllib_device *ieee)
* Here we will check if there are good nets to associate
* with, so we retry or just get back to NO_LINK and scanning
*/
- if (ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATING) {
+ if (ieee->link_state == RTLLIB_ASSOCIATING_AUTHENTICATING) {
netdev_dbg(ieee->dev, "Authentication failed\n");
ieee->softmac_stats.no_auth_rs++;
} else {
@@ -1405,7 +1358,7 @@ static void rtllib_associate_abort(struct rtllib_device *ieee)
ieee->softmac_stats.no_ass_rs++;
}
- ieee->state = RTLLIB_ASSOCIATING_RETRY;
+ ieee->link_state = RTLLIB_ASSOCIATING_RETRY;
schedule_delayed_work(&ieee->associate_retry_wq,
RTLLIB_SOFTMAC_ASSOC_RETRY_TIME);
@@ -1431,10 +1384,10 @@ static void rtllib_associate_step1(struct rtllib_device *ieee, u8 *daddr)
skb = rtllib_authentication_req(beacon, ieee, 0, daddr);
- if (!skb)
+ if (!skb) {
rtllib_associate_abort(ieee);
- else {
- ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATING;
+ } else {
+ ieee->link_state = RTLLIB_ASSOCIATING_AUTHENTICATING;
netdev_dbg(ieee->dev, "Sending authentication request\n");
softmac_mgmt_xmit(skb, ieee);
if (!timer_pending(&ieee->associate_timer)) {
@@ -1456,10 +1409,10 @@ static void rtllib_auth_challenge(struct rtllib_device *ieee, u8 *challenge,
skb = rtllib_authentication_req(beacon, ieee, chlen + 2, beacon->bssid);
- if (!skb)
+ if (!skb) {
rtllib_associate_abort(ieee);
- else {
- c = skb_put(skb, chlen+2);
+ } else {
+ c = skb_put(skb, chlen + 2);
*(c++) = MFIE_TYPE_CHALLENGE;
*(c++) = chlen;
memcpy(c, challenge, chlen);
@@ -1471,7 +1424,7 @@ static void rtllib_auth_challenge(struct rtllib_device *ieee, u8 *challenge,
sizeof(struct rtllib_hdr_3addr));
softmac_mgmt_xmit(skb, ieee);
- mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
+ mod_timer(&ieee->associate_timer, jiffies + (HZ / 2));
}
kfree(challenge);
}
@@ -1487,11 +1440,11 @@ static void rtllib_associate_step2(struct rtllib_device *ieee)
ieee->softmac_stats.tx_ass_rq++;
skb = rtllib_association_req(beacon, ieee);
- if (!skb)
+ if (!skb) {
rtllib_associate_abort(ieee);
- else {
+ } else {
softmac_mgmt_xmit(skb, ieee);
- mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
+ mod_timer(&ieee->associate_timer, jiffies + (HZ / 2));
}
}
@@ -1518,7 +1471,7 @@ static void rtllib_associate_complete_wq(void *data)
netdev_info(ieee->dev, "Using G rates:%d\n", ieee->rate);
} else {
ieee->rate = 22;
- ieee->SetWirelessMode(ieee->dev, IEEE_B);
+ ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_B);
netdev_info(ieee->dev, "Using B rates:%d\n", ieee->rate);
}
if (ieee->ht_info->bCurrentHTSupport && ieee->ht_info->enable_ht) {
@@ -1546,10 +1499,6 @@ static void rtllib_associate_complete_wq(void *data)
netdev_info(ieee->dev, "silent reset associate\n");
ieee->is_silent_reset = false;
}
-
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
-
}
static void rtllib_sta_send_associnfo(struct rtllib_device *ieee)
@@ -1560,7 +1509,7 @@ static void rtllib_associate_complete(struct rtllib_device *ieee)
{
del_timer_sync(&ieee->associate_timer);
- ieee->state = RTLLIB_LINKED;
+ ieee->link_state = MAC80211_LINKED;
rtllib_sta_send_associnfo(ieee);
schedule_work(&ieee->associate_complete_wq);
@@ -1575,9 +1524,6 @@ static void rtllib_associate_procedure_wq(void *data)
ieee->rtllib_ips_leave(ieee->dev);
mutex_lock(&ieee->wx_mutex);
- if (ieee->data_hard_stop)
- ieee->data_hard_stop(ieee->dev);
-
rtllib_stop_scan(ieee);
HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
if (ieee->rf_power_state == rf_off) {
@@ -1603,7 +1549,7 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee,
/* we are interested in new only if we are not associated
* and we are not associating / authenticating
*/
- if (ieee->state != RTLLIB_NOLINK)
+ if (ieee->link_state != MAC80211_NOLINK)
return;
if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability &
@@ -1638,11 +1584,12 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee,
net->ssid_len = net->hidden_ssid_len;
ssidbroad = 1;
}
- } else
+ } else {
ssidmatch =
(ieee->current_network.ssid_len == net->ssid_len) &&
(!strncmp(ieee->current_network.ssid, net->ssid,
net->ssid_len));
+ }
/* if the user set the AP check if match.
* if the network does not broadcast essid we check the
@@ -1701,10 +1648,7 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee,
ieee->ht_info->bCurrentHTSupport =
false;
- ieee->state = RTLLIB_ASSOCIATING;
- if (ieee->LedControlHandler != NULL)
- ieee->LedControlHandler(ieee->dev,
- LED_CTL_START_TO_LINK);
+ ieee->link_state = RTLLIB_ASSOCIATING;
schedule_delayed_work(
&ieee->associate_procedure_wq, 0);
} else {
@@ -1712,19 +1656,17 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee,
(ieee->modulation &
RTLLIB_OFDM_MODULATION)) {
ieee->rate = 108;
- ieee->SetWirelessMode(ieee->dev,
- IEEE_G);
+ ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_G);
netdev_info(ieee->dev,
"Using G rates\n");
} else {
ieee->rate = 22;
- ieee->SetWirelessMode(ieee->dev,
- IEEE_B);
+ ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_B);
netdev_info(ieee->dev,
"Using B rates\n");
}
memset(ieee->dot11ht_oper_rate_set, 0, 16);
- ieee->state = RTLLIB_LINKED;
+ ieee->link_state = MAC80211_LINKED;
}
}
}
@@ -1738,12 +1680,11 @@ static void rtllib_softmac_check_all_nets(struct rtllib_device *ieee)
spin_lock_irqsave(&ieee->lock, flags);
list_for_each_entry(target, &ieee->network_list, list) {
-
/* if the state become different that NOLINK means
* we had found what we are searching for
*/
- if (ieee->state != RTLLIB_NOLINK)
+ if (ieee->link_state != MAC80211_NOLINK)
break;
if (ieee->scan_age == 0 || time_after(target->last_scanned +
@@ -1885,9 +1826,9 @@ static inline u16 assoc_parse(struct rtllib_device *ieee, struct sk_buff *skb,
status_code = le16_to_cpu(response_head->status);
if ((status_code == WLAN_STATUS_ASSOC_DENIED_RATES ||
status_code == WLAN_STATUS_CAPS_UNSUPPORTED) &&
- ((ieee->mode == IEEE_G) &&
- (ieee->current_network.mode == IEEE_N_24G) &&
- (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
+ ((ieee->mode == WIRELESS_MODE_G) &&
+ (ieee->current_network.mode == WIRELESS_MODE_N_24G) &&
+ (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT - 1)))) {
ieee->ht_info->iot_action |= HT_IOT_ACT_PURE_N_MODE;
} else {
ieee->AsocRetryCount = 0;
@@ -1925,7 +1866,6 @@ static inline void rtllib_rx_assoc_rq(struct rtllib_device *ieee,
{
u8 dest[ETH_ALEN];
-
ieee->softmac_stats.rx_ass_rq++;
if (assoc_rq_parse(ieee->dev, skb, dest) != -1)
rtllib_resp_to_assoc_rq(ieee, dest);
@@ -1935,7 +1875,6 @@ static inline void rtllib_rx_assoc_rq(struct rtllib_device *ieee,
void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr)
{
-
struct sk_buff *buf = rtllib_null_func(ieee, pwr);
if (buf)
@@ -2011,7 +1950,7 @@ static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time)
LPSAwakeIntvl_tmp = period +
(psc->LPSAwakeIntvl -
period) -
- ((psc->LPSAwakeIntvl-period) %
+ ((psc->LPSAwakeIntvl - period) %
period);
else
LPSAwakeIntvl_tmp = psc->LPSAwakeIntvl;
@@ -2021,7 +1960,7 @@ static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time)
ieee->current_network.tim.tim_count)
LPSAwakeIntvl_tmp = count +
(psc->LPSAwakeIntvl - count) -
- ((psc->LPSAwakeIntvl-count)%period);
+ ((psc->LPSAwakeIntvl - count) % period);
else
LPSAwakeIntvl_tmp = psc->LPSAwakeIntvl;
}
@@ -2033,8 +1972,6 @@ static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time)
}
return 1;
-
-
}
static inline void rtllib_sta_ps(struct work_struct *work)
@@ -2050,7 +1987,7 @@ static inline void rtllib_sta_ps(struct work_struct *work)
if ((ieee->ps == RTLLIB_PS_DISABLED ||
ieee->iw_mode != IW_MODE_INFRA ||
- ieee->state != RTLLIB_LINKED)) {
+ ieee->link_state != MAC80211_LINKED)) {
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
rtllib_sta_wakeup(ieee, 1);
@@ -2073,7 +2010,6 @@ static inline void rtllib_sta_ps(struct work_struct *work)
ieee->ps_time = time;
}
spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
-
}
ieee->bAwakePktSent = false;
@@ -2088,7 +2024,6 @@ static inline void rtllib_sta_ps(struct work_struct *work)
out:
spin_unlock_irqrestore(&ieee->lock, flags);
-
}
static void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl)
@@ -2105,7 +2040,6 @@ static void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl)
}
}
return;
-
}
if (ieee->sta_sleep == LPS_IS_SLEEP)
@@ -2207,7 +2141,7 @@ rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb,
WLAN_FC_GET_STYPE(frame_ctl));
if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
- ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATED &&
+ ieee->link_state == RTLLIB_ASSOCIATING_AUTHENTICATED &&
(ieee->iw_mode == IW_MODE_INFRA)) {
errcode = assoc_parse(ieee, skb, &aid);
if (!errcode) {
@@ -2217,7 +2151,7 @@ rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb,
if (!network)
return 1;
- ieee->state = RTLLIB_LINKED;
+ ieee->link_state = MAC80211_LINKED;
ieee->assoc_id = aid;
ieee->softmac_stats.rx_ass_ok++;
/* station support qos */
@@ -2286,7 +2220,7 @@ static void rtllib_rx_auth_resp(struct rtllib_device *ieee, struct sk_buff *skb)
}
if (ieee->open_wep || !challenge) {
- ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATED;
+ ieee->link_state = RTLLIB_ASSOCIATING_AUTHENTICATED;
ieee->softmac_stats.rx_auth_rs_ok++;
if (!(ieee->ht_info->iot_action & HT_IOT_ACT_PURE_N_MODE)) {
if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
@@ -2301,14 +2235,14 @@ static void rtllib_rx_auth_resp(struct rtllib_device *ieee, struct sk_buff *skb)
}
/* Dummy wirless mode setting to avoid encryption issue */
if (bSupportNmode) {
- ieee->SetWirelessMode(ieee->dev,
+ ieee->set_wireless_mode(ieee->dev,
ieee->current_network.mode);
} else {
/*TODO*/
- ieee->SetWirelessMode(ieee->dev, IEEE_G);
+ ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_G);
}
- if ((ieee->current_network.mode == IEEE_N_24G) &&
+ if ((ieee->current_network.mode == WIRELESS_MODE_N_24G) &&
bHalfSupportNmode) {
netdev_info(ieee->dev, "======>enter half N mode\n");
ieee->bHalfWirelessN24GMode = true;
@@ -2325,9 +2259,8 @@ static inline int
rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb,
struct rtllib_rx_stats *rx_stats)
{
-
if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
- if (ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATING &&
+ if (ieee->link_state == RTLLIB_ASSOCIATING_AUTHENTICATING &&
(ieee->iw_mode == IW_MODE_INFRA)) {
netdev_dbg(ieee->dev,
"Received authentication response");
@@ -2352,25 +2285,21 @@ rtllib_rx_deauth(struct rtllib_device *ieee, struct sk_buff *skb)
* both for disassociation and deauthentication
*/
if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
- ieee->state == RTLLIB_LINKED &&
+ ieee->link_state == MAC80211_LINKED &&
(ieee->iw_mode == IW_MODE_INFRA)) {
frame_ctl = le16_to_cpu(header->frame_ctl);
netdev_info(ieee->dev,
"==========>received disassoc/deauth(%x) frame, reason code:%x\n",
WLAN_FC_GET_STYPE(frame_ctl),
((struct rtllib_disassoc *)skb->data)->reason);
- ieee->state = RTLLIB_ASSOCIATING;
+ ieee->link_state = RTLLIB_ASSOCIATING;
ieee->softmac_stats.reassoc++;
ieee->is_roaming = true;
ieee->link_detect_info.bBusyTraffic = false;
rtllib_disassociate(ieee);
RemovePeerTS(ieee, header->addr2);
- if (ieee->LedControlHandler != NULL)
- ieee->LedControlHandler(ieee->dev,
- LED_CTL_START_TO_LINK);
-
if (!(ieee->rtllib_ap_sec_type(ieee) &
- (SEC_ALG_CCMP|SEC_ALG_TKIP)))
+ (SEC_ALG_CCMP | SEC_ALG_TKIP)))
schedule_delayed_work(
&ieee->associate_procedure_wq, 5);
}
@@ -2437,7 +2366,6 @@ inline int rtllib_rx_frame_softmac(struct rtllib_device *ieee,
*/
void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee)
{
-
unsigned int queue_index = txb->queue_index;
unsigned long flags;
int i;
@@ -2482,7 +2410,6 @@ void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee)
rtllib_txb_free(txb);
spin_unlock_irqrestore(&ieee->lock, flags);
-
}
void rtllib_reset_queue(struct rtllib_device *ieee)
@@ -2497,7 +2424,6 @@ void rtllib_reset_queue(struct rtllib_device *ieee)
}
ieee->queue_stop = 0;
spin_unlock_irqrestore(&ieee->lock, flags);
-
}
EXPORT_SYMBOL(rtllib_reset_queue);
@@ -2534,25 +2460,17 @@ static void rtllib_start_master_bss(struct rtllib_device *ieee)
ether_addr_copy(ieee->current_network.bssid, ieee->dev->dev_addr);
ieee->set_chan(ieee->dev, ieee->current_network.channel);
- ieee->state = RTLLIB_LINKED;
+ ieee->link_state = MAC80211_LINKED;
ieee->link_change(ieee->dev);
notify_wx_assoc_event(ieee);
-
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
-
netif_carrier_on(ieee->dev);
}
static void rtllib_start_monitor_mode(struct rtllib_device *ieee)
{
/* reset hardware status */
- if (ieee->raw_tx) {
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
-
+ if (ieee->raw_tx)
netif_carrier_on(ieee->dev);
- }
}
static void rtllib_start_ibss_wq(void *data)
@@ -2579,12 +2497,11 @@ static void rtllib_start_ibss_wq(void *data)
ieee->ssid_set = 1;
}
- ieee->state = RTLLIB_NOLINK;
- ieee->mode = IEEE_G;
+ ieee->link_state = MAC80211_NOLINK;
+ ieee->mode = WIRELESS_MODE_G;
/* check if we have this cell in our network list */
rtllib_softmac_check_all_nets(ieee);
-
/* if not then the state is not linked. Maybe the user switched to
* ad-hoc mode just after being in monitor mode, or just after
* being very few time in managed mode (so the card have had no
@@ -2592,25 +2509,24 @@ static void rtllib_start_ibss_wq(void *data)
* after setting ad-hoc mode. So we have to give another try..
* Here, in ibss mode, should be safe to do this without extra care
* (in bss mode we had to make sure no-one tried to associate when
- * we had just checked the ieee->state and we was going to start the
+ * we had just checked the ieee->link_state and we was going to start the
* scan) because in ibss mode the rtllib_new_net function, when
- * finds a good net, just set the ieee->state to RTLLIB_LINKED,
+ * finds a good net, just set the ieee->link_state to MAC80211_LINKED,
* so, at worst, we waste a bit of time to initiate an unneeded syncro
* scan, that will stop at the first round because it sees the state
* associated.
*/
- if (ieee->state == RTLLIB_NOLINK)
+ if (ieee->link_state == MAC80211_NOLINK)
rtllib_start_scan_syncro(ieee, 0);
/* the network definitively is not here.. create a new cell */
- if (ieee->state == RTLLIB_NOLINK) {
+ if (ieee->link_state == MAC80211_NOLINK) {
netdev_info(ieee->dev, "creating new IBSS cell\n");
ieee->current_network.channel = ieee->bss_start_channel;
if (!ieee->wap_set)
eth_random_addr(ieee->current_network.bssid);
if (ieee->modulation & RTLLIB_CCK_MODULATION) {
-
ieee->current_network.rates_len = 4;
ieee->current_network.rates[0] =
@@ -2622,8 +2538,9 @@ static void rtllib_start_ibss_wq(void *data)
ieee->current_network.rates[3] =
RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_11MB;
- } else
+ } else {
ieee->current_network.rates_len = 0;
+ }
if (ieee->modulation & RTLLIB_OFDM_MODULATION) {
ieee->current_network.rates_ex_len = 8;
@@ -2652,35 +2569,28 @@ static void rtllib_start_ibss_wq(void *data)
}
ieee->current_network.qos_data.supported = 0;
- ieee->SetWirelessMode(ieee->dev, IEEE_G);
+ ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_G);
ieee->current_network.mode = ieee->mode;
ieee->current_network.atim_window = 0;
ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
}
netdev_info(ieee->dev, "%s(): ieee->mode = %d\n", __func__, ieee->mode);
- if ((ieee->mode == IEEE_N_24G) || (ieee->mode == IEEE_N_5G))
+ if (ieee->mode == WIRELESS_MODE_N_24G)
HTUseDefaultSetting(ieee);
else
ieee->ht_info->bCurrentHTSupport = false;
ieee->SetHwRegHandler(ieee->dev, HW_VAR_MEDIA_STATUS,
- (u8 *)(&ieee->state));
+ (u8 *)(&ieee->link_state));
- ieee->state = RTLLIB_LINKED;
+ ieee->link_state = MAC80211_LINKED;
ieee->link_change(ieee->dev);
HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
- if (ieee->LedControlHandler != NULL)
- ieee->LedControlHandler(ieee->dev, LED_CTL_LINK);
-
rtllib_start_send_beacons(ieee);
notify_wx_assoc_event(ieee);
-
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
-
netif_carrier_on(ieee->dev);
mutex_unlock(&ieee->wx_mutex);
@@ -2708,7 +2618,7 @@ static void rtllib_start_bss(struct rtllib_device *ieee)
rtllib_softmac_check_all_nets(ieee);
/* ensure no-one start an associating process (thus setting
- * the ieee->state to rtllib_ASSOCIATING) while we
+ * the ieee->link_state to rtllib_ASSOCIATING) while we
* have just checked it and we are going to enable scan.
* The rtllib_new_net function is always called with
* lock held (from both rtllib_softmac_check_all_nets and
@@ -2716,7 +2626,7 @@ static void rtllib_start_bss(struct rtllib_device *ieee)
*/
spin_lock_irqsave(&ieee->lock, flags);
- if (ieee->state == RTLLIB_NOLINK)
+ if (ieee->link_state == MAC80211_NOLINK)
rtllib_start_scan(ieee);
spin_unlock_irqrestore(&ieee->lock, flags);
}
@@ -2734,11 +2644,9 @@ void rtllib_disassociate(struct rtllib_device *ieee)
if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
rtllib_reset_queue(ieee);
- if (ieee->data_hard_stop)
- ieee->data_hard_stop(ieee->dev);
if (IS_DOT11D_ENABLE(ieee))
dot11d_reset(ieee);
- ieee->state = RTLLIB_NOLINK;
+ ieee->link_state = MAC80211_NOLINK;
ieee->is_set_key = false;
ieee->wap_set = 0;
@@ -2757,14 +2665,14 @@ static void rtllib_associate_retry_wq(void *data)
if (!ieee->proto_started)
goto exit;
- if (ieee->state != RTLLIB_ASSOCIATING_RETRY)
+ if (ieee->link_state != RTLLIB_ASSOCIATING_RETRY)
goto exit;
- /* until we do not set the state to RTLLIB_NOLINK
+ /* until we do not set the state to MAC80211_NOLINK
* there are no possibility to have someone else trying
* to start an association procedure (we get here with
- * ieee->state = RTLLIB_ASSOCIATING).
- * When we set the state to RTLLIB_NOLINK it is possible
+ * ieee->link_state = RTLLIB_ASSOCIATING).
+ * When we set the state to MAC80211_NOLINK it is possible
* that the RX path run an attempt to associate, but
* both rtllib_softmac_check_all_nets and the
* RX path works with ieee->lock held so there are no
@@ -2774,13 +2682,13 @@ static void rtllib_associate_retry_wq(void *data)
* state and we are going to start the scan.
*/
ieee->beinretry = true;
- ieee->state = RTLLIB_NOLINK;
+ ieee->link_state = MAC80211_NOLINK;
rtllib_softmac_check_all_nets(ieee);
spin_lock_irqsave(&ieee->lock, flags);
- if (ieee->state == RTLLIB_NOLINK)
+ if (ieee->link_state == MAC80211_NOLINK)
rtllib_start_scan(ieee);
spin_unlock_irqrestore(&ieee->lock, flags);
@@ -2806,7 +2714,6 @@ static struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee)
b->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_BEACON);
return skb;
-
}
struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee)
@@ -2840,7 +2747,6 @@ void rtllib_softmac_stop_protocol(struct rtllib_device *ieee, u8 mesh_flag,
}
EXPORT_SYMBOL(rtllib_softmac_stop_protocol);
-
void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown)
{
if (!ieee->proto_started)
@@ -2859,10 +2765,10 @@ void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown)
cancel_delayed_work_sync(&ieee->link_change_wq);
rtllib_stop_scan(ieee);
- if (ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED)
- ieee->state = RTLLIB_NOLINK;
+ if (ieee->link_state <= RTLLIB_ASSOCIATING_AUTHENTICATED)
+ ieee->link_state = MAC80211_NOLINK;
- if (ieee->state == RTLLIB_LINKED) {
+ if (ieee->link_state == MAC80211_LINKED) {
if (ieee->iw_mode == IW_MODE_INFRA)
SendDisassociation(ieee, 1, WLAN_REASON_DEAUTH_LEAVING);
rtllib_disassociate(ieee);
@@ -2918,27 +2824,25 @@ void rtllib_start_protocol(struct rtllib_device *ieee)
ieee->last_packet_time[i] = 0;
}
- if (ieee->UpdateBeaconInterruptHandler)
- ieee->UpdateBeaconInterruptHandler(ieee->dev, false);
-
ieee->wmm_acm = 0;
/* if the user set the MAC of the ad-hoc cell and then
* switch to managed mode, shall we make sure that association
* attempts does not fail just because the user provide the essid
* and the nic is still checking for the AP MAC ??
*/
- if (ieee->iw_mode == IW_MODE_INFRA) {
+ switch (ieee->iw_mode) {
+ case IW_MODE_INFRA:
rtllib_start_bss(ieee);
- } else if (ieee->iw_mode == IW_MODE_ADHOC) {
- if (ieee->UpdateBeaconInterruptHandler)
- ieee->UpdateBeaconInterruptHandler(ieee->dev, true);
-
+ break;
+ case IW_MODE_ADHOC:
rtllib_start_ibss(ieee);
-
- } else if (ieee->iw_mode == IW_MODE_MASTER) {
+ break;
+ case IW_MODE_MASTER:
rtllib_start_master_bss(ieee);
- } else if (ieee->iw_mode == IW_MODE_MONITOR) {
+ break;
+ case IW_MODE_MONITOR:
rtllib_start_monitor_mode(ieee);
+ break;
}
}
@@ -2948,7 +2852,7 @@ int rtllib_softmac_init(struct rtllib_device *ieee)
memset(&ieee->current_network, 0, sizeof(struct rtllib_network));
- ieee->state = RTLLIB_NOLINK;
+ ieee->link_state = MAC80211_NOLINK;
for (i = 0; i < 5; i++)
ieee->seq_ctrl[i] = 0;
ieee->dot11d_info = kzalloc(sizeof(struct rt_dot11d_info), GFP_ATOMIC);
@@ -3139,7 +3043,7 @@ static void rtllib_MgntDisconnectIBSS(struct rtllib_device *rtllib)
u8 i;
bool bFilterOutNonAssociatedBSSID = false;
- rtllib->state = RTLLIB_NOLINK;
+ rtllib->link_state = MAC80211_NOLINK;
for (i = 0; i < 6; i++)
rtllib->current_network.bssid[i] = 0x55;
@@ -3155,7 +3059,6 @@ static void rtllib_MgntDisconnectIBSS(struct rtllib_device *rtllib)
rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_CECHK_BSSID,
(u8 *)(&bFilterOutNonAssociatedBSSID));
notify_wx_assoc_event(rtllib);
-
}
static void rtllib_MlmeDisassociateRequest(struct rtllib_device *rtllib,
@@ -3167,7 +3070,7 @@ static void rtllib_MlmeDisassociateRequest(struct rtllib_device *rtllib,
RemovePeerTS(rtllib, asSta);
if (memcmp(rtllib->current_network.bssid, asSta, 6) == 0) {
- rtllib->state = RTLLIB_NOLINK;
+ rtllib->link_state = MAC80211_NOLINK;
for (i = 0; i < 6; i++)
rtllib->current_network.bssid[i] = 0x22;
@@ -3179,9 +3082,7 @@ static void rtllib_MlmeDisassociateRequest(struct rtllib_device *rtllib,
rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_BSSID,
rtllib->current_network.bssid);
-
}
-
}
static void
@@ -3198,7 +3099,7 @@ rtllib_MgntDisconnectAP(
rtllib_MlmeDisassociateRequest(rtllib, rtllib->current_network.bssid,
asRsn);
- rtllib->state = RTLLIB_NOLINK;
+ rtllib->link_state = MAC80211_NOLINK;
}
bool rtllib_MgntDisconnect(struct rtllib_device *rtllib, u8 asRsn)
@@ -3206,12 +3107,11 @@ bool rtllib_MgntDisconnect(struct rtllib_device *rtllib, u8 asRsn)
if (rtllib->ps != RTLLIB_PS_DISABLED)
rtllib->sta_wake_up(rtllib->dev);
- if (rtllib->state == RTLLIB_LINKED) {
+ if (rtllib->link_state == MAC80211_LINKED) {
if (rtllib->iw_mode == IW_MODE_ADHOC)
rtllib_MgntDisconnectIBSS(rtllib);
if (rtllib->iw_mode == IW_MODE_INFRA)
rtllib_MgntDisconnectAP(rtllib, asRsn);
-
}
return true;
@@ -3226,11 +3126,10 @@ void notify_wx_assoc_event(struct rtllib_device *ieee)
return;
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- if (ieee->state == RTLLIB_LINKED)
+ if (ieee->link_state == MAC80211_LINKED) {
memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid,
ETH_ALEN);
- else {
-
+ } else {
netdev_info(ieee->dev, "%s(): Tell user space disconnected\n",
__func__);
eth_zero_addr(wrqu.ap_addr.sa_data);
diff --git a/drivers/staging/rtl8192e/rtllib_softmac_wx.c b/drivers/staging/rtl8192e/rtllib_softmac_wx.c
index 1f2fa711e60b..2de63d1f2009 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac_wx.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac_wx.c
@@ -15,16 +15,6 @@
#include "rtllib.h"
#include "dot11d.h"
-/* FIXME: add A freqs */
-
-const long rtllib_wlan_frequencies[] = {
- 2412, 2417, 2422, 2427,
- 2432, 2437, 2442, 2447,
- 2452, 2457, 2462, 2467,
- 2472, 2484
-};
-EXPORT_SYMBOL(rtllib_wlan_frequencies);
-
int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
@@ -43,15 +33,8 @@ int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a,
if (fwrq->e == 1) {
if ((fwrq->m >= (int)2.412e8 &&
fwrq->m <= (int)2.487e8)) {
- int f = fwrq->m / 100000;
- int c = 0;
-
- while ((c < 14) && (f != rtllib_wlan_frequencies[c]))
- c++;
-
- /* hack to fall through */
+ fwrq->m = ieee80211_freq_khz_to_channel(fwrq->m / 100);
fwrq->e = 0;
- fwrq->m = c + 1;
}
}
@@ -70,7 +53,7 @@ int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a,
if (ieee->iw_mode == IW_MODE_ADHOC ||
ieee->iw_mode == IW_MODE_MASTER)
- if (ieee->state == RTLLIB_LINKED) {
+ if (ieee->link_state == MAC80211_LINKED) {
rtllib_stop_send_beacons(ieee);
rtllib_start_send_beacons(ieee);
}
@@ -83,7 +66,6 @@ out:
}
EXPORT_SYMBOL(rtllib_wx_set_freq);
-
int rtllib_wx_get_freq(struct rtllib_device *ieee,
struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
@@ -92,8 +74,8 @@ int rtllib_wx_get_freq(struct rtllib_device *ieee,
if (ieee->current_network.channel == 0)
return -1;
- fwrq->m = rtllib_wlan_frequencies[ieee->current_network.channel-1] *
- 100000;
+ fwrq->m = ieee80211_channel_to_freq_khz(ieee->current_network.channel,
+ NL80211_BAND_2GHZ) * 100;
fwrq->e = 1;
return 0;
}
@@ -113,8 +95,8 @@ int rtllib_wx_get_wap(struct rtllib_device *ieee,
/* We want avoid to give to the user inconsistent infos*/
spin_lock_irqsave(&ieee->lock, flags);
- if (ieee->state != RTLLIB_LINKED &&
- ieee->state != RTLLIB_LINKED_SCANNING &&
+ if (ieee->link_state != MAC80211_LINKED &&
+ ieee->link_state != MAC80211_LINKED_SCANNING &&
ieee->wap_set == 0)
eth_zero_addr(wrqu->ap_addr.sa_data);
@@ -128,13 +110,11 @@ int rtllib_wx_get_wap(struct rtllib_device *ieee,
}
EXPORT_SYMBOL(rtllib_wx_get_wap);
-
int rtllib_wx_set_wap(struct rtllib_device *ieee,
struct iw_request_info *info,
union iwreq_data *awrq,
char *extra)
{
-
int ret = 0;
unsigned long flags;
@@ -164,7 +144,6 @@ int rtllib_wx_set_wap(struct rtllib_device *ieee,
goto out;
}
-
if (ifup)
rtllib_stop_protocol(ieee, true);
@@ -205,8 +184,8 @@ int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a,
goto out;
}
- if (ieee->state != RTLLIB_LINKED &&
- ieee->state != RTLLIB_LINKED_SCANNING &&
+ if (ieee->link_state != MAC80211_LINKED &&
+ ieee->link_state != MAC80211_LINKED_SCANNING &&
ieee->ssid_set == 0) {
ret = -1;
goto out;
@@ -220,7 +199,6 @@ out:
spin_unlock_irqrestore(&ieee->lock, flags);
return ret;
-
}
EXPORT_SYMBOL(rtllib_wx_get_essid);
@@ -228,10 +206,9 @@ int rtllib_wx_set_rate(struct rtllib_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
-
u32 target_rate = wrqu->bitrate.value;
- ieee->rate = target_rate/100000;
+ ieee->rate = target_rate / 100000;
return 0;
}
EXPORT_SYMBOL(rtllib_wx_set_rate);
@@ -250,14 +227,13 @@ int rtllib_wx_get_rate(struct rtllib_device *ieee,
}
EXPORT_SYMBOL(rtllib_wx_get_rate);
-
int rtllib_wx_set_rts(struct rtllib_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- if (wrqu->rts.disabled || !wrqu->rts.fixed)
+ if (wrqu->rts.disabled || !wrqu->rts.fixed) {
ieee->rts = DEFAULT_RTS_THRESHOLD;
- else {
+ } else {
if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
wrqu->rts.value > MAX_RTS_THRESHOLD)
return -EINVAL;
@@ -332,6 +308,7 @@ void rtllib_wx_sync_scan_wq(void *data)
enum ht_channel_width bandwidth = 0;
int b40M = 0;
+ mutex_lock(&ieee->wx_mutex);
if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) {
rtllib_start_scan_syncro(ieee, 0);
goto out;
@@ -339,17 +316,14 @@ void rtllib_wx_sync_scan_wq(void *data)
chan = ieee->current_network.channel;
- ieee->LeisurePSLeave(ieee->dev);
+ ieee->leisure_ps_leave(ieee->dev);
/* notify AP to be in PS mode */
rtllib_sta_ps_send_null_frame(ieee, 1);
rtllib_sta_ps_send_null_frame(ieee, 1);
rtllib_stop_all_queues(ieee);
-
- if (ieee->data_hard_stop)
- ieee->data_hard_stop(ieee->dev);
rtllib_stop_send_beacons(ieee);
- ieee->state = RTLLIB_LINKED_SCANNING;
+ ieee->link_state = MAC80211_LINKED_SCANNING;
ieee->link_change(ieee->dev);
/* wait for ps packet to be kicked out successfully */
msleep(50);
@@ -361,7 +335,7 @@ void rtllib_wx_sync_scan_wq(void *data)
b40M = 1;
chan_offset = ieee->ht_info->CurSTAExtChnlOffset;
bandwidth = (enum ht_channel_width)ieee->ht_info->bCurBW40MHz;
- ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20,
+ ieee->set_bw_mode_handler(ieee->dev, HT_CHANNEL_WIDTH_20,
HT_EXTCHNL_OFFSET_NO_EXT);
}
@@ -374,14 +348,14 @@ void rtllib_wx_sync_scan_wq(void *data)
ieee->set_chan(ieee->dev, chan - 2);
else
ieee->set_chan(ieee->dev, chan);
- ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset);
+ ieee->set_bw_mode_handler(ieee->dev, bandwidth, chan_offset);
} else {
ieee->set_chan(ieee->dev, chan);
}
ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_RESTORE);
- ieee->state = RTLLIB_LINKED;
+ ieee->link_state = MAC80211_LINKED;
ieee->link_change(ieee->dev);
/* Notify AP that I wake up again */
@@ -392,10 +366,6 @@ void rtllib_wx_sync_scan_wq(void *data)
ieee->link_detect_info.NumRecvBcnInPeriod = 1;
ieee->link_detect_info.NumRecvDataInPeriod = 1;
}
-
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
-
if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
rtllib_start_send_beacons(ieee);
@@ -403,7 +373,6 @@ void rtllib_wx_sync_scan_wq(void *data)
out:
mutex_unlock(&ieee->wx_mutex);
-
}
int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a,
@@ -411,21 +380,18 @@ int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a,
{
int ret = 0;
- mutex_lock(&ieee->wx_mutex);
-
if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) {
ret = -1;
goto out;
}
- if (ieee->state == RTLLIB_LINKED) {
+ if (ieee->link_state == MAC80211_LINKED) {
schedule_work(&ieee->wx_sync_scan_wq);
/* intentionally forget to up sem */
return 0;
}
out:
- mutex_unlock(&ieee->wx_mutex);
return ret;
}
EXPORT_SYMBOL(rtllib_wx_set_scan);
@@ -434,7 +400,6 @@ int rtllib_wx_set_essid(struct rtllib_device *ieee,
struct iw_request_info *a,
union iwreq_data *wrqu, char *extra)
{
-
int ret = 0, len;
short proto_started;
unsigned long flags;
@@ -454,7 +419,6 @@ int rtllib_wx_set_essid(struct rtllib_device *ieee,
if (proto_started)
rtllib_stop_protocol(ieee, true);
-
/* this is just to be sure that the GET wx callback
* has consistent infos. not needed otherwise
*/
@@ -492,7 +456,6 @@ int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
-
int *parms = (int *)extra;
int enable = (parms[0] > 0);
short prev = ieee->raw_tx;
@@ -508,12 +471,8 @@ int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
ieee->raw_tx ? "enabled" : "disabled");
if (ieee->iw_mode == IW_MODE_MONITOR) {
- if (prev == 0 && ieee->raw_tx) {
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
-
+ if (prev == 0 && ieee->raw_tx)
netif_carrier_on(ieee->dev);
- }
if (prev && ieee->raw_tx == 1)
netif_carrier_off(ieee->dev);
@@ -530,14 +489,13 @@ int rtllib_wx_get_name(struct rtllib_device *ieee, struct iw_request_info *info,
{
const char *b = ieee->modulation & RTLLIB_CCK_MODULATION ? "b" : "";
const char *g = ieee->modulation & RTLLIB_OFDM_MODULATION ? "g" : "";
- const char *n = ieee->mode & (IEEE_N_24G | IEEE_N_5G) ? "n" : "";
+ const char *n = ieee->mode & (WIRELESS_MODE_N_24G) ? "n" : "";
scnprintf(wrqu->name, sizeof(wrqu->name), "802.11%s%s%s", b, g, n);
return 0;
}
EXPORT_SYMBOL(rtllib_wx_get_name);
-
/* this is mostly stolen from hostap */
int rtllib_wx_set_power(struct rtllib_device *ieee,
struct iw_request_info *info,
@@ -583,12 +541,10 @@ int rtllib_wx_set_power(struct rtllib_device *ieee,
default:
ret = -EINVAL;
goto exit;
-
}
exit:
mutex_unlock(&ieee->wx_mutex);
return ret;
-
}
EXPORT_SYMBOL(rtllib_wx_set_power);
@@ -625,6 +581,5 @@ int rtllib_wx_get_power(struct rtllib_device *ieee,
exit:
mutex_unlock(&ieee->wx_mutex);
return 0;
-
}
EXPORT_SYMBOL(rtllib_wx_get_power);
diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c
index 9ab8ee46ef66..ec038ef806c3 100644
--- a/drivers/staging/rtl8192e/rtllib_tx.c
+++ b/drivers/staging/rtl8192e/rtllib_tx.c
@@ -406,7 +406,7 @@ static void rtllib_query_protectionmode(struct rtllib_device *ieee,
if (is_broadcast_ether_addr(skb->data + 16))
return;
- if (ieee->mode < IEEE_N_24G) {
+ if (ieee->mode < WIRELESS_MODE_N_24G) {
if (skb->len > ieee->rts) {
tcb_desc->bRTSEnable = true;
tcb_desc->rts_rate = MGN_24M;
@@ -486,7 +486,7 @@ static void rtllib_txrate_selectmode(struct rtllib_device *ieee,
!tcb_desc->tx_use_drv_assinged_rate) {
if (ieee->iw_mode == IW_MODE_INFRA ||
ieee->iw_mode == IW_MODE_ADHOC)
- tcb_desc->RATRIndex = 0;
+ tcb_desc->ratr_index = 0;
}
}
@@ -572,8 +572,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
/* If there is no driver handler to take the TXB, don't bother
* creating it...
*/
- if ((!ieee->hard_start_xmit && !(ieee->softmac_features &
- IEEE_SOFTMAC_TX_QUEUE)) ||
+ if (!(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) ||
((!ieee->softmac_data_hard_start_xmit &&
(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
netdev_warn(ieee->dev, "No xmit handler.\n");
@@ -892,7 +891,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
tcb_desc->tx_dis_rate_fallback = 1;
}
- tcb_desc->RATRIndex = 7;
+ tcb_desc->ratr_index = 7;
tcb_desc->tx_use_drv_assinged_rate = 1;
} else {
if (is_multicast_ether_addr(header.addr1))
@@ -916,7 +915,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
tcb_desc->tx_dis_rate_fallback = 1;
}
- tcb_desc->RATRIndex = 7;
+ tcb_desc->ratr_index = 7;
tcb_desc->tx_use_drv_assinged_rate = 1;
tcb_desc->bdhcp = 1;
}
@@ -938,11 +937,6 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_bytes += le16_to_cpu(txb->payload_size);
rtllib_softmac_xmit(txb, ieee);
} else {
- if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
- stats->tx_packets++;
- stats->tx_bytes += le16_to_cpu(txb->payload_size);
- return 0;
- }
rtllib_txb_free(txb);
}
}
diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c
index d6691f3c7c70..e9469bfef3dd 100644
--- a/drivers/staging/rtl8192e/rtllib_wx.c
+++ b/drivers/staging/rtl8192e/rtllib_wx.c
@@ -19,7 +19,7 @@
#include "rtllib.h"
static const char * const rtllib_modes[] = {
- "a", "b", "g", "?", "N-24G", "N-5G"
+ "a", "b", "g", "?", "N-24G"
};
#define MAX_CUSTOM_LEN 64
@@ -118,7 +118,7 @@ static inline char *rtl819x_translate_scan(struct rtllib_device *ieee,
max_rate = rate;
}
- if (network->mode >= IEEE_N_24G) {
+ if (network->mode >= WIRELESS_MODE_N_24G) {
struct ht_capab_ele *ht_cap = NULL;
bool is40M = false, isShortGI = false;
u8 max_mcs = 0;
@@ -416,22 +416,6 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
*/
sec.flags |= SEC_LEVEL;
sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
-
- if (ieee->set_security)
- ieee->set_security(dev, &sec);
-
- /* Do not reset port if card is in Managed mode since resetting will
- * generate new IEEE 802.11 authentication which may end up in looping
- * with IEEE 802.1X. If your hardware requires a reset after WEP
- * configuration (for example... Prism2), implement the reset_port in
- * the callbacks structures used to initialize the 802.11 stack.
- */
- if (ieee->reset_on_keychange &&
- ieee->iw_mode != IW_MODE_INFRA &&
- ieee->reset_port && ieee->reset_port(dev)) {
- netdev_dbg(dev, "%s: reset_port failed\n", dev->name);
- return -EINVAL;
- }
return 0;
}
EXPORT_SYMBOL(rtllib_wx_set_encode);
@@ -623,15 +607,6 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
sec.flags &= ~SEC_LEVEL;
}
done:
- if (ieee->set_security)
- ieee->set_security(ieee->dev, &sec);
-
- if (ieee->reset_on_keychange &&
- ieee->iw_mode != IW_MODE_INFRA &&
- ieee->reset_port && ieee->reset_port(dev)) {
- netdev_dbg(ieee->dev, "Port reset failed\n");
- return -EINVAL;
- }
return ret;
}
EXPORT_SYMBOL(rtllib_wx_set_encode_ext);
@@ -644,7 +619,7 @@ int rtllib_wx_set_mlme(struct rtllib_device *ieee,
bool deauth = false;
struct iw_mlme *mlme = (struct iw_mlme *)extra;
- if (ieee->state != RTLLIB_LINKED)
+ if (ieee->link_state != MAC80211_LINKED)
return -ENOLINK;
mutex_lock(&ieee->wx_mutex);
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
index c3c1b49674d3..1e9e1089032b 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
@@ -2275,7 +2275,10 @@ void Hal_EfuseParseBTCoexistInfo_8723B(
pHalData->EEPROMBluetoothAntNum = tempval & BIT(0);
/* EFUSE_0xC3[6] == 0, S1(Main)-RF_PATH_A; */
/* EFUSE_0xC3[6] == 1, S0(Aux)-RF_PATH_B */
- pHalData->ant_path = (tempval & BIT(6))? RF_PATH_B : RF_PATH_A;
+ if (tempval & BIT(6))
+ pHalData->ant_path = RF_PATH_B;
+ else
+ pHalData->ant_path = RF_PATH_A;
} else {
pHalData->EEPROMBluetoothAntNum = Ant_x1;
if (pHalData->PackageType == PACKAGE_QFN68)
diff --git a/drivers/staging/rtl8723bs/include/sta_info.h b/drivers/staging/rtl8723bs/include/sta_info.h
index 69c377eeeaf0..1ea3fe22b99a 100644
--- a/drivers/staging/rtl8723bs/include/sta_info.h
+++ b/drivers/staging/rtl8723bs/include/sta_info.h
@@ -16,9 +16,9 @@
/* if mode == 0, then the sta is allowed once the addr is hit. */
/* if mode == 1, then the sta is rejected once the addr is non-hit. */
struct rtw_wlan_acl_node {
- struct list_head list;
- u8 addr[ETH_ALEN];
- u8 valid;
+ struct list_head list;
+ u8 addr[ETH_ALEN];
+ u8 valid;
};
/* mode = 0, disable */
@@ -340,19 +340,19 @@ struct sta_priv {
static inline u32 wifi_mac_hash(u8 *mac)
{
- u32 x;
+ u32 x;
- x = mac[0];
- x = (x << 2) ^ mac[1];
- x = (x << 2) ^ mac[2];
- x = (x << 2) ^ mac[3];
- x = (x << 2) ^ mac[4];
- x = (x << 2) ^ mac[5];
+ x = mac[0];
+ x = (x << 2) ^ mac[1];
+ x = (x << 2) ^ mac[2];
+ x = (x << 2) ^ mac[3];
+ x = (x << 2) ^ mac[4];
+ x = (x << 2) ^ mac[5];
- x ^= x >> 8;
- x = x & (NUM_STA - 1);
+ x ^= x >> 8;
+ x = x & (NUM_STA - 1);
- return x;
+ return x;
}
diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
index 84a9f4dd8f95..2ae7843abdf7 100644
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
@@ -305,7 +305,6 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl
memcpy(pwlanhdr->addr2, pnetwork->network.mac_address, ETH_ALEN);
memcpy(pwlanhdr->addr3, pnetwork->network.mac_address, ETH_ALEN);
-
pbuf += sizeof(struct ieee80211_hdr_3addr);
len = sizeof(struct ieee80211_hdr_3addr);
@@ -325,15 +324,14 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl
exit:
return bss;
-
}
/*
- Check the given bss is valid by kernel API cfg80211_get_bss()
- @padapter : the given adapter
-
- return true if bss is valid, false for not found.
-*/
+ * Check the given bss is valid by kernel API cfg80211_get_bss()
+ * @padapter : the given adapter
+ *
+ * return true if bss is valid, false for not found.
+ */
int rtw_cfg80211_check_bss(struct adapter *padapter)
{
struct wlan_bssid_ex *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);
@@ -374,7 +372,6 @@ void rtw_cfg80211_ibss_indicate_connect(struct adapter *padapter)
struct wlan_network *scanned = pmlmepriv->cur_network_scanned;
if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
-
memcpy(&cur_network->network, pnetwork, sizeof(struct wlan_bssid_ex));
rtw_cfg80211_inform_bss(padapter, cur_network);
} else {
@@ -495,7 +492,6 @@ void rtw_cfg80211_indicate_disconnect(struct adapter *padapter)
}
}
-
static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
{
int ret = 0;
@@ -569,7 +565,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
rtw_ap_set_wep_key(padapter, param->u.crypt.key, wep_key_len, wep_key_idx, 1);
goto exit;
-
}
/* group key */
@@ -581,7 +576,7 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
if (param->u.crypt.key_len == 13)
- psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+ psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
@@ -616,11 +611,9 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
pbcmc_sta->ieee8021x_blocked = false;
pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
}
-
}
goto exit;
-
}
if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
@@ -643,7 +636,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
psecuritypriv->busetkipkey = true;
} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
-
psta->dot118021XPrivacy = _AES_;
} else {
psta->dot118021XPrivacy = _NO_PRIVACY_;
@@ -695,17 +687,13 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
pbcmc_sta->ieee8021x_blocked = false;
pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
}
-
}
-
}
-
}
exit:
return ret;
-
}
static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
@@ -789,7 +777,6 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
if (strcmp(param->u.crypt.alg, "none") != 0)
psta->ieee8021x_blocked = false;
-
if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
(padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled)) {
psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
@@ -900,7 +887,6 @@ static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
-
if (!mac_addr || is_broadcast_ether_addr(mac_addr))
param->u.crypt.set_tx = 0; /* for wpa/wpa2 group key */
else
@@ -932,7 +918,6 @@ addkey_end:
kfree(param);
return ret;
-
}
static int cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
@@ -983,7 +968,6 @@ static int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
}
return 0;
-
}
static int cfg80211_rtw_get_station(struct wiphy *wiphy,
@@ -1168,7 +1152,6 @@ void rtw_cfg80211_surveydone_event_callback(struct adapter *padapter)
/* ev =translate_scan(padapter, a, pnetwork, ev, stop); */
rtw_cfg80211_inform_bss(padapter, pnetwork);
}
-
}
spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
@@ -1200,7 +1183,6 @@ static int rtw_cfg80211_set_probe_req_wpsp2pie(struct adapter *padapter, char *b
}
return ret;
-
}
static int cfg80211_rtw_scan(struct wiphy *wiphy
@@ -1305,14 +1287,13 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy
} else if (request->n_channels <= 4) {
for (j = request->n_channels - 1; j >= 0; j--)
for (i = 0; i < survey_times; i++)
- memcpy(&ch[j*survey_times+i], &ch[j], sizeof(struct rtw_ieee80211_channel));
+ memcpy(&ch[j*survey_times+i], &ch[j], sizeof(struct rtw_ieee80211_channel));
_status = rtw_sitesurvey_cmd(padapter, ssid, RTW_SSID_SCAN_AMOUNT, ch, survey_times * request->n_channels);
} else {
_status = rtw_sitesurvey_cmd(padapter, ssid, RTW_SSID_SCAN_AMOUNT, NULL, 0);
}
spin_unlock_bh(&pmlmepriv->lock);
-
if (_status == false)
ret = -1;
@@ -1327,7 +1308,6 @@ check_need_indicate_scan_done:
exit:
return ret;
-
}
static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
@@ -1342,12 +1322,10 @@ static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv, u32
return 0;
}
-
if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
return 0;
-
}
static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
@@ -1373,7 +1351,6 @@ static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
-
break;
default:
psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
@@ -1381,7 +1358,6 @@ static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
}
return 0;
-
}
static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv, u32 cipher, bool ucast)
@@ -1391,7 +1367,6 @@ static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv, u32 ciph
u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :
&psecuritypriv->dot118021XGrpPrivacy;
-
if (!cipher) {
*profile_cipher = _NO_PRIVACY_;
psecuritypriv->ndisencryptstatus = ndisencryptstatus;
@@ -1603,7 +1578,6 @@ static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
}
if (params->ssid_len > IW_ESSID_MAX_SIZE) {
-
ret = -E2BIG;
goto exit;
}
@@ -1671,7 +1645,6 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
padapter->mlmepriv.not_indic_disco = true;
-
if (adapter_wdev_data(padapter)->block == true) {
ret = -EBUSY;
goto exit;
@@ -1694,7 +1667,6 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
}
if (sme->ssid_len > IW_ESSID_MAX_SIZE) {
-
ret = -E2BIG;
goto exit;
}
@@ -1889,7 +1861,6 @@ static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
/* overwrite PMKID */
for (index = 0 ; index < NUM_PMKID_CACHE; index++) {
if (!memcmp(psecuritypriv->PMKIDList[index].Bssid, (u8 *)pmksa->bssid, ETH_ALEN)) {
-
memcpy(psecuritypriv->PMKIDList[index].PMKID, (u8 *)pmksa->pmkid, WLAN_PMKID_LEN);
psecuritypriv->PMKIDList[index].bUsed = true;
psecuritypriv->PMKIDIndex = index+1;
@@ -1899,7 +1870,6 @@ static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
}
if (!blInserted) {
-
memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, (u8 *)pmksa->bssid, ETH_ALEN);
memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, (u8 *)pmksa->pmkid, WLAN_PMKID_LEN);
@@ -2135,11 +2105,9 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
pattrib->seqnum = pmlmeext->mgnt_seq;
pmlmeext->mgnt_seq++;
-
pattrib->last_txcmdsz = pattrib->pktlen;
dump_mgntframe(padapter, pmgntframe);
-
}
fail:
@@ -2147,11 +2115,8 @@ fail:
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
-
}
-
-
static const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
.ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
};
@@ -2324,7 +2289,6 @@ static int rtw_add_beacon(struct adapter *adapter, const u8 *head, size_t head_l
else
ret = -EINVAL;
-
kfree(pbuf);
return ret;
@@ -2404,7 +2368,6 @@ static int cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev
return -EINVAL;
}
-
spin_lock_bh(&pstapriv->asoc_list_lock);
phead = &pstapriv->asoc_list;
@@ -2423,9 +2386,7 @@ static int cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev
break;
}
-
}
-
}
spin_unlock_bh(&pstapriv->asoc_list_lock);
@@ -2433,7 +2394,6 @@ static int cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev
associated_clients_update(padapter, updated);
return ret;
-
}
static int cfg80211_rtw_change_station(struct wiphy *wiphy, struct net_device *ndev,
@@ -2465,7 +2425,6 @@ static struct sta_info *rtw_sta_info_get_by_idx(const int idx, struct sta_priv *
static int cfg80211_rtw_dump_station(struct wiphy *wiphy, struct net_device *ndev,
int idx, u8 *mac, struct station_info *sinfo)
{
-
int ret = 0;
struct adapter *padapter = rtw_netdev_priv(ndev);
struct sta_info *psta = NULL;
@@ -2568,7 +2527,6 @@ static int _cfg80211_rtw_mgmt_tx(struct adapter *padapter, u8 tx_ch, const u8 *b
exit:
return ret;
-
}
static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy,
@@ -2640,7 +2598,6 @@ exit:
static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, enum nl80211_band band)
{
-
#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */
#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */
@@ -2692,12 +2649,10 @@ void rtw_cfg80211_init_wiphy(struct adapter *padapter)
/* copy mac_addr to wiphy */
memcpy(wiphy->perm_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
-
}
static void rtw_cfg80211_preinit_wiphy(struct adapter *padapter, struct wiphy *wiphy)
{
-
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;
@@ -2810,7 +2765,7 @@ int rtw_wdev_alloc(struct adapter *padapter, struct device *dev)
wdev->netdev = pnetdev;
wdev->iftype = NL80211_IFTYPE_STATION; /* will be init in rtw_hal_init() */
- /* Must sync with _rtw_init_mlme_priv() */
+ /* Must sync with _rtw_init_mlme_priv() */
/* pmlmepriv->fw_state = WIFI_STATION_STATE */
padapter->rtw_wdev = wdev;
pnetdev->ieee80211_ptr = wdev;
@@ -2844,7 +2799,6 @@ unregister_wiphy:
wiphy_free(wiphy);
exit:
return ret;
-
}
void rtw_wdev_free(struct wireless_dev *wdev)
diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c
index db2dd0baa8be..08543a3936da 100644
--- a/drivers/staging/rts5208/rtsx.c
+++ b/drivers/staging/rts5208/rtsx.c
@@ -382,27 +382,21 @@ static int rtsx_control_thread(void *__dev)
if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
dev_err(&dev->pci->dev, "UNKNOWN data direction\n");
chip->srb->result = DID_ERROR << 16;
- }
-
- /* reject if target != 0 or if LUN is higher than
- * the maximum known LUN
- */
- else if (chip->srb->device->id) {
+ } else if (chip->srb->device->id) {
+ /* reject if target != 0 or if LUN is higher than
+ * the maximum known LUN
+ */
dev_err(&dev->pci->dev, "Bad target number (%d:%d)\n",
chip->srb->device->id,
(u8)chip->srb->device->lun);
chip->srb->result = DID_BAD_TARGET << 16;
- }
-
- else if (chip->srb->device->lun > chip->max_lun) {
+ } else if (chip->srb->device->lun > chip->max_lun) {
dev_err(&dev->pci->dev, "Bad LUN (%d:%d)\n",
chip->srb->device->id,
(u8)chip->srb->device->lun);
chip->srb->result = DID_BAD_TARGET << 16;
- }
-
- /* we've got a command, let's do it! */
- else {
+ } else {
+ /* we've got a command, let's do it! */
scsi_show_command(chip);
rtsx_invoke_transport(chip->srb, chip);
}
diff --git a/drivers/staging/sm750fb/Kconfig b/drivers/staging/sm750fb/Kconfig
index 1461c89701c3..ab3d9b057d56 100644
--- a/drivers/staging/sm750fb/Kconfig
+++ b/drivers/staging/sm750fb/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
config FB_SM750
tristate "Silicon Motion SM750 framebuffer support"
- depends on FB && PCI
+ depends on FB && PCI && HAS_IOPORT
select FB_MODE_HELPERS
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 22ace3168723..55e302a27847 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -16,7 +16,7 @@
#include <linux/pagemap.h>
#include <linux/screen_info.h>
#include <linux/console.h>
-#include <asm/fb.h>
+
#include "sm750.h"
#include "sm750_accel.h"
#include "sm750_cursor.h"
diff --git a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h
index 66965da11443..52e106f117da 100644
--- a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h
+++ b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h
@@ -78,8 +78,6 @@ struct vchiq_service_params_kernel {
short version_min; /* Update for incompatible changes */
};
-struct vchiq_instance;
-
extern int vchiq_initialise(struct vchiq_instance **pinstance);
extern int vchiq_shutdown(struct vchiq_instance *instance);
extern int vchiq_connect(struct vchiq_instance *instance);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index 90a3958d1f29..aa2313f3bcab 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -415,7 +415,7 @@ free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagel
pagelistinfo->scatterlist_mapped = 0;
/* Deal with any partial cache lines (fragments) */
- if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) {
+ if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS && g_fragments_base) {
char *fragments = g_fragments_base +
(pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) *
g_fragments_size;
@@ -462,7 +462,7 @@ free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagel
cleanup_pagelistinfo(instance, pagelistinfo);
}
-int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
+static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
{
struct device *dev = &pdev->dev;
struct vchiq_drvdata *drvdata = platform_get_drvdata(pdev);
diff --git a/drivers/staging/vt6655/Kconfig b/drivers/staging/vt6655/Kconfig
index d1cd5de46dcf..077f62ebe80c 100644
--- a/drivers/staging/vt6655/Kconfig
+++ b/drivers/staging/vt6655/Kconfig
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
config VT6655
tristate "VIA Technologies VT6655 support"
- depends on PCI && MAC80211 && m
+ depends on PCI && HAS_IOPORT && MAC80211 && m
help
This is a vendor-written driver for VIA VT6655.
diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h
index e33dd1b9c40e..a4799589e469 100644
--- a/drivers/staging/wlan-ng/hfa384x.h
+++ b/drivers/staging/wlan-ng/hfa384x.h
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index c7cd54171d99..3e8c92675c82 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c
index cd271b1da69f..048e1c3fe19b 100644
--- a/drivers/staging/wlan-ng/p80211conv.c
+++ b/drivers/staging/wlan-ng/p80211conv.c
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211conv.h b/drivers/staging/wlan-ng/p80211conv.h
index dfb762bce84d..45234769f45d 100644
--- a/drivers/staging/wlan-ng/p80211conv.h
+++ b/drivers/staging/wlan-ng/p80211conv.h
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211hdr.h b/drivers/staging/wlan-ng/p80211hdr.h
index 93195a4c5b01..7ea1c8ec05ed 100644
--- a/drivers/staging/wlan-ng/p80211hdr.h
+++ b/drivers/staging/wlan-ng/p80211hdr.h
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211ioctl.h b/drivers/staging/wlan-ng/p80211ioctl.h
index b50ce11147dd..176e327a45bc 100644
--- a/drivers/staging/wlan-ng/p80211ioctl.h
+++ b/drivers/staging/wlan-ng/p80211ioctl.h
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h
index 1b91b64c12ed..1cbb4b67a9a6 100644
--- a/drivers/staging/wlan-ng/p80211metadef.h
+++ b/drivers/staging/wlan-ng/p80211metadef.h
@@ -6,27 +6,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h
index 4adc64580185..a52217c9b953 100644
--- a/drivers/staging/wlan-ng/p80211metastruct.h
+++ b/drivers/staging/wlan-ng/p80211metastruct.h
@@ -6,27 +6,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
@@ -114,22 +93,8 @@ struct p80211msg_dot11req_scan_results {
struct p80211item_uint32 cfpollreq;
struct p80211item_uint32 privacy;
struct p80211item_uint32 capinfo;
- struct p80211item_uint32 basicrate1;
- struct p80211item_uint32 basicrate2;
- struct p80211item_uint32 basicrate3;
- struct p80211item_uint32 basicrate4;
- struct p80211item_uint32 basicrate5;
- struct p80211item_uint32 basicrate6;
- struct p80211item_uint32 basicrate7;
- struct p80211item_uint32 basicrate8;
- struct p80211item_uint32 supprate1;
- struct p80211item_uint32 supprate2;
- struct p80211item_uint32 supprate3;
- struct p80211item_uint32 supprate4;
- struct p80211item_uint32 supprate5;
- struct p80211item_uint32 supprate6;
- struct p80211item_uint32 supprate7;
- struct p80211item_uint32 supprate8;
+ struct p80211item_uint32 basicrate[8];
+ struct p80211item_uint32 supprate[8];
} __packed;
struct p80211msg_dot11req_start {
diff --git a/drivers/staging/wlan-ng/p80211mgmt.h b/drivers/staging/wlan-ng/p80211mgmt.h
index fc23fae5651b..7ffc202d9007 100644
--- a/drivers/staging/wlan-ng/p80211mgmt.h
+++ b/drivers/staging/wlan-ng/p80211mgmt.h
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211msg.h b/drivers/staging/wlan-ng/p80211msg.h
index f68d8b7d5ad8..d56bc6079ed4 100644
--- a/drivers/staging/wlan-ng/p80211msg.h
+++ b/drivers/staging/wlan-ng/p80211msg.h
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c
index 6bef419e8ad0..8634fc89a6c2 100644
--- a/drivers/staging/wlan-ng/p80211netdev.c
+++ b/drivers/staging/wlan-ng/p80211netdev.c
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h
index 1cee51a1075e..f5186380b629 100644
--- a/drivers/staging/wlan-ng/p80211netdev.h
+++ b/drivers/staging/wlan-ng/p80211netdev.h
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c
index 809cf3d480e9..6ec559ffd2f9 100644
--- a/drivers/staging/wlan-ng/p80211req.c
+++ b/drivers/staging/wlan-ng/p80211req.c
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211req.h b/drivers/staging/wlan-ng/p80211req.h
index bc45cd5f91e4..39213f73913c 100644
--- a/drivers/staging/wlan-ng/p80211req.h
+++ b/drivers/staging/wlan-ng/p80211req.h
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h
index b2ed96960413..5e4ea5f92058 100644
--- a/drivers/staging/wlan-ng/p80211types.h
+++ b/drivers/staging/wlan-ng/p80211types.h
@@ -9,27 +9,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c
index 3ff7ee7011df..e7b26b057124 100644
--- a/drivers/staging/wlan-ng/p80211wep.c
+++ b/drivers/staging/wlan-ng/p80211wep.c
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c
index 11658865ca50..5d03b2b9aab4 100644
--- a/drivers/staging/wlan-ng/prism2fw.c
+++ b/drivers/staging/wlan-ng/prism2fw.c
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c
index 9030a8939a9b..d5737166564e 100644
--- a/drivers/staging/wlan-ng/prism2mgmt.c
+++ b/drivers/staging/wlan-ng/prism2mgmt.c
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
@@ -437,42 +416,22 @@ int prism2mgmt_scan_results(struct wlandevice *wlandev, void *msgp)
if (item->supprates[count] == 0)
break;
-#define REQBASICRATE(N) \
- do { \
- if ((count >= (N)) && DOT11_RATE5_ISBASIC_GET( \
- item->supprates[(N) - 1])) { \
- req->basicrate ## N .data = item->supprates[(N) - 1]; \
- req->basicrate ## N .status = \
- P80211ENUM_msgitem_status_data_ok; \
- } \
- } while (0)
-
- REQBASICRATE(1);
- REQBASICRATE(2);
- REQBASICRATE(3);
- REQBASICRATE(4);
- REQBASICRATE(5);
- REQBASICRATE(6);
- REQBASICRATE(7);
- REQBASICRATE(8);
-
-#define REQSUPPRATE(N) \
- do { \
- if (count >= (N)) { \
- req->supprate ## N .data = item->supprates[(N) - 1]; \
- req->supprate ## N .status = \
- P80211ENUM_msgitem_status_data_ok; \
- } \
- } while (0)
-
- REQSUPPRATE(1);
- REQSUPPRATE(2);
- REQSUPPRATE(3);
- REQSUPPRATE(4);
- REQSUPPRATE(5);
- REQSUPPRATE(6);
- REQSUPPRATE(7);
- REQSUPPRATE(8);
+ for (int i = 0; i < 8; i++) {
+ if (count > i &&
+ DOT11_RATE5_ISBASIC_GET(item->supprates[i])) {
+ req->basicrate[i].data = item->supprates[i];
+ req->basicrate[i].status =
+ P80211ENUM_msgitem_status_data_ok;
+ }
+ }
+
+ for (int i = 0; i < 8; i++) {
+ if (count > i) {
+ req->supprate[i].data = item->supprates[i];
+ req->supprate[i].status =
+ P80211ENUM_msgitem_status_data_ok;
+ }
+ }
/* beacon period */
req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h
index 7132cec2d7eb..083a055ee986 100644
--- a/drivers/staging/wlan-ng/prism2mgmt.h
+++ b/drivers/staging/wlan-ng/prism2mgmt.h
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c
index fcf8313870af..4346b90c1a77 100644
--- a/drivers/staging/wlan-ng/prism2mib.c
+++ b/drivers/staging/wlan-ng/prism2mib.c
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c
index daa7cc4e897c..57180bb71699 100644
--- a/drivers/staging/wlan-ng/prism2sta.c
+++ b/drivers/staging/wlan-ng/prism2sta.c
@@ -8,27 +8,6 @@
*
* linux-wlan
*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision
- * by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL. If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
* --------------------------------------------------------------------
*
* Inquiries regarding the linux-wlan Open Source project can be
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index 557516c642c3..5b90c22ee3dc 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -726,8 +726,8 @@ static int iscsi_add_notunderstood_response(
}
INIT_LIST_HEAD(&extra_response->er_list);
- strlcpy(extra_response->key, key, sizeof(extra_response->key));
- strlcpy(extra_response->value, NOTUNDERSTOOD,
+ strscpy(extra_response->key, key, sizeof(extra_response->key));
+ strscpy(extra_response->value, NOTUNDERSTOOD,
sizeof(extra_response->value));
list_add_tail(&extra_response->er_list,
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 6231fa4ef5c6..91a75a4a7cc1 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -1375,7 +1375,7 @@ void iscsit_collect_login_stats(
if (conn->param_list)
intrname = iscsi_find_param_from_key(INITIATORNAME,
conn->param_list);
- strlcpy(ls->last_intr_fail_name,
+ strscpy(ls->last_intr_fail_name,
(intrname ? intrname->value : "Unknown"),
sizeof(ls->last_intr_fail_name));
@@ -1414,7 +1414,7 @@ void iscsit_fill_cxn_timeout_err_stats(struct iscsit_session *sess)
return;
spin_lock_bh(&tiqn->sess_err_stats.lock);
- strlcpy(tiqn->sess_err_stats.last_sess_fail_rem_name,
+ strscpy(tiqn->sess_err_stats.last_sess_fail_rem_name,
sess->sess_ops->InitiatorName,
sizeof(tiqn->sess_err_stats.last_sess_fail_rem_name));
tiqn->sess_err_stats.last_sess_failure_type =
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 74b67c346dfe..936e5ff1b209 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -649,7 +649,7 @@ static void dev_set_t10_wwn_model_alias(struct se_device *dev)
* here without potentially breaking existing setups, so continue to
* truncate one byte shorter than what can be carried in INQUIRY.
*/
- strlcpy(dev->t10_wwn.model, configname, INQUIRY_MODEL_LEN);
+ strscpy(dev->t10_wwn.model, configname, INQUIRY_MODEL_LEN);
}
static ssize_t emulate_model_alias_store(struct config_item *item,
@@ -675,7 +675,7 @@ static ssize_t emulate_model_alias_store(struct config_item *item,
if (flag) {
dev_set_t10_wwn_model_alias(dev);
} else {
- strlcpy(dev->t10_wwn.model, dev->transport->inquiry_prod,
+ strscpy(dev->t10_wwn.model, dev->transport->inquiry_prod,
sizeof(dev->t10_wwn.model));
}
da->emulate_model_alias = flag;
@@ -1426,7 +1426,7 @@ static ssize_t target_wwn_vendor_id_store(struct config_item *item,
}
BUILD_BUG_ON(sizeof(dev->t10_wwn.vendor) != INQUIRY_VENDOR_LEN + 1);
- strlcpy(dev->t10_wwn.vendor, stripped, sizeof(dev->t10_wwn.vendor));
+ strscpy(dev->t10_wwn.vendor, stripped, sizeof(dev->t10_wwn.vendor));
pr_debug("Target_Core_ConfigFS: Set emulated T10 Vendor Identification:"
" %s\n", dev->t10_wwn.vendor);
@@ -1482,7 +1482,7 @@ static ssize_t target_wwn_product_id_store(struct config_item *item,
}
BUILD_BUG_ON(sizeof(dev->t10_wwn.model) != INQUIRY_MODEL_LEN + 1);
- strlcpy(dev->t10_wwn.model, stripped, sizeof(dev->t10_wwn.model));
+ strscpy(dev->t10_wwn.model, stripped, sizeof(dev->t10_wwn.model));
pr_debug("Target_Core_ConfigFS: Set emulated T10 Model Identification: %s\n",
dev->t10_wwn.model);
@@ -1538,7 +1538,7 @@ static ssize_t target_wwn_revision_store(struct config_item *item,
}
BUILD_BUG_ON(sizeof(dev->t10_wwn.revision) != INQUIRY_REVISION_LEN + 1);
- strlcpy(dev->t10_wwn.revision, stripped, sizeof(dev->t10_wwn.revision));
+ strscpy(dev->t10_wwn.revision, stripped, sizeof(dev->t10_wwn.revision));
pr_debug("Target_Core_ConfigFS: Set emulated T10 Revision: %s\n",
dev->t10_wwn.revision);
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 90f3f4926172..b7ac60f4a219 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -789,10 +789,10 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
xcopy_lun->lun_tpg = &xcopy_pt_tpg;
/* Preload the default INQUIRY const values */
- strlcpy(dev->t10_wwn.vendor, "LIO-ORG", sizeof(dev->t10_wwn.vendor));
- strlcpy(dev->t10_wwn.model, dev->transport->inquiry_prod,
+ strscpy(dev->t10_wwn.vendor, "LIO-ORG", sizeof(dev->t10_wwn.vendor));
+ strscpy(dev->t10_wwn.model, dev->transport->inquiry_prod,
sizeof(dev->t10_wwn.model));
- strlcpy(dev->t10_wwn.revision, dev->transport->inquiry_rev,
+ strscpy(dev->t10_wwn.revision, dev->transport->inquiry_rev,
sizeof(dev->t10_wwn.revision));
return dev;
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index ce0e000b74fc..4d447520bab8 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -896,7 +896,7 @@ static void fd_free_prot(struct se_device *dev)
fd_dev->fd_prot_file = NULL;
}
-static struct sbc_ops fd_sbc_ops = {
+static struct exec_cmd_ops fd_exec_cmd_ops = {
.execute_rw = fd_execute_rw,
.execute_sync_cache = fd_execute_sync_cache,
.execute_write_same = fd_execute_write_same,
@@ -906,7 +906,7 @@ static struct sbc_ops fd_sbc_ops = {
static sense_reason_t
fd_parse_cdb(struct se_cmd *cmd)
{
- return sbc_parse_cdb(cmd, &fd_sbc_ops);
+ return sbc_parse_cdb(cmd, &fd_exec_cmd_ops);
}
static const struct target_backend_ops fileio_ops = {
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 3c462d69daca..a3c5f3558a33 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -23,13 +23,16 @@
#include <linux/file.h>
#include <linux/module.h>
#include <linux/scatterlist.h>
+#include <linux/pr.h>
#include <scsi/scsi_proto.h>
+#include <scsi/scsi_common.h>
#include <asm/unaligned.h>
#include <target/target_core_base.h>
#include <target/target_core_backend.h>
#include "target_core_iblock.h"
+#include "target_core_pr.h"
#define IBLOCK_MAX_BIO_PER_TASK 32 /* max # of bios to submit at a time */
#define IBLOCK_BIO_POOL_SIZE 128
@@ -309,7 +312,7 @@ static sector_t iblock_get_blocks(struct se_device *dev)
return blocks_long;
}
-static void iblock_complete_cmd(struct se_cmd *cmd)
+static void iblock_complete_cmd(struct se_cmd *cmd, blk_status_t blk_status)
{
struct iblock_req *ibr = cmd->priv;
u8 status;
@@ -317,7 +320,9 @@ static void iblock_complete_cmd(struct se_cmd *cmd)
if (!refcount_dec_and_test(&ibr->pending))
return;
- if (atomic_read(&ibr->ib_bio_err_cnt))
+ if (blk_status == BLK_STS_RESV_CONFLICT)
+ status = SAM_STAT_RESERVATION_CONFLICT;
+ else if (atomic_read(&ibr->ib_bio_err_cnt))
status = SAM_STAT_CHECK_CONDITION;
else
status = SAM_STAT_GOOD;
@@ -330,6 +335,7 @@ static void iblock_bio_done(struct bio *bio)
{
struct se_cmd *cmd = bio->bi_private;
struct iblock_req *ibr = cmd->priv;
+ blk_status_t blk_status = bio->bi_status;
if (bio->bi_status) {
pr_err("bio error: %p, err: %d\n", bio, bio->bi_status);
@@ -342,7 +348,7 @@ static void iblock_bio_done(struct bio *bio)
bio_put(bio);
- iblock_complete_cmd(cmd);
+ iblock_complete_cmd(cmd, blk_status);
}
static struct bio *iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num,
@@ -758,7 +764,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
if (!sgl_nents) {
refcount_set(&ibr->pending, 1);
- iblock_complete_cmd(cmd);
+ iblock_complete_cmd(cmd, BLK_STS_OK);
return 0;
}
@@ -816,7 +822,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
}
iblock_submit_bios(&list);
- iblock_complete_cmd(cmd);
+ iblock_complete_cmd(cmd, BLK_STS_OK);
return 0;
fail_put_bios:
@@ -828,6 +834,258 @@ fail:
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
+static sense_reason_t iblock_execute_pr_out(struct se_cmd *cmd, u8 sa, u64 key,
+ u64 sa_key, u8 type, bool aptpl)
+{
+ struct se_device *dev = cmd->se_dev;
+ struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
+ struct block_device *bdev = ib_dev->ibd_bd;
+ const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
+ int ret;
+
+ if (!ops) {
+ pr_err("Block device does not support pr_ops but iblock device has been configured for PR passthrough.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ switch (sa) {
+ case PRO_REGISTER:
+ case PRO_REGISTER_AND_IGNORE_EXISTING_KEY:
+ if (!ops->pr_register) {
+ pr_err("block device does not support pr_register.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ /* The block layer pr ops always enables aptpl */
+ if (!aptpl)
+ pr_info("APTPL not set by initiator, but will be used.\n");
+
+ ret = ops->pr_register(bdev, key, sa_key,
+ sa == PRO_REGISTER ? 0 : PR_FL_IGNORE_KEY);
+ break;
+ case PRO_RESERVE:
+ if (!ops->pr_reserve) {
+ pr_err("block_device does not support pr_reserve.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ ret = ops->pr_reserve(bdev, key, scsi_pr_type_to_block(type), 0);
+ break;
+ case PRO_CLEAR:
+ if (!ops->pr_clear) {
+ pr_err("block_device does not support pr_clear.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ ret = ops->pr_clear(bdev, key);
+ break;
+ case PRO_PREEMPT:
+ case PRO_PREEMPT_AND_ABORT:
+ if (!ops->pr_clear) {
+ pr_err("block_device does not support pr_preempt.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ ret = ops->pr_preempt(bdev, key, sa_key,
+ scsi_pr_type_to_block(type),
+ sa == PRO_PREEMPT ? false : true);
+ break;
+ case PRO_RELEASE:
+ if (!ops->pr_clear) {
+ pr_err("block_device does not support pr_pclear.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ ret = ops->pr_release(bdev, key, scsi_pr_type_to_block(type));
+ break;
+ default:
+ pr_err("Unknown PERSISTENT_RESERVE_OUT SA: 0x%02x\n", sa);
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ if (!ret)
+ return TCM_NO_SENSE;
+ else if (ret == PR_STS_RESERVATION_CONFLICT)
+ return TCM_RESERVATION_CONFLICT;
+ else
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+}
+
+static void iblock_pr_report_caps(unsigned char *param_data)
+{
+ u16 len = 8;
+
+ put_unaligned_be16(len, &param_data[0]);
+ /*
+ * When using the pr_ops passthrough method we only support exporting
+ * the device through one target port because from the backend module
+ * level we can't see the target port config. As a result we only
+ * support registration directly from the I_T nexus the cmd is sent
+ * through and do not set ATP_C here.
+ *
+ * The block layer pr_ops do not support passing in initiators so
+ * we don't set SIP_C here.
+ */
+ /* PTPL_C: Persistence across Target Power Loss bit */
+ param_data[2] |= 0x01;
+ /*
+ * We are filling in the PERSISTENT RESERVATION TYPE MASK below, so
+ * set the TMV: Task Mask Valid bit.
+ */
+ param_data[3] |= 0x80;
+ /*
+ * Change ALLOW COMMANDs to 0x20 or 0x40 later from Table 166
+ */
+ param_data[3] |= 0x10; /* ALLOW COMMANDs field 001b */
+ /*
+ * PTPL_A: Persistence across Target Power Loss Active bit. The block
+ * layer pr ops always enables this so report it active.
+ */
+ param_data[3] |= 0x01;
+ /*
+ * Setup the PERSISTENT RESERVATION TYPE MASK from Table 212 spc4r37.
+ */
+ param_data[4] |= 0x80; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */
+ param_data[4] |= 0x40; /* PR_TYPE_EXCLUSIVE_ACCESS_REGONLY */
+ param_data[4] |= 0x20; /* PR_TYPE_WRITE_EXCLUSIVE_REGONLY */
+ param_data[4] |= 0x08; /* PR_TYPE_EXCLUSIVE_ACCESS */
+ param_data[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */
+ param_data[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */
+}
+
+static sense_reason_t iblock_pr_read_keys(struct se_cmd *cmd,
+ unsigned char *param_data)
+{
+ struct se_device *dev = cmd->se_dev;
+ struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
+ struct block_device *bdev = ib_dev->ibd_bd;
+ const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
+ int i, len, paths, data_offset;
+ struct pr_keys *keys;
+ sense_reason_t ret;
+
+ if (!ops) {
+ pr_err("Block device does not support pr_ops but iblock device has been configured for PR passthrough.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ if (!ops->pr_read_keys) {
+ pr_err("Block device does not support read_keys.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ /*
+ * We don't know what's under us, but dm-multipath will register every
+ * path with the same key, so start off with enough space for 16 paths.
+ * which is not a lot of memory and should normally be enough.
+ */
+ paths = 16;
+retry:
+ len = 8 * paths;
+ keys = kzalloc(sizeof(*keys) + len, GFP_KERNEL);
+ if (!keys)
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+ keys->num_keys = paths;
+ if (!ops->pr_read_keys(bdev, keys)) {
+ if (keys->num_keys > paths) {
+ kfree(keys);
+ paths *= 2;
+ goto retry;
+ }
+ } else {
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ goto free_keys;
+ }
+
+ ret = TCM_NO_SENSE;
+
+ put_unaligned_be32(keys->generation, &param_data[0]);
+ if (!keys->num_keys) {
+ put_unaligned_be32(0, &param_data[4]);
+ goto free_keys;
+ }
+
+ put_unaligned_be32(8 * keys->num_keys, &param_data[4]);
+
+ data_offset = 8;
+ for (i = 0; i < keys->num_keys; i++) {
+ if (data_offset + 8 > cmd->data_length)
+ break;
+
+ put_unaligned_be64(keys->keys[i], &param_data[data_offset]);
+ data_offset += 8;
+ }
+
+free_keys:
+ kfree(keys);
+ return ret;
+}
+
+static sense_reason_t iblock_pr_read_reservation(struct se_cmd *cmd,
+ unsigned char *param_data)
+{
+ struct se_device *dev = cmd->se_dev;
+ struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
+ struct block_device *bdev = ib_dev->ibd_bd;
+ const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
+ struct pr_held_reservation rsv = { };
+
+ if (!ops) {
+ pr_err("Block device does not support pr_ops but iblock device has been configured for PR passthrough.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ if (!ops->pr_read_reservation) {
+ pr_err("Block device does not support read_keys.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ if (ops->pr_read_reservation(bdev, &rsv))
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+ put_unaligned_be32(rsv.generation, &param_data[0]);
+ if (!block_pr_type_to_scsi(rsv.type)) {
+ put_unaligned_be32(0, &param_data[4]);
+ return TCM_NO_SENSE;
+ }
+
+ put_unaligned_be32(16, &param_data[4]);
+
+ if (cmd->data_length < 16)
+ return TCM_NO_SENSE;
+ put_unaligned_be64(rsv.key, &param_data[8]);
+
+ if (cmd->data_length < 22)
+ return TCM_NO_SENSE;
+ param_data[21] = block_pr_type_to_scsi(rsv.type);
+
+ return TCM_NO_SENSE;
+}
+
+static sense_reason_t iblock_execute_pr_in(struct se_cmd *cmd, u8 sa,
+ unsigned char *param_data)
+{
+ sense_reason_t ret = TCM_NO_SENSE;
+
+ switch (sa) {
+ case PRI_REPORT_CAPABILITIES:
+ iblock_pr_report_caps(param_data);
+ break;
+ case PRI_READ_KEYS:
+ ret = iblock_pr_read_keys(cmd, param_data);
+ break;
+ case PRI_READ_RESERVATION:
+ ret = iblock_pr_read_reservation(cmd, param_data);
+ break;
+ default:
+ pr_err("Unknown PERSISTENT_RESERVE_IN SA: 0x%02x\n", sa);
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ return ret;
+}
+
static sector_t iblock_get_alignment_offset_lbas(struct se_device *dev)
{
struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
@@ -868,17 +1126,19 @@ static unsigned int iblock_get_io_opt(struct se_device *dev)
return bdev_io_opt(bd);
}
-static struct sbc_ops iblock_sbc_ops = {
+static struct exec_cmd_ops iblock_exec_cmd_ops = {
.execute_rw = iblock_execute_rw,
.execute_sync_cache = iblock_execute_sync_cache,
.execute_write_same = iblock_execute_write_same,
.execute_unmap = iblock_execute_unmap,
+ .execute_pr_out = iblock_execute_pr_out,
+ .execute_pr_in = iblock_execute_pr_in,
};
static sense_reason_t
iblock_parse_cdb(struct se_cmd *cmd)
{
- return sbc_parse_cdb(cmd, &iblock_sbc_ops);
+ return sbc_parse_cdb(cmd, &iblock_exec_cmd_ops);
}
static bool iblock_get_write_cache(struct se_device *dev)
@@ -889,6 +1149,7 @@ static bool iblock_get_write_cache(struct se_device *dev)
static const struct target_backend_ops iblock_ops = {
.name = "iblock",
.inquiry_prod = "IBLOCK",
+ .transport_flags_changeable = TRANSPORT_FLAG_PASSTHROUGH_PGR,
.inquiry_rev = IBLOCK_VERSION,
.owner = THIS_MODULE,
.attach_hba = iblock_attach_hba,
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index d19ec4e6a4c0..49d9167bb263 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -3538,6 +3538,37 @@ out_put_pr_reg:
return ret;
}
+static sense_reason_t
+target_try_pr_out_pt(struct se_cmd *cmd, u8 sa, u64 res_key, u64 sa_res_key,
+ u8 type, bool aptpl, bool all_tg_pt, bool spec_i_pt)
+{
+ struct exec_cmd_ops *ops = cmd->protocol_data;
+
+ if (!cmd->se_sess || !cmd->se_lun) {
+ pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ }
+
+ if (!ops->execute_pr_out) {
+ pr_err("SPC-3 PR: Device has been configured for PR passthrough but it's not supported by the backend.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ switch (sa) {
+ case PRO_REGISTER_AND_MOVE:
+ case PRO_REPLACE_LOST_RESERVATION:
+ pr_err("SPC-3 PR: PRO_REGISTER_AND_MOVE and PRO_REPLACE_LOST_RESERVATION are not supported by PR passthrough.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ if (spec_i_pt || all_tg_pt) {
+ pr_err("SPC-3 PR: SPEC_I_PT and ALL_TG_PT are not supported by PR passthrough.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ return ops->execute_pr_out(cmd, sa, res_key, sa_res_key, type, aptpl);
+}
+
/*
* See spc4r17 section 6.14 Table 170
*/
@@ -3641,6 +3672,12 @@ target_scsi3_emulate_pr_out(struct se_cmd *cmd)
return TCM_PARAMETER_LIST_LENGTH_ERROR;
}
+ if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR) {
+ ret = target_try_pr_out_pt(cmd, sa, res_key, sa_res_key, type,
+ aptpl, all_tg_pt, spec_i_pt);
+ goto done;
+ }
+
/*
* (core_scsi3_emulate_pro_* function parameters
* are defined by spc4r17 Table 174:
@@ -3682,6 +3719,7 @@ target_scsi3_emulate_pr_out(struct se_cmd *cmd)
return TCM_INVALID_CDB_FIELD;
}
+done:
if (!ret)
target_complete_cmd(cmd, SAM_STAT_GOOD);
return ret;
@@ -4039,9 +4077,42 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
return 0;
}
+static sense_reason_t target_try_pr_in_pt(struct se_cmd *cmd, u8 sa)
+{
+ struct exec_cmd_ops *ops = cmd->protocol_data;
+ unsigned char *buf;
+ sense_reason_t ret;
+
+ if (cmd->data_length < 8) {
+ pr_err("PRIN SA SCSI Data Length: %u too small\n",
+ cmd->data_length);
+ return TCM_INVALID_CDB_FIELD;
+ }
+
+ if (!ops->execute_pr_in) {
+ pr_err("SPC-3 PR: Device has been configured for PR passthrough but it's not supported by the backend.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ if (sa == PRI_READ_FULL_STATUS) {
+ pr_err("SPC-3 PR: PRI_READ_FULL_STATUS is not supported by PR passthrough.\n");
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ buf = transport_kmap_data_sg(cmd);
+ if (!buf)
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+ ret = ops->execute_pr_in(cmd, sa, buf);
+
+ transport_kunmap_data_sg(cmd);
+ return ret;
+}
+
sense_reason_t
target_scsi3_emulate_pr_in(struct se_cmd *cmd)
{
+ u8 sa = cmd->t_task_cdb[1] & 0x1f;
sense_reason_t ret;
/*
@@ -4060,7 +4131,12 @@ target_scsi3_emulate_pr_in(struct se_cmd *cmd)
return TCM_RESERVATION_CONFLICT;
}
- switch (cmd->t_task_cdb[1] & 0x1f) {
+ if (cmd->se_dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR) {
+ ret = target_try_pr_in_pt(cmd, sa);
+ goto done;
+ }
+
+ switch (sa) {
case PRI_READ_KEYS:
ret = core_scsi3_pri_read_keys(cmd);
break;
@@ -4079,6 +4155,7 @@ target_scsi3_emulate_pr_in(struct se_cmd *cmd)
return TCM_INVALID_CDB_FIELD;
}
+done:
if (!ret)
target_complete_cmd(cmd, SAM_STAT_GOOD);
return ret;
diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
index 6648c1c90e19..6f67cc09c2b5 100644
--- a/drivers/target/target_core_rd.c
+++ b/drivers/target/target_core_rd.c
@@ -643,14 +643,14 @@ static void rd_free_prot(struct se_device *dev)
rd_release_prot_space(rd_dev);
}
-static struct sbc_ops rd_sbc_ops = {
+static struct exec_cmd_ops rd_exec_cmd_ops = {
.execute_rw = rd_execute_rw,
};
static sense_reason_t
rd_parse_cdb(struct se_cmd *cmd)
{
- return sbc_parse_cdb(cmd, &rd_sbc_ops);
+ return sbc_parse_cdb(cmd, &rd_exec_cmd_ops);
}
static const struct target_backend_ops rd_mcp_ops = {
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 7536ca797606..6a02561cc20c 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -192,7 +192,7 @@ EXPORT_SYMBOL(sbc_get_write_same_sectors);
static sense_reason_t
sbc_execute_write_same_unmap(struct se_cmd *cmd)
{
- struct sbc_ops *ops = cmd->protocol_data;
+ struct exec_cmd_ops *ops = cmd->protocol_data;
sector_t nolb = sbc_get_write_same_sectors(cmd);
sense_reason_t ret;
@@ -271,7 +271,8 @@ static inline unsigned long long transport_lba_64(unsigned char *cdb)
}
static sense_reason_t
-sbc_setup_write_same(struct se_cmd *cmd, unsigned char flags, struct sbc_ops *ops)
+sbc_setup_write_same(struct se_cmd *cmd, unsigned char flags,
+ struct exec_cmd_ops *ops)
{
struct se_device *dev = cmd->se_dev;
sector_t end_lba = dev->transport->get_blocks(dev) + 1;
@@ -340,7 +341,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char flags, struct sbc_ops *op
static sense_reason_t
sbc_execute_rw(struct se_cmd *cmd)
{
- struct sbc_ops *ops = cmd->protocol_data;
+ struct exec_cmd_ops *ops = cmd->protocol_data;
return ops->execute_rw(cmd, cmd->t_data_sg, cmd->t_data_nents,
cmd->data_direction);
@@ -566,7 +567,7 @@ out:
static sense_reason_t
sbc_compare_and_write(struct se_cmd *cmd)
{
- struct sbc_ops *ops = cmd->protocol_data;
+ struct exec_cmd_ops *ops = cmd->protocol_data;
struct se_device *dev = cmd->se_dev;
sense_reason_t ret;
int rc;
@@ -764,7 +765,7 @@ sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
}
sense_reason_t
-sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
+sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops)
{
struct se_device *dev = cmd->se_dev;
unsigned char *cdb = cmd->t_task_cdb;
@@ -1076,7 +1077,7 @@ EXPORT_SYMBOL(sbc_get_device_type);
static sense_reason_t
sbc_execute_unmap(struct se_cmd *cmd)
{
- struct sbc_ops *ops = cmd->protocol_data;
+ struct exec_cmd_ops *ops = cmd->protocol_data;
struct se_device *dev = cmd->se_dev;
unsigned char *buf, *ptr = NULL;
sector_t lba;
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 89c0d56294cc..50290abc07bc 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -1424,9 +1424,10 @@ static struct target_opcode_descriptor tcm_opcode_write_verify16 = {
.update_usage_bits = set_dpofua_usage_bits,
};
-static bool tcm_is_ws_enabled(struct se_cmd *cmd)
+static bool tcm_is_ws_enabled(struct target_opcode_descriptor *descr,
+ struct se_cmd *cmd)
{
- struct sbc_ops *ops = cmd->protocol_data;
+ struct exec_cmd_ops *ops = cmd->protocol_data;
struct se_device *dev = cmd->se_dev;
return (dev->dev_attrib.emulate_tpws && !!ops->execute_unmap) ||
@@ -1451,7 +1452,8 @@ static struct target_opcode_descriptor tcm_opcode_write_same32 = {
.update_usage_bits = set_dpofua_usage_bits32,
};
-static bool tcm_is_caw_enabled(struct se_cmd *cmd)
+static bool tcm_is_caw_enabled(struct target_opcode_descriptor *descr,
+ struct se_cmd *cmd)
{
struct se_device *dev = cmd->se_dev;
@@ -1491,7 +1493,8 @@ static struct target_opcode_descriptor tcm_opcode_read_capacity16 = {
0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
};
-static bool tcm_is_rep_ref_enabled(struct se_cmd *cmd)
+static bool tcm_is_rep_ref_enabled(struct target_opcode_descriptor *descr,
+ struct se_cmd *cmd)
{
struct se_device *dev = cmd->se_dev;
@@ -1502,7 +1505,6 @@ static bool tcm_is_rep_ref_enabled(struct se_cmd *cmd)
}
spin_unlock(&dev->t10_alua.lba_map_lock);
return true;
-
}
static struct target_opcode_descriptor tcm_opcode_read_report_refferals = {
@@ -1537,9 +1539,10 @@ static struct target_opcode_descriptor tcm_opcode_sync_cache16 = {
0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
};
-static bool tcm_is_unmap_enabled(struct se_cmd *cmd)
+static bool tcm_is_unmap_enabled(struct target_opcode_descriptor *descr,
+ struct se_cmd *cmd)
{
- struct sbc_ops *ops = cmd->protocol_data;
+ struct exec_cmd_ops *ops = cmd->protocol_data;
struct se_device *dev = cmd->se_dev;
return ops->execute_unmap && dev->dev_attrib.emulate_tpu;
@@ -1659,11 +1662,46 @@ static struct target_opcode_descriptor tcm_opcode_pri_read_resrv = {
0xff, SCSI_CONTROL_MASK},
};
-static bool tcm_is_pr_enabled(struct se_cmd *cmd)
+static bool tcm_is_pr_enabled(struct target_opcode_descriptor *descr,
+ struct se_cmd *cmd)
{
struct se_device *dev = cmd->se_dev;
- return dev->dev_attrib.emulate_pr;
+ if (!dev->dev_attrib.emulate_pr)
+ return false;
+
+ if (!(dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR))
+ return true;
+
+ switch (descr->opcode) {
+ case RESERVE:
+ case RESERVE_10:
+ case RELEASE:
+ case RELEASE_10:
+ /*
+ * The pr_ops which are used by the backend modules don't
+ * support these commands.
+ */
+ return false;
+ case PERSISTENT_RESERVE_OUT:
+ switch (descr->service_action) {
+ case PRO_REGISTER_AND_MOVE:
+ case PRO_REPLACE_LOST_RESERVATION:
+ /*
+ * The backend modules don't have access to ports and
+ * I_T nexuses so they can't handle these type of
+ * requests.
+ */
+ return false;
+ }
+ break;
+ case PERSISTENT_RESERVE_IN:
+ if (descr->service_action == PRI_READ_FULL_STATUS)
+ return false;
+ break;
+ }
+
+ return true;
}
static struct target_opcode_descriptor tcm_opcode_pri_read_caps = {
@@ -1788,20 +1826,13 @@ static struct target_opcode_descriptor tcm_opcode_pro_register_move = {
.enabled = tcm_is_pr_enabled,
};
-static bool tcm_is_scsi2_reservations_enabled(struct se_cmd *cmd)
-{
- struct se_device *dev = cmd->se_dev;
-
- return dev->dev_attrib.emulate_pr;
-}
-
static struct target_opcode_descriptor tcm_opcode_release = {
.support = SCSI_SUPPORT_FULL,
.opcode = RELEASE,
.cdb_size = 6,
.usage_bits = {RELEASE, 0x00, 0x00, 0x00,
0x00, SCSI_CONTROL_MASK},
- .enabled = tcm_is_scsi2_reservations_enabled,
+ .enabled = tcm_is_pr_enabled,
};
static struct target_opcode_descriptor tcm_opcode_release10 = {
@@ -1811,7 +1842,7 @@ static struct target_opcode_descriptor tcm_opcode_release10 = {
.usage_bits = {RELEASE_10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff,
0xff, SCSI_CONTROL_MASK},
- .enabled = tcm_is_scsi2_reservations_enabled,
+ .enabled = tcm_is_pr_enabled,
};
static struct target_opcode_descriptor tcm_opcode_reserve = {
@@ -1820,7 +1851,7 @@ static struct target_opcode_descriptor tcm_opcode_reserve = {
.cdb_size = 6,
.usage_bits = {RESERVE, 0x00, 0x00, 0x00,
0x00, SCSI_CONTROL_MASK},
- .enabled = tcm_is_scsi2_reservations_enabled,
+ .enabled = tcm_is_pr_enabled,
};
static struct target_opcode_descriptor tcm_opcode_reserve10 = {
@@ -1830,7 +1861,7 @@ static struct target_opcode_descriptor tcm_opcode_reserve10 = {
.usage_bits = {RESERVE_10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff,
0xff, SCSI_CONTROL_MASK},
- .enabled = tcm_is_scsi2_reservations_enabled,
+ .enabled = tcm_is_pr_enabled,
};
static struct target_opcode_descriptor tcm_opcode_request_sense = {
@@ -1849,7 +1880,8 @@ static struct target_opcode_descriptor tcm_opcode_inquiry = {
0xff, SCSI_CONTROL_MASK},
};
-static bool tcm_is_3pc_enabled(struct se_cmd *cmd)
+static bool tcm_is_3pc_enabled(struct target_opcode_descriptor *descr,
+ struct se_cmd *cmd)
{
struct se_device *dev = cmd->se_dev;
@@ -1910,8 +1942,8 @@ static struct target_opcode_descriptor tcm_opcode_report_target_pgs = {
0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
};
-
-static bool spc_rsoc_enabled(struct se_cmd *cmd)
+static bool spc_rsoc_enabled(struct target_opcode_descriptor *descr,
+ struct se_cmd *cmd)
{
struct se_device *dev = cmd->se_dev;
@@ -1931,7 +1963,8 @@ static struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = {
.enabled = spc_rsoc_enabled,
};
-static bool tcm_is_set_tpg_enabled(struct se_cmd *cmd)
+static bool tcm_is_set_tpg_enabled(struct target_opcode_descriptor *descr,
+ struct se_cmd *cmd)
{
struct t10_alua_tg_pt_gp *l_tg_pt_gp;
struct se_lun *l_lun = cmd->se_lun;
@@ -2118,7 +2151,7 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode)
if (descr->serv_action_valid)
return TCM_INVALID_CDB_FIELD;
- if (!descr->enabled || descr->enabled(cmd))
+ if (!descr->enabled || descr->enabled(descr, cmd))
*opcode = descr;
break;
case 0x2:
@@ -2132,7 +2165,8 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode)
*/
if (descr->serv_action_valid &&
descr->service_action == requested_sa) {
- if (!descr->enabled || descr->enabled(cmd))
+ if (!descr->enabled || descr->enabled(descr,
+ cmd))
*opcode = descr;
} else if (!descr->serv_action_valid)
return TCM_INVALID_CDB_FIELD;
@@ -2145,7 +2179,8 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode)
* be returned in the one_command parameter data format.
*/
if (descr->service_action == requested_sa)
- if (!descr->enabled || descr->enabled(cmd))
+ if (!descr->enabled || descr->enabled(descr,
+ cmd))
*opcode = descr;
break;
}
@@ -2202,7 +2237,7 @@ spc_emulate_report_supp_op_codes(struct se_cmd *cmd)
for (i = 0; i < ARRAY_SIZE(tcm_supported_opcodes); i++) {
descr = tcm_supported_opcodes[i];
- if (descr->enabled && !descr->enabled(cmd))
+ if (descr->enabled && !descr->enabled(descr, cmd))
continue;
response_length += spc_rsoc_encode_command_descriptor(
@@ -2231,12 +2266,22 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
struct se_device *dev = cmd->se_dev;
unsigned char *cdb = cmd->t_task_cdb;
- if (!dev->dev_attrib.emulate_pr &&
- ((cdb[0] == PERSISTENT_RESERVE_IN) ||
- (cdb[0] == PERSISTENT_RESERVE_OUT) ||
- (cdb[0] == RELEASE || cdb[0] == RELEASE_10) ||
- (cdb[0] == RESERVE || cdb[0] == RESERVE_10))) {
- return TCM_UNSUPPORTED_SCSI_OPCODE;
+ switch (cdb[0]) {
+ case RESERVE:
+ case RESERVE_10:
+ case RELEASE:
+ case RELEASE_10:
+ if (!dev->dev_attrib.emulate_pr)
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+
+ if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ break;
+ case PERSISTENT_RESERVE_IN:
+ case PERSISTENT_RESERVE_OUT:
+ if (!dev->dev_attrib.emulate_pr)
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ break;
}
switch (cdb[0]) {
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index 3861ae06d902..d5b28fd35d66 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -1541,12 +1541,11 @@ static int optee_load_fw(struct platform_device *pdev,
* This uses the GFP_DMA flag to ensure we are allocated memory in the
* 32-bit space since TF-A cannot map memory beyond the 32-bit boundary.
*/
- data_buf = kmalloc(fw->size, GFP_KERNEL | GFP_DMA);
+ data_buf = kmemdup(fw->data, fw->size, GFP_KERNEL | GFP_DMA);
if (!data_buf) {
rc = -ENOMEM;
goto fw_err;
}
- memcpy(data_buf, fw->data, fw->size);
data_pa = virt_to_phys(data_buf);
reg_pair_from_64(&data_pa_high, &data_pa_low, data_pa);
reg_pair_from_64(&data_size_high, &data_size_low, data_size);
diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile
index 78fd365893c1..c8b3d7b78098 100644
--- a/drivers/thunderbolt/Makefile
+++ b/drivers/thunderbolt/Makefile
@@ -2,7 +2,7 @@
obj-${CONFIG_USB4} := thunderbolt.o
thunderbolt-objs := nhi.o nhi_ops.o ctl.o tb.o switch.o cap.o path.o tunnel.o eeprom.o
thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o lc.o tmu.o usb4.o
-thunderbolt-objs += usb4_port.o nvm.o retimer.o quirks.o
+thunderbolt-objs += usb4_port.o nvm.o retimer.o quirks.o clx.o
thunderbolt-${CONFIG_ACPI} += acpi.o
thunderbolt-$(CONFIG_DEBUG_FS) += debugfs.o
diff --git a/drivers/thunderbolt/acpi.c b/drivers/thunderbolt/acpi.c
index 3514bf65b7a4..38fefd0e5268 100644
--- a/drivers/thunderbolt/acpi.c
+++ b/drivers/thunderbolt/acpi.c
@@ -296,16 +296,15 @@ static bool tb_acpi_bus_match(struct device *dev)
static struct acpi_device *tb_acpi_switch_find_companion(struct tb_switch *sw)
{
+ struct tb_switch *parent_sw = tb_switch_parent(sw);
struct acpi_device *adev = NULL;
- struct tb_switch *parent_sw;
/*
* Device routers exists under the downstream facing USB4 port
* of the parent router. Their _ADR is always 0.
*/
- parent_sw = tb_switch_parent(sw);
if (parent_sw) {
- struct tb_port *port = tb_port_at(tb_route(sw), parent_sw);
+ struct tb_port *port = tb_switch_downstream_port(sw);
struct acpi_device *port_adev;
port_adev = acpi_find_child_by_adr(ACPI_COMPANION(&parent_sw->dev),
diff --git a/drivers/thunderbolt/clx.c b/drivers/thunderbolt/clx.c
new file mode 100644
index 000000000000..13d217ae98e6
--- /dev/null
+++ b/drivers/thunderbolt/clx.c
@@ -0,0 +1,423 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CLx support
+ *
+ * Copyright (C) 2020 - 2023, Intel Corporation
+ * Authors: Gil Fine <gil.fine@intel.com>
+ * Mika Westerberg <mika.westerberg@linux.intel.com>
+ */
+
+#include <linux/module.h>
+
+#include "tb.h"
+
+static bool clx_enabled = true;
+module_param_named(clx, clx_enabled, bool, 0444);
+MODULE_PARM_DESC(clx, "allow low power states on the high-speed lanes (default: true)");
+
+static const char *clx_name(unsigned int clx)
+{
+ switch (clx) {
+ case TB_CL0S | TB_CL1 | TB_CL2:
+ return "CL0s/CL1/CL2";
+ case TB_CL1 | TB_CL2:
+ return "CL1/CL2";
+ case TB_CL0S | TB_CL2:
+ return "CL0s/CL2";
+ case TB_CL0S | TB_CL1:
+ return "CL0s/CL1";
+ case TB_CL0S:
+ return "CL0s";
+ case 0:
+ return "disabled";
+ default:
+ return "unknown";
+ }
+}
+
+static int tb_port_pm_secondary_set(struct tb_port *port, bool secondary)
+{
+ u32 phy;
+ int ret;
+
+ ret = tb_port_read(port, &phy, TB_CFG_PORT,
+ port->cap_phy + LANE_ADP_CS_1, 1);
+ if (ret)
+ return ret;
+
+ if (secondary)
+ phy |= LANE_ADP_CS_1_PMS;
+ else
+ phy &= ~LANE_ADP_CS_1_PMS;
+
+ return tb_port_write(port, &phy, TB_CFG_PORT,
+ port->cap_phy + LANE_ADP_CS_1, 1);
+}
+
+static int tb_port_pm_secondary_enable(struct tb_port *port)
+{
+ return tb_port_pm_secondary_set(port, true);
+}
+
+static int tb_port_pm_secondary_disable(struct tb_port *port)
+{
+ return tb_port_pm_secondary_set(port, false);
+}
+
+/* Called for USB4 or Titan Ridge routers only */
+static bool tb_port_clx_supported(struct tb_port *port, unsigned int clx)
+{
+ u32 val, mask = 0;
+ bool ret;
+
+ /* Don't enable CLx in case of two single-lane links */
+ if (!port->bonded && port->dual_link_port)
+ return false;
+
+ /* Don't enable CLx in case of inter-domain link */
+ if (port->xdomain)
+ return false;
+
+ if (tb_switch_is_usb4(port->sw)) {
+ if (!usb4_port_clx_supported(port))
+ return false;
+ } else if (!tb_lc_is_clx_supported(port)) {
+ return false;
+ }
+
+ if (clx & TB_CL0S)
+ mask |= LANE_ADP_CS_0_CL0S_SUPPORT;
+ if (clx & TB_CL1)
+ mask |= LANE_ADP_CS_0_CL1_SUPPORT;
+ if (clx & TB_CL2)
+ mask |= LANE_ADP_CS_0_CL2_SUPPORT;
+
+ ret = tb_port_read(port, &val, TB_CFG_PORT,
+ port->cap_phy + LANE_ADP_CS_0, 1);
+ if (ret)
+ return false;
+
+ return !!(val & mask);
+}
+
+static int tb_port_clx_set(struct tb_port *port, unsigned int clx, bool enable)
+{
+ u32 phy, mask = 0;
+ int ret;
+
+ if (clx & TB_CL0S)
+ mask |= LANE_ADP_CS_1_CL0S_ENABLE;
+ if (clx & TB_CL1)
+ mask |= LANE_ADP_CS_1_CL1_ENABLE;
+ if (clx & TB_CL2)
+ mask |= LANE_ADP_CS_1_CL2_ENABLE;
+
+ if (!mask)
+ return -EOPNOTSUPP;
+
+ ret = tb_port_read(port, &phy, TB_CFG_PORT,
+ port->cap_phy + LANE_ADP_CS_1, 1);
+ if (ret)
+ return ret;
+
+ if (enable)
+ phy |= mask;
+ else
+ phy &= ~mask;
+
+ return tb_port_write(port, &phy, TB_CFG_PORT,
+ port->cap_phy + LANE_ADP_CS_1, 1);
+}
+
+static int tb_port_clx_disable(struct tb_port *port, unsigned int clx)
+{
+ return tb_port_clx_set(port, clx, false);
+}
+
+static int tb_port_clx_enable(struct tb_port *port, unsigned int clx)
+{
+ return tb_port_clx_set(port, clx, true);
+}
+
+static int tb_port_clx(struct tb_port *port)
+{
+ u32 val;
+ int ret;
+
+ if (!tb_port_clx_supported(port, TB_CL0S | TB_CL1 | TB_CL2))
+ return 0;
+
+ ret = tb_port_read(port, &val, TB_CFG_PORT,
+ port->cap_phy + LANE_ADP_CS_1, 1);
+ if (ret)
+ return ret;
+
+ if (val & LANE_ADP_CS_1_CL0S_ENABLE)
+ ret |= TB_CL0S;
+ if (val & LANE_ADP_CS_1_CL1_ENABLE)
+ ret |= TB_CL1;
+ if (val & LANE_ADP_CS_1_CL2_ENABLE)
+ ret |= TB_CL2;
+
+ return ret;
+}
+
+/**
+ * tb_port_clx_is_enabled() - Is given CL state enabled
+ * @port: USB4 port to check
+ * @clx: Mask of CL states to check
+ *
+ * Returns true if any of the given CL states is enabled for @port.
+ */
+bool tb_port_clx_is_enabled(struct tb_port *port, unsigned int clx)
+{
+ return !!(tb_port_clx(port) & clx);
+}
+
+/**
+ * tb_switch_clx_init() - Initialize router CL states
+ * @sw: Router
+ *
+ * Can be called for any router. Initializes the current CL state by
+ * reading it from the hardware.
+ *
+ * Returns %0 in case of success and negative errno in case of failure.
+ */
+int tb_switch_clx_init(struct tb_switch *sw)
+{
+ struct tb_port *up, *down;
+ unsigned int clx, tmp;
+
+ if (tb_switch_is_icm(sw))
+ return 0;
+
+ if (!tb_route(sw))
+ return 0;
+
+ if (!tb_switch_clx_is_supported(sw))
+ return 0;
+
+ up = tb_upstream_port(sw);
+ down = tb_switch_downstream_port(sw);
+
+ clx = tb_port_clx(up);
+ tmp = tb_port_clx(down);
+ if (clx != tmp)
+ tb_sw_warn(sw, "CLx: inconsistent configuration %#x != %#x\n",
+ clx, tmp);
+
+ tb_sw_dbg(sw, "CLx: current mode: %s\n", clx_name(clx));
+
+ sw->clx = clx;
+ return 0;
+}
+
+static int tb_switch_pm_secondary_resolve(struct tb_switch *sw)
+{
+ struct tb_port *up, *down;
+ int ret;
+
+ if (!tb_route(sw))
+ return 0;
+
+ up = tb_upstream_port(sw);
+ down = tb_switch_downstream_port(sw);
+ ret = tb_port_pm_secondary_enable(up);
+ if (ret)
+ return ret;
+
+ return tb_port_pm_secondary_disable(down);
+}
+
+static int tb_switch_mask_clx_objections(struct tb_switch *sw)
+{
+ int up_port = sw->config.upstream_port_number;
+ u32 offset, val[2], mask_obj, unmask_obj;
+ int ret, i;
+
+ /* Only Titan Ridge of pre-USB4 devices support CLx states */
+ if (!tb_switch_is_titan_ridge(sw))
+ return 0;
+
+ if (!tb_route(sw))
+ return 0;
+
+ /*
+ * In Titan Ridge there are only 2 dual-lane Thunderbolt ports:
+ * Port A consists of lane adapters 1,2 and
+ * Port B consists of lane adapters 3,4
+ * If upstream port is A, (lanes are 1,2), we mask objections from
+ * port B (lanes 3,4) and unmask objections from Port A and vice-versa.
+ */
+ if (up_port == 1) {
+ mask_obj = TB_LOW_PWR_C0_PORT_B_MASK;
+ unmask_obj = TB_LOW_PWR_C1_PORT_A_MASK;
+ offset = TB_LOW_PWR_C1_CL1;
+ } else {
+ mask_obj = TB_LOW_PWR_C1_PORT_A_MASK;
+ unmask_obj = TB_LOW_PWR_C0_PORT_B_MASK;
+ offset = TB_LOW_PWR_C3_CL1;
+ }
+
+ ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
+ sw->cap_lp + offset, ARRAY_SIZE(val));
+ if (ret)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(val); i++) {
+ val[i] |= mask_obj;
+ val[i] &= ~unmask_obj;
+ }
+
+ return tb_sw_write(sw, &val, TB_CFG_SWITCH,
+ sw->cap_lp + offset, ARRAY_SIZE(val));
+}
+
+/**
+ * tb_switch_clx_is_supported() - Is CLx supported on this type of router
+ * @sw: The router to check CLx support for
+ */
+bool tb_switch_clx_is_supported(const struct tb_switch *sw)
+{
+ if (!clx_enabled)
+ return false;
+
+ if (sw->quirks & QUIRK_NO_CLX)
+ return false;
+
+ /*
+ * CLx is not enabled and validated on Intel USB4 platforms
+ * before Alder Lake.
+ */
+ if (tb_switch_is_tiger_lake(sw))
+ return false;
+
+ return tb_switch_is_usb4(sw) || tb_switch_is_titan_ridge(sw);
+}
+
+static bool validate_mask(unsigned int clx)
+{
+ /* Previous states need to be enabled */
+ if (clx & TB_CL1)
+ return (clx & TB_CL0S) == TB_CL0S;
+ return true;
+}
+
+/**
+ * tb_switch_clx_enable() - Enable CLx on upstream port of specified router
+ * @sw: Router to enable CLx for
+ * @clx: The CLx state to enable
+ *
+ * CLx is enabled only if both sides of the link support CLx, and if both sides
+ * of the link are not configured as two single lane links and only if the link
+ * is not inter-domain link. The complete set of conditions is described in CM
+ * Guide 1.0 section 8.1.
+ *
+ * Returns %0 on success or an error code on failure.
+ */
+int tb_switch_clx_enable(struct tb_switch *sw, unsigned int clx)
+{
+ bool up_clx_support, down_clx_support;
+ struct tb_switch *parent_sw;
+ struct tb_port *up, *down;
+ int ret;
+
+ if (!clx || sw->clx == clx)
+ return 0;
+
+ if (!validate_mask(clx))
+ return -EINVAL;
+
+ parent_sw = tb_switch_parent(sw);
+ if (!parent_sw)
+ return 0;
+
+ if (!tb_switch_clx_is_supported(parent_sw) ||
+ !tb_switch_clx_is_supported(sw))
+ return 0;
+
+ /* Only support CL2 for v2 routers */
+ if ((clx & TB_CL2) &&
+ (usb4_switch_version(parent_sw) < 2 ||
+ usb4_switch_version(sw) < 2))
+ return -EOPNOTSUPP;
+
+ ret = tb_switch_pm_secondary_resolve(sw);
+ if (ret)
+ return ret;
+
+ up = tb_upstream_port(sw);
+ down = tb_switch_downstream_port(sw);
+
+ up_clx_support = tb_port_clx_supported(up, clx);
+ down_clx_support = tb_port_clx_supported(down, clx);
+
+ tb_port_dbg(up, "CLx: %s %ssupported\n", clx_name(clx),
+ up_clx_support ? "" : "not ");
+ tb_port_dbg(down, "CLx: %s %ssupported\n", clx_name(clx),
+ down_clx_support ? "" : "not ");
+
+ if (!up_clx_support || !down_clx_support)
+ return -EOPNOTSUPP;
+
+ ret = tb_port_clx_enable(up, clx);
+ if (ret)
+ return ret;
+
+ ret = tb_port_clx_enable(down, clx);
+ if (ret) {
+ tb_port_clx_disable(up, clx);
+ return ret;
+ }
+
+ ret = tb_switch_mask_clx_objections(sw);
+ if (ret) {
+ tb_port_clx_disable(up, clx);
+ tb_port_clx_disable(down, clx);
+ return ret;
+ }
+
+ sw->clx |= clx;
+
+ tb_sw_dbg(sw, "CLx: %s enabled\n", clx_name(clx));
+ return 0;
+}
+
+/**
+ * tb_switch_clx_disable() - Disable CLx on upstream port of specified router
+ * @sw: Router to disable CLx for
+ *
+ * Disables all CL states of the given router. Can be called on any
+ * router and if the states were not enabled already does nothing.
+ *
+ * Returns the CL states that were disabled or negative errno in case of
+ * failure.
+ */
+int tb_switch_clx_disable(struct tb_switch *sw)
+{
+ unsigned int clx = sw->clx;
+ struct tb_port *up, *down;
+ int ret;
+
+ if (!tb_switch_clx_is_supported(sw))
+ return 0;
+
+ if (!clx)
+ return 0;
+
+ up = tb_upstream_port(sw);
+ down = tb_switch_downstream_port(sw);
+
+ ret = tb_port_clx_disable(up, clx);
+ if (ret)
+ return ret;
+
+ ret = tb_port_clx_disable(down, clx);
+ if (ret)
+ return ret;
+
+ sw->clx = 0;
+
+ tb_sw_dbg(sw, "CLx: %s disabled\n", clx_name(clx));
+ return clx;
+}
diff --git a/drivers/thunderbolt/ctl.c b/drivers/thunderbolt/ctl.c
index 3a213322ec7a..d997a4c545f7 100644
--- a/drivers/thunderbolt/ctl.c
+++ b/drivers/thunderbolt/ctl.c
@@ -409,6 +409,13 @@ static int tb_async_error(const struct ctl_pkg *pkg)
case TB_CFG_ERROR_HEC_ERROR_DETECTED:
case TB_CFG_ERROR_FLOW_CONTROL_ERROR:
case TB_CFG_ERROR_DP_BW:
+ case TB_CFG_ERROR_ROP_CMPLT:
+ case TB_CFG_ERROR_POP_CMPLT:
+ case TB_CFG_ERROR_PCIE_WAKE:
+ case TB_CFG_ERROR_DP_CON_CHANGE:
+ case TB_CFG_ERROR_DPTX_DISCOVERY:
+ case TB_CFG_ERROR_LINK_RECOVERY:
+ case TB_CFG_ERROR_ASYM_LINK:
return true;
default:
@@ -758,6 +765,27 @@ int tb_cfg_ack_notification(struct tb_ctl *ctl, u64 route,
case TB_CFG_ERROR_DP_BW:
name = "DP_BW";
break;
+ case TB_CFG_ERROR_ROP_CMPLT:
+ name = "router operation completion";
+ break;
+ case TB_CFG_ERROR_POP_CMPLT:
+ name = "port operation completion";
+ break;
+ case TB_CFG_ERROR_PCIE_WAKE:
+ name = "PCIe wake";
+ break;
+ case TB_CFG_ERROR_DP_CON_CHANGE:
+ name = "DP connector change";
+ break;
+ case TB_CFG_ERROR_DPTX_DISCOVERY:
+ name = "DPTX discovery";
+ break;
+ case TB_CFG_ERROR_LINK_RECOVERY:
+ name = "link recovery";
+ break;
+ case TB_CFG_ERROR_ASYM_LINK:
+ name = "asymmetric link";
+ break;
default:
name = "unknown";
break;
diff --git a/drivers/thunderbolt/debugfs.c b/drivers/thunderbolt/debugfs.c
index f92ad71ef983..c9ddd49138d8 100644
--- a/drivers/thunderbolt/debugfs.c
+++ b/drivers/thunderbolt/debugfs.c
@@ -14,12 +14,15 @@
#include "tb.h"
#include "sb_regs.h"
-#define PORT_CAP_PCIE_LEN 1
+#define PORT_CAP_V1_PCIE_LEN 1
+#define PORT_CAP_V2_PCIE_LEN 2
#define PORT_CAP_POWER_LEN 2
#define PORT_CAP_LANE_LEN 3
#define PORT_CAP_USB3_LEN 5
-#define PORT_CAP_DP_LEN 8
-#define PORT_CAP_TMU_LEN 8
+#define PORT_CAP_DP_V1_LEN 9
+#define PORT_CAP_DP_V2_LEN 14
+#define PORT_CAP_TMU_V1_LEN 8
+#define PORT_CAP_TMU_V2_LEN 10
#define PORT_CAP_BASIC_LEN 9
#define PORT_CAP_USB4_LEN 20
@@ -553,8 +556,9 @@ static int margining_run_write(void *data, u64 val)
struct usb4_port *usb4 = port->usb4;
struct tb_switch *sw = port->sw;
struct tb_margining *margining;
+ struct tb_switch *down_sw;
struct tb *tb = sw->tb;
- int ret;
+ int ret, clx;
if (val != 1)
return -EINVAL;
@@ -566,15 +570,24 @@ static int margining_run_write(void *data, u64 val)
goto out_rpm_put;
}
- /*
- * CL states may interfere with lane margining so inform the user know
- * and bail out.
- */
- if (tb_port_is_clx_enabled(port, TB_CL1 | TB_CL2)) {
- tb_port_warn(port,
- "CL states are enabled, Disable them with clx=0 and re-connect\n");
- ret = -EINVAL;
- goto out_unlock;
+ if (tb_is_upstream_port(port))
+ down_sw = sw;
+ else if (port->remote)
+ down_sw = port->remote->sw;
+ else
+ down_sw = NULL;
+
+ if (down_sw) {
+ /*
+ * CL states may interfere with lane margining so
+ * disable them temporarily now.
+ */
+ ret = tb_switch_clx_disable(down_sw);
+ if (ret < 0) {
+ tb_sw_warn(down_sw, "failed to disable CL states\n");
+ goto out_unlock;
+ }
+ clx = ret;
}
margining = usb4->margining;
@@ -586,7 +599,7 @@ static int margining_run_write(void *data, u64 val)
margining->right_high,
USB4_MARGIN_SW_COUNTER_CLEAR);
if (ret)
- goto out_unlock;
+ goto out_clx;
ret = usb4_port_sw_margin_errors(port, &margining->results[0]);
} else {
@@ -600,6 +613,9 @@ static int margining_run_write(void *data, u64 val)
margining->right_high, margining->results);
}
+out_clx:
+ if (down_sw)
+ tb_switch_clx_enable(down_sw, clx);
out_unlock:
mutex_unlock(&tb->lock);
out_rpm_put:
@@ -1148,7 +1164,10 @@ static void port_cap_show(struct tb_port *port, struct seq_file *s,
break;
case TB_PORT_CAP_TIME1:
- length = PORT_CAP_TMU_LEN;
+ if (usb4_switch_version(port->sw) < 2)
+ length = PORT_CAP_TMU_V1_LEN;
+ else
+ length = PORT_CAP_TMU_V2_LEN;
break;
case TB_PORT_CAP_POWER:
@@ -1157,12 +1176,17 @@ static void port_cap_show(struct tb_port *port, struct seq_file *s,
case TB_PORT_CAP_ADAP:
if (tb_port_is_pcie_down(port) || tb_port_is_pcie_up(port)) {
- length = PORT_CAP_PCIE_LEN;
- } else if (tb_port_is_dpin(port) || tb_port_is_dpout(port)) {
- if (usb4_dp_port_bw_mode_supported(port))
- length = PORT_CAP_DP_LEN + 1;
+ if (usb4_switch_version(port->sw) < 2)
+ length = PORT_CAP_V1_PCIE_LEN;
+ else
+ length = PORT_CAP_V2_PCIE_LEN;
+ } else if (tb_port_is_dpin(port)) {
+ if (usb4_switch_version(port->sw) < 2)
+ length = PORT_CAP_DP_V1_LEN;
else
- length = PORT_CAP_DP_LEN;
+ length = PORT_CAP_DP_V2_LEN;
+ } else if (tb_port_is_dpout(port)) {
+ length = PORT_CAP_DP_V1_LEN;
} else if (tb_port_is_usb3_down(port) ||
tb_port_is_usb3_up(port)) {
length = PORT_CAP_USB3_LEN;
diff --git a/drivers/thunderbolt/dma_test.c b/drivers/thunderbolt/dma_test.c
index 14bb6dec6c4b..39476fc48801 100644
--- a/drivers/thunderbolt/dma_test.c
+++ b/drivers/thunderbolt/dma_test.c
@@ -412,6 +412,7 @@ static void speed_get(const struct dma_test *dt, u64 *val)
static int speed_validate(u64 val)
{
switch (val) {
+ case 40:
case 20:
case 10:
case 0:
@@ -489,9 +490,12 @@ static void dma_test_check_errors(struct dma_test *dt, int ret)
if (!dt->error_code) {
if (dt->link_speed && dt->xd->link_speed != dt->link_speed) {
dt->error_code = DMA_TEST_SPEED_ERROR;
- } else if (dt->link_width &&
- dt->xd->link_width != dt->link_width) {
- dt->error_code = DMA_TEST_WIDTH_ERROR;
+ } else if (dt->link_width) {
+ const struct tb_xdomain *xd = dt->xd;
+
+ if ((dt->link_width == 1 && xd->link_width != TB_LINK_WIDTH_SINGLE) ||
+ (dt->link_width == 2 && xd->link_width < TB_LINK_WIDTH_DUAL))
+ dt->error_code = DMA_TEST_WIDTH_ERROR;
} else if (dt->packets_to_send != dt->packets_sent ||
dt->packets_to_receive != dt->packets_received ||
dt->crc_errors || dt->buffer_overflow_errors) {
@@ -756,5 +760,5 @@ module_exit(dma_test_exit);
MODULE_AUTHOR("Isaac Hazan <isaac.hazan@intel.com>");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
-MODULE_DESCRIPTION("DMA traffic test driver");
+MODULE_DESCRIPTION("Thunderbolt/USB4 DMA traffic test driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index 0f6099c18a94..eb241b270f79 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -605,9 +605,8 @@ static int usb4_drom_parse(struct tb_switch *sw)
crc = tb_crc32(sw->drom + TB_DROM_DATA_START, header->data_len);
if (crc != header->data_crc32) {
tb_sw_warn(sw,
- "DROM data CRC32 mismatch (expected: %#x, got: %#x), aborting\n",
+ "DROM data CRC32 mismatch (expected: %#x, got: %#x), continuing\n",
header->data_crc32, crc);
- return -EINVAL;
}
return tb_drom_parse_entries(sw, USB4_DROM_HEADER_SIZE);
diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c
index 86521ebb2579..dbdcad8d73bf 100644
--- a/drivers/thunderbolt/icm.c
+++ b/drivers/thunderbolt/icm.c
@@ -644,13 +644,14 @@ static int add_switch(struct tb_switch *parent_sw, struct tb_switch *sw)
return ret;
}
-static void update_switch(struct tb_switch *parent_sw, struct tb_switch *sw,
- u64 route, u8 connection_id, u8 connection_key,
- u8 link, u8 depth, bool boot)
+static void update_switch(struct tb_switch *sw, u64 route, u8 connection_id,
+ u8 connection_key, u8 link, u8 depth, bool boot)
{
+ struct tb_switch *parent_sw = tb_switch_parent(sw);
+
/* Disconnect from parent */
- tb_port_at(tb_route(sw), parent_sw)->remote = NULL;
- /* Re-connect via updated port*/
+ tb_switch_downstream_port(sw)->remote = NULL;
+ /* Re-connect via updated port */
tb_port_at(route, parent_sw)->remote = tb_upstream_port(sw);
/* Update with the new addressing information */
@@ -671,10 +672,7 @@ static void update_switch(struct tb_switch *parent_sw, struct tb_switch *sw,
static void remove_switch(struct tb_switch *sw)
{
- struct tb_switch *parent_sw;
-
- parent_sw = tb_to_switch(sw->dev.parent);
- tb_port_at(tb_route(sw), parent_sw)->remote = NULL;
+ tb_switch_downstream_port(sw)->remote = NULL;
tb_switch_remove(sw);
}
@@ -755,7 +753,6 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr)
if (sw) {
u8 phy_port, sw_phy_port;
- parent_sw = tb_to_switch(sw->dev.parent);
sw_phy_port = tb_phy_port_from_link(sw->link);
phy_port = tb_phy_port_from_link(link);
@@ -785,7 +782,7 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr)
route = tb_route(sw);
}
- update_switch(parent_sw, sw, route, pkg->connection_id,
+ update_switch(sw, route, pkg->connection_id,
pkg->connection_key, link, depth, boot);
tb_switch_put(sw);
return;
@@ -853,7 +850,8 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr)
sw->security_level = security_level;
sw->boot = boot;
sw->link_speed = speed_gen3 ? 20 : 10;
- sw->link_width = dual_lane ? 2 : 1;
+ sw->link_width = dual_lane ? TB_LINK_WIDTH_DUAL :
+ TB_LINK_WIDTH_SINGLE;
sw->rpm = intel_vss_is_rtd3(pkg->ep_name, sizeof(pkg->ep_name));
if (add_switch(parent_sw, sw))
@@ -1236,9 +1234,8 @@ __icm_tr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr,
if (sw) {
/* Update the switch if it is still in the same place */
if (tb_route(sw) == route && !!sw->authorized == authorized) {
- parent_sw = tb_to_switch(sw->dev.parent);
- update_switch(parent_sw, sw, route, pkg->connection_id,
- 0, 0, 0, boot);
+ update_switch(sw, route, pkg->connection_id, 0, 0, 0,
+ boot);
tb_switch_put(sw);
return;
}
@@ -1276,7 +1273,8 @@ __icm_tr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr,
sw->security_level = security_level;
sw->boot = boot;
sw->link_speed = speed_gen3 ? 20 : 10;
- sw->link_width = dual_lane ? 2 : 1;
+ sw->link_width = dual_lane ? TB_LINK_WIDTH_DUAL :
+ TB_LINK_WIDTH_SINGLE;
sw->rpm = force_rtd3;
if (!sw->rpm)
sw->rpm = intel_vss_is_rtd3(pkg->ep_name,
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index e58beac44295..4b7bec74e89f 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -46,6 +46,10 @@
#define QUIRK_AUTO_CLEAR_INT BIT(0)
#define QUIRK_E2E BIT(1)
+static bool host_reset = true;
+module_param(host_reset, bool, 0444);
+MODULE_PARM_DESC(host_reset, "reset USBv2 host router (default: true)");
+
static int ring_interrupt_index(const struct tb_ring *ring)
{
int bit = ring->hop;
@@ -1217,6 +1221,37 @@ static void nhi_check_iommu(struct tb_nhi *nhi)
str_enabled_disabled(port_ok));
}
+static void nhi_reset(struct tb_nhi *nhi)
+{
+ ktime_t timeout;
+ u32 val;
+
+ val = ioread32(nhi->iobase + REG_CAPS);
+ /* Reset only v2 and later routers */
+ if (FIELD_GET(REG_CAPS_VERSION_MASK, val) < REG_CAPS_VERSION_2)
+ return;
+
+ if (!host_reset) {
+ dev_dbg(&nhi->pdev->dev, "skipping host router reset\n");
+ return;
+ }
+
+ iowrite32(REG_RESET_HRR, nhi->iobase + REG_RESET);
+ msleep(100);
+
+ timeout = ktime_add_ms(ktime_get(), 500);
+ do {
+ val = ioread32(nhi->iobase + REG_RESET);
+ if (!(val & REG_RESET_HRR)) {
+ dev_warn(&nhi->pdev->dev, "host router reset successful\n");
+ return;
+ }
+ usleep_range(10, 20);
+ } while (ktime_before(ktime_get(), timeout));
+
+ dev_warn(&nhi->pdev->dev, "timeout resetting host router\n");
+}
+
static int nhi_init_msi(struct tb_nhi *nhi)
{
struct pci_dev *pdev = nhi->pdev;
@@ -1317,7 +1352,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
nhi->ops = (const struct tb_nhi_ops *)id->driver_data;
/* cannot fail - table is allocated in pcim_iomap_regions */
nhi->iobase = pcim_iomap_table(pdev)[0];
- nhi->hop_count = ioread32(nhi->iobase + REG_HOP_COUNT) & 0x3ff;
+ nhi->hop_count = ioread32(nhi->iobase + REG_CAPS) & 0x3ff;
dev_dbg(dev, "total paths: %d\n", nhi->hop_count);
nhi->tx_rings = devm_kcalloc(&pdev->dev, nhi->hop_count,
@@ -1330,6 +1365,8 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
nhi_check_quirks(nhi);
nhi_check_iommu(nhi);
+ nhi_reset(nhi);
+
res = nhi_init_msi(nhi);
if (res)
return dev_err_probe(dev, res, "cannot enable MSI, aborting\n");
@@ -1480,6 +1517,8 @@ static struct pci_device_id nhi_ids[] = {
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL_P_NHI1),
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI) },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI) },
/* Any USB4 compliant host */
{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_USB4, ~0) },
@@ -1488,6 +1527,7 @@ static struct pci_device_id nhi_ids[] = {
};
MODULE_DEVICE_TABLE(pci, nhi_ids);
+MODULE_DESCRIPTION("Thunderbolt/USB4 core driver");
MODULE_LICENSE("GPL");
static struct pci_driver nhi_driver = {
diff --git a/drivers/thunderbolt/nhi.h b/drivers/thunderbolt/nhi.h
index b0718020c6f5..0f029ce75882 100644
--- a/drivers/thunderbolt/nhi.h
+++ b/drivers/thunderbolt/nhi.h
@@ -75,6 +75,10 @@ extern const struct tb_nhi_ops icl_nhi_ops;
#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_BRIDGE 0x15ef
#define PCI_DEVICE_ID_INTEL_ADL_NHI0 0x463e
#define PCI_DEVICE_ID_INTEL_ADL_NHI1 0x466d
+#define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI 0x5781
+#define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI 0x5784
+#define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HUB_80G_BRIDGE 0x5786
+#define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HUB_40G_BRIDGE 0x57a4
#define PCI_DEVICE_ID_INTEL_MTL_M_NHI0 0x7eb2
#define PCI_DEVICE_ID_INTEL_MTL_P_NHI0 0x7ec2
#define PCI_DEVICE_ID_INTEL_MTL_P_NHI1 0x7ec3
diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h
index 6ba295815477..297a3e440648 100644
--- a/drivers/thunderbolt/nhi_regs.h
+++ b/drivers/thunderbolt/nhi_regs.h
@@ -37,7 +37,7 @@ struct ring_desc {
/* NHI registers in bar 0 */
/*
- * 16 bytes per entry, one entry for every hop (REG_HOP_COUNT)
+ * 16 bytes per entry, one entry for every hop (REG_CAPS)
* 00: physical pointer to an array of struct ring_desc
* 08: ring tail (set by NHI)
* 10: ring head (index of first non posted descriptor)
@@ -46,7 +46,7 @@ struct ring_desc {
#define REG_TX_RING_BASE 0x00000
/*
- * 16 bytes per entry, one entry for every hop (REG_HOP_COUNT)
+ * 16 bytes per entry, one entry for every hop (REG_CAPS)
* 00: physical pointer to an array of struct ring_desc
* 08: ring head (index of first not posted descriptor)
* 10: ring tail (set by NHI)
@@ -56,7 +56,7 @@ struct ring_desc {
#define REG_RX_RING_BASE 0x08000
/*
- * 32 bytes per entry, one entry for every hop (REG_HOP_COUNT)
+ * 32 bytes per entry, one entry for every hop (REG_CAPS)
* 00: enum_ring_flags
* 04: isoch time stamp ?? (write 0)
* ..: unknown
@@ -64,7 +64,7 @@ struct ring_desc {
#define REG_TX_OPTIONS_BASE 0x19800
/*
- * 32 bytes per entry, one entry for every hop (REG_HOP_COUNT)
+ * 32 bytes per entry, one entry for every hop (REG_CAPS)
* 00: enum ring_flags
* If RING_FLAG_E2E_FLOW_CONTROL is set then bits 13-23 must be set to
* the corresponding TX hop id.
@@ -77,7 +77,7 @@ struct ring_desc {
/*
* three bitfields: tx, rx, rx overflow
- * Every bitfield contains one bit for every hop (REG_HOP_COUNT).
+ * Every bitfield contains one bit for every hop (REG_CAPS).
* New interrupts are fired only after ALL registers have been
* read (even those containing only disabled rings).
*/
@@ -87,7 +87,7 @@ struct ring_desc {
/*
* two bitfields: rx, tx
- * Both bitfields contains one bit for every hop (REG_HOP_COUNT). To
+ * Both bitfields contains one bit for every hop (REG_CAPS). To
* enable/disable interrupts set/clear the corresponding bits.
*/
#define REG_RING_INTERRUPT_BASE 0x38200
@@ -104,12 +104,17 @@ struct ring_desc {
#define REG_INT_VEC_ALLOC_REGS (32 / REG_INT_VEC_ALLOC_BITS)
/* The last 11 bits contain the number of hops supported by the NHI port. */
-#define REG_HOP_COUNT 0x39640
+#define REG_CAPS 0x39640
+#define REG_CAPS_VERSION_MASK GENMASK(23, 16)
+#define REG_CAPS_VERSION_2 0x40
#define REG_DMA_MISC 0x39864
#define REG_DMA_MISC_INT_AUTO_CLEAR BIT(2)
#define REG_DMA_MISC_DISABLE_AUTO_CLEAR BIT(17)
+#define REG_RESET 0x39898
+#define REG_RESET_HRR BIT(0)
+
#define REG_INMAIL_DATA 0x39900
#define REG_INMAIL_CMD 0x39904
diff --git a/drivers/thunderbolt/nvm.c b/drivers/thunderbolt/nvm.c
index 3dd5f81bd629..69fb3b0fa34f 100644
--- a/drivers/thunderbolt/nvm.c
+++ b/drivers/thunderbolt/nvm.c
@@ -12,6 +12,10 @@
#include "tb.h"
+#define NVM_MIN_SIZE SZ_32K
+#define NVM_MAX_SIZE SZ_1M
+#define NVM_DATA_DWORDS 16
+
/* Intel specific NVM offsets */
#define INTEL_NVM_DEVID 0x05
#define INTEL_NVM_VERSION 0x08
diff --git a/drivers/thunderbolt/quirks.c b/drivers/thunderbolt/quirks.c
index 1157b8869bcc..488138a28ae1 100644
--- a/drivers/thunderbolt/quirks.c
+++ b/drivers/thunderbolt/quirks.c
@@ -10,6 +10,7 @@
static void quirk_force_power_link(struct tb_switch *sw)
{
sw->quirks |= QUIRK_FORCE_POWER_LINK_CONTROLLER;
+ tb_sw_dbg(sw, "forcing power to link controller\n");
}
static void quirk_dp_credit_allocation(struct tb_switch *sw)
@@ -74,6 +75,14 @@ static const struct tb_quirk tb_quirks[] = {
quirk_usb3_maximum_bandwidth },
{ 0x8087, PCI_DEVICE_ID_INTEL_MTL_P_NHI1, 0x0000, 0x0000,
quirk_usb3_maximum_bandwidth },
+ { 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI, 0x0000, 0x0000,
+ quirk_usb3_maximum_bandwidth },
+ { 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI, 0x0000, 0x0000,
+ quirk_usb3_maximum_bandwidth },
+ { 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HUB_80G_BRIDGE, 0x0000, 0x0000,
+ quirk_usb3_maximum_bandwidth },
+ { 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HUB_40G_BRIDGE, 0x0000, 0x0000,
+ quirk_usb3_maximum_bandwidth },
/*
* CLx is not supported on AMD USB4 Yellow Carp and Pink Sardine platforms.
*/
@@ -105,6 +114,7 @@ void tb_check_quirks(struct tb_switch *sw)
if (q->device && q->device != sw->device)
continue;
+ tb_sw_dbg(sw, "running %ps\n", q->hook);
q->hook(sw);
}
}
diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c
index 9cc28197dbc4..47becb363ada 100644
--- a/drivers/thunderbolt/retimer.c
+++ b/drivers/thunderbolt/retimer.c
@@ -187,10 +187,34 @@ static ssize_t nvm_authenticate_show(struct device *dev,
return ret;
}
+static void tb_retimer_nvm_authenticate_status(struct tb_port *port, u32 *status)
+{
+ int i;
+
+ tb_port_dbg(port, "reading NVM authentication status of retimers\n");
+
+ /*
+ * Before doing anything else, read the authentication status.
+ * If the retimer has it set, store it for the new retimer
+ * device instance.
+ */
+ for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++)
+ usb4_port_retimer_nvm_authenticate_status(port, i, &status[i]);
+}
+
static void tb_retimer_set_inbound_sbtx(struct tb_port *port)
{
int i;
+ /*
+ * When USB4 port is online sideband communications are
+ * already up.
+ */
+ if (!usb4_port_device_is_offline(port->usb4))
+ return;
+
+ tb_port_dbg(port, "enabling sideband transactions\n");
+
for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++)
usb4_port_retimer_set_inbound_sbtx(port, i);
}
@@ -199,6 +223,16 @@ static void tb_retimer_unset_inbound_sbtx(struct tb_port *port)
{
int i;
+ /*
+ * When USB4 port is offline we need to keep the sideband
+ * communications up to make it possible to communicate with
+ * the connected retimers.
+ */
+ if (usb4_port_device_is_offline(port->usb4))
+ return;
+
+ tb_port_dbg(port, "disabling sideband transactions\n");
+
for (i = TB_MAX_RETIMER_INDEX; i >= 1; i--)
usb4_port_retimer_unset_inbound_sbtx(port, i);
}
@@ -229,6 +263,13 @@ static ssize_t nvm_authenticate_store(struct device *dev,
rt->auth_status = 0;
if (val) {
+ /*
+ * When NVM authentication starts the retimer is not
+ * accessible so calling tb_retimer_unset_inbound_sbtx()
+ * will fail and therefore we do not call it. Exception
+ * is when the validation fails or we only write the new
+ * NVM image without authentication.
+ */
tb_retimer_set_inbound_sbtx(rt->port);
if (val == AUTHENTICATE_ONLY) {
ret = tb_retimer_nvm_authenticate(rt, true);
@@ -249,7 +290,8 @@ static ssize_t nvm_authenticate_store(struct device *dev,
}
exit_unlock:
- tb_retimer_unset_inbound_sbtx(rt->port);
+ if (ret || val == WRITE_ONLY)
+ tb_retimer_unset_inbound_sbtx(rt->port);
mutex_unlock(&rt->tb->lock);
exit_rpm:
pm_runtime_mark_last_busy(&rt->dev);
@@ -341,12 +383,6 @@ static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status)
return ret;
}
- if (vendor != PCI_VENDOR_ID_INTEL && vendor != 0x8087) {
- tb_port_info(port, "retimer NVM format of vendor %#x is not supported\n",
- vendor);
- return -EOPNOTSUPP;
- }
-
/*
* Check that it supports NVM operations. If not then don't add
* the device at all.
@@ -455,18 +491,16 @@ int tb_retimer_scan(struct tb_port *port, bool add)
return ret;
/*
- * Enable sideband channel for each retimer. We can do this
- * regardless whether there is device connected or not.
+ * Immediately after sending enumerate retimers read the
+ * authentication status of each retimer.
*/
- tb_retimer_set_inbound_sbtx(port);
+ tb_retimer_nvm_authenticate_status(port, status);
/*
- * Before doing anything else, read the authentication status.
- * If the retimer has it set, store it for the new retimer
- * device instance.
+ * Enable sideband channel for each retimer. We can do this
+ * regardless whether there is device connected or not.
*/
- for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++)
- usb4_port_retimer_nvm_authenticate_status(port, i, &status[i]);
+ tb_retimer_set_inbound_sbtx(port);
for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++) {
/*
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 51e86b5171c7..7ea63bb31714 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -26,10 +26,6 @@ struct nvm_auth_status {
u32 status;
};
-static bool clx_enabled = true;
-module_param_named(clx, clx_enabled, bool, 0444);
-MODULE_PARM_DESC(clx, "allow low power states on the high-speed lanes (default: true)");
-
/*
* Hold NVM authentication failure status per switch This information
* needs to stay around even when the switch gets power cycled so we
@@ -727,7 +723,7 @@ static int tb_init_port(struct tb_port *port)
* can be read from the path config space. Legacy
* devices we use hard-coded value.
*/
- if (tb_switch_is_usb4(port->sw)) {
+ if (port->cap_usb4) {
struct tb_regs_hop hop;
if (!tb_port_read(port, &hop, TB_CFG_HOPS, 0, 2))
@@ -907,15 +903,23 @@ int tb_port_get_link_speed(struct tb_port *port)
speed = (val & LANE_ADP_CS_1_CURRENT_SPEED_MASK) >>
LANE_ADP_CS_1_CURRENT_SPEED_SHIFT;
- return speed == LANE_ADP_CS_1_CURRENT_SPEED_GEN3 ? 20 : 10;
+
+ switch (speed) {
+ case LANE_ADP_CS_1_CURRENT_SPEED_GEN4:
+ return 40;
+ case LANE_ADP_CS_1_CURRENT_SPEED_GEN3:
+ return 20;
+ default:
+ return 10;
+ }
}
/**
* tb_port_get_link_width() - Get current link width
* @port: Port to check (USB4 or CIO)
*
- * Returns link width. Return values can be 1 (Single-Lane), 2 (Dual-Lane)
- * or negative errno in case of failure.
+ * Returns link width. Return the link width as encoded in &enum
+ * tb_link_width or negative errno in case of failure.
*/
int tb_port_get_link_width(struct tb_port *port)
{
@@ -930,11 +934,13 @@ int tb_port_get_link_width(struct tb_port *port)
if (ret)
return ret;
+ /* Matches the values in enum tb_link_width */
return (val & LANE_ADP_CS_1_CURRENT_WIDTH_MASK) >>
LANE_ADP_CS_1_CURRENT_WIDTH_SHIFT;
}
-static bool tb_port_is_width_supported(struct tb_port *port, int width)
+static bool tb_port_is_width_supported(struct tb_port *port,
+ unsigned int width_mask)
{
u32 phy, widths;
int ret;
@@ -950,20 +956,25 @@ static bool tb_port_is_width_supported(struct tb_port *port, int width)
widths = (phy & LANE_ADP_CS_0_SUPPORTED_WIDTH_MASK) >>
LANE_ADP_CS_0_SUPPORTED_WIDTH_SHIFT;
- return !!(widths & width);
+ return widths & width_mask;
+}
+
+static bool is_gen4_link(struct tb_port *port)
+{
+ return tb_port_get_link_speed(port) > 20;
}
/**
* tb_port_set_link_width() - Set target link width of the lane adapter
* @port: Lane adapter
- * @width: Target link width (%1 or %2)
+ * @width: Target link width
*
* Sets the target link width of the lane adapter to @width. Does not
* enable/disable lane bonding. For that call tb_port_set_lane_bonding().
*
* Return: %0 in case of success and negative errno in case of error
*/
-int tb_port_set_link_width(struct tb_port *port, unsigned int width)
+int tb_port_set_link_width(struct tb_port *port, enum tb_link_width width)
{
u32 val;
int ret;
@@ -978,11 +989,14 @@ int tb_port_set_link_width(struct tb_port *port, unsigned int width)
val &= ~LANE_ADP_CS_1_TARGET_WIDTH_MASK;
switch (width) {
- case 1:
+ case TB_LINK_WIDTH_SINGLE:
+ /* Gen 4 link cannot be single */
+ if (is_gen4_link(port))
+ return -EOPNOTSUPP;
val |= LANE_ADP_CS_1_TARGET_WIDTH_SINGLE <<
LANE_ADP_CS_1_TARGET_WIDTH_SHIFT;
break;
- case 2:
+ case TB_LINK_WIDTH_DUAL:
val |= LANE_ADP_CS_1_TARGET_WIDTH_DUAL <<
LANE_ADP_CS_1_TARGET_WIDTH_SHIFT;
break;
@@ -1004,12 +1018,9 @@ int tb_port_set_link_width(struct tb_port *port, unsigned int width)
* cases one should use tb_port_lane_bonding_enable() instead to enable
* lane bonding.
*
- * As a side effect sets @port->bonding accordingly (and does the same
- * for lane 1 too).
- *
* Return: %0 in case of success and negative errno in case of error
*/
-int tb_port_set_lane_bonding(struct tb_port *port, bool bonding)
+static int tb_port_set_lane_bonding(struct tb_port *port, bool bonding)
{
u32 val;
int ret;
@@ -1027,19 +1038,8 @@ int tb_port_set_lane_bonding(struct tb_port *port, bool bonding)
else
val &= ~LANE_ADP_CS_1_LB;
- ret = tb_port_write(port, &val, TB_CFG_PORT,
- port->cap_phy + LANE_ADP_CS_1, 1);
- if (ret)
- return ret;
-
- /*
- * When lane 0 bonding is set it will affect lane 1 too so
- * update both.
- */
- port->bonded = bonding;
- port->dual_link_port->bonded = bonding;
-
- return 0;
+ return tb_port_write(port, &val, TB_CFG_PORT,
+ port->cap_phy + LANE_ADP_CS_1, 1);
}
/**
@@ -1056,36 +1056,52 @@ int tb_port_set_lane_bonding(struct tb_port *port, bool bonding)
*/
int tb_port_lane_bonding_enable(struct tb_port *port)
{
+ enum tb_link_width width;
int ret;
/*
* Enable lane bonding for both links if not already enabled by
* for example the boot firmware.
*/
- ret = tb_port_get_link_width(port);
- if (ret == 1) {
- ret = tb_port_set_link_width(port, 2);
+ width = tb_port_get_link_width(port);
+ if (width == TB_LINK_WIDTH_SINGLE) {
+ ret = tb_port_set_link_width(port, TB_LINK_WIDTH_DUAL);
if (ret)
goto err_lane0;
}
- ret = tb_port_get_link_width(port->dual_link_port);
- if (ret == 1) {
- ret = tb_port_set_link_width(port->dual_link_port, 2);
+ width = tb_port_get_link_width(port->dual_link_port);
+ if (width == TB_LINK_WIDTH_SINGLE) {
+ ret = tb_port_set_link_width(port->dual_link_port,
+ TB_LINK_WIDTH_DUAL);
if (ret)
goto err_lane0;
}
- ret = tb_port_set_lane_bonding(port, true);
- if (ret)
- goto err_lane1;
+ /*
+ * Only set bonding if the link was not already bonded. This
+ * avoids the lane adapter to re-enter bonding state.
+ */
+ if (width == TB_LINK_WIDTH_SINGLE) {
+ ret = tb_port_set_lane_bonding(port, true);
+ if (ret)
+ goto err_lane1;
+ }
+
+ /*
+ * When lane 0 bonding is set it will affect lane 1 too so
+ * update both.
+ */
+ port->bonded = true;
+ port->dual_link_port->bonded = true;
return 0;
err_lane1:
- tb_port_set_link_width(port->dual_link_port, 1);
+ tb_port_set_link_width(port->dual_link_port, TB_LINK_WIDTH_SINGLE);
err_lane0:
- tb_port_set_link_width(port, 1);
+ tb_port_set_link_width(port, TB_LINK_WIDTH_SINGLE);
+
return ret;
}
@@ -1099,27 +1115,34 @@ err_lane0:
void tb_port_lane_bonding_disable(struct tb_port *port)
{
tb_port_set_lane_bonding(port, false);
- tb_port_set_link_width(port->dual_link_port, 1);
- tb_port_set_link_width(port, 1);
+ tb_port_set_link_width(port->dual_link_port, TB_LINK_WIDTH_SINGLE);
+ tb_port_set_link_width(port, TB_LINK_WIDTH_SINGLE);
+ port->dual_link_port->bonded = false;
+ port->bonded = false;
}
/**
* tb_port_wait_for_link_width() - Wait until link reaches specific width
* @port: Port to wait for
- * @width: Expected link width (%1 or %2)
+ * @width_mask: Expected link width mask
* @timeout_msec: Timeout in ms how long to wait
*
* Should be used after both ends of the link have been bonded (or
* bonding has been disabled) to wait until the link actually reaches
- * the expected state. Returns %-ETIMEDOUT if the @width was not reached
- * within the given timeout, %0 if it did.
+ * the expected state. Returns %-ETIMEDOUT if the width was not reached
+ * within the given timeout, %0 if it did. Can be passed a mask of
+ * expected widths and succeeds if any of the widths is reached.
*/
-int tb_port_wait_for_link_width(struct tb_port *port, int width,
+int tb_port_wait_for_link_width(struct tb_port *port, unsigned int width_mask,
int timeout_msec)
{
ktime_t timeout = ktime_add_ms(ktime_get(), timeout_msec);
int ret;
+ /* Gen 4 link does not support single lane */
+ if ((width_mask & TB_LINK_WIDTH_SINGLE) && is_gen4_link(port))
+ return -EOPNOTSUPP;
+
do {
ret = tb_port_get_link_width(port);
if (ret < 0) {
@@ -1130,7 +1153,7 @@ int tb_port_wait_for_link_width(struct tb_port *port, int width,
*/
if (ret != -EACCES)
return ret;
- } else if (ret == width) {
+ } else if (ret & width_mask) {
return 0;
}
@@ -1183,135 +1206,6 @@ int tb_port_update_credits(struct tb_port *port)
return tb_port_do_update_credits(port->dual_link_port);
}
-static int __tb_port_pm_secondary_set(struct tb_port *port, bool secondary)
-{
- u32 phy;
- int ret;
-
- ret = tb_port_read(port, &phy, TB_CFG_PORT,
- port->cap_phy + LANE_ADP_CS_1, 1);
- if (ret)
- return ret;
-
- if (secondary)
- phy |= LANE_ADP_CS_1_PMS;
- else
- phy &= ~LANE_ADP_CS_1_PMS;
-
- return tb_port_write(port, &phy, TB_CFG_PORT,
- port->cap_phy + LANE_ADP_CS_1, 1);
-}
-
-static int tb_port_pm_secondary_enable(struct tb_port *port)
-{
- return __tb_port_pm_secondary_set(port, true);
-}
-
-static int tb_port_pm_secondary_disable(struct tb_port *port)
-{
- return __tb_port_pm_secondary_set(port, false);
-}
-
-/* Called for USB4 or Titan Ridge routers only */
-static bool tb_port_clx_supported(struct tb_port *port, unsigned int clx_mask)
-{
- u32 val, mask = 0;
- bool ret;
-
- /* Don't enable CLx in case of two single-lane links */
- if (!port->bonded && port->dual_link_port)
- return false;
-
- /* Don't enable CLx in case of inter-domain link */
- if (port->xdomain)
- return false;
-
- if (tb_switch_is_usb4(port->sw)) {
- if (!usb4_port_clx_supported(port))
- return false;
- } else if (!tb_lc_is_clx_supported(port)) {
- return false;
- }
-
- if (clx_mask & TB_CL1) {
- /* CL0s and CL1 are enabled and supported together */
- mask |= LANE_ADP_CS_0_CL0S_SUPPORT | LANE_ADP_CS_0_CL1_SUPPORT;
- }
- if (clx_mask & TB_CL2)
- mask |= LANE_ADP_CS_0_CL2_SUPPORT;
-
- ret = tb_port_read(port, &val, TB_CFG_PORT,
- port->cap_phy + LANE_ADP_CS_0, 1);
- if (ret)
- return false;
-
- return !!(val & mask);
-}
-
-static int __tb_port_clx_set(struct tb_port *port, enum tb_clx clx, bool enable)
-{
- u32 phy, mask;
- int ret;
-
- /* CL0s and CL1 are enabled and supported together */
- if (clx == TB_CL1)
- mask = LANE_ADP_CS_1_CL0S_ENABLE | LANE_ADP_CS_1_CL1_ENABLE;
- else
- /* For now we support only CL0s and CL1. Not CL2 */
- return -EOPNOTSUPP;
-
- ret = tb_port_read(port, &phy, TB_CFG_PORT,
- port->cap_phy + LANE_ADP_CS_1, 1);
- if (ret)
- return ret;
-
- if (enable)
- phy |= mask;
- else
- phy &= ~mask;
-
- return tb_port_write(port, &phy, TB_CFG_PORT,
- port->cap_phy + LANE_ADP_CS_1, 1);
-}
-
-static int tb_port_clx_disable(struct tb_port *port, enum tb_clx clx)
-{
- return __tb_port_clx_set(port, clx, false);
-}
-
-static int tb_port_clx_enable(struct tb_port *port, enum tb_clx clx)
-{
- return __tb_port_clx_set(port, clx, true);
-}
-
-/**
- * tb_port_is_clx_enabled() - Is given CL state enabled
- * @port: USB4 port to check
- * @clx_mask: Mask of CL states to check
- *
- * Returns true if any of the given CL states is enabled for @port.
- */
-bool tb_port_is_clx_enabled(struct tb_port *port, unsigned int clx_mask)
-{
- u32 val, mask = 0;
- int ret;
-
- if (!tb_port_clx_supported(port, clx_mask))
- return false;
-
- if (clx_mask & TB_CL1)
- mask |= LANE_ADP_CS_1_CL0S_ENABLE | LANE_ADP_CS_1_CL1_ENABLE;
- if (clx_mask & TB_CL2)
- mask |= LANE_ADP_CS_1_CL2_ENABLE;
-
- ret = tb_port_read(port, &val, TB_CFG_PORT,
- port->cap_phy + LANE_ADP_CS_1, 1);
- if (ret)
- return false;
-
- return !!(val & mask);
-}
-
static int tb_port_start_lane_initialization(struct tb_port *port)
{
int ret;
@@ -1911,20 +1805,57 @@ static ssize_t speed_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(rx_speed, 0444, speed_show, NULL);
static DEVICE_ATTR(tx_speed, 0444, speed_show, NULL);
-static ssize_t lanes_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t rx_lanes_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct tb_switch *sw = tb_to_switch(dev);
+ unsigned int width;
+
+ switch (sw->link_width) {
+ case TB_LINK_WIDTH_SINGLE:
+ case TB_LINK_WIDTH_ASYM_TX:
+ width = 1;
+ break;
+ case TB_LINK_WIDTH_DUAL:
+ width = 2;
+ break;
+ case TB_LINK_WIDTH_ASYM_RX:
+ width = 3;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
- return sysfs_emit(buf, "%u\n", sw->link_width);
+ return sysfs_emit(buf, "%u\n", width);
}
+static DEVICE_ATTR(rx_lanes, 0444, rx_lanes_show, NULL);
-/*
- * Currently link has same amount of lanes both directions (1 or 2) but
- * expose them separately to allow possible asymmetric links in the future.
- */
-static DEVICE_ATTR(rx_lanes, 0444, lanes_show, NULL);
-static DEVICE_ATTR(tx_lanes, 0444, lanes_show, NULL);
+static ssize_t tx_lanes_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct tb_switch *sw = tb_to_switch(dev);
+ unsigned int width;
+
+ switch (sw->link_width) {
+ case TB_LINK_WIDTH_SINGLE:
+ case TB_LINK_WIDTH_ASYM_RX:
+ width = 1;
+ break;
+ case TB_LINK_WIDTH_DUAL:
+ width = 2;
+ break;
+ case TB_LINK_WIDTH_ASYM_TX:
+ width = 3;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
+
+ return sysfs_emit(buf, "%u\n", width);
+}
+static DEVICE_ATTR(tx_lanes, 0444, tx_lanes_show, NULL);
static ssize_t nvm_authenticate_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -2189,8 +2120,9 @@ static int tb_switch_uevent(const struct device *dev, struct kobj_uevent_env *en
const struct tb_switch *sw = tb_to_switch(dev);
const char *type;
- if (sw->config.thunderbolt_version == USB4_VERSION_1_0) {
- if (add_uevent_var(env, "USB4_VERSION=1.0"))
+ if (tb_switch_is_usb4(sw)) {
+ if (add_uevent_var(env, "USB4_VERSION=%u.0",
+ usb4_switch_version(sw)))
return -ENOMEM;
}
@@ -2498,9 +2430,13 @@ int tb_switch_configure(struct tb_switch *sw)
/*
* For USB4 devices, we need to program the CM version
* accordingly so that it knows to expose all the
- * additional capabilities.
+ * additional capabilities. Program it according to USB4
+ * version to avoid changing existing (v1) routers behaviour.
*/
- sw->config.cmuv = USB4_VERSION_1_0;
+ if (usb4_switch_version(sw) < 2)
+ sw->config.cmuv = ROUTER_CS_4_CMUV_V1;
+ else
+ sw->config.cmuv = ROUTER_CS_4_CMUV_V2;
sw->config.plug_events_delay = 0xa;
/* Enumerate the switch */
@@ -2530,6 +2466,22 @@ int tb_switch_configure(struct tb_switch *sw)
return tb_plug_events_active(sw, true);
}
+/**
+ * tb_switch_configuration_valid() - Set the tunneling configuration to be valid
+ * @sw: Router to configure
+ *
+ * Needs to be called before any tunnels can be setup through the
+ * router. Can be called to any router.
+ *
+ * Returns %0 in success and negative errno otherwise.
+ */
+int tb_switch_configuration_valid(struct tb_switch *sw)
+{
+ if (tb_switch_is_usb4(sw))
+ return usb4_switch_configuration_valid(sw);
+ return 0;
+}
+
static int tb_switch_set_uuid(struct tb_switch *sw)
{
bool uid = false;
@@ -2754,9 +2706,9 @@ static int tb_switch_update_link_attributes(struct tb_switch *sw)
*/
int tb_switch_lane_bonding_enable(struct tb_switch *sw)
{
- struct tb_switch *parent = tb_to_switch(sw->dev.parent);
struct tb_port *up, *down;
u64 route = tb_route(sw);
+ unsigned int width_mask;
int ret;
if (!route)
@@ -2766,10 +2718,10 @@ int tb_switch_lane_bonding_enable(struct tb_switch *sw)
return 0;
up = tb_upstream_port(sw);
- down = tb_port_at(route, parent);
+ down = tb_switch_downstream_port(sw);
- if (!tb_port_is_width_supported(up, 2) ||
- !tb_port_is_width_supported(down, 2))
+ if (!tb_port_is_width_supported(up, TB_LINK_WIDTH_DUAL) ||
+ !tb_port_is_width_supported(down, TB_LINK_WIDTH_DUAL))
return 0;
ret = tb_port_lane_bonding_enable(up);
@@ -2785,7 +2737,11 @@ int tb_switch_lane_bonding_enable(struct tb_switch *sw)
return ret;
}
- ret = tb_port_wait_for_link_width(down, 2, 100);
+ /* Any of the widths are all bonded */
+ width_mask = TB_LINK_WIDTH_DUAL | TB_LINK_WIDTH_ASYM_TX |
+ TB_LINK_WIDTH_ASYM_RX;
+
+ ret = tb_port_wait_for_link_width(down, width_mask, 100);
if (ret) {
tb_port_warn(down, "timeout enabling lane bonding\n");
return ret;
@@ -2808,8 +2764,8 @@ int tb_switch_lane_bonding_enable(struct tb_switch *sw)
*/
void tb_switch_lane_bonding_disable(struct tb_switch *sw)
{
- struct tb_switch *parent = tb_to_switch(sw->dev.parent);
struct tb_port *up, *down;
+ int ret;
if (!tb_route(sw))
return;
@@ -2818,7 +2774,7 @@ void tb_switch_lane_bonding_disable(struct tb_switch *sw)
if (!up->bonded)
return;
- down = tb_port_at(tb_route(sw), parent);
+ down = tb_switch_downstream_port(sw);
tb_port_lane_bonding_disable(up);
tb_port_lane_bonding_disable(down);
@@ -2827,7 +2783,8 @@ void tb_switch_lane_bonding_disable(struct tb_switch *sw)
* It is fine if we get other errors as the router might have
* been unplugged.
*/
- if (tb_port_wait_for_link_width(down, 1, 100) == -ETIMEDOUT)
+ ret = tb_port_wait_for_link_width(down, TB_LINK_WIDTH_SINGLE, 100);
+ if (ret == -ETIMEDOUT)
tb_sw_warn(sw, "timeout disabling lane bonding\n");
tb_port_update_credits(down);
@@ -2994,6 +2951,10 @@ int tb_switch_add(struct tb_switch *sw)
if (ret)
return ret;
+ ret = tb_switch_clx_init(sw);
+ if (ret)
+ return ret;
+
ret = tb_switch_tmu_init(sw);
if (ret)
return ret;
@@ -3246,13 +3207,8 @@ void tb_switch_suspend(struct tb_switch *sw, bool runtime)
/*
* Actually only needed for Titan Ridge but for simplicity can be
* done for USB4 device too as CLx is re-enabled at resume.
- * CL0s and CL1 are enabled and supported together.
*/
- if (tb_switch_is_clx_enabled(sw, TB_CL1)) {
- if (tb_switch_disable_clx(sw, TB_CL1))
- tb_sw_warn(sw, "failed to disable %s on upstream port\n",
- tb_switch_clx_name(TB_CL1));
- }
+ tb_switch_clx_disable(sw);
err = tb_plug_events_active(sw, false);
if (err)
@@ -3474,234 +3430,6 @@ struct tb_port *tb_switch_find_port(struct tb_switch *sw,
return NULL;
}
-static int tb_switch_pm_secondary_resolve(struct tb_switch *sw)
-{
- struct tb_switch *parent = tb_switch_parent(sw);
- struct tb_port *up, *down;
- int ret;
-
- if (!tb_route(sw))
- return 0;
-
- up = tb_upstream_port(sw);
- down = tb_port_at(tb_route(sw), parent);
- ret = tb_port_pm_secondary_enable(up);
- if (ret)
- return ret;
-
- return tb_port_pm_secondary_disable(down);
-}
-
-static int __tb_switch_enable_clx(struct tb_switch *sw, enum tb_clx clx)
-{
- struct tb_switch *parent = tb_switch_parent(sw);
- bool up_clx_support, down_clx_support;
- struct tb_port *up, *down;
- int ret;
-
- if (!tb_switch_is_clx_supported(sw))
- return 0;
-
- /*
- * Enable CLx for host router's downstream port as part of the
- * downstream router enabling procedure.
- */
- if (!tb_route(sw))
- return 0;
-
- /* Enable CLx only for first hop router (depth = 1) */
- if (tb_route(parent))
- return 0;
-
- ret = tb_switch_pm_secondary_resolve(sw);
- if (ret)
- return ret;
-
- up = tb_upstream_port(sw);
- down = tb_port_at(tb_route(sw), parent);
-
- up_clx_support = tb_port_clx_supported(up, clx);
- down_clx_support = tb_port_clx_supported(down, clx);
-
- tb_port_dbg(up, "%s %ssupported\n", tb_switch_clx_name(clx),
- up_clx_support ? "" : "not ");
- tb_port_dbg(down, "%s %ssupported\n", tb_switch_clx_name(clx),
- down_clx_support ? "" : "not ");
-
- if (!up_clx_support || !down_clx_support)
- return -EOPNOTSUPP;
-
- ret = tb_port_clx_enable(up, clx);
- if (ret)
- return ret;
-
- ret = tb_port_clx_enable(down, clx);
- if (ret) {
- tb_port_clx_disable(up, clx);
- return ret;
- }
-
- ret = tb_switch_mask_clx_objections(sw);
- if (ret) {
- tb_port_clx_disable(up, clx);
- tb_port_clx_disable(down, clx);
- return ret;
- }
-
- sw->clx = clx;
-
- tb_port_dbg(up, "%s enabled\n", tb_switch_clx_name(clx));
- return 0;
-}
-
-/**
- * tb_switch_enable_clx() - Enable CLx on upstream port of specified router
- * @sw: Router to enable CLx for
- * @clx: The CLx state to enable
- *
- * Enable CLx state only for first hop router. That is the most common
- * use-case, that is intended for better thermal management, and so helps
- * to improve performance. CLx is enabled only if both sides of the link
- * support CLx, and if both sides of the link are not configured as two
- * single lane links and only if the link is not inter-domain link. The
- * complete set of conditions is described in CM Guide 1.0 section 8.1.
- *
- * Return: Returns 0 on success or an error code on failure.
- */
-int tb_switch_enable_clx(struct tb_switch *sw, enum tb_clx clx)
-{
- struct tb_switch *root_sw = sw->tb->root_switch;
-
- if (!clx_enabled)
- return 0;
-
- /*
- * CLx is not enabled and validated on Intel USB4 platforms before
- * Alder Lake.
- */
- if (root_sw->generation < 4 || tb_switch_is_tiger_lake(root_sw))
- return 0;
-
- switch (clx) {
- case TB_CL1:
- /* CL0s and CL1 are enabled and supported together */
- return __tb_switch_enable_clx(sw, clx);
-
- default:
- return -EOPNOTSUPP;
- }
-}
-
-static int __tb_switch_disable_clx(struct tb_switch *sw, enum tb_clx clx)
-{
- struct tb_switch *parent = tb_switch_parent(sw);
- struct tb_port *up, *down;
- int ret;
-
- if (!tb_switch_is_clx_supported(sw))
- return 0;
-
- /*
- * Disable CLx for host router's downstream port as part of the
- * downstream router enabling procedure.
- */
- if (!tb_route(sw))
- return 0;
-
- /* Disable CLx only for first hop router (depth = 1) */
- if (tb_route(parent))
- return 0;
-
- up = tb_upstream_port(sw);
- down = tb_port_at(tb_route(sw), parent);
- ret = tb_port_clx_disable(up, clx);
- if (ret)
- return ret;
-
- ret = tb_port_clx_disable(down, clx);
- if (ret)
- return ret;
-
- sw->clx = TB_CLX_DISABLE;
-
- tb_port_dbg(up, "%s disabled\n", tb_switch_clx_name(clx));
- return 0;
-}
-
-/**
- * tb_switch_disable_clx() - Disable CLx on upstream port of specified router
- * @sw: Router to disable CLx for
- * @clx: The CLx state to disable
- *
- * Return: Returns 0 on success or an error code on failure.
- */
-int tb_switch_disable_clx(struct tb_switch *sw, enum tb_clx clx)
-{
- if (!clx_enabled)
- return 0;
-
- switch (clx) {
- case TB_CL1:
- /* CL0s and CL1 are enabled and supported together */
- return __tb_switch_disable_clx(sw, clx);
-
- default:
- return -EOPNOTSUPP;
- }
-}
-
-/**
- * tb_switch_mask_clx_objections() - Mask CLx objections for a router
- * @sw: Router to mask objections for
- *
- * Mask the objections coming from the second depth routers in order to
- * stop these objections from interfering with the CLx states of the first
- * depth link.
- */
-int tb_switch_mask_clx_objections(struct tb_switch *sw)
-{
- int up_port = sw->config.upstream_port_number;
- u32 offset, val[2], mask_obj, unmask_obj;
- int ret, i;
-
- /* Only Titan Ridge of pre-USB4 devices support CLx states */
- if (!tb_switch_is_titan_ridge(sw))
- return 0;
-
- if (!tb_route(sw))
- return 0;
-
- /*
- * In Titan Ridge there are only 2 dual-lane Thunderbolt ports:
- * Port A consists of lane adapters 1,2 and
- * Port B consists of lane adapters 3,4
- * If upstream port is A, (lanes are 1,2), we mask objections from
- * port B (lanes 3,4) and unmask objections from Port A and vice-versa.
- */
- if (up_port == 1) {
- mask_obj = TB_LOW_PWR_C0_PORT_B_MASK;
- unmask_obj = TB_LOW_PWR_C1_PORT_A_MASK;
- offset = TB_LOW_PWR_C1_CL1;
- } else {
- mask_obj = TB_LOW_PWR_C1_PORT_A_MASK;
- unmask_obj = TB_LOW_PWR_C0_PORT_B_MASK;
- offset = TB_LOW_PWR_C3_CL1;
- }
-
- ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
- sw->cap_lp + offset, ARRAY_SIZE(val));
- if (ret)
- return ret;
-
- for (i = 0; i < ARRAY_SIZE(val); i++) {
- val[i] |= mask_obj;
- val[i] &= ~unmask_obj;
- }
-
- return tb_sw_write(sw, &val, TB_CFG_SWITCH,
- sw->cap_lp + offset, ARRAY_SIZE(val));
-}
-
/*
* Can be used for read/write a specified PCIe bridge for any Thunderbolt 3
* device. For now used only for Titan Ridge.
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index c1af712ca728..62b26b7998fd 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -131,7 +131,7 @@ tb_attach_bandwidth_group(struct tb_cm *tcm, struct tb_port *in,
static void tb_discover_bandwidth_group(struct tb_cm *tcm, struct tb_port *in,
struct tb_port *out)
{
- if (usb4_dp_port_bw_mode_enabled(in)) {
+ if (usb4_dp_port_bandwidth_mode_enabled(in)) {
int index, i;
index = usb4_dp_port_group_id(in);
@@ -240,6 +240,147 @@ static void tb_discover_dp_resources(struct tb *tb)
}
}
+/* Enables CL states up to host router */
+static int tb_enable_clx(struct tb_switch *sw)
+{
+ struct tb_cm *tcm = tb_priv(sw->tb);
+ unsigned int clx = TB_CL0S | TB_CL1;
+ const struct tb_tunnel *tunnel;
+ int ret;
+
+ /*
+ * Currently only enable CLx for the first link. This is enough
+ * to allow the CPU to save energy at least on Intel hardware
+ * and makes it slightly simpler to implement. We may change
+ * this in the future to cover the whole topology if it turns
+ * out to be beneficial.
+ */
+ while (sw && sw->config.depth > 1)
+ sw = tb_switch_parent(sw);
+
+ if (!sw)
+ return 0;
+
+ if (sw->config.depth != 1)
+ return 0;
+
+ /*
+ * If we are re-enabling then check if there is an active DMA
+ * tunnel and in that case bail out.
+ */
+ list_for_each_entry(tunnel, &tcm->tunnel_list, list) {
+ if (tb_tunnel_is_dma(tunnel)) {
+ if (tb_tunnel_port_on_path(tunnel, tb_upstream_port(sw)))
+ return 0;
+ }
+ }
+
+ /*
+ * Initially try with CL2. If that's not supported by the
+ * topology try with CL0s and CL1 and then give up.
+ */
+ ret = tb_switch_clx_enable(sw, clx | TB_CL2);
+ if (ret == -EOPNOTSUPP)
+ ret = tb_switch_clx_enable(sw, clx);
+ return ret == -EOPNOTSUPP ? 0 : ret;
+}
+
+/* Disables CL states up to the host router */
+static void tb_disable_clx(struct tb_switch *sw)
+{
+ do {
+ if (tb_switch_clx_disable(sw) < 0)
+ tb_sw_warn(sw, "failed to disable CL states\n");
+ sw = tb_switch_parent(sw);
+ } while (sw);
+}
+
+static int tb_increase_switch_tmu_accuracy(struct device *dev, void *data)
+{
+ struct tb_switch *sw;
+
+ sw = tb_to_switch(dev);
+ if (!sw)
+ return 0;
+
+ if (tb_switch_tmu_is_configured(sw, TB_SWITCH_TMU_MODE_LOWRES)) {
+ enum tb_switch_tmu_mode mode;
+ int ret;
+
+ if (tb_switch_clx_is_enabled(sw, TB_CL1))
+ mode = TB_SWITCH_TMU_MODE_HIFI_UNI;
+ else
+ mode = TB_SWITCH_TMU_MODE_HIFI_BI;
+
+ ret = tb_switch_tmu_configure(sw, mode);
+ if (ret)
+ return ret;
+
+ return tb_switch_tmu_enable(sw);
+ }
+
+ return 0;
+}
+
+static void tb_increase_tmu_accuracy(struct tb_tunnel *tunnel)
+{
+ struct tb_switch *sw;
+
+ if (!tunnel)
+ return;
+
+ /*
+ * Once first DP tunnel is established we change the TMU
+ * accuracy of first depth child routers (and the host router)
+ * to the highest. This is needed for the DP tunneling to work
+ * but also allows CL0s.
+ *
+ * If both routers are v2 then we don't need to do anything as
+ * they are using enhanced TMU mode that allows all CLx.
+ */
+ sw = tunnel->tb->root_switch;
+ device_for_each_child(&sw->dev, NULL, tb_increase_switch_tmu_accuracy);
+}
+
+static int tb_enable_tmu(struct tb_switch *sw)
+{
+ int ret;
+
+ /*
+ * If both routers at the end of the link are v2 we simply
+ * enable the enhanched uni-directional mode. That covers all
+ * the CL states. For v1 and before we need to use the normal
+ * rate to allow CL1 (when supported). Otherwise we keep the TMU
+ * running at the highest accuracy.
+ */
+ ret = tb_switch_tmu_configure(sw,
+ TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI);
+ if (ret == -EOPNOTSUPP) {
+ if (tb_switch_clx_is_enabled(sw, TB_CL1))
+ ret = tb_switch_tmu_configure(sw,
+ TB_SWITCH_TMU_MODE_LOWRES);
+ else
+ ret = tb_switch_tmu_configure(sw,
+ TB_SWITCH_TMU_MODE_HIFI_BI);
+ }
+ if (ret)
+ return ret;
+
+ /* If it is already enabled in correct mode, don't touch it */
+ if (tb_switch_tmu_is_enabled(sw))
+ return 0;
+
+ ret = tb_switch_tmu_disable(sw);
+ if (ret)
+ return ret;
+
+ ret = tb_switch_tmu_post_time(sw);
+ if (ret)
+ return ret;
+
+ return tb_switch_tmu_enable(sw);
+}
+
static void tb_switch_discover_tunnels(struct tb_switch *sw,
struct list_head *list,
bool alloc_hopids)
@@ -253,13 +394,7 @@ static void tb_switch_discover_tunnels(struct tb_switch *sw,
switch (port->config.type) {
case TB_TYPE_DP_HDMI_IN:
tunnel = tb_tunnel_discover_dp(tb, port, alloc_hopids);
- /*
- * In case of DP tunnel exists, change host router's
- * 1st children TMU mode to HiFi for CL0s to work.
- */
- if (tunnel)
- tb_switch_enable_tmu_1st_child(tb->root_switch,
- TB_SWITCH_TMU_RATE_HIFI);
+ tb_increase_tmu_accuracy(tunnel);
break;
case TB_TYPE_PCIE_DOWN:
@@ -357,25 +492,6 @@ static void tb_scan_xdomain(struct tb_port *port)
}
}
-static int tb_enable_tmu(struct tb_switch *sw)
-{
- int ret;
-
- /* If it is already enabled in correct mode, don't touch it */
- if (tb_switch_tmu_is_enabled(sw, sw->tmu.unidirectional_request))
- return 0;
-
- ret = tb_switch_tmu_disable(sw);
- if (ret)
- return ret;
-
- ret = tb_switch_tmu_post_time(sw);
- if (ret)
- return ret;
-
- return tb_switch_tmu_enable(sw);
-}
-
/**
* tb_find_unused_port() - return the first inactive port on @sw
* @sw: Switch to find the port on
@@ -480,7 +596,8 @@ static int tb_available_bandwidth(struct tb *tb, struct tb_port *src_port,
usb3_consumed_down = 0;
}
- *available_up = *available_down = 40000;
+ /* Maximum possible bandwidth asymmetric Gen 4 link is 120 Gb/s */
+ *available_up = *available_down = 120000;
/* Find the minimum available bandwidth over all links */
tb_for_each_port_on_path(src_port, dst_port, port) {
@@ -491,18 +608,45 @@ static int tb_available_bandwidth(struct tb *tb, struct tb_port *src_port,
if (tb_is_upstream_port(port)) {
link_speed = port->sw->link_speed;
+ /*
+ * sw->link_width is from upstream perspective
+ * so we use the opposite for downstream of the
+ * host router.
+ */
+ if (port->sw->link_width == TB_LINK_WIDTH_ASYM_TX) {
+ up_bw = link_speed * 3 * 1000;
+ down_bw = link_speed * 1 * 1000;
+ } else if (port->sw->link_width == TB_LINK_WIDTH_ASYM_RX) {
+ up_bw = link_speed * 1 * 1000;
+ down_bw = link_speed * 3 * 1000;
+ } else {
+ up_bw = link_speed * port->sw->link_width * 1000;
+ down_bw = up_bw;
+ }
} else {
link_speed = tb_port_get_link_speed(port);
if (link_speed < 0)
return link_speed;
- }
- link_width = port->bonded ? 2 : 1;
+ link_width = tb_port_get_link_width(port);
+ if (link_width < 0)
+ return link_width;
+
+ if (link_width == TB_LINK_WIDTH_ASYM_TX) {
+ up_bw = link_speed * 1 * 1000;
+ down_bw = link_speed * 3 * 1000;
+ } else if (link_width == TB_LINK_WIDTH_ASYM_RX) {
+ up_bw = link_speed * 3 * 1000;
+ down_bw = link_speed * 1 * 1000;
+ } else {
+ up_bw = link_speed * link_width * 1000;
+ down_bw = up_bw;
+ }
+ }
- up_bw = link_speed * link_width * 1000; /* Mb/s */
/* Leave 10% guard band */
up_bw -= up_bw / 10;
- down_bw = up_bw;
+ down_bw -= down_bw / 10;
tb_port_dbg(port, "link total bandwidth %d/%d Mb/s\n", up_bw,
down_bw);
@@ -628,7 +772,7 @@ static int tb_tunnel_usb3(struct tb *tb, struct tb_switch *sw)
* Look up available down port. Since we are chaining it should
* be found right above this switch.
*/
- port = tb_port_at(tb_route(sw), parent);
+ port = tb_switch_downstream_port(sw);
down = tb_find_usb3_down(parent, port);
if (!down)
return 0;
@@ -739,7 +883,6 @@ static void tb_scan_port(struct tb_port *port)
struct tb_port *upstream_port;
bool discovery = false;
struct tb_switch *sw;
- int ret;
if (tb_is_upstream_port(port))
return;
@@ -838,28 +981,20 @@ static void tb_scan_port(struct tb_port *port)
* CL0s and CL1 are enabled and supported together.
* Silently ignore CLx enabling in case CLx is not supported.
*/
- if (discovery) {
+ if (discovery)
tb_sw_dbg(sw, "discovery, not touching CL states\n");
- } else {
- ret = tb_switch_enable_clx(sw, TB_CL1);
- if (ret && ret != -EOPNOTSUPP)
- tb_sw_warn(sw, "failed to enable %s on upstream port\n",
- tb_switch_clx_name(TB_CL1));
- }
-
- if (tb_switch_is_clx_enabled(sw, TB_CL1))
- /*
- * To support highest CLx state, we set router's TMU to
- * Normal-Uni mode.
- */
- tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_NORMAL, true);
- else
- /* If CLx disabled, configure router's TMU to HiFi-Bidir mode*/
- tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_HIFI, false);
+ else if (tb_enable_clx(sw))
+ tb_sw_warn(sw, "failed to enable CL states\n");
if (tb_enable_tmu(sw))
tb_sw_warn(sw, "failed to enable TMU\n");
+ /*
+ * Configuration valid needs to be set after the TMU has been
+ * enabled for the upstream port of the router so we do it here.
+ */
+ tb_switch_configuration_valid(sw);
+
/* Scan upstream retimers */
tb_retimer_scan(upstream_port, true);
@@ -1034,7 +1169,7 @@ tb_recalc_estimated_bandwidth_for_group(struct tb_bandwidth_group *group)
struct tb_tunnel *tunnel;
struct tb_port *out;
- if (!usb4_dp_port_bw_mode_enabled(in))
+ if (!usb4_dp_port_bandwidth_mode_enabled(in))
continue;
tunnel = tb_find_tunnel(tb, TB_TUNNEL_DP, in, NULL);
@@ -1082,7 +1217,7 @@ tb_recalc_estimated_bandwidth_for_group(struct tb_bandwidth_group *group)
else
estimated_bw = estimated_up;
- if (usb4_dp_port_set_estimated_bw(in, estimated_bw))
+ if (usb4_dp_port_set_estimated_bandwidth(in, estimated_bw))
tb_port_warn(in, "failed to update estimated bandwidth\n");
}
@@ -1263,8 +1398,7 @@ static void tb_tunnel_dp(struct tb *tb)
* In case of DP tunnel exists, change host router's 1st children
* TMU mode to HiFi for CL0s to work.
*/
- tb_switch_enable_tmu_1st_child(tb->root_switch, TB_SWITCH_TMU_RATE_HIFI);
-
+ tb_increase_tmu_accuracy(tunnel);
return;
err_free:
@@ -1378,7 +1512,6 @@ static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw)
{
struct tb_port *up, *down, *port;
struct tb_cm *tcm = tb_priv(tb);
- struct tb_switch *parent_sw;
struct tb_tunnel *tunnel;
up = tb_switch_find_port(sw, TB_TYPE_PCIE_UP);
@@ -1389,9 +1522,8 @@ static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw)
* Look up available down port. Since we are chaining it should
* be found right above this switch.
*/
- parent_sw = tb_to_switch(sw->dev.parent);
- port = tb_port_at(tb_route(sw), parent_sw);
- down = tb_find_pcie_down(parent_sw, port);
+ port = tb_switch_downstream_port(sw);
+ down = tb_find_pcie_down(tb_switch_parent(sw), port);
if (!down)
return 0;
@@ -1428,30 +1560,45 @@ static int tb_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
struct tb_port *nhi_port, *dst_port;
struct tb_tunnel *tunnel;
struct tb_switch *sw;
+ int ret;
sw = tb_to_switch(xd->dev.parent);
dst_port = tb_port_at(xd->route, sw);
nhi_port = tb_switch_find_port(tb->root_switch, TB_TYPE_NHI);
mutex_lock(&tb->lock);
+
+ /*
+ * When tunneling DMA paths the link should not enter CL states
+ * so disable them now.
+ */
+ tb_disable_clx(sw);
+
tunnel = tb_tunnel_alloc_dma(tb, nhi_port, dst_port, transmit_path,
transmit_ring, receive_path, receive_ring);
if (!tunnel) {
- mutex_unlock(&tb->lock);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_clx;
}
if (tb_tunnel_activate(tunnel)) {
tb_port_info(nhi_port,
"DMA tunnel activation failed, aborting\n");
- tb_tunnel_free(tunnel);
- mutex_unlock(&tb->lock);
- return -EIO;
+ ret = -EIO;
+ goto err_free;
}
list_add_tail(&tunnel->list, &tcm->tunnel_list);
mutex_unlock(&tb->lock);
return 0;
+
+err_free:
+ tb_tunnel_free(tunnel);
+err_clx:
+ tb_enable_clx(sw);
+ mutex_unlock(&tb->lock);
+
+ return ret;
}
static void __tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
@@ -1477,6 +1624,13 @@ static void __tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
receive_path, receive_ring))
tb_deactivate_and_free_tunnel(tunnel);
}
+
+ /*
+ * Try to re-enable CL states now, it is OK if this fails
+ * because we may still have another DMA tunnel active through
+ * the same host router USB4 downstream port.
+ */
+ tb_enable_clx(sw);
}
static int tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
@@ -1758,12 +1912,12 @@ static void tb_handle_dp_bandwidth_request(struct work_struct *work)
tb_port_dbg(in, "handling bandwidth allocation request\n");
- if (!usb4_dp_port_bw_mode_enabled(in)) {
+ if (!usb4_dp_port_bandwidth_mode_enabled(in)) {
tb_port_warn(in, "bandwidth allocation mode not enabled\n");
goto unlock;
}
- ret = usb4_dp_port_requested_bw(in);
+ ret = usb4_dp_port_requested_bandwidth(in);
if (ret < 0) {
if (ret == -ENODATA)
tb_port_dbg(in, "no bandwidth request active\n");
@@ -1830,17 +1984,26 @@ static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 port)
static void tb_handle_notification(struct tb *tb, u64 route,
const struct cfg_error_pkg *error)
{
- if (tb_cfg_ack_notification(tb->ctl, route, error))
- tb_warn(tb, "could not ack notification on %llx\n", route);
switch (error->error) {
+ case TB_CFG_ERROR_PCIE_WAKE:
+ case TB_CFG_ERROR_DP_CON_CHANGE:
+ case TB_CFG_ERROR_DPTX_DISCOVERY:
+ if (tb_cfg_ack_notification(tb->ctl, route, error))
+ tb_warn(tb, "could not ack notification on %llx\n",
+ route);
+ break;
+
case TB_CFG_ERROR_DP_BW:
+ if (tb_cfg_ack_notification(tb->ctl, route, error))
+ tb_warn(tb, "could not ack notification on %llx\n",
+ route);
tb_queue_dp_bandwidth_request(tb, route, error->port);
break;
default:
- /* Ack is enough */
- return;
+ /* Ignore for now */
+ break;
}
}
@@ -1955,8 +2118,7 @@ static int tb_start(struct tb *tb)
* To support highest CLx state, we set host router's TMU to
* Normal mode.
*/
- tb_switch_tmu_configure(tb->root_switch, TB_SWITCH_TMU_RATE_NORMAL,
- false);
+ tb_switch_tmu_configure(tb->root_switch, TB_SWITCH_TMU_MODE_LOWRES);
/* Enable TMU if it is off */
tb_switch_tmu_enable(tb->root_switch);
/* Full scan to discover devices added before the driver was loaded. */
@@ -1997,34 +2159,19 @@ static int tb_suspend_noirq(struct tb *tb)
static void tb_restore_children(struct tb_switch *sw)
{
struct tb_port *port;
- int ret;
/* No need to restore if the router is already unplugged */
if (sw->is_unplugged)
return;
- /*
- * CL0s and CL1 are enabled and supported together.
- * Silently ignore CLx re-enabling in case CLx is not supported.
- */
- ret = tb_switch_enable_clx(sw, TB_CL1);
- if (ret && ret != -EOPNOTSUPP)
- tb_sw_warn(sw, "failed to re-enable %s on upstream port\n",
- tb_switch_clx_name(TB_CL1));
-
- if (tb_switch_is_clx_enabled(sw, TB_CL1))
- /*
- * To support highest CLx state, we set router's TMU to
- * Normal-Uni mode.
- */
- tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_NORMAL, true);
- else
- /* If CLx disabled, configure router's TMU to HiFi-Bidir mode*/
- tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_HIFI, false);
+ if (tb_enable_clx(sw))
+ tb_sw_warn(sw, "failed to re-enable CL states\n");
if (tb_enable_tmu(sw))
tb_sw_warn(sw, "failed to restore TMU configuration\n");
+ tb_switch_configuration_valid(sw);
+
tb_switch_for_each_port(sw, port) {
if (!tb_port_has_remote(port) && !port->xdomain)
continue;
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 275ff5219a3a..57a9b272cb94 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -19,10 +19,6 @@
#include "ctl.h"
#include "dma_port.h"
-#define NVM_MIN_SIZE SZ_32K
-#define NVM_MAX_SIZE SZ_512K
-#define NVM_DATA_DWORDS 16
-
/* Keep link controller awake during update */
#define QUIRK_FORCE_POWER_LINK_CONTROLLER BIT(0)
/* Disable CLx if not supported */
@@ -77,51 +73,37 @@ enum tb_nvm_write_ops {
#define USB4_SWITCH_MAX_DEPTH 5
/**
- * enum tb_switch_tmu_rate - TMU refresh rate
- * @TB_SWITCH_TMU_RATE_OFF: %0 (Disable Time Sync handshake)
- * @TB_SWITCH_TMU_RATE_HIFI: %16 us time interval between successive
- * transmission of the Delay Request TSNOS
- * (Time Sync Notification Ordered Set) on a Link
- * @TB_SWITCH_TMU_RATE_NORMAL: %1 ms time interval between successive
- * transmission of the Delay Request TSNOS on
- * a Link
+ * enum tb_switch_tmu_mode - TMU mode
+ * @TB_SWITCH_TMU_MODE_OFF: TMU is off
+ * @TB_SWITCH_TMU_MODE_LOWRES: Uni-directional, normal mode
+ * @TB_SWITCH_TMU_MODE_HIFI_UNI: Uni-directional, HiFi mode
+ * @TB_SWITCH_TMU_MODE_HIFI_BI: Bi-directional, HiFi mode
+ * @TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI: Enhanced Uni-directional, MedRes mode
+ *
+ * Ordering is based on TMU accuracy level (highest last).
*/
-enum tb_switch_tmu_rate {
- TB_SWITCH_TMU_RATE_OFF = 0,
- TB_SWITCH_TMU_RATE_HIFI = 16,
- TB_SWITCH_TMU_RATE_NORMAL = 1000,
+enum tb_switch_tmu_mode {
+ TB_SWITCH_TMU_MODE_OFF,
+ TB_SWITCH_TMU_MODE_LOWRES,
+ TB_SWITCH_TMU_MODE_HIFI_UNI,
+ TB_SWITCH_TMU_MODE_HIFI_BI,
+ TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI,
};
/**
- * struct tb_switch_tmu - Structure holding switch TMU configuration
+ * struct tb_switch_tmu - Structure holding router TMU configuration
* @cap: Offset to the TMU capability (%0 if not found)
* @has_ucap: Does the switch support uni-directional mode
- * @rate: TMU refresh rate related to upstream switch. In case of root
- * switch this holds the domain rate. Reflects the HW setting.
- * @unidirectional: Is the TMU in uni-directional or bi-directional mode
- * related to upstream switch. Don't care for root switch.
- * Reflects the HW setting.
- * @unidirectional_request: Is the new TMU mode: uni-directional or bi-directional
- * that is requested to be set. Related to upstream switch.
- * Don't care for root switch.
- * @rate_request: TMU new refresh rate related to upstream switch that is
- * requested to be set. In case of root switch, this holds
- * the new domain rate that is requested to be set.
+ * @mode: TMU mode related to the upstream router. Reflects the HW
+ * setting. Don't care for host router.
+ * @mode_request: TMU mode requested to set. Related to upstream router.
+ * Don't care for host router.
*/
struct tb_switch_tmu {
int cap;
bool has_ucap;
- enum tb_switch_tmu_rate rate;
- bool unidirectional;
- bool unidirectional_request;
- enum tb_switch_tmu_rate rate_request;
-};
-
-enum tb_clx {
- TB_CLX_DISABLE,
- /* CL0s and CL1 are enabled and supported together */
- TB_CL1 = BIT(0),
- TB_CL2 = BIT(1),
+ enum tb_switch_tmu_mode mode;
+ enum tb_switch_tmu_mode mode_request;
};
/**
@@ -142,7 +124,7 @@ enum tb_clx {
* @vendor_name: Name of the vendor (or %NULL if not known)
* @device_name: Name of the device (or %NULL if not known)
* @link_speed: Speed of the link in Gb/s
- * @link_width: Width of the link (1 or 2)
+ * @link_width: Width of the upstream facing link
* @link_usb4: Upstream link is USB4
* @generation: Switch Thunderbolt generation
* @cap_plug_events: Offset to the plug events capability (%0 if not found)
@@ -174,12 +156,17 @@ enum tb_clx {
* @min_dp_main_credits: Router preferred minimum number of buffers for DP MAIN
* @max_pcie_credits: Router preferred number of buffers for PCIe
* @max_dma_credits: Router preferred number of buffers for DMA/P2P
- * @clx: CLx state on the upstream link of the router
+ * @clx: CLx states on the upstream link of the router
*
* When the switch is being added or removed to the domain (other
* switches) you need to have domain lock held.
*
* In USB4 terminology this structure represents a router.
+ *
+ * Note @link_width is not the same as whether link is bonded or not.
+ * For Gen 4 links the link is also bonded when it is asymmetric. The
+ * correct way to find out whether the link is bonded or not is to look
+ * @bonded field of the upstream port.
*/
struct tb_switch {
struct device dev;
@@ -195,7 +182,7 @@ struct tb_switch {
const char *vendor_name;
const char *device_name;
unsigned int link_speed;
- unsigned int link_width;
+ enum tb_link_width link_width;
bool link_usb4;
unsigned int generation;
int cap_plug_events;
@@ -225,7 +212,7 @@ struct tb_switch {
unsigned int min_dp_main_credits;
unsigned int max_pcie_credits;
unsigned int max_dma_credits;
- enum tb_clx clx;
+ unsigned int clx;
};
/**
@@ -455,6 +442,11 @@ struct tb_path {
#define TB_WAKE_ON_PCIE BIT(4)
#define TB_WAKE_ON_DP BIT(5)
+/* CL states */
+#define TB_CL0S BIT(0)
+#define TB_CL1 BIT(1)
+#define TB_CL2 BIT(2)
+
/**
* struct tb_cm_ops - Connection manager specific operations vector
* @driver_ready: Called right after control channel is started. Used by
@@ -802,6 +794,7 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, struct device *parent,
struct tb_switch *tb_switch_alloc_safe_mode(struct tb *tb,
struct device *parent, u64 route);
int tb_switch_configure(struct tb_switch *sw);
+int tb_switch_configuration_valid(struct tb_switch *sw);
int tb_switch_add(struct tb_switch *sw);
void tb_switch_remove(struct tb_switch *sw);
void tb_switch_suspend(struct tb_switch *sw, bool runtime);
@@ -857,6 +850,20 @@ static inline struct tb_switch *tb_switch_parent(struct tb_switch *sw)
return tb_to_switch(sw->dev.parent);
}
+/**
+ * tb_switch_downstream_port() - Return downstream facing port of parent router
+ * @sw: Device router pointer
+ *
+ * Only call for device routers. Returns the downstream facing port of
+ * the parent router.
+ */
+static inline struct tb_port *tb_switch_downstream_port(struct tb_switch *sw)
+{
+ if (WARN_ON(!tb_route(sw)))
+ return NULL;
+ return tb_port_at(tb_route(sw), tb_switch_parent(sw));
+}
+
static inline bool tb_switch_is_light_ridge(const struct tb_switch *sw)
{
return sw->config.vendor_id == PCI_VENDOR_ID_INTEL &&
@@ -936,17 +943,6 @@ static inline bool tb_switch_is_tiger_lake(const struct tb_switch *sw)
}
/**
- * tb_switch_is_usb4() - Is the switch USB4 compliant
- * @sw: Switch to check
- *
- * Returns true if the @sw is USB4 compliant router, false otherwise.
- */
-static inline bool tb_switch_is_usb4(const struct tb_switch *sw)
-{
- return sw->config.thunderbolt_version == USB4_VERSION_1_0;
-}
-
-/**
* tb_switch_is_icm() - Is the switch handled by ICM firmware
* @sw: Switch to check
*
@@ -973,68 +969,58 @@ int tb_switch_tmu_init(struct tb_switch *sw);
int tb_switch_tmu_post_time(struct tb_switch *sw);
int tb_switch_tmu_disable(struct tb_switch *sw);
int tb_switch_tmu_enable(struct tb_switch *sw);
-void tb_switch_tmu_configure(struct tb_switch *sw,
- enum tb_switch_tmu_rate rate,
- bool unidirectional);
-void tb_switch_enable_tmu_1st_child(struct tb_switch *sw,
- enum tb_switch_tmu_rate rate);
+int tb_switch_tmu_configure(struct tb_switch *sw, enum tb_switch_tmu_mode mode);
+
/**
- * tb_switch_tmu_is_enabled() - Checks if the specified TMU mode is enabled
- * @sw: Router whose TMU mode to check
- * @unidirectional: If uni-directional (bi-directional otherwise)
+ * tb_switch_tmu_is_configured() - Is given TMU mode configured
+ * @sw: Router whose mode to check
+ * @mode: Mode to check
*
- * Return true if hardware TMU configuration matches the one passed in
- * as parameter. That is HiFi/Normal and either uni-directional or bi-directional.
+ * Checks if given router TMU mode is configured to @mode. Note the
+ * router TMU might not be enabled to this mode.
*/
-static inline bool tb_switch_tmu_is_enabled(const struct tb_switch *sw,
- bool unidirectional)
+static inline bool tb_switch_tmu_is_configured(const struct tb_switch *sw,
+ enum tb_switch_tmu_mode mode)
{
- return sw->tmu.rate == sw->tmu.rate_request &&
- sw->tmu.unidirectional == unidirectional;
+ return sw->tmu.mode_request == mode;
}
-static inline const char *tb_switch_clx_name(enum tb_clx clx)
+/**
+ * tb_switch_tmu_is_enabled() - Checks if the specified TMU mode is enabled
+ * @sw: Router whose TMU mode to check
+ *
+ * Return true if hardware TMU configuration matches the requested
+ * configuration (and is not %TB_SWITCH_TMU_MODE_OFF).
+ */
+static inline bool tb_switch_tmu_is_enabled(const struct tb_switch *sw)
{
- switch (clx) {
- /* CL0s and CL1 are enabled and supported together */
- case TB_CL1:
- return "CL0s/CL1";
- default:
- return "unknown";
- }
+ return sw->tmu.mode != TB_SWITCH_TMU_MODE_OFF &&
+ sw->tmu.mode == sw->tmu.mode_request;
}
-int tb_switch_enable_clx(struct tb_switch *sw, enum tb_clx clx);
-int tb_switch_disable_clx(struct tb_switch *sw, enum tb_clx clx);
+bool tb_port_clx_is_enabled(struct tb_port *port, unsigned int clx);
+
+int tb_switch_clx_init(struct tb_switch *sw);
+bool tb_switch_clx_is_supported(const struct tb_switch *sw);
+int tb_switch_clx_enable(struct tb_switch *sw, unsigned int clx);
+int tb_switch_clx_disable(struct tb_switch *sw);
/**
- * tb_switch_is_clx_enabled() - Checks if the CLx is enabled
+ * tb_switch_clx_is_enabled() - Checks if the CLx is enabled
* @sw: Router to check for the CLx
- * @clx: The CLx state to check for
+ * @clx: The CLx states to check for
*
* Checks if the specified CLx is enabled on the router upstream link.
+ * Returns true if any of the given states is enabled.
+ *
* Not applicable for a host router.
*/
-static inline bool tb_switch_is_clx_enabled(const struct tb_switch *sw,
- enum tb_clx clx)
+static inline bool tb_switch_clx_is_enabled(const struct tb_switch *sw,
+ unsigned int clx)
{
- return sw->clx == clx;
+ return sw->clx & clx;
}
-/**
- * tb_switch_is_clx_supported() - Is CLx supported on this type of router
- * @sw: The router to check CLx support for
- */
-static inline bool tb_switch_is_clx_supported(const struct tb_switch *sw)
-{
- if (sw->quirks & QUIRK_NO_CLX)
- return false;
-
- return tb_switch_is_usb4(sw) || tb_switch_is_titan_ridge(sw);
-}
-
-int tb_switch_mask_clx_objections(struct tb_switch *sw);
-
int tb_switch_pcie_l1_enable(struct tb_switch *sw);
int tb_switch_xhci_connect(struct tb_switch *sw);
@@ -1073,14 +1059,12 @@ static inline bool tb_port_use_credit_allocation(const struct tb_port *port)
int tb_port_get_link_speed(struct tb_port *port);
int tb_port_get_link_width(struct tb_port *port);
-int tb_port_set_link_width(struct tb_port *port, unsigned int width);
-int tb_port_set_lane_bonding(struct tb_port *port, bool bonding);
+int tb_port_set_link_width(struct tb_port *port, enum tb_link_width width);
int tb_port_lane_bonding_enable(struct tb_port *port);
void tb_port_lane_bonding_disable(struct tb_port *port);
-int tb_port_wait_for_link_width(struct tb_port *port, int width,
+int tb_port_wait_for_link_width(struct tb_port *port, unsigned int width_mask,
int timeout_msec);
int tb_port_update_credits(struct tb_port *port);
-bool tb_port_is_clx_enabled(struct tb_port *port, unsigned int clx);
int tb_switch_find_vse_cap(struct tb_switch *sw, enum tb_switch_vse_cap vsec);
int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap);
@@ -1183,6 +1167,17 @@ static inline struct tb_switch *tb_xdomain_parent(struct tb_xdomain *xd)
return tb_to_switch(xd->dev.parent);
}
+/**
+ * tb_xdomain_downstream_port() - Return downstream facing port of parent router
+ * @xd: Xdomain pointer
+ *
+ * Returns the downstream port the XDomain is connected to.
+ */
+static inline struct tb_port *tb_xdomain_downstream_port(struct tb_xdomain *xd)
+{
+ return tb_port_at(xd->route, tb_xdomain_parent(xd));
+}
+
int tb_retimer_nvm_read(struct tb_retimer *rt, unsigned int address, void *buf,
size_t size);
int tb_retimer_scan(struct tb_port *port, bool add);
@@ -1200,7 +1195,31 @@ static inline struct tb_retimer *tb_to_retimer(struct device *dev)
return NULL;
}
+/**
+ * usb4_switch_version() - Returns USB4 version of the router
+ * @sw: Router to check
+ *
+ * Returns major version of USB4 router (%1 for v1, %2 for v2 and so
+ * on). Can be called to pre-USB4 router too and in that case returns %0.
+ */
+static inline unsigned int usb4_switch_version(const struct tb_switch *sw)
+{
+ return FIELD_GET(USB4_VERSION_MAJOR_MASK, sw->config.thunderbolt_version);
+}
+
+/**
+ * tb_switch_is_usb4() - Is the switch USB4 compliant
+ * @sw: Switch to check
+ *
+ * Returns true if the @sw is USB4 compliant router, false otherwise.
+ */
+static inline bool tb_switch_is_usb4(const struct tb_switch *sw)
+{
+ return usb4_switch_version(sw) > 0;
+}
+
int usb4_switch_setup(struct tb_switch *sw);
+int usb4_switch_configuration_valid(struct tb_switch *sw);
int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid);
int usb4_switch_drom_read(struct tb_switch *sw, unsigned int address, void *buf,
size_t size);
@@ -1273,19 +1292,22 @@ int usb4_usb3_port_release_bandwidth(struct tb_port *port, int *upstream_bw,
int *downstream_bw);
int usb4_dp_port_set_cm_id(struct tb_port *port, int cm_id);
-bool usb4_dp_port_bw_mode_supported(struct tb_port *port);
-bool usb4_dp_port_bw_mode_enabled(struct tb_port *port);
-int usb4_dp_port_set_cm_bw_mode_supported(struct tb_port *port, bool supported);
+bool usb4_dp_port_bandwidth_mode_supported(struct tb_port *port);
+bool usb4_dp_port_bandwidth_mode_enabled(struct tb_port *port);
+int usb4_dp_port_set_cm_bandwidth_mode_supported(struct tb_port *port,
+ bool supported);
int usb4_dp_port_group_id(struct tb_port *port);
int usb4_dp_port_set_group_id(struct tb_port *port, int group_id);
int usb4_dp_port_nrd(struct tb_port *port, int *rate, int *lanes);
int usb4_dp_port_set_nrd(struct tb_port *port, int rate, int lanes);
int usb4_dp_port_granularity(struct tb_port *port);
int usb4_dp_port_set_granularity(struct tb_port *port, int granularity);
-int usb4_dp_port_set_estimated_bw(struct tb_port *port, int bw);
-int usb4_dp_port_allocated_bw(struct tb_port *port);
-int usb4_dp_port_allocate_bw(struct tb_port *port, int bw);
-int usb4_dp_port_requested_bw(struct tb_port *port);
+int usb4_dp_port_set_estimated_bandwidth(struct tb_port *port, int bw);
+int usb4_dp_port_allocated_bandwidth(struct tb_port *port);
+int usb4_dp_port_allocate_bandwidth(struct tb_port *port, int bw);
+int usb4_dp_port_requested_bandwidth(struct tb_port *port);
+
+int usb4_pci_port_set_ext_encapsulation(struct tb_port *port, bool enable);
static inline bool tb_is_usb4_port_device(const struct device *dev)
{
@@ -1303,6 +1325,11 @@ struct usb4_port *usb4_port_device_add(struct tb_port *port);
void usb4_port_device_remove(struct usb4_port *usb4);
int usb4_port_device_resume(struct usb4_port *usb4);
+static inline bool usb4_port_device_is_offline(const struct usb4_port *usb4)
+{
+ return usb4->offline;
+}
+
void tb_check_quirks(struct tb_switch *sw);
#ifdef CONFIG_ACPI
diff --git a/drivers/thunderbolt/tb_msgs.h b/drivers/thunderbolt/tb_msgs.h
index 3234bff07899..cd750e4b3440 100644
--- a/drivers/thunderbolt/tb_msgs.h
+++ b/drivers/thunderbolt/tb_msgs.h
@@ -30,6 +30,13 @@ enum tb_cfg_error {
TB_CFG_ERROR_FLOW_CONTROL_ERROR = 13,
TB_CFG_ERROR_LOCK = 15,
TB_CFG_ERROR_DP_BW = 32,
+ TB_CFG_ERROR_ROP_CMPLT = 33,
+ TB_CFG_ERROR_POP_CMPLT = 34,
+ TB_CFG_ERROR_PCIE_WAKE = 35,
+ TB_CFG_ERROR_DP_CON_CHANGE = 36,
+ TB_CFG_ERROR_DPTX_DISCOVERY = 37,
+ TB_CFG_ERROR_LINK_RECOVERY = 38,
+ TB_CFG_ERROR_ASYM_LINK = 39,
};
/* common header */
diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h
index 2636423748cd..cf9f2370878a 100644
--- a/drivers/thunderbolt/tb_regs.h
+++ b/drivers/thunderbolt/tb_regs.h
@@ -190,11 +190,14 @@ struct tb_regs_switch_header {
u32 thunderbolt_version:8;
} __packed;
-/* USB4 version 1.0 */
-#define USB4_VERSION_1_0 0x20
+/* Used with the router thunderbolt_version */
+#define USB4_VERSION_MAJOR_MASK GENMASK(7, 5)
#define ROUTER_CS_1 0x01
#define ROUTER_CS_4 0x04
+/* Used with the router cmuv field */
+#define ROUTER_CS_4_CMUV_V1 0x10
+#define ROUTER_CS_4_CMUV_V2 0x20
#define ROUTER_CS_5 0x05
#define ROUTER_CS_5_SLP BIT(0)
#define ROUTER_CS_5_WOP BIT(1)
@@ -249,11 +252,13 @@ enum usb4_switch_op {
#define TMU_RTR_CS_3_LOCAL_TIME_NS_MASK GENMASK(15, 0)
#define TMU_RTR_CS_3_TS_PACKET_INTERVAL_MASK GENMASK(31, 16)
#define TMU_RTR_CS_3_TS_PACKET_INTERVAL_SHIFT 16
-#define TMU_RTR_CS_15 0xf
+#define TMU_RTR_CS_15 0x0f
#define TMU_RTR_CS_15_FREQ_AVG_MASK GENMASK(5, 0)
#define TMU_RTR_CS_15_DELAY_AVG_MASK GENMASK(11, 6)
#define TMU_RTR_CS_15_OFFSET_AVG_MASK GENMASK(17, 12)
#define TMU_RTR_CS_15_ERROR_AVG_MASK GENMASK(23, 18)
+#define TMU_RTR_CS_18 0x12
+#define TMU_RTR_CS_18_DELTA_AVG_CONST_MASK GENMASK(23, 16)
#define TMU_RTR_CS_22 0x16
#define TMU_RTR_CS_24 0x18
#define TMU_RTR_CS_25 0x19
@@ -319,6 +324,14 @@ struct tb_regs_port_header {
#define TMU_ADP_CS_3_UDM BIT(29)
#define TMU_ADP_CS_6 0x06
#define TMU_ADP_CS_6_DTS BIT(1)
+#define TMU_ADP_CS_8 0x08
+#define TMU_ADP_CS_8_REPL_TIMEOUT_MASK GENMASK(14, 0)
+#define TMU_ADP_CS_8_EUDM BIT(15)
+#define TMU_ADP_CS_8_REPL_THRESHOLD_MASK GENMASK(25, 16)
+#define TMU_ADP_CS_9 0x09
+#define TMU_ADP_CS_9_REPL_N_MASK GENMASK(7, 0)
+#define TMU_ADP_CS_9_DIRSWITCH_N_MASK GENMASK(15, 8)
+#define TMU_ADP_CS_9_ADP_TS_INTERVAL_MASK GENMASK(31, 16)
/* Lane adapter registers */
#define LANE_ADP_CS_0 0x00
@@ -346,6 +359,7 @@ struct tb_regs_port_header {
#define LANE_ADP_CS_1_CURRENT_SPEED_SHIFT 16
#define LANE_ADP_CS_1_CURRENT_SPEED_GEN2 0x8
#define LANE_ADP_CS_1_CURRENT_SPEED_GEN3 0x4
+#define LANE_ADP_CS_1_CURRENT_SPEED_GEN4 0x2
#define LANE_ADP_CS_1_CURRENT_WIDTH_MASK GENMASK(25, 20)
#define LANE_ADP_CS_1_CURRENT_WIDTH_SHIFT 20
#define LANE_ADP_CS_1_PMS BIT(30)
@@ -436,6 +450,9 @@ struct tb_regs_port_header {
#define DP_COMMON_CAP_1_LANE 0x0
#define DP_COMMON_CAP_2_LANES 0x1
#define DP_COMMON_CAP_4_LANES 0x2
+#define DP_COMMON_CAP_UHBR10 BIT(17)
+#define DP_COMMON_CAP_UHBR20 BIT(18)
+#define DP_COMMON_CAP_UHBR13_5 BIT(19)
#define DP_COMMON_CAP_LTTPR_NS BIT(27)
#define DP_COMMON_CAP_BW_MODE BIT(28)
#define DP_COMMON_CAP_DPRX_DONE BIT(31)
@@ -447,6 +464,8 @@ struct tb_regs_port_header {
/* PCIe adapter registers */
#define ADP_PCIE_CS_0 0x00
#define ADP_PCIE_CS_0_PE BIT(31)
+#define ADP_PCIE_CS_1 0x01
+#define ADP_PCIE_CS_1_EE BIT(0)
/* USB adapter registers */
#define ADP_USB3_CS_0 0x00
diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c
index 24c06e7354cd..9475c6698c7d 100644
--- a/drivers/thunderbolt/test.c
+++ b/drivers/thunderbolt/test.c
@@ -170,6 +170,23 @@ static struct tb_switch *alloc_host_usb4(struct kunit *test)
return sw;
}
+static struct tb_switch *alloc_host_br(struct kunit *test)
+{
+ struct tb_switch *sw;
+
+ sw = alloc_host_usb4(test);
+ if (!sw)
+ return NULL;
+
+ sw->ports[10].config.type = TB_TYPE_DP_HDMI_IN;
+ sw->ports[10].config.max_in_hop_id = 9;
+ sw->ports[10].config.max_out_hop_id = 9;
+ sw->ports[10].cap_adap = -1;
+ sw->ports[10].disabled = false;
+
+ return sw;
+}
+
static struct tb_switch *alloc_dev_default(struct kunit *test,
struct tb_switch *parent,
u64 route, bool bonded)
@@ -1583,6 +1600,71 @@ static void tb_test_tunnel_dp_max_length(struct kunit *test)
tb_tunnel_free(tunnel);
}
+static void tb_test_tunnel_3dp(struct kunit *test)
+{
+ struct tb_switch *host, *dev1, *dev2, *dev3, *dev4, *dev5;
+ struct tb_port *in1, *in2, *in3, *out1, *out2, *out3;
+ struct tb_tunnel *tunnel1, *tunnel2, *tunnel3;
+
+ /*
+ * Create 3 DP tunnels from Host to Devices #2, #5 and #4.
+ *
+ * [Host]
+ * 3 |
+ * 1 |
+ * [Device #1]
+ * 3 / | 5 \ 7
+ * 1 / | \ 1
+ * [Device #2] | [Device #4]
+ * | 1
+ * [Device #3]
+ * | 5
+ * | 1
+ * [Device #5]
+ */
+ host = alloc_host_br(test);
+ dev1 = alloc_dev_default(test, host, 0x3, true);
+ dev2 = alloc_dev_default(test, dev1, 0x303, true);
+ dev3 = alloc_dev_default(test, dev1, 0x503, true);
+ dev4 = alloc_dev_default(test, dev1, 0x703, true);
+ dev5 = alloc_dev_default(test, dev3, 0x50503, true);
+
+ in1 = &host->ports[5];
+ in2 = &host->ports[6];
+ in3 = &host->ports[10];
+
+ out1 = &dev2->ports[13];
+ out2 = &dev5->ports[13];
+ out3 = &dev4->ports[14];
+
+ tunnel1 = tb_tunnel_alloc_dp(NULL, in1, out1, 1, 0, 0);
+ KUNIT_ASSERT_TRUE(test, tunnel1 != NULL);
+ KUNIT_EXPECT_EQ(test, tunnel1->type, TB_TUNNEL_DP);
+ KUNIT_EXPECT_PTR_EQ(test, tunnel1->src_port, in1);
+ KUNIT_EXPECT_PTR_EQ(test, tunnel1->dst_port, out1);
+ KUNIT_ASSERT_EQ(test, tunnel1->npaths, 3);
+ KUNIT_ASSERT_EQ(test, tunnel1->paths[0]->path_length, 3);
+
+ tunnel2 = tb_tunnel_alloc_dp(NULL, in2, out2, 1, 0, 0);
+ KUNIT_ASSERT_TRUE(test, tunnel2 != NULL);
+ KUNIT_EXPECT_EQ(test, tunnel2->type, TB_TUNNEL_DP);
+ KUNIT_EXPECT_PTR_EQ(test, tunnel2->src_port, in2);
+ KUNIT_EXPECT_PTR_EQ(test, tunnel2->dst_port, out2);
+ KUNIT_ASSERT_EQ(test, tunnel2->npaths, 3);
+ KUNIT_ASSERT_EQ(test, tunnel2->paths[0]->path_length, 4);
+
+ tunnel3 = tb_tunnel_alloc_dp(NULL, in3, out3, 1, 0, 0);
+ KUNIT_ASSERT_TRUE(test, tunnel3 != NULL);
+ KUNIT_EXPECT_EQ(test, tunnel3->type, TB_TUNNEL_DP);
+ KUNIT_EXPECT_PTR_EQ(test, tunnel3->src_port, in3);
+ KUNIT_EXPECT_PTR_EQ(test, tunnel3->dst_port, out3);
+ KUNIT_ASSERT_EQ(test, tunnel3->npaths, 3);
+ KUNIT_ASSERT_EQ(test, tunnel3->paths[0]->path_length, 3);
+
+ tb_tunnel_free(tunnel2);
+ tb_tunnel_free(tunnel1);
+}
+
static void tb_test_tunnel_usb3(struct kunit *test)
{
struct tb_switch *host, *dev1, *dev2;
@@ -2790,6 +2872,7 @@ static struct kunit_case tb_test_cases[] = {
KUNIT_CASE(tb_test_tunnel_dp_chain),
KUNIT_CASE(tb_test_tunnel_dp_tree),
KUNIT_CASE(tb_test_tunnel_dp_max_length),
+ KUNIT_CASE(tb_test_tunnel_3dp),
KUNIT_CASE(tb_test_tunnel_port_on_path),
KUNIT_CASE(tb_test_tunnel_usb3),
KUNIT_CASE(tb_test_tunnel_dma),
diff --git a/drivers/thunderbolt/tmu.c b/drivers/thunderbolt/tmu.c
index 626aca3124b1..1269f417515b 100644
--- a/drivers/thunderbolt/tmu.c
+++ b/drivers/thunderbolt/tmu.c
@@ -11,23 +11,63 @@
#include "tb.h"
+static const unsigned int tmu_rates[] = {
+ [TB_SWITCH_TMU_MODE_OFF] = 0,
+ [TB_SWITCH_TMU_MODE_LOWRES] = 1000,
+ [TB_SWITCH_TMU_MODE_HIFI_UNI] = 16,
+ [TB_SWITCH_TMU_MODE_HIFI_BI] = 16,
+ [TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI] = 16,
+};
+
+const struct {
+ unsigned int freq_meas_window;
+ unsigned int avg_const;
+ unsigned int delta_avg_const;
+ unsigned int repl_timeout;
+ unsigned int repl_threshold;
+ unsigned int repl_n;
+ unsigned int dirswitch_n;
+} tmu_params[] = {
+ [TB_SWITCH_TMU_MODE_OFF] = { },
+ [TB_SWITCH_TMU_MODE_LOWRES] = { 30, 4, },
+ [TB_SWITCH_TMU_MODE_HIFI_UNI] = { 800, 8, },
+ [TB_SWITCH_TMU_MODE_HIFI_BI] = { 800, 8, },
+ [TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI] = {
+ 800, 4, 0, 3125, 25, 128, 255,
+ },
+};
+
+static const char *tmu_mode_name(enum tb_switch_tmu_mode mode)
+{
+ switch (mode) {
+ case TB_SWITCH_TMU_MODE_OFF:
+ return "off";
+ case TB_SWITCH_TMU_MODE_LOWRES:
+ return "uni-directional, LowRes";
+ case TB_SWITCH_TMU_MODE_HIFI_UNI:
+ return "uni-directional, HiFi";
+ case TB_SWITCH_TMU_MODE_HIFI_BI:
+ return "bi-directional, HiFi";
+ case TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI:
+ return "enhanced uni-directional, MedRes";
+ default:
+ return "unknown";
+ }
+}
+
+static bool tb_switch_tmu_enhanced_is_supported(const struct tb_switch *sw)
+{
+ return usb4_switch_version(sw) > 1;
+}
+
static int tb_switch_set_tmu_mode_params(struct tb_switch *sw,
- enum tb_switch_tmu_rate rate)
+ enum tb_switch_tmu_mode mode)
{
- u32 freq_meas_wind[2] = { 30, 800 };
- u32 avg_const[2] = { 4, 8 };
u32 freq, avg, val;
int ret;
- if (rate == TB_SWITCH_TMU_RATE_NORMAL) {
- freq = freq_meas_wind[0];
- avg = avg_const[0];
- } else if (rate == TB_SWITCH_TMU_RATE_HIFI) {
- freq = freq_meas_wind[1];
- avg = avg_const[1];
- } else {
- return 0;
- }
+ freq = tmu_params[mode].freq_meas_window;
+ avg = tmu_params[mode].avg_const;
ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
sw->tmu.cap + TMU_RTR_CS_0, 1);
@@ -56,37 +96,30 @@ static int tb_switch_set_tmu_mode_params(struct tb_switch *sw,
FIELD_PREP(TMU_RTR_CS_15_OFFSET_AVG_MASK, avg) |
FIELD_PREP(TMU_RTR_CS_15_ERROR_AVG_MASK, avg);
- return tb_sw_write(sw, &val, TB_CFG_SWITCH,
- sw->tmu.cap + TMU_RTR_CS_15, 1);
-}
-
-static const char *tb_switch_tmu_mode_name(const struct tb_switch *sw)
-{
- bool root_switch = !tb_route(sw);
+ ret = tb_sw_write(sw, &val, TB_CFG_SWITCH,
+ sw->tmu.cap + TMU_RTR_CS_15, 1);
+ if (ret)
+ return ret;
- switch (sw->tmu.rate) {
- case TB_SWITCH_TMU_RATE_OFF:
- return "off";
+ if (tb_switch_tmu_enhanced_is_supported(sw)) {
+ u32 delta_avg = tmu_params[mode].delta_avg_const;
- case TB_SWITCH_TMU_RATE_HIFI:
- /* Root switch does not have upstream directionality */
- if (root_switch)
- return "HiFi";
- if (sw->tmu.unidirectional)
- return "uni-directional, HiFi";
- return "bi-directional, HiFi";
+ ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
+ sw->tmu.cap + TMU_RTR_CS_18, 1);
+ if (ret)
+ return ret;
- case TB_SWITCH_TMU_RATE_NORMAL:
- if (root_switch)
- return "normal";
- return "uni-directional, normal";
+ val &= ~TMU_RTR_CS_18_DELTA_AVG_CONST_MASK;
+ val |= FIELD_PREP(TMU_RTR_CS_18_DELTA_AVG_CONST_MASK, delta_avg);
- default:
- return "unknown";
+ ret = tb_sw_write(sw, &val, TB_CFG_SWITCH,
+ sw->tmu.cap + TMU_RTR_CS_18, 1);
}
+
+ return ret;
}
-static bool tb_switch_tmu_ucap_supported(struct tb_switch *sw)
+static bool tb_switch_tmu_ucap_is_supported(struct tb_switch *sw)
{
int ret;
u32 val;
@@ -182,6 +215,103 @@ static bool tb_port_tmu_is_unidirectional(struct tb_port *port)
return val & TMU_ADP_CS_3_UDM;
}
+static bool tb_port_tmu_is_enhanced(struct tb_port *port)
+{
+ int ret;
+ u32 val;
+
+ ret = tb_port_read(port, &val, TB_CFG_PORT,
+ port->cap_tmu + TMU_ADP_CS_8, 1);
+ if (ret)
+ return false;
+
+ return val & TMU_ADP_CS_8_EUDM;
+}
+
+/* Can be called to non-v2 lane adapters too */
+static int tb_port_tmu_enhanced_enable(struct tb_port *port, bool enable)
+{
+ int ret;
+ u32 val;
+
+ if (!tb_switch_tmu_enhanced_is_supported(port->sw))
+ return 0;
+
+ ret = tb_port_read(port, &val, TB_CFG_PORT,
+ port->cap_tmu + TMU_ADP_CS_8, 1);
+ if (ret)
+ return ret;
+
+ if (enable)
+ val |= TMU_ADP_CS_8_EUDM;
+ else
+ val &= ~TMU_ADP_CS_8_EUDM;
+
+ return tb_port_write(port, &val, TB_CFG_PORT,
+ port->cap_tmu + TMU_ADP_CS_8, 1);
+}
+
+static int tb_port_set_tmu_mode_params(struct tb_port *port,
+ enum tb_switch_tmu_mode mode)
+{
+ u32 repl_timeout, repl_threshold, repl_n, dirswitch_n, val;
+ int ret;
+
+ repl_timeout = tmu_params[mode].repl_timeout;
+ repl_threshold = tmu_params[mode].repl_threshold;
+ repl_n = tmu_params[mode].repl_n;
+ dirswitch_n = tmu_params[mode].dirswitch_n;
+
+ ret = tb_port_read(port, &val, TB_CFG_PORT,
+ port->cap_tmu + TMU_ADP_CS_8, 1);
+ if (ret)
+ return ret;
+
+ val &= ~TMU_ADP_CS_8_REPL_TIMEOUT_MASK;
+ val &= ~TMU_ADP_CS_8_REPL_THRESHOLD_MASK;
+ val |= FIELD_PREP(TMU_ADP_CS_8_REPL_TIMEOUT_MASK, repl_timeout);
+ val |= FIELD_PREP(TMU_ADP_CS_8_REPL_THRESHOLD_MASK, repl_threshold);
+
+ ret = tb_port_write(port, &val, TB_CFG_PORT,
+ port->cap_tmu + TMU_ADP_CS_8, 1);
+ if (ret)
+ return ret;
+
+ ret = tb_port_read(port, &val, TB_CFG_PORT,
+ port->cap_tmu + TMU_ADP_CS_9, 1);
+ if (ret)
+ return ret;
+
+ val &= ~TMU_ADP_CS_9_REPL_N_MASK;
+ val &= ~TMU_ADP_CS_9_DIRSWITCH_N_MASK;
+ val |= FIELD_PREP(TMU_ADP_CS_9_REPL_N_MASK, repl_n);
+ val |= FIELD_PREP(TMU_ADP_CS_9_DIRSWITCH_N_MASK, dirswitch_n);
+
+ return tb_port_write(port, &val, TB_CFG_PORT,
+ port->cap_tmu + TMU_ADP_CS_9, 1);
+}
+
+/* Can be called to non-v2 lane adapters too */
+static int tb_port_tmu_rate_write(struct tb_port *port, int rate)
+{
+ int ret;
+ u32 val;
+
+ if (!tb_switch_tmu_enhanced_is_supported(port->sw))
+ return 0;
+
+ ret = tb_port_read(port, &val, TB_CFG_PORT,
+ port->cap_tmu + TMU_ADP_CS_9, 1);
+ if (ret)
+ return ret;
+
+ val &= ~TMU_ADP_CS_9_ADP_TS_INTERVAL_MASK;
+ val |= FIELD_PREP(TMU_ADP_CS_9_ADP_TS_INTERVAL_MASK, rate);
+
+ return tb_port_write(port, &val, TB_CFG_PORT,
+ port->cap_tmu + TMU_ADP_CS_9, 1);
+}
+
static int tb_port_tmu_time_sync(struct tb_port *port, bool time_sync)
{
u32 val = time_sync ? TMU_ADP_CS_6_DTS : 0;
@@ -224,6 +354,50 @@ static int tb_switch_tmu_set_time_disruption(struct tb_switch *sw, bool set)
return tb_sw_write(sw, &val, TB_CFG_SWITCH, offset, 1);
}
+static int tmu_mode_init(struct tb_switch *sw)
+{
+ bool enhanced, ucap;
+ int ret, rate;
+
+ ucap = tb_switch_tmu_ucap_is_supported(sw);
+ if (ucap)
+ tb_sw_dbg(sw, "TMU: supports uni-directional mode\n");
+ enhanced = tb_switch_tmu_enhanced_is_supported(sw);
+ if (enhanced)
+ tb_sw_dbg(sw, "TMU: supports enhanced uni-directional mode\n");
+
+ ret = tb_switch_tmu_rate_read(sw);
+ if (ret < 0)
+ return ret;
+ rate = ret;
+
+ /* Off by default */
+ sw->tmu.mode = TB_SWITCH_TMU_MODE_OFF;
+
+ if (tb_route(sw)) {
+ struct tb_port *up = tb_upstream_port(sw);
+
+ if (enhanced && tb_port_tmu_is_enhanced(up)) {
+ sw->tmu.mode = TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI;
+ } else if (ucap && tb_port_tmu_is_unidirectional(up)) {
+ if (tmu_rates[TB_SWITCH_TMU_MODE_LOWRES] == rate)
+ sw->tmu.mode = TB_SWITCH_TMU_MODE_LOWRES;
+ else if (tmu_rates[TB_SWITCH_TMU_MODE_LOWRES] == rate)
+ sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_UNI;
+ } else if (rate) {
+ sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_BI;
+ }
+ } else if (rate) {
+ sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_BI;
+ }
+
+ /* Update the initial request to match the current mode */
+ sw->tmu.mode_request = sw->tmu.mode;
+ sw->tmu.has_ucap = ucap;
+
+ return 0;
+}
+
/**
* tb_switch_tmu_init() - Initialize switch TMU structures
* @sw: Switch to initialized
@@ -252,27 +426,11 @@ int tb_switch_tmu_init(struct tb_switch *sw)
port->cap_tmu = cap;
}
- ret = tb_switch_tmu_rate_read(sw);
- if (ret < 0)
+ ret = tmu_mode_init(sw);
+ if (ret)
return ret;
- sw->tmu.rate = ret;
-
- sw->tmu.has_ucap = tb_switch_tmu_ucap_supported(sw);
- if (sw->tmu.has_ucap) {
- tb_sw_dbg(sw, "TMU: supports uni-directional mode\n");
-
- if (tb_route(sw)) {
- struct tb_port *up = tb_upstream_port(sw);
-
- sw->tmu.unidirectional =
- tb_port_tmu_is_unidirectional(up);
- }
- } else {
- sw->tmu.unidirectional = false;
- }
-
- tb_sw_dbg(sw, "TMU: current mode: %s\n", tb_switch_tmu_mode_name(sw));
+ tb_sw_dbg(sw, "TMU: current mode: %s\n", tmu_mode_name(sw->tmu.mode));
return 0;
}
@@ -308,7 +466,7 @@ int tb_switch_tmu_post_time(struct tb_switch *sw)
return ret;
for (i = 0; i < ARRAY_SIZE(gm_local_time); i++)
- tb_sw_dbg(root_switch, "local_time[%d]=0x%08x\n", i,
+ tb_sw_dbg(root_switch, "TMU: local_time[%d]=0x%08x\n", i,
gm_local_time[i]);
/* Convert to nanoseconds (drop fractional part) */
@@ -375,6 +533,23 @@ out:
return ret;
}
+static int disable_enhanced(struct tb_port *up, struct tb_port *down)
+{
+ int ret;
+
+ /*
+ * Router may already been disconnected so ignore errors on the
+ * upstream port.
+ */
+ tb_port_tmu_rate_write(up, 0);
+ tb_port_tmu_enhanced_enable(up, false);
+
+ ret = tb_port_tmu_rate_write(down, 0);
+ if (ret)
+ return ret;
+ return tb_port_tmu_enhanced_enable(down, false);
+}
+
/**
* tb_switch_tmu_disable() - Disable TMU of a switch
* @sw: Switch whose TMU to disable
@@ -383,26 +558,15 @@ out:
*/
int tb_switch_tmu_disable(struct tb_switch *sw)
{
- /*
- * No need to disable TMU on devices that don't support CLx since
- * on these devices e.g. Alpine Ridge and earlier, the TMU mode
- * HiFi bi-directional is enabled by default and we don't change it.
- */
- if (!tb_switch_is_clx_supported(sw))
- return 0;
-
/* Already disabled? */
- if (sw->tmu.rate == TB_SWITCH_TMU_RATE_OFF)
+ if (sw->tmu.mode == TB_SWITCH_TMU_MODE_OFF)
return 0;
-
if (tb_route(sw)) {
- bool unidirectional = sw->tmu.unidirectional;
- struct tb_switch *parent = tb_switch_parent(sw);
struct tb_port *down, *up;
int ret;
- down = tb_port_at(tb_route(sw), parent);
+ down = tb_switch_downstream_port(sw);
up = tb_upstream_port(sw);
/*
* In case of uni-directional time sync, TMU handshake is
@@ -415,37 +579,49 @@ int tb_switch_tmu_disable(struct tb_switch *sw)
* uni-directional mode and we don't want to change it's TMU
* mode.
*/
- tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF);
+ tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]);
tb_port_tmu_time_sync_disable(up);
ret = tb_port_tmu_time_sync_disable(down);
if (ret)
return ret;
- if (unidirectional) {
+ switch (sw->tmu.mode) {
+ case TB_SWITCH_TMU_MODE_LOWRES:
+ case TB_SWITCH_TMU_MODE_HIFI_UNI:
/* The switch may be unplugged so ignore any errors */
tb_port_tmu_unidirectional_disable(up);
ret = tb_port_tmu_unidirectional_disable(down);
if (ret)
return ret;
+ break;
+
+ case TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI:
+ ret = disable_enhanced(up, down);
+ if (ret)
+ return ret;
+ break;
+
+ default:
+ break;
}
} else {
- tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF);
+ tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]);
}
- sw->tmu.unidirectional = false;
- sw->tmu.rate = TB_SWITCH_TMU_RATE_OFF;
+ sw->tmu.mode = TB_SWITCH_TMU_MODE_OFF;
tb_sw_dbg(sw, "TMU: disabled\n");
return 0;
}
-static void __tb_switch_tmu_off(struct tb_switch *sw, bool unidirectional)
+/* Called only when there is failure enabling requested mode */
+static void tb_switch_tmu_off(struct tb_switch *sw)
{
- struct tb_switch *parent = tb_switch_parent(sw);
+ unsigned int rate = tmu_rates[TB_SWITCH_TMU_MODE_OFF];
struct tb_port *down, *up;
- down = tb_port_at(tb_route(sw), parent);
+ down = tb_switch_downstream_port(sw);
up = tb_upstream_port(sw);
/*
* In case of any failure in one of the steps when setting
@@ -456,28 +632,38 @@ static void __tb_switch_tmu_off(struct tb_switch *sw, bool unidirectional)
*/
tb_port_tmu_time_sync_disable(down);
tb_port_tmu_time_sync_disable(up);
- if (unidirectional)
- tb_switch_tmu_rate_write(parent, TB_SWITCH_TMU_RATE_OFF);
- else
- tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF);
- tb_switch_set_tmu_mode_params(sw, sw->tmu.rate);
+ switch (sw->tmu.mode_request) {
+ case TB_SWITCH_TMU_MODE_LOWRES:
+ case TB_SWITCH_TMU_MODE_HIFI_UNI:
+ tb_switch_tmu_rate_write(tb_switch_parent(sw), rate);
+ break;
+ case TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI:
+ disable_enhanced(up, down);
+ break;
+ default:
+ break;
+ }
+
+ /* Always set the rate to 0 */
+ tb_switch_tmu_rate_write(sw, rate);
+
+ tb_switch_set_tmu_mode_params(sw, sw->tmu.mode);
tb_port_tmu_unidirectional_disable(down);
tb_port_tmu_unidirectional_disable(up);
}
/*
* This function is called when the previous TMU mode was
- * TB_SWITCH_TMU_RATE_OFF.
+ * TB_SWITCH_TMU_MODE_OFF.
*/
-static int __tb_switch_tmu_enable_bidirectional(struct tb_switch *sw)
+static int tb_switch_tmu_enable_bidirectional(struct tb_switch *sw)
{
- struct tb_switch *parent = tb_switch_parent(sw);
struct tb_port *up, *down;
int ret;
up = tb_upstream_port(sw);
- down = tb_port_at(tb_route(sw), parent);
+ down = tb_switch_downstream_port(sw);
ret = tb_port_tmu_unidirectional_disable(up);
if (ret)
@@ -487,7 +673,7 @@ static int __tb_switch_tmu_enable_bidirectional(struct tb_switch *sw)
if (ret)
goto out;
- ret = tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_HIFI);
+ ret = tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_HIFI_BI]);
if (ret)
goto out;
@@ -502,12 +688,14 @@ static int __tb_switch_tmu_enable_bidirectional(struct tb_switch *sw)
return 0;
out:
- __tb_switch_tmu_off(sw, false);
+ tb_switch_tmu_off(sw);
return ret;
}
-static int tb_switch_tmu_objection_mask(struct tb_switch *sw)
+/* Only needed for Titan Ridge */
+static int tb_switch_tmu_disable_objections(struct tb_switch *sw)
{
+ struct tb_port *up = tb_upstream_port(sw);
u32 val;
int ret;
@@ -518,36 +706,34 @@ static int tb_switch_tmu_objection_mask(struct tb_switch *sw)
val &= ~TB_TIME_VSEC_3_CS_9_TMU_OBJ_MASK;
- return tb_sw_write(sw, &val, TB_CFG_SWITCH,
- sw->cap_vsec_tmu + TB_TIME_VSEC_3_CS_9, 1);
-}
-
-static int tb_switch_tmu_unidirectional_enable(struct tb_switch *sw)
-{
- struct tb_port *up = tb_upstream_port(sw);
+ ret = tb_sw_write(sw, &val, TB_CFG_SWITCH,
+ sw->cap_vsec_tmu + TB_TIME_VSEC_3_CS_9, 1);
+ if (ret)
+ return ret;
return tb_port_tmu_write(up, TMU_ADP_CS_6,
TMU_ADP_CS_6_DISABLE_TMU_OBJ_MASK,
- TMU_ADP_CS_6_DISABLE_TMU_OBJ_MASK);
+ TMU_ADP_CS_6_DISABLE_TMU_OBJ_CL1 |
+ TMU_ADP_CS_6_DISABLE_TMU_OBJ_CL2);
}
/*
* This function is called when the previous TMU mode was
- * TB_SWITCH_TMU_RATE_OFF.
+ * TB_SWITCH_TMU_MODE_OFF.
*/
-static int __tb_switch_tmu_enable_unidirectional(struct tb_switch *sw)
+static int tb_switch_tmu_enable_unidirectional(struct tb_switch *sw)
{
- struct tb_switch *parent = tb_switch_parent(sw);
struct tb_port *up, *down;
int ret;
up = tb_upstream_port(sw);
- down = tb_port_at(tb_route(sw), parent);
- ret = tb_switch_tmu_rate_write(parent, sw->tmu.rate_request);
+ down = tb_switch_downstream_port(sw);
+ ret = tb_switch_tmu_rate_write(tb_switch_parent(sw),
+ tmu_rates[sw->tmu.mode_request]);
if (ret)
return ret;
- ret = tb_switch_set_tmu_mode_params(sw, sw->tmu.rate_request);
+ ret = tb_switch_set_tmu_mode_params(sw, sw->tmu.mode_request);
if (ret)
return ret;
@@ -570,16 +756,65 @@ static int __tb_switch_tmu_enable_unidirectional(struct tb_switch *sw)
return 0;
out:
- __tb_switch_tmu_off(sw, true);
+ tb_switch_tmu_off(sw);
+ return ret;
+}
+
+/*
+ * This function is called when the previous TMU mode was
+ * TB_SWITCH_TMU_RATE_OFF.
+ */
+static int tb_switch_tmu_enable_enhanced(struct tb_switch *sw)
+{
+ unsigned int rate = tmu_rates[sw->tmu.mode_request];
+ struct tb_port *up, *down;
+ int ret;
+
+ /* Router specific parameters first */
+ ret = tb_switch_set_tmu_mode_params(sw, sw->tmu.mode_request);
+ if (ret)
+ return ret;
+
+ up = tb_upstream_port(sw);
+ down = tb_switch_downstream_port(sw);
+
+ ret = tb_port_set_tmu_mode_params(up, sw->tmu.mode_request);
+ if (ret)
+ goto out;
+
+ ret = tb_port_tmu_rate_write(up, rate);
+ if (ret)
+ goto out;
+
+ ret = tb_port_tmu_enhanced_enable(up, true);
+ if (ret)
+ goto out;
+
+ ret = tb_port_set_tmu_mode_params(down, sw->tmu.mode_request);
+ if (ret)
+ goto out;
+
+ ret = tb_port_tmu_rate_write(down, rate);
+ if (ret)
+ goto out;
+
+ ret = tb_port_tmu_enhanced_enable(down, true);
+ if (ret)
+ goto out;
+
+ return 0;
+
+out:
+ tb_switch_tmu_off(sw);
return ret;
}
-static void __tb_switch_tmu_change_mode_prev(struct tb_switch *sw)
+static void tb_switch_tmu_change_mode_prev(struct tb_switch *sw)
{
- struct tb_switch *parent = tb_switch_parent(sw);
+ unsigned int rate = tmu_rates[sw->tmu.mode];
struct tb_port *down, *up;
- down = tb_port_at(tb_route(sw), parent);
+ down = tb_switch_downstream_port(sw);
up = tb_upstream_port(sw);
/*
* In case of any failure in one of the steps when change mode,
@@ -587,42 +822,97 @@ static void __tb_switch_tmu_change_mode_prev(struct tb_switch *sw)
* In case of additional failures in the functions below,
* ignore them since the caller shall already report a failure.
*/
- tb_port_tmu_set_unidirectional(down, sw->tmu.unidirectional);
- if (sw->tmu.unidirectional_request)
- tb_switch_tmu_rate_write(parent, sw->tmu.rate);
- else
- tb_switch_tmu_rate_write(sw, sw->tmu.rate);
+ switch (sw->tmu.mode) {
+ case TB_SWITCH_TMU_MODE_LOWRES:
+ case TB_SWITCH_TMU_MODE_HIFI_UNI:
+ tb_port_tmu_set_unidirectional(down, true);
+ tb_switch_tmu_rate_write(tb_switch_parent(sw), rate);
+ break;
+
+ case TB_SWITCH_TMU_MODE_HIFI_BI:
+ tb_port_tmu_set_unidirectional(down, false);
+ tb_switch_tmu_rate_write(sw, rate);
+ break;
+
+ default:
+ break;
+ }
+
+ tb_switch_set_tmu_mode_params(sw, sw->tmu.mode);
+
+ switch (sw->tmu.mode) {
+ case TB_SWITCH_TMU_MODE_LOWRES:
+ case TB_SWITCH_TMU_MODE_HIFI_UNI:
+ tb_port_tmu_set_unidirectional(up, true);
+ break;
+
+ case TB_SWITCH_TMU_MODE_HIFI_BI:
+ tb_port_tmu_set_unidirectional(up, false);
+ break;
- tb_switch_set_tmu_mode_params(sw, sw->tmu.rate);
- tb_port_tmu_set_unidirectional(up, sw->tmu.unidirectional);
+ default:
+ break;
+ }
}
-static int __tb_switch_tmu_change_mode(struct tb_switch *sw)
+static int tb_switch_tmu_change_mode(struct tb_switch *sw)
{
- struct tb_switch *parent = tb_switch_parent(sw);
+ unsigned int rate = tmu_rates[sw->tmu.mode_request];
struct tb_port *up, *down;
int ret;
up = tb_upstream_port(sw);
- down = tb_port_at(tb_route(sw), parent);
- ret = tb_port_tmu_set_unidirectional(down, sw->tmu.unidirectional_request);
- if (ret)
- goto out;
+ down = tb_switch_downstream_port(sw);
- if (sw->tmu.unidirectional_request)
- ret = tb_switch_tmu_rate_write(parent, sw->tmu.rate_request);
- else
- ret = tb_switch_tmu_rate_write(sw, sw->tmu.rate_request);
- if (ret)
- return ret;
+ /* Program the upstream router downstream facing lane adapter */
+ switch (sw->tmu.mode_request) {
+ case TB_SWITCH_TMU_MODE_LOWRES:
+ case TB_SWITCH_TMU_MODE_HIFI_UNI:
+ ret = tb_port_tmu_set_unidirectional(down, true);
+ if (ret)
+ goto out;
+ ret = tb_switch_tmu_rate_write(tb_switch_parent(sw), rate);
+ if (ret)
+ goto out;
+ break;
- ret = tb_switch_set_tmu_mode_params(sw, sw->tmu.rate_request);
+ case TB_SWITCH_TMU_MODE_HIFI_BI:
+ ret = tb_port_tmu_set_unidirectional(down, false);
+ if (ret)
+ goto out;
+ ret = tb_switch_tmu_rate_write(sw, rate);
+ if (ret)
+ goto out;
+ break;
+
+ default:
+ /* Not allowed to change modes from other than above */
+ return -EINVAL;
+ }
+
+ ret = tb_switch_set_tmu_mode_params(sw, sw->tmu.mode_request);
if (ret)
return ret;
- ret = tb_port_tmu_set_unidirectional(up, sw->tmu.unidirectional_request);
- if (ret)
- goto out;
+ /* Program the new mode and the downstream router lane adapter */
+ switch (sw->tmu.mode_request) {
+ case TB_SWITCH_TMU_MODE_LOWRES:
+ case TB_SWITCH_TMU_MODE_HIFI_UNI:
+ ret = tb_port_tmu_set_unidirectional(up, true);
+ if (ret)
+ goto out;
+ break;
+
+ case TB_SWITCH_TMU_MODE_HIFI_BI:
+ ret = tb_port_tmu_set_unidirectional(up, false);
+ if (ret)
+ goto out;
+ break;
+
+ default:
+ /* Not allowed to change modes from other than above */
+ return -EINVAL;
+ }
ret = tb_port_tmu_time_sync_enable(down);
if (ret)
@@ -635,7 +925,7 @@ static int __tb_switch_tmu_change_mode(struct tb_switch *sw)
return 0;
out:
- __tb_switch_tmu_change_mode_prev(sw);
+ tb_switch_tmu_change_mode_prev(sw);
return ret;
}
@@ -643,45 +933,21 @@ out:
* tb_switch_tmu_enable() - Enable TMU on a router
* @sw: Router whose TMU to enable
*
- * Enables TMU of a router to be in uni-directional Normal/HiFi
- * or bi-directional HiFi mode. Calling tb_switch_tmu_configure() is required
- * before calling this function, to select the mode Normal/HiFi and
- * directionality (uni-directional/bi-directional).
- * In HiFi mode all tunneling should work. In Normal mode, DP tunneling can't
- * work. Uni-directional mode is required for CLx (Link Low-Power) to work.
+ * Enables TMU of a router to be in uni-directional Normal/HiFi or
+ * bi-directional HiFi mode. Calling tb_switch_tmu_configure() is
+ * required before calling this function.
*/
int tb_switch_tmu_enable(struct tb_switch *sw)
{
- bool unidirectional = sw->tmu.unidirectional_request;
int ret;
- if (unidirectional && !sw->tmu.has_ucap)
- return -EOPNOTSUPP;
-
- /*
- * No need to enable TMU on devices that don't support CLx since on
- * these devices e.g. Alpine Ridge and earlier, the TMU mode HiFi
- * bi-directional is enabled by default.
- */
- if (!tb_switch_is_clx_supported(sw))
- return 0;
-
- if (tb_switch_tmu_is_enabled(sw, sw->tmu.unidirectional_request))
+ if (tb_switch_tmu_is_enabled(sw))
return 0;
- if (tb_switch_is_titan_ridge(sw) && unidirectional) {
- /*
- * Titan Ridge supports CL0s and CL1 only. CL0s and CL1 are
- * enabled and supported together.
- */
- if (!tb_switch_is_clx_enabled(sw, TB_CL1))
- return -EOPNOTSUPP;
-
- ret = tb_switch_tmu_objection_mask(sw);
- if (ret)
- return ret;
-
- ret = tb_switch_tmu_unidirectional_enable(sw);
+ if (tb_switch_is_titan_ridge(sw) &&
+ (sw->tmu.mode_request == TB_SWITCH_TMU_MODE_LOWRES ||
+ sw->tmu.mode_request == TB_SWITCH_TMU_MODE_HIFI_UNI)) {
+ ret = tb_switch_tmu_disable_objections(sw);
if (ret)
return ret;
}
@@ -696,19 +962,30 @@ int tb_switch_tmu_enable(struct tb_switch *sw)
* HiFi-Uni/HiFi-BiDir/Normal-Uni or from Normal-Uni to
* HiFi-Uni.
*/
- if (sw->tmu.rate == TB_SWITCH_TMU_RATE_OFF) {
- if (unidirectional)
- ret = __tb_switch_tmu_enable_unidirectional(sw);
- else
- ret = __tb_switch_tmu_enable_bidirectional(sw);
- if (ret)
- return ret;
- } else if (sw->tmu.rate == TB_SWITCH_TMU_RATE_NORMAL) {
- ret = __tb_switch_tmu_change_mode(sw);
- if (ret)
- return ret;
+ if (sw->tmu.mode == TB_SWITCH_TMU_MODE_OFF) {
+ switch (sw->tmu.mode_request) {
+ case TB_SWITCH_TMU_MODE_LOWRES:
+ case TB_SWITCH_TMU_MODE_HIFI_UNI:
+ ret = tb_switch_tmu_enable_unidirectional(sw);
+ break;
+
+ case TB_SWITCH_TMU_MODE_HIFI_BI:
+ ret = tb_switch_tmu_enable_bidirectional(sw);
+ break;
+ case TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI:
+ ret = tb_switch_tmu_enable_enhanced(sw);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ } else if (sw->tmu.mode == TB_SWITCH_TMU_MODE_LOWRES ||
+ sw->tmu.mode == TB_SWITCH_TMU_MODE_HIFI_UNI ||
+ sw->tmu.mode == TB_SWITCH_TMU_MODE_HIFI_BI) {
+ ret = tb_switch_tmu_change_mode(sw);
+ } else {
+ ret = -EINVAL;
}
- sw->tmu.unidirectional = unidirectional;
} else {
/*
* Host router port configurations are written as
@@ -716,58 +993,68 @@ int tb_switch_tmu_enable(struct tb_switch *sw)
* of the child node - see above.
* Here only the host router' rate configuration is written.
*/
- ret = tb_switch_tmu_rate_write(sw, sw->tmu.rate_request);
- if (ret)
- return ret;
+ ret = tb_switch_tmu_rate_write(sw, tmu_rates[sw->tmu.mode_request]);
}
- sw->tmu.rate = sw->tmu.rate_request;
+ if (ret) {
+ tb_sw_warn(sw, "TMU: failed to enable mode %s: %d\n",
+ tmu_mode_name(sw->tmu.mode_request), ret);
+ } else {
+ sw->tmu.mode = sw->tmu.mode_request;
+ tb_sw_dbg(sw, "TMU: mode set to: %s\n", tmu_mode_name(sw->tmu.mode));
+ }
- tb_sw_dbg(sw, "TMU: mode set to: %s\n", tb_switch_tmu_mode_name(sw));
return tb_switch_tmu_set_time_disruption(sw, false);
}
/**
- * tb_switch_tmu_configure() - Configure the TMU rate and directionality
+ * tb_switch_tmu_configure() - Configure the TMU mode
* @sw: Router whose mode to change
- * @rate: Rate to configure Off/Normal/HiFi
- * @unidirectional: If uni-directional (bi-directional otherwise)
+ * @mode: Mode to configure
*
- * Selects the rate of the TMU and directionality (uni-directional or
- * bi-directional). Must be called before tb_switch_tmu_enable().
+ * Selects the TMU mode that is enabled when tb_switch_tmu_enable() is
+ * next called.
+ *
+ * Returns %0 in success and negative errno otherwise. Specifically
+ * returns %-EOPNOTSUPP if the requested mode is not possible (not
+ * supported by the router and/or topology).
*/
-void tb_switch_tmu_configure(struct tb_switch *sw,
- enum tb_switch_tmu_rate rate, bool unidirectional)
+int tb_switch_tmu_configure(struct tb_switch *sw, enum tb_switch_tmu_mode mode)
{
- sw->tmu.unidirectional_request = unidirectional;
- sw->tmu.rate_request = rate;
-}
+ switch (mode) {
+ case TB_SWITCH_TMU_MODE_OFF:
+ break;
-static int tb_switch_tmu_config_enable(struct device *dev, void *rate)
-{
- if (tb_is_switch(dev)) {
- struct tb_switch *sw = tb_to_switch(dev);
+ case TB_SWITCH_TMU_MODE_LOWRES:
+ case TB_SWITCH_TMU_MODE_HIFI_UNI:
+ if (!sw->tmu.has_ucap)
+ return -EOPNOTSUPP;
+ break;
- tb_switch_tmu_configure(sw, *(enum tb_switch_tmu_rate *)rate,
- tb_switch_is_clx_enabled(sw, TB_CL1));
- if (tb_switch_tmu_enable(sw))
- tb_sw_dbg(sw, "fail switching TMU mode for 1st depth router\n");
+ case TB_SWITCH_TMU_MODE_HIFI_BI:
+ break;
+
+ case TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI: {
+ const struct tb_switch *parent_sw = tb_switch_parent(sw);
+
+ if (!parent_sw || !tb_switch_tmu_enhanced_is_supported(parent_sw))
+ return -EOPNOTSUPP;
+ if (!tb_switch_tmu_enhanced_is_supported(sw))
+ return -EOPNOTSUPP;
+
+ break;
}
- return 0;
-}
+ default:
+ tb_sw_warn(sw, "TMU: unsupported mode %u\n", mode);
+ return -EINVAL;
+ }
-/**
- * tb_switch_enable_tmu_1st_child - Configure and enable TMU for 1st chidren
- * @sw: The router to configure and enable it's children TMU
- * @rate: Rate of the TMU to configure the router's chidren to
- *
- * Configures and enables the TMU mode of 1st depth children of the specified
- * router to the specified rate.
- */
-void tb_switch_enable_tmu_1st_child(struct tb_switch *sw,
- enum tb_switch_tmu_rate rate)
-{
- device_for_each_child(&sw->dev, &rate,
- tb_switch_tmu_config_enable);
+ if (sw->tmu.mode_request != mode) {
+ tb_sw_dbg(sw, "TMU: mode change %s -> %s requested\n",
+ tmu_mode_name(sw->tmu.mode), tmu_mode_name(mode));
+ sw->tmu.mode_request = mode;
+ }
+
+ return 0;
}
diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c
index 4f222673d651..a6810fb36860 100644
--- a/drivers/thunderbolt/tunnel.c
+++ b/drivers/thunderbolt/tunnel.c
@@ -10,6 +10,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/ktime.h>
+#include <linux/string_helpers.h>
#include "tunnel.h"
#include "tb.h"
@@ -41,9 +42,14 @@
* Number of credits we try to allocate for each DMA path if not limited
* by the host router baMaxHI.
*/
-#define TB_DMA_CREDITS 14U
+#define TB_DMA_CREDITS 14
/* Minimum number of credits for DMA path */
-#define TB_MIN_DMA_CREDITS 1U
+#define TB_MIN_DMA_CREDITS 1
+
+static unsigned int dma_credits = TB_DMA_CREDITS;
+module_param(dma_credits, uint, 0444);
+MODULE_PARM_DESC(dma_credits, "specify custom credits for DMA tunnels (default: "
+ __MODULE_STRING(TB_DMA_CREDITS) ")");
static bool bw_alloc_mode = true;
module_param(bw_alloc_mode, bool, 0444);
@@ -95,7 +101,7 @@ static unsigned int tb_available_credits(const struct tb_port *port,
pcie = tb_acpi_may_tunnel_pcie() ? sw->max_pcie_credits : 0;
if (tb_acpi_is_xdomain_allowed()) {
- spare = min_not_zero(sw->max_dma_credits, TB_DMA_CREDITS);
+ spare = min_not_zero(sw->max_dma_credits, dma_credits);
/* Add some credits for potential second DMA tunnel */
spare += TB_MIN_DMA_CREDITS;
} else {
@@ -148,18 +154,49 @@ static struct tb_tunnel *tb_tunnel_alloc(struct tb *tb, size_t npaths,
return tunnel;
}
+static int tb_pci_set_ext_encapsulation(struct tb_tunnel *tunnel, bool enable)
+{
+ int ret;
+
+ /* Only supported of both routers are at least USB4 v2 */
+ if (usb4_switch_version(tunnel->src_port->sw) < 2 ||
+ usb4_switch_version(tunnel->dst_port->sw) < 2)
+ return 0;
+
+ ret = usb4_pci_port_set_ext_encapsulation(tunnel->src_port, enable);
+ if (ret)
+ return ret;
+
+ ret = usb4_pci_port_set_ext_encapsulation(tunnel->dst_port, enable);
+ if (ret)
+ return ret;
+
+ tb_tunnel_dbg(tunnel, "extended encapsulation %s\n",
+ str_enabled_disabled(enable));
+ return 0;
+}
+
static int tb_pci_activate(struct tb_tunnel *tunnel, bool activate)
{
int res;
+ if (activate) {
+ res = tb_pci_set_ext_encapsulation(tunnel, activate);
+ if (res)
+ return res;
+ }
+
res = tb_pci_port_enable(tunnel->src_port, activate);
if (res)
return res;
- if (tb_port_is_pcie_up(tunnel->dst_port))
- return tb_pci_port_enable(tunnel->dst_port, activate);
+ if (tb_port_is_pcie_up(tunnel->dst_port)) {
+ res = tb_pci_port_enable(tunnel->dst_port, activate);
+ if (res)
+ return res;
+ }
- return 0;
+ return activate ? 0 : tb_pci_set_ext_encapsulation(tunnel, activate);
}
static int tb_pci_init_credits(struct tb_path_hop *hop)
@@ -381,6 +418,10 @@ static int tb_dp_cm_handshake(struct tb_port *in, struct tb_port *out,
return -ETIMEDOUT;
}
+/*
+ * Returns maximum possible rate from capability supporting only DP 2.0
+ * and below. Used when DP BW allocation mode is not enabled.
+ */
static inline u32 tb_dp_cap_get_rate(u32 val)
{
u32 rate = (val & DP_COMMON_CAP_RATE_MASK) >> DP_COMMON_CAP_RATE_SHIFT;
@@ -399,6 +440,28 @@ static inline u32 tb_dp_cap_get_rate(u32 val)
}
}
+/*
+ * Returns maximum possible rate from capability supporting DP 2.1
+ * UHBR20, 13.5 and 10 rates as well. Use only when DP BW allocation
+ * mode is enabled.
+ */
+static inline u32 tb_dp_cap_get_rate_ext(u32 val)
+{
+ if (val & DP_COMMON_CAP_UHBR20)
+ return 20000;
+ else if (val & DP_COMMON_CAP_UHBR13_5)
+ return 13500;
+ else if (val & DP_COMMON_CAP_UHBR10)
+ return 10000;
+
+ return tb_dp_cap_get_rate(val);
+}
+
+static inline bool tb_dp_is_uhbr_rate(unsigned int rate)
+{
+ return rate >= 10000;
+}
+
static inline u32 tb_dp_cap_set_rate(u32 val, u32 rate)
{
val &= ~DP_COMMON_CAP_RATE_MASK;
@@ -461,7 +524,9 @@ static inline u32 tb_dp_cap_set_lanes(u32 val, u32 lanes)
static unsigned int tb_dp_bandwidth(unsigned int rate, unsigned int lanes)
{
- /* Tunneling removes the DP 8b/10b encoding */
+ /* Tunneling removes the DP 8b/10b 128/132b encoding */
+ if (tb_dp_is_uhbr_rate(rate))
+ return rate * lanes * 128 / 132;
return rate * lanes * 8 / 10;
}
@@ -604,7 +669,7 @@ static int tb_dp_xchg_caps(struct tb_tunnel *tunnel)
in->cap_adap + DP_REMOTE_CAP, 1);
}
-static int tb_dp_bw_alloc_mode_enable(struct tb_tunnel *tunnel)
+static int tb_dp_bandwidth_alloc_mode_enable(struct tb_tunnel *tunnel)
{
int ret, estimated_bw, granularity, tmp;
struct tb_port *out = tunnel->dst_port;
@@ -616,7 +681,7 @@ static int tb_dp_bw_alloc_mode_enable(struct tb_tunnel *tunnel)
if (!bw_alloc_mode)
return 0;
- ret = usb4_dp_port_set_cm_bw_mode_supported(in, true);
+ ret = usb4_dp_port_set_cm_bandwidth_mode_supported(in, true);
if (ret)
return ret;
@@ -654,6 +719,19 @@ static int tb_dp_bw_alloc_mode_enable(struct tb_tunnel *tunnel)
if (ret)
return ret;
+ /*
+ * Pick up granularity that supports maximum possible bandwidth.
+ * For that we use the UHBR rates too.
+ */
+ in_rate = tb_dp_cap_get_rate_ext(in_dp_cap);
+ out_rate = tb_dp_cap_get_rate_ext(out_dp_cap);
+ rate = min(in_rate, out_rate);
+ tmp = tb_dp_bandwidth(rate, lanes);
+
+ tb_port_dbg(in,
+ "maximum bandwidth through allocation mode %u Mb/s x%u = %u Mb/s\n",
+ rate, lanes, tmp);
+
for (granularity = 250; tmp / granularity > 255 && granularity <= 1000;
granularity *= 2)
;
@@ -680,12 +758,12 @@ static int tb_dp_bw_alloc_mode_enable(struct tb_tunnel *tunnel)
tb_port_dbg(in, "estimated bandwidth %d Mb/s\n", estimated_bw);
- ret = usb4_dp_port_set_estimated_bw(in, estimated_bw);
+ ret = usb4_dp_port_set_estimated_bandwidth(in, estimated_bw);
if (ret)
return ret;
/* Initial allocation should be 0 according the spec */
- ret = usb4_dp_port_allocate_bw(in, 0);
+ ret = usb4_dp_port_allocate_bandwidth(in, 0);
if (ret)
return ret;
@@ -707,7 +785,7 @@ static int tb_dp_init(struct tb_tunnel *tunnel)
if (!tb_switch_is_usb4(sw))
return 0;
- if (!usb4_dp_port_bw_mode_supported(in))
+ if (!usb4_dp_port_bandwidth_mode_supported(in))
return 0;
tb_port_dbg(in, "bandwidth allocation mode supported\n");
@@ -716,17 +794,17 @@ static int tb_dp_init(struct tb_tunnel *tunnel)
if (ret)
return ret;
- return tb_dp_bw_alloc_mode_enable(tunnel);
+ return tb_dp_bandwidth_alloc_mode_enable(tunnel);
}
static void tb_dp_deinit(struct tb_tunnel *tunnel)
{
struct tb_port *in = tunnel->src_port;
- if (!usb4_dp_port_bw_mode_supported(in))
+ if (!usb4_dp_port_bandwidth_mode_supported(in))
return;
- if (usb4_dp_port_bw_mode_enabled(in)) {
- usb4_dp_port_set_cm_bw_mode_supported(in, false);
+ if (usb4_dp_port_bandwidth_mode_enabled(in)) {
+ usb4_dp_port_set_cm_bandwidth_mode_supported(in, false);
tb_port_dbg(in, "bandwidth allocation mode disabled\n");
}
}
@@ -769,15 +847,42 @@ static int tb_dp_activate(struct tb_tunnel *tunnel, bool active)
}
/* max_bw is rounded up to next granularity */
-static int tb_dp_nrd_bandwidth(struct tb_tunnel *tunnel, int *max_bw)
+static int tb_dp_bandwidth_mode_maximum_bandwidth(struct tb_tunnel *tunnel,
+ int *max_bw)
{
struct tb_port *in = tunnel->src_port;
int ret, rate, lanes, nrd_bw;
+ u32 cap;
- ret = usb4_dp_port_nrd(in, &rate, &lanes);
+ /*
+ * DP IN adapter DP_LOCAL_CAP gets updated to the lowest AUX
+ * read parameter values so this so we can use this to determine
+ * the maximum possible bandwidth over this link.
+ *
+ * See USB4 v2 spec 1.0 10.4.4.5.
+ */
+ ret = tb_port_read(in, &cap, TB_CFG_PORT,
+ in->cap_adap + DP_LOCAL_CAP, 1);
if (ret)
return ret;
+ rate = tb_dp_cap_get_rate_ext(cap);
+ if (tb_dp_is_uhbr_rate(rate)) {
+ /*
+ * When UHBR is used there is no reduction in lanes so
+ * we can use this directly.
+ */
+ lanes = tb_dp_cap_get_lanes(cap);
+ } else {
+ /*
+ * If there is no UHBR supported then check the
+ * non-reduced rate and lanes.
+ */
+ ret = usb4_dp_port_nrd(in, &rate, &lanes);
+ if (ret)
+ return ret;
+ }
+
nrd_bw = tb_dp_bandwidth(rate, lanes);
if (max_bw) {
@@ -790,26 +895,27 @@ static int tb_dp_nrd_bandwidth(struct tb_tunnel *tunnel, int *max_bw)
return nrd_bw;
}
-static int tb_dp_bw_mode_consumed_bandwidth(struct tb_tunnel *tunnel,
- int *consumed_up, int *consumed_down)
+static int tb_dp_bandwidth_mode_consumed_bandwidth(struct tb_tunnel *tunnel,
+ int *consumed_up,
+ int *consumed_down)
{
struct tb_port *out = tunnel->dst_port;
struct tb_port *in = tunnel->src_port;
int ret, allocated_bw, max_bw;
- if (!usb4_dp_port_bw_mode_enabled(in))
+ if (!usb4_dp_port_bandwidth_mode_enabled(in))
return -EOPNOTSUPP;
if (!tunnel->bw_mode)
return -EOPNOTSUPP;
/* Read what was allocated previously if any */
- ret = usb4_dp_port_allocated_bw(in);
+ ret = usb4_dp_port_allocated_bandwidth(in);
if (ret < 0)
return ret;
allocated_bw = ret;
- ret = tb_dp_nrd_bandwidth(tunnel, &max_bw);
+ ret = tb_dp_bandwidth_mode_maximum_bandwidth(tunnel, &max_bw);
if (ret < 0)
return ret;
if (allocated_bw == max_bw)
@@ -839,15 +945,15 @@ static int tb_dp_allocated_bandwidth(struct tb_tunnel *tunnel, int *allocated_up
* If we have already set the allocated bandwidth then use that.
* Otherwise we read it from the DPRX.
*/
- if (usb4_dp_port_bw_mode_enabled(in) && tunnel->bw_mode) {
+ if (usb4_dp_port_bandwidth_mode_enabled(in) && tunnel->bw_mode) {
int ret, allocated_bw, max_bw;
- ret = usb4_dp_port_allocated_bw(in);
+ ret = usb4_dp_port_allocated_bandwidth(in);
if (ret < 0)
return ret;
allocated_bw = ret;
- ret = tb_dp_nrd_bandwidth(tunnel, &max_bw);
+ ret = tb_dp_bandwidth_mode_maximum_bandwidth(tunnel, &max_bw);
if (ret < 0)
return ret;
if (allocated_bw == max_bw)
@@ -874,23 +980,23 @@ static int tb_dp_alloc_bandwidth(struct tb_tunnel *tunnel, int *alloc_up,
struct tb_port *in = tunnel->src_port;
int max_bw, ret, tmp;
- if (!usb4_dp_port_bw_mode_enabled(in))
+ if (!usb4_dp_port_bandwidth_mode_enabled(in))
return -EOPNOTSUPP;
- ret = tb_dp_nrd_bandwidth(tunnel, &max_bw);
+ ret = tb_dp_bandwidth_mode_maximum_bandwidth(tunnel, &max_bw);
if (ret < 0)
return ret;
if (in->sw->config.depth < out->sw->config.depth) {
tmp = min(*alloc_down, max_bw);
- ret = usb4_dp_port_allocate_bw(in, tmp);
+ ret = usb4_dp_port_allocate_bandwidth(in, tmp);
if (ret)
return ret;
*alloc_down = tmp;
*alloc_up = 0;
} else {
tmp = min(*alloc_up, max_bw);
- ret = usb4_dp_port_allocate_bw(in, tmp);
+ ret = usb4_dp_port_allocate_bandwidth(in, tmp);
if (ret)
return ret;
*alloc_down = 0;
@@ -900,6 +1006,9 @@ static int tb_dp_alloc_bandwidth(struct tb_tunnel *tunnel, int *alloc_up,
/* Now we can use BW mode registers to figure out the bandwidth */
/* TODO: need to handle discovery too */
tunnel->bw_mode = true;
+
+ tb_port_dbg(in, "allocated bandwidth through allocation mode %d Mb/s\n",
+ tmp);
return 0;
}
@@ -974,23 +1083,20 @@ static int tb_dp_maximum_bandwidth(struct tb_tunnel *tunnel, int *max_up,
int *max_down)
{
struct tb_port *in = tunnel->src_port;
- u32 rate, lanes;
int ret;
- /*
- * DP IN adapter DP_LOCAL_CAP gets updated to the lowest AUX read
- * parameter values so this so we can use this to determine the
- * maximum possible bandwidth over this link.
- */
- ret = tb_dp_read_cap(tunnel, DP_LOCAL_CAP, &rate, &lanes);
- if (ret)
+ if (!usb4_dp_port_bandwidth_mode_enabled(in))
+ return -EOPNOTSUPP;
+
+ ret = tb_dp_bandwidth_mode_maximum_bandwidth(tunnel, NULL);
+ if (ret < 0)
return ret;
if (in->sw->config.depth < tunnel->dst_port->sw->config.depth) {
*max_up = 0;
- *max_down = tb_dp_bandwidth(rate, lanes);
+ *max_down = ret;
} else {
- *max_up = tb_dp_bandwidth(rate, lanes);
+ *max_up = ret;
*max_down = 0;
}
@@ -1011,8 +1117,8 @@ static int tb_dp_consumed_bandwidth(struct tb_tunnel *tunnel, int *consumed_up,
* mode is enabled first and then read the bandwidth
* through those registers.
*/
- ret = tb_dp_bw_mode_consumed_bandwidth(tunnel, consumed_up,
- consumed_down);
+ ret = tb_dp_bandwidth_mode_consumed_bandwidth(tunnel, consumed_up,
+ consumed_down);
if (ret < 0) {
if (ret != -EOPNOTSUPP)
return ret;
@@ -1132,6 +1238,47 @@ static int tb_dp_init_video_path(struct tb_path *path)
return 0;
}
+static void tb_dp_dump(struct tb_tunnel *tunnel)
+{
+ struct tb_port *in, *out;
+ u32 dp_cap, rate, lanes;
+
+ in = tunnel->src_port;
+ out = tunnel->dst_port;
+
+ if (tb_port_read(in, &dp_cap, TB_CFG_PORT,
+ in->cap_adap + DP_LOCAL_CAP, 1))
+ return;
+
+ rate = tb_dp_cap_get_rate(dp_cap);
+ lanes = tb_dp_cap_get_lanes(dp_cap);
+
+ tb_port_dbg(in, "maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n",
+ rate, lanes, tb_dp_bandwidth(rate, lanes));
+
+ out = tunnel->dst_port;
+
+ if (tb_port_read(out, &dp_cap, TB_CFG_PORT,
+ out->cap_adap + DP_LOCAL_CAP, 1))
+ return;
+
+ rate = tb_dp_cap_get_rate(dp_cap);
+ lanes = tb_dp_cap_get_lanes(dp_cap);
+
+ tb_port_dbg(out, "maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n",
+ rate, lanes, tb_dp_bandwidth(rate, lanes));
+
+ if (tb_port_read(in, &dp_cap, TB_CFG_PORT,
+ in->cap_adap + DP_REMOTE_CAP, 1))
+ return;
+
+ rate = tb_dp_cap_get_rate(dp_cap);
+ lanes = tb_dp_cap_get_lanes(dp_cap);
+
+ tb_port_dbg(in, "reduced bandwidth %u Mb/s x%u = %u Mb/s\n",
+ rate, lanes, tb_dp_bandwidth(rate, lanes));
+}
+
/**
* tb_tunnel_discover_dp() - Discover existing Display Port tunnels
* @tb: Pointer to the domain structure
@@ -1209,6 +1356,8 @@ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in,
goto err_deactivate;
}
+ tb_dp_dump(tunnel);
+
tb_tunnel_dbg(tunnel, "discovered\n");
return tunnel;
@@ -1452,6 +1601,10 @@ struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi,
struct tb_path *path;
int credits;
+ /* Ring 0 is reserved for control channel */
+ if (WARN_ON(!receive_ring || !transmit_ring))
+ return NULL;
+
if (receive_ring > 0)
npaths++;
if (transmit_ring > 0)
@@ -1468,7 +1621,7 @@ struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi,
tunnel->dst_port = dst;
tunnel->deinit = tb_dma_deinit;
- credits = min_not_zero(TB_DMA_CREDITS, nhi->sw->max_dma_credits);
+ credits = min_not_zero(dma_credits, nhi->sw->max_dma_credits);
if (receive_ring > 0) {
path = tb_path_alloc(tb, dst, receive_path, nhi, receive_ring, 0,
diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c
index 485b6e430686..05ddb224c464 100644
--- a/drivers/thunderbolt/usb4.c
+++ b/drivers/thunderbolt/usb4.c
@@ -15,6 +15,7 @@
#include "tb.h"
#define USB4_DATA_RETRIES 3
+#define USB4_DATA_DWORDS 16
enum usb4_sb_target {
USB4_SB_TARGET_ROUTER,
@@ -112,7 +113,7 @@ static int __usb4_switch_op(struct tb_switch *sw, u16 opcode, u32 *metadata,
{
const struct tb_cm_ops *cm_ops = sw->tb->cm_ops;
- if (tx_dwords > NVM_DATA_DWORDS || rx_dwords > NVM_DATA_DWORDS)
+ if (tx_dwords > USB4_DATA_DWORDS || rx_dwords > USB4_DATA_DWORDS)
return -EINVAL;
/*
@@ -231,11 +232,14 @@ static bool link_is_usb4(struct tb_port *port)
* is not available for some reason (like that there is Thunderbolt 3
* switch upstream) then the internal xHCI controller is enabled
* instead.
+ *
+ * This does not set the configuration valid bit of the router. To do
+ * that call usb4_switch_configuration_valid().
*/
int usb4_switch_setup(struct tb_switch *sw)
{
- struct tb_port *downstream_port;
- struct tb_switch *parent;
+ struct tb_switch *parent = tb_switch_parent(sw);
+ struct tb_port *down;
bool tbt3, xhci;
u32 val = 0;
int ret;
@@ -249,9 +253,8 @@ int usb4_switch_setup(struct tb_switch *sw)
if (ret)
return ret;
- parent = tb_switch_parent(sw);
- downstream_port = tb_port_at(tb_route(sw), parent);
- sw->link_usb4 = link_is_usb4(downstream_port);
+ down = tb_switch_downstream_port(sw);
+ sw->link_usb4 = link_is_usb4(down);
tb_sw_dbg(sw, "link: %s\n", sw->link_usb4 ? "USB4" : "TBT");
xhci = val & ROUTER_CS_6_HCI;
@@ -288,7 +291,33 @@ int usb4_switch_setup(struct tb_switch *sw)
/* TBT3 supported by the CM */
val |= ROUTER_CS_5_C3S;
- /* Tunneling configuration is ready now */
+
+ return tb_sw_write(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1);
+}
+
+/**
+ * usb4_switch_configuration_valid() - Set tunneling configuration to be valid
+ * @sw: USB4 router
+ *
+ * Sets configuration valid bit for the router. Must be called before
+ * any tunnels can be set through the router and after
+ * usb4_switch_setup() has been called. Can be called to host and device
+ * routers (does nothing for the latter).
+ *
+ * Returns %0 in success and negative errno otherwise.
+ */
+int usb4_switch_configuration_valid(struct tb_switch *sw)
+{
+ u32 val;
+ int ret;
+
+ if (!tb_route(sw))
+ return 0;
+
+ ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1);
+ if (ret)
+ return ret;
+
val |= ROUTER_CS_5_CV;
ret = tb_sw_write(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1);
@@ -703,7 +732,7 @@ int usb4_switch_credits_init(struct tb_switch *sw)
int max_usb3, min_dp_aux, min_dp_main, max_pcie, max_dma;
int ret, length, i, nports;
const struct tb_port *port;
- u32 data[NVM_DATA_DWORDS];
+ u32 data[USB4_DATA_DWORDS];
u32 metadata = 0;
u8 status = 0;
@@ -1199,7 +1228,7 @@ static int usb4_port_wait_for_bit(struct tb_port *port, u32 offset, u32 bit,
static int usb4_port_read_data(struct tb_port *port, void *data, size_t dwords)
{
- if (dwords > NVM_DATA_DWORDS)
+ if (dwords > USB4_DATA_DWORDS)
return -EINVAL;
return tb_port_read(port, data, TB_CFG_PORT, port->cap_usb4 + PORT_CS_2,
@@ -1209,7 +1238,7 @@ static int usb4_port_read_data(struct tb_port *port, void *data, size_t dwords)
static int usb4_port_write_data(struct tb_port *port, const void *data,
size_t dwords)
{
- if (dwords > NVM_DATA_DWORDS)
+ if (dwords > USB4_DATA_DWORDS)
return -EINVAL;
return tb_port_write(port, data, TB_CFG_PORT, port->cap_usb4 + PORT_CS_2,
@@ -1845,7 +1874,7 @@ static int usb4_port_retimer_nvm_read_block(void *data, unsigned int dwaddress,
int ret;
metadata = dwaddress << USB4_NVM_READ_OFFSET_SHIFT;
- if (dwords < NVM_DATA_DWORDS)
+ if (dwords < USB4_DATA_DWORDS)
metadata |= dwords << USB4_NVM_READ_LENGTH_SHIFT;
ret = usb4_port_retimer_write(port, index, USB4_SB_METADATA, &metadata,
@@ -2265,13 +2294,14 @@ int usb4_dp_port_set_cm_id(struct tb_port *port, int cm_id)
}
/**
- * usb4_dp_port_bw_mode_supported() - Is the bandwidth allocation mode supported
+ * usb4_dp_port_bandwidth_mode_supported() - Is the bandwidth allocation mode
+ * supported
* @port: DP IN adapter to check
*
* Can be called to any DP IN adapter. Returns true if the adapter
* supports USB4 bandwidth allocation mode, false otherwise.
*/
-bool usb4_dp_port_bw_mode_supported(struct tb_port *port)
+bool usb4_dp_port_bandwidth_mode_supported(struct tb_port *port)
{
int ret;
u32 val;
@@ -2288,13 +2318,14 @@ bool usb4_dp_port_bw_mode_supported(struct tb_port *port)
}
/**
- * usb4_dp_port_bw_mode_enabled() - Is the bandwidth allocation mode enabled
+ * usb4_dp_port_bandwidth_mode_enabled() - Is the bandwidth allocation mode
+ * enabled
* @port: DP IN adapter to check
*
* Can be called to any DP IN adapter. Returns true if the bandwidth
* allocation mode has been enabled, false otherwise.
*/
-bool usb4_dp_port_bw_mode_enabled(struct tb_port *port)
+bool usb4_dp_port_bandwidth_mode_enabled(struct tb_port *port)
{
int ret;
u32 val;
@@ -2311,7 +2342,8 @@ bool usb4_dp_port_bw_mode_enabled(struct tb_port *port)
}
/**
- * usb4_dp_port_set_cm_bw_mode_supported() - Set/clear CM support for bandwidth allocation mode
+ * usb4_dp_port_set_cm_bandwidth_mode_supported() - Set/clear CM support for
+ * bandwidth allocation mode
* @port: DP IN adapter
* @supported: Does the CM support bandwidth allocation mode
*
@@ -2320,7 +2352,8 @@ bool usb4_dp_port_bw_mode_enabled(struct tb_port *port)
* otherwise. Specifically returns %-OPNOTSUPP if the passed in adapter
* does not support this.
*/
-int usb4_dp_port_set_cm_bw_mode_supported(struct tb_port *port, bool supported)
+int usb4_dp_port_set_cm_bandwidth_mode_supported(struct tb_port *port,
+ bool supported)
{
u32 val;
int ret;
@@ -2594,7 +2627,7 @@ int usb4_dp_port_set_granularity(struct tb_port *port, int granularity)
}
/**
- * usb4_dp_port_set_estimated_bw() - Set estimated bandwidth
+ * usb4_dp_port_set_estimated_bandwidth() - Set estimated bandwidth
* @port: DP IN adapter
* @bw: Estimated bandwidth in Mb/s.
*
@@ -2604,7 +2637,7 @@ int usb4_dp_port_set_granularity(struct tb_port *port, int granularity)
* and negative errno otherwise. Specifically returns %-EOPNOTSUPP if
* the adapter does not support this.
*/
-int usb4_dp_port_set_estimated_bw(struct tb_port *port, int bw)
+int usb4_dp_port_set_estimated_bandwidth(struct tb_port *port, int bw)
{
u32 val, granularity;
int ret;
@@ -2630,14 +2663,14 @@ int usb4_dp_port_set_estimated_bw(struct tb_port *port, int bw)
}
/**
- * usb4_dp_port_allocated_bw() - Return allocated bandwidth
+ * usb4_dp_port_allocated_bandwidth() - Return allocated bandwidth
* @port: DP IN adapter
*
* Reads and returns allocated bandwidth for @port in Mb/s (taking into
* account the programmed granularity). Returns negative errno in case
* of error.
*/
-int usb4_dp_port_allocated_bw(struct tb_port *port)
+int usb4_dp_port_allocated_bandwidth(struct tb_port *port)
{
u32 val, granularity;
int ret;
@@ -2723,7 +2756,7 @@ static int usb4_dp_port_wait_and_clear_cm_ack(struct tb_port *port,
}
/**
- * usb4_dp_port_allocate_bw() - Set allocated bandwidth
+ * usb4_dp_port_allocate_bandwidth() - Set allocated bandwidth
* @port: DP IN adapter
* @bw: New allocated bandwidth in Mb/s
*
@@ -2731,7 +2764,7 @@ static int usb4_dp_port_wait_and_clear_cm_ack(struct tb_port *port,
* driver). Takes into account the programmed granularity. Returns %0 in
* success and negative errno in case of error.
*/
-int usb4_dp_port_allocate_bw(struct tb_port *port, int bw)
+int usb4_dp_port_allocate_bandwidth(struct tb_port *port, int bw)
{
u32 val, granularity;
int ret;
@@ -2765,7 +2798,7 @@ int usb4_dp_port_allocate_bw(struct tb_port *port, int bw)
}
/**
- * usb4_dp_port_requested_bw() - Read requested bandwidth
+ * usb4_dp_port_requested_bandwidth() - Read requested bandwidth
* @port: DP IN adapter
*
* Reads the DPCD (graphics driver) requested bandwidth and returns it
@@ -2774,7 +2807,7 @@ int usb4_dp_port_allocate_bw(struct tb_port *port, int bw)
* the adapter does not support bandwidth allocation mode, and %ENODATA
* if there is no active bandwidth request from the graphics driver.
*/
-int usb4_dp_port_requested_bw(struct tb_port *port)
+int usb4_dp_port_requested_bandwidth(struct tb_port *port)
{
u32 val, granularity;
int ret;
@@ -2797,3 +2830,34 @@ int usb4_dp_port_requested_bw(struct tb_port *port)
return (val & ADP_DP_CS_8_REQUESTED_BW_MASK) * granularity;
}
+
+/**
+ * usb4_pci_port_set_ext_encapsulation() - Enable/disable extended encapsulation
+ * @port: PCIe adapter
+ * @enable: Enable/disable extended encapsulation
+ *
+ * Enables or disables extended encapsulation used in PCIe tunneling. Caller
+ * needs to make sure both adapters support this before enabling. Returns %0 on
+ * success and negative errno otherwise.
+ */
+int usb4_pci_port_set_ext_encapsulation(struct tb_port *port, bool enable)
+{
+ u32 val;
+ int ret;
+
+ if (!tb_port_is_pcie_up(port) && !tb_port_is_pcie_down(port))
+ return -EINVAL;
+
+ ret = tb_port_read(port, &val, TB_CFG_PORT,
+ port->cap_adap + ADP_PCIE_CS_1, 1);
+ if (ret)
+ return ret;
+
+ if (enable)
+ val |= ADP_PCIE_CS_1_EE;
+ else
+ val &= ~ADP_PCIE_CS_1_EE;
+
+ return tb_port_write(port, &val, TB_CFG_PORT,
+ port->cap_adap + ADP_PCIE_CS_1, 1);
+}
diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c
index e2b54887d331..5b5566862318 100644
--- a/drivers/thunderbolt/xdomain.c
+++ b/drivers/thunderbolt/xdomain.c
@@ -537,9 +537,8 @@ static int tb_xdp_link_state_status_request(struct tb_ctl *ctl, u64 route,
static int tb_xdp_link_state_status_response(struct tb *tb, struct tb_ctl *ctl,
struct tb_xdomain *xd, u8 sequence)
{
- struct tb_switch *sw = tb_to_switch(xd->dev.parent);
struct tb_xdp_link_state_status_response res;
- struct tb_port *port = tb_port_at(xd->route, sw);
+ struct tb_port *port = tb_xdomain_downstream_port(xd);
u32 val[2];
int ret;
@@ -1137,7 +1136,7 @@ static int tb_xdomain_update_link_attributes(struct tb_xdomain *xd)
struct tb_port *port;
int ret;
- port = tb_port_at(xd->route, tb_xdomain_parent(xd));
+ port = tb_xdomain_downstream_port(xd);
ret = tb_port_get_link_speed(port);
if (ret < 0)
@@ -1251,8 +1250,7 @@ static int tb_xdomain_get_link_status(struct tb_xdomain *xd)
static int tb_xdomain_link_state_change(struct tb_xdomain *xd,
unsigned int width)
{
- struct tb_switch *sw = tb_to_switch(xd->dev.parent);
- struct tb_port *port = tb_port_at(xd->route, sw);
+ struct tb_port *port = tb_xdomain_downstream_port(xd);
struct tb *tb = xd->tb;
u8 tlw, tls;
u32 val;
@@ -1292,13 +1290,16 @@ static int tb_xdomain_link_state_change(struct tb_xdomain *xd,
static int tb_xdomain_bond_lanes_uuid_high(struct tb_xdomain *xd)
{
+ unsigned int width, width_mask;
struct tb_port *port;
- int ret, width;
+ int ret;
if (xd->target_link_width == LANE_ADP_CS_1_TARGET_WIDTH_SINGLE) {
- width = 1;
+ width = TB_LINK_WIDTH_SINGLE;
+ width_mask = width;
} else if (xd->target_link_width == LANE_ADP_CS_1_TARGET_WIDTH_DUAL) {
- width = 2;
+ width = TB_LINK_WIDTH_DUAL;
+ width_mask = width | TB_LINK_WIDTH_ASYM_TX | TB_LINK_WIDTH_ASYM_RX;
} else {
if (xd->state_retries-- > 0) {
dev_dbg(&xd->dev,
@@ -1309,7 +1310,7 @@ static int tb_xdomain_bond_lanes_uuid_high(struct tb_xdomain *xd)
return -ETIMEDOUT;
}
- port = tb_port_at(xd->route, tb_xdomain_parent(xd));
+ port = tb_xdomain_downstream_port(xd);
/*
* We can't use tb_xdomain_lane_bonding_enable() here because it
@@ -1330,15 +1331,16 @@ static int tb_xdomain_bond_lanes_uuid_high(struct tb_xdomain *xd)
return ret;
}
- ret = tb_port_wait_for_link_width(port, width, XDOMAIN_BONDING_TIMEOUT);
+ ret = tb_port_wait_for_link_width(port, width_mask,
+ XDOMAIN_BONDING_TIMEOUT);
if (ret) {
dev_warn(&xd->dev, "error waiting for link width to become %d\n",
- width);
+ width_mask);
return ret;
}
- port->bonded = width == 2;
- port->dual_link_port->bonded = width == 2;
+ port->bonded = width > TB_LINK_WIDTH_SINGLE;
+ port->dual_link_port->bonded = width > TB_LINK_WIDTH_SINGLE;
tb_port_update_credits(port);
tb_xdomain_update_link_attributes(xd);
@@ -1425,7 +1427,7 @@ static int tb_xdomain_get_properties(struct tb_xdomain *xd)
if (xd->bonding_possible) {
struct tb_port *port;
- port = tb_port_at(xd->route, tb_xdomain_parent(xd));
+ port = tb_xdomain_downstream_port(xd);
if (!port->bonded)
tb_port_disable(port->dual_link_port);
}
@@ -1737,16 +1739,57 @@ static ssize_t speed_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(rx_speed, 0444, speed_show, NULL);
static DEVICE_ATTR(tx_speed, 0444, speed_show, NULL);
-static ssize_t lanes_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t rx_lanes_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct tb_xdomain *xd = container_of(dev, struct tb_xdomain, dev);
+ unsigned int width;
- return sysfs_emit(buf, "%u\n", xd->link_width);
+ switch (xd->link_width) {
+ case TB_LINK_WIDTH_SINGLE:
+ case TB_LINK_WIDTH_ASYM_RX:
+ width = 1;
+ break;
+ case TB_LINK_WIDTH_DUAL:
+ width = 2;
+ break;
+ case TB_LINK_WIDTH_ASYM_TX:
+ width = 3;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
+
+ return sysfs_emit(buf, "%u\n", width);
}
+static DEVICE_ATTR(rx_lanes, 0444, rx_lanes_show, NULL);
+
+static ssize_t tx_lanes_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct tb_xdomain *xd = container_of(dev, struct tb_xdomain, dev);
+ unsigned int width;
-static DEVICE_ATTR(rx_lanes, 0444, lanes_show, NULL);
-static DEVICE_ATTR(tx_lanes, 0444, lanes_show, NULL);
+ switch (xd->link_width) {
+ case TB_LINK_WIDTH_SINGLE:
+ case TB_LINK_WIDTH_ASYM_TX:
+ width = 1;
+ break;
+ case TB_LINK_WIDTH_DUAL:
+ width = 2;
+ break;
+ case TB_LINK_WIDTH_ASYM_RX:
+ width = 3;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
+
+ return sysfs_emit(buf, "%u\n", width);
+}
+static DEVICE_ATTR(tx_lanes, 0444, tx_lanes_show, NULL);
static struct attribute *xdomain_attrs[] = {
&dev_attr_device.attr,
@@ -1976,10 +2019,11 @@ void tb_xdomain_remove(struct tb_xdomain *xd)
*/
int tb_xdomain_lane_bonding_enable(struct tb_xdomain *xd)
{
+ unsigned int width_mask;
struct tb_port *port;
int ret;
- port = tb_port_at(xd->route, tb_xdomain_parent(xd));
+ port = tb_xdomain_downstream_port(xd);
if (!port->dual_link_port)
return -ENODEV;
@@ -1999,7 +2043,12 @@ int tb_xdomain_lane_bonding_enable(struct tb_xdomain *xd)
return ret;
}
- ret = tb_port_wait_for_link_width(port, 2, XDOMAIN_BONDING_TIMEOUT);
+ /* Any of the widths are all bonded */
+ width_mask = TB_LINK_WIDTH_DUAL | TB_LINK_WIDTH_ASYM_TX |
+ TB_LINK_WIDTH_ASYM_RX;
+
+ ret = tb_port_wait_for_link_width(port, width_mask,
+ XDOMAIN_BONDING_TIMEOUT);
if (ret) {
tb_port_warn(port, "failed to enable lane bonding\n");
return ret;
@@ -2024,10 +2073,13 @@ void tb_xdomain_lane_bonding_disable(struct tb_xdomain *xd)
{
struct tb_port *port;
- port = tb_port_at(xd->route, tb_xdomain_parent(xd));
+ port = tb_xdomain_downstream_port(xd);
if (port->dual_link_port) {
+ int ret;
+
tb_port_lane_bonding_disable(port);
- if (tb_port_wait_for_link_width(port, 1, 100) == -ETIMEDOUT)
+ ret = tb_port_wait_for_link_width(port, TB_LINK_WIDTH_SINGLE, 100);
+ if (ret == -ETIMEDOUT)
tb_port_warn(port, "timeout disabling lane bonding\n");
tb_port_disable(port->dual_link_port);
tb_port_update_credits(port);
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 1c9e5d2ea7de..552e8a741562 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -203,8 +203,8 @@ static void n_tty_kick_worker(struct tty_struct *tty)
struct n_tty_data *ldata = tty->disc_data;
/* Did the input worker stop? Restart it */
- if (unlikely(ldata->no_room)) {
- ldata->no_room = 0;
+ if (unlikely(READ_ONCE(ldata->no_room))) {
+ WRITE_ONCE(ldata->no_room, 0);
WARN_RATELIMIT(tty->port->itty == NULL,
"scheduling with invalid itty\n");
@@ -1697,7 +1697,7 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
if (overflow && room < 0)
ldata->read_head--;
room = overflow;
- ldata->no_room = flow && !room;
+ WRITE_ONCE(ldata->no_room, flow && !room);
} else
overflow = 0;
@@ -1728,6 +1728,17 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
} else
n_tty_check_throttle(tty);
+ if (unlikely(ldata->no_room)) {
+ /*
+ * Barrier here is to ensure to read the latest read_tail in
+ * chars_in_buffer() and to make sure that read_tail is not loaded
+ * before ldata->no_room is set.
+ */
+ smp_mb();
+ if (!chars_in_buffer(tty))
+ n_tty_kick_worker(tty);
+ }
+
up_read(&tty->termios_rwsem);
return rcvd;
@@ -2281,8 +2292,14 @@ more_to_be_read:
if (time)
timeout = time;
}
- if (old_tail != ldata->read_tail)
+ if (old_tail != ldata->read_tail) {
+ /*
+ * Make sure no_room is not read in n_tty_kick_worker()
+ * before setting ldata->read_tail in copy_from_read_buf().
+ */
+ smp_mb();
n_tty_kick_worker(tty);
+ }
up_read(&tty->termios_rwsem);
remove_wait_queue(&tty->read_wait, &wait);
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 1e8fe44a7099..1aa3e55c8b47 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -91,7 +91,6 @@ struct serial8250_config {
#define UART_BUG_TXEN BIT(1) /* UART has buggy TX IIR status */
#define UART_BUG_NOMSR BIT(2) /* UART has buggy MSR status bits (Au1x00) */
#define UART_BUG_THRE BIT(3) /* UART has buggy THRE reassertion */
-#define UART_BUG_PARITY BIT(4) /* UART mishandles parity if FIFO enabled */
#define UART_BUG_TXRACE BIT(5) /* UART Tx fails to set remote DR */
@@ -167,18 +166,21 @@ static unsigned int __maybe_unused serial_icr_read(struct uart_8250_port *up,
void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p);
-static inline int serial_dl_read(struct uart_8250_port *up)
+static inline u32 serial_dl_read(struct uart_8250_port *up)
{
return up->dl_read(up);
}
-static inline void serial_dl_write(struct uart_8250_port *up, int value)
+static inline void serial_dl_write(struct uart_8250_port *up, u32 value)
{
up->dl_write(up, value);
}
static inline bool serial8250_set_THRI(struct uart_8250_port *up)
{
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&up->port.lock);
+
if (up->ier & UART_IER_THRI)
return false;
up->ier |= UART_IER_THRI;
@@ -188,6 +190,9 @@ static inline bool serial8250_set_THRI(struct uart_8250_port *up)
static inline bool serial8250_clear_THRI(struct uart_8250_port *up)
{
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&up->port.lock);
+
if (!(up->ier & UART_IER_THRI))
return false;
up->ier &= ~UART_IER_THRI;
diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
index 9d2a7856784f..4a9e71b2dbbc 100644
--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
+++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
@@ -275,6 +275,9 @@ static void __aspeed_vuart_set_throttle(struct uart_8250_port *up,
{
unsigned char irqs = UART_IER_RLSI | UART_IER_RDI;
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&up->port.lock);
+
up->ier &= ~irqs;
if (!throttle)
up->ier |= irqs;
diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c
index af0e1c070187..d4b05d7ad9e8 100644
--- a/drivers/tty/serial/8250/8250_bcm7271.c
+++ b/drivers/tty/serial/8250/8250_bcm7271.c
@@ -605,9 +605,13 @@ static int brcmuart_startup(struct uart_port *port)
/*
* Disable the Receive Data Interrupt because the DMA engine
* will handle this.
+ *
+ * Synchronize UART_IER access against the console.
*/
+ spin_lock_irq(&port->lock);
up->ier &= ~UART_IER_RDI;
serial_port_out(port, UART_IER, up->ier);
+ spin_unlock_irq(&port->lock);
priv->tx_running = false;
priv->dma.rx_dma = NULL;
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 13bf535eedcd..914e0e6251bf 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -488,6 +488,34 @@ static inline void serial8250_apply_quirks(struct uart_8250_port *up)
up->port.quirks |= skip_txen_test ? UPQ_NO_TXEN_TEST : 0;
}
+static struct uart_8250_port *serial8250_setup_port(int index)
+{
+ struct uart_8250_port *up;
+
+ if (index >= UART_NR)
+ return NULL;
+
+ up = &serial8250_ports[index];
+ up->port.line = index;
+
+ serial8250_init_port(up);
+ if (!base_ops)
+ base_ops = up->port.ops;
+ up->port.ops = &univ8250_port_ops;
+
+ timer_setup(&up->timer, serial8250_timeout, 0);
+
+ up->ops = &univ8250_driver_ops;
+
+ if (IS_ENABLED(CONFIG_ALPHA_JENSEN) ||
+ (IS_ENABLED(CONFIG_ALPHA_GENERIC) && alpha_jensen()))
+ up->port.set_mctrl = alpha_jensen_set_mctrl;
+
+ serial8250_set_defaults(up);
+
+ return up;
+}
+
static void __init serial8250_isa_init_ports(void)
{
struct uart_8250_port *up;
@@ -501,26 +529,13 @@ static void __init serial8250_isa_init_ports(void)
if (nr_uarts > UART_NR)
nr_uarts = UART_NR;
- for (i = 0; i < nr_uarts; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
- struct uart_port *port = &up->port;
-
- port->line = i;
- serial8250_init_port(up);
- if (!base_ops)
- base_ops = port->ops;
- port->ops = &univ8250_port_ops;
-
- timer_setup(&up->timer, serial8250_timeout, 0);
-
- up->ops = &univ8250_driver_ops;
-
- if (IS_ENABLED(CONFIG_ALPHA_JENSEN) ||
- (IS_ENABLED(CONFIG_ALPHA_GENERIC) && alpha_jensen()))
- port->set_mctrl = alpha_jensen_set_mctrl;
-
- serial8250_set_defaults(up);
- }
+ /*
+ * Set up initial isa ports based on nr_uart module param, or else
+ * default to CONFIG_SERIAL_8250_RUNTIME_UARTS. Note that we do not
+ * need to increase nr_uarts when setting up the initial isa ports.
+ */
+ for (i = 0; i < nr_uarts; i++)
+ serial8250_setup_port(i);
/* chain base port ops to support Remote Supervisor Adapter */
univ8250_port_ops = *base_ops;
@@ -586,16 +601,29 @@ static void univ8250_console_write(struct console *co, const char *s,
static int univ8250_console_setup(struct console *co, char *options)
{
+ struct uart_8250_port *up;
struct uart_port *port;
- int retval;
+ int retval, i;
/*
* Check whether an invalid uart number has been specified, and
* if so, search for the first available port that does have
* console support.
*/
- if (co->index >= nr_uarts)
+ if (co->index >= UART_NR)
co->index = 0;
+
+ /*
+ * If the console is past the initial isa ports, init more ports up to
+ * co->index as needed and increment nr_uarts accordingly.
+ */
+ for (i = nr_uarts; i <= co->index; i++) {
+ up = serial8250_setup_port(i);
+ if (!up)
+ return -ENODEV;
+ nr_uarts++;
+ }
+
port = &serial8250_ports[co->index].port;
/* link port to console */
port->cons = co;
@@ -822,12 +850,16 @@ static int serial8250_probe(struct platform_device *dev)
uart.port.iotype = p->iotype;
uart.port.flags = p->flags;
uart.port.mapbase = p->mapbase;
+ uart.port.mapsize = p->mapsize;
uart.port.hub6 = p->hub6;
uart.port.has_sysrq = p->has_sysrq;
uart.port.private_data = p->private_data;
uart.port.type = p->type;
+ uart.bugs = p->bugs;
uart.port.serial_in = p->serial_in;
uart.port.serial_out = p->serial_out;
+ uart.dl_read = p->dl_read;
+ uart.dl_write = p->dl_write;
uart.port.handle_irq = p->handle_irq;
uart.port.handle_break = p->handle_break;
uart.port.set_termios = p->set_termios;
@@ -990,12 +1022,24 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
mutex_lock(&serial_mutex);
uart = serial8250_find_match_or_unused(&up->port);
- if (uart && uart->port.type != PORT_8250_CIR) {
+ if (!uart) {
+ /*
+ * If the port is past the initial isa ports, initialize a new
+ * port and increment nr_uarts accordingly.
+ */
+ uart = serial8250_setup_port(nr_uarts);
+ if (!uart)
+ goto unlock;
+ nr_uarts++;
+ }
+
+ if (uart->port.type != PORT_8250_CIR) {
struct mctrl_gpios *gpios;
if (uart->port.dev)
uart_remove_one_port(&serial8250_reg, &uart->port);
+ uart->port.ctrl_id = up->port.ctrl_id;
uart->port.iobase = up->port.iobase;
uart->port.membase = up->port.membase;
uart->port.irq = up->port.irq;
@@ -1120,6 +1164,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
}
}
+unlock:
mutex_unlock(&serial_mutex);
return ret;
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index 0ebde0ab8167..4299a8bd83d9 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -36,7 +36,6 @@
static unsigned int serial8250_early_in(struct uart_port *port, int offset)
{
- int reg_offset = offset;
offset <<= port->regshift;
switch (port->iotype) {
@@ -50,8 +49,6 @@ static unsigned int serial8250_early_in(struct uart_port *port, int offset)
return ioread32be(port->membase + offset);
case UPIO_PORT:
return inb(port->iobase + offset);
- case UPIO_AU:
- return port->serial_in(port, reg_offset);
default:
return 0;
}
@@ -59,7 +56,6 @@ static unsigned int serial8250_early_in(struct uart_port *port, int offset)
static void serial8250_early_out(struct uart_port *port, int offset, int value)
{
- int reg_offset = offset;
offset <<= port->regshift;
switch (port->iotype) {
@@ -78,9 +74,6 @@ static void serial8250_early_out(struct uart_port *port, int offset, int value)
case UPIO_PORT:
outb(value, port->iobase + offset);
break;
- case UPIO_AU:
- port->serial_out(port, reg_offset, value);
- break;
}
}
@@ -199,17 +192,3 @@ OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup);
OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup);
#endif
-
-#ifdef CONFIG_SERIAL_8250_RT288X
-
-static int __init early_au_setup(struct earlycon_device *dev, const char *opt)
-{
- dev->port.serial_in = au_serial_in;
- dev->port.serial_out = au_serial_out;
- dev->port.iotype = UPIO_AU;
- dev->con->write = early_serial8250_write;
- return 0;
-}
-OF_EARLYCON_DECLARE(palmchip, "ralink,rt2880-uart", early_au_setup);
-
-#endif
diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
index 25a9ecf26be6..ef5019e944ea 100644
--- a/drivers/tty/serial/8250/8250_em.c
+++ b/drivers/tty/serial/8250/8250_em.c
@@ -139,12 +139,12 @@ static void serial8250_em_serial_out(struct uart_port *p, int offset, int value)
}
}
-static int serial8250_em_serial_dl_read(struct uart_8250_port *up)
+static u32 serial8250_em_serial_dl_read(struct uart_8250_port *up)
{
return serial_in(up, UART_DLL_EM) | serial_in(up, UART_DLM_EM) << 8;
}
-static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value)
+static void serial8250_em_serial_dl_write(struct uart_8250_port *up, u32 value)
{
serial_out(up, UART_DLL_EM, value & 0xff);
serial_out(up, UART_DLM_EM, value >> 8 & 0xff);
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index b406cba10b0e..077c3ba3539e 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -198,8 +198,12 @@ static int xr17v35x_startup(struct uart_port *port)
/*
* Make sure all interrups are masked until initialization is
* complete and the FIFOs are cleared
+ *
+ * Synchronize UART_IER access against the console.
*/
+ spin_lock_irq(&port->lock);
serial_port_out(port, UART_IER, 0);
+ spin_unlock_irq(&port->lock);
return serial8250_do_startup(port);
}
diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c
index 8adfaa183f77..6af4e1c1210a 100644
--- a/drivers/tty/serial/8250/8250_fsl.c
+++ b/drivers/tty/serial/8250/8250_fsl.c
@@ -38,7 +38,19 @@ int fsl8250_handle_irq(struct uart_port *port)
return 0;
}
- /* This is the WAR; if last event was BRK, then read and return */
+ /*
+ * For a single break the hardware reports LSR.BI for each character
+ * time. This is described in the MPC8313E chip errata as "General17".
+ * A typical break has a duration of 0.3s, with a 115200n8 configuration
+ * that (theoretically) corresponds to ~3500 interrupts in these 0.3s.
+ * In practise it's less (around 500) because of hardware
+ * and software latencies. The workaround recommended by the vendor is
+ * to read the RX register (to clear LSR.DR and thus prevent a FIFO
+ * aging interrupt). To prevent the irq from retriggering LSR must not be
+ * read. (This would clear LSR.BI, hardware would reassert the BI event
+ * immediately and interrupt the CPU again. The hardware clears LSR.BI
+ * when the next valid char is read.)
+ */
if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) {
up->lsr_saved_flags &= ~UART_LSR_BI;
port->serial_in(port, UART_RX);
@@ -172,3 +184,6 @@ static struct platform_driver fsl8250_platform_driver = {
module_platform_driver(fsl8250_platform_driver);
#endif
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Handling of Freescale specific 8250 variants");
diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index fb1d5ec0940e..74da5676ce67 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -222,11 +222,17 @@ static void mtk8250_shutdown(struct uart_port *port)
static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask)
{
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&up->port.lock);
+
serial_out(up, UART_IER, serial_in(up, UART_IER) & (~mask));
}
static void mtk8250_enable_intrs(struct uart_8250_port *up, int mask)
{
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&up->port.lock);
+
serial_out(up, UART_IER, serial_in(up, UART_IER) | mask);
}
@@ -235,6 +241,9 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
struct uart_port *port = &up->port;
int lcr = serial_in(up, UART_LCR);
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&port->lock);
+
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, MTK_UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, lcr);
@@ -422,12 +431,7 @@ static int __maybe_unused mtk8250_runtime_suspend(struct device *dev)
while
(serial_in(up, MTK_UART_DEBUG0));
- if (data->clk_count == 0U) {
- dev_dbg(dev, "%s clock count is 0\n", __func__);
- } else {
- clk_disable_unprepare(data->bus_clk);
- data->clk_count--;
- }
+ clk_disable_unprepare(data->bus_clk);
return 0;
}
@@ -435,19 +439,8 @@ static int __maybe_unused mtk8250_runtime_suspend(struct device *dev)
static int __maybe_unused mtk8250_runtime_resume(struct device *dev)
{
struct mtk8250_data *data = dev_get_drvdata(dev);
- int err;
- if (data->clk_count > 0U) {
- dev_dbg(dev, "%s clock count is %d\n", __func__,
- data->clk_count);
- } else {
- err = clk_prepare_enable(data->bus_clk);
- if (err) {
- dev_warn(dev, "Can't enable bus clock\n");
- return err;
- }
- data->clk_count++;
- }
+ clk_prepare_enable(data->bus_clk);
return 0;
}
@@ -456,14 +449,12 @@ static void
mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
{
if (!state)
- if (!mtk8250_runtime_resume(port->dev))
- pm_runtime_get_sync(port->dev);
+ pm_runtime_get_sync(port->dev);
serial8250_do_pm(port, state, old);
if (state)
- if (!pm_runtime_put_sync_suspend(port->dev))
- mtk8250_runtime_suspend(port->dev);
+ pm_runtime_put_sync_suspend(port->dev);
}
#ifdef CONFIG_SERIAL_8250_DMA
@@ -495,7 +486,7 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
return 0;
}
- data->bus_clk = devm_clk_get(&pdev->dev, "bus");
+ data->bus_clk = devm_clk_get_enabled(&pdev->dev, "bus");
if (IS_ERR(data->bus_clk))
return PTR_ERR(data->bus_clk);
@@ -578,25 +569,16 @@ static int mtk8250_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
- pm_runtime_enable(&pdev->dev);
- err = mtk8250_runtime_resume(&pdev->dev);
- if (err)
- goto err_pm_disable;
-
data->line = serial8250_register_8250_port(&uart);
- if (data->line < 0) {
- err = data->line;
- goto err_pm_disable;
- }
+ if (data->line < 0)
+ return data->line;
data->rx_wakeup_irq = platform_get_irq_optional(pdev, 1);
- return 0;
-
-err_pm_disable:
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
- return err;
+ return 0;
}
static int mtk8250_remove(struct platform_device *pdev)
@@ -610,9 +592,6 @@ static int mtk8250_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
- if (!pm_runtime_status_suspended(&pdev->dev))
- mtk8250_runtime_suspend(&pdev->dev);
-
return 0;
}
diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index 1b461fba15a3..51329625c48a 100644
--- a/drivers/tty/serial/8250/8250_of.c
+++ b/drivers/tty/serial/8250/8250_of.c
@@ -171,11 +171,13 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
switch (type) {
case PORT_RT2880:
- port->iotype = UPIO_AU;
+ ret = rt288x_setup(port);
+ if (ret)
+ goto err_unprepare;
break;
}
- if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) &&
+ if (IS_REACHABLE(CONFIG_SERIAL_8250_FSL) &&
(of_device_is_compatible(np, "fsl,ns16550") ||
of_device_is_compatible(np, "fsl,16550-FIFO64"))) {
port->handle_irq = fsl8250_handle_irq;
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 734f092ef839..d48a82f1634e 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -32,6 +32,7 @@
#include "8250.h"
#define DEFAULT_CLK_SPEED 48000000
+#define OMAP_UART_REGSHIFT 2
#define UART_ERRATA_i202_MDR1_ACCESS (1 << 0)
#define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1)
@@ -115,6 +116,7 @@
#define UART_OMAP_RX_LVL 0x19
struct omap8250_priv {
+ void __iomem *membase;
int line;
u8 habit;
u8 mdr1;
@@ -159,9 +161,9 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p);
static inline void omap_8250_rx_dma_flush(struct uart_8250_port *p) { }
#endif
-static u32 uart_read(struct uart_8250_port *up, u32 reg)
+static u32 uart_read(struct omap8250_priv *priv, u32 reg)
{
- return readl(up->port.membase + (reg << up->port.regshift));
+ return readl(priv->membase + (reg << OMAP_UART_REGSHIFT));
}
/*
@@ -302,6 +304,9 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
struct uart_8250_dma *dma = up->dma;
u8 mcr = serial8250_in_MCR(up);
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&up->port.lock);
+
if (dma && dma->tx_running) {
/*
* TCSANOW requests the change to occur immediately however if
@@ -523,6 +528,10 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state,
u8 efr;
pm_runtime_get_sync(port->dev);
+
+ /* Synchronize UART_IER access against the console. */
+ spin_lock_irq(&port->lock);
+
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, efr | UART_EFR_ECB);
@@ -533,6 +542,8 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state,
serial_out(up, UART_EFR, efr);
serial_out(up, UART_LCR, 0);
+ spin_unlock_irq(&port->lock);
+
pm_runtime_mark_last_busy(port->dev);
pm_runtime_put_autosuspend(port->dev);
}
@@ -548,7 +559,7 @@ static void omap_serial_fill_features_erratas(struct uart_8250_port *up,
u32 mvr, scheme;
u16 revision, major, minor;
- mvr = uart_read(up, UART_OMAP_MVER);
+ mvr = uart_read(priv, UART_OMAP_MVER);
/* Check revision register scheme */
scheme = mvr >> OMAP_UART_MVR_SCHEME_SHIFT;
@@ -616,9 +627,9 @@ static int omap_8250_dma_handle_irq(struct uart_port *port);
static irqreturn_t omap8250_irq(int irq, void *dev_id)
{
- struct uart_port *port = dev_id;
- struct omap8250_priv *priv = port->private_data;
- struct uart_8250_port *up = up_to_u8250p(port);
+ struct omap8250_priv *priv = dev_id;
+ struct uart_8250_port *up = serial8250_get_port(priv->line);
+ struct uart_port *port = &up->port;
unsigned int iir, lsr;
int ret;
@@ -649,6 +660,8 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
if ((lsr & UART_LSR_OE) && up->overrun_backoff_time_ms > 0) {
unsigned long delay;
+ /* Synchronize UART_IER access against the console. */
+ spin_lock(&port->lock);
up->ier = port->serial_in(port, UART_IER);
if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) {
port->ops->stop_rx(port);
@@ -658,6 +671,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
*/
cancel_delayed_work(&up->overrun_backoff);
}
+ spin_unlock(&port->lock);
delay = msecs_to_jiffies(up->overrun_backoff_time_ms);
schedule_delayed_work(&up->overrun_backoff, delay);
@@ -672,6 +686,7 @@ static int omap_8250_startup(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
struct omap8250_priv *priv = port->private_data;
+ struct uart_8250_dma *dma = &priv->omap8250_dma;
int ret;
if (priv->wakeirq) {
@@ -690,25 +705,23 @@ static int omap_8250_startup(struct uart_port *port)
up->msr_saved_flags = 0;
/* Disable DMA for console UART */
- if (uart_console(port))
- up->dma = NULL;
-
- if (up->dma) {
+ if (dma->fn && !uart_console(port)) {
+ up->dma = &priv->omap8250_dma;
ret = serial8250_request_dma(up);
if (ret) {
dev_warn_ratelimited(port->dev,
"failed to request DMA\n");
up->dma = NULL;
}
+ } else {
+ up->dma = NULL;
}
- ret = request_irq(port->irq, omap8250_irq, IRQF_SHARED,
- dev_name(port->dev), port);
- if (ret < 0)
- goto err;
-
+ /* Synchronize UART_IER access against the console. */
+ spin_lock_irq(&port->lock);
up->ier = UART_IER_RLSI | UART_IER_RDI;
serial_out(up, UART_IER, up->ier);
+ spin_unlock_irq(&port->lock);
#ifdef CONFIG_PM
up->capabilities |= UART_CAP_RPM;
@@ -720,17 +733,17 @@ static int omap_8250_startup(struct uart_port *port)
priv->wer |= OMAP_UART_TX_WAKEUP_EN;
serial_out(up, UART_OMAP_WER, priv->wer);
- if (up->dma && !(priv->habit & UART_HAS_EFR2))
+ if (up->dma && !(priv->habit & UART_HAS_EFR2)) {
+ spin_lock_irq(&port->lock);
up->dma->rx_dma(up);
+ spin_unlock_irq(&port->lock);
+ }
+
+ enable_irq(up->port.irq);
pm_runtime_mark_last_busy(port->dev);
pm_runtime_put_autosuspend(port->dev);
return 0;
-err:
- pm_runtime_mark_last_busy(port->dev);
- pm_runtime_put_autosuspend(port->dev);
- dev_pm_clear_wake_irq(port->dev);
- return ret;
}
static void omap_8250_shutdown(struct uart_port *port)
@@ -748,11 +761,16 @@ static void omap_8250_shutdown(struct uart_port *port)
if (priv->habit & UART_HAS_EFR2)
serial_out(up, UART_OMAP_EFR2, 0x0);
+ /* Synchronize UART_IER access against the console. */
+ spin_lock_irq(&port->lock);
up->ier = 0;
serial_out(up, UART_IER, 0);
+ spin_unlock_irq(&port->lock);
+ disable_irq_nosync(up->port.irq);
+ dev_pm_clear_wake_irq(port->dev);
- if (up->dma)
- serial8250_release_dma(up);
+ serial8250_release_dma(up);
+ up->dma = NULL;
/*
* Disable break condition and FIFOs
@@ -763,8 +781,6 @@ static void omap_8250_shutdown(struct uart_port *port)
pm_runtime_mark_last_busy(port->dev);
pm_runtime_put_autosuspend(port->dev);
- free_irq(port->irq, port);
- dev_pm_clear_wake_irq(port->dev);
}
static void omap_8250_throttle(struct uart_port *port)
@@ -791,6 +807,7 @@ static void omap_8250_unthrottle(struct uart_port *port)
pm_runtime_get_sync(port->dev);
+ /* Synchronize UART_IER access against the console. */
spin_lock_irqsave(&port->lock, flags);
priv->throttled = false;
if (up->dma)
@@ -941,6 +958,7 @@ static void __dma_rx_complete(void *param)
struct dma_tx_state state;
unsigned long flags;
+ /* Synchronize UART_IER access against the console. */
spin_lock_irqsave(&p->port.lock, flags);
/*
@@ -998,6 +1016,9 @@ static int omap_8250_rx_dma(struct uart_8250_port *p)
unsigned long flags;
u32 reg;
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&p->port.lock);
+
if (priv->rx_dma_broken)
return -EINVAL;
@@ -1212,6 +1233,9 @@ static u16 omap_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, u16 status
static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir,
u16 status)
{
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&up->port.lock);
+
/*
* Queue a new transfer if FIFO has data.
*/
@@ -1394,7 +1418,7 @@ static int omap8250_probe(struct platform_device *pdev)
UPF_HARD_FLOW;
up.port.private_data = priv;
- up.port.regshift = 2;
+ up.port.regshift = OMAP_UART_REGSHIFT;
up.port.fifosize = 64;
up.tx_loadsz = 64;
up.capabilities = UART_CAP_FIFO;
@@ -1444,8 +1468,6 @@ static int omap8250_probe(struct platform_device *pdev)
&up.overrun_backoff_time_ms) != 0)
up.overrun_backoff_time_ms = 0;
- priv->wakeirq = irq_of_parse_and_map(np, 1);
-
pdata = of_device_get_match_data(&pdev->dev);
if (pdata)
priv->habit |= pdata->habit;
@@ -1457,6 +1479,8 @@ static int omap8250_probe(struct platform_device *pdev)
DEFAULT_CLK_SPEED);
}
+ priv->membase = membase;
+ priv->line = -ENODEV;
priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE;
priv->calc_latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE;
cpu_latency_qos_add_request(&priv->pm_qos_request, priv->latency);
@@ -1464,6 +1488,8 @@ static int omap8250_probe(struct platform_device *pdev)
spin_lock_init(&priv->rx_dma_lock);
+ platform_set_drvdata(pdev, priv);
+
device_init_wakeup(&pdev->dev, true);
pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
@@ -1498,64 +1524,77 @@ static int omap8250_probe(struct platform_device *pdev)
ret = of_property_count_strings(np, "dma-names");
if (ret == 2) {
struct omap8250_dma_params *dma_params = NULL;
+ struct uart_8250_dma *dma = &priv->omap8250_dma;
- up.dma = &priv->omap8250_dma;
- up.dma->fn = the_no_dma_filter_fn;
- up.dma->tx_dma = omap_8250_tx_dma;
- up.dma->rx_dma = omap_8250_rx_dma;
+ dma->fn = the_no_dma_filter_fn;
+ dma->tx_dma = omap_8250_tx_dma;
+ dma->rx_dma = omap_8250_rx_dma;
if (pdata)
dma_params = pdata->dma_params;
if (dma_params) {
- up.dma->rx_size = dma_params->rx_size;
- up.dma->rxconf.src_maxburst = dma_params->rx_trigger;
- up.dma->txconf.dst_maxburst = dma_params->tx_trigger;
+ dma->rx_size = dma_params->rx_size;
+ dma->rxconf.src_maxburst = dma_params->rx_trigger;
+ dma->txconf.dst_maxburst = dma_params->tx_trigger;
priv->rx_trigger = dma_params->rx_trigger;
priv->tx_trigger = dma_params->tx_trigger;
} else {
- up.dma->rx_size = RX_TRIGGER;
- up.dma->rxconf.src_maxburst = RX_TRIGGER;
- up.dma->txconf.dst_maxburst = TX_TRIGGER;
+ dma->rx_size = RX_TRIGGER;
+ dma->rxconf.src_maxburst = RX_TRIGGER;
+ dma->txconf.dst_maxburst = TX_TRIGGER;
}
}
#endif
+
+ irq_set_status_flags(irq, IRQ_NOAUTOEN);
+ ret = devm_request_irq(&pdev->dev, irq, omap8250_irq, 0,
+ dev_name(&pdev->dev), priv);
+ if (ret < 0)
+ return ret;
+
+ priv->wakeirq = irq_of_parse_and_map(np, 1);
+
ret = serial8250_register_8250_port(&up);
if (ret < 0) {
dev_err(&pdev->dev, "unable to register 8250 port\n");
goto err;
}
priv->line = ret;
- platform_set_drvdata(pdev, priv);
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
return 0;
err:
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
+ flush_work(&priv->qos_work);
pm_runtime_disable(&pdev->dev);
+ cpu_latency_qos_remove_request(&priv->pm_qos_request);
return ret;
}
static int omap8250_remove(struct platform_device *pdev)
{
struct omap8250_priv *priv = platform_get_drvdata(pdev);
+ struct uart_8250_port *up;
int err;
err = pm_runtime_resume_and_get(&pdev->dev);
if (err)
return err;
+ up = serial8250_get_port(priv->line);
+ omap_8250_shutdown(&up->port);
+ serial8250_unregister_port(priv->line);
+ priv->line = -ENODEV;
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
flush_work(&priv->qos_work);
pm_runtime_disable(&pdev->dev);
- serial8250_unregister_port(priv->line);
cpu_latency_qos_remove_request(&priv->pm_qos_request);
device_init_wakeup(&pdev->dev, false);
return 0;
}
-#ifdef CONFIG_PM_SLEEP
static int omap8250_prepare(struct device *dev)
{
struct omap8250_priv *priv = dev_get_drvdata(dev);
@@ -1579,33 +1618,38 @@ static int omap8250_suspend(struct device *dev)
{
struct omap8250_priv *priv = dev_get_drvdata(dev);
struct uart_8250_port *up = serial8250_get_port(priv->line);
+ int err;
serial8250_suspend_port(priv->line);
- pm_runtime_get_sync(dev);
+ err = pm_runtime_resume_and_get(dev);
+ if (err)
+ return err;
if (!device_may_wakeup(dev))
priv->wer = 0;
serial_out(up, UART_OMAP_WER, priv->wer);
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
-
+ err = pm_runtime_force_suspend(dev);
flush_work(&priv->qos_work);
- return 0;
+
+ return err;
}
static int omap8250_resume(struct device *dev)
{
struct omap8250_priv *priv = dev_get_drvdata(dev);
+ int err;
+ err = pm_runtime_force_resume(dev);
+ if (err)
+ return err;
serial8250_resume_port(priv->line);
+ /* Paired with pm_runtime_resume_and_get() in omap8250_suspend() */
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
return 0;
}
-#else
-#define omap8250_prepare NULL
-#define omap8250_complete NULL
-#endif
-#ifdef CONFIG_PM
static int omap8250_lost_context(struct uart_8250_port *up)
{
u32 val;
@@ -1621,11 +1665,15 @@ static int omap8250_lost_context(struct uart_8250_port *up)
return 0;
}
+static void uart_write(struct omap8250_priv *priv, u32 reg, u32 val)
+{
+ writel(val, priv->membase + (reg << OMAP_UART_REGSHIFT));
+}
+
/* TODO: in future, this should happen via API in drivers/reset/ */
static int omap8250_soft_reset(struct device *dev)
{
struct omap8250_priv *priv = dev_get_drvdata(dev);
- struct uart_8250_port *up = serial8250_get_port(priv->line);
int timeout = 100;
int sysc;
int syss;
@@ -1639,20 +1687,20 @@ static int omap8250_soft_reset(struct device *dev)
* needing omap8250_soft_reset() quirk. Do it in two writes as
* recommended in the comment for omap8250_update_scr().
*/
- serial_out(up, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1);
- serial_out(up, UART_OMAP_SCR,
+ uart_write(priv, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1);
+ uart_write(priv, UART_OMAP_SCR,
OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL);
- sysc = serial_in(up, UART_OMAP_SYSC);
+ sysc = uart_read(priv, UART_OMAP_SYSC);
/* softreset the UART */
sysc |= OMAP_UART_SYSC_SOFTRESET;
- serial_out(up, UART_OMAP_SYSC, sysc);
+ uart_write(priv, UART_OMAP_SYSC, sysc);
/* By experiments, 1us enough for reset complete on AM335x */
do {
udelay(1);
- syss = serial_in(up, UART_OMAP_SYSS);
+ syss = uart_read(priv, UART_OMAP_SYSS);
} while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE));
if (!timeout) {
@@ -1666,13 +1714,10 @@ static int omap8250_soft_reset(struct device *dev)
static int omap8250_runtime_suspend(struct device *dev)
{
struct omap8250_priv *priv = dev_get_drvdata(dev);
- struct uart_8250_port *up;
-
- /* In case runtime-pm tries this before we are setup */
- if (!priv)
- return 0;
+ struct uart_8250_port *up = NULL;
- up = serial8250_get_port(priv->line);
+ if (priv->line >= 0)
+ up = serial8250_get_port(priv->line);
/*
* When using 'no_console_suspend', the console UART must not be
* suspended. Since driver suspend is managed by runtime suspend,
@@ -1680,7 +1725,7 @@ static int omap8250_runtime_suspend(struct device *dev)
* active during suspend.
*/
if (priv->is_suspending && !console_suspend_enabled) {
- if (uart_console(&up->port))
+ if (up && uart_console(&up->port))
return -EBUSY;
}
@@ -1691,13 +1736,15 @@ static int omap8250_runtime_suspend(struct device *dev)
if (ret)
return ret;
- /* Restore to UART mode after reset (for wakeup) */
- omap8250_update_mdr1(up, priv);
- /* Restore wakeup enable register */
- serial_out(up, UART_OMAP_WER, priv->wer);
+ if (up) {
+ /* Restore to UART mode after reset (for wakeup) */
+ omap8250_update_mdr1(up, priv);
+ /* Restore wakeup enable register */
+ serial_out(up, UART_OMAP_WER, priv->wer);
+ }
}
- if (up->dma && up->dma->rxchan)
+ if (up && up->dma && up->dma->rxchan)
omap_8250_rx_dma_flush(up);
priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE;
@@ -1709,25 +1756,27 @@ static int omap8250_runtime_suspend(struct device *dev)
static int omap8250_runtime_resume(struct device *dev)
{
struct omap8250_priv *priv = dev_get_drvdata(dev);
- struct uart_8250_port *up;
-
- /* In case runtime-pm tries this before we are setup */
- if (!priv)
- return 0;
+ struct uart_8250_port *up = NULL;
- up = serial8250_get_port(priv->line);
+ if (priv->line >= 0)
+ up = serial8250_get_port(priv->line);
- if (omap8250_lost_context(up))
+ if (up && omap8250_lost_context(up)) {
+ spin_lock_irq(&up->port.lock);
omap8250_restore_regs(up);
+ spin_unlock_irq(&up->port.lock);
+ }
- if (up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2))
+ if (up && up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2)) {
+ spin_lock_irq(&up->port.lock);
omap_8250_rx_dma(up);
+ spin_unlock_irq(&up->port.lock);
+ }
priv->latency = priv->calc_latency;
schedule_work(&priv->qos_work);
return 0;
}
-#endif
#ifdef CONFIG_SERIAL_8250_OMAP_TTYO_FIXUP
static int __init omap8250_console_fixup(void)
@@ -1770,17 +1819,17 @@ console_initcall(omap8250_console_fixup);
#endif
static const struct dev_pm_ops omap8250_dev_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(omap8250_suspend, omap8250_resume)
- SET_RUNTIME_PM_OPS(omap8250_runtime_suspend,
+ SYSTEM_SLEEP_PM_OPS(omap8250_suspend, omap8250_resume)
+ RUNTIME_PM_OPS(omap8250_runtime_suspend,
omap8250_runtime_resume, NULL)
- .prepare = omap8250_prepare,
- .complete = omap8250_complete,
+ .prepare = pm_sleep_ptr(omap8250_prepare),
+ .complete = pm_sleep_ptr(omap8250_complete),
};
static struct platform_driver omap8250_platform_driver = {
.driver = {
.name = "omap8250",
- .pm = &omap8250_dev_pm_ops,
+ .pm = pm_ptr(&omap8250_dev_pm_ops),
.of_match_table = omap8250_dt_ids,
},
.probe = omap8250_probe,
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index e80c4f6551a1..d2d547b5da95 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1232,14 +1232,6 @@ static int pci_oxsemi_tornado_setup(struct serial_private *priv,
return pci_default_setup(priv, board, up, idx);
}
-static int pci_asix_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_8250_port *port, int idx)
-{
- port->bugs |= UART_BUG_PARITY;
- return pci_default_setup(priv, board, port, idx);
-}
-
#define QPCR_TEST_FOR1 0x3F
#define QPCR_TEST_GET1 0x00
#define QPCR_TEST_FOR2 0x40
@@ -1955,7 +1947,6 @@ pci_moxa_setup(struct serial_private *priv,
#define PCI_DEVICE_ID_WCH_CH355_4S 0x7173
#define PCI_VENDOR_ID_AGESTAR 0x5372
#define PCI_DEVICE_ID_AGESTAR_9375 0x6872
-#define PCI_VENDOR_ID_ASIX 0x9710
#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
#define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e
@@ -2601,16 +2592,6 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.setup = pci_wch_ch38x_setup,
},
/*
- * ASIX devices with FIFO bug
- */
- {
- .vendor = PCI_VENDOR_ID_ASIX,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_asix_setup,
- },
- /*
* Broadcom TruManage (NetXtreme)
*/
{
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index c153ba3a018a..16aeb1420137 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -325,7 +325,7 @@ static const struct serial8250_config uart_config[] = {
};
/* Uart divisor latch read */
-static int default_serial_dl_read(struct uart_8250_port *up)
+static u32 default_serial_dl_read(struct uart_8250_port *up)
{
/* Assign these in pieces to truncate any bits above 7. */
unsigned char dll = serial_in(up, UART_DLL);
@@ -335,72 +335,12 @@ static int default_serial_dl_read(struct uart_8250_port *up)
}
/* Uart divisor latch write */
-static void default_serial_dl_write(struct uart_8250_port *up, int value)
+static void default_serial_dl_write(struct uart_8250_port *up, u32 value)
{
serial_out(up, UART_DLL, value & 0xff);
serial_out(up, UART_DLM, value >> 8 & 0xff);
}
-#ifdef CONFIG_SERIAL_8250_RT288X
-
-#define UART_REG_UNMAPPED -1
-
-/* Au1x00/RT288x UART hardware has a weird register layout */
-static const s8 au_io_in_map[8] = {
- [UART_RX] = 0,
- [UART_IER] = 2,
- [UART_IIR] = 3,
- [UART_LCR] = 5,
- [UART_MCR] = 6,
- [UART_LSR] = 7,
- [UART_MSR] = 8,
- [UART_SCR] = UART_REG_UNMAPPED,
-};
-
-static const s8 au_io_out_map[8] = {
- [UART_TX] = 1,
- [UART_IER] = 2,
- [UART_FCR] = 4,
- [UART_LCR] = 5,
- [UART_MCR] = 6,
- [UART_LSR] = UART_REG_UNMAPPED,
- [UART_MSR] = UART_REG_UNMAPPED,
- [UART_SCR] = UART_REG_UNMAPPED,
-};
-
-unsigned int au_serial_in(struct uart_port *p, int offset)
-{
- if (offset >= ARRAY_SIZE(au_io_in_map))
- return UINT_MAX;
- offset = au_io_in_map[offset];
- if (offset == UART_REG_UNMAPPED)
- return UINT_MAX;
- return __raw_readl(p->membase + (offset << p->regshift));
-}
-
-void au_serial_out(struct uart_port *p, int offset, int value)
-{
- if (offset >= ARRAY_SIZE(au_io_out_map))
- return;
- offset = au_io_out_map[offset];
- if (offset == UART_REG_UNMAPPED)
- return;
- __raw_writel(value, p->membase + (offset << p->regshift));
-}
-
-/* Au1x00 haven't got a standard divisor latch */
-static int au_serial_dl_read(struct uart_8250_port *up)
-{
- return __raw_readl(up->port.membase + 0x28);
-}
-
-static void au_serial_dl_write(struct uart_8250_port *up, int value)
-{
- __raw_writel(value, up->port.membase + 0x28);
-}
-
-#endif
-
static unsigned int hub6_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
@@ -510,15 +450,6 @@ static void set_io_from_upio(struct uart_port *p)
p->serial_out = mem32be_serial_out;
break;
-#ifdef CONFIG_SERIAL_8250_RT288X
- case UPIO_AU:
- p->serial_in = au_serial_in;
- p->serial_out = au_serial_out;
- up->dl_read = au_serial_dl_read;
- up->dl_write = au_serial_dl_write;
- break;
-#endif
-
default:
p->serial_in = io_serial_in;
p->serial_out = io_serial_out;
@@ -608,6 +539,9 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put);
*/
static int serial8250_em485_init(struct uart_8250_port *p)
{
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&p->port.lock);
+
if (p->em485)
goto deassert_rts;
@@ -746,6 +680,8 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
serial8250_rpm_get(p);
if (p->capabilities & UART_CAP_SLEEP) {
+ /* Synchronize UART_IER access against the console. */
+ spin_lock_irq(&p->port.lock);
if (p->capabilities & UART_CAP_EFR) {
lcr = serial_in(p, UART_LCR);
efr = serial_in(p, UART_EFR);
@@ -759,6 +695,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
serial_out(p, UART_EFR, efr);
serial_out(p, UART_LCR, lcr);
}
+ spin_unlock_irq(&p->port.lock);
}
serial8250_rpm_put(p);
@@ -766,6 +703,9 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
static void serial8250_clear_IER(struct uart_8250_port *up)
{
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&up->port.lock);
+
if (up->capabilities & UART_CAP_UUE)
serial_out(up, UART_IER, UART_IER_UUE);
else
@@ -848,7 +788,7 @@ static void disable_rsa(struct uart_8250_port *up)
static int size_fifo(struct uart_8250_port *up)
{
unsigned char old_fcr, old_mcr, old_lcr;
- unsigned short old_dl;
+ u32 old_dl;
int count;
old_lcr = serial_in(up, UART_LCR);
@@ -1038,6 +978,9 @@ static void autoconfig_16550a(struct uart_8250_port *up)
unsigned char status1, status2;
unsigned int iersave;
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&up->port.lock);
+
up->port.type = PORT_16550A;
up->capabilities |= UART_CAP_FIFO;
@@ -1221,6 +1164,8 @@ static void autoconfig(struct uart_8250_port *up)
/*
* We really do need global IRQs disabled here - we're going to
* be frobbing the chips IRQ enable register to see if it exists.
+ *
+ * Synchronize UART_IER access against the console.
*/
spin_lock_irqsave(&port->lock, flags);
@@ -1393,7 +1338,10 @@ static void autoconfig_irq(struct uart_8250_port *up)
/* forget possible initially masked and pending IRQ */
probe_irq_off(probe_irq_on());
save_mcr = serial8250_in_MCR(up);
+ /* Synchronize UART_IER access against the console. */
+ spin_lock_irq(&port->lock);
save_ier = serial_in(up, UART_IER);
+ spin_unlock_irq(&port->lock);
serial8250_out_MCR(up, UART_MCR_OUT1 | UART_MCR_OUT2);
irqs = probe_irq_on();
@@ -1405,7 +1353,10 @@ static void autoconfig_irq(struct uart_8250_port *up)
serial8250_out_MCR(up,
UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
}
+ /* Synchronize UART_IER access against the console. */
+ spin_lock_irq(&port->lock);
serial_out(up, UART_IER, UART_IER_ALL_INTR);
+ spin_unlock_irq(&port->lock);
serial_in(up, UART_LSR);
serial_in(up, UART_RX);
serial_in(up, UART_IIR);
@@ -1415,7 +1366,10 @@ static void autoconfig_irq(struct uart_8250_port *up)
irq = probe_irq_off(irqs);
serial8250_out_MCR(up, save_mcr);
+ /* Synchronize UART_IER access against the console. */
+ spin_lock_irq(&port->lock);
serial_out(up, UART_IER, save_ier);
+ spin_unlock_irq(&port->lock);
if (port->flags & UPF_FOURPORT)
outb_p(save_ICP, ICP);
@@ -1430,6 +1384,9 @@ static void serial8250_stop_rx(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&port->lock);
+
serial8250_rpm_get(up);
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
@@ -1449,6 +1406,9 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p)
{
unsigned char mcr = serial8250_in_MCR(p);
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&p->port.lock);
+
if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND)
mcr |= UART_MCR_RTS;
else
@@ -1498,6 +1458,9 @@ static void __stop_tx_rs485(struct uart_8250_port *p, u64 stop_delay)
{
struct uart_8250_em485 *em485 = p->em485;
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&p->port.lock);
+
stop_delay += (u64)p->port.rs485.delay_rts_after_send * NSEC_PER_MSEC;
/*
@@ -1677,6 +1640,9 @@ static void serial8250_start_tx(struct uart_port *port)
struct uart_8250_port *up = up_to_u8250p(port);
struct uart_8250_em485 *em485 = up->em485;
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&port->lock);
+
if (!port->x_char && uart_circ_empty(&port->state->xmit))
return;
@@ -1704,6 +1670,9 @@ static void serial8250_disable_ms(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&port->lock);
+
/* no MSR capabilities */
if (up->bugs & UART_BUG_NOMSR)
return;
@@ -1718,6 +1687,9 @@ static void serial8250_enable_ms(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&port->lock);
+
/* no MSR capabilities */
if (up->bugs & UART_BUG_NOMSR)
return;
@@ -2174,6 +2146,14 @@ static void serial8250_put_poll_char(struct uart_port *port,
unsigned int ier;
struct uart_8250_port *up = up_to_u8250p(port);
+ /*
+ * Normally the port is locked to synchronize UART_IER access
+ * against the console. However, this function is only used by
+ * KDB/KGDB, where it may not be possible to acquire the port
+ * lock because all other CPUs are quiesced. The quiescence
+ * should allow safe lockless usage here.
+ */
+
serial8250_rpm_get(up);
/*
* First save the IER then disable the interrupts
@@ -2219,7 +2199,12 @@ int serial8250_do_startup(struct uart_port *port)
serial8250_rpm_get(up);
if (port->type == PORT_16C950) {
- /* Wake up and initialize UART */
+ /*
+ * Wake up and initialize UART
+ *
+ * Synchronize UART_IER access against the console.
+ */
+ spin_lock_irqsave(&port->lock, flags);
up->acr = 0;
serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
serial_port_out(port, UART_EFR, UART_EFR_ECB);
@@ -2229,12 +2214,19 @@ int serial8250_do_startup(struct uart_port *port)
serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
serial_port_out(port, UART_EFR, UART_EFR_ECB);
serial_port_out(port, UART_LCR, 0);
+ spin_unlock_irqrestore(&port->lock, flags);
}
if (port->type == PORT_DA830) {
- /* Reset the port */
+ /*
+ * Reset the port
+ *
+ * Synchronize UART_IER access against the console.
+ */
+ spin_lock_irqsave(&port->lock, flags);
serial_port_out(port, UART_IER, 0);
serial_port_out(port, UART_DA830_PWREMU_MGMT, 0);
+ spin_unlock_irqrestore(&port->lock, flags);
mdelay(10);
/* Enable Tx, Rx and free run mode */
@@ -2345,6 +2337,8 @@ int serial8250_do_startup(struct uart_port *port)
* this interrupt whenever the transmitter is idle and
* the interrupt is enabled. Delays are necessary to
* allow register changes to become visible.
+ *
+ * Synchronize UART_IER access against the console.
*/
spin_lock_irqsave(&port->lock, flags);
@@ -2495,6 +2489,8 @@ void serial8250_do_shutdown(struct uart_port *port)
serial8250_rpm_get(up);
/*
* Disable interrupts from this port
+ *
+ * Synchronize UART_IER access against the console.
*/
spin_lock_irqsave(&port->lock, flags);
up->ier = 0;
@@ -2636,11 +2632,8 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
if (c_cflag & CSTOPB)
cval |= UART_LCR_STOP;
- if (c_cflag & PARENB) {
+ if (c_cflag & PARENB)
cval |= UART_LCR_PARITY;
- if (up->bugs & UART_BUG_PARITY)
- up->fifo_bug = true;
- }
if (!(c_cflag & PARODD))
cval |= UART_LCR_EPAR;
if (c_cflag & CMSPAR)
@@ -2794,6 +2787,8 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
/*
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
+ *
+ * Synchronize UART_IER access against the console.
*/
serial8250_rpm_get(up);
spin_lock_irqsave(&port->lock, flags);
@@ -2801,8 +2796,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
up->lcr = cval; /* Save computed LCR */
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
- /* NOTE: If fifo_bug is not set, a user can set RX_trigger. */
- if ((baud < 2400 && !up->dma) || up->fifo_bug) {
+ if (baud < 2400 && !up->dma) {
up->fcr &= ~UART_FCR_TRIGGER_MASK;
up->fcr |= UART_FCR_TRIGGER_1;
}
@@ -2969,11 +2963,6 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt)
{
if (pt->port.mapsize)
return pt->port.mapsize;
- if (pt->port.iotype == UPIO_AU) {
- if (pt->port.type == PORT_RT2880)
- return 0x100;
- return 0x1000;
- }
if (is_omap1_8250(pt))
return 0x16 << pt->port.regshift;
@@ -3138,8 +3127,7 @@ static int do_set_rxtrig(struct tty_port *port, unsigned char bytes)
struct uart_8250_port *up = up_to_u8250p(uport);
int rxtrig;
- if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 ||
- up->fifo_bug)
+ if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1)
return -EINVAL;
rxtrig = bytes_to_fcr_rxtrig(up, bytes);
@@ -3223,10 +3211,6 @@ static void serial8250_config_port(struct uart_port *port, int flags)
if (flags & UART_CONFIG_TYPE)
autoconfig(up);
- /* if access method is AU, it is a 16550 with a quirk */
- if (port->type == PORT_16550A && port->iotype == UPIO_AU)
- up->bugs |= UART_BUG_NOMSR;
-
/* HW bugs may trigger IRQ while IIR == NO_INT */
if (port->type == PORT_TEGRA)
up->bugs |= UART_BUG_NOMSR;
@@ -3293,6 +3277,7 @@ void serial8250_init_port(struct uart_8250_port *up)
struct uart_port *port = &up->port;
spin_lock_init(&port->lock);
+ port->ctrl_id = 0;
port->ops = &serial8250_pops;
port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
index 795e55142d4c..28b341f602c6 100644
--- a/drivers/tty/serial/8250/8250_pxa.c
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -60,7 +60,7 @@ static const struct of_device_id serial_pxa_dt_ids[] = {
MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
/* Uart divisor latch write */
-static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
+static void serial_pxa_dl_write(struct uart_8250_port *up, u32 value)
{
unsigned int dll;
diff --git a/drivers/tty/serial/8250/8250_rt288x.c b/drivers/tty/serial/8250/8250_rt288x.c
new file mode 100644
index 000000000000..6415ca8d3adf
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_rt288x.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RT288x/Au1xxx driver
+ */
+
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+
+#include "8250.h"
+
+#define RT288X_DL 0x28
+
+/* Au1x00/RT288x UART hardware has a weird register layout */
+static const u8 au_io_in_map[7] = {
+ [UART_RX] = 0,
+ [UART_IER] = 2,
+ [UART_IIR] = 3,
+ [UART_LCR] = 5,
+ [UART_MCR] = 6,
+ [UART_LSR] = 7,
+ [UART_MSR] = 8,
+};
+
+static const u8 au_io_out_map[5] = {
+ [UART_TX] = 1,
+ [UART_IER] = 2,
+ [UART_FCR] = 4,
+ [UART_LCR] = 5,
+ [UART_MCR] = 6,
+};
+
+static unsigned int au_serial_in(struct uart_port *p, int offset)
+{
+ if (offset >= ARRAY_SIZE(au_io_in_map))
+ return UINT_MAX;
+ offset = au_io_in_map[offset];
+
+ return __raw_readl(p->membase + (offset << p->regshift));
+}
+
+static void au_serial_out(struct uart_port *p, int offset, int value)
+{
+ if (offset >= ARRAY_SIZE(au_io_out_map))
+ return;
+ offset = au_io_out_map[offset];
+
+ __raw_writel(value, p->membase + (offset << p->regshift));
+}
+
+/* Au1x00 haven't got a standard divisor latch */
+static u32 au_serial_dl_read(struct uart_8250_port *up)
+{
+ return __raw_readl(up->port.membase + RT288X_DL);
+}
+
+static void au_serial_dl_write(struct uart_8250_port *up, u32 value)
+{
+ __raw_writel(value, up->port.membase + RT288X_DL);
+}
+
+int au_platform_setup(struct plat_serial8250_port *p)
+{
+ p->iotype = UPIO_AU;
+
+ p->serial_in = au_serial_in;
+ p->serial_out = au_serial_out;
+ p->dl_read = au_serial_dl_read;
+ p->dl_write = au_serial_dl_write;
+
+ p->mapsize = 0x1000;
+
+ p->bugs |= UART_BUG_NOMSR;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(au_platform_setup);
+
+int rt288x_setup(struct uart_port *p)
+{
+ struct uart_8250_port *up = up_to_u8250p(p);
+
+ p->iotype = UPIO_AU;
+
+ p->serial_in = au_serial_in;
+ p->serial_out = au_serial_out;
+ up->dl_read = au_serial_dl_read;
+ up->dl_write = au_serial_dl_write;
+
+ p->mapsize = 0x100;
+
+ up->bugs |= UART_BUG_NOMSR;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt288x_setup);
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static void au_putc(struct uart_port *port, unsigned char c)
+{
+ unsigned int status;
+
+ au_serial_out(port, UART_TX, c);
+
+ for (;;) {
+ status = au_serial_in(port, UART_LSR);
+ if (uart_lsr_tx_empty(status))
+ break;
+ cpu_relax();
+ }
+}
+
+static void au_early_serial8250_write(struct console *console,
+ const char *s, unsigned int count)
+{
+ struct earlycon_device *device = console->data;
+ struct uart_port *port = &device->port;
+
+ uart_console_write(port, s, count, au_putc);
+}
+
+static int __init early_au_setup(struct earlycon_device *dev, const char *opt)
+{
+ rt288x_setup(&dev->port);
+ dev->con->write = au_early_serial8250_write;
+
+ return 0;
+}
+OF_EARLYCON_DECLARE(palmchip, "ralink,rt2880-uart", early_au_setup);
+#endif
+
+MODULE_DESCRIPTION("RT288x/Au1xxx UART driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c
index a2978abab0db..a405155264b1 100644
--- a/drivers/tty/serial/8250/8250_uniphier.c
+++ b/drivers/tty/serial/8250/8250_uniphier.c
@@ -145,12 +145,12 @@ static void uniphier_serial_out(struct uart_port *p, int offset, int value)
* The divisor latch register exists at different address.
* Override dl_read/write callbacks.
*/
-static int uniphier_serial_dl_read(struct uart_8250_port *up)
+static u32 uniphier_serial_dl_read(struct uart_8250_port *up)
{
return readl(up->port.membase + UNIPHIER_UART_DLR);
}
-static void uniphier_serial_dl_write(struct uart_8250_port *up, int value)
+static void uniphier_serial_dl_write(struct uart_8250_port *up, u32 value)
{
writel(value, up->port.membase + UNIPHIER_UART_DLR);
}
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 5313aa31930f..ee17cf5c44c6 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -71,14 +71,16 @@ config SERIAL_8250_16550A_VARIANTS
console, you can say N here.
config SERIAL_8250_FINTEK
- bool "Support for Fintek F81216A LPC to 4 UART RS485 API"
+ bool "Support for Fintek variants"
depends on SERIAL_8250
help
- Selecting this option will add support for the RS485 capabilities
- of the Fintek F81216A LPC to 4 UART.
+ Selecting this option will add support for the RS232 and RS485
+ capabilities of the Fintek F81216A LPC to 4 UART as well similar
+ variants.
If this option is not selected the device will be configured as a
- standard 16550A serial port.
+ standard 16550A serial port, however the device may not function
+ correctly without this option enabled.
If unsure, say N.
@@ -377,9 +379,9 @@ config SERIAL_8250_BCM2835AUX
If unsure, say N.
config SERIAL_8250_FSL
- bool "Freescale 16550 UART support" if COMPILE_TEST && !(PPC || ARM || ARM64)
- depends on SERIAL_8250_CONSOLE
- default PPC || ARM || ARM64
+ tristate "Freescale 16550 UART support" if COMPILE_TEST && !(PPC || ARM || ARM64)
+ depends on SERIAL_8250
+ default SERIAL_8250 if PPC || ARM || ARM64
help
Selecting this option enables a workaround for a break-detection
erratum for Freescale 16550 UARTs in the 8250 driver. It also
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 4fc2fc1f41b6..628b75be312e 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o
obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o
obj-$(CONFIG_SERIAL_8250_IOC3) += 8250_ioc3.o
obj-$(CONFIG_SERIAL_8250_OMAP) += 8250_omap.o
+obj-$(CONFIG_SERIAL_8250_RT288X) += 8250_rt288x.o
obj-$(CONFIG_SERIAL_8250_LPC18XX) += 8250_lpc18xx.o
obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o
obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 71a7a3e724ca..bdc568a4ab66 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1555,6 +1555,29 @@ config SERIAL_SUNPLUS_CONSOLE
you can alter that using a kernel command line option such as
"console=ttySUPx".
+config SERIAL_NUVOTON_MA35D1
+ tristate "Nuvoton MA35D1 family UART support"
+ depends on ARCH_MA35 || COMPILE_TEST
+ select SERIAL_CORE
+ help
+ This driver supports Nuvoton MA35D1 family UART ports. If you would
+ like to use them, you must answer Y or M to this option. Note that
+ for use as console, it must be included in kernel and not as a
+ module. If you enable this option, Ma35D1 serial ports in the system
+ will be registered as ttyNVTx.
+
+config SERIAL_NUVOTON_MA35D1_CONSOLE
+ bool "Console on a Nuvotn MA35D1 family UART port"
+ depends on SERIAL_NUVOTON_MA35D1=y
+ select SERIAL_CORE_CONSOLE
+ help
+ Select this options if you'd like to use the UART port0 of the
+ Nuvoton MA35D1 family as a console.
+ Even if you say Y here, the currently visible virtual console
+ (/dev/tty0) will still be used as the system console by default,
+ but you can alter that using a kernel command line option such as
+ "console=ttyNVTx".
+
endmenu
config SERIAL_MCTRL_GPIO
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index cd9afd9e3018..d4123469583d 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -3,7 +3,8 @@
# Makefile for the kernel serial device drivers.
#
-obj-$(CONFIG_SERIAL_CORE) += serial_core.o
+obj-$(CONFIG_SERIAL_CORE) += serial_base.o
+serial_base-y := serial_core.o serial_base_bus.o serial_ctrl.o serial_port.o
obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
obj-$(CONFIG_SERIAL_EARLYCON_SEMIHOST) += earlycon-semihost.o
@@ -21,7 +22,7 @@ obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
obj-$(CONFIG_SERIAL_21285) += 21285.o
# Now bring in any enabled 8250/16450/16550 type drivers.
-obj-$(CONFIG_SERIAL_8250) += 8250/
+obj-y += 8250/
obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
@@ -93,3 +94,4 @@ obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o
obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o
obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
+obj-$(CONFIG_SERIAL_NUVOTON_MA35D1) += ma35d1_serial.o
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index d8c2f3455eeb..c5c3f4674459 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2166,6 +2166,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
* ----------^----------^----------^----------^-----
*/
pl011_write_lcr_h(uap, lcr_h);
+
+ /*
+ * Receive was disabled by pl011_disable_uart during shutdown.
+ * Need to reenable receive if you need to use a tty_driver
+ * returns from tty_find_polling_driver() after a port shutdown.
+ */
+ old_cr |= UART011_CR_RXE;
pl011_write(old_cr, uap, REG_CR);
spin_unlock_irqrestore(&port->lock, flags);
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 9cd7479b03c0..3467a875641a 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -868,11 +868,11 @@ static void atmel_complete_tx_dma(void *arg)
dmaengine_terminate_all(chan);
uart_xmit_advance(port, atmel_port->tx_len);
- spin_lock_irq(&atmel_port->lock_tx);
+ spin_lock(&atmel_port->lock_tx);
async_tx_ack(atmel_port->desc_tx);
atmel_port->cookie_tx = -EINVAL;
atmel_port->desc_tx = NULL;
- spin_unlock_irq(&atmel_port->lock_tx);
+ spin_unlock(&atmel_port->lock_tx);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
@@ -3006,14 +3006,13 @@ static int atmel_serial_remove(struct platform_device *pdev)
{
struct uart_port *port = platform_get_drvdata(pdev);
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- int ret = 0;
tasklet_kill(&atmel_port->tasklet_rx);
tasklet_kill(&atmel_port->tasklet_tx);
device_init_wakeup(&pdev->dev, 0);
- ret = uart_remove_one_port(&atmel_uart, port);
+ uart_remove_one_port(&atmel_uart, port);
kfree(atmel_port->rx_ring.buf);
@@ -3023,7 +3022,7 @@ static int atmel_serial_remove(struct platform_device *pdev)
pdev->dev.of_node = NULL;
- return ret;
+ return 0;
}
static SIMPLE_DEV_PM_OPS(atmel_serial_pm_ops, atmel_serial_suspend,
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index e190dce58f46..e49bc4019b50 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -514,7 +514,9 @@ static int uart_clps711x_remove(struct platform_device *pdev)
{
struct clps711x_port *s = platform_get_drvdata(pdev);
- return uart_remove_one_port(&clps711x_uart, &s->port);
+ uart_remove_one_port(&clps711x_uart, &s->port);
+
+ return 0;
}
static const struct of_device_id __maybe_unused clps711x_uart_dt_ids[] = {
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index 349e7da643f0..66afa9bea6bf 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -1431,7 +1431,10 @@ static int cpm_uart_probe(struct platform_device *ofdev)
static int cpm_uart_remove(struct platform_device *ofdev)
{
struct uart_cpm_port *pinfo = platform_get_drvdata(ofdev);
- return uart_remove_one_port(&cpm_reg, &pinfo->port);
+
+ uart_remove_one_port(&cpm_reg, &pinfo->port);
+
+ return 0;
}
static const struct of_device_id cpm_uart_match[] = {
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 7fd30fcc10c6..4d80fae20177 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -238,6 +238,7 @@
/* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */
#define DMA_RX_TIMEOUT (10)
+#define DMA_RX_IDLE_CHARS 8
#define UART_AUTOSUSPEND_TIMEOUT 3000
#define DRIVER_NAME "fsl-lpuart"
@@ -282,6 +283,7 @@ struct lpuart_port {
struct scatterlist rx_sgl, tx_sgl[2];
struct circ_buf rx_ring;
int rx_dma_rng_buf_len;
+ int last_residue;
unsigned int dma_tx_nents;
wait_queue_head_t dma_wait;
bool is_cs7; /* Set to true when character size is 7 */
@@ -331,7 +333,7 @@ static struct lpuart_soc_data imx8qxp_data = {
.devtype = IMX8QXP_LPUART,
.iotype = UPIO_MEM32,
.reg_off = IMX_REG_OFF,
- .rx_watermark = 31,
+ .rx_watermark = 7, /* A lower watermark is ideal for low baud rates. */
};
static struct lpuart_soc_data imxrt1050_data = {
.devtype = IMXRT1050_LPUART,
@@ -1255,6 +1257,8 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
sport->port.icount.rx += copied;
}
+ sport->last_residue = state.residue;
+
exit:
dma_sync_sg_for_device(chan->device->dev, &sport->rx_sgl, 1,
DMA_FROM_DEVICE);
@@ -1272,11 +1276,43 @@ static void lpuart_dma_rx_complete(void *arg)
lpuart_copy_rx_to_tty(sport);
}
+/*
+ * Timer function to simulate the hardware EOP (End Of Package) event.
+ * The timer callback is to check for new RX data and copy to TTY buffer.
+ * If no new data are received since last interval, the EOP condition is
+ * met, complete the DMA transfer by copying the data. Otherwise, just
+ * restart timer.
+ */
static void lpuart_timer_func(struct timer_list *t)
{
struct lpuart_port *sport = from_timer(sport, t, lpuart_timer);
+ enum dma_status dmastat;
+ struct dma_chan *chan = sport->dma_rx_chan;
+ struct circ_buf *ring = &sport->rx_ring;
+ struct dma_tx_state state;
+ unsigned long flags;
+ int count;
- lpuart_copy_rx_to_tty(sport);
+ dmastat = dmaengine_tx_status(chan, sport->dma_rx_cookie, &state);
+ if (dmastat == DMA_ERROR) {
+ dev_err(sport->port.dev, "Rx DMA transfer failed!\n");
+ return;
+ }
+
+ ring->head = sport->rx_sgl.length - state.residue;
+ count = CIRC_CNT(ring->head, ring->tail, sport->rx_sgl.length);
+
+ /* Check if new data received before copying */
+ if ((count != 0) && (sport->last_residue == state.residue))
+ lpuart_copy_rx_to_tty(sport);
+ else
+ mod_timer(&sport->lpuart_timer,
+ jiffies + sport->dma_rx_timeout);
+
+ if (spin_trylock_irqsave(&sport->port.lock, flags)) {
+ sport->last_residue = state.residue;
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+ }
}
static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
@@ -1297,9 +1333,20 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
*/
sport->rx_dma_rng_buf_len = (DMA_RX_TIMEOUT * baud / bits / 1000) * 2;
sport->rx_dma_rng_buf_len = (1 << fls(sport->rx_dma_rng_buf_len));
+ sport->rx_dma_rng_buf_len = max_t(int,
+ sport->rxfifo_size * 2,
+ sport->rx_dma_rng_buf_len);
+ /*
+ * Keep this condition check in case rxfifo_size is unavailable
+ * for some SoCs.
+ */
if (sport->rx_dma_rng_buf_len < 16)
sport->rx_dma_rng_buf_len = 16;
+ sport->last_residue = 0;
+ sport->dma_rx_timeout = max(nsecs_to_jiffies(
+ sport->port.frame_time * DMA_RX_IDLE_CHARS), 1UL);
+
ring->buf = kzalloc(sport->rx_dma_rng_buf_len, GFP_ATOMIC);
if (!ring->buf)
return -ENOMEM;
@@ -1689,12 +1736,13 @@ static void lpuart_rx_dma_startup(struct lpuart_port *sport)
if (!sport->dma_rx_chan)
goto err;
+ /* set default Rx DMA timeout */
+ sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT);
+
ret = lpuart_start_rx_dma(sport);
if (ret)
goto err;
- /* set Rx DMA timeout */
- sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT);
if (!sport->dma_rx_timeout)
sport->dma_rx_timeout = 1;
@@ -2676,6 +2724,7 @@ OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup);
+OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8ulp-lpuart", lpuart32_imx_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,imxrt1050-lpuart", lpuart32_imx_early_console_setup);
EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index c5e17569c3ad..7341d060f85c 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -369,6 +369,16 @@ static void imx_uart_soft_reset(struct imx_port *sport)
sport->idle_counter = 0;
}
+static void imx_uart_disable_loopback_rs485(struct imx_port *sport)
+{
+ unsigned int uts;
+
+ /* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */
+ uts = imx_uart_readl(sport, imx_uart_uts_reg(sport));
+ uts &= ~UTS_LOOP;
+ imx_uart_writel(sport, uts, imx_uart_uts_reg(sport));
+}
+
/* called with port.lock taken and irqs off */
static void imx_uart_start_rx(struct uart_port *port)
{
@@ -390,6 +400,7 @@ static void imx_uart_start_rx(struct uart_port *port)
/* Write UCR2 first as it includes RXEN */
imx_uart_writel(sport, ucr2, UCR2);
imx_uart_writel(sport, ucr1, UCR1);
+ imx_uart_disable_loopback_rs485(sport);
}
/* called with port.lock taken and irqs off */
@@ -1422,7 +1433,7 @@ static int imx_uart_startup(struct uart_port *port)
int retval;
unsigned long flags;
int dma_is_inited = 0;
- u32 ucr1, ucr2, ucr3, ucr4, uts;
+ u32 ucr1, ucr2, ucr3, ucr4;
retval = clk_prepare_enable(sport->clk_per);
if (retval)
@@ -1521,10 +1532,7 @@ static int imx_uart_startup(struct uart_port *port)
imx_uart_writel(sport, ucr2, UCR2);
}
- /* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */
- uts = imx_uart_readl(sport, imx_uart_uts_reg(sport));
- uts &= ~UTS_LOOP;
- imx_uart_writel(sport, uts, imx_uart_uts_reg(sport));
+ imx_uart_disable_loopback_rs485(sport);
spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -2467,7 +2475,9 @@ static int imx_uart_remove(struct platform_device *pdev)
{
struct imx_port *sport = platform_get_drvdata(pdev);
- return uart_remove_one_port(&imx_uart_uart_driver, &sport->port);
+ uart_remove_one_port(&imx_uart_uart_driver, &sport->port);
+
+ return 0;
}
static void imx_uart_restore_context(struct imx_port *sport)
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index f1387f1024db..bcaa479608d8 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -890,7 +890,9 @@ static int lqasc_remove(struct platform_device *pdev)
{
struct uart_port *port = platform_get_drvdata(pdev);
- return uart_remove_one_port(&lqasc_reg, port);
+ uart_remove_one_port(&lqasc_reg, port);
+
+ return 0;
}
static const struct ltq_soc_data soc_data_lantiq = {
diff --git a/drivers/tty/serial/ma35d1_serial.c b/drivers/tty/serial/ma35d1_serial.c
new file mode 100644
index 000000000000..2604b4d9fb78
--- /dev/null
+++ b/drivers/tty/serial/ma35d1_serial.c
@@ -0,0 +1,821 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * MA35D1 serial driver
+ * Copyright (C) 2023 Nuvoton Technology Corp.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/iopoll.h>
+#include <linux/serial_core.h>
+#include <linux/slab.h>
+#include <linux/tty_flip.h>
+#include <linux/units.h>
+
+#define MA35_UART_NR 17
+
+#define MA35_RBR_REG 0x00
+#define MA35_THR_REG 0x00
+#define MA35_IER_REG 0x04
+#define MA35_FCR_REG 0x08
+#define MA35_LCR_REG 0x0C
+#define MA35_MCR_REG 0x10
+#define MA35_MSR_REG 0x14
+#define MA35_FSR_REG 0x18
+#define MA35_ISR_REG 0x1C
+#define MA35_TOR_REG 0x20
+#define MA35_BAUD_REG 0x24
+#define MA35_ALTCTL_REG 0x2C
+#define MA35_FUN_SEL_REG 0x30
+#define MA35_WKCTL_REG 0x40
+#define MA35_WKSTS_REG 0x44
+
+/* MA35_IER_REG - Interrupt Enable Register */
+#define MA35_IER_RDA_IEN BIT(0) /* RBR Available Interrupt Enable */
+#define MA35_IER_THRE_IEN BIT(1) /* THR Empty Interrupt Enable */
+#define MA35_IER_RLS_IEN BIT(2) /* RX Line Status Interrupt Enable */
+#define MA35_IER_RTO_IEN BIT(4) /* RX Time-out Interrupt Enable */
+#define MA35_IER_BUFERR_IEN BIT(5) /* Buffer Error Interrupt Enable */
+#define MA35_IER_TIME_OUT_EN BIT(11) /* RX Buffer Time-out Counter Enable */
+#define MA35_IER_AUTO_RTS BIT(12) /* nRTS Auto-flow Control Enable */
+#define MA35_IER_AUTO_CTS BIT(13) /* nCTS Auto-flow Control Enable */
+
+/* MA35_FCR_REG - FIFO Control Register */
+#define MA35_FCR_RFR BIT(1) /* RX Field Software Reset */
+#define MA35_FCR_TFR BIT(2) /* TX Field Software Reset */
+#define MA35_FCR_RFITL_MASK GENMASK(7, 4) /* RX FIFO Interrupt Trigger Level */
+#define MA35_FCR_RFITL_1BYTE FIELD_PREP(MA35_FCR_RFITL_MASK, 0)
+#define MA35_FCR_RFITL_4BYTES FIELD_PREP(MA35_FCR_RFITL_MASK, 1)
+#define MA35_FCR_RFITL_8BYTES FIELD_PREP(MA35_FCR_RFITL_MASK, 2)
+#define MA35_FCR_RFITL_14BYTES FIELD_PREP(MA35_FCR_RFITL_MASK, 3)
+#define MA35_FCR_RFITL_30BYTES FIELD_PREP(MA35_FCR_RFITL_MASK, 4)
+#define MA35_FCR_RTSTL_MASK GENMASK(19, 16) /* nRTS Trigger Level */
+#define MA35_FCR_RTSTL_1BYTE FIELD_PREP(MA35_FCR_RTSTL_MASK, 0)
+#define MA35_FCR_RTSTL_4BYTES FIELD_PREP(MA35_FCR_RTSTL_MASK, 1)
+#define MA35_FCR_RTSTL_8BYTES FIELD_PREP(MA35_FCR_RTSTL_MASK, 2)
+#define MA35_FCR_RTSTL_14BYTES FIELD_PREP(MA35_FCR_RTSTL_MASK, 3)
+#define MA35_FCR_RTSTLL_30BYTES FIELD_PREP(MA35_FCR_RTSTL_MASK, 4)
+
+/* MA35_LCR_REG - Line Control Register */
+#define MA35_LCR_NSB BIT(2) /* Number of “STOP Bit” */
+#define MA35_LCR_PBE BIT(3) /* Parity Bit Enable */
+#define MA35_LCR_EPE BIT(4) /* Even Parity Enable */
+#define MA35_LCR_SPE BIT(5) /* Stick Parity Enable */
+#define MA35_LCR_BREAK BIT(6) /* Break Control */
+#define MA35_LCR_WLS_MASK GENMASK(1, 0) /* Word Length Selection */
+#define MA35_LCR_WLS_5BITS FIELD_PREP(MA35_LCR_WLS_MASK, 0)
+#define MA35_LCR_WLS_6BITS FIELD_PREP(MA35_LCR_WLS_MASK, 1)
+#define MA35_LCR_WLS_7BITS FIELD_PREP(MA35_LCR_WLS_MASK, 2)
+#define MA35_LCR_WLS_8BITS FIELD_PREP(MA35_LCR_WLS_MASK, 3)
+
+/* MA35_MCR_REG - Modem Control Register */
+#define MA35_MCR_RTS_CTRL BIT(1) /* nRTS Signal Control */
+#define MA35_MCR_RTSACTLV BIT(9) /* nRTS Pin Active Level */
+#define MA35_MCR_RTSSTS BIT(13) /* nRTS Pin Status (Read Only) */
+
+/* MA35_MSR_REG - Modem Status Register */
+#define MA35_MSR_CTSDETF BIT(0) /* Detect nCTS State Change Flag */
+#define MA35_MSR_CTSSTS BIT(4) /* nCTS Pin Status (Read Only) */
+#define MA35_MSR_CTSACTLV BIT(8) /* nCTS Pin Active Level */
+
+/* MA35_FSR_REG - FIFO Status Register */
+#define MA35_FSR_RX_OVER_IF BIT(0) /* RX Overflow Error Interrupt Flag */
+#define MA35_FSR_PEF BIT(4) /* Parity Error Flag*/
+#define MA35_FSR_FEF BIT(5) /* Framing Error Flag */
+#define MA35_FSR_BIF BIT(6) /* Break Interrupt Flag */
+#define MA35_FSR_RX_EMPTY BIT(14) /* Receiver FIFO Empty (Read Only) */
+#define MA35_FSR_RX_FULL BIT(15) /* Receiver FIFO Full (Read Only) */
+#define MA35_FSR_TX_EMPTY BIT(22) /* Transmitter FIFO Empty (Read Only) */
+#define MA35_FSR_TX_FULL BIT(23) /* Transmitter FIFO Full (Read Only) */
+#define MA35_FSR_TX_OVER_IF BIT(24) /* TX Overflow Error Interrupt Flag */
+#define MA35_FSR_TE_FLAG BIT(28) /* Transmitter Empty Flag (Read Only) */
+#define MA35_FSR_RXPTR_MSK GENMASK(13, 8) /* TX FIFO Pointer mask */
+#define MA35_FSR_TXPTR_MSK GENMASK(21, 16) /* RX FIFO Pointer mask */
+
+/* MA35_ISR_REG - Interrupt Status Register */
+#define MA35_ISR_RDA_IF BIT(0) /* RBR Available Interrupt Flag */
+#define MA35_ISR_THRE_IF BIT(1) /* THR Empty Interrupt Flag */
+#define MA35_ISR_RLSIF BIT(2) /* Receive Line Interrupt Flag */
+#define MA35_ISR_MODEMIF BIT(3) /* MODEM Interrupt Flag */
+#define MA35_ISR_RXTO_IF BIT(4) /* RX Time-out Interrupt Flag */
+#define MA35_ISR_BUFEIF BIT(5) /* Buffer Error Interrupt Flag */
+#define MA35_ISR_WK_IF BIT(6) /* UART Wake-up Interrupt Flag */
+#define MA35_ISR_RDAINT BIT(8) /* RBR Available Interrupt Indicator */
+#define MA35_ISR_THRE_INT BIT(9) /* THR Empty Interrupt Indicator */
+#define MA35_ISR_ALL 0xFFFFFFFF
+
+/* MA35_BAUD_REG - Baud Rate Divider Register */
+#define MA35_BAUD_MODE_MASK GENMASK(29, 28)
+#define MA35_BAUD_MODE0 FIELD_PREP(MA35_BAUD_MODE_MASK, 0)
+#define MA35_BAUD_MODE1 FIELD_PREP(MA35_BAUD_MODE_MASK, 2)
+#define MA35_BAUD_MODE2 FIELD_PREP(MA35_BAUD_MODE_MASK, 3)
+#define MA35_BAUD_MASK GENMASK(15, 0)
+
+/* MA35_ALTCTL_REG - Alternate Control/Status Register */
+#define MA35_ALTCTL_RS485AUD BIT(10) /* RS-485 Auto Direction Function */
+
+/* MA35_FUN_SEL_REG - Function Select Register */
+#define MA35_FUN_SEL_MASK GENMASK(2, 0)
+#define MA35_FUN_SEL_UART FIELD_PREP(MA35_FUN_SEL_MASK, 0)
+#define MA35_FUN_SEL_RS485 FIELD_PREP(MA35_FUN_SEL_MASK, 3)
+
+/* The constrain for MA35D1 UART baud rate divider */
+#define MA35_BAUD_DIV_MAX 0xFFFF
+#define MA35_BAUD_DIV_MIN 11
+
+/* UART FIFO depth */
+#define MA35_UART_FIFO_DEPTH 32
+/* UART console clock */
+#define MA35_UART_CONSOLE_CLK (24 * HZ_PER_MHZ)
+/* UART register ioremap size */
+#define MA35_UART_REG_SIZE 0x100
+/* Rx Timeout */
+#define MA35_UART_RX_TOUT 0x40
+
+#define MA35_IER_CONFIG (MA35_IER_RTO_IEN | MA35_IER_RDA_IEN | \
+ MA35_IER_TIME_OUT_EN | MA35_IER_BUFERR_IEN)
+
+#define MA35_ISR_IF_CHECK (MA35_ISR_RDA_IF | MA35_ISR_RXTO_IF | \
+ MA35_ISR_THRE_INT | MA35_ISR_BUFEIF)
+
+#define MA35_FSR_TX_BOTH_EMPTY (MA35_FSR_TE_FLAG | MA35_FSR_TX_EMPTY)
+
+static struct uart_driver ma35d1serial_reg;
+
+struct uart_ma35d1_port {
+ struct uart_port port;
+ struct clk *clk;
+ u16 capabilities; /* port capabilities */
+ u8 ier;
+ u8 lcr;
+ u8 mcr;
+ u32 baud_rate;
+ u32 console_baud_rate;
+ u32 console_line;
+ u32 console_int;
+};
+
+static struct uart_ma35d1_port ma35d1serial_ports[MA35_UART_NR];
+
+static struct uart_ma35d1_port *to_ma35d1_uart_port(struct uart_port *uart)
+{
+ return container_of(uart, struct uart_ma35d1_port, port);
+}
+
+static u32 serial_in(struct uart_ma35d1_port *p, u32 offset)
+{
+ return readl_relaxed(p->port.membase + offset);
+}
+
+static void serial_out(struct uart_ma35d1_port *p, u32 offset, u32 value)
+{
+ writel_relaxed(value, p->port.membase + offset);
+}
+
+static void __stop_tx(struct uart_ma35d1_port *p)
+{
+ u32 ier;
+
+ ier = serial_in(p, MA35_IER_REG);
+ if (ier & MA35_IER_THRE_IEN)
+ serial_out(p, MA35_IER_REG, ier & ~MA35_IER_THRE_IEN);
+}
+
+static void ma35d1serial_stop_tx(struct uart_port *port)
+{
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+
+ __stop_tx(up);
+}
+
+static void transmit_chars(struct uart_ma35d1_port *up)
+{
+ u32 count;
+ u8 ch;
+
+ if (uart_tx_stopped(&up->port)) {
+ ma35d1serial_stop_tx(&up->port);
+ return;
+ }
+ count = MA35_UART_FIFO_DEPTH - FIELD_GET(MA35_FSR_TXPTR_MSK,
+ serial_in(up, MA35_FSR_REG));
+ uart_port_tx_limited(&up->port, ch, count,
+ !(serial_in(up, MA35_FSR_REG) & MA35_FSR_TX_FULL),
+ serial_out(up, MA35_THR_REG, ch),
+ ({}));
+}
+
+static void ma35d1serial_start_tx(struct uart_port *port)
+{
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+ u32 ier;
+
+ ier = serial_in(up, MA35_IER_REG);
+ serial_out(up, MA35_IER_REG, ier & ~MA35_IER_THRE_IEN);
+ transmit_chars(up);
+ serial_out(up, MA35_IER_REG, ier | MA35_IER_THRE_IEN);
+}
+
+static void ma35d1serial_stop_rx(struct uart_port *port)
+{
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+ u32 ier;
+
+ ier = serial_in(up, MA35_IER_REG);
+ ier &= ~MA35_IER_RDA_IEN;
+ serial_out(up, MA35_IER_REG, ier);
+}
+
+static void receive_chars(struct uart_ma35d1_port *up)
+{
+ int max_count = 256;
+ u8 ch, flag;
+ u32 fsr;
+
+ fsr = serial_in(up, MA35_FSR_REG);
+ do {
+ flag = TTY_NORMAL;
+ up->port.icount.rx++;
+
+ if (unlikely(fsr & (MA35_FSR_BIF | MA35_FSR_FEF |
+ MA35_FSR_PEF | MA35_FSR_RX_OVER_IF))) {
+ if (fsr & MA35_FSR_BIF) {
+ up->port.icount.brk++;
+ if (uart_handle_break(&up->port))
+ continue;
+ }
+ if (fsr & MA35_FSR_FEF)
+ up->port.icount.frame++;
+ if (fsr & MA35_FSR_PEF)
+ up->port.icount.parity++;
+ if (fsr & MA35_FSR_RX_OVER_IF)
+ up->port.icount.overrun++;
+
+ serial_out(up, MA35_FSR_REG,
+ fsr & (MA35_FSR_BIF | MA35_FSR_FEF |
+ MA35_FSR_PEF | MA35_FSR_RX_OVER_IF));
+ if (fsr & MA35_FSR_BIF)
+ flag = TTY_BREAK;
+ else if (fsr & MA35_FSR_PEF)
+ flag = TTY_PARITY;
+ else if (fsr & MA35_FSR_FEF)
+ flag = TTY_FRAME;
+ }
+
+ ch = serial_in(up, MA35_RBR_REG);
+ if (uart_handle_sysrq_char(&up->port, ch))
+ continue;
+
+ spin_lock(&up->port.lock);
+ uart_insert_char(&up->port, fsr, MA35_FSR_RX_OVER_IF, ch, flag);
+ spin_unlock(&up->port.lock);
+
+ fsr = serial_in(up, MA35_FSR_REG);
+ } while (!(fsr & MA35_FSR_RX_EMPTY) && (max_count-- > 0));
+
+ spin_lock(&up->port.lock);
+ tty_flip_buffer_push(&up->port.state->port);
+ spin_unlock(&up->port.lock);
+}
+
+static irqreturn_t ma35d1serial_interrupt(int irq, void *dev_id)
+{
+ struct uart_port *port = dev_id;
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+ u32 isr, fsr;
+
+ isr = serial_in(up, MA35_ISR_REG);
+ fsr = serial_in(up, MA35_FSR_REG);
+
+ if (!(isr & MA35_ISR_IF_CHECK))
+ return IRQ_NONE;
+
+ if (isr & (MA35_ISR_RDA_IF | MA35_ISR_RXTO_IF))
+ receive_chars(up);
+ if (isr & MA35_ISR_THRE_INT)
+ transmit_chars(up);
+ if (fsr & MA35_FSR_TX_OVER_IF)
+ serial_out(up, MA35_FSR_REG, MA35_FSR_TX_OVER_IF);
+
+ return IRQ_HANDLED;
+}
+
+static u32 ma35d1serial_tx_empty(struct uart_port *port)
+{
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+ u32 fsr;
+
+ fsr = serial_in(up, MA35_FSR_REG);
+ if ((fsr & MA35_FSR_TX_BOTH_EMPTY) == MA35_FSR_TX_BOTH_EMPTY)
+ return TIOCSER_TEMT;
+ else
+ return 0;
+}
+
+static u32 ma35d1serial_get_mctrl(struct uart_port *port)
+{
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+ u32 status;
+ u32 ret = 0;
+
+ status = serial_in(up, MA35_MSR_REG);
+ if (!(status & MA35_MSR_CTSSTS))
+ ret |= TIOCM_CTS;
+ return ret;
+}
+
+static void ma35d1serial_set_mctrl(struct uart_port *port, u32 mctrl)
+{
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+ u32 mcr, msr, ier;
+
+ mcr = serial_in(up, MA35_MCR_REG);
+ mcr &= ~MA35_MCR_RTS_CTRL;
+
+ if (mctrl & TIOCM_RTS)
+ mcr |= MA35_MCR_RTSACTLV;
+ else
+ mcr &= ~MA35_MCR_RTSACTLV;
+
+ if (up->mcr & UART_MCR_AFE) {
+ ier = serial_in(up, MA35_IER_REG);
+ ier |= MA35_IER_AUTO_RTS | MA35_IER_AUTO_CTS;
+ serial_out(up, MA35_IER_REG, ier);
+ up->port.flags |= UPF_HARD_FLOW;
+ } else {
+ ier = serial_in(up, MA35_IER_REG);
+ ier &= ~(MA35_IER_AUTO_RTS | MA35_IER_AUTO_CTS);
+ serial_out(up, MA35_IER_REG, ier);
+ up->port.flags &= ~UPF_HARD_FLOW;
+ }
+
+ msr = serial_in(up, MA35_MSR_REG);
+ msr |= MA35_MSR_CTSACTLV;
+ serial_out(up, MA35_MSR_REG, msr);
+ serial_out(up, MA35_MCR_REG, mcr);
+}
+
+static void ma35d1serial_break_ctl(struct uart_port *port, int break_state)
+{
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+ unsigned long flags;
+ u32 lcr;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ lcr = serial_in(up, MA35_LCR_REG);
+ if (break_state != 0)
+ lcr |= MA35_LCR_BREAK;
+ else
+ lcr &= ~MA35_LCR_BREAK;
+ serial_out(up, MA35_LCR_REG, lcr);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static int ma35d1serial_startup(struct uart_port *port)
+{
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+ u32 fcr;
+ int retval;
+
+ /* Reset FIFO */
+ serial_out(up, MA35_FCR_REG, MA35_FCR_TFR | MA35_FCR_RFR);
+
+ /* Clear pending interrupts */
+ serial_out(up, MA35_ISR_REG, MA35_ISR_ALL);
+
+ retval = request_irq(port->irq, ma35d1serial_interrupt, 0,
+ dev_name(port->dev), port);
+ if (retval) {
+ dev_err(up->port.dev, "request irq failed.\n");
+ return retval;
+ }
+
+ fcr = serial_in(up, MA35_FCR_REG);
+ fcr |= MA35_FCR_RFITL_4BYTES | MA35_FCR_RTSTL_8BYTES;
+ serial_out(up, MA35_FCR_REG, fcr);
+ serial_out(up, MA35_LCR_REG, MA35_LCR_WLS_8BITS);
+ serial_out(up, MA35_TOR_REG, MA35_UART_RX_TOUT);
+ serial_out(up, MA35_IER_REG, MA35_IER_CONFIG);
+ return 0;
+}
+
+static void ma35d1serial_shutdown(struct uart_port *port)
+{
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+
+ serial_out(up, MA35_IER_REG, 0);
+ free_irq(port->irq, port);
+}
+
+static void ma35d1serial_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ const struct ktermios *old)
+{
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+ unsigned long flags;
+ u32 baud, quot;
+ u32 lcr = 0;
+
+ lcr = UART_LCR_WLEN(tty_get_char_size(termios->c_cflag));
+
+ if (termios->c_cflag & CSTOPB)
+ lcr |= MA35_LCR_NSB;
+ if (termios->c_cflag & PARENB)
+ lcr |= MA35_LCR_PBE;
+ if (!(termios->c_cflag & PARODD))
+ lcr |= MA35_LCR_EPE;
+ if (termios->c_cflag & CMSPAR)
+ lcr |= MA35_LCR_SPE;
+
+ baud = uart_get_baud_rate(port, termios, old,
+ port->uartclk / MA35_BAUD_DIV_MAX,
+ port->uartclk / MA35_BAUD_DIV_MIN);
+
+ /* MA35D1 UART baud rate equation: baudrate = UART_CLK / (quot + 2) */
+ quot = (port->uartclk / baud) - 2;
+
+ /*
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ up->port.read_status_mask = MA35_FSR_RX_OVER_IF;
+ if (termios->c_iflag & INPCK)
+ up->port.read_status_mask |= MA35_FSR_FEF | MA35_FSR_PEF;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ up->port.read_status_mask |= MA35_FSR_BIF;
+
+ /* Characteres to ignore */
+ up->port.ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ up->port.ignore_status_mask |= MA35_FSR_FEF | MA35_FSR_PEF;
+ if (termios->c_iflag & IGNBRK) {
+ up->port.ignore_status_mask |= MA35_FSR_BIF;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ up->port.ignore_status_mask |= MA35_FSR_RX_OVER_IF;
+ }
+ if (termios->c_cflag & CRTSCTS)
+ up->mcr |= UART_MCR_AFE;
+ else
+ up->mcr &= ~UART_MCR_AFE;
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ ma35d1serial_set_mctrl(&up->port, up->port.mctrl);
+
+ serial_out(up, MA35_BAUD_REG, MA35_BAUD_MODE2 | FIELD_PREP(MA35_BAUD_MASK, quot));
+
+ serial_out(up, MA35_LCR_REG, lcr);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static const char *ma35d1serial_type(struct uart_port *port)
+{
+ return "ma35d1-uart";
+}
+
+static void ma35d1serial_config_port(struct uart_port *port, int flags)
+{
+ /*
+ * Driver core for serial ports forces a non-zero value for port type.
+ * Write an arbitrary value here to accommodate the serial core driver,
+ * as ID part of UAPI is redundant.
+ */
+ port->type = 1;
+}
+
+static int ma35d1serial_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ if (port->type != PORT_UNKNOWN && ser->type != 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct uart_ops ma35d1serial_ops = {
+ .tx_empty = ma35d1serial_tx_empty,
+ .set_mctrl = ma35d1serial_set_mctrl,
+ .get_mctrl = ma35d1serial_get_mctrl,
+ .stop_tx = ma35d1serial_stop_tx,
+ .start_tx = ma35d1serial_start_tx,
+ .stop_rx = ma35d1serial_stop_rx,
+ .break_ctl = ma35d1serial_break_ctl,
+ .startup = ma35d1serial_startup,
+ .shutdown = ma35d1serial_shutdown,
+ .set_termios = ma35d1serial_set_termios,
+ .type = ma35d1serial_type,
+ .config_port = ma35d1serial_config_port,
+ .verify_port = ma35d1serial_verify_port,
+};
+
+static const struct of_device_id ma35d1_serial_of_match[] = {
+ { .compatible = "nuvoton,ma35d1-uart" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ma35d1_serial_of_match);
+
+#ifdef CONFIG_SERIAL_NUVOTON_MA35D1_CONSOLE
+
+static struct device_node *ma35d1serial_uart_nodes[MA35_UART_NR];
+
+static void wait_for_xmitr(struct uart_ma35d1_port *up)
+{
+ unsigned int reg = 0;
+
+ read_poll_timeout_atomic(serial_in, reg, reg & MA35_FSR_TX_EMPTY,
+ 1, 10000, false,
+ up, MA35_FSR_REG);
+}
+
+static void ma35d1serial_console_putchar(struct uart_port *port, unsigned char ch)
+{
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+
+ wait_for_xmitr(up);
+ serial_out(up, MA35_THR_REG, ch);
+}
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ *
+ * The console_lock must be held when we get here.
+ */
+static void ma35d1serial_console_write(struct console *co, const char *s, u32 count)
+{
+ struct uart_ma35d1_port *up = &ma35d1serial_ports[co->index];
+ unsigned long flags;
+ int locked = 1;
+ u32 ier;
+
+ if (up->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock_irqsave(&up->port.lock, flags);
+ else
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ /*
+ * First save the IER then disable the interrupts
+ */
+ ier = serial_in(up, MA35_IER_REG);
+ serial_out(up, MA35_IER_REG, 0);
+
+ uart_console_write(&up->port, s, count, ma35d1serial_console_putchar);
+
+ wait_for_xmitr(up);
+ serial_out(up, MA35_IER_REG, ier);
+
+ if (locked)
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static int __init ma35d1serial_console_setup(struct console *co, char *options)
+{
+ struct device_node *np;
+ struct uart_ma35d1_port *p;
+ u32 val32[4];
+ struct uart_port *port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if ((co->index < 0) || (co->index >= MA35_UART_NR)) {
+ pr_debug("Console Port%x out of range\n", co->index);
+ return -EINVAL;
+ }
+
+ np = ma35d1serial_uart_nodes[co->index];
+ p = &ma35d1serial_ports[co->index];
+ if (!np || !p)
+ return -ENODEV;
+
+ if (of_property_read_u32_array(np, "reg", val32, ARRAY_SIZE(val32)) != 0)
+ return -EINVAL;
+
+ p->port.iobase = val32[1];
+ p->port.membase = ioremap(p->port.iobase, MA35_UART_REG_SIZE);
+ if (!p->port.membase)
+ return -ENOMEM;
+
+ p->port.ops = &ma35d1serial_ops;
+ p->port.line = 0;
+ p->port.uartclk = MA35_UART_CONSOLE_CLK;
+
+ port = &ma35d1serial_ports[co->index].port;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct console ma35d1serial_console = {
+ .name = "ttyNVT",
+ .write = ma35d1serial_console_write,
+ .device = uart_console_device,
+ .setup = ma35d1serial_console_setup,
+ .flags = CON_PRINTBUFFER | CON_ENABLED,
+ .index = -1,
+ .data = &ma35d1serial_reg,
+};
+
+static void ma35d1serial_console_init_port(void)
+{
+ u32 i = 0;
+ struct device_node *np;
+
+ for_each_matching_node(np, ma35d1_serial_of_match) {
+ if (ma35d1serial_uart_nodes[i] == NULL) {
+ of_node_get(np);
+ ma35d1serial_uart_nodes[i] = np;
+ i++;
+ if (i == MA35_UART_NR)
+ break;
+ }
+ }
+}
+
+static int __init ma35d1serial_console_init(void)
+{
+ ma35d1serial_console_init_port();
+ register_console(&ma35d1serial_console);
+ return 0;
+}
+console_initcall(ma35d1serial_console_init);
+
+#define MA35D1SERIAL_CONSOLE (&ma35d1serial_console)
+#else
+#define MA35D1SERIAL_CONSOLE NULL
+#endif
+
+static struct uart_driver ma35d1serial_reg = {
+ .owner = THIS_MODULE,
+ .driver_name = "serial",
+ .dev_name = "ttyNVT",
+ .major = TTY_MAJOR,
+ .minor = 64,
+ .cons = MA35D1SERIAL_CONSOLE,
+ .nr = MA35_UART_NR,
+};
+
+/*
+ * Register a set of serial devices attached to a platform device.
+ * The list is terminated with a zero flags entry, which means we expect
+ * all entries to have at least UPF_BOOT_AUTOCONF set.
+ */
+static int ma35d1serial_probe(struct platform_device *pdev)
+{
+ struct resource *res_mem;
+ struct uart_ma35d1_port *up;
+ int ret = 0;
+
+ if (pdev->dev.of_node) {
+ ret = of_alias_get_id(pdev->dev.of_node, "serial");
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", ret);
+ return ret;
+ }
+ }
+ up = &ma35d1serial_ports[ret];
+ up->port.line = ret;
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res_mem)
+ return -ENODEV;
+
+ up->port.iobase = res_mem->start;
+ up->port.membase = ioremap(up->port.iobase, MA35_UART_REG_SIZE);
+ up->port.ops = &ma35d1serial_ops;
+
+ spin_lock_init(&up->port.lock);
+
+ up->clk = of_clk_get(pdev->dev.of_node, 0);
+ if (IS_ERR(up->clk)) {
+ ret = PTR_ERR(up->clk);
+ dev_err(&pdev->dev, "failed to get core clk: %d\n", ret);
+ goto err_iounmap;
+ }
+
+ ret = clk_prepare_enable(up->clk);
+ if (ret)
+ goto err_iounmap;
+
+ if (up->port.line != 0)
+ up->port.uartclk = clk_get_rate(up->clk);
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ goto err_clk_disable;
+
+ up->port.irq = ret;
+ up->port.dev = &pdev->dev;
+ up->port.flags = UPF_BOOT_AUTOCONF;
+
+ platform_set_drvdata(pdev, up);
+
+ ret = uart_add_one_port(&ma35d1serial_reg, &up->port);
+ if (ret < 0)
+ goto err_free_irq;
+
+ return 0;
+
+err_free_irq:
+ free_irq(up->port.irq, &up->port);
+
+err_clk_disable:
+ clk_disable_unprepare(up->clk);
+
+err_iounmap:
+ iounmap(up->port.membase);
+ return ret;
+}
+
+/*
+ * Remove serial ports registered against a platform device.
+ */
+static int ma35d1serial_remove(struct platform_device *dev)
+{
+ struct uart_port *port = platform_get_drvdata(dev);
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+
+ uart_remove_one_port(&ma35d1serial_reg, port);
+ clk_disable_unprepare(up->clk);
+ return 0;
+}
+
+static int ma35d1serial_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct uart_port *port = platform_get_drvdata(dev);
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+
+ uart_suspend_port(&ma35d1serial_reg, &up->port);
+ if (up->port.line == 0) {
+ up->console_baud_rate = serial_in(up, MA35_BAUD_REG);
+ up->console_line = serial_in(up, MA35_LCR_REG);
+ up->console_int = serial_in(up, MA35_IER_REG);
+ }
+ return 0;
+}
+
+static int ma35d1serial_resume(struct platform_device *dev)
+{
+ struct uart_port *port = platform_get_drvdata(dev);
+ struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
+
+ if (up->port.line == 0) {
+ serial_out(up, MA35_BAUD_REG, up->console_baud_rate);
+ serial_out(up, MA35_LCR_REG, up->console_line);
+ serial_out(up, MA35_IER_REG, up->console_int);
+ }
+ uart_resume_port(&ma35d1serial_reg, &up->port);
+ return 0;
+}
+
+static struct platform_driver ma35d1serial_driver = {
+ .probe = ma35d1serial_probe,
+ .remove = ma35d1serial_remove,
+ .suspend = ma35d1serial_suspend,
+ .resume = ma35d1serial_resume,
+ .driver = {
+ .name = "ma35d1-uart",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(ma35d1_serial_of_match),
+ },
+};
+
+static int __init ma35d1serial_init(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&ma35d1serial_reg);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&ma35d1serial_driver);
+ if (ret)
+ uart_unregister_driver(&ma35d1serial_reg);
+
+ return ret;
+}
+
+static void __exit ma35d1serial_exit(void)
+{
+ platform_driver_unregister(&ma35d1serial_driver);
+ uart_unregister_driver(&ma35d1serial_reg);
+}
+
+module_init(ma35d1serial_init);
+module_exit(ma35d1serial_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MA35D1 serial driver");
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 9fee722058f4..997e39449766 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1636,7 +1636,7 @@ static struct i2c_driver max310x_i2c_driver = {
.of_match_table = max310x_dt_ids,
.pm = &max310x_pm_ops,
},
- .probe_new = max310x_i2c_probe,
+ .probe = max310x_i2c_probe,
.remove = max310x_i2c_remove,
};
#endif
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 8582479f0211..444c74eeab7d 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -1053,6 +1053,11 @@ static int setup_fifos(struct qcom_geni_serial_port *port)
(port->tx_fifo_depth * port->tx_fifo_width) / BITS_PER_BYTE;
if (port->rx_buf && (old_rx_fifo_depth != port->rx_fifo_depth) && port->rx_fifo_depth) {
+ /*
+ * Use krealloc rather than krealloc_array because rx_buf is
+ * accessed as 1 byte entries as well as 4 byte entries so it's
+ * not necessarily an array.
+ */
port->rx_buf = devm_krealloc(uport->dev, port->rx_buf,
port->rx_fifo_depth * sizeof(u32),
GFP_KERNEL);
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index 2a7520ad3abd..b29e9dfd81a6 100644
--- a/drivers/tty/serial/samsung_tty.c
+++ b/drivers/tty/serial/samsung_tty.c
@@ -24,6 +24,7 @@
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
+#include <linux/math.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/io.h>
@@ -1459,8 +1460,12 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
continue;
rate = clk_get_rate(clk);
- if (!rate)
+ if (!rate) {
+ dev_err(ourport->port.dev,
+ "Failed to get clock rate for %s.\n", clkname);
+ clk_put(clk);
continue;
+ }
if (ourport->info->has_divslot) {
unsigned long div = rate / req_baud;
@@ -1481,15 +1486,21 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
}
quot--;
- calc_deviation = req_baud - baud;
- if (calc_deviation < 0)
- calc_deviation = -calc_deviation;
+ calc_deviation = abs(req_baud - baud);
if (calc_deviation < deviation) {
+ /*
+ * If we find a better clk, release the previous one, if
+ * any.
+ */
+ if (!IS_ERR(*best_clk))
+ clk_put(*best_clk);
*best_clk = clk;
best_quot = quot;
*clk_num = cnt;
deviation = calc_deviation;
+ } else {
+ clk_put(clk);
}
}
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index abad091baeea..2e7e7c409cf2 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1709,7 +1709,7 @@ static struct i2c_driver sc16is7xx_i2c_uart_driver = {
.name = SC16IS7XX_NAME,
.of_match_table = sc16is7xx_dt_ids,
},
- .probe_new = sc16is7xx_i2c_probe,
+ .probe = sc16is7xx_i2c_probe,
.remove = sc16is7xx_i2c_remove,
.id_table = sc16is7xx_i2c_id_table,
};
diff --git a/drivers/tty/serial/serial_base.h b/drivers/tty/serial/serial_base.h
new file mode 100644
index 000000000000..9faac0ff6b89
--- /dev/null
+++ b/drivers/tty/serial/serial_base.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Serial core related functions, serial port device drivers do not need this.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ * Author: Tony Lindgren <tony@atomide.com>
+ */
+
+#define to_serial_base_ctrl_device(d) container_of((d), struct serial_ctrl_device, dev)
+#define to_serial_base_port_device(d) container_of((d), struct serial_port_device, dev)
+
+struct uart_driver;
+struct uart_port;
+struct device_driver;
+struct device;
+
+struct serial_ctrl_device {
+ struct device dev;
+};
+
+struct serial_port_device {
+ struct device dev;
+ struct uart_port *port;
+};
+
+int serial_base_ctrl_init(void);
+void serial_base_ctrl_exit(void);
+
+int serial_base_port_init(void);
+void serial_base_port_exit(void);
+
+int serial_base_driver_register(struct device_driver *driver);
+void serial_base_driver_unregister(struct device_driver *driver);
+
+struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port,
+ struct device *parent);
+struct serial_port_device *serial_base_port_add(struct uart_port *port,
+ struct serial_ctrl_device *parent);
+void serial_base_ctrl_device_remove(struct serial_ctrl_device *ctrl_dev);
+void serial_base_port_device_remove(struct serial_port_device *port_dev);
+
+int serial_ctrl_register_port(struct uart_driver *drv, struct uart_port *port);
+void serial_ctrl_unregister_port(struct uart_driver *drv, struct uart_port *port);
+
+int serial_core_register_port(struct uart_driver *drv, struct uart_port *port);
+void serial_core_unregister_port(struct uart_driver *drv, struct uart_port *port);
diff --git a/drivers/tty/serial/serial_base_bus.c b/drivers/tty/serial/serial_base_bus.c
new file mode 100644
index 000000000000..6ff59c89d867
--- /dev/null
+++ b/drivers/tty/serial/serial_base_bus.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Serial base bus layer for controllers
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ * Author: Tony Lindgren <tony@atomide.com>
+ *
+ * The serial core bus manages the serial core controller instances.
+ */
+
+#include <linux/container_of.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/serial_core.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "serial_base.h"
+
+static bool serial_base_initialized;
+
+static int serial_base_match(struct device *dev, struct device_driver *drv)
+{
+ int len = strlen(drv->name);
+
+ return !strncmp(dev_name(dev), drv->name, len);
+}
+
+static struct bus_type serial_base_bus_type = {
+ .name = "serial-base",
+ .match = serial_base_match,
+};
+
+int serial_base_driver_register(struct device_driver *driver)
+{
+ driver->bus = &serial_base_bus_type;
+
+ return driver_register(driver);
+}
+
+void serial_base_driver_unregister(struct device_driver *driver)
+{
+ driver_unregister(driver);
+}
+
+static int serial_base_device_init(struct uart_port *port,
+ struct device *dev,
+ struct device *parent_dev,
+ const struct device_type *type,
+ void (*release)(struct device *dev),
+ int id)
+{
+ device_initialize(dev);
+ dev->type = type;
+ dev->parent = parent_dev;
+ dev->bus = &serial_base_bus_type;
+ dev->release = release;
+
+ if (!serial_base_initialized) {
+ dev_dbg(port->dev, "uart_add_one_port() called before arch_initcall()?\n");
+ return -EPROBE_DEFER;
+ }
+
+ return dev_set_name(dev, "%s.%s.%d", type->name, dev_name(port->dev), id);
+}
+
+static const struct device_type serial_ctrl_type = {
+ .name = "ctrl",
+};
+
+static void serial_base_ctrl_release(struct device *dev)
+{
+ struct serial_ctrl_device *ctrl_dev = to_serial_base_ctrl_device(dev);
+
+ kfree(ctrl_dev);
+}
+
+void serial_base_ctrl_device_remove(struct serial_ctrl_device *ctrl_dev)
+{
+ if (!ctrl_dev)
+ return;
+
+ device_del(&ctrl_dev->dev);
+}
+
+struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port,
+ struct device *parent)
+{
+ struct serial_ctrl_device *ctrl_dev;
+ int err;
+
+ ctrl_dev = kzalloc(sizeof(*ctrl_dev), GFP_KERNEL);
+ if (!ctrl_dev)
+ return ERR_PTR(-ENOMEM);
+
+ err = serial_base_device_init(port, &ctrl_dev->dev,
+ parent, &serial_ctrl_type,
+ serial_base_ctrl_release,
+ port->ctrl_id);
+ if (err)
+ goto err_put_device;
+
+ err = device_add(&ctrl_dev->dev);
+ if (err)
+ goto err_put_device;
+
+ return ctrl_dev;
+
+err_put_device:
+ put_device(&ctrl_dev->dev);
+
+ return ERR_PTR(err);
+}
+
+static const struct device_type serial_port_type = {
+ .name = "port",
+};
+
+static void serial_base_port_release(struct device *dev)
+{
+ struct serial_port_device *port_dev = to_serial_base_port_device(dev);
+
+ kfree(port_dev);
+}
+
+struct serial_port_device *serial_base_port_add(struct uart_port *port,
+ struct serial_ctrl_device *ctrl_dev)
+{
+ struct serial_port_device *port_dev;
+ int err;
+
+ port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL);
+ if (!port_dev)
+ return ERR_PTR(-ENOMEM);
+
+ err = serial_base_device_init(port, &port_dev->dev,
+ &ctrl_dev->dev, &serial_port_type,
+ serial_base_port_release,
+ port->line);
+ if (err)
+ goto err_put_device;
+
+ port_dev->port = port;
+
+ err = device_add(&port_dev->dev);
+ if (err)
+ goto err_put_device;
+
+ return port_dev;
+
+err_put_device:
+ put_device(&port_dev->dev);
+
+ return ERR_PTR(err);
+}
+
+void serial_base_port_device_remove(struct serial_port_device *port_dev)
+{
+ if (!port_dev)
+ return;
+
+ device_del(&port_dev->dev);
+}
+
+static int serial_base_init(void)
+{
+ int ret;
+
+ ret = bus_register(&serial_base_bus_type);
+ if (ret)
+ return ret;
+
+ ret = serial_base_ctrl_init();
+ if (ret)
+ goto err_bus_unregister;
+
+ ret = serial_base_port_init();
+ if (ret)
+ goto err_ctrl_exit;
+
+ serial_base_initialized = true;
+
+ return 0;
+
+err_ctrl_exit:
+ serial_base_ctrl_exit();
+
+err_bus_unregister:
+ bus_unregister(&serial_base_bus_type);
+
+ return ret;
+}
+arch_initcall(serial_base_init);
+
+static void serial_base_exit(void)
+{
+ serial_base_port_exit();
+ serial_base_ctrl_exit();
+ bus_unregister(&serial_base_bus_type);
+}
+module_exit(serial_base_exit);
+
+MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
+MODULE_DESCRIPTION("Serial core bus");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 54e82f476a2c..831d033611e6 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -17,6 +17,7 @@
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/of.h>
+#include <linux/pm_runtime.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/device.h>
@@ -31,6 +32,8 @@
#include <linux/irq.h>
#include <linux/uaccess.h>
+#include "serial_base.h"
+
/*
* This is used to lock changes in serial line configuration.
*/
@@ -134,9 +137,30 @@ static void __uart_start(struct tty_struct *tty)
{
struct uart_state *state = tty->driver_data;
struct uart_port *port = state->uart_port;
+ struct serial_port_device *port_dev;
+ int err;
+
+ if (!port || port->flags & UPF_DEAD || uart_tx_stopped(port))
+ return;
+
+ port_dev = port->port_dev;
+
+ /* Increment the runtime PM usage count for the active check below */
+ err = pm_runtime_get(&port_dev->dev);
+ if (err < 0) {
+ pm_runtime_put_noidle(&port_dev->dev);
+ return;
+ }
- if (port && !(port->flags & UPF_DEAD) && !uart_tx_stopped(port))
+ /*
+ * Start TX if enabled, and kick runtime PM. If the device is not
+ * enabled, serial_port_runtime_resume() calls start_tx() again
+ * after enabling the device.
+ */
+ if (pm_runtime_active(&port_dev->dev))
port->ops->start_tx(port);
+ pm_runtime_mark_last_busy(&port_dev->dev);
+ pm_runtime_put_autosuspend(&port_dev->dev);
}
static void uart_start(struct tty_struct *tty)
@@ -2333,8 +2357,11 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
* able to Re-start_rx later.
*/
if (!console_suspend_enabled && uart_console(uport)) {
- if (uport->ops->start_rx)
+ if (uport->ops->start_rx) {
+ spin_lock_irq(&uport->lock);
uport->ops->stop_rx(uport);
+ spin_unlock_irq(&uport->lock);
+ }
goto unlock;
}
@@ -2427,8 +2454,11 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
if (console_suspend_enabled)
uart_change_pm(state, UART_PM_STATE_ON);
uport->ops->set_termios(uport, &termios, NULL);
- if (!console_suspend_enabled && uport->ops->start_rx)
+ if (!console_suspend_enabled && uport->ops->start_rx) {
+ spin_lock_irq(&uport->lock);
uport->ops->start_rx(uport);
+ spin_unlock_irq(&uport->lock);
+ }
if (console_suspend_enabled)
console_start(uport->cons);
}
@@ -3042,7 +3072,7 @@ static const struct attribute_group tty_dev_attr_group = {
};
/**
- * uart_add_one_port - attach a driver-defined port structure
+ * serial_core_add_one_port - attach a driver-defined port structure
* @drv: pointer to the uart low level driver structure for this port
* @uport: uart port structure to use for this port.
*
@@ -3051,8 +3081,9 @@ static const struct attribute_group tty_dev_attr_group = {
* This allows the driver @drv to register its own uart_port structure with the
* core driver. The main purpose is to allow the low level uart drivers to
* expand uart_port, rather than having yet more levels of structures.
+ * Caller must hold port_mutex.
*/
-int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
+static int serial_core_add_one_port(struct uart_driver *drv, struct uart_port *uport)
{
struct uart_state *state;
struct tty_port *port;
@@ -3066,7 +3097,6 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
state = drv->state + uport->line;
port = &state->port;
- mutex_lock(&port_mutex);
mutex_lock(&port->mutex);
if (state->uart_port) {
ret = -EINVAL;
@@ -3131,21 +3161,14 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
uport->line);
}
- /*
- * Ensure UPF_DEAD is not set.
- */
- uport->flags &= ~UPF_DEAD;
-
out:
mutex_unlock(&port->mutex);
- mutex_unlock(&port_mutex);
return ret;
}
-EXPORT_SYMBOL(uart_add_one_port);
/**
- * uart_remove_one_port - detach a driver defined port structure
+ * serial_core_remove_one_port - detach a driver defined port structure
* @drv: pointer to the uart low level driver structure for this port
* @uport: uart port structure for this port
*
@@ -3153,21 +3176,16 @@ EXPORT_SYMBOL(uart_add_one_port);
*
* This unhooks (and hangs up) the specified port structure from the core
* driver. No further calls will be made to the low-level code for this port.
+ * Caller must hold port_mutex.
*/
-int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
+static void serial_core_remove_one_port(struct uart_driver *drv,
+ struct uart_port *uport)
{
struct uart_state *state = drv->state + uport->line;
struct tty_port *port = &state->port;
struct uart_port *uart_port;
struct tty_struct *tty;
- int ret = 0;
-
- mutex_lock(&port_mutex);
- /*
- * Mark the port "dead" - this prevents any opens from
- * succeeding while we shut down the port.
- */
mutex_lock(&port->mutex);
uart_port = uart_port_check(state);
if (uart_port != uport)
@@ -3176,10 +3194,8 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
if (!uart_port) {
mutex_unlock(&port->mutex);
- ret = -EINVAL;
- goto out;
+ return;
}
- uport->flags |= UPF_DEAD;
mutex_unlock(&port->mutex);
/*
@@ -3211,18 +3227,14 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
* Indicate that there isn't a port here anymore.
*/
uport->type = PORT_UNKNOWN;
+ uport->port_dev = NULL;
mutex_lock(&port->mutex);
WARN_ON(atomic_dec_return(&state->refcount) < 0);
wait_event(state->remove_wait, !atomic_read(&state->refcount));
state->uart_port = NULL;
mutex_unlock(&port->mutex);
-out:
- mutex_unlock(&port_mutex);
-
- return ret;
}
-EXPORT_SYMBOL(uart_remove_one_port);
/**
* uart_match_port - are the two ports equivalent?
@@ -3257,6 +3269,144 @@ bool uart_match_port(const struct uart_port *port1,
}
EXPORT_SYMBOL(uart_match_port);
+static struct serial_ctrl_device *
+serial_core_get_ctrl_dev(struct serial_port_device *port_dev)
+{
+ struct device *dev = &port_dev->dev;
+
+ return to_serial_base_ctrl_device(dev->parent);
+}
+
+/*
+ * Find a registered serial core controller device if one exists. Returns
+ * the first device matching the ctrl_id. Caller must hold port_mutex.
+ */
+static struct serial_ctrl_device *serial_core_ctrl_find(struct uart_driver *drv,
+ struct device *phys_dev,
+ int ctrl_id)
+{
+ struct uart_state *state;
+ int i;
+
+ lockdep_assert_held(&port_mutex);
+
+ for (i = 0; i < drv->nr; i++) {
+ state = drv->state + i;
+ if (!state->uart_port || !state->uart_port->port_dev)
+ continue;
+
+ if (state->uart_port->dev == phys_dev &&
+ state->uart_port->ctrl_id == ctrl_id)
+ return serial_core_get_ctrl_dev(state->uart_port->port_dev);
+ }
+
+ return NULL;
+}
+
+static struct serial_ctrl_device *serial_core_ctrl_device_add(struct uart_port *port)
+{
+ return serial_base_ctrl_add(port, port->dev);
+}
+
+static int serial_core_port_device_add(struct serial_ctrl_device *ctrl_dev,
+ struct uart_port *port)
+{
+ struct serial_port_device *port_dev;
+
+ port_dev = serial_base_port_add(port, ctrl_dev);
+ if (IS_ERR(port_dev))
+ return PTR_ERR(port_dev);
+
+ port->port_dev = port_dev;
+
+ return 0;
+}
+
+/*
+ * Initialize a serial core port device, and a controller device if needed.
+ */
+int serial_core_register_port(struct uart_driver *drv, struct uart_port *port)
+{
+ struct serial_ctrl_device *ctrl_dev, *new_ctrl_dev = NULL;
+ int ret;
+
+ mutex_lock(&port_mutex);
+
+ /*
+ * Prevent serial_port_runtime_resume() from trying to use the port
+ * until serial_core_add_one_port() has completed
+ */
+ port->flags |= UPF_DEAD;
+
+ /* Inititalize a serial core controller device if needed */
+ ctrl_dev = serial_core_ctrl_find(drv, port->dev, port->ctrl_id);
+ if (!ctrl_dev) {
+ new_ctrl_dev = serial_core_ctrl_device_add(port);
+ if (IS_ERR(new_ctrl_dev)) {
+ ret = PTR_ERR(new_ctrl_dev);
+ goto err_unlock;
+ }
+ ctrl_dev = new_ctrl_dev;
+ }
+
+ /*
+ * Initialize a serial core port device. Tag the port dead to prevent
+ * serial_port_runtime_resume() trying to do anything until port has
+ * been registered. It gets cleared by serial_core_add_one_port().
+ */
+ ret = serial_core_port_device_add(ctrl_dev, port);
+ if (ret)
+ goto err_unregister_ctrl_dev;
+
+ ret = serial_core_add_one_port(drv, port);
+ if (ret)
+ goto err_unregister_port_dev;
+
+ port->flags &= ~UPF_DEAD;
+
+ mutex_unlock(&port_mutex);
+
+ return 0;
+
+err_unregister_port_dev:
+ serial_base_port_device_remove(port->port_dev);
+
+err_unregister_ctrl_dev:
+ serial_base_ctrl_device_remove(new_ctrl_dev);
+
+err_unlock:
+ mutex_unlock(&port_mutex);
+
+ return ret;
+}
+
+/*
+ * Removes a serial core port device, and the related serial core controller
+ * device if the last instance.
+ */
+void serial_core_unregister_port(struct uart_driver *drv, struct uart_port *port)
+{
+ struct device *phys_dev = port->dev;
+ struct serial_port_device *port_dev = port->port_dev;
+ struct serial_ctrl_device *ctrl_dev = serial_core_get_ctrl_dev(port_dev);
+ int ctrl_id = port->ctrl_id;
+
+ mutex_lock(&port_mutex);
+
+ port->flags |= UPF_DEAD;
+
+ serial_core_remove_one_port(drv, port);
+
+ /* Note that struct uart_port *port is no longer valid at this point */
+ serial_base_port_device_remove(port_dev);
+
+ /* Drop the serial core controller device if no ports are using it */
+ if (!serial_core_ctrl_find(drv, phys_dev, ctrl_id))
+ serial_base_ctrl_device_remove(ctrl_dev);
+
+ mutex_unlock(&port_mutex);
+}
+
/**
* uart_handle_dcd_change - handle a change of carrier detect state
* @uport: uart_port structure for the open port
diff --git a/drivers/tty/serial/serial_ctrl.c b/drivers/tty/serial/serial_ctrl.c
new file mode 100644
index 000000000000..6fcf634425dc
--- /dev/null
+++ b/drivers/tty/serial/serial_ctrl.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Serial core controller driver
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ * Author: Tony Lindgren <tony@atomide.com>
+ *
+ * This driver manages the serial core controller struct device instances.
+ * The serial core controller devices are children of the physical serial
+ * port device.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/serial_core.h>
+#include <linux/spinlock.h>
+
+#include "serial_base.h"
+
+static int serial_ctrl_probe(struct device *dev)
+{
+ pm_runtime_enable(dev);
+
+ return 0;
+}
+
+static int serial_ctrl_remove(struct device *dev)
+{
+ pm_runtime_disable(dev);
+
+ return 0;
+}
+
+/*
+ * Serial core controller device init functions. Note that the physical
+ * serial port device driver may not have completed probe at this point.
+ */
+int serial_ctrl_register_port(struct uart_driver *drv, struct uart_port *port)
+{
+ return serial_core_register_port(drv, port);
+}
+
+void serial_ctrl_unregister_port(struct uart_driver *drv, struct uart_port *port)
+{
+ serial_core_unregister_port(drv, port);
+}
+
+static struct device_driver serial_ctrl_driver = {
+ .name = "ctrl",
+ .suppress_bind_attrs = true,
+ .probe = serial_ctrl_probe,
+ .remove = serial_ctrl_remove,
+};
+
+int serial_base_ctrl_init(void)
+{
+ return serial_base_driver_register(&serial_ctrl_driver);
+}
+
+void serial_base_ctrl_exit(void)
+{
+ serial_base_driver_unregister(&serial_ctrl_driver);
+}
+
+MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
+MODULE_DESCRIPTION("Serial core controller driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/serial_port.c b/drivers/tty/serial/serial_port.c
new file mode 100644
index 000000000000..862423237007
--- /dev/null
+++ b/drivers/tty/serial/serial_port.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Serial core port device driver
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ * Author: Tony Lindgren <tony@atomide.com>
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/serial_core.h>
+#include <linux/spinlock.h>
+
+#include "serial_base.h"
+
+#define SERIAL_PORT_AUTOSUSPEND_DELAY_MS 500
+
+/* Only considers pending TX for now. Caller must take care of locking */
+static int __serial_port_busy(struct uart_port *port)
+{
+ return !uart_tx_stopped(port) &&
+ uart_circ_chars_pending(&port->state->xmit);
+}
+
+static int serial_port_runtime_resume(struct device *dev)
+{
+ struct serial_port_device *port_dev = to_serial_base_port_device(dev);
+ struct uart_port *port;
+ unsigned long flags;
+
+ port = port_dev->port;
+
+ if (port->flags & UPF_DEAD)
+ goto out;
+
+ /* Flush any pending TX for the port */
+ spin_lock_irqsave(&port->lock, flags);
+ if (__serial_port_busy(port))
+ port->ops->start_tx(port);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+out:
+ pm_runtime_mark_last_busy(dev);
+
+ return 0;
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(serial_port_pm,
+ NULL, serial_port_runtime_resume, NULL);
+
+static int serial_port_probe(struct device *dev)
+{
+ pm_runtime_enable(dev);
+ pm_runtime_set_autosuspend_delay(dev, SERIAL_PORT_AUTOSUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(dev);
+
+ return 0;
+}
+
+static int serial_port_remove(struct device *dev)
+{
+ pm_runtime_dont_use_autosuspend(dev);
+ pm_runtime_disable(dev);
+
+ return 0;
+}
+
+/*
+ * Serial core port device init functions. Note that the physical serial
+ * port device driver may not have completed probe at this point.
+ */
+int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
+{
+ return serial_ctrl_register_port(drv, port);
+}
+EXPORT_SYMBOL(uart_add_one_port);
+
+void uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
+{
+ serial_ctrl_unregister_port(drv, port);
+}
+EXPORT_SYMBOL(uart_remove_one_port);
+
+static struct device_driver serial_port_driver = {
+ .name = "port",
+ .suppress_bind_attrs = true,
+ .probe = serial_port_probe,
+ .remove = serial_port_remove,
+ .pm = pm_ptr(&serial_port_pm),
+};
+
+int serial_base_port_init(void)
+{
+ return serial_base_driver_register(&serial_port_driver);
+}
+
+void serial_base_port_exit(void)
+{
+ serial_base_driver_unregister(&serial_port_driver);
+}
+
+MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
+MODULE_DESCRIPTION("Serial controller port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
index 5215e6910f68..aa471c9c24d9 100644
--- a/drivers/tty/serial/st-asc.c
+++ b/drivers/tty/serial/st-asc.c
@@ -754,7 +754,7 @@ static struct asc_port *asc_of_get_asc_port(struct platform_device *pdev)
asc_ports[id].hw_flow_control = of_property_read_bool(np,
"uart-has-rtscts");
- asc_ports[id].force_m1 = of_property_read_bool(np, "st,force_m1");
+ asc_ports[id].force_m1 = of_property_read_bool(np, "st,force-m1");
asc_ports[id].port.line = id;
asc_ports[id].rts = NULL;
@@ -796,7 +796,9 @@ static int asc_serial_remove(struct platform_device *pdev)
{
struct uart_port *port = platform_get_drvdata(pdev);
- return uart_remove_one_port(&asc_uart_driver, port);
+ uart_remove_one_port(&asc_uart_driver, port);
+
+ return 0;
}
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 1e38fc9b10c1..e9e11a259621 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -1755,13 +1755,10 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
struct uart_port *port = platform_get_drvdata(pdev);
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- int err;
u32 cr3;
pm_runtime_get_sync(&pdev->dev);
- err = uart_remove_one_port(&stm32_usart_driver, port);
- if (err)
- return(err);
+ uart_remove_one_port(&stm32_usart_driver, port);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 94584e54ebbe..679574893ebe 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -685,18 +685,15 @@ static int ulite_assign(struct device *dev, int id, phys_addr_t base, int irq,
*
* @dev: pointer to device structure
*/
-static int ulite_release(struct device *dev)
+static void ulite_release(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
- int rc = 0;
if (port) {
- rc = uart_remove_one_port(&ulite_uart_driver, port);
+ uart_remove_one_port(&ulite_uart_driver, port);
dev_set_drvdata(dev, NULL);
port->mapbase = 0;
}
-
- return rc;
}
/**
@@ -900,14 +897,13 @@ static int ulite_remove(struct platform_device *pdev)
{
struct uart_port *port = dev_get_drvdata(&pdev->dev);
struct uartlite_data *pdata = port->private_data;
- int rc;
clk_disable_unprepare(pdata->clk);
- rc = ulite_release(&pdev->dev);
+ ulite_release(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
- return rc;
+ return 0;
}
/* work with hotplug and coldplug */
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index 8e521c69a959..20a751663ef9 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -1670,14 +1670,13 @@ static int cdns_uart_remove(struct platform_device *pdev)
{
struct uart_port *port = platform_get_drvdata(pdev);
struct cdns_uart *cdns_uart_data = port->private_data;
- int rc;
/* Remove the cdns_uart port from the serial core */
#ifdef CONFIG_COMMON_CLK
clk_notifier_unregister(cdns_uart_data->uartclk,
&cdns_uart_data->clk_rate_change_nb);
#endif
- rc = uart_remove_one_port(cdns_uart_data->cdns_uart_driver, port);
+ uart_remove_one_port(cdns_uart_data->cdns_uart_driver, port);
port->mapbase = 0;
clk_disable_unprepare(cdns_uart_data->uartclk);
clk_disable_unprepare(cdns_uart_data->pclk);
@@ -1693,7 +1692,7 @@ static int cdns_uart_remove(struct platform_device *pdev)
if (!--instances)
uart_unregister_driver(cdns_uart_data->cdns_uart_driver);
- return rc;
+ return 0;
}
static struct platform_driver cdns_uart_platform_driver = {
diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h
index 1e0d80e98d26..89769a1f1f97 100644
--- a/drivers/tty/tty.h
+++ b/drivers/tty/tty.h
@@ -99,14 +99,15 @@ extern int tty_ldisc_autoload;
/* tty_audit.c */
#ifdef CONFIG_AUDIT
-void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size);
-void tty_audit_tiocsti(struct tty_struct *tty, char ch);
+void tty_audit_add_data(const struct tty_struct *tty, const void *data,
+ size_t size);
+void tty_audit_tiocsti(const struct tty_struct *tty, char ch);
#else
-static inline void tty_audit_add_data(struct tty_struct *tty, const void *data,
- size_t size)
+static inline void tty_audit_add_data(const struct tty_struct *tty,
+ const void *data, size_t size)
{
}
-static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch)
+static inline void tty_audit_tiocsti(const struct tty_struct *tty, char ch)
{
}
#endif
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
index ca7afd7b2716..24d010589379 100644
--- a/drivers/tty/tty_audit.c
+++ b/drivers/tty/tty_audit.c
@@ -15,7 +15,7 @@
struct tty_audit_buf {
struct mutex mutex; /* Protects all data below */
dev_t dev; /* The TTY which the data is from */
- unsigned icanon:1;
+ bool icanon;
size_t valid;
unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */
};
@@ -33,16 +33,16 @@ static struct tty_audit_buf *tty_audit_buf_alloc(void)
{
struct tty_audit_buf *buf;
- buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+ buf = kzalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
goto err;
+
buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
if (!buf->data)
goto err_buf;
+
mutex_init(&buf->mutex);
- buf->dev = MKDEV(0, 0);
- buf->icanon = 0;
- buf->valid = 0;
+
return buf;
err_buf:
@@ -59,27 +59,27 @@ static void tty_audit_buf_free(struct tty_audit_buf *buf)
}
static void tty_audit_log(const char *description, dev_t dev,
- unsigned char *data, size_t size)
+ const unsigned char *data, size_t size)
{
struct audit_buffer *ab;
pid_t pid = task_pid_nr(current);
uid_t uid = from_kuid(&init_user_ns, task_uid(current));
uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current));
unsigned int sessionid = audit_get_sessionid(current);
+ char name[TASK_COMM_LEN];
ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_TTY);
- if (ab) {
- char name[sizeof(current->comm)];
-
- audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d"
- " minor=%d comm=", description, pid, uid,
- loginuid, sessionid, MAJOR(dev), MINOR(dev));
- get_task_comm(name, current);
- audit_log_untrustedstring(ab, name);
- audit_log_format(ab, " data=");
- audit_log_n_hex(ab, data, size);
- audit_log_end(ab);
- }
+ if (!ab)
+ return;
+
+ audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d minor=%d comm=",
+ description, pid, uid, loginuid, sessionid,
+ MAJOR(dev), MINOR(dev));
+ get_task_comm(name, current);
+ audit_log_untrustedstring(ab, name);
+ audit_log_format(ab, " data=");
+ audit_log_n_hex(ab, data, size);
+ audit_log_end(ab);
}
/*
@@ -134,7 +134,7 @@ void tty_audit_fork(struct signal_struct *sig)
/*
* tty_audit_tiocsti - Log TIOCSTI
*/
-void tty_audit_tiocsti(struct tty_struct *tty, char ch)
+void tty_audit_tiocsti(const struct tty_struct *tty, char ch)
{
dev_t dev;
@@ -199,11 +199,12 @@ static struct tty_audit_buf *tty_audit_buf_get(void)
*
* Audit @data of @size from @tty, if necessary.
*/
-void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size)
+void tty_audit_add_data(const struct tty_struct *tty, const void *data,
+ size_t size)
{
struct tty_audit_buf *buf;
- unsigned int icanon = !!L_ICANON(tty);
unsigned int audit_tty;
+ bool icanon = L_ICANON(tty);
dev_t dev;
audit_tty = READ_ONCE(current->signal->audit_tty);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 4737a8f92c2e..3959efc717aa 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -101,6 +101,7 @@
#include <linux/compat.h>
#include <linux/uaccess.h>
#include <linux/termios_internal.h>
+#include <linux/fs.h>
#include <linux/kbd_kern.h>
#include <linux/vt_kern.h>
@@ -811,18 +812,26 @@ void start_tty(struct tty_struct *tty)
}
EXPORT_SYMBOL(start_tty);
-static void tty_update_time(struct timespec64 *time)
+static void tty_update_time(struct tty_struct *tty, bool mtime)
{
time64_t sec = ktime_get_real_seconds();
+ struct tty_file_private *priv;
- /*
- * We only care if the two values differ in anything other than the
- * lower three bits (i.e every 8 seconds). If so, then we can update
- * the time of the tty device, otherwise it could be construded as a
- * security leak to let userspace know the exact timing of the tty.
- */
- if ((sec ^ time->tv_sec) & ~7)
- time->tv_sec = sec;
+ spin_lock(&tty->files_lock);
+ list_for_each_entry(priv, &tty->tty_files, list) {
+ struct inode *inode = file_inode(priv->file);
+ struct timespec64 *time = mtime ? &inode->i_mtime : &inode->i_atime;
+
+ /*
+ * We only care if the two values differ in anything other than the
+ * lower three bits (i.e every 8 seconds). If so, then we can update
+ * the time of the tty device, otherwise it could be construded as a
+ * security leak to let userspace know the exact timing of the tty.
+ */
+ if ((sec ^ time->tv_sec) & ~7)
+ time->tv_sec = sec;
+ }
+ spin_unlock(&tty->files_lock);
}
/*
@@ -928,7 +937,7 @@ static ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to)
tty_ldisc_deref(ld);
if (i > 0)
- tty_update_time(&inode->i_atime);
+ tty_update_time(tty, false);
return i;
}
@@ -1036,7 +1045,7 @@ static inline ssize_t do_tty_write(
cond_resched();
}
if (written) {
- tty_update_time(&file_inode(file)->i_mtime);
+ tty_update_time(tty, true);
ret = written;
}
out:
diff --git a/drivers/ufs/core/ufs-fault-injection.c b/drivers/ufs/core/ufs-fault-injection.c
index 7ac7c4e7ff83..5b1184aac585 100644
--- a/drivers/ufs/core/ufs-fault-injection.c
+++ b/drivers/ufs/core/ufs-fault-injection.c
@@ -54,7 +54,7 @@ static int ufs_fault_set(const char *val, const struct kernel_param *kp)
if (!setup_fault_attr(attr, (char *)val))
return -EINVAL;
- strlcpy(kp->arg, val, FAULT_INJ_STR_SIZE);
+ strscpy(kp->arg, val, FAULT_INJ_STR_SIZE);
return 0;
}
diff --git a/drivers/ufs/core/ufs-hwmon.c b/drivers/ufs/core/ufs-hwmon.c
index 4c6a872b7a7c..101d7082446f 100644
--- a/drivers/ufs/core/ufs-hwmon.c
+++ b/drivers/ufs/core/ufs-hwmon.c
@@ -146,7 +146,7 @@ static umode_t ufs_hwmon_is_visible(const void *_data, enum hwmon_sensor_types t
return 0;
}
-static const struct hwmon_channel_info *ufs_hwmon_info[] = {
+static const struct hwmon_channel_info *const ufs_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LCRIT),
NULL
};
diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
index 51b3c6ae781d..6fb0e007af63 100644
--- a/drivers/ufs/core/ufs-mcq.c
+++ b/drivers/ufs/core/ufs-mcq.c
@@ -12,21 +12,26 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include "ufshcd-priv.h"
+#include <linux/delay.h>
+#include <scsi/scsi_cmnd.h>
+#include <linux/bitfield.h>
+#include <linux/iopoll.h>
#define MAX_QUEUE_SUP GENMASK(7, 0)
#define UFS_MCQ_MIN_RW_QUEUES 2
#define UFS_MCQ_MIN_READ_QUEUES 0
-#define UFS_MCQ_NUM_DEV_CMD_QUEUES 1
#define UFS_MCQ_MIN_POLL_QUEUES 0
#define QUEUE_EN_OFFSET 31
#define QUEUE_ID_OFFSET 16
-#define MAX_DEV_CMD_ENTRIES 2
#define MCQ_CFG_MAC_MASK GENMASK(16, 8)
#define MCQ_QCFG_SIZE 0x40
#define MCQ_ENTRY_SIZE_IN_DWORD 8
#define CQE_UCD_BA GENMASK_ULL(63, 7)
+/* Max mcq register polling time in microseconds */
+#define MCQ_POLL_US 500000
+
static int rw_queue_count_set(const char *val, const struct kernel_param *kp)
{
return param_set_uint_minmax(val, kp, UFS_MCQ_MIN_RW_QUEUES,
@@ -108,8 +113,7 @@ struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba,
u32 utag = blk_mq_unique_tag(req);
u32 hwq = blk_mq_unique_tag_to_hwq(utag);
- /* uhq[0] is used to serve device commands */
- return &hba->uhq[hwq + UFSHCD_MCQ_IO_QUEUE_OFFSET];
+ return &hba->uhq[hwq];
}
/**
@@ -153,8 +157,7 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba)
/* maxq is 0 based value */
hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities) + 1;
- tot_queues = UFS_MCQ_NUM_DEV_CMD_QUEUES + read_queues + poll_queues +
- rw_queues;
+ tot_queues = read_queues + poll_queues + rw_queues;
if (hba_maxq < tot_queues) {
dev_err(hba->dev, "Total queues (%d) exceeds HC capacity (%d)\n",
@@ -162,7 +165,7 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba)
return -EOPNOTSUPP;
}
- rem = hba_maxq - UFS_MCQ_NUM_DEV_CMD_QUEUES;
+ rem = hba_maxq;
if (rw_queues) {
hba->nr_queues[HCTX_TYPE_DEFAULT] = rw_queues;
@@ -188,7 +191,7 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba)
for (i = 0; i < HCTX_MAX_TYPES; i++)
host->nr_hw_queues += hba->nr_queues[i];
- hba->nr_hw_queues = host->nr_hw_queues + UFS_MCQ_NUM_DEV_CMD_QUEUES;
+ hba->nr_hw_queues = host->nr_hw_queues;
return 0;
}
@@ -270,44 +273,57 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba,
}
static void ufshcd_mcq_process_cqe(struct ufs_hba *hba,
- struct ufs_hw_queue *hwq)
+ struct ufs_hw_queue *hwq)
{
struct cq_entry *cqe = ufshcd_mcq_cur_cqe(hwq);
int tag = ufshcd_mcq_get_tag(hba, hwq, cqe);
- ufshcd_compl_one_cqe(hba, tag, cqe);
+ if (cqe->command_desc_base_addr) {
+ ufshcd_compl_one_cqe(hba, tag, cqe);
+ /* After processed the cqe, mark it empty (invalid) entry */
+ cqe->command_desc_base_addr = 0;
+ }
}
-unsigned long ufshcd_mcq_poll_cqe_nolock(struct ufs_hba *hba,
- struct ufs_hw_queue *hwq)
+void ufshcd_mcq_compl_all_cqes_lock(struct ufs_hba *hba,
+ struct ufs_hw_queue *hwq)
{
- unsigned long completed_reqs = 0;
+ unsigned long flags;
+ u32 entries = hwq->max_entries;
- ufshcd_mcq_update_cq_tail_slot(hwq);
- while (!ufshcd_mcq_is_cq_empty(hwq)) {
+ spin_lock_irqsave(&hwq->cq_lock, flags);
+ while (entries > 0) {
ufshcd_mcq_process_cqe(hba, hwq);
ufshcd_mcq_inc_cq_head_slot(hwq);
- completed_reqs++;
+ entries--;
}
- if (completed_reqs)
- ufshcd_mcq_update_cq_head(hwq);
-
- return completed_reqs;
+ ufshcd_mcq_update_cq_tail_slot(hwq);
+ hwq->cq_head_slot = hwq->cq_tail_slot;
+ spin_unlock_irqrestore(&hwq->cq_lock, flags);
}
-EXPORT_SYMBOL_GPL(ufshcd_mcq_poll_cqe_nolock);
unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba,
struct ufs_hw_queue *hwq)
{
- unsigned long completed_reqs, flags;
+ unsigned long completed_reqs = 0;
+ unsigned long flags;
spin_lock_irqsave(&hwq->cq_lock, flags);
- completed_reqs = ufshcd_mcq_poll_cqe_nolock(hba, hwq);
+ ufshcd_mcq_update_cq_tail_slot(hwq);
+ while (!ufshcd_mcq_is_cq_empty(hwq)) {
+ ufshcd_mcq_process_cqe(hba, hwq);
+ ufshcd_mcq_inc_cq_head_slot(hwq);
+ completed_reqs++;
+ }
+
+ if (completed_reqs)
+ ufshcd_mcq_update_cq_head(hwq);
spin_unlock_irqrestore(&hwq->cq_lock, flags);
return completed_reqs;
}
+EXPORT_SYMBOL_GPL(ufshcd_mcq_poll_cqe_lock);
void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba)
{
@@ -420,13 +436,243 @@ int ufshcd_mcq_init(struct ufs_hba *hba)
hwq->max_entries = hba->nutrs;
spin_lock_init(&hwq->sq_lock);
spin_lock_init(&hwq->cq_lock);
+ mutex_init(&hwq->sq_mutex);
}
/* The very first HW queue serves device commands */
hba->dev_cmd_queue = &hba->uhq[0];
- /* Give dev_cmd_queue the minimal number of entries */
- hba->dev_cmd_queue->max_entries = MAX_DEV_CMD_ENTRIES;
host->host_tagset = 1;
return 0;
}
+
+static int ufshcd_mcq_sq_stop(struct ufs_hba *hba, struct ufs_hw_queue *hwq)
+{
+ void __iomem *reg;
+ u32 id = hwq->id, val;
+ int err;
+
+ if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC)
+ return -ETIMEDOUT;
+
+ writel(SQ_STOP, mcq_opr_base(hba, OPR_SQD, id) + REG_SQRTC);
+ reg = mcq_opr_base(hba, OPR_SQD, id) + REG_SQRTS;
+ err = read_poll_timeout(readl, val, val & SQ_STS, 20,
+ MCQ_POLL_US, false, reg);
+ if (err)
+ dev_err(hba->dev, "%s: failed. hwq-id=%d, err=%d\n",
+ __func__, id, err);
+ return err;
+}
+
+static int ufshcd_mcq_sq_start(struct ufs_hba *hba, struct ufs_hw_queue *hwq)
+{
+ void __iomem *reg;
+ u32 id = hwq->id, val;
+ int err;
+
+ if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC)
+ return -ETIMEDOUT;
+
+ writel(SQ_START, mcq_opr_base(hba, OPR_SQD, id) + REG_SQRTC);
+ reg = mcq_opr_base(hba, OPR_SQD, id) + REG_SQRTS;
+ err = read_poll_timeout(readl, val, !(val & SQ_STS), 20,
+ MCQ_POLL_US, false, reg);
+ if (err)
+ dev_err(hba->dev, "%s: failed. hwq-id=%d, err=%d\n",
+ __func__, id, err);
+ return err;
+}
+
+/**
+ * ufshcd_mcq_sq_cleanup - Clean up submission queue resources
+ * associated with the pending command.
+ * @hba - per adapter instance.
+ * @task_tag - The command's task tag.
+ *
+ * Returns 0 for success; error code otherwise.
+ */
+int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag)
+{
+ struct ufshcd_lrb *lrbp = &hba->lrb[task_tag];
+ struct scsi_cmnd *cmd = lrbp->cmd;
+ struct ufs_hw_queue *hwq;
+ void __iomem *reg, *opr_sqd_base;
+ u32 nexus, id, val;
+ int err;
+
+ if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC)
+ return -ETIMEDOUT;
+
+ if (task_tag != hba->nutrs - UFSHCD_NUM_RESERVED) {
+ if (!cmd)
+ return -EINVAL;
+ hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd));
+ } else {
+ hwq = hba->dev_cmd_queue;
+ }
+
+ id = hwq->id;
+
+ mutex_lock(&hwq->sq_mutex);
+
+ /* stop the SQ fetching before working on it */
+ err = ufshcd_mcq_sq_stop(hba, hwq);
+ if (err)
+ goto unlock;
+
+ /* SQCTI = EXT_IID, IID, LUN, Task Tag */
+ nexus = lrbp->lun << 8 | task_tag;
+ opr_sqd_base = mcq_opr_base(hba, OPR_SQD, id);
+ writel(nexus, opr_sqd_base + REG_SQCTI);
+
+ /* SQRTCy.ICU = 1 */
+ writel(SQ_ICU, opr_sqd_base + REG_SQRTC);
+
+ /* Poll SQRTSy.CUS = 1. Return result from SQRTSy.RTC */
+ reg = opr_sqd_base + REG_SQRTS;
+ err = read_poll_timeout(readl, val, val & SQ_CUS, 20,
+ MCQ_POLL_US, false, reg);
+ if (err)
+ dev_err(hba->dev, "%s: failed. hwq=%d, tag=%d err=%ld\n",
+ __func__, id, task_tag,
+ FIELD_GET(SQ_ICU_ERR_CODE_MASK, readl(reg)));
+
+ if (ufshcd_mcq_sq_start(hba, hwq))
+ err = -ETIMEDOUT;
+
+unlock:
+ mutex_unlock(&hwq->sq_mutex);
+ return err;
+}
+
+/**
+ * ufshcd_mcq_nullify_sqe - Nullify the submission queue entry.
+ * Write the sqe's Command Type to 0xF. The host controller will not
+ * fetch any sqe with Command Type = 0xF.
+ *
+ * @utrd - UTP Transfer Request Descriptor to be nullified.
+ */
+static void ufshcd_mcq_nullify_sqe(struct utp_transfer_req_desc *utrd)
+{
+ u32 dword_0;
+
+ dword_0 = le32_to_cpu(utrd->header.dword_0);
+ dword_0 &= ~UPIU_COMMAND_TYPE_MASK;
+ dword_0 |= FIELD_PREP(UPIU_COMMAND_TYPE_MASK, 0xF);
+ utrd->header.dword_0 = cpu_to_le32(dword_0);
+}
+
+/**
+ * ufshcd_mcq_sqe_search - Search for the command in the submission queue
+ * If the command is in the submission queue and not issued to the device yet,
+ * nullify the sqe so the host controller will skip fetching the sqe.
+ *
+ * @hba - per adapter instance.
+ * @hwq - Hardware Queue to be searched.
+ * @task_tag - The command's task tag.
+ *
+ * Returns true if the SQE containing the command is present in the SQ
+ * (not fetched by the controller); returns false if the SQE is not in the SQ.
+ */
+static bool ufshcd_mcq_sqe_search(struct ufs_hba *hba,
+ struct ufs_hw_queue *hwq, int task_tag)
+{
+ struct ufshcd_lrb *lrbp = &hba->lrb[task_tag];
+ struct utp_transfer_req_desc *utrd;
+ u32 mask = hwq->max_entries - 1;
+ __le64 cmd_desc_base_addr;
+ bool ret = false;
+ u64 addr, match;
+ u32 sq_head_slot;
+
+ if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC)
+ return true;
+
+ mutex_lock(&hwq->sq_mutex);
+
+ ufshcd_mcq_sq_stop(hba, hwq);
+ sq_head_slot = ufshcd_mcq_get_sq_head_slot(hwq);
+ if (sq_head_slot == hwq->sq_tail_slot)
+ goto out;
+
+ cmd_desc_base_addr = lrbp->utr_descriptor_ptr->command_desc_base_addr;
+ addr = le64_to_cpu(cmd_desc_base_addr) & CQE_UCD_BA;
+
+ while (sq_head_slot != hwq->sq_tail_slot) {
+ utrd = hwq->sqe_base_addr +
+ sq_head_slot * sizeof(struct utp_transfer_req_desc);
+ match = le64_to_cpu(utrd->command_desc_base_addr) & CQE_UCD_BA;
+ if (addr == match) {
+ ufshcd_mcq_nullify_sqe(utrd);
+ ret = true;
+ goto out;
+ }
+ sq_head_slot = (sq_head_slot + 1) & mask;
+ }
+
+out:
+ ufshcd_mcq_sq_start(hba, hwq);
+ mutex_unlock(&hwq->sq_mutex);
+ return ret;
+}
+
+/**
+ * ufshcd_mcq_abort - Abort the command in MCQ.
+ * @cmd - The command to be aborted.
+ *
+ * Returns SUCCESS or FAILED error codes
+ */
+int ufshcd_mcq_abort(struct scsi_cmnd *cmd)
+{
+ struct Scsi_Host *host = cmd->device->host;
+ struct ufs_hba *hba = shost_priv(host);
+ int tag = scsi_cmd_to_rq(cmd)->tag;
+ struct ufshcd_lrb *lrbp = &hba->lrb[tag];
+ struct ufs_hw_queue *hwq;
+ int err = FAILED;
+
+ if (!ufshcd_cmd_inflight(lrbp->cmd)) {
+ dev_err(hba->dev,
+ "%s: skip abort. cmd at tag %d already completed.\n",
+ __func__, tag);
+ goto out;
+ }
+
+ /* Skip task abort in case previous aborts failed and report failure */
+ if (lrbp->req_abort_skip) {
+ dev_err(hba->dev, "%s: skip abort. tag %d failed earlier\n",
+ __func__, tag);
+ goto out;
+ }
+
+ hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd));
+
+ if (ufshcd_mcq_sqe_search(hba, hwq, tag)) {
+ /*
+ * Failure. The command should not be "stuck" in SQ for
+ * a long time which resulted in command being aborted.
+ */
+ dev_err(hba->dev, "%s: cmd found in sq. hwq=%d, tag=%d\n",
+ __func__, hwq->id, tag);
+ goto out;
+ }
+
+ /*
+ * The command is not in the submission queue, and it is not
+ * in the completion queue either. Query the device to see if
+ * the command is being processed in the device.
+ */
+ if (ufshcd_try_to_abort_task(hba, tag)) {
+ dev_err(hba->dev, "%s: device abort failed %d\n", __func__, err);
+ lrbp->req_abort_skip = true;
+ goto out;
+ }
+
+ err = SUCCESS;
+ if (ufshcd_cmd_inflight(lrbp->cmd))
+ ufshcd_release_scsi_cmd(hba, lrbp);
+
+out:
+ return err;
+}
diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c
index 883f0e44b54e..6c72075750dd 100644
--- a/drivers/ufs/core/ufs-sysfs.c
+++ b/drivers/ufs/core/ufs-sysfs.c
@@ -168,7 +168,7 @@ static ssize_t auto_hibern8_show(struct device *dev,
}
pm_runtime_get_sync(hba->dev);
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
ahit = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER);
ufshcd_release(hba);
pm_runtime_put_sync(hba->dev);
@@ -298,6 +298,37 @@ out:
return res < 0 ? res : count;
}
+static ssize_t wb_flush_threshold_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%u\n", hba->vps->wb_flush_threshold);
+}
+
+static ssize_t wb_flush_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+ unsigned int wb_flush_threshold;
+
+ if (kstrtouint(buf, 0, &wb_flush_threshold))
+ return -EINVAL;
+
+ /* The range of values for wb_flush_threshold is (0,10] */
+ if (wb_flush_threshold > UFS_WB_BUF_REMAIN_PERCENT(100) ||
+ wb_flush_threshold == 0) {
+ dev_err(dev, "The value of wb_flush_threshold is invalid!\n");
+ return -EINVAL;
+ }
+
+ hba->vps->wb_flush_threshold = wb_flush_threshold;
+
+ return count;
+}
+
static DEVICE_ATTR_RW(rpm_lvl);
static DEVICE_ATTR_RO(rpm_target_dev_state);
static DEVICE_ATTR_RO(rpm_target_link_state);
@@ -307,6 +338,7 @@ static DEVICE_ATTR_RO(spm_target_link_state);
static DEVICE_ATTR_RW(auto_hibern8);
static DEVICE_ATTR_RW(wb_on);
static DEVICE_ATTR_RW(enable_wb_buf_flush);
+static DEVICE_ATTR_RW(wb_flush_threshold);
static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
&dev_attr_rpm_lvl.attr,
@@ -318,6 +350,7 @@ static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
&dev_attr_auto_hibern8.attr,
&dev_attr_wb_on.attr,
&dev_attr_enable_wb_buf_flush.attr,
+ &dev_attr_wb_flush_threshold.attr,
NULL
};
diff --git a/drivers/ufs/core/ufshcd-crypto.c b/drivers/ufs/core/ufshcd-crypto.c
index 198360fe5e8e..f2c4422cab86 100644
--- a/drivers/ufs/core/ufshcd-crypto.c
+++ b/drivers/ufs/core/ufshcd-crypto.c
@@ -24,7 +24,7 @@ static int ufshcd_program_key(struct ufs_hba *hba,
u32 slot_offset = hba->crypto_cfg_register + slot * sizeof(*cfg);
int err = 0;
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
if (hba->vops && hba->vops->program_key) {
err = hba->vops->program_key(hba, cfg, slot);
diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h
index d53b93c21a0c..9566a95aeed9 100644
--- a/drivers/ufs/core/ufshcd-priv.h
+++ b/drivers/ufs/core/ufshcd-priv.h
@@ -71,22 +71,24 @@ void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds);
void ufshcd_mcq_select_mcq_mode(struct ufs_hba *hba);
u32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i);
void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i);
-unsigned long ufshcd_mcq_poll_cqe_nolock(struct ufs_hba *hba,
- struct ufs_hw_queue *hwq);
struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba,
struct request *req);
unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba,
struct ufs_hw_queue *hwq);
+void ufshcd_mcq_compl_all_cqes_lock(struct ufs_hba *hba,
+ struct ufs_hw_queue *hwq);
+bool ufshcd_cmd_inflight(struct scsi_cmnd *cmd);
+int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag);
+int ufshcd_mcq_abort(struct scsi_cmnd *cmd);
+int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag);
+void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
+ struct ufshcd_lrb *lrbp);
-#define UFSHCD_MCQ_IO_QUEUE_OFFSET 1
#define SD_ASCII_STD true
#define SD_RAW false
int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
u8 **buf, bool ascii);
-int ufshcd_hold(struct ufs_hba *hba, bool async);
-void ufshcd_release(struct ufs_hba *hba);
-
int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
@@ -366,10 +368,11 @@ static inline bool ufs_is_valid_unit_desc_lun(struct ufs_dev_info *dev_info, u8
static inline void ufshcd_inc_sq_tail(struct ufs_hw_queue *q)
__must_hold(&q->sq_lock)
{
- u32 mask = q->max_entries - 1;
u32 val;
- q->sq_tail_slot = (q->sq_tail_slot + 1) & mask;
+ q->sq_tail_slot++;
+ if (q->sq_tail_slot == q->max_entries)
+ q->sq_tail_slot = 0;
val = q->sq_tail_slot * sizeof(struct utp_transfer_req_desc);
writel(val, q->mcq_sq_tail);
}
@@ -404,4 +407,12 @@ static inline struct cq_entry *ufshcd_mcq_cur_cqe(struct ufs_hw_queue *q)
return cqe + q->cq_head_slot;
}
+
+static inline u32 ufshcd_mcq_get_sq_head_slot(struct ufs_hw_queue *q)
+{
+ u32 val = readl(q->mcq_sq_head);
+
+ return val / sizeof(struct utp_transfer_req_desc);
+}
+
#endif /* _UFSHCD_PRIV_H_ */
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index e7e79f515e14..983fae84d9e8 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -98,7 +98,7 @@
/* Polling time to wait for fDeviceInit */
#define FDEVICEINIT_COMPL_TIMEOUT 1500 /* millisecs */
-/* UFSHC 4.0 compliant HC support this mode, refer param_set_mcq_mode() */
+/* UFSHC 4.0 compliant HC support this mode. */
static bool use_mcq_mode = true;
static bool is_mcq_supported(struct ufs_hba *hba)
@@ -106,23 +106,7 @@ static bool is_mcq_supported(struct ufs_hba *hba)
return hba->mcq_sup && use_mcq_mode;
}
-static int param_set_mcq_mode(const char *val, const struct kernel_param *kp)
-{
- int ret;
-
- ret = param_set_bool(val, kp);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static const struct kernel_param_ops mcq_mode_ops = {
- .set = param_set_mcq_mode,
- .get = param_get_bool,
-};
-
-module_param_cb(use_mcq_mode, &mcq_mode_ops, &use_mcq_mode, 0644);
+module_param(use_mcq_mode, bool, 0644);
MODULE_PARM_DESC(use_mcq_mode, "Control MCQ mode for controllers starting from UFSHCI 4.0. 1 - enable MCQ, 0 - disable MCQ. MCQ is enabled by default");
#define ufshcd_toggle_vreg(_dev, _vreg, _on) \
@@ -173,7 +157,6 @@ EXPORT_SYMBOL_GPL(ufshcd_dump_regs);
enum {
UFSHCD_MAX_CHANNEL = 0,
UFSHCD_MAX_ID = 1,
- UFSHCD_NUM_RESERVED = 1,
UFSHCD_CMD_PER_LUN = 32 - UFSHCD_NUM_RESERVED,
UFSHCD_CAN_QUEUE = 32 - UFSHCD_NUM_RESERVED,
};
@@ -301,7 +284,6 @@ static int ufshcd_setup_hba_vreg(struct ufs_hba *hba, bool on);
static int ufshcd_setup_vreg(struct ufs_hba *hba, bool on);
static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
struct ufs_vreg *vreg);
-static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag);
static void ufshcd_wb_toggle_buf_flush_during_h8(struct ufs_hba *hba,
bool enable);
static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba);
@@ -1205,7 +1187,7 @@ static int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba,
bool timeout = false, do_last_check = false;
ktime_t start;
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
/*
* Wait for all the outstanding tasks/transfer requests.
@@ -1326,7 +1308,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us)
}
/* let's not get into low power until clock scaling is completed */
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
out:
return ret;
@@ -1656,7 +1638,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev,
goto out;
ufshcd_rpm_get_sync(hba);
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
hba->clk_scaling.is_enabled = value;
@@ -1739,7 +1721,7 @@ static void ufshcd_ungate_work(struct work_struct *work)
spin_lock_irqsave(hba->host->host_lock, flags);
if (hba->clk_gating.state == CLKS_ON) {
spin_unlock_irqrestore(hba->host->host_lock, flags);
- goto unblock_reqs;
+ return;
}
spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -1762,25 +1744,21 @@ static void ufshcd_ungate_work(struct work_struct *work)
}
hba->clk_gating.is_suspended = false;
}
-unblock_reqs:
- ufshcd_scsi_unblock_requests(hba);
}
/**
* ufshcd_hold - Enable clocks that were gated earlier due to ufshcd_release.
* Also, exit from hibern8 mode and set the link as active.
* @hba: per adapter instance
- * @async: This indicates whether caller should ungate clocks asynchronously.
*/
-int ufshcd_hold(struct ufs_hba *hba, bool async)
+void ufshcd_hold(struct ufs_hba *hba)
{
- int rc = 0;
bool flush_result;
unsigned long flags;
if (!ufshcd_is_clkgating_allowed(hba) ||
!hba->clk_gating.is_initialized)
- goto out;
+ return;
spin_lock_irqsave(hba->host->host_lock, flags);
hba->clk_gating.active_reqs++;
@@ -1797,15 +1775,10 @@ start:
*/
if (ufshcd_can_hibern8_during_gating(hba) &&
ufshcd_is_link_hibern8(hba)) {
- if (async) {
- rc = -EAGAIN;
- hba->clk_gating.active_reqs--;
- break;
- }
spin_unlock_irqrestore(hba->host->host_lock, flags);
flush_result = flush_work(&hba->clk_gating.ungate_work);
if (hba->clk_gating.is_suspended && !flush_result)
- goto out;
+ return;
spin_lock_irqsave(hba->host->host_lock, flags);
goto start;
}
@@ -1827,21 +1800,14 @@ start:
hba->clk_gating.state = REQ_CLKS_ON;
trace_ufshcd_clk_gating(dev_name(hba->dev),
hba->clk_gating.state);
- if (queue_work(hba->clk_gating.clk_gating_workq,
- &hba->clk_gating.ungate_work))
- ufshcd_scsi_block_requests(hba);
+ queue_work(hba->clk_gating.clk_gating_workq,
+ &hba->clk_gating.ungate_work);
/*
* fall through to check if we should wait for this
* work to be done or not.
*/
fallthrough;
case REQ_CLKS_ON:
- if (async) {
- rc = -EAGAIN;
- hba->clk_gating.active_reqs--;
- break;
- }
-
spin_unlock_irqrestore(hba->host->host_lock, flags);
flush_work(&hba->clk_gating.ungate_work);
/* Make sure state is CLKS_ON before returning */
@@ -1853,8 +1819,6 @@ start:
break;
}
spin_unlock_irqrestore(hba->host->host_lock, flags);
-out:
- return rc;
}
EXPORT_SYMBOL_GPL(ufshcd_hold);
@@ -2086,7 +2050,7 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
ufshcd_remove_clk_gating_sysfs(hba);
/* Ungate the clock if necessary. */
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
hba->clk_gating.is_initialized = false;
ufshcd_release(hba);
@@ -2336,18 +2300,20 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba)
/* Read crypto capabilities */
err = ufshcd_hba_init_crypto_capabilities(hba);
- if (err)
+ if (err) {
dev_err(hba->dev, "crypto setup failed\n");
+ return err;
+ }
hba->mcq_sup = FIELD_GET(MASK_MCQ_SUPPORT, hba->capabilities);
if (!hba->mcq_sup)
- return err;
+ return 0;
hba->mcq_capabilities = ufshcd_readl(hba, REG_MCQCAP);
hba->ext_iid_sup = FIELD_GET(MASK_EXT_IID_SUPPORT,
hba->mcq_capabilities);
- return err;
+ return 0;
}
/**
@@ -2482,7 +2448,7 @@ int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
if (hba->quirks & UFSHCD_QUIRK_BROKEN_UIC_CMD)
return 0;
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
mutex_lock(&hba->uic_cmd_mutex);
ufshcd_add_delay_before_dme_cmd(hba);
@@ -2533,7 +2499,7 @@ static void ufshcd_sgl_to_prdt(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, int
* 11b to indicate Dword granularity. A value of '3'
* indicates 4 bytes, '7' indicates 8 bytes, etc."
*/
- WARN_ONCE(len > 256 * 1024, "len = %#x\n", len);
+ WARN_ONCE(len > SZ_256K, "len = %#x\n", len);
prd->size = cpu_to_le32(len - 1);
prd->addr = cpu_to_le64(sg->dma_address);
prd->reserved = 0;
@@ -2885,12 +2851,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
WARN_ONCE(tag < 0 || tag >= hba->nutrs, "Invalid tag %d\n", tag);
- /*
- * Allows the UFS error handler to wait for prior ufshcd_queuecommand()
- * calls.
- */
- rcu_read_lock();
-
switch (hba->ufshcd_state) {
case UFSHCD_STATE_OPERATIONAL:
break;
@@ -2936,16 +2896,9 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
hba->req_abort_count = 0;
- err = ufshcd_hold(hba, true);
- if (err) {
- err = SCSI_MLQUEUE_HOST_BUSY;
- goto out;
- }
- WARN_ON(ufshcd_is_clkgating_allowed(hba) &&
- (hba->clk_gating.state != CLKS_ON));
+ ufshcd_hold(hba);
lrbp = &hba->lrb[tag];
- WARN_ON(lrbp->cmd);
lrbp->cmd = cmd;
lrbp->task_tag = tag;
lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
@@ -2961,7 +2914,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
err = ufshcd_map_sg(hba, lrbp);
if (err) {
- lrbp->cmd = NULL;
ufshcd_release(hba);
goto out;
}
@@ -2972,8 +2924,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
ufshcd_send_command(hba, tag, hwq);
out:
- rcu_read_unlock();
-
if (ufs_trigger_eh()) {
unsigned long flags;
@@ -2999,13 +2949,50 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba,
}
/*
- * Clear all the requests from the controller for which a bit has been set in
- * @mask and wait until the controller confirms that these requests have been
- * cleared.
+ * Check with the block layer if the command is inflight
+ * @cmd: command to check.
+ *
+ * Returns true if command is inflight; false if not.
+ */
+bool ufshcd_cmd_inflight(struct scsi_cmnd *cmd)
+{
+ struct request *rq;
+
+ if (!cmd)
+ return false;
+
+ rq = scsi_cmd_to_rq(cmd);
+ if (!blk_mq_request_started(rq))
+ return false;
+
+ return true;
+}
+
+/*
+ * Clear the pending command in the controller and wait until
+ * the controller confirms that the command has been cleared.
+ * @hba: per adapter instance
+ * @task_tag: The tag number of the command to be cleared.
*/
-static int ufshcd_clear_cmds(struct ufs_hba *hba, u32 mask)
+static int ufshcd_clear_cmd(struct ufs_hba *hba, u32 task_tag)
{
+ u32 mask = 1U << task_tag;
unsigned long flags;
+ int err;
+
+ if (is_mcq_enabled(hba)) {
+ /*
+ * MCQ mode. Clean up the MCQ resources similar to
+ * what the ufshcd_utrl_clear() does for SDB mode.
+ */
+ err = ufshcd_mcq_sq_cleanup(hba, task_tag);
+ if (err) {
+ dev_err(hba->dev, "%s: failed tag=%d. err=%d\n",
+ __func__, task_tag, err);
+ return err;
+ }
+ return 0;
+ }
/* clear outstanding transaction before retry */
spin_lock_irqsave(hba->host->host_lock, flags);
@@ -3099,14 +3086,23 @@ retry:
* not trigger any race conditions.
*/
hba->dev_cmd.complete = NULL;
- err = ufshcd_get_tr_ocs(lrbp, hba->dev_cmd.cqe);
+ err = ufshcd_get_tr_ocs(lrbp, NULL);
if (!err)
err = ufshcd_dev_cmd_completion(hba, lrbp);
} else {
err = -ETIMEDOUT;
dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
__func__, lrbp->task_tag);
- if (ufshcd_clear_cmds(hba, 1U << lrbp->task_tag) == 0) {
+
+ /* MCQ mode */
+ if (is_mcq_enabled(hba)) {
+ err = ufshcd_clear_cmd(hba, lrbp->task_tag);
+ hba->dev_cmd.complete = NULL;
+ return err;
+ }
+
+ /* SDB mode */
+ if (ufshcd_clear_cmd(hba, lrbp->task_tag) == 0) {
/* successfully cleared the command, retry if needed */
err = -EAGAIN;
/*
@@ -3180,13 +3176,12 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
down_read(&hba->clk_scaling_lock);
lrbp = &hba->lrb[tag];
- WARN_ON(lrbp->cmd);
+ lrbp->cmd = NULL;
err = ufshcd_compose_dev_cmd(hba, lrbp, cmd_type, tag);
if (unlikely(err))
goto out;
hba->dev_cmd.complete = &wait;
- hba->dev_cmd.cqe = NULL;
ufshcd_add_query_upiu_trace(hba, UFS_QUERY_SEND, lrbp->ucd_req_ptr);
@@ -3267,7 +3262,7 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
BUG_ON(!hba);
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
mutex_lock(&hba->dev_cmd.lock);
ufshcd_init_query(hba, &request, &response, opcode, idn, index,
selector);
@@ -3341,7 +3336,7 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
return -EINVAL;
}
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
mutex_lock(&hba->dev_cmd.lock);
ufshcd_init_query(hba, &request, &response, opcode, idn, index,
@@ -3437,7 +3432,7 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
return -EINVAL;
}
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
mutex_lock(&hba->dev_cmd.lock);
ufshcd_init_query(hba, &request, &response, opcode, idn, index,
@@ -3779,7 +3774,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
/*
* Allocate memory for UTP Transfer descriptors
- * UFSHCI requires 1024 byte alignment of UTRD
+ * UFSHCI requires 1KB alignment of UTRD
*/
utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
hba->utrdl_base_addr = dmam_alloc_coherent(hba->dev,
@@ -3787,7 +3782,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
&hba->utrdl_dma_addr,
GFP_KERNEL);
if (!hba->utrdl_base_addr ||
- WARN_ON(hba->utrdl_dma_addr & (1024 - 1))) {
+ WARN_ON(hba->utrdl_dma_addr & (SZ_1K - 1))) {
dev_err(hba->dev,
"Transfer Descriptor Memory allocation failed\n");
goto out;
@@ -3803,7 +3798,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
goto skip_utmrdl;
/*
* Allocate memory for UTP Task Management descriptors
- * UFSHCI requires 1024 byte alignment of UTMRD
+ * UFSHCI requires 1KB alignment of UTMRD
*/
utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
hba->utmrdl_base_addr = dmam_alloc_coherent(hba->dev,
@@ -3811,7 +3806,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
&hba->utmrdl_dma_addr,
GFP_KERNEL);
if (!hba->utmrdl_base_addr ||
- WARN_ON(hba->utmrdl_dma_addr & (1024 - 1))) {
+ WARN_ON(hba->utmrdl_dma_addr & (SZ_1K - 1))) {
dev_err(hba->dev,
"Task Management Descriptor Memory allocation failed\n");
goto out;
@@ -3868,10 +3863,8 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)
/* Configure UTRD with command descriptor base address */
cmd_desc_element_addr =
(cmd_desc_dma_addr + (cmd_desc_size * i));
- utrdlp[i].command_desc_base_addr_lo =
- cpu_to_le32(lower_32_bits(cmd_desc_element_addr));
- utrdlp[i].command_desc_base_addr_hi =
- cpu_to_le32(upper_32_bits(cmd_desc_element_addr));
+ utrdlp[i].command_desc_base_addr =
+ cpu_to_le64(cmd_desc_element_addr);
/* Response upiu and prdt offset should be in double words */
if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) {
@@ -4255,7 +4248,7 @@ int ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode)
uic_cmd.command = UIC_CMD_DME_SET;
uic_cmd.argument1 = UIC_ARG_MIB(PA_PWRMODE);
uic_cmd.argument3 = mode;
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
ufshcd_release(hba);
@@ -4362,7 +4355,7 @@ void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit)
if (update &&
!pm_runtime_suspended(&hba->ufs_device_wlun->sdev_gendev)) {
ufshcd_rpm_get_sync(hba);
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
ufshcd_auto_hibern8_enable(hba);
ufshcd_release(hba);
ufshcd_rpm_put_sync(hba);
@@ -4955,7 +4948,7 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba)
int err = 0;
int retries;
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
mutex_lock(&hba->dev_cmd.lock);
for (retries = NOP_OUT_RETRIES; retries > 0; retries--) {
err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_NOP,
@@ -5148,7 +5141,7 @@ static int ufshcd_slave_configure(struct scsi_device *sdev)
blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1);
if (hba->quirks & UFSHCD_QUIRK_4KB_DMA_ALIGNMENT)
- blk_queue_update_dma_alignment(q, 4096 - 1);
+ blk_queue_update_dma_alignment(q, SZ_4K - 1);
/*
* Block runtime-pm until all consumers are added.
* Refer ufshcd_setup_links().
@@ -5416,13 +5409,12 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
}
/* Release the resources allocated for processing a SCSI command. */
-static void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
- struct ufshcd_lrb *lrbp)
+void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
+ struct ufshcd_lrb *lrbp)
{
struct scsi_cmnd *cmd = lrbp->cmd;
scsi_dma_unmap(cmd);
- lrbp->cmd = NULL; /* Mark the command as completed. */
ufshcd_release(hba);
ufshcd_clk_scaling_update_busy(hba);
}
@@ -5438,6 +5430,7 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag,
{
struct ufshcd_lrb *lrbp;
struct scsi_cmnd *cmd;
+ enum utp_ocs ocs;
lrbp = &hba->lrb[task_tag];
lrbp->compl_time_stamp = ktime_get();
@@ -5453,8 +5446,11 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag,
} else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE ||
lrbp->command_type == UTP_CMD_TYPE_UFS_STORAGE) {
if (hba->dev_cmd.complete) {
- hba->dev_cmd.cqe = cqe;
- ufshcd_add_command_trace(hba, task_tag, UFS_DEV_COMP);
+ if (cqe) {
+ ocs = le32_to_cpu(cqe->status) & MASK_OCS;
+ lrbp->utr_descriptor_ptr->header.dword_2 =
+ cpu_to_le32(ocs);
+ }
complete(hba->dev_cmd.complete);
ufshcd_clk_scaling_update_busy(hba);
}
@@ -5507,7 +5503,7 @@ static int ufshcd_poll(struct Scsi_Host *shost, unsigned int queue_num)
struct ufs_hw_queue *hwq;
if (is_mcq_enabled(hba)) {
- hwq = &hba->uhq[queue_num + UFSHCD_MCQ_IO_QUEUE_OFFSET];
+ hwq = &hba->uhq[queue_num];
return ufshcd_mcq_poll_cqe_lock(hba, hwq);
}
@@ -5532,6 +5528,57 @@ static int ufshcd_poll(struct Scsi_Host *shost, unsigned int queue_num)
}
/**
+ * ufshcd_mcq_compl_pending_transfer - MCQ mode function. It is
+ * invoked from the error handler context or ufshcd_host_reset_and_restore()
+ * to complete the pending transfers and free the resources associated with
+ * the scsi command.
+ *
+ * @hba: per adapter instance
+ * @force_compl: This flag is set to true when invoked
+ * from ufshcd_host_reset_and_restore() in which case it requires special
+ * handling because the host controller has been reset by ufshcd_hba_stop().
+ */
+static void ufshcd_mcq_compl_pending_transfer(struct ufs_hba *hba,
+ bool force_compl)
+{
+ struct ufs_hw_queue *hwq;
+ struct ufshcd_lrb *lrbp;
+ struct scsi_cmnd *cmd;
+ unsigned long flags;
+ u32 hwq_num, utag;
+ int tag;
+
+ for (tag = 0; tag < hba->nutrs; tag++) {
+ lrbp = &hba->lrb[tag];
+ cmd = lrbp->cmd;
+ if (!ufshcd_cmd_inflight(cmd) ||
+ test_bit(SCMD_STATE_COMPLETE, &cmd->state))
+ continue;
+
+ utag = blk_mq_unique_tag(scsi_cmd_to_rq(cmd));
+ hwq_num = blk_mq_unique_tag_to_hwq(utag);
+ hwq = &hba->uhq[hwq_num];
+
+ if (force_compl) {
+ ufshcd_mcq_compl_all_cqes_lock(hba, hwq);
+ /*
+ * For those cmds of which the cqes are not present
+ * in the cq, complete them explicitly.
+ */
+ if (cmd && !test_bit(SCMD_STATE_COMPLETE, &cmd->state)) {
+ spin_lock_irqsave(&hwq->cq_lock, flags);
+ set_host_byte(cmd, DID_REQUEUE);
+ ufshcd_release_scsi_cmd(hba, lrbp);
+ scsi_done(cmd);
+ spin_unlock_irqrestore(&hwq->cq_lock, flags);
+ }
+ } else {
+ ufshcd_mcq_poll_cqe_lock(hba, hwq);
+ }
+ }
+}
+
+/**
* ufshcd_transfer_req_compl - handle SCSI and query command completion
* @hba: per adapter instance
*
@@ -6095,9 +6142,13 @@ out:
}
/* Complete requests that have door-bell cleared */
-static void ufshcd_complete_requests(struct ufs_hba *hba)
+static void ufshcd_complete_requests(struct ufs_hba *hba, bool force_compl)
{
- ufshcd_transfer_req_compl(hba);
+ if (is_mcq_enabled(hba))
+ ufshcd_mcq_compl_pending_transfer(hba, force_compl);
+ else
+ ufshcd_transfer_req_compl(hba);
+
ufshcd_tmc_handler(hba);
}
@@ -6241,22 +6292,22 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
ufshcd_setup_vreg(hba, true);
ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq);
ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2);
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
if (!ufshcd_is_clkgating_allowed(hba))
ufshcd_setup_clocks(hba, true);
ufshcd_release(hba);
pm_op = hba->is_sys_suspended ? UFS_SYSTEM_PM : UFS_RUNTIME_PM;
ufshcd_vops_resume(hba, pm_op);
} else {
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
if (ufshcd_is_clkscaling_supported(hba) &&
hba->clk_scaling.is_enabled)
ufshcd_suspend_clkscaling(hba);
ufshcd_clk_scaling_allow(hba, false);
}
ufshcd_scsi_block_requests(hba);
- /* Drain ufshcd_queuecommand() */
- synchronize_rcu();
+ /* Wait for ongoing ufshcd_queuecommand() calls to finish. */
+ blk_mq_wait_quiesce_done(&hba->host->tag_set);
cancel_work_sync(&hba->eeh_work);
}
@@ -6338,18 +6389,36 @@ static bool ufshcd_abort_all(struct ufs_hba *hba)
bool needs_reset = false;
int tag, ret;
- /* Clear pending transfer requests */
- for_each_set_bit(tag, &hba->outstanding_reqs, hba->nutrs) {
- ret = ufshcd_try_to_abort_task(hba, tag);
- dev_err(hba->dev, "Aborting tag %d / CDB %#02x %s\n", tag,
- hba->lrb[tag].cmd ? hba->lrb[tag].cmd->cmnd[0] : -1,
- ret ? "failed" : "succeeded");
- if (ret) {
- needs_reset = true;
- goto out;
+ if (is_mcq_enabled(hba)) {
+ struct ufshcd_lrb *lrbp;
+ int tag;
+
+ for (tag = 0; tag < hba->nutrs; tag++) {
+ lrbp = &hba->lrb[tag];
+ if (!ufshcd_cmd_inflight(lrbp->cmd))
+ continue;
+ ret = ufshcd_try_to_abort_task(hba, tag);
+ dev_err(hba->dev, "Aborting tag %d / CDB %#02x %s\n", tag,
+ hba->lrb[tag].cmd ? hba->lrb[tag].cmd->cmnd[0] : -1,
+ ret ? "failed" : "succeeded");
+ if (ret) {
+ needs_reset = true;
+ goto out;
+ }
+ }
+ } else {
+ /* Clear pending transfer requests */
+ for_each_set_bit(tag, &hba->outstanding_reqs, hba->nutrs) {
+ ret = ufshcd_try_to_abort_task(hba, tag);
+ dev_err(hba->dev, "Aborting tag %d / CDB %#02x %s\n", tag,
+ hba->lrb[tag].cmd ? hba->lrb[tag].cmd->cmnd[0] : -1,
+ ret ? "failed" : "succeeded");
+ if (ret) {
+ needs_reset = true;
+ goto out;
+ }
}
}
-
/* Clear pending task management requests */
for_each_set_bit(tag, &hba->outstanding_tasks, hba->nutmrs) {
if (ufshcd_clear_tm_cmd(hba, tag)) {
@@ -6360,7 +6429,7 @@ static bool ufshcd_abort_all(struct ufs_hba *hba)
out:
/* Complete the requests that are cleared by s/w */
- ufshcd_complete_requests(hba);
+ ufshcd_complete_requests(hba, false);
return needs_reset;
}
@@ -6400,7 +6469,7 @@ static void ufshcd_err_handler(struct work_struct *work)
spin_unlock_irqrestore(hba->host->host_lock, flags);
ufshcd_err_handling_prepare(hba);
/* Complete requests that have door-bell cleared by h/w */
- ufshcd_complete_requests(hba);
+ ufshcd_complete_requests(hba, false);
spin_lock_irqsave(hba->host->host_lock, flags);
again:
needs_restore = false;
@@ -6771,7 +6840,7 @@ static irqreturn_t ufshcd_handle_mcq_cq_events(struct ufs_hba *hba)
ufshcd_mcq_write_cqis(hba, events, i);
if (events & UFSHCD_MCQ_CQIS_TAIL_ENT_PUSH_STS)
- ufshcd_mcq_poll_cqe_nolock(hba, hwq);
+ ufshcd_mcq_poll_cqe_lock(hba, hwq);
}
return IRQ_HANDLED;
@@ -6901,7 +6970,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
return PTR_ERR(req);
req->end_io_data = &wait;
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
spin_lock_irqsave(host->host_lock, flags);
@@ -7037,7 +7106,6 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
down_read(&hba->clk_scaling_lock);
lrbp = &hba->lrb[tag];
- WARN_ON(lrbp->cmd);
lrbp->cmd = NULL;
lrbp->task_tag = tag;
lrbp->lun = 0;
@@ -7138,7 +7206,7 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
cmd_type = DEV_CMD_TYPE_NOP;
fallthrough;
case UPIU_TRANSACTION_QUERY_REQ:
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
mutex_lock(&hba->dev_cmd.lock);
err = ufshcd_issue_devman_upiu_cmd(hba, req_upiu, rsp_upiu,
desc_buff, buff_len,
@@ -7204,12 +7272,11 @@ int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *r
u16 ehs_len;
/* Protects use of hba->reserved_slot. */
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
mutex_lock(&hba->dev_cmd.lock);
down_read(&hba->clk_scaling_lock);
lrbp = &hba->lrb[tag];
- WARN_ON(lrbp->cmd);
lrbp->cmd = NULL;
lrbp->task_tag = tag;
lrbp->lun = UFS_UPIU_RPMB_WLUN;
@@ -7281,7 +7348,9 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
unsigned long flags, pending_reqs = 0, not_cleared = 0;
struct Scsi_Host *host;
struct ufs_hba *hba;
- u32 pos;
+ struct ufs_hw_queue *hwq;
+ struct ufshcd_lrb *lrbp;
+ u32 pos, not_cleared_mask = 0;
int err;
u8 resp = 0xF, lun;
@@ -7296,6 +7365,20 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
goto out;
}
+ if (is_mcq_enabled(hba)) {
+ for (pos = 0; pos < hba->nutrs; pos++) {
+ lrbp = &hba->lrb[pos];
+ if (ufshcd_cmd_inflight(lrbp->cmd) &&
+ lrbp->lun == lun) {
+ ufshcd_clear_cmd(hba, pos);
+ hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(lrbp->cmd));
+ ufshcd_mcq_poll_cqe_lock(hba, hwq);
+ }
+ }
+ err = 0;
+ goto out;
+ }
+
/* clear the commands that were pending for corresponding LUN */
spin_lock_irqsave(&hba->outstanding_lock, flags);
for_each_set_bit(pos, &hba->outstanding_reqs, hba->nutrs)
@@ -7304,17 +7387,20 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
hba->outstanding_reqs &= ~pending_reqs;
spin_unlock_irqrestore(&hba->outstanding_lock, flags);
- if (ufshcd_clear_cmds(hba, pending_reqs) < 0) {
- spin_lock_irqsave(&hba->outstanding_lock, flags);
- not_cleared = pending_reqs &
- ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
- hba->outstanding_reqs |= not_cleared;
- spin_unlock_irqrestore(&hba->outstanding_lock, flags);
+ for_each_set_bit(pos, &pending_reqs, hba->nutrs) {
+ if (ufshcd_clear_cmd(hba, pos) < 0) {
+ spin_lock_irqsave(&hba->outstanding_lock, flags);
+ not_cleared = 1U << pos &
+ ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+ hba->outstanding_reqs |= not_cleared;
+ not_cleared_mask |= not_cleared;
+ spin_unlock_irqrestore(&hba->outstanding_lock, flags);
- dev_err(hba->dev, "%s: failed to clear requests %#lx\n",
- __func__, not_cleared);
+ dev_err(hba->dev, "%s: failed to clear request %d\n",
+ __func__, pos);
+ }
}
- __ufshcd_transfer_req_compl(hba, pending_reqs & ~not_cleared);
+ __ufshcd_transfer_req_compl(hba, pending_reqs & ~not_cleared_mask);
out:
hba->req_abort_count = 0;
@@ -7352,7 +7438,7 @@ static void ufshcd_set_req_abort_skip(struct ufs_hba *hba, unsigned long bitmap)
*
* Returns zero on success, non-zero on failure
*/
-static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
+int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
{
struct ufshcd_lrb *lrbp = &hba->lrb[tag];
int err = 0;
@@ -7375,6 +7461,20 @@ static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
*/
dev_err(hba->dev, "%s: cmd at tag %d not pending in the device.\n",
__func__, tag);
+ if (is_mcq_enabled(hba)) {
+ /* MCQ mode */
+ if (ufshcd_cmd_inflight(lrbp->cmd)) {
+ /* sleep for max. 200us same delay as in SDB mode */
+ usleep_range(100, 200);
+ continue;
+ }
+ /* command completed already */
+ dev_err(hba->dev, "%s: cmd at tag=%d is cleared.\n",
+ __func__, tag);
+ goto out;
+ }
+
+ /* Single Doorbell Mode */
reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
if (reg & (1 << tag)) {
/* sleep for max. 200us to stabilize */
@@ -7411,7 +7511,7 @@ static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
goto out;
}
- err = ufshcd_clear_cmds(hba, 1U << tag);
+ err = ufshcd_clear_cmd(hba, tag);
if (err)
dev_err(hba->dev, "%s: Failed clearing cmd at tag %d, err %d\n",
__func__, tag, err);
@@ -7439,14 +7539,17 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
WARN_ONCE(tag < 0, "Invalid tag %d\n", tag);
- ufshcd_hold(hba, false);
- reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
- /* If command is already aborted/completed, return FAILED. */
- if (!(test_bit(tag, &hba->outstanding_reqs))) {
- dev_err(hba->dev,
- "%s: cmd at tag %d already completed, outstanding=0x%lx, doorbell=0x%x\n",
- __func__, tag, hba->outstanding_reqs, reg);
- goto release;
+ ufshcd_hold(hba);
+
+ if (!is_mcq_enabled(hba)) {
+ reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+ if (!test_bit(tag, &hba->outstanding_reqs)) {
+ /* If command is already aborted/completed, return FAILED. */
+ dev_err(hba->dev,
+ "%s: cmd at tag %d already completed, outstanding=0x%lx, doorbell=0x%x\n",
+ __func__, tag, hba->outstanding_reqs, reg);
+ goto release;
+ }
}
/* Print Transfer Request of aborted task */
@@ -7471,7 +7574,8 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
}
hba->req_abort_count++;
- if (!(reg & (1 << tag))) {
+ if (!is_mcq_enabled(hba) && !(reg & (1 << tag))) {
+ /* only execute this code in single doorbell mode */
dev_err(hba->dev,
"%s: cmd was completed, but without a notifying intr, tag = %d",
__func__, tag);
@@ -7497,6 +7601,12 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
goto release;
}
+ if (is_mcq_enabled(hba)) {
+ /* MCQ mode. Branch off to handle abort for mcq mode */
+ err = ufshcd_mcq_abort(cmd);
+ goto release;
+ }
+
/* Skip task abort in case previous aborts failed and report failure */
if (lrbp->req_abort_skip) {
dev_err(hba->dev, "%s: skipping abort\n", __func__);
@@ -7552,7 +7662,7 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
ufshpb_toggle_state(hba, HPB_PRESENT, HPB_RESET);
ufshcd_hba_stop(hba);
hba->silence_err_logs = true;
- ufshcd_complete_requests(hba);
+ ufshcd_complete_requests(hba, true);
hba->silence_err_logs = false;
/* scale up clocks to max frequency before full reinitialization */
@@ -8502,11 +8612,15 @@ err:
static void ufshcd_config_mcq(struct ufs_hba *hba)
{
int ret;
+ u32 intrs;
ret = ufshcd_mcq_vops_config_esi(hba);
dev_info(hba->dev, "ESI %sconfigured\n", ret ? "is not " : "");
- ufshcd_enable_intr(hba, UFSHCD_ENABLE_MCQ_INTRS);
+ intrs = UFSHCD_ENABLE_MCQ_INTRS;
+ if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_INTR)
+ intrs &= ~MCQ_CQ_EVENT_STATUS;
+ ufshcd_enable_intr(hba, intrs);
ufshcd_mcq_make_queues_operational(hba);
ufshcd_mcq_config_mac(hba, hba->nutrs);
@@ -8774,7 +8888,7 @@ static const struct scsi_host_template ufshcd_driver_template = {
.cmd_per_lun = UFSHCD_CMD_PER_LUN,
.can_queue = UFSHCD_CAN_QUEUE,
.max_segment_size = PRDT_DATA_BYTE_COUNT_MAX,
- .max_sectors = (1 << 20) / SECTOR_SIZE, /* 1 MiB */
+ .max_sectors = SZ_1M / SECTOR_SIZE,
.max_host_blocked = 1,
.track_queue_depth = 1,
.skip_settle_delay = 1,
@@ -9184,7 +9298,8 @@ static int ufshcd_execute_start_stop(struct scsi_device *sdev,
};
return scsi_execute_cmd(sdev, cdb, REQ_OP_DRV_IN, /*buffer=*/NULL,
- /*bufflen=*/0, /*timeout=*/HZ, /*retries=*/0, &args);
+ /*bufflen=*/0, /*timeout=*/10 * HZ, /*retries=*/0,
+ &args);
}
/**
@@ -9430,7 +9545,7 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
* If we can't transition into any of the low power modes
* just gate the clocks.
*/
- ufshcd_hold(hba, false);
+ ufshcd_hold(hba);
hba->clk_gating.is_suspended = true;
if (ufshcd_is_clkscaling_supported(hba))
@@ -9775,28 +9890,6 @@ out:
}
#endif
-static void ufshcd_wl_shutdown(struct device *dev)
-{
- struct scsi_device *sdev = to_scsi_device(dev);
- struct ufs_hba *hba;
-
- hba = shost_priv(sdev->host);
-
- down(&hba->host_sem);
- hba->shutting_down = true;
- up(&hba->host_sem);
-
- /* Turn on everything while shutting down */
- ufshcd_rpm_get_sync(hba);
- scsi_device_quiesce(sdev);
- shost_for_each_device(sdev, hba->host) {
- if (sdev == hba->ufs_device_wlun)
- continue;
- scsi_device_quiesce(sdev);
- }
- __ufshcd_wl_suspend(hba, UFS_SHUTDOWN_PM);
-}
-
/**
* ufshcd_suspend - helper function for suspend operations
* @hba: per adapter instance
@@ -9981,25 +10074,34 @@ int ufshcd_runtime_resume(struct device *dev)
EXPORT_SYMBOL(ufshcd_runtime_resume);
#endif /* CONFIG_PM */
-/**
- * ufshcd_shutdown - shutdown routine
- * @hba: per adapter instance
- *
- * This function would turn off both UFS device and UFS hba
- * regulators. It would also disable clocks.
- *
- * Returns 0 always to allow force shutdown even in case of errors.
- */
-int ufshcd_shutdown(struct ufs_hba *hba)
+static void ufshcd_wl_shutdown(struct device *dev)
{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ufs_hba *hba = shost_priv(sdev->host);
+
+ down(&hba->host_sem);
+ hba->shutting_down = true;
+ up(&hba->host_sem);
+
+ /* Turn on everything while shutting down */
+ ufshcd_rpm_get_sync(hba);
+ scsi_device_quiesce(sdev);
+ shost_for_each_device(sdev, hba->host) {
+ if (sdev == hba->ufs_device_wlun)
+ continue;
+ scsi_device_quiesce(sdev);
+ }
+ __ufshcd_wl_suspend(hba, UFS_SHUTDOWN_PM);
+
+ /*
+ * Next, turn off the UFS controller and the UFS regulators. Disable
+ * clocks.
+ */
if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba))
ufshcd_suspend(hba);
hba->is_powered = false;
- /* allow force shutdown even in case of errors */
- return 0;
}
-EXPORT_SYMBOL(ufshcd_shutdown);
/**
* ufshcd_remove - de-allocate SCSI host and host memory space
@@ -10226,6 +10328,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
host->max_channel = UFSHCD_MAX_CHANNEL;
host->unique_id = host->host_no;
host->max_cmd_len = UFS_CDB_SIZE;
+ host->queuecommand_may_block = !!(hba->caps & UFSHCD_CAP_CLK_GATING);
hba->max_pwr_info.is_valid = false;
diff --git a/drivers/ufs/core/ufshpb.c b/drivers/ufs/core/ufshpb.c
index a46a7666c891..255f8b38d0c2 100644
--- a/drivers/ufs/core/ufshpb.c
+++ b/drivers/ufs/core/ufshpb.c
@@ -30,7 +30,7 @@ static struct kmem_cache *ufshpb_mctx_cache;
static mempool_t *ufshpb_mctx_pool;
static mempool_t *ufshpb_page_pool;
/* A cache size of 2MB can cache ppn in the 1GB range. */
-static unsigned int ufshpb_host_map_kbytes = 2048;
+static unsigned int ufshpb_host_map_kbytes = SZ_2K;
static int tot_active_srgn_pages;
static struct workqueue_struct *ufshpb_wq;
@@ -2461,7 +2461,7 @@ static void ufshpb_hpb_lu_prepared(struct ufs_hba *hba)
init_success = !ufshpb_check_hpb_reset_query(hba);
- pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * 1024) / PAGE_SIZE;
+ pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * SZ_1K) / PAGE_SIZE;
if (pool_size > tot_active_srgn_pages) {
mempool_resize(ufshpb_mctx_pool, tot_active_srgn_pages);
mempool_resize(ufshpb_page_pool, tot_active_srgn_pages);
@@ -2527,7 +2527,7 @@ static int ufshpb_init_mem_wq(struct ufs_hba *hba)
return -ENOMEM;
}
- pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * 1024) / PAGE_SIZE;
+ pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * SZ_1K) / PAGE_SIZE;
dev_info(hba->dev, "%s:%d ufshpb_host_map_kbytes %u pool_size %u\n",
__func__, __LINE__, ufshpb_host_map_kbytes, pool_size);
diff --git a/drivers/ufs/core/ufshpb.h b/drivers/ufs/core/ufshpb.h
index 0d6e6004d783..b428bbdd2799 100644
--- a/drivers/ufs/core/ufshpb.h
+++ b/drivers/ufs/core/ufshpb.h
@@ -25,7 +25,7 @@
/* hpb map & entries macro */
#define HPB_RGN_SIZE_UNIT 512
-#define HPB_ENTRY_BLOCK_SIZE 4096
+#define HPB_ENTRY_BLOCK_SIZE SZ_4K
#define HPB_ENTRY_SIZE 0x8
#define PINNED_NOT_SET U32_MAX
diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig
index 8793e3433580..16624ba08050 100644
--- a/drivers/ufs/host/Kconfig
+++ b/drivers/ufs/host/Kconfig
@@ -59,7 +59,7 @@ config SCSI_UFS_QCOM
depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM
depends on GENERIC_MSI_IRQ
depends on RESET_CONTROLLER
- select QCOM_SCM if SCSI_UFS_CRYPTO
+ select QCOM_INLINE_CRYPTO_ENGINE if SCSI_UFS_CRYPTO
help
This selects the QCOM specific additions to UFSHCD platform driver.
UFS host on QCOM needs some vendor specific configuration before
diff --git a/drivers/ufs/host/Makefile b/drivers/ufs/host/Makefile
index d7c5bf7fa512..4573aead02eb 100644
--- a/drivers/ufs/host/Makefile
+++ b/drivers/ufs/host/Makefile
@@ -3,9 +3,7 @@
obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o
obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o
obj-$(CONFIG_SCSI_UFS_CDNS_PLATFORM) += cdns-pltfrm.o
-obj-$(CONFIG_SCSI_UFS_QCOM) += ufs_qcom.o
-ufs_qcom-y += ufs-qcom.o
-ufs_qcom-$(CONFIG_SCSI_UFS_CRYPTO) += ufs-qcom-ice.o
+obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
obj-$(CONFIG_SCSI_UFS_EXYNOS) += ufs-exynos.o
obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
diff --git a/drivers/ufs/host/cdns-pltfrm.c b/drivers/ufs/host/cdns-pltfrm.c
index e05c0ae64eea..26761425a76c 100644
--- a/drivers/ufs/host/cdns-pltfrm.c
+++ b/drivers/ufs/host/cdns-pltfrm.c
@@ -328,7 +328,6 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
static struct platform_driver cdns_ufs_pltfrm_driver = {
.probe = cdns_ufs_pltfrm_probe,
.remove = cdns_ufs_pltfrm_remove,
- .shutdown = ufshcd_pltfrm_shutdown,
.driver = {
.name = "cdns-ufshcd",
.pm = &cdns_ufs_dev_pm_ops,
diff --git a/drivers/ufs/host/tc-dwc-g210-pci.c b/drivers/ufs/host/tc-dwc-g210-pci.c
index 92b8ad4b58fe..f96fe5855841 100644
--- a/drivers/ufs/host/tc-dwc-g210-pci.c
+++ b/drivers/ufs/host/tc-dwc-g210-pci.c
@@ -33,15 +33,6 @@ static struct ufs_hba_variant_ops tc_dwc_g210_pci_hba_vops = {
};
/**
- * tc_dwc_g210_pci_shutdown - main function to put the controller in reset state
- * @pdev: pointer to PCI device handle
- */
-static void tc_dwc_g210_pci_shutdown(struct pci_dev *pdev)
-{
- ufshcd_shutdown((struct ufs_hba *)pci_get_drvdata(pdev));
-}
-
-/**
* tc_dwc_g210_pci_remove - de-allocate PCI/SCSI host and host memory space
* data structure memory
* @pdev: pointer to PCI handle
@@ -137,7 +128,6 @@ static struct pci_driver tc_dwc_g210_pci_driver = {
.id_table = tc_dwc_g210_pci_tbl,
.probe = tc_dwc_g210_pci_probe,
.remove = tc_dwc_g210_pci_remove,
- .shutdown = tc_dwc_g210_pci_shutdown,
.driver = {
.pm = &tc_dwc_g210_pci_pm_ops
},
diff --git a/drivers/ufs/host/tc-dwc-g210-pltfrm.c b/drivers/ufs/host/tc-dwc-g210-pltfrm.c
index f15a84d0c176..4d5389dd9585 100644
--- a/drivers/ufs/host/tc-dwc-g210-pltfrm.c
+++ b/drivers/ufs/host/tc-dwc-g210-pltfrm.c
@@ -92,7 +92,6 @@ static const struct dev_pm_ops tc_dwc_g210_pltfm_pm_ops = {
static struct platform_driver tc_dwc_g210_pltfm_driver = {
.probe = tc_dwc_g210_pltfm_probe,
.remove = tc_dwc_g210_pltfm_remove,
- .shutdown = ufshcd_pltfrm_shutdown,
.driver = {
.name = "tc-dwc-g210-pltfm",
.pm = &tc_dwc_g210_pltfm_pm_ops,
diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
index 0bf5390739e1..3396e0388512 100644
--- a/drivers/ufs/host/ufs-exynos.c
+++ b/drivers/ufs/host/ufs-exynos.c
@@ -1306,7 +1306,7 @@ static int exynos_ufs_hce_enable_notify(struct ufs_hba *hba,
* (ufshcd_async_scan()). Note: this callback may also be called
* from other functions than ufshcd_init().
*/
- hba->host->max_segment_size = 4096;
+ hba->host->max_segment_size = SZ_4K;
if (ufs->drv_data->pre_hce_enable) {
ret = ufs->drv_data->pre_hce_enable(ufs);
@@ -1757,7 +1757,6 @@ static const struct dev_pm_ops exynos_ufs_pm_ops = {
static struct platform_driver exynos_ufs_pltform = {
.probe = exynos_ufs_probe,
.remove = exynos_ufs_remove,
- .shutdown = ufshcd_pltfrm_shutdown,
.driver = {
.name = "exynos-ufshc",
.pm = &exynos_ufs_pm_ops,
diff --git a/drivers/ufs/host/ufs-hisi.c b/drivers/ufs/host/ufs-hisi.c
index 4c423eba8aa9..5b3060cd0ab8 100644
--- a/drivers/ufs/host/ufs-hisi.c
+++ b/drivers/ufs/host/ufs-hisi.c
@@ -335,29 +335,29 @@ static void ufs_hisi_pwr_change_pre_change(struct ufs_hba *hba)
/* PA_TxSkip */
ufshcd_dme_set(hba, UIC_ARG_MIB(0x155c), 0x0);
/*PA_PWRModeUserData0 = 8191, default is 0*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b0), 8191);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b0), SZ_8K - 1);
/*PA_PWRModeUserData1 = 65535, default is 0*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b1), 65535);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b1), SZ_64K - 1);
/*PA_PWRModeUserData2 = 32767, default is 0*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b2), 32767);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b2), SZ_32K - 1);
/*DME_FC0ProtectionTimeOutVal = 8191, default is 0*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(0xd041), 8191);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(0xd041), SZ_8K - 1);
/*DME_TC0ReplayTimeOutVal = 65535, default is 0*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(0xd042), 65535);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(0xd042), SZ_64K - 1);
/*DME_AFC0ReqTimeOutVal = 32767, default is 0*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(0xd043), 32767);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(0xd043), SZ_32K - 1);
/*PA_PWRModeUserData3 = 8191, default is 0*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b3), 8191);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b3), SZ_8K - 1);
/*PA_PWRModeUserData4 = 65535, default is 0*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b4), 65535);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b4), SZ_64K - 1);
/*PA_PWRModeUserData5 = 32767, default is 0*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b5), 32767);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b5), SZ_32K - 1);
/*DME_FC1ProtectionTimeOutVal = 8191, default is 0*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(0xd044), 8191);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(0xd044), SZ_8K - 1);
/*DME_TC1ReplayTimeOutVal = 65535, default is 0*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(0xd045), 65535);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(0xd045), SZ_64K - 1);
/*DME_AFC1ReqTimeOutVal = 32767, default is 0*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(0xd046), 32767);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(0xd046), SZ_32K - 1);
}
static int ufs_hisi_pwr_change_notify(struct ufs_hba *hba,
@@ -593,7 +593,6 @@ static const struct dev_pm_ops ufs_hisi_pm_ops = {
static struct platform_driver ufs_hisi_pltform = {
.probe = ufs_hisi_probe,
.remove = ufs_hisi_remove,
- .shutdown = ufshcd_pltfrm_shutdown,
.driver = {
.name = "ufshcd-hisi",
.pm = &ufs_hisi_pm_ops,
diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c
index 73e217260390..e68b05976f9e 100644
--- a/drivers/ufs/host/ufs-mediatek.c
+++ b/drivers/ufs/host/ufs-mediatek.c
@@ -410,9 +410,6 @@ static int ufs_mtk_wait_link_state(struct ufs_hba *hba, u32 state,
usleep_range(100, 200);
} while (ktime_before(time_checked, timeout));
- if (val == state)
- return 0;
-
return -ETIMEDOUT;
}
@@ -901,6 +898,8 @@ static int ufs_mtk_init(struct ufs_hba *hba)
hba->caps |= UFSHCD_CAP_CLK_SCALING;
hba->quirks |= UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL;
+ hba->quirks |= UFSHCD_QUIRK_MCQ_BROKEN_INTR;
+ hba->quirks |= UFSHCD_QUIRK_MCQ_BROKEN_RTC;
hba->vps->wb_flush_threshold = UFS_WB_BUF_REMAIN_PERCENT(80);
if (host->caps & UFS_MTK_CAP_DISABLE_AH8)
@@ -1650,7 +1649,6 @@ static const struct dev_pm_ops ufs_mtk_pm_ops = {
static struct platform_driver ufs_mtk_pltform = {
.probe = ufs_mtk_probe,
.remove = ufs_mtk_remove,
- .shutdown = ufshcd_pltfrm_shutdown,
.driver = {
.name = "ufshcd-mtk",
.pm = &ufs_mtk_pm_ops,
diff --git a/drivers/ufs/host/ufs-qcom-ice.c b/drivers/ufs/host/ufs-qcom-ice.c
deleted file mode 100644
index 453978877ae9..000000000000
--- a/drivers/ufs/host/ufs-qcom-ice.c
+++ /dev/null
@@ -1,244 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Qualcomm ICE (Inline Crypto Engine) support.
- *
- * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
- * Copyright 2019 Google LLC
- */
-
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/firmware/qcom/qcom_scm.h>
-
-#include "ufs-qcom.h"
-
-#define AES_256_XTS_KEY_SIZE 64
-
-/* QCOM ICE registers */
-
-#define QCOM_ICE_REG_CONTROL 0x0000
-#define QCOM_ICE_REG_RESET 0x0004
-#define QCOM_ICE_REG_VERSION 0x0008
-#define QCOM_ICE_REG_FUSE_SETTING 0x0010
-#define QCOM_ICE_REG_PARAMETERS_1 0x0014
-#define QCOM_ICE_REG_PARAMETERS_2 0x0018
-#define QCOM_ICE_REG_PARAMETERS_3 0x001C
-#define QCOM_ICE_REG_PARAMETERS_4 0x0020
-#define QCOM_ICE_REG_PARAMETERS_5 0x0024
-
-/* QCOM ICE v3.X only */
-#define QCOM_ICE_GENERAL_ERR_STTS 0x0040
-#define QCOM_ICE_INVALID_CCFG_ERR_STTS 0x0030
-#define QCOM_ICE_GENERAL_ERR_MASK 0x0044
-
-/* QCOM ICE v2.X only */
-#define QCOM_ICE_REG_NON_SEC_IRQ_STTS 0x0040
-#define QCOM_ICE_REG_NON_SEC_IRQ_MASK 0x0044
-
-#define QCOM_ICE_REG_NON_SEC_IRQ_CLR 0x0048
-#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME1 0x0050
-#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME2 0x0054
-#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME1 0x0058
-#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME2 0x005C
-#define QCOM_ICE_REG_STREAM1_BIST_ERROR_VEC 0x0060
-#define QCOM_ICE_REG_STREAM2_BIST_ERROR_VEC 0x0064
-#define QCOM_ICE_REG_STREAM1_BIST_FINISH_VEC 0x0068
-#define QCOM_ICE_REG_STREAM2_BIST_FINISH_VEC 0x006C
-#define QCOM_ICE_REG_BIST_STATUS 0x0070
-#define QCOM_ICE_REG_BYPASS_STATUS 0x0074
-#define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000
-#define QCOM_ICE_REG_ENDIAN_SWAP 0x1004
-#define QCOM_ICE_REG_TEST_BUS_CONTROL 0x1010
-#define QCOM_ICE_REG_TEST_BUS_REG 0x1014
-
-/* BIST ("built-in self-test"?) status flags */
-#define QCOM_ICE_BIST_STATUS_MASK 0xF0000000
-
-#define QCOM_ICE_FUSE_SETTING_MASK 0x1
-#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK 0x2
-#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK 0x4
-
-#define qcom_ice_writel(host, val, reg) \
- writel((val), (host)->ice_mmio + (reg))
-#define qcom_ice_readl(host, reg) \
- readl((host)->ice_mmio + (reg))
-
-static bool qcom_ice_supported(struct ufs_qcom_host *host)
-{
- struct device *dev = host->hba->dev;
- u32 regval = qcom_ice_readl(host, QCOM_ICE_REG_VERSION);
- int major = regval >> 24;
- int minor = (regval >> 16) & 0xFF;
- int step = regval & 0xFFFF;
-
- /* For now this driver only supports ICE version 3. */
- if (major != 3) {
- dev_warn(dev, "Unsupported ICE version: v%d.%d.%d\n",
- major, minor, step);
- return false;
- }
-
- dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n",
- major, minor, step);
-
- /* If fuses are blown, ICE might not work in the standard way. */
- regval = qcom_ice_readl(host, QCOM_ICE_REG_FUSE_SETTING);
- if (regval & (QCOM_ICE_FUSE_SETTING_MASK |
- QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK |
- QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK)) {
- dev_warn(dev, "Fuses are blown; ICE is unusable!\n");
- return false;
- }
- return true;
-}
-
-int ufs_qcom_ice_init(struct ufs_qcom_host *host)
-{
- struct ufs_hba *hba = host->hba;
- struct device *dev = hba->dev;
- struct platform_device *pdev = to_platform_device(dev);
- struct resource *res;
- int err;
-
- if (!(ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES) &
- MASK_CRYPTO_SUPPORT))
- return 0;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice");
- if (!res) {
- dev_warn(dev, "ICE registers not found\n");
- goto disable;
- }
-
- if (!qcom_scm_ice_available()) {
- dev_warn(dev, "ICE SCM interface not found\n");
- goto disable;
- }
-
- host->ice_mmio = devm_ioremap_resource(dev, res);
- if (IS_ERR(host->ice_mmio)) {
- err = PTR_ERR(host->ice_mmio);
- return err;
- }
-
- if (!qcom_ice_supported(host))
- goto disable;
-
- return 0;
-
-disable:
- dev_warn(dev, "Disabling inline encryption support\n");
- hba->caps &= ~UFSHCD_CAP_CRYPTO;
- return 0;
-}
-
-static void qcom_ice_low_power_mode_enable(struct ufs_qcom_host *host)
-{
- u32 regval;
-
- regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL);
- /*
- * Enable low power mode sequence
- * [0]-0, [1]-0, [2]-0, [3]-E, [4]-0, [5]-0, [6]-0, [7]-0
- */
- regval |= 0x7000;
- qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL);
-}
-
-static void qcom_ice_optimization_enable(struct ufs_qcom_host *host)
-{
- u32 regval;
-
- /* ICE Optimizations Enable Sequence */
- regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL);
- regval |= 0xD807100;
- /* ICE HPG requires delay before writing */
- udelay(5);
- qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL);
- udelay(5);
-}
-
-int ufs_qcom_ice_enable(struct ufs_qcom_host *host)
-{
- if (!(host->hba->caps & UFSHCD_CAP_CRYPTO))
- return 0;
- qcom_ice_low_power_mode_enable(host);
- qcom_ice_optimization_enable(host);
- return ufs_qcom_ice_resume(host);
-}
-
-/* Poll until all BIST bits are reset */
-static int qcom_ice_wait_bist_status(struct ufs_qcom_host *host)
-{
- int count;
- u32 reg;
-
- for (count = 0; count < 100; count++) {
- reg = qcom_ice_readl(host, QCOM_ICE_REG_BIST_STATUS);
- if (!(reg & QCOM_ICE_BIST_STATUS_MASK))
- break;
- udelay(50);
- }
- if (reg)
- return -ETIMEDOUT;
- return 0;
-}
-
-int ufs_qcom_ice_resume(struct ufs_qcom_host *host)
-{
- int err;
-
- if (!(host->hba->caps & UFSHCD_CAP_CRYPTO))
- return 0;
-
- err = qcom_ice_wait_bist_status(host);
- if (err) {
- dev_err(host->hba->dev, "BIST status error (%d)\n", err);
- return err;
- }
- return 0;
-}
-
-/*
- * Program a key into a QC ICE keyslot, or evict a keyslot. QC ICE requires
- * vendor-specific SCM calls for this; it doesn't support the standard way.
- */
-int ufs_qcom_ice_program_key(struct ufs_hba *hba,
- const union ufs_crypto_cfg_entry *cfg, int slot)
-{
- union ufs_crypto_cap_entry cap;
- union {
- u8 bytes[AES_256_XTS_KEY_SIZE];
- u32 words[AES_256_XTS_KEY_SIZE / sizeof(u32)];
- } key;
- int i;
- int err;
-
- if (!(cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE))
- return qcom_scm_ice_invalidate_key(slot);
-
- /* Only AES-256-XTS has been tested so far. */
- cap = hba->crypto_cap_array[cfg->crypto_cap_idx];
- if (cap.algorithm_id != UFS_CRYPTO_ALG_AES_XTS ||
- cap.key_size != UFS_CRYPTO_KEY_SIZE_256) {
- dev_err_ratelimited(hba->dev,
- "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n",
- cap.algorithm_id, cap.key_size);
- return -EINVAL;
- }
-
- memcpy(key.bytes, cfg->crypto_key, AES_256_XTS_KEY_SIZE);
-
- /*
- * The SCM call byte-swaps the 32-bit words of the key. So we have to
- * do the same, in order for the final key be correct.
- */
- for (i = 0; i < ARRAY_SIZE(key.words); i++)
- __cpu_to_be32s(&key.words[i]);
-
- err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE,
- QCOM_SCM_ICE_CIPHER_AES_256_XTS,
- cfg->data_unit_size);
- memzero_explicit(&key, sizeof(key));
- return err;
-}
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 82d02e7f3b4f..8d6fd4c3324f 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -15,6 +15,8 @@
#include <linux/reset-controller.h>
#include <linux/devfreq.h>
+#include <soc/qcom/ice.h>
+
#include <ufs/ufshcd.h>
#include "ufshcd-pltfrm.h"
#include <ufs/unipro.h>
@@ -55,6 +57,100 @@ static struct ufs_qcom_host *rcdev_to_ufs_host(struct reset_controller_dev *rcd)
return container_of(rcd, struct ufs_qcom_host, rcdev);
}
+#ifdef CONFIG_SCSI_UFS_CRYPTO
+
+static inline void ufs_qcom_ice_enable(struct ufs_qcom_host *host)
+{
+ if (host->hba->caps & UFSHCD_CAP_CRYPTO)
+ qcom_ice_enable(host->ice);
+}
+
+static int ufs_qcom_ice_init(struct ufs_qcom_host *host)
+{
+ struct ufs_hba *hba = host->hba;
+ struct device *dev = hba->dev;
+ struct qcom_ice *ice;
+
+ ice = of_qcom_ice_get(dev);
+ if (ice == ERR_PTR(-EOPNOTSUPP)) {
+ dev_warn(dev, "Disabling inline encryption support\n");
+ ice = NULL;
+ }
+
+ if (IS_ERR_OR_NULL(ice))
+ return PTR_ERR_OR_ZERO(ice);
+
+ host->ice = ice;
+ hba->caps |= UFSHCD_CAP_CRYPTO;
+
+ return 0;
+}
+
+static inline int ufs_qcom_ice_resume(struct ufs_qcom_host *host)
+{
+ if (host->hba->caps & UFSHCD_CAP_CRYPTO)
+ return qcom_ice_resume(host->ice);
+
+ return 0;
+}
+
+static inline int ufs_qcom_ice_suspend(struct ufs_qcom_host *host)
+{
+ if (host->hba->caps & UFSHCD_CAP_CRYPTO)
+ return qcom_ice_suspend(host->ice);
+
+ return 0;
+}
+
+static int ufs_qcom_ice_program_key(struct ufs_hba *hba,
+ const union ufs_crypto_cfg_entry *cfg,
+ int slot)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ union ufs_crypto_cap_entry cap;
+ bool config_enable =
+ cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE;
+
+ /* Only AES-256-XTS has been tested so far. */
+ cap = hba->crypto_cap_array[cfg->crypto_cap_idx];
+ if (cap.algorithm_id != UFS_CRYPTO_ALG_AES_XTS ||
+ cap.key_size != UFS_CRYPTO_KEY_SIZE_256)
+ return -EINVAL;
+
+ if (config_enable)
+ return qcom_ice_program_key(host->ice,
+ QCOM_ICE_CRYPTO_ALG_AES_XTS,
+ QCOM_ICE_CRYPTO_KEY_SIZE_256,
+ cfg->crypto_key,
+ cfg->data_unit_size, slot);
+ else
+ return qcom_ice_evict_key(host->ice, slot);
+}
+
+#else
+
+#define ufs_qcom_ice_program_key NULL
+
+static inline void ufs_qcom_ice_enable(struct ufs_qcom_host *host)
+{
+}
+
+static int ufs_qcom_ice_init(struct ufs_qcom_host *host)
+{
+ return 0;
+}
+
+static inline int ufs_qcom_ice_resume(struct ufs_qcom_host *host)
+{
+ return 0;
+}
+
+static inline int ufs_qcom_ice_suspend(struct ufs_qcom_host *host)
+{
+ return 0;
+}
+#endif
+
static int ufs_qcom_host_clk_get(struct device *dev,
const char *name, struct clk **clk_out, bool optional)
{
@@ -607,7 +703,7 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
ufs_qcom_disable_lane_clks(host);
}
- return 0;
+ return ufs_qcom_ice_suspend(host);
}
static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
@@ -853,7 +949,6 @@ static void ufs_qcom_set_caps(struct ufs_hba *hba)
hba->caps |= UFSHCD_CAP_CLK_SCALING | UFSHCD_CAP_WB_WITH_CLK_SCALING;
hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
hba->caps |= UFSHCD_CAP_WB_EN;
- hba->caps |= UFSHCD_CAP_CRYPTO;
hba->caps |= UFSHCD_CAP_AGGR_POWER_COLLAPSE;
hba->caps |= UFSHCD_CAP_RPM_AUTOSUSPEND;
@@ -1556,7 +1651,7 @@ static irqreturn_t ufs_qcom_mcq_esi_handler(int irq, void *__hba)
struct ufs_hw_queue *hwq = &hba->uhq[id];
ufshcd_mcq_write_cqis(hba, 0x1, id);
- ufshcd_mcq_poll_cqe_nolock(hba, hwq);
+ ufshcd_mcq_poll_cqe_lock(hba, hwq);
return IRQ_HANDLED;
}
@@ -1723,7 +1818,6 @@ static const struct dev_pm_ops ufs_qcom_pm_ops = {
static struct platform_driver ufs_qcom_pltform = {
.probe = ufs_qcom_probe,
.remove = ufs_qcom_remove,
- .shutdown = ufshcd_pltfrm_shutdown,
.driver = {
.name = "ufshcd-qcom",
.pm = &ufs_qcom_pm_ops,
diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
index 39e774254fb2..6289ad5a42d0 100644
--- a/drivers/ufs/host/ufs-qcom.h
+++ b/drivers/ufs/host/ufs-qcom.h
@@ -7,6 +7,7 @@
#include <linux/reset-controller.h>
#include <linux/reset.h>
+#include <soc/qcom/ice.h>
#include <ufs/ufshcd.h>
#define MAX_UFS_QCOM_HOSTS 1
@@ -205,12 +206,13 @@ struct ufs_qcom_host {
struct clk *tx_l1_sync_clk;
bool is_lane_clks_enabled;
+#ifdef CONFIG_SCSI_UFS_CRYPTO
+ struct qcom_ice *ice;
+#endif
+
void __iomem *dev_ref_clk_ctrl_mmio;
bool is_dev_ref_clk_enabled;
struct ufs_hw_version hw_ver;
-#ifdef CONFIG_SCSI_UFS_CRYPTO
- void __iomem *ice_mmio;
-#endif
u32 dev_ref_clk_en_mask;
@@ -248,28 +250,4 @@ static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host)
return host->caps & UFS_QCOM_CAP_QUNIPRO;
}
-/* ufs-qcom-ice.c */
-
-#ifdef CONFIG_SCSI_UFS_CRYPTO
-int ufs_qcom_ice_init(struct ufs_qcom_host *host);
-int ufs_qcom_ice_enable(struct ufs_qcom_host *host);
-int ufs_qcom_ice_resume(struct ufs_qcom_host *host);
-int ufs_qcom_ice_program_key(struct ufs_hba *hba,
- const union ufs_crypto_cfg_entry *cfg, int slot);
-#else
-static inline int ufs_qcom_ice_init(struct ufs_qcom_host *host)
-{
- return 0;
-}
-static inline int ufs_qcom_ice_enable(struct ufs_qcom_host *host)
-{
- return 0;
-}
-static inline int ufs_qcom_ice_resume(struct ufs_qcom_host *host)
-{
- return 0;
-}
-#define ufs_qcom_ice_program_key NULL
-#endif /* !CONFIG_SCSI_UFS_CRYPTO */
-
#endif /* UFS_QCOM_H_ */
diff --git a/drivers/ufs/host/ufs-sprd.c b/drivers/ufs/host/ufs-sprd.c
index 051f3f40d92c..2bad75dd6d58 100644
--- a/drivers/ufs/host/ufs-sprd.c
+++ b/drivers/ufs/host/ufs-sprd.c
@@ -444,7 +444,6 @@ static const struct dev_pm_ops ufs_sprd_pm_ops = {
static struct platform_driver ufs_sprd_pltform = {
.probe = ufs_sprd_probe,
.remove = ufs_sprd_remove,
- .shutdown = ufshcd_pltfrm_shutdown,
.driver = {
.name = "ufshcd-sprd",
.pm = &ufs_sprd_pm_ops,
diff --git a/drivers/ufs/host/ufshcd-pci.c b/drivers/ufs/host/ufshcd-pci.c
index 9c911787f84c..cf3987773051 100644
--- a/drivers/ufs/host/ufshcd-pci.c
+++ b/drivers/ufs/host/ufshcd-pci.c
@@ -505,15 +505,6 @@ static int ufshcd_pci_restore(struct device *dev)
#endif
/**
- * ufshcd_pci_shutdown - main function to put the controller in reset state
- * @pdev: pointer to PCI device handle
- */
-static void ufshcd_pci_shutdown(struct pci_dev *pdev)
-{
- ufshcd_shutdown((struct ufs_hba *)pci_get_drvdata(pdev));
-}
-
-/**
* ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
* data structure memory
* @pdev: pointer to PCI handle
@@ -608,6 +599,7 @@ static const struct pci_device_id ufshcd_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x54FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops },
{ PCI_VDEVICE(INTEL, 0x7E47), (kernel_ulong_t)&ufs_intel_mtl_hba_vops },
{ PCI_VDEVICE(INTEL, 0xA847), (kernel_ulong_t)&ufs_intel_mtl_hba_vops },
+ { PCI_VDEVICE(INTEL, 0x7747), (kernel_ulong_t)&ufs_intel_mtl_hba_vops },
{ } /* terminate list */
};
@@ -618,7 +610,6 @@ static struct pci_driver ufshcd_pci_driver = {
.id_table = ufshcd_pci_tbl,
.probe = ufshcd_pci_probe,
.remove = ufshcd_pci_remove,
- .shutdown = ufshcd_pci_shutdown,
.driver = {
.pm = &ufshcd_pci_pm_ops
},
diff --git a/drivers/ufs/host/ufshcd-pltfrm.c b/drivers/ufs/host/ufshcd-pltfrm.c
index 5739ff007828..0b7430033047 100644
--- a/drivers/ufs/host/ufshcd-pltfrm.c
+++ b/drivers/ufs/host/ufshcd-pltfrm.c
@@ -190,12 +190,6 @@ out:
return err;
}
-void ufshcd_pltfrm_shutdown(struct platform_device *pdev)
-{
- ufshcd_shutdown((struct ufs_hba *)platform_get_drvdata(pdev));
-}
-EXPORT_SYMBOL_GPL(ufshcd_pltfrm_shutdown);
-
static void ufshcd_init_lanes_per_dir(struct ufs_hba *hba)
{
struct device *dev = hba->dev;
diff --git a/drivers/ufs/host/ufshcd-pltfrm.h b/drivers/ufs/host/ufshcd-pltfrm.h
index 2e4ba2bfbcad..2df108f4ac13 100644
--- a/drivers/ufs/host/ufshcd-pltfrm.h
+++ b/drivers/ufs/host/ufshcd-pltfrm.h
@@ -31,7 +31,6 @@ int ufshcd_get_pwr_dev_param(const struct ufs_dev_params *dev_param,
void ufshcd_init_pwr_dev_param(struct ufs_dev_params *dev_param);
int ufshcd_pltfrm_init(struct platform_device *pdev,
const struct ufs_hba_variant_ops *vops);
-void ufshcd_pltfrm_shutdown(struct platform_device *pdev);
int ufshcd_populate_vreg(struct device *dev, const char *name,
struct ufs_vreg **out_vreg);
diff --git a/drivers/uio/uio_dfl.c b/drivers/uio/uio_dfl.c
index 69e93f3e7faf..6d99e5a06ae8 100644
--- a/drivers/uio/uio_dfl.c
+++ b/drivers/uio/uio_dfl.c
@@ -46,11 +46,13 @@ static int uio_dfl_probe(struct dfl_device *ddev)
#define FME_FEATURE_ID_ETH_GROUP 0x10
#define FME_FEATURE_ID_HSSI_SUBSYS 0x15
+#define FME_FEATURE_ID_VENDOR_SPECIFIC 0x23
#define PORT_FEATURE_ID_IOPLL_USRCLK 0x14
static const struct dfl_device_id uio_dfl_ids[] = {
{ FME_ID, FME_FEATURE_ID_ETH_GROUP },
{ FME_ID, FME_FEATURE_ID_HSSI_SUBSYS },
+ { FME_ID, FME_FEATURE_ID_VENDOR_SPECIFIC },
{ PORT_ID, PORT_FEATURE_ID_IOPLL_USRCLK },
{ }
};
diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
index 6db5cb1b2dbb..bb9d5d7ffefc 100644
--- a/drivers/usb/c67x00/c67x00-drv.c
+++ b/drivers/usb/c67x00/c67x00-drv.c
@@ -177,7 +177,7 @@ static int c67x00_drv_probe(struct platform_device *pdev)
return ret;
}
-static int c67x00_drv_remove(struct platform_device *pdev)
+static void c67x00_drv_remove(struct platform_device *pdev)
{
struct c67x00_device *c67x00 = platform_get_drvdata(pdev);
struct resource *res;
@@ -197,13 +197,11 @@ static int c67x00_drv_remove(struct platform_device *pdev)
release_mem_region(res->start, resource_size(res));
kfree(c67x00);
-
- return 0;
}
static struct platform_driver c67x00_driver = {
.probe = c67x00_drv_probe,
- .remove = c67x00_drv_remove,
+ .remove_new = c67x00_drv_remove,
.driver = {
.name = "c67x00",
},
diff --git a/drivers/usb/cdns3/Kconfig b/drivers/usb/cdns3/Kconfig
index b98ca0a1352a..0a514b591527 100644
--- a/drivers/usb/cdns3/Kconfig
+++ b/drivers/usb/cdns3/Kconfig
@@ -78,6 +78,17 @@ config USB_CDNS3_IMX
For example, imx8qm and imx8qxp.
+config USB_CDNS3_STARFIVE
+ tristate "Cadence USB3 support on StarFive SoC platforms"
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ help
+ Say 'Y' or 'M' here if you are building for StarFive SoCs
+ platforms that contain Cadence USB3 controller core.
+
+ e.g. JH7110.
+
+ If you choose to build this driver as module it will
+ be dynamically linked and module will be called cdns3-starfive.ko
endif
if USB_CDNS_SUPPORT
diff --git a/drivers/usb/cdns3/Makefile b/drivers/usb/cdns3/Makefile
index 61edb2f89276..48dfae75b5aa 100644
--- a/drivers/usb/cdns3/Makefile
+++ b/drivers/usb/cdns3/Makefile
@@ -24,6 +24,7 @@ endif
obj-$(CONFIG_USB_CDNS3_PCI_WRAP) += cdns3-pci-wrap.o
obj-$(CONFIG_USB_CDNS3_TI) += cdns3-ti.o
obj-$(CONFIG_USB_CDNS3_IMX) += cdns3-imx.o
+obj-$(CONFIG_USB_CDNS3_STARFIVE) += cdns3-starfive.o
cdnsp-udc-pci-y := cdnsp-pci.o
diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
index 1dcadef933e3..ea19253fd2d0 100644
--- a/drivers/usb/cdns3/cdns3-gadget.c
+++ b/drivers/usb/cdns3/cdns3-gadget.c
@@ -800,7 +800,8 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep,
if (request->status == -EINPROGRESS)
request->status = status;
- usb_gadget_unmap_request_by_dev(priv_dev->sysdev, request,
+ if (likely(!(priv_req->flags & REQUEST_UNALIGNED)))
+ usb_gadget_unmap_request_by_dev(priv_dev->sysdev, request,
priv_ep->dir);
if ((priv_req->flags & REQUEST_UNALIGNED) &&
@@ -808,10 +809,10 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep,
/* Make DMA buffer CPU accessible */
dma_sync_single_for_cpu(priv_dev->sysdev,
priv_req->aligned_buf->dma,
- priv_req->aligned_buf->size,
+ request->actual,
priv_req->aligned_buf->dir);
memcpy(request->buf, priv_req->aligned_buf->buf,
- request->length);
+ request->actual);
}
priv_req->flags &= ~(REQUEST_PENDING | REQUEST_UNALIGNED);
@@ -2543,10 +2544,12 @@ static int __cdns3_gadget_ep_queue(struct usb_ep *ep,
if (ret < 0)
return ret;
- ret = usb_gadget_map_request_by_dev(priv_dev->sysdev, request,
+ if (likely(!(priv_req->flags & REQUEST_UNALIGNED))) {
+ ret = usb_gadget_map_request_by_dev(priv_dev->sysdev, request,
usb_endpoint_dir_in(ep->desc));
- if (ret)
- return ret;
+ if (ret)
+ return ret;
+ }
list_add_tail(&request->list, &priv_ep->deferred_req_list);
diff --git a/drivers/usb/cdns3/cdns3-imx.c b/drivers/usb/cdns3/cdns3-imx.c
index 59860d1753fd..281de47e2a3b 100644
--- a/drivers/usb/cdns3/cdns3-imx.c
+++ b/drivers/usb/cdns3/cdns3-imx.c
@@ -105,11 +105,11 @@ static inline void cdns_imx_writel(struct cdns_imx *data, u32 offset, u32 value)
}
static const struct clk_bulk_data imx_cdns3_core_clks[] = {
- { .id = "usb3_lpm_clk" },
- { .id = "usb3_bus_clk" },
- { .id = "usb3_aclk" },
- { .id = "usb3_ipg_clk" },
- { .id = "usb3_core_pclk" },
+ { .id = "lpm" },
+ { .id = "bus" },
+ { .id = "aclk" },
+ { .id = "ipg" },
+ { .id = "core" },
};
static int cdns_imx_noncore_init(struct cdns_imx *data)
@@ -218,7 +218,7 @@ err:
return ret;
}
-static int cdns_imx_remove(struct platform_device *pdev)
+static void cdns_imx_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct cdns_imx *data = dev_get_drvdata(dev);
@@ -229,8 +229,6 @@ static int cdns_imx_remove(struct platform_device *pdev)
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
platform_set_drvdata(pdev, NULL);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -375,14 +373,22 @@ static inline bool cdns_imx_is_power_lost(struct cdns_imx *data)
return false;
}
+static int __maybe_unused cdns_imx_system_suspend(struct device *dev)
+{
+ pm_runtime_put_sync(dev);
+ return 0;
+}
+
static int __maybe_unused cdns_imx_system_resume(struct device *dev)
{
struct cdns_imx *data = dev_get_drvdata(dev);
int ret;
- ret = cdns_imx_resume(dev);
- if (ret)
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0) {
+ dev_err(dev, "Could not get runtime PM.\n");
return ret;
+ }
if (cdns_imx_is_power_lost(data)) {
dev_dbg(dev, "resume from power lost\n");
@@ -405,7 +411,7 @@ static int cdns_imx_platform_suspend(struct device *dev,
static const struct dev_pm_ops cdns_imx_pm_ops = {
SET_RUNTIME_PM_OPS(cdns_imx_suspend, cdns_imx_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(cdns_imx_suspend, cdns_imx_system_resume)
+ SET_SYSTEM_SLEEP_PM_OPS(cdns_imx_system_suspend, cdns_imx_system_resume)
};
static const struct of_device_id cdns_imx_of_match[] = {
@@ -416,7 +422,7 @@ MODULE_DEVICE_TABLE(of, cdns_imx_of_match);
static struct platform_driver cdns_imx_driver = {
.probe = cdns_imx_probe,
- .remove = cdns_imx_remove,
+ .remove_new = cdns_imx_remove,
.driver = {
.name = "cdns3-imx",
.of_match_table = cdns_imx_of_match,
diff --git a/drivers/usb/cdns3/cdns3-plat.c b/drivers/usb/cdns3/cdns3-plat.c
index 2bc5d094548b..884e2301237f 100644
--- a/drivers/usb/cdns3/cdns3-plat.c
+++ b/drivers/usb/cdns3/cdns3-plat.c
@@ -175,7 +175,7 @@ err_phy3_init:
*
* Returns 0 on success otherwise negative errno
*/
-static int cdns3_plat_remove(struct platform_device *pdev)
+static void cdns3_plat_remove(struct platform_device *pdev)
{
struct cdns *cdns = platform_get_drvdata(pdev);
struct device *dev = cdns->dev;
@@ -187,7 +187,6 @@ static int cdns3_plat_remove(struct platform_device *pdev)
set_phy_power_off(cdns);
phy_exit(cdns->usb2_phy);
phy_exit(cdns->usb3_phy);
- return 0;
}
#ifdef CONFIG_PM
@@ -320,7 +319,7 @@ MODULE_DEVICE_TABLE(of, of_cdns3_match);
static struct platform_driver cdns3_driver = {
.probe = cdns3_plat_probe,
- .remove = cdns3_plat_remove,
+ .remove_new = cdns3_plat_remove,
.driver = {
.name = "cdns-usb3",
.of_match_table = of_match_ptr(of_cdns3_match),
diff --git a/drivers/usb/cdns3/cdns3-starfive.c b/drivers/usb/cdns3/cdns3-starfive.c
new file mode 100644
index 000000000000..fc1f003b145d
--- /dev/null
+++ b/drivers/usb/cdns3/cdns3-starfive.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * cdns3-starfive.c - StarFive specific Glue layer for Cadence USB Controller
+ *
+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
+ *
+ * Author: Minda Chen <minda.chen@starfivetech.com>
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/reset.h>
+#include <linux/regmap.h>
+#include <linux/usb/otg.h>
+#include "core.h"
+
+#define USB_STRAP_HOST BIT(17)
+#define USB_STRAP_DEVICE BIT(18)
+#define USB_STRAP_MASK GENMASK(18, 16)
+
+#define USB_SUSPENDM_HOST BIT(19)
+#define USB_SUSPENDM_MASK BIT(19)
+
+#define USB_MISC_CFG_MASK GENMASK(23, 20)
+#define USB_SUSPENDM_BYPS BIT(20)
+#define USB_PLL_EN BIT(22)
+#define USB_REFCLK_MODE BIT(23)
+
+struct cdns_starfive {
+ struct device *dev;
+ struct regmap *stg_syscon;
+ struct reset_control *resets;
+ struct clk_bulk_data *clks;
+ int num_clks;
+ u32 stg_usb_mode;
+};
+
+static void cdns_mode_init(struct platform_device *pdev,
+ struct cdns_starfive *data)
+{
+ enum usb_dr_mode mode;
+
+ regmap_update_bits(data->stg_syscon, data->stg_usb_mode,
+ USB_MISC_CFG_MASK,
+ USB_SUSPENDM_BYPS | USB_PLL_EN | USB_REFCLK_MODE);
+
+ /* dr mode setting */
+ mode = usb_get_dr_mode(&pdev->dev);
+
+ switch (mode) {
+ case USB_DR_MODE_HOST:
+ regmap_update_bits(data->stg_syscon,
+ data->stg_usb_mode,
+ USB_STRAP_MASK,
+ USB_STRAP_HOST);
+ regmap_update_bits(data->stg_syscon,
+ data->stg_usb_mode,
+ USB_SUSPENDM_MASK,
+ USB_SUSPENDM_HOST);
+ break;
+
+ case USB_DR_MODE_PERIPHERAL:
+ regmap_update_bits(data->stg_syscon, data->stg_usb_mode,
+ USB_STRAP_MASK, USB_STRAP_DEVICE);
+ regmap_update_bits(data->stg_syscon, data->stg_usb_mode,
+ USB_SUSPENDM_MASK, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+static int cdns_clk_rst_init(struct cdns_starfive *data)
+{
+ int ret;
+
+ ret = clk_bulk_prepare_enable(data->num_clks, data->clks);
+ if (ret)
+ return dev_err_probe(data->dev, ret,
+ "failed to enable clocks\n");
+
+ ret = reset_control_deassert(data->resets);
+ if (ret) {
+ dev_err(data->dev, "failed to reset clocks\n");
+ goto err_clk_init;
+ }
+
+ return ret;
+
+err_clk_init:
+ clk_bulk_disable_unprepare(data->num_clks, data->clks);
+ return ret;
+}
+
+static void cdns_clk_rst_deinit(struct cdns_starfive *data)
+{
+ reset_control_assert(data->resets);
+ clk_bulk_disable_unprepare(data->num_clks, data->clks);
+}
+
+static int cdns_starfive_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct cdns_starfive *data;
+ unsigned int args;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->dev = dev;
+
+ data->stg_syscon =
+ syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node,
+ "starfive,stg-syscon", 1, &args);
+
+ if (IS_ERR(data->stg_syscon))
+ return dev_err_probe(dev, PTR_ERR(data->stg_syscon),
+ "Failed to parse starfive,stg-syscon\n");
+
+ data->stg_usb_mode = args;
+
+ data->num_clks = devm_clk_bulk_get_all(data->dev, &data->clks);
+ if (data->num_clks < 0)
+ return dev_err_probe(data->dev, -ENODEV,
+ "Failed to get clocks\n");
+
+ data->resets = devm_reset_control_array_get_exclusive(data->dev);
+ if (IS_ERR(data->resets))
+ return dev_err_probe(data->dev, PTR_ERR(data->resets),
+ "Failed to get resets");
+
+ cdns_mode_init(pdev, data);
+ ret = cdns_clk_rst_init(data);
+ if (ret)
+ return ret;
+
+ ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+ if (ret) {
+ dev_err(dev, "Failed to create children\n");
+ cdns_clk_rst_deinit(data);
+ return ret;
+ }
+
+ device_set_wakeup_capable(dev, true);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ platform_set_drvdata(pdev, data);
+
+ return 0;
+}
+
+static int cdns_starfive_remove_core(struct device *dev, void *c)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ platform_device_unregister(pdev);
+
+ return 0;
+}
+
+static int cdns_starfive_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct cdns_starfive *data = dev_get_drvdata(dev);
+
+ pm_runtime_get_sync(dev);
+ device_for_each_child(dev, NULL, cdns_starfive_remove_core);
+
+ pm_runtime_disable(dev);
+ pm_runtime_put_noidle(dev);
+ cdns_clk_rst_deinit(data);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int cdns_starfive_runtime_resume(struct device *dev)
+{
+ struct cdns_starfive *data = dev_get_drvdata(dev);
+
+ return clk_bulk_prepare_enable(data->num_clks, data->clks);
+}
+
+static int cdns_starfive_runtime_suspend(struct device *dev)
+{
+ struct cdns_starfive *data = dev_get_drvdata(dev);
+
+ clk_bulk_disable_unprepare(data->num_clks, data->clks);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int cdns_starfive_resume(struct device *dev)
+{
+ struct cdns_starfive *data = dev_get_drvdata(dev);
+
+ return cdns_clk_rst_init(data);
+}
+
+static int cdns_starfive_suspend(struct device *dev)
+{
+ struct cdns_starfive *data = dev_get_drvdata(dev);
+
+ cdns_clk_rst_deinit(data);
+
+ return 0;
+}
+#endif
+#endif
+
+static const struct dev_pm_ops cdns_starfive_pm_ops = {
+ SET_RUNTIME_PM_OPS(cdns_starfive_runtime_suspend,
+ cdns_starfive_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(cdns_starfive_suspend, cdns_starfive_resume)
+};
+
+static const struct of_device_id cdns_starfive_of_match[] = {
+ { .compatible = "starfive,jh7110-usb", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cdns_starfive_of_match);
+
+static struct platform_driver cdns_starfive_driver = {
+ .probe = cdns_starfive_probe,
+ .remove = cdns_starfive_remove,
+ .driver = {
+ .name = "cdns3-starfive",
+ .of_match_table = cdns_starfive_of_match,
+ .pm = &cdns_starfive_pm_ops,
+ },
+};
+module_platform_driver(cdns_starfive_driver);
+
+MODULE_ALIAS("platform:cdns3-starfive");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Cadence USB3 StarFive Glue Layer");
diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c
index 07c318770362..81b9132e3aaa 100644
--- a/drivers/usb/cdns3/cdns3-ti.c
+++ b/drivers/usb/cdns3/cdns3-ti.c
@@ -199,7 +199,7 @@ static int cdns_ti_remove_core(struct device *dev, void *c)
return 0;
}
-static int cdns_ti_remove(struct platform_device *pdev)
+static void cdns_ti_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -208,8 +208,6 @@ static int cdns_ti_remove(struct platform_device *pdev)
pm_runtime_disable(dev);
platform_set_drvdata(pdev, NULL);
-
- return 0;
}
static const struct of_device_id cdns_ti_of_match[] = {
@@ -221,7 +219,7 @@ MODULE_DEVICE_TABLE(of, cdns_ti_of_match);
static struct platform_driver cdns_ti_driver = {
.probe = cdns_ti_probe,
- .remove = cdns_ti_remove,
+ .remove_new = cdns_ti_remove,
.driver = {
.name = "cdns3-ti",
.of_match_table = cdns_ti_of_match,
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 2855ac303001..336ef6dd8e7d 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -70,6 +70,10 @@ static const struct ci_hdrc_imx_platform_flag imx7ulp_usb_data = {
CI_HDRC_PMQOS,
};
+static const struct ci_hdrc_imx_platform_flag imx8ulp_usb_data = {
+ .flags = CI_HDRC_SUPPORTS_RUNTIME_PM,
+};
+
static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx23-usb", .data = &imx23_usb_data},
{ .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
@@ -80,6 +84,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data},
{ .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data},
{ .compatible = "fsl,imx7ulp-usb", .data = &imx7ulp_usb_data},
+ { .compatible = "fsl,imx8ulp-usb", .data = &imx8ulp_usb_data},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
@@ -502,7 +507,7 @@ disable_hsic_regulator:
return ret;
}
-static int ci_hdrc_imx_remove(struct platform_device *pdev)
+static void ci_hdrc_imx_remove(struct platform_device *pdev)
{
struct ci_hdrc_imx_data *data = platform_get_drvdata(pdev);
@@ -522,8 +527,6 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
if (data->hsic_pad_regulator)
regulator_disable(data->hsic_pad_regulator);
}
-
- return 0;
}
static void ci_hdrc_imx_shutdown(struct platform_device *pdev)
@@ -650,7 +653,7 @@ static const struct dev_pm_ops ci_hdrc_imx_pm_ops = {
};
static struct platform_driver ci_hdrc_imx_driver = {
.probe = ci_hdrc_imx_probe,
- .remove = ci_hdrc_imx_remove,
+ .remove_new = ci_hdrc_imx_remove,
.shutdown = ci_hdrc_imx_shutdown,
.driver = {
.name = "imx_usb",
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index 46105457e1ca..7b5b47ce8a02 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -274,7 +274,7 @@ err_iface:
return ret;
}
-static int ci_hdrc_msm_remove(struct platform_device *pdev)
+static void ci_hdrc_msm_remove(struct platform_device *pdev)
{
struct ci_hdrc_msm *ci = platform_get_drvdata(pdev);
@@ -282,8 +282,6 @@ static int ci_hdrc_msm_remove(struct platform_device *pdev)
ci_hdrc_remove_device(ci->ci);
clk_disable_unprepare(ci->iface_clk);
clk_disable_unprepare(ci->core_clk);
-
- return 0;
}
static const struct of_device_id msm_ci_dt_match[] = {
@@ -294,7 +292,7 @@ MODULE_DEVICE_TABLE(of, msm_ci_dt_match);
static struct platform_driver ci_hdrc_msm_driver = {
.probe = ci_hdrc_msm_probe,
- .remove = ci_hdrc_msm_remove,
+ .remove_new = ci_hdrc_msm_remove,
.driver = {
.name = "msm_hsusb",
.of_match_table = msm_ci_dt_match,
diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c b/drivers/usb/chipidea/ci_hdrc_tegra.c
index a72a9474afea..ca36d11a69ea 100644
--- a/drivers/usb/chipidea/ci_hdrc_tegra.c
+++ b/drivers/usb/chipidea/ci_hdrc_tegra.c
@@ -362,7 +362,7 @@ fail_power_off:
return err;
}
-static int tegra_usb_remove(struct platform_device *pdev)
+static void tegra_usb_remove(struct platform_device *pdev)
{
struct tegra_usb *usb = platform_get_drvdata(pdev);
@@ -371,8 +371,6 @@ static int tegra_usb_remove(struct platform_device *pdev)
pm_runtime_put_sync_suspend(&pdev->dev);
pm_runtime_force_suspend(&pdev->dev);
-
- return 0;
}
static int __maybe_unused tegra_usb_runtime_resume(struct device *dev)
@@ -410,7 +408,7 @@ static struct platform_driver tegra_usb_driver = {
.pm = &tegra_usb_pm,
},
.probe = tegra_usb_probe,
- .remove = tegra_usb_remove,
+ .remove_new = tegra_usb_remove,
};
module_platform_driver(tegra_usb_driver);
diff --git a/drivers/usb/chipidea/ci_hdrc_usb2.c b/drivers/usb/chipidea/ci_hdrc_usb2.c
index dc86b12060b5..1321ee67f3b8 100644
--- a/drivers/usb/chipidea/ci_hdrc_usb2.c
+++ b/drivers/usb/chipidea/ci_hdrc_usb2.c
@@ -106,20 +106,18 @@ clk_err:
return ret;
}
-static int ci_hdrc_usb2_remove(struct platform_device *pdev)
+static void ci_hdrc_usb2_remove(struct platform_device *pdev)
{
struct ci_hdrc_usb2_priv *priv = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
ci_hdrc_remove_device(priv->ci_pdev);
clk_disable_unprepare(priv->clk);
-
- return 0;
}
static struct platform_driver ci_hdrc_usb2_driver = {
.probe = ci_hdrc_usb2_probe,
- .remove = ci_hdrc_usb2_remove,
+ .remove_new = ci_hdrc_usb2_remove,
.driver = {
.name = "chipidea-usb2",
.of_match_table = of_match_ptr(ci_hdrc_usb2_of_match),
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 798cb077867a..51994d655b82 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -1227,7 +1227,7 @@ ulpi_exit:
return ret;
}
-static int ci_hdrc_remove(struct platform_device *pdev)
+static void ci_hdrc_remove(struct platform_device *pdev)
{
struct ci_hdrc *ci = platform_get_drvdata(pdev);
@@ -1245,8 +1245,6 @@ static int ci_hdrc_remove(struct platform_device *pdev)
ci_hdrc_enter_lpm(ci, true);
ci_usb_phy_exit(ci);
ci_ulpi_exit(ci);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -1485,7 +1483,7 @@ static const struct dev_pm_ops ci_pm_ops = {
static struct platform_driver ci_hdrc_driver = {
.probe = ci_hdrc_probe,
- .remove = ci_hdrc_remove,
+ .remove_new = ci_hdrc_remove,
.driver = {
.name = "ci_hdrc",
.pm = &ci_pm_ops,
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index c57c1a71a513..9ee9621e2ccc 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -113,7 +113,6 @@
#define MX7D_USBNC_USB_CTRL2_DP_DM_MASK (BIT(12) | BIT(13) | \
BIT(14) | BIT(15))
-#define MX7D_USB_OTG_PHY_CFG1 0x30
#define MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL BIT(0)
#define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 BIT(1)
#define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 BIT(2)
@@ -135,7 +134,7 @@
#define TXVREFTUNE0_MASK (0xf << 20)
#define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \
- MX6_BM_ID_WAKEUP)
+ MX6_BM_ID_WAKEUP | MX6SX_BM_DPDM_WAKEUP_EN)
struct usbmisc_ops {
/* It's called once when probe a usb device */
@@ -152,6 +151,7 @@ struct usbmisc_ops {
int (*charger_detection)(struct imx_usbmisc_data *data);
/* It's called when system resume from usb power lost */
int (*power_lost_check)(struct imx_usbmisc_data *data);
+ void (*vbus_comparator_on)(struct imx_usbmisc_data *data, bool on);
};
struct imx_usbmisc {
@@ -875,6 +875,33 @@ static int imx7d_charger_detection(struct imx_usbmisc_data *data)
return ret;
}
+static void usbmisc_imx7d_vbus_comparator_on(struct imx_usbmisc_data *data,
+ bool on)
+{
+ unsigned long flags;
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ u32 val;
+
+ if (data->hsic)
+ return;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ /*
+ * Disable VBUS valid comparator when in suspend mode,
+ * when OTG is disabled and DRVVBUS0 is asserted case
+ * the Bandgap circuitry and VBUS Valid comparator are
+ * still powered, even in Suspend or Sleep mode.
+ */
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
+ if (on)
+ val |= MX7D_USB_OTG_PHY_CFG2_DRVVBUS0;
+ else
+ val &= ~MX7D_USB_OTG_PHY_CFG2_DRVVBUS0;
+
+ writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+}
+
static int usbmisc_imx7ulp_init(struct imx_usbmisc_data *data)
{
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
@@ -1018,6 +1045,7 @@ static const struct usbmisc_ops imx7d_usbmisc_ops = {
.set_wakeup = usbmisc_imx7d_set_wakeup,
.charger_detection = imx7d_charger_detection,
.power_lost_check = usbmisc_imx7d_power_lost_check,
+ .vbus_comparator_on = usbmisc_imx7d_vbus_comparator_on,
};
static const struct usbmisc_ops imx7ulp_usbmisc_ops = {
@@ -1132,6 +1160,9 @@ int imx_usbmisc_suspend(struct imx_usbmisc_data *data, bool wakeup)
usbmisc = dev_get_drvdata(data->dev);
+ if (usbmisc->ops->vbus_comparator_on)
+ usbmisc->ops->vbus_comparator_on(data, false);
+
if (wakeup && usbmisc->ops->set_wakeup)
ret = usbmisc->ops->set_wakeup(data, true);
if (ret) {
@@ -1185,6 +1216,9 @@ int imx_usbmisc_resume(struct imx_usbmisc_data *data, bool wakeup)
goto hsic_set_clk_fail;
}
+ if (usbmisc->ops->vbus_comparator_on)
+ usbmisc->ops->vbus_comparator_on(data, true);
+
return 0;
hsic_set_clk_fail:
diff --git a/drivers/usb/common/led.c b/drivers/usb/common/led.c
index 0865dd44a80a..1de18d90b134 100644
--- a/drivers/usb/common/led.c
+++ b/drivers/usb/common/led.c
@@ -14,8 +14,6 @@
#define BLINK_DELAY 30
-static unsigned long usb_blink_delay = BLINK_DELAY;
-
DEFINE_LED_TRIGGER(ledtrig_usb_gadget);
DEFINE_LED_TRIGGER(ledtrig_usb_host);
@@ -32,7 +30,7 @@ void usb_led_activity(enum usb_led_event ev)
break;
}
/* led_trigger_blink_oneshot() handles trig == NULL gracefully */
- led_trigger_blink_oneshot(trig, &usb_blink_delay, &usb_blink_delay, 0);
+ led_trigger_blink_oneshot(trig, BLINK_DELAY, BLINK_DELAY, 0);
}
EXPORT_SYMBOL_GPL(usb_led_activity);
diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c
index e20874caba36..766005d20bae 100644
--- a/drivers/usb/common/usb-conn-gpio.c
+++ b/drivers/usb/common/usb-conn-gpio.c
@@ -267,7 +267,7 @@ put_role_sw:
return ret;
}
-static int usb_conn_remove(struct platform_device *pdev)
+static void usb_conn_remove(struct platform_device *pdev)
{
struct usb_conn_info *info = platform_get_drvdata(pdev);
@@ -277,8 +277,6 @@ static int usb_conn_remove(struct platform_device *pdev)
regulator_disable(info->vbus);
usb_role_switch_put(info->role_sw);
-
- return 0;
}
static int __maybe_unused usb_conn_suspend(struct device *dev)
@@ -338,7 +336,7 @@ MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
static struct platform_driver usb_conn_driver = {
.probe = usb_conn_probe,
- .remove = usb_conn_remove,
+ .remove_new = usb_conn_remove,
.driver = {
.name = "usb-conn-gpio",
.pm = &usb_conn_pm_ops,
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index fcf68818e999..1a16a8bdea60 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -746,6 +746,7 @@ static int driver_resume(struct usb_interface *intf)
return 0;
}
+#ifdef CONFIG_PM
/* The following routines apply to the entire device, not interfaces */
void usbfs_notify_suspend(struct usb_device *udev)
{
@@ -764,6 +765,7 @@ void usbfs_notify_resume(struct usb_device *udev)
}
mutex_unlock(&usbfs_mutex);
}
+#endif
struct usb_driver usbfs_driver = {
.name = "usbfs",
@@ -2640,21 +2642,21 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
snoop(&dev->dev, "%s: CONTROL\n", __func__);
ret = proc_control(ps, p);
if (ret >= 0)
- inode->i_mtime = current_time(inode);
+ inode->i_mtime = inode->i_ctime = current_time(inode);
break;
case USBDEVFS_BULK:
snoop(&dev->dev, "%s: BULK\n", __func__);
ret = proc_bulk(ps, p);
if (ret >= 0)
- inode->i_mtime = current_time(inode);
+ inode->i_mtime = inode->i_ctime = current_time(inode);
break;
case USBDEVFS_RESETEP:
snoop(&dev->dev, "%s: RESETEP\n", __func__);
ret = proc_resetep(ps, p);
if (ret >= 0)
- inode->i_mtime = current_time(inode);
+ inode->i_mtime = inode->i_ctime = current_time(inode);
break;
case USBDEVFS_RESET:
@@ -2666,7 +2668,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
snoop(&dev->dev, "%s: CLEAR_HALT\n", __func__);
ret = proc_clearhalt(ps, p);
if (ret >= 0)
- inode->i_mtime = current_time(inode);
+ inode->i_mtime = inode->i_ctime = current_time(inode);
break;
case USBDEVFS_GETDRIVER:
@@ -2693,7 +2695,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
snoop(&dev->dev, "%s: SUBMITURB\n", __func__);
ret = proc_submiturb(ps, p);
if (ret >= 0)
- inode->i_mtime = current_time(inode);
+ inode->i_mtime = inode->i_ctime = current_time(inode);
break;
#ifdef CONFIG_COMPAT
@@ -2701,14 +2703,14 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
snoop(&dev->dev, "%s: CONTROL32\n", __func__);
ret = proc_control_compat(ps, p);
if (ret >= 0)
- inode->i_mtime = current_time(inode);
+ inode->i_mtime = inode->i_ctime = current_time(inode);
break;
case USBDEVFS_BULK32:
snoop(&dev->dev, "%s: BULK32\n", __func__);
ret = proc_bulk_compat(ps, p);
if (ret >= 0)
- inode->i_mtime = current_time(inode);
+ inode->i_mtime = inode->i_ctime = current_time(inode);
break;
case USBDEVFS_DISCSIGNAL32:
@@ -2720,7 +2722,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
snoop(&dev->dev, "%s: SUBMITURB32\n", __func__);
ret = proc_submiturb_compat(ps, p);
if (ret >= 0)
- inode->i_mtime = current_time(inode);
+ inode->i_mtime = inode->i_ctime = current_time(inode);
break;
case USBDEVFS_IOCTL32:
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index ab2f3737764e..990280688b25 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -415,12 +415,15 @@ static int check_root_hub_suspended(struct device *dev)
return 0;
}
-static int suspend_common(struct device *dev, bool do_wakeup)
+static int suspend_common(struct device *dev, pm_message_t msg)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct usb_hcd *hcd = pci_get_drvdata(pci_dev);
+ bool do_wakeup;
int retval;
+ do_wakeup = PMSG_IS_AUTO(msg) ? true : device_may_wakeup(dev);
+
/* Root hub suspend should have stopped all downstream traffic,
* and all bus master traffic. And done so for both the interface
* and the stub usb_device (which we check here). But maybe it
@@ -447,7 +450,7 @@ static int suspend_common(struct device *dev, bool do_wakeup)
(retval == 0 && do_wakeup && hcd->shared_hcd &&
HCD_WAKEUP_PENDING(hcd->shared_hcd))) {
if (hcd->driver->pci_resume)
- hcd->driver->pci_resume(hcd, false);
+ hcd->driver->pci_resume(hcd, msg);
retval = -EBUSY;
}
if (retval)
@@ -470,7 +473,7 @@ static int suspend_common(struct device *dev, bool do_wakeup)
return retval;
}
-static int resume_common(struct device *dev, int event)
+static int resume_common(struct device *dev, pm_message_t msg)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct usb_hcd *hcd = pci_get_drvdata(pci_dev);
@@ -498,12 +501,11 @@ static int resume_common(struct device *dev, int event)
* No locking is needed because PCI controller drivers do not
* get unbound during system resume.
*/
- if (pci_dev->class == CL_EHCI && event != PM_EVENT_AUTO_RESUME)
+ if (pci_dev->class == CL_EHCI && msg.event != PM_EVENT_AUTO_RESUME)
for_each_companion(pci_dev, hcd,
ehci_wait_for_companions);
- retval = hcd->driver->pci_resume(hcd,
- event == PM_EVENT_RESTORE);
+ retval = hcd->driver->pci_resume(hcd, msg);
if (retval) {
dev_err(dev, "PCI post-resume error %d!\n", retval);
usb_hc_died(hcd);
@@ -516,7 +518,7 @@ static int resume_common(struct device *dev, int event)
static int hcd_pci_suspend(struct device *dev)
{
- return suspend_common(dev, device_may_wakeup(dev));
+ return suspend_common(dev, PMSG_SUSPEND);
}
static int hcd_pci_suspend_noirq(struct device *dev)
@@ -577,12 +579,12 @@ static int hcd_pci_resume_noirq(struct device *dev)
static int hcd_pci_resume(struct device *dev)
{
- return resume_common(dev, PM_EVENT_RESUME);
+ return resume_common(dev, PMSG_RESUME);
}
static int hcd_pci_restore(struct device *dev)
{
- return resume_common(dev, PM_EVENT_RESTORE);
+ return resume_common(dev, PMSG_RESTORE);
}
#else
@@ -600,7 +602,7 @@ static int hcd_pci_runtime_suspend(struct device *dev)
{
int retval;
- retval = suspend_common(dev, true);
+ retval = suspend_common(dev, PMSG_AUTO_SUSPEND);
if (retval == 0)
powermac_set_asic(to_pci_dev(dev), 0);
dev_dbg(dev, "hcd_pci_runtime_suspend: %d\n", retval);
@@ -612,7 +614,7 @@ static int hcd_pci_runtime_resume(struct device *dev)
int retval;
powermac_set_asic(to_pci_dev(dev), 1);
- retval = resume_common(dev, PM_EVENT_AUTO_RESUME);
+ retval = resume_common(dev, PMSG_AUTO_RESUME);
dev_dbg(dev, "hcd_pci_runtime_resume: %d\n", retval);
return retval;
}
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 97a0f8faea6e..a739403a9e45 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2018,6 +2018,19 @@ bool usb_device_is_owned(struct usb_device *udev)
return !!hub->ports[udev->portnum - 1]->port_owner;
}
+static void update_port_device_state(struct usb_device *udev)
+{
+ struct usb_hub *hub;
+ struct usb_port *port_dev;
+
+ if (udev->parent) {
+ hub = usb_hub_to_struct_hub(udev->parent);
+ port_dev = hub->ports[udev->portnum - 1];
+ WRITE_ONCE(port_dev->state, udev->state);
+ sysfs_notify_dirent(port_dev->state_kn);
+ }
+}
+
static void recursively_mark_NOTATTACHED(struct usb_device *udev)
{
struct usb_hub *hub = usb_hub_to_struct_hub(udev);
@@ -2030,6 +2043,7 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
if (udev->state == USB_STATE_SUSPENDED)
udev->active_duration -= jiffies;
udev->state = USB_STATE_NOTATTACHED;
+ update_port_device_state(udev);
}
/**
@@ -2086,6 +2100,7 @@ void usb_set_device_state(struct usb_device *udev,
udev->state != USB_STATE_SUSPENDED)
udev->active_duration += jiffies;
udev->state = new_state;
+ update_port_device_state(udev);
} else
recursively_mark_NOTATTACHED(udev);
spin_unlock_irqrestore(&device_state_lock, flags);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index e23833562e4f..37897afd1b64 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -84,6 +84,8 @@ struct usb_hub {
* @peer: related usb2 and usb3 ports (share the same connector)
* @req: default pm qos request for hubs without port power control
* @connect_type: port's connect type
+ * @state: device state of the usb device attached to the port
+ * @state_kn: kernfs_node of the sysfs attribute that accesses @state
* @location: opaque representation of platform connector location
* @status_lock: synchronize port_event() vs usb_port_{suspend|resume}
* @portnum: port index num based one
@@ -100,6 +102,8 @@ struct usb_port {
struct usb_port *peer;
struct dev_pm_qos_request *req;
enum usb_port_connect_type connect_type;
+ enum usb_device_state state;
+ struct kernfs_node *state_kn;
usb_port_location_t location;
struct mutex status_lock;
u32 over_current_count;
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index 06a8f1f84f6f..77be0dc28da9 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -160,6 +160,16 @@ static ssize_t connect_type_show(struct device *dev,
}
static DEVICE_ATTR_RO(connect_type);
+static ssize_t state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_port *port_dev = to_usb_port(dev);
+ enum usb_device_state state = READ_ONCE(port_dev->state);
+
+ return sysfs_emit(buf, "%s\n", usb_state_string(state));
+}
+static DEVICE_ATTR_RO(state);
+
static ssize_t over_current_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -259,6 +269,7 @@ static DEVICE_ATTR_RW(usb3_lpm_permit);
static struct attribute *port_dev_attrs[] = {
&dev_attr_connect_type.attr,
+ &dev_attr_state.attr,
&dev_attr_location.attr,
&dev_attr_quirks.attr,
&dev_attr_over_current_count.attr,
@@ -705,19 +716,24 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
return retval;
}
+ port_dev->state_kn = sysfs_get_dirent(port_dev->dev.kobj.sd, "state");
+ if (!port_dev->state_kn) {
+ dev_err(&port_dev->dev, "failed to sysfs_get_dirent 'state'\n");
+ retval = -ENODEV;
+ goto err_unregister;
+ }
+
/* Set default policy of port-poweroff disabled. */
retval = dev_pm_qos_add_request(&port_dev->dev, port_dev->req,
DEV_PM_QOS_FLAGS, PM_QOS_FLAG_NO_POWER_OFF);
if (retval < 0) {
- device_unregister(&port_dev->dev);
- return retval;
+ goto err_put_kn;
}
retval = component_add(&port_dev->dev, &connector_ops);
if (retval) {
dev_warn(&port_dev->dev, "failed to add component\n");
- device_unregister(&port_dev->dev);
- return retval;
+ goto err_put_kn;
}
find_and_link_peer(hub, port1);
@@ -754,6 +770,13 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
port_dev->req = NULL;
}
return 0;
+
+err_put_kn:
+ sysfs_put(port_dev->state_kn);
+err_unregister:
+ device_unregister(&port_dev->dev);
+
+ return retval;
}
void usb_hub_remove_port_device(struct usb_hub *hub, int port1)
@@ -765,5 +788,6 @@ void usb_hub_remove_port_device(struct usb_hub *hub, int port1)
if (peer)
unlink_peers(port_dev, peer);
component_del(&port_dev->dev, &connector_ops);
+ sysfs_put(port_dev->state_kn);
device_unregister(&port_dev->dev);
}
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 21d16533bd2f..4c7c3dd15f9b 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -161,6 +161,25 @@ static void dwc2_set_amlogic_g12a_params(struct dwc2_hsotg *hsotg)
p->hird_threshold_en = false;
}
+static void dwc2_set_amlogic_a1_params(struct dwc2_hsotg *hsotg)
+{
+ struct dwc2_core_params *p = &hsotg->params;
+
+ p->otg_caps.hnp_support = false;
+ p->otg_caps.srp_support = false;
+ p->speed = DWC2_SPEED_PARAM_HIGH;
+ p->host_rx_fifo_size = 192;
+ p->host_nperio_tx_fifo_size = 128;
+ p->host_perio_tx_fifo_size = 128;
+ p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI;
+ p->phy_utmi_width = 8;
+ p->ahbcfg = GAHBCFG_HBSTLEN_INCR8 << GAHBCFG_HBSTLEN_SHIFT;
+ p->lpm = false;
+ p->lpm_clock_gating = false;
+ p->besl = false;
+ p->hird_threshold_en = false;
+}
+
static void dwc2_set_amcc_params(struct dwc2_hsotg *hsotg)
{
struct dwc2_core_params *p = &hsotg->params;
@@ -258,6 +277,8 @@ const struct of_device_id dwc2_of_match_table[] = {
.data = dwc2_set_amlogic_params },
{ .compatible = "amlogic,meson-g12a-usb",
.data = dwc2_set_amlogic_g12a_params },
+ { .compatible = "amlogic,meson-a1-usb",
+ .data = dwc2_set_amlogic_a1_params },
{ .compatible = "amcc,dwc-otg", .data = dwc2_set_amcc_params },
{ .compatible = "apm,apm82181-dwc-otg", .data = dwc2_set_amcc_params },
{ .compatible = "st,stm32f4x9-fsotg",
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index 5aee284018c0..0a806f80217e 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -203,6 +203,11 @@ int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
return ret;
}
+static void dwc2_reset_control_assert(void *data)
+{
+ reset_control_assert(data);
+}
+
static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
{
int i, ret;
@@ -213,6 +218,10 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
"error getting reset control\n");
reset_control_deassert(hsotg->reset);
+ ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert,
+ hsotg->reset);
+ if (ret)
+ return ret;
hsotg->reset_ecc = devm_reset_control_get_optional(hsotg->dev, "dwc2-ecc");
if (IS_ERR(hsotg->reset_ecc))
@@ -220,6 +229,10 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
"error getting reset control for ecc\n");
reset_control_deassert(hsotg->reset_ecc);
+ ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert,
+ hsotg->reset_ecc);
+ if (ret)
+ return ret;
/*
* Attempt to find a generic PHY, then look for an old style
@@ -288,7 +301,7 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
* stops device processing. Any resources used on behalf of this device are
* freed.
*/
-static int dwc2_driver_remove(struct platform_device *dev)
+static void dwc2_driver_remove(struct platform_device *dev)
{
struct dwc2_hsotg *hsotg = platform_get_drvdata(dev);
struct dwc2_gregs_backup *gr;
@@ -338,11 +351,6 @@ static int dwc2_driver_remove(struct platform_device *dev)
if (hsotg->ll_hw_enabled)
dwc2_lowlevel_hw_disable(hsotg);
-
- reset_control_assert(hsotg->reset);
- reset_control_assert(hsotg->reset_ecc);
-
- return 0;
}
/**
@@ -746,7 +754,7 @@ static struct platform_driver dwc2_platform_driver = {
.pm = &dwc2_dev_pm_ops,
},
.probe = dwc2_driver_probe,
- .remove = dwc2_driver_remove,
+ .remove_new = dwc2_driver_remove,
.shutdown = dwc2_driver_shutdown,
};
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index d68958e151a7..f6689b731718 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1800,6 +1800,17 @@ static int dwc3_probe(struct platform_device *pdev)
dwc_res = *res;
dwc_res.start += DWC3_GLOBALS_REGS_START;
+ if (dev->of_node) {
+ struct device_node *parent = of_get_parent(dev->of_node);
+
+ if (of_device_is_compatible(parent, "realtek,rtd-dwc3")) {
+ dwc_res.start -= DWC3_GLOBALS_REGS_START;
+ dwc_res.start += DWC3_RTK_RTD_GLOBALS_REGS_START;
+ }
+
+ of_node_put(parent);
+ }
+
regs = devm_ioremap_resource(dev, &dwc_res);
if (IS_ERR(regs))
return PTR_ERR(regs);
@@ -1913,7 +1924,7 @@ err_put_psy:
return ret;
}
-static int dwc3_remove(struct platform_device *pdev)
+static void dwc3_remove(struct platform_device *pdev)
{
struct dwc3 *dwc = platform_get_drvdata(pdev);
@@ -1940,8 +1951,6 @@ static int dwc3_remove(struct platform_device *pdev)
if (dwc->usb_psy)
power_supply_put(dwc->usb_psy);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -2252,7 +2261,7 @@ MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match);
static struct platform_driver dwc3_driver = {
.probe = dwc3_probe,
- .remove = dwc3_remove,
+ .remove_new = dwc3_remove,
.driver = {
.name = "dwc3",
.of_match_table = of_match_ptr(of_dwc3_match),
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 1f043c31a096..8b1295e4dcdd 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -84,6 +84,8 @@
#define DWC3_OTG_REGS_START 0xcc00
#define DWC3_OTG_REGS_END 0xccff
+#define DWC3_RTK_RTD_GLOBALS_REGS_START 0x8100
+
/* Global Registers */
#define DWC3_GSBUSCFG0 0xc100
#define DWC3_GSBUSCFG1 0xc104
diff --git a/drivers/usb/dwc3/dwc3-am62.c b/drivers/usb/dwc3/dwc3-am62.c
index cda9458c809b..1755f2f848c5 100644
--- a/drivers/usb/dwc3/dwc3-am62.c
+++ b/drivers/usb/dwc3/dwc3-am62.c
@@ -275,7 +275,7 @@ static int dwc3_ti_remove_core(struct device *dev, void *c)
return 0;
}
-static int dwc3_ti_remove(struct platform_device *pdev)
+static void dwc3_ti_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dwc3_data *data = platform_get_drvdata(pdev);
@@ -294,7 +294,6 @@ static int dwc3_ti_remove(struct platform_device *pdev)
pm_runtime_set_suspended(dev);
platform_set_drvdata(pdev, NULL);
- return 0;
}
#ifdef CONFIG_PM
@@ -362,7 +361,7 @@ MODULE_DEVICE_TABLE(of, dwc3_ti_of_match);
static struct platform_driver dwc3_ti_driver = {
.probe = dwc3_ti_probe,
- .remove = dwc3_ti_remove,
+ .remove_new = dwc3_ti_remove,
.driver = {
.name = "dwc3-am62",
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index 4be6a873bd07..f882dd647340 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -128,7 +128,7 @@ vdd33_err:
return ret;
}
-static int dwc3_exynos_remove(struct platform_device *pdev)
+static void dwc3_exynos_remove(struct platform_device *pdev)
{
struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
int i;
@@ -143,8 +143,6 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
regulator_disable(exynos->vdd33);
regulator_disable(exynos->vdd10);
-
- return 0;
}
static const struct dwc3_exynos_driverdata exynos5250_drvdata = {
@@ -234,7 +232,7 @@ static const struct dev_pm_ops dwc3_exynos_dev_pm_ops = {
static struct platform_driver dwc3_exynos_driver = {
.probe = dwc3_exynos_probe,
- .remove = dwc3_exynos_remove,
+ .remove_new = dwc3_exynos_remove,
.driver = {
.name = "exynos-dwc3",
.of_match_table = exynos_dwc3_match,
diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c
index 174f07614318..8b9a3bb587bf 100644
--- a/drivers/usb/dwc3/dwc3-imx8mp.c
+++ b/drivers/usb/dwc3/dwc3-imx8mp.c
@@ -266,7 +266,7 @@ disable_hsio_clk:
return err;
}
-static int dwc3_imx8mp_remove(struct platform_device *pdev)
+static void dwc3_imx8mp_remove(struct platform_device *pdev)
{
struct dwc3_imx8mp *dwc3_imx = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
@@ -280,8 +280,6 @@ static int dwc3_imx8mp_remove(struct platform_device *pdev)
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
platform_set_drvdata(pdev, NULL);
-
- return 0;
}
static int __maybe_unused dwc3_imx8mp_suspend(struct dwc3_imx8mp *dwc3_imx,
@@ -411,7 +409,7 @@ MODULE_DEVICE_TABLE(of, dwc3_imx8mp_of_match);
static struct platform_driver dwc3_imx8mp_driver = {
.probe = dwc3_imx8mp_probe,
- .remove = dwc3_imx8mp_remove,
+ .remove_new = dwc3_imx8mp_remove,
.driver = {
.name = "imx8mp-dwc3",
.pm = &dwc3_imx8mp_dev_pm_ops,
diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c
index 1317959294e6..0a09aedc2573 100644
--- a/drivers/usb/dwc3/dwc3-keystone.c
+++ b/drivers/usb/dwc3/dwc3-keystone.c
@@ -181,7 +181,7 @@ static int kdwc3_remove_core(struct device *dev, void *c)
return 0;
}
-static int kdwc3_remove(struct platform_device *pdev)
+static void kdwc3_remove(struct platform_device *pdev)
{
struct dwc3_keystone *kdwc = platform_get_drvdata(pdev);
struct device_node *node = pdev->dev.of_node;
@@ -198,8 +198,6 @@ static int kdwc3_remove(struct platform_device *pdev)
phy_pm_runtime_put_sync(kdwc->usb3_phy);
platform_set_drvdata(pdev, NULL);
-
- return 0;
}
static const struct of_device_id kdwc3_of_match[] = {
@@ -211,7 +209,7 @@ MODULE_DEVICE_TABLE(of, kdwc3_of_match);
static struct platform_driver kdwc3_driver = {
.probe = kdwc3_probe,
- .remove = kdwc3_remove,
+ .remove_new = kdwc3_remove,
.driver = {
.name = "keystone-dwc3",
.of_match_table = kdwc3_of_match,
diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
index b282ad0e69c6..e99c7489dba0 100644
--- a/drivers/usb/dwc3/dwc3-meson-g12a.c
+++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
@@ -140,7 +140,6 @@ static const char * const meson_a1_phy_names[] = {
struct dwc3_meson_g12a;
struct dwc3_meson_g12a_drvdata {
- bool otg_switch_supported;
bool otg_phy_host_port_disable;
struct clk_bulk_data *clks;
int num_clks;
@@ -189,7 +188,6 @@ static int dwc3_meson_gxl_usb_post_init(struct dwc3_meson_g12a *priv);
*/
static const struct dwc3_meson_g12a_drvdata gxl_drvdata = {
- .otg_switch_supported = true,
.otg_phy_host_port_disable = true,
.clks = meson_gxl_clocks,
.num_clks = ARRAY_SIZE(meson_g12a_clocks),
@@ -203,7 +201,6 @@ static const struct dwc3_meson_g12a_drvdata gxl_drvdata = {
};
static const struct dwc3_meson_g12a_drvdata gxm_drvdata = {
- .otg_switch_supported = true,
.otg_phy_host_port_disable = true,
.clks = meson_gxl_clocks,
.num_clks = ARRAY_SIZE(meson_g12a_clocks),
@@ -217,7 +214,6 @@ static const struct dwc3_meson_g12a_drvdata gxm_drvdata = {
};
static const struct dwc3_meson_g12a_drvdata axg_drvdata = {
- .otg_switch_supported = true,
.clks = meson_gxl_clocks,
.num_clks = ARRAY_SIZE(meson_gxl_clocks),
.phy_names = meson_a1_phy_names,
@@ -230,7 +226,6 @@ static const struct dwc3_meson_g12a_drvdata axg_drvdata = {
};
static const struct dwc3_meson_g12a_drvdata g12a_drvdata = {
- .otg_switch_supported = true,
.clks = meson_g12a_clocks,
.num_clks = ARRAY_SIZE(meson_g12a_clocks),
.phy_names = meson_g12a_phy_names,
@@ -242,7 +237,6 @@ static const struct dwc3_meson_g12a_drvdata g12a_drvdata = {
};
static const struct dwc3_meson_g12a_drvdata a1_drvdata = {
- .otg_switch_supported = false,
.clks = meson_a1_clocks,
.num_clks = ARRAY_SIZE(meson_a1_clocks),
.phy_names = meson_a1_phy_names,
@@ -307,7 +301,7 @@ static int dwc3_meson_g12a_usb2_init_phy(struct dwc3_meson_g12a *priv, int i,
U2P_R0_POWER_ON_RESET,
U2P_R0_POWER_ON_RESET);
- if (priv->drvdata->otg_switch_supported && i == USB2_OTG_PHY) {
+ if (i == USB2_OTG_PHY) {
regmap_update_bits(priv->u2p_regmap[i], U2P_R0,
U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS,
U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS);
@@ -490,7 +484,7 @@ static int dwc3_meson_g12a_otg_mode_set(struct dwc3_meson_g12a *priv,
{
int ret;
- if (!priv->drvdata->otg_switch_supported || !priv->phys[USB2_OTG_PHY])
+ if (!priv->phys[USB2_OTG_PHY])
return -EINVAL;
if (mode == PHY_MODE_USB_HOST)
@@ -589,9 +583,6 @@ static int dwc3_meson_g12a_otg_init(struct platform_device *pdev,
int ret, irq;
struct device *dev = &pdev->dev;
- if (!priv->drvdata->otg_switch_supported)
- return 0;
-
if (priv->otg_mode == USB_DR_MODE_OTG) {
/* Ack irq before registering */
regmap_update_bits(priv->usb_glue_regmap, USB_R5,
@@ -805,7 +796,7 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev)
ret = dwc3_meson_g12a_otg_init(pdev, priv);
if (ret)
- goto err_phys_power;
+ goto err_plat_depopulate;
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
@@ -813,6 +804,9 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev)
return 0;
+err_plat_depopulate:
+ of_platform_depopulate(dev);
+
err_phys_power:
for (i = 0 ; i < PHY_COUNT ; ++i)
phy_power_off(priv->phys[i]);
@@ -835,14 +829,13 @@ err_disable_clks:
return ret;
}
-static int dwc3_meson_g12a_remove(struct platform_device *pdev)
+static void dwc3_meson_g12a_remove(struct platform_device *pdev)
{
struct dwc3_meson_g12a *priv = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
int i;
- if (priv->drvdata->otg_switch_supported)
- usb_role_switch_unregister(priv->role_switch);
+ usb_role_switch_unregister(priv->role_switch);
of_platform_depopulate(dev);
@@ -859,8 +852,6 @@ static int dwc3_meson_g12a_remove(struct platform_device *pdev)
clk_bulk_disable_unprepare(priv->drvdata->num_clks,
priv->drvdata->clks);
-
- return 0;
}
static int __maybe_unused dwc3_meson_g12a_runtime_suspend(struct device *dev)
@@ -971,7 +962,7 @@ MODULE_DEVICE_TABLE(of, dwc3_meson_g12a_match);
static struct platform_driver dwc3_meson_g12a_driver = {
.probe = dwc3_meson_g12a_probe,
- .remove = dwc3_meson_g12a_remove,
+ .remove_new = dwc3_meson_g12a_remove,
.driver = {
.name = "dwc3-meson-g12a",
.of_match_table = dwc3_meson_g12a_match,
diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c
index 71fd620c5161..7e6ad8fe61a5 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -112,13 +112,11 @@ static void __dwc3_of_simple_teardown(struct dwc3_of_simple *simple)
pm_runtime_set_suspended(simple->dev);
}
-static int dwc3_of_simple_remove(struct platform_device *pdev)
+static void dwc3_of_simple_remove(struct platform_device *pdev)
{
struct dwc3_of_simple *simple = platform_get_drvdata(pdev);
__dwc3_of_simple_teardown(simple);
-
- return 0;
}
static void dwc3_of_simple_shutdown(struct platform_device *pdev)
@@ -183,7 +181,7 @@ MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
static struct platform_driver dwc3_of_simple_driver = {
.probe = dwc3_of_simple_probe,
- .remove = dwc3_of_simple_remove,
+ .remove_new = dwc3_of_simple_remove,
.shutdown = dwc3_of_simple_shutdown,
.driver = {
.name = "dwc3-of-simple",
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index efaf0db595f4..d5c77db4daa9 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -534,7 +534,7 @@ err1:
return ret;
}
-static int dwc3_omap_remove(struct platform_device *pdev)
+static void dwc3_omap_remove(struct platform_device *pdev)
{
struct dwc3_omap *omap = platform_get_drvdata(pdev);
@@ -543,8 +543,6 @@ static int dwc3_omap_remove(struct platform_device *pdev)
of_platform_depopulate(omap->dev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
static const struct of_device_id of_dwc3_match[] = {
@@ -611,7 +609,7 @@ static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
static struct platform_driver dwc3_omap_driver = {
.probe = dwc3_omap_probe,
- .remove = dwc3_omap_remove,
+ .remove_new = dwc3_omap_remove,
.driver = {
.name = "omap-dwc3",
.of_match_table = of_dwc3_match,
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index 79b22abf9727..3de43df6bbe8 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -167,7 +167,8 @@ static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom)
qcom->edev = extcon_get_edev_by_phandle(dev, 0);
if (IS_ERR(qcom->edev))
- return PTR_ERR(qcom->edev);
+ return dev_err_probe(dev, PTR_ERR(qcom->edev),
+ "Failed to get extcon\n");
qcom->vbus_nb.notifier_call = dwc3_qcom_vbus_notifier;
@@ -252,16 +253,14 @@ static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom)
qcom->icc_path_ddr = of_icc_get(dev, "usb-ddr");
if (IS_ERR(qcom->icc_path_ddr)) {
- dev_err(dev, "failed to get usb-ddr path: %ld\n",
- PTR_ERR(qcom->icc_path_ddr));
- return PTR_ERR(qcom->icc_path_ddr);
+ return dev_err_probe(dev, PTR_ERR(qcom->icc_path_ddr),
+ "failed to get usb-ddr path\n");
}
qcom->icc_path_apps = of_icc_get(dev, "apps-usb");
if (IS_ERR(qcom->icc_path_apps)) {
- dev_err(dev, "failed to get apps-usb path: %ld\n",
- PTR_ERR(qcom->icc_path_apps));
- ret = PTR_ERR(qcom->icc_path_apps);
+ ret = dev_err_probe(dev, PTR_ERR(qcom->icc_path_apps),
+ "failed to get apps-usb path\n");
goto put_path_ddr;
}
@@ -800,6 +799,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct dwc3_qcom *qcom;
struct resource *res, *parent_res = NULL;
+ struct resource local_res;
int ret, i;
bool ignore_pipe_clk;
bool wakeup_source;
@@ -821,9 +821,8 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
qcom->resets = devm_reset_control_array_get_optional_exclusive(dev);
if (IS_ERR(qcom->resets)) {
- ret = PTR_ERR(qcom->resets);
- dev_err(&pdev->dev, "failed to get resets, err=%d\n", ret);
- return ret;
+ return dev_err_probe(&pdev->dev, PTR_ERR(qcom->resets),
+ "failed to get resets\n");
}
ret = reset_control_assert(qcom->resets);
@@ -842,7 +841,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
ret = dwc3_qcom_clk_init(qcom, of_clk_get_parent_count(np));
if (ret) {
- dev_err(dev, "failed to get clocks\n");
+ dev_err_probe(dev, ret, "failed to get clocks\n");
goto reset_assert;
}
@@ -851,9 +850,8 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
if (np) {
parent_res = res;
} else {
- parent_res = kmemdup(res, sizeof(struct resource), GFP_KERNEL);
- if (!parent_res)
- return -ENOMEM;
+ memcpy(&local_res, res, sizeof(struct resource));
+ parent_res = &local_res;
parent_res->start = res->start +
qcom->acpi_pdata->qscratch_base_offset;
@@ -865,9 +863,10 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
if (IS_ERR_OR_NULL(qcom->urs_usb)) {
dev_err(dev, "failed to create URS USB platdev\n");
if (!qcom->urs_usb)
- return -ENODEV;
+ ret = -ENODEV;
else
- return PTR_ERR(qcom->urs_usb);
+ ret = PTR_ERR(qcom->urs_usb);
+ goto clk_disable;
}
}
}
@@ -947,14 +946,18 @@ reset_assert:
return ret;
}
-static int dwc3_qcom_remove(struct platform_device *pdev)
+static void dwc3_qcom_remove(struct platform_device *pdev)
{
struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
+ struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
int i;
device_remove_software_node(&qcom->dwc3->dev);
- of_platform_depopulate(dev);
+ if (np)
+ of_platform_depopulate(&pdev->dev);
+ else
+ platform_device_put(pdev);
for (i = qcom->num_clocks - 1; i >= 0; i--) {
clk_disable_unprepare(qcom->clks[i]);
@@ -967,8 +970,6 @@ static int dwc3_qcom_remove(struct platform_device *pdev)
pm_runtime_allow(dev);
pm_runtime_disable(dev);
-
- return 0;
}
static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev)
@@ -1061,7 +1062,7 @@ MODULE_DEVICE_TABLE(acpi, dwc3_qcom_acpi_match);
static struct platform_driver dwc3_qcom_driver = {
.probe = dwc3_qcom_probe,
- .remove = dwc3_qcom_remove,
+ .remove_new = dwc3_qcom_remove,
.driver = {
.name = "dwc3-qcom",
.pm = &dwc3_qcom_dev_pm_ops,
diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c
index fea5290de83f..211360eee95a 100644
--- a/drivers/usb/dwc3/dwc3-st.c
+++ b/drivers/usb/dwc3/dwc3-st.c
@@ -305,7 +305,7 @@ undo_platform_dev_alloc:
return ret;
}
-static int st_dwc3_remove(struct platform_device *pdev)
+static void st_dwc3_remove(struct platform_device *pdev)
{
struct st_dwc3 *dwc3_data = platform_get_drvdata(pdev);
@@ -313,8 +313,6 @@ static int st_dwc3_remove(struct platform_device *pdev)
reset_control_assert(dwc3_data->rstc_pwrdn);
reset_control_assert(dwc3_data->rstc_rst);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -364,7 +362,7 @@ MODULE_DEVICE_TABLE(of, st_dwc3_match);
static struct platform_driver st_dwc3_driver = {
.probe = st_dwc3_probe,
- .remove = st_dwc3_remove,
+ .remove_new = st_dwc3_remove,
.driver = {
.name = "usb-st-dwc3",
.of_match_table = st_dwc3_match,
diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index 2c36f97652ca..19307d24f3a0 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -305,7 +305,7 @@ err_clk_put:
return ret;
}
-static int dwc3_xlnx_remove(struct platform_device *pdev)
+static void dwc3_xlnx_remove(struct platform_device *pdev)
{
struct dwc3_xlnx *priv_data = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
@@ -318,8 +318,6 @@ static int dwc3_xlnx_remove(struct platform_device *pdev)
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
pm_runtime_set_suspended(dev);
-
- return 0;
}
static int __maybe_unused dwc3_xlnx_runtime_suspend(struct device *dev)
@@ -388,7 +386,7 @@ static const struct dev_pm_ops dwc3_xlnx_dev_pm_ops = {
static struct platform_driver dwc3_xlnx_driver = {
.probe = dwc3_xlnx_probe,
- .remove = dwc3_xlnx_remove,
+ .remove_new = dwc3_xlnx_remove,
.driver = {
.name = "dwc3-xilinx",
.of_match_table = dwc3_xlnx_of_match,
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 953b752a5052..b94243237293 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -1207,5 +1207,8 @@ void dwc3_ep0_interrupt(struct dwc3 *dwc,
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
}
break;
+ default:
+ dev_err(dwc->dev, "unknown endpoint event %d\n", event->endpoint_event);
+ break;
}
}
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index b78599dd705c..5fd067151fbf 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2703,13 +2703,17 @@ static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc)
static int dwc3_gadget_soft_connect(struct dwc3 *dwc)
{
+ int ret;
+
/*
* In the Synopsys DWC_usb31 1.90a programming guide section
* 4.1.9, it specifies that for a reconnect after a
* device-initiated disconnect requires a core soft reset
* (DCTL.CSftRst) before enabling the run/stop bit.
*/
- dwc3_core_soft_reset(dwc);
+ ret = dwc3_core_soft_reset(dwc);
+ if (ret)
+ return ret;
dwc3_event_buffers_setup(dwc);
__dwc3_gadget_start(dwc);
@@ -2744,7 +2748,9 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
ret = pm_runtime_get_sync(dwc->dev);
if (!ret || ret < 0) {
pm_runtime_put(dwc->dev);
- return 0;
+ if (ret < 0)
+ pm_runtime_set_suspended(dwc->dev);
+ return ret;
}
if (dwc->pullups_connected == is_on) {
@@ -3809,6 +3815,9 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
break;
case DWC3_DEPEVT_RXTXFIFOEVT:
break;
+ default:
+ dev_err(dwc->dev, "unknown endpoint event %d\n", event->endpoint_event);
+ break;
}
}
diff --git a/drivers/usb/fotg210/fotg210-core.c b/drivers/usb/fotg210/fotg210-core.c
index cb75464ab290..958fc40eae86 100644
--- a/drivers/usb/fotg210/fotg210-core.c
+++ b/drivers/usb/fotg210/fotg210-core.c
@@ -165,7 +165,7 @@ static int fotg210_probe(struct platform_device *pdev)
return ret;
}
-static int fotg210_remove(struct platform_device *pdev)
+static void fotg210_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
enum usb_dr_mode mode;
@@ -176,8 +176,6 @@ static int fotg210_remove(struct platform_device *pdev)
fotg210_udc_remove(pdev);
else
fotg210_hcd_remove(pdev);
-
- return 0;
}
#ifdef CONFIG_OF
@@ -196,7 +194,7 @@ static struct platform_driver fotg210_driver = {
.of_match_table = of_match_ptr(fotg210_of_match),
},
.probe = fotg210_probe,
- .remove = fotg210_remove,
+ .remove_new = fotg210_remove,
};
static int __init fotg210_init(void)
diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
index 9f6b10134121..ea85e2c701a1 100644
--- a/drivers/usb/gadget/function/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
@@ -23,7 +23,11 @@
#define HIDG_MINORS 4
static int major, minors;
-static struct class *hidg_class;
+
+static const struct class hidg_class = {
+ .name = "hidg",
+};
+
static DEFINE_IDA(hidg_ida);
static DEFINE_MUTEX(hidg_ida_lock); /* protects access to hidg_ida */
@@ -1272,7 +1276,7 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi)
device_initialize(&hidg->dev);
hidg->dev.release = hidg_release;
- hidg->dev.class = hidg_class;
+ hidg->dev.class = &hidg_class;
hidg->dev.devt = MKDEV(major, opts->minor);
ret = dev_set_name(&hidg->dev, "hidg%d", opts->minor);
if (ret)
@@ -1325,17 +1329,13 @@ int ghid_setup(struct usb_gadget *g, int count)
int status;
dev_t dev;
- hidg_class = class_create("hidg");
- if (IS_ERR(hidg_class)) {
- status = PTR_ERR(hidg_class);
- hidg_class = NULL;
+ status = class_register(&hidg_class);
+ if (status)
return status;
- }
status = alloc_chrdev_region(&dev, 0, count, "hidg");
if (status) {
- class_destroy(hidg_class);
- hidg_class = NULL;
+ class_unregister(&hidg_class);
return status;
}
@@ -1352,6 +1352,5 @@ void ghid_cleanup(void)
major = minors = 0;
}
- class_destroy(hidg_class);
- hidg_class = NULL;
+ class_unregister(&hidg_class);
}
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index 3a30feb47073..da07e45ae6df 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -2857,7 +2857,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
const char **name_pfx)
{
struct fsg_lun *lun;
- char *pathbuf, *p;
+ char *pathbuf = NULL, *p = "(no medium)";
int rc = -ENOMEM;
if (id >= ARRAY_SIZE(common->luns))
@@ -2907,12 +2907,9 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
rc = fsg_lun_open(lun, cfg->filename);
if (rc)
goto error_lun;
- }
- pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
- p = "(no medium)";
- if (fsg_lun_is_open(lun)) {
p = "(error)";
+ pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
if (pathbuf) {
p = file_path(lun->filp, pathbuf, PATH_MAX);
if (IS_ERR(p))
@@ -2931,7 +2928,6 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
error_lun:
if (device_is_registered(&lun->dev))
device_unregister(&lun->dev);
- fsg_lun_close(lun);
common->luns[id] = NULL;
error_sysfs:
kfree(lun);
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c
index 28db3e336e7d..076dd4c1be96 100644
--- a/drivers/usb/gadget/function/f_printer.c
+++ b/drivers/usb/gadget/function/f_printer.c
@@ -54,7 +54,10 @@
#define DEFAULT_Q_LEN 10 /* same as legacy g_printer gadget */
static int major, minors;
-static struct class *usb_gadget_class;
+static const struct class usb_gadget_class = {
+ .name = "usb_printer_gadget",
+};
+
static DEFINE_IDA(printer_ida);
static DEFINE_MUTEX(printer_ida_lock); /* protects access do printer_ida */
@@ -1120,7 +1123,7 @@ autoconf_fail:
/* Setup the sysfs files for the printer gadget. */
devt = MKDEV(major, dev->minor);
- pdev = device_create(usb_gadget_class, NULL, devt,
+ pdev = device_create(&usb_gadget_class, NULL, devt,
NULL, "g_printer%d", dev->minor);
if (IS_ERR(pdev)) {
ERROR(dev, "Failed to create device: g_printer\n");
@@ -1143,7 +1146,7 @@ autoconf_fail:
return 0;
fail_cdev_add:
- device_destroy(usb_gadget_class, devt);
+ device_destroy(&usb_gadget_class, devt);
fail_rx_reqs:
while (!list_empty(&dev->rx_reqs)) {
@@ -1211,8 +1214,8 @@ static ssize_t f_printer_opts_pnp_string_show(struct config_item *item,
if (!opts->pnp_string)
goto unlock;
- result = strlcpy(page, opts->pnp_string, PAGE_SIZE);
- if (result >= PAGE_SIZE) {
+ result = strscpy(page, opts->pnp_string, PAGE_SIZE);
+ if (result < 1) {
result = PAGE_SIZE;
} else if (page[result - 1] != '\n' && result + 1 < PAGE_SIZE) {
page[result++] = '\n';
@@ -1410,7 +1413,7 @@ static void printer_func_unbind(struct usb_configuration *c,
dev = func_to_printer(f);
- device_destroy(usb_gadget_class, MKDEV(major, dev->minor));
+ device_destroy(&usb_gadget_class, MKDEV(major, dev->minor));
/* Remove Character Device */
cdev_del(&dev->printer_cdev);
@@ -1512,19 +1515,14 @@ static int gprinter_setup(int count)
int status;
dev_t devt;
- usb_gadget_class = class_create("usb_printer_gadget");
- if (IS_ERR(usb_gadget_class)) {
- status = PTR_ERR(usb_gadget_class);
- usb_gadget_class = NULL;
- pr_err("unable to create usb_gadget class %d\n", status);
+ status = class_register(&usb_gadget_class);
+ if (status)
return status;
- }
status = alloc_chrdev_region(&devt, 0, count, "USB printer gadget");
if (status) {
pr_err("alloc_chrdev_region %d\n", status);
- class_destroy(usb_gadget_class);
- usb_gadget_class = NULL;
+ class_unregister(&usb_gadget_class);
return status;
}
@@ -1540,6 +1538,5 @@ static void gprinter_cleanup(void)
unregister_chrdev_region(MKDEV(major, 0), minors);
major = minors = 0;
}
- class_destroy(usb_gadget_class);
- usb_gadget_class = NULL;
+ class_unregister(&usb_gadget_class);
}
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c
index a0ca47fbff0f..1115396b46a0 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -539,16 +539,20 @@ static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head,
static int gs_start_io(struct gs_port *port)
{
struct list_head *head = &port->read_pool;
- struct usb_ep *ep = port->port_usb->out;
+ struct usb_ep *ep;
int status;
unsigned started;
+ if (!port->port_usb || !port->port.tty)
+ return -EIO;
+
/* Allocate RX and TX I/O buffers. We can't easily do this much
* earlier (with GFP_KERNEL) because the requests are coupled to
* endpoints, as are the packet sizes we'll be using. Different
* configurations may use different endpoints with a given port;
* and high speed vs full speed changes packet sizes too.
*/
+ ep = port->port_usb->out;
status = gs_alloc_requests(ep, head, gs_read_complete,
&port->read_allocated);
if (status)
@@ -916,8 +920,11 @@ static void __gs_console_push(struct gs_console *cons)
}
req->length = size;
+
+ spin_unlock_irq(&cons->lock);
if (usb_ep_queue(ep, req, GFP_ATOMIC))
req->length = 0;
+ spin_lock_irq(&cons->lock);
}
static void gs_console_work(struct work_struct *work)
@@ -1420,10 +1427,19 @@ EXPORT_SYMBOL_GPL(gserial_disconnect);
void gserial_suspend(struct gserial *gser)
{
- struct gs_port *port = gser->ioport;
+ struct gs_port *port;
unsigned long flags;
- spin_lock_irqsave(&port->port_lock, flags);
+ spin_lock_irqsave(&serial_port_lock, flags);
+ port = gser->ioport;
+
+ if (!port) {
+ spin_unlock_irqrestore(&serial_port_lock, flags);
+ return;
+ }
+
+ spin_lock(&port->port_lock);
+ spin_unlock(&serial_port_lock);
port->suspended = true;
spin_unlock_irqrestore(&port->port_lock, flags);
}
diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c
index dd1c6b2ca7c6..91af3b1ef0d4 100644
--- a/drivers/usb/gadget/function/uvc_video.c
+++ b/drivers/usb/gadget/function/uvc_video.c
@@ -382,9 +382,12 @@ static void uvcg_video_pump(struct work_struct *work)
{
struct uvc_video *video = container_of(work, struct uvc_video, pump);
struct uvc_video_queue *queue = &video->queue;
+ /* video->max_payload_size is only set when using bulk transfer */
+ bool is_bulk = video->max_payload_size;
struct usb_request *req = NULL;
struct uvc_buffer *buf;
unsigned long flags;
+ bool buf_done;
int ret;
while (video->ep->enabled) {
@@ -408,20 +411,47 @@ static void uvcg_video_pump(struct work_struct *work)
*/
spin_lock_irqsave(&queue->irqlock, flags);
buf = uvcg_queue_head(queue);
- if (buf == NULL) {
+
+ if (buf != NULL) {
+ video->encode(req, video, buf);
+ buf_done = buf->state == UVC_BUF_STATE_DONE;
+ } else if (!(queue->flags & UVC_QUEUE_DISCONNECTED) && !is_bulk) {
+ /*
+ * No video buffer available; the queue is still connected and
+ * we're transferring over ISOC. Queue a 0 length request to
+ * prevent missed ISOC transfers.
+ */
+ req->length = 0;
+ buf_done = false;
+ } else {
+ /*
+ * Either the queue has been disconnected or no video buffer
+ * available for bulk transfer. Either way, stop processing
+ * further.
+ */
spin_unlock_irqrestore(&queue->irqlock, flags);
break;
}
- video->encode(req, video, buf);
-
/*
- * With usb3 we have more requests. This will decrease the
- * interrupt load to a quarter but also catches the corner
- * cases, which needs to be handled.
+ * With USB3 handling more requests at a higher speed, we can't
+ * afford to generate an interrupt for every request. Decide to
+ * interrupt:
+ *
+ * - When no more requests are available in the free queue, as
+ * this may be our last chance to refill the endpoint's
+ * request queue.
+ *
+ * - When this is request is the last request for the video
+ * buffer, as we want to start sending the next video buffer
+ * ASAP in case it doesn't get started already in the next
+ * iteration of this loop.
+ *
+ * - Four times over the length of the requests queue (as
+ * indicated by video->uvc_num_requests), as a trade-off
+ * between latency and interrupt load.
*/
- if (list_empty(&video->req_free) ||
- buf->state == UVC_BUF_STATE_DONE ||
+ if (list_empty(&video->req_free) || buf_done ||
!(video->req_int_count %
DIV_ROUND_UP(video->uvc_num_requests, 4))) {
video->req_int_count = 0;
@@ -441,8 +471,7 @@ static void uvcg_video_pump(struct work_struct *work)
/* Endpoint now owns the request */
req = NULL;
- if (buf->state != UVC_BUF_STATE_DONE)
- video->req_int_count++;
+ video->req_int_count++;
}
if (!req)
@@ -527,4 +556,3 @@ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc)
V4L2_BUF_TYPE_VIDEO_OUTPUT, &video->mutex);
return 0;
}
-
diff --git a/drivers/usb/gadget/legacy/g_ffs.c b/drivers/usb/gadget/legacy/g_ffs.c
index 097854683e5b..a9544fea8723 100644
--- a/drivers/usb/gadget/legacy/g_ffs.c
+++ b/drivers/usb/gadget/legacy/g_ffs.c
@@ -389,8 +389,10 @@ static int gfs_bind(struct usb_composite_dev *cdev)
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
- if (!usb_desc)
+ if (!usb_desc) {
+ ret = -ENOMEM;
goto error_rndis;
+ }
usb_otg_descriptor_init(cdev->gadget, usb_desc);
gfs_otg_desc[0] = usb_desc;
gfs_otg_desc[1] = NULL;
diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c
index 133daf88162e..4ca67b2f8f24 100644
--- a/drivers/usb/gadget/legacy/hid.c
+++ b/drivers/usb/gadget/legacy/hid.c
@@ -237,7 +237,7 @@ static int hidg_plat_driver_probe(struct platform_device *pdev)
return 0;
}
-static int hidg_plat_driver_remove(struct platform_device *pdev)
+static void hidg_plat_driver_remove(struct platform_device *pdev)
{
struct hidg_func_node *e, *n;
@@ -245,8 +245,6 @@ static int hidg_plat_driver_remove(struct platform_device *pdev)
list_del(&e->node);
kfree(e);
}
-
- return 0;
}
@@ -263,7 +261,7 @@ static struct usb_composite_driver hidg_driver = {
};
static struct platform_driver hidg_plat_driver = {
- .remove = hidg_plat_driver_remove,
+ .remove_new = hidg_plat_driver_remove,
.driver = {
.name = "hidg",
},
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
index 83cae6bb12eb..aae1787320d4 100644
--- a/drivers/usb/gadget/udc/Kconfig
+++ b/drivers/usb/gadget/udc/Kconfig
@@ -463,6 +463,8 @@ config USB_ASPEED_UDC
source "drivers/usb/gadget/udc/aspeed-vhub/Kconfig"
+source "drivers/usb/gadget/udc/cdns2/Kconfig"
+
#
# LAST -- dummy/emulated controller
#
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
index ee569f63c74a..b52f93e9c61d 100644
--- a/drivers/usb/gadget/udc/Makefile
+++ b/drivers/usb/gadget/udc/Makefile
@@ -42,3 +42,4 @@ obj-$(CONFIG_USB_ASPEED_VHUB) += aspeed-vhub/
obj-$(CONFIG_USB_ASPEED_UDC) += aspeed_udc.o
obj-$(CONFIG_USB_BDC_UDC) += bdc/
obj-$(CONFIG_USB_MAX3420_UDC) += max3420_udc.o
+obj-$(CONFIG_USB_CDNS2_UDC) += cdns2/
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c
index 86398a04a012..16f2db8c4a2b 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/core.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c
@@ -253,14 +253,14 @@ void ast_vhub_init_hw(struct ast_vhub *vhub)
vhub->regs + AST_VHUB_IER);
}
-static int ast_vhub_remove(struct platform_device *pdev)
+static void ast_vhub_remove(struct platform_device *pdev)
{
struct ast_vhub *vhub = platform_get_drvdata(pdev);
unsigned long flags;
int i;
if (!vhub || !vhub->regs)
- return 0;
+ return;
/* Remove devices */
for (i = 0; i < vhub->max_ports; i++)
@@ -289,8 +289,6 @@ static int ast_vhub_remove(struct platform_device *pdev)
vhub->ep0_bufs,
vhub->ep0_bufs_dma);
vhub->ep0_bufs = NULL;
-
- return 0;
}
static int ast_vhub_probe(struct platform_device *pdev)
@@ -431,7 +429,7 @@ MODULE_DEVICE_TABLE(of, ast_vhub_dt_ids);
static struct platform_driver ast_vhub_driver = {
.probe = ast_vhub_probe,
- .remove = ast_vhub_remove,
+ .remove_new = ast_vhub_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = ast_vhub_dt_ids,
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index 53ca38c4b3ec..6c0ed3fa5eb1 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -2369,7 +2369,7 @@ static int usba_udc_probe(struct platform_device *pdev)
return 0;
}
-static int usba_udc_remove(struct platform_device *pdev)
+static void usba_udc_remove(struct platform_device *pdev)
{
struct usba_udc *udc;
int i;
@@ -2382,8 +2382,6 @@ static int usba_udc_remove(struct platform_device *pdev)
for (i = 1; i < udc->num_ep; i++)
usba_ep_cleanup_debugfs(&udc->usba_ep[i]);
usba_cleanup_debugfs(udc);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -2450,7 +2448,7 @@ static SIMPLE_DEV_PM_OPS(usba_udc_pm_ops, usba_udc_suspend, usba_udc_resume);
static struct platform_driver udc_driver = {
.probe = usba_udc_probe,
- .remove = usba_udc_remove,
+ .remove_new = usba_udc_remove,
.driver = {
.name = "atmel_usba_udc",
.pm = &usba_udc_pm_ops,
diff --git a/drivers/usb/gadget/udc/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c
index a3055dd4acfb..da7011d906e0 100644
--- a/drivers/usb/gadget/udc/bcm63xx_udc.c
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
@@ -2354,7 +2354,7 @@ report_request_failure:
* bcm63xx_udc_remove - Remove the device from the system.
* @pdev: Platform device struct from the bcm63xx BSP code.
*/
-static int bcm63xx_udc_remove(struct platform_device *pdev)
+static void bcm63xx_udc_remove(struct platform_device *pdev)
{
struct bcm63xx_udc *udc = platform_get_drvdata(pdev);
@@ -2363,13 +2363,11 @@ static int bcm63xx_udc_remove(struct platform_device *pdev)
BUG_ON(udc->driver);
bcm63xx_uninit_udc_hw(udc);
-
- return 0;
}
static struct platform_driver bcm63xx_udc_driver = {
.probe = bcm63xx_udc_probe,
- .remove = bcm63xx_udc_remove,
+ .remove_new = bcm63xx_udc_remove,
.driver = {
.name = DRV_MODULE_NAME,
},
diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c
index 9849e0c86e23..35a652807fca 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_core.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_core.c
@@ -583,7 +583,7 @@ disable_clk:
return ret;
}
-static int bdc_remove(struct platform_device *pdev)
+static void bdc_remove(struct platform_device *pdev)
{
struct bdc *bdc;
@@ -593,7 +593,6 @@ static int bdc_remove(struct platform_device *pdev)
bdc_hw_exit(bdc);
bdc_phy_exit(bdc);
clk_disable_unprepare(bdc->clk);
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -648,7 +647,7 @@ static struct platform_driver bdc_driver = {
.of_match_table = bdc_of_match,
},
.probe = bdc_probe,
- .remove = bdc_remove,
+ .remove_new = bdc_remove,
};
module_platform_driver(bdc_driver);
diff --git a/drivers/usb/gadget/udc/cdns2/Kconfig b/drivers/usb/gadget/udc/cdns2/Kconfig
new file mode 100644
index 000000000000..c07d353903ea
--- /dev/null
+++ b/drivers/usb/gadget/udc/cdns2/Kconfig
@@ -0,0 +1,11 @@
+config USB_CDNS2_UDC
+ tristate "Cadence USBHS Device Controller"
+ depends on USB_PCI && ACPI && HAS_DMA
+ help
+ Cadence USBHS Device controller is a PCI based USB peripheral
+ controller which supports both full and high speed USB 2.0
+ data transfers.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "cdns2-udc-pci.ko" and to
+ force all gadget drivers to also be dynamically linked.
diff --git a/drivers/usb/gadget/udc/cdns2/Makefile b/drivers/usb/gadget/udc/cdns2/Makefile
new file mode 100644
index 000000000000..a1ffbbe2e768
--- /dev/null
+++ b/drivers/usb/gadget/udc/cdns2/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+# define_trace.h needs to know how to find our header
+CFLAGS_cdns2-trace.o := -I$(src)
+
+obj-$(CONFIG_USB_CDNS2_UDC) += cdns2-udc-pci.o
+cdns2-udc-pci-$(CONFIG_USB_CDNS2_UDC) += cdns2-pci.o cdns2-gadget.o cdns2-ep0.o
+cdns2-udc-pci-$(CONFIG_TRACING) += cdns2-trace.o
diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-debug.h b/drivers/usb/gadget/udc/cdns2/cdns2-debug.h
new file mode 100644
index 000000000000..be9ae0d28a40
--- /dev/null
+++ b/drivers/usb/gadget/udc/cdns2/cdns2-debug.h
@@ -0,0 +1,203 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Cadence USBHS-DEV Driver.
+ * Debug header file.
+ *
+ * Copyright (C) 2023 Cadence.
+ *
+ * Author: Pawel Laszczak <pawell@cadence.com>
+ */
+
+#ifndef __LINUX_CDNS2_DEBUG
+#define __LINUX_CDNS2_DEBUG
+
+static inline const char *cdns2_decode_usb_irq(char *str, size_t size,
+ u8 usb_irq, u8 ext_irq)
+{
+ int ret;
+
+ ret = snprintf(str, size, "usbirq: 0x%02x - ", usb_irq);
+
+ if (usb_irq & USBIRQ_SOF)
+ ret += snprintf(str + ret, size - ret, "SOF ");
+ if (usb_irq & USBIRQ_SUTOK)
+ ret += snprintf(str + ret, size - ret, "SUTOK ");
+ if (usb_irq & USBIRQ_SUDAV)
+ ret += snprintf(str + ret, size - ret, "SETUP ");
+ if (usb_irq & USBIRQ_SUSPEND)
+ ret += snprintf(str + ret, size - ret, "Suspend ");
+ if (usb_irq & USBIRQ_URESET)
+ ret += snprintf(str + ret, size - ret, "Reset ");
+ if (usb_irq & USBIRQ_HSPEED)
+ ret += snprintf(str + ret, size - ret, "HS ");
+ if (usb_irq & USBIRQ_LPM)
+ ret += snprintf(str + ret, size - ret, "LPM ");
+
+ ret += snprintf(str + ret, size - ret, ", EXT: 0x%02x - ", ext_irq);
+
+ if (ext_irq & EXTIRQ_WAKEUP)
+ ret += snprintf(str + ret, size - ret, "Wakeup ");
+ if (ext_irq & EXTIRQ_VBUSFAULT_FALL)
+ ret += snprintf(str + ret, size - ret, "VBUS_FALL ");
+ if (ext_irq & EXTIRQ_VBUSFAULT_RISE)
+ ret += snprintf(str + ret, size - ret, "VBUS_RISE ");
+
+ if (ret >= size)
+ pr_info("CDNS2: buffer overflowed.\n");
+
+ return str;
+}
+
+static inline const char *cdns2_decode_dma_irq(char *str, size_t size,
+ u32 ep_ists, u32 ep_sts,
+ const char *ep_name)
+{
+ int ret;
+
+ ret = snprintf(str, size, "ISTS: %08x, %s: %08x ",
+ ep_ists, ep_name, ep_sts);
+
+ if (ep_sts & DMA_EP_STS_IOC)
+ ret += snprintf(str + ret, size - ret, "IOC ");
+ if (ep_sts & DMA_EP_STS_ISP)
+ ret += snprintf(str + ret, size - ret, "ISP ");
+ if (ep_sts & DMA_EP_STS_DESCMIS)
+ ret += snprintf(str + ret, size - ret, "DESCMIS ");
+ if (ep_sts & DMA_EP_STS_TRBERR)
+ ret += snprintf(str + ret, size - ret, "TRBERR ");
+ if (ep_sts & DMA_EP_STS_OUTSMM)
+ ret += snprintf(str + ret, size - ret, "OUTSMM ");
+ if (ep_sts & DMA_EP_STS_ISOERR)
+ ret += snprintf(str + ret, size - ret, "ISOERR ");
+ if (ep_sts & DMA_EP_STS_DBUSY)
+ ret += snprintf(str + ret, size - ret, "DBUSY ");
+ if (DMA_EP_STS_CCS(ep_sts))
+ ret += snprintf(str + ret, size - ret, "CCS ");
+
+ if (ret >= size)
+ pr_info("CDNS2: buffer overflowed.\n");
+
+ return str;
+}
+
+static inline const char *cdns2_decode_epx_irq(char *str, size_t size,
+ char *ep_name, u32 ep_ists,
+ u32 ep_sts)
+{
+ return cdns2_decode_dma_irq(str, size, ep_ists, ep_sts, ep_name);
+}
+
+static inline const char *cdns2_decode_ep0_irq(char *str, size_t size,
+ u32 ep_ists, u32 ep_sts,
+ int dir)
+{
+ return cdns2_decode_dma_irq(str, size, ep_ists, ep_sts,
+ dir ? "ep0IN" : "ep0OUT");
+}
+
+static inline const char *cdns2_raw_ring(struct cdns2_endpoint *pep,
+ struct cdns2_trb *trbs,
+ char *str, size_t size)
+{
+ struct cdns2_ring *ring = &pep->ring;
+ struct cdns2_trb *trb;
+ dma_addr_t dma;
+ int ret;
+ int i;
+
+ ret = snprintf(str, size, "\n\t\tTR for %s:", pep->name);
+
+ trb = &trbs[ring->dequeue];
+ dma = cdns2_trb_virt_to_dma(pep, trb);
+ ret += snprintf(str + ret, size - ret,
+ "\n\t\tRing deq index: %d, trb: V=%p, P=0x%pad\n",
+ ring->dequeue, trb, &dma);
+
+ trb = &trbs[ring->enqueue];
+ dma = cdns2_trb_virt_to_dma(pep, trb);
+ ret += snprintf(str + ret, size - ret,
+ "\t\tRing enq index: %d, trb: V=%p, P=0x%pad\n",
+ ring->enqueue, trb, &dma);
+
+ ret += snprintf(str + ret, size - ret,
+ "\t\tfree trbs: %d, CCS=%d, PCS=%d\n",
+ ring->free_trbs, ring->ccs, ring->pcs);
+
+ if (TRBS_PER_SEGMENT > 40) {
+ ret += snprintf(str + ret, size - ret,
+ "\t\tTransfer ring %d too big\n", TRBS_PER_SEGMENT);
+ return str;
+ }
+
+ dma = ring->dma;
+ for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
+ trb = &trbs[i];
+ ret += snprintf(str + ret, size - ret,
+ "\t\t@%pad %08x %08x %08x\n", &dma,
+ le32_to_cpu(trb->buffer),
+ le32_to_cpu(trb->length),
+ le32_to_cpu(trb->control));
+ dma += sizeof(*trb);
+ }
+
+ if (ret >= size)
+ pr_info("CDNS2: buffer overflowed.\n");
+
+ return str;
+}
+
+static inline const char *cdns2_trb_type_string(u8 type)
+{
+ switch (type) {
+ case TRB_NORMAL:
+ return "Normal";
+ case TRB_LINK:
+ return "Link";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static inline const char *cdns2_decode_trb(char *str, size_t size, u32 flags,
+ u32 length, u32 buffer)
+{
+ int type = TRB_FIELD_TO_TYPE(flags);
+ int ret;
+
+ switch (type) {
+ case TRB_LINK:
+ ret = snprintf(str, size,
+ "LINK %08x type '%s' flags %c:%c:%c%c:%c",
+ buffer, cdns2_trb_type_string(type),
+ flags & TRB_CYCLE ? 'C' : 'c',
+ flags & TRB_TOGGLE ? 'T' : 't',
+ flags & TRB_CHAIN ? 'C' : 'c',
+ flags & TRB_CHAIN ? 'H' : 'h',
+ flags & TRB_IOC ? 'I' : 'i');
+ break;
+ case TRB_NORMAL:
+ ret = snprintf(str, size,
+ "type: '%s', Buffer: %08x, length: %ld, burst len: %ld, "
+ "flags %c:%c:%c%c:%c",
+ cdns2_trb_type_string(type),
+ buffer, TRB_LEN(length),
+ TRB_FIELD_TO_BURST(length),
+ flags & TRB_CYCLE ? 'C' : 'c',
+ flags & TRB_ISP ? 'I' : 'i',
+ flags & TRB_CHAIN ? 'C' : 'c',
+ flags & TRB_CHAIN ? 'H' : 'h',
+ flags & TRB_IOC ? 'I' : 'i');
+ break;
+ default:
+ ret = snprintf(str, size, "type '%s' -> raw %08x %08x %08x",
+ cdns2_trb_type_string(type),
+ buffer, length, flags);
+ }
+
+ if (ret >= size)
+ pr_info("CDNS2: buffer overflowed.\n");
+
+ return str;
+}
+
+#endif /*__LINUX_CDNS2_DEBUG*/
diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-ep0.c b/drivers/usb/gadget/udc/cdns2/cdns2-ep0.c
new file mode 100644
index 000000000000..fa12a5d46f2e
--- /dev/null
+++ b/drivers/usb/gadget/udc/cdns2/cdns2-ep0.c
@@ -0,0 +1,659 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Cadence USBHS-DEV driver.
+ *
+ * Copyright (C) 2023 Cadence Design Systems.
+ *
+ * Authors: Pawel Laszczak <pawell@cadence.com>
+ */
+
+#include <linux/usb/composite.h>
+#include <asm/unaligned.h>
+
+#include "cdns2-gadget.h"
+#include "cdns2-trace.h"
+
+static struct usb_endpoint_descriptor cdns2_gadget_ep0_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
+ .wMaxPacketSize = cpu_to_le16(64)
+};
+
+static int cdns2_w_index_to_ep_index(u16 wIndex)
+{
+ if (!(wIndex & USB_ENDPOINT_NUMBER_MASK))
+ return 0;
+
+ return ((wIndex & USB_ENDPOINT_NUMBER_MASK) * 2) +
+ (wIndex & USB_ENDPOINT_DIR_MASK ? 1 : 0) - 1;
+}
+
+static bool cdns2_check_new_setup(struct cdns2_device *pdev)
+{
+ u8 reg;
+
+ reg = readb(&pdev->ep0_regs->cs);
+
+ return !!(reg & EP0CS_CHGSET);
+}
+
+static void cdns2_ep0_enqueue(struct cdns2_device *pdev, dma_addr_t dma_addr,
+ unsigned int length, int zlp)
+{
+ struct cdns2_adma_regs __iomem *regs = pdev->adma_regs;
+ struct cdns2_endpoint *pep = &pdev->eps[0];
+ struct cdns2_ring *ring = &pep->ring;
+
+ ring->trbs[0].buffer = cpu_to_le32(TRB_BUFFER(dma_addr));
+ ring->trbs[0].length = cpu_to_le32(TRB_LEN(length));
+
+ if (zlp) {
+ ring->trbs[0].control = cpu_to_le32(TRB_CYCLE |
+ TRB_TYPE(TRB_NORMAL));
+ ring->trbs[1].buffer = cpu_to_le32(TRB_BUFFER(dma_addr));
+ ring->trbs[1].length = cpu_to_le32(TRB_LEN(0));
+ ring->trbs[1].control = cpu_to_le32(TRB_CYCLE | TRB_IOC |
+ TRB_TYPE(TRB_NORMAL));
+ } else {
+ ring->trbs[0].control = cpu_to_le32(TRB_CYCLE | TRB_IOC |
+ TRB_TYPE(TRB_NORMAL));
+ ring->trbs[1].control = 0;
+ }
+
+ trace_cdns2_queue_trb(pep, ring->trbs);
+
+ if (!pep->dir)
+ writel(0, &pdev->ep0_regs->rxbc);
+
+ cdns2_select_ep(pdev, pep->dir);
+
+ writel(DMA_EP_STS_TRBERR, &regs->ep_sts);
+ writel(pep->ring.dma, &regs->ep_traddr);
+
+ trace_cdns2_doorbell_ep0(pep, readl(&regs->ep_traddr));
+
+ writel(DMA_EP_CMD_DRDY, &regs->ep_cmd);
+}
+
+static int cdns2_ep0_delegate_req(struct cdns2_device *pdev)
+{
+ int ret;
+
+ spin_unlock(&pdev->lock);
+ ret = pdev->gadget_driver->setup(&pdev->gadget, &pdev->setup);
+ spin_lock(&pdev->lock);
+
+ return ret;
+}
+
+static void cdns2_ep0_stall(struct cdns2_device *pdev)
+{
+ struct cdns2_endpoint *pep = &pdev->eps[0];
+ struct cdns2_request *preq;
+
+ preq = cdns2_next_preq(&pep->pending_list);
+ set_reg_bit_8(&pdev->ep0_regs->cs, EP0CS_DSTALL);
+
+ if (pdev->ep0_stage == CDNS2_DATA_STAGE && preq)
+ cdns2_gadget_giveback(pep, preq, -ECONNRESET);
+ else if (preq)
+ list_del_init(&preq->list);
+
+ pdev->ep0_stage = CDNS2_SETUP_STAGE;
+ pep->ep_state |= EP_STALLED;
+}
+
+static void cdns2_status_stage(struct cdns2_device *pdev)
+{
+ struct cdns2_endpoint *pep = &pdev->eps[0];
+ struct cdns2_request *preq;
+
+ preq = cdns2_next_preq(&pep->pending_list);
+ if (preq)
+ list_del_init(&preq->list);
+
+ pdev->ep0_stage = CDNS2_SETUP_STAGE;
+ writeb(EP0CS_HSNAK, &pdev->ep0_regs->cs);
+}
+
+static int cdns2_req_ep0_set_configuration(struct cdns2_device *pdev,
+ struct usb_ctrlrequest *ctrl_req)
+{
+ enum usb_device_state state = pdev->gadget.state;
+ u32 config = le16_to_cpu(ctrl_req->wValue);
+ int ret;
+
+ if (state < USB_STATE_ADDRESS) {
+ dev_err(pdev->dev, "Set Configuration - bad device state\n");
+ return -EINVAL;
+ }
+
+ ret = cdns2_ep0_delegate_req(pdev);
+ if (ret)
+ return ret;
+
+ trace_cdns2_device_state(config ? "configured" : "addressed");
+
+ if (!config)
+ usb_gadget_set_state(&pdev->gadget, USB_STATE_ADDRESS);
+
+ return 0;
+}
+
+static int cdns2_req_ep0_set_address(struct cdns2_device *pdev, u32 addr)
+{
+ enum usb_device_state device_state = pdev->gadget.state;
+ u8 reg;
+
+ if (addr > USB_DEVICE_MAX_ADDRESS) {
+ dev_err(pdev->dev,
+ "Device address (%d) cannot be greater than %d\n",
+ addr, USB_DEVICE_MAX_ADDRESS);
+ return -EINVAL;
+ }
+
+ if (device_state == USB_STATE_CONFIGURED) {
+ dev_err(pdev->dev,
+ "can't set_address from configured state\n");
+ return -EINVAL;
+ }
+
+ reg = readb(&pdev->usb_regs->fnaddr);
+ pdev->dev_address = reg;
+
+ usb_gadget_set_state(&pdev->gadget,
+ (addr ? USB_STATE_ADDRESS : USB_STATE_DEFAULT));
+
+ trace_cdns2_device_state(addr ? "addressed" : "default");
+
+ return 0;
+}
+
+static int cdns2_req_ep0_handle_status(struct cdns2_device *pdev,
+ struct usb_ctrlrequest *ctrl)
+{
+ struct cdns2_endpoint *pep;
+ __le16 *response_pkt;
+ u16 status = 0;
+ int ep_sts;
+ u32 recip;
+
+ recip = ctrl->bRequestType & USB_RECIP_MASK;
+
+ switch (recip) {
+ case USB_RECIP_DEVICE:
+ status = pdev->gadget.is_selfpowered;
+ status |= pdev->may_wakeup << USB_DEVICE_REMOTE_WAKEUP;
+ break;
+ case USB_RECIP_INTERFACE:
+ return cdns2_ep0_delegate_req(pdev);
+ case USB_RECIP_ENDPOINT:
+ ep_sts = cdns2_w_index_to_ep_index(le16_to_cpu(ctrl->wIndex));
+ pep = &pdev->eps[ep_sts];
+
+ if (pep->ep_state & EP_STALLED)
+ status = BIT(USB_ENDPOINT_HALT);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ put_unaligned_le16(status, (__le16 *)pdev->ep0_preq.request.buf);
+
+ cdns2_ep0_enqueue(pdev, pdev->ep0_preq.request.dma,
+ sizeof(*response_pkt), 0);
+
+ return 0;
+}
+
+static int cdns2_ep0_handle_feature_device(struct cdns2_device *pdev,
+ struct usb_ctrlrequest *ctrl,
+ int set)
+{
+ enum usb_device_state state;
+ enum usb_device_speed speed;
+ int ret = 0;
+ u32 wValue;
+ u16 tmode;
+
+ wValue = le16_to_cpu(ctrl->wValue);
+ state = pdev->gadget.state;
+ speed = pdev->gadget.speed;
+
+ switch (wValue) {
+ case USB_DEVICE_REMOTE_WAKEUP:
+ pdev->may_wakeup = !!set;
+ break;
+ case USB_DEVICE_TEST_MODE:
+ if (state != USB_STATE_CONFIGURED || speed > USB_SPEED_HIGH)
+ return -EINVAL;
+
+ tmode = le16_to_cpu(ctrl->wIndex);
+
+ if (!set || (tmode & 0xff) != 0)
+ return -EINVAL;
+
+ tmode >>= 8;
+ switch (tmode) {
+ case USB_TEST_J:
+ case USB_TEST_K:
+ case USB_TEST_SE0_NAK:
+ case USB_TEST_PACKET:
+ /*
+ * The USBHS controller automatically handles the
+ * Set_Feature(testmode) request. Standard test modes
+ * that use values of test mode selector from
+ * 01h to 04h (Test_J, Test_K, Test_SE0_NAK,
+ * Test_Packet) are supported by the
+ * controller(HS - ack, FS - stall).
+ */
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int cdns2_ep0_handle_feature_intf(struct cdns2_device *pdev,
+ struct usb_ctrlrequest *ctrl,
+ int set)
+{
+ int ret = 0;
+ u32 wValue;
+
+ wValue = le16_to_cpu(ctrl->wValue);
+
+ switch (wValue) {
+ case USB_INTRF_FUNC_SUSPEND:
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int cdns2_ep0_handle_feature_endpoint(struct cdns2_device *pdev,
+ struct usb_ctrlrequest *ctrl,
+ int set)
+{
+ struct cdns2_endpoint *pep;
+ u8 wValue;
+
+ wValue = le16_to_cpu(ctrl->wValue);
+ pep = &pdev->eps[cdns2_w_index_to_ep_index(le16_to_cpu(ctrl->wIndex))];
+
+ if (wValue != USB_ENDPOINT_HALT)
+ return -EINVAL;
+
+ if (!(le16_to_cpu(ctrl->wIndex) & ~USB_DIR_IN))
+ return 0;
+
+ switch (wValue) {
+ case USB_ENDPOINT_HALT:
+ if (set || !(pep->ep_state & EP_WEDGE))
+ return cdns2_halt_endpoint(pdev, pep, set);
+ break;
+ default:
+ dev_warn(pdev->dev, "WARN Incorrect wValue %04x\n", wValue);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cdns2_req_ep0_handle_feature(struct cdns2_device *pdev,
+ struct usb_ctrlrequest *ctrl,
+ int set)
+{
+ switch (ctrl->bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ return cdns2_ep0_handle_feature_device(pdev, ctrl, set);
+ case USB_RECIP_INTERFACE:
+ return cdns2_ep0_handle_feature_intf(pdev, ctrl, set);
+ case USB_RECIP_ENDPOINT:
+ return cdns2_ep0_handle_feature_endpoint(pdev, ctrl, set);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int cdns2_ep0_std_request(struct cdns2_device *pdev)
+{
+ struct usb_ctrlrequest *ctrl = &pdev->setup;
+ int ret;
+
+ switch (ctrl->bRequest) {
+ case USB_REQ_SET_ADDRESS:
+ ret = cdns2_req_ep0_set_address(pdev,
+ le16_to_cpu(ctrl->wValue));
+ break;
+ case USB_REQ_SET_CONFIGURATION:
+ ret = cdns2_req_ep0_set_configuration(pdev, ctrl);
+ break;
+ case USB_REQ_GET_STATUS:
+ ret = cdns2_req_ep0_handle_status(pdev, ctrl);
+ break;
+ case USB_REQ_CLEAR_FEATURE:
+ ret = cdns2_req_ep0_handle_feature(pdev, ctrl, 0);
+ break;
+ case USB_REQ_SET_FEATURE:
+ ret = cdns2_req_ep0_handle_feature(pdev, ctrl, 1);
+ break;
+ default:
+ ret = cdns2_ep0_delegate_req(pdev);
+ break;
+ }
+
+ return ret;
+}
+
+static void __pending_setup_status_handler(struct cdns2_device *pdev)
+{
+ struct usb_request *request = pdev->pending_status_request;
+
+ if (pdev->status_completion_no_call && request && request->complete) {
+ request->complete(&pdev->eps[0].endpoint, request);
+ pdev->status_completion_no_call = 0;
+ }
+}
+
+void cdns2_pending_setup_status_handler(struct work_struct *work)
+{
+ struct cdns2_device *pdev = container_of(work, struct cdns2_device,
+ pending_status_wq);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdev->lock, flags);
+ __pending_setup_status_handler(pdev);
+ spin_unlock_irqrestore(&pdev->lock, flags);
+}
+
+void cdns2_handle_setup_packet(struct cdns2_device *pdev)
+{
+ struct usb_ctrlrequest *ctrl = &pdev->setup;
+ struct cdns2_endpoint *pep = &pdev->eps[0];
+ struct cdns2_request *preq;
+ int ret = 0;
+ u16 len;
+ u8 reg;
+ int i;
+
+ writeb(EP0CS_CHGSET, &pdev->ep0_regs->cs);
+
+ for (i = 0; i < 8; i++)
+ ((u8 *)&pdev->setup)[i] = readb(&pdev->ep0_regs->setupdat[i]);
+
+ /*
+ * If SETUP packet was modified while reading just simple ignore it.
+ * The new one will be handled latter.
+ */
+ if (cdns2_check_new_setup(pdev)) {
+ trace_cdns2_ep0_setup("overridden");
+ return;
+ }
+
+ trace_cdns2_ctrl_req(ctrl);
+
+ if (!pdev->gadget_driver)
+ goto out;
+
+ if (pdev->gadget.state == USB_STATE_NOTATTACHED) {
+ dev_err(pdev->dev, "ERR: Setup detected in unattached state\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pep = &pdev->eps[0];
+
+ /* Halt for Ep0 is cleared automatically when SETUP packet arrives. */
+ pep->ep_state &= ~EP_STALLED;
+
+ if (!list_empty(&pep->pending_list)) {
+ preq = cdns2_next_preq(&pep->pending_list);
+ cdns2_gadget_giveback(pep, preq, -ECONNRESET);
+ }
+
+ len = le16_to_cpu(ctrl->wLength);
+ if (len)
+ pdev->ep0_stage = CDNS2_DATA_STAGE;
+ else
+ pdev->ep0_stage = CDNS2_STATUS_STAGE;
+
+ pep->dir = ctrl->bRequestType & USB_DIR_IN;
+
+ /*
+ * SET_ADDRESS request is acknowledged automatically by controller and
+ * in the worse case driver may not notice this request. To check
+ * whether this request has been processed driver can use
+ * fnaddr register.
+ */
+ reg = readb(&pdev->usb_regs->fnaddr);
+ if (pdev->setup.bRequest != USB_REQ_SET_ADDRESS &&
+ pdev->dev_address != reg)
+ cdns2_req_ep0_set_address(pdev, reg);
+
+ if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD)
+ ret = cdns2_ep0_std_request(pdev);
+ else
+ ret = cdns2_ep0_delegate_req(pdev);
+
+ if (ret == USB_GADGET_DELAYED_STATUS) {
+ trace_cdns2_ep0_status_stage("delayed");
+ return;
+ }
+
+out:
+ if (ret < 0)
+ cdns2_ep0_stall(pdev);
+ else if (pdev->ep0_stage == CDNS2_STATUS_STAGE)
+ cdns2_status_stage(pdev);
+}
+
+static void cdns2_transfer_completed(struct cdns2_device *pdev)
+{
+ struct cdns2_endpoint *pep = &pdev->eps[0];
+
+ if (!list_empty(&pep->pending_list)) {
+ struct cdns2_request *preq;
+
+ trace_cdns2_complete_trb(pep, pep->ring.trbs);
+ preq = cdns2_next_preq(&pep->pending_list);
+
+ preq->request.actual =
+ TRB_LEN(le32_to_cpu(pep->ring.trbs->length));
+ cdns2_gadget_giveback(pep, preq, 0);
+ }
+
+ cdns2_status_stage(pdev);
+}
+
+void cdns2_handle_ep0_interrupt(struct cdns2_device *pdev, int dir)
+{
+ u32 ep_sts_reg;
+
+ cdns2_select_ep(pdev, dir);
+
+ trace_cdns2_ep0_irq(pdev);
+
+ ep_sts_reg = readl(&pdev->adma_regs->ep_sts);
+ writel(ep_sts_reg, &pdev->adma_regs->ep_sts);
+
+ __pending_setup_status_handler(pdev);
+
+ if ((ep_sts_reg & DMA_EP_STS_IOC) || (ep_sts_reg & DMA_EP_STS_ISP)) {
+ pdev->eps[0].dir = dir;
+ cdns2_transfer_completed(pdev);
+ }
+}
+
+/*
+ * Function shouldn't be called by gadget driver,
+ * endpoint 0 is allways active.
+ */
+static int cdns2_gadget_ep0_enable(struct usb_ep *ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ return -EINVAL;
+}
+
+/*
+ * Function shouldn't be called by gadget driver,
+ * endpoint 0 is allways active.
+ */
+static int cdns2_gadget_ep0_disable(struct usb_ep *ep)
+{
+ return -EINVAL;
+}
+
+static int cdns2_gadget_ep0_set_halt(struct usb_ep *ep, int value)
+{
+ struct cdns2_endpoint *pep = ep_to_cdns2_ep(ep);
+ struct cdns2_device *pdev = pep->pdev;
+ unsigned long flags;
+
+ if (!value)
+ return 0;
+
+ spin_lock_irqsave(&pdev->lock, flags);
+ cdns2_ep0_stall(pdev);
+ spin_unlock_irqrestore(&pdev->lock, flags);
+
+ return 0;
+}
+
+static int cdns2_gadget_ep0_set_wedge(struct usb_ep *ep)
+{
+ return cdns2_gadget_ep0_set_halt(ep, 1);
+}
+
+static int cdns2_gadget_ep0_queue(struct usb_ep *ep,
+ struct usb_request *request,
+ gfp_t gfp_flags)
+{
+ struct cdns2_endpoint *pep = ep_to_cdns2_ep(ep);
+ struct cdns2_device *pdev = pep->pdev;
+ struct cdns2_request *preq;
+ unsigned long flags;
+ u8 zlp = 0;
+ int ret;
+
+ spin_lock_irqsave(&pdev->lock, flags);
+
+ preq = to_cdns2_request(request);
+
+ trace_cdns2_request_enqueue(preq);
+
+ /* Cancel the request if controller receive new SETUP packet. */
+ if (cdns2_check_new_setup(pdev)) {
+ trace_cdns2_ep0_setup("overridden");
+ spin_unlock_irqrestore(&pdev->lock, flags);
+ return -ECONNRESET;
+ }
+
+ /* Send STATUS stage. Should be called only for SET_CONFIGURATION. */
+ if (pdev->ep0_stage == CDNS2_STATUS_STAGE) {
+ cdns2_status_stage(pdev);
+
+ request->actual = 0;
+ pdev->status_completion_no_call = true;
+ pdev->pending_status_request = request;
+ usb_gadget_set_state(&pdev->gadget, USB_STATE_CONFIGURED);
+ spin_unlock_irqrestore(&pdev->lock, flags);
+
+ /*
+ * Since there is no completion interrupt for status stage,
+ * it needs to call ->completion in software after
+ * cdns2_gadget_ep0_queue is back.
+ */
+ queue_work(system_freezable_wq, &pdev->pending_status_wq);
+ return 0;
+ }
+
+ if (!list_empty(&pep->pending_list)) {
+ trace_cdns2_ep0_setup("pending");
+ dev_err(pdev->dev,
+ "can't handle multiple requests for ep0\n");
+ spin_unlock_irqrestore(&pdev->lock, flags);
+ return -EBUSY;
+ }
+
+ ret = usb_gadget_map_request_by_dev(pdev->dev, request, pep->dir);
+ if (ret) {
+ spin_unlock_irqrestore(&pdev->lock, flags);
+ dev_err(pdev->dev, "failed to map request\n");
+ return -EINVAL;
+ }
+
+ request->status = -EINPROGRESS;
+ list_add_tail(&preq->list, &pep->pending_list);
+
+ if (request->zero && request->length &&
+ (request->length % ep->maxpacket == 0))
+ zlp = 1;
+
+ cdns2_ep0_enqueue(pdev, request->dma, request->length, zlp);
+
+ spin_unlock_irqrestore(&pdev->lock, flags);
+
+ return 0;
+}
+
+static const struct usb_ep_ops cdns2_gadget_ep0_ops = {
+ .enable = cdns2_gadget_ep0_enable,
+ .disable = cdns2_gadget_ep0_disable,
+ .alloc_request = cdns2_gadget_ep_alloc_request,
+ .free_request = cdns2_gadget_ep_free_request,
+ .queue = cdns2_gadget_ep0_queue,
+ .dequeue = cdns2_gadget_ep_dequeue,
+ .set_halt = cdns2_gadget_ep0_set_halt,
+ .set_wedge = cdns2_gadget_ep0_set_wedge,
+};
+
+void cdns2_ep0_config(struct cdns2_device *pdev)
+{
+ struct cdns2_endpoint *pep;
+
+ pep = &pdev->eps[0];
+
+ if (!list_empty(&pep->pending_list)) {
+ struct cdns2_request *preq;
+
+ preq = cdns2_next_preq(&pep->pending_list);
+ list_del_init(&preq->list);
+ }
+
+ writeb(EP0_FIFO_AUTO, &pdev->ep0_regs->fifo);
+ cdns2_select_ep(pdev, USB_DIR_OUT);
+ writel(DMA_EP_CFG_ENABLE, &pdev->adma_regs->ep_cfg);
+
+ writeb(EP0_FIFO_IO_TX | EP0_FIFO_AUTO, &pdev->ep0_regs->fifo);
+ cdns2_select_ep(pdev, USB_DIR_IN);
+ writel(DMA_EP_CFG_ENABLE, &pdev->adma_regs->ep_cfg);
+
+ writeb(pdev->gadget.ep0->maxpacket, &pdev->ep0_regs->maxpack);
+ writel(DMA_EP_IEN_EP_OUT0 | DMA_EP_IEN_EP_IN0,
+ &pdev->adma_regs->ep_ien);
+}
+
+void cdns2_init_ep0(struct cdns2_device *pdev,
+ struct cdns2_endpoint *pep)
+{
+ u16 maxpacket = le16_to_cpu(cdns2_gadget_ep0_desc.wMaxPacketSize);
+
+ usb_ep_set_maxpacket_limit(&pep->endpoint, maxpacket);
+
+ pep->endpoint.ops = &cdns2_gadget_ep0_ops;
+ pep->endpoint.desc = &cdns2_gadget_ep0_desc;
+ pep->endpoint.caps.type_control = true;
+ pep->endpoint.caps.dir_in = true;
+ pep->endpoint.caps.dir_out = true;
+
+ pdev->gadget.ep0 = &pep->endpoint;
+}
diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c
new file mode 100644
index 000000000000..0eed0e03842c
--- /dev/null
+++ b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c
@@ -0,0 +1,2474 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Cadence USBHS-DEV Driver - gadget side.
+ *
+ * Copyright (C) 2023 Cadence Design Systems.
+ *
+ * Authors: Pawel Laszczak <pawell@cadence.com>
+ */
+
+/*
+ * Work around 1:
+ * At some situations, the controller may get stale data address in TRB
+ * at below sequences:
+ * 1. Controller read TRB includes data address
+ * 2. Software updates TRBs includes data address and Cycle bit
+ * 3. Controller read TRB which includes Cycle bit
+ * 4. DMA run with stale data address
+ *
+ * To fix this problem, driver needs to make the first TRB in TD as invalid.
+ * After preparing all TRBs driver needs to check the position of DMA and
+ * if the DMA point to the first just added TRB and doorbell is 1,
+ * then driver must defer making this TRB as valid. This TRB will be make
+ * as valid during adding next TRB only if DMA is stopped or at TRBERR
+ * interrupt.
+ *
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/pm_runtime.h>
+#include <linux/interrupt.h>
+#include <linux/property.h>
+#include <linux/dmapool.h>
+#include <linux/iopoll.h>
+
+#include "cdns2-gadget.h"
+#include "cdns2-trace.h"
+
+/**
+ * set_reg_bit_32 - set bit in given 32 bits register.
+ * @ptr: register address.
+ * @mask: bits to set.
+ */
+static void set_reg_bit_32(void __iomem *ptr, u32 mask)
+{
+ mask = readl(ptr) | mask;
+ writel(mask, ptr);
+}
+
+/*
+ * clear_reg_bit_32 - clear bit in given 32 bits register.
+ * @ptr: register address.
+ * @mask: bits to clear.
+ */
+static void clear_reg_bit_32(void __iomem *ptr, u32 mask)
+{
+ mask = readl(ptr) & ~mask;
+ writel(mask, ptr);
+}
+
+/* Clear bit in given 8 bits register. */
+static void clear_reg_bit_8(void __iomem *ptr, u8 mask)
+{
+ mask = readb(ptr) & ~mask;
+ writeb(mask, ptr);
+}
+
+/* Set bit in given 16 bits register. */
+void set_reg_bit_8(void __iomem *ptr, u8 mask)
+{
+ mask = readb(ptr) | mask;
+ writeb(mask, ptr);
+}
+
+static int cdns2_get_dma_pos(struct cdns2_device *pdev,
+ struct cdns2_endpoint *pep)
+{
+ int dma_index;
+
+ dma_index = readl(&pdev->adma_regs->ep_traddr) - pep->ring.dma;
+
+ return dma_index / TRB_SIZE;
+}
+
+/* Get next private request from list. */
+struct cdns2_request *cdns2_next_preq(struct list_head *list)
+{
+ return list_first_entry_or_null(list, struct cdns2_request, list);
+}
+
+void cdns2_select_ep(struct cdns2_device *pdev, u32 ep)
+{
+ if (pdev->selected_ep == ep)
+ return;
+
+ pdev->selected_ep = ep;
+ writel(ep, &pdev->adma_regs->ep_sel);
+}
+
+dma_addr_t cdns2_trb_virt_to_dma(struct cdns2_endpoint *pep,
+ struct cdns2_trb *trb)
+{
+ u32 offset = (char *)trb - (char *)pep->ring.trbs;
+
+ return pep->ring.dma + offset;
+}
+
+static void cdns2_free_tr_segment(struct cdns2_endpoint *pep)
+{
+ struct cdns2_device *pdev = pep->pdev;
+ struct cdns2_ring *ring = &pep->ring;
+
+ if (pep->ring.trbs) {
+ dma_pool_free(pdev->eps_dma_pool, ring->trbs, ring->dma);
+ memset(ring, 0, sizeof(*ring));
+ }
+}
+
+/* Allocates Transfer Ring segment. */
+static int cdns2_alloc_tr_segment(struct cdns2_endpoint *pep)
+{
+ struct cdns2_device *pdev = pep->pdev;
+ struct cdns2_trb *link_trb;
+ struct cdns2_ring *ring;
+
+ ring = &pep->ring;
+
+ if (!ring->trbs) {
+ ring->trbs = dma_pool_alloc(pdev->eps_dma_pool,
+ GFP_DMA32 | GFP_ATOMIC,
+ &ring->dma);
+ if (!ring->trbs)
+ return -ENOMEM;
+ }
+
+ memset(ring->trbs, 0, TR_SEG_SIZE);
+
+ if (!pep->num)
+ return 0;
+
+ /* Initialize the last TRB as Link TRB */
+ link_trb = (ring->trbs + (TRBS_PER_SEGMENT - 1));
+ link_trb->buffer = cpu_to_le32(TRB_BUFFER(ring->dma));
+ link_trb->control = cpu_to_le32(TRB_CYCLE | TRB_TYPE(TRB_LINK) |
+ TRB_TOGGLE);
+
+ return 0;
+}
+
+/*
+ * Stalls and flushes selected endpoint.
+ * Endpoint must be selected before invoking this function.
+ */
+static void cdns2_ep_stall_flush(struct cdns2_endpoint *pep)
+{
+ struct cdns2_device *pdev = pep->pdev;
+ int val;
+
+ trace_cdns2_ep_halt(pep, 1, 1);
+
+ writel(DMA_EP_CMD_DFLUSH, &pdev->adma_regs->ep_cmd);
+
+ /* Wait for DFLUSH cleared. */
+ readl_poll_timeout_atomic(&pdev->adma_regs->ep_cmd, val,
+ !(val & DMA_EP_CMD_DFLUSH), 1, 1000);
+ pep->ep_state |= EP_STALLED;
+ pep->ep_state &= ~EP_STALL_PENDING;
+}
+
+/*
+ * Increment a trb index.
+ *
+ * The index should never point to the last link TRB in TR. After incrementing,
+ * if it point to the link TRB, wrap around to the beginning and revert
+ * cycle state bit. The link TRB is always at the last TRB entry.
+ */
+static void cdns2_ep_inc_trb(int *index, u8 *cs, int trb_in_seg)
+{
+ (*index)++;
+ if (*index == (trb_in_seg - 1)) {
+ *index = 0;
+ *cs ^= 1;
+ }
+}
+
+static void cdns2_ep_inc_enq(struct cdns2_ring *ring)
+{
+ ring->free_trbs--;
+ cdns2_ep_inc_trb(&ring->enqueue, &ring->pcs, TRBS_PER_SEGMENT);
+}
+
+static void cdns2_ep_inc_deq(struct cdns2_ring *ring)
+{
+ ring->free_trbs++;
+ cdns2_ep_inc_trb(&ring->dequeue, &ring->ccs, TRBS_PER_SEGMENT);
+}
+
+/*
+ * Enable/disable LPM.
+ *
+ * If bit USBCS_LPMNYET is not set and device receive Extended Token packet,
+ * then controller answer with ACK handshake.
+ * If bit USBCS_LPMNYET is set and device receive Extended Token packet,
+ * then controller answer with NYET handshake.
+ */
+static void cdns2_enable_l1(struct cdns2_device *pdev, int enable)
+{
+ if (enable) {
+ clear_reg_bit_8(&pdev->usb_regs->usbcs, USBCS_LPMNYET);
+ writeb(LPMCLOCK_SLEEP_ENTRY, &pdev->usb_regs->lpmclock);
+ } else {
+ set_reg_bit_8(&pdev->usb_regs->usbcs, USBCS_LPMNYET);
+ }
+}
+
+static enum usb_device_speed cdns2_get_speed(struct cdns2_device *pdev)
+{
+ u8 speed = readb(&pdev->usb_regs->speedctrl);
+
+ if (speed & SPEEDCTRL_HS)
+ return USB_SPEED_HIGH;
+ else if (speed & SPEEDCTRL_FS)
+ return USB_SPEED_FULL;
+
+ return USB_SPEED_UNKNOWN;
+}
+
+static struct cdns2_trb *cdns2_next_trb(struct cdns2_endpoint *pep,
+ struct cdns2_trb *trb)
+{
+ if (trb == (pep->ring.trbs + (TRBS_PER_SEGMENT - 1)))
+ return pep->ring.trbs;
+ else
+ return ++trb;
+}
+
+void cdns2_gadget_giveback(struct cdns2_endpoint *pep,
+ struct cdns2_request *preq,
+ int status)
+{
+ struct usb_request *request = &preq->request;
+ struct cdns2_device *pdev = pep->pdev;
+
+ list_del_init(&preq->list);
+
+ if (request->status == -EINPROGRESS)
+ request->status = status;
+
+ usb_gadget_unmap_request_by_dev(pdev->dev, request, pep->dir);
+
+ /* All TRBs have finished, clear the counter. */
+ preq->finished_trb = 0;
+
+ trace_cdns2_request_giveback(preq);
+
+ if (request->complete) {
+ spin_unlock(&pdev->lock);
+ usb_gadget_giveback_request(&pep->endpoint, request);
+ spin_lock(&pdev->lock);
+ }
+
+ if (request->buf == pdev->zlp_buf)
+ cdns2_gadget_ep_free_request(&pep->endpoint, request);
+}
+
+static void cdns2_wa1_restore_cycle_bit(struct cdns2_endpoint *pep)
+{
+ /* Work around for stale data address in TRB. */
+ if (pep->wa1_set) {
+ trace_cdns2_wa1(pep, "restore cycle bit");
+
+ pep->wa1_set = 0;
+ pep->wa1_trb_index = 0xFFFF;
+ if (pep->wa1_cycle_bit)
+ pep->wa1_trb->control |= cpu_to_le32(0x1);
+ else
+ pep->wa1_trb->control &= cpu_to_le32(~0x1);
+ }
+}
+
+static int cdns2_wa1_update_guard(struct cdns2_endpoint *pep,
+ struct cdns2_trb *trb)
+{
+ struct cdns2_device *pdev = pep->pdev;
+
+ if (!pep->wa1_set) {
+ u32 doorbell;
+
+ doorbell = !!(readl(&pdev->adma_regs->ep_cmd) & DMA_EP_CMD_DRDY);
+
+ if (doorbell) {
+ pep->wa1_cycle_bit = pep->ring.pcs ? TRB_CYCLE : 0;
+ pep->wa1_set = 1;
+ pep->wa1_trb = trb;
+ pep->wa1_trb_index = pep->ring.enqueue;
+ trace_cdns2_wa1(pep, "set guard");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void cdns2_wa1_tray_restore_cycle_bit(struct cdns2_device *pdev,
+ struct cdns2_endpoint *pep)
+{
+ int dma_index;
+ u32 doorbell;
+
+ doorbell = !!(readl(&pdev->adma_regs->ep_cmd) & DMA_EP_CMD_DRDY);
+ dma_index = cdns2_get_dma_pos(pdev, pep);
+
+ if (!doorbell || dma_index != pep->wa1_trb_index)
+ cdns2_wa1_restore_cycle_bit(pep);
+}
+
+static int cdns2_prepare_ring(struct cdns2_device *pdev,
+ struct cdns2_endpoint *pep,
+ int num_trbs)
+{
+ struct cdns2_trb *link_trb = NULL;
+ int doorbell, dma_index;
+ struct cdns2_ring *ring;
+ u32 ch_bit = 0;
+
+ ring = &pep->ring;
+
+ if (num_trbs > ring->free_trbs) {
+ pep->ep_state |= EP_RING_FULL;
+ trace_cdns2_no_room_on_ring("Ring full\n");
+ return -ENOBUFS;
+ }
+
+ if ((ring->enqueue + num_trbs) >= (TRBS_PER_SEGMENT - 1)) {
+ doorbell = !!(readl(&pdev->adma_regs->ep_cmd) & DMA_EP_CMD_DRDY);
+ dma_index = cdns2_get_dma_pos(pdev, pep);
+
+ /* Driver can't update LINK TRB if it is current processed. */
+ if (doorbell && dma_index == TRBS_PER_SEGMENT - 1) {
+ pep->ep_state |= EP_DEFERRED_DRDY;
+ return -ENOBUFS;
+ }
+
+ /* Update C bt in Link TRB before starting DMA. */
+ link_trb = ring->trbs + (TRBS_PER_SEGMENT - 1);
+
+ /*
+ * For TRs size equal 2 enabling TRB_CHAIN for epXin causes
+ * that DMA stuck at the LINK TRB.
+ * On the other hand, removing TRB_CHAIN for longer TRs for
+ * epXout cause that DMA stuck after handling LINK TRB.
+ * To eliminate this strange behavioral driver set TRB_CHAIN
+ * bit only for TR size > 2.
+ */
+ if (pep->type == USB_ENDPOINT_XFER_ISOC || TRBS_PER_SEGMENT > 2)
+ ch_bit = TRB_CHAIN;
+
+ link_trb->control = cpu_to_le32(((ring->pcs) ? TRB_CYCLE : 0) |
+ TRB_TYPE(TRB_LINK) | TRB_TOGGLE | ch_bit);
+ }
+
+ return 0;
+}
+
+static void cdns2_dbg_request_trbs(struct cdns2_endpoint *pep,
+ struct cdns2_request *preq)
+{
+ struct cdns2_trb *link_trb = pep->ring.trbs + (TRBS_PER_SEGMENT - 1);
+ struct cdns2_trb *trb = preq->trb;
+ int num_trbs = preq->num_of_trb;
+ int i = 0;
+
+ while (i < num_trbs) {
+ trace_cdns2_queue_trb(pep, trb + i);
+ if (trb + i == link_trb) {
+ trb = pep->ring.trbs;
+ num_trbs = num_trbs - i;
+ i = 0;
+ } else {
+ i++;
+ }
+ }
+}
+
+static unsigned int cdns2_count_trbs(struct cdns2_endpoint *pep,
+ u64 addr, u64 len)
+{
+ unsigned int num_trbs = 1;
+
+ if (pep->type == USB_ENDPOINT_XFER_ISOC) {
+ /*
+ * To speed up DMA performance address should not exceed 4KB.
+ * for high bandwidth transfer and driver will split
+ * such buffer into two TRBs.
+ */
+ num_trbs = DIV_ROUND_UP(len +
+ (addr & (TRB_MAX_ISO_BUFF_SIZE - 1)),
+ TRB_MAX_ISO_BUFF_SIZE);
+
+ if (pep->interval > 1)
+ num_trbs = pep->dir ? num_trbs * pep->interval : 1;
+ } else if (pep->dir) {
+ /*
+ * One extra link trb for IN direction.
+ * Sometimes DMA doesn't want advance to next TD and transfer
+ * hangs. This extra Link TRB force DMA to advance to next TD.
+ */
+ num_trbs++;
+ }
+
+ return num_trbs;
+}
+
+static unsigned int cdns2_count_sg_trbs(struct cdns2_endpoint *pep,
+ struct usb_request *req)
+{
+ unsigned int i, len, full_len, num_trbs = 0;
+ struct scatterlist *sg;
+ int trb_len = 0;
+
+ full_len = req->length;
+
+ for_each_sg(req->sg, sg, req->num_sgs, i) {
+ len = sg_dma_len(sg);
+ num_trbs += cdns2_count_trbs(pep, sg_dma_address(sg), len);
+ len = min(len, full_len);
+
+ /*
+ * For HS ISO transfer TRBs should not exceed max packet size.
+ * When DMA is working, and data exceed max packet size then
+ * some data will be read in single mode instead burst mode.
+ * This behavior will drastically reduce the copying speed.
+ * To avoid this we need one or two extra TRBs.
+ * This issue occurs for UVC class with sg_supported = 1
+ * because buffers addresses are not aligned to 1024.
+ */
+ if (pep->type == USB_ENDPOINT_XFER_ISOC) {
+ u8 temp;
+
+ trb_len += len;
+ temp = trb_len >> 10;
+
+ if (temp) {
+ if (trb_len % 1024)
+ num_trbs = num_trbs + temp;
+ else
+ num_trbs = num_trbs + temp - 1;
+
+ trb_len = trb_len - (temp << 10);
+ }
+ }
+
+ full_len -= len;
+ if (full_len == 0)
+ break;
+ }
+
+ return num_trbs;
+}
+
+/*
+ * Function prepares the array with optimized AXI burst value for different
+ * transfer lengths. Controller handles the final data which are less
+ * then AXI burst size as single byte transactions.
+ * e.g.:
+ * Let's assume that driver prepares trb with trb->length 700 and burst size
+ * will be set to 128. In this case the controller will handle a first 512 as
+ * single AXI transaction but the next 188 bytes will be handled
+ * as 47 separate AXI transaction.
+ * The better solution is to use the burst size equal 16 and then we will
+ * have only 25 AXI transaction (10 * 64 + 15 *4).
+ */
+static void cdsn2_isoc_burst_opt(struct cdns2_device *pdev)
+{
+ int axi_burst_option[] = {1, 2, 4, 8, 16, 32, 64, 128};
+ int best_burst;
+ int array_size;
+ int opt_burst;
+ int trb_size;
+ int i, j;
+
+ array_size = ARRAY_SIZE(axi_burst_option);
+
+ for (i = 0; i <= MAX_ISO_SIZE; i++) {
+ trb_size = i / 4;
+ best_burst = trb_size ? trb_size : 1;
+
+ for (j = 0; j < array_size; j++) {
+ opt_burst = trb_size / axi_burst_option[j];
+ opt_burst += trb_size % axi_burst_option[j];
+
+ if (opt_burst < best_burst) {
+ best_burst = opt_burst;
+ pdev->burst_opt[i] = axi_burst_option[j];
+ }
+ }
+ }
+}
+
+static void cdns2_ep_tx_isoc(struct cdns2_endpoint *pep,
+ struct cdns2_request *preq,
+ int num_trbs)
+{
+ struct scatterlist *sg = NULL;
+ u32 remaining_packet_size = 0;
+ struct cdns2_trb *trb;
+ bool first_trb = true;
+ dma_addr_t trb_dma;
+ u32 trb_buff_len;
+ u32 block_length;
+ int td_idx = 0;
+ int split_size;
+ u32 full_len;
+ int enqd_len;
+ int sent_len;
+ int sg_iter;
+ u32 control;
+ int num_tds;
+ u32 length;
+
+ /*
+ * For OUT direction 1 TD per interval is enough
+ * because TRBs are not dumped by controller.
+ */
+ num_tds = pep->dir ? pep->interval : 1;
+ split_size = preq->request.num_sgs ? 1024 : 3072;
+
+ for (td_idx = 0; td_idx < num_tds; td_idx++) {
+ if (preq->request.num_sgs) {
+ sg = preq->request.sg;
+ trb_dma = sg_dma_address(sg);
+ block_length = sg_dma_len(sg);
+ } else {
+ trb_dma = preq->request.dma;
+ block_length = preq->request.length;
+ }
+
+ full_len = preq->request.length;
+ sg_iter = preq->request.num_sgs ? preq->request.num_sgs : 1;
+ remaining_packet_size = split_size;
+
+ for (enqd_len = 0; enqd_len < full_len;
+ enqd_len += trb_buff_len) {
+ if (remaining_packet_size == 0)
+ remaining_packet_size = split_size;
+
+ /*
+ * Calculate TRB length.- buffer can't across 4KB
+ * and max packet size.
+ */
+ trb_buff_len = TRB_BUFF_LEN_UP_TO_BOUNDARY(trb_dma);
+ trb_buff_len = min(trb_buff_len, remaining_packet_size);
+ trb_buff_len = min(trb_buff_len, block_length);
+
+ if (trb_buff_len > full_len - enqd_len)
+ trb_buff_len = full_len - enqd_len;
+
+ control = TRB_TYPE(TRB_NORMAL);
+
+ /*
+ * For IN direction driver has to set the IOC for
+ * last TRB in last TD.
+ * For OUT direction driver must set IOC and ISP
+ * only for last TRB in each TDs.
+ */
+ if (enqd_len + trb_buff_len >= full_len || !pep->dir)
+ control |= TRB_IOC | TRB_ISP;
+
+ /*
+ * Don't give the first TRB to the hardware (by toggling
+ * the cycle bit) until we've finished creating all the
+ * other TRBs.
+ */
+ if (first_trb) {
+ first_trb = false;
+ if (pep->ring.pcs == 0)
+ control |= TRB_CYCLE;
+ } else {
+ control |= pep->ring.pcs;
+ }
+
+ if (enqd_len + trb_buff_len < full_len)
+ control |= TRB_CHAIN;
+
+ length = TRB_LEN(trb_buff_len) |
+ TRB_BURST(pep->pdev->burst_opt[trb_buff_len]);
+
+ trb = pep->ring.trbs + pep->ring.enqueue;
+ trb->buffer = cpu_to_le32(TRB_BUFFER(trb_dma));
+ trb->length = cpu_to_le32(length);
+ trb->control = cpu_to_le32(control);
+
+ trb_dma += trb_buff_len;
+ sent_len = trb_buff_len;
+
+ if (sg && sent_len >= block_length) {
+ /* New sg entry */
+ --sg_iter;
+ sent_len -= block_length;
+ if (sg_iter != 0) {
+ sg = sg_next(sg);
+ trb_dma = sg_dma_address(sg);
+ block_length = sg_dma_len(sg);
+ }
+ }
+
+ remaining_packet_size -= trb_buff_len;
+ block_length -= sent_len;
+ preq->end_trb = pep->ring.enqueue;
+
+ cdns2_ep_inc_enq(&pep->ring);
+ }
+ }
+}
+
+static void cdns2_ep_tx_bulk(struct cdns2_endpoint *pep,
+ struct cdns2_request *preq,
+ int trbs_per_td)
+{
+ struct scatterlist *sg = NULL;
+ struct cdns2_ring *ring;
+ struct cdns2_trb *trb;
+ dma_addr_t trb_dma;
+ int sg_iter = 0;
+ u32 control;
+ u32 length;
+
+ if (preq->request.num_sgs) {
+ sg = preq->request.sg;
+ trb_dma = sg_dma_address(sg);
+ length = sg_dma_len(sg);
+ } else {
+ trb_dma = preq->request.dma;
+ length = preq->request.length;
+ }
+
+ ring = &pep->ring;
+
+ for (sg_iter = 0; sg_iter < trbs_per_td; sg_iter++) {
+ control = TRB_TYPE(TRB_NORMAL) | ring->pcs | TRB_ISP;
+ trb = pep->ring.trbs + ring->enqueue;
+
+ if (pep->dir && sg_iter == trbs_per_td - 1) {
+ preq->end_trb = ring->enqueue;
+ control = ring->pcs | TRB_TYPE(TRB_LINK) | TRB_CHAIN
+ | TRB_IOC;
+ cdns2_ep_inc_enq(&pep->ring);
+
+ if (ring->enqueue == 0)
+ control |= TRB_TOGGLE;
+
+ /* Point to next bad TRB. */
+ trb->buffer = cpu_to_le32(pep->ring.dma +
+ (ring->enqueue * TRB_SIZE));
+ trb->length = 0;
+ trb->control = cpu_to_le32(control);
+ break;
+ }
+
+ /*
+ * Don't give the first TRB to the hardware (by toggling
+ * the cycle bit) until we've finished creating all the
+ * other TRBs.
+ */
+ if (sg_iter == 0)
+ control = control ^ TRB_CYCLE;
+
+ /* For last TRB in TD. */
+ if (sg_iter == (trbs_per_td - (pep->dir ? 2 : 1)))
+ control |= TRB_IOC;
+ else
+ control |= TRB_CHAIN;
+
+ trb->buffer = cpu_to_le32(trb_dma);
+ trb->length = cpu_to_le32(TRB_BURST(pep->trb_burst_size) |
+ TRB_LEN(length));
+ trb->control = cpu_to_le32(control);
+
+ if (sg && sg_iter < (trbs_per_td - 1)) {
+ sg = sg_next(sg);
+ trb_dma = sg_dma_address(sg);
+ length = sg_dma_len(sg);
+ }
+
+ preq->end_trb = ring->enqueue;
+ cdns2_ep_inc_enq(&pep->ring);
+ }
+}
+
+static void cdns2_set_drdy(struct cdns2_device *pdev,
+ struct cdns2_endpoint *pep)
+{
+ trace_cdns2_ring(pep);
+
+ /*
+ * Memory barrier - Cycle Bit must be set before doorbell.
+ */
+ dma_wmb();
+
+ /* Clearing TRBERR and DESCMIS before setting DRDY. */
+ writel(DMA_EP_STS_TRBERR | DMA_EP_STS_DESCMIS,
+ &pdev->adma_regs->ep_sts);
+ writel(DMA_EP_CMD_DRDY, &pdev->adma_regs->ep_cmd);
+
+ if (readl(&pdev->adma_regs->ep_sts) & DMA_EP_STS_TRBERR) {
+ writel(DMA_EP_STS_TRBERR, &pdev->adma_regs->ep_sts);
+ writel(DMA_EP_CMD_DRDY, &pdev->adma_regs->ep_cmd);
+ }
+
+ trace_cdns2_doorbell_epx(pep, readl(&pdev->adma_regs->ep_traddr));
+}
+
+static int cdns2_prepare_first_isoc_transfer(struct cdns2_device *pdev,
+ struct cdns2_endpoint *pep)
+{
+ struct cdns2_trb *trb;
+ u32 buffer;
+ u8 hw_ccs;
+
+ if ((readl(&pdev->adma_regs->ep_cmd) & DMA_EP_CMD_DRDY))
+ return -EBUSY;
+
+ if (!pep->dir) {
+ set_reg_bit_32(&pdev->adma_regs->ep_cfg, DMA_EP_CFG_ENABLE);
+ writel(pep->ring.dma + pep->ring.dequeue,
+ &pdev->adma_regs->ep_traddr);
+ return 0;
+ }
+
+ /*
+ * The first packet after doorbell can be corrupted so,
+ * driver prepares 0 length packet as first packet.
+ */
+ buffer = pep->ring.dma + pep->ring.dequeue * TRB_SIZE;
+ hw_ccs = !!DMA_EP_STS_CCS(readl(&pdev->adma_regs->ep_sts));
+
+ trb = &pep->ring.trbs[TRBS_PER_SEGMENT];
+ trb->length = 0;
+ trb->buffer = cpu_to_le32(TRB_BUFFER(buffer));
+ trb->control = cpu_to_le32((hw_ccs ? TRB_CYCLE : 0) | TRB_TYPE(TRB_NORMAL));
+
+ /*
+ * LINK TRB is used to force updating cycle bit in controller and
+ * move to correct place in transfer ring.
+ */
+ trb++;
+ trb->length = 0;
+ trb->buffer = cpu_to_le32(TRB_BUFFER(buffer));
+ trb->control = cpu_to_le32((hw_ccs ? TRB_CYCLE : 0) |
+ TRB_TYPE(TRB_LINK) | TRB_CHAIN);
+
+ if (hw_ccs != pep->ring.ccs)
+ trb->control |= cpu_to_le32(TRB_TOGGLE);
+
+ set_reg_bit_32(&pdev->adma_regs->ep_cfg, DMA_EP_CFG_ENABLE);
+ writel(pep->ring.dma + (TRBS_PER_SEGMENT * TRB_SIZE),
+ &pdev->adma_regs->ep_traddr);
+
+ return 0;
+}
+
+/* Prepare and start transfer on no-default endpoint. */
+static int cdns2_ep_run_transfer(struct cdns2_endpoint *pep,
+ struct cdns2_request *preq)
+{
+ struct cdns2_device *pdev = pep->pdev;
+ struct cdns2_ring *ring;
+ u32 togle_pcs = 1;
+ int num_trbs;
+ int ret;
+
+ cdns2_select_ep(pdev, pep->endpoint.address);
+
+ if (preq->request.sg)
+ num_trbs = cdns2_count_sg_trbs(pep, &preq->request);
+ else
+ num_trbs = cdns2_count_trbs(pep, preq->request.dma,
+ preq->request.length);
+
+ ret = cdns2_prepare_ring(pdev, pep, num_trbs);
+ if (ret)
+ return ret;
+
+ ring = &pep->ring;
+ preq->start_trb = ring->enqueue;
+ preq->trb = ring->trbs + ring->enqueue;
+
+ if (usb_endpoint_xfer_isoc(pep->endpoint.desc)) {
+ cdns2_ep_tx_isoc(pep, preq, num_trbs);
+ } else {
+ togle_pcs = cdns2_wa1_update_guard(pep, ring->trbs + ring->enqueue);
+ cdns2_ep_tx_bulk(pep, preq, num_trbs);
+ }
+
+ preq->num_of_trb = num_trbs;
+
+ /*
+ * Memory barrier - cycle bit must be set as the last operation.
+ */
+ dma_wmb();
+
+ /* Give the TD to the consumer. */
+ if (togle_pcs)
+ preq->trb->control = preq->trb->control ^ cpu_to_le32(1);
+
+ cdns2_wa1_tray_restore_cycle_bit(pdev, pep);
+ cdns2_dbg_request_trbs(pep, preq);
+
+ if (!pep->wa1_set && !(pep->ep_state & EP_STALLED) && !pep->skip) {
+ if (pep->type == USB_ENDPOINT_XFER_ISOC) {
+ ret = cdns2_prepare_first_isoc_transfer(pdev, pep);
+ if (ret)
+ return 0;
+ }
+
+ cdns2_set_drdy(pdev, pep);
+ }
+
+ return 0;
+}
+
+/* Prepare and start transfer for all not started requests. */
+static int cdns2_start_all_request(struct cdns2_device *pdev,
+ struct cdns2_endpoint *pep)
+{
+ struct cdns2_request *preq;
+ int ret;
+
+ while (!list_empty(&pep->deferred_list)) {
+ preq = cdns2_next_preq(&pep->deferred_list);
+
+ ret = cdns2_ep_run_transfer(pep, preq);
+ if (ret)
+ return ret;
+
+ list_move_tail(&preq->list, &pep->pending_list);
+ }
+
+ pep->ep_state &= ~EP_RING_FULL;
+
+ return 0;
+}
+
+/*
+ * Check whether trb has been handled by DMA.
+ *
+ * Endpoint must be selected before invoking this function.
+ *
+ * Returns false if request has not been handled by DMA, else returns true.
+ *
+ * SR - start ring
+ * ER - end ring
+ * DQ = ring->dequeue - dequeue position
+ * EQ = ring->enqueue - enqueue position
+ * ST = preq->start_trb - index of first TRB in transfer ring
+ * ET = preq->end_trb - index of last TRB in transfer ring
+ * CI = current_index - index of processed TRB by DMA.
+ *
+ * As first step, we check if the TRB between the ST and ET.
+ * Then, we check if cycle bit for index pep->dequeue
+ * is correct.
+ *
+ * some rules:
+ * 1. ring->dequeue never equals to current_index.
+ * 2 ring->enqueue never exceed ring->dequeue
+ * 3. exception: ring->enqueue == ring->dequeue
+ * and ring->free_trbs is zero.
+ * This case indicate that TR is full.
+ *
+ * At below two cases, the request have been handled.
+ * Case 1 - ring->dequeue < current_index
+ * SR ... EQ ... DQ ... CI ... ER
+ * SR ... DQ ... CI ... EQ ... ER
+ *
+ * Case 2 - ring->dequeue > current_index
+ * This situation takes place when CI go through the LINK TRB at the end of
+ * transfer ring.
+ * SR ... CI ... EQ ... DQ ... ER
+ */
+static bool cdns2_trb_handled(struct cdns2_endpoint *pep,
+ struct cdns2_request *preq)
+{
+ struct cdns2_device *pdev = pep->pdev;
+ struct cdns2_ring *ring;
+ struct cdns2_trb *trb;
+ int current_index = 0;
+ int handled = 0;
+ int doorbell;
+
+ ring = &pep->ring;
+ current_index = cdns2_get_dma_pos(pdev, pep);
+ doorbell = !!(readl(&pdev->adma_regs->ep_cmd) & DMA_EP_CMD_DRDY);
+
+ /*
+ * Only ISO transfer can use 2 entries outside the standard
+ * Transfer Ring. First of them is used as zero length packet and the
+ * second as LINK TRB.
+ */
+ if (current_index >= TRBS_PER_SEGMENT)
+ goto finish;
+
+ /* Current trb doesn't belong to this request. */
+ if (preq->start_trb < preq->end_trb) {
+ if (ring->dequeue > preq->end_trb)
+ goto finish;
+
+ if (ring->dequeue < preq->start_trb)
+ goto finish;
+ }
+
+ if (preq->start_trb > preq->end_trb && ring->dequeue > preq->end_trb &&
+ ring->dequeue < preq->start_trb)
+ goto finish;
+
+ if (preq->start_trb == preq->end_trb && ring->dequeue != preq->end_trb)
+ goto finish;
+
+ trb = &ring->trbs[ring->dequeue];
+
+ if ((le32_to_cpu(trb->control) & TRB_CYCLE) != ring->ccs)
+ goto finish;
+
+ if (doorbell == 1 && current_index == ring->dequeue)
+ goto finish;
+
+ /* The corner case for TRBS_PER_SEGMENT equal 2). */
+ if (TRBS_PER_SEGMENT == 2 && pep->type != USB_ENDPOINT_XFER_ISOC) {
+ handled = 1;
+ goto finish;
+ }
+
+ if (ring->enqueue == ring->dequeue &&
+ ring->free_trbs == 0) {
+ handled = 1;
+ } else if (ring->dequeue < current_index) {
+ if ((current_index == (TRBS_PER_SEGMENT - 1)) &&
+ !ring->dequeue)
+ goto finish;
+
+ handled = 1;
+ } else if (ring->dequeue > current_index) {
+ handled = 1;
+ }
+
+finish:
+ trace_cdns2_request_handled(preq, current_index, handled);
+
+ return handled;
+}
+
+static void cdns2_skip_isoc_td(struct cdns2_device *pdev,
+ struct cdns2_endpoint *pep,
+ struct cdns2_request *preq)
+{
+ struct cdns2_trb *trb;
+ int i;
+
+ trb = pep->ring.trbs + pep->ring.dequeue;
+
+ for (i = preq->finished_trb ; i < preq->num_of_trb; i++) {
+ preq->finished_trb++;
+ trace_cdns2_complete_trb(pep, trb);
+ cdns2_ep_inc_deq(&pep->ring);
+ trb = cdns2_next_trb(pep, trb);
+ }
+
+ cdns2_gadget_giveback(pep, preq, 0);
+ cdns2_prepare_first_isoc_transfer(pdev, pep);
+ pep->skip = false;
+ cdns2_set_drdy(pdev, pep);
+}
+
+static void cdns2_transfer_completed(struct cdns2_device *pdev,
+ struct cdns2_endpoint *pep)
+{
+ struct cdns2_request *preq = NULL;
+ bool request_handled = false;
+ struct cdns2_trb *trb;
+
+ while (!list_empty(&pep->pending_list)) {
+ preq = cdns2_next_preq(&pep->pending_list);
+ trb = pep->ring.trbs + pep->ring.dequeue;
+
+ /*
+ * The TRB was changed as link TRB, and the request
+ * was handled at ep_dequeue.
+ */
+ while (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK &&
+ le32_to_cpu(trb->length)) {
+ trace_cdns2_complete_trb(pep, trb);
+ cdns2_ep_inc_deq(&pep->ring);
+ trb = pep->ring.trbs + pep->ring.dequeue;
+ }
+
+ /*
+ * Re-select endpoint. It could be changed by other CPU
+ * during handling usb_gadget_giveback_request.
+ */
+ cdns2_select_ep(pdev, pep->endpoint.address);
+
+ while (cdns2_trb_handled(pep, preq)) {
+ preq->finished_trb++;
+
+ if (preq->finished_trb >= preq->num_of_trb)
+ request_handled = true;
+
+ trb = pep->ring.trbs + pep->ring.dequeue;
+ trace_cdns2_complete_trb(pep, trb);
+
+ if (pep->dir && pep->type == USB_ENDPOINT_XFER_ISOC)
+ /*
+ * For ISOC IN controller doens't update the
+ * trb->length.
+ */
+ preq->request.actual = preq->request.length;
+ else
+ preq->request.actual +=
+ TRB_LEN(le32_to_cpu(trb->length));
+
+ cdns2_ep_inc_deq(&pep->ring);
+ }
+
+ if (request_handled) {
+ cdns2_gadget_giveback(pep, preq, 0);
+ request_handled = false;
+ } else {
+ goto prepare_next_td;
+ }
+
+ if (pep->type != USB_ENDPOINT_XFER_ISOC &&
+ TRBS_PER_SEGMENT == 2)
+ break;
+ }
+
+prepare_next_td:
+ if (pep->skip && preq)
+ cdns2_skip_isoc_td(pdev, pep, preq);
+
+ if (!(pep->ep_state & EP_STALLED) &&
+ !(pep->ep_state & EP_STALL_PENDING))
+ cdns2_start_all_request(pdev, pep);
+}
+
+static void cdns2_wakeup(struct cdns2_device *pdev)
+{
+ if (!pdev->may_wakeup)
+ return;
+
+ /* Start driving resume signaling to indicate remote wakeup. */
+ set_reg_bit_8(&pdev->usb_regs->usbcs, USBCS_SIGRSUME);
+}
+
+static void cdns2_rearm_transfer(struct cdns2_endpoint *pep, u8 rearm)
+{
+ struct cdns2_device *pdev = pep->pdev;
+
+ cdns2_wa1_restore_cycle_bit(pep);
+
+ if (rearm) {
+ trace_cdns2_ring(pep);
+
+ /* Cycle Bit must be updated before arming DMA. */
+ dma_wmb();
+
+ writel(DMA_EP_CMD_DRDY, &pdev->adma_regs->ep_cmd);
+
+ cdns2_wakeup(pdev);
+
+ trace_cdns2_doorbell_epx(pep,
+ readl(&pdev->adma_regs->ep_traddr));
+ }
+}
+
+static void cdns2_handle_epx_interrupt(struct cdns2_endpoint *pep)
+{
+ struct cdns2_device *pdev = pep->pdev;
+ u8 isoerror = 0;
+ u32 ep_sts_reg;
+ u32 val;
+
+ cdns2_select_ep(pdev, pep->endpoint.address);
+
+ trace_cdns2_epx_irq(pdev, pep);
+
+ ep_sts_reg = readl(&pdev->adma_regs->ep_sts);
+ writel(ep_sts_reg, &pdev->adma_regs->ep_sts);
+
+ if (pep->type == USB_ENDPOINT_XFER_ISOC) {
+ u8 mult;
+ u8 cs;
+
+ mult = USB_EP_MAXP_MULT(pep->endpoint.desc->wMaxPacketSize);
+ cs = pep->dir ? readb(&pdev->epx_regs->ep[pep->num - 1].txcs) :
+ readb(&pdev->epx_regs->ep[pep->num - 1].rxcs);
+ if (mult > 0)
+ isoerror = EPX_CS_ERR(cs);
+ }
+
+ /*
+ * Sometimes ISO Error for mult=1 or mult=2 is not propagated on time
+ * from USB module to DMA module. To protect against this driver
+ * checks also the txcs/rxcs registers.
+ */
+ if ((ep_sts_reg & DMA_EP_STS_ISOERR) || isoerror) {
+ clear_reg_bit_32(&pdev->adma_regs->ep_cfg, DMA_EP_CFG_ENABLE);
+
+ /* Wait for DBUSY cleared. */
+ readl_poll_timeout_atomic(&pdev->adma_regs->ep_sts, val,
+ !(val & DMA_EP_STS_DBUSY), 1, 125);
+
+ writel(DMA_EP_CMD_DFLUSH, &pep->pdev->adma_regs->ep_cmd);
+
+ /* Wait for DFLUSH cleared. */
+ readl_poll_timeout_atomic(&pep->pdev->adma_regs->ep_cmd, val,
+ !(val & DMA_EP_CMD_DFLUSH), 1, 10);
+
+ pep->skip = true;
+ }
+
+ if (ep_sts_reg & DMA_EP_STS_TRBERR || pep->skip) {
+ if (pep->ep_state & EP_STALL_PENDING &&
+ !(ep_sts_reg & DMA_EP_STS_DESCMIS))
+ cdns2_ep_stall_flush(pep);
+
+ /*
+ * For isochronous transfer driver completes request on
+ * IOC or on TRBERR. IOC appears only when device receive
+ * OUT data packet. If host disable stream or lost some packet
+ * then the only way to finish all queued transfer is to do it
+ * on TRBERR event.
+ */
+ if (pep->type == USB_ENDPOINT_XFER_ISOC && !pep->wa1_set) {
+ if (!pep->dir)
+ clear_reg_bit_32(&pdev->adma_regs->ep_cfg,
+ DMA_EP_CFG_ENABLE);
+
+ cdns2_transfer_completed(pdev, pep);
+ if (pep->ep_state & EP_DEFERRED_DRDY) {
+ pep->ep_state &= ~EP_DEFERRED_DRDY;
+ cdns2_set_drdy(pdev, pep);
+ }
+
+ return;
+ }
+
+ cdns2_transfer_completed(pdev, pep);
+
+ if (!(pep->ep_state & EP_STALLED) &&
+ !(pep->ep_state & EP_STALL_PENDING)) {
+ if (pep->ep_state & EP_DEFERRED_DRDY) {
+ pep->ep_state &= ~EP_DEFERRED_DRDY;
+ cdns2_start_all_request(pdev, pep);
+ } else {
+ cdns2_rearm_transfer(pep, pep->wa1_set);
+ }
+ }
+
+ return;
+ }
+
+ if ((ep_sts_reg & DMA_EP_STS_IOC) || (ep_sts_reg & DMA_EP_STS_ISP))
+ cdns2_transfer_completed(pdev, pep);
+}
+
+static void cdns2_disconnect_gadget(struct cdns2_device *pdev)
+{
+ if (pdev->gadget_driver && pdev->gadget_driver->disconnect)
+ pdev->gadget_driver->disconnect(&pdev->gadget);
+}
+
+static irqreturn_t cdns2_usb_irq_handler(int irq, void *data)
+{
+ struct cdns2_device *pdev = data;
+ unsigned long reg_ep_ists;
+ u8 reg_usb_irq_m;
+ u8 reg_ext_irq_m;
+ u8 reg_usb_irq;
+ u8 reg_ext_irq;
+
+ if (pdev->in_lpm)
+ return IRQ_NONE;
+
+ reg_usb_irq_m = readb(&pdev->interrupt_regs->usbien);
+ reg_ext_irq_m = readb(&pdev->interrupt_regs->extien);
+
+ /* Mask all sources of interrupt. */
+ writeb(0, &pdev->interrupt_regs->usbien);
+ writeb(0, &pdev->interrupt_regs->extien);
+ writel(0, &pdev->adma_regs->ep_ien);
+
+ /* Clear interrupt sources. */
+ writel(0, &pdev->adma_regs->ep_sts);
+ writeb(0, &pdev->interrupt_regs->usbirq);
+ writeb(0, &pdev->interrupt_regs->extirq);
+
+ reg_ep_ists = readl(&pdev->adma_regs->ep_ists);
+ reg_usb_irq = readb(&pdev->interrupt_regs->usbirq);
+ reg_ext_irq = readb(&pdev->interrupt_regs->extirq);
+
+ if (reg_ep_ists || (reg_usb_irq & reg_usb_irq_m) ||
+ (reg_ext_irq & reg_ext_irq_m))
+ return IRQ_WAKE_THREAD;
+
+ writeb(USB_IEN_INIT, &pdev->interrupt_regs->usbien);
+ writeb(EXTIRQ_WAKEUP, &pdev->interrupt_regs->extien);
+ writel(~0, &pdev->adma_regs->ep_ien);
+
+ return IRQ_NONE;
+}
+
+static irqreturn_t cdns2_thread_usb_irq_handler(struct cdns2_device *pdev)
+{
+ u8 usb_irq, ext_irq;
+ int speed;
+ int i;
+
+ ext_irq = readb(&pdev->interrupt_regs->extirq) & EXTIRQ_WAKEUP;
+ writeb(ext_irq, &pdev->interrupt_regs->extirq);
+
+ usb_irq = readb(&pdev->interrupt_regs->usbirq) & USB_IEN_INIT;
+ writeb(usb_irq, &pdev->interrupt_regs->usbirq);
+
+ if (!ext_irq && !usb_irq)
+ return IRQ_NONE;
+
+ trace_cdns2_usb_irq(usb_irq, ext_irq);
+
+ if (ext_irq & EXTIRQ_WAKEUP) {
+ if (pdev->gadget_driver && pdev->gadget_driver->resume) {
+ spin_unlock(&pdev->lock);
+ pdev->gadget_driver->resume(&pdev->gadget);
+ spin_lock(&pdev->lock);
+ }
+ }
+
+ if (usb_irq & USBIRQ_LPM) {
+ u8 reg = readb(&pdev->usb_regs->lpmctrl);
+
+ /* LPM1 enter */
+ if (!(reg & LPMCTRLLH_LPMNYET))
+ writeb(0, &pdev->usb_regs->sleep_clkgate);
+ }
+
+ if (usb_irq & USBIRQ_SUSPEND) {
+ if (pdev->gadget_driver && pdev->gadget_driver->suspend) {
+ spin_unlock(&pdev->lock);
+ pdev->gadget_driver->suspend(&pdev->gadget);
+ spin_lock(&pdev->lock);
+ }
+ }
+
+ if (usb_irq & USBIRQ_URESET) {
+ if (pdev->gadget_driver) {
+ pdev->dev_address = 0;
+
+ spin_unlock(&pdev->lock);
+ usb_gadget_udc_reset(&pdev->gadget,
+ pdev->gadget_driver);
+ spin_lock(&pdev->lock);
+
+ /*
+ * The USBIRQ_URESET is reported at the beginning of
+ * reset signal. 100ms is enough time to finish reset
+ * process. For high-speed reset procedure is completed
+ * when controller detect HS mode.
+ */
+ for (i = 0; i < 100; i++) {
+ mdelay(1);
+ speed = cdns2_get_speed(pdev);
+ if (speed == USB_SPEED_HIGH)
+ break;
+ }
+
+ pdev->gadget.speed = speed;
+ cdns2_enable_l1(pdev, 0);
+ cdns2_ep0_config(pdev);
+ pdev->may_wakeup = 0;
+ }
+ }
+
+ if (usb_irq & USBIRQ_SUDAV) {
+ pdev->ep0_stage = CDNS2_SETUP_STAGE;
+ cdns2_handle_setup_packet(pdev);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* Deferred USB interrupt handler. */
+static irqreturn_t cdns2_thread_irq_handler(int irq, void *data)
+{
+ struct cdns2_device *pdev = data;
+ unsigned long dma_ep_ists;
+ unsigned long flags;
+ unsigned int bit;
+
+ local_bh_disable();
+ spin_lock_irqsave(&pdev->lock, flags);
+
+ cdns2_thread_usb_irq_handler(pdev);
+
+ dma_ep_ists = readl(&pdev->adma_regs->ep_ists);
+ if (!dma_ep_ists)
+ goto unlock;
+
+ trace_cdns2_dma_ep_ists(dma_ep_ists);
+
+ /* Handle default endpoint OUT. */
+ if (dma_ep_ists & DMA_EP_ISTS_EP_OUT0)
+ cdns2_handle_ep0_interrupt(pdev, USB_DIR_OUT);
+
+ /* Handle default endpoint IN. */
+ if (dma_ep_ists & DMA_EP_ISTS_EP_IN0)
+ cdns2_handle_ep0_interrupt(pdev, USB_DIR_IN);
+
+ dma_ep_ists &= ~(DMA_EP_ISTS_EP_OUT0 | DMA_EP_ISTS_EP_IN0);
+
+ for_each_set_bit(bit, &dma_ep_ists, sizeof(u32) * BITS_PER_BYTE) {
+ u8 ep_idx = bit > 16 ? (bit - 16) * 2 : (bit * 2) - 1;
+
+ /*
+ * Endpoints in pdev->eps[] are held in order:
+ * ep0, ep1out, ep1in, ep2out, ep2in... ep15out, ep15in.
+ * but in dma_ep_ists in order:
+ * ep0 ep1out ep2out ... ep15out ep0in ep1in .. ep15in
+ */
+ cdns2_handle_epx_interrupt(&pdev->eps[ep_idx]);
+ }
+
+unlock:
+ writel(~0, &pdev->adma_regs->ep_ien);
+ writeb(USB_IEN_INIT, &pdev->interrupt_regs->usbien);
+ writeb(EXTIRQ_WAKEUP, &pdev->interrupt_regs->extien);
+
+ spin_unlock_irqrestore(&pdev->lock, flags);
+ local_bh_enable();
+
+ return IRQ_HANDLED;
+}
+
+/* Calculates and assigns onchip memory for endpoints. */
+static void cdns2_eps_onchip_buffer_init(struct cdns2_device *pdev)
+{
+ struct cdns2_endpoint *pep;
+ int min_buf_tx = 0;
+ int min_buf_rx = 0;
+ u16 tx_offset = 0;
+ u16 rx_offset = 0;
+ int free;
+ int i;
+
+ for (i = 0; i < CDNS2_ENDPOINTS_NUM; i++) {
+ pep = &pdev->eps[i];
+
+ if (!(pep->ep_state & EP_CLAIMED))
+ continue;
+
+ if (pep->dir)
+ min_buf_tx += pep->buffering;
+ else
+ min_buf_rx += pep->buffering;
+ }
+
+ for (i = 0; i < CDNS2_ENDPOINTS_NUM; i++) {
+ pep = &pdev->eps[i];
+
+ if (!(pep->ep_state & EP_CLAIMED))
+ continue;
+
+ if (pep->dir) {
+ free = pdev->onchip_tx_buf - min_buf_tx;
+
+ if (free + pep->buffering >= 4)
+ free = 4;
+ else
+ free = free + pep->buffering;
+
+ min_buf_tx = min_buf_tx - pep->buffering + free;
+
+ pep->buffering = free;
+
+ writel(tx_offset,
+ &pdev->epx_regs->txstaddr[pep->num - 1]);
+ pdev->epx_regs->txstaddr[pep->num - 1] = tx_offset;
+
+ dev_dbg(pdev->dev, "%s onchip address %04x, buffering: %d\n",
+ pep->name, tx_offset, pep->buffering);
+
+ tx_offset += pep->buffering * 1024;
+ } else {
+ free = pdev->onchip_rx_buf - min_buf_rx;
+
+ if (free + pep->buffering >= 4)
+ free = 4;
+ else
+ free = free + pep->buffering;
+
+ min_buf_rx = min_buf_rx - pep->buffering + free;
+
+ pep->buffering = free;
+ writel(rx_offset,
+ &pdev->epx_regs->rxstaddr[pep->num - 1]);
+
+ dev_dbg(pdev->dev, "%s onchip address %04x, buffering: %d\n",
+ pep->name, rx_offset, pep->buffering);
+
+ rx_offset += pep->buffering * 1024;
+ }
+ }
+}
+
+/* Configure hardware endpoint. */
+static int cdns2_ep_config(struct cdns2_endpoint *pep, bool enable)
+{
+ bool is_iso_ep = (pep->type == USB_ENDPOINT_XFER_ISOC);
+ struct cdns2_device *pdev = pep->pdev;
+ u32 max_packet_size;
+ u8 dir = 0;
+ u8 ep_cfg;
+ u8 mult;
+ u32 val;
+ int ret;
+
+ switch (pep->type) {
+ case USB_ENDPOINT_XFER_INT:
+ ep_cfg = EPX_CON_TYPE_INT;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ ep_cfg = EPX_CON_TYPE_BULK;
+ break;
+ default:
+ mult = USB_EP_MAXP_MULT(pep->endpoint.desc->wMaxPacketSize);
+ ep_cfg = mult << EPX_CON_ISOD_SHIFT;
+ ep_cfg |= EPX_CON_TYPE_ISOC;
+
+ if (pep->dir) {
+ set_reg_bit_8(&pdev->epx_regs->isoautoarm, BIT(pep->num));
+ set_reg_bit_8(&pdev->epx_regs->isoautodump, BIT(pep->num));
+ set_reg_bit_8(&pdev->epx_regs->isodctrl, BIT(pep->num));
+ }
+ }
+
+ switch (pdev->gadget.speed) {
+ case USB_SPEED_FULL:
+ max_packet_size = is_iso_ep ? 1023 : 64;
+ break;
+ case USB_SPEED_HIGH:
+ max_packet_size = is_iso_ep ? 1024 : 512;
+ break;
+ default:
+ /* All other speed are not supported. */
+ return -EINVAL;
+ }
+
+ ep_cfg |= (EPX_CON_VAL | (pep->buffering - 1));
+
+ if (pep->dir) {
+ dir = FIFOCTRL_IO_TX;
+ writew(max_packet_size, &pdev->epx_regs->txmaxpack[pep->num - 1]);
+ writeb(ep_cfg, &pdev->epx_regs->ep[pep->num - 1].txcon);
+ } else {
+ writew(max_packet_size, &pdev->epx_regs->rxmaxpack[pep->num - 1]);
+ writeb(ep_cfg, &pdev->epx_regs->ep[pep->num - 1].rxcon);
+ }
+
+ writeb(pep->num | dir | FIFOCTRL_FIFOAUTO,
+ &pdev->usb_regs->fifoctrl);
+ writeb(pep->num | dir, &pdev->epx_regs->endprst);
+ writeb(pep->num | ENDPRST_FIFORST | ENDPRST_TOGRST | dir,
+ &pdev->epx_regs->endprst);
+
+ if (max_packet_size == 1024)
+ pep->trb_burst_size = 128;
+ else if (max_packet_size >= 512)
+ pep->trb_burst_size = 64;
+ else
+ pep->trb_burst_size = 16;
+
+ cdns2_select_ep(pdev, pep->num | pep->dir);
+ writel(DMA_EP_CMD_EPRST | DMA_EP_CMD_DFLUSH, &pdev->adma_regs->ep_cmd);
+
+ ret = readl_poll_timeout_atomic(&pdev->adma_regs->ep_cmd, val,
+ !(val & (DMA_EP_CMD_DFLUSH |
+ DMA_EP_CMD_EPRST)),
+ 1, 1000);
+
+ if (ret)
+ return ret;
+
+ writel(DMA_EP_STS_TRBERR | DMA_EP_STS_ISOERR, &pdev->adma_regs->ep_sts_en);
+
+ if (enable)
+ writel(DMA_EP_CFG_ENABLE, &pdev->adma_regs->ep_cfg);
+
+ trace_cdns2_epx_hw_cfg(pdev, pep);
+
+ dev_dbg(pdev->dev, "Configure %s: with MPS: %08x, ep con: %02x\n",
+ pep->name, max_packet_size, ep_cfg);
+
+ return 0;
+}
+
+struct usb_request *cdns2_gadget_ep_alloc_request(struct usb_ep *ep,
+ gfp_t gfp_flags)
+{
+ struct cdns2_endpoint *pep = ep_to_cdns2_ep(ep);
+ struct cdns2_request *preq;
+
+ preq = kzalloc(sizeof(*preq), gfp_flags);
+ if (!preq)
+ return NULL;
+
+ preq->pep = pep;
+
+ trace_cdns2_alloc_request(preq);
+
+ return &preq->request;
+}
+
+void cdns2_gadget_ep_free_request(struct usb_ep *ep,
+ struct usb_request *request)
+{
+ struct cdns2_request *preq = to_cdns2_request(request);
+
+ trace_cdns2_free_request(preq);
+ kfree(preq);
+}
+
+static int cdns2_gadget_ep_enable(struct usb_ep *ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ u32 reg = DMA_EP_STS_EN_TRBERREN;
+ struct cdns2_endpoint *pep;
+ struct cdns2_device *pdev;
+ unsigned long flags;
+ int enable = 1;
+ int ret = 0;
+
+ if (!ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT ||
+ !desc->wMaxPacketSize) {
+ return -EINVAL;
+ }
+
+ pep = ep_to_cdns2_ep(ep);
+ pdev = pep->pdev;
+
+ if (dev_WARN_ONCE(pdev->dev, pep->ep_state & EP_ENABLED,
+ "%s is already enabled\n", pep->name))
+ return 0;
+
+ spin_lock_irqsave(&pdev->lock, flags);
+
+ pep->type = usb_endpoint_type(desc);
+ pep->interval = desc->bInterval ? BIT(desc->bInterval - 1) : 0;
+
+ if (pdev->gadget.speed == USB_SPEED_FULL)
+ if (pep->type == USB_ENDPOINT_XFER_INT)
+ pep->interval = desc->bInterval;
+
+ if (pep->interval > ISO_MAX_INTERVAL &&
+ pep->type == USB_ENDPOINT_XFER_ISOC) {
+ dev_err(pdev->dev, "ISO period is limited to %d (current: %d)\n",
+ ISO_MAX_INTERVAL, pep->interval);
+
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ /*
+ * During ISO OUT traffic DMA reads Transfer Ring for the EP which has
+ * never got doorbell.
+ * This issue was detected only on simulation, but to avoid this issue
+ * driver add protection against it. To fix it driver enable ISO OUT
+ * endpoint before setting DRBL. This special treatment of ISO OUT
+ * endpoints are recommended by controller specification.
+ */
+ if (pep->type == USB_ENDPOINT_XFER_ISOC && !pep->dir)
+ enable = 0;
+
+ ret = cdns2_alloc_tr_segment(pep);
+ if (ret)
+ goto exit;
+
+ ret = cdns2_ep_config(pep, enable);
+ if (ret) {
+ cdns2_free_tr_segment(pep);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ trace_cdns2_gadget_ep_enable(pep);
+
+ pep->ep_state &= ~(EP_STALLED | EP_STALL_PENDING);
+ pep->ep_state |= EP_ENABLED;
+ pep->wa1_set = 0;
+ pep->ring.enqueue = 0;
+ pep->ring.dequeue = 0;
+ reg = readl(&pdev->adma_regs->ep_sts);
+ pep->ring.pcs = !!DMA_EP_STS_CCS(reg);
+ pep->ring.ccs = !!DMA_EP_STS_CCS(reg);
+
+ writel(pep->ring.dma, &pdev->adma_regs->ep_traddr);
+
+ /* one TRB is reserved for link TRB used in DMULT mode*/
+ pep->ring.free_trbs = TRBS_PER_SEGMENT - 1;
+
+exit:
+ spin_unlock_irqrestore(&pdev->lock, flags);
+
+ return ret;
+}
+
+static int cdns2_gadget_ep_disable(struct usb_ep *ep)
+{
+ struct cdns2_endpoint *pep;
+ struct cdns2_request *preq;
+ struct cdns2_device *pdev;
+ unsigned long flags;
+ int val;
+
+ if (!ep)
+ return -EINVAL;
+
+ pep = ep_to_cdns2_ep(ep);
+ pdev = pep->pdev;
+
+ if (dev_WARN_ONCE(pdev->dev, !(pep->ep_state & EP_ENABLED),
+ "%s is already disabled\n", pep->name))
+ return 0;
+
+ spin_lock_irqsave(&pdev->lock, flags);
+
+ trace_cdns2_gadget_ep_disable(pep);
+
+ cdns2_select_ep(pdev, ep->desc->bEndpointAddress);
+
+ clear_reg_bit_32(&pdev->adma_regs->ep_cfg, DMA_EP_CFG_ENABLE);
+
+ /*
+ * Driver needs some time before resetting endpoint.
+ * It need waits for clearing DBUSY bit or for timeout expired.
+ * 10us is enough time for controller to stop transfer.
+ */
+ readl_poll_timeout_atomic(&pdev->adma_regs->ep_sts, val,
+ !(val & DMA_EP_STS_DBUSY), 1, 10);
+ writel(DMA_EP_CMD_EPRST, &pdev->adma_regs->ep_cmd);
+
+ readl_poll_timeout_atomic(&pdev->adma_regs->ep_cmd, val,
+ !(val & (DMA_EP_CMD_DFLUSH | DMA_EP_CMD_EPRST)),
+ 1, 1000);
+
+ while (!list_empty(&pep->pending_list)) {
+ preq = cdns2_next_preq(&pep->pending_list);
+ cdns2_gadget_giveback(pep, preq, -ESHUTDOWN);
+ }
+
+ while (!list_empty(&pep->deferred_list)) {
+ preq = cdns2_next_preq(&pep->deferred_list);
+ cdns2_gadget_giveback(pep, preq, -ESHUTDOWN);
+ }
+
+ ep->desc = NULL;
+ pep->ep_state &= ~EP_ENABLED;
+
+ spin_unlock_irqrestore(&pdev->lock, flags);
+
+ return 0;
+}
+
+static int cdns2_ep_enqueue(struct cdns2_endpoint *pep,
+ struct cdns2_request *preq,
+ gfp_t gfp_flags)
+{
+ struct cdns2_device *pdev = pep->pdev;
+ struct usb_request *request;
+ int ret;
+
+ request = &preq->request;
+ request->actual = 0;
+ request->status = -EINPROGRESS;
+
+ ret = usb_gadget_map_request_by_dev(pdev->dev, request, pep->dir);
+ if (ret) {
+ trace_cdns2_request_enqueue_error(preq);
+ return ret;
+ }
+
+ list_add_tail(&preq->list, &pep->deferred_list);
+ trace_cdns2_request_enqueue(preq);
+
+ if (!(pep->ep_state & EP_STALLED) && !(pep->ep_state & EP_STALL_PENDING))
+ cdns2_start_all_request(pdev, pep);
+
+ return 0;
+}
+
+static int cdns2_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
+ gfp_t gfp_flags)
+{
+ struct usb_request *zlp_request;
+ struct cdns2_request *preq;
+ struct cdns2_endpoint *pep;
+ struct cdns2_device *pdev;
+ unsigned long flags;
+ int ret;
+
+ if (!request || !ep)
+ return -EINVAL;
+
+ pep = ep_to_cdns2_ep(ep);
+ pdev = pep->pdev;
+
+ if (!(pep->ep_state & EP_ENABLED)) {
+ dev_err(pdev->dev, "%s: can't queue to disabled endpoint\n",
+ pep->name);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&pdev->lock, flags);
+
+ preq = to_cdns2_request(request);
+ ret = cdns2_ep_enqueue(pep, preq, gfp_flags);
+
+ if (ret == 0 && request->zero && request->length &&
+ (request->length % ep->maxpacket == 0)) {
+ struct cdns2_request *preq;
+
+ zlp_request = cdns2_gadget_ep_alloc_request(ep, GFP_ATOMIC);
+ zlp_request->buf = pdev->zlp_buf;
+ zlp_request->length = 0;
+
+ preq = to_cdns2_request(zlp_request);
+ ret = cdns2_ep_enqueue(pep, preq, gfp_flags);
+ }
+
+ spin_unlock_irqrestore(&pdev->lock, flags);
+ return ret;
+}
+
+int cdns2_gadget_ep_dequeue(struct usb_ep *ep,
+ struct usb_request *request)
+{
+ struct cdns2_request *preq, *preq_temp, *cur_preq;
+ struct cdns2_endpoint *pep;
+ struct cdns2_trb *link_trb;
+ u8 req_on_hw_ring = 0;
+ unsigned long flags;
+ u32 buffer;
+ int val, i;
+
+ if (!ep || !request || !ep->desc)
+ return -EINVAL;
+
+ pep = ep_to_cdns2_ep(ep);
+ if (!pep->endpoint.desc) {
+ dev_err(pep->pdev->dev, "%s: can't dequeue to disabled endpoint\n",
+ pep->name);
+ return -ESHUTDOWN;
+ }
+
+ /* Requests has been dequeued during disabling endpoint. */
+ if (!(pep->ep_state & EP_ENABLED))
+ return 0;
+
+ spin_lock_irqsave(&pep->pdev->lock, flags);
+
+ cur_preq = to_cdns2_request(request);
+ trace_cdns2_request_dequeue(cur_preq);
+
+ list_for_each_entry_safe(preq, preq_temp, &pep->pending_list, list) {
+ if (cur_preq == preq) {
+ req_on_hw_ring = 1;
+ goto found;
+ }
+ }
+
+ list_for_each_entry_safe(preq, preq_temp, &pep->deferred_list, list) {
+ if (cur_preq == preq)
+ goto found;
+ }
+
+ goto not_found;
+
+found:
+ link_trb = preq->trb;
+
+ /* Update ring only if removed request is on pending_req_list list. */
+ if (req_on_hw_ring && link_trb) {
+ /* Stop DMA */
+ writel(DMA_EP_CMD_DFLUSH, &pep->pdev->adma_regs->ep_cmd);
+
+ /* Wait for DFLUSH cleared. */
+ readl_poll_timeout_atomic(&pep->pdev->adma_regs->ep_cmd, val,
+ !(val & DMA_EP_CMD_DFLUSH), 1, 1000);
+
+ buffer = cpu_to_le32(TRB_BUFFER(pep->ring.dma +
+ ((preq->end_trb + 1) * TRB_SIZE)));
+
+ for (i = 0; i < preq->num_of_trb; i++) {
+ link_trb->buffer = buffer;
+ link_trb->control = cpu_to_le32((le32_to_cpu(link_trb->control)
+ & TRB_CYCLE) | TRB_CHAIN |
+ TRB_TYPE(TRB_LINK));
+
+ trace_cdns2_queue_trb(pep, link_trb);
+ link_trb = cdns2_next_trb(pep, link_trb);
+ }
+
+ if (pep->wa1_trb == preq->trb)
+ cdns2_wa1_restore_cycle_bit(pep);
+ }
+
+ cdns2_gadget_giveback(pep, cur_preq, -ECONNRESET);
+
+ preq = cdns2_next_preq(&pep->pending_list);
+ if (preq)
+ cdns2_rearm_transfer(pep, 1);
+
+not_found:
+ spin_unlock_irqrestore(&pep->pdev->lock, flags);
+ return 0;
+}
+
+int cdns2_halt_endpoint(struct cdns2_device *pdev,
+ struct cdns2_endpoint *pep,
+ int value)
+{
+ u8 __iomem *conf;
+ int dir = 0;
+
+ if (!(pep->ep_state & EP_ENABLED))
+ return -EPERM;
+
+ if (pep->dir) {
+ dir = ENDPRST_IO_TX;
+ conf = &pdev->epx_regs->ep[pep->num - 1].txcon;
+ } else {
+ conf = &pdev->epx_regs->ep[pep->num - 1].rxcon;
+ }
+
+ if (!value) {
+ struct cdns2_trb *trb = NULL;
+ struct cdns2_request *preq;
+ struct cdns2_trb trb_tmp;
+
+ preq = cdns2_next_preq(&pep->pending_list);
+ if (preq) {
+ trb = preq->trb;
+ if (trb) {
+ trb_tmp = *trb;
+ trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE);
+ }
+ }
+
+ trace_cdns2_ep_halt(pep, 0, 0);
+
+ /* Resets Sequence Number */
+ writeb(dir | pep->num, &pdev->epx_regs->endprst);
+ writeb(dir | ENDPRST_TOGRST | pep->num,
+ &pdev->epx_regs->endprst);
+
+ clear_reg_bit_8(conf, EPX_CON_STALL);
+
+ pep->ep_state &= ~(EP_STALLED | EP_STALL_PENDING);
+
+ if (preq) {
+ if (trb)
+ *trb = trb_tmp;
+
+ cdns2_rearm_transfer(pep, 1);
+ }
+
+ cdns2_start_all_request(pdev, pep);
+ } else {
+ trace_cdns2_ep_halt(pep, 1, 0);
+ set_reg_bit_8(conf, EPX_CON_STALL);
+ writeb(dir | pep->num, &pdev->epx_regs->endprst);
+ writeb(dir | ENDPRST_FIFORST | pep->num,
+ &pdev->epx_regs->endprst);
+ pep->ep_state |= EP_STALLED;
+ }
+
+ return 0;
+}
+
+/* Sets/clears stall on selected endpoint. */
+static int cdns2_gadget_ep_set_halt(struct usb_ep *ep, int value)
+{
+ struct cdns2_endpoint *pep = ep_to_cdns2_ep(ep);
+ struct cdns2_device *pdev = pep->pdev;
+ struct cdns2_request *preq;
+ unsigned long flags = 0;
+ int ret;
+
+ spin_lock_irqsave(&pdev->lock, flags);
+
+ preq = cdns2_next_preq(&pep->pending_list);
+ if (value && preq) {
+ trace_cdns2_ep_busy_try_halt_again(pep);
+ ret = -EAGAIN;
+ goto done;
+ }
+
+ if (!value)
+ pep->ep_state &= ~EP_WEDGE;
+
+ ret = cdns2_halt_endpoint(pdev, pep, value);
+
+done:
+ spin_unlock_irqrestore(&pdev->lock, flags);
+ return ret;
+}
+
+static int cdns2_gadget_ep_set_wedge(struct usb_ep *ep)
+{
+ struct cdns2_endpoint *pep = ep_to_cdns2_ep(ep);
+
+ cdns2_gadget_ep_set_halt(ep, 1);
+ pep->ep_state |= EP_WEDGE;
+
+ return 0;
+}
+
+static struct
+cdns2_endpoint *cdns2_find_available_ep(struct cdns2_device *pdev,
+ struct usb_endpoint_descriptor *desc)
+{
+ struct cdns2_endpoint *pep;
+ struct usb_ep *ep;
+ int ep_correct;
+
+ list_for_each_entry(ep, &pdev->gadget.ep_list, ep_list) {
+ unsigned long num;
+ int ret;
+ /* ep name pattern likes epXin or epXout. */
+ char c[2] = {ep->name[2], '\0'};
+
+ ret = kstrtoul(c, 10, &num);
+ if (ret)
+ return ERR_PTR(ret);
+ pep = ep_to_cdns2_ep(ep);
+
+ if (pep->num != num)
+ continue;
+
+ ep_correct = (pep->endpoint.caps.dir_in &&
+ usb_endpoint_dir_in(desc)) ||
+ (pep->endpoint.caps.dir_out &&
+ usb_endpoint_dir_out(desc));
+
+ if (ep_correct && !(pep->ep_state & EP_CLAIMED))
+ return pep;
+ }
+
+ return ERR_PTR(-ENOENT);
+}
+
+/*
+ * Function used to recognize which endpoints will be used to optimize
+ * on-chip memory usage.
+ */
+static struct
+usb_ep *cdns2_gadget_match_ep(struct usb_gadget *gadget,
+ struct usb_endpoint_descriptor *desc,
+ struct usb_ss_ep_comp_descriptor *comp_desc)
+{
+ struct cdns2_device *pdev = gadget_to_cdns2_device(gadget);
+ struct cdns2_endpoint *pep;
+ unsigned long flags;
+
+ pep = cdns2_find_available_ep(pdev, desc);
+ if (IS_ERR(pep)) {
+ dev_err(pdev->dev, "no available ep\n");
+ return NULL;
+ }
+
+ spin_lock_irqsave(&pdev->lock, flags);
+
+ if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_ISOC)
+ pep->buffering = 4;
+ else
+ pep->buffering = 1;
+
+ pep->ep_state |= EP_CLAIMED;
+ spin_unlock_irqrestore(&pdev->lock, flags);
+
+ return &pep->endpoint;
+}
+
+static const struct usb_ep_ops cdns2_gadget_ep_ops = {
+ .enable = cdns2_gadget_ep_enable,
+ .disable = cdns2_gadget_ep_disable,
+ .alloc_request = cdns2_gadget_ep_alloc_request,
+ .free_request = cdns2_gadget_ep_free_request,
+ .queue = cdns2_gadget_ep_queue,
+ .dequeue = cdns2_gadget_ep_dequeue,
+ .set_halt = cdns2_gadget_ep_set_halt,
+ .set_wedge = cdns2_gadget_ep_set_wedge,
+};
+
+static int cdns2_gadget_get_frame(struct usb_gadget *gadget)
+{
+ struct cdns2_device *pdev = gadget_to_cdns2_device(gadget);
+
+ return readw(&pdev->usb_regs->frmnr);
+}
+
+static int cdns2_gadget_wakeup(struct usb_gadget *gadget)
+{
+ struct cdns2_device *pdev = gadget_to_cdns2_device(gadget);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdev->lock, flags);
+ cdns2_wakeup(pdev);
+ spin_unlock_irqrestore(&pdev->lock, flags);
+
+ return 0;
+}
+
+static int cdns2_gadget_set_selfpowered(struct usb_gadget *gadget,
+ int is_selfpowered)
+{
+ struct cdns2_device *pdev = gadget_to_cdns2_device(gadget);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdev->lock, flags);
+ pdev->is_selfpowered = !!is_selfpowered;
+ spin_unlock_irqrestore(&pdev->lock, flags);
+ return 0;
+}
+
+/* Disable interrupts and begin the controller halting process. */
+static void cdns2_quiesce(struct cdns2_device *pdev)
+{
+ set_reg_bit_8(&pdev->usb_regs->usbcs, USBCS_DISCON);
+
+ /* Disable interrupt. */
+ writeb(0, &pdev->interrupt_regs->extien),
+ writeb(0, &pdev->interrupt_regs->usbien),
+ writew(0, &pdev->adma_regs->ep_ien);
+
+ /* Clear interrupt line. */
+ writeb(0x0, &pdev->interrupt_regs->usbirq);
+}
+
+static void cdns2_gadget_config(struct cdns2_device *pdev)
+{
+ cdns2_ep0_config(pdev);
+
+ /* Enable DMA interrupts for all endpoints. */
+ writel(~0x0, &pdev->adma_regs->ep_ien);
+ cdns2_enable_l1(pdev, 0);
+ writeb(USB_IEN_INIT, &pdev->interrupt_regs->usbien);
+ writeb(EXTIRQ_WAKEUP, &pdev->interrupt_regs->extien);
+ writel(DMA_CONF_DMULT, &pdev->adma_regs->conf);
+}
+
+static int cdns2_gadget_pullup(struct usb_gadget *gadget, int is_on)
+{
+ struct cdns2_device *pdev = gadget_to_cdns2_device(gadget);
+ unsigned long flags;
+
+ trace_cdns2_pullup(is_on);
+
+ /*
+ * Disable events handling while controller is being
+ * enabled/disabled.
+ */
+ disable_irq(pdev->irq);
+ spin_lock_irqsave(&pdev->lock, flags);
+
+ if (is_on) {
+ cdns2_gadget_config(pdev);
+ clear_reg_bit_8(&pdev->usb_regs->usbcs, USBCS_DISCON);
+ } else {
+ cdns2_quiesce(pdev);
+ }
+
+ spin_unlock_irqrestore(&pdev->lock, flags);
+ enable_irq(pdev->irq);
+
+ return 0;
+}
+
+static int cdns2_gadget_udc_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
+{
+ struct cdns2_device *pdev = gadget_to_cdns2_device(gadget);
+ enum usb_device_speed max_speed = driver->max_speed;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdev->lock, flags);
+ pdev->gadget_driver = driver;
+
+ /* Limit speed if necessary. */
+ max_speed = min(driver->max_speed, gadget->max_speed);
+
+ switch (max_speed) {
+ case USB_SPEED_FULL:
+ writeb(SPEEDCTRL_HSDISABLE, &pdev->usb_regs->speedctrl);
+ break;
+ case USB_SPEED_HIGH:
+ writeb(0, &pdev->usb_regs->speedctrl);
+ break;
+ default:
+ dev_err(pdev->dev, "invalid maximum_speed parameter %d\n",
+ max_speed);
+ fallthrough;
+ case USB_SPEED_UNKNOWN:
+ /* Default to highspeed. */
+ max_speed = USB_SPEED_HIGH;
+ break;
+ }
+
+ /* Reset all USB endpoints. */
+ writeb(ENDPRST_IO_TX, &pdev->usb_regs->endprst);
+ writeb(ENDPRST_FIFORST | ENDPRST_TOGRST | ENDPRST_IO_TX,
+ &pdev->usb_regs->endprst);
+ writeb(ENDPRST_FIFORST | ENDPRST_TOGRST, &pdev->usb_regs->endprst);
+
+ cdns2_eps_onchip_buffer_init(pdev);
+
+ cdns2_gadget_config(pdev);
+ spin_unlock_irqrestore(&pdev->lock, flags);
+
+ return 0;
+}
+
+static int cdns2_gadget_udc_stop(struct usb_gadget *gadget)
+{
+ struct cdns2_device *pdev = gadget_to_cdns2_device(gadget);
+ struct cdns2_endpoint *pep;
+ u32 bEndpointAddress;
+ struct usb_ep *ep;
+ int val;
+
+ pdev->gadget_driver = NULL;
+ pdev->gadget.speed = USB_SPEED_UNKNOWN;
+
+ list_for_each_entry(ep, &pdev->gadget.ep_list, ep_list) {
+ pep = ep_to_cdns2_ep(ep);
+ bEndpointAddress = pep->num | pep->dir;
+ cdns2_select_ep(pdev, bEndpointAddress);
+ writel(DMA_EP_CMD_EPRST, &pdev->adma_regs->ep_cmd);
+ readl_poll_timeout_atomic(&pdev->adma_regs->ep_cmd, val,
+ !(val & DMA_EP_CMD_EPRST), 1, 100);
+ }
+
+ cdns2_quiesce(pdev);
+
+ writeb(ENDPRST_IO_TX, &pdev->usb_regs->endprst);
+ writeb(ENDPRST_FIFORST | ENDPRST_TOGRST | ENDPRST_IO_TX,
+ &pdev->epx_regs->endprst);
+ writeb(ENDPRST_FIFORST | ENDPRST_TOGRST, &pdev->epx_regs->endprst);
+
+ return 0;
+}
+
+static const struct usb_gadget_ops cdns2_gadget_ops = {
+ .get_frame = cdns2_gadget_get_frame,
+ .wakeup = cdns2_gadget_wakeup,
+ .set_selfpowered = cdns2_gadget_set_selfpowered,
+ .pullup = cdns2_gadget_pullup,
+ .udc_start = cdns2_gadget_udc_start,
+ .udc_stop = cdns2_gadget_udc_stop,
+ .match_ep = cdns2_gadget_match_ep,
+};
+
+static void cdns2_free_all_eps(struct cdns2_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < CDNS2_ENDPOINTS_NUM; i++)
+ cdns2_free_tr_segment(&pdev->eps[i]);
+}
+
+/* Initializes software endpoints of gadget. */
+static int cdns2_init_eps(struct cdns2_device *pdev)
+{
+ struct cdns2_endpoint *pep;
+ int i;
+
+ for (i = 0; i < CDNS2_ENDPOINTS_NUM; i++) {
+ bool direction = !(i & 1); /* Start from OUT endpoint. */
+ u8 epnum = ((i + 1) >> 1);
+
+ /*
+ * Endpoints are being held in pdev->eps[] in form:
+ * ep0, ep1out, ep1in ... ep15out, ep15in.
+ */
+ if (!CDNS2_IF_EP_EXIST(pdev, epnum, direction))
+ continue;
+
+ pep = &pdev->eps[i];
+ pep->pdev = pdev;
+ pep->num = epnum;
+ /* 0 for OUT, 1 for IN. */
+ pep->dir = direction ? USB_DIR_IN : USB_DIR_OUT;
+ pep->idx = i;
+
+ /* Ep0in and ep0out are represented by pdev->eps[0]. */
+ if (!epnum) {
+ int ret;
+
+ snprintf(pep->name, sizeof(pep->name), "ep%d%s",
+ epnum, "BiDir");
+
+ cdns2_init_ep0(pdev, pep);
+
+ ret = cdns2_alloc_tr_segment(pep);
+ if (ret) {
+ dev_err(pdev->dev, "Failed to init ep0\n");
+ return ret;
+ }
+ } else {
+ snprintf(pep->name, sizeof(pep->name), "ep%d%s",
+ epnum, !!direction ? "in" : "out");
+ pep->endpoint.name = pep->name;
+
+ usb_ep_set_maxpacket_limit(&pep->endpoint, 1024);
+ pep->endpoint.ops = &cdns2_gadget_ep_ops;
+ list_add_tail(&pep->endpoint.ep_list, &pdev->gadget.ep_list);
+
+ pep->endpoint.caps.dir_in = direction;
+ pep->endpoint.caps.dir_out = !direction;
+
+ pep->endpoint.caps.type_iso = 1;
+ pep->endpoint.caps.type_bulk = 1;
+ pep->endpoint.caps.type_int = 1;
+ }
+
+ pep->endpoint.name = pep->name;
+ pep->ep_state = 0;
+
+ dev_dbg(pdev->dev, "Init %s, SupType: CTRL: %s, INT: %s, "
+ "BULK: %s, ISOC %s, SupDir IN: %s, OUT: %s\n",
+ pep->name,
+ (pep->endpoint.caps.type_control) ? "yes" : "no",
+ (pep->endpoint.caps.type_int) ? "yes" : "no",
+ (pep->endpoint.caps.type_bulk) ? "yes" : "no",
+ (pep->endpoint.caps.type_iso) ? "yes" : "no",
+ (pep->endpoint.caps.dir_in) ? "yes" : "no",
+ (pep->endpoint.caps.dir_out) ? "yes" : "no");
+
+ INIT_LIST_HEAD(&pep->pending_list);
+ INIT_LIST_HEAD(&pep->deferred_list);
+ }
+
+ return 0;
+}
+
+static int cdns2_gadget_start(struct cdns2_device *pdev)
+{
+ u32 max_speed;
+ void *buf;
+ int val;
+ int ret;
+
+ pdev->usb_regs = pdev->regs;
+ pdev->ep0_regs = pdev->regs;
+ pdev->epx_regs = pdev->regs;
+ pdev->interrupt_regs = pdev->regs;
+ pdev->adma_regs = pdev->regs + CDNS2_ADMA_REGS_OFFSET;
+
+ /* Reset controller. */
+ set_reg_bit_8(&pdev->usb_regs->cpuctrl, CPUCTRL_SW_RST);
+
+ ret = readl_poll_timeout_atomic(&pdev->usb_regs->cpuctrl, val,
+ !(val & CPUCTRL_SW_RST), 1, 10000);
+ if (ret) {
+ dev_err(pdev->dev, "Error: reset controller timeout\n");
+ return -EINVAL;
+ }
+
+ usb_initialize_gadget(pdev->dev, &pdev->gadget, NULL);
+
+ device_property_read_u16(pdev->dev, "cdns,on-chip-tx-buff-size",
+ &pdev->onchip_tx_buf);
+ device_property_read_u16(pdev->dev, "cdns,on-chip-rx-buff-size",
+ &pdev->onchip_rx_buf);
+ device_property_read_u32(pdev->dev, "cdns,avail-endpoints",
+ &pdev->eps_supported);
+
+ /*
+ * Driver assumes that each USBHS controller has at least
+ * one IN and one OUT non control endpoint.
+ */
+ if (!pdev->onchip_tx_buf && !pdev->onchip_rx_buf) {
+ ret = -EINVAL;
+ dev_err(pdev->dev, "Invalid on-chip memory configuration\n");
+ goto put_gadget;
+ }
+
+ if (!(pdev->eps_supported & ~0x00010001)) {
+ ret = -EINVAL;
+ dev_err(pdev->dev, "No hardware endpoints available\n");
+ goto put_gadget;
+ }
+
+ max_speed = usb_get_maximum_speed(pdev->dev);
+
+ switch (max_speed) {
+ case USB_SPEED_FULL:
+ case USB_SPEED_HIGH:
+ break;
+ default:
+ dev_err(pdev->dev, "invalid maximum_speed parameter %d\n",
+ max_speed);
+ fallthrough;
+ case USB_SPEED_UNKNOWN:
+ max_speed = USB_SPEED_HIGH;
+ break;
+ }
+
+ pdev->gadget.max_speed = max_speed;
+ pdev->gadget.speed = USB_SPEED_UNKNOWN;
+ pdev->gadget.ops = &cdns2_gadget_ops;
+ pdev->gadget.name = "usbhs-gadget";
+ pdev->gadget.quirk_avoids_skb_reserve = 1;
+ pdev->gadget.irq = pdev->irq;
+
+ spin_lock_init(&pdev->lock);
+ INIT_WORK(&pdev->pending_status_wq, cdns2_pending_setup_status_handler);
+
+ /* Initialize endpoint container. */
+ INIT_LIST_HEAD(&pdev->gadget.ep_list);
+ pdev->eps_dma_pool = dma_pool_create("cdns2_eps_dma_pool", pdev->dev,
+ TR_SEG_SIZE, 8, 0);
+ if (!pdev->eps_dma_pool) {
+ dev_err(pdev->dev, "Failed to create TRB dma pool\n");
+ ret = -ENOMEM;
+ goto put_gadget;
+ }
+
+ ret = cdns2_init_eps(pdev);
+ if (ret) {
+ dev_err(pdev->dev, "Failed to create endpoints\n");
+ goto destroy_dma_pool;
+ }
+
+ pdev->gadget.sg_supported = 1;
+
+ pdev->zlp_buf = kzalloc(CDNS2_EP_ZLP_BUF_SIZE, GFP_KERNEL);
+ if (!pdev->zlp_buf) {
+ ret = -ENOMEM;
+ goto destroy_dma_pool;
+ }
+
+ /* Allocate memory for setup packet buffer. */
+ buf = dma_alloc_coherent(pdev->dev, 8, &pdev->ep0_preq.request.dma,
+ GFP_DMA);
+ pdev->ep0_preq.request.buf = buf;
+
+ if (!pdev->ep0_preq.request.buf) {
+ ret = -ENOMEM;
+ goto free_zlp_buf;
+ }
+
+ /* Add USB gadget device. */
+ ret = usb_add_gadget(&pdev->gadget);
+ if (ret < 0) {
+ dev_err(pdev->dev, "Failed to add gadget\n");
+ goto free_ep0_buf;
+ }
+
+ return 0;
+
+free_ep0_buf:
+ dma_free_coherent(pdev->dev, 8, pdev->ep0_preq.request.buf,
+ pdev->ep0_preq.request.dma);
+free_zlp_buf:
+ kfree(pdev->zlp_buf);
+destroy_dma_pool:
+ dma_pool_destroy(pdev->eps_dma_pool);
+put_gadget:
+ usb_put_gadget(&pdev->gadget);
+
+ return ret;
+}
+
+int cdns2_gadget_suspend(struct cdns2_device *pdev)
+{
+ unsigned long flags;
+
+ cdns2_disconnect_gadget(pdev);
+
+ spin_lock_irqsave(&pdev->lock, flags);
+ pdev->gadget.speed = USB_SPEED_UNKNOWN;
+
+ trace_cdns2_device_state("notattached");
+ usb_gadget_set_state(&pdev->gadget, USB_STATE_NOTATTACHED);
+ cdns2_enable_l1(pdev, 0);
+
+ /* Disable interrupt for device. */
+ writeb(0, &pdev->interrupt_regs->usbien);
+ writel(0, &pdev->adma_regs->ep_ien);
+ spin_unlock_irqrestore(&pdev->lock, flags);
+
+ return 0;
+}
+
+int cdns2_gadget_resume(struct cdns2_device *pdev, bool hibernated)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdev->lock, flags);
+
+ if (!pdev->gadget_driver) {
+ spin_unlock_irqrestore(&pdev->lock, flags);
+ return 0;
+ }
+
+ cdns2_gadget_config(pdev);
+
+ if (hibernated)
+ clear_reg_bit_8(&pdev->usb_regs->usbcs, USBCS_DISCON);
+
+ spin_unlock_irqrestore(&pdev->lock, flags);
+
+ return 0;
+}
+
+void cdns2_gadget_remove(struct cdns2_device *pdev)
+{
+ pm_runtime_mark_last_busy(pdev->dev);
+ pm_runtime_put_autosuspend(pdev->dev);
+
+ usb_del_gadget(&pdev->gadget);
+ cdns2_free_all_eps(pdev);
+
+ dma_pool_destroy(pdev->eps_dma_pool);
+ kfree(pdev->zlp_buf);
+ usb_put_gadget(&pdev->gadget);
+}
+
+int cdns2_gadget_init(struct cdns2_device *pdev)
+{
+ int ret;
+
+ /* Ensure 32-bit DMA Mask. */
+ ret = dma_set_mask_and_coherent(pdev->dev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_err(pdev->dev, "Failed to set dma mask: %d\n", ret);
+ return ret;
+ }
+
+ pm_runtime_get_sync(pdev->dev);
+
+ cdsn2_isoc_burst_opt(pdev);
+
+ ret = cdns2_gadget_start(pdev);
+ if (ret) {
+ pm_runtime_put_sync(pdev->dev);
+ return ret;
+ }
+
+ /*
+ * Because interrupt line can be shared with other components in
+ * driver it can't use IRQF_ONESHOT flag here.
+ */
+ ret = devm_request_threaded_irq(pdev->dev, pdev->irq,
+ cdns2_usb_irq_handler,
+ cdns2_thread_irq_handler,
+ IRQF_SHARED,
+ dev_name(pdev->dev),
+ pdev);
+ if (ret)
+ goto err0;
+
+ return 0;
+
+err0:
+ cdns2_gadget_remove(pdev);
+
+ return ret;
+}
diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-gadget.h b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.h
new file mode 100644
index 000000000000..71e2f62d653a
--- /dev/null
+++ b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.h
@@ -0,0 +1,707 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * USBHS-DEV device controller driver header file
+ *
+ * Copyright (C) 2023 Cadence.
+ *
+ * Author: Pawel Laszczak <pawell@cadence.com>
+ */
+
+#ifndef __LINUX_CDNS2_GADGET
+#define __LINUX_CDNS2_GADGET
+
+#include <linux/usb/gadget.h>
+#include <linux/dma-direction.h>
+
+/*
+ * USBHS register interface.
+ * This corresponds to the USBHS Device Controller Interface.
+ */
+
+/**
+ * struct cdns2_ep0_regs - endpoint 0 related registers.
+ * @rxbc: receive (OUT) 0 endpoint byte count register.
+ * @txbc: transmit (IN) 0 endpoint byte count register.
+ * @cs: 0 endpoint control and status register.
+ * @reserved1: reserved.
+ * @fifo: 0 endpoint fifo register.
+ * @reserved2: reserved.
+ * @setupdat: SETUP data register.
+ * @reserved4: reserved.
+ * @maxpack: 0 endpoint max packet size.
+ */
+struct cdns2_ep0_regs {
+ __u8 rxbc;
+ __u8 txbc;
+ __u8 cs;
+ __u8 reserved1[4];
+ __u8 fifo;
+ __le32 reserved2[94];
+ __u8 setupdat[8];
+ __u8 reserved4[88];
+ __u8 maxpack;
+} __packed __aligned(4);
+
+/* EP0CS - bitmasks. */
+/* Endpoint 0 stall bit for status stage. */
+#define EP0CS_STALL BIT(0)
+/* HSNAK bit. */
+#define EP0CS_HSNAK BIT(1)
+/* IN 0 endpoint busy bit. */
+#define EP0CS_TXBSY_MSK BIT(2)
+/* OUT 0 endpoint busy bit. */
+#define EP0CS_RXBSY_MSK BIT(3)
+/* Send STALL in the data stage phase. */
+#define EP0CS_DSTALL BIT(4)
+/* SETUP buffer content was changed. */
+#define EP0CS_CHGSET BIT(7)
+
+/* EP0FIFO - bitmasks. */
+/* Direction. */
+#define EP0_FIFO_IO_TX BIT(4)
+/* FIFO auto bit. */
+#define EP0_FIFO_AUTO BIT(5)
+/* FIFO commit bit. */
+#define EP0_FIFO_COMMIT BIT(6)
+/* FIFO access bit. */
+#define EP0_FIFO_ACCES BIT(7)
+
+/**
+ * struct cdns2_epx_base - base endpoint registers.
+ * @rxbc: OUT endpoint byte count register.
+ * @rxcon: OUT endpoint control register.
+ * @rxcs: OUT endpoint control and status register.
+ * @txbc: IN endpoint byte count register.
+ * @txcon: IN endpoint control register.
+ * @txcs: IN endpoint control and status register.
+ */
+struct cdns2_epx_base {
+ __le16 rxbc;
+ __u8 rxcon;
+ __u8 rxcs;
+ __le16 txbc;
+ __u8 txcon;
+ __u8 txcs;
+} __packed __aligned(4);
+
+/* rxcon/txcon - endpoint control register bitmasks. */
+/* Endpoint buffering: 0 - single buffering ... 3 - quad buffering. */
+#define EPX_CON_BUF GENMASK(1, 0)
+/* Endpoint type. */
+#define EPX_CON_TYPE GENMASK(3, 2)
+/* Endpoint type: isochronous. */
+#define EPX_CON_TYPE_ISOC 0x4
+/* Endpoint type: bulk. */
+#define EPX_CON_TYPE_BULK 0x8
+/* Endpoint type: interrupt. */
+#define EPX_CON_TYPE_INT 0xC
+/* Number of packets per microframe. */
+#define EPX_CON_ISOD GENMASK(5, 4)
+#define EPX_CON_ISOD_SHIFT 0x4
+/* Endpoint stall bit. */
+#define EPX_CON_STALL BIT(6)
+/* Endpoint enable bit.*/
+#define EPX_CON_VAL BIT(7)
+
+/* rxcs/txcs - endpoint control and status bitmasks. */
+/* Data sequence error for the ISO endpoint. */
+#define EPX_CS_ERR(p) ((p) & BIT(0))
+
+/**
+ * struct cdns2_epx_regs - endpoint 1..15 related registers.
+ * @reserved: reserved.
+ * @ep: none control endpoints array.
+ * @reserved2: reserved.
+ * @endprst: endpoint reset register.
+ * @reserved3: reserved.
+ * @isoautoarm: ISO auto-arm register.
+ * @reserved4: reserved.
+ * @isodctrl: ISO control register.
+ * @reserved5: reserved.
+ * @isoautodump: ISO auto dump enable register.
+ * @reserved6: reserved.
+ * @rxmaxpack: receive (OUT) Max packet size register.
+ * @reserved7: reserved.
+ * @rxstaddr: receive (OUT) start address endpoint buffer register.
+ * @reserved8: reserved.
+ * @txstaddr: transmit (IN) start address endpoint buffer register.
+ * @reserved9: reserved.
+ * @txmaxpack: transmit (IN) Max packet size register.
+ */
+struct cdns2_epx_regs {
+ __le32 reserved[2];
+ struct cdns2_epx_base ep[15];
+ __u8 reserved2[290];
+ __u8 endprst;
+ __u8 reserved3[41];
+ __le16 isoautoarm;
+ __u8 reserved4[10];
+ __le16 isodctrl;
+ __le16 reserved5;
+ __le16 isoautodump;
+ __le32 reserved6;
+ __le16 rxmaxpack[15];
+ __le32 reserved7[65];
+ __le32 rxstaddr[15];
+ __u8 reserved8[4];
+ __le32 txstaddr[15];
+ __u8 reserved9[98];
+ __le16 txmaxpack[15];
+} __packed __aligned(4);
+
+/* ENDPRST - bitmasks. */
+/* Endpoint number. */
+#define ENDPRST_EP GENMASK(3, 0)
+/* IN direction bit. */
+#define ENDPRST_IO_TX BIT(4)
+/* Toggle reset bit. */
+#define ENDPRST_TOGRST BIT(5)
+/* FIFO reset bit. */
+#define ENDPRST_FIFORST BIT(6)
+/* Toggle status and reset bit. */
+#define ENDPRST_TOGSETQ BIT(7)
+
+/**
+ * struct cdns2_interrupt_regs - USB interrupt related registers.
+ * @reserved: reserved.
+ * @usbirq: USB interrupt request register.
+ * @extirq: external interrupt request register.
+ * @rxpngirq: external interrupt request register.
+ * @reserved1: reserved.
+ * @usbien: USB interrupt enable register.
+ * @extien: external interrupt enable register.
+ * @reserved2: reserved.
+ * @usbivect: USB interrupt vector register.
+ */
+struct cdns2_interrupt_regs {
+ __u8 reserved[396];
+ __u8 usbirq;
+ __u8 extirq;
+ __le16 rxpngirq;
+ __le16 reserved1[4];
+ __u8 usbien;
+ __u8 extien;
+ __le16 reserved2[3];
+ __u8 usbivect;
+} __packed __aligned(4);
+
+/* EXTIRQ and EXTIEN - bitmasks. */
+/* VBUS fault fall interrupt. */
+#define EXTIRQ_VBUSFAULT_FALL BIT(0)
+/* VBUS fault fall interrupt. */
+#define EXTIRQ_VBUSFAULT_RISE BIT(1)
+/* Wake up interrupt bit. */
+#define EXTIRQ_WAKEUP BIT(7)
+
+/* USBIEN and USBIRQ - bitmasks. */
+/* SETUP data valid interrupt bit.*/
+#define USBIRQ_SUDAV BIT(0)
+/* Start-of-frame interrupt bit. */
+#define USBIRQ_SOF BIT(1)
+/* SETUP token interrupt bit. */
+#define USBIRQ_SUTOK BIT(2)
+/* USB suspend interrupt bit. */
+#define USBIRQ_SUSPEND BIT(3)
+/* USB reset interrupt bit. */
+#define USBIRQ_URESET BIT(4)
+/* USB high-speed mode interrupt bit. */
+#define USBIRQ_HSPEED BIT(5)
+/* Link Power Management interrupt bit. */
+#define USBIRQ_LPM BIT(7)
+
+#define USB_IEN_INIT (USBIRQ_SUDAV | USBIRQ_SUSPEND | USBIRQ_URESET \
+ | USBIRQ_HSPEED | USBIRQ_LPM)
+/**
+ * struct cdns2_usb_regs - USB controller registers.
+ * @reserved: reserved.
+ * @lpmctrl: LPM control register.
+ * @lpmclock: LPM clock register.
+ * @reserved2: reserved.
+ * @endprst: endpoint reset register.
+ * @usbcs: USB control and status register.
+ * @frmnr: USB frame counter register.
+ * @fnaddr: function Address register.
+ * @clkgate: clock gate register.
+ * @fifoctrl: FIFO control register.
+ * @speedctrl: speed Control register.
+ * @sleep_clkgate: sleep Clock Gate register.
+ * @reserved3: reserved.
+ * @cpuctrl: microprocessor control register.
+ */
+struct cdns2_usb_regs {
+ __u8 reserved[4];
+ __u16 lpmctrl;
+ __u8 lpmclock;
+ __u8 reserved2[411];
+ __u8 endprst;
+ __u8 usbcs;
+ __le16 frmnr;
+ __u8 fnaddr;
+ __u8 clkgate;
+ __u8 fifoctrl;
+ __u8 speedctrl;
+ __u8 sleep_clkgate;
+ __u8 reserved3[533];
+ __u8 cpuctrl;
+} __packed __aligned(4);
+
+/* LPMCTRL - bitmasks. */
+/* BESL (Best Effort Service Latency). */
+#define LPMCTRLLL_HIRD GENMASK(7, 4)
+/* Last received Remote Wakeup field from LPM Extended Token packet. */
+#define LPMCTRLLH_BREMOTEWAKEUP BIT(8)
+/* Reflects value of the lpmnyet bit located in the usbcs[1] register. */
+#define LPMCTRLLH_LPMNYET BIT(16)
+
+/* LPMCLOCK - bitmasks. */
+/*
+ * If bit is 1 the controller automatically turns off clock
+ * (utmisleepm goes to low), else the microprocessor should use
+ * sleep clock gate register to turn off clock.
+ */
+#define LPMCLOCK_SLEEP_ENTRY BIT(7)
+
+/* USBCS - bitmasks. */
+/* Send NYET handshake for the LPM transaction. */
+#define USBCS_LPMNYET BIT(2)
+/* Remote wake-up bit. */
+#define USBCS_SIGRSUME BIT(5)
+/* Software disconnect bit. */
+#define USBCS_DISCON BIT(6)
+/* Indicates that a wakeup pin resumed the controller. */
+#define USBCS_WAKESRC BIT(7)
+
+/* FIFOCTRL - bitmasks. */
+/* Endpoint number. */
+#define FIFOCTRL_EP GENMASK(3, 0)
+/* Direction bit. */
+#define FIFOCTRL_IO_TX BIT(4)
+/* FIFO auto bit. */
+#define FIFOCTRL_FIFOAUTO BIT(5)
+/* FIFO commit bit. */
+#define FIFOCTRL_FIFOCMIT BIT(6)
+/* FIFO access bit. */
+#define FIFOCTRL_FIFOACC BIT(7)
+
+/* SPEEDCTRL - bitmasks. */
+/* Device works in Full Speed. */
+#define SPEEDCTRL_FS BIT(1)
+/* Device works in High Speed. */
+#define SPEEDCTRL_HS BIT(2)
+/* Force FS mode. */
+#define SPEEDCTRL_HSDISABLE BIT(7)
+
+/* CPUCTRL- bitmasks. */
+/* Controller reset bit. */
+#define CPUCTRL_SW_RST BIT(1)
+
+/**
+ * struct cdns2_adma_regs - ADMA controller registers.
+ * @conf: DMA global configuration register.
+ * @sts: DMA global Status register.
+ * @reserved1: reserved.
+ * @ep_sel: DMA endpoint select register.
+ * @ep_traddr: DMA endpoint transfer ring address register.
+ * @ep_cfg: DMA endpoint configuration register.
+ * @ep_cmd: DMA endpoint command register.
+ * @ep_sts: DMA endpoint status register.
+ * @reserved2: reserved.
+ * @ep_sts_en: DMA endpoint status enable register.
+ * @drbl: DMA doorbell register.
+ * @ep_ien: DMA endpoint interrupt enable register.
+ * @ep_ists: DMA endpoint interrupt status register.
+ * @axim_ctrl: AXI Master Control register.
+ * @axim_id: AXI Master ID register.
+ * @reserved3: reserved.
+ * @axim_cap: AXI Master Wrapper Extended Capability.
+ * @reserved4: reserved.
+ * @axim_ctrl0: AXI Master Wrapper Extended Capability Control Register 0.
+ * @axim_ctrl1: AXI Master Wrapper Extended Capability Control Register 1.
+ */
+struct cdns2_adma_regs {
+ __le32 conf;
+ __le32 sts;
+ __le32 reserved1[5];
+ __le32 ep_sel;
+ __le32 ep_traddr;
+ __le32 ep_cfg;
+ __le32 ep_cmd;
+ __le32 ep_sts;
+ __le32 reserved2;
+ __le32 ep_sts_en;
+ __le32 drbl;
+ __le32 ep_ien;
+ __le32 ep_ists;
+ __le32 axim_ctrl;
+ __le32 axim_id;
+ __le32 reserved3;
+ __le32 axim_cap;
+ __le32 reserved4;
+ __le32 axim_ctrl0;
+ __le32 axim_ctrl1;
+};
+
+#define CDNS2_ADMA_REGS_OFFSET 0x400
+
+/* DMA_CONF - bitmasks. */
+/* Reset USB device configuration. */
+#define DMA_CONF_CFGRST BIT(0)
+/* Singular DMA transfer mode.*/
+#define DMA_CONF_DSING BIT(8)
+/* Multiple DMA transfers mode.*/
+#define DMA_CONF_DMULT BIT(9)
+
+/* DMA_EP_CFG - bitmasks. */
+/* Endpoint enable. */
+#define DMA_EP_CFG_ENABLE BIT(0)
+
+/* DMA_EP_CMD - bitmasks. */
+/* Endpoint reset. */
+#define DMA_EP_CMD_EPRST BIT(0)
+/* Transfer descriptor ready. */
+#define DMA_EP_CMD_DRDY BIT(6)
+/* Data flush. */
+#define DMA_EP_CMD_DFLUSH BIT(7)
+
+/* DMA_EP_STS - bitmasks. */
+/* Interrupt On Complete. */
+#define DMA_EP_STS_IOC BIT(2)
+/* Interrupt on Short Packet. */
+#define DMA_EP_STS_ISP BIT(3)
+/* Transfer descriptor missing. */
+#define DMA_EP_STS_DESCMIS BIT(4)
+/* TRB error. */
+#define DMA_EP_STS_TRBERR BIT(7)
+/* DMA busy bit. */
+#define DMA_EP_STS_DBUSY BIT(9)
+/* Current Cycle Status. */
+#define DMA_EP_STS_CCS(p) ((p) & BIT(11))
+/* OUT size mismatch. */
+#define DMA_EP_STS_OUTSMM BIT(14)
+/* ISO transmission error. */
+#define DMA_EP_STS_ISOERR BIT(15)
+
+/* DMA_EP_STS_EN - bitmasks. */
+/* OUT transfer missing descriptor enable. */
+#define DMA_EP_STS_EN_DESCMISEN BIT(4)
+/* TRB enable. */
+#define DMA_EP_STS_EN_TRBERREN BIT(7)
+/* OUT size mismatch enable. */
+#define DMA_EP_STS_EN_OUTSMMEN BIT(14)
+/* ISO transmission error enable. */
+#define DMA_EP_STS_EN_ISOERREN BIT(15)
+
+/* DMA_EP_IEN - bitmasks. */
+#define DMA_EP_IEN(index) (1 << (index))
+#define DMA_EP_IEN_EP_OUT0 BIT(0)
+#define DMA_EP_IEN_EP_IN0 BIT(16)
+
+/* DMA_EP_ISTS - bitmasks. */
+#define DMA_EP_ISTS(index) (1 << (index))
+#define DMA_EP_ISTS_EP_OUT0 BIT(0)
+#define DMA_EP_ISTS_EP_IN0 BIT(16)
+
+#define gadget_to_cdns2_device(g) (container_of(g, struct cdns2_device, gadget))
+#define ep_to_cdns2_ep(ep) (container_of(ep, struct cdns2_endpoint, endpoint))
+
+/*-------------------------------------------------------------------------*/
+#define TRBS_PER_SEGMENT 600
+#define ISO_MAX_INTERVAL 8
+#define MAX_TRB_LENGTH BIT(16)
+#define MAX_ISO_SIZE 3076
+/*
+ * To improve performance the TRB buffer pointers can't cross
+ * 4KB boundaries.
+ */
+#define TRB_MAX_ISO_BUFF_SHIFT 12
+#define TRB_MAX_ISO_BUFF_SIZE BIT(TRB_MAX_ISO_BUFF_SHIFT)
+/* How much data is left before the 4KB boundary? */
+#define TRB_BUFF_LEN_UP_TO_BOUNDARY(addr) (TRB_MAX_ISO_BUFF_SIZE - \
+ ((addr) & (TRB_MAX_ISO_BUFF_SIZE - 1)))
+
+#if TRBS_PER_SEGMENT < 2
+#error "Incorrect TRBS_PER_SEGMENT. Minimal Transfer Ring size is 2."
+#endif
+
+/**
+ * struct cdns2_trb - represent Transfer Descriptor block.
+ * @buffer: pointer to buffer data.
+ * @length: length of data.
+ * @control: control flags.
+ *
+ * This structure describes transfer block handled by DMA module.
+ */
+struct cdns2_trb {
+ __le32 buffer;
+ __le32 length;
+ __le32 control;
+};
+
+#define TRB_SIZE (sizeof(struct cdns2_trb))
+/*
+ * These two extra TRBs are reserved for isochronous transfer
+ * to inject 0 length packet and extra LINK TRB to synchronize the ISO transfer.
+ */
+#define TRB_ISO_RESERVED 2
+#define TR_SEG_SIZE (TRB_SIZE * (TRBS_PER_SEGMENT + TRB_ISO_RESERVED))
+
+/* TRB bit mask. */
+#define TRB_TYPE_BITMASK GENMASK(15, 10)
+#define TRB_TYPE(p) ((p) << 10)
+#define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10)
+
+/* TRB type IDs. */
+/* Used for Bulk, Interrupt, ISOC, and control data stage. */
+#define TRB_NORMAL 1
+/* TRB for linking ring segments. */
+#define TRB_LINK 6
+
+/* Cycle bit - indicates TRB ownership by driver or hw. */
+#define TRB_CYCLE BIT(0)
+/*
+ * When set to '1', the device will toggle its interpretation of the Cycle bit.
+ */
+#define TRB_TOGGLE BIT(1)
+/* Interrupt on short packet. */
+#define TRB_ISP BIT(2)
+/* Chain bit associate this TRB with next one TRB. */
+#define TRB_CHAIN BIT(4)
+/* Interrupt on completion. */
+#define TRB_IOC BIT(5)
+
+/* Transfer_len bitmasks. */
+#define TRB_LEN(p) ((p) & GENMASK(16, 0))
+#define TRB_BURST(p) (((p) << 24) & GENMASK(31, 24))
+#define TRB_FIELD_TO_BURST(p) (((p) & GENMASK(31, 24)) >> 24)
+
+/* Data buffer pointer bitmasks. */
+#define TRB_BUFFER(p) ((p) & GENMASK(31, 0))
+
+/*-------------------------------------------------------------------------*/
+/* Driver numeric constants. */
+
+/* Maximum address that can be assigned to device. */
+#define USB_DEVICE_MAX_ADDRESS 127
+
+/* One control and 15 IN and 15 OUT endpoints. */
+#define CDNS2_ENDPOINTS_NUM 31
+
+#define CDNS2_EP_ZLP_BUF_SIZE 512
+
+/*-------------------------------------------------------------------------*/
+/* Used structures. */
+
+struct cdns2_device;
+
+/**
+ * struct cdns2_ring - transfer ring representation.
+ * @trbs: pointer to transfer ring.
+ * @dma: dma address of transfer ring.
+ * @free_trbs: number of free TRBs in transfer ring.
+ * @pcs: producer cycle state.
+ * @ccs: consumer cycle state.
+ * @enqueue: enqueue index in transfer ring.
+ * @dequeue: dequeue index in transfer ring.
+ */
+struct cdns2_ring {
+ struct cdns2_trb *trbs;
+ dma_addr_t dma;
+ int free_trbs;
+ u8 pcs;
+ u8 ccs;
+ int enqueue;
+ int dequeue;
+};
+
+/**
+ * struct cdns2_endpoint - extended device side representation of USB endpoint.
+ * @endpoint: usb endpoint.
+ * @pending_list: list of requests queuing on transfer ring.
+ * @deferred_list: list of requests waiting for queuing on transfer ring.
+ * @pdev: device associated with endpoint.
+ * @name: a human readable name e.g. ep1out.
+ * @ring: transfer ring associated with endpoint.
+ * @ep_state: state of endpoint.
+ * @idx: index of endpoint in pdev->eps table.
+ * @dir: endpoint direction.
+ * @num: endpoint number (1 - 15).
+ * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK.
+ * @interval: interval between packets used for ISOC and Interrupt endpoint.
+ * @buffering: on-chip buffers assigned to endpoint.
+ * @trb_burst_size: number of burst used in TRB.
+ * @skip: Sometimes the controller cannot process isochronous endpoint ring
+ * quickly enough and it will miss some isoc tds on the ring and
+ * generate ISO transmition error.
+ * Driver sets skip flag when receive a ISO transmition error and
+ * process the missed TDs on the endpoint ring.
+ * @wa1_set: use WA1.
+ * @wa1_trb: TRB assigned to WA1.
+ * @wa1_trb_index: TRB index for WA1.
+ * @wa1_cycle_bit: correct cycle bit for WA1.
+ */
+struct cdns2_endpoint {
+ struct usb_ep endpoint;
+ struct list_head pending_list;
+ struct list_head deferred_list;
+
+ struct cdns2_device *pdev;
+ char name[20];
+
+ struct cdns2_ring ring;
+
+#define EP_ENABLED BIT(0)
+#define EP_STALLED BIT(1)
+#define EP_STALL_PENDING BIT(2)
+#define EP_WEDGE BIT(3)
+#define EP_CLAIMED BIT(4)
+#define EP_RING_FULL BIT(5)
+#define EP_DEFERRED_DRDY BIT(6)
+
+ u32 ep_state;
+
+ u8 idx;
+ u8 dir;
+ u8 num;
+ u8 type;
+ int interval;
+ u8 buffering;
+ u8 trb_burst_size;
+ bool skip;
+
+ unsigned int wa1_set:1;
+ struct cdns2_trb *wa1_trb;
+ unsigned int wa1_trb_index;
+ unsigned int wa1_cycle_bit:1;
+};
+
+/**
+ * struct cdns2_request - extended device side representation of usb_request
+ * object.
+ * @request: generic usb_request object describing single I/O request.
+ * @pep: extended representation of usb_ep object.
+ * @trb: the first TRB association with this request.
+ * @start_trb: number of the first TRB in transfer ring.
+ * @end_trb: number of the last TRB in transfer ring.
+ * @list: used for queuing request in lists.
+ * @finished_trb: number of trb has already finished per request.
+ * @num_of_trb: how many trbs are associated with request.
+ */
+struct cdns2_request {
+ struct usb_request request;
+ struct cdns2_endpoint *pep;
+ struct cdns2_trb *trb;
+ int start_trb;
+ int end_trb;
+ struct list_head list;
+ int finished_trb;
+ int num_of_trb;
+};
+
+#define to_cdns2_request(r) (container_of(r, struct cdns2_request, request))
+
+/* Stages used during enumeration process.*/
+#define CDNS2_SETUP_STAGE 0x0
+#define CDNS2_DATA_STAGE 0x1
+#define CDNS2_STATUS_STAGE 0x2
+
+/**
+ * struct cdns2_device - represent USB device.
+ * @dev: pointer to device structure associated whit this controller.
+ * @gadget: device side representation of the peripheral controller.
+ * @gadget_driver: pointer to the gadget driver.
+ * @lock: for synchronizing.
+ * @irq: interrupt line number.
+ * @regs: base address for registers
+ * @usb_regs: base address for common USB registers.
+ * @ep0_regs: base address for endpoint 0 related registers.
+ * @epx_regs: base address for all none control endpoint registers.
+ * @interrupt_regs: base address for interrupt handling related registers.
+ * @adma_regs: base address for ADMA registers.
+ * @eps_dma_pool: endpoint Transfer Ring pool.
+ * @setup: used while processing usb control requests.
+ * @ep0_preq: private request used while handling EP0.
+ * @ep0_stage: ep0 stage during enumeration process.
+ * @zlp_buf: zlp buffer.
+ * @dev_address: device address assigned by host.
+ * @eps: array of objects describing endpoints.
+ * @selected_ep: actually selected endpoint. It's used only to improve
+ * performance by limiting access to dma_ep_sel register.
+ * @is_selfpowered: device is self powered.
+ * @may_wakeup: allows device to remote wakeup the host.
+ * @status_completion_no_call: indicate that driver is waiting for status
+ * stage completion. It's used in deferred SET_CONFIGURATION request.
+ * @in_lpm: indicate the controller is in low power mode.
+ * @pending_status_wq: workqueue handling status stage for deferred requests.
+ * @pending_status_request: request for which status stage was deferred.
+ * @eps_supported: endpoints supported by controller in form:
+ * bit: 0 - ep0, 1 - epOut1, 2 - epIn1, 3 - epOut2 ...
+ * @burst_opt: array with the best burst size value for different TRB size.
+ * @onchip_tx_buf: size of transmit on-chip buffer in KB.
+ * @onchip_rx_buf: size of receive on-chip buffer in KB.
+ */
+struct cdns2_device {
+ struct device *dev;
+ struct usb_gadget gadget;
+ struct usb_gadget_driver *gadget_driver;
+
+ /* generic spin-lock for drivers */
+ spinlock_t lock;
+ int irq;
+ void __iomem *regs;
+ struct cdns2_usb_regs __iomem *usb_regs;
+ struct cdns2_ep0_regs __iomem *ep0_regs;
+ struct cdns2_epx_regs __iomem *epx_regs;
+ struct cdns2_interrupt_regs __iomem *interrupt_regs;
+ struct cdns2_adma_regs __iomem *adma_regs;
+ struct dma_pool *eps_dma_pool;
+ struct usb_ctrlrequest setup;
+ struct cdns2_request ep0_preq;
+ u8 ep0_stage;
+ void *zlp_buf;
+ u8 dev_address;
+ struct cdns2_endpoint eps[CDNS2_ENDPOINTS_NUM];
+ u32 selected_ep;
+ bool is_selfpowered;
+ bool may_wakeup;
+ bool status_completion_no_call;
+ bool in_lpm;
+ struct work_struct pending_status_wq;
+ struct usb_request *pending_status_request;
+ u32 eps_supported;
+ u8 burst_opt[MAX_ISO_SIZE + 1];
+
+ /*in KB */
+ u16 onchip_tx_buf;
+ u16 onchip_rx_buf;
+};
+
+#define CDNS2_IF_EP_EXIST(pdev, ep_num, dir) \
+ ((pdev)->eps_supported & \
+ (BIT(ep_num) << ((dir) ? 0 : 16)))
+
+dma_addr_t cdns2_trb_virt_to_dma(struct cdns2_endpoint *pep,
+ struct cdns2_trb *trb);
+void cdns2_pending_setup_status_handler(struct work_struct *work);
+void cdns2_select_ep(struct cdns2_device *pdev, u32 ep);
+struct cdns2_request *cdns2_next_preq(struct list_head *list);
+struct usb_request *cdns2_gadget_ep_alloc_request(struct usb_ep *ep,
+ gfp_t gfp_flags);
+void cdns2_gadget_ep_free_request(struct usb_ep *ep,
+ struct usb_request *request);
+int cdns2_gadget_ep_dequeue(struct usb_ep *ep, struct usb_request *request);
+void cdns2_gadget_giveback(struct cdns2_endpoint *pep,
+ struct cdns2_request *priv_req,
+ int status);
+void cdns2_init_ep0(struct cdns2_device *pdev, struct cdns2_endpoint *pep);
+void cdns2_ep0_config(struct cdns2_device *pdev);
+void cdns2_handle_ep0_interrupt(struct cdns2_device *pdev, int dir);
+void cdns2_handle_setup_packet(struct cdns2_device *pdev);
+int cdns2_gadget_resume(struct cdns2_device *pdev, bool hibernated);
+int cdns2_gadget_suspend(struct cdns2_device *pdev);
+void cdns2_gadget_remove(struct cdns2_device *pdev);
+int cdns2_gadget_init(struct cdns2_device *pdev);
+void set_reg_bit_8(void __iomem *ptr, u8 mask);
+int cdns2_halt_endpoint(struct cdns2_device *pdev, struct cdns2_endpoint *pep,
+ int value);
+
+#endif /* __LINUX_CDNS2_GADGET */
diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-pci.c b/drivers/usb/gadget/udc/cdns2/cdns2-pci.c
new file mode 100644
index 000000000000..1691541c9413
--- /dev/null
+++ b/drivers/usb/gadget/udc/cdns2/cdns2-pci.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Cadence USBHS-DEV controller - PCI Glue driver.
+ *
+ * Copyright (C) 2023 Cadence.
+ *
+ * Author: Pawel Laszczak <pawell@cadence.com>
+ *
+ */
+
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+
+#include "cdns2-gadget.h"
+
+#define PCI_DRIVER_NAME "cdns-pci-usbhs"
+#define CDNS_VENDOR_ID 0x17cd
+#define CDNS_DEVICE_ID 0x0120
+#define PCI_BAR_DEV 0
+#define PCI_DEV_FN_DEVICE 0
+
+static int cdns2_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ resource_size_t rsrc_start, rsrc_len;
+ struct device *dev = &pdev->dev;
+ struct cdns2_device *priv_dev;
+ struct resource *res;
+ int ret;
+
+ /* For GADGET PCI (devfn) function number is 0. */
+ if (!id || pdev->devfn != PCI_DEV_FN_DEVICE ||
+ pdev->class != PCI_CLASS_SERIAL_USB_DEVICE)
+ return -EINVAL;
+
+ ret = pcim_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "Enabling PCI device has failed %d\n", ret);
+ return ret;
+ }
+
+ pci_set_master(pdev);
+
+ priv_dev = devm_kzalloc(&pdev->dev, sizeof(*priv_dev), GFP_KERNEL);
+ if (!priv_dev)
+ return -ENOMEM;
+
+ dev_dbg(dev, "Initialize resources\n");
+ rsrc_start = pci_resource_start(pdev, PCI_BAR_DEV);
+ rsrc_len = pci_resource_len(pdev, PCI_BAR_DEV);
+
+ res = devm_request_mem_region(dev, rsrc_start, rsrc_len, "dev");
+ if (!res) {
+ dev_dbg(dev, "controller already in use\n");
+ return -EBUSY;
+ }
+
+ priv_dev->regs = devm_ioremap(dev, rsrc_start, rsrc_len);
+ if (!priv_dev->regs) {
+ dev_dbg(dev, "error mapping memory\n");
+ return -EFAULT;
+ }
+
+ priv_dev->irq = pdev->irq;
+ dev_dbg(dev, "USBSS-DEV physical base addr: %pa\n",
+ &rsrc_start);
+
+ priv_dev->dev = dev;
+
+ priv_dev->eps_supported = 0x000f000f;
+ priv_dev->onchip_tx_buf = 16;
+ priv_dev->onchip_rx_buf = 16;
+
+ ret = cdns2_gadget_init(priv_dev);
+ if (ret)
+ return ret;
+
+ pci_set_drvdata(pdev, priv_dev);
+
+ device_wakeup_enable(&pdev->dev);
+ if (pci_dev_run_wake(pdev))
+ pm_runtime_put_noidle(&pdev->dev);
+
+ return 0;
+}
+
+static void cdns2_pci_remove(struct pci_dev *pdev)
+{
+ struct cdns2_device *priv_dev = pci_get_drvdata(pdev);
+
+ if (pci_dev_run_wake(pdev))
+ pm_runtime_get_noresume(&pdev->dev);
+
+ cdns2_gadget_remove(priv_dev);
+}
+
+static int cdns2_pci_suspend(struct device *dev)
+{
+ struct cdns2_device *priv_dev = dev_get_drvdata(dev);
+
+ return cdns2_gadget_suspend(priv_dev);
+}
+
+static int cdns2_pci_resume(struct device *dev)
+{
+ struct cdns2_device *priv_dev = dev_get_drvdata(dev);
+
+ return cdns2_gadget_resume(priv_dev, 1);
+}
+
+static const struct dev_pm_ops cdns2_pci_pm_ops = {
+ SYSTEM_SLEEP_PM_OPS(cdns2_pci_suspend, cdns2_pci_resume)
+};
+
+static const struct pci_device_id cdns2_pci_ids[] = {
+ { PCI_VENDOR_ID_CDNS, CDNS_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_SERIAL_USB_DEVICE, PCI_ANY_ID },
+ { 0, }
+};
+
+static struct pci_driver cdns2_pci_driver = {
+ .name = "cdns2-pci",
+ .id_table = &cdns2_pci_ids[0],
+ .probe = cdns2_pci_probe,
+ .remove = cdns2_pci_remove,
+ .driver = {
+ .pm = pm_ptr(&cdns2_pci_pm_ops),
+ }
+};
+
+module_pci_driver(cdns2_pci_driver);
+MODULE_DEVICE_TABLE(pci, cdns2_pci_ids);
+
+MODULE_ALIAS("pci:cdns2");
+MODULE_AUTHOR("Pawel Laszczak <pawell@cadence.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cadence CDNS2 PCI driver");
diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-trace.c b/drivers/usb/gadget/udc/cdns2/cdns2-trace.c
new file mode 100644
index 000000000000..de6b8cc3d071
--- /dev/null
+++ b/drivers/usb/gadget/udc/cdns2/cdns2-trace.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * USBHS device controller driver Trace Support
+ *
+ * Copyright (C) 2023 Cadence.
+ *
+ * Author: Pawel Laszczak <pawell@cadence.com>
+ */
+
+#define CREATE_TRACE_POINTS
+#include "cdns2-trace.h"
diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-trace.h b/drivers/usb/gadget/udc/cdns2/cdns2-trace.h
new file mode 100644
index 000000000000..61f241634ea5
--- /dev/null
+++ b/drivers/usb/gadget/udc/cdns2/cdns2-trace.h
@@ -0,0 +1,605 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * USBHS-DEV device controller driver.
+ * Trace support header file.
+ *
+ * Copyright (C) 2023 Cadence.
+ *
+ * Author: Pawel Laszczak <pawell@cadence.com>
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM cdns2-dev
+
+/*
+ * The TRACE_SYSTEM_VAR defaults to TRACE_SYSTEM, but must be a
+ * legitimate C variable. It is not exported to user space.
+ */
+#undef TRACE_SYSTEM_VAR
+#define TRACE_SYSTEM_VAR cdns2_dev
+
+#if !defined(__LINUX_CDNS2_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#define __LINUX_CDNS2_TRACE
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+#include <asm/byteorder.h>
+#include <linux/usb/ch9.h>
+#include "cdns2-gadget.h"
+#include "cdns2-debug.h"
+
+#define CDNS2_MSG_MAX 500
+
+DECLARE_EVENT_CLASS(cdns2_log_enable_disable,
+ TP_PROTO(int set),
+ TP_ARGS(set),
+ TP_STRUCT__entry(
+ __field(int, set)
+ ),
+ TP_fast_assign(
+ __entry->set = set;
+ ),
+ TP_printk("%s", __entry->set ? "enabled" : "disabled")
+);
+
+DEFINE_EVENT(cdns2_log_enable_disable, cdns2_pullup,
+ TP_PROTO(int set),
+ TP_ARGS(set)
+);
+
+DEFINE_EVENT(cdns2_log_enable_disable, cdns2_lpm,
+ TP_PROTO(int set),
+ TP_ARGS(set)
+);
+
+DEFINE_EVENT(cdns2_log_enable_disable, cdns2_may_wakeup,
+ TP_PROTO(int set),
+ TP_ARGS(set)
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_simple,
+ TP_PROTO(char *msg),
+ TP_ARGS(msg),
+ TP_STRUCT__entry(
+ __string(text, msg)
+ ),
+ TP_fast_assign(
+ __assign_str(text, msg);
+ ),
+ TP_printk("%s", __get_str(text))
+);
+
+DEFINE_EVENT(cdns2_log_simple, cdns2_no_room_on_ring,
+ TP_PROTO(char *msg),
+ TP_ARGS(msg)
+);
+
+DEFINE_EVENT(cdns2_log_simple, cdns2_ep0_status_stage,
+ TP_PROTO(char *msg),
+ TP_ARGS(msg)
+);
+
+DEFINE_EVENT(cdns2_log_simple, cdns2_ep0_set_config,
+ TP_PROTO(char *msg),
+ TP_ARGS(msg)
+);
+
+DEFINE_EVENT(cdns2_log_simple, cdns2_ep0_setup,
+ TP_PROTO(char *msg),
+ TP_ARGS(msg)
+);
+
+DEFINE_EVENT(cdns2_log_simple, cdns2_device_state,
+ TP_PROTO(char *msg),
+ TP_ARGS(msg)
+);
+
+TRACE_EVENT(cdns2_ep_halt,
+ TP_PROTO(struct cdns2_endpoint *ep_priv, u8 halt, u8 flush),
+ TP_ARGS(ep_priv, halt, flush),
+ TP_STRUCT__entry(
+ __string(name, ep_priv->name)
+ __field(u8, halt)
+ __field(u8, flush)
+ ),
+ TP_fast_assign(
+ __assign_str(name, ep_priv->name);
+ __entry->halt = halt;
+ __entry->flush = flush;
+ ),
+ TP_printk("Halt %s for %s: %s", __entry->flush ? " and flush" : "",
+ __get_str(name), __entry->halt ? "set" : "cleared")
+);
+
+TRACE_EVENT(cdns2_wa1,
+ TP_PROTO(struct cdns2_endpoint *ep_priv, char *msg),
+ TP_ARGS(ep_priv, msg),
+ TP_STRUCT__entry(
+ __string(ep_name, ep_priv->name)
+ __string(msg, msg)
+ ),
+ TP_fast_assign(
+ __assign_str(ep_name, ep_priv->name);
+ __assign_str(msg, msg);
+ ),
+ TP_printk("WA1: %s %s", __get_str(ep_name), __get_str(msg))
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_doorbell,
+ TP_PROTO(struct cdns2_endpoint *pep, u32 ep_trbaddr),
+ TP_ARGS(pep, ep_trbaddr),
+ TP_STRUCT__entry(
+ __string(name, pep->num ? pep->name :
+ (pep->dir ? "ep0in" : "ep0out"))
+ __field(u32, ep_trbaddr)
+ ),
+ TP_fast_assign(
+ __assign_str(name, pep->name);
+ __entry->ep_trbaddr = ep_trbaddr;
+ ),
+ TP_printk("%s, ep_trbaddr %08x", __get_str(name),
+ __entry->ep_trbaddr)
+);
+
+DEFINE_EVENT(cdns2_log_doorbell, cdns2_doorbell_ep0,
+ TP_PROTO(struct cdns2_endpoint *pep, u32 ep_trbaddr),
+ TP_ARGS(pep, ep_trbaddr)
+);
+
+DEFINE_EVENT(cdns2_log_doorbell, cdns2_doorbell_epx,
+ TP_PROTO(struct cdns2_endpoint *pep, u32 ep_trbaddr),
+ TP_ARGS(pep, ep_trbaddr)
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_usb_irq,
+ TP_PROTO(u32 usb_irq, u32 ext_irq),
+ TP_ARGS(usb_irq, ext_irq),
+ TP_STRUCT__entry(
+ __field(u32, usb_irq)
+ __field(u32, ext_irq)
+ ),
+ TP_fast_assign(
+ __entry->usb_irq = usb_irq;
+ __entry->ext_irq = ext_irq;
+ ),
+ TP_printk("%s", cdns2_decode_usb_irq(__get_buf(CDNS2_MSG_MAX),
+ CDNS2_MSG_MAX,
+ __entry->usb_irq,
+ __entry->ext_irq))
+);
+
+DEFINE_EVENT(cdns2_log_usb_irq, cdns2_usb_irq,
+ TP_PROTO(u32 usb_irq, u32 ext_irq),
+ TP_ARGS(usb_irq, ext_irq)
+);
+
+TRACE_EVENT(cdns2_dma_ep_ists,
+ TP_PROTO(u32 dma_ep_ists),
+ TP_ARGS(dma_ep_ists),
+ TP_STRUCT__entry(
+ __field(u32, dma_ep_ists)
+ ),
+ TP_fast_assign(
+ __entry->dma_ep_ists = dma_ep_ists;
+ ),
+ TP_printk("OUT: 0x%04x, IN: 0x%04x", (u16)__entry->dma_ep_ists,
+ __entry->dma_ep_ists >> 16)
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_epx_irq,
+ TP_PROTO(struct cdns2_device *pdev, struct cdns2_endpoint *pep),
+ TP_ARGS(pdev, pep),
+ TP_STRUCT__entry(
+ __string(ep_name, pep->name)
+ __field(u32, ep_sts)
+ __field(u32, ep_ists)
+ __field(u32, ep_traddr)
+ ),
+ TP_fast_assign(
+ __assign_str(ep_name, pep->name);
+ __entry->ep_sts = readl(&pdev->adma_regs->ep_sts);
+ __entry->ep_ists = readl(&pdev->adma_regs->ep_ists);
+ __entry->ep_traddr = readl(&pdev->adma_regs->ep_traddr);
+ ),
+ TP_printk("%s, ep_traddr: %08x",
+ cdns2_decode_epx_irq(__get_buf(CDNS2_MSG_MAX), CDNS2_MSG_MAX,
+ __get_str(ep_name),
+ __entry->ep_ists, __entry->ep_sts),
+ __entry->ep_traddr)
+);
+
+DEFINE_EVENT(cdns2_log_epx_irq, cdns2_epx_irq,
+ TP_PROTO(struct cdns2_device *pdev, struct cdns2_endpoint *pep),
+ TP_ARGS(pdev, pep)
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_ep0_irq,
+ TP_PROTO(struct cdns2_device *pdev),
+ TP_ARGS(pdev),
+ TP_STRUCT__entry(
+ __field(int, ep_dir)
+ __field(u32, ep_ists)
+ __field(u32, ep_sts)
+ ),
+ TP_fast_assign(
+ __entry->ep_dir = pdev->selected_ep;
+ __entry->ep_ists = readl(&pdev->adma_regs->ep_ists);
+ __entry->ep_sts = readl(&pdev->adma_regs->ep_sts);
+ ),
+ TP_printk("%s", cdns2_decode_ep0_irq(__get_buf(CDNS2_MSG_MAX),
+ CDNS2_MSG_MAX,
+ __entry->ep_ists, __entry->ep_sts,
+ __entry->ep_dir))
+);
+
+DEFINE_EVENT(cdns2_log_ep0_irq, cdns2_ep0_irq,
+ TP_PROTO(struct cdns2_device *pdev),
+ TP_ARGS(pdev)
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_ctrl,
+ TP_PROTO(struct usb_ctrlrequest *ctrl),
+ TP_ARGS(ctrl),
+ TP_STRUCT__entry(
+ __field(u8, bRequestType)
+ __field(u8, bRequest)
+ __field(u16, wValue)
+ __field(u16, wIndex)
+ __field(u16, wLength)
+ ),
+ TP_fast_assign(
+ __entry->bRequestType = ctrl->bRequestType;
+ __entry->bRequest = ctrl->bRequest;
+ __entry->wValue = le16_to_cpu(ctrl->wValue);
+ __entry->wIndex = le16_to_cpu(ctrl->wIndex);
+ __entry->wLength = le16_to_cpu(ctrl->wLength);
+ ),
+ TP_printk("%s", usb_decode_ctrl(__get_buf(CDNS2_MSG_MAX), CDNS2_MSG_MAX,
+ __entry->bRequestType,
+ __entry->bRequest, __entry->wValue,
+ __entry->wIndex, __entry->wLength)
+ )
+);
+
+DEFINE_EVENT(cdns2_log_ctrl, cdns2_ctrl_req,
+ TP_PROTO(struct usb_ctrlrequest *ctrl),
+ TP_ARGS(ctrl)
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_request,
+ TP_PROTO(struct cdns2_request *preq),
+ TP_ARGS(preq),
+ TP_STRUCT__entry(
+ __string(name, preq->pep->name)
+ __field(struct usb_request *, request)
+ __field(struct cdns2_request *, preq)
+ __field(void *, buf)
+ __field(unsigned int, actual)
+ __field(unsigned int, length)
+ __field(int, status)
+ __field(dma_addr_t, dma)
+ __field(int, zero)
+ __field(int, short_not_ok)
+ __field(int, no_interrupt)
+ __field(struct scatterlist*, sg)
+ __field(unsigned int, num_sgs)
+ __field(unsigned int, num_mapped_sgs)
+ __field(int, start_trb)
+ __field(int, end_trb)
+ ),
+ TP_fast_assign(
+ __assign_str(name, preq->pep->name);
+ __entry->request = &preq->request;
+ __entry->preq = preq;
+ __entry->buf = preq->request.buf;
+ __entry->actual = preq->request.actual;
+ __entry->length = preq->request.length;
+ __entry->status = preq->request.status;
+ __entry->dma = preq->request.dma;
+ __entry->zero = preq->request.zero;
+ __entry->short_not_ok = preq->request.short_not_ok;
+ __entry->no_interrupt = preq->request.no_interrupt;
+ __entry->sg = preq->request.sg;
+ __entry->num_sgs = preq->request.num_sgs;
+ __entry->num_mapped_sgs = preq->request.num_mapped_sgs;
+ __entry->start_trb = preq->start_trb;
+ __entry->end_trb = preq->end_trb;
+ ),
+ TP_printk("%s: req: %p, preq: %p, req buf: %p, length: %u/%u, status: %d,"
+ "buf dma: (%pad), %s%s%s, sg: %p, num_sgs: %d, num_m_sgs: %d,"
+ "trb: [start: %d, end: %d]",
+ __get_str(name), __entry->request, __entry->preq,
+ __entry->buf, __entry->actual, __entry->length,
+ __entry->status, &__entry->dma,
+ __entry->zero ? "Z" : "z",
+ __entry->short_not_ok ? "S" : "s",
+ __entry->no_interrupt ? "I" : "i",
+ __entry->sg, __entry->num_sgs, __entry->num_mapped_sgs,
+ __entry->start_trb,
+ __entry->end_trb
+ )
+);
+
+DEFINE_EVENT(cdns2_log_request, cdns2_request_enqueue,
+ TP_PROTO(struct cdns2_request *preq),
+ TP_ARGS(preq)
+);
+
+DEFINE_EVENT(cdns2_log_request, cdns2_request_enqueue_error,
+ TP_PROTO(struct cdns2_request *preq),
+ TP_ARGS(preq)
+);
+
+DEFINE_EVENT(cdns2_log_request, cdns2_alloc_request,
+ TP_PROTO(struct cdns2_request *preq),
+ TP_ARGS(preq)
+);
+
+DEFINE_EVENT(cdns2_log_request, cdns2_free_request,
+ TP_PROTO(struct cdns2_request *preq),
+ TP_ARGS(preq)
+);
+
+DEFINE_EVENT(cdns2_log_request, cdns2_ep_queue,
+ TP_PROTO(struct cdns2_request *preq),
+ TP_ARGS(preq)
+);
+
+DEFINE_EVENT(cdns2_log_request, cdns2_request_dequeue,
+ TP_PROTO(struct cdns2_request *preq),
+ TP_ARGS(preq)
+);
+
+DEFINE_EVENT(cdns2_log_request, cdns2_request_giveback,
+ TP_PROTO(struct cdns2_request *preq),
+ TP_ARGS(preq)
+);
+
+TRACE_EVENT(cdns2_ep0_enqueue,
+ TP_PROTO(struct cdns2_device *dev_priv, struct usb_request *request),
+ TP_ARGS(dev_priv, request),
+ TP_STRUCT__entry(
+ __field(int, dir)
+ __field(int, length)
+ ),
+ TP_fast_assign(
+ __entry->dir = dev_priv->eps[0].dir;
+ __entry->length = request->length;
+ ),
+ TP_printk("Queue to ep0%s length: %u", __entry->dir ? "in" : "out",
+ __entry->length)
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_map_request,
+ TP_PROTO(struct cdns2_request *priv_req),
+ TP_ARGS(priv_req),
+ TP_STRUCT__entry(
+ __string(name, priv_req->pep->name)
+ __field(struct usb_request *, req)
+ __field(void *, buf)
+ __field(dma_addr_t, dma)
+ ),
+ TP_fast_assign(
+ __assign_str(name, priv_req->pep->name);
+ __entry->req = &priv_req->request;
+ __entry->buf = priv_req->request.buf;
+ __entry->dma = priv_req->request.dma;
+ ),
+ TP_printk("%s: req: %p, req buf %p, dma %p",
+ __get_str(name), __entry->req, __entry->buf, &__entry->dma
+ )
+);
+
+DEFINE_EVENT(cdns2_log_map_request, cdns2_map_request,
+ TP_PROTO(struct cdns2_request *req),
+ TP_ARGS(req)
+);
+DEFINE_EVENT(cdns2_log_map_request, cdns2_mapped_request,
+ TP_PROTO(struct cdns2_request *req),
+ TP_ARGS(req)
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_trb,
+ TP_PROTO(struct cdns2_endpoint *pep, struct cdns2_trb *trb),
+ TP_ARGS(pep, trb),
+ TP_STRUCT__entry(
+ __string(name, pep->name)
+ __field(struct cdns2_trb *, trb)
+ __field(u32, buffer)
+ __field(u32, length)
+ __field(u32, control)
+ __field(u32, type)
+ ),
+ TP_fast_assign(
+ __assign_str(name, pep->name);
+ __entry->trb = trb;
+ __entry->buffer = le32_to_cpu(trb->buffer);
+ __entry->length = le32_to_cpu(trb->length);
+ __entry->control = le32_to_cpu(trb->control);
+ __entry->type = usb_endpoint_type(pep->endpoint.desc);
+ ),
+ TP_printk("%s: trb V: %p, dma buf: P: 0x%08x, %s",
+ __get_str(name), __entry->trb, __entry->buffer,
+ cdns2_decode_trb(__get_buf(CDNS2_MSG_MAX), CDNS2_MSG_MAX,
+ __entry->control, __entry->length,
+ __entry->buffer))
+);
+
+DEFINE_EVENT(cdns2_log_trb, cdns2_queue_trb,
+ TP_PROTO(struct cdns2_endpoint *pep, struct cdns2_trb *trb),
+ TP_ARGS(pep, trb)
+);
+
+DEFINE_EVENT(cdns2_log_trb, cdns2_complete_trb,
+ TP_PROTO(struct cdns2_endpoint *pep, struct cdns2_trb *trb),
+ TP_ARGS(pep, trb)
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_ring,
+ TP_PROTO(struct cdns2_endpoint *pep),
+ TP_ARGS(pep),
+ TP_STRUCT__entry(
+ __dynamic_array(u8, tr_seg, TR_SEG_SIZE)
+ __dynamic_array(u8, pep, sizeof(struct cdns2_endpoint))
+ __dynamic_array(char, buffer,
+ (TRBS_PER_SEGMENT * 65) + CDNS2_MSG_MAX)
+ ),
+ TP_fast_assign(
+ memcpy(__get_dynamic_array(pep), pep,
+ sizeof(struct cdns2_endpoint));
+ memcpy(__get_dynamic_array(tr_seg), pep->ring.trbs,
+ TR_SEG_SIZE);
+ ),
+
+ TP_printk("%s",
+ cdns2_raw_ring((struct cdns2_endpoint *)__get_str(pep),
+ (struct cdns2_trb *)__get_str(tr_seg),
+ __get_str(buffer),
+ (TRBS_PER_SEGMENT * 65) + CDNS2_MSG_MAX))
+);
+
+DEFINE_EVENT(cdns2_log_ring, cdns2_ring,
+ TP_PROTO(struct cdns2_endpoint *pep),
+ TP_ARGS(pep)
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_ep,
+ TP_PROTO(struct cdns2_endpoint *pep),
+ TP_ARGS(pep),
+ TP_STRUCT__entry(
+ __string(name, pep->name)
+ __field(unsigned int, maxpacket)
+ __field(unsigned int, maxpacket_limit)
+ __field(unsigned int, flags)
+ __field(unsigned int, dir)
+ __field(u8, enqueue)
+ __field(u8, dequeue)
+ ),
+ TP_fast_assign(
+ __assign_str(name, pep->name);
+ __entry->maxpacket = pep->endpoint.maxpacket;
+ __entry->maxpacket_limit = pep->endpoint.maxpacket_limit;
+ __entry->flags = pep->ep_state;
+ __entry->dir = pep->dir;
+ __entry->enqueue = pep->ring.enqueue;
+ __entry->dequeue = pep->ring.dequeue;
+ ),
+ TP_printk("%s: mps: %d/%d, enq idx: %d, deq idx: %d, "
+ "flags: %s%s%s%s, dir: %s",
+ __get_str(name), __entry->maxpacket,
+ __entry->maxpacket_limit, __entry->enqueue,
+ __entry->dequeue,
+ __entry->flags & EP_ENABLED ? "EN | " : "",
+ __entry->flags & EP_STALLED ? "STALLED | " : "",
+ __entry->flags & EP_WEDGE ? "WEDGE | " : "",
+ __entry->flags & EP_RING_FULL ? "RING FULL |" : "",
+ __entry->dir ? "IN" : "OUT"
+ )
+);
+
+DEFINE_EVENT(cdns2_log_ep, cdns2_gadget_ep_enable,
+ TP_PROTO(struct cdns2_endpoint *pep),
+ TP_ARGS(pep)
+);
+
+DEFINE_EVENT(cdns2_log_ep, cdns2_gadget_ep_disable,
+ TP_PROTO(struct cdns2_endpoint *pep),
+ TP_ARGS(pep)
+);
+
+DEFINE_EVENT(cdns2_log_ep, cdns2_iso_out_ep_disable,
+ TP_PROTO(struct cdns2_endpoint *pep),
+ TP_ARGS(pep)
+);
+
+DEFINE_EVENT(cdns2_log_ep, cdns2_ep_busy_try_halt_again,
+ TP_PROTO(struct cdns2_endpoint *pep),
+ TP_ARGS(pep)
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_request_handled,
+ TP_PROTO(struct cdns2_request *priv_req, int current_index,
+ int handled),
+ TP_ARGS(priv_req, current_index, handled),
+ TP_STRUCT__entry(
+ __field(struct cdns2_request *, priv_req)
+ __field(unsigned int, dma_position)
+ __field(unsigned int, handled)
+ __field(unsigned int, dequeue_idx)
+ __field(unsigned int, enqueue_idx)
+ __field(unsigned int, start_trb)
+ __field(unsigned int, end_trb)
+ ),
+ TP_fast_assign(
+ __entry->priv_req = priv_req;
+ __entry->dma_position = current_index;
+ __entry->handled = handled;
+ __entry->dequeue_idx = priv_req->pep->ring.dequeue;
+ __entry->enqueue_idx = priv_req->pep->ring.enqueue;
+ __entry->start_trb = priv_req->start_trb;
+ __entry->end_trb = priv_req->end_trb;
+ ),
+ TP_printk("Req: %p %s, DMA pos: %d, ep deq: %d, ep enq: %d,"
+ " start trb: %d, end trb: %d",
+ __entry->priv_req,
+ __entry->handled ? "handled" : "not handled",
+ __entry->dma_position, __entry->dequeue_idx,
+ __entry->enqueue_idx, __entry->start_trb,
+ __entry->end_trb
+ )
+);
+
+DEFINE_EVENT(cdns2_log_request_handled, cdns2_request_handled,
+ TP_PROTO(struct cdns2_request *priv_req, int current_index,
+ int handled),
+ TP_ARGS(priv_req, current_index, handled)
+);
+
+DECLARE_EVENT_CLASS(cdns2_log_epx_reg_config,
+ TP_PROTO(struct cdns2_device *pdev, struct cdns2_endpoint *pep),
+ TP_ARGS(pdev, pep),
+ TP_STRUCT__entry(
+ __string(ep_name, pep->name)
+ __field(u8, burst_size)
+ __field(__le16, maxpack_reg)
+ __field(__u8, con_reg)
+ __field(u32, ep_sel_reg)
+ __field(u32, ep_sts_en_reg)
+ __field(u32, ep_cfg_reg)
+ ),
+ TP_fast_assign(
+ __assign_str(ep_name, pep->name);
+ __entry->burst_size = pep->trb_burst_size;
+ __entry->maxpack_reg = pep->dir ? readw(&pdev->epx_regs->txmaxpack[pep->num - 1]) :
+ readw(&pdev->epx_regs->rxmaxpack[pep->num - 1]);
+ __entry->con_reg = pep->dir ? readb(&pdev->epx_regs->ep[pep->num - 1].txcon) :
+ readb(&pdev->epx_regs->ep[pep->num - 1].rxcon);
+ __entry->ep_sel_reg = readl(&pdev->adma_regs->ep_sel);
+ __entry->ep_sts_en_reg = readl(&pdev->adma_regs->ep_sts_en);
+ __entry->ep_cfg_reg = readl(&pdev->adma_regs->ep_cfg);
+ ),
+
+ TP_printk("%s, maxpack: %d, con: %02x, dma_ep_sel: %08x, dma_ep_sts_en: %08x"
+ " dma_ep_cfg %08x",
+ __get_str(ep_name), __entry->maxpack_reg, __entry->con_reg,
+ __entry->ep_sel_reg, __entry->ep_sts_en_reg,
+ __entry->ep_cfg_reg
+ )
+);
+
+DEFINE_EVENT(cdns2_log_epx_reg_config, cdns2_epx_hw_cfg,
+ TP_PROTO(struct cdns2_device *pdev, struct cdns2_endpoint *pep),
+ TP_ARGS(pdev, pep)
+);
+
+#endif /* __LINUX_CDNS2_TRACE */
+
+/* This part must be outside header guard. */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE cdns2-trace
+
+#include <trace/define_trace.h>
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 83fd1de14784..59188ea065e0 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -61,7 +61,7 @@ struct usb_udc {
struct mutex connect_lock;
};
-static struct class *udc_class;
+static const struct class udc_class;
static LIST_HEAD(udc_list);
/* Protects udc_list, udc->driver, driver->is_bound, and related calls */
@@ -1378,7 +1378,7 @@ int usb_add_gadget(struct usb_gadget *gadget)
device_initialize(&udc->dev);
udc->dev.release = usb_udc_release;
- udc->dev.class = udc_class;
+ udc->dev.class = &udc_class;
udc->dev.groups = usb_udc_attr_groups;
udc->dev.parent = gadget->dev.parent;
ret = dev_set_name(&udc->dev, "%s",
@@ -1856,6 +1856,11 @@ static int usb_udc_uevent(const struct device *dev, struct kobj_uevent_env *env)
return 0;
}
+static const struct class udc_class = {
+ .name = "udc",
+ .dev_uevent = usb_udc_uevent,
+};
+
static const struct bus_type gadget_bus_type = {
.name = "gadget",
.probe = gadget_bind_driver,
@@ -1867,18 +1872,13 @@ static int __init usb_udc_init(void)
{
int rc;
- udc_class = class_create("udc");
- if (IS_ERR(udc_class)) {
- pr_err("failed to create udc class --> %ld\n",
- PTR_ERR(udc_class));
- return PTR_ERR(udc_class);
- }
-
- udc_class->dev_uevent = usb_udc_uevent;
+ rc = class_register(&udc_class);
+ if (rc)
+ return rc;
rc = bus_register(&gadget_bus_type);
if (rc)
- class_destroy(udc_class);
+ class_unregister(&udc_class);
return rc;
}
subsys_initcall(usb_udc_init);
@@ -1886,7 +1886,7 @@ subsys_initcall(usb_udc_init);
static void __exit usb_udc_exit(void)
{
bus_unregister(&gadget_bus_type);
- class_destroy(udc_class);
+ class_unregister(&udc_class);
}
module_exit(usb_udc_exit);
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index 899ac9f9c279..0953e1b5c030 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -1108,13 +1108,12 @@ err_udc:
return rc;
}
-static int dummy_udc_remove(struct platform_device *pdev)
+static void dummy_udc_remove(struct platform_device *pdev)
{
struct dummy *dum = platform_get_drvdata(pdev);
device_remove_file(&dum->gadget.dev, &dev_attr_function);
usb_del_gadget_udc(&dum->gadget);
- return 0;
}
static void dummy_udc_pm(struct dummy *dum, struct dummy_hcd *dum_hcd,
@@ -1150,7 +1149,7 @@ static int dummy_udc_resume(struct platform_device *pdev)
static struct platform_driver dummy_udc_driver = {
.probe = dummy_udc_probe,
- .remove = dummy_udc_remove,
+ .remove_new = dummy_udc_remove,
.suspend = dummy_udc_suspend,
.resume = dummy_udc_resume,
.driver = {
@@ -2701,7 +2700,7 @@ put_usb2_hcd:
return retval;
}
-static int dummy_hcd_remove(struct platform_device *pdev)
+static void dummy_hcd_remove(struct platform_device *pdev)
{
struct dummy *dum;
@@ -2717,8 +2716,6 @@ static int dummy_hcd_remove(struct platform_device *pdev)
dum->hs_hcd = NULL;
dum->ss_hcd = NULL;
-
- return 0;
}
static int dummy_hcd_suspend(struct platform_device *pdev, pm_message_t state)
@@ -2753,7 +2750,7 @@ static int dummy_hcd_resume(struct platform_device *pdev)
static struct platform_driver dummy_hcd_driver = {
.probe = dummy_hcd_probe,
- .remove = dummy_hcd_remove,
+ .remove_new = dummy_hcd_remove,
.suspend = dummy_hcd_suspend,
.resume = dummy_hcd_resume,
.driver = {
diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
index 3b1cc8fa30c8..9c5dc1c1a68e 100644
--- a/drivers/usb/gadget/udc/fsl_qe_udc.c
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -2628,7 +2628,7 @@ static int qe_udc_resume(struct platform_device *dev)
}
#endif
-static int qe_udc_remove(struct platform_device *ofdev)
+static void qe_udc_remove(struct platform_device *ofdev)
{
struct qe_udc *udc = platform_get_drvdata(ofdev);
struct qe_ep *ep;
@@ -2679,8 +2679,6 @@ static int qe_udc_remove(struct platform_device *ofdev)
/* wait for release() of gadget.dev to free udc */
wait_for_completion(&done);
-
- return 0;
}
/*-------------------------------------------------------------------------*/
@@ -2708,7 +2706,7 @@ static struct platform_driver udc_driver = {
.of_match_table = qe_udc_match,
},
.probe = qe_udc_probe,
- .remove = qe_udc_remove,
+ .remove_new = qe_udc_remove,
#ifdef CONFIG_PM
.suspend = qe_udc_suspend,
.resume = qe_udc_resume,
diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c
index 08ba9c8c1e67..bd03d475f927 100644
--- a/drivers/usb/gadget/udc/fusb300_udc.c
+++ b/drivers/usb/gadget/udc/fusb300_udc.c
@@ -1338,7 +1338,7 @@ static const struct usb_gadget_ops fusb300_gadget_ops = {
.udc_stop = fusb300_udc_stop,
};
-static int fusb300_remove(struct platform_device *pdev)
+static void fusb300_remove(struct platform_device *pdev)
{
struct fusb300 *fusb300 = platform_get_drvdata(pdev);
int i;
@@ -1352,8 +1352,6 @@ static int fusb300_remove(struct platform_device *pdev)
for (i = 0; i < FUSB300_MAX_NUM_EP; i++)
kfree(fusb300->ep[i]);
kfree(fusb300);
-
- return 0;
}
static int fusb300_probe(struct platform_device *pdev)
@@ -1508,7 +1506,7 @@ clean_up:
}
static struct platform_driver fusb300_driver = {
- .remove = fusb300_remove,
+ .remove_new = fusb300_remove,
.driver = {
.name = udc_name,
},
diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c
index 06e21cee431b..e05f45a4b56b 100644
--- a/drivers/usb/gadget/udc/m66592-udc.c
+++ b/drivers/usb/gadget/udc/m66592-udc.c
@@ -1512,7 +1512,7 @@ static const struct usb_gadget_ops m66592_gadget_ops = {
.pullup = m66592_pullup,
};
-static int m66592_remove(struct platform_device *pdev)
+static void m66592_remove(struct platform_device *pdev)
{
struct m66592 *m66592 = platform_get_drvdata(pdev);
@@ -1527,7 +1527,6 @@ static int m66592_remove(struct platform_device *pdev)
clk_put(m66592->clk);
}
kfree(m66592);
- return 0;
}
static void nop_completion(struct usb_ep *ep, struct usb_request *r)
@@ -1688,7 +1687,7 @@ clean_up:
/*-------------------------------------------------------------------------*/
static struct platform_driver m66592_driver = {
- .remove = m66592_remove,
+ .remove_new = m66592_remove,
.driver = {
.name = udc_name,
},
diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c
index 411b6179782c..3473048a85f5 100644
--- a/drivers/usb/gadget/udc/mv_u3d_core.c
+++ b/drivers/usb/gadget/udc/mv_u3d_core.c
@@ -1746,7 +1746,7 @@ static irqreturn_t mv_u3d_irq(int irq, void *dev)
return IRQ_HANDLED;
}
-static int mv_u3d_remove(struct platform_device *dev)
+static void mv_u3d_remove(struct platform_device *dev)
{
struct mv_u3d *u3d = platform_get_drvdata(dev);
@@ -1775,8 +1775,6 @@ static int mv_u3d_remove(struct platform_device *dev)
clk_put(u3d->clk);
kfree(u3d);
-
- return 0;
}
static int mv_u3d_probe(struct platform_device *dev)
@@ -2049,7 +2047,7 @@ static void mv_u3d_shutdown(struct platform_device *dev)
static struct platform_driver mv_u3d_driver = {
.probe = mv_u3d_probe,
- .remove = mv_u3d_remove,
+ .remove_new = mv_u3d_remove,
.shutdown = mv_u3d_shutdown,
.driver = {
.name = "mv-u3d",
diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c
index 08474c08d874..79db74e2040b 100644
--- a/drivers/usb/gadget/udc/mv_udc_core.c
+++ b/drivers/usb/gadget/udc/mv_udc_core.c
@@ -2077,7 +2077,7 @@ static void gadget_release(struct device *_dev)
complete(udc->done);
}
-static int mv_udc_remove(struct platform_device *pdev)
+static void mv_udc_remove(struct platform_device *pdev)
{
struct mv_udc *udc;
@@ -2099,8 +2099,6 @@ static int mv_udc_remove(struct platform_device *pdev)
/* free dev, wait for the release() finished */
wait_for_completion(udc->done);
-
- return 0;
}
static int mv_udc_probe(struct platform_device *pdev)
@@ -2411,7 +2409,7 @@ static void mv_udc_shutdown(struct platform_device *pdev)
static struct platform_driver udc_driver = {
.probe = mv_udc_probe,
- .remove = mv_udc_remove,
+ .remove_new = mv_udc_remove,
.shutdown = mv_udc_shutdown,
.driver = {
.name = "mv-udc",
diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c
index 538c1b9a2883..12e76bb62c20 100644
--- a/drivers/usb/gadget/udc/net2272.c
+++ b/drivers/usb/gadget/udc/net2272.c
@@ -2670,7 +2670,7 @@ net2272_plat_probe(struct platform_device *pdev)
return ret;
}
-static int
+static void
net2272_plat_remove(struct platform_device *pdev)
{
struct net2272 *dev = platform_get_drvdata(pdev);
@@ -2681,13 +2681,11 @@ net2272_plat_remove(struct platform_device *pdev)
resource_size(&pdev->resource[0]));
usb_put_gadget(&dev->gadget);
-
- return 0;
}
static struct platform_driver net2272_plat_driver = {
.probe = net2272_plat_probe,
- .remove = net2272_plat_remove,
+ .remove_new = net2272_plat_remove,
.driver = {
.name = driver_name,
},
diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c
index 2d87c7cd5f7e..10c5d7f726a1 100644
--- a/drivers/usb/gadget/udc/omap_udc.c
+++ b/drivers/usb/gadget/udc/omap_udc.c
@@ -2927,7 +2927,7 @@ cleanup0:
return status;
}
-static int omap_udc_remove(struct platform_device *pdev)
+static void omap_udc_remove(struct platform_device *pdev)
{
DECLARE_COMPLETION_ONSTACK(done);
@@ -2939,8 +2939,6 @@ static int omap_udc_remove(struct platform_device *pdev)
release_mem_region(pdev->resource[0].start,
resource_size(&pdev->resource[0]));
-
- return 0;
}
/* suspend/resume/wakeup from sysfs (echo > power/state) or when the
@@ -2985,7 +2983,7 @@ static int omap_udc_resume(struct platform_device *dev)
static struct platform_driver udc_driver = {
.probe = omap_udc_probe,
- .remove = omap_udc_remove,
+ .remove_new = omap_udc_remove,
.suspend = omap_udc_suspend,
.resume = omap_udc_resume,
.driver = {
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c
index 0ecdfd2ba9e9..c4e1d957f913 100644
--- a/drivers/usb/gadget/udc/pxa27x_udc.c
+++ b/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -2445,7 +2445,7 @@ err:
* pxa_udc_remove - removes the udc device driver
* @_dev: platform device
*/
-static int pxa_udc_remove(struct platform_device *_dev)
+static void pxa_udc_remove(struct platform_device *_dev)
{
struct pxa_udc *udc = platform_get_drvdata(_dev);
@@ -2460,8 +2460,6 @@ static int pxa_udc_remove(struct platform_device *_dev)
udc->transceiver = NULL;
the_controller = NULL;
clk_unprepare(udc->clk);
-
- return 0;
}
static void pxa_udc_shutdown(struct platform_device *_dev)
@@ -2472,12 +2470,6 @@ static void pxa_udc_shutdown(struct platform_device *_dev)
udc_disable(udc);
}
-#ifdef CONFIG_PXA27x
-extern void pxa27x_clear_otgph(void);
-#else
-#define pxa27x_clear_otgph() do {} while (0)
-#endif
-
#ifdef CONFIG_PM
/**
* pxa_udc_suspend - Suspend udc device
@@ -2547,7 +2539,7 @@ static struct platform_driver udc_driver = {
.of_match_table = of_match_ptr(udc_pxa_dt_ids),
},
.probe = pxa_udc_probe,
- .remove = pxa_udc_remove,
+ .remove_new = pxa_udc_remove,
.shutdown = pxa_udc_shutdown,
#ifdef CONFIG_PM
.suspend = pxa_udc_suspend,
diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c
index 38e4d6b505a0..51b665f15c8e 100644
--- a/drivers/usb/gadget/udc/r8a66597-udc.c
+++ b/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1805,7 +1805,7 @@ static const struct usb_gadget_ops r8a66597_gadget_ops = {
.set_selfpowered = r8a66597_set_selfpowered,
};
-static int r8a66597_remove(struct platform_device *pdev)
+static void r8a66597_remove(struct platform_device *pdev)
{
struct r8a66597 *r8a66597 = platform_get_drvdata(pdev);
@@ -1816,8 +1816,6 @@ static int r8a66597_remove(struct platform_device *pdev)
if (r8a66597->pdata->on_chip) {
clk_disable_unprepare(r8a66597->clk);
}
-
- return 0;
}
static void nop_completion(struct usb_ep *ep, struct usb_request *r)
@@ -1966,7 +1964,7 @@ clean_up2:
/*-------------------------------------------------------------------------*/
static struct platform_driver r8a66597_driver = {
- .remove = r8a66597_remove,
+ .remove_new = r8a66597_remove,
.driver = {
.name = udc_name,
},
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index eb008e873361..59bb25de2015 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -2653,7 +2653,7 @@ static void renesas_usb3_debugfs_init(struct renesas_usb3 *usb3,
}
/*------- platform_driver ------------------------------------------------*/
-static int renesas_usb3_remove(struct platform_device *pdev)
+static void renesas_usb3_remove(struct platform_device *pdev)
{
struct renesas_usb3 *usb3 = platform_get_drvdata(pdev);
@@ -2669,8 +2669,6 @@ static int renesas_usb3_remove(struct platform_device *pdev)
__renesas_usb3_ep_free_request(usb3->ep0_req);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
static int renesas_usb3_init_ep(struct renesas_usb3 *usb3, struct device *dev,
@@ -3015,7 +3013,7 @@ static SIMPLE_DEV_PM_OPS(renesas_usb3_pm_ops, renesas_usb3_suspend,
static struct platform_driver renesas_usb3_driver = {
.probe = renesas_usb3_probe,
- .remove = renesas_usb3_remove,
+ .remove_new = renesas_usb3_remove,
.driver = {
.name = udc_name,
.pm = &renesas_usb3_pm_ops,
diff --git a/drivers/usb/gadget/udc/renesas_usbf.c b/drivers/usb/gadget/udc/renesas_usbf.c
index 84ac9fe4ce7f..6cd0af83e91e 100644
--- a/drivers/usb/gadget/udc/renesas_usbf.c
+++ b/drivers/usb/gadget/udc/renesas_usbf.c
@@ -3361,15 +3361,13 @@ static int usbf_probe(struct platform_device *pdev)
return 0;
}
-static int usbf_remove(struct platform_device *pdev)
+static void usbf_remove(struct platform_device *pdev)
{
struct usbf_udc *udc = platform_get_drvdata(pdev);
usb_del_gadget_udc(&udc->gadget);
pm_runtime_put(&pdev->dev);
-
- return 0;
}
static const struct of_device_id usbf_match[] = {
@@ -3385,7 +3383,7 @@ static struct platform_driver udc_driver = {
.of_match_table = usbf_match,
},
.probe = usbf_probe,
- .remove = usbf_remove,
+ .remove_new = usbf_remove,
};
module_platform_driver(udc_driver);
diff --git a/drivers/usb/gadget/udc/rzv2m_usb3drd.c b/drivers/usb/gadget/udc/rzv2m_usb3drd.c
index 589c7252e014..36f4ff00d22f 100644
--- a/drivers/usb/gadget/udc/rzv2m_usb3drd.c
+++ b/drivers/usb/gadget/udc/rzv2m_usb3drd.c
@@ -58,7 +58,7 @@ void rzv2m_usb3drd_reset(struct device *dev, bool host)
}
EXPORT_SYMBOL_GPL(rzv2m_usb3drd_reset);
-static int rzv2m_usb3drd_remove(struct platform_device *pdev)
+static void rzv2m_usb3drd_remove(struct platform_device *pdev)
{
struct rzv2m_usb3drd *usb3 = platform_get_drvdata(pdev);
@@ -66,8 +66,6 @@ static int rzv2m_usb3drd_remove(struct platform_device *pdev)
pm_runtime_put(usb3->dev);
pm_runtime_disable(&pdev->dev);
reset_control_assert(usb3->drd_rstc);
-
- return 0;
}
static int rzv2m_usb3drd_probe(struct platform_device *pdev)
@@ -129,7 +127,7 @@ static struct platform_driver rzv2m_usb3drd_driver = {
.of_match_table = rzv2m_usb3drd_of_match,
},
.probe = rzv2m_usb3drd_probe,
- .remove = rzv2m_usb3drd_remove,
+ .remove_new = rzv2m_usb3drd_remove,
};
module_platform_driver(rzv2m_usb3drd_driver);
diff --git a/drivers/usb/gadget/udc/snps_udc_plat.c b/drivers/usb/gadget/udc/snps_udc_plat.c
index 0d3e705655b9..0ed685db149d 100644
--- a/drivers/usb/gadget/udc/snps_udc_plat.c
+++ b/drivers/usb/gadget/udc/snps_udc_plat.c
@@ -225,7 +225,7 @@ exit_phy:
return ret;
}
-static int udc_plat_remove(struct platform_device *pdev)
+static void udc_plat_remove(struct platform_device *pdev)
{
struct udc *dev;
@@ -234,7 +234,7 @@ static int udc_plat_remove(struct platform_device *pdev)
usb_del_gadget_udc(&dev->gadget);
/* gadget driver must not be registered */
if (WARN_ON(dev->driver))
- return 0;
+ return;
/* dma pool cleanup */
free_dma_pools(dev);
@@ -248,8 +248,6 @@ static int udc_plat_remove(struct platform_device *pdev)
extcon_unregister_notifier(dev->edev, EXTCON_USB, &dev->nb);
dev_info(&pdev->dev, "Synopsys UDC platform driver removed\n");
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -315,7 +313,7 @@ MODULE_DEVICE_TABLE(of, of_udc_match);
static struct platform_driver udc_plat_driver = {
.probe = udc_plat_probe,
- .remove = udc_plat_remove,
+ .remove_new = udc_plat_remove,
.driver = {
.name = "snps-udc-plat",
.of_match_table = of_match_ptr(of_udc_match),
diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
index 34e9c1df54c7..83eaa65ddde3 100644
--- a/drivers/usb/gadget/udc/tegra-xudc.c
+++ b/drivers/usb/gadget/udc/tegra-xudc.c
@@ -3906,7 +3906,7 @@ put_padctl:
return err;
}
-static int tegra_xudc_remove(struct platform_device *pdev)
+static void tegra_xudc_remove(struct platform_device *pdev)
{
struct tegra_xudc *xudc = platform_get_drvdata(pdev);
unsigned int i;
@@ -3936,8 +3936,6 @@ static int tegra_xudc_remove(struct platform_device *pdev)
pm_runtime_put(xudc->dev);
tegra_xusb_padctl_put(xudc->padctl);
-
- return 0;
}
static int __maybe_unused tegra_xudc_powergate(struct tegra_xudc *xudc)
@@ -4063,7 +4061,7 @@ static const struct dev_pm_ops tegra_xudc_pm_ops = {
static struct platform_driver tegra_xudc_driver = {
.probe = tegra_xudc_probe,
- .remove = tegra_xudc_remove,
+ .remove_new = tegra_xudc_remove,
.driver = {
.name = "tegra-xudc",
.pm = &tegra_xudc_pm_ops,
diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c
index 4827e3cd3834..a4a7b90a97e7 100644
--- a/drivers/usb/gadget/udc/udc-xilinx.c
+++ b/drivers/usb/gadget/udc/udc-xilinx.c
@@ -192,7 +192,7 @@ struct xusb_udc {
bool dma_enabled;
struct clk *clk;
- unsigned int (*read_fn)(void __iomem *);
+ unsigned int (*read_fn)(void __iomem *reg);
void (*write_fn)(void __iomem *, u32, u32);
};
@@ -2178,14 +2178,12 @@ fail:
*
* Return: 0 always
*/
-static int xudc_remove(struct platform_device *pdev)
+static void xudc_remove(struct platform_device *pdev)
{
struct xusb_udc *udc = platform_get_drvdata(pdev);
usb_del_gadget_udc(&udc->gadget);
clk_disable_unprepare(udc->clk);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -2257,7 +2255,7 @@ static struct platform_driver xudc_driver = {
.pm = &xudc_pm_ops,
},
.probe = xudc_probe,
- .remove = xudc_remove,
+ .remove_new = xudc_remove,
};
module_platform_driver(xudc_driver);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index c170672f847e..4448d0ab06f0 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -376,7 +376,7 @@ config USB_ISP116X_HCD
config USB_ISP1362_HCD
tristate "ISP1362 HCD support"
- depends on HAS_IOMEM
+ depends on HAS_IOPORT
depends on COMPILE_TEST # nothing uses this
help
Supports the Philips ISP1362 chip as a host controller
@@ -578,7 +578,7 @@ endif # USB_OHCI_HCD
config USB_UHCI_HCD
tristate "UHCI HCD (most Intel and VIA) support"
- depends on USB_PCI || USB_UHCI_SUPPORT_NON_PCI_HC
+ depends on (USB_PCI && HAS_IOPORT) || USB_UHCI_SUPPORT_NON_PCI_HC
help
The Universal Host Controller Interface is a standard by Intel for
accessing the USB hardware in the PC (which is also called the USB
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 8b775e7bab06..61808c51e702 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -173,7 +173,7 @@ fail_create_hcd:
return retval;
}
-static int ehci_atmel_drv_remove(struct platform_device *pdev)
+static void ehci_atmel_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -181,8 +181,6 @@ static int ehci_atmel_drv_remove(struct platform_device *pdev)
usb_put_hcd(hcd);
atmel_stop_ehci(pdev);
-
- return 0;
}
static int __maybe_unused ehci_atmel_drv_suspend(struct device *dev)
@@ -223,7 +221,7 @@ static SIMPLE_DEV_PM_OPS(ehci_atmel_pm_ops, ehci_atmel_drv_suspend,
static struct platform_driver ehci_atmel_driver = {
.probe = ehci_atmel_drv_probe,
- .remove = ehci_atmel_drv_remove,
+ .remove_new = ehci_atmel_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "atmel-ehci",
diff --git a/drivers/usb/host/ehci-brcm.c b/drivers/usb/host/ehci-brcm.c
index 6a0f64c9e5e8..0362a082abb4 100644
--- a/drivers/usb/host/ehci-brcm.c
+++ b/drivers/usb/host/ehci-brcm.c
@@ -188,7 +188,7 @@ err_hcd:
return err;
}
-static int ehci_brcm_remove(struct platform_device *dev)
+static void ehci_brcm_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct brcm_priv *priv = hcd_to_ehci_priv(hcd);
@@ -196,7 +196,6 @@ static int ehci_brcm_remove(struct platform_device *dev)
usb_remove_hcd(hcd);
clk_disable_unprepare(priv->clk);
usb_put_hcd(hcd);
- return 0;
}
static int __maybe_unused ehci_brcm_suspend(struct device *dev)
@@ -250,7 +249,7 @@ static const struct of_device_id brcm_ehci_of_match[] = {
static struct platform_driver ehci_brcm_driver = {
.probe = ehci_brcm_probe,
- .remove = ehci_brcm_remove,
+ .remove_new = ehci_brcm_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ehci-brcm",
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index 47c9f06c3d84..20f8c0ec6810 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -230,7 +230,7 @@ fail_clk:
return err;
}
-static int exynos_ehci_remove(struct platform_device *pdev)
+static void exynos_ehci_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd);
@@ -244,8 +244,6 @@ static int exynos_ehci_remove(struct platform_device *pdev)
clk_disable_unprepare(exynos_ehci->clk);
usb_put_hcd(hcd);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -311,7 +309,7 @@ MODULE_DEVICE_TABLE(of, exynos_ehci_match);
static struct platform_driver exynos_ehci_driver = {
.probe = exynos_ehci_probe,
- .remove = exynos_ehci_remove,
+ .remove_new = exynos_ehci_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "exynos-ehci",
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index d74fa5ba845b..81d60a695510 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -684,7 +684,7 @@ static const struct ehci_driver_overrides ehci_fsl_overrides __initconst = {
*
* Reverses the effect of usb_hcd_fsl_probe().
*/
-static int fsl_ehci_drv_remove(struct platform_device *pdev)
+static void fsl_ehci_drv_remove(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -703,13 +703,11 @@ static int fsl_ehci_drv_remove(struct platform_device *pdev)
if (pdata->exit)
pdata->exit(pdev);
usb_put_hcd(hcd);
-
- return 0;
}
static struct platform_driver ehci_fsl_driver = {
.probe = fsl_ehci_drv_probe,
- .remove = fsl_ehci_drv_remove,
+ .remove_new = fsl_ehci_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
index 0717f2ccf49d..14150e4d3382 100644
--- a/drivers/usb/host/ehci-grlib.c
+++ b/drivers/usb/host/ehci-grlib.c
@@ -140,7 +140,7 @@ err_irq:
}
-static int ehci_hcd_grlib_remove(struct platform_device *op)
+static void ehci_hcd_grlib_remove(struct platform_device *op)
{
struct usb_hcd *hcd = platform_get_drvdata(op);
@@ -151,8 +151,6 @@ static int ehci_hcd_grlib_remove(struct platform_device *op)
irq_dispose_mapping(hcd->irq);
usb_put_hcd(hcd);
-
- return 0;
}
@@ -170,7 +168,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_grlib_of_match);
static struct platform_driver ehci_grlib_driver = {
.probe = ehci_hcd_grlib_probe,
- .remove = ehci_hcd_grlib_remove,
+ .remove_new = ehci_hcd_grlib_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "grlib-ehci",
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index fa46d217dd10..9320cf0e5bc7 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -235,7 +235,7 @@ err_put_hcd:
return retval;
}
-static int mv_ehci_remove(struct platform_device *pdev)
+static void mv_ehci_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct ehci_hcd_mv *ehci_mv = hcd_to_ehci_hcd_mv(hcd);
@@ -254,8 +254,6 @@ static int mv_ehci_remove(struct platform_device *pdev)
}
usb_put_hcd(hcd);
-
- return 0;
}
static const struct platform_device_id ehci_id_table[] = {
@@ -282,7 +280,7 @@ static const struct of_device_id ehci_mv_dt_ids[] = {
static struct platform_driver ehci_mv_driver = {
.probe = mv_ehci_probe,
- .remove = mv_ehci_remove,
+ .remove_new = mv_ehci_remove,
.shutdown = mv_ehci_shutdown,
.driver = {
.name = "mv-ehci",
diff --git a/drivers/usb/host/ehci-npcm7xx.c b/drivers/usb/host/ehci-npcm7xx.c
index 63af1a827fcb..ad79ce63afcf 100644
--- a/drivers/usb/host/ehci-npcm7xx.c
+++ b/drivers/usb/host/ehci-npcm7xx.c
@@ -106,15 +106,13 @@ fail:
return retval;
}
-static int npcm7xx_ehci_hcd_drv_remove(struct platform_device *pdev)
+static void npcm7xx_ehci_hcd_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
-
- return 0;
}
static const struct of_device_id npcm7xx_ehci_id_table[] = {
@@ -125,7 +123,7 @@ MODULE_DEVICE_TABLE(of, npcm7xx_ehci_id_table);
static struct platform_driver npcm7xx_ehci_hcd_driver = {
.probe = npcm7xx_ehci_hcd_drv_probe,
- .remove = npcm7xx_ehci_hcd_drv_remove,
+ .remove_new = npcm7xx_ehci_hcd_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "npcm7xx-ehci",
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 7dd984722a7f..cb6509a735ac 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -237,7 +237,7 @@ err_phy:
* the HCD's stop() method. It is always called from a thread
* context, normally "rmmod", "apmd", or something similar.
*/
-static int ehci_hcd_omap_remove(struct platform_device *pdev)
+static void ehci_hcd_omap_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -254,8 +254,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
usb_put_hcd(hcd);
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
-
- return 0;
}
static const struct of_device_id omap_ehci_dt_ids[] = {
@@ -267,7 +265,7 @@ MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids);
static struct platform_driver ehci_hcd_omap_driver = {
.probe = ehci_hcd_omap_probe,
- .remove = ehci_hcd_omap_remove,
+ .remove_new = ehci_hcd_omap_remove,
.shutdown = usb_hcd_platform_shutdown,
/*.suspend = ehci_hcd_omap_suspend, */
/*.resume = ehci_hcd_omap_resume, */
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index a3454a3ea4e0..2cfb27dc943a 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -321,7 +321,7 @@ err:
return err;
}
-static int ehci_orion_drv_remove(struct platform_device *pdev)
+static void ehci_orion_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct orion_ehci_hcd *priv = hcd_to_orion_priv(hcd);
@@ -332,8 +332,6 @@ static int ehci_orion_drv_remove(struct platform_device *pdev)
clk_disable_unprepare(priv->clk);
usb_put_hcd(hcd);
-
- return 0;
}
static const struct of_device_id ehci_orion_dt_ids[] = {
@@ -345,7 +343,7 @@ MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids);
static struct platform_driver ehci_orion_driver = {
.probe = ehci_orion_drv_probe,
- .remove = ehci_orion_drv_remove,
+ .remove_new = ehci_orion_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "orion-ehci",
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 4b148fe5e43b..889dc4426271 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -354,10 +354,11 @@ done:
* Also they depend on separate root hub suspend/resume.
*/
-static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+static int ehci_pci_resume(struct usb_hcd *hcd, pm_message_t msg)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ bool hibernated = (msg.event == PM_EVENT_RESTORE);
if (ehci_resume(hcd, hibernated) != 0)
(void) ehci_pci_reinit(ehci, pdev);
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index fe497c876d76..83bf56c9424f 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -400,7 +400,7 @@ err_put_clks:
return err;
}
-static int ehci_platform_remove(struct platform_device *dev)
+static void ehci_platform_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
@@ -424,8 +424,6 @@ static int ehci_platform_remove(struct platform_device *dev)
if (pdata == &ehci_platform_defaults)
dev->dev.platform_data = NULL;
-
- return 0;
}
static int __maybe_unused ehci_platform_suspend(struct device *dev)
@@ -511,7 +509,7 @@ static SIMPLE_DEV_PM_OPS(ehci_platform_pm_ops, ehci_platform_suspend,
static struct platform_driver ehci_platform_driver = {
.id_table = ehci_platform_table,
.probe = ehci_platform_probe,
- .remove = ehci_platform_remove,
+ .remove_new = ehci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ehci-platform",
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index b3aa464e9d2c..7fd83e806ae4 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -184,7 +184,7 @@ err_irq:
}
-static int ehci_hcd_ppc_of_remove(struct platform_device *op)
+static void ehci_hcd_ppc_of_remove(struct platform_device *op)
{
struct usb_hcd *hcd = platform_get_drvdata(op);
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
@@ -216,8 +216,6 @@ static int ehci_hcd_ppc_of_remove(struct platform_device *op)
}
}
usb_put_hcd(hcd);
-
- return 0;
}
@@ -232,7 +230,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
static struct platform_driver ehci_hcd_ppc_of_driver = {
.probe = ehci_hcd_ppc_of_probe,
- .remove = ehci_hcd_ppc_of_remove,
+ .remove_new = ehci_hcd_ppc_of_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ppc-of-ehci",
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
index c25c51d26f26..0520e762801d 100644
--- a/drivers/usb/host/ehci-sh.c
+++ b/drivers/usb/host/ehci-sh.c
@@ -147,7 +147,7 @@ fail_create_hcd:
return ret;
}
-static int ehci_hcd_sh_remove(struct platform_device *pdev)
+static void ehci_hcd_sh_remove(struct platform_device *pdev)
{
struct ehci_sh_priv *priv = platform_get_drvdata(pdev);
struct usb_hcd *hcd = priv->hcd;
@@ -157,8 +157,6 @@ static int ehci_hcd_sh_remove(struct platform_device *pdev)
clk_disable(priv->fclk);
clk_disable(priv->iclk);
-
- return 0;
}
static void ehci_hcd_sh_shutdown(struct platform_device *pdev)
@@ -172,7 +170,7 @@ static void ehci_hcd_sh_shutdown(struct platform_device *pdev)
static struct platform_driver ehci_hcd_sh_driver = {
.probe = ehci_hcd_sh_probe,
- .remove = ehci_hcd_sh_remove,
+ .remove_new = ehci_hcd_sh_remove,
.shutdown = ehci_hcd_sh_shutdown,
.driver = {
.name = "sh_ehci",
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index c4ddd1022f60..1407703649be 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -124,7 +124,7 @@ fail:
return retval ;
}
-static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
+static void spear_ehci_hcd_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct spear_ehci *sehci = to_spear_ehci(hcd);
@@ -134,8 +134,6 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
if (sehci->clk)
clk_disable_unprepare(sehci->clk);
usb_put_hcd(hcd);
-
- return 0;
}
static const struct of_device_id spear_ehci_id_table[] = {
@@ -146,7 +144,7 @@ MODULE_DEVICE_TABLE(of, spear_ehci_id_table);
static struct platform_driver spear_ehci_hcd_driver = {
.probe = spear_ehci_hcd_drv_probe,
- .remove = spear_ehci_hcd_drv_remove,
+ .remove_new = spear_ehci_hcd_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "spear-ehci",
diff --git a/drivers/usb/host/ehci-st.c b/drivers/usb/host/ehci-st.c
index f731dc98c533..ee0976b815b4 100644
--- a/drivers/usb/host/ehci-st.c
+++ b/drivers/usb/host/ehci-st.c
@@ -252,7 +252,7 @@ err_put_hcd:
return err;
}
-static int st_ehci_platform_remove(struct platform_device *dev)
+static void st_ehci_platform_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
@@ -271,8 +271,6 @@ static int st_ehci_platform_remove(struct platform_device *dev)
if (pdata == &ehci_platform_defaults)
dev->dev.platform_data = NULL;
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -328,7 +326,7 @@ MODULE_DEVICE_TABLE(of, st_ehci_ids);
static struct platform_driver ehci_platform_driver = {
.probe = st_ehci_platform_probe,
- .remove = st_ehci_platform_remove,
+ .remove_new = st_ehci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "st-ehci",
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index 3d7893747835..a2112c28f631 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -201,7 +201,7 @@ err_irq:
*
* Return: Always return 0
*/
-static int ehci_hcd_xilinx_of_remove(struct platform_device *op)
+static void ehci_hcd_xilinx_of_remove(struct platform_device *op)
{
struct usb_hcd *hcd = platform_get_drvdata(op);
@@ -210,8 +210,6 @@ static int ehci_hcd_xilinx_of_remove(struct platform_device *op)
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
-
- return 0;
}
static const struct of_device_id ehci_hcd_xilinx_of_match[] = {
@@ -222,7 +220,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_xilinx_of_match);
static struct platform_driver ehci_hcd_xilinx_of_driver = {
.probe = ehci_hcd_xilinx_of_probe,
- .remove = ehci_hcd_xilinx_of_remove,
+ .remove_new = ehci_hcd_xilinx_of_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "xilinx-of-ehci",
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
index 92794ffc25c8..66a045e01dad 100644
--- a/drivers/usb/host/fhci-hcd.c
+++ b/drivers/usb/host/fhci-hcd.c
@@ -757,7 +757,7 @@ err_regs:
return ret;
}
-static int fhci_remove(struct device *dev)
+static void fhci_remove(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct fhci_hcd *fhci = hcd_to_fhci(hcd);
@@ -771,12 +771,11 @@ static int fhci_remove(struct device *dev)
qe_pin_free(fhci->pins[j]);
fhci_dfs_destroy(fhci);
usb_put_hcd(hcd);
- return 0;
}
-static int of_fhci_remove(struct platform_device *ofdev)
+static void of_fhci_remove(struct platform_device *ofdev)
{
- return fhci_remove(&ofdev->dev);
+ fhci_remove(&ofdev->dev);
}
static const struct of_device_id of_fhci_match[] = {
@@ -791,7 +790,7 @@ static struct platform_driver of_fhci_driver = {
.of_match_table = of_fhci_match,
},
.probe = of_fhci_probe,
- .remove = of_fhci_remove,
+ .remove_new = of_fhci_remove,
};
module_platform_driver(of_fhci_driver);
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 9db909d12354..a9877f2569f4 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -265,10 +265,9 @@ static int __unregister_subdev(struct device *dev, void *d)
return 0;
}
-static int fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
+static void fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
{
device_for_each_child(&ofdev->dev, NULL, __unregister_subdev);
- return 0;
}
#ifdef CONFIG_PPC_MPC512x
@@ -362,7 +361,7 @@ static struct platform_driver fsl_usb2_mph_dr_driver = {
.of_match_table = fsl_usb2_mph_dr_of_match,
},
.probe = fsl_usb2_mph_dr_of_probe,
- .remove = fsl_usb2_mph_dr_of_remove,
+ .remove_new = fsl_usb2_mph_dr_of_remove,
};
module_platform_driver(fsl_usb2_mph_dr_driver);
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 49ae01487af4..a82d8926e922 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1526,14 +1526,14 @@ static const struct hc_driver isp116x_hc_driver = {
/*----------------------------------------------------------------*/
-static int isp116x_remove(struct platform_device *pdev)
+static void isp116x_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct isp116x *isp116x;
struct resource *res;
if (!hcd)
- return 0;
+ return;
isp116x = hcd_to_isp116x(hcd);
remove_debug_file(isp116x);
usb_remove_hcd(hcd);
@@ -1548,7 +1548,6 @@ static int isp116x_remove(struct platform_device *pdev)
release_mem_region(res->start, 2);
usb_put_hcd(hcd);
- return 0;
}
static int isp116x_probe(struct platform_device *pdev)
@@ -1685,7 +1684,7 @@ MODULE_ALIAS("platform:isp116x-hcd");
static struct platform_driver isp116x_driver = {
.probe = isp116x_probe,
- .remove = isp116x_remove,
+ .remove_new = isp116x_remove,
.suspend = isp116x_suspend,
.resume = isp116x_resume,
.driver = {
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index b0da143ef4be..606f0a64f3b7 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2606,7 +2606,7 @@ static const struct hc_driver isp1362_hc_driver = {
/*-------------------------------------------------------------------------*/
-static int isp1362_remove(struct platform_device *pdev)
+static void isp1362_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd);
@@ -2617,8 +2617,6 @@ static int isp1362_remove(struct platform_device *pdev)
DBG(0, "%s: put_hcd\n", __func__);
usb_put_hcd(hcd);
DBG(0, "%s: Done\n", __func__);
-
- return 0;
}
static int isp1362_probe(struct platform_device *pdev)
@@ -2760,7 +2758,7 @@ static int isp1362_resume(struct platform_device *pdev)
static struct platform_driver isp1362_driver = {
.probe = isp1362_probe,
- .remove = isp1362_remove,
+ .remove_new = isp1362_remove,
.suspend = isp1362_suspend,
.resume = isp1362_resume,
diff --git a/drivers/usb/host/octeon-hcd.c b/drivers/usb/host/octeon-hcd.c
index a1cd81d4a114..19d5777f5db2 100644
--- a/drivers/usb/host/octeon-hcd.c
+++ b/drivers/usb/host/octeon-hcd.c
@@ -3680,7 +3680,7 @@ static int octeon_usb_probe(struct platform_device *pdev)
return 0;
}
-static int octeon_usb_remove(struct platform_device *pdev)
+static void octeon_usb_remove(struct platform_device *pdev)
{
int status;
struct device *dev = &pdev->dev;
@@ -3696,8 +3696,6 @@ static int octeon_usb_remove(struct platform_device *pdev)
dev_dbg(dev, "USB shutdown failed with %d\n", status);
usb_put_hcd(hcd);
-
- return 0;
}
static const struct of_device_id octeon_usb_match[] = {
@@ -3714,7 +3712,7 @@ static struct platform_driver octeon_usb_driver = {
.of_match_table = octeon_usb_match,
},
.probe = octeon_usb_probe,
- .remove = octeon_usb_remove,
+ .remove_new = octeon_usb_remove,
};
static int __init octeon_usb_driver_init(void)
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 533537ef3c21..b9ce8d80f20b 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -599,7 +599,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
}
-static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
+static void ohci_hcd_at91_drv_remove(struct platform_device *pdev)
{
struct at91_usbh_data *pdata = dev_get_platdata(&pdev->dev);
int i;
@@ -611,7 +611,6 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 0);
usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev);
- return 0;
}
static int __maybe_unused
@@ -683,7 +682,7 @@ static SIMPLE_DEV_PM_OPS(ohci_hcd_at91_pm_ops, ohci_hcd_at91_drv_suspend,
static struct platform_driver ohci_hcd_at91_driver = {
.probe = ohci_hcd_at91_drv_probe,
- .remove = ohci_hcd_at91_drv_remove,
+ .remove_new = ohci_hcd_at91_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "at91_ohci",
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index d4818e8d652b..e4191a868944 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -469,14 +469,12 @@ err:
return error;
}
-static int ohci_da8xx_remove(struct platform_device *pdev)
+static void ohci_da8xx_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -533,7 +531,7 @@ static const struct ohci_driver_overrides da8xx_overrides __initconst = {
*/
static struct platform_driver ohci_hcd_da8xx_driver = {
.probe = ohci_da8xx_probe,
- .remove = ohci_da8xx_remove,
+ .remove_new = ohci_da8xx_remove,
.shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_da8xx_suspend,
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 8af17c1ee5cc..ab31c459b32d 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -198,7 +198,7 @@ fail_clk:
return err;
}
-static int exynos_ohci_remove(struct platform_device *pdev)
+static void exynos_ohci_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
@@ -212,8 +212,6 @@ static int exynos_ohci_remove(struct platform_device *pdev)
clk_disable_unprepare(exynos_ohci->clk);
usb_put_hcd(hcd);
-
- return 0;
}
static void exynos_ohci_shutdown(struct platform_device *pdev)
@@ -285,7 +283,7 @@ MODULE_DEVICE_TABLE(of, exynos_ohci_match);
static struct platform_driver exynos_ohci_driver = {
.probe = exynos_ohci_probe,
- .remove = exynos_ohci_remove,
+ .remove_new = exynos_ohci_remove,
.shutdown = exynos_ohci_shutdown,
.driver = {
.name = "exynos-ohci",
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index 5b32e683e367..c04b2af5c766 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -237,7 +237,7 @@ fail_disable:
return ret;
}
-static int ohci_hcd_nxp_remove(struct platform_device *pdev)
+static void ohci_hcd_nxp_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -246,8 +246,6 @@ static int ohci_hcd_nxp_remove(struct platform_device *pdev)
usb_put_hcd(hcd);
clk_disable_unprepare(usb_host_clk);
isp1301_i2c_client = NULL;
-
- return 0;
}
/* work with hotplug and coldplug */
@@ -267,7 +265,7 @@ static struct platform_driver ohci_hcd_nxp_driver = {
.of_match_table = of_match_ptr(ohci_hcd_nxp_match),
},
.probe = ohci_hcd_nxp_probe,
- .remove = ohci_hcd_nxp_remove,
+ .remove_new = ohci_hcd_nxp_remove,
};
static int __init ohci_nxp_init(void)
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index c82121602511..21a6f6c55e07 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -321,7 +321,7 @@ err_put_hcd:
* the HCD's stop() method. It is always called from a thread
* context, normally "rmmod", "apmd", or something similar.
*/
-static int ohci_hcd_omap_remove(struct platform_device *pdev)
+static void ohci_hcd_omap_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct ohci_omap_priv *priv = hcd_to_ohci_omap_priv(hcd);
@@ -340,7 +340,6 @@ static int ohci_hcd_omap_remove(struct platform_device *pdev)
clk_unprepare(priv->usb_host_ck);
clk_put(priv->usb_host_ck);
usb_put_hcd(hcd);
- return 0;
}
/*-------------------------------------------------------------------------*/
@@ -391,7 +390,7 @@ static int ohci_omap_resume(struct platform_device *dev)
*/
static struct platform_driver ohci_hcd_omap_driver = {
.probe = ohci_hcd_omap_probe,
- .remove = ohci_hcd_omap_remove,
+ .remove_new = ohci_hcd_omap_remove,
.shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_omap_suspend,
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index d7b4f40f9ff4..900ea0d368e0 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -301,6 +301,12 @@ static struct pci_driver ohci_pci_driver = {
#endif
};
+#ifdef CONFIG_PM
+static int ohci_pci_resume(struct usb_hcd *hcd, pm_message_t msg)
+{
+ return ohci_resume(hcd, msg.event == PM_EVENT_RESTORE);
+}
+#endif
static int __init ohci_pci_init(void)
{
if (usb_disabled())
@@ -311,7 +317,7 @@ static int __init ohci_pci_init(void)
#ifdef CONFIG_PM
/* Entries for the PCI suspend/resume callbacks are special */
ohci_pci_hc_driver.pci_suspend = ohci_suspend;
- ohci_pci_hc_driver.pci_resume = ohci_resume;
+ ohci_pci_hc_driver.pci_resume = ohci_pci_resume;
#endif
return pci_register_driver(&ohci_pci_driver);
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index a84305091c43..45a2c981319e 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -33,7 +33,7 @@
#include "ohci.h"
#define DRIVER_DESC "OHCI generic platform driver"
-#define OHCI_MAX_CLKS 3
+#define OHCI_MAX_CLKS 4
#define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv)
struct ohci_platform_priv {
@@ -239,7 +239,7 @@ err_put_clks:
return err;
}
-static int ohci_platform_remove(struct platform_device *dev)
+static void ohci_platform_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
@@ -264,8 +264,6 @@ static int ohci_platform_remove(struct platform_device *dev)
if (pdata == &ohci_platform_defaults)
dev->dev.platform_data = NULL;
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -347,7 +345,7 @@ static const struct dev_pm_ops ohci_platform_pm_ops = {
static struct platform_driver ohci_platform_driver = {
.id_table = ohci_platform_table,
.probe = ohci_platform_probe,
- .remove = ohci_platform_remove,
+ .remove_new = ohci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ohci-platform",
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index f2f6c832ec98..35a7ad7e2569 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -176,7 +176,7 @@ err_rmr:
return rv;
}
-static int ohci_hcd_ppc_of_remove(struct platform_device *op)
+static void ohci_hcd_ppc_of_remove(struct platform_device *op)
{
struct usb_hcd *hcd = platform_get_drvdata(op);
@@ -187,8 +187,6 @@ static int ohci_hcd_ppc_of_remove(struct platform_device *op)
irq_dispose_mapping(hcd->irq);
usb_put_hcd(hcd);
-
- return 0;
}
static const struct of_device_id ohci_hcd_ppc_of_match[] = {
@@ -224,7 +222,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match);
static struct platform_driver ohci_hcd_ppc_of_driver = {
.probe = ohci_hcd_ppc_of_probe,
- .remove = ohci_hcd_ppc_of_remove,
+ .remove_new = ohci_hcd_ppc_of_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ppc-of-ohci",
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 0bc7e96bcc93..7410442f720f 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -29,6 +29,7 @@
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/pxa2xx_udc.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/signal.h>
@@ -263,12 +264,6 @@ static inline void pxa27x_reset_hc(struct pxa27x_ohci *pxa_ohci)
__raw_writel(uhchr & ~UHCHR_FHR, pxa_ohci->mmio_base + UHCHR);
}
-#ifdef CONFIG_PXA27x
-extern void pxa27x_clear_otgph(void);
-#else
-#define pxa27x_clear_otgph() do {} while (0)
-#endif
-
static int pxa27x_start_hc(struct pxa27x_ohci *pxa_ohci, struct device *dev)
{
int retval;
@@ -506,7 +501,7 @@ static int ohci_hcd_pxa27x_probe(struct platform_device *pdev)
* the HCD's stop() method. It is always called from a thread
* context, normally "rmmod", "apmd", or something similar.
*/
-static int ohci_hcd_pxa27x_remove(struct platform_device *pdev)
+static void ohci_hcd_pxa27x_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd);
@@ -519,7 +514,6 @@ static int ohci_hcd_pxa27x_remove(struct platform_device *pdev)
pxa27x_ohci_set_vbus_power(pxa_ohci, i, false);
usb_put_hcd(hcd);
- return 0;
}
/*-------------------------------------------------------------------------*/
@@ -577,7 +571,7 @@ static const struct dev_pm_ops ohci_hcd_pxa27x_pm_ops = {
static struct platform_driver ohci_hcd_pxa27x_driver = {
.probe = ohci_hcd_pxa27x_probe,
- .remove = ohci_hcd_pxa27x_remove,
+ .remove_new = ohci_hcd_pxa27x_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "pxa27x-ohci",
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 85a0a9ae0095..c5c9b4cbcb9a 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -329,7 +329,7 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc)
* the HCD's stop() method. It is always called from a thread
* context, normally "rmmod", "apmd", or something similar.
*/
-static int
+static void
ohci_hcd_s3c2410_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
@@ -337,7 +337,6 @@ ohci_hcd_s3c2410_remove(struct platform_device *dev)
usb_remove_hcd(hcd);
s3c2410_stop_hc(dev);
usb_put_hcd(hcd);
- return 0;
}
/*
@@ -458,7 +457,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_s3c2410_dt_ids);
static struct platform_driver ohci_hcd_s3c2410_driver = {
.probe = ohci_hcd_s3c2410_probe,
- .remove = ohci_hcd_s3c2410_remove,
+ .remove_new = ohci_hcd_s3c2410_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "s3c2410-ohci",
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index f5de586454e3..0468eeb4fcfd 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -185,7 +185,7 @@ err0:
return retval;
}
-static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
+static void ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct resource *mem;
@@ -202,8 +202,6 @@ static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
sm501_modify_reg(pdev->dev.parent, SM501_IRQ_MASK, 0, 1 << 6);
sm501_unit_power(pdev->dev.parent, SM501_GATE_USB_HOST, 0);
-
- return 0;
}
/*-------------------------------------------------------------------------*/
@@ -255,7 +253,7 @@ static int ohci_sm501_resume(struct platform_device *pdev)
*/
static struct platform_driver ohci_hcd_sm501_driver = {
.probe = ohci_hcd_sm501_drv_probe,
- .remove = ohci_hcd_sm501_drv_remove,
+ .remove_new = ohci_hcd_sm501_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.suspend = ohci_sm501_suspend,
.resume = ohci_sm501_resume,
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index 196951a27f3f..f4b2656407dd 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -98,7 +98,7 @@ fail:
return retval;
}
-static int spear_ohci_hcd_drv_remove(struct platform_device *pdev)
+static void spear_ohci_hcd_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct spear_ohci *sohci_p = to_spear_ohci(hcd);
@@ -108,7 +108,6 @@ static int spear_ohci_hcd_drv_remove(struct platform_device *pdev)
clk_disable_unprepare(sohci_p->clk);
usb_put_hcd(hcd);
- return 0;
}
#if defined(CONFIG_PM)
@@ -159,7 +158,7 @@ MODULE_DEVICE_TABLE(of, spear_ohci_id_table);
/* Driver definition to register with the platform bus */
static struct platform_driver spear_ohci_hcd_driver = {
.probe = spear_ohci_hcd_drv_probe,
- .remove = spear_ohci_hcd_drv_remove,
+ .remove_new = spear_ohci_hcd_drv_remove,
#ifdef CONFIG_PM
.suspend = spear_ohci_hcd_drv_suspend,
.resume = spear_ohci_hcd_drv_resume,
diff --git a/drivers/usb/host/ohci-st.c b/drivers/usb/host/ohci-st.c
index 82eef3c62e11..884e447a8098 100644
--- a/drivers/usb/host/ohci-st.c
+++ b/drivers/usb/host/ohci-st.c
@@ -233,7 +233,7 @@ err_put_hcd:
return err;
}
-static int st_ohci_platform_remove(struct platform_device *dev)
+static void st_ohci_platform_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
@@ -253,8 +253,6 @@ static int st_ohci_platform_remove(struct platform_device *dev)
if (pdata == &ohci_platform_defaults)
dev->dev.platform_data = NULL;
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -306,7 +304,7 @@ MODULE_DEVICE_TABLE(of, st_ohci_platform_ids);
static struct platform_driver ohci_platform_driver = {
.probe = st_ohci_platform_probe,
- .remove = st_ohci_platform_remove,
+ .remove_new = st_ohci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "st-ohci",
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index f998d3f1a78a..50c1ccabb0f5 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -4278,14 +4278,12 @@ static void oxu_remove(struct platform_device *pdev, struct usb_hcd *hcd)
usb_put_hcd(hcd);
}
-static int oxu_drv_remove(struct platform_device *pdev)
+static void oxu_drv_remove(struct platform_device *pdev)
{
struct oxu_info *info = platform_get_drvdata(pdev);
oxu_remove(pdev, info->hcd[0]);
oxu_remove(pdev, info->hcd[1]);
-
- return 0;
}
static void oxu_drv_shutdown(struct platform_device *pdev)
@@ -4317,7 +4315,7 @@ static int oxu_drv_resume(struct device *dev)
static struct platform_driver oxu_driver = {
.probe = oxu_drv_probe,
- .remove = oxu_drv_remove,
+ .remove_new = oxu_drv_remove,
.shutdown = oxu_drv_shutdown,
.suspend = oxu_drv_suspend,
.resume = oxu_drv_resume,
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index abb88dd40d4e..9f4bf8c5f8a5 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -2379,7 +2379,7 @@ static const struct dev_pm_ops r8a66597_dev_pm_ops = {
#define R8A66597_DEV_PM_OPS NULL
#endif
-static int r8a66597_remove(struct platform_device *pdev)
+static void r8a66597_remove(struct platform_device *pdev)
{
struct r8a66597 *r8a66597 = platform_get_drvdata(pdev);
struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597);
@@ -2390,7 +2390,6 @@ static int r8a66597_remove(struct platform_device *pdev)
if (r8a66597->pdata->on_chip)
clk_put(r8a66597->clk);
usb_put_hcd(hcd);
- return 0;
}
static int r8a66597_probe(struct platform_device *pdev)
@@ -2511,7 +2510,7 @@ clean_up:
static struct platform_driver r8a66597_driver = {
.probe = r8a66597_probe,
- .remove = r8a66597_remove,
+ .remove_new = r8a66597_remove,
.driver = {
.name = hcd_name,
.pm = R8A66597_DEV_PM_OPS,
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index b8b90eec9107..0956495bba57 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1579,7 +1579,7 @@ static const struct hc_driver sl811h_hc_driver = {
/*-------------------------------------------------------------------------*/
-static int
+static void
sl811h_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
@@ -1599,7 +1599,6 @@ sl811h_remove(struct platform_device *dev)
iounmap(sl811->addr_reg);
usb_put_hcd(hcd);
- return 0;
}
static int
@@ -1783,7 +1782,7 @@ sl811h_resume(struct platform_device *dev)
/* this driver is exported so sl811_cs can depend on it */
struct platform_driver sl811h_driver = {
.probe = sl811h_probe,
- .remove = sl811h_remove,
+ .remove_new = sl811h_remove,
.suspend = sl811h_suspend,
.resume = sl811h_resume,
diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c
index 907d5f01edfd..ac3fc5970315 100644
--- a/drivers/usb/host/uhci-grlib.c
+++ b/drivers/usb/host/uhci-grlib.c
@@ -147,7 +147,7 @@ err_usb:
return rv;
}
-static int uhci_hcd_grlib_remove(struct platform_device *op)
+static void uhci_hcd_grlib_remove(struct platform_device *op)
{
struct usb_hcd *hcd = platform_get_drvdata(op);
@@ -157,8 +157,6 @@ static int uhci_hcd_grlib_remove(struct platform_device *op)
irq_dispose_mapping(hcd->irq);
usb_put_hcd(hcd);
-
- return 0;
}
/* Make sure the controller is quiescent and that we're not using it
@@ -185,7 +183,7 @@ MODULE_DEVICE_TABLE(of, uhci_hcd_grlib_of_match);
static struct platform_driver uhci_grlib_driver = {
.probe = uhci_hcd_grlib_probe,
- .remove = uhci_hcd_grlib_remove,
+ .remove_new = uhci_hcd_grlib_remove,
.shutdown = uhci_hcd_grlib_shutdown,
.driver = {
.name = "grlib-uhci",
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 7cdc2fa7c28f..fd2408b553cf 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -841,7 +841,7 @@ static int uhci_count_ports(struct usb_hcd *hcd)
static const char hcd_name[] = "uhci_hcd";
-#ifdef CONFIG_USB_PCI
+#if defined(CONFIG_USB_PCI) && defined(CONFIG_HAS_IOPORT)
#include "uhci-pci.c"
#define PCI_DRIVER uhci_pci_driver
#endif
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 0688c3e5bfe2..13ee2a6144b2 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -505,6 +505,14 @@ static inline bool uhci_is_aspeed(const struct uhci_hcd *uhci)
* we use memory mapped registers.
*/
+#ifdef CONFIG_HAS_IOPORT
+#define UHCI_IN(x) x
+#define UHCI_OUT(x) x
+#else
+#define UHCI_IN(x) 0
+#define UHCI_OUT(x) do { } while (0)
+#endif
+
#ifndef CONFIG_USB_UHCI_SUPPORT_NON_PCI_HC
/* Support PCI only */
static inline u32 uhci_readl(const struct uhci_hcd *uhci, int reg)
@@ -539,7 +547,7 @@ static inline void uhci_writeb(const struct uhci_hcd *uhci, u8 val, int reg)
#else
/* Support non-PCI host controllers */
-#ifdef CONFIG_USB_PCI
+#if defined(CONFIG_USB_PCI) && defined(HAS_IOPORT)
/* Support PCI and non-PCI host controllers */
#define uhci_has_pci_registers(u) ((u)->io_addr != 0)
#else
@@ -587,7 +595,7 @@ static inline int uhci_aspeed_reg(unsigned int reg)
static inline u32 uhci_readl(const struct uhci_hcd *uhci, int reg)
{
if (uhci_has_pci_registers(uhci))
- return inl(uhci->io_addr + reg);
+ return UHCI_IN(inl(uhci->io_addr + reg));
else if (uhci_is_aspeed(uhci))
return readl(uhci->regs + uhci_aspeed_reg(reg));
#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
@@ -601,7 +609,7 @@ static inline u32 uhci_readl(const struct uhci_hcd *uhci, int reg)
static inline void uhci_writel(const struct uhci_hcd *uhci, u32 val, int reg)
{
if (uhci_has_pci_registers(uhci))
- outl(val, uhci->io_addr + reg);
+ UHCI_OUT(outl(val, uhci->io_addr + reg));
else if (uhci_is_aspeed(uhci))
writel(val, uhci->regs + uhci_aspeed_reg(reg));
#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
@@ -615,7 +623,7 @@ static inline void uhci_writel(const struct uhci_hcd *uhci, u32 val, int reg)
static inline u16 uhci_readw(const struct uhci_hcd *uhci, int reg)
{
if (uhci_has_pci_registers(uhci))
- return inw(uhci->io_addr + reg);
+ return UHCI_IN(inw(uhci->io_addr + reg));
else if (uhci_is_aspeed(uhci))
return readl(uhci->regs + uhci_aspeed_reg(reg));
#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
@@ -629,7 +637,7 @@ static inline u16 uhci_readw(const struct uhci_hcd *uhci, int reg)
static inline void uhci_writew(const struct uhci_hcd *uhci, u16 val, int reg)
{
if (uhci_has_pci_registers(uhci))
- outw(val, uhci->io_addr + reg);
+ UHCI_OUT(outw(val, uhci->io_addr + reg));
else if (uhci_is_aspeed(uhci))
writel(val, uhci->regs + uhci_aspeed_reg(reg));
#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
@@ -643,7 +651,7 @@ static inline void uhci_writew(const struct uhci_hcd *uhci, u16 val, int reg)
static inline u8 uhci_readb(const struct uhci_hcd *uhci, int reg)
{
if (uhci_has_pci_registers(uhci))
- return inb(uhci->io_addr + reg);
+ return UHCI_IN(inb(uhci->io_addr + reg));
else if (uhci_is_aspeed(uhci))
return readl(uhci->regs + uhci_aspeed_reg(reg));
#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
@@ -657,7 +665,7 @@ static inline u8 uhci_readb(const struct uhci_hcd *uhci, int reg)
static inline void uhci_writeb(const struct uhci_hcd *uhci, u8 val, int reg)
{
if (uhci_has_pci_registers(uhci))
- outb(val, uhci->io_addr + reg);
+ UHCI_OUT(outb(val, uhci->io_addr + reg));
else if (uhci_is_aspeed(uhci))
writel(val, uhci->regs + uhci_aspeed_reg(reg));
#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
@@ -668,6 +676,8 @@ static inline void uhci_writeb(const struct uhci_hcd *uhci, u8 val, int reg)
writeb(val, uhci->regs + reg);
}
#endif /* CONFIG_USB_UHCI_SUPPORT_NON_PCI_HC */
+#undef UHCI_IN
+#undef UHCI_OUT
/*
* The GRLIB GRUSBHC controller can use big endian format for its descriptors.
diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c
index 7bd2fddde770..5edf6a08cf82 100644
--- a/drivers/usb/host/uhci-pci.c
+++ b/drivers/usb/host/uhci-pci.c
@@ -169,7 +169,7 @@ static void uhci_shutdown(struct pci_dev *pdev)
#ifdef CONFIG_PM
-static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated);
+static int uhci_pci_resume(struct usb_hcd *hcd, pm_message_t state);
static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
@@ -204,14 +204,15 @@ done_okay:
/* Check for race with a wakeup request */
if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) {
- uhci_pci_resume(hcd, false);
+ uhci_pci_resume(hcd, PMSG_SUSPEND);
rc = -EBUSY;
}
return rc;
}
-static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+static int uhci_pci_resume(struct usb_hcd *hcd, pm_message_t msg)
{
+ bool hibernated = (msg.event == PM_EVENT_RESTORE);
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
dev_dbg(uhci_dev(uhci), "%s\n", __func__);
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index b2049b47a08d..71ca532fc086 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -152,7 +152,7 @@ err_rmr:
return ret;
}
-static int uhci_hcd_platform_remove(struct platform_device *pdev)
+static void uhci_hcd_platform_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -160,8 +160,6 @@ static int uhci_hcd_platform_remove(struct platform_device *pdev)
clk_disable_unprepare(uhci->clk);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
-
- return 0;
}
/* Make sure the controller is quiescent and that we're not using it
@@ -187,7 +185,7 @@ MODULE_DEVICE_TABLE(of, platform_uhci_ids);
static struct platform_driver uhci_platform_driver = {
.probe = uhci_hcd_platform_probe,
- .remove = uhci_hcd_platform_remove,
+ .remove_new = uhci_hcd_platform_remove,
.shutdown = uhci_hcd_platform_shutdown,
.driver = {
.name = "platform-uhci",
diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c
index 08369857686e..f9a4a4b0eb57 100644
--- a/drivers/usb/host/xhci-histb.c
+++ b/drivers/usb/host/xhci-histb.c
@@ -164,16 +164,6 @@ static void xhci_histb_host_disable(struct xhci_hcd_histb *histb)
clk_disable_unprepare(histb->bus_clk);
}
-static void xhci_histb_quirks(struct device *dev, struct xhci_hcd *xhci)
-{
- /*
- * As of now platform drivers don't provide MSI support so we ensure
- * here that the generic code does not try to make a pci_dev from our
- * dev struct in order to setup MSI
- */
- xhci->quirks |= XHCI_PLAT;
-}
-
/* called during probe() after chip reset completes */
static int xhci_histb_setup(struct usb_hcd *hcd)
{
@@ -186,7 +176,7 @@ static int xhci_histb_setup(struct usb_hcd *hcd)
return ret;
}
- return xhci_gen_setup(hcd, xhci_histb_quirks);
+ return xhci_gen_setup(hcd, NULL);
}
static const struct xhci_driver_overrides xhci_histb_overrides __initconst = {
@@ -319,7 +309,7 @@ disable_pm:
return ret;
}
-static int xhci_histb_remove(struct platform_device *dev)
+static void xhci_histb_remove(struct platform_device *dev)
{
struct xhci_hcd_histb *histb = platform_get_drvdata(dev);
struct usb_hcd *hcd = histb->hcd;
@@ -339,8 +329,6 @@ static int xhci_histb_remove(struct platform_device *dev)
usb_put_hcd(hcd);
pm_runtime_put_sync(&dev->dev);
pm_runtime_disable(&dev->dev);
-
- return 0;
}
static int __maybe_unused xhci_histb_suspend(struct device *dev)
@@ -367,7 +355,7 @@ static int __maybe_unused xhci_histb_resume(struct device *dev)
if (!device_may_wakeup(dev))
xhci_histb_host_enable(histb);
- return xhci_resume(xhci, 0);
+ return xhci_resume(xhci, PMSG_RESUME);
}
static const struct dev_pm_ops xhci_histb_pm_ops = {
@@ -385,7 +373,7 @@ MODULE_DEVICE_TABLE(of, histb_xhci_of_match);
static struct platform_driver histb_xhci_driver = {
.probe = xhci_histb_probe,
- .remove = xhci_histb_remove,
+ .remove_new = xhci_histb_remove,
.driver = {
.name = "xhci-histb",
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 7e106bd804ca..19a402123de0 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -143,7 +143,6 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring,
xhci_link_segments(ring->enq_seg, first, ring->type, chain_links);
xhci_link_segments(last, next, ring->type, chain_links);
ring->num_segs += num_segs;
- ring->num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs;
if (ring->type != TYPE_EVENT && ring->enq_seg == ring->last_seg) {
ring->last_seg->trbs[TRBS_PER_SEGMENT-1].link.control
@@ -422,22 +421,14 @@ void xhci_free_endpoint_ring(struct xhci_hcd *xhci,
* Allocate a new ring which has same segment numbers and link the two rings.
*/
int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
- unsigned int num_trbs, gfp_t flags)
+ unsigned int num_new_segs, gfp_t flags)
{
struct xhci_segment *first;
struct xhci_segment *last;
- unsigned int num_segs;
- unsigned int num_segs_needed;
int ret;
- num_segs_needed = (num_trbs + (TRBS_PER_SEGMENT - 1) - 1) /
- (TRBS_PER_SEGMENT - 1);
-
- /* Allocate number of segments we needed, or double the ring size */
- num_segs = max(ring->num_segs, num_segs_needed);
-
ret = xhci_alloc_segments_for_ring(xhci, &first, &last,
- num_segs, ring->cycle_state, ring->type,
+ num_new_segs, ring->cycle_state, ring->type,
ring->bounce_buf_len, flags);
if (ret)
return -ENOMEM;
@@ -457,7 +448,7 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
return ret;
}
- xhci_link_rings(xhci, ring, first, last, num_segs);
+ xhci_link_rings(xhci, ring, first, last, num_new_segs);
trace_xhci_ring_expansion(ring);
xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion,
"ring expansion succeed, now has %d segments",
@@ -1831,13 +1822,15 @@ xhci_free_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
* low or high 32 bits of ERSTBA immediately causes the controller to
* dereference the partially cleared 64 bit address, causing IOMMU error.
*/
- tmp = readl(&ir->ir_set->erst_size);
- tmp &= ERST_SIZE_MASK;
- writel(tmp, &ir->ir_set->erst_size);
-
- tmp64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
- tmp64 &= (u64) ERST_PTR_MASK;
- xhci_write_64(xhci, tmp64, &ir->ir_set->erst_dequeue);
+ if (ir->ir_set) {
+ tmp = readl(&ir->ir_set->erst_size);
+ tmp &= ERST_SIZE_MASK;
+ writel(tmp, &ir->ir_set->erst_size);
+
+ tmp64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
+ tmp64 &= (u64) ERST_PTR_MASK;
+ xhci_write_64(xhci, tmp64, &ir->ir_set->erst_dequeue);
+ }
/* free interrrupter event ring */
if (ir->event_ring)
@@ -1968,7 +1961,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
{
u32 temp, port_offset, port_count;
int i;
- u8 major_revision, minor_revision;
+ u8 major_revision, minor_revision, tmp_minor_revision;
struct xhci_hub *rhub;
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
struct xhci_port_cap *port_cap;
@@ -1988,6 +1981,15 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
*/
if (minor_revision > 0x00 && minor_revision < 0x10)
minor_revision <<= 4;
+ /*
+ * Some zhaoxin's xHCI controller that follow usb3.1 spec
+ * but only support Gen1.
+ */
+ if (xhci->quirks & XHCI_ZHAOXIN_HOST) {
+ tmp_minor_revision = minor_revision;
+ minor_revision = 0;
+ }
+
} else if (major_revision <= 0x02) {
rhub = &xhci->usb2_rhub;
} else {
@@ -1996,10 +1998,6 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
/* Ignoring port protocol we can't understand. FIXME */
return;
}
- rhub->maj_rev = XHCI_EXT_PORT_MAJOR(temp);
-
- if (rhub->min_rev < minor_revision)
- rhub->min_rev = minor_revision;
/* Port offset and count in the third dword, see section 7.2 */
temp = readl(addr + 2);
@@ -2017,8 +2015,6 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
if (xhci->num_port_caps > max_caps)
return;
- port_cap->maj_rev = major_revision;
- port_cap->min_rev = minor_revision;
port_cap->psi_count = XHCI_EXT_PORT_PSIC(temp);
if (port_cap->psi_count) {
@@ -2039,6 +2035,11 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
XHCI_EXT_PORT_PSIV(port_cap->psi[i - 1])))
port_cap->psi_uid_count++;
+ if (xhci->quirks & XHCI_ZHAOXIN_HOST &&
+ major_revision == 0x03 &&
+ XHCI_EXT_PORT_PSIV(port_cap->psi[i]) >= 5)
+ minor_revision = tmp_minor_revision;
+
xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n",
XHCI_EXT_PORT_PSIV(port_cap->psi[i]),
XHCI_EXT_PORT_PSIE(port_cap->psi[i]),
@@ -2048,6 +2049,15 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
XHCI_EXT_PORT_PSIM(port_cap->psi[i]));
}
}
+
+ rhub->maj_rev = major_revision;
+
+ if (rhub->min_rev < minor_revision)
+ rhub->min_rev = minor_revision;
+
+ port_cap->maj_rev = major_revision;
+ port_cap->min_rev = minor_revision;
+
/* cache usb2 port capabilities */
if (major_revision < 0x03 && xhci->num_ext_caps < max_caps)
xhci->ext_caps[xhci->num_ext_caps++] = temp;
@@ -2227,43 +2237,50 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
}
static struct xhci_interrupter *
-xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int intr_num, gfp_t flags)
+xhci_alloc_interrupter(struct xhci_hcd *xhci, gfp_t flags)
{
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
struct xhci_interrupter *ir;
- u64 erst_base;
- u32 erst_size;
int ret;
- if (intr_num > xhci->max_interrupters) {
- xhci_warn(xhci, "Can't allocate interrupter %d, max interrupters %d\n",
- intr_num, xhci->max_interrupters);
- return NULL;
- }
-
- if (xhci->interrupter) {
- xhci_warn(xhci, "Can't allocate already set up interrupter %d\n", intr_num);
- return NULL;
- }
-
ir = kzalloc_node(sizeof(*ir), flags, dev_to_node(dev));
if (!ir)
return NULL;
- ir->ir_set = &xhci->run_regs->ir_set[intr_num];
ir->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1, TYPE_EVENT,
0, flags);
if (!ir->event_ring) {
- xhci_warn(xhci, "Failed to allocate interrupter %d event ring\n", intr_num);
- goto fail_ir;
+ xhci_warn(xhci, "Failed to allocate interrupter event ring\n");
+ kfree(ir);
+ return NULL;
}
ret = xhci_alloc_erst(xhci, ir->event_ring, &ir->erst, flags);
if (ret) {
- xhci_warn(xhci, "Failed to allocate interrupter %d erst\n", intr_num);
- goto fail_ev;
+ xhci_warn(xhci, "Failed to allocate interrupter erst\n");
+ xhci_ring_free(xhci, ir->event_ring);
+ kfree(ir);
+ return NULL;
+ }
+ return ir;
+}
+
+static int
+xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir,
+ unsigned int intr_num)
+{
+ u64 erst_base;
+ u32 erst_size;
+
+ if (intr_num > xhci->max_interrupters) {
+ xhci_warn(xhci, "Can't add interrupter %d, max interrupters %d\n",
+ intr_num, xhci->max_interrupters);
+ return -EINVAL;
}
+
+ ir->ir_set = &xhci->run_regs->ir_set[intr_num];
+
/* set ERST count with the number of entries in the segment table */
erst_size = readl(&ir->ir_set->erst_size);
erst_size &= ERST_SIZE_MASK;
@@ -2278,14 +2295,7 @@ xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int intr_num, gfp_t flags
/* Set the event ring dequeue address of this interrupter */
xhci_set_hc_event_deq(xhci, ir);
- return ir;
-
-fail_ev:
- xhci_ring_free(xhci, ir->event_ring);
-fail_ir:
- kfree(ir);
-
- return NULL;
+ return 0;
}
int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
@@ -2352,8 +2362,12 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
* and our use of dma addresses in the trb_address_map radix tree needs
* TRB_SEGMENT_SIZE alignment, so we pick the greater alignment need.
*/
- xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
- TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size);
+ if (xhci->quirks & XHCI_ZHAOXIN_TRB_FETCH)
+ xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
+ TRB_SEGMENT_SIZE * 2, TRB_SEGMENT_SIZE * 2, xhci->page_size * 2);
+ else
+ xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
+ TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size);
/* See Table 46 and Note on Figure 55 */
xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,
@@ -2407,15 +2421,17 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
"// Doorbell array is located at offset 0x%x from cap regs base addr",
val);
xhci->dba = (void __iomem *) xhci->cap_regs + val;
- /* Set ir_set to interrupt register set 0 */
- /* allocate and set up primary interrupter with an event ring. */
+ /* Allocate and set up primary interrupter 0 with an event ring. */
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Allocating primary event ring");
- xhci->interrupter = xhci_alloc_interrupter(xhci, 0, flags);
+ xhci->interrupter = xhci_alloc_interrupter(xhci, flags);
if (!xhci->interrupter)
goto fail;
+ if (xhci_add_interrupter(xhci, xhci->interrupter, 0))
+ goto fail;
+
xhci->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX;
/*
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 90cf40d6d0c3..51d9d4d4f6a5 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -418,12 +418,6 @@ static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci)
struct usb_hcd *hcd = xhci_to_hcd(xhci);
struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
- /*
- * As of now platform drivers don't provide MSI support so we ensure
- * here that the generic code does not try to make a pci_dev from our
- * dev struct in order to setup MSI
- */
- xhci->quirks |= XHCI_PLAT;
xhci->quirks |= XHCI_MTK_HOST;
/*
* MTK host controller gives a spurious successful event after a
@@ -673,7 +667,7 @@ disable_pm:
return ret;
}
-static int xhci_mtk_remove(struct platform_device *pdev)
+static void xhci_mtk_remove(struct platform_device *pdev)
{
struct xhci_hcd_mtk *mtk = platform_get_drvdata(pdev);
struct usb_hcd *hcd = mtk->hcd;
@@ -703,8 +697,6 @@ static int xhci_mtk_remove(struct platform_device *pdev)
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
pm_runtime_set_suspended(dev);
-
- return 0;
}
static int __maybe_unused xhci_mtk_suspend(struct device *dev)
@@ -824,7 +816,7 @@ MODULE_DEVICE_TABLE(of, mtk_xhci_of_match);
static struct platform_driver mtk_xhci_driver = {
.probe = xhci_mtk_probe,
- .remove = xhci_mtk_remove,
+ .remove_new = xhci_mtk_remove,
.driver = {
.name = "xhci-mtk",
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 79b3691f373f..c6742bae41c0 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -108,9 +108,6 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci)
struct usb_hcd *hcd = xhci_to_hcd(xhci);
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
- if (xhci->quirks & XHCI_PLAT)
- return;
-
/* return if using legacy interrupt */
if (hcd->irq > 0)
return;
@@ -208,10 +205,6 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
struct pci_dev *pdev;
int ret;
- /* The xhci platform device has set up IRQs through usb_add_hcd. */
- if (xhci->quirks & XHCI_PLAT)
- return 0;
-
pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
/*
* Some Fresco Logic host controllers advertise MSI, but fail to
@@ -528,6 +521,19 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4))
xhci->quirks |= XHCI_NO_SOFT_RETRY;
+ if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) {
+ xhci->quirks |= XHCI_ZHAOXIN_HOST;
+ xhci->quirks |= XHCI_LPM_SUPPORT;
+
+ if (pdev->device == 0x9202) {
+ xhci->quirks |= XHCI_RESET_ON_RESUME;
+ xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH;
+ }
+
+ if (pdev->device == 0x9203)
+ xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH;
+ }
+
/* xHC spec requires PCI devices to support D3hot and D3cold */
if (xhci->hci_version >= 0x120)
xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
@@ -832,7 +838,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
return ret;
}
-static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+static int xhci_pci_resume(struct usb_hcd *hcd, pm_message_t msg)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
@@ -867,7 +873,7 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
xhci_pme_quirk(hcd);
- retval = xhci_resume(xhci, hibernated);
+ retval = xhci_resume(xhci, msg);
return retval;
}
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index b0c8e8efc43b..b26ea7cb4357 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -78,12 +78,7 @@ static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
{
struct xhci_plat_priv *priv = xhci_to_priv(xhci);
- /*
- * As of now platform drivers don't provide MSI support so we ensure
- * here that the generic code does not try to make a pci_dev from our
- * dev struct in order to setup MSI
- */
- xhci->quirks |= XHCI_PLAT | priv->quirks;
+ xhci->quirks |= priv->quirks;
}
/* called during probe() after chip reset completes */
@@ -294,10 +289,6 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
xhci->shared_hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev,
"usb-phy", 1);
if (IS_ERR(xhci->shared_hcd->usb_phy)) {
- if (PTR_ERR(xhci->shared_hcd->usb_phy) != -ENODEV)
- dev_err(sysdev, "%s get usb3phy fail (ret=%d)\n",
- __func__,
- (int)PTR_ERR(xhci->shared_hcd->usb_phy));
xhci->shared_hcd->usb_phy = NULL;
} else {
ret = usb_phy_init(xhci->shared_hcd->usb_phy);
@@ -399,7 +390,7 @@ static int xhci_generic_plat_probe(struct platform_device *pdev)
return xhci_plat_probe(pdev, sysdev, priv_match);
}
-int xhci_plat_remove(struct platform_device *dev)
+void xhci_plat_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -407,8 +398,8 @@ int xhci_plat_remove(struct platform_device *dev)
struct clk *reg_clk = xhci->reg_clk;
struct usb_hcd *shared_hcd = xhci->shared_hcd;
- pm_runtime_get_sync(&dev->dev);
xhci->xhc_state |= XHCI_STATE_REMOVING;
+ pm_runtime_get_sync(&dev->dev);
if (shared_hcd) {
usb_remove_hcd(shared_hcd);
@@ -430,8 +421,6 @@ int xhci_plat_remove(struct platform_device *dev)
pm_runtime_disable(&dev->dev);
pm_runtime_put_noidle(&dev->dev);
pm_runtime_set_suspended(&dev->dev);
-
- return 0;
}
EXPORT_SYMBOL_GPL(xhci_plat_remove);
@@ -478,7 +467,7 @@ static int __maybe_unused xhci_plat_resume(struct device *dev)
if (ret)
return ret;
- ret = xhci_resume(xhci, 0);
+ ret = xhci_resume(xhci, PMSG_RESUME);
if (ret)
return ret;
@@ -507,7 +496,7 @@ static int __maybe_unused xhci_plat_runtime_resume(struct device *dev)
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- return xhci_resume(xhci, 0);
+ return xhci_resume(xhci, PMSG_AUTO_RESUME);
}
const struct dev_pm_ops xhci_plat_pm_ops = {
@@ -530,7 +519,7 @@ MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);
static struct platform_driver usb_generic_xhci_driver = {
.probe = xhci_generic_plat_probe,
- .remove = xhci_plat_remove,
+ .remove_new = xhci_plat_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "xhci-hcd",
diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h
index 83b5b5aa9f8e..2d15386f2c50 100644
--- a/drivers/usb/host/xhci-plat.h
+++ b/drivers/usb/host/xhci-plat.h
@@ -25,7 +25,7 @@ struct xhci_plat_priv {
int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev,
const struct xhci_plat_priv *priv_match);
-int xhci_plat_remove(struct platform_device *dev);
+void xhci_plat_remove(struct platform_device *dev);
extern const struct dev_pm_ops xhci_plat_pm_ops;
#endif /* _XHCI_PLAT_H */
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index ad966b797b89..bf5261fed32c 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -276,10 +276,10 @@ static int xhci_renesas_probe(struct platform_device *pdev)
}
static struct platform_driver usb_xhci_renesas_driver = {
- .probe = xhci_renesas_probe,
- .remove = xhci_plat_remove,
+ .probe = xhci_renesas_probe,
+ .remove_new = xhci_plat_remove,
.shutdown = usb_hcd_platform_shutdown,
- .driver = {
+ .driver = {
.name = "xhci-renesas-hcd",
.pm = &xhci_plat_pm_ops,
.of_match_table = usb_xhci_of_match,
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 2bc82b3a2f98..646ff125def5 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -174,12 +174,10 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
/* All other rings have link trbs */
if (!trb_is_link(ring->dequeue)) {
- if (last_trb_on_seg(ring->deq_seg, ring->dequeue)) {
+ if (last_trb_on_seg(ring->deq_seg, ring->dequeue))
xhci_warn(xhci, "Missing link TRB at end of segment\n");
- } else {
+ else
ring->dequeue++;
- ring->num_trbs_free++;
- }
}
while (trb_is_link(ring->dequeue)) {
@@ -221,9 +219,6 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
unsigned int link_trb_count = 0;
chain = le32_to_cpu(ring->enqueue->generic.field[3]) & TRB_CHAIN;
- /* If this is not event ring, there is one less usable TRB */
- if (!trb_is_link(ring->enqueue))
- ring->num_trbs_free--;
if (last_trb_on_seg(ring->enq_seg, ring->enqueue)) {
xhci_err(xhci, "Tried to move enqueue past ring segment\n");
@@ -276,45 +271,84 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
trace_xhci_inc_enq(ring);
}
-static int xhci_num_trbs_to(struct xhci_segment *start_seg, union xhci_trb *start,
- struct xhci_segment *end_seg, union xhci_trb *end,
- unsigned int num_segs)
+/*
+ * Return number of free normal TRBs from enqueue to dequeue pointer on ring.
+ * Not counting an assumed link TRB at end of each TRBS_PER_SEGMENT sized segment.
+ * Only for transfer and command rings where driver is the producer, not for
+ * event rings.
+ */
+static unsigned int xhci_num_trbs_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
{
+ struct xhci_segment *enq_seg = ring->enq_seg;
+ union xhci_trb *enq = ring->enqueue;
union xhci_trb *last_on_seg;
- int num = 0;
+ unsigned int free = 0;
int i = 0;
+ /* Ring might be empty even if enq != deq if enq is left on a link trb */
+ if (trb_is_link(enq)) {
+ enq_seg = enq_seg->next;
+ enq = enq_seg->trbs;
+ }
+
+ /* Empty ring, common case, don't walk the segments */
+ if (enq == ring->dequeue)
+ return ring->num_segs * (TRBS_PER_SEGMENT - 1);
+
do {
- if (start_seg == end_seg && end >= start)
- return num + (end - start);
- last_on_seg = &start_seg->trbs[TRBS_PER_SEGMENT - 1];
- num += last_on_seg - start;
- start_seg = start_seg->next;
- start = start_seg->trbs;
- } while (i++ <= num_segs);
-
- return -EINVAL;
+ if (ring->deq_seg == enq_seg && ring->dequeue >= enq)
+ return free + (ring->dequeue - enq);
+ last_on_seg = &enq_seg->trbs[TRBS_PER_SEGMENT - 1];
+ free += last_on_seg - enq;
+ enq_seg = enq_seg->next;
+ enq = enq_seg->trbs;
+ } while (i++ <= ring->num_segs);
+
+ return free;
}
/*
* Check to see if there's room to enqueue num_trbs on the ring and make sure
* enqueue pointer will not advance into dequeue segment. See rules above.
+ * return number of new segments needed to ensure this.
*/
-static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
- unsigned int num_trbs)
+
+static unsigned int xhci_ring_expansion_needed(struct xhci_hcd *xhci, struct xhci_ring *ring,
+ unsigned int num_trbs)
{
- int num_trbs_in_deq_seg;
+ struct xhci_segment *seg;
+ int trbs_past_seg;
+ int enq_used;
+ int new_segs;
+
+ enq_used = ring->enqueue - ring->enq_seg->trbs;
+
+ /* how many trbs will be queued past the enqueue segment? */
+ trbs_past_seg = enq_used + num_trbs - (TRBS_PER_SEGMENT - 1);
- if (ring->num_trbs_free < num_trbs)
+ if (trbs_past_seg <= 0)
return 0;
- if (ring->type != TYPE_COMMAND && ring->type != TYPE_EVENT) {
- num_trbs_in_deq_seg = ring->dequeue - ring->deq_seg->trbs;
- if (ring->num_trbs_free < num_trbs + num_trbs_in_deq_seg)
- return 0;
+ /* Empty ring special case, enqueue stuck on link trb while dequeue advanced */
+ if (trb_is_link(ring->enqueue) && ring->enq_seg->next->trbs == ring->dequeue)
+ return 0;
+
+ new_segs = 1 + (trbs_past_seg / (TRBS_PER_SEGMENT - 1));
+ seg = ring->enq_seg;
+
+ while (new_segs > 0) {
+ seg = seg->next;
+ if (seg == ring->deq_seg) {
+ xhci_dbg(xhci, "Ring expansion by %d segments needed\n",
+ new_segs);
+ xhci_dbg(xhci, "Adding %d trbs moves enq %d trbs into deq seg\n",
+ num_trbs, trbs_past_seg % TRBS_PER_SEGMENT);
+ return new_segs;
+ }
+ new_segs--;
}
- return 1;
+ return 0;
}
/* Ring the host controller doorbell after placing a command on the ring */
@@ -1268,10 +1302,7 @@ static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci,
unsigned int ep_index)
{
union xhci_trb *dequeue_temp;
- int num_trbs_free_temp;
- bool revert = false;
- num_trbs_free_temp = ep_ring->num_trbs_free;
dequeue_temp = ep_ring->dequeue;
/* If we get two back-to-back stalls, and the first stalled transfer
@@ -1287,7 +1318,6 @@ static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci,
while (ep_ring->dequeue != dev->eps[ep_index].queued_deq_ptr) {
/* We have more usable TRBs */
- ep_ring->num_trbs_free++;
ep_ring->dequeue++;
if (trb_is_link(ep_ring->dequeue)) {
if (ep_ring->dequeue ==
@@ -1297,15 +1327,10 @@ static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci,
ep_ring->dequeue = ep_ring->deq_seg->trbs;
}
if (ep_ring->dequeue == dequeue_temp) {
- revert = true;
+ xhci_dbg(xhci, "Unable to find new dequeue pointer\n");
break;
}
}
-
- if (revert) {
- xhci_dbg(xhci, "Unable to find new dequeue pointer\n");
- ep_ring->num_trbs_free = num_trbs_free_temp;
- }
}
/*
@@ -2160,7 +2185,6 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
u32 trb_comp_code)
{
struct xhci_ep_ctx *ep_ctx;
- int trbs_freed;
ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep->ep_index);
@@ -2230,13 +2254,6 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
}
/* Update ring dequeue pointer */
- trbs_freed = xhci_num_trbs_to(ep_ring->deq_seg, ep_ring->dequeue,
- td->last_trb_seg, td->last_trb,
- ep_ring->num_segs);
- if (trbs_freed < 0)
- xhci_dbg(xhci, "Failed to count freed trbs at TD finish\n");
- else
- ep_ring->num_trbs_free += trbs_freed;
ep_ring->dequeue = td->last_trb;
ep_ring->deq_seg = td->last_trb_seg;
inc_deq(xhci, ep_ring);
@@ -2460,7 +2477,6 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
/* Update ring dequeue pointer */
ep->ring->dequeue = td->last_trb;
ep->ring->deq_seg = td->last_trb_seg;
- ep->ring->num_trbs_free += td->num_trbs - 1;
inc_deq(xhci, ep->ring);
return xhci_td_cleanup(xhci, td, ep->ring, status);
@@ -3165,13 +3181,13 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
/*
* Does various checks on the endpoint ring, and makes it ready to queue num_trbs.
- * FIXME allocate segments if the ring is full.
+ * expand ring if it start to be full.
*/
static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
u32 ep_state, unsigned int num_trbs, gfp_t mem_flags)
{
- unsigned int num_trbs_needed;
unsigned int link_trb_count = 0;
+ unsigned int new_segs = 0;
/* Make sure the endpoint has been added to xHC schedule */
switch (ep_state) {
@@ -3202,20 +3218,17 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
return -EINVAL;
}
- while (1) {
- if (room_on_ring(xhci, ep_ring, num_trbs))
- break;
-
- if (ep_ring == xhci->cmd_ring) {
- xhci_err(xhci, "Do not support expand command ring\n");
- return -ENOMEM;
- }
+ if (ep_ring != xhci->cmd_ring) {
+ new_segs = xhci_ring_expansion_needed(xhci, ep_ring, num_trbs);
+ } else if (xhci_num_trbs_free(xhci, ep_ring) <= num_trbs) {
+ xhci_err(xhci, "Do not support expand command ring\n");
+ return -ENOMEM;
+ }
+ if (new_segs) {
xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion,
"ERROR no room on ep ring, try ring expansion");
- num_trbs_needed = num_trbs - ep_ring->num_trbs_free;
- if (xhci_ring_expansion(xhci, ep_ring, num_trbs_needed,
- mem_flags)) {
+ if (xhci_ring_expansion(xhci, ep_ring, new_segs, mem_flags)) {
xhci_err(xhci, "Ring expansion failed\n");
return -ENOMEM;
}
@@ -4185,7 +4198,6 @@ cleanup:
ep_ring->enqueue = urb_priv->td[0].first_trb;
ep_ring->enq_seg = urb_priv->td[0].start_seg;
ep_ring->cycle_state = start_cycle;
- ep_ring->num_trbs_free = ep_ring->num_trbs_free_temp;
usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
return ret;
}
@@ -4267,7 +4279,6 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
}
skip_start_over:
- ep_ring->num_trbs_free_temp = ep_ring->num_trbs_free;
return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index);
}
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index c75d93244143..6ca8a37e53e1 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -1828,6 +1828,9 @@ static int tegra_xusb_probe(struct platform_device *pdev)
goto remove_usb2;
}
+ if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
+ xhci->shared_hcd->can_do_streams = 1;
+
err = usb_add_hcd(xhci->shared_hcd, tegra->xhci_irq, IRQF_SHARED);
if (err < 0) {
dev_err(&pdev->dev, "failed to add shared HCD: %d\n", err);
@@ -1909,7 +1912,7 @@ put_padctl:
return err;
}
-static int tegra_xusb_remove(struct platform_device *pdev)
+static void tegra_xusb_remove(struct platform_device *pdev)
{
struct tegra_xusb *tegra = platform_get_drvdata(pdev);
struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd);
@@ -1939,8 +1942,6 @@ static int tegra_xusb_remove(struct platform_device *pdev)
tegra_xusb_clk_disable(tegra);
regulator_bulk_disable(tegra->soc->num_supplies, tegra->supplies);
tegra_xusb_padctl_put(tegra->padctl);
-
- return 0;
}
static bool xhci_hub_ports_suspended(struct xhci_hub *hub)
@@ -2272,7 +2273,7 @@ static int tegra_xusb_exit_elpg(struct tegra_xusb *tegra, bool runtime)
if (wakeup)
tegra_xhci_disable_phy_sleepwalk(tegra);
- err = xhci_resume(xhci, 0);
+ err = xhci_resume(xhci, runtime ? PMSG_AUTO_RESUME : PMSG_RESUME);
if (err < 0) {
dev_err(tegra->dev, "failed to resume XHCI: %d\n", err);
goto disable_phy;
@@ -2650,7 +2651,7 @@ MODULE_DEVICE_TABLE(of, tegra_xusb_of_match);
static struct platform_driver tegra_xusb_driver = {
.probe = tegra_xusb_probe,
- .remove = tegra_xusb_remove,
+ .remove_new = tegra_xusb_remove,
.driver = {
.name = "tegra-xusb",
.pm = &tegra_xusb_pm_ops,
@@ -2662,7 +2663,6 @@ static void tegra_xhci_quirks(struct device *dev, struct xhci_hcd *xhci)
{
struct tegra_xusb *tegra = dev_get_drvdata(dev);
- xhci->quirks |= XHCI_PLAT;
if (tegra && tegra->soc->lpm_support)
xhci->quirks |= XHCI_LPM_SUPPORT;
}
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
index 4286dba5b157..d6b32f2ad90e 100644
--- a/drivers/usb/host/xhci-trace.h
+++ b/drivers/usb/host/xhci-trace.h
@@ -80,20 +80,16 @@ DECLARE_EVENT_CLASS(xhci_log_ctx,
__field(dma_addr_t, ctx_dma)
__field(u8 *, ctx_va)
__field(unsigned, ctx_ep_num)
- __field(int, slot_id)
__dynamic_array(u32, ctx_data,
((HCC_64BYTE_CONTEXT(xhci->hcc_params) + 1) * 8) *
((ctx->type == XHCI_CTX_TYPE_INPUT) + ep_num + 1))
),
TP_fast_assign(
- struct usb_device *udev;
- udev = to_usb_device(xhci_to_hcd(xhci)->self.controller);
__entry->ctx_64 = HCC_64BYTE_CONTEXT(xhci->hcc_params);
__entry->ctx_type = ctx->type;
__entry->ctx_dma = ctx->dma;
__entry->ctx_va = ctx->bytes;
- __entry->slot_id = udev->slot_id;
__entry->ctx_ep_num = ep_num;
memcpy(__get_dynamic_array(ctx_data), ctx->bytes,
((HCC_64BYTE_CONTEXT(xhci->hcc_params) + 1) * 32) *
@@ -462,7 +458,6 @@ DECLARE_EVENT_CLASS(xhci_log_ring,
__field(unsigned int, num_segs)
__field(unsigned int, stream_id)
__field(unsigned int, cycle_state)
- __field(unsigned int, num_trbs_free)
__field(unsigned int, bounce_buf_len)
),
TP_fast_assign(
@@ -473,18 +468,16 @@ DECLARE_EVENT_CLASS(xhci_log_ring,
__entry->enq_seg = ring->enq_seg->dma;
__entry->deq_seg = ring->deq_seg->dma;
__entry->cycle_state = ring->cycle_state;
- __entry->num_trbs_free = ring->num_trbs_free;
__entry->bounce_buf_len = ring->bounce_buf_len;
__entry->enq = xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue);
__entry->deq = xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue);
),
- TP_printk("%s %p: enq %pad(%pad) deq %pad(%pad) segs %d stream %d free_trbs %d bounce %d cycle %d",
+ TP_printk("%s %p: enq %pad(%pad) deq %pad(%pad) segs %d stream %d bounce %d cycle %d",
xhci_ring_type_string(__entry->type), __entry->ring,
&__entry->enq, &__entry->enq_seg,
&__entry->deq, &__entry->deq_seg,
__entry->num_segs,
__entry->stream_id,
- __entry->num_trbs_free,
__entry->bounce_buf_len,
__entry->cycle_state
)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 78790dc13c5f..fae994f679d4 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -833,7 +833,7 @@ static bool xhci_pending_portevent(struct xhci_hcd *xhci)
ports = xhci->usb3_rhub.ports;
while (port_index--) {
portsc = readl(ports[port_index]->addr);
- if (portsc & PORT_CHANGE_MASK ||
+ if (portsc & (PORT_CHANGE_MASK | PORT_CAS) ||
(portsc & PORT_PLS_MASK) == XDEV_RESUME)
return true;
}
@@ -960,8 +960,9 @@ EXPORT_SYMBOL_GPL(xhci_suspend);
* This is called when the machine transition from S3/S4 mode.
*
*/
-int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)
{
+ bool hibernated = (msg.event == PM_EVENT_RESTORE);
u32 command, temp = 0;
struct usb_hcd *hcd = xhci_to_hcd(xhci);
int retval = 0;
@@ -1027,7 +1028,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
temp = readl(&xhci->op_regs->status);
/* re-initialize the HC on Restore Error, or Host Controller Error */
- if (temp & (STS_SRE | STS_HCE)) {
+ if ((temp & (STS_SRE | STS_HCE)) &&
+ !(xhci->xhc_state & XHCI_STATE_REMOVING)) {
reinit_xhc = true;
if (!xhci->broken_suspend)
xhci_warn(xhci, "xHC error in resume, USBSTS 0x%x, Reinit\n", temp);
@@ -1116,7 +1118,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
* the first wake signalling failed, give it that chance.
*/
pending_portevent = xhci_pending_portevent(xhci);
- if (!pending_portevent) {
+ if (!pending_portevent && msg.event == PM_EVENT_AUTO_RESUME) {
msleep(120);
pending_portevent = xhci_pending_portevent(xhci);
}
@@ -4604,7 +4606,7 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci,
}
}
- if (xhci->quirks & XHCI_INTEL_HOST)
+ if (xhci->quirks & (XHCI_INTEL_HOST | XHCI_ZHAOXIN_HOST))
timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
else
timeout_ns = udev->u1_params.sel;
@@ -4668,7 +4670,7 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci,
}
}
- if (xhci->quirks & XHCI_INTEL_HOST)
+ if (xhci->quirks & (XHCI_INTEL_HOST | XHCI_ZHAOXIN_HOST))
timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
else
timeout_ns = udev->u2_params.sel;
@@ -4740,37 +4742,30 @@ static int xhci_update_timeout_for_interface(struct xhci_hcd *xhci,
return 0;
}
-static int xhci_check_intel_tier_policy(struct usb_device *udev,
+static int xhci_check_tier_policy(struct xhci_hcd *xhci,
+ struct usb_device *udev,
enum usb3_link_state state)
{
- struct usb_device *parent;
- unsigned int num_hubs;
+ struct usb_device *parent = udev->parent;
+ int tier = 1; /* roothub is tier1 */
- /* Don't enable U1 if the device is on a 2nd tier hub or lower. */
- for (parent = udev->parent, num_hubs = 0; parent->parent;
- parent = parent->parent)
- num_hubs++;
+ while (parent) {
+ parent = parent->parent;
+ tier++;
+ }
- if (num_hubs < 2)
- return 0;
+ if (xhci->quirks & XHCI_INTEL_HOST && tier > 3)
+ goto fail;
+ if (xhci->quirks & XHCI_ZHAOXIN_HOST && tier > 2)
+ goto fail;
- dev_dbg(&udev->dev, "Disabling U1/U2 link state for device"
- " below second-tier hub.\n");
- dev_dbg(&udev->dev, "Plug device into first-tier hub "
- "to decrease power consumption.\n");
+ return 0;
+fail:
+ dev_dbg(&udev->dev, "Tier policy prevents U1/U2 LPM states for devices at tier %d\n",
+ tier);
return -E2BIG;
}
-static int xhci_check_tier_policy(struct xhci_hcd *xhci,
- struct usb_device *udev,
- enum usb3_link_state state)
-{
- if (xhci->quirks & XHCI_INTEL_HOST)
- return xhci_check_intel_tier_policy(udev, state);
- else
- return 0;
-}
-
/* Returns the U1 or U2 timeout that should be enabled.
* If the tier check or timeout setting functions return with a non-zero exit
* code, that means the timeout value has been finalized and we shouldn't look
@@ -5180,7 +5175,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
xhci->quirks |= quirks;
- get_quirks(dev, xhci);
+ if (get_quirks)
+ get_quirks(dev, xhci);
/* In xhci controllers which follow xhci 1.0 spec gives a spurious
* success event after a short transfer. This quirk will ignore such
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 6b690ec91ff3..7e282b4522c0 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1633,8 +1633,7 @@ struct xhci_ring {
u32 cycle_state;
unsigned int stream_id;
unsigned int num_segs;
- unsigned int num_trbs_free;
- unsigned int num_trbs_free_temp;
+ unsigned int num_trbs_free; /* used only by xhci DbC */
unsigned int bounce_buf_len;
enum xhci_ring_type type;
bool last_td_was_short;
@@ -1874,7 +1873,7 @@ struct xhci_hcd {
#define XHCI_SPURIOUS_REBOOT BIT_ULL(13)
#define XHCI_COMP_MODE_QUIRK BIT_ULL(14)
#define XHCI_AVOID_BEI BIT_ULL(15)
-#define XHCI_PLAT BIT_ULL(16)
+#define XHCI_PLAT BIT_ULL(16) /* Deprecated */
#define XHCI_SLOW_SUSPEND BIT_ULL(17)
#define XHCI_SPURIOUS_WAKEUP BIT_ULL(18)
/* For controllers with a broken beyond repair streams implementation */
@@ -1905,6 +1904,8 @@ struct xhci_hcd {
#define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42)
#define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43)
#define XHCI_RESET_TO_DEFAULT BIT_ULL(44)
+#define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45)
+#define XHCI_ZHAOXIN_HOST BIT_ULL(46)
unsigned int num_active_eps;
unsigned int limit_active_eps;
@@ -2140,7 +2141,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
int xhci_ext_cap_init(struct xhci_hcd *xhci);
int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup);
-int xhci_resume(struct xhci_hcd *xhci, bool hibernated);
+int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg);
irqreturn_t xhci_irq(struct usb_hcd *hcd);
irqreturn_t xhci_msi_irq(int irq, void *hcd);
diff --git a/drivers/usb/isp1760/isp1760-if.c b/drivers/usb/isp1760/isp1760-if.c
index 65ba5aca2a4f..fe1e3985419a 100644
--- a/drivers/usb/isp1760/isp1760-if.c
+++ b/drivers/usb/isp1760/isp1760-if.c
@@ -246,11 +246,9 @@ static int isp1760_plat_probe(struct platform_device *pdev)
return 0;
}
-static int isp1760_plat_remove(struct platform_device *pdev)
+static void isp1760_plat_remove(struct platform_device *pdev)
{
isp1760_unregister(&pdev->dev);
-
- return 0;
}
#ifdef CONFIG_OF
@@ -265,7 +263,7 @@ MODULE_DEVICE_TABLE(of, isp1760_of_match);
static struct platform_driver isp1760_plat_driver = {
.probe = isp1760_plat_probe,
- .remove = isp1760_plat_remove,
+ .remove_new = isp1760_plat_remove,
.driver = {
.name = "isp1760",
.of_match_table = of_match_ptr(isp1760_of_match),
diff --git a/drivers/usb/misc/onboard_usb_hub.c b/drivers/usb/misc/onboard_usb_hub.c
index 12fc6eb67c3b..83f14ca1d38e 100644
--- a/drivers/usb/misc/onboard_usb_hub.c
+++ b/drivers/usb/misc/onboard_usb_hub.c
@@ -278,7 +278,7 @@ static int onboard_hub_probe(struct platform_device *pdev)
return 0;
}
-static int onboard_hub_remove(struct platform_device *pdev)
+static void onboard_hub_remove(struct platform_device *pdev)
{
struct onboard_hub *hub = dev_get_drvdata(&pdev->dev);
struct usbdev_node *node;
@@ -306,7 +306,7 @@ static int onboard_hub_remove(struct platform_device *pdev)
mutex_unlock(&hub->lock);
- return onboard_hub_power_off(hub);
+ onboard_hub_power_off(hub);
}
MODULE_DEVICE_TABLE(of, onboard_hub_match);
@@ -317,7 +317,7 @@ static const struct dev_pm_ops __maybe_unused onboard_hub_pm_ops = {
static struct platform_driver onboard_hub_driver = {
.probe = onboard_hub_probe,
- .remove = onboard_hub_remove,
+ .remove_new = onboard_hub_remove,
.driver = {
.name = "onboard-usb-hub",
diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c
index b7f13df00764..7f371ea1248c 100644
--- a/drivers/usb/misc/qcom_eud.c
+++ b/drivers/usb/misc/qcom_eud.c
@@ -22,10 +22,10 @@
#define EUD_REG_VBUS_INT_CLR 0x0080
#define EUD_REG_CSR_EUD_EN 0x1014
#define EUD_REG_SW_ATTACH_DET 0x1018
-#define EUD_REG_EUD_EN2 0x0000
+#define EUD_REG_EUD_EN2 0x0000
#define EUD_ENABLE BIT(0)
-#define EUD_INT_PET_EUD BIT(0)
+#define EUD_INT_PET_EUD BIT(0)
#define EUD_INT_VBUS BIT(2)
#define EUD_INT_SAFE_MODE BIT(4)
#define EUD_INT_ALL (EUD_INT_VBUS | EUD_INT_SAFE_MODE)
@@ -217,7 +217,7 @@ static int eud_probe(struct platform_device *pdev)
return 0;
}
-static int eud_remove(struct platform_device *pdev)
+static void eud_remove(struct platform_device *pdev)
{
struct eud_chip *chip = platform_get_drvdata(pdev);
@@ -226,8 +226,6 @@ static int eud_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, false);
disable_irq_wake(chip->irq);
-
- return 0;
}
static const struct of_device_id eud_dt_match[] = {
@@ -238,7 +236,7 @@ MODULE_DEVICE_TABLE(of, eud_dt_match);
static struct platform_driver eud_driver = {
.probe = eud_probe,
- .remove = eud_remove,
+ .remove_new = eud_remove,
.driver = {
.name = "qcom_eud",
.dev_groups = eud_groups,
diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c
index ce1da80d3365..e4edb486b69e 100644
--- a/drivers/usb/misc/usb251xb.c
+++ b/drivers/usb/misc/usb251xb.c
@@ -416,14 +416,13 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
return dev_err_probe(dev, PTR_ERR(hub->gpio_reset),
"unable to request GPIO reset pin\n");
- if (of_property_read_u16_array(np, "vendor-id", &hub->vendor_id, 1))
+ if (of_property_read_u16(np, "vendor-id", &hub->vendor_id))
hub->vendor_id = USB251XB_DEF_VENDOR_ID;
- if (of_property_read_u16_array(np, "product-id",
- &hub->product_id, 1))
+ if (of_property_read_u16(np, "product-id", &hub->product_id))
hub->product_id = data->product_id;
- if (of_property_read_u16_array(np, "device-id", &hub->device_id, 1))
+ if (of_property_read_u16(np, "device-id", &hub->device_id))
hub->device_id = USB251XB_DEF_DEVICE_ID;
hub->conf_data1 = USB251XB_DEF_CONFIG_DATA_1;
@@ -532,7 +531,7 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
if (!of_property_read_u32(np, "power-on-time-ms", &property_u32))
hub->power_on_time = min_t(u8, property_u32 / 2, 255);
- if (of_property_read_u16_array(np, "language-id", &hub->lang_id, 1))
+ if (of_property_read_u16(np, "language-id", &hub->lang_id))
hub->lang_id = USB251XB_DEF_LANGUAGE_ID;
if (of_property_read_u8(np, "boost-up", &hub->boost_up))
@@ -746,7 +745,7 @@ static struct i2c_driver usb251xb_i2c_driver = {
.of_match_table = usb251xb_of_match,
.pm = &usb251xb_pm_ops,
},
- .probe_new = usb251xb_i2c_probe,
+ .probe = usb251xb_i2c_probe,
.id_table = usb251xb_id,
};
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index c6cfd1edaf76..72765077932c 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -335,14 +335,12 @@ static int usb3503_platform_probe(struct platform_device *pdev)
return usb3503_probe(hub);
}
-static int usb3503_platform_remove(struct platform_device *pdev)
+static void usb3503_platform_remove(struct platform_device *pdev)
{
struct usb3503 *hub;
hub = platform_get_drvdata(pdev);
clk_disable_unprepare(hub->clk);
-
- return 0;
}
static int __maybe_unused usb3503_suspend(struct usb3503 *hub)
@@ -413,7 +411,7 @@ static struct i2c_driver usb3503_i2c_driver = {
.pm = pm_ptr(&usb3503_i2c_pm_ops),
.of_match_table = of_match_ptr(usb3503_of_match),
},
- .probe_new = usb3503_i2c_probe,
+ .probe = usb3503_i2c_probe,
.remove = usb3503_i2c_remove,
.id_table = usb3503_id,
};
@@ -425,7 +423,7 @@ static struct platform_driver usb3503_platform_driver = {
.pm = pm_ptr(&usb3503_platform_pm_ops),
},
.probe = usb3503_platform_probe,
- .remove = usb3503_platform_remove,
+ .remove_new = usb3503_platform_remove,
};
static int __init usb3503_init(void)
diff --git a/drivers/usb/misc/usb4604.c b/drivers/usb/misc/usb4604.c
index 6b5e77231efa..065e269ba4e3 100644
--- a/drivers/usb/misc/usb4604.c
+++ b/drivers/usb/misc/usb4604.c
@@ -154,7 +154,7 @@ static struct i2c_driver usb4604_i2c_driver = {
.pm = pm_ptr(&usb4604_i2c_pm_ops),
.of_match_table = of_match_ptr(usb4604_of_match),
},
- .probe_new = usb4604_i2c_probe,
+ .probe = usb4604_i2c_probe,
.id_table = usb4604_id,
};
module_i2c_driver(usb4604_i2c_driver);
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 952c56789258..9ca9305243fe 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -213,7 +213,10 @@ static unsigned char xfer_to_pipe[4] = {
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
};
-static struct class *mon_bin_class;
+static const struct class mon_bin_class = {
+ .name = "usbmon",
+};
+
static dev_t mon_bin_dev0;
static struct cdev mon_bin_cdev;
@@ -1360,7 +1363,7 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
if (minor >= MON_BIN_MAX_MINOR)
return 0;
- dev = device_create(mon_bin_class, ubus ? ubus->controller : NULL,
+ dev = device_create(&mon_bin_class, ubus ? ubus->controller : NULL,
MKDEV(MAJOR(mon_bin_dev0), minor), NULL,
"usbmon%d", minor);
if (IS_ERR(dev))
@@ -1372,18 +1375,16 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
void mon_bin_del(struct mon_bus *mbus)
{
- device_destroy(mon_bin_class, mbus->classdev->devt);
+ device_destroy(&mon_bin_class, mbus->classdev->devt);
}
int __init mon_bin_init(void)
{
int rc;
- mon_bin_class = class_create("usbmon");
- if (IS_ERR(mon_bin_class)) {
- rc = PTR_ERR(mon_bin_class);
+ rc = class_register(&mon_bin_class);
+ if (rc)
goto err_class;
- }
rc = alloc_chrdev_region(&mon_bin_dev0, 0, MON_BIN_MAX_MINOR, "usbmon");
if (rc < 0)
@@ -1401,7 +1402,7 @@ int __init mon_bin_init(void)
err_add:
unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
err_dev:
- class_destroy(mon_bin_class);
+ class_unregister(&mon_bin_class);
err_class:
return rc;
}
@@ -1410,5 +1411,5 @@ void mon_bin_exit(void)
{
cdev_del(&mon_bin_cdev);
unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
- class_destroy(mon_bin_class);
+ class_unregister(&mon_bin_class);
}
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index d162afbbe19f..ecbd3784bec3 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2330,7 +2330,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
spin_lock_init(&musb->lock);
spin_lock_init(&musb->list_lock);
- musb->board_set_power = plat->set_power;
musb->min_power = plat->min_power;
musb->ops = plat->platform_ops;
musb->port_mode = plat->mode;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index b7588d11cfc5..91b5b6b66f96 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -352,8 +352,6 @@ struct musb {
u16 epmask;
u8 nr_endpoints;
- int (*board_set_power)(int state);
-
u8 min_power; /* vbus for periph, in mA/2 */
enum musb_mode port_mode;
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index a1f29dbc62e6..cbc707fe570f 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -11,6 +11,8 @@
* interface.
*/
+#include <linux/gpio/consumer.h>
+#include <linux/delay.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -30,6 +32,8 @@ struct tusb6010_glue {
struct device *dev;
struct platform_device *musb;
struct platform_device *phy;
+ struct gpio_desc *enable;
+ struct gpio_desc *intpin;
};
static void tusb_musb_set_vbus(struct musb *musb, int is_on);
@@ -1021,16 +1025,29 @@ static void tusb_setup_cpu_interface(struct musb *musb)
static int tusb_musb_start(struct musb *musb)
{
+ struct tusb6010_glue *glue = dev_get_drvdata(musb->controller->parent);
void __iomem *tbase = musb->ctrl_base;
- int ret = 0;
unsigned long flags;
u32 reg;
+ int i;
- if (musb->board_set_power)
- ret = musb->board_set_power(1);
- if (ret != 0) {
- printk(KERN_ERR "tusb: Cannot enable TUSB6010\n");
- return ret;
+ /*
+ * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
+ * 1.5 V voltage regulators of PM companion chip. Companion chip will then
+ * provide then PGOOD signal to TUSB6010 which will release it from reset.
+ */
+ gpiod_set_value(glue->enable, 1);
+ msleep(1);
+
+ /* Wait for 100ms until TUSB6010 pulls INT pin down */
+ i = 100;
+ while (i && gpiod_get_value(glue->intpin)) {
+ msleep(1);
+ i--;
+ }
+ if (!i) {
+ pr_err("tusb: Powerup respones failed\n");
+ return -ENODEV;
}
spin_lock_irqsave(&musb->lock, flags);
@@ -1083,8 +1100,8 @@ static int tusb_musb_start(struct musb *musb)
err:
spin_unlock_irqrestore(&musb->lock, flags);
- if (musb->board_set_power)
- musb->board_set_power(0);
+ gpiod_set_value(glue->enable, 0);
+ msleep(10);
return -ENODEV;
}
@@ -1158,11 +1175,13 @@ done:
static int tusb_musb_exit(struct musb *musb)
{
+ struct tusb6010_glue *glue = dev_get_drvdata(musb->controller->parent);
+
del_timer_sync(&musb->dev_timer);
the_musb = NULL;
- if (musb->board_set_power)
- musb->board_set_power(0);
+ gpiod_set_value(glue->enable, 0);
+ msleep(10);
iounmap(musb->sync_va);
@@ -1218,6 +1237,15 @@ static int tusb_probe(struct platform_device *pdev)
glue->dev = &pdev->dev;
+ glue->enable = devm_gpiod_get(glue->dev, "enable", GPIOD_OUT_LOW);
+ if (IS_ERR(glue->enable))
+ return dev_err_probe(glue->dev, PTR_ERR(glue->enable),
+ "could not obtain power on/off GPIO\n");
+ glue->intpin = devm_gpiod_get(glue->dev, "int", GPIOD_IN);
+ if (IS_ERR(glue->intpin))
+ return dev_err_probe(glue->dev, PTR_ERR(glue->intpin),
+ "could not obtain INT GPIO\n");
+
pdata->platform_ops = &tusb_ops;
usb_phy_generic_register();
@@ -1236,10 +1264,7 @@ static int tusb_probe(struct platform_device *pdev)
musb_resources[1].end = pdev->resource[1].end;
musb_resources[1].flags = pdev->resource[1].flags;
- musb_resources[2].name = pdev->resource[2].name;
- musb_resources[2].start = pdev->resource[2].start;
- musb_resources[2].end = pdev->resource[2].end;
- musb_resources[2].flags = pdev->resource[2].flags;
+ musb_resources[2] = DEFINE_RES_IRQ_NAMED(gpiod_to_irq(glue->intpin), "mc");
pinfo = tusb_dev_info;
pinfo.parent = &pdev->dev;
diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c
index f4ee14d98585..993d7525a102 100644
--- a/drivers/usb/phy/phy-isp1301.c
+++ b/drivers/usb/phy/phy-isp1301.c
@@ -132,7 +132,7 @@ static struct i2c_driver isp1301_driver = {
.name = DRV_NAME,
.of_match_table = isp1301_of_match,
},
- .probe_new = isp1301_probe,
+ .probe = isp1301_probe,
.remove = isp1301_remove,
.id_table = isp1301_id,
};
diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c
index 47562d49dfc1..5cac31c6029b 100644
--- a/drivers/usb/phy/phy-tahvo.c
+++ b/drivers/usb/phy/phy-tahvo.c
@@ -391,7 +391,7 @@ static int tahvo_usb_probe(struct platform_device *pdev)
tu->irq = ret = platform_get_irq(pdev, 0);
if (ret < 0)
- return ret;
+ goto err_remove_phy;
ret = request_threaded_irq(tu->irq, NULL, tahvo_usb_vbus_interrupt,
IRQF_ONESHOT,
"tahvo-vbus", tu);
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index fa34efabcccf..111b7ee152c4 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -762,7 +762,7 @@ probe_end_pipe_exit:
return ret;
}
-static int usbhs_remove(struct platform_device *pdev)
+static void usbhs_remove(struct platform_device *pdev)
{
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
@@ -780,8 +780,6 @@ static int usbhs_remove(struct platform_device *pdev)
usbhs_mod_remove(priv);
usbhs_fifo_remove(priv);
usbhs_pipe_remove(priv);
-
- return 0;
}
static __maybe_unused int usbhsc_suspend(struct device *dev)
@@ -826,7 +824,7 @@ static struct platform_driver renesas_usbhs_driver = {
.of_match_table = usbhs_of_match,
},
.probe = usbhs_probe,
- .remove = usbhs_remove,
+ .remove_new = usbhs_remove,
};
module_platform_driver(renesas_usbhs_driver);
diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
index 0395bd5dbd3e..ae41578bd014 100644
--- a/drivers/usb/roles/class.c
+++ b/drivers/usb/roles/class.c
@@ -14,7 +14,9 @@
#include <linux/mutex.h>
#include <linux/slab.h>
-static struct class *role_class;
+static const struct class role_class = {
+ .name = "usb_role",
+};
struct usb_role_switch {
struct device dev;
@@ -95,7 +97,7 @@ static void *usb_role_switch_match(const struct fwnode_handle *fwnode, const cha
if (id && !fwnode_property_present(fwnode, id))
return NULL;
- dev = class_find_device_by_fwnode(role_class, fwnode);
+ dev = class_find_device_by_fwnode(&role_class, fwnode);
return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER);
}
@@ -111,7 +113,7 @@ usb_role_switch_is_parent(struct fwnode_handle *fwnode)
return NULL;
}
- dev = class_find_device_by_fwnode(role_class, parent);
+ dev = class_find_device_by_fwnode(&role_class, parent);
fwnode_handle_put(parent);
return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER);
}
@@ -191,7 +193,7 @@ usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode)
if (!fwnode)
return NULL;
- dev = class_find_device_by_fwnode(role_class, fwnode);
+ dev = class_find_device_by_fwnode(&role_class, fwnode);
if (dev)
WARN_ON(!try_module_get(dev->parent->driver->owner));
@@ -338,7 +340,7 @@ usb_role_switch_register(struct device *parent,
sw->dev.parent = parent;
sw->dev.fwnode = desc->fwnode;
- sw->dev.class = role_class;
+ sw->dev.class = &role_class;
sw->dev.type = &usb_role_dev_type;
dev_set_drvdata(&sw->dev, desc->driver_data);
dev_set_name(&sw->dev, "%s-role-switch",
@@ -392,14 +394,13 @@ EXPORT_SYMBOL_GPL(usb_role_switch_get_drvdata);
static int __init usb_roles_init(void)
{
- role_class = class_create("usb_role");
- return PTR_ERR_OR_ZERO(role_class);
+ return class_register(&role_class);
}
subsys_initcall(usb_roles_init);
static void __exit usb_roles_exit(void)
{
- class_destroy(role_class);
+ class_unregister(&role_class);
}
module_exit(usb_roles_exit);
diff --git a/drivers/usb/roles/intel-xhci-usb-role-switch.c b/drivers/usb/roles/intel-xhci-usb-role-switch.c
index 5c96e929acea..e5c6c413a075 100644
--- a/drivers/usb/roles/intel-xhci-usb-role-switch.c
+++ b/drivers/usb/roles/intel-xhci-usb-role-switch.c
@@ -195,7 +195,7 @@ static int intel_xhci_usb_probe(struct platform_device *pdev)
return 0;
}
-static int intel_xhci_usb_remove(struct platform_device *pdev)
+static void intel_xhci_usb_remove(struct platform_device *pdev)
{
struct intel_xhci_usb_data *data = platform_get_drvdata(pdev);
@@ -203,8 +203,6 @@ static int intel_xhci_usb_remove(struct platform_device *pdev)
usb_role_switch_unregister(data->role_sw);
fwnode_handle_put(software_node_fwnode(&intel_xhci_usb_node));
-
- return 0;
}
static const struct platform_device_id intel_xhci_usb_table[] = {
@@ -219,7 +217,7 @@ static struct platform_driver intel_xhci_usb_driver = {
},
.id_table = intel_xhci_usb_table,
.probe = intel_xhci_usb_probe,
- .remove = intel_xhci_usb_remove,
+ .remove_new = intel_xhci_usb_remove,
};
module_platform_driver(intel_xhci_usb_driver);
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 9452291f1703..67a07cc007f0 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -433,10 +433,11 @@ static int ark3116_tiocmset(struct tty_struct *tty,
return 0;
}
-static void ark3116_break_ctl(struct tty_struct *tty, int break_state)
+static int ark3116_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct ark3116_private *priv = usb_get_serial_port_data(port);
+ int ret;
/* LCR is also used for other things: protect access */
mutex_lock(&priv->hw_lock);
@@ -446,9 +447,11 @@ static void ark3116_break_ctl(struct tty_struct *tty, int break_state)
else
priv->lcr &= ~UART_LCR_SBC;
- ark3116_write_reg(port->serial, UART_LCR, priv->lcr);
+ ret = ark3116_write_reg(port->serial, UART_LCR, priv->lcr);
mutex_unlock(&priv->hw_lock);
+
+ return ret;
}
static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 9331a562dac0..cf47ee4ae5d3 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -46,7 +46,7 @@ static void belkin_sa_process_read_urb(struct urb *urb);
static void belkin_sa_set_termios(struct tty_struct *tty,
struct usb_serial_port *port,
const struct ktermios *old_termios);
-static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state);
+static int belkin_sa_break_ctl(struct tty_struct *tty, int break_state);
static int belkin_sa_tiocmget(struct tty_struct *tty);
static int belkin_sa_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
@@ -399,13 +399,19 @@ static void belkin_sa_set_termios(struct tty_struct *tty,
spin_unlock_irqrestore(&priv->lock, flags);
}
-static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state)
+static int belkin_sa_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
+ int ret;
- if (BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0) < 0)
+ ret = BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0);
+ if (ret < 0) {
dev_err(&port->dev, "Set break_ctl %d\n", break_state);
+ return ret;
+ }
+
+ return 0;
}
static int belkin_sa_tiocmget(struct tty_struct *tty)
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 6e1b87e67304..612bea504d7a 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -562,12 +562,12 @@ static void ch341_set_termios(struct tty_struct *tty,
* TCSBRKP. Due to how the simulation is implemented the duration can't be
* controlled. The duration is always about (1s / 46bd * 9bit) = 196ms.
*/
-static void ch341_simulate_break(struct tty_struct *tty, int break_state)
+static int ch341_simulate_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned long now, delay;
- int r;
+ int r, r2;
if (break_state != 0) {
dev_dbg(&port->dev, "enter break state requested\n");
@@ -599,7 +599,7 @@ static void ch341_simulate_break(struct tty_struct *tty, int break_state)
*/
priv->break_end = jiffies + (11 * HZ / CH341_MIN_BPS);
- return;
+ return 0;
}
dev_dbg(&port->dev, "leave break state requested\n");
@@ -615,17 +615,22 @@ static void ch341_simulate_break(struct tty_struct *tty, int break_state)
schedule_timeout_interruptible(delay);
}
+ r = 0;
restore:
/* Restore original baud rate */
- r = ch341_set_baudrate_lcr(port->serial->dev, priv, priv->baud_rate,
- priv->lcr);
- if (r < 0)
+ r2 = ch341_set_baudrate_lcr(port->serial->dev, priv, priv->baud_rate,
+ priv->lcr);
+ if (r2 < 0) {
dev_err(&port->dev,
"restoring original baud rate of %u failed: %d\n",
- priv->baud_rate, r);
+ priv->baud_rate, r2);
+ return r2;
+ }
+
+ return r;
}
-static void ch341_break_ctl(struct tty_struct *tty, int break_state)
+static int ch341_break_ctl(struct tty_struct *tty, int break_state)
{
const uint16_t ch341_break_reg =
((uint16_t) CH341_REG_LCR << 8) | CH341_REG_BREAK;
@@ -635,17 +640,17 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state)
uint16_t reg_contents;
uint8_t break_reg[2];
- if (priv->quirks & CH341_QUIRK_SIMULATE_BREAK) {
- ch341_simulate_break(tty, break_state);
- return;
- }
+ if (priv->quirks & CH341_QUIRK_SIMULATE_BREAK)
+ return ch341_simulate_break(tty, break_state);
r = ch341_control_in(port->serial->dev, CH341_REQ_READ_REG,
ch341_break_reg, 0, break_reg, 2);
if (r) {
dev_err(&port->dev, "%s - USB control read error (%d)\n",
__func__, r);
- return;
+ if (r > 0)
+ r = -EIO;
+ return r;
}
dev_dbg(&port->dev, "%s - initial ch341 break register contents - reg1: %x, reg2: %x\n",
__func__, break_reg[0], break_reg[1]);
@@ -663,9 +668,13 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state)
reg_contents = get_unaligned_le16(break_reg);
r = ch341_control_out(port->serial->dev, CH341_REQ_WRITE_REG,
ch341_break_reg, reg_contents);
- if (r < 0)
+ if (r < 0) {
dev_err(&port->dev, "%s - USB control write error (%d)\n",
__func__, r);
+ return r;
+ }
+
+ return 0;
}
static int ch341_tiocmset(struct tty_struct *tty,
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index cdea1bff3b70..1e61fe043171 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -39,7 +39,7 @@ static int cp210x_tiocmget(struct tty_struct *);
static int cp210x_tiocmset(struct tty_struct *, unsigned int, unsigned int);
static int cp210x_tiocmset_port(struct usb_serial_port *port,
unsigned int, unsigned int);
-static void cp210x_break_ctl(struct tty_struct *, int);
+static int cp210x_break_ctl(struct tty_struct *, int);
static int cp210x_attach(struct usb_serial *);
static void cp210x_disconnect(struct usb_serial *);
static void cp210x_release(struct usb_serial *);
@@ -1434,18 +1434,26 @@ static int cp210x_tiocmget(struct tty_struct *tty)
return result;
}
-static void cp210x_break_ctl(struct tty_struct *tty, int break_state)
+static int cp210x_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
+ struct cp210x_serial_private *priv = usb_get_serial_data(port->serial);
u16 state;
+ if (priv->partnum == CP210X_PARTNUM_CP2105) {
+ if (cp210x_interface_num(port->serial) == 1)
+ return -ENOTTY;
+ }
+
if (break_state == 0)
state = BREAK_OFF;
else
state = BREAK_ON;
+
dev_dbg(&port->dev, "%s - turning break %s\n", __func__,
state == BREAK_OFF ? "off" : "on");
- cp210x_write_u16_reg(port, CP210X_SET_BREAK, state);
+
+ return cp210x_write_u16_reg(port, CP210X_SET_BREAK, state);
}
#ifdef CONFIG_GPIOLIB
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 45d688e9b93f..d1dea3850576 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -217,7 +217,7 @@ static void digi_rx_unthrottle(struct tty_struct *tty);
static void digi_set_termios(struct tty_struct *tty,
struct usb_serial_port *port,
const struct ktermios *old_termios);
-static void digi_break_ctl(struct tty_struct *tty, int break_state);
+static int digi_break_ctl(struct tty_struct *tty, int break_state);
static int digi_tiocmget(struct tty_struct *tty);
static int digi_tiocmset(struct tty_struct *tty, unsigned int set,
unsigned int clear);
@@ -839,7 +839,7 @@ static void digi_set_termios(struct tty_struct *tty,
}
-static void digi_break_ctl(struct tty_struct *tty, int break_state)
+static int digi_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
unsigned char buf[4];
@@ -848,7 +848,8 @@ static void digi_break_ctl(struct tty_struct *tty, int break_state)
buf[1] = 2; /* length */
buf[2] = break_state ? 1 : 0;
buf[3] = 0; /* pad */
- digi_write_inb_command(port, buf, 4, 0);
+
+ return digi_write_inb_command(port, buf, 4, 0);
}
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index 891fb1fe69df..5f7a46bcace6 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -448,7 +448,7 @@ static void f81534a_process_read_urb(struct urb *urb)
tty_flip_buffer_push(&port->port);
}
-static void f81232_break_ctl(struct tty_struct *tty, int break_state)
+static int f81232_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct f81232_private *priv = usb_get_serial_port_data(port);
@@ -467,6 +467,8 @@ static void f81232_break_ctl(struct tty_struct *tty, int break_state)
dev_err(&port->dev, "set break failed: %d\n", status);
mutex_unlock(&priv->lock);
+
+ return status;
}
static int f81232_find_clk(speed_t baudrate)
diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index 4083ae961be4..ef126cd3d94f 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -656,7 +656,7 @@ out_unlock:
return status;
}
-static void f81534_break_ctl(struct tty_struct *tty, int break_state)
+static int f81534_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct f81534_port_private *port_priv = usb_get_serial_port_data(port);
@@ -675,6 +675,8 @@ static void f81534_break_ctl(struct tty_struct *tty, int break_state)
dev_err(&port->dev, "set break failed: %d\n", status);
mutex_unlock(&port_priv->lcr_mutex);
+
+ return status;
}
static int f81534_update_mctrl(struct usb_serial_port *port, unsigned int set,
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 05e28a5ce42b..1bf23611be12 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -2550,11 +2550,12 @@ static void ftdi_process_read_urb(struct urb *urb)
tty_flip_buffer_push(&port->port);
}
-static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
+static int ftdi_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
u16 value;
+ int ret;
/* break_state = -1 to turn on break, and 0 to turn off break */
/* see drivers/char/tty_io.c to see it used */
@@ -2565,19 +2566,22 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
else
value = priv->last_set_data_value;
- if (usb_control_msg(port->serial->dev,
+ ret = usb_control_msg(port->serial->dev,
usb_sndctrlpipe(port->serial->dev, 0),
FTDI_SIO_SET_DATA_REQUEST,
FTDI_SIO_SET_DATA_REQUEST_TYPE,
value, priv->channel,
- NULL, 0, WDR_TIMEOUT) < 0) {
+ NULL, 0, WDR_TIMEOUT);
+ if (ret < 0) {
dev_err(&port->dev, "%s FAILED to enable/disable break state (state was %d)\n",
__func__, break_state);
+ return ret;
}
dev_dbg(&port->dev, "%s break state is %d - urb is %d\n", __func__,
break_state, value);
+ return 0;
}
static bool ftdi_tx_empty(struct usb_serial_port *port)
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 3a4c0febf335..abe4bbb0ac65 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1560,12 +1560,12 @@ static int edge_ioctl(struct tty_struct *tty,
* SerialBreak
* this function sends a break to the port
*****************************************************************************/
-static void edge_break(struct tty_struct *tty, int break_state)
+static int edge_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct edgeport_serial *edge_serial = usb_get_serial_data(port->serial);
- int status;
+ int status = 0;
if (!edge_serial->is_epic ||
edge_serial->epic_descriptor.Supports.IOSPChase) {
@@ -1597,6 +1597,8 @@ static void edge_break(struct tty_struct *tty, int break_state)
dev_dbg(&port->dev, "%s - error sending break set/clear command.\n",
__func__);
}
+
+ return status;
}
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index bc3c24ea42c1..7a3a6e539456 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2421,7 +2421,7 @@ static int edge_tiocmget(struct tty_struct *tty)
return result;
}
-static void edge_break(struct tty_struct *tty, int break_state)
+static int edge_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
@@ -2430,10 +2430,15 @@ static void edge_break(struct tty_struct *tty, int break_state)
if (break_state == -1)
bv = 1; /* On */
+
status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv);
- if (status)
+ if (status) {
dev_dbg(&port->dev, "%s - error %d sending break set/clear command.\n",
__func__, status);
+ return status;
+ }
+
+ return 0;
}
static void edge_heartbeat_schedule(struct edgeport_serial *edge_serial)
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 2966e0c4941e..93b17e0e05a3 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -599,7 +599,7 @@ struct keyspan_port_private {
#include "keyspan_usa67msg.h"
-static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
+static int keyspan_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct keyspan_port_private *p_priv;
@@ -611,7 +611,10 @@ static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
else
p_priv->break_on = 0;
+ /* FIXME: return errors */
keyspan_send_setup(port, 0);
+
+ return 0;
}
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 6fd15cd9e1eb..0eef358b314a 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -299,7 +299,7 @@ static speed_t keyspan_pda_setbaud(struct usb_serial *serial, speed_t baud)
return baud;
}
-static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state)
+static int keyspan_pda_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
@@ -315,9 +315,13 @@ static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state)
4, /* set break */
USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
value, 0, NULL, 0, 2000);
- if (result < 0)
+ if (result < 0) {
dev_dbg(&port->dev, "%s - error %d from usb_control_msg\n",
__func__, result);
+ return result;
+ }
+
+ return 0;
}
static void keyspan_pda_set_termios(struct tty_struct *tty,
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index d3852feb81a4..6570c8817a80 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -47,7 +47,7 @@ static void mct_u232_read_int_callback(struct urb *urb);
static void mct_u232_set_termios(struct tty_struct *tty,
struct usb_serial_port *port,
const struct ktermios *old_termios);
-static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
+static int mct_u232_break_ctl(struct tty_struct *tty, int break_state);
static int mct_u232_tiocmget(struct tty_struct *tty);
static int mct_u232_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
@@ -677,7 +677,7 @@ static void mct_u232_set_termios(struct tty_struct *tty,
spin_unlock_irqrestore(&priv->lock, flags);
} /* mct_u232_set_termios */
-static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
+static int mct_u232_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
@@ -691,7 +691,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
lcr |= MCT_U232_SET_BREAK;
spin_unlock_irqrestore(&priv->lock, flags);
- mct_u232_set_line_ctrl(port, lcr);
+ return mct_u232_set_line_ctrl(port, lcr);
} /* mct_u232_break_ctl */
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 1d1f85fabc28..23544074eb1c 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -996,7 +996,7 @@ static void mos7720_close(struct usb_serial_port *port)
mos7720_port->open = 0;
}
-static void mos7720_break(struct tty_struct *tty, int break_state)
+static int mos7720_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
unsigned char data;
@@ -1007,7 +1007,7 @@ static void mos7720_break(struct tty_struct *tty, int break_state)
mos7720_port = usb_get_serial_port_data(port);
if (mos7720_port == NULL)
- return;
+ return -ENODEV;
if (break_state == -1)
data = mos7720_port->shadowLCR | UART_LCR_SBC;
@@ -1015,8 +1015,9 @@ static void mos7720_break(struct tty_struct *tty, int break_state)
data = mos7720_port->shadowLCR & ~UART_LCR_SBC;
mos7720_port->shadowLCR = data;
- write_mos_reg(serial, port->port_number, MOS7720_LCR,
- mos7720_port->shadowLCR);
+
+ return write_mos_reg(serial, port->port_number, MOS7720_LCR,
+ mos7720_port->shadowLCR);
}
/*
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 73370eaae0ab..8b0308d84270 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -787,7 +787,7 @@ static void mos7840_close(struct usb_serial_port *port)
* mos7840_break
* this function sends a break to the port
*****************************************************************************/
-static void mos7840_break(struct tty_struct *tty, int break_state)
+static int mos7840_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7840_port = usb_get_serial_port_data(port);
@@ -801,8 +801,9 @@ static void mos7840_break(struct tty_struct *tty, int break_state)
/* FIXME: no locking on shadowLCR anywhere in driver */
mos7840_port->shadowLCR = data;
dev_dbg(&port->dev, "%s mos7840_port->shadowLCR is %x\n", __func__, mos7840_port->shadowLCR);
- mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER,
- mos7840_port->shadowLCR);
+
+ return mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER,
+ mos7840_port->shadowLCR);
}
/*****************************************************************************
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c
index faa0eedfe245..1f7bb3e4fcf2 100644
--- a/drivers/usb/serial/mxuport.c
+++ b/drivers/usb/serial/mxuport.c
@@ -1230,7 +1230,7 @@ static void mxuport_close(struct usb_serial_port *port)
}
/* Send a break to the port. */
-static void mxuport_break_ctl(struct tty_struct *tty, int break_state)
+static int mxuport_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
@@ -1244,8 +1244,8 @@ static void mxuport_break_ctl(struct tty_struct *tty, int break_state)
dev_dbg(&port->dev, "%s - clearing break\n", __func__);
}
- mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_BREAK,
- enable, port->port_number);
+ return mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_BREAK,
+ enable, port->port_number);
}
static int mxuport_resume(struct usb_serial *serial)
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index fd42e3a0bd18..288a96a74266 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1151,6 +1151,10 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x90fa),
.driver_info = RSVD(3) },
/* u-blox products */
+ { USB_DEVICE(UBLOX_VENDOR_ID, 0x1311) }, /* u-blox LARA-R6 01B */
+ { USB_DEVICE(UBLOX_VENDOR_ID, 0x1312), /* u-blox LARA-R6 01B (RMNET) */
+ .driver_info = RSVD(4) },
+ { USB_DEVICE_INTERFACE_CLASS(UBLOX_VENDOR_ID, 0x1313, 0xff) }, /* u-blox LARA-R6 01B (ECM) */
{ USB_DEVICE(UBLOX_VENDOR_ID, 0x1341) }, /* u-blox LARA-L6 */
{ USB_DEVICE(UBLOX_VENDOR_ID, 0x1342), /* u-blox LARA-L6 (RMNET) */
.driver_info = RSVD(4) },
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 8949c1891164..d93f5d584557 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -173,7 +173,7 @@ MODULE_DEVICE_TABLE(usb, id_table);
#define PL2303_HXN_FLOWCTRL_RTS_CTS 0x18
#define PL2303_HXN_FLOWCTRL_XON_XOFF 0x0c
-static void pl2303_set_break(struct usb_serial_port *port, bool enable);
+static int pl2303_set_break(struct usb_serial_port *port, bool enable);
enum pl2303_type {
TYPE_H,
@@ -1060,7 +1060,7 @@ static int pl2303_carrier_raised(struct usb_serial_port *port)
return 0;
}
-static void pl2303_set_break(struct usb_serial_port *port, bool enable)
+static int pl2303_set_break(struct usb_serial_port *port, bool enable)
{
struct usb_serial *serial = port->serial;
u16 state;
@@ -1077,15 +1077,19 @@ static void pl2303_set_break(struct usb_serial_port *port, bool enable)
result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
0, NULL, 0, 100);
- if (result)
+ if (result) {
dev_err(&port->dev, "error sending break = %d\n", result);
+ return result;
+ }
+
+ return 0;
}
-static void pl2303_break_ctl(struct tty_struct *tty, int state)
+static int pl2303_break_ctl(struct tty_struct *tty, int state)
{
struct usb_serial_port *port = tty->driver_data;
- pl2303_set_break(port, state);
+ return pl2303_set_break(port, state);
}
static void pl2303_update_line_status(struct usb_serial_port *port,
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index fee581409bf6..821f25e52ec2 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -741,7 +741,7 @@ static int qt2_tiocmset(struct tty_struct *tty,
return update_mctrl(port_priv, set, clear);
}
-static void qt2_break_ctl(struct tty_struct *tty, int break_state)
+static int qt2_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct qt2_port_private *port_priv;
@@ -754,10 +754,14 @@ static void qt2_break_ctl(struct tty_struct *tty, int break_state)
status = qt2_control_msg(port->serial->dev, QT2_BREAK_CONTROL,
val, port_priv->device_port);
- if (status < 0)
+ if (status < 0) {
dev_warn(&port->dev,
"%s - failed to send control message: %i\n", __func__,
status);
+ return status;
+ }
+
+ return 0;
}
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index b99f78224846..0fba25abf671 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -319,7 +319,7 @@ static void ti_set_termios(struct tty_struct *tty,
static int ti_tiocmget(struct tty_struct *tty);
static int ti_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
-static void ti_break(struct tty_struct *tty, int break_state);
+static int ti_break(struct tty_struct *tty, int break_state);
static void ti_interrupt_callback(struct urb *urb);
static void ti_bulk_in_callback(struct urb *urb);
static void ti_bulk_out_callback(struct urb *urb);
@@ -1071,7 +1071,7 @@ static int ti_tiocmset(struct tty_struct *tty,
}
-static void ti_break(struct tty_struct *tty, int break_state)
+static int ti_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
@@ -1083,8 +1083,12 @@ static void ti_break(struct tty_struct *tty, int break_state)
tport->tp_uart_base_addr + TI_UART_OFFSET_LCR,
TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0);
- if (status)
+ if (status) {
dev_dbg(&port->dev, "%s - error setting break, %d\n", __func__, status);
+ return status;
+ }
+
+ return 0;
}
static int ti_get_port_from_code(unsigned char code)
diff --git a/drivers/usb/serial/upd78f0730.c b/drivers/usb/serial/upd78f0730.c
index c47439bd90fa..46952182e04f 100644
--- a/drivers/usb/serial/upd78f0730.c
+++ b/drivers/usb/serial/upd78f0730.c
@@ -238,12 +238,13 @@ static int upd78f0730_tiocmset(struct tty_struct *tty,
return res;
}
-static void upd78f0730_break_ctl(struct tty_struct *tty, int break_state)
+static int upd78f0730_break_ctl(struct tty_struct *tty, int break_state)
{
struct upd78f0730_port_private *private;
struct usb_serial_port *port = tty->driver_data;
struct upd78f0730_set_dtr_rts request;
struct device *dev = &port->dev;
+ int res;
private = usb_get_serial_port_data(port);
@@ -258,8 +259,10 @@ static void upd78f0730_break_ctl(struct tty_struct *tty, int break_state)
request.opcode = UPD78F0730_CMD_SET_DTR_RTS;
request.params = private->line_signals;
- upd78f0730_send_ctl(port, &request, sizeof(request));
+ res = upd78f0730_send_ctl(port, &request, sizeof(request));
mutex_unlock(&private->lock);
+
+ return res;
}
static void upd78f0730_dtr_rts(struct usb_serial_port *port, int on)
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index f8404073558b..7b4805c1004d 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -539,9 +539,9 @@ static int serial_break(struct tty_struct *tty, int break_state)
dev_dbg(&port->dev, "%s\n", __func__);
if (port->serial->type->break_ctl)
- port->serial->type->break_ctl(tty, break_state);
+ return port->serial->type->break_ctl(tty, break_state);
- return 0;
+ return -ENOTTY;
}
static int serial_proc_show(struct seq_file *m, void *v)
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
index aaf4813e4971..6934970f180d 100644
--- a/drivers/usb/serial/usb_debug.c
+++ b/drivers/usb/serial/usb_debug.c
@@ -47,12 +47,19 @@ MODULE_DEVICE_TABLE(usb, id_table_combined);
/* This HW really does not support a serial break, so one will be
* emulated when ever the break state is set to true.
*/
-static void usb_debug_break_ctl(struct tty_struct *tty, int break_state)
+static int usb_debug_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
+ int ret;
+
if (!break_state)
- return;
- usb_serial_generic_write(tty, port, USB_DEBUG_BRK, USB_DEBUG_BRK_SIZE);
+ return 0;
+
+ ret = usb_serial_generic_write(tty, port, USB_DEBUG_BRK, USB_DEBUG_BRK_SIZE);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
static void usb_debug_process_read_urb(struct urb *urb)
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 7f82d40753ee..ca48e90a8e81 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -87,7 +87,7 @@ static void whiteheat_set_termios(struct tty_struct *tty,
static int whiteheat_tiocmget(struct tty_struct *tty);
static int whiteheat_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
-static void whiteheat_break_ctl(struct tty_struct *tty, int break_state);
+static int whiteheat_break_ctl(struct tty_struct *tty, int break_state);
static struct usb_serial_driver whiteheat_fake_device = {
.driver = {
@@ -449,10 +449,11 @@ static void whiteheat_set_termios(struct tty_struct *tty,
firm_setup_port(tty);
}
-static void whiteheat_break_ctl(struct tty_struct *tty, int break_state)
+static int whiteheat_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
- firm_set_break(port, break_state);
+
+ return firm_set_break(port, break_state);
}
diff --git a/drivers/usb/serial/xr_serial.c b/drivers/usb/serial/xr_serial.c
index fdb0aae546c3..4ec7c5892b84 100644
--- a/drivers/usb/serial/xr_serial.c
+++ b/drivers/usb/serial/xr_serial.c
@@ -503,7 +503,7 @@ static void xr_dtr_rts(struct usb_serial_port *port, int on)
xr_tiocmset_port(port, 0, TIOCM_DTR | TIOCM_RTS);
}
-static void xr_break_ctl(struct tty_struct *tty, int break_state)
+static int xr_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
struct xr_data *data = usb_get_serial_port_data(port);
@@ -517,7 +517,7 @@ static void xr_break_ctl(struct tty_struct *tty, int break_state)
dev_dbg(&port->dev, "Turning break %s\n", state == 0 ? "off" : "on");
- xr_set_reg_uart(port, type->tx_break, state);
+ return xr_set_reg_uart(port, type->tx_break, state);
}
/* Tx and Rx clock mask values obtained from section 3.3.4 of datasheet */
diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
index 831e7049977d..2f80c2792dbd 100644
--- a/drivers/usb/typec/Kconfig
+++ b/drivers/usb/typec/Kconfig
@@ -100,19 +100,6 @@ config TYPEC_STUSB160X
If you choose to build this driver as a dynamically linked module, the
module will be called stusb160x.ko.
-config TYPEC_QCOM_PMIC
- tristate "Qualcomm PMIC USB Type-C driver"
- depends on ARCH_QCOM || COMPILE_TEST
- depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
- help
- Driver for supporting role switch over the Qualcomm PMIC. This will
- handle the USB Type-C role and orientation detection reported by the
- QCOM PMIC if the PMIC has the capability to handle USB Type-C
- detection.
-
- It will also enable the VBUS output to connected devices when a
- DFP connection is made.
-
config TYPEC_WUSB3801
tristate "Willsemi WUSB3801 Type-C port controller driver"
depends on I2C
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index 4a83dad51a6c..7a368fea61bc 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_TYPEC_UCSI) += ucsi/
obj-$(CONFIG_TYPEC_TPS6598X) += tipd/
obj-$(CONFIG_TYPEC_ANX7411) += anx7411.o
obj-$(CONFIG_TYPEC_HD3SS3220) += hd3ss3220.o
-obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom-pmic-typec.o
obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o
obj-$(CONFIG_TYPEC_RT1719) += rt1719.o
obj-$(CONFIG_TYPEC_WUSB3801) += wusb3801.o
diff --git a/drivers/usb/typec/anx7411.c b/drivers/usb/typec/anx7411.c
index 3d5edce270a4..221604f933a4 100644
--- a/drivers/usb/typec/anx7411.c
+++ b/drivers/usb/typec/anx7411.c
@@ -1584,7 +1584,7 @@ static struct i2c_driver anx7411_driver = {
.of_match_table = anx_match_table,
.pm = &anx7411_pm_ops,
},
- .probe_new = anx7411_i2c_probe,
+ .probe = anx7411_i2c_probe,
.remove = anx7411_i2c_remove,
.id_table = anx7411_id,
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index 349cc2030c90..faa184ae3dac 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -2110,7 +2110,7 @@ typec_port_register_altmode(struct typec_port *port,
struct typec_mux *mux;
struct typec_retimer *retimer;
- mux = typec_mux_get(&port->dev, desc);
+ mux = typec_mux_get(&port->dev);
if (IS_ERR(mux))
return ERR_CAST(mux);
@@ -2274,7 +2274,7 @@ struct typec_port *typec_register_port(struct device *parent,
return ERR_PTR(ret);
}
- port->mux = typec_mux_get(&port->dev, NULL);
+ port->mux = typec_mux_get(&port->dev);
if (IS_ERR(port->mux)) {
ret = PTR_ERR(port->mux);
put_device(&port->dev);
diff --git a/drivers/usb/typec/hd3ss3220.c b/drivers/usb/typec/hd3ss3220.c
index 8bbeb9b1e439..fb1242e82ffd 100644
--- a/drivers/usb/typec/hd3ss3220.c
+++ b/drivers/usb/typec/hd3ss3220.c
@@ -292,8 +292,8 @@ static struct i2c_driver hd3ss3220_driver = {
.name = "hd3ss3220",
.of_match_table = dev_ids,
},
- .probe_new = hd3ss3220_probe,
- .remove = hd3ss3220_remove,
+ .probe = hd3ss3220_probe,
+ .remove = hd3ss3220_remove,
};
module_i2c_driver(hd3ss3220_driver);
diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
index d9eaf9a0b0bf..80dd91938d96 100644
--- a/drivers/usb/typec/mux.c
+++ b/drivers/usb/typec/mux.c
@@ -265,60 +265,19 @@ static int mux_fwnode_match(struct device *dev, const void *fwnode)
static void *typec_mux_match(const struct fwnode_handle *fwnode,
const char *id, void *data)
{
- const struct typec_altmode_desc *desc = data;
struct device *dev;
- bool match;
- int nval;
- u16 *val;
- int ret;
- int i;
/*
- * Check has the identifier already been "consumed". If it
- * has, no need to do any extra connection identification.
+ * Device graph (OF graph) does not give any means to identify the
+ * device type or the device class of the remote port parent that @fwnode
+ * represents, so in order to identify the type or the class of @fwnode
+ * an additional device property is needed. With typec muxes the
+ * property is named "mode-switch" (@id). The value of the device
+ * property is ignored.
*/
- match = !id;
- if (match)
- goto find_mux;
-
- if (!desc) {
- /*
- * Accessory Mode muxes & muxes which explicitly specify
- * the required identifier can avoid SVID matching.
- */
- match = fwnode_property_present(fwnode, "accessory") ||
- fwnode_property_present(fwnode, id);
- if (match)
- goto find_mux;
- return NULL;
- }
-
- /* Alternate Mode muxes */
- nval = fwnode_property_count_u16(fwnode, "svid");
- if (nval <= 0)
+ if (id && !fwnode_property_present(fwnode, id))
return NULL;
- val = kcalloc(nval, sizeof(*val), GFP_KERNEL);
- if (!val)
- return ERR_PTR(-ENOMEM);
-
- ret = fwnode_property_read_u16_array(fwnode, "svid", val, nval);
- if (ret < 0) {
- kfree(val);
- return ERR_PTR(ret);
- }
-
- for (i = 0; i < nval; i++) {
- match = val[i] == desc->svid;
- if (match) {
- kfree(val);
- goto find_mux;
- }
- }
- kfree(val);
- return NULL;
-
-find_mux:
dev = class_find_device(&typec_mux_class, NULL, fwnode,
mux_fwnode_match);
@@ -328,15 +287,13 @@ find_mux:
/**
* fwnode_typec_mux_get - Find USB Type-C Multiplexer
* @fwnode: The caller device node
- * @desc: Alt Mode description
*
* Finds a mux linked to the caller. This function is primarily meant for the
* Type-C drivers. Returns a reference to the mux on success, NULL if no
* matching connection was found, or ERR_PTR(-EPROBE_DEFER) when a connection
* was found but the mux has not been enumerated yet.
*/
-struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode,
- const struct typec_altmode_desc *desc)
+struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode)
{
struct typec_mux_dev *mux_devs[TYPEC_MUX_MAX_DEVS];
struct typec_mux *mux;
@@ -349,7 +306,7 @@ struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode,
return ERR_PTR(-ENOMEM);
count = fwnode_connection_find_matches(fwnode, "mode-switch",
- (void *)desc, typec_mux_match,
+ NULL, typec_mux_match,
(void **)mux_devs,
ARRAY_SIZE(mux_devs));
if (count <= 0) {
diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig
index c46fa4f9d3df..784b9d8107e9 100644
--- a/drivers/usb/typec/mux/Kconfig
+++ b/drivers/usb/typec/mux/Kconfig
@@ -35,4 +35,14 @@ config TYPEC_MUX_INTEL_PMC
control the USB role switch and also the multiplexer/demultiplexer
switches used with USB Type-C Alternate Modes.
+config TYPEC_MUX_NB7VPQ904M
+ tristate "On Semiconductor NB7VPQ904M Type-C redriver driver"
+ depends on I2C
+ depends on DRM || DRM=n
+ select DRM_PANEL_BRIDGE if DRM
+ select REGMAP_I2C
+ help
+ Say Y or M if your system has a On Semiconductor NB7VPQ904M Type-C
+ redriver chip found on some devices with a Type-C port.
+
endmenu
diff --git a/drivers/usb/typec/mux/Makefile b/drivers/usb/typec/mux/Makefile
index dda67e19b58b..76196096ef41 100644
--- a/drivers/usb/typec/mux/Makefile
+++ b/drivers/usb/typec/mux/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_TYPEC_MUX_FSA4480) += fsa4480.o
obj-$(CONFIG_TYPEC_MUX_GPIO_SBU) += gpio-sbu-mux.o
obj-$(CONFIG_TYPEC_MUX_PI3USB30532) += pi3usb30532.o
obj-$(CONFIG_TYPEC_MUX_INTEL_PMC) += intel_pmc_mux.o
+obj-$(CONFIG_TYPEC_MUX_NB7VPQ904M) += nb7vpq904m.o
diff --git a/drivers/usb/typec/mux/fsa4480.c b/drivers/usb/typec/mux/fsa4480.c
index d6495e533e58..e0ee1f621abb 100644
--- a/drivers/usb/typec/mux/fsa4480.c
+++ b/drivers/usb/typec/mux/fsa4480.c
@@ -25,15 +25,24 @@
#define FSA4480_DELAY_L_MIC 0x0e
#define FSA4480_DELAY_L_SENSE 0x0f
#define FSA4480_DELAY_L_AGND 0x10
+#define FSA4480_FUNCTION_ENABLE 0x12
#define FSA4480_RESET 0x1e
#define FSA4480_MAX_REGISTER 0x1f
#define FSA4480_ENABLE_DEVICE BIT(7)
#define FSA4480_ENABLE_SBU GENMASK(6, 5)
#define FSA4480_ENABLE_USB GENMASK(4, 3)
+#define FSA4480_ENABLE_SENSE BIT(2)
+#define FSA4480_ENABLE_MIC BIT(1)
+#define FSA4480_ENABLE_AGND BIT(0)
#define FSA4480_SEL_SBU_REVERSE GENMASK(6, 5)
#define FSA4480_SEL_USB GENMASK(4, 3)
+#define FSA4480_SEL_SENSE BIT(2)
+#define FSA4480_SEL_MIC BIT(1)
+#define FSA4480_SEL_AGND BIT(0)
+
+#define FSA4480_ENABLE_AUTO_JACK_DETECT BIT(0)
struct fsa4480 {
struct i2c_client *client;
@@ -46,8 +55,11 @@ struct fsa4480 {
struct regmap *regmap;
+ enum typec_orientation orientation;
+ unsigned long mode;
+ unsigned int svid;
+
u8 cur_enable;
- u8 cur_select;
};
static const struct regmap_config fsa4480_regmap_config = {
@@ -58,19 +70,45 @@ static const struct regmap_config fsa4480_regmap_config = {
.disable_locking = true,
};
-static int fsa4480_switch_set(struct typec_switch_dev *sw,
- enum typec_orientation orientation)
+static int fsa4480_set(struct fsa4480 *fsa)
{
- struct fsa4480 *fsa = typec_switch_get_drvdata(sw);
- u8 new_sel;
-
- mutex_lock(&fsa->lock);
- new_sel = FSA4480_SEL_USB;
- if (orientation == TYPEC_ORIENTATION_REVERSE)
- new_sel |= FSA4480_SEL_SBU_REVERSE;
-
- if (new_sel == fsa->cur_select)
- goto out_unlock;
+ bool reverse = (fsa->orientation == TYPEC_ORIENTATION_REVERSE);
+ u8 enable = FSA4480_ENABLE_DEVICE;
+ u8 sel = 0;
+
+ /* USB Mode */
+ if (fsa->mode < TYPEC_STATE_MODAL ||
+ (!fsa->svid && (fsa->mode == TYPEC_MODE_USB2 ||
+ fsa->mode == TYPEC_MODE_USB3))) {
+ enable |= FSA4480_ENABLE_USB;
+ sel = FSA4480_SEL_USB;
+ } else if (fsa->svid) {
+ switch (fsa->mode) {
+ /* DP Only */
+ case TYPEC_DP_STATE_C:
+ case TYPEC_DP_STATE_E:
+ enable |= FSA4480_ENABLE_SBU;
+ if (reverse)
+ sel = FSA4480_SEL_SBU_REVERSE;
+ break;
+
+ /* DP + USB */
+ case TYPEC_DP_STATE_D:
+ case TYPEC_DP_STATE_F:
+ enable |= FSA4480_ENABLE_USB | FSA4480_ENABLE_SBU;
+ sel = FSA4480_SEL_USB;
+ if (reverse)
+ sel |= FSA4480_SEL_SBU_REVERSE;
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+ } else if (fsa->mode == TYPEC_MODE_AUDIO) {
+ /* Audio Accessory Mode, setup to auto Jack Detection */
+ enable |= FSA4480_ENABLE_USB | FSA4480_ENABLE_AGND;
+ } else
+ return -EOPNOTSUPP;
if (fsa->cur_enable & FSA4480_ENABLE_SBU) {
/* Disable SBU output while re-configuring the switch */
@@ -81,48 +119,64 @@ static int fsa4480_switch_set(struct typec_switch_dev *sw,
usleep_range(35, 1000);
}
- regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, new_sel);
- fsa->cur_select = new_sel;
+ regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, sel);
+ regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, enable);
- if (fsa->cur_enable & FSA4480_ENABLE_SBU) {
- regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, fsa->cur_enable);
+ /* Start AUDIO JACK DETECTION to setup MIC, AGND & Sense muxes */
+ if (enable & FSA4480_ENABLE_AGND)
+ regmap_write(fsa->regmap, FSA4480_FUNCTION_ENABLE,
+ FSA4480_ENABLE_AUTO_JACK_DETECT);
+ if (enable & FSA4480_ENABLE_SBU) {
/* 15us to allow the SBU switch to turn on again */
usleep_range(15, 1000);
}
-out_unlock:
- mutex_unlock(&fsa->lock);
+ fsa->cur_enable = enable;
return 0;
}
+static int fsa4480_switch_set(struct typec_switch_dev *sw,
+ enum typec_orientation orientation)
+{
+ struct fsa4480 *fsa = typec_switch_get_drvdata(sw);
+ int ret = 0;
+
+ mutex_lock(&fsa->lock);
+
+ if (fsa->orientation != orientation) {
+ fsa->orientation = orientation;
+
+ ret = fsa4480_set(fsa);
+ }
+
+ mutex_unlock(&fsa->lock);
+
+ return ret;
+}
+
static int fsa4480_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state)
{
struct fsa4480 *fsa = typec_mux_get_drvdata(mux);
- u8 new_enable;
+ int ret = 0;
mutex_lock(&fsa->lock);
- new_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB;
- if (state->mode >= TYPEC_DP_STATE_A)
- new_enable |= FSA4480_ENABLE_SBU;
+ if (fsa->mode != state->mode) {
+ fsa->mode = state->mode;
- if (new_enable == fsa->cur_enable)
- goto out_unlock;
+ if (state->alt)
+ fsa->svid = state->alt->svid;
+ else
+ fsa->svid = 0; // No SVID
- regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, new_enable);
- fsa->cur_enable = new_enable;
-
- if (new_enable & FSA4480_ENABLE_SBU) {
- /* 15us to allow the SBU switch to turn off */
- usleep_range(15, 1000);
+ ret = fsa4480_set(fsa);
}
-out_unlock:
mutex_unlock(&fsa->lock);
- return 0;
+ return ret;
}
static int fsa4480_probe(struct i2c_client *client)
@@ -143,8 +197,10 @@ static int fsa4480_probe(struct i2c_client *client)
if (IS_ERR(fsa->regmap))
return dev_err_probe(dev, PTR_ERR(fsa->regmap), "failed to initialize regmap\n");
+ /* Safe mode */
fsa->cur_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB;
- fsa->cur_select = FSA4480_SEL_USB;
+ fsa->mode = TYPEC_STATE_SAFE;
+ fsa->orientation = TYPEC_ORIENTATION_NONE;
/* set default settings */
regmap_write(fsa->regmap, FSA4480_SLOW_L, 0x00);
@@ -156,7 +212,7 @@ static int fsa4480_probe(struct i2c_client *client)
regmap_write(fsa->regmap, FSA4480_DELAY_L_MIC, 0x00);
regmap_write(fsa->regmap, FSA4480_DELAY_L_SENSE, 0x00);
regmap_write(fsa->regmap, FSA4480_DELAY_L_AGND, 0x09);
- regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, fsa->cur_select);
+ regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, FSA4480_SEL_USB);
regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, fsa->cur_enable);
sw_desc.drvdata = fsa;
@@ -206,7 +262,7 @@ static struct i2c_driver fsa4480_driver = {
.name = "fsa4480",
.of_match_table = fsa4480_of_table,
},
- .probe_new = fsa4480_probe,
+ .probe = fsa4480_probe,
.remove = fsa4480_remove,
.id_table = fsa4480_table,
};
diff --git a/drivers/usb/typec/mux/gpio-sbu-mux.c b/drivers/usb/typec/mux/gpio-sbu-mux.c
index f62516dafe8f..ad60fd4e8431 100644
--- a/drivers/usb/typec/mux/gpio-sbu-mux.c
+++ b/drivers/usb/typec/mux/gpio-sbu-mux.c
@@ -3,14 +3,11 @@
* Copyright (C) 2022 Linaro Ltd.
*/
-#include <linux/bits.h>
-#include <linux/i2c.h>
-#include <linux/kernel.h>
+#include <linux/device.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
-#include <linux/regmap.h>
#include <linux/usb/typec_dp.h>
#include <linux/usb/typec_mux.h>
@@ -140,7 +137,7 @@ static int gpio_sbu_mux_probe(struct platform_device *pdev)
return 0;
}
-static int gpio_sbu_mux_remove(struct platform_device *pdev)
+static void gpio_sbu_mux_remove(struct platform_device *pdev)
{
struct gpio_sbu_mux *sbu_mux = platform_get_drvdata(pdev);
@@ -148,8 +145,6 @@ static int gpio_sbu_mux_remove(struct platform_device *pdev)
typec_mux_unregister(sbu_mux->mux);
typec_switch_unregister(sbu_mux->sw);
-
- return 0;
}
static const struct of_device_id gpio_sbu_mux_match[] = {
@@ -160,7 +155,7 @@ MODULE_DEVICE_TABLE(of, gpio_sbu_mux_match);
static struct platform_driver gpio_sbu_mux_driver = {
.probe = gpio_sbu_mux_probe,
- .remove = gpio_sbu_mux_remove,
+ .remove_new = gpio_sbu_mux_remove,
.driver = {
.name = "gpio_sbu_mux",
.of_match_table = gpio_sbu_mux_match,
diff --git a/drivers/usb/typec/mux/intel_pmc_mux.c b/drivers/usb/typec/mux/intel_pmc_mux.c
index 34e4188a40ff..5e8edf3881c0 100644
--- a/drivers/usb/typec/mux/intel_pmc_mux.c
+++ b/drivers/usb/typec/mux/intel_pmc_mux.c
@@ -15,6 +15,8 @@
#include <linux/usb/typec_mux.h>
#include <linux/usb/typec_dp.h>
#include <linux/usb/typec_tbt.h>
+#include <linux/debugfs.h>
+#include <linux/usb.h>
#include <asm/intel_scu_ipc.h>
@@ -143,8 +145,12 @@ struct pmc_usb {
struct acpi_device *iom_adev;
void __iomem *iom_base;
u32 iom_port_status_offset;
+
+ struct dentry *dentry;
};
+static struct dentry *pmc_mux_debugfs_root;
+
static void update_port_status(struct pmc_usb_port *port)
{
u8 port_num;
@@ -639,6 +645,29 @@ static int pmc_usb_probe_iom(struct pmc_usb *pmc)
return 0;
}
+static int port_iom_status_show(struct seq_file *s, void *unused)
+{
+ struct pmc_usb_port *port = s->private;
+
+ update_port_status(port);
+ seq_printf(s, "0x%08x\n", port->iom_status);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(port_iom_status);
+
+static void pmc_mux_port_debugfs_init(struct pmc_usb_port *port)
+{
+ struct dentry *debugfs_dir;
+ char name[6];
+
+ snprintf(name, sizeof(name), "port%d", port->usb3_port - 1);
+
+ debugfs_dir = debugfs_create_dir(name, port->pmc->dentry);
+ debugfs_create_file("iom_status", 0400, debugfs_dir, port,
+ &port_iom_status_fops);
+}
+
static int pmc_usb_probe(struct platform_device *pdev)
{
struct fwnode_handle *fwnode = NULL;
@@ -674,6 +703,8 @@ static int pmc_usb_probe(struct platform_device *pdev)
if (ret)
return ret;
+ pmc->dentry = debugfs_create_dir(dev_name(pmc->dev), pmc_mux_debugfs_root);
+
/*
* For every physical USB connector (USB2 and USB3 combo) there is a
* child ACPI device node under the PMC mux ACPI device object.
@@ -688,6 +719,8 @@ static int pmc_usb_probe(struct platform_device *pdev)
fwnode_handle_put(fwnode);
goto err_remove_ports;
}
+
+ pmc_mux_port_debugfs_init(&pmc->port[i]);
}
platform_set_drvdata(pdev, pmc);
@@ -703,10 +736,12 @@ err_remove_ports:
acpi_dev_put(pmc->iom_adev);
+ debugfs_remove(pmc->dentry);
+
return ret;
}
-static int pmc_usb_remove(struct platform_device *pdev)
+static void pmc_usb_remove(struct platform_device *pdev)
{
struct pmc_usb *pmc = platform_get_drvdata(pdev);
int i;
@@ -719,7 +754,7 @@ static int pmc_usb_remove(struct platform_device *pdev)
acpi_dev_put(pmc->iom_adev);
- return 0;
+ debugfs_remove(pmc->dentry);
}
static const struct acpi_device_id pmc_usb_acpi_ids[] = {
@@ -734,10 +769,23 @@ static struct platform_driver pmc_usb_driver = {
.acpi_match_table = ACPI_PTR(pmc_usb_acpi_ids),
},
.probe = pmc_usb_probe,
- .remove = pmc_usb_remove,
+ .remove_new = pmc_usb_remove,
};
-module_platform_driver(pmc_usb_driver);
+static int __init pmc_usb_init(void)
+{
+ pmc_mux_debugfs_root = debugfs_create_dir("intel_pmc_mux", usb_debug_root);
+
+ return platform_driver_register(&pmc_usb_driver);
+}
+module_init(pmc_usb_init);
+
+static void __exit pmc_usb_exit(void)
+{
+ platform_driver_unregister(&pmc_usb_driver);
+ debugfs_remove(pmc_mux_debugfs_root);
+}
+module_exit(pmc_usb_exit);
MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/typec/mux/nb7vpq904m.c b/drivers/usb/typec/mux/nb7vpq904m.c
new file mode 100644
index 000000000000..80e580d50129
--- /dev/null
+++ b/drivers/usb/typec/mux/nb7vpq904m.c
@@ -0,0 +1,529 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * OnSemi NB7VPQ904M Type-C driver
+ *
+ * Copyright (C) 2023 Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+ */
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/bitfield.h>
+#include <linux/of_graph.h>
+#include <drm/drm_bridge.h>
+#include <linux/usb/typec_dp.h>
+#include <linux/usb/typec_mux.h>
+#include <linux/usb/typec_retimer.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+
+#define NB7_CHNA 0
+#define NB7_CHNB 1
+#define NB7_CHNC 2
+#define NB7_CHND 3
+#define NB7_IS_CHAN_AD(channel) (channel == NB7_CHNA || channel == NB7_CHND)
+
+#define GEN_DEV_SET_REG 0x00
+
+#define GEN_DEV_SET_CHIP_EN BIT(0)
+#define GEN_DEV_SET_CHNA_EN BIT(4)
+#define GEN_DEV_SET_CHNB_EN BIT(5)
+#define GEN_DEV_SET_CHNC_EN BIT(6)
+#define GEN_DEV_SET_CHND_EN BIT(7)
+
+#define GEN_DEV_SET_OP_MODE_MASK GENMASK(3, 1)
+
+#define GEN_DEV_SET_OP_MODE_DP_CC2 0
+#define GEN_DEV_SET_OP_MODE_DP_CC1 1
+#define GEN_DEV_SET_OP_MODE_DP_4LANE 2
+#define GEN_DEV_SET_OP_MODE_USB 5
+
+#define EQ_SETTING_REG_BASE 0x01
+#define EQ_SETTING_REG(n) (EQ_SETTING_REG_BASE + (n) * 2)
+#define EQ_SETTING_MASK GENMASK(3, 1)
+
+#define OUTPUT_COMPRESSION_AND_POL_REG_BASE 0x02
+#define OUTPUT_COMPRESSION_AND_POL_REG(n) (OUTPUT_COMPRESSION_AND_POL_REG_BASE + (n) * 2)
+#define OUTPUT_COMPRESSION_MASK GENMASK(2, 1)
+
+#define FLAT_GAIN_REG_BASE 0x18
+#define FLAT_GAIN_REG(n) (FLAT_GAIN_REG_BASE + (n) * 2)
+#define FLAT_GAIN_MASK GENMASK(1, 0)
+
+#define LOSS_MATCH_REG_BASE 0x19
+#define LOSS_MATCH_REG(n) (LOSS_MATCH_REG_BASE + (n) * 2)
+#define LOSS_MATCH_MASK GENMASK(1, 0)
+
+#define AUX_CC_REG 0x09
+
+#define CHIP_VERSION_REG 0x17
+
+struct nb7vpq904m {
+ struct i2c_client *client;
+ struct gpio_desc *enable_gpio;
+ struct regulator *vcc_supply;
+ struct regmap *regmap;
+ struct typec_switch_dev *sw;
+ struct typec_retimer *retimer;
+
+ bool swap_data_lanes;
+ struct typec_switch *typec_switch;
+
+ struct drm_bridge bridge;
+
+ struct mutex lock; /* protect non-concurrent retimer & switch */
+
+ enum typec_orientation orientation;
+ unsigned long mode;
+ unsigned int svid;
+};
+
+static void nb7vpq904m_set_channel(struct nb7vpq904m *nb7, unsigned int channel, bool dp)
+{
+ u8 eq, out_comp, flat_gain, loss_match;
+
+ if (dp) {
+ eq = NB7_IS_CHAN_AD(channel) ? 0x6 : 0x4;
+ out_comp = 0x3;
+ flat_gain = NB7_IS_CHAN_AD(channel) ? 0x2 : 0x1;
+ loss_match = 0x3;
+ } else {
+ eq = 0x4;
+ out_comp = 0x3;
+ flat_gain = NB7_IS_CHAN_AD(channel) ? 0x3 : 0x1;
+ loss_match = NB7_IS_CHAN_AD(channel) ? 0x1 : 0x3;
+ }
+
+ regmap_update_bits(nb7->regmap, EQ_SETTING_REG(channel),
+ EQ_SETTING_MASK, FIELD_PREP(EQ_SETTING_MASK, eq));
+ regmap_update_bits(nb7->regmap, OUTPUT_COMPRESSION_AND_POL_REG(channel),
+ OUTPUT_COMPRESSION_MASK, FIELD_PREP(OUTPUT_COMPRESSION_MASK, out_comp));
+ regmap_update_bits(nb7->regmap, FLAT_GAIN_REG(channel),
+ FLAT_GAIN_MASK, FIELD_PREP(FLAT_GAIN_MASK, flat_gain));
+ regmap_update_bits(nb7->regmap, LOSS_MATCH_REG(channel),
+ LOSS_MATCH_MASK, FIELD_PREP(LOSS_MATCH_MASK, loss_match));
+}
+
+static int nb7vpq904m_set(struct nb7vpq904m *nb7)
+{
+ bool reverse = (nb7->orientation == TYPEC_ORIENTATION_REVERSE);
+
+ switch (nb7->mode) {
+ case TYPEC_STATE_SAFE:
+ regmap_write(nb7->regmap, GEN_DEV_SET_REG,
+ GEN_DEV_SET_CHIP_EN |
+ GEN_DEV_SET_CHNA_EN |
+ GEN_DEV_SET_CHNB_EN |
+ GEN_DEV_SET_CHNC_EN |
+ GEN_DEV_SET_CHND_EN |
+ FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK,
+ GEN_DEV_SET_OP_MODE_USB));
+ nb7vpq904m_set_channel(nb7, NB7_CHNA, false);
+ nb7vpq904m_set_channel(nb7, NB7_CHNB, false);
+ nb7vpq904m_set_channel(nb7, NB7_CHNC, false);
+ nb7vpq904m_set_channel(nb7, NB7_CHND, false);
+ regmap_write(nb7->regmap, AUX_CC_REG, 0x2);
+
+ return 0;
+
+ case TYPEC_STATE_USB:
+ /*
+ * Normal Orientation (CC1)
+ * A -> USB RX
+ * B -> USB TX
+ * C -> X
+ * D -> X
+ * Flipped Orientation (CC2)
+ * A -> X
+ * B -> X
+ * C -> USB TX
+ * D -> USB RX
+ *
+ * Reversed if data lanes are swapped
+ */
+ if (reverse ^ nb7->swap_data_lanes) {
+ regmap_write(nb7->regmap, GEN_DEV_SET_REG,
+ GEN_DEV_SET_CHIP_EN |
+ GEN_DEV_SET_CHNA_EN |
+ GEN_DEV_SET_CHNB_EN |
+ FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK,
+ GEN_DEV_SET_OP_MODE_USB));
+ nb7vpq904m_set_channel(nb7, NB7_CHNA, false);
+ nb7vpq904m_set_channel(nb7, NB7_CHNB, false);
+ } else {
+ regmap_write(nb7->regmap, GEN_DEV_SET_REG,
+ GEN_DEV_SET_CHIP_EN |
+ GEN_DEV_SET_CHNC_EN |
+ GEN_DEV_SET_CHND_EN |
+ FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK,
+ GEN_DEV_SET_OP_MODE_USB));
+ nb7vpq904m_set_channel(nb7, NB7_CHNC, false);
+ nb7vpq904m_set_channel(nb7, NB7_CHND, false);
+ }
+ regmap_write(nb7->regmap, AUX_CC_REG, 0x2);
+
+ return 0;
+
+ default:
+ if (nb7->svid != USB_TYPEC_DP_SID)
+ return -EINVAL;
+
+ break;
+ }
+
+ /* DP Altmode Setup */
+
+ regmap_write(nb7->regmap, AUX_CC_REG, reverse ? 0x1 : 0x0);
+
+ switch (nb7->mode) {
+ case TYPEC_DP_STATE_C:
+ case TYPEC_DP_STATE_E:
+ /*
+ * Normal Orientation (CC1)
+ * A -> DP3
+ * B -> DP2
+ * C -> DP1
+ * D -> DP0
+ * Flipped Orientation (CC2)
+ * A -> DP0
+ * B -> DP1
+ * C -> DP2
+ * D -> DP3
+ */
+ regmap_write(nb7->regmap, GEN_DEV_SET_REG,
+ GEN_DEV_SET_CHIP_EN |
+ GEN_DEV_SET_CHNA_EN |
+ GEN_DEV_SET_CHNB_EN |
+ GEN_DEV_SET_CHNC_EN |
+ GEN_DEV_SET_CHND_EN |
+ FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK,
+ GEN_DEV_SET_OP_MODE_DP_4LANE));
+ nb7vpq904m_set_channel(nb7, NB7_CHNA, true);
+ nb7vpq904m_set_channel(nb7, NB7_CHNB, true);
+ nb7vpq904m_set_channel(nb7, NB7_CHNC, true);
+ nb7vpq904m_set_channel(nb7, NB7_CHND, true);
+ break;
+
+ case TYPEC_DP_STATE_D:
+ case TYPEC_DP_STATE_F:
+ regmap_write(nb7->regmap, GEN_DEV_SET_REG,
+ GEN_DEV_SET_CHIP_EN |
+ GEN_DEV_SET_CHNA_EN |
+ GEN_DEV_SET_CHNB_EN |
+ GEN_DEV_SET_CHNC_EN |
+ GEN_DEV_SET_CHND_EN |
+ FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK,
+ reverse ^ nb7->swap_data_lanes ?
+ GEN_DEV_SET_OP_MODE_DP_CC2
+ : GEN_DEV_SET_OP_MODE_DP_CC1));
+
+ /*
+ * Normal Orientation (CC1)
+ * A -> USB RX
+ * B -> USB TX
+ * C -> DP1
+ * D -> DP0
+ * Flipped Orientation (CC2)
+ * A -> DP0
+ * B -> DP1
+ * C -> USB TX
+ * D -> USB RX
+ *
+ * Reversed if data lanes are swapped
+ */
+ if (nb7->swap_data_lanes) {
+ nb7vpq904m_set_channel(nb7, NB7_CHNA, !reverse);
+ nb7vpq904m_set_channel(nb7, NB7_CHNB, !reverse);
+ nb7vpq904m_set_channel(nb7, NB7_CHNC, reverse);
+ nb7vpq904m_set_channel(nb7, NB7_CHND, reverse);
+ } else {
+ nb7vpq904m_set_channel(nb7, NB7_CHNA, reverse);
+ nb7vpq904m_set_channel(nb7, NB7_CHNB, reverse);
+ nb7vpq904m_set_channel(nb7, NB7_CHNC, !reverse);
+ nb7vpq904m_set_channel(nb7, NB7_CHND, !reverse);
+ }
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int nb7vpq904m_sw_set(struct typec_switch_dev *sw, enum typec_orientation orientation)
+{
+ struct nb7vpq904m *nb7 = typec_switch_get_drvdata(sw);
+ int ret;
+
+ ret = typec_switch_set(nb7->typec_switch, orientation);
+ if (ret)
+ return ret;
+
+ mutex_lock(&nb7->lock);
+
+ if (nb7->orientation != orientation) {
+ nb7->orientation = orientation;
+
+ ret = nb7vpq904m_set(nb7);
+ }
+
+ mutex_unlock(&nb7->lock);
+
+ return ret;
+}
+
+static int nb7vpq904m_retimer_set(struct typec_retimer *retimer, struct typec_retimer_state *state)
+{
+ struct nb7vpq904m *nb7 = typec_retimer_get_drvdata(retimer);
+ int ret = 0;
+
+ mutex_lock(&nb7->lock);
+
+ if (nb7->mode != state->mode) {
+ nb7->mode = state->mode;
+
+ if (state->alt)
+ nb7->svid = state->alt->svid;
+ else
+ nb7->svid = 0; // No SVID
+
+ ret = nb7vpq904m_set(nb7);
+ }
+
+ mutex_unlock(&nb7->lock);
+
+ return ret;
+}
+
+#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_PANEL_BRIDGE)
+static int nb7vpq904m_bridge_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
+{
+ struct nb7vpq904m *nb7 = container_of(bridge, struct nb7vpq904m, bridge);
+ struct drm_bridge *next_bridge;
+
+ if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+ return -EINVAL;
+
+ next_bridge = devm_drm_of_get_bridge(&nb7->client->dev, nb7->client->dev.of_node, 0, 0);
+ if (IS_ERR(next_bridge)) {
+ dev_err(&nb7->client->dev, "failed to acquire drm_bridge: %pe\n", next_bridge);
+ return PTR_ERR(next_bridge);
+ }
+
+ return drm_bridge_attach(bridge->encoder, next_bridge, bridge,
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+}
+
+static const struct drm_bridge_funcs nb7vpq904m_bridge_funcs = {
+ .attach = nb7vpq904m_bridge_attach,
+};
+
+static int nb7vpq904m_register_bridge(struct nb7vpq904m *nb7)
+{
+ nb7->bridge.funcs = &nb7vpq904m_bridge_funcs;
+ nb7->bridge.of_node = nb7->client->dev.of_node;
+
+ return devm_drm_bridge_add(&nb7->client->dev, &nb7->bridge);
+}
+#else
+static int nb7vpq904m_register_bridge(struct nb7vpq904m *nb7)
+{
+ return 0;
+}
+#endif
+
+static const struct regmap_config nb7_regmap = {
+ .max_register = 0x1f,
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+enum {
+ NORMAL_LANE_MAPPING,
+ INVERT_LANE_MAPPING,
+};
+
+#define DATA_LANES_COUNT 4
+
+static const int supported_data_lane_mapping[][DATA_LANES_COUNT] = {
+ [NORMAL_LANE_MAPPING] = { 0, 1, 2, 3 },
+ [INVERT_LANE_MAPPING] = { 3, 2, 1, 0 },
+};
+
+static int nb7vpq904m_parse_data_lanes_mapping(struct nb7vpq904m *nb7)
+{
+ struct device_node *ep;
+ u32 data_lanes[4];
+ int ret, i, j;
+
+ ep = of_graph_get_endpoint_by_regs(nb7->client->dev.of_node, 1, 0);
+
+ if (ep) {
+ ret = of_property_count_u32_elems(ep, "data-lanes");
+ if (ret == -EINVAL)
+ /* Property isn't here, consider default mapping */
+ goto out_done;
+ if (ret < 0)
+ goto out_error;
+
+ if (ret != DATA_LANES_COUNT) {
+ dev_err(&nb7->client->dev, "expected 4 data lanes\n");
+ ret = -EINVAL;
+ goto out_error;
+ }
+
+ ret = of_property_read_u32_array(ep, "data-lanes", data_lanes, DATA_LANES_COUNT);
+ if (ret)
+ goto out_error;
+
+ for (i = 0; i < ARRAY_SIZE(supported_data_lane_mapping); i++) {
+ for (j = 0; j < DATA_LANES_COUNT; j++) {
+ if (data_lanes[j] != supported_data_lane_mapping[i][j])
+ break;
+ }
+
+ if (j == DATA_LANES_COUNT)
+ break;
+ }
+
+ switch (i) {
+ case NORMAL_LANE_MAPPING:
+ break;
+ case INVERT_LANE_MAPPING:
+ nb7->swap_data_lanes = true;
+ dev_info(&nb7->client->dev, "using inverted data lanes mapping\n");
+ break;
+ default:
+ dev_err(&nb7->client->dev, "invalid data lanes mapping\n");
+ ret = -EINVAL;
+ goto out_error;
+ }
+ }
+
+out_done:
+ ret = 0;
+
+out_error:
+ of_node_put(ep);
+
+ return ret;
+}
+
+static int nb7vpq904m_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct typec_switch_desc sw_desc = { };
+ struct typec_retimer_desc retimer_desc = { };
+ struct nb7vpq904m *nb7;
+ int ret;
+
+ nb7 = devm_kzalloc(dev, sizeof(*nb7), GFP_KERNEL);
+ if (!nb7)
+ return -ENOMEM;
+
+ nb7->client = client;
+
+ nb7->regmap = devm_regmap_init_i2c(client, &nb7_regmap);
+ if (IS_ERR(nb7->regmap)) {
+ dev_err(&client->dev, "Failed to allocate register map\n");
+ return PTR_ERR(nb7->regmap);
+ }
+
+ nb7->mode = TYPEC_STATE_SAFE;
+ nb7->orientation = TYPEC_ORIENTATION_NONE;
+
+ mutex_init(&nb7->lock);
+
+ nb7->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);
+ if (IS_ERR(nb7->enable_gpio))
+ return dev_err_probe(dev, PTR_ERR(nb7->enable_gpio),
+ "unable to acquire enable gpio\n");
+
+ nb7->vcc_supply = devm_regulator_get_optional(dev, "vcc");
+ if (IS_ERR(nb7->vcc_supply))
+ return PTR_ERR(nb7->vcc_supply);
+
+ nb7->typec_switch = fwnode_typec_switch_get(dev->fwnode);
+ if (IS_ERR(nb7->typec_switch))
+ return dev_err_probe(dev, PTR_ERR(nb7->typec_switch),
+ "failed to acquire orientation-switch\n");
+
+ ret = nb7vpq904m_parse_data_lanes_mapping(nb7);
+ if (ret)
+ return ret;
+
+ ret = regulator_enable(nb7->vcc_supply);
+ if (ret)
+ dev_warn(dev, "Failed to enable vcc: %d\n", ret);
+
+ gpiod_set_value(nb7->enable_gpio, 1);
+
+ ret = nb7vpq904m_register_bridge(nb7);
+ if (ret)
+ return ret;
+
+ sw_desc.drvdata = nb7;
+ sw_desc.fwnode = dev->fwnode;
+ sw_desc.set = nb7vpq904m_sw_set;
+
+ nb7->sw = typec_switch_register(dev, &sw_desc);
+ if (IS_ERR(nb7->sw))
+ return dev_err_probe(dev, PTR_ERR(nb7->sw),
+ "Error registering typec switch\n");
+
+ retimer_desc.drvdata = nb7;
+ retimer_desc.fwnode = dev->fwnode;
+ retimer_desc.set = nb7vpq904m_retimer_set;
+
+ nb7->retimer = typec_retimer_register(dev, &retimer_desc);
+ if (IS_ERR(nb7->retimer)) {
+ typec_switch_unregister(nb7->sw);
+ return dev_err_probe(dev, PTR_ERR(nb7->retimer),
+ "Error registering typec retimer\n");
+ }
+
+ return 0;
+}
+
+static void nb7vpq904m_remove(struct i2c_client *client)
+{
+ struct nb7vpq904m *nb7 = i2c_get_clientdata(client);
+
+ typec_retimer_unregister(nb7->retimer);
+ typec_switch_unregister(nb7->sw);
+
+ gpiod_set_value(nb7->enable_gpio, 0);
+
+ regulator_disable(nb7->vcc_supply);
+}
+
+static const struct i2c_device_id nb7vpq904m_table[] = {
+ { "nb7vpq904m" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, nb7vpq904m_table);
+
+static const struct of_device_id nb7vpq904m_of_table[] = {
+ { .compatible = "onnn,nb7vpq904m" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, nb7vpq904m_of_table);
+
+static struct i2c_driver nb7vpq904m_driver = {
+ .driver = {
+ .name = "nb7vpq904m",
+ .of_match_table = nb7vpq904m_of_table,
+ },
+ .probe_new = nb7vpq904m_probe,
+ .remove = nb7vpq904m_remove,
+ .id_table = nb7vpq904m_table,
+};
+
+module_i2c_driver(nb7vpq904m_driver);
+
+MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>");
+MODULE_DESCRIPTION("OnSemi NB7VPQ904M Type-C driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/typec/mux/pi3usb30532.c b/drivers/usb/typec/mux/pi3usb30532.c
index 1cd388b55c30..8eeec135dcdb 100644
--- a/drivers/usb/typec/mux/pi3usb30532.c
+++ b/drivers/usb/typec/mux/pi3usb30532.c
@@ -178,7 +178,7 @@ static struct i2c_driver pi3usb30532_driver = {
.driver = {
.name = "pi3usb30532",
},
- .probe_new = pi3usb30532_probe,
+ .probe = pi3usb30532_probe,
.remove = pi3usb30532_remove,
.id_table = pi3usb30532_table,
};
diff --git a/drivers/usb/typec/qcom-pmic-typec.c b/drivers/usb/typec/qcom-pmic-typec.c
deleted file mode 100644
index 432ea62f1bab..000000000000
--- a/drivers/usb/typec/qcom-pmic-typec.c
+++ /dev/null
@@ -1,261 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2020, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/usb/role.h>
-#include <linux/usb/typec_mux.h>
-
-#define TYPEC_MISC_STATUS 0xb
-#define CC_ATTACHED BIT(0)
-#define CC_ORIENTATION BIT(1)
-#define SNK_SRC_MODE BIT(6)
-#define TYPEC_MODE_CFG 0x44
-#define TYPEC_DISABLE_CMD BIT(0)
-#define EN_SNK_ONLY BIT(1)
-#define EN_SRC_ONLY BIT(2)
-#define TYPEC_VCONN_CONTROL 0x46
-#define VCONN_EN_SRC BIT(0)
-#define VCONN_EN_VAL BIT(1)
-#define TYPEC_EXIT_STATE_CFG 0x50
-#define SEL_SRC_UPPER_REF BIT(2)
-#define TYPEC_INTR_EN_CFG_1 0x5e
-#define TYPEC_INTR_EN_CFG_1_MASK GENMASK(7, 0)
-
-struct qcom_pmic_typec {
- struct device *dev;
- struct regmap *regmap;
- u32 base;
-
- struct typec_port *port;
- struct usb_role_switch *role_sw;
-
- struct regulator *vbus_reg;
- bool vbus_enabled;
-};
-
-static void qcom_pmic_typec_enable_vbus_regulator(struct qcom_pmic_typec
- *qcom_usb, bool enable)
-{
- int ret;
-
- if (enable == qcom_usb->vbus_enabled)
- return;
-
- if (enable) {
- ret = regulator_enable(qcom_usb->vbus_reg);
- if (ret)
- return;
- } else {
- ret = regulator_disable(qcom_usb->vbus_reg);
- if (ret)
- return;
- }
- qcom_usb->vbus_enabled = enable;
-}
-
-static void qcom_pmic_typec_check_connection(struct qcom_pmic_typec *qcom_usb)
-{
- enum typec_orientation orientation;
- enum usb_role role;
- unsigned int stat;
- bool enable_vbus;
-
- regmap_read(qcom_usb->regmap, qcom_usb->base + TYPEC_MISC_STATUS,
- &stat);
-
- if (stat & CC_ATTACHED) {
- orientation = (stat & CC_ORIENTATION) ?
- TYPEC_ORIENTATION_REVERSE :
- TYPEC_ORIENTATION_NORMAL;
- typec_set_orientation(qcom_usb->port, orientation);
-
- role = (stat & SNK_SRC_MODE) ? USB_ROLE_HOST : USB_ROLE_DEVICE;
- if (role == USB_ROLE_HOST)
- enable_vbus = true;
- else
- enable_vbus = false;
- } else {
- role = USB_ROLE_NONE;
- enable_vbus = false;
- }
-
- qcom_pmic_typec_enable_vbus_regulator(qcom_usb, enable_vbus);
- usb_role_switch_set_role(qcom_usb->role_sw, role);
-}
-
-static irqreturn_t qcom_pmic_typec_interrupt(int irq, void *_qcom_usb)
-{
- struct qcom_pmic_typec *qcom_usb = _qcom_usb;
-
- qcom_pmic_typec_check_connection(qcom_usb);
- return IRQ_HANDLED;
-}
-
-static void qcom_pmic_typec_typec_hw_init(struct qcom_pmic_typec *qcom_usb,
- enum typec_port_type type)
-{
- u8 mode = 0;
-
- regmap_update_bits(qcom_usb->regmap,
- qcom_usb->base + TYPEC_INTR_EN_CFG_1,
- TYPEC_INTR_EN_CFG_1_MASK, 0);
-
- if (type == TYPEC_PORT_SRC)
- mode = EN_SRC_ONLY;
- else if (type == TYPEC_PORT_SNK)
- mode = EN_SNK_ONLY;
-
- regmap_update_bits(qcom_usb->regmap, qcom_usb->base + TYPEC_MODE_CFG,
- EN_SNK_ONLY | EN_SRC_ONLY, mode);
-
- regmap_update_bits(qcom_usb->regmap,
- qcom_usb->base + TYPEC_VCONN_CONTROL,
- VCONN_EN_SRC | VCONN_EN_VAL, VCONN_EN_SRC);
- regmap_update_bits(qcom_usb->regmap,
- qcom_usb->base + TYPEC_EXIT_STATE_CFG,
- SEL_SRC_UPPER_REF, SEL_SRC_UPPER_REF);
-}
-
-static int qcom_pmic_typec_probe(struct platform_device *pdev)
-{
- struct qcom_pmic_typec *qcom_usb;
- struct device *dev = &pdev->dev;
- struct fwnode_handle *fwnode;
- struct typec_capability cap;
- const char *buf;
- int ret, irq, role;
- u32 reg;
-
- ret = device_property_read_u32(dev, "reg", &reg);
- if (ret < 0) {
- dev_err(dev, "missing base address\n");
- return ret;
- }
-
- qcom_usb = devm_kzalloc(dev, sizeof(*qcom_usb), GFP_KERNEL);
- if (!qcom_usb)
- return -ENOMEM;
-
- qcom_usb->dev = dev;
- qcom_usb->base = reg;
-
- qcom_usb->regmap = dev_get_regmap(dev->parent, NULL);
- if (!qcom_usb->regmap) {
- dev_err(dev, "Failed to get regmap\n");
- return -EINVAL;
- }
-
- qcom_usb->vbus_reg = devm_regulator_get(qcom_usb->dev, "usb_vbus");
- if (IS_ERR(qcom_usb->vbus_reg))
- return PTR_ERR(qcom_usb->vbus_reg);
-
- fwnode = device_get_named_child_node(dev, "connector");
- if (!fwnode)
- return -EINVAL;
-
- ret = fwnode_property_read_string(fwnode, "power-role", &buf);
- if (!ret) {
- role = typec_find_port_power_role(buf);
- if (role < 0)
- role = TYPEC_PORT_SNK;
- } else {
- role = TYPEC_PORT_SNK;
- }
- cap.type = role;
-
- ret = fwnode_property_read_string(fwnode, "data-role", &buf);
- if (!ret) {
- role = typec_find_port_data_role(buf);
- if (role < 0)
- role = TYPEC_PORT_UFP;
- } else {
- role = TYPEC_PORT_UFP;
- }
- cap.data = role;
-
- cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
- cap.fwnode = fwnode;
- qcom_usb->port = typec_register_port(dev, &cap);
- if (IS_ERR(qcom_usb->port)) {
- ret = PTR_ERR(qcom_usb->port);
- dev_err(dev, "Failed to register type c port %d\n", ret);
- goto err_put_node;
- }
- fwnode_handle_put(fwnode);
-
- qcom_usb->role_sw = fwnode_usb_role_switch_get(dev_fwnode(qcom_usb->dev));
- if (IS_ERR(qcom_usb->role_sw)) {
- ret = dev_err_probe(dev, PTR_ERR(qcom_usb->role_sw),
- "failed to get role switch\n");
- goto err_typec_port;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- goto err_usb_role_sw;
-
- ret = devm_request_threaded_irq(qcom_usb->dev, irq, NULL,
- qcom_pmic_typec_interrupt, IRQF_ONESHOT,
- "qcom-pmic-typec", qcom_usb);
- if (ret) {
- dev_err(&pdev->dev, "Could not request IRQ\n");
- goto err_usb_role_sw;
- }
-
- platform_set_drvdata(pdev, qcom_usb);
- qcom_pmic_typec_typec_hw_init(qcom_usb, cap.type);
- qcom_pmic_typec_check_connection(qcom_usb);
-
- return 0;
-
-err_usb_role_sw:
- usb_role_switch_put(qcom_usb->role_sw);
-err_typec_port:
- typec_unregister_port(qcom_usb->port);
-err_put_node:
- fwnode_handle_put(fwnode);
-
- return ret;
-}
-
-static int qcom_pmic_typec_remove(struct platform_device *pdev)
-{
- struct qcom_pmic_typec *qcom_usb = platform_get_drvdata(pdev);
-
- usb_role_switch_set_role(qcom_usb->role_sw, USB_ROLE_NONE);
- qcom_pmic_typec_enable_vbus_regulator(qcom_usb, 0);
-
- typec_unregister_port(qcom_usb->port);
- usb_role_switch_put(qcom_usb->role_sw);
-
- return 0;
-}
-
-static const struct of_device_id qcom_pmic_typec_table[] = {
- { .compatible = "qcom,pm8150b-usb-typec" },
- { }
-};
-MODULE_DEVICE_TABLE(of, qcom_pmic_typec_table);
-
-static struct platform_driver qcom_pmic_typec = {
- .driver = {
- .name = "qcom,pmic-typec",
- .of_match_table = qcom_pmic_typec_table,
- },
- .probe = qcom_pmic_typec_probe,
- .remove = qcom_pmic_typec_remove,
-};
-module_platform_driver(qcom_pmic_typec);
-
-MODULE_DESCRIPTION("QCOM PMIC USB type C driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/typec/rt1719.c b/drivers/usb/typec/rt1719.c
index ea8b700b0ceb..be02d420920e 100644
--- a/drivers/usb/typec/rt1719.c
+++ b/drivers/usb/typec/rt1719.c
@@ -949,7 +949,7 @@ static struct i2c_driver rt1719_driver = {
.name = "rt1719",
.of_match_table = rt1719_device_table,
},
- .probe_new = rt1719_probe,
+ .probe = rt1719_probe,
.remove = rt1719_remove,
};
module_i2c_driver(rt1719_driver);
diff --git a/drivers/usb/typec/stusb160x.c b/drivers/usb/typec/stusb160x.c
index 494b371151e0..3ab118df1bd4 100644
--- a/drivers/usb/typec/stusb160x.c
+++ b/drivers/usb/typec/stusb160x.c
@@ -870,7 +870,7 @@ static struct i2c_driver stusb160x_driver = {
.pm = &stusb160x_pm_ops,
.of_match_table = stusb160x_of_match,
},
- .probe_new = stusb160x_probe,
+ .probe = stusb160x_probe,
.remove = stusb160x_remove,
};
module_i2c_driver(stusb160x_driver);
diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig
index e6b88ca4a4b9..5d393f520fc2 100644
--- a/drivers/usb/typec/tcpm/Kconfig
+++ b/drivers/usb/typec/tcpm/Kconfig
@@ -76,4 +76,15 @@ config TYPEC_WCOVE
To compile this driver as module, choose M here: the module will be
called typec_wcove.ko
+config TYPEC_QCOM_PMIC
+ tristate "Qualcomm PMIC USB Type-C Port Controller Manager driver"
+ depends on ARCH_QCOM || COMPILE_TEST
+ help
+ A Type-C port and Power Delivery driver which aggregates two
+ discrete pieces of silicon in the PM8150b PMIC block: the
+ Type-C port controller and the Power Delivery PHY.
+
+ This driver enables Type-C role switching, orientation, Alternate
+ mode and Power Delivery support both for VBUS and VCONN.
+
endif # TYPEC_TCPM
diff --git a/drivers/usb/typec/tcpm/Makefile b/drivers/usb/typec/tcpm/Makefile
index 08e57bb499cb..7a8cad0c0bdb 100644
--- a/drivers/usb/typec/tcpm/Makefile
+++ b/drivers/usb/typec/tcpm/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_TYPEC_MT6360) += tcpci_mt6360.o
obj-$(CONFIG_TYPEC_TCPCI_MT6370) += tcpci_mt6370.o
obj-$(CONFIG_TYPEC_TCPCI_MAXIM) += tcpci_maxim.o
tcpci_maxim-y += tcpci_maxim_core.o maxim_contaminant.o
+obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom/
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index 62ba53357612..7fc1ffa14f76 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -1836,7 +1836,7 @@ static struct i2c_driver fusb302_driver = {
.pm = &fusb302_pm_ops,
.of_match_table = of_match_ptr(fusb302_dt_match),
},
- .probe_new = fusb302_probe,
+ .probe = fusb302_probe,
.remove = fusb302_remove,
.id_table = fusb302_i2c_device_id,
};
diff --git a/drivers/usb/typec/tcpm/qcom/Makefile b/drivers/usb/typec/tcpm/qcom/Makefile
new file mode 100644
index 000000000000..dc1e8832e197
--- /dev/null
+++ b/drivers/usb/typec/tcpm/qcom/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom_pmic_tcpm.o
+qcom_pmic_tcpm-y += qcom_pmic_typec.o \
+ qcom_pmic_typec_port.o \
+ qcom_pmic_typec_pdphy.o
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
new file mode 100644
index 000000000000..a905160dd860
--- /dev/null
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023, Linaro Ltd. All rights reserved.
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/usb/role.h>
+#include <linux/usb/tcpm.h>
+#include <linux/usb/typec_mux.h>
+#include "qcom_pmic_typec_pdphy.h"
+#include "qcom_pmic_typec_port.h"
+
+struct pmic_typec_resources {
+ struct pmic_typec_pdphy_resources *pdphy_res;
+ struct pmic_typec_port_resources *port_res;
+};
+
+struct pmic_typec {
+ struct device *dev;
+ struct tcpm_port *tcpm_port;
+ struct tcpc_dev tcpc;
+ struct pmic_typec_pdphy *pmic_typec_pdphy;
+ struct pmic_typec_port *pmic_typec_port;
+ bool vbus_enabled;
+ struct mutex lock; /* VBUS state serialization */
+};
+
+#define tcpc_to_tcpm(_tcpc_) container_of(_tcpc_, struct pmic_typec, tcpc)
+
+static int qcom_pmic_typec_get_vbus(struct tcpc_dev *tcpc)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+ int ret;
+
+ mutex_lock(&tcpm->lock);
+ ret = tcpm->vbus_enabled || qcom_pmic_typec_port_get_vbus(tcpm->pmic_typec_port);
+ mutex_unlock(&tcpm->lock);
+
+ return ret;
+}
+
+static int qcom_pmic_typec_set_vbus(struct tcpc_dev *tcpc, bool on, bool sink)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+ int ret = 0;
+
+ mutex_lock(&tcpm->lock);
+ if (tcpm->vbus_enabled == on)
+ goto done;
+
+ ret = qcom_pmic_typec_port_set_vbus(tcpm->pmic_typec_port, on);
+ if (ret)
+ goto done;
+
+ tcpm->vbus_enabled = on;
+ tcpm_vbus_change(tcpm->tcpm_port);
+
+done:
+ dev_dbg(tcpm->dev, "set_vbus set: %d result %d\n", on, ret);
+ mutex_unlock(&tcpm->lock);
+
+ return ret;
+}
+
+static int qcom_pmic_typec_set_vconn(struct tcpc_dev *tcpc, bool on)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_port_set_vconn(tcpm->pmic_typec_port, on);
+}
+
+static int qcom_pmic_typec_get_cc(struct tcpc_dev *tcpc,
+ enum typec_cc_status *cc1,
+ enum typec_cc_status *cc2)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_port_get_cc(tcpm->pmic_typec_port, cc1, cc2);
+}
+
+static int qcom_pmic_typec_set_cc(struct tcpc_dev *tcpc,
+ enum typec_cc_status cc)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_port_set_cc(tcpm->pmic_typec_port, cc);
+}
+
+static int qcom_pmic_typec_set_polarity(struct tcpc_dev *tcpc,
+ enum typec_cc_polarity pol)
+{
+ /* Polarity is set separately by phy-qcom-qmp.c */
+ return 0;
+}
+
+static int qcom_pmic_typec_start_toggling(struct tcpc_dev *tcpc,
+ enum typec_port_type port_type,
+ enum typec_cc_status cc)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_port_start_toggling(tcpm->pmic_typec_port,
+ port_type, cc);
+}
+
+static int qcom_pmic_typec_set_roles(struct tcpc_dev *tcpc, bool attached,
+ enum typec_role power_role,
+ enum typec_data_role data_role)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_pdphy_set_roles(tcpm->pmic_typec_pdphy,
+ data_role, power_role);
+}
+
+static int qcom_pmic_typec_set_pd_rx(struct tcpc_dev *tcpc, bool on)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_pdphy_set_pd_rx(tcpm->pmic_typec_pdphy, on);
+}
+
+static int qcom_pmic_typec_pd_transmit(struct tcpc_dev *tcpc,
+ enum tcpm_transmit_type type,
+ const struct pd_message *msg,
+ unsigned int negotiated_rev)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_pdphy_pd_transmit(tcpm->pmic_typec_pdphy, type,
+ msg, negotiated_rev);
+}
+
+static int qcom_pmic_typec_init(struct tcpc_dev *tcpc)
+{
+ return 0;
+}
+
+static int qcom_pmic_typec_probe(struct platform_device *pdev)
+{
+ struct pmic_typec *tcpm;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct pmic_typec_resources *res;
+ struct regmap *regmap;
+ u32 base[2];
+ int ret;
+
+ res = of_device_get_match_data(dev);
+ if (!res)
+ return -ENODEV;
+
+ tcpm = devm_kzalloc(dev, sizeof(*tcpm), GFP_KERNEL);
+ if (!tcpm)
+ return -ENOMEM;
+
+ tcpm->dev = dev;
+ tcpm->tcpc.init = qcom_pmic_typec_init;
+ tcpm->tcpc.get_vbus = qcom_pmic_typec_get_vbus;
+ tcpm->tcpc.set_vbus = qcom_pmic_typec_set_vbus;
+ tcpm->tcpc.set_cc = qcom_pmic_typec_set_cc;
+ tcpm->tcpc.get_cc = qcom_pmic_typec_get_cc;
+ tcpm->tcpc.set_polarity = qcom_pmic_typec_set_polarity;
+ tcpm->tcpc.set_vconn = qcom_pmic_typec_set_vconn;
+ tcpm->tcpc.start_toggling = qcom_pmic_typec_start_toggling;
+ tcpm->tcpc.set_pd_rx = qcom_pmic_typec_set_pd_rx;
+ tcpm->tcpc.set_roles = qcom_pmic_typec_set_roles;
+ tcpm->tcpc.pd_transmit = qcom_pmic_typec_pd_transmit;
+
+ regmap = dev_get_regmap(dev->parent, NULL);
+ if (!regmap) {
+ dev_err(dev, "Failed to get regmap\n");
+ return -ENODEV;
+ }
+
+ ret = of_property_read_u32_array(np, "reg", base, 2);
+ if (ret)
+ return ret;
+
+ tcpm->pmic_typec_port = qcom_pmic_typec_port_alloc(dev);
+ if (IS_ERR(tcpm->pmic_typec_port))
+ return PTR_ERR(tcpm->pmic_typec_port);
+
+ tcpm->pmic_typec_pdphy = qcom_pmic_typec_pdphy_alloc(dev);
+ if (IS_ERR(tcpm->pmic_typec_pdphy))
+ return PTR_ERR(tcpm->pmic_typec_pdphy);
+
+ ret = qcom_pmic_typec_port_probe(pdev, tcpm->pmic_typec_port,
+ res->port_res, regmap, base[0]);
+ if (ret)
+ return ret;
+
+ ret = qcom_pmic_typec_pdphy_probe(pdev, tcpm->pmic_typec_pdphy,
+ res->pdphy_res, regmap, base[1]);
+ if (ret)
+ return ret;
+
+ mutex_init(&tcpm->lock);
+ platform_set_drvdata(pdev, tcpm);
+
+ tcpm->tcpc.fwnode = device_get_named_child_node(tcpm->dev, "connector");
+ if (IS_ERR(tcpm->tcpc.fwnode))
+ return PTR_ERR(tcpm->tcpc.fwnode);
+
+ tcpm->tcpm_port = tcpm_register_port(tcpm->dev, &tcpm->tcpc);
+ if (IS_ERR(tcpm->tcpm_port)) {
+ ret = PTR_ERR(tcpm->tcpm_port);
+ goto fwnode_remove;
+ }
+
+ ret = qcom_pmic_typec_port_start(tcpm->pmic_typec_port,
+ tcpm->tcpm_port);
+ if (ret)
+ goto fwnode_remove;
+
+ ret = qcom_pmic_typec_pdphy_start(tcpm->pmic_typec_pdphy,
+ tcpm->tcpm_port);
+ if (ret)
+ goto fwnode_remove;
+
+ return 0;
+
+fwnode_remove:
+ fwnode_remove_software_node(tcpm->tcpc.fwnode);
+
+ return ret;
+}
+
+static void qcom_pmic_typec_remove(struct platform_device *pdev)
+{
+ struct pmic_typec *tcpm = platform_get_drvdata(pdev);
+
+ qcom_pmic_typec_pdphy_stop(tcpm->pmic_typec_pdphy);
+ qcom_pmic_typec_port_stop(tcpm->pmic_typec_port);
+ tcpm_unregister_port(tcpm->tcpm_port);
+ fwnode_remove_software_node(tcpm->tcpc.fwnode);
+}
+
+static struct pmic_typec_pdphy_resources pm8150b_pdphy_res = {
+ .irq_params = {
+ {
+ .virq = PMIC_PDPHY_SIG_TX_IRQ,
+ .irq_name = "sig-tx",
+ },
+ {
+ .virq = PMIC_PDPHY_SIG_RX_IRQ,
+ .irq_name = "sig-rx",
+ },
+ {
+ .virq = PMIC_PDPHY_MSG_TX_IRQ,
+ .irq_name = "msg-tx",
+ },
+ {
+ .virq = PMIC_PDPHY_MSG_RX_IRQ,
+ .irq_name = "msg-rx",
+ },
+ {
+ .virq = PMIC_PDPHY_MSG_TX_FAIL_IRQ,
+ .irq_name = "msg-tx-failed",
+ },
+ {
+ .virq = PMIC_PDPHY_MSG_TX_DISCARD_IRQ,
+ .irq_name = "msg-tx-discarded",
+ },
+ {
+ .virq = PMIC_PDPHY_MSG_RX_DISCARD_IRQ,
+ .irq_name = "msg-rx-discarded",
+ },
+ },
+ .nr_irqs = 7,
+};
+
+static struct pmic_typec_port_resources pm8150b_port_res = {
+ .irq_params = {
+ {
+ .irq_name = "vpd-detect",
+ .virq = PMIC_TYPEC_VPD_IRQ,
+ },
+
+ {
+ .irq_name = "cc-state-change",
+ .virq = PMIC_TYPEC_CC_STATE_IRQ,
+ },
+ {
+ .irq_name = "vconn-oc",
+ .virq = PMIC_TYPEC_VCONN_OC_IRQ,
+ },
+
+ {
+ .irq_name = "vbus-change",
+ .virq = PMIC_TYPEC_VBUS_IRQ,
+ },
+
+ {
+ .irq_name = "attach-detach",
+ .virq = PMIC_TYPEC_ATTACH_DETACH_IRQ,
+ },
+ {
+ .irq_name = "legacy-cable-detect",
+ .virq = PMIC_TYPEC_LEGACY_CABLE_IRQ,
+ },
+
+ {
+ .irq_name = "try-snk-src-detect",
+ .virq = PMIC_TYPEC_TRY_SNK_SRC_IRQ,
+ },
+ },
+ .nr_irqs = 7,
+};
+
+static struct pmic_typec_resources pm8150b_typec_res = {
+ .pdphy_res = &pm8150b_pdphy_res,
+ .port_res = &pm8150b_port_res,
+};
+
+static const struct of_device_id qcom_pmic_typec_table[] = {
+ { .compatible = "qcom,pm8150b-typec", .data = &pm8150b_typec_res },
+ { }
+};
+MODULE_DEVICE_TABLE(of, qcom_pmic_typec_table);
+
+static struct platform_driver qcom_pmic_typec_driver = {
+ .driver = {
+ .name = "qcom,pmic-typec",
+ .of_match_table = qcom_pmic_typec_table,
+ },
+ .probe = qcom_pmic_typec_probe,
+ .remove_new = qcom_pmic_typec_remove,
+};
+
+module_platform_driver(qcom_pmic_typec_driver);
+
+MODULE_DESCRIPTION("QCOM PMIC USB Type-C Port Manager Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
new file mode 100644
index 000000000000..4e1b846627d2
--- /dev/null
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
@@ -0,0 +1,528 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023, Linaro Ltd. All rights reserved.
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/usb/pd.h>
+#include <linux/usb/tcpm.h>
+#include "qcom_pmic_typec_pdphy.h"
+
+struct pmic_typec_pdphy_irq_data {
+ int virq;
+ int irq;
+ struct pmic_typec_pdphy *pmic_typec_pdphy;
+};
+
+struct pmic_typec_pdphy {
+ struct device *dev;
+ struct tcpm_port *tcpm_port;
+ struct regmap *regmap;
+ u32 base;
+
+ unsigned int nr_irqs;
+ struct pmic_typec_pdphy_irq_data *irq_data;
+
+ struct work_struct reset_work;
+ struct work_struct receive_work;
+ struct regulator *vdd_pdphy;
+ spinlock_t lock; /* Register atomicity */
+};
+
+static void qcom_pmic_typec_pdphy_reset_on(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ int ret;
+
+ /* Terminate TX */
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, 0);
+ if (ret)
+ goto err;
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_FRAME_FILTER_REG, 0);
+ if (ret)
+ goto err;
+
+ return;
+err:
+ dev_err(dev, "pd_reset_on error\n");
+}
+
+static void qcom_pmic_typec_pdphy_reset_off(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ int ret;
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_FRAME_FILTER_REG,
+ FRAME_FILTER_EN_SOP | FRAME_FILTER_EN_HARD_RESET);
+ if (ret)
+ dev_err(dev, "pd_reset_off error\n");
+}
+
+static void qcom_pmic_typec_pdphy_sig_reset_work(struct work_struct *work)
+{
+ struct pmic_typec_pdphy *pmic_typec_pdphy = container_of(work, struct pmic_typec_pdphy,
+ reset_work);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
+
+ qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
+ qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy);
+
+ spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
+
+ tcpm_pd_hard_reset(pmic_typec_pdphy->tcpm_port);
+}
+
+static int
+qcom_pmic_typec_pdphy_clear_tx_control_reg(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ unsigned int val;
+ int ret;
+
+ /* Clear TX control register */
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, 0);
+ if (ret)
+ goto done;
+
+ /* Perform readback to ensure sufficient delay for command to latch */
+ ret = regmap_read(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, &val);
+
+done:
+ if (ret)
+ dev_err(dev, "pd_clear_tx_control_reg: clear tx flag\n");
+
+ return ret;
+}
+
+static int
+qcom_pmic_typec_pdphy_pd_transmit_signal(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ enum tcpm_transmit_type type,
+ unsigned int negotiated_rev)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ unsigned int val;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
+
+ /* Clear TX control register */
+ ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy);
+ if (ret)
+ goto done;
+
+ val = TX_CONTROL_SEND_SIGNAL;
+ if (negotiated_rev == PD_REV30)
+ val |= TX_CONTROL_RETRY_COUNT(2);
+ else
+ val |= TX_CONTROL_RETRY_COUNT(3);
+
+ if (type == TCPC_TX_CABLE_RESET || type == TCPC_TX_HARD_RESET)
+ val |= TX_CONTROL_FRAME_TYPE(1);
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, val);
+
+done:
+ spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
+
+ dev_vdbg(dev, "pd_transmit_signal: type %d negotiate_rev %d send %d\n",
+ type, negotiated_rev, ret);
+
+ return ret;
+}
+
+static int
+qcom_pmic_typec_pdphy_pd_transmit_payload(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ enum tcpm_transmit_type type,
+ const struct pd_message *msg,
+ unsigned int negotiated_rev)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ unsigned int val, hdr_len, txbuf_len, txsize_len;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
+
+ ret = regmap_read(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG,
+ &val);
+ if (ret)
+ goto done;
+
+ if (val) {
+ dev_err(dev, "pd_transmit_payload: RX message pending\n");
+ ret = -EBUSY;
+ goto done;
+ }
+
+ /* Clear TX control register */
+ ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy);
+ if (ret)
+ goto done;
+
+ hdr_len = sizeof(msg->header);
+ txbuf_len = pd_header_cnt_le(msg->header) * 4;
+ txsize_len = hdr_len + txbuf_len - 1;
+
+ /* Write message header sizeof(u16) to USB_PDPHY_TX_BUFFER_HDR_REG */
+ ret = regmap_bulk_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_BUFFER_HDR_REG,
+ &msg->header, hdr_len);
+ if (ret)
+ goto done;
+
+ /* Write payload to USB_PDPHY_TX_BUFFER_DATA_REG for txbuf_len */
+ if (txbuf_len) {
+ ret = regmap_bulk_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_BUFFER_DATA_REG,
+ &msg->payload, txbuf_len);
+ if (ret)
+ goto done;
+ }
+
+ /* Write total length ((header + data) - 1) to USB_PDPHY_TX_SIZE_REG */
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_SIZE_REG,
+ txsize_len);
+ if (ret)
+ goto done;
+
+ /* Clear TX control register */
+ ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy);
+ if (ret)
+ goto done;
+
+ /* Initiate transmit with retry count as indicated by PD revision */
+ val = TX_CONTROL_FRAME_TYPE(type) | TX_CONTROL_SEND_MSG;
+ if (pd_header_rev(msg->header) == PD_REV30)
+ val |= TX_CONTROL_RETRY_COUNT(2);
+ else
+ val |= TX_CONTROL_RETRY_COUNT(3);
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, val);
+
+done:
+ spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
+
+ if (ret) {
+ dev_err(dev, "pd_transmit_payload: hdr %*ph data %*ph ret %d\n",
+ hdr_len, &msg->header, txbuf_len, &msg->payload, ret);
+ }
+
+ return ret;
+}
+
+int qcom_pmic_typec_pdphy_pd_transmit(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ enum tcpm_transmit_type type,
+ const struct pd_message *msg,
+ unsigned int negotiated_rev)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ int ret;
+
+ if (msg) {
+ ret = qcom_pmic_typec_pdphy_pd_transmit_payload(pmic_typec_pdphy,
+ type, msg,
+ negotiated_rev);
+ } else {
+ ret = qcom_pmic_typec_pdphy_pd_transmit_signal(pmic_typec_pdphy,
+ type,
+ negotiated_rev);
+ }
+
+ if (ret)
+ dev_dbg(dev, "pd_transmit: type %x result %d\n", type, ret);
+
+ return ret;
+}
+
+static void qcom_pmic_typec_pdphy_pd_receive(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ struct pd_message msg;
+ unsigned int size, rx_status;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
+
+ ret = regmap_read(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_RX_SIZE_REG, &size);
+ if (ret)
+ goto done;
+
+ /* Hardware requires +1 of the real read value to be passed */
+ if (size < 1 || size > sizeof(msg.payload) + 1) {
+ dev_dbg(dev, "pd_receive: invalid size %d\n", size);
+ goto done;
+ }
+
+ size += 1;
+ ret = regmap_read(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_RX_STATUS_REG,
+ &rx_status);
+
+ if (ret)
+ goto done;
+
+ ret = regmap_bulk_read(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_RX_BUFFER_REG,
+ (u8 *)&msg, size);
+ if (ret)
+ goto done;
+
+ /* Return ownership of RX buffer to hardware */
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG, 0);
+
+done:
+ spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
+
+ if (!ret) {
+ dev_vdbg(dev, "pd_receive: handing %d bytes to tcpm\n", size);
+ tcpm_pd_receive(pmic_typec_pdphy->tcpm_port, &msg);
+ }
+}
+
+static irqreturn_t qcom_pmic_typec_pdphy_isr(int irq, void *dev_id)
+{
+ struct pmic_typec_pdphy_irq_data *irq_data = dev_id;
+ struct pmic_typec_pdphy *pmic_typec_pdphy = irq_data->pmic_typec_pdphy;
+ struct device *dev = pmic_typec_pdphy->dev;
+
+ switch (irq_data->virq) {
+ case PMIC_PDPHY_SIG_TX_IRQ:
+ dev_err(dev, "isr: tx_sig\n");
+ break;
+ case PMIC_PDPHY_SIG_RX_IRQ:
+ schedule_work(&pmic_typec_pdphy->reset_work);
+ break;
+ case PMIC_PDPHY_MSG_TX_IRQ:
+ tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port,
+ TCPC_TX_SUCCESS);
+ break;
+ case PMIC_PDPHY_MSG_RX_IRQ:
+ qcom_pmic_typec_pdphy_pd_receive(pmic_typec_pdphy);
+ break;
+ case PMIC_PDPHY_MSG_TX_FAIL_IRQ:
+ tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port,
+ TCPC_TX_FAILED);
+ break;
+ case PMIC_PDPHY_MSG_TX_DISCARD_IRQ:
+ tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port,
+ TCPC_TX_DISCARDED);
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+int qcom_pmic_typec_pdphy_set_pd_rx(struct pmic_typec_pdphy *pmic_typec_pdphy, bool on)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG, !on);
+
+ spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
+
+ dev_dbg(pmic_typec_pdphy->dev, "set_pd_rx: %s\n", on ? "on" : "off");
+
+ return ret;
+}
+
+int qcom_pmic_typec_pdphy_set_roles(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ bool data_role_host, bool power_role_src)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
+
+ ret = regmap_update_bits(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_MSG_CONFIG_REG,
+ MSG_CONFIG_PORT_DATA_ROLE |
+ MSG_CONFIG_PORT_POWER_ROLE,
+ data_role_host << 3 | power_role_src << 2);
+
+ spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
+
+ dev_dbg(dev, "pdphy_set_roles: data_role_host=%d power_role_src=%d\n",
+ data_role_host, power_role_src);
+
+ return ret;
+}
+
+static int qcom_pmic_typec_pdphy_enable(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ int ret;
+
+ ret = regulator_enable(pmic_typec_pdphy->vdd_pdphy);
+ if (ret)
+ return ret;
+
+ /* PD 2.0, DR=TYPEC_DEVICE, PR=TYPEC_SINK */
+ ret = regmap_update_bits(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_MSG_CONFIG_REG,
+ MSG_CONFIG_SPEC_REV_MASK, PD_REV20);
+ if (ret)
+ goto done;
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0);
+ if (ret)
+ goto done;
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG,
+ CONTROL_ENABLE);
+ if (ret)
+ goto done;
+
+ qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy);
+done:
+ if (ret) {
+ regulator_disable(pmic_typec_pdphy->vdd_pdphy);
+ dev_err(dev, "pdphy_enable fail %d\n", ret);
+ }
+
+ return ret;
+}
+
+static int qcom_pmic_typec_pdphy_disable(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ int ret;
+
+ qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0);
+
+ regulator_disable(pmic_typec_pdphy->vdd_pdphy);
+
+ return ret;
+}
+
+static int pmic_typec_pdphy_reset(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ int ret;
+
+ ret = qcom_pmic_typec_pdphy_disable(pmic_typec_pdphy);
+ if (ret)
+ goto done;
+
+ usleep_range(400, 500);
+ ret = qcom_pmic_typec_pdphy_enable(pmic_typec_pdphy);
+done:
+ return ret;
+}
+
+int qcom_pmic_typec_pdphy_start(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ struct tcpm_port *tcpm_port)
+{
+ int i;
+ int ret;
+
+ pmic_typec_pdphy->tcpm_port = tcpm_port;
+
+ ret = pmic_typec_pdphy_reset(pmic_typec_pdphy);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
+ enable_irq(pmic_typec_pdphy->irq_data[i].irq);
+
+ return 0;
+}
+
+void qcom_pmic_typec_pdphy_stop(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ int i;
+
+ for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
+ disable_irq(pmic_typec_pdphy->irq_data[i].irq);
+
+ qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
+}
+
+struct pmic_typec_pdphy *qcom_pmic_typec_pdphy_alloc(struct device *dev)
+{
+ return devm_kzalloc(dev, sizeof(struct pmic_typec_pdphy), GFP_KERNEL);
+}
+
+int qcom_pmic_typec_pdphy_probe(struct platform_device *pdev,
+ struct pmic_typec_pdphy *pmic_typec_pdphy,
+ struct pmic_typec_pdphy_resources *res,
+ struct regmap *regmap,
+ u32 base)
+{
+ struct device *dev = &pdev->dev;
+ struct pmic_typec_pdphy_irq_data *irq_data;
+ int i, ret, irq;
+
+ if (!res->nr_irqs || res->nr_irqs > PMIC_PDPHY_MAX_IRQS)
+ return -EINVAL;
+
+ irq_data = devm_kzalloc(dev, sizeof(*irq_data) * res->nr_irqs,
+ GFP_KERNEL);
+ if (!irq_data)
+ return -ENOMEM;
+
+ pmic_typec_pdphy->vdd_pdphy = devm_regulator_get(dev, "vdd-pdphy");
+ if (IS_ERR(pmic_typec_pdphy->vdd_pdphy))
+ return PTR_ERR(pmic_typec_pdphy->vdd_pdphy);
+
+ pmic_typec_pdphy->dev = dev;
+ pmic_typec_pdphy->base = base;
+ pmic_typec_pdphy->regmap = regmap;
+ pmic_typec_pdphy->nr_irqs = res->nr_irqs;
+ pmic_typec_pdphy->irq_data = irq_data;
+ spin_lock_init(&pmic_typec_pdphy->lock);
+ INIT_WORK(&pmic_typec_pdphy->reset_work, qcom_pmic_typec_pdphy_sig_reset_work);
+
+ for (i = 0; i < res->nr_irqs; i++, irq_data++) {
+ irq = platform_get_irq_byname(pdev, res->irq_params[i].irq_name);
+ if (irq < 0)
+ return irq;
+
+ irq_data->pmic_typec_pdphy = pmic_typec_pdphy;
+ irq_data->irq = irq;
+ irq_data->virq = res->irq_params[i].virq;
+
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ qcom_pmic_typec_pdphy_isr,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN,
+ res->irq_params[i].irq_name,
+ irq_data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h
new file mode 100644
index 000000000000..e67954e31b14
--- /dev/null
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Ltd. All rights reserved.
+ */
+#ifndef __QCOM_PMIC_PDPHY_H__
+#define __QCOM_PMIC_PDPHY_H__
+
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/usb/tcpm.h>
+
+#define USB_PDPHY_MAX_DATA_OBJ_LEN 28
+#define USB_PDPHY_MSG_HDR_LEN 2
+
+/* PD PHY register offsets and bit fields */
+#define USB_PDPHY_MSG_CONFIG_REG 0x40
+#define MSG_CONFIG_PORT_DATA_ROLE BIT(3)
+#define MSG_CONFIG_PORT_POWER_ROLE BIT(2)
+#define MSG_CONFIG_SPEC_REV_MASK (BIT(1) | BIT(0))
+
+#define USB_PDPHY_EN_CONTROL_REG 0x46
+#define CONTROL_ENABLE BIT(0)
+
+#define USB_PDPHY_RX_STATUS_REG 0x4A
+#define RX_FRAME_TYPE (BIT(0) | BIT(1) | BIT(2))
+
+#define USB_PDPHY_FRAME_FILTER_REG 0x4C
+#define FRAME_FILTER_EN_HARD_RESET BIT(5)
+#define FRAME_FILTER_EN_SOP BIT(0)
+
+#define USB_PDPHY_TX_SIZE_REG 0x42
+#define TX_SIZE_MASK 0xF
+
+#define USB_PDPHY_TX_CONTROL_REG 0x44
+#define TX_CONTROL_RETRY_COUNT(n) (((n) & 0x3) << 5)
+#define TX_CONTROL_FRAME_TYPE(n) (((n) & 0x7) << 2)
+#define TX_CONTROL_FRAME_TYPE_CABLE_RESET (0x1 << 2)
+#define TX_CONTROL_SEND_SIGNAL BIT(1)
+#define TX_CONTROL_SEND_MSG BIT(0)
+
+#define USB_PDPHY_RX_SIZE_REG 0x48
+
+#define USB_PDPHY_RX_ACKNOWLEDGE_REG 0x4B
+#define RX_BUFFER_TOKEN BIT(0)
+
+#define USB_PDPHY_BIST_MODE_REG 0x4E
+#define BIST_MODE_MASK 0xF
+#define BIST_ENABLE BIT(7)
+#define PD_MSG_BIST 0x3
+#define PD_BIST_TEST_DATA_MODE 0x8
+
+#define USB_PDPHY_TX_BUFFER_HDR_REG 0x60
+#define USB_PDPHY_TX_BUFFER_DATA_REG 0x62
+
+#define USB_PDPHY_RX_BUFFER_REG 0x80
+
+/* VDD regulator */
+#define VDD_PDPHY_VOL_MIN 2800000 /* uV */
+#define VDD_PDPHY_VOL_MAX 3300000 /* uV */
+#define VDD_PDPHY_HPM_LOAD 3000 /* uA */
+
+/* Message Spec Rev field */
+#define PD_MSG_HDR_REV(hdr) (((hdr) >> 6) & 3)
+
+/* timers */
+#define RECEIVER_RESPONSE_TIME 15 /* tReceiverResponse */
+#define HARD_RESET_COMPLETE_TIME 5 /* tHardResetComplete */
+
+/* Interrupt numbers */
+#define PMIC_PDPHY_SIG_TX_IRQ 0x0
+#define PMIC_PDPHY_SIG_RX_IRQ 0x1
+#define PMIC_PDPHY_MSG_TX_IRQ 0x2
+#define PMIC_PDPHY_MSG_RX_IRQ 0x3
+#define PMIC_PDPHY_MSG_TX_FAIL_IRQ 0x4
+#define PMIC_PDPHY_MSG_TX_DISCARD_IRQ 0x5
+#define PMIC_PDPHY_MSG_RX_DISCARD_IRQ 0x6
+#define PMIC_PDPHY_FR_SWAP_IRQ 0x7
+
+/* Resources */
+#define PMIC_PDPHY_MAX_IRQS 0x08
+
+struct pmic_typec_pdphy_irq_params {
+ int virq;
+ char *irq_name;
+};
+
+struct pmic_typec_pdphy_resources {
+ unsigned int nr_irqs;
+ struct pmic_typec_pdphy_irq_params irq_params[PMIC_PDPHY_MAX_IRQS];
+};
+
+/* API */
+struct pmic_typec_pdphy;
+
+struct pmic_typec_pdphy *qcom_pmic_typec_pdphy_alloc(struct device *dev);
+
+int qcom_pmic_typec_pdphy_probe(struct platform_device *pdev,
+ struct pmic_typec_pdphy *pmic_typec_pdphy,
+ struct pmic_typec_pdphy_resources *res,
+ struct regmap *regmap,
+ u32 base);
+
+int qcom_pmic_typec_pdphy_start(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ struct tcpm_port *tcpm_port);
+
+void qcom_pmic_typec_pdphy_stop(struct pmic_typec_pdphy *pmic_typec_pdphy);
+
+int qcom_pmic_typec_pdphy_set_roles(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ bool power_role_src, bool data_role_host);
+
+int qcom_pmic_typec_pdphy_set_pd_rx(struct pmic_typec_pdphy *pmic_typec_pdphy, bool on);
+
+int qcom_pmic_typec_pdphy_pd_transmit(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ enum tcpm_transmit_type type,
+ const struct pd_message *msg,
+ unsigned int negotiated_rev);
+
+#endif /* __QCOM_PMIC_TYPEC_PDPHY_H__ */
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
new file mode 100644
index 000000000000..94285f64b67d
--- /dev/null
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
@@ -0,0 +1,556 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023, Linaro Ltd. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/usb/tcpm.h>
+#include <linux/usb/typec_mux.h>
+#include <linux/workqueue.h>
+#include "qcom_pmic_typec_port.h"
+
+struct pmic_typec_port_irq_data {
+ int virq;
+ int irq;
+ struct pmic_typec_port *pmic_typec_port;
+};
+
+struct pmic_typec_port {
+ struct device *dev;
+ struct tcpm_port *tcpm_port;
+ struct regmap *regmap;
+ u32 base;
+ unsigned int nr_irqs;
+ struct pmic_typec_port_irq_data *irq_data;
+
+ struct regulator *vdd_vbus;
+
+ int cc;
+ bool debouncing_cc;
+ struct delayed_work cc_debounce_dwork;
+
+ spinlock_t lock; /* Register atomicity */
+};
+
+static const char * const typec_cc_status_name[] = {
+ [TYPEC_CC_OPEN] = "Open",
+ [TYPEC_CC_RA] = "Ra",
+ [TYPEC_CC_RD] = "Rd",
+ [TYPEC_CC_RP_DEF] = "Rp-def",
+ [TYPEC_CC_RP_1_5] = "Rp-1.5",
+ [TYPEC_CC_RP_3_0] = "Rp-3.0",
+};
+
+static const char *rp_unknown = "unknown";
+
+static const char *cc_to_name(enum typec_cc_status cc)
+{
+ if (cc > TYPEC_CC_RP_3_0)
+ return rp_unknown;
+
+ return typec_cc_status_name[cc];
+}
+
+static const char * const rp_sel_name[] = {
+ [TYPEC_SRC_RP_SEL_80UA] = "Rp-def-80uA",
+ [TYPEC_SRC_RP_SEL_180UA] = "Rp-1.5-180uA",
+ [TYPEC_SRC_RP_SEL_330UA] = "Rp-3.0-330uA",
+};
+
+static const char *rp_sel_to_name(int rp_sel)
+{
+ if (rp_sel > TYPEC_SRC_RP_SEL_330UA)
+ return rp_unknown;
+
+ return rp_sel_name[rp_sel];
+}
+
+#define misc_to_cc(msic) !!(misc & CC_ORIENTATION) ? "cc1" : "cc2"
+#define misc_to_vconn(msic) !!(misc & CC_ORIENTATION) ? "cc2" : "cc1"
+
+static void qcom_pmic_typec_port_cc_debounce(struct work_struct *work)
+{
+ struct pmic_typec_port *pmic_typec_port =
+ container_of(work, struct pmic_typec_port, cc_debounce_dwork.work);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pmic_typec_port->lock, flags);
+ pmic_typec_port->debouncing_cc = false;
+ spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
+
+ dev_dbg(pmic_typec_port->dev, "Debounce cc complete\n");
+}
+
+static irqreturn_t pmic_typec_port_isr(int irq, void *dev_id)
+{
+ struct pmic_typec_port_irq_data *irq_data = dev_id;
+ struct pmic_typec_port *pmic_typec_port = irq_data->pmic_typec_port;
+ u32 misc_stat;
+ bool vbus_change = false;
+ bool cc_change = false;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_port->lock, flags);
+
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MISC_STATUS_REG,
+ &misc_stat);
+ if (ret)
+ goto done;
+
+ switch (irq_data->virq) {
+ case PMIC_TYPEC_VBUS_IRQ:
+ vbus_change = true;
+ break;
+ case PMIC_TYPEC_CC_STATE_IRQ:
+ case PMIC_TYPEC_ATTACH_DETACH_IRQ:
+ if (!pmic_typec_port->debouncing_cc)
+ cc_change = true;
+ break;
+ }
+
+done:
+ spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
+
+ if (vbus_change)
+ tcpm_vbus_change(pmic_typec_port->tcpm_port);
+
+ if (cc_change)
+ tcpm_cc_change(pmic_typec_port->tcpm_port);
+
+ return IRQ_HANDLED;
+}
+
+int qcom_pmic_typec_port_get_vbus(struct pmic_typec_port *pmic_typec_port)
+{
+ struct device *dev = pmic_typec_port->dev;
+ unsigned int misc;
+ int ret;
+
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MISC_STATUS_REG,
+ &misc);
+ if (ret)
+ misc = 0;
+
+ dev_dbg(dev, "get_vbus: 0x%08x detect %d\n", misc, !!(misc & TYPEC_VBUS_DETECT));
+
+ return !!(misc & TYPEC_VBUS_DETECT);
+}
+
+int qcom_pmic_typec_port_set_vbus(struct pmic_typec_port *pmic_typec_port, bool on)
+{
+ u32 sm_stat;
+ u32 val;
+ int ret;
+
+ if (on) {
+ ret = regulator_enable(pmic_typec_port->vdd_vbus);
+ if (ret)
+ return ret;
+
+ val = TYPEC_SM_VBUS_VSAFE5V;
+ } else {
+ ret = regulator_disable(pmic_typec_port->vdd_vbus);
+ if (ret)
+ return ret;
+
+ val = TYPEC_SM_VBUS_VSAFE0V;
+ }
+
+ /* Poll waiting for transition to required vSafe5V or vSafe0V */
+ ret = regmap_read_poll_timeout(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_SM_STATUS_REG,
+ sm_stat, sm_stat & val,
+ 100, 250000);
+ if (ret)
+ dev_warn(pmic_typec_port->dev, "vbus vsafe%dv fail\n", on ? 5 : 0);
+
+ return 0;
+}
+
+int qcom_pmic_typec_port_get_cc(struct pmic_typec_port *pmic_typec_port,
+ enum typec_cc_status *cc1,
+ enum typec_cc_status *cc2)
+{
+ struct device *dev = pmic_typec_port->dev;
+ unsigned int misc, val;
+ bool attached;
+ int ret = 0;
+
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MISC_STATUS_REG, &misc);
+ if (ret)
+ goto done;
+
+ attached = !!(misc & CC_ATTACHED);
+
+ if (pmic_typec_port->debouncing_cc) {
+ ret = -EBUSY;
+ goto done;
+ }
+
+ *cc1 = TYPEC_CC_OPEN;
+ *cc2 = TYPEC_CC_OPEN;
+
+ if (!attached)
+ goto done;
+
+ if (misc & SNK_SRC_MODE) {
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_SRC_STATUS_REG,
+ &val);
+ if (ret)
+ goto done;
+ switch (val & DETECTED_SRC_TYPE_MASK) {
+ case SRC_RD_OPEN:
+ val = TYPEC_CC_RD;
+ break;
+ case SRC_RD_RA_VCONN:
+ val = TYPEC_CC_RD;
+ *cc1 = TYPEC_CC_RA;
+ *cc2 = TYPEC_CC_RA;
+ break;
+ default:
+ dev_warn(dev, "unexpected src status %.2x\n", val);
+ val = TYPEC_CC_RD;
+ break;
+ }
+ } else {
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_SNK_STATUS_REG,
+ &val);
+ if (ret)
+ goto done;
+ switch (val & DETECTED_SNK_TYPE_MASK) {
+ case SNK_RP_STD:
+ val = TYPEC_CC_RP_DEF;
+ break;
+ case SNK_RP_1P5:
+ val = TYPEC_CC_RP_1_5;
+ break;
+ case SNK_RP_3P0:
+ val = TYPEC_CC_RP_3_0;
+ break;
+ default:
+ dev_warn(dev, "unexpected snk status %.2x\n", val);
+ val = TYPEC_CC_RP_DEF;
+ break;
+ }
+ val = TYPEC_CC_RP_DEF;
+ }
+
+ if (misc & CC_ORIENTATION)
+ *cc2 = val;
+ else
+ *cc1 = val;
+
+done:
+ dev_dbg(dev, "get_cc: misc 0x%08x cc1 0x%08x %s cc2 0x%08x %s attached %d cc=%s\n",
+ misc, *cc1, cc_to_name(*cc1), *cc2, cc_to_name(*cc2), attached,
+ misc_to_cc(misc));
+
+ return ret;
+}
+
+static void qcom_pmic_set_cc_debounce(struct pmic_typec_port *pmic_typec_port)
+{
+ pmic_typec_port->debouncing_cc = true;
+ schedule_delayed_work(&pmic_typec_port->cc_debounce_dwork,
+ msecs_to_jiffies(2));
+}
+
+int qcom_pmic_typec_port_set_cc(struct pmic_typec_port *pmic_typec_port,
+ enum typec_cc_status cc)
+{
+ struct device *dev = pmic_typec_port->dev;
+ unsigned int mode, currsrc;
+ unsigned int misc;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_port->lock, flags);
+
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MISC_STATUS_REG,
+ &misc);
+ if (ret)
+ goto done;
+
+ mode = EN_SRC_ONLY;
+
+ switch (cc) {
+ case TYPEC_CC_OPEN:
+ currsrc = TYPEC_SRC_RP_SEL_80UA;
+ break;
+ case TYPEC_CC_RP_DEF:
+ currsrc = TYPEC_SRC_RP_SEL_80UA;
+ break;
+ case TYPEC_CC_RP_1_5:
+ currsrc = TYPEC_SRC_RP_SEL_180UA;
+ break;
+ case TYPEC_CC_RP_3_0:
+ currsrc = TYPEC_SRC_RP_SEL_330UA;
+ break;
+ case TYPEC_CC_RD:
+ currsrc = TYPEC_SRC_RP_SEL_80UA;
+ mode = EN_SNK_ONLY;
+ break;
+ default:
+ dev_warn(dev, "unexpected set_cc %d\n", cc);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (mode == EN_SRC_ONLY) {
+ ret = regmap_write(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_CURRSRC_CFG_REG,
+ currsrc);
+ if (ret)
+ goto done;
+ }
+
+ pmic_typec_port->cc = cc;
+ qcom_pmic_set_cc_debounce(pmic_typec_port);
+ ret = 0;
+
+done:
+ spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
+
+ dev_dbg(dev, "set_cc: currsrc=%x %s mode %s debounce %d attached %d cc=%s\n",
+ currsrc, rp_sel_to_name(currsrc),
+ mode == EN_SRC_ONLY ? "EN_SRC_ONLY" : "EN_SNK_ONLY",
+ pmic_typec_port->debouncing_cc, !!(misc & CC_ATTACHED),
+ misc_to_cc(misc));
+
+ return ret;
+}
+
+int qcom_pmic_typec_port_set_vconn(struct pmic_typec_port *pmic_typec_port, bool on)
+{
+ struct device *dev = pmic_typec_port->dev;
+ unsigned int orientation, misc, mask, value;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_port->lock, flags);
+
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MISC_STATUS_REG, &misc);
+ if (ret)
+ goto done;
+
+ /* Set VCONN on the inversion of the active CC channel */
+ orientation = (misc & CC_ORIENTATION) ? 0 : VCONN_EN_ORIENTATION;
+ if (on) {
+ mask = VCONN_EN_ORIENTATION | VCONN_EN_VALUE;
+ value = orientation | VCONN_EN_VALUE | VCONN_EN_SRC;
+ } else {
+ mask = VCONN_EN_VALUE;
+ value = 0;
+ }
+
+ ret = regmap_update_bits(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_VCONN_CONTROL_REG,
+ mask, value);
+done:
+ spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
+
+ dev_dbg(dev, "set_vconn: orientation %d control 0x%08x state %s cc %s vconn %s\n",
+ orientation, value, on ? "on" : "off", misc_to_vconn(misc), misc_to_cc(misc));
+
+ return ret;
+}
+
+int qcom_pmic_typec_port_start_toggling(struct pmic_typec_port *pmic_typec_port,
+ enum typec_port_type port_type,
+ enum typec_cc_status cc)
+{
+ struct device *dev = pmic_typec_port->dev;
+ unsigned int misc;
+ u8 mode = 0;
+ unsigned long flags;
+ int ret;
+
+ switch (port_type) {
+ case TYPEC_PORT_SRC:
+ mode = EN_SRC_ONLY;
+ break;
+ case TYPEC_PORT_SNK:
+ mode = EN_SNK_ONLY;
+ break;
+ case TYPEC_PORT_DRP:
+ mode = EN_TRY_SNK;
+ break;
+ }
+
+ spin_lock_irqsave(&pmic_typec_port->lock, flags);
+
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MISC_STATUS_REG, &misc);
+ if (ret)
+ goto done;
+
+ dev_dbg(dev, "start_toggling: misc 0x%08x attached %d port_type %d current cc %d new %d\n",
+ misc, !!(misc & CC_ATTACHED), port_type, pmic_typec_port->cc, cc);
+
+ qcom_pmic_set_cc_debounce(pmic_typec_port);
+
+ /* force it to toggle at least once */
+ ret = regmap_write(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MODE_CFG_REG,
+ TYPEC_DISABLE_CMD);
+ if (ret)
+ goto done;
+
+ ret = regmap_write(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MODE_CFG_REG,
+ mode);
+done:
+ spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
+
+ return ret;
+}
+
+#define TYPEC_INTR_EN_CFG_1_MASK \
+ (TYPEC_LEGACY_CABLE_INT_EN | \
+ TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN | \
+ TYPEC_TRYSOURCE_DETECT_INT_EN | \
+ TYPEC_TRYSINK_DETECT_INT_EN | \
+ TYPEC_CCOUT_DETACH_INT_EN | \
+ TYPEC_CCOUT_ATTACH_INT_EN | \
+ TYPEC_VBUS_DEASSERT_INT_EN | \
+ TYPEC_VBUS_ASSERT_INT_EN)
+
+#define TYPEC_INTR_EN_CFG_2_MASK \
+ (TYPEC_STATE_MACHINE_CHANGE_INT_EN | TYPEC_VBUS_ERROR_INT_EN | \
+ TYPEC_DEBOUNCE_DONE_INT_EN)
+
+int qcom_pmic_typec_port_start(struct pmic_typec_port *pmic_typec_port,
+ struct tcpm_port *tcpm_port)
+{
+ int i;
+ int mask;
+ int ret;
+
+ /* Configure interrupt sources */
+ ret = regmap_write(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_INTERRUPT_EN_CFG_1_REG,
+ TYPEC_INTR_EN_CFG_1_MASK);
+ if (ret)
+ goto done;
+
+ ret = regmap_write(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_INTERRUPT_EN_CFG_2_REG,
+ TYPEC_INTR_EN_CFG_2_MASK);
+ if (ret)
+ goto done;
+
+ /* start in TRY_SNK mode */
+ ret = regmap_write(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MODE_CFG_REG, EN_TRY_SNK);
+ if (ret)
+ goto done;
+
+ /* Configure VCONN for software control */
+ ret = regmap_update_bits(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_VCONN_CONTROL_REG,
+ VCONN_EN_SRC | VCONN_EN_VALUE, VCONN_EN_SRC);
+ if (ret)
+ goto done;
+
+ /* Set CC threshold to 1.6 Volts | tPDdebounce = 10-20ms */
+ mask = SEL_SRC_UPPER_REF | USE_TPD_FOR_EXITING_ATTACHSRC;
+ ret = regmap_update_bits(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_EXIT_STATE_CFG_REG,
+ mask, mask);
+ if (ret)
+ goto done;
+
+ pmic_typec_port->tcpm_port = tcpm_port;
+
+ for (i = 0; i < pmic_typec_port->nr_irqs; i++)
+ enable_irq(pmic_typec_port->irq_data[i].irq);
+
+done:
+ return ret;
+}
+
+void qcom_pmic_typec_port_stop(struct pmic_typec_port *pmic_typec_port)
+{
+ int i;
+
+ for (i = 0; i < pmic_typec_port->nr_irqs; i++)
+ disable_irq(pmic_typec_port->irq_data[i].irq);
+}
+
+struct pmic_typec_port *qcom_pmic_typec_port_alloc(struct device *dev)
+{
+ return devm_kzalloc(dev, sizeof(struct pmic_typec_port), GFP_KERNEL);
+}
+
+int qcom_pmic_typec_port_probe(struct platform_device *pdev,
+ struct pmic_typec_port *pmic_typec_port,
+ struct pmic_typec_port_resources *res,
+ struct regmap *regmap,
+ u32 base)
+{
+ struct device *dev = &pdev->dev;
+ struct pmic_typec_port_irq_data *irq_data;
+ int i, ret, irq;
+
+ if (!res->nr_irqs || res->nr_irqs > PMIC_TYPEC_MAX_IRQS)
+ return -EINVAL;
+
+ irq_data = devm_kzalloc(dev, sizeof(*irq_data) * res->nr_irqs,
+ GFP_KERNEL);
+ if (!irq_data)
+ return -ENOMEM;
+
+ pmic_typec_port->vdd_vbus = devm_regulator_get(dev, "vdd-vbus");
+ if (IS_ERR(pmic_typec_port->vdd_vbus))
+ return PTR_ERR(pmic_typec_port->vdd_vbus);
+
+ pmic_typec_port->dev = dev;
+ pmic_typec_port->base = base;
+ pmic_typec_port->regmap = regmap;
+ pmic_typec_port->nr_irqs = res->nr_irqs;
+ pmic_typec_port->irq_data = irq_data;
+ spin_lock_init(&pmic_typec_port->lock);
+ INIT_DELAYED_WORK(&pmic_typec_port->cc_debounce_dwork,
+ qcom_pmic_typec_port_cc_debounce);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ for (i = 0; i < res->nr_irqs; i++, irq_data++) {
+ irq = platform_get_irq_byname(pdev,
+ res->irq_params[i].irq_name);
+ if (irq < 0)
+ return irq;
+
+ irq_data->pmic_typec_port = pmic_typec_port;
+ irq_data->irq = irq;
+ irq_data->virq = res->irq_params[i].virq;
+ ret = devm_request_threaded_irq(dev, irq, NULL, pmic_typec_port_isr,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN,
+ res->irq_params[i].irq_name,
+ irq_data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h
new file mode 100644
index 000000000000..d4d358c680b6
--- /dev/null
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Ltd. All rights reserved.
+ */
+#ifndef __QCOM_PMIC_TYPEC_H__
+#define __QCOM_PMIC_TYPEC_H__
+
+#include <linux/platform_device.h>
+#include <linux/usb/tcpm.h>
+
+#define TYPEC_SNK_STATUS_REG 0x06
+#define DETECTED_SNK_TYPE_MASK GENMASK(6, 0)
+#define SNK_DAM_MASK GENMASK(6, 4)
+#define SNK_DAM_500MA BIT(6)
+#define SNK_DAM_1500MA BIT(5)
+#define SNK_DAM_3000MA BIT(4)
+#define SNK_RP_STD BIT(3)
+#define SNK_RP_1P5 BIT(2)
+#define SNK_RP_3P0 BIT(1)
+#define SNK_RP_SHORT BIT(0)
+
+#define TYPEC_SRC_STATUS_REG 0x08
+#define DETECTED_SRC_TYPE_MASK GENMASK(4, 0)
+#define SRC_HIGH_BATT BIT(5)
+#define SRC_DEBUG_ACCESS BIT(4)
+#define SRC_RD_OPEN BIT(3)
+#define SRC_RD_RA_VCONN BIT(2)
+#define SRC_RA_OPEN BIT(1)
+#define AUDIO_ACCESS_RA_RA BIT(0)
+
+#define TYPEC_STATE_MACHINE_STATUS_REG 0x09
+#define TYPEC_ATTACH_DETACH_STATE BIT(5)
+
+#define TYPEC_SM_STATUS_REG 0x0A
+#define TYPEC_SM_VBUS_VSAFE5V BIT(5)
+#define TYPEC_SM_VBUS_VSAFE0V BIT(6)
+#define TYPEC_SM_USBIN_LT_LV BIT(7)
+
+#define TYPEC_MISC_STATUS_REG 0x0B
+#define TYPEC_WATER_DETECTION_STATUS BIT(7)
+#define SNK_SRC_MODE BIT(6)
+#define TYPEC_VBUS_DETECT BIT(5)
+#define TYPEC_VBUS_ERROR_STATUS BIT(4)
+#define TYPEC_DEBOUNCE_DONE BIT(3)
+#define CC_ORIENTATION BIT(1)
+#define CC_ATTACHED BIT(0)
+
+#define LEGACY_CABLE_STATUS_REG 0x0D
+#define TYPEC_LEGACY_CABLE_STATUS BIT(1)
+#define TYPEC_NONCOMP_LEGACY_CABLE_STATUS BIT(0)
+
+#define TYPEC_U_USB_STATUS_REG 0x0F
+#define U_USB_GROUND_NOVBUS BIT(6)
+#define U_USB_GROUND BIT(4)
+#define U_USB_FMB1 BIT(3)
+#define U_USB_FLOAT1 BIT(2)
+#define U_USB_FMB2 BIT(1)
+#define U_USB_FLOAT2 BIT(0)
+
+#define TYPEC_MODE_CFG_REG 0x44
+#define TYPEC_TRY_MODE_MASK GENMASK(4, 3)
+#define EN_TRY_SNK BIT(4)
+#define EN_TRY_SRC BIT(3)
+#define TYPEC_POWER_ROLE_CMD_MASK GENMASK(2, 0)
+#define EN_SRC_ONLY BIT(2)
+#define EN_SNK_ONLY BIT(1)
+#define TYPEC_DISABLE_CMD BIT(0)
+
+#define TYPEC_VCONN_CONTROL_REG 0x46
+#define VCONN_EN_ORIENTATION BIT(2)
+#define VCONN_EN_VALUE BIT(1)
+#define VCONN_EN_SRC BIT(0)
+
+#define TYPEC_CCOUT_CONTROL_REG 0x48
+#define TYPEC_CCOUT_BUFFER_EN BIT(2)
+#define TYPEC_CCOUT_VALUE BIT(1)
+#define TYPEC_CCOUT_SRC BIT(0)
+
+#define DEBUG_ACCESS_SRC_CFG_REG 0x4C
+#define EN_UNORIENTED_DEBUG_ACCESS_SRC BIT(0)
+
+#define TYPE_C_CRUDE_SENSOR_CFG_REG 0x4e
+#define EN_SRC_CRUDE_SENSOR BIT(1)
+#define EN_SNK_CRUDE_SENSOR BIT(0)
+
+#define TYPEC_EXIT_STATE_CFG_REG 0x50
+#define BYPASS_VSAFE0V_DURING_ROLE_SWAP BIT(3)
+#define SEL_SRC_UPPER_REF BIT(2)
+#define USE_TPD_FOR_EXITING_ATTACHSRC BIT(1)
+#define EXIT_SNK_BASED_ON_CC BIT(0)
+
+#define TYPEC_CURRSRC_CFG_REG 0x52
+#define TYPEC_SRC_RP_SEL_330UA BIT(1)
+#define TYPEC_SRC_RP_SEL_180UA BIT(0)
+#define TYPEC_SRC_RP_SEL_80UA 0
+#define TYPEC_SRC_RP_SEL_MASK GENMASK(1, 0)
+
+#define TYPEC_INTERRUPT_EN_CFG_1_REG 0x5E
+#define TYPEC_LEGACY_CABLE_INT_EN BIT(7)
+#define TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN BIT(6)
+#define TYPEC_TRYSOURCE_DETECT_INT_EN BIT(5)
+#define TYPEC_TRYSINK_DETECT_INT_EN BIT(4)
+#define TYPEC_CCOUT_DETACH_INT_EN BIT(3)
+#define TYPEC_CCOUT_ATTACH_INT_EN BIT(2)
+#define TYPEC_VBUS_DEASSERT_INT_EN BIT(1)
+#define TYPEC_VBUS_ASSERT_INT_EN BIT(0)
+
+#define TYPEC_INTERRUPT_EN_CFG_2_REG 0x60
+#define TYPEC_SRC_BATT_HPWR_INT_EN BIT(6)
+#define MICRO_USB_STATE_CHANGE_INT_EN BIT(5)
+#define TYPEC_STATE_MACHINE_CHANGE_INT_EN BIT(4)
+#define TYPEC_DEBUG_ACCESS_DETECT_INT_EN BIT(3)
+#define TYPEC_WATER_DETECTION_INT_EN BIT(2)
+#define TYPEC_VBUS_ERROR_INT_EN BIT(1)
+#define TYPEC_DEBOUNCE_DONE_INT_EN BIT(0)
+
+#define TYPEC_DEBOUNCE_OPTION_REG 0x62
+#define REDUCE_TCCDEBOUNCE_TO_2MS BIT(2)
+
+#define TYPE_C_SBU_CFG_REG 0x6A
+#define SEL_SBU1_ISRC_VAL 0x04
+#define SEL_SBU2_ISRC_VAL 0x01
+
+#define TYPEC_U_USB_CFG_REG 0x70
+#define EN_MICRO_USB_FACTORY_MODE BIT(1)
+#define EN_MICRO_USB_MODE BIT(0)
+
+#define TYPEC_PMI632_U_USB_WATER_PROTECTION_CFG_REG 0x72
+
+#define TYPEC_U_USB_WATER_PROTECTION_CFG_REG 0x73
+#define EN_MICRO_USB_WATER_PROTECTION BIT(4)
+#define MICRO_USB_DETECTION_ON_TIME_CFG_MASK GENMASK(3, 2)
+#define MICRO_USB_DETECTION_PERIOD_CFG_MASK GENMASK(1, 0)
+
+#define TYPEC_PMI632_MICRO_USB_MODE_REG 0x73
+#define MICRO_USB_MODE_ONLY BIT(0)
+
+/* Interrupt numbers */
+#define PMIC_TYPEC_OR_RID_IRQ 0x0
+#define PMIC_TYPEC_VPD_IRQ 0x1
+#define PMIC_TYPEC_CC_STATE_IRQ 0x2
+#define PMIC_TYPEC_VCONN_OC_IRQ 0x3
+#define PMIC_TYPEC_VBUS_IRQ 0x4
+#define PMIC_TYPEC_ATTACH_DETACH_IRQ 0x5
+#define PMIC_TYPEC_LEGACY_CABLE_IRQ 0x6
+#define PMIC_TYPEC_TRY_SNK_SRC_IRQ 0x7
+
+/* Resources */
+#define PMIC_TYPEC_MAX_IRQS 0x08
+
+struct pmic_typec_port_irq_params {
+ int virq;
+ char *irq_name;
+};
+
+struct pmic_typec_port_resources {
+ unsigned int nr_irqs;
+ struct pmic_typec_port_irq_params irq_params[PMIC_TYPEC_MAX_IRQS];
+};
+
+/* API */
+struct pmic_typec;
+
+struct pmic_typec_port *qcom_pmic_typec_port_alloc(struct device *dev);
+
+int qcom_pmic_typec_port_probe(struct platform_device *pdev,
+ struct pmic_typec_port *pmic_typec_port,
+ struct pmic_typec_port_resources *res,
+ struct regmap *regmap,
+ u32 base);
+
+int qcom_pmic_typec_port_start(struct pmic_typec_port *pmic_typec_port,
+ struct tcpm_port *tcpm_port);
+
+void qcom_pmic_typec_port_stop(struct pmic_typec_port *pmic_typec_port);
+
+int qcom_pmic_typec_port_get_cc(struct pmic_typec_port *pmic_typec_port,
+ enum typec_cc_status *cc1,
+ enum typec_cc_status *cc2);
+
+int qcom_pmic_typec_port_set_cc(struct pmic_typec_port *pmic_typec_port,
+ enum typec_cc_status cc);
+
+int qcom_pmic_typec_port_get_vbus(struct pmic_typec_port *pmic_typec_port);
+
+int qcom_pmic_typec_port_set_vconn(struct pmic_typec_port *pmic_typec_port, bool on);
+
+int qcom_pmic_typec_port_start_toggling(struct pmic_typec_port *pmic_typec_port,
+ enum typec_port_type port_type,
+ enum typec_cc_status cc);
+
+int qcom_pmic_typec_port_set_vbus(struct pmic_typec_port *pmic_typec_port, bool on);
+
+#endif /* __QCOM_PMIC_TYPE_C_PORT_H__ */
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index 8da23240afbe..fc708c289a73 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -895,7 +895,7 @@ static struct i2c_driver tcpci_i2c_driver = {
.name = "tcpci",
.of_match_table = of_match_ptr(tcpci_of_match),
},
- .probe_new = tcpci_probe,
+ .probe = tcpci_probe,
.remove = tcpci_remove,
.id_table = tcpci_id,
};
diff --git a/drivers/usb/typec/tcpm/tcpci_maxim_core.c b/drivers/usb/typec/tcpm/tcpci_maxim_core.c
index f32cda2a5e3a..9454b12a073c 100644
--- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c
+++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c
@@ -508,7 +508,7 @@ static struct i2c_driver max_tcpci_i2c_driver = {
.name = "maxtcpc",
.of_match_table = of_match_ptr(max_tcpci_of_match),
},
- .probe_new = max_tcpci_probe,
+ .probe = max_tcpci_probe,
.remove = max_tcpci_remove,
.id_table = max_tcpci_id,
};
diff --git a/drivers/usb/typec/tcpm/tcpci_mt6360.c b/drivers/usb/typec/tcpm/tcpci_mt6360.c
index 6fa8fd5c8041..02b7fd302265 100644
--- a/drivers/usb/typec/tcpm/tcpci_mt6360.c
+++ b/drivers/usb/typec/tcpm/tcpci_mt6360.c
@@ -178,13 +178,12 @@ static int mt6360_tcpc_probe(struct platform_device *pdev)
return 0;
}
-static int mt6360_tcpc_remove(struct platform_device *pdev)
+static void mt6360_tcpc_remove(struct platform_device *pdev)
{
struct mt6360_tcpc_info *mti = platform_get_drvdata(pdev);
disable_irq(mti->irq);
tcpci_unregister_port(mti->tcpci);
- return 0;
}
static int __maybe_unused mt6360_tcpc_suspend(struct device *dev)
@@ -222,7 +221,7 @@ static struct platform_driver mt6360_tcpc_driver = {
.of_match_table = mt6360_tcpc_of_id,
},
.probe = mt6360_tcpc_probe,
- .remove = mt6360_tcpc_remove,
+ .remove_new = mt6360_tcpc_remove,
};
module_platform_driver(mt6360_tcpc_driver);
diff --git a/drivers/usb/typec/tcpm/tcpci_mt6370.c b/drivers/usb/typec/tcpm/tcpci_mt6370.c
index c5bb201a5163..2a079464b398 100644
--- a/drivers/usb/typec/tcpm/tcpci_mt6370.c
+++ b/drivers/usb/typec/tcpm/tcpci_mt6370.c
@@ -178,12 +178,10 @@ static int mt6370_tcpc_probe(struct platform_device *pdev)
return 0;
}
-static int mt6370_tcpc_remove(struct platform_device *pdev)
+static void mt6370_tcpc_remove(struct platform_device *pdev)
{
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
-
- return 0;
}
static const struct of_device_id mt6370_tcpc_devid_table[] = {
@@ -198,7 +196,7 @@ static struct platform_driver mt6370_tcpc_driver = {
.of_match_table = mt6370_tcpc_devid_table,
},
.probe = mt6370_tcpc_probe,
- .remove = mt6370_tcpc_remove,
+ .remove_new = mt6370_tcpc_remove,
};
module_platform_driver(mt6370_tcpc_driver);
diff --git a/drivers/usb/typec/tcpm/tcpci_rt1711h.c b/drivers/usb/typec/tcpm/tcpci_rt1711h.c
index a0e9e3fe8564..17ebc5fb684f 100644
--- a/drivers/usb/typec/tcpm/tcpci_rt1711h.c
+++ b/drivers/usb/typec/tcpm/tcpci_rt1711h.c
@@ -412,7 +412,7 @@ static struct i2c_driver rt1711h_i2c_driver = {
.name = "rt1711h",
.of_match_table = of_match_ptr(rt1711h_of_match),
},
- .probe_new = rt1711h_probe,
+ .probe = rt1711h_probe,
.remove = rt1711h_remove,
.id_table = rt1711h_id,
};
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 3c6b0c8e2d3a..829d75ebab42 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -4885,7 +4885,8 @@ static void run_state_machine(struct tcpm_port *port)
break;
case PORT_RESET:
tcpm_reset_port(port);
- tcpm_set_cc(port, TYPEC_CC_OPEN);
+ tcpm_set_cc(port, tcpm_default_state(port) == SNK_UNATTACHED ?
+ TYPEC_CC_RD : tcpm_rp_cc(port));
tcpm_set_state(port, PORT_RESET_WAIT_OFF,
PD_T_ERROR_RECOVERY);
break;
@@ -6339,6 +6340,27 @@ static int tcpm_psy_get_current_now(struct tcpm_port *port,
return 0;
}
+static int tcpm_psy_get_input_power_limit(struct tcpm_port *port,
+ union power_supply_propval *val)
+{
+ unsigned int src_mv, src_ma, max_src_uw = 0;
+ unsigned int i, tmp;
+
+ for (i = 0; i < port->nr_source_caps; i++) {
+ u32 pdo = port->source_caps[i];
+
+ if (pdo_type(pdo) == PDO_TYPE_FIXED) {
+ src_mv = pdo_fixed_voltage(pdo);
+ src_ma = pdo_max_current(pdo);
+ tmp = src_mv * src_ma;
+ max_src_uw = tmp > max_src_uw ? tmp : max_src_uw;
+ }
+ }
+
+ val->intval = max_src_uw;
+ return 0;
+}
+
static int tcpm_psy_get_prop(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -6368,6 +6390,9 @@ static int tcpm_psy_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CURRENT_NOW:
ret = tcpm_psy_get_current_now(port, val);
break;
+ case POWER_SUPPLY_PROP_INPUT_POWER_LIMIT:
+ tcpm_psy_get_input_power_limit(port, val);
+ break;
default:
ret = -EINVAL;
break;
diff --git a/drivers/usb/typec/tcpm/wcove.c b/drivers/usb/typec/tcpm/wcove.c
index 20917d85d6f4..87d4abde0ea2 100644
--- a/drivers/usb/typec/tcpm/wcove.c
+++ b/drivers/usb/typec/tcpm/wcove.c
@@ -671,7 +671,7 @@ static int wcove_typec_probe(struct platform_device *pdev)
return 0;
}
-static int wcove_typec_remove(struct platform_device *pdev)
+static void wcove_typec_remove(struct platform_device *pdev)
{
struct wcove_typec *wcove = platform_get_drvdata(pdev);
unsigned int val;
@@ -684,8 +684,6 @@ static int wcove_typec_remove(struct platform_device *pdev)
tcpm_unregister_port(wcove->tcpm);
fwnode_remove_software_node(wcove->tcpc.fwnode);
-
- return 0;
}
static struct platform_driver wcove_typec_driver = {
@@ -693,7 +691,7 @@ static struct platform_driver wcove_typec_driver = {
.name = "bxt_wcove_usbc",
},
.probe = wcove_typec_probe,
- .remove = wcove_typec_remove,
+ .remove_new = wcove_typec_remove,
};
module_platform_driver(wcove_typec_driver);
diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c
index 603dbd44deba..37b56ce75f39 100644
--- a/drivers/usb/typec/tipd/core.c
+++ b/drivers/usb/typec/tipd/core.c
@@ -950,7 +950,7 @@ static struct i2c_driver tps6598x_i2c_driver = {
.pm = &tps6598x_pm_ops,
.of_match_table = tps6598x_of_match,
},
- .probe_new = tps6598x_probe,
+ .probe = tps6598x_probe,
.remove = tps6598x_remove,
.id_table = tps6598x_id,
};
diff --git a/drivers/usb/typec/ucsi/psy.c b/drivers/usb/typec/ucsi/psy.c
index 56bf56517f75..384b42267f1f 100644
--- a/drivers/usb/typec/ucsi/psy.c
+++ b/drivers/usb/typec/ucsi/psy.c
@@ -27,8 +27,20 @@ static enum power_supply_property ucsi_psy_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_SCOPE,
};
+static int ucsi_psy_get_scope(struct ucsi_connector *con,
+ union power_supply_propval *val)
+{
+ u8 scope = POWER_SUPPLY_SCOPE_UNKNOWN;
+ struct device *dev = con->ucsi->dev;
+
+ device_property_read_u8(dev, "scope", &scope);
+ val->intval = scope;
+ return 0;
+}
+
static int ucsi_psy_get_online(struct ucsi_connector *con,
union power_supply_propval *val)
{
@@ -194,6 +206,8 @@ static int ucsi_psy_get_prop(struct power_supply *psy,
return ucsi_psy_get_current_max(con, val);
case POWER_SUPPLY_PROP_CURRENT_NOW:
return ucsi_psy_get_current_now(con, val);
+ case POWER_SUPPLY_PROP_SCOPE:
+ return ucsi_psy_get_scope(con, val);
default:
return -EINVAL;
}
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index b664ecbb798b..9b6d6b14431f 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -812,6 +812,23 @@ static void ucsi_partner_change(struct ucsi_connector *con)
break;
}
+ if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
+ switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
+ case UCSI_CONSTAT_PARTNER_TYPE_DEBUG:
+ typec_set_mode(con->port, TYPEC_MODE_DEBUG);
+ break;
+ case UCSI_CONSTAT_PARTNER_TYPE_AUDIO:
+ typec_set_mode(con->port, TYPEC_MODE_AUDIO);
+ break;
+ default:
+ if (UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) ==
+ UCSI_CONSTAT_PARTNER_FLAG_USB)
+ typec_set_mode(con->port, TYPEC_STATE_USB);
+ }
+ } else {
+ typec_set_mode(con->port, TYPEC_STATE_SAFE);
+ }
+
/* Only notify USB controller if partner supports USB data */
if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB))
u_role = USB_ROLE_NONE;
diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c
index 217355f1f9b9..6bbf490ac401 100644
--- a/drivers/usb/typec/ucsi/ucsi_acpi.c
+++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
@@ -212,7 +212,7 @@ static int ucsi_acpi_probe(struct platform_device *pdev)
return 0;
}
-static int ucsi_acpi_remove(struct platform_device *pdev)
+static void ucsi_acpi_remove(struct platform_device *pdev)
{
struct ucsi_acpi *ua = platform_get_drvdata(pdev);
@@ -221,8 +221,6 @@ static int ucsi_acpi_remove(struct platform_device *pdev)
acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev), ACPI_DEVICE_NOTIFY,
ucsi_acpi_notify);
-
- return 0;
}
static int ucsi_acpi_resume(struct device *dev)
@@ -247,7 +245,7 @@ static struct platform_driver ucsi_acpi_platform_driver = {
.acpi_match_table = ACPI_PTR(ucsi_acpi_match),
},
.probe = ucsi_acpi_probe,
- .remove = ucsi_acpi_remove,
+ .remove_new = ucsi_acpi_remove,
};
module_platform_driver(ucsi_acpi_platform_driver);
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index e0ed465bd518..607061a37eca 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -1495,7 +1495,7 @@ static struct i2c_driver ucsi_ccg_driver = {
.acpi_match_table = amd_i2c_ucsi_match,
.of_match_table = ucsi_ccg_of_match_table,
},
- .probe_new = ucsi_ccg_probe,
+ .probe = ucsi_ccg_probe,
.remove = ucsi_ccg_remove,
.id_table = ucsi_ccg_device_id,
};
diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c
index b454a5159896..1fe9cb5b6bd9 100644
--- a/drivers/usb/typec/ucsi/ucsi_glink.c
+++ b/drivers/usb/typec/ucsi/ucsi_glink.c
@@ -245,7 +245,7 @@ static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv)
struct pmic_glink_ucsi *ucsi = priv;
const struct pmic_glink_hdr *hdr = data;
- switch (hdr->opcode) {
+ switch (le32_to_cpu(hdr->opcode)) {
case UC_UCSI_READ_BUF_REQ:
pmic_glink_ucsi_read_ack(ucsi, data, len);
break;
diff --git a/drivers/usb/typec/ucsi/ucsi_stm32g0.c b/drivers/usb/typec/ucsi/ucsi_stm32g0.c
index 93fead0096b7..93d7806681cf 100644
--- a/drivers/usb/typec/ucsi/ucsi_stm32g0.c
+++ b/drivers/usb/typec/ucsi/ucsi_stm32g0.c
@@ -763,7 +763,7 @@ static struct i2c_driver ucsi_stm32g0_i2c_driver = {
.of_match_table = of_match_ptr(ucsi_stm32g0_typec_of_match),
.pm = pm_sleep_ptr(&ucsi_stm32g0_pm_ops),
},
- .probe_new = ucsi_stm32g0_probe,
+ .probe = ucsi_stm32g0_probe,
.remove = ucsi_stm32g0_remove,
.id_table = ucsi_stm32g0_typec_i2c_devid
};
diff --git a/drivers/usb/typec/wusb3801.c b/drivers/usb/typec/wusb3801.c
index a43a18d4b02e..6062875fb04a 100644
--- a/drivers/usb/typec/wusb3801.c
+++ b/drivers/usb/typec/wusb3801.c
@@ -420,7 +420,7 @@ static const struct of_device_id wusb3801_of_match[] = {
MODULE_DEVICE_TABLE(of, wusb3801_of_match);
static struct i2c_driver wusb3801_driver = {
- .probe_new = wusb3801_probe,
+ .probe = wusb3801_probe,
.remove = wusb3801_remove,
.driver = {
.name = "wusb3801",
diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c
index e8c3131a8543..0a6624d37929 100644
--- a/drivers/usb/usbip/stub_main.c
+++ b/drivers/usb/usbip/stub_main.c
@@ -167,15 +167,13 @@ static ssize_t match_busid_show(struct device_driver *drv, char *buf)
static ssize_t match_busid_store(struct device_driver *dev, const char *buf,
size_t count)
{
- int len;
char busid[BUSID_SIZE];
if (count < 5)
return -EINVAL;
/* busid needs to include \0 termination */
- len = strlcpy(busid, buf + 4, BUSID_SIZE);
- if (sizeof(busid) <= len)
+ if (strscpy(busid, buf + 4, BUSID_SIZE) < 0)
return -EINVAL;
if (!strncmp(buf, "add ", 4)) {
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index 233265550fc6..37d1fc34e8a5 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -1393,7 +1393,7 @@ put_usb2_hcd:
return ret;
}
-static int vhci_hcd_remove(struct platform_device *pdev)
+static void vhci_hcd_remove(struct platform_device *pdev)
{
struct vhci *vhci = *((void **)dev_get_platdata(&pdev->dev));
@@ -1410,8 +1410,6 @@ static int vhci_hcd_remove(struct platform_device *pdev)
vhci->vhci_hcd_hs = NULL;
vhci->vhci_hcd_ss = NULL;
-
- return 0;
}
#ifdef CONFIG_PM
@@ -1485,7 +1483,7 @@ static int vhci_hcd_resume(struct platform_device *pdev)
static struct platform_driver vhci_driver = {
.probe = vhci_hcd_probe,
- .remove = vhci_hcd_remove,
+ .remove_new = vhci_hcd_remove,
.suspend = vhci_hcd_suspend,
.resume = vhci_hcd_resume,
.driver = {
diff --git a/drivers/vdpa/Kconfig b/drivers/vdpa/Kconfig
index cd6ad92f3f05..656c1cb541de 100644
--- a/drivers/vdpa/Kconfig
+++ b/drivers/vdpa/Kconfig
@@ -116,4 +116,14 @@ config ALIBABA_ENI_VDPA
This driver includes a HW monitor device that
reads health values from the DPU.
+config PDS_VDPA
+ tristate "vDPA driver for AMD/Pensando DSC devices"
+ select VIRTIO_PCI_LIB
+ depends on PCI_MSI
+ depends on PDS_CORE
+ help
+ vDPA network driver for AMD/Pensando's PDS Core devices.
+ With this driver, the VirtIO dataplane can be
+ offloaded to an AMD/Pensando DSC device.
+
endif # VDPA
diff --git a/drivers/vdpa/Makefile b/drivers/vdpa/Makefile
index 59396ff2a318..8f53c6f3cca7 100644
--- a/drivers/vdpa/Makefile
+++ b/drivers/vdpa/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_MLX5_VDPA) += mlx5/
obj-$(CONFIG_VP_VDPA) += virtio_pci/
obj-$(CONFIG_ALIBABA_ENI_VDPA) += alibaba/
obj-$(CONFIG_SNET_VDPA) += solidrun/
+obj-$(CONFIG_PDS_VDPA) += pds/
diff --git a/drivers/vdpa/ifcvf/ifcvf_base.c b/drivers/vdpa/ifcvf/ifcvf_base.c
index 5563b3a773c7..060f837a4f9f 100644
--- a/drivers/vdpa/ifcvf/ifcvf_base.c
+++ b/drivers/vdpa/ifcvf/ifcvf_base.c
@@ -69,6 +69,37 @@ static int ifcvf_read_config_range(struct pci_dev *dev,
return 0;
}
+static u16 ifcvf_get_vq_size(struct ifcvf_hw *hw, u16 qid)
+{
+ u16 queue_size;
+
+ vp_iowrite16(qid, &hw->common_cfg->queue_select);
+ queue_size = vp_ioread16(&hw->common_cfg->queue_size);
+
+ return queue_size;
+}
+
+/* This function returns the max allowed safe size for
+ * all virtqueues. It is the minimal size that can be
+ * suppprted by all virtqueues.
+ */
+u16 ifcvf_get_max_vq_size(struct ifcvf_hw *hw)
+{
+ u16 queue_size, max_size, qid;
+
+ max_size = ifcvf_get_vq_size(hw, 0);
+ for (qid = 1; qid < hw->nr_vring; qid++) {
+ queue_size = ifcvf_get_vq_size(hw, qid);
+ /* 0 means the queue is unavailable */
+ if (!queue_size)
+ continue;
+
+ max_size = min(queue_size, max_size);
+ }
+
+ return max_size;
+}
+
int ifcvf_init_hw(struct ifcvf_hw *hw, struct pci_dev *pdev)
{
struct virtio_pci_cap cap;
@@ -134,6 +165,9 @@ next:
}
hw->nr_vring = vp_ioread16(&hw->common_cfg->num_queues);
+ hw->vring = kzalloc(sizeof(struct vring_info) * hw->nr_vring, GFP_KERNEL);
+ if (!hw->vring)
+ return -ENOMEM;
for (i = 0; i < hw->nr_vring; i++) {
vp_iowrite16(i, &hw->common_cfg->queue_select);
@@ -170,21 +204,9 @@ void ifcvf_set_status(struct ifcvf_hw *hw, u8 status)
void ifcvf_reset(struct ifcvf_hw *hw)
{
- hw->config_cb.callback = NULL;
- hw->config_cb.private = NULL;
-
ifcvf_set_status(hw, 0);
- /* flush set_status, make sure VF is stopped, reset */
- ifcvf_get_status(hw);
-}
-
-static void ifcvf_add_status(struct ifcvf_hw *hw, u8 status)
-{
- if (status != 0)
- status |= ifcvf_get_status(hw);
-
- ifcvf_set_status(hw, status);
- ifcvf_get_status(hw);
+ while (ifcvf_get_status(hw))
+ msleep(1);
}
u64 ifcvf_get_hw_features(struct ifcvf_hw *hw)
@@ -204,11 +226,29 @@ u64 ifcvf_get_hw_features(struct ifcvf_hw *hw)
return features;
}
-u64 ifcvf_get_features(struct ifcvf_hw *hw)
+/* return provisioned vDPA dev features */
+u64 ifcvf_get_dev_features(struct ifcvf_hw *hw)
{
return hw->dev_features;
}
+u64 ifcvf_get_driver_features(struct ifcvf_hw *hw)
+{
+ struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg;
+ u32 features_lo, features_hi;
+ u64 features;
+
+ vp_iowrite32(0, &cfg->device_feature_select);
+ features_lo = vp_ioread32(&cfg->guest_feature);
+
+ vp_iowrite32(1, &cfg->device_feature_select);
+ features_hi = vp_ioread32(&cfg->guest_feature);
+
+ features = ((u64)features_hi << 32) | features_lo;
+
+ return features;
+}
+
int ifcvf_verify_min_features(struct ifcvf_hw *hw, u64 features)
{
if (!(features & BIT_ULL(VIRTIO_F_ACCESS_PLATFORM)) && features) {
@@ -275,7 +315,7 @@ void ifcvf_write_dev_config(struct ifcvf_hw *hw, u64 offset,
vp_iowrite8(*p++, hw->dev_cfg + offset + i);
}
-static void ifcvf_set_features(struct ifcvf_hw *hw, u64 features)
+void ifcvf_set_driver_features(struct ifcvf_hw *hw, u64 features)
{
struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg;
@@ -286,105 +326,104 @@ static void ifcvf_set_features(struct ifcvf_hw *hw, u64 features)
vp_iowrite32(features >> 32, &cfg->guest_feature);
}
-static int ifcvf_config_features(struct ifcvf_hw *hw)
-{
- ifcvf_set_features(hw, hw->req_features);
- ifcvf_add_status(hw, VIRTIO_CONFIG_S_FEATURES_OK);
-
- if (!(ifcvf_get_status(hw) & VIRTIO_CONFIG_S_FEATURES_OK)) {
- IFCVF_ERR(hw->pdev, "Failed to set FEATURES_OK status\n");
- return -EIO;
- }
-
- return 0;
-}
-
u16 ifcvf_get_vq_state(struct ifcvf_hw *hw, u16 qid)
{
- struct ifcvf_lm_cfg __iomem *ifcvf_lm;
- void __iomem *avail_idx_addr;
+ struct ifcvf_lm_cfg __iomem *lm_cfg = hw->lm_cfg;
u16 last_avail_idx;
- u32 q_pair_id;
- ifcvf_lm = (struct ifcvf_lm_cfg __iomem *)hw->lm_cfg;
- q_pair_id = qid / 2;
- avail_idx_addr = &ifcvf_lm->vring_lm_cfg[q_pair_id].idx_addr[qid % 2];
- last_avail_idx = vp_ioread16(avail_idx_addr);
+ last_avail_idx = vp_ioread16(&lm_cfg->vq_state_region + qid * 2);
return last_avail_idx;
}
int ifcvf_set_vq_state(struct ifcvf_hw *hw, u16 qid, u16 num)
{
- struct ifcvf_lm_cfg __iomem *ifcvf_lm;
- void __iomem *avail_idx_addr;
- u32 q_pair_id;
+ struct ifcvf_lm_cfg __iomem *lm_cfg = hw->lm_cfg;
- ifcvf_lm = (struct ifcvf_lm_cfg __iomem *)hw->lm_cfg;
- q_pair_id = qid / 2;
- avail_idx_addr = &ifcvf_lm->vring_lm_cfg[q_pair_id].idx_addr[qid % 2];
- hw->vring[qid].last_avail_idx = num;
- vp_iowrite16(num, avail_idx_addr);
+ vp_iowrite16(num, &lm_cfg->vq_state_region + qid * 2);
return 0;
}
-static int ifcvf_hw_enable(struct ifcvf_hw *hw)
+void ifcvf_set_vq_num(struct ifcvf_hw *hw, u16 qid, u32 num)
{
- struct virtio_pci_common_cfg __iomem *cfg;
- u32 i;
+ struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg;
- cfg = hw->common_cfg;
- for (i = 0; i < hw->nr_vring; i++) {
- if (!hw->vring[i].ready)
- break;
+ vp_iowrite16(qid, &cfg->queue_select);
+ vp_iowrite16(num, &cfg->queue_size);
+}
- vp_iowrite16(i, &cfg->queue_select);
- vp_iowrite64_twopart(hw->vring[i].desc, &cfg->queue_desc_lo,
- &cfg->queue_desc_hi);
- vp_iowrite64_twopart(hw->vring[i].avail, &cfg->queue_avail_lo,
- &cfg->queue_avail_hi);
- vp_iowrite64_twopart(hw->vring[i].used, &cfg->queue_used_lo,
- &cfg->queue_used_hi);
- vp_iowrite16(hw->vring[i].size, &cfg->queue_size);
- ifcvf_set_vq_state(hw, i, hw->vring[i].last_avail_idx);
- vp_iowrite16(1, &cfg->queue_enable);
- }
+int ifcvf_set_vq_address(struct ifcvf_hw *hw, u16 qid, u64 desc_area,
+ u64 driver_area, u64 device_area)
+{
+ struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg;
+
+ vp_iowrite16(qid, &cfg->queue_select);
+ vp_iowrite64_twopart(desc_area, &cfg->queue_desc_lo,
+ &cfg->queue_desc_hi);
+ vp_iowrite64_twopart(driver_area, &cfg->queue_avail_lo,
+ &cfg->queue_avail_hi);
+ vp_iowrite64_twopart(device_area, &cfg->queue_used_lo,
+ &cfg->queue_used_hi);
return 0;
}
-static void ifcvf_hw_disable(struct ifcvf_hw *hw)
+bool ifcvf_get_vq_ready(struct ifcvf_hw *hw, u16 qid)
{
- u32 i;
+ struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg;
+ u16 queue_enable;
- ifcvf_set_config_vector(hw, VIRTIO_MSI_NO_VECTOR);
- for (i = 0; i < hw->nr_vring; i++) {
- ifcvf_set_vq_vector(hw, i, VIRTIO_MSI_NO_VECTOR);
- }
+ vp_iowrite16(qid, &cfg->queue_select);
+ queue_enable = vp_ioread16(&cfg->queue_enable);
+
+ return (bool)queue_enable;
}
-int ifcvf_start_hw(struct ifcvf_hw *hw)
+void ifcvf_set_vq_ready(struct ifcvf_hw *hw, u16 qid, bool ready)
{
- ifcvf_reset(hw);
- ifcvf_add_status(hw, VIRTIO_CONFIG_S_ACKNOWLEDGE);
- ifcvf_add_status(hw, VIRTIO_CONFIG_S_DRIVER);
+ struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg;
- if (ifcvf_config_features(hw) < 0)
- return -EINVAL;
+ vp_iowrite16(qid, &cfg->queue_select);
+ vp_iowrite16(ready, &cfg->queue_enable);
+}
- if (ifcvf_hw_enable(hw) < 0)
- return -EINVAL;
+static void ifcvf_reset_vring(struct ifcvf_hw *hw)
+{
+ u16 qid;
- ifcvf_add_status(hw, VIRTIO_CONFIG_S_DRIVER_OK);
+ for (qid = 0; qid < hw->nr_vring; qid++) {
+ hw->vring[qid].cb.callback = NULL;
+ hw->vring[qid].cb.private = NULL;
+ ifcvf_set_vq_vector(hw, qid, VIRTIO_MSI_NO_VECTOR);
+ }
+}
- return 0;
+static void ifcvf_reset_config_handler(struct ifcvf_hw *hw)
+{
+ hw->config_cb.callback = NULL;
+ hw->config_cb.private = NULL;
+ ifcvf_set_config_vector(hw, VIRTIO_MSI_NO_VECTOR);
+}
+
+static void ifcvf_synchronize_irq(struct ifcvf_hw *hw)
+{
+ u32 nvectors = hw->num_msix_vectors;
+ struct pci_dev *pdev = hw->pdev;
+ int i, irq;
+
+ for (i = 0; i < nvectors; i++) {
+ irq = pci_irq_vector(pdev, i);
+ if (irq >= 0)
+ synchronize_irq(irq);
+ }
}
-void ifcvf_stop_hw(struct ifcvf_hw *hw)
+void ifcvf_stop(struct ifcvf_hw *hw)
{
- ifcvf_hw_disable(hw);
- ifcvf_reset(hw);
+ ifcvf_synchronize_irq(hw);
+ ifcvf_reset_vring(hw);
+ ifcvf_reset_config_handler(hw);
}
void ifcvf_notify_queue(struct ifcvf_hw *hw, u16 qid)
diff --git a/drivers/vdpa/ifcvf/ifcvf_base.h b/drivers/vdpa/ifcvf/ifcvf_base.h
index c20d1c40214e..b57849c643f6 100644
--- a/drivers/vdpa/ifcvf/ifcvf_base.h
+++ b/drivers/vdpa/ifcvf/ifcvf_base.h
@@ -24,15 +24,9 @@
#define N3000_DEVICE_ID 0x1041
#define N3000_SUBSYS_DEVICE_ID 0x001A
-/* Max 8 data queue pairs(16 queues) and one control vq for now. */
-#define IFCVF_MAX_QUEUES 17
-
#define IFCVF_QUEUE_ALIGNMENT PAGE_SIZE
-#define IFCVF_QUEUE_MAX 32768
#define IFCVF_PCI_MAX_RESOURCE 6
-#define IFCVF_LM_CFG_SIZE 0x40
-#define IFCVF_LM_RING_STATE_OFFSET 0x20
#define IFCVF_LM_BAR 4
#define IFCVF_ERR(pdev, fmt, ...) dev_err(&pdev->dev, fmt, ##__VA_ARGS__)
@@ -47,12 +41,7 @@
#define MSIX_VECTOR_DEV_SHARED 3
struct vring_info {
- u64 desc;
- u64 avail;
- u64 used;
- u16 size;
u16 last_avail_idx;
- bool ready;
void __iomem *notify_addr;
phys_addr_t notify_pa;
u32 irq;
@@ -60,10 +49,18 @@ struct vring_info {
char msix_name[256];
};
+struct ifcvf_lm_cfg {
+ __le64 control;
+ __le64 status;
+ __le64 lm_mem_log_start_addr;
+ __le64 lm_mem_log_end_addr;
+ __le16 vq_state_region;
+};
+
struct ifcvf_hw {
u8 __iomem *isr;
/* Live migration */
- u8 __iomem *lm_cfg;
+ struct ifcvf_lm_cfg __iomem *lm_cfg;
/* Notification bar number */
u8 notify_bar;
u8 msix_vector_status;
@@ -74,13 +71,12 @@ struct ifcvf_hw {
phys_addr_t notify_base_pa;
u32 notify_off_multiplier;
u32 dev_type;
- u64 req_features;
u64 hw_features;
/* provisioned device features */
u64 dev_features;
struct virtio_pci_common_cfg __iomem *common_cfg;
void __iomem *dev_cfg;
- struct vring_info vring[IFCVF_MAX_QUEUES];
+ struct vring_info *vring;
void __iomem * const *base;
char config_msix_name[256];
struct vdpa_callback config_cb;
@@ -88,6 +84,7 @@ struct ifcvf_hw {
int vqs_reused_irq;
u16 nr_vring;
/* VIRTIO_PCI_CAP_DEVICE_CFG size */
+ u32 num_msix_vectors;
u32 cap_dev_config_size;
struct pci_dev *pdev;
};
@@ -98,16 +95,6 @@ struct ifcvf_adapter {
struct ifcvf_hw *vf;
};
-struct ifcvf_vring_lm_cfg {
- u32 idx_addr[2];
- u8 reserved[IFCVF_LM_CFG_SIZE - 8];
-};
-
-struct ifcvf_lm_cfg {
- u8 reserved[IFCVF_LM_RING_STATE_OFFSET];
- struct ifcvf_vring_lm_cfg vring_lm_cfg[IFCVF_MAX_QUEUES];
-};
-
struct ifcvf_vdpa_mgmt_dev {
struct vdpa_mgmt_dev mdev;
struct ifcvf_hw vf;
@@ -116,8 +103,7 @@ struct ifcvf_vdpa_mgmt_dev {
};
int ifcvf_init_hw(struct ifcvf_hw *hw, struct pci_dev *dev);
-int ifcvf_start_hw(struct ifcvf_hw *hw);
-void ifcvf_stop_hw(struct ifcvf_hw *hw);
+void ifcvf_stop(struct ifcvf_hw *hw);
void ifcvf_notify_queue(struct ifcvf_hw *hw, u16 qid);
void ifcvf_read_dev_config(struct ifcvf_hw *hw, u64 offset,
void *dst, int length);
@@ -127,7 +113,7 @@ u8 ifcvf_get_status(struct ifcvf_hw *hw);
void ifcvf_set_status(struct ifcvf_hw *hw, u8 status);
void io_write64_twopart(u64 val, u32 *lo, u32 *hi);
void ifcvf_reset(struct ifcvf_hw *hw);
-u64 ifcvf_get_features(struct ifcvf_hw *hw);
+u64 ifcvf_get_dev_features(struct ifcvf_hw *hw);
u64 ifcvf_get_hw_features(struct ifcvf_hw *hw);
int ifcvf_verify_min_features(struct ifcvf_hw *hw, u64 features);
u16 ifcvf_get_vq_state(struct ifcvf_hw *hw, u16 qid);
@@ -137,4 +123,12 @@ int ifcvf_probed_virtio_net(struct ifcvf_hw *hw);
u32 ifcvf_get_config_size(struct ifcvf_hw *hw);
u16 ifcvf_set_vq_vector(struct ifcvf_hw *hw, u16 qid, int vector);
u16 ifcvf_set_config_vector(struct ifcvf_hw *hw, int vector);
+void ifcvf_set_vq_num(struct ifcvf_hw *hw, u16 qid, u32 num);
+int ifcvf_set_vq_address(struct ifcvf_hw *hw, u16 qid, u64 desc_area,
+ u64 driver_area, u64 device_area);
+bool ifcvf_get_vq_ready(struct ifcvf_hw *hw, u16 qid);
+void ifcvf_set_vq_ready(struct ifcvf_hw *hw, u16 qid, bool ready);
+void ifcvf_set_driver_features(struct ifcvf_hw *hw, u64 features);
+u64 ifcvf_get_driver_features(struct ifcvf_hw *hw);
+u16 ifcvf_get_max_vq_size(struct ifcvf_hw *hw);
#endif /* _IFCVF_H_ */
diff --git a/drivers/vdpa/ifcvf/ifcvf_main.c b/drivers/vdpa/ifcvf/ifcvf_main.c
index 7f78c47e40d6..e98fa8100f3c 100644
--- a/drivers/vdpa/ifcvf/ifcvf_main.c
+++ b/drivers/vdpa/ifcvf/ifcvf_main.c
@@ -125,6 +125,7 @@ static void ifcvf_free_irq(struct ifcvf_hw *vf)
ifcvf_free_vq_irq(vf);
ifcvf_free_config_irq(vf);
ifcvf_free_irq_vectors(pdev);
+ vf->num_msix_vectors = 0;
}
/* ifcvf MSIX vectors allocator, this helper tries to allocate
@@ -343,56 +344,11 @@ static int ifcvf_request_irq(struct ifcvf_hw *vf)
if (ret)
return ret;
- return 0;
-}
-
-static int ifcvf_start_datapath(struct ifcvf_adapter *adapter)
-{
- struct ifcvf_hw *vf = adapter->vf;
- u8 status;
- int ret;
-
- ret = ifcvf_start_hw(vf);
- if (ret < 0) {
- status = ifcvf_get_status(vf);
- status |= VIRTIO_CONFIG_S_FAILED;
- ifcvf_set_status(vf, status);
- }
-
- return ret;
-}
-
-static int ifcvf_stop_datapath(struct ifcvf_adapter *adapter)
-{
- struct ifcvf_hw *vf = adapter->vf;
- int i;
-
- for (i = 0; i < vf->nr_vring; i++)
- vf->vring[i].cb.callback = NULL;
-
- ifcvf_stop_hw(vf);
+ vf->num_msix_vectors = nvectors;
return 0;
}
-static void ifcvf_reset_vring(struct ifcvf_adapter *adapter)
-{
- struct ifcvf_hw *vf = adapter->vf;
- int i;
-
- for (i = 0; i < vf->nr_vring; i++) {
- vf->vring[i].last_avail_idx = 0;
- vf->vring[i].desc = 0;
- vf->vring[i].avail = 0;
- vf->vring[i].used = 0;
- vf->vring[i].ready = 0;
- vf->vring[i].cb.callback = NULL;
- vf->vring[i].cb.private = NULL;
- }
-
- ifcvf_reset(vf);
-}
-
static struct ifcvf_adapter *vdpa_to_adapter(struct vdpa_device *vdpa_dev)
{
return container_of(vdpa_dev, struct ifcvf_adapter, vdpa);
@@ -414,7 +370,7 @@ static u64 ifcvf_vdpa_get_device_features(struct vdpa_device *vdpa_dev)
u64 features;
if (type == VIRTIO_ID_NET || type == VIRTIO_ID_BLOCK)
- features = ifcvf_get_features(vf);
+ features = ifcvf_get_dev_features(vf);
else {
features = 0;
IFCVF_ERR(pdev, "VIRTIO ID %u not supported\n", vf->dev_type);
@@ -432,7 +388,7 @@ static int ifcvf_vdpa_set_driver_features(struct vdpa_device *vdpa_dev, u64 feat
if (ret)
return ret;
- vf->req_features = features;
+ ifcvf_set_driver_features(vf, features);
return 0;
}
@@ -440,8 +396,11 @@ static int ifcvf_vdpa_set_driver_features(struct vdpa_device *vdpa_dev, u64 feat
static u64 ifcvf_vdpa_get_driver_features(struct vdpa_device *vdpa_dev)
{
struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
+ u64 features;
+
+ features = ifcvf_get_driver_features(vf);
- return vf->req_features;
+ return features;
}
static u8 ifcvf_vdpa_get_status(struct vdpa_device *vdpa_dev)
@@ -453,13 +412,11 @@ static u8 ifcvf_vdpa_get_status(struct vdpa_device *vdpa_dev)
static void ifcvf_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
{
- struct ifcvf_adapter *adapter;
struct ifcvf_hw *vf;
u8 status_old;
int ret;
vf = vdpa_to_vf(vdpa_dev);
- adapter = vdpa_to_adapter(vdpa_dev);
status_old = ifcvf_get_status(vf);
if (status_old == status)
@@ -469,16 +426,9 @@ static void ifcvf_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
!(status_old & VIRTIO_CONFIG_S_DRIVER_OK)) {
ret = ifcvf_request_irq(vf);
if (ret) {
- status = ifcvf_get_status(vf);
- status |= VIRTIO_CONFIG_S_FAILED;
- ifcvf_set_status(vf, status);
+ IFCVF_ERR(vf->pdev, "failed to request irq with error %d\n", ret);
return;
}
-
- if (ifcvf_start_datapath(adapter) < 0)
- IFCVF_ERR(adapter->pdev,
- "Failed to set ifcvf vdpa status %u\n",
- status);
}
ifcvf_set_status(vf, status);
@@ -486,30 +436,24 @@ static void ifcvf_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
static int ifcvf_vdpa_reset(struct vdpa_device *vdpa_dev)
{
- struct ifcvf_adapter *adapter;
- struct ifcvf_hw *vf;
- u8 status_old;
-
- vf = vdpa_to_vf(vdpa_dev);
- adapter = vdpa_to_adapter(vdpa_dev);
- status_old = ifcvf_get_status(vf);
+ struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
+ u8 status = ifcvf_get_status(vf);
- if (status_old == 0)
- return 0;
+ ifcvf_stop(vf);
- if (status_old & VIRTIO_CONFIG_S_DRIVER_OK) {
- ifcvf_stop_datapath(adapter);
+ if (status & VIRTIO_CONFIG_S_DRIVER_OK)
ifcvf_free_irq(vf);
- }
- ifcvf_reset_vring(adapter);
+ ifcvf_reset(vf);
return 0;
}
static u16 ifcvf_vdpa_get_vq_num_max(struct vdpa_device *vdpa_dev)
{
- return IFCVF_QUEUE_MAX;
+ struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
+
+ return ifcvf_get_max_vq_size(vf);
}
static int ifcvf_vdpa_get_vq_state(struct vdpa_device *vdpa_dev, u16 qid,
@@ -542,14 +486,14 @@ static void ifcvf_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev,
{
struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
- vf->vring[qid].ready = ready;
+ ifcvf_set_vq_ready(vf, qid, ready);
}
static bool ifcvf_vdpa_get_vq_ready(struct vdpa_device *vdpa_dev, u16 qid)
{
struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
- return vf->vring[qid].ready;
+ return ifcvf_get_vq_ready(vf, qid);
}
static void ifcvf_vdpa_set_vq_num(struct vdpa_device *vdpa_dev, u16 qid,
@@ -557,7 +501,7 @@ static void ifcvf_vdpa_set_vq_num(struct vdpa_device *vdpa_dev, u16 qid,
{
struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
- vf->vring[qid].size = num;
+ ifcvf_set_vq_num(vf, qid, num);
}
static int ifcvf_vdpa_set_vq_address(struct vdpa_device *vdpa_dev, u16 qid,
@@ -566,11 +510,7 @@ static int ifcvf_vdpa_set_vq_address(struct vdpa_device *vdpa_dev, u16 qid,
{
struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
- vf->vring[qid].desc = desc_area;
- vf->vring[qid].avail = driver_area;
- vf->vring[qid].used = device_area;
-
- return 0;
+ return ifcvf_set_vq_address(vf, qid, desc_area, driver_area, device_area);
}
static void ifcvf_vdpa_kick_vq(struct vdpa_device *vdpa_dev, u16 qid)
@@ -892,6 +832,7 @@ static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
err:
+ kfree(ifcvf_mgmt_dev->vf.vring);
kfree(ifcvf_mgmt_dev);
return ret;
}
@@ -902,6 +843,7 @@ static void ifcvf_remove(struct pci_dev *pdev)
ifcvf_mgmt_dev = pci_get_drvdata(pdev);
vdpa_mgmtdev_unregister(&ifcvf_mgmt_dev->mdev);
+ kfree(ifcvf_mgmt_dev->vf.vring);
kfree(ifcvf_mgmt_dev);
}
@@ -911,7 +853,9 @@ static struct pci_device_id ifcvf_pci_ids[] = {
N3000_DEVICE_ID,
PCI_VENDOR_ID_INTEL,
N3000_SUBSYS_DEVICE_ID) },
- /* C5000X-PL network device */
+ /* C5000X-PL network device
+ * F2000X-PL network device
+ */
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_REDHAT_QUMRANET,
VIRTIO_TRANS_ID_NET,
PCI_VENDOR_ID_INTEL,
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
index 279ac6a558d2..9138ef2fb2c8 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
@@ -83,6 +83,7 @@ struct mlx5_vq_restore_info {
u64 driver_addr;
u16 avail_index;
u16 used_index;
+ struct msi_map map;
bool ready;
bool restore;
};
@@ -118,6 +119,7 @@ struct mlx5_vdpa_virtqueue {
u16 avail_idx;
u16 used_idx;
int fw_state;
+ struct msi_map map;
/* keep last in the struct */
struct mlx5_vq_restore_info ri;
@@ -808,6 +810,13 @@ static bool counters_supported(const struct mlx5_vdpa_dev *mvdev)
BIT_ULL(MLX5_OBJ_TYPE_VIRTIO_Q_COUNTERS);
}
+static bool msix_mode_supported(struct mlx5_vdpa_dev *mvdev)
+{
+ return MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, event_mode) &
+ (1 << MLX5_VIRTIO_Q_EVENT_MODE_MSIX_MODE) &&
+ pci_msix_can_alloc_dyn(mvdev->mdev->pdev);
+}
+
static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq)
{
int inlen = MLX5_ST_SZ_BYTES(create_virtio_net_q_in);
@@ -849,9 +858,15 @@ static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque
if (vq_is_tx(mvq->index))
MLX5_SET(virtio_net_q_object, obj_context, tisn_or_qpn, ndev->res.tisn);
- MLX5_SET(virtio_q, vq_ctx, event_mode, MLX5_VIRTIO_Q_EVENT_MODE_QP_MODE);
+ if (mvq->map.virq) {
+ MLX5_SET(virtio_q, vq_ctx, event_mode, MLX5_VIRTIO_Q_EVENT_MODE_MSIX_MODE);
+ MLX5_SET(virtio_q, vq_ctx, event_qpn_or_msix, mvq->map.index);
+ } else {
+ MLX5_SET(virtio_q, vq_ctx, event_mode, MLX5_VIRTIO_Q_EVENT_MODE_QP_MODE);
+ MLX5_SET(virtio_q, vq_ctx, event_qpn_or_msix, mvq->fwqp.mqp.qpn);
+ }
+
MLX5_SET(virtio_q, vq_ctx, queue_index, mvq->index);
- MLX5_SET(virtio_q, vq_ctx, event_qpn_or_msix, mvq->fwqp.mqp.qpn);
MLX5_SET(virtio_q, vq_ctx, queue_size, mvq->num_ent);
MLX5_SET(virtio_q, vq_ctx, virtio_version_1_0,
!!(ndev->mvdev.actual_features & BIT_ULL(VIRTIO_F_VERSION_1)));
@@ -1194,6 +1209,56 @@ static void counter_set_dealloc(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_vir
mlx5_vdpa_warn(&ndev->mvdev, "dealloc counter set 0x%x\n", mvq->counter_set_id);
}
+static irqreturn_t mlx5_vdpa_int_handler(int irq, void *priv)
+{
+ struct vdpa_callback *cb = priv;
+
+ if (cb->callback)
+ return cb->callback(cb->private);
+
+ return IRQ_HANDLED;
+}
+
+static void alloc_vector(struct mlx5_vdpa_net *ndev,
+ struct mlx5_vdpa_virtqueue *mvq)
+{
+ struct mlx5_vdpa_irq_pool *irqp = &ndev->irqp;
+ struct mlx5_vdpa_irq_pool_entry *ent;
+ int err;
+ int i;
+
+ for (i = 0; i < irqp->num_ent; i++) {
+ ent = &irqp->entries[i];
+ if (!ent->used) {
+ snprintf(ent->name, MLX5_VDPA_IRQ_NAME_LEN, "%s-vq-%d",
+ dev_name(&ndev->mvdev.vdev.dev), mvq->index);
+ ent->dev_id = &ndev->event_cbs[mvq->index];
+ err = request_irq(ent->map.virq, mlx5_vdpa_int_handler, 0,
+ ent->name, ent->dev_id);
+ if (err)
+ return;
+
+ ent->used = true;
+ mvq->map = ent->map;
+ return;
+ }
+ }
+}
+
+static void dealloc_vector(struct mlx5_vdpa_net *ndev,
+ struct mlx5_vdpa_virtqueue *mvq)
+{
+ struct mlx5_vdpa_irq_pool *irqp = &ndev->irqp;
+ int i;
+
+ for (i = 0; i < irqp->num_ent; i++)
+ if (mvq->map.virq == irqp->entries[i].map.virq) {
+ free_irq(mvq->map.virq, irqp->entries[i].dev_id);
+ irqp->entries[i].used = false;
+ return;
+ }
+}
+
static int setup_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq)
{
u16 idx = mvq->index;
@@ -1223,27 +1288,31 @@ static int setup_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq)
err = counter_set_alloc(ndev, mvq);
if (err)
- goto err_counter;
+ goto err_connect;
+ alloc_vector(ndev, mvq);
err = create_virtqueue(ndev, mvq);
if (err)
- goto err_connect;
+ goto err_vq;
if (mvq->ready) {
err = modify_virtqueue(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY);
if (err) {
mlx5_vdpa_warn(&ndev->mvdev, "failed to modify to ready vq idx %d(%d)\n",
idx, err);
- goto err_connect;
+ goto err_modify;
}
}
mvq->initialized = true;
return 0;
-err_connect:
+err_modify:
+ destroy_virtqueue(ndev, mvq);
+err_vq:
+ dealloc_vector(ndev, mvq);
counter_set_dealloc(ndev, mvq);
-err_counter:
+err_connect:
qp_destroy(ndev, &mvq->vqqp);
err_vqqp:
qp_destroy(ndev, &mvq->fwqp);
@@ -1288,6 +1357,7 @@ static void teardown_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *
suspend_vq(ndev, mvq);
destroy_virtqueue(ndev, mvq);
+ dealloc_vector(ndev, mvq);
counter_set_dealloc(ndev, mvq);
qp_destroy(ndev, &mvq->vqqp);
qp_destroy(ndev, &mvq->fwqp);
@@ -2505,6 +2575,7 @@ static int save_channel_info(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqu
ri->desc_addr = mvq->desc_addr;
ri->device_addr = mvq->device_addr;
ri->driver_addr = mvq->driver_addr;
+ ri->map = mvq->map;
ri->restore = true;
return 0;
}
@@ -2549,6 +2620,7 @@ static void restore_channels_info(struct mlx5_vdpa_net *ndev)
mvq->desc_addr = ri->desc_addr;
mvq->device_addr = ri->device_addr;
mvq->driver_addr = ri->driver_addr;
+ mvq->map = ri->map;
}
}
@@ -2833,6 +2905,25 @@ static struct device *mlx5_get_vq_dma_dev(struct vdpa_device *vdev, u16 idx)
return mvdev->vdev.dma_dev;
}
+static void free_irqs(struct mlx5_vdpa_net *ndev)
+{
+ struct mlx5_vdpa_irq_pool_entry *ent;
+ int i;
+
+ if (!msix_mode_supported(&ndev->mvdev))
+ return;
+
+ if (!ndev->irqp.entries)
+ return;
+
+ for (i = ndev->irqp.num_ent - 1; i >= 0; i--) {
+ ent = ndev->irqp.entries + i;
+ if (ent->map.virq)
+ pci_msix_free_irq(ndev->mvdev.mdev->pdev, ent->map);
+ }
+ kfree(ndev->irqp.entries);
+}
+
static void mlx5_vdpa_free(struct vdpa_device *vdev)
{
struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev);
@@ -2848,6 +2939,7 @@ static void mlx5_vdpa_free(struct vdpa_device *vdev)
mlx5_mpfs_del_mac(pfmdev, ndev->config.mac);
}
mlx5_vdpa_free_resources(&ndev->mvdev);
+ free_irqs(ndev);
kfree(ndev->event_cbs);
kfree(ndev->vqs);
}
@@ -2876,9 +2968,23 @@ static struct vdpa_notification_area mlx5_get_vq_notification(struct vdpa_device
return ret;
}
-static int mlx5_get_vq_irq(struct vdpa_device *vdv, u16 idx)
+static int mlx5_get_vq_irq(struct vdpa_device *vdev, u16 idx)
{
- return -EOPNOTSUPP;
+ struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev);
+ struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
+ struct mlx5_vdpa_virtqueue *mvq;
+
+ if (!is_index_valid(mvdev, idx))
+ return -EINVAL;
+
+ if (is_ctrl_vq_idx(mvdev, idx))
+ return -EOPNOTSUPP;
+
+ mvq = &ndev->vqs[idx];
+ if (!mvq->map.virq)
+ return -EOPNOTSUPP;
+
+ return mvq->map.virq;
}
static u64 mlx5_vdpa_get_driver_features(struct vdpa_device *vdev)
@@ -3155,6 +3261,34 @@ static int config_func_mtu(struct mlx5_core_dev *mdev, u16 mtu)
return err;
}
+static void allocate_irqs(struct mlx5_vdpa_net *ndev)
+{
+ struct mlx5_vdpa_irq_pool_entry *ent;
+ int i;
+
+ if (!msix_mode_supported(&ndev->mvdev))
+ return;
+
+ if (!ndev->mvdev.mdev->pdev)
+ return;
+
+ ndev->irqp.entries = kcalloc(ndev->mvdev.max_vqs, sizeof(*ndev->irqp.entries), GFP_KERNEL);
+ if (!ndev->irqp.entries)
+ return;
+
+
+ for (i = 0; i < ndev->mvdev.max_vqs; i++) {
+ ent = ndev->irqp.entries + i;
+ snprintf(ent->name, MLX5_VDPA_IRQ_NAME_LEN, "%s-vq-%d",
+ dev_name(&ndev->mvdev.vdev.dev), i);
+ ent->map = pci_msix_alloc_irq_at(ndev->mvdev.mdev->pdev, MSI_ANY_INDEX, NULL);
+ if (!ent->map.virq)
+ return;
+
+ ndev->irqp.num_ent++;
+ }
+}
+
static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name,
const struct vdpa_dev_set_config *add_config)
{
@@ -3233,6 +3367,7 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name,
}
init_mvqs(ndev);
+ allocate_irqs(ndev);
init_rwsem(&ndev->reslock);
config = &ndev->config;
@@ -3413,6 +3548,17 @@ static void mlx5v_remove(struct auxiliary_device *adev)
kfree(mgtdev);
}
+static void mlx5v_shutdown(struct auxiliary_device *auxdev)
+{
+ struct mlx5_vdpa_mgmtdev *mgtdev;
+ struct mlx5_vdpa_net *ndev;
+
+ mgtdev = auxiliary_get_drvdata(auxdev);
+ ndev = mgtdev->ndev;
+
+ free_irqs(ndev);
+}
+
static const struct auxiliary_device_id mlx5v_id_table[] = {
{ .name = MLX5_ADEV_NAME ".vnet", },
{},
@@ -3424,6 +3570,7 @@ static struct auxiliary_driver mlx5v_driver = {
.name = "vnet",
.probe = mlx5v_probe,
.remove = mlx5v_remove,
+ .shutdown = mlx5v_shutdown,
.id_table = mlx5v_id_table,
};
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.h b/drivers/vdpa/mlx5/net/mlx5_vnet.h
index c90a89e1de4d..36c44d9fdd16 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.h
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.h
@@ -26,6 +26,20 @@ static inline u16 key2vid(u64 key)
return (u16)(key >> 48) & 0xfff;
}
+#define MLX5_VDPA_IRQ_NAME_LEN 32
+
+struct mlx5_vdpa_irq_pool_entry {
+ struct msi_map map;
+ bool used;
+ char name[MLX5_VDPA_IRQ_NAME_LEN];
+ void *dev_id;
+};
+
+struct mlx5_vdpa_irq_pool {
+ int num_ent;
+ struct mlx5_vdpa_irq_pool_entry *entries;
+};
+
struct mlx5_vdpa_net {
struct mlx5_vdpa_dev mvdev;
struct mlx5_vdpa_net_resources res;
@@ -49,6 +63,7 @@ struct mlx5_vdpa_net {
struct vdpa_callback config_cb;
struct mlx5_vdpa_wq_ent cvq_ent;
struct hlist_head macvlan_hash[MLX5V_MACVLAN_SIZE];
+ struct mlx5_vdpa_irq_pool irqp;
struct dentry *debugfs;
};
diff --git a/drivers/vdpa/pds/Makefile b/drivers/vdpa/pds/Makefile
new file mode 100644
index 000000000000..2e22418e3ab3
--- /dev/null
+++ b/drivers/vdpa/pds/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright(c) 2023 Advanced Micro Devices, Inc
+
+obj-$(CONFIG_PDS_VDPA) := pds_vdpa.o
+
+pds_vdpa-y := aux_drv.o \
+ cmds.o \
+ vdpa_dev.o
+
+pds_vdpa-$(CONFIG_DEBUG_FS) += debugfs.o
diff --git a/drivers/vdpa/pds/aux_drv.c b/drivers/vdpa/pds/aux_drv.c
new file mode 100644
index 000000000000..186e9ee22eb1
--- /dev/null
+++ b/drivers/vdpa/pds/aux_drv.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Advanced Micro Devices, Inc */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/pci.h>
+#include <linux/vdpa.h>
+#include <linux/virtio_pci_modern.h>
+
+#include <linux/pds/pds_common.h>
+#include <linux/pds/pds_core_if.h>
+#include <linux/pds/pds_adminq.h>
+#include <linux/pds/pds_auxbus.h>
+
+#include "aux_drv.h"
+#include "debugfs.h"
+#include "vdpa_dev.h"
+
+static const struct auxiliary_device_id pds_vdpa_id_table[] = {
+ { .name = PDS_VDPA_DEV_NAME, },
+ {},
+};
+
+static int pds_vdpa_device_id_check(struct pci_dev *pdev)
+{
+ if (pdev->device != PCI_DEVICE_ID_PENSANDO_VDPA_VF ||
+ pdev->vendor != PCI_VENDOR_ID_PENSANDO)
+ return -ENODEV;
+
+ return PCI_DEVICE_ID_PENSANDO_VDPA_VF;
+}
+
+static int pds_vdpa_probe(struct auxiliary_device *aux_dev,
+ const struct auxiliary_device_id *id)
+
+{
+ struct pds_auxiliary_dev *padev =
+ container_of(aux_dev, struct pds_auxiliary_dev, aux_dev);
+ struct device *dev = &aux_dev->dev;
+ struct pds_vdpa_aux *vdpa_aux;
+ int err;
+
+ vdpa_aux = kzalloc(sizeof(*vdpa_aux), GFP_KERNEL);
+ if (!vdpa_aux)
+ return -ENOMEM;
+
+ vdpa_aux->padev = padev;
+ vdpa_aux->vf_id = pci_iov_vf_id(padev->vf_pdev);
+ auxiliary_set_drvdata(aux_dev, vdpa_aux);
+
+ /* Get device ident info and set up the vdpa_mgmt_dev */
+ err = pds_vdpa_get_mgmt_info(vdpa_aux);
+ if (err)
+ goto err_free_mem;
+
+ /* Find the virtio configuration */
+ vdpa_aux->vd_mdev.pci_dev = padev->vf_pdev;
+ vdpa_aux->vd_mdev.device_id_check = pds_vdpa_device_id_check;
+ vdpa_aux->vd_mdev.dma_mask = DMA_BIT_MASK(PDS_CORE_ADDR_LEN);
+ err = vp_modern_probe(&vdpa_aux->vd_mdev);
+ if (err) {
+ dev_err(dev, "Unable to probe for virtio configuration: %pe\n",
+ ERR_PTR(err));
+ goto err_free_mgmt_info;
+ }
+
+ /* Let vdpa know that we can provide devices */
+ err = vdpa_mgmtdev_register(&vdpa_aux->vdpa_mdev);
+ if (err) {
+ dev_err(dev, "%s: Failed to initialize vdpa_mgmt interface: %pe\n",
+ __func__, ERR_PTR(err));
+ goto err_free_virtio;
+ }
+
+ pds_vdpa_debugfs_add_pcidev(vdpa_aux);
+ pds_vdpa_debugfs_add_ident(vdpa_aux);
+
+ return 0;
+
+err_free_virtio:
+ vp_modern_remove(&vdpa_aux->vd_mdev);
+err_free_mgmt_info:
+ pci_free_irq_vectors(padev->vf_pdev);
+err_free_mem:
+ kfree(vdpa_aux);
+ auxiliary_set_drvdata(aux_dev, NULL);
+
+ return err;
+}
+
+static void pds_vdpa_remove(struct auxiliary_device *aux_dev)
+{
+ struct pds_vdpa_aux *vdpa_aux = auxiliary_get_drvdata(aux_dev);
+ struct device *dev = &aux_dev->dev;
+
+ vdpa_mgmtdev_unregister(&vdpa_aux->vdpa_mdev);
+ vp_modern_remove(&vdpa_aux->vd_mdev);
+ pci_free_irq_vectors(vdpa_aux->padev->vf_pdev);
+
+ pds_vdpa_debugfs_del_vdpadev(vdpa_aux);
+ kfree(vdpa_aux);
+ auxiliary_set_drvdata(aux_dev, NULL);
+
+ dev_info(dev, "Removed\n");
+}
+
+static struct auxiliary_driver pds_vdpa_driver = {
+ .name = PDS_DEV_TYPE_VDPA_STR,
+ .probe = pds_vdpa_probe,
+ .remove = pds_vdpa_remove,
+ .id_table = pds_vdpa_id_table,
+};
+
+static void __exit pds_vdpa_cleanup(void)
+{
+ auxiliary_driver_unregister(&pds_vdpa_driver);
+
+ pds_vdpa_debugfs_destroy();
+}
+module_exit(pds_vdpa_cleanup);
+
+static int __init pds_vdpa_init(void)
+{
+ int err;
+
+ pds_vdpa_debugfs_create();
+
+ err = auxiliary_driver_register(&pds_vdpa_driver);
+ if (err) {
+ pr_err("%s: aux driver register failed: %pe\n",
+ PDS_VDPA_DRV_NAME, ERR_PTR(err));
+ pds_vdpa_debugfs_destroy();
+ }
+
+ return err;
+}
+module_init(pds_vdpa_init);
+
+MODULE_DESCRIPTION(PDS_VDPA_DRV_DESCRIPTION);
+MODULE_AUTHOR("Advanced Micro Devices, Inc");
+MODULE_LICENSE("GPL");
diff --git a/drivers/vdpa/pds/aux_drv.h b/drivers/vdpa/pds/aux_drv.h
new file mode 100644
index 000000000000..26b75344156e
--- /dev/null
+++ b/drivers/vdpa/pds/aux_drv.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Advanced Micro Devices, Inc */
+
+#ifndef _AUX_DRV_H_
+#define _AUX_DRV_H_
+
+#include <linux/virtio_pci_modern.h>
+
+#define PDS_VDPA_DRV_DESCRIPTION "AMD/Pensando vDPA VF Device Driver"
+#define PDS_VDPA_DRV_NAME KBUILD_MODNAME
+
+struct pds_vdpa_aux {
+ struct pds_auxiliary_dev *padev;
+
+ struct vdpa_mgmt_dev vdpa_mdev;
+ struct pds_vdpa_device *pdsv;
+
+ struct pds_vdpa_ident ident;
+
+ int vf_id;
+ struct dentry *dentry;
+ struct virtio_pci_modern_device vd_mdev;
+
+ int nintrs;
+};
+#endif /* _AUX_DRV_H_ */
diff --git a/drivers/vdpa/pds/cmds.c b/drivers/vdpa/pds/cmds.c
new file mode 100644
index 000000000000..80863a41c3cd
--- /dev/null
+++ b/drivers/vdpa/pds/cmds.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Advanced Micro Devices, Inc */
+
+#include <linux/vdpa.h>
+#include <linux/virtio_pci_modern.h>
+
+#include <linux/pds/pds_common.h>
+#include <linux/pds/pds_core_if.h>
+#include <linux/pds/pds_adminq.h>
+#include <linux/pds/pds_auxbus.h>
+
+#include "vdpa_dev.h"
+#include "aux_drv.h"
+#include "cmds.h"
+
+int pds_vdpa_init_hw(struct pds_vdpa_device *pdsv)
+{
+ struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev;
+ struct device *dev = &padev->aux_dev.dev;
+ union pds_core_adminq_cmd cmd = {
+ .vdpa_init.opcode = PDS_VDPA_CMD_INIT,
+ .vdpa_init.vdpa_index = pdsv->vdpa_index,
+ .vdpa_init.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id),
+ };
+ union pds_core_adminq_comp comp = {};
+ int err;
+
+ /* Initialize the vdpa/virtio device */
+ err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_init),
+ &comp, 0);
+ if (err)
+ dev_dbg(dev, "Failed to init hw, status %d: %pe\n",
+ comp.status, ERR_PTR(err));
+
+ return err;
+}
+
+int pds_vdpa_cmd_reset(struct pds_vdpa_device *pdsv)
+{
+ struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev;
+ struct device *dev = &padev->aux_dev.dev;
+ union pds_core_adminq_cmd cmd = {
+ .vdpa.opcode = PDS_VDPA_CMD_RESET,
+ .vdpa.vdpa_index = pdsv->vdpa_index,
+ .vdpa.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id),
+ };
+ union pds_core_adminq_comp comp = {};
+ int err;
+
+ err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa), &comp, 0);
+ if (err)
+ dev_dbg(dev, "Failed to reset hw, status %d: %pe\n",
+ comp.status, ERR_PTR(err));
+
+ return err;
+}
+
+int pds_vdpa_cmd_set_status(struct pds_vdpa_device *pdsv, u8 status)
+{
+ struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev;
+ struct device *dev = &padev->aux_dev.dev;
+ union pds_core_adminq_cmd cmd = {
+ .vdpa_status.opcode = PDS_VDPA_CMD_STATUS_UPDATE,
+ .vdpa_status.vdpa_index = pdsv->vdpa_index,
+ .vdpa_status.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id),
+ .vdpa_status.status = status,
+ };
+ union pds_core_adminq_comp comp = {};
+ int err;
+
+ err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_status), &comp, 0);
+ if (err)
+ dev_dbg(dev, "Failed to set status to %#x, error status %d: %pe\n",
+ status, comp.status, ERR_PTR(err));
+
+ return err;
+}
+
+int pds_vdpa_cmd_set_mac(struct pds_vdpa_device *pdsv, u8 *mac)
+{
+ struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev;
+ struct device *dev = &padev->aux_dev.dev;
+ union pds_core_adminq_cmd cmd = {
+ .vdpa_setattr.opcode = PDS_VDPA_CMD_SET_ATTR,
+ .vdpa_setattr.vdpa_index = pdsv->vdpa_index,
+ .vdpa_setattr.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id),
+ .vdpa_setattr.attr = PDS_VDPA_ATTR_MAC,
+ };
+ union pds_core_adminq_comp comp = {};
+ int err;
+
+ ether_addr_copy(cmd.vdpa_setattr.mac, mac);
+ err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_setattr),
+ &comp, 0);
+ if (err)
+ dev_dbg(dev, "Failed to set mac address %pM, status %d: %pe\n",
+ mac, comp.status, ERR_PTR(err));
+
+ return err;
+}
+
+int pds_vdpa_cmd_set_max_vq_pairs(struct pds_vdpa_device *pdsv, u16 max_vqp)
+{
+ struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev;
+ struct device *dev = &padev->aux_dev.dev;
+ union pds_core_adminq_cmd cmd = {
+ .vdpa_setattr.opcode = PDS_VDPA_CMD_SET_ATTR,
+ .vdpa_setattr.vdpa_index = pdsv->vdpa_index,
+ .vdpa_setattr.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id),
+ .vdpa_setattr.attr = PDS_VDPA_ATTR_MAX_VQ_PAIRS,
+ .vdpa_setattr.max_vq_pairs = cpu_to_le16(max_vqp),
+ };
+ union pds_core_adminq_comp comp = {};
+ int err;
+
+ err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_setattr),
+ &comp, 0);
+ if (err)
+ dev_dbg(dev, "Failed to set max vq pairs %u, status %d: %pe\n",
+ max_vqp, comp.status, ERR_PTR(err));
+
+ return err;
+}
+
+int pds_vdpa_cmd_init_vq(struct pds_vdpa_device *pdsv, u16 qid, u16 invert_idx,
+ struct pds_vdpa_vq_info *vq_info)
+{
+ struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev;
+ struct device *dev = &padev->aux_dev.dev;
+ union pds_core_adminq_cmd cmd = {
+ .vdpa_vq_init.opcode = PDS_VDPA_CMD_VQ_INIT,
+ .vdpa_vq_init.vdpa_index = pdsv->vdpa_index,
+ .vdpa_vq_init.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id),
+ .vdpa_vq_init.qid = cpu_to_le16(qid),
+ .vdpa_vq_init.len = cpu_to_le16(ilog2(vq_info->q_len)),
+ .vdpa_vq_init.desc_addr = cpu_to_le64(vq_info->desc_addr),
+ .vdpa_vq_init.avail_addr = cpu_to_le64(vq_info->avail_addr),
+ .vdpa_vq_init.used_addr = cpu_to_le64(vq_info->used_addr),
+ .vdpa_vq_init.intr_index = cpu_to_le16(qid),
+ .vdpa_vq_init.avail_index = cpu_to_le16(vq_info->avail_idx ^ invert_idx),
+ .vdpa_vq_init.used_index = cpu_to_le16(vq_info->used_idx ^ invert_idx),
+ };
+ union pds_core_adminq_comp comp = {};
+ int err;
+
+ dev_dbg(dev, "%s: qid %d len %d desc_addr %#llx avail_addr %#llx used_addr %#llx\n",
+ __func__, qid, ilog2(vq_info->q_len),
+ vq_info->desc_addr, vq_info->avail_addr, vq_info->used_addr);
+
+ err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_vq_init),
+ &comp, 0);
+ if (err)
+ dev_dbg(dev, "Failed to init vq %d, status %d: %pe\n",
+ qid, comp.status, ERR_PTR(err));
+
+ return err;
+}
+
+int pds_vdpa_cmd_reset_vq(struct pds_vdpa_device *pdsv, u16 qid, u16 invert_idx,
+ struct pds_vdpa_vq_info *vq_info)
+{
+ struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev;
+ struct device *dev = &padev->aux_dev.dev;
+ union pds_core_adminq_cmd cmd = {
+ .vdpa_vq_reset.opcode = PDS_VDPA_CMD_VQ_RESET,
+ .vdpa_vq_reset.vdpa_index = pdsv->vdpa_index,
+ .vdpa_vq_reset.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id),
+ .vdpa_vq_reset.qid = cpu_to_le16(qid),
+ };
+ union pds_core_adminq_comp comp = {};
+ int err;
+
+ err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_vq_reset),
+ &comp, 0);
+ if (err) {
+ dev_dbg(dev, "Failed to reset vq %d, status %d: %pe\n",
+ qid, comp.status, ERR_PTR(err));
+ return err;
+ }
+
+ vq_info->avail_idx = le16_to_cpu(comp.vdpa_vq_reset.avail_index) ^ invert_idx;
+ vq_info->used_idx = le16_to_cpu(comp.vdpa_vq_reset.used_index) ^ invert_idx;
+
+ return 0;
+}
diff --git a/drivers/vdpa/pds/cmds.h b/drivers/vdpa/pds/cmds.h
new file mode 100644
index 000000000000..e24d85cb8f1c
--- /dev/null
+++ b/drivers/vdpa/pds/cmds.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Advanced Micro Devices, Inc */
+
+#ifndef _VDPA_CMDS_H_
+#define _VDPA_CMDS_H_
+
+int pds_vdpa_init_hw(struct pds_vdpa_device *pdsv);
+
+int pds_vdpa_cmd_reset(struct pds_vdpa_device *pdsv);
+int pds_vdpa_cmd_set_status(struct pds_vdpa_device *pdsv, u8 status);
+int pds_vdpa_cmd_set_mac(struct pds_vdpa_device *pdsv, u8 *mac);
+int pds_vdpa_cmd_set_max_vq_pairs(struct pds_vdpa_device *pdsv, u16 max_vqp);
+int pds_vdpa_cmd_init_vq(struct pds_vdpa_device *pdsv, u16 qid, u16 invert_idx,
+ struct pds_vdpa_vq_info *vq_info);
+int pds_vdpa_cmd_reset_vq(struct pds_vdpa_device *pdsv, u16 qid, u16 invert_idx,
+ struct pds_vdpa_vq_info *vq_info);
+int pds_vdpa_cmd_set_features(struct pds_vdpa_device *pdsv, u64 features);
+#endif /* _VDPA_CMDS_H_ */
diff --git a/drivers/vdpa/pds/debugfs.c b/drivers/vdpa/pds/debugfs.c
new file mode 100644
index 000000000000..21a0dc0cb607
--- /dev/null
+++ b/drivers/vdpa/pds/debugfs.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Advanced Micro Devices, Inc */
+
+#include <linux/pci.h>
+#include <linux/vdpa.h>
+
+#include <linux/pds/pds_common.h>
+#include <linux/pds/pds_core_if.h>
+#include <linux/pds/pds_adminq.h>
+#include <linux/pds/pds_auxbus.h>
+
+#include "aux_drv.h"
+#include "vdpa_dev.h"
+#include "debugfs.h"
+
+static struct dentry *dbfs_dir;
+
+void pds_vdpa_debugfs_create(void)
+{
+ dbfs_dir = debugfs_create_dir(PDS_VDPA_DRV_NAME, NULL);
+}
+
+void pds_vdpa_debugfs_destroy(void)
+{
+ debugfs_remove_recursive(dbfs_dir);
+ dbfs_dir = NULL;
+}
+
+#define PRINT_SBIT_NAME(__seq, __f, __name) \
+ do { \
+ if ((__f) & (__name)) \
+ seq_printf(__seq, " %s", &#__name[16]); \
+ } while (0)
+
+static void print_status_bits(struct seq_file *seq, u8 status)
+{
+ seq_puts(seq, "status:");
+ PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_ACKNOWLEDGE);
+ PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_DRIVER);
+ PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_DRIVER_OK);
+ PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_FEATURES_OK);
+ PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_NEEDS_RESET);
+ PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_FAILED);
+ seq_puts(seq, "\n");
+}
+
+static void print_feature_bits_all(struct seq_file *seq, u64 features)
+{
+ int i;
+
+ seq_puts(seq, "features:");
+
+ for (i = 0; i < (sizeof(u64) * 8); i++) {
+ u64 mask = BIT_ULL(i);
+
+ switch (features & mask) {
+ case BIT_ULL(VIRTIO_NET_F_CSUM):
+ seq_puts(seq, " VIRTIO_NET_F_CSUM");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_GUEST_CSUM):
+ seq_puts(seq, " VIRTIO_NET_F_GUEST_CSUM");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_CTRL_GUEST_OFFLOADS):
+ seq_puts(seq, " VIRTIO_NET_F_CTRL_GUEST_OFFLOADS");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_MTU):
+ seq_puts(seq, " VIRTIO_NET_F_MTU");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_MAC):
+ seq_puts(seq, " VIRTIO_NET_F_MAC");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_GUEST_TSO4):
+ seq_puts(seq, " VIRTIO_NET_F_GUEST_TSO4");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_GUEST_TSO6):
+ seq_puts(seq, " VIRTIO_NET_F_GUEST_TSO6");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_GUEST_ECN):
+ seq_puts(seq, " VIRTIO_NET_F_GUEST_ECN");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_GUEST_UFO):
+ seq_puts(seq, " VIRTIO_NET_F_GUEST_UFO");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_HOST_TSO4):
+ seq_puts(seq, " VIRTIO_NET_F_HOST_TSO4");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_HOST_TSO6):
+ seq_puts(seq, " VIRTIO_NET_F_HOST_TSO6");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_HOST_ECN):
+ seq_puts(seq, " VIRTIO_NET_F_HOST_ECN");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_HOST_UFO):
+ seq_puts(seq, " VIRTIO_NET_F_HOST_UFO");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_MRG_RXBUF):
+ seq_puts(seq, " VIRTIO_NET_F_MRG_RXBUF");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_STATUS):
+ seq_puts(seq, " VIRTIO_NET_F_STATUS");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_CTRL_VQ):
+ seq_puts(seq, " VIRTIO_NET_F_CTRL_VQ");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_CTRL_RX):
+ seq_puts(seq, " VIRTIO_NET_F_CTRL_RX");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_CTRL_VLAN):
+ seq_puts(seq, " VIRTIO_NET_F_CTRL_VLAN");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_CTRL_RX_EXTRA):
+ seq_puts(seq, " VIRTIO_NET_F_CTRL_RX_EXTRA");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_GUEST_ANNOUNCE):
+ seq_puts(seq, " VIRTIO_NET_F_GUEST_ANNOUNCE");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_MQ):
+ seq_puts(seq, " VIRTIO_NET_F_MQ");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR):
+ seq_puts(seq, " VIRTIO_NET_F_CTRL_MAC_ADDR");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_HASH_REPORT):
+ seq_puts(seq, " VIRTIO_NET_F_HASH_REPORT");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_RSS):
+ seq_puts(seq, " VIRTIO_NET_F_RSS");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_RSC_EXT):
+ seq_puts(seq, " VIRTIO_NET_F_RSC_EXT");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_STANDBY):
+ seq_puts(seq, " VIRTIO_NET_F_STANDBY");
+ break;
+ case BIT_ULL(VIRTIO_NET_F_SPEED_DUPLEX):
+ seq_puts(seq, " VIRTIO_NET_F_SPEED_DUPLEX");
+ break;
+ case BIT_ULL(VIRTIO_F_NOTIFY_ON_EMPTY):
+ seq_puts(seq, " VIRTIO_F_NOTIFY_ON_EMPTY");
+ break;
+ case BIT_ULL(VIRTIO_F_ANY_LAYOUT):
+ seq_puts(seq, " VIRTIO_F_ANY_LAYOUT");
+ break;
+ case BIT_ULL(VIRTIO_F_VERSION_1):
+ seq_puts(seq, " VIRTIO_F_VERSION_1");
+ break;
+ case BIT_ULL(VIRTIO_F_ACCESS_PLATFORM):
+ seq_puts(seq, " VIRTIO_F_ACCESS_PLATFORM");
+ break;
+ case BIT_ULL(VIRTIO_F_RING_PACKED):
+ seq_puts(seq, " VIRTIO_F_RING_PACKED");
+ break;
+ case BIT_ULL(VIRTIO_F_ORDER_PLATFORM):
+ seq_puts(seq, " VIRTIO_F_ORDER_PLATFORM");
+ break;
+ case BIT_ULL(VIRTIO_F_SR_IOV):
+ seq_puts(seq, " VIRTIO_F_SR_IOV");
+ break;
+ case 0:
+ break;
+ default:
+ seq_printf(seq, " bit_%d", i);
+ break;
+ }
+ }
+
+ seq_puts(seq, "\n");
+}
+
+void pds_vdpa_debugfs_add_pcidev(struct pds_vdpa_aux *vdpa_aux)
+{
+ vdpa_aux->dentry = debugfs_create_dir(pci_name(vdpa_aux->padev->vf_pdev), dbfs_dir);
+}
+
+static int identity_show(struct seq_file *seq, void *v)
+{
+ struct pds_vdpa_aux *vdpa_aux = seq->private;
+ struct vdpa_mgmt_dev *mgmt;
+
+ seq_printf(seq, "aux_dev: %s\n",
+ dev_name(&vdpa_aux->padev->aux_dev.dev));
+
+ mgmt = &vdpa_aux->vdpa_mdev;
+ seq_printf(seq, "max_vqs: %d\n", mgmt->max_supported_vqs);
+ seq_printf(seq, "config_attr_mask: %#llx\n", mgmt->config_attr_mask);
+ seq_printf(seq, "supported_features: %#llx\n", mgmt->supported_features);
+ print_feature_bits_all(seq, mgmt->supported_features);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(identity);
+
+void pds_vdpa_debugfs_add_ident(struct pds_vdpa_aux *vdpa_aux)
+{
+ debugfs_create_file("identity", 0400, vdpa_aux->dentry,
+ vdpa_aux, &identity_fops);
+}
+
+static int config_show(struct seq_file *seq, void *v)
+{
+ struct pds_vdpa_device *pdsv = seq->private;
+ struct virtio_net_config vc;
+ u64 driver_features;
+ u8 status;
+
+ memcpy_fromio(&vc, pdsv->vdpa_aux->vd_mdev.device,
+ sizeof(struct virtio_net_config));
+
+ seq_printf(seq, "mac: %pM\n", vc.mac);
+ seq_printf(seq, "max_virtqueue_pairs: %d\n",
+ __virtio16_to_cpu(true, vc.max_virtqueue_pairs));
+ seq_printf(seq, "mtu: %d\n", __virtio16_to_cpu(true, vc.mtu));
+ seq_printf(seq, "speed: %d\n", le32_to_cpu(vc.speed));
+ seq_printf(seq, "duplex: %d\n", vc.duplex);
+ seq_printf(seq, "rss_max_key_size: %d\n", vc.rss_max_key_size);
+ seq_printf(seq, "rss_max_indirection_table_length: %d\n",
+ le16_to_cpu(vc.rss_max_indirection_table_length));
+ seq_printf(seq, "supported_hash_types: %#x\n",
+ le32_to_cpu(vc.supported_hash_types));
+ seq_printf(seq, "vn_status: %#x\n",
+ __virtio16_to_cpu(true, vc.status));
+
+ status = vp_modern_get_status(&pdsv->vdpa_aux->vd_mdev);
+ seq_printf(seq, "dev_status: %#x\n", status);
+ print_status_bits(seq, status);
+
+ seq_printf(seq, "req_features: %#llx\n", pdsv->req_features);
+ print_feature_bits_all(seq, pdsv->req_features);
+ driver_features = vp_modern_get_driver_features(&pdsv->vdpa_aux->vd_mdev);
+ seq_printf(seq, "driver_features: %#llx\n", driver_features);
+ print_feature_bits_all(seq, driver_features);
+ seq_printf(seq, "vdpa_index: %d\n", pdsv->vdpa_index);
+ seq_printf(seq, "num_vqs: %d\n", pdsv->num_vqs);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(config);
+
+static int vq_show(struct seq_file *seq, void *v)
+{
+ struct pds_vdpa_vq_info *vq = seq->private;
+
+ seq_printf(seq, "ready: %d\n", vq->ready);
+ seq_printf(seq, "desc_addr: %#llx\n", vq->desc_addr);
+ seq_printf(seq, "avail_addr: %#llx\n", vq->avail_addr);
+ seq_printf(seq, "used_addr: %#llx\n", vq->used_addr);
+ seq_printf(seq, "q_len: %d\n", vq->q_len);
+ seq_printf(seq, "qid: %d\n", vq->qid);
+
+ seq_printf(seq, "doorbell: %#llx\n", vq->doorbell);
+ seq_printf(seq, "avail_idx: %d\n", vq->avail_idx);
+ seq_printf(seq, "used_idx: %d\n", vq->used_idx);
+ seq_printf(seq, "irq: %d\n", vq->irq);
+ seq_printf(seq, "irq-name: %s\n", vq->irq_name);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(vq);
+
+void pds_vdpa_debugfs_add_vdpadev(struct pds_vdpa_aux *vdpa_aux)
+{
+ int i;
+
+ debugfs_create_file("config", 0400, vdpa_aux->dentry, vdpa_aux->pdsv, &config_fops);
+
+ for (i = 0; i < vdpa_aux->pdsv->num_vqs; i++) {
+ char name[8];
+
+ snprintf(name, sizeof(name), "vq%02d", i);
+ debugfs_create_file(name, 0400, vdpa_aux->dentry,
+ &vdpa_aux->pdsv->vqs[i], &vq_fops);
+ }
+}
+
+void pds_vdpa_debugfs_del_vdpadev(struct pds_vdpa_aux *vdpa_aux)
+{
+ debugfs_remove_recursive(vdpa_aux->dentry);
+ vdpa_aux->dentry = NULL;
+}
+
+void pds_vdpa_debugfs_reset_vdpadev(struct pds_vdpa_aux *vdpa_aux)
+{
+ /* we don't keep track of the entries, so remove it all
+ * then rebuild the basics
+ */
+ pds_vdpa_debugfs_del_vdpadev(vdpa_aux);
+ pds_vdpa_debugfs_add_pcidev(vdpa_aux);
+ pds_vdpa_debugfs_add_ident(vdpa_aux);
+}
diff --git a/drivers/vdpa/pds/debugfs.h b/drivers/vdpa/pds/debugfs.h
new file mode 100644
index 000000000000..c088a4e8f1e9
--- /dev/null
+++ b/drivers/vdpa/pds/debugfs.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2023 Advanced Micro Devices, Inc */
+
+#ifndef _PDS_VDPA_DEBUGFS_H_
+#define _PDS_VDPA_DEBUGFS_H_
+
+#include <linux/debugfs.h>
+
+void pds_vdpa_debugfs_create(void);
+void pds_vdpa_debugfs_destroy(void);
+void pds_vdpa_debugfs_add_pcidev(struct pds_vdpa_aux *vdpa_aux);
+void pds_vdpa_debugfs_add_ident(struct pds_vdpa_aux *vdpa_aux);
+void pds_vdpa_debugfs_add_vdpadev(struct pds_vdpa_aux *vdpa_aux);
+void pds_vdpa_debugfs_del_vdpadev(struct pds_vdpa_aux *vdpa_aux);
+void pds_vdpa_debugfs_reset_vdpadev(struct pds_vdpa_aux *vdpa_aux);
+
+#endif /* _PDS_VDPA_DEBUGFS_H_ */
diff --git a/drivers/vdpa/pds/vdpa_dev.c b/drivers/vdpa/pds/vdpa_dev.c
new file mode 100644
index 000000000000..5071a4d58f8d
--- /dev/null
+++ b/drivers/vdpa/pds/vdpa_dev.c
@@ -0,0 +1,769 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Advanced Micro Devices, Inc */
+
+#include <linux/pci.h>
+#include <linux/vdpa.h>
+#include <uapi/linux/vdpa.h>
+#include <linux/virtio_pci_modern.h>
+
+#include <linux/pds/pds_common.h>
+#include <linux/pds/pds_core_if.h>
+#include <linux/pds/pds_adminq.h>
+#include <linux/pds/pds_auxbus.h>
+
+#include "vdpa_dev.h"
+#include "aux_drv.h"
+#include "cmds.h"
+#include "debugfs.h"
+
+static u64 pds_vdpa_get_driver_features(struct vdpa_device *vdpa_dev);
+
+static struct pds_vdpa_device *vdpa_to_pdsv(struct vdpa_device *vdpa_dev)
+{
+ return container_of(vdpa_dev, struct pds_vdpa_device, vdpa_dev);
+}
+
+static int pds_vdpa_notify_handler(struct notifier_block *nb,
+ unsigned long ecode,
+ void *data)
+{
+ struct pds_vdpa_device *pdsv = container_of(nb, struct pds_vdpa_device, nb);
+ struct device *dev = &pdsv->vdpa_aux->padev->aux_dev.dev;
+
+ dev_dbg(dev, "%s: event code %lu\n", __func__, ecode);
+
+ if (ecode == PDS_EVENT_RESET || ecode == PDS_EVENT_LINK_CHANGE) {
+ if (pdsv->config_cb.callback)
+ pdsv->config_cb.callback(pdsv->config_cb.private);
+ }
+
+ return 0;
+}
+
+static int pds_vdpa_register_event_handler(struct pds_vdpa_device *pdsv)
+{
+ struct device *dev = &pdsv->vdpa_aux->padev->aux_dev.dev;
+ struct notifier_block *nb = &pdsv->nb;
+ int err;
+
+ if (!nb->notifier_call) {
+ nb->notifier_call = pds_vdpa_notify_handler;
+ err = pdsc_register_notify(nb);
+ if (err) {
+ nb->notifier_call = NULL;
+ dev_err(dev, "failed to register pds event handler: %ps\n",
+ ERR_PTR(err));
+ return -EINVAL;
+ }
+ dev_dbg(dev, "pds event handler registered\n");
+ }
+
+ return 0;
+}
+
+static void pds_vdpa_unregister_event_handler(struct pds_vdpa_device *pdsv)
+{
+ if (pdsv->nb.notifier_call) {
+ pdsc_unregister_notify(&pdsv->nb);
+ pdsv->nb.notifier_call = NULL;
+ }
+}
+
+static int pds_vdpa_set_vq_address(struct vdpa_device *vdpa_dev, u16 qid,
+ u64 desc_addr, u64 driver_addr, u64 device_addr)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+
+ pdsv->vqs[qid].desc_addr = desc_addr;
+ pdsv->vqs[qid].avail_addr = driver_addr;
+ pdsv->vqs[qid].used_addr = device_addr;
+
+ return 0;
+}
+
+static void pds_vdpa_set_vq_num(struct vdpa_device *vdpa_dev, u16 qid, u32 num)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+
+ pdsv->vqs[qid].q_len = num;
+}
+
+static void pds_vdpa_kick_vq(struct vdpa_device *vdpa_dev, u16 qid)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+
+ iowrite16(qid, pdsv->vqs[qid].notify);
+}
+
+static void pds_vdpa_set_vq_cb(struct vdpa_device *vdpa_dev, u16 qid,
+ struct vdpa_callback *cb)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+
+ pdsv->vqs[qid].event_cb = *cb;
+}
+
+static irqreturn_t pds_vdpa_isr(int irq, void *data)
+{
+ struct pds_vdpa_vq_info *vq;
+
+ vq = data;
+ if (vq->event_cb.callback)
+ vq->event_cb.callback(vq->event_cb.private);
+
+ return IRQ_HANDLED;
+}
+
+static void pds_vdpa_release_irq(struct pds_vdpa_device *pdsv, int qid)
+{
+ if (pdsv->vqs[qid].irq == VIRTIO_MSI_NO_VECTOR)
+ return;
+
+ free_irq(pdsv->vqs[qid].irq, &pdsv->vqs[qid]);
+ pdsv->vqs[qid].irq = VIRTIO_MSI_NO_VECTOR;
+}
+
+static void pds_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, u16 qid, bool ready)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+ struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev;
+ struct device *dev = &pdsv->vdpa_dev.dev;
+ u64 driver_features;
+ u16 invert_idx = 0;
+ int irq;
+ int err;
+
+ dev_dbg(dev, "%s: qid %d ready %d => %d\n",
+ __func__, qid, pdsv->vqs[qid].ready, ready);
+ if (ready == pdsv->vqs[qid].ready)
+ return;
+
+ driver_features = pds_vdpa_get_driver_features(vdpa_dev);
+ if (driver_features & BIT_ULL(VIRTIO_F_RING_PACKED))
+ invert_idx = PDS_VDPA_PACKED_INVERT_IDX;
+
+ if (ready) {
+ irq = pci_irq_vector(pdev, qid);
+ snprintf(pdsv->vqs[qid].irq_name, sizeof(pdsv->vqs[qid].irq_name),
+ "vdpa-%s-%d", dev_name(dev), qid);
+
+ err = request_irq(irq, pds_vdpa_isr, 0,
+ pdsv->vqs[qid].irq_name, &pdsv->vqs[qid]);
+ if (err) {
+ dev_err(dev, "%s: no irq for qid %d: %pe\n",
+ __func__, qid, ERR_PTR(err));
+ return;
+ }
+ pdsv->vqs[qid].irq = irq;
+
+ /* Pass vq setup info to DSC using adminq to gather up and
+ * send all info at once so FW can do its full set up in
+ * one easy operation
+ */
+ err = pds_vdpa_cmd_init_vq(pdsv, qid, invert_idx, &pdsv->vqs[qid]);
+ if (err) {
+ dev_err(dev, "Failed to init vq %d: %pe\n",
+ qid, ERR_PTR(err));
+ pds_vdpa_release_irq(pdsv, qid);
+ ready = false;
+ }
+ } else {
+ err = pds_vdpa_cmd_reset_vq(pdsv, qid, invert_idx, &pdsv->vqs[qid]);
+ if (err)
+ dev_err(dev, "%s: reset_vq failed qid %d: %pe\n",
+ __func__, qid, ERR_PTR(err));
+ pds_vdpa_release_irq(pdsv, qid);
+ }
+
+ pdsv->vqs[qid].ready = ready;
+}
+
+static bool pds_vdpa_get_vq_ready(struct vdpa_device *vdpa_dev, u16 qid)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+
+ return pdsv->vqs[qid].ready;
+}
+
+static int pds_vdpa_set_vq_state(struct vdpa_device *vdpa_dev, u16 qid,
+ const struct vdpa_vq_state *state)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+ struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev;
+ struct device *dev = &padev->aux_dev.dev;
+ u64 driver_features;
+ u16 avail;
+ u16 used;
+
+ if (pdsv->vqs[qid].ready) {
+ dev_err(dev, "Setting device position is denied while vq is enabled\n");
+ return -EINVAL;
+ }
+
+ driver_features = pds_vdpa_get_driver_features(vdpa_dev);
+ if (driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) {
+ avail = state->packed.last_avail_idx |
+ (state->packed.last_avail_counter << 15);
+ used = state->packed.last_used_idx |
+ (state->packed.last_used_counter << 15);
+
+ /* The avail and used index are stored with the packed wrap
+ * counter bit inverted. This way, in case set_vq_state is
+ * not called, the initial value can be set to zero prior to
+ * feature negotiation, and it is good for both packed and
+ * split vq.
+ */
+ avail ^= PDS_VDPA_PACKED_INVERT_IDX;
+ used ^= PDS_VDPA_PACKED_INVERT_IDX;
+ } else {
+ avail = state->split.avail_index;
+ /* state->split does not provide a used_index:
+ * the vq will be set to "empty" here, and the vq will read
+ * the current used index the next time the vq is kicked.
+ */
+ used = avail;
+ }
+
+ if (used != avail) {
+ dev_dbg(dev, "Setting used equal to avail, for interoperability\n");
+ used = avail;
+ }
+
+ pdsv->vqs[qid].avail_idx = avail;
+ pdsv->vqs[qid].used_idx = used;
+
+ return 0;
+}
+
+static int pds_vdpa_get_vq_state(struct vdpa_device *vdpa_dev, u16 qid,
+ struct vdpa_vq_state *state)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+ struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev;
+ struct device *dev = &padev->aux_dev.dev;
+ u64 driver_features;
+ u16 avail;
+ u16 used;
+
+ if (pdsv->vqs[qid].ready) {
+ dev_err(dev, "Getting device position is denied while vq is enabled\n");
+ return -EINVAL;
+ }
+
+ avail = pdsv->vqs[qid].avail_idx;
+ used = pdsv->vqs[qid].used_idx;
+
+ driver_features = pds_vdpa_get_driver_features(vdpa_dev);
+ if (driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) {
+ avail ^= PDS_VDPA_PACKED_INVERT_IDX;
+ used ^= PDS_VDPA_PACKED_INVERT_IDX;
+
+ state->packed.last_avail_idx = avail & 0x7fff;
+ state->packed.last_avail_counter = avail >> 15;
+ state->packed.last_used_idx = used & 0x7fff;
+ state->packed.last_used_counter = used >> 15;
+ } else {
+ state->split.avail_index = avail;
+ /* state->split does not provide a used_index. */
+ }
+
+ return 0;
+}
+
+static struct vdpa_notification_area
+pds_vdpa_get_vq_notification(struct vdpa_device *vdpa_dev, u16 qid)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+ struct virtio_pci_modern_device *vd_mdev;
+ struct vdpa_notification_area area;
+
+ area.addr = pdsv->vqs[qid].notify_pa;
+
+ vd_mdev = &pdsv->vdpa_aux->vd_mdev;
+ if (!vd_mdev->notify_offset_multiplier)
+ area.size = PDS_PAGE_SIZE;
+ else
+ area.size = vd_mdev->notify_offset_multiplier;
+
+ return area;
+}
+
+static int pds_vdpa_get_vq_irq(struct vdpa_device *vdpa_dev, u16 qid)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+
+ return pdsv->vqs[qid].irq;
+}
+
+static u32 pds_vdpa_get_vq_align(struct vdpa_device *vdpa_dev)
+{
+ return PDS_PAGE_SIZE;
+}
+
+static u32 pds_vdpa_get_vq_group(struct vdpa_device *vdpa_dev, u16 idx)
+{
+ return 0;
+}
+
+static u64 pds_vdpa_get_device_features(struct vdpa_device *vdpa_dev)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+
+ return pdsv->supported_features;
+}
+
+static int pds_vdpa_set_driver_features(struct vdpa_device *vdpa_dev, u64 features)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+ struct device *dev = &pdsv->vdpa_dev.dev;
+ u64 driver_features;
+ u64 nego_features;
+ u64 missing;
+
+ if (!(features & BIT_ULL(VIRTIO_F_ACCESS_PLATFORM)) && features) {
+ dev_err(dev, "VIRTIO_F_ACCESS_PLATFORM is not negotiated\n");
+ return -EOPNOTSUPP;
+ }
+
+ pdsv->req_features = features;
+
+ /* Check for valid feature bits */
+ nego_features = features & le64_to_cpu(pdsv->vdpa_aux->ident.hw_features);
+ missing = pdsv->req_features & ~nego_features;
+ if (missing) {
+ dev_err(dev, "Can't support all requested features in %#llx, missing %#llx features\n",
+ pdsv->req_features, missing);
+ return -EOPNOTSUPP;
+ }
+
+ driver_features = pds_vdpa_get_driver_features(vdpa_dev);
+ dev_dbg(dev, "%s: %#llx => %#llx\n",
+ __func__, driver_features, nego_features);
+
+ if (driver_features == nego_features)
+ return 0;
+
+ vp_modern_set_features(&pdsv->vdpa_aux->vd_mdev, nego_features);
+
+ return 0;
+}
+
+static u64 pds_vdpa_get_driver_features(struct vdpa_device *vdpa_dev)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+
+ return vp_modern_get_driver_features(&pdsv->vdpa_aux->vd_mdev);
+}
+
+static void pds_vdpa_set_config_cb(struct vdpa_device *vdpa_dev,
+ struct vdpa_callback *cb)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+
+ pdsv->config_cb.callback = cb->callback;
+ pdsv->config_cb.private = cb->private;
+}
+
+static u16 pds_vdpa_get_vq_num_max(struct vdpa_device *vdpa_dev)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+
+ /* qemu has assert() that vq_num_max <= VIRTQUEUE_MAX_SIZE (1024) */
+ return min_t(u16, 1024, BIT(le16_to_cpu(pdsv->vdpa_aux->ident.max_qlen)));
+}
+
+static u32 pds_vdpa_get_device_id(struct vdpa_device *vdpa_dev)
+{
+ return VIRTIO_ID_NET;
+}
+
+static u32 pds_vdpa_get_vendor_id(struct vdpa_device *vdpa_dev)
+{
+ return PCI_VENDOR_ID_PENSANDO;
+}
+
+static u8 pds_vdpa_get_status(struct vdpa_device *vdpa_dev)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+
+ return vp_modern_get_status(&pdsv->vdpa_aux->vd_mdev);
+}
+
+static void pds_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+ struct device *dev = &pdsv->vdpa_dev.dev;
+ u8 old_status;
+ int i;
+
+ old_status = pds_vdpa_get_status(vdpa_dev);
+ dev_dbg(dev, "%s: old %#x new %#x\n", __func__, old_status, status);
+
+ pds_vdpa_cmd_set_status(pdsv, status);
+
+ /* Note: still working with FW on the need for this reset cmd */
+ if (status == 0) {
+ pds_vdpa_cmd_reset(pdsv);
+
+ for (i = 0; i < pdsv->num_vqs; i++) {
+ pdsv->vqs[i].avail_idx = 0;
+ pdsv->vqs[i].used_idx = 0;
+ }
+ }
+
+ if (status & ~old_status & VIRTIO_CONFIG_S_FEATURES_OK) {
+ for (i = 0; i < pdsv->num_vqs; i++) {
+ pdsv->vqs[i].notify =
+ vp_modern_map_vq_notify(&pdsv->vdpa_aux->vd_mdev,
+ i, &pdsv->vqs[i].notify_pa);
+ }
+ }
+}
+
+static int pds_vdpa_reset(struct vdpa_device *vdpa_dev)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+ struct device *dev;
+ int err = 0;
+ u8 status;
+ int i;
+
+ dev = &pdsv->vdpa_aux->padev->aux_dev.dev;
+ status = pds_vdpa_get_status(vdpa_dev);
+
+ if (status == 0)
+ return 0;
+
+ if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
+ /* Reset the vqs */
+ for (i = 0; i < pdsv->num_vqs && !err; i++) {
+ err = pds_vdpa_cmd_reset_vq(pdsv, i, 0, &pdsv->vqs[i]);
+ if (err)
+ dev_err(dev, "%s: reset_vq failed qid %d: %pe\n",
+ __func__, i, ERR_PTR(err));
+ pds_vdpa_release_irq(pdsv, i);
+ memset(&pdsv->vqs[i], 0, sizeof(pdsv->vqs[0]));
+ pdsv->vqs[i].ready = false;
+ }
+ }
+
+ pds_vdpa_set_status(vdpa_dev, 0);
+
+ return 0;
+}
+
+static size_t pds_vdpa_get_config_size(struct vdpa_device *vdpa_dev)
+{
+ return sizeof(struct virtio_net_config);
+}
+
+static void pds_vdpa_get_config(struct vdpa_device *vdpa_dev,
+ unsigned int offset,
+ void *buf, unsigned int len)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+ void __iomem *device;
+
+ if (offset + len > sizeof(struct virtio_net_config)) {
+ WARN(true, "%s: bad read, offset %d len %d\n", __func__, offset, len);
+ return;
+ }
+
+ device = pdsv->vdpa_aux->vd_mdev.device;
+ memcpy_fromio(buf, device + offset, len);
+}
+
+static void pds_vdpa_set_config(struct vdpa_device *vdpa_dev,
+ unsigned int offset, const void *buf,
+ unsigned int len)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+ void __iomem *device;
+
+ if (offset + len > sizeof(struct virtio_net_config)) {
+ WARN(true, "%s: bad read, offset %d len %d\n", __func__, offset, len);
+ return;
+ }
+
+ device = pdsv->vdpa_aux->vd_mdev.device;
+ memcpy_toio(device + offset, buf, len);
+}
+
+static const struct vdpa_config_ops pds_vdpa_ops = {
+ .set_vq_address = pds_vdpa_set_vq_address,
+ .set_vq_num = pds_vdpa_set_vq_num,
+ .kick_vq = pds_vdpa_kick_vq,
+ .set_vq_cb = pds_vdpa_set_vq_cb,
+ .set_vq_ready = pds_vdpa_set_vq_ready,
+ .get_vq_ready = pds_vdpa_get_vq_ready,
+ .set_vq_state = pds_vdpa_set_vq_state,
+ .get_vq_state = pds_vdpa_get_vq_state,
+ .get_vq_notification = pds_vdpa_get_vq_notification,
+ .get_vq_irq = pds_vdpa_get_vq_irq,
+ .get_vq_align = pds_vdpa_get_vq_align,
+ .get_vq_group = pds_vdpa_get_vq_group,
+
+ .get_device_features = pds_vdpa_get_device_features,
+ .set_driver_features = pds_vdpa_set_driver_features,
+ .get_driver_features = pds_vdpa_get_driver_features,
+ .set_config_cb = pds_vdpa_set_config_cb,
+ .get_vq_num_max = pds_vdpa_get_vq_num_max,
+ .get_device_id = pds_vdpa_get_device_id,
+ .get_vendor_id = pds_vdpa_get_vendor_id,
+ .get_status = pds_vdpa_get_status,
+ .set_status = pds_vdpa_set_status,
+ .reset = pds_vdpa_reset,
+ .get_config_size = pds_vdpa_get_config_size,
+ .get_config = pds_vdpa_get_config,
+ .set_config = pds_vdpa_set_config,
+};
+static struct virtio_device_id pds_vdpa_id_table[] = {
+ {VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID},
+ {0},
+};
+
+static int pds_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
+ const struct vdpa_dev_set_config *add_config)
+{
+ struct pds_vdpa_aux *vdpa_aux;
+ struct pds_vdpa_device *pdsv;
+ struct vdpa_mgmt_dev *mgmt;
+ u16 fw_max_vqs, vq_pairs;
+ struct device *dma_dev;
+ struct pci_dev *pdev;
+ struct device *dev;
+ u8 mac[ETH_ALEN];
+ int err;
+ int i;
+
+ vdpa_aux = container_of(mdev, struct pds_vdpa_aux, vdpa_mdev);
+ dev = &vdpa_aux->padev->aux_dev.dev;
+ mgmt = &vdpa_aux->vdpa_mdev;
+
+ if (vdpa_aux->pdsv) {
+ dev_warn(dev, "Multiple vDPA devices on a VF is not supported.\n");
+ return -EOPNOTSUPP;
+ }
+
+ pdsv = vdpa_alloc_device(struct pds_vdpa_device, vdpa_dev,
+ dev, &pds_vdpa_ops, 1, 1, name, false);
+ if (IS_ERR(pdsv)) {
+ dev_err(dev, "Failed to allocate vDPA structure: %pe\n", pdsv);
+ return PTR_ERR(pdsv);
+ }
+
+ vdpa_aux->pdsv = pdsv;
+ pdsv->vdpa_aux = vdpa_aux;
+
+ pdev = vdpa_aux->padev->vf_pdev;
+ dma_dev = &pdev->dev;
+ pdsv->vdpa_dev.dma_dev = dma_dev;
+
+ pdsv->supported_features = mgmt->supported_features;
+
+ if (add_config->mask & BIT_ULL(VDPA_ATTR_DEV_FEATURES)) {
+ u64 unsupp_features =
+ add_config->device_features & ~mgmt->supported_features;
+
+ if (unsupp_features) {
+ dev_err(dev, "Unsupported features: %#llx\n", unsupp_features);
+ err = -EOPNOTSUPP;
+ goto err_unmap;
+ }
+
+ pdsv->supported_features = add_config->device_features;
+ }
+
+ err = pds_vdpa_cmd_reset(pdsv);
+ if (err) {
+ dev_err(dev, "Failed to reset hw: %pe\n", ERR_PTR(err));
+ goto err_unmap;
+ }
+
+ err = pds_vdpa_init_hw(pdsv);
+ if (err) {
+ dev_err(dev, "Failed to init hw: %pe\n", ERR_PTR(err));
+ goto err_unmap;
+ }
+
+ fw_max_vqs = le16_to_cpu(pdsv->vdpa_aux->ident.max_vqs);
+ vq_pairs = fw_max_vqs / 2;
+
+ /* Make sure we have the queues being requested */
+ if (add_config->mask & (1 << VDPA_ATTR_DEV_NET_CFG_MAX_VQP))
+ vq_pairs = add_config->net.max_vq_pairs;
+
+ pdsv->num_vqs = 2 * vq_pairs;
+ if (pdsv->supported_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ))
+ pdsv->num_vqs++;
+
+ if (pdsv->num_vqs > fw_max_vqs) {
+ dev_err(dev, "%s: queue count requested %u greater than max %u\n",
+ __func__, pdsv->num_vqs, fw_max_vqs);
+ err = -ENOSPC;
+ goto err_unmap;
+ }
+
+ if (pdsv->num_vqs != fw_max_vqs) {
+ err = pds_vdpa_cmd_set_max_vq_pairs(pdsv, vq_pairs);
+ if (err) {
+ dev_err(dev, "Failed to set max_vq_pairs: %pe\n",
+ ERR_PTR(err));
+ goto err_unmap;
+ }
+ }
+
+ /* Set a mac, either from the user config if provided
+ * or set a random mac if default is 00:..:00
+ */
+ if (add_config->mask & BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR)) {
+ ether_addr_copy(mac, add_config->net.mac);
+ pds_vdpa_cmd_set_mac(pdsv, mac);
+ } else {
+ struct virtio_net_config __iomem *vc;
+
+ vc = pdsv->vdpa_aux->vd_mdev.device;
+ memcpy_fromio(mac, vc->mac, sizeof(mac));
+ if (is_zero_ether_addr(mac)) {
+ eth_random_addr(mac);
+ dev_info(dev, "setting random mac %pM\n", mac);
+ pds_vdpa_cmd_set_mac(pdsv, mac);
+ }
+ }
+
+ for (i = 0; i < pdsv->num_vqs; i++) {
+ pdsv->vqs[i].qid = i;
+ pdsv->vqs[i].pdsv = pdsv;
+ pdsv->vqs[i].irq = VIRTIO_MSI_NO_VECTOR;
+ pdsv->vqs[i].notify = vp_modern_map_vq_notify(&pdsv->vdpa_aux->vd_mdev,
+ i, &pdsv->vqs[i].notify_pa);
+ }
+
+ pdsv->vdpa_dev.mdev = &vdpa_aux->vdpa_mdev;
+
+ err = pds_vdpa_register_event_handler(pdsv);
+ if (err) {
+ dev_err(dev, "Failed to register for PDS events: %pe\n", ERR_PTR(err));
+ goto err_unmap;
+ }
+
+ /* We use the _vdpa_register_device() call rather than the
+ * vdpa_register_device() to avoid a deadlock because our
+ * dev_add() is called with the vdpa_dev_lock already set
+ * by vdpa_nl_cmd_dev_add_set_doit()
+ */
+ err = _vdpa_register_device(&pdsv->vdpa_dev, pdsv->num_vqs);
+ if (err) {
+ dev_err(dev, "Failed to register to vDPA bus: %pe\n", ERR_PTR(err));
+ goto err_unevent;
+ }
+
+ pds_vdpa_debugfs_add_vdpadev(vdpa_aux);
+
+ return 0;
+
+err_unevent:
+ pds_vdpa_unregister_event_handler(pdsv);
+err_unmap:
+ put_device(&pdsv->vdpa_dev.dev);
+ vdpa_aux->pdsv = NULL;
+ return err;
+}
+
+static void pds_vdpa_dev_del(struct vdpa_mgmt_dev *mdev,
+ struct vdpa_device *vdpa_dev)
+{
+ struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
+ struct pds_vdpa_aux *vdpa_aux;
+
+ pds_vdpa_unregister_event_handler(pdsv);
+
+ vdpa_aux = container_of(mdev, struct pds_vdpa_aux, vdpa_mdev);
+ _vdpa_unregister_device(vdpa_dev);
+
+ pds_vdpa_cmd_reset(vdpa_aux->pdsv);
+ pds_vdpa_debugfs_reset_vdpadev(vdpa_aux);
+
+ vdpa_aux->pdsv = NULL;
+
+ dev_info(&vdpa_aux->padev->aux_dev.dev, "Removed vdpa device\n");
+}
+
+static const struct vdpa_mgmtdev_ops pds_vdpa_mgmt_dev_ops = {
+ .dev_add = pds_vdpa_dev_add,
+ .dev_del = pds_vdpa_dev_del
+};
+
+int pds_vdpa_get_mgmt_info(struct pds_vdpa_aux *vdpa_aux)
+{
+ union pds_core_adminq_cmd cmd = {
+ .vdpa_ident.opcode = PDS_VDPA_CMD_IDENT,
+ .vdpa_ident.vf_id = cpu_to_le16(vdpa_aux->vf_id),
+ };
+ union pds_core_adminq_comp comp = {};
+ struct vdpa_mgmt_dev *mgmt;
+ struct pci_dev *pf_pdev;
+ struct device *pf_dev;
+ struct pci_dev *pdev;
+ dma_addr_t ident_pa;
+ struct device *dev;
+ u16 dev_intrs;
+ u16 max_vqs;
+ int err;
+
+ dev = &vdpa_aux->padev->aux_dev.dev;
+ pdev = vdpa_aux->padev->vf_pdev;
+ mgmt = &vdpa_aux->vdpa_mdev;
+
+ /* Get resource info through the PF's adminq. It is a block of info,
+ * so we need to map some memory for PF to make available to the
+ * firmware for writing the data.
+ */
+ pf_pdev = pci_physfn(vdpa_aux->padev->vf_pdev);
+ pf_dev = &pf_pdev->dev;
+ ident_pa = dma_map_single(pf_dev, &vdpa_aux->ident,
+ sizeof(vdpa_aux->ident), DMA_FROM_DEVICE);
+ if (dma_mapping_error(pf_dev, ident_pa)) {
+ dev_err(dev, "Failed to map ident space\n");
+ return -ENOMEM;
+ }
+
+ cmd.vdpa_ident.ident_pa = cpu_to_le64(ident_pa);
+ cmd.vdpa_ident.len = cpu_to_le32(sizeof(vdpa_aux->ident));
+ err = pds_client_adminq_cmd(vdpa_aux->padev, &cmd,
+ sizeof(cmd.vdpa_ident), &comp, 0);
+ dma_unmap_single(pf_dev, ident_pa,
+ sizeof(vdpa_aux->ident), DMA_FROM_DEVICE);
+ if (err) {
+ dev_err(dev, "Failed to ident hw, status %d: %pe\n",
+ comp.status, ERR_PTR(err));
+ return err;
+ }
+
+ max_vqs = le16_to_cpu(vdpa_aux->ident.max_vqs);
+ dev_intrs = pci_msix_vec_count(pdev);
+ dev_dbg(dev, "ident.max_vqs %d dev_intrs %d\n", max_vqs, dev_intrs);
+
+ max_vqs = min_t(u16, dev_intrs, max_vqs);
+ mgmt->max_supported_vqs = min_t(u16, PDS_VDPA_MAX_QUEUES, max_vqs);
+ vdpa_aux->nintrs = mgmt->max_supported_vqs;
+
+ mgmt->ops = &pds_vdpa_mgmt_dev_ops;
+ mgmt->id_table = pds_vdpa_id_table;
+ mgmt->device = dev;
+ mgmt->supported_features = le64_to_cpu(vdpa_aux->ident.hw_features);
+ mgmt->config_attr_mask = BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR);
+ mgmt->config_attr_mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP);
+ mgmt->config_attr_mask |= BIT_ULL(VDPA_ATTR_DEV_FEATURES);
+
+ err = pci_alloc_irq_vectors(pdev, vdpa_aux->nintrs, vdpa_aux->nintrs,
+ PCI_IRQ_MSIX);
+ if (err < 0) {
+ dev_err(dev, "Couldn't get %d msix vectors: %pe\n",
+ vdpa_aux->nintrs, ERR_PTR(err));
+ return err;
+ }
+ vdpa_aux->nintrs = err;
+
+ return 0;
+}
diff --git a/drivers/vdpa/pds/vdpa_dev.h b/drivers/vdpa/pds/vdpa_dev.h
new file mode 100644
index 000000000000..a1bc37de9537
--- /dev/null
+++ b/drivers/vdpa/pds/vdpa_dev.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2023 Advanced Micro Devices, Inc */
+
+#ifndef _VDPA_DEV_H_
+#define _VDPA_DEV_H_
+
+#include <linux/pci.h>
+#include <linux/vdpa.h>
+
+struct pds_vdpa_vq_info {
+ bool ready;
+ u64 desc_addr;
+ u64 avail_addr;
+ u64 used_addr;
+ u32 q_len;
+ u16 qid;
+ int irq;
+ char irq_name[32];
+
+ void __iomem *notify;
+ dma_addr_t notify_pa;
+
+ u64 doorbell;
+ u16 avail_idx;
+ u16 used_idx;
+
+ struct vdpa_callback event_cb;
+ struct pds_vdpa_device *pdsv;
+};
+
+#define PDS_VDPA_MAX_QUEUES 65
+#define PDS_VDPA_MAX_QLEN 32768
+struct pds_vdpa_device {
+ struct vdpa_device vdpa_dev;
+ struct pds_vdpa_aux *vdpa_aux;
+
+ struct pds_vdpa_vq_info vqs[PDS_VDPA_MAX_QUEUES];
+ u64 supported_features; /* specified device features */
+ u64 req_features; /* features requested by vdpa */
+ u8 vdpa_index; /* rsvd for future subdevice use */
+ u8 num_vqs; /* num vqs in use */
+ struct vdpa_callback config_cb;
+ struct notifier_block nb;
+};
+
+#define PDS_VDPA_PACKED_INVERT_IDX 0x8000
+
+int pds_vdpa_get_mgmt_info(struct pds_vdpa_aux *vdpa_aux);
+#endif /* _VDPA_DEV_H_ */
diff --git a/drivers/vdpa/solidrun/snet_ctrl.c b/drivers/vdpa/solidrun/snet_ctrl.c
index 3858738643b4..3cef2571d15d 100644
--- a/drivers/vdpa/solidrun/snet_ctrl.c
+++ b/drivers/vdpa/solidrun/snet_ctrl.c
@@ -16,6 +16,7 @@ enum snet_ctrl_opcodes {
SNET_CTRL_OP_DESTROY = 1,
SNET_CTRL_OP_READ_VQ_STATE,
SNET_CTRL_OP_SUSPEND,
+ SNET_CTRL_OP_RESUME,
};
#define SNET_CTRL_TIMEOUT 2000000
@@ -328,3 +329,8 @@ int snet_suspend_dev(struct snet *snet)
{
return snet_send_ctrl_msg(snet, SNET_CTRL_OP_SUSPEND, 0);
}
+
+int snet_resume_dev(struct snet *snet)
+{
+ return snet_send_ctrl_msg(snet, SNET_CTRL_OP_RESUME, 0);
+}
diff --git a/drivers/vdpa/solidrun/snet_hwmon.c b/drivers/vdpa/solidrun/snet_hwmon.c
index 42c87387a0f1..af531a339082 100644
--- a/drivers/vdpa/solidrun/snet_hwmon.c
+++ b/drivers/vdpa/solidrun/snet_hwmon.c
@@ -159,7 +159,7 @@ static const struct hwmon_ops snet_hwmon_ops = {
.read_string = snet_hwmon_read_string
};
-static const struct hwmon_channel_info *snet_hwmon_info[] = {
+static const struct hwmon_channel_info * const snet_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_LABEL,
HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LABEL),
HWMON_CHANNEL_INFO(power, HWMON_P_INPUT | HWMON_P_LABEL),
diff --git a/drivers/vdpa/solidrun/snet_main.c b/drivers/vdpa/solidrun/snet_main.c
index cdcd84ce4f5a..99428a04068d 100644
--- a/drivers/vdpa/solidrun/snet_main.c
+++ b/drivers/vdpa/solidrun/snet_main.c
@@ -509,6 +509,20 @@ static int snet_suspend(struct vdpa_device *vdev)
return ret;
}
+static int snet_resume(struct vdpa_device *vdev)
+{
+ struct snet *snet = vdpa_to_snet(vdev);
+ int ret;
+
+ ret = snet_resume_dev(snet);
+ if (ret)
+ SNET_ERR(snet->pdev, "SNET[%u] resume failed, err: %d\n", snet->sid, ret);
+ else
+ SNET_DBG(snet->pdev, "Resume SNET[%u] device\n", snet->sid);
+
+ return ret;
+}
+
static const struct vdpa_config_ops snet_config_ops = {
.set_vq_address = snet_set_vq_address,
.set_vq_num = snet_set_vq_num,
@@ -536,6 +550,7 @@ static const struct vdpa_config_ops snet_config_ops = {
.get_config = snet_get_config,
.set_config = snet_set_config,
.suspend = snet_suspend,
+ .resume = snet_resume,
};
static int psnet_open_pf_bar(struct pci_dev *pdev, struct psnet *psnet)
diff --git a/drivers/vdpa/solidrun/snet_vdpa.h b/drivers/vdpa/solidrun/snet_vdpa.h
index 3c78d4e7d485..36ac285835ea 100644
--- a/drivers/vdpa/solidrun/snet_vdpa.h
+++ b/drivers/vdpa/solidrun/snet_vdpa.h
@@ -204,5 +204,6 @@ void snet_ctrl_clear(struct snet *snet);
int snet_destroy_dev(struct snet *snet);
int snet_read_vq_state(struct snet *snet, u16 idx, struct vdpa_vq_state *state);
int snet_suspend_dev(struct snet *snet);
+int snet_resume_dev(struct snet *snet);
#endif //_SNET_VDPA_H_
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
index 4619b4a520ef..dc38ed21319d 100644
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
+++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -726,7 +726,11 @@ static int vduse_vdpa_set_vq_affinity(struct vdpa_device *vdpa, u16 idx,
{
struct vduse_dev *dev = vdpa_to_vduse(vdpa);
- cpumask_copy(&dev->vqs[idx]->irq_affinity, cpu_mask);
+ if (cpu_mask)
+ cpumask_copy(&dev->vqs[idx]->irq_affinity, cpu_mask);
+ else
+ cpumask_setall(&dev->vqs[idx]->irq_affinity);
+
return 0;
}
diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index 89e06c981e43..aba36f5be4ec 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -57,6 +57,7 @@ source "drivers/vfio/pci/Kconfig"
source "drivers/vfio/platform/Kconfig"
source "drivers/vfio/mdev/Kconfig"
source "drivers/vfio/fsl-mc/Kconfig"
+source "drivers/vfio/cdx/Kconfig"
endif
source "virt/lib/Kconfig"
diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index 70e7dcb302ef..66f418aef5a9 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -10,7 +10,8 @@ vfio-$(CONFIG_VFIO_VIRQFD) += virqfd.o
obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
-obj-$(CONFIG_VFIO_PCI) += pci/
-obj-$(CONFIG_VFIO_PLATFORM) += platform/
+obj-$(CONFIG_VFIO_PCI_CORE) += pci/
+obj-$(CONFIG_VFIO_PLATFORM_BASE) += platform/
obj-$(CONFIG_VFIO_MDEV) += mdev/
obj-$(CONFIG_VFIO_FSL_MC) += fsl-mc/
+obj-$(CONFIG_VFIO_CDX) += cdx/
diff --git a/drivers/vfio/cdx/Kconfig b/drivers/vfio/cdx/Kconfig
new file mode 100644
index 000000000000..e6de0a0caa32
--- /dev/null
+++ b/drivers/vfio/cdx/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# VFIO CDX configuration
+#
+# Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
+#
+
+config VFIO_CDX
+ tristate "VFIO support for CDX bus devices"
+ depends on CDX_BUS
+ select EVENTFD
+ help
+ Driver to enable VFIO support for the devices on CDX bus.
+ This is required to make use of CDX devices present in
+ the system using the VFIO framework.
+
+ If you don't know what to do here, say N.
diff --git a/drivers/vfio/cdx/Makefile b/drivers/vfio/cdx/Makefile
new file mode 100644
index 000000000000..cd4a2e6fe609
--- /dev/null
+++ b/drivers/vfio/cdx/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
+#
+
+obj-$(CONFIG_VFIO_CDX) += vfio-cdx.o
+
+vfio-cdx-objs := main.o
diff --git a/drivers/vfio/cdx/main.c b/drivers/vfio/cdx/main.c
new file mode 100644
index 000000000000..c376a69d2db2
--- /dev/null
+++ b/drivers/vfio/cdx/main.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
+ */
+
+#include <linux/vfio.h>
+#include <linux/cdx/cdx_bus.h>
+
+#include "private.h"
+
+static int vfio_cdx_open_device(struct vfio_device *core_vdev)
+{
+ struct vfio_cdx_device *vdev =
+ container_of(core_vdev, struct vfio_cdx_device, vdev);
+ struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
+ int count = cdx_dev->res_count;
+ int i;
+
+ vdev->regions = kcalloc(count, sizeof(struct vfio_cdx_region),
+ GFP_KERNEL_ACCOUNT);
+ if (!vdev->regions)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++) {
+ struct resource *res = &cdx_dev->res[i];
+
+ vdev->regions[i].addr = res->start;
+ vdev->regions[i].size = resource_size(res);
+ vdev->regions[i].type = res->flags;
+ /*
+ * Only regions addressed with PAGE granularity may be
+ * MMAP'ed securely.
+ */
+ if (!(vdev->regions[i].addr & ~PAGE_MASK) &&
+ !(vdev->regions[i].size & ~PAGE_MASK))
+ vdev->regions[i].flags |=
+ VFIO_REGION_INFO_FLAG_MMAP;
+ vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ;
+ if (!(cdx_dev->res[i].flags & IORESOURCE_READONLY))
+ vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_WRITE;
+ }
+
+ return 0;
+}
+
+static void vfio_cdx_close_device(struct vfio_device *core_vdev)
+{
+ struct vfio_cdx_device *vdev =
+ container_of(core_vdev, struct vfio_cdx_device, vdev);
+
+ kfree(vdev->regions);
+ cdx_dev_reset(core_vdev->dev);
+}
+
+static int vfio_cdx_ioctl_get_info(struct vfio_cdx_device *vdev,
+ struct vfio_device_info __user *arg)
+{
+ unsigned long minsz = offsetofend(struct vfio_device_info, num_irqs);
+ struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
+ struct vfio_device_info info;
+
+ if (copy_from_user(&info, arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ info.flags = VFIO_DEVICE_FLAGS_CDX;
+ info.flags |= VFIO_DEVICE_FLAGS_RESET;
+
+ info.num_regions = cdx_dev->res_count;
+ info.num_irqs = 0;
+
+ return copy_to_user(arg, &info, minsz) ? -EFAULT : 0;
+}
+
+static int vfio_cdx_ioctl_get_region_info(struct vfio_cdx_device *vdev,
+ struct vfio_region_info __user *arg)
+{
+ unsigned long minsz = offsetofend(struct vfio_region_info, offset);
+ struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
+ struct vfio_region_info info;
+
+ if (copy_from_user(&info, arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ if (info.index >= cdx_dev->res_count)
+ return -EINVAL;
+
+ /* map offset to the physical address */
+ info.offset = vfio_cdx_index_to_offset(info.index);
+ info.size = vdev->regions[info.index].size;
+ info.flags = vdev->regions[info.index].flags;
+
+ return copy_to_user(arg, &info, minsz) ? -EFAULT : 0;
+}
+
+static long vfio_cdx_ioctl(struct vfio_device *core_vdev,
+ unsigned int cmd, unsigned long arg)
+{
+ struct vfio_cdx_device *vdev =
+ container_of(core_vdev, struct vfio_cdx_device, vdev);
+ void __user *uarg = (void __user *)arg;
+
+ switch (cmd) {
+ case VFIO_DEVICE_GET_INFO:
+ return vfio_cdx_ioctl_get_info(vdev, uarg);
+ case VFIO_DEVICE_GET_REGION_INFO:
+ return vfio_cdx_ioctl_get_region_info(vdev, uarg);
+ case VFIO_DEVICE_RESET:
+ return cdx_dev_reset(core_vdev->dev);
+ default:
+ return -ENOTTY;
+ }
+}
+
+static int vfio_cdx_mmap_mmio(struct vfio_cdx_region region,
+ struct vm_area_struct *vma)
+{
+ u64 size = vma->vm_end - vma->vm_start;
+ u64 pgoff, base;
+
+ pgoff = vma->vm_pgoff &
+ ((1U << (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+ base = pgoff << PAGE_SHIFT;
+
+ if (base + size > region.size)
+ return -EINVAL;
+
+ vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
+ vma->vm_page_prot = pgprot_device(vma->vm_page_prot);
+
+ return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ size, vma->vm_page_prot);
+}
+
+static int vfio_cdx_mmap(struct vfio_device *core_vdev,
+ struct vm_area_struct *vma)
+{
+ struct vfio_cdx_device *vdev =
+ container_of(core_vdev, struct vfio_cdx_device, vdev);
+ struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
+ unsigned int index;
+
+ index = vma->vm_pgoff >> (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT);
+
+ if (index >= cdx_dev->res_count)
+ return -EINVAL;
+
+ if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP))
+ return -EINVAL;
+
+ if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ) &&
+ (vma->vm_flags & VM_READ))
+ return -EPERM;
+
+ if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE) &&
+ (vma->vm_flags & VM_WRITE))
+ return -EPERM;
+
+ return vfio_cdx_mmap_mmio(vdev->regions[index], vma);
+}
+
+static const struct vfio_device_ops vfio_cdx_ops = {
+ .name = "vfio-cdx",
+ .open_device = vfio_cdx_open_device,
+ .close_device = vfio_cdx_close_device,
+ .ioctl = vfio_cdx_ioctl,
+ .mmap = vfio_cdx_mmap,
+ .bind_iommufd = vfio_iommufd_physical_bind,
+ .unbind_iommufd = vfio_iommufd_physical_unbind,
+ .attach_ioas = vfio_iommufd_physical_attach_ioas,
+};
+
+static int vfio_cdx_probe(struct cdx_device *cdx_dev)
+{
+ struct vfio_cdx_device *vdev;
+ struct device *dev = &cdx_dev->dev;
+ int ret;
+
+ vdev = vfio_alloc_device(vfio_cdx_device, vdev, dev,
+ &vfio_cdx_ops);
+ if (IS_ERR(vdev))
+ return PTR_ERR(vdev);
+
+ ret = vfio_register_group_dev(&vdev->vdev);
+ if (ret)
+ goto out_uninit;
+
+ dev_set_drvdata(dev, vdev);
+ return 0;
+
+out_uninit:
+ vfio_put_device(&vdev->vdev);
+ return ret;
+}
+
+static int vfio_cdx_remove(struct cdx_device *cdx_dev)
+{
+ struct device *dev = &cdx_dev->dev;
+ struct vfio_cdx_device *vdev = dev_get_drvdata(dev);
+
+ vfio_unregister_group_dev(&vdev->vdev);
+ vfio_put_device(&vdev->vdev);
+
+ return 0;
+}
+
+static const struct cdx_device_id vfio_cdx_table[] = {
+ { CDX_DEVICE_DRIVER_OVERRIDE(CDX_ANY_ID, CDX_ANY_ID,
+ CDX_ID_F_VFIO_DRIVER_OVERRIDE) }, /* match all by default */
+ {}
+};
+
+MODULE_DEVICE_TABLE(cdx, vfio_cdx_table);
+
+static struct cdx_driver vfio_cdx_driver = {
+ .probe = vfio_cdx_probe,
+ .remove = vfio_cdx_remove,
+ .match_id_table = vfio_cdx_table,
+ .driver = {
+ .name = "vfio-cdx",
+ .owner = THIS_MODULE,
+ },
+ .driver_managed_dma = true,
+};
+
+module_driver(vfio_cdx_driver, cdx_driver_register, cdx_driver_unregister);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("VFIO for CDX devices - User Level meta-driver");
diff --git a/drivers/vfio/cdx/private.h b/drivers/vfio/cdx/private.h
new file mode 100644
index 000000000000..8bdc117ea88e
--- /dev/null
+++ b/drivers/vfio/cdx/private.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
+ */
+
+#ifndef VFIO_CDX_PRIVATE_H
+#define VFIO_CDX_PRIVATE_H
+
+#define VFIO_CDX_OFFSET_SHIFT 40
+
+static inline u64 vfio_cdx_index_to_offset(u32 index)
+{
+ return ((u64)(index) << VFIO_CDX_OFFSET_SHIFT);
+}
+
+struct vfio_cdx_region {
+ u32 flags;
+ u32 type;
+ u64 addr;
+ resource_size_t size;
+};
+
+struct vfio_cdx_device {
+ struct vfio_device vdev;
+ struct vfio_cdx_region *regions;
+};
+
+#endif /* VFIO_CDX_PRIVATE_H */
diff --git a/drivers/vfio/fsl-mc/Kconfig b/drivers/vfio/fsl-mc/Kconfig
index 597d338c5c8a..7d1d690348f0 100644
--- a/drivers/vfio/fsl-mc/Kconfig
+++ b/drivers/vfio/fsl-mc/Kconfig
@@ -1,6 +1,8 @@
+menu "VFIO support for FSL_MC bus devices"
+ depends on FSL_MC_BUS
+
config VFIO_FSL_MC
tristate "VFIO support for QorIQ DPAA2 fsl-mc bus devices"
- depends on FSL_MC_BUS
select EVENTFD
help
Driver to enable support for the VFIO QorIQ DPAA2 fsl-mc
@@ -8,3 +10,5 @@ config VFIO_FSL_MC
fsl-mc bus devices using the VFIO framework.
If you don't know what to do here, say N.
+
+endmenu
diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc.c b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
index c89a047a4cd8..f2140e94d41e 100644
--- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c
+++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
@@ -570,7 +570,7 @@ static void vfio_fsl_mc_release_dev(struct vfio_device *core_vdev)
mutex_destroy(&vdev->igate);
}
-static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev)
+static void vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev)
{
struct device *dev = &mc_dev->dev;
struct vfio_fsl_mc_device *vdev = dev_get_drvdata(dev);
@@ -578,7 +578,6 @@ static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev)
vfio_unregister_group_dev(&vdev->vdev);
dprc_remove_devices(mc_dev, NULL, 0);
vfio_put_device(&vdev->vdev);
- return 0;
}
static const struct vfio_device_ops vfio_fsl_mc_ops = {
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 58f91b3bd670..ed4737de4528 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -72,12 +72,6 @@ int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
parent->nr_types = nr_types;
atomic_set(&parent->available_instances, mdev_driver->max_instances);
- if (!mdev_bus_compat_class) {
- mdev_bus_compat_class = class_compat_register("mdev_bus");
- if (!mdev_bus_compat_class)
- return -ENOMEM;
- }
-
ret = parent_create_sysfs_files(parent);
if (ret)
return ret;
@@ -251,13 +245,24 @@ int mdev_device_remove(struct mdev_device *mdev)
static int __init mdev_init(void)
{
- return bus_register(&mdev_bus_type);
+ int ret;
+
+ ret = bus_register(&mdev_bus_type);
+ if (ret)
+ return ret;
+
+ mdev_bus_compat_class = class_compat_register("mdev_bus");
+ if (!mdev_bus_compat_class) {
+ bus_unregister(&mdev_bus_type);
+ return -ENOMEM;
+ }
+
+ return 0;
}
static void __exit mdev_exit(void)
{
- if (mdev_bus_compat_class)
- class_compat_unregister(mdev_bus_compat_class);
+ class_compat_unregister(mdev_bus_compat_class);
bus_unregister(&mdev_bus_type);
}
diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig
index f9d0c908e738..86bb7835cf3c 100644
--- a/drivers/vfio/pci/Kconfig
+++ b/drivers/vfio/pci/Kconfig
@@ -1,5 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
-if PCI && MMU
+menu "VFIO support for PCI devices"
+ depends on PCI && MMU
+
config VFIO_PCI_CORE
tristate
select VFIO_VIRQFD
@@ -7,9 +9,11 @@ config VFIO_PCI_CORE
config VFIO_PCI_MMAP
def_bool y if !S390
+ depends on VFIO_PCI_CORE
config VFIO_PCI_INTX
def_bool y if !S390
+ depends on VFIO_PCI_CORE
config VFIO_PCI
tristate "Generic VFIO support for any PCI device"
@@ -59,4 +63,4 @@ source "drivers/vfio/pci/mlx5/Kconfig"
source "drivers/vfio/pci/hisilicon/Kconfig"
-endif
+endmenu
diff --git a/drivers/vfio/pci/hisilicon/Kconfig b/drivers/vfio/pci/hisilicon/Kconfig
index 5daa0f45d2f9..cbf1c32f6ebf 100644
--- a/drivers/vfio/pci/hisilicon/Kconfig
+++ b/drivers/vfio/pci/hisilicon/Kconfig
@@ -1,13 +1,13 @@
# SPDX-License-Identifier: GPL-2.0-only
config HISI_ACC_VFIO_PCI
- tristate "VFIO PCI support for HiSilicon ACC devices"
+ tristate "VFIO support for HiSilicon ACC PCI devices"
depends on ARM64 || (COMPILE_TEST && 64BIT)
- depends on VFIO_PCI_CORE
depends on PCI_MSI
depends on CRYPTO_DEV_HISI_QM
depends on CRYPTO_DEV_HISI_HPRE
depends on CRYPTO_DEV_HISI_SEC2
depends on CRYPTO_DEV_HISI_ZIP
+ select VFIO_PCI_CORE
help
This provides generic PCI support for HiSilicon ACC devices
using the VFIO framework.
diff --git a/drivers/vfio/pci/mlx5/Kconfig b/drivers/vfio/pci/mlx5/Kconfig
index 29ba9c504a75..7088edc4fb28 100644
--- a/drivers/vfio/pci/mlx5/Kconfig
+++ b/drivers/vfio/pci/mlx5/Kconfig
@@ -2,7 +2,7 @@
config MLX5_VFIO_PCI
tristate "VFIO support for MLX5 PCI devices"
depends on MLX5_CORE
- depends on VFIO_PCI_CORE
+ select VFIO_PCI_CORE
help
This provides migration support for MLX5 devices using the VFIO
framework.
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index 948cdd464f4e..7e2e62ab0869 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -1566,8 +1566,8 @@ static int vfio_cap_init(struct vfio_pci_core_device *vdev)
}
if (!len) {
- pci_info(pdev, "%s: hiding cap %#x@%#x\n", __func__,
- cap, pos);
+ pci_dbg(pdev, "%s: hiding cap %#x@%#x\n", __func__,
+ cap, pos);
*prev = next;
pos = next;
continue;
@@ -1643,8 +1643,8 @@ static int vfio_ecap_init(struct vfio_pci_core_device *vdev)
}
if (!len) {
- pci_info(pdev, "%s: hiding ecap %#x@%#x\n",
- __func__, ecap, epos);
+ pci_dbg(pdev, "%s: hiding ecap %#x@%#x\n",
+ __func__, ecap, epos);
/* If not the first in the chain, we can skip over it */
if (prev) {
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index a5ab416cf476..20d7b69ea6ff 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -530,8 +530,11 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev)
vdev->msix_bar = table & PCI_MSIX_TABLE_BIR;
vdev->msix_offset = table & PCI_MSIX_TABLE_OFFSET;
vdev->msix_size = ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) * 16;
- } else
+ vdev->has_dyn_msix = pci_msix_can_alloc_dyn(pdev);
+ } else {
vdev->msix_bar = 0xFF;
+ vdev->has_dyn_msix = false;
+ }
if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev))
vdev->has_vga = true;
@@ -882,6 +885,37 @@ int vfio_pci_core_register_dev_region(struct vfio_pci_core_device *vdev,
}
EXPORT_SYMBOL_GPL(vfio_pci_core_register_dev_region);
+static int vfio_pci_info_atomic_cap(struct vfio_pci_core_device *vdev,
+ struct vfio_info_cap *caps)
+{
+ struct vfio_device_info_cap_pci_atomic_comp cap = {
+ .header.id = VFIO_DEVICE_INFO_CAP_PCI_ATOMIC_COMP,
+ .header.version = 1
+ };
+ struct pci_dev *pdev = pci_physfn(vdev->pdev);
+ u32 devcap2;
+
+ pcie_capability_read_dword(pdev, PCI_EXP_DEVCAP2, &devcap2);
+
+ if ((devcap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP32) &&
+ !pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP32))
+ cap.flags |= VFIO_PCI_ATOMIC_COMP32;
+
+ if ((devcap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP64) &&
+ !pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP64))
+ cap.flags |= VFIO_PCI_ATOMIC_COMP64;
+
+ if ((devcap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP128) &&
+ !pci_enable_atomic_ops_to_root(pdev,
+ PCI_EXP_DEVCAP2_ATOMIC_COMP128))
+ cap.flags |= VFIO_PCI_ATOMIC_COMP128;
+
+ if (!cap.flags)
+ return -ENODEV;
+
+ return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
+}
+
static int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev,
struct vfio_device_info __user *arg)
{
@@ -920,6 +954,13 @@ static int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev,
return ret;
}
+ ret = vfio_pci_info_atomic_cap(vdev, &caps);
+ if (ret && ret != -ENODEV) {
+ pci_warn(vdev->pdev,
+ "Failed to setup AtomicOps info capability\n");
+ return ret;
+ }
+
if (caps.size) {
info.flags |= VFIO_DEVICE_FLAGS_CAPS;
if (info.argsz < sizeof(info) + caps.size) {
@@ -1111,7 +1152,7 @@ static int vfio_pci_ioctl_get_irq_info(struct vfio_pci_core_device *vdev,
if (info.index == VFIO_PCI_INTX_IRQ_INDEX)
info.flags |=
(VFIO_IRQ_INFO_MASKABLE | VFIO_IRQ_INFO_AUTOMASKED);
- else
+ else if (info.index != VFIO_PCI_MSIX_IRQ_INDEX || !vdev->has_dyn_msix)
info.flags |= VFIO_IRQ_INFO_NORESIZE;
return copy_to_user(arg, &info, minsz) ? -EFAULT : 0;
@@ -2102,6 +2143,7 @@ int vfio_pci_core_init_dev(struct vfio_device *core_vdev)
INIT_LIST_HEAD(&vdev->vma_list);
INIT_LIST_HEAD(&vdev->sriov_pfs_item);
init_rwsem(&vdev->memory_lock);
+ xa_init(&vdev->ctx);
return 0;
}
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index bffb0741518b..cbb4bcbfbf83 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -48,6 +48,39 @@ static bool is_irq_none(struct vfio_pci_core_device *vdev)
vdev->irq_type == VFIO_PCI_MSIX_IRQ_INDEX);
}
+static
+struct vfio_pci_irq_ctx *vfio_irq_ctx_get(struct vfio_pci_core_device *vdev,
+ unsigned long index)
+{
+ return xa_load(&vdev->ctx, index);
+}
+
+static void vfio_irq_ctx_free(struct vfio_pci_core_device *vdev,
+ struct vfio_pci_irq_ctx *ctx, unsigned long index)
+{
+ xa_erase(&vdev->ctx, index);
+ kfree(ctx);
+}
+
+static struct vfio_pci_irq_ctx *
+vfio_irq_ctx_alloc(struct vfio_pci_core_device *vdev, unsigned long index)
+{
+ struct vfio_pci_irq_ctx *ctx;
+ int ret;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT);
+ if (!ctx)
+ return NULL;
+
+ ret = xa_insert(&vdev->ctx, index, ctx, GFP_KERNEL_ACCOUNT);
+ if (ret) {
+ kfree(ctx);
+ return NULL;
+ }
+
+ return ctx;
+}
+
/*
* INTx
*/
@@ -55,14 +88,21 @@ static void vfio_send_intx_eventfd(void *opaque, void *unused)
{
struct vfio_pci_core_device *vdev = opaque;
- if (likely(is_intx(vdev) && !vdev->virq_disabled))
- eventfd_signal(vdev->ctx[0].trigger, 1);
+ if (likely(is_intx(vdev) && !vdev->virq_disabled)) {
+ struct vfio_pci_irq_ctx *ctx;
+
+ ctx = vfio_irq_ctx_get(vdev, 0);
+ if (WARN_ON_ONCE(!ctx))
+ return;
+ eventfd_signal(ctx->trigger, 1);
+ }
}
/* Returns true if the INTx vfio_pci_irq_ctx.masked value is changed. */
bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
+ struct vfio_pci_irq_ctx *ctx;
unsigned long flags;
bool masked_changed = false;
@@ -77,7 +117,14 @@ bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)
if (unlikely(!is_intx(vdev))) {
if (vdev->pci_2_3)
pci_intx(pdev, 0);
- } else if (!vdev->ctx[0].masked) {
+ goto out_unlock;
+ }
+
+ ctx = vfio_irq_ctx_get(vdev, 0);
+ if (WARN_ON_ONCE(!ctx))
+ goto out_unlock;
+
+ if (!ctx->masked) {
/*
* Can't use check_and_mask here because we always want to
* mask, not just when something is pending.
@@ -87,10 +134,11 @@ bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)
else
disable_irq_nosync(pdev->irq);
- vdev->ctx[0].masked = true;
+ ctx->masked = true;
masked_changed = true;
}
+out_unlock:
spin_unlock_irqrestore(&vdev->irqlock, flags);
return masked_changed;
}
@@ -105,6 +153,7 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *unused)
{
struct vfio_pci_core_device *vdev = opaque;
struct pci_dev *pdev = vdev->pdev;
+ struct vfio_pci_irq_ctx *ctx;
unsigned long flags;
int ret = 0;
@@ -117,7 +166,14 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *unused)
if (unlikely(!is_intx(vdev))) {
if (vdev->pci_2_3)
pci_intx(pdev, 1);
- } else if (vdev->ctx[0].masked && !vdev->virq_disabled) {
+ goto out_unlock;
+ }
+
+ ctx = vfio_irq_ctx_get(vdev, 0);
+ if (WARN_ON_ONCE(!ctx))
+ goto out_unlock;
+
+ if (ctx->masked && !vdev->virq_disabled) {
/*
* A pending interrupt here would immediately trigger,
* but we can avoid that overhead by just re-sending
@@ -129,9 +185,10 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *unused)
} else
enable_irq(pdev->irq);
- vdev->ctx[0].masked = (ret > 0);
+ ctx->masked = (ret > 0);
}
+out_unlock:
spin_unlock_irqrestore(&vdev->irqlock, flags);
return ret;
@@ -146,18 +203,23 @@ void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)
static irqreturn_t vfio_intx_handler(int irq, void *dev_id)
{
struct vfio_pci_core_device *vdev = dev_id;
+ struct vfio_pci_irq_ctx *ctx;
unsigned long flags;
int ret = IRQ_NONE;
+ ctx = vfio_irq_ctx_get(vdev, 0);
+ if (WARN_ON_ONCE(!ctx))
+ return ret;
+
spin_lock_irqsave(&vdev->irqlock, flags);
if (!vdev->pci_2_3) {
disable_irq_nosync(vdev->pdev->irq);
- vdev->ctx[0].masked = true;
+ ctx->masked = true;
ret = IRQ_HANDLED;
- } else if (!vdev->ctx[0].masked && /* may be shared */
+ } else if (!ctx->masked && /* may be shared */
pci_check_and_mask_intx(vdev->pdev)) {
- vdev->ctx[0].masked = true;
+ ctx->masked = true;
ret = IRQ_HANDLED;
}
@@ -171,27 +233,27 @@ static irqreturn_t vfio_intx_handler(int irq, void *dev_id)
static int vfio_intx_enable(struct vfio_pci_core_device *vdev)
{
+ struct vfio_pci_irq_ctx *ctx;
+
if (!is_irq_none(vdev))
return -EINVAL;
if (!vdev->pdev->irq)
return -ENODEV;
- vdev->ctx = kzalloc(sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL_ACCOUNT);
- if (!vdev->ctx)
+ ctx = vfio_irq_ctx_alloc(vdev, 0);
+ if (!ctx)
return -ENOMEM;
- vdev->num_ctx = 1;
-
/*
* If the virtual interrupt is masked, restore it. Devices
* supporting DisINTx can be masked at the hardware level
* here, non-PCI-2.3 devices will have to wait until the
* interrupt is enabled.
*/
- vdev->ctx[0].masked = vdev->virq_disabled;
+ ctx->masked = vdev->virq_disabled;
if (vdev->pci_2_3)
- pci_intx(vdev->pdev, !vdev->ctx[0].masked);
+ pci_intx(vdev->pdev, !ctx->masked);
vdev->irq_type = VFIO_PCI_INTX_IRQ_INDEX;
@@ -202,41 +264,46 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev, int fd)
{
struct pci_dev *pdev = vdev->pdev;
unsigned long irqflags = IRQF_SHARED;
+ struct vfio_pci_irq_ctx *ctx;
struct eventfd_ctx *trigger;
unsigned long flags;
int ret;
- if (vdev->ctx[0].trigger) {
+ ctx = vfio_irq_ctx_get(vdev, 0);
+ if (WARN_ON_ONCE(!ctx))
+ return -EINVAL;
+
+ if (ctx->trigger) {
free_irq(pdev->irq, vdev);
- kfree(vdev->ctx[0].name);
- eventfd_ctx_put(vdev->ctx[0].trigger);
- vdev->ctx[0].trigger = NULL;
+ kfree(ctx->name);
+ eventfd_ctx_put(ctx->trigger);
+ ctx->trigger = NULL;
}
if (fd < 0) /* Disable only */
return 0;
- vdev->ctx[0].name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)",
- pci_name(pdev));
- if (!vdev->ctx[0].name)
+ ctx->name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)",
+ pci_name(pdev));
+ if (!ctx->name)
return -ENOMEM;
trigger = eventfd_ctx_fdget(fd);
if (IS_ERR(trigger)) {
- kfree(vdev->ctx[0].name);
+ kfree(ctx->name);
return PTR_ERR(trigger);
}
- vdev->ctx[0].trigger = trigger;
+ ctx->trigger = trigger;
if (!vdev->pci_2_3)
irqflags = 0;
ret = request_irq(pdev->irq, vfio_intx_handler,
- irqflags, vdev->ctx[0].name, vdev);
+ irqflags, ctx->name, vdev);
if (ret) {
- vdev->ctx[0].trigger = NULL;
- kfree(vdev->ctx[0].name);
+ ctx->trigger = NULL;
+ kfree(ctx->name);
eventfd_ctx_put(trigger);
return ret;
}
@@ -246,7 +313,7 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev, int fd)
* disable_irq won't.
*/
spin_lock_irqsave(&vdev->irqlock, flags);
- if (!vdev->pci_2_3 && vdev->ctx[0].masked)
+ if (!vdev->pci_2_3 && ctx->masked)
disable_irq_nosync(pdev->irq);
spin_unlock_irqrestore(&vdev->irqlock, flags);
@@ -255,12 +322,17 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev, int fd)
static void vfio_intx_disable(struct vfio_pci_core_device *vdev)
{
- vfio_virqfd_disable(&vdev->ctx[0].unmask);
- vfio_virqfd_disable(&vdev->ctx[0].mask);
+ struct vfio_pci_irq_ctx *ctx;
+
+ ctx = vfio_irq_ctx_get(vdev, 0);
+ WARN_ON_ONCE(!ctx);
+ if (ctx) {
+ vfio_virqfd_disable(&ctx->unmask);
+ vfio_virqfd_disable(&ctx->mask);
+ }
vfio_intx_set_signal(vdev, -1);
vdev->irq_type = VFIO_PCI_NUM_IRQS;
- vdev->num_ctx = 0;
- kfree(vdev->ctx);
+ vfio_irq_ctx_free(vdev, ctx, 0);
}
/*
@@ -284,11 +356,6 @@ static int vfio_msi_enable(struct vfio_pci_core_device *vdev, int nvec, bool msi
if (!is_irq_none(vdev))
return -EINVAL;
- vdev->ctx = kcalloc(nvec, sizeof(struct vfio_pci_irq_ctx),
- GFP_KERNEL_ACCOUNT);
- if (!vdev->ctx)
- return -ENOMEM;
-
/* return the number of supported vectors if we can't get all: */
cmd = vfio_pci_memory_lock_and_enable(vdev);
ret = pci_alloc_irq_vectors(pdev, 1, nvec, flag);
@@ -296,12 +363,10 @@ static int vfio_msi_enable(struct vfio_pci_core_device *vdev, int nvec, bool msi
if (ret > 0)
pci_free_irq_vectors(pdev);
vfio_pci_memory_unlock_and_restore(vdev, cmd);
- kfree(vdev->ctx);
return ret;
}
vfio_pci_memory_unlock_and_restore(vdev, cmd);
- vdev->num_ctx = nvec;
vdev->irq_type = msix ? VFIO_PCI_MSIX_IRQ_INDEX :
VFIO_PCI_MSI_IRQ_INDEX;
@@ -316,53 +381,91 @@ static int vfio_msi_enable(struct vfio_pci_core_device *vdev, int nvec, bool msi
return 0;
}
-static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev,
- int vector, int fd, bool msix)
+/*
+ * vfio_msi_alloc_irq() returns the Linux IRQ number of an MSI or MSI-X device
+ * interrupt vector. If a Linux IRQ number is not available then a new
+ * interrupt is allocated if dynamic MSI-X is supported.
+ *
+ * Where is vfio_msi_free_irq()? Allocated interrupts are maintained,
+ * essentially forming a cache that subsequent allocations can draw from.
+ * Interrupts are freed using pci_free_irq_vectors() when MSI/MSI-X is
+ * disabled.
+ */
+static int vfio_msi_alloc_irq(struct vfio_pci_core_device *vdev,
+ unsigned int vector, bool msix)
{
struct pci_dev *pdev = vdev->pdev;
- struct eventfd_ctx *trigger;
- int irq, ret;
+ struct msi_map map;
+ int irq;
u16 cmd;
- if (vector < 0 || vector >= vdev->num_ctx)
+ irq = pci_irq_vector(pdev, vector);
+ if (WARN_ON_ONCE(irq == 0))
return -EINVAL;
+ if (irq > 0 || !msix || !vdev->has_dyn_msix)
+ return irq;
- irq = pci_irq_vector(pdev, vector);
+ cmd = vfio_pci_memory_lock_and_enable(vdev);
+ map = pci_msix_alloc_irq_at(pdev, vector, NULL);
+ vfio_pci_memory_unlock_and_restore(vdev, cmd);
- if (vdev->ctx[vector].trigger) {
- irq_bypass_unregister_producer(&vdev->ctx[vector].producer);
+ return map.index < 0 ? map.index : map.virq;
+}
+static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev,
+ unsigned int vector, int fd, bool msix)
+{
+ struct pci_dev *pdev = vdev->pdev;
+ struct vfio_pci_irq_ctx *ctx;
+ struct eventfd_ctx *trigger;
+ int irq = -EINVAL, ret;
+ u16 cmd;
+
+ ctx = vfio_irq_ctx_get(vdev, vector);
+
+ if (ctx) {
+ irq_bypass_unregister_producer(&ctx->producer);
+ irq = pci_irq_vector(pdev, vector);
cmd = vfio_pci_memory_lock_and_enable(vdev);
- free_irq(irq, vdev->ctx[vector].trigger);
+ free_irq(irq, ctx->trigger);
vfio_pci_memory_unlock_and_restore(vdev, cmd);
-
- kfree(vdev->ctx[vector].name);
- eventfd_ctx_put(vdev->ctx[vector].trigger);
- vdev->ctx[vector].trigger = NULL;
+ /* Interrupt stays allocated, will be freed at MSI-X disable. */
+ kfree(ctx->name);
+ eventfd_ctx_put(ctx->trigger);
+ vfio_irq_ctx_free(vdev, ctx, vector);
}
if (fd < 0)
return 0;
- vdev->ctx[vector].name = kasprintf(GFP_KERNEL_ACCOUNT,
- "vfio-msi%s[%d](%s)",
- msix ? "x" : "", vector,
- pci_name(pdev));
- if (!vdev->ctx[vector].name)
+ if (irq == -EINVAL) {
+ /* Interrupt stays allocated, will be freed at MSI-X disable. */
+ irq = vfio_msi_alloc_irq(vdev, vector, msix);
+ if (irq < 0)
+ return irq;
+ }
+
+ ctx = vfio_irq_ctx_alloc(vdev, vector);
+ if (!ctx)
return -ENOMEM;
+ ctx->name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-msi%s[%d](%s)",
+ msix ? "x" : "", vector, pci_name(pdev));
+ if (!ctx->name) {
+ ret = -ENOMEM;
+ goto out_free_ctx;
+ }
+
trigger = eventfd_ctx_fdget(fd);
if (IS_ERR(trigger)) {
- kfree(vdev->ctx[vector].name);
- return PTR_ERR(trigger);
+ ret = PTR_ERR(trigger);
+ goto out_free_name;
}
/*
- * The MSIx vector table resides in device memory which may be cleared
- * via backdoor resets. We don't allow direct access to the vector
- * table so even if a userspace driver attempts to save/restore around
- * such a reset it would be unsuccessful. To avoid this, restore the
- * cached value of the message prior to enabling.
+ * If the vector was previously allocated, refresh the on-device
+ * message data before enabling in case it had been cleared or
+ * corrupted (e.g. due to backdoor resets) since writing.
*/
cmd = vfio_pci_memory_lock_and_enable(vdev);
if (msix) {
@@ -372,37 +475,39 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev,
pci_write_msi_msg(irq, &msg);
}
- ret = request_irq(irq, vfio_msihandler, 0,
- vdev->ctx[vector].name, trigger);
+ ret = request_irq(irq, vfio_msihandler, 0, ctx->name, trigger);
vfio_pci_memory_unlock_and_restore(vdev, cmd);
- if (ret) {
- kfree(vdev->ctx[vector].name);
- eventfd_ctx_put(trigger);
- return ret;
- }
+ if (ret)
+ goto out_put_eventfd_ctx;
- vdev->ctx[vector].producer.token = trigger;
- vdev->ctx[vector].producer.irq = irq;
- ret = irq_bypass_register_producer(&vdev->ctx[vector].producer);
+ ctx->producer.token = trigger;
+ ctx->producer.irq = irq;
+ ret = irq_bypass_register_producer(&ctx->producer);
if (unlikely(ret)) {
dev_info(&pdev->dev,
"irq bypass producer (token %p) registration fails: %d\n",
- vdev->ctx[vector].producer.token, ret);
+ ctx->producer.token, ret);
- vdev->ctx[vector].producer.token = NULL;
+ ctx->producer.token = NULL;
}
- vdev->ctx[vector].trigger = trigger;
+ ctx->trigger = trigger;
return 0;
+
+out_put_eventfd_ctx:
+ eventfd_ctx_put(trigger);
+out_free_name:
+ kfree(ctx->name);
+out_free_ctx:
+ vfio_irq_ctx_free(vdev, ctx, vector);
+ return ret;
}
static int vfio_msi_set_block(struct vfio_pci_core_device *vdev, unsigned start,
unsigned count, int32_t *fds, bool msix)
{
- int i, j, ret = 0;
-
- if (start >= vdev->num_ctx || start + count > vdev->num_ctx)
- return -EINVAL;
+ unsigned int i, j;
+ int ret = 0;
for (i = 0, j = start; i < count && !ret; i++, j++) {
int fd = fds ? fds[i] : -1;
@@ -410,8 +515,8 @@ static int vfio_msi_set_block(struct vfio_pci_core_device *vdev, unsigned start,
}
if (ret) {
- for (--j; j >= (int)start; j--)
- vfio_msi_set_vector_signal(vdev, j, -1, msix);
+ for (i = start; i < j; i++)
+ vfio_msi_set_vector_signal(vdev, i, -1, msix);
}
return ret;
@@ -420,16 +525,16 @@ static int vfio_msi_set_block(struct vfio_pci_core_device *vdev, unsigned start,
static void vfio_msi_disable(struct vfio_pci_core_device *vdev, bool msix)
{
struct pci_dev *pdev = vdev->pdev;
- int i;
+ struct vfio_pci_irq_ctx *ctx;
+ unsigned long i;
u16 cmd;
- for (i = 0; i < vdev->num_ctx; i++) {
- vfio_virqfd_disable(&vdev->ctx[i].unmask);
- vfio_virqfd_disable(&vdev->ctx[i].mask);
+ xa_for_each(&vdev->ctx, i, ctx) {
+ vfio_virqfd_disable(&ctx->unmask);
+ vfio_virqfd_disable(&ctx->mask);
+ vfio_msi_set_vector_signal(vdev, i, -1, msix);
}
- vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
-
cmd = vfio_pci_memory_lock_and_enable(vdev);
pci_free_irq_vectors(pdev);
vfio_pci_memory_unlock_and_restore(vdev, cmd);
@@ -442,8 +547,6 @@ static void vfio_msi_disable(struct vfio_pci_core_device *vdev, bool msix)
pci_intx(pdev, 0);
vdev->irq_type = VFIO_PCI_NUM_IRQS;
- vdev->num_ctx = 0;
- kfree(vdev->ctx);
}
/*
@@ -463,14 +566,18 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_core_device *vdev,
if (unmask)
vfio_pci_intx_unmask(vdev);
} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+ struct vfio_pci_irq_ctx *ctx = vfio_irq_ctx_get(vdev, 0);
int32_t fd = *(int32_t *)data;
+
+ if (WARN_ON_ONCE(!ctx))
+ return -EINVAL;
if (fd >= 0)
return vfio_virqfd_enable((void *) vdev,
vfio_pci_intx_unmask_handler,
vfio_send_intx_eventfd, NULL,
- &vdev->ctx[0].unmask, fd);
+ &ctx->unmask, fd);
- vfio_virqfd_disable(&vdev->ctx[0].unmask);
+ vfio_virqfd_disable(&ctx->unmask);
}
return 0;
@@ -543,7 +650,8 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_core_device *vdev,
unsigned index, unsigned start,
unsigned count, uint32_t flags, void *data)
{
- int i;
+ struct vfio_pci_irq_ctx *ctx;
+ unsigned int i;
bool msix = (index == VFIO_PCI_MSIX_IRQ_INDEX) ? true : false;
if (irq_is(vdev, index) && !count && (flags & VFIO_IRQ_SET_DATA_NONE)) {
@@ -573,18 +681,19 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_core_device *vdev,
return ret;
}
- if (!irq_is(vdev, index) || start + count > vdev->num_ctx)
+ if (!irq_is(vdev, index))
return -EINVAL;
for (i = start; i < start + count; i++) {
- if (!vdev->ctx[i].trigger)
+ ctx = vfio_irq_ctx_get(vdev, i);
+ if (!ctx)
continue;
if (flags & VFIO_IRQ_SET_DATA_NONE) {
- eventfd_signal(vdev->ctx[i].trigger, 1);
+ eventfd_signal(ctx->trigger, 1);
} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
uint8_t *bools = data;
if (bools[i - start])
- eventfd_signal(vdev->ctx[i].trigger, 1);
+ eventfd_signal(ctx->trigger, 1);
}
}
return 0;
diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig
index 331a5920f5ab..88fcde51f024 100644
--- a/drivers/vfio/platform/Kconfig
+++ b/drivers/vfio/platform/Kconfig
@@ -1,8 +1,14 @@
# SPDX-License-Identifier: GPL-2.0-only
-config VFIO_PLATFORM
- tristate "VFIO support for platform devices"
+menu "VFIO support for platform devices"
depends on ARM || ARM64 || COMPILE_TEST
+
+config VFIO_PLATFORM_BASE
+ tristate
select VFIO_VIRQFD
+
+config VFIO_PLATFORM
+ tristate "Generic VFIO support for any platform device"
+ select VFIO_PLATFORM_BASE
help
Support for platform devices with VFIO. This is required to make
use of platform devices present on the system using the VFIO
@@ -10,10 +16,10 @@ config VFIO_PLATFORM
If you don't know what to do here, say N.
-if VFIO_PLATFORM
config VFIO_AMBA
tristate "VFIO support for AMBA devices"
depends on ARM_AMBA || COMPILE_TEST
+ select VFIO_PLATFORM_BASE
help
Support for ARM AMBA devices with VFIO. This is required to make
use of ARM AMBA devices present on the system using the VFIO
@@ -21,5 +27,9 @@ config VFIO_AMBA
If you don't know what to do here, say N.
+menu "VFIO platform reset drivers"
+ depends on VFIO_PLATFORM_BASE
+
source "drivers/vfio/platform/reset/Kconfig"
-endif
+endmenu
+endmenu
diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
index 3f3a24e7c4ef..ee4fb6a82ca8 100644
--- a/drivers/vfio/platform/Makefile
+++ b/drivers/vfio/platform/Makefile
@@ -1,13 +1,10 @@
# SPDX-License-Identifier: GPL-2.0
vfio-platform-base-y := vfio_platform_common.o vfio_platform_irq.o
-vfio-platform-y := vfio_platform.o
+obj-$(CONFIG_VFIO_PLATFORM_BASE) += vfio-platform-base.o
+obj-$(CONFIG_VFIO_PLATFORM_BASE) += reset/
+vfio-platform-y := vfio_platform.o
obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
-obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform-base.o
-obj-$(CONFIG_VFIO_PLATFORM) += reset/
vfio-amba-y := vfio_amba.o
-
obj-$(CONFIG_VFIO_AMBA) += vfio-amba.o
-obj-$(CONFIG_VFIO_AMBA) += vfio-platform-base.o
-obj-$(CONFIG_VFIO_AMBA) += reset/
diff --git a/drivers/vfio/platform/reset/Kconfig b/drivers/vfio/platform/reset/Kconfig
index 12f5f3d80387..dcc08dc145a5 100644
--- a/drivers/vfio/platform/reset/Kconfig
+++ b/drivers/vfio/platform/reset/Kconfig
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
+if VFIO_PLATFORM
config VFIO_PLATFORM_CALXEDAXGMAC_RESET
tristate "VFIO support for calxeda xgmac reset"
help
@@ -21,3 +22,4 @@ config VFIO_PLATFORM_BCMFLEXRM_RESET
Enables the VFIO platform driver to handle reset for Broadcom FlexRM
If you don't know what to do here, say N.
+endif
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index ae2273196b0c..f2ed7167c848 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -546,7 +546,7 @@ static void vhost_net_busy_poll(struct vhost_net *net,
endtime = busy_clock() + busyloop_timeout;
while (vhost_can_busy_poll(endtime)) {
- if (vhost_has_work(&net->dev)) {
+ if (vhost_vq_has_work(vq)) {
*busyloop_intr = true;
break;
}
@@ -1347,8 +1347,10 @@ static int vhost_net_open(struct inode *inode, struct file *f)
VHOST_NET_PKT_WEIGHT, VHOST_NET_WEIGHT, true,
NULL);
- vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev);
- vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev);
+ vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev,
+ vqs[VHOST_NET_VQ_TX]);
+ vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev,
+ vqs[VHOST_NET_VQ_RX]);
f->private_data = n;
n->page_frag.page = NULL;
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index bb10fa4bb4f6..c83f7f043470 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -167,6 +167,7 @@ MODULE_PARM_DESC(max_io_vqs, "Set the max number of IO virtqueues a vhost scsi d
struct vhost_scsi_virtqueue {
struct vhost_virtqueue vq;
+ struct vhost_scsi *vs;
/*
* Reference counting for inflight reqs, used for flush operation. At
* each time, one reference tracks new commands submitted, while we
@@ -181,6 +182,9 @@ struct vhost_scsi_virtqueue {
struct vhost_scsi_cmd *scsi_cmds;
struct sbitmap scsi_tags;
int max_cmds;
+
+ struct vhost_work completion_work;
+ struct llist_head completion_list;
};
struct vhost_scsi {
@@ -190,12 +194,8 @@ struct vhost_scsi {
struct vhost_dev dev;
struct vhost_scsi_virtqueue *vqs;
- unsigned long *compl_bitmap;
struct vhost_scsi_inflight **old_inflight;
- struct vhost_work vs_completion_work; /* cmd completion work item */
- struct llist_head vs_completion_list; /* cmd completion queue */
-
struct vhost_work vs_event_work; /* evt injection work item */
struct llist_head vs_event_list; /* evt injection queue */
@@ -353,15 +353,17 @@ static void vhost_scsi_release_cmd(struct se_cmd *se_cmd)
if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) {
struct vhost_scsi_tmf *tmf = container_of(se_cmd,
struct vhost_scsi_tmf, se_cmd);
+ struct vhost_virtqueue *vq = &tmf->svq->vq;
- vhost_work_queue(&tmf->vhost->dev, &tmf->vwork);
+ vhost_vq_work_queue(vq, &tmf->vwork);
} else {
struct vhost_scsi_cmd *cmd = container_of(se_cmd,
struct vhost_scsi_cmd, tvc_se_cmd);
- struct vhost_scsi *vs = cmd->tvc_vhost;
+ struct vhost_scsi_virtqueue *svq = container_of(cmd->tvc_vq,
+ struct vhost_scsi_virtqueue, vq);
- llist_add(&cmd->tvc_completion_list, &vs->vs_completion_list);
- vhost_work_queue(&vs->dev, &vs->vs_completion_work);
+ llist_add(&cmd->tvc_completion_list, &svq->completion_list);
+ vhost_vq_work_queue(&svq->vq, &svq->completion_work);
}
}
@@ -509,17 +511,17 @@ static void vhost_scsi_evt_work(struct vhost_work *work)
*/
static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
{
- struct vhost_scsi *vs = container_of(work, struct vhost_scsi,
- vs_completion_work);
+ struct vhost_scsi_virtqueue *svq = container_of(work,
+ struct vhost_scsi_virtqueue, completion_work);
struct virtio_scsi_cmd_resp v_rsp;
struct vhost_scsi_cmd *cmd, *t;
struct llist_node *llnode;
struct se_cmd *se_cmd;
struct iov_iter iov_iter;
- int ret, vq;
+ bool signal = false;
+ int ret;
- bitmap_zero(vs->compl_bitmap, vs->dev.nvqs);
- llnode = llist_del_all(&vs->vs_completion_list);
+ llnode = llist_del_all(&svq->completion_list);
llist_for_each_entry_safe(cmd, t, llnode, tvc_completion_list) {
se_cmd = &cmd->tvc_se_cmd;
@@ -539,21 +541,17 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
cmd->tvc_in_iovs, sizeof(v_rsp));
ret = copy_to_iter(&v_rsp, sizeof(v_rsp), &iov_iter);
if (likely(ret == sizeof(v_rsp))) {
- struct vhost_scsi_virtqueue *q;
+ signal = true;
+
vhost_add_used(cmd->tvc_vq, cmd->tvc_vq_desc, 0);
- q = container_of(cmd->tvc_vq, struct vhost_scsi_virtqueue, vq);
- vq = q - vs->vqs;
- __set_bit(vq, vs->compl_bitmap);
} else
pr_err("Faulted on virtio_scsi_cmd_resp\n");
vhost_scsi_release_cmd_res(se_cmd);
}
- vq = -1;
- while ((vq = find_next_bit(vs->compl_bitmap, vs->dev.nvqs, vq + 1))
- < vs->dev.nvqs)
- vhost_signal(&vs->dev, &vs->vqs[vq].vq);
+ if (signal)
+ vhost_signal(&svq->vs->dev, &svq->vq);
}
static struct vhost_scsi_cmd *
@@ -1135,12 +1133,27 @@ static void vhost_scsi_tmf_resp_work(struct vhost_work *work)
{
struct vhost_scsi_tmf *tmf = container_of(work, struct vhost_scsi_tmf,
vwork);
- int resp_code;
+ struct vhost_virtqueue *ctl_vq, *vq;
+ int resp_code, i;
+
+ if (tmf->scsi_resp == TMR_FUNCTION_COMPLETE) {
+ /*
+ * Flush IO vqs that don't share a worker with the ctl to make
+ * sure they have sent their responses before us.
+ */
+ ctl_vq = &tmf->vhost->vqs[VHOST_SCSI_VQ_CTL].vq;
+ for (i = VHOST_SCSI_VQ_IO; i < tmf->vhost->dev.nvqs; i++) {
+ vq = &tmf->vhost->vqs[i].vq;
+
+ if (vhost_vq_is_setup(vq) &&
+ vq->worker != ctl_vq->worker)
+ vhost_vq_flush(vq);
+ }
- if (tmf->scsi_resp == TMR_FUNCTION_COMPLETE)
resp_code = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
- else
+ } else {
resp_code = VIRTIO_SCSI_S_FUNCTION_REJECTED;
+ }
vhost_scsi_send_tmf_resp(tmf->vhost, &tmf->svq->vq, tmf->in_iovs,
tmf->vq_desc, &tmf->resp_iov, resp_code);
@@ -1335,11 +1348,9 @@ static void vhost_scsi_ctl_handle_kick(struct vhost_work *work)
}
static void
-vhost_scsi_send_evt(struct vhost_scsi *vs,
- struct vhost_scsi_tpg *tpg,
- struct se_lun *lun,
- u32 event,
- u32 reason)
+vhost_scsi_send_evt(struct vhost_scsi *vs, struct vhost_virtqueue *vq,
+ struct vhost_scsi_tpg *tpg, struct se_lun *lun,
+ u32 event, u32 reason)
{
struct vhost_scsi_evt *evt;
@@ -1361,7 +1372,7 @@ vhost_scsi_send_evt(struct vhost_scsi *vs,
}
llist_add(&evt->list, &vs->vs_event_list);
- vhost_work_queue(&vs->dev, &vs->vs_event_work);
+ vhost_vq_work_queue(vq, &vs->vs_event_work);
}
static void vhost_scsi_evt_handle_kick(struct vhost_work *work)
@@ -1375,7 +1386,8 @@ static void vhost_scsi_evt_handle_kick(struct vhost_work *work)
goto out;
if (vs->vs_events_missed)
- vhost_scsi_send_evt(vs, NULL, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
+ vhost_scsi_send_evt(vs, vq, NULL, NULL, VIRTIO_SCSI_T_NO_EVENT,
+ 0);
out:
mutex_unlock(&vq->mutex);
}
@@ -1770,6 +1782,7 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
static int vhost_scsi_open(struct inode *inode, struct file *f)
{
+ struct vhost_scsi_virtqueue *svq;
struct vhost_scsi *vs;
struct vhost_virtqueue **vqs;
int r = -ENOMEM, i, nvqs = vhost_scsi_max_io_vqs;
@@ -1788,10 +1801,6 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
}
nvqs += VHOST_SCSI_VQ_IO;
- vs->compl_bitmap = bitmap_alloc(nvqs, GFP_KERNEL);
- if (!vs->compl_bitmap)
- goto err_compl_bitmap;
-
vs->old_inflight = kmalloc_array(nvqs, sizeof(*vs->old_inflight),
GFP_KERNEL | __GFP_ZERO);
if (!vs->old_inflight)
@@ -1806,7 +1815,6 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
if (!vqs)
goto err_local_vqs;
- vhost_work_init(&vs->vs_completion_work, vhost_scsi_complete_cmd_work);
vhost_work_init(&vs->vs_event_work, vhost_scsi_evt_work);
vs->vs_events_nr = 0;
@@ -1817,8 +1825,14 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
vs->vqs[VHOST_SCSI_VQ_CTL].vq.handle_kick = vhost_scsi_ctl_handle_kick;
vs->vqs[VHOST_SCSI_VQ_EVT].vq.handle_kick = vhost_scsi_evt_handle_kick;
for (i = VHOST_SCSI_VQ_IO; i < nvqs; i++) {
- vqs[i] = &vs->vqs[i].vq;
- vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick;
+ svq = &vs->vqs[i];
+
+ vqs[i] = &svq->vq;
+ svq->vs = vs;
+ init_llist_head(&svq->completion_list);
+ vhost_work_init(&svq->completion_work,
+ vhost_scsi_complete_cmd_work);
+ svq->vq.handle_kick = vhost_scsi_handle_kick;
}
vhost_dev_init(&vs->dev, vqs, nvqs, UIO_MAXIOV,
VHOST_SCSI_WEIGHT, 0, true, NULL);
@@ -1833,8 +1847,6 @@ err_local_vqs:
err_vqs:
kfree(vs->old_inflight);
err_inflight:
- bitmap_free(vs->compl_bitmap);
-err_compl_bitmap:
kvfree(vs);
err_vs:
return r;
@@ -1854,7 +1866,6 @@ static int vhost_scsi_release(struct inode *inode, struct file *f)
kfree(vs->dev.vqs);
kfree(vs->vqs);
kfree(vs->old_inflight);
- bitmap_free(vs->compl_bitmap);
kvfree(vs);
return 0;
}
@@ -1916,6 +1927,14 @@ vhost_scsi_ioctl(struct file *f,
if (copy_from_user(&features, featurep, sizeof features))
return -EFAULT;
return vhost_scsi_set_features(vs, features);
+ case VHOST_NEW_WORKER:
+ case VHOST_FREE_WORKER:
+ case VHOST_ATTACH_VRING_WORKER:
+ case VHOST_GET_VRING_WORKER:
+ mutex_lock(&vs->dev.mutex);
+ r = vhost_worker_ioctl(&vs->dev, ioctl, argp);
+ mutex_unlock(&vs->dev.mutex);
+ return r;
default:
mutex_lock(&vs->dev.mutex);
r = vhost_dev_ioctl(&vs->dev, ioctl, argp);
@@ -1995,7 +2014,7 @@ vhost_scsi_do_plug(struct vhost_scsi_tpg *tpg,
goto unlock;
if (vhost_has_feature(vq, VIRTIO_SCSI_F_HOTPLUG))
- vhost_scsi_send_evt(vs, tpg, lun,
+ vhost_scsi_send_evt(vs, vq, tpg, lun,
VIRTIO_SCSI_T_TRANSPORT_RESET, reason);
unlock:
mutex_unlock(&vq->mutex);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 60c9ebd629dd..c71d573f1c94 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -187,13 +187,15 @@ EXPORT_SYMBOL_GPL(vhost_work_init);
/* Init poll structure */
void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
- __poll_t mask, struct vhost_dev *dev)
+ __poll_t mask, struct vhost_dev *dev,
+ struct vhost_virtqueue *vq)
{
init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup);
init_poll_funcptr(&poll->table, vhost_poll_func);
poll->mask = mask;
poll->dev = dev;
poll->wqh = NULL;
+ poll->vq = vq;
vhost_work_init(&poll->work, fn);
}
@@ -231,46 +233,102 @@ void vhost_poll_stop(struct vhost_poll *poll)
}
EXPORT_SYMBOL_GPL(vhost_poll_stop);
-void vhost_dev_flush(struct vhost_dev *dev)
+static void vhost_worker_queue(struct vhost_worker *worker,
+ struct vhost_work *work)
+{
+ if (!test_and_set_bit(VHOST_WORK_QUEUED, &work->flags)) {
+ /* We can only add the work to the list after we're
+ * sure it was not in the list.
+ * test_and_set_bit() implies a memory barrier.
+ */
+ llist_add(&work->node, &worker->work_list);
+ vhost_task_wake(worker->vtsk);
+ }
+}
+
+bool vhost_vq_work_queue(struct vhost_virtqueue *vq, struct vhost_work *work)
+{
+ struct vhost_worker *worker;
+ bool queued = false;
+
+ rcu_read_lock();
+ worker = rcu_dereference(vq->worker);
+ if (worker) {
+ queued = true;
+ vhost_worker_queue(worker, work);
+ }
+ rcu_read_unlock();
+
+ return queued;
+}
+EXPORT_SYMBOL_GPL(vhost_vq_work_queue);
+
+void vhost_vq_flush(struct vhost_virtqueue *vq)
{
struct vhost_flush_struct flush;
- if (dev->worker.vtsk) {
- init_completion(&flush.wait_event);
- vhost_work_init(&flush.work, vhost_flush_work);
+ init_completion(&flush.wait_event);
+ vhost_work_init(&flush.work, vhost_flush_work);
- vhost_work_queue(dev, &flush.work);
+ if (vhost_vq_work_queue(vq, &flush.work))
wait_for_completion(&flush.wait_event);
- }
}
-EXPORT_SYMBOL_GPL(vhost_dev_flush);
+EXPORT_SYMBOL_GPL(vhost_vq_flush);
-void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work)
+/**
+ * vhost_worker_flush - flush a worker
+ * @worker: worker to flush
+ *
+ * This does not use RCU to protect the worker, so the device or worker
+ * mutex must be held.
+ */
+static void vhost_worker_flush(struct vhost_worker *worker)
{
- if (!dev->worker.vtsk)
- return;
+ struct vhost_flush_struct flush;
- if (!test_and_set_bit(VHOST_WORK_QUEUED, &work->flags)) {
- /* We can only add the work to the list after we're
- * sure it was not in the list.
- * test_and_set_bit() implies a memory barrier.
- */
- llist_add(&work->node, &dev->worker.work_list);
- vhost_task_wake(dev->worker.vtsk);
+ init_completion(&flush.wait_event);
+ vhost_work_init(&flush.work, vhost_flush_work);
+
+ vhost_worker_queue(worker, &flush.work);
+ wait_for_completion(&flush.wait_event);
+}
+
+void vhost_dev_flush(struct vhost_dev *dev)
+{
+ struct vhost_worker *worker;
+ unsigned long i;
+
+ xa_for_each(&dev->worker_xa, i, worker) {
+ mutex_lock(&worker->mutex);
+ if (!worker->attachment_cnt) {
+ mutex_unlock(&worker->mutex);
+ continue;
+ }
+ vhost_worker_flush(worker);
+ mutex_unlock(&worker->mutex);
}
}
-EXPORT_SYMBOL_GPL(vhost_work_queue);
+EXPORT_SYMBOL_GPL(vhost_dev_flush);
/* A lockless hint for busy polling code to exit the loop */
-bool vhost_has_work(struct vhost_dev *dev)
+bool vhost_vq_has_work(struct vhost_virtqueue *vq)
{
- return !llist_empty(&dev->worker.work_list);
+ struct vhost_worker *worker;
+ bool has_work = false;
+
+ rcu_read_lock();
+ worker = rcu_dereference(vq->worker);
+ if (worker && !llist_empty(&worker->work_list))
+ has_work = true;
+ rcu_read_unlock();
+
+ return has_work;
}
-EXPORT_SYMBOL_GPL(vhost_has_work);
+EXPORT_SYMBOL_GPL(vhost_vq_has_work);
void vhost_poll_queue(struct vhost_poll *poll)
{
- vhost_work_queue(poll->dev, &poll->work);
+ vhost_vq_work_queue(poll->vq, &poll->work);
}
EXPORT_SYMBOL_GPL(vhost_poll_queue);
@@ -329,6 +387,7 @@ static void vhost_vq_reset(struct vhost_dev *dev,
vq->busyloop_timeout = 0;
vq->umem = NULL;
vq->iotlb = NULL;
+ rcu_assign_pointer(vq->worker, NULL);
vhost_vring_call_reset(&vq->call_ctx);
__vhost_vq_meta_reset(vq);
}
@@ -458,8 +517,6 @@ void vhost_dev_init(struct vhost_dev *dev,
dev->umem = NULL;
dev->iotlb = NULL;
dev->mm = NULL;
- memset(&dev->worker, 0, sizeof(dev->worker));
- init_llist_head(&dev->worker.work_list);
dev->iov_limit = iov_limit;
dev->weight = weight;
dev->byte_weight = byte_weight;
@@ -469,7 +526,7 @@ void vhost_dev_init(struct vhost_dev *dev,
INIT_LIST_HEAD(&dev->read_list);
INIT_LIST_HEAD(&dev->pending_list);
spin_lock_init(&dev->iotlb_lock);
-
+ xa_init_flags(&dev->worker_xa, XA_FLAGS_ALLOC);
for (i = 0; i < dev->nvqs; ++i) {
vq = dev->vqs[i];
@@ -481,7 +538,7 @@ void vhost_dev_init(struct vhost_dev *dev,
vhost_vq_reset(dev, vq);
if (vq->handle_kick)
vhost_poll_init(&vq->poll, vq->handle_kick,
- EPOLLIN, dev);
+ EPOLLIN, dev, vq);
}
}
EXPORT_SYMBOL_GPL(vhost_dev_init);
@@ -531,38 +588,284 @@ static void vhost_detach_mm(struct vhost_dev *dev)
dev->mm = NULL;
}
-static void vhost_worker_free(struct vhost_dev *dev)
+static void vhost_worker_destroy(struct vhost_dev *dev,
+ struct vhost_worker *worker)
+{
+ if (!worker)
+ return;
+
+ WARN_ON(!llist_empty(&worker->work_list));
+ xa_erase(&dev->worker_xa, worker->id);
+ vhost_task_stop(worker->vtsk);
+ kfree(worker);
+}
+
+static void vhost_workers_free(struct vhost_dev *dev)
{
- if (!dev->worker.vtsk)
+ struct vhost_worker *worker;
+ unsigned long i;
+
+ if (!dev->use_worker)
return;
- WARN_ON(!llist_empty(&dev->worker.work_list));
- vhost_task_stop(dev->worker.vtsk);
- dev->worker.kcov_handle = 0;
- dev->worker.vtsk = NULL;
+ for (i = 0; i < dev->nvqs; i++)
+ rcu_assign_pointer(dev->vqs[i]->worker, NULL);
+ /*
+ * Free the default worker we created and cleanup workers userspace
+ * created but couldn't clean up (it forgot or crashed).
+ */
+ xa_for_each(&dev->worker_xa, i, worker)
+ vhost_worker_destroy(dev, worker);
+ xa_destroy(&dev->worker_xa);
}
-static int vhost_worker_create(struct vhost_dev *dev)
+static struct vhost_worker *vhost_worker_create(struct vhost_dev *dev)
{
+ struct vhost_worker *worker;
struct vhost_task *vtsk;
char name[TASK_COMM_LEN];
+ int ret;
+ u32 id;
+
+ worker = kzalloc(sizeof(*worker), GFP_KERNEL_ACCOUNT);
+ if (!worker)
+ return NULL;
snprintf(name, sizeof(name), "vhost-%d", current->pid);
- vtsk = vhost_task_create(vhost_worker, &dev->worker, name);
+ vtsk = vhost_task_create(vhost_worker, worker, name);
if (!vtsk)
- return -ENOMEM;
+ goto free_worker;
+
+ mutex_init(&worker->mutex);
+ init_llist_head(&worker->work_list);
+ worker->kcov_handle = kcov_common_handle();
+ worker->vtsk = vtsk;
- dev->worker.kcov_handle = kcov_common_handle();
- dev->worker.vtsk = vtsk;
vhost_task_start(vtsk);
+
+ ret = xa_alloc(&dev->worker_xa, &id, worker, xa_limit_32b, GFP_KERNEL);
+ if (ret < 0)
+ goto stop_worker;
+ worker->id = id;
+
+ return worker;
+
+stop_worker:
+ vhost_task_stop(vtsk);
+free_worker:
+ kfree(worker);
+ return NULL;
+}
+
+/* Caller must have device mutex */
+static void __vhost_vq_attach_worker(struct vhost_virtqueue *vq,
+ struct vhost_worker *worker)
+{
+ struct vhost_worker *old_worker;
+
+ old_worker = rcu_dereference_check(vq->worker,
+ lockdep_is_held(&vq->dev->mutex));
+
+ mutex_lock(&worker->mutex);
+ worker->attachment_cnt++;
+ mutex_unlock(&worker->mutex);
+ rcu_assign_pointer(vq->worker, worker);
+
+ if (!old_worker)
+ return;
+ /*
+ * Take the worker mutex to make sure we see the work queued from
+ * device wide flushes which doesn't use RCU for execution.
+ */
+ mutex_lock(&old_worker->mutex);
+ old_worker->attachment_cnt--;
+ /*
+ * We don't want to call synchronize_rcu for every vq during setup
+ * because it will slow down VM startup. If we haven't done
+ * VHOST_SET_VRING_KICK and not done the driver specific
+ * SET_ENDPOINT/RUNNUNG then we can skip the sync since there will
+ * not be any works queued for scsi and net.
+ */
+ mutex_lock(&vq->mutex);
+ if (!vhost_vq_get_backend(vq) && !vq->kick) {
+ mutex_unlock(&vq->mutex);
+ mutex_unlock(&old_worker->mutex);
+ /*
+ * vsock can queue anytime after VHOST_VSOCK_SET_GUEST_CID.
+ * Warn if it adds support for multiple workers but forgets to
+ * handle the early queueing case.
+ */
+ WARN_ON(!old_worker->attachment_cnt &&
+ !llist_empty(&old_worker->work_list));
+ return;
+ }
+ mutex_unlock(&vq->mutex);
+
+ /* Make sure new vq queue/flush/poll calls see the new worker */
+ synchronize_rcu();
+ /* Make sure whatever was queued gets run */
+ vhost_worker_flush(old_worker);
+ mutex_unlock(&old_worker->mutex);
+}
+
+ /* Caller must have device mutex */
+static int vhost_vq_attach_worker(struct vhost_virtqueue *vq,
+ struct vhost_vring_worker *info)
+{
+ unsigned long index = info->worker_id;
+ struct vhost_dev *dev = vq->dev;
+ struct vhost_worker *worker;
+
+ if (!dev->use_worker)
+ return -EINVAL;
+
+ worker = xa_find(&dev->worker_xa, &index, UINT_MAX, XA_PRESENT);
+ if (!worker || worker->id != info->worker_id)
+ return -ENODEV;
+
+ __vhost_vq_attach_worker(vq, worker);
+ return 0;
+}
+
+/* Caller must have device mutex */
+static int vhost_new_worker(struct vhost_dev *dev,
+ struct vhost_worker_state *info)
+{
+ struct vhost_worker *worker;
+
+ worker = vhost_worker_create(dev);
+ if (!worker)
+ return -ENOMEM;
+
+ info->worker_id = worker->id;
+ return 0;
+}
+
+/* Caller must have device mutex */
+static int vhost_free_worker(struct vhost_dev *dev,
+ struct vhost_worker_state *info)
+{
+ unsigned long index = info->worker_id;
+ struct vhost_worker *worker;
+
+ worker = xa_find(&dev->worker_xa, &index, UINT_MAX, XA_PRESENT);
+ if (!worker || worker->id != info->worker_id)
+ return -ENODEV;
+
+ mutex_lock(&worker->mutex);
+ if (worker->attachment_cnt) {
+ mutex_unlock(&worker->mutex);
+ return -EBUSY;
+ }
+ mutex_unlock(&worker->mutex);
+
+ vhost_worker_destroy(dev, worker);
return 0;
}
+static int vhost_get_vq_from_user(struct vhost_dev *dev, void __user *argp,
+ struct vhost_virtqueue **vq, u32 *id)
+{
+ u32 __user *idxp = argp;
+ u32 idx;
+ long r;
+
+ r = get_user(idx, idxp);
+ if (r < 0)
+ return r;
+
+ if (idx >= dev->nvqs)
+ return -ENOBUFS;
+
+ idx = array_index_nospec(idx, dev->nvqs);
+
+ *vq = dev->vqs[idx];
+ *id = idx;
+ return 0;
+}
+
+/* Caller must have device mutex */
+long vhost_worker_ioctl(struct vhost_dev *dev, unsigned int ioctl,
+ void __user *argp)
+{
+ struct vhost_vring_worker ring_worker;
+ struct vhost_worker_state state;
+ struct vhost_worker *worker;
+ struct vhost_virtqueue *vq;
+ long ret;
+ u32 idx;
+
+ if (!dev->use_worker)
+ return -EINVAL;
+
+ if (!vhost_dev_has_owner(dev))
+ return -EINVAL;
+
+ ret = vhost_dev_check_owner(dev);
+ if (ret)
+ return ret;
+
+ switch (ioctl) {
+ /* dev worker ioctls */
+ case VHOST_NEW_WORKER:
+ ret = vhost_new_worker(dev, &state);
+ if (!ret && copy_to_user(argp, &state, sizeof(state)))
+ ret = -EFAULT;
+ return ret;
+ case VHOST_FREE_WORKER:
+ if (copy_from_user(&state, argp, sizeof(state)))
+ return -EFAULT;
+ return vhost_free_worker(dev, &state);
+ /* vring worker ioctls */
+ case VHOST_ATTACH_VRING_WORKER:
+ case VHOST_GET_VRING_WORKER:
+ break;
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ ret = vhost_get_vq_from_user(dev, argp, &vq, &idx);
+ if (ret)
+ return ret;
+
+ switch (ioctl) {
+ case VHOST_ATTACH_VRING_WORKER:
+ if (copy_from_user(&ring_worker, argp, sizeof(ring_worker))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ ret = vhost_vq_attach_worker(vq, &ring_worker);
+ break;
+ case VHOST_GET_VRING_WORKER:
+ worker = rcu_dereference_check(vq->worker,
+ lockdep_is_held(&dev->mutex));
+ if (!worker) {
+ ret = -EINVAL;
+ break;
+ }
+
+ ring_worker.index = idx;
+ ring_worker.worker_id = worker->id;
+
+ if (copy_to_user(argp, &ring_worker, sizeof(ring_worker)))
+ ret = -EFAULT;
+ break;
+ default:
+ ret = -ENOIOCTLCMD;
+ break;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(vhost_worker_ioctl);
+
/* Caller should have device mutex */
long vhost_dev_set_owner(struct vhost_dev *dev)
{
- int err;
+ struct vhost_worker *worker;
+ int err, i;
/* Is there an owner already? */
if (vhost_dev_has_owner(dev)) {
@@ -572,20 +875,32 @@ long vhost_dev_set_owner(struct vhost_dev *dev)
vhost_attach_mm(dev);
- if (dev->use_worker) {
- err = vhost_worker_create(dev);
- if (err)
- goto err_worker;
- }
-
err = vhost_dev_alloc_iovecs(dev);
if (err)
goto err_iovecs;
+ if (dev->use_worker) {
+ /*
+ * This should be done last, because vsock can queue work
+ * before VHOST_SET_OWNER so it simplifies the failure path
+ * below since we don't have to worry about vsock queueing
+ * while we free the worker.
+ */
+ worker = vhost_worker_create(dev);
+ if (!worker) {
+ err = -ENOMEM;
+ goto err_worker;
+ }
+
+ for (i = 0; i < dev->nvqs; i++)
+ __vhost_vq_attach_worker(dev->vqs[i], worker);
+ }
+
return 0;
-err_iovecs:
- vhost_worker_free(dev);
+
err_worker:
+ vhost_dev_free_iovecs(dev);
+err_iovecs:
vhost_detach_mm(dev);
err_mm:
return err;
@@ -677,7 +992,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
dev->iotlb = NULL;
vhost_clear_msg(dev);
wake_up_interruptible_poll(&dev->wait, EPOLLIN | EPOLLRDNORM);
- vhost_worker_free(dev);
+ vhost_workers_free(dev);
vhost_detach_mm(dev);
}
EXPORT_SYMBOL_GPL(vhost_dev_cleanup);
@@ -1565,21 +1880,15 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg
struct file *eventfp, *filep = NULL;
bool pollstart = false, pollstop = false;
struct eventfd_ctx *ctx = NULL;
- u32 __user *idxp = argp;
struct vhost_virtqueue *vq;
struct vhost_vring_state s;
struct vhost_vring_file f;
u32 idx;
long r;
- r = get_user(idx, idxp);
+ r = vhost_get_vq_from_user(d, argp, &vq, &idx);
if (r < 0)
return r;
- if (idx >= d->nvqs)
- return -ENOBUFS;
-
- idx = array_index_nospec(idx, d->nvqs);
- vq = d->vqs[idx];
if (ioctl == VHOST_SET_VRING_NUM ||
ioctl == VHOST_SET_VRING_ADDR) {
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index fc900be504b3..f60d5f7bef94 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -28,8 +28,12 @@ struct vhost_work {
struct vhost_worker {
struct vhost_task *vtsk;
+ /* Used to serialize device wide flushing with worker swapping. */
+ struct mutex mutex;
struct llist_head work_list;
u64 kcov_handle;
+ u32 id;
+ int attachment_cnt;
};
/* Poll a file (eventfd or socket) */
@@ -41,17 +45,17 @@ struct vhost_poll {
struct vhost_work work;
__poll_t mask;
struct vhost_dev *dev;
+ struct vhost_virtqueue *vq;
};
-void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn);
-void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work);
-bool vhost_has_work(struct vhost_dev *dev);
-
void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
- __poll_t mask, struct vhost_dev *dev);
+ __poll_t mask, struct vhost_dev *dev,
+ struct vhost_virtqueue *vq);
int vhost_poll_start(struct vhost_poll *poll, struct file *file);
void vhost_poll_stop(struct vhost_poll *poll);
void vhost_poll_queue(struct vhost_poll *poll);
+
+void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn);
void vhost_dev_flush(struct vhost_dev *dev);
struct vhost_log {
@@ -74,6 +78,7 @@ struct vhost_vring_call {
/* The virtqueue structure describes a queue attached to a device. */
struct vhost_virtqueue {
struct vhost_dev *dev;
+ struct vhost_worker __rcu *worker;
/* The actual ring of buffers. */
struct mutex mutex;
@@ -158,7 +163,6 @@ struct vhost_dev {
struct vhost_virtqueue **vqs;
int nvqs;
struct eventfd_ctx *log_ctx;
- struct vhost_worker worker;
struct vhost_iotlb *umem;
struct vhost_iotlb *iotlb;
spinlock_t iotlb_lock;
@@ -168,6 +172,7 @@ struct vhost_dev {
int iov_limit;
int weight;
int byte_weight;
+ struct xarray worker_xa;
bool use_worker;
int (*msg_handler)(struct vhost_dev *dev, u32 asid,
struct vhost_iotlb_msg *msg);
@@ -188,16 +193,21 @@ void vhost_dev_cleanup(struct vhost_dev *);
void vhost_dev_stop(struct vhost_dev *);
long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp);
long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp);
+long vhost_worker_ioctl(struct vhost_dev *dev, unsigned int ioctl,
+ void __user *argp);
bool vhost_vq_access_ok(struct vhost_virtqueue *vq);
bool vhost_log_access_ok(struct vhost_dev *);
void vhost_clear_msg(struct vhost_dev *dev);
int vhost_get_vq_desc(struct vhost_virtqueue *,
- struct iovec iov[], unsigned int iov_count,
+ struct iovec iov[], unsigned int iov_size,
unsigned int *out_num, unsigned int *in_num,
struct vhost_log *log, unsigned int *log_num);
void vhost_discard_vq_desc(struct vhost_virtqueue *, int n);
+void vhost_vq_flush(struct vhost_virtqueue *vq);
+bool vhost_vq_work_queue(struct vhost_virtqueue *vq, struct vhost_work *work);
+bool vhost_vq_has_work(struct vhost_virtqueue *vq);
bool vhost_vq_is_setup(struct vhost_virtqueue *vq);
int vhost_vq_init_access(struct vhost_virtqueue *);
int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 6578db78f0ae..817d377a3f36 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -285,7 +285,7 @@ vhost_transport_send_pkt(struct sk_buff *skb)
atomic_inc(&vsock->queued_replies);
virtio_vsock_skb_queue_tail(&vsock->send_pkt_queue, skb);
- vhost_work_queue(&vsock->dev, &vsock->send_pkt_work);
+ vhost_vq_work_queue(&vsock->vqs[VSOCK_VQ_RX], &vsock->send_pkt_work);
rcu_read_unlock();
return len;
@@ -583,7 +583,7 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
/* Some packets may have been queued before the device was started,
* let's kick the send worker to send them.
*/
- vhost_work_queue(&vsock->dev, &vsock->send_pkt_work);
+ vhost_vq_work_queue(&vsock->vqs[VSOCK_VQ_RX], &vsock->send_pkt_work);
mutex_unlock(&vsock->dev.mutex);
return 0;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index bf05363d8906..8b2b9ac37c3d 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -11,6 +11,13 @@ config APERTURE_HELPERS
Support tracking and hand-over of aperture ownership. Required
by graphics drivers for firmware-provided framebuffers.
+config STI_CORE
+ bool
+ depends on PARISC
+ help
+ STI refers to the HP "Standard Text Interface" which is a set of
+ BIOS routines contained in a ROM chip in HP PA-RISC based machines.
+
config VIDEO_CMDLINE
bool
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 831c9fa57a6c..6bbc03950899 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_APERTURE_HELPERS) += aperture.o
+obj-$(CONFIG_STI_CORE) += sticore.o
obj-$(CONFIG_VGASTATE) += vgastate.o
obj-$(CONFIG_VIDEO_CMDLINE) += cmdline.o
obj-$(CONFIG_VIDEO_NOMODESET) += nomodeset.o
diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c
index b009468ffdff..561be8feca96 100644
--- a/drivers/video/aperture.c
+++ b/drivers/video/aperture.c
@@ -43,7 +43,7 @@
* base = mem->start;
* size = resource_size(mem);
*
- * ret = aperture_remove_conflicting_devices(base, size, false, "example");
+ * ret = aperture_remove_conflicting_devices(base, size, "example");
* if (ret)
* return ret;
*
@@ -274,7 +274,6 @@ static void aperture_detach_devices(resource_size_t base, resource_size_t size)
* aperture_remove_conflicting_devices - remove devices in the given range
* @base: the aperture's base address in physical memory
* @size: aperture size in bytes
- * @primary: also kick vga16fb if present; only relevant for VGA devices
* @name: a descriptive name of the requesting driver
*
* This function removes devices that own apertures within @base and @size.
@@ -283,7 +282,7 @@ static void aperture_detach_devices(resource_size_t base, resource_size_t size)
* 0 on success, or a negative errno code otherwise
*/
int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size,
- bool primary, const char *name)
+ const char *name)
{
/*
* If a driver asked to unregister a platform device registered by
@@ -298,19 +297,42 @@ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t si
aperture_detach_devices(base, size);
- /*
- * If this is the primary adapter, there could be a VGA device
- * that consumes the VGA framebuffer I/O range. Remove this device
- * as well.
- */
- if (primary)
- aperture_detach_devices(VGA_FB_PHYS_BASE, VGA_FB_PHYS_SIZE);
-
return 0;
}
EXPORT_SYMBOL(aperture_remove_conflicting_devices);
/**
+ * __aperture_remove_legacy_vga_devices - remove legacy VGA devices of a PCI devices
+ * @pdev: PCI device
+ *
+ * This function removes VGA devices provided by @pdev, such as a VGA
+ * framebuffer or a console. This is useful if you have a VGA-compatible
+ * PCI graphics device with framebuffers in non-BAR locations. Drivers
+ * should acquire ownership of those memory areas and afterwards call
+ * this helper to release remaining VGA devices.
+ *
+ * If your hardware has its framebuffers accessible via PCI BARS, use
+ * aperture_remove_conflicting_pci_devices() instead. The function will
+ * release any VGA devices automatically.
+ *
+ * WARNING: Apparently we must remove graphics drivers before calling
+ * this helper. Otherwise the vga fbdev driver falls over if
+ * we have vgacon configured.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise
+ */
+int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev)
+{
+ /* VGA framebuffer */
+ aperture_detach_devices(VGA_FB_PHYS_BASE, VGA_FB_PHYS_SIZE);
+
+ /* VGA textmode console */
+ return vga_remove_vgacon(pdev);
+}
+EXPORT_SYMBOL(__aperture_remove_legacy_vga_devices);
+
+/**
* aperture_remove_conflicting_pci_devices - remove existing framebuffers for PCI devices
* @pdev: PCI device
* @name: a descriptive name of the requesting driver
@@ -326,11 +348,13 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *na
{
bool primary = false;
resource_size_t base, size;
- int bar, ret;
+ int bar, ret = 0;
-#ifdef CONFIG_X86
- primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-#endif
+ if (pdev == vga_default_device())
+ primary = true;
+
+ if (primary)
+ sysfb_disable();
for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) {
if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
@@ -338,20 +362,18 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *na
base = pci_resource_start(pdev, bar);
size = pci_resource_len(pdev, bar);
- ret = aperture_remove_conflicting_devices(base, size, primary, name);
- if (ret)
- return ret;
+ aperture_detach_devices(base, size);
}
/*
- * WARNING: Apparently we must kick fbdev drivers before vgacon,
- * otherwise the vga fbdev driver falls over.
+ * If this is the primary adapter, there could be a VGA device
+ * that consumes the VGA framebuffer I/O range. Remove this
+ * device as well.
*/
- ret = vga_remove_vgacon(pdev);
- if (ret)
- return ret;
+ if (primary)
+ ret = __aperture_remove_legacy_vga_devices(pdev);
- return 0;
+ return ret;
}
EXPORT_SYMBOL(aperture_remove_conflicting_pci_devices);
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index a479aab90f78..f51ada4795e8 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -803,8 +803,8 @@ static struct i2c_driver adp8860_driver = {
.name = KBUILD_MODNAME,
.pm = &adp8860_i2c_pm_ops,
},
- .probe_new = adp8860_probe,
- .remove = adp8860_remove,
+ .probe = adp8860_probe,
+ .remove = adp8860_remove,
.id_table = adp8860_id,
};
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index d6b0007db649..6bb18dc970e9 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -973,8 +973,8 @@ static struct i2c_driver adp8870_driver = {
.name = KBUILD_MODNAME,
.pm = &adp8870_i2c_pm_ops,
},
- .probe_new = adp8870_probe,
- .remove = adp8870_remove,
+ .probe = adp8870_probe,
+ .remove = adp8870_remove,
.id_table = adp8870_id,
};
diff --git a/drivers/video/backlight/arcxcnn_bl.c b/drivers/video/backlight/arcxcnn_bl.c
index 088bcca547dd..1d5a570cfe02 100644
--- a/drivers/video/backlight/arcxcnn_bl.c
+++ b/drivers/video/backlight/arcxcnn_bl.c
@@ -392,7 +392,7 @@ static struct i2c_driver arcxcnn_driver = {
.name = "arcxcnn_bl",
.of_match_table = arcxcnn_dt_ids,
},
- .probe_new = arcxcnn_probe,
+ .probe = arcxcnn_probe,
.remove = arcxcnn_remove,
.id_table = arcxcnn_ids,
};
diff --git a/drivers/video/backlight/bd6107.c b/drivers/video/backlight/bd6107.c
index f4db6c064635..7df25faa07a5 100644
--- a/drivers/video/backlight/bd6107.c
+++ b/drivers/video/backlight/bd6107.c
@@ -192,7 +192,7 @@ static struct i2c_driver bd6107_driver = {
.driver = {
.name = "bd6107",
},
- .probe_new = bd6107_probe,
+ .probe = bd6107_probe,
.remove = bd6107_remove,
.id_table = bd6107_ids,
};
diff --git a/drivers/video/backlight/ktz8866.c b/drivers/video/backlight/ktz8866.c
index d38c13ad39c7..9c980f2571ee 100644
--- a/drivers/video/backlight/ktz8866.c
+++ b/drivers/video/backlight/ktz8866.c
@@ -196,7 +196,7 @@ static struct i2c_driver ktz8866_driver = {
.name = "ktz8866",
.of_match_table = ktz8866_match_table,
},
- .probe_new = ktz8866_probe,
+ .probe = ktz8866_probe,
.remove = ktz8866_remove,
.id_table = ktz8866_ids,
};
diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c
index a1b6a2ad73a0..3259292fda76 100644
--- a/drivers/video/backlight/led_bl.c
+++ b/drivers/video/backlight/led_bl.c
@@ -209,8 +209,11 @@ static int led_bl_probe(struct platform_device *pdev)
return PTR_ERR(priv->bl_dev);
}
- for (i = 0; i < priv->nb_leds; i++)
+ for (i = 0; i < priv->nb_leds; i++) {
+ mutex_lock(&priv->leds[i]->led_access);
led_sysfs_disable(priv->leds[i]);
+ mutex_unlock(&priv->leds[i]->led_access);
+ }
backlight_update_status(priv->bl_dev);
diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c
index d8c42acecb5d..8fcb62be597b 100644
--- a/drivers/video/backlight/lm3630a_bl.c
+++ b/drivers/video/backlight/lm3630a_bl.c
@@ -202,7 +202,9 @@ static int lm3630a_bank_a_update_status(struct backlight_device *bl)
usleep_range(1000, 2000);
/* minimum brightness is 0x04 */
ret = lm3630a_write(pchip, REG_BRT_A, bl->props.brightness);
- if (bl->props.brightness < 0x4)
+
+ if (backlight_is_blank(bl) || (backlight_get_brightness(bl) < 0x4))
+ /* turn the string off */
ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDA_ENABLE, 0);
else
ret |= lm3630a_update(pchip, REG_CTRL,
@@ -277,7 +279,9 @@ static int lm3630a_bank_b_update_status(struct backlight_device *bl)
usleep_range(1000, 2000);
/* minimum brightness is 0x04 */
ret = lm3630a_write(pchip, REG_BRT_B, bl->props.brightness);
- if (bl->props.brightness < 0x4)
+
+ if (backlight_is_blank(bl) || (backlight_get_brightness(bl) < 0x4))
+ /* turn the string off */
ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, 0);
else
ret |= lm3630a_update(pchip, REG_CTRL,
@@ -616,7 +620,7 @@ static struct i2c_driver lm3630a_i2c_driver = {
.name = LM3630A_NAME,
.of_match_table = lm3630a_match_table,
},
- .probe_new = lm3630a_probe,
+ .probe = lm3630a_probe,
.remove = lm3630a_remove,
.id_table = lm3630a_id,
};
diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c
index a836628ce06e..5246c171497d 100644
--- a/drivers/video/backlight/lm3639_bl.c
+++ b/drivers/video/backlight/lm3639_bl.c
@@ -411,7 +411,7 @@ static struct i2c_driver lm3639_i2c_driver = {
.driver = {
.name = LM3639_NAME,
},
- .probe_new = lm3639_probe,
+ .probe = lm3639_probe,
.remove = lm3639_remove,
.id_table = lm3639_id,
};
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index a57c9ef3b1cc..1c9e921bca14 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -218,23 +218,10 @@ err:
static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br)
{
- struct pwm_device *pwm;
struct pwm_state state;
- /* request pwm device with the consumer name */
- if (!lp->pwm) {
- pwm = devm_pwm_get(lp->dev, lp->chipname);
- if (IS_ERR(pwm))
- return;
-
- lp->pwm = pwm;
-
- pwm_init_state(lp->pwm, &state);
- } else {
- pwm_get_state(lp->pwm, &state);
- }
+ pwm_get_state(lp->pwm, &state);
- state.period = lp->pdata->period_ns;
state.duty_cycle = div_u64(br * state.period, max_br);
state.enabled = state.duty_cycle;
@@ -339,6 +326,7 @@ static int lp855x_parse_dt(struct lp855x *lp)
of_property_read_string(node, "bl-name", &pdata->name);
of_property_read_u8(node, "dev-ctrl", &pdata->device_control);
of_property_read_u8(node, "init-brt", &pdata->initial_brightness);
+ /* Deprecated, specify period in pwms property instead */
of_property_read_u32(node, "pwm-period", &pdata->period_ns);
/* Fill ROM platform data if defined */
@@ -399,6 +387,7 @@ static int lp855x_probe(struct i2c_client *cl)
const struct i2c_device_id *id = i2c_client_get_device_id(cl);
const struct acpi_device_id *acpi_id = NULL;
struct device *dev = &cl->dev;
+ struct pwm_state pwmstate;
struct lp855x *lp;
int ret;
@@ -457,11 +446,6 @@ static int lp855x_probe(struct i2c_client *cl)
}
}
- if (lp->pdata->period_ns > 0)
- lp->mode = PWM_BASED;
- else
- lp->mode = REGISTER_BASED;
-
lp->supply = devm_regulator_get(dev, "power");
if (IS_ERR(lp->supply)) {
if (PTR_ERR(lp->supply) == -EPROBE_DEFER)
@@ -472,11 +456,31 @@ static int lp855x_probe(struct i2c_client *cl)
lp->enable = devm_regulator_get_optional(dev, "enable");
if (IS_ERR(lp->enable)) {
ret = PTR_ERR(lp->enable);
- if (ret == -ENODEV) {
+ if (ret == -ENODEV)
lp->enable = NULL;
- } else {
+ else
return dev_err_probe(dev, ret, "getting enable regulator\n");
- }
+ }
+
+ lp->pwm = devm_pwm_get(lp->dev, lp->chipname);
+ if (IS_ERR(lp->pwm)) {
+ ret = PTR_ERR(lp->pwm);
+ if (ret == -ENODEV || ret == -EINVAL)
+ lp->pwm = NULL;
+ else
+ return dev_err_probe(dev, ret, "getting PWM\n");
+
+ lp->mode = REGISTER_BASED;
+ dev_dbg(dev, "mode: register based\n");
+ } else {
+ pwm_init_state(lp->pwm, &pwmstate);
+ /* Legacy platform data compatibility */
+ if (lp->pdata->period_ns > 0)
+ pwmstate.period = lp->pdata->period_ns;
+ pwm_apply_state(lp->pwm, &pwmstate);
+
+ lp->mode = PWM_BASED;
+ dev_dbg(dev, "mode: PWM based\n");
}
if (lp->supply) {
@@ -587,7 +591,7 @@ static struct i2c_driver lp855x_driver = {
.of_match_table = of_match_ptr(lp855x_dt_ids),
.acpi_match_table = ACPI_PTR(lp855x_acpi_match),
},
- .probe_new = lp855x_probe,
+ .probe = lp855x_probe,
.remove = lp855x_remove,
.id_table = lp855x_ids,
};
diff --git a/drivers/video/backlight/lv5207lp.c b/drivers/video/backlight/lv5207lp.c
index 00673c8b66ac..56695ce67e48 100644
--- a/drivers/video/backlight/lv5207lp.c
+++ b/drivers/video/backlight/lv5207lp.c
@@ -141,7 +141,7 @@ static struct i2c_driver lv5207lp_driver = {
.driver = {
.name = "lv5207lp",
},
- .probe_new = lv5207lp_probe,
+ .probe = lv5207lp_probe,
.remove = lv5207lp_remove,
.id_table = lv5207lp_ids,
};
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index fce412234d10..a51fbab96368 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -54,8 +54,7 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb)
if (pb->post_pwm_on_delay)
msleep(pb->post_pwm_on_delay);
- if (pb->enable_gpio)
- gpiod_set_value_cansleep(pb->enable_gpio, 1);
+ gpiod_set_value_cansleep(pb->enable_gpio, 1);
pb->enabled = true;
}
@@ -65,8 +64,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb)
if (!pb->enabled)
return;
- if (pb->enable_gpio)
- gpiod_set_value_cansleep(pb->enable_gpio, 0);
+ gpiod_set_value_cansleep(pb->enable_gpio, 0);
if (pb->pwm_off_delay)
msleep(pb->pwm_off_delay);
@@ -429,8 +427,7 @@ static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
* Synchronize the enable_gpio with the observed state of the
* hardware.
*/
- if (pb->enable_gpio)
- gpiod_direction_output(pb->enable_gpio, active);
+ gpiod_direction_output(pb->enable_gpio, active);
/*
* Do not change pb->enabled here! pb->enabled essentially
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 22cea5082ac4..a2a88d42edf0 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -141,6 +141,7 @@ config STI_CONSOLE
depends on PARISC && HAS_IOMEM
select FONT_SUPPORT
select CRC32
+ select STI_CORE
default y
help
The STI console is the builtin display/keyboard on HP-PARISC
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index db07b784bd2c..fd79016a0d95 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -5,8 +5,6 @@
obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o
obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o
-obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o
+obj-$(CONFIG_STI_CONSOLE) += sticon.o
obj-$(CONFIG_VGA_CONSOLE) += vgacon.o
obj-$(CONFIG_MDA_CONSOLE) += mdacon.o
-
-obj-$(CONFIG_FB_STI) += sticore.o
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 2cea69418a83..d11cfd2d68b5 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -50,7 +50,7 @@
#include <asm/io.h>
-#include "../fbdev/sticore.h"
+#include <video/sticore.h>
/* switching to graphics mode */
#define BLANK 0
@@ -282,7 +282,7 @@ static void sticon_init(struct vc_data *c, int init)
vc_cols = sti_onscreen_x(sti) / sti->font->width;
vc_rows = sti_onscreen_y(sti) / sti->font->height;
c->vc_can_do_color = 1;
-
+
if (init) {
c->vc_cols = vc_cols;
c->vc_rows = vc_rows;
@@ -374,7 +374,7 @@ static const struct consw sti_con = {
.con_font_set = sticon_font_set,
.con_font_default = sticon_font_default,
.con_build_attr = sticon_build_attr,
- .con_invert_region = sticon_invert_region,
+ .con_invert_region = sticon_invert_region,
};
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 0fdf5f46802c..6df9bd09454a 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -158,6 +158,27 @@ config FB_DEFERRED_IO
bool
depends on FB
+config FB_IO_HELPERS
+ bool
+ depends on FB
+ select FB_CFB_COPYAREA
+ select FB_CFB_FILLRECT
+ select FB_CFB_IMAGEBLIT
+
+config FB_SYS_HELPERS
+ bool
+ depends on FB
+ select FB_SYS_COPYAREA
+ select FB_SYS_FILLRECT
+ select FB_SYS_FOPS
+ select FB_SYS_IMAGEBLIT
+
+config FB_SYS_HELPERS_DEFERRED
+ bool
+ depends on FB
+ select FB_DEFERRED_IO
+ select FB_SYS_HELPERS
+
config FB_HECUBA
tristate
depends on FB
@@ -551,10 +572,9 @@ config FB_STI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
+ select STI_CORE
default y
help
- STI refers to the HP "Standard Text Interface" which is a set of
- BIOS routines contained in a ROM chip in HP PA-RISC based machines.
Enabling this option will implement the linux framebuffer device
using calls to the STI BIOS routines for initialisation.
diff --git a/drivers/video/fbdev/arcfb.c b/drivers/video/fbdev/arcfb.c
index 08d15e408413..9aaea3be8281 100644
--- a/drivers/video/fbdev/arcfb.c
+++ b/drivers/video/fbdev/arcfb.c
@@ -41,6 +41,7 @@
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/arcfb.h>
@@ -260,7 +261,7 @@ static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper,
ks108_set_yaddr(par, chipindex, upper/8);
linesize = par->info->var.xres/8;
- src = (unsigned char __force *) par->info->screen_base + (left/8) +
+ src = (unsigned char *)par->info->screen_buffer + (left/8) +
(upper * linesize);
ks108_set_xaddr(par, chipindex, left);
@@ -451,6 +452,9 @@ static ssize_t arcfb_write(struct fb_info *info, const char __user *buf,
struct arcfb_par *par;
unsigned int xres;
+ if (!info->screen_buffer)
+ return -ENODEV;
+
p = *ppos;
par = info->par;
xres = info->var.xres;
@@ -468,7 +472,7 @@ static ssize_t arcfb_write(struct fb_info *info, const char __user *buf,
if (count) {
char *base_addr;
- base_addr = (char __force *)info->screen_base;
+ base_addr = info->screen_buffer;
count -= copy_from_user(base_addr + p, buf, count);
*ppos += count;
err = -EFAULT;
@@ -525,7 +529,7 @@ static int arcfb_probe(struct platform_device *dev)
if (!info)
goto err_fb_alloc;
- info->screen_base = (char __iomem *)videomemory;
+ info->screen_buffer = videomemory;
info->fbops = &arcfb_ops;
info->var = arcfb_var;
@@ -598,7 +602,7 @@ static void arcfb_remove(struct platform_device *dev)
unregister_framebuffer(info);
if (irq)
free_irq(((struct arcfb_par *)(info->par))->irq, info);
- vfree((void __force *)info->screen_base);
+ vfree(info->screen_buffer);
framebuffer_release(info);
}
}
diff --git a/drivers/video/fbdev/aty/atyfb.h b/drivers/video/fbdev/aty/atyfb.h
index 465f55beb97f..30da3e82ed3c 100644
--- a/drivers/video/fbdev/aty/atyfb.h
+++ b/drivers/video/fbdev/aty/atyfb.h
@@ -3,8 +3,10 @@
* ATI Frame Buffer Device Driver Core Definitions
*/
+#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
+
/*
* Elements of the hardware specific atyfb_par structure
*/
diff --git a/drivers/video/fbdev/aty/mach64_cursor.c b/drivers/video/fbdev/aty/mach64_cursor.c
index 4ad0331a8c57..971355c2cd7e 100644
--- a/drivers/video/fbdev/aty/mach64_cursor.c
+++ b/drivers/video/fbdev/aty/mach64_cursor.c
@@ -153,7 +153,7 @@ static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
u8 m, b;
// Clear cursor image with 1010101010...
- fb_memset(dst, 0xaa, 1024);
+ fb_memset_io(dst, 0xaa, 1024);
offset = align - width*2;
diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c
index aed88ce45bf0..5c232eb13724 100644
--- a/drivers/video/fbdev/au1200fb.c
+++ b/drivers/video/fbdev/au1200fb.c
@@ -1568,7 +1568,7 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
fbi->fix.mmio_len = 0;
fbi->fix.accel = FB_ACCEL_NONE;
- fbi->screen_base = (char __iomem *) fbdev->fb_mem;
+ fbi->screen_buffer = fbdev->fb_mem;
au1200fb_update_fbinfo(fbi);
diff --git a/drivers/video/fbdev/broadsheetfb.c b/drivers/video/fbdev/broadsheetfb.c
index b518cacbf7cd..06403a4fe0e3 100644
--- a/drivers/video/fbdev/broadsheetfb.c
+++ b/drivers/video/fbdev/broadsheetfb.c
@@ -824,7 +824,7 @@ static void broadsheet_init_display(struct broadsheetfb_par *par)
broadsheet_burst_write(par, (panel_table[par->panel_index].w *
panel_table[par->panel_index].h)/2,
- (u16 *) par->info->screen_base);
+ (u16 *)par->info->screen_buffer);
broadsheet_send_command(par, BS_CMD_LD_IMG_END);
@@ -865,7 +865,7 @@ static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
u16 y1, u16 y2)
{
u16 args[5];
- unsigned char *buf = (unsigned char *)par->info->screen_base;
+ unsigned char *buf = par->info->screen_buffer;
mutex_lock(&(par->io_lock));
/* y1 must be a multiple of 4 so drop the lower bits */
@@ -913,7 +913,7 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
broadsheet_burst_write(par, (panel_table[par->panel_index].w *
panel_table[par->panel_index].h)/2,
- (u16 *) par->info->screen_base);
+ (u16 *)par->info->screen_buffer);
broadsheet_send_command(par, BS_CMD_LD_IMG_END);
@@ -1013,8 +1013,8 @@ static ssize_t broadsheetfb_write(struct fb_info *info, const char __user *buf,
int err = 0;
unsigned long total_size;
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
+ if (!info->screen_buffer)
+ return -ENODEV;
total_size = info->fix.smem_len;
@@ -1033,7 +1033,7 @@ static ssize_t broadsheetfb_write(struct fb_info *info, const char __user *buf,
count = total_size - p;
}
- dst = (void *)(info->screen_base + p);
+ dst = info->screen_buffer + p;
if (copy_from_user(dst, buf, count))
err = -EFAULT;
@@ -1109,7 +1109,7 @@ static int broadsheetfb_probe(struct platform_device *dev)
if (!videomemory)
goto err_fb_rel;
- info->screen_base = (char *)videomemory;
+ info->screen_buffer = videomemory;
info->fbops = &broadsheetfb_ops;
broadsheetfb_var.xres = dpyw;
@@ -1205,7 +1205,7 @@ static void broadsheetfb_remove(struct platform_device *dev)
fb_deferred_io_cleanup(info);
par->board->cleanup(par);
fb_dealloc_cmap(&info->cmap);
- vfree((void *)info->screen_base);
+ vfree(info->screen_buffer);
module_put(par->board->owner);
framebuffer_release(info);
}
@@ -1223,3 +1223,5 @@ module_platform_driver(broadsheetfb_driver);
MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
MODULE_AUTHOR("Jaya Kumar");
MODULE_LICENSE("GPL");
+
+MODULE_FIRMWARE("broadsheet.wbf");
diff --git a/drivers/video/fbdev/chipsfb.c b/drivers/video/fbdev/chipsfb.c
index 7799d52a651f..2a27ba94f652 100644
--- a/drivers/video/fbdev/chipsfb.c
+++ b/drivers/video/fbdev/chipsfb.c
@@ -332,7 +332,7 @@ static const struct fb_var_screeninfo chipsfb_var = {
static void init_chips(struct fb_info *p, unsigned long addr)
{
- fb_memset(p->screen_base, 0, 0x100000);
+ fb_memset_io(p->screen_base, 0, 0x100000);
p->fix = chipsfb_fix;
p->fix.smem_start = addr;
diff --git a/drivers/video/fbdev/cobalt_lcdfb.c b/drivers/video/fbdev/cobalt_lcdfb.c
index feeace079425..3d59a01ec677 100644
--- a/drivers/video/fbdev/cobalt_lcdfb.c
+++ b/drivers/video/fbdev/cobalt_lcdfb.c
@@ -129,6 +129,9 @@ static ssize_t cobalt_lcdfb_read(struct fb_info *info, char __user *buf,
unsigned long pos;
int len, retval = 0;
+ if (!info->screen_base)
+ return -ENODEV;
+
pos = *ppos;
if (pos >= LCD_CHARS_MAX || count == 0)
return 0;
@@ -175,6 +178,9 @@ static ssize_t cobalt_lcdfb_write(struct fb_info *info, const char __user *buf,
unsigned long pos;
int len, retval = 0;
+ if (!info->screen_base)
+ return -ENODEV;
+
pos = *ppos;
if (pos >= LCD_CHARS_MAX || count == 0)
return 0;
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
index 08fabce76b74..8f0060160ffb 100644
--- a/drivers/video/fbdev/core/Makefile
+++ b/drivers/video/fbdev/core/Makefile
@@ -2,7 +2,7 @@
obj-$(CONFIG_FB_NOTIFY) += fb_notify.o
obj-$(CONFIG_FB) += fb.o
fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
- modedb.o fbcvt.o fb_cmdline.o
+ modedb.o fbcvt.o fb_cmdline.o fb_io_fops.o
fb-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE),y)
diff --git a/drivers/video/fbdev/core/fb_io_fops.c b/drivers/video/fbdev/core/fb_io_fops.c
new file mode 100644
index 000000000000..5985e5e1b040
--- /dev/null
+++ b/drivers/video/fbdev/core/fb_io_fops.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+ssize_t fb_io_read(struct fb_info *info, char __user *buf, size_t count, loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ u8 *buffer, *dst;
+ u8 __iomem *src;
+ int c, cnt = 0, err = 0;
+ unsigned long total_size, trailing;
+
+ if (!info->screen_base)
+ return -ENODEV;
+
+ total_size = info->screen_size;
+
+ if (total_size == 0)
+ total_size = info->fix.smem_len;
+
+ if (p >= total_size)
+ return 0;
+
+ if (count >= total_size)
+ count = total_size;
+
+ if (count + p > total_size)
+ count = total_size - p;
+
+ buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+ GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ src = (u8 __iomem *) (info->screen_base + p);
+
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+
+ while (count) {
+ c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+ dst = buffer;
+ fb_memcpy_fromio(dst, src, c);
+ dst += c;
+ src += c;
+
+ trailing = copy_to_user(buf, buffer, c);
+ if (trailing == c) {
+ err = -EFAULT;
+ break;
+ }
+ c -= trailing;
+
+ *ppos += c;
+ buf += c;
+ cnt += c;
+ count -= c;
+ }
+
+ kfree(buffer);
+
+ return cnt ? cnt : err;
+}
+EXPORT_SYMBOL(fb_io_read);
+
+ssize_t fb_io_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ u8 *buffer, *src;
+ u8 __iomem *dst;
+ int c, cnt = 0, err = 0;
+ unsigned long total_size, trailing;
+
+ if (!info->screen_base)
+ return -ENODEV;
+
+ total_size = info->screen_size;
+
+ if (total_size == 0)
+ total_size = info->fix.smem_len;
+
+ if (p > total_size)
+ return -EFBIG;
+
+ if (count > total_size) {
+ err = -EFBIG;
+ count = total_size;
+ }
+
+ if (count + p > total_size) {
+ if (!err)
+ err = -ENOSPC;
+
+ count = total_size - p;
+ }
+
+ buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+ GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ dst = (u8 __iomem *) (info->screen_base + p);
+
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+
+ while (count) {
+ c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+ src = buffer;
+
+ trailing = copy_from_user(src, buf, c);
+ if (trailing == c) {
+ err = -EFAULT;
+ break;
+ }
+ c -= trailing;
+
+ fb_memcpy_toio(dst, src, c);
+ dst += c;
+ src += c;
+ *ppos += c;
+ buf += c;
+ cnt += c;
+ count -= c;
+ }
+
+ kfree(buffer);
+
+ return (cnt) ? cnt : err;
+}
+EXPORT_SYMBOL(fb_io_write);
diff --git a/drivers/video/fbdev/core/fb_sys_fops.c b/drivers/video/fbdev/core/fb_sys_fops.c
index ff275d7f3eaf..0cb0989abda6 100644
--- a/drivers/video/fbdev/core/fb_sys_fops.c
+++ b/drivers/video/fbdev/core/fb_sys_fops.c
@@ -19,10 +19,11 @@ ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count,
unsigned long p = *ppos;
void *src;
int err = 0;
- unsigned long total_size;
+ unsigned long total_size, c;
+ ssize_t ret;
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
+ if (!info->screen_buffer)
+ return -ENODEV;
total_size = info->screen_size;
@@ -38,18 +39,19 @@ ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count,
if (count + p > total_size)
count = total_size - p;
- src = (void __force *)(info->screen_base + p);
+ src = info->screen_buffer + p;
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
- if (copy_to_user(buf, src, count))
+ c = copy_to_user(buf, src, count);
+ if (c)
err = -EFAULT;
+ ret = count - c;
- if (!err)
- *ppos += count;
+ *ppos += ret;
- return (err) ? err : count;
+ return ret ? ret : err;
}
EXPORT_SYMBOL_GPL(fb_sys_read);
@@ -59,10 +61,11 @@ ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
unsigned long p = *ppos;
void *dst;
int err = 0;
- unsigned long total_size;
+ unsigned long total_size, c;
+ size_t ret;
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
+ if (!info->screen_buffer)
+ return -ENODEV;
total_size = info->screen_size;
@@ -84,18 +87,19 @@ ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
count = total_size - p;
}
- dst = (void __force *) (info->screen_base + p);
+ dst = info->screen_buffer + p;
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
- if (copy_from_user(dst, buf, count))
+ c = copy_from_user(dst, buf, count);
+ if (c)
err = -EFAULT;
+ ret = count - c;
- if (!err)
- *ppos += count;
+ *ppos += ret;
- return (err) ? err : count;
+ return ret ? ret : err;
}
EXPORT_SYMBOL_GPL(fb_sys_write);
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index eb565a10e5cd..c6c9d040bdec 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -75,7 +75,6 @@
#include <linux/interrupt.h>
#include <linux/crc32.h> /* For counting font checksums */
#include <linux/uaccess.h>
-#include <asm/fb.h>
#include <asm/irq.h>
#include "fbcon.h"
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 28739f1cb5e7..329d16e49a90 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -37,8 +37,6 @@
#include <linux/mem_encrypt.h>
#include <linux/pci.h>
-#include <asm/fb.h>
-
#include <video/nomodeset.h>
#include <video/vga.h>
@@ -761,14 +759,9 @@ static struct fb_info *file_fb_info(struct file *file)
static ssize_t
fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
- unsigned long p = *ppos;
struct fb_info *info = file_fb_info(file);
- u8 *buffer, *dst;
- u8 __iomem *src;
- int c, cnt = 0, err = 0;
- unsigned long total_size;
- if (!info || ! info->screen_base)
+ if (!info)
return -ENODEV;
if (info->state != FBINFO_STATE_RUNNING)
@@ -777,63 +770,15 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
if (info->fbops->fb_read)
return info->fbops->fb_read(info, buf, count, ppos);
- total_size = info->screen_size;
-
- if (total_size == 0)
- total_size = info->fix.smem_len;
-
- if (p >= total_size)
- return 0;
-
- if (count >= total_size)
- count = total_size;
-
- if (count + p > total_size)
- count = total_size - p;
-
- buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
- GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- src = (u8 __iomem *) (info->screen_base + p);
-
- if (info->fbops->fb_sync)
- info->fbops->fb_sync(info);
-
- while (count) {
- c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
- dst = buffer;
- fb_memcpy_fromfb(dst, src, c);
- dst += c;
- src += c;
-
- if (copy_to_user(buf, buffer, c)) {
- err = -EFAULT;
- break;
- }
- *ppos += c;
- buf += c;
- cnt += c;
- count -= c;
- }
-
- kfree(buffer);
-
- return (err) ? err : cnt;
+ return fb_io_read(info, buf, count, ppos);
}
static ssize_t
fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
- unsigned long p = *ppos;
struct fb_info *info = file_fb_info(file);
- u8 *buffer, *src;
- u8 __iomem *dst;
- int c, cnt = 0, err = 0;
- unsigned long total_size;
- if (!info || !info->screen_base)
+ if (!info)
return -ENODEV;
if (info->state != FBINFO_STATE_RUNNING)
@@ -842,57 +787,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
if (info->fbops->fb_write)
return info->fbops->fb_write(info, buf, count, ppos);
- total_size = info->screen_size;
-
- if (total_size == 0)
- total_size = info->fix.smem_len;
-
- if (p > total_size)
- return -EFBIG;
-
- if (count > total_size) {
- err = -EFBIG;
- count = total_size;
- }
-
- if (count + p > total_size) {
- if (!err)
- err = -ENOSPC;
-
- count = total_size - p;
- }
-
- buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
- GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- dst = (u8 __iomem *) (info->screen_base + p);
-
- if (info->fbops->fb_sync)
- info->fbops->fb_sync(info);
-
- while (count) {
- c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
- src = buffer;
-
- if (copy_from_user(src, buf, c)) {
- err = -EFAULT;
- break;
- }
-
- fb_memcpy_tofb(dst, src, c);
- dst += c;
- src += c;
- *ppos += c;
- buf += c;
- cnt += c;
- count -= c;
- }
-
- kfree(buffer);
-
- return (cnt) ? cnt : err;
+ return fb_io_write(info, buf, count, ppos);
}
int
diff --git a/drivers/video/fbdev/core/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c
index 335e92b813fc..665ef7a0a249 100644
--- a/drivers/video/fbdev/core/sysimgblt.c
+++ b/drivers/video/fbdev/core/sysimgblt.c
@@ -189,7 +189,7 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
u32 bit_mask, eorx, shift;
- const char *s = image->data, *src;
+ const u8 *s = image->data, *src;
u32 *dst;
const u32 *tab;
size_t tablen;
diff --git a/drivers/video/fbdev/hecubafb.c b/drivers/video/fbdev/hecubafb.c
index 5a149458d3b4..7ce0a16ce8b9 100644
--- a/drivers/video/fbdev/hecubafb.c
+++ b/drivers/video/fbdev/hecubafb.c
@@ -102,7 +102,7 @@ static void apollo_send_command(struct hecubafb_par *par, unsigned char data)
static void hecubafb_dpy_update(struct hecubafb_par *par)
{
int i;
- unsigned char *buf = (unsigned char __force *)par->info->screen_base;
+ unsigned char *buf = par->info->screen_buffer;
apollo_send_command(par, APOLLO_START_NEW_IMG);
@@ -163,8 +163,8 @@ static ssize_t hecubafb_write(struct fb_info *info, const char __user *buf,
int err = 0;
unsigned long total_size;
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
+ if (!info->screen_buffer)
+ return -ENODEV;
total_size = info->fix.smem_len;
@@ -183,7 +183,7 @@ static ssize_t hecubafb_write(struct fb_info *info, const char __user *buf,
count = total_size - p;
}
- dst = (void __force *) (info->screen_base + p);
+ dst = info->screen_buffer + p;
if (copy_from_user(dst, buf, count))
err = -EFAULT;
@@ -239,7 +239,7 @@ static int hecubafb_probe(struct platform_device *dev)
if (!info)
goto err_fballoc;
- info->screen_base = (char __force __iomem *)videomemory;
+ info->screen_buffer = videomemory;
info->fbops = &hecubafb_ops;
info->var = hecubafb_var;
@@ -287,7 +287,7 @@ static void hecubafb_remove(struct platform_device *dev)
struct hecubafb_par *par = info->par;
fb_deferred_io_cleanup(info);
unregister_framebuffer(info);
- vfree((void __force *)info->screen_base);
+ vfree(info->screen_buffer);
if (par->board->remove)
par->board->remove(par);
module_put(par->board->owner);
diff --git a/drivers/video/fbdev/hitfb.c b/drivers/video/fbdev/hitfb.c
index 3033f5056976..9fd196637d14 100644
--- a/drivers/video/fbdev/hitfb.c
+++ b/drivers/video/fbdev/hitfb.c
@@ -42,17 +42,33 @@ static struct fb_fix_screeninfo hitfb_fix = {
.accel = FB_ACCEL_NONE,
};
+static volatile void __iomem *hitfb_offset_to_addr(unsigned int offset)
+{
+ return (__force volatile void __iomem *)(uintptr_t)offset;
+}
+
+static u16 hitfb_readw(unsigned int offset)
+{
+ return fb_readw(hitfb_offset_to_addr(offset));
+}
+
+static void hitfb_writew(u16 value, unsigned int offset)
+{
+ fb_writew(value, hitfb_offset_to_addr(offset));
+}
+
static inline void hitfb_accel_wait(void)
{
- while (fb_readw(HD64461_GRCFGR) & HD64461_GRCFGR_ACCSTATUS) ;
+ while (hitfb_readw(HD64461_GRCFGR) & HD64461_GRCFGR_ACCSTATUS)
+ ;
}
static inline void hitfb_accel_start(int truecolor)
{
if (truecolor) {
- fb_writew(6, HD64461_GRCFGR);
+ hitfb_writew(6, HD64461_GRCFGR);
} else {
- fb_writew(7, HD64461_GRCFGR);
+ hitfb_writew(7, HD64461_GRCFGR);
}
}
@@ -63,11 +79,11 @@ static inline void hitfb_accel_set_dest(int truecolor, u16 dx, u16 dy,
if (truecolor)
saddr <<= 1;
- fb_writew(width-1, HD64461_BBTDWR);
- fb_writew(height-1, HD64461_BBTDHR);
+ hitfb_writew(width-1, HD64461_BBTDWR);
+ hitfb_writew(height-1, HD64461_BBTDHR);
- fb_writew(saddr & 0xffff, HD64461_BBTDSARL);
- fb_writew(saddr >> 16, HD64461_BBTDSARH);
+ hitfb_writew(saddr & 0xffff, HD64461_BBTDSARL);
+ hitfb_writew(saddr >> 16, HD64461_BBTDSARH);
}
@@ -80,7 +96,7 @@ static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx,
height--;
width--;
- fb_writew(rop, HD64461_BBTROPR);
+ hitfb_writew(rop, HD64461_BBTROPR);
if ((sy < dy) || ((sy == dy) && (sx <= dx))) {
saddr = WIDTH * (sy + height) + sx + width;
daddr = WIDTH * (dy + height) + dx + width;
@@ -91,32 +107,32 @@ static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx,
maddr =
(((width >> 4) + 1) * (height + 1) - 1) * 2;
- fb_writew((1 << 5) | 1, HD64461_BBTMDR);
+ hitfb_writew((1 << 5) | 1, HD64461_BBTMDR);
} else
- fb_writew(1, HD64461_BBTMDR);
+ hitfb_writew(1, HD64461_BBTMDR);
} else {
saddr = WIDTH * sy + sx;
daddr = WIDTH * dy + dx;
if (mask_addr) {
- fb_writew((1 << 5), HD64461_BBTMDR);
+ hitfb_writew((1 << 5), HD64461_BBTMDR);
} else {
- fb_writew(0, HD64461_BBTMDR);
+ hitfb_writew(0, HD64461_BBTMDR);
}
}
if (truecolor) {
saddr <<= 1;
daddr <<= 1;
}
- fb_writew(width, HD64461_BBTDWR);
- fb_writew(height, HD64461_BBTDHR);
- fb_writew(saddr & 0xffff, HD64461_BBTSSARL);
- fb_writew(saddr >> 16, HD64461_BBTSSARH);
- fb_writew(daddr & 0xffff, HD64461_BBTDSARL);
- fb_writew(daddr >> 16, HD64461_BBTDSARH);
+ hitfb_writew(width, HD64461_BBTDWR);
+ hitfb_writew(height, HD64461_BBTDHR);
+ hitfb_writew(saddr & 0xffff, HD64461_BBTSSARL);
+ hitfb_writew(saddr >> 16, HD64461_BBTSSARH);
+ hitfb_writew(daddr & 0xffff, HD64461_BBTDSARL);
+ hitfb_writew(daddr >> 16, HD64461_BBTDSARH);
if (mask_addr) {
maddr += mask_addr;
- fb_writew(maddr & 0xffff, HD64461_BBTMARL);
- fb_writew(maddr >> 16, HD64461_BBTMARH);
+ hitfb_writew(maddr & 0xffff, HD64461_BBTMARL);
+ hitfb_writew(maddr >> 16, HD64461_BBTMARH);
}
hitfb_accel_start(truecolor);
}
@@ -127,17 +143,17 @@ static void hitfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
cfb_fillrect(p, rect);
else {
hitfb_accel_wait();
- fb_writew(0x00f0, HD64461_BBTROPR);
- fb_writew(16, HD64461_BBTMDR);
+ hitfb_writew(0x00f0, HD64461_BBTROPR);
+ hitfb_writew(16, HD64461_BBTMDR);
if (p->var.bits_per_pixel == 16) {
- fb_writew(((u32 *) (p->pseudo_palette))[rect->color],
+ hitfb_writew(((u32 *) (p->pseudo_palette))[rect->color],
HD64461_GRSCR);
hitfb_accel_set_dest(1, rect->dx, rect->dy, rect->width,
rect->height);
hitfb_accel_start(1);
} else {
- fb_writew(rect->color, HD64461_GRSCR);
+ hitfb_writew(rect->color, HD64461_GRSCR);
hitfb_accel_set_dest(0, rect->dx, rect->dy, rect->width,
rect->height);
hitfb_accel_start(0);
@@ -162,43 +178,43 @@ static int hitfb_pan_display(struct fb_var_screeninfo *var,
if (xoffset != 0)
return -EINVAL;
- fb_writew((yoffset*info->fix.line_length)>>10, HD64461_LCDCBAR);
+ hitfb_writew((yoffset*info->fix.line_length)>>10, HD64461_LCDCBAR);
return 0;
}
-int hitfb_blank(int blank_mode, struct fb_info *info)
+static int hitfb_blank(int blank_mode, struct fb_info *info)
{
unsigned short v;
if (blank_mode) {
- v = fb_readw(HD64461_LDR1);
+ v = hitfb_readw(HD64461_LDR1);
v &= ~HD64461_LDR1_DON;
- fb_writew(v, HD64461_LDR1);
+ hitfb_writew(v, HD64461_LDR1);
- v = fb_readw(HD64461_LCDCCR);
+ v = hitfb_readw(HD64461_LCDCCR);
v |= HD64461_LCDCCR_MOFF;
- fb_writew(v, HD64461_LCDCCR);
+ hitfb_writew(v, HD64461_LCDCCR);
- v = fb_readw(HD64461_STBCR);
+ v = hitfb_readw(HD64461_STBCR);
v |= HD64461_STBCR_SLCDST;
- fb_writew(v, HD64461_STBCR);
+ hitfb_writew(v, HD64461_STBCR);
} else {
- v = fb_readw(HD64461_STBCR);
+ v = hitfb_readw(HD64461_STBCR);
v &= ~HD64461_STBCR_SLCDST;
- fb_writew(v, HD64461_STBCR);
+ hitfb_writew(v, HD64461_STBCR);
- v = fb_readw(HD64461_LCDCCR);
+ v = hitfb_readw(HD64461_LCDCCR);
v &= ~(HD64461_LCDCCR_MOFF | HD64461_LCDCCR_STREQ);
- fb_writew(v, HD64461_LCDCCR);
+ hitfb_writew(v, HD64461_LCDCCR);
do {
- v = fb_readw(HD64461_LCDCCR);
+ v = hitfb_readw(HD64461_LCDCCR);
} while(v&HD64461_LCDCCR_STBACK);
- v = fb_readw(HD64461_LDR1);
+ v = hitfb_readw(HD64461_LDR1);
v |= HD64461_LDR1_DON;
- fb_writew(v, HD64461_LDR1);
+ hitfb_writew(v, HD64461_LDR1);
}
return 0;
}
@@ -211,10 +227,10 @@ static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
switch (info->var.bits_per_pixel) {
case 8:
- fb_writew(regno << 8, HD64461_CPTWAR);
- fb_writew(red >> 10, HD64461_CPTWDR);
- fb_writew(green >> 10, HD64461_CPTWDR);
- fb_writew(blue >> 10, HD64461_CPTWDR);
+ hitfb_writew(regno << 8, HD64461_CPTWAR);
+ hitfb_writew(red >> 10, HD64461_CPTWDR);
+ hitfb_writew(green >> 10, HD64461_CPTWDR);
+ hitfb_writew(blue >> 10, HD64461_CPTWDR);
break;
case 16:
if (regno >= 16)
@@ -302,11 +318,11 @@ static int hitfb_set_par(struct fb_info *info)
break;
}
- fb_writew(info->fix.line_length, HD64461_LCDCLOR);
- ldr3 = fb_readw(HD64461_LDR3);
+ hitfb_writew(info->fix.line_length, HD64461_LCDCLOR);
+ ldr3 = hitfb_readw(HD64461_LDR3);
ldr3 &= ~15;
ldr3 |= (info->var.bits_per_pixel == 8) ? 4 : 8;
- fb_writew(ldr3, HD64461_LDR3);
+ hitfb_writew(ldr3, HD64461_LDR3);
return 0;
}
@@ -337,9 +353,9 @@ static int hitfb_probe(struct platform_device *dev)
hitfb_fix.smem_start = HD64461_IO_OFFSET(0x02000000);
hitfb_fix.smem_len = 512 * 1024;
- lcdclor = fb_readw(HD64461_LCDCLOR);
- ldvndr = fb_readw(HD64461_LDVNDR);
- ldr3 = fb_readw(HD64461_LDR3);
+ lcdclor = hitfb_readw(HD64461_LCDCLOR);
+ ldvndr = hitfb_readw(HD64461_LDVNDR);
+ ldr3 = hitfb_readw(HD64461_LDR3);
switch (ldr3 & 15) {
default:
@@ -392,7 +408,7 @@ static int hitfb_probe(struct platform_device *dev)
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
- info->screen_base = (void *)hitfb_fix.smem_start;
+ info->screen_base = (char __iomem *)(uintptr_t)hitfb_fix.smem_start;
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (unlikely(ret < 0))
@@ -428,10 +444,10 @@ static int hitfb_suspend(struct device *dev)
{
u16 v;
- hitfb_blank(1,0);
- v = fb_readw(HD64461_STBCR);
+ hitfb_blank(1, NULL);
+ v = hitfb_readw(HD64461_STBCR);
v |= HD64461_STBCR_SLCKE_IST;
- fb_writew(v, HD64461_STBCR);
+ hitfb_writew(v, HD64461_STBCR);
return 0;
}
@@ -440,13 +456,13 @@ static int hitfb_resume(struct device *dev)
{
u16 v;
- v = fb_readw(HD64461_STBCR);
+ v = hitfb_readw(HD64461_STBCR);
v &= ~HD64461_STBCR_SLCKE_OST;
msleep(100);
- v = fb_readw(HD64461_STBCR);
+ v = hitfb_readw(HD64461_STBCR);
v &= ~HD64461_STBCR_SLCKE_IST;
- fb_writew(v, HD64461_STBCR);
- hitfb_blank(0,0);
+ hitfb_writew(v, HD64461_STBCR);
+ hitfb_blank(0, NULL);
return 0;
}
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c
index 34781dec3856..1ae35ab62b29 100644
--- a/drivers/video/fbdev/hyperv_fb.c
+++ b/drivers/video/fbdev/hyperv_fb.c
@@ -1073,7 +1073,7 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
info->screen_size = dio_fb_size;
getmem_done:
- aperture_remove_conflicting_devices(base, size, false, KBUILD_MODNAME);
+ aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME);
if (gen2vm) {
/* framebuffer is reallocated, clear screen_info to avoid misuse from kexec */
diff --git a/drivers/video/fbdev/kyro/fbdev.c b/drivers/video/fbdev/kyro/fbdev.c
index 0596573ef140..3f277bdb3a32 100644
--- a/drivers/video/fbdev/kyro/fbdev.c
+++ b/drivers/video/fbdev/kyro/fbdev.c
@@ -737,7 +737,7 @@ static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
info->var.bits_per_pixel);
size *= info->var.yres_virtual;
- fb_memset(info->screen_base, 0, size);
+ fb_memset_io(info->screen_base, 0, size);
if (register_framebuffer(info) < 0)
goto out_unmap;
diff --git a/drivers/video/fbdev/matrox/matroxfb_accel.c b/drivers/video/fbdev/matrox/matroxfb_accel.c
index 9cb0685feddd..ce51227798a1 100644
--- a/drivers/video/fbdev/matrox/matroxfb_accel.c
+++ b/drivers/video/fbdev/matrox/matroxfb_accel.c
@@ -88,7 +88,7 @@
static inline void matrox_cfb4_pal(u_int32_t* pal) {
unsigned int i;
-
+
for (i = 0; i < 16; i++) {
pal[i] = i * 0x11111111U;
}
@@ -96,7 +96,7 @@ static inline void matrox_cfb4_pal(u_int32_t* pal) {
static inline void matrox_cfb8_pal(u_int32_t* pal) {
unsigned int i;
-
+
for (i = 0; i < 16; i++) {
pal[i] = i * 0x01010101U;
}
@@ -482,7 +482,7 @@ static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx,
/* Tell... well, why bother... */
while (height--) {
size_t i;
-
+
for (i = 0; i < step; i += 4) {
/* Hope that there are at least three readable bytes beyond the end of bitmap */
fb_writel(get_unaligned((u_int32_t*)(chardata + i)),mmio.vaddr);
diff --git a/drivers/video/fbdev/matrox/matroxfb_base.h b/drivers/video/fbdev/matrox/matroxfb_base.h
index 958be6805f87..c93c69bbcd57 100644
--- a/drivers/video/fbdev/matrox/matroxfb_base.h
+++ b/drivers/video/fbdev/matrox/matroxfb_base.h
@@ -301,9 +301,9 @@ struct matrox_altout {
int (*verifymode)(void* altout_dev, u_int32_t mode);
int (*getqueryctrl)(void* altout_dev,
struct v4l2_queryctrl* ctrl);
- int (*getctrl)(void* altout_dev,
+ int (*getctrl)(void *altout_dev,
struct v4l2_control* ctrl);
- int (*setctrl)(void* altout_dev,
+ int (*setctrl)(void *altout_dev,
struct v4l2_control* ctrl);
};
diff --git a/drivers/video/fbdev/metronomefb.c b/drivers/video/fbdev/metronomefb.c
index bbdbf463f0c8..ebdb4949c4ac 100644
--- a/drivers/video/fbdev/metronomefb.c
+++ b/drivers/video/fbdev/metronomefb.c
@@ -438,7 +438,7 @@ static void metronomefb_dpy_update(struct metronomefb_par *par)
{
int fbsize;
u16 cksum;
- unsigned char *buf = (unsigned char __force *)par->info->screen_base;
+ unsigned char *buf = par->info->screen_buffer;
fbsize = par->info->fix.smem_len;
/* copy from vm to metromem */
@@ -453,7 +453,7 @@ static u16 metronomefb_dpy_update_page(struct metronomefb_par *par, int index)
{
int i;
u16 csum = 0;
- u16 *buf = (u16 __force *)(par->info->screen_base + index);
+ u16 *buf = (u16 *)(par->info->screen_buffer + index);
u16 *img = (u16 *)(par->metromem_img + index);
/* swizzle from vm to metromem and recalc cksum at the same time*/
@@ -523,8 +523,8 @@ static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf,
int err = 0;
unsigned long total_size;
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
+ if (!info->screen_buffer)
+ return -ENODEV;
total_size = info->fix.smem_len;
@@ -543,7 +543,7 @@ static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf,
count = total_size - p;
}
- dst = (void __force *)(info->screen_base + p);
+ dst = info->screen_buffer + p;
if (copy_from_user(dst, buf, count))
err = -EFAULT;
@@ -599,7 +599,7 @@ static int metronomefb_probe(struct platform_device *dev)
goto err;
/* we have two blocks of memory.
- info->screen_base which is vm, and is the fb used by apps.
+ info->screen_buffer which is vm, and is the fb used by apps.
par->metromem which is physically contiguous memory and
contains the display controller commands, waveform,
processed image data and padding. this is the data pulled
@@ -634,7 +634,7 @@ static int metronomefb_probe(struct platform_device *dev)
if (!videomemory)
goto err_fb_rel;
- info->screen_base = (char __force __iomem *)videomemory;
+ info->screen_buffer = videomemory;
info->fbops = &metronomefb_ops;
metronomefb_fix.line_length = fw;
@@ -756,7 +756,7 @@ static void metronomefb_remove(struct platform_device *dev)
fb_dealloc_cmap(&info->cmap);
par->board->cleanup(par);
vfree(par->csum_table);
- vfree((void __force *)info->screen_base);
+ vfree(info->screen_buffer);
module_put(par->board->owner);
dev_dbg(&dev->dev, "calling release\n");
framebuffer_release(info);
@@ -778,3 +778,5 @@ MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size");
MODULE_DESCRIPTION("fbdev driver for Metronome controller");
MODULE_AUTHOR("Jaya Kumar");
MODULE_LICENSE("GPL");
+
+MODULE_FIRMWARE("metronome.wbf");
diff --git a/drivers/video/fbdev/omap/lcd_mipid.c b/drivers/video/fbdev/omap/lcd_mipid.c
index 03cff39d392d..a0fc4570403b 100644
--- a/drivers/video/fbdev/omap/lcd_mipid.c
+++ b/drivers/video/fbdev/omap/lcd_mipid.c
@@ -7,6 +7,7 @@
*/
#include <linux/device.h>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/spi/spi.h>
@@ -41,6 +42,7 @@ struct mipid_device {
when we can issue the
next sleep in/out command */
unsigned long hw_guard_wait; /* max guard time in jiffies */
+ struct gpio_desc *reset;
struct omapfb_device *fbdev;
struct spi_device *spi;
@@ -556,6 +558,12 @@ static int mipid_spi_probe(struct spi_device *spi)
return -ENOMEM;
}
+ /* This will de-assert RESET if active */
+ md->reset = gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(md->reset))
+ return dev_err_probe(&spi->dev, PTR_ERR(md->reset),
+ "no reset GPIO line\n");
+
spi->mode = SPI_MODE_0;
md->spi = spi;
dev_set_drvdata(&spi->dev, md);
@@ -563,17 +571,23 @@ static int mipid_spi_probe(struct spi_device *spi)
r = mipid_detect(md);
if (r < 0)
- return r;
+ goto free_md;
omapfb_register_panel(&md->panel);
return 0;
+
+free_md:
+ kfree(md);
+ return r;
}
static void mipid_spi_remove(struct spi_device *spi)
{
struct mipid_device *md = dev_get_drvdata(&spi->dev);
+ /* Asserts RESET */
+ gpiod_set_value(md->reset, 1);
mipid_disable(&md->panel);
kfree(md);
}
diff --git a/drivers/video/fbdev/ps3fb.c b/drivers/video/fbdev/ps3fb.c
index 98aaa330a193..d4abcf8aff75 100644
--- a/drivers/video/fbdev/ps3fb.c
+++ b/drivers/video/fbdev/ps3fb.c
@@ -650,7 +650,7 @@ static int ps3fb_set_par(struct fb_info *info)
}
/* Clear XDR frame buffer memory */
- memset((void __force *)info->screen_base, 0, info->fix.smem_len);
+ memset(info->screen_buffer, 0, info->fix.smem_len);
/* Clear DDR frame buffer memory */
lines = vmode->yres * par->num_frames;
@@ -1140,7 +1140,7 @@ static int ps3fb_probe(struct ps3_system_bus_device *dev)
* memory
*/
fb_start = ps3fb_videomemory.address + GPU_FB_START;
- info->screen_base = (char __force __iomem *)fb_start;
+ info->screen_buffer = fb_start;
info->fix.smem_start = __pa(fb_start);
info->fix.smem_len = ps3fb_videomemory.size - GPU_FB_START;
diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c
index 6888127a5eb8..c692cd597ce3 100644
--- a/drivers/video/fbdev/pvr2fb.c
+++ b/drivers/video/fbdev/pvr2fb.c
@@ -647,6 +647,9 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
struct page **pages;
int ret, i;
+ if (!info->screen_base)
+ return -ENODEV;
+
nr_pages = (count + PAGE_SIZE - 1) >> PAGE_SHIFT;
pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL);
@@ -798,7 +801,7 @@ static int __maybe_unused pvr2fb_common_init(void)
goto out_err;
}
- fb_memset(fb_info->screen_base, 0, pvr2_fix.smem_len);
+ fb_memset_io(fb_info->screen_base, 0, pvr2_fix.smem_len);
pvr2_fix.ypanstep = nopan ? 0 : 1;
pvr2_fix.ywrapstep = nowrap ? 0 : 1;
diff --git a/drivers/video/fbdev/sh7760fb.c b/drivers/video/fbdev/sh7760fb.c
index 768011bdb430..98c5227098a8 100644
--- a/drivers/video/fbdev/sh7760fb.c
+++ b/drivers/video/fbdev/sh7760fb.c
@@ -136,11 +136,13 @@ static int sh7760fb_get_color_info(struct device *dev,
break;
case LDDFR_4BPP_MONO:
lgray = 1;
+ fallthrough;
case LDDFR_4BPP:
lbpp = 4;
break;
case LDDFR_6BPP_MONO:
lgray = 1;
+ fallthrough;
case LDDFR_8BPP:
lbpp = 8;
break;
diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c
index 093f035d1246..0adb2ba965e7 100644
--- a/drivers/video/fbdev/sh_mobile_lcdcfb.c
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c
@@ -824,7 +824,7 @@ static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24;
break;
case V4L2_PIX_FMT_BGR32:
- format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
+ format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDBBSIFR_RPKF_ARGB32;
break;
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV21:
diff --git a/drivers/video/fbdev/sm712fb.c b/drivers/video/fbdev/sm712fb.c
index b528776c7612..b7ad3c644e13 100644
--- a/drivers/video/fbdev/sm712fb.c
+++ b/drivers/video/fbdev/sm712fb.c
@@ -1028,12 +1028,9 @@ static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
int c, i, cnt = 0, err = 0;
unsigned long total_size;
- if (!info || !info->screen_base)
+ if (!info->screen_base)
return -ENODEV;
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
-
total_size = info->screen_size;
if (total_size == 0)
@@ -1094,12 +1091,9 @@ static ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
int c, i, cnt = 0, err = 0;
unsigned long total_size;
- if (!info || !info->screen_base)
+ if (!info->screen_base)
return -ENODEV;
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
-
total_size = info->screen_size;
if (total_size == 0)
diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c
index 2ad6e98ce10d..17cec62cc65d 100644
--- a/drivers/video/fbdev/smscufx.c
+++ b/drivers/video/fbdev/smscufx.c
@@ -1150,7 +1150,7 @@ static void ufx_free_framebuffer(struct ufx_data *dev)
fb_dealloc_cmap(&info->cmap);
if (info->monspecs.modedb)
fb_destroy_modedb(info->monspecs.modedb);
- vfree(info->screen_base);
+ vfree(info->screen_buffer);
fb_destroy_modelist(&info->modelist);
@@ -1257,7 +1257,7 @@ static int ufx_ops_set_par(struct fb_info *info)
if ((result == 0) && (dev->fb_count == 0)) {
/* paint greenscreen */
- pix_framebuffer = (u16 *) info->screen_base;
+ pix_framebuffer = (u16 *)info->screen_buffer;
for (i = 0; i < info->fix.smem_len / 2; i++)
pix_framebuffer[i] = 0x37e6;
@@ -1303,7 +1303,7 @@ static int ufx_realloc_framebuffer(struct ufx_data *dev, struct fb_info *info)
{
int old_len = info->fix.smem_len;
int new_len;
- unsigned char *old_fb = info->screen_base;
+ unsigned char *old_fb = info->screen_buffer;
unsigned char *new_fb;
pr_debug("Reallocating framebuffer. Addresses will change!");
@@ -1318,12 +1318,12 @@ static int ufx_realloc_framebuffer(struct ufx_data *dev, struct fb_info *info)
if (!new_fb)
return -ENOMEM;
- if (info->screen_base) {
+ if (info->screen_buffer) {
memcpy(new_fb, old_fb, old_len);
- vfree(info->screen_base);
+ vfree(info->screen_buffer);
}
- info->screen_base = new_fb;
+ info->screen_buffer = new_fb;
info->fix.smem_len = PAGE_ALIGN(new_len);
info->fix.smem_start = (unsigned long) new_fb;
info->flags = smscufx_info_flags;
@@ -1746,7 +1746,7 @@ reset_active:
atomic_set(&dev->usb_active, 0);
setup_modes:
fb_destroy_modedb(info->monspecs.modedb);
- vfree(info->screen_base);
+ vfree(info->screen_buffer);
fb_destroy_modelist(&info->modelist);
error:
fb_dealloc_cmap(&info->cmap);
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 132d1a205011..11c373798279 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -301,6 +301,9 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
void *dst;
int ret;
+ if (!info->screen_buffer)
+ return -ENODEV;
+
total_size = info->fix.smem_len;
if (p > total_size)
diff --git a/drivers/video/fbdev/sstfb.c b/drivers/video/fbdev/sstfb.c
index da296b2ab54a..582324f5d869 100644
--- a/drivers/video/fbdev/sstfb.c
+++ b/drivers/video/fbdev/sstfb.c
@@ -335,7 +335,7 @@ static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t)
static void sstfb_clear_screen(struct fb_info *info)
{
/* clear screen */
- fb_memset(info->screen_base, 0, info->fix.smem_len);
+ fb_memset_io(info->screen_base, 0, info->fix.smem_len);
}
diff --git a/drivers/video/fbdev/sticore.h b/drivers/video/fbdev/sticore.h
deleted file mode 100644
index 0ebdd28a0b81..000000000000
--- a/drivers/video/fbdev/sticore.h
+++ /dev/null
@@ -1,404 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef STICORE_H
-#define STICORE_H
-
-/* generic STI structures & functions */
-
-#define MAX_STI_ROMS 4 /* max no. of ROMs which this driver handles */
-
-#define STI_REGION_MAX 8 /* hardcoded STI constants */
-#define STI_DEV_NAME_LENGTH 32
-#define STI_MONITOR_MAX 256
-
-#define STI_FONT_HPROMAN8 1
-#define STI_FONT_KANA8 2
-
-#define ALT_CODE_TYPE_UNKNOWN 0x00 /* alt code type values */
-#define ALT_CODE_TYPE_PA_RISC_64 0x01
-
-/* The latency of the STI functions cannot really be reduced by setting
- * this to 0; STI doesn't seem to be designed to allow calling a different
- * function (or the same function with different arguments) after a
- * function exited with 1 as return value.
- *
- * As all of the functions below could be called from interrupt context,
- * we have to spin_lock_irqsave around the do { ret = bla(); } while(ret==1)
- * block. Really bad latency there.
- *
- * Probably the best solution to all this is have the generic code manage
- * the screen buffer and a kernel thread to call STI occasionally.
- *
- * Luckily, the frame buffer guys have the same problem so we can just wait
- * for them to fix it and steal their solution. prumpf
- */
-
-#include <asm/io.h>
-
-#define STI_WAIT 1
-
-#define STI_PTR(p) ( virt_to_phys(p) )
-#define PTR_STI(p) ( phys_to_virt((unsigned long)p) )
-
-#define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x)
-#define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y)
-
-/* sti_font_xy() use the native font ROM ! */
-#define sti_font_x(sti) (PTR_STI(sti->font)->width)
-#define sti_font_y(sti) (PTR_STI(sti->font)->height)
-
-#ifdef CONFIG_64BIT
-#define STI_LOWMEM (GFP_KERNEL | GFP_DMA)
-#else
-#define STI_LOWMEM (GFP_KERNEL)
-#endif
-
-
-/* STI function configuration structs */
-
-typedef union region {
- struct {
- u32 offset : 14; /* offset in 4kbyte page */
- u32 sys_only : 1; /* don't map to user space */
- u32 cache : 1; /* map to data cache */
- u32 btlb : 1; /* map to block tlb */
- u32 last : 1; /* last region in list */
- u32 length : 14; /* length in 4kbyte page */
- } region_desc;
-
- u32 region; /* complete region value */
-} region_t;
-
-#define REGION_OFFSET_TO_PHYS( rt, hpa ) \
- (((rt).region_desc.offset << 12) + (hpa))
-
-struct sti_glob_cfg_ext {
- u8 curr_mon; /* current monitor configured */
- u8 friendly_boot; /* in friendly boot mode */
- s16 power; /* power calculation (in Watts) */
- s32 freq_ref; /* frequency reference */
- u32 sti_mem_addr; /* pointer to global sti memory (size=sti_mem_request) */
- u32 future_ptr; /* pointer to future data */
-};
-
-struct sti_glob_cfg {
- s32 text_planes; /* number of planes used for text */
- s16 onscreen_x; /* screen width in pixels */
- s16 onscreen_y; /* screen height in pixels */
- s16 offscreen_x; /* offset width in pixels */
- s16 offscreen_y; /* offset height in pixels */
- s16 total_x; /* frame buffer width in pixels */
- s16 total_y; /* frame buffer height in pixels */
- u32 region_ptrs[STI_REGION_MAX]; /* region pointers */
- s32 reent_lvl; /* storage for reentry level value */
- u32 save_addr; /* where to save or restore reentrant state */
- u32 ext_ptr; /* pointer to extended glob_cfg data structure */
-};
-
-
-/* STI init function structs */
-
-struct sti_init_flags {
- u32 wait : 1; /* should routine idle wait or not */
- u32 reset : 1; /* hard reset the device? */
- u32 text : 1; /* turn on text display planes? */
- u32 nontext : 1; /* turn on non-text display planes? */
- u32 clear : 1; /* clear text display planes? */
- u32 cmap_blk : 1; /* non-text planes cmap black? */
- u32 enable_be_timer : 1; /* enable bus error timer */
- u32 enable_be_int : 1; /* enable bus error timer interrupt */
- u32 no_chg_tx : 1; /* don't change text settings */
- u32 no_chg_ntx : 1; /* don't change non-text settings */
- u32 no_chg_bet : 1; /* don't change berr timer settings */
- u32 no_chg_bei : 1; /* don't change berr int settings */
- u32 init_cmap_tx : 1; /* initialize cmap for text planes */
- u32 cmt_chg : 1; /* change current monitor type */
- u32 retain_ie : 1; /* don't allow reset to clear int enables */
- u32 caller_bootrom : 1; /* set only by bootrom for each call */
- u32 caller_kernel : 1; /* set only by kernel for each call */
- u32 caller_other : 1; /* set only by non-[BR/K] caller */
- u32 pad : 14; /* pad to word boundary */
- u32 future_ptr; /* pointer to future data */
-};
-
-struct sti_init_inptr_ext {
- u8 config_mon_type; /* configure to monitor type */
- u8 pad[1]; /* pad to word boundary */
- u16 inflight_data; /* inflight data possible on PCI */
- u32 future_ptr; /* pointer to future data */
-};
-
-struct sti_init_inptr {
- s32 text_planes; /* number of planes to use for text */
- u32 ext_ptr; /* pointer to extended init_graph inptr data structure*/
-};
-
-
-struct sti_init_outptr {
- s32 errno; /* error number on failure */
- s32 text_planes; /* number of planes used for text */
- u32 future_ptr; /* pointer to future data */
-};
-
-
-
-/* STI configuration function structs */
-
-struct sti_conf_flags {
- u32 wait : 1; /* should routine idle wait or not */
- u32 pad : 31; /* pad to word boundary */
- u32 future_ptr; /* pointer to future data */
-};
-
-struct sti_conf_inptr {
- u32 future_ptr; /* pointer to future data */
-};
-
-struct sti_conf_outptr_ext {
- u32 crt_config[3]; /* hardware specific X11/OGL information */
- u32 crt_hdw[3];
- u32 future_ptr;
-};
-
-struct sti_conf_outptr {
- s32 errno; /* error number on failure */
- s16 onscreen_x; /* screen width in pixels */
- s16 onscreen_y; /* screen height in pixels */
- s16 offscreen_x; /* offscreen width in pixels */
- s16 offscreen_y; /* offscreen height in pixels */
- s16 total_x; /* frame buffer width in pixels */
- s16 total_y; /* frame buffer height in pixels */
- s32 bits_per_pixel; /* bits/pixel device has configured */
- s32 bits_used; /* bits which can be accessed */
- s32 planes; /* number of fb planes in system */
- u8 dev_name[STI_DEV_NAME_LENGTH]; /* null terminated product name */
- u32 attributes; /* flags denoting attributes */
- u32 ext_ptr; /* pointer to future data */
-};
-
-struct sti_rom {
- u8 type[4];
- u8 res004;
- u8 num_mons;
- u8 revno[2];
- u32 graphics_id[2];
-
- u32 font_start;
- u32 statesize;
- u32 last_addr;
- u32 region_list;
-
- u16 reentsize;
- u16 maxtime;
- u32 mon_tbl_addr;
- u32 user_data_addr;
- u32 sti_mem_req;
-
- u32 user_data_size;
- u16 power;
- u8 bus_support;
- u8 ext_bus_support;
- u8 alt_code_type;
- u8 ext_dd_struct[3];
- u32 cfb_addr;
-
- u32 init_graph;
- u32 state_mgmt;
- u32 font_unpmv;
- u32 block_move;
- u32 self_test;
- u32 excep_hdlr;
- u32 inq_conf;
- u32 set_cm_entry;
- u32 dma_ctrl;
- u8 res040[7 * 4];
-
- u32 init_graph_addr;
- u32 state_mgmt_addr;
- u32 font_unp_addr;
- u32 block_move_addr;
- u32 self_test_addr;
- u32 excep_hdlr_addr;
- u32 inq_conf_addr;
- u32 set_cm_entry_addr;
- u32 image_unpack_addr;
- u32 pa_risx_addrs[7];
-};
-
-struct sti_rom_font {
- u16 first_char;
- u16 last_char;
- u8 width;
- u8 height;
- u8 font_type; /* language type */
- u8 bytes_per_char;
- u32 next_font;
- u8 underline_height;
- u8 underline_pos;
- u8 res008[2];
-};
-
-/* sticore internal font handling */
-
-struct sti_cooked_font {
- struct sti_rom_font *raw; /* native ptr for STI functions */
- void *raw_ptr; /* kmalloc'ed font data */
- struct sti_cooked_font *next_font;
- int height, width;
- int refcount;
- u32 crc;
-};
-
-struct sti_cooked_rom {
- struct sti_rom *raw;
- struct sti_cooked_font *font_start;
-};
-
-/* STI font printing function structs */
-
-struct sti_font_inptr {
- u32 font_start_addr; /* address of font start */
- s16 index; /* index into font table of character */
- u8 fg_color; /* foreground color of character */
- u8 bg_color; /* background color of character */
- s16 dest_x; /* X location of character upper left */
- s16 dest_y; /* Y location of character upper left */
- u32 future_ptr; /* pointer to future data */
-};
-
-struct sti_font_flags {
- u32 wait : 1; /* should routine idle wait or not */
- u32 non_text : 1; /* font unpack/move in non_text planes =1, text =0 */
- u32 pad : 30; /* pad to word boundary */
- u32 future_ptr; /* pointer to future data */
-};
-
-struct sti_font_outptr {
- s32 errno; /* error number on failure */
- u32 future_ptr; /* pointer to future data */
-};
-
-/* STI blockmove structs */
-
-struct sti_blkmv_flags {
- u32 wait : 1; /* should routine idle wait or not */
- u32 color : 1; /* change color during move? */
- u32 clear : 1; /* clear during move? */
- u32 non_text : 1; /* block move in non_text planes =1, text =0 */
- u32 pad : 28; /* pad to word boundary */
- u32 future_ptr; /* pointer to future data */
-};
-
-struct sti_blkmv_inptr {
- u8 fg_color; /* foreground color after move */
- u8 bg_color; /* background color after move */
- s16 src_x; /* source upper left pixel x location */
- s16 src_y; /* source upper left pixel y location */
- s16 dest_x; /* dest upper left pixel x location */
- s16 dest_y; /* dest upper left pixel y location */
- s16 width; /* block width in pixels */
- s16 height; /* block height in pixels */
- u32 future_ptr; /* pointer to future data */
-};
-
-struct sti_blkmv_outptr {
- s32 errno; /* error number on failure */
- u32 future_ptr; /* pointer to future data */
-};
-
-
-/* sti_all_data is an internal struct which needs to be allocated in
- * low memory (< 4GB) if STI is used with 32bit STI on a 64bit kernel */
-
-struct sti_all_data {
- struct sti_glob_cfg glob_cfg;
- struct sti_glob_cfg_ext glob_cfg_ext;
-
- struct sti_conf_inptr inq_inptr;
- struct sti_conf_outptr inq_outptr; /* configuration */
- struct sti_conf_outptr_ext inq_outptr_ext;
-
- struct sti_init_inptr_ext init_inptr_ext;
- struct sti_init_inptr init_inptr;
- struct sti_init_outptr init_outptr;
-
- struct sti_blkmv_inptr blkmv_inptr;
- struct sti_blkmv_outptr blkmv_outptr;
-
- struct sti_font_inptr font_inptr;
- struct sti_font_outptr font_outptr;
-
- /* leave as last entries */
- unsigned long save_addr[1024 / sizeof(unsigned long)];
- /* min 256 bytes which is STI default, max sti->sti_mem_request */
- unsigned long sti_mem_addr[256 / sizeof(unsigned long)];
- /* do not add something below here ! */
-};
-
-/* internal generic STI struct */
-
-struct sti_struct {
- spinlock_t lock;
-
- /* char **mon_strings; */
- int sti_mem_request;
- u32 graphics_id[2];
-
- struct sti_cooked_rom *rom;
-
- unsigned long font_unpmv;
- unsigned long block_move;
- unsigned long init_graph;
- unsigned long inq_conf;
-
- /* all following fields are initialized by the generic routines */
- int text_planes;
- region_t regions[STI_REGION_MAX];
- unsigned long regions_phys[STI_REGION_MAX];
-
- struct sti_glob_cfg *glob_cfg; /* points into sti_all_data */
-
- int wordmode;
- struct sti_cooked_font *font; /* ptr to selected font (cooked) */
-
- struct pci_dev *pd;
-
- /* PCI data structures (pg. 17ff from sti.pdf) */
- u8 rm_entry[16]; /* pci region mapper array == pci config space offset */
-
- /* pointer to the fb_info where this STI device is used */
- struct fb_info *info;
-
- /* pointer to all internal data */
- struct sti_all_data *sti_data;
-
- /* pa_path of this device */
- char pa_path[24];
-};
-
-
-/* sticore interface functions */
-
-struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */
-void sti_font_convert_bytemode(struct sti_struct *sti, struct sti_cooked_font *f);
-
-
-/* sticore main function to call STI firmware */
-
-int sti_call(const struct sti_struct *sti, unsigned long func,
- const void *flags, void *inptr, void *outptr,
- struct sti_glob_cfg *glob_cfg);
-
-
-/* functions to call the STI ROM directly */
-
-void sti_putc(struct sti_struct *sti, int c, int y, int x,
- struct sti_cooked_font *font);
-void sti_set(struct sti_struct *sti, int src_y, int src_x,
- int height, int width, u8 color);
-void sti_clear(struct sti_struct *sti, int src_y, int src_x,
- int height, int width, int c, struct sti_cooked_font *font);
-void sti_bmove(struct sti_struct *sti, int src_y, int src_x,
- int dst_y, int dst_x, int height, int width,
- struct sti_cooked_font *font);
-
-#endif /* STICORE_H */
diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c
index 686a234f3899..c746deb79afc 100644
--- a/drivers/video/fbdev/stifb.c
+++ b/drivers/video/fbdev/stifb.c
@@ -69,11 +69,11 @@
#include <asm/grfioctl.h> /* for HP-UX compatibility */
#include <linux/uaccess.h>
-#include "sticore.h"
+#include <video/sticore.h>
-/* REGION_BASE(fb_info, index) returns the virtual address for region <index> */
+/* REGION_BASE(fb_info, index) returns the physical address for region <index> */
#define REGION_BASE(fb_info, index) \
- F_EXTEND(fb_info->sti->glob_cfg->region_ptrs[index])
+ F_EXTEND(fb_info->sti->regions_phys[index])
#define NGLEDEVDEPROM_CRT_REGION 1
@@ -527,8 +527,8 @@ rattlerSetupPlanes(struct stifb_info *fb)
fb->id = saved_id;
for (y = 0; y < fb->info.var.yres; ++y)
- fb_memset(fb->info.screen_base + y * fb->info.fix.line_length,
- 0xff, fb->info.var.xres * fb->info.var.bits_per_pixel/8);
+ fb_memset_io(fb->info.screen_base + y * fb->info.fix.line_length,
+ 0xff, fb->info.var.xres * fb->info.var.bits_per_pixel/8);
CRX24_SET_OVLY_MASK(fb);
SETUP_FB(fb);
diff --git a/drivers/video/fbdev/tdfxfb.c b/drivers/video/fbdev/tdfxfb.c
index d17e5e1472aa..cdf8e9fe9948 100644
--- a/drivers/video/fbdev/tdfxfb.c
+++ b/drivers/video/fbdev/tdfxfb.c
@@ -1116,7 +1116,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
u8 *mask = (u8 *)cursor->mask;
int i;
- fb_memset(cursorbase, 0, 1024);
+ fb_memset_io(cursorbase, 0, 1024);
for (i = 0; i < cursor->image.height; i++) {
int h = 0;
diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c
index dabc30a09f96..a4a21b4ac28c 100644
--- a/drivers/video/fbdev/udlfb.c
+++ b/drivers/video/fbdev/udlfb.c
@@ -1008,7 +1008,7 @@ static void dlfb_ops_destroy(struct fb_info *info)
fb_dealloc_cmap(&info->cmap);
if (info->monspecs.modedb)
fb_destroy_modedb(info->monspecs.modedb);
- vfree(info->screen_base);
+ vfree(info->screen_buffer);
fb_destroy_modelist(&info->modelist);
@@ -1122,7 +1122,7 @@ static int dlfb_ops_set_par(struct fb_info *info)
/* paint greenscreen */
- pix_framebuffer = (u16 *) info->screen_base;
+ pix_framebuffer = (u16 *)info->screen_buffer;
for (i = 0; i < info->fix.smem_len / 2; i++)
pix_framebuffer[i] = 0x37e6;
}
@@ -1221,7 +1221,7 @@ static void dlfb_deferred_vfree(struct dlfb_data *dlfb, void *mem)
static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info, u32 new_len)
{
u32 old_len = info->fix.smem_len;
- const void *old_fb = (const void __force *)info->screen_base;
+ const void *old_fb = info->screen_buffer;
unsigned char *new_fb;
unsigned char *new_back = NULL;
@@ -1238,12 +1238,12 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info
}
memset(new_fb, 0xff, new_len);
- if (info->screen_base) {
+ if (info->screen_buffer) {
memcpy(new_fb, old_fb, old_len);
- dlfb_deferred_vfree(dlfb, (void __force *)info->screen_base);
+ dlfb_deferred_vfree(dlfb, info->screen_buffer);
}
- info->screen_base = (char __iomem *)new_fb;
+ info->screen_buffer = new_fb;
info->fix.smem_len = new_len;
info->fix.smem_start = (unsigned long) new_fb;
info->flags = udlfb_info_flags;
diff --git a/drivers/video/fbdev/vfb.c b/drivers/video/fbdev/vfb.c
index 6f1990969361..cf3c72754ce7 100644
--- a/drivers/video/fbdev/vfb.c
+++ b/drivers/video/fbdev/vfb.c
@@ -440,7 +440,7 @@ static int vfb_probe(struct platform_device *dev)
if (!info)
goto err;
- info->screen_base = (char __iomem *)videomemory;
+ info->screen_buffer = videomemory;
info->fbops = &vfb_ops;
if (!fb_find_mode(&info->var, info, mode_option,
diff --git a/drivers/video/fbdev/via/via-core.c b/drivers/video/fbdev/via/via-core.c
index 2c1803eb196f..908524a74a38 100644
--- a/drivers/video/fbdev/via/via-core.c
+++ b/drivers/video/fbdev/via/via-core.c
@@ -11,7 +11,7 @@
#include <linux/aperture.h>
#include <linux/via-core.h>
#include <linux/via_i2c.h>
-#include <linux/via-gpio.h>
+#include "via-gpio.h"
#include "global.h"
#include <linux/module.h>
diff --git a/drivers/video/fbdev/via/via-gpio.c b/drivers/video/fbdev/via/via-gpio.c
index f1b670397c02..2719943c06f4 100644
--- a/drivers/video/fbdev/via/via-gpio.c
+++ b/drivers/video/fbdev/via/via-gpio.c
@@ -7,10 +7,11 @@
#include <linux/spinlock.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
#include <linux/platform_device.h>
#include <linux/via-core.h>
-#include <linux/via-gpio.h>
#include <linux/export.h>
+#include "via-gpio.h"
/*
* The ports we know about. Note that the port-25 gpios are not
@@ -189,19 +190,14 @@ static struct viafb_pm_hooks viafb_gpio_pm_hooks = {
};
#endif /* CONFIG_PM */
-/*
- * Look up a specific gpio and return the number it was assigned.
- */
-int viafb_gpio_lookup(const char *name)
-{
- int i;
-
- for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i++)
- if (!strcmp(name, viafb_gpio_config.active_gpios[i]->vg_name))
- return viafb_gpio_config.gpio_chip.base + i;
- return -1;
-}
-EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
+static struct gpiod_lookup_table viafb_gpio_table = {
+ .dev_id = "viafb-camera",
+ .table = {
+ GPIO_LOOKUP("via-gpio", 2, "VGPIO2", GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP("via-gpio", 3, "VGPIO3", GPIO_ACTIVE_HIGH),
+ { }
+ },
+};
/*
* Platform device stuff.
@@ -249,12 +245,16 @@ static int viafb_gpio_probe(struct platform_device *platdev)
* Get registered.
*/
viafb_gpio_config.gpio_chip.base = -1; /* Dynamic */
+ viafb_gpio_config.gpio_chip.label = "via-gpio";
ret = gpiochip_add_data(&viafb_gpio_config.gpio_chip,
&viafb_gpio_config);
if (ret) {
printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret);
viafb_gpio_config.gpio_chip.ngpio = 0;
}
+
+ gpiod_add_lookup_table(&viafb_gpio_table);
+
#ifdef CONFIG_PM
viafb_pm_register(&viafb_gpio_pm_hooks);
#endif
diff --git a/drivers/video/fbdev/via/via-gpio.h b/drivers/video/fbdev/via/via-gpio.h
new file mode 100644
index 000000000000..2ffedf282f7e
--- /dev/null
+++ b/drivers/video/fbdev/via/via-gpio.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Support for viafb GPIO ports.
+ *
+ * Copyright 2009 Jonathan Corbet <corbet@lwn.net>
+ */
+
+#ifndef __VIA_GPIO_H__
+#define __VIA_GPIO_H__
+
+extern int viafb_gpio_init(void);
+extern void viafb_gpio_exit(void);
+#endif
diff --git a/drivers/video/fbdev/wmt_ge_rops.c b/drivers/video/fbdev/wmt_ge_rops.c
index 3ed143457d22..b70961901683 100644
--- a/drivers/video/fbdev/wmt_ge_rops.c
+++ b/drivers/video/fbdev/wmt_ge_rops.c
@@ -9,7 +9,9 @@
#include <linux/module.h>
#include <linux/fb.h>
+#include <linux/io.h>
#include <linux/platform_device.h>
+
#include "core/fb_draw.h"
#include "wmt_ge_rops.h"
diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c
index d7f3e6281ce4..9b2a786621a6 100644
--- a/drivers/video/fbdev/xen-fbfront.c
+++ b/drivers/video/fbdev/xen-fbfront.c
@@ -429,7 +429,7 @@ static int xenfb_probe(struct xenbus_device *dev,
fb_info->pseudo_palette = fb_info->par;
fb_info->par = info;
- fb_info->screen_base = info->fb;
+ fb_info->screen_buffer = info->fb;
fb_info->fbops = &xenfb_fb_ops;
fb_info->var.xres_virtual = fb_info->var.xres = video[KPARAM_WIDTH];
diff --git a/drivers/video/console/sticore.c b/drivers/video/sticore.c
index db568f67e4dc..c3765ad6eedf 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/sticore.c
@@ -4,14 +4,14 @@
* core code for console driver using HP's STI firmware
*
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- * Copyright (C) 2001-2020 Helge Deller <deller@gmx.de>
+ * Copyright (C) 2001-2023 Helge Deller <deller@gmx.de>
* Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
- *
+ *
* TODO:
* - call STI in virtual mode rather than in real mode
- * - screen blanking with state_mgmt() in text mode STI ?
+ * - screen blanking with state_mgmt() in text mode STI ?
* - try to make it work on m68k hp workstations ;)
- *
+ *
*/
#define pr_fmt(fmt) "%s: " fmt, KBUILD_MODNAME
@@ -30,9 +30,8 @@
#include <asm/pdc.h>
#include <asm/cacheflush.h>
#include <asm/grfioctl.h>
-#include <asm/fb.h>
-#include "../fbdev/sticore.h"
+#include <video/sticore.h>
#define STI_DRIVERVERSION "Version 0.9c"
@@ -42,6 +41,26 @@ static struct sti_struct *default_sti __read_mostly;
static int num_sti_roms __read_mostly;
static struct sti_struct *sti_roms[MAX_STI_ROMS] __read_mostly;
+static void *store_sti_val(struct sti_struct *sti, void *ptr, unsigned long val)
+{
+ u32 *ptr32 = ptr;
+
+ if (IS_ENABLED(CONFIG_64BIT) && sti->do_call64) {
+ /* used for 64-bit STI ROM */
+ unsigned long *ptr64 = ptr;
+
+ ptr64 = PTR_ALIGN(ptr64, sizeof(void *));
+ *ptr64++ = val;
+ return ptr64;
+ }
+
+ /* used for 32-bit STI ROM */
+ *ptr32++ = val;
+ return ptr32;
+}
+
+#define store_sti_ptr(sti, dest, ptr) \
+ store_sti_val(sti, dest, STI_PTR(ptr))
/* The colour indices used by STI are
* 0 - Black
@@ -66,12 +85,12 @@ static const u8 col_trans[8] = {
#define c_index(sti, c) ((c) & 0xff)
static const struct sti_init_flags default_init_flags = {
- .wait = STI_WAIT,
+ .wait = STI_WAIT,
.reset = 1,
- .text = 1,
+ .text = 1,
.nontext = 1,
- .no_chg_bet = 1,
- .no_chg_bei = 1,
+ .no_chg_bet = 1,
+ .no_chg_bei = 1,
.init_cmap_tx = 1,
};
@@ -88,7 +107,7 @@ static int sti_init_graph(struct sti_struct *sti)
memset(inptr, 0, sizeof(*inptr));
inptr->text_planes = 3; /* # of text planes (max 3 for STI) */
memset(inptr_ext, 0, sizeof(*inptr_ext));
- inptr->ext_ptr = STI_PTR(inptr_ext);
+ store_sti_ptr(sti, &inptr->ext_ptr, inptr_ext);
outptr->errno = 0;
ret = sti_call(sti, sti->init_graph, &default_init_flags, inptr,
@@ -104,7 +123,7 @@ static int sti_init_graph(struct sti_struct *sti)
pr_err("STI init_graph failed (ret %d, errno %d)\n", ret, err);
return -1;
}
-
+
return 0;
}
@@ -119,8 +138,8 @@ static void sti_inq_conf(struct sti_struct *sti)
unsigned long flags;
s32 ret;
- outptr->ext_ptr = STI_PTR(&sti->sti_data->inq_outptr_ext);
-
+ store_sti_ptr(sti, &outptr->ext_ptr, &sti->sti_data->inq_outptr_ext);
+
do {
spin_lock_irqsave(&sti->lock, flags);
memset(inptr, 0, sizeof(*inptr));
@@ -139,9 +158,9 @@ void
sti_putc(struct sti_struct *sti, int c, int y, int x,
struct sti_cooked_font *font)
{
- struct sti_font_inptr *inptr = &sti->sti_data->font_inptr;
+ struct sti_font_inptr *inptr;
struct sti_font_inptr inptr_default = {
- .font_start_addr = STI_PTR(font->raw),
+ .font_start_addr = (void *)STI_PTR(font->raw),
.index = c_index(sti, c),
.fg_color = c_fg(sti, c),
.bg_color = c_bg(sti, c),
@@ -154,7 +173,14 @@ sti_putc(struct sti_struct *sti, int c, int y, int x,
do {
spin_lock_irqsave(&sti->lock, flags);
- *inptr = inptr_default;
+ inptr = &inptr_default;
+ if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) {
+ /* copy below 4G if calling 32-bit on LP64 kernel */
+ inptr = &sti->sti_data->font_inptr;
+ *inptr = inptr_default;
+ /* skip first 4 bytes for 32-bit STI call */
+ inptr = (void *)(((unsigned long)inptr) + sizeof(u32));
+ }
ret = sti_call(sti, sti->font_unpmv, &default_font_flags,
inptr, outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
@@ -162,16 +188,16 @@ sti_putc(struct sti_struct *sti, int c, int y, int x,
}
static const struct sti_blkmv_flags clear_blkmv_flags = {
- .wait = STI_WAIT,
- .color = 1,
- .clear = 1,
+ .wait = STI_WAIT,
+ .color = 1,
+ .clear = 1,
};
void
sti_set(struct sti_struct *sti, int src_y, int src_x,
int height, int width, u8 color)
{
- struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
+ struct sti_blkmv_inptr *inptr;
struct sti_blkmv_inptr inptr_default = {
.fg_color = color,
.bg_color = color,
@@ -185,10 +211,15 @@ sti_set(struct sti_struct *sti, int src_y, int src_x,
struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr;
s32 ret;
unsigned long flags;
-
+
do {
spin_lock_irqsave(&sti->lock, flags);
- *inptr = inptr_default;
+ inptr = &inptr_default;
+ if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) {
+ /* copy below 4G if calling 32-bit on LP64 kernel */
+ inptr = &sti->sti_data->blkmv_inptr;
+ *inptr = inptr_default;
+ }
ret = sti_call(sti, sti->block_move, &clear_blkmv_flags,
inptr, outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
@@ -199,7 +230,7 @@ void
sti_clear(struct sti_struct *sti, int src_y, int src_x,
int height, int width, int c, struct sti_cooked_font *font)
{
- struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
+ struct sti_blkmv_inptr *inptr;
struct sti_blkmv_inptr inptr_default = {
.fg_color = c_fg(sti, c),
.bg_color = c_bg(sti, c),
@@ -216,7 +247,12 @@ sti_clear(struct sti_struct *sti, int src_y, int src_x,
do {
spin_lock_irqsave(&sti->lock, flags);
- *inptr = inptr_default;
+ inptr = &inptr_default;
+ if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) {
+ /* copy below 4G if calling 32-bit on LP64 kernel */
+ inptr = &sti->sti_data->blkmv_inptr;
+ *inptr = inptr_default;
+ }
ret = sti_call(sti, sti->block_move, &clear_blkmv_flags,
inptr, outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
@@ -224,7 +260,7 @@ sti_clear(struct sti_struct *sti, int src_y, int src_x,
}
static const struct sti_blkmv_flags default_blkmv_flags = {
- .wait = STI_WAIT,
+ .wait = STI_WAIT,
};
void
@@ -232,7 +268,7 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x,
int dst_y, int dst_x, int height, int width,
struct sti_cooked_font *font)
{
- struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
+ struct sti_blkmv_inptr *inptr;
struct sti_blkmv_inptr inptr_default = {
.src_x = src_x * font->width,
.src_y = src_y * font->height,
@@ -247,7 +283,12 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x,
do {
spin_lock_irqsave(&sti->lock, flags);
- *inptr = inptr_default;
+ inptr = &inptr_default;
+ if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) {
+ /* copy below 4G if calling 32-bit on LP64 kernel */
+ inptr = &sti->sti_data->blkmv_inptr;
+ *inptr = inptr_default;
+ }
ret = sti_call(sti, sti->block_move, &default_blkmv_flags,
inptr, outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
@@ -291,14 +332,14 @@ static int __init sti_setup(char *str)
{
if (str)
strscpy(default_sti_path, str, sizeof(default_sti_path));
-
+
return 1;
}
/* Assuming the machine has multiple STI consoles (=graphic cards) which
* all get detected by sticon, the user may define with the linux kernel
* parameter sti=<x> which of them will be the initial boot-console.
- * <x> is a number between 0 and MAX_STI_ROMS, with 0 as the default
+ * <x> is a number between 0 and MAX_STI_ROMS, with 0 as the default
* STI screen.
*/
__setup("sti=", sti_setup);
@@ -341,13 +382,13 @@ static int sti_font_setup(char *str)
* should be used by the sticon driver to draw characters to the screen.
* Possible values are:
* - sti_font=<fb_fontname>:
- * <fb_fontname> is the name of one of the linux-kernel built-in
- * framebuffer font names (e.g. VGA8x16, SUN22x18).
- * This is only available if the fonts have been statically compiled
+ * <fb_fontname> is the name of one of the linux-kernel built-in
+ * framebuffer font names (e.g. VGA8x16, SUN22x18).
+ * This is only available if the fonts have been statically compiled
* in with e.g. the CONFIG_FONT_8x16 or CONFIG_FONT_SUN12x22 options.
* - sti_font=<number> (<number> = 1,2,3,...)
* most STI ROMs have built-in HP specific fonts, which can be selected
- * by giving the desired number to the sticon driver.
+ * by giving the desired number to the sticon driver.
* NOTE: This number is machine and STI ROM dependend.
* - sti_font=<height>x<width> (e.g. sti_font=16x8)
* <height> and <width> gives hints to the height and width of the
@@ -359,43 +400,32 @@ __setup("sti_font=", sti_font_setup);
#endif
-
-static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg,
- unsigned int sti_mem_request)
+
+static void sti_dump_globcfg(struct sti_struct *sti)
{
- struct sti_glob_cfg_ext *cfg;
-
+ struct sti_glob_cfg *glob_cfg = sti->glob_cfg;
+ struct sti_glob_cfg_ext *cfg = &sti->sti_data->glob_cfg_ext;
+
pr_debug("%d text planes\n"
"%4d x %4d screen resolution\n"
"%4d x %4d offscreen\n"
- "%4d x %4d layout\n"
- "regions at %08x %08x %08x %08x\n"
- "regions at %08x %08x %08x %08x\n"
- "reent_lvl %d\n"
- "save_addr %08x\n",
+ "%4d x %4d layout\n",
glob_cfg->text_planes,
glob_cfg->onscreen_x, glob_cfg->onscreen_y,
glob_cfg->offscreen_x, glob_cfg->offscreen_y,
- glob_cfg->total_x, glob_cfg->total_y,
- glob_cfg->region_ptrs[0], glob_cfg->region_ptrs[1],
- glob_cfg->region_ptrs[2], glob_cfg->region_ptrs[3],
- glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],
- glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],
- glob_cfg->reent_lvl,
- glob_cfg->save_addr);
-
- /* dump extended cfg */
- cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr);
+ glob_cfg->total_x, glob_cfg->total_y);
+
+ /* dump extended cfg */
pr_debug("monitor %d\n"
"in friendly mode: %d\n"
"power consumption %d watts\n"
"freq ref %d\n"
- "sti_mem_addr %08x (size=%d bytes)\n",
+ "sti_mem_addr %px (size=%d bytes)\n",
cfg->curr_mon,
cfg->friendly_boot,
cfg->power,
cfg->freq_ref,
- cfg->sti_mem_addr, sti_mem_request);
+ cfg->sti_mem_addr, sti->sti_mem_request);
}
static void sti_dump_outptr(struct sti_struct *sti)
@@ -415,7 +445,7 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
{
struct sti_glob_cfg *glob_cfg;
struct sti_glob_cfg_ext *glob_cfg_ext;
- void *save_addr;
+ void *save_addr, *ptr;
void *sti_mem_addr;
int i, size;
@@ -433,14 +463,12 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
save_addr = &sti->sti_data->save_addr;
sti_mem_addr = &sti->sti_data->sti_mem_addr;
- glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
- glob_cfg->save_addr = STI_PTR(save_addr);
- for (i=0; i<8; i++) {
+ for (i = 0; i < STI_REGION_MAX; i++) {
unsigned long newhpa, len;
-
+
if (sti->pd) {
unsigned char offs = sti->rm_entry[i];
-
+
if (offs == 0)
continue;
if (offs != PCI_ROM_ADDRESS &&
@@ -456,18 +484,15 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
sti->regions_phys[i] =
REGION_OFFSET_TO_PHYS(sti->regions[i], newhpa);
-
+
len = sti->regions[i].region_desc.length * 4096;
- if (len)
- glob_cfg->region_ptrs[i] = sti->regions_phys[i];
-
- pr_debug("region #%d: phys %08lx, region_ptr %08x, len=%lukB, "
+
+ pr_debug("region #%d: phys %08lx, len=%lukB, "
"btlb=%d, sysonly=%d, cache=%d, last=%d\n",
- i, sti->regions_phys[i], glob_cfg->region_ptrs[i],
- len/1024,
+ i, sti->regions_phys[i], len / 1024,
sti->regions[i].region_desc.btlb,
sti->regions[i].region_desc.sys_only,
- sti->regions[i].region_desc.cache,
+ sti->regions[i].region_desc.cache,
sti->regions[i].region_desc.last);
/* last entry reached ? */
@@ -475,14 +500,19 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
break;
}
- if (++i<8 && sti->regions[i].region)
- pr_warn("future ptr (0x%8x) not yet supported !\n",
- sti->regions[i].region);
+ ptr = &glob_cfg->region_ptrs;
+ for (i = 0; i < STI_REGION_MAX; i++)
+ ptr = store_sti_val(sti, ptr, sti->regions_phys[i]);
+
+ *(s32 *)ptr = 0; /* set reent_lvl */
+ ptr += sizeof(s32);
+ ptr = store_sti_ptr(sti, ptr, save_addr);
+ ptr = store_sti_ptr(sti, ptr, glob_cfg_ext);
- glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
+ store_sti_ptr(sti, &glob_cfg_ext->sti_mem_addr, sti_mem_addr);
sti->glob_cfg = glob_cfg;
-
+
return 0;
}
@@ -495,7 +525,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
void *dest;
struct sti_rom_font *nf;
struct sti_cooked_font *cooked_font;
-
+
if (fbfont_name && strlen(fbfont_name))
fbfont = find_font(fbfont_name);
if (!fbfont)
@@ -505,8 +535,8 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
pr_info(" using %ux%u framebuffer font %s\n",
fbfont->width, fbfont->height, fbfont->name);
-
- bpc = ((fbfont->width+7)/8) * fbfont->height;
+
+ bpc = ((fbfont->width+7)/8) * fbfont->height;
size = bpc * fbfont->charcount;
size += sizeof(struct sti_rom_font);
@@ -533,7 +563,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
kfree(nf);
return NULL;
}
-
+
cooked_font->raw = nf;
cooked_font->raw_ptr = nf;
cooked_font->next_font = NULL;
@@ -617,9 +647,9 @@ static void sti_dump_rom(struct sti_struct *sti)
int nr;
pr_info(" id %04x-%04x, conforms to spec rev. %d.%02x\n",
- rom->graphics_id[0],
+ rom->graphics_id[0],
rom->graphics_id[1],
- rom->revno[0] >> 4,
+ rom->revno[0] >> 4,
rom->revno[0] & 0x0f);
pr_debug(" supports %d monitors\n", rom->num_mons);
pr_debug(" font start %08x\n", rom->font_start);
@@ -647,7 +677,7 @@ static int sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
{
struct sti_rom_font *raw_font, *font_start;
struct sti_cooked_font *cooked_font;
-
+
cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
if (!cooked_font)
return 0;
@@ -745,7 +775,7 @@ static struct sti_rom *sti_get_bmode_rom (unsigned long address)
raw_font = ((void *)raw) + raw->font_start;
font_start = raw_font;
-
+
while (raw_font->next_font) {
BMODE_RELOCATE (raw_font->next_font);
raw_font = ((void *)font_start) + raw_font->next_font;
@@ -759,7 +789,7 @@ static struct sti_rom *sti_get_wmode_rom(unsigned long address)
struct sti_rom *raw;
unsigned long size;
- /* read the ROM size directly from the struct in ROM */
+ /* read the ROM size directly from the struct in ROM */
size = gsc_readl(address + offsetof(struct sti_rom,last_addr));
raw = kmalloc(size, STI_LOWMEM);
@@ -803,10 +833,19 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti,
raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64
? "and 64 " : "");
- sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff);
- sti->block_move = address + (raw->block_move & 0x03ffffff);
- sti->init_graph = address + (raw->init_graph & 0x03ffffff);
- sti->inq_conf = address + (raw->inq_conf & 0x03ffffff);
+ if (IS_ENABLED(CONFIG_64BIT) &&
+ raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64) {
+ sti->do_call64 = 1;
+ sti->font_unpmv = address + (raw->font_unp_addr & 0x03ffffff);
+ sti->block_move = address + (raw->block_move_addr & 0x03ffffff);
+ sti->init_graph = address + (raw->init_graph_addr & 0x03ffffff);
+ sti->inq_conf = address + (raw->inq_conf_addr & 0x03ffffff);
+ } else {
+ sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff);
+ sti->block_move = address + (raw->block_move & 0x03ffffff);
+ sti->init_graph = address + (raw->init_graph & 0x03ffffff);
+ sti->inq_conf = address + (raw->inq_conf & 0x03ffffff);
+ }
sti->rom = cooked;
sti->rom->raw = raw;
@@ -819,7 +858,13 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti,
sti_font_convert_bytemode(sti, sti->font);
sti_dump_font(sti->font);
+ pr_info(" using %d-bit STI ROM functions\n",
+ (IS_ENABLED(CONFIG_64BIT) && sti->do_call64) ? 64 : 32);
+
sti->sti_mem_request = raw->sti_mem_req;
+ pr_debug(" mem_request = %d, reentsize %d\n",
+ sti->sti_mem_request, raw->reentsize);
+
sti->graphics_id[0] = raw->graphics_id[0];
sti->graphics_id[1] = raw->graphics_id[1];
@@ -869,7 +914,7 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address,
pr_warn("maximum number of STI ROMS reached !\n");
return NULL;
}
-
+
sti = kzalloc(sizeof(*sti), GFP_KERNEL);
if (!sti)
return NULL;
@@ -877,10 +922,12 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address,
spin_lock_init(&sti->lock);
test_rom:
- /* if we can't read the ROM, bail out early. Not being able
- * to read the hpa is okay, for romless sti */
- if (pdc_add_valid(address))
+ /* pdc_add_valid() works only on 32-bit kernels */
+ if ((!IS_ENABLED(CONFIG_64BIT) ||
+ (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS32)) &&
+ pdc_add_valid(address)) {
goto out_err;
+ }
sig = gsc_readl(address);
@@ -890,19 +937,19 @@ test_rom:
u32 *rm;
i = gsc_readl(address+0x04);
if (i != 1) {
- /* The ROM could have multiple architecture
+ /* The ROM could have multiple architecture
* dependent images (e.g. i386, parisc,...) */
pr_warn("PCI ROM is not a STI ROM type image (0x%8x)\n", i);
goto out_err;
}
-
+
sti->pd = pd;
i = gsc_readl(address+0x0c);
pr_debug("PCI ROM size (from header) = %d kB\n",
le16_to_cpu(i>>16)*512/1024);
rm_offset = le16_to_cpu(i & 0xffff);
- if (rm_offset) {
+ if (rm_offset) {
/* read 16 bytes from the pci region mapper array */
rm = (u32*) &sti->rm_entry;
*rm++ = gsc_readl(address+rm_offset+0x00);
@@ -915,9 +962,9 @@ test_rom:
pr_debug("sig %04x, PCI STI ROM at %08lx\n", sig, address);
goto test_rom;
}
-
+
ok = 0;
-
+
if ((sig & 0xff) == 0x01) {
pr_debug(" byte mode ROM at %08lx, hpa at %08lx\n",
address, hpa);
@@ -941,7 +988,7 @@ test_rom:
*/
if (sti->pd) {
unsigned long rom_base;
- rom_base = pci_resource_start(sti->pd, PCI_ROM_RESOURCE);
+ rom_base = pci_resource_start(sti->pd, PCI_ROM_RESOURCE);
pci_write_config_dword(sti->pd, PCI_ROM_ADDRESS, rom_base & ~PCI_ROM_ADDRESS_ENABLE);
pr_debug("STI PCI ROM disabled\n");
}
@@ -950,15 +997,15 @@ test_rom:
goto out_err;
sti_inq_conf(sti);
- sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request);
+ sti_dump_globcfg(sti);
sti_dump_outptr(sti);
-
+
pr_info(" graphics card name: %s\n",
sti->sti_data->inq_outptr.dev_name);
sti_roms[num_sti_roms] = sti;
num_sti_roms++;
-
+
return sti;
out_err:
@@ -974,9 +1021,9 @@ static void sticore_check_for_default_sti(struct sti_struct *sti, char *path)
}
/*
- * on newer systems PDC gives the address of the ROM
+ * on newer systems PDC gives the address of the ROM
* in the additional address field addr[1] while on
- * older Systems the PDC stores it in page0->proc_sti
+ * older Systems the PDC stores it in page0->proc_sti
*/
static int __init sticore_pa_init(struct parisc_device *dev)
{
@@ -1005,7 +1052,7 @@ static int sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent)
unsigned int fb_len, rom_len;
int err;
struct sti_struct *sti;
-
+
err = pci_enable_device(pd);
if (err < 0) {
dev_err(&pd->dev, "Cannot enable PCI device\n");
@@ -1032,7 +1079,7 @@ static int sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent)
print_pci_hwpath(pd, sti->pa_path);
sticore_check_for_default_sti(sti, sti->pa_path);
}
-
+
if (!sti) {
pr_warn("Unable to handle STI device '%s'\n", pci_name(pd));
return -ENODEV;
@@ -1136,36 +1183,19 @@ int sti_call(const struct sti_struct *sti, unsigned long func,
unsigned long _glob_cfg = STI_PTR(glob_cfg);
int ret;
-#ifdef CONFIG_64BIT
/* Check for overflow when using 32bit STI on 64bit kernel. */
- if (WARN_ONCE(_flags>>32 || _inptr>>32 || _outptr>>32 || _glob_cfg>>32,
+ if (WARN_ONCE(IS_ENABLED(CONFIG_64BIT) && !sti->do_call64 &&
+ (upper_32_bits(_flags) || upper_32_bits(_inptr) ||
+ upper_32_bits(_outptr) || upper_32_bits(_glob_cfg)),
"Out of 32bit-range pointers!"))
return -1;
-#endif
- ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg);
+ ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg,
+ sti->do_call64);
return ret;
}
-#if defined(CONFIG_FB_STI)
-/* check if given fb_info is the primary device */
-int fb_is_primary_device(struct fb_info *info)
-{
- struct sti_struct *sti;
-
- sti = sti_get_rom(0);
-
- /* if no built-in graphics card found, allow any fb driver as default */
- if (!sti)
- return true;
-
- /* return true if it's the default built-in framebuffer driver */
- return (sti->info == info);
-}
-EXPORT_SYMBOL(fb_is_primary_device);
-#endif
-
MODULE_AUTHOR("Philipp Rumpf, Helge Deller, Thomas Bogendoerfer");
MODULE_DESCRIPTION("Core STI driver for HP's NGLE series graphics cards in HP PARISC machines");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
index 23112d84218f..4b773bd7c58c 100644
--- a/drivers/virtio/virtio_pci_common.h
+++ b/drivers/virtio/virtio_pci_common.h
@@ -45,9 +45,10 @@ struct virtio_pci_vq_info {
struct virtio_pci_device {
struct virtio_device vdev;
struct pci_dev *pci_dev;
- struct virtio_pci_legacy_device ldev;
- struct virtio_pci_modern_device mdev;
-
+ union {
+ struct virtio_pci_legacy_device ldev;
+ struct virtio_pci_modern_device mdev;
+ };
bool is_legacy;
/* Where to read and clear interrupt */
diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c
index 869cb46bef96..aad7d9296e77 100644
--- a/drivers/virtio/virtio_pci_modern_dev.c
+++ b/drivers/virtio/virtio_pci_modern_dev.c
@@ -218,21 +218,29 @@ int vp_modern_probe(struct virtio_pci_modern_device *mdev)
int err, common, isr, notify, device;
u32 notify_length;
u32 notify_offset;
+ int devid;
check_offsets();
- /* We only own devices >= 0x1000 and <= 0x107f: leave the rest. */
- if (pci_dev->device < 0x1000 || pci_dev->device > 0x107f)
- return -ENODEV;
-
- if (pci_dev->device < 0x1040) {
- /* Transitional devices: use the PCI subsystem device id as
- * virtio device id, same as legacy driver always did.
- */
- mdev->id.device = pci_dev->subsystem_device;
+ if (mdev->device_id_check) {
+ devid = mdev->device_id_check(pci_dev);
+ if (devid < 0)
+ return devid;
+ mdev->id.device = devid;
} else {
- /* Modern devices: simply use PCI device id, but start from 0x1040. */
- mdev->id.device = pci_dev->device - 0x1040;
+ /* We only own devices >= 0x1000 and <= 0x107f: leave the rest. */
+ if (pci_dev->device < 0x1000 || pci_dev->device > 0x107f)
+ return -ENODEV;
+
+ if (pci_dev->device < 0x1040) {
+ /* Transitional devices: use the PCI subsystem device id as
+ * virtio device id, same as legacy driver always did.
+ */
+ mdev->id.device = pci_dev->subsystem_device;
+ } else {
+ /* Modern devices: simply use PCI device id, but start from 0x1040. */
+ mdev->id.device = pci_dev->device - 0x1040;
+ }
}
mdev->id.vendor = pci_dev->subsystem_vendor;
@@ -260,7 +268,8 @@ int vp_modern_probe(struct virtio_pci_modern_device *mdev)
return -EINVAL;
}
- err = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(64));
+ err = dma_set_mask_and_coherent(&pci_dev->dev,
+ mdev->dma_mask ? : DMA_BIT_MASK(64));
if (err)
err = dma_set_mask_and_coherent(&pci_dev->dev,
DMA_BIT_MASK(32));
diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
index eb6aee8c06b2..989e2d7184ce 100644
--- a/drivers/virtio/virtio_vdpa.c
+++ b/drivers/virtio/virtio_vdpa.c
@@ -385,7 +385,9 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
err = PTR_ERR(vqs[i]);
goto err_setup_vq;
}
- ops->set_vq_affinity(vdpa, i, &masks[i]);
+
+ if (ops->set_vq_affinity)
+ ops->set_vq_affinity(vdpa, i, &masks[i]);
}
cb.callback = virtio_vdpa_config_cb;
diff --git a/drivers/w1/masters/sgi_w1.c b/drivers/w1/masters/sgi_w1.c
index e8c7fa68d3cc..d7fbc3c146e1 100644
--- a/drivers/w1/masters/sgi_w1.c
+++ b/drivers/w1/masters/sgi_w1.c
@@ -93,7 +93,7 @@ static int sgi_w1_probe(struct platform_device *pdev)
pdata = dev_get_platdata(&pdev->dev);
if (pdata) {
- strlcpy(sdev->dev_id, pdata->dev_id, sizeof(sdev->dev_id));
+ strscpy(sdev->dev_id, pdata->dev_id, sizeof(sdev->dev_id));
sdev->bus_master.dev_id = sdev->dev_id;
}
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 687753889c34..32b8a757744e 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -71,8 +71,8 @@ config W1_SLAVE_DS2805
help
Say Y here if you want to use a 1-wire
is a 112-byte user-programmable EEPROM is
- organized as 7 pages of 16 bytes each with 64bit
- unique number. Requires OverDrive Speed to talk to.
+ organized as 7 pages of 16 bytes each with 64bit
+ unique number. Requires OverDrive Speed to talk to.
config W1_SLAVE_DS2430
tristate "256b EEPROM family support (DS2430)"
diff --git a/drivers/w1/slaves/w1_ds2438.c b/drivers/w1/slaves/w1_ds2438.c
index ca64f99c8f3d..e008c27b3db9 100644
--- a/drivers/w1/slaves/w1_ds2438.c
+++ b/drivers/w1/slaves/w1_ds2438.c
@@ -66,8 +66,6 @@ static int w1_ds2438_get_page(struct w1_slave *sl, int pageno, u8 *buf)
size_t count;
while (retries--) {
- crc = 0;
-
if (w1_reset_select_slave(sl))
continue;
w1_buf[0] = W1_DS2438_RECALL_MEMORY;
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 067692626cf0..c85e80c7e130 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -284,7 +284,7 @@ static int read_powermode(struct w1_slave *sl);
* trigger_bulk_read() - function to trigger a bulk read on the bus
* @dev_master: the device master of the bus
*
- * Send a SKIP ROM follow by a CONVERT T commmand on the bus.
+ * Send a SKIP ROM follow by a CONVERT T command on the bus.
* It also set the status flag in each slave &struct w1_therm_family_data
* to signal that a conversion is in progress.
*
@@ -454,7 +454,7 @@ static const struct hwmon_channel_info w1_temp = {
.config = w1_temp_config,
};
-static const struct hwmon_channel_info *w1_info[] = {
+static const struct hwmon_channel_info * const w1_info[] = {
&w1_temp,
NULL
};
@@ -1159,29 +1159,26 @@ static int convert_t(struct w1_slave *sl, struct therm_info *info)
w1_write_8(dev_master, W1_CONVERT_TEMP);
- if (strong_pullup) { /*some device need pullup */
+ if (SLAVE_FEATURES(sl) & W1_THERM_POLL_COMPLETION) {
+ ret = w1_poll_completion(dev_master, W1_POLL_CONVERT_TEMP);
+ if (ret) {
+ dev_dbg(&sl->dev, "%s: Timeout\n", __func__);
+ goto mt_unlock;
+ }
+ mutex_unlock(&dev_master->bus_mutex);
+ } else if (!strong_pullup) { /*no device need pullup */
sleep_rem = msleep_interruptible(t_conv);
if (sleep_rem != 0) {
ret = -EINTR;
goto mt_unlock;
}
mutex_unlock(&dev_master->bus_mutex);
- } else { /*no device need pullup */
- if (SLAVE_FEATURES(sl) & W1_THERM_POLL_COMPLETION) {
- ret = w1_poll_completion(dev_master, W1_POLL_CONVERT_TEMP);
- if (ret) {
- dev_dbg(&sl->dev, "%s: Timeout\n", __func__);
- goto mt_unlock;
- }
- mutex_unlock(&dev_master->bus_mutex);
- } else {
- /* Fixed delay */
- mutex_unlock(&dev_master->bus_mutex);
- sleep_rem = msleep_interruptible(t_conv);
- if (sleep_rem != 0) {
- ret = -EINTR;
- goto dec_refcnt;
- }
+ } else { /*some device need pullup */
+ mutex_unlock(&dev_master->bus_mutex);
+ sleep_rem = msleep_interruptible(t_conv);
+ if (sleep_rem != 0) {
+ ret = -EINTR;
+ goto dec_refcnt;
}
}
ret = read_scratchpad(sl, info);
@@ -1515,7 +1512,7 @@ static int trigger_bulk_read(struct w1_master *dev_master)
if (bulk_read_support(sl)) {
int t_cur = conversion_time(sl);
- t_conv = t_cur > t_conv ? t_cur : t_conv;
+ t_conv = max(t_cur, t_conv);
strong_pullup = strong_pullup ||
(w1_strong_pullup == 2 ||
(!SLAVE_POWERMODE(sl) &&
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 9d199fed9628..5353cbd75126 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -32,7 +32,7 @@ static int w1_timeout = 10;
module_param_named(timeout, w1_timeout, int, 0);
MODULE_PARM_DESC(timeout, "time in seconds between automatic slave searches");
-static int w1_timeout_us = 0;
+static int w1_timeout_us;
module_param_named(timeout_us, w1_timeout_us, int, 0);
MODULE_PARM_DESC(timeout_us,
"time in microseconds between automatic slave searches");
@@ -58,11 +58,6 @@ MODULE_PARM_DESC(slave_ttl,
DEFINE_MUTEX(w1_mlock);
LIST_HEAD(w1_masters);
-static int w1_master_match(struct device *dev, struct device_driver *drv)
-{
- return 1;
-}
-
static int w1_master_probe(struct device *dev)
{
return -ENODEV;
@@ -174,7 +169,6 @@ static int w1_uevent(const struct device *dev, struct kobj_uevent_env *env);
static struct bus_type w1_bus_type = {
.name = "w1",
- .match = w1_master_match,
.uevent = w1_uevent,
};
@@ -301,17 +295,13 @@ static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct devic
static ssize_t w1_master_attribute_show_timeout(struct device *dev, struct device_attribute *attr, char *buf)
{
- ssize_t count;
- count = sprintf(buf, "%d\n", w1_timeout);
- return count;
+ return sprintf(buf, "%d\n", w1_timeout);
}
static ssize_t w1_master_attribute_show_timeout_us(struct device *dev,
struct device_attribute *attr, char *buf)
{
- ssize_t count;
- count = sprintf(buf, "%d\n", w1_timeout_us);
- return count;
+ return sprintf(buf, "%d\n", w1_timeout_us);
}
static ssize_t w1_master_attribute_store_max_slave_count(struct device *dev,
@@ -501,7 +491,7 @@ static ssize_t w1_master_attribute_store_remove(struct device *dev,
struct w1_master *md = dev_to_w1_master(dev);
struct w1_reg_num rn;
struct w1_slave *sl;
- ssize_t result = count;
+ ssize_t result;
if (w1_atoreg_num(dev, buf, count, &rn))
return -EINVAL;
@@ -702,6 +692,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
dev_err(&sl->dev,
"Device registration [%s] failed. err=%d\n",
dev_name(&sl->dev), err);
+ of_node_put(sl->dev.of_node);
put_device(&sl->dev);
return err;
}
@@ -830,49 +821,47 @@ int w1_slave_detach(struct w1_slave *sl)
struct w1_master *w1_search_master_id(u32 id)
{
- struct w1_master *dev;
- int found = 0;
+ struct w1_master *dev = NULL, *iter;
mutex_lock(&w1_mlock);
- list_for_each_entry(dev, &w1_masters, w1_master_entry) {
- if (dev->id == id) {
- found = 1;
- atomic_inc(&dev->refcnt);
+ list_for_each_entry(iter, &w1_masters, w1_master_entry) {
+ if (iter->id == id) {
+ dev = iter;
+ atomic_inc(&iter->refcnt);
break;
}
}
mutex_unlock(&w1_mlock);
- return (found)?dev:NULL;
+ return dev;
}
struct w1_slave *w1_search_slave(struct w1_reg_num *id)
{
struct w1_master *dev;
- struct w1_slave *sl = NULL;
- int found = 0;
+ struct w1_slave *sl = NULL, *iter;
mutex_lock(&w1_mlock);
list_for_each_entry(dev, &w1_masters, w1_master_entry) {
mutex_lock(&dev->list_mutex);
- list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
- if (sl->reg_num.family == id->family &&
- sl->reg_num.id == id->id &&
- sl->reg_num.crc == id->crc) {
- found = 1;
+ list_for_each_entry(iter, &dev->slist, w1_slave_entry) {
+ if (iter->reg_num.family == id->family &&
+ iter->reg_num.id == id->id &&
+ iter->reg_num.crc == id->crc) {
+ sl = iter;
atomic_inc(&dev->refcnt);
- atomic_inc(&sl->refcnt);
+ atomic_inc(&iter->refcnt);
break;
}
}
mutex_unlock(&dev->list_mutex);
- if (found)
+ if (sl)
break;
}
mutex_unlock(&w1_mlock);
- return (found)?sl:NULL;
+ return sl;
}
void w1_reconnect_slaves(struct w1_family *f, int attach)
@@ -1263,10 +1252,10 @@ err_out_exit_init:
static void __exit w1_fini(void)
{
- struct w1_master *dev;
+ struct w1_master *dev, *n;
/* Set netlink removal messages and some cleanup */
- list_for_each_entry(dev, &w1_masters, w1_master_entry)
+ list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry)
__w1_remove_master_device(dev);
w1_fini_netlink();